video: driver: request api changes for dynamic controls

- Request api allows to synchronize controls along
  with buffers.
- Client allocates a request fd. This request fd is
  associated with control and set using s_ext_ctrls.
  Such controls are stored by the framework and not
  applied immediately.
- Request fd is also associated with input qbuf and
  queued to driver. Following this actual request is
  queued. Buffers do not enter the queue untill the
  request is queued.
- As part of qbuf, driver call request_setup() which
  inturn sets the control to driver.

Change-Id: I316c4dc2a0091b21059230be5ee5fd6379259456
Signed-off-by: Darshana Patil <quic_darshana@quicinc.com>
This commit is contained in:
Darshana Patil
2022-01-11 17:48:20 -08:00
parent 57c103b1ad
commit acc83ca211
16 changed files with 335 additions and 102 deletions

View File

@@ -25,8 +25,6 @@ int msm_vidc_s_selection(void* instance, struct v4l2_selection* s);
int msm_vidc_g_selection(void* instance, struct v4l2_selection* s); int msm_vidc_g_selection(void* instance, struct v4l2_selection* s);
int msm_vidc_s_param(void *instance, struct v4l2_streamparm *sp); int msm_vidc_s_param(void *instance, struct v4l2_streamparm *sp);
int msm_vidc_g_param(void *instance, struct v4l2_streamparm *sp); int msm_vidc_g_param(void *instance, struct v4l2_streamparm *sp);
int msm_vidc_s_ext_ctrl(void *instance, struct v4l2_ext_controls *a);
int msm_vidc_g_ext_ctrl(void *instance, struct v4l2_ext_controls *a);
int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b); int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b);
int msm_vidc_release_buffer(void *instance, int buffer_type, int msm_vidc_release_buffer(void *instance, int buffer_type,
unsigned int buffer_index); unsigned int buffer_index);

View File

@@ -47,6 +47,7 @@ struct msm_vidc_iface_q_info {
struct msm_video_device { struct msm_video_device {
enum msm_vidc_domain_type type; enum msm_vidc_domain_type type;
struct video_device vdev; struct video_device vdev;
struct v4l2_m2m_dev *m2m_dev;
}; };
struct msm_vidc_core_power { struct msm_vidc_core_power {
@@ -65,6 +66,7 @@ struct msm_vidc_core {
struct platform_device *pdev; struct platform_device *pdev;
struct msm_video_device vdev[2]; struct msm_video_device vdev[2];
struct v4l2_device v4l2_dev; struct v4l2_device v4l2_dev;
struct media_device media_dev;
struct list_head instances; struct list_head instances;
struct list_head dangling_instances; struct list_head dangling_instances;
struct dentry *debugfs_parent; struct dentry *debugfs_parent;
@@ -104,9 +106,11 @@ struct msm_vidc_core {
struct v4l2_ctrl_ops *v4l2_ctrl_ops; struct v4l2_ctrl_ops *v4l2_ctrl_ops;
struct vb2_ops *vb2_ops; struct vb2_ops *vb2_ops;
struct vb2_mem_ops *vb2_mem_ops; struct vb2_mem_ops *vb2_mem_ops;
struct v4l2_m2m_ops *v4l2_m2m_ops;
struct msm_vidc_venus_ops *venus_ops; struct msm_vidc_venus_ops *venus_ops;
struct msm_vidc_session_ops *session_ops; struct msm_vidc_session_ops *session_ops;
struct msm_vidc_memory_ops *mem_ops; struct msm_vidc_memory_ops *mem_ops;
struct media_device_ops *media_device_ops;
u32 header_id; u32 header_id;
u32 packet_id; u32 packet_id;
u32 sys_init_id; u32 sys_init_id;

View File

@@ -86,9 +86,14 @@ enum msm_vidc_inst_state {
MSM_VIDC_ERROR = 12, MSM_VIDC_ERROR = 12,
}; };
struct buf_queue {
struct vb2_queue *vb2q;
};
struct msm_vidc_inst { struct msm_vidc_inst {
struct list_head list; struct list_head list;
struct mutex lock; struct mutex lock;
struct mutex request_lock;
enum msm_vidc_inst_state state; enum msm_vidc_inst_state state;
enum msm_vidc_domain_type domain; enum msm_vidc_domain_type domain;
enum msm_vidc_codec_type codec; enum msm_vidc_codec_type codec;
@@ -101,6 +106,8 @@ struct msm_vidc_inst {
struct v4l2_format fmts[MAX_PORT]; struct v4l2_format fmts[MAX_PORT];
struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl_handler ctrl_handler;
struct v4l2_fh event_handler; struct v4l2_fh event_handler;
struct v4l2_m2m_dev *m2m_dev;
struct v4l2_m2m_ctx *m2m_ctx;
struct v4l2_ctrl **ctrls; struct v4l2_ctrl **ctrls;
u32 num_ctrls; u32 num_ctrls;
struct msm_vidc_inst_cap_entry children; struct msm_vidc_inst_cap_entry children;
@@ -108,7 +115,7 @@ struct msm_vidc_inst {
enum hfi_rate_control hfi_rc_type; enum hfi_rate_control hfi_rc_type;
enum hfi_layer_encoding_type hfi_layer_type; enum hfi_layer_encoding_type hfi_layer_type;
bool request; bool request;
struct vb2_queue vb2q[MAX_PORT]; struct buf_queue bufq[MAX_PORT];
struct msm_vidc_rectangle crop; struct msm_vidc_rectangle crop;
struct msm_vidc_rectangle compose; struct msm_vidc_rectangle compose;
struct msm_vidc_power power; struct msm_vidc_power power;

View File

@@ -14,6 +14,7 @@
#include <media/v4l2-ioctl.h> #include <media/v4l2-ioctl.h>
#include <media/v4l2-event.h> #include <media/v4l2-event.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-mem2mem.h>
#include <media/videobuf2-core.h> #include <media/videobuf2-core.h>
#include <media/videobuf2-v4l2.h> #include <media/videobuf2-v4l2.h>

View File

@@ -64,5 +64,8 @@ int msm_v4l2_querymenu(struct file *file, void *fh,
struct v4l2_querymenu *qmenu); struct v4l2_querymenu *qmenu);
unsigned int msm_v4l2_poll(struct file *filp, unsigned int msm_v4l2_poll(struct file *filp,
struct poll_table_struct *pt); struct poll_table_struct *pt);
int msm_v4l2_request_validate(struct media_request *req);
void msm_v4l2_request_queue(struct media_request *req);
void msm_v4l2_m2m_device_run(void *priv);
void msm_v4l2_m2m_job_abort(void *priv);
#endif // _MSM_VIDC_V4L2_H_ #endif // _MSM_VIDC_V4L2_H_

View File

@@ -38,4 +38,6 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count);
void msm_vidc_stop_streaming(struct vb2_queue *q); void msm_vidc_stop_streaming(struct vb2_queue *q);
void msm_vidc_buf_queue(struct vb2_buffer *vb2); void msm_vidc_buf_queue(struct vb2_buffer *vb2);
void msm_vidc_buf_cleanup(struct vb2_buffer *vb); void msm_vidc_buf_cleanup(struct vb2_buffer *vb);
int msm_vidc_buf_out_validate(struct vb2_buffer *vb);
void msm_vidc_buf_request_complete(struct vb2_buffer *vb);
#endif // _MSM_VIDC_VB2_H_ #endif // _MSM_VIDC_VB2_H_

View File

@@ -1511,7 +1511,7 @@ int msm_vdec_input_port_settings_change(struct msm_vidc_inst *inst)
u32 rc = 0; u32 rc = 0;
struct v4l2_event event = {0}; struct v4l2_event event = {0};
if (!inst->vb2q[INPUT_PORT].streaming) { if (!inst->bufq[INPUT_PORT].vb2q->streaming) {
i_vpr_e(inst, "%s: input port not streaming\n", i_vpr_e(inst, "%s: input port not streaming\n",
__func__); __func__);
return 0; return 0;
@@ -1588,7 +1588,7 @@ int msm_vdec_streamon_input(struct msm_vidc_inst *inst)
} }
if (is_input_meta_enabled(inst) && if (is_input_meta_enabled(inst) &&
!inst->vb2q[INPUT_META_PORT].streaming) { !inst->bufq[INPUT_META_PORT].vb2q->streaming) {
i_vpr_e(inst, i_vpr_e(inst,
"%s: Meta port must be streamed on before data port\n", "%s: Meta port must be streamed on before data port\n",
__func__); __func__);
@@ -1897,7 +1897,7 @@ int msm_vdec_streamon_output(struct msm_vidc_inst *inst)
capability = inst->capabilities; capability = inst->capabilities;
if (is_output_meta_enabled(inst) && if (is_output_meta_enabled(inst) &&
!inst->vb2q[OUTPUT_META_PORT].streaming) { !inst->bufq[OUTPUT_META_PORT].vb2q->streaming) {
i_vpr_e(inst, i_vpr_e(inst,
"%s: Meta port must be streamed on before data port\n", "%s: Meta port must be streamed on before data port\n",
__func__); __func__);
@@ -2347,8 +2347,8 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
return rc; return rc;
} else if (cmd == V4L2_DEC_CMD_START) { } else if (cmd == V4L2_DEC_CMD_START) {
i_vpr_h(inst, "received cmd: resume\n"); i_vpr_h(inst, "received cmd: resume\n");
vb2_clear_last_buffer_dequeued(&inst->vb2q[OUTPUT_META_PORT]); vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_META_PORT].vb2q);
vb2_clear_last_buffer_dequeued(&inst->vb2q[OUTPUT_PORT]); vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_PORT].vb2q);
if (capability->cap[CODED_FRAMES].value == CODED_FRAMES_INTERLACE && if (capability->cap[CODED_FRAMES].value == CODED_FRAMES_INTERLACE &&
!is_ubwc_colorformat(capability->cap[PIX_FMTS].value)) { !is_ubwc_colorformat(capability->cap[PIX_FMTS].value)) {
@@ -2417,7 +2417,7 @@ int msm_vdec_try_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
pix_fmt = v4l2_codec_to_driver(f->fmt.pix_mp.pixelformat, __func__); pix_fmt = v4l2_codec_to_driver(f->fmt.pix_mp.pixelformat, __func__);
} }
} else if (f->type == OUTPUT_MPLANE) { } else if (f->type == OUTPUT_MPLANE) {
if (inst->vb2q[INPUT_PORT].streaming) { if (inst->bufq[INPUT_PORT].vb2q->streaming) {
f->fmt.pix_mp.height = inst->fmts[INPUT_PORT].fmt.pix_mp.height; f->fmt.pix_mp.height = inst->fmts[INPUT_PORT].fmt.pix_mp.height;
f->fmt.pix_mp.width = inst->fmts[INPUT_PORT].fmt.pix_mp.width; f->fmt.pix_mp.width = inst->fmts[INPUT_PORT].fmt.pix_mp.width;
} }
@@ -2558,7 +2558,7 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
} else if (f->type == OUTPUT_MPLANE) { } else if (f->type == OUTPUT_MPLANE) {
fmt = &inst->fmts[OUTPUT_PORT]; fmt = &inst->fmts[OUTPUT_PORT];
fmt->type = OUTPUT_MPLANE; fmt->type = OUTPUT_MPLANE;
if (inst->vb2q[INPUT_PORT].streaming) { if (inst->bufq[INPUT_PORT].vb2q->streaming) {
f->fmt.pix_mp.height = inst->fmts[INPUT_PORT].fmt.pix_mp.height; f->fmt.pix_mp.height = inst->fmts[INPUT_PORT].fmt.pix_mp.height;
f->fmt.pix_mp.width = inst->fmts[INPUT_PORT].fmt.pix_mp.width; f->fmt.pix_mp.width = inst->fmts[INPUT_PORT].fmt.pix_mp.width;
} }
@@ -2576,7 +2576,7 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
fmt->fmt.pix_mp.plane_fmt[0].sizeimage = call_session_op(core, fmt->fmt.pix_mp.plane_fmt[0].sizeimage = call_session_op(core,
buffer_size, inst, MSM_VIDC_BUF_OUTPUT); buffer_size, inst, MSM_VIDC_BUF_OUTPUT);
if (!inst->vb2q[INPUT_PORT].streaming) if (!inst->bufq[INPUT_PORT].vb2q->streaming)
inst->buffers.output.min_count = call_session_op(core, inst->buffers.output.min_count = call_session_op(core,
min_count, inst, MSM_VIDC_BUF_OUTPUT); min_count, inst, MSM_VIDC_BUF_OUTPUT);
inst->buffers.output.extra_count = call_session_op(core, inst->buffers.output.extra_count = call_session_op(core,
@@ -2594,7 +2594,7 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
msm_vidc_update_cap_value(inst, PIX_FMTS, pix_fmt, __func__); msm_vidc_update_cap_value(inst, PIX_FMTS, pix_fmt, __func__);
/* update crop while input port is not streaming */ /* update crop while input port is not streaming */
if (!inst->vb2q[INPUT_PORT].streaming) { if (!inst->bufq[INPUT_PORT].vb2q->streaming) {
inst->crop.top = 0; inst->crop.top = 0;
inst->crop.left = 0; inst->crop.left = 0;
inst->crop.width = f->fmt.pix_mp.width; inst->crop.width = f->fmt.pix_mp.width;
@@ -2762,8 +2762,8 @@ set_default:
msm_vidc_update_cap_value(inst, is_frame_rate ? FRAME_RATE : OPERATING_RATE, msm_vidc_update_cap_value(inst, is_frame_rate ? FRAME_RATE : OPERATING_RATE,
q16_rate, __func__); q16_rate, __func__);
if (is_realtime_session(inst) && if (is_realtime_session(inst) &&
((s_parm->type == INPUT_MPLANE && inst->vb2q[INPUT_PORT].streaming) || ((s_parm->type == INPUT_MPLANE && inst->bufq[INPUT_PORT].vb2q->streaming) ||
(s_parm->type == OUTPUT_MPLANE && inst->vb2q[OUTPUT_PORT].streaming))) { (s_parm->type == OUTPUT_MPLANE && inst->bufq[OUTPUT_PORT].vb2q->streaming))) {
rc = msm_vidc_check_core_mbps(inst); rc = msm_vidc_check_core_mbps(inst);
if (rc) { if (rc) {
i_vpr_e(inst, "%s: unsupported load\n", __func__); i_vpr_e(inst, "%s: unsupported load\n", __func__);
@@ -2833,7 +2833,7 @@ static int msm_vdec_check_colorformat_supported(struct msm_vidc_inst* inst,
bool supported = true; bool supported = true;
/* do not reject coloformats before streamon */ /* do not reject coloformats before streamon */
if (!inst->vb2q[INPUT_PORT].streaming) if (!inst->bufq[INPUT_PORT].vb2q->streaming)
return true; return true;
/* /*

View File

@@ -815,7 +815,7 @@ int msm_venc_streamon_input(struct msm_vidc_inst *inst)
} }
if (is_input_meta_enabled(inst) && if (is_input_meta_enabled(inst) &&
!inst->vb2q[INPUT_META_PORT].streaming) { !inst->bufq[INPUT_META_PORT].vb2q->streaming) {
i_vpr_e(inst, i_vpr_e(inst,
"%s: Meta port must be streamed on before data port\n", "%s: Meta port must be streamed on before data port\n",
__func__); __func__);
@@ -923,8 +923,8 @@ int msm_venc_process_cmd(struct msm_vidc_inst *inst, u32 cmd)
i_vpr_h(inst, "received cmd: resume\n"); i_vpr_h(inst, "received cmd: resume\n");
if (!msm_vidc_allow_start(inst)) if (!msm_vidc_allow_start(inst))
return -EBUSY; return -EBUSY;
vb2_clear_last_buffer_dequeued(&inst->vb2q[OUTPUT_META_PORT]); vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_META_PORT].vb2q);
vb2_clear_last_buffer_dequeued(&inst->vb2q[OUTPUT_PORT]); vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_PORT].vb2q);
rc = msm_vidc_state_change_start(inst); rc = msm_vidc_state_change_start(inst);
if (rc) if (rc)
@@ -989,7 +989,7 @@ int msm_venc_streamon_output(struct msm_vidc_inst *inst)
} }
if (is_output_meta_enabled(inst) && if (is_output_meta_enabled(inst) &&
!inst->vb2q[OUTPUT_META_PORT].streaming) { !inst->bufq[OUTPUT_META_PORT].vb2q->streaming) {
i_vpr_e(inst, i_vpr_e(inst,
"%s: Meta port must be streamed on before data port\n", "%s: Meta port must be streamed on before data port\n",
__func__); __func__);
@@ -1619,8 +1619,8 @@ int msm_venc_s_param(struct msm_vidc_inst *inst,
msm_vidc_update_cap_value(inst, is_frame_rate ? FRAME_RATE : OPERATING_RATE, msm_vidc_update_cap_value(inst, is_frame_rate ? FRAME_RATE : OPERATING_RATE,
q16_rate, __func__); q16_rate, __func__);
if (is_realtime_session(inst) && if (is_realtime_session(inst) &&
((s_parm->type == INPUT_MPLANE && inst->vb2q[INPUT_PORT].streaming) || ((s_parm->type == INPUT_MPLANE && inst->bufq[INPUT_PORT].vb2q->streaming) ||
(s_parm->type == OUTPUT_MPLANE && inst->vb2q[OUTPUT_PORT].streaming))) { (s_parm->type == OUTPUT_MPLANE && inst->bufq[OUTPUT_PORT].vb2q->streaming))) {
rc = msm_vidc_check_core_mbps(inst); rc = msm_vidc_check_core_mbps(inst);
if (rc) { if (rc) {
i_vpr_e(inst, "%s: unsupported load\n", __func__); i_vpr_e(inst, "%s: unsupported load\n", __func__);
@@ -1646,7 +1646,7 @@ int msm_venc_s_param(struct msm_vidc_inst *inst,
* FRAME_RATE cap id. * FRAME_RATE cap id.
* In dynamic case, frame rate is set like below. * In dynamic case, frame rate is set like below.
*/ */
if (inst->vb2q[OUTPUT_PORT].streaming) { if (inst->bufq[OUTPUT_PORT].vb2q->streaming) {
rc = venus_hfi_session_property(inst, rc = venus_hfi_session_property(inst,
HFI_PROP_FRAME_RATE, HFI_PROP_FRAME_RATE,
HFI_HOST_FLAGS_NONE, HFI_HOST_FLAGS_NONE,

View File

@@ -51,7 +51,7 @@ static int get_poll_flags(struct msm_vidc_inst *inst, u32 port)
__func__, inst, port); __func__, inst, port);
return poll; return poll;
} }
q = &inst->vb2q[port]; q = inst->bufq[port].vb2q;
spin_lock_irqsave(&q->done_lock, flags); spin_lock_irqsave(&q->done_lock, flags);
if (!list_empty(&q->done_list)) if (!list_empty(&q->done_list))
@@ -85,10 +85,10 @@ int msm_vidc_poll(void *instance, struct file *filp,
} }
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->bufq[INPUT_META_PORT].vb2q->done_wq, wait);
poll_wait(filp, &inst->vb2q[OUTPUT_META_PORT].done_wq, wait); poll_wait(filp, &inst->bufq[OUTPUT_META_PORT].vb2q->done_wq, wait);
poll_wait(filp, &inst->vb2q[INPUT_PORT].done_wq, wait); poll_wait(filp, &inst->bufq[INPUT_PORT].vb2q->done_wq, wait);
poll_wait(filp, &inst->vb2q[OUTPUT_PORT].done_wq, wait); poll_wait(filp, &inst->bufq[OUTPUT_PORT].vb2q->done_wq, wait);
if (v4l2_event_pending(&inst->event_handler)) if (v4l2_event_pending(&inst->event_handler))
poll |= POLLPRI; poll |= POLLPRI;
@@ -402,7 +402,7 @@ int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b)
goto exit; goto exit;
} }
rc = vb2_reqbufs(&inst->vb2q[port], b); rc = vb2_reqbufs(inst->bufq[port].vb2q, b);
if (rc) { if (rc) {
i_vpr_e(inst, "%s: vb2_reqbufs(%d) failed, %d\n", i_vpr_e(inst, "%s: vb2_reqbufs(%d) failed, %d\n",
__func__, b->type, rc); __func__, b->type, rc);
@@ -511,7 +511,7 @@ int msm_vidc_streamon(void *instance, enum v4l2_buf_type type)
goto exit; goto exit;
} }
rc = vb2_streamon(&inst->vb2q[port], type); rc = vb2_streamon(inst->bufq[port].vb2q, type);
if (rc) { if (rc) {
i_vpr_e(inst, "%s: vb2_streamon(%d) failed, %d\n", i_vpr_e(inst, "%s: vb2_streamon(%d) failed, %d\n",
__func__, type, rc); __func__, type, rc);
@@ -556,7 +556,7 @@ int msm_vidc_streamoff(void *instance, enum v4l2_buf_type type)
goto exit; goto exit;
} }
rc = vb2_streamoff(&inst->vb2q[port], type); rc = vb2_streamoff(inst->bufq[port].vb2q, type);
if (rc) { if (rc) {
i_vpr_e(inst, "%s: vb2_streamoff(%d) failed, %d\n", i_vpr_e(inst, "%s: vb2_streamoff(%d) failed, %d\n",
__func__, type, rc); __func__, type, rc);
@@ -833,6 +833,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
inst->auto_framerate = DEFAULT_FPS << 16; inst->auto_framerate = DEFAULT_FPS << 16;
kref_init(&inst->kref); kref_init(&inst->kref);
mutex_init(&inst->lock); mutex_init(&inst->lock);
mutex_init(&inst->request_lock);
msm_vidc_update_debug_str(inst); msm_vidc_update_debug_str(inst);
i_vpr_h(inst, "Opening video instance: %d\n", session_type); i_vpr_h(inst, "Opening video instance: %d\n", session_type);
@@ -903,10 +904,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
goto error; goto error;
} }
if (is_decode_session(inst)) rc = msm_vidc_event_queue_init(inst);
rc = msm_vdec_inst_init(inst);
else if (is_encode_session(inst))
rc = msm_venc_inst_init(inst);
if (rc) if (rc)
goto error; goto error;
@@ -914,7 +912,10 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
if (rc) if (rc)
goto error; goto error;
rc = msm_vidc_event_queue_init(inst); if (is_decode_session(inst))
rc = msm_vdec_inst_init(inst);
else if (is_encode_session(inst))
rc = msm_venc_inst_init(inst);
if (rc) if (rc)
goto error; goto error;

View File

@@ -173,7 +173,7 @@ static u32 msm_vidc_get_port_info(struct msm_vidc_inst *inst,
if (capability->cap[cap_id].flags & CAP_FLAG_INPUT_PORT && if (capability->cap[cap_id].flags & CAP_FLAG_INPUT_PORT &&
capability->cap[cap_id].flags & CAP_FLAG_OUTPUT_PORT) { capability->cap[cap_id].flags & CAP_FLAG_OUTPUT_PORT) {
if (inst->vb2q[OUTPUT_PORT].streaming) if (inst->bufq[OUTPUT_PORT].vb2q->streaming)
return get_hfi_port(inst, INPUT_PORT); return get_hfi_port(inst, INPUT_PORT);
else else
return get_hfi_port(inst, OUTPUT_PORT); return get_hfi_port(inst, OUTPUT_PORT);
@@ -844,11 +844,8 @@ int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl)
i_vpr_h(inst, "%s: state %d, name %s, id 0x%x value %d\n", i_vpr_h(inst, "%s: state %d, name %s, id 0x%x value %d\n",
__func__, inst->state, ctrl->name, ctrl->id, ctrl->val); __func__, inst->state, ctrl->name, ctrl->id, ctrl->val);
if (!msm_vidc_allow_s_ctrl(inst, ctrl->id)) { if (!msm_vidc_allow_s_ctrl(inst, ctrl->id))
i_vpr_e(inst, "%s: state %d, name %s, id %#x not allowed\n", return -EINVAL;
__func__, inst->state, ctrl->name, ctrl->id, ctrl->val);
return -EBUSY;
}
cap_id = msm_vidc_get_cap_id(inst, ctrl->id); cap_id = msm_vidc_get_cap_id(inst, ctrl->id);
if (cap_id == INST_CAP_NONE) { if (cap_id == INST_CAP_NONE) {
@@ -859,7 +856,7 @@ int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl)
capability->cap[cap_id].flags |= CAP_FLAG_CLIENT_SET; capability->cap[cap_id].flags |= CAP_FLAG_CLIENT_SET;
/* Static setting */ /* Static setting */
if (!inst->vb2q[OUTPUT_PORT].streaming) { if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) {
msm_vidc_update_cap_value(inst, cap_id, ctrl->val, __func__); msm_vidc_update_cap_value(inst, cap_id, ctrl->val, __func__);
if (ctrl->id == V4L2_CID_MPEG_VIDC_SECURE) { if (ctrl->id == V4L2_CID_MPEG_VIDC_SECURE) {
@@ -927,7 +924,7 @@ int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl)
} }
/* check if dynamic adjustment is allowed */ /* check if dynamic adjustment is allowed */
if (inst->vb2q[OUTPUT_PORT].streaming && if (inst->bufq[OUTPUT_PORT].vb2q->streaming &&
!(capability->cap[cap_id].flags & CAP_FLAG_DYNAMIC_ALLOWED)) { !(capability->cap[cap_id].flags & CAP_FLAG_DYNAMIC_ALLOWED)) {
i_vpr_e(inst, i_vpr_e(inst,
"%s: dynamic setting of cap[%d] %s is not allowed\n", "%s: dynamic setting of cap[%d] %s is not allowed\n",
@@ -951,8 +948,12 @@ int msm_v4l2_op_s_ctrl(struct v4l2_ctrl *ctrl)
} }
/* dynamic controls with request will be set along with qbuf */ /* dynamic controls with request will be set along with qbuf */
if (inst->request) if (inst->request) {
i_vpr_l(inst,
"%s: request api enabled, dynamic ctrls to be set with qbuf\n",
__func__);
return 0; return 0;
}
/* Dynamic set control ASAP */ /* Dynamic set control ASAP */
rc = msm_vidc_set_v4l2_properties(inst); rc = msm_vidc_set_v4l2_properties(inst);
@@ -1574,7 +1575,7 @@ int msm_vidc_adjust_layer_count(void *instance, struct v4l2_ctrl *ctrl)
META_EVA_STATS, __func__)) META_EVA_STATS, __func__))
return -EINVAL; return -EINVAL;
if (!inst->vb2q[OUTPUT_PORT].streaming) { if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) {
rc = msm_vidc_adjust_static_layer_count_and_type(inst, rc = msm_vidc_adjust_static_layer_count_and_type(inst,
client_layer_count); client_layer_count);
if (rc) if (rc)
@@ -1742,7 +1743,7 @@ int msm_vidc_adjust_bitrate(void *instance, struct v4l2_ctrl *ctrl)
return 0; return 0;
} }
if (inst->vb2q[OUTPUT_PORT].streaming) if (inst->bufq[OUTPUT_PORT].vb2q->streaming)
return 0; return 0;
if (msm_vidc_get_parent_value(inst, BIT_RATE, if (msm_vidc_get_parent_value(inst, BIT_RATE,
@@ -1821,7 +1822,7 @@ int msm_vidc_adjust_dynamic_layer_bitrate(void *instance, struct v4l2_ctrl *ctrl
if (capability->cap[BIT_RATE].flags & CAP_FLAG_CLIENT_SET) if (capability->cap[BIT_RATE].flags & CAP_FLAG_CLIENT_SET)
return 0; return 0;
if (!inst->vb2q[OUTPUT_PORT].streaming) if (!inst->bufq[OUTPUT_PORT].vb2q->streaming)
return 0; return 0;
/* /*
@@ -2167,7 +2168,7 @@ int msm_vidc_adjust_cac(void *instance, struct v4l2_ctrl *ctrl)
adjusted_value = ctrl ? ctrl->val : adjusted_value = ctrl ? ctrl->val :
capability->cap[CONTENT_ADAPTIVE_CODING].value; capability->cap[CONTENT_ADAPTIVE_CODING].value;
if (inst->vb2q[OUTPUT_PORT].streaming) if (inst->bufq[OUTPUT_PORT].vb2q->streaming)
return 0; return 0;
if (msm_vidc_get_parent_value(inst, CONTENT_ADAPTIVE_CODING, if (msm_vidc_get_parent_value(inst, CONTENT_ADAPTIVE_CODING,
@@ -2213,7 +2214,7 @@ int msm_vidc_adjust_bitrate_boost(void *instance, struct v4l2_ctrl *ctrl)
adjusted_value = ctrl ? ctrl->val : adjusted_value = ctrl ? ctrl->val :
capability->cap[BITRATE_BOOST].value; capability->cap[BITRATE_BOOST].value;
if (inst->vb2q[OUTPUT_PORT].streaming) if (inst->bufq[OUTPUT_PORT].vb2q->streaming)
return 0; return 0;
if (msm_vidc_get_parent_value(inst, BITRATE_BOOST, if (msm_vidc_get_parent_value(inst, BITRATE_BOOST,
@@ -2267,7 +2268,7 @@ int msm_vidc_adjust_min_quality(void *instance, struct v4l2_ctrl *ctrl)
* Therefore, below streaming check is required to avoid * Therefore, below streaming check is required to avoid
* runtime modification of MIN_QUALITY. * runtime modification of MIN_QUALITY.
*/ */
if (inst->vb2q[OUTPUT_PORT].streaming) if (inst->bufq[OUTPUT_PORT].vb2q->streaming)
return 0; return 0;
if (msm_vidc_get_parent_value(inst, MIN_QUALITY, if (msm_vidc_get_parent_value(inst, MIN_QUALITY,
@@ -2886,7 +2887,7 @@ int msm_vidc_set_frame_qp(void *instance,
BITRATE_MODE, &rc_type, __func__)) BITRATE_MODE, &rc_type, __func__))
return -EINVAL; return -EINVAL;
if (inst->vb2q[OUTPUT_PORT].streaming) { if (inst->bufq[OUTPUT_PORT].vb2q->streaming) {
if (rc_type != HFI_RC_OFF) { if (rc_type != HFI_RC_OFF) {
i_vpr_h(inst, i_vpr_h(inst,
"%s: dynamic qp not allowed for rc type %d\n", "%s: dynamic qp not allowed for rc type %d\n",
@@ -3068,7 +3069,7 @@ int msm_vidc_set_layer_count_and_type(void *instance,
return -EINVAL; return -EINVAL;
} }
if (!inst->vb2q[OUTPUT_PORT].streaming) { if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) {
/* set layer type */ /* set layer type */
hfi_layer_type = inst->hfi_layer_type; hfi_layer_type = inst->hfi_layer_type;
cap_id = LAYER_TYPE; cap_id = LAYER_TYPE;
@@ -3112,7 +3113,7 @@ int msm_vidc_set_gop_size(void *instance,
return -EINVAL; return -EINVAL;
} }
if (inst->vb2q[OUTPUT_PORT].streaming) { if (inst->bufq[OUTPUT_PORT].vb2q->streaming) {
if (inst->hfi_layer_type == HFI_HIER_B) { if (inst->hfi_layer_type == HFI_HIER_B) {
i_vpr_l(inst, i_vpr_l(inst,
"%s: HB dyn GOP setting is not supported\n", "%s: HB dyn GOP setting is not supported\n",
@@ -3155,7 +3156,7 @@ int msm_vidc_set_bitrate(void *instance,
* In this case, client did not change bitrate, hence, no need to set * In this case, client did not change bitrate, hence, no need to set
* to fw. * to fw.
*/ */
if (inst->vb2q[OUTPUT_PORT].streaming) if (inst->bufq[OUTPUT_PORT].vb2q->streaming)
return 0; return 0;
if (msm_vidc_get_parent_value(inst, BIT_RATE, if (msm_vidc_get_parent_value(inst, BIT_RATE,
@@ -3218,7 +3219,7 @@ int msm_vidc_set_dynamic_layer_bitrate(void *instance,
return -EINVAL; return -EINVAL;
} }
if (!inst->vb2q[OUTPUT_PORT].streaming) if (!inst->bufq[OUTPUT_PORT].vb2q->streaming)
return 0; return 0;
/* set Total Bitrate */ /* set Total Bitrate */
@@ -3311,7 +3312,7 @@ int msm_vidc_set_flip(void *instance,
if (vflip) if (vflip)
hfi_value |= HFI_VERTICAL_FLIP; hfi_value |= HFI_VERTICAL_FLIP;
if (inst->vb2q[OUTPUT_PORT].streaming) { if (inst->bufq[OUTPUT_PORT].vb2q->streaming) {
if (hfi_value != HFI_DISABLE_FLIP) { if (hfi_value != HFI_DISABLE_FLIP) {
rc = msm_vidc_set_req_sync_frame(inst, rc = msm_vidc_set_req_sync_frame(inst,
REQUEST_I_FRAME); REQUEST_I_FRAME);

View File

@@ -487,7 +487,7 @@ static ssize_t inst_info_read(struct file *file, char __user *buf,
"type: %s\n", i == INPUT_PORT ? "type: %s\n", i == INPUT_PORT ?
"Output" : "Capture"); "Output" : "Capture");
cur += write_str(cur, end - cur, "count: %u\n", cur += write_str(cur, end - cur, "count: %u\n",
inst->vb2q[i].num_buffers); inst->bufq[i].vb2q->num_buffers);
for (j = 0; j < f->fmt.pix_mp.num_planes; j++) for (j = 0; j < f->fmt.pix_mp.num_planes; j++)
cur += write_str(cur, end - cur, cur += write_str(cur, end - cur,

View File

@@ -1285,11 +1285,11 @@ bool msm_vidc_allow_s_ctrl(struct msm_vidc_inst *inst, u32 id)
goto exit; goto exit;
} }
if (is_decode_session(inst)) { if (is_decode_session(inst)) {
if (!inst->vb2q[INPUT_PORT].streaming) { if (!inst->bufq[INPUT_PORT].vb2q->streaming) {
allow = true; allow = true;
goto exit; goto exit;
} }
if (inst->vb2q[INPUT_PORT].streaming) { if (inst->bufq[INPUT_PORT].vb2q->streaming) {
switch (id) { switch (id) {
case V4L2_CID_MPEG_VIDC_CODEC_CONFIG: case V4L2_CID_MPEG_VIDC_CODEC_CONFIG:
case V4L2_CID_MPEG_VIDC_PRIORITY: case V4L2_CID_MPEG_VIDC_PRIORITY:
@@ -1544,20 +1544,20 @@ enum msm_vidc_allow msm_vidc_allow_streamoff(struct msm_vidc_inst *inst, u32 typ
return MSM_VIDC_DISALLOW; return MSM_VIDC_DISALLOW;
} }
if (type == INPUT_MPLANE) { if (type == INPUT_MPLANE) {
if (!inst->vb2q[INPUT_PORT].streaming) if (!inst->bufq[INPUT_PORT].vb2q->streaming)
allow = MSM_VIDC_IGNORE; allow = MSM_VIDC_IGNORE;
} else if (type == INPUT_META_PLANE) { } else if (type == INPUT_META_PLANE) {
if (inst->vb2q[INPUT_PORT].streaming) if (inst->bufq[INPUT_PORT].vb2q->streaming)
allow = MSM_VIDC_DISALLOW; allow = MSM_VIDC_DISALLOW;
else if (!inst->vb2q[INPUT_META_PORT].streaming) else if (!inst->bufq[INPUT_META_PORT].vb2q->streaming)
allow = MSM_VIDC_IGNORE; allow = MSM_VIDC_IGNORE;
} else if (type == OUTPUT_MPLANE) { } else if (type == OUTPUT_MPLANE) {
if (!inst->vb2q[OUTPUT_PORT].streaming) if (!inst->bufq[OUTPUT_PORT].vb2q->streaming)
allow = MSM_VIDC_IGNORE; allow = MSM_VIDC_IGNORE;
} else if (type == OUTPUT_META_PLANE) { } else if (type == OUTPUT_META_PLANE) {
if (inst->vb2q[OUTPUT_PORT].streaming) if (inst->bufq[OUTPUT_PORT].vb2q->streaming)
allow = MSM_VIDC_DISALLOW; allow = MSM_VIDC_DISALLOW;
else if (!inst->vb2q[OUTPUT_META_PORT].streaming) else if (!inst->bufq[OUTPUT_META_PORT].vb2q->streaming)
allow = MSM_VIDC_IGNORE; allow = MSM_VIDC_IGNORE;
} }
if (allow != MSM_VIDC_ALLOW) if (allow != MSM_VIDC_ALLOW)
@@ -1582,7 +1582,7 @@ enum msm_vidc_allow msm_vidc_allow_qbuf(struct msm_vidc_inst *inst, u32 type)
return MSM_VIDC_DISALLOW; return MSM_VIDC_DISALLOW;
/* defer queuing if streamon not completed */ /* defer queuing if streamon not completed */
if (!inst->vb2q[port].streaming) if (!inst->bufq[port].vb2q->streaming)
return MSM_VIDC_DEFER; return MSM_VIDC_DEFER;
if (type == INPUT_META_PLANE || type == OUTPUT_META_PLANE) if (type == INPUT_META_PLANE || type == OUTPUT_META_PLANE)
@@ -3641,7 +3641,7 @@ int msm_vidc_vb2_buffer_done(struct msm_vidc_inst *inst,
if (port < 0) if (port < 0)
return -EINVAL; return -EINVAL;
q = &inst->vb2q[port]; q = inst->bufq[port].vb2q;
if (!q->streaming) { if (!q->streaming) {
i_vpr_e(inst, "%s: port %d is not streaming\n", i_vpr_e(inst, "%s: port %d is not streaming\n",
__func__, port); __func__, port);
@@ -3675,6 +3675,7 @@ int msm_vidc_vb2_buffer_done(struct msm_vidc_inst *inst,
vbuf->flags = buf->flags; vbuf->flags = buf->flags;
vb2->timestamp = buf->timestamp; vb2->timestamp = buf->timestamp;
vb2->planes[0].bytesused = buf->data_size + vb2->planes[0].data_offset; vb2->planes[0].bytesused = buf->data_size + vb2->planes[0].data_offset;
v4l2_ctrl_request_complete(vb2->req_obj.req, &inst->ctrl_handler);
vb2_buffer_done(vb2, state); vb2_buffer_done(vb2, state);
return 0; return 0;
@@ -3754,45 +3755,112 @@ static int vb2q_init(struct msm_vidc_inst *inst,
return rc; return rc;
} }
static int m2m_queue_init(void *priv, struct vb2_queue *src_vq,
struct vb2_queue *dst_vq)
{
int rc = 0;
struct msm_vidc_inst *inst = priv;
struct msm_vidc_core *core;
if (!inst || !inst->core || !src_vq || !dst_vq) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
core = inst->core;
src_vq->supports_requests = 1;
src_vq->lock = &inst->request_lock;
src_vq->dev = &core->pdev->dev;
rc = vb2q_init(inst, src_vq, INPUT_MPLANE);
if (rc)
goto fail_input_vb2q_init;
inst->bufq[INPUT_PORT].vb2q = src_vq;
dst_vq->lock = src_vq->lock;
dst_vq->dev = &core->pdev->dev;
rc = vb2q_init(inst, dst_vq, OUTPUT_MPLANE);
if (rc)
goto fail_out_vb2q_init;
inst->bufq[OUTPUT_PORT].vb2q = dst_vq;
return rc;
fail_out_vb2q_init:
vb2_queue_release(inst->bufq[INPUT_PORT].vb2q);
fail_input_vb2q_init:
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;
struct msm_vidc_core *core;
if (!inst) { if (!inst || !inst->core) {
i_vpr_e(inst, "%s: invalid params\n", __func__); d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL; return -EINVAL;
} }
core = inst->core;
if (inst->vb2q_init) { if (inst->vb2q_init) {
i_vpr_h(inst, "%s: vb2q already inited\n", __func__); i_vpr_h(inst, "%s: vb2q already inited\n", __func__);
return 0; return 0;
} }
rc = vb2q_init(inst, &inst->vb2q[INPUT_PORT], INPUT_MPLANE); inst->m2m_dev = v4l2_m2m_init(core->v4l2_m2m_ops);
if (rc) if (IS_ERR(inst->m2m_dev)) {
goto exit; i_vpr_e(inst, "%s: failed to initialize v4l2 m2m device\n", __func__);
rc = PTR_ERR(inst->m2m_dev);
goto fail_m2m_init;
}
rc = vb2q_init(inst, &inst->vb2q[OUTPUT_PORT], OUTPUT_MPLANE); /* v4l2_m2m_ctx_init will do input & output queues initialization */
if (rc) inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_init);
goto fail_out_vb2q_init; if (!inst->m2m_ctx) {
i_vpr_e(inst, "%s: v4l2_m2m_ctx_init failed\n", __func__);
goto fail_m2m_ctx_init;
}
inst->event_handler.m2m_ctx = inst->m2m_ctx;
rc = vb2q_init(inst, &inst->vb2q[INPUT_META_PORT], INPUT_META_PLANE); inst->bufq[INPUT_META_PORT].vb2q = kzalloc(sizeof(struct vb2_queue), GFP_KERNEL);
if (!inst->bufq[INPUT_META_PORT].vb2q) {
i_vpr_e(inst, "%s: queue allocation failed for input meta port\n", __func__);
goto fail_in_meta_alloc;
}
/* do input meta port queues initialization */
rc = vb2q_init(inst, inst->bufq[INPUT_META_PORT].vb2q, INPUT_META_PLANE);
if (rc) if (rc)
goto fail_in_meta_vb2q_init; goto fail_in_meta_vb2q_init;
rc = vb2q_init(inst, &inst->vb2q[OUTPUT_META_PORT], OUTPUT_META_PLANE); inst->bufq[OUTPUT_META_PORT].vb2q = kzalloc(sizeof(struct vb2_queue), GFP_KERNEL);
if (!inst->bufq[OUTPUT_META_PORT].vb2q) {
i_vpr_e(inst, "%s: queue allocation failed for output meta port\n", __func__);
goto fail_out_meta_alloc;
}
/* do output meta port queues initialization */
rc = vb2q_init(inst, inst->bufq[OUTPUT_META_PORT].vb2q, OUTPUT_META_PLANE);
if (rc) if (rc)
goto fail_out_meta_vb2q_init; goto fail_out_meta_vb2q_init;
inst->vb2q_init = true; inst->vb2q_init = true;
return 0; return 0;
fail_out_meta_vb2q_init: fail_out_meta_vb2q_init:
vb2_queue_release(&inst->vb2q[INPUT_META_PORT]); kfree(inst->bufq[OUTPUT_META_PORT].vb2q);
inst->bufq[OUTPUT_META_PORT].vb2q = NULL;
fail_out_meta_alloc:
vb2_queue_release(inst->bufq[INPUT_META_PORT].vb2q);
fail_in_meta_vb2q_init: fail_in_meta_vb2q_init:
vb2_queue_release(&inst->vb2q[OUTPUT_PORT]); kfree(inst->bufq[INPUT_META_PORT].vb2q);
fail_out_vb2q_init: inst->bufq[INPUT_META_PORT].vb2q = NULL;
vb2_queue_release(&inst->vb2q[INPUT_PORT]); fail_in_meta_alloc:
exit: v4l2_m2m_ctx_release(inst->m2m_ctx);
inst->bufq[OUTPUT_PORT].vb2q = NULL;
inst->bufq[INPUT_PORT].vb2q = NULL;
fail_m2m_ctx_init:
v4l2_m2m_release(inst->m2m_dev);
fail_m2m_init:
return rc; return rc;
} }
@@ -3809,10 +3877,20 @@ int msm_vidc_vb2_queue_deinit(struct msm_vidc_inst *inst)
return 0; return 0;
} }
vb2_queue_release(&inst->vb2q[OUTPUT_META_PORT]); vb2_queue_release(inst->bufq[OUTPUT_META_PORT].vb2q);
vb2_queue_release(&inst->vb2q[INPUT_META_PORT]); kfree(inst->bufq[OUTPUT_META_PORT].vb2q);
vb2_queue_release(&inst->vb2q[OUTPUT_PORT]); inst->bufq[OUTPUT_META_PORT].vb2q = NULL;
vb2_queue_release(&inst->vb2q[INPUT_PORT]); vb2_queue_release(inst->bufq[INPUT_META_PORT].vb2q);
kfree(inst->bufq[INPUT_META_PORT].vb2q);
inst->bufq[INPUT_META_PORT].vb2q = NULL;
/*
* vb2_queue_release() for input and output queues
* is called from v4l2_m2m_ctx_release()
*/
v4l2_m2m_ctx_release(inst->m2m_ctx);
inst->bufq[OUTPUT_PORT].vb2q = NULL;
inst->bufq[INPUT_PORT].vb2q = NULL;
v4l2_m2m_release(inst->m2m_dev);
inst->vb2q_init = false; inst->vb2q_init = false;
return rc; return rc;
@@ -5169,6 +5247,8 @@ static void msm_vidc_close_helper(struct kref *kref)
if (inst->response_workq) if (inst->response_workq)
destroy_workqueue(inst->response_workq); destroy_workqueue(inst->response_workq);
msm_vidc_remove_dangling_session(inst); msm_vidc_remove_dangling_session(inst);
mutex_destroy(&inst->request_lock);
mutex_destroy(&inst->lock);
kfree(inst->capabilities); kfree(inst->capabilities);
kfree(inst); kfree(inst);
} }
@@ -5371,7 +5451,7 @@ int msm_vidc_update_buffer_count(struct msm_vidc_inst *inst, u32 port)
inst->buffers.input.actual_count); inst->buffers.input.actual_count);
break; break;
case OUTPUT_PORT: case OUTPUT_PORT:
if (!inst->vb2q[INPUT_PORT].streaming) if (!inst->bufq[INPUT_PORT].vb2q->streaming)
inst->buffers.output.min_count = call_session_op(core, inst->buffers.output.min_count = call_session_op(core,
min_count, inst, MSM_VIDC_BUF_OUTPUT); min_count, inst, MSM_VIDC_BUF_OUTPUT);
inst->buffers.output.extra_count = call_session_op(core, inst->buffers.output.extra_count = call_session_op(core,

View File

@@ -120,6 +120,8 @@ static struct vb2_ops msm_vb2_ops = {
.buf_queue = msm_vidc_buf_queue, .buf_queue = msm_vidc_buf_queue,
.buf_cleanup = msm_vidc_buf_cleanup, .buf_cleanup = msm_vidc_buf_cleanup,
.stop_streaming = msm_vidc_stop_streaming, .stop_streaming = msm_vidc_stop_streaming,
.buf_out_validate = msm_vidc_buf_out_validate,
.buf_request_complete = msm_vidc_buf_request_complete,
}; };
static struct vb2_mem_ops msm_vb2_mem_ops = { static struct vb2_mem_ops msm_vb2_mem_ops = {
@@ -131,6 +133,16 @@ static struct vb2_mem_ops msm_vb2_mem_ops = {
.unmap_dmabuf = msm_vb2_unmap_dmabuf, .unmap_dmabuf = msm_vb2_unmap_dmabuf,
}; };
static struct media_device_ops msm_v4l2_media_ops = {
.req_validate = msm_v4l2_request_validate,
.req_queue = msm_v4l2_request_queue,
};
static struct v4l2_m2m_ops msm_v4l2_m2m_ops = {
.device_run = msm_v4l2_m2m_device_run,
.job_abort = msm_v4l2_m2m_job_abort,
};
static int msm_vidc_init_ops(struct msm_vidc_core *core) static int msm_vidc_init_ops(struct msm_vidc_core *core)
{ {
if (!core) { if (!core) {
@@ -145,6 +157,8 @@ static int msm_vidc_init_ops(struct msm_vidc_core *core)
core->v4l2_ctrl_ops = &msm_v4l2_ctrl_ops; core->v4l2_ctrl_ops = &msm_v4l2_ctrl_ops;
core->vb2_ops = &msm_vb2_ops; core->vb2_ops = &msm_vb2_ops;
core->vb2_mem_ops = &msm_vb2_mem_ops; core->vb2_mem_ops = &msm_vb2_mem_ops;
core->media_device_ops = &msm_v4l2_media_ops;
core->v4l2_m2m_ops = &msm_v4l2_m2m_ops;
return 0; return 0;
} }

View File

@@ -142,6 +142,11 @@ static void msm_vidc_unregister_video_device(struct msm_vidc_core *core,
else else
return; return;
#ifdef CONFIG_MEDIA_CONTROLLER
v4l2_m2m_unregister_media_controller(core->vdev[index].m2m_dev);
v4l2_m2m_release(core->vdev[index].m2m_dev);
#endif
//rc = device_create_file(&core->vdev[index].vdev.dev, &dev_attr_link_name); //rc = device_create_file(&core->vdev[index].vdev.dev, &dev_attr_link_name);
video_set_drvdata(&core->vdev[index].vdev, NULL); video_set_drvdata(&core->vdev[index].vdev, NULL);
video_unregister_device(&core->vdev[index].vdev); video_unregister_device(&core->vdev[index].vdev);
@@ -152,16 +157,19 @@ static int msm_vidc_register_video_device(struct msm_vidc_core *core,
enum msm_vidc_domain_type type, int nr) enum msm_vidc_domain_type type, int nr)
{ {
int rc = 0; int rc = 0;
int index; int index, media_index;
d_vpr_h("%s()\n", __func__); d_vpr_h("%s()\n", __func__);
if (type == MSM_VIDC_DECODER) if (type == MSM_VIDC_DECODER) {
index = 0; index = 0;
else if (type == MSM_VIDC_ENCODER) media_index = MEDIA_ENT_F_PROC_VIDEO_DECODER;
} else if (type == MSM_VIDC_ENCODER) {
index = 1; index = 1;
else media_index = MEDIA_ENT_F_PROC_VIDEO_ENCODER;
} else {
return -EINVAL; return -EINVAL;
}
core->vdev[index].vdev.release = core->vdev[index].vdev.release =
msm_vidc_release_video_device; msm_vidc_release_video_device;
@@ -189,11 +197,34 @@ static int msm_vidc_register_video_device(struct msm_vidc_core *core,
//rc = device_create_file(&core->vdev[index].vdev.dev, &dev_attr_link_name); //rc = device_create_file(&core->vdev[index].vdev.dev, &dev_attr_link_name);
if (rc) { if (rc) {
d_vpr_e("Failed to create video device file\n"); d_vpr_e("Failed to create video device file\n");
video_unregister_device(&core->vdev[index].vdev); goto video_reg_failed;
return rc;
} }
#ifdef CONFIG_MEDIA_CONTROLLER
core->vdev[index].m2m_dev = v4l2_m2m_init(core->v4l2_m2m_ops);
if (IS_ERR(core->vdev[index].m2m_dev)) {
d_vpr_e("Failed to initialize V4L2 M2M device\n");
rc = PTR_ERR(core->vdev[index].m2m_dev);
goto m2m_init_failed;
}
rc = v4l2_m2m_register_media_controller(core->vdev[index].m2m_dev,
&core->vdev[index].vdev, media_index);
if (rc) {
d_vpr_e("%s: m2m_dev controller register failed for session type %d\n",
__func__, index);
goto m2m_mc_failed;
}
#endif
return 0; return 0;
#ifdef CONFIG_MEDIA_CONTROLLER
m2m_mc_failed:
v4l2_m2m_release(core->vdev[index].m2m_dev);
m2m_init_failed:
#endif
video_reg_failed:
video_unregister_device(&core->vdev[index].vdev);
return rc;
} }
static int msm_vidc_check_mmrm_support(struct msm_vidc_core *core) static int msm_vidc_check_mmrm_support(struct msm_vidc_core *core)
@@ -333,12 +364,18 @@ static int msm_vidc_remove(struct platform_device* pdev)
msm_vidc_core_deinit(core, true); msm_vidc_core_deinit(core, true);
of_platform_depopulate(&pdev->dev); of_platform_depopulate(&pdev->dev);
#ifdef CONFIG_MEDIA_CONTROLLER
media_device_unregister(&core->media_dev);
#endif
msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER); msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER);
msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER); msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER);
//device_remove_file(&core->vdev[MSM_VIDC_ENCODER].vdev.dev, //device_remove_file(&core->vdev[MSM_VIDC_ENCODER].vdev.dev,
//&dev_attr_link_name); //&dev_attr_link_name);
//device_remove_file(&core->vdev[MSM_VIDC_DECODER].vdev.dev, //device_remove_file(&core->vdev[MSM_VIDC_DECODER].vdev.dev,
//&dev_attr_link_name); //&dev_attr_link_name);
#ifdef CONFIG_MEDIA_CONTROLLER
media_device_cleanup(&core->media_dev);
#endif
v4l2_device_unregister(&core->v4l2_dev); v4l2_device_unregister(&core->v4l2_dev);
sysfs_remove_group(&pdev->dev.kobj, &msm_vidc_core_attr_group); sysfs_remove_group(&pdev->dev.kobj, &msm_vidc_core_attr_group);
@@ -428,6 +465,14 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
goto v4l2_reg_failed; goto v4l2_reg_failed;
} }
#ifdef CONFIG_MEDIA_CONTROLLER
core->media_dev.dev = &core->pdev->dev;
strscpy(core->media_dev.model, "msm_vidc_media", sizeof(core->media_dev.model));
media_device_init(&core->media_dev);
core->media_dev.ops = core->media_device_ops;
core->v4l2_dev.mdev = &core->media_dev;
#endif
/* setup the decoder device */ /* setup the decoder device */
rc = msm_vidc_register_video_device(core, MSM_VIDC_DECODER, nr); rc = msm_vidc_register_video_device(core, MSM_VIDC_DECODER, nr);
if (rc) { if (rc) {
@@ -441,7 +486,13 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
d_vpr_e("Failed to register video encoder\n"); d_vpr_e("Failed to register video encoder\n");
goto enc_reg_failed; goto enc_reg_failed;
} }
#ifdef CONFIG_MEDIA_CONTROLLER
rc = media_device_register(&core->media_dev);
if (rc) {
d_vpr_e("%s: media_device_register failed with %d\n", __func__, rc);
goto media_reg_failed;
}
#endif
rc = msm_vidc_check_mmrm_support(core); rc = msm_vidc_check_mmrm_support(core);
if (rc) { if (rc) {
d_vpr_e("Failed to check MMRM scaling support\n"); d_vpr_e("Failed to check MMRM scaling support\n");
@@ -477,6 +528,10 @@ static int msm_vidc_probe_video_device(struct platform_device *pdev)
core_init_failed: core_init_failed:
of_platform_depopulate(&pdev->dev); of_platform_depopulate(&pdev->dev);
sub_dev_failed: sub_dev_failed:
#ifdef CONFIG_MEDIA_CONTROLLER
media_device_unregister(&core->media_dev);
media_reg_failed:
#endif
msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER); msm_vidc_unregister_video_device(core, MSM_VIDC_ENCODER);
enc_reg_failed: enc_reg_failed:
msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER); msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER);

View File

@@ -696,3 +696,30 @@ unlock:
return rc; return rc;
} }
int msm_v4l2_request_validate(struct media_request *req)
{
return vb2_request_validate(req);
}
void msm_v4l2_request_queue(struct media_request *req)
{
v4l2_m2m_request_queue(req);
}
void msm_v4l2_m2m_device_run(void *priv)
{
d_vpr_l("%s: \n", __func__);
}
void msm_v4l2_m2m_job_abort(void *priv)
{
struct msm_vidc_inst *inst = priv;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return;
}
i_vpr_h(inst, "%s: m2m job aborted\n", __func__);
v4l2_m2m_job_finish(inst->m2m_dev, inst->m2m_ctx);
}

View File

@@ -24,13 +24,13 @@ struct vb2_queue *msm_vidc_get_vb2q(struct msm_vidc_inst *inst,
return NULL; return NULL;
} }
if (type == INPUT_MPLANE) { if (type == INPUT_MPLANE) {
q = &inst->vb2q[INPUT_PORT]; q = inst->bufq[INPUT_PORT].vb2q;
} else if (type == OUTPUT_MPLANE) { } else if (type == OUTPUT_MPLANE) {
q = &inst->vb2q[OUTPUT_PORT]; q = inst->bufq[OUTPUT_PORT].vb2q;
} else if (type == INPUT_META_PLANE) { } else if (type == INPUT_META_PLANE) {
q = &inst->vb2q[INPUT_META_PORT]; q = inst->bufq[INPUT_META_PORT].vb2q;
} else if (type == OUTPUT_META_PLANE) { } else if (type == OUTPUT_META_PLANE) {
q = &inst->vb2q[OUTPUT_META_PORT]; q = inst->bufq[OUTPUT_META_PORT].vb2q;
} else { } else {
i_vpr_e(inst, "%s: invalid buffer type %d\n", i_vpr_e(inst, "%s: invalid buffer type %d\n",
__func__, type); __func__, type);
@@ -263,8 +263,8 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count)
if (rc) if (rc)
goto error; goto error;
if ((q->type == INPUT_MPLANE && inst->vb2q[OUTPUT_PORT].streaming) || if ((q->type == INPUT_MPLANE && inst->bufq[OUTPUT_PORT].vb2q->streaming) ||
(q->type == OUTPUT_MPLANE && inst->vb2q[INPUT_PORT].streaming)) { (q->type == OUTPUT_MPLANE && inst->bufq[INPUT_PORT].vb2q->streaming)) {
rc = msm_vidc_get_properties(inst); rc = msm_vidc_get_properties(inst);
if (rc) if (rc)
goto error; goto error;
@@ -345,6 +345,28 @@ void msm_vidc_buf_queue(struct vb2_buffer *vb2)
return; return;
} }
/*
* As part of every qbuf initalise request to true.
* If there are any dynamic controls associated with qbuf,
* they will set as part s_ctrl() from v4l2_ctrl_request_setup().
* Once v4l2_ctrl_request_setup() is done, reset request variable.
* If the buffer does not have any requests with it, then
* v4l2_ctrl_request_setup() will return 0.
*/
inst->request = true;
rc = v4l2_ctrl_request_setup(vb2->req_obj.req,
&inst->ctrl_handler);
if (rc) {
inst->request = false;
i_vpr_e(inst, "%s: request setup failed, error %d\n",
__func__, rc);
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
v4l2_ctrl_request_complete(vb2->req_obj.req, &inst->ctrl_handler);
vb2_buffer_done(vb2, VB2_BUF_STATE_ERROR);
return;
}
inst->request = false;
if (is_decode_session(inst)) if (is_decode_session(inst))
rc = msm_vdec_qbuf(inst, vb2); rc = msm_vdec_qbuf(inst, vb2);
else if (is_encode_session(inst)) else if (is_encode_session(inst))
@@ -355,6 +377,7 @@ void msm_vidc_buf_queue(struct vb2_buffer *vb2)
if (rc) { if (rc) {
print_vb2_buffer("failed vb2-qbuf", inst, vb2); print_vb2_buffer("failed vb2-qbuf", inst, vb2);
msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__); msm_vidc_change_inst_state(inst, MSM_VIDC_ERROR, __func__);
v4l2_ctrl_request_complete(vb2->req_obj.req, &inst->ctrl_handler);
vb2_buffer_done(vb2, VB2_BUF_STATE_ERROR); vb2_buffer_done(vb2, VB2_BUF_STATE_ERROR);
} }
} }
@@ -362,3 +385,20 @@ void msm_vidc_buf_queue(struct vb2_buffer *vb2)
void msm_vidc_buf_cleanup(struct vb2_buffer *vb) void msm_vidc_buf_cleanup(struct vb2_buffer *vb)
{ {
} }
int msm_vidc_buf_out_validate(struct vb2_buffer *vb)
{
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
vbuf->field = V4L2_FIELD_NONE;
return 0;
}
void msm_vidc_buf_request_complete(struct vb2_buffer *vb)
{
struct msm_vidc_inst *inst = vb2_get_drv_priv(vb->vb2_queue);
i_vpr_l(inst, "%s: vb type %d, index %d\n",
__func__, vb->type, vb->index);
v4l2_ctrl_request_complete(vb->req_obj.req, &inst->ctrl_handler);
}