Commit f5a3d0c4 authored by Matthew Garrett's avatar Matthew Garrett Committed by Keith Packard

i915: Fix opregion notifications

opregion-based platforms will send ACPI video event 0x80 for a range of
notification types for legacy compatibility. This is interpreted as a
display switch event, which may not be appropriate in the circumstances.
When we receive such an event we should make sure that the platform is
genuinely requesting a display switch before passing that event through
to userspace.
Signed-off-by: default avatarMatthew Garrett <mjg@redhat.com>
Tested-by: default avatarAdam Jackson <ajax@redhat.com>
Signed-off-by: default avatarKeith Packard <keithp@keithp.com>
parent 2bf71160
...@@ -46,7 +46,6 @@ ...@@ -46,7 +46,6 @@
#define PREFIX "ACPI: " #define PREFIX "ACPI: "
#define ACPI_VIDEO_CLASS "video"
#define ACPI_VIDEO_BUS_NAME "Video Bus" #define ACPI_VIDEO_BUS_NAME "Video Bus"
#define ACPI_VIDEO_DEVICE_NAME "Video Device" #define ACPI_VIDEO_DEVICE_NAME "Video Device"
#define ACPI_VIDEO_NOTIFY_SWITCH 0x80 #define ACPI_VIDEO_NOTIFY_SWITCH 0x80
...@@ -1445,7 +1444,8 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event) ...@@ -1445,7 +1444,8 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch, case ACPI_VIDEO_NOTIFY_SWITCH: /* User requested a switch,
* most likely via hotkey. */ * most likely via hotkey. */
acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_proc_event(device, event, 0);
keycode = KEY_SWITCHVIDEOMODE; if (!acpi_notifier_call_chain(device, event, 0))
keycode = KEY_SWITCHVIDEOMODE;
break; break;
case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video case ACPI_VIDEO_NOTIFY_PROBE: /* User plugged in or removed a video
...@@ -1475,7 +1475,8 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event) ...@@ -1475,7 +1475,8 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event)
break; break;
} }
acpi_notifier_call_chain(device, event, 0); if (event != ACPI_VIDEO_NOTIFY_SWITCH)
acpi_notifier_call_chain(device, event, 0);
if (keycode) { if (keycode) {
input_report_key(input, keycode, 1); input_report_key(input, keycode, 1);
......
...@@ -297,19 +297,26 @@ static int intel_opregion_video_event(struct notifier_block *nb, ...@@ -297,19 +297,26 @@ static int intel_opregion_video_event(struct notifier_block *nb,
/* The only video events relevant to opregion are 0x80. These indicate /* The only video events relevant to opregion are 0x80. These indicate
either a docking event, lid switch or display switch request. In either a docking event, lid switch or display switch request. In
Linux, these are handled by the dock, button and video drivers. Linux, these are handled by the dock, button and video drivers.
We might want to fix the video driver to be opregion-aware in */
future, but right now we just indicate to the firmware that the
request has been handled */
struct opregion_acpi *acpi; struct opregion_acpi *acpi;
struct acpi_bus_event *event = data;
int ret = NOTIFY_OK;
if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0)
return NOTIFY_DONE;
if (!system_opregion) if (!system_opregion)
return NOTIFY_DONE; return NOTIFY_DONE;
acpi = system_opregion->acpi; acpi = system_opregion->acpi;
if (event->type == 0x80 && !(acpi->cevt & 0x1))
ret = NOTIFY_BAD;
acpi->csts = 0; acpi->csts = 0;
return NOTIFY_OK; return ret;
} }
static struct notifier_block intel_opregion_notifier = { static struct notifier_block intel_opregion_notifier = {
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
struct acpi_device; struct acpi_device;
#define ACPI_VIDEO_CLASS "video"
#define ACPI_VIDEO_DISPLAY_CRT 1 #define ACPI_VIDEO_DISPLAY_CRT 1
#define ACPI_VIDEO_DISPLAY_TV 2 #define ACPI_VIDEO_DISPLAY_TV 2
#define ACPI_VIDEO_DISPLAY_DVI 3 #define ACPI_VIDEO_DISPLAY_DVI 3
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment