Hello Andrzej, Andrzej Hajda wrote: > MIXER in SoCs prior to Exynos5420 supports only 4 video modes: > 720x480, 720x576, 1280x720, 1920x1080. Support for other modes can be > enabled by manipulating timings of HDMI. To allow it MIXER must pass > actual video mode to HDMI, the proper way to do it is to modify > adjusted_mode property in crtc::mode_fixup callback. Adding such callback > allows also to simplify mixer_cfg_scan code - choosing mode is performed > already in crtc::mode_fixup. mode_fixup is also better place to check > interlace flag. Reviewed-by: Tobias Jakobi <tjakobi@xxxxxxxxxxxxxxxxxxxxx> > Signed-off-by: Andrzej Hajda <a.hajda@xxxxxxxxxxx> > --- > drivers/gpu/drm/exynos/exynos_mixer.c | 70 +++++++++++++++++++++++++---------- > 1 file changed, 50 insertions(+), 20 deletions(-) > > diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c > index f6ea9d9..5aae82b 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); > @@ -1033,6 +1017,51 @@ 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, > @@ -1043,6 +1072,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 = { > -- To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html