3 #include <linux/slab.h>
17 #define NOUVEAU_DSM_LED 0x02
18 #define NOUVEAU_DSM_LED_STATE 0x00
19 #define NOUVEAU_DSM_LED_OFF 0x10
20 #define NOUVEAU_DSM_LED_STAMINA 0x11
21 #define NOUVEAU_DSM_LED_SPEED 0x12
23 #define NOUVEAU_DSM_POWER 0x03
24 #define NOUVEAU_DSM_POWER_STATE 0x00
25 #define NOUVEAU_DSM_POWER_SPEED 0x01
26 #define NOUVEAU_DSM_POWER_STAMINA 0x02
28 #define NOUVEAU_DSM_OPTIMUS_FN 0x1A
29 #define NOUVEAU_DSM_OPTIMUS_ARGS 0x03000001
31 static struct nouveau_dsm_priv {
33 bool optimus_detected;
38 #define NOUVEAU_DSM_HAS_MUX 0x1
39 #define NOUVEAU_DSM_HAS_OPT 0x2
41 static const char nouveau_dsm_muid[] = {
42 0xA0, 0xA0, 0x95, 0x9D, 0x60, 0x00, 0x48, 0x4D,
43 0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
46 static const char nouveau_op_dsm_muid[] = {
47 0xF8, 0xD8, 0x86, 0xA4, 0xDA, 0x0B, 0x1B, 0x47,
48 0xA7, 0x2B, 0x60, 0x42, 0xA6, 0xB5, 0xBE, 0xE0,
63 params[0].buffer.length =
sizeof(nouveau_op_dsm_muid);
64 params[0].buffer.pointer = (
char *)nouveau_op_dsm_muid;
66 params[1].integer.value = 0x00000100;
70 params[3].buffer.length = 4;
72 for (i = 0; i < 4; i++)
73 args_buff[i] = (arg >> i * 8) & 0xFF;
74 params[3].buffer.pointer = args_buff;
85 if (obj->
integer.value == 0x80000002) {
90 if (obj->
buffer.length == 4 && result) {
92 *result |= obj->
buffer.pointer[0];
93 *result |= (obj->
buffer.pointer[1] << 8);
94 *result |= (obj->
buffer.pointer[2] << 16);
95 *result |= (obj->
buffer.pointer[3] << 24);
114 params[0].buffer.length =
sizeof(nouveau_dsm_muid);
115 params[0].buffer.pointer = (
char *)nouveau_dsm_muid;
117 params[1].integer.value = 0x00000102;
132 if (obj->
integer.value == 0x80000002)
136 if (obj->
buffer.length == 4 && result) {
138 *result |= obj->
buffer.pointer[0];
139 *result |= (obj->
buffer.pointer[1] << 8);
140 *result |= (obj->
buffer.pointer[2] << 16);
141 *result |= (obj->
buffer.pointer[3] << 24);
150 static int nouveau_test_dsm(
acpi_handle test_handle,
158 if (dsm_func(test_handle, 0, 0, &result))
163 return result & 1 && result & (1 << sfnc);
166 static int nouveau_dsm_switch_mux(
acpi_handle handle,
int mux_id)
188 if (!nouveau_dsm_priv.dsm_detected && nouveau_dsm_priv.optimus_detected)
204 if (!nouveau_dsm_priv.dsm_detected && nouveau_dsm_priv.optimus_detected)
207 return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state);
210 static int nouveau_dsm_get_client_id(
struct pci_dev *pdev)
217 if (pdev->
bus->number == 0)
224 .switchto = nouveau_dsm_switchto,
225 .power_state = nouveau_dsm_power_state,
226 .get_client_id = nouveau_dsm_get_client_id,
229 static int nouveau_dsm_pci_probe(
struct pci_dev *pdev)
235 dhandle = DEVICE_ACPI_HANDLE(&pdev->
dev);
247 if (nouveau_test_dsm(dhandle, nouveau_optimus_dsm,
252 nouveau_dsm_priv.dhandle = dhandle;
257 static bool nouveau_dsm_detect(
void)
259 char acpi_method_name[255] = { 0 };
273 printk(
"MXM: GUID detected in BIOS\n");
279 retval = nouveau_dsm_pci_probe(pdev);
286 if (vga_count == 2 && has_dsm && guid_valid) {
289 printk(
KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n",
291 nouveau_dsm_priv.dsm_detected =
true;
295 if (has_optimus == 1) {
298 printk(
KERN_INFO "VGA switcheroo: detected Optimus DSM method %s handle\n",
300 nouveau_dsm_priv.optimus_detected =
true;
311 r = nouveau_dsm_detect();
322 if (!nouveau_dsm_priv.optimus_detected)
331 if (nouveau_dsm_priv.optimus_detected || nouveau_dsm_priv.dsm_detected)
345 rom_arg.pointer = &rom_arg_elements[0];
348 rom_arg_elements[0].integer.value =
offset;
351 rom_arg_elements[1].integer.value = len;
369 if (!nouveau_dsm_priv.dsm_detected && !nouveau_dsm_priv.optimus_detected)
372 dhandle = DEVICE_ACPI_HANDLE(&pdev->
dev);
380 nouveau_dsm_priv.rom_handle = rom_handle;
386 return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len);
392 struct acpi_device *acpidev;
406 handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev);