wcd-mbhc-v2.c 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. // Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  3. #include <linux/module.h>
  4. #include <linux/init.h>
  5. #include <linux/slab.h>
  6. #include <linux/device.h>
  7. #include <linux/pm_runtime.h>
  8. #include <linux/printk.h>
  9. #include <linux/delay.h>
  10. #include <linux/kernel.h>
  11. #include <sound/soc.h>
  12. #include <sound/jack.h>
  13. #include "wcd-mbhc-v2.h"
  14. #define HS_DETECT_PLUG_TIME_MS (3 * 1000)
  15. #define MBHC_BUTTON_PRESS_THRESHOLD_MIN 250
  16. #define GND_MIC_SWAP_THRESHOLD 4
  17. #define WCD_FAKE_REMOVAL_MIN_PERIOD_MS 100
  18. #define HPHL_CROSS_CONN_THRESHOLD 100
  19. #define HS_VREF_MIN_VAL 1400
  20. #define FAKE_REM_RETRY_ATTEMPTS 3
  21. #define WCD_MBHC_ADC_HS_THRESHOLD_MV 1700
  22. #define WCD_MBHC_ADC_HPH_THRESHOLD_MV 75
  23. #define WCD_MBHC_ADC_MICBIAS_MV 1800
  24. #define WCD_MBHC_FAKE_INS_RETRY 4
  25. #define WCD_MBHC_JACK_MASK (SND_JACK_HEADSET | SND_JACK_LINEOUT | \
  26. SND_JACK_MECHANICAL)
  27. #define WCD_MBHC_JACK_BUTTON_MASK (SND_JACK_BTN_0 | SND_JACK_BTN_1 | \
  28. SND_JACK_BTN_2 | SND_JACK_BTN_3 | \
  29. SND_JACK_BTN_4 | SND_JACK_BTN_5)
  30. enum wcd_mbhc_adc_mux_ctl {
  31. MUX_CTL_AUTO = 0,
  32. MUX_CTL_IN2P,
  33. MUX_CTL_IN3P,
  34. MUX_CTL_IN4P,
  35. MUX_CTL_HPH_L,
  36. MUX_CTL_HPH_R,
  37. MUX_CTL_NONE,
  38. };
  39. struct wcd_mbhc {
  40. struct device *dev;
  41. struct snd_soc_component *component;
  42. struct snd_soc_jack *jack;
  43. struct wcd_mbhc_config *cfg;
  44. const struct wcd_mbhc_cb *mbhc_cb;
  45. const struct wcd_mbhc_intr *intr_ids;
  46. struct wcd_mbhc_field *fields;
  47. /* Delayed work to report long button press */
  48. struct delayed_work mbhc_btn_dwork;
  49. /* Work to correct accessory type */
  50. struct work_struct correct_plug_swch;
  51. struct mutex lock;
  52. int buttons_pressed;
  53. u32 hph_status; /* track headhpone status */
  54. u8 current_plug;
  55. bool is_btn_press;
  56. bool in_swch_irq_handler;
  57. bool hs_detect_work_stop;
  58. bool is_hs_recording;
  59. bool extn_cable_hph_rem;
  60. bool force_linein;
  61. bool impedance_detect;
  62. unsigned long event_state;
  63. unsigned long jiffies_atreport;
  64. /* impedance of hphl and hphr */
  65. uint32_t zl, zr;
  66. /* Holds type of Headset - Mono/Stereo */
  67. enum wcd_mbhc_hph_type hph_type;
  68. /* Holds mbhc detection method - ADC/Legacy */
  69. int mbhc_detection_logic;
  70. };
  71. static inline int wcd_mbhc_write_field(const struct wcd_mbhc *mbhc,
  72. int field, int val)
  73. {
  74. if (!mbhc->fields[field].reg)
  75. return 0;
  76. return snd_soc_component_write_field(mbhc->component,
  77. mbhc->fields[field].reg,
  78. mbhc->fields[field].mask, val);
  79. }
  80. static inline int wcd_mbhc_read_field(const struct wcd_mbhc *mbhc, int field)
  81. {
  82. if (!mbhc->fields[field].reg)
  83. return 0;
  84. return snd_soc_component_read_field(mbhc->component,
  85. mbhc->fields[field].reg,
  86. mbhc->fields[field].mask);
  87. }
  88. static void wcd_program_hs_vref(struct wcd_mbhc *mbhc)
  89. {
  90. u32 reg_val = ((mbhc->cfg->v_hs_max - HS_VREF_MIN_VAL) / 100);
  91. wcd_mbhc_write_field(mbhc, WCD_MBHC_HS_VREF, reg_val);
  92. }
  93. static void wcd_program_btn_threshold(const struct wcd_mbhc *mbhc, bool micbias)
  94. {
  95. struct snd_soc_component *component = mbhc->component;
  96. mbhc->mbhc_cb->set_btn_thr(component, mbhc->cfg->btn_low,
  97. mbhc->cfg->btn_high,
  98. mbhc->cfg->num_btn, micbias);
  99. }
  100. static void wcd_mbhc_curr_micbias_control(const struct wcd_mbhc *mbhc,
  101. const enum wcd_mbhc_cs_mb_en_flag cs_mb_en)
  102. {
  103. /*
  104. * Some codecs handle micbias/pullup enablement in codec
  105. * drivers itself and micbias is not needed for regular
  106. * plug type detection. So if micbias_control callback function
  107. * is defined, just return.
  108. */
  109. if (mbhc->mbhc_cb->mbhc_micbias_control)
  110. return;
  111. switch (cs_mb_en) {
  112. case WCD_MBHC_EN_CS:
  113. wcd_mbhc_write_field(mbhc, WCD_MBHC_MICB_CTRL, 0);
  114. wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3);
  115. /* Program Button threshold registers as per CS */
  116. wcd_program_btn_threshold(mbhc, false);
  117. break;
  118. case WCD_MBHC_EN_MB:
  119. wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0);
  120. wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1);
  121. /* Disable PULL_UP_EN & enable MICBIAS */
  122. wcd_mbhc_write_field(mbhc, WCD_MBHC_MICB_CTRL, 2);
  123. /* Program Button threshold registers as per MICBIAS */
  124. wcd_program_btn_threshold(mbhc, true);
  125. break;
  126. case WCD_MBHC_EN_PULLUP:
  127. wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3);
  128. wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1);
  129. wcd_mbhc_write_field(mbhc, WCD_MBHC_MICB_CTRL, 1);
  130. /* Program Button threshold registers as per MICBIAS */
  131. wcd_program_btn_threshold(mbhc, true);
  132. break;
  133. case WCD_MBHC_EN_NONE:
  134. wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0);
  135. wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1);
  136. wcd_mbhc_write_field(mbhc, WCD_MBHC_MICB_CTRL, 0);
  137. break;
  138. default:
  139. dev_err(mbhc->dev, "%s: Invalid parameter", __func__);
  140. break;
  141. }
  142. }
  143. int wcd_mbhc_event_notify(struct wcd_mbhc *mbhc, unsigned long event)
  144. {
  145. struct snd_soc_component *component;
  146. bool micbias2 = false;
  147. if (!mbhc)
  148. return 0;
  149. component = mbhc->component;
  150. if (mbhc->mbhc_cb->micbias_enable_status)
  151. micbias2 = mbhc->mbhc_cb->micbias_enable_status(component, MIC_BIAS_2);
  152. switch (event) {
  153. /* MICBIAS usage change */
  154. case WCD_EVENT_POST_DAPM_MICBIAS_2_ON:
  155. mbhc->is_hs_recording = true;
  156. break;
  157. case WCD_EVENT_POST_MICBIAS_2_ON:
  158. /* Disable current source if micbias2 enabled */
  159. if (mbhc->mbhc_cb->mbhc_micbias_control) {
  160. if (wcd_mbhc_read_field(mbhc, WCD_MBHC_FSM_EN))
  161. wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0);
  162. } else {
  163. mbhc->is_hs_recording = true;
  164. wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_MB);
  165. }
  166. break;
  167. case WCD_EVENT_PRE_MICBIAS_2_OFF:
  168. /*
  169. * Before MICBIAS_2 is turned off, if FSM is enabled,
  170. * make sure current source is enabled so as to detect
  171. * button press/release events
  172. */
  173. if (mbhc->mbhc_cb->mbhc_micbias_control/* && !mbhc->micbias_enable*/) {
  174. if (wcd_mbhc_read_field(mbhc, WCD_MBHC_FSM_EN))
  175. wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3);
  176. }
  177. break;
  178. /* MICBIAS usage change */
  179. case WCD_EVENT_POST_DAPM_MICBIAS_2_OFF:
  180. mbhc->is_hs_recording = false;
  181. break;
  182. case WCD_EVENT_POST_MICBIAS_2_OFF:
  183. if (!mbhc->mbhc_cb->mbhc_micbias_control)
  184. mbhc->is_hs_recording = false;
  185. /* Enable PULL UP if PA's are enabled */
  186. if ((test_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state)) ||
  187. (test_bit(WCD_MBHC_EVENT_PA_HPHR, &mbhc->event_state)))
  188. /* enable pullup and cs, disable mb */
  189. wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_PULLUP);
  190. else
  191. /* enable current source and disable mb, pullup*/
  192. wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_CS);
  193. break;
  194. case WCD_EVENT_POST_HPHL_PA_OFF:
  195. clear_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state);
  196. /* check if micbias is enabled */
  197. if (micbias2)
  198. /* Disable cs, pullup & enable micbias */
  199. wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_MB);
  200. else
  201. /* Disable micbias, pullup & enable cs */
  202. wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_CS);
  203. break;
  204. case WCD_EVENT_POST_HPHR_PA_OFF:
  205. clear_bit(WCD_MBHC_EVENT_PA_HPHR, &mbhc->event_state);
  206. /* check if micbias is enabled */
  207. if (micbias2)
  208. /* Disable cs, pullup & enable micbias */
  209. wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_MB);
  210. else
  211. /* Disable micbias, pullup & enable cs */
  212. wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_CS);
  213. break;
  214. case WCD_EVENT_PRE_HPHL_PA_ON:
  215. set_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state);
  216. /* check if micbias is enabled */
  217. if (micbias2)
  218. /* Disable cs, pullup & enable micbias */
  219. wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_MB);
  220. else
  221. /* Disable micbias, enable pullup & cs */
  222. wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_PULLUP);
  223. break;
  224. case WCD_EVENT_PRE_HPHR_PA_ON:
  225. set_bit(WCD_MBHC_EVENT_PA_HPHR, &mbhc->event_state);
  226. /* check if micbias is enabled */
  227. if (micbias2)
  228. /* Disable cs, pullup & enable micbias */
  229. wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_MB);
  230. else
  231. /* Disable micbias, enable pullup & cs */
  232. wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_PULLUP);
  233. break;
  234. default:
  235. break;
  236. }
  237. return 0;
  238. }
  239. EXPORT_SYMBOL_GPL(wcd_mbhc_event_notify);
  240. static int wcd_cancel_btn_work(struct wcd_mbhc *mbhc)
  241. {
  242. return cancel_delayed_work_sync(&mbhc->mbhc_btn_dwork);
  243. }
  244. static void wcd_micbias_disable(struct wcd_mbhc *mbhc)
  245. {
  246. struct snd_soc_component *component = mbhc->component;
  247. if (mbhc->mbhc_cb->mbhc_micbias_control)
  248. mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2, MICB_DISABLE);
  249. if (mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic)
  250. mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(component, MIC_BIAS_2, false);
  251. if (mbhc->mbhc_cb->set_micbias_value) {
  252. mbhc->mbhc_cb->set_micbias_value(component);
  253. wcd_mbhc_write_field(mbhc, WCD_MBHC_MICB_CTRL, 0);
  254. }
  255. }
  256. static void wcd_mbhc_report_plug_removal(struct wcd_mbhc *mbhc,
  257. enum snd_jack_types jack_type)
  258. {
  259. mbhc->hph_status &= ~jack_type;
  260. /*
  261. * cancel possibly scheduled btn work and
  262. * report release if we reported button press
  263. */
  264. if (!wcd_cancel_btn_work(mbhc) && mbhc->buttons_pressed) {
  265. snd_soc_jack_report(mbhc->jack, 0, mbhc->buttons_pressed);
  266. mbhc->buttons_pressed &= ~WCD_MBHC_JACK_BUTTON_MASK;
  267. }
  268. wcd_micbias_disable(mbhc);
  269. mbhc->hph_type = WCD_MBHC_HPH_NONE;
  270. mbhc->zl = mbhc->zr = 0;
  271. snd_soc_jack_report(mbhc->jack, mbhc->hph_status, WCD_MBHC_JACK_MASK);
  272. mbhc->current_plug = MBHC_PLUG_TYPE_NONE;
  273. mbhc->force_linein = false;
  274. }
  275. static void wcd_mbhc_compute_impedance(struct wcd_mbhc *mbhc)
  276. {
  277. if (!mbhc->impedance_detect)
  278. return;
  279. if (mbhc->cfg->linein_th != 0) {
  280. u8 fsm_en = wcd_mbhc_read_field(mbhc, WCD_MBHC_FSM_EN);
  281. /* Set MUX_CTL to AUTO for Z-det */
  282. wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0);
  283. wcd_mbhc_write_field(mbhc, WCD_MBHC_MUX_CTL, MUX_CTL_AUTO);
  284. wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1);
  285. mbhc->mbhc_cb->compute_impedance(mbhc->component, &mbhc->zl, &mbhc->zr);
  286. wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, fsm_en);
  287. }
  288. }
  289. static void wcd_mbhc_report_plug_insertion(struct wcd_mbhc *mbhc,
  290. enum snd_jack_types jack_type)
  291. {
  292. bool is_pa_on;
  293. /*
  294. * Report removal of current jack type.
  295. * Headphone to headset shouldn't report headphone
  296. * removal.
  297. */
  298. if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET &&
  299. jack_type == SND_JACK_HEADPHONE)
  300. mbhc->hph_status &= ~SND_JACK_HEADSET;
  301. /* Report insertion */
  302. switch (jack_type) {
  303. case SND_JACK_HEADPHONE:
  304. mbhc->current_plug = MBHC_PLUG_TYPE_HEADPHONE;
  305. break;
  306. case SND_JACK_HEADSET:
  307. mbhc->current_plug = MBHC_PLUG_TYPE_HEADSET;
  308. mbhc->jiffies_atreport = jiffies;
  309. break;
  310. case SND_JACK_LINEOUT:
  311. mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH;
  312. break;
  313. default:
  314. break;
  315. }
  316. is_pa_on = wcd_mbhc_read_field(mbhc, WCD_MBHC_HPH_PA_EN);
  317. if (!is_pa_on) {
  318. wcd_mbhc_compute_impedance(mbhc);
  319. if ((mbhc->zl > mbhc->cfg->linein_th) &&
  320. (mbhc->zr > mbhc->cfg->linein_th) &&
  321. (jack_type == SND_JACK_HEADPHONE)) {
  322. jack_type = SND_JACK_LINEOUT;
  323. mbhc->force_linein = true;
  324. mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH;
  325. if (mbhc->hph_status) {
  326. mbhc->hph_status &= ~(SND_JACK_HEADSET |
  327. SND_JACK_LINEOUT);
  328. snd_soc_jack_report(mbhc->jack, mbhc->hph_status,
  329. WCD_MBHC_JACK_MASK);
  330. }
  331. }
  332. }
  333. /* Do not calculate impedance again for lineout
  334. * as during playback pa is on and impedance values
  335. * will not be correct resulting in lineout detected
  336. * as headphone.
  337. */
  338. if (is_pa_on && mbhc->force_linein) {
  339. jack_type = SND_JACK_LINEOUT;
  340. mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH;
  341. if (mbhc->hph_status) {
  342. mbhc->hph_status &= ~(SND_JACK_HEADSET |
  343. SND_JACK_LINEOUT);
  344. snd_soc_jack_report(mbhc->jack, mbhc->hph_status,
  345. WCD_MBHC_JACK_MASK);
  346. }
  347. }
  348. mbhc->hph_status |= jack_type;
  349. if (jack_type == SND_JACK_HEADPHONE && mbhc->mbhc_cb->mbhc_micb_ramp_control)
  350. mbhc->mbhc_cb->mbhc_micb_ramp_control(mbhc->component, false);
  351. snd_soc_jack_report(mbhc->jack, (mbhc->hph_status | SND_JACK_MECHANICAL),
  352. WCD_MBHC_JACK_MASK);
  353. }
  354. static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion,
  355. enum snd_jack_types jack_type)
  356. {
  357. WARN_ON(!mutex_is_locked(&mbhc->lock));
  358. if (!insertion) /* Report removal */
  359. wcd_mbhc_report_plug_removal(mbhc, jack_type);
  360. else
  361. wcd_mbhc_report_plug_insertion(mbhc, jack_type);
  362. }
  363. static void wcd_cancel_hs_detect_plug(struct wcd_mbhc *mbhc,
  364. struct work_struct *work)
  365. {
  366. mbhc->hs_detect_work_stop = true;
  367. mutex_unlock(&mbhc->lock);
  368. cancel_work_sync(work);
  369. mutex_lock(&mbhc->lock);
  370. }
  371. static void wcd_mbhc_cancel_pending_work(struct wcd_mbhc *mbhc)
  372. {
  373. /* cancel pending button press */
  374. wcd_cancel_btn_work(mbhc);
  375. /* cancel correct work function */
  376. wcd_cancel_hs_detect_plug(mbhc, &mbhc->correct_plug_swch);
  377. }
  378. static void wcd_mbhc_elec_hs_report_unplug(struct wcd_mbhc *mbhc)
  379. {
  380. wcd_mbhc_cancel_pending_work(mbhc);
  381. /* Report extension cable */
  382. wcd_mbhc_report_plug(mbhc, 1, SND_JACK_LINEOUT);
  383. /*
  384. * Disable HPHL trigger and MIC Schmitt triggers.
  385. * Setup for insertion detection.
  386. */
  387. disable_irq_nosync(mbhc->intr_ids->mbhc_hs_rem_intr);
  388. wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_NONE);
  389. /* Disable HW FSM */
  390. wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0);
  391. wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC, 3);
  392. /* Set the detection type appropriately */
  393. wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_DETECTION_TYPE, 1);
  394. enable_irq(mbhc->intr_ids->mbhc_hs_ins_intr);
  395. }
  396. static void wcd_mbhc_find_plug_and_report(struct wcd_mbhc *mbhc,
  397. enum wcd_mbhc_plug_type plug_type)
  398. {
  399. if (mbhc->current_plug == plug_type)
  400. return;
  401. mutex_lock(&mbhc->lock);
  402. switch (plug_type) {
  403. case MBHC_PLUG_TYPE_HEADPHONE:
  404. wcd_mbhc_report_plug(mbhc, 1, SND_JACK_HEADPHONE);
  405. break;
  406. case MBHC_PLUG_TYPE_HEADSET:
  407. wcd_mbhc_report_plug(mbhc, 1, SND_JACK_HEADSET);
  408. break;
  409. case MBHC_PLUG_TYPE_HIGH_HPH:
  410. wcd_mbhc_report_plug(mbhc, 1, SND_JACK_LINEOUT);
  411. break;
  412. case MBHC_PLUG_TYPE_GND_MIC_SWAP:
  413. if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE)
  414. wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADPHONE);
  415. if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET)
  416. wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADSET);
  417. break;
  418. default:
  419. WARN(1, "Unexpected current plug_type %d, plug_type %d\n",
  420. mbhc->current_plug, plug_type);
  421. break;
  422. }
  423. mutex_unlock(&mbhc->lock);
  424. }
  425. static void wcd_schedule_hs_detect_plug(struct wcd_mbhc *mbhc,
  426. struct work_struct *work)
  427. {
  428. WARN_ON(!mutex_is_locked(&mbhc->lock));
  429. mbhc->hs_detect_work_stop = false;
  430. schedule_work(work);
  431. }
  432. static void wcd_mbhc_adc_detect_plug_type(struct wcd_mbhc *mbhc)
  433. {
  434. struct snd_soc_component *component = mbhc->component;
  435. WARN_ON(!mutex_is_locked(&mbhc->lock));
  436. if (mbhc->mbhc_cb->hph_pull_down_ctrl)
  437. mbhc->mbhc_cb->hph_pull_down_ctrl(component, false);
  438. wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 0);
  439. if (mbhc->mbhc_cb->mbhc_micbias_control) {
  440. mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2,
  441. MICB_ENABLE);
  442. wcd_schedule_hs_detect_plug(mbhc, &mbhc->correct_plug_swch);
  443. }
  444. }
  445. static irqreturn_t wcd_mbhc_mech_plug_detect_irq(int irq, void *data)
  446. {
  447. struct snd_soc_component *component;
  448. enum snd_jack_types jack_type;
  449. struct wcd_mbhc *mbhc = data;
  450. bool detection_type;
  451. component = mbhc->component;
  452. mutex_lock(&mbhc->lock);
  453. mbhc->in_swch_irq_handler = true;
  454. wcd_mbhc_cancel_pending_work(mbhc);
  455. detection_type = wcd_mbhc_read_field(mbhc, WCD_MBHC_MECH_DETECTION_TYPE);
  456. /* Set the detection type appropriately */
  457. wcd_mbhc_write_field(mbhc, WCD_MBHC_MECH_DETECTION_TYPE, !detection_type);
  458. /* Enable micbias ramp */
  459. if (mbhc->mbhc_cb->mbhc_micb_ramp_control)
  460. mbhc->mbhc_cb->mbhc_micb_ramp_control(component, true);
  461. if (detection_type) {
  462. if (mbhc->current_plug != MBHC_PLUG_TYPE_NONE)
  463. goto exit;
  464. /* Make sure MASTER_BIAS_CTL is enabled */
  465. mbhc->mbhc_cb->mbhc_bias(component, true);
  466. mbhc->is_btn_press = false;
  467. wcd_mbhc_adc_detect_plug_type(mbhc);
  468. } else {
  469. /* Disable HW FSM */
  470. wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0);
  471. wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0);
  472. mbhc->extn_cable_hph_rem = false;
  473. if (mbhc->current_plug == MBHC_PLUG_TYPE_NONE)
  474. goto exit;
  475. mbhc->is_btn_press = false;
  476. switch (mbhc->current_plug) {
  477. case MBHC_PLUG_TYPE_HEADPHONE:
  478. jack_type = SND_JACK_HEADPHONE;
  479. break;
  480. case MBHC_PLUG_TYPE_HEADSET:
  481. jack_type = SND_JACK_HEADSET;
  482. break;
  483. case MBHC_PLUG_TYPE_HIGH_HPH:
  484. if (mbhc->mbhc_detection_logic == WCD_DETECTION_ADC)
  485. wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_ISRC_EN, 0);
  486. jack_type = SND_JACK_LINEOUT;
  487. break;
  488. case MBHC_PLUG_TYPE_GND_MIC_SWAP:
  489. dev_err(mbhc->dev, "Ground and Mic Swapped on plug\n");
  490. goto exit;
  491. default:
  492. dev_err(mbhc->dev, "Invalid current plug: %d\n",
  493. mbhc->current_plug);
  494. goto exit;
  495. }
  496. disable_irq_nosync(mbhc->intr_ids->mbhc_hs_rem_intr);
  497. disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr);
  498. wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_DETECTION_TYPE, 1);
  499. wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC, 0);
  500. wcd_mbhc_report_plug(mbhc, 0, jack_type);
  501. }
  502. exit:
  503. mbhc->in_swch_irq_handler = false;
  504. mutex_unlock(&mbhc->lock);
  505. return IRQ_HANDLED;
  506. }
  507. static int wcd_mbhc_get_button_mask(struct wcd_mbhc *mbhc)
  508. {
  509. int mask = 0;
  510. int btn;
  511. btn = wcd_mbhc_read_field(mbhc, WCD_MBHC_BTN_RESULT);
  512. switch (btn) {
  513. case 0:
  514. mask = SND_JACK_BTN_0;
  515. break;
  516. case 1:
  517. mask = SND_JACK_BTN_1;
  518. break;
  519. case 2:
  520. mask = SND_JACK_BTN_2;
  521. break;
  522. case 3:
  523. mask = SND_JACK_BTN_3;
  524. break;
  525. case 4:
  526. mask = SND_JACK_BTN_4;
  527. break;
  528. case 5:
  529. mask = SND_JACK_BTN_5;
  530. break;
  531. default:
  532. break;
  533. }
  534. return mask;
  535. }
  536. static void wcd_btn_long_press_fn(struct work_struct *work)
  537. {
  538. struct delayed_work *dwork = to_delayed_work(work);
  539. struct wcd_mbhc *mbhc = container_of(dwork, struct wcd_mbhc, mbhc_btn_dwork);
  540. if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET)
  541. snd_soc_jack_report(mbhc->jack, mbhc->buttons_pressed,
  542. mbhc->buttons_pressed);
  543. }
  544. static irqreturn_t wcd_mbhc_btn_press_handler(int irq, void *data)
  545. {
  546. struct wcd_mbhc *mbhc = data;
  547. int mask;
  548. unsigned long msec_val;
  549. mutex_lock(&mbhc->lock);
  550. wcd_cancel_btn_work(mbhc);
  551. mbhc->is_btn_press = true;
  552. msec_val = jiffies_to_msecs(jiffies - mbhc->jiffies_atreport);
  553. /* Too short, ignore button press */
  554. if (msec_val < MBHC_BUTTON_PRESS_THRESHOLD_MIN)
  555. goto done;
  556. /* If switch interrupt already kicked in, ignore button press */
  557. if (mbhc->in_swch_irq_handler)
  558. goto done;
  559. /* Plug isn't headset, ignore button press */
  560. if (mbhc->current_plug != MBHC_PLUG_TYPE_HEADSET)
  561. goto done;
  562. mask = wcd_mbhc_get_button_mask(mbhc);
  563. mbhc->buttons_pressed |= mask;
  564. if (schedule_delayed_work(&mbhc->mbhc_btn_dwork, msecs_to_jiffies(400)) == 0)
  565. WARN(1, "Button pressed twice without release event\n");
  566. done:
  567. mutex_unlock(&mbhc->lock);
  568. return IRQ_HANDLED;
  569. }
  570. static irqreturn_t wcd_mbhc_btn_release_handler(int irq, void *data)
  571. {
  572. struct wcd_mbhc *mbhc = data;
  573. int ret;
  574. mutex_lock(&mbhc->lock);
  575. if (mbhc->is_btn_press)
  576. mbhc->is_btn_press = false;
  577. else /* fake btn press */
  578. goto exit;
  579. if (!(mbhc->buttons_pressed & WCD_MBHC_JACK_BUTTON_MASK))
  580. goto exit;
  581. ret = wcd_cancel_btn_work(mbhc);
  582. if (ret == 0) { /* Reporting long button release event */
  583. snd_soc_jack_report(mbhc->jack, 0, mbhc->buttons_pressed);
  584. } else {
  585. if (!mbhc->in_swch_irq_handler) {
  586. /* Reporting btn press n Release */
  587. snd_soc_jack_report(mbhc->jack, mbhc->buttons_pressed,
  588. mbhc->buttons_pressed);
  589. snd_soc_jack_report(mbhc->jack, 0, mbhc->buttons_pressed);
  590. }
  591. }
  592. mbhc->buttons_pressed &= ~WCD_MBHC_JACK_BUTTON_MASK;
  593. exit:
  594. mutex_unlock(&mbhc->lock);
  595. return IRQ_HANDLED;
  596. }
  597. static irqreturn_t wcd_mbhc_hph_ocp_irq(struct wcd_mbhc *mbhc, bool hphr)
  598. {
  599. /* TODO Find a better way to report this to Userspace */
  600. dev_err(mbhc->dev, "MBHC Over Current on %s detected\n",
  601. hphr ? "HPHR" : "HPHL");
  602. wcd_mbhc_write_field(mbhc, WCD_MBHC_OCP_FSM_EN, 0);
  603. wcd_mbhc_write_field(mbhc, WCD_MBHC_OCP_FSM_EN, 1);
  604. return IRQ_HANDLED;
  605. }
  606. static irqreturn_t wcd_mbhc_hphl_ocp_irq(int irq, void *data)
  607. {
  608. return wcd_mbhc_hph_ocp_irq(data, false);
  609. }
  610. static irqreturn_t wcd_mbhc_hphr_ocp_irq(int irq, void *data)
  611. {
  612. return wcd_mbhc_hph_ocp_irq(data, true);
  613. }
  614. static int wcd_mbhc_initialise(struct wcd_mbhc *mbhc)
  615. {
  616. struct snd_soc_component *component = mbhc->component;
  617. int ret;
  618. ret = pm_runtime_get_sync(component->dev);
  619. if (ret < 0 && ret != -EACCES) {
  620. dev_err_ratelimited(component->dev,
  621. "pm_runtime_get_sync failed in %s, ret %d\n",
  622. __func__, ret);
  623. pm_runtime_put_noidle(component->dev);
  624. return ret;
  625. }
  626. mutex_lock(&mbhc->lock);
  627. /* enable HS detection */
  628. if (mbhc->mbhc_cb->hph_pull_up_control_v2)
  629. mbhc->mbhc_cb->hph_pull_up_control_v2(component,
  630. HS_PULLUP_I_DEFAULT);
  631. else if (mbhc->mbhc_cb->hph_pull_up_control)
  632. mbhc->mbhc_cb->hph_pull_up_control(component, I_DEFAULT);
  633. else
  634. wcd_mbhc_write_field(mbhc, WCD_MBHC_HS_L_DET_PULL_UP_CTRL, 3);
  635. wcd_mbhc_write_field(mbhc, WCD_MBHC_HPHL_PLUG_TYPE, mbhc->cfg->hphl_swh);
  636. wcd_mbhc_write_field(mbhc, WCD_MBHC_GND_PLUG_TYPE, mbhc->cfg->gnd_swh);
  637. wcd_mbhc_write_field(mbhc, WCD_MBHC_SW_HPH_LP_100K_TO_GND, 1);
  638. if (mbhc->cfg->gnd_det_en && mbhc->mbhc_cb->mbhc_gnd_det_ctrl)
  639. mbhc->mbhc_cb->mbhc_gnd_det_ctrl(component, true);
  640. wcd_mbhc_write_field(mbhc, WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL, 1);
  641. wcd_mbhc_write_field(mbhc, WCD_MBHC_L_DET_EN, 1);
  642. /* Insertion debounce set to 96ms */
  643. wcd_mbhc_write_field(mbhc, WCD_MBHC_INSREM_DBNC, 6);
  644. /* Button Debounce set to 16ms */
  645. wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_DBNC, 2);
  646. /* enable bias */
  647. mbhc->mbhc_cb->mbhc_bias(component, true);
  648. /* enable MBHC clock */
  649. if (mbhc->mbhc_cb->clk_setup)
  650. mbhc->mbhc_cb->clk_setup(component, true);
  651. /* program HS_VREF value */
  652. wcd_program_hs_vref(mbhc);
  653. wcd_program_btn_threshold(mbhc, false);
  654. mutex_unlock(&mbhc->lock);
  655. pm_runtime_mark_last_busy(component->dev);
  656. pm_runtime_put_autosuspend(component->dev);
  657. return 0;
  658. }
  659. static int wcd_mbhc_get_micbias(struct wcd_mbhc *mbhc)
  660. {
  661. int micbias = 0;
  662. if (mbhc->mbhc_cb->get_micbias_val) {
  663. mbhc->mbhc_cb->get_micbias_val(mbhc->component, &micbias);
  664. } else {
  665. u8 vout_ctl = 0;
  666. /* Read MBHC Micbias (Mic Bias2) voltage */
  667. vout_ctl = wcd_mbhc_read_field(mbhc, WCD_MBHC_MICB2_VOUT);
  668. /* Formula for getting micbias from vout
  669. * micbias = 1.0V + VOUT_CTL * 50mV
  670. */
  671. micbias = 1000 + (vout_ctl * 50);
  672. }
  673. return micbias;
  674. }
  675. static int wcd_get_voltage_from_adc(u8 val, int micbias)
  676. {
  677. /* Formula for calculating voltage from ADC
  678. * Voltage = ADC_RESULT*12.5mV*V_MICBIAS/1.8
  679. */
  680. return ((val * 125 * micbias)/(WCD_MBHC_ADC_MICBIAS_MV * 10));
  681. }
  682. static int wcd_measure_adc_continuous(struct wcd_mbhc *mbhc)
  683. {
  684. u8 adc_result;
  685. int output_mv;
  686. int retry = 3;
  687. u8 adc_en;
  688. /* Pre-requisites for ADC continuous measurement */
  689. /* Read legacy electircal detection and disable */
  690. wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC, 0x00);
  691. /* Set ADC to continuous measurement */
  692. wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, 1);
  693. /* Read ADC Enable bit to restore after adc measurement */
  694. adc_en = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_EN);
  695. /* Disable ADC_ENABLE bit */
  696. wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 0);
  697. /* Disable MBHC FSM */
  698. wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0);
  699. /* Set the MUX selection to IN2P */
  700. wcd_mbhc_write_field(mbhc, WCD_MBHC_MUX_CTL, MUX_CTL_IN2P);
  701. /* Enable MBHC FSM */
  702. wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1);
  703. /* Enable ADC_ENABLE bit */
  704. wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 1);
  705. while (retry--) {
  706. /* wait for 3 msec before reading ADC result */
  707. usleep_range(3000, 3100);
  708. adc_result = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_RESULT);
  709. }
  710. /* Restore ADC Enable */
  711. wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, adc_en);
  712. /* Get voltage from ADC result */
  713. output_mv = wcd_get_voltage_from_adc(adc_result, wcd_mbhc_get_micbias(mbhc));
  714. return output_mv;
  715. }
  716. static int wcd_measure_adc_once(struct wcd_mbhc *mbhc, int mux_ctl)
  717. {
  718. struct device *dev = mbhc->dev;
  719. u8 adc_timeout = 0;
  720. u8 adc_complete = 0;
  721. u8 adc_result;
  722. int retry = 6;
  723. int ret;
  724. int output_mv = 0;
  725. u8 adc_en;
  726. wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, 0);
  727. /* Read ADC Enable bit to restore after adc measurement */
  728. adc_en = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_EN);
  729. /* Trigger ADC one time measurement */
  730. wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 0);
  731. wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0);
  732. /* Set the appropriate MUX selection */
  733. wcd_mbhc_write_field(mbhc, WCD_MBHC_MUX_CTL, mux_ctl);
  734. wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1);
  735. wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 1);
  736. while (retry--) {
  737. /* wait for 600usec to get adc results */
  738. usleep_range(600, 610);
  739. /* check for ADC Timeout */
  740. adc_timeout = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_TIMEOUT);
  741. if (adc_timeout)
  742. continue;
  743. /* Read ADC complete bit */
  744. adc_complete = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_COMPLETE);
  745. if (!adc_complete)
  746. continue;
  747. /* Read ADC result */
  748. adc_result = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_RESULT);
  749. /* Get voltage from ADC result */
  750. output_mv = wcd_get_voltage_from_adc(adc_result,
  751. wcd_mbhc_get_micbias(mbhc));
  752. break;
  753. }
  754. /* Restore ADC Enable */
  755. wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, adc_en);
  756. if (retry <= 0) {
  757. dev_err(dev, "%s: adc complete: %d, adc timeout: %d\n",
  758. __func__, adc_complete, adc_timeout);
  759. ret = -EINVAL;
  760. } else {
  761. ret = output_mv;
  762. }
  763. return ret;
  764. }
  765. /* To determine if cross connection occurred */
  766. static int wcd_check_cross_conn(struct wcd_mbhc *mbhc)
  767. {
  768. u8 adc_mode, elect_ctl, adc_en, fsm_en;
  769. int hphl_adc_res, hphr_adc_res;
  770. bool is_cross_conn = false;
  771. /* If PA is enabled, dont check for cross-connection */
  772. if (wcd_mbhc_read_field(mbhc, WCD_MBHC_HPH_PA_EN))
  773. return -EINVAL;
  774. /* Read legacy electircal detection and disable */
  775. elect_ctl = wcd_mbhc_read_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC);
  776. wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC, 0);
  777. /* Read and set ADC to single measurement */
  778. adc_mode = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_MODE);
  779. /* Read ADC Enable bit to restore after adc measurement */
  780. adc_en = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_EN);
  781. /* Read FSM status */
  782. fsm_en = wcd_mbhc_read_field(mbhc, WCD_MBHC_FSM_EN);
  783. /* Get adc result for HPH L */
  784. hphl_adc_res = wcd_measure_adc_once(mbhc, MUX_CTL_HPH_L);
  785. if (hphl_adc_res < 0)
  786. return hphl_adc_res;
  787. /* Get adc result for HPH R in mV */
  788. hphr_adc_res = wcd_measure_adc_once(mbhc, MUX_CTL_HPH_R);
  789. if (hphr_adc_res < 0)
  790. return hphr_adc_res;
  791. if (hphl_adc_res > HPHL_CROSS_CONN_THRESHOLD ||
  792. hphr_adc_res > HPHL_CROSS_CONN_THRESHOLD)
  793. is_cross_conn = true;
  794. wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0);
  795. /* Set the MUX selection to Auto */
  796. wcd_mbhc_write_field(mbhc, WCD_MBHC_MUX_CTL, MUX_CTL_AUTO);
  797. wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1);
  798. /* Restore ADC Enable */
  799. wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, adc_en);
  800. /* Restore ADC mode */
  801. wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, adc_mode);
  802. /* Restore FSM state */
  803. wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, fsm_en);
  804. /* Restore electrical detection */
  805. wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl);
  806. return is_cross_conn;
  807. }
  808. static int wcd_mbhc_adc_get_hs_thres(struct wcd_mbhc *mbhc)
  809. {
  810. int hs_threshold, micbias_mv;
  811. micbias_mv = wcd_mbhc_get_micbias(mbhc);
  812. if (mbhc->cfg->hs_thr) {
  813. if (mbhc->cfg->micb_mv == micbias_mv)
  814. hs_threshold = mbhc->cfg->hs_thr;
  815. else
  816. hs_threshold = (mbhc->cfg->hs_thr *
  817. micbias_mv) / mbhc->cfg->micb_mv;
  818. } else {
  819. hs_threshold = ((WCD_MBHC_ADC_HS_THRESHOLD_MV *
  820. micbias_mv) / WCD_MBHC_ADC_MICBIAS_MV);
  821. }
  822. return hs_threshold;
  823. }
  824. static int wcd_mbhc_adc_get_hph_thres(struct wcd_mbhc *mbhc)
  825. {
  826. int hph_threshold, micbias_mv;
  827. micbias_mv = wcd_mbhc_get_micbias(mbhc);
  828. if (mbhc->cfg->hph_thr) {
  829. if (mbhc->cfg->micb_mv == micbias_mv)
  830. hph_threshold = mbhc->cfg->hph_thr;
  831. else
  832. hph_threshold = (mbhc->cfg->hph_thr *
  833. micbias_mv) / mbhc->cfg->micb_mv;
  834. } else {
  835. hph_threshold = ((WCD_MBHC_ADC_HPH_THRESHOLD_MV *
  836. micbias_mv) / WCD_MBHC_ADC_MICBIAS_MV);
  837. }
  838. return hph_threshold;
  839. }
  840. static void wcd_mbhc_adc_update_fsm_source(struct wcd_mbhc *mbhc,
  841. enum wcd_mbhc_plug_type plug_type)
  842. {
  843. bool micbias2 = false;
  844. switch (plug_type) {
  845. case MBHC_PLUG_TYPE_HEADPHONE:
  846. wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3);
  847. break;
  848. case MBHC_PLUG_TYPE_HEADSET:
  849. if (mbhc->mbhc_cb->micbias_enable_status)
  850. micbias2 = mbhc->mbhc_cb->micbias_enable_status(mbhc->component,
  851. MIC_BIAS_2);
  852. if (!mbhc->is_hs_recording && !micbias2)
  853. wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3);
  854. break;
  855. default:
  856. wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0);
  857. break;
  858. }
  859. }
  860. static void wcd_mbhc_bcs_enable(struct wcd_mbhc *mbhc, int plug_type, bool enable)
  861. {
  862. switch (plug_type) {
  863. case MBHC_PLUG_TYPE_HEADSET:
  864. case MBHC_PLUG_TYPE_HEADPHONE:
  865. if (mbhc->mbhc_cb->bcs_enable)
  866. mbhc->mbhc_cb->bcs_enable(mbhc->component, enable);
  867. break;
  868. default:
  869. break;
  870. }
  871. }
  872. static int wcd_mbhc_get_plug_from_adc(struct wcd_mbhc *mbhc, int adc_result)
  873. {
  874. enum wcd_mbhc_plug_type plug_type;
  875. u32 hph_thr, hs_thr;
  876. hs_thr = wcd_mbhc_adc_get_hs_thres(mbhc);
  877. hph_thr = wcd_mbhc_adc_get_hph_thres(mbhc);
  878. if (adc_result < hph_thr)
  879. plug_type = MBHC_PLUG_TYPE_HEADPHONE;
  880. else if (adc_result > hs_thr)
  881. plug_type = MBHC_PLUG_TYPE_HIGH_HPH;
  882. else
  883. plug_type = MBHC_PLUG_TYPE_HEADSET;
  884. return plug_type;
  885. }
  886. static int wcd_mbhc_get_spl_hs_thres(struct wcd_mbhc *mbhc)
  887. {
  888. int hs_threshold, micbias_mv;
  889. micbias_mv = wcd_mbhc_get_micbias(mbhc);
  890. if (mbhc->cfg->hs_thr && mbhc->cfg->micb_mv != WCD_MBHC_ADC_MICBIAS_MV) {
  891. if (mbhc->cfg->micb_mv == micbias_mv)
  892. hs_threshold = mbhc->cfg->hs_thr;
  893. else
  894. hs_threshold = (mbhc->cfg->hs_thr * micbias_mv) / mbhc->cfg->micb_mv;
  895. } else {
  896. hs_threshold = ((WCD_MBHC_ADC_HS_THRESHOLD_MV * micbias_mv) /
  897. WCD_MBHC_ADC_MICBIAS_MV);
  898. }
  899. return hs_threshold;
  900. }
  901. static bool wcd_mbhc_check_for_spl_headset(struct wcd_mbhc *mbhc)
  902. {
  903. bool is_spl_hs = false;
  904. int output_mv, hs_threshold, hph_threshold;
  905. if (!mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic)
  906. return false;
  907. /* Bump up MIC_BIAS2 to 2.7V */
  908. mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(mbhc->component, MIC_BIAS_2, true);
  909. usleep_range(10000, 10100);
  910. output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
  911. hs_threshold = wcd_mbhc_get_spl_hs_thres(mbhc);
  912. hph_threshold = wcd_mbhc_adc_get_hph_thres(mbhc);
  913. if (!(output_mv > hs_threshold || output_mv < hph_threshold))
  914. is_spl_hs = true;
  915. /* Back MIC_BIAS2 to 1.8v if the type is not special headset */
  916. if (!is_spl_hs) {
  917. mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(mbhc->component, MIC_BIAS_2, false);
  918. /* Add 10ms delay for micbias to settle */
  919. usleep_range(10000, 10100);
  920. }
  921. return is_spl_hs;
  922. }
  923. static void wcd_correct_swch_plug(struct work_struct *work)
  924. {
  925. struct wcd_mbhc *mbhc;
  926. struct snd_soc_component *component;
  927. enum wcd_mbhc_plug_type plug_type = MBHC_PLUG_TYPE_INVALID;
  928. unsigned long timeout;
  929. int pt_gnd_mic_swap_cnt = 0;
  930. int output_mv, cross_conn, hs_threshold, try = 0, micbias_mv;
  931. bool is_spl_hs = false;
  932. bool is_pa_on;
  933. int ret;
  934. mbhc = container_of(work, struct wcd_mbhc, correct_plug_swch);
  935. component = mbhc->component;
  936. ret = pm_runtime_get_sync(component->dev);
  937. if (ret < 0 && ret != -EACCES) {
  938. dev_err_ratelimited(component->dev,
  939. "pm_runtime_get_sync failed in %s, ret %d\n",
  940. __func__, ret);
  941. pm_runtime_put_noidle(component->dev);
  942. return;
  943. }
  944. micbias_mv = wcd_mbhc_get_micbias(mbhc);
  945. hs_threshold = wcd_mbhc_adc_get_hs_thres(mbhc);
  946. /* Mask ADC COMPLETE interrupt */
  947. disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr);
  948. /* Check for cross connection */
  949. do {
  950. cross_conn = wcd_check_cross_conn(mbhc);
  951. try++;
  952. } while (try < GND_MIC_SWAP_THRESHOLD);
  953. if (cross_conn > 0) {
  954. plug_type = MBHC_PLUG_TYPE_GND_MIC_SWAP;
  955. dev_err(mbhc->dev, "cross connection found, Plug type %d\n",
  956. plug_type);
  957. goto correct_plug_type;
  958. }
  959. /* Find plug type */
  960. output_mv = wcd_measure_adc_continuous(mbhc);
  961. plug_type = wcd_mbhc_get_plug_from_adc(mbhc, output_mv);
  962. /*
  963. * Report plug type if it is either headset or headphone
  964. * else start the 3 sec loop
  965. */
  966. switch (plug_type) {
  967. case MBHC_PLUG_TYPE_HEADPHONE:
  968. wcd_mbhc_find_plug_and_report(mbhc, plug_type);
  969. break;
  970. case MBHC_PLUG_TYPE_HEADSET:
  971. wcd_mbhc_find_plug_and_report(mbhc, plug_type);
  972. wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, 0);
  973. wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 0);
  974. wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 1);
  975. break;
  976. default:
  977. break;
  978. }
  979. correct_plug_type:
  980. /* Disable BCS slow insertion detection */
  981. wcd_mbhc_bcs_enable(mbhc, plug_type, false);
  982. timeout = jiffies + msecs_to_jiffies(HS_DETECT_PLUG_TIME_MS);
  983. while (!time_after(jiffies, timeout)) {
  984. if (mbhc->hs_detect_work_stop) {
  985. wcd_micbias_disable(mbhc);
  986. goto exit;
  987. }
  988. msleep(180);
  989. /*
  990. * Use ADC single mode to minimize the chance of missing out
  991. * btn press/release for HEADSET type during correct work.
  992. */
  993. output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
  994. plug_type = wcd_mbhc_get_plug_from_adc(mbhc, output_mv);
  995. is_pa_on = wcd_mbhc_read_field(mbhc, WCD_MBHC_HPH_PA_EN);
  996. if (output_mv > hs_threshold && !is_spl_hs) {
  997. is_spl_hs = wcd_mbhc_check_for_spl_headset(mbhc);
  998. output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
  999. if (is_spl_hs) {
  1000. hs_threshold *= wcd_mbhc_get_micbias(mbhc);
  1001. hs_threshold /= micbias_mv;
  1002. }
  1003. }
  1004. if ((output_mv <= hs_threshold) && !is_pa_on) {
  1005. /* Check for cross connection*/
  1006. cross_conn = wcd_check_cross_conn(mbhc);
  1007. if (cross_conn > 0) { /* cross-connection */
  1008. pt_gnd_mic_swap_cnt++;
  1009. if (pt_gnd_mic_swap_cnt < GND_MIC_SWAP_THRESHOLD)
  1010. continue;
  1011. else
  1012. plug_type = MBHC_PLUG_TYPE_GND_MIC_SWAP;
  1013. } else if (!cross_conn) { /* no cross connection */
  1014. pt_gnd_mic_swap_cnt = 0;
  1015. plug_type = wcd_mbhc_get_plug_from_adc(mbhc, output_mv);
  1016. continue;
  1017. } else /* Error if (cross_conn < 0) */
  1018. continue;
  1019. if (pt_gnd_mic_swap_cnt == GND_MIC_SWAP_THRESHOLD) {
  1020. /* US_EU gpio present, flip switch */
  1021. if (mbhc->cfg->swap_gnd_mic) {
  1022. if (mbhc->cfg->swap_gnd_mic(component, true))
  1023. continue;
  1024. }
  1025. }
  1026. }
  1027. /* cable is extension cable */
  1028. if (output_mv > hs_threshold || mbhc->force_linein)
  1029. plug_type = MBHC_PLUG_TYPE_HIGH_HPH;
  1030. }
  1031. wcd_mbhc_bcs_enable(mbhc, plug_type, true);
  1032. if (plug_type == MBHC_PLUG_TYPE_HIGH_HPH) {
  1033. if (is_spl_hs)
  1034. plug_type = MBHC_PLUG_TYPE_HEADSET;
  1035. else
  1036. wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_ISRC_EN, 1);
  1037. }
  1038. wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, 0);
  1039. wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 0);
  1040. wcd_mbhc_find_plug_and_report(mbhc, plug_type);
  1041. /*
  1042. * Set DETECTION_DONE bit for HEADSET
  1043. * so that btn press/release interrupt can be generated.
  1044. * For other plug type, clear the bit.
  1045. */
  1046. if (plug_type == MBHC_PLUG_TYPE_HEADSET)
  1047. wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 1);
  1048. else
  1049. wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 0);
  1050. if (mbhc->mbhc_cb->mbhc_micbias_control)
  1051. wcd_mbhc_adc_update_fsm_source(mbhc, plug_type);
  1052. exit:
  1053. if (mbhc->mbhc_cb->mbhc_micbias_control/* && !mbhc->micbias_enable*/)
  1054. mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2, MICB_DISABLE);
  1055. /*
  1056. * If plug type is corrected from special headset to headphone,
  1057. * clear the micbias enable flag, set micbias back to 1.8V and
  1058. * disable micbias.
  1059. */
  1060. if (plug_type == MBHC_PLUG_TYPE_HEADPHONE) {
  1061. wcd_micbias_disable(mbhc);
  1062. /*
  1063. * Enable ADC COMPLETE interrupt for HEADPHONE.
  1064. * Btn release may happen after the correct work, ADC COMPLETE
  1065. * interrupt needs to be captured to correct plug type.
  1066. */
  1067. enable_irq(mbhc->intr_ids->mbhc_hs_ins_intr);
  1068. }
  1069. if (mbhc->mbhc_cb->hph_pull_down_ctrl)
  1070. mbhc->mbhc_cb->hph_pull_down_ctrl(component, true);
  1071. pm_runtime_mark_last_busy(component->dev);
  1072. pm_runtime_put_autosuspend(component->dev);
  1073. }
  1074. static irqreturn_t wcd_mbhc_adc_hs_rem_irq(int irq, void *data)
  1075. {
  1076. struct wcd_mbhc *mbhc = data;
  1077. unsigned long timeout;
  1078. int adc_threshold, output_mv, retry = 0;
  1079. mutex_lock(&mbhc->lock);
  1080. timeout = jiffies + msecs_to_jiffies(WCD_FAKE_REMOVAL_MIN_PERIOD_MS);
  1081. adc_threshold = wcd_mbhc_adc_get_hs_thres(mbhc);
  1082. do {
  1083. retry++;
  1084. /*
  1085. * read output_mv every 10ms to look for
  1086. * any change in IN2_P
  1087. */
  1088. usleep_range(10000, 10100);
  1089. output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
  1090. /* Check for fake removal */
  1091. if ((output_mv <= adc_threshold) && retry > FAKE_REM_RETRY_ATTEMPTS)
  1092. goto exit;
  1093. } while (!time_after(jiffies, timeout));
  1094. /*
  1095. * ADC COMPLETE and ELEC_REM interrupts are both enabled for
  1096. * HEADPHONE, need to reject the ADC COMPLETE interrupt which
  1097. * follows ELEC_REM one when HEADPHONE is removed.
  1098. */
  1099. if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE)
  1100. mbhc->extn_cable_hph_rem = true;
  1101. wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 0);
  1102. wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, 0);
  1103. wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 0);
  1104. wcd_mbhc_elec_hs_report_unplug(mbhc);
  1105. wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0);
  1106. exit:
  1107. mutex_unlock(&mbhc->lock);
  1108. return IRQ_HANDLED;
  1109. }
  1110. static irqreturn_t wcd_mbhc_adc_hs_ins_irq(int irq, void *data)
  1111. {
  1112. struct wcd_mbhc *mbhc = data;
  1113. u8 clamp_state;
  1114. u8 clamp_retry = WCD_MBHC_FAKE_INS_RETRY;
  1115. /*
  1116. * ADC COMPLETE and ELEC_REM interrupts are both enabled for HEADPHONE,
  1117. * need to reject the ADC COMPLETE interrupt which follows ELEC_REM one
  1118. * when HEADPHONE is removed.
  1119. */
  1120. if (mbhc->extn_cable_hph_rem == true) {
  1121. mbhc->extn_cable_hph_rem = false;
  1122. return IRQ_HANDLED;
  1123. }
  1124. do {
  1125. clamp_state = wcd_mbhc_read_field(mbhc, WCD_MBHC_IN2P_CLAMP_STATE);
  1126. if (clamp_state)
  1127. return IRQ_HANDLED;
  1128. /*
  1129. * check clamp for 120ms but at 30ms chunks to leave
  1130. * room for other interrupts to be processed
  1131. */
  1132. usleep_range(30000, 30100);
  1133. } while (--clamp_retry);
  1134. /*
  1135. * If current plug is headphone then there is no chance to
  1136. * get ADC complete interrupt, so connected cable should be
  1137. * headset not headphone.
  1138. */
  1139. if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE) {
  1140. disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr);
  1141. wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 1);
  1142. wcd_mbhc_find_plug_and_report(mbhc, MBHC_PLUG_TYPE_HEADSET);
  1143. return IRQ_HANDLED;
  1144. }
  1145. return IRQ_HANDLED;
  1146. }
  1147. int wcd_mbhc_get_impedance(struct wcd_mbhc *mbhc, uint32_t *zl, uint32_t *zr)
  1148. {
  1149. *zl = mbhc->zl;
  1150. *zr = mbhc->zr;
  1151. if (*zl && *zr)
  1152. return 0;
  1153. else
  1154. return -EINVAL;
  1155. }
  1156. EXPORT_SYMBOL(wcd_mbhc_get_impedance);
  1157. void wcd_mbhc_set_hph_type(struct wcd_mbhc *mbhc, int hph_type)
  1158. {
  1159. mbhc->hph_type = hph_type;
  1160. }
  1161. EXPORT_SYMBOL(wcd_mbhc_set_hph_type);
  1162. int wcd_mbhc_get_hph_type(struct wcd_mbhc *mbhc)
  1163. {
  1164. return mbhc->hph_type;
  1165. }
  1166. EXPORT_SYMBOL(wcd_mbhc_get_hph_type);
  1167. int wcd_mbhc_start(struct wcd_mbhc *mbhc, struct wcd_mbhc_config *cfg,
  1168. struct snd_soc_jack *jack)
  1169. {
  1170. if (!mbhc || !cfg || !jack)
  1171. return -EINVAL;
  1172. mbhc->cfg = cfg;
  1173. mbhc->jack = jack;
  1174. return wcd_mbhc_initialise(mbhc);
  1175. }
  1176. EXPORT_SYMBOL(wcd_mbhc_start);
  1177. void wcd_mbhc_stop(struct wcd_mbhc *mbhc)
  1178. {
  1179. mbhc->current_plug = MBHC_PLUG_TYPE_NONE;
  1180. mbhc->hph_status = 0;
  1181. disable_irq_nosync(mbhc->intr_ids->hph_left_ocp);
  1182. disable_irq_nosync(mbhc->intr_ids->hph_right_ocp);
  1183. }
  1184. EXPORT_SYMBOL(wcd_mbhc_stop);
  1185. int wcd_dt_parse_mbhc_data(struct device *dev, struct wcd_mbhc_config *cfg)
  1186. {
  1187. struct device_node *np = dev->of_node;
  1188. int ret, i, microvolt;
  1189. if (of_property_read_bool(np, "qcom,hphl-jack-type-normally-closed"))
  1190. cfg->hphl_swh = false;
  1191. else
  1192. cfg->hphl_swh = true;
  1193. if (of_property_read_bool(np, "qcom,ground-jack-type-normally-closed"))
  1194. cfg->gnd_swh = false;
  1195. else
  1196. cfg->gnd_swh = true;
  1197. ret = of_property_read_u32(np, "qcom,mbhc-headset-vthreshold-microvolt",
  1198. &microvolt);
  1199. if (ret)
  1200. dev_dbg(dev, "missing qcom,mbhc-hs-mic-max-vthreshold--microvolt in dt node\n");
  1201. else
  1202. cfg->hs_thr = microvolt/1000;
  1203. ret = of_property_read_u32(np, "qcom,mbhc-headphone-vthreshold-microvolt",
  1204. &microvolt);
  1205. if (ret)
  1206. dev_dbg(dev, "missing qcom,mbhc-hs-mic-min-vthreshold-microvolt entry\n");
  1207. else
  1208. cfg->hph_thr = microvolt/1000;
  1209. ret = of_property_read_u32_array(np,
  1210. "qcom,mbhc-buttons-vthreshold-microvolt",
  1211. &cfg->btn_high[0],
  1212. WCD_MBHC_DEF_BUTTONS);
  1213. if (ret)
  1214. dev_err(dev, "missing qcom,mbhc-buttons-vthreshold-microvolt entry\n");
  1215. for (i = 0; i < WCD_MBHC_DEF_BUTTONS; i++) {
  1216. if (ret) /* default voltage */
  1217. cfg->btn_high[i] = 500000;
  1218. else
  1219. /* Micro to Milli Volts */
  1220. cfg->btn_high[i] = cfg->btn_high[i]/1000;
  1221. }
  1222. return 0;
  1223. }
  1224. EXPORT_SYMBOL(wcd_dt_parse_mbhc_data);
  1225. struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component,
  1226. const struct wcd_mbhc_cb *mbhc_cb,
  1227. const struct wcd_mbhc_intr *intr_ids,
  1228. struct wcd_mbhc_field *fields,
  1229. bool impedance_det_en)
  1230. {
  1231. struct device *dev = component->dev;
  1232. struct wcd_mbhc *mbhc;
  1233. int ret;
  1234. if (!intr_ids || !fields || !mbhc_cb || !mbhc_cb->mbhc_bias || !mbhc_cb->set_btn_thr) {
  1235. dev_err(dev, "%s: Insufficient mbhc configuration\n", __func__);
  1236. return ERR_PTR(-EINVAL);
  1237. }
  1238. mbhc = kzalloc(sizeof(*mbhc), GFP_KERNEL);
  1239. if (!mbhc)
  1240. return ERR_PTR(-ENOMEM);
  1241. mbhc->component = component;
  1242. mbhc->dev = dev;
  1243. mbhc->intr_ids = intr_ids;
  1244. mbhc->mbhc_cb = mbhc_cb;
  1245. mbhc->fields = fields;
  1246. mbhc->mbhc_detection_logic = WCD_DETECTION_ADC;
  1247. if (mbhc_cb->compute_impedance)
  1248. mbhc->impedance_detect = impedance_det_en;
  1249. INIT_DELAYED_WORK(&mbhc->mbhc_btn_dwork, wcd_btn_long_press_fn);
  1250. mutex_init(&mbhc->lock);
  1251. INIT_WORK(&mbhc->correct_plug_swch, wcd_correct_swch_plug);
  1252. ret = request_threaded_irq(mbhc->intr_ids->mbhc_sw_intr, NULL,
  1253. wcd_mbhc_mech_plug_detect_irq,
  1254. IRQF_ONESHOT | IRQF_TRIGGER_RISING,
  1255. "mbhc sw intr", mbhc);
  1256. if (ret)
  1257. goto err_free_mbhc;
  1258. ret = request_threaded_irq(mbhc->intr_ids->mbhc_btn_press_intr, NULL,
  1259. wcd_mbhc_btn_press_handler,
  1260. IRQF_ONESHOT | IRQF_TRIGGER_RISING,
  1261. "Button Press detect", mbhc);
  1262. if (ret)
  1263. goto err_free_sw_intr;
  1264. ret = request_threaded_irq(mbhc->intr_ids->mbhc_btn_release_intr, NULL,
  1265. wcd_mbhc_btn_release_handler,
  1266. IRQF_ONESHOT | IRQF_TRIGGER_RISING,
  1267. "Button Release detect", mbhc);
  1268. if (ret)
  1269. goto err_free_btn_press_intr;
  1270. ret = request_threaded_irq(mbhc->intr_ids->mbhc_hs_ins_intr, NULL,
  1271. wcd_mbhc_adc_hs_ins_irq,
  1272. IRQF_ONESHOT | IRQF_TRIGGER_RISING,
  1273. "Elect Insert", mbhc);
  1274. if (ret)
  1275. goto err_free_btn_release_intr;
  1276. disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr);
  1277. ret = request_threaded_irq(mbhc->intr_ids->mbhc_hs_rem_intr, NULL,
  1278. wcd_mbhc_adc_hs_rem_irq,
  1279. IRQF_ONESHOT | IRQF_TRIGGER_RISING,
  1280. "Elect Remove", mbhc);
  1281. if (ret)
  1282. goto err_free_hs_ins_intr;
  1283. disable_irq_nosync(mbhc->intr_ids->mbhc_hs_rem_intr);
  1284. ret = request_threaded_irq(mbhc->intr_ids->hph_left_ocp, NULL,
  1285. wcd_mbhc_hphl_ocp_irq,
  1286. IRQF_ONESHOT | IRQF_TRIGGER_RISING,
  1287. "HPH_L OCP detect", mbhc);
  1288. if (ret)
  1289. goto err_free_hs_rem_intr;
  1290. ret = request_threaded_irq(mbhc->intr_ids->hph_right_ocp, NULL,
  1291. wcd_mbhc_hphr_ocp_irq,
  1292. IRQF_ONESHOT | IRQF_TRIGGER_RISING,
  1293. "HPH_R OCP detect", mbhc);
  1294. if (ret)
  1295. goto err_free_hph_left_ocp;
  1296. return mbhc;
  1297. err_free_hph_left_ocp:
  1298. free_irq(mbhc->intr_ids->hph_left_ocp, mbhc);
  1299. err_free_hs_rem_intr:
  1300. free_irq(mbhc->intr_ids->mbhc_hs_rem_intr, mbhc);
  1301. err_free_hs_ins_intr:
  1302. free_irq(mbhc->intr_ids->mbhc_hs_ins_intr, mbhc);
  1303. err_free_btn_release_intr:
  1304. free_irq(mbhc->intr_ids->mbhc_btn_release_intr, mbhc);
  1305. err_free_btn_press_intr:
  1306. free_irq(mbhc->intr_ids->mbhc_btn_press_intr, mbhc);
  1307. err_free_sw_intr:
  1308. free_irq(mbhc->intr_ids->mbhc_sw_intr, mbhc);
  1309. err_free_mbhc:
  1310. kfree(mbhc);
  1311. dev_err(dev, "Failed to request mbhc interrupts %d\n", ret);
  1312. return ERR_PTR(ret);
  1313. }
  1314. EXPORT_SYMBOL(wcd_mbhc_init);
  1315. void wcd_mbhc_deinit(struct wcd_mbhc *mbhc)
  1316. {
  1317. free_irq(mbhc->intr_ids->hph_right_ocp, mbhc);
  1318. free_irq(mbhc->intr_ids->hph_left_ocp, mbhc);
  1319. free_irq(mbhc->intr_ids->mbhc_hs_rem_intr, mbhc);
  1320. free_irq(mbhc->intr_ids->mbhc_hs_ins_intr, mbhc);
  1321. free_irq(mbhc->intr_ids->mbhc_btn_release_intr, mbhc);
  1322. free_irq(mbhc->intr_ids->mbhc_btn_press_intr, mbhc);
  1323. free_irq(mbhc->intr_ids->mbhc_sw_intr, mbhc);
  1324. mutex_lock(&mbhc->lock);
  1325. wcd_cancel_hs_detect_plug(mbhc, &mbhc->correct_plug_swch);
  1326. mutex_unlock(&mbhc->lock);
  1327. kfree(mbhc);
  1328. }
  1329. EXPORT_SYMBOL(wcd_mbhc_deinit);
  1330. static int __init mbhc_init(void)
  1331. {
  1332. return 0;
  1333. }
  1334. static void __exit mbhc_exit(void)
  1335. {
  1336. }
  1337. module_init(mbhc_init);
  1338. module_exit(mbhc_exit);
  1339. MODULE_DESCRIPTION("wcd MBHC v2 module");
  1340. MODULE_LICENSE("GPL");