MMFMWK-7806: drm: imx: dcss: check up/down scale ratios
When scaling up/down, DCSS has limits that cannot be exceeded. This patch adds checks before the plane is updated and rejects those planes that exceed the up/down scale limits. Currently, the limit is 3:1 for downscaling and 1:3 for upscaling for both video and graphics channels. When support for WR_SCL/RD_SRC will be added, these limits will increase to the following values: * video: 7:1 downscale, 1:7 upscale * graphics: 5:1 downscale, 1:5 upscale Signed-off-by: Laurentiu Palcu <laurentiu.palcu@nxp.com>pull/10/head
parent
cd2ce2b7c9
commit
305d4e7232
|
@ -119,6 +119,7 @@ static const struct drm_plane_funcs dcss_plane_funcs = {
|
|||
static int dcss_plane_atomic_check(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
struct dcss_plane *dcss_plane = to_dcss_plane(plane);
|
||||
struct drm_framebuffer *fb = state->fb;
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
|
@ -145,6 +146,13 @@ static int dcss_plane_atomic_check(struct drm_plane *plane,
|
|||
state->crtc_y + state->crtc_h > vdisplay)
|
||||
return -EINVAL;
|
||||
|
||||
if (!dcss_scaler_can_scale(dcss_plane->dcss, dcss_plane->ch_num,
|
||||
state->src_w >> 16, state->src_h >> 16,
|
||||
state->crtc_w, state->crtc_h)) {
|
||||
DRM_DEBUG_KMS("Invalid upscale/downscale ratio.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -338,6 +338,48 @@ static void dcss_scaler_fractions_set(struct dcss_soc *dcss, int ch_num,
|
|||
DCSS_SCALER_H_CHR_INC);
|
||||
}
|
||||
|
||||
/*
|
||||
* The values below are without RD_SRC/WR_SCL support. When support will be
|
||||
* added, these need to be changed accordingly.
|
||||
*/
|
||||
#define DCSS_SCALER_VIDEO_RATIO 3 /* 7 with RD_SRC/WR_SCL */
|
||||
#define DCSS_SCALER_GRAPHICS_RATIO 3 /* 5 with RD_SRC/WR_SCL */
|
||||
|
||||
/* convert to fixed point (###.# #### #### ####), easier to work with */
|
||||
#define DCSS_SCALER_VIDEO_DOWN_RATIO_FP (DCSS_SCALER_VIDEO_RATIO << 13)
|
||||
#define DCSS_SCALER_VIDEO_UP_RATIO_FP \
|
||||
((1 << 13) / DCSS_SCALER_VIDEO_RATIO)
|
||||
|
||||
#define DCSS_SCALER_GRAPHICS_DOWN_RATIO_FP (DCSS_SCALER_GRAPHICS_RATIO << 13)
|
||||
#define DCSS_SCALER_GRAPHICS_UP_RATIO_FP \
|
||||
((1 << 13) / DCSS_SCALER_GRAPHICS_RATIO)
|
||||
|
||||
static const struct dcss_scaler_ratios {
|
||||
u16 downscale_ratio;
|
||||
u16 upscale_ratio;
|
||||
} dcss_scaler_ratios_map[] = {
|
||||
{DCSS_SCALER_GRAPHICS_DOWN_RATIO_FP, DCSS_SCALER_GRAPHICS_UP_RATIO_FP},
|
||||
{DCSS_SCALER_VIDEO_DOWN_RATIO_FP, DCSS_SCALER_VIDEO_UP_RATIO_FP},
|
||||
{DCSS_SCALER_VIDEO_DOWN_RATIO_FP, DCSS_SCALER_VIDEO_UP_RATIO_FP},
|
||||
};
|
||||
|
||||
bool dcss_scaler_can_scale(struct dcss_soc *dcss, int ch_num,
|
||||
int src_xres, int src_yres,
|
||||
int dst_xres, int dst_yres)
|
||||
{
|
||||
u32 vscale_fp, hscale_fp;
|
||||
|
||||
/* Convert to fixed point. Easier to work with. */
|
||||
vscale_fp = (src_yres << 13) / dst_yres;
|
||||
hscale_fp = (src_xres << 13) / dst_xres;
|
||||
|
||||
return vscale_fp <= dcss_scaler_ratios_map[ch_num].downscale_ratio &&
|
||||
vscale_fp >= dcss_scaler_ratios_map[ch_num].upscale_ratio &&
|
||||
hscale_fp <= dcss_scaler_ratios_map[ch_num].downscale_ratio &&
|
||||
hscale_fp >= dcss_scaler_ratios_map[ch_num].upscale_ratio;
|
||||
}
|
||||
EXPORT_SYMBOL(dcss_scaler_can_scale);
|
||||
|
||||
static void dcss_scaler_coef_clr(struct dcss_soc *dcss, int ch_num)
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -77,6 +77,9 @@ void dcss_ss_enable(struct dcss_soc *dcss, bool en);
|
|||
void dcss_scaler_enable(struct dcss_soc *dcss, int ch_num, bool en);
|
||||
void dcss_scaler_setup(struct dcss_soc *dcss, int ch_num, u32 pix_format,
|
||||
int src_xres, int src_yres, int dst_xres, int dst_yres);
|
||||
bool dcss_scaler_can_scale(struct dcss_soc *dcss, int ch_num,
|
||||
int src_xres, int src_yres,
|
||||
int dst_xres, int dst_yres);
|
||||
|
||||
/* CTXLD */
|
||||
int dcss_ctxld_enable(struct dcss_soc *dcss);
|
||||
|
|
Loading…
Reference in New Issue