diff --git a/driver/vidc/inc/msm_vdec.h b/driver/vidc/inc/msm_vdec.h index cd9c631a11..c7df1df6cd 100644 --- a/driver/vidc/inc/msm_vdec.h +++ b/driver/vidc/inc/msm_vdec.h @@ -9,19 +9,18 @@ #include "msm_vidc_core.h" #include "msm_vidc_inst.h" -int msm_vdec_stop_input(struct msm_vidc_inst *inst); -int msm_vdec_start_input(struct msm_vidc_inst *inst); -int msm_vdec_stop_output(struct msm_vidc_inst *inst); -int msm_vdec_start_output(struct msm_vidc_inst *inst); +int msm_vdec_streamoff_input(struct msm_vidc_inst *inst); +int msm_vdec_streamon_input(struct msm_vidc_inst *inst); +int msm_vdec_streamoff_output(struct msm_vidc_inst *inst); +int msm_vdec_streamon_output(struct msm_vidc_inst *inst); int msm_vdec_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2); int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f); int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f); int msm_vdec_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f); int msm_vdec_inst_init(struct msm_vidc_inst *inst); +int msm_vdec_inst_deinit(struct msm_vidc_inst *inst); int msm_vdec_input_port_settings_change(struct msm_vidc_inst *inst); int msm_vdec_output_port_settings_change(struct msm_vidc_inst *inst); int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd); -int msm_vdec_subscribe_port_settings_change(struct msm_vidc_inst *inst, - enum msm_vidc_port_type port); #endif // _MSM_VDEC_H_ \ No newline at end of file diff --git a/driver/vidc/inc/msm_venc.h b/driver/vidc/inc/msm_venc.h index 05d2794448..04a55d7677 100644 --- a/driver/vidc/inc/msm_venc.h +++ b/driver/vidc/inc/msm_venc.h @@ -9,14 +9,15 @@ #include "msm_vidc_core.h" #include "msm_vidc_inst.h" -int msm_venc_stop_input(struct msm_vidc_inst *inst); -int msm_venc_start_input(struct msm_vidc_inst *inst); -int msm_venc_stop_output(struct msm_vidc_inst *inst); -int msm_venc_start_output(struct msm_vidc_inst *inst); +int msm_venc_streamoff_input(struct msm_vidc_inst *inst); +int msm_venc_streamon_input(struct msm_vidc_inst *inst); +int msm_venc_streamoff_output(struct msm_vidc_inst *inst); +int msm_venc_streamon_output(struct msm_vidc_inst *inst); int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd); int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f); int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f); int msm_venc_enum_fmt(struct msm_vidc_inst *inst, struct v4l2_fmtdesc *f); int msm_venc_inst_init(struct msm_vidc_inst *inst); +int msm_venc_inst_deinit(struct msm_vidc_inst *inst); #endif // _MSM_VENC_H_ \ No newline at end of file diff --git a/driver/vidc/inc/msm_vidc_core.h b/driver/vidc/inc/msm_vidc_core.h index 6f9eb84c44..140b57985b 100644 --- a/driver/vidc/inc/msm_vidc_core.h +++ b/driver/vidc/inc/msm_vidc_core.h @@ -60,18 +60,6 @@ enum msm_vidc_core_state { MSM_VIDC_CORE_ERROR = 2, }; -enum work_type { - MSM_VIDC_INST_WORK_PSC = 1, -}; - -struct work_header { - void *data; - struct list_head list; - enum work_type type; - u32 session_id; - u32 data_size; -}; - struct msm_vidc_core { struct platform_device *pdev; struct msm_video_device vdev[2]; @@ -120,9 +108,6 @@ struct msm_vidc_core { u32 header_id; u32 packet_id; struct completion init_done; - struct list_head inst_works; /* list of struct work_header */ - struct delayed_work inst_work; - struct workqueue_struct *inst_workq; }; #endif // _MSM_VIDC_CORE_H_ diff --git a/driver/vidc/inc/msm_vidc_driver.h b/driver/vidc/inc/msm_vidc_driver.h index 64fcd6cb9c..ec9159732a 100644 --- a/driver/vidc/inc/msm_vidc_driver.h +++ b/driver/vidc/inc/msm_vidc_driver.h @@ -177,6 +177,7 @@ u32 v4l2_colorformat_from_driver(enum msm_vidc_colorformat_type colorformat, const char *func); int v4l2_type_to_driver_port(struct msm_vidc_inst *inst, u32 type, const char *func); +const char *state_name(enum msm_vidc_inst_state state); int msm_vidc_change_inst_state(struct msm_vidc_inst *inst, enum msm_vidc_inst_state state, const char *func); int msm_vidc_get_input_internal_buffers(struct msm_vidc_inst *inst, @@ -193,13 +194,14 @@ int msm_vidc_remove_session(struct msm_vidc_inst *inst); int msm_vidc_add_session(struct msm_vidc_inst *inst); int msm_vidc_session_open(struct msm_vidc_inst *inst); int msm_vidc_session_set_codec(struct msm_vidc_inst *inst); -int msm_vidc_session_start(struct msm_vidc_inst* inst, +int msm_vidc_session_streamon(struct msm_vidc_inst *inst, enum msm_vidc_port_type port); -int msm_vidc_session_stop(struct msm_vidc_inst *inst, +int msm_vidc_session_streamoff(struct msm_vidc_inst *inst, enum msm_vidc_port_type port); int msm_vidc_session_close(struct msm_vidc_inst *inst); int msm_vidc_get_inst_capability(struct msm_vidc_inst *inst); int msm_vidc_core_init(struct msm_vidc_core *core); +int msm_vidc_core_deinit(struct msm_vidc_core *core); int msm_vidc_smmu_fault_handler(struct iommu_domain *domain, struct device *dev, unsigned long iova, int flags, void *data); int msm_vidc_trigger_ssr(struct msm_vidc_core *core, @@ -208,8 +210,10 @@ void msm_vidc_ssr_handler(struct work_struct *work); void msm_vidc_pm_work_handler(struct work_struct *work); void msm_vidc_fw_unload_handler(struct work_struct *work); void msm_vidc_batch_handler(struct work_struct *work); -int msm_vidc_setup_event_queue(struct msm_vidc_inst *inst); +int msm_vidc_event_queue_init(struct msm_vidc_inst *inst); +int msm_vidc_event_queue_deinit(struct msm_vidc_inst *inst); int msm_vidc_vb2_queue_init(struct msm_vidc_inst *inst); +int msm_vidc_vb2_queue_deinit(struct msm_vidc_inst *inst); int msm_vidc_get_control(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl); u32 msm_vidc_get_buffer_region(struct msm_vidc_inst *inst, enum msm_vidc_buffer_type buffer_type, const char *func); @@ -231,14 +235,33 @@ int msm_vidc_put_driver_buf(struct msm_vidc_inst *inst, int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct vb2_buffer *vb2); int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst, struct msm_vidc_buffer *buffer); +void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst); struct msm_vidc_buffer *get_meta_buffer(struct msm_vidc_inst *inst, struct msm_vidc_buffer *vbuf); +struct msm_vidc_inst *get_inst_ref(struct msm_vidc_core *core, + struct msm_vidc_inst *instance); struct msm_vidc_inst *get_inst(struct msm_vidc_core *core, u32 session_id); void put_inst(struct msm_vidc_inst *inst); -int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst* inst); -int msm_vidc_get_fps(struct msm_vidc_inst* inst); -int msm_vidc_num_queued_bufs(struct msm_vidc_inst* inst, u32 type); +bool msm_vidc_allow_s_fmt(struct msm_vidc_inst *inst, u32 type); +bool msm_vidc_allow_s_ctrl(struct msm_vidc_inst *inst, u32 id); +bool msm_vidc_allow_reqbufs(struct msm_vidc_inst *inst, u32 type); +bool msm_vidc_allow_stop(struct msm_vidc_inst *inst); +bool msm_vidc_allow_start(struct msm_vidc_inst *inst); +bool msm_vidc_allow_streamon(struct msm_vidc_inst *inst, u32 type); +bool msm_vidc_allow_streamoff(struct msm_vidc_inst *inst, u32 type); +bool msm_vidc_allow_qbuf(struct msm_vidc_inst *inst); +int msm_vidc_allow_input_psc(struct msm_vidc_inst *inst); +bool msm_vidc_allow_last_flag(struct msm_vidc_inst *inst); +int msm_vidc_state_change_streamon(struct msm_vidc_inst *inst, u32 type); +int msm_vidc_state_change_streamoff(struct msm_vidc_inst *inst, u32 type); +int msm_vidc_state_change_stop(struct msm_vidc_inst *inst); +int msm_vidc_state_change_start(struct msm_vidc_inst *inst); +int msm_vidc_state_change_input_psc(struct msm_vidc_inst *inst); +int msm_vidc_state_change_last_flag(struct msm_vidc_inst *inst); +int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst *inst); +int msm_vidc_get_fps(struct msm_vidc_inst *inst); +int msm_vidc_num_queued_bufs(struct msm_vidc_inst *inst, u32 type); void core_lock(struct msm_vidc_core *core, const char *function); void core_unlock(struct msm_vidc_core *core, const char *function); void inst_lock(struct msm_vidc_inst *inst, const char *function); diff --git a/driver/vidc/inc/msm_vidc_inst.h b/driver/vidc/inc/msm_vidc_inst.h index 350bf3c4c6..f7d6d9abd4 100644 --- a/driver/vidc/inc/msm_vidc_inst.h +++ b/driver/vidc/inc/msm_vidc_inst.h @@ -34,6 +34,7 @@ struct msm_vidc_allocations_info { struct msm_vidc_allocations line; struct msm_vidc_allocations dpb; struct msm_vidc_allocations persist; + struct msm_vidc_allocations vpss; }; struct msm_vidc_mappings_info { @@ -48,6 +49,7 @@ struct msm_vidc_mappings_info { struct msm_vidc_mappings line; struct msm_vidc_mappings dpb; struct msm_vidc_mappings persist; + struct msm_vidc_mappings vpss; }; struct msm_vidc_buffers_info { @@ -62,6 +64,7 @@ struct msm_vidc_buffers_info { struct msm_vidc_buffers line; struct msm_vidc_buffers dpb; struct msm_vidc_buffers persist; + struct msm_vidc_buffers vpss; }; enum msm_vidc_inst_state { @@ -119,6 +122,9 @@ struct msm_vidc_inst { struct msm_vidc_decode_batch decode_batch; struct msm_vidc_decode_vpp_delay decode_vpp_delay; struct msm_vidc_session_idle session_idle; + struct delayed_work input_psc_work; + struct workqueue_struct *input_psc_workq; + struct list_head input_psc_works; /* list of struct input_psc_work */ struct list_head input_ts; struct list_head enc_input_crs; struct list_head decode_bitrate_data; diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index 5b61e2b880..a3aa5442c5 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/driver/vidc/inc/msm_vidc_internal.h @@ -708,6 +708,12 @@ struct msm_vidc_buffers { bool reuse; }; +struct input_psc_work { + struct list_head list; + void *data; + u32 data_size; +}; + struct msm_vidc_ssr { bool trigger; enum msm_vidc_ssr_trigger_type ssr_type; diff --git a/driver/vidc/inc/msm_vidc_vb2.h b/driver/vidc/inc/msm_vidc_vb2.h index 2611d5f30a..c924c1dd4b 100644 --- a/driver/vidc/inc/msm_vidc_vb2.h +++ b/driver/vidc/inc/msm_vidc_vb2.h @@ -8,6 +8,10 @@ #include #include +#include "msm_vidc_inst.h" + +struct vb2_queue *msm_vidc_get_vb2q(struct msm_vidc_inst *inst, + u32 type, const char *func); /* vb2_mem_ops */ void *msm_vb2_get_userptr(struct device *dev, unsigned long vaddr, diff --git a/driver/vidc/inc/venus_hfi.h b/driver/vidc/inc/venus_hfi.h index 44393c75be..57a0dbcea5 100644 --- a/driver/vidc/inc/venus_hfi.h +++ b/driver/vidc/inc/venus_hfi.h @@ -64,14 +64,13 @@ int venus_hfi_session_close(struct msm_vidc_inst *inst); int venus_hfi_session_open(struct msm_vidc_inst *inst); int venus_hfi_session_set_codec(struct msm_vidc_inst *inst); int venus_hfi_core_init(struct msm_vidc_core *core); -int venus_hfi_core_release(struct msm_vidc_core *core); +int venus_hfi_core_deinit(struct msm_vidc_core *core); int venus_hfi_suspend(struct msm_vidc_core *core); int venus_hfi_scale_clocks(struct msm_vidc_inst* inst, u64 freq); int venus_hfi_scale_buses(struct msm_vidc_inst* inst, u64 bw_ddr, u64 bw_llcc); void venus_hfi_work_handler(struct work_struct *work); void venus_hfi_pm_work_handler(struct work_struct *work); -void venus_hfi_inst_work_handler(struct work_struct *work); irqreturn_t venus_hfi_isr(int irq, void *data); void __write_register(struct msm_vidc_core *core, diff --git a/driver/vidc/inc/venus_hfi_response.h b/driver/vidc/inc/venus_hfi_response.h index c48a92f0b3..57110372c3 100644 --- a/driver/vidc/inc/venus_hfi_response.h +++ b/driver/vidc/inc/venus_hfi_response.h @@ -14,5 +14,8 @@ bool is_valid_port(struct msm_vidc_inst *inst, u32 port, const char *func); bool is_valid_hfi_buffer_type(struct msm_vidc_inst *inst, u32 buffer_type, const char *func); +void handle_session_input_psc_work_handler(struct work_struct *work); +int handle_session_input_psc(struct msm_vidc_inst *inst, + struct input_psc_work *psc_work); #endif // __VENUS_HFI_RESPONSE_H__ diff --git a/driver/vidc/src/msm_vdec.c b/driver/vidc/src/msm_vdec.c index 3c39f81dbb..bff4c0f954 100644 --- a/driver/vidc/src/msm_vdec.c +++ b/driver/vidc/src/msm_vdec.c @@ -1158,7 +1158,7 @@ int msm_vdec_output_port_settings_change(struct msm_vidc_inst *inst) return 0; } -int msm_vdec_stop_input(struct msm_vidc_inst *inst) +int msm_vdec_streamoff_input(struct msm_vidc_inst *inst) { int rc = 0; @@ -1167,31 +1167,28 @@ int msm_vdec_stop_input(struct msm_vidc_inst *inst) return -EINVAL; } - rc = msm_vidc_session_stop(inst, INPUT_PORT); + rc = msm_vidc_session_streamoff(inst, INPUT_PORT); if (rc) return rc; return 0; } -int msm_vdec_start_input(struct msm_vidc_inst *inst) +int msm_vdec_streamon_input(struct msm_vidc_inst *inst) { int rc = 0; - struct msm_vidc_core *core; if (!inst || !inst->core) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } - core = inst->core; - s_vpr_h(inst->sid, "%s()\n", __func__); if (is_input_meta_enabled(inst) && !inst->vb2q[INPUT_META_PORT].streaming) { s_vpr_e(inst->sid, "%s: Meta port must be streamed on before data port\n", __func__); - goto error; + return -EINVAL; } //rc = msm_vidc_check_session_supported(inst); @@ -1244,20 +1241,19 @@ int msm_vdec_start_input(struct msm_vidc_inst *inst) if (rc) return rc; - rc = msm_vidc_session_start(inst, INPUT_PORT); + rc = msm_vidc_session_streamon(inst, INPUT_PORT); if (rc) goto error; - s_vpr_h(inst->sid, "%s: done\n", __func__); return 0; error: s_vpr_e(inst->sid, "%s: failed\n", __func__); - msm_vdec_stop_input(inst); + msm_vdec_streamoff_input(inst); return rc; } -int msm_vdec_stop_output(struct msm_vidc_inst *inst) +int msm_vdec_streamoff_output(struct msm_vidc_inst *inst) { int rc = 0; @@ -1266,7 +1262,7 @@ int msm_vdec_stop_output(struct msm_vidc_inst *inst) return -EINVAL; } - rc = msm_vidc_session_stop(inst, OUTPUT_PORT); + rc = msm_vidc_session_streamoff(inst, OUTPUT_PORT); if (rc) return rc; @@ -1385,11 +1381,10 @@ static int msm_vdec_subscribe_output_port_settings_change(struct msm_vidc_inst * return rc; } -int msm_vdec_start_output(struct msm_vidc_inst *inst) +int msm_vdec_streamon_output(struct msm_vidc_inst *inst) { int rc = 0; - d_vpr_h("%s()\n", __func__); if (!inst || !inst->core) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; @@ -1400,7 +1395,7 @@ int msm_vdec_start_output(struct msm_vidc_inst *inst) s_vpr_e(inst->sid, "%s: Meta port must be streamed on before data port\n", __func__); - goto error; + return -EINVAL; } rc = msm_vdec_set_output_properties(inst); @@ -1409,26 +1404,27 @@ int msm_vdec_start_output(struct msm_vidc_inst *inst) if (!inst->opsc_properties_set) { memcpy(&inst->subcr_params[OUTPUT_PORT], - &inst->subcr_params[INPUT_PORT], sizeof(inst->subcr_params[INPUT_PORT])); + &inst->subcr_params[INPUT_PORT], + sizeof(inst->subcr_params[INPUT_PORT])); rc = msm_vdec_subscribe_output_port_settings_change(inst, OUTPUT_PORT); if (rc) - return rc; + goto error; inst->opsc_properties_set = true; } rc = msm_vdec_subscribe_metadata(inst, OUTPUT_PORT); if (rc) - return rc; + goto error; - rc = msm_vidc_session_start(inst, OUTPUT_PORT); + rc = msm_vidc_session_streamon(inst, OUTPUT_PORT); if (rc) goto error; - d_vpr_h("%s: done\n", __func__); return 0; error: - msm_vdec_stop_output(inst); + s_vpr_e(inst->sid, "%s: failed\n", __func__); + msm_vdec_streamoff_output(inst); return rc; } @@ -1468,6 +1464,8 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd) } if (cmd == V4L2_DEC_CMD_STOP) { + if (!msm_vidc_allow_stop(inst)) + return -EBUSY; rc = venus_hfi_session_command(inst, HFI_CMD_DRAIN, INPUT_PORT, @@ -1476,6 +1474,23 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd) 0); if (rc) return rc; + rc = msm_vidc_state_change_stop(inst); + if (rc) + return rc; + } else if (cmd == V4L2_DEC_CMD_START) { + if (!msm_vidc_allow_start(inst)) + return -EBUSY; + rc = msm_vidc_state_change_start(inst); + if (rc) + return rc; + rc = venus_hfi_session_command(inst, + HFI_CMD_RESUME, + OUTPUT_PORT, + HFI_PAYLOAD_NONE, + NULL, + 0); + if (rc) + return rc; } else { d_vpr_e("%s: unknown cmd %d\n", __func__, cmd); return -EINVAL; @@ -1490,23 +1505,13 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) struct msm_vidc_core *core; struct v4l2_format *fmt; - d_vpr_h("%s()\n", __func__); if (!inst || !inst->core) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } core = inst->core; - if (inst->state == MSM_VIDC_START) { - d_vpr_e("%s: invalid state %d\n", __func__, inst->state); - return -EINVAL; - } - if (f->type == INPUT_MPLANE) { - if (inst->state == MSM_VIDC_START_INPUT) { - d_vpr_e("%s: invalid state %d\n", __func__, inst->state); - return -EINVAL; - } if (inst->fmts[INPUT_PORT].fmt.pix_mp.pixelformat != f->fmt.pix_mp.pixelformat) { s_vpr_e(inst->sid, @@ -1562,10 +1567,6 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) //msm_vidc_update_batching(inst); } else if (f->type == INPUT_META_PLANE) { - if (inst->state == MSM_VIDC_START_INPUT) { - d_vpr_e("%s: invalid state %d\n", __func__, inst->state); - return -EINVAL; - } fmt = &inst->fmts[INPUT_META_PORT]; fmt->type = INPUT_META_PLANE; fmt->fmt.meta.dataformat = V4L2_META_FMT_VIDC; @@ -1592,10 +1593,6 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) inst->buffers.input_meta.min_count, inst->buffers.input_meta.extra_count); } else if (f->type == OUTPUT_MPLANE) { - if (inst->state == MSM_VIDC_START_OUTPUT) { - d_vpr_e("%s: invalid state %d\n", __func__, inst->state); - return -EINVAL; - } fmt = &inst->fmts[OUTPUT_PORT]; fmt->type = OUTPUT_MPLANE; fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat; @@ -1637,10 +1634,6 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) inst->buffers.output.min_count, inst->buffers.output.extra_count); } else if (f->type == OUTPUT_META_PLANE) { - if (inst->state == MSM_VIDC_START_OUTPUT) { - d_vpr_e("%s: invalid state %d\n", __func__, inst->state); - return -EINVAL; - } fmt = &inst->fmts[OUTPUT_META_PORT]; fmt->type = OUTPUT_META_PLANE; fmt->fmt.meta.dataformat = V4L2_META_FMT_VIDC; @@ -1681,7 +1674,6 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) int rc = 0; int port; - d_vpr_h("%s()\n", __func__); if (!inst) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; @@ -1767,7 +1759,6 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst) struct msm_vidc_core *core; struct v4l2_format *f; - d_vpr_h("%s()\n", __func__); if (!inst || !inst->core) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; @@ -1850,3 +1841,16 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst) return rc; } + +int msm_vdec_inst_deinit(struct msm_vidc_inst *inst) +{ + int rc = 0; + + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + rc = msm_vidc_ctrl_deinit(inst); + + return rc; +} diff --git a/driver/vidc/src/msm_venc.c b/driver/vidc/src/msm_venc.c index b071853345..94db5ab018 100644 --- a/driver/vidc/src/msm_venc.c +++ b/driver/vidc/src/msm_venc.c @@ -701,7 +701,7 @@ static int msm_venc_metadata_subscription(struct msm_vidc_inst *inst, return rc; } -int msm_venc_stop_input(struct msm_vidc_inst *inst) +int msm_venc_streamoff_input(struct msm_vidc_inst *inst) { int rc = 0; @@ -710,31 +710,28 @@ int msm_venc_stop_input(struct msm_vidc_inst *inst) return -EINVAL; } - rc = msm_vidc_session_stop(inst, INPUT_PORT); + rc = msm_vidc_session_streamoff(inst, INPUT_PORT); if (rc) return rc; return 0; } -int msm_venc_start_input(struct msm_vidc_inst *inst) +int msm_venc_streamon_input(struct msm_vidc_inst *inst) { int rc = 0; - struct msm_vidc_core *core; if (!inst || !inst->core) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } - core = inst->core; - s_vpr_h(inst->sid, "%s()\n", __func__); if (is_input_meta_enabled(inst) && !inst->vb2q[INPUT_META_PORT].streaming) { s_vpr_e(inst->sid, "%s: Meta port must be streamed on before data port\n", __func__); - goto error; + return -EINVAL; } //rc = msm_vidc_check_session_supported(inst); @@ -780,16 +777,15 @@ int msm_venc_start_input(struct msm_vidc_inst *inst) if (rc) return rc; - rc = msm_vidc_session_start(inst, INPUT_PORT); + rc = msm_vidc_session_streamon(inst, INPUT_PORT); if (rc) goto error; - s_vpr_h(inst->sid, "%s: done\n", __func__); return 0; error: s_vpr_e(inst->sid, "%s: failed\n", __func__); - msm_venc_stop_input(inst); + msm_venc_streamoff_input(inst); return rc; } @@ -803,6 +799,8 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd) } if (cmd == V4L2_ENC_CMD_STOP) { + if (!msm_vidc_allow_stop(inst)) + return -EBUSY; rc = venus_hfi_session_command(inst, HFI_CMD_DRAIN, INPUT_PORT, @@ -811,6 +809,17 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd) 0); if (rc) return rc; + } else if (cmd == V4L2_ENC_CMD_START) { + if (!msm_vidc_allow_start(inst)) + return -EBUSY; + rc = venus_hfi_session_command(inst, + HFI_CMD_RESUME, + INPUT_PORT, + HFI_PAYLOAD_NONE, + NULL, + 0); + if (rc) + return rc; } else { d_vpr_e("%s: unknown cmd %d\n", __func__, cmd); return -EINVAL; @@ -818,7 +827,7 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd) return 0; } -int msm_venc_stop_output(struct msm_vidc_inst *inst) +int msm_venc_streamoff_output(struct msm_vidc_inst *inst) { int rc = 0; @@ -827,18 +836,17 @@ int msm_venc_stop_output(struct msm_vidc_inst *inst) return -EINVAL; } - rc = msm_vidc_session_stop(inst, OUTPUT_PORT); + rc = msm_vidc_session_streamoff(inst, OUTPUT_PORT); if (rc) return rc; return 0; } -int msm_venc_start_output(struct msm_vidc_inst *inst) +int msm_venc_streamon_output(struct msm_vidc_inst *inst) { int rc = 0; - d_vpr_h("%s()\n", __func__); if (!inst || !inst->core) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; @@ -849,7 +857,7 @@ int msm_venc_start_output(struct msm_vidc_inst *inst) s_vpr_e(inst->sid, "%s: Meta port must be streamed on before data port\n", __func__); - goto error; + return -EINVAL; } rc = msm_venc_set_output_properties(inst); @@ -858,11 +866,11 @@ int msm_venc_start_output(struct msm_vidc_inst *inst) rc = msm_vidc_adjust_v4l2_properties(inst); if (rc) - return -EINVAL; + goto error; rc = msm_vidc_set_v4l2_properties(inst); if (rc) - return -EINVAL; + goto error; rc = msm_venc_set_internal_properties(inst); if (rc) @@ -870,21 +878,21 @@ int msm_venc_start_output(struct msm_vidc_inst *inst) rc = msm_venc_property_subscription(inst, OUTPUT_PORT); if (rc) - return rc; + goto error; rc = msm_venc_metadata_subscription(inst, OUTPUT_PORT); if (rc) - return rc; + goto error; - rc = msm_vidc_session_start(inst, OUTPUT_PORT); + rc = msm_vidc_session_streamon(inst, OUTPUT_PORT); if (rc) goto error; - d_vpr_h("%s: done\n", __func__); return 0; error: - msm_venc_stop_output(inst); + s_vpr_e(inst->sid, "%s: failed\n", __func__); + msm_venc_streamoff_output(inst); return rc; } @@ -894,23 +902,13 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) struct msm_vidc_core *core; struct v4l2_format *fmt; - d_vpr_h("%s()\n", __func__); if (!inst || !inst->core) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } core = inst->core; - if (inst->state == MSM_VIDC_START) { - d_vpr_e("%s: invalid state %d\n", __func__, inst->state); - return -EINVAL; - } - if (f->type == INPUT_MPLANE) { - if (inst->state == MSM_VIDC_START_INPUT) { - d_vpr_e("%s: invalid state %d\n", __func__, inst->state); - return -EINVAL; - } fmt = &inst->fmts[INPUT_PORT]; fmt->type = INPUT_MPLANE; fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat; @@ -959,10 +957,6 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) //msm_vidc_update_batching(inst); } else if (f->type == INPUT_META_PLANE) { - if (inst->state == MSM_VIDC_START_INPUT) { - d_vpr_e("%s: invalid state %d\n", __func__, inst->state); - return -EINVAL; - } fmt = &inst->fmts[INPUT_META_PORT]; fmt->type = INPUT_META_PLANE; fmt->fmt.meta.dataformat = V4L2_META_FMT_VIDC; @@ -989,10 +983,6 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) inst->buffers.input_meta.min_count, inst->buffers.input_meta.extra_count); } else if (f->type == OUTPUT_MPLANE) { - if (inst->state == MSM_VIDC_START_OUTPUT) { - d_vpr_e("%s: invalid state %d\n", __func__, inst->state); - return -EINVAL; - } fmt = &inst->fmts[OUTPUT_PORT]; if (fmt->fmt.pix_mp.pixelformat != f->fmt.pix_mp.pixelformat) { s_vpr_e(inst->sid, @@ -1053,10 +1043,6 @@ int msm_venc_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) inst->buffers.output.min_count, inst->buffers.output.extra_count); } else if (f->type == OUTPUT_META_PLANE) { - if (inst->state == MSM_VIDC_START_OUTPUT) { - d_vpr_e("%s: invalid state %d\n", __func__, inst->state); - return -EINVAL; - } fmt = &inst->fmts[OUTPUT_META_PORT]; fmt->type = OUTPUT_META_PLANE; fmt->fmt.meta.dataformat = V4L2_META_FMT_VIDC; @@ -1097,7 +1083,6 @@ int msm_venc_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f) int rc = 0; int port; - d_vpr_h("%s()\n", __func__); if (!inst) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; @@ -1265,3 +1250,16 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst) return rc; } + +int msm_venc_inst_deinit(struct msm_vidc_inst *inst) +{ + int rc = 0; + + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + rc = msm_vidc_ctrl_deinit(inst); + + return rc; +} diff --git a/driver/vidc/src/msm_vidc.c b/driver/vidc/src/msm_vidc.c index 36899dfea4..7e964544a6 100644 --- a/driver/vidc/src/msm_vidc.c +++ b/driver/vidc/src/msm_vidc.c @@ -15,6 +15,7 @@ #include "msm_vidc_debug.h" #include "msm_vidc_control.h" #include "msm_vidc_power.h" +#include "venus_hfi_response.h" #define MSM_VIDC_DRV_NAME "msm_vidc_driver" /* kernel/msm-4.19 */ @@ -68,6 +69,10 @@ int msm_vidc_poll(void *instance, struct file *filp, d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } + if (inst->state == MSM_VIDC_ERROR) { + s_vpr_e(inst->sid, "%s: inst in error state\n", __func__); + return -EINVAL; + } poll_wait(filp, &inst->event_handler.wait, wait); poll_wait(filp, &inst->vb2q[INPUT_META_PORT].done_wq, wait); @@ -216,24 +221,8 @@ int msm_vidc_s_fmt(void *instance, struct v4l2_format *f) return -EINVAL; } - if (f->type == INPUT_MPLANE) { - if (inst->state != MSM_VIDC_OPEN && - inst->state != MSM_VIDC_START_OUTPUT) { - s_vpr_e(inst->sid, - "%s: s_fmt(%d) not allowed in %d state\n", - __func__, f->type, inst->state); - return -EINVAL; - } - } else if (f->type == OUTPUT_MPLANE) { - if (inst->state != MSM_VIDC_OPEN && - inst->state != MSM_VIDC_START_INPUT && - inst->state != MSM_VIDC_DRAIN_START_INPUT) { - s_vpr_e(inst->sid, - "%s: s_fmt(%d) not allowed in %d state\n", - __func__, f->type, inst->state); - return -EINVAL; - } - } + if (!msm_vidc_allow_s_fmt(inst, f->type)) + return -EBUSY; if (inst->domain == MSM_VIDC_DECODER) rc = msm_vdec_s_fmt(inst, f); @@ -261,8 +250,18 @@ int msm_vidc_g_fmt(void *instance, struct v4l2_format *f) rc = msm_vdec_g_fmt(inst, f); if (inst->domain == MSM_VIDC_ENCODER) rc = msm_venc_g_fmt(inst, f); + if (rc) + return rc; - return rc; + if (f->type == INPUT_MPLANE || f->type == OUTPUT_MPLANE) + s_vpr_h(inst->sid, + "%s: type %d format %#x width %d height %d size %d\n", + __func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, + f->fmt.pix_mp.height, f->fmt.pix_mp.plane_fmt[0].sizeimage); + else if (f->type == INPUT_META_PLANE || f->type == OUTPUT_META_PLANE) + s_vpr_h(inst->sid, "%s: meta type %d size %d\n", + __func__, f->type, f->fmt.meta.buffersize); + return 0; } EXPORT_SYMBOL(msm_vidc_g_fmt); @@ -273,6 +272,9 @@ int msm_vidc_s_ctrl(void *instance, struct v4l2_control *control) if (!inst || !control) return -EINVAL; + if (!msm_vidc_allow_s_ctrl(inst, control->id)) + return -EBUSY; + return v4l2_s_ctrl(NULL, &inst->ctrl_handler, control); } EXPORT_SYMBOL(msm_vidc_s_ctrl); @@ -316,25 +318,9 @@ int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b) mutex_lock(&inst->lock); - if (b->type == INPUT_MPLANE) { - if (inst->state != MSM_VIDC_OPEN && - inst->state != MSM_VIDC_START_OUTPUT) { - s_vpr_e(inst->sid, - "%s: reqbufs(%d) not allowed in %d state\n", - __func__, b->type, inst->state); - rc = -EINVAL; - goto unlock; - } - } else if (b->type == OUTPUT_MPLANE) { - if (inst->state != MSM_VIDC_OPEN && - inst->state != MSM_VIDC_START_INPUT && - inst->state != MSM_VIDC_DRAIN_START_INPUT) { - s_vpr_e(inst->sid, - "%s: reqbufs(%d) not allowed in %d state\n", - __func__, b->type, inst->state); - rc = -EINVAL; - goto unlock; - } + if (!msm_vidc_allow_reqbufs(inst, b->type)) { + rc = -EBUSY; + goto unlock; } port = v4l2_type_to_driver_port(inst, b->type, __func__); @@ -370,22 +356,13 @@ int msm_vidc_qbuf(void *instance, struct media_device *mdev, mutex_lock(&inst->lock); - if (inst->state == MSM_VIDC_ERROR) { - s_vpr_e(inst->sid, "%s: error state\n", __func__); - rc = -EINVAL; + if (!msm_vidc_allow_qbuf(inst)) { + rc = -EBUSY; goto unlock; } - if (b->type == INPUT_MPLANE) { - q = &inst->vb2q[INPUT_PORT]; - } else if (b->type == OUTPUT_MPLANE) { - q = &inst->vb2q[OUTPUT_PORT]; - } else if (b->type == INPUT_META_PLANE) { - q = &inst->vb2q[INPUT_META_PORT]; - } else if (b->type == OUTPUT_META_PLANE) { - q = &inst->vb2q[OUTPUT_META_PORT]; - } else { - s_vpr_e(inst->sid, "%s: invalid buffer type %d\n", - __func__, b->type); + + q = msm_vidc_get_vb2q(inst, b->type, __func__); + if (!q) { rc = -EINVAL; goto unlock; } @@ -412,17 +389,9 @@ int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b) } mutex_lock(&inst->lock); - if (b->type == INPUT_MPLANE) { - q = &inst->vb2q[INPUT_PORT]; - } else if (b->type == OUTPUT_MPLANE) { - q = &inst->vb2q[OUTPUT_PORT]; - } else if (b->type == INPUT_META_PLANE) { - q = &inst->vb2q[INPUT_META_PORT]; - } else if (b->type == OUTPUT_META_PLANE) { - q = &inst->vb2q[OUTPUT_META_PORT]; - } else { - s_vpr_e(inst->sid, "%s: invalid buffer type %d\n", - __func__, b->type); + + q = msm_vidc_get_vb2q(inst, b->type, __func__); + if (!q) { rc = -EINVAL; goto unlock; } @@ -445,7 +414,6 @@ int msm_vidc_streamon(void *instance, enum v4l2_buf_type type) { int rc = 0; struct msm_vidc_inst *inst = instance; - enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR; int port; if (!inst) { @@ -455,26 +423,13 @@ int msm_vidc_streamon(void *instance, enum v4l2_buf_type type) mutex_lock(&inst->lock); - if (type == INPUT_MPLANE) { - if (inst->state != MSM_VIDC_OPEN && - inst->state != MSM_VIDC_START_OUTPUT) { - s_vpr_e(inst->sid, - "%s: streamon(%d) not allowed in %d state\n", - __func__, type, inst->state); - rc = -EINVAL; - goto unlock; - } - } else if (type == OUTPUT_MPLANE) { - if (inst->state != MSM_VIDC_OPEN && - inst->state != MSM_VIDC_START_INPUT && - inst->state != MSM_VIDC_DRAIN_START_INPUT) { - s_vpr_e(inst->sid, - "%s: streamon(%d) not allowed in %d state\n", - __func__, type, inst->state); - rc = -EINVAL; - goto unlock; - } + if (!msm_vidc_allow_streamon(inst, type)) { + rc = -EBUSY; + goto unlock; } + rc = msm_vidc_state_change_streamon(inst, type); + if (rc) + goto unlock; port = v4l2_type_to_driver_port(inst, type, __func__); if (port < 0) { @@ -486,34 +441,10 @@ int msm_vidc_streamon(void *instance, enum v4l2_buf_type type) if (rc) { s_vpr_e(inst->sid, "%s: vb2_streamon(%d) failed, %d\n", __func__, type, rc); + msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); goto unlock; } - if (type == INPUT_MPLANE) { - if (inst->state == MSM_VIDC_OPEN) { - new_state = MSM_VIDC_START_INPUT; - } else if (inst->state == MSM_VIDC_START_OUTPUT) { - new_state = MSM_VIDC_START; - } - rc = msm_vidc_change_inst_state(inst, new_state, __func__); - if (rc) - goto unlock; - } else if (type == OUTPUT_MPLANE) { - if (inst->state == MSM_VIDC_OPEN) { - new_state = MSM_VIDC_START_OUTPUT; - } else if (inst->state == MSM_VIDC_START_INPUT) { - new_state = MSM_VIDC_START; - } else if (inst->state == MSM_VIDC_DRAIN_START_INPUT) { - if (0 /* check if input port settings change pending */) - new_state = MSM_VIDC_DRC_DRAIN; - else - new_state = MSM_VIDC_DRAIN; - } - rc = msm_vidc_change_inst_state(inst, new_state, __func__); - if (rc) - goto unlock; - } - unlock: mutex_unlock(&inst->lock); return rc; @@ -524,7 +455,6 @@ int msm_vidc_streamoff(void *instance, enum v4l2_buf_type type) { int rc = 0; struct msm_vidc_inst *inst = instance; - enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR; int port; if (!inst) { @@ -534,25 +464,13 @@ int msm_vidc_streamoff(void *instance, enum v4l2_buf_type type) mutex_lock(&inst->lock); - if (type == INPUT_MPLANE) { - if (inst->state == MSM_VIDC_OPEN || - inst->state == MSM_VIDC_START_OUTPUT) { - s_vpr_e(inst->sid, - "%s: streamoff(%d) not allowed in %d state\n", - __func__, type, inst->state); - rc = -EINVAL; - goto unlock; - } - } else if (type == OUTPUT_MPLANE) { - if (inst->state == MSM_VIDC_OPEN || - inst->state == MSM_VIDC_START_INPUT) { - s_vpr_e(inst->sid, - "%s: streamoff(%d) not allowed in %d state\n", - __func__, type, inst->state); - rc = -EINVAL; - goto unlock; - } + if (!msm_vidc_allow_streamoff(inst, type)) { + rc = -EBUSY; + goto unlock; } + rc = msm_vidc_state_change_streamoff(inst, type); + if (rc) + goto unlock; port = v4l2_type_to_driver_port(inst, type, __func__); if (port < 0) { @@ -564,45 +482,10 @@ int msm_vidc_streamoff(void *instance, enum v4l2_buf_type type) if (rc) { s_vpr_e(inst->sid, "%s: vb2_streamoff(%d) failed, %d\n", __func__, type, rc); + msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); goto unlock; } - if (type == INPUT_MPLANE) { - if (inst->state == MSM_VIDC_START_INPUT) { - new_state = MSM_VIDC_OPEN; - } else if (inst->state == MSM_VIDC_START) { - new_state = MSM_VIDC_START_OUTPUT; - } else if (inst->state == MSM_VIDC_DRC || - inst->state == MSM_VIDC_DRC_LAST_FLAG || - inst->state == MSM_VIDC_DRAIN || - inst->state == MSM_VIDC_DRAIN_LAST_FLAG || - inst->state == MSM_VIDC_DRC_DRAIN || - inst->state == MSM_VIDC_DRC_DRAIN_LAST_FLAG || - inst->state == MSM_VIDC_DRAIN_START_INPUT) { - new_state = MSM_VIDC_START_OUTPUT; - /* discard pending port settings change if any */ - } - rc = msm_vidc_change_inst_state(inst, new_state, __func__); - if (rc) - goto unlock; - } else if (type == OUTPUT_MPLANE) { - if (inst->state == MSM_VIDC_START_OUTPUT) { - new_state = MSM_VIDC_OPEN; - } else if (inst->state == MSM_VIDC_START || - inst->state == MSM_VIDC_DRAIN || - inst->state == MSM_VIDC_DRAIN_LAST_FLAG || - inst->state == MSM_VIDC_DRC || - inst->state == MSM_VIDC_DRC_LAST_FLAG || - inst->state == MSM_VIDC_DRC_DRAIN) { - new_state = MSM_VIDC_START_INPUT; - } else if (inst->state == MSM_VIDC_DRC_DRAIN_LAST_FLAG) { - new_state = MSM_VIDC_DRAIN_START_INPUT; - } - rc = msm_vidc_change_inst_state(inst, new_state, __func__); - if (rc) - goto unlock; - } - unlock: mutex_unlock(&inst->lock); return rc; @@ -740,8 +623,10 @@ void *msm_vidc_open(void *vidc_core, u32 session_type) if (core->state == MSM_VIDC_CORE_DEINIT) { rc = msm_vidc_core_init(core); - if (rc) + if (rc) { + msm_vidc_core_deinit(core); return NULL; + } } inst = kzalloc(sizeof(*inst), GFP_KERNEL); @@ -750,25 +635,34 @@ void *msm_vidc_open(void *vidc_core, u32 session_type) return NULL; } inst->core = core; + kref_init(&inst->kref); + mutex_init(&inst->lock); + + rc = msm_vidc_add_session(inst); + if (rc) { + d_vpr_e("%s: failed to get session id\n", __func__); + goto error; + } + s_vpr_i(inst->sid, "Opening video instance: %d\n", session_type); + + inst->input_psc_workq = create_singlethread_workqueue("input_psc_workq"); + if (!inst->input_psc_workq) { + d_vpr_e("%s: create input_psc_workq failed\n", __func__); + goto error; + } inst->capabilities = kzalloc( sizeof(struct msm_vidc_inst_capability), GFP_KERNEL); if (!inst->capabilities) { s_vpr_e(inst->sid, "%s: inst capability allocation failed\n", __func__); - return NULL; + goto error; } - rc = msm_vidc_add_session(inst); - if (rc) { - d_vpr_e("%s: failed to get session id\n", __func__); - return NULL; - } + INIT_DELAYED_WORK(&inst->input_psc_work, + handle_session_input_psc_work_handler); - s_vpr_i(inst->sid, "Opening video instance: %d\n", session_type); - - kref_init(&inst->kref); - mutex_init(&inst->lock); + INIT_LIST_HEAD(&inst->input_psc_works); INIT_LIST_HEAD(&inst->buffers.input.list); INIT_LIST_HEAD(&inst->buffers.input_meta.list); INIT_LIST_HEAD(&inst->buffers.output.list); @@ -780,6 +674,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type) INIT_LIST_HEAD(&inst->buffers.line.list); INIT_LIST_HEAD(&inst->buffers.dpb.list); INIT_LIST_HEAD(&inst->buffers.persist.list); + INIT_LIST_HEAD(&inst->buffers.vpss.list); INIT_LIST_HEAD(&inst->allocations.bin.list); INIT_LIST_HEAD(&inst->allocations.arp.list); INIT_LIST_HEAD(&inst->allocations.comv.list); @@ -787,6 +682,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type) INIT_LIST_HEAD(&inst->allocations.line.list); INIT_LIST_HEAD(&inst->allocations.dpb.list); INIT_LIST_HEAD(&inst->allocations.persist.list); + INIT_LIST_HEAD(&inst->allocations.vpss.list); INIT_LIST_HEAD(&inst->mappings.input.list); INIT_LIST_HEAD(&inst->mappings.input_meta.list); INIT_LIST_HEAD(&inst->mappings.output.list); @@ -798,6 +694,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type) INIT_LIST_HEAD(&inst->mappings.line.list); INIT_LIST_HEAD(&inst->mappings.dpb.list); INIT_LIST_HEAD(&inst->mappings.persist.list); + INIT_LIST_HEAD(&inst->mappings.vpss.list); INIT_LIST_HEAD(&inst->children.list); INIT_LIST_HEAD(&inst->firmware.list); inst->domain = session_type; @@ -812,21 +709,18 @@ void *msm_vidc_open(void *vidc_core, u32 session_type) //inst->debugfs_root = // msm_vidc_debugfs_init_inst(inst, core->debugfs_root); - if (is_decode_session(inst)) { + if (is_decode_session(inst)) rc = msm_vdec_inst_init(inst); - if (rc) - goto error; - } else if (is_encode_session(inst)) { + else if (is_encode_session(inst)) rc = msm_venc_inst_init(inst); - if (rc) - goto error; - } + if (rc) + goto error; rc = msm_vidc_vb2_queue_init(inst); if (rc) goto error; - rc = msm_vidc_setup_event_queue(inst); + rc = msm_vidc_event_queue_init(inst); if (rc) goto error; @@ -854,9 +748,12 @@ int msm_vidc_close(void *instance) return -EINVAL; } s_vpr_h(inst->sid, "%s()\n", __func__); + mutex_lock(&inst->lock); msm_vidc_session_close(inst); msm_vidc_remove_session(inst); - + msm_vidc_destroy_buffers(inst); + mutex_unlock(&inst->lock); + put_inst(inst); return rc; } EXPORT_SYMBOL(msm_vidc_close); diff --git a/driver/vidc/src/msm_vidc_control.c b/driver/vidc/src/msm_vidc_control.c index 3bb7295e33..73f77f9b5c 100644 --- a/driver/vidc/src/msm_vidc_control.c +++ b/driver/vidc/src/msm_vidc_control.c @@ -346,7 +346,7 @@ int msm_vidc_ctrl_deinit(struct msm_vidc_inst *inst) d_vpr_e("%s: invalid parameters\n", __func__); return -EINVAL; } - + s_vpr_h(inst->sid, "%s(): num ctrls %d\n", __func__, inst->num_ctrls); v4l2_ctrl_handler_free(&inst->ctrl_handler); kfree(inst->ctrls); @@ -362,7 +362,6 @@ int msm_vidc_ctrl_init(struct msm_vidc_inst *inst) struct v4l2_ctrl_config ctrl_cfg = {0}; int num_ctrls = 0, ctrl_idx = 0; - d_vpr_h("%s()\n", __func__); if (!inst || !inst->core || !inst->capabilities) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; @@ -497,6 +496,7 @@ int msm_vidc_ctrl_init(struct msm_vidc_inst *inst) ctrl_idx++; } inst->num_ctrls = num_ctrls; + s_vpr_h(inst->sid, "%s(): num ctrls %d\n", __func__, inst->num_ctrls); return rc; } diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index 01b15e7a6c..b2dd409537 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/driver/vidc/src/msm_vidc_driver.c @@ -14,8 +14,11 @@ #include "msm_vidc_memory.h" #include "msm_vidc_debug.h" #include "msm_vidc_power.h" -#include "venus_hfi.h" #include "msm_vidc.h" +#include "msm_vdec.h" +#include "msm_venc.h" +#include "venus_hfi.h" +#include "venus_hfi_response.h" #define COUNT_BITS(a, out) { \ while ((a) >= 1) { \ @@ -345,6 +348,8 @@ struct msm_vidc_buffers *msm_vidc_get_buffers( return &inst->buffers.dpb; case MSM_VIDC_BUF_PERSIST: return &inst->buffers.persist; + case MSM_VIDC_BUF_VPSS: + return &inst->buffers.vpss; default: s_vpr_e(inst->sid, "%s: invalid driver buffer type %d\n", func, buffer_type); @@ -379,6 +384,8 @@ struct msm_vidc_mappings *msm_vidc_get_mappings( return &inst->mappings.dpb; case MSM_VIDC_BUF_PERSIST: return &inst->mappings.persist; + case MSM_VIDC_BUF_VPSS: + return &inst->mappings.vpss; default: s_vpr_e(inst->sid, "%s: invalid driver buffer type %d\n", func, buffer_type); @@ -405,6 +412,8 @@ struct msm_vidc_allocations *msm_vidc_get_allocations( return &inst->allocations.dpb; case MSM_VIDC_BUF_PERSIST: return &inst->allocations.persist; + case MSM_VIDC_BUF_VPSS: + return &inst->allocations.vpss; default: s_vpr_e(inst->sid, "%s: invalid driver buffer type %d\n", func, buffer_type); @@ -412,6 +421,55 @@ struct msm_vidc_allocations *msm_vidc_get_allocations( } } +const char *state_name(enum msm_vidc_inst_state state) +{ + const char *name = "UNKNOWN"; + + switch (state) { + case MSM_VIDC_OPEN: + name = "OPEN"; + break; + case MSM_VIDC_START_INPUT: + name = "START_INPUT"; + break; + case MSM_VIDC_START_OUTPUT: + name = "START_OUTPUT"; + break; + case MSM_VIDC_START: + name = "START"; + break; + case MSM_VIDC_DRC: + name = "DRC"; + break; + case MSM_VIDC_DRC_LAST_FLAG: + name = "DRC_LAST_FLAG"; + break; + case MSM_VIDC_DRAIN: + name = "DRAIN"; + break; + case MSM_VIDC_DRAIN_LAST_FLAG: + name = "DRAIN_LAST_FLAG"; + break; + case MSM_VIDC_DRC_DRAIN: + name = "DRC_DRAIN"; + break; + case MSM_VIDC_DRC_DRAIN_LAST_FLAG: + name = "DRC_DRAIN_LAST_FLAG"; + break; + case MSM_VIDC_DRAIN_START_INPUT: + name = "DRAIN_START_INPUT"; + break; + case MSM_VIDC_ERROR: + name = "ERROR"; + break; + default: + name = "UNKNOWN"; + break; + } + + return name; +} + int msm_vidc_change_inst_state(struct msm_vidc_inst *inst, enum msm_vidc_inst_state request_state, const char *func) { @@ -427,17 +485,531 @@ int msm_vidc_change_inst_state(struct msm_vidc_inst *inst, if (inst->state == MSM_VIDC_ERROR) { s_vpr_h(inst->sid, - "%s: inst is in bad state, can not change state to %d\n", - func, request_state); + "%s: inst is in bad state, can not change state to %s\n", + func, state_name(request_state)); return 0; } - s_vpr_h(inst->sid, "%s: state changed from %d to %d\n", - func, inst->state, request_state); + s_vpr_h(inst->sid, "%s: state changed from %s to %s\n", + func, state_name(inst->state), state_name(request_state)); inst->state = request_state; return 0; } +bool msm_vidc_allow_s_fmt(struct msm_vidc_inst *inst, u32 type) +{ + bool allow = false; + + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return false; + } + if (inst->state == MSM_VIDC_OPEN) { + allow = true; + goto exit; + } + if (inst->state == MSM_VIDC_START_INPUT) { + if (type == OUTPUT_MPLANE || type == OUTPUT_META_PLANE) { + allow = true; + goto exit; + } + } + if (inst->state == MSM_VIDC_START_OUTPUT) { + if (type == INPUT_MPLANE || type == INPUT_META_PLANE) { + allow = true; + goto exit; + } + } + +exit: + if (!allow) + s_vpr_e(inst->sid, "%s: type %d not allowed in state %s\n", + __func__, type, state_name(inst->state)); + return allow; +} + +bool msm_vidc_allow_s_ctrl(struct msm_vidc_inst *inst, u32 id) +{ + bool allow = false; + + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return false; + } + if (inst->state == MSM_VIDC_OPEN) { + allow = true; + goto exit; + } + if (inst->state == MSM_VIDC_START || inst->state == MSM_VIDC_START_OUTPUT) { + switch (id) { + case V4L2_CID_MPEG_VIDEO_BITRATE: + case V4L2_CID_MPEG_VIDEO_GOP_SIZE: + case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME: + case V4L2_CID_HFLIP: + case V4L2_CID_VFLIP: + case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: + case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER: + case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L0_BR: + case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L1_BR: + case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L2_BR: + case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L3_BR: + case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L4_BR: + case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L5_BR: + case V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_L6_BR: + case V4L2_CID_MPEG_VIDC_BASELAYER_PRIORITY: + case V4L2_CID_MPEG_VIDC_USELTRFRAME: + case V4L2_CID_MPEG_VIDC_MARKLTRFRAME: + case V4L2_CID_MPEG_VIDC_VIDEO_BLUR_TYPES: + case V4L2_CID_MPEG_VIDC_VIDEO_BLUR_RESOLUTION: + allow = true; + break; + default: + allow = false; + break; + } + } + +exit: + if (!allow) + s_vpr_e(inst->sid, "%s: id %d not allowed in state %s\n", + __func__, id, state_name(inst->state)); + return allow; +} + +bool msm_vidc_allow_reqbufs(struct msm_vidc_inst *inst, u32 type) +{ + bool allow = false; + + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return false; + } + if (inst->state == MSM_VIDC_OPEN) { + allow = true; + goto exit; + } + if (inst->state == MSM_VIDC_START_INPUT) { + if (type == OUTPUT_MPLANE || type == OUTPUT_META_PLANE) { + allow = true; + goto exit; + } + } + if (inst->state == MSM_VIDC_START_OUTPUT) { + if (type == INPUT_MPLANE || type == INPUT_META_PLANE) { + allow = true; + goto exit; + } + } + +exit: + if (!allow) + s_vpr_e(inst->sid, "%s: type %d not allowed in state %s\n", + __func__, type, state_name(inst->state)); + return allow; +} + +bool msm_vidc_allow_stop(struct msm_vidc_inst *inst) +{ + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return false; + } + if (inst->state == MSM_VIDC_START || + inst->state == MSM_VIDC_DRC || + inst->state == MSM_VIDC_DRC_LAST_FLAG || + inst->state == MSM_VIDC_DRC_DRAIN) + return true; + + s_vpr_e(inst->sid, "%s: not allowed in state %s\n", + __func__, state_name(inst->state)); + return false; +} + +bool msm_vidc_allow_start(struct msm_vidc_inst *inst) +{ + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return false; + } + if (inst->state == MSM_VIDC_DRAIN_LAST_FLAG || + inst->state == MSM_VIDC_DRC_LAST_FLAG || + inst->state == MSM_VIDC_DRC_DRAIN_LAST_FLAG) + return true; + + s_vpr_e(inst->sid, "%s: not allowed in state %s\n", + __func__, state_name(inst->state)); + return false; +} + +bool msm_vidc_allow_streamon(struct msm_vidc_inst *inst, u32 type) +{ + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return false; + } + if (type == INPUT_MPLANE || type == INPUT_META_PLANE) { + if (inst->state == MSM_VIDC_OPEN || + inst->state == MSM_VIDC_START_OUTPUT) + return true; + } else if (type == OUTPUT_MPLANE || type == OUTPUT_META_PLANE) { + if (inst->state == MSM_VIDC_OPEN || + inst->state == MSM_VIDC_START_INPUT || + inst->state == MSM_VIDC_DRAIN_START_INPUT) + return true; + } + + s_vpr_e(inst->sid, "%s: type %d not allowed in state %s\n", + __func__, type, state_name(inst->state)); + return false; +} + +bool msm_vidc_allow_streamoff(struct msm_vidc_inst *inst, u32 type) +{ + bool allow = true; + + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return false; + } + if (type == INPUT_MPLANE || type == INPUT_META_PLANE) { + if (inst->state == MSM_VIDC_OPEN || + inst->state == MSM_VIDC_START_OUTPUT) + allow = false; + } else if (type == OUTPUT_MPLANE || type == OUTPUT_META_PLANE) { + if (inst->state == MSM_VIDC_OPEN || + inst->state == MSM_VIDC_START_INPUT) + allow = false; + } + if (!allow) + s_vpr_e(inst->sid, "%s: type %d not allowed in state %s\n", + __func__, type, state_name(inst->state)); + + return allow; +} + +bool msm_vidc_allow_qbuf(struct msm_vidc_inst *inst) +{ + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return false; + } + if (inst->state == MSM_VIDC_ERROR) { + s_vpr_e(inst->sid, "%s: inst in error state\n", __func__); + return false; + } else { + return true; + } +} + +int msm_vidc_allow_input_psc(struct msm_vidc_inst *inst) +{ + int rc = 0; + + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + if (inst->state == MSM_VIDC_START || + inst->state == MSM_VIDC_START_INPUT || + inst->state == MSM_VIDC_DRAIN) { + rc = 0; + } else if (inst->state == MSM_VIDC_DRC || + inst->state == MSM_VIDC_DRC_LAST_FLAG || + inst->state == MSM_VIDC_DRC_DRAIN || + inst->state == MSM_VIDC_DRC_DRAIN_LAST_FLAG || + inst->state == MSM_VIDC_DRAIN_START_INPUT) { + s_vpr_h(inst->sid, "%s: input psc postponed, inst state %s\n", + __func__, state_name(inst->state)); + rc = -EAGAIN; + } else { + s_vpr_e(inst->sid, "%s: input psc in wrong state %s\n", + __func__, state_name(inst->state)); + rc = -EINVAL; + } + + return rc; +} + +bool msm_vidc_allow_last_flag(struct msm_vidc_inst *inst) +{ + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return false; + } + if (inst->state == MSM_VIDC_DRC || + inst->state == MSM_VIDC_DRAIN || + inst->state == MSM_VIDC_DRC_DRAIN) + return true; + + s_vpr_e(inst->sid, "%s: not allowed in state %s\n", + __func__, state_name(inst->state)); + return false; +} + +int msm_vidc_state_change_streamon(struct msm_vidc_inst *inst, u32 type) +{ + int rc = 0; + enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR; + struct input_psc_work *psc_work; + + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (type == INPUT_MPLANE) { + if (inst->state == MSM_VIDC_OPEN) + new_state = MSM_VIDC_START_INPUT; + else if (inst->state == MSM_VIDC_START_OUTPUT) + new_state = MSM_VIDC_START; + } else if (type == OUTPUT_MPLANE) { + if (inst->state == MSM_VIDC_OPEN) { + new_state = MSM_VIDC_START_OUTPUT; + } else if (inst->state == MSM_VIDC_START_INPUT) { + new_state = MSM_VIDC_START; + } else if (inst->state == MSM_VIDC_DRAIN_START_INPUT) { + s_vpr_h(inst->sid, + "%s: streamon(output) in DRAIN_START_INPUT state\n", + __func__); + if (list_empty(&inst->input_psc_works)) { + new_state = MSM_VIDC_DRAIN; + } else { + s_vpr_h(inst->sid, + "%s: streamon(output) in DRAIN_START_INPUT state, input psc pending\n", + __func__); + psc_work = list_first_entry(&inst->input_psc_works, + struct input_psc_work, list); + rc = handle_session_input_psc(inst, psc_work); + if (rc) { + s_vpr_e(inst->sid, + "%s: handle input psc failed\n", __func__); + new_state = MSM_VIDC_ERROR; + } else { + new_state = MSM_VIDC_DRC_DRAIN; + } + list_del(&psc_work->list); + kfree(psc_work->data); + kfree(psc_work); + } + } + } + rc = msm_vidc_change_inst_state(inst, new_state, __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_state_change_streamoff(struct msm_vidc_inst *inst, u32 type) +{ + int rc = 0; + enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR; + struct input_psc_work *psc_work, *dummy; + + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (type == INPUT_MPLANE) { + if (inst->state == MSM_VIDC_START_INPUT) { + new_state = MSM_VIDC_OPEN; + } else if (inst->state == MSM_VIDC_START) { + new_state = MSM_VIDC_START_OUTPUT; + } else if (inst->state == MSM_VIDC_DRC || + inst->state == MSM_VIDC_DRC_LAST_FLAG || + inst->state == MSM_VIDC_DRAIN || + inst->state == MSM_VIDC_DRAIN_LAST_FLAG || + inst->state == MSM_VIDC_DRC_DRAIN || + inst->state == MSM_VIDC_DRC_DRAIN_LAST_FLAG || + inst->state == MSM_VIDC_DRAIN_START_INPUT) { + new_state = MSM_VIDC_START_OUTPUT; + /* discard pending port settings change if any */ + list_for_each_entry_safe(psc_work, dummy, + &inst->input_psc_works, list) { + s_vpr_h(inst->sid, + "%s: discard pending input psc\n", __func__); + list_del(&psc_work->list); + kfree(psc_work->data); + kfree(psc_work); + } + } + } else if (type == OUTPUT_MPLANE) { + if (inst->state == MSM_VIDC_START_OUTPUT) { + new_state = MSM_VIDC_OPEN; + } else if (inst->state == MSM_VIDC_START || + inst->state == MSM_VIDC_DRAIN || + inst->state == MSM_VIDC_DRAIN_LAST_FLAG || + inst->state == MSM_VIDC_DRC || + inst->state == MSM_VIDC_DRC_LAST_FLAG || + inst->state == MSM_VIDC_DRC_DRAIN) { + new_state = MSM_VIDC_START_INPUT; + } else if (inst->state == MSM_VIDC_DRC_DRAIN_LAST_FLAG) { + new_state = MSM_VIDC_DRAIN_START_INPUT; + } + } + rc = msm_vidc_change_inst_state(inst, new_state, __func__); + if (rc) + goto exit; + +exit: + return rc; +} + +int msm_vidc_state_change_stop(struct msm_vidc_inst *inst) +{ + int rc = 0; + enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR; + + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (inst->state == MSM_VIDC_START) { + new_state = MSM_VIDC_DRAIN; + } else if (inst->state == MSM_VIDC_DRC) { + new_state = MSM_VIDC_DRC_DRAIN; + } else if (inst->state == MSM_VIDC_DRC_DRAIN || + inst->state == MSM_VIDC_DRC_LAST_FLAG) { + new_state = MSM_VIDC_DRC_DRAIN_LAST_FLAG; + } else { + s_vpr_e(inst->sid, "%s: wrong state %s\n", + __func__, state_name(inst->state)); + msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); + return -EINVAL; + } + rc = msm_vidc_change_inst_state(inst, new_state, __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_state_change_start(struct msm_vidc_inst *inst) +{ + int rc = 0; + enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR; + struct input_psc_work *psc_work; + + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + if (inst->state == MSM_VIDC_DRAIN_LAST_FLAG || + inst->state == MSM_VIDC_DRC_LAST_FLAG) { + if (list_empty(&inst->input_psc_works)) { + new_state = MSM_VIDC_START; + } else { + s_vpr_h(inst->sid, + "%s: start in DRC(DRAIN)_LAST_FLAG state, input psc pending\n", + __func__); + psc_work = list_first_entry(&inst->input_psc_works, + struct input_psc_work, list); + rc = handle_session_input_psc(inst, psc_work); + if (rc) { + s_vpr_e(inst->sid, + "%s: handle input psc failed\n", __func__); + new_state = MSM_VIDC_ERROR; + } else { + new_state = MSM_VIDC_DRC; + } + list_del(&psc_work->list); + kfree(psc_work->data); + kfree(psc_work); + } + } else if (inst->state == MSM_VIDC_DRC_DRAIN_LAST_FLAG) { + if (list_empty(&inst->input_psc_works)) { + new_state = MSM_VIDC_DRAIN; + } else { + s_vpr_h(inst->sid, + "%s: start in DRC_DRAIN_LAST_FLAG state, input psc pending\n"); + psc_work = list_first_entry(&inst->input_psc_works, + struct input_psc_work, list); + rc = handle_session_input_psc(inst, psc_work); + if (rc) { + s_vpr_e(inst->sid, + "%s: handle input psc failed\n", __func__); + new_state = MSM_VIDC_ERROR; + } else { + new_state = MSM_VIDC_DRC_DRAIN; + } + list_del(&psc_work->list); + kfree(psc_work->data); + kfree(psc_work); + } + } else { + s_vpr_e(inst->sid, "%s: wrong state %s\n", + __func__, state_name(inst->state)); + msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); + return -EINVAL; + } + rc = msm_vidc_change_inst_state(inst, new_state, __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_state_change_input_psc(struct msm_vidc_inst *inst) +{ + int rc = 0; + enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR; + + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + /* don't change state as output port is not started yet */ + if (inst->state == MSM_VIDC_START_INPUT) + return 0; + + if (inst->state == MSM_VIDC_START) { + new_state = MSM_VIDC_DRC; + } else if (inst->state == MSM_VIDC_DRAIN) { + new_state = MSM_VIDC_DRC_DRAIN; + } else { + s_vpr_e(inst->sid, "%s: wrong state %s\n", + __func__, state_name(inst->state)); + msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); + return -EINVAL; + } + rc = msm_vidc_change_inst_state(inst, new_state, __func__); + if (rc) + return rc; + + return rc; +} + +int msm_vidc_state_change_last_flag(struct msm_vidc_inst *inst) +{ + int rc = 0; + enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR; + + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + if (inst->state == MSM_VIDC_DRC) { + new_state = MSM_VIDC_DRC_LAST_FLAG; + } else if (inst->state == MSM_VIDC_DRAIN) { + new_state = MSM_VIDC_DRAIN_LAST_FLAG; + } else if (inst->state == MSM_VIDC_DRC_DRAIN) { + new_state = MSM_VIDC_DRC_DRAIN_LAST_FLAG; + } else { + s_vpr_e(inst->sid, "%s: wrong state %s\n", + __func__, state_name(inst->state)); + msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); + return -EINVAL; + } + rc = msm_vidc_change_inst_state(inst, new_state, __func__); + if (rc) + return rc; + + return rc; +} + int msm_vidc_get_control(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl) { int rc = 0; @@ -602,10 +1174,6 @@ int msm_vidc_put_driver_buf(struct msm_vidc_inst *inst, return -EINVAL; } - /* do not unmap / delete read only buffer */ - if (buf->attr & MSM_VIDC_ATTR_READ_ONLY) - return 0; - rc = msm_vidc_unmap_driver_buf(inst, buf); if (rc) return rc; @@ -1218,20 +1786,18 @@ int msm_vidc_vb2_buffer_done(struct msm_vidc_inst *inst, return 0; } -int msm_vidc_setup_event_queue(struct msm_vidc_inst *inst) +int msm_vidc_event_queue_init(struct msm_vidc_inst *inst) { int rc = 0; int index; struct msm_vidc_core *core; - d_vpr_h("%s()\n", __func__); if (!inst || !inst->core) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } core = inst->core; - // TODO: check decode is index = 0 and encode is index 1 if (is_decode_session(inst)) index = 0; else if (is_encode_session(inst)) @@ -1245,9 +1811,25 @@ int msm_vidc_setup_event_queue(struct msm_vidc_inst *inst) return rc; } +int msm_vidc_event_queue_deinit(struct msm_vidc_inst *inst) +{ + int rc = 0; + + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + v4l2_fh_del(&inst->event_handler); + v4l2_fh_exit(&inst->event_handler); + + return rc; +} + static int vb2q_init(struct msm_vidc_inst *inst, struct vb2_queue *q, enum v4l2_buf_type type) { + int rc = 0; struct msm_vidc_core *core; if (!inst || !q || !inst->core) { @@ -1264,14 +1846,17 @@ static int vb2q_init(struct msm_vidc_inst *inst, q->drv_priv = inst; q->allow_zero_bytesused = 1; q->copy_timestamp = 1; - return vb2_queue_init(q); + rc = vb2_queue_init(q); + if (rc) + s_vpr_e(inst->sid, "%s: vb2_queue_init failed for type %d\n", + __func__, type); + return rc; } int msm_vidc_vb2_queue_init(struct msm_vidc_inst *inst) { int rc = 0; - d_vpr_h("%s()\n", __func__); if (!inst) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; @@ -1296,6 +1881,22 @@ int msm_vidc_vb2_queue_init(struct msm_vidc_inst *inst) return rc; } +int msm_vidc_vb2_queue_deinit(struct msm_vidc_inst *inst) +{ + int rc = 0; + + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + vb2_queue_release(&inst->vb2q[OUTPUT_META_PORT]); + vb2_queue_release(&inst->vb2q[INPUT_META_PORT]); + vb2_queue_release(&inst->vb2q[OUTPUT_PORT]); + vb2_queue_release(&inst->vb2q[INPUT_PORT]); + + return rc; +} + int msm_vidc_add_session(struct msm_vidc_inst *inst) { int rc = 0; @@ -1388,7 +1989,7 @@ int msm_vidc_session_set_codec(struct msm_vidc_inst *inst) return 0; } -int msm_vidc_session_start(struct msm_vidc_inst* inst, +int msm_vidc_session_streamon(struct msm_vidc_inst *inst, enum msm_vidc_port_type port) { int rc = 0; @@ -1407,7 +2008,7 @@ int msm_vidc_session_start(struct msm_vidc_inst* inst, return rc; } -int msm_vidc_session_stop(struct msm_vidc_inst *inst, +int msm_vidc_session_streamoff(struct msm_vidc_inst *inst, enum msm_vidc_port_type port) { int rc = 0; @@ -1433,9 +2034,9 @@ int msm_vidc_session_stop(struct msm_vidc_inst *inst, return rc; core = inst->core; - mutex_unlock(&inst->lock); s_vpr_h(inst->sid, "%s: wait on port: %d for time: %d ms\n", __func__, port, core->capabilities[HW_RESPONSE_TIMEOUT].value); + mutex_unlock(&inst->lock); rc = wait_for_completion_timeout( &inst->completions[signal_type], msecs_to_jiffies( @@ -1472,10 +2073,12 @@ int msm_vidc_session_close(struct msm_vidc_inst *inst) core = inst->core; s_vpr_h(inst->sid, "%s: wait on close for time: %d ms\n", __func__, core->capabilities[HW_RESPONSE_TIMEOUT].value); + mutex_unlock(&inst->lock); rc = wait_for_completion_timeout( &inst->completions[SIGNAL_CMD_CLOSE], msecs_to_jiffies( core->capabilities[HW_RESPONSE_TIMEOUT].value)); + mutex_lock(&inst->lock); if (!rc) { s_vpr_e(inst->sid, "%s: session close timed out\n", __func__); //msm_comm_kill_session(inst); @@ -1519,6 +2122,20 @@ int msm_vidc_get_inst_capability(struct msm_vidc_inst *inst) return rc; } +static int msm_vidc_deinit_core_caps(struct msm_vidc_core *core) +{ + int rc = 0; + + if (!core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + kfree(core->capabilities); + core->capabilities = NULL; + + return rc; +} + static int msm_vidc_init_core_caps(struct msm_vidc_core *core) { int rc = 0; @@ -1563,6 +2180,8 @@ static int msm_vidc_init_core_caps(struct msm_vidc_core *core) } exit: + if (rc) + msm_vidc_deinit_core_caps(core); return rc; } @@ -1595,6 +2214,20 @@ static void update_inst_capability(struct msm_platform_inst_capability *in, } } +static int msm_vidc_deinit_instance_caps(struct msm_vidc_core *core) +{ + int rc = 0; + + if (!core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + kfree(core->inst_caps); + core->inst_caps = NULL; + + return rc; +} + static int msm_vidc_init_instance_caps(struct msm_vidc_core *core) { int rc = 0; @@ -1607,7 +2240,7 @@ static int msm_vidc_init_instance_caps(struct msm_vidc_core *core) if (!core || !core->platform || !core->capabilities) { d_vpr_e("%s: invalid params\n", __func__); rc = -EINVAL; - goto exit; + goto error; } platform_data = core->platform->data.instance_data; @@ -1615,7 +2248,7 @@ static int msm_vidc_init_instance_caps(struct msm_vidc_core *core) d_vpr_e("%s: platform instance data is NULL\n", __func__); rc = -EINVAL; - goto exit; + goto error; } enc_valid_codecs = core->capabilities[ENC_CODECS].value; @@ -1637,7 +2270,7 @@ static int msm_vidc_init_instance_caps(struct msm_vidc_core *core) d_vpr_e("%s: failed to allocate core capabilities\n", __func__); rc = -ENOMEM; - goto exit; + goto error; } } else { d_vpr_e("%s: capabilities memory is expected to be freed\n", @@ -1692,7 +2325,28 @@ static int msm_vidc_init_instance_caps(struct msm_vidc_core *core) } } } -exit: + + return 0; +error: + if (rc) + msm_vidc_deinit_instance_caps(core); + return rc; +} + +int msm_vidc_core_deinit(struct msm_vidc_core *core) +{ + int rc = 0; + + d_vpr_h("%s()\n", __func__); + if (!core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + mutex_lock(&core->lock); + venus_hfi_core_deinit(core); + msm_vidc_deinit_instance_caps(core); + msm_vidc_deinit_core_caps(core); + mutex_unlock(&core->lock); return rc; } @@ -1736,16 +2390,14 @@ int msm_vidc_core_init(struct msm_vidc_core *core) goto unlock; } - mutex_unlock(&core->lock); - /*TODO: acquire lock or not */ d_vpr_h("%s(): waiting for sys init done, %d ms\n", __func__, core->capabilities[HW_RESPONSE_TIMEOUT].value); + mutex_unlock(&core->lock); rc = wait_for_completion_timeout(&core->init_done, msecs_to_jiffies( core->capabilities[HW_RESPONSE_TIMEOUT].value)); if (!rc) { d_vpr_e("%s: system init timed out\n", __func__); - //msm_comm_kill_session(inst); - //rc = -EIO; + rc = -ETIMEDOUT; } else { d_vpr_h("%s: system init wait completed\n", __func__); rc = 0; @@ -1785,6 +2437,82 @@ void msm_vidc_batch_handler(struct work_struct *work) { } +void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst) +{ + struct msm_vidc_buffers *buffers; + struct msm_vidc_buffer *buf, *dummy; + enum msm_vidc_buffer_type buf_types[] = { + MSM_VIDC_BUF_INPUT, + MSM_VIDC_BUF_OUTPUT, + MSM_VIDC_BUF_INPUT_META, + MSM_VIDC_BUF_OUTPUT_META, + MSM_VIDC_BUF_BIN, + MSM_VIDC_BUF_ARP, + MSM_VIDC_BUF_COMV, + MSM_VIDC_BUF_NON_COMV, + MSM_VIDC_BUF_LINE, + MSM_VIDC_BUF_DPB, + MSM_VIDC_BUF_PERSIST, + MSM_VIDC_BUF_VPSS, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(buf_types); i++) { + buffers = msm_vidc_get_buffers(inst, buf_types[i], __func__); + if (!buffers) + continue; + list_for_each_entry_safe(buf, dummy, &buffers->list, list) { + s_vpr_e(inst->sid, + "destroying buffer: type %d idx %d fd %d addr %#x size %d\n", + buf->type, buf->index, buf->fd, buf->device_addr, buf->buffer_size); + if (is_internal_buffer(buf->type)) + msm_vidc_destroy_internal_buffer(inst, buf); + else + msm_vidc_put_driver_buf(inst, buf); + } + } +} + +static void msm_vidc_close_helper(struct kref *kref) +{ + struct msm_vidc_inst *inst = container_of(kref, + struct msm_vidc_inst, kref); + + s_vpr_h(inst->sid, "%s()\n", __func__); + msm_vidc_event_queue_deinit(inst); + msm_vidc_vb2_queue_deinit(inst); + if (is_decode_session(inst)) + msm_vdec_inst_deinit(inst); + else if (is_encode_session(inst)) + msm_venc_inst_deinit(inst); + kfree(inst->capabilities); + if (inst->input_psc_workq) + destroy_workqueue(inst->input_psc_workq); +} + +struct msm_vidc_inst *get_inst_ref(struct msm_vidc_core *core, + struct msm_vidc_inst *instance) +{ + struct msm_vidc_inst *inst = NULL; + bool matches = false; + + if (!core) { + d_vpr_e("%s: invalid params\n", __func__); + return NULL; + } + + mutex_lock(&core->lock); + list_for_each_entry(inst, &core->instances, list) { + if (inst == instance) { + matches = true; + break; + } + } + inst = (matches && kref_get_unless_zero(&inst->kref)) ? inst : NULL; + mutex_unlock(&core->lock); + return inst; +} + struct msm_vidc_inst *get_inst(struct msm_vidc_core *core, u32 session_id) { @@ -1808,14 +2536,6 @@ struct msm_vidc_inst *get_inst(struct msm_vidc_core *core, return inst; } -static void put_inst_helper(struct kref *kref) -{ - struct msm_vidc_inst *inst = container_of(kref, - struct msm_vidc_inst, kref); - - msm_vidc_close(inst); -} - void put_inst(struct msm_vidc_inst *inst) { if (!inst) { @@ -1823,7 +2543,7 @@ void put_inst(struct msm_vidc_inst *inst) return; } - kref_put(&inst->kref, put_inst_helper); + kref_put(&inst->kref, msm_vidc_close_helper); } void core_lock(struct msm_vidc_core *core, const char *function) diff --git a/driver/vidc/src/msm_vidc_probe.c b/driver/vidc/src/msm_vidc_probe.c index 7086d606ab..a28d88594d 100644 --- a/driver/vidc/src/msm_vidc_probe.c +++ b/driver/vidc/src/msm_vidc_probe.c @@ -20,6 +20,8 @@ #define BASE_DEVICE_NUMBER 32 +struct msm_vidc_core *g_core; + static int msm_vidc_deinit_irq(struct msm_vidc_core *core) { struct msm_vidc_dt *dt; @@ -214,25 +216,15 @@ 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; @@ -249,6 +241,7 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev) core = kzalloc(sizeof(*core), GFP_KERNEL); if (!core) return -ENOMEM; + g_core = core; core->pdev = pdev; dev_set_drvdata(&pdev->dev, core); @@ -379,6 +372,7 @@ static int msm_vidc_remove(struct platform_device *pdev) msm_vidc_deinitialize_core(core); dev_set_drvdata(&pdev->dev, NULL); kfree(core); + g_core = NULL; return 0; } diff --git a/driver/vidc/src/msm_vidc_vb2.c b/driver/vidc/src/msm_vidc_vb2.c index 401ccba14c..8023dd0812 100644 --- a/driver/vidc/src/msm_vidc_vb2.c +++ b/driver/vidc/src/msm_vidc_vb2.c @@ -13,6 +13,30 @@ #include "msm_vidc_debug.h" #include "msm_vidc_control.h" +struct vb2_queue *msm_vidc_get_vb2q(struct msm_vidc_inst *inst, + u32 type, const char *func) +{ + struct vb2_queue *q = NULL; + + if (!inst) { + d_vpr_e("%s: invalid buffer type %d\n", func); + return NULL; + } + if (type == INPUT_MPLANE) { + q = &inst->vb2q[INPUT_PORT]; + } else if (type == OUTPUT_MPLANE) { + q = &inst->vb2q[OUTPUT_PORT]; + } else if (type == INPUT_META_PLANE) { + q = &inst->vb2q[INPUT_META_PORT]; + } else if (type == OUTPUT_META_PLANE) { + q = &inst->vb2q[OUTPUT_META_PORT]; + } else { + s_vpr_e(inst->sid, "%s: invalid buffer type %d\n", + __func__, type); + } + return q; +} + void *msm_vb2_get_userptr(struct device *dev, unsigned long vaddr, unsigned long size, enum dma_data_direction dma_dir) { @@ -72,12 +96,6 @@ int msm_vidc_queue_setup(struct vb2_queue *q, return -EINVAL; if (port == INPUT_PORT) { - if (inst->state == MSM_VIDC_START_INPUT) { - d_vpr_e("%s: input invalid state %d\n", - __func__, inst->state); - return -EINVAL; - } - *num_planes = 1; if (*num_buffers < inst->buffers.input.min_count + inst->buffers.input.extra_count) @@ -86,12 +104,6 @@ int msm_vidc_queue_setup(struct vb2_queue *q, inst->buffers.input.actual_count = *num_buffers; } else if (port == INPUT_META_PORT) { - if (inst->state == MSM_VIDC_START_INPUT) { - d_vpr_e("%s: input_meta invalid state %d\n", - __func__, inst->state); - return -EINVAL; - } - *num_planes = 1; if (*num_buffers < inst->buffers.input_meta.min_count + inst->buffers.input_meta.extra_count) @@ -100,12 +112,6 @@ int msm_vidc_queue_setup(struct vb2_queue *q, inst->buffers.input_meta.actual_count = *num_buffers; } else if (port == OUTPUT_PORT) { - if (inst->state == MSM_VIDC_START_OUTPUT) { - d_vpr_e("%s: output invalid state %d\n", - __func__, inst->state); - return -EINVAL; - } - *num_planes = 1; if (*num_buffers < inst->buffers.output.min_count + inst->buffers.output.extra_count) @@ -114,12 +120,6 @@ int msm_vidc_queue_setup(struct vb2_queue *q, inst->buffers.output.actual_count = *num_buffers; } else if (port == OUTPUT_META_PORT) { - if (inst->state == MSM_VIDC_START_OUTPUT) { - d_vpr_e("%s: output_meta invalid state %d\n", - __func__, inst->state); - return -EINVAL; - } - *num_planes = 1; if (*num_buffers < inst->buffers.output_meta.min_count + inst->buffers.output_meta.extra_count) @@ -174,26 +174,29 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count) if (q->type == INPUT_MPLANE) { if (is_decode_session(inst)) - rc = msm_vdec_start_input(inst); + rc = msm_vdec_streamon_input(inst); else if (is_encode_session(inst)) - rc = msm_venc_start_input(inst); + rc = msm_venc_streamon_input(inst); else goto error; } else if (q->type == OUTPUT_MPLANE) { if (is_decode_session(inst)) - rc = msm_vdec_start_output(inst); + rc = msm_vdec_streamon_output(inst); else if (is_encode_session(inst)) - rc = msm_venc_start_output(inst); + rc = msm_venc_streamon_output(inst); else goto error; } else { + s_vpr_e(inst->sid, "%s: invalid type %d\n", q->type); goto error; } + if (!rc) + s_vpr_h(inst->sid, "Streamon: %d successful\n", q->type); return rc; error: - s_vpr_e(inst->sid, "%s: invalid session/qtype, qtype %d\n", __func__, q->type); + s_vpr_h(inst->sid, "Streamon: %d failed\n", q->type); return -EINVAL; } @@ -225,30 +228,29 @@ void msm_vidc_stop_streaming(struct vb2_queue *q) if (q->type == INPUT_MPLANE) { if (is_decode_session(inst)) - rc = msm_vdec_stop_input(inst); + rc = msm_vdec_streamoff_input(inst); else if (is_encode_session(inst)) - rc = msm_venc_stop_input(inst); + rc = msm_venc_streamoff_input(inst); else goto error; } else if (q->type == OUTPUT_MPLANE) { if (is_decode_session(inst)) - rc = msm_vdec_stop_output(inst); + rc = msm_vdec_streamoff_output(inst); else if (is_encode_session(inst)) - rc = msm_venc_stop_output(inst); + rc = msm_venc_streamoff_output(inst); else goto error; } else { + s_vpr_e(inst->sid, "%s: invalid type %d\n", q->type); goto error; } - if (rc) - s_vpr_e(inst->sid, "%s: stop failed for qtype: %d\n", - __func__, q->type); + if (!rc) + s_vpr_h(inst->sid, "Streamoff: %d successful\n", q->type); return; error: - s_vpr_e(inst->sid, "%s: invalid session/qtype, qtype: %d\n", - __func__, q->type); + s_vpr_e(inst->sid, "Streamoff: %d failed\n", q->type); return; } diff --git a/driver/vidc/src/venus_hfi.c b/driver/vidc/src/venus_hfi.c index 591bda389c..ea5ae830a5 100644 --- a/driver/vidc/src/venus_hfi.c +++ b/driver/vidc/src/venus_hfi.c @@ -2080,7 +2080,7 @@ static void __set_queue_hdr_defaults(struct hfi_queue_header *q_hdr) q_hdr->qhdr_write_idx = 0x0; } -static void __interface_queues_release(struct msm_vidc_core *core) +static void __interface_queues_deinit(struct msm_vidc_core *core) { int i; @@ -2394,7 +2394,7 @@ static void __unload_fw(struct msm_vidc_core *core) qcom_scm_pas_shutdown(core->dt->fw_cookie); core->dt->fw_cookie = 0; - __interface_queues_release(core); + __interface_queues_deinit(core); call_venus_op(core, power_off, core); __deinit_resources(core); @@ -2425,7 +2425,7 @@ irqreturn_t venus_hfi_isr(int irq, void *data) { struct msm_vidc_core *core = data; - d_vpr_e("%s()\n", __func__); + d_vpr_l("%s()\n", __func__); disable_irq_nosync(irq); queue_work(core->device_workq, &core->device_work); @@ -2443,7 +2443,6 @@ void venus_hfi_work_handler(struct work_struct *work) d_vpr_e("%s: invalid params\n", __func__); return; } - d_vpr_e("%s(): core %pK\n", __func__, core); mutex_lock(&core->lock); if (__resume(core)) { @@ -2546,12 +2545,11 @@ int venus_hfi_core_init(struct msm_vidc_core *core) { int rc = 0; - d_vpr_h("%s(): core %p\n", __func__, core); - if (!core) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } + d_vpr_h("%s(): core %pK\n", __func__, core); core->packet_size = 4096; core->packet = kzalloc(core->packet_size, GFP_KERNEL); @@ -2580,27 +2578,49 @@ int venus_hfi_core_init(struct msm_vidc_core *core) if (rc) goto error; - __sys_init(core); - __sys_image_version(core); - __sys_set_debug(core, (msm_vidc_debug & FW_LOGMASK) >> FW_LOGSHIFT); - __enable_subcaches(core); - __set_subcaches(core); + rc = __enable_subcaches(core); + if (rc) + goto error; + + rc = __sys_init(core); + if (rc) + goto error; + + rc = __sys_image_version(core); + if (rc) + goto error; + + rc = __sys_set_debug(core, (msm_vidc_debug & FW_LOGMASK) >> FW_LOGSHIFT); + if (rc) + goto error; + + rc = __set_subcaches(core); + if (rc) + goto error; d_vpr_h("%s(): successful\n", __func__); return 0; error: d_vpr_h("%s(): failed\n", __func__); - __unload_fw(core); - kfree(core->response_packet); - kfree(core->packet); + venus_hfi_core_deinit(core); return rc; } -int venus_hfi_core_release(struct msm_vidc_core *core) +int venus_hfi_core_deinit(struct msm_vidc_core *core) { - d_vpr_h("%s(): core %p\n", __func__, core); - + if (!core) { + d_vpr_h("%s(): invalid params\n", __func__); + return -EINVAL; + } + d_vpr_h("%s(): core %pK\n", __func__, core); + __disable_subcaches(core); + __interface_queues_deinit(core); + __unload_fw(core); + kfree(core->response_packet); + core->response_packet = NULL; + kfree(core->packet); + core->packet = NULL; return 0; } @@ -2867,7 +2887,6 @@ int venus_hfi_queue_buffer(struct msm_vidc_inst *inst, struct msm_vidc_core *core; struct hfi_buffer hfi_buffer; - d_vpr_h("%s(): inst %p\n", __func__, inst); if (!inst || !inst->core || !inst->packet) { d_vpr_e("%s: Invalid params\n", __func__); return -EINVAL; @@ -2927,7 +2946,6 @@ int venus_hfi_release_buffer(struct msm_vidc_inst *inst, struct msm_vidc_core *core; struct hfi_buffer hfi_buffer; - d_vpr_h("%s(): inst %p\n", __func__, inst); if (!inst || !buffer) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; diff --git a/driver/vidc/src/venus_hfi_response.c b/driver/vidc/src/venus_hfi_response.c index 6c3e1b7b2c..fbb1a77f1c 100644 --- a/driver/vidc/src/venus_hfi_response.c +++ b/driver/vidc/src/venus_hfi_response.c @@ -10,6 +10,8 @@ #include "msm_vidc_driver.h" #include "msm_vdec.h" +extern struct msm_vidc_core *g_core; + void print_psc_properties(u32 tag, const char *str, struct msm_vidc_inst *inst, struct msm_vidc_subscription_params subsc_params) { @@ -421,8 +423,6 @@ static int handle_output_buffer(struct msm_vidc_inst *inst, //todo: moved to HFI_PROP_PICTURE_TYPE /*if (buffer->flags & HFI_BUF_FW_FLAG_KEYFRAME) buf->flags |= MSM_VIDC_BUF_FLAG_KEYFRAME;*/ - if (buffer->flags & HFI_BUF_FW_FLAG_LAST) - buf->flags |= MSM_VIDC_BUF_FLAG_LAST; //moved to HFI_INFO_DATA_CORRUPT /*if (buffer->flags & HFI_BUF_FW_FLAG_CORRUPT) buf->flags |= MSM_VIDC_BUF_FLAG_ERROR;*/ @@ -432,6 +432,12 @@ static int handle_output_buffer(struct msm_vidc_inst *inst, /*if (buffer->flags & HFI_BUF_FW_FLAG_SUBFRAME) buf->flags |= MSM_VIDC_BUF_FLAG_SUBFRAME;*/ + if (buffer->flags & HFI_BUF_FW_FLAG_LAST) { + if (msm_vidc_allow_last_flag(inst)) { + buf->flags |= MSM_VIDC_BUF_FLAG_LAST; + msm_vidc_state_change_last_flag(inst); + } + } print_vidc_buffer(VIDC_HIGH, "FBD", inst, buf); return rc; @@ -531,7 +537,9 @@ static int handle_dequeue_buffers(struct msm_vidc_inst* inst) if (buf->attr & MSM_VIDC_ATTR_DEQUEUED) { buf->attr &= ~MSM_VIDC_ATTR_DEQUEUED; msm_vidc_vb2_buffer_done(inst, buf); - msm_vidc_put_driver_buf(inst, buf); + /* do not unmap / delete read only buffer */ + if (!(buf->attr & MSM_VIDC_ATTR_READ_ONLY)) + msm_vidc_put_driver_buf(inst, buf); } } } @@ -962,11 +970,10 @@ exit: return rc; } -static int venus_hfi_input_psc(struct msm_vidc_core *core, - struct work_header *work_hdr) +int handle_session_input_psc(struct msm_vidc_inst *inst, + struct input_psc_work *psc_work) { int rc = 0; - struct msm_vidc_inst *inst; struct hfi_header *hdr = NULL; struct hfi_packet *packet; u8 *pkt, *temp_pkt; @@ -974,32 +981,25 @@ static int venus_hfi_input_psc(struct msm_vidc_core *core, u32 hfi_port = 0; int i; - if (!work_hdr) { + if (!inst || !psc_work) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } - hdr = (struct hfi_header *)work_hdr->data; + hdr = (struct hfi_header *)psc_work->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__)) { + if (validate_packet(pkt, psc_work->data, + psc_work->data_size, __func__)) { rc = -EINVAL; goto exit; } @@ -1034,47 +1034,48 @@ static int venus_hfi_input_psc(struct msm_vidc_core *core, 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; - } - } + 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) +void handle_session_input_psc_work_handler(struct work_struct *work) { - struct msm_vidc_core *core; - struct work_header *work_hdr, *dummy = NULL; + int rc = 0; + struct msm_vidc_inst *inst; + struct input_psc_work *psc_work, *dummy = NULL; - core = container_of(work, struct msm_vidc_core, inst_work.work); - if (!core) { + inst = container_of(work, struct msm_vidc_inst, input_psc_work.work); + inst = get_inst_ref(g_core, inst); + if (!inst) { 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; + mutex_lock(&inst->lock); + list_for_each_entry_safe(psc_work, dummy, &inst->input_psc_works, list) { + rc = msm_vidc_allow_input_psc(inst); + if (!rc) { + rc = handle_session_input_psc(inst, psc_work); + if (!rc) + rc = msm_vidc_state_change_input_psc(inst); + + /* either handle input psc or state change failed */ + if (rc) + msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); } - list_del(&work_hdr->list); - kfree(work_hdr->data); - kfree(work_hdr); + list_del(&psc_work->list); + kfree(psc_work->data); + kfree(psc_work); } + mutex_unlock(&inst->lock); + + put_inst(inst); } static int handle_session_response(struct msm_vidc_core *core, @@ -1110,12 +1111,10 @@ static int handle_session_response(struct msm_vidc_core *core, packet->type < HFI_CMD_END) { if (packet->type == HFI_CMD_SETTINGS_CHANGE && packet->port == HFI_PORT_BITSTREAM) { - struct work_header *work; + struct input_psc_work *work; - work = kzalloc(sizeof(struct work_header), GFP_KERNEL); + work = kzalloc(sizeof(struct input_psc_work), 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) { @@ -1123,9 +1122,9 @@ static int handle_session_response(struct msm_vidc_core *core, 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)); + list_add_tail(&work->list, &inst->input_psc_works); + queue_delayed_work(inst->input_psc_workq, + &inst->input_psc_work, msecs_to_jiffies(0)); goto exit; } if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {