summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc.c6
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_common.c109
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_common.h1
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_internal.h6
4 files changed, 121 insertions, 1 deletions
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;