Re: [PATCH v3 3/3] media: iris: Add ROI support framework for iris video encoder
Deepa Guthyappa Madivalara <[email protected]> Thu, 6 Aug 2026 11:36:43 -0700
| Newsgroups | org.kernel.vger.linux-media,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
On 8/4/2026 9:06 PM, Bryan O'Donoghue wrote: > On 04/08/2026 21:05, Deepa Guthyappa Madivalara wrote: >> Add ROI support in the iris driver, including control structures >> and default parameters. Extend support to set ROI parameters >> using custom control V4L2_CID_MPEG_VIDEO_ROI_MB_DELTA_QP. >> Implement internal buffer list support for BUF_ROIMB_DELTAQP that holds >> ROI MB based delta_qp as expected by the firmware. When an input >> arrives queue the corresponding ROI MB delta_qp buffer to firmware. >> >> Signed-off-by: Deepa Guthyappa Madivalara >> <[email protected]> >> --- >> drivers/media/platform/qcom/iris/iris_buffer.c | 101 >> ++++++++++++++++++++ >> drivers/media/platform/qcom/iris/iris_buffer.h | 22 +++++ >> drivers/media/platform/qcom/iris/iris_ctrls.c | 104 >> ++++++++++++++++++++- >> drivers/media/platform/qcom/iris/iris_ctrls.h | 3 + >> drivers/media/platform/qcom/iris/iris_hfi_common.h | 1 + >> drivers/media/platform/qcom/iris/iris_hfi_gen2.c | 14 +++ >> .../platform/qcom/iris/iris_hfi_gen2_command.c | 62 ++++++++++++ >> .../platform/qcom/iris/iris_hfi_gen2_defines.h | 3 + >> .../platform/qcom/iris/iris_hfi_gen2_packet.c | 6 +- >> .../platform/qcom/iris/iris_hfi_gen2_packet.h | 3 + >> .../platform/qcom/iris/iris_hfi_gen2_response.c | 29 ++++++ >> .../platform/qcom/iris/iris_platform_common.h | 5 + >> drivers/media/platform/qcom/iris/iris_venc.c | 4 + >> drivers/media/platform/qcom/iris/iris_venc.h | 2 + >> drivers/media/platform/qcom/iris/iris_vidc.c | 2 + >> 15 files changed, 357 insertions(+), 4 deletions(-) >> >> diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c >> b/drivers/media/platform/qcom/iris/iris_buffer.c >> index >> eb8de60c1177f5e1ab83b90a3c8c80e0b4d1f02e..8186a7d011460af4dfcab0f204da08e19b027b33 >> 100644 >> --- a/drivers/media/platform/qcom/iris/iris_buffer.c >> +++ b/drivers/media/platform/qcom/iris/iris_buffer.c >> @@ -5,11 +5,13 @@ >> >> #include <media/v4l2-event.h> >> #include <media/v4l2-mem2mem.h> >> +#include <linux/slab.h> >> >> #include "iris_buffer.h" >> #include "iris_instance.h" >> #include "iris_power.h" >> #include "iris_vpu_buffer.h" >> +#include "iris_hfi_gen2_defines.h" >> >> #define PIXELS_4K 4096 >> #define MAX_WIDTH 4096 >> @@ -705,6 +707,23 @@ int >> iris_destroy_dequeued_internal_buffers(struct iris_inst *inst, u32 >> plane) >> return iris_destroy_internal_buffers(inst, plane, false); >> } >> >> +int iris_destroy_roi_metadata_buffers(struct iris_inst *inst) >> +{ >> + struct iris_buffer *buf, *next; >> + struct iris_buffers *buffers; >> + int ret = 0; >> + >> + if (inst->domain == ENCODER) { >> + buffers = &inst->buffers[BUF_ROIMB_DELTAQP]; >> + list_for_each_entry_safe(buf, next, &buffers->list, list) { >> + ret = iris_destroy_internal_buffer(inst, buf); >> + if (ret) >> + return ret; >> + } >> + } >> + >> + return ret; >> +} >> static int iris_release_internal_buffers(struct iris_inst *inst, >> enum iris_buffer_type buffer_type) >> { >> @@ -928,3 +947,85 @@ int iris_vb2_buffer_done(struct iris_inst *inst, >> struct iris_buffer *buf) >> >> return 0; >> } >> + >> +static int iris_fill_roi_data(struct iris_inst *inst, struct >> iris_buffer *buffer) >> +{ >> + s8 *p_array = (s8 *)inst->fw_caps[ROI_PARAMS].p_array; >> + u32 array_size = inst->fw_caps[ROI_PARAMS].elems; >> + struct metabuf_header *mbuf_hdr = buffer->kvaddr; >> + struct metapayload_header *mbuf_payload_hdr; >> + s16 *p_16; >> + u32 payload_offset; >> + >> + memset(mbuf_hdr, 0, sizeof(struct metabuf_header)); >> + mbuf_hdr->count = 1; >> + mbuf_hdr->size = sizeof(struct metabuf_header) + >> + sizeof(struct metapayload_header); >> + mbuf_hdr->version = 1 << 16; > > That's a weird way to set a header version number though isn't it. > > Either say mbuf_hdr->version = 0x10000 or just BIT(16) > ok, will update in v4 >> + mbuf_payload_hdr = (struct metapayload_header *)(mbuf_hdr + 1); > mbuf_hdr++; > mbuf_payload_hdr = (struct metapayload_header *)(mbuf_hdr); > > would also work > ok, will update in v4 >> + payload_offset = sizeof(struct metabuf_header) + >> + sizeof(struct metapayload_header); >> + >> + memset(mbuf_payload_hdr, 0, sizeof(struct metapayload_header)); > >> + mbuf_payload_hdr->type = HFI_PROP_ROI_INFO; >> + mbuf_payload_hdr->size = array_size * 2; > > Instead of * 2 it should be * sizeof(datatype); > ok, will update in v4 > BTW the name "metadata" seems strangely generic. > This is the same struct used for different metadata. Keeping it generic to reuse this in future. >> + mbuf_payload_hdr->version = 1 << 16; >> + mbuf_payload_hdr->offset = ALIGN(payload_offset, (u32)256); >> + mbuf_payload_hdr->flags = 0; >> + >> + /* Firmware expects 2bytes of delta_Qp, int16_t */ >> + p_16 = buffer->kvaddr + mbuf_payload_hdr->offset; >> + for (int i = 0; i < array_size; i++) >> + p_16[i] = p_array[i]; >> + >> + return 0; >> +} >> + >> +int iris_hfi_gen2_session_alloc_roi_metadata_buffer(struct iris_inst >> *inst) >> +{ >> + struct iris_buffers *buffers = &inst->buffers[BUF_ROIMB_DELTAQP]; >> + struct iris_core *core = inst->core; >> + struct iris_buffer *buffer, *first_buffer, *next; >> + bool found = false; >> + int ret = 0; >> + >> + if (!buffers->size) >> + return 0; >> + >> + list_for_each_entry_safe(buffer, next, &buffers->list, list) { >> + if (buffer->attr & BUF_ATTR_DEQUEUED) { >> + buffer->attr &= ~BUF_ATTR_DEQUEUED; >> + list_move(&buffer->list, &buffers->list); >> + found = true; >> + break; >> + } >> + } >> + if (!found) { >> + buffer = kzalloc_obj(*buffer); >> + if (!buffer) >> + return -ENOMEM; >> + >> + INIT_LIST_HEAD(&buffer->list); >> + buffer->type = BUF_ROIMB_DELTAQP; >> + buffer->index++; >> + buffer->buffer_size = buffers->size; >> + buffer->dma_attrs = DMA_ATTR_WRITE_COMBINE; >> + >> + buffer->kvaddr = dma_alloc_attrs(core->dev, >> buffer->buffer_size, >> + &buffer->device_addr, GFP_KERNEL, >> + buffer->dma_attrs); >> + >> + if (!buffer->kvaddr) { >> + kfree(buffer); >> + return -ENOMEM; >> + } >> + list_add(&buffer->list, &buffers->list); >> + } >> + >> + first_buffer = list_first_entry(&buffers->list, struct >> iris_buffer, list); >> + ret = iris_fill_roi_data(inst, first_buffer); >> + if (ret) >> + return ret; >> + >> + return ret; >> +} >> diff --git a/drivers/media/platform/qcom/iris/iris_buffer.h >> b/drivers/media/platform/qcom/iris/iris_buffer.h >> index >> ab8e5d953101a786ade20540ee3c3ed226160cbe..df9d018493f3ec37fd5e6b0ba049dba0b5ae76e9 >> 100644 >> --- a/drivers/media/platform/qcom/iris/iris_buffer.h >> +++ b/drivers/media/platform/qcom/iris/iris_buffer.h >> @@ -28,6 +28,7 @@ struct iris_inst; >> * @BUF_SCRATCH_2: buffer to store encoding context data for HW >> * @BUF_VPSS: buffer to store VPSS context data for HW >> * @BUF_PARTIAL: buffer for AV1 IBC data >> + * @BUF_ROIMB_DELTAQP: metadata buffer for ROI MB DeltaQp >> * @BUF_TYPE_MAX: max buffer types >> */ >> enum iris_buffer_type { >> @@ -44,6 +45,7 @@ enum iris_buffer_type { >> BUF_SCRATCH_2, >> BUF_VPSS, >> BUF_PARTIAL, >> + BUF_ROIMB_DELTAQP, >> BUF_TYPE_MAX, >> }; >> >> @@ -107,6 +109,24 @@ struct iris_buffers { >> u32 size; >> }; >> >> +/* Metadata buffer header */ >> +struct metabuf_header { >> + u32 count; >> + u32 size; >> + u32 version; >> + u32 reserved[5]; >> +}; >> + >> +/* Metadata buffer payload header */ >> +struct metapayload_header { >> + u32 type; >> + u32 size; >> + u32 version; >> + u32 offset; >> + u32 flags; >> + u32 reserved[3]; >> +}; > > But these are roi metadata buffers not generic metadata buffers right ? > > So the name should describe what it is an roi_medatadata_thing not a > metadata_thing. > > OTOH if these are meant to be generic metadata buffers then the > addition of these data-structures and the associated logic to support > them should live in their own patch - describing metadata buffers. > they are generic, will split the patch in v4 >> + >> int iris_get_buffer_size(struct iris_inst *inst, enum >> iris_buffer_type buffer_type); >> void iris_get_internal_buffers(struct iris_inst *inst, u32 plane); >> int iris_create_internal_buffers(struct iris_inst *inst, u32 plane); >> @@ -121,5 +141,7 @@ int iris_queue_buffer(struct iris_inst *inst, >> struct iris_buffer *buf); >> int iris_queue_deferred_buffers(struct iris_inst *inst, enum >> iris_buffer_type buf_type); >> int iris_vb2_buffer_done(struct iris_inst *inst, struct iris_buffer >> *buf); >> void iris_vb2_queue_error(struct iris_inst *inst); >> +int iris_hfi_gen2_session_alloc_roi_metadata_buffer(struct iris_inst >> *inst); >> +int iris_destroy_roi_metadata_buffers(struct iris_inst *inst); >> >> #endif >> diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.c >> b/drivers/media/platform/qcom/iris/iris_ctrls.c >> index >> bf17d310eac081ffd3a4ad4842c2255ad798d4d8..4da24a29567f7824f91b4d68a8310b248ab62176 >> 100644 >> --- a/drivers/media/platform/qcom/iris/iris_ctrls.c >> +++ b/drivers/media/platform/qcom/iris/iris_ctrls.c >> @@ -156,6 +156,10 @@ static enum platform_inst_fw_cap_type >> iris_get_cap_id(u32 id) >> return LAYER5_BITRATE_HEVC; >> case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: >> return REQUEST_SYNC_FRAME; >> + case V4L2_CID_MPEG_VIDEO_ROI_MB_DELTA_QP: >> + return ROI_PARAMS; >> + case V4L2_CID_MPEG_VIDEO_ROI_MB_SIZE: >> + return MB_SIZE; >> default: >> return INST_FW_CAP_MAX; >> } >> @@ -301,6 +305,10 @@ static u32 iris_get_v4l2_id(enum >> platform_inst_fw_cap_type cap_id) >> return V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR; >> case REQUEST_SYNC_FRAME: >> return V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME; >> + case ROI_PARAMS: >> + return V4L2_CID_MPEG_VIDEO_ROI_MB_DELTA_QP; >> + case MB_SIZE: >> + return V4L2_CID_MPEG_VIDEO_ROI_MB_SIZE; >> default: >> return 0; >> } >> @@ -327,6 +335,14 @@ static int iris_op_s_ctrl(struct v4l2_ctrl *ctrl) >> >> inst->fw_caps[cap_id].value = ctrl->val; >> >> + if (inst->fw_caps[cap_id].flags & CAP_FLAG_CUSTOM) { >> + if (cap_id == ROI_PARAMS) { >> + inst->fw_caps[cap_id].p_array = >> + (const void *)ctrl->p_new.p; >> + inst->fw_caps[cap_id].elems = ctrl->new_elems; >> + } >> + } >> + >> if (vb2_is_streaming(q)) { >> if (cap[cap_id].set) >> cap[cap_id].set(inst, cap_id); >> @@ -335,8 +351,52 @@ static int iris_op_s_ctrl(struct v4l2_ctrl *ctrl) >> return 0; >> } >> >> +static int iris_get_roi_mb_size(struct iris_inst *inst) >> +{ >> + return inst->codec == V4L2_PIX_FMT_HEVC ? 32 : 16; >> +} >> + >> +static int iris_op_g_ctrl(struct v4l2_ctrl *ctrl) >> +{ >> + struct iris_inst *inst = container_of(ctrl->handler, struct >> iris_inst, ctrl_handler); >> + enum platform_inst_fw_cap_type cap_id; >> + >> + cap_id = iris_get_cap_id(ctrl->id); >> + if (!iris_valid_cap_id(cap_id)) >> + return -EINVAL; >> + >> + if (cap_id == MB_SIZE) >> + ctrl->val = iris_get_roi_mb_size(inst); >> + >> + return 0; >> +} >> + >> static const struct v4l2_ctrl_ops iris_ctrl_ops = { >> .s_ctrl = iris_op_s_ctrl, >> + .g_volatile_ctrl = iris_op_g_ctrl, >> +}; >> + >> +const struct v4l2_ctrl_config roi_mbqp_cfg = { >> + .ops = &iris_ctrl_ops, >> + .id = V4L2_CID_MPEG_VIDEO_ROI_MB_DELTA_QP, >> + .name = "Enc Mb ROI Delta QP", >> + .type = V4L2_CTRL_TYPE_S8, >> + .dims = {139264}, /* Max MBPF = 8192 * 4352 / 256 */ >> + .min = -31, >> + .max = 30, >> + .def = 0, >> + .step = 1, >> +}; >> + >> +static const struct v4l2_ctrl_config roi_mbqp_size = { >> + .ops = &iris_ctrl_ops, >> + .id = V4L2_CID_MPEG_VIDEO_ROI_MB_SIZE, >> + .name = "ROI Mb size", >> + .type = V4L2_CTRL_TYPE_U8, >> + .min = 16, >> + .max = 32, >> + .def = 16, >> + .step = 1, >> }; >> >> int iris_ctrls_init(struct iris_inst *inst) >> @@ -361,7 +421,7 @@ int iris_ctrls_init(struct iris_inst *inst) >> return ret; >> >> for (idx = 1; idx < INST_FW_CAP_MAX; idx++) { >> - struct v4l2_ctrl *ctrl; >> + struct v4l2_ctrl *ctrl = NULL; >> >> v4l2_id = iris_get_v4l2_id(cap[idx].cap_id); >> if (!v4l2_id) >> @@ -379,6 +439,13 @@ int iris_ctrls_init(struct iris_inst *inst) >> cap[idx].max, >> ~(cap[idx].step_or_mask), >> cap[idx].value); >> + } else if (cap[idx].flags & CAP_FLAG_CUSTOM) { >> + if (cap[idx].cap_id == ROI_PARAMS) >> + ctrl = v4l2_ctrl_new_custom(&inst->ctrl_handler, >> + &roi_mbqp_cfg, NULL); >> + if (cap[idx].cap_id == MB_SIZE) >> + ctrl = v4l2_ctrl_new_custom(&inst->ctrl_handler, >> + &roi_mbqp_size, NULL); >> } else { >> ctrl = v4l2_ctrl_new_std(&inst->ctrl_handler, >> &iris_ctrl_ops, >> @@ -1540,3 +1607,38 @@ int iris_set_properties(struct iris_inst >> *inst, u32 plane) >> >> return 0; >> } >> + >> +int iris_set_metadata_delivery(struct iris_inst *inst, u32 plane) >> +{ >> + const struct iris_hfi_session_ops *hfi_ops = inst->hfi_session_ops; >> + int ret = 0; >> + >> + /*subscribe to metadata delivery only if ROI is enabled */ >> + if (!inst->fw_caps[ROI_PARAMS].p_array) >> + return ret; >> + >> + ret = hfi_ops->session_subscribe_metadata_delivery(inst, plane); >> + if (ret) >> + return ret; >> + >> + return ret; >> +} >> + >> +int iris_set_roi_params(struct iris_inst *inst, u32 plane) >> +{ >> + struct iris_buffers *buffers = &inst->buffers[BUF_ROIMB_DELTAQP]; >> + u32 metadata_header_bytes = 256; >> + u32 size = 0; >> + int ret = 0; >> + >> + if (!inst->fw_caps[ROI_PARAMS].p_array) >> + return -EINVAL; >> + >> + size = inst->fw_caps[ROI_PARAMS].elems * 2 + metadata_header_bytes; >> + buffers->size = ALIGN(size, 4096); >> + iris_hfi_gen2_session_alloc_roi_metadata_buffer(inst); >> + if (ret) >> + return ret; >> + >> + return 0; >> +} >> diff --git a/drivers/media/platform/qcom/iris/iris_ctrls.h >> b/drivers/media/platform/qcom/iris/iris_ctrls.h >> index >> 5180d53d3c904cad460b2760913b475d0ff1bb55..df8fa957a6127338ae63bdd44871e363deeb48fc >> 100644 >> --- a/drivers/media/platform/qcom/iris/iris_ctrls.h >> +++ b/drivers/media/platform/qcom/iris/iris_ctrls.h >> @@ -50,5 +50,8 @@ int iris_set_layer_bitrate(struct iris_inst *inst, >> enum platform_inst_fw_cap_typ >> int iris_set_req_sync_frame(struct iris_inst *inst, enum >> platform_inst_fw_cap_type cap_id); >> int iris_set_time_delta_based_rc(struct iris_inst *inst, enum >> platform_inst_fw_cap_type cap_id); >> int iris_set_properties(struct iris_inst *inst, u32 plane); >> +int iris_set_roi_params(struct iris_inst *inst, u32 plane); >> +int iris_set_metadata_delivery(struct iris_inst *inst, u32 plane); >> +int iris_set_roi_mb_size(struct iris_inst *inst); >> >> #endif >> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_common.h >> b/drivers/media/platform/qcom/iris/iris_hfi_common.h >> index >> a27447eb2519962cb958b0e330a6d018310c3450..5692375cdd357f9b00760053ffff5af4bd9cce9c >> 100644 >> --- a/drivers/media/platform/qcom/iris/iris_hfi_common.h >> +++ b/drivers/media/platform/qcom/iris/iris_hfi_common.h >> @@ -131,6 +131,7 @@ struct iris_hfi_session_ops { >> int (*session_drain)(struct iris_inst *inst, u32 plane); >> int (*session_resume_drain)(struct iris_inst *inst, u32 plane); >> int (*session_close)(struct iris_inst *inst); >> + int (*session_subscribe_metadata_delivery)(struct iris_inst >> *inst, u32 plane); >> }; >> >> struct hfi_subscription_params { >> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2.c >> b/drivers/media/platform/qcom/iris/iris_hfi_gen2.c >> index >> 3b8fbefb8b93576962abd3850215f7b7fb364930..4d40d6733e5877a302ce63fb0b4a61b8f284e6dc >> 100644 >> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2.c >> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2.c >> @@ -1782,6 +1782,20 @@ static const struct platform_inst_fw_cap >> inst_fw_cap_sm8550_enc[] = { >> .flags = CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED, >> .set = iris_set_req_sync_frame, >> }, >> + { >> + .cap_id = ROI_PARAMS, >> + .step_or_mask = 1, >> + .p_array = NULL, >> + .hfi_id = HFI_PROP_ROI_INFO, >> + .flags = CAP_FLAG_INPUT_PORT | CAP_FLAG_CUSTOM | >> + CAP_FLAG_DYNAMIC_ALLOWED, >> + .set = iris_set_roi_params, >> + }, >> + { >> + .cap_id = MB_SIZE, >> + .step_or_mask = 1, >> + .flags = CAP_FLAG_OUTPUT_PORT | CAP_FLAG_CUSTOM, >> + }, > > The enumeration of the platform and the implementation of the logic > should be separated into different patches. > ok, will update in v4 >> }; >> >> static const u32 sm8550_vdec_input_config_params_default[] = { >> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c >> b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c >> index >> 388a36ff2b07b7bcd8db21d4345bc900356b4ec3..4581a6ea74a708b0d493bc71d2d1822eda078860 >> 100644 >> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c >> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_command.c >> @@ -134,6 +134,7 @@ static u32 >> iris_hfi_gen2_get_port_from_buf_type(struct iris_inst *inst, >> switch (buffer_type) { >> case BUF_INPUT: >> case BUF_VPSS: >> + case BUF_ROIMB_DELTAQP: >> return HFI_PORT_RAW; >> case BUF_OUTPUT: >> case BUF_BIN: >> @@ -1267,6 +1268,8 @@ static u32 >> iris_hfi_gen2_buf_type_from_driver(u32 domain, enum iris_buffer_type >> return HFI_BUFFER_VPSS; >> case BUF_PARTIAL: >> return HFI_BUFFER_PARTIAL_DATA; >> + case BUF_ROIMB_DELTAQP: >> + return HFI_BUFFER_METADATA; >> default: >> return 0; >> } >> @@ -1307,10 +1310,29 @@ static void iris_hfi_gen2_get_buffer(u32 >> domain, struct iris_buffer *buffer, >> buf->timestamp = buffer->timestamp; >> } >> >> +static struct iris_buffer *iris_queue_metadata_buffers(struct >> iris_inst *inst, >> + enum iris_buffer_type buffer_type, >> u32 index) >> +{ >> + struct iris_buffers *buffers = &inst->buffers[buffer_type]; >> + struct iris_buffer *buffer = NULL; >> + >> + if (list_empty(&buffers->list)) >> + return NULL; >> + >> + buffer = list_first_entry(&buffers->list, typeof(*buffer), list); >> + if ((buffer->attr & BUF_ATTR_QUEUED) || (buffer->attr & >> BUF_ATTR_DEQUEUED)) >> + return NULL; >> + >> + buffer->index = index; >> + >> + return buffer; >> +} >> + >> static int iris_hfi_gen2_session_queue_buffer(struct iris_inst >> *inst, struct iris_buffer *buffer) >> { >> struct iris_inst_hfi_gen2 *inst_hfi_gen2 = >> to_iris_inst_hfi_gen2(inst); >> struct iris_hfi_buffer hfi_buffer; >> + struct iris_hfi_buffer hfi_meta_buffer; >> u32 port; >> int ret; >> >> @@ -1331,6 +1353,25 @@ static int >> iris_hfi_gen2_session_queue_buffer(struct iris_inst *inst, struct iri >> &hfi_buffer, >> sizeof(hfi_buffer)); >> >> + /* check if any metadata buffer is available not queued, queueit */ >> + if (port == HFI_PORT_RAW) { >> + buffer = iris_queue_metadata_buffers(inst, >> BUF_ROIMB_DELTAQP, buffer->index); >> + if (buffer) { >> + iris_hfi_gen2_get_buffer(inst->domain, buffer, >> &hfi_meta_buffer); >> + port = iris_hfi_gen2_get_port_from_buf_type(inst, >> buffer->type); >> + iris_hfi_gen2_create_packet(inst_hfi_gen2->packet, >> + HFI_CMD_BUFFER, >> + HFI_HOST_FLAGS_INTR_REQUIRED, >> + HFI_PAYLOAD_STRUCTURE, >> + port, >> + inst->core->packet_id++, >> + &hfi_meta_buffer, >> + sizeof(hfi_meta_buffer)); >> + >> + buffer->attr |= BUF_ATTR_QUEUED; >> + buffer->attr &= ~BUF_ATTR_DEQUEUED; >> + } >> + } >> return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, >> inst_hfi_gen2->packet->size); >> } >> @@ -1359,6 +1400,26 @@ static int >> iris_hfi_gen2_session_release_buffer(struct iris_inst *inst, struct i >> inst_hfi_gen2->packet->size); >> } >> >> +static int iris_hfi_gen2_subscribe_metadata_delivery(struct >> iris_inst *inst, u32 plane) >> +{ >> + struct iris_inst_hfi_gen2 *inst_hfi_gen2 = >> to_iris_inst_hfi_gen2(inst); >> + u32 port = iris_hfi_gen2_get_port(inst, >> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); >> + u32 payload[2] = {HFI_MODE_METADATA, HFI_PROP_ROI_INFO}; >> + >> + iris_hfi_gen2_packet_session_command(inst, >> + HFI_CMD_DELIVERY_MODE, >> + (HFI_HOST_FLAGS_RESPONSE_REQUIRED | >> + HFI_HOST_FLAGS_INTR_REQUIRED), >> + port, >> + inst->session_id, >> + HFI_PAYLOAD_U32_ARRAY, >> + &payload, >> + sizeof(u32) * 2); >> + >> + return iris_hfi_queue_cmd_write(inst->core, inst_hfi_gen2->packet, >> + inst_hfi_gen2->packet->size); >> +} >> + >> static const struct iris_hfi_session_ops iris_hfi_gen2_session_ops = { >> .session_open = iris_hfi_gen2_session_open, >> .session_set_config_params = >> iris_hfi_gen2_session_set_config_params, >> @@ -1372,6 +1433,7 @@ static const struct iris_hfi_session_ops >> iris_hfi_gen2_session_ops = { >> .session_drain = iris_hfi_gen2_session_drain, >> .session_resume_drain = iris_hfi_gen2_session_resume_drain, >> .session_close = iris_hfi_gen2_session_close, >> + .session_subscribe_metadata_delivery = >> iris_hfi_gen2_subscribe_metadata_delivery, >> }; >> >> static struct iris_inst *iris_hfi_gen2_get_instance(void) >> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h >> b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h >> index >> f43aea10090d8f1d6ae5c20547e5f6321b2ca203..d0661f5fe6a6f39295dad8950edb2f1a85893216 >> 100644 >> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h >> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_defines.h >> @@ -20,6 +20,7 @@ >> #define HFI_CMD_DRAIN 0x01000007 >> #define HFI_CMD_RESUME 0x01000008 >> #define HFI_CMD_BUFFER 0x01000009 >> +#define HFI_CMD_DELIVERY_MODE 0x0100000A >> #define HFI_CMD_SUBSCRIBE_MODE 0x0100000B >> #define HFI_CMD_SETTINGS_CHANGE 0x0100000C >> #define HFI_CMD_PAUSE 0x01000011 >> @@ -133,6 +134,7 @@ enum hfi_flip { >> #define HFI_PROP_DEC_START_FROM_RAP_FRAME 0x03000169 >> #define HFI_PROP_NO_OUTPUT 0x0300016a >> #define HFI_PROP_BUFFER_MARK 0x0300016c >> +#define HFI_PROP_ROI_INFO 0x03000173 >> #define HFI_PROP_WORST_COMPRESSION_RATIO 0x03000174 >> #define HFI_PROP_WORST_COMPLEXITY_FACTOR 0x03000175 >> #define HFI_PROP_RAW_RESOLUTION 0x03000178 >> @@ -174,6 +176,7 @@ enum hfi_flip { >> enum hfi_property_mode_type { >> HFI_MODE_PORT_SETTINGS_CHANGE = 0x00000001, >> HFI_MODE_PROPERTY = 0x00000002, >> + HFI_MODE_METADATA = 0x00000004, >> }; >> >> enum hfi_color_format { >> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c >> b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c >> index >> 0d05dd2afc07d830cc8502ab5f28001312991ba8..aeb0426a05694f219f82145cd84a28287ed3075e >> 100644 >> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c >> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.c >> @@ -100,9 +100,9 @@ static void iris_hfi_gen2_create_header(struct >> iris_hfi_header *hdr, >> hdr->num_packets = 0; >> } >> >> -static void iris_hfi_gen2_create_packet(struct iris_hfi_header *hdr, >> u32 pkt_type, >> - u32 pkt_flags, u32 payload_type, u32 port, >> - u32 packet_id, void *payload, u32 payload_size) >> +void iris_hfi_gen2_create_packet(struct iris_hfi_header *hdr, u32 >> pkt_type, >> + u32 pkt_flags, u32 payload_type, u32 port, >> + u32 packet_id, void *payload, u32 payload_size) >> { >> struct iris_hfi_packet *pkt = (struct iris_hfi_packet *)((u8 >> *)hdr + hdr->size); >> u32 pkt_size = sizeof(*pkt) + payload_size; >> diff --git a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h >> b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h >> index >> 25b9582349ca1a0ce6efc0b146a3abb798485c45..613eb500609f745daebdcbdf9a25b85cb9465a79 >> 100644 >> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h >> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_packet.h >> @@ -121,5 +121,8 @@ void iris_hfi_gen2_packet_session_property(struct >> iris_inst *inst, >> void iris_hfi_gen2_packet_sys_interframe_powercollapse(struct >> iris_core *core, >> struct iris_hfi_header *hdr); >> void iris_hfi_gen2_packet_sys_pc_prep(struct iris_core *core, >> struct iris_hfi_header *hdr); >> +void iris_hfi_gen2_create_packet(struct iris_hfi_header *hdr, u32 >> pkt_type, >> + u32 pkt_flags, u32 payload_type, u32 port, >> + u32 packet_id, void *payload, u32 payload_size); >> >> #endif >> diff --git >> a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c >> b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c >> index >> 8c2644c7f6e85983d7ad7584fc0cb570e4813ae4..f63e0a7723e8583da818c2b004e367c1dd3d94f7 >> 100644 >> --- a/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c >> +++ b/drivers/media/platform/qcom/iris/iris_hfi_gen2_response.c >> @@ -58,6 +58,8 @@ static u32 iris_hfi_gen2_buf_type_to_driver(struct >> iris_inst *inst, >> return BUF_PARTIAL; >> case HFI_BUFFER_VPSS: >> return BUF_VPSS; >> + case HFI_BUFFER_METADATA: >> + return BUF_ROIMB_DELTAQP; >> default: >> return 0; >> } >> @@ -77,6 +79,7 @@ static bool >> iris_hfi_gen2_is_valid_hfi_buffer_type(u32 buffer_type) >> case HFI_BUFFER_PERSIST: >> case HFI_BUFFER_VPSS: >> case HFI_BUFFER_PARTIAL_DATA: >> + case HFI_BUFFER_METADATA: >> return true; >> default: >> return false; >> @@ -452,6 +455,30 @@ static int >> iris_hfi_gen2_handle_release_internal_buffer(struct iris_inst *inst, >> return 0; >> } >> >> +static int iris_hfi_gen2_handle_output_metadata_buffer(struct >> iris_inst *inst, >> + struct iris_hfi_buffer *buffer) >> +{ >> + u32 buf_type = iris_hfi_gen2_buf_type_to_driver(inst, >> HFI_BUFFER_METADATA); >> + struct iris_buffers *buffers = &inst->buffers[buf_type]; >> + struct iris_buffer *buf, *iter; >> + bool found = false; >> + >> + list_for_each_entry(iter, &buffers->list, list) { >> + if (iter->device_addr == buffer->base_address) { >> + found = true; >> + buf = iter; >> + break; >> + } >> + } >> + if (!found) >> + return -EINVAL; >> + >> + buf->attr &= ~BUF_ATTR_QUEUED; >> + buf->attr |= BUF_ATTR_DEQUEUED; >> + >> + return 0; >> +} >> + >> static int iris_hfi_gen2_handle_session_stop(struct iris_inst *inst, >> struct iris_hfi_packet *pkt) >> { >> @@ -499,6 +526,8 @@ static int >> iris_hfi_gen2_handle_session_buffer(struct iris_inst *inst, >> return iris_hfi_gen2_handle_input_buffer(inst, buffer); >> else if (buffer->type == HFI_BUFFER_BITSTREAM) >> return iris_hfi_gen2_handle_output_buffer(inst, buffer); >> + else if (buffer->type == HFI_BUFFER_METADATA) >> + return iris_hfi_gen2_handle_output_metadata_buffer(inst, >> buffer); >> else >> return >> iris_hfi_gen2_handle_release_internal_buffer(inst, buffer); >> } >> diff --git a/drivers/media/platform/qcom/iris/iris_platform_common.h >> b/drivers/media/platform/qcom/iris/iris_platform_common.h >> index >> 9748095091461ba13443c63955a42906fa4f050c..9910eb5514b3ae0a6b5349adb071d0a56375102c >> 100644 >> --- a/drivers/media/platform/qcom/iris/iris_platform_common.h >> +++ b/drivers/media/platform/qcom/iris/iris_platform_common.h >> @@ -186,6 +186,8 @@ enum platform_inst_fw_cap_type { >> LAYER5_BITRATE_HEVC, >> REQUEST_SYNC_FRAME, >> TIME_DELTA_BASED_RC, >> + ROI_PARAMS, >> + MB_SIZE, >> INST_FW_CAP_MAX, >> }; >> >> @@ -197,6 +199,7 @@ enum platform_inst_fw_cap_flags { >> CAP_FLAG_CLIENT_SET = BIT(4), >> CAP_FLAG_BITMASK = BIT(5), >> CAP_FLAG_VOLATILE = BIT(6), >> + CAP_FLAG_CUSTOM = BIT(7), >> }; >> >> struct platform_inst_fw_cap { >> @@ -206,6 +209,8 @@ struct platform_inst_fw_cap { >> s64 step_or_mask; >> s64 value; >> u32 hfi_id; >> + const void *p_array; >> + u32 elems; >> enum platform_inst_fw_cap_flags flags; >> int (*set)(struct iris_inst *inst, >> enum platform_inst_fw_cap_type cap_id); >> diff --git a/drivers/media/platform/qcom/iris/iris_venc.c >> b/drivers/media/platform/qcom/iris/iris_venc.c >> index >> a945992f63aa8a0c40b8d6bc473d0bc90270e6cd..21ba9639d17b2c64e8fa33b4aacbd1946fc4dae2 >> 100644 >> --- a/drivers/media/platform/qcom/iris/iris_venc.c >> +++ b/drivers/media/platform/qcom/iris/iris_venc.c >> @@ -498,6 +498,10 @@ int iris_venc_streamon_output(struct iris_inst >> *inst) >> if (ret) >> goto error; >> >> + ret = iris_set_metadata_delivery(inst, >> V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); >> + if (ret) >> + goto error; >> + >> ret = iris_alloc_and_queue_persist_bufs(inst, BUF_ARP); >> if (ret) >> return ret; >> diff --git a/drivers/media/platform/qcom/iris/iris_venc.h >> b/drivers/media/platform/qcom/iris/iris_venc.h >> index >> 00c1716b2747c7e840c2a3317800d83663744bf0..df97011636740be6cdfe5867f273c5f93408f570 >> 100644 >> --- a/drivers/media/platform/qcom/iris/iris_venc.h >> +++ b/drivers/media/platform/qcom/iris/iris_venc.h >> @@ -22,5 +22,7 @@ int iris_venc_streamon_output(struct iris_inst *inst); >> int iris_venc_qbuf(struct iris_inst *inst, struct vb2_v4l2_buffer >> *vbuf); >> int iris_venc_start_cmd(struct iris_inst *inst); >> int iris_venc_stop_cmd(struct iris_inst *inst); >> +struct iris_buffer *iris_queue_metadata_buffers(struct iris_inst *inst, >> + enum iris_buffer_type buffer_type, u32 index); >> >> #endif >> diff --git a/drivers/media/platform/qcom/iris/iris_vidc.c >> b/drivers/media/platform/qcom/iris/iris_vidc.c >> index >> fcbc60016beec693f2ce27927a09a2d51494bc38..fae3d113a9dc990f06167ee0b7fb8fab24a0552c >> 100644 >> --- a/drivers/media/platform/qcom/iris/iris_vidc.c >> +++ b/drivers/media/platform/qcom/iris/iris_vidc.c >> @@ -180,6 +180,7 @@ int iris_open(struct file *filp) >> INIT_LIST_HEAD(&inst->buffers[BUF_SCRATCH_2].list); >> INIT_LIST_HEAD(&inst->buffers[BUF_VPSS].list); >> INIT_LIST_HEAD(&inst->buffers[BUF_PARTIAL].list); >> + INIT_LIST_HEAD(&inst->buffers[BUF_ROIMB_DELTAQP].list); >> init_completion(&inst->completion); >> init_completion(&inst->flush_completion); >> >> @@ -299,6 +300,7 @@ int iris_close(struct file *filp) >> iris_destroy_all_internal_buffers(inst, >> V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); >> iris_check_num_queued_internal_buffers(inst, >> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); >> iris_check_num_queued_internal_buffers(inst, >> V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE); >> + iris_destroy_roi_metadata_buffers(inst); >> iris_remove_session(inst); >> mutex_unlock(&inst->lock); >> mutex_destroy(&inst->ctx_q_lock); >> >> -- >> 2.34.1 >> >