summaryrefslogtreecommitdiff
path: root/drivers/amvdec_ports/decoder/vdec_vp9_if.c (plain)
blob: 7d395ba3b51d8f718f14e1e96d0bbdc928519fd3
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_drv.h"
30#include "../aml_vcodec_adapt.h"
31#include "../vdec_drv_base.h"
32#include "../aml_vcodec_vfm.h"
33#include "aml_vp9_parser.h"
34#include "vdec_vp9_trigger.h"
35
36#define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_V4L2
37#include <trace/events/meson_atrace.h>
38
39#define PREFIX_SIZE (16)
40
41#define NAL_TYPE(value) ((value) & 0x1F)
42#define HEADER_BUFFER_SIZE (32 * 1024)
43#define SYNC_CODE (0x498342)
44
45extern int vp9_need_prefix;
46bool need_trigger;
47int dump_cnt = 0;
48
49/**
50 * struct vp9_fb - vp9 decode frame buffer information
51 * @vdec_fb_va : virtual address of struct vdec_fb
52 * @y_fb_dma : dma address of Y frame buffer (luma)
53 * @c_fb_dma : dma address of C frame buffer (chroma)
54 * @poc : picture order count of frame buffer
55 * @reserved : for 8 bytes alignment
56 */
57struct vp9_fb {
58 uint64_t vdec_fb_va;
59 uint64_t y_fb_dma;
60 uint64_t c_fb_dma;
61 int32_t poc;
62 uint32_t reserved;
63};
64
65/**
66 * struct vdec_vp9_dec_info - decode information
67 * @dpb_sz : decoding picture buffer size
68 * @resolution_changed : resoltion change happen
69 * @reserved : for 8 bytes alignment
70 * @bs_dma : Input bit-stream buffer dma address
71 * @y_fb_dma : Y frame buffer dma address
72 * @c_fb_dma : C frame buffer dma address
73 * @vdec_fb_va : VDEC frame buffer struct virtual address
74 */
75struct vdec_vp9_dec_info {
76 uint32_t dpb_sz;
77 uint32_t resolution_changed;
78 uint32_t reserved;
79 uint64_t bs_dma;
80 uint64_t y_fb_dma;
81 uint64_t c_fb_dma;
82 uint64_t vdec_fb_va;
83};
84
85/**
86 * struct vdec_vp9_vsi - shared memory for decode information exchange
87 * between VPU and Host.
88 * The memory is allocated by VPU then mapping to Host
89 * in vpu_dec_init() and freed in vpu_dec_deinit()
90 * by VPU.
91 * AP-W/R : AP is writer/reader on this item
92 * VPU-W/R: VPU is write/reader on this item
93 * @hdr_buf : Header parsing buffer (AP-W, VPU-R)
94 * @list_free : free frame buffer ring list (AP-W/R, VPU-W)
95 * @list_disp : display frame buffer ring list (AP-R, VPU-W)
96 * @dec : decode information (AP-R, VPU-W)
97 * @pic : picture information (AP-R, VPU-W)
98 * @crop : crop information (AP-R, VPU-W)
99 */
100struct vdec_vp9_vsi {
101 char *header_buf;
102 int sps_size;
103 int pps_size;
104 int sei_size;
105 int head_offset;
106 struct vdec_vp9_dec_info dec;
107 struct vdec_pic_info pic;
108 struct vdec_pic_info cur_pic;
109 struct v4l2_rect crop;
110 bool is_combine;
111 int nalu_pos;
112 struct vp9_param_sets ps;
113};
114
115/**
116 * struct vdec_vp9_inst - vp9 decoder instance
117 * @num_nalu : how many nalus be decoded
118 * @ctx : point to aml_vcodec_ctx
119 * @vsi : VPU shared information
120 */
121struct vdec_vp9_inst {
122 unsigned int num_nalu;
123 struct aml_vcodec_ctx *ctx;
124 struct aml_vdec_adapt vdec;
125 struct vdec_vp9_vsi *vsi;
126 struct vcodec_vfm_s vfm;
127 struct aml_dec_params parms;
128 struct completion comp;
129};
130
131static int vdec_write_nalu(struct vdec_vp9_inst *inst,
132 u8 *buf, u32 size, u64 ts);
133
134static void get_pic_info(struct vdec_vp9_inst *inst,
135 struct vdec_pic_info *pic)
136{
137 *pic = inst->vsi->pic;
138
139 aml_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
140 pic->visible_width, pic->visible_height,
141 pic->coded_width, pic->coded_height);
142 aml_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
143 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
144}
145
146static void get_crop_info(struct vdec_vp9_inst *inst, struct v4l2_rect *cr)
147{
148 cr->left = inst->vsi->crop.left;
149 cr->top = inst->vsi->crop.top;
150 cr->width = inst->vsi->crop.width;
151 cr->height = inst->vsi->crop.height;
152
153 aml_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d",
154 cr->left, cr->top, cr->width, cr->height);
155}
156
157static void get_dpb_size(struct vdec_vp9_inst *inst, unsigned int *dpb_sz)
158{
159 *dpb_sz = inst->vsi->dec.dpb_sz;
160 aml_vcodec_debug(inst, "sz=%d", *dpb_sz);
161}
162
163static u32 vdec_config_default_parms(u8 *parm)
164{
165 u8 *pbuf = parm;
166
167 pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
168 pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:7;");
169 pbuf += sprintf(pbuf, "vp9_double_write_mode:16;");
170 pbuf += sprintf(pbuf, "vp9_buf_width:1920;");
171 pbuf += sprintf(pbuf, "vp9_buf_height:1088;");
172 pbuf += sprintf(pbuf, "vp9_max_pic_w:4096;");
173 pbuf += sprintf(pbuf, "vp9_max_pic_h:2304;");
174 pbuf += sprintf(pbuf, "save_buffer_mode:0;");
175 pbuf += sprintf(pbuf, "no_head:0;");
176 pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;");
177 pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:0;");
178
179 return parm - pbuf;
180}
181
182static void vdec_parser_parms(struct vdec_vp9_inst *inst)
183{
184 struct aml_vcodec_ctx *ctx = inst->ctx;
185
186 if (ctx->config.parm.dec.parms_status &
187 V4L2_CONFIG_PARM_DECODE_CFGINFO) {
188 u8 *pbuf = ctx->config.buf;
189
190 pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
191 pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;",
192 ctx->config.parm.dec.cfg.ref_buf_margin);
193 pbuf += sprintf(pbuf, "vp9_double_write_mode:%d;",
194 ctx->config.parm.dec.cfg.double_write_mode);
195 pbuf += sprintf(pbuf, "vp9_buf_width:%d;",
196 ctx->config.parm.dec.cfg.init_width);
197 pbuf += sprintf(pbuf, "vp9_buf_height:%d;",
198 ctx->config.parm.dec.cfg.init_height);
199 pbuf += sprintf(pbuf, "save_buffer_mode:0;");
200 pbuf += sprintf(pbuf, "no_head:0;");
201 pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;",
202 ctx->config.parm.dec.cfg.canvas_mem_mode);
203 pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:%d;",
204 ctx->config.parm.dec.cfg.canvas_mem_endian);
205 ctx->config.length = pbuf - ctx->config.buf;
206 } else {
207 ctx->config.parm.dec.cfg.double_write_mode = 16;
208 ctx->config.parm.dec.cfg.ref_buf_margin = 7;
209 ctx->config.length = vdec_config_default_parms(ctx->config.buf);
210 }
211
212 if ((ctx->config.parm.dec.parms_status &
213 V4L2_CONFIG_PARM_DECODE_HDRINFO) &&
214 inst->parms.hdr.color_parms.present_flag) {
215 u8 *pbuf = ctx->config.buf + ctx->config.length;
216
217 pbuf += sprintf(pbuf, "mG.x:%d;",
218 ctx->config.parm.dec.hdr.color_parms.primaries[0][0]);
219 pbuf += sprintf(pbuf, "mG.y:%d;",
220 ctx->config.parm.dec.hdr.color_parms.primaries[0][1]);
221 pbuf += sprintf(pbuf, "mB.x:%d;",
222 ctx->config.parm.dec.hdr.color_parms.primaries[1][0]);
223 pbuf += sprintf(pbuf, "mB.y:%d;",
224 ctx->config.parm.dec.hdr.color_parms.primaries[1][1]);
225 pbuf += sprintf(pbuf, "mR.x:%d;",
226 ctx->config.parm.dec.hdr.color_parms.primaries[2][0]);
227 pbuf += sprintf(pbuf, "mR.y:%d;",
228 ctx->config.parm.dec.hdr.color_parms.primaries[2][1]);
229 pbuf += sprintf(pbuf, "mW.x:%d;",
230 ctx->config.parm.dec.hdr.color_parms.white_point[0]);
231 pbuf += sprintf(pbuf, "mW.y:%d;",
232 ctx->config.parm.dec.hdr.color_parms.white_point[1]);
233 pbuf += sprintf(pbuf, "mMaxDL:%d;",
234 ctx->config.parm.dec.hdr.color_parms.luminance[0] / 1000);
235 pbuf += sprintf(pbuf, "mMinDL:%d;",
236 ctx->config.parm.dec.hdr.color_parms.luminance[1]);
237 pbuf += sprintf(pbuf, "mMaxCLL:%d;",
238 ctx->config.parm.dec.hdr.color_parms.content_light_level.max_content);
239 pbuf += sprintf(pbuf, "mMaxFALL:%d;",
240 ctx->config.parm.dec.hdr.color_parms.content_light_level.max_pic_average);
241 ctx->config.length = pbuf - ctx->config.buf;
242 inst->parms.hdr = ctx->config.parm.dec.hdr;
243 inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_HDRINFO;
244 }
245
246 inst->vdec.config = ctx->config;
247 inst->parms.cfg = ctx->config.parm.dec.cfg;
248 inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO;
249}
250
251static int vdec_vp9_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
252{
253 struct vdec_vp9_inst *inst = NULL;
254 int ret = -1;
255
256 inst = kzalloc(sizeof(*inst), GFP_KERNEL);
257 if (!inst)
258 return -ENOMEM;
259
260 inst->vdec.video_type = VFORMAT_VP9;
261 inst->vdec.dev = ctx->dev->vpu_plat_dev;
262 inst->vdec.filp = ctx->dev->filp;
263 inst->vdec.ctx = ctx;
264 inst->ctx = ctx;
265
266 vdec_parser_parms(inst);
267
268 /* set play mode.*/
269 if (ctx->is_drm_mode)
270 inst->vdec.port.flag |= PORT_FLAG_DRM;
271
272 /* to eable vp9 hw.*/
273 inst->vdec.port.type = PORT_TYPE_HEVC;
274
275 /* init vfm */
276 inst->vfm.ctx = ctx;
277 inst->vfm.ada_ctx = &inst->vdec;
278 ret = vcodec_vfm_init(&inst->vfm);
279 if (ret) {
280 pr_err("%s, init vfm failed.\n", __func__);
281 goto err;
282 }
283
284 /* probe info from the stream */
285 inst->vsi = kzalloc(sizeof(struct vdec_vp9_vsi), GFP_KERNEL);
286 if (!inst->vsi) {
287 ret = -ENOMEM;
288 goto err;
289 }
290
291 /* alloc the header buffer to be used cache sps or spp etc.*/
292 inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
293 if (!inst->vsi) {
294 ret = -ENOMEM;
295 goto err;
296 }
297
298 init_completion(&inst->comp);
299
300 aml_vcodec_debug(inst, "vp9 Instance >> %p", inst);
301
302 ctx->ada_ctx = &inst->vdec;
303 *h_vdec = (unsigned long)inst;
304
305 /* init decoder. */
306 ret = video_decoder_init(&inst->vdec);
307 if (ret) {
308 aml_vcodec_err(inst, "vdec_vp9 init err=%d", ret);
309 goto err;
310 }
311
312 //dump_init();
313
314 return 0;
315err:
316 if (inst)
317 vcodec_vfm_release(&inst->vfm);
318 if (inst && inst->vsi && inst->vsi->header_buf)
319 kfree(inst->vsi->header_buf);
320 if (inst && inst->vsi)
321 kfree(inst->vsi);
322 if (inst)
323 kfree(inst);
324 *h_vdec = 0;
325
326 return ret;
327}
328
329#if 0
330static int refer_buffer_num(int level_idc, int poc_cnt,
331 int mb_width, int mb_height)
332{
333 return 20;
334}
335#endif
336
337static int vdec_get_dw_mode(struct vdec_vp9_inst *inst, int dw_mode)
338{
339 u32 valid_dw_mode = inst->parms.cfg.double_write_mode;
340 int w = inst->parms.cfg.init_width;
341 int h = inst->parms.cfg.init_height;
342 u32 dw = 0x1; /*1:1*/
343
344 switch (valid_dw_mode) {
345 case 0x100:
346 if (w > 1920 && h > 1088)
347 dw = 0x4; /*1:2*/
348 break;
349 case 0x200:
350 if (w > 1920 && h > 1088)
351 dw = 0x2; /*1:4*/
352 break;
353 case 0x300:
354 if (w > 1280 && h > 720)
355 dw = 0x4; /*1:2*/
356 break;
357 default:
358 dw = valid_dw_mode;
359 break;
360 }
361
362 return dw;
363}
364
365static int vdec_pic_scale(struct vdec_vp9_inst *inst, int length, int dw_mode)
366{
367 int ret = 64;
368
369 switch (vdec_get_dw_mode(inst, dw_mode)) {
370 case 0x0: /* only afbc, output afbc */
371 ret = 64;
372 break;
373 case 0x1: /* afbc and (w x h), output YUV420 */
374 ret = length;
375 break;
376 case 0x2: /* afbc and (w/4 x h/4), output YUV420 */
377 case 0x3: /* afbc and (w/4 x h/4), output afbc and YUV420 */
378 ret = length >> 2;
379 break;
380 case 0x4: /* afbc and (w/2 x h/2), output YUV420 */
381 ret = length >> 1;
382 break;
383 case 0x10: /* (w x h), output YUV420-8bit) */
384 default:
385 ret = length;
386 break;
387 }
388
389 return ret;
390}
391
392static void fill_vdec_params(struct vdec_vp9_inst *inst,
393 struct VP9Context *vp9_ctx)
394{
395 struct vdec_pic_info *pic = &inst->vsi->pic;
396 struct vdec_vp9_dec_info *dec = &inst->vsi->dec;
397 struct v4l2_rect *rect = &inst->vsi->crop;
398 int dw = inst->parms.cfg.double_write_mode;
399 int margin = inst->parms.cfg.ref_buf_margin;
400
401 /* fill visible area size that be used for EGL. */
402 pic->visible_width = vdec_pic_scale(inst, vp9_ctx->render_width, dw);
403 pic->visible_height = vdec_pic_scale(inst, vp9_ctx->render_height, dw);
404
405 /* calc visible ares. */
406 rect->left = 0;
407 rect->top = 0;
408 rect->width = pic->visible_width;
409 rect->height = pic->visible_height;
410
411 /* config canvas size that be used for decoder. */
412 pic->coded_width = vdec_pic_scale(inst, ALIGN(vp9_ctx->width, 32), dw);
413 pic->coded_height = vdec_pic_scale(inst, ALIGN(vp9_ctx->height, 32), dw);
414
415 pic->y_len_sz = pic->coded_width * pic->coded_height;
416 pic->c_len_sz = pic->y_len_sz >> 1;
417
418 /* calc DPB size */
419 dec->dpb_sz = 5 + margin;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h);
420
421 inst->parms.ps.visible_width = pic->visible_width;
422 inst->parms.ps.visible_height = pic->visible_height;
423 inst->parms.ps.coded_width = pic->coded_width;
424 inst->parms.ps.coded_height = pic->coded_height;
425 inst->parms.ps.dpb_size = dec->dpb_sz;
426 inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_PSINFO;
427
428 aml_vcodec_debug(inst, "[%d] The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n",
429 inst->ctx->id, dw, pic->coded_width, pic->coded_height,
430 pic->visible_width, pic->visible_height,
431 dec->dpb_sz - margin, margin);
432}
433
434static int stream_parse_by_ucode(struct vdec_vp9_inst *inst, u8 *buf, u32 size)
435{
436 int ret = 0;
437
438 ret = vdec_write_nalu(inst, buf, size, 0);
439 if (ret < 0) {
440 pr_err("write frame data failed. err: %d\n", ret);
441 return ret;
442 }
443
444 /* wait ucode parse ending. */
445 wait_for_completion_timeout(&inst->comp,
446 msecs_to_jiffies(1000));
447
448 return inst->vsi->dec.dpb_sz ? 0 : -1;
449}
450
451static int stream_parse(struct vdec_vp9_inst *inst, u8 *buf, u32 size)
452{
453 int ret = 0;
454 struct vp9_param_sets *ps = NULL;
455
456 ps = vzalloc(sizeof(struct vp9_param_sets));
457 if (ps == NULL)
458 return -ENOMEM;
459
460 ret = vp9_decode_extradata_ps(buf, size, ps);
461 if (ret) {
462 pr_err("parse extra data failed. err: %d\n", ret);
463 goto out;
464 }
465
466 if (ps->head_parsed)
467 fill_vdec_params(inst, &ps->ctx);
468
469 ret = ps->head_parsed ? 0 : -1;
470out:
471 vfree(ps);
472
473 return ret;
474}
475
476static int vdec_vp9_probe(unsigned long h_vdec,
477 struct aml_vcodec_mem *bs, void *out)
478{
479 struct vdec_vp9_inst *inst =
480 (struct vdec_vp9_inst *)h_vdec;
481 struct stream_info *st;
482 u8 *buf = (u8 *)bs->vaddr;
483 u32 size = bs->size;
484 int ret = 0;
485
486 st = (struct stream_info *)buf;
487 if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
488 return 0;
489
490 if (st->magic == NORe || st->magic == NORn)
491 ret = stream_parse(inst, st->data, st->length);
492 else {
493 if (inst->ctx->param_sets_from_ucode)
494 ret = stream_parse_by_ucode(inst, buf, size);
495 else
496 ret = stream_parse(inst, buf, size);
497 }
498
499 inst->vsi->cur_pic = inst->vsi->pic;
500
501 return ret;
502}
503
504static void vdec_vp9_deinit(unsigned long h_vdec)
505{
506 ulong flags;
507 struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
508 struct aml_vcodec_ctx *ctx = inst->ctx;
509
510 aml_vcodec_debug_enter(inst);
511
512 video_decoder_release(&inst->vdec);
513
514 vcodec_vfm_release(&inst->vfm);
515
516 //dump_deinit();
517
518 spin_lock_irqsave(&ctx->slock, flags);
519 if (inst->vsi && inst->vsi->header_buf)
520 kfree(inst->vsi->header_buf);
521
522 if (inst->vsi)
523 kfree(inst->vsi);
524
525 kfree(inst);
526
527 ctx->drv_handle = 0;
528 spin_unlock_irqrestore(&ctx->slock, flags);
529
530 need_trigger = false;
531 dump_cnt = 0;
532}
533
534static int vdec_vp9_get_fb(struct vdec_vp9_inst *inst, struct vdec_v4l2_buffer **out)
535{
536 return get_fb_from_queue(inst->ctx, out);
537}
538
539static void vdec_vp9_get_vf(struct vdec_vp9_inst *inst, struct vdec_v4l2_buffer **out)
540{
541 struct vframe_s *vf = NULL;
542 struct vdec_v4l2_buffer *fb = NULL;
543
544 vf = peek_video_frame(&inst->vfm);
545 if (!vf) {
546 aml_vcodec_debug(inst, "there is no vframe.");
547 *out = NULL;
548 return;
549 }
550
551 vf = get_video_frame(&inst->vfm);
552 if (!vf) {
553 aml_vcodec_debug(inst, "the vframe is avalid.");
554 *out = NULL;
555 return;
556 }
557
558 atomic_set(&vf->use_cnt, 1);
559
560 fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
561 fb->vf_handle = (unsigned long)vf;
562 fb->status = FB_ST_DISPLAY;
563
564 *out = fb;
565
566 //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used);
567 //dump_write(fb->base_y.vaddr, fb->base_y.bytes_used);
568 //dump_write(fb->base_c.vaddr, fb->base_c.bytes_used);
569
570 /* convert yuv format. */
571 //swap_uv(fb->base_c.vaddr, fb->base_c.size);
572}
573
574static void add_prefix_data(struct vp9_superframe_split *s,
575 u8 **out, u32 *out_size)
576{
577 int i;
578 u8 *p = NULL;
579 u32 length;
580
581 length = s->size + s->nb_frames * PREFIX_SIZE;
582 p = vzalloc(length);
583 if (!p) {
584 pr_err("alloc size %d failed.\n" ,length);
585 return;
586 }
587
588 memcpy(p, s->data, s->size);
589 p += s->size;
590
591 for (i = s->nb_frames; i > 0; i--) {
592 u32 frame_size = s->sizes[i - 1];
593 u8 *prefix = NULL;
594
595 p -= frame_size;
596 memmove(p + PREFIX_SIZE * i, p, frame_size);
597 prefix = p + PREFIX_SIZE * (i - 1);
598
599 /*add amlogic frame headers.*/
600 frame_size += 16;
601 prefix[0] = (frame_size >> 24) & 0xff;
602 prefix[1] = (frame_size >> 16) & 0xff;
603 prefix[2] = (frame_size >> 8 ) & 0xff;
604 prefix[3] = (frame_size >> 0 ) & 0xff;
605 prefix[4] = ((frame_size >> 24) & 0xff) ^ 0xff;
606 prefix[5] = ((frame_size >> 16) & 0xff) ^ 0xff;
607 prefix[6] = ((frame_size >> 8 ) & 0xff) ^ 0xff;
608 prefix[7] = ((frame_size >> 0 ) & 0xff) ^ 0xff;
609 prefix[8] = 0;
610 prefix[9] = 0;
611 prefix[10] = 0;
612 prefix[11] = 1;
613 prefix[12] = 'A';
614 prefix[13] = 'M';
615 prefix[14] = 'L';
616 prefix[15] = 'V';
617 frame_size -= 16;
618 }
619
620 *out = p;
621 *out_size = length;
622}
623
624static void trigger_decoder(struct aml_vdec_adapt *vdec)
625{
626 int i, ret;
627 u32 frame_size = 0;
628 u8 *p = vp9_trigger_header;
629
630 for (i = 0; i < ARRAY_SIZE(vp9_trigger_framesize); i++) {
631 frame_size = vp9_trigger_framesize[i];
632 ret = vdec_vframe_write(vdec, p,
633 frame_size, 0);
634 pr_err("write trigger frame %d\n", ret);
635 p += frame_size;
636 }
637}
638
639static int vdec_write_nalu(struct vdec_vp9_inst *inst,
640 u8 *buf, u32 size, u64 ts)
641{
642 int ret = 0;
643 struct aml_vdec_adapt *vdec = &inst->vdec;
644 struct vp9_superframe_split s;
645 u8 *data = NULL;
646 u32 length = 0;
647 bool need_prefix = vp9_need_prefix;
648
649 memset(&s, 0, sizeof(s));
650
651 /*trigger.*/
652 if (0 && !need_trigger) {
653 trigger_decoder(vdec);
654 need_trigger = true;
655 }
656
657 if (need_prefix) {
658 /*parse superframe.*/
659 s.data = buf;
660 s.data_size = size;
661 ret = vp9_superframe_split_filter(&s);
662 if (ret) {
663 pr_err("parse frames failed.\n");
664 return ret;
665 }
666
667 /*add headers.*/
668 add_prefix_data(&s, &data, &length);
669 ret = vdec_vframe_write(vdec, data, length, ts);
670 vfree(data);
671 } else {
672 ret = vdec_vframe_write(vdec, buf, size, ts);
673 }
674
675 return ret;
676}
677
678static bool monitor_res_change(struct vdec_vp9_inst *inst, u8 *buf, u32 size)
679{
680 int ret = -1;
681 u8 *p = buf;
682 int len = size;
683 u32 synccode = vp9_need_prefix ?
684 ((p[1] << 16) | (p[2] << 8) | p[3]) :
685 ((p[17] << 16) | (p[18] << 8) | p[19]);
686
687 if (synccode == SYNC_CODE) {
688 ret = stream_parse(inst, p, len);
689 if (!ret && (inst->vsi->cur_pic.coded_width !=
690 inst->vsi->pic.coded_width ||
691 inst->vsi->cur_pic.coded_height !=
692 inst->vsi->pic.coded_height)) {
693 inst->vsi->cur_pic = inst->vsi->pic;
694 return true;
695 }
696 }
697
698 return false;
699}
700
701static int vdec_vp9_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
702 u64 timestamp, bool *res_chg)
703{
704 struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
705 struct aml_vdec_adapt *vdec = &inst->vdec;
706 struct stream_info *st;
707 u8 *buf;
708 u32 size;
709 int ret = -1;
710
711 if (bs == NULL)
712 return -1;
713
714 if (vdec_input_full(vdec)) {
715 ATRACE_COUNTER("vdec_input_full", 0);
716 return -EAGAIN;
717 }
718
719 buf = (u8 *)bs->vaddr;
720 size = bs->size;
721 st = (struct stream_info *)buf;
722
723 if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
724 ret = vdec_vbuf_write(vdec, st->m.buf, sizeof(st->m.drm));
725 else if (st->magic == NORe)
726 ret = vdec_vbuf_write(vdec, st->data, st->length);
727 else if (st->magic == NORn)
728 ret = vdec_write_nalu(inst, st->data, st->length, timestamp);
729 else if (inst->ctx->is_stream_mode)
730 ret = vdec_vbuf_write(vdec, buf, size);
731 else {
732 /*checked whether the resolution changes.*/
733 if ((*res_chg = monitor_res_change(inst, buf, size)))
734 return 0;
735
736 ret = vdec_write_nalu(inst, buf, size, timestamp);
737 }
738 ATRACE_COUNTER("v4l2_decode_write", ret);
739
740 return ret;
741}
742
743 static void get_param_config_info(struct vdec_vp9_inst *inst,
744 struct aml_dec_params *parms)
745 {
746 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO)
747 parms->cfg = inst->parms.cfg;
748 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO)
749 parms->ps = inst->parms.ps;
750 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO)
751 parms->hdr = inst->parms.hdr;
752 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO)
753 parms->cnt = inst->parms.cnt;
754
755 parms->parms_status |= inst->parms.parms_status;
756
757 aml_vcodec_debug(inst, "parms status: %u", parms->parms_status);
758 }
759
760static int vdec_vp9_get_param(unsigned long h_vdec,
761 enum vdec_get_param_type type, void *out)
762{
763 int ret = 0;
764 struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
765
766 if (!inst) {
767 pr_err("the vp9 inst of dec is invalid.\n");
768 return -1;
769 }
770
771 switch (type) {
772 case GET_PARAM_DISP_FRAME_BUFFER:
773 vdec_vp9_get_vf(inst, out);
774 break;
775
776 case GET_PARAM_FREE_FRAME_BUFFER:
777 ret = vdec_vp9_get_fb(inst, out);
778 break;
779
780 case GET_PARAM_PIC_INFO:
781 get_pic_info(inst, out);
782 break;
783
784 case GET_PARAM_DPB_SIZE:
785 get_dpb_size(inst, out);
786 break;
787
788 case GET_PARAM_CROP_INFO:
789 get_crop_info(inst, out);
790 break;
791
792 case GET_PARAM_CONFIG_INFO:
793 get_param_config_info(inst, out);
794 break;
795 default:
796 aml_vcodec_err(inst, "invalid get parameter type=%d", type);
797 ret = -EINVAL;
798 }
799
800 return ret;
801}
802
803static void set_param_write_sync(struct vdec_vp9_inst *inst)
804{
805 complete(&inst->comp);
806}
807
808static void set_param_ps_info(struct vdec_vp9_inst *inst,
809 struct aml_vdec_ps_infos *ps)
810{
811 struct vdec_pic_info *pic = &inst->vsi->pic;
812 struct vdec_vp9_dec_info *dec = &inst->vsi->dec;
813 struct v4l2_rect *rect = &inst->vsi->crop;
814
815 /* fill visible area size that be used for EGL. */
816 pic->visible_width = ps->visible_width;
817 pic->visible_height = ps->visible_height;
818
819 /* calc visible ares. */
820 rect->left = 0;
821 rect->top = 0;
822 rect->width = pic->visible_width;
823 rect->height = pic->visible_height;
824
825 /* config canvas size that be used for decoder. */
826 pic->coded_width = ps->coded_width;
827 pic->coded_height = ps->coded_height;
828
829 pic->y_len_sz = pic->coded_width * pic->coded_height;
830 pic->c_len_sz = pic->y_len_sz >> 1;
831
832 /* calc DPB size */
833 dec->dpb_sz = 5;
834
835 inst->parms.ps = *ps;
836 inst->parms.parms_status |=
837 V4L2_CONFIG_PARM_DECODE_PSINFO;
838
839 /*wake up*/
840 complete(&inst->comp);
841
842 pr_info("Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n",
843 ps->visible_width, ps->visible_height,
844 ps->coded_width, ps->coded_height,
845 ps->dpb_size);
846}
847
848static void set_param_hdr_info(struct vdec_vp9_inst *inst,
849 struct aml_vdec_hdr_infos *hdr)
850{
851 if ((inst->parms.parms_status &
852 V4L2_CONFIG_PARM_DECODE_HDRINFO)) {
853 inst->parms.hdr = *hdr;
854 inst->parms.parms_status |=
855 V4L2_CONFIG_PARM_DECODE_HDRINFO;
856 aml_vdec_dispatch_event(inst->ctx,
857 V4L2_EVENT_SRC_CH_HDRINFO);
858 pr_info("VP9 set HDR infos\n");
859 }
860}
861
862static void set_param_post_event(struct vdec_vp9_inst *inst, u32 *event)
863{
864 aml_vdec_dispatch_event(inst->ctx, *event);
865 pr_info("VP9 post event: %d\n", *event);
866}
867
868static int vdec_vp9_set_param(unsigned long h_vdec,
869 enum vdec_set_param_type type, void *in)
870{
871 int ret = 0;
872 struct vdec_vp9_inst *inst = (struct vdec_vp9_inst *)h_vdec;
873
874 if (!inst) {
875 pr_err("the vp9 inst of dec is invalid.\n");
876 return -1;
877 }
878
879 switch (type) {
880 case SET_PARAM_WRITE_FRAME_SYNC:
881 set_param_write_sync(inst);
882 break;
883
884 case SET_PARAM_PS_INFO:
885 set_param_ps_info(inst, in);
886 break;
887
888 case SET_PARAM_HDR_INFO:
889 set_param_hdr_info(inst, in);
890 break;
891
892 case SET_PARAM_POST_EVENT:
893 set_param_post_event(inst, in);
894 break;
895 default:
896 aml_vcodec_err(inst, "invalid set parameter type=%d", type);
897 ret = -EINVAL;
898 }
899
900 return ret;
901}
902
903static struct vdec_common_if vdec_vp9_if = {
904 .init = vdec_vp9_init,
905 .probe = vdec_vp9_probe,
906 .decode = vdec_vp9_decode,
907 .get_param = vdec_vp9_get_param,
908 .set_param = vdec_vp9_set_param,
909 .deinit = vdec_vp9_deinit,
910};
911
912struct vdec_common_if *get_vp9_dec_comm_if(void);
913
914struct vdec_common_if *get_vp9_dec_comm_if(void)
915{
916 return &vdec_vp9_if;
917}
918
919