wm8804.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * wm8804.c -- WM8804 S/PDIF transceiver driver
  4. *
  5. * Copyright 2010-11 Wolfson Microelectronics plc
  6. *
  7. * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
  8. */
  9. #include <linux/module.h>
  10. #include <linux/moduleparam.h>
  11. #include <linux/init.h>
  12. #include <linux/gpio/consumer.h>
  13. #include <linux/delay.h>
  14. #include <linux/pm.h>
  15. #include <linux/pm_runtime.h>
  16. #include <linux/of_device.h>
  17. #include <linux/regulator/consumer.h>
  18. #include <linux/slab.h>
  19. #include <sound/core.h>
  20. #include <sound/pcm.h>
  21. #include <sound/pcm_params.h>
  22. #include <sound/soc.h>
  23. #include <sound/initval.h>
  24. #include <sound/tlv.h>
  25. #include <sound/soc-dapm.h>
  26. #include "wm8804.h"
  27. #define WM8804_NUM_SUPPLIES 2
  28. static const char *wm8804_supply_names[WM8804_NUM_SUPPLIES] = {
  29. "PVDD",
  30. "DVDD"
  31. };
  32. static const struct reg_default wm8804_reg_defaults[] = {
  33. { 3, 0x21 }, /* R3 - PLL1 */
  34. { 4, 0xFD }, /* R4 - PLL2 */
  35. { 5, 0x36 }, /* R5 - PLL3 */
  36. { 6, 0x07 }, /* R6 - PLL4 */
  37. { 7, 0x16 }, /* R7 - PLL5 */
  38. { 8, 0x18 }, /* R8 - PLL6 */
  39. { 9, 0xFF }, /* R9 - SPDMODE */
  40. { 10, 0x00 }, /* R10 - INTMASK */
  41. { 18, 0x00 }, /* R18 - SPDTX1 */
  42. { 19, 0x00 }, /* R19 - SPDTX2 */
  43. { 20, 0x00 }, /* R20 - SPDTX3 */
  44. { 21, 0x71 }, /* R21 - SPDTX4 */
  45. { 22, 0x0B }, /* R22 - SPDTX5 */
  46. { 23, 0x70 }, /* R23 - GPO0 */
  47. { 24, 0x57 }, /* R24 - GPO1 */
  48. { 26, 0x42 }, /* R26 - GPO2 */
  49. { 27, 0x06 }, /* R27 - AIFTX */
  50. { 28, 0x06 }, /* R28 - AIFRX */
  51. { 29, 0x80 }, /* R29 - SPDRX1 */
  52. { 30, 0x07 }, /* R30 - PWRDN */
  53. };
  54. struct wm8804_priv {
  55. struct device *dev;
  56. struct regmap *regmap;
  57. struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES];
  58. struct notifier_block disable_nb[WM8804_NUM_SUPPLIES];
  59. int mclk_div;
  60. struct gpio_desc *reset;
  61. int aif_pwr;
  62. };
  63. static int txsrc_put(struct snd_kcontrol *kcontrol,
  64. struct snd_ctl_elem_value *ucontrol);
  65. static int wm8804_aif_event(struct snd_soc_dapm_widget *w,
  66. struct snd_kcontrol *kcontrol, int event);
  67. /*
  68. * We can't use the same notifier block for more than one supply and
  69. * there's no way I can see to get from a callback to the caller
  70. * except container_of().
  71. */
  72. #define WM8804_REGULATOR_EVENT(n) \
  73. static int wm8804_regulator_event_##n(struct notifier_block *nb, \
  74. unsigned long event, void *data) \
  75. { \
  76. struct wm8804_priv *wm8804 = container_of(nb, struct wm8804_priv, \
  77. disable_nb[n]); \
  78. if (event & REGULATOR_EVENT_DISABLE) { \
  79. regcache_mark_dirty(wm8804->regmap); \
  80. } \
  81. return 0; \
  82. }
  83. WM8804_REGULATOR_EVENT(0)
  84. WM8804_REGULATOR_EVENT(1)
  85. static const char *txsrc_text[] = { "S/PDIF RX", "AIF" };
  86. static SOC_ENUM_SINGLE_DECL(txsrc, WM8804_SPDTX4, 6, txsrc_text);
  87. static const struct snd_kcontrol_new wm8804_tx_source_mux[] = {
  88. SOC_DAPM_ENUM_EXT("Input Source", txsrc,
  89. snd_soc_dapm_get_enum_double, txsrc_put),
  90. };
  91. static const struct snd_soc_dapm_widget wm8804_dapm_widgets[] = {
  92. SND_SOC_DAPM_OUTPUT("SPDIF Out"),
  93. SND_SOC_DAPM_INPUT("SPDIF In"),
  94. SND_SOC_DAPM_PGA("SPDIFTX", WM8804_PWRDN, 2, 1, NULL, 0),
  95. SND_SOC_DAPM_PGA("SPDIFRX", WM8804_PWRDN, 1, 1, NULL, 0),
  96. SND_SOC_DAPM_MUX("Tx Source", SND_SOC_NOPM, 6, 0, wm8804_tx_source_mux),
  97. SND_SOC_DAPM_AIF_OUT_E("AIFTX", NULL, 0, SND_SOC_NOPM, 0, 0, wm8804_aif_event,
  98. SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
  99. SND_SOC_DAPM_AIF_IN_E("AIFRX", NULL, 0, SND_SOC_NOPM, 0, 0, wm8804_aif_event,
  100. SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
  101. };
  102. static const struct snd_soc_dapm_route wm8804_dapm_routes[] = {
  103. { "AIFRX", NULL, "Playback" },
  104. { "Tx Source", "AIF", "AIFRX" },
  105. { "SPDIFRX", NULL, "SPDIF In" },
  106. { "Tx Source", "S/PDIF RX", "SPDIFRX" },
  107. { "SPDIFTX", NULL, "Tx Source" },
  108. { "SPDIF Out", NULL, "SPDIFTX" },
  109. { "AIFTX", NULL, "SPDIFRX" },
  110. { "Capture", NULL, "AIFTX" },
  111. };
  112. static int wm8804_aif_event(struct snd_soc_dapm_widget *w,
  113. struct snd_kcontrol *kcontrol, int event)
  114. {
  115. struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
  116. struct wm8804_priv *wm8804 = snd_soc_component_get_drvdata(component);
  117. switch (event) {
  118. case SND_SOC_DAPM_POST_PMU:
  119. /* power up the aif */
  120. if (!wm8804->aif_pwr)
  121. snd_soc_component_update_bits(component, WM8804_PWRDN, 0x10, 0x0);
  122. wm8804->aif_pwr++;
  123. break;
  124. case SND_SOC_DAPM_POST_PMD:
  125. /* power down only both paths are disabled */
  126. wm8804->aif_pwr--;
  127. if (!wm8804->aif_pwr)
  128. snd_soc_component_update_bits(component, WM8804_PWRDN, 0x10, 0x10);
  129. break;
  130. }
  131. return 0;
  132. }
  133. static int txsrc_put(struct snd_kcontrol *kcontrol,
  134. struct snd_ctl_elem_value *ucontrol)
  135. {
  136. struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
  137. struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
  138. struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
  139. unsigned int val = ucontrol->value.enumerated.item[0] << e->shift_l;
  140. unsigned int mask = 1 << e->shift_l;
  141. unsigned int txpwr;
  142. if (val != 0 && val != mask)
  143. return -EINVAL;
  144. snd_soc_dapm_mutex_lock(dapm);
  145. if (snd_soc_component_test_bits(component, e->reg, mask, val)) {
  146. /* save the current power state of the transmitter */
  147. txpwr = snd_soc_component_read(component, WM8804_PWRDN) & 0x4;
  148. /* power down the transmitter */
  149. snd_soc_component_update_bits(component, WM8804_PWRDN, 0x4, 0x4);
  150. /* set the tx source */
  151. snd_soc_component_update_bits(component, e->reg, mask, val);
  152. /* restore the transmitter's configuration */
  153. snd_soc_component_update_bits(component, WM8804_PWRDN, 0x4, txpwr);
  154. }
  155. snd_soc_dapm_mutex_unlock(dapm);
  156. return 0;
  157. }
  158. static bool wm8804_volatile(struct device *dev, unsigned int reg)
  159. {
  160. switch (reg) {
  161. case WM8804_RST_DEVID1:
  162. case WM8804_DEVID2:
  163. case WM8804_DEVREV:
  164. case WM8804_INTSTAT:
  165. case WM8804_SPDSTAT:
  166. case WM8804_RXCHAN1:
  167. case WM8804_RXCHAN2:
  168. case WM8804_RXCHAN3:
  169. case WM8804_RXCHAN4:
  170. case WM8804_RXCHAN5:
  171. return true;
  172. default:
  173. return false;
  174. }
  175. }
  176. static int wm8804_soft_reset(struct wm8804_priv *wm8804)
  177. {
  178. return regmap_write(wm8804->regmap, WM8804_RST_DEVID1, 0x0);
  179. }
  180. static int wm8804_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
  181. {
  182. struct snd_soc_component *component;
  183. u16 format, master, bcp, lrp;
  184. component = dai->component;
  185. switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  186. case SND_SOC_DAIFMT_I2S:
  187. format = 0x2;
  188. break;
  189. case SND_SOC_DAIFMT_RIGHT_J:
  190. format = 0x0;
  191. break;
  192. case SND_SOC_DAIFMT_LEFT_J:
  193. format = 0x1;
  194. break;
  195. case SND_SOC_DAIFMT_DSP_A:
  196. case SND_SOC_DAIFMT_DSP_B:
  197. format = 0x3;
  198. break;
  199. default:
  200. dev_err(dai->dev, "Unknown dai format\n");
  201. return -EINVAL;
  202. }
  203. /* set data format */
  204. snd_soc_component_update_bits(component, WM8804_AIFTX, 0x3, format);
  205. snd_soc_component_update_bits(component, WM8804_AIFRX, 0x3, format);
  206. switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  207. case SND_SOC_DAIFMT_CBM_CFM:
  208. master = 1;
  209. break;
  210. case SND_SOC_DAIFMT_CBS_CFS:
  211. master = 0;
  212. break;
  213. default:
  214. dev_err(dai->dev, "Unknown master/slave configuration\n");
  215. return -EINVAL;
  216. }
  217. /* set master/slave mode */
  218. snd_soc_component_update_bits(component, WM8804_AIFRX, 0x40, master << 6);
  219. bcp = lrp = 0;
  220. switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  221. case SND_SOC_DAIFMT_NB_NF:
  222. break;
  223. case SND_SOC_DAIFMT_IB_IF:
  224. bcp = lrp = 1;
  225. break;
  226. case SND_SOC_DAIFMT_IB_NF:
  227. bcp = 1;
  228. break;
  229. case SND_SOC_DAIFMT_NB_IF:
  230. lrp = 1;
  231. break;
  232. default:
  233. dev_err(dai->dev, "Unknown polarity configuration\n");
  234. return -EINVAL;
  235. }
  236. /* set frame inversion */
  237. snd_soc_component_update_bits(component, WM8804_AIFTX, 0x10 | 0x20,
  238. (bcp << 4) | (lrp << 5));
  239. snd_soc_component_update_bits(component, WM8804_AIFRX, 0x10 | 0x20,
  240. (bcp << 4) | (lrp << 5));
  241. return 0;
  242. }
  243. static int wm8804_hw_params(struct snd_pcm_substream *substream,
  244. struct snd_pcm_hw_params *params,
  245. struct snd_soc_dai *dai)
  246. {
  247. struct snd_soc_component *component;
  248. u16 blen;
  249. component = dai->component;
  250. switch (params_width(params)) {
  251. case 16:
  252. blen = 0x0;
  253. break;
  254. case 20:
  255. blen = 0x1;
  256. break;
  257. case 24:
  258. blen = 0x2;
  259. break;
  260. default:
  261. dev_err(dai->dev, "Unsupported word length: %u\n",
  262. params_width(params));
  263. return -EINVAL;
  264. }
  265. /* set word length */
  266. snd_soc_component_update_bits(component, WM8804_AIFTX, 0xc, blen << 2);
  267. snd_soc_component_update_bits(component, WM8804_AIFRX, 0xc, blen << 2);
  268. return 0;
  269. }
  270. struct pll_div {
  271. u32 prescale:1;
  272. u32 mclkdiv:1;
  273. u32 freqmode:2;
  274. u32 n:4;
  275. u32 k:22;
  276. };
  277. /* PLL rate to output rate divisions */
  278. static struct {
  279. unsigned int div;
  280. unsigned int freqmode;
  281. unsigned int mclkdiv;
  282. } post_table[] = {
  283. { 2, 0, 0 },
  284. { 4, 0, 1 },
  285. { 4, 1, 0 },
  286. { 8, 1, 1 },
  287. { 8, 2, 0 },
  288. { 16, 2, 1 },
  289. { 12, 3, 0 },
  290. { 24, 3, 1 }
  291. };
  292. #define FIXED_PLL_SIZE ((1ULL << 22) * 10)
  293. static int pll_factors(struct pll_div *pll_div, unsigned int target,
  294. unsigned int source, unsigned int mclk_div)
  295. {
  296. u64 Kpart;
  297. unsigned long int K, Ndiv, Nmod, tmp;
  298. int i;
  299. /*
  300. * Scale the output frequency up; the PLL should run in the
  301. * region of 90-100MHz.
  302. */
  303. for (i = 0; i < ARRAY_SIZE(post_table); i++) {
  304. tmp = target * post_table[i].div;
  305. if ((tmp >= 90000000 && tmp <= 100000000) &&
  306. (mclk_div == post_table[i].mclkdiv)) {
  307. pll_div->freqmode = post_table[i].freqmode;
  308. pll_div->mclkdiv = post_table[i].mclkdiv;
  309. target *= post_table[i].div;
  310. break;
  311. }
  312. }
  313. if (i == ARRAY_SIZE(post_table)) {
  314. pr_err("%s: Unable to scale output frequency: %uHz\n",
  315. __func__, target);
  316. return -EINVAL;
  317. }
  318. pll_div->prescale = 0;
  319. Ndiv = target / source;
  320. if (Ndiv < 5) {
  321. source >>= 1;
  322. pll_div->prescale = 1;
  323. Ndiv = target / source;
  324. }
  325. if (Ndiv < 5 || Ndiv > 13) {
  326. pr_err("%s: WM8804 N value is not within the recommended range: %lu\n",
  327. __func__, Ndiv);
  328. return -EINVAL;
  329. }
  330. pll_div->n = Ndiv;
  331. Nmod = target % source;
  332. Kpart = FIXED_PLL_SIZE * (u64)Nmod;
  333. do_div(Kpart, source);
  334. K = Kpart & 0xffffffff;
  335. if ((K % 10) >= 5)
  336. K += 5;
  337. K /= 10;
  338. pll_div->k = K;
  339. return 0;
  340. }
  341. static int wm8804_set_pll(struct snd_soc_dai *dai, int pll_id,
  342. int source, unsigned int freq_in,
  343. unsigned int freq_out)
  344. {
  345. struct snd_soc_component *component = dai->component;
  346. struct wm8804_priv *wm8804 = snd_soc_component_get_drvdata(component);
  347. bool change;
  348. if (!freq_in || !freq_out) {
  349. /* disable the PLL */
  350. regmap_update_bits_check(wm8804->regmap, WM8804_PWRDN,
  351. 0x1, 0x1, &change);
  352. if (change)
  353. pm_runtime_put(wm8804->dev);
  354. } else {
  355. int ret;
  356. struct pll_div pll_div;
  357. ret = pll_factors(&pll_div, freq_out, freq_in,
  358. wm8804->mclk_div);
  359. if (ret)
  360. return ret;
  361. /* power down the PLL before reprogramming it */
  362. regmap_update_bits_check(wm8804->regmap, WM8804_PWRDN,
  363. 0x1, 0x1, &change);
  364. if (!change)
  365. pm_runtime_get_sync(wm8804->dev);
  366. /* set PLLN and PRESCALE */
  367. snd_soc_component_update_bits(component, WM8804_PLL4, 0xf | 0x10,
  368. pll_div.n | (pll_div.prescale << 4));
  369. /* set mclkdiv and freqmode */
  370. snd_soc_component_update_bits(component, WM8804_PLL5, 0x3 | 0x8,
  371. pll_div.freqmode | (pll_div.mclkdiv << 3));
  372. /* set PLLK */
  373. snd_soc_component_write(component, WM8804_PLL1, pll_div.k & 0xff);
  374. snd_soc_component_write(component, WM8804_PLL2, (pll_div.k >> 8) & 0xff);
  375. snd_soc_component_write(component, WM8804_PLL3, pll_div.k >> 16);
  376. /* power up the PLL */
  377. snd_soc_component_update_bits(component, WM8804_PWRDN, 0x1, 0);
  378. }
  379. return 0;
  380. }
  381. static int wm8804_set_sysclk(struct snd_soc_dai *dai,
  382. int clk_id, unsigned int freq, int dir)
  383. {
  384. struct snd_soc_component *component;
  385. component = dai->component;
  386. switch (clk_id) {
  387. case WM8804_TX_CLKSRC_MCLK:
  388. if ((freq >= 10000000 && freq <= 14400000)
  389. || (freq >= 16280000 && freq <= 27000000))
  390. snd_soc_component_update_bits(component, WM8804_PLL6, 0x80, 0x80);
  391. else {
  392. dev_err(dai->dev, "OSCCLOCK is not within the "
  393. "recommended range: %uHz\n", freq);
  394. return -EINVAL;
  395. }
  396. break;
  397. case WM8804_TX_CLKSRC_PLL:
  398. snd_soc_component_update_bits(component, WM8804_PLL6, 0x80, 0);
  399. break;
  400. case WM8804_CLKOUT_SRC_CLK1:
  401. snd_soc_component_update_bits(component, WM8804_PLL6, 0x8, 0);
  402. break;
  403. case WM8804_CLKOUT_SRC_OSCCLK:
  404. snd_soc_component_update_bits(component, WM8804_PLL6, 0x8, 0x8);
  405. break;
  406. default:
  407. dev_err(dai->dev, "Unknown clock source: %d\n", clk_id);
  408. return -EINVAL;
  409. }
  410. return 0;
  411. }
  412. static int wm8804_set_clkdiv(struct snd_soc_dai *dai,
  413. int div_id, int div)
  414. {
  415. struct snd_soc_component *component;
  416. struct wm8804_priv *wm8804;
  417. component = dai->component;
  418. switch (div_id) {
  419. case WM8804_CLKOUT_DIV:
  420. snd_soc_component_update_bits(component, WM8804_PLL5, 0x30,
  421. (div & 0x3) << 4);
  422. break;
  423. case WM8804_MCLK_DIV:
  424. wm8804 = snd_soc_component_get_drvdata(component);
  425. wm8804->mclk_div = div;
  426. break;
  427. default:
  428. dev_err(dai->dev, "Unknown clock divider: %d\n", div_id);
  429. return -EINVAL;
  430. }
  431. return 0;
  432. }
  433. static const struct snd_soc_dai_ops wm8804_dai_ops = {
  434. .hw_params = wm8804_hw_params,
  435. .set_fmt = wm8804_set_fmt,
  436. .set_sysclk = wm8804_set_sysclk,
  437. .set_clkdiv = wm8804_set_clkdiv,
  438. .set_pll = wm8804_set_pll
  439. };
  440. #define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
  441. SNDRV_PCM_FMTBIT_S24_LE)
  442. #define WM8804_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
  443. SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \
  444. SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
  445. SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
  446. static struct snd_soc_dai_driver wm8804_dai = {
  447. .name = "wm8804-spdif",
  448. .playback = {
  449. .stream_name = "Playback",
  450. .channels_min = 2,
  451. .channels_max = 2,
  452. .rates = WM8804_RATES,
  453. .formats = WM8804_FORMATS,
  454. },
  455. .capture = {
  456. .stream_name = "Capture",
  457. .channels_min = 2,
  458. .channels_max = 2,
  459. .rates = WM8804_RATES,
  460. .formats = WM8804_FORMATS,
  461. },
  462. .ops = &wm8804_dai_ops,
  463. .symmetric_rates = 1
  464. };
  465. static const struct snd_soc_component_driver soc_component_dev_wm8804 = {
  466. .dapm_widgets = wm8804_dapm_widgets,
  467. .num_dapm_widgets = ARRAY_SIZE(wm8804_dapm_widgets),
  468. .dapm_routes = wm8804_dapm_routes,
  469. .num_dapm_routes = ARRAY_SIZE(wm8804_dapm_routes),
  470. .use_pmdown_time = 1,
  471. .endianness = 1,
  472. .non_legacy_dai_naming = 1,
  473. };
  474. const struct regmap_config wm8804_regmap_config = {
  475. .reg_bits = 8,
  476. .val_bits = 8,
  477. .max_register = WM8804_MAX_REGISTER,
  478. .volatile_reg = wm8804_volatile,
  479. .cache_type = REGCACHE_RBTREE,
  480. .reg_defaults = wm8804_reg_defaults,
  481. .num_reg_defaults = ARRAY_SIZE(wm8804_reg_defaults),
  482. };
  483. EXPORT_SYMBOL_GPL(wm8804_regmap_config);
  484. int wm8804_probe(struct device *dev, struct regmap *regmap)
  485. {
  486. struct wm8804_priv *wm8804;
  487. unsigned int id1, id2;
  488. int i, ret;
  489. wm8804 = devm_kzalloc(dev, sizeof(*wm8804), GFP_KERNEL);
  490. if (!wm8804)
  491. return -ENOMEM;
  492. dev_set_drvdata(dev, wm8804);
  493. wm8804->dev = dev;
  494. wm8804->regmap = regmap;
  495. wm8804->reset = devm_gpiod_get_optional(dev, "wlf,reset",
  496. GPIOD_OUT_LOW);
  497. if (IS_ERR(wm8804->reset)) {
  498. ret = PTR_ERR(wm8804->reset);
  499. dev_err(dev, "Failed to get reset line: %d\n", ret);
  500. return ret;
  501. }
  502. for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++)
  503. wm8804->supplies[i].supply = wm8804_supply_names[i];
  504. ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(wm8804->supplies),
  505. wm8804->supplies);
  506. if (ret) {
  507. dev_err(dev, "Failed to request supplies: %d\n", ret);
  508. return ret;
  509. }
  510. wm8804->disable_nb[0].notifier_call = wm8804_regulator_event_0;
  511. wm8804->disable_nb[1].notifier_call = wm8804_regulator_event_1;
  512. /* This should really be moved into the regulator core */
  513. for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) {
  514. struct regulator *regulator = wm8804->supplies[i].consumer;
  515. ret = devm_regulator_register_notifier(regulator,
  516. &wm8804->disable_nb[i]);
  517. if (ret != 0) {
  518. dev_err(dev,
  519. "Failed to register regulator notifier: %d\n",
  520. ret);
  521. return ret;
  522. }
  523. }
  524. ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies),
  525. wm8804->supplies);
  526. if (ret) {
  527. dev_err(dev, "Failed to enable supplies: %d\n", ret);
  528. return ret;
  529. }
  530. gpiod_set_value_cansleep(wm8804->reset, 1);
  531. ret = regmap_read(regmap, WM8804_RST_DEVID1, &id1);
  532. if (ret < 0) {
  533. dev_err(dev, "Failed to read device ID: %d\n", ret);
  534. goto err_reg_enable;
  535. }
  536. ret = regmap_read(regmap, WM8804_DEVID2, &id2);
  537. if (ret < 0) {
  538. dev_err(dev, "Failed to read device ID: %d\n", ret);
  539. goto err_reg_enable;
  540. }
  541. id2 = (id2 << 8) | id1;
  542. if (id2 != 0x8805) {
  543. dev_err(dev, "Invalid device ID: %#x\n", id2);
  544. ret = -EINVAL;
  545. goto err_reg_enable;
  546. }
  547. ret = regmap_read(regmap, WM8804_DEVREV, &id1);
  548. if (ret < 0) {
  549. dev_err(dev, "Failed to read device revision: %d\n",
  550. ret);
  551. goto err_reg_enable;
  552. }
  553. dev_info(dev, "revision %c\n", id1 + 'A');
  554. if (!wm8804->reset) {
  555. ret = wm8804_soft_reset(wm8804);
  556. if (ret < 0) {
  557. dev_err(dev, "Failed to issue reset: %d\n", ret);
  558. goto err_reg_enable;
  559. }
  560. }
  561. ret = devm_snd_soc_register_component(dev, &soc_component_dev_wm8804,
  562. &wm8804_dai, 1);
  563. if (ret < 0) {
  564. dev_err(dev, "Failed to register CODEC: %d\n", ret);
  565. goto err_reg_enable;
  566. }
  567. pm_runtime_set_active(dev);
  568. pm_runtime_enable(dev);
  569. pm_runtime_idle(dev);
  570. return 0;
  571. err_reg_enable:
  572. regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
  573. return ret;
  574. }
  575. EXPORT_SYMBOL_GPL(wm8804_probe);
  576. void wm8804_remove(struct device *dev)
  577. {
  578. pm_runtime_disable(dev);
  579. }
  580. EXPORT_SYMBOL_GPL(wm8804_remove);
  581. #if IS_ENABLED(CONFIG_PM)
  582. static int wm8804_runtime_resume(struct device *dev)
  583. {
  584. struct wm8804_priv *wm8804 = dev_get_drvdata(dev);
  585. int ret;
  586. ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies),
  587. wm8804->supplies);
  588. if (ret) {
  589. dev_err(wm8804->dev, "Failed to enable supplies: %d\n", ret);
  590. return ret;
  591. }
  592. regcache_sync(wm8804->regmap);
  593. /* Power up OSCCLK */
  594. regmap_update_bits(wm8804->regmap, WM8804_PWRDN, 0x8, 0x0);
  595. return 0;
  596. }
  597. static int wm8804_runtime_suspend(struct device *dev)
  598. {
  599. struct wm8804_priv *wm8804 = dev_get_drvdata(dev);
  600. /* Power down OSCCLK */
  601. regmap_update_bits(wm8804->regmap, WM8804_PWRDN, 0x8, 0x8);
  602. regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies),
  603. wm8804->supplies);
  604. return 0;
  605. }
  606. #endif
  607. const struct dev_pm_ops wm8804_pm = {
  608. SET_RUNTIME_PM_OPS(wm8804_runtime_suspend, wm8804_runtime_resume, NULL)
  609. };
  610. EXPORT_SYMBOL_GPL(wm8804_pm);
  611. MODULE_DESCRIPTION("ASoC WM8804 driver");
  612. MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>");
  613. MODULE_LICENSE("GPL");