tas571x.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. /*
  2. * TAS571x amplifier audio driver
  3. *
  4. * Copyright (C) 2015 Google, Inc.
  5. * Copyright (c) 2013 Daniel Mack <zonque@gmail.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. */
  12. #include <linux/clk.h>
  13. #include <linux/delay.h>
  14. #include <linux/device.h>
  15. #include <linux/gpio/consumer.h>
  16. #include <linux/i2c.h>
  17. #include <linux/init.h>
  18. #include <linux/kernel.h>
  19. #include <linux/module.h>
  20. #include <linux/of_device.h>
  21. #include <linux/regmap.h>
  22. #include <linux/regulator/consumer.h>
  23. #include <linux/stddef.h>
  24. #include <sound/pcm_params.h>
  25. #include <sound/soc.h>
  26. #include <sound/tlv.h>
  27. #include "tas571x.h"
  28. #define TAS571X_MAX_SUPPLIES 6
  29. struct tas571x_chip {
  30. const char *const *supply_names;
  31. int num_supply_names;
  32. const struct snd_kcontrol_new *controls;
  33. int num_controls;
  34. const struct regmap_config *regmap_config;
  35. int vol_reg_size;
  36. };
  37. struct tas571x_private {
  38. const struct tas571x_chip *chip;
  39. struct regmap *regmap;
  40. struct regulator_bulk_data supplies[TAS571X_MAX_SUPPLIES];
  41. struct clk *mclk;
  42. unsigned int format;
  43. struct gpio_desc *reset_gpio;
  44. struct gpio_desc *pdn_gpio;
  45. struct snd_soc_codec_driver codec_driver;
  46. };
  47. static int tas571x_register_size(struct tas571x_private *priv, unsigned int reg)
  48. {
  49. switch (reg) {
  50. case TAS571X_MVOL_REG:
  51. case TAS571X_CH1_VOL_REG:
  52. case TAS571X_CH2_VOL_REG:
  53. return priv->chip->vol_reg_size;
  54. default:
  55. return 1;
  56. }
  57. }
  58. static int tas571x_reg_write(void *context, unsigned int reg,
  59. unsigned int value)
  60. {
  61. struct i2c_client *client = context;
  62. struct tas571x_private *priv = i2c_get_clientdata(client);
  63. unsigned int i, size;
  64. uint8_t buf[5];
  65. int ret;
  66. size = tas571x_register_size(priv, reg);
  67. buf[0] = reg;
  68. for (i = size; i >= 1; --i) {
  69. buf[i] = value;
  70. value >>= 8;
  71. }
  72. ret = i2c_master_send(client, buf, size + 1);
  73. if (ret == size + 1)
  74. return 0;
  75. else if (ret < 0)
  76. return ret;
  77. else
  78. return -EIO;
  79. }
  80. static int tas571x_reg_read(void *context, unsigned int reg,
  81. unsigned int *value)
  82. {
  83. struct i2c_client *client = context;
  84. struct tas571x_private *priv = i2c_get_clientdata(client);
  85. uint8_t send_buf, recv_buf[4];
  86. struct i2c_msg msgs[2];
  87. unsigned int size;
  88. unsigned int i;
  89. int ret;
  90. size = tas571x_register_size(priv, reg);
  91. send_buf = reg;
  92. msgs[0].addr = client->addr;
  93. msgs[0].len = sizeof(send_buf);
  94. msgs[0].buf = &send_buf;
  95. msgs[0].flags = 0;
  96. msgs[1].addr = client->addr;
  97. msgs[1].len = size;
  98. msgs[1].buf = recv_buf;
  99. msgs[1].flags = I2C_M_RD;
  100. ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
  101. if (ret < 0)
  102. return ret;
  103. else if (ret != ARRAY_SIZE(msgs))
  104. return -EIO;
  105. *value = 0;
  106. for (i = 0; i < size; i++) {
  107. *value <<= 8;
  108. *value |= recv_buf[i];
  109. }
  110. return 0;
  111. }
  112. static int tas571x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format)
  113. {
  114. struct tas571x_private *priv = snd_soc_codec_get_drvdata(dai->codec);
  115. priv->format = format;
  116. return 0;
  117. }
  118. static int tas571x_hw_params(struct snd_pcm_substream *substream,
  119. struct snd_pcm_hw_params *params,
  120. struct snd_soc_dai *dai)
  121. {
  122. struct tas571x_private *priv = snd_soc_codec_get_drvdata(dai->codec);
  123. u32 val;
  124. switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {
  125. case SND_SOC_DAIFMT_RIGHT_J:
  126. val = 0x00;
  127. break;
  128. case SND_SOC_DAIFMT_I2S:
  129. val = 0x03;
  130. break;
  131. case SND_SOC_DAIFMT_LEFT_J:
  132. val = 0x06;
  133. break;
  134. default:
  135. return -EINVAL;
  136. }
  137. if (params_width(params) >= 24)
  138. val += 2;
  139. else if (params_width(params) >= 20)
  140. val += 1;
  141. return regmap_update_bits(priv->regmap, TAS571X_SDI_REG,
  142. TAS571X_SDI_FMT_MASK, val);
  143. }
  144. static int tas571x_set_bias_level(struct snd_soc_codec *codec,
  145. enum snd_soc_bias_level level)
  146. {
  147. struct tas571x_private *priv = snd_soc_codec_get_drvdata(codec);
  148. int ret;
  149. switch (level) {
  150. case SND_SOC_BIAS_ON:
  151. break;
  152. case SND_SOC_BIAS_PREPARE:
  153. break;
  154. case SND_SOC_BIAS_STANDBY:
  155. if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
  156. if (!IS_ERR(priv->mclk)) {
  157. ret = clk_prepare_enable(priv->mclk);
  158. if (ret) {
  159. dev_err(codec->dev,
  160. "Failed to enable master clock: %d\n",
  161. ret);
  162. return ret;
  163. }
  164. }
  165. gpiod_set_value(priv->pdn_gpio, 0);
  166. usleep_range(5000, 6000);
  167. regcache_cache_only(priv->regmap, false);
  168. ret = regcache_sync(priv->regmap);
  169. if (ret)
  170. return ret;
  171. }
  172. break;
  173. case SND_SOC_BIAS_OFF:
  174. regcache_cache_only(priv->regmap, true);
  175. gpiod_set_value(priv->pdn_gpio, 1);
  176. if (!IS_ERR(priv->mclk))
  177. clk_disable_unprepare(priv->mclk);
  178. break;
  179. }
  180. return 0;
  181. }
  182. static const struct snd_soc_dai_ops tas571x_dai_ops = {
  183. .set_fmt = tas571x_set_dai_fmt,
  184. .hw_params = tas571x_hw_params,
  185. };
  186. static const char *const tas5711_supply_names[] = {
  187. "AVDD",
  188. "DVDD",
  189. "PVDD_A",
  190. "PVDD_B",
  191. "PVDD_C",
  192. "PVDD_D",
  193. };
  194. static const DECLARE_TLV_DB_SCALE(tas5711_volume_tlv, -10350, 50, 1);
  195. static const struct snd_kcontrol_new tas5711_controls[] = {
  196. SOC_SINGLE_TLV("Master Volume",
  197. TAS571X_MVOL_REG,
  198. 0, 0xff, 1, tas5711_volume_tlv),
  199. SOC_DOUBLE_R_TLV("Speaker Volume",
  200. TAS571X_CH1_VOL_REG,
  201. TAS571X_CH2_VOL_REG,
  202. 0, 0xff, 1, tas5711_volume_tlv),
  203. SOC_DOUBLE("Speaker Switch",
  204. TAS571X_SOFT_MUTE_REG,
  205. TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT,
  206. 1, 1),
  207. };
  208. static const struct reg_default tas5711_reg_defaults[] = {
  209. { 0x04, 0x05 },
  210. { 0x05, 0x40 },
  211. { 0x06, 0x00 },
  212. { 0x07, 0xff },
  213. { 0x08, 0x30 },
  214. { 0x09, 0x30 },
  215. { 0x1b, 0x82 },
  216. };
  217. static const struct regmap_config tas5711_regmap_config = {
  218. .reg_bits = 8,
  219. .val_bits = 32,
  220. .max_register = 0xff,
  221. .reg_read = tas571x_reg_read,
  222. .reg_write = tas571x_reg_write,
  223. .reg_defaults = tas5711_reg_defaults,
  224. .num_reg_defaults = ARRAY_SIZE(tas5711_reg_defaults),
  225. .cache_type = REGCACHE_RBTREE,
  226. };
  227. static const struct tas571x_chip tas5711_chip = {
  228. .supply_names = tas5711_supply_names,
  229. .num_supply_names = ARRAY_SIZE(tas5711_supply_names),
  230. .controls = tas5711_controls,
  231. .num_controls = ARRAY_SIZE(tas5711_controls),
  232. .regmap_config = &tas5711_regmap_config,
  233. .vol_reg_size = 1,
  234. };
  235. static const char *const tas5717_supply_names[] = {
  236. "AVDD",
  237. "DVDD",
  238. "HPVDD",
  239. "PVDD_AB",
  240. "PVDD_CD",
  241. };
  242. static const DECLARE_TLV_DB_SCALE(tas5717_volume_tlv, -10375, 25, 0);
  243. static const struct snd_kcontrol_new tas5717_controls[] = {
  244. /* MVOL LSB is ignored - see comments in tas571x_i2c_probe() */
  245. SOC_SINGLE_TLV("Master Volume",
  246. TAS571X_MVOL_REG, 1, 0x1ff, 1,
  247. tas5717_volume_tlv),
  248. SOC_DOUBLE_R_TLV("Speaker Volume",
  249. TAS571X_CH1_VOL_REG, TAS571X_CH2_VOL_REG,
  250. 1, 0x1ff, 1, tas5717_volume_tlv),
  251. SOC_DOUBLE("Speaker Switch",
  252. TAS571X_SOFT_MUTE_REG,
  253. TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT,
  254. 1, 1),
  255. };
  256. static const struct reg_default tas5717_reg_defaults[] = {
  257. { 0x04, 0x05 },
  258. { 0x05, 0x40 },
  259. { 0x06, 0x00 },
  260. { 0x07, 0x03ff },
  261. { 0x08, 0x00c0 },
  262. { 0x09, 0x00c0 },
  263. { 0x1b, 0x82 },
  264. };
  265. static const struct regmap_config tas5717_regmap_config = {
  266. .reg_bits = 8,
  267. .val_bits = 32,
  268. .max_register = 0xff,
  269. .reg_read = tas571x_reg_read,
  270. .reg_write = tas571x_reg_write,
  271. .reg_defaults = tas5717_reg_defaults,
  272. .num_reg_defaults = ARRAY_SIZE(tas5717_reg_defaults),
  273. .cache_type = REGCACHE_RBTREE,
  274. };
  275. /* This entry is reused for tas5719 as the software interface is identical. */
  276. static const struct tas571x_chip tas5717_chip = {
  277. .supply_names = tas5717_supply_names,
  278. .num_supply_names = ARRAY_SIZE(tas5717_supply_names),
  279. .controls = tas5717_controls,
  280. .num_controls = ARRAY_SIZE(tas5717_controls),
  281. .regmap_config = &tas5717_regmap_config,
  282. .vol_reg_size = 2,
  283. };
  284. static const struct snd_soc_dapm_widget tas571x_dapm_widgets[] = {
  285. SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),
  286. SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),
  287. SND_SOC_DAPM_OUTPUT("OUT_A"),
  288. SND_SOC_DAPM_OUTPUT("OUT_B"),
  289. SND_SOC_DAPM_OUTPUT("OUT_C"),
  290. SND_SOC_DAPM_OUTPUT("OUT_D"),
  291. };
  292. static const struct snd_soc_dapm_route tas571x_dapm_routes[] = {
  293. { "DACL", NULL, "Playback" },
  294. { "DACR", NULL, "Playback" },
  295. { "OUT_A", NULL, "DACL" },
  296. { "OUT_B", NULL, "DACL" },
  297. { "OUT_C", NULL, "DACR" },
  298. { "OUT_D", NULL, "DACR" },
  299. };
  300. static const struct snd_soc_codec_driver tas571x_codec = {
  301. .set_bias_level = tas571x_set_bias_level,
  302. .idle_bias_off = true,
  303. .dapm_widgets = tas571x_dapm_widgets,
  304. .num_dapm_widgets = ARRAY_SIZE(tas571x_dapm_widgets),
  305. .dapm_routes = tas571x_dapm_routes,
  306. .num_dapm_routes = ARRAY_SIZE(tas571x_dapm_routes),
  307. };
  308. static struct snd_soc_dai_driver tas571x_dai = {
  309. .name = "tas571x-hifi",
  310. .playback = {
  311. .stream_name = "Playback",
  312. .channels_min = 2,
  313. .channels_max = 2,
  314. .rates = SNDRV_PCM_RATE_8000_48000,
  315. .formats = SNDRV_PCM_FMTBIT_S32_LE |
  316. SNDRV_PCM_FMTBIT_S24_LE |
  317. SNDRV_PCM_FMTBIT_S16_LE,
  318. },
  319. .ops = &tas571x_dai_ops,
  320. };
  321. static const struct of_device_id tas571x_of_match[];
  322. static int tas571x_i2c_probe(struct i2c_client *client,
  323. const struct i2c_device_id *id)
  324. {
  325. struct tas571x_private *priv;
  326. struct device *dev = &client->dev;
  327. const struct of_device_id *of_id;
  328. int i, ret;
  329. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  330. if (!priv)
  331. return -ENOMEM;
  332. i2c_set_clientdata(client, priv);
  333. of_id = of_match_device(tas571x_of_match, dev);
  334. if (!of_id) {
  335. dev_err(dev, "Unknown device type\n");
  336. return -EINVAL;
  337. }
  338. priv->chip = of_id->data;
  339. priv->mclk = devm_clk_get(dev, "mclk");
  340. if (IS_ERR(priv->mclk) && PTR_ERR(priv->mclk) != -ENOENT) {
  341. dev_err(dev, "Failed to request mclk: %ld\n",
  342. PTR_ERR(priv->mclk));
  343. return PTR_ERR(priv->mclk);
  344. }
  345. BUG_ON(priv->chip->num_supply_names > TAS571X_MAX_SUPPLIES);
  346. for (i = 0; i < priv->chip->num_supply_names; i++)
  347. priv->supplies[i].supply = priv->chip->supply_names[i];
  348. ret = devm_regulator_bulk_get(dev, priv->chip->num_supply_names,
  349. priv->supplies);
  350. if (ret) {
  351. dev_err(dev, "Failed to get supplies: %d\n", ret);
  352. return ret;
  353. }
  354. ret = regulator_bulk_enable(priv->chip->num_supply_names,
  355. priv->supplies);
  356. if (ret) {
  357. dev_err(dev, "Failed to enable supplies: %d\n", ret);
  358. return ret;
  359. }
  360. priv->regmap = devm_regmap_init(dev, NULL, client,
  361. priv->chip->regmap_config);
  362. if (IS_ERR(priv->regmap))
  363. return PTR_ERR(priv->regmap);
  364. priv->pdn_gpio = devm_gpiod_get_optional(dev, "pdn", GPIOD_OUT_LOW);
  365. if (IS_ERR(priv->pdn_gpio)) {
  366. dev_err(dev, "error requesting pdn_gpio: %ld\n",
  367. PTR_ERR(priv->pdn_gpio));
  368. return PTR_ERR(priv->pdn_gpio);
  369. }
  370. priv->reset_gpio = devm_gpiod_get_optional(dev, "reset",
  371. GPIOD_OUT_HIGH);
  372. if (IS_ERR(priv->reset_gpio)) {
  373. dev_err(dev, "error requesting reset_gpio: %ld\n",
  374. PTR_ERR(priv->reset_gpio));
  375. return PTR_ERR(priv->reset_gpio);
  376. } else if (priv->reset_gpio) {
  377. /* pulse the active low reset line for ~100us */
  378. usleep_range(100, 200);
  379. gpiod_set_value(priv->reset_gpio, 0);
  380. usleep_range(12000, 20000);
  381. }
  382. ret = regmap_write(priv->regmap, TAS571X_OSC_TRIM_REG, 0);
  383. if (ret)
  384. return ret;
  385. ret = regmap_update_bits(priv->regmap, TAS571X_SYS_CTRL_2_REG,
  386. TAS571X_SYS_CTRL_2_SDN_MASK, 0);
  387. if (ret)
  388. return ret;
  389. memcpy(&priv->codec_driver, &tas571x_codec, sizeof(priv->codec_driver));
  390. priv->codec_driver.controls = priv->chip->controls;
  391. priv->codec_driver.num_controls = priv->chip->num_controls;
  392. if (priv->chip->vol_reg_size == 2) {
  393. /*
  394. * The master volume defaults to 0x3ff (mute), but we ignore
  395. * (zero) the LSB because the hardware step size is 0.125 dB
  396. * and TLV_DB_SCALE_ITEM has a resolution of 0.01 dB.
  397. */
  398. ret = regmap_update_bits(priv->regmap, TAS571X_MVOL_REG, 1, 0);
  399. if (ret)
  400. return ret;
  401. }
  402. regcache_cache_only(priv->regmap, true);
  403. gpiod_set_value(priv->pdn_gpio, 1);
  404. return snd_soc_register_codec(&client->dev, &priv->codec_driver,
  405. &tas571x_dai, 1);
  406. }
  407. static int tas571x_i2c_remove(struct i2c_client *client)
  408. {
  409. struct tas571x_private *priv = i2c_get_clientdata(client);
  410. snd_soc_unregister_codec(&client->dev);
  411. regulator_bulk_disable(priv->chip->num_supply_names, priv->supplies);
  412. return 0;
  413. }
  414. static const struct of_device_id tas571x_of_match[] = {
  415. { .compatible = "ti,tas5711", .data = &tas5711_chip, },
  416. { .compatible = "ti,tas5717", .data = &tas5717_chip, },
  417. { .compatible = "ti,tas5719", .data = &tas5717_chip, },
  418. { }
  419. };
  420. MODULE_DEVICE_TABLE(of, tas571x_of_match);
  421. static const struct i2c_device_id tas571x_i2c_id[] = {
  422. { "tas5711", 0 },
  423. { "tas5717", 0 },
  424. { "tas5719", 0 },
  425. { }
  426. };
  427. MODULE_DEVICE_TABLE(i2c, tas571x_i2c_id);
  428. static struct i2c_driver tas571x_i2c_driver = {
  429. .driver = {
  430. .name = "tas571x",
  431. .of_match_table = of_match_ptr(tas571x_of_match),
  432. },
  433. .probe = tas571x_i2c_probe,
  434. .remove = tas571x_i2c_remove,
  435. .id_table = tas571x_i2c_id,
  436. };
  437. module_i2c_driver(tas571x_i2c_driver);
  438. MODULE_DESCRIPTION("ASoC TAS571x driver");
  439. MODULE_AUTHOR("Kevin Cernekee <cernekee@chromium.org>");
  440. MODULE_LICENSE("GPL");