From 83bcf3e52e9cfc727df33f1055ef0618c91719d0 Mon Sep 17 00:00:00 2001 From: Koba Ko Date: Tue, 17 Jan 2023 20:34:36 +0800 Subject: platform/x86: dell-wmi: Add a keymap for KEY_MUTE in type 0x0010 table Some platforms send the speaker-mute key from EC. dell-wmi can't recognize it. Add a new keymap for KEY_MUTE in type 0x0010 table. Signed-off-by: Koba Ko Link: https://lore.kernel.org/r/20230117123436.200440-1-koba.ko@canonical.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/dell/dell-wmi-base.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/dell/dell-wmi-base.c b/drivers/platform/x86/dell/dell-wmi-base.c index 0a259a27459f..502783a7adb1 100644 --- a/drivers/platform/x86/dell/dell-wmi-base.c +++ b/drivers/platform/x86/dell/dell-wmi-base.c @@ -261,6 +261,9 @@ static const struct key_entry dell_wmi_keymap_type_0010[] = { { KE_KEY, 0x57, { KEY_BRIGHTNESSDOWN } }, { KE_KEY, 0x58, { KEY_BRIGHTNESSUP } }, + /*Speaker Mute*/ + { KE_KEY, 0x109, { KEY_MUTE} }, + /* Mic mute */ { KE_KEY, 0x150, { KEY_MICMUTE } }, -- cgit v1.2.3 From 3ee5447b2048c8389ed899838a40b40180d50906 Mon Sep 17 00:00:00 2001 From: Rishit Bansal Date: Sat, 21 Jan 2023 03:42:14 +0530 Subject: platform/x86: hp-wmi: Handle Omen Key event Add support to map the "HP Omen Key" to KEY_PROG2. Laptops in the HP Omen Series open the HP Omen Command Center application on windows. But, on linux it fails with the following message from the hp-wmi driver: [ 5143.415714] hp_wmi: Unknown event_id - 29 - 0x21a5 Also adds support to map Fn+Esc to KEY_FN_ESC. This currently throws the following message on the hp-wmi driver: [ 6082.143785] hp_wmi: Unknown key code - 0x21a7 There is also a "Win-Lock" key on HP Omen Laptops which supports Enabling and Disabling the Windows key, which trigger commands 0x21a4 and 0x121a4 respectively, but I wasn't able to find any KEY in input.h to map this to. Signed-off-by: Rishit Bansal Link: https://lore.kernel.org/r/20230120221214.24426-1-rishitbansal0@gmail.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/hp/hp-wmi.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c index 0a99058be813..4a3851332ef2 100644 --- a/drivers/platform/x86/hp/hp-wmi.c +++ b/drivers/platform/x86/hp/hp-wmi.c @@ -90,6 +90,7 @@ enum hp_wmi_event_ids { HPWMI_PEAKSHIFT_PERIOD = 0x0F, HPWMI_BATTERY_CHARGE_PERIOD = 0x10, HPWMI_SANITIZATION_MODE = 0x17, + HPWMI_OMEN_KEY = 0x1D, HPWMI_SMART_EXPERIENCE_APP = 0x21, }; @@ -216,6 +217,8 @@ static const struct key_entry hp_wmi_keymap[] = { { KE_KEY, 0x213b, { KEY_INFO } }, { KE_KEY, 0x2169, { KEY_ROTATE_DISPLAY } }, { KE_KEY, 0x216a, { KEY_SETUP } }, + { KE_KEY, 0x21a5, { KEY_PROG2 } }, /* HP Omen Key */ + { KE_KEY, 0x21a7, { KEY_FN_ESC } }, { KE_KEY, 0x21a9, { KEY_TOUCHPAD_OFF } }, { KE_KEY, 0x121a9, { KEY_TOUCHPAD_ON } }, { KE_KEY, 0x231b, { KEY_HELP } }, @@ -810,6 +813,7 @@ static void hp_wmi_notify(u32 value, void *context) case HPWMI_SMART_ADAPTER: break; case HPWMI_BEZEL_BUTTON: + case HPWMI_OMEN_KEY: key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY); if (key_code < 0) break; -- cgit v1.2.3 From a410429a3b7e748a9db9f357e71e2e085a21c902 Mon Sep 17 00:00:00 2001 From: Kevin Kuriakose Date: Thu, 19 Jan 2023 20:39:25 +0530 Subject: platform/x86: gigabyte-wmi: add support for B450M DS3H WIFI-CF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To the best of my knowledge this is the same board as the B450M DS3H-CF, but with an added WiFi card. Name obtained using dmidecode, tested with force_load on v6.1.6 Signed-off-by: Kevin Kuriakose Acked-by: Thomas Weißschuh Link: https://lore.kernel.org/r/20230119150925.31962-1-kevinmkuriakose@gmail.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/gigabyte-wmi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/platform/x86/gigabyte-wmi.c b/drivers/platform/x86/gigabyte-wmi.c index 5e7e6659a849..322cfaeda17b 100644 --- a/drivers/platform/x86/gigabyte-wmi.c +++ b/drivers/platform/x86/gigabyte-wmi.c @@ -141,6 +141,7 @@ static u8 gigabyte_wmi_detect_sensor_usability(struct wmi_device *wdev) static const struct dmi_system_id gigabyte_wmi_known_working_platforms[] = { DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M DS3H-CF"), + DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M DS3H WIFI-CF"), DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M S2H V2"), DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE AX V2"), DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE"), -- cgit v1.2.3 From fdcc0602d64f22185f61c70747214b630049cc33 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 20 Jan 2023 15:34:41 +0100 Subject: platform/x86: asus-wmi: Fix kbd_dock_devid tablet-switch reporting Commit 1ea0d3b46798 ("platform/x86: asus-wmi: Simplify tablet-mode-switch handling") unified the asus-wmi tablet-switch handling, but it did not take into account that the value returned for the kbd_dock_devid WMI method is inverted where as the other ones are not inverted. This causes asus-wmi to report an inverted tablet-switch state for devices which use the kbd_dock_devid, which causes libinput to ignore touchpad events while the affected T10x model 2-in-1s are docked. Add inverting of the return value in the kbd_dock_devid case to fix this. Fixes: 1ea0d3b46798 ("platform/x86: asus-wmi: Simplify tablet-mode-switch handling") Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20230120143441.527334-1-hdegoede@redhat.com --- drivers/platform/x86/asus-wmi.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 104188d70988..1038dfdcdd32 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -225,6 +225,7 @@ struct asus_wmi { int tablet_switch_event_code; u32 tablet_switch_dev_id; + bool tablet_switch_inverted; enum fan_type fan_type; enum fan_type gpu_fan_type; @@ -493,6 +494,13 @@ static bool asus_wmi_dev_is_present(struct asus_wmi *asus, u32 dev_id) } /* Input **********************************************************************/ +static void asus_wmi_tablet_sw_report(struct asus_wmi *asus, bool value) +{ + input_report_switch(asus->inputdev, SW_TABLET_MODE, + asus->tablet_switch_inverted ? !value : value); + input_sync(asus->inputdev); +} + static void asus_wmi_tablet_sw_init(struct asus_wmi *asus, u32 dev_id, int event_code) { struct device *dev = &asus->platform_device->dev; @@ -501,7 +509,7 @@ static void asus_wmi_tablet_sw_init(struct asus_wmi *asus, u32 dev_id, int event result = asus_wmi_get_devstate_simple(asus, dev_id); if (result >= 0) { input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE); - input_report_switch(asus->inputdev, SW_TABLET_MODE, result); + asus_wmi_tablet_sw_report(asus, result); asus->tablet_switch_dev_id = dev_id; asus->tablet_switch_event_code = event_code; } else if (result == -ENODEV) { @@ -534,6 +542,7 @@ static int asus_wmi_input_init(struct asus_wmi *asus) case asus_wmi_no_tablet_switch: break; case asus_wmi_kbd_dock_devid: + asus->tablet_switch_inverted = true; asus_wmi_tablet_sw_init(asus, ASUS_WMI_DEVID_KBD_DOCK, NOTIFY_KBD_DOCK_CHANGE); break; case asus_wmi_lid_flip_devid: @@ -573,10 +582,8 @@ static void asus_wmi_tablet_mode_get_state(struct asus_wmi *asus) return; result = asus_wmi_get_devstate_simple(asus, asus->tablet_switch_dev_id); - if (result >= 0) { - input_report_switch(asus->inputdev, SW_TABLET_MODE, result); - input_sync(asus->inputdev); - } + if (result >= 0) + asus_wmi_tablet_sw_report(asus, result); } /* dGPU ********************************************************************/ -- cgit v1.2.3 From 8e60615e8932167057b363c11a7835da7f007106 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 20 Jan 2023 13:15:18 -0600 Subject: platform/x86/amd: pmc: Disable IRQ1 wakeup for RN/CZN By default when the system is configured for low power idle in the FADT the keyboard is set up as a wake source. This matches the behavior that Windows uses for Modern Standby as well. It has been reported that a variety of AMD based designs there are spurious wakeups are happening where two IRQ sources are active. For example: ``` PM: Triggering wakeup from IRQ 9 PM: Triggering wakeup from IRQ 1 ``` In these designs IRQ 9 is the ACPI SCI and IRQ 1 is the keyboard. One way to trigger this problem is to suspend the laptop and then unplug the AC adapter. The SOC will be in a hardware sleep state and plugging in the AC adapter returns control to the kernel's s2idle loop. Normally if just IRQ 9 was active the s2idle loop would advance any EC transactions and no other IRQ being active would cause the s2idle loop to put the SOC back into hardware sleep state. When this bug occurred IRQ 1 is also active even if no keyboard activity occurred. This causes the s2idle loop to break and the system to wake. This is a platform firmware bug triggering IRQ1 without keyboard activity. This occurs in Windows as well, but Windows will enter "SW DRIPS" and then with no activity enters back into "HW DRIPS" (hardware sleep state). This issue affects Renoir, Lucienne, Cezanne, and Barcelo platforms. It does not happen on newer systems such as Mendocino or Rembrandt. It's been fixed in newer platform firmware. To avoid triggering the bug on older systems check the SMU F/W version and adjust the policy at suspend time for s2idle wakeup from keyboard on these systems. A lot of thought and experimentation has been given around the timing of disabling IRQ1, and to make it work the "suspend" PM callback is restored. Reported-by: Kai-Heng Feng Reported-by: Xaver Hugl Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2115 Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1951 Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20230120191519.15926-1-mario.limonciello@amd.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/amd/pmc.c | 50 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/amd/pmc.c b/drivers/platform/x86/amd/pmc.c index 8d924986381b..be1b49824edb 100644 --- a/drivers/platform/x86/amd/pmc.c +++ b/drivers/platform/x86/amd/pmc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -653,6 +654,33 @@ static int amd_pmc_get_os_hint(struct amd_pmc_dev *dev) return -EINVAL; } +static int amd_pmc_czn_wa_irq1(struct amd_pmc_dev *pdev) +{ + struct device *d; + int rc; + + if (!pdev->major) { + rc = amd_pmc_get_smu_version(pdev); + if (rc) + return rc; + } + + if (pdev->major > 64 || (pdev->major == 64 && pdev->minor > 65)) + return 0; + + d = bus_find_device_by_name(&serio_bus, NULL, "serio0"); + if (!d) + return 0; + if (device_may_wakeup(d)) { + dev_info_once(d, "Disabling IRQ1 wakeup source to avoid platform firmware bug\n"); + disable_irq_wake(1); + device_set_wakeup_enable(d, false); + } + put_device(d); + + return 0; +} + static int amd_pmc_verify_czn_rtc(struct amd_pmc_dev *pdev, u32 *arg) { struct rtc_device *rtc_device; @@ -782,6 +810,25 @@ static struct acpi_s2idle_dev_ops amd_pmc_s2idle_dev_ops = { .check = amd_pmc_s2idle_check, .restore = amd_pmc_s2idle_restore, }; + +static int __maybe_unused amd_pmc_suspend_handler(struct device *dev) +{ + struct amd_pmc_dev *pdev = dev_get_drvdata(dev); + + if (pdev->cpu_id == AMD_CPU_ID_CZN) { + int rc = amd_pmc_czn_wa_irq1(pdev); + + if (rc) { + dev_err(pdev->dev, "failed to adjust keyboard wakeup: %d\n", rc); + return rc; + } + } + + return 0; +} + +static SIMPLE_DEV_PM_OPS(amd_pmc_pm, amd_pmc_suspend_handler, NULL); + #endif static const struct pci_device_id pmc_pci_ids[] = { @@ -980,6 +1027,9 @@ static struct platform_driver amd_pmc_driver = { .name = "amd_pmc", .acpi_match_table = amd_pmc_acpi_ids, .dev_groups = pmc_groups, +#ifdef CONFIG_SUSPEND + .pm = &amd_pmc_pm, +#endif }, .probe = amd_pmc_probe, .remove = amd_pmc_remove, -- cgit v1.2.3 From 062c1394cbda95b0c51839b5221c7267e1e7f57e Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Fri, 20 Jan 2023 13:15:19 -0600 Subject: platform/x86/amd: pmc: Add a module parameter to disable workarounds Some users may want to live with the bugs that exist in platform firmware and have workarounds in AMD PMC driver. To allow them to bypass these workarounds, introduce a module parameter. Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20230120191519.15926-2-mario.limonciello@amd.com Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/amd/pmc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/amd/pmc.c b/drivers/platform/x86/amd/pmc.c index be1b49824edb..3cbb01ec10e3 100644 --- a/drivers/platform/x86/amd/pmc.c +++ b/drivers/platform/x86/amd/pmc.c @@ -161,6 +161,10 @@ static bool enable_stb; module_param(enable_stb, bool, 0644); MODULE_PARM_DESC(enable_stb, "Enable the STB debug mechanism"); +static bool disable_workarounds; +module_param(disable_workarounds, bool, 0644); +MODULE_PARM_DESC(disable_workarounds, "Disable workarounds for platform bugs"); + static struct amd_pmc_dev pmc; static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg, bool ret); static int amd_pmc_read_stb(struct amd_pmc_dev *dev, u32 *buf); @@ -743,8 +747,8 @@ static void amd_pmc_s2idle_prepare(void) /* Reset and Start SMU logging - to monitor the s0i3 stats */ amd_pmc_setup_smu_logging(pdev); - /* Activate CZN specific RTC functionality */ - if (pdev->cpu_id == AMD_CPU_ID_CZN) { + /* Activate CZN specific platform bug workarounds */ + if (pdev->cpu_id == AMD_CPU_ID_CZN && !disable_workarounds) { rc = amd_pmc_verify_czn_rtc(pdev, &arg); if (rc) { dev_err(pdev->dev, "failed to set RTC: %d\n", rc); @@ -815,7 +819,7 @@ static int __maybe_unused amd_pmc_suspend_handler(struct device *dev) { struct amd_pmc_dev *pdev = dev_get_drvdata(dev); - if (pdev->cpu_id == AMD_CPU_ID_CZN) { + if (pdev->cpu_id == AMD_CPU_ID_CZN && !disable_workarounds) { int rc = amd_pmc_czn_wa_irq1(pdev); if (rc) { -- cgit v1.2.3 From ce95010ef62d4bf470928969bafc9070ae98cbb1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 23 Jan 2023 14:28:24 +0100 Subject: platform/x86: hp-wmi: Fix cast to smaller integer type warning Fix the following compiler warning: drivers/platform/x86/hp/hp-wmi.c:551:24: warning: cast to smaller integer type 'enum hp_wmi_radio' from 'void *' [-Wvoid-pointer-to-enum-cast] Reported-by: kernel test robot Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20230123132824.660062-1-hdegoede@redhat.com --- drivers/platform/x86/hp/hp-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c index 4a3851332ef2..2ef201b625b3 100644 --- a/drivers/platform/x86/hp/hp-wmi.c +++ b/drivers/platform/x86/hp/hp-wmi.c @@ -551,7 +551,7 @@ static int __init hp_wmi_enable_hotkeys(void) static int hp_wmi_set_block(void *data, bool blocked) { - enum hp_wmi_radio r = (enum hp_wmi_radio) data; + enum hp_wmi_radio r = (long)data; int query = BIT(r + 8) | ((!blocked) << r); int ret; -- cgit v1.2.3 From 39f5a81f7ad80eb3fbcbfd817c6552db9de5504d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 24 Jan 2023 11:57:52 +0100 Subject: platform/x86: apple-gmux: Move port defines to apple-gmux.h This is a preparation patch for adding a new static inline apple_gmux_detect() helper which actually checks a supported gmux is present, rather then only checking an ACPI device with the HID is there as apple_gmux_present() does. Fixes: 21245df307cb ("ACPI: video: Add Apple GMUX brightness control detection") Link: https://lore.kernel.org/platform-driver-x86/20230123113750.462144-1-hdegoede@redhat.com/ Reported-by: Emmanouil Kouroupakis Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20230124105754.62167-2-hdegoede@redhat.com --- drivers/platform/x86/apple-gmux.c | 23 ----------------------- include/linux/apple-gmux.h | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index ca33df7ea550..a0af01f6a0fd 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -64,29 +64,6 @@ struct apple_gmux_data { static struct apple_gmux_data *apple_gmux_data; -/* - * gmux port offsets. Many of these are not yet used, but may be in the - * future, and it's useful to have them documented here anyhow. - */ -#define GMUX_PORT_VERSION_MAJOR 0x04 -#define GMUX_PORT_VERSION_MINOR 0x05 -#define GMUX_PORT_VERSION_RELEASE 0x06 -#define GMUX_PORT_SWITCH_DISPLAY 0x10 -#define GMUX_PORT_SWITCH_GET_DISPLAY 0x11 -#define GMUX_PORT_INTERRUPT_ENABLE 0x14 -#define GMUX_PORT_INTERRUPT_STATUS 0x16 -#define GMUX_PORT_SWITCH_DDC 0x28 -#define GMUX_PORT_SWITCH_EXTERNAL 0x40 -#define GMUX_PORT_SWITCH_GET_EXTERNAL 0x41 -#define GMUX_PORT_DISCRETE_POWER 0x50 -#define GMUX_PORT_MAX_BRIGHTNESS 0x70 -#define GMUX_PORT_BRIGHTNESS 0x74 -#define GMUX_PORT_VALUE 0xc2 -#define GMUX_PORT_READ 0xd0 -#define GMUX_PORT_WRITE 0xd4 - -#define GMUX_MIN_IO_LEN (GMUX_PORT_BRIGHTNESS + 4) - #define GMUX_INTERRUPT_ENABLE 0xff #define GMUX_INTERRUPT_DISABLE 0x00 diff --git a/include/linux/apple-gmux.h b/include/linux/apple-gmux.h index ddb10aa67b14..80efaaf89e07 100644 --- a/include/linux/apple-gmux.h +++ b/include/linux/apple-gmux.h @@ -11,6 +11,29 @@ #define GMUX_ACPI_HID "APP000B" +/* + * gmux port offsets. Many of these are not yet used, but may be in the + * future, and it's useful to have them documented here anyhow. + */ +#define GMUX_PORT_VERSION_MAJOR 0x04 +#define GMUX_PORT_VERSION_MINOR 0x05 +#define GMUX_PORT_VERSION_RELEASE 0x06 +#define GMUX_PORT_SWITCH_DISPLAY 0x10 +#define GMUX_PORT_SWITCH_GET_DISPLAY 0x11 +#define GMUX_PORT_INTERRUPT_ENABLE 0x14 +#define GMUX_PORT_INTERRUPT_STATUS 0x16 +#define GMUX_PORT_SWITCH_DDC 0x28 +#define GMUX_PORT_SWITCH_EXTERNAL 0x40 +#define GMUX_PORT_SWITCH_GET_EXTERNAL 0x41 +#define GMUX_PORT_DISCRETE_POWER 0x50 +#define GMUX_PORT_MAX_BRIGHTNESS 0x70 +#define GMUX_PORT_BRIGHTNESS 0x74 +#define GMUX_PORT_VALUE 0xc2 +#define GMUX_PORT_READ 0xd0 +#define GMUX_PORT_WRITE 0xd4 + +#define GMUX_MIN_IO_LEN (GMUX_PORT_BRIGHTNESS + 4) + #if IS_ENABLED(CONFIG_APPLE_GMUX) /** -- cgit v1.2.3 From d143908f80f3e5d164ac3342f73d6b9f536e8b4d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 24 Jan 2023 11:57:53 +0100 Subject: platform/x86: apple-gmux: Add apple_gmux_detect() helper Add a new (static inline) apple_gmux_detect() helper to apple-gmux.h which can be used for gmux detection instead of apple_gmux_present(). The latter is not really reliable since an ACPI device with a HID of APP000B is present on some devices without a gmux at all, as well as on devices with a newer (unsupported) MMIO based gmux model. This causes apple_gmux_present() to return false-positives on a number of different Apple laptop models. This new helper uses the same probing as the actual apple-gmux driver, so that it does not return false positives. To avoid code duplication the gmux_probe() function of the actual driver is also moved over to using the new apple_gmux_detect() helper. This avoids false positives (vs _HID + IO region detection) on: MacBookPro5,4 https://pastebin.com/8Xjq7RhS MacBookPro8,1 https://linux-hardware.org/?probe=e513cfbadb&log=dmesg MacBookPro9,2 https://bugzilla.kernel.org/attachment.cgi?id=278961 MacBookPro10,2 https://lkml.org/lkml/2014/9/22/657 MacBookPro11,2 https://forums.fedora-fr.org/viewtopic.php?id=70142 MacBookPro11,4 https://raw.githubusercontent.com/im-0/investigate-card-reader-suspend-problem-on-mbp11.4/master/test-16/dmesg Fixes: 21245df307cb ("ACPI: video: Add Apple GMUX brightness control detection") Link: https://lore.kernel.org/platform-driver-x86/20230123113750.462144-1-hdegoede@redhat.com/ Reported-by: Emmanouil Kouroupakis Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20230124105754.62167-3-hdegoede@redhat.com --- drivers/platform/x86/apple-gmux.c | 70 ++++++++----------------------- include/linux/apple-gmux.h | 86 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c index a0af01f6a0fd..9333f82cfa8a 100644 --- a/drivers/platform/x86/apple-gmux.c +++ b/drivers/platform/x86/apple-gmux.c @@ -226,23 +226,6 @@ static void gmux_write32(struct apple_gmux_data *gmux_data, int port, gmux_pio_write32(gmux_data, port, val); } -static bool gmux_is_indexed(struct apple_gmux_data *gmux_data) -{ - u16 val; - - outb(0xaa, gmux_data->iostart + 0xcc); - outb(0x55, gmux_data->iostart + 0xcd); - outb(0x00, gmux_data->iostart + 0xce); - - val = inb(gmux_data->iostart + 0xcc) | - (inb(gmux_data->iostart + 0xcd) << 8); - - if (val == 0x55aa) - return true; - - return false; -} - /** * DOC: Backlight control * @@ -582,60 +565,43 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) int ret = -ENXIO; acpi_status status; unsigned long long gpe; + bool indexed = false; + u32 version; if (apple_gmux_data) return -EBUSY; + if (!apple_gmux_detect(pnp, &indexed)) { + pr_info("gmux device not present\n"); + return -ENODEV; + } + gmux_data = kzalloc(sizeof(*gmux_data), GFP_KERNEL); if (!gmux_data) return -ENOMEM; pnp_set_drvdata(pnp, gmux_data); res = pnp_get_resource(pnp, IORESOURCE_IO, 0); - if (!res) { - pr_err("Failed to find gmux I/O resource\n"); - goto err_free; - } - gmux_data->iostart = res->start; gmux_data->iolen = resource_size(res); - if (gmux_data->iolen < GMUX_MIN_IO_LEN) { - pr_err("gmux I/O region too small (%lu < %u)\n", - gmux_data->iolen, GMUX_MIN_IO_LEN); - goto err_free; - } - if (!request_region(gmux_data->iostart, gmux_data->iolen, "Apple gmux")) { pr_err("gmux I/O already in use\n"); goto err_free; } - /* - * Invalid version information may indicate either that the gmux - * device isn't present or that it's a new one that uses indexed - * io - */ - - ver_major = gmux_read8(gmux_data, GMUX_PORT_VERSION_MAJOR); - ver_minor = gmux_read8(gmux_data, GMUX_PORT_VERSION_MINOR); - ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE); - if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) { - if (gmux_is_indexed(gmux_data)) { - u32 version; - mutex_init(&gmux_data->index_lock); - gmux_data->indexed = true; - version = gmux_read32(gmux_data, - GMUX_PORT_VERSION_MAJOR); - ver_major = (version >> 24) & 0xff; - ver_minor = (version >> 16) & 0xff; - ver_release = (version >> 8) & 0xff; - } else { - pr_info("gmux device not present\n"); - ret = -ENODEV; - goto err_release; - } + if (indexed) { + mutex_init(&gmux_data->index_lock); + gmux_data->indexed = true; + version = gmux_read32(gmux_data, GMUX_PORT_VERSION_MAJOR); + ver_major = (version >> 24) & 0xff; + ver_minor = (version >> 16) & 0xff; + ver_release = (version >> 8) & 0xff; + } else { + ver_major = gmux_read8(gmux_data, GMUX_PORT_VERSION_MAJOR); + ver_minor = gmux_read8(gmux_data, GMUX_PORT_VERSION_MINOR); + ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE); } pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor, ver_release, (gmux_data->indexed ? "indexed" : "classic")); diff --git a/include/linux/apple-gmux.h b/include/linux/apple-gmux.h index 80efaaf89e07..1f68b49bcd68 100644 --- a/include/linux/apple-gmux.h +++ b/include/linux/apple-gmux.h @@ -8,6 +8,8 @@ #define LINUX_APPLE_GMUX_H #include +#include +#include #define GMUX_ACPI_HID "APP000B" @@ -35,14 +37,89 @@ #define GMUX_MIN_IO_LEN (GMUX_PORT_BRIGHTNESS + 4) #if IS_ENABLED(CONFIG_APPLE_GMUX) +static inline bool apple_gmux_is_indexed(unsigned long iostart) +{ + u16 val; + + outb(0xaa, iostart + 0xcc); + outb(0x55, iostart + 0xcd); + outb(0x00, iostart + 0xce); + + val = inb(iostart + 0xcc) | (inb(iostart + 0xcd) << 8); + if (val == 0x55aa) + return true; + + return false; +} /** - * apple_gmux_present() - detect if gmux is built into the machine + * apple_gmux_detect() - detect if gmux is built into the machine + * + * @pnp_dev: Device to probe or NULL to use the first matching device + * @indexed_ret: Returns (by reference) if the gmux is indexed or not + * + * Detect if a supported gmux device is present by actually probing it. + * This avoids the false positives returned on some models by + * apple_gmux_present(). + * + * Return: %true if a supported gmux ACPI device is detected and the kernel + * was configured with CONFIG_APPLE_GMUX, %false otherwise. + */ +static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, bool *indexed_ret) +{ + u8 ver_major, ver_minor, ver_release; + struct device *dev = NULL; + struct acpi_device *adev; + struct resource *res; + bool indexed = false; + bool ret = false; + + if (!pnp_dev) { + adev = acpi_dev_get_first_match_dev(GMUX_ACPI_HID, NULL, -1); + if (!adev) + return false; + + dev = get_device(acpi_get_first_physical_node(adev)); + acpi_dev_put(adev); + if (!dev) + return false; + + pnp_dev = to_pnp_dev(dev); + } + + res = pnp_get_resource(pnp_dev, IORESOURCE_IO, 0); + if (!res || resource_size(res) < GMUX_MIN_IO_LEN) + goto out; + + /* + * Invalid version information may indicate either that the gmux + * device isn't present or that it's a new one that uses indexed io. + */ + ver_major = inb(res->start + GMUX_PORT_VERSION_MAJOR); + ver_minor = inb(res->start + GMUX_PORT_VERSION_MINOR); + ver_release = inb(res->start + GMUX_PORT_VERSION_RELEASE); + if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) { + indexed = apple_gmux_is_indexed(res->start); + if (!indexed) + goto out; + } + + if (indexed_ret) + *indexed_ret = indexed; + + ret = true; +out: + put_device(dev); + return ret; +} + +/** + * apple_gmux_present() - check if gmux ACPI device is present * * Drivers may use this to activate quirks specific to dual GPU MacBook Pros * and Mac Pros, e.g. for deferred probing, runtime pm and backlight. * - * Return: %true if gmux is present and the kernel was configured + * Return: %true if gmux ACPI device is present and the kernel was configured * with CONFIG_APPLE_GMUX, %false otherwise. */ static inline bool apple_gmux_present(void) @@ -57,6 +134,11 @@ static inline bool apple_gmux_present(void) return false; } +static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, bool *indexed_ret) +{ + return false; +} + #endif /* !CONFIG_APPLE_GMUX */ #endif /* LINUX_APPLE_GMUX_H */ -- cgit v1.2.3 From b0935f110cff5d70da05c5cb1670bee0b07b631c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 24 Jan 2023 11:57:54 +0100 Subject: ACPI: video: Fix apple gmux detection Some apple laptop models have an ACPI device with a HID of APP000B and that device has an IO resource (so it does not describe the new unsupported MMIO based gmux type), but there actually is no gmux in the laptop at all. The gmux_probe() function of the actual apple-gmux driver has code to detect this, this code has been factored out into a new apple_gmux_detect() helper in apple-gmux.h. Use this new function to fix acpi_video_get_backlight_type() wrongly returning apple_gmux as type on the following laptops: MacBookPro5,4 https://pastebin.com/8Xjq7RhS MacBookPro8,1 https://linux-hardware.org/?probe=e513cfbadb&log=dmesg MacBookPro9,2 https://bugzilla.kernel.org/attachment.cgi?id=278961 MacBookPro10,2 https://lkml.org/lkml/2014/9/22/657 MacBookPro11,2 https://forums.fedora-fr.org/viewtopic.php?id=70142 MacBookPro11,4 https://raw.githubusercontent.com/im-0/investigate-card-reader-suspend-problem-on-mbp11.4/mast Fixes: 21245df307cb ("ACPI: video: Add Apple GMUX brightness control detection") Link: https://lore.kernel.org/platform-driver-x86/20230123113750.462144-1-hdegoede@redhat.com/ Reported-by: Emmanouil Kouroupakis Acked-by: Rafael J. Wysocki Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20230124105754.62167-4-hdegoede@redhat.com --- drivers/acpi/video_detect.c | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 65cec7bb6d96..8626869c4904 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -110,26 +110,6 @@ static bool nvidia_wmi_ec_supported(void) } #endif -static bool apple_gmux_backlight_present(void) -{ - struct acpi_device *adev; - struct device *dev; - - adev = acpi_dev_get_first_match_dev(GMUX_ACPI_HID, NULL, -1); - if (!adev) - return false; - - dev = acpi_get_first_physical_node(adev); - if (!dev) - return false; - - /* - * drivers/platform/x86/apple-gmux.c only supports old style - * Apple GMUX with an IO-resource. - */ - return pnp_get_resource(to_pnp_dev(dev), IORESOURCE_IO, 0) != NULL; -} - /* Force to use vendor driver when the ACPI device is known to be * buggy */ static int video_detect_force_vendor(const struct dmi_system_id *d) @@ -766,6 +746,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native) { static DEFINE_MUTEX(init_mutex); static bool nvidia_wmi_ec_present; + static bool apple_gmux_present; static bool native_available; static bool init_done; static long video_caps; @@ -779,6 +760,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native) ACPI_UINT32_MAX, find_video, NULL, &video_caps, NULL); nvidia_wmi_ec_present = nvidia_wmi_ec_supported(); + apple_gmux_present = apple_gmux_detect(NULL, NULL); init_done = true; } if (native) @@ -800,7 +782,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native) if (nvidia_wmi_ec_present) return acpi_backlight_nvidia_wmi_ec; - if (apple_gmux_backlight_present()) + if (apple_gmux_present) return acpi_backlight_apple_gmux; /* Use ACPI video if available, except when native should be preferred. */ -- cgit v1.2.3 From 1bc5d819f0b9784043ea08570e1b21107aa35739 Mon Sep 17 00:00:00 2001 From: Mark Pearson Date: Tue, 24 Jan 2023 10:36:23 -0500 Subject: platform/x86: thinkpad_acpi: Fix profile modes on Intel platforms My last commit to fix profile mode displays on AMD platforms caused an issue on Intel platforms - sorry! In it I was reading the current functional mode (MMC, PSC, AMT) from the BIOS but didn't account for the fact that on some of our Intel platforms I use a different API which returns just the profile and not the functional mode. This commit fixes it so that on Intel platforms it knows the functional mode is always MMC. I also fixed a potential problem that a platform may try to set the mode for both MMC and PSC - which was incorrect. Tested on X1 Carbon 9 (Intel) and Z13 (AMD). Link: https://bugzilla.kernel.org/show_bug.cgi?id=216963 Fixes: fde5f74ccfc7 ("platform/x86: thinkpad_acpi: Fix profile mode display in AMT mode") Cc: stable@vger.kernel.org Reviewed-by: Mario Limonciello Signed-off-by: Mark Pearson Link: https://lore.kernel.org/r/20230124153623.145188-1-mpearson-lenovo@squebb.ca Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/platform/x86/thinkpad_acpi.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index a95946800ae9..02860c32625e 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -10496,8 +10496,7 @@ static int dytc_profile_set(struct platform_profile_handler *pprof, if (err) goto unlock; } - } - if (dytc_capabilities & BIT(DYTC_FC_PSC)) { + } else if (dytc_capabilities & BIT(DYTC_FC_PSC)) { err = dytc_command(DYTC_SET_COMMAND(DYTC_FUNCTION_PSC, perfmode, 1), &output); if (err) goto unlock; @@ -10525,14 +10524,16 @@ static void dytc_profile_refresh(void) err = dytc_command(DYTC_CMD_MMC_GET, &output); else err = dytc_cql_command(DYTC_CMD_GET, &output); - } else if (dytc_capabilities & BIT(DYTC_FC_PSC)) + funcmode = DYTC_FUNCTION_MMC; + } else if (dytc_capabilities & BIT(DYTC_FC_PSC)) { err = dytc_command(DYTC_CMD_GET, &output); - + /* Check if we are PSC mode, or have AMT enabled */ + funcmode = (output >> DYTC_GET_FUNCTION_BIT) & 0xF; + } mutex_unlock(&dytc_mutex); if (err) return; - funcmode = (output >> DYTC_GET_FUNCTION_BIT) & 0xF; perfmode = (output >> DYTC_GET_MODE_BIT) & 0xF; convert_dytc_to_profile(funcmode, perfmode, &profile); if (profile != dytc_current_profile) { -- cgit v1.2.3