msm-cdc-supply.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  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. dev_info(dev, "%s: %s: vol=[%d %d]uV, curr=[%d]uA, ond %d\n",
  56. __func__, cdc_vreg->name, cdc_vreg->min_uV, cdc_vreg->max_uV,
  57. cdc_vreg->optimum_uA, cdc_vreg->ondemand);
  58. done:
  59. return rc;
  60. }
  61. static int msm_cdc_parse_supplies(struct device *dev,
  62. struct cdc_regulator *cdc_reg,
  63. const char *sup_list, int sup_cnt,
  64. bool is_ond)
  65. {
  66. int idx, rc = 0;
  67. const char *name = NULL;
  68. for (idx = 0; idx < sup_cnt; idx++) {
  69. rc = of_property_read_string_index(dev->of_node, sup_list, idx,
  70. &name);
  71. if (rc) {
  72. dev_err(dev, "%s: read string %s[%d] error (%d)\n",
  73. __func__, sup_list, idx, rc);
  74. goto done;
  75. }
  76. dev_dbg(dev, "%s: Found cdc supply %s as part of %s\n",
  77. __func__, name, sup_list);
  78. rc = msm_cdc_dt_parse_vreg_info(dev, &cdc_reg[idx], name,
  79. is_ond);
  80. if (rc) {
  81. dev_err(dev, "%s: parse %s vreg info failed (%d)\n",
  82. __func__, name, rc);
  83. goto done;
  84. }
  85. }
  86. done:
  87. return rc;
  88. }
  89. static int msm_cdc_check_supply_param(struct device *dev,
  90. struct cdc_regulator *cdc_vreg,
  91. int num_supplies)
  92. {
  93. if (!dev) {
  94. pr_err("%s: device is NULL\n", __func__);
  95. return -ENODEV;
  96. }
  97. if (!cdc_vreg || (num_supplies <= 0)) {
  98. dev_err(dev, "%s: supply check failed: vreg: %pK, num_supplies: %d\n",
  99. __func__, cdc_vreg, num_supplies);
  100. return -EINVAL;
  101. }
  102. return 0;
  103. }
  104. /*
  105. * msm_cdc_is_ondemand_supply:
  106. * return if ondemand supply true or not
  107. *
  108. * @dev: pointer to codec device
  109. * @supplies: pointer to regulator bulk data
  110. * @cdc_vreg: pointer to platform regulator data
  111. * @num_supplies: number of supplies
  112. * @supply_name: supply name to be checked
  113. *
  114. * Return true/false
  115. */
  116. bool msm_cdc_is_ondemand_supply(struct device *dev,
  117. struct regulator_bulk_data *supplies,
  118. struct cdc_regulator *cdc_vreg,
  119. int num_supplies,
  120. char *supply_name)
  121. {
  122. bool rc = false;
  123. int ret, i;
  124. if ((!supply_name) || (!supplies)) {
  125. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  126. __func__);
  127. return rc;
  128. }
  129. /* input parameter validation */
  130. ret = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  131. if (ret)
  132. return rc;
  133. for (i = 0; i < num_supplies; i++) {
  134. if (cdc_vreg[i].ondemand &&
  135. !strcmp(cdc_vreg[i].name, supply_name))
  136. return true;
  137. }
  138. return rc;
  139. }
  140. EXPORT_SYMBOL(msm_cdc_is_ondemand_supply);
  141. /*
  142. * msm_cdc_disable_ondemand_supply:
  143. * Disable codec ondemand supply
  144. *
  145. * @dev: pointer to codec device
  146. * @supplies: pointer to regulator bulk data
  147. * @cdc_vreg: pointer to platform regulator data
  148. * @num_supplies: number of supplies
  149. * @supply_name: Ondemand supply name to be enabled
  150. *
  151. * Return error code if supply disable is failed
  152. */
  153. int msm_cdc_disable_ondemand_supply(struct device *dev,
  154. struct regulator_bulk_data *supplies,
  155. struct cdc_regulator *cdc_vreg,
  156. int num_supplies,
  157. char *supply_name)
  158. {
  159. int rc, i;
  160. if ((!supply_name) || (!supplies)) {
  161. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  162. __func__);
  163. return -EINVAL;
  164. }
  165. /* input parameter validation */
  166. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  167. if (rc)
  168. return rc;
  169. for (i = 0; i < num_supplies; i++) {
  170. if (cdc_vreg[i].ondemand &&
  171. !strcmp(cdc_vreg[i].name, supply_name)) {
  172. rc = regulator_disable(supplies[i].consumer);
  173. if (rc)
  174. dev_err(dev, "%s: failed to disable supply %s, err:%d\n",
  175. __func__, supplies[i].supply, rc);
  176. break;
  177. }
  178. }
  179. if (i == num_supplies) {
  180. dev_err(dev, "%s: not able to find supply %s\n",
  181. __func__, supply_name);
  182. rc = -EINVAL;
  183. }
  184. return rc;
  185. }
  186. EXPORT_SYMBOL(msm_cdc_disable_ondemand_supply);
  187. /*
  188. * msm_cdc_enable_ondemand_supply:
  189. * Enable codec ondemand supply
  190. *
  191. * @dev: pointer to codec device
  192. * @supplies: pointer to regulator bulk data
  193. * @cdc_vreg: pointer to platform regulator data
  194. * @num_supplies: number of supplies
  195. * @supply_name: Ondemand supply name to be enabled
  196. *
  197. * Return error code if supply enable is failed
  198. */
  199. int msm_cdc_enable_ondemand_supply(struct device *dev,
  200. struct regulator_bulk_data *supplies,
  201. struct cdc_regulator *cdc_vreg,
  202. int num_supplies,
  203. char *supply_name)
  204. {
  205. int rc, i;
  206. if ((!supply_name) || (!supplies)) {
  207. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  208. __func__);
  209. return -EINVAL;
  210. }
  211. /* input parameter validation */
  212. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  213. if (rc)
  214. return rc;
  215. for (i = 0; i < num_supplies; i++) {
  216. if (cdc_vreg[i].ondemand &&
  217. !strcmp(cdc_vreg[i].name, supply_name)) {
  218. rc = regulator_enable(supplies[i].consumer);
  219. if (rc)
  220. dev_err(dev, "%s: failed to enable supply %s, rc: %d\n",
  221. __func__, supplies[i].supply, rc);
  222. break;
  223. }
  224. }
  225. if (i == num_supplies) {
  226. dev_err(dev, "%s: not able to find supply %s\n",
  227. __func__, supply_name);
  228. rc = -EINVAL;
  229. }
  230. return rc;
  231. }
  232. EXPORT_SYMBOL(msm_cdc_enable_ondemand_supply);
  233. /*
  234. * msm_cdc_disable_static_supplies:
  235. * Disable codec static supplies
  236. *
  237. * @dev: pointer to codec device
  238. * @supplies: pointer to regulator bulk data
  239. * @cdc_vreg: pointer to platform regulator data
  240. * @num_supplies: number of supplies
  241. *
  242. * Return error code if supply disable is failed
  243. */
  244. int msm_cdc_disable_static_supplies(struct device *dev,
  245. struct regulator_bulk_data *supplies,
  246. struct cdc_regulator *cdc_vreg,
  247. int num_supplies)
  248. {
  249. int rc, i;
  250. if ((!dev) || (!supplies) || (!cdc_vreg)) {
  251. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  252. __func__);
  253. return -EINVAL;
  254. }
  255. /* input parameter validation */
  256. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  257. if (rc)
  258. return rc;
  259. for (i = 0; i < num_supplies; i++) {
  260. if (cdc_vreg[i].ondemand)
  261. continue;
  262. rc = regulator_disable(supplies[i].consumer);
  263. if (rc)
  264. dev_err(dev, "%s: failed to disable supply %s, err:%d\n",
  265. __func__, supplies[i].supply, rc);
  266. else
  267. dev_dbg(dev, "%s: disabled regulator %s\n",
  268. __func__, supplies[i].supply);
  269. }
  270. return rc;
  271. }
  272. EXPORT_SYMBOL(msm_cdc_disable_static_supplies);
  273. /*
  274. * msm_cdc_release_supplies:
  275. * Release codec power supplies
  276. *
  277. * @dev: pointer to codec device
  278. * @supplies: pointer to regulator bulk data
  279. * @cdc_vreg: pointer to platform regulator data
  280. * @num_supplies: number of supplies
  281. *
  282. * Return error code if supply disable is failed
  283. */
  284. int msm_cdc_release_supplies(struct device *dev,
  285. struct regulator_bulk_data *supplies,
  286. struct cdc_regulator *cdc_vreg,
  287. int num_supplies)
  288. {
  289. int rc = 0;
  290. int i;
  291. if ((!dev) || (!supplies) || (!cdc_vreg)) {
  292. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  293. __func__);
  294. return -EINVAL;
  295. }
  296. /* input parameter validation */
  297. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  298. if (rc)
  299. return rc;
  300. msm_cdc_disable_static_supplies(dev, supplies, cdc_vreg,
  301. num_supplies);
  302. for (i = 0; i < num_supplies; i++) {
  303. if (regulator_count_voltages(supplies[i].consumer) < 0)
  304. continue;
  305. regulator_set_voltage(supplies[i].consumer, 0,
  306. cdc_vreg[i].max_uV);
  307. regulator_set_load(supplies[i].consumer, 0);
  308. }
  309. return rc;
  310. }
  311. EXPORT_SYMBOL(msm_cdc_release_supplies);
  312. /*
  313. * msm_cdc_enable_static_supplies:
  314. * Enable codec static supplies
  315. *
  316. * @dev: pointer to codec device
  317. * @supplies: pointer to regulator bulk data
  318. * @cdc_vreg: pointer to platform regulator data
  319. * @num_supplies: number of supplies
  320. *
  321. * Return error code if supply enable is failed
  322. */
  323. int msm_cdc_enable_static_supplies(struct device *dev,
  324. struct regulator_bulk_data *supplies,
  325. struct cdc_regulator *cdc_vreg,
  326. int num_supplies)
  327. {
  328. int rc, i;
  329. if ((!dev) || (!supplies) || (!cdc_vreg)) {
  330. pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
  331. __func__);
  332. return -EINVAL;
  333. }
  334. /* input parameter validation */
  335. rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
  336. if (rc)
  337. return rc;
  338. for (i = 0; i < num_supplies; i++) {
  339. if (cdc_vreg[i].ondemand)
  340. continue;
  341. rc = regulator_enable(supplies[i].consumer);
  342. if (rc) {
  343. dev_err(dev, "%s: failed to enable supply %s, rc: %d\n",
  344. __func__, supplies[i].supply, rc);
  345. break;
  346. }
  347. }
  348. while (rc && i--)
  349. if (!cdc_vreg[i].ondemand)
  350. regulator_disable(supplies[i].consumer);
  351. return rc;
  352. }
  353. EXPORT_SYMBOL(msm_cdc_enable_static_supplies);
  354. /*
  355. * msm_cdc_init_supplies:
  356. * Initialize codec static supplies
  357. *
  358. * @dev: pointer to codec device
  359. * @supplies: pointer to regulator bulk data
  360. * @cdc_vreg: pointer to platform regulator data
  361. * @num_supplies: number of supplies
  362. *
  363. * Return error code if supply init is failed
  364. */
  365. int msm_cdc_init_supplies(struct device *dev,
  366. struct regulator_bulk_data **supplies,
  367. struct cdc_regulator *cdc_vreg,
  368. int num_supplies)
  369. {
  370. return msm_cdc_init_supplies_v2(dev, supplies, cdc_vreg,
  371. num_supplies, false);
  372. }
  373. EXPORT_SYMBOL(msm_cdc_init_supplies);
  374. /*
  375. * msm_cdc_init_supplies_v2:
  376. * Initialize codec static supplies.
  377. * Initialize codec dynamic supplies based on vote_regulator_on_demand
  378. *
  379. * @dev: pointer to codec device
  380. * @supplies: pointer to regulator bulk data
  381. * @cdc_vreg: pointer to platform regulator data
  382. * @num_supplies: number of supplies
  383. * @vote_regulator_on_demand: initialize codec dynamic supplies at runtime
  384. *
  385. * Return error code if supply init is failed
  386. */
  387. int msm_cdc_init_supplies_v2(struct device *dev,
  388. struct regulator_bulk_data **supplies,
  389. struct cdc_regulator *cdc_vreg,
  390. int num_supplies, u32 vote_regulator_on_demand)
  391. {
  392. struct regulator_bulk_data *vsup;
  393. int rc;
  394. int i;
  395. if (!dev || !cdc_vreg) {
  396. pr_err("%s: device pointer or dce_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. vsup = devm_kcalloc(dev, num_supplies,
  405. sizeof(struct regulator_bulk_data),
  406. GFP_KERNEL);
  407. if (!vsup)
  408. return -ENOMEM;
  409. for (i = 0; i < num_supplies; i++) {
  410. if (!cdc_vreg[i].name) {
  411. dev_err(dev, "%s: supply name not defined\n",
  412. __func__);
  413. rc = -EINVAL;
  414. goto err_supply;
  415. }
  416. vsup[i].supply = cdc_vreg[i].name;
  417. }
  418. rc = devm_regulator_bulk_get(dev, num_supplies, vsup);
  419. if (rc) {
  420. dev_err(dev, "%s: failed to get supplies (%d)\n",
  421. __func__, rc);
  422. goto err_supply;
  423. }
  424. /* Set voltage and current on regulators */
  425. for (i = 0; i < num_supplies; i++) {
  426. if (regulator_count_voltages(vsup[i].consumer) < 0)
  427. continue;
  428. if (cdc_vreg[i].ondemand && vote_regulator_on_demand)
  429. continue;
  430. rc = regulator_set_voltage(vsup[i].consumer,
  431. cdc_vreg[i].min_uV,
  432. cdc_vreg[i].max_uV);
  433. if (rc) {
  434. dev_err(dev, "%s: set regulator voltage failed for %s, err:%d\n",
  435. __func__, vsup[i].supply, rc);
  436. goto err_supply;
  437. }
  438. rc = regulator_set_load(vsup[i].consumer,
  439. cdc_vreg[i].optimum_uA);
  440. if (rc < 0) {
  441. dev_err(dev, "%s: set regulator optimum mode failed for %s, err:%d\n",
  442. __func__, vsup[i].supply, rc);
  443. goto err_supply;
  444. }
  445. }
  446. *supplies = vsup;
  447. return 0;
  448. err_supply:
  449. return rc;
  450. }
  451. EXPORT_SYMBOL(msm_cdc_init_supplies_v2);
  452. /*
  453. * msm_cdc_get_power_supplies:
  454. * Get codec power supplies from device tree.
  455. * Allocate memory to hold regulator data for
  456. * all power supplies.
  457. *
  458. * @dev: pointer to codec device
  459. * @cdc_vreg: pointer to codec regulator
  460. * @total_num_supplies: total number of supplies read from DT
  461. *
  462. * Return error code if supply disable is failed
  463. */
  464. int msm_cdc_get_power_supplies(struct device *dev,
  465. struct cdc_regulator **cdc_vreg,
  466. int *total_num_supplies)
  467. {
  468. const char *static_prop_name = "qcom,cdc-static-supplies";
  469. const char *ond_prop_name = "qcom,cdc-on-demand-supplies";
  470. const char *cp_prop_name = "qcom,cdc-cp-supplies";
  471. int static_sup_cnt = 0;
  472. int ond_sup_cnt = 0;
  473. int cp_sup_cnt = 0;
  474. int num_supplies = 0;
  475. struct cdc_regulator *cdc_reg;
  476. int rc;
  477. if (!dev) {
  478. pr_err("%s: device pointer is NULL\n", __func__);
  479. return -EINVAL;
  480. }
  481. static_sup_cnt = of_property_count_strings(dev->of_node,
  482. static_prop_name);
  483. if (static_sup_cnt < 0) {
  484. dev_err(dev, "%s: Failed to get static supplies(%d)\n",
  485. __func__, static_sup_cnt);
  486. rc = static_sup_cnt;
  487. goto err_supply_cnt;
  488. }
  489. ond_sup_cnt = of_property_count_strings(dev->of_node, ond_prop_name);
  490. if (ond_sup_cnt < 0)
  491. ond_sup_cnt = 0;
  492. cp_sup_cnt = of_property_count_strings(dev->of_node,
  493. cp_prop_name);
  494. if (cp_sup_cnt < 0)
  495. cp_sup_cnt = 0;
  496. num_supplies = static_sup_cnt + ond_sup_cnt + cp_sup_cnt;
  497. if (num_supplies <= 0) {
  498. dev_err(dev, "%s: supply count is 0 or negative\n", __func__);
  499. rc = -EINVAL;
  500. goto err_supply_cnt;
  501. }
  502. cdc_reg = devm_kcalloc(dev, num_supplies,
  503. sizeof(struct cdc_regulator),
  504. GFP_KERNEL);
  505. if (!cdc_reg) {
  506. rc = -ENOMEM;
  507. goto err_mem_alloc;
  508. }
  509. rc = msm_cdc_parse_supplies(dev, cdc_reg, static_prop_name,
  510. static_sup_cnt, false);
  511. if (rc) {
  512. dev_err(dev, "%s: failed to parse static supplies(%d)\n",
  513. __func__, rc);
  514. goto err_sup;
  515. }
  516. rc = msm_cdc_parse_supplies(dev, &cdc_reg[static_sup_cnt],
  517. ond_prop_name, ond_sup_cnt,
  518. true);
  519. if (rc) {
  520. dev_err(dev, "%s: failed to parse demand supplies(%d)\n",
  521. __func__, rc);
  522. goto err_sup;
  523. }
  524. rc = msm_cdc_parse_supplies(dev,
  525. &cdc_reg[static_sup_cnt + ond_sup_cnt],
  526. cp_prop_name, cp_sup_cnt, true);
  527. if (rc) {
  528. dev_err(dev, "%s: failed to parse cp supplies(%d)\n",
  529. __func__, rc);
  530. goto err_sup;
  531. }
  532. *cdc_vreg = cdc_reg;
  533. *total_num_supplies = num_supplies;
  534. return 0;
  535. err_sup:
  536. err_supply_cnt:
  537. err_mem_alloc:
  538. return rc;
  539. }
  540. EXPORT_SYMBOL(msm_cdc_get_power_supplies);
  541. /*
  542. * msm_cdc_init_wcd_supply:
  543. * Initialize wcd supply parameters.
  544. *
  545. * @np: device node pointer to codec device
  546. * @name: power supply name
  547. * @cdc_supply: codec supply struct to hold wcd params
  548. *
  549. * Return error code if init failed
  550. */
  551. int msm_cdc_init_wcd_supply(struct device_node *np, const char *name,
  552. struct cdc_wcd_supply *cdc_supply)
  553. {
  554. struct platform_device *pdev = NULL;
  555. if (!np || !cdc_supply)
  556. return -EINVAL;
  557. pdev = of_find_device_by_node(np);
  558. if (!pdev)
  559. return -EINVAL;
  560. cdc_supply->dev = &pdev->dev;
  561. cdc_supply->name = name;
  562. cdc_supply->component = snd_soc_lookup_component(&pdev->dev, NULL);
  563. return 0;
  564. }
  565. EXPORT_SYMBOL(msm_cdc_init_wcd_supply);
  566. /*
  567. * msm_cdc_enable_wcd_supply:
  568. * Enable/Disable wcd supply.
  569. *
  570. * @cdc_supply: codec supply struct to hold wcd params
  571. * @enable: bool to inform whether to enable or disable
  572. *
  573. * Return error code if enable/disable failed
  574. */
  575. int msm_cdc_enable_wcd_supply(struct cdc_wcd_supply *cdc_supply, bool enable)
  576. {
  577. struct snd_soc_component *component = cdc_supply->component;
  578. int rc;
  579. if (!component) {
  580. pr_err("%s: Component memory is NULL\n", __func__);
  581. return -EINVAL;
  582. }
  583. if (enable)
  584. rc = snd_soc_dapm_force_enable_pin(
  585. snd_soc_component_get_dapm(component),
  586. cdc_supply->name);
  587. else
  588. rc = snd_soc_dapm_disable_pin(
  589. snd_soc_component_get_dapm(component),
  590. cdc_supply->name);
  591. if (!rc)
  592. snd_soc_dapm_sync(snd_soc_component_get_dapm(component));
  593. else
  594. dev_err(component->dev, "%s: micbias %s force %s pin failed\n",
  595. __func__, cdc_supply->name, (enable ? "enable" : "disable"));
  596. return rc;
  597. }
  598. EXPORT_SYMBOL(msm_cdc_enable_wcd_supply);