video: driver: new workhandler for inst events
create a new work handler and post and handle events like psc. introduce reuse concept for internal buffers. Change-Id: Ibeaabae1b5923681756e959389df00b287206fb6 Signed-off-by: Darshana Patil <darshana@codeaurora.org>
This commit is contained in:
@@ -725,56 +725,53 @@ static int msm_vdec_set_output_properties(struct msm_vidc_inst *inst)
|
||||
static int msm_vdec_get_input_internal_buffers(struct msm_vidc_inst *inst)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_vidc_core *core;
|
||||
|
||||
if (!inst || !inst->core) {
|
||||
if (!inst) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
core = inst->core;
|
||||
|
||||
/*
|
||||
* TODO: Remove the hack of sending bigger buffer sizes
|
||||
* once internal buffer calculations are finalised
|
||||
*/
|
||||
inst->buffers.bin.size = call_session_op(core, buffer_size,
|
||||
inst, MSM_VIDC_BUF_BIN) + 100000000;
|
||||
inst->buffers.comv.size = call_session_op(core, buffer_size,
|
||||
inst, MSM_VIDC_BUF_COMV) + 100000000;
|
||||
inst->buffers.non_comv.size = call_session_op(core, buffer_size,
|
||||
inst, MSM_VIDC_BUF_NON_COMV) + 100000000;
|
||||
inst->buffers.line.size = call_session_op(core, buffer_size,
|
||||
inst, MSM_VIDC_BUF_LINE) + 100000000;
|
||||
inst->buffers.persist.size = call_session_op(core, buffer_size,
|
||||
inst, MSM_VIDC_BUF_PERSIST) + 100000000;
|
||||
rc = msm_vidc_get_input_internal_buffers(inst, MSM_VIDC_BUF_BIN);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
inst->buffers.bin.min_count = call_session_op(core, min_count,
|
||||
inst, MSM_VIDC_BUF_BIN);
|
||||
inst->buffers.comv.min_count = call_session_op(core, min_count,
|
||||
inst, MSM_VIDC_BUF_COMV);
|
||||
inst->buffers.non_comv.min_count = call_session_op(core, min_count,
|
||||
inst, MSM_VIDC_BUF_NON_COMV);
|
||||
inst->buffers.line.min_count = call_session_op(core, min_count,
|
||||
inst, MSM_VIDC_BUF_LINE);
|
||||
inst->buffers.persist.min_count = call_session_op(core, min_count,
|
||||
inst, MSM_VIDC_BUF_PERSIST);
|
||||
rc = msm_vidc_get_input_internal_buffers(inst, MSM_VIDC_BUF_COMV);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
s_vpr_h(inst->sid, "internal buffer: min size\n");
|
||||
s_vpr_h(inst->sid, "bin buffer: %d %d\n",
|
||||
rc = msm_vidc_get_input_internal_buffers(inst, MSM_VIDC_BUF_NON_COMV);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = msm_vidc_get_input_internal_buffers(inst, MSM_VIDC_BUF_LINE);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = msm_vidc_get_input_internal_buffers(inst, MSM_VIDC_BUF_PERSIST);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
s_vpr_h(inst->sid, "internal buffer: min size reuse\n");
|
||||
s_vpr_h(inst->sid, "bin buffer: %d %d %d\n",
|
||||
inst->buffers.bin.min_count,
|
||||
inst->buffers.bin.size);
|
||||
s_vpr_h(inst->sid, "comv buffer: %d %d\n",
|
||||
inst->buffers.bin.size,
|
||||
inst->buffers.bin.reuse);
|
||||
s_vpr_h(inst->sid, "comv buffer: %d %d %d\n",
|
||||
inst->buffers.comv.min_count,
|
||||
inst->buffers.comv.size);
|
||||
s_vpr_h(inst->sid, "non_comv buffer: %d %d\n",
|
||||
inst->buffers.comv.size,
|
||||
inst->buffers.comv.reuse);
|
||||
s_vpr_h(inst->sid, "non_comv buffer: %d %d %d\n",
|
||||
inst->buffers.non_comv.min_count,
|
||||
inst->buffers.non_comv.size);
|
||||
s_vpr_h(inst->sid, "line buffer: %d %d\n",
|
||||
inst->buffers.non_comv.size,
|
||||
inst->buffers.non_comv.reuse);
|
||||
s_vpr_h(inst->sid, "line buffer: %d %d %d\n",
|
||||
inst->buffers.line.min_count,
|
||||
inst->buffers.line.size);
|
||||
s_vpr_h(inst->sid, "persist buffer: %d %d\n",
|
||||
inst->buffers.line.size,
|
||||
inst->buffers.line.reuse);
|
||||
s_vpr_h(inst->sid, "buffer: %d %d %d\n",
|
||||
inst->buffers.persist.min_count,
|
||||
inst->buffers.persist.size);
|
||||
inst->buffers.persist.size,
|
||||
inst->buffers.persist.reuse);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -1821,4 +1818,3 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst)
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@@ -909,6 +909,45 @@ int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_get_input_internal_buffers(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type)
|
||||
{
|
||||
u32 buf_size;
|
||||
u32 buf_count;
|
||||
struct msm_vidc_core *core;
|
||||
struct msm_vidc_buffers *buffers;
|
||||
|
||||
if (!inst || !inst->core) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
core = inst->core;
|
||||
|
||||
/*
|
||||
* TODO: Remove the hack of sending bigger buffer sizes
|
||||
* once internal buffer calculations are finalised
|
||||
*/
|
||||
buf_size = call_session_op(core, buffer_size,
|
||||
inst, buffer_type) + 100000000;
|
||||
|
||||
buf_count = call_session_op(core, min_count,
|
||||
inst, buffer_type);
|
||||
|
||||
buffers = msm_vidc_get_buffers(inst, buffer_type, __func__);
|
||||
if (!buffers)
|
||||
return -EINVAL;
|
||||
|
||||
if (buf_size <= buffers->size &&
|
||||
buf_count <= buffers->min_count) {
|
||||
buffers->reuse = true;
|
||||
} else {
|
||||
buffers->reuse = false;
|
||||
buffers->size = buf_size;
|
||||
buffers->min_count = buf_count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_vidc_create_internal_buffer(struct msm_vidc_inst *inst,
|
||||
enum msm_vidc_buffer_type buffer_type, u32 index)
|
||||
{
|
||||
@@ -1015,6 +1054,12 @@ int msm_vidc_create_internal_buffers(struct msm_vidc_inst *inst,
|
||||
if (!buffers)
|
||||
return -EINVAL;
|
||||
|
||||
if (buffers->reuse) {
|
||||
s_vpr_l(inst->sid, "%s: reuse enabled for buffer type %#x\n",
|
||||
__func__, buffer_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < buffers->min_count; i++)
|
||||
rc = msm_vidc_create_internal_buffer(inst, buffer_type, i);
|
||||
|
||||
@@ -1043,6 +1088,12 @@ int msm_vidc_queue_internal_buffers(struct msm_vidc_inst *inst,
|
||||
if (!buffers)
|
||||
return -EINVAL;
|
||||
|
||||
if (buffers->reuse) {
|
||||
s_vpr_l(inst->sid, "%s: reuse enabled for buffer type %#x\n",
|
||||
__func__, buffer_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(buffer, dummy, &buffers->list, list) {
|
||||
/* do not queue pending release buffers */
|
||||
if (buffer->flags & MSM_VIDC_ATTR_PENDING_RELEASE)
|
||||
@@ -1085,6 +1136,12 @@ int msm_vidc_release_internal_buffers(struct msm_vidc_inst *inst,
|
||||
if (!buffers)
|
||||
return -EINVAL;
|
||||
|
||||
if (buffers->reuse) {
|
||||
s_vpr_l(inst->sid, "%s: reuse enabled for buffer type %#x\n",
|
||||
__func__, buffer_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(buffer, dummy, &buffers->list, list) {
|
||||
/* do not release already pending release buffers */
|
||||
if (buffer->attr & MSM_VIDC_ATTR_PENDING_RELEASE)
|
||||
|
@@ -214,15 +214,25 @@ static int msm_vidc_initialize_core(struct msm_vidc_core *core)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
core->inst_workq = create_singlethread_workqueue("inst_workq");
|
||||
if (!core->inst_workq) {
|
||||
d_vpr_e("%s: create workq failed\n", __func__);
|
||||
destroy_workqueue(core->inst_workq);
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mutex_init(&core->lock);
|
||||
INIT_LIST_HEAD(&core->instances);
|
||||
INIT_LIST_HEAD(&core->dangling_instances);
|
||||
INIT_LIST_HEAD(&core->inst_works);
|
||||
|
||||
INIT_WORK(&core->device_work, venus_hfi_work_handler);
|
||||
INIT_DELAYED_WORK(&core->pm_work, venus_hfi_pm_work_handler);
|
||||
INIT_DELAYED_WORK(&core->fw_unload_work, msm_vidc_fw_unload_handler);
|
||||
INIT_DELAYED_WORK(&core->batch_work, msm_vidc_batch_handler);
|
||||
INIT_WORK(&core->ssr_work, msm_vidc_ssr_handler);
|
||||
INIT_DELAYED_WORK(&core->inst_work, venus_hfi_inst_work_handler);
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
|
@@ -124,8 +124,7 @@ int validate_packet(u8 *response_pkt, u8 *core_resp_pkt,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
response_limit = core_resp_pkt + core_resp_pkt_size -
|
||||
max(sizeof(struct hfi_header), sizeof(struct hfi_packet));
|
||||
response_limit = core_resp_pkt + core_resp_pkt_size;
|
||||
|
||||
if (response_pkt < core_resp_pkt || response_pkt > response_limit) {
|
||||
d_vpr_e("%s: invalid packet address\n", func);
|
||||
@@ -963,6 +962,121 @@ exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int venus_hfi_input_psc(struct msm_vidc_core *core,
|
||||
struct work_header *work_hdr)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_vidc_inst *inst;
|
||||
struct hfi_header *hdr = NULL;
|
||||
struct hfi_packet *packet;
|
||||
u8 *pkt, *temp_pkt;
|
||||
u32 hfi_cmd_type = 0;
|
||||
u32 hfi_port = 0;
|
||||
int i;
|
||||
|
||||
if (!work_hdr) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hdr = (struct hfi_header *)work_hdr->data;
|
||||
if (!hdr) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
inst = get_inst(core, hdr->session_id);
|
||||
if (!inst) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&inst->lock);
|
||||
hfi_cmd_type = 0;
|
||||
hfi_port = 0;
|
||||
pkt = (u8 *)((u8 *)hdr + sizeof(struct hfi_header));
|
||||
temp_pkt = pkt;
|
||||
|
||||
for (i = 0; i < hdr->num_packets; i++) {
|
||||
if (validate_packet(pkt, work_hdr->data,
|
||||
work_hdr->data_size, __func__)) {
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
packet = (struct hfi_packet *)pkt;
|
||||
if (packet->type > HFI_CMD_BEGIN &&
|
||||
packet->type < HFI_CMD_END) {
|
||||
if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
|
||||
s_vpr_e(inst->sid,
|
||||
"%s: invalid packet type %d in port settings change\n",
|
||||
__func__, packet->type);
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
hfi_cmd_type = packet->type;
|
||||
hfi_port = packet->port;
|
||||
rc = handle_session_command(inst, packet);
|
||||
} else if (packet->type > HFI_PROP_BEGIN &&
|
||||
packet->type < HFI_PROP_END) {
|
||||
rc = handle_session_property(inst, packet);
|
||||
} else if (packet->type > HFI_SESSION_ERROR_BEGIN &&
|
||||
packet->type < HFI_SESSION_ERROR_END) {
|
||||
rc = handle_session_error(inst, packet);
|
||||
} else if (packet->type > HFI_INFORMATION_BEGIN &&
|
||||
packet->type < HFI_INFORMATION_END) {
|
||||
rc = handle_session_info(inst, packet);
|
||||
} else {
|
||||
s_vpr_e(inst->sid, "%s: Unknown packet type: %#x\n",
|
||||
__func__, packet->type);
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
pkt += packet->size;
|
||||
}
|
||||
|
||||
if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
|
||||
if (hfi_port == HFI_PORT_BITSTREAM) {
|
||||
print_psc_properties(VIDC_HIGH, "INPUT_PSC", inst,
|
||||
inst->subcr_params[INPUT_PORT]);
|
||||
rc = msm_vdec_input_port_settings_change(inst);
|
||||
if (rc)
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
mutex_unlock(&inst->lock);
|
||||
put_inst(inst);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void venus_hfi_inst_work_handler(struct work_struct *work)
|
||||
{
|
||||
struct msm_vidc_core *core;
|
||||
struct work_header *work_hdr, *dummy = NULL;
|
||||
|
||||
core = container_of(work, struct msm_vidc_core, inst_work.work);
|
||||
if (!core) {
|
||||
d_vpr_e("%s: invalid params\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(work_hdr, dummy, &core->inst_works, list) {
|
||||
switch (work_hdr->type) {
|
||||
case MSM_VIDC_INST_WORK_PSC:
|
||||
venus_hfi_input_psc(core, work_hdr);
|
||||
break;
|
||||
default:
|
||||
d_vpr_e("%s(): invalid work type: %d\n", __func__,
|
||||
work_hdr->type);
|
||||
break;
|
||||
}
|
||||
list_del(&work_hdr->list);
|
||||
kfree(work_hdr->data);
|
||||
kfree(work_hdr);
|
||||
}
|
||||
}
|
||||
|
||||
static int handle_session_response(struct msm_vidc_core *core,
|
||||
struct hfi_header *hdr)
|
||||
{
|
||||
@@ -994,6 +1108,26 @@ static int handle_session_response(struct msm_vidc_core *core,
|
||||
packet = (struct hfi_packet *)pkt;
|
||||
if (packet->type > HFI_CMD_BEGIN &&
|
||||
packet->type < HFI_CMD_END) {
|
||||
if (packet->type == HFI_CMD_SETTINGS_CHANGE &&
|
||||
packet->port == HFI_PORT_BITSTREAM) {
|
||||
struct work_header *work;
|
||||
|
||||
work = kzalloc(sizeof(struct work_header), GFP_KERNEL);
|
||||
INIT_LIST_HEAD(&work->list);
|
||||
work->type = MSM_VIDC_INST_WORK_PSC;
|
||||
work->session_id = hdr->session_id;
|
||||
work->data_size = hdr->size;
|
||||
work->data = kzalloc(hdr->size, GFP_KERNEL);
|
||||
if (!work->data) {
|
||||
rc= -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
memcpy(work->data, (void *)hdr, hdr->size);
|
||||
list_add_tail(&work->list, &core->inst_works);
|
||||
queue_delayed_work(core->inst_workq,
|
||||
&core->inst_work, msecs_to_jiffies(0));
|
||||
goto exit;
|
||||
}
|
||||
if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
|
||||
s_vpr_e(inst->sid,
|
||||
"%s: invalid packet type %d in port settings change\n",
|
||||
@@ -1029,18 +1163,15 @@ static int handle_session_response(struct msm_vidc_core *core,
|
||||
}
|
||||
|
||||
if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {
|
||||
if (hfi_port == HFI_PORT_BITSTREAM) {
|
||||
print_psc_properties(VIDC_HIGH, "INPUT_PSC", inst,
|
||||
inst->subcr_params[INPUT_PORT]);
|
||||
rc = msm_vdec_input_port_settings_change(inst);
|
||||
if (rc)
|
||||
goto exit;
|
||||
} else if (hfi_port == HFI_PORT_RAW) {
|
||||
if (hfi_port == HFI_PORT_RAW) {
|
||||
print_psc_properties(VIDC_HIGH, "OUTPUT_PSC", inst,
|
||||
inst->subcr_params[OUTPUT_PORT]);
|
||||
rc = msm_vdec_output_port_settings_change(inst);
|
||||
if (rc)
|
||||
goto exit;
|
||||
} else {
|
||||
s_vpr_e(inst->sid, "%s: invalid port type: %#x\n",
|
||||
__func__, hfi_port);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user