summaryrefslogtreecommitdiff
path: root/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c (plain)
blob: cdde95b1c69ef9241df2aa7de756f46248d3022c
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_mpeg12_parser.h"
33
34#define NAL_TYPE(value) ((value) & 0x1F)
35#define HEADER_BUFFER_SIZE (32 * 1024)
36
37/**
38 * struct mpeg12_fb - mpeg12 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 mpeg12_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_mpeg12_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_mpeg12_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_mpeg12_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_mpeg12_vsi {
89 char *header_buf;
90 int sps_size;
91 int pps_size;
92 int sei_size;
93 int head_offset;
94 struct vdec_mpeg12_dec_info dec;
95 struct vdec_pic_info pic;
96 struct v4l2_rect crop;
97 bool is_combine;
98 int nalu_pos;
99 //struct mpeg12_param_sets ps;
100};
101
102/**
103 * struct vdec_mpeg12_inst - mpeg12 decoder instance
104 * @num_nalu : how many nalus be decoded
105 * @ctx : point to aml_vcodec_ctx
106 * @vsi : VPU shared information
107 */
108struct vdec_mpeg12_inst {
109 unsigned int num_nalu;
110 struct aml_vcodec_ctx *ctx;
111 struct aml_vdec_adapt vdec;
112 struct vdec_mpeg12_vsi *vsi;
113 struct vcodec_vfm_s vfm;
114};
115
116static void get_pic_info(struct vdec_mpeg12_inst *inst,
117 struct vdec_pic_info *pic)
118{
119 *pic = inst->vsi->pic;
120
121 aml_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
122 pic->visible_width, pic->visible_height,
123 pic->coded_width, pic->coded_height);
124 aml_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
125 pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
126}
127
128static void get_crop_info(struct vdec_mpeg12_inst *inst, struct v4l2_rect *cr)
129{
130 cr->left = inst->vsi->crop.left;
131 cr->top = inst->vsi->crop.top;
132 cr->width = inst->vsi->crop.width;
133 cr->height = inst->vsi->crop.height;
134
135 aml_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d",
136 cr->left, cr->top, cr->width, cr->height);
137}
138
139static void get_dpb_size(struct vdec_mpeg12_inst *inst, unsigned int *dpb_sz)
140{
141 *dpb_sz = inst->vsi->dec.dpb_sz;
142 aml_vcodec_debug(inst, "sz=%d", *dpb_sz);
143}
144
145static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
146{
147 struct vdec_mpeg12_inst *inst = NULL;
148 int ret = -1;
149
150 inst = kzalloc(sizeof(*inst), GFP_KERNEL);
151 if (!inst)
152 return -ENOMEM;
153
154 inst->ctx = ctx;
155
156 inst->vdec.video_type = VFORMAT_MPEG12;
157 inst->vdec.dev = ctx->dev->vpu_plat_dev;
158 inst->vdec.filp = ctx->dev->filp;
159 inst->vdec.ctx = ctx;
160
161 /* set play mode.*/
162 if (ctx->is_drm_mode)
163 inst->vdec.port.flag |= PORT_FLAG_DRM;
164
165 /* to eable mpeg12 hw.*/
166 inst->vdec.port.type = PORT_TYPE_VIDEO;
167
168 /* init vfm */
169 inst->vfm.ctx = ctx;
170 inst->vfm.ada_ctx = &inst->vdec;
171 vcodec_vfm_init(&inst->vfm);
172
173 ret = video_decoder_init(&inst->vdec);
174 if (ret) {
175 aml_vcodec_err(inst, "vdec_mpeg12 init err=%d", ret);
176 goto error_free_inst;
177 }
178
179 /* probe info from the stream */
180 inst->vsi = kzalloc(sizeof(struct vdec_mpeg12_vsi), GFP_KERNEL);
181 if (!inst->vsi) {
182 ret = -ENOMEM;
183 goto error_free_inst;
184 }
185
186 /* alloc the header buffer to be used cache sps or spp etc.*/
187 inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
188 if (!inst->vsi) {
189 ret = -ENOMEM;
190 goto error_free_vsi;
191 }
192
193 inst->vsi->pic.visible_width = 1920;
194 inst->vsi->pic.visible_height = 1080;
195 inst->vsi->pic.coded_width = 1920;
196 inst->vsi->pic.coded_height = 1088;
197 inst->vsi->pic.y_bs_sz = 0;
198 inst->vsi->pic.y_len_sz = (1920 * 1088);
199 inst->vsi->pic.c_bs_sz = 0;
200 inst->vsi->pic.c_len_sz = (1920 * 1088 / 2);
201
202 aml_vcodec_debug(inst, "mpeg12 Instance >> %p", inst);
203
204 ctx->ada_ctx = &inst->vdec;
205 *h_vdec = (unsigned long)inst;
206
207 //dump_init();
208
209 return 0;
210
211error_free_vsi:
212 kfree(inst->vsi);
213error_free_inst:
214 kfree(inst);
215 *h_vdec = 0;
216
217 return ret;
218}
219
220static void fill_vdec_params(struct vdec_mpeg12_inst *inst,
221 struct MpvParseContext *dec_ps)
222{
223 struct vdec_pic_info *pic = &inst->vsi->pic;
224 struct vdec_mpeg12_dec_info *dec = &inst->vsi->dec;
225 struct v4l2_rect *rect = &inst->vsi->crop;
226
227 /* fill visible area size that be used for EGL. */
228 pic->visible_width = dec_ps->width;
229 pic->visible_height = dec_ps->height;
230
231 /* calc visible ares. */
232 rect->left = 0;
233 rect->top = 0;
234 rect->width = pic->visible_width;
235 rect->height = pic->visible_height;
236
237 /* config canvas size that be used for decoder. */
238 pic->coded_width = ALIGN(dec_ps->coded_width, 64);
239 pic->coded_height = ALIGN(dec_ps->coded_height, 64);;
240
241 pic->y_len_sz = pic->coded_width * pic->coded_height;
242 pic->c_len_sz = pic->y_len_sz >> 1;
243
244 /* calc DPB size */
245 dec->dpb_sz = 9;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h);
246
247 pr_info("[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n",
248 inst->ctx->id, pic->coded_width, pic->coded_height,
249 pic->visible_width, pic->visible_height, dec->dpb_sz);
250}
251
252static int stream_parse(struct vdec_mpeg12_inst *inst, u8 *buf, u32 size)
253{
254 int ret = 0;
255 struct mpeg12_param_sets *ps = NULL;
256
257 ps = kzalloc(sizeof(struct mpeg12_param_sets), GFP_KERNEL);
258 if (ps == NULL)
259 return -ENOMEM;
260
261 ret = mpeg12_decode_extradata_ps(buf, size, ps);
262 if (ret) {
263 pr_err("parse extra data failed. err: %d\n", ret);
264 goto out;
265 }
266
267 if (ps->head_parsed)
268 fill_vdec_params(inst, &ps->dec_ps);
269
270 ret = ps->head_parsed ? 0 : -1;
271out:
272 kfree(ps);
273
274 return ret;
275}
276
277static int vdec_mpeg12_probe(unsigned long h_vdec,
278 struct aml_vcodec_mem *bs, void *out)
279{
280 struct vdec_mpeg12_inst *inst =
281 (struct vdec_mpeg12_inst *)h_vdec;
282 struct stream_info *st;
283 u8 *buf = (u8 *)bs->vaddr;
284 u32 size = bs->size;
285 int ret = 0;
286
287 st = (struct stream_info *)buf;
288 if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
289 return 0;
290
291 if (st->magic == NORe || st->magic == NORn)
292 ret = stream_parse(inst, st->data, st->length);
293 else
294 ret = stream_parse(inst, buf, size);
295
296 return ret;
297}
298
299static void vdec_mpeg12_deinit(unsigned long h_vdec)
300{
301 struct vdec_mpeg12_inst *inst = (struct vdec_mpeg12_inst *)h_vdec;
302
303 if (!inst)
304 return;
305
306 aml_vcodec_debug_enter(inst);
307
308 video_decoder_release(&inst->vdec);
309
310 vcodec_vfm_release(&inst->vfm);
311
312 //dump_deinit();
313
314 if (inst->vsi && inst->vsi->header_buf)
315 kfree(inst->vsi->header_buf);
316
317 if (inst->vsi)
318 kfree(inst->vsi);
319
320 kfree(inst);
321}
322
323static int vdec_mpeg12_get_fb(struct vdec_mpeg12_inst *inst, struct vdec_v4l2_buffer **out)
324{
325 return get_fb_from_queue(inst->ctx, out);
326}
327
328static void vdec_mpeg12_get_vf(struct vdec_mpeg12_inst *inst, struct vdec_v4l2_buffer **out)
329{
330 struct vframe_s *vf = NULL;
331 struct vdec_v4l2_buffer *fb = NULL;
332
333 vf = peek_video_frame(&inst->vfm);
334 if (!vf) {
335 aml_vcodec_debug(inst, "there is no vframe.");
336 *out = NULL;
337 return;
338 }
339
340 vf = get_video_frame(&inst->vfm);
341 if (!vf) {
342 aml_vcodec_debug(inst, "the vframe is avalid.");
343 *out = NULL;
344 return;
345 }
346
347 atomic_set(&vf->use_cnt, 1);
348
349 fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
350 fb->vf_handle = (unsigned long)vf;
351 fb->status = FB_ST_DISPLAY;
352
353 *out = fb;
354
355 //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used);
356 //dump_write(fb->base_y.va, fb->base_y.bytes_used);
357 //dump_write(fb->base_c.va, fb->base_c.bytes_used);
358
359 /* convert yuv format. */
360 //swap_uv(fb->base_c.va, fb->base_c.size);
361}
362
363static int vdec_write_nalu(struct vdec_mpeg12_inst *inst,
364 u8 *buf, u32 size, u64 ts)
365{
366 int ret = 0;
367 struct aml_vdec_adapt *vdec = &inst->vdec;
368
369 ret = vdec_vframe_write(vdec, buf, size, ts);
370
371 return ret;
372}
373
374static int vdec_mpeg12_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
375 u64 timestamp, bool *res_chg)
376{
377 struct vdec_mpeg12_inst *inst = (struct vdec_mpeg12_inst *)h_vdec;
378 struct aml_vdec_adapt *vdec = &inst->vdec;
379 struct stream_info *st;
380 u8 *buf;
381 u32 size;
382 int ret = 0;
383
384 /* bs NULL means flush decoder */
385 if (bs == NULL)
386 return 0;
387
388 buf = (u8 *)bs->vaddr;
389 size = bs->size;
390 st = (struct stream_info *)buf;
391
392 if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
393 ret = vdec_vbuf_write(vdec, st->m.buf, sizeof(st->m.drm));
394 else if (st->magic == NORe)
395 ret = vdec_vbuf_write(vdec, st->data, st->length);
396 else if (st->magic == NORn)
397 ret = vdec_write_nalu(inst, st->data, st->length, timestamp);
398 else if (inst->ctx->is_stream_mode)
399 ret = vdec_vbuf_write(vdec, buf, size);
400 else
401 ret = vdec_write_nalu(inst, buf, size, timestamp);
402
403 return ret;
404}
405
406static int vdec_mpeg12_get_param(unsigned long h_vdec,
407 enum vdec_get_param_type type, void *out)
408{
409 int ret = 0;
410 struct vdec_mpeg12_inst *inst = (struct vdec_mpeg12_inst *)h_vdec;
411
412 if (!inst) {
413 pr_err("the mpeg12 inst of dec is invalid.\n");
414 return -1;
415 }
416
417 switch (type) {
418 case GET_PARAM_DISP_FRAME_BUFFER:
419 vdec_mpeg12_get_vf(inst, out);
420 break;
421
422 case GET_PARAM_FREE_FRAME_BUFFER:
423 ret = vdec_mpeg12_get_fb(inst, out);
424 break;
425
426 case GET_PARAM_PIC_INFO:
427 get_pic_info(inst, out);
428 break;
429
430 case GET_PARAM_DPB_SIZE:
431 get_dpb_size(inst, out);
432 break;
433
434 case GET_PARAM_CROP_INFO:
435 get_crop_info(inst, out);
436 break;
437
438 default:
439 aml_vcodec_err(inst, "invalid get parameter type=%d", type);
440 ret = -EINVAL;
441 }
442
443 return ret;
444}
445
446static void set_param_pic_info(struct vdec_mpeg12_inst *inst,
447 struct aml_vdec_pic_infos *info)
448{
449 pr_info("---%s, %d\n", __func__, __LINE__);
450}
451
452static int vdec_mpeg12_set_param(unsigned long h_vdec,
453 enum vdec_set_param_type type, void *in)
454{
455 int ret = 0;
456 struct vdec_mpeg12_inst *inst = (struct vdec_mpeg12_inst *)h_vdec;
457
458 if (!inst) {
459 pr_err("the mpeg12 inst of dec is invalid.\n");
460 return -1;
461 }
462
463 switch (type) {
464 case SET_PARAM_PIC_INFO:
465 set_param_pic_info(inst, in);
466 break;
467
468 default:
469 aml_vcodec_err(inst, "invalid set parameter type=%d", type);
470 ret = -EINVAL;
471 }
472
473 return ret;
474}
475
476static struct vdec_common_if vdec_mpeg12_if = {
477 .init = vdec_mpeg12_init,
478 .probe = vdec_mpeg12_probe,
479 .decode = vdec_mpeg12_decode,
480 .get_param = vdec_mpeg12_get_param,
481 .set_param = vdec_mpeg12_set_param,
482 .deinit = vdec_mpeg12_deinit,
483};
484
485struct vdec_common_if *get_mpeg12_dec_comm_if(void);
486
487struct vdec_common_if *get_mpeg12_dec_comm_if(void)
488{
489 return &vdec_mpeg12_if;
490}
491