msm: vidc: update input tag implementation

In qbuf (input) store input_tag to etb_data list and send it to
firmware in etb. Firmware will return input_tag in ftb_done,
store it in fbd_data list and return the same when client does
dqbuf (output).

Change-Id: I3589e5a3017cac49000fc64191f9f756bc4011f4
Signed-off-by: Govindaraj Rajagopal <grajagop@codeaurora.org>
This commit is contained in:
Govindaraj Rajagopal 2020-02-28 17:42:40 +05:30 • committed by Darshana Patil
commit 455cd2b148
4 changed files with 23 additions and 163 deletions

View file

@ -363,7 +363,6 @@ int msm_vidc_qbuf(void *instance, struct media_device *mdev,
struct v4l2_buffer *b)
{
struct msm_vidc_inst *inst = instance;
struct msm_vidc_client_data *client_data = NULL;
int rc = 0;
unsigned int i = 0;
struct buf_queue *q = NULL;
@ -402,16 +401,15 @@ int msm_vidc_qbuf(void *instance, struct media_device *mdev,
}
if (b->type == INPUT_MPLANE) {
client_data = msm_comm_store_client_data(inst,
b->m.planes[0].reserved[MSM_VIDC_INPUT_TAG_1]);
if (!client_data) {
s_vpr_e(inst->sid,
"%s: failed to store client data\n", __func__);
rc = msm_comm_store_input_tag(&inst->etb_data, b->index,
b->m.planes[0].reserved[MSM_VIDC_INPUT_TAG_1],
0, inst->sid);
if (rc) {
s_vpr_e(inst->sid, "Failed to store input tag");
return -EINVAL;
}
msm_comm_store_input_tag(&inst->etb_data, b->index,
client_data->id, 0, inst->sid);
}
/*
* set perf mode for image session buffers so that
* they will be processed quickly
@ -442,8 +440,6 @@ int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
int rc = 0;
unsigned int i = 0;
struct buf_queue *q = NULL;
u32 input_tag = 0, input_tag2 = 0;
bool remove;
if (!inst || !b || !valid_v4l2_buffer(b, inst)) {
d_vpr_e("%s: invalid params, %pK %pK\n",
@ -474,36 +470,15 @@ int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
b->m.planes[i].reserved[MSM_VIDC_DATA_OFFSET] =
b->m.planes[i].data_offset;
}
/**
* Flush handling:
* Don't fetch tag - if flush issued at input/output port.
* Fetch tag - if atleast 1 ebd received after flush. (Flush_done
* event may be notified to userspace even before client
* dequeus all buffers at FBD, to avoid this race condition
* fetch tag atleast 1 ETB is successfully processed after flush)
*/
if (b->type == OUTPUT_MPLANE && !inst->in_flush &&
!inst->out_flush &&
(inst->session_type == MSM_VIDC_ENCODER ||
inst->clk_data.buffer_counter)) {
if (b->type == OUTPUT_MPLANE) {
rc = msm_comm_fetch_input_tag(&inst->fbd_data, b->index,
&input_tag, &input_tag2, inst->sid);
&b->m.planes[0].reserved[MSM_VIDC_INPUT_TAG_1],
&b->m.planes[0].reserved[MSM_VIDC_INPUT_TAG_2],
inst->sid);
if (rc) {
s_vpr_e(inst->sid, "Failed to fetch input tag");
return -EINVAL;
}
/**
* During flush input_tag & input_tag2 will be zero.
* Check before retrieving client data
*/
if (input_tag) {
remove = !(b->flags & V4L2_BUF_FLAG_END_OF_SUBFRAME) &&
!(b->flags & V4L2_BUF_FLAG_CODECCONFIG);
msm_comm_fetch_client_data(inst, remove,
input_tag, input_tag2,
&b->m.planes[0].reserved[MSM_VIDC_INPUT_TAG_1],
&b->m.planes[0].reserved[MSM_VIDC_INPUT_TAG_2]);
}
}
return rc;
@ -1470,7 +1445,6 @@ void *msm_vidc_open(int core_id, int session_type)
INIT_MSM_VIDC_LIST(&inst->registeredbufs);
INIT_MSM_VIDC_LIST(&inst->refbufs);
INIT_MSM_VIDC_LIST(&inst->eosbufs);
INIT_MSM_VIDC_LIST(&inst->client_data);
INIT_MSM_VIDC_LIST(&inst->etb_data);
INIT_MSM_VIDC_LIST(&inst->fbd_data);
INIT_MSM_VIDC_LIST(&inst->window_data);
@ -1575,7 +1549,6 @@ fail_bufq_capture:
DEINIT_MSM_VIDC_LIST(&inst->registeredbufs);
DEINIT_MSM_VIDC_LIST(&inst->eosbufs);
DEINIT_MSM_VIDC_LIST(&inst->input_crs);
DEINIT_MSM_VIDC_LIST(&inst->client_data);
DEINIT_MSM_VIDC_LIST(&inst->etb_data);
DEINIT_MSM_VIDC_LIST(&inst->fbd_data);
DEINIT_MSM_VIDC_LIST(&inst->window_data);
@ -1645,8 +1618,6 @@ static void msm_vidc_cleanup_instance(struct msm_vidc_inst *inst)
if (msm_comm_release_input_tag(inst))
s_vpr_e(inst->sid, "Failed to release input_tag buffers\n");
msm_comm_release_client_data(inst, true);
msm_comm_release_window_data(inst);
msm_comm_release_eos_buffers(inst);
@ -1702,7 +1673,6 @@ int msm_vidc_destroy(struct msm_vidc_inst *inst)
DEINIT_MSM_VIDC_LIST(&inst->registeredbufs);
DEINIT_MSM_VIDC_LIST(&inst->eosbufs);
DEINIT_MSM_VIDC_LIST(&inst->input_crs);
DEINIT_MSM_VIDC_LIST(&inst->client_data);
DEINIT_MSM_VIDC_LIST(&inst->etb_data);
DEINIT_MSM_VIDC_LIST(&inst->fbd_data);
DEINIT_MSM_VIDC_LIST(&inst->window_data);

View file

@ -2042,7 +2042,6 @@ static void handle_session_flush(enum hal_command_response cmd, void *data)
if (flush_type == HAL_FLUSH_ALL) {
msm_comm_clear_window_data(inst);
msm_comm_release_client_data(inst, false);
inst->clk_data.buffer_counter = 0;
}
@ -2511,6 +2510,7 @@ static void handle_fbd(enum hal_command_response cmd, void *data)
u64 time_usec = 0;
u32 planes[VIDEO_MAX_PLANES] = {0};
struct v4l2_format *f;
int rc = 0;
if (!response) {
d_vpr_e("Invalid response from vidc_hal\n");
@ -2574,8 +2574,11 @@ static void handle_fbd(enum hal_command_response cmd, void *data)
vb->timestamp = (time_usec * NSEC_PER_USEC);
msm_comm_store_input_tag(&inst->fbd_data, vb->index,
fill_buf_done->input_tag, fill_buf_done->input_tag2, inst->sid);
rc = msm_comm_store_input_tag(&inst->fbd_data, vb->index,
fill_buf_done->input_tag,
fill_buf_done->input_tag2, inst->sid);
if (rc)
s_vpr_e(inst->sid, "Failed to store input tag");
if (inst->session_type == MSM_VIDC_ENCODER) {
if (inst->max_filled_len < fill_buf_done->filled_len1)
@ -6783,120 +6786,16 @@ bool kref_get_mbuf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *mbuf)
return ret;
}
struct msm_vidc_client_data *msm_comm_store_client_data(
struct msm_vidc_inst *inst, u32 itag)
{
struct msm_vidc_client_data *data = NULL, *temp = NULL;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return NULL;
}
mutex_lock(&inst->client_data.lock);
list_for_each_entry(temp, &inst->client_data.list, list) {
if (!temp->id) {
data = temp;
break;
}
}
if (!data) {
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
s_vpr_e(inst->sid, "%s: No memory avilable", __func__);
goto exit;
}
INIT_LIST_HEAD(&data->list);
list_add_tail(&data->list, &inst->client_data.list);
}
/**
* Special handling, if etb_counter reaches to 2^32 - 1,
* then start next value from 1 not 0.
*/
if (!inst->etb_counter)
inst->etb_counter = 1;
data->id = inst->etb_counter++;
data->input_tag = itag;
exit:
mutex_unlock(&inst->client_data.lock);
return data;
}
void msm_comm_fetch_client_data(struct msm_vidc_inst *inst, bool remove,
u32 itag, u32 itag2, u32 *otag, u32 *otag2)
{
struct msm_vidc_client_data *temp, *next;
bool found_itag = false, found_itag2 = false;
if (!inst || !otag || !otag2) {
d_vpr_e("%s: invalid params %pK %x %x\n",
__func__, inst, otag, otag2);
return;
}
/**
* Some interlace clips, both BF & TF is available in single ETB buffer.
* In that case, firmware copies same input_tag value to both input_tag
* and input_tag2 at FBD.
*/
if (!itag2 || itag == itag2)
found_itag2 = true;
mutex_lock(&inst->client_data.lock);
list_for_each_entry_safe(temp, next, &inst->client_data.list, list) {
if (temp->id == itag) {
*otag = temp->input_tag;
found_itag = true;
if (remove)
temp->id = 0;
} else if (!found_itag2 && temp->id == itag2) {
*otag2 = temp->input_tag;
found_itag2 = true;
if (remove)
temp->id = 0;
}
if (found_itag && found_itag2)
break;
}
mutex_unlock(&inst->client_data.lock);
if (!found_itag || !found_itag2) {
s_vpr_e(inst->sid, "%s: client data not found - %u, %u\n",
__func__, itag, itag2);
}
}
void msm_comm_release_client_data(struct msm_vidc_inst *inst, bool remove)
{
struct msm_vidc_client_data *temp, *next;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return;
}
mutex_lock(&inst->client_data.lock);
list_for_each_entry_safe(temp, next, &inst->client_data.list, list) {
temp->id = 0;
if (remove) {
list_del(&temp->list);
kfree(temp);
}
}
mutex_unlock(&inst->client_data.lock);
}
void msm_comm_store_input_tag(struct msm_vidc_list *data_list,
int msm_comm_store_input_tag(struct msm_vidc_list *data_list,
u32 index, u32 itag, u32 itag2, u32 sid)
{
struct msm_vidc_buf_data *pdata = NULL;
bool found = false;
int rc = 0;
if (!data_list) {
s_vpr_e(sid, "%s: invalid params\n", __func__);
return;
return -EINVAL;
}
mutex_lock(&data_list->lock);
@ -6913,6 +6812,7 @@ void msm_comm_store_input_tag(struct msm_vidc_list *data_list,
pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
s_vpr_e(sid, "%s: malloc failure.\n", __func__);
rc = -ENOMEM;
goto exit;
}
pdata->index = index;
@ -6923,6 +6823,8 @@ void msm_comm_store_input_tag(struct msm_vidc_list *data_list,
exit:
mutex_unlock(&data_list->lock);
return rc;
}
int msm_comm_fetch_input_tag(struct msm_vidc_list *data_list,

View file

@ -308,16 +308,11 @@ void print_vb2_buffer(const char *str, struct msm_vidc_inst *inst,
struct vb2_buffer *vb2);
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_input_tag(struct msm_vidc_list *data_list,
int msm_comm_store_input_tag(struct msm_vidc_list *data_list,
u32 index, u32 itag, u32 itag2, u32 sid);
int msm_comm_fetch_input_tag(struct msm_vidc_list *data_list,
u32 index, u32 *itag, u32 *itag2, u32 sid);
int msm_comm_release_input_tag(struct msm_vidc_inst *inst);
struct msm_vidc_client_data *msm_comm_store_client_data(
struct msm_vidc_inst *inst, u32 itag);
void msm_comm_fetch_client_data(struct msm_vidc_inst *inst, bool remove,
u32 itag, u32 itag2, u32 *mdata, u32 *mtarget);
void msm_comm_release_client_data(struct msm_vidc_inst *inst, bool remove);
int msm_comm_qbufs_batch(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *mbuf);
int msm_comm_qbuf_decode_batch(struct msm_vidc_inst *inst,

View file

@ -204,12 +204,6 @@ struct msm_vidc_window_data {
u32 etb_count;
};
struct msm_vidc_client_data {
struct list_head list;
u32 id;
u32 input_tag;
};
struct msm_vidc_common_data {
char key[128];
int value;
@ -530,7 +524,6 @@ struct msm_vidc_inst {
enum multi_stream stream_output_mode;
struct v4l2_ctrl **ctrls;
u32 num_ctrls;
u32 etb_counter;
int bit_depth;
struct kref kref;
bool in_flush;