xref: /linux/drivers/media/platform/mediatek/vcodec/decoder/vdec_msg_queue.c (revision a23e1966932464e1c5226cb9ac4ce1d5fc10ba22)
1b199fe46SYunfei Dong // SPDX-License-Identifier: GPL-2.0
2b199fe46SYunfei Dong /*
3b199fe46SYunfei Dong  * Copyright (c) 2021 MediaTek Inc.
4b199fe46SYunfei Dong  * Author: Yunfei Dong <yunfei.dong@mediatek.com>
5b199fe46SYunfei Dong  */
6b199fe46SYunfei Dong 
7b199fe46SYunfei Dong #include <linux/freezer.h>
8b199fe46SYunfei Dong #include <linux/interrupt.h>
9b199fe46SYunfei Dong #include <linux/kthread.h>
10b199fe46SYunfei Dong 
11*31272a39SYunfei Dong #include "mtk_vcodec_dec_drv.h"
12b199fe46SYunfei Dong #include "mtk_vcodec_dec_pm.h"
13b199fe46SYunfei Dong #include "vdec_msg_queue.h"
14b199fe46SYunfei Dong 
15b199fe46SYunfei Dong #define VDEC_MSG_QUEUE_TIMEOUT_MS 1500
16b199fe46SYunfei Dong 
17b199fe46SYunfei Dong /* the size used to store lat slice header information */
18b199fe46SYunfei Dong #define VDEC_LAT_SLICE_HEADER_SZ    (640 * SZ_1K)
19b199fe46SYunfei Dong 
20b199fe46SYunfei Dong /* the size used to store avc error information */
21b199fe46SYunfei Dong #define VDEC_ERR_MAP_SZ_AVC         (17 * SZ_1K)
22b199fe46SYunfei Dong 
232f5d0aefSXiaoyong Lu #define VDEC_RD_MV_BUFFER_SZ        (((SZ_4K * 2304 >> 4) + SZ_1K) << 1)
242f5d0aefSXiaoyong Lu #define VDEC_LAT_TILE_SZ            (64 * V4L2_AV1_MAX_TILE_COUNT)
252f5d0aefSXiaoyong Lu 
26b199fe46SYunfei Dong /* core will read the trans buffer which decoded by lat to decode again.
27b199fe46SYunfei Dong  * The trans buffer size of FHD and 4K bitstreams are different.
28b199fe46SYunfei Dong  */
vde_msg_queue_get_trans_size(int width,int height)29b199fe46SYunfei Dong static int vde_msg_queue_get_trans_size(int width, int height)
30b199fe46SYunfei Dong {
31b199fe46SYunfei Dong 	if (width > 1920 || height > 1088)
32b199fe46SYunfei Dong 		return 30 * SZ_1M;
33b199fe46SYunfei Dong 	else
34b199fe46SYunfei Dong 		return 6 * SZ_1M;
35b199fe46SYunfei Dong }
36b199fe46SYunfei Dong 
vdec_msg_queue_init_ctx(struct vdec_msg_queue_ctx * ctx,int hardware_index)37b199fe46SYunfei Dong void vdec_msg_queue_init_ctx(struct vdec_msg_queue_ctx *ctx, int hardware_index)
38b199fe46SYunfei Dong {
39b199fe46SYunfei Dong 	init_waitqueue_head(&ctx->ready_to_use);
40b199fe46SYunfei Dong 	INIT_LIST_HEAD(&ctx->ready_queue);
41b199fe46SYunfei Dong 	spin_lock_init(&ctx->ready_lock);
42b199fe46SYunfei Dong 	ctx->ready_num = 0;
43b199fe46SYunfei Dong 	ctx->hardware_index = hardware_index;
44b199fe46SYunfei Dong }
45b199fe46SYunfei Dong 
vdec_get_buf_list(int hardware_index,struct vdec_lat_buf * buf)46b199fe46SYunfei Dong static struct list_head *vdec_get_buf_list(int hardware_index, struct vdec_lat_buf *buf)
47b199fe46SYunfei Dong {
48b199fe46SYunfei Dong 	switch (hardware_index) {
49b199fe46SYunfei Dong 	case MTK_VDEC_CORE:
50b199fe46SYunfei Dong 		return &buf->core_list;
51b199fe46SYunfei Dong 	case MTK_VDEC_LAT0:
52b199fe46SYunfei Dong 		return &buf->lat_list;
53b199fe46SYunfei Dong 	default:
54b199fe46SYunfei Dong 		return NULL;
55b199fe46SYunfei Dong 	}
56b199fe46SYunfei Dong }
57b199fe46SYunfei Dong 
vdec_msg_queue_inc(struct vdec_msg_queue * msg_queue,int hardware_index)585bbb6e2cSYunfei Dong static void vdec_msg_queue_inc(struct vdec_msg_queue *msg_queue, int hardware_index)
595bbb6e2cSYunfei Dong {
605bbb6e2cSYunfei Dong 	if (hardware_index == MTK_VDEC_CORE)
615bbb6e2cSYunfei Dong 		atomic_inc(&msg_queue->core_list_cnt);
625bbb6e2cSYunfei Dong 	else
635bbb6e2cSYunfei Dong 		atomic_inc(&msg_queue->lat_list_cnt);
645bbb6e2cSYunfei Dong }
655bbb6e2cSYunfei Dong 
vdec_msg_queue_dec(struct vdec_msg_queue * msg_queue,int hardware_index)665bbb6e2cSYunfei Dong static void vdec_msg_queue_dec(struct vdec_msg_queue *msg_queue, int hardware_index)
675bbb6e2cSYunfei Dong {
685bbb6e2cSYunfei Dong 	if (hardware_index == MTK_VDEC_CORE)
695bbb6e2cSYunfei Dong 		atomic_dec(&msg_queue->core_list_cnt);
705bbb6e2cSYunfei Dong 	else
715bbb6e2cSYunfei Dong 		atomic_dec(&msg_queue->lat_list_cnt);
725bbb6e2cSYunfei Dong }
735bbb6e2cSYunfei Dong 
vdec_msg_queue_qbuf(struct vdec_msg_queue_ctx * msg_ctx,struct vdec_lat_buf * buf)74b199fe46SYunfei Dong int vdec_msg_queue_qbuf(struct vdec_msg_queue_ctx *msg_ctx, struct vdec_lat_buf *buf)
75b199fe46SYunfei Dong {
76b199fe46SYunfei Dong 	struct list_head *head;
77b199fe46SYunfei Dong 
78b199fe46SYunfei Dong 	head = vdec_get_buf_list(msg_ctx->hardware_index, buf);
79b199fe46SYunfei Dong 	if (!head) {
8041f03c67SYunfei Dong 		mtk_v4l2_vdec_err(buf->ctx, "fail to qbuf: %d", msg_ctx->hardware_index);
81b199fe46SYunfei Dong 		return -EINVAL;
82b199fe46SYunfei Dong 	}
83b199fe46SYunfei Dong 
84b199fe46SYunfei Dong 	spin_lock(&msg_ctx->ready_lock);
85b199fe46SYunfei Dong 	list_add_tail(head, &msg_ctx->ready_queue);
86b199fe46SYunfei Dong 	msg_ctx->ready_num++;
87b199fe46SYunfei Dong 
885bbb6e2cSYunfei Dong 	vdec_msg_queue_inc(&buf->ctx->msg_queue, msg_ctx->hardware_index);
892e0ef56dSYunfei Dong 	if (msg_ctx->hardware_index != MTK_VDEC_CORE) {
90b199fe46SYunfei Dong 		wake_up_all(&msg_ctx->ready_to_use);
912e0ef56dSYunfei Dong 	} else {
922864e304SYunfei Dong 		if (!(buf->ctx->msg_queue.status & CONTEXT_LIST_QUEUED)) {
932864e304SYunfei Dong 			queue_work(buf->ctx->dev->core_workqueue, &buf->ctx->msg_queue.core_work);
942864e304SYunfei Dong 			buf->ctx->msg_queue.status |= CONTEXT_LIST_QUEUED;
952e0ef56dSYunfei Dong 		}
962e0ef56dSYunfei Dong 	}
97b199fe46SYunfei Dong 
9841f03c67SYunfei Dong 	mtk_v4l2_vdec_dbg(3, buf->ctx, "enqueue buf type: %d addr: 0x%p num: %d",
99b199fe46SYunfei Dong 			  msg_ctx->hardware_index, buf, msg_ctx->ready_num);
100b199fe46SYunfei Dong 	spin_unlock(&msg_ctx->ready_lock);
101b199fe46SYunfei Dong 
102b199fe46SYunfei Dong 	return 0;
103b199fe46SYunfei Dong }
104b199fe46SYunfei Dong 
vdec_msg_queue_wait_event(struct vdec_msg_queue_ctx * msg_ctx)105b199fe46SYunfei Dong static bool vdec_msg_queue_wait_event(struct vdec_msg_queue_ctx *msg_ctx)
106b199fe46SYunfei Dong {
107b199fe46SYunfei Dong 	int ret;
108b199fe46SYunfei Dong 
109b199fe46SYunfei Dong 	ret = wait_event_timeout(msg_ctx->ready_to_use,
110b199fe46SYunfei Dong 				 !list_empty(&msg_ctx->ready_queue),
111b199fe46SYunfei Dong 				 msecs_to_jiffies(VDEC_MSG_QUEUE_TIMEOUT_MS));
112b199fe46SYunfei Dong 	if (!ret)
113b199fe46SYunfei Dong 		return false;
114b199fe46SYunfei Dong 
115b199fe46SYunfei Dong 	return true;
116b199fe46SYunfei Dong }
117b199fe46SYunfei Dong 
vdec_msg_queue_dqbuf(struct vdec_msg_queue_ctx * msg_ctx)118b199fe46SYunfei Dong struct vdec_lat_buf *vdec_msg_queue_dqbuf(struct vdec_msg_queue_ctx *msg_ctx)
119b199fe46SYunfei Dong {
120b199fe46SYunfei Dong 	struct vdec_lat_buf *buf;
121b199fe46SYunfei Dong 	struct list_head *head;
122b199fe46SYunfei Dong 	int ret;
123b199fe46SYunfei Dong 
124b199fe46SYunfei Dong 	spin_lock(&msg_ctx->ready_lock);
125b199fe46SYunfei Dong 	if (list_empty(&msg_ctx->ready_queue)) {
126b199fe46SYunfei Dong 		spin_unlock(&msg_ctx->ready_lock);
127b199fe46SYunfei Dong 
128b199fe46SYunfei Dong 		if (msg_ctx->hardware_index == MTK_VDEC_CORE)
129b199fe46SYunfei Dong 			return NULL;
130b199fe46SYunfei Dong 
131b199fe46SYunfei Dong 		ret = vdec_msg_queue_wait_event(msg_ctx);
132b199fe46SYunfei Dong 		if (!ret)
133b199fe46SYunfei Dong 			return NULL;
134b199fe46SYunfei Dong 		spin_lock(&msg_ctx->ready_lock);
135b199fe46SYunfei Dong 	}
136b199fe46SYunfei Dong 
137b199fe46SYunfei Dong 	if (msg_ctx->hardware_index == MTK_VDEC_CORE)
138b199fe46SYunfei Dong 		buf = list_first_entry(&msg_ctx->ready_queue,
139b199fe46SYunfei Dong 				       struct vdec_lat_buf, core_list);
140b199fe46SYunfei Dong 	else
141b199fe46SYunfei Dong 		buf = list_first_entry(&msg_ctx->ready_queue,
142b199fe46SYunfei Dong 				       struct vdec_lat_buf, lat_list);
143b199fe46SYunfei Dong 
144b199fe46SYunfei Dong 	head = vdec_get_buf_list(msg_ctx->hardware_index, buf);
145b199fe46SYunfei Dong 	if (!head) {
146b199fe46SYunfei Dong 		spin_unlock(&msg_ctx->ready_lock);
14741f03c67SYunfei Dong 		mtk_v4l2_vdec_err(buf->ctx, "fail to dqbuf: %d", msg_ctx->hardware_index);
148b199fe46SYunfei Dong 		return NULL;
149b199fe46SYunfei Dong 	}
150b199fe46SYunfei Dong 	list_del(head);
1515bbb6e2cSYunfei Dong 	vdec_msg_queue_dec(&buf->ctx->msg_queue, msg_ctx->hardware_index);
152b199fe46SYunfei Dong 
153b199fe46SYunfei Dong 	msg_ctx->ready_num--;
15441f03c67SYunfei Dong 	mtk_v4l2_vdec_dbg(3, buf->ctx, "dqueue buf type:%d addr: 0x%p num: %d",
155b199fe46SYunfei Dong 			  msg_ctx->hardware_index, buf, msg_ctx->ready_num);
156b199fe46SYunfei Dong 	spin_unlock(&msg_ctx->ready_lock);
157b199fe46SYunfei Dong 
158b199fe46SYunfei Dong 	return buf;
159b199fe46SYunfei Dong }
160b199fe46SYunfei Dong 
vdec_msg_queue_update_ube_rptr(struct vdec_msg_queue * msg_queue,uint64_t ube_rptr)161b199fe46SYunfei Dong void vdec_msg_queue_update_ube_rptr(struct vdec_msg_queue *msg_queue, uint64_t ube_rptr)
162b199fe46SYunfei Dong {
163b199fe46SYunfei Dong 	spin_lock(&msg_queue->lat_ctx.ready_lock);
164b199fe46SYunfei Dong 	msg_queue->wdma_rptr_addr = ube_rptr;
16541f03c67SYunfei Dong 	mtk_v4l2_vdec_dbg(3, msg_queue->ctx, "update ube rprt (0x%llx)", ube_rptr);
166b199fe46SYunfei Dong 	spin_unlock(&msg_queue->lat_ctx.ready_lock);
167b199fe46SYunfei Dong }
168b199fe46SYunfei Dong 
vdec_msg_queue_update_ube_wptr(struct vdec_msg_queue * msg_queue,uint64_t ube_wptr)169b199fe46SYunfei Dong void vdec_msg_queue_update_ube_wptr(struct vdec_msg_queue *msg_queue, uint64_t ube_wptr)
170b199fe46SYunfei Dong {
171b199fe46SYunfei Dong 	spin_lock(&msg_queue->lat_ctx.ready_lock);
172b199fe46SYunfei Dong 	msg_queue->wdma_wptr_addr = ube_wptr;
17341f03c67SYunfei Dong 	mtk_v4l2_vdec_dbg(3, msg_queue->ctx, "update ube wprt: (0x%llx 0x%llx) offset: 0x%llx",
174b199fe46SYunfei Dong 			  msg_queue->wdma_rptr_addr, msg_queue->wdma_wptr_addr,
175b199fe46SYunfei Dong 			  ube_wptr);
176b199fe46SYunfei Dong 	spin_unlock(&msg_queue->lat_ctx.ready_lock);
177b199fe46SYunfei Dong }
178b199fe46SYunfei Dong 
vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue * msg_queue)179b199fe46SYunfei Dong bool vdec_msg_queue_wait_lat_buf_full(struct vdec_msg_queue *msg_queue)
180b199fe46SYunfei Dong {
181297160d4SYunfei Dong 	if (atomic_read(&msg_queue->lat_list_cnt) == NUM_BUFFER_COUNT) {
18241f03c67SYunfei Dong 		mtk_v4l2_vdec_dbg(3, msg_queue->ctx, "wait buf full: (%d %d) ready:%d status:%d",
183297160d4SYunfei Dong 				  atomic_read(&msg_queue->lat_list_cnt),
184297160d4SYunfei Dong 				  atomic_read(&msg_queue->core_list_cnt),
18541f03c67SYunfei Dong 				  msg_queue->lat_ctx.ready_num, msg_queue->status);
186297160d4SYunfei Dong 		return true;
1872cfca6c1SYunfei Dong 	}
188b199fe46SYunfei Dong 
189962508e3SYunfei Dong 	msg_queue->flush_done = false;
190962508e3SYunfei Dong 	vdec_msg_queue_qbuf(&msg_queue->core_ctx, &msg_queue->empty_lat_buf);
191962508e3SYunfei Dong 	wait_event(msg_queue->core_dec_done, msg_queue->flush_done);
192af50b13dSYunfei Dong 
19341f03c67SYunfei Dong 	mtk_v4l2_vdec_dbg(3, msg_queue->ctx, "flush done => ready_num:%d status:%d list(%d %d)",
194962508e3SYunfei Dong 			  msg_queue->lat_ctx.ready_num, msg_queue->status,
195af50b13dSYunfei Dong 			  atomic_read(&msg_queue->lat_list_cnt),
196297160d4SYunfei Dong 			  atomic_read(&msg_queue->core_list_cnt));
197af50b13dSYunfei Dong 
198b199fe46SYunfei Dong 	return false;
199b199fe46SYunfei Dong }
200b199fe46SYunfei Dong 
vdec_msg_queue_deinit(struct vdec_msg_queue * msg_queue,struct mtk_vcodec_dec_ctx * ctx)201b199fe46SYunfei Dong void vdec_msg_queue_deinit(struct vdec_msg_queue *msg_queue,
20201abf5fbSYunfei Dong 			   struct mtk_vcodec_dec_ctx *ctx)
203b199fe46SYunfei Dong {
204b199fe46SYunfei Dong 	struct vdec_lat_buf *lat_buf;
205b199fe46SYunfei Dong 	struct mtk_vcodec_mem *mem;
206b199fe46SYunfei Dong 	int i;
207b199fe46SYunfei Dong 
208b199fe46SYunfei Dong 	mem = &msg_queue->wdma_addr;
209b199fe46SYunfei Dong 	if (mem->va)
210b199fe46SYunfei Dong 		mtk_vcodec_mem_free(ctx, mem);
211b199fe46SYunfei Dong 	for (i = 0; i < NUM_BUFFER_COUNT; i++) {
212b199fe46SYunfei Dong 		lat_buf = &msg_queue->lat_buf[i];
213b199fe46SYunfei Dong 
214b199fe46SYunfei Dong 		mem = &lat_buf->wdma_err_addr;
215b199fe46SYunfei Dong 		if (mem->va)
216b199fe46SYunfei Dong 			mtk_vcodec_mem_free(ctx, mem);
217b199fe46SYunfei Dong 
218b199fe46SYunfei Dong 		mem = &lat_buf->slice_bc_addr;
219b199fe46SYunfei Dong 		if (mem->va)
220b199fe46SYunfei Dong 			mtk_vcodec_mem_free(ctx, mem);
221b199fe46SYunfei Dong 
2222f5d0aefSXiaoyong Lu 		mem = &lat_buf->rd_mv_addr;
2232f5d0aefSXiaoyong Lu 		if (mem->va)
2242f5d0aefSXiaoyong Lu 			mtk_vcodec_mem_free(ctx, mem);
2252f5d0aefSXiaoyong Lu 
2262f5d0aefSXiaoyong Lu 		mem = &lat_buf->tile_addr;
2272f5d0aefSXiaoyong Lu 		if (mem->va)
2282f5d0aefSXiaoyong Lu 			mtk_vcodec_mem_free(ctx, mem);
2292f5d0aefSXiaoyong Lu 
230b199fe46SYunfei Dong 		kfree(lat_buf->private_data);
231be40f524SDan Carpenter 		lat_buf->private_data = NULL;
232b199fe46SYunfei Dong 	}
233297160d4SYunfei Dong 
234d05dea76SYunfei Dong 	if (msg_queue->wdma_addr.size)
235297160d4SYunfei Dong 		cancel_work_sync(&msg_queue->core_work);
236b199fe46SYunfei Dong }
237b199fe46SYunfei Dong 
vdec_msg_queue_core_work(struct work_struct * work)238365e4ba0SYunfei Dong static void vdec_msg_queue_core_work(struct work_struct *work)
239365e4ba0SYunfei Dong {
240365e4ba0SYunfei Dong 	struct vdec_msg_queue *msg_queue =
241365e4ba0SYunfei Dong 		container_of(work, struct vdec_msg_queue, core_work);
24201abf5fbSYunfei Dong 	struct mtk_vcodec_dec_ctx *ctx =
24301abf5fbSYunfei Dong 		container_of(msg_queue, struct mtk_vcodec_dec_ctx, msg_queue);
244*31272a39SYunfei Dong 	struct mtk_vcodec_dec_dev *dev = ctx->dev;
245365e4ba0SYunfei Dong 	struct vdec_lat_buf *lat_buf;
2462864e304SYunfei Dong 
247297160d4SYunfei Dong 	spin_lock(&msg_queue->core_ctx.ready_lock);
2482864e304SYunfei Dong 	ctx->msg_queue.status &= ~CONTEXT_LIST_QUEUED;
249297160d4SYunfei Dong 	spin_unlock(&msg_queue->core_ctx.ready_lock);
250365e4ba0SYunfei Dong 
251297160d4SYunfei Dong 	lat_buf = vdec_msg_queue_dqbuf(&msg_queue->core_ctx);
252365e4ba0SYunfei Dong 	if (!lat_buf)
253365e4ba0SYunfei Dong 		return;
254365e4ba0SYunfei Dong 
255962508e3SYunfei Dong 	if (lat_buf->is_last_frame) {
256962508e3SYunfei Dong 		ctx->msg_queue.status = CONTEXT_LIST_DEC_DONE;
257962508e3SYunfei Dong 		msg_queue->flush_done = true;
258962508e3SYunfei Dong 		wake_up(&ctx->msg_queue.core_dec_done);
259962508e3SYunfei Dong 
260962508e3SYunfei Dong 		return;
261962508e3SYunfei Dong 	}
262962508e3SYunfei Dong 
263365e4ba0SYunfei Dong 	ctx = lat_buf->ctx;
2647c6785d2SYunfei Dong 	mtk_vcodec_dec_enable_hardware(ctx, MTK_VDEC_CORE);
265365e4ba0SYunfei Dong 	mtk_vcodec_set_curr_ctx(dev, ctx, MTK_VDEC_CORE);
266365e4ba0SYunfei Dong 
267365e4ba0SYunfei Dong 	lat_buf->core_decode(lat_buf);
268365e4ba0SYunfei Dong 
269365e4ba0SYunfei Dong 	mtk_vcodec_set_curr_ctx(dev, NULL, MTK_VDEC_CORE);
2707c6785d2SYunfei Dong 	mtk_vcodec_dec_disable_hardware(ctx, MTK_VDEC_CORE);
271365e4ba0SYunfei Dong 	vdec_msg_queue_qbuf(&ctx->msg_queue.lat_ctx, lat_buf);
272365e4ba0SYunfei Dong 
2732864e304SYunfei Dong 	if (!(ctx->msg_queue.status & CONTEXT_LIST_QUEUED) &&
2742864e304SYunfei Dong 	    atomic_read(&msg_queue->core_list_cnt)) {
275297160d4SYunfei Dong 		spin_lock(&msg_queue->core_ctx.ready_lock);
2762864e304SYunfei Dong 		ctx->msg_queue.status |= CONTEXT_LIST_QUEUED;
277297160d4SYunfei Dong 		spin_unlock(&msg_queue->core_ctx.ready_lock);
2782864e304SYunfei Dong 		queue_work(ctx->dev->core_workqueue, &msg_queue->core_work);
279365e4ba0SYunfei Dong 	}
280365e4ba0SYunfei Dong }
281365e4ba0SYunfei Dong 
vdec_msg_queue_init(struct vdec_msg_queue * msg_queue,struct mtk_vcodec_dec_ctx * ctx,core_decode_cb_t core_decode,int private_size)282b199fe46SYunfei Dong int vdec_msg_queue_init(struct vdec_msg_queue *msg_queue,
28301abf5fbSYunfei Dong 			struct mtk_vcodec_dec_ctx *ctx, core_decode_cb_t core_decode,
284b199fe46SYunfei Dong 			int private_size)
285b199fe46SYunfei Dong {
286b199fe46SYunfei Dong 	struct vdec_lat_buf *lat_buf;
287b199fe46SYunfei Dong 	int i, err;
288b199fe46SYunfei Dong 
289b199fe46SYunfei Dong 	/* already init msg queue */
290b199fe46SYunfei Dong 	if (msg_queue->wdma_addr.size)
291b199fe46SYunfei Dong 		return 0;
292b199fe46SYunfei Dong 
293b199fe46SYunfei Dong 	vdec_msg_queue_init_ctx(&msg_queue->lat_ctx, MTK_VDEC_LAT0);
294297160d4SYunfei Dong 	vdec_msg_queue_init_ctx(&msg_queue->core_ctx, MTK_VDEC_CORE);
295365e4ba0SYunfei Dong 	INIT_WORK(&msg_queue->core_work, vdec_msg_queue_core_work);
2965bbb6e2cSYunfei Dong 
2975bbb6e2cSYunfei Dong 	atomic_set(&msg_queue->lat_list_cnt, 0);
2985bbb6e2cSYunfei Dong 	atomic_set(&msg_queue->core_list_cnt, 0);
299d227af84SYunfei Dong 	init_waitqueue_head(&msg_queue->core_dec_done);
3002864e304SYunfei Dong 	msg_queue->status = CONTEXT_LIST_EMPTY;
3015bbb6e2cSYunfei Dong 
302b199fe46SYunfei Dong 	msg_queue->wdma_addr.size =
303b199fe46SYunfei Dong 		vde_msg_queue_get_trans_size(ctx->picinfo.buf_w,
304b199fe46SYunfei Dong 					     ctx->picinfo.buf_h);
305b199fe46SYunfei Dong 	err = mtk_vcodec_mem_alloc(ctx, &msg_queue->wdma_addr);
306b199fe46SYunfei Dong 	if (err) {
30741f03c67SYunfei Dong 		mtk_v4l2_vdec_err(ctx, "failed to allocate wdma_addr buf");
308cf10b0bbSDan Carpenter 		msg_queue->wdma_addr.size = 0;
309b199fe46SYunfei Dong 		return -ENOMEM;
310b199fe46SYunfei Dong 	}
311b199fe46SYunfei Dong 	msg_queue->wdma_rptr_addr = msg_queue->wdma_addr.dma_addr;
312b199fe46SYunfei Dong 	msg_queue->wdma_wptr_addr = msg_queue->wdma_addr.dma_addr;
313b199fe46SYunfei Dong 
314962508e3SYunfei Dong 	msg_queue->empty_lat_buf.ctx = ctx;
315962508e3SYunfei Dong 	msg_queue->empty_lat_buf.core_decode = NULL;
316962508e3SYunfei Dong 	msg_queue->empty_lat_buf.is_last_frame = true;
317962508e3SYunfei Dong 
31841f03c67SYunfei Dong 	msg_queue->ctx = ctx;
319b199fe46SYunfei Dong 	for (i = 0; i < NUM_BUFFER_COUNT; i++) {
320b199fe46SYunfei Dong 		lat_buf = &msg_queue->lat_buf[i];
321b199fe46SYunfei Dong 
322b199fe46SYunfei Dong 		lat_buf->wdma_err_addr.size = VDEC_ERR_MAP_SZ_AVC;
323b199fe46SYunfei Dong 		err = mtk_vcodec_mem_alloc(ctx, &lat_buf->wdma_err_addr);
324b199fe46SYunfei Dong 		if (err) {
32541f03c67SYunfei Dong 			mtk_v4l2_vdec_err(ctx, "failed to allocate wdma_err_addr buf[%d]", i);
326b199fe46SYunfei Dong 			goto mem_alloc_err;
327b199fe46SYunfei Dong 		}
328b199fe46SYunfei Dong 
329b199fe46SYunfei Dong 		lat_buf->slice_bc_addr.size = VDEC_LAT_SLICE_HEADER_SZ;
330b199fe46SYunfei Dong 		err = mtk_vcodec_mem_alloc(ctx, &lat_buf->slice_bc_addr);
331b199fe46SYunfei Dong 		if (err) {
33241f03c67SYunfei Dong 			mtk_v4l2_vdec_err(ctx, "failed to allocate wdma_addr buf[%d]", i);
333b199fe46SYunfei Dong 			goto mem_alloc_err;
334b199fe46SYunfei Dong 		}
335b199fe46SYunfei Dong 
3362f5d0aefSXiaoyong Lu 		if (ctx->current_codec == V4L2_PIX_FMT_AV1_FRAME) {
3372f5d0aefSXiaoyong Lu 			lat_buf->rd_mv_addr.size = VDEC_RD_MV_BUFFER_SZ;
3382f5d0aefSXiaoyong Lu 			err = mtk_vcodec_mem_alloc(ctx, &lat_buf->rd_mv_addr);
3392f5d0aefSXiaoyong Lu 			if (err) {
34041f03c67SYunfei Dong 				mtk_v4l2_vdec_err(ctx, "failed to allocate rd_mv_addr buf[%d]", i);
341cf10b0bbSDan Carpenter 				goto mem_alloc_err;
3422f5d0aefSXiaoyong Lu 			}
3432f5d0aefSXiaoyong Lu 
3442f5d0aefSXiaoyong Lu 			lat_buf->tile_addr.size = VDEC_LAT_TILE_SZ;
3452f5d0aefSXiaoyong Lu 			err = mtk_vcodec_mem_alloc(ctx, &lat_buf->tile_addr);
3462f5d0aefSXiaoyong Lu 			if (err) {
34741f03c67SYunfei Dong 				mtk_v4l2_vdec_err(ctx, "failed to allocate tile_addr buf[%d]", i);
348cf10b0bbSDan Carpenter 				goto mem_alloc_err;
3492f5d0aefSXiaoyong Lu 			}
3502f5d0aefSXiaoyong Lu 		}
3512f5d0aefSXiaoyong Lu 
352b199fe46SYunfei Dong 		lat_buf->private_data = kzalloc(private_size, GFP_KERNEL);
353b199fe46SYunfei Dong 		if (!lat_buf->private_data) {
354b199fe46SYunfei Dong 			err = -ENOMEM;
355b199fe46SYunfei Dong 			goto mem_alloc_err;
356b199fe46SYunfei Dong 		}
357b199fe46SYunfei Dong 
358b199fe46SYunfei Dong 		lat_buf->ctx = ctx;
359b199fe46SYunfei Dong 		lat_buf->core_decode = core_decode;
360962508e3SYunfei Dong 		lat_buf->is_last_frame = false;
361b199fe46SYunfei Dong 		err = vdec_msg_queue_qbuf(&msg_queue->lat_ctx, lat_buf);
362b199fe46SYunfei Dong 		if (err) {
36341f03c67SYunfei Dong 			mtk_v4l2_vdec_err(ctx, "failed to qbuf buf[%d]", i);
364b199fe46SYunfei Dong 			goto mem_alloc_err;
365b199fe46SYunfei Dong 		}
366b199fe46SYunfei Dong 	}
367b199fe46SYunfei Dong 	return 0;
368b199fe46SYunfei Dong 
369b199fe46SYunfei Dong mem_alloc_err:
370b199fe46SYunfei Dong 	vdec_msg_queue_deinit(msg_queue, ctx);
371b199fe46SYunfei Dong 	return err;
372b199fe46SYunfei Dong }
373