msm: vidc: enable mark_data feature
Use v4l2_buffer.m.planes[0].reserved[3,4] to pass
mark_data and mark_target with userspace.
Use 2 lists to store and pass mark_data between
v4l2_buffer and HFI.
CRs-fixed: 2099825
Change-Id: I2102b80a81041a6283061bcf320de9a21b373156
Signed-off-by: Qiwei Liu <qiweil@codeaurora.org>
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 920e91a..c5d3a4a 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -510,6 +510,12 @@
msm_comm_update_input_cr(inst, b->index, cr);
}
+ if (inst->session_type == MSM_VIDC_DECODER &&
+ b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ msm_comm_store_mark_data(&inst->etb_data, b->index,
+ b->m.planes[0].reserved[3], b->m.planes[0].reserved[4]);
+ }
+
q = msm_comm_get_vb2q(inst, b->type);
if (!q) {
dprintk(VIDC_ERR,
@@ -562,6 +568,13 @@
b->m.planes[i].reserved[1] = b->m.planes[i].data_offset;
}
+ if (inst->session_type == MSM_VIDC_DECODER &&
+ b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ msm_comm_fetch_mark_data(&inst->fbd_data, b->index,
+ &b->m.planes[0].reserved[3],
+ &b->m.planes[0].reserved[4]);
+ }
+
return rc;
}
EXPORT_SYMBOL(msm_vidc_dqbuf);
@@ -1566,6 +1579,8 @@
INIT_MSM_VIDC_LIST(&inst->registeredbufs);
INIT_MSM_VIDC_LIST(&inst->reconbufs);
INIT_MSM_VIDC_LIST(&inst->eosbufs);
+ INIT_MSM_VIDC_LIST(&inst->etb_data);
+ INIT_MSM_VIDC_LIST(&inst->fbd_data);
kref_init(&inst->kref);
@@ -1673,6 +1688,8 @@
DEINIT_MSM_VIDC_LIST(&inst->eosbufs);
DEINIT_MSM_VIDC_LIST(&inst->freqs);
DEINIT_MSM_VIDC_LIST(&inst->input_crs);
+ DEINIT_MSM_VIDC_LIST(&inst->etb_data);
+ DEINIT_MSM_VIDC_LIST(&inst->fbd_data);
kfree(inst);
inst = NULL;
@@ -1716,6 +1733,10 @@
dprintk(VIDC_ERR,
"Failed to release persist buffers\n");
+ if (msm_comm_release_mark_data(inst))
+ dprintk(VIDC_ERR,
+ "Failed to release mark_data buffers\n");
+
/*
* At this point all buffes should be with driver
* irrespective of scenario
@@ -1771,6 +1792,8 @@
DEINIT_MSM_VIDC_LIST(&inst->eosbufs);
DEINIT_MSM_VIDC_LIST(&inst->freqs);
DEINIT_MSM_VIDC_LIST(&inst->input_crs);
+ DEINIT_MSM_VIDC_LIST(&inst->etb_data);
+ DEINIT_MSM_VIDC_LIST(&inst->fbd_data);
mutex_destroy(&inst->sync_lock);
mutex_destroy(&inst->bufq[CAPTURE_PORT].lock);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 8fd1dd1..bcbd986 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -2569,6 +2569,11 @@
}
vb->timestamp = (time_usec * NSEC_PER_USEC);
+ if (inst->session_type == MSM_VIDC_DECODER) {
+ msm_comm_store_mark_data(&inst->fbd_data, vb->index,
+ fill_buf_done->mark_data, fill_buf_done->mark_target);
+ }
+
extra_idx = EXTRADATA_IDX(inst->bufq[CAPTURE_PORT].num_planes);
if (extra_idx && extra_idx < VIDEO_MAX_PLANES)
vb->planes[extra_idx].bytesused = vb->planes[extra_idx].length;
@@ -3955,9 +3960,6 @@
data->clnt_data = data->device_addr;
if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- bool pic_decoding_mode = msm_comm_g_ctrl_for_id(inst,
- V4L2_CID_MPEG_VIDC_VIDEO_PICTYPE_DEC_MODE);
-
data->buffer_type = HAL_BUFFER_INPUT;
data->filled_len = vb->planes[0].bytesused;
data->offset = vb->planes[0].data_offset;
@@ -3974,13 +3976,10 @@
if (vbuf->flags & V4L2_QCOM_BUF_TIMESTAMP_INVALID)
data->timestamp = LLONG_MAX;
- /* XXX: This is a dirty hack necessitated by the firmware,
- * which refuses to issue FBDs for non I-frames in Picture Type
- * Decoding mode, unless we pass in non-zero value in mark_data
- * and mark_target.
- */
- data->mark_data = data->mark_target =
- pic_decoding_mode ? 0xdeadbeef : 0;
+ if (inst->session_type == MSM_VIDC_DECODER) {
+ msm_comm_fetch_mark_data(&inst->etb_data, vb->index,
+ &data->mark_data, &data->mark_target);
+ }
} else if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
data->buffer_type = msm_comm_get_hal_output_buffer(inst);
@@ -6610,3 +6609,93 @@
return ret;
}
+void msm_comm_store_mark_data(struct msm_vidc_list *data_list,
+ u32 index, u32 mark_data, u32 mark_target)
+{
+ struct msm_vidc_buf_data *pdata = NULL;
+ bool found = false;
+
+ if (!data_list) {
+ dprintk(VIDC_ERR, "%s: invalid params %pK\n",
+ __func__, data_list);
+ return;
+ }
+
+ mutex_lock(&data_list->lock);
+ list_for_each_entry(pdata, &data_list->list, list) {
+ if (pdata->index == index) {
+ pdata->mark_data = mark_data;
+ pdata->mark_target = mark_target;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dprintk(VIDC_WARN, "%s: malloc failure.\n", __func__);
+ goto exit;
+ }
+ pdata->index = index;
+ pdata->mark_data = mark_data;
+ pdata->mark_target = mark_target;
+ list_add_tail(&pdata->list, &data_list->list);
+ }
+
+exit:
+ mutex_unlock(&data_list->lock);
+}
+
+void msm_comm_fetch_mark_data(struct msm_vidc_list *data_list,
+ u32 index, u32 *mark_data, u32 *mark_target)
+{
+ struct msm_vidc_buf_data *pdata = NULL;
+
+ if (!data_list || !mark_data || !mark_target) {
+ dprintk(VIDC_ERR, "%s: invalid params %pK %pK %pK\n",
+ __func__, data_list, mark_data, mark_target);
+ return;
+ }
+
+ *mark_data = *mark_target = 0;
+ mutex_lock(&data_list->lock);
+ list_for_each_entry(pdata, &data_list->list, list) {
+ if (pdata->index == index) {
+ *mark_data = pdata->mark_data;
+ *mark_target = pdata->mark_target;
+ /* clear after fetch */
+ pdata->mark_data = pdata->mark_target = 0;
+ break;
+ }
+ }
+ mutex_unlock(&data_list->lock);
+}
+
+int msm_comm_release_mark_data(struct msm_vidc_inst *inst)
+{
+ struct msm_vidc_buf_data *pdata, *next;
+
+ if (!inst) {
+ dprintk(VIDC_ERR, "%s: invalid params %pK\n",
+ __func__, inst);
+ return -EINVAL;
+ }
+
+ mutex_lock(&inst->etb_data.lock);
+ list_for_each_entry_safe(pdata, next, &inst->etb_data.list, list) {
+ list_del(&pdata->list);
+ kfree(pdata);
+ }
+ mutex_unlock(&inst->etb_data.lock);
+
+ mutex_lock(&inst->fbd_data.lock);
+ list_for_each_entry_safe(pdata, next, &inst->fbd_data.list, list) {
+ list_del(&pdata->list);
+ kfree(pdata);
+ }
+ mutex_unlock(&inst->fbd_data.lock);
+
+ return 0;
+}
+
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index 05e2b91..053a250 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -154,5 +154,10 @@
struct v4l2_buffer *v4l2);
void kref_put_mbuf(struct msm_vidc_buffer *mbuf);
bool kref_get_mbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf);
+void msm_comm_store_mark_data(struct msm_vidc_list *data_list,
+ u32 index, u32 mark_data, u32 mark_target);
+void msm_comm_fetch_mark_data(struct msm_vidc_list *data_list,
+ u32 index, u32 *mark_data, u32 *mark_target);
+int msm_comm_release_mark_data(struct msm_vidc_inst *inst);
#endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index ba05059..a0f7d2e 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -175,6 +175,13 @@
u32 *vpe_csc_custom_limit_coeff;
};
+struct msm_vidc_buf_data {
+ struct list_head list;
+ u32 index;
+ u32 mark_data;
+ u32 mark_target;
+};
+
struct msm_vidc_common_data {
char key[128];
int value;
@@ -349,6 +356,8 @@
struct msm_vidc_list reconbufs;
struct msm_vidc_list eosbufs;
struct msm_vidc_list registeredbufs;
+ struct msm_vidc_list etb_data;
+ struct msm_vidc_list fbd_data;
struct buffer_requirements buff_req;
struct smem_client *mem_client;
struct v4l2_ctrl_handler ctrl_handler;