All of lore.kernel.org
 help / color / mirror / Atom feed
* 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

* 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

* 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

* 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

* 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

* 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

* 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.