summaryrefslogtreecommitdiff
path: root/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c (plain)
blob: 0db4eca5c80d9d68c9bbffd6f4c2f07a445db64b
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_mjpeg_parser.h"
33
34#define NAL_TYPE(value) ((value) & 0x1F)
35#define HEADER_BUFFER_SIZE (32 * 1024)
36
37/**
38 * struct mjpeg_fb - mjpeg 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 mjpeg_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_mjpeg_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_mjpeg_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_mjpeg_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_mjpeg_vsi {
89 char *header_buf;
90 int sps_size;
91 int pps_size;
92 int sei_size;
93 int head_offset;
94 struct vdec_mjpeg_dec_info dec;
95 struct vdec_pic_info pic;
96 struct v4l2_rect crop;
97 bool is_combine;
98 int nalu_pos;
99 //struct mjpeg_param_sets ps;
100};
101
102/**
103 * struct vdec_mjpeg_inst - mjpeg 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_mjpeg_inst {
109 unsigned int num_nalu;
110 struct aml_vcodec_ctx *ctx;
111 struct aml_vdec_adapt vdec;
112 struct vdec_mjpeg_vsi *vsi;
113 struct vcodec_vfm_s vfm;
114};
115
116static void get_pic_info(struct vdec_mjpeg_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_mjpeg_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_mjpeg_inst *inst, unsigned int *dpb_sz)
140{
141 *dpb_sz = 20;//inst->vsi->dec.dpb_sz;
142 aml_vcodec_debug(inst, "sz=%d", *dpb_sz);
143}
144
145static int vdec_mjpeg_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
146{
147 struct vdec_mjpeg_inst *inst = NULL;
148 int ret = -1;
149
150 inst = kzalloc(sizeof(*inst), GFP_KERNEL);
151 if (!inst)
152 return -ENOMEM;
153
154 inst->vdec.video_type = VFORMAT_MJPEG;
155 inst->vdec.dev = ctx->dev->vpu_plat_dev;
156 inst->vdec.filp = ctx->dev->filp;
157 inst->vdec.config = ctx->config;
158 inst->vdec.ctx = ctx;
159 inst->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 mjpeg 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_mjpeg init err=%d", ret);
176 goto error_free_inst;
177 }
178
179 /* probe info from the stream */
180 inst->vsi = kzalloc(sizeof(struct vdec_mjpeg_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, "mjpeg 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
220#if 0
221static int refer_buffer_num(int level_idc, int poc_cnt,
222 int mb_width, int mb_height)
223{
224 return 20;
225}
226#endif
227
228static void fill_vdec_params(struct vdec_mjpeg_inst *inst,
229 struct MJpegDecodeContext *ps)
230{
231 struct vdec_pic_info *pic = &inst->vsi->pic;
232 struct vdec_mjpeg_dec_info *dec = &inst->vsi->dec;
233 struct v4l2_rect *rect = &inst->vsi->crop;
234
235 /* fill visible area size that be used for EGL. */
236 pic->visible_width = ps->width;
237 pic->visible_height = ps->height;
238
239 /* calc visible ares. */
240 rect->left = 0;
241 rect->top = 0;
242 rect->width = pic->visible_width;
243 rect->height = pic->visible_height;
244
245 /* config canvas size that be used for decoder. */
246 pic->coded_width = ALIGN(ps->width, 64);
247 pic->coded_height = ALIGN(ps->height, 64);
248
249 pic->y_len_sz = pic->coded_width * pic->coded_height;
250 pic->c_len_sz = pic->y_len_sz >> 1;
251
252 /* calc DPB size */
253 dec->dpb_sz = 9;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h);
254
255 pr_info("[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n",
256 inst->ctx->id, pic->coded_width, pic->coded_height,
257 pic->visible_width, pic->visible_height, dec->dpb_sz);
258}
259
260static int stream_parse(struct vdec_mjpeg_inst *inst, u8 *buf, u32 size)
261{
262 int ret = 0;
263 struct mjpeg_param_sets *ps = NULL;
264
265 ps = kzalloc(sizeof(struct mjpeg_param_sets), GFP_KERNEL);
266 if (ps == NULL)
267 return -ENOMEM;
268
269 ret = mjpeg_decode_extradata_ps(buf, size, ps);
270 if (ret) {
271 pr_err("parse extra data failed. err: %d\n", ret);
272 goto out;
273 }
274
275 if (ps->head_parsed)
276 fill_vdec_params(inst, &ps->dec_ps);
277
278 ret = ps->head_parsed ? 0 : -1;
279out:
280 kfree(ps);
281
282 return ret;
283}
284
285static int vdec_mjpeg_probe(unsigned long h_vdec,
286 struct aml_vcodec_mem *bs, void *out)
287{
288 struct vdec_mjpeg_inst *inst =
289 (struct vdec_mjpeg_inst *)h_vdec;
290 struct stream_info *st;
291 u8 *buf = (u8 *)bs->vaddr;
292 u32 size = bs->size;
293 int ret = 0;
294
295 st = (struct stream_info *)buf;
296 if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
297 return 0;
298
299 if (st->magic == NORe || st->magic == NORn)
300 ret = stream_parse(inst, st->data, st->length);
301 else
302 ret = stream_parse(inst, buf, size);
303
304 return ret;
305}
306
307static void vdec_mjpeg_deinit(unsigned long h_vdec)
308{
309 struct vdec_mjpeg_inst *inst = (struct vdec_mjpeg_inst *)h_vdec;
310
311 if (!inst)
312 return;
313
314 aml_vcodec_debug_enter(inst);
315
316 video_decoder_release(&inst->vdec);
317
318 vcodec_vfm_release(&inst->vfm);
319
320 //dump_deinit();
321
322 if (inst->vsi && inst->vsi->header_buf)
323 kfree(inst->vsi->header_buf);
324
325 if (inst->vsi)
326 kfree(inst->vsi);
327
328 kfree(inst);
329}
330
331static int vdec_mjpeg_get_fb(struct vdec_mjpeg_inst *inst, struct vdec_v4l2_buffer **out)
332{
333 return get_fb_from_queue(inst->ctx, out);
334}
335
336static void vdec_mjpeg_get_vf(struct vdec_mjpeg_inst *inst, struct vdec_v4l2_buffer **out)
337{
338 struct vframe_s *vf = NULL;
339 struct vdec_v4l2_buffer *fb = NULL;
340
341 vf = peek_video_frame(&inst->vfm);
342 if (!vf) {
343 aml_vcodec_debug(inst, "there is no vframe.");
344 *out = NULL;
345 return;
346 }
347
348 vf = get_video_frame(&inst->vfm);
349 if (!vf) {
350 aml_vcodec_debug(inst, "the vframe is avalid.");
351 *out = NULL;
352 return;
353 }
354
355 atomic_set(&vf->use_cnt, 1);
356
357 fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
358 fb->vf_handle = (unsigned long)vf;
359 fb->status = FB_ST_DISPLAY;
360
361 *out = fb;
362
363 //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used);
364 //dump_write(fb->base_y.va, fb->base_y.bytes_used);
365 //dump_write(fb->base_c.va, fb->base_c.bytes_used);
366
367 /* convert yuv format. */
368 //swap_uv(fb->base_c.va, fb->base_c.size);
369}
370
371static int vdec_write_nalu(struct vdec_mjpeg_inst *inst,
372 u8 *buf, u32 size, u64 ts)
373{
374 int ret = 0;
375 struct aml_vdec_adapt *vdec = &inst->vdec;
376
377 ret = vdec_vframe_write(vdec, buf, size, ts);
378
379 return ret;
380}
381
382static int vdec_mjpeg_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
383 u64 timestamp, bool *res_chg)
384{
385 struct vdec_mjpeg_inst *inst = (struct vdec_mjpeg_inst *)h_vdec;
386 struct aml_vdec_adapt *vdec = &inst->vdec;
387 struct stream_info *st;
388 u8 *buf;
389 u32 size;
390 int ret = 0;
391
392 /* bs NULL means flush decoder */
393 if (bs == NULL)
394 return 0;
395
396 buf = (u8 *)bs->vaddr;
397 size = bs->size;
398 st = (struct stream_info *)buf;
399
400 if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
401 ret = vdec_vbuf_write(vdec, st->m.buf, sizeof(st->m.drm));
402 else if (st->magic == NORe)
403 ret = vdec_vbuf_write(vdec, st->data, st->length);
404 else if (st->magic == NORn)
405 ret = vdec_write_nalu(inst, st->data, st->length, timestamp);
406 else if (inst->ctx->is_stream_mode)
407 ret = vdec_vbuf_write(vdec, buf, size);
408 else
409 ret = vdec_write_nalu(inst, buf, size, timestamp);
410
411 return ret;
412}
413
414static int vdec_mjpeg_get_param(unsigned long h_vdec,
415 enum vdec_get_param_type type, void *out)
416{
417 int ret = 0;
418 struct vdec_mjpeg_inst *inst = (struct vdec_mjpeg_inst *)h_vdec;
419
420 if (!inst) {
421 pr_err("the mjpeg inst of dec is invalid.\n");
422 return -1;
423 }
424
425 switch (type) {
426 case GET_PARAM_DISP_FRAME_BUFFER:
427 vdec_mjpeg_get_vf(inst, out);
428 break;
429
430 case GET_PARAM_FREE_FRAME_BUFFER:
431 ret = vdec_mjpeg_get_fb(inst, out);
432 break;
433
434 case GET_PARAM_PIC_INFO:
435 get_pic_info(inst, out);
436 break;
437
438 case GET_PARAM_DPB_SIZE:
439 get_dpb_size(inst, out);
440 break;
441
442 case GET_PARAM_CROP_INFO:
443 get_crop_info(inst, out);
444 break;
445
446 default:
447 aml_vcodec_err(inst, "invalid get parameter type=%d", type);
448 ret = -EINVAL;
449 }
450
451 return ret;
452}
453
454static void set_param_ps_info(struct vdec_mjpeg_inst *inst,
455 struct aml_vdec_ps_infos *ps)
456{
457 pr_info("---%s, %d\n", __func__, __LINE__);
458}
459
460static int vdec_mjpeg_set_param(unsigned long h_vdec,
461 enum vdec_set_param_type type, void *in)
462{
463 int ret = 0;
464 struct vdec_mjpeg_inst *inst = (struct vdec_mjpeg_inst *)h_vdec;
465
466 if (!inst) {
467 pr_err("the mjpeg inst of dec is invalid.\n");
468 return -1;
469 }
470
471 switch (type) {
472 case SET_PARAM_PS_INFO:
473 set_param_ps_info(inst, in);
474 break;
475
476 default:
477 aml_vcodec_err(inst, "invalid set parameter type=%d", type);
478 ret = -EINVAL;
479 }
480
481 return ret;
482}
483
484static struct vdec_common_if vdec_mjpeg_if = {
485 .init = vdec_mjpeg_init,
486 .probe = vdec_mjpeg_probe,
487 .decode = vdec_mjpeg_decode,
488 .get_param = vdec_mjpeg_get_param,
489 .set_param = vdec_mjpeg_set_param,
490 .deinit = vdec_mjpeg_deinit,
491};
492
493struct vdec_common_if *get_mjpeg_dec_comm_if(void);
494
495struct vdec_common_if *get_mjpeg_dec_comm_if(void)
496{
497 return &vdec_mjpeg_if;
498}
499