drm/exynos: Add drm notification of hotplug to dp
authorSean Paul <seanpaul@chromium.org>
Tue, 20 Nov 2012 15:55:18 +0000 (10:55 -0500)
committerGerrit <chrome-bot@google.com>
Tue, 20 Nov 2012 22:47:00 +0000 (14:47 -0800)
Instead of polling the connector for hotplug, use the hotplug workqueue
to fire a drm hotplug notification when we detect a cable change.

This will also update userspace when the state has changed, and notify
fbdev.

At this point in time, the patch should be a no-op, but it's important
if we want to use EDID to mode set.

BUG=chrome-os-partner:11158
TEST=Tested on snow, no regressions detected

Change-Id: Ib6b0c789f6abc45a118a04dcb8a73e8e35fd4a85
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/38408
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
drivers/gpu/drm/exynos/exynos_dp_core.c
drivers/gpu/drm/exynos/exynos_drm_connector.c

index 25e612a..0f02404 100644 (file)
@@ -10,6 +10,9 @@
  * option) any later version.
  */
 
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -915,12 +918,9 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
        irq_type = exynos_dp_get_irq_type(dp);
        switch (irq_type) {
        case DP_IRQ_TYPE_HP_CABLE_IN:
-               dev_dbg(dp->dev, "Received irq - cable in\n");
-               schedule_work(&dp->hotplug_work);
-               exynos_dp_clear_hotplug_interrupts(dp);
-               break;
        case DP_IRQ_TYPE_HP_CABLE_OUT:
-               dev_dbg(dp->dev, "Received irq - cable out\n");
+               dev_dbg(dp->dev, "Received irq - type=%d\n", irq_type);
+               schedule_work(&dp->hotplug_work);
                exynos_dp_clear_hotplug_interrupts(dp);
                break;
        case DP_IRQ_TYPE_HP_CHANGE:
@@ -946,6 +946,10 @@ static void exynos_dp_hotplug(struct work_struct *work)
 
        dp = container_of(work, struct exynos_dp_device, hotplug_work);
 
+       /* Cable is disconnected, skip dp initialization */
+       if (exynos_dp_detect_hpd(dp))
+               goto out;
+
 #ifdef CONFIG_DRM_PTN3460
        ret = ptn3460_wait_until_ready(30 * 1000);
        if (ret) {
@@ -954,12 +958,6 @@ static void exynos_dp_hotplug(struct work_struct *work)
        }
 #endif
 
-       ret = exynos_dp_detect_hpd(dp);
-       if (ret) {
-               /* Cable has been disconnected, we're done */
-               return;
-       }
-
        ret = exynos_dp_handle_edid(dp);
        if (ret) {
                dev_err(dp->dev, "unable to handle edid\n");
@@ -986,6 +984,9 @@ static void exynos_dp_hotplug(struct work_struct *work)
 
        exynos_dp_init_video(dp);
        exynos_dp_config_video(dp);
+
+out:
+       drm_helper_hpd_irq_event(dp->drm_dev);
 }
 
 static int exynos_dp_power_off(struct exynos_dp_device *dp)
index 911768e..24065fe 100644 (file)
@@ -346,6 +346,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
                break;
        case EXYNOS_DRM_DISPLAY_TYPE_FIMD:
                type = DRM_MODE_CONNECTOR_eDP;
+               connector->polled = DRM_CONNECTOR_POLL_HPD;
                break;
        default:
                type = DRM_MODE_CONNECTOR_Unknown;