From 84d22be9dca4e16eb617dcdca9f754f8230a712c Mon Sep 17 00:00:00 2001 From: Praneeth Paladugu Date: Tue, 18 Jul 2017 22:55:59 -0700 Subject: [PATCH] msm: vidc: Add support for decoder STOP command Decoder STOP command is to signal HW that this is the EOS buffer. HW returns all the pending ETB's and FTB's. One of the FTB_DONE's will have EOS flag back to client. With this, driver don't need to support zero_bytes_used input buffers. CRs-Fixed: 2078801 Signed-off-by: Praneeth Paladugu Change-Id: I44c60db1c98707501b5637eba5d1d81663d6a722 --- drivers/media/platform/msm/vidc/msm_vidc.c | 6 +- .../media/platform/msm/vidc/msm_vidc_common.c | 109 ++++++++++++++++++ .../media/platform/msm/vidc/msm_vidc_common.h | 1 + .../platform/msm/vidc/msm_vidc_internal.h | 6 + 4 files changed, 121 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c index 02bfc459614f..20d5ba661a6b 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_vidc.c @@ -1238,7 +1238,7 @@ static inline int vb2_bufq_init(struct msm_vidc_inst *inst, q->ops = msm_venc_get_vb2q_ops(); q->mem_ops = &msm_vidc_vb2_mem_ops; q->drv_priv = inst; - q->allow_zero_bytesused = 1; + q->allow_zero_bytesused = !V4L2_TYPE_IS_OUTPUT(type); return vb2_queue_init(q); } @@ -1356,6 +1356,7 @@ void *msm_vidc_open(int core_id, int session_type) INIT_MSM_VIDC_LIST(&inst->pending_getpropq); INIT_MSM_VIDC_LIST(&inst->outputbufs); INIT_MSM_VIDC_LIST(&inst->registeredbufs); + INIT_MSM_VIDC_LIST(&inst->eosbufs); kref_init(&inst->kref); @@ -1448,6 +1449,7 @@ fail_mem_client: DEINIT_MSM_VIDC_LIST(&inst->pending_getpropq); DEINIT_MSM_VIDC_LIST(&inst->outputbufs); DEINIT_MSM_VIDC_LIST(&inst->registeredbufs); + DEINIT_MSM_VIDC_LIST(&inst->eosbufs); kfree(inst); inst = NULL; @@ -1473,6 +1475,7 @@ static void cleanup_instance(struct msm_vidc_inst *inst) dprintk(VIDC_ERR, "Failed to release scratch buffers\n"); } + msm_comm_release_eos_buffers(inst); if (msm_comm_release_persist_buffers(inst)) { dprintk(VIDC_ERR, @@ -1516,6 +1519,7 @@ int msm_vidc_destroy(struct msm_vidc_inst *inst) DEINIT_MSM_VIDC_LIST(&inst->pending_getpropq); DEINIT_MSM_VIDC_LIST(&inst->outputbufs); DEINIT_MSM_VIDC_LIST(&inst->registeredbufs); + DEINIT_MSM_VIDC_LIST(&inst->eosbufs); v4l2_fh_del(&inst->event_handler); v4l2_fh_exit(&inst->event_handler); diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index 7ae3a1ea5eba..ca72d0fa31a1 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -1829,6 +1829,26 @@ static struct vb2_buffer *get_vb_from_device_addr(struct buf_queue *bufq, return vb; } +static bool is_eos_buffer(struct msm_vidc_inst *inst, u32 device_addr) +{ + struct eos_buf *temp, *next; + bool found = false; + + mutex_lock(&inst->eosbufs.lock); + list_for_each_entry_safe(temp, next, &inst->eosbufs.list, list) { + if (temp->smem->device_addr == device_addr) { + found = true; + list_del(&temp->list); + msm_comm_smem_free(inst, temp->smem); + kfree(temp); + break; + } + } + mutex_unlock(&inst->eosbufs.lock); + + return found; +} + static void handle_ebd(enum hal_command_response cmd, void *data) { struct msm_vidc_cb_data_done *response = data; @@ -1849,6 +1869,14 @@ static void handle_ebd(enum hal_command_response cmd, void *data) return; } + empty_buf_done = (struct vidc_hal_ebd *)&response->input_done; + /* If this is internal EOS buffer, handle it in driver */ + if (is_eos_buffer(inst, empty_buf_done->packet_buffer)) { + dprintk(VIDC_DBG, "Received EOS buffer %pK\n", + (void *)empty_buf_done->packet_buffer); + goto exit; + } + vb = get_vb_from_device_addr(&inst->bufq[OUTPUT_PORT], response->input_done.packet_buffer); if (vb) { @@ -1900,6 +1928,7 @@ static void handle_ebd(enum hal_command_response cmd, void *data) msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_EBD); } +exit: put_inst(inst); } @@ -3587,6 +3616,66 @@ int msm_vidc_comm_cmd(void *instance, union msm_v4l2_cmd *cmd) "Failed to flush buffers: %d\n", rc); } break; + + case V4L2_DEC_CMD_STOP: + { + struct vidc_frame_data data = {0}; + struct hfi_device *hdev; + struct eos_buf *binfo; + u32 smem_flags = 0; + + get_inst(inst->core, inst); + if (inst->session_type != MSM_VIDC_DECODER) { + dprintk(VIDC_DBG, + "Non-Decoder session. DEC_STOP is not valid\n"); + rc = -EINVAL; + goto exit; + } + + binfo = kzalloc(sizeof(*binfo), GFP_KERNEL); + if (!binfo) { + dprintk(VIDC_ERR, "%s: Out of memory\n", __func__); + rc = -ENOMEM; + goto exit; + } + + if (inst->flags & VIDC_SECURE) + smem_flags |= SMEM_SECURE; + + binfo->smem = msm_comm_smem_alloc(inst, + SZ_4K, 1, smem_flags, + HAL_BUFFER_INPUT, 0); + if (!binfo->smem) { + dprintk(VIDC_ERR, + "Failed to allocate eos memory\n"); + goto exit; + } + + mutex_lock(&inst->eosbufs.lock); + list_add_tail(&binfo->list, &inst->eosbufs.list); + mutex_unlock(&inst->eosbufs.lock); + + data.alloc_len = binfo->smem->size; + data.device_addr = binfo->smem->device_addr; + data.clnt_data = data.device_addr; + data.buffer_type = HAL_BUFFER_INPUT; + data.filled_len = 0; + data.offset = 0; + data.flags = HAL_BUFFERFLAG_EOS; + data.timestamp = LLONG_MAX; + data.extradata_addr = data.device_addr; + data.extradata_size = 0; + dprintk(VIDC_DBG, "Queueing EOS buffer %pK\n", + (void *)data.device_addr); + hdev = inst->core->device; + + rc = call_hfi_op(hdev, session_etb, inst->session, + &data); +exit: + put_inst(inst); + break; + } + default: dprintk(VIDC_ERR, "Unknown Command %d\n", which_cmd); rc = -ENOTSUPP; @@ -4307,6 +4396,26 @@ exit: return rc; } +void msm_comm_release_eos_buffers(struct msm_vidc_inst *inst) +{ + struct eos_buf *buf, *next; + + if (!inst) { + dprintk(VIDC_ERR, + "Invalid instance pointer = %pK\n", inst); + return; + } + + mutex_lock(&inst->eosbufs.lock); + list_for_each_entry_safe(buf, next, &inst->eosbufs.list, list) { + list_del(&buf->list); + msm_comm_smem_free(inst, buf->smem); + kfree(buf); + } + INIT_LIST_HEAD(&inst->eosbufs.list); + mutex_unlock(&inst->eosbufs.lock); +} + int msm_comm_release_persist_buffers(struct msm_vidc_inst *inst) { struct msm_smem *handle; diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h index 5658df95db26..d6e8a84fb5bb 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h @@ -60,6 +60,7 @@ int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst, bool check_for_reuse); int msm_comm_release_persist_buffers(struct msm_vidc_inst *inst); int msm_comm_release_output_buffers(struct msm_vidc_inst *inst); +void msm_comm_release_eos_buffers(struct msm_vidc_inst *inst); int msm_comm_force_cleanup(struct msm_vidc_inst *inst); int msm_comm_suspend(int core_id); enum hal_extradata_id msm_comm_get_hal_extradata_index( diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h index 4cb900bbca10..08ba0bfb566e 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h @@ -132,6 +132,11 @@ enum buffer_owner { MAX_OWNER }; +struct eos_buf { + struct list_head list; + struct msm_smem *smem; +}; + struct internal_buf { struct list_head list; enum hal_buffer buffer_type; @@ -270,6 +275,7 @@ struct msm_vidc_inst { struct msm_vidc_list persistbufs; struct msm_vidc_list pending_getpropq; struct msm_vidc_list outputbufs; + struct msm_vidc_list eosbufs; struct msm_vidc_list registeredbufs; struct buffer_requirements buff_req; void *mem_client;