* properly check for _DSM function support and Optimus support for vga_switcheroo @ 2011-12-17 12:14 Lekensteyn [not found] ` <CALBR5ZxR9iuvT57bDZ8yW9ZkZjuoUhBTYw4HBsmsiwoRi4gSkw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 9+ messages in thread From: Lekensteyn @ 2011-12-17 12:14 UTC (permalink / raw) To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW [-- Attachment #1.1: Type: text/plain, Size: 892 bytes --] Hello guys, I've prepared a patch based on my findings for the bbswitch module (https://github.com/Lekensteyn/acpi-stuff/tree/master/bbswitch). This adds a proper check whether a _DSM function is supported or not and make OFF / ON for vga_switcheroo work for nVidia Optimus models. The patch is based against the mainline kernel. It has been tested on my Clevo B7130 laptop running kernel 3.2 which has a GT425M dGPU: # cat /sys/kernel/debug/vgaswitcheroo/switch 0:IGD:+:Pwr:0000:00:02.0 1:DIS: :Pwr:0000:01:00.0 # tee /sys/kernel/debug/vgaswitcheroo/switch <<<OFF OFF # cat /sys/kernel/debug/vgaswitcheroo/switch 0:IGD:+:Pwr:0000:00:02.0 1:DIS: :Off:0000:01:00.0 # tee /sys/kernel/debug/vgaswitcheroo/switch <<<ON ON # cat /sys/kernel/debug/vgaswitcheroo/switch 0:IGD:+:Pwr:0000:00:02.0 1:DIS: :Pwr:0000:01:00.0 The iGPU/dGPU LEDS on the keyboard also change as a result. Regards, Peter [-- Attachment #1.2: Type: text/html, Size: 1084 bytes --] [-- Attachment #2: nouveau-switcheroo-optimus.patch --] [-- Type: text/x-diff, Size: 8640 bytes --] From b6e1b5b316ae17ccb7def0a8b38e69ad4c99c55d Mon Sep 17 00:00:00 2001 From: Peter Lekensteyn <lekensteyn@gmail.com> Date: Sat, 17 Dec 2011 12:53:43 +0100 Subject: [PATCH 1/2] nouveau: properly check for _DSM function support According to the ACPI spec version 4, section 9.14.1, _DSM functions must return a value with the first bit enabled if any DSM functions are supported for the given UUID and revision ID. For a given function index n to be marked supported, bit n must be enabled. Signed-off-by: Peter Lekensteyn <lekensteyn@gmail.com> --- drivers/gpu/drm/nouveau/nouveau_acpi.c | 35 ++++++++++++++++++++----------- 1 files changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 525744d..96756d0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -18,12 +18,6 @@ #include <linux/vga_switcheroo.h> -#define NOUVEAU_DSM_SUPPORTED 0x00 -#define NOUVEAU_DSM_SUPPORTED_FUNCTIONS 0x00 - -#define NOUVEAU_DSM_ACTIVE 0x01 -#define NOUVEAU_DSM_ACTIVE_QUERY 0x00 - #define NOUVEAU_DSM_LED 0x02 #define NOUVEAU_DSM_LED_STATE 0x00 #define NOUVEAU_DSM_LED_OFF 0x10 @@ -35,6 +29,7 @@ #define NOUVEAU_DSM_POWER_SPEED 0x01 #define NOUVEAU_DSM_POWER_STAMINA 0x02 +#define NOUVEAU_DSM_OPTIMUS_FN 0x1A static struct nouveau_dsm_priv { bool dsm_detected; bool optimus_detected; @@ -148,6 +143,23 @@ static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result) return 0; } +/* Returns 1 if a DSM function is usable and 0 otherwise */ +static int nouveau_test_dsm(acpi_handle test_handle, + int (*dsm_func)(acpi_handle, int, int, uint32_t *), + int sfnc) +{ + u32 result = 0; + + /* Function 0 returns a Buffer containing available functions. The args + * parameter is ignored for function 0, so just put 0 in it */ + if (dsm_func(test_handle, 0, 0, &result)) + return 0; + + /* ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. If + * the n-th bit is enabled, function n is supported */ + return result & 1 && result & (1 << sfnc); +} + static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) { mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); @@ -212,8 +224,7 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) { acpi_handle dhandle, nvidia_handle; acpi_status status; - int ret, retval = 0; - uint32_t result; + int retval = 0; dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); if (!dhandle) @@ -224,13 +235,11 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) return false; } - ret = nouveau_dsm(dhandle, NOUVEAU_DSM_SUPPORTED, - NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result); - if (ret == 0) + if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) retval |= NOUVEAU_DSM_HAS_MUX; - ret = nouveau_optimus_dsm(dhandle, 0, 0, &result); - if (ret == 0) + if (nouveau_test_dsm(dhandle, nouveau_optimus_dsm, + NOUVEAU_DSM_OPTIMUS_FN)) retval |= NOUVEAU_DSM_HAS_OPT; if (retval) -- 1.7.5.4 From 58c5de8578e387ce0dbd8a77f9cbc36b2f5823a1 Mon Sep 17 00:00:00 2001 From: Peter Lekensteyn <lekensteyn@gmail.com> Date: Sat, 17 Dec 2011 12:54:04 +0100 Subject: [PATCH 2/2] nouveau: Support Optimus models for vga_switcheroo Newer nVidia cards with Optimus do not support/use the DSM switching functions. Instead, it require a DSM function to be called prior to bringing a device into D3 state. No other _DSM calls are necessary before/after enabling/disabling a device. Switching between discrete and integrated GPU is not supported by this Optimus _DSM call, therefore return on the switching method. Signed-off-by: Peter Lekensteyn <lekensteyn@gmail.com> --- drivers/gpu/drm/nouveau/nouveau_acpi.c | 44 +++++++++++++++++++++++++++--- drivers/gpu/drm/nouveau/nouveau_drv.h | 1 + drivers/gpu/drm/nouveau/nouveau_state.c | 1 + 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 96756d0..7814a76 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -30,6 +30,8 @@ #define NOUVEAU_DSM_POWER_STAMINA 0x02 #define NOUVEAU_DSM_OPTIMUS_FN 0x1A +#define NOUVEAU_DSM_OPTIMUS_ARGS 0x03000001 + static struct nouveau_dsm_priv { bool dsm_detected; bool optimus_detected; @@ -56,7 +58,8 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t * struct acpi_object_list input; union acpi_object params[4]; union acpi_object *obj; - int err; + int i, err; + char args_buff[4]; input.count = 4; input.pointer = params; @@ -68,7 +71,11 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t * params[2].type = ACPI_TYPE_INTEGER; params[2].integer.value = func; params[3].type = ACPI_TYPE_BUFFER; - params[3].buffer.length = 0; + params[3].buffer.length = 4; + /* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */ + for (i = 0; i < 4; i++) + args_buff[i] = (arg >> i * 8) & 0xFF; + params[3].buffer.pointer = args_buff; err = acpi_evaluate_object(handle, "_DSM", &input, &output); if (err) { @@ -180,6 +187,10 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id) { + /* perhaps the _DSM functions are mutually exclusive, but prepare for + * the future */ + if (!nouveau_dsm_priv.dsm_detected && nouveau_dsm_priv.optimus_detected) + return 0; if (id == VGA_SWITCHEROO_IGD) return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_STAMINA); else @@ -192,6 +203,11 @@ static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id, if (id == VGA_SWITCHEROO_IGD) return 0; + /* Optimus laptops have the card already disabled in + * nouveau_switcheroo_set_state */ + if (!nouveau_dsm_priv.dsm_detected && nouveau_dsm_priv.optimus_detected) + return 0; + return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state); } @@ -278,15 +294,22 @@ static bool nouveau_dsm_detect(void) } if (vga_count == 2 && has_dsm && guid_valid) { - acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer); + acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, + &buffer); printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n", - acpi_method_name); + acpi_method_name); nouveau_dsm_priv.dsm_detected = true; ret = true; } - if (has_optimus == 1) + if (has_optimus == 1) { + acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, + &buffer); + printk(KERN_INFO "VGA switcheroo: detected Optimus DSM method %s handle\n", + acpi_method_name); nouveau_dsm_priv.optimus_detected = true; + ret = true; + } return ret; } @@ -302,6 +325,17 @@ void nouveau_register_dsm_handler(void) vga_switcheroo_register_handler(&nouveau_dsm_handler); } +/* Must be called for Optimus models before the card can be turned off */ +void nouveau_switcheroo_optimus_dsm(void) +{ + u32 result = 0; + if (!nouveau_dsm_priv.optimus_detected) + return; + + nouveau_optimus_dsm(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_OPTIMUS_FN, + NOUVEAU_DSM_OPTIMUS_ARGS, &result); +} + void nouveau_unregister_dsm_handler(void) { vga_switcheroo_unregister_handler(); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 4c0be3a..061577c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1041,6 +1041,7 @@ extern int nouveau_dma_wait(struct nouveau_channel *, int slots, int size); #if defined(CONFIG_ACPI) void nouveau_register_dsm_handler(void); void nouveau_unregister_dsm_handler(void); +void nouveau_switcheroo_optimus_dsm(void); int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len); bool nouveau_acpi_rom_supported(struct pci_dev *pdev); int nouveau_acpi_edid(struct drm_device *, struct drm_connector *); diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index d8831ab..ef270cf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -525,6 +525,7 @@ static void nouveau_switcheroo_set_state(struct pci_dev *pdev, printk(KERN_ERR "VGA switcheroo: switched nouveau off\n"); dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; drm_kms_helper_poll_disable(dev); + nouveau_switcheroo_optimus_dsm(); nouveau_pci_suspend(pdev, pmm); dev->switch_power_state = DRM_SWITCH_POWER_OFF; } -- 1.7.5.4 [-- Attachment #3: Type: text/plain, Size: 181 bytes --] _______________________________________________ Nouveau mailing list Nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org http://lists.freedesktop.org/mailman/listinfo/nouveau ^ permalink raw reply related [flat|nested] 9+ messages in thread
[parent not found: <CALBR5ZxR9iuvT57bDZ8yW9ZkZjuoUhBTYw4HBsmsiwoRi4gSkw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* properly check for _DSM function support and Optimus support for vga_switcheroo [not found] ` <CALBR5ZxR9iuvT57bDZ8yW9ZkZjuoUhBTYw4HBsmsiwoRi4gSkw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2011-12-17 22:50 ` Lekensteyn [not found] ` <CALBR5ZyE2ZRX7eFBhooB22e9BRf0f3H2xqtvXB2iwe8nvKKnvw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 9+ messages in thread From: Lekensteyn @ 2011-12-17 22:50 UTC (permalink / raw) To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW [-- Attachment #1.1: Type: text/plain, Size: 966 bytes --] Hello guys, I've prepared a patch based on my findings for the bbswitch module (https://github.com/Lekensteyn/acpi-stuff/tree/master/bbswitch). This adds a proper check whether a _DSM function is supported or not and make OFF / ON for vga_switcheroo work for nVidia Optimus models. The patch is based against the mainline kernel. It has been tested on my Clevo B7130 laptop running kernel 3.2 which has a GT425M dGPU: # cat /sys/kernel/debug/vgaswitcheroo/switch 0:IGD:+:Pwr:0000:00:02.0 1:DIS: :Pwr:0000:01:00.0 # tee /sys/kernel/debug/vgaswitcheroo/switch <<<OFF OFF # cat /sys/kernel/debug/vgaswitcheroo/switch 0:IGD:+:Pwr:0000:00:02.0 1:DIS: :Off:0000:01:00.0 # tee /sys/kernel/debug/vgaswitcheroo/switch <<<ON ON # cat /sys/kernel/debug/vgaswitcheroo/switch 0:IGD:+:Pwr:0000:00:02.0 1:DIS: :Pwr:0000:01:00.0 The iGPU/dGPU LEDS on the keyboard also change as a result. A second patch to make the device stay off after suspend is in progress. Regards, Peter [-- Attachment #1.2: Type: text/html, Size: 1225 bytes --] [-- Attachment #2: nouveau-switcheroo-optimus.patch --] [-- Type: text/x-diff, Size: 8640 bytes --] From b6e1b5b316ae17ccb7def0a8b38e69ad4c99c55d Mon Sep 17 00:00:00 2001 From: Peter Lekensteyn <lekensteyn@gmail.com> Date: Sat, 17 Dec 2011 12:53:43 +0100 Subject: [PATCH 1/2] nouveau: properly check for _DSM function support According to the ACPI spec version 4, section 9.14.1, _DSM functions must return a value with the first bit enabled if any DSM functions are supported for the given UUID and revision ID. For a given function index n to be marked supported, bit n must be enabled. Signed-off-by: Peter Lekensteyn <lekensteyn@gmail.com> --- drivers/gpu/drm/nouveau/nouveau_acpi.c | 35 ++++++++++++++++++++----------- 1 files changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 525744d..96756d0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -18,12 +18,6 @@ #include <linux/vga_switcheroo.h> -#define NOUVEAU_DSM_SUPPORTED 0x00 -#define NOUVEAU_DSM_SUPPORTED_FUNCTIONS 0x00 - -#define NOUVEAU_DSM_ACTIVE 0x01 -#define NOUVEAU_DSM_ACTIVE_QUERY 0x00 - #define NOUVEAU_DSM_LED 0x02 #define NOUVEAU_DSM_LED_STATE 0x00 #define NOUVEAU_DSM_LED_OFF 0x10 @@ -35,6 +29,7 @@ #define NOUVEAU_DSM_POWER_SPEED 0x01 #define NOUVEAU_DSM_POWER_STAMINA 0x02 +#define NOUVEAU_DSM_OPTIMUS_FN 0x1A static struct nouveau_dsm_priv { bool dsm_detected; bool optimus_detected; @@ -148,6 +143,23 @@ static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result) return 0; } +/* Returns 1 if a DSM function is usable and 0 otherwise */ +static int nouveau_test_dsm(acpi_handle test_handle, + int (*dsm_func)(acpi_handle, int, int, uint32_t *), + int sfnc) +{ + u32 result = 0; + + /* Function 0 returns a Buffer containing available functions. The args + * parameter is ignored for function 0, so just put 0 in it */ + if (dsm_func(test_handle, 0, 0, &result)) + return 0; + + /* ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. If + * the n-th bit is enabled, function n is supported */ + return result & 1 && result & (1 << sfnc); +} + static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) { mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); @@ -212,8 +224,7 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) { acpi_handle dhandle, nvidia_handle; acpi_status status; - int ret, retval = 0; - uint32_t result; + int retval = 0; dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); if (!dhandle) @@ -224,13 +235,11 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) return false; } - ret = nouveau_dsm(dhandle, NOUVEAU_DSM_SUPPORTED, - NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result); - if (ret == 0) + if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) retval |= NOUVEAU_DSM_HAS_MUX; - ret = nouveau_optimus_dsm(dhandle, 0, 0, &result); - if (ret == 0) + if (nouveau_test_dsm(dhandle, nouveau_optimus_dsm, + NOUVEAU_DSM_OPTIMUS_FN)) retval |= NOUVEAU_DSM_HAS_OPT; if (retval) -- 1.7.5.4 From 58c5de8578e387ce0dbd8a77f9cbc36b2f5823a1 Mon Sep 17 00:00:00 2001 From: Peter Lekensteyn <lekensteyn@gmail.com> Date: Sat, 17 Dec 2011 12:54:04 +0100 Subject: [PATCH 2/2] nouveau: Support Optimus models for vga_switcheroo Newer nVidia cards with Optimus do not support/use the DSM switching functions. Instead, it require a DSM function to be called prior to bringing a device into D3 state. No other _DSM calls are necessary before/after enabling/disabling a device. Switching between discrete and integrated GPU is not supported by this Optimus _DSM call, therefore return on the switching method. Signed-off-by: Peter Lekensteyn <lekensteyn@gmail.com> --- drivers/gpu/drm/nouveau/nouveau_acpi.c | 44 +++++++++++++++++++++++++++--- drivers/gpu/drm/nouveau/nouveau_drv.h | 1 + drivers/gpu/drm/nouveau/nouveau_state.c | 1 + 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 96756d0..7814a76 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -30,6 +30,8 @@ #define NOUVEAU_DSM_POWER_STAMINA 0x02 #define NOUVEAU_DSM_OPTIMUS_FN 0x1A +#define NOUVEAU_DSM_OPTIMUS_ARGS 0x03000001 + static struct nouveau_dsm_priv { bool dsm_detected; bool optimus_detected; @@ -56,7 +58,8 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t * struct acpi_object_list input; union acpi_object params[4]; union acpi_object *obj; - int err; + int i, err; + char args_buff[4]; input.count = 4; input.pointer = params; @@ -68,7 +71,11 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t * params[2].type = ACPI_TYPE_INTEGER; params[2].integer.value = func; params[3].type = ACPI_TYPE_BUFFER; - params[3].buffer.length = 0; + params[3].buffer.length = 4; + /* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */ + for (i = 0; i < 4; i++) + args_buff[i] = (arg >> i * 8) & 0xFF; + params[3].buffer.pointer = args_buff; err = acpi_evaluate_object(handle, "_DSM", &input, &output); if (err) { @@ -180,6 +187,10 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id) { + /* perhaps the _DSM functions are mutually exclusive, but prepare for + * the future */ + if (!nouveau_dsm_priv.dsm_detected && nouveau_dsm_priv.optimus_detected) + return 0; if (id == VGA_SWITCHEROO_IGD) return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_STAMINA); else @@ -192,6 +203,11 @@ static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id, if (id == VGA_SWITCHEROO_IGD) return 0; + /* Optimus laptops have the card already disabled in + * nouveau_switcheroo_set_state */ + if (!nouveau_dsm_priv.dsm_detected && nouveau_dsm_priv.optimus_detected) + return 0; + return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state); } @@ -278,15 +294,22 @@ static bool nouveau_dsm_detect(void) } if (vga_count == 2 && has_dsm && guid_valid) { - acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer); + acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, + &buffer); printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n", - acpi_method_name); + acpi_method_name); nouveau_dsm_priv.dsm_detected = true; ret = true; } - if (has_optimus == 1) + if (has_optimus == 1) { + acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, + &buffer); + printk(KERN_INFO "VGA switcheroo: detected Optimus DSM method %s handle\n", + acpi_method_name); nouveau_dsm_priv.optimus_detected = true; + ret = true; + } return ret; } @@ -302,6 +325,17 @@ void nouveau_register_dsm_handler(void) vga_switcheroo_register_handler(&nouveau_dsm_handler); } +/* Must be called for Optimus models before the card can be turned off */ +void nouveau_switcheroo_optimus_dsm(void) +{ + u32 result = 0; + if (!nouveau_dsm_priv.optimus_detected) + return; + + nouveau_optimus_dsm(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_OPTIMUS_FN, + NOUVEAU_DSM_OPTIMUS_ARGS, &result); +} + void nouveau_unregister_dsm_handler(void) { vga_switcheroo_unregister_handler(); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 4c0be3a..061577c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1041,6 +1041,7 @@ extern int nouveau_dma_wait(struct nouveau_channel *, int slots, int size); #if defined(CONFIG_ACPI) void nouveau_register_dsm_handler(void); void nouveau_unregister_dsm_handler(void); +void nouveau_switcheroo_optimus_dsm(void); int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len); bool nouveau_acpi_rom_supported(struct pci_dev *pdev); int nouveau_acpi_edid(struct drm_device *, struct drm_connector *); diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index d8831ab..ef270cf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -525,6 +525,7 @@ static void nouveau_switcheroo_set_state(struct pci_dev *pdev, printk(KERN_ERR "VGA switcheroo: switched nouveau off\n"); dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; drm_kms_helper_poll_disable(dev); + nouveau_switcheroo_optimus_dsm(); nouveau_pci_suspend(pdev, pmm); dev->switch_power_state = DRM_SWITCH_POWER_OFF; } -- 1.7.5.4 [-- Attachment #3: Type: text/plain, Size: 181 bytes --] _______________________________________________ Nouveau mailing list Nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org http://lists.freedesktop.org/mailman/listinfo/nouveau ^ permalink raw reply related [flat|nested] 9+ messages in thread
[parent not found: <CALBR5ZyE2ZRX7eFBhooB22e9BRf0f3H2xqtvXB2iwe8nvKKnvw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: properly check for _DSM function support and Optimus support for vga_switcheroo [not found] ` <CALBR5ZyE2ZRX7eFBhooB22e9BRf0f3H2xqtvXB2iwe8nvKKnvw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2011-12-19 4:39 ` Omar Andrés Zapata Mesa [not found] ` <CAOB9epp8EdpetsPStfdnGNx5-2dKi42j3DQiVKN_dzMdFcssWA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 9+ messages in thread From: Omar Andrés Zapata Mesa @ 2011-12-19 4:39 UTC (permalink / raw) To: Lekensteyn; +Cc: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW [-- Attachment #1.1: Type: text/plain, Size: 1963 bytes --] Tested on toshiba m645 optimus intel/nvidia 310m output bbswitch: Found discrete VGA device 0000:01:00.0: \_SB_.PCI0.P0P2.VGA_ [21832.787656] bbswitch: detected an Optimus _DSM function [21832.787664] bbswitch: Succesfully loaded. Discrete card 0000:01:00.0 is on but dont work nvidia video card. do it work with not mux optimus? On Sat, Dec 17, 2011 at 5:50 PM, Lekensteyn <lekensteyn-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > Hello guys, > > I've prepared a patch based on my findings for the bbswitch module > (https://github.com/Lekensteyn/acpi-stuff/tree/master/bbswitch). This > adds a proper > check whether a _DSM function is supported or not and make OFF / ON for > vga_switcheroo work for nVidia Optimus models. The patch is based against > the > mainline kernel. > > It has been tested on my Clevo B7130 laptop running kernel 3.2 which has a > GT425M > dGPU: > # cat /sys/kernel/debug/vgaswitcheroo/switch > 0:IGD:+:Pwr:0000:00:02.0 > 1:DIS: :Pwr:0000:01:00.0 > # tee /sys/kernel/debug/vgaswitcheroo/switch <<<OFF > OFF > # cat /sys/kernel/debug/vgaswitcheroo/switch > 0:IGD:+:Pwr:0000:00:02.0 > 1:DIS: :Off:0000:01:00.0 > # tee /sys/kernel/debug/vgaswitcheroo/switch <<<ON > ON > # cat /sys/kernel/debug/vgaswitcheroo/switch > 0:IGD:+:Pwr:0000:00:02.0 > 1:DIS: :Pwr:0000:01:00.0 > > The iGPU/dGPU LEDS on the keyboard also change as a result. > > A second patch to make the device stay off after suspend is in progress. > > Regards, > Peter > > > _______________________________________________ > Nouveau mailing list > Nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org > http://lists.freedesktop.org/mailman/listinfo/nouveau > > -- Omar Andres Zapata Mesa Fundamental Interaction Phenomenology Gruop (Gfif) Head Developer http://gfif.udea.edu.co Gfif Developers (Gfif Dev) Division of computer science http://gfifdev.udea.edu.co System Engineering Student Universidad de Antioquia At Medellin - Colombia Usuario Linux #490962 [-- Attachment #1.2: Type: text/html, Size: 3797 bytes --] [-- Attachment #2: Type: text/plain, Size: 181 bytes --] _______________________________________________ Nouveau mailing list Nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org http://lists.freedesktop.org/mailman/listinfo/nouveau ^ permalink raw reply [flat|nested] 9+ messages in thread
[parent not found: <CAOB9epp8EdpetsPStfdnGNx5-2dKi42j3DQiVKN_dzMdFcssWA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: properly check for _DSM function support and Optimus support for vga_switcheroo [not found] ` <CAOB9epp8EdpetsPStfdnGNx5-2dKi42j3DQiVKN_dzMdFcssWA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2011-12-19 9:44 ` Lekensteyn [not found] ` <CALBR5Zw0gEDqKrSUF3R30tSSC6DUgfhVm0Y1Mp60e4bB4ObijQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 9+ messages in thread From: Lekensteyn @ 2011-12-19 9:44 UTC (permalink / raw) To: Omar Andrés Zapata Mesa; +Cc: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW [-- Attachment #1.1: Type: text/plain, Size: 2508 bytes --] It's works on a muxless Clevo B7130 intel / nvidia GT425M. It has also been tested on the legacy optimus call, although that crashed X http://pastebin.com/9Sum3tT3 That bug is said to be fixed http://cgit.freedesktop.org/xorg/xserver/commit/?id=fb22a408c69a84f81905147de9e82cf66ffb6eb2 2011/12/19 Omar Andrés Zapata Mesa <andresete.chaos-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > Tested on toshiba m645 optimus intel/nvidia 310m > output > bbswitch: Found discrete VGA device 0000:01:00.0: \_SB_.PCI0.P0P2.VGA_ > [21832.787656] bbswitch: detected an Optimus _DSM function > [21832.787664] bbswitch: Succesfully loaded. Discrete card 0000:01:00.0 is > on > but dont work nvidia video card. do it work with not mux optimus? > > > On Sat, Dec 17, 2011 at 5:50 PM, Lekensteyn <lekensteyn-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > >> Hello guys, >> >> I've prepared a patch based on my findings for the bbswitch module >> (https://github.com/Lekensteyn/acpi-stuff/tree/master/bbswitch). This >> adds a proper >> check whether a _DSM function is supported or not and make OFF / ON for >> vga_switcheroo work for nVidia Optimus models. The patch is based against >> the >> mainline kernel. >> >> It has been tested on my Clevo B7130 laptop running kernel 3.2 which has >> a GT425M >> dGPU: >> # cat /sys/kernel/debug/vgaswitcheroo/switch >> 0:IGD:+:Pwr:0000:00:02.0 >> 1:DIS: :Pwr:0000:01:00.0 >> # tee /sys/kernel/debug/vgaswitcheroo/switch <<<OFF >> OFF >> # cat /sys/kernel/debug/vgaswitcheroo/switch >> 0:IGD:+:Pwr:0000:00:02.0 >> 1:DIS: :Off:0000:01:00.0 >> # tee /sys/kernel/debug/vgaswitcheroo/switch <<<ON >> ON >> # cat /sys/kernel/debug/vgaswitcheroo/switch >> 0:IGD:+:Pwr:0000:00:02.0 >> 1:DIS: :Pwr:0000:01:00.0 >> >> The iGPU/dGPU LEDS on the keyboard also change as a result. >> >> A second patch to make the device stay off after suspend is in progress. >> >> Regards, >> Peter >> >> >> _______________________________________________ >> Nouveau mailing list >> Nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org >> http://lists.freedesktop.org/mailman/listinfo/nouveau >> >> > > > -- > Omar Andres Zapata Mesa > Fundamental Interaction Phenomenology Gruop (Gfif) > Head Developer > http://gfif.udea.edu.co > Gfif Developers (Gfif Dev) > Division of computer science > http://gfifdev.udea.edu.co > System Engineering Student > Universidad de Antioquia At Medellin - Colombia > Usuario Linux #490962 > > [-- Attachment #1.2: Type: text/html, Size: 4759 bytes --] [-- Attachment #2: Type: text/plain, Size: 181 bytes --] _______________________________________________ Nouveau mailing list Nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org http://lists.freedesktop.org/mailman/listinfo/nouveau ^ permalink raw reply [flat|nested] 9+ messages in thread
[parent not found: <CALBR5Zw0gEDqKrSUF3R30tSSC6DUgfhVm0Y1Mp60e4bB4ObijQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: properly check for _DSM function support and Optimus support for vga_switcheroo [not found] ` <CALBR5Zw0gEDqKrSUF3R30tSSC6DUgfhVm0Y1Mp60e4bB4ObijQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2011-12-19 10:04 ` Gianluca Cecchi [not found] ` <CAG2kNCwBwRJ_VrS9NHnmGvOTTLuwmBKd5kG8OknJG+f20Kvqsg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 9+ messages in thread From: Gianluca Cecchi @ 2011-12-19 10:04 UTC (permalink / raw) To: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW >> On Sat, Dec 17, 2011 at 5:50 PM, Lekensteyn <lekensteyn-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: >>> >>> Hello guys, >>> >>> I've prepared a patch based on my findings for the bbswitch module >>> (https://github.com/Lekensteyn/acpi-stuff/tree/master/bbswitch). This >>> adds a proper >>> check whether a _DSM function is supported or not and make OFF / ON for >>> vga_switcheroo work for nVidia Optimus models. The patch is based against >>> the >>> mainline kernel. >>> >>> It has been tested on my Clevo B7130 laptop running kernel 3.2 which has Hello, I have an Asus U36SD laptop with Optimus and Fedora 16 with kernel 3.1.5-6.fc16.x86_64 Any way I can test it? Currently I'm using acpi_call to switch off nvidia card and gain 4w for more battery life. [g.cecchi@ope46 ~]$ lspci -vnnn|grep -i vga 00:02.0 VGA compatible controller [0300]: Intel Corporation 2nd Generation Core Processor Family Integrated Graphics Controller [8086:0126] (rev 09) (prog-if 00 [VGA controller]) 01:00.0 VGA compatible controller [0300]: nVidia Corporation Device [10de:1050] (rev ff) (prog-if ff) What benefit would it give me? Chance to use nvidia for graphic related apps ? With nouveau andor nvidia proprietary driver? Thanks in advance for any pointer Gianluca ^ permalink raw reply [flat|nested] 9+ messages in thread
[parent not found: <CAG2kNCwBwRJ_VrS9NHnmGvOTTLuwmBKd5kG8OknJG+f20Kvqsg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: properly check for _DSM function support and Optimus support for vga_switcheroo [not found] ` <CAG2kNCwBwRJ_VrS9NHnmGvOTTLuwmBKd5kG8OknJG+f20Kvqsg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2011-12-19 13:26 ` Lekensteyn 2012-01-08 23:13 ` Lekensteyn 0 siblings, 1 reply; 9+ messages in thread From: Lekensteyn @ 2011-12-19 13:26 UTC (permalink / raw) To: Gianluca Cecchi; +Cc: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW [-- Attachment #1.1: Type: text/plain, Size: 2009 bytes --] A quickly written way to test this module is described for Ubuntu at http://pastebin.com/c5XqKSsW. Basically, you need to apply the patch on nouveau and rebuild the nouveau kernel module. A comparison of different methods that works for toggling the dGPU is available: https://github.com/Bumblebee-Project/Bumblebee/wiki/Comparison-of-PM-methods Regards, Lekensteyn On Mon, Dec 19, 2011 at 11:04 AM, Gianluca Cecchi <gianluca.cecchi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org > wrote: > >> On Sat, Dec 17, 2011 at 5:50 PM, Lekensteyn <lekensteyn-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > wrote: > >>> > >>> Hello guys, > >>> > >>> I've prepared a patch based on my findings for the bbswitch module > >>> (https://github.com/Lekensteyn/acpi-stuff/tree/master/bbswitch). This > >>> adds a proper > >>> check whether a _DSM function is supported or not and make OFF / ON for > >>> vga_switcheroo work for nVidia Optimus models. The patch is based > against > >>> the > >>> mainline kernel. > >>> > >>> It has been tested on my Clevo B7130 laptop running kernel 3.2 which > has > > Hello, > I have an Asus U36SD laptop with Optimus and Fedora 16 with kernel > 3.1.5-6.fc16.x86_64 > Any way I can test it? > Currently I'm using acpi_call to switch off nvidia card and gain 4w > for more battery life. > > [g.cecchi@ope46 ~]$ lspci -vnnn|grep -i vga > 00:02.0 VGA compatible controller [0300]: Intel Corporation 2nd > Generation Core Processor Family Integrated Graphics Controller > [8086:0126] (rev 09) (prog-if 00 [VGA controller]) > 01:00.0 VGA compatible controller [0300]: nVidia Corporation Device > [10de:1050] (rev ff) (prog-if ff) > > What benefit would it give me? Chance to use nvidia for graphic > related apps ? With nouveau andor nvidia proprietary driver? > Thanks in advance for any pointer > > Gianluca > _______________________________________________ > Nouveau mailing list > Nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org > http://lists.freedesktop.org/mailman/listinfo/nouveau > [-- Attachment #1.2: Type: text/html, Size: 3115 bytes --] [-- Attachment #2: Type: text/plain, Size: 181 bytes --] _______________________________________________ Nouveau mailing list Nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org http://lists.freedesktop.org/mailman/listinfo/nouveau ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: properly check for _DSM function support and Optimus support for vga_switcheroo 2011-12-19 13:26 ` Lekensteyn @ 2012-01-08 23:13 ` Lekensteyn [not found] ` <CALBR5Zxuwv-zBQfVr7By3su2rjWjcVapX7oCCfeybjBMPY9cbA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 0 siblings, 1 reply; 9+ messages in thread From: Lekensteyn @ 2012-01-08 23:13 UTC (permalink / raw) To: Gianluca Cecchi; +Cc: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW [-- Attachment #1.1: Type: text/plain, Size: 2379 bytes --] Any activity on this? The newly attached patch contains one difference with the previous one: a dummy function has been added to avoid an error if ACPI is disabled. Regards, Lekensteyn On Mon, Dec 19, 2011 at 2:26 PM, Lekensteyn <lekensteyn-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > A quickly written way to test this module is described for Ubuntu at > http://pastebin.com/c5XqKSsW. Basically, you need to apply the patch on > nouveau > and rebuild the nouveau kernel module. > > A comparison of different methods that works for toggling the dGPU is > available: > > https://github.com/Bumblebee-Project/Bumblebee/wiki/Comparison-of-PM-methods > > Regards, > Lekensteyn > > > On Mon, Dec 19, 2011 at 11:04 AM, Gianluca Cecchi < > gianluca.cecchi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > >> >> On Sat, Dec 17, 2011 at 5:50 PM, Lekensteyn <lekensteyn-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> >> wrote: >> >>> >> >>> Hello guys, >> >>> >> >>> I've prepared a patch based on my findings for the bbswitch module >> >>> (https://github.com/Lekensteyn/acpi-stuff/tree/master/bbswitch). This >> >>> adds a proper >> >>> check whether a _DSM function is supported or not and make OFF / ON >> for >> >>> vga_switcheroo work for nVidia Optimus models. The patch is based >> against >> >>> the >> >>> mainline kernel. >> >>> >> >>> It has been tested on my Clevo B7130 laptop running kernel 3.2 which >> has >> >> Hello, >> I have an Asus U36SD laptop with Optimus and Fedora 16 with kernel >> 3.1.5-6.fc16.x86_64 >> Any way I can test it? >> Currently I'm using acpi_call to switch off nvidia card and gain 4w >> for more battery life. >> >> [g.cecchi@ope46 ~]$ lspci -vnnn|grep -i vga >> 00:02.0 VGA compatible controller [0300]: Intel Corporation 2nd >> Generation Core Processor Family Integrated Graphics Controller >> [8086:0126] (rev 09) (prog-if 00 [VGA controller]) >> 01:00.0 VGA compatible controller [0300]: nVidia Corporation Device >> [10de:1050] (rev ff) (prog-if ff) >> >> What benefit would it give me? Chance to use nvidia for graphic >> related apps ? With nouveau andor nvidia proprietary driver? >> Thanks in advance for any pointer >> >> Gianluca >> _______________________________________________ >> Nouveau mailing list >> Nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org >> http://lists.freedesktop.org/mailman/listinfo/nouveau >> > > [-- Attachment #1.2: Type: text/html, Size: 3811 bytes --] [-- Attachment #2: nouveau-switcheroo-optimus.patch --] [-- Type: text/x-diff, Size: 9131 bytes --] From b6e1b5b316ae17ccb7def0a8b38e69ad4c99c55d Mon Sep 17 00:00:00 2001 From: Peter Lekensteyn <lekensteyn@gmail.com> Date: Sat, 17 Dec 2011 12:53:43 +0100 Subject: [PATCH 1/2] nouveau: properly check for _DSM function support According to the ACPI spec version 4, section 9.14.1, _DSM functions must return a value with the first bit enabled if any DSM functions are supported for the given UUID and revision ID. For a given function index n to be marked supported, bit n must be enabled. Signed-off-by: Peter Lekensteyn <lekensteyn@gmail.com> --- drivers/gpu/drm/nouveau/nouveau_acpi.c | 35 ++++++++++++++++++++----------- 1 files changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 525744d..96756d0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -18,12 +18,6 @@ #include <linux/vga_switcheroo.h> -#define NOUVEAU_DSM_SUPPORTED 0x00 -#define NOUVEAU_DSM_SUPPORTED_FUNCTIONS 0x00 - -#define NOUVEAU_DSM_ACTIVE 0x01 -#define NOUVEAU_DSM_ACTIVE_QUERY 0x00 - #define NOUVEAU_DSM_LED 0x02 #define NOUVEAU_DSM_LED_STATE 0x00 #define NOUVEAU_DSM_LED_OFF 0x10 @@ -35,6 +29,7 @@ #define NOUVEAU_DSM_POWER_SPEED 0x01 #define NOUVEAU_DSM_POWER_STAMINA 0x02 +#define NOUVEAU_DSM_OPTIMUS_FN 0x1A static struct nouveau_dsm_priv { bool dsm_detected; bool optimus_detected; @@ -148,6 +143,23 @@ static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result) return 0; } +/* Returns 1 if a DSM function is usable and 0 otherwise */ +static int nouveau_test_dsm(acpi_handle test_handle, + int (*dsm_func)(acpi_handle, int, int, uint32_t *), + int sfnc) +{ + u32 result = 0; + + /* Function 0 returns a Buffer containing available functions. The args + * parameter is ignored for function 0, so just put 0 in it */ + if (dsm_func(test_handle, 0, 0, &result)) + return 0; + + /* ACPI Spec v4 9.14.1: if bit 0 is zero, no function is supported. If + * the n-th bit is enabled, function n is supported */ + return result & 1 && result & (1 << sfnc); +} + static int nouveau_dsm_switch_mux(acpi_handle handle, int mux_id) { mxm_wmi_call_mxmx(mux_id == NOUVEAU_DSM_LED_STAMINA ? MXM_MXDS_ADAPTER_IGD : MXM_MXDS_ADAPTER_0); @@ -212,8 +224,7 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) { acpi_handle dhandle, nvidia_handle; acpi_status status; - int ret, retval = 0; - uint32_t result; + int retval = 0; dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); if (!dhandle) @@ -224,13 +235,11 @@ static int nouveau_dsm_pci_probe(struct pci_dev *pdev) return false; } - ret = nouveau_dsm(dhandle, NOUVEAU_DSM_SUPPORTED, - NOUVEAU_DSM_SUPPORTED_FUNCTIONS, &result); - if (ret == 0) + if (nouveau_test_dsm(dhandle, nouveau_dsm, NOUVEAU_DSM_POWER)) retval |= NOUVEAU_DSM_HAS_MUX; - ret = nouveau_optimus_dsm(dhandle, 0, 0, &result); - if (ret == 0) + if (nouveau_test_dsm(dhandle, nouveau_optimus_dsm, + NOUVEAU_DSM_OPTIMUS_FN)) retval |= NOUVEAU_DSM_HAS_OPT; if (retval) -- 1.7.5.4 From 9c1a466321c9bdc44fb45205ebb5469da3d2adba Mon Sep 17 00:00:00 2001 From: Peter Lekensteyn <lekensteyn@gmail.com> Date: Sat, 17 Dec 2011 12:54:04 +0100 Subject: [PATCH 2/2] nouveau: Support Optimus models for vga_switcheroo Newer nVidia cards with Optimus do not support/use the DSM switching functions. Instead, it require a DSM function to be called prior to bringing a device into D3 state. No other _DSM calls are necessary before/after enabling/disabling a device. Switching between discrete and integrated GPU is not supported by this Optimus _DSM call, therefore return on the switching method. Signed-off-by: Peter Lekensteyn <lekensteyn@gmail.com> --- drivers/gpu/drm/nouveau/nouveau_acpi.c | 44 +++++++++++++++++++++++++++--- drivers/gpu/drm/nouveau/nouveau_drv.h | 2 + drivers/gpu/drm/nouveau/nouveau_state.c | 1 + 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index 96756d0..7814a76 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -30,6 +30,8 @@ #define NOUVEAU_DSM_POWER_STAMINA 0x02 #define NOUVEAU_DSM_OPTIMUS_FN 0x1A +#define NOUVEAU_DSM_OPTIMUS_ARGS 0x03000001 + static struct nouveau_dsm_priv { bool dsm_detected; bool optimus_detected; @@ -56,7 +58,8 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t * struct acpi_object_list input; union acpi_object params[4]; union acpi_object *obj; - int err; + int i, err; + char args_buff[4]; input.count = 4; input.pointer = params; @@ -68,7 +71,11 @@ static int nouveau_optimus_dsm(acpi_handle handle, int func, int arg, uint32_t * params[2].type = ACPI_TYPE_INTEGER; params[2].integer.value = func; params[3].type = ACPI_TYPE_BUFFER; - params[3].buffer.length = 0; + params[3].buffer.length = 4; + /* ACPI is little endian, AABBCCDD becomes {DD,CC,BB,AA} */ + for (i = 0; i < 4; i++) + args_buff[i] = (arg >> i * 8) & 0xFF; + params[3].buffer.pointer = args_buff; err = acpi_evaluate_object(handle, "_DSM", &input, &output); if (err) { @@ -180,6 +187,10 @@ static int nouveau_dsm_set_discrete_state(acpi_handle handle, enum vga_switchero static int nouveau_dsm_switchto(enum vga_switcheroo_client_id id) { + /* perhaps the _DSM functions are mutually exclusive, but prepare for + * the future */ + if (!nouveau_dsm_priv.dsm_detected && nouveau_dsm_priv.optimus_detected) + return 0; if (id == VGA_SWITCHEROO_IGD) return nouveau_dsm_switch_mux(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_LED_STAMINA); else @@ -192,6 +203,11 @@ static int nouveau_dsm_power_state(enum vga_switcheroo_client_id id, if (id == VGA_SWITCHEROO_IGD) return 0; + /* Optimus laptops have the card already disabled in + * nouveau_switcheroo_set_state */ + if (!nouveau_dsm_priv.dsm_detected && nouveau_dsm_priv.optimus_detected) + return 0; + return nouveau_dsm_set_discrete_state(nouveau_dsm_priv.dhandle, state); } @@ -278,15 +294,22 @@ static bool nouveau_dsm_detect(void) } if (vga_count == 2 && has_dsm && guid_valid) { - acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, &buffer); + acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, + &buffer); printk(KERN_INFO "VGA switcheroo: detected DSM switching method %s handle\n", - acpi_method_name); + acpi_method_name); nouveau_dsm_priv.dsm_detected = true; ret = true; } - if (has_optimus == 1) + if (has_optimus == 1) { + acpi_get_name(nouveau_dsm_priv.dhandle, ACPI_FULL_PATHNAME, + &buffer); + printk(KERN_INFO "VGA switcheroo: detected Optimus DSM method %s handle\n", + acpi_method_name); nouveau_dsm_priv.optimus_detected = true; + ret = true; + } return ret; } @@ -302,6 +325,17 @@ void nouveau_register_dsm_handler(void) vga_switcheroo_register_handler(&nouveau_dsm_handler); } +/* Must be called for Optimus models before the card can be turned off */ +void nouveau_switcheroo_optimus_dsm(void) +{ + u32 result = 0; + if (!nouveau_dsm_priv.optimus_detected) + return; + + nouveau_optimus_dsm(nouveau_dsm_priv.dhandle, NOUVEAU_DSM_OPTIMUS_FN, + NOUVEAU_DSM_OPTIMUS_ARGS, &result); +} + void nouveau_unregister_dsm_handler(void) { vga_switcheroo_unregister_handler(); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 4c0be3a..4f369f4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1041,12 +1041,14 @@ extern int nouveau_dma_wait(struct nouveau_channel *, int slots, int size); #if defined(CONFIG_ACPI) void nouveau_register_dsm_handler(void); void nouveau_unregister_dsm_handler(void); +void nouveau_switcheroo_optimus_dsm(void); int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len); bool nouveau_acpi_rom_supported(struct pci_dev *pdev); int nouveau_acpi_edid(struct drm_device *, struct drm_connector *); #else static inline void nouveau_register_dsm_handler(void) {} static inline void nouveau_unregister_dsm_handler(void) {} +static inline void nouveau_switcheroo_optimus_dsm(void) {} static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; } static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; } static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { return -EINVAL; } diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index d8831ab..ef270cf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -525,6 +525,7 @@ static void nouveau_switcheroo_set_state(struct pci_dev *pdev, printk(KERN_ERR "VGA switcheroo: switched nouveau off\n"); dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; drm_kms_helper_poll_disable(dev); + nouveau_switcheroo_optimus_dsm(); nouveau_pci_suspend(pdev, pmm); dev->switch_power_state = DRM_SWITCH_POWER_OFF; } -- 1.7.5.4 [-- Attachment #3: Type: text/plain, Size: 181 bytes --] _______________________________________________ Nouveau mailing list Nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org http://lists.freedesktop.org/mailman/listinfo/nouveau ^ permalink raw reply related [flat|nested] 9+ messages in thread
[parent not found: <CALBR5Zxuwv-zBQfVr7By3su2rjWjcVapX7oCCfeybjBMPY9cbA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: properly check for _DSM function support and Optimus support for vga_switcheroo [not found] ` <CALBR5Zxuwv-zBQfVr7By3su2rjWjcVapX7oCCfeybjBMPY9cbA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> @ 2012-01-09 22:45 ` Ben Skeggs 2012-01-12 17:29 ` Dave Airlie 0 siblings, 1 reply; 9+ messages in thread From: Ben Skeggs @ 2012-01-09 22:45 UTC (permalink / raw) To: Lekensteyn Cc: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, airlied-H+wXaHxf7aLQT0dZR+AlfA On Mon, 2012-01-09 at 00:13 +0100, Lekensteyn wrote: > Any activity on this? The newly attached patch contains one difference > with the previous > one: a dummy function has been added to avoid an error if ACPI is > disabled. Dave, Any thoughts on this? Ben. > > Regards, > Lekensteyn > > On Mon, Dec 19, 2011 at 2:26 PM, Lekensteyn <lekensteyn-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > wrote: > A quickly written way to test this module is described for > Ubuntu at > http://pastebin.com/c5XqKSsW. Basically, you need to apply the > patch on nouveau > and rebuild the nouveau kernel module. > > A comparison of different methods that works for toggling the > dGPU is available: > https://github.com/Bumblebee-Project/Bumblebee/wiki/Comparison-of-PM-methods > > Regards, > Lekensteyn > > > On Mon, Dec 19, 2011 at 11:04 AM, Gianluca Cecchi > <gianluca.cecchi-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > >> On Sat, Dec 17, 2011 at 5:50 PM, Lekensteyn > <lekensteyn-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > >>> > >>> Hello guys, > >>> > >>> I've prepared a patch based on my findings for the > bbswitch module > >>> > (https://github.com/Lekensteyn/acpi-stuff/tree/master/bbswitch). This > >>> adds a proper > >>> check whether a _DSM function is supported or not > and make OFF / ON for > >>> vga_switcheroo work for nVidia Optimus models. The > patch is based against > >>> the > >>> mainline kernel. > >>> > >>> It has been tested on my Clevo B7130 laptop > running kernel 3.2 which has > > > Hello, > I have an Asus U36SD laptop with Optimus and Fedora 16 > with kernel > 3.1.5-6.fc16.x86_64 > Any way I can test it? > Currently I'm using acpi_call to switch off nvidia > card and gain 4w > for more battery life. > > [g.cecchi@ope46 ~]$ lspci -vnnn|grep -i vga > 00:02.0 VGA compatible controller [0300]: Intel > Corporation 2nd > Generation Core Processor Family Integrated Graphics > Controller > [8086:0126] (rev 09) (prog-if 00 [VGA controller]) > 01:00.0 VGA compatible controller [0300]: nVidia > Corporation Device > [10de:1050] (rev ff) (prog-if ff) > > What benefit would it give me? Chance to use nvidia > for graphic > related apps ? With nouveau andor nvidia proprietary > driver? > Thanks in advance for any pointer > > Gianluca > _______________________________________________ > Nouveau mailing list > Nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org > http://lists.freedesktop.org/mailman/listinfo/nouveau > > > > > _______________________________________________ > Nouveau mailing list > Nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org > http://lists.freedesktop.org/mailman/listinfo/nouveau ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: properly check for _DSM function support and Optimus support for vga_switcheroo 2012-01-09 22:45 ` Ben Skeggs @ 2012-01-12 17:29 ` Dave Airlie 0 siblings, 0 replies; 9+ messages in thread From: Dave Airlie @ 2012-01-12 17:29 UTC (permalink / raw) To: skeggsb-Re5JQEeQqe8AvxtiuMwx3w Cc: nouveau-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW, airlied-H+wXaHxf7aLQT0dZR+AlfA On Mon, Jan 9, 2012 at 10:45 PM, Ben Skeggs <skeggsb-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > On Mon, 2012-01-09 at 00:13 +0100, Lekensteyn wrote: >> Any activity on this? The newly attached patch contains one difference >> with the previous >> one: a dummy function has been added to avoid an error if ACPI is >> disabled. > Dave, > > Any thoughts on this? Yeah they both look fine, I'll test them on my machine tomorrow hopefully. Dave. ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2012-01-12 17:29 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2011-12-17 12:14 properly check for _DSM function support and Optimus support for vga_switcheroo Lekensteyn [not found] ` <CALBR5ZxR9iuvT57bDZ8yW9ZkZjuoUhBTYw4HBsmsiwoRi4gSkw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2011-12-17 22:50 ` Lekensteyn [not found] ` <CALBR5ZyE2ZRX7eFBhooB22e9BRf0f3H2xqtvXB2iwe8nvKKnvw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2011-12-19 4:39 ` Omar Andrés Zapata Mesa [not found] ` <CAOB9epp8EdpetsPStfdnGNx5-2dKi42j3DQiVKN_dzMdFcssWA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2011-12-19 9:44 ` Lekensteyn [not found] ` <CALBR5Zw0gEDqKrSUF3R30tSSC6DUgfhVm0Y1Mp60e4bB4ObijQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2011-12-19 10:04 ` Gianluca Cecchi [not found] ` <CAG2kNCwBwRJ_VrS9NHnmGvOTTLuwmBKd5kG8OknJG+f20Kvqsg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2011-12-19 13:26 ` Lekensteyn 2012-01-08 23:13 ` Lekensteyn [not found] ` <CALBR5Zxuwv-zBQfVr7By3su2rjWjcVapX7oCCfeybjBMPY9cbA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org> 2012-01-09 22:45 ` Ben Skeggs 2012-01-12 17:29 ` Dave Airlie
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.