wcd9xxx-rst.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. /* Copyright (c) 2017-2018, 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. #include <asoc/wcd9360-registers.h>
  24. #include "wcd9360/wcd9360-irq.h"
  25. /* wcd9335 interrupt table */
  26. static const struct intr_data wcd9335_intr_table[] = {
  27. {WCD9XXX_IRQ_SLIMBUS, false},
  28. {WCD9335_IRQ_MBHC_SW_DET, true},
  29. {WCD9335_IRQ_MBHC_BUTTON_PRESS_DET, true},
  30. {WCD9335_IRQ_MBHC_BUTTON_RELEASE_DET, true},
  31. {WCD9335_IRQ_MBHC_ELECT_INS_REM_DET, true},
  32. {WCD9335_IRQ_MBHC_ELECT_INS_REM_LEG_DET, true},
  33. {WCD9335_IRQ_FLL_LOCK_LOSS, false},
  34. {WCD9335_IRQ_HPH_PA_CNPL_COMPLETE, false},
  35. {WCD9335_IRQ_HPH_PA_CNPR_COMPLETE, false},
  36. {WCD9335_IRQ_EAR_PA_CNP_COMPLETE, false},
  37. {WCD9335_IRQ_LINE_PA1_CNP_COMPLETE, false},
  38. {WCD9335_IRQ_LINE_PA2_CNP_COMPLETE, false},
  39. {WCD9335_IRQ_LINE_PA3_CNP_COMPLETE, false},
  40. {WCD9335_IRQ_LINE_PA4_CNP_COMPLETE, false},
  41. {WCD9335_IRQ_HPH_PA_OCPL_FAULT, false},
  42. {WCD9335_IRQ_HPH_PA_OCPR_FAULT, false},
  43. {WCD9335_IRQ_EAR_PA_OCP_FAULT, false},
  44. {WCD9335_IRQ_SOUNDWIRE, false},
  45. {WCD9335_IRQ_VDD_DIG_RAMP_COMPLETE, false},
  46. {WCD9335_IRQ_RCO_ERROR, false},
  47. {WCD9335_IRQ_SVA_ERROR, false},
  48. {WCD9335_IRQ_MAD_AUDIO, false},
  49. {WCD9335_IRQ_MAD_BEACON, false},
  50. {WCD9335_IRQ_SVA_OUTBOX1, true},
  51. {WCD9335_IRQ_SVA_OUTBOX2, true},
  52. {WCD9335_IRQ_MAD_ULTRASOUND, false},
  53. {WCD9335_IRQ_VBAT_ATTACK, false},
  54. {WCD9335_IRQ_VBAT_RESTORE, false},
  55. };
  56. static const struct intr_data wcd934x_intr_table[] = {
  57. {WCD9XXX_IRQ_SLIMBUS, false},
  58. {WCD934X_IRQ_MBHC_SW_DET, true},
  59. {WCD934X_IRQ_MBHC_BUTTON_PRESS_DET, true},
  60. {WCD934X_IRQ_MBHC_BUTTON_RELEASE_DET, true},
  61. {WCD934X_IRQ_MBHC_ELECT_INS_REM_DET, true},
  62. {WCD934X_IRQ_MBHC_ELECT_INS_REM_LEG_DET, true},
  63. {WCD934X_IRQ_MISC, false},
  64. {WCD934X_IRQ_HPH_PA_CNPL_COMPLETE, false},
  65. {WCD934X_IRQ_HPH_PA_CNPR_COMPLETE, false},
  66. {WCD934X_IRQ_EAR_PA_CNP_COMPLETE, false},
  67. {WCD934X_IRQ_LINE_PA1_CNP_COMPLETE, false},
  68. {WCD934X_IRQ_LINE_PA2_CNP_COMPLETE, false},
  69. {WCD934X_IRQ_SLNQ_ANALOG_ERROR, false},
  70. {WCD934X_IRQ_RESERVED_3, false},
  71. {WCD934X_IRQ_HPH_PA_OCPL_FAULT, false},
  72. {WCD934X_IRQ_HPH_PA_OCPR_FAULT, false},
  73. {WCD934X_IRQ_EAR_PA_OCP_FAULT, false},
  74. {WCD934X_IRQ_SOUNDWIRE, false},
  75. {WCD934X_IRQ_VDD_DIG_RAMP_COMPLETE, false},
  76. {WCD934X_IRQ_RCO_ERROR, false},
  77. {WCD934X_IRQ_CPE_ERROR, false},
  78. {WCD934X_IRQ_MAD_AUDIO, false},
  79. {WCD934X_IRQ_MAD_BEACON, false},
  80. {WCD934X_IRQ_CPE1_INTR, true},
  81. {WCD934X_IRQ_RESERVED_4, false},
  82. {WCD934X_IRQ_MAD_ULTRASOUND, false},
  83. {WCD934X_IRQ_VBAT_ATTACK, false},
  84. {WCD934X_IRQ_VBAT_RESTORE, false},
  85. };
  86. static const struct intr_data wcd9360_intr_table[] = {
  87. {WCD9XXX_IRQ_SLIMBUS, false},
  88. {WCD9360_IRQ_MISC, false},
  89. {WCD9360_IRQ_LDO_RXTX_SCD, false},
  90. {WCD9360_IRQ_EAR_PA_SCD, false},
  91. {WCD9360_IRQ_AUX_PA_SCD, false},
  92. {WCD9360_IRQ_EAR_PA_CNP_COMPLETE, false},
  93. {WCD9360_IRQ_AUX_PA_CNP_COMPLETE, false},
  94. {WCD9360_IRQ_RESERVED_3, false},
  95. {WCD9360_IRQ_SOUNDWIRE, false},
  96. {WCD9360_IRQ_RCO_ERROR, false},
  97. {WCD9360_IRQ_CPE_ERROR, false},
  98. {WCD9360_IRQ_MAD_AUDIO, false},
  99. {WCD9360_IRQ_MAD_BEACON, false},
  100. {WCD9360_IRQ_CPE1_INTR, true},
  101. {WCD9360_IRQ_RESERVED_4, false},
  102. {WCD9360_IRQ_MAD_ULTRASOUND, false},
  103. };
  104. /*
  105. * wcd9335_bring_down: Bringdown WCD Codec
  106. *
  107. * @wcd9xxx: Pointer to wcd9xxx structure
  108. *
  109. * Returns 0 for success or negative error code for failure
  110. */
  111. static int wcd9335_bring_down(struct wcd9xxx *wcd9xxx)
  112. {
  113. if (!wcd9xxx || !wcd9xxx->regmap)
  114. return -EINVAL;
  115. regmap_write(wcd9xxx->regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  116. 0x04);
  117. return 0;
  118. }
  119. /*
  120. * wcd9335_bring_up: Bringup WCD Codec
  121. *
  122. * @wcd9xxx: Pointer to the wcd9xxx structure
  123. *
  124. * Returns 0 for success or negative error code for failure
  125. */
  126. static int wcd9335_bring_up(struct wcd9xxx *wcd9xxx)
  127. {
  128. int ret = 0;
  129. int val, byte0;
  130. struct regmap *wcd_regmap;
  131. if (!wcd9xxx)
  132. return -EINVAL;
  133. if (!wcd9xxx->regmap) {
  134. dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null!\n",
  135. __func__);
  136. return -EINVAL;
  137. }
  138. wcd_regmap = wcd9xxx->regmap;
  139. regmap_read(wcd_regmap, WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT0, &val);
  140. regmap_read(wcd_regmap, WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE0, &byte0);
  141. if ((val < 0) || (byte0 < 0)) {
  142. dev_err(wcd9xxx->dev, "%s: tasha codec version detection fail!\n",
  143. __func__);
  144. return -EINVAL;
  145. }
  146. if ((val & 0x80) && (byte0 == 0x0)) {
  147. dev_info(wcd9xxx->dev, "%s: wcd9335 codec version is v1.1\n",
  148. __func__);
  149. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x01);
  150. regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_CCL_2, 0xFC);
  151. regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_CCL_4, 0x21);
  152. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  153. 0x5);
  154. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  155. 0x7);
  156. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  157. 0x3);
  158. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x3);
  159. } else if (byte0 == 0x1) {
  160. dev_info(wcd9xxx->dev, "%s: wcd9335 codec version is v2.0\n",
  161. __func__);
  162. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x01);
  163. regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_TEST_2, 0x00);
  164. regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_CCL_8, 0x6F);
  165. regmap_write(wcd_regmap, WCD9335_BIAS_VBG_FINE_ADJ, 0x65);
  166. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  167. 0x5);
  168. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  169. 0x7);
  170. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  171. 0x3);
  172. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x3);
  173. } else if ((byte0 == 0) && (!(val & 0x80))) {
  174. dev_info(wcd9xxx->dev, "%s: wcd9335 codec version is v1.0\n",
  175. __func__);
  176. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x01);
  177. regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_CCL_2, 0xFC);
  178. regmap_write(wcd_regmap, WCD9335_SIDO_SIDO_CCL_4, 0x21);
  179. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  180. 0x3);
  181. regmap_write(wcd_regmap, WCD9335_CODEC_RPM_RST_CTL, 0x3);
  182. } else {
  183. dev_err(wcd9xxx->dev, "%s: tasha codec version unknown\n",
  184. __func__);
  185. ret = -EINVAL;
  186. }
  187. return ret;
  188. }
  189. /*
  190. * wcd9335_get_cdc_info: Get codec specific information
  191. *
  192. * @wcd9xxx: pointer to wcd9xxx structure
  193. * @wcd_type: pointer to wcd9xxx_codec_type structure
  194. *
  195. * Returns 0 for success or negative error code for failure
  196. */
  197. static int wcd9335_get_cdc_info(struct wcd9xxx *wcd9xxx,
  198. struct wcd9xxx_codec_type *wcd_type)
  199. {
  200. u16 id_minor, id_major;
  201. struct regmap *wcd_regmap;
  202. int rc, val, version = 0;
  203. if (!wcd9xxx || !wcd_type)
  204. return -EINVAL;
  205. if (!wcd9xxx->regmap) {
  206. dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null!\n",
  207. __func__);
  208. return -EINVAL;
  209. }
  210. wcd_regmap = wcd9xxx->regmap;
  211. rc = regmap_bulk_read(wcd_regmap, WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE0,
  212. (u8 *)&id_minor, sizeof(u16));
  213. if (rc)
  214. return -EINVAL;
  215. rc = regmap_bulk_read(wcd_regmap, WCD9335_CHIP_TIER_CTRL_CHIP_ID_BYTE2,
  216. (u8 *)&id_major, sizeof(u16));
  217. if (rc)
  218. return -EINVAL;
  219. dev_info(wcd9xxx->dev, "%s: wcd9xxx chip id major 0x%x, minor 0x%x\n",
  220. __func__, id_major, id_minor);
  221. /* Version detection */
  222. if (id_major == TASHA_MAJOR) {
  223. regmap_read(wcd_regmap, WCD9335_CHIP_TIER_CTRL_EFUSE_VAL_OUT0,
  224. &val);
  225. version = ((u8)val & 0x80) >> 7;
  226. } else if (id_major == TASHA2P0_MAJOR)
  227. version = 2;
  228. else
  229. dev_err(wcd9xxx->dev, "%s: wcd9335 version unknown (major 0x%x, minor 0x%x)\n",
  230. __func__, id_major, id_minor);
  231. /* Fill codec type info */
  232. wcd_type->id_major = id_major;
  233. wcd_type->id_minor = id_minor;
  234. wcd_type->num_irqs = WCD9335_NUM_IRQS;
  235. wcd_type->version = version;
  236. wcd_type->slim_slave_type = WCD9XXX_SLIM_SLAVE_ADDR_TYPE_1;
  237. wcd_type->i2c_chip_status = 0x01;
  238. wcd_type->intr_tbl = wcd9335_intr_table;
  239. wcd_type->intr_tbl_size = ARRAY_SIZE(wcd9335_intr_table);
  240. wcd_type->intr_reg[WCD9XXX_INTR_STATUS_BASE] =
  241. WCD9335_INTR_PIN1_STATUS0;
  242. wcd_type->intr_reg[WCD9XXX_INTR_CLEAR_BASE] =
  243. WCD9335_INTR_PIN1_CLEAR0;
  244. wcd_type->intr_reg[WCD9XXX_INTR_MASK_BASE] =
  245. WCD9335_INTR_PIN1_MASK0;
  246. wcd_type->intr_reg[WCD9XXX_INTR_LEVEL_BASE] =
  247. WCD9335_INTR_LEVEL0;
  248. wcd_type->intr_reg[WCD9XXX_INTR_CLR_COMMIT] =
  249. WCD9335_INTR_CLR_COMMIT;
  250. return rc;
  251. }
  252. /*
  253. * wcd934x_bring_down: Bringdown WCD Codec
  254. *
  255. * @wcd9xxx: Pointer to wcd9xxx structure
  256. *
  257. * Returns 0 for success or negative error code for failure
  258. */
  259. static int wcd934x_bring_down(struct wcd9xxx *wcd9xxx)
  260. {
  261. if (!wcd9xxx || !wcd9xxx->regmap)
  262. return -EINVAL;
  263. regmap_write(wcd9xxx->regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  264. 0x04);
  265. return 0;
  266. }
  267. /*
  268. * wcd934x_bring_up: Bringup WCD Codec
  269. *
  270. * @wcd9xxx: Pointer to the wcd9xxx structure
  271. *
  272. * Returns 0 for success or negative error code for failure
  273. */
  274. static int wcd934x_bring_up(struct wcd9xxx *wcd9xxx)
  275. {
  276. struct regmap *wcd_regmap;
  277. if (!wcd9xxx)
  278. return -EINVAL;
  279. if (!wcd9xxx->regmap) {
  280. dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null!\n",
  281. __func__);
  282. return -EINVAL;
  283. }
  284. wcd_regmap = wcd9xxx->regmap;
  285. regmap_write(wcd_regmap, WCD934X_CODEC_RPM_RST_CTL, 0x01);
  286. regmap_write(wcd_regmap, WCD934X_SIDO_NEW_VOUT_A_STARTUP, 0x19);
  287. regmap_write(wcd_regmap, WCD934X_SIDO_NEW_VOUT_D_STARTUP, 0x15);
  288. /* Add 1msec delay for VOUT to settle */
  289. usleep_range(1000, 1100);
  290. regmap_write(wcd_regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x5);
  291. regmap_write(wcd_regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x7);
  292. regmap_write(wcd_regmap, WCD934X_CODEC_RPM_RST_CTL, 0x3);
  293. regmap_write(wcd_regmap, WCD934X_CODEC_RPM_RST_CTL, 0x7);
  294. regmap_write(wcd_regmap, WCD934X_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x3);
  295. return 0;
  296. }
  297. /*
  298. * wcd934x_get_cdc_info: Get codec specific information
  299. *
  300. * @wcd9xxx: pointer to wcd9xxx structure
  301. * @wcd_type: pointer to wcd9xxx_codec_type structure
  302. *
  303. * Returns 0 for success or negative error code for failure
  304. */
  305. static int wcd934x_get_cdc_info(struct wcd9xxx *wcd9xxx,
  306. struct wcd9xxx_codec_type *wcd_type)
  307. {
  308. u16 id_minor, id_major;
  309. struct regmap *wcd_regmap;
  310. int rc, version = -1;
  311. if (!wcd9xxx || !wcd_type)
  312. return -EINVAL;
  313. if (!wcd9xxx->regmap) {
  314. dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null\n", __func__);
  315. return -EINVAL;
  316. }
  317. wcd_regmap = wcd9xxx->regmap;
  318. rc = regmap_bulk_read(wcd_regmap, WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE0,
  319. (u8 *)&id_minor, sizeof(u16));
  320. if (rc)
  321. return -EINVAL;
  322. rc = regmap_bulk_read(wcd_regmap, WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE2,
  323. (u8 *)&id_major, sizeof(u16));
  324. if (rc)
  325. return -EINVAL;
  326. dev_info(wcd9xxx->dev, "%s: wcd9xxx chip id major 0x%x, minor 0x%x\n",
  327. __func__, id_major, id_minor);
  328. if (id_major != TAVIL_MAJOR)
  329. goto version_unknown;
  330. /*
  331. * As fine version info cannot be retrieved before tavil probe.
  332. * Assign coarse versions for possible future use before tavil probe.
  333. */
  334. if (id_minor == cpu_to_le16(0))
  335. version = TAVIL_VERSION_1_0;
  336. else if (id_minor == cpu_to_le16(0x01))
  337. version = TAVIL_VERSION_1_1;
  338. version_unknown:
  339. if (version < 0)
  340. dev_err(wcd9xxx->dev, "%s: wcd934x version unknown\n",
  341. __func__);
  342. /* Fill codec type info */
  343. wcd_type->id_major = id_major;
  344. wcd_type->id_minor = id_minor;
  345. wcd_type->num_irqs = WCD934X_NUM_IRQS;
  346. wcd_type->version = version;
  347. wcd_type->slim_slave_type = WCD9XXX_SLIM_SLAVE_ADDR_TYPE_1;
  348. wcd_type->i2c_chip_status = 0x01;
  349. wcd_type->intr_tbl = wcd934x_intr_table;
  350. wcd_type->intr_tbl_size = ARRAY_SIZE(wcd934x_intr_table);
  351. wcd_type->intr_reg[WCD9XXX_INTR_STATUS_BASE] =
  352. WCD934X_INTR_PIN1_STATUS0;
  353. wcd_type->intr_reg[WCD9XXX_INTR_CLEAR_BASE] =
  354. WCD934X_INTR_PIN1_CLEAR0;
  355. wcd_type->intr_reg[WCD9XXX_INTR_MASK_BASE] =
  356. WCD934X_INTR_PIN1_MASK0;
  357. wcd_type->intr_reg[WCD9XXX_INTR_LEVEL_BASE] =
  358. WCD934X_INTR_LEVEL0;
  359. wcd_type->intr_reg[WCD9XXX_INTR_CLR_COMMIT] =
  360. WCD934X_INTR_CLR_COMMIT;
  361. return rc;
  362. }
  363. /*
  364. * wcd9360_bring_down: Bringdown WCD Codec
  365. *
  366. * @wcd9xxx: Pointer to wcd9xxx structure
  367. *
  368. * Returns 0 for success or negative error code for failure
  369. */
  370. static int wcd9360_bring_down(struct wcd9xxx *wcd9xxx)
  371. {
  372. if (!wcd9xxx || !wcd9xxx->regmap)
  373. return -EINVAL;
  374. regmap_write(wcd9xxx->regmap, WCD9360_CODEC_RPM_PWR_CDC_DIG_HM_CTL,
  375. 0x04);
  376. return 0;
  377. }
  378. /*
  379. * wcd9360_bring_up: Bringup WCD Codec
  380. *
  381. * @wcd9xxx: Pointer to the wcd9xxx structure
  382. *
  383. * Returns 0 for success or negative error code for failure
  384. */
  385. static int wcd9360_bring_up(struct wcd9xxx *wcd9xxx)
  386. {
  387. struct regmap *wcd_regmap;
  388. if (!wcd9xxx)
  389. return -EINVAL;
  390. if (!wcd9xxx->regmap) {
  391. dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null!\n",
  392. __func__);
  393. return -EINVAL;
  394. }
  395. wcd_regmap = wcd9xxx->regmap;
  396. regmap_write(wcd_regmap, WCD9360_CODEC_RPM_RST_CTL, 0x01);
  397. regmap_write(wcd_regmap, WCD9360_SIDO_NEW_VOUT_A_STARTUP, 0x19);
  398. regmap_write(wcd_regmap, WCD9360_SIDO_NEW_VOUT_D_STARTUP, 0x15);
  399. /* Add 1msec delay for VOUT to settle */
  400. usleep_range(1000, 1100);
  401. regmap_write(wcd_regmap, WCD9360_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x5);
  402. regmap_write(wcd_regmap, WCD9360_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x7);
  403. regmap_write(wcd_regmap, WCD9360_CODEC_RPM_RST_CTL, 0x3);
  404. regmap_write(wcd_regmap, WCD9360_CODEC_RPM_RST_CTL, 0x7);
  405. regmap_write(wcd_regmap, WCD9360_CODEC_RPM_PWR_CDC_DIG_HM_CTL, 0x3);
  406. return 0;
  407. }
  408. /*
  409. * wcd9360_get_cdc_info: Get codec specific information
  410. *
  411. * @wcd9xxx: pointer to wcd9xxx structure
  412. * @wcd_type: pointer to wcd9xxx_codec_type structure
  413. *
  414. * Returns 0 for success or negative error code for failure
  415. */
  416. static int wcd9360_get_cdc_info(struct wcd9xxx *wcd9xxx,
  417. struct wcd9xxx_codec_type *wcd_type)
  418. {
  419. u16 id_minor, id_major;
  420. struct regmap *wcd_regmap;
  421. int rc, version = -1;
  422. if (!wcd9xxx || !wcd_type)
  423. return -EINVAL;
  424. if (!wcd9xxx->regmap) {
  425. dev_err(wcd9xxx->dev, "%s: wcd9xxx regmap is null\n", __func__);
  426. return -EINVAL;
  427. }
  428. wcd_regmap = wcd9xxx->regmap;
  429. rc = regmap_bulk_read(wcd_regmap, WCD9360_CHIP_TIER_CTRL_CHIP_ID_BYTE0,
  430. (u8 *)&id_minor, sizeof(u16));
  431. if (rc)
  432. return -EINVAL;
  433. rc = regmap_bulk_read(wcd_regmap, WCD9360_CHIP_TIER_CTRL_CHIP_ID_BYTE2,
  434. (u8 *)&id_major, sizeof(u16));
  435. if (rc)
  436. return -EINVAL;
  437. dev_info(wcd9xxx->dev, "%s: wcd9xxx chip id major 0x%x, minor 0x%x\n",
  438. __func__, id_major, id_minor);
  439. if (id_major != PAHU_MAJOR)
  440. goto version_unknown;
  441. /*
  442. * As fine version info cannot be retrieved before pahu probe.
  443. * Assign coarse versions for possible future use before Pahu probe.
  444. */
  445. if (id_minor == cpu_to_le16(0))
  446. version = PAHU_VERSION_1_0;
  447. version_unknown:
  448. if (version < 0)
  449. dev_err(wcd9xxx->dev, "%s: wcd934x version unknown\n",
  450. __func__);
  451. /* Fill codec type info */
  452. wcd_type->id_major = id_major;
  453. wcd_type->id_minor = id_minor;
  454. wcd_type->num_irqs = WCD9360_NUM_IRQS;
  455. wcd_type->version = version;
  456. wcd_type->slim_slave_type = WCD9XXX_SLIM_SLAVE_ADDR_TYPE_1;
  457. wcd_type->i2c_chip_status = 0x01;
  458. wcd_type->intr_tbl = wcd9360_intr_table;
  459. wcd_type->intr_tbl_size = ARRAY_SIZE(wcd934x_intr_table);
  460. wcd_type->intr_reg[WCD9XXX_INTR_STATUS_BASE] =
  461. WCD9360_INTR_PIN1_STATUS0;
  462. wcd_type->intr_reg[WCD9XXX_INTR_CLEAR_BASE] =
  463. WCD9360_INTR_PIN1_CLEAR0;
  464. wcd_type->intr_reg[WCD9XXX_INTR_MASK_BASE] =
  465. WCD9360_INTR_PIN1_MASK0;
  466. wcd_type->intr_reg[WCD9XXX_INTR_LEVEL_BASE] =
  467. WCD9360_INTR_LEVEL0;
  468. wcd_type->intr_reg[WCD9XXX_INTR_CLR_COMMIT] =
  469. WCD9360_INTR_CLR_COMMIT;
  470. return rc;
  471. }
  472. codec_bringdown_fn wcd9xxx_bringdown_fn(int type)
  473. {
  474. codec_bringdown_fn cdc_bdown_fn;
  475. switch (type) {
  476. case WCD9360:
  477. cdc_bdown_fn = wcd9360_bring_down;
  478. break;
  479. case WCD934X:
  480. cdc_bdown_fn = wcd934x_bring_down;
  481. break;
  482. case WCD9335:
  483. cdc_bdown_fn = wcd9335_bring_down;
  484. break;
  485. default:
  486. cdc_bdown_fn = NULL;
  487. break;
  488. }
  489. return cdc_bdown_fn;
  490. }
  491. codec_bringup_fn wcd9xxx_bringup_fn(int type)
  492. {
  493. codec_bringup_fn cdc_bup_fn;
  494. switch (type) {
  495. case WCD9360:
  496. cdc_bup_fn = wcd9360_bring_up;
  497. break;
  498. case WCD934X:
  499. cdc_bup_fn = wcd934x_bring_up;
  500. break;
  501. case WCD9335:
  502. cdc_bup_fn = wcd9335_bring_up;
  503. break;
  504. default:
  505. cdc_bup_fn = NULL;
  506. break;
  507. }
  508. return cdc_bup_fn;
  509. }
  510. codec_type_fn wcd9xxx_get_codec_info_fn(int type)
  511. {
  512. codec_type_fn cdc_type_fn;
  513. switch (type) {
  514. case WCD9360:
  515. cdc_type_fn = wcd9360_get_cdc_info;
  516. break;
  517. case WCD934X:
  518. cdc_type_fn = wcd934x_get_cdc_info;
  519. break;
  520. case WCD9335:
  521. cdc_type_fn = wcd9335_get_cdc_info;
  522. break;
  523. default:
  524. cdc_type_fn = NULL;
  525. break;
  526. }
  527. return cdc_type_fn;
  528. }