summaryrefslogtreecommitdiff
path: root/drivers/amvdec_ports/decoder/vdec_h264_if.c (plain)
blob: efa9fc77e3c8f51ca0ea3b284e05c3fd460203cd
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 "../vdec_drv_if.h"
26#include "../aml_vcodec_util.h"
27#include "../aml_vcodec_dec.h"
28//#include "../aml_vcodec_intr.h"
29#include "../aml_vcodec_adapt.h"
30#include "../vdec_drv_base.h"
31#include "../aml_vcodec_vfm.h"
32#include "h264_stream.h"
33#include "h264_parse.h"
34#include <uapi/linux/swab.h>
35
36/* h264 NALU type */
37#define NAL_NON_IDR_SLICE 0x01
38#define NAL_IDR_SLICE 0x05
39#define NAL_H264_SEI 0x06
40#define NAL_H264_SPS 0x07
41#define NAL_H264_PPS 0x08
42
43#define NAL_TYPE(value) ((value) & 0x1F)
44
45#define BUF_PREDICTION_SZ (64 * 1024)//(32 * 1024)
46
47#define MB_UNIT_LEN 16
48
49/* motion vector size (bytes) for every macro block */
50#define HW_MB_STORE_SZ 64
51
52#define H264_MAX_FB_NUM 17
53#define HDR_PARSING_BUF_SZ 1024
54
55#define HEADER_BUFFER_SIZE (32 * 1024)
56
57/**
58 * struct h264_fb - h264 decode frame buffer information
59 * @vdec_fb_va : virtual address of struct vdec_fb
60 * @y_fb_dma : dma address of Y frame buffer (luma)
61 * @c_fb_dma : dma address of C frame buffer (chroma)
62 * @poc : picture order count of frame buffer
63 * @reserved : for 8 bytes alignment
64 */
65struct h264_fb {
66 uint64_t vdec_fb_va;
67 uint64_t y_fb_dma;
68 uint64_t c_fb_dma;
69 int32_t poc;
70 uint32_t reserved;
71};
72
73/**
74 * struct h264_ring_fb_list - ring frame buffer list
75 * @fb_list : frame buffer arrary
76 * @read_idx : read index
77 * @write_idx : write index
78 * @count : buffer count in list
79 */
80struct h264_ring_fb_list {
81 struct h264_fb fb_list[H264_MAX_FB_NUM];
82 unsigned int read_idx;
83 unsigned int write_idx;
84 unsigned int count;
85 unsigned int reserved;
86};
87
88/**
89 * struct vdec_h264_dec_info - decode information
90 * @dpb_sz : decoding picture buffer size
91 * @realloc_mv_buf : flag to notify driver to re-allocate mv buffer
92 * @reserved : for 8 bytes alignment
93 * @bs_dma : Input bit-stream buffer dma address
94 * @y_fb_dma : Y frame buffer dma address
95 * @c_fb_dma : C frame buffer dma address
96 * @vdec_fb_va : VDEC frame buffer struct virtual address
97 */
98struct vdec_h264_dec_info {
99 uint32_t dpb_sz;
100 uint32_t realloc_mv_buf;
101 uint32_t reserved;
102 uint64_t bs_dma;
103 uint64_t y_fb_dma;
104 uint64_t c_fb_dma;
105 uint64_t vdec_fb_va;
106};
107
108/**
109 * struct vdec_h264_vsi - shared memory for decode information exchange
110 * between VPU and Host.
111 * The memory is allocated by VPU then mapping to Host
112 * in vpu_dec_init() and freed in vpu_dec_deinit()
113 * by VPU.
114 * AP-W/R : AP is writer/reader on this item
115 * VPU-W/R: VPU is write/reader on this item
116 * @hdr_buf : Header parsing buffer (AP-W, VPU-R)
117 * @pred_buf_dma : HW working predication buffer dma address (AP-W, VPU-R)
118 * @mv_buf_dma : HW working motion vector buffer dma address (AP-W, VPU-R)
119 * @list_free : free frame buffer ring list (AP-W/R, VPU-W)
120 * @list_disp : display frame buffer ring list (AP-R, VPU-W)
121 * @dec : decode information (AP-R, VPU-W)
122 * @pic : picture information (AP-R, VPU-W)
123 * @crop : crop information (AP-R, VPU-W)
124 */
125struct vdec_h264_vsi {
126 unsigned char hdr_buf[HDR_PARSING_BUF_SZ];
127 char *header_buf;
128 int sps_size;
129 int pps_size;
130 int sei_size;
131 int head_offset;
132 uint64_t pred_buf_dma;
133 uint64_t mv_buf_dma[H264_MAX_FB_NUM];
134 struct h264_ring_fb_list list_free;
135 struct h264_ring_fb_list list_disp;
136 struct vdec_h264_dec_info dec;
137 struct vdec_pic_info pic;
138 struct vdec_pic_info cur_pic;
139 struct v4l2_rect crop;
140 bool is_combine;
141 int nalu_pos;
142};
143
144/**
145 * struct vdec_h264_inst - h264 decoder instance
146 * @num_nalu : how many nalus be decoded
147 * @ctx : point to aml_vcodec_ctx
148 * @pred_buf : HW working predication buffer
149 * @mv_buf : HW working motion vector buffer
150 * @vpu : VPU instance
151 * @vsi : VPU shared information
152 */
153struct vdec_h264_inst {
154 unsigned int num_nalu;
155 struct aml_vcodec_ctx *ctx;
156 struct aml_vcodec_mem pred_buf;
157 struct aml_vcodec_mem mv_buf[H264_MAX_FB_NUM];
158 //struct vdec_vpu_inst vpu;
159 struct aml_vdec_adapt vdec;
160 struct vdec_h264_vsi *vsi;
161 struct vcodec_vfm_s vfm;
162};
163
164#if 0
165#define DUMP_FILE_NAME "/data/dump/dump.tmp"
166static struct file *filp;
167static loff_t file_pos;
168
169void dump_write(const char __user *buf, size_t count)
170{
171 mm_segment_t old_fs;
172
173 if (!filp)
174 return;
175
176 old_fs = get_fs();
177 set_fs(KERNEL_DS);
178
179 if (count != vfs_write(filp, buf, count, &file_pos))
180 pr_err("Failed to write file\n");
181
182 set_fs(old_fs);
183}
184
185void dump_init(void)
186{
187 filp = filp_open(DUMP_FILE_NAME, O_CREAT | O_RDWR, 0644);
188 if (IS_ERR(filp)) {
189 pr_err("open dump file failed\n");
190 filp = NULL;
191 }
192}
193
194void dump_deinit(void)
195{
196 if (filp) {
197 filp_close(filp, current->files);
198 filp = NULL;
199 file_pos = 0;
200 }
201}
202
203void swap_uv(void *uv, int size)
204{
205 int i;
206 __u16 *p = uv;
207
208 size /= 2;
209
210 for (i = 0; i < size; i++, p++)
211 *p = __swab16(*p);
212}
213#endif
214
215static void get_pic_info(struct vdec_h264_inst *inst,
216 struct vdec_pic_info *pic)
217{
218 *pic = inst->vsi->pic;
219
220 aml_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
221 pic->visible_width, pic->visible_height,
222 pic->coded_width, pic->coded_height);
223 aml_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
224 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
225}
226
227static void get_crop_info(struct vdec_h264_inst *inst, struct v4l2_rect *cr)
228{
229 cr->left = inst->vsi->crop.left;
230 cr->top = inst->vsi->crop.top;
231 cr->width = inst->vsi->crop.width;
232 cr->height = inst->vsi->crop.height;
233
234 aml_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d",
235 cr->left, cr->top, cr->width, cr->height);
236}
237
238static void get_dpb_size(struct vdec_h264_inst *inst, unsigned int *dpb_sz)
239{
240 *dpb_sz = inst->vsi->dec.dpb_sz;
241 aml_vcodec_debug(inst, "sz=%d", *dpb_sz);
242}
243
244static int find_start_code(unsigned char *data, unsigned int data_sz)
245{
246 if (data_sz > 3 && data[0] == 0 && data[1] == 0 && data[2] == 1)
247 return 3;
248
249 if (data_sz > 4 && data[0] == 0 && data[1] == 0 && data[2] == 0 &&
250 data[3] == 1)
251 return 4;
252
253 return -1;
254}
255
256static void skip_aud_data(u8 **data, u32 *size)
257{
258 int i;
259
260 i = find_start_code(*data, *size);
261 if (i > 0 && (*data)[i++] == 0x9 && (*data)[i++] == 0xf0) {
262 *size -= i;
263 *data += i;
264 }
265}
266
267static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
268{
269 struct vdec_h264_inst *inst = NULL;
270 int ret = -1;
271
272 inst = kzalloc(sizeof(*inst), GFP_KERNEL);
273 if (!inst)
274 return -ENOMEM;
275
276 inst->ctx = ctx;
277
278 inst->vdec.format = VFORMAT_H264;
279 inst->vdec.dev = ctx->dev->vpu_plat_dev;
280 inst->vdec.filp = ctx->dev->filp;
281 inst->vdec.ctx = ctx;
282
283 /* set play mode.*/
284 if (ctx->is_drm_mode)
285 inst->vdec.port.flag |= PORT_FLAG_DRM;
286
287 /* init vfm */
288 inst->vfm.ctx = ctx;
289 inst->vfm.ada_ctx = &inst->vdec;
290 vcodec_vfm_init(&inst->vfm);
291
292 ret = video_decoder_init(&inst->vdec);
293 if (ret) {
294 aml_vcodec_err(inst, "vdec_h264 init err=%d", ret);
295 goto error_free_inst;
296 }
297
298 /* probe info from the stream */
299 inst->vsi = kzalloc(sizeof(struct vdec_h264_vsi), GFP_KERNEL);
300 if (!inst->vsi) {
301 ret = -ENOMEM;
302 goto error_free_inst;
303 }
304
305 /* alloc the header buffer to be used cache sps or spp etc.*/
306 inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
307 if (!inst->vsi) {
308 ret = -ENOMEM;
309 goto error_free_vsi;
310 }
311
312 inst->vsi->pic.visible_width = 1920;
313 inst->vsi->pic.visible_height = 1080;
314 inst->vsi->pic.coded_width = 1920;
315 inst->vsi->pic.coded_height = 1088;
316 inst->vsi->pic.y_bs_sz = 0;
317 inst->vsi->pic.y_len_sz = (1920 * 1088);
318 inst->vsi->pic.c_bs_sz = 0;
319 inst->vsi->pic.c_len_sz = (1920 * 1088 / 2);
320
321 aml_vcodec_debug(inst, "H264 Instance >> %p", inst);
322
323 ctx->ada_ctx = &inst->vdec;
324 *h_vdec = (unsigned long)inst;
325
326 //dump_init();
327
328 return 0;
329
330error_free_vsi:
331 kfree(inst->vsi);
332error_free_inst:
333 kfree(inst);
334 *h_vdec = 0;
335
336 return ret;
337}
338
339static int refer_buffer_num(int level_idc, int poc_cnt,
340 int mb_width, int mb_height)
341{
342 int max_ref_num = 27;
343 int size, size_margin = 6;
344 int pic_size = mb_width * mb_height * 384;
345
346 switch (level_idc) {
347 case 9:
348 size = 152064;
349 break;
350 case 10:
351 size = 152064;
352 break;
353 case 11:
354 size = 345600;
355 break;
356 case 12:
357 size = 912384;
358 break;
359 case 13:
360 size = 912384;
361 break;
362 case 20:
363 size = 912384;
364 break;
365 case 21:
366 size = 1824768;
367 break;
368 case 22:
369 size = 3110400;
370 break;
371 case 30:
372 size = 3110400;
373 break;
374 case 31:
375 size = 6912000;
376 break;
377 case 32:
378 size = 7864320;
379 break;
380 case 40:
381 size = 12582912;
382 break;
383 case 41:
384 size = 12582912;
385 break;
386 case 42:
387 size = 13369344;
388 break;
389 case 50:
390 size = 42393600;
391 break;
392 case 51:
393 case 52:
394 default:
395 size = 70778880;
396 break;
397 }
398
399 size /= pic_size;
400 size = size + 1; /* need more buffers */
401
402 if (poc_cnt > size)
403 size = poc_cnt;
404
405 size = size + size_margin;
406 if (size > max_ref_num)
407 size = max_ref_num;
408
409 return size;
410}
411
412static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps)
413{
414 struct vdec_pic_info *pic = &inst->vsi->pic;
415 struct vdec_h264_dec_info *dec = &inst->vsi->dec;
416 struct v4l2_rect *rect = &inst->vsi->crop;
417 unsigned int mb_w, mb_h, width, height;
418 unsigned int crop_unit_x = 0, crop_unit_y = 0;
419 unsigned int poc_cnt = 0;
420
421 mb_w = sps->pic_width_in_mbs_minus1 + 1;
422 mb_h = sps->pic_height_in_map_units_minus1 + 1;
423
424 width = mb_w << 4; // 16
425 height = (2 - sps->frame_mbs_only_flag) * (mb_h << 4);
426
427 if (sps->frame_cropping_flag) {
428 if (0 == sps->chroma_format_idc) {// monochrome
429 crop_unit_x = 1;
430 crop_unit_y = 2 - sps->frame_mbs_only_flag;
431 } else if (1 == sps->chroma_format_idc) {// 4:2:0
432 crop_unit_x = 2;
433 crop_unit_y = 2 * (2 - sps->frame_mbs_only_flag);
434 } else if (2 == sps->chroma_format_idc) {// 4:2:2
435 crop_unit_x = 2;
436 crop_unit_y = 2 - sps->frame_mbs_only_flag;
437 } else {// 3 == sps.chroma_format_idc // 4:4:4
438 crop_unit_x = 1;
439 crop_unit_y = 2 - sps->frame_mbs_only_flag;
440 }
441 }
442
443 width -= crop_unit_x * (sps->frame_crop_left_offset +
444 sps->frame_crop_right_offset);
445 height -= crop_unit_y * (sps->frame_crop_top_offset +
446 sps->frame_crop_bottom_offset);
447
448 /* fill visible area size that be used for EGL. */
449 pic->visible_width = width;
450 pic->visible_height = height;
451
452 /* calc visible ares. */
453 rect->left = 0;
454 rect->top = 0;
455 rect->width = pic->visible_width;
456 rect->height = pic->visible_height;
457
458 /* config canvas size that be used for decoder. */
459 pic->coded_width = ALIGN(mb_w, 4) << 4;
460 pic->coded_height = ALIGN(mb_h, 4) << 4;
461 pic->y_len_sz = pic->coded_width * pic->coded_height;
462 pic->c_len_sz = pic->y_len_sz >> 1;
463
464 /* calc DPB size */
465 poc_cnt = sps->pic_order_cnt_type;
466 if (!poc_cnt)
467 poc_cnt = (sps->log2_max_pic_order_cnt_lsb_minus4 + 4) << 1;
468
469 dec->dpb_sz = refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h);
470
471 aml_vcodec_debug(inst, "[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n",
472 inst->ctx->id, pic->coded_width, pic->coded_height,
473 pic->visible_width, pic->visible_height, dec->dpb_sz);
474}
475
476static void search_from_st(u8 *buf, u32 size, int *pos, bool *is_combine)
477{
478 int i = 0, j = 0, cnt = 0;
479 u8 *p = buf;
480
481 for (i = 4; i < size; i++) {
482 j = find_start_code(p, 7);
483 if (j > 0) {
484 if (++cnt > 1) {
485 *is_combine = true;
486 break;
487 }
488
489 *pos = p - buf + j;
490 p += j;
491 i += j;
492 }
493 p++;
494 }
495
496 //pr_info("nal pos: %d, is_combine: %d\n",*pos, *is_combine);
497}
498
499static int stream_parse(struct vdec_h264_inst *inst, u8 *buf, u32 size)
500{
501 struct h264_stream_t s;
502 struct h264_SPS_t *sps;
503 unsigned int nal_type;
504 int nal_idx = 0;
505 int real_data_pos, real_data_size;
506 bool is_combine = false;
507
508 search_from_st(buf, size, &nal_idx, &is_combine);
509 if (nal_idx < 0)
510 return -1;
511
512 nal_type = NAL_TYPE(buf[nal_idx]);
513 if (nal_type != NAL_H264_SPS)
514 return -1;
515
516 /* if the st compose from csd + slice that is the combine data. */
517 inst->vsi->is_combine = is_combine;
518 inst->vsi->nalu_pos = nal_idx;
519
520 /* start code plus nal type. */
521 real_data_pos = nal_idx + 1;
522 real_data_size = size - real_data_pos;
523
524 sps = kzalloc(sizeof(struct h264_SPS_t), GFP_KERNEL);
525 if (sps == NULL)
526 return -ENOMEM;
527
528 h264_stream_set(&s, &buf[real_data_pos], real_data_size);
529 h264_sps_parse(&s, sps);
530 //h264_sps_info(sps);
531
532 fill_vdec_params(inst, sps);
533
534 kfree(sps);
535
536 return 0;
537}
538
539static int vdec_h264_probe(unsigned long h_vdec,
540 struct aml_vcodec_mem *bs, void *out)
541{
542 struct vdec_h264_inst *inst =
543 (struct vdec_h264_inst *)h_vdec;
544 struct stream_info *st;
545 u8 *buf = (u8 *)bs->va;
546 u32 size = bs->size;
547 int ret = 0;
548
549 st = (struct stream_info *)buf;
550 if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
551 return 0;
552
553 if (st->magic == NORe || st->magic == NORn) {
554 buf = st->data;
555 size = st->length;
556 }
557
558 skip_aud_data(&buf, &size);
559 ret = stream_parse(inst, buf, size);
560
561 inst->vsi->cur_pic = inst->vsi->pic;
562
563 return ret;
564}
565
566static void vdec_h264_deinit(unsigned long h_vdec)
567{
568 struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
569
570 if (!inst)
571 return;
572
573 aml_vcodec_debug_enter(inst);
574
575 video_decoder_release(&inst->vdec);
576
577 vcodec_vfm_release(&inst->vfm);
578
579 //dump_deinit();
580
581 if (inst->vsi && inst->vsi->header_buf)
582 kfree(inst->vsi->header_buf);
583
584 if (inst->vsi)
585 kfree(inst->vsi);
586
587 kfree(inst);
588}
589
590static int vdec_h264_get_fb(struct vdec_h264_inst *inst, struct vdec_fb **out)
591{
592 return get_fb_from_queue(inst->ctx, out);
593}
594
595static void vdec_h264_get_vf(struct vdec_h264_inst *inst, struct vdec_fb **out)
596{
597 struct vframe_s *vf = NULL;
598 struct vdec_fb *fb = NULL;
599
600 aml_vcodec_debug(inst, "%s() [%d], vfm: %p",
601 __func__, __LINE__, &inst->vfm);
602
603 vf = peek_video_frame(&inst->vfm);
604 if (!vf) {
605 aml_vcodec_debug(inst, "there is no vframe.");
606 *out = NULL;
607 return;
608 }
609
610 vf = get_video_frame(&inst->vfm);
611 if (!vf) {
612 aml_vcodec_debug(inst, "the vframe is avalid.");
613 *out = NULL;
614 return;
615 }
616
617 atomic_set(&vf->use_cnt, 1);
618
619 aml_vcodec_debug(inst, "%s() [%d], vf: %p, v4l_mem_handle: %lx, idx: %d\n",
620 __func__, __LINE__, vf, vf->v4l_mem_handle, vf->index);
621
622 fb = (struct vdec_fb *)vf->v4l_mem_handle;
623 fb->vf_handle = (unsigned long)vf;
624 fb->status = FB_ST_DISPLAY;
625
626 *out = fb;
627
628 //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used);
629 //dump_write(fb->base_y.va, fb->base_y.bytes_used);
630 //dump_write(fb->base_c.va, fb->base_c.bytes_used);
631
632 /* convert yuv format. */
633 //swap_uv(fb->base_c.va, fb->base_c.size);
634
635 aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu",
636 __func__, __LINE__, fb->base_y.va,
637 (unsigned int)virt_to_phys(fb->base_y.va), fb->base_y.size);
638 aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu",
639 __func__, __LINE__, fb->base_c.va,
640 (unsigned int)virt_to_phys(fb->base_c.va), fb->base_c.size);
641}
642
643static int vdec_write_nalu(struct vdec_h264_inst *inst,
644 u8 *buf, u32 size, u64 ts)
645{
646 int ret = -1;
647 struct aml_vdec_adapt *vdec = &inst->vdec;
648 bool is_combine = inst->vsi->is_combine;
649 int nalu_pos;
650 u32 nal_type;
651
652 nalu_pos = find_start_code(buf, size);
653 if (nalu_pos < 0)
654 goto err;
655
656 nal_type = NAL_TYPE(buf[nalu_pos]);
657 aml_vcodec_debug(inst, "NALU type: %d, size: %u", nal_type, size);
658
659 if (nal_type == NAL_H264_SPS && !is_combine) {
660 if (inst->vsi->head_offset + size > HEADER_BUFFER_SIZE) {
661 ret = -EILSEQ;
662 goto err;
663 }
664 inst->vsi->sps_size = size;
665 memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, size);
666 inst->vsi->head_offset += inst->vsi->sps_size;
667 ret = size;
668 } else if (nal_type == NAL_H264_PPS && !is_combine) {
669 //buf_sz -= nal_start_idx;
670 if (inst->vsi->head_offset + size > HEADER_BUFFER_SIZE) {
671 ret = -EILSEQ;
672 goto err;
673 }
674 inst->vsi->pps_size = size;
675 memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, size);
676 inst->vsi->head_offset += inst->vsi->pps_size;
677 ret = size;
678 } else if (nal_type == NAL_H264_SEI && !is_combine) {
679 if (inst->vsi->head_offset + size > HEADER_BUFFER_SIZE) {
680 ret = -EILSEQ;
681 goto err;
682 }
683 inst->vsi->sei_size = size;
684 memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, size);
685 inst->vsi->head_offset += inst->vsi->sei_size;
686 ret = size;
687 } else if (inst->vsi->head_offset == 0) {
688 ret = vdec_vframe_write(vdec, buf, size, ts);
689
690 aml_vcodec_debug(inst, "buf: %p, buf size: %u, write to: %d",
691 buf, size, ret);
692 } else {
693 char *write_buf = vmalloc(inst->vsi->head_offset + size);
694 if (!write_buf) {
695 ret = -ENOMEM;
696 goto err;
697 }
698
699 memcpy(write_buf, inst->vsi->header_buf, inst->vsi->head_offset);
700 memcpy(write_buf + inst->vsi->head_offset, buf, size);
701
702 ret = vdec_vframe_write(vdec, write_buf,
703 inst->vsi->head_offset + size, ts);
704
705 aml_vcodec_debug(inst, "buf: %p, buf size: %u, write to: %d",
706 write_buf, inst->vsi->head_offset + size, ret);
707
708 memset(inst->vsi->header_buf, 0, HEADER_BUFFER_SIZE);
709 inst->vsi->head_offset = 0;
710 inst->vsi->sps_size = 0;
711 inst->vsi->pps_size = 0;
712 inst->vsi->sei_size = 0;
713
714 vfree(write_buf);
715 }
716
717 return ret;
718err:
719 aml_vcodec_err(inst, "%s err(%d)", __func__, ret);
720 return ret;
721}
722
723static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
724 unsigned long int timestamp, bool *res_chg)
725{
726 struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
727 struct aml_vdec_adapt *vdec = &inst->vdec;
728 struct stream_info *st;
729 int nalu_pos;
730 u32 nal_type;
731 u8 *buf;
732 u32 size;
733 int ret = -1;
734
735 /* bs NULL means flush decoder */
736 if (bs == NULL)
737 return -1;
738
739 buf = (u8 *)bs->va;
740 size = bs->size;
741 st = (struct stream_info *)buf;
742
743 if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
744 ret = vdec_vbuf_write(vdec, st->m.buf, sizeof(st->m.drm));
745 else if (st->magic == NORe)
746 ret = vdec_vbuf_write(vdec, st->data, st->length);
747 else if (st->magic == NORn)
748 ret = vdec_write_nalu(inst, st->data, st->length, timestamp);
749 else if (inst->ctx->is_stream_mode)
750 ret = vdec_vbuf_write(vdec, buf, size);
751 else {
752 /*checked whether the resolution chagnes.*/
753 u8 *p = buf;
754 u32 l = size;
755
756 skip_aud_data(&p, &l);
757
758 nalu_pos = find_start_code(p, l);
759 if (nalu_pos < 0)
760 return -1;
761
762 nal_type = NAL_TYPE(p[nalu_pos]);
763 if (nal_type == NAL_H264_SPS) {
764 stream_parse(inst, p, l);
765 if (inst->vsi->cur_pic.coded_width !=
766 inst->vsi->pic.coded_width ||
767 inst->vsi->cur_pic.coded_height !=
768 inst->vsi->pic.coded_height) {
769 inst->vsi->cur_pic = inst->vsi->pic;
770 *res_chg = true;
771 return 0;
772 }
773 }
774 ret = vdec_write_nalu(inst, buf, size, timestamp);
775 }
776
777 return ret;
778}
779
780static int vdec_h264_get_param(unsigned long h_vdec,
781 enum vdec_get_param_type type, void *out)
782{
783 int ret = 0;
784 struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
785
786 if (!inst) {
787 pr_err("the h264 inst of dec is invalid.\n");
788 return -1;
789 }
790
791 switch (type) {
792 case GET_PARAM_DISP_FRAME_BUFFER:
793 vdec_h264_get_vf(inst, out);
794 break;
795
796 case GET_PARAM_FREE_FRAME_BUFFER:
797 ret = vdec_h264_get_fb(inst, out);
798 break;
799
800 case GET_PARAM_PIC_INFO:
801 get_pic_info(inst, out);
802 break;
803
804 case GET_PARAM_DPB_SIZE:
805 get_dpb_size(inst, out);
806 break;
807
808 case GET_PARAM_CROP_INFO:
809 get_crop_info(inst, out);
810 break;
811
812 default:
813 aml_vcodec_err(inst, "invalid get parameter type=%d", type);
814 ret = -EINVAL;
815 }
816
817 return ret;
818}
819
820static struct vdec_common_if vdec_h264_if = {
821 vdec_h264_init,
822 vdec_h264_probe,
823 vdec_h264_decode,
824 vdec_h264_get_param,
825 vdec_h264_deinit,
826};
827
828struct vdec_common_if *get_h264_dec_comm_if(void);
829
830struct vdec_common_if *get_h264_dec_comm_if(void)
831{
832 return &vdec_h264_if;
833}
834