From 114105ed04d96e6358478dcf9f23801d4a172d0f Mon Sep 17 00:00:00 2001 From: Shirish S Date: Fri, 5 Apr 2013 07:52:00 -0400 Subject: [PATCH] CHROMIUM: fix 800x600 resolution for exynos5 hdmi 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 Signed-off-by: Shirish S Signed-off-by: Akshay Saraswat Reviewed-on: https://gerrit.chromium.org/gerrit/47650 Reviewed-by: Sean Paul Tested-by: Yuly Novikov Commit-Queue: Shirish S --- drivers/gpu/drm/exynos/exynos_hdmi.c | 8 ++++ drivers/gpu/drm/exynos/exynos_mixer.c | 60 ++++++++++++++++++++++++--- drivers/gpu/drm/exynos/regs-mixer.h | 18 +++++++- 3 files changed, 79 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 153edeb058a9..49bee4f515fe 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -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); + } } } diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 1fd60bd2de03..4ec9b72d91bc 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -52,6 +52,12 @@ #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, diff --git a/drivers/gpu/drm/exynos/regs-mixer.h b/drivers/gpu/drm/exynos/regs-mixer.h index 81e4feea68e1..464b5046f9c0 100644 --- a/drivers/gpu/drm/exynos/regs-mixer.h +++ b/drivers/gpu/drm/exynos/regs-mixer.h @@ -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) @@ -143,6 +146,19 @@ #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 */ -- 2.20.1