1
0
Fork 0

MLK-24998-7 drm/imx: lcdifv3: implement mode_valid() for CRTC

Add mode_valid() implementation for CRTC to filter out any
mode which cannot be supported by LCDIFv3. Only check the
CEA and DMT modes for pixel clock round rate is same with
the value from mode.

Signed-off-by: Fancy Fang <chen.fang@nxp.com>
Reviewed-by: Liu Ying <victor.liu@nxp.com>
(cherry picked from commit f252a44da9f90951614c0bf513df6bd4d145e76e)
zero-colors
Fancy Fang 2020-11-16 15:27:55 +08:00
parent 76bc28934e
commit d7e6489482
3 changed files with 44 additions and 0 deletions

View File

@ -192,12 +192,44 @@ static void lcdifv3_crtc_atomic_disable(struct drm_crtc *crtc,
pm_runtime_put(lcdifv3_crtc->dev->parent);
}
static enum drm_mode_status lcdifv3_crtc_mode_valid(struct drm_crtc * crtc,
const struct drm_display_mode *mode)
{
u8 vic;
long rate;
const struct drm_display_mode *dmt;
struct lcdifv3_crtc *lcdifv3_crtc = to_lcdifv3_crtc(crtc);
struct lcdifv3_soc *lcdifv3 = dev_get_drvdata(lcdifv3_crtc->dev->parent);
/* check CEA-861 mode */
vic = drm_match_cea_mode(mode);
if (vic)
goto check_pix_clk;
/* check DMT mode */
dmt = drm_mode_find_dmt(crtc->dev, mode->hdisplay, mode->vdisplay,
drm_mode_vrefresh(mode), false);
if (dmt && drm_mode_equal(mode, dmt))
goto check_pix_clk;
return MODE_OK;
check_pix_clk:
rate = lcdifv3_pix_clk_round_rate(lcdifv3, mode->clock * 1000);
if (rate <= 0 || rate != mode->clock * 1000)
return MODE_BAD;
return MODE_OK;
}
static const struct drm_crtc_helper_funcs lcdifv3_helper_funcs = {
.atomic_check = lcdifv3_crtc_atomic_check,
.atomic_begin = lcdifv3_crtc_atomic_begin,
.atomic_flush = lcdifv3_crtc_atomic_flush,
.atomic_enable = lcdifv3_crtc_atomic_enable,
.atomic_disable = lcdifv3_crtc_atomic_disable,
.mode_valid = lcdifv3_crtc_mode_valid,
};
static int lcdifv3_enable_vblank(struct drm_crtc *crtc)

View File

@ -512,6 +512,16 @@ void lcdifv3_disable_controller(struct lcdifv3_soc *lcdifv3)
}
EXPORT_SYMBOL(lcdifv3_disable_controller);
long lcdifv3_pix_clk_round_rate(struct lcdifv3_soc *lcdifv3,
unsigned long rate)
{
if (unlikely(!rate))
return -EINVAL;
return clk_round_rate(lcdifv3->clk_pix, rate);
}
EXPORT_SYMBOL(lcdifv3_pix_clk_round_rate);
static int hdmimix_lcdif3_setup(struct lcdifv3_soc *lcdifv3)
{
struct device *dev = lcdifv3->dev;

View File

@ -30,5 +30,7 @@ void lcdifv3_en_shadow_load(struct lcdifv3_soc *lcdifv3);
void lcdifv3_enable_controller(struct lcdifv3_soc *lcdifv3);
void lcdifv3_disable_controller(struct lcdifv3_soc *lcdifv3);
void lcdifv3_dump_registers(struct lcdifv3_soc *lcdifv3);
long lcdifv3_pix_clk_round_rate(struct lcdifv3_soc *lcdifv3,
unsigned long rate);
#endif