da7219-aad.c 28 KB

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