video: driver: add support for instance states

Add support for all the required instance states and
move the states accordingly.

Change-Id: Iac1046ab8c7a0116df6ed3069d566c7a1b65e61c
Signed-off-by: Maheshwar Ajja <majja@codeaurora.org>
This commit is contained in:
Maheshwar Ajja
2020-12-30 08:30:11 -08:00
committed by Darshana Patil
parent 7c203e7bf5
commit 58cd1120ee
18 changed files with 1119 additions and 461 deletions

View File

@@ -9,19 +9,18 @@
#include "msm_vidc_core.h" #include "msm_vidc_core.h"
#include "msm_vidc_inst.h" #include "msm_vidc_inst.h"
int msm_vdec_stop_input(struct msm_vidc_inst *inst); int msm_vdec_streamoff_input(struct msm_vidc_inst *inst);
int msm_vdec_start_input(struct msm_vidc_inst *inst); int msm_vdec_streamon_input(struct msm_vidc_inst *inst);
int msm_vdec_stop_output(struct msm_vidc_inst *inst); int msm_vdec_streamoff_output(struct msm_vidc_inst *inst);
int msm_vdec_start_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_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_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_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_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_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_input_port_settings_change(struct msm_vidc_inst *inst);
int msm_vdec_output_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_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_ #endif // _MSM_VDEC_H_

View File

@@ -9,14 +9,15 @@
#include "msm_vidc_core.h" #include "msm_vidc_core.h"
#include "msm_vidc_inst.h" #include "msm_vidc_inst.h"
int msm_venc_stop_input(struct msm_vidc_inst *inst); int msm_venc_streamoff_input(struct msm_vidc_inst *inst);
int msm_venc_start_input(struct msm_vidc_inst *inst); int msm_venc_streamon_input(struct msm_vidc_inst *inst);
int msm_venc_stop_output(struct msm_vidc_inst *inst); int msm_venc_streamoff_output(struct msm_vidc_inst *inst);
int msm_venc_start_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_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_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_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_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_init(struct msm_vidc_inst *inst);
int msm_venc_inst_deinit(struct msm_vidc_inst *inst);
#endif // _MSM_VENC_H_ #endif // _MSM_VENC_H_

View File

@@ -60,18 +60,6 @@ enum msm_vidc_core_state {
MSM_VIDC_CORE_ERROR = 2, 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 msm_vidc_core {
struct platform_device *pdev; struct platform_device *pdev;
struct msm_video_device vdev[2]; struct msm_video_device vdev[2];
@@ -120,9 +108,6 @@ struct msm_vidc_core {
u32 header_id; u32 header_id;
u32 packet_id; u32 packet_id;
struct completion init_done; 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_ #endif // _MSM_VIDC_CORE_H_

View File

@@ -177,6 +177,7 @@ u32 v4l2_colorformat_from_driver(enum msm_vidc_colorformat_type colorformat,
const char *func); const char *func);
int v4l2_type_to_driver_port(struct msm_vidc_inst *inst, u32 type, int v4l2_type_to_driver_port(struct msm_vidc_inst *inst, u32 type,
const char *func); const char *func);
const char *state_name(enum msm_vidc_inst_state state);
int msm_vidc_change_inst_state(struct msm_vidc_inst *inst, int msm_vidc_change_inst_state(struct msm_vidc_inst *inst,
enum msm_vidc_inst_state state, const char *func); enum msm_vidc_inst_state state, const char *func);
int msm_vidc_get_input_internal_buffers(struct msm_vidc_inst *inst, 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_add_session(struct msm_vidc_inst *inst);
int msm_vidc_session_open(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_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); 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); enum msm_vidc_port_type port);
int msm_vidc_session_close(struct msm_vidc_inst *inst); int msm_vidc_session_close(struct msm_vidc_inst *inst);
int msm_vidc_get_inst_capability(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_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, int msm_vidc_smmu_fault_handler(struct iommu_domain *domain,
struct device *dev, unsigned long iova, int flags, void *data); struct device *dev, unsigned long iova, int flags, void *data);
int msm_vidc_trigger_ssr(struct msm_vidc_core *core, 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_pm_work_handler(struct work_struct *work);
void msm_vidc_fw_unload_handler(struct work_struct *work); void msm_vidc_fw_unload_handler(struct work_struct *work);
void msm_vidc_batch_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_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); 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, u32 msm_vidc_get_buffer_region(struct msm_vidc_inst *inst,
enum msm_vidc_buffer_type buffer_type, const char *func); 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_queue_buffer(struct msm_vidc_inst *inst, struct vb2_buffer *vb2);
int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst, int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buffer); 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 *get_meta_buffer(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *vbuf); 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, struct msm_vidc_inst *get_inst(struct msm_vidc_core *core,
u32 session_id); u32 session_id);
void put_inst(struct msm_vidc_inst *inst); void put_inst(struct msm_vidc_inst *inst);
int msm_vidc_get_mbs_per_frame(struct msm_vidc_inst* inst); bool msm_vidc_allow_s_fmt(struct msm_vidc_inst *inst, u32 type);
int msm_vidc_get_fps(struct msm_vidc_inst* inst); bool msm_vidc_allow_s_ctrl(struct msm_vidc_inst *inst, u32 id);
int msm_vidc_num_queued_bufs(struct msm_vidc_inst* inst, u32 type); 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_lock(struct msm_vidc_core *core, const char *function);
void core_unlock(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); void inst_lock(struct msm_vidc_inst *inst, const char *function);

View File

@@ -34,6 +34,7 @@ struct msm_vidc_allocations_info {
struct msm_vidc_allocations line; struct msm_vidc_allocations line;
struct msm_vidc_allocations dpb; struct msm_vidc_allocations dpb;
struct msm_vidc_allocations persist; struct msm_vidc_allocations persist;
struct msm_vidc_allocations vpss;
}; };
struct msm_vidc_mappings_info { struct msm_vidc_mappings_info {
@@ -48,6 +49,7 @@ struct msm_vidc_mappings_info {
struct msm_vidc_mappings line; struct msm_vidc_mappings line;
struct msm_vidc_mappings dpb; struct msm_vidc_mappings dpb;
struct msm_vidc_mappings persist; struct msm_vidc_mappings persist;
struct msm_vidc_mappings vpss;
}; };
struct msm_vidc_buffers_info { struct msm_vidc_buffers_info {
@@ -62,6 +64,7 @@ struct msm_vidc_buffers_info {
struct msm_vidc_buffers line; struct msm_vidc_buffers line;
struct msm_vidc_buffers dpb; struct msm_vidc_buffers dpb;
struct msm_vidc_buffers persist; struct msm_vidc_buffers persist;
struct msm_vidc_buffers vpss;
}; };
enum msm_vidc_inst_state { enum msm_vidc_inst_state {
@@ -119,6 +122,9 @@ struct msm_vidc_inst {
struct msm_vidc_decode_batch decode_batch; struct msm_vidc_decode_batch decode_batch;
struct msm_vidc_decode_vpp_delay decode_vpp_delay; struct msm_vidc_decode_vpp_delay decode_vpp_delay;
struct msm_vidc_session_idle session_idle; 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 input_ts;
struct list_head enc_input_crs; struct list_head enc_input_crs;
struct list_head decode_bitrate_data; struct list_head decode_bitrate_data;

View File

@@ -708,6 +708,12 @@ struct msm_vidc_buffers {
bool reuse; bool reuse;
}; };
struct input_psc_work {
struct list_head list;
void *data;
u32 data_size;
};
struct msm_vidc_ssr { struct msm_vidc_ssr {
bool trigger; bool trigger;
enum msm_vidc_ssr_trigger_type ssr_type; enum msm_vidc_ssr_trigger_type ssr_type;

View File

@@ -8,6 +8,10 @@
#include <media/videobuf2-core.h> #include <media/videobuf2-core.h>
#include <media/videobuf2-v4l2.h> #include <media/videobuf2-v4l2.h>
#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 */ /* vb2_mem_ops */
void *msm_vb2_get_userptr(struct device *dev, unsigned long vaddr, void *msm_vb2_get_userptr(struct device *dev, unsigned long vaddr,

View File

@@ -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_open(struct msm_vidc_inst *inst);
int venus_hfi_session_set_codec(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_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_suspend(struct msm_vidc_core *core);
int venus_hfi_scale_clocks(struct msm_vidc_inst* inst, u64 freq); 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); 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_work_handler(struct work_struct *work);
void venus_hfi_pm_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); irqreturn_t venus_hfi_isr(int irq, void *data);
void __write_register(struct msm_vidc_core *core, void __write_register(struct msm_vidc_core *core,

View File

@@ -14,5 +14,8 @@ bool is_valid_port(struct msm_vidc_inst *inst, u32 port,
const char *func); const char *func);
bool is_valid_hfi_buffer_type(struct msm_vidc_inst *inst, bool is_valid_hfi_buffer_type(struct msm_vidc_inst *inst,
u32 buffer_type, const char *func); 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__ #endif // __VENUS_HFI_RESPONSE_H__

View File

@@ -1158,7 +1158,7 @@ int msm_vdec_output_port_settings_change(struct msm_vidc_inst *inst)
return 0; 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; int rc = 0;
@@ -1167,31 +1167,28 @@ int msm_vdec_stop_input(struct msm_vidc_inst *inst)
return -EINVAL; return -EINVAL;
} }
rc = msm_vidc_session_stop(inst, INPUT_PORT); rc = msm_vidc_session_streamoff(inst, INPUT_PORT);
if (rc) if (rc)
return rc; return rc;
return 0; 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; int rc = 0;
struct msm_vidc_core *core;
if (!inst || !inst->core) { if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
core = inst->core;
s_vpr_h(inst->sid, "%s()\n", __func__);
if (is_input_meta_enabled(inst) && if (is_input_meta_enabled(inst) &&
!inst->vb2q[INPUT_META_PORT].streaming) { !inst->vb2q[INPUT_META_PORT].streaming) {
s_vpr_e(inst->sid, s_vpr_e(inst->sid,
"%s: Meta port must be streamed on before data port\n", "%s: Meta port must be streamed on before data port\n",
__func__); __func__);
goto error; return -EINVAL;
} }
//rc = msm_vidc_check_session_supported(inst); //rc = msm_vidc_check_session_supported(inst);
@@ -1244,20 +1241,19 @@ int msm_vdec_start_input(struct msm_vidc_inst *inst)
if (rc) if (rc)
return rc; return rc;
rc = msm_vidc_session_start(inst, INPUT_PORT); rc = msm_vidc_session_streamon(inst, INPUT_PORT);
if (rc) if (rc)
goto error; goto error;
s_vpr_h(inst->sid, "%s: done\n", __func__);
return 0; return 0;
error: error:
s_vpr_e(inst->sid, "%s: failed\n", __func__); s_vpr_e(inst->sid, "%s: failed\n", __func__);
msm_vdec_stop_input(inst); msm_vdec_streamoff_input(inst);
return rc; 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; int rc = 0;
@@ -1266,7 +1262,7 @@ int msm_vdec_stop_output(struct msm_vidc_inst *inst)
return -EINVAL; return -EINVAL;
} }
rc = msm_vidc_session_stop(inst, OUTPUT_PORT); rc = msm_vidc_session_streamoff(inst, OUTPUT_PORT);
if (rc) if (rc)
return rc; return rc;
@@ -1385,11 +1381,10 @@ static int msm_vdec_subscribe_output_port_settings_change(struct msm_vidc_inst *
return rc; 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; int rc = 0;
d_vpr_h("%s()\n", __func__);
if (!inst || !inst->core) { if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
@@ -1400,7 +1395,7 @@ int msm_vdec_start_output(struct msm_vidc_inst *inst)
s_vpr_e(inst->sid, s_vpr_e(inst->sid,
"%s: Meta port must be streamed on before data port\n", "%s: Meta port must be streamed on before data port\n",
__func__); __func__);
goto error; return -EINVAL;
} }
rc = msm_vdec_set_output_properties(inst); 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) { if (!inst->opsc_properties_set) {
memcpy(&inst->subcr_params[OUTPUT_PORT], 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); rc = msm_vdec_subscribe_output_port_settings_change(inst, OUTPUT_PORT);
if (rc) if (rc)
return rc; goto error;
inst->opsc_properties_set = true; inst->opsc_properties_set = true;
} }
rc = msm_vdec_subscribe_metadata(inst, OUTPUT_PORT); rc = msm_vdec_subscribe_metadata(inst, OUTPUT_PORT);
if (rc) if (rc)
return rc; goto error;
rc = msm_vidc_session_start(inst, OUTPUT_PORT); rc = msm_vidc_session_streamon(inst, OUTPUT_PORT);
if (rc) if (rc)
goto error; goto error;
d_vpr_h("%s: done\n", __func__);
return 0; return 0;
error: error:
msm_vdec_stop_output(inst); s_vpr_e(inst->sid, "%s: failed\n", __func__);
msm_vdec_streamoff_output(inst);
return rc; 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 (cmd == V4L2_DEC_CMD_STOP) {
if (!msm_vidc_allow_stop(inst))
return -EBUSY;
rc = venus_hfi_session_command(inst, rc = venus_hfi_session_command(inst,
HFI_CMD_DRAIN, HFI_CMD_DRAIN,
INPUT_PORT, INPUT_PORT,
@@ -1476,6 +1474,23 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
0); 0);
if (rc) if (rc)
return 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 { } else {
d_vpr_e("%s: unknown cmd %d\n", __func__, cmd); d_vpr_e("%s: unknown cmd %d\n", __func__, cmd);
return -EINVAL; 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 msm_vidc_core *core;
struct v4l2_format *fmt; struct v4l2_format *fmt;
d_vpr_h("%s()\n", __func__);
if (!inst || !inst->core) { if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
core = inst->core; 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 (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 != if (inst->fmts[INPUT_PORT].fmt.pix_mp.pixelformat !=
f->fmt.pix_mp.pixelformat) { f->fmt.pix_mp.pixelformat) {
s_vpr_e(inst->sid, 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); //msm_vidc_update_batching(inst);
} else if (f->type == INPUT_META_PLANE) { } 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 = &inst->fmts[INPUT_META_PORT];
fmt->type = INPUT_META_PLANE; fmt->type = INPUT_META_PLANE;
fmt->fmt.meta.dataformat = V4L2_META_FMT_VIDC; 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.min_count,
inst->buffers.input_meta.extra_count); inst->buffers.input_meta.extra_count);
} else if (f->type == OUTPUT_MPLANE) { } 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 = &inst->fmts[OUTPUT_PORT];
fmt->type = OUTPUT_MPLANE; fmt->type = OUTPUT_MPLANE;
fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat; 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.min_count,
inst->buffers.output.extra_count); inst->buffers.output.extra_count);
} else if (f->type == OUTPUT_META_PLANE) { } 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 = &inst->fmts[OUTPUT_META_PORT];
fmt->type = OUTPUT_META_PLANE; fmt->type = OUTPUT_META_PLANE;
fmt->fmt.meta.dataformat = V4L2_META_FMT_VIDC; 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 rc = 0;
int port; int port;
d_vpr_h("%s()\n", __func__);
if (!inst) { if (!inst) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
@@ -1767,7 +1759,6 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst)
struct msm_vidc_core *core; struct msm_vidc_core *core;
struct v4l2_format *f; struct v4l2_format *f;
d_vpr_h("%s()\n", __func__);
if (!inst || !inst->core) { if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
@@ -1850,3 +1841,16 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst)
return rc; 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;
}

View File

@@ -701,7 +701,7 @@ static int msm_venc_metadata_subscription(struct msm_vidc_inst *inst,
return rc; 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; int rc = 0;
@@ -710,31 +710,28 @@ int msm_venc_stop_input(struct msm_vidc_inst *inst)
return -EINVAL; return -EINVAL;
} }
rc = msm_vidc_session_stop(inst, INPUT_PORT); rc = msm_vidc_session_streamoff(inst, INPUT_PORT);
if (rc) if (rc)
return rc; return rc;
return 0; 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; int rc = 0;
struct msm_vidc_core *core;
if (!inst || !inst->core) { if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
core = inst->core;
s_vpr_h(inst->sid, "%s()\n", __func__);
if (is_input_meta_enabled(inst) && if (is_input_meta_enabled(inst) &&
!inst->vb2q[INPUT_META_PORT].streaming) { !inst->vb2q[INPUT_META_PORT].streaming) {
s_vpr_e(inst->sid, s_vpr_e(inst->sid,
"%s: Meta port must be streamed on before data port\n", "%s: Meta port must be streamed on before data port\n",
__func__); __func__);
goto error; return -EINVAL;
} }
//rc = msm_vidc_check_session_supported(inst); //rc = msm_vidc_check_session_supported(inst);
@@ -780,16 +777,15 @@ int msm_venc_start_input(struct msm_vidc_inst *inst)
if (rc) if (rc)
return rc; return rc;
rc = msm_vidc_session_start(inst, INPUT_PORT); rc = msm_vidc_session_streamon(inst, INPUT_PORT);
if (rc) if (rc)
goto error; goto error;
s_vpr_h(inst->sid, "%s: done\n", __func__);
return 0; return 0;
error: error:
s_vpr_e(inst->sid, "%s: failed\n", __func__); s_vpr_e(inst->sid, "%s: failed\n", __func__);
msm_venc_stop_input(inst); msm_venc_streamoff_input(inst);
return rc; 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 (cmd == V4L2_ENC_CMD_STOP) {
if (!msm_vidc_allow_stop(inst))
return -EBUSY;
rc = venus_hfi_session_command(inst, rc = venus_hfi_session_command(inst,
HFI_CMD_DRAIN, HFI_CMD_DRAIN,
INPUT_PORT, INPUT_PORT,
@@ -811,6 +809,17 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
0); 0);
if (rc) if (rc)
return 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 { } else {
d_vpr_e("%s: unknown cmd %d\n", __func__, cmd); d_vpr_e("%s: unknown cmd %d\n", __func__, cmd);
return -EINVAL; return -EINVAL;
@@ -818,7 +827,7 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
return 0; 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; int rc = 0;
@@ -827,18 +836,17 @@ int msm_venc_stop_output(struct msm_vidc_inst *inst)
return -EINVAL; return -EINVAL;
} }
rc = msm_vidc_session_stop(inst, OUTPUT_PORT); rc = msm_vidc_session_streamoff(inst, OUTPUT_PORT);
if (rc) if (rc)
return rc; return rc;
return 0; 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; int rc = 0;
d_vpr_h("%s()\n", __func__);
if (!inst || !inst->core) { if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
@@ -849,7 +857,7 @@ int msm_venc_start_output(struct msm_vidc_inst *inst)
s_vpr_e(inst->sid, s_vpr_e(inst->sid,
"%s: Meta port must be streamed on before data port\n", "%s: Meta port must be streamed on before data port\n",
__func__); __func__);
goto error; return -EINVAL;
} }
rc = msm_venc_set_output_properties(inst); 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); rc = msm_vidc_adjust_v4l2_properties(inst);
if (rc) if (rc)
return -EINVAL; goto error;
rc = msm_vidc_set_v4l2_properties(inst); rc = msm_vidc_set_v4l2_properties(inst);
if (rc) if (rc)
return -EINVAL; goto error;
rc = msm_venc_set_internal_properties(inst); rc = msm_venc_set_internal_properties(inst);
if (rc) if (rc)
@@ -870,21 +878,21 @@ int msm_venc_start_output(struct msm_vidc_inst *inst)
rc = msm_venc_property_subscription(inst, OUTPUT_PORT); rc = msm_venc_property_subscription(inst, OUTPUT_PORT);
if (rc) if (rc)
return rc; goto error;
rc = msm_venc_metadata_subscription(inst, OUTPUT_PORT); rc = msm_venc_metadata_subscription(inst, OUTPUT_PORT);
if (rc) if (rc)
return rc; goto error;
rc = msm_vidc_session_start(inst, OUTPUT_PORT); rc = msm_vidc_session_streamon(inst, OUTPUT_PORT);
if (rc) if (rc)
goto error; goto error;
d_vpr_h("%s: done\n", __func__);
return 0; return 0;
error: error:
msm_venc_stop_output(inst); s_vpr_e(inst->sid, "%s: failed\n", __func__);
msm_venc_streamoff_output(inst);
return rc; 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 msm_vidc_core *core;
struct v4l2_format *fmt; struct v4l2_format *fmt;
d_vpr_h("%s()\n", __func__);
if (!inst || !inst->core) { if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
core = inst->core; 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 (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 = &inst->fmts[INPUT_PORT];
fmt->type = INPUT_MPLANE; fmt->type = INPUT_MPLANE;
fmt->fmt.pix_mp.pixelformat = f->fmt.pix_mp.pixelformat; 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); //msm_vidc_update_batching(inst);
} else if (f->type == INPUT_META_PLANE) { } 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 = &inst->fmts[INPUT_META_PORT];
fmt->type = INPUT_META_PLANE; fmt->type = INPUT_META_PLANE;
fmt->fmt.meta.dataformat = V4L2_META_FMT_VIDC; 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.min_count,
inst->buffers.input_meta.extra_count); inst->buffers.input_meta.extra_count);
} else if (f->type == OUTPUT_MPLANE) { } 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 = &inst->fmts[OUTPUT_PORT];
if (fmt->fmt.pix_mp.pixelformat != f->fmt.pix_mp.pixelformat) { if (fmt->fmt.pix_mp.pixelformat != f->fmt.pix_mp.pixelformat) {
s_vpr_e(inst->sid, 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.min_count,
inst->buffers.output.extra_count); inst->buffers.output.extra_count);
} else if (f->type == OUTPUT_META_PLANE) { } 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 = &inst->fmts[OUTPUT_META_PORT];
fmt->type = OUTPUT_META_PLANE; fmt->type = OUTPUT_META_PLANE;
fmt->fmt.meta.dataformat = V4L2_META_FMT_VIDC; 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 rc = 0;
int port; int port;
d_vpr_h("%s()\n", __func__);
if (!inst) { if (!inst) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
@@ -1265,3 +1250,16 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst)
return rc; 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;
}

View File

@@ -15,6 +15,7 @@
#include "msm_vidc_debug.h" #include "msm_vidc_debug.h"
#include "msm_vidc_control.h" #include "msm_vidc_control.h"
#include "msm_vidc_power.h" #include "msm_vidc_power.h"
#include "venus_hfi_response.h"
#define MSM_VIDC_DRV_NAME "msm_vidc_driver" #define MSM_VIDC_DRV_NAME "msm_vidc_driver"
/* kernel/msm-4.19 */ /* 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__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; 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->event_handler.wait, wait);
poll_wait(filp, &inst->vb2q[INPUT_META_PORT].done_wq, 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; return -EINVAL;
} }
if (f->type == INPUT_MPLANE) { if (!msm_vidc_allow_s_fmt(inst, f->type))
if (inst->state != MSM_VIDC_OPEN && return -EBUSY;
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 (inst->domain == MSM_VIDC_DECODER) if (inst->domain == MSM_VIDC_DECODER)
rc = msm_vdec_s_fmt(inst, f); 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); rc = msm_vdec_g_fmt(inst, f);
if (inst->domain == MSM_VIDC_ENCODER) if (inst->domain == MSM_VIDC_ENCODER)
rc = msm_venc_g_fmt(inst, f); 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); EXPORT_SYMBOL(msm_vidc_g_fmt);
@@ -273,6 +272,9 @@ int msm_vidc_s_ctrl(void *instance, struct v4l2_control *control)
if (!inst || !control) if (!inst || !control)
return -EINVAL; return -EINVAL;
if (!msm_vidc_allow_s_ctrl(inst, control->id))
return -EBUSY;
return v4l2_s_ctrl(NULL, &inst->ctrl_handler, control); return v4l2_s_ctrl(NULL, &inst->ctrl_handler, control);
} }
EXPORT_SYMBOL(msm_vidc_s_ctrl); EXPORT_SYMBOL(msm_vidc_s_ctrl);
@@ -316,25 +318,9 @@ int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b)
mutex_lock(&inst->lock); mutex_lock(&inst->lock);
if (b->type == INPUT_MPLANE) { if (!msm_vidc_allow_reqbufs(inst, b->type)) {
if (inst->state != MSM_VIDC_OPEN && rc = -EBUSY;
inst->state != MSM_VIDC_START_OUTPUT) { goto unlock;
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;
}
} }
port = v4l2_type_to_driver_port(inst, b->type, __func__); 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); mutex_lock(&inst->lock);
if (inst->state == MSM_VIDC_ERROR) { if (!msm_vidc_allow_qbuf(inst)) {
s_vpr_e(inst->sid, "%s: error state\n", __func__); rc = -EBUSY;
rc = -EINVAL;
goto unlock; goto unlock;
} }
if (b->type == INPUT_MPLANE) {
q = &inst->vb2q[INPUT_PORT]; q = msm_vidc_get_vb2q(inst, b->type, __func__);
} else if (b->type == OUTPUT_MPLANE) { if (!q) {
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);
rc = -EINVAL; rc = -EINVAL;
goto unlock; goto unlock;
} }
@@ -412,17 +389,9 @@ int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
} }
mutex_lock(&inst->lock); mutex_lock(&inst->lock);
if (b->type == INPUT_MPLANE) {
q = &inst->vb2q[INPUT_PORT]; q = msm_vidc_get_vb2q(inst, b->type, __func__);
} else if (b->type == OUTPUT_MPLANE) { if (!q) {
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);
rc = -EINVAL; rc = -EINVAL;
goto unlock; goto unlock;
} }
@@ -445,7 +414,6 @@ int msm_vidc_streamon(void *instance, enum v4l2_buf_type type)
{ {
int rc = 0; int rc = 0;
struct msm_vidc_inst *inst = instance; struct msm_vidc_inst *inst = instance;
enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR;
int port; int port;
if (!inst) { if (!inst) {
@@ -455,26 +423,13 @@ int msm_vidc_streamon(void *instance, enum v4l2_buf_type type)
mutex_lock(&inst->lock); mutex_lock(&inst->lock);
if (type == INPUT_MPLANE) { if (!msm_vidc_allow_streamon(inst, type)) {
if (inst->state != MSM_VIDC_OPEN && rc = -EBUSY;
inst->state != MSM_VIDC_START_OUTPUT) { goto unlock;
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;
}
} }
rc = msm_vidc_state_change_streamon(inst, type);
if (rc)
goto unlock;
port = v4l2_type_to_driver_port(inst, type, __func__); port = v4l2_type_to_driver_port(inst, type, __func__);
if (port < 0) { if (port < 0) {
@@ -486,34 +441,10 @@ int msm_vidc_streamon(void *instance, enum v4l2_buf_type type)
if (rc) { if (rc) {
s_vpr_e(inst->sid, "%s: vb2_streamon(%d) failed, %d\n", s_vpr_e(inst->sid, "%s: vb2_streamon(%d) failed, %d\n",
__func__, type, rc); __func__, type, rc);
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
goto unlock; 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: unlock:
mutex_unlock(&inst->lock); mutex_unlock(&inst->lock);
return rc; return rc;
@@ -524,7 +455,6 @@ int msm_vidc_streamoff(void *instance, enum v4l2_buf_type type)
{ {
int rc = 0; int rc = 0;
struct msm_vidc_inst *inst = instance; struct msm_vidc_inst *inst = instance;
enum msm_vidc_inst_state new_state = MSM_VIDC_ERROR;
int port; int port;
if (!inst) { if (!inst) {
@@ -534,25 +464,13 @@ int msm_vidc_streamoff(void *instance, enum v4l2_buf_type type)
mutex_lock(&inst->lock); mutex_lock(&inst->lock);
if (type == INPUT_MPLANE) { if (!msm_vidc_allow_streamoff(inst, type)) {
if (inst->state == MSM_VIDC_OPEN || rc = -EBUSY;
inst->state == MSM_VIDC_START_OUTPUT) { goto unlock;
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;
}
} }
rc = msm_vidc_state_change_streamoff(inst, type);
if (rc)
goto unlock;
port = v4l2_type_to_driver_port(inst, type, __func__); port = v4l2_type_to_driver_port(inst, type, __func__);
if (port < 0) { if (port < 0) {
@@ -564,45 +482,10 @@ int msm_vidc_streamoff(void *instance, enum v4l2_buf_type type)
if (rc) { if (rc) {
s_vpr_e(inst->sid, "%s: vb2_streamoff(%d) failed, %d\n", s_vpr_e(inst->sid, "%s: vb2_streamoff(%d) failed, %d\n",
__func__, type, rc); __func__, type, rc);
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
goto unlock; 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: unlock:
mutex_unlock(&inst->lock); mutex_unlock(&inst->lock);
return rc; return rc;
@@ -740,8 +623,10 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
if (core->state == MSM_VIDC_CORE_DEINIT) { if (core->state == MSM_VIDC_CORE_DEINIT) {
rc = msm_vidc_core_init(core); rc = msm_vidc_core_init(core);
if (rc) if (rc) {
msm_vidc_core_deinit(core);
return NULL; return NULL;
}
} }
inst = kzalloc(sizeof(*inst), GFP_KERNEL); inst = kzalloc(sizeof(*inst), GFP_KERNEL);
@@ -750,25 +635,34 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
return NULL; return NULL;
} }
inst->core = core; 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( inst->capabilities = kzalloc(
sizeof(struct msm_vidc_inst_capability), GFP_KERNEL); sizeof(struct msm_vidc_inst_capability), GFP_KERNEL);
if (!inst->capabilities) { if (!inst->capabilities) {
s_vpr_e(inst->sid, s_vpr_e(inst->sid,
"%s: inst capability allocation failed\n", __func__); "%s: inst capability allocation failed\n", __func__);
return NULL; goto error;
} }
rc = msm_vidc_add_session(inst); INIT_DELAYED_WORK(&inst->input_psc_work,
if (rc) { handle_session_input_psc_work_handler);
d_vpr_e("%s: failed to get session id\n", __func__);
return NULL;
}
s_vpr_i(inst->sid, "Opening video instance: %d\n", session_type); INIT_LIST_HEAD(&inst->input_psc_works);
kref_init(&inst->kref);
mutex_init(&inst->lock);
INIT_LIST_HEAD(&inst->buffers.input.list); INIT_LIST_HEAD(&inst->buffers.input.list);
INIT_LIST_HEAD(&inst->buffers.input_meta.list); INIT_LIST_HEAD(&inst->buffers.input_meta.list);
INIT_LIST_HEAD(&inst->buffers.output.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.line.list);
INIT_LIST_HEAD(&inst->buffers.dpb.list); INIT_LIST_HEAD(&inst->buffers.dpb.list);
INIT_LIST_HEAD(&inst->buffers.persist.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.bin.list);
INIT_LIST_HEAD(&inst->allocations.arp.list); INIT_LIST_HEAD(&inst->allocations.arp.list);
INIT_LIST_HEAD(&inst->allocations.comv.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.line.list);
INIT_LIST_HEAD(&inst->allocations.dpb.list); INIT_LIST_HEAD(&inst->allocations.dpb.list);
INIT_LIST_HEAD(&inst->allocations.persist.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.list);
INIT_LIST_HEAD(&inst->mappings.input_meta.list); INIT_LIST_HEAD(&inst->mappings.input_meta.list);
INIT_LIST_HEAD(&inst->mappings.output.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.line.list);
INIT_LIST_HEAD(&inst->mappings.dpb.list); INIT_LIST_HEAD(&inst->mappings.dpb.list);
INIT_LIST_HEAD(&inst->mappings.persist.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->children.list);
INIT_LIST_HEAD(&inst->firmware.list); INIT_LIST_HEAD(&inst->firmware.list);
inst->domain = session_type; inst->domain = session_type;
@@ -812,21 +709,18 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
//inst->debugfs_root = //inst->debugfs_root =
// msm_vidc_debugfs_init_inst(inst, core->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); rc = msm_vdec_inst_init(inst);
if (rc) else if (is_encode_session(inst))
goto error;
} else if (is_encode_session(inst)) {
rc = msm_venc_inst_init(inst); rc = msm_venc_inst_init(inst);
if (rc) if (rc)
goto error; goto error;
}
rc = msm_vidc_vb2_queue_init(inst); rc = msm_vidc_vb2_queue_init(inst);
if (rc) if (rc)
goto error; goto error;
rc = msm_vidc_setup_event_queue(inst); rc = msm_vidc_event_queue_init(inst);
if (rc) if (rc)
goto error; goto error;
@@ -854,9 +748,12 @@ int msm_vidc_close(void *instance)
return -EINVAL; return -EINVAL;
} }
s_vpr_h(inst->sid, "%s()\n", __func__); s_vpr_h(inst->sid, "%s()\n", __func__);
mutex_lock(&inst->lock);
msm_vidc_session_close(inst); msm_vidc_session_close(inst);
msm_vidc_remove_session(inst); msm_vidc_remove_session(inst);
msm_vidc_destroy_buffers(inst);
mutex_unlock(&inst->lock);
put_inst(inst);
return rc; return rc;
} }
EXPORT_SYMBOL(msm_vidc_close); EXPORT_SYMBOL(msm_vidc_close);

View File

@@ -346,7 +346,7 @@ int msm_vidc_ctrl_deinit(struct msm_vidc_inst *inst)
d_vpr_e("%s: invalid parameters\n", __func__); d_vpr_e("%s: invalid parameters\n", __func__);
return -EINVAL; return -EINVAL;
} }
s_vpr_h(inst->sid, "%s(): num ctrls %d\n", __func__, inst->num_ctrls);
v4l2_ctrl_handler_free(&inst->ctrl_handler); v4l2_ctrl_handler_free(&inst->ctrl_handler);
kfree(inst->ctrls); kfree(inst->ctrls);
@@ -362,7 +362,6 @@ int msm_vidc_ctrl_init(struct msm_vidc_inst *inst)
struct v4l2_ctrl_config ctrl_cfg = {0}; struct v4l2_ctrl_config ctrl_cfg = {0};
int num_ctrls = 0, ctrl_idx = 0; int num_ctrls = 0, ctrl_idx = 0;
d_vpr_h("%s()\n", __func__);
if (!inst || !inst->core || !inst->capabilities) { if (!inst || !inst->core || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
@@ -497,6 +496,7 @@ int msm_vidc_ctrl_init(struct msm_vidc_inst *inst)
ctrl_idx++; ctrl_idx++;
} }
inst->num_ctrls = num_ctrls; inst->num_ctrls = num_ctrls;
s_vpr_h(inst->sid, "%s(): num ctrls %d\n", __func__, inst->num_ctrls);
return rc; return rc;
} }

View File

@@ -14,8 +14,11 @@
#include "msm_vidc_memory.h" #include "msm_vidc_memory.h"
#include "msm_vidc_debug.h" #include "msm_vidc_debug.h"
#include "msm_vidc_power.h" #include "msm_vidc_power.h"
#include "venus_hfi.h"
#include "msm_vidc.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) { \ #define COUNT_BITS(a, out) { \
while ((a) >= 1) { \ while ((a) >= 1) { \
@@ -345,6 +348,8 @@ struct msm_vidc_buffers *msm_vidc_get_buffers(
return &inst->buffers.dpb; return &inst->buffers.dpb;
case MSM_VIDC_BUF_PERSIST: case MSM_VIDC_BUF_PERSIST:
return &inst->buffers.persist; return &inst->buffers.persist;
case MSM_VIDC_BUF_VPSS:
return &inst->buffers.vpss;
default: default:
s_vpr_e(inst->sid, "%s: invalid driver buffer type %d\n", s_vpr_e(inst->sid, "%s: invalid driver buffer type %d\n",
func, buffer_type); func, buffer_type);
@@ -379,6 +384,8 @@ struct msm_vidc_mappings *msm_vidc_get_mappings(
return &inst->mappings.dpb; return &inst->mappings.dpb;
case MSM_VIDC_BUF_PERSIST: case MSM_VIDC_BUF_PERSIST:
return &inst->mappings.persist; return &inst->mappings.persist;
case MSM_VIDC_BUF_VPSS:
return &inst->mappings.vpss;
default: default:
s_vpr_e(inst->sid, "%s: invalid driver buffer type %d\n", s_vpr_e(inst->sid, "%s: invalid driver buffer type %d\n",
func, buffer_type); func, buffer_type);
@@ -405,6 +412,8 @@ struct msm_vidc_allocations *msm_vidc_get_allocations(
return &inst->allocations.dpb; return &inst->allocations.dpb;
case MSM_VIDC_BUF_PERSIST: case MSM_VIDC_BUF_PERSIST:
return &inst->allocations.persist; return &inst->allocations.persist;
case MSM_VIDC_BUF_VPSS:
return &inst->allocations.vpss;
default: default:
s_vpr_e(inst->sid, "%s: invalid driver buffer type %d\n", s_vpr_e(inst->sid, "%s: invalid driver buffer type %d\n",
func, buffer_type); 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, int msm_vidc_change_inst_state(struct msm_vidc_inst *inst,
enum msm_vidc_inst_state request_state, const char *func) 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) { if (inst->state == MSM_VIDC_ERROR) {
s_vpr_h(inst->sid, s_vpr_h(inst->sid,
"%s: inst is in bad state, can not change state to %d\n", "%s: inst is in bad state, can not change state to %s\n",
func, request_state); func, state_name(request_state));
return 0; return 0;
} }
s_vpr_h(inst->sid, "%s: state changed from %d to %d\n", s_vpr_h(inst->sid, "%s: state changed from %s to %s\n",
func, inst->state, request_state); func, state_name(inst->state), state_name(request_state));
inst->state = request_state; inst->state = request_state;
return 0; 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 msm_vidc_get_control(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
{ {
int rc = 0; int rc = 0;
@@ -602,10 +1174,6 @@ int msm_vidc_put_driver_buf(struct msm_vidc_inst *inst,
return -EINVAL; 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); rc = msm_vidc_unmap_driver_buf(inst, buf);
if (rc) if (rc)
return rc; return rc;
@@ -1218,20 +1786,18 @@ int msm_vidc_vb2_buffer_done(struct msm_vidc_inst *inst,
return 0; 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 rc = 0;
int index; int index;
struct msm_vidc_core *core; struct msm_vidc_core *core;
d_vpr_h("%s()\n", __func__);
if (!inst || !inst->core) { if (!inst || !inst->core) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
core = inst->core; core = inst->core;
// TODO: check decode is index = 0 and encode is index 1
if (is_decode_session(inst)) if (is_decode_session(inst))
index = 0; index = 0;
else if (is_encode_session(inst)) else if (is_encode_session(inst))
@@ -1245,9 +1811,25 @@ int msm_vidc_setup_event_queue(struct msm_vidc_inst *inst)
return rc; 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, static int vb2q_init(struct msm_vidc_inst *inst,
struct vb2_queue *q, enum v4l2_buf_type type) struct vb2_queue *q, enum v4l2_buf_type type)
{ {
int rc = 0;
struct msm_vidc_core *core; struct msm_vidc_core *core;
if (!inst || !q || !inst->core) { if (!inst || !q || !inst->core) {
@@ -1264,14 +1846,17 @@ static int vb2q_init(struct msm_vidc_inst *inst,
q->drv_priv = inst; q->drv_priv = inst;
q->allow_zero_bytesused = 1; q->allow_zero_bytesused = 1;
q->copy_timestamp = 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 msm_vidc_vb2_queue_init(struct msm_vidc_inst *inst)
{ {
int rc = 0; int rc = 0;
d_vpr_h("%s()\n", __func__);
if (!inst) { if (!inst) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
@@ -1296,6 +1881,22 @@ int msm_vidc_vb2_queue_init(struct msm_vidc_inst *inst)
return rc; 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 msm_vidc_add_session(struct msm_vidc_inst *inst)
{ {
int rc = 0; int rc = 0;
@@ -1388,7 +1989,7 @@ int msm_vidc_session_set_codec(struct msm_vidc_inst *inst)
return 0; 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) enum msm_vidc_port_type port)
{ {
int rc = 0; int rc = 0;
@@ -1407,7 +2008,7 @@ int msm_vidc_session_start(struct msm_vidc_inst* inst,
return rc; 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) enum msm_vidc_port_type port)
{ {
int rc = 0; int rc = 0;
@@ -1433,9 +2034,9 @@ int msm_vidc_session_stop(struct msm_vidc_inst *inst,
return rc; return rc;
core = inst->core; core = inst->core;
mutex_unlock(&inst->lock);
s_vpr_h(inst->sid, "%s: wait on port: %d for time: %d ms\n", s_vpr_h(inst->sid, "%s: wait on port: %d for time: %d ms\n",
__func__, port, core->capabilities[HW_RESPONSE_TIMEOUT].value); __func__, port, core->capabilities[HW_RESPONSE_TIMEOUT].value);
mutex_unlock(&inst->lock);
rc = wait_for_completion_timeout( rc = wait_for_completion_timeout(
&inst->completions[signal_type], &inst->completions[signal_type],
msecs_to_jiffies( msecs_to_jiffies(
@@ -1472,10 +2073,12 @@ int msm_vidc_session_close(struct msm_vidc_inst *inst)
core = inst->core; core = inst->core;
s_vpr_h(inst->sid, "%s: wait on close for time: %d ms\n", s_vpr_h(inst->sid, "%s: wait on close for time: %d ms\n",
__func__, core->capabilities[HW_RESPONSE_TIMEOUT].value); __func__, core->capabilities[HW_RESPONSE_TIMEOUT].value);
mutex_unlock(&inst->lock);
rc = wait_for_completion_timeout( rc = wait_for_completion_timeout(
&inst->completions[SIGNAL_CMD_CLOSE], &inst->completions[SIGNAL_CMD_CLOSE],
msecs_to_jiffies( msecs_to_jiffies(
core->capabilities[HW_RESPONSE_TIMEOUT].value)); core->capabilities[HW_RESPONSE_TIMEOUT].value));
mutex_lock(&inst->lock);
if (!rc) { if (!rc) {
s_vpr_e(inst->sid, "%s: session close timed out\n", __func__); s_vpr_e(inst->sid, "%s: session close timed out\n", __func__);
//msm_comm_kill_session(inst); //msm_comm_kill_session(inst);
@@ -1519,6 +2122,20 @@ int msm_vidc_get_inst_capability(struct msm_vidc_inst *inst)
return rc; 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) static int msm_vidc_init_core_caps(struct msm_vidc_core *core)
{ {
int rc = 0; int rc = 0;
@@ -1563,6 +2180,8 @@ static int msm_vidc_init_core_caps(struct msm_vidc_core *core)
} }
exit: exit:
if (rc)
msm_vidc_deinit_core_caps(core);
return rc; 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) static int msm_vidc_init_instance_caps(struct msm_vidc_core *core)
{ {
int rc = 0; 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) { if (!core || !core->platform || !core->capabilities) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
rc = -EINVAL; rc = -EINVAL;
goto exit; goto error;
} }
platform_data = core->platform->data.instance_data; 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", d_vpr_e("%s: platform instance data is NULL\n",
__func__); __func__);
rc = -EINVAL; rc = -EINVAL;
goto exit; goto error;
} }
enc_valid_codecs = core->capabilities[ENC_CODECS].value; 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", d_vpr_e("%s: failed to allocate core capabilities\n",
__func__); __func__);
rc = -ENOMEM; rc = -ENOMEM;
goto exit; goto error;
} }
} else { } else {
d_vpr_e("%s: capabilities memory is expected to be freed\n", 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; return rc;
} }
@@ -1736,16 +2390,14 @@ int msm_vidc_core_init(struct msm_vidc_core *core)
goto unlock; goto unlock;
} }
mutex_unlock(&core->lock);
/*TODO: acquire lock or not */
d_vpr_h("%s(): waiting for sys init done, %d ms\n", __func__, d_vpr_h("%s(): waiting for sys init done, %d ms\n", __func__,
core->capabilities[HW_RESPONSE_TIMEOUT].value); core->capabilities[HW_RESPONSE_TIMEOUT].value);
mutex_unlock(&core->lock);
rc = wait_for_completion_timeout(&core->init_done, msecs_to_jiffies( rc = wait_for_completion_timeout(&core->init_done, msecs_to_jiffies(
core->capabilities[HW_RESPONSE_TIMEOUT].value)); core->capabilities[HW_RESPONSE_TIMEOUT].value));
if (!rc) { if (!rc) {
d_vpr_e("%s: system init timed out\n", __func__); d_vpr_e("%s: system init timed out\n", __func__);
//msm_comm_kill_session(inst); rc = -ETIMEDOUT;
//rc = -EIO;
} else { } else {
d_vpr_h("%s: system init wait completed\n", __func__); d_vpr_h("%s: system init wait completed\n", __func__);
rc = 0; 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, struct msm_vidc_inst *get_inst(struct msm_vidc_core *core,
u32 session_id) u32 session_id)
{ {
@@ -1808,14 +2536,6 @@ struct msm_vidc_inst *get_inst(struct msm_vidc_core *core,
return inst; 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) void put_inst(struct msm_vidc_inst *inst)
{ {
if (!inst) { if (!inst) {
@@ -1823,7 +2543,7 @@ void put_inst(struct msm_vidc_inst *inst)
return; 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) void core_lock(struct msm_vidc_core *core, const char *function)

View File

@@ -20,6 +20,8 @@
#define BASE_DEVICE_NUMBER 32 #define BASE_DEVICE_NUMBER 32
struct msm_vidc_core *g_core;
static int msm_vidc_deinit_irq(struct msm_vidc_core *core) static int msm_vidc_deinit_irq(struct msm_vidc_core *core)
{ {
struct msm_vidc_dt *dt; struct msm_vidc_dt *dt;
@@ -214,25 +216,15 @@ static int msm_vidc_initialize_core(struct msm_vidc_core *core)
goto exit; 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); mutex_init(&core->lock);
INIT_LIST_HEAD(&core->instances); INIT_LIST_HEAD(&core->instances);
INIT_LIST_HEAD(&core->dangling_instances); INIT_LIST_HEAD(&core->dangling_instances);
INIT_LIST_HEAD(&core->inst_works);
INIT_WORK(&core->device_work, venus_hfi_work_handler); INIT_WORK(&core->device_work, venus_hfi_work_handler);
INIT_DELAYED_WORK(&core->pm_work, venus_hfi_pm_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->fw_unload_work, msm_vidc_fw_unload_handler);
INIT_DELAYED_WORK(&core->batch_work, msm_vidc_batch_handler); INIT_DELAYED_WORK(&core->batch_work, msm_vidc_batch_handler);
INIT_WORK(&core->ssr_work, msm_vidc_ssr_handler); INIT_WORK(&core->ssr_work, msm_vidc_ssr_handler);
INIT_DELAYED_WORK(&core->inst_work, venus_hfi_inst_work_handler);
exit: exit:
return rc; return rc;
@@ -249,6 +241,7 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
core = kzalloc(sizeof(*core), GFP_KERNEL); core = kzalloc(sizeof(*core), GFP_KERNEL);
if (!core) if (!core)
return -ENOMEM; return -ENOMEM;
g_core = core;
core->pdev = pdev; core->pdev = pdev;
dev_set_drvdata(&pdev->dev, core); dev_set_drvdata(&pdev->dev, core);
@@ -379,6 +372,7 @@ static int msm_vidc_remove(struct platform_device *pdev)
msm_vidc_deinitialize_core(core); msm_vidc_deinitialize_core(core);
dev_set_drvdata(&pdev->dev, NULL); dev_set_drvdata(&pdev->dev, NULL);
kfree(core); kfree(core);
g_core = NULL;
return 0; return 0;
} }

View File

@@ -13,6 +13,30 @@
#include "msm_vidc_debug.h" #include "msm_vidc_debug.h"
#include "msm_vidc_control.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, void *msm_vb2_get_userptr(struct device *dev, unsigned long vaddr,
unsigned long size, enum dma_data_direction dma_dir) unsigned long size, enum dma_data_direction dma_dir)
{ {
@@ -72,12 +96,6 @@ int msm_vidc_queue_setup(struct vb2_queue *q,
return -EINVAL; return -EINVAL;
if (port == INPUT_PORT) { 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; *num_planes = 1;
if (*num_buffers < inst->buffers.input.min_count + if (*num_buffers < inst->buffers.input.min_count +
inst->buffers.input.extra_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; inst->buffers.input.actual_count = *num_buffers;
} else if (port == INPUT_META_PORT) { } 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; *num_planes = 1;
if (*num_buffers < inst->buffers.input_meta.min_count + if (*num_buffers < inst->buffers.input_meta.min_count +
inst->buffers.input_meta.extra_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; inst->buffers.input_meta.actual_count = *num_buffers;
} else if (port == OUTPUT_PORT) { } 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; *num_planes = 1;
if (*num_buffers < inst->buffers.output.min_count + if (*num_buffers < inst->buffers.output.min_count +
inst->buffers.output.extra_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; inst->buffers.output.actual_count = *num_buffers;
} else if (port == OUTPUT_META_PORT) { } 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; *num_planes = 1;
if (*num_buffers < inst->buffers.output_meta.min_count + if (*num_buffers < inst->buffers.output_meta.min_count +
inst->buffers.output_meta.extra_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 (q->type == INPUT_MPLANE) {
if (is_decode_session(inst)) if (is_decode_session(inst))
rc = msm_vdec_start_input(inst); rc = msm_vdec_streamon_input(inst);
else if (is_encode_session(inst)) else if (is_encode_session(inst))
rc = msm_venc_start_input(inst); rc = msm_venc_streamon_input(inst);
else else
goto error; goto error;
} else if (q->type == OUTPUT_MPLANE) { } else if (q->type == OUTPUT_MPLANE) {
if (is_decode_session(inst)) if (is_decode_session(inst))
rc = msm_vdec_start_output(inst); rc = msm_vdec_streamon_output(inst);
else if (is_encode_session(inst)) else if (is_encode_session(inst))
rc = msm_venc_start_output(inst); rc = msm_venc_streamon_output(inst);
else else
goto error; goto error;
} else { } else {
s_vpr_e(inst->sid, "%s: invalid type %d\n", q->type);
goto error; goto error;
} }
if (!rc)
s_vpr_h(inst->sid, "Streamon: %d successful\n", q->type);
return rc; return rc;
error: 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; return -EINVAL;
} }
@@ -225,30 +228,29 @@ void msm_vidc_stop_streaming(struct vb2_queue *q)
if (q->type == INPUT_MPLANE) { if (q->type == INPUT_MPLANE) {
if (is_decode_session(inst)) if (is_decode_session(inst))
rc = msm_vdec_stop_input(inst); rc = msm_vdec_streamoff_input(inst);
else if (is_encode_session(inst)) else if (is_encode_session(inst))
rc = msm_venc_stop_input(inst); rc = msm_venc_streamoff_input(inst);
else else
goto error; goto error;
} else if (q->type == OUTPUT_MPLANE) { } else if (q->type == OUTPUT_MPLANE) {
if (is_decode_session(inst)) if (is_decode_session(inst))
rc = msm_vdec_stop_output(inst); rc = msm_vdec_streamoff_output(inst);
else if (is_encode_session(inst)) else if (is_encode_session(inst))
rc = msm_venc_stop_output(inst); rc = msm_venc_streamoff_output(inst);
else else
goto error; goto error;
} else { } else {
s_vpr_e(inst->sid, "%s: invalid type %d\n", q->type);
goto error; goto error;
} }
if (rc) if (!rc)
s_vpr_e(inst->sid, "%s: stop failed for qtype: %d\n", s_vpr_h(inst->sid, "Streamoff: %d successful\n", q->type);
__func__, q->type);
return; return;
error: error:
s_vpr_e(inst->sid, "%s: invalid session/qtype, qtype: %d\n", s_vpr_e(inst->sid, "Streamoff: %d failed\n", q->type);
__func__, q->type);
return; return;
} }

View File

@@ -2080,7 +2080,7 @@ static void __set_queue_hdr_defaults(struct hfi_queue_header *q_hdr)
q_hdr->qhdr_write_idx = 0x0; 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; int i;
@@ -2394,7 +2394,7 @@ static void __unload_fw(struct msm_vidc_core *core)
qcom_scm_pas_shutdown(core->dt->fw_cookie); qcom_scm_pas_shutdown(core->dt->fw_cookie);
core->dt->fw_cookie = 0; core->dt->fw_cookie = 0;
__interface_queues_release(core); __interface_queues_deinit(core);
call_venus_op(core, power_off, core); call_venus_op(core, power_off, core);
__deinit_resources(core); __deinit_resources(core);
@@ -2425,7 +2425,7 @@ irqreturn_t venus_hfi_isr(int irq, void *data)
{ {
struct msm_vidc_core *core = data; struct msm_vidc_core *core = data;
d_vpr_e("%s()\n", __func__); d_vpr_l("%s()\n", __func__);
disable_irq_nosync(irq); disable_irq_nosync(irq);
queue_work(core->device_workq, &core->device_work); 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__); d_vpr_e("%s: invalid params\n", __func__);
return; return;
} }
d_vpr_e("%s(): core %pK\n", __func__, core);
mutex_lock(&core->lock); mutex_lock(&core->lock);
if (__resume(core)) { if (__resume(core)) {
@@ -2546,12 +2545,11 @@ int venus_hfi_core_init(struct msm_vidc_core *core)
{ {
int rc = 0; int rc = 0;
d_vpr_h("%s(): core %p\n", __func__, core);
if (!core) { if (!core) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
d_vpr_h("%s(): core %pK\n", __func__, core);
core->packet_size = 4096; core->packet_size = 4096;
core->packet = kzalloc(core->packet_size, GFP_KERNEL); core->packet = kzalloc(core->packet_size, GFP_KERNEL);
@@ -2580,27 +2578,49 @@ int venus_hfi_core_init(struct msm_vidc_core *core)
if (rc) if (rc)
goto error; goto error;
__sys_init(core); rc = __enable_subcaches(core);
__sys_image_version(core); if (rc)
__sys_set_debug(core, (msm_vidc_debug & FW_LOGMASK) >> FW_LOGSHIFT); goto error;
__enable_subcaches(core);
__set_subcaches(core); 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__); d_vpr_h("%s(): successful\n", __func__);
return 0; return 0;
error: error:
d_vpr_h("%s(): failed\n", __func__); d_vpr_h("%s(): failed\n", __func__);
__unload_fw(core); venus_hfi_core_deinit(core);
kfree(core->response_packet);
kfree(core->packet);
return rc; 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; return 0;
} }
@@ -2867,7 +2887,6 @@ int venus_hfi_queue_buffer(struct msm_vidc_inst *inst,
struct msm_vidc_core *core; struct msm_vidc_core *core;
struct hfi_buffer hfi_buffer; struct hfi_buffer hfi_buffer;
d_vpr_h("%s(): inst %p\n", __func__, inst);
if (!inst || !inst->core || !inst->packet) { if (!inst || !inst->core || !inst->packet) {
d_vpr_e("%s: Invalid params\n", __func__); d_vpr_e("%s: Invalid params\n", __func__);
return -EINVAL; return -EINVAL;
@@ -2927,7 +2946,6 @@ int venus_hfi_release_buffer(struct msm_vidc_inst *inst,
struct msm_vidc_core *core; struct msm_vidc_core *core;
struct hfi_buffer hfi_buffer; struct hfi_buffer hfi_buffer;
d_vpr_h("%s(): inst %p\n", __func__, inst);
if (!inst || !buffer) { if (!inst || !buffer) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;

View File

@@ -10,6 +10,8 @@
#include "msm_vidc_driver.h" #include "msm_vidc_driver.h"
#include "msm_vdec.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, void print_psc_properties(u32 tag, const char *str, struct msm_vidc_inst *inst,
struct msm_vidc_subscription_params subsc_params) 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 //todo: moved to HFI_PROP_PICTURE_TYPE
/*if (buffer->flags & HFI_BUF_FW_FLAG_KEYFRAME) /*if (buffer->flags & HFI_BUF_FW_FLAG_KEYFRAME)
buf->flags |= MSM_VIDC_BUF_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 //moved to HFI_INFO_DATA_CORRUPT
/*if (buffer->flags & HFI_BUF_FW_FLAG_CORRUPT) /*if (buffer->flags & HFI_BUF_FW_FLAG_CORRUPT)
buf->flags |= MSM_VIDC_BUF_FLAG_ERROR;*/ 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) /*if (buffer->flags & HFI_BUF_FW_FLAG_SUBFRAME)
buf->flags |= MSM_VIDC_BUF_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); print_vidc_buffer(VIDC_HIGH, "FBD", inst, buf);
return rc; return rc;
@@ -531,7 +537,9 @@ static int handle_dequeue_buffers(struct msm_vidc_inst* inst)
if (buf->attr & MSM_VIDC_ATTR_DEQUEUED) { if (buf->attr & MSM_VIDC_ATTR_DEQUEUED) {
buf->attr &= ~MSM_VIDC_ATTR_DEQUEUED; buf->attr &= ~MSM_VIDC_ATTR_DEQUEUED;
msm_vidc_vb2_buffer_done(inst, buf); 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; return rc;
} }
static int venus_hfi_input_psc(struct msm_vidc_core *core, int handle_session_input_psc(struct msm_vidc_inst *inst,
struct work_header *work_hdr) struct input_psc_work *psc_work)
{ {
int rc = 0; int rc = 0;
struct msm_vidc_inst *inst;
struct hfi_header *hdr = NULL; struct hfi_header *hdr = NULL;
struct hfi_packet *packet; struct hfi_packet *packet;
u8 *pkt, *temp_pkt; u8 *pkt, *temp_pkt;
@@ -974,32 +981,25 @@ static int venus_hfi_input_psc(struct msm_vidc_core *core,
u32 hfi_port = 0; u32 hfi_port = 0;
int i; int i;
if (!work_hdr) { if (!inst || !psc_work) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
hdr = (struct hfi_header *)work_hdr->data; hdr = (struct hfi_header *)psc_work->data;
if (!hdr) { if (!hdr) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; 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_cmd_type = 0;
hfi_port = 0; hfi_port = 0;
pkt = (u8 *)((u8 *)hdr + sizeof(struct hfi_header)); pkt = (u8 *)((u8 *)hdr + sizeof(struct hfi_header));
temp_pkt = pkt; temp_pkt = pkt;
for (i = 0; i < hdr->num_packets; i++) { for (i = 0; i < hdr->num_packets; i++) {
if (validate_packet(pkt, work_hdr->data, if (validate_packet(pkt, psc_work->data,
work_hdr->data_size, __func__)) { psc_work->data_size, __func__)) {
rc = -EINVAL; rc = -EINVAL;
goto exit; goto exit;
} }
@@ -1034,47 +1034,48 @@ static int venus_hfi_input_psc(struct msm_vidc_core *core,
pkt += packet->size; pkt += packet->size;
} }
if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) { print_psc_properties(VIDC_HIGH, "INPUT_PSC", inst,
if (hfi_port == HFI_PORT_BITSTREAM) { inst->subcr_params[INPUT_PORT]);
print_psc_properties(VIDC_HIGH, "INPUT_PSC", inst, rc = msm_vdec_input_port_settings_change(inst);
inst->subcr_params[INPUT_PORT]); if (rc)
rc = msm_vdec_input_port_settings_change(inst); goto exit;
if (rc)
goto exit;
}
}
exit: exit:
mutex_unlock(&inst->lock);
put_inst(inst);
return rc; 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; int rc = 0;
struct work_header *work_hdr, *dummy = NULL; struct msm_vidc_inst *inst;
struct input_psc_work *psc_work, *dummy = NULL;
core = container_of(work, struct msm_vidc_core, inst_work.work); inst = container_of(work, struct msm_vidc_inst, input_psc_work.work);
if (!core) { inst = get_inst_ref(g_core, inst);
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return; return;
} }
list_for_each_entry_safe(work_hdr, dummy, &core->inst_works, list) { mutex_lock(&inst->lock);
switch (work_hdr->type) { list_for_each_entry_safe(psc_work, dummy, &inst->input_psc_works, list) {
case MSM_VIDC_INST_WORK_PSC: rc = msm_vidc_allow_input_psc(inst);
venus_hfi_input_psc(core, work_hdr); if (!rc) {
break; rc = handle_session_input_psc(inst, psc_work);
default: if (!rc)
d_vpr_e("%s(): invalid work type: %d\n", __func__, rc = msm_vidc_state_change_input_psc(inst);
work_hdr->type);
break; /* 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); list_del(&psc_work->list);
kfree(work_hdr->data); kfree(psc_work->data);
kfree(work_hdr); kfree(psc_work);
} }
mutex_unlock(&inst->lock);
put_inst(inst);
} }
static int handle_session_response(struct msm_vidc_core *core, 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) { packet->type < HFI_CMD_END) {
if (packet->type == HFI_CMD_SETTINGS_CHANGE && if (packet->type == HFI_CMD_SETTINGS_CHANGE &&
packet->port == HFI_PORT_BITSTREAM) { 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); 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_size = hdr->size;
work->data = kzalloc(hdr->size, GFP_KERNEL); work->data = kzalloc(hdr->size, GFP_KERNEL);
if (!work->data) { if (!work->data) {
@@ -1123,9 +1122,9 @@ static int handle_session_response(struct msm_vidc_core *core,
goto exit; goto exit;
} }
memcpy(work->data, (void *)hdr, hdr->size); memcpy(work->data, (void *)hdr, hdr->size);
list_add_tail(&work->list, &core->inst_works); list_add_tail(&work->list, &inst->input_psc_works);
queue_delayed_work(core->inst_workq, queue_delayed_work(inst->input_psc_workq,
&core->inst_work, msecs_to_jiffies(0)); &inst->input_psc_work, msecs_to_jiffies(0));
goto exit; goto exit;
} }
if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) { if (hfi_cmd_type == HFI_CMD_SETTINGS_CHANGE) {