391 lines
14 KiB
Diff
391 lines
14 KiB
Diff
From 76556b655f7b50afe5c58006f44221900e5711a9 Mon Sep 17 00:00:00 2001
|
|
From: "Luke D. Jones" <luke@ljones.dev>
|
|
Date: Wed, 23 Aug 2023 11:05:59 +1200
|
|
Subject: [PATCH v2] ALSA: hda: cs35l41: Support ASUS 2023 laptops with missing
|
|
DSD
|
|
|
|
Support adding the missing DSD properties required for ASUS ROG 2023
|
|
laptops and other ASUS laptops to properly utilise the cs35l41.
|
|
|
|
The currently added laptops are:
|
|
- ASUS GS650P, i2c
|
|
- ASUS GA402X, i2c
|
|
- ASUS GU604V, spi
|
|
- ASUS GU603V, spi
|
|
- ASUS GV601V, spi
|
|
- ASUS GZ301V, spi
|
|
- ASUS ROG ALLY, i2c
|
|
- ASUS G614J, spi
|
|
- ASUS G634J, spi
|
|
- ASUS G614JI, spi
|
|
- ASUS G713P, i2c
|
|
- ASUS H7604JV, spi
|
|
|
|
The SPI connected amps may be required to use an external DSD patch
|
|
to fix or add the "cs-gpios" property.
|
|
|
|
Co-developed-by: Jonathan LoBue <jlobue10@gmail.com>
|
|
Signed-off-by: Jonathan LoBue <jlobue10@gmail.com>
|
|
Co-developed-by: Luke D. Jones <luke@ljones.dev>
|
|
Signed-off-by: Luke D. Jones <luke@ljones.dev>
|
|
---
|
|
sound/pci/hda/cs35l41_hda_property.c | 57 ++++++++++++++++++++++++++++
|
|
1 file changed, 57 insertions(+)
|
|
|
|
diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c
|
|
index c83328971728..de0802859849 100644
|
|
--- a/sound/pci/hda/cs35l41_hda_property.c
|
|
+++ b/sound/pci/hda/cs35l41_hda_property.c
|
|
@@ -76,6 +76,49 @@ static int hp_vision_acpi_fix(struct cs35l41_hda *cs35l41, struct device *physde
|
|
hw_cfg->bst_ind = 1000;
|
|
hw_cfg->bst_ipk = 4500;
|
|
hw_cfg->bst_cap = 24;
|
|
+
|
|
+ hw_cfg->valid = true;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * The CSC3551 is used in almost the entire ROG laptop range in 2023, this is likely to
|
|
+ * also include many non ROG labelled laptops. It is also used with either I2C connection or
|
|
+ * SPI connection. The SPI connected versions may be missing a chip select GPIO and require
|
|
+ * an DSD table patch.
|
|
+ */
|
|
+static int asus_rog_2023_no_acpi(struct cs35l41_hda *cs35l41, struct device *physdev, int id,
|
|
+ const char *hid)
|
|
+{
|
|
+ struct cs35l41_hw_cfg *hw_cfg = &cs35l41->hw_cfg;
|
|
+ int reset_gpio = 0;
|
|
+ int spkr_gpio = 2;
|
|
+
|
|
+ /* check SPI or I2C address to assign the index */
|
|
+ cs35l41->index = (id == 0 || id == 0x40) ? 0 : 1;
|
|
+ cs35l41->channel_index = 0;
|
|
+ hw_cfg->spk_pos = cs35l41->index;
|
|
+ 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;
|
|
+
|
|
+ if (strcmp(cs35l41->acpi_subsystem_id, "10431483") == 0)
|
|
+ spkr_gpio = 1;
|
|
+ cs35l41->speaker_id = cs35l41_get_speaker_id(physdev, 0, 0, spkr_gpio);
|
|
+
|
|
+ if (strcmp(cs35l41->acpi_subsystem_id, "10431473") == 0
|
|
+ || strcmp(cs35l41->acpi_subsystem_id, "10431483") == 0
|
|
+ || strcmp(cs35l41->acpi_subsystem_id, "10431493") == 0
|
|
+ || strcmp(cs35l41->acpi_subsystem_id, "10431CAF") == 0
|
|
+ || strcmp(cs35l41->acpi_subsystem_id, "10431CCF") == 0
|
|
+ || strcmp(cs35l41->acpi_subsystem_id, "10431E02") == 0) {
|
|
+ reset_gpio = 1;
|
|
+ }
|
|
+ cs35l41->reset_gpio = gpiod_get_index(physdev, NULL, reset_gpio, GPIOD_OUT_HIGH);
|
|
+
|
|
hw_cfg->valid = true;
|
|
|
|
return 0;
|
|
@@ -92,6 +135,20 @@ 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", "10431433", asus_rog_2023_no_acpi }, // GS650P i2c
|
|
+ { "CSC3551", "10431463", asus_rog_2023_no_acpi }, // GA402X/N i2c, rst=0
|
|
+ { "CSC3551", "10431473", asus_rog_2023_no_acpi }, // GU604V spi, rst=1
|
|
+ { "CSC3551", "10431483", asus_rog_2023_no_acpi }, // GU603V spi, rst=1, spkr=1
|
|
+ { "CSC3551", "10431493", asus_rog_2023_no_acpi }, // GV601V spi, rst=1
|
|
+ { "CSC3551", "10431573", asus_rog_2023_no_acpi }, // GZ301V spi, rst=0
|
|
+ { "CSC3551", "104317F3", asus_rog_2023_no_acpi }, // ROG ALLY i2c, rst=0
|
|
+ { "CSC3551", "10431B93", asus_rog_2023_no_acpi }, // G614J spi, rst=0
|
|
+ { "CSC3551", "10431C9F", asus_rog_2023_no_acpi }, // G614JI spi, rst=0
|
|
+ { "CSC3551", "10431CAF", asus_rog_2023_no_acpi }, // G634J spi, rst=1
|
|
+ { "CSC3551", "10431CCF", asus_rog_2023_no_acpi }, // G814J spi, rst=1
|
|
+ { "CSC3551", "10431D1F", asus_rog_2023_no_acpi }, // G713P i2c, rst=0
|
|
+ { "CSC3551", "10431E02", asus_rog_2023_no_acpi }, // UX3042Z spi, rst=1
|
|
+ { "CSC3551", "10431F1F", asus_rog_2023_no_acpi }, // H7604JV spi, rst=0
|
|
{}
|
|
};
|
|
|
|
--
|
|
2.41.0
|
|
|
|
From b35a4c957b3f0e5b4c7c73dec4fe3a5b9dbc4873 Mon Sep 17 00:00:00 2001
|
|
From: "Luke D. Jones" <luke@ljones.dev>
|
|
Date: Sun, 30 Apr 2023 10:56:34 +1200
|
|
Subject: [PATCH v6 1/1] platform/x86: asus-wmi: add support for ASUS screenpad
|
|
|
|
Add support for the WMI methods used to turn off and adjust the
|
|
brightness of the secondary "screenpad" device found on some high-end
|
|
ASUS laptops like the GX650P series and others.
|
|
|
|
There are some small quirks with this device when considering only the
|
|
raw WMI methods:
|
|
1. The Off method can only switch the device off
|
|
2. Changing the brightness turns the device back on
|
|
3. To turn the device back on the brightness must be > 1
|
|
4. When the device is off the brightness can't be changed (so it is
|
|
stored by the driver if device is off).
|
|
5. Booting with a value of 0 brightness (retained by bios) means the bios
|
|
will set a value of >0 <15
|
|
6. When the device is off it is "unplugged"
|
|
|
|
asus_wmi sets the minimum brightness as 20 in general use, and 60 for
|
|
booting with values <= min.
|
|
|
|
The ACPI methods are used in a new backlight device named asus_screenpad.
|
|
|
|
Signed-off-by: Luke D. Jones <luke@ljones.dev>
|
|
---
|
|
drivers/platform/x86/asus-wmi.c | 133 +++++++++++++++++++++
|
|
drivers/platform/x86/asus-wmi.h | 1 +
|
|
include/linux/platform_data/x86/asus-wmi.h | 4 +
|
|
3 files changed, 138 insertions(+)
|
|
|
|
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
|
|
index f54178d6f780..0b13be703856 100644
|
|
--- a/drivers/platform/x86/asus-wmi.c
|
|
+++ b/drivers/platform/x86/asus-wmi.c
|
|
@@ -25,6 +25,7 @@
|
|
#include <linux/input/sparse-keymap.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/leds.h>
|
|
+#include <linux/minmax.h>
|
|
#include <linux/module.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/pci_hotplug.h>
|
|
@@ -127,6 +128,10 @@ module_param(fnlock_default, bool, 0444);
|
|
#define NVIDIA_TEMP_MIN 75
|
|
#define NVIDIA_TEMP_MAX 87
|
|
|
|
+#define ASUS_SCREENPAD_BRIGHT_MIN 20
|
|
+#define ASUS_SCREENPAD_BRIGHT_MAX 255
|
|
+#define ASUS_SCREENPAD_BRIGHT_DEFAULT 60
|
|
+
|
|
static const char * const ashs_ids[] = { "ATK4001", "ATK4002", NULL };
|
|
|
|
static int throttle_thermal_policy_write(struct asus_wmi *);
|
|
@@ -212,6 +217,7 @@ struct asus_wmi {
|
|
|
|
struct input_dev *inputdev;
|
|
struct backlight_device *backlight_device;
|
|
+ struct backlight_device *screenpad_backlight_device;
|
|
struct platform_device *platform_device;
|
|
|
|
struct led_classdev wlan_led;
|
|
@@ -3776,6 +3782,124 @@ static int is_display_toggle(int code)
|
|
return 0;
|
|
}
|
|
|
|
+/* Screenpad backlight *******************************************************/
|
|
+
|
|
+static int read_screenpad_backlight_power(struct asus_wmi *asus)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ ret = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_SCREENPAD_POWER);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ /* 1 == powered */
|
|
+ return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
|
|
+}
|
|
+
|
|
+static int read_screenpad_brightness(struct backlight_device *bd)
|
|
+{
|
|
+ struct asus_wmi *asus = bl_get_data(bd);
|
|
+ u32 retval;
|
|
+ int err;
|
|
+
|
|
+ err = read_screenpad_backlight_power(asus);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+ /* The device brightness can only be read if powered, so return stored */
|
|
+ if (err == FB_BLANK_POWERDOWN)
|
|
+ return asus->driver->screenpad_brightness - ASUS_SCREENPAD_BRIGHT_MIN;
|
|
+
|
|
+ err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT, &retval);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+
|
|
+ return (retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK) - ASUS_SCREENPAD_BRIGHT_MIN;
|
|
+}
|
|
+
|
|
+static int update_screenpad_bl_status(struct backlight_device *bd)
|
|
+{
|
|
+ struct asus_wmi *asus = bl_get_data(bd);
|
|
+ int power, err = 0;
|
|
+ u32 ctrl_param;
|
|
+
|
|
+ power = read_screenpad_backlight_power(asus);
|
|
+ if (power < 0)
|
|
+ return power;
|
|
+
|
|
+ if (bd->props.power != power) {
|
|
+ if (power != FB_BLANK_UNBLANK) {
|
|
+ /* Only brightness > 0 can power it back on */
|
|
+ ctrl_param = asus->driver->screenpad_brightness - ASUS_SCREENPAD_BRIGHT_MIN;
|
|
+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT,
|
|
+ ctrl_param, NULL);
|
|
+ } else {
|
|
+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_POWER, 0, NULL);
|
|
+ }
|
|
+ } else if (power == FB_BLANK_UNBLANK) {
|
|
+ /* Only set brightness if powered on or we get invalid/unsync state */
|
|
+ ctrl_param = bd->props.brightness + ASUS_SCREENPAD_BRIGHT_MIN;
|
|
+ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_SCREENPAD_LIGHT, ctrl_param, NULL);
|
|
+ }
|
|
+
|
|
+ /* Ensure brightness is stored to turn back on with */
|
|
+ if (err == 0)
|
|
+ asus->driver->screenpad_brightness = bd->props.brightness + ASUS_SCREENPAD_BRIGHT_MIN;
|
|
+
|
|
+ return err;
|
|
+}
|
|
+
|
|
+static const struct backlight_ops asus_screenpad_bl_ops = {
|
|
+ .get_brightness = read_screenpad_brightness,
|
|
+ .update_status = update_screenpad_bl_status,
|
|
+ .options = BL_CORE_SUSPENDRESUME,
|
|
+};
|
|
+
|
|
+static int asus_screenpad_init(struct asus_wmi *asus)
|
|
+{
|
|
+ struct backlight_device *bd;
|
|
+ struct backlight_properties props;
|
|
+ int err, power;
|
|
+ int brightness = 0;
|
|
+
|
|
+ power = read_screenpad_backlight_power(asus);
|
|
+ if (power < 0)
|
|
+ return power;
|
|
+
|
|
+ if (power != FB_BLANK_POWERDOWN) {
|
|
+ err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT, &brightness);
|
|
+ if (err < 0)
|
|
+ return err;
|
|
+ }
|
|
+ /* default to an acceptable min brightness on boot if too low */
|
|
+ if (brightness < ASUS_SCREENPAD_BRIGHT_MIN)
|
|
+ brightness = ASUS_SCREENPAD_BRIGHT_DEFAULT;
|
|
+
|
|
+ memset(&props, 0, sizeof(struct backlight_properties));
|
|
+ props.type = BACKLIGHT_RAW; /* ensure this bd is last to be picked */
|
|
+ props.max_brightness = ASUS_SCREENPAD_BRIGHT_MAX - ASUS_SCREENPAD_BRIGHT_MIN;
|
|
+ bd = backlight_device_register("asus_screenpad",
|
|
+ &asus->platform_device->dev, asus,
|
|
+ &asus_screenpad_bl_ops, &props);
|
|
+ if (IS_ERR(bd)) {
|
|
+ pr_err("Could not register backlight device\n");
|
|
+ return PTR_ERR(bd);
|
|
+ }
|
|
+
|
|
+ asus->screenpad_backlight_device = bd;
|
|
+ asus->driver->screenpad_brightness = brightness;
|
|
+ bd->props.brightness = brightness;
|
|
+ bd->props.power = power;
|
|
+ backlight_update_status(bd);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void asus_screenpad_exit(struct asus_wmi *asus)
|
|
+{
|
|
+ backlight_device_unregister(asus->screenpad_backlight_device);
|
|
+
|
|
+ asus->screenpad_backlight_device = NULL;
|
|
+}
|
|
+
|
|
/* Fn-lock ********************************************************************/
|
|
|
|
static bool asus_wmi_has_fnlock_key(struct asus_wmi *asus)
|
|
@@ -4431,6 +4555,12 @@ static int asus_wmi_add(struct platform_device *pdev)
|
|
} else if (asus->driver->quirks->wmi_backlight_set_devstate)
|
|
err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT, 2, NULL);
|
|
|
|
+ if (asus_wmi_dev_is_present(asus, ASUS_WMI_DEVID_SCREENPAD_LIGHT)) {
|
|
+ err = asus_screenpad_init(asus);
|
|
+ if (err && err != -ENODEV)
|
|
+ goto fail_screenpad;
|
|
+ }
|
|
+
|
|
if (asus_wmi_has_fnlock_key(asus)) {
|
|
asus->fnlock_locked = fnlock_default;
|
|
asus_wmi_fnlock_update(asus);
|
|
@@ -4454,6 +4584,8 @@ static int asus_wmi_add(struct platform_device *pdev)
|
|
asus_wmi_backlight_exit(asus);
|
|
fail_backlight:
|
|
asus_wmi_rfkill_exit(asus);
|
|
+fail_screenpad:
|
|
+ asus_screenpad_exit(asus);
|
|
fail_rfkill:
|
|
asus_wmi_led_exit(asus);
|
|
fail_leds:
|
|
@@ -4480,6 +4612,7 @@ static int asus_wmi_remove(struct platform_device *device)
|
|
asus = platform_get_drvdata(device);
|
|
wmi_remove_notify_handler(asus->driver->event_guid);
|
|
asus_wmi_backlight_exit(asus);
|
|
+ asus_screenpad_exit(asus);
|
|
asus_wmi_input_exit(asus);
|
|
asus_wmi_led_exit(asus);
|
|
asus_wmi_rfkill_exit(asus);
|
|
diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h
|
|
index a478ebfd34df..5fbdd0eafa02 100644
|
|
--- a/drivers/platform/x86/asus-wmi.h
|
|
+++ b/drivers/platform/x86/asus-wmi.h
|
|
@@ -57,6 +57,7 @@ struct quirk_entry {
|
|
struct asus_wmi_driver {
|
|
int brightness;
|
|
int panel_power;
|
|
+ int screenpad_brightness;
|
|
int wlan_ctrl_by_user;
|
|
|
|
const char *name;
|
|
diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h
|
|
index 16e99a1c37fc..63e630276499 100644
|
|
--- a/include/linux/platform_data/x86/asus-wmi.h
|
|
+++ b/include/linux/platform_data/x86/asus-wmi.h
|
|
@@ -58,6 +58,10 @@
|
|
#define ASUS_WMI_DEVID_KBD_BACKLIGHT 0x00050021
|
|
#define ASUS_WMI_DEVID_LIGHT_SENSOR 0x00050022 /* ?? */
|
|
#define ASUS_WMI_DEVID_LIGHTBAR 0x00050025
|
|
+/* This can only be used to disable the screen, not re-enable */
|
|
+#define ASUS_WMI_DEVID_SCREENPAD_POWER 0x00050031
|
|
+/* Writing a brightness re-enables the screen if disabled */
|
|
+#define ASUS_WMI_DEVID_SCREENPAD_LIGHT 0x00050032
|
|
#define ASUS_WMI_DEVID_FAN_BOOST_MODE 0x00110018
|
|
#define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY 0x00120075
|
|
|
|
--
|
|
2.41.0
|
|
|
|
From 7760e10674dbb9127450629308c6ee1c35d5fc19 Mon Sep 17 00:00:00 2001
|
|
From: "Luke D. Jones" <luke@ljones.dev>
|
|
Date: Thu, 9 Nov 2023 09:41:13 +1300
|
|
Subject: [PATCH] ALSA: hda/realtek: Add quirk for ASUS ROG G814Jx
|
|
|
|
Adds the required quirk to enable the Cirrus amp and correct pins
|
|
on the ASUS ROG G814J series which uses an SPI connected Cirrus amp.
|
|
|
|
While this works if the related _DSD properties are made available, these
|
|
aren't included in the ACPI of these laptops (yet).
|
|
|
|
Signed-off-by: Luke D. Jones <luke@ljones.dev>
|
|
---
|
|
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 58006c8bcfb9..a690baa202c5 100644
|
|
--- a/sound/pci/hda/patch_realtek.c
|
|
+++ b/sound/pci/hda/patch_realtek.c
|
|
@@ -9924,6 +9924,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
|
|
SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JI", ALC285_FIXUP_ASUS_HEADSET_MIC),
|
|
SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JYR/JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
|
|
SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC),
|
|
+ SND_PCI_QUIRK(0x1043, 0x1ccf, "ASUS G814JI", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
|
|
SND_PCI_QUIRK(0x1043, 0x1d1f, "ASUS ROG Strix G17 2023 (G713PV)", ALC287_FIXUP_CS35L41_I2C_2),
|
|
SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401),
|
|
SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
|
|
--
|
|
2.41.0
|