[PATCH v1 4/6] ASoC: codecs: rk3308: support ADC stereo-group routing
Xing Zheng
zhengxing at rock-chips.com
Sat Oct 31 21:01:23 PDT 2026
Allow boards to describe the internal ADC-group mux with rockchip,adc-
grps-route. Validate all four group IDs before updating the GRF and
configure the physical ADC groups selected for the requested PCM channel
count.
Reject duplicate and out-of-range IDs and incomplete mappings. Preserve
the existing identity mapping and leave the GRF unchanged when the
property is absent.
Signed-off-by: Xing Zheng <zhengxing at rock-chips.com>
---
sound/soc/codecs/rk3308_codec.c | 44 +++++++++++++++++++++++++++++++--
1 file changed, 42 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/rk3308_codec.c b/sound/soc/codecs/rk3308_codec.c
index fc7e20e82700..319b2391dd9b 100644
--- a/sound/soc/codecs/rk3308_codec.c
+++ b/sound/soc/codecs/rk3308_codec.c
@@ -28,6 +28,7 @@
#define ADC_LR_GROUP_MAX 4
+#define GRF_SOC_CON1 0x304
#define GRF_CHIP_ID 0x800
enum {
@@ -47,6 +48,7 @@ struct rk3308_codec_priv {
struct snd_soc_component *component;
unsigned char codec_ver;
u32 micbias_level;
+ u32 adc_grps[ADC_LR_GROUP_MAX];
};
static struct clk_bulk_data rk3308_codec_clocks[] = {
@@ -794,7 +796,7 @@ static int rk3308_codec_adc_dig_config(struct rk3308_codec_priv *rk3308,
* grp 3 = ADC7 and ADC8
*/
u32 used_adc_grps;
- int grp;
+ int grp, idx;
switch (params_channels(params)) {
case 1:
@@ -829,7 +831,8 @@ static int rk3308_codec_adc_dig_config(struct rk3308_codec_priv *rk3308,
return -EINVAL;
}
- for (grp = 0; grp < used_adc_grps; grp++) {
+ for (idx = 0; idx < used_adc_grps; idx++) {
+ grp = rk3308->adc_grps[idx];
regmap_update_bits(rk3308->regmap,
RK3308_ADC_DIG_CON03(grp),
RK3308_ADC_L_CH_BIST_MSK | RK3308_ADC_R_CH_BIST_MSK,
@@ -1086,6 +1089,39 @@ static int rk3308_codec_set_micbias_level(struct rk3308_codec_priv *rk3308)
return 0;
}
+static int rk3308_codec_adc_grps_route(struct rk3308_codec_priv *rk3308)
+{
+ struct device_node *np = rk3308->dev->of_node;
+ unsigned int seen = 0, val = 0;
+ int grp, ret;
+
+ for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++)
+ rk3308->adc_grps[grp] = grp;
+
+ if (!of_find_property(np, "rockchip,adc-grps-route", NULL))
+ return 0;
+
+ if (of_property_count_u32_elems(np, "rockchip,adc-grps-route") !=
+ ADC_LR_GROUP_MAX)
+ return -EINVAL;
+
+ ret = of_property_read_u32_array(np, "rockchip,adc-grps-route",
+ rk3308->adc_grps, ADC_LR_GROUP_MAX);
+ if (ret)
+ return ret;
+
+ for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
+ u32 input = rk3308->adc_grps[grp];
+
+ if (input >= ADC_LR_GROUP_MAX || (seen & BIT(input)))
+ return -EINVAL;
+ seen |= BIT(input);
+ val |= input << (grp * 2);
+ }
+
+ return regmap_write(rk3308->grf, GRF_SOC_CON1, (0xff << 16) | val);
+}
+
static int rk3308_codec_platform_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -1131,6 +1167,10 @@ static int rk3308_codec_platform_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rk3308);
+ err = rk3308_codec_adc_grps_route(rk3308);
+ if (err)
+ return dev_err_probe(dev, err, "Invalid ADC group routing\n");
+
err = rk3308_codec_set_micbias_level(rk3308);
if (err)
return err;
More information about the linux-arm-kernel
mailing list