Subject: [PATCH] [acpi video] Add interface for display switching

- Add video_switch_{prev,next}() for cycling through output choices
- Add find_active() and get_video_dev() helpers for those functions

Signed-off-by: Patrick Mochel <mochel@linux.intel.com>

---

 drivers/acpi/drivers/video/bus-device.c |   81 +++++++++++++++++++++++++++++++
 drivers/acpi/drivers/video/video.h      |    3 +
 2 files changed, 84 insertions(+), 0 deletions(-)

applies-to: 795ec5ec72e11288fbb3db463873595b4b649a14
852029b9e620b73277f46964c3e8557643aeca33
diff --git a/drivers/acpi/drivers/video/bus-device.c b/drivers/acpi/drivers/video/bus-device.c
index c1f5172..80b76c4 100644
--- a/drivers/acpi/drivers/video/bus-device.c
+++ b/drivers/acpi/drivers/video/bus-device.c
@@ -462,6 +462,36 @@ int video_dev_get_state(struct acpi_vide
 EXPORT_SYMBOL_GPL(video_dev_get_state);
 
 
+static int find_active(struct acpi_video_bus * vb)
+{
+	u32 output_state, graphics_state;
+	int ret;
+	int i;
+
+	for (i = 0; i < vb->v_dev_num; i++) {
+		if (vb->v_dev[i].v_device) {
+			ret = video_dev_get_state(vb->v_dev[i].v_device,
+						  &output_state, 
+						  &graphics_state);
+			if (ret)
+				continue;
+			if (output_state & VIDEO_OUTPUT_ACTIVE)
+				return i;
+		}
+	}
+	return -1;
+}
+
+static struct acpi_video_dev * get_video_dev(struct acpi_video_bus * vb, int index)
+{
+	if (index >= vb->v_dev_num)
+		index = 0;
+	else if (index < 0)
+		index = vb->v_dev_num - 1;
+	return vb->v_dev[index].v_device;
+}
+
+
 /**
  *	video_dev_set_state - Set the device state via _DCS
  *	@vd:	The ACPI video device
@@ -475,3 +505,54 @@ int video_dev_set_state(struct acpi_vide
 
 EXPORT_SYMBOL_GPL(video_dev_set_state);
 
+
+int video_switch_next(struct acpi_video_bus * vb)
+{
+	struct acpi_video_dev * vd, * next_vd;
+	int index;
+
+	index = find_active(vb);
+	if (index < 0)
+		return -ENODEV;
+
+	vd = get_video_dev(vb, index);
+	next_vd = get_video_dev(vb, index + 1);
+
+	/*
+	 * Turn off this device
+	 */
+	video_dev_set_state(vd, 0);
+
+	/*
+	 * Enable the next one in line
+	 */
+	video_dev_set_state(next_vd, 0x80000001);
+
+	return 0;
+}
+
+int video_switch_prev(struct acpi_video_bus * vb)
+{
+	struct acpi_video_dev * vd, * prev_vd;
+	int index;
+
+	index = find_active(vb);
+	if (index < 0)
+		return -ENODEV;
+
+	vd = get_video_dev(vb, index);
+	prev_vd = get_video_dev(vb, index - 1);
+
+	/*
+	 * Turn off this device
+	 */
+	video_dev_set_state(vd, 0);
+
+	/*
+	 * Enable the next one in line
+	 */
+	video_dev_set_state(prev_vd, 0x80000001);
+
+	return 0;
+}
+
diff --git a/drivers/acpi/drivers/video/video.h b/drivers/acpi/drivers/video/video.h
index 41c0e92..77bfad8 100644
--- a/drivers/acpi/drivers/video/video.h
+++ b/drivers/acpi/drivers/video/video.h
@@ -122,3 +122,6 @@ extern int video_bus_enable(struct acpi_
 extern int video_bus_disable(struct acpi_video_bus * vb);
 extern int video_bus_set_post(struct acpi_video_bus * vb, u32 post);
 extern int video_bus_dos_set(struct acpi_video_bus * vb, u32 value);
+
+extern int video_switch_next(struct acpi_video_bus * vb);
+extern int video_switch_prev(struct acpi_video_bus * vb);
---
0.99.9.GIT