wcd-mbhc-adc.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
  3. */
  4. #include <linux/module.h>
  5. #include <linux/init.h>
  6. #include <linux/slab.h>
  7. #include <linux/of_gpio.h>
  8. #include <linux/platform_device.h>
  9. #include <linux/device.h>
  10. #include <linux/printk.h>
  11. #include <linux/ratelimit.h>
  12. #include <linux/list.h>
  13. #include <linux/bitops.h>
  14. #include <linux/delay.h>
  15. #include <linux/pm_runtime.h>
  16. #include <linux/kernel.h>
  17. #include <linux/input.h>
  18. #include <linux/firmware.h>
  19. #include <linux/completion.h>
  20. #include <sound/soc.h>
  21. #include <sound/jack.h>
  22. #include "wcd-mbhc-adc.h"
  23. #include <asoc/wcd-mbhc-v2.h>
  24. #include <asoc/pdata.h>
  25. #define WCD_MBHC_ADC_HS_THRESHOLD_MV 1700
  26. #define WCD_MBHC_ADC_HPH_THRESHOLD_MV 75
  27. #define WCD_MBHC_ADC_MICBIAS_MV 1800
  28. #define WCD_MBHC_FAKE_INS_RETRY 4
  29. static int wcd_mbhc_get_micbias(struct wcd_mbhc *mbhc)
  30. {
  31. int micbias = 0;
  32. u8 vout_ctl = 0;
  33. /* Read MBHC Micbias (Mic Bias2) voltage */
  34. WCD_MBHC_REG_READ(WCD_MBHC_MICB2_VOUT, vout_ctl);
  35. /* Formula for getting micbias from vout
  36. * micbias = 1.0V + VOUT_CTL * 50mV
  37. */
  38. micbias = 1000 + (vout_ctl * 50);
  39. pr_debug("%s: vout_ctl: %d, micbias: %d\n",
  40. __func__, vout_ctl, micbias);
  41. return micbias;
  42. }
  43. static int wcd_get_voltage_from_adc(u8 val, int micbias)
  44. {
  45. /* Formula for calculating voltage from ADC
  46. * Voltage = ADC_RESULT*12.5mV*V_MICBIAS/1.8
  47. */
  48. return ((val * 125 * micbias)/(WCD_MBHC_ADC_MICBIAS_MV * 10));
  49. }
  50. static int wcd_measure_adc_continuous(struct wcd_mbhc *mbhc)
  51. {
  52. u8 adc_result = 0;
  53. int output_mv = 0;
  54. int retry = 3;
  55. u8 adc_en = 0;
  56. pr_debug("%s: enter\n", __func__);
  57. /* Pre-requisites for ADC continuous measurement */
  58. /* Read legacy electircal detection and disable */
  59. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 0x00);
  60. /* Set ADC to continuous measurement */
  61. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_MODE, 1);
  62. /* Read ADC Enable bit to restore after adc measurement */
  63. WCD_MBHC_REG_READ(WCD_MBHC_ADC_EN, adc_en);
  64. /* Disable ADC_ENABLE bit */
  65. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 0);
  66. /* Disable MBHC FSM */
  67. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
  68. /* Set the MUX selection to IN2P */
  69. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MUX_CTL, MUX_CTL_IN2P);
  70. /* Enable MBHC FSM */
  71. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 1);
  72. /* Enable ADC_ENABLE bit */
  73. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 1);
  74. while (retry--) {
  75. /* wait for 3 msec before reading ADC result */
  76. usleep_range(3000, 3100);
  77. /* Read ADC result */
  78. WCD_MBHC_REG_READ(WCD_MBHC_ADC_RESULT, adc_result);
  79. }
  80. /* Restore ADC Enable */
  81. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, adc_en);
  82. /* Get voltage from ADC result */
  83. output_mv = wcd_get_voltage_from_adc(adc_result,
  84. wcd_mbhc_get_micbias(mbhc));
  85. pr_debug("%s: adc_result: 0x%x, output_mv: %d\n",
  86. __func__, adc_result, output_mv);
  87. return output_mv;
  88. }
  89. static int wcd_measure_adc_once(struct wcd_mbhc *mbhc, int mux_ctl)
  90. {
  91. u8 adc_timeout = 0;
  92. u8 adc_complete = 0;
  93. u8 adc_result = 0;
  94. int retry = 6;
  95. int ret = 0;
  96. int output_mv = 0;
  97. u8 adc_en = 0;
  98. pr_debug("%s: enter\n", __func__);
  99. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_MODE, 0);
  100. /* Read ADC Enable bit to restore after adc measurement */
  101. WCD_MBHC_REG_READ(WCD_MBHC_ADC_EN, adc_en);
  102. /* Trigger ADC one time measurement */
  103. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 0);
  104. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
  105. /* Set the appropriate MUX selection */
  106. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MUX_CTL, mux_ctl);
  107. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 1);
  108. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 1);
  109. while (retry--) {
  110. /* wait for 600usec to get adc results */
  111. usleep_range(600, 610);
  112. /* check for ADC Timeout */
  113. WCD_MBHC_REG_READ(WCD_MBHC_ADC_TIMEOUT, adc_timeout);
  114. if (adc_timeout)
  115. continue;
  116. /* Read ADC complete bit */
  117. WCD_MBHC_REG_READ(WCD_MBHC_ADC_COMPLETE, adc_complete);
  118. if (!adc_complete)
  119. continue;
  120. /* Read ADC result */
  121. WCD_MBHC_REG_READ(WCD_MBHC_ADC_RESULT, adc_result);
  122. pr_debug("%s: ADC result: 0x%x\n", __func__, adc_result);
  123. /* Get voltage from ADC result */
  124. output_mv = wcd_get_voltage_from_adc(adc_result,
  125. wcd_mbhc_get_micbias(mbhc));
  126. break;
  127. }
  128. /* Restore ADC Enable */
  129. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, adc_en);
  130. if (retry <= 0) {
  131. pr_err("%s: adc complete: %d, adc timeout: %d\n",
  132. __func__, adc_complete, adc_timeout);
  133. ret = -EINVAL;
  134. } else {
  135. pr_debug("%s: adc complete: %d, adc timeout: %d output_mV: %d\n",
  136. __func__, adc_complete, adc_timeout, output_mv);
  137. ret = output_mv;
  138. }
  139. pr_debug("%s: leave\n", __func__);
  140. return ret;
  141. }
  142. static bool wcd_mbhc_adc_detect_anc_plug_type(struct wcd_mbhc *mbhc)
  143. {
  144. bool anc_mic_found = false;
  145. u16 fsm_en = 0;
  146. u8 det = 0;
  147. unsigned long retry = 0;
  148. int valid_plug_cnt = 0, invalid_plug_cnt = 0;
  149. int ret = 0;
  150. u8 elect_ctl = 0;
  151. u8 adc_mode = 0;
  152. u8 vref = 0;
  153. int vref_mv[] = {1650, 1500, 1600, 1700};
  154. if (mbhc->mbhc_cfg->anc_micbias < MIC_BIAS_1 ||
  155. mbhc->mbhc_cfg->anc_micbias > MIC_BIAS_4)
  156. return false;
  157. if (!mbhc->mbhc_cb->mbhc_micbias_control)
  158. return false;
  159. /* Disable Detection done for ADC operation */
  160. WCD_MBHC_REG_READ(WCD_MBHC_DETECTION_DONE, det);
  161. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_DETECTION_DONE, 0);
  162. /* Mask ADC COMPLETE interrupt */
  163. wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_INS, false);
  164. WCD_MBHC_REG_READ(WCD_MBHC_FSM_EN, fsm_en);
  165. mbhc->mbhc_cb->mbhc_micbias_control(mbhc->component,
  166. mbhc->mbhc_cfg->anc_micbias,
  167. MICB_ENABLE);
  168. /* Read legacy electircal detection and disable */
  169. WCD_MBHC_REG_READ(WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl);
  170. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 0x00);
  171. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ANC_DET_EN, 1);
  172. WCD_MBHC_REG_READ(WCD_MBHC_ADC_MODE, adc_mode);
  173. /*
  174. * wait for button debounce time 20ms. If 4-pole plug is inserted
  175. * into 5-pole jack, then there will be a button press interrupt
  176. * during anc plug detection. In that case though Hs_comp_res is 0,
  177. * it should not be declared as ANC plug type
  178. */
  179. usleep_range(20000, 20100);
  180. /*
  181. * After enabling FSM, to handle slow insertion scenarios,
  182. * check IN3 voltage is below the Vref
  183. */
  184. WCD_MBHC_REG_READ(WCD_MBHC_HS_VREF, vref);
  185. do {
  186. if (wcd_swch_level_remove(mbhc)) {
  187. pr_debug("%s: Switch level is low\n", __func__);
  188. goto done;
  189. }
  190. pr_debug("%s: Retry attempt %lu\n", __func__, retry + 1);
  191. ret = wcd_measure_adc_once(mbhc, MUX_CTL_IN3P);
  192. /* TODO - check the logic */
  193. if (ret && (ret < vref_mv[vref]))
  194. valid_plug_cnt++;
  195. else
  196. invalid_plug_cnt++;
  197. retry++;
  198. } while (retry < ANC_DETECT_RETRY_CNT);
  199. pr_debug("%s: valid: %d, invalid: %d\n", __func__, valid_plug_cnt,
  200. invalid_plug_cnt);
  201. /* decision logic */
  202. if (valid_plug_cnt > invalid_plug_cnt)
  203. anc_mic_found = true;
  204. done:
  205. /* Restore ADC mode */
  206. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_MODE, adc_mode);
  207. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ANC_DET_EN, 0);
  208. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
  209. /* Set the MUX selection to AUTO */
  210. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MUX_CTL, MUX_CTL_AUTO);
  211. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 1);
  212. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, fsm_en);
  213. /* Restore detection done */
  214. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_DETECTION_DONE, det);
  215. /* Restore electrical detection */
  216. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl);
  217. mbhc->mbhc_cb->mbhc_micbias_control(mbhc->component,
  218. mbhc->mbhc_cfg->anc_micbias,
  219. MICB_DISABLE);
  220. pr_debug("%s: anc mic %sfound\n", __func__,
  221. anc_mic_found ? "" : "not ");
  222. return anc_mic_found;
  223. }
  224. /* To determine if cross connection occurred */
  225. static int wcd_check_cross_conn(struct wcd_mbhc *mbhc)
  226. {
  227. enum wcd_mbhc_plug_type plug_type = MBHC_PLUG_TYPE_NONE;
  228. int hphl_adc_res = 0, hphr_adc_res = 0;
  229. u8 fsm_en = 0;
  230. int ret = 0;
  231. u8 adc_mode = 0;
  232. u8 elect_ctl = 0;
  233. u8 adc_en = 0;
  234. pr_debug("%s: enter\n", __func__);
  235. /* Check for button press and plug detection */
  236. if (wcd_swch_level_remove(mbhc)) {
  237. pr_debug("%s: Switch level is low\n", __func__);
  238. return -EINVAL;
  239. }
  240. /* If PA is enabled, dont check for cross-connection */
  241. if (mbhc->mbhc_cb->hph_pa_on_status)
  242. if (mbhc->mbhc_cb->hph_pa_on_status(mbhc->component))
  243. return -EINVAL;
  244. /* Read legacy electircal detection and disable */
  245. WCD_MBHC_REG_READ(WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl);
  246. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 0x00);
  247. /* Read and set ADC to single measurement */
  248. WCD_MBHC_REG_READ(WCD_MBHC_ADC_MODE, adc_mode);
  249. /* Read ADC Enable bit to restore after adc measurement */
  250. WCD_MBHC_REG_READ(WCD_MBHC_ADC_EN, adc_en);
  251. /* Read FSM status */
  252. WCD_MBHC_REG_READ(WCD_MBHC_FSM_EN, fsm_en);
  253. /* Get adc result for HPH L */
  254. hphl_adc_res = wcd_measure_adc_once(mbhc, MUX_CTL_HPH_L);
  255. if (hphl_adc_res < 0) {
  256. pr_err("%s: hphl_adc_res adc measurement failed\n", __func__);
  257. ret = hphl_adc_res;
  258. goto done;
  259. }
  260. /* Get adc result for HPH R in mV */
  261. hphr_adc_res = wcd_measure_adc_once(mbhc, MUX_CTL_HPH_R);
  262. if (hphr_adc_res < 0) {
  263. pr_err("%s: hphr_adc_res adc measurement failed\n", __func__);
  264. ret = hphr_adc_res;
  265. goto done;
  266. }
  267. if (hphl_adc_res > 100 || hphr_adc_res > 100) {
  268. plug_type = MBHC_PLUG_TYPE_GND_MIC_SWAP;
  269. pr_debug("%s: Cross connection identified\n", __func__);
  270. } else {
  271. pr_debug("%s: No Cross connection found\n", __func__);
  272. }
  273. done:
  274. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
  275. /* Set the MUX selection to Auto */
  276. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MUX_CTL, MUX_CTL_AUTO);
  277. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 1);
  278. /* Restore ADC Enable */
  279. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, adc_en);
  280. /* Restore ADC mode */
  281. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_MODE, adc_mode);
  282. /* Restore FSM state */
  283. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, fsm_en);
  284. /* Restore electrical detection */
  285. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl);
  286. pr_debug("%s: leave, plug type: %d\n", __func__, plug_type);
  287. return (plug_type == MBHC_PLUG_TYPE_GND_MIC_SWAP) ? true : false;
  288. }
  289. static int wcd_mbhc_adc_get_spl_hs_thres(struct wcd_mbhc *mbhc)
  290. {
  291. int hs_threshold, micbias_mv;
  292. micbias_mv = wcd_mbhc_get_micbias(mbhc);
  293. if (mbhc->hs_thr && mbhc->micb_mv != WCD_MBHC_ADC_MICBIAS_MV) {
  294. if (mbhc->micb_mv == micbias_mv)
  295. hs_threshold = mbhc->hs_thr;
  296. else
  297. hs_threshold = (mbhc->hs_thr *
  298. micbias_mv) / mbhc->micb_mv;
  299. } else {
  300. hs_threshold = ((WCD_MBHC_ADC_HS_THRESHOLD_MV *
  301. micbias_mv) / WCD_MBHC_ADC_MICBIAS_MV);
  302. }
  303. return hs_threshold;
  304. }
  305. static int wcd_mbhc_adc_get_hs_thres(struct wcd_mbhc *mbhc)
  306. {
  307. int hs_threshold, micbias_mv;
  308. micbias_mv = wcd_mbhc_get_micbias(mbhc);
  309. if (mbhc->hs_thr) {
  310. if (mbhc->micb_mv == micbias_mv)
  311. hs_threshold = mbhc->hs_thr;
  312. else
  313. hs_threshold = (mbhc->hs_thr *
  314. micbias_mv) / mbhc->micb_mv;
  315. } else {
  316. hs_threshold = ((WCD_MBHC_ADC_HS_THRESHOLD_MV *
  317. micbias_mv) / WCD_MBHC_ADC_MICBIAS_MV);
  318. }
  319. return hs_threshold;
  320. }
  321. static int wcd_mbhc_adc_get_hph_thres(struct wcd_mbhc *mbhc)
  322. {
  323. int hph_threshold, micbias_mv;
  324. micbias_mv = wcd_mbhc_get_micbias(mbhc);
  325. if (mbhc->hph_thr) {
  326. if (mbhc->micb_mv == micbias_mv)
  327. hph_threshold = mbhc->hph_thr;
  328. else
  329. hph_threshold = (mbhc->hph_thr *
  330. micbias_mv) / mbhc->micb_mv;
  331. } else {
  332. hph_threshold = ((WCD_MBHC_ADC_HPH_THRESHOLD_MV *
  333. micbias_mv) / WCD_MBHC_ADC_MICBIAS_MV);
  334. }
  335. return hph_threshold;
  336. }
  337. static bool wcd_mbhc_adc_check_for_spl_headset(struct wcd_mbhc *mbhc,
  338. int *spl_hs_cnt)
  339. {
  340. bool spl_hs = false;
  341. int output_mv = 0;
  342. int adc_threshold = 0, adc_hph_threshold = 0;
  343. pr_debug("%s: enter\n", __func__);
  344. if (!mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic)
  345. goto exit;
  346. /* Bump up MB2 to 2.7V */
  347. mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(mbhc->component,
  348. mbhc->mbhc_cfg->mbhc_micbias, true);
  349. usleep_range(10000, 10100);
  350. /*
  351. * Use ADC single mode to minimize the chance of missing out
  352. * btn press/relesae for HEADSET type during correct work.
  353. */
  354. output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
  355. adc_threshold = wcd_mbhc_adc_get_spl_hs_thres(mbhc);
  356. adc_hph_threshold = wcd_mbhc_adc_get_hph_thres(mbhc);
  357. if (output_mv > adc_threshold || output_mv < adc_hph_threshold) {
  358. spl_hs = false;
  359. } else {
  360. spl_hs = true;
  361. if (spl_hs_cnt)
  362. *spl_hs_cnt += 1;
  363. }
  364. /* MB2 back to 1.8v if the type is not special headset */
  365. if (spl_hs_cnt && (*spl_hs_cnt != WCD_MBHC_SPL_HS_CNT)) {
  366. mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(mbhc->component,
  367. mbhc->mbhc_cfg->mbhc_micbias, false);
  368. /* Add 10ms delay for micbias to settle */
  369. usleep_range(10000, 10100);
  370. }
  371. if (spl_hs)
  372. pr_debug("%s: Detected special HS (%d)\n", __func__, spl_hs);
  373. exit:
  374. pr_debug("%s: leave\n", __func__);
  375. return spl_hs;
  376. }
  377. static bool wcd_is_special_headset(struct wcd_mbhc *mbhc)
  378. {
  379. int delay = 0;
  380. bool ret = false;
  381. bool is_spl_hs = false;
  382. int output_mv = 0;
  383. int adc_threshold = 0;
  384. /*
  385. * Increase micbias to 2.7V to detect headsets with
  386. * threshold on microphone
  387. */
  388. if (mbhc->mbhc_cb->mbhc_micbias_control &&
  389. !mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic) {
  390. pr_debug("%s: callback fn micb_ctrl_thr_mic not defined\n",
  391. __func__);
  392. return false;
  393. } else if (mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic) {
  394. ret = mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(mbhc->component,
  395. MIC_BIAS_2, true);
  396. if (ret) {
  397. pr_err("%s: mbhc_micb_ctrl_thr_mic failed, ret: %d\n",
  398. __func__, ret);
  399. return false;
  400. }
  401. }
  402. adc_threshold = wcd_mbhc_adc_get_spl_hs_thres(mbhc);
  403. while (!is_spl_hs) {
  404. if (mbhc->hs_detect_work_stop) {
  405. pr_debug("%s: stop requested: %d\n", __func__,
  406. mbhc->hs_detect_work_stop);
  407. break;
  408. }
  409. delay += 50;
  410. /* Wait for 50ms for FSM to update result */
  411. msleep(50);
  412. output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
  413. if (output_mv <= adc_threshold) {
  414. pr_debug("%s: Special headset detected in %d msecs\n",
  415. __func__, delay);
  416. is_spl_hs = true;
  417. }
  418. if (delay == SPECIAL_HS_DETECT_TIME_MS) {
  419. pr_debug("%s: Spl headset not found in 2 sec\n",
  420. __func__);
  421. break;
  422. }
  423. }
  424. if (is_spl_hs) {
  425. pr_debug("%s: Headset with threshold found\n", __func__);
  426. mbhc->micbias_enable = true;
  427. ret = true;
  428. }
  429. if (mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic &&
  430. !mbhc->micbias_enable)
  431. mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(mbhc->component,
  432. MIC_BIAS_2,
  433. false);
  434. pr_debug("%s: leave, micb_enable: %d\n", __func__,
  435. mbhc->micbias_enable);
  436. return ret;
  437. }
  438. static void wcd_mbhc_adc_update_fsm_source(struct wcd_mbhc *mbhc,
  439. enum wcd_mbhc_plug_type plug_type)
  440. {
  441. bool micbias2;
  442. micbias2 = mbhc->mbhc_cb->micbias_enable_status(mbhc,
  443. MIC_BIAS_2);
  444. switch (plug_type) {
  445. case MBHC_PLUG_TYPE_HEADPHONE:
  446. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 3);
  447. break;
  448. case MBHC_PLUG_TYPE_HEADSET:
  449. case MBHC_PLUG_TYPE_ANC_HEADPHONE:
  450. if (!mbhc->is_hs_recording && !micbias2)
  451. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 3);
  452. break;
  453. default:
  454. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 0);
  455. break;
  456. };
  457. }
  458. /* should be called under interrupt context that hold suspend */
  459. static void wcd_schedule_hs_detect_plug(struct wcd_mbhc *mbhc,
  460. struct work_struct *work)
  461. {
  462. pr_debug("%s: scheduling correct_swch_plug\n", __func__);
  463. WCD_MBHC_RSC_ASSERT_LOCKED(mbhc);
  464. mbhc->hs_detect_work_stop = false;
  465. mbhc->mbhc_cb->lock_sleep(mbhc, true);
  466. schedule_work(work);
  467. }
  468. /* called under codec_resource_lock acquisition */
  469. static void wcd_cancel_hs_detect_plug(struct wcd_mbhc *mbhc,
  470. struct work_struct *work)
  471. {
  472. pr_debug("%s: Canceling correct_plug_swch\n", __func__);
  473. mbhc->hs_detect_work_stop = true;
  474. WCD_MBHC_RSC_UNLOCK(mbhc);
  475. if (cancel_work_sync(work)) {
  476. pr_debug("%s: correct_plug_swch is canceled\n",
  477. __func__);
  478. mbhc->mbhc_cb->lock_sleep(mbhc, false);
  479. }
  480. WCD_MBHC_RSC_LOCK(mbhc);
  481. }
  482. /* called under codec_resource_lock acquisition */
  483. static void wcd_mbhc_adc_detect_plug_type(struct wcd_mbhc *mbhc)
  484. {
  485. struct snd_soc_component *component = mbhc->component;
  486. pr_debug("%s: enter\n", __func__);
  487. WCD_MBHC_RSC_ASSERT_LOCKED(mbhc);
  488. if (mbhc->mbhc_cb->hph_pull_down_ctrl)
  489. mbhc->mbhc_cb->hph_pull_down_ctrl(component, false);
  490. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_DETECTION_DONE, 0);
  491. if (mbhc->mbhc_cb->mbhc_micbias_control) {
  492. mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2,
  493. MICB_ENABLE);
  494. } else {
  495. pr_err("%s: Mic Bias is not enabled\n", __func__);
  496. return;
  497. }
  498. /* Re-initialize button press completion object */
  499. reinit_completion(&mbhc->btn_press_compl);
  500. wcd_schedule_hs_detect_plug(mbhc, &mbhc->correct_plug_swch);
  501. pr_debug("%s: leave\n", __func__);
  502. }
  503. static void wcd_micbias_disable(struct wcd_mbhc *mbhc)
  504. {
  505. if (mbhc->micbias_enable) {
  506. mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(
  507. mbhc->component, MIC_BIAS_2, false);
  508. if (mbhc->mbhc_cb->set_micbias_value)
  509. mbhc->mbhc_cb->set_micbias_value(
  510. mbhc->component);
  511. mbhc->micbias_enable = false;
  512. }
  513. }
  514. static int wcd_mbhc_get_plug_from_adc(struct wcd_mbhc *mbhc, int adc_result)
  515. {
  516. enum wcd_mbhc_plug_type plug_type = MBHC_PLUG_TYPE_INVALID;
  517. u32 hph_thr = 0, hs_thr = 0;
  518. hs_thr = wcd_mbhc_adc_get_hs_thres(mbhc);
  519. hph_thr = wcd_mbhc_adc_get_hph_thres(mbhc);
  520. if (adc_result < hph_thr)
  521. plug_type = MBHC_PLUG_TYPE_HEADPHONE;
  522. else if (adc_result > hs_thr)
  523. plug_type = MBHC_PLUG_TYPE_HIGH_HPH;
  524. else
  525. plug_type = MBHC_PLUG_TYPE_HEADSET;
  526. pr_debug("%s: plug type is %d found\n", __func__, plug_type);
  527. return plug_type;
  528. }
  529. static void wcd_correct_swch_plug(struct work_struct *work)
  530. {
  531. struct wcd_mbhc *mbhc;
  532. struct snd_soc_component *component;
  533. enum wcd_mbhc_plug_type plug_type = MBHC_PLUG_TYPE_INVALID;
  534. unsigned long timeout;
  535. bool wrk_complete = false;
  536. int pt_gnd_mic_swap_cnt = 0;
  537. int no_gnd_mic_swap_cnt = 0;
  538. bool is_pa_on = false, spl_hs = false, spl_hs_reported = false;
  539. int ret = 0;
  540. int spl_hs_count = 0;
  541. int output_mv = 0;
  542. int cross_conn;
  543. int try = 0;
  544. int hs_threshold, micbias_mv;
  545. pr_debug("%s: enter\n", __func__);
  546. mbhc = container_of(work, struct wcd_mbhc, correct_plug_swch);
  547. component = mbhc->component;
  548. micbias_mv = wcd_mbhc_get_micbias(mbhc);
  549. hs_threshold = wcd_mbhc_adc_get_hs_thres(mbhc);
  550. WCD_MBHC_RSC_LOCK(mbhc);
  551. /* Mask ADC COMPLETE interrupt */
  552. wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_INS, false);
  553. WCD_MBHC_RSC_UNLOCK(mbhc);
  554. /* Check for cross connection */
  555. do {
  556. cross_conn = wcd_check_cross_conn(mbhc);
  557. try++;
  558. } while (try < mbhc->swap_thr);
  559. if (cross_conn > 0) {
  560. plug_type = MBHC_PLUG_TYPE_GND_MIC_SWAP;
  561. pr_debug("%s: cross connection found, Plug type %d\n",
  562. __func__, plug_type);
  563. goto correct_plug_type;
  564. }
  565. /* Find plug type */
  566. output_mv = wcd_measure_adc_continuous(mbhc);
  567. plug_type = wcd_mbhc_get_plug_from_adc(mbhc, output_mv);
  568. /*
  569. * Report plug type if it is either headset or headphone
  570. * else start the 3 sec loop
  571. */
  572. if ((plug_type == MBHC_PLUG_TYPE_HEADSET ||
  573. plug_type == MBHC_PLUG_TYPE_HEADPHONE) &&
  574. (!wcd_swch_level_remove(mbhc))) {
  575. WCD_MBHC_RSC_LOCK(mbhc);
  576. wcd_mbhc_find_plug_and_report(mbhc, plug_type);
  577. WCD_MBHC_RSC_UNLOCK(mbhc);
  578. }
  579. /*
  580. * Set DETECTION_DONE bit for HEADSET and ANC_HEADPHONE,
  581. * so that btn press/release interrupt can be generated.
  582. */
  583. if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET ||
  584. mbhc->current_plug == MBHC_PLUG_TYPE_ANC_HEADPHONE) {
  585. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_MODE, 0);
  586. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 0);
  587. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_DETECTION_DONE, 1);
  588. }
  589. correct_plug_type:
  590. /*
  591. * Callback to disable BCS slow insertion detection
  592. */
  593. if (plug_type == MBHC_PLUG_TYPE_HEADSET ||
  594. plug_type == MBHC_PLUG_TYPE_HEADPHONE)
  595. mbhc->mbhc_cb->bcs_enable(mbhc, false);
  596. timeout = jiffies + msecs_to_jiffies(HS_DETECT_PLUG_TIME_MS);
  597. while (!time_after(jiffies, timeout)) {
  598. if (mbhc->hs_detect_work_stop) {
  599. pr_debug("%s: stop requested: %d\n", __func__,
  600. mbhc->hs_detect_work_stop);
  601. wcd_micbias_disable(mbhc);
  602. goto exit;
  603. }
  604. /* allow sometime and re-check stop requested again */
  605. msleep(20);
  606. if (mbhc->hs_detect_work_stop) {
  607. pr_debug("%s: stop requested: %d\n", __func__,
  608. mbhc->hs_detect_work_stop);
  609. wcd_micbias_disable(mbhc);
  610. goto exit;
  611. }
  612. msleep(180);
  613. /*
  614. * Use ADC single mode to minimize the chance of missing out
  615. * btn press/release for HEADSET type during correct work.
  616. */
  617. output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
  618. /*
  619. * instead of hogging system by contineous polling, wait for
  620. * sometime and re-check stop request again.
  621. */
  622. plug_type = wcd_mbhc_get_plug_from_adc(mbhc, output_mv);
  623. if ((output_mv > hs_threshold) &&
  624. (spl_hs_count < WCD_MBHC_SPL_HS_CNT)) {
  625. spl_hs = wcd_mbhc_adc_check_for_spl_headset(mbhc,
  626. &spl_hs_count);
  627. output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
  628. if (spl_hs_count == WCD_MBHC_SPL_HS_CNT) {
  629. hs_threshold = (hs_threshold *
  630. wcd_mbhc_get_micbias(mbhc)) / micbias_mv;
  631. spl_hs = true;
  632. mbhc->micbias_enable = true;
  633. }
  634. }
  635. if (mbhc->mbhc_cb->hph_pa_on_status)
  636. is_pa_on = mbhc->mbhc_cb->hph_pa_on_status(
  637. mbhc->component);
  638. if ((output_mv <= hs_threshold) &&
  639. (!is_pa_on)) {
  640. /* Check for cross connection*/
  641. ret = wcd_check_cross_conn(mbhc);
  642. if (ret < 0)
  643. continue;
  644. else if (ret > 0) {
  645. pt_gnd_mic_swap_cnt++;
  646. no_gnd_mic_swap_cnt = 0;
  647. if (pt_gnd_mic_swap_cnt <
  648. mbhc->swap_thr) {
  649. continue;
  650. } else if (pt_gnd_mic_swap_cnt >
  651. mbhc->swap_thr) {
  652. /*
  653. * This is due to GND/MIC switch didn't
  654. * work, Report unsupported plug.
  655. */
  656. pr_debug("%s: switch did not work\n",
  657. __func__);
  658. plug_type = MBHC_PLUG_TYPE_GND_MIC_SWAP;
  659. goto report;
  660. } else {
  661. plug_type = MBHC_PLUG_TYPE_GND_MIC_SWAP;
  662. }
  663. } else {
  664. no_gnd_mic_swap_cnt++;
  665. pt_gnd_mic_swap_cnt = 0;
  666. plug_type = wcd_mbhc_get_plug_from_adc(
  667. mbhc, output_mv);
  668. if ((no_gnd_mic_swap_cnt <
  669. mbhc->swap_thr) &&
  670. (spl_hs_count != WCD_MBHC_SPL_HS_CNT)) {
  671. continue;
  672. } else {
  673. no_gnd_mic_swap_cnt = 0;
  674. }
  675. }
  676. if ((pt_gnd_mic_swap_cnt == mbhc->swap_thr) &&
  677. (plug_type == MBHC_PLUG_TYPE_GND_MIC_SWAP)) {
  678. /*
  679. * if switch is toggled, check again,
  680. * otherwise report unsupported plug
  681. */
  682. if (mbhc->mbhc_cfg->swap_gnd_mic &&
  683. mbhc->mbhc_cfg->swap_gnd_mic(component,
  684. true)) {
  685. pr_debug("%s: US_EU gpio present,flip switch\n"
  686. , __func__);
  687. continue;
  688. }
  689. }
  690. }
  691. if (output_mv > hs_threshold) {
  692. pr_debug("%s: cable is extension cable\n", __func__);
  693. plug_type = MBHC_PLUG_TYPE_HIGH_HPH;
  694. wrk_complete = true;
  695. } else {
  696. pr_debug("%s: cable might be headset: %d\n", __func__,
  697. plug_type);
  698. if (plug_type != MBHC_PLUG_TYPE_GND_MIC_SWAP) {
  699. plug_type = wcd_mbhc_get_plug_from_adc(
  700. mbhc, output_mv);
  701. if (!spl_hs_reported &&
  702. spl_hs_count == WCD_MBHC_SPL_HS_CNT) {
  703. spl_hs_reported = true;
  704. WCD_MBHC_RSC_LOCK(mbhc);
  705. wcd_mbhc_find_plug_and_report(mbhc,
  706. plug_type);
  707. WCD_MBHC_RSC_UNLOCK(mbhc);
  708. continue;
  709. } else if (spl_hs_reported)
  710. continue;
  711. /*
  712. * Report headset only if not already reported
  713. * and if there is not button press without
  714. * release
  715. */
  716. if ((mbhc->current_plug !=
  717. MBHC_PLUG_TYPE_HEADSET) &&
  718. (mbhc->current_plug !=
  719. MBHC_PLUG_TYPE_ANC_HEADPHONE) &&
  720. !wcd_swch_level_remove(mbhc)) {
  721. pr_debug("%s: cable is %s headset\n",
  722. __func__,
  723. ((spl_hs_count ==
  724. WCD_MBHC_SPL_HS_CNT) ?
  725. "special ":""));
  726. goto report;
  727. }
  728. }
  729. wrk_complete = false;
  730. }
  731. }
  732. if ((plug_type == MBHC_PLUG_TYPE_HEADSET ||
  733. plug_type == MBHC_PLUG_TYPE_HEADPHONE))
  734. mbhc->mbhc_cb->bcs_enable(mbhc, true);
  735. if (!wrk_complete) {
  736. /*
  737. * If plug_tye is headset, we might have already reported either
  738. * in detect_plug-type or in above while loop, no need to report
  739. * again
  740. */
  741. if ((plug_type == MBHC_PLUG_TYPE_HEADSET) ||
  742. (plug_type == MBHC_PLUG_TYPE_ANC_HEADPHONE)) {
  743. pr_debug("%s: plug_type:0x%x already reported\n",
  744. __func__, mbhc->current_plug);
  745. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_MODE, 0);
  746. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 0);
  747. goto enable_supply;
  748. }
  749. }
  750. if (plug_type == MBHC_PLUG_TYPE_HIGH_HPH) {
  751. if (wcd_is_special_headset(mbhc)) {
  752. pr_debug("%s: Special headset found %d\n",
  753. __func__, plug_type);
  754. plug_type = MBHC_PLUG_TYPE_HEADSET;
  755. } else {
  756. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_ISRC_EN, 1);
  757. }
  758. }
  759. report:
  760. if (wcd_swch_level_remove(mbhc)) {
  761. pr_debug("%s: Switch level is low\n", __func__);
  762. goto exit;
  763. }
  764. pr_debug("%s: Valid plug found, plug type %d wrk_cmpt %d btn_intr %d\n",
  765. __func__, plug_type, wrk_complete,
  766. mbhc->btn_press_intr);
  767. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_MODE, 0);
  768. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 0);
  769. WCD_MBHC_RSC_LOCK(mbhc);
  770. wcd_mbhc_find_plug_and_report(mbhc, plug_type);
  771. WCD_MBHC_RSC_UNLOCK(mbhc);
  772. enable_supply:
  773. /*
  774. * Set DETECTION_DONE bit for HEADSET and ANC_HEADPHONE,
  775. * so that btn press/release interrupt can be generated.
  776. * For other plug type, clear the bit.
  777. */
  778. if (plug_type == MBHC_PLUG_TYPE_HEADSET ||
  779. plug_type == MBHC_PLUG_TYPE_ANC_HEADPHONE)
  780. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_DETECTION_DONE, 1);
  781. else
  782. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_DETECTION_DONE, 0);
  783. if (mbhc->mbhc_cb->mbhc_micbias_control)
  784. wcd_mbhc_adc_update_fsm_source(mbhc, plug_type);
  785. exit:
  786. if (mbhc->mbhc_cb->mbhc_micbias_control &&
  787. !mbhc->micbias_enable)
  788. mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2,
  789. MICB_DISABLE);
  790. /*
  791. * If plug type is corrected from special headset to headphone,
  792. * clear the micbias enable flag, set micbias back to 1.8V and
  793. * disable micbias.
  794. */
  795. if (plug_type == MBHC_PLUG_TYPE_HEADPHONE &&
  796. mbhc->micbias_enable) {
  797. if (mbhc->mbhc_cb->mbhc_micbias_control)
  798. mbhc->mbhc_cb->mbhc_micbias_control(
  799. component, MIC_BIAS_2,
  800. MICB_DISABLE);
  801. if (mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic)
  802. mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(
  803. component,
  804. MIC_BIAS_2, false);
  805. if (mbhc->mbhc_cb->set_micbias_value) {
  806. mbhc->mbhc_cb->set_micbias_value(component);
  807. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MICB_CTRL, 0);
  808. }
  809. mbhc->micbias_enable = false;
  810. }
  811. if (mbhc->mbhc_cfg->detect_extn_cable &&
  812. ((plug_type == MBHC_PLUG_TYPE_HEADPHONE) ||
  813. (plug_type == MBHC_PLUG_TYPE_HEADSET)) &&
  814. !mbhc->hs_detect_work_stop) {
  815. WCD_MBHC_RSC_LOCK(mbhc);
  816. wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_REM, true);
  817. WCD_MBHC_RSC_UNLOCK(mbhc);
  818. }
  819. /*
  820. * Enable ADC COMPLETE interrupt for HEADPHONE.
  821. * Btn release may happen after the correct work, ADC COMPLETE
  822. * interrupt needs to be captured to correct plug type.
  823. */
  824. if (plug_type == MBHC_PLUG_TYPE_HEADPHONE) {
  825. WCD_MBHC_RSC_LOCK(mbhc);
  826. wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_INS,
  827. true);
  828. WCD_MBHC_RSC_UNLOCK(mbhc);
  829. }
  830. if (mbhc->mbhc_cb->hph_pull_down_ctrl)
  831. mbhc->mbhc_cb->hph_pull_down_ctrl(component, true);
  832. mbhc->mbhc_cb->lock_sleep(mbhc, false);
  833. pr_debug("%s: leave\n", __func__);
  834. }
  835. static irqreturn_t wcd_mbhc_adc_hs_rem_irq(int irq, void *data)
  836. {
  837. struct wcd_mbhc *mbhc = data;
  838. unsigned long timeout;
  839. int adc_threshold, output_mv, retry = 0;
  840. bool hphpa_on = false;
  841. u8 moisture_status = 0;
  842. pr_debug("%s: enter\n", __func__);
  843. WCD_MBHC_RSC_LOCK(mbhc);
  844. timeout = jiffies +
  845. msecs_to_jiffies(WCD_FAKE_REMOVAL_MIN_PERIOD_MS);
  846. adc_threshold = wcd_mbhc_adc_get_hs_thres(mbhc);
  847. do {
  848. retry++;
  849. /*
  850. * read output_mv every 10ms to look for
  851. * any change in IN2_P
  852. */
  853. usleep_range(10000, 10100);
  854. output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
  855. pr_debug("%s: Check for fake removal: output_mv %d\n",
  856. __func__, output_mv);
  857. if ((output_mv <= adc_threshold) &&
  858. retry > FAKE_REM_RETRY_ATTEMPTS) {
  859. pr_debug("%s: headset is NOT actually removed\n",
  860. __func__);
  861. goto exit;
  862. }
  863. } while (!time_after(jiffies, timeout));
  864. if (wcd_swch_level_remove(mbhc)) {
  865. pr_debug("%s: Switch level is low ", __func__);
  866. goto exit;
  867. }
  868. if (mbhc->mbhc_cfg->moisture_en) {
  869. if (mbhc->mbhc_cb->hph_pa_on_status)
  870. if (mbhc->mbhc_cb->hph_pa_on_status(mbhc->component)) {
  871. hphpa_on = true;
  872. WCD_MBHC_REG_UPDATE_BITS(
  873. WCD_MBHC_HPH_PA_EN, 0);
  874. }
  875. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPHR_GND, 1);
  876. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPHL_GND, 1);
  877. /* wait for 50ms to get moisture status */
  878. usleep_range(50000, 50100);
  879. WCD_MBHC_REG_READ(WCD_MBHC_MOISTURE_STATUS, moisture_status);
  880. }
  881. if (mbhc->mbhc_cfg->moisture_en && !moisture_status) {
  882. pr_debug("%s: moisture present in jack\n", __func__);
  883. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 0);
  884. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MECH_DETECTION_TYPE, 1);
  885. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 1);
  886. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
  887. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 0);
  888. mbhc->btn_press_intr = false;
  889. mbhc->is_btn_press = false;
  890. if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET)
  891. wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADSET);
  892. else if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE)
  893. wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADPHONE);
  894. else if (mbhc->current_plug == MBHC_PLUG_TYPE_GND_MIC_SWAP)
  895. wcd_mbhc_report_plug(mbhc, 0, SND_JACK_UNSUPPORTED);
  896. else if (mbhc->current_plug == MBHC_PLUG_TYPE_HIGH_HPH)
  897. wcd_mbhc_report_plug(mbhc, 0, SND_JACK_LINEOUT);
  898. } else {
  899. /*
  900. * ADC COMPLETE and ELEC_REM interrupts are both enabled for
  901. * HEADPHONE, need to reject the ADC COMPLETE interrupt which
  902. * follows ELEC_REM one when HEADPHONE is removed.
  903. */
  904. if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE)
  905. mbhc->extn_cable_hph_rem = true;
  906. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_DETECTION_DONE, 0);
  907. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_MODE, 0);
  908. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 0);
  909. wcd_mbhc_elec_hs_report_unplug(mbhc);
  910. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 0);
  911. if (hphpa_on) {
  912. hphpa_on = false;
  913. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPH_PA_EN, 3);
  914. }
  915. }
  916. exit:
  917. WCD_MBHC_RSC_UNLOCK(mbhc);
  918. pr_debug("%s: leave\n", __func__);
  919. return IRQ_HANDLED;
  920. }
  921. static irqreturn_t wcd_mbhc_adc_hs_ins_irq(int irq, void *data)
  922. {
  923. struct wcd_mbhc *mbhc = data;
  924. u8 clamp_state = 0;
  925. u8 clamp_retry = WCD_MBHC_FAKE_INS_RETRY;
  926. pr_debug("%s: enter\n", __func__);
  927. /*
  928. * ADC COMPLETE and ELEC_REM interrupts are both enabled for HEADPHONE,
  929. * need to reject the ADC COMPLETE interrupt which follows ELEC_REM one
  930. * when HEADPHONE is removed.
  931. */
  932. if (mbhc->extn_cable_hph_rem == true) {
  933. mbhc->extn_cable_hph_rem = false;
  934. pr_debug("%s: leave\n", __func__);
  935. return IRQ_HANDLED;
  936. }
  937. do {
  938. WCD_MBHC_REG_READ(WCD_MBHC_IN2P_CLAMP_STATE, clamp_state);
  939. if (clamp_state) {
  940. pr_debug("%s: fake insertion irq, leave\n", __func__);
  941. return IRQ_HANDLED;
  942. }
  943. /*
  944. * check clamp for 120ms but at 30ms chunks to leave
  945. * room for other interrupts to be processed
  946. */
  947. usleep_range(30000, 30100);
  948. } while (--clamp_retry);
  949. WCD_MBHC_RSC_LOCK(mbhc);
  950. /*
  951. * If current plug is headphone then there is no chance to
  952. * get ADC complete interrupt, so connected cable should be
  953. * headset not headphone.
  954. */
  955. if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE) {
  956. wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_INS, false);
  957. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_DETECTION_DONE, 1);
  958. wcd_mbhc_find_plug_and_report(mbhc, MBHC_PLUG_TYPE_HEADSET);
  959. WCD_MBHC_RSC_UNLOCK(mbhc);
  960. return IRQ_HANDLED;
  961. }
  962. if (!mbhc->mbhc_cfg->detect_extn_cable) {
  963. pr_debug("%s: Returning as Extension cable feature not enabled\n",
  964. __func__);
  965. WCD_MBHC_RSC_UNLOCK(mbhc);
  966. return IRQ_HANDLED;
  967. }
  968. pr_debug("%s: Disable electrical headset insertion interrupt\n",
  969. __func__);
  970. wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_INS, false);
  971. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 0);
  972. WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_ISRC_EN, 0);
  973. mbhc->is_extn_cable = true;
  974. mbhc->btn_press_intr = false;
  975. wcd_mbhc_adc_detect_plug_type(mbhc);
  976. WCD_MBHC_RSC_UNLOCK(mbhc);
  977. pr_debug("%s: leave\n", __func__);
  978. return IRQ_HANDLED;
  979. }
  980. static struct wcd_mbhc_fn mbhc_fn = {
  981. .wcd_mbhc_hs_ins_irq = wcd_mbhc_adc_hs_ins_irq,
  982. .wcd_mbhc_hs_rem_irq = wcd_mbhc_adc_hs_rem_irq,
  983. .wcd_mbhc_detect_plug_type = wcd_mbhc_adc_detect_plug_type,
  984. .wcd_mbhc_detect_anc_plug_type = wcd_mbhc_adc_detect_anc_plug_type,
  985. .wcd_cancel_hs_detect_plug = wcd_cancel_hs_detect_plug,
  986. };
  987. /* Function: wcd_mbhc_adc_init
  988. * @mbhc: MBHC function pointer
  989. * Description: Initialize MBHC ADC related function pointers to MBHC structure
  990. */
  991. void wcd_mbhc_adc_init(struct wcd_mbhc *mbhc)
  992. {
  993. if (!mbhc) {
  994. pr_err("%s: mbhc is NULL\n", __func__);
  995. return;
  996. }
  997. mbhc->mbhc_fn = &mbhc_fn;
  998. INIT_WORK(&mbhc->correct_plug_swch, wcd_correct_swch_plug);
  999. }
  1000. EXPORT_SYMBOL(wcd_mbhc_adc_init);