tas2552.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  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
  103. static void tas2552_sw_shutdown(struct tas2552_data *tas_data, int sw_shutdown)
  104. {
  105. u8 cfg1_reg;
  106. if (sw_shutdown)
  107. cfg1_reg = 0;
  108. else
  109. cfg1_reg = TAS2552_SWS_MASK;
  110. snd_soc_update_bits(tas_data->codec, TAS2552_CFG_1,
  111. TAS2552_SWS_MASK, cfg1_reg);
  112. }
  113. #endif
  114. static int tas2552_hw_params(struct snd_pcm_substream *substream,
  115. struct snd_pcm_hw_params *params,
  116. struct snd_soc_dai *dai)
  117. {
  118. struct snd_soc_codec *codec = dai->codec;
  119. struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev);
  120. int sample_rate, pll_clk;
  121. int d;
  122. u8 p, j;
  123. if (!tas2552->mclk)
  124. return -EINVAL;
  125. snd_soc_update_bits(codec, TAS2552_CFG_2, TAS2552_PLL_ENABLE, 0);
  126. if (tas2552->mclk == TAS2552_245MHZ_CLK ||
  127. tas2552->mclk == TAS2552_225MHZ_CLK) {
  128. /* By pass the PLL configuration */
  129. snd_soc_update_bits(codec, TAS2552_PLL_CTRL_2,
  130. TAS2552_PLL_BYPASS_MASK,
  131. TAS2552_PLL_BYPASS);
  132. } else {
  133. /* Fill in the PLL control registers for J & D
  134. * PLL_CLK = (.5 * freq * J.D) / 2^p
  135. * Need to fill in J and D here based on incoming freq
  136. */
  137. p = snd_soc_read(codec, TAS2552_PLL_CTRL_1);
  138. p = (p >> 7);
  139. sample_rate = params_rate(params);
  140. if (sample_rate == 48000)
  141. pll_clk = TAS2552_245MHZ_CLK;
  142. else if (sample_rate == 44100)
  143. pll_clk = TAS2552_225MHZ_CLK;
  144. else {
  145. dev_vdbg(codec->dev, "Substream sample rate is not found %i\n",
  146. params_rate(params));
  147. return -EINVAL;
  148. }
  149. j = (pll_clk * 2 * (1 << p)) / tas2552->mclk;
  150. d = (pll_clk * 2 * (1 << p)) % tas2552->mclk;
  151. snd_soc_update_bits(codec, TAS2552_PLL_CTRL_1,
  152. TAS2552_PLL_J_MASK, j);
  153. snd_soc_write(codec, TAS2552_PLL_CTRL_2,
  154. (d >> 7) & TAS2552_PLL_D_UPPER_MASK);
  155. snd_soc_write(codec, TAS2552_PLL_CTRL_3,
  156. d & TAS2552_PLL_D_LOWER_MASK);
  157. }
  158. return 0;
  159. }
  160. static int tas2552_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  161. {
  162. struct snd_soc_codec *codec = dai->codec;
  163. u8 serial_format;
  164. u8 serial_control_mask;
  165. switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  166. case SND_SOC_DAIFMT_CBS_CFS:
  167. serial_format = 0x00;
  168. break;
  169. case SND_SOC_DAIFMT_CBS_CFM:
  170. serial_format = TAS2552_WORD_CLK_MASK;
  171. break;
  172. case SND_SOC_DAIFMT_CBM_CFS:
  173. serial_format = TAS2552_BIT_CLK_MASK;
  174. break;
  175. case SND_SOC_DAIFMT_CBM_CFM:
  176. serial_format = (TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK);
  177. break;
  178. default:
  179. dev_vdbg(codec->dev, "DAI Format master is not found\n");
  180. return -EINVAL;
  181. }
  182. serial_control_mask = TAS2552_BIT_CLK_MASK | TAS2552_WORD_CLK_MASK;
  183. switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  184. case SND_SOC_DAIFMT_I2S:
  185. serial_format &= TAS2552_DAIFMT_I2S_MASK;
  186. break;
  187. case SND_SOC_DAIFMT_DSP_A:
  188. serial_format |= TAS2552_DAIFMT_DSP;
  189. break;
  190. case SND_SOC_DAIFMT_RIGHT_J:
  191. serial_format |= TAS2552_DAIFMT_RIGHT_J;
  192. break;
  193. case SND_SOC_DAIFMT_LEFT_J:
  194. serial_format |= TAS2552_DAIFMT_LEFT_J;
  195. break;
  196. default:
  197. dev_vdbg(codec->dev, "DAI Format is not found\n");
  198. return -EINVAL;
  199. }
  200. if (fmt & SND_SOC_DAIFMT_FORMAT_MASK)
  201. serial_control_mask |= TAS2552_DATA_FORMAT_MASK;
  202. snd_soc_update_bits(codec, TAS2552_SER_CTRL_1, serial_control_mask,
  203. serial_format);
  204. return 0;
  205. }
  206. static int tas2552_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
  207. unsigned int freq, int dir)
  208. {
  209. struct snd_soc_codec *codec = dai->codec;
  210. struct tas2552_data *tas2552 = dev_get_drvdata(codec->dev);
  211. tas2552->mclk = freq;
  212. return 0;
  213. }
  214. static int tas2552_mute(struct snd_soc_dai *dai, int mute)
  215. {
  216. u8 cfg1_reg;
  217. struct snd_soc_codec *codec = dai->codec;
  218. if (mute)
  219. cfg1_reg = TAS2552_MUTE_MASK;
  220. else
  221. cfg1_reg = ~TAS2552_MUTE_MASK;
  222. snd_soc_update_bits(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK, cfg1_reg);
  223. return 0;
  224. }
  225. #ifdef CONFIG_PM
  226. static int tas2552_runtime_suspend(struct device *dev)
  227. {
  228. struct tas2552_data *tas2552 = dev_get_drvdata(dev);
  229. tas2552_sw_shutdown(tas2552, 0);
  230. regcache_cache_only(tas2552->regmap, true);
  231. regcache_mark_dirty(tas2552->regmap);
  232. if (tas2552->enable_gpio)
  233. gpiod_set_value(tas2552->enable_gpio, 0);
  234. return 0;
  235. }
  236. static int tas2552_runtime_resume(struct device *dev)
  237. {
  238. struct tas2552_data *tas2552 = dev_get_drvdata(dev);
  239. if (tas2552->enable_gpio)
  240. gpiod_set_value(tas2552->enable_gpio, 1);
  241. tas2552_sw_shutdown(tas2552, 1);
  242. regcache_cache_only(tas2552->regmap, false);
  243. regcache_sync(tas2552->regmap);
  244. return 0;
  245. }
  246. #endif
  247. static const struct dev_pm_ops tas2552_pm = {
  248. SET_RUNTIME_PM_OPS(tas2552_runtime_suspend, tas2552_runtime_resume,
  249. NULL)
  250. };
  251. static struct snd_soc_dai_ops tas2552_speaker_dai_ops = {
  252. .hw_params = tas2552_hw_params,
  253. .set_sysclk = tas2552_set_dai_sysclk,
  254. .set_fmt = tas2552_set_dai_fmt,
  255. .digital_mute = tas2552_mute,
  256. };
  257. /* Formats supported by TAS2552 driver. */
  258. #define TAS2552_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
  259. SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
  260. /* TAS2552 dai structure. */
  261. static struct snd_soc_dai_driver tas2552_dai[] = {
  262. {
  263. .name = "tas2552-amplifier",
  264. .playback = {
  265. .stream_name = "Playback",
  266. .channels_min = 2,
  267. .channels_max = 2,
  268. .rates = SNDRV_PCM_RATE_8000_192000,
  269. .formats = TAS2552_FORMATS,
  270. },
  271. .ops = &tas2552_speaker_dai_ops,
  272. },
  273. };
  274. /*
  275. * DAC digital volumes. From -7 to 24 dB in 1 dB steps
  276. */
  277. static DECLARE_TLV_DB_SCALE(dac_tlv, -7, 100, 24);
  278. static const struct snd_kcontrol_new tas2552_snd_controls[] = {
  279. SOC_SINGLE_TLV("Speaker Driver Playback Volume",
  280. TAS2552_PGA_GAIN, 0, 0x1f, 1, dac_tlv),
  281. SOC_DAPM_SINGLE("Playback AMP", SND_SOC_NOPM, 0, 1, 0),
  282. };
  283. static const struct reg_default tas2552_init_regs[] = {
  284. { TAS2552_RESERVED_0D, 0xc0 },
  285. };
  286. static int tas2552_codec_probe(struct snd_soc_codec *codec)
  287. {
  288. struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
  289. int ret;
  290. tas2552->codec = codec;
  291. ret = regulator_bulk_enable(ARRAY_SIZE(tas2552->supplies),
  292. tas2552->supplies);
  293. if (ret != 0) {
  294. dev_err(codec->dev, "Failed to enable supplies: %d\n",
  295. ret);
  296. return ret;
  297. }
  298. if (tas2552->enable_gpio)
  299. gpiod_set_value(tas2552->enable_gpio, 1);
  300. ret = pm_runtime_get_sync(codec->dev);
  301. if (ret < 0) {
  302. dev_err(codec->dev, "Enabling device failed: %d\n",
  303. ret);
  304. goto probe_fail;
  305. }
  306. snd_soc_write(codec, TAS2552_CFG_1, TAS2552_MUTE_MASK |
  307. TAS2552_PLL_SRC_BCLK);
  308. snd_soc_write(codec, TAS2552_CFG_3, TAS2552_I2S_OUT_SEL |
  309. TAS2552_DIN_SRC_SEL_AVG_L_R | TAS2552_88_96KHZ);
  310. snd_soc_write(codec, TAS2552_DOUT, TAS2552_PDM_DATA_I);
  311. snd_soc_write(codec, TAS2552_OUTPUT_DATA, TAS2552_PDM_DATA_V_I | 0x8);
  312. snd_soc_write(codec, TAS2552_PDM_CFG, TAS2552_PDM_BCLK_SEL);
  313. snd_soc_write(codec, TAS2552_BOOST_PT_CTRL, TAS2552_APT_DELAY_200 |
  314. TAS2552_APT_THRESH_2_1_7);
  315. ret = regmap_register_patch(tas2552->regmap, tas2552_init_regs,
  316. ARRAY_SIZE(tas2552_init_regs));
  317. if (ret != 0) {
  318. dev_err(codec->dev, "Failed to write init registers: %d\n",
  319. ret);
  320. goto patch_fail;
  321. }
  322. snd_soc_write(codec, TAS2552_CFG_2, TAS2552_BOOST_EN |
  323. TAS2552_APT_EN | TAS2552_LIM_EN);
  324. return 0;
  325. patch_fail:
  326. pm_runtime_put(codec->dev);
  327. probe_fail:
  328. if (tas2552->enable_gpio)
  329. gpiod_set_value(tas2552->enable_gpio, 0);
  330. regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies),
  331. tas2552->supplies);
  332. return -EIO;
  333. }
  334. static int tas2552_codec_remove(struct snd_soc_codec *codec)
  335. {
  336. struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
  337. pm_runtime_put(codec->dev);
  338. if (tas2552->enable_gpio)
  339. gpiod_set_value(tas2552->enable_gpio, 0);
  340. return 0;
  341. };
  342. #ifdef CONFIG_PM
  343. static int tas2552_suspend(struct snd_soc_codec *codec)
  344. {
  345. struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
  346. int ret;
  347. ret = regulator_bulk_disable(ARRAY_SIZE(tas2552->supplies),
  348. tas2552->supplies);
  349. if (ret != 0)
  350. dev_err(codec->dev, "Failed to disable supplies: %d\n",
  351. ret);
  352. return 0;
  353. }
  354. static int tas2552_resume(struct snd_soc_codec *codec)
  355. {
  356. struct tas2552_data *tas2552 = snd_soc_codec_get_drvdata(codec);
  357. int ret;
  358. ret = regulator_bulk_enable(ARRAY_SIZE(tas2552->supplies),
  359. tas2552->supplies);
  360. if (ret != 0) {
  361. dev_err(codec->dev, "Failed to enable supplies: %d\n",
  362. ret);
  363. }
  364. return 0;
  365. }
  366. #else
  367. #define tas2552_suspend NULL
  368. #define tas2552_resume NULL
  369. #endif
  370. static struct snd_soc_codec_driver soc_codec_dev_tas2552 = {
  371. .probe = tas2552_codec_probe,
  372. .remove = tas2552_codec_remove,
  373. .suspend = tas2552_suspend,
  374. .resume = tas2552_resume,
  375. .controls = tas2552_snd_controls,
  376. .num_controls = ARRAY_SIZE(tas2552_snd_controls),
  377. .dapm_widgets = tas2552_dapm_widgets,
  378. .num_dapm_widgets = ARRAY_SIZE(tas2552_dapm_widgets),
  379. .dapm_routes = tas2552_audio_map,
  380. .num_dapm_routes = ARRAY_SIZE(tas2552_audio_map),
  381. };
  382. static const struct regmap_config tas2552_regmap_config = {
  383. .reg_bits = 8,
  384. .val_bits = 8,
  385. .max_register = TAS2552_MAX_REG,
  386. .reg_defaults = tas2552_reg_defs,
  387. .num_reg_defaults = ARRAY_SIZE(tas2552_reg_defs),
  388. .cache_type = REGCACHE_RBTREE,
  389. };
  390. static int tas2552_probe(struct i2c_client *client,
  391. const struct i2c_device_id *id)
  392. {
  393. struct device *dev;
  394. struct tas2552_data *data;
  395. int ret;
  396. int i;
  397. dev = &client->dev;
  398. data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
  399. if (data == NULL)
  400. return -ENOMEM;
  401. data->enable_gpio = devm_gpiod_get(dev, "enable");
  402. if (IS_ERR(data->enable_gpio)) {
  403. ret = PTR_ERR(data->enable_gpio);
  404. if (ret != -ENOENT && ret != -ENOSYS)
  405. return ret;
  406. data->enable_gpio = NULL;
  407. } else {
  408. gpiod_direction_output(data->enable_gpio, 0);
  409. }
  410. data->tas2552_client = client;
  411. data->regmap = devm_regmap_init_i2c(client, &tas2552_regmap_config);
  412. if (IS_ERR(data->regmap)) {
  413. ret = PTR_ERR(data->regmap);
  414. dev_err(&client->dev, "Failed to allocate register map: %d\n",
  415. ret);
  416. return ret;
  417. }
  418. for (i = 0; i < ARRAY_SIZE(data->supplies); i++)
  419. data->supplies[i].supply = tas2552_supply_names[i];
  420. ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->supplies),
  421. data->supplies);
  422. if (ret != 0) {
  423. dev_err(dev, "Failed to request supplies: %d\n", ret);
  424. return ret;
  425. }
  426. pm_runtime_set_active(&client->dev);
  427. pm_runtime_set_autosuspend_delay(&client->dev, 1000);
  428. pm_runtime_use_autosuspend(&client->dev);
  429. pm_runtime_enable(&client->dev);
  430. pm_runtime_mark_last_busy(&client->dev);
  431. pm_runtime_put_sync_autosuspend(&client->dev);
  432. dev_set_drvdata(&client->dev, data);
  433. ret = snd_soc_register_codec(&client->dev,
  434. &soc_codec_dev_tas2552,
  435. tas2552_dai, ARRAY_SIZE(tas2552_dai));
  436. if (ret < 0)
  437. dev_err(&client->dev, "Failed to register codec: %d\n", ret);
  438. return ret;
  439. }
  440. static int tas2552_i2c_remove(struct i2c_client *client)
  441. {
  442. snd_soc_unregister_codec(&client->dev);
  443. return 0;
  444. }
  445. static const struct i2c_device_id tas2552_id[] = {
  446. { "tas2552", 0 },
  447. { }
  448. };
  449. MODULE_DEVICE_TABLE(i2c, tas2552_id);
  450. #if IS_ENABLED(CONFIG_OF)
  451. static const struct of_device_id tas2552_of_match[] = {
  452. { .compatible = "ti,tas2552", },
  453. {},
  454. };
  455. MODULE_DEVICE_TABLE(of, tas2552_of_match);
  456. #endif
  457. static struct i2c_driver tas2552_i2c_driver = {
  458. .driver = {
  459. .name = "tas2552",
  460. .owner = THIS_MODULE,
  461. .of_match_table = of_match_ptr(tas2552_of_match),
  462. .pm = &tas2552_pm,
  463. },
  464. .probe = tas2552_probe,
  465. .remove = tas2552_i2c_remove,
  466. .id_table = tas2552_id,
  467. };
  468. module_i2c_driver(tas2552_i2c_driver);
  469. MODULE_AUTHOR("Dan Muprhy <dmurphy@ti.com>");
  470. MODULE_DESCRIPTION("TAS2552 Audio amplifier driver");
  471. MODULE_LICENSE("GPL");