tas2552.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. /*
  2. * tas2552.c - ALSA SoC Texas Instruments TAS2552 Mono Audio Amplifier
  3. *
  4. * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
  5. *
  6. * Author: Dan Murphy <dmurphy@ti.com>
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * version 2 as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. */
  17. #include <linux/module.h>
  18. #include <linux/errno.h>
  19. #include <linux/device.h>
  20. #include <linux/i2c.h>
  21. #include <linux/gpio.h>
  22. #include <linux/of_gpio.h>
  23. #include <linux/pm_runtime.h>
  24. #include <linux/regmap.h>
  25. #include <linux/slab.h>
  26. #include <linux/gpio/consumer.h>
  27. #include <linux/regulator/consumer.h>
  28. #include <sound/pcm.h>
  29. #include <sound/pcm_params.h>
  30. #include <sound/soc.h>
  31. #include <sound/soc-dapm.h>
  32. #include <sound/tlv.h>
  33. #include <sound/tas2552-plat.h>
  34. #include "tas2552.h"
  35. static struct reg_default tas2552_reg_defs[] = {
  36. {TAS2552_CFG_1, 0x22},
  37. {TAS2552_CFG_3, 0x80},
  38. {TAS2552_DOUT, 0x00},
  39. {TAS2552_OUTPUT_DATA, 0xc0},
  40. {TAS2552_PDM_CFG, 0x01},
  41. {TAS2552_PGA_GAIN, 0x00},
  42. {TAS2552_BOOST_PT_CTRL, 0x0f},
  43. {TAS2552_RESERVED_0D, 0x00},
  44. {TAS2552_LIMIT_RATE_HYS, 0x08},
  45. {TAS2552_CFG_2, 0xef},
  46. {TAS2552_SER_CTRL_1, 0x00},
  47. {TAS2552_SER_CTRL_2, 0x00},
  48. {TAS2552_PLL_CTRL_1, 0x10},
  49. {TAS2552_PLL_CTRL_2, 0x00},
  50. {TAS2552_PLL_CTRL_3, 0x00},
  51. {TAS2552_BTIP, 0x8f},
  52. {TAS2552_BTS_CTRL, 0x80},
  53. {TAS2552_LIMIT_RELEASE, 0x04},
  54. {TAS2552_LIMIT_INT_COUNT, 0x00},
  55. {TAS2552_EDGE_RATE_CTRL, 0x40},
  56. {TAS2552_VBAT_DATA, 0x00},
  57. };
  58. #define TAS2552_NUM_SUPPLIES 3
  59. static const char *tas2552_supply_names[TAS2552_NUM_SUPPLIES] = {
  60. "vbat", /* vbat voltage */
  61. "iovdd", /* I/O Voltage */
  62. "avdd", /* Analog DAC Voltage */
  63. };
  64. struct tas2552_data {
  65. struct snd_soc_codec *codec;
  66. struct regmap *regmap;
  67. struct i2c_client *tas2552_client;
  68. struct regulator_bulk_data supplies[TAS2552_NUM_SUPPLIES];
  69. struct gpio_desc *enable_gpio;
  70. unsigned char regs[TAS2552_VBAT_DATA];
  71. unsigned int mclk;
  72. };
  73. /* Input mux controls */
  74. static const char *tas2552_input_texts[] = {
  75. "Digital", "Analog"
  76. };
  77. static SOC_ENUM_SINGLE_DECL(tas2552_input_mux_enum, TAS2552_CFG_3, 7,
  78. tas2552_input_texts);
  79. static const struct snd_kcontrol_new tas2552_input_mux_control[] = {
  80. SOC_DAPM_ENUM("Input selection", tas2552_input_mux_enum)
  81. };
  82. static const struct snd_soc_dapm_widget tas2552_dapm_widgets[] =
  83. {
  84. SND_SOC_DAPM_INPUT("IN"),
  85. /* MUX Controls */
  86. SND_SOC_DAPM_MUX("Input selection", SND_SOC_NOPM, 0, 0,
  87. tas2552_input_mux_control),
  88. SND_SOC_DAPM_AIF_IN("DAC IN", "DAC Playback", 0, SND_SOC_NOPM, 0, 0),
  89. SND_SOC_DAPM_DAC("DAC", NULL, SND_SOC_NOPM, 0, 0),
  90. SND_SOC_DAPM_OUT_DRV("ClassD", TAS2552_CFG_2, 7, 0, NULL, 0),
  91. SND_SOC_DAPM_SUPPLY("PLL", TAS2552_CFG_2, 3, 0, NULL, 0),
  92. SND_SOC_DAPM_OUTPUT("OUT")
  93. };
  94. static const struct snd_soc_dapm_route tas2552_audio_map[] = {
  95. {"DAC", NULL, "DAC IN"},
  96. {"Input selection", "Digital", "DAC"},
  97. {"Input selection", "Analog", "IN"},
  98. {"ClassD", NULL, "Input selection"},
  99. {"OUT", NULL, "ClassD"},
  100. {"ClassD", NULL, "PLL"},
  101. };
  102. #ifdef CONFIG_PM_RUNTIME
  103. static void tas2552_sw_shutdown(struct tas2552_data *tas_data, int sw_shutdown)
  104. {
  105. u8 cfg1_reg;
  106. if (!tas_data->codec)
  107. return;
  108. if (sw_shutdown)
  109. cfg1_reg = 0;
  110. else
  111. cfg1_reg = TAS2552_SWS_MASK;
  112. snd_soc_update_bits(tas_data->codec, TAS2552_CFG_1,
  113. TAS2552_SWS_MASK, cfg1_reg);
  114. }
  115. #endif
  116. static int tas2552_hw_params(struct snd_pcm_substream *substream,
  117. struct snd_pcm_hw_params *params,
  118. struct snd_soc_dai *dai)
  119. {
  120. struct snd_soc_codec *codec = dai->codec;
  121. struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev);
  122. int sample_rate, pll_clk;
  123. int d;
  124. u8 p, j;
  125. if (!tas2552->mclk)
  126. return -EINVAL;
  127. snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0);
  128. if (tas2552->mclk == TAS2552_245MHZ_CLK ||
  129. tas2552->mclk == TAS2552_225MHZ_CLK) {
  130. /* By pass the PLL configuration */
  131. snd_soc_update_bits(codec, TAS2552_PLL_CTRL_2,
  132. TAS2552_PLL_BYPASS_MASK,
  133. TAS2552_PLL_BYPASS);
  134. } else {
  135. /* Fill in the PLL control registers for J & D
  136. * PLL_CLK = (.5 * freq * J.D) / 2^p
  137. * Need to fill in J and D here based on incoming freq
  138. */
  139. p = snd_soc_read(codec, TAS2552_PLL_CTRL_1);
  140. p = (p >> 7);
  141. sample_rate = params_rate(params);
  142. if (sample_rate == 48000)
  143. pll_clk = TAS2552_245MHZ_CLK;
  144. else if (sample_rate == 44100)
  145. pll_clk = TAS2552_225MHZ_CLK;
  146. else {
  147. dev_vdbg(codec->dev, "Substream sample rate is not found %i\n",
  148. params_rate(params));
  149. return -EINVAL;
  150. }
  151. j = (pll_clk * 2 * (1 << p)) / tas2552->mclk;
  152. d = (pll_clk * 2 * (1 << p)) % tas2552->mclk;
  153. snd_soc_update_bits(codec, TAS2552_PLL_CTRL_1,
  154. TAS2552_PLL_J_MASK, j);
  155. snd_soc_write(codec, TAS2552_PLL_CTRL_2,
  156. (d >> 7) & TAS2552_PLL_D_UPPER_MASK);
  157. snd_soc_write(codec, TAS2552_PLL_CTRL_3,
  158. d & TAS2552_PLL_D_LOWER_MASK);
  159. }
  160. return 0;
  161. }
  162. static int tas2552_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  163. {
  164. struct snd_soc_codec *codec = dai->codec;
  165. u8 serial_format;
  166. u8 serial_control_mask;
  167. switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  168. case SND_SOC_DAIFMT_CBS_CFS:
  169. serial_format = 0x00;
  170. break;
  171. case SND_SOC_DAIFMT_CBS_CFM:
  172. serial_format = TAS2552_WORD_CLK_MASK;
  173. break;
  174. case SND_SOC_DAIFMT_CBM_CFS:
  175. serial_format = TAS2552_BIT_CLK_MASK;
  176. break;
  177. case SND_SOC_DAIFMT_CBM_CFM:
  178. serial_format = (TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK);
  179. break;
  180. default:
  181. dev_vdbg(codec->dev, "DAI Format master is not found\n");
  182. return -EINVAL;
  183. }
  184. serial_control_mask = TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK;
  185. switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  186. case SND_SOC_DAIFMT_I2S:
  187. serial_format &= TAS2552_DAIFMT_I2S_MASK;
  188. break;
  189. case SND_SOC_DAIFMT_DSP_A:
  190. serial_format |= TAS2552_DAIFMT_DSP;
  191. break;
  192. case SND_SOC_DAIFMT_RIGHT_J:
  193. serial_format |= TAS2552_DAIFMT_RIGHT_J;
  194. break;
  195. case SND_SOC_DAIFMT_LEFT_J:
  196. serial_format |= TAS2552_DAIFMT_LEFT_J;
  197. break;
  198. default:
  199. dev_vdbg(codec->dev, "DAI Format is not found\n");
  200. return -EINVAL;
  201. }
  202. if (fmt & SND_SOC_DAIFMT_FORMAT_MASK)
  203. serial_control_mask |= TAS2552_DATA_FORMAT_MASK;
  204. snd_soc_update_bits(codec, TAS2552_SER_CTRL_1, serial_control_mask,
  205. serial_format);
  206. return 0;
  207. }
  208. static int tas2552_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
  209. unsigned int freq, int dir)
  210. {
  211. struct snd_soc_codec *codec = dai->codec;
  212. struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev);
  213. tas2552->mclk = freq;
  214. return 0;
  215. }
  216. static int tas2552_mute(struct snd_soc_dai *dai, int mute)
  217. {
  218. u8 cfg1_reg;
  219. struct snd_soc_codec *codec = dai->codec;
  220. if (mute)
  221. cfg1_reg = TAS2552_MUTE_MASK;
  222. else
  223. cfg1_reg = ~TAS2552_MUTE_MASK;
  224. snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK, cfg1_reg);
  225. return 0;
  226. }
  227. #ifdef CONFIG_PM_RUNTIME
  228. static int tas2552_runtime_suspend(struct device *dev)
  229. {
  230. struct tas2552_data *tas2552 = dev_get_drvdata(dev);
  231. tas2552_sw_shutdown(tas2552, 0);
  232. regcache_cache_only(tas2552->regmap, true);
  233. regcache_mark_dirty(tas2552->regmap);
  234. if (tas2552->enable_gpio)
  235. gpiod_set_value(tas2552->enable_gpio, 0);
  236. return 0;
  237. }
  238. static int tas2552_runtime_resume(struct device *dev)
  239. {
  240. struct tas2552_data *tas2552 = dev_get_drvdata(dev);
  241. if (tas2552->enable_gpio)
  242. gpiod_set_value(tas2552->enable_gpio, 1);
  243. tas2552_sw_shutdown(tas2552, 1);
  244. regcache_cache_only(tas2552->regmap, false);
  245. regcache_sync(tas2552->regmap);
  246. return 0;
  247. }
  248. #endif
  249. static const struct dev_pm_ops tas2552_pm = {
  250. SET_RUNTIME_PM_OPS(tas2552_runtime_suspend, tas2552_runtime_resume,
  251. NULL)
  252. };
  253. static struct snd_soc_dai_ops tas2552_speaker_dai_ops = {
  254. .hw_params = tas2552_hw_params,
  255. .set_sysclk = tas2552_set_dai_sysclk,
  256. .set_fmt = tas2552_set_dai_fmt,
  257. .digital_mute = tas2552_mute,
  258. };
  259. /* Formats supported by TAS2552 driver. */
  260. #define TAS2552_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
  261. SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
  262. /* TAS2552 dai structure. */
  263. static struct snd_soc_dai_driver tas2552_dai[] = {
  264. {
  265. .name = "tas2552-amplifier",
  266. .playback = {
  267. .stream_name = "Playback",
  268. .channels_min = 2,
  269. .channels_max = 2,
  270. .rates = SNDRV_PCM_RATE_8000_192000,
  271. .formats = TAS2552_FORMATS,
  272. },
  273. .ops = &tas2552_speaker_dai_ops,
  274. },
  275. };
  276. /*
  277. * DAC digital volumes. From -7 to 24 dB in 1 dB steps
  278. */
  279. static DECLARE_TLV_DB_SCALE(dac_tlv, -7, 100, 24);
  280. static const struct snd_kcontrol_new tas2552_snd_controls[] = {
  281. SOC_SINGLE_TLV("Speaker Driver Playback Volume",
  282. TAS2552_PGA_GAIN, 0, 0x1f, 1, dac_tlv),
  283. };
  284. static const struct reg_default tas2552_init_regs[] = {
  285. { TAS2552_RESERVED_0D, 0xc0 },
  286. };
  287. static int tas2552_codec_probe(struct snd_soc_codec *codec)
  288. {
  289. struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
  290. struct snd_soc_dapm_context *dapm = &codec->dapm;
  291. int ret;
  292. tas2552->codec = codec;
  293. ret = regulator_bulk_enable(ARRAY_SIZE(tas2552->supplies),
  294. tas2552->supplies);
  295. if (ret != 0) {
  296. dev_err(codec->dev, "Failed to enable supplies: %d\n",
  297. ret);
  298. return ret;
  299. }
  300. if (tas2552->enable_gpio)
  301. gpiod_set_value(tas2552->enable_gpio, 1);
  302. ret = pm_runtime_get_sync(codec->dev);
  303. if (ret < 0) {
  304. dev_err(codec->dev, "Enabling device failed: %d\n",
  305. ret);
  306. goto probe_fail;
  307. }
  308. snd_soc_write(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK |
  309. TAS2552_PLL_SRC_BCLK);
  310. snd_soc_write(codec, TAS2552_CFG_3, TAS2552_I2S_OUT_SEL |
  311. TAS2552_DIN_SRC_SEL_AVG_L_R | TAS2552_88_96KHZ);
  312. snd_soc_write(codec, TAS2552_DOUT, TAS2552_PDM_DATA_I);
  313. snd_soc_write(codec, TAS2552_OUTPUT_DATA, TAS2552_PDM_DATA_V_I | 0x8);
  314. snd_soc_write(codec, TAS2552_PDM_CFG, TAS2552_PDM_BCLK_SEL);
  315. snd_soc_write(codec, TAS2552_BOOST_PT_CTRL, TAS2552_APT_DELAY_200 |
  316. TAS2552_APT_THRESH_2_1_7);
  317. ret = regmap_register_patch(tas2552->regmap, tas2552_init_regs,
  318. ARRAY_SIZE(tas2552_init_regs));
  319. if (ret != 0) {
  320. dev_err(codec->dev, "Failed to write init registers: %d\n",
  321. ret);
  322. goto patch_fail;
  323. }
  324. snd_soc_write(codec, TAS2552_CFG_2, TAS2552_BOOST_EN |
  325. TAS2552_APT_EN | TAS2552_LIM_EN);
  326. snd_soc_dapm_new_controls(dapm, tas2552_dapm_widgets,
  327. ARRAY_SIZE(tas2552_dapm_widgets));
  328. snd_soc_dapm_add_routes(dapm, tas2552_audio_map,
  329. ARRAY_SIZE(tas2552_audio_map));
  330. return 0;
  331. patch_fail:
  332. pm_runtime_put(codec->dev);
  333. probe_fail:
  334. if (tas2552->enable_gpio)
  335. gpiod_set_value(tas2552->enable_gpio, 0);
  336. regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies),
  337. tas2552->supplies);
  338. return -EIO;
  339. }
  340. static int tas2552_codec_remove(struct snd_soc_codec *codec)
  341. {
  342. struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
  343. pm_runtime_put(codec->dev);
  344. if (tas2552->enable_gpio)
  345. gpiod_set_value(tas2552->enable_gpio, 0);
  346. return 0;
  347. };
  348. #ifdef CONFIG_PM
  349. static int tas2552_suspend(struct snd_soc_codec *codec)
  350. {
  351. struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
  352. int ret;
  353. ret = regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies),
  354. tas2552->supplies);
  355. if (ret != 0)
  356. dev_err(codec->dev, "Failed to disable supplies: %d\n",
  357. ret);
  358. return 0;
  359. }
  360. static int tas2552_resume(struct snd_soc_codec *codec)
  361. {
  362. struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
  363. int ret;
  364. ret = regulator_bulk_enable(ARRAY_SIZE(tas2552->supplies),
  365. tas2552->supplies);
  366. if (ret != 0) {
  367. dev_err(codec->dev, "Failed to enable supplies: %d\n",
  368. ret);
  369. }
  370. return 0;
  371. }
  372. #else
  373. #define tas2552_suspend NULL
  374. #define tas2552_resume NULL
  375. #endif
  376. static struct snd_soc_codec_driver soc_codec_dev_tas2552 = {
  377. .probe = tas2552_codec_probe,
  378. .remove = tas2552_codec_remove,
  379. .suspend = tas2552_suspend,
  380. .resume = tas2552_resume,
  381. .controls = tas2552_snd_controls,
  382. .num_controls = ARRAY_SIZE(tas2552_snd_controls),
  383. };
  384. static const struct regmap_config tas2552_regmap_config = {
  385. .reg_bits = 8,
  386. .val_bits = 8,
  387. .max_register = TAS2552_MAX_REG,
  388. .reg_defaults = tas2552_reg_defs,
  389. .num_reg_defaults = ARRAY_SIZE(tas2552_reg_defs),
  390. .cache_type = REGCACHE_RBTREE,
  391. };
  392. static int tas2552_probe(struct i2c_client *client,
  393. const struct i2c_device_id *id)
  394. {
  395. struct device *dev;
  396. struct tas2552_data *data;
  397. int ret;
  398. int i;
  399. dev = &client->dev;
  400. data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
  401. if (data == NULL)
  402. return -ENOMEM;
  403. data->enable_gpio = devm_gpiod_get(dev, "enable");
  404. if (IS_ERR(data->enable_gpio)) {
  405. ret = PTR_ERR(data->enable_gpio);
  406. if (ret != -ENOENT && ret != -ENOSYS)
  407. return ret;
  408. data->enable_gpio = NULL;
  409. } else {
  410. gpiod_direction_output(data->enable_gpio, 0);
  411. }
  412. data->tas2552_client = client;
  413. data->regmap = devm_regmap_init_i2c(client, &tas2552_regmap_config);
  414. if (IS_ERR(data->regmap)) {
  415. ret = PTR_ERR(data->regmap);
  416. dev_err(&client->dev, "Failed to allocate register map: %d\n",
  417. ret);
  418. return ret;
  419. }
  420. for (i = 0; i < ARRAY_SIZE(data->supplies); i++)
  421. data->supplies[i].supply = tas2552_supply_names[i];
  422. ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies),
  423. data->supplies);
  424. if (ret != 0) {
  425. dev_err(dev, "Failed to request supplies: %d\n", ret);
  426. return ret;
  427. }
  428. pm_runtime_set_active(&client->dev);
  429. pm_runtime_set_autosuspend_delay(&client->dev, 1000);
  430. pm_runtime_use_autosuspend(&client->dev);
  431. pm_runtime_enable(&client->dev);
  432. pm_runtime_mark_last_busy(&client->dev);
  433. pm_runtime_put_sync_autosuspend(&client->dev);
  434. dev_set_drvdata(&client->dev, data);
  435. ret = snd_soc_register_codec(&client->dev,
  436. &soc_codec_dev_tas2552,
  437. tas2552_dai, ARRAY_SIZE(tas2552_dai));
  438. if (ret < 0)
  439. dev_err(&client->dev, "Failed to register codec: %d\n", ret);
  440. return ret;
  441. }
  442. static int tas2552_i2c_remove(struct i2c_client *client)
  443. {
  444. snd_soc_unregister_codec(&client->dev);
  445. return 0;
  446. }
  447. static const struct i2c_device_id tas2552_id[] = {
  448. { "tas2552", 0 },
  449. { }
  450. };
  451. MODULE_DEVICE_TABLE(i2c, tas2552_id);
  452. #if IS_ENABLED(CONFIG_OF)
  453. static const struct of_device_id tas2552_of_match[] = {
  454. { .compatible = "ti,tas2552", },
  455. {},
  456. };
  457. MODULE_DEVICE_TABLE(of, tas2552_of_match);
  458. #endif
  459. static struct i2c_driver tas2552_i2c_driver = {
  460. .driver = {
  461. .name = "tas2552",
  462. .owner = THIS_MODULE,
  463. .of_match_table = of_match_ptr(tas2552_of_match),
  464. .pm = &tas2552_pm,
  465. },
  466. .probe = tas2552_probe,
  467. .remove = tas2552_i2c_remove,
  468. .id_table = tas2552_id,
  469. };
  470. module_i2c_driver(tas2552_i2c_driver);
  471. MODULE_AUTHOR("Dan Muprhy <dmurphy@ti.com>");
  472. MODULE_DESCRIPTION("TAS2552 Audio amplifier driver");
  473. MODULE_LICENSE("GPL");