summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c71
1 files changed, 51 insertions, 20 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index c0e92021748b..e9122db95cb2 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -115,6 +115,7 @@ struct mixer_context {
struct clk *sclk_hdmi;
struct clk *mout_mixer;
enum mixer_version_id mxr_ver;
+ int scan_value;
};
struct mixer_drv_data {
@@ -367,23 +368,11 @@ static void mixer_cfg_scan(struct mixer_context *ctx, int width, int height)
val = test_bit(MXR_BIT_INTERLACE, &ctx->flags) ?
MXR_CFG_SCAN_INTERLACE : MXR_CFG_SCAN_PROGRESSIVE;
- /* setup display size */
- if (ctx->mxr_ver == MXR_VER_128_0_0_184) {
+ if (ctx->mxr_ver == MXR_VER_128_0_0_184)
mixer_reg_write(ctx, MXR_RESOLUTION,
MXR_MXR_RES_HEIGHT(height) | MXR_MXR_RES_WIDTH(width));
- } else {
- /* choosing between proper HD and SD mode */
- if (height <= 480)
- val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD;
- else if (height <= 576)
- val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD;
- else if (height <= 720)
- val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
- else if (height <= 1080)
- val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD;
- else
- val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD;
- }
+ else
+ val |= ctx->scan_value;
mixer_reg_writemask(ctx, MXR_CFG, val, MXR_CFG_SCAN_MASK);
}
@@ -467,11 +456,6 @@ static void mixer_commit(struct mixer_context *ctx)
{
struct drm_display_mode *mode = &ctx->crtc->base.state->adjusted_mode;
- if (mode->flags & DRM_MODE_FLAG_INTERLACE)
- __set_bit(MXR_BIT_INTERLACE, &ctx->flags);
- else
- __clear_bit(MXR_BIT_INTERLACE, &ctx->flags);
-
mixer_cfg_scan(ctx, mode->hdisplay, mode->vdisplay);
mixer_cfg_rgb_fmt(ctx, mode->vdisplay);
mixer_run(ctx);
@@ -1034,6 +1018,52 @@ static int mixer_mode_valid(struct exynos_drm_crtc *crtc,
return MODE_BAD;
}
+static bool mixer_mode_fixup(struct exynos_drm_crtc *crtc,
+ const struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode)
+{
+ struct mixer_context *ctx = crtc->ctx;
+ int width = mode->hdisplay, height = mode->vdisplay, i;
+
+ struct {
+ int hdisplay, vdisplay, htotal, vtotal, scan_val;
+ } static const modes[] = {
+ { 720, 480, 858, 525, MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD },
+ { 720, 576, 864, 625, MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD },
+ { 1280, 720, 1650, 750, MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD },
+ { 1920, 1080, 2200, 1125, MXR_CFG_SCAN_HD_1080 |
+ MXR_CFG_SCAN_HD }
+ };
+
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+ __set_bit(MXR_BIT_INTERLACE, &ctx->flags);
+ else
+ __clear_bit(MXR_BIT_INTERLACE, &ctx->flags);
+
+ if (ctx->mxr_ver == MXR_VER_128_0_0_184)
+ return true;
+
+ for (i = 0; i < ARRAY_SIZE(modes); ++i)
+ if (width <= modes[i].hdisplay && height <= modes[i].vdisplay) {
+ ctx->scan_value = modes[i].scan_val;
+ if (width < modes[i].hdisplay ||
+ height < modes[i].vdisplay) {
+ adjusted_mode->hdisplay = modes[i].hdisplay;
+ adjusted_mode->hsync_start = modes[i].hdisplay;
+ adjusted_mode->hsync_end = modes[i].htotal;
+ adjusted_mode->htotal = modes[i].htotal;
+ adjusted_mode->vdisplay = modes[i].vdisplay;
+ adjusted_mode->vsync_start = modes[i].vdisplay;
+ adjusted_mode->vsync_end = modes[i].vtotal;
+ adjusted_mode->vtotal = modes[i].vtotal;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
static const struct exynos_drm_crtc_ops mixer_crtc_ops = {
.enable = mixer_enable,
.disable = mixer_disable,
@@ -1044,6 +1074,7 @@ static const struct exynos_drm_crtc_ops mixer_crtc_ops = {
.disable_plane = mixer_disable_plane,
.atomic_flush = mixer_atomic_flush,
.mode_valid = mixer_mode_valid,
+ .mode_fixup = mixer_mode_fixup,
};
static const struct mixer_drv_data exynos5420_mxr_drv_data = {