drm/ptn-exynos: Synchronize PTN init with hotplug
authorSean Paul <seanpaul@chromium.org>
Mon, 29 Oct 2012 15:31:10 +0000 (11:31 -0400)
committerGerrit <chrome-bot@google.com>
Tue, 13 Nov 2012 17:31:16 +0000 (09:31 -0800)
Gate the DP hotplug work function on ptn3460 initailization if the
bridge chip is present. This ensures we can completely set up the
hardware before trying to read EDID and configure video.

BUG=chrome-os-partner:11158
TEST=Tested on snow, boot/suspend-resume/idle suspend-resume

Change-Id: I7f2ca812bdaaaba5350deed29939afec5d4e8a23
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/36794

drivers/gpu/drm/exynos/exynos_dp_core.c
drivers/gpu/drm/i2c/ptn3460.c
include/drm/i2c/ptn3460.h [new file with mode: 0644]

index 8d9e1a8..25e612a 100644 (file)
 #include "exynos_drm_drv.h"
 #include "exynos_drm_display.h"
 
+#ifdef CONFIG_DRM_PTN3460
+#include "i2c/ptn3460.h"
+#endif
+
 #include <plat/cpu.h>
 
 #include "exynos_dp_core.h"
@@ -942,6 +946,14 @@ static void exynos_dp_hotplug(struct work_struct *work)
 
        dp = container_of(work, struct exynos_dp_device, hotplug_work);
 
+#ifdef CONFIG_DRM_PTN3460
+       ret = ptn3460_wait_until_ready(30 * 1000);
+       if (ret) {
+               DRM_ERROR("PTN3460 is not ready, don't plug\n");
+               return;
+       }
+#endif
+
        ret = exynos_dp_detect_hpd(dp);
        if (ret) {
                /* Cable has been disconnected, we're done */
index 6dda5fb..6ec15ba 100644 (file)
 #include <linux/gpio.h>
 #include <linux/delay.h>
 
+#include "drmP.h"
+
+#include "i2c/ptn3460.h"
+
 #define PTN3460_EDID_EMULATION_ADDR            0x84
 #define PTN3460_EDID_ENABLE_EMULATION          0
 #define PTN3460_EDID_EMULATION_SELECTION       1
@@ -35,6 +39,31 @@ struct ptn3460_platform_data {
        struct delayed_work ptn_work;
 };
 
+#define PTN3460_READY_BLOCK    0
+#define PTN3460_READY_UNBLOCK  1
+
+static atomic_t ptn3460_ready;
+static wait_queue_head_t ptn3460_wait_queue;
+
+int ptn3460_wait_until_ready(int timeout_ms)
+{
+       static atomic_t wait_queue_initialized;
+       int ret;
+
+       if (atomic_add_return(1, &wait_queue_initialized) == 1)
+               init_waitqueue_head(&ptn3460_wait_queue);
+
+       ret = wait_event_timeout(ptn3460_wait_queue,
+                       atomic_read(&ptn3460_ready) == PTN3460_READY_UNBLOCK,
+                       msecs_to_jiffies(timeout_ms));
+       if (!ret) {
+               DRM_ERROR("Wait until ready timed out\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
 static int ptn3460_write_byte(struct ptn3460_platform_data *pd, char addr,
                char val)
 {
@@ -116,6 +145,9 @@ static void ptn3460_work(struct work_struct *work)
        ret = ptn3460_select_edid(pd);
        if (ret)
                dev_err(pd->dev, "Select edid failed ret=%d\n", ret);
+
+       atomic_set(&ptn3460_ready, PTN3460_READY_UNBLOCK);
+       wake_up(&ptn3460_wait_queue);
 }
 
 static int ptn3460_power_up(struct ptn3460_platform_data *pd)
@@ -143,6 +175,8 @@ static int ptn3460_power_down(struct ptn3460_platform_data *pd)
        if (work_pending(&pd->ptn_work.work))
                flush_work_sync(&pd->ptn_work.work);
 
+       atomic_set(&ptn3460_ready, PTN3460_READY_BLOCK);
+
        if (pd->gpio_rst_n > 0)
                gpio_set_value(pd->gpio_rst_n, 1);
 
diff --git a/include/drm/i2c/ptn3460.h b/include/drm/i2c/ptn3460.h
new file mode 100644 (file)
index 0000000..8e3b3ae
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2012 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DRM_I2C_PTN3460_H_
+#define _DRM_I2C_PTN3460_H_
+
+int ptn3460_wait_until_ready(int timeout_ms);
+
+#endif