msm-cdc-supply.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/kernel.h>
  6. #include <linux/module.h>
  7. #include <linux/of_irq.h>
  8. #include <linux/of_device.h>
  9. #include <linux/slab.h>
  10. #include <linux/regulator/consumer.h>
  11. #include <asoc/msm-cdc-supply.h>
  12. #include <sound/soc.h>
  13. #define CODEC_DT_MAX_PROP_SIZE 40
  14. static int msm_cdc_dt_parse_vreg_info(struct device *dev,
  15. struct cdc_regulator *cdc_vreg,
  16. const char *name, bool is_ond)
  17. {
  18. char prop_name[CODEC_DT_MAX_PROP_SIZE];
  19. struct device_node *regulator_node = NULL;
  20. const __be32 *prop;
  21. int len, rc;
  22. u32 prop_val;
  23. /* Parse supply name */
  24. snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply", name);
  25. regulator_node = of_parse_phandle(dev->of_node, prop_name, 0);
  26. if (!regulator_node) {
  27. dev_err(dev, "%s: Looking up %s property in node %s failed",
  28. __func__, prop_name, dev->of_node->full_name);
  29. rc = -EINVAL;
  30. goto done;
  31. }
  32. cdc_vreg->name = name;
  33. cdc_vreg->ondemand = is_ond;
  34. /* Parse supply - voltage */
  35. snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "qcom,%s-voltage", name);
  36. prop = of_get_property(dev->of_node, prop_name, &len);
  37. if (!prop || (len != (2 * sizeof(__be32)))) {
  38. dev_err(dev, "%s: %s %s property\n", __func__,
  39. prop ? "invalid format" : "no", prop_name);
  40. rc = -EINVAL;
  41. goto done;
  42. } else {
  43. cdc_vreg->min_uV = be32_to_cpup(&prop[0]);
  44. cdc_vreg->max_uV = be32_to_cpup(&prop[1]);
  45. }
  46. /* Parse supply - current */
  47. snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "qcom,%s-current", name);
  48. rc = of_property_read_u32(dev->of_node, prop_name, &prop_val);
  49. if (rc) {
  50. dev_err(dev, "%s: Looking up %s property in node %s failed",
  51. __func__, prop_name, dev->of_node->full_name);
  52. goto done;
  53. }
  54. cdc_vreg->optimum_uA = prop_val;
  55. /* Parse supply - LPM or NOM mode(default NOM) */
  56. snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "qcom,%s-lpm-supported", name);
  57. rc = of_property_read_u32(dev->of_node, prop_name, &prop_val);
  58. if (rc) {
  59. dev_dbg(dev, "%s: Looking up %s property in node %s failed",
  60. __func__, prop_name, dev->of_node->full_name);
  61. cdc_vreg->lpm_supported = 0;
  62. rc = 0;
  63. } else {
  64. cdc_vreg->lpm_supported = prop_val;
  65. }
  66. dev_info(dev, "%s: %s: vol=[%d %d]uV, curr=[%d]uA, ond %d lpm %d\n",
  67. __func__, cdc_vreg->name, cdc_vreg->min_uV, cdc_vreg->max_uV,
  68. cdc_vreg->optimum_uA, cdc_vreg->ondemand,
  69. cdc_vreg->lpm_supported);
  70. done:
  71. return rc;
  72. }
  73. static int msm_cdc_parse_supplies(struct device *dev,
  74. struct cdc_regulator *cdc_reg,
  75. const char *sup_list, int sup_cnt,
  76. bool is_ond)
  77. {
  78. int idx, rc = 0;
  79. const char *name = NULL;
  80. for (idx = 0; idx < sup_cnt; idx++) {
  81. rc = of_property_read_string_index(dev->of_node, sup_list, idx,
  82. &name);
  83. if (rc) {
  84. dev_err(dev, "%s: read string %s[%d] error (%d)\n",
  85. __func__, sup_list, idx, rc);
  86. goto done;
  87. }
  88. dev_dbg(dev, "%s: Found cdc supply %s as part of %s\n",
  89. __func__, name, sup_list);
  90. rc = msm_cdc_dt_parse_vreg_info(dev, &cdc_reg[idx], name,
  91. is_ond);
  92. if (rc) {
  93. dev_err(dev, "%s: parse %s vreg info failed (%d)\n",
  94. __func__, name, rc);
  95. goto done;
  96. }
  97. }
  98. done:
  99. return rc;
  100. }
  101. static int msm_cdc_check_supply_param(struct device *dev,
  102. struct cdc_regulator *cdc_vreg,
  103. int num_supplies)
  104. {
  105. if (!dev) {
  106. pr_err("%s: device is NULL\n", __func__);
  107. return -ENODEV;
  108. }
  109. if (!cdc_vreg || (num_supplies <= 0)) {
  110. dev_err(dev, "%s: supply check failed: vreg: %pK, num_supplies: %d\n",
  111. __func__, cdc_vreg, num_supplies);
  112. return -EINVAL;
  113. }
  114. return 0;
  115. }
  116. /*
  117. * msm_cdc_is_ondemand_supply:
  118. * return if ondemand supply true or not
  119. *
  120. * @dev: pointer to codec device
  121. * @supplies: pointer to regulator bulk data
  122. * @cdc_vreg: pointer to platform regulator data
  123. * @num_supplies: number of supplies
  124. * @supply_name: supply name to be checked
  125. *
  126. * Return true/false
  127. */
  128. bool msm_cdc_is_ondemand_supply(struct device *dev,
  129. struct regulator_bulk_data *supplies,
  130. struct cdc_regulator *cdc_vreg,
  131. int num_supplies,
  132. char *supply_name)
  133. {
  134. bool rc = false;
  135. int ret, i;
  136. if ((!supply_name) || (!supplies)) {
  137. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  138. __func__);
  139. return rc;
  140. }
  141. /* input parameter validation */
  142. ret = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  143. if (ret)
  144. return rc;
  145. for (i = 0; i < num_supplies; i++) {
  146. if (cdc_vreg[i].ondemand &&
  147. !strcmp(cdc_vreg[i].name, supply_name))
  148. return true;
  149. }
  150. return rc;
  151. }
  152. EXPORT_SYMBOL(msm_cdc_is_ondemand_supply);
  153. /*
  154. * msm_cdc_disable_ondemand_supply:
  155. * Disable codec ondemand supply
  156. *
  157. * @dev: pointer to codec device
  158. * @supplies: pointer to regulator bulk data
  159. * @cdc_vreg: pointer to platform regulator data
  160. * @num_supplies: number of supplies
  161. * @supply_name: Ondemand supply name to be enabled
  162. *
  163. * Return error code if supply disable is failed
  164. */
  165. int msm_cdc_disable_ondemand_supply(struct device *dev,
  166. struct regulator_bulk_data *supplies,
  167. struct cdc_regulator *cdc_vreg,
  168. int num_supplies,
  169. char *supply_name)
  170. {
  171. int rc, i;
  172. if ((!supply_name) || (!supplies)) {
  173. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  174. __func__);
  175. return -EINVAL;
  176. }
  177. /* input parameter validation */
  178. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  179. if (rc)
  180. return rc;
  181. for (i = 0; i < num_supplies; i++) {
  182. if (cdc_vreg[i].ondemand &&
  183. !strcmp(cdc_vreg[i].name, supply_name)) {
  184. rc = regulator_disable(supplies[i].consumer);
  185. if (rc)
  186. dev_err(dev, "%s: failed to disable supply %s, err:%d\n",
  187. __func__, supplies[i].supply, rc);
  188. break;
  189. }
  190. }
  191. if (i == num_supplies) {
  192. dev_err(dev, "%s: not able to find supply %s\n",
  193. __func__, supply_name);
  194. rc = -EINVAL;
  195. }
  196. return rc;
  197. }
  198. EXPORT_SYMBOL(msm_cdc_disable_ondemand_supply);
  199. /*
  200. * msm_cdc_enable_ondemand_supply:
  201. * Enable codec ondemand supply
  202. *
  203. * @dev: pointer to codec device
  204. * @supplies: pointer to regulator bulk data
  205. * @cdc_vreg: pointer to platform regulator data
  206. * @num_supplies: number of supplies
  207. * @supply_name: Ondemand supply name to be enabled
  208. *
  209. * Return error code if supply enable is failed
  210. */
  211. int msm_cdc_enable_ondemand_supply(struct device *dev,
  212. struct regulator_bulk_data *supplies,
  213. struct cdc_regulator *cdc_vreg,
  214. int num_supplies,
  215. char *supply_name)
  216. {
  217. int rc, i;
  218. if ((!supply_name) || (!supplies)) {
  219. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  220. __func__);
  221. return -EINVAL;
  222. }
  223. /* input parameter validation */
  224. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  225. if (rc)
  226. return rc;
  227. for (i = 0; i < num_supplies; i++) {
  228. if (cdc_vreg[i].ondemand &&
  229. !strcmp(cdc_vreg[i].name, supply_name)) {
  230. rc = regulator_enable(supplies[i].consumer);
  231. if (rc)
  232. dev_err(dev, "%s: failed to enable supply %s, rc: %d\n",
  233. __func__, supplies[i].supply, rc);
  234. break;
  235. }
  236. }
  237. if (i == num_supplies) {
  238. dev_err(dev, "%s: not able to find supply %s\n",
  239. __func__, supply_name);
  240. rc = -EINVAL;
  241. }
  242. return rc;
  243. }
  244. EXPORT_SYMBOL(msm_cdc_enable_ondemand_supply);
  245. /*
  246. * msm_cdc_set_supplies_lpm_mode:
  247. * Update load for given supply string
  248. *
  249. * @dev: pointer to codec device
  250. * @supplies: pointer to regulator bulk data
  251. * @cdc_vreg: pointer to platform regulator data
  252. * @num_supplies: number of supplies
  253. * @supply_name: supply name to be checked
  254. * @min_max: Apply optimum or 0 current
  255. *
  256. * Return error code if set current fail
  257. */
  258. int msm_cdc_set_supplies_lpm_mode(struct device *dev,
  259. struct regulator_bulk_data *supplies,
  260. struct cdc_regulator *cdc_vreg,
  261. int num_supplies,
  262. bool flag)
  263. {
  264. int rc = 0, i;
  265. if (!supplies) {
  266. pr_err("%s: supplies is NULL\n",
  267. __func__);
  268. return -EINVAL;
  269. }
  270. /* input parameter validation */
  271. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  272. if (rc)
  273. return rc;
  274. for (i = 0; i < num_supplies; i++) {
  275. if (cdc_vreg[i].lpm_supported) {
  276. rc = regulator_set_load(
  277. supplies[i].consumer,
  278. flag ? 0 : cdc_vreg[i].optimum_uA);
  279. if (rc)
  280. dev_err(dev,
  281. "%s: failed to set supply %s to %s, err:%d\n",
  282. __func__, supplies[i].supply,
  283. flag ? "LPM" : "NOM",
  284. rc);
  285. else
  286. dev_dbg(dev, "%s: regulator %s load set to %s\n",
  287. __func__, supplies[i].supply,
  288. flag ? "LPM" : "NOM");
  289. }
  290. }
  291. return rc;
  292. }
  293. EXPORT_SYMBOL(msm_cdc_set_supplies_lpm_mode);
  294. /*
  295. * msm_cdc_disable_static_supplies:
  296. * Disable codec static supplies
  297. *
  298. * @dev: pointer to codec device
  299. * @supplies: pointer to regulator bulk data
  300. * @cdc_vreg: pointer to platform regulator data
  301. * @num_supplies: number of supplies
  302. *
  303. * Return error code if supply disable is failed
  304. */
  305. int msm_cdc_disable_static_supplies(struct device *dev,
  306. struct regulator_bulk_data *supplies,
  307. struct cdc_regulator *cdc_vreg,
  308. int num_supplies)
  309. {
  310. int rc, i;
  311. if ((!dev) || (!supplies) || (!cdc_vreg)) {
  312. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  313. __func__);
  314. return -EINVAL;
  315. }
  316. /* input parameter validation */
  317. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  318. if (rc)
  319. return rc;
  320. for (i = 0; i < num_supplies; i++) {
  321. if (cdc_vreg[i].ondemand)
  322. continue;
  323. rc = regulator_disable(supplies[i].consumer);
  324. if (rc)
  325. dev_err(dev, "%s: failed to disable supply %s, err:%d\n",
  326. __func__, supplies[i].supply, rc);
  327. else
  328. dev_dbg(dev, "%s: disabled regulator %s\n",
  329. __func__, supplies[i].supply);
  330. }
  331. return rc;
  332. }
  333. EXPORT_SYMBOL(msm_cdc_disable_static_supplies);
  334. /*
  335. * msm_cdc_release_supplies:
  336. * Release codec power supplies
  337. *
  338. * @dev: pointer to codec device
  339. * @supplies: pointer to regulator bulk data
  340. * @cdc_vreg: pointer to platform regulator data
  341. * @num_supplies: number of supplies
  342. *
  343. * Return error code if supply disable is failed
  344. */
  345. int msm_cdc_release_supplies(struct device *dev,
  346. struct regulator_bulk_data *supplies,
  347. struct cdc_regulator *cdc_vreg,
  348. int num_supplies)
  349. {
  350. int rc = 0;
  351. int i;
  352. if ((!dev) || (!supplies) || (!cdc_vreg)) {
  353. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  354. __func__);
  355. return -EINVAL;
  356. }
  357. /* input parameter validation */
  358. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  359. if (rc)
  360. return rc;
  361. msm_cdc_disable_static_supplies(dev, supplies, cdc_vreg,
  362. num_supplies);
  363. for (i = 0; i < num_supplies; i++) {
  364. if (regulator_count_voltages(supplies[i].consumer) < 0)
  365. continue;
  366. regulator_set_voltage(supplies[i].consumer, 0,
  367. cdc_vreg[i].max_uV);
  368. regulator_set_load(supplies[i].consumer, 0);
  369. }
  370. return rc;
  371. }
  372. EXPORT_SYMBOL(msm_cdc_release_supplies);
  373. /*
  374. * msm_cdc_enable_static_supplies:
  375. * Enable codec static supplies
  376. *
  377. * @dev: pointer to codec device
  378. * @supplies: pointer to regulator bulk data
  379. * @cdc_vreg: pointer to platform regulator data
  380. * @num_supplies: number of supplies
  381. *
  382. * Return error code if supply enable is failed
  383. */
  384. int msm_cdc_enable_static_supplies(struct device *dev,
  385. struct regulator_bulk_data *supplies,
  386. struct cdc_regulator *cdc_vreg,
  387. int num_supplies)
  388. {
  389. int rc, i;
  390. if ((!dev) || (!supplies) || (!cdc_vreg)) {
  391. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  392. __func__);
  393. return -EINVAL;
  394. }
  395. /* input parameter validation */
  396. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  397. if (rc)
  398. return rc;
  399. for (i = 0; i < num_supplies; i++) {
  400. if (cdc_vreg[i].ondemand)
  401. continue;
  402. rc = regulator_enable(supplies[i].consumer);
  403. if (rc) {
  404. dev_err(dev, "%s: failed to enable supply %s, rc: %d\n",
  405. __func__, supplies[i].supply, rc);
  406. break;
  407. }
  408. }
  409. while (rc && i--)
  410. if (!cdc_vreg[i].ondemand)
  411. regulator_disable(supplies[i].consumer);
  412. return rc;
  413. }
  414. EXPORT_SYMBOL(msm_cdc_enable_static_supplies);
  415. /*
  416. * msm_cdc_init_supplies:
  417. * Initialize codec static supplies
  418. *
  419. * @dev: pointer to codec device
  420. * @supplies: pointer to regulator bulk data
  421. * @cdc_vreg: pointer to platform regulator data
  422. * @num_supplies: number of supplies
  423. *
  424. * Return error code if supply init is failed
  425. */
  426. int msm_cdc_init_supplies(struct device *dev,
  427. struct regulator_bulk_data **supplies,
  428. struct cdc_regulator *cdc_vreg,
  429. int num_supplies)
  430. {
  431. return msm_cdc_init_supplies_v2(dev, supplies, cdc_vreg,
  432. num_supplies, false);
  433. }
  434. EXPORT_SYMBOL(msm_cdc_init_supplies);
  435. /*
  436. * msm_cdc_init_supplies_v2:
  437. * Initialize codec static supplies.
  438. * Initialize codec dynamic supplies based on vote_regulator_on_demand
  439. *
  440. * @dev: pointer to codec device
  441. * @supplies: pointer to regulator bulk data
  442. * @cdc_vreg: pointer to platform regulator data
  443. * @num_supplies: number of supplies
  444. * @vote_regulator_on_demand: initialize codec dynamic supplies at runtime
  445. *
  446. * Return error code if supply init is failed
  447. */
  448. int msm_cdc_init_supplies_v2(struct device *dev,
  449. struct regulator_bulk_data **supplies,
  450. struct cdc_regulator *cdc_vreg,
  451. int num_supplies, u32 vote_regulator_on_demand)
  452. {
  453. struct regulator_bulk_data *vsup;
  454. int rc;
  455. int i;
  456. if (!dev || !cdc_vreg) {
  457. pr_err("%s: device pointer or dce_vreg is NULL\n",
  458. __func__);
  459. return -EINVAL;
  460. }
  461. /* input parameter validation */
  462. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  463. if (rc)
  464. return rc;
  465. vsup = devm_kcalloc(dev, num_supplies,
  466. sizeof(struct regulator_bulk_data),
  467. GFP_KERNEL);
  468. if (!vsup)
  469. return -ENOMEM;
  470. for (i = 0; i < num_supplies; i++) {
  471. if (!cdc_vreg[i].name) {
  472. dev_err(dev, "%s: supply name not defined\n",
  473. __func__);
  474. rc = -EINVAL;
  475. goto err_supply;
  476. }
  477. vsup[i].supply = cdc_vreg[i].name;
  478. }
  479. rc = devm_regulator_bulk_get(dev, num_supplies, vsup);
  480. if (rc) {
  481. dev_err(dev, "%s: failed to get supplies (%d)\n",
  482. __func__, rc);
  483. goto err_supply;
  484. }
  485. /* Set voltage and current on regulators */
  486. for (i = 0; i < num_supplies; i++) {
  487. if (regulator_count_voltages(vsup[i].consumer) < 0)
  488. continue;
  489. if (cdc_vreg[i].ondemand && vote_regulator_on_demand)
  490. continue;
  491. rc = regulator_set_voltage(vsup[i].consumer,
  492. cdc_vreg[i].min_uV,
  493. cdc_vreg[i].max_uV);
  494. if (rc) {
  495. dev_err(dev, "%s: set regulator voltage failed for %s, err:%d\n",
  496. __func__, vsup[i].supply, rc);
  497. goto err_supply;
  498. }
  499. rc = regulator_set_load(vsup[i].consumer,
  500. cdc_vreg[i].optimum_uA);
  501. if (rc < 0) {
  502. dev_err(dev, "%s: set regulator optimum mode failed for %s, err:%d\n",
  503. __func__, vsup[i].supply, rc);
  504. goto err_supply;
  505. }
  506. }
  507. *supplies = vsup;
  508. return 0;
  509. err_supply:
  510. return rc;
  511. }
  512. EXPORT_SYMBOL(msm_cdc_init_supplies_v2);
  513. /*
  514. * msm_cdc_get_power_supplies:
  515. * Get codec power supplies from device tree.
  516. * Allocate memory to hold regulator data for
  517. * all power supplies.
  518. *
  519. * @dev: pointer to codec device
  520. * @cdc_vreg: pointer to codec regulator
  521. * @total_num_supplies: total number of supplies read from DT
  522. *
  523. * Return error code if supply disable is failed
  524. */
  525. int msm_cdc_get_power_supplies(struct device *dev,
  526. struct cdc_regulator **cdc_vreg,
  527. int *total_num_supplies)
  528. {
  529. const char *static_prop_name = "qcom,cdc-static-supplies";
  530. const char *ond_prop_name = "qcom,cdc-on-demand-supplies";
  531. const char *cp_prop_name = "qcom,cdc-cp-supplies";
  532. int static_sup_cnt = 0;
  533. int ond_sup_cnt = 0;
  534. int cp_sup_cnt = 0;
  535. int num_supplies = 0;
  536. struct cdc_regulator *cdc_reg;
  537. int rc;
  538. if (!dev) {
  539. pr_err("%s: device pointer is NULL\n", __func__);
  540. return -EINVAL;
  541. }
  542. static_sup_cnt = of_property_count_strings(dev->of_node,
  543. static_prop_name);
  544. if (static_sup_cnt < 0) {
  545. dev_err(dev, "%s: Failed to get static supplies(%d)\n",
  546. __func__, static_sup_cnt);
  547. rc = static_sup_cnt;
  548. goto err_supply_cnt;
  549. }
  550. ond_sup_cnt = of_property_count_strings(dev->of_node, ond_prop_name);
  551. if (ond_sup_cnt < 0)
  552. ond_sup_cnt = 0;
  553. cp_sup_cnt = of_property_count_strings(dev->of_node,
  554. cp_prop_name);
  555. if (cp_sup_cnt < 0)
  556. cp_sup_cnt = 0;
  557. num_supplies = static_sup_cnt + ond_sup_cnt + cp_sup_cnt;
  558. if (num_supplies <= 0) {
  559. dev_err(dev, "%s: supply count is 0 or negative\n", __func__);
  560. rc = -EINVAL;
  561. goto err_supply_cnt;
  562. }
  563. cdc_reg = devm_kcalloc(dev, num_supplies,
  564. sizeof(struct cdc_regulator),
  565. GFP_KERNEL);
  566. if (!cdc_reg) {
  567. rc = -ENOMEM;
  568. goto err_mem_alloc;
  569. }
  570. rc = msm_cdc_parse_supplies(dev, cdc_reg, static_prop_name,
  571. static_sup_cnt, false);
  572. if (rc) {
  573. dev_err(dev, "%s: failed to parse static supplies(%d)\n",
  574. __func__, rc);
  575. goto err_sup;
  576. }
  577. rc = msm_cdc_parse_supplies(dev, &cdc_reg[static_sup_cnt],
  578. ond_prop_name, ond_sup_cnt,
  579. true);
  580. if (rc) {
  581. dev_err(dev, "%s: failed to parse demand supplies(%d)\n",
  582. __func__, rc);
  583. goto err_sup;
  584. }
  585. rc = msm_cdc_parse_supplies(dev,
  586. &cdc_reg[static_sup_cnt + ond_sup_cnt],
  587. cp_prop_name, cp_sup_cnt, true);
  588. if (rc) {
  589. dev_err(dev, "%s: failed to parse cp supplies(%d)\n",
  590. __func__, rc);
  591. goto err_sup;
  592. }
  593. *cdc_vreg = cdc_reg;
  594. *total_num_supplies = num_supplies;
  595. return 0;
  596. err_sup:
  597. err_supply_cnt:
  598. err_mem_alloc:
  599. return rc;
  600. }
  601. EXPORT_SYMBOL(msm_cdc_get_power_supplies);
  602. /*
  603. * msm_cdc_init_wcd_supply:
  604. * Initialize wcd supply parameters.
  605. *
  606. * @np: device node pointer to codec device
  607. * @name: power supply name
  608. * @cdc_supply: codec supply struct to hold wcd params
  609. *
  610. * Return error code if init failed
  611. */
  612. int msm_cdc_init_wcd_supply(struct device_node *np, const char *name,
  613. struct cdc_wcd_supply *cdc_supply)
  614. {
  615. struct platform_device *pdev = NULL;
  616. if (!np || !cdc_supply)
  617. return -EINVAL;
  618. pdev = of_find_device_by_node(np);
  619. if (!pdev)
  620. return -EINVAL;
  621. cdc_supply->dev = &pdev->dev;
  622. cdc_supply->name = name;
  623. cdc_supply->component = snd_soc_lookup_component(&pdev->dev, NULL);
  624. return 0;
  625. }
  626. EXPORT_SYMBOL(msm_cdc_init_wcd_supply);
  627. /*
  628. * msm_cdc_enable_wcd_supply:
  629. * Enable/Disable wcd supply.
  630. *
  631. * @cdc_supply: codec supply struct to hold wcd params
  632. * @enable: bool to inform whether to enable or disable
  633. *
  634. * Return error code if enable/disable failed
  635. */
  636. int msm_cdc_enable_wcd_supply(struct cdc_wcd_supply *cdc_supply, bool enable)
  637. {
  638. struct snd_soc_component *component = cdc_supply->component;
  639. int rc;
  640. if (!component) {
  641. pr_err("%s: Component memory is NULL\n", __func__);
  642. return -EINVAL;
  643. }
  644. if (enable)
  645. rc = snd_soc_dapm_force_enable_pin(
  646. snd_soc_component_get_dapm(component),
  647. cdc_supply->name);
  648. else
  649. rc = snd_soc_dapm_disable_pin(
  650. snd_soc_component_get_dapm(component),
  651. cdc_supply->name);
  652. if (!rc)
  653. snd_soc_dapm_sync(snd_soc_component_get_dapm(component));
  654. else
  655. dev_err(component->dev, "%s: micbias %s force %s pin failed\n",
  656. __func__, cdc_supply->name, (enable ? "enable" : "disable"));
  657. return rc;
  658. }
  659. EXPORT_SYMBOL(msm_cdc_enable_wcd_supply);