Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexVinarskis/77d55a0a0f4150576ba77e5f4241d512 to your computer and use it in GitHub Desktop.
Save alexVinarskis/77d55a0a0f4150576ba77e5f4241d512 to your computer and use it in GitHub Desktop.
Dell XPS 9530 Sound

Intro

Dell XPS 9530 (15", 2023 model) comes with 4 speakers: two up firing tweeters, and two down firing woofers. Upper speakers are connected directly to audio codec, while bottom ones are powered by Cirrus CS35L41 smart amplifiers.

On Linux, only two upper speakers worked, enabling bottom ones requires extra steps. Since most of volume comes from bottom speakers, without them speakers are essentially worthless.

Reason for lack of support out of the box was as following:

  • Cirrus amp requires correct parameter to operate, which typicall shall be part of BIOS's ACPI tables in the form of _DSD (Device specific data). For particalar model these were missing. A patch is required to add them to directly in Cirrus's kernel driver.
  • Cirrus amp requires firmware and tuning files to operate. These are not part of Linux kernel, and shall be loaded from userspace. These can be (unoficially) extracted from Windows Realtek audio driver, or (officially) added to linux-firmware repository by Cirrus developers.
  • Particularly XPS 9530 experiences a BIOS firmware bug, which misconfigures Intel Lpss subsystem to use incorrect clock rates. This results in hugely capped SPI speed (3051Hz, instead of required 4Mhz), which makes firmware loading (which takes place on boot and on wake up from suspend) to take just over 3 minutes. During this 3 minutes anything sound related is not really operational. Morevover, during wake up from suspend, device will not resume operation but will be stuck with black screen for the said duration. A patch to Intel Lpss driver is required to conditionally disable incorrecrtly configured clock divider for particular model, since its unlikely that Dell will ever fix it in their firmware.

Latest status

There are a number of independent fixes required to make speakers work. Details can be found in Guide section, here is latest status of each one:

  • Amplifier's Firmware and Tunings were merged to linux-firmware upstream, available from tag 20240115 onwards. For Arch users it is already in aur repositories. For Ubuntu users, it is not yet, but can be downloaded as debian package from here.
  • Quirk to enable woofers and Cirrus amp loading was merged to sound subsystem and to kernel upstream, available from tag 6.7 onwards.
  • Missing _DSD properties fix and safety guard against too slow SPI speed were merged (1, 2) to sound subsystem and to kernel upstream, available from tag 6.8 onwards. Was later backported to 6.7.1.
  • Intel Lpss patch was merged (1, 2) to kernel upstream. Landing with 6.9 release.

Projection: Sounds will be fully operation out-of-the-box from kernel 6.9 onwards. Backport to 6.8.y (link) and 6.7.y (link) were submitted, but not reviewed/accepted yet.

Optional, but highly recommended equilizer changes are (and always will be required) to be added manually. See Post Installation for more for more info.

Useful links

How-to Guides

Shortcut for Ubuntu/Debian users

I have compiled 6.7 kernel with backported Intel Lpss patch. Installing this kernel (provided that you have correct version of linux-firmware installed) will automatically fix your sound. Please note its highly recommended to compile your own kernel, both for compatibility and security reasons. If you still decide to use ready solution instead, install all of these packages with sudo dpkg -i packageNameHere.deb anotherPackageHere.deb....:

Reboot, make sure you are running kernel version 6.7.0-xps9530-sound. Equalizer guide (see below) still applies, as it will never be included in the kernel.

Generic patching guide

In order to apply patches:

  1. Download kernel from source, Git or tarball.
  2. Copy your current .config for simplicity.
  3. Make sure you can build the kernel as is.
  4. Apply required patches. This can be done by running git apply path_to_file/name_of_file.patch inside of kernel root folder.
  5. Rebuild the kernel with patches applied.
  6. Install the kernel. Make sure to update boot prefernce (In case of ubuntu this is done in Grub). Make sure to boot from newly modified kernel.

A lot/most of steps described here were automated with scripts to automatically download/patch/build/install modified kernel. These are conditioned on distro and kernel version being used, thus will not be added here. They can be found in Discord/Github discussion threads.

Guide for stable kernel 6.7.1/6.7.2/6.7.3

  1. Add amplifier firmware and tuning files either manually (see below) or by getting linux-firmware package version 20240115 or newer.
  2. Apply Intel Lpss patch to unblock capped SPI speed. Patch was submitted here, however, due to selective backporting of patches to stable, will not apply cleanly. A pseudo-backport of the patch is attached in this gist as mfd-intel-lpss-v4-backport.patch.

Rest of patches were merged to stable.

Guide for kernel 6.8

  1. Add amplifier firmware and tuning files either manually (see below) or by getting linux-firmware package version 20240115 or newer.
  2. Apply Intel Lpss patch to unblock capped SPI speed. Patch was submitted here, or attached in this gist as mfd-intel-lpss-v4.patch.

Rest of patches were merged to mainline.

Guide for kernel 6.7

For those patching kernel source of version 6.7:

  1. Add amplifier firmware and tuning files either manually (see below) or by getting linux-firmware package version 20240115 or newer.
  2. Cirrus has alterened framework for adding missing _DSD, which makes it significantly easier. However, commit adding _DSD for 9530 was not merged until early 6.8. You should apply these (1, 2) patches manually, or cherry-pick them.
  3. Apply Intel Lpss patch to unblock capped SPI speed. Patch was submitted here, or attached in this gist as mfd-intel-lpss-v4.patch.

Guide for kernel <= 6.6

Before 6.7, Cirrus used slightly different framework for adding missing _DSD, so different patch is required.

  1. Add amplifier firmware and tuning files. Cirrus developers have added these to linux-firmware in this commit. If you do not get this update yet, you can manually add these files to respective folders in /lib/firmware/cirrus.... Only files with ..10280beb.. in the name are required for XPS 9530.2
  2. Apply older patch adding the same missing _DSD, just in different format. Patch was submitted here, or attached in this gist as ALSA-hda-cs35l41-Dell-Fiorano-add-missing-_DSD-CS.patch.
  3. Apply patch to enable audio output to woofers, and Cirrus SPI modules loading. Patch was submitted here, or attached in this gist as ALSA-hda-realtek-fix-speakers-on-XPS-9530-2023.patch.
  4. Apply Intel Lpss patch to unblock capped SPI speed. Patch was submitted here, or attached in this gist as mfd-intel-lpss-v4.patch. It may not apply cleanly, as some intermediate changes were merged. In that case, add changes manually, its pretty straight forward.

Debugging

Most of development work and debugging takes/took place on Discord server, and some of it on the github issue thread, both links added above. Please do not use this this gist for debugging discussions, it is here to serve as a top level summary. All the questions can be asked on Discord server. These changes was tested on multiple XPS 9530 devices, on kernels 6.6...6.8, for months, and is known to work.

Post Installation

Above changes, once merged to mainline kernel will enable subwoofers audio output on Dell XPS 9530 out of the box. With default tuning files from Cirrus, sound is incredebely loud, however quality is far from awesome compared to Windows: there is additional cracking, vibrations due to resonance etc.

Thus, its highly recommended to apply equlizer tunning: @DanShaders has made a tuning table for Pipewire based on band-wise comparison between Windows and Linux playback. Adding proposed changes makes sound extremely close to (in my opinion, the same as) sound on Windows. Max volume is slightly lower than without this change, however sound clarity and surround effect is much higher, most of cracking and vibration is gone, just like on Windows.

To do so, add contents of this file to ~/.config/pipewire/pipewire.conf.d/sink-eq6.conf, and run systemctl --user restart pipewire && wpctl set-default internal_speaker once.

More details in original comment.

Credits

  • Everyone participating in development and debugging of these patches both on Github issue thread and Discord server.
  • Andy Shevchenko for his help with Intel Lpss patch.
  • @DanShaders for equalizer tuning.
From c814d07190a645dcce33e4407c6f6d8bb7ebaef2 Mon Sep 17 00:00:00 2001
From: Aleksandrs Vinarskis <alex.vinarskis@gmail.com>
Date: Tue, 12 Dec 2023 20:52:43 +0100
Subject: [PATCH 1/1] ALSA: hda: cs35l41: Dell Fiorano add missing _DSD properties
Dell XPS 9530 (2023) has two SPI connected CS35L41 amplifiers, however
is missing _DSD properties, cs-gpios and has a firmware bug which caps SPI
controller's speed to unusable 3051Hz. This patch adds _DSD properties and
sets second cs-gpio. In case SPI speed bug is detected, it will not
initialize the device to avoid hangs on wake up.
Resolution of SPI speed bug requires either a patch to `intel-lpss.c` or an
UEFI update with corrected values from Dell. Tested with locally applied
patch to `intel-lpss` on multiple XPS 9530 devices.
Co-developed-by: Jasper Smet <josbeir@gmail.com>
Signed-off-by: Jasper Smet <josbeir@gmail.com>
Signed-off-by: Aleksandrs Vinarskis <alex.vinarskis@gmail.com>
---
sound/pci/hda/cs35l41_hda_property.c | 47 ++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c
index c83328971728..69446a794397 100644
--- a/sound/pci/hda/cs35l41_hda_property.c
+++ b/sound/pci/hda/cs35l41_hda_property.c
@@ -7,9 +7,55 @@
// Author: Stefan Binding <sbinding@opensource.cirrus.com>
#include <linux/gpio/consumer.h>
+#include <linux/spi/spi.h>
#include <linux/string.h>
#include "cs35l41_hda_property.h"
+/*
+ * Device 10280BEB (Dell XPS 9530) doesn't have _DSD at all. Moreover, pin that is typically
+ * used for `speaker_id` is missing. SPI's cs-gpios definitions are also missing.
+ */
+static int dell_fiorano_no_acpi(struct cs35l41_hda *cs35l41, struct device *physdev, int id,
+ const char *hid)
+{
+ struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
+ struct spi_device *spi = to_spi_device(cs35l41->dev);
+
+ /*
+ * 10280BEB has a firmware bug, which wrongly enables clock divider for intel-lpss
+ * Resultant SPI clock is 100Mhz/32767=3051Hz, which leads to ~3 minute hang on boot/wake up
+ * Avoid initializing device if lpss was not patched/fixed UEFI was not installed
+ */
+ if (spi->max_speed_hz < CS35L41_SPI_MAX_FREQ) {
+ dev_err(cs35l41->dev, "SPI's max_speed_hz is capped at %u Hz, will not continue to avoid hanging\n",
+ spi->max_speed_hz);
+ return -EINVAL;
+ }
+
+ dev_info(cs35l41->dev, "Adding DSD properties for %s\n", cs35l41->acpi_subsystem_id);
+
+ /* check SPI address to assign the index */
+ cs35l41->index = id;
+ cs35l41->channel_index = 0;
+ /* 10280BEB is missing pin which is typically assigned to `spk-id-gpios` */
+ cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, cs35l41->index, 2, -1);
+ cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, 1, GPIOD_OUT_LOW);
+
+ hw_cfg->spk_pos = cs35l41->index ? 1 : 0; // 0th L, 1st R
+ hw_cfg->bst_type = CS35L41_EXT_BOOST;
+ hw_cfg->gpio1.func = CS35l41_VSPK_SWITCH;
+ hw_cfg->gpio1.valid = true;
+ hw_cfg->gpio2.func = CS35L41_INTERRUPT;
+ hw_cfg->gpio2.valid = true;
+ hw_cfg->valid = true;
+
+ /* Add second cs-gpio here */
+ if (cs35l41->index)
+ spi->cs_gpiod = gpiod_get_index(physdev, NULL, 0, GPIOD_OUT_HIGH);
+
+ return 0;
+}
+
/*
* Device CLSA010(0/1) doesn't have _DSD so a gpiod_get by the label reset won't work.
* And devices created by serial-multi-instantiate don't have their device struct
@@ -92,6 +138,7 @@ static const struct cs35l41_prop_model cs35l41_prop_model_table[] = {
{ "CLSA0100", NULL, lenovo_legion_no_acpi },
{ "CLSA0101", NULL, lenovo_legion_no_acpi },
{ "CSC3551", "103C89C6", hp_vision_acpi_fix },
+ { "CSC3551", "10280BEB", dell_fiorano_no_acpi },
{}
};
--
2.40.1
From da308cd4fc2fb8b140a235be6063d4725b93d6f9 Mon Sep 17 00:00:00 2001
From: Alex Vinarskis <alex.vinarskis@gmail.com>
Date: Sat, 2 Dec 2023 12:08:39 +0100
Subject: [PATCH] ALSA: hda/realtek: fix speakers on XPS 9530 (2023)
---
sound/pci/hda/patch_realtek.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 5618b1d9bfd1..9413dd03f2bc 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -9684,6 +9684,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x0b1a, "Dell Precision 5570", ALC289_FIXUP_DUAL_SPK),
SND_PCI_QUIRK(0x1028, 0x0b37, "Dell Inspiron 16 Plus 7620 2-in-1", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
SND_PCI_QUIRK(0x1028, 0x0b71, "Dell Inspiron 16 Plus 7620", ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS),
+ SND_PCI_QUIRK(0x1028, 0x0beb, "Dell XPS 15 9530 (2023)", ALC289_FIXUP_DELL_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1028, 0x0c03, "Dell Precision 5340", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0c19, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS),
SND_PCI_QUIRK(0x1028, 0x0c1a, "Dell Precision 3340", ALC236_FIXUP_DELL_DUAL_CODECS),
--
2.40.1
From a4793acbbcf1404fcb20e0f8896d3da8a078b17a Mon Sep 17 00:00:00 2001
From: Aleksandrs Vinarskis <alex.vinarskis@gmail.com>
Date: Fri, 26 Jan 2024 21:19:46 +0100
Subject: [PATCH 1/1] backport: intel-lpss patch v4
---
drivers/mfd/intel-lpss-pci.c | 30 +++++++++++++++++++++---------
drivers/mfd/intel-lpss.c | 9 ++++++++-
drivers/mfd/intel-lpss.h | 14 +++++++++++++-
3 files changed, 42 insertions(+), 11 deletions(-)
diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c
index ae5759200622..3870d96fe7c7 100644
--- a/drivers/mfd/intel-lpss-pci.c
+++ b/drivers/mfd/intel-lpss-pci.c
@@ -18,19 +18,30 @@
#include "intel-lpss.h"
-/* Some DSDTs have an unused GEXP ACPI device conflicting with I2C4 resources */
-static const struct pci_device_id ignore_resource_conflicts_ids[] = {
- /* Microsoft Surface Go (version 1) I2C4 */
- { PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, 0x9d64, 0x152d, 0x1182), },
- /* Microsoft Surface Go 2 I2C4 */
- { PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, 0x9d64, 0x152d, 0x1237), },
+static const struct pci_device_id quirk_ids[] = {
+ {
+ /* Microsoft Surface Go (version 1) I2C4 */
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, 0x9d64, 0x152d, 0x1182),
+ .driver_data = QUIRK_IGNORE_RESOURCE_CONFLICTS,
+ },
+ {
+ /* Microsoft Surface Go 2 I2C4 */
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, 0x9d64, 0x152d, 0x1237),
+ .driver_data = QUIRK_IGNORE_RESOURCE_CONFLICTS,
+ },
+ {
+ /* Dell XPS 9530 (2023) */
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, 0x51fb, 0x1028, 0x0beb),
+ .driver_data = QUIRK_CLOCK_DIVIDER_UNITY,
+ },
{ }
-};
+ };
static int intel_lpss_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
struct intel_lpss_platform_info *info;
+ const struct pci_device_id *quirk_pci_info;
int ret;
ret = pcim_enable_device(pdev);
@@ -45,8 +56,9 @@ static int intel_lpss_pci_probe(struct pci_dev *pdev,
info->mem = &pdev->resource[0];
info->irq = pdev->irq;
- if (pci_match_id(ignore_resource_conflicts_ids, pdev))
- info->ignore_resource_conflicts = true;
+ quirk_pci_info = pci_match_id(quirk_ids, pdev);
+ if (quirk_pci_info)
+ info->quirks = quirk_pci_info->driver_data;
pdev->d3cold_delay = 0;
diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c
index 9591b354072a..1e5fa60e5068 100644
--- a/drivers/mfd/intel-lpss.c
+++ b/drivers/mfd/intel-lpss.c
@@ -292,6 +292,7 @@ static int intel_lpss_register_clock_divider(struct intel_lpss *lpss,
{
char name[32];
struct clk *tmp = *clk;
+ int ret;
snprintf(name, sizeof(name), "%s-enable", devname);
tmp = clk_register_gate(NULL, name, __clk_get_name(tmp), 0,
@@ -308,6 +309,12 @@ static int intel_lpss_register_clock_divider(struct intel_lpss *lpss,
return PTR_ERR(tmp);
*clk = tmp;
+ if (lpss->info->quirks & QUIRK_CLOCK_DIVIDER_UNITY) {
+ ret = clk_set_rate(tmp, lpss->info->clk_rate);
+ if (ret)
+ return ret;
+ }
+
snprintf(name, sizeof(name), "%s-update", devname);
tmp = clk_register_gate(NULL, name, __clk_get_name(tmp),
CLK_SET_RATE_PARENT, lpss->priv, 31, 0, NULL);
@@ -401,7 +408,7 @@ int intel_lpss_probe(struct device *dev,
return ret;
lpss->cell->swnode = info->swnode;
- lpss->cell->ignore_resource_conflicts = info->ignore_resource_conflicts;
+ lpss->cell->ignore_resource_conflicts = info->quirks & QUIRK_IGNORE_RESOURCE_CONFLICTS;
intel_lpss_init_dev(lpss);
diff --git a/drivers/mfd/intel-lpss.h b/drivers/mfd/intel-lpss.h
index 062ce95b68b9..831f5f5bb356 100644
--- a/drivers/mfd/intel-lpss.h
+++ b/drivers/mfd/intel-lpss.h
@@ -11,16 +11,28 @@
#ifndef __MFD_INTEL_LPSS_H
#define __MFD_INTEL_LPSS_H
+#include <linux/bits.h>
#include <linux/pm.h>
+/*
+ * Some DSDTs have an unused GEXP ACPI device conflicting with I2C4 resources.
+ * Set to ignore resource conflicts with ACPI declared SystemMemory regions.
+ */
+#define QUIRK_IGNORE_RESOURCE_CONFLICTS BIT(0)
+/*
+ * Some devices have misconfigured clock divider due to a firmware bug.
+ * Set this to force the clock divider to 1:1 ratio.
+ */
+#define QUIRK_CLOCK_DIVIDER_UNITY BIT(1)
+
struct device;
struct resource;
struct software_node;
struct intel_lpss_platform_info {
struct resource *mem;
- bool ignore_resource_conflicts;
int irq;
+ unsigned int quirks;
unsigned long clk_rate;
const char *clk_con_id;
const struct software_node *swnode;
--
2.40.1
From 0e38c939950234e0ddb5b560fbb86ea6d8aaef71 Mon Sep 17 00:00:00 2001
From: Aleksandrs Vinarskis <alex.vinarskis@gmail.com>
Date: Tue, 19 Dec 2023 11:50:25 +0100
Subject: [PATCH 1/2] mfd: intel-lpss: Switch to generalized quirk table
Introduce generic quirk table, and port existing walkaround for select
Microsoft devices to it. This is a preparation for
QUIRK_CLOCK_DIVIDER_UNITY.
Signed-off-by: Aleksandrs Vinarskis <alex.vinarskis@gmail.com>
---
drivers/mfd/intel-lpss-pci.c | 23 +++++++++++++++--------
drivers/mfd/intel-lpss.c | 2 +-
drivers/mfd/intel-lpss.h | 9 ++++++++-
3 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c
index 4621d3950b8f..07713a2f694f 100644
--- a/drivers/mfd/intel-lpss-pci.c
+++ b/drivers/mfd/intel-lpss-pci.c
@@ -23,12 +23,17 @@
#include "intel-lpss.h"
-/* Some DSDTs have an unused GEXP ACPI device conflicting with I2C4 resources */
-static const struct pci_device_id ignore_resource_conflicts_ids[] = {
- /* Microsoft Surface Go (version 1) I2C4 */
- { PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, 0x9d64, 0x152d, 0x1182), },
- /* Microsoft Surface Go 2 I2C4 */
- { PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, 0x9d64, 0x152d, 0x1237), },
+static const struct pci_device_id quirk_ids[] = {
+ {
+ /* Microsoft Surface Go (version 1) I2C4 */
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, 0x9d64, 0x152d, 0x1182),
+ .driver_data = QUIRK_IGNORE_RESOURCE_CONFLICTS,
+ },
+ {
+ /* Microsoft Surface Go 2 I2C4 */
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, 0x9d64, 0x152d, 0x1237),
+ .driver_data = QUIRK_IGNORE_RESOURCE_CONFLICTS,
+ },
{ }
};
@@ -36,6 +41,7 @@ static int intel_lpss_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
const struct intel_lpss_platform_info *data = (void *)id->driver_data;
+ const struct pci_device_id *quirk_pci_info;
struct intel_lpss_platform_info *info;
int ret;
@@ -55,8 +61,9 @@ static int intel_lpss_pci_probe(struct pci_dev *pdev,
info->mem = pci_resource_n(pdev, 0);
info->irq = pci_irq_vector(pdev, 0);
- if (pci_match_id(ignore_resource_conflicts_ids, pdev))
- info->ignore_resource_conflicts = true;
+ quirk_pci_info = pci_match_id(quirk_ids, pdev);
+ if (quirk_pci_info)
+ info->quirks = quirk_pci_info->driver_data;
pdev->d3cold_delay = 0;
diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c
index eff423f7dd28..aafa0da5f8db 100644
--- a/drivers/mfd/intel-lpss.c
+++ b/drivers/mfd/intel-lpss.c
@@ -412,7 +412,7 @@ int intel_lpss_probe(struct device *dev,
return ret;
lpss->cell->swnode = info->swnode;
- lpss->cell->ignore_resource_conflicts = info->ignore_resource_conflicts;
+ lpss->cell->ignore_resource_conflicts = info->quirks & QUIRK_IGNORE_RESOURCE_CONFLICTS;
intel_lpss_init_dev(lpss);
diff --git a/drivers/mfd/intel-lpss.h b/drivers/mfd/intel-lpss.h
index c1d72b117ed5..2fa9ef916258 100644
--- a/drivers/mfd/intel-lpss.h
+++ b/drivers/mfd/intel-lpss.h
@@ -11,16 +11,23 @@
#ifndef __MFD_INTEL_LPSS_H
#define __MFD_INTEL_LPSS_H
+#include <linux/bits.h>
#include <linux/pm.h>
+/*
+ * Some DSDTs have an unused GEXP ACPI device conflicting with I2C4 resources.
+ * Set to ignore resource conflicts with ACPI declared SystemMemory regions.
+ */
+#define QUIRK_IGNORE_RESOURCE_CONFLICTS BIT(0)
+
struct device;
struct resource;
struct software_node;
struct intel_lpss_platform_info {
struct resource *mem;
- bool ignore_resource_conflicts;
int irq;
+ unsigned int quirks;
unsigned long clk_rate;
const char *clk_con_id;
const struct software_node *swnode;
--
2.40.1
From 25bfaaaf8dbfd53fe3f9c03eb4fbfa45c04d01d3 Mon Sep 17 00:00:00 2001
From: Aleksandrs Vinarskis <alex.vinarskis@gmail.com>
Date: Tue, 19 Dec 2023 12:11:36 +0100
Subject: [PATCH 2/2] mfd: intel-lpss: Introduce QUIRK_CLOCK_DIVIDER_UNITY for
XPS 9530
Some devices (eg. Dell XPS 9530, 2023) due to a firmware bug have a
misconfigured clock divider, which should've been 1:1. This introduces
quirk which conditionally re-configures the clock divider to 1:1.
Signed-off-by: Aleksandrs Vinarskis <alex.vinarskis@gmail.com>
---
drivers/mfd/intel-lpss-pci.c | 5 +++++
drivers/mfd/intel-lpss.c | 7 +++++++
drivers/mfd/intel-lpss.h | 5 +++++
3 files changed, 17 insertions(+)
diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c
index 07713a2f694f..8c00e0c695c5 100644
--- a/drivers/mfd/intel-lpss-pci.c
+++ b/drivers/mfd/intel-lpss-pci.c
@@ -34,6 +34,11 @@ static const struct pci_device_id quirk_ids[] = {
PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, 0x9d64, 0x152d, 0x1237),
.driver_data = QUIRK_IGNORE_RESOURCE_CONFLICTS,
},
+ {
+ /* Dell XPS 9530 (2023) */
+ PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, 0x51fb, 0x1028, 0x0beb),
+ .driver_data = QUIRK_CLOCK_DIVIDER_UNITY,
+ },
{ }
};
diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c
index aafa0da5f8db..2a9018112dfc 100644
--- a/drivers/mfd/intel-lpss.c
+++ b/drivers/mfd/intel-lpss.c
@@ -300,6 +300,7 @@ static int intel_lpss_register_clock_divider(struct intel_lpss *lpss,
{
char name[32];
struct clk *tmp = *clk;
+ int ret;
snprintf(name, sizeof(name), "%s-enable", devname);
tmp = clk_register_gate(NULL, name, __clk_get_name(tmp), 0,
@@ -316,6 +317,12 @@ static int intel_lpss_register_clock_divider(struct intel_lpss *lpss,
return PTR_ERR(tmp);
*clk = tmp;
+ if (lpss->info->quirks & QUIRK_CLOCK_DIVIDER_UNITY) {
+ ret = clk_set_rate(tmp, lpss->info->clk_rate);
+ if (ret)
+ return ret;
+ }
+
snprintf(name, sizeof(name), "%s-update", devname);
tmp = clk_register_gate(NULL, name, __clk_get_name(tmp),
CLK_SET_RATE_PARENT, lpss->priv, 31, 0, NULL);
diff --git a/drivers/mfd/intel-lpss.h b/drivers/mfd/intel-lpss.h
index 2fa9ef916258..6f8f668f4c6f 100644
--- a/drivers/mfd/intel-lpss.h
+++ b/drivers/mfd/intel-lpss.h
@@ -19,6 +19,11 @@
* Set to ignore resource conflicts with ACPI declared SystemMemory regions.
*/
#define QUIRK_IGNORE_RESOURCE_CONFLICTS BIT(0)
+/*
+ * Some devices have misconfigured clock divider due to a firmware bug.
+ * Set this to force the clock divider to 1:1 ratio.
+ */
+#define QUIRK_CLOCK_DIVIDER_UNITY BIT(1)
struct device;
struct resource;
--
2.40.1
@lifeisafractal
Copy link

lifeisafractal commented Mar 13, 2024

Thanks to you and everyone that got these patches together. Dell's response in their forums was so disappointing, but the open source community's perseverance is amazing. Just wanted to say thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment