Re: [PATCH RFC 1/7] media: qcom: iris: add QC10C & P010 buffer size calculations

From: Neil Armstrong

Date: Fri Apr 17 2026 - 04:05:22 EST


On 4/17/26 08:47, Dikshita Agarwal wrote:


On 4/8/2026 10:13 PM, Neil Armstrong wrote:
The P010 (YUV format with 16-bits per pixel with interleaved UV)
and QC10C (P010 compressed mode similar to QC08C) requires specific
buffer calculations to allocate the right buffer size for DPB frames
and frames consumed by userspace.

Similar to 8bit, the 10bit DPB frames uses QC10C format.

Signed-off-by: Neil Armstrong <neil.armstrong@xxxxxxxxxx>
---
drivers/media/platform/qcom/iris/iris_buffer.c | 81 +++++++++++++++++++++++++-
1 file changed, 80 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c
index 9151f43bc6b9..a0e31bff8f26 100644
--- a/drivers/media/platform/qcom/iris/iris_buffer.c
+++ b/drivers/media/platform/qcom/iris/iris_buffer.c
@@ -15,7 +15,9 @@
#define MAX_WIDTH 4096
#define MAX_HEIGHT 2304
#define Y_STRIDE_ALIGN 128
+#define Y_STRIDE_ALIGN_P010 256
#define UV_STRIDE_ALIGN 128
+#define UV_STRIDE_ALIGN_P010 256
#define Y_SCANLINE_ALIGN 32
#define UV_SCANLINE_ALIGN 16
#define UV_SCANLINE_ALIGN_QC08C 32
@@ -80,6 +82,26 @@ static u32 iris_yuv_buffer_size_nv12(struct iris_inst *inst)
return ALIGN(y_plane + uv_plane, PIXELS_4K);
}
+static u32 iris_yuv_buffer_size_p010(struct iris_inst *inst)
+{
+ u32 y_plane, uv_plane, y_stride, uv_stride, y_scanlines, uv_scanlines;
+ struct v4l2_format *f;
+
+ if (inst->domain == DECODER)
+ f = inst->fmt_dst;
+ else
+ f = inst->fmt_src;
+
+ y_stride = ALIGN(f->fmt.pix_mp.width * 2, Y_STRIDE_ALIGN_P010);
+ uv_stride = ALIGN(f->fmt.pix_mp.width * 2, UV_STRIDE_ALIGN_P010);
+ y_scanlines = ALIGN(f->fmt.pix_mp.height, Y_SCANLINE_ALIGN);
+ uv_scanlines = ALIGN((f->fmt.pix_mp.height + 1) >> 1, UV_SCANLINE_ALIGN);
+ y_plane = y_stride * y_scanlines;
+ uv_plane = uv_stride * uv_scanlines;
+
+ return ALIGN(y_plane + uv_plane, PIXELS_4K);
+}
+
/*
* QC08C:
* Compressed Macro-tile format for NV12.
@@ -204,6 +226,55 @@ static u32 iris_yuv_buffer_size_qc08c(struct iris_inst *inst)
return ALIGN(y_meta_plane + y_plane + uv_meta_plane + uv_plane, PIXELS_4K);
}
+/*
+ * QC10C:
+ * Compressed Macro-tile format for TP10.
+ */
+static u32 iris_yuv_buffer_size_qc10c(struct iris_inst *inst)
+{
+ u32 y_stride, y_buf_height;
+ u32 uv_stride, uv_buf_height;
+ u32 y_md_stride, y_md_height;
+ u32 uv_md_stride, uv_md_height;
+ u32 y_data_size, uv_data_size;
+ u32 y_md_size, uv_md_size;
+ struct v4l2_format *f = NULL;
+
+ if (inst->domain == DECODER)
+ f = inst->fmt_dst;
+ else
+ f = inst->fmt_src;
+
+ y_stride = ALIGN(ALIGN(f->fmt.pix_mp.width, 192) * 4 / 3,
+ Y_STRIDE_ALIGN_P010);

Y_STRIDE_ALIGN_P010 is being used for both P010 and QC10C, lets keep it
Y_STRIDE_ALIGN_10_BIT ? or something similar ?

+ y_buf_height = ALIGN(f->fmt.pix_mp.height, UV_SCANLINE_ALIGN);

why not call it y_scanlines only?

+
+ y_data_size = ALIGN(y_stride * y_buf_height, PIXELS_4K);

s/y_data_size/y_plane ?

+
+ uv_stride = ALIGN(ALIGN(f->fmt.pix_mp.width, 192) * 4 / 3,
+ UV_STRIDE_ALIGN_P010);
+ uv_buf_height = ALIGN((f->fmt.pix_mp.height + 1) / 2,
+ UV_SCANLINE_ALIGN);

s/uv_buf_height/uv_scanline?

+
+ uv_data_size = ALIGN(uv_stride * uv_buf_height, PIXELS_4K);

s/uv_data_size/uv_plane?

Pls keep all these names consistent with other functions, applies to below
variables as well.


Thanks,
Dikshita

+
+ y_md_stride = ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.width, 48),
+ META_STRIDE_ALIGNED);
+ y_md_height = ALIGN(DIV_ROUND_UP(f->fmt.pix_mp.height, 4),
+ META_SCANLINE_ALIGNED);
+
+ y_md_size = ALIGN(y_md_stride * y_md_height, PIXELS_4K);
+
+ uv_md_stride = ALIGN(DIV_ROUND_UP((f->fmt.pix_mp.width + 1) / 2, 24),
+ META_STRIDE_ALIGNED);
+ uv_md_height = ALIGN(DIV_ROUND_UP((f->fmt.pix_mp.height + 1) / 2, 4),
+ META_SCANLINE_ALIGNED);
+
+ uv_md_size = ALIGN(uv_md_stride * uv_md_height, PIXELS_4K);
+
+ return y_data_size + uv_data_size + y_md_size + uv_md_size;
+}
+
static u32 iris_dec_bitstream_buffer_size(struct iris_inst *inst)
{
struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
@@ -268,10 +339,18 @@ int iris_get_buffer_size(struct iris_inst *inst,
case BUF_OUTPUT:
if (inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_QC08C)
return iris_yuv_buffer_size_qc08c(inst);
+ else if (inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_QC10C)
+ return iris_yuv_buffer_size_qc10c(inst);
+ else if (inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_P010)
+ return iris_yuv_buffer_size_p010(inst);
else
return iris_yuv_buffer_size_nv12(inst);
case BUF_DPB:
- return iris_yuv_buffer_size_qc08c(inst);
+ if (inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_QC10C ||
+ inst->fmt_dst->fmt.pix_mp.pixelformat == V4L2_PIX_FMT_P010)

Please introduce one API, is_10bit_format and use that here instead.

Ack


Thanks,
Dikshita
+ return iris_yuv_buffer_size_qc10c(inst);
+ else
+ return iris_yuv_buffer_size_qc08c(inst);
default:
return 0;
}