Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: mediatek: vcodec: decoder: Fix resolution clamping in TRY_FMT

In commit b018be06f3c7 ("media: mediatek: vcodec: Read max resolution
from dec_capability"), TRY_FMT clamps the resolution to the maximum
that was previously set either by default 1080p or the limit set by a
previous S_FMT call. This does not make sense when doing TRY_FMT for
the output side, which may have different capabilities.

Instead, for the output side, find the maximum resolution based on the
pixel format requested. For the capture side, find the maximum
resolution based on the currently set output format.

The maximum resolution is found from the list of per-format frame
sizes, so the patch "media: mediatek: vcodec: dec: Fix 4K frame size
enumeration" is needed.

Fixes: b018be06f3c7 ("media: mediatek: vcodec: Read max resolution from dec_capability")
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
Tested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>

authored by

Chen-Yu Tsai and committed by
Mauro Carvalho Chehab
d7abd054 3b6a81a3

+36 -12
+36 -12
drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec.c
··· 263 263 } 264 264 } 265 265 266 + static const struct v4l2_frmsize_stepwise *mtk_vdec_get_frmsize(struct mtk_vcodec_ctx *ctx, 267 + u32 pixfmt) 268 + { 269 + const struct mtk_vcodec_dec_pdata *dec_pdata = ctx->dev->vdec_pdata; 270 + int i; 271 + 272 + for (i = 0; i < *dec_pdata->num_framesizes; ++i) 273 + if (pixfmt == dec_pdata->vdec_framesizes[i].fourcc) 274 + return &dec_pdata->vdec_framesizes[i].stepwise; 275 + 276 + /* 277 + * This should never happen since vidioc_try_fmt_vid_out_mplane() 278 + * always passes through a valid format for the output side, and 279 + * for the capture side, a valid output format should already have 280 + * been set. 281 + */ 282 + WARN_ONCE(1, "Unsupported format requested.\n"); 283 + return &dec_pdata->vdec_framesizes[0].stepwise; 284 + } 285 + 266 286 static int vidioc_try_fmt(struct mtk_vcodec_ctx *ctx, struct v4l2_format *f, 267 287 const struct mtk_video_fmt *fmt) 268 288 { 269 289 struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp; 290 + const struct v4l2_frmsize_stepwise *frmsize; 291 + u32 fourcc; 270 292 271 293 pix_fmt_mp->field = V4L2_FIELD_NONE; 272 294 273 - pix_fmt_mp->width = 274 - clamp(pix_fmt_mp->width, MTK_VDEC_MIN_W, ctx->max_width); 275 - pix_fmt_mp->height = 276 - clamp(pix_fmt_mp->height, MTK_VDEC_MIN_H, ctx->max_height); 295 + /* Always apply frame size constraints from the coded side */ 296 + if (V4L2_TYPE_IS_OUTPUT(f->type)) 297 + fourcc = f->fmt.pix_mp.pixelformat; 298 + else 299 + fourcc = ctx->q_data[MTK_Q_DATA_SRC].fmt->fourcc; 300 + 301 + frmsize = mtk_vdec_get_frmsize(ctx, fourcc); 302 + pix_fmt_mp->width = clamp(pix_fmt_mp->width, MTK_VDEC_MIN_W, frmsize->max_width); 303 + pix_fmt_mp->height = clamp(pix_fmt_mp->height, MTK_VDEC_MIN_H, frmsize->max_height); 277 304 278 305 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 279 306 pix_fmt_mp->num_planes = 1; ··· 316 289 */ 317 290 tmp_w = pix_fmt_mp->width; 318 291 tmp_h = pix_fmt_mp->height; 319 - v4l_bound_align_image(&pix_fmt_mp->width, 320 - MTK_VDEC_MIN_W, 321 - ctx->max_width, 6, 322 - &pix_fmt_mp->height, 323 - MTK_VDEC_MIN_H, 324 - ctx->max_height, 6, 9); 292 + v4l_bound_align_image(&pix_fmt_mp->width, MTK_VDEC_MIN_W, frmsize->max_width, 6, 293 + &pix_fmt_mp->height, MTK_VDEC_MIN_H, frmsize->max_height, 6, 294 + 9); 325 295 326 296 if (pix_fmt_mp->width < tmp_w && 327 - (pix_fmt_mp->width + 64) <= ctx->max_width) 297 + (pix_fmt_mp->width + 64) <= frmsize->max_width) 328 298 pix_fmt_mp->width += 64; 329 299 if (pix_fmt_mp->height < tmp_h && 330 - (pix_fmt_mp->height + 64) <= ctx->max_height) 300 + (pix_fmt_mp->height + 64) <= frmsize->max_height) 331 301 pix_fmt_mp->height += 64; 332 302 333 303 mtk_v4l2_debug(0,