From acc83ca2113a1cda14bbfe31baa2a08cc63cb55c Mon Sep 17 00:00:00 2001 From: Darshana Patil Date: Tue, 11 Jan 2022 17:48:20 -0800 Subject: [PATCH] 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 --- driver/vidc/inc/msm_vidc.h | 2 - driver/vidc/inc/msm_vidc_core.h | 4 + driver/vidc/inc/msm_vidc_inst.h | 9 +- driver/vidc/inc/msm_vidc_internal.h | 1 + driver/vidc/inc/msm_vidc_v4l2.h | 5 +- driver/vidc/inc/msm_vidc_vb2.h | 4 +- driver/vidc/src/msm_vdec.c | 24 ++--- driver/vidc/src/msm_venc.c | 14 +-- driver/vidc/src/msm_vidc.c | 27 +++--- driver/vidc/src/msm_vidc_control.c | 43 ++++----- driver/vidc/src/msm_vidc_debug.c | 2 +- driver/vidc/src/msm_vidc_driver.c | 140 ++++++++++++++++++++++------ driver/vidc/src/msm_vidc_platform.c | 14 +++ driver/vidc/src/msm_vidc_probe.c | 69 ++++++++++++-- driver/vidc/src/msm_vidc_v4l2.c | 27 ++++++ driver/vidc/src/msm_vidc_vb2.c | 52 +++++++++-- 16 files changed, 335 insertions(+), 102 deletions(-) diff --git a/driver/vidc/inc/msm_vidc.h b/driver/vidc/inc/msm_vidc.h index 685e33f5b8..28202fc002 100644 --- a/driver/vidc/inc/msm_vidc.h +++ b/driver/vidc/inc/msm_vidc.h @@ -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_s_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_release_buffer(void *instance, int buffer_type, unsigned int buffer_index); diff --git a/driver/vidc/inc/msm_vidc_core.h b/driver/vidc/inc/msm_vidc_core.h index 77a5f463d9..27862c4e6d 100644 --- a/driver/vidc/inc/msm_vidc_core.h +++ b/driver/vidc/inc/msm_vidc_core.h @@ -47,6 +47,7 @@ struct msm_vidc_iface_q_info { struct msm_video_device { enum msm_vidc_domain_type type; struct video_device vdev; + struct v4l2_m2m_dev *m2m_dev; }; struct msm_vidc_core_power { @@ -65,6 +66,7 @@ struct msm_vidc_core { struct platform_device *pdev; struct msm_video_device vdev[2]; struct v4l2_device v4l2_dev; + struct media_device media_dev; struct list_head instances; struct list_head dangling_instances; struct dentry *debugfs_parent; @@ -104,9 +106,11 @@ struct msm_vidc_core { struct v4l2_ctrl_ops *v4l2_ctrl_ops; struct vb2_ops *vb2_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_session_ops *session_ops; struct msm_vidc_memory_ops *mem_ops; + struct media_device_ops *media_device_ops; u32 header_id; u32 packet_id; u32 sys_init_id; diff --git a/driver/vidc/inc/msm_vidc_inst.h b/driver/vidc/inc/msm_vidc_inst.h index 7ed3096e03..d990ba844f 100644 --- a/driver/vidc/inc/msm_vidc_inst.h +++ b/driver/vidc/inc/msm_vidc_inst.h @@ -86,9 +86,14 @@ enum msm_vidc_inst_state { MSM_VIDC_ERROR = 12, }; +struct buf_queue { + struct vb2_queue *vb2q; +}; + struct msm_vidc_inst { struct list_head list; struct mutex lock; + struct mutex request_lock; enum msm_vidc_inst_state state; enum msm_vidc_domain_type domain; enum msm_vidc_codec_type codec; @@ -101,6 +106,8 @@ struct msm_vidc_inst { struct v4l2_format fmts[MAX_PORT]; struct v4l2_ctrl_handler ctrl_handler; struct v4l2_fh event_handler; + struct v4l2_m2m_dev *m2m_dev; + struct v4l2_m2m_ctx *m2m_ctx; struct v4l2_ctrl **ctrls; u32 num_ctrls; struct msm_vidc_inst_cap_entry children; @@ -108,7 +115,7 @@ struct msm_vidc_inst { enum hfi_rate_control hfi_rc_type; enum hfi_layer_encoding_type hfi_layer_type; bool request; - struct vb2_queue vb2q[MAX_PORT]; + struct buf_queue bufq[MAX_PORT]; struct msm_vidc_rectangle crop; struct msm_vidc_rectangle compose; struct msm_vidc_power power; diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index b152ba2a43..7ae860fe65 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/driver/vidc/inc/msm_vidc_internal.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/driver/vidc/inc/msm_vidc_v4l2.h b/driver/vidc/inc/msm_vidc_v4l2.h index d283adbe07..d04badf32a 100644 --- a/driver/vidc/inc/msm_vidc_v4l2.h +++ b/driver/vidc/inc/msm_vidc_v4l2.h @@ -64,5 +64,8 @@ int msm_v4l2_querymenu(struct file *file, void *fh, struct v4l2_querymenu *qmenu); unsigned int msm_v4l2_poll(struct file *filp, 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_ diff --git a/driver/vidc/inc/msm_vidc_vb2.h b/driver/vidc/inc/msm_vidc_vb2.h index 140031c68a..a1f6aef999 100644 --- a/driver/vidc/inc/msm_vidc_vb2.h +++ b/driver/vidc/inc/msm_vidc_vb2.h @@ -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_buf_queue(struct vb2_buffer *vb2); void msm_vidc_buf_cleanup(struct vb2_buffer *vb); -#endif // _MSM_VIDC_VB2_H_ \ No newline at end of file +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_ diff --git a/driver/vidc/src/msm_vdec.c b/driver/vidc/src/msm_vdec.c index 5e0b1a5ac8..3a91ab17bb 100644 --- a/driver/vidc/src/msm_vdec.c +++ b/driver/vidc/src/msm_vdec.c @@ -1511,7 +1511,7 @@ int msm_vdec_input_port_settings_change(struct msm_vidc_inst *inst) u32 rc = 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", __func__); return 0; @@ -1588,7 +1588,7 @@ int msm_vdec_streamon_input(struct msm_vidc_inst *inst) } if (is_input_meta_enabled(inst) && - !inst->vb2q[INPUT_META_PORT].streaming) { + !inst->bufq[INPUT_META_PORT].vb2q->streaming) { i_vpr_e(inst, "%s: Meta port must be streamed on before data port\n", __func__); @@ -1897,7 +1897,7 @@ int msm_vdec_streamon_output(struct msm_vidc_inst *inst) capability = inst->capabilities; if (is_output_meta_enabled(inst) && - !inst->vb2q[OUTPUT_META_PORT].streaming) { + !inst->bufq[OUTPUT_META_PORT].vb2q->streaming) { i_vpr_e(inst, "%s: Meta port must be streamed on before data port\n", __func__); @@ -2347,8 +2347,8 @@ int msm_vdec_process_cmd(struct msm_vidc_inst *inst, u32 cmd) return rc; } else if (cmd == V4L2_DEC_CMD_START) { i_vpr_h(inst, "received cmd: resume\n"); - vb2_clear_last_buffer_dequeued(&inst->vb2q[OUTPUT_META_PORT]); - vb2_clear_last_buffer_dequeued(&inst->vb2q[OUTPUT_PORT]); + vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_META_PORT].vb2q); + vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_PORT].vb2q); if (capability->cap[CODED_FRAMES].value == CODED_FRAMES_INTERLACE && !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__); } } 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.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) { fmt = &inst->fmts[OUTPUT_PORT]; 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.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, 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, min_count, inst, MSM_VIDC_BUF_OUTPUT); 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__); /* 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.left = 0; 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, q16_rate, __func__); if (is_realtime_session(inst) && - ((s_parm->type == INPUT_MPLANE && inst->vb2q[INPUT_PORT].streaming) || - (s_parm->type == OUTPUT_MPLANE && inst->vb2q[OUTPUT_PORT].streaming))) { + ((s_parm->type == INPUT_MPLANE && inst->bufq[INPUT_PORT].vb2q->streaming) || + (s_parm->type == OUTPUT_MPLANE && inst->bufq[OUTPUT_PORT].vb2q->streaming))) { rc = msm_vidc_check_core_mbps(inst); if (rc) { 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; /* do not reject coloformats before streamon */ - if (!inst->vb2q[INPUT_PORT].streaming) + if (!inst->bufq[INPUT_PORT].vb2q->streaming) return true; /* diff --git a/driver/vidc/src/msm_venc.c b/driver/vidc/src/msm_venc.c index b959be39cf..4751ca96ba 100644 --- a/driver/vidc/src/msm_venc.c +++ b/driver/vidc/src/msm_venc.c @@ -815,7 +815,7 @@ int msm_venc_streamon_input(struct msm_vidc_inst *inst) } if (is_input_meta_enabled(inst) && - !inst->vb2q[INPUT_META_PORT].streaming) { + !inst->bufq[INPUT_META_PORT].vb2q->streaming) { i_vpr_e(inst, "%s: Meta port must be streamed on before data port\n", __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"); if (!msm_vidc_allow_start(inst)) return -EBUSY; - vb2_clear_last_buffer_dequeued(&inst->vb2q[OUTPUT_META_PORT]); - vb2_clear_last_buffer_dequeued(&inst->vb2q[OUTPUT_PORT]); + vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_META_PORT].vb2q); + vb2_clear_last_buffer_dequeued(inst->bufq[OUTPUT_PORT].vb2q); rc = msm_vidc_state_change_start(inst); if (rc) @@ -989,7 +989,7 @@ int msm_venc_streamon_output(struct msm_vidc_inst *inst) } if (is_output_meta_enabled(inst) && - !inst->vb2q[OUTPUT_META_PORT].streaming) { + !inst->bufq[OUTPUT_META_PORT].vb2q->streaming) { i_vpr_e(inst, "%s: Meta port must be streamed on before data port\n", __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, q16_rate, __func__); if (is_realtime_session(inst) && - ((s_parm->type == INPUT_MPLANE && inst->vb2q[INPUT_PORT].streaming) || - (s_parm->type == OUTPUT_MPLANE && inst->vb2q[OUTPUT_PORT].streaming))) { + ((s_parm->type == INPUT_MPLANE && inst->bufq[INPUT_PORT].vb2q->streaming) || + (s_parm->type == OUTPUT_MPLANE && inst->bufq[OUTPUT_PORT].vb2q->streaming))) { rc = msm_vidc_check_core_mbps(inst); if (rc) { 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. * 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, HFI_PROP_FRAME_RATE, HFI_HOST_FLAGS_NONE, diff --git a/driver/vidc/src/msm_vidc.c b/driver/vidc/src/msm_vidc.c index 8b955a407a..6c4d7a2a7e 100644 --- a/driver/vidc/src/msm_vidc.c +++ b/driver/vidc/src/msm_vidc.c @@ -51,7 +51,7 @@ static int get_poll_flags(struct msm_vidc_inst *inst, u32 port) __func__, inst, port); return poll; } - q = &inst->vb2q[port]; + q = inst->bufq[port].vb2q; spin_lock_irqsave(&q->done_lock, flags); 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->vb2q[INPUT_META_PORT].done_wq, wait); - poll_wait(filp, &inst->vb2q[OUTPUT_META_PORT].done_wq, wait); - poll_wait(filp, &inst->vb2q[INPUT_PORT].done_wq, wait); - poll_wait(filp, &inst->vb2q[OUTPUT_PORT].done_wq, wait); + poll_wait(filp, &inst->bufq[INPUT_META_PORT].vb2q->done_wq, wait); + poll_wait(filp, &inst->bufq[OUTPUT_META_PORT].vb2q->done_wq, wait); + poll_wait(filp, &inst->bufq[INPUT_PORT].vb2q->done_wq, wait); + poll_wait(filp, &inst->bufq[OUTPUT_PORT].vb2q->done_wq, wait); if (v4l2_event_pending(&inst->event_handler)) poll |= POLLPRI; @@ -402,7 +402,7 @@ int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b) goto exit; } - rc = vb2_reqbufs(&inst->vb2q[port], b); + rc = vb2_reqbufs(inst->bufq[port].vb2q, b); if (rc) { i_vpr_e(inst, "%s: vb2_reqbufs(%d) failed, %d\n", __func__, b->type, rc); @@ -511,7 +511,7 @@ int msm_vidc_streamon(void *instance, enum v4l2_buf_type type) goto exit; } - rc = vb2_streamon(&inst->vb2q[port], type); + rc = vb2_streamon(inst->bufq[port].vb2q, type); if (rc) { i_vpr_e(inst, "%s: vb2_streamon(%d) failed, %d\n", __func__, type, rc); @@ -556,7 +556,7 @@ int msm_vidc_streamoff(void *instance, enum v4l2_buf_type type) goto exit; } - rc = vb2_streamoff(&inst->vb2q[port], type); + rc = vb2_streamoff(inst->bufq[port].vb2q, type); if (rc) { i_vpr_e(inst, "%s: vb2_streamoff(%d) failed, %d\n", __func__, type, rc); @@ -833,6 +833,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type) inst->auto_framerate = DEFAULT_FPS << 16; kref_init(&inst->kref); mutex_init(&inst->lock); + mutex_init(&inst->request_lock); msm_vidc_update_debug_str(inst); 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; } - if (is_decode_session(inst)) - rc = msm_vdec_inst_init(inst); - else if (is_encode_session(inst)) - rc = msm_venc_inst_init(inst); + rc = msm_vidc_event_queue_init(inst); if (rc) goto error; @@ -914,7 +912,10 @@ void *msm_vidc_open(void *vidc_core, u32 session_type) if (rc) 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) goto error; diff --git a/driver/vidc/src/msm_vidc_control.c b/driver/vidc/src/msm_vidc_control.c index cbc67dc0d6..d5c1608829 100644 --- a/driver/vidc/src/msm_vidc_control.c +++ b/driver/vidc/src/msm_vidc_control.c @@ -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 && 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); else 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", __func__, inst->state, ctrl->name, ctrl->id, ctrl->val); - if (!msm_vidc_allow_s_ctrl(inst, ctrl->id)) { - i_vpr_e(inst, "%s: state %d, name %s, id %#x not allowed\n", - __func__, inst->state, ctrl->name, ctrl->id, ctrl->val); - return -EBUSY; - } + if (!msm_vidc_allow_s_ctrl(inst, ctrl->id)) + return -EINVAL; cap_id = msm_vidc_get_cap_id(inst, ctrl->id); 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; /* 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__); 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 */ - if (inst->vb2q[OUTPUT_PORT].streaming && + if (inst->bufq[OUTPUT_PORT].vb2q->streaming && !(capability->cap[cap_id].flags & CAP_FLAG_DYNAMIC_ALLOWED)) { i_vpr_e(inst, "%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 */ - 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; + } /* Dynamic set control ASAP */ 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__)) 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, client_layer_count); if (rc) @@ -1742,7 +1743,7 @@ int msm_vidc_adjust_bitrate(void *instance, struct v4l2_ctrl *ctrl) return 0; } - if (inst->vb2q[OUTPUT_PORT].streaming) + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) return 0; 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) return 0; - if (!inst->vb2q[OUTPUT_PORT].streaming) + if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) return 0; /* @@ -2167,7 +2168,7 @@ int msm_vidc_adjust_cac(void *instance, struct v4l2_ctrl *ctrl) adjusted_value = ctrl ? ctrl->val : capability->cap[CONTENT_ADAPTIVE_CODING].value; - if (inst->vb2q[OUTPUT_PORT].streaming) + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) return 0; 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 : capability->cap[BITRATE_BOOST].value; - if (inst->vb2q[OUTPUT_PORT].streaming) + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) return 0; 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 * runtime modification of MIN_QUALITY. */ - if (inst->vb2q[OUTPUT_PORT].streaming) + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) return 0; 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__)) return -EINVAL; - if (inst->vb2q[OUTPUT_PORT].streaming) { + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) { if (rc_type != HFI_RC_OFF) { i_vpr_h(inst, "%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; } - if (!inst->vb2q[OUTPUT_PORT].streaming) { + if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) { /* set layer type */ hfi_layer_type = inst->hfi_layer_type; cap_id = LAYER_TYPE; @@ -3112,7 +3113,7 @@ int msm_vidc_set_gop_size(void *instance, return -EINVAL; } - if (inst->vb2q[OUTPUT_PORT].streaming) { + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) { if (inst->hfi_layer_type == HFI_HIER_B) { i_vpr_l(inst, "%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 * to fw. */ - if (inst->vb2q[OUTPUT_PORT].streaming) + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) return 0; if (msm_vidc_get_parent_value(inst, BIT_RATE, @@ -3218,7 +3219,7 @@ int msm_vidc_set_dynamic_layer_bitrate(void *instance, return -EINVAL; } - if (!inst->vb2q[OUTPUT_PORT].streaming) + if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) return 0; /* set Total Bitrate */ @@ -3311,7 +3312,7 @@ int msm_vidc_set_flip(void *instance, if (vflip) hfi_value |= HFI_VERTICAL_FLIP; - if (inst->vb2q[OUTPUT_PORT].streaming) { + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) { if (hfi_value != HFI_DISABLE_FLIP) { rc = msm_vidc_set_req_sync_frame(inst, REQUEST_I_FRAME); diff --git a/driver/vidc/src/msm_vidc_debug.c b/driver/vidc/src/msm_vidc_debug.c index 3f476ab1ad..ac29f02821 100644 --- a/driver/vidc/src/msm_vidc_debug.c +++ b/driver/vidc/src/msm_vidc_debug.c @@ -487,7 +487,7 @@ static ssize_t inst_info_read(struct file *file, char __user *buf, "type: %s\n", i == INPUT_PORT ? "Output" : "Capture"); 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++) cur += write_str(cur, end - cur, diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index 665e3558ac..2e70e4f4d2 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/driver/vidc/src/msm_vidc_driver.c @@ -1285,11 +1285,11 @@ bool msm_vidc_allow_s_ctrl(struct msm_vidc_inst *inst, u32 id) goto exit; } if (is_decode_session(inst)) { - if (!inst->vb2q[INPUT_PORT].streaming) { + if (!inst->bufq[INPUT_PORT].vb2q->streaming) { allow = true; goto exit; } - if (inst->vb2q[INPUT_PORT].streaming) { + if (inst->bufq[INPUT_PORT].vb2q->streaming) { switch (id) { case V4L2_CID_MPEG_VIDC_CODEC_CONFIG: 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; } if (type == INPUT_MPLANE) { - if (!inst->vb2q[INPUT_PORT].streaming) + if (!inst->bufq[INPUT_PORT].vb2q->streaming) allow = MSM_VIDC_IGNORE; } else if (type == INPUT_META_PLANE) { - if (inst->vb2q[INPUT_PORT].streaming) + if (inst->bufq[INPUT_PORT].vb2q->streaming) 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; } else if (type == OUTPUT_MPLANE) { - if (!inst->vb2q[OUTPUT_PORT].streaming) + if (!inst->bufq[OUTPUT_PORT].vb2q->streaming) allow = MSM_VIDC_IGNORE; } else if (type == OUTPUT_META_PLANE) { - if (inst->vb2q[OUTPUT_PORT].streaming) + if (inst->bufq[OUTPUT_PORT].vb2q->streaming) 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; } 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; /* defer queuing if streamon not completed */ - if (!inst->vb2q[port].streaming) + if (!inst->bufq[port].vb2q->streaming) return MSM_VIDC_DEFER; 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) return -EINVAL; - q = &inst->vb2q[port]; + q = inst->bufq[port].vb2q; if (!q->streaming) { i_vpr_e(inst, "%s: port %d is not streaming\n", __func__, port); @@ -3675,6 +3675,7 @@ int msm_vidc_vb2_buffer_done(struct msm_vidc_inst *inst, vbuf->flags = buf->flags; vb2->timestamp = buf->timestamp; 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); return 0; @@ -3754,45 +3755,112 @@ static int vb2q_init(struct msm_vidc_inst *inst, 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 rc = 0; + struct msm_vidc_core *core; - if (!inst) { - i_vpr_e(inst, "%s: invalid params\n", __func__); + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } + core = inst->core; if (inst->vb2q_init) { i_vpr_h(inst, "%s: vb2q already inited\n", __func__); return 0; } - rc = vb2q_init(inst, &inst->vb2q[INPUT_PORT], INPUT_MPLANE); - if (rc) - goto exit; + inst->m2m_dev = v4l2_m2m_init(core->v4l2_m2m_ops); + if (IS_ERR(inst->m2m_dev)) { + 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); - if (rc) - goto fail_out_vb2q_init; + /* v4l2_m2m_ctx_init will do input & output queues initialization */ + inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_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) 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) goto fail_out_meta_vb2q_init; inst->vb2q_init = true; return 0; + 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: - vb2_queue_release(&inst->vb2q[OUTPUT_PORT]); -fail_out_vb2q_init: - vb2_queue_release(&inst->vb2q[INPUT_PORT]); -exit: + kfree(inst->bufq[INPUT_META_PORT].vb2q); + inst->bufq[INPUT_META_PORT].vb2q = NULL; +fail_in_meta_alloc: + 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; } @@ -3809,10 +3877,20 @@ int msm_vidc_vb2_queue_deinit(struct msm_vidc_inst *inst) return 0; } - 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]); + vb2_queue_release(inst->bufq[OUTPUT_META_PORT].vb2q); + kfree(inst->bufq[OUTPUT_META_PORT].vb2q); + inst->bufq[OUTPUT_META_PORT].vb2q = NULL; + 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; return rc; @@ -5169,6 +5247,8 @@ static void msm_vidc_close_helper(struct kref *kref) if (inst->response_workq) destroy_workqueue(inst->response_workq); msm_vidc_remove_dangling_session(inst); + mutex_destroy(&inst->request_lock); + mutex_destroy(&inst->lock); kfree(inst->capabilities); kfree(inst); } @@ -5371,7 +5451,7 @@ int msm_vidc_update_buffer_count(struct msm_vidc_inst *inst, u32 port) inst->buffers.input.actual_count); break; 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, min_count, inst, MSM_VIDC_BUF_OUTPUT); inst->buffers.output.extra_count = call_session_op(core, diff --git a/driver/vidc/src/msm_vidc_platform.c b/driver/vidc/src/msm_vidc_platform.c index 8fb06d0793..a8757629cc 100644 --- a/driver/vidc/src/msm_vidc_platform.c +++ b/driver/vidc/src/msm_vidc_platform.c @@ -120,6 +120,8 @@ static struct vb2_ops msm_vb2_ops = { .buf_queue = msm_vidc_buf_queue, .buf_cleanup = msm_vidc_buf_cleanup, .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 = { @@ -131,6 +133,16 @@ static struct vb2_mem_ops msm_vb2_mem_ops = { .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) { 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->vb2_ops = &msm_vb2_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; } diff --git a/driver/vidc/src/msm_vidc_probe.c b/driver/vidc/src/msm_vidc_probe.c index 2a7485a679..945cb0648b 100644 --- a/driver/vidc/src/msm_vidc_probe.c +++ b/driver/vidc/src/msm_vidc_probe.c @@ -142,6 +142,11 @@ static void msm_vidc_unregister_video_device(struct msm_vidc_core *core, else 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); video_set_drvdata(&core->vdev[index].vdev, NULL); 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) { int rc = 0; - int index; + int index, media_index; d_vpr_h("%s()\n", __func__); - if (type == MSM_VIDC_DECODER) + if (type == MSM_VIDC_DECODER) { index = 0; - else if (type == MSM_VIDC_ENCODER) + media_index = MEDIA_ENT_F_PROC_VIDEO_DECODER; + } else if (type == MSM_VIDC_ENCODER) { index = 1; - else + media_index = MEDIA_ENT_F_PROC_VIDEO_ENCODER; + } else { return -EINVAL; + } core->vdev[index].vdev.release = 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); if (rc) { d_vpr_e("Failed to create video device file\n"); - video_unregister_device(&core->vdev[index].vdev); - return rc; + goto video_reg_failed; } +#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; +#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) @@ -333,12 +364,18 @@ static int msm_vidc_remove(struct platform_device* pdev) msm_vidc_core_deinit(core, true); 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_DECODER); //device_remove_file(&core->vdev[MSM_VIDC_ENCODER].vdev.dev, //&dev_attr_link_name); //device_remove_file(&core->vdev[MSM_VIDC_DECODER].vdev.dev, //&dev_attr_link_name); +#ifdef CONFIG_MEDIA_CONTROLLER + media_device_cleanup(&core->media_dev); +#endif v4l2_device_unregister(&core->v4l2_dev); 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; } +#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 */ rc = msm_vidc_register_video_device(core, MSM_VIDC_DECODER, nr); 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"); 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); if (rc) { 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: of_platform_depopulate(&pdev->dev); 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); enc_reg_failed: msm_vidc_unregister_video_device(core, MSM_VIDC_DECODER); diff --git a/driver/vidc/src/msm_vidc_v4l2.c b/driver/vidc/src/msm_vidc_v4l2.c index 8ba23827f0..7dbbf744d4 100644 --- a/driver/vidc/src/msm_vidc_v4l2.c +++ b/driver/vidc/src/msm_vidc_v4l2.c @@ -696,3 +696,30 @@ unlock: 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); +} \ No newline at end of file diff --git a/driver/vidc/src/msm_vidc_vb2.c b/driver/vidc/src/msm_vidc_vb2.c index 4cfd2f9816..d05bdeb9af 100644 --- a/driver/vidc/src/msm_vidc_vb2.c +++ b/driver/vidc/src/msm_vidc_vb2.c @@ -24,13 +24,13 @@ struct vb2_queue *msm_vidc_get_vb2q(struct msm_vidc_inst *inst, return NULL; } if (type == INPUT_MPLANE) { - q = &inst->vb2q[INPUT_PORT]; + q = inst->bufq[INPUT_PORT].vb2q; } else if (type == OUTPUT_MPLANE) { - q = &inst->vb2q[OUTPUT_PORT]; + q = inst->bufq[OUTPUT_PORT].vb2q; } 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) { - q = &inst->vb2q[OUTPUT_META_PORT]; + q = inst->bufq[OUTPUT_META_PORT].vb2q; } else { i_vpr_e(inst, "%s: invalid buffer type %d\n", __func__, type); @@ -263,8 +263,8 @@ int msm_vidc_start_streaming(struct vb2_queue *q, unsigned int count) if (rc) goto error; - if ((q->type == INPUT_MPLANE && inst->vb2q[OUTPUT_PORT].streaming) || - (q->type == OUTPUT_MPLANE && inst->vb2q[INPUT_PORT].streaming)) { + if ((q->type == INPUT_MPLANE && inst->bufq[OUTPUT_PORT].vb2q->streaming) || + (q->type == OUTPUT_MPLANE && inst->bufq[INPUT_PORT].vb2q->streaming)) { rc = msm_vidc_get_properties(inst); if (rc) goto error; @@ -345,6 +345,28 @@ void msm_vidc_buf_queue(struct vb2_buffer *vb2) 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)) rc = msm_vdec_qbuf(inst, vb2); else if (is_encode_session(inst)) @@ -355,6 +377,7 @@ void msm_vidc_buf_queue(struct vb2_buffer *vb2) if (rc) { print_vb2_buffer("failed vb2-qbuf", inst, vb2); 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); } } @@ -362,3 +385,20 @@ void msm_vidc_buf_queue(struct vb2_buffer *vb2) 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); +}