diff --git a/driver/vidc/inc/msm_vidc_inst.h b/driver/vidc/inc/msm_vidc_inst.h index d1841a9a56..c3acb30354 100644 --- a/driver/vidc/inc/msm_vidc_inst.h +++ b/driver/vidc/inc/msm_vidc_inst.h @@ -144,6 +144,7 @@ struct msm_vidc_inst { struct list_head caps_list; struct list_head children_list; struct list_head firmware_list; + struct list_head pending_pkts; /* list of struct hfi_pending_packet */ bool once_per_session_set; bool ipsc_properties_set; bool opsc_properties_set; diff --git a/driver/vidc/inc/msm_vidc_memory.h b/driver/vidc/inc/msm_vidc_memory.h index 1226205875..69c4acf3c8 100644 --- a/driver/vidc/inc/msm_vidc_memory.h +++ b/driver/vidc/inc/msm_vidc_memory.h @@ -11,6 +11,8 @@ struct msm_vidc_core; struct msm_vidc_inst; +#define MSM_MEM_POOL_PACKET_SIZE 1024 + struct msm_memory_dmabuf { struct list_head list; struct dma_buf *dmabuf; @@ -23,6 +25,7 @@ enum msm_memory_pool_type { MSM_MEM_POOL_ALLOC, MSM_MEM_POOL_TIMESTAMP, MSM_MEM_POOL_DMABUF, + MSM_MEM_POOL_PACKET, MSM_MEM_POOL_MAX, }; diff --git a/driver/vidc/inc/venus_hfi.h b/driver/vidc/inc/venus_hfi.h index 48c9a85235..129b66280a 100644 --- a/driver/vidc/inc/venus_hfi.h +++ b/driver/vidc/inc/venus_hfi.h @@ -28,6 +28,11 @@ struct vidc_buffer_addr_info { u32 response_required; }; +struct hfi_pending_packet { + struct list_head list; + void *data; +}; + int venus_hfi_session_property(struct msm_vidc_inst *inst, u32 pkt_type, u32 flags, u32 port, u32 payload_type, void *payload, u32 payload_size); diff --git a/driver/vidc/src/msm_vidc.c b/driver/vidc/src/msm_vidc.c index 3d09ab5a86..5c4f632195 100644 --- a/driver/vidc/src/msm_vidc.c +++ b/driver/vidc/src/msm_vidc.c @@ -945,6 +945,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type) INIT_LIST_HEAD(&inst->firmware_list); INIT_LIST_HEAD(&inst->enc_input_crs); INIT_LIST_HEAD(&inst->dmabuf_tracker); + INIT_LIST_HEAD(&inst->pending_pkts); for (i = 0; i < MAX_SIGNAL; i++) init_completion(&inst->completions[i]); diff --git a/driver/vidc/src/msm_vidc_control.c b/driver/vidc/src/msm_vidc_control.c index 18a3706005..175a547fc9 100644 --- a/driver/vidc/src/msm_vidc_control.c +++ b/driver/vidc/src/msm_vidc_control.c @@ -945,14 +945,6 @@ int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl) kfree(curr_node); } - /* dynamic controls with request will be set along with qbuf */ - if (inst->request) { - i_vpr_l(inst, - "%s: request api enabled, dynamic ctrls to be set with qbuf\n", - __func__); - return 0; - } - /* Dynamic set control ASAP */ rc = msm_vidc_set_v4l2_properties(inst); if (rc) { diff --git a/driver/vidc/src/msm_vidc_memory.c b/driver/vidc/src/msm_vidc_memory.c index 8e54aa8b57..9cf1ff5bf2 100644 --- a/driver/vidc/src/msm_vidc_memory.c +++ b/driver/vidc/src/msm_vidc_memory.c @@ -17,6 +17,7 @@ #include "msm_vidc_dt.h" #include "msm_vidc_core.h" #include "msm_vidc_events.h" +#include "venus_hfi.h" struct msm_vidc_buf_region_name { enum msm_vidc_buffer_region region; @@ -589,6 +590,8 @@ static struct msm_vidc_type_size_name buftype_size_name_arr[] = { {MSM_MEM_POOL_ALLOC, sizeof(struct msm_vidc_alloc), "MSM_MEM_POOL_ALLOC" }, {MSM_MEM_POOL_TIMESTAMP, sizeof(struct msm_vidc_timestamp), "MSM_MEM_POOL_TIMESTAMP" }, {MSM_MEM_POOL_DMABUF, sizeof(struct msm_memory_dmabuf), "MSM_MEM_POOL_DMABUF" }, + {MSM_MEM_POOL_PACKET, sizeof(struct hfi_pending_packet) + MSM_MEM_POOL_PACKET_SIZE, + "MSM_MEM_POOL_PACKET"}, }; int msm_memory_pools_init(struct msm_vidc_inst *inst) diff --git a/driver/vidc/src/venus_hfi.c b/driver/vidc/src/venus_hfi.c index 2b1d9fc59d..ed4960d460 100644 --- a/driver/vidc/src/venus_hfi.c +++ b/driver/vidc/src/venus_hfi.c @@ -3047,6 +3047,43 @@ unlock: return rc; } +static int venus_hfi_cache_packet(struct msm_vidc_inst *inst) +{ + int rc = 0; + struct hfi_header *hdr; + struct hfi_pending_packet *packet; + + if (!inst->packet) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + hdr = (struct hfi_header *)inst->packet; + if (hdr->size < sizeof(struct hfi_header)) { + d_vpr_e("%s: invalid hdr size %d\n", __func__, hdr->size); + return -EINVAL; + } + + packet = msm_memory_pool_alloc(inst, MSM_MEM_POOL_PACKET); + if (!packet) { + i_vpr_e(inst, "%s: failed to allocate pending packet\n", __func__); + return -ENOMEM; + } + + INIT_LIST_HEAD(&packet->list); + list_add_tail(&packet->list, &inst->pending_pkts); + packet->data = (u8 *)packet + sizeof(struct hfi_pending_packet); + + if (hdr->size > MSM_MEM_POOL_PACKET_SIZE) { + i_vpr_e(inst, "%s: header size %d exceeds pool packet size %d\n", + __func__, hdr->size, MSM_MEM_POOL_PACKET_SIZE); + return -EINVAL; + } + memcpy(packet->data, inst->packet, hdr->size); + + return rc; +} + int venus_hfi_session_property(struct msm_vidc_inst *inst, u32 pkt_type, u32 flags, u32 port, u32 payload_type, void *payload, u32 payload_size) @@ -3081,6 +3118,12 @@ int venus_hfi_session_property(struct msm_vidc_inst *inst, if (rc) goto unlock; + /* skip sending packet to firmware */ + if (inst->request) { + rc = venus_hfi_cache_packet(inst); + goto unlock; + } + rc = __iface_cmdq_write(inst->core, inst->packet); if (rc) goto unlock; @@ -3381,6 +3424,48 @@ unlock: return rc; } +static int venus_hfi_add_pending_packets(struct msm_vidc_inst *inst) +{ + int rc = 0; + int num_packets = 0; + struct hfi_pending_packet *pkt_info, *dummy; + struct hfi_header *hdr, *src_hdr; + struct hfi_packet *src_pkt; + + if (!inst || !inst->packet) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + hdr = (struct hfi_header *)inst->packet; + if (hdr->size < sizeof(struct hfi_header)) { + i_vpr_e(inst, "%s: invalid hdr size %d\n", + __func__, hdr->size); + return -EINVAL; + } + + list_for_each_entry_safe(pkt_info, dummy, &inst->pending_pkts, list) { + src_hdr = (struct hfi_header *)(pkt_info->data); + num_packets = src_hdr->num_packets; + src_pkt = (struct hfi_packet *)((u8 *)src_hdr + sizeof(struct hfi_header)); + while (num_packets > 0) { + memcpy((u8 *)hdr + hdr->size, (void *)src_pkt, src_pkt->size); + hdr->num_packets++; + hdr->size += src_pkt->size; + num_packets--; + src_pkt = (struct hfi_packet *)((u8 *)src_pkt + src_pkt->size); + if ((u8 *)src_pkt < (u8 *)src_hdr || + (u8 *)src_pkt > (u8 *)src_hdr + hdr->size) { + i_vpr_e(inst, "%s: invalid packet address\n", __func__); + return -EINVAL; + } + } + list_del(&pkt_info->list); + msm_memory_pool_free(inst, pkt_info); + } + return rc; +} + int venus_hfi_queue_buffer(struct msm_vidc_inst *inst, struct msm_vidc_buffer *buffer, struct msm_vidc_buffer *metabuf) { @@ -3438,6 +3523,10 @@ int venus_hfi_queue_buffer(struct msm_vidc_inst *inst, goto unlock; } + rc = venus_hfi_add_pending_packets(inst); + if (rc) + goto unlock; + rc = __iface_cmdq_write(inst->core, inst->packet); if (rc) goto unlock;