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