drm/nouveau: Intercept ACPI_VIDEO_NOTIFY_PROBE
authorHans de Goede <hdegoede@redhat.com>
Wed, 9 Nov 2016 17:17:44 +0000 (18:17 +0100)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 16 Nov 2016 23:50:37 +0000 (09:50 +1000)
commit3a6536c51d5db3adf58dcd466a3aee6233b58544
tree1ed563a1d9eeeac4a70c3206d3cb5a19fd11bd99
parentdc2b65592801b80fe8944cb84f635e1725a7bd98
drm/nouveau: Intercept ACPI_VIDEO_NOTIFY_PROBE

Various notebooks with nvidia GPUs generate an ACPI_VIDEO_NOTIFY_PROBE
acpi-video event when an external device gets plugged in (and again on
modesets on that connector), the default behavior in the acpi-video
driver for this is to send a KEY_SWITCHVIDEOMODE evdev event, which
causes e.g. gnome-settings-daemon to ask us to rescan the connectors
(good), but also causes g-s-d to switch to mirror mode on a newly plugged
monitor rather then using the monitor to extend the desktop (bad)
as KEY_SWITCHVIDEOMODE is supposed to switch between extend the desktop
vs mirror mode.

More troublesome are the repeated ACPI_VIDEO_NOTIFY_PROBE events on
changing the mode on the connector, which cause g-s-d to switch
between mirror/extend mode, which causes a new ACPI_VIDEO_NOTIFY_PROBE
event and we end up with an endless loop.

This commit fixes this by adding an acpi notifier block handler to
nouveau_display.c to intercept ACPI_VIDEO_NOTIFY_PROBE and:

1) Wake-up runtime suspended GPUs and call drm_helper_hpd_irq_event()
   on them, this is necessary in some cases for the GPU to detect connector
   hotplug events while runtime suspended
2) Return NOTIFY_BAD to stop acpi-video from emitting a bogus
   KEY_SWITCHVIDEOMODE key-press event

There already is another acpi notifier block handler registered in
drivers/gpu/drm/nouveau/nvkm/engine/device/acpi.c, but that is not
suitable since that one gets unregistered on runtime suspend, and
we also want to intercept ACPI_VIDEO_NOTIFY_PROBE when runtime suspended.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drv.h