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