lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <ca3a07c8987a033c3d505f5d79956d0e935ea03f.1768180827.git.cy_huang@richtek.com>
Date: Mon, 12 Jan 2026 09:27:34 +0800
From: <cy_huang@...htek.com>
To: Mark Brown <broonie@...nel.org>, Krzysztof Kozlowski <krzk+dt@...nel.org>
CC: Rob Herring <robh@...nel.org>, Conor Dooley <conor+dt@...nel.org>, "Liam
 Girdwood" <lgirdwood@...il.com>, ChiYuan Huang <cy_huang@...htek.com>,
	<musk_wang@...htek.com>, <roy_chiu@...htek.com>, <allen_lin@...htek.com>,
	<devicetree@...r.kernel.org>, <linux-sound@...r.kernel.org>,
	<linux-kernel@...r.kernel.org>
Subject: [PATCH v2 3/3] ASoC: codecs: rtq9128: Add compatible changes for rtq9154

From: ChiYuan Huang <cy_huang@...htek.com>

Although rtq9154 only modify the outter package, some register settings
related to the channel order definition are still different. Use the chip
model ID code to seperate these changes.

Signed-off-by: ChiYuan Huang <cy_huang@...htek.com>
---
 sound/soc/codecs/rtq9128.c | 108 +++++++++++++++++++++++++++++++++++--
 1 file changed, 104 insertions(+), 4 deletions(-)

diff --git a/sound/soc/codecs/rtq9128.c b/sound/soc/codecs/rtq9128.c
index 289bb3c04a90..14a2c0723d33 100644
--- a/sound/soc/codecs/rtq9128.c
+++ b/sound/soc/codecs/rtq9128.c
@@ -40,6 +40,12 @@
 #define RTQ9128_REG_EFUSE_DATA	0xE0
 #define RTQ9128_REG_VENDOR_ID	0xF9
 
+#define RTQ9154_REG_CH1_VOL	0x34
+#define RTQ9154_REG_CH2_VOL	0x33
+#define RTQ9154_REG_CH3_VOL	0x32
+#define RTQ9154_REG_CH4_VOL	0x31
+#define RTQ9154_REG_AUTOULQM	0xAD
+
 #define RTQ9128_CHSTAT_VAL_MASK	GENMASK(1, 0)
 #define RTQ9128_DOLEN_MASK	GENMASK(7, 6)
 #define RTQ9128_TDMSRCIN_MASK	GENMASK(5, 4)
@@ -48,6 +54,7 @@
 #define RTQ9128_MSMUTE_MASK	BIT(0)
 #define RTQ9128_DIE_CHECK_MASK	GENMASK(4, 0)
 #define RTQ9128_VENDOR_ID_MASK	GENMASK(19, 8)
+#define RTQ9128_MODEL_ID_MASK	GENMASK(7, 4)
 
 #define RTQ9128_SOFT_RESET_VAL	0x80
 #define RTQ9128_VENDOR_ID_VAL	0x470
@@ -56,6 +63,15 @@
 #define RTQ9128_TKA470B_VAL	0
 #define RTQ9128_RTQ9128DH_VAL	0x0F
 #define RTQ9128_RTQ9128DL_VAL	0x10
+#define RTQ9154_MODEL_ID	0x08
+
+#define RTQ9154_AUTOULQM_VAL	0x82
+
+enum rtq9128_chip_model {
+	CHIP_MODEL_RTQ9128 = 0,
+	CHIP_MODEL_RTQ9154,
+	CHIP_MODEL_MAX
+};
 
 struct rtq9128_data {
 	struct gpio_desc *enable;
@@ -63,6 +79,7 @@ struct rtq9128_data {
 	int tdm_slots;
 	int tdm_slot_width;
 	bool tdm_input_data2_select;
+	enum rtq9128_chip_model chip_model;
 };
 
 struct rtq9128_init_reg {
@@ -251,6 +268,28 @@ static const struct soc_enum rtq9128_out4_phase_enum =
 	SOC_ENUM_SINGLE(RTQ9128_REG_PLLTRI_GEN2, 0, ARRAY_SIZE(phase_select_text),
 			phase_select_text);
 
+static const struct soc_enum rtq9154_ch1_si_enum =
+	SOC_ENUM_SINGLE(RTQ9128_REG_SDI_SEL, 0, ARRAY_SIZE(source_select_text),
+			source_select_text);
+static const struct soc_enum rtq9154_ch2_si_enum =
+	SOC_ENUM_SINGLE(RTQ9128_REG_SDI_SEL, 2, ARRAY_SIZE(source_select_text),
+			source_select_text);
+static const struct soc_enum rtq9154_ch3_si_enum =
+	SOC_ENUM_SINGLE(RTQ9128_REG_SDI_SEL, 4, ARRAY_SIZE(source_select_text),
+			source_select_text);
+static const struct soc_enum rtq9154_ch4_si_enum =
+	SOC_ENUM_SINGLE(RTQ9128_REG_SDI_SEL, 6, ARRAY_SIZE(source_select_text),
+			source_select_text);
+static const struct soc_enum rtq9154_out1_phase_enum =
+	SOC_ENUM_SINGLE(RTQ9128_REG_PLLTRI_GEN2, 0, ARRAY_SIZE(phase_select_text),
+			phase_select_text);
+static const struct soc_enum rtq9154_out2_phase_enum =
+	SOC_ENUM_SINGLE(RTQ9128_REG_PLLTRI_GEN2, 4, ARRAY_SIZE(phase_select_text),
+			phase_select_text);
+static const struct soc_enum rtq9154_out3_phase_enum =
+	SOC_ENUM_SINGLE(RTQ9128_REG_PLLTRI_GEN1, 0, ARRAY_SIZE(phase_select_text),
+			phase_select_text);
+
 /*
  * In general usage, DVDD could be 1P8V, 3P0V or 3P3V.
  * This DVDD undervoltage protection is to prevent from the abnormal power
@@ -283,10 +322,33 @@ static const struct snd_kcontrol_new rtq9128_snd_ctrls[] = {
 	SOC_ENUM("DVDD UV Threshold Select", rtq9128_dvdduv_select_enum),
 };
 
+static const struct snd_kcontrol_new rtq9154_snd_ctrls[] = {
+	SOC_SINGLE_TLV("MS Volume", RTQ9128_REG_MS_VOL, 2, 511, 1, dig_tlv),
+	SOC_SINGLE_TLV("CH1 Volume", RTQ9154_REG_CH1_VOL, 2, 511, 1, dig_tlv),
+	SOC_SINGLE_TLV("CH2 Volume", RTQ9154_REG_CH2_VOL, 2, 511, 1, dig_tlv),
+	SOC_SINGLE_TLV("CH3 Volume", RTQ9154_REG_CH3_VOL, 2, 511, 1, dig_tlv),
+	SOC_SINGLE_TLV("CH4 Volume", RTQ9154_REG_CH4_VOL, 2, 511, 1, dig_tlv),
+	SOC_SINGLE_TLV("SPK Gain Volume", RTQ9128_REG_MISC, 0, 5, 0, spkgain_tlv),
+	SOC_SINGLE("PBTL12 Switch", RTQ9128_REG_MISC, 4, 1, 0),
+	SOC_SINGLE("PBTL34 Switch", RTQ9128_REG_MISC, 5, 1, 0),
+	SOC_SINGLE("Spread Spectrum Switch", RTQ9128_REG_PWM_SS_OPT, 7, 1, 0),
+	SOC_SINGLE("SDO Select", RTQ9128_REG_SDO_SEL, 0, 15, 0),
+	SOC_ENUM("CH1 SI Select", rtq9154_ch1_si_enum),
+	SOC_ENUM("CH2 SI Select", rtq9154_ch2_si_enum),
+	SOC_ENUM("CH3 SI Select", rtq9154_ch3_si_enum),
+	SOC_ENUM("CH4 SI Select", rtq9154_ch4_si_enum),
+	SOC_ENUM("PWM FREQ Select", rtq9128_pwm_freq_enum),
+	SOC_ENUM("OUT1 Phase Select", rtq9154_out1_phase_enum),
+	SOC_ENUM("OUT2 Phase Select", rtq9154_out2_phase_enum),
+	SOC_ENUM("OUT3 Phase Select", rtq9154_out3_phase_enum),
+	SOC_ENUM("DVDD UV Threshold Select", rtq9128_dvdduv_select_enum),
+};
+
 static int rtq9128_dac_power_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
 				   int event)
 {
 	struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+	struct rtq9128_data *data = snd_soc_component_get_drvdata(comp);
 	unsigned int shift, mask;
 	int ret;
 
@@ -301,6 +363,10 @@ static int rtq9128_dac_power_event(struct snd_soc_dapm_widget *w, struct snd_kco
 	else
 		shift = 0;
 
+	/* Compared to RTQ9128, RTQ9154 use the reverse order for DACx bitfield location */
+	if (data->chip_model == CHIP_MODEL_RTQ9154)
+		shift = 6 - shift;
+
 	mask = RTQ9128_CHSTAT_VAL_MASK << shift;
 
 	/* Turn channel state to Normal or HiZ */
@@ -387,6 +453,7 @@ static const struct rtq9128_init_reg rtq9128_dl_tables[] = {
 
 static int rtq9128_component_probe(struct snd_soc_component *comp)
 {
+	struct rtq9128_data *data = snd_soc_component_get_drvdata(comp);
 	const struct rtq9128_init_reg *table, *curr;
 	size_t table_size;
 	unsigned int val;
@@ -421,6 +488,14 @@ static int rtq9128_component_probe(struct snd_soc_component *comp)
 			return ret;
 	}
 
+
+	if (data->chip_model == CHIP_MODEL_RTQ9154) {
+		/* Enable RTQ9154 Specific AUTO ULQM feature */
+		ret = snd_soc_component_write(comp, RTQ9154_REG_AUTOULQM, RTQ9154_AUTOULQM_VAL);
+		if (ret < 0)
+			return ret;
+	}
+
 	pm_runtime_mark_last_busy(comp->dev);
 	pm_runtime_put(comp->dev);
 
@@ -439,6 +514,18 @@ static const struct snd_soc_component_driver rtq9128_comp_driver = {
 	.endianness = 1,
 };
 
+static const struct snd_soc_component_driver rtq9154_comp_driver = {
+	.probe = rtq9128_component_probe,
+	.controls = rtq9154_snd_ctrls,
+	.num_controls = ARRAY_SIZE(rtq9154_snd_ctrls),
+	.dapm_widgets = rtq9128_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(rtq9128_dapm_widgets),
+	.dapm_routes = rtq9128_dapm_routes,
+	.num_dapm_routes = ARRAY_SIZE(rtq9128_dapm_routes),
+	.use_pmdown_time = 1,
+	.endianness = 1,
+};
+
 static int rtq9128_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
 	struct rtq9128_data *data = snd_soc_dai_get_drvdata(dai);
@@ -679,7 +766,8 @@ static int rtq9128_probe(struct i2c_client *i2c)
 	struct device *dev = &i2c->dev;
 	struct rtq9128_data *data;
 	struct regmap *regmap;
-	unsigned int venid;
+	unsigned int veninfo, venid, chip_model;
+	const struct snd_soc_component_driver *comp_drv;
 	int ret;
 
 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
@@ -712,21 +800,33 @@ static int rtq9128_probe(struct i2c_client *i2c)
 	if (IS_ERR(regmap))
 		return dev_err_probe(dev, PTR_ERR(regmap), "Failed to init regmap\n");
 
-	ret = regmap_read(regmap, RTQ9128_REG_VENDOR_ID, &venid);
+	ret = regmap_read(regmap, RTQ9128_REG_VENDOR_ID, &veninfo);
 	if (ret)
 		return dev_err_probe(dev, ret, "Failed to get vendor id\n");
 
-	venid = FIELD_GET(RTQ9128_VENDOR_ID_MASK, venid);
+	venid = FIELD_GET(RTQ9128_VENDOR_ID_MASK, veninfo);
 	if (venid != RTQ9128_VENDOR_ID_VAL)
 		return dev_err_probe(dev, -ENODEV, "Vendor ID not match (0x%x)\n", venid);
 
+	chip_model = FIELD_GET(RTQ9128_MODEL_ID_MASK, veninfo);
+	switch (chip_model) {
+	case RTQ9154_MODEL_ID:
+		data->chip_model = CHIP_MODEL_RTQ9154;
+		comp_drv = &rtq9154_comp_driver;
+		break;
+	default:
+		data->chip_model = CHIP_MODEL_RTQ9128;
+		comp_drv = &rtq9128_comp_driver;
+		break;
+	}
+
 	pm_runtime_set_active(dev);
 	pm_runtime_mark_last_busy(dev);
 	ret = devm_pm_runtime_enable(dev);
 	if (ret)
 		return dev_err_probe(dev, ret, "Failed to enable pm runtime\n");
 
-	return devm_snd_soc_register_component(dev, &rtq9128_comp_driver, &rtq9128_dai, 1);
+	return devm_snd_soc_register_component(dev, comp_drv, &rtq9128_dai, 1);
 }
 
 static int rtq9128_pm_runtime_suspend(struct device *dev)
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ