[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