xref: /linux/sound/soc/codecs/wcd-common.c (revision ebaf88c0546ddfd5efe5d7867a2e8e9f0e5969ed)
1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2025, Qualcomm Technologies, Inc. and/or its subsidiaries.
3 
4 #include <linux/export.h>
5 #include <linux/module.h>
6 #include <linux/init.h>
7 #include <linux/device.h>
8 #include <linux/of.h>
9 #include <linux/printk.h>
10 #include <linux/component.h>
11 #include <linux/pm_runtime.h>
12 
13 #include "wcd-common.h"
14 
15 #define WCD_MIN_MICBIAS_MV	1000
16 #define WCD_DEF_MICBIAS_MV	1800
17 #define WCD_MAX_MICBIAS_MV	2850
18 
19 int wcd_get_micb_vout_ctl_val(struct device *dev, u32 micb_mv)
20 {
21 	/* min micbias voltage is 1V and maximum is 2.85V */
22 	if (micb_mv < WCD_MIN_MICBIAS_MV || micb_mv > WCD_MAX_MICBIAS_MV) {
23 		dev_err(dev, "Unsupported micbias voltage (%u mV)\n", micb_mv);
24 		return -EINVAL;
25 	}
26 
27 	return (micb_mv - WCD_MIN_MICBIAS_MV) / 50;
28 }
29 EXPORT_SYMBOL_GPL(wcd_get_micb_vout_ctl_val);
30 
31 static int wcd_get_micbias_val(struct device *dev, int micb_num, u32 *micb_mv)
32 {
33 	char micbias[64];
34 	int mv;
35 
36 	sprintf(micbias, "qcom,micbias%d-microvolt", micb_num);
37 
38 	if (of_property_read_u32(dev->of_node, micbias, &mv)) {
39 		dev_err(dev, "%s value not found, using default\n", micbias);
40 		mv = WCD_DEF_MICBIAS_MV;
41 	} else {
42 		/* convert it to milli volts */
43 		mv = mv/1000;
44 	}
45 	if (micb_mv)
46 		*micb_mv = mv;
47 
48 	mv = wcd_get_micb_vout_ctl_val(dev, mv);
49 	if (mv < 0) {
50 		dev_err(dev, "Unsupported %s voltage (%d mV), falling back to default (%d mV)\n",
51 				micbias, mv, WCD_DEF_MICBIAS_MV);
52 		return wcd_get_micb_vout_ctl_val(dev, WCD_DEF_MICBIAS_MV);
53 	}
54 
55 	return mv;
56 }
57 
58 int wcd_dt_parse_micbias_info(struct wcd_common *common)
59 {
60 	int i;
61 
62 	for (i = 0; i < common->max_bias; i++) {
63 		common->micb_vout[i] = wcd_get_micbias_val(common->dev, i + 1, &common->micb_mv[i]);
64 		if (common->micb_vout[i] < 0)
65 			return -EINVAL;
66 	}
67 
68 	return 0;
69 }
70 EXPORT_SYMBOL_GPL(wcd_dt_parse_micbias_info);
71 
72 static int wcd_sdw_component_bind(struct device *dev, struct device *master, void *data)
73 {
74 	pm_runtime_set_autosuspend_delay(dev, 3000);
75 	pm_runtime_use_autosuspend(dev);
76 	pm_runtime_mark_last_busy(dev);
77 	pm_runtime_set_active(dev);
78 	pm_runtime_enable(dev);
79 
80 	return 0;
81 }
82 
83 static void wcd_sdw_component_unbind(struct device *dev, struct device *master, void *data)
84 {
85 	pm_runtime_disable(dev);
86 	pm_runtime_set_suspended(dev);
87 	pm_runtime_dont_use_autosuspend(dev);
88 }
89 
90 const struct component_ops wcd_sdw_component_ops = {
91 	.bind = wcd_sdw_component_bind,
92 	.unbind = wcd_sdw_component_unbind,
93 };
94 EXPORT_SYMBOL_GPL(wcd_sdw_component_ops);
95 
96 MODULE_DESCRIPTION("Common Qualcomm WCD Codec helpers driver");
97 MODULE_LICENSE("GPL");
98