From: Jernej Skrabec <jernej.skra...@gmail.com> Account for U/V channel subsampling by reducing the dot clock and resolution with a divider in the DE3 timing controller if a YUV format is selected.
Signed-off-by: Jernej Skrabec <jernej.skra...@gmail.com> Signed-off-by: Ryan Walklin <r...@testtoast.com> -- Changelog v5..v6: - Update to obtain color format from mixer if required. --- drivers/gpu/drm/sun4i/sun4i_tcon.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 960e83c8291da..4cd3a07daf6e4 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -37,6 +37,7 @@ #include "sun4i_tcon.h" #include "sun6i_mipi_dsi.h" #include "sun4i_tcon_dclk.h" +#include "sun8i_mixer.h" #include "sun8i_tcon_top.h" #include "sunxi_engine.h" @@ -598,14 +599,27 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, const struct drm_display_mode *mode) { - unsigned int bp, hsync, vsync, vtotal; + unsigned int bp, hsync, vsync, vtotal, div; + struct sun4i_crtc *scrtc = tcon->crtc; + struct sun8i_mixer *mixer = engine_to_sun8i_mixer(scrtc->engine); + u8 clk_delay; u32 val; WARN_ON(!tcon->quirks->has_channel_1); + switch (mixer->color_model.format) { + case MEDIA_BUS_FMT_UYYVYY8_0_5X24: + case MEDIA_BUS_FMT_UYYVYY10_0_5X30: + div = 2; + break; + default: + div = 1; + break; + } + /* Configure the dot clock */ - clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000); + clk_set_rate(tcon->sclk1, mode->crtc_clock * 1000 / div); /* Adjust clock delay */ clk_delay = sun4i_tcon_get_clk_delay(mode, 1); @@ -624,17 +638,17 @@ static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, /* Set the input resolution */ regmap_write(tcon->regs, SUN4I_TCON1_BASIC0_REG, - SUN4I_TCON1_BASIC0_X(mode->crtc_hdisplay) | + SUN4I_TCON1_BASIC0_X(mode->crtc_hdisplay / div) | SUN4I_TCON1_BASIC0_Y(mode->crtc_vdisplay)); /* Set the upscaling resolution */ regmap_write(tcon->regs, SUN4I_TCON1_BASIC1_REG, - SUN4I_TCON1_BASIC1_X(mode->crtc_hdisplay) | + SUN4I_TCON1_BASIC1_X(mode->crtc_hdisplay / div) | SUN4I_TCON1_BASIC1_Y(mode->crtc_vdisplay)); /* Set the output resolution */ regmap_write(tcon->regs, SUN4I_TCON1_BASIC2_REG, - SUN4I_TCON1_BASIC2_X(mode->crtc_hdisplay) | + SUN4I_TCON1_BASIC2_X(mode->crtc_hdisplay / div) | SUN4I_TCON1_BASIC2_Y(mode->crtc_vdisplay)); /* Set horizontal display timings */ @@ -642,8 +656,8 @@ static void sun4i_tcon1_mode_set(struct sun4i_tcon *tcon, DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n", mode->htotal, bp); regmap_write(tcon->regs, SUN4I_TCON1_BASIC3_REG, - SUN4I_TCON1_BASIC3_H_TOTAL(mode->crtc_htotal) | - SUN4I_TCON1_BASIC3_H_BACKPORCH(bp)); + SUN4I_TCON1_BASIC3_H_TOTAL(mode->crtc_htotal / div) | + SUN4I_TCON1_BASIC3_H_BACKPORCH(bp / div)); bp = mode->crtc_vtotal - mode->crtc_vsync_start; DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n", -- 2.48.1