summaryrefslogtreecommitdiff
path: root/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c (plain)
blob: c9ec20274efa2beca84e6db7c2b81aef53514a07
1/*
2* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; either version 2 of the License, or
7* (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful, but WITHOUT
10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12* more details.
13*
14* You should have received a copy of the GNU General Public License along
15* with this program; if not, write to the Free Software Foundation, Inc.,
16* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17*
18* Description:
19*/
20#include <linux/module.h>
21#include <linux/slab.h>
22#include <linux/timer.h>
23#include <linux/delay.h>
24#include <linux/kernel.h>
25#include <uapi/linux/swab.h>
26#include "../vdec_drv_if.h"
27#include "../aml_vcodec_util.h"
28#include "../aml_vcodec_dec.h"
29#include "../aml_vcodec_adapt.h"
30#include "../vdec_drv_base.h"
31#include "../aml_vcodec_vfm.h"
32#include "aml_mpeg4_parser.h"
33
34#define NAL_TYPE(value) ((value) & 0x1F)
35#define HEADER_BUFFER_SIZE (32 * 1024)
36
37/**
38 * struct mpeg4_fb - mpeg4 decode frame buffer information
39 * @vdec_fb_va : virtual address of struct vdec_fb
40 * @y_fb_dma : dma address of Y frame buffer (luma)
41 * @c_fb_dma : dma address of C frame buffer (chroma)
42 * @poc : picture order count of frame buffer
43 * @reserved : for 8 bytes alignment
44 */
45struct mpeg4_fb {
46 uint64_t vdec_fb_va;
47 uint64_t y_fb_dma;
48 uint64_t c_fb_dma;
49 int32_t poc;
50 uint32_t reserved;
51};
52
53/**
54 * struct vdec_mpeg4_dec_info - decode information
55 * @dpb_sz : decoding picture buffer size
56 * @resolution_changed : resoltion change happen
57 * @reserved : for 8 bytes alignment
58 * @bs_dma : Input bit-stream buffer dma address
59 * @y_fb_dma : Y frame buffer dma address
60 * @c_fb_dma : C frame buffer dma address
61 * @vdec_fb_va : VDEC frame buffer struct virtual address
62 */
63struct vdec_mpeg4_dec_info {
64 uint32_t dpb_sz;
65 uint32_t resolution_changed;
66 uint32_t reserved;
67 uint64_t bs_dma;
68 uint64_t y_fb_dma;
69 uint64_t c_fb_dma;
70 uint64_t vdec_fb_va;
71};
72
73/**
74 * struct vdec_mpeg4_vsi - shared memory for decode information exchange
75 * between VPU and Host.
76 * The memory is allocated by VPU then mapping to Host
77 * in vpu_dec_init() and freed in vpu_dec_deinit()
78 * by VPU.
79 * AP-W/R : AP is writer/reader on this item
80 * VPU-W/R: VPU is write/reader on this item
81 * @hdr_buf : Header parsing buffer (AP-W, VPU-R)
82 * @list_free : free frame buffer ring list (AP-W/R, VPU-W)
83 * @list_disp : display frame buffer ring list (AP-R, VPU-W)
84 * @dec : decode information (AP-R, VPU-W)
85 * @pic : picture information (AP-R, VPU-W)
86 * @crop : crop information (AP-R, VPU-W)
87 */
88struct vdec_mpeg4_vsi {
89 char *header_buf;
90 int sps_size;
91 int pps_size;
92 int sei_size;
93 int head_offset;
94 struct vdec_mpeg4_dec_info dec;
95 struct vdec_pic_info pic;
96 struct vdec_pic_info cur_pic;
97 struct v4l2_rect crop;
98 bool is_combine;
99 int nalu_pos;
100 //struct mpeg4ParamSets ps;
101};
102
103/**
104 * struct vdec_mpeg4_inst - mpeg4 decoder instance
105 * @num_nalu : how many nalus be decoded
106 * @ctx : point to aml_vcodec_ctx
107 * @vsi : VPU shared information
108 */
109struct vdec_mpeg4_inst {
110 unsigned int num_nalu;
111 struct aml_vcodec_ctx *ctx;
112 struct aml_vdec_adapt vdec;
113 struct vdec_mpeg4_vsi *vsi;
114 struct vcodec_vfm_s vfm;
115 struct completion comp;
116};
117
118static void get_pic_info(struct vdec_mpeg4_inst *inst,
119 struct vdec_pic_info *pic)
120{
121 *pic = inst->vsi->pic;
122
123 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
124 "pic(%d, %d), buf(%d, %d)\n",
125 pic->visible_width, pic->visible_height,
126 pic->coded_width, pic->coded_height);
127 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
128 "Y(%d, %d), C(%d, %d)\n",
129 pic->y_bs_sz, pic->y_len_sz,
130 pic->c_bs_sz, pic->c_len_sz);
131}
132
133static void get_crop_info(struct vdec_mpeg4_inst *inst, struct v4l2_rect *cr)
134{
135 cr->left = inst->vsi->crop.left;
136 cr->top = inst->vsi->crop.top;
137 cr->width = inst->vsi->crop.width;
138 cr->height = inst->vsi->crop.height;
139
140 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO,
141 "l=%d, t=%d, w=%d, h=%d\n",
142 cr->left, cr->top, cr->width, cr->height);
143}
144
145static void get_dpb_size(struct vdec_mpeg4_inst *inst, unsigned int *dpb_sz)
146{
147 *dpb_sz = 9;//inst->vsi->dec.dpb_sz;
148 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_EXINFO, "sz=%d\n", *dpb_sz);
149}
150
151static int vdec_mpeg4_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
152{
153 struct vdec_mpeg4_inst *inst = NULL;
154 int ret = -1;
155
156 inst = kzalloc(sizeof(*inst), GFP_KERNEL);
157 if (!inst)
158 return -ENOMEM;
159
160 inst->vdec.video_type = VFORMAT_MPEG4;
161 inst->vdec.format = VIDEO_DEC_FORMAT_MPEG4_5;
162 inst->vdec.dev = ctx->dev->vpu_plat_dev;
163 inst->vdec.filp = ctx->dev->filp;
164 inst->vdec.config = ctx->config;
165 inst->vdec.ctx = ctx;
166 inst->ctx = ctx;
167
168 /* set play mode.*/
169 if (ctx->is_drm_mode)
170 inst->vdec.port.flag |= PORT_FLAG_DRM;
171
172 /* to eable mpeg4 hw.*/
173 inst->vdec.port.type = PORT_TYPE_VIDEO;
174
175 /* init vfm */
176 inst->vfm.ctx = ctx;
177 inst->vfm.ada_ctx = &inst->vdec;
178 ret = vcodec_vfm_init(&inst->vfm);
179 if (ret) {
180 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
181 "init vfm failed.\n");
182 goto err;
183 }
184
185 ret = video_decoder_init(&inst->vdec);
186 if (ret) {
187 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
188 "vdec_mpeg4 init err=%d\n", ret);
189 goto err;
190 }
191
192 /* probe info from the stream */
193 inst->vsi = kzalloc(sizeof(struct vdec_mpeg4_vsi), GFP_KERNEL);
194 if (!inst->vsi) {
195 ret = -ENOMEM;
196 goto err;
197 }
198
199 /* alloc the header buffer to be used cache sps or spp etc.*/
200 inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
201 if (!inst->vsi->header_buf) {
202 ret = -ENOMEM;
203 goto err;
204 }
205
206 inst->vsi->pic.visible_width = 1920;
207 inst->vsi->pic.visible_height = 1080;
208 inst->vsi->pic.coded_width = 1920;
209 inst->vsi->pic.coded_height = 1088;
210 inst->vsi->pic.y_bs_sz = 0;
211 inst->vsi->pic.y_len_sz = (1920 * 1088);
212 inst->vsi->pic.c_bs_sz = 0;
213 inst->vsi->pic.c_len_sz = (1920 * 1088 / 2);
214
215 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
216 "mpeg4 Instance >> %lx\n", (ulong) inst);
217
218 ctx->ada_ctx = &inst->vdec;
219 *h_vdec = (unsigned long)inst;
220
221 //dump_init();
222
223 return 0;
224
225err:
226 if (inst)
227 vcodec_vfm_release(&inst->vfm);
228 if (inst && inst->vsi && inst->vsi->header_buf)
229 kfree(inst->vsi->header_buf);
230 if (inst && inst->vsi)
231 kfree(inst->vsi);
232 if (inst)
233 kfree(inst);
234 *h_vdec = 0;
235
236 return ret;
237}
238
239#if 0
240static int refer_buffer_num(int level_idc, int poc_cnt,
241 int mb_width, int mb_height)
242{
243 return 20;
244}
245#endif
246
247static void fill_vdec_params(struct vdec_mpeg4_inst *inst,
248 struct mpeg4_dec_param *dec_ps)
249{
250 struct vdec_pic_info *pic = &inst->vsi->pic;
251 struct vdec_mpeg4_dec_info *dec = &inst->vsi->dec;
252 struct v4l2_rect *rect = &inst->vsi->crop;
253
254 /* fill visible area size that be used for EGL. */
255 pic->visible_width = dec_ps->m.width;
256 pic->visible_height = dec_ps->m.height;
257
258 /* calc visible ares. */
259 rect->left = 0;
260 rect->top = 0;
261 rect->width = pic->visible_width;
262 rect->height = pic->visible_height;
263
264 /* config canvas size that be used for decoder. */
265 pic->coded_width = ALIGN(dec_ps->m.width, 64);
266 pic->coded_height = ALIGN(dec_ps->m.height, 64);
267
268 pic->y_len_sz = pic->coded_width * pic->coded_height;
269 pic->c_len_sz = pic->y_len_sz >> 1;
270
271 /* calc DPB size */
272 dec->dpb_sz = 9;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h);
273
274 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_BUFMGR,
275 "The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n",
276 pic->coded_width, pic->coded_height,
277 pic->visible_width, pic->visible_height, dec->dpb_sz);
278}
279
280static int parse_stream_ucode(struct vdec_mpeg4_inst *inst, u8 *buf, u32 size)
281{
282 int ret = 0;
283 struct aml_vdec_adapt *vdec = &inst->vdec;
284
285 ret = vdec_vframe_write(vdec, buf, size, 0);
286 if (ret < 0) {
287 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
288 "write frame data failed. err: %d\n", ret);
289 return ret;
290 }
291
292 /* wait ucode parse ending. */
293 wait_for_completion_timeout(&inst->comp,
294 msecs_to_jiffies(1000));
295
296 return inst->vsi->dec.dpb_sz ? 0 : -1;
297}
298
299static int parse_stream_ucode_dma(struct vdec_mpeg4_inst *inst,
300 ulong buf, u32 size, u32 handle)
301{
302 int ret = 0;
303 struct aml_vdec_adapt *vdec = &inst->vdec;
304
305 ret = vdec_vframe_write_with_dma(vdec, buf, size, 0, handle);
306 if (ret < 0) {
307 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
308 "write frame data failed. err: %d\n", ret);
309 return ret;
310 }
311
312 /* wait ucode parse ending. */
313 wait_for_completion_timeout(&inst->comp,
314 msecs_to_jiffies(1000));
315
316 return inst->vsi->dec.dpb_sz ? 0 : -1;
317}
318
319static int parse_stream_cpu(struct vdec_mpeg4_inst *inst, u8 *buf, u32 size)
320{
321 int ret = 0;
322 struct mpeg4_param_sets *ps = NULL;
323
324 ps = kzalloc(sizeof(struct mpeg4_param_sets), GFP_KERNEL);
325 if (ps == NULL)
326 return -ENOMEM;
327
328 ret = mpeg4_decode_extradata_ps(buf, size, ps);
329 if (ret) {
330 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
331 "parse extra data failed. err: %d\n", ret);
332 goto out;
333 }
334
335 if (ps->head_parsed)
336 fill_vdec_params(inst, &ps->dec_ps);
337
338 ret = ps->head_parsed ? 0 : -1;
339out:
340 kfree(ps);
341
342 return ret;
343}
344
345static int vdec_mpeg4_probe(unsigned long h_vdec,
346 struct aml_vcodec_mem *bs, void *out)
347{
348 struct vdec_mpeg4_inst *inst =
349 (struct vdec_mpeg4_inst *)h_vdec;
350 u8 *buf = (u8 *)bs->vaddr;
351 u32 size = bs->size;
352 int ret = 0;
353
354 if (inst->ctx->is_drm_mode) {
355 if (bs->model == VB2_MEMORY_MMAP) {
356 struct aml_video_stream *s =
357 (struct aml_video_stream *) buf;
358
359 if ((s->magic != AML_VIDEO_MAGIC) &&
360 (s->type != V4L_STREAM_TYPE_MATEDATA))
361 return -1;
362
363 if (inst->ctx->param_sets_from_ucode) {
364 ret = parse_stream_ucode(inst, s->data, s->len);
365 } else {
366 ret = parse_stream_cpu(inst, s->data, s->len);
367 }
368 } else if (bs->model == VB2_MEMORY_DMABUF ||
369 bs->model == VB2_MEMORY_USERPTR) {
370 ret = parse_stream_ucode_dma(inst, bs->addr, size,
371 BUFF_IDX(bs, bs->index));
372 }
373 } else {
374 if (inst->ctx->param_sets_from_ucode) {
375 ret = parse_stream_ucode(inst, buf, size);
376 } else {
377 ret = parse_stream_cpu(inst, buf, size);
378 }
379 }
380
381 inst->vsi->cur_pic = inst->vsi->pic;
382
383 return ret;
384}
385
386static void vdec_mpeg4_deinit(unsigned long h_vdec)
387{
388 struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec;
389
390 if (!inst)
391 return;
392
393 video_decoder_release(&inst->vdec);
394
395 vcodec_vfm_release(&inst->vfm);
396
397 //dump_deinit();
398
399 if (inst->vsi && inst->vsi->header_buf)
400 kfree(inst->vsi->header_buf);
401
402 if (inst->vsi)
403 kfree(inst->vsi);
404
405 kfree(inst);
406}
407
408static int vdec_mpeg4_get_fb(struct vdec_mpeg4_inst *inst, struct vdec_v4l2_buffer **out)
409{
410 return get_fb_from_queue(inst->ctx, out);
411}
412
413static void vdec_mpeg4_get_vf(struct vdec_mpeg4_inst *inst, struct vdec_v4l2_buffer **out)
414{
415 struct vframe_s *vf = NULL;
416 struct vdec_v4l2_buffer *fb = NULL;
417
418 vf = peek_video_frame(&inst->vfm);
419 if (!vf) {
420 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
421 "there is no vframe.\n");
422 *out = NULL;
423 return;
424 }
425
426 vf = get_video_frame(&inst->vfm);
427 if (!vf) {
428 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
429 "the vframe is avalid.\n");
430 *out = NULL;
431 return;
432 }
433
434 atomic_set(&vf->use_cnt, 1);
435
436 fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
437 fb->vf_handle = (unsigned long)vf;
438 fb->status = FB_ST_DISPLAY;
439
440 *out = fb;
441
442 //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used);
443 //dump_write(fb->base_y.va, fb->base_y.bytes_used);
444 //dump_write(fb->base_c.va, fb->base_c.bytes_used);
445
446 /* convert yuv format. */
447 //swap_uv(fb->base_c.va, fb->base_c.size);
448}
449
450static int vdec_write_nalu(struct vdec_mpeg4_inst *inst,
451 u8 *buf, u32 size, u64 ts)
452{
453 int ret = 0;
454 struct aml_vdec_adapt *vdec = &inst->vdec;
455
456 ret = vdec_vframe_write(vdec, buf, size, ts);
457
458 return ret;
459}
460
461static int vdec_mpeg4_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
462 u64 timestamp, bool *res_chg)
463{
464 struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec;
465 struct aml_vdec_adapt *vdec = &inst->vdec;
466 u8 *buf = (u8 *) bs->vaddr;
467 u32 size = bs->size;
468 int ret = -1;
469
470 if (vdec_input_full(vdec))
471 return -EAGAIN;
472
473 if (inst->ctx->is_drm_mode) {
474 if (bs->model == VB2_MEMORY_MMAP) {
475 struct aml_video_stream *s =
476 (struct aml_video_stream *) buf;
477
478 if (s->magic != AML_VIDEO_MAGIC)
479 return -1;
480
481 ret = vdec_vframe_write(vdec,
482 s->data,
483 s->len,
484 timestamp);
485 } else if (bs->model == VB2_MEMORY_DMABUF ||
486 bs->model == VB2_MEMORY_USERPTR) {
487 ret = vdec_vframe_write_with_dma(vdec,
488 bs->addr, size, timestamp,
489 BUFF_IDX(bs, bs->index));
490 }
491 } else {
492 ret = vdec_write_nalu(inst, buf, size, timestamp);
493 }
494
495 return ret;
496}
497
498static int vdec_mpeg4_get_param(unsigned long h_vdec,
499 enum vdec_get_param_type type, void *out)
500{
501 int ret = 0;
502 struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec;
503
504 if (!inst) {
505 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
506 "the mpeg4 inst of dec is invalid.\n");
507 return -1;
508 }
509
510 switch (type) {
511 case GET_PARAM_DISP_FRAME_BUFFER:
512 vdec_mpeg4_get_vf(inst, out);
513 break;
514
515 case GET_PARAM_FREE_FRAME_BUFFER:
516 ret = vdec_mpeg4_get_fb(inst, out);
517 break;
518
519 case GET_PARAM_PIC_INFO:
520 get_pic_info(inst, out);
521 break;
522
523 case GET_PARAM_DPB_SIZE:
524 get_dpb_size(inst, out);
525 break;
526
527 case GET_PARAM_CROP_INFO:
528 get_crop_info(inst, out);
529 break;
530
531 default:
532 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO,
533 "invalid get parameter type=%d\n", type);
534 ret = -EINVAL;
535 }
536
537 return ret;
538}
539
540static void set_param_ps_info(struct vdec_mpeg4_inst *inst,
541 struct aml_vdec_ps_infos *ps)
542{
543 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_PRINFO, "\n");
544}
545
546static int vdec_mpeg4_set_param(unsigned long h_vdec,
547 enum vdec_set_param_type type, void *in)
548{
549 int ret = 0;
550 struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec;
551
552 if (!inst) {
553 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
554 "the mpeg4 inst of dec is invalid.\n");
555 return -1;
556 }
557
558 switch (type) {
559 case SET_PARAM_PS_INFO:
560 set_param_ps_info(inst, in);
561 break;
562
563 default:
564 v4l_dbg(inst->ctx, V4L_DEBUG_CODEC_ERROR,
565 "invalid set parameter type=%d\n", type);
566 ret = -EINVAL;
567 }
568
569 return ret;
570}
571
572static struct vdec_common_if vdec_mpeg4_if = {
573 .init = vdec_mpeg4_init,
574 .probe = vdec_mpeg4_probe,
575 .decode = vdec_mpeg4_decode,
576 .get_param = vdec_mpeg4_get_param,
577 .set_param = vdec_mpeg4_set_param,
578 .deinit = vdec_mpeg4_deinit,
579};
580
581struct vdec_common_if *get_mpeg4_dec_comm_if(void);
582
583struct vdec_common_if *get_mpeg4_dec_comm_if(void)
584{
585 return &vdec_mpeg4_if;
586}
587