* [PATCH AUTOSEL 6.12 4/6] ALSA: hda/cs35l56: Workaround bad dev-index on Lenovo Yoga Book 9i GenX
[not found] <20250723005805.1023184-1-sashal@kernel.org>
@ 2025-07-23 0:58 ` Sasha Levin
0 siblings, 0 replies; only message in thread
From: Sasha Levin @ 2025-07-23 0:58 UTC (permalink / raw)
To: patches, stable
Cc: Richard Fitzgerald, Brian Howard, Takashi Iwai, Sasha Levin,
david.rhodes, linux-sound, patches
From: Richard Fitzgerald <rf@opensource.cirrus.com>
[ Upstream commit 40b1c2f9b299295ed0482e1fee6f46521e6e79e5 ]
The Lenovo Yoga Book 9i GenX has the wrong values in the cirrus,dev-index
_DSD property. Add a fixup for this model to ignore the property and
hardcode the index from the I2C bus address.
The error in the cirrus,dev-index property would prevent the second amp
instance from probing. The component binding would never see all the
required instances and so there would not be a binding between
patch_realtek.c and the cs35l56 driver.
Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Reported-by: Brian Howard <blhoward2@gmail.com>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220228
Link: https://patch.msgid.link/20250714110154.204740-1-rf@opensource.cirrus.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Now let me analyze the actual changes in the current commit more
carefully. The commit adds:
1. A fixup function for the Yoga Book 9i GenX that hardcodes the device
index based on I2C address
2. A fixup table mechanism to apply platform-specific workarounds
3. Modified the cs35l56_hda_read_acpi function to apply fixups before
reading the device index
**Analysis and Backport Decision: YES**
This commit should be backported to stable kernel trees for the
following reasons:
1. **Fixes a real bug affecting users**: The commit fixes a hardware
initialization failure on the Lenovo Yoga Book 9i GenX laptop where
the second amplifier would fail to probe due to incorrect cirrus,dev-
index values in the ACPI _DSD property. This prevents audio from
working properly on this device.
2. **Small and contained fix**: The changes are minimal and localized
to:
- Adding a platform-specific fixup function that maps I2C addresses
to correct device indices
- Adding infrastructure to apply platform fixups
- Modifying the initialization flow to check for fixups before
reading ACPI properties
3. **Low regression risk**:
- The fixup only applies to one specific laptop model (17AA390B)
- The fixup infrastructure is designed to be non-invasive - it only
activates for specific subsystem IDs
- The changes don't affect the behavior for any other devices
4. **Follows stable kernel criteria**:
- Fixes a real bug that bothers people (audio not working on a
consumer laptop)
- The fix is obviously correct and tested (reported by a user and has
a bug report)
- Small change (adds ~60 lines, mostly the fixup infrastructure)
- No new features, just a workaround for broken firmware
5. **Similar to previously backported commits**: Looking at the
historical commits, we see that:
- Commit 91191a6e50a2 ("ALSA: hda: cs35l56: Don't use the device
index as a calibration index") was marked as backport-worthy (YES)
and addressed a similar issue with device index handling
- Multiple commits adding quirks for Lenovo devices with
CS35L41/CS35L56 have been backported (marked YES)
6. **Hardware enablement**: This falls into the category of hardware
enablement fixes which are generally considered appropriate for
stable kernels when they fix broken hardware without risking existing
functionality.
The commit message clearly indicates this is fixing a specific hardware
issue where "The error in the cirrus,dev-index property would prevent
the second amp instance from probing" which would result in no audio
binding and broken audio on this laptop model.
sound/pci/hda/cs35l56_hda.c | 110 +++++++++++++++++++++++++++---------
1 file changed, 82 insertions(+), 28 deletions(-)
diff --git a/sound/pci/hda/cs35l56_hda.c b/sound/pci/hda/cs35l56_hda.c
index 7baf3b506eefe..7823f71012a8a 100644
--- a/sound/pci/hda/cs35l56_hda.c
+++ b/sound/pci/hda/cs35l56_hda.c
@@ -876,6 +876,52 @@ static int cs35l56_hda_system_resume(struct device *dev)
return 0;
}
+static int cs35l56_hda_fixup_yoga9(struct cs35l56_hda *cs35l56, int *bus_addr)
+{
+ /* The cirrus,dev-index property has the wrong values */
+ switch (*bus_addr) {
+ case 0x30:
+ cs35l56->index = 1;
+ return 0;
+ case 0x31:
+ cs35l56->index = 0;
+ return 0;
+ default:
+ /* There is a pseudo-address for broadcast to both amps - ignore it */
+ dev_dbg(cs35l56->base.dev, "Ignoring I2C address %#x\n", *bus_addr);
+ return 0;
+ }
+}
+
+static const struct {
+ const char *sub;
+ int (*fixup_fn)(struct cs35l56_hda *cs35l56, int *bus_addr);
+} cs35l56_hda_fixups[] = {
+ {
+ .sub = "17AA390B", /* Lenovo Yoga Book 9i GenX */
+ .fixup_fn = cs35l56_hda_fixup_yoga9,
+ },
+};
+
+static int cs35l56_hda_apply_platform_fixups(struct cs35l56_hda *cs35l56, const char *sub,
+ int *bus_addr)
+{
+ int i;
+
+ if (IS_ERR(sub))
+ return 0;
+
+ for (i = 0; i < ARRAY_SIZE(cs35l56_hda_fixups); i++) {
+ if (strcasecmp(cs35l56_hda_fixups[i].sub, sub) == 0) {
+ dev_dbg(cs35l56->base.dev, "Applying fixup for %s\n",
+ cs35l56_hda_fixups[i].sub);
+ return (cs35l56_hda_fixups[i].fixup_fn)(cs35l56, bus_addr);
+ }
+ }
+
+ return 0;
+}
+
static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
{
u32 values[HDA_MAX_COMPONENTS];
@@ -900,39 +946,47 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
ACPI_COMPANION_SET(cs35l56->base.dev, adev);
}
- property = "cirrus,dev-index";
- ret = device_property_count_u32(cs35l56->base.dev, property);
- if (ret <= 0)
- goto err;
-
- if (ret > ARRAY_SIZE(values)) {
- ret = -EINVAL;
- goto err;
- }
- nval = ret;
+ /* Initialize things that could be overwritten by a fixup */
+ cs35l56->index = -1;
- ret = device_property_read_u32_array(cs35l56->base.dev, property, values, nval);
+ sub = acpi_get_subsystem_id(ACPI_HANDLE(cs35l56->base.dev));
+ ret = cs35l56_hda_apply_platform_fixups(cs35l56, sub, &id);
if (ret)
- goto err;
+ return ret;
- cs35l56->index = -1;
- for (i = 0; i < nval; i++) {
- if (values[i] == id) {
- cs35l56->index = i;
- break;
- }
- }
- /*
- * It's not an error for the ID to be missing: for I2C there can be
- * an alias address that is not a real device. So reject silently.
- */
if (cs35l56->index == -1) {
- dev_dbg(cs35l56->base.dev, "No index found in %s\n", property);
- ret = -ENODEV;
- goto err;
- }
+ property = "cirrus,dev-index";
+ ret = device_property_count_u32(cs35l56->base.dev, property);
+ if (ret <= 0)
+ goto err;
- sub = acpi_get_subsystem_id(ACPI_HANDLE(cs35l56->base.dev));
+ if (ret > ARRAY_SIZE(values)) {
+ ret = -EINVAL;
+ goto err;
+ }
+ nval = ret;
+
+ ret = device_property_read_u32_array(cs35l56->base.dev, property, values, nval);
+ if (ret)
+ goto err;
+
+ for (i = 0; i < nval; i++) {
+ if (values[i] == id) {
+ cs35l56->index = i;
+ break;
+ }
+ }
+
+ /*
+ * It's not an error for the ID to be missing: for I2C there can be
+ * an alias address that is not a real device. So reject silently.
+ */
+ if (cs35l56->index == -1) {
+ dev_dbg(cs35l56->base.dev, "No index found in %s\n", property);
+ ret = -ENODEV;
+ goto err;
+ }
+ }
if (IS_ERR(sub)) {
dev_info(cs35l56->base.dev,
--
2.39.5
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2025-07-23 0:58 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20250723005805.1023184-1-sashal@kernel.org>
2025-07-23 0:58 ` [PATCH AUTOSEL 6.12 4/6] ALSA: hda/cs35l56: Workaround bad dev-index on Lenovo Yoga Book 9i GenX Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).