media: iris: Add support for QC08C format for decoder

Introduce handling for the QC08C format in the decoder. QC08C format is
NV12 with UBWC compression. Update format checks and configuration to
enable decoding of QC08C streams.

Signed-off-by: Dikshita Agarwal <dikshita.agarwal@oss.qualcomm.com>
Reviewed-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
Signed-off-by: Bryan O'Donoghue <bod@kernel.org>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
This commit is contained in:
Dikshita Agarwal 2025-10-08 15:22:26 +05:30 committed by Hans Verkuil
parent 7c1f3bd58f
commit cfd71b14b0
6 changed files with 72 additions and 19 deletions

View File

@ -261,7 +261,10 @@ int iris_get_buffer_size(struct iris_inst *inst,
case BUF_INPUT:
return iris_dec_bitstream_buffer_size(inst);
case BUF_OUTPUT:
return iris_yuv_buffer_size_nv12(inst);
if (inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_QC08C)
return iris_yuv_buffer_size_qc08c(inst);
else
return iris_yuv_buffer_size_nv12(inst);
case BUF_DPB:
return iris_yuv_buffer_size_qc08c(inst);
default:

View File

@ -774,20 +774,21 @@ static int iris_hfi_gen1_set_raw_format(struct iris_inst *inst, u32 plane)
pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat;
if (iris_split_mode_enabled(inst)) {
fmt.buffer_type = HFI_BUFFER_OUTPUT;
fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ?
HFI_COLOR_FORMAT_NV12_UBWC : 0;
fmt.format = HFI_COLOR_FORMAT_NV12_UBWC;
ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt));
if (ret)
return ret;
fmt.buffer_type = HFI_BUFFER_OUTPUT2;
fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0;
fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ?
HFI_COLOR_FORMAT_NV12 : HFI_COLOR_FORMAT_NV12_UBWC;
ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt));
} else {
fmt.buffer_type = HFI_BUFFER_OUTPUT;
fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FORMAT_NV12 : 0;
fmt.format = pixelformat == V4L2_PIX_FMT_NV12 ?
HFI_COLOR_FORMAT_NV12 : HFI_COLOR_FORMAT_NV12_UBWC;
ret = hfi_gen1_set_property(inst, ptype, &fmt, sizeof(fmt));
}
@ -806,6 +807,9 @@ static int iris_hfi_gen1_set_format_constraints(struct iris_inst *inst, u32 plan
const u32 ptype = HFI_PROPERTY_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO;
struct hfi_uncompressed_plane_actual_constraints_info pconstraint;
if (inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_QC08C)
return 0;
pconstraint.buffer_type = HFI_BUFFER_OUTPUT2;
pconstraint.num_planes = 2;
pconstraint.plane_format[0].stride_multiples = 128;

View File

@ -443,7 +443,8 @@ static int iris_hfi_gen2_set_colorformat(struct iris_inst *inst, u32 plane)
if (inst->domain == DECODER) {
pixelformat = inst->fmt_dst->fmt.pix_mp.pixelformat;
hfi_colorformat = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FMT_NV12 : 0;
hfi_colorformat = pixelformat == V4L2_PIX_FMT_NV12 ?
HFI_COLOR_FMT_NV12 : HFI_COLOR_FMT_NV12_UBWC;
} else {
pixelformat = inst->fmt_src->fmt.pix_mp.pixelformat;
hfi_colorformat = pixelformat == V4L2_PIX_FMT_NV12 ? HFI_COLOR_FMT_NV12 : 0;

View File

@ -15,12 +15,17 @@
#define DEFAULT_WIDTH 320
#define DEFAULT_HEIGHT 240
enum iris_fmt_type {
enum iris_fmt_type_out {
IRIS_FMT_H264,
IRIS_FMT_HEVC,
IRIS_FMT_VP9,
};
enum iris_fmt_type_cap {
IRIS_FMT_NV12,
IRIS_FMT_QC08C,
};
struct iris_fmt {
u32 pixfmt;
u32 type;

View File

@ -34,7 +34,8 @@ int iris_get_mbpf(struct iris_inst *inst)
bool iris_split_mode_enabled(struct iris_inst *inst)
{
return inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_NV12;
return inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_NV12 ||
inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_QC08C;
}
void iris_helper_buffers_done(struct iris_inst *inst, unsigned int type,

View File

@ -67,7 +67,7 @@ void iris_vdec_inst_deinit(struct iris_inst *inst)
kfree(inst->fmt_src);
}
static const struct iris_fmt iris_vdec_formats[] = {
static const struct iris_fmt iris_vdec_formats_out[] = {
[IRIS_FMT_H264] = {
.pixfmt = V4L2_PIX_FMT_H264,
.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
@ -82,12 +82,35 @@ static const struct iris_fmt iris_vdec_formats[] = {
},
};
static const struct iris_fmt iris_vdec_formats_cap[] = {
[IRIS_FMT_NV12] = {
.pixfmt = V4L2_PIX_FMT_NV12,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
},
[IRIS_FMT_QC08C] = {
.pixfmt = V4L2_PIX_FMT_QC08C,
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
},
};
static const struct iris_fmt *
find_format(struct iris_inst *inst, u32 pixfmt, u32 type)
{
unsigned int size = ARRAY_SIZE(iris_vdec_formats);
const struct iris_fmt *fmt = iris_vdec_formats;
const struct iris_fmt *fmt = NULL;
unsigned int size = 0;
unsigned int i;
switch (type) {
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
fmt = iris_vdec_formats_out;
size = ARRAY_SIZE(iris_vdec_formats_out);
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
fmt = iris_vdec_formats_cap;
size = ARRAY_SIZE(iris_vdec_formats_cap);
break;
default:
return NULL;
}
for (i = 0; i < size; i++) {
if (fmt[i].pixfmt == pixfmt)
@ -103,8 +126,21 @@ find_format(struct iris_inst *inst, u32 pixfmt, u32 type)
static const struct iris_fmt *
find_format_by_index(struct iris_inst *inst, u32 index, u32 type)
{
const struct iris_fmt *fmt = iris_vdec_formats;
unsigned int size = ARRAY_SIZE(iris_vdec_formats);
const struct iris_fmt *fmt = NULL;
unsigned int size = 0;
switch (type) {
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
fmt = iris_vdec_formats_out;
size = ARRAY_SIZE(iris_vdec_formats_out);
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
fmt = iris_vdec_formats_cap;
size = ARRAY_SIZE(iris_vdec_formats_cap);
break;
default:
return NULL;
}
if (index >= size || fmt[index].type != type)
return NULL;
@ -126,9 +162,10 @@ int iris_vdec_enum_fmt(struct iris_inst *inst, struct v4l2_fmtdesc *f)
f->flags = V4L2_FMT_FLAG_COMPRESSED | V4L2_FMT_FLAG_DYN_RESOLUTION;
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
if (f->index)
fmt = find_format_by_index(inst, f->index, f->type);
if (!fmt)
return -EINVAL;
f->pixelformat = V4L2_PIX_FMT_NV12;
f->pixelformat = fmt->pixfmt;
break;
default:
return -EINVAL;
@ -157,7 +194,7 @@ int iris_vdec_try_fmt(struct iris_inst *inst, struct v4l2_format *f)
}
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
if (f->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12) {
if (!fmt) {
f_inst = inst->fmt_dst;
f->fmt.pix_mp.pixelformat = f_inst->fmt.pix_mp.pixelformat;
f->fmt.pix_mp.width = f_inst->fmt.pix_mp.width;
@ -236,10 +273,11 @@ int iris_vdec_s_fmt(struct iris_inst *inst, struct v4l2_format *f)
inst->crop.height = f->fmt.pix_mp.height;
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
if (!(find_format(inst, f->fmt.pix_mp.pixelformat, f->type)))
return -EINVAL;
fmt = inst->fmt_dst;
fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
if (fmt->fmt.pix_mp.pixelformat != V4L2_PIX_FMT_NV12)
return -EINVAL;
fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat;
fmt->fmt.pix_mp.width = ALIGN(f->fmt.pix_mp.width, 128);
fmt->fmt.pix_mp.height = ALIGN(f->fmt.pix_mp.height, 32);
@ -266,7 +304,8 @@ int iris_vdec_validate_format(struct iris_inst *inst, u32 pixelformat)
{
const struct iris_fmt *fmt = NULL;
if (pixelformat != V4L2_PIX_FMT_NV12) {
fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
if (!fmt) {
fmt = find_format(inst, pixelformat, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
if (!fmt)
return -EINVAL;