drm/exynos: Convert dp driver to use panel_ops
authorSean Paul <seanpaul@chromium.org>
Thu, 25 Oct 2012 15:53:01 +0000 (11:53 -0400)
committerGerrit <chrome-bot@google.com>
Tue, 13 Nov 2012 17:31:11 +0000 (09:31 -0800)
This patch changes the dp driver to implement panel_ops. This gets
rid of the dp_dev hack that was introduced when dp moved into drm.

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

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

index 2b58af1..f20d0c0 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <video/exynos_dp.h>
 #include "exynos_drm_drv.h"
+#include "exynos_drm_display.h"
 
 #include <plat/cpu.h>
 
@@ -955,7 +956,7 @@ static void exynos_dp_hotplug(struct work_struct *work)
 
        if (dp->training_type == SW_LINK_TRAINING)
                ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
-                                               dp->video_info->link_rate);
+                       dp->video_info->link_rate);
        else
                ret = exynos_dp_set_hw_link_train(dp,
                        dp->video_info->lane_count, dp->video_info->link_rate);
@@ -975,6 +976,89 @@ static void exynos_dp_hotplug(struct work_struct *work)
        exynos_dp_config_video(dp);
 }
 
+static int exynos_dp_power_off(struct exynos_dp_device *dp)
+{
+       disable_irq(dp->irq);
+
+       if (work_pending(&dp->hotplug_work))
+               flush_work_sync(&dp->hotplug_work);
+
+       if (dp->phy_ops.phy_exit)
+               dp->phy_ops.phy_exit();
+
+       clk_disable(dp->clock);
+       return 0;
+}
+
+static int exynos_dp_power_on(struct exynos_dp_device *dp)
+{
+       if (dp->phy_ops.phy_init)
+               dp->phy_ops.phy_init();
+
+       clk_enable(dp->clock);
+
+       exynos_dp_init_dp(dp);
+
+       enable_irq(dp->irq);
+
+       return 0;
+}
+
+static int exynos_dp_power(void *ctx, int mode)
+{
+       struct exynos_dp_device *dp = ctx;
+
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+               return exynos_dp_power_on(dp);
+
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               return exynos_dp_power_off(dp);
+
+       default:
+               DRM_ERROR("Unknown dpms mode %d\n", mode);
+       }
+       return -EINVAL;
+}
+
+static int exynos_dp_check_timing(void *ctx, void *timing)
+{
+       /*
+        * TODO(seanpaul): The datasheet isn't terribly descriptive about the
+        * limitations we have here. It's not vitally important to implement
+        * this right now, but should be implemented once we use EDID to mode
+        * set.
+        */
+       return 0;
+}
+
+static bool exynos_dp_is_connected(void *ctx)
+{
+       struct exynos_dp_device *dp = ctx;
+       int ret;
+
+       ret = exynos_dp_detect_hpd(dp);
+       return !ret;
+}
+
+static int exynos_dp_subdrv_probe(void *ctx, struct drm_device *drm_dev)
+{
+       struct exynos_dp_device *dp = ctx;
+
+       dp->drm_dev = drm_dev;
+
+       return 0;
+}
+
+static struct exynos_panel_ops dp_panel_ops = {
+       .subdrv_probe = exynos_dp_subdrv_probe,
+       .is_connected = exynos_dp_is_connected,
+       .check_timing = exynos_dp_check_timing,
+       .power = exynos_dp_power,
+};
+
 static int __devinit exynos_dp_probe(struct platform_device *pdev)
 {
        struct resource *res;
@@ -1052,8 +1136,12 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
 
        dp->training_type = pdata->training_type;
        dp->video_info = pdata->video_info;
-       if (pdata->phy_init)
-               pdata->phy_init();
+       if (pdata->phy_init) {
+               dp->phy_ops.phy_init = pdata->phy_init;
+               dp->phy_ops.phy_init();
+       }
+       if (pdata->phy_exit)
+               dp->phy_ops.phy_exit = pdata->phy_exit;
 
        INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
 
@@ -1068,7 +1156,8 @@ static int __devinit exynos_dp_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, dp);
 
-       exynos_fimd_dp_attach(dp->dev);
+       exynos_display_attach_panel(EXYNOS_DRM_DISPLAY_TYPE_FIMD, &dp_panel_ops,
+                       dp);
 
        return 0;
 
@@ -1089,14 +1178,13 @@ err_dp:
 
 static int __devexit exynos_dp_remove(struct platform_device *pdev)
 {
-       struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
        struct exynos_dp_device *dp = platform_get_drvdata(pdev);
 
        if (work_pending(&dp->hotplug_work))
                flush_work_sync(&dp->hotplug_work);
 
-       if (pdata && pdata->phy_exit)
-               pdata->phy_exit();
+       if (dp->phy_ops.phy_exit)
+               dp->phy_ops.phy_exit();
 
        if (gpio_is_valid(dp->hpd_gpio))
                gpio_free(dp->hpd_gpio);
@@ -1115,59 +1203,33 @@ static int __devexit exynos_dp_remove(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM_SLEEP
-int exynos_dp_suspend(struct device *dev)
+static int exynos_dp_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
-       struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
        struct exynos_dp_device *dp = platform_get_drvdata(pdev);
 
-       disable_irq(dp->irq);
-
-       if (work_pending(&dp->hotplug_work))
-               flush_work_sync(&dp->hotplug_work);
-
-       if (pdata && pdata->phy_exit)
-               pdata->phy_exit();
-
-       clk_disable(dp->clock);
-
-       return 0;
+       return exynos_dp_power(dp, DRM_MODE_DPMS_SUSPEND);
 }
 
-int exynos_dp_resume(struct device *dev)
+static int exynos_dp_resume(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
-       struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
        struct exynos_dp_device *dp = platform_get_drvdata(pdev);
 
-       if (pdata && pdata->phy_init)
-               pdata->phy_init();
-
-       clk_enable(dp->clock);
-
-       exynos_dp_init_dp(dp);
-
-       enable_irq(dp->irq);
-
-       return 0;
-}
-#else
-int exynos_dp_suspend(struct device *dev)
-{
-       return 0;
-}
-
-int exynos_dp_resume(struct device *dev)
-{
-       return 0;
+       return exynos_dp_power(dp, DRM_MODE_DPMS_ON);
 }
 #endif
 
+static const struct dev_pm_ops dp_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
+};
+
 struct platform_driver dp_driver = {
        .probe          = exynos_dp_probe,
        .remove         = __devexit_p(exynos_dp_remove),
        .driver         = {
                .name   = "s5p-dp",
                .owner  = THIS_MODULE,
+               .pm     = &dp_pm_ops,
        },
 };
index 61a170a..13d2cc1 100644 (file)
@@ -33,24 +33,27 @@ struct link_train {
        enum link_training_state lt_state;
 };
 
+struct dp_phy_ops {
+       void (*phy_init)(void);
+       void (*phy_exit)(void);
+};
+
 struct exynos_dp_device {
        struct device           *dev;
+       struct drm_device       *drm_dev;
        struct resource         *res;
        struct clk              *clock;
        unsigned int            irq;
        void __iomem            *reg_base;
        int                     hpd_gpio;
 
+       struct dp_phy_ops       phy_ops;
        struct video_info       *video_info;
        enum link_training_type training_type;
        struct link_train       link_train;
        struct work_struct      hotplug_work;
 };
 
-/* exynos_dp_core.c */
-int exynos_dp_suspend(struct device *dev);
-int exynos_dp_resume(struct device *dev);
-
 /* exynos_dp_reg.c */
 void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable);
 void exynos_dp_stop_video(struct exynos_dp_device *dp);
index af5f824..4641b9a 100644 (file)
@@ -100,23 +100,6 @@ struct fimd_context {
        struct exynos_drm_panel_info *panel;
 };
 
-static struct device *dp_dev;
-
-void exynos_fimd_dp_attach(struct device *dev)
-{
-       DRM_DEBUG_KMS("%s. %s.\n", __FILE__, __func__);
-       dp_dev = dev;
-}
-
-static bool fimd_display_is_connected(void *ctx)
-{
-       DRM_DEBUG_KMS("%s\n", __FILE__);
-
-       /* TODO. */
-
-       return true;
-}
-
 static struct exynos_drm_panel_info *fimd_get_panel(void *ctx)
 {
        struct fimd_context *fimd_ctx = ctx;
@@ -126,28 +109,6 @@ static struct exynos_drm_panel_info *fimd_get_panel(void *ctx)
        return fimd_ctx->panel;
 }
 
-static int fimd_check_timing(void *ctx, void *timing)
-{
-       struct fimd_context *fimd_ctx = ctx;
-       struct fb_videomode *check_timing = timing;
-       int i;
-
-       DRM_DEBUG_KMS("%s\n", __FILE__);
-
-       for (i = 0;i< MAX_NR_PANELS;i++) {
-               if (fimd_ctx->panel[i].timing.xres == -1 &&
-                   fimd_ctx->panel[i].timing.yres == -1)
-                        break;
-
-               if (fimd_ctx->panel[i].timing.xres == check_timing->xres &&
-                   fimd_ctx->panel[i].timing.yres == check_timing->yres &&
-                   fimd_ctx->panel[i].timing.refresh == check_timing->refresh)
-                       return 0;
-       }
-
-       return -EINVAL;
-}
-
 static int fimd_power_on(struct fimd_context *ctx, bool enable);
 
 static int fimd_power(void *ctx, int mode)
@@ -226,11 +187,6 @@ static void fimd_commit(void *ctx)
        writel(val, fimd_ctx->regs + VIDCON0);
 }
 
-static struct exynos_panel_ops fimd_panel_ops = {
-       .is_connected = fimd_display_is_connected,
-       .check_timing = fimd_check_timing,
-};
-
 static int fimd_enable_vblank(void *ctx, int pipe)
 {
        struct fimd_context *fimd_ctx = ctx;
@@ -854,13 +810,7 @@ static int fimd_power_on(struct fimd_context *fimd_ctx, bool enable)
                        writel(MIE_CLK_ENABLE, fimd_ctx->regs + DPCLKCON);
 
                fimd_window_resume(fimd_ctx);
-
-               if (dp_dev)
-                       exynos_dp_resume(dp_dev);
        } else {
-               if (dp_dev)
-                       exynos_dp_suspend(dp_dev);
-
                /*
                 * We need to make sure that all windows are disabled before we
                 * suspend that connector. Otherwise we might try to scan from
@@ -1068,8 +1018,6 @@ static int __devinit fimd_probe(struct platform_device *pdev)
 
        exynos_display_attach_controller(EXYNOS_DRM_DISPLAY_TYPE_FIMD,
                        &fimd_controller_ops, fimd_ctx);
-       exynos_display_attach_panel(EXYNOS_DRM_DISPLAY_TYPE_FIMD,
-                       &fimd_panel_ops, fimd_ctx);
 
        return 0;