extcon-arizona.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917
  1. /*
  2. * extcon-arizona.c - Extcon driver Wolfson Arizona devices
  3. *
  4. * Copyright (C) 2012 Wolfson Microelectronics plc
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include <linux/kernel.h>
  17. #include <linux/module.h>
  18. #include <linux/i2c.h>
  19. #include <linux/slab.h>
  20. #include <linux/interrupt.h>
  21. #include <linux/err.h>
  22. #include <linux/gpio.h>
  23. #include <linux/input.h>
  24. #include <linux/platform_device.h>
  25. #include <linux/pm_runtime.h>
  26. #include <linux/regulator/consumer.h>
  27. #include <linux/extcon.h>
  28. #include <linux/mfd/arizona/core.h>
  29. #include <linux/mfd/arizona/pdata.h>
  30. #include <linux/mfd/arizona/registers.h>
  31. #define ARIZONA_DEFAULT_HP 32
  32. #define ARIZONA_NUM_BUTTONS 6
  33. #define ARIZONA_ACCDET_MODE_MIC 0
  34. #define ARIZONA_ACCDET_MODE_HPL 1
  35. #define ARIZONA_ACCDET_MODE_HPR 2
  36. struct arizona_extcon_info {
  37. struct device *dev;
  38. struct arizona *arizona;
  39. struct mutex lock;
  40. struct regulator *micvdd;
  41. struct input_dev *input;
  42. int micd_mode;
  43. const struct arizona_micd_config *micd_modes;
  44. int micd_num_modes;
  45. bool micd_reva;
  46. bool micd_clamp;
  47. bool hpdet_active;
  48. bool mic;
  49. bool detecting;
  50. int jack_flips;
  51. int hpdet_ip;
  52. struct extcon_dev edev;
  53. };
  54. static const struct arizona_micd_config micd_default_modes[] = {
  55. { ARIZONA_ACCDET_SRC, 1 << ARIZONA_MICD_BIAS_SRC_SHIFT, 0 },
  56. { 0, 2 << ARIZONA_MICD_BIAS_SRC_SHIFT, 1 },
  57. };
  58. static struct {
  59. u16 status;
  60. int report;
  61. } arizona_lvl_to_key[ARIZONA_NUM_BUTTONS] = {
  62. { 0x1, BTN_0 },
  63. { 0x2, BTN_1 },
  64. { 0x4, BTN_2 },
  65. { 0x8, BTN_3 },
  66. { 0x10, BTN_4 },
  67. { 0x20, BTN_5 },
  68. };
  69. #define ARIZONA_CABLE_MECHANICAL 0
  70. #define ARIZONA_CABLE_MICROPHONE 1
  71. #define ARIZONA_CABLE_HEADPHONE 2
  72. #define ARIZONA_CABLE_LINEOUT 3
  73. static const char *arizona_cable[] = {
  74. "Mechanical",
  75. "Microphone",
  76. "Headphone",
  77. "Line-out",
  78. NULL,
  79. };
  80. static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode)
  81. {
  82. struct arizona *arizona = info->arizona;
  83. if (arizona->pdata.micd_pol_gpio > 0)
  84. gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio,
  85. info->micd_modes[mode].gpio);
  86. regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
  87. ARIZONA_MICD_BIAS_SRC_MASK,
  88. info->micd_modes[mode].bias);
  89. regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
  90. ARIZONA_ACCDET_SRC, info->micd_modes[mode].src);
  91. info->micd_mode = mode;
  92. dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode);
  93. }
  94. static struct {
  95. unsigned int factor_a;
  96. unsigned int factor_b;
  97. } arizona_hpdet_b_ranges[] = {
  98. { 5528, 362464 },
  99. { 11084, 6186851 },
  100. { 11065, 65460395 },
  101. };
  102. static struct {
  103. int min;
  104. int max;
  105. } arizona_hpdet_c_ranges[] = {
  106. { 0, 30 },
  107. { 8, 100 },
  108. { 100, 1000 },
  109. { 1000, 10000 },
  110. };
  111. static int arizona_hpdet_read(struct arizona_extcon_info *info)
  112. {
  113. struct arizona *arizona = info->arizona;
  114. unsigned int val, range;
  115. int ret;
  116. ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val);
  117. if (ret != 0) {
  118. dev_err(arizona->dev, "Failed to read HPDET status: %d\n",
  119. ret);
  120. return ret;
  121. }
  122. switch (info->hpdet_ip) {
  123. case 0:
  124. if (!(val & ARIZONA_HP_DONE)) {
  125. dev_err(arizona->dev, "HPDET did not complete: %x\n",
  126. val);
  127. val = ARIZONA_DEFAULT_HP;
  128. }
  129. val &= ARIZONA_HP_LVL_MASK;
  130. break;
  131. case 1:
  132. if (!(val & ARIZONA_HP_DONE_B)) {
  133. dev_err(arizona->dev, "HPDET did not complete: %x\n",
  134. val);
  135. return ARIZONA_DEFAULT_HP;
  136. }
  137. ret = regmap_read(arizona->regmap, ARIZONA_HP_DACVAL, &val);
  138. if (ret != 0) {
  139. dev_err(arizona->dev, "Failed to read HP value: %d\n",
  140. ret);
  141. return ARIZONA_DEFAULT_HP;
  142. }
  143. regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
  144. &range);
  145. range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
  146. >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
  147. if (range < ARRAY_SIZE(arizona_hpdet_b_ranges) - 1 &&
  148. (val < 100 || val > 0x3fb)) {
  149. range++;
  150. dev_dbg(arizona->dev, "Moving to HPDET range %d\n",
  151. range);
  152. regmap_update_bits(arizona->regmap,
  153. ARIZONA_HEADPHONE_DETECT_1,
  154. ARIZONA_HP_IMPEDANCE_RANGE_MASK,
  155. range <<
  156. ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
  157. return -EAGAIN;
  158. }
  159. /* If we go out of range report top of range */
  160. if (val < 100 || val > 0x3fb) {
  161. dev_dbg(arizona->dev, "Measurement out of range\n");
  162. return 10000;
  163. }
  164. dev_dbg(arizona->dev, "HPDET read %d in range %d\n",
  165. val, range);
  166. val = arizona_hpdet_b_ranges[range].factor_b
  167. / ((val * 100) -
  168. arizona_hpdet_b_ranges[range].factor_a);
  169. break;
  170. default:
  171. dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n",
  172. info->hpdet_ip);
  173. case 2:
  174. if (!(val & ARIZONA_HP_DONE_B)) {
  175. dev_err(arizona->dev, "HPDET did not complete: %x\n",
  176. val);
  177. return ARIZONA_DEFAULT_HP;
  178. }
  179. val &= ARIZONA_HP_LVL_B_MASK;
  180. regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
  181. &range);
  182. range = (range & ARIZONA_HP_IMPEDANCE_RANGE_MASK)
  183. >> ARIZONA_HP_IMPEDANCE_RANGE_SHIFT;
  184. /* Skip up or down a range? */
  185. if (range && (val < arizona_hpdet_c_ranges[range].min)) {
  186. range--;
  187. dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",
  188. arizona_hpdet_c_ranges[range].min,
  189. arizona_hpdet_c_ranges[range].max);
  190. regmap_update_bits(arizona->regmap,
  191. ARIZONA_HEADPHONE_DETECT_1,
  192. ARIZONA_HP_IMPEDANCE_RANGE_MASK,
  193. range <<
  194. ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
  195. return -EAGAIN;
  196. }
  197. if (range < ARRAY_SIZE(arizona_hpdet_c_ranges) - 1 &&
  198. (val >= arizona_hpdet_c_ranges[range].max)) {
  199. range++;
  200. dev_dbg(arizona->dev, "Moving to HPDET range %d-%d\n",
  201. arizona_hpdet_c_ranges[range].min,
  202. arizona_hpdet_c_ranges[range].max);
  203. regmap_update_bits(arizona->regmap,
  204. ARIZONA_HEADPHONE_DETECT_1,
  205. ARIZONA_HP_IMPEDANCE_RANGE_MASK,
  206. range <<
  207. ARIZONA_HP_IMPEDANCE_RANGE_SHIFT);
  208. return -EAGAIN;
  209. }
  210. }
  211. dev_dbg(arizona->dev, "HP impedance %d ohms\n", val);
  212. return val;
  213. }
  214. static irqreturn_t arizona_hpdet_irq(int irq, void *data)
  215. {
  216. struct arizona_extcon_info *info = data;
  217. struct arizona *arizona = info->arizona;
  218. int report = ARIZONA_CABLE_HEADPHONE;
  219. int ret;
  220. mutex_lock(&info->lock);
  221. /* If we got a spurious IRQ for some reason then ignore it */
  222. if (!info->hpdet_active) {
  223. dev_warn(arizona->dev, "Spurious HPDET IRQ\n");
  224. mutex_unlock(&info->lock);
  225. return IRQ_NONE;
  226. }
  227. /* If the cable was removed while measuring ignore the result */
  228. ret = extcon_get_cable_state_(&info->edev, ARIZONA_CABLE_MECHANICAL);
  229. if (ret < 0) {
  230. dev_err(arizona->dev, "Failed to check cable state: %d\n",
  231. ret);
  232. goto out;
  233. } else if (!ret) {
  234. dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n");
  235. goto done;
  236. }
  237. ret = arizona_hpdet_read(info);
  238. if (ret == -EAGAIN) {
  239. goto out;
  240. } else if (ret < 0) {
  241. goto done;
  242. }
  243. /* Reset back to starting range */
  244. regmap_update_bits(arizona->regmap,
  245. ARIZONA_HEADPHONE_DETECT_1,
  246. ARIZONA_HP_IMPEDANCE_RANGE_MASK, 0);
  247. /* Report high impedence cables as line outputs */
  248. if (ret >= 5000)
  249. report = ARIZONA_CABLE_LINEOUT;
  250. else
  251. report = ARIZONA_CABLE_HEADPHONE;
  252. ret = extcon_set_cable_state_(&info->edev, report, true);
  253. if (ret != 0)
  254. dev_err(arizona->dev, "Failed to report HP/line: %d\n",
  255. ret);
  256. ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000, 0);
  257. if (ret != 0)
  258. dev_warn(arizona->dev, "Failed to undo magic: %d\n", ret);
  259. ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000, 0);
  260. if (ret != 0)
  261. dev_warn(arizona->dev, "Failed to undo magic: %d\n", ret);
  262. done:
  263. regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
  264. ARIZONA_HP_POLL, 0);
  265. /* Revert back to MICDET mode */
  266. regmap_update_bits(arizona->regmap,
  267. ARIZONA_ACCESSORY_DETECT_MODE_1,
  268. ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
  269. /* If we have a mic then reenable MICDET */
  270. if (info->mic)
  271. arizona_start_mic(info);
  272. if (info->hpdet_active) {
  273. pm_runtime_put_autosuspend(info->dev);
  274. info->hpdet_active = false;
  275. }
  276. out:
  277. mutex_unlock(&info->lock);
  278. return IRQ_HANDLED;
  279. }
  280. static void arizona_identify_headphone(struct arizona_extcon_info *info)
  281. {
  282. struct arizona *arizona = info->arizona;
  283. int ret;
  284. dev_dbg(arizona->dev, "Starting HPDET\n");
  285. /* Make sure we keep the device enabled during the measurement */
  286. pm_runtime_get(info->dev);
  287. info->hpdet_active = true;
  288. if (info->mic)
  289. arizona_stop_mic(info);
  290. ret = regmap_update_bits(arizona->regmap, 0x225, 0x4000, 0x4000);
  291. if (ret != 0)
  292. dev_warn(arizona->dev, "Failed to do magic: %d\n", ret);
  293. ret = regmap_update_bits(arizona->regmap, 0x226, 0x4000, 0x4000);
  294. if (ret != 0)
  295. dev_warn(arizona->dev, "Failed to do magic: %d\n", ret);
  296. ret = regmap_update_bits(arizona->regmap,
  297. ARIZONA_ACCESSORY_DETECT_MODE_1,
  298. ARIZONA_ACCDET_MODE_MASK,
  299. ARIZONA_ACCDET_MODE_HPL);
  300. if (ret != 0) {
  301. dev_err(arizona->dev, "Failed to set HPDETL mode: %d\n", ret);
  302. goto err;
  303. }
  304. ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1,
  305. ARIZONA_HP_POLL, ARIZONA_HP_POLL);
  306. if (ret != 0) {
  307. dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n",
  308. ret);
  309. goto err;
  310. }
  311. return;
  312. err:
  313. regmap_update_bits(arizona->regmap, ARIZONA_ACCESSORY_DETECT_MODE_1,
  314. ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
  315. /* Just report headphone */
  316. ret = extcon_update_state(&info->edev,
  317. 1 << ARIZONA_CABLE_HEADPHONE,
  318. 1 << ARIZONA_CABLE_HEADPHONE);
  319. if (ret != 0)
  320. dev_err(arizona->dev, "Failed to report headphone: %d\n", ret);
  321. if (info->mic)
  322. arizona_start_mic(info);
  323. info->hpdet_active = false;
  324. }
  325. }
  326. info->hpdet_active = false;
  327. }
  328. static void arizona_start_mic(struct arizona_extcon_info *info)
  329. {
  330. struct arizona *arizona = info->arizona;
  331. bool change;
  332. int ret;
  333. info->detecting = true;
  334. info->mic = false;
  335. info->jack_flips = 0;
  336. /* Microphone detection can't use idle mode */
  337. pm_runtime_get(info->dev);
  338. ret = regulator_enable(info->micvdd);
  339. if (ret != 0) {
  340. dev_err(arizona->dev, "Failed to enable MICVDD: %d\n",
  341. ret);
  342. }
  343. if (info->micd_reva) {
  344. regmap_write(arizona->regmap, 0x80, 0x3);
  345. regmap_write(arizona->regmap, 0x294, 0);
  346. regmap_write(arizona->regmap, 0x80, 0x0);
  347. }
  348. regmap_update_bits(arizona->regmap,
  349. ARIZONA_ACCESSORY_DETECT_MODE_1,
  350. ARIZONA_ACCDET_MODE_MASK, ARIZONA_ACCDET_MODE_MIC);
  351. regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
  352. ARIZONA_MICD_ENA, ARIZONA_MICD_ENA,
  353. &change);
  354. if (!change) {
  355. regulator_disable(info->micvdd);
  356. pm_runtime_put_autosuspend(info->dev);
  357. }
  358. }
  359. static void arizona_stop_mic(struct arizona_extcon_info *info)
  360. {
  361. struct arizona *arizona = info->arizona;
  362. bool change;
  363. regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1,
  364. ARIZONA_MICD_ENA, 0,
  365. &change);
  366. if (info->micd_reva) {
  367. regmap_write(arizona->regmap, 0x80, 0x3);
  368. regmap_write(arizona->regmap, 0x294, 2);
  369. regmap_write(arizona->regmap, 0x80, 0x0);
  370. }
  371. if (change) {
  372. regulator_disable(info->micvdd);
  373. pm_runtime_mark_last_busy(info->dev);
  374. pm_runtime_put_autosuspend(info->dev);
  375. }
  376. }
  377. static irqreturn_t arizona_micdet(int irq, void *data)
  378. {
  379. struct arizona_extcon_info *info = data;
  380. struct arizona *arizona = info->arizona;
  381. unsigned int val, lvl;
  382. int ret, i;
  383. mutex_lock(&info->lock);
  384. ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val);
  385. if (ret != 0) {
  386. dev_err(arizona->dev, "Failed to read MICDET: %d\n", ret);
  387. mutex_unlock(&info->lock);
  388. return IRQ_NONE;
  389. }
  390. dev_dbg(arizona->dev, "MICDET: %x\n", val);
  391. if (!(val & ARIZONA_MICD_VALID)) {
  392. dev_warn(arizona->dev, "Microphone detection state invalid\n");
  393. mutex_unlock(&info->lock);
  394. return IRQ_NONE;
  395. }
  396. /* Due to jack detect this should never happen */
  397. if (!(val & ARIZONA_MICD_STS)) {
  398. dev_warn(arizona->dev, "Detected open circuit\n");
  399. info->detecting = false;
  400. goto handled;
  401. }
  402. /* If we got a high impedence we should have a headset, report it. */
  403. if (info->detecting && (val & 0x400)) {
  404. arizona_identify_headphone(info);
  405. ret = extcon_update_state(&info->edev,
  406. 1 << ARIZONA_CABLE_MICROPHONE,
  407. 1 << ARIZONA_CABLE_MICROPHONE);
  408. if (ret != 0)
  409. dev_err(arizona->dev, "Headset report failed: %d\n",
  410. ret);
  411. info->mic = true;
  412. info->detecting = false;
  413. goto handled;
  414. }
  415. /* If we detected a lower impedence during initial startup
  416. * then we probably have the wrong polarity, flip it. Don't
  417. * do this for the lowest impedences to speed up detection of
  418. * plain headphones. If both polarities report a low
  419. * impedence then give up and report headphones.
  420. */
  421. if (info->detecting && (val & 0x3f8)) {
  422. info->jack_flips++;
  423. if (info->jack_flips >= info->micd_num_modes) {
  424. dev_dbg(arizona->dev, "Detected HP/line\n");
  425. arizona_identify_headphone(info);
  426. info->detecting = false;
  427. arizona_stop_mic(info);
  428. } else {
  429. info->micd_mode++;
  430. if (info->micd_mode == info->micd_num_modes)
  431. info->micd_mode = 0;
  432. arizona_extcon_set_mode(info, info->micd_mode);
  433. info->jack_flips++;
  434. }
  435. goto handled;
  436. }
  437. /*
  438. * If we're still detecting and we detect a short then we've
  439. * got a headphone. Otherwise it's a button press.
  440. */
  441. if (val & 0x3fc) {
  442. if (info->mic) {
  443. dev_dbg(arizona->dev, "Mic button detected\n");
  444. lvl = val & ARIZONA_MICD_LVL_MASK;
  445. lvl >>= ARIZONA_MICD_LVL_SHIFT;
  446. for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
  447. if (lvl & arizona_lvl_to_key[i].status)
  448. input_report_key(info->input,
  449. arizona_lvl_to_key[i].report,
  450. 1);
  451. input_sync(info->input);
  452. } else if (info->detecting) {
  453. dev_dbg(arizona->dev, "Headphone detected\n");
  454. info->detecting = false;
  455. arizona_stop_mic(info);
  456. arizona_identify_headphone(info);
  457. } else {
  458. dev_warn(arizona->dev, "Button with no mic: %x\n",
  459. val);
  460. }
  461. } else {
  462. dev_dbg(arizona->dev, "Mic button released\n");
  463. for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
  464. input_report_key(info->input,
  465. arizona_lvl_to_key[i].report, 0);
  466. input_sync(info->input);
  467. }
  468. handled:
  469. pm_runtime_mark_last_busy(info->dev);
  470. mutex_unlock(&info->lock);
  471. return IRQ_HANDLED;
  472. }
  473. static irqreturn_t arizona_jackdet(int irq, void *data)
  474. {
  475. struct arizona_extcon_info *info = data;
  476. struct arizona *arizona = info->arizona;
  477. unsigned int val, present, mask;
  478. int ret, i;
  479. pm_runtime_get_sync(info->dev);
  480. mutex_lock(&info->lock);
  481. if (arizona->pdata.jd_gpio5) {
  482. mask = ARIZONA_MICD_CLAMP_STS;
  483. present = 0;
  484. } else {
  485. mask = ARIZONA_JD1_STS;
  486. present = ARIZONA_JD1_STS;
  487. }
  488. ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val);
  489. if (ret != 0) {
  490. dev_err(arizona->dev, "Failed to read jackdet status: %d\n",
  491. ret);
  492. mutex_unlock(&info->lock);
  493. pm_runtime_put_autosuspend(info->dev);
  494. return IRQ_NONE;
  495. }
  496. if ((val & mask) == present) {
  497. dev_dbg(arizona->dev, "Detected jack\n");
  498. ret = extcon_set_cable_state_(&info->edev,
  499. ARIZONA_CABLE_MECHANICAL, true);
  500. if (ret != 0)
  501. dev_err(arizona->dev, "Mechanical report failed: %d\n",
  502. ret);
  503. arizona_start_mic(info);
  504. } else {
  505. dev_dbg(arizona->dev, "Detected jack removal\n");
  506. arizona_stop_mic(info);
  507. for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
  508. input_report_key(info->input,
  509. arizona_lvl_to_key[i].report, 0);
  510. input_sync(info->input);
  511. ret = extcon_update_state(&info->edev, 0xffffffff, 0);
  512. if (ret != 0)
  513. dev_err(arizona->dev, "Removal report failed: %d\n",
  514. ret);
  515. }
  516. mutex_unlock(&info->lock);
  517. pm_runtime_mark_last_busy(info->dev);
  518. pm_runtime_put_autosuspend(info->dev);
  519. return IRQ_HANDLED;
  520. }
  521. static int arizona_extcon_probe(struct platform_device *pdev)
  522. {
  523. struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
  524. struct arizona_pdata *pdata;
  525. struct arizona_extcon_info *info;
  526. int jack_irq_fall, jack_irq_rise;
  527. int ret, mode, i;
  528. pdata = dev_get_platdata(arizona->dev);
  529. info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
  530. if (!info) {
  531. dev_err(&pdev->dev, "Failed to allocate memory\n");
  532. ret = -ENOMEM;
  533. goto err;
  534. }
  535. info->micvdd = devm_regulator_get(arizona->dev, "MICVDD");
  536. if (IS_ERR(info->micvdd)) {
  537. ret = PTR_ERR(info->micvdd);
  538. dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret);
  539. goto err;
  540. }
  541. mutex_init(&info->lock);
  542. info->arizona = arizona;
  543. info->dev = &pdev->dev;
  544. info->detecting = true;
  545. platform_set_drvdata(pdev, info);
  546. switch (arizona->type) {
  547. case WM5102:
  548. switch (arizona->rev) {
  549. case 0:
  550. info->micd_reva = true;
  551. break;
  552. default:
  553. info->micd_clamp = true;
  554. info->hpdet_ip = 1;
  555. break;
  556. }
  557. break;
  558. default:
  559. break;
  560. }
  561. info->edev.name = "Headset Jack";
  562. info->edev.supported_cable = arizona_cable;
  563. ret = extcon_dev_register(&info->edev, arizona->dev);
  564. if (ret < 0) {
  565. dev_err(arizona->dev, "extcon_dev_register() failed: %d\n",
  566. ret);
  567. goto err;
  568. }
  569. if (pdata->num_micd_configs) {
  570. info->micd_modes = pdata->micd_configs;
  571. info->micd_num_modes = pdata->num_micd_configs;
  572. } else {
  573. info->micd_modes = micd_default_modes;
  574. info->micd_num_modes = ARRAY_SIZE(micd_default_modes);
  575. }
  576. if (arizona->pdata.micd_pol_gpio > 0) {
  577. if (info->micd_modes[0].gpio)
  578. mode = GPIOF_OUT_INIT_HIGH;
  579. else
  580. mode = GPIOF_OUT_INIT_LOW;
  581. ret = devm_gpio_request_one(&pdev->dev,
  582. arizona->pdata.micd_pol_gpio,
  583. mode,
  584. "MICD polarity");
  585. if (ret != 0) {
  586. dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
  587. arizona->pdata.micd_pol_gpio, ret);
  588. goto err_register;
  589. }
  590. }
  591. if (arizona->pdata.micd_bias_start_time)
  592. regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
  593. ARIZONA_MICD_BIAS_STARTTIME_MASK,
  594. arizona->pdata.micd_bias_start_time
  595. << ARIZONA_MICD_BIAS_STARTTIME_SHIFT);
  596. /*
  597. * If we have a clamp use it, activating in conjunction with
  598. * GPIO5 if that is connected for jack detect operation.
  599. */
  600. if (info->micd_clamp) {
  601. if (arizona->pdata.jd_gpio5) {
  602. /* Put the GPIO into input mode */
  603. regmap_write(arizona->regmap, ARIZONA_GPIO5_CTRL,
  604. 0xc101);
  605. regmap_update_bits(arizona->regmap,
  606. ARIZONA_MICD_CLAMP_CONTROL,
  607. ARIZONA_MICD_CLAMP_MODE_MASK, 0x9);
  608. } else {
  609. regmap_update_bits(arizona->regmap,
  610. ARIZONA_MICD_CLAMP_CONTROL,
  611. ARIZONA_MICD_CLAMP_MODE_MASK, 0x4);
  612. }
  613. regmap_update_bits(arizona->regmap,
  614. ARIZONA_JACK_DETECT_DEBOUNCE,
  615. ARIZONA_MICD_CLAMP_DB,
  616. ARIZONA_MICD_CLAMP_DB);
  617. }
  618. arizona_extcon_set_mode(info, 0);
  619. info->input = devm_input_allocate_device(&pdev->dev);
  620. if (!info->input) {
  621. dev_err(arizona->dev, "Can't allocate input dev\n");
  622. ret = -ENOMEM;
  623. goto err_register;
  624. }
  625. for (i = 0; i < ARIZONA_NUM_BUTTONS; i++)
  626. input_set_capability(info->input, EV_KEY,
  627. arizona_lvl_to_key[i].report);
  628. info->input->name = "Headset";
  629. info->input->phys = "arizona/extcon";
  630. info->input->dev.parent = &pdev->dev;
  631. pm_runtime_enable(&pdev->dev);
  632. pm_runtime_idle(&pdev->dev);
  633. pm_runtime_get_sync(&pdev->dev);
  634. if (arizona->pdata.jd_gpio5) {
  635. jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
  636. jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
  637. } else {
  638. jack_irq_rise = ARIZONA_IRQ_JD_RISE;
  639. jack_irq_fall = ARIZONA_IRQ_JD_FALL;
  640. }
  641. ret = arizona_request_irq(arizona, jack_irq_rise,
  642. "JACKDET rise", arizona_jackdet, info);
  643. if (ret != 0) {
  644. dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
  645. ret);
  646. goto err_input;
  647. }
  648. ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
  649. if (ret != 0) {
  650. dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n",
  651. ret);
  652. goto err_rise;
  653. }
  654. ret = arizona_request_irq(arizona, jack_irq_fall,
  655. "JACKDET fall", arizona_jackdet, info);
  656. if (ret != 0) {
  657. dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret);
  658. goto err_rise_wake;
  659. }
  660. ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1);
  661. if (ret != 0) {
  662. dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n",
  663. ret);
  664. goto err_fall;
  665. }
  666. ret = arizona_request_irq(arizona, ARIZONA_IRQ_MICDET,
  667. "MICDET", arizona_micdet, info);
  668. if (ret != 0) {
  669. dev_err(&pdev->dev, "Failed to get MICDET IRQ: %d\n", ret);
  670. goto err_fall_wake;
  671. }
  672. ret = arizona_request_irq(arizona, ARIZONA_IRQ_HPDET,
  673. "HPDET", arizona_hpdet_irq, info);
  674. if (ret != 0) {
  675. dev_err(&pdev->dev, "Failed to get HPDET IRQ: %d\n", ret);
  676. goto err_micdet;
  677. }
  678. regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
  679. ARIZONA_MICD_RATE_MASK,
  680. 8 << ARIZONA_MICD_RATE_SHIFT);
  681. arizona_clk32k_enable(arizona);
  682. regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_DEBOUNCE,
  683. ARIZONA_JD1_DB, ARIZONA_JD1_DB);
  684. regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
  685. ARIZONA_JD1_ENA, ARIZONA_JD1_ENA);
  686. ret = regulator_allow_bypass(info->micvdd, true);
  687. if (ret != 0)
  688. dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n",
  689. ret);
  690. pm_runtime_put(&pdev->dev);
  691. ret = input_register_device(info->input);
  692. if (ret) {
  693. dev_err(&pdev->dev, "Can't register input device: %d\n", ret);
  694. goto err_hpdet;
  695. }
  696. return 0;
  697. err_hpdet:
  698. arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
  699. err_micdet:
  700. arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
  701. err_fall_wake:
  702. arizona_set_irq_wake(arizona, jack_irq_fall, 0);
  703. err_fall:
  704. arizona_free_irq(arizona, jack_irq_fall, info);
  705. err_rise_wake:
  706. arizona_set_irq_wake(arizona, jack_irq_rise, 0);
  707. err_rise:
  708. arizona_free_irq(arizona, jack_irq_rise, info);
  709. err_input:
  710. err_register:
  711. pm_runtime_disable(&pdev->dev);
  712. extcon_dev_unregister(&info->edev);
  713. err:
  714. return ret;
  715. }
  716. static int arizona_extcon_remove(struct platform_device *pdev)
  717. {
  718. struct arizona_extcon_info *info = platform_get_drvdata(pdev);
  719. struct arizona *arizona = info->arizona;
  720. int jack_irq_rise, jack_irq_fall;
  721. pm_runtime_disable(&pdev->dev);
  722. regmap_update_bits(arizona->regmap,
  723. ARIZONA_MICD_CLAMP_CONTROL,
  724. ARIZONA_MICD_CLAMP_MODE_MASK, 0);
  725. if (arizona->pdata.jd_gpio5) {
  726. jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE;
  727. jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL;
  728. } else {
  729. jack_irq_rise = ARIZONA_IRQ_JD_RISE;
  730. jack_irq_fall = ARIZONA_IRQ_JD_FALL;
  731. }
  732. arizona_set_irq_wake(arizona, jack_irq_rise, 0);
  733. arizona_set_irq_wake(arizona, jack_irq_fall, 0);
  734. arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info);
  735. arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info);
  736. arizona_free_irq(arizona, jack_irq_rise, info);
  737. arizona_free_irq(arizona, jack_irq_fall, info);
  738. regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE,
  739. ARIZONA_JD1_ENA, 0);
  740. arizona_clk32k_disable(arizona);
  741. extcon_dev_unregister(&info->edev);
  742. return 0;
  743. }
  744. static struct platform_driver arizona_extcon_driver = {
  745. .driver = {
  746. .name = "arizona-extcon",
  747. .owner = THIS_MODULE,
  748. },
  749. .probe = arizona_extcon_probe,
  750. .remove = arizona_extcon_remove,
  751. };
  752. module_platform_driver(arizona_extcon_driver);
  753. MODULE_DESCRIPTION("Arizona Extcon driver");
  754. MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
  755. MODULE_LICENSE("GPL");
  756. MODULE_ALIAS("platform:extcon-arizona");