diff options
Diffstat (limited to 'drivers/media/platform/mediatek/vcodec/decoder')
15 files changed, 117 insertions, 58 deletions
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c index 1f32ba11a18c..d76e891f784b 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c @@ -882,8 +882,10 @@ void vb2ops_vdec_stop_streaming(struct vb2_queue *q) src_buf->vb2_buf.req_obj.req; v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR); - if (req) + if (req) { v4l2_ctrl_request_complete(req, &ctx->ctrl_hdl); + media_request_manual_complete(req); + } } } return; diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c index 3b81fae9f913..e936ed8dffba 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c @@ -200,7 +200,7 @@ static int fops_vcodec_open(struct file *file) struct vb2_queue *src_vq; unsigned long flags; - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + ctx = kzalloc_obj(*ctx); if (!ctx) return -ENOMEM; diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h index 9d68808e8f9c..c9d27534c63e 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h @@ -7,6 +7,8 @@ #ifndef _MTK_VCODEC_DEC_DRV_H_ #define _MTK_VCODEC_DEC_DRV_H_ +#include <linux/kref.h> + #include "../common/mtk_vcodec_cmn_drv.h" #include "../common/mtk_vcodec_dbgfs.h" #include "../common/mtk_vcodec_fw_priv.h" @@ -129,6 +131,16 @@ struct mtk_vcodec_dec_pdata { }; /** + * struct mtk_vcodec_dec_request - Media request private data. + * @refcount: Used to ensure we don't complete the request too soon + * @req: Media Request structure + */ +struct mtk_vcodec_dec_request { + struct kref refcount; + struct media_request req; +}; + +/** * struct mtk_vcodec_dec_ctx - Context (instance) private data. * * @type: type of decoder instance @@ -324,6 +336,11 @@ static inline struct mtk_vcodec_dec_ctx *ctrl_to_dec_ctx(struct v4l2_ctrl *ctrl) return container_of(ctrl->handler, struct mtk_vcodec_dec_ctx, ctrl_hdl); } +static inline struct mtk_vcodec_dec_request *req_to_dec_req(struct media_request *req) +{ + return container_of(req, struct mtk_vcodec_dec_request, req); +} + /* Wake up context wait_queue */ static inline void wake_up_dec_ctx(struct mtk_vcodec_dec_ctx *ctx, unsigned int reason, unsigned int hw_id) diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c index aefd3e9e3061..f6f03c61c643 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_pm.c @@ -67,11 +67,7 @@ static int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm) static void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm) { - int ret; - - ret = pm_runtime_put(pm->dev); - if (ret && ret != -EAGAIN) - dev_err(pm->dev, "pm_runtime_put fail %d", ret); + pm_runtime_put(pm->dev); } static void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm) diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c index d873159b9b30..ab1894fba0d9 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c @@ -242,10 +242,18 @@ static const struct v4l2_frmsize_stepwise stepwise_fhd = { .step_height = 16 }; +static void mtk_vcodec_dec_request_release(struct kref *ref) +{ + struct mtk_vcodec_dec_request *req = + container_of(ref, struct mtk_vcodec_dec_request, refcount); + media_request_manual_complete(&req->req); +} + static void mtk_vdec_stateless_cap_to_disp(struct mtk_vcodec_dec_ctx *ctx, int error, - struct media_request *src_buf_req) + struct media_request *mreq) { - struct vb2_v4l2_buffer *vb2_dst; + struct mtk_vcodec_dec_request *req = req_to_dec_req(mreq); + struct vb2_v4l2_buffer *dst_buf; enum vb2_buffer_state state; if (error) @@ -253,17 +261,9 @@ static void mtk_vdec_stateless_cap_to_disp(struct mtk_vcodec_dec_ctx *ctx, int e else state = VB2_BUF_STATE_DONE; - vb2_dst = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); - if (vb2_dst) { - v4l2_m2m_buf_done(vb2_dst, state); - mtk_v4l2_vdec_dbg(2, ctx, "free frame buffer id:%d to done list", - vb2_dst->vb2_buf.index); - } else { - mtk_v4l2_vdec_err(ctx, "dst buffer is NULL"); - } - - if (src_buf_req) - v4l2_ctrl_request_complete(src_buf_req, &ctx->ctrl_hdl); + dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); + v4l2_m2m_buf_done(dst_buf, state); + kref_put(&req->refcount, mtk_vcodec_dec_request_release); } static struct vdec_fb *vdec_get_cap_buffer(struct mtk_vcodec_dec_ctx *ctx) @@ -306,6 +306,7 @@ static void vb2ops_vdec_buf_request_complete(struct vb2_buffer *vb) struct mtk_vcodec_dec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); v4l2_ctrl_request_complete(vb->req_obj.req, &ctx->ctrl_hdl); + media_request_manual_complete(vb->req_obj.req); } static void mtk_vdec_worker(struct work_struct *work) @@ -317,8 +318,9 @@ static void mtk_vdec_worker(struct work_struct *work) struct vb2_buffer *vb2_src; struct mtk_vcodec_mem *bs_src; struct mtk_video_dec_buf *dec_buf_src; - struct media_request *src_buf_req; - enum vb2_buffer_state state; + struct media_request *mreq; + struct mtk_vcodec_dec_request *req; + enum vb2_buffer_state buf_state; bool res_chg = false; int ret; @@ -350,14 +352,26 @@ static void mtk_vdec_worker(struct work_struct *work) mtk_v4l2_vdec_dbg(3, ctx, "[%d] Bitstream VA=%p DMA=%pad Size=%zx vb=%p", ctx->id, bs_src->va, &bs_src->dma_addr, bs_src->size, vb2_src); /* Apply request controls. */ - src_buf_req = vb2_src->req_obj.req; - if (src_buf_req) - v4l2_ctrl_request_setup(src_buf_req, &ctx->ctrl_hdl); - else + mreq = vb2_src->req_obj.req; + if (WARN_ON(!mreq)) { + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); mtk_v4l2_vdec_err(ctx, "vb2 buffer media request is NULL"); + return; + } + + v4l2_ctrl_request_setup(mreq, &ctx->ctrl_hdl); + + /* Keep a reference so that if the processing completes before this function + * ends, we won't accidently update a freshly queued request. + */ + req = req_to_dec_req(mreq); + kref_get(&req->refcount); ret = vdec_if_decode(ctx, bs_src, NULL, &res_chg); - if (ret && ret != -EAGAIN) { + if (ret == -EAGAIN) + goto done; + + if (ret) { mtk_v4l2_vdec_err(ctx, "[%d] decode src_buf[%d] sz=0x%zx pts=%llu ret=%d res_chg=%d", ctx->id, vb2_src->index, bs_src->size, @@ -367,21 +381,23 @@ static void mtk_vdec_worker(struct work_struct *work) dec_buf_src->error = true; mutex_unlock(&ctx->lock); } - } - state = ret ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE; - if (!IS_VDEC_LAT_ARCH(dev->vdec_pdata->hw_arch) || - ctx->current_codec == V4L2_PIX_FMT_VP8_FRAME) { - v4l2_m2m_buf_done_and_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx, state); - if (src_buf_req) - v4l2_ctrl_request_complete(src_buf_req, &ctx->ctrl_hdl); + buf_state = VB2_BUF_STATE_ERROR; } else { - if (ret != -EAGAIN) { - v4l2_m2m_src_buf_remove(ctx->m2m_ctx); - v4l2_m2m_buf_done(vb2_v4l2_src, state); - } - v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); + buf_state = VB2_BUF_STATE_DONE; } + + v4l2_ctrl_request_complete(mreq, &ctx->ctrl_hdl); + v4l2_m2m_src_buf_remove(ctx->m2m_ctx); + v4l2_m2m_buf_done(vb2_v4l2_src, buf_state); + + if (ret || !IS_VDEC_LAT_ARCH(dev->vdec_pdata->hw_arch) || + ctx->current_codec == V4L2_PIX_FMT_VP8_FRAME) + mtk_vdec_stateless_cap_to_disp(ctx, ret, mreq); + +done: + kref_put(&req->refcount, mtk_vcodec_dec_request_release); + v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx); } static void vb2ops_vdec_stateless_buf_queue(struct vb2_buffer *vb) @@ -502,6 +518,12 @@ static int mtk_vdec_s_ctrl(struct v4l2_ctrl *ctrl) mtk_v4l2_vdec_err(ctx, "VP9: bit_depth:%d", frame->bit_depth); return -EINVAL; } + + if (!(frame->flags & V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING) || + !(frame->flags & V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING)) { + mtk_v4l2_vdec_err(ctx, "VP9: only 420 subsampling is supported"); + return -EINVAL; + } break; case V4L2_CID_STATELESS_AV1_SEQUENCE: seq = (struct v4l2_ctrl_av1_sequence *)hdr_ctrl->p_new.p; @@ -709,6 +731,22 @@ static int mtk_vcodec_dec_ctrls_setup(struct mtk_vcodec_dec_ctx *ctx) return 0; } +static struct media_request *fops_media_request_alloc(struct media_device *mdev) +{ + struct mtk_vcodec_dec_request *req; + + req = kzalloc_obj(*req); + + return &req->req; +} + +static void fops_media_request_free(struct media_request *mreq) +{ + struct mtk_vcodec_dec_request *req = req_to_dec_req(mreq); + + kfree(req); +} + static int fops_media_request_validate(struct media_request *mreq) { const unsigned int buffer_cnt = vb2_request_buffer_cnt(mreq); @@ -729,9 +767,20 @@ static int fops_media_request_validate(struct media_request *mreq) return vb2_request_validate(mreq); } +static void fops_media_request_queue(struct media_request *mreq) +{ + struct mtk_vcodec_dec_request *req = req_to_dec_req(mreq); + + media_request_mark_manual_completion(mreq); + kref_init(&req->refcount); + v4l2_m2m_request_queue(mreq); +} + const struct media_device_ops mtk_vcodec_media_ops = { + .req_alloc = fops_media_request_alloc, + .req_free = fops_media_request_free, .req_validate = fops_media_request_validate, - .req_queue = v4l2_m2m_request_queue, + .req_queue = fops_media_request_queue, }; static void mtk_vcodec_add_formats(unsigned int fourcc, diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_av1_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_av1_req_lat_if.c index 7be4b6086920..2d622e85f827 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_av1_req_lat_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_av1_req_lat_if.c @@ -1879,7 +1879,7 @@ static int vdec_av1_slice_init(struct mtk_vcodec_dec_ctx *ctx) struct vdec_av1_slice_init_vsi *vsi; int ret; - instance = kzalloc(sizeof(*instance), GFP_KERNEL); + instance = kzalloc_obj(*instance); if (!instance) return -ENOMEM; diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_if.c index 795cb19b075d..a95327388f57 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_if.c @@ -270,7 +270,7 @@ static int vdec_h264_init(struct mtk_vcodec_dec_ctx *ctx) struct vdec_h264_inst *inst = NULL; int err; - inst = kzalloc(sizeof(*inst), GFP_KERNEL); + inst = kzalloc_obj(*inst); if (!inst) return -ENOMEM; diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_if.c index b9a5ea7887d3..1f691cd2f4c3 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_if.c @@ -273,7 +273,7 @@ static int vdec_h264_slice_init(struct mtk_vcodec_dec_ctx *ctx) struct vdec_h264_slice_inst *inst; int err; - inst = kzalloc(sizeof(*inst), GFP_KERNEL); + inst = kzalloc_obj(*inst); if (!inst) return -ENOMEM; diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c index 9a9dc2f88d6e..10359ce9b934 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_h264_req_multi_if.c @@ -1208,7 +1208,7 @@ static int vdec_h264_slice_init(struct mtk_vcodec_dec_ctx *ctx) int err, vsi_size; unsigned char *temp; - inst = kzalloc(sizeof(*inst), GFP_KERNEL); + inst = kzalloc_obj(*inst); if (!inst) return -ENOMEM; diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c index 88eca50c2017..02f39954a4c2 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c @@ -858,7 +858,7 @@ static int vdec_hevc_slice_init(struct mtk_vcodec_dec_ctx *ctx) struct vdec_hevc_slice_inst *inst; int err, vsi_size; - inst = kzalloc(sizeof(*inst), GFP_KERNEL); + inst = kzalloc_obj(*inst); if (!inst) return -ENOMEM; diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_if.c index 5f848691cea4..fd15d462b168 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_if.c @@ -390,7 +390,7 @@ static int vdec_vp8_init(struct mtk_vcodec_dec_ctx *ctx) struct vdec_vp8_inst *inst; int err; - inst = kzalloc(sizeof(*inst), GFP_KERNEL); + inst = kzalloc_obj(*inst); if (!inst) return -ENOMEM; diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_req_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_req_if.c index e1d4960553f2..391e789a5a13 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_req_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_req_if.c @@ -275,7 +275,7 @@ static int vdec_vp8_slice_init(struct mtk_vcodec_dec_ctx *ctx) struct vdec_vp8_slice_inst *inst; int err; - inst = kzalloc(sizeof(*inst), GFP_KERNEL); + inst = kzalloc_obj(*inst); if (!inst) return -ENOMEM; diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_if.c index eb3354192853..80554b2c26c0 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_if.c @@ -548,10 +548,9 @@ static bool vp9_wait_dec_end(struct vdec_vp9_inst *inst) static struct vdec_vp9_inst *vp9_alloc_inst(struct mtk_vcodec_dec_ctx *ctx) { int result; - struct mtk_vcodec_mem mem; + struct mtk_vcodec_mem mem = { }; struct vdec_vp9_inst *inst; - memset(&mem, 0, sizeof(mem)); mem.size = sizeof(struct vdec_vp9_inst); result = mtk_vcodec_mem_alloc(ctx, &mem); if (result) diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c index cd1935014d76..adbacabdbebc 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c @@ -1848,7 +1848,7 @@ static int vdec_vp9_slice_init(struct mtk_vcodec_dec_ctx *ctx) struct vdec_vp9_slice_init_vsi *vsi; int ret; - instance = kzalloc(sizeof(*instance), GFP_KERNEL); + instance = kzalloc_obj(*instance); if (!instance) return -ENOMEM; diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c index 40b97f114cf6..b35759a0b353 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c @@ -182,12 +182,11 @@ static int vcodec_vpu_send_msg(struct vdec_vpu_inst *vpu, void *msg, int len) static int vcodec_send_ap_ipi(struct vdec_vpu_inst *vpu, unsigned int msg_id) { - struct vdec_ap_ipi_cmd msg; + struct vdec_ap_ipi_cmd msg = { }; int err = 0; mtk_vdec_debug(vpu->ctx, "+ id=%X", msg_id); - memset(&msg, 0, sizeof(msg)); msg.msg_id = msg_id; if (vpu->fw_abi_version < 2) msg.vpu_inst_addr = vpu->inst_addr; @@ -202,7 +201,7 @@ static int vcodec_send_ap_ipi(struct vdec_vpu_inst *vpu, unsigned int msg_id) int vpu_dec_init(struct vdec_vpu_inst *vpu) { - struct vdec_ap_ipi_init msg; + struct vdec_ap_ipi_init msg = { }; int err; init_waitqueue_head(&vpu->wq); @@ -226,7 +225,6 @@ int vpu_dec_init(struct vdec_vpu_inst *vpu) } } - memset(&msg, 0, sizeof(msg)); msg.msg_id = AP_IPIMSG_DEC_INIT; msg.ap_inst_addr = (unsigned long)vpu; msg.codec_type = vpu->codec_type; @@ -246,7 +244,7 @@ int vpu_dec_init(struct vdec_vpu_inst *vpu) int vpu_dec_start(struct vdec_vpu_inst *vpu, uint32_t *data, unsigned int len) { - struct vdec_ap_ipi_dec_start msg; + struct vdec_ap_ipi_dec_start msg = { }; int i; int err = 0; @@ -255,7 +253,6 @@ int vpu_dec_start(struct vdec_vpu_inst *vpu, uint32_t *data, unsigned int len) return -EINVAL; } - memset(&msg, 0, sizeof(msg)); msg.msg_id = AP_IPIMSG_DEC_START; if (vpu->fw_abi_version < 2) msg.vpu_inst_addr = vpu->inst_addr; @@ -274,7 +271,7 @@ int vpu_dec_start(struct vdec_vpu_inst *vpu, uint32_t *data, unsigned int len) int vpu_dec_get_param(struct vdec_vpu_inst *vpu, uint32_t *data, unsigned int len, unsigned int param_type) { - struct vdec_ap_ipi_get_param msg; + struct vdec_ap_ipi_get_param msg = { }; int err; if (len > ARRAY_SIZE(msg.data)) { @@ -282,7 +279,6 @@ int vpu_dec_get_param(struct vdec_vpu_inst *vpu, uint32_t *data, return -EINVAL; } - memset(&msg, 0, sizeof(msg)); msg.msg_id = AP_IPIMSG_DEC_GET_PARAM; msg.inst_id = vpu->inst_id; memcpy(msg.data, data, sizeof(unsigned int) * len); |
