Skip to contentSkip to conversation

vga_switcheroo: add mux switched interface

PATCH In review Dave Airlie 2 participants 6 messages Jan 8, 2013 – Jan 9, 2013

Subsystems (4)
lore
Share & tools
lore

Dave Airlie

author maintainer
#0 lore raw

PATCH 1/2 vga_switcheroo: add mux switched interface

From: Dave Airlie <[email protected]>

this tells the drivers when the mux is switch to/from it, can be used to report outputs as disconnected to userspace etc.

---
 drivers/gpu/vga/vga_switcheroo.c | 19 +++++++++++++++++++
 include/linux/vga_switcheroo.h   |  1 +
 2 files changed, 20 insertions(+)
drivers/gpu/vga/vga_switcheroo.c +19 -0
index fa60add..2362175 100644
@@ -93,6 +93,9 @@ static void vga_switcheroo_enable(void)
 			return;
 
 		client->id = ret;
+
+		if (client->ops->mux_switched)
+			client->ops->mux_switched(client->pdev, client->active ? VGA_SWITCHEROO_ON : VGA_SWITCHEROO_OFF);
 	}
 	vga_switcheroo_debugfs_init(&vgasr_priv);
 	vgasr_priv.active = true;
@@ -345,6 +348,13 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
 	if (ret)
 		return ret;
 
+	/* call mux switched callbacks */
+	if (active->ops->mux_switched)
+		active->ops->mux_switched(active->pdev, VGA_SWITCHEROO_OFF);
+
+	if (new_client->ops->mux_switched)
+		new_client->ops->mux_switched(new_client->pdev, VGA_SWITCHEROO_ON);
+
 	if (new_client->ops->reprobe)
 		new_client->ops->reprobe(new_client->pdev);
 
@@ -452,7 +462,16 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
 	vgasr_priv.delayed_switch_active = false;
 
 	if (just_mux) {
+		struct vga_switcheroo_client *active;
+		active = find_active_client(&vgasr_priv.clients);
+		if (!active)
+			return 0;
 		ret = vgasr_priv.handler->switchto(client_id);
+
+		if (active->ops->mux_switched)
+			active->ops->mux_switched(active->pdev, VGA_SWITCHEROO_OFF);
+		if (client->ops->mux_switched)
+			client->ops->mux_switched(client->pdev, VGA_SWITCHEROO_ON);
 		goto out;
 	}
 
include/linux/vga_switcheroo.h +1 -0
index ddb419c..6275719 100644
@@ -40,6 +40,7 @@ struct vga_switcheroo_client_ops {
 	void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state);
 	void (*reprobe)(struct pci_dev *dev);
 	bool (*can_switch)(struct pci_dev *dev);
+	void (*mux_switched)(struct pci_dev *dev, enum vga_switcheroo_state);
 };
 
 #if defined(CONFIG_VGA_SWITCHEROO)
Signature · 1 line
1.8.1
author maintainer
#1 lore raw

PATCH 2/2 radeon: add support for forcing off lvds when mux switched away

From: Dave Airlie <[email protected]>

otherwise userspace can get very confused

---
 drivers/gpu/drm/radeon/radeon_connectors.c |  4 ++++
 drivers/gpu/drm/radeon/radeon_device.c     | 14 ++++++++++++++
 drivers/gpu/drm/radeon/radeon_mode.h       |  2 ++
 3 files changed, 20 insertions(+)
drivers/gpu/drm/radeon/radeon_connectors.c +4 -0
index 2399f25..e5a4a10 100644
@@ -611,6 +611,10 @@ radeon_lvds_detect(struct drm_connector *connector, bool force)
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 	struct drm_encoder *encoder = radeon_best_single_encoder(connector);
 	enum drm_connector_status ret = connector_status_disconnected;
+	struct radeon_device *rdev = connector->dev->dev_private;
+
+	if (rdev->mode_info.mux_force_disconnected)
+		return connector_status_disconnected;
 
 	if (encoder) {
 		struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
drivers/gpu/drm/radeon/radeon_device.c +14 -0
index cd75626..bf66f09 100644
@@ -945,10 +945,24 @@ static bool radeon_switcheroo_can_switch(struct pci_dev *pdev)
 	return can_switch;
 }
 
+static void radeon_switcheroo_mux_switched(struct pci_dev *pdev, enum vga_switcheroo_state state)
+{
+	struct drm_device *dev = pci_get_drvdata(pdev);
+	struct radeon_device *rdev = dev->dev_private;
+
+	if (state == VGA_SWITCHEROO_OFF)
+		rdev->mode_info.mux_force_disconnected = true;
+	else
+		rdev->mode_info.mux_force_disconnected = false;
+
+	drm_kms_helper_hotplug_event(dev);
+}
+
 static const struct vga_switcheroo_client_ops radeon_switcheroo_ops = {
 	.set_gpu_state = radeon_switcheroo_set_state,
 	.reprobe = NULL,
 	.can_switch = radeon_switcheroo_can_switch,
+	.mux_switched = radeon_switcheroo_mux_switched,
 };
 
 /**
drivers/gpu/drm/radeon/radeon_mode.h +2 -0
index 4003f5a..172eed8 100644
@@ -256,6 +256,8 @@ struct radeon_mode_info {
 	u16 firmware_flags;
 	/* pointer to backlight encoder */
 	struct radeon_encoder *bl_encoder;
+
+	bool mux_force_disconnected;
 };
 
 #define RADEON_MAX_BL_LEVEL 0xFF
Signature · 1 line
1.8.1
Reviewed-by on v1 2/2
#2 lore raw

Re: [PATCH 2/2] radeon: add support for forcing off lvds when mux switched away

Quoted 3 lines · Dave Airlie

From: Dave Airlie <[email protected]>

otherwise userspace can get very confused

It might be worth adding the switch state checks to the dp_detect function to handle eDP and DP to LVDS bridges, but I think all the laptops with eDP or DP bridges are mux-less, so probably not a big deal. Other than that:

Quoted 70 lines
---
 drivers/gpu/drm/radeon/radeon_connectors.c |  4 ++++
 drivers/gpu/drm/radeon/radeon_device.c     | 14 ++++++++++++++
 drivers/gpu/drm/radeon/radeon_mode.h       |  2 ++
 3 files changed, 20 insertions(+)
drivers/gpu/drm/radeon/radeon_connectors.c +4 -0
index 2399f25..e5a4a10 100644
@@ -611,6 +611,10 @@ radeon_lvds_detect(struct drm_connector *connector, bool force)
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        struct drm_encoder *encoder = radeon_best_single_encoder(connector);
        enum drm_connector_status ret = connector_status_disconnected;
+       struct radeon_device *rdev = connector->dev->dev_private;
+
+       if (rdev->mode_info.mux_force_disconnected)
+               return connector_status_disconnected;
 
        if (encoder) {
                struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
drivers/gpu/drm/radeon/radeon_device.c +14 -0
index cd75626..bf66f09 100644
@@ -945,10 +945,24 @@ static bool radeon_switcheroo_can_switch(struct pci_dev *pdev)
        return can_switch;
 }
 
+static void radeon_switcheroo_mux_switched(struct pci_dev *pdev, enum vga_switcheroo_state state)
+{
+       struct drm_device *dev = pci_get_drvdata(pdev);
+       struct radeon_device *rdev = dev->dev_private;
+
+       if (state == VGA_SWITCHEROO_OFF)
+               rdev->mode_info.mux_force_disconnected = true;
+       else
+               rdev->mode_info.mux_force_disconnected = false;
+
+       drm_kms_helper_hotplug_event(dev);
+}
+
 static const struct vga_switcheroo_client_ops radeon_switcheroo_ops = {
        .set_gpu_state = radeon_switcheroo_set_state,
        .reprobe = NULL,
        .can_switch = radeon_switcheroo_can_switch,
+       .mux_switched = radeon_switcheroo_mux_switched,
 };
 
 /**
drivers/gpu/drm/radeon/radeon_mode.h +2 -1
index 4003f5a..172eed8 100644
@@ -256,6 +256,8 @@ struct radeon_mode_info {
        u16 firmware_flags;
        /* pointer to backlight encoder */
        struct radeon_encoder *bl_encoder;
+
+       bool mux_force_disconnected;
 };
 
 #define RADEON_MAX_BL_LEVEL 0xFF
--

1.8.1

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

#3 lore raw

Re: [PATCH 2/2] radeon: add support for forcing off lvds when mux switched away

In reply to Dave Airlie
Quoted 3 lines · Dave Airlie

From: Dave Airlie <[email protected]>

otherwise userspace can get very confused

Thinking about this more, we probably want to check whether we have a muxed to mux-less system otherwise we'll be disconnecting the display when we switch. Looks like the first patch is cognizant of that, but this one is not unless I'm missing something.

Alex

Quoted 70 lines
---
 drivers/gpu/drm/radeon/radeon_connectors.c |  4 ++++
 drivers/gpu/drm/radeon/radeon_device.c     | 14 ++++++++++++++
 drivers/gpu/drm/radeon/radeon_mode.h       |  2 ++
 3 files changed, 20 insertions(+)
drivers/gpu/drm/radeon/radeon_connectors.c +4 -0
index 2399f25..e5a4a10 100644
@@ -611,6 +611,10 @@ radeon_lvds_detect(struct drm_connector *connector, bool force)
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        struct drm_encoder *encoder = radeon_best_single_encoder(connector);
        enum drm_connector_status ret = connector_status_disconnected;
+       struct radeon_device *rdev = connector->dev->dev_private;
+
+       if (rdev->mode_info.mux_force_disconnected)
+               return connector_status_disconnected;
 
        if (encoder) {
                struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
drivers/gpu/drm/radeon/radeon_device.c +14 -0
index cd75626..bf66f09 100644
@@ -945,10 +945,24 @@ static bool radeon_switcheroo_can_switch(struct pci_dev *pdev)
        return can_switch;
 }
 
+static void radeon_switcheroo_mux_switched(struct pci_dev *pdev, enum vga_switcheroo_state state)
+{
+       struct drm_device *dev = pci_get_drvdata(pdev);
+       struct radeon_device *rdev = dev->dev_private;
+
+       if (state == VGA_SWITCHEROO_OFF)
+               rdev->mode_info.mux_force_disconnected = true;
+       else
+               rdev->mode_info.mux_force_disconnected = false;
+
+       drm_kms_helper_hotplug_event(dev);
+}
+
 static const struct vga_switcheroo_client_ops radeon_switcheroo_ops = {
        .set_gpu_state = radeon_switcheroo_set_state,
        .reprobe = NULL,
        .can_switch = radeon_switcheroo_can_switch,
+       .mux_switched = radeon_switcheroo_mux_switched,
 };
 
 /**
drivers/gpu/drm/radeon/radeon_mode.h +2 -1
index 4003f5a..172eed8 100644
@@ -256,6 +256,8 @@ struct radeon_mode_info {
        u16 firmware_flags;
        /* pointer to backlight encoder */
        struct radeon_encoder *bl_encoder;
+
+       bool mux_force_disconnected;
 };
 
 #define RADEON_MAX_BL_LEVEL 0xFF
--

1.8.1

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

author maintainer
#4 lore raw

Re: [PATCH 2/2] radeon: add support for forcing off lvds when mux switched away

Quoted 10 lines · Alex Deucher
Quoted 3 lines · Dave Airlie

From: Dave Airlie <[email protected]>

otherwise userspace can get very confused

Thinking about this more, we probably want to check whether we have a muxed to mux-less system otherwise we'll be disconnecting the display when we switch. Looks like the first patch is cognizant of that, but this one is not unless I'm missing something.

vga switcheroo is only for muxed systems, for muxless there is no "switching".

Dave.

Reviewed-by on v1 1/2
#5 lore raw
In reply to Dave Airlie
Quoted 6 lines · Dave Airlie

From: Dave Airlie <[email protected]>

this tells the drivers when the mux is switch to/from it, can be used to report outputs as disconnected to userspace etc.

Quoted 69 lines
---
 drivers/gpu/vga/vga_switcheroo.c | 19 +++++++++++++++++++
 include/linux/vga_switcheroo.h   |  1 +
 2 files changed, 20 insertions(+)
drivers/gpu/vga/vga_switcheroo.c +19 -0
index fa60add..2362175 100644
@@ -93,6 +93,9 @@ static void vga_switcheroo_enable(void)
                        return;
 
                client->id = ret;
+
+               if (client->ops->mux_switched)
+                       client->ops->mux_switched(client->pdev, client->active ? VGA_SWITCHEROO_ON : VGA_SWITCHEROO_OFF);
        }
        vga_switcheroo_debugfs_init(&vgasr_priv);
        vgasr_priv.active = true;
@@ -345,6 +348,13 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client)
        if (ret)
                return ret;
 
+       /* call mux switched callbacks */
+       if (active->ops->mux_switched)
+               active->ops->mux_switched(active->pdev, VGA_SWITCHEROO_OFF);
+
+       if (new_client->ops->mux_switched)
+               new_client->ops->mux_switched(new_client->pdev, VGA_SWITCHEROO_ON);
+
        if (new_client->ops->reprobe)
                new_client->ops->reprobe(new_client->pdev);
 
@@ -452,7 +462,16 @@ vga_switcheroo_debugfs_write(struct file *filp, const char __user *ubuf,
        vgasr_priv.delayed_switch_active = false;
 
        if (just_mux) {
+               struct vga_switcheroo_client *active;
+               active = find_active_client(&vgasr_priv.clients);
+               if (!active)
+                       return 0;
                ret = vgasr_priv.handler->switchto(client_id);
+
+               if (active->ops->mux_switched)
+                       active->ops->mux_switched(active->pdev, VGA_SWITCHEROO_OFF);
+               if (client->ops->mux_switched)
+                       client->ops->mux_switched(client->pdev, VGA_SWITCHEROO_ON);
                goto out;
        }
 
include/linux/vga_switcheroo.h +1 -1
index ddb419c..6275719 100644
@@ -40,6 +40,7 @@ struct vga_switcheroo_client_ops {
        void (*set_gpu_state)(struct pci_dev *dev, enum vga_switcheroo_state);
        void (*reprobe)(struct pci_dev *dev);
        bool (*can_switch)(struct pci_dev *dev);
+       void (*mux_switched)(struct pci_dev *dev, enum vga_switcheroo_state);
 };
 
 #if defined(CONFIG_VGA_SWITCHEROO)
--

1.8.1

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel