drm/exynos: add display-mode-check operation to exynos_mixer_ops struct
authorRahul Sharma <rahul.sharma@samsung.com>
Tue, 15 Jan 2013 13:11:05 +0000 (08:11 -0500)
committerInki Dae <inki.dae@samsung.com>
Thu, 21 Feb 2013 06:00:27 +0000 (15:00 +0900)
This patch adds the display mode check operation to exynos_mixer_ops
in drm-common-hdmi. In Exynos SoCs, mixer IP can put certain restrictions
on the proposed display modes. These restriction needs to be considered
during mode negotiation, which happens immediately after edid parsing.

Both, mixer check-mode and hdmi check-timing callbacks are called one after
another and ANDed result is returned back.

Signed-off-by: Rahul Sharma <rahul.sharma@samsung.com>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Inki Dae <inki.dae@samsung.com>
drivers/gpu/drm/exynos/exynos_drm_hdmi.c
drivers/gpu/drm/exynos/exynos_drm_hdmi.h
drivers/gpu/drm/exynos/exynos_hdmi.c

index 28644539b3056620912df744aaac7cccad6fa9a4..7c27df03c9fff3154093c45cf0749d414aa44a0f 100644 (file)
@@ -124,9 +124,21 @@ static struct edid *drm_hdmi_get_edid(struct device *dev,
 static int drm_hdmi_check_timing(struct device *dev, void *timing)
 {
        struct drm_hdmi_context *ctx = to_context(dev);
+       int ret = 0;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
+       /*
+       * Both, mixer and hdmi should be able to handle the requested mode.
+       * If any of the two fails, return mode as BAD.
+       */
+
+       if (mixer_ops && mixer_ops->check_timing)
+               ret = mixer_ops->check_timing(ctx->mixer_ctx->ctx, timing);
+
+       if (ret)
+               return ret;
+
        if (hdmi_ops && hdmi_ops->check_timing)
                return hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, timing);
 
index d80516fc9ed7efd4675dd582ba3601118a4ffbad..b7faa3662307eec4e9ead166f2fb1b36fc0cf241 100644 (file)
@@ -32,7 +32,7 @@ struct exynos_hdmi_ops {
        bool (*is_connected)(void *ctx);
        struct edid *(*get_edid)(void *ctx,
                        struct drm_connector *connector);
-       int (*check_timing)(void *ctx, void *timing);
+       int (*check_timing)(void *ctx, struct fb_videomode *timing);
        int (*power_on)(void *ctx, int mode);
 
        /* manager */
@@ -58,6 +58,9 @@ struct exynos_mixer_ops {
        void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay);
        void (*win_commit)(void *ctx, int zpos);
        void (*win_disable)(void *ctx, int zpos);
+
+       /* display */
+       int (*check_timing)(void *ctx, struct fb_videomode *timing);
 };
 
 void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx);
index fbab3c4686031ce9c07a1b19546ab73ddb4f92e7..ba330157552568129ed3abc3d3354c49b330fe3f 100644 (file)
@@ -1457,21 +1457,20 @@ static int hdmi_v14_check_timing(struct fb_videomode *check_timing)
        return -EINVAL;
 }
 
-static int hdmi_check_timing(void *ctx, void *timing)
+static int hdmi_check_timing(void *ctx, struct fb_videomode *timing)
 {
        struct hdmi_context *hdata = ctx;
-       struct fb_videomode *check_timing = timing;
 
        DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
 
-       DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", check_timing->xres,
-                       check_timing->yres, check_timing->refresh,
-                       check_timing->vmode);
+       DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", timing->xres,
+                       timing->yres, timing->refresh,
+                       timing->vmode);
 
        if (hdata->type == HDMI_TYPE13)
-               return hdmi_v13_check_timing(check_timing);
+               return hdmi_v13_check_timing(timing);
        else
-               return hdmi_v14_check_timing(check_timing);
+               return hdmi_v14_check_timing(timing);
 }
 
 static void hdmi_set_acr(u32 freq, u8 *acr)