msm-cdc-supply.c 20 KB

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