da7219-aad.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * da7219-aad.c - Dialog DA7219 ALSA SoC AAD Driver
  4. *
  5. * Copyright (c) 2015 Dialog Semiconductor Ltd.
  6. *
  7. * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
  8. */
  9. #include <linux/module.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/clk.h>
  12. #include <linux/i2c.h>
  13. #include <linux/property.h>
  14. #include <linux/pm_wakeirq.h>
  15. #include <linux/slab.h>
  16. #include <linux/delay.h>
  17. #include <linux/workqueue.h>
  18. #include <sound/soc.h>
  19. #include <sound/jack.h>
  20. #include <sound/da7219.h>
  21. #include "da7219.h"
  22. #include "da7219-aad.h"
  23. /*
  24. * Detection control
  25. */
  26. void da7219_aad_jack_det(struct snd_soc_component *component, struct snd_soc_jack *jack)
  27. {
  28. struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
  29. da7219->aad->jack = jack;
  30. da7219->aad->jack_inserted = false;
  31. /* Send an initial empty report */
  32. snd_soc_jack_report(jack, 0, DA7219_AAD_REPORT_ALL_MASK);
  33. /* Enable/Disable jack detection */
  34. snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1,
  35. DA7219_ACCDET_EN_MASK,
  36. (jack ? DA7219_ACCDET_EN_MASK : 0));
  37. }
  38. EXPORT_SYMBOL_GPL(da7219_aad_jack_det);
  39. /*
  40. * Button/HPTest work
  41. */
  42. static void da7219_aad_btn_det_work(struct work_struct *work)
  43. {
  44. struct da7219_aad_priv *da7219_aad =
  45. container_of(work, struct da7219_aad_priv, btn_det_work);
  46. struct snd_soc_component *component = da7219_aad->component;
  47. struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
  48. struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
  49. u8 statusa, micbias_ctrl;
  50. bool micbias_up = false;
  51. int retries = 0;
  52. /* Drive headphones/lineout */
  53. snd_soc_component_update_bits(component, DA7219_HP_L_CTRL,
  54. DA7219_HP_L_AMP_OE_MASK,
  55. DA7219_HP_L_AMP_OE_MASK);
  56. snd_soc_component_update_bits(component, DA7219_HP_R_CTRL,
  57. DA7219_HP_R_AMP_OE_MASK,
  58. DA7219_HP_R_AMP_OE_MASK);
  59. /* Make sure mic bias is up */
  60. snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
  61. snd_soc_dapm_sync(dapm);
  62. do {
  63. statusa = snd_soc_component_read(component, DA7219_ACCDET_STATUS_A);
  64. if (statusa & DA7219_MICBIAS_UP_STS_MASK)
  65. micbias_up = true;
  66. else if (retries++ < DA7219_AAD_MICBIAS_CHK_RETRIES)
  67. msleep(DA7219_AAD_MICBIAS_CHK_DELAY);
  68. } while ((!micbias_up) && (retries < DA7219_AAD_MICBIAS_CHK_RETRIES));
  69. if (retries >= DA7219_AAD_MICBIAS_CHK_RETRIES)
  70. dev_warn(component->dev, "Mic bias status check timed out");
  71. da7219->micbias_on_event = true;
  72. /*
  73. * Mic bias pulse required to enable mic, must be done before enabling
  74. * button detection to prevent erroneous button readings.
  75. */
  76. if (da7219_aad->micbias_pulse_lvl && da7219_aad->micbias_pulse_time) {
  77. /* Pulse higher level voltage */
  78. micbias_ctrl = snd_soc_component_read(component, DA7219_MICBIAS_CTRL);
  79. snd_soc_component_update_bits(component, DA7219_MICBIAS_CTRL,
  80. DA7219_MICBIAS1_LEVEL_MASK,
  81. da7219_aad->micbias_pulse_lvl);
  82. msleep(da7219_aad->micbias_pulse_time);
  83. snd_soc_component_write(component, DA7219_MICBIAS_CTRL, micbias_ctrl);
  84. }
  85. snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1,
  86. DA7219_BUTTON_CONFIG_MASK,
  87. da7219_aad->btn_cfg);
  88. }
  89. static void da7219_aad_hptest_work(struct work_struct *work)
  90. {
  91. struct da7219_aad_priv *da7219_aad =
  92. container_of(work, struct da7219_aad_priv, hptest_work);
  93. struct snd_soc_component *component = da7219_aad->component;
  94. struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
  95. struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
  96. __le16 tonegen_freq_hptest;
  97. u8 pll_srm_sts, pll_ctrl, gain_ramp_ctrl, accdet_cfg8;
  98. int report = 0, ret = 0;
  99. /* Lock DAPM, Kcontrols affected by this test and the PLL */
  100. snd_soc_dapm_mutex_lock(dapm);
  101. mutex_lock(&da7219->ctrl_lock);
  102. mutex_lock(&da7219->pll_lock);
  103. /* Ensure MCLK is available for HP test procedure */
  104. if (da7219->mclk) {
  105. ret = clk_prepare_enable(da7219->mclk);
  106. if (ret) {
  107. dev_err(component->dev, "Failed to enable mclk - %d\n", ret);
  108. mutex_unlock(&da7219->pll_lock);
  109. mutex_unlock(&da7219->ctrl_lock);
  110. snd_soc_dapm_mutex_unlock(dapm);
  111. return;
  112. }
  113. }
  114. /*
  115. * If MCLK not present, then we're using the internal oscillator and
  116. * require different frequency settings to achieve the same result.
  117. *
  118. * If MCLK is present, but PLL is not enabled then we enable it here to
  119. * ensure a consistent detection procedure.
  120. */
  121. pll_srm_sts = snd_soc_component_read(component, DA7219_PLL_SRM_STS);
  122. if (pll_srm_sts & DA7219_PLL_SRM_STS_MCLK) {
  123. tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ);
  124. pll_ctrl = snd_soc_component_read(component, DA7219_PLL_CTRL);
  125. if ((pll_ctrl & DA7219_PLL_MODE_MASK) == DA7219_PLL_MODE_BYPASS)
  126. da7219_set_pll(component, DA7219_SYSCLK_PLL,
  127. DA7219_PLL_FREQ_OUT_98304);
  128. } else {
  129. tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ_INT_OSC);
  130. }
  131. /* Ensure gain ramping at fastest rate */
  132. gain_ramp_ctrl = snd_soc_component_read(component, DA7219_GAIN_RAMP_CTRL);
  133. snd_soc_component_write(component, DA7219_GAIN_RAMP_CTRL, DA7219_GAIN_RAMP_RATE_X8);
  134. /* Bypass cache so it saves current settings */
  135. regcache_cache_bypass(da7219->regmap, true);
  136. /* Make sure Tone Generator is disabled */
  137. snd_soc_component_write(component, DA7219_TONE_GEN_CFG1, 0);
  138. /* Enable HPTest block, 1KOhms check */
  139. snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_8,
  140. DA7219_HPTEST_EN_MASK | DA7219_HPTEST_RES_SEL_MASK,
  141. DA7219_HPTEST_EN_MASK |
  142. DA7219_HPTEST_RES_SEL_1KOHMS);
  143. /* Set gains to 0db */
  144. snd_soc_component_write(component, DA7219_DAC_L_GAIN, DA7219_DAC_DIGITAL_GAIN_0DB);
  145. snd_soc_component_write(component, DA7219_DAC_R_GAIN, DA7219_DAC_DIGITAL_GAIN_0DB);
  146. snd_soc_component_write(component, DA7219_HP_L_GAIN, DA7219_HP_AMP_GAIN_0DB);
  147. snd_soc_component_write(component, DA7219_HP_R_GAIN, DA7219_HP_AMP_GAIN_0DB);
  148. /* Disable DAC filters, EQs and soft mute */
  149. snd_soc_component_update_bits(component, DA7219_DAC_FILTERS1, DA7219_HPF_MODE_MASK,
  150. 0);
  151. snd_soc_component_update_bits(component, DA7219_DAC_FILTERS4, DA7219_DAC_EQ_EN_MASK,
  152. 0);
  153. snd_soc_component_update_bits(component, DA7219_DAC_FILTERS5,
  154. DA7219_DAC_SOFTMUTE_EN_MASK, 0);
  155. /* Enable HP left & right paths */
  156. snd_soc_component_update_bits(component, DA7219_CP_CTRL, DA7219_CP_EN_MASK,
  157. DA7219_CP_EN_MASK);
  158. snd_soc_component_update_bits(component, DA7219_DIG_ROUTING_DAC,
  159. DA7219_DAC_L_SRC_MASK | DA7219_DAC_R_SRC_MASK,
  160. DA7219_DAC_L_SRC_TONEGEN |
  161. DA7219_DAC_R_SRC_TONEGEN);
  162. snd_soc_component_update_bits(component, DA7219_DAC_L_CTRL,
  163. DA7219_DAC_L_EN_MASK | DA7219_DAC_L_MUTE_EN_MASK,
  164. DA7219_DAC_L_EN_MASK);
  165. snd_soc_component_update_bits(component, DA7219_DAC_R_CTRL,
  166. DA7219_DAC_R_EN_MASK | DA7219_DAC_R_MUTE_EN_MASK,
  167. DA7219_DAC_R_EN_MASK);
  168. snd_soc_component_update_bits(component, DA7219_MIXOUT_L_SELECT,
  169. DA7219_MIXOUT_L_MIX_SELECT_MASK,
  170. DA7219_MIXOUT_L_MIX_SELECT_MASK);
  171. snd_soc_component_update_bits(component, DA7219_MIXOUT_R_SELECT,
  172. DA7219_MIXOUT_R_MIX_SELECT_MASK,
  173. DA7219_MIXOUT_R_MIX_SELECT_MASK);
  174. snd_soc_component_update_bits(component, DA7219_DROUTING_ST_OUTFILT_1L,
  175. DA7219_OUTFILT_ST_1L_SRC_MASK,
  176. DA7219_DMIX_ST_SRC_OUTFILT1L);
  177. snd_soc_component_update_bits(component, DA7219_DROUTING_ST_OUTFILT_1R,
  178. DA7219_OUTFILT_ST_1R_SRC_MASK,
  179. DA7219_DMIX_ST_SRC_OUTFILT1R);
  180. snd_soc_component_update_bits(component, DA7219_MIXOUT_L_CTRL,
  181. DA7219_MIXOUT_L_AMP_EN_MASK,
  182. DA7219_MIXOUT_L_AMP_EN_MASK);
  183. snd_soc_component_update_bits(component, DA7219_MIXOUT_R_CTRL,
  184. DA7219_MIXOUT_R_AMP_EN_MASK,
  185. DA7219_MIXOUT_R_AMP_EN_MASK);
  186. snd_soc_component_update_bits(component, DA7219_HP_L_CTRL,
  187. DA7219_HP_L_AMP_OE_MASK | DA7219_HP_L_AMP_EN_MASK,
  188. DA7219_HP_L_AMP_OE_MASK | DA7219_HP_L_AMP_EN_MASK);
  189. snd_soc_component_update_bits(component, DA7219_HP_R_CTRL,
  190. DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK,
  191. DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK);
  192. msleep(DA7219_SETTLING_DELAY);
  193. snd_soc_component_update_bits(component, DA7219_HP_L_CTRL,
  194. DA7219_HP_L_AMP_MUTE_EN_MASK |
  195. DA7219_HP_L_AMP_MIN_GAIN_EN_MASK, 0);
  196. snd_soc_component_update_bits(component, DA7219_HP_R_CTRL,
  197. DA7219_HP_R_AMP_MUTE_EN_MASK |
  198. DA7219_HP_R_AMP_MIN_GAIN_EN_MASK, 0);
  199. /*
  200. * If we're running from the internal oscillator then give audio paths
  201. * time to settle before running test.
  202. */
  203. if (!(pll_srm_sts & DA7219_PLL_SRM_STS_MCLK))
  204. msleep(DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY);
  205. /* Configure & start Tone Generator */
  206. snd_soc_component_write(component, DA7219_TONE_GEN_ON_PER, DA7219_BEEP_ON_PER_MASK);
  207. regmap_raw_write(da7219->regmap, DA7219_TONE_GEN_FREQ1_L,
  208. &tonegen_freq_hptest, sizeof(tonegen_freq_hptest));
  209. snd_soc_component_update_bits(component, DA7219_TONE_GEN_CFG2,
  210. DA7219_SWG_SEL_MASK | DA7219_TONE_GEN_GAIN_MASK,
  211. DA7219_SWG_SEL_SRAMP |
  212. DA7219_TONE_GEN_GAIN_MINUS_15DB);
  213. snd_soc_component_write(component, DA7219_TONE_GEN_CFG1, DA7219_START_STOPN_MASK);
  214. msleep(DA7219_AAD_HPTEST_PERIOD);
  215. /* Grab comparator reading */
  216. accdet_cfg8 = snd_soc_component_read(component, DA7219_ACCDET_CONFIG_8);
  217. if (accdet_cfg8 & DA7219_HPTEST_COMP_MASK)
  218. report |= SND_JACK_HEADPHONE;
  219. else
  220. report |= SND_JACK_LINEOUT;
  221. /* Stop tone generator */
  222. snd_soc_component_write(component, DA7219_TONE_GEN_CFG1, 0);
  223. msleep(DA7219_AAD_HPTEST_PERIOD);
  224. /* Restore original settings from cache */
  225. regcache_mark_dirty(da7219->regmap);
  226. regcache_sync_region(da7219->regmap, DA7219_HP_L_CTRL,
  227. DA7219_HP_R_CTRL);
  228. msleep(DA7219_SETTLING_DELAY);
  229. regcache_sync_region(da7219->regmap, DA7219_MIXOUT_L_CTRL,
  230. DA7219_MIXOUT_R_CTRL);
  231. regcache_sync_region(da7219->regmap, DA7219_DROUTING_ST_OUTFILT_1L,
  232. DA7219_DROUTING_ST_OUTFILT_1R);
  233. regcache_sync_region(da7219->regmap, DA7219_MIXOUT_L_SELECT,
  234. DA7219_MIXOUT_R_SELECT);
  235. regcache_sync_region(da7219->regmap, DA7219_DAC_L_CTRL,
  236. DA7219_DAC_R_CTRL);
  237. regcache_sync_region(da7219->regmap, DA7219_DIG_ROUTING_DAC,
  238. DA7219_DIG_ROUTING_DAC);
  239. regcache_sync_region(da7219->regmap, DA7219_CP_CTRL, DA7219_CP_CTRL);
  240. regcache_sync_region(da7219->regmap, DA7219_DAC_FILTERS5,
  241. DA7219_DAC_FILTERS5);
  242. regcache_sync_region(da7219->regmap, DA7219_DAC_FILTERS4,
  243. DA7219_DAC_FILTERS1);
  244. regcache_sync_region(da7219->regmap, DA7219_HP_L_GAIN,
  245. DA7219_HP_R_GAIN);
  246. regcache_sync_region(da7219->regmap, DA7219_DAC_L_GAIN,
  247. DA7219_DAC_R_GAIN);
  248. regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_ON_PER,
  249. DA7219_TONE_GEN_ON_PER);
  250. regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_FREQ1_L,
  251. DA7219_TONE_GEN_FREQ1_U);
  252. regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_CFG1,
  253. DA7219_TONE_GEN_CFG2);
  254. regcache_cache_bypass(da7219->regmap, false);
  255. /* Disable HPTest block */
  256. snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_8,
  257. DA7219_HPTEST_EN_MASK, 0);
  258. /*
  259. * If we're running from the internal oscillator then give audio paths
  260. * time to settle before allowing headphones to be driven as required.
  261. */
  262. if (!(pll_srm_sts & DA7219_PLL_SRM_STS_MCLK))
  263. msleep(DA7219_AAD_HPTEST_INT_OSC_PATH_DELAY);
  264. /* Restore gain ramping rate */
  265. snd_soc_component_write(component, DA7219_GAIN_RAMP_CTRL, gain_ramp_ctrl);
  266. /* Drive Headphones/lineout */
  267. snd_soc_component_update_bits(component, DA7219_HP_L_CTRL, DA7219_HP_L_AMP_OE_MASK,
  268. DA7219_HP_L_AMP_OE_MASK);
  269. snd_soc_component_update_bits(component, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK,
  270. DA7219_HP_R_AMP_OE_MASK);
  271. /* Restore PLL to previous configuration, if re-configured */
  272. if ((pll_srm_sts & DA7219_PLL_SRM_STS_MCLK) &&
  273. ((pll_ctrl & DA7219_PLL_MODE_MASK) == DA7219_PLL_MODE_BYPASS))
  274. da7219_set_pll(component, DA7219_SYSCLK_MCLK, 0);
  275. /* Remove MCLK, if previously enabled */
  276. if (da7219->mclk)
  277. clk_disable_unprepare(da7219->mclk);
  278. mutex_unlock(&da7219->pll_lock);
  279. mutex_unlock(&da7219->ctrl_lock);
  280. snd_soc_dapm_mutex_unlock(dapm);
  281. /*
  282. * Only send report if jack hasn't been removed during process,
  283. * otherwise it's invalid and we drop it.
  284. */
  285. if (da7219_aad->jack_inserted)
  286. snd_soc_jack_report(da7219_aad->jack, report,
  287. SND_JACK_HEADSET | SND_JACK_LINEOUT);
  288. }
  289. /*
  290. * IRQ
  291. */
  292. static irqreturn_t da7219_aad_irq_thread(int irq, void *data)
  293. {
  294. struct da7219_aad_priv *da7219_aad = data;
  295. struct snd_soc_component *component = da7219_aad->component;
  296. struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
  297. struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
  298. u8 events[DA7219_AAD_IRQ_REG_MAX];
  299. u8 statusa;
  300. int i, report = 0, mask = 0;
  301. /* Read current IRQ events */
  302. regmap_bulk_read(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A,
  303. events, DA7219_AAD_IRQ_REG_MAX);
  304. if (!events[DA7219_AAD_IRQ_REG_A] && !events[DA7219_AAD_IRQ_REG_B])
  305. return IRQ_NONE;
  306. /* Read status register for jack insertion & type status */
  307. statusa = snd_soc_component_read(component, DA7219_ACCDET_STATUS_A);
  308. /* Clear events */
  309. regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A,
  310. events, DA7219_AAD_IRQ_REG_MAX);
  311. dev_dbg(component->dev, "IRQ events = 0x%x|0x%x, status = 0x%x\n",
  312. events[DA7219_AAD_IRQ_REG_A], events[DA7219_AAD_IRQ_REG_B],
  313. statusa);
  314. if (statusa & DA7219_JACK_INSERTION_STS_MASK) {
  315. /* Jack Insertion */
  316. if (events[DA7219_AAD_IRQ_REG_A] &
  317. DA7219_E_JACK_INSERTED_MASK) {
  318. report |= SND_JACK_MECHANICAL;
  319. mask |= SND_JACK_MECHANICAL;
  320. da7219_aad->jack_inserted = true;
  321. }
  322. /* Jack type detection */
  323. if (events[DA7219_AAD_IRQ_REG_A] &
  324. DA7219_E_JACK_DETECT_COMPLETE_MASK) {
  325. /*
  326. * If 4-pole, then enable button detection, else perform
  327. * HP impedance test to determine output type to report.
  328. *
  329. * We schedule work here as the tasks themselves can
  330. * take time to complete, and in particular for hptest
  331. * we want to be able to check if the jack was removed
  332. * during the procedure as this will invalidate the
  333. * result. By doing this as work, the IRQ thread can
  334. * handle a removal, and we can check at the end of
  335. * hptest if we have a valid result or not.
  336. */
  337. if (statusa & DA7219_JACK_TYPE_STS_MASK) {
  338. report |= SND_JACK_HEADSET;
  339. mask |= SND_JACK_HEADSET | SND_JACK_LINEOUT;
  340. schedule_work(&da7219_aad->btn_det_work);
  341. } else {
  342. schedule_work(&da7219_aad->hptest_work);
  343. }
  344. }
  345. /* Button support for 4-pole jack */
  346. if (statusa & DA7219_JACK_TYPE_STS_MASK) {
  347. for (i = 0; i < DA7219_AAD_MAX_BUTTONS; ++i) {
  348. /* Button Press */
  349. if (events[DA7219_AAD_IRQ_REG_B] &
  350. (DA7219_E_BUTTON_A_PRESSED_MASK << i)) {
  351. report |= SND_JACK_BTN_0 >> i;
  352. mask |= SND_JACK_BTN_0 >> i;
  353. }
  354. }
  355. snd_soc_jack_report(da7219_aad->jack, report, mask);
  356. for (i = 0; i < DA7219_AAD_MAX_BUTTONS; ++i) {
  357. /* Button Release */
  358. if (events[DA7219_AAD_IRQ_REG_B] &
  359. (DA7219_E_BUTTON_A_RELEASED_MASK >> i)) {
  360. report &= ~(SND_JACK_BTN_0 >> i);
  361. mask |= SND_JACK_BTN_0 >> i;
  362. }
  363. }
  364. }
  365. } else {
  366. /* Jack removal */
  367. if (events[DA7219_AAD_IRQ_REG_A] & DA7219_E_JACK_REMOVED_MASK) {
  368. report = 0;
  369. mask |= DA7219_AAD_REPORT_ALL_MASK;
  370. da7219_aad->jack_inserted = false;
  371. /* Un-drive headphones/lineout */
  372. snd_soc_component_update_bits(component, DA7219_HP_R_CTRL,
  373. DA7219_HP_R_AMP_OE_MASK, 0);
  374. snd_soc_component_update_bits(component, DA7219_HP_L_CTRL,
  375. DA7219_HP_L_AMP_OE_MASK, 0);
  376. /* Ensure button detection disabled */
  377. snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1,
  378. DA7219_BUTTON_CONFIG_MASK, 0);
  379. da7219->micbias_on_event = false;
  380. /* Disable mic bias */
  381. snd_soc_dapm_disable_pin(dapm, "Mic Bias");
  382. snd_soc_dapm_sync(dapm);
  383. /* Cancel any pending work */
  384. cancel_work_sync(&da7219_aad->btn_det_work);
  385. cancel_work_sync(&da7219_aad->hptest_work);
  386. }
  387. }
  388. snd_soc_jack_report(da7219_aad->jack, report, mask);
  389. return IRQ_HANDLED;
  390. }
  391. /*
  392. * DT/ACPI to pdata conversion
  393. */
  394. static enum da7219_aad_micbias_pulse_lvl
  395. da7219_aad_fw_micbias_pulse_lvl(struct device *dev, u32 val)
  396. {
  397. switch (val) {
  398. case 2800:
  399. return DA7219_AAD_MICBIAS_PULSE_LVL_2_8V;
  400. case 2900:
  401. return DA7219_AAD_MICBIAS_PULSE_LVL_2_9V;
  402. default:
  403. dev_warn(dev, "Invalid micbias pulse level");
  404. return DA7219_AAD_MICBIAS_PULSE_LVL_OFF;
  405. }
  406. }
  407. static enum da7219_aad_btn_cfg
  408. da7219_aad_fw_btn_cfg(struct device *dev, u32 val)
  409. {
  410. switch (val) {
  411. case 2:
  412. return DA7219_AAD_BTN_CFG_2MS;
  413. case 5:
  414. return DA7219_AAD_BTN_CFG_5MS;
  415. case 10:
  416. return DA7219_AAD_BTN_CFG_10MS;
  417. case 50:
  418. return DA7219_AAD_BTN_CFG_50MS;
  419. case 100:
  420. return DA7219_AAD_BTN_CFG_100MS;
  421. case 200:
  422. return DA7219_AAD_BTN_CFG_200MS;
  423. case 500:
  424. return DA7219_AAD_BTN_CFG_500MS;
  425. default:
  426. dev_warn(dev, "Invalid button config");
  427. return DA7219_AAD_BTN_CFG_10MS;
  428. }
  429. }
  430. static enum da7219_aad_mic_det_thr
  431. da7219_aad_fw_mic_det_thr(struct device *dev, u32 val)
  432. {
  433. switch (val) {
  434. case 200:
  435. return DA7219_AAD_MIC_DET_THR_200_OHMS;
  436. case 500:
  437. return DA7219_AAD_MIC_DET_THR_500_OHMS;
  438. case 750:
  439. return DA7219_AAD_MIC_DET_THR_750_OHMS;
  440. case 1000:
  441. return DA7219_AAD_MIC_DET_THR_1000_OHMS;
  442. default:
  443. dev_warn(dev, "Invalid mic detect threshold");
  444. return DA7219_AAD_MIC_DET_THR_500_OHMS;
  445. }
  446. }
  447. static enum da7219_aad_jack_ins_deb
  448. da7219_aad_fw_jack_ins_deb(struct device *dev, u32 val)
  449. {
  450. switch (val) {
  451. case 5:
  452. return DA7219_AAD_JACK_INS_DEB_5MS;
  453. case 10:
  454. return DA7219_AAD_JACK_INS_DEB_10MS;
  455. case 20:
  456. return DA7219_AAD_JACK_INS_DEB_20MS;
  457. case 50:
  458. return DA7219_AAD_JACK_INS_DEB_50MS;
  459. case 100:
  460. return DA7219_AAD_JACK_INS_DEB_100MS;
  461. case 200:
  462. return DA7219_AAD_JACK_INS_DEB_200MS;
  463. case 500:
  464. return DA7219_AAD_JACK_INS_DEB_500MS;
  465. case 1000:
  466. return DA7219_AAD_JACK_INS_DEB_1S;
  467. default:
  468. dev_warn(dev, "Invalid jack insert debounce");
  469. return DA7219_AAD_JACK_INS_DEB_20MS;
  470. }
  471. }
  472. static enum da7219_aad_jack_det_rate
  473. da7219_aad_fw_jack_det_rate(struct device *dev, const char *str)
  474. {
  475. if (!strcmp(str, "32ms_64ms")) {
  476. return DA7219_AAD_JACK_DET_RATE_32_64MS;
  477. } else if (!strcmp(str, "64ms_128ms")) {
  478. return DA7219_AAD_JACK_DET_RATE_64_128MS;
  479. } else if (!strcmp(str, "128ms_256ms")) {
  480. return DA7219_AAD_JACK_DET_RATE_128_256MS;
  481. } else if (!strcmp(str, "256ms_512ms")) {
  482. return DA7219_AAD_JACK_DET_RATE_256_512MS;
  483. } else {
  484. dev_warn(dev, "Invalid jack detect rate");
  485. return DA7219_AAD_JACK_DET_RATE_256_512MS;
  486. }
  487. }
  488. static enum da7219_aad_jack_rem_deb
  489. da7219_aad_fw_jack_rem_deb(struct device *dev, u32 val)
  490. {
  491. switch (val) {
  492. case 1:
  493. return DA7219_AAD_JACK_REM_DEB_1MS;
  494. case 5:
  495. return DA7219_AAD_JACK_REM_DEB_5MS;
  496. case 10:
  497. return DA7219_AAD_JACK_REM_DEB_10MS;
  498. case 20:
  499. return DA7219_AAD_JACK_REM_DEB_20MS;
  500. default:
  501. dev_warn(dev, "Invalid jack removal debounce");
  502. return DA7219_AAD_JACK_REM_DEB_1MS;
  503. }
  504. }
  505. static enum da7219_aad_btn_avg
  506. da7219_aad_fw_btn_avg(struct device *dev, u32 val)
  507. {
  508. switch (val) {
  509. case 1:
  510. return DA7219_AAD_BTN_AVG_1;
  511. case 2:
  512. return DA7219_AAD_BTN_AVG_2;
  513. case 4:
  514. return DA7219_AAD_BTN_AVG_4;
  515. case 8:
  516. return DA7219_AAD_BTN_AVG_8;
  517. default:
  518. dev_warn(dev, "Invalid button average value");
  519. return DA7219_AAD_BTN_AVG_2;
  520. }
  521. }
  522. static enum da7219_aad_adc_1bit_rpt
  523. da7219_aad_fw_adc_1bit_rpt(struct device *dev, u32 val)
  524. {
  525. switch (val) {
  526. case 1:
  527. return DA7219_AAD_ADC_1BIT_RPT_1;
  528. case 2:
  529. return DA7219_AAD_ADC_1BIT_RPT_2;
  530. case 4:
  531. return DA7219_AAD_ADC_1BIT_RPT_4;
  532. case 8:
  533. return DA7219_AAD_ADC_1BIT_RPT_8;
  534. default:
  535. dev_warn(dev, "Invalid ADC 1-bit repeat value");
  536. return DA7219_AAD_ADC_1BIT_RPT_1;
  537. }
  538. }
  539. static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct device *dev)
  540. {
  541. struct i2c_client *i2c = to_i2c_client(dev);
  542. struct fwnode_handle *aad_np;
  543. struct da7219_aad_pdata *aad_pdata;
  544. const char *fw_str;
  545. u32 fw_val32;
  546. aad_np = device_get_named_child_node(dev, "da7219_aad");
  547. if (!aad_np)
  548. return NULL;
  549. aad_pdata = devm_kzalloc(dev, sizeof(*aad_pdata), GFP_KERNEL);
  550. if (!aad_pdata)
  551. return NULL;
  552. aad_pdata->irq = i2c->irq;
  553. if (fwnode_property_read_u32(aad_np, "dlg,micbias-pulse-lvl",
  554. &fw_val32) >= 0)
  555. aad_pdata->micbias_pulse_lvl =
  556. da7219_aad_fw_micbias_pulse_lvl(dev, fw_val32);
  557. else
  558. aad_pdata->micbias_pulse_lvl = DA7219_AAD_MICBIAS_PULSE_LVL_OFF;
  559. if (fwnode_property_read_u32(aad_np, "dlg,micbias-pulse-time",
  560. &fw_val32) >= 0)
  561. aad_pdata->micbias_pulse_time = fw_val32;
  562. if (fwnode_property_read_u32(aad_np, "dlg,btn-cfg", &fw_val32) >= 0)
  563. aad_pdata->btn_cfg = da7219_aad_fw_btn_cfg(dev, fw_val32);
  564. else
  565. aad_pdata->btn_cfg = DA7219_AAD_BTN_CFG_10MS;
  566. if (fwnode_property_read_u32(aad_np, "dlg,mic-det-thr", &fw_val32) >= 0)
  567. aad_pdata->mic_det_thr =
  568. da7219_aad_fw_mic_det_thr(dev, fw_val32);
  569. else
  570. aad_pdata->mic_det_thr = DA7219_AAD_MIC_DET_THR_500_OHMS;
  571. if (fwnode_property_read_u32(aad_np, "dlg,jack-ins-deb", &fw_val32) >= 0)
  572. aad_pdata->jack_ins_deb =
  573. da7219_aad_fw_jack_ins_deb(dev, fw_val32);
  574. else
  575. aad_pdata->jack_ins_deb = DA7219_AAD_JACK_INS_DEB_20MS;
  576. if (!fwnode_property_read_string(aad_np, "dlg,jack-det-rate", &fw_str))
  577. aad_pdata->jack_det_rate =
  578. da7219_aad_fw_jack_det_rate(dev, fw_str);
  579. else
  580. aad_pdata->jack_det_rate = DA7219_AAD_JACK_DET_RATE_256_512MS;
  581. if (fwnode_property_read_u32(aad_np, "dlg,jack-rem-deb", &fw_val32) >= 0)
  582. aad_pdata->jack_rem_deb =
  583. da7219_aad_fw_jack_rem_deb(dev, fw_val32);
  584. else
  585. aad_pdata->jack_rem_deb = DA7219_AAD_JACK_REM_DEB_1MS;
  586. if (fwnode_property_read_u32(aad_np, "dlg,a-d-btn-thr", &fw_val32) >= 0)
  587. aad_pdata->a_d_btn_thr = (u8) fw_val32;
  588. else
  589. aad_pdata->a_d_btn_thr = 0xA;
  590. if (fwnode_property_read_u32(aad_np, "dlg,d-b-btn-thr", &fw_val32) >= 0)
  591. aad_pdata->d_b_btn_thr = (u8) fw_val32;
  592. else
  593. aad_pdata->d_b_btn_thr = 0x16;
  594. if (fwnode_property_read_u32(aad_np, "dlg,b-c-btn-thr", &fw_val32) >= 0)
  595. aad_pdata->b_c_btn_thr = (u8) fw_val32;
  596. else
  597. aad_pdata->b_c_btn_thr = 0x21;
  598. if (fwnode_property_read_u32(aad_np, "dlg,c-mic-btn-thr", &fw_val32) >= 0)
  599. aad_pdata->c_mic_btn_thr = (u8) fw_val32;
  600. else
  601. aad_pdata->c_mic_btn_thr = 0x3E;
  602. if (fwnode_property_read_u32(aad_np, "dlg,btn-avg", &fw_val32) >= 0)
  603. aad_pdata->btn_avg = da7219_aad_fw_btn_avg(dev, fw_val32);
  604. else
  605. aad_pdata->btn_avg = DA7219_AAD_BTN_AVG_2;
  606. if (fwnode_property_read_u32(aad_np, "dlg,adc-1bit-rpt", &fw_val32) >= 0)
  607. aad_pdata->adc_1bit_rpt =
  608. da7219_aad_fw_adc_1bit_rpt(dev, fw_val32);
  609. else
  610. aad_pdata->adc_1bit_rpt = DA7219_AAD_ADC_1BIT_RPT_1;
  611. return aad_pdata;
  612. }
  613. static void da7219_aad_handle_pdata(struct snd_soc_component *component)
  614. {
  615. struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
  616. struct da7219_aad_priv *da7219_aad = da7219->aad;
  617. struct da7219_pdata *pdata = da7219->pdata;
  618. if ((pdata) && (pdata->aad_pdata)) {
  619. struct da7219_aad_pdata *aad_pdata = pdata->aad_pdata;
  620. u8 cfg, mask;
  621. da7219_aad->irq = aad_pdata->irq;
  622. switch (aad_pdata->micbias_pulse_lvl) {
  623. case DA7219_AAD_MICBIAS_PULSE_LVL_2_8V:
  624. case DA7219_AAD_MICBIAS_PULSE_LVL_2_9V:
  625. da7219_aad->micbias_pulse_lvl =
  626. (aad_pdata->micbias_pulse_lvl <<
  627. DA7219_MICBIAS1_LEVEL_SHIFT);
  628. break;
  629. default:
  630. break;
  631. }
  632. da7219_aad->micbias_pulse_time = aad_pdata->micbias_pulse_time;
  633. switch (aad_pdata->btn_cfg) {
  634. case DA7219_AAD_BTN_CFG_2MS:
  635. case DA7219_AAD_BTN_CFG_5MS:
  636. case DA7219_AAD_BTN_CFG_10MS:
  637. case DA7219_AAD_BTN_CFG_50MS:
  638. case DA7219_AAD_BTN_CFG_100MS:
  639. case DA7219_AAD_BTN_CFG_200MS:
  640. case DA7219_AAD_BTN_CFG_500MS:
  641. da7219_aad->btn_cfg = (aad_pdata->btn_cfg <<
  642. DA7219_BUTTON_CONFIG_SHIFT);
  643. }
  644. cfg = 0;
  645. mask = 0;
  646. switch (aad_pdata->mic_det_thr) {
  647. case DA7219_AAD_MIC_DET_THR_200_OHMS:
  648. case DA7219_AAD_MIC_DET_THR_500_OHMS:
  649. case DA7219_AAD_MIC_DET_THR_750_OHMS:
  650. case DA7219_AAD_MIC_DET_THR_1000_OHMS:
  651. cfg |= (aad_pdata->mic_det_thr <<
  652. DA7219_MIC_DET_THRESH_SHIFT);
  653. mask |= DA7219_MIC_DET_THRESH_MASK;
  654. }
  655. snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1, mask, cfg);
  656. cfg = 0;
  657. mask = 0;
  658. switch (aad_pdata->jack_ins_deb) {
  659. case DA7219_AAD_JACK_INS_DEB_5MS:
  660. case DA7219_AAD_JACK_INS_DEB_10MS:
  661. case DA7219_AAD_JACK_INS_DEB_20MS:
  662. case DA7219_AAD_JACK_INS_DEB_50MS:
  663. case DA7219_AAD_JACK_INS_DEB_100MS:
  664. case DA7219_AAD_JACK_INS_DEB_200MS:
  665. case DA7219_AAD_JACK_INS_DEB_500MS:
  666. case DA7219_AAD_JACK_INS_DEB_1S:
  667. cfg |= (aad_pdata->jack_ins_deb <<
  668. DA7219_JACKDET_DEBOUNCE_SHIFT);
  669. mask |= DA7219_JACKDET_DEBOUNCE_MASK;
  670. }
  671. switch (aad_pdata->jack_det_rate) {
  672. case DA7219_AAD_JACK_DET_RATE_32_64MS:
  673. case DA7219_AAD_JACK_DET_RATE_64_128MS:
  674. case DA7219_AAD_JACK_DET_RATE_128_256MS:
  675. case DA7219_AAD_JACK_DET_RATE_256_512MS:
  676. cfg |= (aad_pdata->jack_det_rate <<
  677. DA7219_JACK_DETECT_RATE_SHIFT);
  678. mask |= DA7219_JACK_DETECT_RATE_MASK;
  679. }
  680. switch (aad_pdata->jack_rem_deb) {
  681. case DA7219_AAD_JACK_REM_DEB_1MS:
  682. case DA7219_AAD_JACK_REM_DEB_5MS:
  683. case DA7219_AAD_JACK_REM_DEB_10MS:
  684. case DA7219_AAD_JACK_REM_DEB_20MS:
  685. cfg |= (aad_pdata->jack_rem_deb <<
  686. DA7219_JACKDET_REM_DEB_SHIFT);
  687. mask |= DA7219_JACKDET_REM_DEB_MASK;
  688. }
  689. snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_2, mask, cfg);
  690. snd_soc_component_write(component, DA7219_ACCDET_CONFIG_3,
  691. aad_pdata->a_d_btn_thr);
  692. snd_soc_component_write(component, DA7219_ACCDET_CONFIG_4,
  693. aad_pdata->d_b_btn_thr);
  694. snd_soc_component_write(component, DA7219_ACCDET_CONFIG_5,
  695. aad_pdata->b_c_btn_thr);
  696. snd_soc_component_write(component, DA7219_ACCDET_CONFIG_6,
  697. aad_pdata->c_mic_btn_thr);
  698. cfg = 0;
  699. mask = 0;
  700. switch (aad_pdata->btn_avg) {
  701. case DA7219_AAD_BTN_AVG_1:
  702. case DA7219_AAD_BTN_AVG_2:
  703. case DA7219_AAD_BTN_AVG_4:
  704. case DA7219_AAD_BTN_AVG_8:
  705. cfg |= (aad_pdata->btn_avg <<
  706. DA7219_BUTTON_AVERAGE_SHIFT);
  707. mask |= DA7219_BUTTON_AVERAGE_MASK;
  708. }
  709. switch (aad_pdata->adc_1bit_rpt) {
  710. case DA7219_AAD_ADC_1BIT_RPT_1:
  711. case DA7219_AAD_ADC_1BIT_RPT_2:
  712. case DA7219_AAD_ADC_1BIT_RPT_4:
  713. case DA7219_AAD_ADC_1BIT_RPT_8:
  714. cfg |= (aad_pdata->adc_1bit_rpt <<
  715. DA7219_ADC_1_BIT_REPEAT_SHIFT);
  716. mask |= DA7219_ADC_1_BIT_REPEAT_MASK;
  717. }
  718. snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_7, mask, cfg);
  719. }
  720. }
  721. /*
  722. * Suspend/Resume
  723. */
  724. void da7219_aad_suspend(struct snd_soc_component *component)
  725. {
  726. struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
  727. struct da7219_aad_priv *da7219_aad = da7219->aad;
  728. struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
  729. u8 micbias_ctrl;
  730. if (da7219_aad->jack) {
  731. /* Disable jack detection during suspend */
  732. snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1,
  733. DA7219_ACCDET_EN_MASK, 0);
  734. /*
  735. * If we have a 4-pole jack inserted, then micbias will be
  736. * enabled. We can disable micbias here, and keep a note to
  737. * re-enable it on resume. If jack removal occurred during
  738. * suspend then this will be dealt with through the IRQ handler.
  739. */
  740. if (da7219_aad->jack_inserted) {
  741. micbias_ctrl = snd_soc_component_read(component, DA7219_MICBIAS_CTRL);
  742. if (micbias_ctrl & DA7219_MICBIAS1_EN_MASK) {
  743. snd_soc_dapm_disable_pin(dapm, "Mic Bias");
  744. snd_soc_dapm_sync(dapm);
  745. da7219_aad->micbias_resume_enable = true;
  746. }
  747. }
  748. }
  749. }
  750. void da7219_aad_resume(struct snd_soc_component *component)
  751. {
  752. struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
  753. struct da7219_aad_priv *da7219_aad = da7219->aad;
  754. struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
  755. if (da7219_aad->jack) {
  756. /* Re-enable micbias if previously enabled for 4-pole jack */
  757. if (da7219_aad->jack_inserted &&
  758. da7219_aad->micbias_resume_enable) {
  759. snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
  760. snd_soc_dapm_sync(dapm);
  761. da7219_aad->micbias_resume_enable = false;
  762. }
  763. /* Re-enable jack detection */
  764. snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1,
  765. DA7219_ACCDET_EN_MASK,
  766. DA7219_ACCDET_EN_MASK);
  767. }
  768. }
  769. /*
  770. * Init/Exit
  771. */
  772. int da7219_aad_init(struct snd_soc_component *component)
  773. {
  774. struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
  775. struct da7219_aad_priv *da7219_aad = da7219->aad;
  776. u8 mask[DA7219_AAD_IRQ_REG_MAX];
  777. int ret;
  778. da7219_aad->component = component;
  779. /* Handle any DT/ACPI/platform data */
  780. da7219_aad_handle_pdata(component);
  781. /* Disable button detection */
  782. snd_soc_component_update_bits(component, DA7219_ACCDET_CONFIG_1,
  783. DA7219_BUTTON_CONFIG_MASK, 0);
  784. INIT_WORK(&da7219_aad->btn_det_work, da7219_aad_btn_det_work);
  785. INIT_WORK(&da7219_aad->hptest_work, da7219_aad_hptest_work);
  786. ret = request_threaded_irq(da7219_aad->irq, NULL,
  787. da7219_aad_irq_thread,
  788. IRQF_TRIGGER_LOW | IRQF_ONESHOT,
  789. "da7219-aad", da7219_aad);
  790. if (ret) {
  791. dev_err(component->dev, "Failed to request IRQ: %d\n", ret);
  792. return ret;
  793. }
  794. /* Unmask AAD IRQs */
  795. memset(mask, 0, DA7219_AAD_IRQ_REG_MAX);
  796. regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_MASK_A,
  797. &mask, DA7219_AAD_IRQ_REG_MAX);
  798. return 0;
  799. }
  800. EXPORT_SYMBOL_GPL(da7219_aad_init);
  801. void da7219_aad_exit(struct snd_soc_component *component)
  802. {
  803. struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
  804. struct da7219_aad_priv *da7219_aad = da7219->aad;
  805. u8 mask[DA7219_AAD_IRQ_REG_MAX];
  806. /* Mask off AAD IRQs */
  807. memset(mask, DA7219_BYTE_MASK, DA7219_AAD_IRQ_REG_MAX);
  808. regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_MASK_A,
  809. mask, DA7219_AAD_IRQ_REG_MAX);
  810. free_irq(da7219_aad->irq, da7219_aad);
  811. cancel_work_sync(&da7219_aad->btn_det_work);
  812. cancel_work_sync(&da7219_aad->hptest_work);
  813. }
  814. EXPORT_SYMBOL_GPL(da7219_aad_exit);
  815. /*
  816. * AAD related I2C probe handling
  817. */
  818. int da7219_aad_probe(struct i2c_client *i2c)
  819. {
  820. struct da7219_priv *da7219 = i2c_get_clientdata(i2c);
  821. struct device *dev = &i2c->dev;
  822. struct da7219_aad_priv *da7219_aad;
  823. da7219_aad = devm_kzalloc(dev, sizeof(*da7219_aad), GFP_KERNEL);
  824. if (!da7219_aad)
  825. return -ENOMEM;
  826. da7219->aad = da7219_aad;
  827. /* Retrieve any DT/ACPI/platform data */
  828. if (da7219->pdata && !da7219->pdata->aad_pdata)
  829. da7219->pdata->aad_pdata = da7219_aad_fw_to_pdata(dev);
  830. return 0;
  831. }
  832. EXPORT_SYMBOL_GPL(da7219_aad_probe);
  833. MODULE_DESCRIPTION("ASoC DA7219 AAD Driver");
  834. MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
  835. MODULE_LICENSE("GPL");