|
@@ -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)
|
|
|
{
|
|
@@ -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);
|
|
|
|