Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c2a0e32
FROMLIST: media: iris: Fix buffer count reporting in internal buffer …
Jul 4, 2025
f20241b
FROMLIST: media: iris: Report unreleased PERSIST buffers on session c…
Jul 4, 2025
04e934d
FROMLIST: media: iris: Fix memory leak by freeing untracked persist b…
Jul 4, 2025
9e91225
FROMLIST: media: iris: Fix buffer timestamp handling
Jul 4, 2025
66e18bc
FROMLIST: media: iris: Fix port streaming handling
Jul 4, 2025
e85e1ad
FROMLIST: media: iris: Allow substate transition to load resources du…
Jul 4, 2025
85b36da
FROMLIST: media: iris: Always destroy internal buffers on firmware re…
Jul 4, 2025
269d2a8
FROMLIST: media: iris: Update vbuf flags before v4l2_m2m_buf_done
Jul 4, 2025
809c3e3
FROMLIST: media: iris: Allow stop on firmware only if start was issued.
Jul 4, 2025
1c6720f
FROMLIST: media: iris: Send dummy buffer address for all codecs durin…
Jul 4, 2025
649f7f8
FROMLIST: media: iris: Fix missing LAST flag handling during drain
Jul 4, 2025
fa11b05
FROMLIST: media: iris: Add support for video encoder device
Jul 4, 2025
c03d481
FROMLIST: media: iris: Initialize and deinitialize encoder instance s…
Jul 4, 2025
07eb86d
FROMLIST: media: iris: Add support for ENUM_FMT, S/G/TRY_FMT encoder
Jul 4, 2025
e6eb612
FROMLIST: media: iris: Add support for ENUM_FRAMESIZES/FRAMEINTERVALS…
Jul 4, 2025
12b666e
FROMLIST: media: iris: Add support for VIDIOC_QUERYCAP for encoder vi…
Jul 4, 2025
c9657b8
FROMLIST: media: iris: Add encoder support for V4L2 event subscription
Jul 4, 2025
9e43d42
FROMLIST: media: iris: Add support for G/S_SELECTION for encoder vide…
Jul 4, 2025
5c35c94
FROMLIST: media: iris: Add support for G/S_PARM for encoder video device
Jul 4, 2025
6f7e9e4
FROMLIST: media: iris: Add platform-specific capabilities for encoder…
Jul 4, 2025
26f32fc
FROMLIST: media: iris: Add V4L2 streaming support for encoder video d…
Jul 4, 2025
e32b86b
FROMLIST: media: iris: Set platform capabilities to firmware for enco…
Jul 4, 2025
0dda4c0
FROMLIST: media: iris: Allocate and queue internal buffers for encode…
Jul 4, 2025
cef00f3
FROMLIST: media: iris: Add support for buffer management ioctls for e…
Jul 4, 2025
4449558
FROMLIST: media: iris: Add support for drain sequence in encoder vide…
Jul 4, 2025
7000de9
FROMLIST: dt-bindings: media: qcom,sm8550-iris: Add X1E80100 compatible
stephan-gh Jul 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ properties:
- items:
- enum:
- qcom,sa8775p-iris
- qcom,x1e80100-iris
- const: qcom,sm8550-iris
- enum:
- qcom,qcs8300-iris
Expand Down
5 changes: 3 additions & 2 deletions drivers/media/platform/qcom/iris/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
qcom-iris-objs += \
iris_buffer.o \
qcom-iris-objs += iris_buffer.o \
iris_common.o \
iris_core.o \
iris_ctrls.o \
iris_firmware.o \
Expand All @@ -19,6 +19,7 @@ qcom-iris-objs += \
iris_vidc.o \
iris_vb2.o \
iris_vdec.o \
iris_venc.o \
iris_vpu2.o \
iris_vpu3x.o \
iris_vpu_buffer.o \
Expand Down
226 changes: 180 additions & 46 deletions drivers/media/platform/qcom/iris/iris_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,12 @@
static u32 iris_yuv_buffer_size_nv12(struct iris_inst *inst)
{
u32 y_plane, uv_plane, y_stride, uv_stride, y_scanlines, uv_scanlines;
struct v4l2_format *f = inst->fmt_dst;
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, Y_STRIDE_ALIGN);
uv_stride = ALIGN(f->fmt.pix_mp.width, UV_STRIDE_ALIGN);
Expand Down Expand Up @@ -194,7 +199,7 @@ 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);
}

static u32 iris_bitstream_buffer_size(struct iris_inst *inst)
static u32 iris_dec_bitstream_buffer_size(struct iris_inst *inst)
{
struct platform_inst_caps *caps = inst->core->iris_platform_data->inst_caps;
u32 base_res_mbs = NUM_MBS_4K;
Expand All @@ -219,18 +224,58 @@ static u32 iris_bitstream_buffer_size(struct iris_inst *inst)
return ALIGN(frame_size, PIXELS_4K);
}

static u32 iris_enc_bitstream_buffer_size(struct iris_inst *inst)
{
u32 aligned_width, aligned_height, bitstream_size, yuv_size;
int bitrate_mode, frame_rc;
struct v4l2_format *f;

f = inst->fmt_dst;

bitrate_mode = inst->fw_caps[BITRATE_MODE].value;
frame_rc = inst->fw_caps[FRAME_RC_ENABLE].value;

aligned_width = ALIGN(f->fmt.pix_mp.width, 32);
aligned_height = ALIGN(f->fmt.pix_mp.height, 32);
bitstream_size = aligned_width * aligned_height * 3;
yuv_size = (aligned_width * aligned_height * 3) >> 1;
if (aligned_width * aligned_height > (4096 * 2176))
/* bitstream_size = 0.25 * yuv_size; */
bitstream_size = (bitstream_size >> 3);
else if (aligned_width * aligned_height > (1280 * 720))
/* bitstream_size = 0.5 * yuv_size; */
bitstream_size = (bitstream_size >> 2);

if ((!frame_rc || bitrate_mode == V4L2_MPEG_VIDEO_BITRATE_MODE_CQ) &&
bitstream_size < yuv_size)
bitstream_size = (bitstream_size << 1);

return ALIGN(bitstream_size, 4096);
}

int iris_get_buffer_size(struct iris_inst *inst,
enum iris_buffer_type buffer_type)
{
switch (buffer_type) {
case BUF_INPUT:
return iris_bitstream_buffer_size(inst);
case BUF_OUTPUT:
return iris_yuv_buffer_size_nv12(inst);
case BUF_DPB:
return iris_yuv_buffer_size_qc08c(inst);
default:
return 0;
if (inst->domain == DECODER) {
switch (buffer_type) {
case BUF_INPUT:
return iris_dec_bitstream_buffer_size(inst);
case BUF_OUTPUT:
return iris_yuv_buffer_size_nv12(inst);
case BUF_DPB:
return iris_yuv_buffer_size_qc08c(inst);
default:
return 0;
}
} else {
switch (buffer_type) {
case BUF_INPUT:
return iris_yuv_buffer_size_nv12(inst);
case BUF_OUTPUT:
return iris_enc_bitstream_buffer_size(inst);
default:
return 0;
}
}
}

Expand All @@ -249,16 +294,30 @@ void iris_get_internal_buffers(struct iris_inst *inst, u32 plane)
const u32 *internal_buf_type;
u32 internal_buffer_count, i;

if (V4L2_TYPE_IS_OUTPUT(plane)) {
internal_buf_type = platform_data->dec_ip_int_buf_tbl;
internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size;
for (i = 0; i < internal_buffer_count; i++)
iris_fill_internal_buf_info(inst, internal_buf_type[i]);
if (inst->domain == DECODER) {
if (V4L2_TYPE_IS_OUTPUT(plane)) {
internal_buf_type = platform_data->dec_ip_int_buf_tbl;
internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size;
for (i = 0; i < internal_buffer_count; i++)
iris_fill_internal_buf_info(inst, internal_buf_type[i]);
} else {
internal_buf_type = platform_data->dec_op_int_buf_tbl;
internal_buffer_count = platform_data->dec_op_int_buf_tbl_size;
for (i = 0; i < internal_buffer_count; i++)
iris_fill_internal_buf_info(inst, internal_buf_type[i]);
}
} else {
internal_buf_type = platform_data->dec_op_int_buf_tbl;
internal_buffer_count = platform_data->dec_op_int_buf_tbl_size;
for (i = 0; i < internal_buffer_count; i++)
iris_fill_internal_buf_info(inst, internal_buf_type[i]);
if (V4L2_TYPE_IS_OUTPUT(plane)) {
internal_buf_type = platform_data->enc_ip_int_buf_tbl;
internal_buffer_count = platform_data->enc_ip_int_buf_tbl_size;
for (i = 0; i < internal_buffer_count; i++)
iris_fill_internal_buf_info(inst, internal_buf_type[i]);
} else {
internal_buf_type = platform_data->enc_op_int_buf_tbl;
internal_buffer_count = platform_data->enc_op_int_buf_tbl_size;
for (i = 0; i < internal_buffer_count; i++)
iris_fill_internal_buf_info(inst, internal_buf_type[i]);
}
}
}

Expand Down Expand Up @@ -299,12 +358,22 @@ int iris_create_internal_buffers(struct iris_inst *inst, u32 plane)
const u32 *internal_buf_type;
int ret;

if (V4L2_TYPE_IS_OUTPUT(plane)) {
internal_buf_type = platform_data->dec_ip_int_buf_tbl;
internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size;
if (inst->domain == DECODER) {
if (V4L2_TYPE_IS_OUTPUT(plane)) {
internal_buf_type = platform_data->dec_ip_int_buf_tbl;
internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size;
} else {
internal_buf_type = platform_data->dec_op_int_buf_tbl;
internal_buffer_count = platform_data->dec_op_int_buf_tbl_size;
}
} else {
internal_buf_type = platform_data->dec_op_int_buf_tbl;
internal_buffer_count = platform_data->dec_op_int_buf_tbl_size;
if (V4L2_TYPE_IS_OUTPUT(plane)) {
internal_buf_type = platform_data->enc_ip_int_buf_tbl;
internal_buffer_count = platform_data->enc_ip_int_buf_tbl_size;
} else {
internal_buf_type = platform_data->enc_op_int_buf_tbl;
internal_buffer_count = platform_data->enc_op_int_buf_tbl_size;
}
}

for (i = 0; i < internal_buffer_count; i++) {
Expand Down Expand Up @@ -334,6 +403,29 @@ int iris_queue_buffer(struct iris_inst *inst, struct iris_buffer *buf)
return 0;
}

int iris_queue_internal_deferred_buffers(struct iris_inst *inst, enum iris_buffer_type buffer_type)
{
struct iris_buffer *buffer, *next;
struct iris_buffers *buffers;
int ret = 0;

buffers = &inst->buffers[buffer_type];
list_for_each_entry_safe(buffer, next, &buffers->list, list) {
if (buffer->attr & BUF_ATTR_PENDING_RELEASE)
continue;
if (buffer->attr & BUF_ATTR_QUEUED)
continue;

if (buffer->attr & BUF_ATTR_DEFERRED) {
ret = iris_queue_buffer(inst, buffer);
if (ret)
return ret;
}
}

return ret;
}

int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane)
{
const struct iris_platform_data *platform_data = inst->core->iris_platform_data;
Expand All @@ -343,12 +435,22 @@ int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane)
u32 internal_buffer_count, i;
int ret;

if (V4L2_TYPE_IS_OUTPUT(plane)) {
internal_buf_type = platform_data->dec_ip_int_buf_tbl;
internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size;
if (inst->domain == DECODER) {
if (V4L2_TYPE_IS_OUTPUT(plane)) {
internal_buf_type = platform_data->dec_ip_int_buf_tbl;
internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size;
} else {
internal_buf_type = platform_data->dec_op_int_buf_tbl;
internal_buffer_count = platform_data->dec_op_int_buf_tbl_size;
}
} else {
internal_buf_type = platform_data->dec_op_int_buf_tbl;
internal_buffer_count = platform_data->dec_op_int_buf_tbl_size;
if (V4L2_TYPE_IS_OUTPUT(plane)) {
internal_buf_type = platform_data->enc_ip_int_buf_tbl;
internal_buffer_count = platform_data->enc_ip_int_buf_tbl_size;
} else {
internal_buf_type = platform_data->enc_op_int_buf_tbl;
internal_buffer_count = platform_data->enc_op_int_buf_tbl_size;
}
}

for (i = 0; i < internal_buffer_count; i++) {
Expand All @@ -358,6 +460,10 @@ int iris_queue_internal_buffers(struct iris_inst *inst, u32 plane)
continue;
if (buffer->attr & BUF_ATTR_QUEUED)
continue;
if (buffer->type == BUF_DPB && inst->state != IRIS_INST_STREAMING) {
buffer->attr |= BUF_ATTR_DEFERRED;
continue;
}
ret = iris_queue_buffer(inst, buffer);
if (ret)
return ret;
Expand Down Expand Up @@ -388,12 +494,22 @@ static int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane, bool
u32 i, len;
int ret;

if (V4L2_TYPE_IS_OUTPUT(plane)) {
internal_buf_type = platform_data->dec_ip_int_buf_tbl;
len = platform_data->dec_ip_int_buf_tbl_size;
if (inst->domain == DECODER) {
if (V4L2_TYPE_IS_OUTPUT(plane)) {
internal_buf_type = platform_data->dec_ip_int_buf_tbl;
len = platform_data->dec_ip_int_buf_tbl_size;
} else {
internal_buf_type = platform_data->dec_op_int_buf_tbl;
len = platform_data->dec_op_int_buf_tbl_size;
}
} else {
internal_buf_type = platform_data->dec_op_int_buf_tbl;
len = platform_data->dec_op_int_buf_tbl_size;
if (V4L2_TYPE_IS_OUTPUT(plane)) {
internal_buf_type = platform_data->enc_ip_int_buf_tbl;
len = platform_data->enc_ip_int_buf_tbl_size;
} else {
internal_buf_type = platform_data->enc_op_int_buf_tbl;
len = platform_data->enc_op_int_buf_tbl_size;
}
}

for (i = 0; i < len; i++) {
Expand All @@ -413,6 +529,19 @@ static int iris_destroy_internal_buffers(struct iris_inst *inst, u32 plane, bool
}
}

if (force) {
if (inst->domain == DECODER)
buffers = &inst->buffers[BUF_PERSIST];
else
buffers = &inst->buffers[BUF_ARP];

list_for_each_entry_safe(buf, next, &buffers->list, list) {
ret = iris_destroy_internal_buffer(inst, buf);
if (ret)
return ret;
}
}

return 0;
}

Expand Down Expand Up @@ -455,8 +584,13 @@ static int iris_release_input_internal_buffers(struct iris_inst *inst)
u32 internal_buffer_count, i;
int ret;

internal_buf_type = platform_data->dec_ip_int_buf_tbl;
internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size;
if (inst->domain == DECODER) {
internal_buf_type = platform_data->dec_ip_int_buf_tbl;
internal_buffer_count = platform_data->dec_ip_int_buf_tbl_size;
} else {
internal_buf_type = platform_data->enc_ip_int_buf_tbl;
internal_buffer_count = platform_data->enc_ip_int_buf_tbl_size;
}

for (i = 0; i < internal_buffer_count; i++) {
ret = iris_release_internal_buffers(inst, internal_buf_type[i]);
Expand All @@ -467,20 +601,20 @@ static int iris_release_input_internal_buffers(struct iris_inst *inst)
return 0;
}

int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst)
int iris_alloc_and_queue_persist_bufs(struct iris_inst *inst, enum iris_buffer_type buffer_type)
{
struct iris_buffers *buffers = &inst->buffers[BUF_PERSIST];
struct iris_buffers *buffers = &inst->buffers[buffer_type];
struct iris_buffer *buffer, *next;
int ret;
u32 i;

if (!list_empty(&buffers->list))
return 0;

iris_fill_internal_buf_info(inst, BUF_PERSIST);
iris_fill_internal_buf_info(inst, buffer_type);

for (i = 0; i < buffers->min_count; i++) {
ret = iris_create_internal_buffer(inst, BUF_PERSIST, i);
ret = iris_create_internal_buffer(inst, buffer_type, i);
if (ret)
return ret;
}
Expand Down Expand Up @@ -569,14 +703,14 @@ iris_helper_find_buf(struct iris_inst *inst, u32 type, u32 idx)
return v4l2_m2m_dst_buf_remove_by_idx(m2m_ctx, idx);
}

static void iris_get_ts_metadata(struct iris_inst *inst, u64 timestamp_ns,
static void iris_get_ts_metadata(struct iris_inst *inst, u64 timestamp_us,
struct vb2_v4l2_buffer *vbuf)
{
u32 mask = V4L2_BUF_FLAG_TIMECODE | V4L2_BUF_FLAG_TSTAMP_SRC_MASK;
u32 i;

for (i = 0; i < ARRAY_SIZE(inst->tss); ++i) {
if (inst->tss[i].ts_ns != timestamp_ns)
if (inst->tss[i].ts_us != timestamp_us)
continue;

vbuf->flags &= ~mask;
Expand Down Expand Up @@ -614,6 +748,8 @@ int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf)

vb2 = &vbuf->vb2_buf;

vbuf->flags |= buf->flags;

if (buf->flags & V4L2_BUF_FLAG_ERROR) {
state = VB2_BUF_STATE_ERROR;
vb2_set_plane_payload(vb2, 0, 0);
Expand All @@ -622,8 +758,6 @@ int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf)
return 0;
}

vbuf->flags |= buf->flags;

if (V4L2_TYPE_IS_CAPTURE(type)) {
vb2_set_plane_payload(vb2, 0, buf->data_size);
vbuf->sequence = inst->sequence_cap++;
Expand All @@ -643,7 +777,7 @@ int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer *buf)
}

state = VB2_BUF_STATE_DONE;
vb2->timestamp = buf->timestamp;
vb2->timestamp = buf->timestamp * NSEC_PER_USEC;
v4l2_m2m_buf_done(vbuf, state);

return 0;
Expand Down
Loading