msm-cdc-supply.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  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_set_supply_min_voltage:
  155. * Set min supply voltage for particular 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: Supply name to change voltage for
  162. * @vval_min: Min voltage to be set in uV
  163. * @override_min_vol: True if override min voltage from default
  164. * Return error code if unable to set voltage
  165. */
  166. int msm_cdc_set_supply_min_voltage(struct device *dev,
  167. struct regulator_bulk_data *supplies,
  168. struct cdc_regulator *cdc_vreg,
  169. int num_supplies, char *supply_name,
  170. int vval_min, bool override_min_vol)
  171. {
  172. int rc = 0, i;
  173. if ((!supply_name) || (!supplies)) {
  174. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  175. __func__);
  176. return -EINVAL;
  177. }
  178. /* input parameter validation */
  179. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  180. if (rc)
  181. return rc;
  182. for (i = 0; i < num_supplies; i++) {
  183. if (!strcmp(cdc_vreg[i].name, supply_name)) {
  184. if (override_min_vol)
  185. regulator_set_voltage(supplies[i].consumer,
  186. vval_min, cdc_vreg[i].max_uV);
  187. else
  188. regulator_set_voltage(supplies[i].consumer,
  189. cdc_vreg[i].min_uV, cdc_vreg[i].max_uV);
  190. break;
  191. }
  192. }
  193. return rc;
  194. }
  195. EXPORT_SYMBOL(msm_cdc_set_supply_min_voltage);
  196. /*
  197. * msm_cdc_disable_ondemand_supply:
  198. * Disable codec ondemand supply
  199. *
  200. * @dev: pointer to codec device
  201. * @supplies: pointer to regulator bulk data
  202. * @cdc_vreg: pointer to platform regulator data
  203. * @num_supplies: number of supplies
  204. * @supply_name: Ondemand supply name to be enabled
  205. *
  206. * Return error code if supply disable is failed
  207. */
  208. int msm_cdc_disable_ondemand_supply(struct device *dev,
  209. struct regulator_bulk_data *supplies,
  210. struct cdc_regulator *cdc_vreg,
  211. int num_supplies,
  212. char *supply_name)
  213. {
  214. int rc, i;
  215. if ((!supply_name) || (!supplies)) {
  216. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  217. __func__);
  218. return -EINVAL;
  219. }
  220. /* input parameter validation */
  221. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  222. if (rc)
  223. return rc;
  224. for (i = 0; i < num_supplies; i++) {
  225. if (cdc_vreg[i].ondemand &&
  226. !strcmp(cdc_vreg[i].name, supply_name)) {
  227. rc = regulator_disable(supplies[i].consumer);
  228. if (rc)
  229. dev_err(dev, "%s: failed to disable supply %s, err:%d\n",
  230. __func__, supplies[i].supply, rc);
  231. break;
  232. }
  233. }
  234. if (i == num_supplies) {
  235. dev_err(dev, "%s: not able to find supply %s\n",
  236. __func__, supply_name);
  237. rc = -EINVAL;
  238. }
  239. return rc;
  240. }
  241. EXPORT_SYMBOL(msm_cdc_disable_ondemand_supply);
  242. /*
  243. * msm_cdc_enable_ondemand_supply:
  244. * Enable codec ondemand supply
  245. *
  246. * @dev: pointer to codec device
  247. * @supplies: pointer to regulator bulk data
  248. * @cdc_vreg: pointer to platform regulator data
  249. * @num_supplies: number of supplies
  250. * @supply_name: Ondemand supply name to be enabled
  251. *
  252. * Return error code if supply enable is failed
  253. */
  254. int msm_cdc_enable_ondemand_supply(struct device *dev,
  255. struct regulator_bulk_data *supplies,
  256. struct cdc_regulator *cdc_vreg,
  257. int num_supplies,
  258. char *supply_name)
  259. {
  260. int rc, i;
  261. if ((!supply_name) || (!supplies)) {
  262. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  263. __func__);
  264. return -EINVAL;
  265. }
  266. /* input parameter validation */
  267. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  268. if (rc)
  269. return rc;
  270. for (i = 0; i < num_supplies; i++) {
  271. if (cdc_vreg[i].ondemand &&
  272. !strcmp(cdc_vreg[i].name, supply_name)) {
  273. rc = regulator_enable(supplies[i].consumer);
  274. if (rc)
  275. dev_err(dev, "%s: failed to enable supply %s, rc: %d\n",
  276. __func__, supplies[i].supply, rc);
  277. break;
  278. }
  279. }
  280. if (i == num_supplies) {
  281. dev_err(dev, "%s: not able to find supply %s\n",
  282. __func__, supply_name);
  283. rc = -EINVAL;
  284. }
  285. return rc;
  286. }
  287. EXPORT_SYMBOL(msm_cdc_enable_ondemand_supply);
  288. /*
  289. * msm_cdc_set_supplies_lpm_mode:
  290. * Update load for given supply string
  291. *
  292. * @dev: pointer to codec device
  293. * @supplies: pointer to regulator bulk data
  294. * @cdc_vreg: pointer to platform regulator data
  295. * @num_supplies: number of supplies
  296. * @supply_name: supply name to be checked
  297. * @min_max: Apply optimum or 0 current
  298. *
  299. * Return error code if set current fail
  300. */
  301. int msm_cdc_set_supplies_lpm_mode(struct device *dev,
  302. struct regulator_bulk_data *supplies,
  303. struct cdc_regulator *cdc_vreg,
  304. int num_supplies,
  305. bool flag)
  306. {
  307. int rc = 0, i;
  308. if (!supplies) {
  309. pr_err("%s: supplies is NULL\n",
  310. __func__);
  311. return -EINVAL;
  312. }
  313. /* input parameter validation */
  314. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  315. if (rc)
  316. return rc;
  317. for (i = 0; i < num_supplies; i++) {
  318. if (cdc_vreg[i].lpm_supported) {
  319. rc = regulator_set_load(
  320. supplies[i].consumer,
  321. flag ? 0 : cdc_vreg[i].optimum_uA);
  322. if (rc)
  323. dev_err(dev,
  324. "%s: failed to set supply %s to %s, err:%d\n",
  325. __func__, supplies[i].supply,
  326. flag ? "LPM" : "NOM",
  327. rc);
  328. else
  329. dev_dbg(dev, "%s: regulator %s load set to %s\n",
  330. __func__, supplies[i].supply,
  331. flag ? "LPM" : "NOM");
  332. }
  333. }
  334. return rc;
  335. }
  336. EXPORT_SYMBOL(msm_cdc_set_supplies_lpm_mode);
  337. /*
  338. * msm_cdc_disable_static_supplies:
  339. * Disable codec static supplies
  340. *
  341. * @dev: pointer to codec device
  342. * @supplies: pointer to regulator bulk data
  343. * @cdc_vreg: pointer to platform regulator data
  344. * @num_supplies: number of supplies
  345. *
  346. * Return error code if supply disable is failed
  347. */
  348. int msm_cdc_disable_static_supplies(struct device *dev,
  349. struct regulator_bulk_data *supplies,
  350. struct cdc_regulator *cdc_vreg,
  351. int num_supplies)
  352. {
  353. int rc, i;
  354. if ((!dev) || (!supplies) || (!cdc_vreg)) {
  355. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  356. __func__);
  357. return -EINVAL;
  358. }
  359. /* input parameter validation */
  360. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  361. if (rc)
  362. return rc;
  363. for (i = 0; i < num_supplies; i++) {
  364. if (cdc_vreg[i].ondemand)
  365. continue;
  366. rc = regulator_disable(supplies[i].consumer);
  367. if (rc)
  368. dev_err(dev, "%s: failed to disable supply %s, err:%d\n",
  369. __func__, supplies[i].supply, rc);
  370. else
  371. dev_dbg(dev, "%s: disabled regulator %s\n",
  372. __func__, supplies[i].supply);
  373. }
  374. return rc;
  375. }
  376. EXPORT_SYMBOL(msm_cdc_disable_static_supplies);
  377. /*
  378. * msm_cdc_release_supplies:
  379. * Release codec power supplies
  380. *
  381. * @dev: pointer to codec device
  382. * @supplies: pointer to regulator bulk data
  383. * @cdc_vreg: pointer to platform regulator data
  384. * @num_supplies: number of supplies
  385. *
  386. * Return error code if supply disable is failed
  387. */
  388. int msm_cdc_release_supplies(struct device *dev,
  389. struct regulator_bulk_data *supplies,
  390. struct cdc_regulator *cdc_vreg,
  391. int num_supplies)
  392. {
  393. int rc = 0;
  394. int i;
  395. if ((!dev) || (!supplies) || (!cdc_vreg)) {
  396. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  397. __func__);
  398. return -EINVAL;
  399. }
  400. /* input parameter validation */
  401. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  402. if (rc)
  403. return rc;
  404. msm_cdc_disable_static_supplies(dev, supplies, cdc_vreg,
  405. num_supplies);
  406. for (i = 0; i < num_supplies; i++) {
  407. if (regulator_count_voltages(supplies[i].consumer) < 0)
  408. continue;
  409. regulator_set_voltage(supplies[i].consumer, 0,
  410. cdc_vreg[i].max_uV);
  411. regulator_set_load(supplies[i].consumer, 0);
  412. }
  413. return rc;
  414. }
  415. EXPORT_SYMBOL(msm_cdc_release_supplies);
  416. /*
  417. * msm_cdc_enable_static_supplies:
  418. * Enable codec static supplies
  419. *
  420. * @dev: pointer to codec device
  421. * @supplies: pointer to regulator bulk data
  422. * @cdc_vreg: pointer to platform regulator data
  423. * @num_supplies: number of supplies
  424. *
  425. * Return error code if supply enable is failed
  426. */
  427. int msm_cdc_enable_static_supplies(struct device *dev,
  428. struct regulator_bulk_data *supplies,
  429. struct cdc_regulator *cdc_vreg,
  430. int num_supplies)
  431. {
  432. int rc, i;
  433. if ((!dev) || (!supplies) || (!cdc_vreg)) {
  434. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  435. __func__);
  436. return -EINVAL;
  437. }
  438. /* input parameter validation */
  439. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  440. if (rc)
  441. return rc;
  442. for (i = 0; i < num_supplies; i++) {
  443. if (cdc_vreg[i].ondemand)
  444. continue;
  445. rc = regulator_enable(supplies[i].consumer);
  446. if (rc) {
  447. dev_err(dev, "%s: failed to enable supply %s, rc: %d\n",
  448. __func__, supplies[i].supply, rc);
  449. break;
  450. }
  451. }
  452. while (rc && i--)
  453. if (!cdc_vreg[i].ondemand)
  454. regulator_disable(supplies[i].consumer);
  455. return rc;
  456. }
  457. EXPORT_SYMBOL(msm_cdc_enable_static_supplies);
  458. /*
  459. * msm_cdc_init_supplies:
  460. * Initialize codec static supplies
  461. *
  462. * @dev: pointer to codec device
  463. * @supplies: pointer to regulator bulk data
  464. * @cdc_vreg: pointer to platform regulator data
  465. * @num_supplies: number of supplies
  466. *
  467. * Return error code if supply init is failed
  468. */
  469. int msm_cdc_init_supplies(struct device *dev,
  470. struct regulator_bulk_data **supplies,
  471. struct cdc_regulator *cdc_vreg,
  472. int num_supplies)
  473. {
  474. return msm_cdc_init_supplies_v2(dev, supplies, cdc_vreg,
  475. num_supplies, false);
  476. }
  477. EXPORT_SYMBOL(msm_cdc_init_supplies);
  478. /*
  479. * msm_cdc_init_supplies_v2:
  480. * Initialize codec static supplies.
  481. * Initialize codec dynamic supplies based on vote_regulator_on_demand
  482. *
  483. * @dev: pointer to codec device
  484. * @supplies: pointer to regulator bulk data
  485. * @cdc_vreg: pointer to platform regulator data
  486. * @num_supplies: number of supplies
  487. * @vote_regulator_on_demand: initialize codec dynamic supplies at runtime
  488. *
  489. * Return error code if supply init is failed
  490. */
  491. int msm_cdc_init_supplies_v2(struct device *dev,
  492. struct regulator_bulk_data **supplies,
  493. struct cdc_regulator *cdc_vreg,
  494. int num_supplies, u32 vote_regulator_on_demand)
  495. {
  496. struct regulator_bulk_data *vsup;
  497. int rc;
  498. int i;
  499. if (!dev || !cdc_vreg) {
  500. pr_err("%s: device pointer or dce_vreg is NULL\n",
  501. __func__);
  502. return -EINVAL;
  503. }
  504. /* input parameter validation */
  505. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  506. if (rc)
  507. return rc;
  508. vsup = devm_kcalloc(dev, num_supplies,
  509. sizeof(struct regulator_bulk_data),
  510. GFP_KERNEL);
  511. if (!vsup)
  512. return -ENOMEM;
  513. for (i = 0; i < num_supplies; i++) {
  514. if (!cdc_vreg[i].name) {
  515. dev_err(dev, "%s: supply name not defined\n",
  516. __func__);
  517. rc = -EINVAL;
  518. goto err_supply;
  519. }
  520. vsup[i].supply = cdc_vreg[i].name;
  521. }
  522. rc = devm_regulator_bulk_get(dev, num_supplies, vsup);
  523. if (rc) {
  524. dev_err(dev, "%s: failed to get supplies (%d)\n",
  525. __func__, rc);
  526. goto err_supply;
  527. }
  528. /* Set voltage and current on regulators */
  529. for (i = 0; i < num_supplies; i++) {
  530. if (regulator_count_voltages(vsup[i].consumer) < 0)
  531. continue;
  532. if (cdc_vreg[i].ondemand && vote_regulator_on_demand)
  533. continue;
  534. rc = regulator_set_voltage(vsup[i].consumer,
  535. cdc_vreg[i].min_uV,
  536. cdc_vreg[i].max_uV);
  537. if (rc) {
  538. dev_err(dev, "%s: set regulator voltage failed for %s, err:%d\n",
  539. __func__, vsup[i].supply, rc);
  540. goto err_supply;
  541. }
  542. rc = regulator_set_load(vsup[i].consumer,
  543. cdc_vreg[i].optimum_uA);
  544. if (rc < 0) {
  545. dev_err(dev, "%s: set regulator optimum mode failed for %s, err:%d\n",
  546. __func__, vsup[i].supply, rc);
  547. goto err_supply;
  548. }
  549. }
  550. *supplies = vsup;
  551. return 0;
  552. err_supply:
  553. return rc;
  554. }
  555. EXPORT_SYMBOL(msm_cdc_init_supplies_v2);
  556. /*
  557. * msm_cdc_get_power_supplies:
  558. * Get codec power supplies from device tree.
  559. * Allocate memory to hold regulator data for
  560. * all power supplies.
  561. *
  562. * @dev: pointer to codec device
  563. * @cdc_vreg: pointer to codec regulator
  564. * @total_num_supplies: total number of supplies read from DT
  565. *
  566. * Return error code if supply disable is failed
  567. */
  568. int msm_cdc_get_power_supplies(struct device *dev,
  569. struct cdc_regulator **cdc_vreg,
  570. int *total_num_supplies)
  571. {
  572. const char *static_prop_name = "qcom,cdc-static-supplies";
  573. const char *ond_prop_name = "qcom,cdc-on-demand-supplies";
  574. const char *cp_prop_name = "qcom,cdc-cp-supplies";
  575. int static_sup_cnt = 0;
  576. int ond_sup_cnt = 0;
  577. int cp_sup_cnt = 0;
  578. int num_supplies = 0;
  579. struct cdc_regulator *cdc_reg;
  580. int rc;
  581. if (!dev) {
  582. pr_err("%s: device pointer is NULL\n", __func__);
  583. return -EINVAL;
  584. }
  585. static_sup_cnt = of_property_count_strings(dev->of_node,
  586. static_prop_name);
  587. if (static_sup_cnt < 0) {
  588. dev_err(dev, "%s: Failed to get static supplies(%d)\n",
  589. __func__, static_sup_cnt);
  590. rc = static_sup_cnt;
  591. goto err_supply_cnt;
  592. }
  593. ond_sup_cnt = of_property_count_strings(dev->of_node, ond_prop_name);
  594. if (ond_sup_cnt < 0)
  595. ond_sup_cnt = 0;
  596. cp_sup_cnt = of_property_count_strings(dev->of_node,
  597. cp_prop_name);
  598. if (cp_sup_cnt < 0)
  599. cp_sup_cnt = 0;
  600. num_supplies = static_sup_cnt + ond_sup_cnt + cp_sup_cnt;
  601. if (num_supplies <= 0) {
  602. dev_err(dev, "%s: supply count is 0 or negative\n", __func__);
  603. rc = -EINVAL;
  604. goto err_supply_cnt;
  605. }
  606. cdc_reg = devm_kcalloc(dev, num_supplies,
  607. sizeof(struct cdc_regulator),
  608. GFP_KERNEL);
  609. if (!cdc_reg) {
  610. rc = -ENOMEM;
  611. goto err_mem_alloc;
  612. }
  613. rc = msm_cdc_parse_supplies(dev, cdc_reg, static_prop_name,
  614. static_sup_cnt, false);
  615. if (rc) {
  616. dev_err(dev, "%s: failed to parse static supplies(%d)\n",
  617. __func__, rc);
  618. goto err_sup;
  619. }
  620. rc = msm_cdc_parse_supplies(dev, &cdc_reg[static_sup_cnt],
  621. ond_prop_name, ond_sup_cnt,
  622. true);
  623. if (rc) {
  624. dev_err(dev, "%s: failed to parse demand supplies(%d)\n",
  625. __func__, rc);
  626. goto err_sup;
  627. }
  628. rc = msm_cdc_parse_supplies(dev,
  629. &cdc_reg[static_sup_cnt + ond_sup_cnt],
  630. cp_prop_name, cp_sup_cnt, true);
  631. if (rc) {
  632. dev_err(dev, "%s: failed to parse cp supplies(%d)\n",
  633. __func__, rc);
  634. goto err_sup;
  635. }
  636. *cdc_vreg = cdc_reg;
  637. *total_num_supplies = num_supplies;
  638. return 0;
  639. err_sup:
  640. err_supply_cnt:
  641. err_mem_alloc:
  642. return rc;
  643. }
  644. EXPORT_SYMBOL(msm_cdc_get_power_supplies);
  645. /*
  646. * msm_cdc_init_wcd_supply:
  647. * Initialize wcd supply parameters.
  648. *
  649. * @np: device node pointer to codec device
  650. * @name: power supply name
  651. * @cdc_supply: codec supply struct to hold wcd params
  652. *
  653. * Return error code if init failed
  654. */
  655. int msm_cdc_init_wcd_supply(struct device_node *np, const char *name,
  656. struct cdc_wcd_supply *cdc_supply)
  657. {
  658. struct platform_device *pdev = NULL;
  659. if (!np || !cdc_supply)
  660. return -EINVAL;
  661. pdev = of_find_device_by_node(np);
  662. if (!pdev)
  663. return -EINVAL;
  664. cdc_supply->dev = &pdev->dev;
  665. cdc_supply->name = name;
  666. cdc_supply->component = snd_soc_lookup_component(&pdev->dev, NULL);
  667. return 0;
  668. }
  669. EXPORT_SYMBOL(msm_cdc_init_wcd_supply);
  670. /*
  671. * msm_cdc_enable_wcd_supply:
  672. * Enable/Disable wcd supply.
  673. *
  674. * @cdc_supply: codec supply struct to hold wcd params
  675. * @enable: bool to inform whether to enable or disable
  676. *
  677. * Return error code if enable/disable failed
  678. */
  679. int msm_cdc_enable_wcd_supply(struct cdc_wcd_supply *cdc_supply, bool enable)
  680. {
  681. struct snd_soc_component *component = cdc_supply->component;
  682. int rc;
  683. if (!component) {
  684. pr_err("%s: Component memory is NULL\n", __func__);
  685. return -EINVAL;
  686. }
  687. if (enable)
  688. rc = snd_soc_dapm_force_enable_pin(
  689. snd_soc_component_get_dapm(component),
  690. cdc_supply->name);
  691. else
  692. rc = snd_soc_dapm_disable_pin(
  693. snd_soc_component_get_dapm(component),
  694. cdc_supply->name);
  695. if (!rc)
  696. snd_soc_dapm_sync(snd_soc_component_get_dapm(component));
  697. else
  698. dev_err(component->dev, "%s: micbias %s force %s pin failed\n",
  699. __func__, cdc_supply->name, (enable ? "enable" : "disable"));
  700. return rc;
  701. }
  702. EXPORT_SYMBOL(msm_cdc_enable_wcd_supply);