summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_display.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-11-17 10:08:29 +1000
committerDave Airlie <airlied@redhat.com>2016-11-17 10:08:29 +1000
commit08859ede42e7b0a1bf7363669a9ed0177b07bc2e (patch)
tree932b86f6c13b9045df89fb98e361c7f62dd41cf5 /drivers/gpu/drm/nouveau/nouveau_display.c
parentb7c0e47d98249c2ddf21ea197b651093c6aaee00 (diff)
parented828666a797bf78c12e83e847516588e1b1cb11 (diff)
downloadlinux-08859ede42e7b0a1bf7363669a9ed0177b07bc2e.tar.bz2
Merge branch 'linux-4.10' of git://github.com/skeggsb/linux into drm-next
- GP102/GP104 devinit (suspend/resume, optimus) hang fix - GP102/GP104 hardware cursor fix - Fix for a regression on some non-MST monitors that was caused by the MST work - Workaround for certain laptops where ACPI sends display hotkey presses on a modeset, causing gnome-settings-daemon to go into a continuous loop * 'linux-4.10' of git://github.com/skeggsb/linux: drm/nouveau/disp/gp102: rename from gp104 drm/nouveau/ce/gp102: rename from gp104 drm/nouveau/fb/gp102: rename from gp104 drm/nouveau/disp/gp102: fix cursor/overlay immediate channel indices drm/nouveau/disp/nv50-: specify ctrl/user separately when constructing classes drm/nouveau/disp/nv50-: split chid into chid.ctrl and chid.user drm/nouveau: Intercept ACPI_VIDEO_NOTIFY_PROBE drm/nouveau/devinit/gm200: drop pmu reset sequence drm/nouveau/devinit/gm200: replace while loops with PTIMER-based timeout loops drm/nouveau/pmu/gp102: initial implementation drm/nouveau/pmu/gp100: initial implementation drm/nouveau/pmu: execute reset before running devinit drm/nouveau/pmu: move ucode handling into gt215 implementation drm/nouveau/core: initial support for GP102 drm/nouveau/device/pci: fix oops if no mmu subdev present drm/nouveau/kms/nv50: avoid touching DP_MSTM_CTRL if !DP_MST_CAP
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_display.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c61
1 files changed, 60 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 5698687bc197..bd37ae127582 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -24,6 +24,7 @@
*
*/
+#include <acpi/video.h>
#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
@@ -348,6 +349,55 @@ static struct nouveau_drm_prop_enum_list dither_depth[] = {
} \
} while(0)
+#ifdef CONFIG_ACPI
+
+/*
+ * Hans de Goede: This define belongs in acpi/video.h, I've submitted a patch
+ * to the acpi subsys to move it there from drivers/acpi/acpi_video.c .
+ * This should be dropped once that is merged.
+ */
+#ifndef ACPI_VIDEO_NOTIFY_PROBE
+#define ACPI_VIDEO_NOTIFY_PROBE 0x81
+#endif
+
+static void
+nouveau_display_acpi_work(struct work_struct *work)
+{
+ struct nouveau_drm *drm = container_of(work, typeof(*drm), acpi_work);
+
+ pm_runtime_get_sync(drm->dev->dev);
+
+ drm_helper_hpd_irq_event(drm->dev);
+
+ pm_runtime_mark_last_busy(drm->dev->dev);
+ pm_runtime_put_sync(drm->dev->dev);
+}
+
+static int
+nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val,
+ void *data)
+{
+ struct nouveau_drm *drm = container_of(nb, typeof(*drm), acpi_nb);
+ struct acpi_bus_event *info = data;
+
+ if (!strcmp(info->device_class, ACPI_VIDEO_CLASS)) {
+ if (info->type == ACPI_VIDEO_NOTIFY_PROBE) {
+ /*
+ * This may be the only indication we receive of a
+ * connector hotplug on a runtime suspended GPU,
+ * schedule acpi_work to check.
+ */
+ schedule_work(&drm->acpi_work);
+
+ /* acpi-video should not generate keypresses for this */
+ return NOTIFY_BAD;
+ }
+ }
+
+ return NOTIFY_DONE;
+}
+#endif
+
int
nouveau_display_init(struct drm_device *dev)
{
@@ -488,7 +538,7 @@ nouveau_display_create(struct drm_device *dev)
if (nouveau_modeset != 2 && drm->vbios.dcb.entries) {
static const u16 oclass[] = {
- GP104_DISP,
+ GP102_DISP,
GP100_DISP,
GM200_DISP,
GM107_DISP,
@@ -532,6 +582,12 @@ nouveau_display_create(struct drm_device *dev)
}
nouveau_backlight_init(dev);
+#ifdef CONFIG_ACPI
+ INIT_WORK(&drm->acpi_work, nouveau_display_acpi_work);
+ drm->acpi_nb.notifier_call = nouveau_display_acpi_ntfy;
+ register_acpi_notifier(&drm->acpi_nb);
+#endif
+
return 0;
vblank_err:
@@ -547,6 +603,9 @@ nouveau_display_destroy(struct drm_device *dev)
{
struct nouveau_display *disp = nouveau_display(dev);
+#ifdef CONFIG_ACPI
+ unregister_acpi_notifier(&nouveau_drm(dev)->acpi_nb);
+#endif
nouveau_backlight_exit(dev);
nouveau_display_vblank_fini(dev);