* [RFC PATCH 0/2] Fix second CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios
@ 2026-02-15 13:55 Khalil
2026-02-15 13:55 ` [RFC PATCH 1/2] platform/x86: serial-multi-instantiate: Add GPIO chip select support for SPI devices Khalil
2026-02-15 13:55 ` [RFC PATCH 2/2] spi: pxa2xx: Handle dynamic " Khalil
0 siblings, 2 replies; 15+ messages in thread
From: Khalil @ 2026-02-15 13:55 UTC (permalink / raw)
To: broonie, hdegoede, ilpo.jarvinen
Cc: rf, linux-spi, platform-driver-x86, linux-kernel
To: broonie@kernel.org, hdegoede@kernel.org, ilpo.jarvinen@linux.intel.com
Cc: rf@opensource.cirrus.com, linux-spi@vger.kernel.org,
platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org
Hi,
This patch series fixes an issue where the second Cirrus Logic CS35L56
amplifier fails to probe on several HP and ASUS laptops with Intel Lunar
Lake processors. The amplifiers are connected via SPI, and the second
one (CS1) always times out reading HALO_STATE (returns all zeros).
Speakers work correctly in Windows.
The root cause is a broken ACPI DSDT on these machines. The SPI
controller's _DSD declares:
"cs-gpios", Package (0x01) { Zero }
This only defines CS0 (native). The CS1 GPIO entry is missing entirely,
even though the ACPI device node (CSC3556) does define a GpioIo resource
for CS1 and both SpiSerialBusV2 resources correctly specify
DeviceSelection 0 and 1.
This causes two problems:
1. The SPI framework has no GPIO descriptor for CS1, so it never toggles
the actual chip select line to the second amplifier.
2. On Intel LPSS controllers with dynamic clock gating
(cs_clk_stays_gated=true, e.g., Cannon Lake and later), the SPI
clock is gated when no native CS is asserted. With GPIO chip select,
the native CS register is never asserted, so the clock never runs.
The fix is in two parts:
Patch 1 modifies serial-multi-instantiate to acquire the CS GPIO from
the ACPI GpioIo resource and install it on the controller's cs_gpiods
array. Setting it directly on the spi_device doesn't work because
__spi_add_device() unconditionally overwrites spi->cs_gpiod[] from
ctlr->cs_gpiods[cs]. The array is reallocated to accommodate the
additional chip select.
Patch 2 modifies spi-pxa2xx to handle GPIO chip select on LPSS
controllers with dynamic clock gating. When spi_is_csgpiod() is true,
cs_assert asserts the native CS in the control register (to enable the
clock domain) and forces the clock gate on. cs_deassert reverses both.
Tested on HP EliteBook 8 G1i (Intel Core Ultra 7 258V, Lunar Lake-M)
with 2x CS35L56 Rev B0. Both amplifiers now probe successfully, load
calibration and tuning, and produce audio.
Related bug reports:
- https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/2131138
- https://bugzilla.kernel.org/show_bug.cgi?id=221064
- https://github.com/thesofproject/linux/issues/5621
Khalil Laleh (2):
platform/x86: serial-multi-instantiate: Add GPIO chip select support
for SPI devices
spi: pxa2xx: Handle dynamic clock gating for GPIO chip select devices
drivers/platform/x86/serial-multi-instantiate.c | 83 ++++++++++++++++++
drivers/spi/spi-pxa2xx.c | 35 +++++++-
2 files changed, 114 insertions(+), 4 deletions(-)
--
^ permalink raw reply [flat|nested] 15+ messages in thread
* [RFC PATCH 1/2] platform/x86: serial-multi-instantiate: Add GPIO chip select support for SPI devices
2026-02-15 13:55 [RFC PATCH 0/2] Fix second CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios Khalil
@ 2026-02-15 13:55 ` Khalil
2026-02-23 15:50 ` Richard Fitzgerald
` (2 more replies)
2026-02-15 13:55 ` [RFC PATCH 2/2] spi: pxa2xx: Handle dynamic " Khalil
1 sibling, 3 replies; 15+ messages in thread
From: Khalil @ 2026-02-15 13:55 UTC (permalink / raw)
To: broonie, hdegoede, ilpo.jarvinen
Cc: rf, linux-spi, platform-driver-x86, linux-kernel, Khalil Laleh
To: broonie@kernel.org, hdegoede@kernel.org, ilpo.jarvinen@linux.intel.com
Cc: rf@opensource.cirrus.com, linux-spi@vger.kernel.org,
platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org
Some ACPI platforms (e.g., HP/ASUS laptops with Intel Lunar Lake and
dual CS35L56 amplifiers) have a broken cs-gpios property in the SPI
controller's _DSD that only declares the first chip select. The second
chip select GPIO is defined as a GpioIo resource in the peripheral's
ACPI node but is not referenced by the controller.
This causes the SPI framework to have no GPIO descriptor for CS > 0,
so the chip select line is never toggled for the second device.
Fix this by acquiring the chip select GPIO from the ACPI GpioIo resource
in serial-multi-instantiate and installing it on the controller's
cs_gpiods array. The GPIO must be set on the controller (not the device)
because __spi_add_device() unconditionally overwrites spi->cs_gpiod[]
from ctlr->cs_gpiods[cs].
The controller's cs_gpiods array is reallocated to accommodate the
additional chip select, and SPI_CONTROLLER_GPIO_SS is set so the
framework calls both the GPIO toggle and the controller's set_cs
callback (needed for clock gate management on Intel LPSS controllers).
Link: https://bugzilla.kernel.org/show_bug.cgi?id=221064
Link: https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/2131138
Link: https://github.com/thesofproject/linux/issues/5621
Signed-off-by: Khalil Laleh <khalilst@gmail.com>
---
drivers/platform/x86/serial-multi-instantiate.c | 83 ++++++++++++++++++
1 file changed, 83 insertions(+)
--- a/drivers/platform/x86/serial-multi-instantiate.c
+++ b/drivers/platform/x86/serial-multi-instantiate.c
@@ -8,6 +8,9 @@
#include <linux/acpi.h>
#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/machine.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
@@ -17,6 +20,17 @@
#include <linux/spi/spi.h>
#include <linux/types.h>
+/*
+ * ACPI GPIO mapping for the chip select GpioIo resource.
+ * Maps "cs-gpios" to the first GpioIo resource in the ACPI _CRS.
+ */
+static const struct acpi_gpio_params smi_cs_gpio_params = { 0, 0, false };
+
+static const struct acpi_gpio_mapping smi_cs_gpio_mapping[] = {
+ { "cs-gpios", &smi_cs_gpio_params, 1 },
+ { }
+};
+
#define IRQ_RESOURCE_TYPE GENMASK(1, 0)
#define IRQ_RESOURCE_NONE 0
#define IRQ_RESOURCE_GPIO 1
@@ -114,8 +128,11 @@
struct acpi_device *adev = ACPI_COMPANION(dev);
struct spi_controller *ctlr;
struct spi_device *spi_dev;
+ struct gpio_desc *cs_gpio = NULL;
char name[50];
int i, ret, count;
+ bool gpio_mapped = false;
+ u16 cs;
ret = acpi_spi_count_resources(adev);
if (ret < 0)
@@ -139,6 +156,72 @@
}
ctlr = spi_dev->controller;
+ cs = spi_get_chipselect(spi_dev, 0);
+
+ if (cs >= ctlr->num_chipselect) {
+ dev_info(dev, "Increasing num_chipselect from %u to %u for CS%u\n",
+ ctlr->num_chipselect, cs + 1, cs);
+ ctlr->num_chipselect = cs + 1;
+ }
+
+ /*
+ * For devices with CS > 0, use GPIO chip select from ACPI
+ * GpioIo resource. The GPIO must be set on the controller's
+ * cs_gpiods array (not the device's cs_gpiod) because
+ * __spi_add_device() overwrites spi->cs_gpiod from
+ * ctlr->cs_gpiods[cs]. Also reallocate the array since
+ * a broken ACPI cs-gpios property may have undersized it.
+ *
+ * SPI_CONTROLLER_GPIO_SS ensures the framework calls both
+ * the GPIO toggle and controller->set_cs (for clock gate
+ * management on Intel LPSS controllers).
+ */
+ if (cs > 0 && !gpio_mapped) {
+ ret = devm_acpi_dev_add_driver_gpios(dev, smi_cs_gpio_mapping);
+ if (ret)
+ dev_warn(dev, "Failed to add GPIO mapping: %d\n", ret);
+ else
+ gpio_mapped = true;
+ }
+
+ if (cs > 0 && gpio_mapped && !cs_gpio) {
+ cs_gpio = devm_gpiod_get(dev, "cs", GPIOD_OUT_HIGH);
+ if (IS_ERR(cs_gpio)) {
+ dev_warn(dev, "Failed to get CS GPIO: %ld\n",
+ PTR_ERR(cs_gpio));
+ cs_gpio = NULL;
+ } else {
+ dev_info(dev, "Got CS GPIO for amp CS%u\n", cs);
+ }
+ }
+
+ if (cs > 0 && cs_gpio) {
+ /*
+ * Set GPIO on the controller's cs_gpiods array so
+ * __spi_add_device() will propagate it to the device.
+ * Reallocate the array to fit the new num_chipselect.
+ */
+ struct gpio_desc **new_gpiods;
+
+ new_gpiods = devm_kcalloc(&ctlr->dev,
+ ctlr->num_chipselect,
+ sizeof(*new_gpiods),
+ GFP_KERNEL);
+ if (new_gpiods) {
+ if (ctlr->cs_gpiods)
+ new_gpiods[0] = ctlr->cs_gpiods[0];
+ new_gpiods[cs] = cs_gpio;
+ ctlr->cs_gpiods = new_gpiods;
+ ctlr->flags |= SPI_CONTROLLER_GPIO_SS;
+ dev_info(dev, "Set GPIO CS on controller for CS%u\n", cs);
+ } else {
+ dev_err(dev, "Failed to alloc cs_gpiods\n");
+ }
+ }
+
+ dev_info(dev, "Device %d: CS=%u, num_chipselect=%u, gpio_cs=%s\n",
+ i, cs, ctlr->num_chipselect,
+ (cs > 0 && cs_gpio) ? "yes" : "no");
strscpy(spi_dev->modalias, inst_array[i].type);
^ permalink raw reply [flat|nested] 15+ messages in thread
* [RFC PATCH 2/2] spi: pxa2xx: Handle dynamic clock gating for GPIO chip select devices
2026-02-15 13:55 [RFC PATCH 0/2] Fix second CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios Khalil
2026-02-15 13:55 ` [RFC PATCH 1/2] platform/x86: serial-multi-instantiate: Add GPIO chip select support for SPI devices Khalil
@ 2026-02-15 13:55 ` Khalil
1 sibling, 0 replies; 15+ messages in thread
From: Khalil @ 2026-02-15 13:55 UTC (permalink / raw)
To: broonie, hdegoede, ilpo.jarvinen
Cc: rf, linux-spi, platform-driver-x86, linux-kernel, Khalil Laleh
To: broonie@kernel.org, hdegoede@kernel.org, ilpo.jarvinen@linux.intel.com
Cc: rf@opensource.cirrus.com, linux-spi@vger.kernel.org,
platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org
On Intel LPSS SPI controllers (Cannon Lake and later), the
cs_clk_stays_gated flag is set, meaning the SPI clock is dynamically
gated based on the native chip select state. When using GPIO chip
select (spi_is_csgpiod() returns true), the native CS register is never
asserted through the normal path, so the SPI clock never runs and all
reads return zeros.
Fix this by handling GPIO chip select devices explicitly in cs_assert
and cs_deassert:
- cs_assert: Assert the native CS in the control register (to enable
the clock domain) and force the clock gate on via
LPSS_PRIV_CLOCK_GATE.
- cs_deassert: Deassert the native CS and restore the clock gate to
auto mode.
The SPI framework handles the actual GPIO toggle; this code only
manages the LPSS clock gating. SPI_CONTROLLER_GPIO_SS must be set on
the controller (done by serial-multi-instantiate) so the framework
calls both the GPIO toggle and this set_cs callback.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=221064
Link: https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/2131138
Link: https://github.com/thesofproject/linux/issues/5621
Signed-off-by: Khalil Laleh <khalilst@gmail.com>
---
drivers/spi/spi-pxa2xx.c | 35 +++++++++++++++++++++++++++++----
1 file changed, 31 insertions(+), 4 deletions(-)
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -419,20 +419,43 @@
{
struct driver_data *drv_data =
spi_controller_get_devdata(spi->controller);
+ const struct lpss_config *config;
if (drv_data->ssp_type == CE4100_SSP) {
pxa2xx_spi_write(drv_data, SSSR, spi_get_chipselect(spi, 0));
return;
}
- if (is_lpss_ssp(drv_data))
- lpss_ssp_cs_control(spi, true);
+ if (is_lpss_ssp(drv_data)) {
+ config = lpss_get_config(drv_data);
+
+ if (spi_is_csgpiod(spi)) {
+ /*
+ * GPIO handles the actual chip select to the device.
+ * On LPSS controllers with dynamic clock gating, the
+ * SPI clock won't run unless the native CS state says
+ * "asserted" in the CS control register. Assert native
+ * CS in the register to enable the clock, and force
+ * the clock gate on.
+ */
+ lpss_ssp_cs_control(spi, true);
+ if (config->cs_clk_stays_gated) {
+ __lpss_ssp_update_priv(drv_data,
+ LPSS_PRIV_CLOCK_GATE,
+ LPSS_PRIV_CLOCK_GATE_CLK_CTL_MASK,
+ LPSS_PRIV_CLOCK_GATE_CLK_CTL_FORCE_ON);
+ }
+ } else {
+ lpss_ssp_cs_control(spi, true);
+ }
+ }
}
static void cs_deassert(struct spi_device *spi)
{
struct driver_data *drv_data =
spi_controller_get_devdata(spi->controller);
+ const struct lpss_config *config;
unsigned long timeout;
if (drv_data->ssp_type == CE4100_SSP)
@@ -444,8 +467,22 @@
!time_after(jiffies, timeout))
cpu_relax();
- if (is_lpss_ssp(drv_data))
- lpss_ssp_cs_control(spi, false);
+ if (is_lpss_ssp(drv_data)) {
+ config = lpss_get_config(drv_data);
+
+ if (spi_is_csgpiod(spi)) {
+ /* Deassert native CS and restore clock gating */
+ lpss_ssp_cs_control(spi, false);
+ if (config->cs_clk_stays_gated) {
+ __lpss_ssp_update_priv(drv_data,
+ LPSS_PRIV_CLOCK_GATE,
+ LPSS_PRIV_CLOCK_GATE_CLK_CTL_MASK,
+ LPSS_PRIV_CLOCK_GATE_CLK_CTL_FORCE_OFF);
+ }
+ } else {
+ lpss_ssp_cs_control(spi, false);
+ }
+ }
}
static void pxa2xx_spi_set_cs(struct spi_device *spi, bool level)
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RFC PATCH 1/2] platform/x86: serial-multi-instantiate: Add GPIO chip select support for SPI devices
2026-02-15 13:55 ` [RFC PATCH 1/2] platform/x86: serial-multi-instantiate: Add GPIO chip select support for SPI devices Khalil
@ 2026-02-23 15:50 ` Richard Fitzgerald
2026-04-11 18:04 ` [PATCH v2 0/3] Fix CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios Khalil
2026-04-12 16:31 ` Khalil
2 siblings, 0 replies; 15+ messages in thread
From: Richard Fitzgerald @ 2026-02-23 15:50 UTC (permalink / raw)
To: Khalil, broonie, hdegoede, ilpo.jarvinen
Cc: linux-spi, platform-driver-x86, linux-kernel
On 15/02/2026 1:55 pm, Khalil wrote:
> To: broonie@kernel.org, hdegoede@kernel.org, ilpo.jarvinen@linux.intel.com
> Cc: rf@opensource.cirrus.com, linux-spi@vger.kernel.org,
> platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org
>
> Some ACPI platforms (e.g., HP/ASUS laptops with Intel Lunar Lake and
> dual CS35L56 amplifiers) have a broken cs-gpios property in the SPI
The only Asus model we are aware of with CS35L56 and a cs-gpios problem
is the GU605C. That was fixed by a BIOS update so doesn't need a kernel
workaround. Is this the Asus you are referring to? Or is there another?
> controller's _DSD that only declares the first chip select. The second
> chip select GPIO is defined as a GpioIo resource in the peripheral's
Maybe the second. Maybe the first. It depends on the hardware.
Some laptops have four amps and four chip selects.
> ACPI node but is not referenced by the controller.
>
> This causes the SPI framework to have no GPIO descriptor for CS > 0,
> so the chip select line is never toggled for the second device.
>
It fails before that matters. The driver for that device will never be
probed because SPI core rejects the invalid chip select.
> Fix this by acquiring the chip select GPIO from the ACPI GpioIo resource
> in serial-multi-instantiate and installing it on the controller's
> cs_gpiods array. The GPIO must be set on the controller (not the device)
> because __spi_add_device() unconditionally overwrites spi->cs_gpiod[]
> from ctlr->cs_gpiods[cs].
If you change __spi_add_device() so it doesn't overwrite preset cs_gpiod
you could set it on the device. You wouldn't have to mess around with
the controller configuration after the controller has probed.
Alternatively, if you can make the amp driver probe, it can fix itself
up like the cs35l41_hda driver does. Maybe you can use this
special case in the SPI core:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/spi/spi.c?h=linux-6.19.y#n616
...
> +/*
> + * ACPI GPIO mapping for the chip select GpioIo resource.
> + * Maps "cs-gpios" to the first GpioIo resource in the ACPI _CRS.
> + */
> +static const struct acpi_gpio_params smi_cs_gpio_params = { 0, 0, false };
> +
> +static const struct acpi_gpio_mapping smi_cs_gpio_mapping[] = {
> + { "cs-gpios", &smi_cs_gpio_params, 1 },
> + { }
> +};
> +
> #define IRQ_RESOURCE_TYPE GENMASK(1, 0)
> #define IRQ_RESOURCE_NONE 0
> #define IRQ_RESOURCE_GPIO 1
> @@ -114,8 +128,11 @@
> struct acpi_device *adev = ACPI_COMPANION(dev);
> struct spi_controller *ctlr;
> struct spi_device *spi_dev;
> + struct gpio_desc *cs_gpio = NULL;
> char name[50];
> int i, ret, count;
> + bool gpio_mapped = false;
> + u16 cs;
>
> ret = acpi_spi_count_resources(adev);
> if (ret < 0)
> @@ -139,6 +156,72 @@
> }
>
> ctlr = spi_dev->controller;
> + cs = spi_get_chipselect(spi_dev, 0);
> +
> + if (cs >= ctlr->num_chipselect) {
> + dev_info(dev, "Increasing num_chipselect from %u to %u for CS%u\n",
> + ctlr->num_chipselect, cs + 1, cs);
> + ctlr->num_chipselect = cs + 1;
> + }
> +
> + /*
> + * For devices with CS > 0, use GPIO chip select from ACPI
> + * GpioIo resource. The GPIO must be set on the controller's
> + * cs_gpiods array (not the device's cs_gpiod) because
> + * __spi_add_device() overwrites spi->cs_gpiod from
> + * ctlr->cs_gpiods[cs]. Also reallocate the array since
> + * a broken ACPI cs-gpios property may have undersized it.
> + *
> + * SPI_CONTROLLER_GPIO_SS ensures the framework calls both
> + * the GPIO toggle and controller->set_cs (for clock gate
> + * management on Intel LPSS controllers).
> + */
Only do this fixup for models where you know what the cs-gpios mappings
should be.
> + if (cs > 0 && !gpio_mapped) {
> + ret = devm_acpi_dev_add_driver_gpios(dev, smi_cs_gpio_mapping);
> + if (ret)
> + dev_warn(dev, "Failed to add GPIO mapping: %d\n", ret);
> + else
> + gpio_mapped = true;
> + }
> +
> + if (cs > 0 && gpio_mapped && !cs_gpio) {
> + cs_gpio = devm_gpiod_get(dev, "cs", GPIOD_OUT_HIGH);
> + if (IS_ERR(cs_gpio)) {
> + dev_warn(dev, "Failed to get CS GPIO: %ld\n",
> + PTR_ERR(cs_gpio));
> + cs_gpio = NULL;
> + } else {
> + dev_info(dev, "Got CS GPIO for amp CS%u\n", cs);
> + }
> + }
> +
> + if (cs > 0 && cs_gpio) {
> + /*
> + * Set GPIO on the controller's cs_gpiods array so
> + * __spi_add_device() will propagate it to the device.
> + * Reallocate the array to fit the new num_chipselect.
> + */
> + struct gpio_desc **new_gpiods;
> +
> + new_gpiods = devm_kcalloc(&ctlr->dev,
> + ctlr->num_chipselect,
> + sizeof(*new_gpiods),
> + GFP_KERNEL);
> + if (new_gpiods) {
> + if (ctlr->cs_gpiods)
> + new_gpiods[0] = ctlr->cs_gpiods[0];
> + new_gpiods[cs] = cs_gpio;
> + ctlr->cs_gpiods = new_gpiods;
> + ctlr->flags |= SPI_CONTROLLER_GPIO_SS;
Messing with the configuration of a probed SPI controller seems risky.
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 0/3] Fix CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios
2026-02-15 13:55 ` [RFC PATCH 1/2] platform/x86: serial-multi-instantiate: Add GPIO chip select support for SPI devices Khalil
2026-02-23 15:50 ` Richard Fitzgerald
@ 2026-04-11 18:04 ` Khalil
2026-04-11 18:04 ` [PATCH 1/3] spi: Preserve preset cs_gpiod in __spi_add_device() Khalil
` (3 more replies)
2026-04-12 16:31 ` Khalil
2 siblings, 4 replies; 15+ messages in thread
From: Khalil @ 2026-04-11 18:04 UTC (permalink / raw)
To: broonie, hdegoede, ilpo.jarvinen
Cc: rf, linux-spi, platform-driver-x86, linux-kernel
To: broonie@kernel.org, hdegoede@kernel.org, ilpo.jarvinen@linux.intel.com
Cc: rf@opensource.cirrus.com, linux-spi@vger.kernel.org,
platform-driver-x86@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20260215135524.1171065-2-khalil@rentman.nl>
Hi,
This is v2 of the patch series fixing dual CS35L56 amplifiers on HP
laptops with Intel Lunar Lake and broken ACPI cs-gpios.
Changes since RFC v1 (addressing feedback from Richard Fitzgerald):
- Added DMI quirk table: GPIO CS fixup is now only applied on known
affected platforms (HP EliteBook 8 G1i, board 8D8A), not generically
for all devices with CS > 0.
- Fixed chip select range check: only chip selects outside the
controller's num_chipselect range are fixed up. A NULL cs_gpiods[cs]
within range means "native chip select", not broken. This avoids
incorrectly replacing native CS0 with the GPIO descriptor.
- Removed ASUS reference (GU605C was fixed by BIOS update).
- Added Patch 1/3 (spi core): __spi_add_device() now preserves preset
cs_gpiod on the device instead of unconditionally overwriting from
ctlr->cs_gpiods. This was suggested by Richard as the preferred
approach to avoid modifying controller state post-probe.
- Patch 2/3 (serial-multi-instantiate): Extracted GPIO fixup into a
dedicated helper function. Currently still installs the GPIO on the
controller's cs_gpiods array because __spi_add_device() overwrites
device-level cs_gpiod. With Patch 1/3 applied, a future cleanup
could set the GPIO directly on the device instead.
- Patch 3/3 (spi-pxa2xx): Unchanged from v1. Handles clock gating
on Intel LPSS controllers when GPIO chip select is active.
Note: While Richard also suggested the cs35l41_hda self-fixup approach
(setting cs_gpiod on the device post-probe via spi_setup), this doesn't
work here because the device can't even be added to the bus - SPI core
rejects it with -EINVAL when cs >= num_chipselect. The serial-multi-
instantiate approach is necessary to extend num_chipselect first.
Regarding modifying the probed controller: I acknowledge this is not
ideal. Patch 1/3 is a step toward the cleaner approach (preset on
device). However, num_chipselect still needs to be extended, and
cs_gpiods needs to be expanded to prevent out-of-bounds access in
__spi_add_device(). I'm open to suggestions for a cleaner way to
handle this.
Tested on HP EliteBook 8 G1i 16 inch (Intel Core Ultra 7 258V,
Lunar Lake-M) with 2x CS35L56 Rev B0. Both amplifiers probe
successfully, load calibration and tuning, and produce audio.
Related bug reports:
- https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/2131138
- https://bugzilla.kernel.org/show_bug.cgi?id=221064
- https://github.com/thesofproject/linux/issues/5621
Khalil (3):
spi: Preserve preset cs_gpiod in __spi_add_device()
platform/x86: serial-multi-instantiate: Fix SPI chip select on
platforms with incomplete ACPI cs-gpios
spi: pxa2xx: Handle clock gating for GPIO chip select devices
drivers/spi/spi.c | 3 +-
drivers/platform/x86/serial-multi-instantiate.c | 156 +++++++++++++++-
drivers/spi/spi-pxa2xx.c | 78 ++++-----
3 files changed, 196 insertions(+), 41 deletions(-)
--
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/3] spi: Preserve preset cs_gpiod in __spi_add_device()
2026-04-11 18:04 ` [PATCH v2 0/3] Fix CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios Khalil
@ 2026-04-11 18:04 ` Khalil
2026-04-11 18:04 ` [PATCH 2/3] platform/x86: serial-multi-instantiate: Fix SPI chip select on platforms with incomplete ACPI cs-gpios Khalil
` (2 subsequent siblings)
3 siblings, 0 replies; 15+ messages in thread
From: Khalil @ 2026-04-11 18:04 UTC (permalink / raw)
To: broonie, hdegoede, ilpo.jarvinen
Cc: rf, linux-spi, platform-driver-x86, linux-kernel, Khalil
From: Khalil <khalilst@gmail.com>
__spi_add_device() unconditionally overwrites spi->cs_gpiod[] from
ctlr->cs_gpiods[cs], even if the caller has already set a GPIO
descriptor on the device. This prevents drivers like
serial-multi-instantiate from pre-configuring a GPIO chip select
acquired from ACPI before adding the device.
Skip the overwrite when the device already has a cs_gpiod set for
the given index, allowing callers to preset GPIO chip selects that
aren't described in the controller's cs-gpios property.
This is useful on platforms where the ACPI _DSD cs-gpios property
on the SPI controller is incomplete, but the peripheral's ACPI node
does contain the correct GpioIo resource for its chip select.
Suggested-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Khalil <khalilst@gmail.com>
---
drivers/spi/spi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index XXXXXXX..XXXXXXX 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -1148,7 +1148,8 @@ static int __spi_add_device(struct spi_device *spi)
if (ctlr->cs_gpiods) {
for (idx = 0; idx < SPI_CS_CNT_MAX; idx++) {
- if (is_valid_cs(cs))
+ cs = spi_get_chipselect(spi, idx);
+ if (is_valid_cs(cs) && !spi_get_csgpiod(spi, idx))
spi_set_csgpiod(spi, idx, ctlr->cs_gpiods[cs]);
}
}
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 2/3] platform/x86: serial-multi-instantiate: Fix SPI chip select on platforms with incomplete ACPI cs-gpios
2026-04-11 18:04 ` [PATCH v2 0/3] Fix CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios Khalil
2026-04-11 18:04 ` [PATCH 1/3] spi: Preserve preset cs_gpiod in __spi_add_device() Khalil
@ 2026-04-11 18:04 ` Khalil
2026-04-11 18:04 ` [PATCH 3/3] spi: pxa2xx: Handle clock gating for GPIO chip select devices Khalil
2026-04-11 21:57 ` [PATCH v2 0/3] Fix CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios Mark Brown
3 siblings, 0 replies; 15+ messages in thread
From: Khalil @ 2026-04-11 18:04 UTC (permalink / raw)
To: broonie, hdegoede, ilpo.jarvinen
Cc: rf, linux-spi, platform-driver-x86, linux-kernel, Khalil
From: Khalil <khalilst@gmail.com>
Some HP laptops with Intel Lunar Lake and dual Cirrus Logic CS35L56
amplifiers over SPI have an incomplete cs-gpios property in the SPI
controller's _DSD - it only declares the first chip select. The
remaining chip select GPIOs are defined as GpioIo resources in the
peripheral's ACPI node but are not referenced by the controller.
This causes the SPI framework to reject devices whose chip select
exceeds num_chipselect with -EINVAL, preventing the second amplifier
from probing.
Fix this on known affected platforms by:
1. Adding a DMI quirk table to identify affected systems
2. For devices with chip selects outside the controller's range,
acquiring the GPIO from the peripheral's ACPI GpioIo resource
3. Extending num_chipselect and reallocating the controller's
cs_gpiods array to install the GPIO descriptor
4. Setting SPI_CONTROLLER_GPIO_SS so the framework calls both
the GPIO toggle and controller->set_cs (needed for clock
gating on Intel LPSS controllers)
Only chip selects beyond the controller's num_chipselect are fixed up.
Chip selects within range with a NULL cs_gpiods entry are left alone,
as NULL means "native chip select" which is intentional.
Tested on HP EliteBook 8 G1i 16 inch (board 8D8A) with 2x CS35L56
Rev B0 amplifiers. Both amplifiers probe and produce audio.
Signed-off-by: Khalil <khalilst@gmail.com>
---
drivers/platform/x86/serial-multi-instantiate.c | 163 ++++++++++++++-
1 file changed, 156 insertions(+), 7 deletions(-)
diff --git a/drivers/platform/x86/serial-multi-instantiate.c b/drivers/platform/x86/serial-multi-instantiate.c
index XXXXXXX..XXXXXXX 100644
--- a/drivers/platform/x86/serial-multi-instantiate.c
+++ b/drivers/platform/x86/serial-multi-instantiate.c
@@ -8,6 +8,10 @@
#include <linux/acpi.h>
#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/dmi.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/machine.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
@@ -46,6 +50,53 @@ struct smi {
int spi_num;
struct i2c_client **i2c_devs;
struct spi_device **spi_devs;
+ struct gpio_desc *cs_gpio;
+};
+
+/*
+ * Quirk data for platforms with broken ACPI SPI chip select descriptions.
+ * cs_gpio_idx: index of the GpioIo resource in the ACPI _CRS that provides
+ * the chip select GPIO for devices missing a proper cs-gpios
+ * entry on the SPI controller.
+ */
+struct smi_cs_gpio_quirk {
+ int cs_gpio_idx;
+};
+
+static const struct smi_cs_gpio_quirk hp_elitebook_8g1i_quirk = {
+ .cs_gpio_idx = 0,
+};
+
+/*
+ * DMI table of platforms with broken SPI chip select ACPI descriptions.
+ *
+ * These systems have multiple SPI peripherals (e.g., dual CS35L56
+ * amplifiers) but the SPI controller's _DSD cs-gpios property is
+ * incomplete - it only declares the first chip select. The remaining
+ * chip select GPIOs are defined as GpioIo resources in the peripheral's
+ * ACPI node but are not referenced by the controller.
+ */
+static const struct dmi_system_id smi_cs_gpio_dmi_table[] = {
+ {
+ .ident = "HP EliteBook 8 G1i 16 inch",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_BOARD_NAME, "8D8A"),
+ },
+ .driver_data = (void *)&hp_elitebook_8g1i_quirk,
+ },
+ { }
+};
+
+/*
+ * ACPI GPIO mapping for the chip select GpioIo resource.
+ * Maps "cs-gpios" to the GpioIo resource at index 0 of the ACPI _CRS.
+ */
+static const struct acpi_gpio_params smi_cs_gpio_params = { 0, 0, false };
+
+static const struct acpi_gpio_mapping smi_cs_gpio_mapping[] = {
+ { "cs-gpios", &smi_cs_gpio_params, 1 },
+ { }
};
static int smi_get_irq(struct platform_device *pdev, struct acpi_device *adev,
@@ -99,6 +150,85 @@ static void smi_devs_unregister(struct smi *smi)
}
}
+/*
+ * smi_spi_setup_cs_gpio - Fix up chip select for a device on a platform
+ * with broken ACPI cs-gpios description.
+ *
+ * On affected platforms, the SPI controller's cs-gpios property is incomplete,
+ * so the framework has no GPIO descriptor for some chip selects. This causes
+ * __spi_add_device() to reject the device with -EINVAL (cs >= num_chipselect).
+ *
+ * This function:
+ * 1. Extends num_chipselect if the device's CS is out of range
+ * 2. Reallocates cs_gpiods to match, preventing out-of-bounds access
+ * in __spi_add_device()
+ * 3. Installs the GPIO from the peripheral's ACPI node into the
+ * controller's cs_gpiods array so __spi_add_device() propagates
+ * it to the device
+ * 4. Sets SPI_CONTROLLER_GPIO_SS so the framework calls both the GPIO
+ * toggle and controller->set_cs (needed for clock gating on Intel
+ * LPSS controllers)
+ */
+static int smi_spi_setup_cs_gpio(struct device *dev,
+ struct spi_device *spi_dev,
+ struct smi *smi,
+ const struct smi_cs_gpio_quirk *quirk)
+{
+ struct spi_controller *ctlr = spi_dev->controller;
+ struct gpio_desc **new_gpiods;
+ u16 cs = spi_get_chipselect(spi_dev, 0);
+
+ /*
+ * Only fix up chip selects that the controller doesn't know about.
+ * A NULL cs_gpiods[cs] within the controller's num_chipselect range
+ * means "native chip select" - that's intentional, not broken.
+ * The broken case is when cs >= num_chipselect, meaning the ACPI
+ * cs-gpios property on the controller was incomplete.
+ */
+ if (cs < ctlr->num_chipselect)
+ return 0;
+
+ /* Extend num_chipselect to cover this device */
+ dev_info(dev, "Extending num_chipselect from %u to %u for CS%u\n",
+ ctlr->num_chipselect, cs + 1, cs);
+ ctlr->num_chipselect = cs + 1;
+
+ /* Acquire the CS GPIO from the ACPI GpioIo resource if not yet done */
+ if (!smi->cs_gpio) {
+ int ret;
+
+ ret = devm_acpi_dev_add_driver_gpios(dev, smi_cs_gpio_mapping);
+ if (ret) {
+ dev_warn(dev, "Failed to add CS GPIO mapping: %d\n", ret);
+ return ret;
+ }
+
+ smi->cs_gpio = devm_gpiod_get(dev, "cs", GPIOD_OUT_HIGH);
+ if (IS_ERR(smi->cs_gpio)) {
+ dev_warn(dev, "Failed to get CS GPIO: %ld\n",
+ PTR_ERR(smi->cs_gpio));
+ smi->cs_gpio = NULL;
+ return -ENOENT;
+ }
+ dev_info(dev, "Acquired CS GPIO for CS%u from ACPI GpioIo[%d]\n",
+ cs, quirk->cs_gpio_idx);
+ }
+
+ /*
+ * Reallocate the controller's cs_gpiods array to accommodate the
+ * new num_chipselect, and install the GPIO descriptor. This is
+ * necessary because __spi_add_device() unconditionally reads
+ * ctlr->cs_gpiods[cs] to set the device's cs_gpiod.
+ */
+ new_gpiods = devm_kcalloc(&ctlr->dev, ctlr->num_chipselect,
+ sizeof(*new_gpiods), GFP_KERNEL);
+ if (!new_gpiods)
+ return -ENOMEM;
+
+ if (ctlr->cs_gpiods) {
+ unsigned int i;
+
+ for (i = 0; i < cs; i++)
+ new_gpiods[i] = ctlr->cs_gpiods[i];
+ }
+ new_gpiods[cs] = smi->cs_gpio;
+ ctlr->cs_gpiods = new_gpiods;
+
+ /*
+ * SPI_CONTROLLER_GPIO_SS ensures the framework calls both the
+ * GPIO CS toggle and controller->set_cs(). This is required on
+ * Intel LPSS controllers where set_cs handles clock gating.
+ */
+ ctlr->flags |= SPI_CONTROLLER_GPIO_SS;
+
+ dev_info(dev, "Installed GPIO CS on controller for CS%u\n", cs);
+ return 0;
+}
+
/**
* smi_spi_probe - Instantiate multiple SPI devices from inst array
* @pdev: Platform device
@@ -112,10 +242,19 @@ static int smi_spi_probe(struct platform_device *pdev, struct smi *smi,
{
struct device *dev = &pdev->dev;
struct acpi_device *adev = ACPI_COMPANION(dev);
+ const struct dmi_system_id *dmi_id;
+ const struct smi_cs_gpio_quirk *quirk = NULL;
struct spi_controller *ctlr;
struct spi_device *spi_dev;
char name[50];
int i, ret, count;
+ u16 cs;
+
+ dmi_id = dmi_first_match(smi_cs_gpio_dmi_table);
+ if (dmi_id) {
+ quirk = dmi_id->driver_data;
+ dev_info(dev, "Applying CS GPIO quirk for %s\n", dmi_id->ident);
+ }
ret = acpi_spi_count_resources(adev);
if (ret < 0)
@@ -139,6 +278,19 @@ static int smi_spi_probe(struct platform_device *pdev, struct smi *smi,
}
ctlr = spi_dev->controller;
+ cs = spi_get_chipselect(spi_dev, 0);
+
+ /*
+ * On quirked platforms, fix up the chip select GPIO for
+ * devices that would otherwise fail due to incomplete
+ * ACPI cs-gpios on the SPI controller.
+ */
+ if (quirk) {
+ ret = smi_spi_setup_cs_gpio(dev, spi_dev, smi, quirk);
+ if (ret)
+ dev_dbg(dev, "CS GPIO setup returned %d for CS%u\n",
+ ret, cs);
+ }
strscpy(spi_dev->modalias, inst_array[i].type);
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 3/3] spi: pxa2xx: Handle clock gating for GPIO chip select devices
2026-04-11 18:04 ` [PATCH v2 0/3] Fix CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios Khalil
2026-04-11 18:04 ` [PATCH 1/3] spi: Preserve preset cs_gpiod in __spi_add_device() Khalil
2026-04-11 18:04 ` [PATCH 2/3] platform/x86: serial-multi-instantiate: Fix SPI chip select on platforms with incomplete ACPI cs-gpios Khalil
@ 2026-04-11 18:04 ` Khalil
2026-04-11 21:57 ` [PATCH v2 0/3] Fix CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios Mark Brown
3 siblings, 0 replies; 15+ messages in thread
From: Khalil @ 2026-04-11 18:04 UTC (permalink / raw)
To: broonie, hdegoede, ilpo.jarvinen
Cc: rf, linux-spi, platform-driver-x86, linux-kernel, Khalil
From: Khalil <khalilst@gmail.com>
On Intel LPSS SPI controllers (Cannon Lake and later) with dynamic
clock gating (cs_clk_stays_gated=true), the SPI clock is gated when
no native chip select is asserted. When using a GPIO chip select
(via SPI_CONTROLLER_GPIO_SS), the SPI framework toggles the GPIO
and also calls the controller's set_cs callback.
Handle this in the pxa2xx cs_assert/cs_deassert functions: when the
device uses a GPIO chip select on an LPSS controller, assert native
CS in the control register to enable the clock, and force the clock
gate on. On deassert, restore both.
This is needed on platforms where serial-multi-instantiate installs
a GPIO chip select from the peripheral's ACPI GpioIo resource to
work around an incomplete cs-gpios property on the SPI controller.
Also remove the unconditional num_chipselect bump to 2 that was
added as a temporary workaround - the proper fix is now in
serial-multi-instantiate.
Signed-off-by: Khalil <khalilst@gmail.com>
---
drivers/spi/spi-pxa2xx.c | 78 ++++++++++++++++++++-------------------
1 file changed, 41 insertions(+), 37 deletions(-)
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index XXXXXXX..XXXXXXX 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -419,33 +419,43 @@ static void cs_assert(struct spi_device *spi)
{
struct driver_data *drv_data =
spi_controller_get_devdata(spi->controller);
- struct gpio_desc *cs_gpio;
+ const struct lpss_config *config;
if (drv_data->ssp_type == CE4100_SSP) {
pxa2xx_spi_write(drv_data, SSSR, spi_get_chipselect(spi, 0));
return;
}
- /*
- * For devices with GPIO chip select, toggle the GPIO directly.
- * This ensures GPIO CS works on Intel LPSS which only has native CS0.
- */
- cs_gpio = spi_get_csgpiod(spi, 0);
- if (cs_gpio) {
- /* For ACPI: LOW = selected (gpiod_set_value uses logical value) */
- gpiod_set_value_cansleep(cs_gpio, 0);
- return;
- }
-
- if (is_lpss_ssp(drv_data))
- lpss_ssp_cs_control(spi, true);
+ if (is_lpss_ssp(drv_data)) {
+ config = lpss_get_config(drv_data);
+
+ if (spi_is_csgpiod(spi)) {
+ /*
+ * GPIO handles the actual chip select to the device.
+ * On LPSS controllers with dynamic clock gating, the
+ * SPI clock won't run unless the native CS state says
+ * "asserted" in the CS control register. Assert native
+ * CS in the register to enable the clock, and force
+ * the clock gate on.
+ */
+ lpss_ssp_cs_control(spi, true);
+ if (config->cs_clk_stays_gated) {
+ __lpss_ssp_update_priv(drv_data,
+ LPSS_PRIV_CLOCK_GATE,
+ LPSS_PRIV_CLOCK_GATE_CLK_CTL_MASK,
+ LPSS_PRIV_CLOCK_GATE_CLK_CTL_FORCE_ON);
+ }
+ } else {
+ lpss_ssp_cs_control(spi, true);
+ }
+ }
}
static void cs_deassert(struct spi_device *spi)
{
struct driver_data *drv_data =
spi_controller_get_devdata(spi->controller);
- struct gpio_desc *cs_gpio;
+ const struct lpss_config *config;
unsigned long timeout;
if (drv_data->ssp_type == CE4100_SSP)
@@ -457,19 +467,22 @@ static void cs_deassert(struct spi_device *spi)
!time_after(jiffies, timeout))
cpu_relax();
- /*
- * For devices with GPIO chip select, toggle the GPIO directly.
- * This ensures GPIO CS works on Intel LPSS which only has native CS0.
- */
- cs_gpio = spi_get_csgpiod(spi, 0);
- if (cs_gpio) {
- /* For ACPI: HIGH = deselected (gpiod_set_value uses logical value) */
- gpiod_set_value_cansleep(cs_gpio, 1);
- return;
- }
-
- if (is_lpss_ssp(drv_data))
- lpss_ssp_cs_control(spi, false);
+ if (is_lpss_ssp(drv_data)) {
+ config = lpss_get_config(drv_data);
+
+ if (spi_is_csgpiod(spi)) {
+ /* Deassert native CS and restore clock gating */
+ lpss_ssp_cs_control(spi, false);
+ if (config->cs_clk_stays_gated) {
+ __lpss_ssp_update_priv(drv_data,
+ LPSS_PRIV_CLOCK_GATE,
+ LPSS_PRIV_CLOCK_GATE_CLK_CTL_MASK,
+ LPSS_PRIV_CLOCK_GATE_CLK_CTL_FORCE_OFF);
+ }
+ } else {
+ lpss_ssp_cs_control(spi, false);
+ }
+ }
}
static void pxa2xx_spi_set_cs(struct spi_device *spi, bool level)
@@ -1454,13 +1467,6 @@ static int pxa2xx_spi_probe(struct device *dev, ...)
}
}
controller->num_chipselect = platform_info->num_chipselect;
-
- /* Fix for HP EliteBook CS35L56 speakers - need at least 2 chip selects */
- if (is_lpss_ssp(drv_data) && controller->num_chipselect < 2) {
- dev_info(dev, "Increasing num_chipselect from %d to 2 for LPSS audio\n",
- controller->num_chipselect);
- controller->num_chipselect = 2;
- }
controller->use_gpio_descriptors = true;
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 0/3] Fix CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios
2026-04-11 18:04 ` [PATCH v2 0/3] Fix CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios Khalil
` (2 preceding siblings ...)
2026-04-11 18:04 ` [PATCH 3/3] spi: pxa2xx: Handle clock gating for GPIO chip select devices Khalil
@ 2026-04-11 21:57 ` Mark Brown
2026-04-13 8:48 ` Richard Fitzgerald
3 siblings, 1 reply; 15+ messages in thread
From: Mark Brown @ 2026-04-11 21:57 UTC (permalink / raw)
To: Khalil
Cc: hdegoede, ilpo.jarvinen, rf, linux-spi, platform-driver-x86,
linux-kernel
[-- Attachment #1: Type: text/plain, Size: 268 bytes --]
On Sat, Apr 11, 2026 at 08:04:11PM +0200, Khalil wrote:
> This is v2 of the patch series fixing dual CS35L56 amplifiers on HP
> laptops with Intel Lunar Lake and broken ACPI cs-gpios.
I can't work out what these apply against, please submit against my
current tree.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH v2 0/3] Fix CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios
2026-02-15 13:55 ` [RFC PATCH 1/2] platform/x86: serial-multi-instantiate: Add GPIO chip select support for SPI devices Khalil
2026-02-23 15:50 ` Richard Fitzgerald
2026-04-11 18:04 ` [PATCH v2 0/3] Fix CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios Khalil
@ 2026-04-12 16:31 ` Khalil
2026-04-12 16:31 ` [PATCH 1/3] spi: Preserve preset cs_gpiod in __spi_add_device() Khalil
` (2 more replies)
2 siblings, 3 replies; 15+ messages in thread
From: Khalil @ 2026-04-12 16:31 UTC (permalink / raw)
To: broonie, hdegoede, ilpo.jarvinen
Cc: rf, linux-spi, platform-driver-x86, linux-kernel, Khalil
Hi,
This is v2 of the patch series fixing dual CS35L56 amplifiers on HP
laptops with Intel Lunar Lake and broken ACPI cs-gpios.
Changes since RFC v1 (addressing feedback from Richard Fitzgerald):
- Added DMI quirk table: GPIO CS fixup is now only applied on known
affected platforms (HP EliteBook 8 G1i, board 8D8A), not generically
for all devices with CS > 0.
- Fixed chip select range check: only chip selects outside the
controller's num_chipselect range are fixed up. A NULL cs_gpiods[cs]
within range means "native chip select", not broken. This avoids
incorrectly replacing native CS0 with the GPIO descriptor.
- Removed ASUS reference (GU605C was fixed by BIOS update).
- Added Patch 1/3 (spi core): __spi_add_device() now preserves preset
cs_gpiod on the device instead of unconditionally overwriting from
ctlr->cs_gpiods. This was suggested by Richard as the preferred
approach to avoid modifying controller state post-probe.
- Patch 2/3 (serial-multi-instantiate): Extracted GPIO fixup into a
dedicated helper function. Currently still installs the GPIO on the
controller's cs_gpiods array because __spi_add_device() overwrites
device-level cs_gpiod. With Patch 1/3 applied, a future cleanup
could set the GPIO directly on the device instead.
- Patch 3/3 (spi-pxa2xx): Unchanged from v1. Handles clock gating
on Intel LPSS controllers when GPIO chip select is active.
Note: While Richard also suggested the cs35l41_hda self-fixup approach
(setting cs_gpiod on the device post-probe via spi_setup), this doesn't
work here because the device can't even be added to the bus - SPI core
rejects it with -EINVAL when cs >= num_chipselect. The serial-multi-
instantiate approach is necessary to extend num_chipselect first.
Regarding modifying the probed controller: I acknowledge this is not
ideal. Patch 1/3 is a step toward the cleaner approach (preset on
device). However, num_chipselect still needs to be extended, and
cs_gpiods needs to be expanded to prevent out-of-bounds access in
__spi_add_device(). I'm open to suggestions for a cleaner way to
handle this.
Tested on HP EliteBook 8 G1i 16 inch (Intel Core Ultra 7 258V,
Lunar Lake-M) with 2x CS35L56 Rev B0. Both amplifiers probe
successfully, load calibration and tuning, and produce audio.
Related bug reports:
- https://bugs.launchpad.net/ubuntu/+source/alsa-driver/+bug/2131138
- https://bugzilla.kernel.org/show_bug.cgi?id=221064
- https://github.com/thesofproject/linux/issues/5621
Khalil (3):
spi: Preserve preset cs_gpiod in __spi_add_device()
platform/x86: serial-multi-instantiate: Fix SPI chip select on
platforms with incomplete ACPI cs-gpios
spi: pxa2xx: Handle clock gating for GPIO chip select devices
.../platform/x86/serial-multi-instantiate.c | 168 ++++++++++++++++++
drivers/spi/spi-pxa2xx.c | 45 ++++-
drivers/spi/spi.c | 3 +-
3 files changed, 211 insertions(+), 5 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/3] spi: Preserve preset cs_gpiod in __spi_add_device()
2026-04-12 16:31 ` Khalil
@ 2026-04-12 16:31 ` Khalil
2026-04-12 16:31 ` [PATCH 2/3] platform/x86: serial-multi-instantiate: Fix SPI chip select on platforms with incomplete ACPI cs-gpios Khalil
2026-04-12 16:31 ` [PATCH 3/3] spi: pxa2xx: Handle clock gating for GPIO chip select devices Khalil
2 siblings, 0 replies; 15+ messages in thread
From: Khalil @ 2026-04-12 16:31 UTC (permalink / raw)
To: broonie, hdegoede, ilpo.jarvinen
Cc: rf, linux-spi, platform-driver-x86, linux-kernel, Khalil, Khalil
__spi_add_device() unconditionally overwrites spi->cs_gpiod[] from
ctlr->cs_gpiods[cs], even if the caller has already set a GPIO
descriptor on the device. This prevents drivers like
serial-multi-instantiate from pre-configuring a GPIO chip select
acquired from ACPI before adding the device.
Skip the overwrite when the device already has a cs_gpiod set for
the given index, allowing callers to preset GPIO chip selects that
aren't described in the controller's cs-gpios property.
This is useful on platforms where the ACPI _DSD cs-gpios property
on the SPI controller is incomplete, but the peripheral's ACPI node
does contain the correct GpioIo resource for its chip select.
Suggested-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Signed-off-by: Khalil <khalilst@gmail.com>
---
drivers/spi/spi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index a0b2bd3b8..64be99d13 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -734,7 +734,8 @@ static int __spi_add_device(struct spi_device *spi, struct spi_device *parent)
for (idx = 0; idx < spi->num_chipselect; idx++) {
cs = spi_get_chipselect(spi, idx);
- spi_set_csgpiod(spi, idx, ctlr->cs_gpiods[cs]);
+ if (!spi_get_csgpiod(spi, idx))
+ spi_set_csgpiod(spi, idx, ctlr->cs_gpiods[cs]);
}
}
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 2/3] platform/x86: serial-multi-instantiate: Fix SPI chip select on platforms with incomplete ACPI cs-gpios
2026-04-12 16:31 ` Khalil
2026-04-12 16:31 ` [PATCH 1/3] spi: Preserve preset cs_gpiod in __spi_add_device() Khalil
@ 2026-04-12 16:31 ` Khalil
2026-04-12 16:31 ` [PATCH 3/3] spi: pxa2xx: Handle clock gating for GPIO chip select devices Khalil
2 siblings, 0 replies; 15+ messages in thread
From: Khalil @ 2026-04-12 16:31 UTC (permalink / raw)
To: broonie, hdegoede, ilpo.jarvinen
Cc: rf, linux-spi, platform-driver-x86, linux-kernel, Khalil, Khalil
Some HP laptops with Intel Lunar Lake and dual Cirrus Logic CS35L56
amplifiers over SPI have an incomplete cs-gpios property in the SPI
controller's _DSD - it only declares the first chip select. The
remaining chip select GPIOs are defined as GpioIo resources in the
peripheral's ACPI node but are not referenced by the controller.
This causes the SPI framework to reject devices whose chip select
exceeds num_chipselect with -EINVAL, preventing the second amplifier
from probing.
Fix this on known affected platforms by:
1. Adding a DMI quirk table to identify affected systems
2. For devices with chip selects outside the controller's range,
acquiring the GPIO from the peripheral's ACPI GpioIo resource
3. Extending num_chipselect and reallocating the controller's
cs_gpiods array to install the GPIO descriptor
4. Setting SPI_CONTROLLER_GPIO_SS so the framework calls both
the GPIO toggle and controller->set_cs (needed for clock
gating on Intel LPSS controllers)
Only chip selects beyond the controller's num_chipselect are fixed up.
Chip selects within range with a NULL cs_gpiods entry are left alone,
as NULL means "native chip select" which is intentional.
Tested on HP EliteBook 8 G1i 16 inch (board 8D8A) with 2x CS35L56
Rev B0 amplifiers. Both amplifiers probe and produce audio.
Signed-off-by: Khalil <khalilst@gmail.com>
---
.../platform/x86/serial-multi-instantiate.c | 168 ++++++++++++++++++
1 file changed, 168 insertions(+)
diff --git a/drivers/platform/x86/serial-multi-instantiate.c b/drivers/platform/x86/serial-multi-instantiate.c
index 1a369334f..0d30bd0a7 100644
--- a/drivers/platform/x86/serial-multi-instantiate.c
+++ b/drivers/platform/x86/serial-multi-instantiate.c
@@ -8,6 +8,10 @@
#include <linux/acpi.h>
#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/dmi.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/machine.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
@@ -46,6 +50,53 @@ struct smi {
int spi_num;
struct i2c_client **i2c_devs;
struct spi_device **spi_devs;
+ struct gpio_desc *cs_gpio;
+};
+
+/*
+ * Quirk data for platforms with broken ACPI SPI chip select descriptions.
+ * cs_gpio_idx: index of the GpioIo resource in the ACPI _CRS that provides
+ * the chip select GPIO for devices missing a proper cs-gpios
+ * entry on the SPI controller.
+ */
+struct smi_cs_gpio_quirk {
+ int cs_gpio_idx;
+};
+
+static const struct smi_cs_gpio_quirk hp_elitebook_8g1i_quirk = {
+ .cs_gpio_idx = 0,
+};
+
+/*
+ * DMI table of platforms with broken SPI chip select ACPI descriptions.
+ *
+ * These systems have multiple SPI peripherals (e.g., dual CS35L56
+ * amplifiers) but the SPI controller's _DSD cs-gpios property is
+ * incomplete - it only declares the first chip select. The remaining
+ * chip select GPIOs are defined as GpioIo resources in the peripheral's
+ * ACPI node but are not referenced by the controller.
+ */
+static const struct dmi_system_id smi_cs_gpio_dmi_table[] = {
+ {
+ .ident = "HP EliteBook 8 G1i 16 inch",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_BOARD_NAME, "8D8A"),
+ },
+ .driver_data = (void *)&hp_elitebook_8g1i_quirk,
+ },
+ { }
+};
+
+/*
+ * ACPI GPIO mapping for the chip select GpioIo resource.
+ * Maps "cs-gpios" to the GpioIo resource at index 0 of the ACPI _CRS.
+ */
+static const struct acpi_gpio_params smi_cs_gpio_params = { 0, 0, false };
+
+static const struct acpi_gpio_mapping smi_cs_gpio_mapping[] = {
+ { "cs-gpios", &smi_cs_gpio_params, 1 },
+ { }
};
static int smi_get_irq(struct platform_device *pdev, struct acpi_device *adev,
@@ -99,6 +150,101 @@ static void smi_devs_unregister(struct smi *smi)
}
}
+/*
+ * smi_spi_setup_cs_gpio - Fix up chip select for a device on a platform
+ * with broken ACPI cs-gpios description.
+ *
+ * On affected platforms, the SPI controller's cs-gpios property is incomplete,
+ * so the framework has no GPIO descriptor for some chip selects. This causes
+ * __spi_add_device() to reject the device with -EINVAL (cs >= num_chipselect).
+ *
+ * This function:
+ * 1. Extends num_chipselect if the device's CS is out of range
+ * 2. Reallocates cs_gpiods to match, preventing out-of-bounds access
+ * in __spi_add_device()
+ * 3. Installs the GPIO from the peripheral's ACPI node into the
+ * controller's cs_gpiods array so __spi_add_device() propagates
+ * it to the device
+ * 4. Sets SPI_CONTROLLER_GPIO_SS so the framework calls both the GPIO
+ * toggle and controller->set_cs (needed for clock gating on Intel
+ * LPSS controllers)
+ */
+static int smi_spi_setup_cs_gpio(struct device *dev,
+ struct spi_device *spi_dev,
+ struct smi *smi,
+ const struct smi_cs_gpio_quirk *quirk)
+{
+ struct spi_controller *ctlr = spi_dev->controller;
+ struct gpio_desc **new_gpiods;
+ u16 cs = spi_get_chipselect(spi_dev, 0);
+
+ /*
+ * Only fix up chip selects that the controller doesn't know about.
+ * A NULL cs_gpiods[cs] within the controller's num_chipselect range
+ * means "native chip select" - that's intentional, not broken.
+ * The broken case is when cs >= num_chipselect, meaning the ACPI
+ * cs-gpios property on the controller was incomplete.
+ */
+ if (cs < ctlr->num_chipselect)
+ return 0;
+
+ /* Extend num_chipselect to cover this device */
+ dev_info(dev, "Extending num_chipselect from %u to %u for CS%u\n",
+ ctlr->num_chipselect, cs + 1, cs);
+ ctlr->num_chipselect = cs + 1;
+
+ /* Acquire the CS GPIO from the ACPI GpioIo resource if not yet done */
+ if (!smi->cs_gpio) {
+ int ret;
+
+ ret = devm_acpi_dev_add_driver_gpios(dev, smi_cs_gpio_mapping);
+ if (ret) {
+ dev_warn(dev, "Failed to add CS GPIO mapping: %d\n", ret);
+ return ret;
+ }
+
+ smi->cs_gpio = devm_gpiod_get(dev, "cs", GPIOD_OUT_HIGH);
+ if (IS_ERR(smi->cs_gpio)) {
+ dev_warn(dev, "Failed to get CS GPIO: %ld\n",
+ PTR_ERR(smi->cs_gpio));
+ smi->cs_gpio = NULL;
+ return -ENOENT;
+ }
+ dev_info(dev, "Acquired CS GPIO for CS%u from ACPI GpioIo[%d]\n",
+ cs, quirk->cs_gpio_idx);
+ }
+
+ /*
+ * Reallocate the controller's cs_gpiods array to accommodate the
+ * new num_chipselect, and install the GPIO descriptor. This is
+ * necessary because __spi_add_device() unconditionally reads
+ * ctlr->cs_gpiods[cs] to set the device's cs_gpiod.
+ */
+ new_gpiods = devm_kcalloc(&ctlr->dev, ctlr->num_chipselect,
+ sizeof(*new_gpiods), GFP_KERNEL);
+ if (!new_gpiods)
+ return -ENOMEM;
+
+ if (ctlr->cs_gpiods) {
+ unsigned int i;
+
+ for (i = 0; i < cs; i++)
+ new_gpiods[i] = ctlr->cs_gpiods[i];
+ }
+ new_gpiods[cs] = smi->cs_gpio;
+ ctlr->cs_gpiods = new_gpiods;
+
+ /*
+ * SPI_CONTROLLER_GPIO_SS ensures the framework calls both the
+ * GPIO CS toggle and controller->set_cs(). This is required on
+ * Intel LPSS controllers where set_cs handles clock gating.
+ */
+ ctlr->flags |= SPI_CONTROLLER_GPIO_SS;
+
+ dev_info(dev, "Installed GPIO CS on controller for CS%u\n", cs);
+ return 0;
+}
+
/**
* smi_spi_probe - Instantiate multiple SPI devices from inst array
* @pdev: Platform device
@@ -112,10 +258,19 @@ static int smi_spi_probe(struct platform_device *pdev, struct smi *smi,
{
struct device *dev = &pdev->dev;
struct acpi_device *adev = ACPI_COMPANION(dev);
+ const struct dmi_system_id *dmi_id;
+ const struct smi_cs_gpio_quirk *quirk = NULL;
struct spi_controller *ctlr;
struct spi_device *spi_dev;
char name[50];
int i, ret, count;
+ u16 cs;
+
+ dmi_id = dmi_first_match(smi_cs_gpio_dmi_table);
+ if (dmi_id) {
+ quirk = dmi_id->driver_data;
+ dev_info(dev, "Applying CS GPIO quirk for %s\n", dmi_id->ident);
+ }
ret = acpi_spi_count_resources(adev);
if (ret < 0)
@@ -139,6 +294,19 @@ static int smi_spi_probe(struct platform_device *pdev, struct smi *smi,
}
ctlr = spi_dev->controller;
+ cs = spi_get_chipselect(spi_dev, 0);
+
+ /*
+ * On quirked platforms, fix up the chip select GPIO for
+ * devices that would otherwise fail due to incomplete
+ * ACPI cs-gpios on the SPI controller.
+ */
+ if (quirk) {
+ ret = smi_spi_setup_cs_gpio(dev, spi_dev, smi, quirk);
+ if (ret)
+ dev_dbg(dev, "CS GPIO setup returned %d for CS%u\n",
+ ret, cs);
+ }
strscpy(spi_dev->modalias, inst_array[i].type);
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 3/3] spi: pxa2xx: Handle clock gating for GPIO chip select devices
2026-04-12 16:31 ` Khalil
2026-04-12 16:31 ` [PATCH 1/3] spi: Preserve preset cs_gpiod in __spi_add_device() Khalil
2026-04-12 16:31 ` [PATCH 2/3] platform/x86: serial-multi-instantiate: Fix SPI chip select on platforms with incomplete ACPI cs-gpios Khalil
@ 2026-04-12 16:31 ` Khalil
2 siblings, 0 replies; 15+ messages in thread
From: Khalil @ 2026-04-12 16:31 UTC (permalink / raw)
To: broonie, hdegoede, ilpo.jarvinen
Cc: rf, linux-spi, platform-driver-x86, linux-kernel, Khalil, Khalil
On Intel LPSS SPI controllers (Cannon Lake and later) with dynamic
clock gating (cs_clk_stays_gated=true), the SPI clock is gated when
no native chip select is asserted. When using a GPIO chip select
(via SPI_CONTROLLER_GPIO_SS), the SPI framework toggles the GPIO
and also calls the controller's set_cs callback.
Handle this in the pxa2xx cs_assert/cs_deassert functions: when the
device uses a GPIO chip select on an LPSS controller, assert native
CS in the control register to enable the clock, and force the clock
gate on. On deassert, restore both.
This is needed on platforms where serial-multi-instantiate installs
a GPIO chip select from the peripheral's ACPI GpioIo resource to
work around an incomplete cs-gpios property on the SPI controller.
Signed-off-by: Khalil <khalilst@gmail.com>
---
drivers/spi/spi-pxa2xx.c | 45 ++++++++++++++++++++++++++++++++++++----
1 file changed, 41 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 6291d7c2e..fe5762063 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -419,20 +419,43 @@ static void cs_assert(struct spi_device *spi)
{
struct driver_data *drv_data =
spi_controller_get_devdata(spi->controller);
+ const struct lpss_config *config;
if (drv_data->ssp_type == CE4100_SSP) {
pxa2xx_spi_write(drv_data, SSSR, spi_get_chipselect(spi, 0));
return;
}
- if (is_lpss_ssp(drv_data))
- lpss_ssp_cs_control(spi, true);
+ if (is_lpss_ssp(drv_data)) {
+ config = lpss_get_config(drv_data);
+
+ if (spi_is_csgpiod(spi)) {
+ /*
+ * GPIO handles the actual chip select to the device.
+ * On LPSS controllers with dynamic clock gating, the
+ * SPI clock won't run unless the native CS state says
+ * "asserted" in the CS control register. Assert native
+ * CS in the register to enable the clock, and force
+ * the clock gate on.
+ */
+ lpss_ssp_cs_control(spi, true);
+ if (config->cs_clk_stays_gated) {
+ __lpss_ssp_update_priv(drv_data,
+ LPSS_PRIV_CLOCK_GATE,
+ LPSS_PRIV_CLOCK_GATE_CLK_CTL_MASK,
+ LPSS_PRIV_CLOCK_GATE_CLK_CTL_FORCE_ON);
+ }
+ } else {
+ lpss_ssp_cs_control(spi, true);
+ }
+ }
}
static void cs_deassert(struct spi_device *spi)
{
struct driver_data *drv_data =
spi_controller_get_devdata(spi->controller);
+ const struct lpss_config *config;
unsigned long timeout;
if (drv_data->ssp_type == CE4100_SSP)
@@ -444,8 +467,22 @@ static void cs_deassert(struct spi_device *spi)
!time_after(jiffies, timeout))
cpu_relax();
- if (is_lpss_ssp(drv_data))
- lpss_ssp_cs_control(spi, false);
+ if (is_lpss_ssp(drv_data)) {
+ config = lpss_get_config(drv_data);
+
+ if (spi_is_csgpiod(spi)) {
+ /* Deassert native CS and restore clock gating */
+ lpss_ssp_cs_control(spi, false);
+ if (config->cs_clk_stays_gated) {
+ __lpss_ssp_update_priv(drv_data,
+ LPSS_PRIV_CLOCK_GATE,
+ LPSS_PRIV_CLOCK_GATE_CLK_CTL_MASK,
+ LPSS_PRIV_CLOCK_GATE_CLK_CTL_FORCE_OFF);
+ }
+ } else {
+ lpss_ssp_cs_control(spi, false);
+ }
+ }
}
static void pxa2xx_spi_set_cs(struct spi_device *spi, bool level)
--
2.43.0
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 0/3] Fix CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios
2026-04-11 21:57 ` [PATCH v2 0/3] Fix CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios Mark Brown
@ 2026-04-13 8:48 ` Richard Fitzgerald
2026-04-13 9:02 ` Richard Fitzgerald
0 siblings, 1 reply; 15+ messages in thread
From: Richard Fitzgerald @ 2026-04-13 8:48 UTC (permalink / raw)
To: Khalil, Mark Brown
Cc: hdegoede, ilpo.jarvinen, linux-spi, platform-driver-x86, linux-kernel
On 11/04/2026 10:57 pm, Mark Brown wrote:
> On Sat, Apr 11, 2026 at 08:04:11PM +0200, Khalil wrote:
>
>> This is v2 of the patch series fixing dual CS35L56 amplifiers on HP
>> laptops with Intel Lunar Lake and broken ACPI cs-gpios.
>
> I can't work out what these apply against, please submit against my
> current tree.
Also please put V2 (or whatever version) on all patches in the series,
not just the cover letter.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH v2 0/3] Fix CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios
2026-04-13 8:48 ` Richard Fitzgerald
@ 2026-04-13 9:02 ` Richard Fitzgerald
0 siblings, 0 replies; 15+ messages in thread
From: Richard Fitzgerald @ 2026-04-13 9:02 UTC (permalink / raw)
To: Khalil, Mark Brown
Cc: hdegoede, ilpo.jarvinen, linux-spi, platform-driver-x86, linux-kernel
On 13/04/2026 9:48 am, Richard Fitzgerald wrote:
> On 11/04/2026 10:57 pm, Mark Brown wrote:
>> On Sat, Apr 11, 2026 at 08:04:11PM +0200, Khalil wrote:
>>
>>> This is v2 of the patch series fixing dual CS35L56 amplifiers on HP
>>> laptops with Intel Lunar Lake and broken ACPI cs-gpios.
>>
>> I can't work out what these apply against, please submit against my
>> current tree.
>
> Also please put V2 (or whatever version) on all patches in the series,
> not just the cover letter.
... and use ./scripts/get_maintainer.pl to get the emails of the
maintainers and reviewers.
The email for Hans de Goede is <hansg@kernel.org>
Can you also cc patches@opensource.cirrus.com. Thanks.
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-04-13 9:02 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-02-15 13:55 [RFC PATCH 0/2] Fix second CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios Khalil
2026-02-15 13:55 ` [RFC PATCH 1/2] platform/x86: serial-multi-instantiate: Add GPIO chip select support for SPI devices Khalil
2026-02-23 15:50 ` Richard Fitzgerald
2026-04-11 18:04 ` [PATCH v2 0/3] Fix CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios Khalil
2026-04-11 18:04 ` [PATCH 1/3] spi: Preserve preset cs_gpiod in __spi_add_device() Khalil
2026-04-11 18:04 ` [PATCH 2/3] platform/x86: serial-multi-instantiate: Fix SPI chip select on platforms with incomplete ACPI cs-gpios Khalil
2026-04-11 18:04 ` [PATCH 3/3] spi: pxa2xx: Handle clock gating for GPIO chip select devices Khalil
2026-04-11 21:57 ` [PATCH v2 0/3] Fix CS35L56 amplifier on Intel LPSS SPI with broken ACPI cs-gpios Mark Brown
2026-04-13 8:48 ` Richard Fitzgerald
2026-04-13 9:02 ` Richard Fitzgerald
2026-04-12 16:31 ` Khalil
2026-04-12 16:31 ` [PATCH 1/3] spi: Preserve preset cs_gpiod in __spi_add_device() Khalil
2026-04-12 16:31 ` [PATCH 2/3] platform/x86: serial-multi-instantiate: Fix SPI chip select on platforms with incomplete ACPI cs-gpios Khalil
2026-04-12 16:31 ` [PATCH 3/3] spi: pxa2xx: Handle clock gating for GPIO chip select devices Khalil
2026-02-15 13:55 ` [RFC PATCH 2/2] spi: pxa2xx: Handle dynamic " Khalil
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®