summaryrefslogtreecommitdiff
path: root/drivers/amvdec_ports/decoder/vdec_hevc_if.c (plain)
blob: 59ce85fe147c54c52cbd6f4faf9b85c8577b6680
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_hevc_parser.h"
33
34#define HEVC_NAL_TYPE(value) ((value >> 1) & 0x3F)
35#define HEADER_BUFFER_SIZE (32 * 1024)
36
37/**
38 * struct hevc_fb - hevc 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 hevc_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_hevc_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_hevc_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_hevc_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_hevc_vsi {
89 char *header_buf;
90 int sps_size;
91 int pps_size;
92 int sei_size;
93 int head_offset;
94 struct vdec_hevc_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 h265_param_sets ps;
101};
102
103/**
104 * struct vdec_hevc_inst - hevc 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_hevc_inst {
110 unsigned int num_nalu;
111 struct aml_vcodec_ctx *ctx;
112 struct aml_vdec_adapt vdec;
113 struct vdec_hevc_vsi *vsi;
114 struct vcodec_vfm_s vfm;
115 struct completion comp;
116};
117
118static void get_pic_info(struct vdec_hevc_inst *inst,
119 struct vdec_pic_info *pic)
120{
121 *pic = inst->vsi->pic;
122
123 aml_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
124 pic->visible_width, pic->visible_height,
125 pic->coded_width, pic->coded_height);
126 aml_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
127 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
128}
129
130static void get_crop_info(struct vdec_hevc_inst *inst, struct v4l2_rect *cr)
131{
132 cr->left = inst->vsi->crop.left;
133 cr->top = inst->vsi->crop.top;
134 cr->width = inst->vsi->crop.width;
135 cr->height = inst->vsi->crop.height;
136
137 aml_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d",
138 cr->left, cr->top, cr->width, cr->height);
139}
140
141static void get_dpb_size(struct vdec_hevc_inst *inst, unsigned int *dpb_sz)
142{
143 *dpb_sz = inst->vsi->dec.dpb_sz;
144 aml_vcodec_debug(inst, "sz=%d", *dpb_sz);
145}
146
147static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
148{
149 struct vdec_hevc_inst *inst = NULL;
150 int ret = -1;
151
152 inst = kzalloc(sizeof(*inst), GFP_KERNEL);
153 if (!inst)
154 return -ENOMEM;
155
156 inst->ctx = ctx;
157
158 inst->vdec.video_type = VFORMAT_HEVC;
159 inst->vdec.dev = ctx->dev->vpu_plat_dev;
160 inst->vdec.filp = ctx->dev->filp;
161 inst->vdec.ctx = ctx;
162
163 /* set play mode.*/
164 if (ctx->is_drm_mode)
165 inst->vdec.port.flag |= PORT_FLAG_DRM;
166
167 /* to eable hevc hw.*/
168 inst->vdec.port.type = PORT_TYPE_HEVC;
169
170 /* init vfm */
171 inst->vfm.ctx = ctx;
172 inst->vfm.ada_ctx = &inst->vdec;
173 vcodec_vfm_init(&inst->vfm);
174
175 ret = video_decoder_init(&inst->vdec);
176 if (ret) {
177 aml_vcodec_err(inst, "vdec_hevc init err=%d", ret);
178 goto error_free_inst;
179 }
180
181 /* probe info from the stream */
182 inst->vsi = kzalloc(sizeof(struct vdec_hevc_vsi), GFP_KERNEL);
183 if (!inst->vsi) {
184 ret = -ENOMEM;
185 goto error_free_inst;
186 }
187
188 /* alloc the header buffer to be used cache sps or spp etc.*/
189 inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
190 if (!inst->vsi) {
191 ret = -ENOMEM;
192 goto error_free_vsi;
193 }
194
195 inst->vsi->pic.visible_width = 1920;
196 inst->vsi->pic.visible_height = 1080;
197 inst->vsi->pic.coded_width = 1920;
198 inst->vsi->pic.coded_height = 1088;
199 inst->vsi->pic.y_bs_sz = 0;
200 inst->vsi->pic.y_len_sz = (1920 * 1088);
201 inst->vsi->pic.c_bs_sz = 0;
202 inst->vsi->pic.c_len_sz = (1920 * 1088 / 2);
203
204 init_completion(&inst->comp);
205
206 aml_vcodec_debug(inst, "hevc Instance >> %p", inst);
207
208 ctx->ada_ctx = &inst->vdec;
209 *h_vdec = (unsigned long)inst;
210
211 //dump_init();
212
213 return 0;
214
215error_free_vsi:
216 kfree(inst->vsi);
217error_free_inst:
218 kfree(inst);
219 *h_vdec = 0;
220
221 return ret;
222}
223
224
225static int refer_buffer_num(struct h265_SPS_t *sps)
226{
227 int used_buf_num = 0;
228 int sps_pic_buf_diff = 0;
229
230 if ((!sps->temporal_layer[0].num_reorder_pics) &&
231 (sps->temporal_layer[0].max_dec_pic_buffering)) {
232 /* the range of sps_num_reorder_pics_0 is in
233 [0, sps_max_dec_pic_buffering_minus1_0] */
234 used_buf_num = sps->temporal_layer[0].max_dec_pic_buffering;
235 } else
236 used_buf_num = sps->temporal_layer[0].num_reorder_pics;
237
238 sps_pic_buf_diff = sps->temporal_layer[0].max_dec_pic_buffering -
239 sps->temporal_layer[0].num_reorder_pics + 1;
240
241 if (sps_pic_buf_diff >= 4)
242 used_buf_num += 1;
243
244 /*need one more for multi instance, as
245 apply_ref_pic_set() has no chanch to run to
246 to clear referenced flag in some case */
247 used_buf_num++;
248
249 /* for eos add more buffer to flush.*/
250 used_buf_num++;
251
252 return used_buf_num;
253}
254
255static void fill_vdec_params(struct vdec_hevc_inst *inst, struct h265_SPS_t *sps)
256{
257 struct vdec_pic_info *pic = &inst->vsi->pic;
258 struct vdec_hevc_dec_info *dec = &inst->vsi->dec;
259 struct v4l2_rect *rect = &inst->vsi->crop;
260
261 /* fill visible area size that be used for EGL. */
262 pic->visible_width = sps->width - (sps->output_window.left_offset +
263 sps->output_window.right_offset);
264 pic->visible_height = sps->height - (sps->output_window.top_offset +
265 sps->output_window.bottom_offset);
266
267 /* calc visible ares. */
268 rect->left = 0;
269 rect->top = 0;
270 rect->width = pic->visible_width;
271 rect->height = pic->visible_height;
272
273 /* config canvas size that be used for decoder. */
274 pic->coded_width = ALIGN(sps->width, 32);
275 pic->coded_height = ALIGN(sps->height, 32);
276
277 pic->y_len_sz = pic->coded_width * pic->coded_height;
278 pic->c_len_sz = pic->y_len_sz >> 1;
279
280 /* calc DPB size */
281 dec->dpb_sz = refer_buffer_num(sps);
282
283 pr_info("[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n",
284 inst->ctx->id, pic->coded_width, pic->coded_height,
285 pic->visible_width, pic->visible_height, dec->dpb_sz);
286}
287
288static int stream_parse_by_ucode(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
289{
290 int ret = 0;
291 struct aml_vdec_adapt *vdec = &inst->vdec;
292
293 ret = vdec_vframe_write(vdec, buf, size, 0);
294 if (ret < 0) {
295 pr_err("write frame data failed. err: %d\n", ret);
296 return ret;
297 }
298
299 /* wait ucode parse ending. */
300 wait_for_completion_timeout(&inst->comp,
301 msecs_to_jiffies(1000));
302
303 return inst->vsi->dec.dpb_sz ? 0 : -1;
304}
305
306static int stream_parse(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
307{
308 int ret = 0;
309 struct h265_param_sets *ps = NULL;
310
311 ps = kzalloc(sizeof(struct h265_param_sets), GFP_KERNEL);
312 if (ps == NULL)
313 return -ENOMEM;
314
315 ret = h265_decode_extradata_ps(buf, size, ps);
316 if (ret) {
317 pr_err("parse extra data failed. err: %d\n", ret);
318 goto out;
319 }
320
321 if (ps->sps_parsed)
322 fill_vdec_params(inst, &ps->sps);
323
324 ret = ps->sps_parsed ? 0 : -1;
325out:
326 kfree(ps);
327
328 return ret;
329}
330
331static int vdec_hevc_probe(unsigned long h_vdec,
332 struct aml_vcodec_mem *bs, void *out)
333{
334 struct vdec_hevc_inst *inst =
335 (struct vdec_hevc_inst *)h_vdec;
336 struct stream_info *st;
337 u8 *buf = (u8 *)bs->vaddr;
338 u32 size = bs->size;
339 int ret = 0;
340
341 st = (struct stream_info *)buf;
342 if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
343 return 0;
344
345 if (st->magic == NORe || st->magic == NORn)
346 ret = stream_parse(inst, st->data, st->length);
347 else {
348 if (inst->ctx->param_sets_from_ucode)
349 ret = stream_parse_by_ucode(inst, buf, size);
350 else
351 ret = stream_parse(inst, buf, size);
352 }
353
354 inst->vsi->cur_pic = inst->vsi->pic;
355
356 return ret;
357}
358
359static void vdec_hevc_deinit(unsigned long h_vdec)
360{
361 ulong flags;
362 struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
363 struct aml_vcodec_ctx *ctx = inst->ctx;
364
365 aml_vcodec_debug_enter(inst);
366
367 video_decoder_release(&inst->vdec);
368
369 vcodec_vfm_release(&inst->vfm);
370
371 //dump_deinit();
372
373 spin_lock_irqsave(&ctx->slock, flags);
374 if (inst->vsi && inst->vsi->header_buf)
375 kfree(inst->vsi->header_buf);
376
377 if (inst->vsi)
378 kfree(inst->vsi);
379
380 kfree(inst);
381
382 ctx->drv_handle = 0;
383 spin_unlock_irqrestore(&ctx->slock, flags);
384}
385
386static int vdec_hevc_get_fb(struct vdec_hevc_inst *inst, struct vdec_v4l2_buffer **out)
387{
388 return get_fb_from_queue(inst->ctx, out);
389}
390
391static void vdec_hevc_get_vf(struct vdec_hevc_inst *inst, struct vdec_v4l2_buffer **out)
392{
393 struct vframe_s *vf = NULL;
394 struct vdec_v4l2_buffer *fb = NULL;
395
396 vf = peek_video_frame(&inst->vfm);
397 if (!vf) {
398 aml_vcodec_debug(inst, "there is no vframe.");
399 *out = NULL;
400 return;
401 }
402
403 vf = get_video_frame(&inst->vfm);
404 if (!vf) {
405 aml_vcodec_debug(inst, "the vframe is avalid.");
406 *out = NULL;
407 return;
408 }
409
410 atomic_set(&vf->use_cnt, 1);
411
412 fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
413 fb->vf_handle = (unsigned long)vf;
414 fb->status = FB_ST_DISPLAY;
415
416 *out = fb;
417
418 //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used);
419 //dump_write(fb->base_y.vaddr, fb->base_y.bytes_used);
420 //dump_write(fb->base_c.vaddr, fb->base_c.bytes_used);
421
422 /* convert yuv format. */
423 //swap_uv(fb->base_c.vaddr, fb->base_c.size);
424}
425
426static int vdec_write_nalu(struct vdec_hevc_inst *inst,
427 u8 *buf, u32 size, u64 ts)
428{
429 int ret = 0;
430 struct aml_vdec_adapt *vdec = &inst->vdec;
431
432 ret = vdec_vframe_write(vdec, buf, size, ts);
433
434 return ret;
435}
436
437static bool monitor_res_change(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
438{
439 int ret = 0, i = 0, j = 0;
440 u8 *p = buf;
441 int len = size;
442 u32 type;
443
444 for (i = 4; i < size; i++) {
445 j = find_start_code(p, len);
446 if (j > 0) {
447 len = size - (p - buf);
448 type = HEVC_NAL_TYPE(p[j]);
449 if (type != HEVC_NAL_AUD &&
450 (type > HEVC_NAL_PPS || type < HEVC_NAL_VPS))
451 break;
452
453 if (type == HEVC_NAL_SPS) {
454 ret = stream_parse(inst, p, len);
455 if (!ret && (inst->vsi->cur_pic.coded_width !=
456 inst->vsi->pic.coded_width ||
457 inst->vsi->cur_pic.coded_height !=
458 inst->vsi->pic.coded_height)) {
459 inst->vsi->cur_pic = inst->vsi->pic;
460 return true;
461 }
462 }
463 p += j;
464 }
465 p++;
466 }
467
468 return false;
469}
470
471static int vdec_hevc_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
472 u64 timestamp, bool *res_chg)
473{
474 struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
475 struct aml_vdec_adapt *vdec = &inst->vdec;
476 struct stream_info *st;
477 u8 *buf;
478 u32 size;
479 int ret = -1;
480
481 /* bs NULL means flush decoder */
482 if (bs == NULL)
483 return -1;
484
485 buf = (u8 *)bs->vaddr;
486 size = bs->size;
487 st = (struct stream_info *)buf;
488
489 if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
490 ret = vdec_vbuf_write(vdec, st->m.buf, sizeof(st->m.drm));
491 else if (st->magic == NORe)
492 ret = vdec_vbuf_write(vdec, st->data, st->length);
493 else if (st->magic == NORn)
494 ret = vdec_write_nalu(inst, st->data, st->length, timestamp);
495 else if (inst->ctx->is_stream_mode)
496 ret = vdec_vbuf_write(vdec, buf, size);
497 else {
498 /*checked whether the resolution changes.*/
499 if ((*res_chg = monitor_res_change(inst, buf, size)))
500 return 0;
501
502 ret = vdec_write_nalu(inst, buf, size, timestamp);
503 }
504
505 return ret;
506}
507
508static int vdec_hevc_get_param(unsigned long h_vdec,
509 enum vdec_get_param_type type, void *out)
510{
511 int ret = 0;
512 struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
513
514 if (!inst) {
515 pr_err("the hevc inst of dec is invalid.\n");
516 return -1;
517 }
518
519 switch (type) {
520 case GET_PARAM_DISP_FRAME_BUFFER:
521 vdec_hevc_get_vf(inst, out);
522 break;
523
524 case GET_PARAM_FREE_FRAME_BUFFER:
525 ret = vdec_hevc_get_fb(inst, out);
526 break;
527
528 case GET_PARAM_PIC_INFO:
529 get_pic_info(inst, out);
530 break;
531
532 case GET_PARAM_DPB_SIZE:
533 get_dpb_size(inst, out);
534 break;
535
536 case GET_PARAM_CROP_INFO:
537 get_crop_info(inst, out);
538 break;
539
540 default:
541 aml_vcodec_err(inst, "invalid get parameter type=%d", type);
542 ret = -EINVAL;
543 }
544
545 return ret;
546}
547
548static void set_param_write_sync(struct vdec_hevc_inst *inst)
549{
550 complete(&inst->comp);
551}
552
553static void set_param_pic_info(struct vdec_hevc_inst *inst,
554 struct aml_vdec_pic_infos *info)
555{
556 struct vdec_pic_info *pic = &inst->vsi->pic;
557 struct vdec_hevc_dec_info *dec = &inst->vsi->dec;
558 struct v4l2_rect *rect = &inst->vsi->crop;
559
560 /* fill visible area size that be used for EGL. */
561 pic->visible_width = info->visible_width;
562 pic->visible_height = info->visible_height;
563
564 /* calc visible ares. */
565 rect->left = 0;
566 rect->top = 0;
567 rect->width = pic->visible_width;
568 rect->height = pic->visible_height;
569
570 /* config canvas size that be used for decoder. */
571 pic->coded_width = ALIGN(info->coded_width, 64);
572 pic->coded_height = ALIGN(info->coded_height, 64);
573 pic->y_len_sz = pic->coded_width * pic->coded_height;
574 pic->c_len_sz = pic->y_len_sz >> 1;
575
576 dec->dpb_sz = info->dpb_size;
577
578 /*wake up*/
579 complete(&inst->comp);
580
581 pr_info("Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n",
582 pic->visible_width, pic->visible_height,
583 pic->coded_width, pic->coded_height,
584 dec->dpb_sz);
585}
586
587static int vdec_hevc_set_param(unsigned long h_vdec,
588 enum vdec_set_param_type type, void *in)
589{
590 int ret = 0;
591 struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
592
593 if (!inst) {
594 pr_err("the hevc inst of dec is invalid.\n");
595 return -1;
596 }
597
598 switch (type) {
599 case SET_PARAM_WRITE_FRAME_SYNC:
600 set_param_write_sync(inst);
601 break;
602
603 case SET_PARAM_PIC_INFO:
604 set_param_pic_info(inst, in);
605 break;
606
607 default:
608 aml_vcodec_err(inst, "invalid set parameter type=%d", type);
609 ret = -EINVAL;
610 }
611
612 return ret;
613}
614
615static struct vdec_common_if vdec_hevc_if = {
616 .init = vdec_hevc_init,
617 .probe = vdec_hevc_probe,
618 .decode = vdec_hevc_decode,
619 .get_param = vdec_hevc_get_param,
620 .set_param = vdec_hevc_set_param,
621 .deinit = vdec_hevc_deinit,
622};
623
624struct vdec_common_if *get_hevc_dec_comm_if(void);
625
626struct vdec_common_if *get_hevc_dec_comm_if(void)
627{
628 return &vdec_hevc_if;
629}
630