diff mbox

[v2.1,2/3] apple-gmux: Add switch_ddc support

Message ID 3f927fb1a1df18bfdbb501b98a6b2dcd5c064f02.1439739853.git.lukas@wunner.de (mailing list archive)
State New, archived
Headers show

Commit Message

Lukas Wunner Aug. 14, 2015, 4:18 p.m. UTC
Originally by Seth Forshee <seth.forshee@canonical.com>, 2012-10-04:
The gmux allows muxing the DDC independently from the display, so
support this functionality. This will allow reading the EDID for the
inactive GPU, fixing issues with machines that either don't have a VBT
or have invalid mode data in the VBT.

Modified by Lukas Wunner <lukas@wunner.de>, 2015-03-27:
If the inactive client registers before the active client then
old_ddc_owner cannot be determined with find_active_client()
(null pointer dereference). Therefore change semantics of the
->switch_ddc handler callback to return old_ddc_owner.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=88861
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61115
Tested-by: Pierre Moreau <pierre.morrow@free.fr>
    [MBP  5,3 2009  nvidia 9400M + 9600M GT   pre-retina]
Tested-by: Paul Hordiienko <pvt.gord@gmail.com>
    [MBP  6,2 2010  intel ILK + nvidia GT216  pre-retina]
Tested-by: William Brown <william@blackhats.net.au>
    [MBP  8,2 2011  intel SNB + amd turks     pre-retina]
Tested-by: Lukas Wunner <lukas@wunner.de>
    [MBP  9,1 2012  intel IVB + nvidia GK107  pre-retina]
Tested-by: Bruno Bierbaumer <bruno@bierbaumer.net>
    [MBP 11,3 2013  intel HSW + nvidia GK107  retina -- work in progress]

Cc: Seth Forshee <seth.forshee@canonical.com>
Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 drivers/platform/x86/apple-gmux.c | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

Comments

Daniel Vetter Aug. 25, 2015, 8:13 a.m. UTC | #1
On Fri, Aug 14, 2015 at 06:18:55PM +0200, Lukas Wunner wrote:
> Originally by Seth Forshee <seth.forshee@canonical.com>, 2012-10-04:
> The gmux allows muxing the DDC independently from the display, so
> support this functionality. This will allow reading the EDID for the
> inactive GPU, fixing issues with machines that either don't have a VBT
> or have invalid mode data in the VBT.
> 
> Modified by Lukas Wunner <lukas@wunner.de>, 2015-03-27:
> If the inactive client registers before the active client then
> old_ddc_owner cannot be determined with find_active_client()
> (null pointer dereference). Therefore change semantics of the
> ->switch_ddc handler callback to return old_ddc_owner.
> 
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=88861
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=61115
> Tested-by: Pierre Moreau <pierre.morrow@free.fr>
>     [MBP  5,3 2009  nvidia 9400M + 9600M GT   pre-retina]
> Tested-by: Paul Hordiienko <pvt.gord@gmail.com>
>     [MBP  6,2 2010  intel ILK + nvidia GT216  pre-retina]
> Tested-by: William Brown <william@blackhats.net.au>
>     [MBP  8,2 2011  intel SNB + amd turks     pre-retina]
> Tested-by: Lukas Wunner <lukas@wunner.de>
>     [MBP  9,1 2012  intel IVB + nvidia GK107  pre-retina]
> Tested-by: Bruno Bierbaumer <bruno@bierbaumer.net>
>     [MBP 11,3 2013  intel HSW + nvidia GK107  retina -- work in progress]
> 
> Cc: Seth Forshee <seth.forshee@canonical.com>
> Signed-off-by: Lukas Wunner <lukas@wunner.de>
> ---
>  drivers/platform/x86/apple-gmux.c | 25 +++++++++++++++++++++++--
>  1 file changed, 23 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
> index 0dec3f5..08bdf1e 100644
> --- a/drivers/platform/x86/apple-gmux.c
> +++ b/drivers/platform/x86/apple-gmux.c
> @@ -273,14 +273,34 @@ static const struct backlight_ops gmux_bl_ops = {
>  	.update_status = gmux_update_status,
>  };
>  
> +static int gmux_switch_ddc(enum vga_switcheroo_client_id id)
> +{
> +	enum vga_switcheroo_client_id old_ddc_owner;
> +
> +	if (gmux_read8(apple_gmux_data, GMUX_PORT_SWITCH_DDC) == 1)
> +		old_ddc_owner = VGA_SWITCHEROO_IGD;
> +	else
> +		old_ddc_owner = VGA_SWITCHEROO_DIS;
> +
> +	pr_debug("Switching gmux DDC from %d to %d\n", old_ddc_owner, id);
> +
> +	if (id == old_ddc_owner)
> +		return old_ddc_owner;
> +
> +	if (id == VGA_SWITCHEROO_IGD)
> +		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1);
> +	else
> +		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 2);
> +
> +	return old_ddc_owner;
> +}
> +
>  static int gmux_switchto(enum vga_switcheroo_client_id id)
>  {
>  	if (id == VGA_SWITCHEROO_IGD) {
> -		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1);
>  		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DISPLAY, 2);
>  		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 2);
>  	} else {
> -		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 2);
>  		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DISPLAY, 3);
>  		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3);
>  	}
> @@ -347,6 +367,7 @@ gmux_active_client(struct apple_gmux_data *gmux_data)
>  }

If we'd required that switchto also switches ddc then the error handling
in patch 1 would be a lot simpler. switch_ddc would then only be for
temporary switching while probing.
-Daniel

>  
>  static struct vga_switcheroo_handler gmux_handler = {
> +	.switch_ddc = gmux_switch_ddc,
>  	.switchto = gmux_switchto,
>  	.power_state = gmux_set_power_state,
>  	.get_client_id = gmux_get_client_id,
> -- 
> 2.1.0
>
diff mbox

Patch

diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index 0dec3f5..08bdf1e 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -273,14 +273,34 @@  static const struct backlight_ops gmux_bl_ops = {
 	.update_status = gmux_update_status,
 };
 
+static int gmux_switch_ddc(enum vga_switcheroo_client_id id)
+{
+	enum vga_switcheroo_client_id old_ddc_owner;
+
+	if (gmux_read8(apple_gmux_data, GMUX_PORT_SWITCH_DDC) == 1)
+		old_ddc_owner = VGA_SWITCHEROO_IGD;
+	else
+		old_ddc_owner = VGA_SWITCHEROO_DIS;
+
+	pr_debug("Switching gmux DDC from %d to %d\n", old_ddc_owner, id);
+
+	if (id == old_ddc_owner)
+		return old_ddc_owner;
+
+	if (id == VGA_SWITCHEROO_IGD)
+		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1);
+	else
+		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 2);
+
+	return old_ddc_owner;
+}
+
 static int gmux_switchto(enum vga_switcheroo_client_id id)
 {
 	if (id == VGA_SWITCHEROO_IGD) {
-		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 1);
 		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DISPLAY, 2);
 		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 2);
 	} else {
-		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DDC, 2);
 		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_DISPLAY, 3);
 		gmux_write8(apple_gmux_data, GMUX_PORT_SWITCH_EXTERNAL, 3);
 	}
@@ -347,6 +367,7 @@  gmux_active_client(struct apple_gmux_data *gmux_data)
 }
 
 static struct vga_switcheroo_handler gmux_handler = {
+	.switch_ddc = gmux_switch_ddc,
 	.switchto = gmux_switchto,
 	.power_state = gmux_set_power_state,
 	.get_client_id = gmux_get_client_id,