Support Optimus machines through WMMX (GH-2)
This should finally support machines like the Lenovo Y570. WMMX methods should be more reliable than direct DSM probing so let's try that before calling DSM directly.
This commit is contained in:
parent
7fd02221b2
commit
0ec41fa2da
28
bbswitch.c
28
bbswitch.c
@ -44,7 +44,7 @@ static const char acpi_optimus_dsm_muid[16] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define MXM_WMMX_GUID "F6CB5C3C-9CAE-4EBD-B577-931EA32A2CC0"
|
#define MXM_WMMX_GUID "F6CB5C3C-9CAE-4EBD-B577-931EA32A2CC0"
|
||||||
#define MXM_WMMX_FUNC_DSM 0x4D53445F /* NVIDIA DSM */
|
#define MXM_WMMX_FUNC_DSM 0x4D53445F /* NVIDIA/Optimus DSM */
|
||||||
static const char acpi_nvidia_dsm_muid[16] = {
|
static const char acpi_nvidia_dsm_muid[16] = {
|
||||||
0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D,
|
0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D,
|
||||||
0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4
|
0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4
|
||||||
@ -73,6 +73,7 @@ enum dsm_type {
|
|||||||
DSM_TYPE_OPTIMUS,
|
DSM_TYPE_OPTIMUS,
|
||||||
DSM_TYPE_NVIDIA,
|
DSM_TYPE_NVIDIA,
|
||||||
/* _DSM call through a WMI MX method */
|
/* _DSM call through a WMI MX method */
|
||||||
|
DSM_TYPE_OPTIMUS_WMI,
|
||||||
DSM_TYPE_NVIDIA_WMI,
|
DSM_TYPE_NVIDIA_WMI,
|
||||||
};
|
};
|
||||||
static enum dsm_type dsm_type = DSM_TYPE_UNSUPPORTED;
|
static enum dsm_type dsm_type = DSM_TYPE_UNSUPPORTED;
|
||||||
@ -220,10 +221,9 @@ static int has_wmi_func(const char muid[16], int revid, int sfnc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int bbswitch_optimus_dsm(void) {
|
static int bbswitch_optimus_dsm(void) {
|
||||||
|
char args[] = {1, 0, 0, 3};
|
||||||
|
u32 result = 0;
|
||||||
if (dsm_type == DSM_TYPE_OPTIMUS) {
|
if (dsm_type == DSM_TYPE_OPTIMUS) {
|
||||||
char args[] = {1, 0, 0, 3};
|
|
||||||
u32 result = 0;
|
|
||||||
|
|
||||||
if (acpi_call_dsm(dis_handle, acpi_optimus_dsm_muid, 0x100, 0x1A, args,
|
if (acpi_call_dsm(dis_handle, acpi_optimus_dsm_muid, 0x100, 0x1A, args,
|
||||||
&result)) {
|
&result)) {
|
||||||
// failure
|
// failure
|
||||||
@ -231,6 +231,13 @@ static int bbswitch_optimus_dsm(void) {
|
|||||||
}
|
}
|
||||||
printk(KERN_DEBUG "bbswitch: Result of Optimus _DSM call: %08X\n",
|
printk(KERN_DEBUG "bbswitch: Result of Optimus _DSM call: %08X\n",
|
||||||
result);
|
result);
|
||||||
|
} else if (dsm_type == DSM_TYPE_OPTIMUS_WMI) {
|
||||||
|
if (wmmx_call(acpi_optimus_dsm_muid, 0x100, 0x1A, args, &result)) {
|
||||||
|
// failure
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
printk(KERN_DEBUG "bbswitch: Result of WMMX call for Optimus: %08X\n",
|
||||||
|
result);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -446,13 +453,20 @@ static int __init bbswitch_init(void) {
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_dsm_func(acpi_optimus_dsm_muid, 0x100, 0x1A)) {
|
if (has_wmi_func(acpi_optimus_dsm_muid, 0x100, 0x1A)) {
|
||||||
dsm_type = DSM_TYPE_OPTIMUS;
|
dsm_type = DSM_TYPE_OPTIMUS_WMI;
|
||||||
printk(KERN_INFO "bbswitch: detected an Optimus _DSM function\n");
|
printk(KERN_INFO "bbswitch: detected an Optimus WMMX function\n");
|
||||||
} else if (has_wmi_func(acpi_nvidia_dsm_muid, 0x102, 0x3)) {
|
} else if (has_wmi_func(acpi_nvidia_dsm_muid, 0x102, 0x3)) {
|
||||||
dsm_type = DSM_TYPE_NVIDIA_WMI;
|
dsm_type = DSM_TYPE_NVIDIA_WMI;
|
||||||
printk(KERN_INFO "bbswitch: detected a nVidia WMMX function\n");
|
printk(KERN_INFO "bbswitch: detected a nVidia WMMX function\n");
|
||||||
|
} else if (has_dsm_func(acpi_optimus_dsm_muid, 0x100, 0x1A)) {
|
||||||
|
/* necessary for at least Lenovo Ideapad Z570 which does not have the
|
||||||
|
* WMMX method */
|
||||||
|
dsm_type = DSM_TYPE_OPTIMUS;
|
||||||
|
printk(KERN_INFO "bbswitch: detected an Optimus _DSM function\n");
|
||||||
} else if (has_dsm_func(acpi_nvidia_dsm_muid, 0x102, 0x3)) {
|
} else if (has_dsm_func(acpi_nvidia_dsm_muid, 0x102, 0x3)) {
|
||||||
|
/* necessary for at least Dell XPS L501X bios A08 which does not have
|
||||||
|
* the WMMX method */
|
||||||
dsm_type = DSM_TYPE_NVIDIA;
|
dsm_type = DSM_TYPE_NVIDIA;
|
||||||
printk(KERN_INFO "bbswitch: detected a nVidia _DSM function\n");
|
printk(KERN_INFO "bbswitch: detected a nVidia _DSM function\n");
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user