summaryrefslogtreecommitdiff
path: root/drivers/amvdec_ports/decoder/vdec_hevc_if.c (plain)
blob: cd4d36153d6ffbe3fcc63cf505ba497db2ad6289
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 aml_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
126 pic->visible_width, pic->visible_height,
127 pic->coded_width, pic->coded_height);
128 aml_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
129 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
130}
131
132static void get_crop_info(struct vdec_hevc_inst *inst, struct v4l2_rect *cr)
133{
134 cr->left = inst->vsi->crop.left;
135 cr->top = inst->vsi->crop.top;
136 cr->width = inst->vsi->crop.width;
137 cr->height = inst->vsi->crop.height;
138
139 aml_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d",
140 cr->left, cr->top, cr->width, cr->height);
141}
142
143static void get_dpb_size(struct vdec_hevc_inst *inst, unsigned int *dpb_sz)
144{
145 *dpb_sz = inst->vsi->dec.dpb_sz;
146 aml_vcodec_debug(inst, "sz=%d", *dpb_sz);
147}
148
149static u32 vdec_config_default_parms(u8 *parm)
150{
151 u8 *pbuf = parm;
152
153 pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
154 pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:7;");
155 pbuf += sprintf(pbuf, "hevc_double_write_mode:16;");
156 pbuf += sprintf(pbuf, "hevc_buf_width:4096;");
157 pbuf += sprintf(pbuf, "hevc_buf_height:2304;");
158 pbuf += sprintf(pbuf, "save_buffer_mode:0;");
159 pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:0;");
160 pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:0;");
161
162 return parm - pbuf;
163}
164
165static void vdec_parser_parms(struct vdec_hevc_inst *inst)
166{
167 struct aml_vcodec_ctx *ctx = inst->ctx;
168
169 if (ctx->config.parm.dec.parms_status &
170 V4L2_CONFIG_PARM_DECODE_CFGINFO) {
171 u8 *pbuf = ctx->config.buf;
172
173 pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
174 pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;",
175 ctx->config.parm.dec.cfg.ref_buf_margin);
176 pbuf += sprintf(pbuf, "hevc_double_write_mode:%d;",
177 ctx->config.parm.dec.cfg.double_write_mode);
178 pbuf += sprintf(pbuf, "hevc_buf_width:4096;");
179 pbuf += sprintf(pbuf, "hevc_buf_height:2304;");
180 pbuf += sprintf(pbuf, "save_buffer_mode:0;");
181 pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_mode:%d;",
182 ctx->config.parm.dec.cfg.canvas_mem_mode);
183 pbuf += sprintf(pbuf, "parm_v4l_canvas_mem_endian:%d;",
184 ctx->config.parm.dec.cfg.canvas_mem_endian);
185 ctx->config.length = pbuf - ctx->config.buf;
186 } else {
187 ctx->config.parm.dec.cfg.double_write_mode = 16;
188 ctx->config.parm.dec.cfg.ref_buf_margin = 7;
189 ctx->config.length = vdec_config_default_parms(ctx->config.buf);
190 }
191
192 inst->vdec.config = ctx->config;
193 inst->parms.cfg = ctx->config.parm.dec.cfg;
194 inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_CFGINFO;
195}
196
197static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
198{
199 struct vdec_hevc_inst *inst = NULL;
200 int ret = -1;
201
202 inst = kzalloc(sizeof(*inst), GFP_KERNEL);
203 if (!inst)
204 return -ENOMEM;
205
206 inst->vdec.video_type = VFORMAT_HEVC;
207 inst->vdec.dev = ctx->dev->vpu_plat_dev;
208 inst->vdec.filp = ctx->dev->filp;
209 inst->vdec.ctx = ctx;
210 inst->ctx = ctx;
211
212 vdec_parser_parms(inst);
213
214 /* set play mode.*/
215 if (ctx->is_drm_mode)
216 inst->vdec.port.flag |= PORT_FLAG_DRM;
217
218 /* to eable hevc hw.*/
219 inst->vdec.port.type = PORT_TYPE_HEVC;
220
221 /* init vfm */
222 inst->vfm.ctx = ctx;
223 inst->vfm.ada_ctx = &inst->vdec;
224 ret = vcodec_vfm_init(&inst->vfm);
225 if (ret) {
226 pr_err("%s, init vfm failed.\n", __func__);
227 goto err;
228 }
229
230 ret = video_decoder_init(&inst->vdec);
231 if (ret) {
232 aml_vcodec_err(inst, "vdec_hevc init err=%d", ret);
233 goto err;
234 }
235
236 /* probe info from the stream */
237 inst->vsi = kzalloc(sizeof(struct vdec_hevc_vsi), GFP_KERNEL);
238 if (!inst->vsi) {
239 ret = -ENOMEM;
240 goto err;
241 }
242
243 /* alloc the header buffer to be used cache sps or spp etc.*/
244 inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
245 if (!inst->vsi) {
246 ret = -ENOMEM;
247 goto err;
248 }
249
250 init_completion(&inst->comp);
251
252 aml_vcodec_debug(inst, "hevc Instance >> %p", inst);
253
254 ctx->ada_ctx = &inst->vdec;
255 *h_vdec = (unsigned long)inst;
256
257 //dump_init();
258
259 return 0;
260err:
261 if (inst)
262 vcodec_vfm_release(&inst->vfm);
263 if (inst && inst->vsi && inst->vsi->header_buf)
264 kfree(inst->vsi->header_buf);
265 if (inst && inst->vsi)
266 kfree(inst->vsi);
267 if (inst)
268 kfree(inst);
269 *h_vdec = 0;
270
271 return ret;
272}
273
274
275static int refer_buffer_num(struct h265_SPS_t *sps)
276{
277 int used_buf_num = 0;
278 int sps_pic_buf_diff = 0;
279
280 if ((!sps->temporal_layer[0].num_reorder_pics) &&
281 (sps->temporal_layer[0].max_dec_pic_buffering)) {
282 /* the range of sps_num_reorder_pics_0 is in
283 [0, sps_max_dec_pic_buffering_minus1_0] */
284 used_buf_num = sps->temporal_layer[0].max_dec_pic_buffering;
285 } else
286 used_buf_num = sps->temporal_layer[0].num_reorder_pics;
287
288 sps_pic_buf_diff = sps->temporal_layer[0].max_dec_pic_buffering -
289 sps->temporal_layer[0].num_reorder_pics + 1;
290
291 if (sps_pic_buf_diff >= 4)
292 used_buf_num += 1;
293
294 /*need one more for multi instance, as
295 apply_ref_pic_set() has no chanch to run to
296 to clear referenced flag in some case */
297 used_buf_num++;
298
299 /* for eos add more buffer to flush.*/
300 used_buf_num++;
301
302 return used_buf_num;
303}
304
305static int vdec_get_dw_mode(struct vdec_hevc_inst *inst, int dw_mode)
306{
307 u32 valid_dw_mode = inst->parms.cfg.double_write_mode;
308 int w = inst->parms.cfg.init_width;
309 int h = inst->parms.cfg.init_height;
310 u32 dw = 0x1; /*1:1*/
311
312 switch (valid_dw_mode) {
313 case 0x100:
314 if (w > 1920 && h > 1088)
315 dw = 0x4; /*1:2*/
316 break;
317 case 0x200:
318 if (w > 1920 && h > 1088)
319 dw = 0x2; /*1:4*/
320 break;
321 case 0x300:
322 if (w > 1280 && h > 720)
323 dw = 0x4; /*1:2*/
324 break;
325 default:
326 dw = valid_dw_mode;
327 break;
328 }
329
330 return dw;
331}
332
333static int vdec_pic_scale(struct vdec_hevc_inst *inst, int length, int dw_mode)
334{
335 int ret = 64;
336
337 switch (vdec_get_dw_mode(inst, dw_mode)) {
338 case 0x0: /* only afbc, output afbc */
339 ret = 64;
340 break;
341 case 0x1: /* afbc and (w x h), output YUV420 */
342 ret = length;
343 break;
344 case 0x2: /* afbc and (w/4 x h/4), output YUV420 */
345 case 0x3: /* afbc and (w/4 x h/4), output afbc and YUV420 */
346 ret = length >> 2;
347 break;
348 case 0x4: /* afbc and (w/2 x h/2), output YUV420 */
349 ret = length >> 1;
350 break;
351 case 0x10: /* (w x h), output YUV420-8bit)*/
352 default:
353 ret = length;
354 break;
355 }
356
357 return ret;
358}
359
360static void fill_vdec_params(struct vdec_hevc_inst *inst, struct h265_SPS_t *sps)
361{
362 struct vdec_pic_info *pic = &inst->vsi->pic;
363 struct vdec_hevc_dec_info *dec = &inst->vsi->dec;
364 struct v4l2_rect *rect = &inst->vsi->crop;
365 int dw = inst->parms.cfg.double_write_mode;
366 int margin = inst->parms.cfg.ref_buf_margin;
367
368 /* fill visible area size that be used for EGL. */
369 pic->visible_width = sps->width - (sps->output_window.left_offset +
370 sps->output_window.right_offset);
371 pic->visible_height = sps->height - (sps->output_window.top_offset +
372 sps->output_window.bottom_offset);
373 pic->visible_width = vdec_pic_scale(inst, pic->visible_width, dw);
374 pic->visible_height = vdec_pic_scale(inst, pic->visible_height, dw);
375
376 /* calc visible ares. */
377 rect->left = 0;
378 rect->top = 0;
379 rect->width = pic->visible_width;
380 rect->height = pic->visible_height;
381
382 /* config canvas size that be used for decoder. */
383 pic->coded_width = vdec_pic_scale(inst, ALIGN(sps->width, 32), dw);
384 pic->coded_height = vdec_pic_scale(inst, ALIGN(sps->height, 32), dw);
385
386 pic->y_len_sz = pic->coded_width * pic->coded_height;
387 pic->c_len_sz = pic->y_len_sz >> 1;
388
389 /* calc DPB size */
390 dec->dpb_sz = refer_buffer_num(sps) + margin;
391
392 inst->parms.ps.visible_width = pic->visible_width;
393 inst->parms.ps.visible_height = pic->visible_height;
394 inst->parms.ps.coded_width = pic->coded_width;
395 inst->parms.ps.coded_height = pic->coded_height;
396 inst->parms.ps.dpb_size = dec->dpb_sz;
397 inst->parms.parms_status |= V4L2_CONFIG_PARM_DECODE_PSINFO;
398
399 pr_info("[%d] The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n",
400 inst->ctx->id, dw, pic->coded_width, pic->coded_height,
401 pic->visible_width, pic->visible_height,
402 dec->dpb_sz - margin, margin);
403}
404
405static int stream_parse_by_ucode(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
406{
407 int ret = 0;
408 struct aml_vdec_adapt *vdec = &inst->vdec;
409
410 ret = vdec_vframe_write(vdec, buf, size, 0);
411 if (ret < 0) {
412 pr_err("write frame data failed. err: %d\n", ret);
413 return ret;
414 }
415
416 /* wait ucode parse ending. */
417 wait_for_completion_timeout(&inst->comp,
418 msecs_to_jiffies(1000));
419
420 return inst->vsi->dec.dpb_sz ? 0 : -1;
421}
422
423static int stream_parse(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
424{
425 int ret = 0;
426 struct h265_param_sets *ps = NULL;
427
428 ps = vzalloc(sizeof(struct h265_param_sets));
429 if (ps == NULL)
430 return -ENOMEM;
431
432 ret = h265_decode_extradata_ps(buf, size, ps);
433 if (ret) {
434 pr_err("parse extra data failed. err: %d\n", ret);
435 goto out;
436 }
437
438 if (ps->sps_parsed)
439 fill_vdec_params(inst, &ps->sps);
440
441 ret = ps->sps_parsed ? 0 : -1;
442out:
443 vfree(ps);
444
445 return ret;
446}
447
448static int vdec_hevc_probe(unsigned long h_vdec,
449 struct aml_vcodec_mem *bs, void *out)
450{
451 struct vdec_hevc_inst *inst =
452 (struct vdec_hevc_inst *)h_vdec;
453 struct stream_info *st;
454 u8 *buf = (u8 *)bs->vaddr;
455 u32 size = bs->size;
456 int ret = 0;
457
458 st = (struct stream_info *)buf;
459 if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
460 return 0;
461
462 if (st->magic == NORe || st->magic == NORn)
463 ret = stream_parse(inst, st->data, st->length);
464 else {
465 if (inst->ctx->param_sets_from_ucode)
466 ret = stream_parse_by_ucode(inst, buf, size);
467 else
468 ret = stream_parse(inst, buf, size);
469 }
470
471 inst->vsi->cur_pic = inst->vsi->pic;
472
473 return ret;
474}
475
476static void vdec_hevc_deinit(unsigned long h_vdec)
477{
478 ulong flags;
479 struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
480 struct aml_vcodec_ctx *ctx = inst->ctx;
481
482 aml_vcodec_debug_enter(inst);
483
484 video_decoder_release(&inst->vdec);
485
486 vcodec_vfm_release(&inst->vfm);
487
488 //dump_deinit();
489
490 spin_lock_irqsave(&ctx->slock, flags);
491 if (inst->vsi && inst->vsi->header_buf)
492 kfree(inst->vsi->header_buf);
493
494 if (inst->vsi)
495 kfree(inst->vsi);
496
497 kfree(inst);
498
499 ctx->drv_handle = 0;
500 spin_unlock_irqrestore(&ctx->slock, flags);
501}
502
503static int vdec_hevc_get_fb(struct vdec_hevc_inst *inst, struct vdec_v4l2_buffer **out)
504{
505 return get_fb_from_queue(inst->ctx, out);
506}
507
508static void vdec_hevc_get_vf(struct vdec_hevc_inst *inst, struct vdec_v4l2_buffer **out)
509{
510 struct vframe_s *vf = NULL;
511 struct vdec_v4l2_buffer *fb = NULL;
512
513 vf = peek_video_frame(&inst->vfm);
514 if (!vf) {
515 aml_vcodec_debug(inst, "there is no vframe.");
516 *out = NULL;
517 return;
518 }
519
520 vf = get_video_frame(&inst->vfm);
521 if (!vf) {
522 aml_vcodec_debug(inst, "the vframe is avalid.");
523 *out = NULL;
524 return;
525 }
526
527 atomic_set(&vf->use_cnt, 1);
528
529 fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
530 fb->vf_handle = (unsigned long)vf;
531 fb->status = FB_ST_DISPLAY;
532
533 *out = fb;
534
535 //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used);
536 //dump_write(fb->base_y.vaddr, fb->base_y.bytes_used);
537 //dump_write(fb->base_c.vaddr, fb->base_c.bytes_used);
538
539 /* convert yuv format. */
540 //swap_uv(fb->base_c.vaddr, fb->base_c.size);
541}
542
543static int vdec_write_nalu(struct vdec_hevc_inst *inst,
544 u8 *buf, u32 size, u64 ts)
545{
546 int ret = 0;
547 struct aml_vdec_adapt *vdec = &inst->vdec;
548
549 ret = vdec_vframe_write(vdec, buf, size, ts);
550
551 return ret;
552}
553
554static bool monitor_res_change(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
555{
556 int ret = 0, i = 0, j = 0;
557 u8 *p = buf;
558 int len = size;
559 u32 type;
560
561 for (i = 4; i < size; i++) {
562 j = find_start_code(p, len);
563 if (j > 0) {
564 len = size - (p - buf);
565 type = HEVC_NAL_TYPE(p[j]);
566 if (type != HEVC_NAL_AUD &&
567 (type > HEVC_NAL_PPS || type < HEVC_NAL_VPS))
568 break;
569
570 if (type == HEVC_NAL_SPS) {
571 ret = stream_parse(inst, p, len);
572 if (ret)
573 break;
574 }
575 p += j;
576 }
577 p++;
578 }
579
580 if (!ret && (inst->vsi->cur_pic.coded_width !=
581 inst->vsi->pic.coded_width ||
582 inst->vsi->cur_pic.coded_height !=
583 inst->vsi->pic.coded_height)) {
584 inst->vsi->cur_pic = inst->vsi->pic;
585 return true;
586 }
587
588 return false;
589}
590
591static int vdec_hevc_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
592 u64 timestamp, bool *res_chg)
593{
594 struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
595 struct aml_vdec_adapt *vdec = &inst->vdec;
596 struct stream_info *st;
597 u8 *buf;
598 u32 size;
599 int ret = -1;
600
601 if (bs == NULL)
602 return -1;
603
604 if (vdec_input_full(vdec))
605 return -EAGAIN;
606
607 buf = (u8 *)bs->vaddr;
608 size = bs->size;
609 st = (struct stream_info *)buf;
610
611 if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
612 ret = vdec_vbuf_write(vdec, st->m.buf, sizeof(st->m.drm));
613 else if (st->magic == NORe)
614 ret = vdec_vbuf_write(vdec, st->data, st->length);
615 else if (st->magic == NORn)
616 ret = vdec_write_nalu(inst, st->data, st->length, timestamp);
617 else if (inst->ctx->is_stream_mode)
618 ret = vdec_vbuf_write(vdec, buf, size);
619 else {
620 /*checked whether the resolution changes.*/
621 if ((*res_chg = monitor_res_change(inst, buf, size)))
622 return 0;
623
624 ret = vdec_write_nalu(inst, buf, size, timestamp);
625 }
626
627 return ret;
628}
629
630 static void get_param_config_info(struct vdec_hevc_inst *inst,
631 struct aml_dec_params *parms)
632 {
633 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CFGINFO)
634 parms->cfg = inst->parms.cfg;
635 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_PSINFO)
636 parms->ps = inst->parms.ps;
637 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_HDRINFO)
638 parms->hdr = inst->parms.hdr;
639 if (inst->parms.parms_status & V4L2_CONFIG_PARM_DECODE_CNTINFO)
640 parms->cnt = inst->parms.cnt;
641
642 parms->parms_status |= inst->parms.parms_status;
643
644 aml_vcodec_debug(inst, "parms status: %u", parms->parms_status);
645 }
646
647static int vdec_hevc_get_param(unsigned long h_vdec,
648 enum vdec_get_param_type type, void *out)
649{
650 int ret = 0;
651 struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
652
653 if (!inst) {
654 pr_err("the hevc inst of dec is invalid.\n");
655 return -1;
656 }
657
658 switch (type) {
659 case GET_PARAM_DISP_FRAME_BUFFER:
660 vdec_hevc_get_vf(inst, out);
661 break;
662
663 case GET_PARAM_FREE_FRAME_BUFFER:
664 ret = vdec_hevc_get_fb(inst, out);
665 break;
666
667 case GET_PARAM_PIC_INFO:
668 get_pic_info(inst, out);
669 break;
670
671 case GET_PARAM_DPB_SIZE:
672 get_dpb_size(inst, out);
673 break;
674
675 case GET_PARAM_CROP_INFO:
676 get_crop_info(inst, out);
677 break;
678
679 case GET_PARAM_CONFIG_INFO:
680 get_param_config_info(inst, out);
681 break;
682 default:
683 aml_vcodec_err(inst, "invalid get parameter type=%d", type);
684 ret = -EINVAL;
685 }
686
687 return ret;
688}
689
690static void set_param_write_sync(struct vdec_hevc_inst *inst)
691{
692 complete(&inst->comp);
693}
694
695static void set_param_ps_info(struct vdec_hevc_inst *inst,
696 struct aml_vdec_ps_infos *ps)
697{
698 struct vdec_pic_info *pic = &inst->vsi->pic;
699 struct vdec_hevc_dec_info *dec = &inst->vsi->dec;
700 struct v4l2_rect *rect = &inst->vsi->crop;
701
702 /* fill visible area size that be used for EGL. */
703 pic->visible_width = ps->visible_width;
704 pic->visible_height = ps->visible_height;
705
706 /* calc visible ares. */
707 rect->left = 0;
708 rect->top = 0;
709 rect->width = pic->visible_width;
710 rect->height = pic->visible_height;
711
712 /* config canvas size that be used for decoder. */
713 pic->coded_width = ALIGN(ps->coded_width, 64);
714 pic->coded_height = ALIGN(ps->coded_height, 64);
715 pic->y_len_sz = pic->coded_width * pic->coded_height;
716 pic->c_len_sz = pic->y_len_sz >> 1;
717
718 dec->dpb_sz = ps->dpb_size;
719
720 inst->parms.ps = *ps;
721 inst->parms.parms_status |=
722 V4L2_CONFIG_PARM_DECODE_PSINFO;
723
724 /*wake up*/
725 complete(&inst->comp);
726
727 pr_info("Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n",
728 pic->visible_width, pic->visible_height,
729 pic->coded_width, pic->coded_height,
730 dec->dpb_sz);
731}
732
733static void set_param_hdr_info(struct vdec_hevc_inst *inst,
734 struct aml_vdec_hdr_infos *hdr)
735{
736 if (!(inst->parms.parms_status &
737 V4L2_CONFIG_PARM_DECODE_HDRINFO)) {
738 inst->parms.hdr = *hdr;
739 inst->parms.parms_status |=
740 V4L2_CONFIG_PARM_DECODE_HDRINFO;
741 aml_vdec_dispatch_event(inst->ctx,
742 V4L2_EVENT_SRC_CH_HDRINFO);
743 pr_info("H265 set HDR infos\n");
744 }
745}
746
747static void set_param_post_event(struct vdec_hevc_inst *inst, u32 *event)
748{
749 aml_vdec_dispatch_event(inst->ctx, *event);
750 pr_info("H265 post event: %d\n", *event);
751}
752
753static int vdec_hevc_set_param(unsigned long h_vdec,
754 enum vdec_set_param_type type, void *in)
755{
756 int ret = 0;
757 struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
758
759 if (!inst) {
760 pr_err("the hevc inst of dec is invalid.\n");
761 return -1;
762 }
763
764 switch (type) {
765 case SET_PARAM_WRITE_FRAME_SYNC:
766 set_param_write_sync(inst);
767 break;
768
769 case SET_PARAM_PS_INFO:
770 set_param_ps_info(inst, in);
771 break;
772
773 case SET_PARAM_HDR_INFO:
774 set_param_hdr_info(inst, in);
775 break;
776
777 case SET_PARAM_POST_EVENT:
778 set_param_post_event(inst, in);
779 break;
780 default:
781 aml_vcodec_err(inst, "invalid set parameter type=%d", type);
782 ret = -EINVAL;
783 }
784
785 return ret;
786}
787
788static struct vdec_common_if vdec_hevc_if = {
789 .init = vdec_hevc_init,
790 .probe = vdec_hevc_probe,
791 .decode = vdec_hevc_decode,
792 .get_param = vdec_hevc_get_param,
793 .set_param = vdec_hevc_set_param,
794 .deinit = vdec_hevc_deinit,
795};
796
797struct vdec_common_if *get_hevc_dec_comm_if(void);
798
799struct vdec_common_if *get_hevc_dec_comm_if(void)
800{
801 return &vdec_hevc_if;
802}
803