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>
m->crtc_htotal - m->crtc_hdisplay - 0xe0);
hdmi_set_reg(tg->hact_sz, 2, m->crtc_hdisplay + 0xe0);
}
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);
+ }
#define MIXER_WIN_NR 3
#define MIXER_DEFAULT_WIN 0
#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;
struct hdmi_win_data {
dma_addr_t dma_addr;
dma_addr_t chroma_dma_addr;
struct hdmi_win_data win_data[MIXER_WIN_NR];
unsigned long event_flags;
int previous_dxy;
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 {
};
struct mixer_scan_range {
.max_res = { 720, 576 },
.mode_type = EXYNOS_MIXER_MODE_SD_PAL,
},
.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 },
{
.min_res = { 1024, 0 },
.max_res = { 1280, 720 },
writel(val, res->mixer_regs + reg_id);
}
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;
enum exynos_mixer_mode_type exynos_mixer_get_mode_type(int width, int height)
{
int i;
mixer_cfg_scan(mctx, mode_width, mode_height);
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);
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);
}
mixer_cfg_rgb_fmt(mctx, mode_height);
}
DRM_DEBUG_KMS("set [%d]x[%d] at (%d,%d) to [%d]x[%d] at (%d,%d)\n",
}
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)
win = overlay->zpos;
if (win == DEFAULT_ZPOS)
win_data->fb_width = overlay->fb_pitch / (overlay->bpp >> 3);
win_data->fb_height = overlay->fb_height;
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;
win_data->mode_width = overlay->mode_width;
win_data->mode_height = overlay->mode_height;
if (mixer_get_layer_update_count(mctx))
goto out;
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;
for (i = 0; i < MIXER_WIN_NR; i++)
mctx->win_data[i].updated = false;
clk_disable(res->sclk_mixer);
}
mixer_win_reset(mctx);
clk_disable(res->sclk_mixer);
}
mixer_win_reset(mctx);
+ mctx->toggle_3d_state = TOGGLE_3D_STATE_DISABLED;
mctx->is_mixer_powered_on = false;
}
mctx->is_mixer_powered_on = false;
}
goto fail;
mctx->is_mixer_powered_on = false;
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,
pm_runtime_enable(dev);
exynos_display_attach_controller(EXYNOS_DRM_DISPLAY_TYPE_MIXER,
#define MXR_STATUS_SYNC_ENABLE (1 << 2)
#define MXR_STATUS_REG_RUN (1 << 0)
#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)
/* 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)
#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 */
#endif /* SAMSUNG_REGS_MIXER_H */