media: mtk-vcodec: Add work queue for core hardware decode

Add work queue to process core hardware information.
First, get lat_buf from message queue, then call core
hardware of each codec(H264/VP9/AV1) to decode, finally
puts lat_buf back to the message.

Signed-off-by: Yunfei Dong <yunfei.dong@mediatek.com>
Reviewed-by: Steve Cho <stevecho@chromium.org>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
Yunfei Dong 2022-01-13 05:10:50 +01:00 committed by Mauro Carvalho Chehab
parent 66e860ffed
commit 365e4ba01d
4 changed files with 53 additions and 1 deletions

View File

@ -311,6 +311,18 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
goto err_dec_pm;
}
if (IS_VDEC_LAT_ARCH(dev->vdec_pdata->hw_arch)) {
vdec_msg_queue_init_ctx(&dev->msg_queue_core_ctx, MTK_VDEC_CORE);
dev->core_workqueue =
alloc_ordered_workqueue("core-decoder",
WQ_MEM_RECLAIM | WQ_FREEZABLE);
if (!dev->core_workqueue) {
mtk_v4l2_err("Failed to create core workqueue");
ret = -EINVAL;
goto err_res;
}
}
for (i = 0; i < MTK_VDEC_HW_MAX; i++)
mutex_init(&dev->dec_mutex[i]);
mutex_init(&dev->dev_mutex);
@ -322,7 +334,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
if (ret) {
mtk_v4l2_err("v4l2_device_register err=%d", ret);
goto err_res;
goto err_core_workq;
}
init_waitqueue_head(&dev->queue);
@ -423,6 +435,9 @@ err_dec_mem_init:
video_unregister_device(vfd_dec);
err_dec_alloc:
v4l2_device_unregister(&dev->v4l2_dev);
err_core_workq:
if (IS_VDEC_LAT_ARCH(dev->vdec_pdata->hw_arch))
destroy_workqueue(dev->core_workqueue);
err_res:
mtk_vcodec_release_dec_pm(&dev->pm);
err_dec_pm:

View File

@ -27,6 +27,7 @@
#define MTK_VCODEC_MAX_PLANES 3
#define MTK_V4L2_BENCHMARK 0
#define WAIT_INTR_TIMEOUT_MS 1000
#define IS_VDEC_LAT_ARCH(hw_arch) ((hw_arch) >= MTK_VDEC_LAT_SINGLE_CORE)
/*
* enum mtk_hw_reg_idx - MTK hw register base index
@ -464,6 +465,7 @@ struct mtk_vcodec_enc_pdata {
* @dec_capability: used to identify decode capability, ex: 4k
* @enc_capability: used to identify encode capability
*
* @core_workqueue: queue used for core hardware decode
* @msg_queue_core_ctx: msg queue context used for core workqueue
*
* @subdev_dev: subdev hardware device
@ -508,6 +510,7 @@ struct mtk_vcodec_dev {
unsigned int dec_capability;
unsigned int enc_capability;
struct workqueue_struct *core_workqueue;
struct vdec_msg_queue_ctx msg_queue_core_ctx;
void *subdev_dev[MTK_VDEC_HW_MAX];

View File

@ -68,6 +68,9 @@ int vdec_msg_queue_qbuf(struct vdec_msg_queue_ctx *msg_ctx, struct vdec_lat_buf
if (msg_ctx->hardware_index != MTK_VDEC_CORE)
wake_up_all(&msg_ctx->ready_to_use);
else
queue_work(buf->ctx->dev->core_workqueue,
&buf->ctx->msg_queue.core_work);
mtk_v4l2_debug(3, "enqueue buf type: %d addr: 0x%p num: %d",
msg_ctx->hardware_index, buf, msg_ctx->ready_num);
@ -195,6 +198,34 @@ void vdec_msg_queue_deinit(struct vdec_msg_queue *msg_queue,
}
}
static void vdec_msg_queue_core_work(struct work_struct *work)
{
struct vdec_msg_queue *msg_queue =
container_of(work, struct vdec_msg_queue, core_work);
struct mtk_vcodec_ctx *ctx =
container_of(msg_queue, struct mtk_vcodec_ctx, msg_queue);
struct mtk_vcodec_dev *dev = ctx->dev;
struct vdec_lat_buf *lat_buf;
lat_buf = vdec_msg_queue_dqbuf(&dev->msg_queue_core_ctx);
if (!lat_buf)
return;
ctx = lat_buf->ctx;
mtk_vcodec_set_curr_ctx(dev, ctx, MTK_VDEC_CORE);
lat_buf->core_decode(lat_buf);
mtk_vcodec_set_curr_ctx(dev, NULL, MTK_VDEC_CORE);
vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf);
if (!list_empty(&ctx->msg_queue.lat_ctx.ready_queue)) {
mtk_v4l2_debug(3, "re-schedule to decode for core: %d",
dev->msg_queue_core_ctx.ready_num);
queue_work(dev->core_workqueue, &msg_queue->core_work);
}
}
int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
struct mtk_vcodec_ctx *ctx, core_decode_cb_t core_decode,
int private_size)
@ -207,6 +238,7 @@ int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
return 0;
vdec_msg_queue_init_ctx(&msg_queue->lat_ctx, MTK_VDEC_LAT0);
INIT_WORK(&msg_queue->core_work, vdec_msg_queue_core_work);
msg_queue->wdma_addr.size =
vde_msg_queue_get_trans_size(ctx->picinfo.buf_w,
ctx->picinfo.buf_h);

View File

@ -68,6 +68,7 @@ struct vdec_lat_buf {
* @wdma_addr: wdma address used for ube
* @wdma_rptr_addr: ube read point
* @wdma_wptr_addr: ube write point
* @core_work: core hardware work
* @lat_ctx: used to store lat buffer list
*/
struct vdec_msg_queue {
@ -77,6 +78,7 @@ struct vdec_msg_queue {
u64 wdma_rptr_addr;
u64 wdma_wptr_addr;
struct work_struct core_work;
struct vdec_msg_queue_ctx lat_ctx;
};