CHROMIUM: fix 800x600 resolution for exynos5 hdmi
authorShirish S <s.shirish@samsung.com>
Fri, 5 Apr 2013 11:52:00 +0000 (07:52 -0400)
committerChromeBot <chrome-bot@google.com>
Wed, 8 May 2013 03:59:33 +0000 (20:59 -0700)
800x600 resolution is not cleanly supported by the exynos5 mixer block.
Hw team suggested following workaround to enable the above resolution.

1) In MIXER_CFG register, set HD_SD and HD_MODE bits to 1.
2) In MIXER0_GRAPHIC0_DXY, set MIXER0_GRP0_DX to 32.
3) In MIXER_TVOUT_CFG, Change 3D one path mode to 3D two path AFTER 1 FRAME.

BUG=chrome-os-partner:12643 & chromium:225983
TEST:
1) Booted with HDMI Connectd to Sink that supports only 800x600
2) HDMI Unplug-plug scenarios
3) S2R by running powerd_dbus_suspend

Change-Id: Ic5952ff3982c4923eabb69febeabfeb445e7a79c
Signed-off-by: Rahul Sharma <rahul.sharma@samsung.com>
Signed-off-by: Shirish S <s.shirish@samsung.com>
Signed-off-by: Akshay Saraswat <Akshay.s@samsung.com>
Reviewed-on: https://gerrit.chromium.org/gerrit/47650
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Tested-by: Yuly Novikov <ynovikov@chromium.org>
Commit-Queue: Shirish S <shirish@chromium.org>

drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/exynos/regs-mixer.h

index 153edeb..49bee4f 100644 (file)
@@ -1894,6 +1894,14 @@ static void hdmi_v14_mode_set(struct hdmi_context *hdata,
                                m->crtc_htotal - m->crtc_hdisplay - 0xe0);
                        hdmi_set_reg(tg->hact_sz, 2, m->crtc_hdisplay + 0xe0);
                }
+
+               /* Workaround 3 implementation for 800x600 resolution support */
+               if (m->hdisplay == 800 && m->vdisplay == 600
+                                       && m->clock == 40000) {
+                       hdmi_set_reg(tg->hact_st, 2,
+                               m->crtc_htotal - m->crtc_hdisplay - 0x20);
+                       hdmi_set_reg(tg->hact_sz, 2, m->crtc_hdisplay + 0x20);
+               }
        }
 }
 
index 1fd60bd..4ec9b72 100644 (file)
 #define MIXER_WIN_NR           3
 #define MIXER_DEFAULT_WIN      0
 
+enum toggle_3d_workaround_state {
+       TOGGLE_3D_STATE_ACTIVE,
+       TOGGLE_3D_STATE_ESTABLISHED,
+       TOGGLE_3D_STATE_DISABLED,
+};
+
 struct hdmi_win_data {
        dma_addr_t              dma_addr;
        dma_addr_t              chroma_dma_addr;
@@ -99,6 +105,7 @@ struct mixer_context {
        struct hdmi_win_data    win_data[MIXER_WIN_NR];
        unsigned long           event_flags;
        int                     previous_dxy;
+       enum toggle_3d_workaround_state toggle_3d_state;
 };
 
 struct mixer_scan_range {
@@ -156,6 +163,11 @@ struct mixer_scan_range scan_ranges[] = {
                .max_res = { 720, 576 },
                .mode_type = EXYNOS_MIXER_MODE_SD_PAL,
        },
+       {
+               .min_res = { 800, 600 },
+               .max_res = { 800, 600 },
+               .mode_type = EXYNOS_MIXER_MODE_HD_1080,
+       },
        {
                .min_res = { 1024, 0 },
                .max_res = { 1280, 720 },
@@ -226,6 +238,25 @@ static inline void mixer_reg_writemask(struct mixer_resources *res,
        writel(val, res->mixer_regs + reg_id);
 }
 
+static inline void mixer_workaround_action(struct mixer_context *mctx)
+{
+       struct mixer_resources *res = &mctx->mixer_res;
+
+       switch (mctx->toggle_3d_state) {
+       case TOGGLE_3D_STATE_ACTIVE:
+               mixer_reg_writemask(res, MXR_TVOUT_CFG,
+                       MXR_STATUS_3D_TWO_PATH, MXR_TVOUT_CFG_MASK);
+               mctx->toggle_3d_state = TOGGLE_3D_STATE_ESTABLISHED;
+               break;
+       case TOGGLE_3D_STATE_ESTABLISHED:
+               mixer_reg_writemask(res, MXR_TVOUT_CFG,
+                       MXR_STATUS_3D_ONE_PATH, MXR_TVOUT_CFG_MASK);
+               break;
+       default:
+               break;
+       }
+}
+
 enum exynos_mixer_mode_type exynos_mixer_get_mode_type(int width, int height)
 {
        int i;
@@ -771,10 +802,14 @@ static void mixer_graph_buffer(struct mixer_context *mctx, int win)
 
        mixer_cfg_scan(mctx, mode_width, mode_height);
 
-       /* Workaround 4 implementation for 1440x900 resolution support */
-       if (res->is_soc_exynos5) {
+       if (res->is_soc_exynos5 && win == MIXER_DEFAULT_WIN) {
+               /* Workaround 4:implementation of 1440x900 resolution */
                if (mode_width == 1440 && mode_height == 900)
                        mixer_set_layer_offset(mctx, 224);
+
+               /* Workaround 3:implementation of 800x600 resolution */
+               if (mode_width == 800 && mode_height == 600)
+                       mixer_set_layer_offset(mctx, 32);
        }
 
        mixer_cfg_rgb_fmt(mctx, mode_height);
@@ -862,10 +897,10 @@ static void mixer_win_mode_set(void *ctx,
        }
 
        DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
-                                overlay->fb_width, overlay->fb_height,
-                                overlay->fb_x, overlay->fb_y,
-                                overlay->crtc_width, overlay->crtc_height,
-                                overlay->crtc_x, overlay->crtc_y);
+                               overlay->fb_width, overlay->fb_height,
+                               overlay->fb_x, overlay->fb_y,
+                               overlay->crtc_width, overlay->crtc_height,
+                               overlay->crtc_x, overlay->crtc_y);
 
        win = overlay->zpos;
        if (win == DEFAULT_ZPOS)
@@ -893,6 +928,11 @@ static void mixer_win_mode_set(void *ctx,
        win_data->fb_width = overlay->fb_pitch / (overlay->bpp >> 3);
        win_data->fb_height = overlay->fb_height;
 
+       if (win_data->mode_width == 800 &&
+                       win_data->mode_height == 600 &&
+                       mctx->toggle_3d_state != TOGGLE_3D_STATE_ESTABLISHED)
+               mctx->toggle_3d_state = TOGGLE_3D_STATE_ACTIVE;
+
        win_data->mode_width = overlay->mode_width;
        win_data->mode_height = overlay->mode_height;
 
@@ -1015,6 +1055,8 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg)
                if (mixer_get_layer_update_count(mctx))
                        goto out;
 
+               mixer_workaround_action(mctx);
+
                for (i = 0; i < MIXER_WIN_NR; i++)
                        mctx->win_data[i].updated = false;
 
@@ -1147,6 +1189,7 @@ static void mixer_resource_poweroff(struct mixer_context *mctx)
                clk_disable(res->sclk_mixer);
        }
        mixer_win_reset(mctx);
+       mctx->toggle_3d_state = TOGGLE_3D_STATE_DISABLED;
        mctx->is_mixer_powered_on = false;
 }
 
@@ -1420,6 +1463,11 @@ static int __devinit mixer_probe(struct platform_device *pdev)
                goto fail;
 
        mctx->is_mixer_powered_on = false;
+       /* Initialize the mixer state as disabled
+        * It shall be updated in the mode set
+        */
+       mctx->toggle_3d_state = TOGGLE_3D_STATE_DISABLED;
+
        pm_runtime_enable(dev);
 
        exynos_display_attach_controller(EXYNOS_DRM_DISPLAY_TYPE_MIXER,
index 81e4fee..464b504 100644 (file)
@@ -77,6 +77,9 @@
 #define MXR_STATUS_SYNC_ENABLE         (1 << 2)
 #define MXR_STATUS_REG_RUN             (1 << 0)
 
+/* bits for MXR_TVOUT_CFG */
+#define MXR_TVOUT_CFG_MASK             0x3F
+
 /* bits for MXR_CFG */
 #define MXR_CFG_RGB601_0_255           (0 << 9)
 #define MXR_CFG_RGB601_16_235          (1 << 9)
 #define MXR_CFG_LAYER_UPDATE_COUNT0    29
 #define MXR_CFG_LAYER_UPDATE_COUNT_MASK        ((1 << 29) | (1 << 30))
 #define MXR_STATUS_SOFT_RESET           (1 << 8)
-
+/*
+ * Enable:
+ *     Side by Side Frame Packing
+ *     Stereoscopic format
+ */
+#define MXR_STATUS_3D_ONE_PATH           ((1 << 4) | (1 << 1) | (1 << 0))
+/*
+ * Enable:
+ *     Side by Side Frame Packing
+ *     3D Two path mode
+ *     Stereoscopic format
+ */
+#define MXR_STATUS_3D_TWO_PATH           ((1 << 4) | (1 << 2) | \
+                                               (1 << 1) | (1 << 0))
 #endif /* SAMSUNG_REGS_MIXER_H */