Skip to content

Commit 309e94a

Browse files
committed
ASoC: codecs: wcd93xxx: remove code duplication
Merge series from Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>: All the Qualcomm WCD codecs and WCD based codecs have lots of code in common, resulting in lot of duplicate code. This series is an attempt to clean some of this by moving the common code to wcd-common library or to soundwire helper functions. Currently I have done cleanups for 4 codecs wcd934x, wcd937x, wcd938x and wcd939x, however any new Qualcomm codecs can avoid this duplication by using the wcd-common library. I have also added two helpers of_sdw_find_device_by_node() and sdw_slave_get_current_bank() in soundwire layer for the codecs to use them, this series was already acked by Soundwire maintainer Vinod. As original cleanup series was depending on the new soundwire interfaces I have combined both the series as they are cleaning up code duplications. As am touching the same codec drivers, 2 bug fixes are also added at the start of the series. There is still lot of code that is duplicate, but this is just a starting point for such cleanups. I have tested this on T14s, any testing is appreciated.
2 parents dfe3de7 + 0266f95 commit 309e94a

17 files changed

Lines changed: 359 additions & 582 deletions

File tree

drivers/soundwire/bus.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,6 +1360,18 @@ int sdw_slave_get_scale_index(struct sdw_slave *slave, u8 *base)
13601360
}
13611361
EXPORT_SYMBOL(sdw_slave_get_scale_index);
13621362

1363+
int sdw_slave_get_current_bank(struct sdw_slave *slave)
1364+
{
1365+
int tmp;
1366+
1367+
tmp = sdw_read(slave, SDW_SCP_CTRL);
1368+
if (tmp < 0)
1369+
return tmp;
1370+
1371+
return FIELD_GET(SDW_SCP_STAT_CURR_BANK, tmp);
1372+
}
1373+
EXPORT_SYMBOL_GPL(sdw_slave_get_current_bank);
1374+
13631375
static int sdw_slave_set_frequency(struct sdw_slave *slave)
13641376
{
13651377
int scale_index;

drivers/soundwire/slave.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,4 +273,10 @@ int sdw_of_find_slaves(struct sdw_bus *bus)
273273
return 0;
274274
}
275275

276+
struct device *of_sdw_find_device_by_node(struct device_node *np)
277+
{
278+
return bus_find_device_by_of_node(&sdw_bus_type, np);
279+
}
280+
EXPORT_SYMBOL_GPL(of_sdw_find_device_by_node);
281+
276282
MODULE_IMPORT_NS("SND_SOC_SDCA");

include/linux/soundwire/sdw.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
struct dentry;
2121
struct fwnode_handle;
22+
struct device_node;
2223

2324
struct sdw_bus;
2425
struct sdw_slave;
@@ -1086,6 +1087,10 @@ int sdw_stream_add_slave(struct sdw_slave *slave,
10861087
int sdw_stream_remove_slave(struct sdw_slave *slave,
10871088
struct sdw_stream_runtime *stream);
10881089

1090+
struct device *of_sdw_find_device_by_node(struct device_node *np);
1091+
1092+
int sdw_slave_get_current_bank(struct sdw_slave *sdev);
1093+
10891094
int sdw_slave_get_scale_index(struct sdw_slave *slave, u8 *base);
10901095

10911096
/* messaging and data APIs */
@@ -1119,6 +1124,18 @@ static inline int sdw_stream_remove_slave(struct sdw_slave *slave,
11191124
return -EINVAL;
11201125
}
11211126

1127+
static inline struct device *of_sdw_find_device_by_node(struct device_node *np)
1128+
{
1129+
WARN_ONCE(1, "SoundWire API is disabled");
1130+
return NULL;
1131+
}
1132+
1133+
static inline int sdw_slave_get_current_bank(struct sdw_slave *sdev)
1134+
{
1135+
WARN_ONCE(1, "SoundWire API is disabled");
1136+
return -EINVAL;
1137+
}
1138+
11221139
/* messaging and data APIs */
11231140
static inline int sdw_read(struct sdw_slave *slave, u32 addr)
11241141
{

sound/soc/codecs/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2274,6 +2274,9 @@ config SND_SOC_UDA1380
22742274
config SND_SOC_WCD_CLASSH
22752275
tristate
22762276

2277+
config SND_SOC_WCD_COMMON
2278+
tristate
2279+
22772280
config SND_SOC_WCD9335
22782281
tristate "WCD9335 Codec"
22792282
depends on SLIMBUS
@@ -2295,6 +2298,7 @@ config SND_SOC_WCD934X
22952298
select REGMAP_IRQ
22962299
select REGMAP_SLIMBUS
22972300
select SND_SOC_WCD_CLASSH
2301+
select SND_SOC_WCD_COMMON
22982302
select SND_SOC_WCD_MBHC
22992303
depends on MFD_WCD934X || COMPILE_TEST
23002304
help
@@ -2306,6 +2310,7 @@ config SND_SOC_WCD937X
23062310
tristate
23072311
depends on SOUNDWIRE || !SOUNDWIRE
23082312
select SND_SOC_WCD_CLASSH
2313+
select SND_SOC_WCD_COMMON
23092314

23102315
config SND_SOC_WCD937X_SDW
23112316
tristate "WCD9370/WCD9375 Codec - SDW"
@@ -2325,6 +2330,7 @@ config SND_SOC_WCD938X
23252330
tristate
23262331
depends on SOUNDWIRE || !SOUNDWIRE
23272332
select SND_SOC_WCD_CLASSH
2333+
select SND_SOC_WCD_COMMON
23282334
select MULTIPLEXER
23292335

23302336
config SND_SOC_WCD938X_SDW
@@ -2344,6 +2350,7 @@ config SND_SOC_WCD939X
23442350
depends on SOUNDWIRE || !SOUNDWIRE
23452351
depends on TYPEC || !TYPEC
23462352
select SND_SOC_WCD_CLASSH
2353+
select SND_SOC_WCD_COMMON
23472354

23482355
config SND_SOC_WCD939X_SDW
23492356
tristate "WCD9390/WCD9395 Codec - SDW"

sound/soc/codecs/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ snd-soc-uda1334-y := uda1334.o
344344
snd-soc-uda1342-y := uda1342.o
345345
snd-soc-uda1380-y := uda1380.o
346346
snd-soc-wcd-classh-y := wcd-clsh-v2.o
347+
snd-soc-wcd-common-y := wcd-common.o
347348
snd-soc-wcd-mbhc-y := wcd-mbhc-v2.o
348349
snd-soc-wcd9335-y := wcd9335.o
349350
snd-soc-wcd934x-y := wcd934x.o
@@ -774,6 +775,7 @@ obj-$(CONFIG_SND_SOC_UDA1334) += snd-soc-uda1334.o
774775
obj-$(CONFIG_SND_SOC_UDA1342) += snd-soc-uda1342.o
775776
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
776777
obj-$(CONFIG_SND_SOC_WCD_CLASSH) += snd-soc-wcd-classh.o
778+
obj-$(CONFIG_SND_SOC_WCD_COMMON) += snd-soc-wcd-common.o
777779
obj-$(CONFIG_SND_SOC_WCD_MBHC) += snd-soc-wcd-mbhc.o
778780
obj-$(CONFIG_SND_SOC_WCD9335) += snd-soc-wcd9335.o
779781
obj-$(CONFIG_SND_SOC_WCD934X) += snd-soc-wcd934x.o

sound/soc/codecs/wcd-common.c

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
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+
#include <linux/soundwire/sdw.h>
13+
#include <linux/soundwire/sdw_type.h>
14+
#include <linux/regmap.h>
15+
16+
#include "wcd-common.h"
17+
18+
#define WCD_MIN_MICBIAS_MV 1000
19+
#define WCD_DEF_MICBIAS_MV 1800
20+
#define WCD_MAX_MICBIAS_MV 2850
21+
22+
#define SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(m) (0xE0 + 0x10 * (m))
23+
24+
int wcd_get_micb_vout_ctl_val(struct device *dev, u32 micb_mv)
25+
{
26+
/* min micbias voltage is 1V and maximum is 2.85V */
27+
if (micb_mv < WCD_MIN_MICBIAS_MV || micb_mv > WCD_MAX_MICBIAS_MV) {
28+
dev_err(dev, "Unsupported micbias voltage (%u mV)\n", micb_mv);
29+
return -EINVAL;
30+
}
31+
32+
return (micb_mv - WCD_MIN_MICBIAS_MV) / 50;
33+
}
34+
EXPORT_SYMBOL_GPL(wcd_get_micb_vout_ctl_val);
35+
36+
static int wcd_get_micbias_val(struct device *dev, int micb_num, u32 *micb_mv)
37+
{
38+
char micbias[64];
39+
int mv;
40+
41+
sprintf(micbias, "qcom,micbias%d-microvolt", micb_num);
42+
43+
if (of_property_read_u32(dev->of_node, micbias, &mv)) {
44+
dev_err(dev, "%s value not found, using default\n", micbias);
45+
mv = WCD_DEF_MICBIAS_MV;
46+
} else {
47+
/* convert it to milli volts */
48+
mv = mv/1000;
49+
}
50+
if (micb_mv)
51+
*micb_mv = mv;
52+
53+
mv = wcd_get_micb_vout_ctl_val(dev, mv);
54+
if (mv < 0) {
55+
dev_err(dev, "Unsupported %s voltage (%d mV), falling back to default (%d mV)\n",
56+
micbias, mv, WCD_DEF_MICBIAS_MV);
57+
return wcd_get_micb_vout_ctl_val(dev, WCD_DEF_MICBIAS_MV);
58+
}
59+
60+
return mv;
61+
}
62+
63+
int wcd_dt_parse_micbias_info(struct wcd_common *common)
64+
{
65+
int i;
66+
67+
for (i = 0; i < common->max_bias; i++) {
68+
common->micb_vout[i] = wcd_get_micbias_val(common->dev, i + 1, &common->micb_mv[i]);
69+
if (common->micb_vout[i] < 0)
70+
return -EINVAL;
71+
}
72+
73+
return 0;
74+
}
75+
EXPORT_SYMBOL_GPL(wcd_dt_parse_micbias_info);
76+
77+
static int wcd_sdw_component_bind(struct device *dev, struct device *master, void *data)
78+
{
79+
pm_runtime_set_autosuspend_delay(dev, 3000);
80+
pm_runtime_use_autosuspend(dev);
81+
pm_runtime_mark_last_busy(dev);
82+
pm_runtime_set_active(dev);
83+
pm_runtime_enable(dev);
84+
85+
return 0;
86+
}
87+
88+
static void wcd_sdw_component_unbind(struct device *dev, struct device *master, void *data)
89+
{
90+
pm_runtime_disable(dev);
91+
pm_runtime_set_suspended(dev);
92+
pm_runtime_dont_use_autosuspend(dev);
93+
}
94+
95+
const struct component_ops wcd_sdw_component_ops = {
96+
.bind = wcd_sdw_component_bind,
97+
.unbind = wcd_sdw_component_unbind,
98+
};
99+
EXPORT_SYMBOL_GPL(wcd_sdw_component_ops);
100+
101+
int wcd_update_status(struct sdw_slave *slave, enum sdw_slave_status status)
102+
{
103+
struct regmap *regmap = dev_get_regmap(&slave->dev, NULL);
104+
105+
if (regmap && status == SDW_SLAVE_ATTACHED) {
106+
/* Write out any cached changes that happened between probe and attach */
107+
regcache_cache_only(regmap, false);
108+
return regcache_sync(regmap);
109+
}
110+
111+
return 0;
112+
}
113+
EXPORT_SYMBOL_GPL(wcd_update_status);
114+
115+
int wcd_bus_config(struct sdw_slave *slave, struct sdw_bus_params *params)
116+
{
117+
sdw_write(slave, SWRS_SCP_HOST_CLK_DIV2_CTL_BANK(params->next_bank), 0x01);
118+
119+
return 0;
120+
}
121+
EXPORT_SYMBOL_GPL(wcd_bus_config);
122+
123+
int wcd_interrupt_callback(struct sdw_slave *slave, struct irq_domain *slave_irq,
124+
unsigned int wcd_intr_status0, unsigned int wcd_intr_status1,
125+
unsigned int wcd_intr_status2)
126+
{
127+
struct regmap *regmap = dev_get_regmap(&slave->dev, NULL);
128+
u32 sts1, sts2, sts3;
129+
130+
do {
131+
handle_nested_irq(irq_find_mapping(slave_irq, 0));
132+
regmap_read(regmap, wcd_intr_status0, &sts1);
133+
regmap_read(regmap, wcd_intr_status1, &sts2);
134+
regmap_read(regmap, wcd_intr_status2, &sts3);
135+
136+
} while (sts1 || sts2 || sts3);
137+
138+
return IRQ_HANDLED;
139+
}
140+
EXPORT_SYMBOL_GPL(wcd_interrupt_callback);
141+
142+
MODULE_DESCRIPTION("Common Qualcomm WCD Codec helpers driver");
143+
MODULE_LICENSE("GPL");

sound/soc/codecs/wcd-common.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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_sdw_ch_info {
18+
int port_num;
19+
unsigned int ch_mask;
20+
unsigned int master_ch_mask;
21+
};
22+
23+
#define WCD_SDW_CH(id, pn, cmask) \
24+
[id] = { \
25+
.port_num = pn, \
26+
.ch_mask = cmask, \
27+
.master_ch_mask = cmask, \
28+
}
29+
30+
struct wcd_common {
31+
struct device *dev;
32+
int max_bias;
33+
u32 micb_mv[WCD_MAX_MICBIAS];
34+
u32 micb_vout[WCD_MAX_MICBIAS];
35+
};
36+
37+
extern const struct component_ops wcd_sdw_component_ops;
38+
int wcd_get_micb_vout_ctl_val(struct device *dev, u32 micb_mv);
39+
int wcd_dt_parse_micbias_info(struct wcd_common *common);
40+
int wcd_update_status(struct sdw_slave *slave, enum sdw_slave_status status);
41+
int wcd_bus_config(struct sdw_slave *slave, struct sdw_bus_params *params);
42+
int wcd_interrupt_callback(struct sdw_slave *slave, struct irq_domain *slave_irq,
43+
unsigned int wcd_intr_status0, unsigned int wcd_intr_status1,
44+
unsigned int wcd_intr_status2);
45+
46+
#endif /* __WCD_COMMON_H__ */

0 commit comments

Comments
 (0)