Commit 83abd4d4 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'platform-drivers-x86-v6.2-3' of...

Merge tag 'platform-drivers-x86-v6.2-3' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86

Pull x86 platform driver fixes from Hans de Goede:

 -  Fix false positive apple_gmux backlight detection on older iGPU only
    MacBook models

 -  Various other small fixes and hardware-id additions

* tag 'platform-drivers-x86-v6.2-3' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86:
  platform/x86: thinkpad_acpi: Fix profile modes on Intel platforms
  ACPI: video: Fix apple gmux detection
  platform/x86: apple-gmux: Add apple_gmux_detect() helper
  platform/x86: apple-gmux: Move port defines to apple-gmux.h
  platform/x86: hp-wmi: Fix cast to smaller integer type warning
  platform/x86/amd: pmc: Add a module parameter to disable workarounds
  platform/x86/amd: pmc: Disable IRQ1 wakeup for RN/CZN
  platform/x86: asus-wmi: Fix kbd_dock_devid tablet-switch reporting
  platform/x86: gigabyte-wmi: add support for B450M DS3H WIFI-CF
  platform/x86: hp-wmi: Handle Omen Key event
  platform/x86: dell-wmi: Add a keymap for KEY_MUTE in type 0x0010 table
parents 28b4387f 1bc5d819
...@@ -110,26 +110,6 @@ static bool nvidia_wmi_ec_supported(void) ...@@ -110,26 +110,6 @@ static bool nvidia_wmi_ec_supported(void)
} }
#endif #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 /* Force to use vendor driver when the ACPI device is known to be
* buggy */ * buggy */
static int video_detect_force_vendor(const struct dmi_system_id *d) 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) ...@@ -766,6 +746,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
{ {
static DEFINE_MUTEX(init_mutex); static DEFINE_MUTEX(init_mutex);
static bool nvidia_wmi_ec_present; static bool nvidia_wmi_ec_present;
static bool apple_gmux_present;
static bool native_available; static bool native_available;
static bool init_done; static bool init_done;
static long video_caps; static long video_caps;
...@@ -779,6 +760,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native) ...@@ -779,6 +760,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
ACPI_UINT32_MAX, find_video, NULL, ACPI_UINT32_MAX, find_video, NULL,
&video_caps, NULL); &video_caps, NULL);
nvidia_wmi_ec_present = nvidia_wmi_ec_supported(); nvidia_wmi_ec_present = nvidia_wmi_ec_supported();
apple_gmux_present = apple_gmux_detect(NULL, NULL);
init_done = true; init_done = true;
} }
if (native) if (native)
...@@ -800,7 +782,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native) ...@@ -800,7 +782,7 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
if (nvidia_wmi_ec_present) if (nvidia_wmi_ec_present)
return acpi_backlight_nvidia_wmi_ec; return acpi_backlight_nvidia_wmi_ec;
if (apple_gmux_backlight_present()) if (apple_gmux_present)
return acpi_backlight_apple_gmux; return acpi_backlight_apple_gmux;
/* Use ACPI video if available, except when native should be preferred. */ /* Use ACPI video if available, except when native should be preferred. */
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/serio.h>
#include <linux/suspend.h> #include <linux/suspend.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
...@@ -160,6 +161,10 @@ static bool enable_stb; ...@@ -160,6 +161,10 @@ static bool enable_stb;
module_param(enable_stb, bool, 0644); module_param(enable_stb, bool, 0644);
MODULE_PARM_DESC(enable_stb, "Enable the STB debug mechanism"); 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 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_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); static int amd_pmc_read_stb(struct amd_pmc_dev *dev, u32 *buf);
...@@ -653,6 +658,33 @@ static int amd_pmc_get_os_hint(struct amd_pmc_dev *dev) ...@@ -653,6 +658,33 @@ static int amd_pmc_get_os_hint(struct amd_pmc_dev *dev)
return -EINVAL; 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) static int amd_pmc_verify_czn_rtc(struct amd_pmc_dev *pdev, u32 *arg)
{ {
struct rtc_device *rtc_device; struct rtc_device *rtc_device;
...@@ -715,8 +747,8 @@ static void amd_pmc_s2idle_prepare(void) ...@@ -715,8 +747,8 @@ static void amd_pmc_s2idle_prepare(void)
/* Reset and Start SMU logging - to monitor the s0i3 stats */ /* Reset and Start SMU logging - to monitor the s0i3 stats */
amd_pmc_setup_smu_logging(pdev); amd_pmc_setup_smu_logging(pdev);
/* Activate CZN specific RTC functionality */ /* Activate CZN specific platform bug workarounds */
if (pdev->cpu_id == AMD_CPU_ID_CZN) { if (pdev->cpu_id == AMD_CPU_ID_CZN && !disable_workarounds) {
rc = amd_pmc_verify_czn_rtc(pdev, &arg); rc = amd_pmc_verify_czn_rtc(pdev, &arg);
if (rc) { if (rc) {
dev_err(pdev->dev, "failed to set RTC: %d\n", rc); dev_err(pdev->dev, "failed to set RTC: %d\n", rc);
...@@ -782,6 +814,25 @@ static struct acpi_s2idle_dev_ops amd_pmc_s2idle_dev_ops = { ...@@ -782,6 +814,25 @@ static struct acpi_s2idle_dev_ops amd_pmc_s2idle_dev_ops = {
.check = amd_pmc_s2idle_check, .check = amd_pmc_s2idle_check,
.restore = amd_pmc_s2idle_restore, .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 && !disable_workarounds) {
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 #endif
static const struct pci_device_id pmc_pci_ids[] = { static const struct pci_device_id pmc_pci_ids[] = {
...@@ -980,6 +1031,9 @@ static struct platform_driver amd_pmc_driver = { ...@@ -980,6 +1031,9 @@ static struct platform_driver amd_pmc_driver = {
.name = "amd_pmc", .name = "amd_pmc",
.acpi_match_table = amd_pmc_acpi_ids, .acpi_match_table = amd_pmc_acpi_ids,
.dev_groups = pmc_groups, .dev_groups = pmc_groups,
#ifdef CONFIG_SUSPEND
.pm = &amd_pmc_pm,
#endif
}, },
.probe = amd_pmc_probe, .probe = amd_pmc_probe,
.remove = amd_pmc_remove, .remove = amd_pmc_remove,
......
...@@ -64,29 +64,6 @@ struct apple_gmux_data { ...@@ -64,29 +64,6 @@ struct apple_gmux_data {
static struct apple_gmux_data *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_ENABLE 0xff
#define GMUX_INTERRUPT_DISABLE 0x00 #define GMUX_INTERRUPT_DISABLE 0x00
...@@ -249,23 +226,6 @@ static void gmux_write32(struct apple_gmux_data *gmux_data, int port, ...@@ -249,23 +226,6 @@ static void gmux_write32(struct apple_gmux_data *gmux_data, int port,
gmux_pio_write32(gmux_data, port, val); 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 * DOC: Backlight control
* *
...@@ -605,60 +565,43 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id) ...@@ -605,60 +565,43 @@ static int gmux_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
int ret = -ENXIO; int ret = -ENXIO;
acpi_status status; acpi_status status;
unsigned long long gpe; unsigned long long gpe;
bool indexed = false;
u32 version;
if (apple_gmux_data) if (apple_gmux_data)
return -EBUSY; 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); gmux_data = kzalloc(sizeof(*gmux_data), GFP_KERNEL);
if (!gmux_data) if (!gmux_data)
return -ENOMEM; return -ENOMEM;
pnp_set_drvdata(pnp, gmux_data); pnp_set_drvdata(pnp, gmux_data);
res = pnp_get_resource(pnp, IORESOURCE_IO, 0); 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->iostart = res->start;
gmux_data->iolen = resource_size(res); 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, if (!request_region(gmux_data->iostart, gmux_data->iolen,
"Apple gmux")) { "Apple gmux")) {
pr_err("gmux I/O already in use\n"); pr_err("gmux I/O already in use\n");
goto err_free; goto err_free;
} }
/* if (indexed) {
* 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); mutex_init(&gmux_data->index_lock);
gmux_data->indexed = true; gmux_data->indexed = true;
version = gmux_read32(gmux_data, version = gmux_read32(gmux_data, GMUX_PORT_VERSION_MAJOR);
GMUX_PORT_VERSION_MAJOR);
ver_major = (version >> 24) & 0xff; ver_major = (version >> 24) & 0xff;
ver_minor = (version >> 16) & 0xff; ver_minor = (version >> 16) & 0xff;
ver_release = (version >> 8) & 0xff; ver_release = (version >> 8) & 0xff;
} else { } else {
pr_info("gmux device not present\n"); ver_major = gmux_read8(gmux_data, GMUX_PORT_VERSION_MAJOR);
ret = -ENODEV; ver_minor = gmux_read8(gmux_data, GMUX_PORT_VERSION_MINOR);
goto err_release; ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE);
}
} }
pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor, pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor,
ver_release, (gmux_data->indexed ? "indexed" : "classic")); ver_release, (gmux_data->indexed ? "indexed" : "classic"));
......
...@@ -225,6 +225,7 @@ struct asus_wmi { ...@@ -225,6 +225,7 @@ struct asus_wmi {
int tablet_switch_event_code; int tablet_switch_event_code;
u32 tablet_switch_dev_id; u32 tablet_switch_dev_id;
bool tablet_switch_inverted;
enum fan_type fan_type; enum fan_type fan_type;
enum fan_type gpu_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) ...@@ -493,6 +494,13 @@ static bool asus_wmi_dev_is_present(struct asus_wmi *asus, u32 dev_id)
} }
/* Input **********************************************************************/ /* 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) static void asus_wmi_tablet_sw_init(struct asus_wmi *asus, u32 dev_id, int event_code)
{ {
struct device *dev = &asus->platform_device->dev; 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 ...@@ -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); result = asus_wmi_get_devstate_simple(asus, dev_id);
if (result >= 0) { if (result >= 0) {
input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE); 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_dev_id = dev_id;
asus->tablet_switch_event_code = event_code; asus->tablet_switch_event_code = event_code;
} else if (result == -ENODEV) { } else if (result == -ENODEV) {
...@@ -534,6 +542,7 @@ static int asus_wmi_input_init(struct asus_wmi *asus) ...@@ -534,6 +542,7 @@ static int asus_wmi_input_init(struct asus_wmi *asus)
case asus_wmi_no_tablet_switch: case asus_wmi_no_tablet_switch:
break; break;
case asus_wmi_kbd_dock_devid: 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); asus_wmi_tablet_sw_init(asus, ASUS_WMI_DEVID_KBD_DOCK, NOTIFY_KBD_DOCK_CHANGE);
break; break;
case asus_wmi_lid_flip_devid: case asus_wmi_lid_flip_devid:
...@@ -573,10 +582,8 @@ static void asus_wmi_tablet_mode_get_state(struct asus_wmi *asus) ...@@ -573,10 +582,8 @@ static void asus_wmi_tablet_mode_get_state(struct asus_wmi *asus)
return; return;
result = asus_wmi_get_devstate_simple(asus, asus->tablet_switch_dev_id); result = asus_wmi_get_devstate_simple(asus, asus->tablet_switch_dev_id);
if (result >= 0) { if (result >= 0)
input_report_switch(asus->inputdev, SW_TABLET_MODE, result); asus_wmi_tablet_sw_report(asus, result);
input_sync(asus->inputdev);
}
} }
/* dGPU ********************************************************************/ /* dGPU ********************************************************************/
......
...@@ -261,6 +261,9 @@ static const struct key_entry dell_wmi_keymap_type_0010[] = { ...@@ -261,6 +261,9 @@ static const struct key_entry dell_wmi_keymap_type_0010[] = {
{ KE_KEY, 0x57, { KEY_BRIGHTNESSDOWN } }, { KE_KEY, 0x57, { KEY_BRIGHTNESSDOWN } },
{ KE_KEY, 0x58, { KEY_BRIGHTNESSUP } }, { KE_KEY, 0x58, { KEY_BRIGHTNESSUP } },
/*Speaker Mute*/
{ KE_KEY, 0x109, { KEY_MUTE} },
/* Mic mute */ /* Mic mute */
{ KE_KEY, 0x150, { KEY_MICMUTE } }, { KE_KEY, 0x150, { KEY_MICMUTE } },
......
...@@ -141,6 +141,7 @@ static u8 gigabyte_wmi_detect_sensor_usability(struct wmi_device *wdev) ...@@ -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[] = { 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-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("B450M S2H V2"),
DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE AX V2"), DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE AX V2"),
DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE"), DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE"),
......
...@@ -90,6 +90,7 @@ enum hp_wmi_event_ids { ...@@ -90,6 +90,7 @@ enum hp_wmi_event_ids {
HPWMI_PEAKSHIFT_PERIOD = 0x0F, HPWMI_PEAKSHIFT_PERIOD = 0x0F,
HPWMI_BATTERY_CHARGE_PERIOD = 0x10, HPWMI_BATTERY_CHARGE_PERIOD = 0x10,
HPWMI_SANITIZATION_MODE = 0x17, HPWMI_SANITIZATION_MODE = 0x17,
HPWMI_OMEN_KEY = 0x1D,
HPWMI_SMART_EXPERIENCE_APP = 0x21, HPWMI_SMART_EXPERIENCE_APP = 0x21,
}; };
...@@ -216,6 +217,8 @@ static const struct key_entry hp_wmi_keymap[] = { ...@@ -216,6 +217,8 @@ static const struct key_entry hp_wmi_keymap[] = {
{ KE_KEY, 0x213b, { KEY_INFO } }, { KE_KEY, 0x213b, { KEY_INFO } },
{ KE_KEY, 0x2169, { KEY_ROTATE_DISPLAY } }, { KE_KEY, 0x2169, { KEY_ROTATE_DISPLAY } },
{ KE_KEY, 0x216a, { KEY_SETUP } }, { 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, 0x21a9, { KEY_TOUCHPAD_OFF } },
{ KE_KEY, 0x121a9, { KEY_TOUCHPAD_ON } }, { KE_KEY, 0x121a9, { KEY_TOUCHPAD_ON } },
{ KE_KEY, 0x231b, { KEY_HELP } }, { KE_KEY, 0x231b, { KEY_HELP } },
...@@ -548,7 +551,7 @@ static int __init hp_wmi_enable_hotkeys(void) ...@@ -548,7 +551,7 @@ static int __init hp_wmi_enable_hotkeys(void)
static int hp_wmi_set_block(void *data, bool blocked) 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 query = BIT(r + 8) | ((!blocked) << r);
int ret; int ret;
...@@ -810,6 +813,7 @@ static void hp_wmi_notify(u32 value, void *context) ...@@ -810,6 +813,7 @@ static void hp_wmi_notify(u32 value, void *context)
case HPWMI_SMART_ADAPTER: case HPWMI_SMART_ADAPTER:
break; break;
case HPWMI_BEZEL_BUTTON: case HPWMI_BEZEL_BUTTON:
case HPWMI_OMEN_KEY:
key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY); key_code = hp_wmi_read_int(HPWMI_HOTKEY_QUERY);
if (key_code < 0) if (key_code < 0)
break; break;
......
...@@ -10496,8 +10496,7 @@ static int dytc_profile_set(struct platform_profile_handler *pprof, ...@@ -10496,8 +10496,7 @@ static int dytc_profile_set(struct platform_profile_handler *pprof,
if (err) if (err)
goto unlock; goto unlock;
} }
} } else if (dytc_capabilities & BIT(DYTC_FC_PSC)) {
if (dytc_capabilities & BIT(DYTC_FC_PSC)) {
err = dytc_command(DYTC_SET_COMMAND(DYTC_FUNCTION_PSC, perfmode, 1), &output); err = dytc_command(DYTC_SET_COMMAND(DYTC_FUNCTION_PSC, perfmode, 1), &output);
if (err) if (err)
goto unlock; goto unlock;
...@@ -10525,14 +10524,16 @@ static void dytc_profile_refresh(void) ...@@ -10525,14 +10524,16 @@ static void dytc_profile_refresh(void)
err = dytc_command(DYTC_CMD_MMC_GET, &output); err = dytc_command(DYTC_CMD_MMC_GET, &output);
else else
err = dytc_cql_command(DYTC_CMD_GET, &output); 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); 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); mutex_unlock(&dytc_mutex);
if (err) if (err)
return; return;
funcmode = (output >> DYTC_GET_FUNCTION_BIT) & 0xF;
perfmode = (output >> DYTC_GET_MODE_BIT) & 0xF; perfmode = (output >> DYTC_GET_MODE_BIT) & 0xF;
convert_dytc_to_profile(funcmode, perfmode, &profile); convert_dytc_to_profile(funcmode, perfmode, &profile);
if (profile != dytc_current_profile) { if (profile != dytc_current_profile) {
......
...@@ -8,18 +8,118 @@ ...@@ -8,18 +8,118 @@
#define LINUX_APPLE_GMUX_H #define LINUX_APPLE_GMUX_H
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/io.h>
#include <linux/pnp.h>
#define GMUX_ACPI_HID "APP000B" #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) #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_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() - detect if gmux is built into the machine * apple_gmux_present() - check if gmux ACPI device is present
* *
* Drivers may use this to activate quirks specific to dual GPU MacBook Pros * 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. * 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. * with CONFIG_APPLE_GMUX, %false otherwise.
*/ */
static inline bool apple_gmux_present(void) static inline bool apple_gmux_present(void)
...@@ -34,6 +134,11 @@ static inline bool apple_gmux_present(void) ...@@ -34,6 +134,11 @@ static inline bool apple_gmux_present(void)
return false; return false;
} }
static inline bool apple_gmux_detect(struct pnp_dev *pnp_dev, bool *indexed_ret)
{
return false;
}
#endif /* !CONFIG_APPLE_GMUX */ #endif /* !CONFIG_APPLE_GMUX */
#endif /* LINUX_APPLE_GMUX_H */ #endif /* LINUX_APPLE_GMUX_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment