wcd9xxx-rst.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /* Copyright (c) 2017, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/device.h>
  14. #include <linux/regmap.h>
  15. #include <linux/delay.h>
  16. #include "core.h"
  17. #include "pdata.h"
  18. #include "wcd9xxx-utils.h"
  19. #include "wcd9335_registers.h"
  20. #include "wcd9335_irq.h"
  21. #include <asoc/wcd934x_registers.h>
  22. #include "wcd934x/wcd934x_irq.h"
  23. /* wcd9335 interrupt table */
  24. static const struct intr_data wcd9335_intr_table[] = {
  25. {WCD9XXX_IRQ_SLIMBUS, false},
  26. {WCD9335_IRQ_MBHC_SW_DET, true},
  27. {WCD9335_IRQ_MBHC_BUTTON_PRESS_DET, true},
  28. {WCD9335_IRQ_MBHC_BUTTON_RELEASE_DET, true},
  29. {WCD9335_IRQ_MBHC_ELECT_INS_REM_DET, true},
  30. {WCD9335_IRQ_MBHC_ELECT_INS_REM_LEG_DET, true},
  31. {WCD9335_IRQ_FLL_LOCK_LOSS, false},
  32. {WCD9335_IRQ_HPH_PA_CNPL_COMPLETE, false},
  33. {WCD9335_IRQ_HPH_PA_CNPR_COMPLETE, false},
  34. {WCD9335_IRQ_EAR_PA_CNP_COMPLETE, false},
  35. {WCD9335_IRQ_LINE_PA1_CNP_COMPLETE, false},
  36. {WCD9335_IRQ_LINE_PA2_CNP_COMPLETE, false},
  37. {WCD9335_IRQ_LINE_PA3_CNP_COMPLETE, false},
  38. {WCD9335_IRQ_LINE_PA4_CNP_COMPLETE, false},
  39. {WCD9335_IRQ_HPH_PA_OCPL_FAULT, false},
  40. {WCD9335_IRQ_HPH_PA_OCPR_FAULT, false},
  41. {WCD9335_IRQ_EAR_PA_OCP_FAULT, false},
  42. {WCD9335_IRQ_SOUNDWIRE, false},
  43. {WCD9335_IRQ_VDD_DIG_RAMP_COMPLETE, false},
  44. {WCD9335_IRQ_RCO_ERROR, false},
  45. {WCD9335_IRQ_SVA_ERROR, false},
  46. {WCD9335_IRQ_MAD_AUDIO, false},
  47. {WCD9335_IRQ_MAD_BEACON, false},
  48. {WCD9335_IRQ_SVA_OUTBOX1, true},
  49. {WCD9335_IRQ_SVA_OUTBOX2, true},
  50. {WCD9335_IRQ_MAD_ULTRASOUND, false},
  51. {WCD9335_IRQ_VBAT_ATTACK, false},
  52. {WCD9335_IRQ_VBAT_RESTORE, false},
  53. };
  54. static const struct intr_data wcd934x_intr_table[] = {
  55. {WCD9XXX_IRQ_SLIMBUS, false},
  56. {WCD934X_IRQ_MBHC_SW_DET, true},
  57. {WCD934X_IRQ_MBHC_BUTTON_PRESS_DET, true},
  58. {WCD934X_IRQ_MBHC_BUTTON_RELEASE_DET, true},
  59. {WCD934X_IRQ_MBHC_ELECT_INS_REM_DET, true},
  60. {WCD934X_IRQ_MBHC_ELECT_INS_REM_LEG_DET, true},
  61. {WCD934X_IRQ_MISC, false},
  62. {WCD934X_IRQ_HPH_PA_CNPL_COMPLETE, false},
  63. {WCD934X_IRQ_HPH_PA_CNPR_COMPLETE, false},
  64. {WCD934X_IRQ_EAR_PA_CNP_COMPLETE, false},
  65. {WCD934X_IRQ_LINE_PA1_CNP_COMPLETE, false},
  66. {WCD934X_IRQ_LINE_PA2_CNP_COMPLETE, false},
  67. {WCD934X_IRQ_SLNQ_ANALOG_ERROR, false},
  68. {WCD934X_IRQ_RESERVED_3, false},
  69. {WCD934X_IRQ_HPH_PA_OCPL_FAULT, false},
  70. {WCD934X_IRQ_HPH_PA_OCPR_FAULT, false},
  71. {WCD934X_IRQ_EAR_PA_OCP_FAULT, false},
  72. {WCD934X_IRQ_SOUNDWIRE, false},
  73. {WCD934X_IRQ_VDD_DIG_RAMP_COMPLETE, false},
  74. {WCD934X_IRQ_RCO_ERROR, false},
  75. {WCD934X_IRQ_CPE_ERROR, false},
  76. {WCD934X_IRQ_MAD_AUDIO, false},
  77. {WCD934X_IRQ_MAD_BEACON, false},
  78. {WCD934X_IRQ_CPE1_INTR, true},
  79. {WCD934X_IRQ_RESERVED_4, false},
  80. {WCD934X_IRQ_MAD_ULTRASOUND, false},
  81. {WCD934X_IRQ_VBAT_ATTACK, false},
  82. {WCD934X_IRQ_VBAT_RESTORE, false},
  83. };
  84. /*
  85. * wcd9335_bring_down: Bringdown WCD Codec
  86. *
  87. * @wcd9xxx: Pointer to wcd9xxx structure
  88. *
  89. * Returns 0 for success or negative error code for failure
  90. */
  91. static int wcd9335_bring_down(struct wcd9xxx *wcd9xxx)
  92. {
  93. if (!wcd9xxx || !wcd9xxx->regmap)
  94. return -EINVAL;
  95. regmap_write(wcd9xxx->regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  96. 0x04);
  97. return 0;
  98. }
  99. /*
  100. * wcd9335_bring_up: Bringup WCD Codec
  101. *
  102. * @wcd9xxx: Pointer to the wcd9xxx structure
  103. *
  104. * Returns 0 for success or negative error code for failure
  105. */
  106. static int wcd9335_bring_up(struct wcd9xxx *wcd9xxx)
  107. {
  108. int ret = 0;
  109. int val, byte0;
  110. struct regmap *wcd_regmap;
  111. if (!wcd9xxx)
  112. return -EINVAL;
  113. if (!wcd9xxx->regmap) {
  114. dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null!\n",
  115. __func__);
  116. return -EINVAL;
  117. }
  118. wcd_regmap = wcd9xxx->regmap;
  119. regmap_read(wcd_regmap, WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT0, &val);
  120. regmap_read(wcd_regmap, WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE0, &byte0);
  121. if ((val < 0) || (byte0 < 0)) {
  122. dev_err(wcd9xxx->dev, "%s: tasha codec version detection fail!\n",
  123. __func__);
  124. return -EINVAL;
  125. }
  126. if ((val & 0x80) && (byte0 == 0x0)) {
  127. dev_info(wcd9xxx->dev, "%s: wcd9335 codec version is v1.1\n",
  128. __func__);
  129. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x01);
  130. regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_CCL_2, 0xFC);
  131. regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_CCL_4, 0x21);
  132. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  133. 0x5);
  134. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  135. 0x7);
  136. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  137. 0x3);
  138. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x3);
  139. } else if (byte0 == 0x1) {
  140. dev_info(wcd9xxx->dev, "%s: wcd9335 codec version is v2.0\n",
  141. __func__);
  142. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x01);
  143. regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_TEST_2, 0x00);
  144. regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_CCL_8, 0x6F);
  145. regmap_write(wcd_regmap, WCD9335_BIAS_VBG_FINE_ADJ, 0x65);
  146. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  147. 0x5);
  148. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  149. 0x7);
  150. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  151. 0x3);
  152. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x3);
  153. } else if ((byte0 == 0) && (!(val & 0x80))) {
  154. dev_info(wcd9xxx->dev, "%s: wcd9335 codec version is v1.0\n",
  155. __func__);
  156. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x01);
  157. regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_CCL_2, 0xFC);
  158. regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_CCL_4, 0x21);
  159. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  160. 0x3);
  161. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x3);
  162. } else {
  163. dev_err(wcd9xxx->dev, "%s: tasha codec version unknown\n",
  164. __func__);
  165. ret = -EINVAL;
  166. }
  167. return ret;
  168. }
  169. /*
  170. * wcd9335_get_cdc_info: Get codec specific information
  171. *
  172. * @wcd9xxx: pointer to wcd9xxx structure
  173. * @wcd_type: pointer to wcd9xxx_codec_type structure
  174. *
  175. * Returns 0 for success or negative error code for failure
  176. */
  177. static int wcd9335_get_cdc_info(struct wcd9xxx *wcd9xxx,
  178. struct wcd9xxx_codec_type *wcd_type)
  179. {
  180. u16 id_minor, id_major;
  181. struct regmap *wcd_regmap;
  182. int rc, val, version = 0;
  183. if (!wcd9xxx || !wcd_type)
  184. return -EINVAL;
  185. if (!wcd9xxx->regmap) {
  186. dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null!\n",
  187. __func__);
  188. return -EINVAL;
  189. }
  190. wcd_regmap = wcd9xxx->regmap;
  191. rc = regmap_bulk_read(wcd_regmap, WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE0,
  192. (u8 *)&id_minor, sizeof(u16));
  193. if (rc)
  194. return -EINVAL;
  195. rc = regmap_bulk_read(wcd_regmap, WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE2,
  196. (u8 *)&id_major, sizeof(u16));
  197. if (rc)
  198. return -EINVAL;
  199. dev_info(wcd9xxx->dev, "%s: wcd9xxx chip id major 0x%x, minor 0x%x\n",
  200. __func__, id_major, id_minor);
  201. /* Version detection */
  202. if (id_major == TASHA_MAJOR) {
  203. regmap_read(wcd_regmap, WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT0,
  204. &val);
  205. version = ((u8)val & 0x80) >> 7;
  206. } else if (id_major == TASHA2P0_MAJOR)
  207. version = 2;
  208. else
  209. dev_err(wcd9xxx->dev, "%s: wcd9335 version unknown (major 0x%x, minor 0x%x)\n",
  210. __func__, id_major, id_minor);
  211. /* Fill codec type info */
  212. wcd_type->id_major = id_major;
  213. wcd_type->id_minor = id_minor;
  214. wcd_type->num_irqs = WCD9335_NUM_IRQS;
  215. wcd_type->version = version;
  216. wcd_type->slim_slave_type = WCD9XXX_SLIM_SLAVE_ADDR_TYPE_1;
  217. wcd_type->i2c_chip_status = 0x01;
  218. wcd_type->intr_tbl = wcd9335_intr_table;
  219. wcd_type->intr_tbl_size = ARRAY_SIZE(wcd9335_intr_table);
  220. wcd_type->intr_reg[WCD9XXX_INTR_STATUS_BASE] =
  221. WCD9335_INTR_PIN1_STATUS0;
  222. wcd_type->intr_reg[WCD9XXX_INTR_CLEAR_BASE] =
  223. WCD9335_INTR_PIN1_CLEAR0;
  224. wcd_type->intr_reg[WCD9XXX_INTR_MASK_BASE] =
  225. WCD9335_INTR_PIN1_MASK0;
  226. wcd_type->intr_reg[WCD9XXX_INTR_LEVEL_BASE] =
  227. WCD9335_INTR_LEVEL0;
  228. wcd_type->intr_reg[WCD9XXX_INTR_CLR_COMMIT] =
  229. WCD9335_INTR_CLR_COMMIT;
  230. return rc;
  231. }
  232. /*
  233. * wcd934x_bring_down: Bringdown WCD Codec
  234. *
  235. * @wcd9xxx: Pointer to wcd9xxx structure
  236. *
  237. * Returns 0 for success or negative error code for failure
  238. */
  239. static int wcd934x_bring_down(struct wcd9xxx *wcd9xxx)
  240. {
  241. if (!wcd9xxx || !wcd9xxx->regmap)
  242. return -EINVAL;
  243. regmap_write(wcd9xxx->regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  244. 0x04);
  245. return 0;
  246. }
  247. /*
  248. * wcd934x_bring_up: Bringup WCD Codec
  249. *
  250. * @wcd9xxx: Pointer to the wcd9xxx structure
  251. *
  252. * Returns 0 for success or negative error code for failure
  253. */
  254. static int wcd934x_bring_up(struct wcd9xxx *wcd9xxx)
  255. {
  256. struct regmap *wcd_regmap;
  257. if (!wcd9xxx)
  258. return -EINVAL;
  259. if (!wcd9xxx->regmap) {
  260. dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null!\n",
  261. __func__);
  262. return -EINVAL;
  263. }
  264. wcd_regmap = wcd9xxx->regmap;
  265. regmap_write(wcd_regmap, WCD934X_CODEC_RPM_RST_CTL, 0x01);
  266. regmap_write(wcd_regmap, WCD934X_SIDO_NEW_VOUT_A_STARTUP, 0x19);
  267. regmap_write(wcd_regmap, WCD934X_SIDO_NEW_VOUT_D_STARTUP, 0x15);
  268. /* Add 1msec delay for VOUT to settle */
  269. usleep_range(1000, 1100);
  270. regmap_write(wcd_regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x5);
  271. regmap_write(wcd_regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x7);
  272. regmap_write(wcd_regmap, WCD934X_CODEC_RPM_RST_CTL, 0x3);
  273. regmap_write(wcd_regmap, WCD934X_CODEC_RPM_RST_CTL, 0x7);
  274. regmap_write(wcd_regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x3);
  275. return 0;
  276. }
  277. /*
  278. * wcd934x_get_cdc_info: Get codec specific information
  279. *
  280. * @wcd9xxx: pointer to wcd9xxx structure
  281. * @wcd_type: pointer to wcd9xxx_codec_type structure
  282. *
  283. * Returns 0 for success or negative error code for failure
  284. */
  285. static int wcd934x_get_cdc_info(struct wcd9xxx *wcd9xxx,
  286. struct wcd9xxx_codec_type *wcd_type)
  287. {
  288. u16 id_minor, id_major;
  289. struct regmap *wcd_regmap;
  290. int rc, version = -1;
  291. if (!wcd9xxx || !wcd_type)
  292. return -EINVAL;
  293. if (!wcd9xxx->regmap) {
  294. dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null\n", __func__);
  295. return -EINVAL;
  296. }
  297. wcd_regmap = wcd9xxx->regmap;
  298. rc = regmap_bulk_read(wcd_regmap, WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE0,
  299. (u8 *)&id_minor, sizeof(u16));
  300. if (rc)
  301. return -EINVAL;
  302. rc = regmap_bulk_read(wcd_regmap, WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE2,
  303. (u8 *)&id_major, sizeof(u16));
  304. if (rc)
  305. return -EINVAL;
  306. dev_info(wcd9xxx->dev, "%s: wcd9xxx chip id major 0x%x, minor 0x%x\n",
  307. __func__, id_major, id_minor);
  308. if (id_major != TAVIL_MAJOR)
  309. goto version_unknown;
  310. /*
  311. * As fine version info cannot be retrieved before tavil probe.
  312. * Assign coarse versions for possible future use before tavil probe.
  313. */
  314. if (id_minor == cpu_to_le16(0))
  315. version = TAVIL_VERSION_1_0;
  316. else if (id_minor == cpu_to_le16(0x01))
  317. version = TAVIL_VERSION_1_1;
  318. version_unknown:
  319. if (version < 0)
  320. dev_err(wcd9xxx->dev, "%s: wcd934x version unknown\n",
  321. __func__);
  322. /* Fill codec type info */
  323. wcd_type->id_major = id_major;
  324. wcd_type->id_minor = id_minor;
  325. wcd_type->num_irqs = WCD934X_NUM_IRQS;
  326. wcd_type->version = version;
  327. wcd_type->slim_slave_type = WCD9XXX_SLIM_SLAVE_ADDR_TYPE_1;
  328. wcd_type->i2c_chip_status = 0x01;
  329. wcd_type->intr_tbl = wcd934x_intr_table;
  330. wcd_type->intr_tbl_size = ARRAY_SIZE(wcd934x_intr_table);
  331. wcd_type->intr_reg[WCD9XXX_INTR_STATUS_BASE] =
  332. WCD934X_INTR_PIN1_STATUS0;
  333. wcd_type->intr_reg[WCD9XXX_INTR_CLEAR_BASE] =
  334. WCD934X_INTR_PIN1_CLEAR0;
  335. wcd_type->intr_reg[WCD9XXX_INTR_MASK_BASE] =
  336. WCD934X_INTR_PIN1_MASK0;
  337. wcd_type->intr_reg[WCD9XXX_INTR_LEVEL_BASE] =
  338. WCD934X_INTR_LEVEL0;
  339. wcd_type->intr_reg[WCD9XXX_INTR_CLR_COMMIT] =
  340. WCD934X_INTR_CLR_COMMIT;
  341. return rc;
  342. }
  343. codec_bringdown_fn wcd9xxx_bringdown_fn(int type)
  344. {
  345. codec_bringdown_fn cdc_bdown_fn;
  346. switch (type) {
  347. case WCD934X:
  348. cdc_bdown_fn = wcd934x_bring_down;
  349. break;
  350. case WCD9335:
  351. cdc_bdown_fn = wcd9335_bring_down;
  352. break;
  353. default:
  354. cdc_bdown_fn = NULL;
  355. break;
  356. }
  357. return cdc_bdown_fn;
  358. }
  359. codec_bringup_fn wcd9xxx_bringup_fn(int type)
  360. {
  361. codec_bringup_fn cdc_bup_fn;
  362. switch (type) {
  363. case WCD934X:
  364. cdc_bup_fn = wcd934x_bring_up;
  365. break;
  366. case WCD9335:
  367. cdc_bup_fn = wcd9335_bring_up;
  368. break;
  369. default:
  370. cdc_bup_fn = NULL;
  371. break;
  372. }
  373. return cdc_bup_fn;
  374. }
  375. codec_type_fn wcd9xxx_get_codec_info_fn(int type)
  376. {
  377. codec_type_fn cdc_type_fn;
  378. switch (type) {
  379. case WCD934X:
  380. cdc_type_fn = wcd934x_get_cdc_info;
  381. break;
  382. case WCD9335:
  383. cdc_type_fn = wcd9335_get_cdc_info;
  384. break;
  385. default:
  386. cdc_type_fn = NULL;
  387. break;
  388. }
  389. return cdc_type_fn;
  390. }