Skip to content

Commit 4f16b63

Browse files
Srinivas Kandagatlabroonie
authored andcommitted
ASoC: codecs: wcd: add common helper for wcd codecs
All the Qualcomm WCD codecs have most of its code duplicated across all these 3/4 drivers. This is an attempt to remove those duplicate parts by adding a common helper library for these codecs. To start with move all the micbias parsing and voltage settings these are identical in WCD934x, WCD937x, WCD938x and WCD939x codec driver. Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com> Link: https://patch.msgid.link/20250909121954.225833-8-srinivas.kandagatla@oss.qualcomm.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 45a3295 commit 4f16b63

8 files changed

Lines changed: 182 additions & 265 deletions

File tree

sound/soc/codecs/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2233,6 +2233,9 @@ config SND_SOC_UDA1380
22332233
config SND_SOC_WCD_CLASSH
22342234
tristate
22352235

2236+
config SND_SOC_WCD_COMMON
2237+
tristate
2238+
22362239
config SND_SOC_WCD9335
22372240
tristate "WCD9335 Codec"
22382241
depends on SLIMBUS
@@ -2254,6 +2257,7 @@ config SND_SOC_WCD934X
22542257
select REGMAP_IRQ
22552258
select REGMAP_SLIMBUS
22562259
select SND_SOC_WCD_CLASSH
2260+
select SND_SOC_WCD_COMMON
22572261
select SND_SOC_WCD_MBHC
22582262
depends on MFD_WCD934X || COMPILE_TEST
22592263
help
@@ -2265,6 +2269,7 @@ config SND_SOC_WCD937X
22652269
tristate
22662270
depends on SOUNDWIRE || !SOUNDWIRE
22672271
select SND_SOC_WCD_CLASSH
2272+
select SND_SOC_WCD_COMMON
22682273

22692274
config SND_SOC_WCD937X_SDW
22702275
tristate "WCD9370/WCD9375 Codec - SDW"
@@ -2284,6 +2289,7 @@ config SND_SOC_WCD938X
22842289
tristate
22852290
depends on SOUNDWIRE || !SOUNDWIRE
22862291
select SND_SOC_WCD_CLASSH
2292+
select SND_SOC_WCD_COMMON
22872293
select MULTIPLEXER
22882294

22892295
config SND_SOC_WCD938X_SDW
@@ -2303,6 +2309,7 @@ config SND_SOC_WCD939X
23032309
depends on SOUNDWIRE || !SOUNDWIRE
23042310
depends on TYPEC || !TYPEC
23052311
select SND_SOC_WCD_CLASSH
2312+
select SND_SOC_WCD_COMMON
23062313

23072314
config SND_SOC_WCD939X_SDW
23082315
tristate "WCD9390/WCD9395 Codec - SDW"

sound/soc/codecs/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ snd-soc-uda1334-y := uda1334.o
339339
snd-soc-uda1342-y := uda1342.o
340340
snd-soc-uda1380-y := uda1380.o
341341
snd-soc-wcd-classh-y := wcd-clsh-v2.o
342+
snd-soc-wcd-common-y := wcd-common.o
342343
snd-soc-wcd-mbhc-y := wcd-mbhc-v2.o
343344
snd-soc-wcd9335-y := wcd9335.o
344345
snd-soc-wcd934x-y := wcd934x.o
@@ -761,6 +762,7 @@ obj-$(CONFIG_SND_SOC_UDA1334) += snd-soc-uda1334.o
761762
obj-$(CONFIG_SND_SOC_UDA1342) += snd-soc-uda1342.o
762763
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
763764
obj-$(CONFIG_SND_SOC_WCD_CLASSH) += snd-soc-wcd-classh.o
765+
obj-$(CONFIG_SND_SOC_WCD_COMMON) += snd-soc-wcd-common.o
764766
obj-$(CONFIG_SND_SOC_WCD_MBHC) += snd-soc-wcd-mbhc.o
765767
obj-$(CONFIG_SND_SOC_WCD9335) += snd-soc-wcd9335.o
766768
obj-$(CONFIG_SND_SOC_WCD934X) += snd-soc-wcd934x.o

sound/soc/codecs/wcd-common.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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+
11+
#include "wcd-common.h"
12+
13+
#define WCD_MIN_MICBIAS_MV 1000
14+
#define WCD_DEF_MICBIAS_MV 1800
15+
#define WCD_MAX_MICBIAS_MV 2850
16+
17+
int wcd_get_micb_vout_ctl_val(struct device *dev, u32 micb_mv)
18+
{
19+
/* min micbias voltage is 1V and maximum is 2.85V */
20+
if (micb_mv < WCD_MIN_MICBIAS_MV || micb_mv > WCD_MAX_MICBIAS_MV) {
21+
dev_err(dev, "Unsupported micbias voltage (%u mV)\n", micb_mv);
22+
return -EINVAL;
23+
}
24+
25+
return (micb_mv - WCD_MIN_MICBIAS_MV) / 50;
26+
}
27+
EXPORT_SYMBOL_GPL(wcd_get_micb_vout_ctl_val);
28+
29+
static int wcd_get_micbias_val(struct device *dev, int micb_num, u32 *micb_mv)
30+
{
31+
char micbias[64];
32+
int mv;
33+
34+
sprintf(micbias, "qcom,micbias%d-microvolt", micb_num);
35+
36+
if (of_property_read_u32(dev->of_node, micbias, &mv)) {
37+
dev_err(dev, "%s value not found, using default\n", micbias);
38+
mv = WCD_DEF_MICBIAS_MV;
39+
} else {
40+
/* convert it to milli volts */
41+
mv = mv/1000;
42+
}
43+
if (micb_mv)
44+
*micb_mv = mv;
45+
46+
mv = wcd_get_micb_vout_ctl_val(dev, mv);
47+
if (mv < 0) {
48+
dev_err(dev, "Unsupported %s voltage (%d mV), falling back to default (%d mV)\n",
49+
micbias, mv, WCD_DEF_MICBIAS_MV);
50+
return wcd_get_micb_vout_ctl_val(dev, WCD_DEF_MICBIAS_MV);
51+
}
52+
53+
return mv;
54+
}
55+
56+
int wcd_dt_parse_micbias_info(struct wcd_common *common)
57+
{
58+
int i;
59+
60+
for (i = 0; i < common->max_bias; i++) {
61+
common->micb_vout[i] = wcd_get_micbias_val(common->dev, i + 1, &common->micb_mv[i]);
62+
if (common->micb_vout[i] < 0)
63+
return -EINVAL;
64+
}
65+
66+
return 0;
67+
}
68+
EXPORT_SYMBOL_GPL(wcd_dt_parse_micbias_info);
69+
MODULE_DESCRIPTION("Common Qualcomm WCD Codec helpers driver");
70+
MODULE_LICENSE("GPL");

sound/soc/codecs/wcd-common.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Copyright (c) 2025, Qualcomm Technologies, Inc. and/or its subsidiaries.
4+
*/
5+
6+
#ifndef __WCD_COMMON_H__
7+
#define __WCD_COMMON_H__
8+
9+
struct device;
10+
struct sdw_slave;
11+
struct sdw_bus_params;
12+
struct irq_domain;
13+
enum sdw_slave_status;
14+
15+
#define WCD_MAX_MICBIAS 4
16+
17+
struct wcd_common {
18+
struct device *dev;
19+
int max_bias;
20+
u32 micb_mv[WCD_MAX_MICBIAS];
21+
u32 micb_vout[WCD_MAX_MICBIAS];
22+
};
23+
24+
int wcd_get_micb_vout_ctl_val(struct device *dev, u32 micb_mv);
25+
int wcd_dt_parse_micbias_info(struct wcd_common *common);
26+
27+
#endif /* __WCD_COMMON_H__ */

sound/soc/codecs/wcd934x.c

Lines changed: 23 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <sound/soc-dapm.h>
2222
#include <sound/tlv.h>
2323
#include "wcd-clsh-v2.h"
24+
#include "wcd-common.h"
2425
#include "wcd-mbhc-v2.h"
2526

2627
#include <dt-bindings/sound/qcom,wcd934x.h>
@@ -116,9 +117,6 @@
116117
#define WCD934X_DEC_PWR_LVL_DF 0x00
117118
#define WCD934X_DEC_PWR_LVL_HYBRID WCD934X_DEC_PWR_LVL_DF
118119

119-
#define WCD934X_DEF_MICBIAS_MV 1800
120-
#define WCD934X_MAX_MICBIAS_MV 2850
121-
122120
#define WCD_IIR_FILTER_SIZE (sizeof(u32) * BAND_MAX)
123121

124122
#define WCD_IIR_FILTER_CTL(xname, iidx, bidx) \
@@ -530,6 +528,7 @@ struct wcd934x_codec {
530528
struct slim_device *sdev;
531529
struct slim_device *sidev;
532530
struct wcd_clsh_ctrl *clsh_ctrl;
531+
struct wcd_common common;
533532
struct snd_soc_component *component;
534533
struct wcd934x_slim_ch rx_chs[WCD934X_RX_MAX];
535534
struct wcd934x_slim_ch tx_chs[WCD934X_TX_MAX];
@@ -555,7 +554,6 @@ struct wcd934x_codec {
555554
struct mutex micb_lock;
556555
u32 micb_ref[WCD934X_MAX_MICBIAS];
557556
u32 pullup_ref[WCD934X_MAX_MICBIAS];
558-
u32 micb2_mv;
559557
};
560558

561559
#define to_wcd934x_codec(_hw) container_of(_hw, struct wcd934x_codec, hw)
@@ -2168,55 +2166,24 @@ static struct clk *wcd934x_register_mclk_output(struct wcd934x_codec *wcd)
21682166
return NULL;
21692167
}
21702168

2171-
static int wcd934x_get_micbias_val(struct device *dev, const char *micbias,
2172-
u32 *micb_mv)
2173-
{
2174-
int mv;
2175-
2176-
if (of_property_read_u32(dev->parent->of_node, micbias, &mv)) {
2177-
dev_err(dev, "%s value not found, using default\n", micbias);
2178-
mv = WCD934X_DEF_MICBIAS_MV;
2179-
} else {
2180-
/* convert it to milli volts */
2181-
mv = mv/1000;
2182-
}
2183-
2184-
if (mv < 1000 || mv > 2850) {
2185-
dev_err(dev, "%s value not in valid range, using default\n",
2186-
micbias);
2187-
mv = WCD934X_DEF_MICBIAS_MV;
2188-
}
2189-
2190-
if (micb_mv)
2191-
*micb_mv = mv;
2192-
2193-
return (mv - 1000) / 50;
2194-
}
2195-
21962169
static int wcd934x_init_dmic(struct snd_soc_component *comp)
21972170
{
2198-
int vout_ctl_1, vout_ctl_2, vout_ctl_3, vout_ctl_4;
21992171
struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
22002172
u32 def_dmic_rate, dmic_clk_drv;
2173+
int ret;
22012174

2202-
vout_ctl_1 = wcd934x_get_micbias_val(comp->dev,
2203-
"qcom,micbias1-microvolt", NULL);
2204-
vout_ctl_2 = wcd934x_get_micbias_val(comp->dev,
2205-
"qcom,micbias2-microvolt",
2206-
&wcd->micb2_mv);
2207-
vout_ctl_3 = wcd934x_get_micbias_val(comp->dev,
2208-
"qcom,micbias3-microvolt", NULL);
2209-
vout_ctl_4 = wcd934x_get_micbias_val(comp->dev,
2210-
"qcom,micbias4-microvolt", NULL);
2175+
ret = wcd_dt_parse_mbhc_data(comp->dev, &wcd->mbhc_cfg);
2176+
if (ret)
2177+
return ret;
22112178

22122179
snd_soc_component_update_bits(comp, WCD934X_ANA_MICB1,
2213-
WCD934X_MICB_VAL_MASK, vout_ctl_1);
2180+
WCD934X_MICB_VAL_MASK, wcd->common.micb_vout[0]);
22142181
snd_soc_component_update_bits(comp, WCD934X_ANA_MICB2,
2215-
WCD934X_MICB_VAL_MASK, vout_ctl_2);
2182+
WCD934X_MICB_VAL_MASK, wcd->common.micb_vout[1]);
22162183
snd_soc_component_update_bits(comp, WCD934X_ANA_MICB3,
2217-
WCD934X_MICB_VAL_MASK, vout_ctl_3);
2184+
WCD934X_MICB_VAL_MASK, wcd->common.micb_vout[2]);
22182185
snd_soc_component_update_bits(comp, WCD934X_ANA_MICB4,
2219-
WCD934X_MICB_VAL_MASK, vout_ctl_4);
2186+
WCD934X_MICB_VAL_MASK, wcd->common.micb_vout[3]);
22202187

22212188
if (wcd->rate == WCD934X_MCLK_CLK_9P6MHZ)
22222189
def_dmic_rate = WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ;
@@ -2517,15 +2484,6 @@ static void wcd934x_mbhc_micb_ramp_control(struct snd_soc_component *component,
25172484
}
25182485
}
25192486

2520-
static int wcd934x_get_micb_vout_ctl_val(u32 micb_mv)
2521-
{
2522-
/* min micbias voltage is 1V and maximum is 2.85V */
2523-
if (micb_mv < 1000 || micb_mv > 2850)
2524-
return -EINVAL;
2525-
2526-
return (micb_mv - 1000) / 50;
2527-
}
2528-
25292487
static int wcd934x_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
25302488
int req_volt, int micb_num)
25312489
{
@@ -2562,7 +2520,7 @@ static int wcd934x_mbhc_micb_adjust_voltage(struct snd_soc_component *component,
25622520
cur_vout_ctl = snd_soc_component_read_field(component, micb_reg,
25632521
WCD934X_MICB_VAL_MASK);
25642522

2565-
req_vout_ctl = wcd934x_get_micb_vout_ctl_val(req_volt);
2523+
req_vout_ctl = wcd_get_micb_vout_ctl_val(component->dev, req_volt);
25662524
if (req_vout_ctl < 0) {
25672525
ret = -EINVAL;
25682526
goto exit;
@@ -2610,10 +2568,10 @@ static int wcd934x_mbhc_micb_ctrl_threshold_mic(struct snd_soc_component *compon
26102568
* voltage needed to detect threshold microphone, then do
26112569
* not change the micbias, just return.
26122570
*/
2613-
if (wcd934x->micb2_mv >= WCD_MBHC_THR_HS_MICB_MV)
2571+
if (wcd934x->common.micb_mv[1] >= WCD_MBHC_THR_HS_MICB_MV)
26142572
return 0;
26152573

2616-
micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : wcd934x->micb2_mv;
2574+
micb_mv = req_en ? WCD_MBHC_THR_HS_MICB_MV : wcd934x->common.micb_mv[1];
26172575

26182576
rc = wcd934x_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_2);
26192577

@@ -3036,7 +2994,7 @@ static void wcd934x_mbhc_deinit(struct snd_soc_component *component)
30362994
static int wcd934x_comp_probe(struct snd_soc_component *component)
30372995
{
30382996
struct wcd934x_codec *wcd = dev_get_drvdata(component->dev);
3039-
int i;
2997+
int i, ret;
30402998

30412999
snd_soc_component_init_regmap(component, wcd->regmap);
30423000
wcd->component = component;
@@ -3054,7 +3012,12 @@ static int wcd934x_comp_probe(struct snd_soc_component *component)
30543012
for (i = 0; i < NUM_CODEC_DAIS; i++)
30553013
INIT_LIST_HEAD(&wcd->dai[i].slim_ch_list);
30563014

3057-
wcd934x_init_dmic(component);
3015+
3016+
ret = wcd934x_init_dmic(component);
3017+
if (ret) {
3018+
dev_err(component->dev, "Failed to Initialize micbias\n");
3019+
return ret;
3020+
}
30583021

30593022
if (wcd934x_mbhc_init(component))
30603023
dev_err(component->dev, "Failed to Initialize MBHC\n");
@@ -5860,14 +5823,13 @@ static int wcd934x_codec_parse_data(struct wcd934x_codec *wcd)
58605823
cfg->anc_micbias = MIC_BIAS_2;
58615824
cfg->v_hs_max = WCD_MBHC_HS_V_MAX;
58625825
cfg->num_btn = WCD934X_MBHC_MAX_BUTTONS;
5863-
cfg->micb_mv = wcd->micb2_mv;
5826+
cfg->micb_mv = wcd->common.micb_mv[1];
58645827
cfg->linein_th = 5000;
58655828
cfg->hs_thr = 1700;
58665829
cfg->hph_thr = 50;
58675830

58685831
wcd_dt_parse_mbhc_data(dev, cfg);
58695832

5870-
58715833
return 0;
58725834
}
58735835

@@ -5888,6 +5850,8 @@ static int wcd934x_codec_probe(struct platform_device *pdev)
58885850
wcd->sdev = to_slim_device(data->dev);
58895851
mutex_init(&wcd->sysclk_mutex);
58905852
mutex_init(&wcd->micb_lock);
5853+
wcd->common.dev = dev->parent;
5854+
wcd->common.max_bias = 4;
58915855

58925856
ret = wcd934x_codec_parse_data(wcd);
58935857
if (ret)

0 commit comments

Comments
 (0)