summaryrefslogtreecommitdiff
path: root/drivers/stream_input/amports/amstream.c (plain)
blob: 8c9ef119cfad898a8e64dffc7c1689bc4688709b
1/*
2 * drivers/amlogic/media/stream_input/amports/amstream.c
3 *
4 * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 */
17#define DEBUG
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/types.h>
21#include <linux/fs.h>
22#include <linux/init.h>
23#include <linux/device.h>
24#include <linux/slab.h>
25#include <linux/vmalloc.h>
26#include <linux/mm.h>
27#include <linux/amlogic/major.h>
28#include <linux/sched.h>
29#include <linux/interrupt.h>
30#include <linux/delay.h>
31#include <linux/kthread.h>
32
33#include <linux/amlogic/media/utils/amstream.h>
34#include <linux/amlogic/media/utils/vformat.h>
35#include <linux/amlogic/media/utils/aformat.h>
36
37#include <linux/amlogic/media/frame_sync/tsync.h>
38#include <linux/amlogic/media/frame_sync/ptsserv.h>
39#include <linux/amlogic/media/frame_sync/timestamp.h>
40
41#include <linux/types.h>
42#include <linux/uaccess.h>
43#include <linux/io.h>
44/* #include <mach/am_regs.h> */
45
46#include <linux/platform_device.h>
47#include <linux/mutex.h>
48#include <linux/poll.h>
49#include <linux/dma-mapping.h>
50#include <linux/dma-contiguous.h>
51#include <linux/uaccess.h>
52#include <linux/clk.h>
53#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
54/* #include <mach/mod_gate.h> */
55/* #include <mach/power_gate.h> */
56#endif
57#include "../parser/streambuf.h"
58#include "../parser/streambuf_reg.h"
59#include "../parser/tsdemux.h"
60#include "../parser/psparser.h"
61#include "../parser/esparser.h"
62#include "../../frame_provider/decoder/utils/vdec.h"
63#include "adec.h"
64#include "../parser/rmparser.h"
65#include "amports_priv.h"
66#include <linux/amlogic/media/utils/amports_config.h>
67#include <linux/amlogic/media/frame_sync/tsync_pcr.h>
68#include "../parser/thread_rw.h"
69#include <linux/firmware.h>
70#include <linux/of.h>
71#include <linux/of_fdt.h>
72#include <linux/libfdt_env.h>
73#include <linux/of_reserved_mem.h>
74#include <linux/reset.h>
75#ifdef CONFIG_COMPAT
76#include <linux/compat.h>
77#endif
78#include <linux/amlogic/media/codec_mm/codec_mm.h>
79#include <linux/amlogic/media/codec_mm/configs.h>
80#include "../../frame_provider/decoder/utils/firmware.h"
81#include "../../common/chips/chips.h"
82#include "../../common/chips/decoder_cpu_ver_info.h"
83#include "../subtitle/subtitle.h"
84
85//#define G12A_BRINGUP_DEBUG
86
87#define CONFIG_AM_VDEC_REAL //DEBUG_TMP
88
89#define DEVICE_NAME "amstream-dev"
90#define DRIVER_NAME "amstream"
91#define MODULE_NAME "amstream"
92
93#define MAX_AMSTREAM_PORT_NUM ARRAY_SIZE(ports)
94u32 amstream_port_num;
95u32 amstream_buf_num;
96
97u32 amstream_audio_reset = 0;
98
99#if 0
100#if MESON_CPU_TYPE == MESON_CPU_TYPE_MESONG9TV
101#define NO_VDEC2_INIT 1
102#elif MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD
103#define NO_VDEC2_INIT IS_MESON_M8M2_CPU
104#endif
105#endif
106#define NO_VDEC2_INIT 1
107
108#define DEFAULT_VIDEO_BUFFER_SIZE (1024 * 1024 * 3)
109#define DEFAULT_VIDEO_BUFFER_SIZE_4K (1024 * 1024 * 6)
110#define DEFAULT_VIDEO_BUFFER_SIZE_TVP (1024 * 1024 * 10)
111#define DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP (1024 * 1024 * 15)
112
113
114#define DEFAULT_AUDIO_BUFFER_SIZE (1024*768*2)
115#define DEFAULT_SUBTITLE_BUFFER_SIZE (1024*256)
116
117static int def_4k_vstreambuf_sizeM =
118 (DEFAULT_VIDEO_BUFFER_SIZE_4K >> 20);
119static int def_vstreambuf_sizeM =
120 (DEFAULT_VIDEO_BUFFER_SIZE >> 20);
121static int slow_input;
122
123
124
125
126/* #define DATA_DEBUG */
127static int use_bufferlevelx10000 = 10000;
128static int reset_canuse_buferlevel(int level);
129static struct platform_device *amstream_pdev;
130struct device *amports_get_dma_device(void)
131{
132 return &amstream_pdev->dev;
133}
134EXPORT_SYMBOL(amports_get_dma_device);
135
136#ifdef DATA_DEBUG
137#include <linux/fs.h>
138
139#define DEBUG_FILE_NAME "/sdcard/debug.tmp"
140static struct file *debug_filp;
141static loff_t debug_file_pos;
142
143void debug_file_write(const char __user *buf, size_t count)
144{
145 mm_segment_t old_fs;
146
147 if (!debug_filp)
148 return;
149
150 old_fs = get_fs();
151 set_fs(KERNEL_DS);
152
153 if (count != vfs_write(debug_filp, buf, count, &debug_file_pos))
154 pr_err("Failed to write debug file\n");
155
156 set_fs(old_fs);
157}
158#endif
159
160
161
162static int amstream_open(struct inode *inode, struct file *file);
163static int amstream_release(struct inode *inode, struct file *file);
164static long amstream_ioctl(struct file *file, unsigned int cmd, ulong arg);
165#ifdef CONFIG_COMPAT
166static long amstream_compat_ioctl
167 (struct file *file, unsigned int cmd, ulong arg);
168#endif
169static ssize_t amstream_vbuf_write
170(struct file *file, const char *buf, size_t count, loff_t *ppos);
171static ssize_t amstream_vframe_write
172(struct file *file, const char *buf, size_t count, loff_t *ppos);
173static ssize_t amstream_abuf_write
174(struct file *file, const char *buf, size_t count, loff_t *ppos);
175static ssize_t amstream_mpts_write
176(struct file *file, const char *buf, size_t count, loff_t *ppos);
177static ssize_t amstream_mpps_write
178(struct file *file, const char *buf, size_t count, loff_t *ppos);
179static ssize_t amstream_sub_read
180(struct file *file, char *buf, size_t count, loff_t *ppos);
181static ssize_t amstream_sub_write
182(struct file *file, const char *buf, size_t count, loff_t *ppos);
183static unsigned int amstream_sub_poll
184(struct file *file, poll_table *wait_table);
185static unsigned int amstream_userdata_poll
186(struct file *file, poll_table *wait_table);
187static ssize_t amstream_userdata_read
188(struct file *file, char *buf, size_t count, loff_t *ppos);
189static int (*amstream_adec_status)
190(struct adec_status *astatus);
191#ifdef CONFIG_AM_VDEC_REAL
192static ssize_t amstream_mprm_write
193(struct file *file, const char *buf, size_t count, loff_t *ppos);
194#endif
195
196static const struct file_operations vbuf_fops = {
197 .owner = THIS_MODULE,
198 .open = amstream_open,
199 .release = amstream_release,
200 .write = amstream_vbuf_write,
201 .unlocked_ioctl = amstream_ioctl,
202#ifdef CONFIG_COMPAT
203 .compat_ioctl = amstream_compat_ioctl,
204#endif
205};
206
207static const struct file_operations vframe_fops = {
208 .owner = THIS_MODULE,
209 .open = amstream_open,
210 .release = amstream_release,
211 .write = amstream_vframe_write,
212 .unlocked_ioctl = amstream_ioctl,
213#ifdef CONFIG_COMPAT
214 .compat_ioctl = amstream_compat_ioctl,
215#endif
216};
217
218static const struct file_operations abuf_fops = {
219 .owner = THIS_MODULE,
220 .open = amstream_open,
221 .release = amstream_release,
222 .write = amstream_abuf_write,
223 .unlocked_ioctl = amstream_ioctl,
224#ifdef CONFIG_COMPAT
225 .compat_ioctl = amstream_compat_ioctl,
226#endif
227};
228
229static const struct file_operations mpts_fops = {
230 .owner = THIS_MODULE,
231 .open = amstream_open,
232 .release = amstream_release,
233 .write = amstream_mpts_write,
234 .unlocked_ioctl = amstream_ioctl,
235#ifdef CONFIG_COMPAT
236 .compat_ioctl = amstream_compat_ioctl,
237#endif
238};
239
240static const struct file_operations mpps_fops = {
241 .owner = THIS_MODULE,
242 .open = amstream_open,
243 .release = amstream_release,
244 .write = amstream_mpps_write,
245 .unlocked_ioctl = amstream_ioctl,
246#ifdef CONFIG_COMPAT
247 .compat_ioctl = amstream_compat_ioctl,
248#endif
249};
250
251static const struct file_operations mprm_fops = {
252 .owner = THIS_MODULE,
253 .open = amstream_open,
254 .release = amstream_release,
255#ifdef CONFIG_AM_VDEC_REAL
256 .write = amstream_mprm_write,
257#endif
258 .unlocked_ioctl = amstream_ioctl,
259#ifdef CONFIG_COMPAT
260 .compat_ioctl = amstream_compat_ioctl,
261#endif
262};
263
264static const struct file_operations sub_fops = {
265 .owner = THIS_MODULE,
266 .open = amstream_open,
267 .release = amstream_release,
268 .write = amstream_sub_write,
269 .unlocked_ioctl = amstream_ioctl,
270#ifdef CONFIG_COMPAT
271 .compat_ioctl = amstream_compat_ioctl,
272#endif
273};
274
275static const struct file_operations sub_read_fops = {
276 .owner = THIS_MODULE,
277 .open = amstream_open,
278 .release = amstream_release,
279 .read = amstream_sub_read,
280 .poll = amstream_sub_poll,
281 .unlocked_ioctl = amstream_ioctl,
282#ifdef CONFIG_COMPAT
283 .compat_ioctl = amstream_compat_ioctl,
284#endif
285};
286
287static const struct file_operations userdata_fops = {
288 .owner = THIS_MODULE,
289 .open = amstream_open,
290 .release = amstream_release,
291 .read = amstream_userdata_read,
292 .poll = amstream_userdata_poll,
293 .unlocked_ioctl = amstream_ioctl,
294#ifdef CONFIG_COMPAT
295 .compat_ioctl = amstream_compat_ioctl,
296#endif
297};
298
299static const struct file_operations amstream_fops = {
300 .owner = THIS_MODULE,
301 .open = amstream_open,
302 .release = amstream_release,
303 .unlocked_ioctl = amstream_ioctl,
304#ifdef CONFIG_COMPAT
305 .compat_ioctl = amstream_compat_ioctl,
306#endif
307};
308
309/**************************************************/
310static struct audio_info audio_dec_info;
311static struct class *amstream_dev_class;
312static DEFINE_MUTEX(amstream_mutex);
313
314atomic_t subdata_ready = ATOMIC_INIT(0);
315static int sub_type;
316static int sub_port_inited;
317/* wait queue for poll */
318static wait_queue_head_t amstream_sub_wait;
319atomic_t userdata_ready = ATOMIC_INIT(0);
320static int userdata_length;
321static wait_queue_head_t amstream_userdata_wait;
322#define USERDATA_FIFO_NUM 1024
323static struct userdata_poc_info_t userdata_poc_info[USERDATA_FIFO_NUM];
324static int userdata_poc_ri, userdata_poc_wi;
325static int last_read_wi;
326static u32 ud_ready_vdec_flag;
327
328
329
330static DEFINE_MUTEX(userdata_mutex);
331
332static struct stream_port_s ports[] = {
333 {
334 .name = "amstream_vbuf",
335 .type = PORT_TYPE_ES | PORT_TYPE_VIDEO,
336 .fops = &vbuf_fops,
337 },
338#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
339 {
340 .name = "amstream_vbuf_sched",
341 .type = PORT_TYPE_ES | PORT_TYPE_VIDEO |
342 PORT_TYPE_DECODER_SCHED,
343 .fops = &vbuf_fops,
344 },
345 {
346 .name = "amstream_vframe",
347 .type = PORT_TYPE_ES | PORT_TYPE_VIDEO |
348 PORT_TYPE_FRAME | PORT_TYPE_DECODER_SCHED,
349 .fops = &vframe_fops,
350 },
351#endif
352 {
353 .name = "amstream_abuf",
354 .type = PORT_TYPE_ES | PORT_TYPE_AUDIO,
355 .fops = &abuf_fops,
356 },
357 {
358 .name = "amstream_mpts",
359 .type = PORT_TYPE_MPTS | PORT_TYPE_VIDEO |
360 PORT_TYPE_AUDIO | PORT_TYPE_SUB,
361 .fops = &mpts_fops,
362 },
363#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
364 {
365 .name = "amstream_mpts_sched",
366 .type = PORT_TYPE_MPTS | PORT_TYPE_VIDEO |
367 PORT_TYPE_AUDIO | PORT_TYPE_SUB |
368 PORT_TYPE_DECODER_SCHED,
369 .fops = &mpts_fops,
370 },
371#endif
372 {
373 .name = "amstream_mpps",
374 .type = PORT_TYPE_MPPS | PORT_TYPE_VIDEO |
375 PORT_TYPE_AUDIO | PORT_TYPE_SUB,
376 .fops = &mpps_fops,
377 },
378 {
379 .name = "amstream_rm",
380 .type = PORT_TYPE_RM | PORT_TYPE_VIDEO | PORT_TYPE_AUDIO,
381 .fops = &mprm_fops,
382 },
383 {
384 .name = "amstream_sub",
385 .type = PORT_TYPE_SUB,
386 .fops = &sub_fops,
387 },
388 {
389 .name = "amstream_sub_read",
390 .type = PORT_TYPE_SUB_RD,
391 .fops = &sub_read_fops,
392 },
393 {
394 .name = "amstream_userdata",
395 .type = PORT_TYPE_USERDATA,
396 .fops = &userdata_fops,
397 },
398 {
399 .name = "amstream_hevc",
400 .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | PORT_TYPE_HEVC,
401 .fops = &vbuf_fops,
402 .vformat = VFORMAT_HEVC,
403 },
404#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
405 {
406 .name = "amstream_hevc_frame",
407 .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | PORT_TYPE_HEVC |
408 PORT_TYPE_FRAME | PORT_TYPE_DECODER_SCHED,
409 .fops = &vframe_fops,
410 .vformat = VFORMAT_HEVC,
411 },
412 {
413 .name = "amstream_hevc_sched",
414 .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | PORT_TYPE_HEVC |
415 PORT_TYPE_DECODER_SCHED,
416 .fops = &vbuf_fops,
417 .vformat = VFORMAT_HEVC,
418 },
419#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
420 {
421 .name = "amstream_dves_avc",
422 .type = PORT_TYPE_ES | PORT_TYPE_VIDEO |
423 PORT_TYPE_DECODER_SCHED | PORT_TYPE_DUALDEC,
424 .fops = &vbuf_fops,
425 },
426 {
427 .name = "amstream_dves_hevc",
428 .type = PORT_TYPE_ES | PORT_TYPE_VIDEO | PORT_TYPE_HEVC |
429 PORT_TYPE_DECODER_SCHED | PORT_TYPE_DUALDEC,
430 .fops = &vbuf_fops,
431 .vformat = VFORMAT_HEVC,
432 },
433#endif
434#endif
435};
436
437static struct stream_buf_s bufs[BUF_MAX_NUM] = {
438 {
439 .reg_base = VLD_MEM_VIFIFO_REG_BASE,
440 .type = BUF_TYPE_VIDEO,
441 .buf_start = 0,
442 .buf_size = DEFAULT_VIDEO_BUFFER_SIZE,
443 .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE,
444 .first_tstamp = INVALID_PTS
445 },
446 {
447 .reg_base = AIU_MEM_AIFIFO_REG_BASE,
448 .type = BUF_TYPE_AUDIO,
449 .buf_start = 0,
450 .buf_size = DEFAULT_AUDIO_BUFFER_SIZE,
451 .default_buf_size = DEFAULT_AUDIO_BUFFER_SIZE,
452 .first_tstamp = INVALID_PTS
453 },
454 {
455 .reg_base = 0,
456 .type = BUF_TYPE_SUBTITLE,
457 .buf_start = 0,
458 .buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE,
459 .default_buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE,
460 .first_tstamp = INVALID_PTS
461 },
462 {
463 .reg_base = 0,
464 .type = BUF_TYPE_USERDATA,
465 .buf_start = 0,
466 .buf_size = 0,
467 .first_tstamp = INVALID_PTS
468 },
469 {
470 .reg_base = HEVC_STREAM_REG_BASE,
471 .type = BUF_TYPE_HEVC,
472 .buf_start = 0,
473 .buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K,
474 .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K,
475 .first_tstamp = INVALID_PTS
476 },
477};
478
479struct stream_buf_s *get_buf_by_type(u32 type)
480{
481 if (PTS_TYPE_VIDEO == type)
482 return &bufs[BUF_TYPE_VIDEO];
483 if (PTS_TYPE_AUDIO == type)
484 return &bufs[BUF_TYPE_AUDIO];
485 if (has_hevc_vdec()) {
486 if (PTS_TYPE_HEVC == type)
487 return &bufs[BUF_TYPE_HEVC];
488 }
489
490 return NULL;
491}
492
493void set_sample_rate_info(int arg)
494{
495 audio_dec_info.sample_rate = arg;
496 audio_dec_info.valid = 1;
497}
498
499void set_ch_num_info(int arg)
500{
501 audio_dec_info.channels = arg;
502}
503
504struct audio_info *get_audio_info(void)
505{
506 return &audio_dec_info;
507}
508EXPORT_SYMBOL(get_audio_info);
509
510static void amstream_change_vbufsize(struct port_priv_s *priv,
511 struct stream_buf_s *pvbuf)
512{
513 if (pvbuf->buf_start != 0) {
514 pr_info("streambuf is alloced before\n");
515 return;
516 }
517 if (pvbuf->for_4k) {
518 pvbuf->buf_size = def_4k_vstreambuf_sizeM * SZ_1M;
519 if (priv->vdec->port_flag & PORT_FLAG_DRM)
520 pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP;
521 if ((pvbuf->buf_size > 30 * SZ_1M) &&
522 (codec_mm_get_total_size() < 220 * SZ_1M)) {
523 /*if less than 250M, used 20M for 4K & 265*/
524 pvbuf->buf_size = pvbuf->buf_size >> 1;
525 }
526 } else if (pvbuf->buf_size > def_vstreambuf_sizeM * SZ_1M) {
527 if (priv->vdec->port_flag & PORT_FLAG_DRM)
528 pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_TVP;
529 } else {
530 pvbuf->buf_size = def_vstreambuf_sizeM * SZ_1M;
531 if (priv->vdec->port_flag & PORT_FLAG_DRM)
532 pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_TVP;
533 }
534 reset_canuse_buferlevel(10000);
535}
536
537static bool port_get_inited(struct port_priv_s *priv)
538{
539 struct stream_port_s *port = priv->port;
540
541 if (port->type & PORT_TYPE_VIDEO) {
542 struct vdec_s *vdec = priv->vdec;
543
544 return vdec->port_flag & PORT_FLAG_INITED;
545 }
546
547 return port->flag & PORT_FLAG_INITED;
548}
549
550static void port_set_inited(struct port_priv_s *priv)
551{
552 struct stream_port_s *port = priv->port;
553
554 if (port->type & PORT_TYPE_VIDEO) {
555 struct vdec_s *vdec = priv->vdec;
556
557 vdec->port_flag |= PORT_FLAG_INITED;
558 } else
559 port->flag |= PORT_FLAG_INITED;
560}
561
562static void video_port_release(struct port_priv_s *priv,
563 struct stream_buf_s *pbuf, int release_num)
564{
565 struct stream_port_s *port = priv->port;
566 struct vdec_s *vdec = priv->vdec;
567 struct vdec_s *slave = NULL;
568 bool is_multidec = !vdec_single(vdec);
569
570 switch (release_num) {
571 default:
572 /*fallthrough*/
573 case 0: /*release all */
574 /*fallthrough*/
575 case 4:
576 if ((port->type & PORT_TYPE_FRAME) == 0)
577 esparser_release(pbuf);
578 /*fallthrough*/
579 case 3:
580 if (vdec->slave)
581 slave = vdec->slave;
582 vdec_release(vdec);
583 if (slave)
584 vdec_release(slave);
585 priv->vdec = NULL;
586 /*fallthrough*/
587 case 2:
588 if ((port->type & PORT_TYPE_FRAME) == 0)
589 stbuf_release(pbuf, is_multidec);
590 /*fallthrough*/
591 case 1:
592 ;
593 }
594}
595
596static int video_port_init(struct port_priv_s *priv,
597 struct stream_buf_s *pbuf)
598{
599 int r;
600 struct stream_port_s *port = priv->port;
601 struct vdec_s *vdec = priv->vdec;
602
603 if ((vdec->port_flag & PORT_FLAG_VFORMAT) == 0) {
604 pr_err("vformat not set\n");
605 return -EPERM;
606 }
607 if (vdec_dual(vdec) && vdec_secure(vdec)) {
608 /*copy drm flags for slave dec.*/
609 vdec->slave->port_flag |= PORT_FLAG_DRM;
610 }
611 if (port->vformat == VFORMAT_H264_4K2K ||
612 (priv->vdec->sys_info->height *
613 priv->vdec->sys_info->width) > 1920*1088) {
614 pbuf->for_4k = 1;
615 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX
616 && port->vformat == VFORMAT_H264) {
617 vdec_poweron(VDEC_HEVC);
618 }
619 } else {
620 pbuf->for_4k = 0;
621 }
622
623 if (port->type & PORT_TYPE_FRAME) {
624 r = vdec_init(vdec,
625 (priv->vdec->sys_info->height *
626 priv->vdec->sys_info->width) > 1920*1088);
627 if (r < 0) {
628 pr_err("video_port_init %d, vdec_init failed\n",
629 __LINE__);
630 video_port_release(priv, pbuf, 2);
631 return r;
632 }
633
634 return 0;
635 }
636
637 amstream_change_vbufsize(priv, pbuf);
638
639 if (has_hevc_vdec()) {
640 if (port->type & PORT_TYPE_MPTS) {
641 if (pbuf->type == BUF_TYPE_HEVC)
642 vdec_poweroff(VDEC_1);
643 else
644 vdec_poweroff(VDEC_HEVC);
645 }
646 }
647
648 r = stbuf_init(pbuf, vdec, false);
649 if (r < 0) {
650 pr_err("video_port_init %d, stbuf_init failed\n", __LINE__);
651 return r;
652 }
653
654 /* todo: set path based on port flag */
655 r = vdec_init(vdec,
656 (priv->vdec->sys_info->height *
657 priv->vdec->sys_info->width) > 1920*1088);
658
659 if (r < 0) {
660 pr_err("video_port_init %d, vdec_init failed\n", __LINE__);
661 video_port_release(priv, pbuf, 2);
662 return r;
663 }
664
665 if (vdec_dual(vdec)) {
666 r = vdec_init(vdec->slave,
667 (priv->vdec->sys_info->height *
668 priv->vdec->sys_info->width) > 1920*1088);
669 if (r < 0) {
670 pr_err("video_port_init %d, vdec_init failed\n",
671 __LINE__);
672 video_port_release(priv, pbuf, 2);
673 return r;
674 }
675 }
676
677 if (port->type & PORT_TYPE_ES) {
678 r = esparser_init(pbuf, vdec);
679 if (r < 0) {
680 video_port_release(priv, pbuf, 3);
681 pr_err("esparser_init() failed\n");
682 return r;
683 }
684 }
685
686 pbuf->flag |= BUF_FLAG_IN_USE;
687
688 return 0;
689}
690
691static void audio_port_release(struct stream_port_s *port,
692 struct stream_buf_s *pbuf, int release_num)
693{
694 switch (release_num) {
695 default:
696 /*fallthrough*/
697 case 0: /*release all */
698 /*fallthrough*/
699 case 4:
700 esparser_release(pbuf);
701 /*fallthrough*/
702 case 3:
703 adec_release(port->vformat);
704 /*fallthrough*/
705 case 2:
706 stbuf_release(pbuf, false);
707 /*fallthrough*/
708 case 1:
709 ;
710 }
711 amstream_audio_reset = 0;
712 return;
713}
714
715static int audio_port_reset(struct stream_port_s *port,
716 struct stream_buf_s *pbuf)
717{
718 int r;
719
720 if ((port->flag & PORT_FLAG_AFORMAT) == 0) {
721 pr_err("aformat not set\n");
722 return 0;
723 }
724
725 pts_stop(PTS_TYPE_AUDIO);
726
727 stbuf_release(pbuf, false);
728
729 r = stbuf_init(pbuf, NULL, false);
730 if (r < 0)
731 return r;
732
733 r = adec_init(port);
734 if (r < 0) {
735 audio_port_release(port, pbuf, 2);
736 return r;
737 }
738
739 if (port->type & PORT_TYPE_ES)
740 esparser_audio_reset_s(pbuf);
741
742 if (port->type & PORT_TYPE_MPTS)
743 tsdemux_audio_reset();
744
745 if (port->type & PORT_TYPE_MPPS)
746 psparser_audio_reset();
747
748#ifdef CONFIG_AM_VDEC_REAL
749 if (port->type & PORT_TYPE_RM)
750 rm_audio_reset();
751#endif
752
753 pbuf->flag |= BUF_FLAG_IN_USE;
754 amstream_audio_reset = 1;
755
756 r = pts_start(PTS_TYPE_AUDIO);
757
758 return r;
759}
760
761static int sub_port_reset(struct stream_port_s *port,
762 struct stream_buf_s *pbuf)
763{
764 int r;
765
766 port->flag &= (~PORT_FLAG_INITED);
767
768 stbuf_release(pbuf, false);
769
770 r = stbuf_init(pbuf, NULL, false);
771 if (r < 0)
772 return r;
773
774 if (port->type & PORT_TYPE_MPTS)
775 tsdemux_sub_reset();
776
777 if (port->type & PORT_TYPE_MPPS)
778 psparser_sub_reset();
779
780 if (port->sid == 0xffff) { /* es sub */
781 esparser_sub_reset();
782 pbuf->flag |= BUF_FLAG_PARSER;
783 }
784
785 pbuf->flag |= BUF_FLAG_IN_USE;
786
787 port->flag |= PORT_FLAG_INITED;
788
789 return 0;
790}
791
792static int audio_port_init(struct stream_port_s *port,
793 struct stream_buf_s *pbuf)
794{
795 int r;
796
797 if ((port->flag & PORT_FLAG_AFORMAT) == 0) {
798 pr_err("aformat not set\n");
799 return 0;
800 }
801
802 r = stbuf_init(pbuf, NULL, false);
803 if (r < 0)
804 return r;
805 r = adec_init(port);
806 if (r < 0) {
807 audio_port_release(port, pbuf, 2);
808 return r;
809 }
810 if (port->type & PORT_TYPE_ES) {
811 r = esparser_init(pbuf, NULL);
812 if (r < 0) {
813 audio_port_release(port, pbuf, 3);
814 return r;
815 }
816 }
817 pbuf->flag |= BUF_FLAG_IN_USE;
818 return 0;
819}
820
821static void sub_port_release(struct stream_port_s *port,
822 struct stream_buf_s *pbuf)
823{
824 if ((port->sid == 0xffff) &&
825 ((port->type & (PORT_TYPE_MPPS | PORT_TYPE_MPTS)) == 0)) {
826 /* this is es sub */
827 esparser_release(pbuf);
828 }
829 stbuf_release(pbuf, false);
830 sub_port_inited = 0;
831}
832
833static int sub_port_init(struct stream_port_s *port, struct stream_buf_s *pbuf)
834{
835 int r;
836 r = stbuf_init(pbuf, NULL, false);
837 if (r < 0)
838 return r;
839 if ((port->flag & PORT_FLAG_SID) == 0) {
840 pr_err("subtitle id not set\n");
841 return 0;
842 }
843
844 if ((port->sid == 0xffff) &&
845 ((port->type & (PORT_TYPE_MPPS | PORT_TYPE_MPTS)) == 0)) {
846 /* es sub */
847 r = esparser_init(pbuf, NULL);
848 if (r < 0) {
849 sub_port_release(port, pbuf);
850 return r;
851 }
852 }
853
854 sub_port_inited = 1;
855 return 0;
856}
857
858static void amstream_user_buffer_init(void)
859{
860 struct stream_buf_s *pubuf = &bufs[BUF_TYPE_USERDATA];
861
862 pubuf->buf_size = 0;
863 pubuf->buf_start = 0;
864 pubuf->buf_wp = 0;
865 pubuf->buf_rp = 0;
866}
867
868static int amstream_port_init(struct port_priv_s *priv)
869{
870 int r = 0;
871 struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO];
872 struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO];
873 struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE];
874 struct stream_port_s *port = priv->port;
875 struct vdec_s *vdec = priv->vdec;
876
877 mutex_lock(&amstream_mutex);
878
879 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A) {
880 r = check_efuse_chip(port->vformat);
881 if (r) {
882 pr_info("No support video format %d.\n", port->vformat);
883 mutex_unlock(&amstream_mutex);
884 return 0;
885 }
886 }
887
888 /* try to reload the fw.*/
889 r = video_fw_reload(FW_LOAD_TRY);
890 if (r)
891 pr_err("the firmware reload fail.\n");
892
893 stbuf_fetch_init();
894
895 amstream_user_buffer_init();
896
897 if (port_get_inited(priv)) {
898 mutex_unlock(&amstream_mutex);
899 return 0;
900 }
901
902 if ((port->type & PORT_TYPE_AUDIO) &&
903 (port->flag & PORT_FLAG_AFORMAT)) {
904 r = audio_port_init(port, pabuf);
905 if (r < 0) {
906 pr_err("audio_port_init failed\n");
907 goto error1;
908 }
909 }
910
911 if ((port->type & PORT_TYPE_VIDEO) &&
912 (vdec->port_flag & PORT_FLAG_VFORMAT)) {
913 pvbuf->for_4k = 0;
914 if (has_hevc_vdec()) {
915 if (port->vformat == VFORMAT_HEVC ||
916 port->vformat == VFORMAT_AVS2 ||
917 port->vformat == VFORMAT_VP9)
918 pvbuf = &bufs[BUF_TYPE_HEVC];
919 }
920 mutex_lock(&priv->mutex);
921 r = video_port_init(priv, pvbuf);
922 if (r < 0) {
923 mutex_unlock(&priv->mutex);
924 pr_err("video_port_init failed\n");
925 goto error2;
926 }
927 mutex_unlock(&priv->mutex);
928 }
929
930 if ((port->type & PORT_TYPE_SUB) && (port->flag & PORT_FLAG_SID)) {
931 r = sub_port_init(port, psbuf);
932 if (r < 0) {
933 pr_err("sub_port_init failed\n");
934 goto error3;
935 }
936 }
937
938 if (port->type & PORT_TYPE_MPTS) {
939 if (has_hevc_vdec()) {
940 r = tsdemux_init(
941 (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff,
942 (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff,
943 (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff,
944 (port->pcr_inited == 1) ? port->pcrid : 0xffff,
945 (port->vformat == VFORMAT_HEVC) ||
946 (port->vformat == VFORMAT_AVS2) ||
947 (port->vformat == VFORMAT_VP9),
948 vdec);
949 } else {
950 r = tsdemux_init(
951 (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff,
952 (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff,
953 (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff,
954 (port->pcr_inited == 1) ? port->pcrid : 0xffff,
955 0,
956 vdec);
957 }
958
959 if (r < 0) {
960 pr_err("tsdemux_init failed\n");
961 goto error4;
962 }
963 tsync_pcr_start();
964 }
965 if (port->type & PORT_TYPE_MPPS) {
966 r = psparser_init(
967 (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff,
968 (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff,
969 (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff,
970 priv->vdec);
971 if (r < 0) {
972 pr_err("psparser_init failed\n");
973 goto error5;
974 }
975 }
976#ifdef CONFIG_AM_VDEC_REAL
977 if (port->type & PORT_TYPE_RM) {
978 rm_set_vasid(
979 (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff,
980 (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff);
981 }
982#endif
983#if 1 /* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */
984 if (!NO_VDEC2_INIT) {
985 if ((port->type & PORT_TYPE_VIDEO)
986 && (port->vformat == VFORMAT_H264_4K2K))
987 stbuf_vdec2_init(pvbuf);
988 }
989#endif
990
991 if ((port->type & PORT_TYPE_VIDEO) &&
992 (vdec->port_flag & PORT_FLAG_VFORMAT))
993 /* connect vdec at the end after all HW initialization */
994 vdec_connect(vdec);
995
996 tsync_audio_break(0); /* clear audio break */
997 set_vsync_pts_inc_mode(0); /* clear video inc */
998
999 port_set_inited(priv);
1000
1001 mutex_unlock(&amstream_mutex);
1002 return 0;
1003 /*errors follow here */
1004error5:
1005 tsdemux_release();
1006error4:
1007 sub_port_release(port, psbuf);
1008error3:
1009 video_port_release(priv, pvbuf, 0);
1010error2:
1011 audio_port_release(port, pabuf, 0);
1012error1:
1013 mutex_unlock(&amstream_mutex);
1014 return r;
1015}
1016
1017static int amstream_port_release(struct port_priv_s *priv)
1018{
1019 struct stream_port_s *port = priv->port;
1020 struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO];
1021 struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO];
1022 struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE];
1023
1024 if (has_hevc_vdec()) {
1025 if (port->vformat == VFORMAT_HEVC
1026 || port->vformat == VFORMAT_AVS2
1027 || port->vformat == VFORMAT_VP9)
1028 pvbuf = &bufs[BUF_TYPE_HEVC];
1029 }
1030
1031 if (port->type & PORT_TYPE_MPTS) {
1032 vdec_disconnect(priv->vdec);
1033 tsync_pcr_stop();
1034 tsdemux_release();
1035 }
1036
1037 if (port->type & PORT_TYPE_MPPS)
1038 psparser_release();
1039
1040 if (port->type & PORT_TYPE_VIDEO)
1041 video_port_release(priv, pvbuf, 0);
1042
1043 if (port->type & PORT_TYPE_AUDIO)
1044 audio_port_release(port, pabuf, 0);
1045
1046 if (port->type & PORT_TYPE_SUB)
1047 sub_port_release(port, psbuf);
1048
1049 port->pcr_inited = 0;
1050 port->flag = 0;
1051 return 0;
1052}
1053
1054static void amstream_change_avid(struct stream_port_s *port)
1055{
1056 if (port->type & PORT_TYPE_MPTS) {
1057 tsdemux_change_avid(
1058 (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff,
1059 (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff);
1060 }
1061
1062 if (port->type & PORT_TYPE_MPPS) {
1063 psparser_change_avid(
1064 (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff,
1065 (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff);
1066 }
1067
1068#ifdef CONFIG_AM_VDEC_REAL
1069 if (port->type & PORT_TYPE_RM) {
1070 rm_set_vasid(
1071 (port->flag & PORT_FLAG_VID) ? port->vid : 0xffff,
1072 (port->flag & PORT_FLAG_AID) ? port->aid : 0xffff);
1073 }
1074#endif
1075}
1076
1077static void amstream_change_sid(struct stream_port_s *port)
1078{
1079 if (port->type & PORT_TYPE_MPTS) {
1080 tsdemux_change_sid(
1081 (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff);
1082 }
1083
1084 if (port->type & PORT_TYPE_MPPS) {
1085 psparser_change_sid(
1086 (port->flag & PORT_FLAG_SID) ? port->sid : 0xffff);
1087 }
1088}
1089
1090/**************************************************/
1091static ssize_t amstream_vbuf_write(struct file *file, const char *buf,
1092 size_t count, loff_t *ppos)
1093{
1094 struct port_priv_s *priv = (struct port_priv_s *)file->private_data;
1095 struct stream_port_s *port = priv->port;
1096 struct stream_buf_s *pbuf = NULL;
1097 int r;
1098 if (has_hevc_vdec()) {
1099 pbuf = (port->type & PORT_TYPE_HEVC) ? &bufs[BUF_TYPE_HEVC] :
1100 &bufs[BUF_TYPE_VIDEO];
1101 } else
1102 pbuf = &bufs[BUF_TYPE_VIDEO];
1103
1104 if (!(port_get_inited(priv))) {
1105 r = amstream_port_init(priv);
1106 if (r < 0)
1107 return r;
1108 }
1109
1110 if (priv->vdec->port_flag & PORT_FLAG_DRM)
1111 r = drm_write(file, pbuf, buf, count);
1112 else
1113 r = esparser_write(file, pbuf, buf, count);
1114 if (slow_input) {
1115 pr_info("slow_input: es codec write size %x\n", r);
1116 msleep(3000);
1117 }
1118#ifdef DATA_DEBUG
1119 debug_file_write(buf, r);
1120#endif
1121
1122 return r;
1123}
1124
1125static ssize_t amstream_vframe_write(struct file *file, const char *buf,
1126 size_t count, loff_t *ppos)
1127{
1128 struct port_priv_s *priv = (struct port_priv_s *)file->private_data;
1129 ssize_t ret;
1130 int wait_max_cnt = 5;
1131#ifdef DATA_DEBUG
1132 debug_file_write(buf, count);
1133#endif
1134 do {
1135 ret = vdec_write_vframe(priv->vdec, buf, count);
1136 if (file->f_flags & O_NONBLOCK) {
1137 break;/*alway return for no block mode.*/
1138 } else if (ret == -EAGAIN) {
1139 int level;
1140 level = vdec_input_level(&priv->vdec->input);
1141 if (wait_max_cnt-- < 0)
1142 break;
1143 msleep(20);
1144 }
1145 } while (ret == -EAGAIN);
1146 return ret;
1147}
1148
1149static ssize_t amstream_abuf_write(struct file *file, const char *buf,
1150 size_t count, loff_t *ppos)
1151{
1152 struct port_priv_s *priv = (struct port_priv_s *)file->private_data;
1153 struct stream_port_s *port = priv->port;
1154 struct stream_buf_s *pbuf = &bufs[BUF_TYPE_AUDIO];
1155 int r;
1156
1157 if (!(port_get_inited(priv))) {
1158 r = amstream_port_init(priv);
1159 if (r < 0)
1160 return r;
1161 }
1162
1163 if (port->flag & PORT_FLAG_DRM)
1164 r = drm_write(file, pbuf, buf, count);
1165 else
1166 r = esparser_write(file, pbuf, buf, count);
1167
1168 return r;
1169}
1170
1171static ssize_t amstream_mpts_write(struct file *file, const char *buf,
1172 size_t count, loff_t *ppos)
1173{
1174 struct port_priv_s *priv = (struct port_priv_s *)file->private_data;
1175 struct stream_port_s *port = priv->port;
1176 struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO];
1177 struct stream_buf_s *pvbuf = NULL;
1178 int r = 0;
1179
1180 if (has_hevc_vdec()) {
1181 pvbuf = (port->vformat == VFORMAT_HEVC ||
1182 port->vformat == VFORMAT_AVS2 ||
1183 port->vformat == VFORMAT_VP9) ?
1184 &bufs[BUF_TYPE_HEVC] : &bufs[BUF_TYPE_VIDEO];
1185 } else
1186 pvbuf = &bufs[BUF_TYPE_VIDEO];
1187
1188 if (!(port_get_inited(priv))) {
1189 r = amstream_port_init(priv);
1190 if (r < 0)
1191 return r;
1192 }
1193#ifdef DATA_DEBUG
1194 debug_file_write(buf, count);
1195#endif
1196 if (port->flag & PORT_FLAG_DRM)
1197 r = drm_tswrite(file, pvbuf, pabuf, buf, count);
1198 else
1199 r = tsdemux_write(file, pvbuf, pabuf, buf, count);
1200 if (slow_input) {
1201 pr_info("slow_input: ts codec write size %x\n", r);
1202 msleep(3000);
1203 }
1204 return r;
1205}
1206
1207static ssize_t amstream_mpps_write(struct file *file, const char *buf,
1208 size_t count, loff_t *ppos)
1209{
1210 struct port_priv_s *priv = (struct port_priv_s *)file->private_data;
1211 struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO];
1212 struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO];
1213 int r;
1214
1215 if (!(port_get_inited(priv))) {
1216 r = amstream_port_init(priv);
1217 if (r < 0)
1218 return r;
1219 }
1220 return psparser_write(file, pvbuf, pabuf, buf, count);
1221}
1222
1223#ifdef CONFIG_AM_VDEC_REAL
1224static ssize_t amstream_mprm_write(struct file *file, const char *buf,
1225 size_t count, loff_t *ppos)
1226{
1227 struct port_priv_s *priv = (struct port_priv_s *)file->private_data;
1228 struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO];
1229 struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO];
1230 int r;
1231
1232 if (!(port_get_inited(priv))) {
1233 r = amstream_port_init(priv);
1234 if (r < 0)
1235 return r;
1236 }
1237 return rmparser_write(file, pvbuf, pabuf, buf, count);
1238}
1239#endif
1240
1241static ssize_t amstream_sub_read(struct file *file, char __user *buf,
1242 size_t count, loff_t *ppos)
1243{
1244 u32 sub_rp, sub_wp, sub_start, data_size, res;
1245 struct stream_buf_s *s_buf = &bufs[BUF_TYPE_SUBTITLE];
1246
1247 if (sub_port_inited == 0)
1248 return 0;
1249
1250 sub_rp = stbuf_sub_rp_get();
1251 sub_wp = stbuf_sub_wp_get();
1252 sub_start = stbuf_sub_start_get();
1253
1254 if (sub_wp == sub_rp || sub_rp == 0)
1255 return 0;
1256
1257 if (sub_wp > sub_rp)
1258 data_size = sub_wp - sub_rp;
1259 else
1260 data_size = s_buf->buf_size - sub_rp + sub_wp;
1261
1262 if (data_size > count)
1263 data_size = count;
1264
1265 if (sub_wp < sub_rp) {
1266 int first_num = s_buf->buf_size - (sub_rp - sub_start);
1267
1268 if (data_size <= first_num) {
1269 res = copy_to_user((void *)buf,
1270 (void *)(codec_mm_phys_to_virt(sub_rp)),
1271 data_size);
1272 stbuf_sub_rp_set(sub_rp + data_size - res);
1273
1274 return data_size - res;
1275 } else {
1276 if (first_num > 0) {
1277 res = copy_to_user((void *)buf,
1278 (void *)(codec_mm_phys_to_virt(sub_rp)),
1279 first_num);
1280 stbuf_sub_rp_set(sub_rp + first_num -
1281 res);
1282
1283 return first_num - res;
1284 }
1285
1286 res = copy_to_user((void *)buf,
1287 (void *)(codec_mm_phys_to_virt(sub_start)),
1288 data_size - first_num);
1289
1290 stbuf_sub_rp_set(sub_start + data_size -
1291 first_num - res);
1292
1293 return data_size - first_num - res;
1294 }
1295 } else {
1296 res =
1297 copy_to_user((void *)buf,
1298 (void *)(codec_mm_phys_to_virt(sub_rp)),
1299 data_size);
1300
1301 stbuf_sub_rp_set(sub_rp + data_size - res);
1302
1303 return data_size - res;
1304 }
1305}
1306
1307static ssize_t amstream_sub_write(struct file *file, const char *buf,
1308 size_t count, loff_t *ppos)
1309{
1310 struct port_priv_s *priv = (struct port_priv_s *)file->private_data;
1311 struct stream_buf_s *pbuf = &bufs[BUF_TYPE_SUBTITLE];
1312 int r;
1313
1314 if (!(port_get_inited(priv))) {
1315 r = amstream_port_init(priv);
1316 if (r < 0)
1317 return r;
1318 }
1319 r = esparser_write(file, pbuf, buf, count);
1320 if (r < 0)
1321 return r;
1322
1323 wakeup_sub_poll();
1324
1325 return r;
1326}
1327
1328static unsigned int amstream_sub_poll(struct file *file,
1329 poll_table *wait_table)
1330{
1331 poll_wait(file, &amstream_sub_wait, wait_table);
1332
1333 if (atomic_read(&subdata_ready)) {
1334 atomic_dec(&subdata_ready);
1335 return POLLOUT | POLLWRNORM;
1336 }
1337
1338 return 0;
1339}
1340
1341static void set_userdata_poc(struct userdata_poc_info_t poc)
1342{
1343 userdata_poc_info[userdata_poc_wi] = poc;
1344 userdata_poc_wi++;
1345 if (userdata_poc_wi == USERDATA_FIFO_NUM)
1346 userdata_poc_wi = 0;
1347}
1348EXPORT_SYMBOL(set_userdata_poc);
1349
1350void init_userdata_fifo(void)
1351{
1352 userdata_poc_ri = 0;
1353 userdata_poc_wi = 0;
1354 userdata_length = 0;
1355}
1356EXPORT_SYMBOL(init_userdata_fifo);
1357
1358void reset_userdata_fifo(int bInit)
1359{
1360 struct stream_buf_s *userdata_buf;
1361 int wi, ri;
1362 u32 rp, wp;
1363
1364 mutex_lock(&userdata_mutex);
1365
1366 wi = userdata_poc_wi;
1367 ri = userdata_poc_ri;
1368
1369 userdata_buf = &bufs[BUF_TYPE_USERDATA];
1370 rp = userdata_buf->buf_rp;
1371 wp = userdata_buf->buf_wp;
1372 if (bInit) {
1373 /* decoder reset */
1374 userdata_buf->buf_rp = 0;
1375 userdata_buf->buf_wp = 0;
1376 userdata_poc_ri = 0;
1377 userdata_poc_wi = 0;
1378 } else {
1379 /* just clean fifo buffer */
1380 userdata_buf->buf_rp = userdata_buf->buf_wp;
1381 userdata_poc_ri = userdata_poc_wi;
1382 }
1383 userdata_length = 0;
1384 last_read_wi = userdata_poc_wi;
1385
1386 mutex_unlock(&userdata_mutex);
1387 pr_debug("reset_userdata_fifo, bInit=%d, wi=%d, ri=%d, rp=%d, wp=%d\n",
1388 bInit, wi, ri, rp, wp);
1389}
1390EXPORT_SYMBOL(reset_userdata_fifo);
1391
1392int wakeup_userdata_poll(struct userdata_poc_info_t poc,
1393 int wp,
1394 unsigned long start_phyaddr,
1395 int buf_size,
1396 int data_length)
1397{
1398 struct stream_buf_s *userdata_buf = &bufs[BUF_TYPE_USERDATA];
1399 mutex_lock(&userdata_mutex);
1400
1401 if (data_length & 0x7)
1402 data_length = (((data_length + 8) >> 3) << 3);
1403 set_userdata_poc(poc);
1404 userdata_buf->buf_start = start_phyaddr;
1405 userdata_buf->buf_wp = wp;
1406 userdata_buf->buf_size = buf_size;
1407 atomic_set(&userdata_ready, 1);
1408 userdata_length += data_length;
1409 mutex_unlock(&userdata_mutex);
1410
1411 wake_up_interruptible(&amstream_userdata_wait);
1412 return userdata_buf->buf_rp;
1413}
1414EXPORT_SYMBOL(wakeup_userdata_poll);
1415
1416
1417void amstream_wakeup_userdata_poll(struct vdec_s *vdec)
1418{
1419 int vdec_id;
1420
1421 vdec_id = vdec->id;
1422 if (vdec_id > 31) {
1423 pr_info("Error, not support so many instances(%d) user data push\n",
1424 vdec_id);
1425 return;
1426 }
1427
1428 mutex_lock(&userdata_mutex);
1429 ud_ready_vdec_flag |= (1<<vdec_id);
1430
1431 atomic_set(&userdata_ready, 1);
1432 mutex_unlock(&userdata_mutex);
1433
1434 wake_up_interruptible(&amstream_userdata_wait);
1435}
1436EXPORT_SYMBOL(amstream_wakeup_userdata_poll);
1437
1438static unsigned int amstream_userdata_poll(struct file *file,
1439 poll_table *wait_table)
1440{
1441 poll_wait(file, &amstream_userdata_wait, wait_table);
1442 if (atomic_read(&userdata_ready)) {
1443 atomic_set(&userdata_ready, 0);
1444 return POLLIN | POLLRDNORM;
1445 }
1446 return 0;
1447}
1448
1449static ssize_t amstream_userdata_read(struct file *file, char __user *buf,
1450 size_t count, loff_t *ppos)
1451{
1452 u32 data_size, res, retVal = 0;
1453 u32 buf_wp, buf_rp, buf_size;
1454 unsigned long buf_start;
1455 struct stream_buf_s *userdata_buf = &bufs[BUF_TYPE_USERDATA];
1456#ifdef DEBUG_USER_DATA
1457 int old_wi;
1458#endif
1459
1460 mutex_lock(&userdata_mutex);
1461
1462 if (userdata_poc_ri != last_read_wi) {
1463 /***********************************************
1464 app picks up poc counter wrong from last read user data
1465 for H264. So, we need to recalculate userdata_poc_ri
1466 to the userdata_poc_wi from the last read.
1467 ***********************************************/
1468#if 0
1469 pr_info("app pick up poc error: ri = %d, last_wi = %d\n",
1470 userdata_poc_ri, last_read_wi);
1471#endif
1472 userdata_poc_ri = last_read_wi;
1473 }
1474
1475 buf_wp = userdata_buf->buf_wp;
1476 buf_rp = userdata_buf->buf_rp;
1477 buf_size = userdata_buf->buf_size;
1478 buf_start = userdata_buf->buf_start;
1479#ifdef DEBUG_USER_DATA
1480 old_wi = last_read_wi;
1481#endif
1482 last_read_wi = userdata_poc_wi;
1483 mutex_unlock(&userdata_mutex);
1484
1485 if (buf_start == 0 || buf_size == 0)
1486 return 0;
1487 if (buf_wp == buf_rp)
1488 return 0;
1489 if (buf_wp > buf_rp)
1490 data_size = buf_wp - buf_rp;
1491 else
1492 data_size = buf_size - buf_rp + buf_wp;
1493
1494 if (data_size > count)
1495 data_size = count;
1496#ifdef DEBUG_USER_DATA
1497 pr_info("wi:%d ri:%d wp:%d rp:%d size:%d, last_read_wi=%d\n",
1498 userdata_poc_wi, userdata_poc_ri,
1499 buf_wp, buf_rp, data_size, old_wi);
1500#endif
1501 if (buf_wp < buf_rp) {
1502 int first_num = buf_size - buf_rp;
1503 if (data_size <= first_num) {
1504 res = copy_to_user((void *)buf,
1505 (void *)((buf_rp +
1506 buf_start)), data_size);
1507 if (res)
1508 pr_info("p1 read not end res=%d, request=%d\n",
1509 res, data_size);
1510
1511 mutex_lock(&userdata_mutex);
1512 userdata_buf->buf_rp += data_size - res;
1513 mutex_unlock(&userdata_mutex);
1514 retVal = data_size - res;
1515 } else {
1516 if (first_num > 0) {
1517 res = copy_to_user((void *)buf,
1518 (void *)((buf_rp +
1519 buf_start)), first_num);
1520 if (res)
1521 pr_info("p2 read not end res=%d, request=%d\n",
1522 res, first_num);
1523
1524 res = copy_to_user((void *)buf+first_num,
1525 (void *)(buf_start),
1526 data_size - first_num);
1527
1528 if (res)
1529 pr_info("p3 read not end res=%d, request=%d\n",
1530 res, data_size - first_num);
1531
1532 mutex_lock(&userdata_mutex);
1533 userdata_buf->buf_rp += data_size;
1534 if (userdata_buf->buf_rp >= buf_size)
1535 userdata_buf->buf_rp =
1536 userdata_buf->buf_rp - buf_size;
1537 mutex_unlock(&userdata_mutex);
1538
1539 retVal = data_size;
1540 } else {
1541 /* first_num == 0*/
1542 res = copy_to_user((void *)buf,
1543 (void *)((buf_start)),
1544 data_size - first_num);
1545 mutex_lock(&userdata_mutex);
1546 userdata_buf->buf_rp =
1547 data_size - first_num - res;
1548 mutex_unlock(&userdata_mutex);
1549 retVal = data_size - first_num - res;
1550 }
1551 }
1552 } else {
1553 res = copy_to_user((void *)buf,
1554 (void *)((buf_rp + buf_start)),
1555 data_size);
1556 if (res)
1557 pr_info("p4 read not end res=%d, request=%d\n",
1558 res, data_size);
1559
1560 mutex_lock(&userdata_mutex);
1561 userdata_buf->buf_rp += data_size - res;
1562 mutex_unlock(&userdata_mutex);
1563 retVal = data_size - res;
1564 }
1565 return retVal;
1566}
1567
1568static int amstream_open(struct inode *inode, struct file *file)
1569{
1570 s32 i;
1571 struct stream_port_s *s;
1572 struct stream_port_s *port = &ports[iminor(inode)];
1573 struct port_priv_s *priv;
1574#ifdef G12A_BRINGUP_DEBUG
1575 if (vdec_get_debug_flags() & 0xff0000) {
1576 pr_info("%s force open port %d\n",
1577 __func__,
1578 ((vdec_get_debug_flags() >> 16) & 0xff) - 1);
1579 port = &ports[((vdec_get_debug_flags() >> 16) & 0xff) - 1];
1580 }
1581 pr_info("%s, port name %s\n", __func__, port->name);
1582#endif
1583 if (iminor(inode) >= amstream_port_num)
1584 return -ENODEV;
1585
1586 mutex_lock(&amstream_mutex);
1587
1588 if (port->type & PORT_TYPE_VIDEO) {
1589 for (s = &ports[0], i = 0; i < amstream_port_num; i++, s++) {
1590 if ((!is_mult_inc(s->type)) &&
1591 (s->type & PORT_TYPE_VIDEO) &&
1592 (s->flag & PORT_FLAG_IN_USE)) {
1593 mutex_unlock(&amstream_mutex);
1594 return -EBUSY;
1595 }
1596 }
1597 }
1598
1599 if ((port->flag & PORT_FLAG_IN_USE) &&
1600 ((port->type & PORT_TYPE_FRAME) == 0)) {
1601 mutex_unlock(&amstream_mutex);
1602 return -EBUSY;
1603 }
1604
1605 /* check other ports conflicts for audio */
1606 for (s = &ports[0], i = 0; i < amstream_port_num; i++, s++) {
1607 if ((s->flag & PORT_FLAG_IN_USE) &&
1608 ((port->type) & (s->type) & PORT_TYPE_AUDIO)) {
1609 mutex_unlock(&amstream_mutex);
1610 return -EBUSY;
1611 }
1612 }
1613
1614 priv = kzalloc(sizeof(struct port_priv_s), GFP_KERNEL);
1615 if (priv == NULL) {
1616 mutex_unlock(&amstream_mutex);
1617 return -ENOMEM;
1618 }
1619
1620 mutex_init(&priv->mutex);
1621
1622 priv->port = port;
1623
1624 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
1625 /* TODO: mod gate */
1626 /* switch_mod_gate_by_name("demux", 1); */
1627 amports_switch_gate("demux", 1);
1628 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) {
1629 /* TODO: clc gate */
1630 /* CLK_GATE_ON(HIU_PARSER_TOP); */
1631 amports_switch_gate("parser_top", 1);
1632 }
1633
1634 if (port->type & PORT_TYPE_VIDEO) {
1635 /* TODO: mod gate */
1636 /* switch_mod_gate_by_name("vdec", 1); */
1637 amports_switch_gate("vdec", 1);
1638
1639 if (has_hevc_vdec()) {
1640 if (port->type &
1641 (PORT_TYPE_MPTS | PORT_TYPE_HEVC))
1642 vdec_poweron(VDEC_HEVC);
1643
1644 if ((port->type & PORT_TYPE_HEVC) == 0)
1645 vdec_poweron(VDEC_1);
1646 } else {
1647 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8)
1648 vdec_poweron(VDEC_1);
1649 }
1650 }
1651
1652 if (port->type & PORT_TYPE_AUDIO) {
1653 /* TODO: mod gate */
1654 /* switch_mod_gate_by_name("audio", 1); */
1655 amports_switch_gate("audio", 1);
1656 }
1657 }
1658
1659 port->vid = 0;
1660 port->aid = 0;
1661 port->sid = 0;
1662 port->pcrid = 0xffff;
1663 file->f_op = port->fops;
1664 file->private_data = priv;
1665
1666 port->flag = PORT_FLAG_IN_USE;
1667 port->pcr_inited = 0;
1668#ifdef DATA_DEBUG
1669 debug_filp = filp_open(DEBUG_FILE_NAME, O_WRONLY, 0);
1670 if (IS_ERR(debug_filp)) {
1671 pr_err("amstream: open debug file failed\n");
1672 debug_filp = NULL;
1673 }
1674#endif
1675 mutex_unlock(&amstream_mutex);
1676
1677 if (port->type & PORT_TYPE_VIDEO) {
1678 priv->vdec = vdec_create(port, NULL);
1679
1680 if (priv->vdec == NULL) {
1681 port->flag = 0;
1682 kfree(priv);
1683 pr_err("amstream: vdec creation failed\n");
1684 return -ENOMEM;
1685 }
1686
1687 if ((port->type & PORT_TYPE_DUALDEC) ||
1688 (vdec_get_debug_flags() & 0x100)) {
1689 priv->vdec->slave = vdec_create(port, priv->vdec);
1690
1691 if (priv->vdec->slave == NULL) {
1692 vdec_release(priv->vdec);
1693 port->flag = 0;
1694 kfree(priv);
1695 pr_err("amstream: sub vdec creation failed\n");
1696 return -ENOMEM;
1697 }
1698 }
1699 }
1700 return 0;
1701}
1702
1703static int amstream_release(struct inode *inode, struct file *file)
1704{
1705 struct port_priv_s *priv = file->private_data;
1706 struct stream_port_s *port = priv->port;
1707 struct vdec_s *slave = NULL;
1708#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
1709 u32 port_flag = 0;
1710#endif
1711
1712 if (iminor(inode) >= amstream_port_num)
1713 return -ENODEV;
1714
1715 mutex_lock(&amstream_mutex);
1716
1717 if (port_get_inited(priv))
1718 amstream_port_release(priv);
1719
1720 if (priv->vdec) {
1721#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
1722 port_flag = priv->vdec->port_flag;
1723#endif
1724 if (priv->vdec->slave)
1725 slave = priv->vdec->slave;
1726 vdec_release(priv->vdec);
1727 if (slave)
1728 vdec_release(slave);
1729 priv->vdec = NULL;
1730 }
1731
1732 if ((port->type & (PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)) ==
1733 PORT_TYPE_AUDIO) {
1734 s32 i;
1735 struct stream_port_s *s;
1736
1737 for (s = &ports[0], i = 0; i < amstream_port_num; i++, s++) {
1738 if ((s->flag & PORT_FLAG_IN_USE)
1739 && (s->type & PORT_TYPE_VIDEO))
1740 break;
1741 }
1742 if (i == amstream_port_num)
1743 timestamp_firstvpts_set(0);
1744 }
1745 port->flag = 0;
1746
1747 /* timestamp_pcrscr_set(0); */
1748
1749#ifdef DATA_DEBUG
1750 if (debug_filp) {
1751 filp_close(debug_filp, current->files);
1752 debug_filp = NULL;
1753 debug_file_pos = 0;
1754 }
1755#endif
1756 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
1757 if (port->type & PORT_TYPE_VIDEO) {
1758 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) {
1759#ifndef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
1760 if (has_hevc_vdec())
1761 vdec_poweroff(VDEC_HEVC);
1762
1763 vdec_poweroff(VDEC_1);
1764#else
1765 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX
1766 && port->vformat == VFORMAT_H264
1767 && bufs[BUF_TYPE_VIDEO].for_4k) {
1768 vdec_poweroff(VDEC_HEVC);
1769 bufs[BUF_TYPE_VIDEO].for_4k = 0;
1770 }
1771
1772 if ((port->vformat == VFORMAT_HEVC
1773 || port->vformat == VFORMAT_AVS2
1774 || port->vformat == VFORMAT_VP9)) {
1775 vdec_poweroff(VDEC_HEVC);
1776 } else {
1777 vdec_poweroff(VDEC_1);
1778 }
1779#endif
1780 }
1781 /* TODO: mod gate */
1782 /* switch_mod_gate_by_name("vdec", 0); */
1783 amports_switch_gate("vdec", 0);
1784 }
1785
1786 if (port->type & PORT_TYPE_AUDIO) {
1787 /* TODO: mod gate */
1788 /* switch_mod_gate_by_name("audio", 0); */
1789 /* amports_switch_gate("audio", 0); */
1790 }
1791
1792 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) {
1793 /* TODO: clc gate */
1794 /* CLK_GATE_OFF(HIU_PARSER_TOP); */
1795 amports_switch_gate("parser_top", 0);
1796 }
1797 /* TODO: mod gate */
1798 /* switch_mod_gate_by_name("demux", 0); */
1799 amports_switch_gate("demux", 0);
1800 }
1801
1802 mutex_destroy(&priv->mutex);
1803
1804 kfree(priv);
1805
1806 mutex_unlock(&amstream_mutex);
1807 return 0;
1808}
1809
1810static long amstream_ioctl_get_version(struct port_priv_s *priv,
1811 ulong arg)
1812{
1813 int version = (AMSTREAM_IOC_VERSION_FIRST & 0xffff) << 16
1814 | (AMSTREAM_IOC_VERSION_SECOND & 0xffff);
1815 put_user(version, (u32 __user *)arg);
1816
1817 return 0;
1818}
1819static long amstream_ioctl_get(struct port_priv_s *priv, ulong arg)
1820{
1821 struct stream_port_s *this = priv->port;
1822 long r = 0;
1823
1824 struct am_ioctl_parm parm;
1825
1826 if (copy_from_user
1827 ((void *)&parm, (void *)arg,
1828 sizeof(parm)))
1829 r = -EFAULT;
1830
1831 switch (parm.cmd) {
1832 case AMSTREAM_GET_SUB_LENGTH:
1833 if ((this->type & PORT_TYPE_SUB) ||
1834 (this->type & PORT_TYPE_SUB_RD)) {
1835 u32 sub_wp, sub_rp;
1836 struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE];
1837 int val;
1838
1839 sub_wp = stbuf_sub_wp_get();
1840 sub_rp = stbuf_sub_rp_get();
1841
1842 if (sub_wp == sub_rp)
1843 val = 0;
1844 else if (sub_wp > sub_rp)
1845 val = sub_wp - sub_rp;
1846 else
1847 val = psbuf->buf_size - (sub_rp - sub_wp);
1848 parm.data_32 = val;
1849 } else
1850 r = -EINVAL;
1851 break;
1852 case AMSTREAM_GET_UD_LENGTH:
1853 if (this->type & PORT_TYPE_USERDATA) {
1854 parm.data_32 = userdata_length;
1855 userdata_length = 0;
1856 } else
1857 r = -EINVAL;
1858 break;
1859 case AMSTREAM_GET_APTS_LOOKUP:
1860 if (this->type & PORT_TYPE_AUDIO) {
1861 u32 pts = 0, frame_size, offset;
1862
1863 offset = parm.data_32;
1864 pts_lookup_offset(PTS_TYPE_AUDIO, offset, &pts,
1865 &frame_size, 300);
1866 parm.data_32 = pts;
1867 }
1868 break;
1869 case AMSTREAM_GET_FIRST_APTS_FLAG:
1870 if (this->type & PORT_TYPE_AUDIO) {
1871 parm.data_32 = first_pts_checkin_complete(
1872 PTS_TYPE_AUDIO);
1873 }
1874 break;
1875 case AMSTREAM_GET_APTS:
1876 parm.data_32 = timestamp_apts_get();
1877 break;
1878 case AMSTREAM_GET_VPTS:
1879 parm.data_32 = timestamp_vpts_get();
1880 break;
1881 case AMSTREAM_GET_PCRSCR:
1882 parm.data_32 = timestamp_pcrscr_get();
1883 break;
1884 case AMSTREAM_GET_LAST_CHECKIN_APTS:
1885 parm.data_32 = get_last_checkin_pts(PTS_TYPE_AUDIO);
1886 break;
1887 case AMSTREAM_GET_LAST_CHECKIN_VPTS:
1888 parm.data_32 = get_last_checkin_pts(PTS_TYPE_VIDEO);
1889 break;
1890 case AMSTREAM_GET_LAST_CHECKOUT_APTS:
1891 parm.data_32 = get_last_checkout_pts(PTS_TYPE_AUDIO);
1892 break;
1893 case AMSTREAM_GET_LAST_CHECKOUT_VPTS:
1894 parm.data_32 = get_last_checkout_pts(PTS_TYPE_VIDEO);
1895 break;
1896 case AMSTREAM_GET_SUB_NUM:
1897 parm.data_32 = psparser_get_sub_found_num();
1898 break;
1899 case AMSTREAM_GET_VIDEO_DELAY_LIMIT_MS:
1900 parm.data_32 = bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms;
1901 break;
1902 case AMSTREAM_GET_AUDIO_DELAY_LIMIT_MS:
1903 parm.data_32 = bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms;
1904 break;
1905 case AMSTREAM_GET_VIDEO_CUR_DELAY_MS: {
1906 int delay;
1907
1908 delay = calculation_stream_delayed_ms(
1909 PTS_TYPE_VIDEO, NULL, NULL);
1910 if (delay >= 0)
1911 parm.data_32 = delay;
1912 else
1913 parm.data_32 = 0;
1914 }
1915 break;
1916
1917 case AMSTREAM_GET_AUDIO_CUR_DELAY_MS: {
1918 int delay;
1919
1920 delay = calculation_stream_delayed_ms(
1921 PTS_TYPE_AUDIO, NULL, NULL);
1922 if (delay >= 0)
1923 parm.data_32 = delay;
1924 else
1925 parm.data_32 = 0;
1926 }
1927 break;
1928 case AMSTREAM_GET_AUDIO_AVG_BITRATE_BPS: {
1929 int delay;
1930 u32 avgbps;
1931
1932 delay = calculation_stream_delayed_ms(
1933 PTS_TYPE_AUDIO, NULL, &avgbps);
1934 if (delay >= 0)
1935 parm.data_32 = avgbps;
1936 else
1937 parm.data_32 = 0;
1938 }
1939 break;
1940 case AMSTREAM_GET_VIDEO_AVG_BITRATE_BPS: {
1941 int delay;
1942 u32 avgbps;
1943
1944 delay = calculation_stream_delayed_ms(
1945 PTS_TYPE_VIDEO, NULL, &avgbps);
1946 if (delay >= 0)
1947 parm.data_32 = avgbps;
1948 else
1949 parm.data_32 = 0;
1950 }
1951 break;
1952 case AMSTREAM_GET_ION_ID:
1953 parm.data_32 = priv->vdec->vf_receiver_inst;
1954 break;
1955 case AMSTREAM_GET_NEED_MORE_DATA:
1956 parm.data_32 = vdec_need_more_data(priv->vdec);
1957 break;
1958 case AMSTREAM_GET_FREED_HANDLE:
1959 parm.data_32 = vdec_input_get_freed_handle(priv->vdec);
1960 break;
1961 default:
1962 r = -ENOIOCTLCMD;
1963 break;
1964 }
1965 /* pr_info("parm size:%d\n", sizeof(parm)); */
1966 if (r == 0) {
1967 if (copy_to_user((void *)arg, &parm, sizeof(parm)))
1968 r = -EFAULT;
1969 }
1970
1971 return r;
1972
1973}
1974static long amstream_ioctl_set(struct port_priv_s *priv, ulong arg)
1975{
1976 struct stream_port_s *this = priv->port;
1977 struct am_ioctl_parm parm;
1978 long r = 0;
1979
1980 if (copy_from_user
1981 ((void *)&parm, (void *)arg,
1982 sizeof(parm)))
1983 r = -EFAULT;
1984
1985 switch (parm.cmd) {
1986 case AMSTREAM_SET_VB_START:
1987 if ((this->type & PORT_TYPE_VIDEO) &&
1988 ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) {
1989 if (has_hevc_vdec())
1990 bufs[BUF_TYPE_HEVC].buf_start = parm.data_32;
1991 bufs[BUF_TYPE_VIDEO].buf_start = parm.data_32;
1992 } else
1993 r = -EINVAL;
1994 break;
1995 case AMSTREAM_SET_VB_SIZE:
1996 if ((this->type & PORT_TYPE_VIDEO) &&
1997 ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) {
1998 if (bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_ALLOC) {
1999 if (has_hevc_vdec()) {
2000 r = stbuf_change_size(
2001 &bufs[BUF_TYPE_HEVC],
2002 parm.data_32,
2003 false);
2004 }
2005 r += stbuf_change_size(
2006 &bufs[BUF_TYPE_VIDEO],
2007 parm.data_32,
2008 false);
2009 }
2010 } else if (this->type & PORT_TYPE_FRAME) {
2011 /* todo: frame based set max buffer size */
2012 r = 0;
2013 } else
2014 r = -EINVAL;
2015 break;
2016 case AMSTREAM_SET_AB_START:
2017 if ((this->type & PORT_TYPE_AUDIO) &&
2018 ((bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_IN_USE) == 0))
2019 bufs[BUF_TYPE_AUDIO].buf_start = parm.data_32;
2020 else
2021 r = -EINVAL;
2022 break;
2023 case AMSTREAM_SET_AB_SIZE:
2024 if ((this->type & PORT_TYPE_AUDIO) &&
2025 ((bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_IN_USE) == 0)) {
2026 if (bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_ALLOC) {
2027 r = stbuf_change_size(
2028 &bufs[BUF_TYPE_AUDIO],
2029 parm.data_32,
2030 false);
2031 }
2032 } else
2033 r = -EINVAL;
2034 break;
2035 case AMSTREAM_SET_VFORMAT:
2036 if ((this->type & PORT_TYPE_VIDEO) &&
2037 (parm.data_vformat < VFORMAT_MAX)) {
2038 this->vformat = parm.data_vformat;
2039 this->flag |= PORT_FLAG_VFORMAT;
2040
2041 vdec_set_format(priv->vdec, this->vformat);
2042 } else
2043 r = -EINVAL;
2044 break;
2045 case AMSTREAM_SET_AFORMAT:
2046 if ((this->type & PORT_TYPE_AUDIO) &&
2047 (parm.data_aformat < AFORMAT_MAX)) {
2048 memset(&audio_dec_info, 0,
2049 sizeof(struct audio_info));
2050 /* for new format,reset the audio info. */
2051 this->aformat = parm.data_aformat;
2052 this->flag |= PORT_FLAG_AFORMAT;
2053 } else
2054 r = -EINVAL;
2055 break;
2056 case AMSTREAM_SET_VID:
2057 if (this->type & PORT_TYPE_VIDEO) {
2058 this->vid = parm.data_32;
2059 this->flag |= PORT_FLAG_VID;
2060 } else
2061 r = -EINVAL;
2062
2063 break;
2064 case AMSTREAM_SET_AID:
2065 if (this->type & PORT_TYPE_AUDIO) {
2066 this->aid = parm.data_32;
2067 this->flag |= PORT_FLAG_AID;
2068
2069 if (port_get_inited(priv)) {
2070 tsync_audio_break(1);
2071 amstream_change_avid(this);
2072 }
2073 } else
2074 r = -EINVAL;
2075 break;
2076 case AMSTREAM_SET_SID:
2077 if (this->type & PORT_TYPE_SUB) {
2078 this->sid = parm.data_32;
2079 this->flag |= PORT_FLAG_SID;
2080
2081 if (port_get_inited(priv))
2082 amstream_change_sid(this);
2083 } else
2084 r = -EINVAL;
2085
2086 break;
2087 case AMSTREAM_IOC_PCRID:
2088 this->pcrid = parm.data_32;
2089 this->pcr_inited = 1;
2090 pr_err("set pcrid = 0x%x\n", this->pcrid);
2091 break;
2092 case AMSTREAM_SET_ACHANNEL:
2093 if (this->type & PORT_TYPE_AUDIO) {
2094 this->achanl = parm.data_32;
2095 set_ch_num_info(parm.data_32);
2096 } else
2097 r = -EINVAL;
2098 break;
2099 case AMSTREAM_SET_SAMPLERATE:
2100 if (this->type & PORT_TYPE_AUDIO) {
2101 this->asamprate = parm.data_32;
2102 set_sample_rate_info(parm.data_32);
2103 } else
2104 r = -EINVAL;
2105 break;
2106 case AMSTREAM_SET_DATAWIDTH:
2107 if (this->type & PORT_TYPE_AUDIO)
2108 this->adatawidth = parm.data_32;
2109 else
2110 r = -EINVAL;
2111 break;
2112 case AMSTREAM_SET_TSTAMP:
2113 if ((this->type & (PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)) ==
2114 ((PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)))
2115 r = -EINVAL;
2116 else if (this->type & PORT_TYPE_FRAME)
2117 r = vdec_set_pts(priv->vdec, parm.data_32);
2118 else if (has_hevc_vdec() && this->type & PORT_TYPE_HEVC)
2119 r = es_vpts_checkin(&bufs[BUF_TYPE_HEVC],
2120 parm.data_32);
2121 else if (this->type & PORT_TYPE_VIDEO)
2122 r = es_vpts_checkin(&bufs[BUF_TYPE_VIDEO],
2123 parm.data_32);
2124 else if (this->type & PORT_TYPE_AUDIO)
2125 r = es_apts_checkin(&bufs[BUF_TYPE_AUDIO],
2126 parm.data_32);
2127 break;
2128 case AMSTREAM_SET_TSTAMP_US64:
2129 if ((this->type & (PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)) ==
2130 ((PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)))
2131 r = -EINVAL;
2132 else {
2133 u64 pts = parm.data_64;
2134
2135 if (this->type & PORT_TYPE_FRAME) {
2136 /*
2137 *todo: check upper layer for decoder handler
2138 * life sequence or multi-tasking management
2139 */
2140 r = vdec_set_pts64(priv->vdec, pts);
2141 } else if (has_hevc_vdec()) {
2142 if (this->type & PORT_TYPE_HEVC) {
2143 r = es_vpts_checkin_us64(
2144 &bufs[BUF_TYPE_HEVC], pts);
2145 } else if (this->type & PORT_TYPE_VIDEO) {
2146 r = es_vpts_checkin_us64(
2147 &bufs[BUF_TYPE_VIDEO], pts);
2148 } else if (this->type & PORT_TYPE_AUDIO) {
2149 r = es_vpts_checkin_us64(
2150 &bufs[BUF_TYPE_AUDIO], pts);
2151 }
2152 } else {
2153 if (this->type & PORT_TYPE_VIDEO) {
2154 r = es_vpts_checkin_us64(
2155 &bufs[BUF_TYPE_VIDEO], pts);
2156 } else if (this->type & PORT_TYPE_AUDIO) {
2157 r = es_vpts_checkin_us64(
2158 &bufs[BUF_TYPE_AUDIO], pts);
2159 }
2160 }
2161 }
2162 break;
2163 case AMSTREAM_PORT_INIT:
2164 r = amstream_port_init(priv);
2165 break;
2166 case AMSTREAM_SET_TRICKMODE:
2167 if ((this->type & PORT_TYPE_VIDEO) == 0)
2168 return -EINVAL;
2169 r = vdec_set_trickmode(priv->vdec, parm.data_32);
2170 if (r == -1)
2171 return -ENODEV;
2172 break;
2173
2174 case AMSTREAM_AUDIO_RESET:
2175 if (this->type & PORT_TYPE_AUDIO) {
2176 struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO];
2177
2178 r = audio_port_reset(this, pabuf);
2179 } else
2180 r = -EINVAL;
2181
2182 break;
2183 case AMSTREAM_SUB_RESET:
2184 if (this->type & PORT_TYPE_SUB) {
2185 struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE];
2186
2187 r = sub_port_reset(this, psbuf);
2188 } else
2189 r = -EINVAL;
2190 break;
2191 case AMSTREAM_DEC_RESET:
2192 tsync_set_dec_reset();
2193 break;
2194 case AMSTREAM_SET_TS_SKIPBYTE:
2195 tsdemux_set_skipbyte(parm.data_32);
2196 break;
2197 case AMSTREAM_SET_SUB_TYPE:
2198 sub_type = parm.data_32;
2199 break;
2200 case AMSTREAM_SET_PCRSCR:
2201 timestamp_pcrscr_set(parm.data_32);
2202 break;
2203 case AMSTREAM_SET_DEMUX:
2204 tsdemux_set_demux(parm.data_32);
2205 break;
2206 case AMSTREAM_SET_VIDEO_DELAY_LIMIT_MS:
2207 if (has_hevc_vdec())
2208 bufs[BUF_TYPE_HEVC].max_buffer_delay_ms = parm.data_32;
2209 bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms = parm.data_32;
2210 break;
2211 case AMSTREAM_SET_AUDIO_DELAY_LIMIT_MS:
2212 bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms = parm.data_32;
2213 break;
2214 case AMSTREAM_SET_DRMMODE:
2215 if (parm.data_32 == 1) {
2216 pr_debug("set drmmode\n");
2217 this->flag |= PORT_FLAG_DRM;
2218 if ((this->type & PORT_TYPE_VIDEO) &&
2219 (priv->vdec))
2220 priv->vdec->port_flag |= PORT_FLAG_DRM;
2221 } else {
2222 this->flag &= (~PORT_FLAG_DRM);
2223 pr_debug("no drmmode\n");
2224 }
2225 break;
2226 case AMSTREAM_SET_APTS: {
2227 unsigned int pts;
2228
2229 pts = parm.data_32;
2230 if (tsync_get_mode() == TSYNC_MODE_PCRMASTER)
2231 tsync_pcr_set_apts(pts);
2232 else
2233 tsync_set_apts(pts);
2234 break;
2235 }
2236 case AMSTREAM_SET_FRAME_BASE_PATH:
2237 if (is_mult_inc(this->type) &&
2238 (parm.frame_base_video_path < FRAME_BASE_PATH_MAX)) {
2239 vdec_set_video_path(priv->vdec, parm.data_32);
2240 } else
2241 r = -EINVAL;
2242 break;
2243 case AMSTREAM_SET_EOS:
2244 if (priv->vdec)
2245 vdec_set_eos(priv->vdec, parm.data_32);
2246 break;
2247 case AMSTREAM_SET_RECEIVE_ID:
2248 if (is_mult_inc(this->type))
2249 vdec_set_receive_id(priv->vdec, parm.data_32);
2250 else
2251 r = -EINVAL;
2252 break;
2253 case AMSTREAM_SET_IS_RESET:
2254 if (priv->vdec)
2255 vdec_set_isreset(priv->vdec, parm.data_32);
2256 break;
2257 case AMSTREAM_SET_DV_META_WITH_EL:
2258 if (priv->vdec) {
2259 vdec_set_dv_metawithel(priv->vdec, parm.data_32);
2260 if (vdec_dual(priv->vdec) && priv->vdec->slave)
2261 vdec_set_dv_metawithel(priv->vdec->slave,
2262 parm.data_32);
2263 }
2264 break;
2265 case AMSTREAM_SET_NO_POWERDOWN:
2266 vdec_set_no_powerdown(parm.data_32);
2267 break;
2268 default:
2269 r = -ENOIOCTLCMD;
2270 break;
2271 }
2272 return r;
2273}
2274
2275static enum E_ASPECT_RATIO get_normalized_aspect_ratio(u32 ratio_control)
2276{
2277 enum E_ASPECT_RATIO euAspectRatio;
2278
2279 ratio_control = ratio_control >> DISP_RATIO_ASPECT_RATIO_BIT;
2280
2281 switch (ratio_control) {
2282 case 0x8c:
2283 case 0x90:
2284 euAspectRatio = ASPECT_RATIO_16_9;
2285 /*pr_info("ASPECT_RATIO_16_9\n");*/
2286 break;
2287 case 0xbb:
2288 case 0xc0:
2289 euAspectRatio = ASPECT_RATIO_4_3;
2290 /*pr_info("ASPECT_RATIO_4_3\n");*/
2291 break;
2292 default:
2293 euAspectRatio = ASPECT_UNDEFINED;
2294 /*pr_info("ASPECT_UNDEFINED and ratio_control = 0x%x\n",
2295 ratio_control);*/
2296 break;
2297 }
2298
2299 return euAspectRatio;
2300}
2301
2302static long amstream_ioctl_get_ex(struct port_priv_s *priv, ulong arg)
2303{
2304 struct stream_port_s *this = priv->port;
2305 long r = 0;
2306 struct am_ioctl_parm_ex parm;
2307
2308 if (copy_from_user
2309 ((void *)&parm, (void *)arg,
2310 sizeof(parm)))
2311 r = -EFAULT;
2312
2313 switch (parm.cmd) {
2314 case AMSTREAM_GET_EX_VB_STATUS:
2315 if (this->type & PORT_TYPE_VIDEO) {
2316 struct am_ioctl_parm_ex *p = &parm;
2317 struct stream_buf_s *buf = NULL;
2318
2319 buf = (this->vformat == VFORMAT_HEVC ||
2320 this->vformat == VFORMAT_AVS2 ||
2321 this->vformat == VFORMAT_VP9) ?
2322 &bufs[BUF_TYPE_HEVC] :
2323 &bufs[BUF_TYPE_VIDEO];
2324
2325 if (this->type & PORT_TYPE_FRAME) {
2326 struct vdec_input_status_s status;
2327
2328 /*
2329 *todo: check upper layer for decoder
2330 * handler lifecycle
2331 */
2332 if (priv->vdec == NULL) {
2333 r = -EINVAL;
2334 break;
2335 }
2336
2337 r = vdec_input_get_status(&priv->vdec->input,
2338 &status);
2339 if (r == 0) {
2340 p->status.size = status.size;
2341 p->status.data_len = status.data_len;
2342 p->status.free_len = status.free_len;
2343 p->status.read_pointer =
2344 status.read_pointer;
2345 }
2346 break;
2347 }
2348
2349 p->status.size = stbuf_canusesize(buf);
2350 p->status.data_len = stbuf_level(buf);
2351 p->status.free_len = stbuf_space(buf);
2352 p->status.read_pointer = stbuf_rp(buf);
2353 } else
2354 r = -EINVAL;
2355 break;
2356 case AMSTREAM_GET_EX_AB_STATUS:
2357 if (this->type & PORT_TYPE_AUDIO) {
2358 struct am_ioctl_parm_ex *p = &parm;
2359 struct stream_buf_s *buf = &bufs[BUF_TYPE_AUDIO];
2360
2361
2362 p->status.size = stbuf_canusesize(buf);
2363 p->status.data_len = stbuf_level(buf);
2364 p->status.free_len = stbuf_space(buf);
2365 p->status.read_pointer = stbuf_rp(buf);
2366
2367 } else
2368 r = -EINVAL;
2369 break;
2370 case AMSTREAM_GET_EX_VDECSTAT:
2371 if ((this->type & PORT_TYPE_VIDEO) == 0) {
2372 pr_err("no video\n");
2373 return -EINVAL;
2374 } else {
2375 struct vdec_info vstatus;
2376 struct am_ioctl_parm_ex *p = &parm;
2377
2378 memset(&vstatus, 0, sizeof(vstatus));
2379
2380 mutex_lock(&priv->mutex);
2381 if (vdec_status(priv->vdec, &vstatus) == -1) {
2382 mutex_unlock(&priv->mutex);
2383 return -ENODEV;
2384 }
2385 mutex_unlock(&priv->mutex);
2386
2387 p->vstatus.width = vstatus.frame_width;
2388 p->vstatus.height = vstatus.frame_height;
2389 p->vstatus.fps = vstatus.frame_rate;
2390 p->vstatus.error_count = vstatus.error_count;
2391 p->vstatus.status = vstatus.status;
2392 p->vstatus.euAspectRatio =
2393 get_normalized_aspect_ratio(
2394 vstatus.ratio_control);
2395
2396 }
2397 break;
2398 case AMSTREAM_GET_EX_ADECSTAT:
2399 if ((this->type & PORT_TYPE_AUDIO) == 0) {
2400 pr_err("no audio\n");
2401 return -EINVAL;
2402 }
2403 if (amstream_adec_status == NULL) {
2404 /*
2405 *pr_err("no amstream_adec_status\n");
2406 *return -ENODEV;
2407 */
2408 memset(&parm.astatus, 0, sizeof(parm.astatus));
2409 } else {
2410 struct adec_status astatus;
2411 struct am_ioctl_parm_ex *p = &parm;
2412
2413 amstream_adec_status(&astatus);
2414 p->astatus.channels = astatus.channels;
2415 p->astatus.sample_rate = astatus.sample_rate;
2416 p->astatus.resolution = astatus.resolution;
2417 p->astatus.error_count = astatus.error_count;
2418 p->astatus.status = astatus.status;
2419 }
2420 break;
2421
2422 case AMSTREAM_GET_EX_UD_POC:
2423 if (this->type & PORT_TYPE_USERDATA) {
2424 struct userdata_poc_info_t userdata_poc =
2425 userdata_poc_info[userdata_poc_ri];
2426 memcpy(&parm.data_userdata_info,
2427 &userdata_poc,
2428 sizeof(struct userdata_poc_info_t));
2429
2430 userdata_poc_ri++;
2431 if (userdata_poc_ri == USERDATA_FIFO_NUM)
2432 userdata_poc_ri = 0;
2433 } else
2434 r = -EINVAL;
2435 break;
2436 default:
2437 r = -ENOIOCTLCMD;
2438 break;
2439 }
2440 /* pr_info("parm size:%zx\n", sizeof(parm)); */
2441 if (r == 0) {
2442 if (copy_to_user((void *)arg, &parm, sizeof(parm)))
2443 r = -EFAULT;
2444 }
2445 return r;
2446
2447}
2448static long amstream_ioctl_set_ex(struct port_priv_s *priv, ulong arg)
2449{
2450 long r = 0;
2451 return r;
2452}
2453static long amstream_ioctl_get_ptr(struct port_priv_s *priv, ulong arg)
2454{
2455 long r = 0;
2456
2457 struct am_ioctl_parm_ptr parm;
2458
2459 if (copy_from_user
2460 ((void *)&parm, (void *)arg,
2461 sizeof(parm)))
2462 return -EFAULT;
2463
2464 switch (parm.cmd) {
2465 case AMSTREAM_GET_PTR_SUB_INFO:
2466 {
2467 struct subtitle_info msub_info[MAX_SUB_NUM];
2468 struct subtitle_info *psub_info[MAX_SUB_NUM];
2469 int i;
2470
2471 for (i = 0; i < MAX_SUB_NUM; i++)
2472 psub_info[i] = &msub_info[i];
2473
2474 r = psparser_get_sub_info(psub_info);
2475
2476 if (r == 0) {
2477 memcpy(parm.pdata_sub_info, msub_info,
2478 sizeof(struct subtitle_info)
2479 * MAX_SUB_NUM);
2480 }
2481 }
2482 break;
2483 default:
2484 r = -ENOIOCTLCMD;
2485 break;
2486 }
2487 /* pr_info("parm size:%d\n", sizeof(parm)); */
2488 if (r == 0) {
2489 if (copy_to_user((void *)arg, &parm, sizeof(parm)))
2490 r = -EFAULT;
2491 }
2492
2493 return r;
2494
2495}
2496static long amstream_ioctl_set_ptr(struct port_priv_s *priv, ulong arg)
2497{
2498 struct stream_port_s *this = priv->port;
2499 struct am_ioctl_parm_ptr parm;
2500 long r = 0;
2501
2502 if (copy_from_user
2503 ((void *)&parm, (void *)arg,
2504 sizeof(parm))) {
2505 pr_err("[%s]%d, arg err\n", __func__, __LINE__);
2506 r = -EFAULT;
2507 }
2508 switch (parm.cmd) {
2509 case AMSTREAM_SET_PTR_AUDIO_INFO:
2510 if ((this->type & PORT_TYPE_VIDEO)
2511 || (this->type & PORT_TYPE_AUDIO)) {
2512 if (parm.pdata_audio_info != NULL) {
2513 if (copy_from_user
2514 ((void *)&audio_dec_info, (void *)parm.pdata_audio_info,
2515 sizeof(audio_dec_info))) {
2516 pr_err("[%s]%d, arg err\n", __func__, __LINE__);
2517 r = -EFAULT;
2518 }
2519 }
2520 } else
2521 r = -EINVAL;
2522 break;
2523 case AMSTREAM_SET_PTR_CONFIGS:
2524 if (this->type & PORT_TYPE_VIDEO) {
2525 if (!parm.pointer || (parm.len <= 0) ||
2526 (parm.len > PAGE_SIZE)) {
2527 r = -EINVAL;
2528 } else {
2529 r = copy_from_user(priv->vdec->config,
2530 parm.pointer, parm.len);
2531 if (r)
2532 r = -EINVAL;
2533 else
2534 priv->vdec->config_len = parm.len;
2535 }
2536 } else
2537 r = -EINVAL;
2538 break;
2539 default:
2540 r = -ENOIOCTLCMD;
2541 break;
2542 }
2543 return r;
2544}
2545
2546static long amstream_do_ioctl_new(struct port_priv_s *priv,
2547 unsigned int cmd, ulong arg)
2548{
2549 long r = 0;
2550 struct stream_port_s *this = priv->port;
2551
2552 switch (cmd) {
2553 case AMSTREAM_IOC_GET_VERSION:
2554 r = amstream_ioctl_get_version(priv, arg);
2555 break;
2556 case AMSTREAM_IOC_GET:
2557 r = amstream_ioctl_get(priv, arg);
2558 break;
2559 case AMSTREAM_IOC_SET:
2560 r = amstream_ioctl_set(priv, arg);
2561 break;
2562 case AMSTREAM_IOC_GET_EX:
2563 r = amstream_ioctl_get_ex(priv, arg);
2564 break;
2565 case AMSTREAM_IOC_SET_EX:
2566 r = amstream_ioctl_set_ex(priv, arg);
2567 break;
2568 case AMSTREAM_IOC_GET_PTR:
2569 r = amstream_ioctl_get_ptr(priv, arg);
2570 break;
2571 case AMSTREAM_IOC_SET_PTR:
2572 r = amstream_ioctl_set_ptr(priv, arg);
2573 break;
2574 case AMSTREAM_IOC_SYSINFO:
2575 if (this->type & PORT_TYPE_VIDEO)
2576 r = vdec_set_decinfo(priv->vdec, (void *)arg);
2577 else
2578 r = -EINVAL;
2579 break;
2580 case AMSTREAM_IOC_GET_QOSINFO:
2581 {
2582 struct av_param_qosinfo_t __user *uarg = (void *)arg;
2583 struct vframe_qos_s *qos_info = vdec_get_qos_info();
2584 if (this->type & PORT_TYPE_VIDEO) {
2585 if (qos_info != NULL && copy_to_user((void *)uarg->vframe_qos,
2586 qos_info,
2587 QOS_FRAME_NUM*sizeof(struct vframe_qos_s))) {
2588 r = -EFAULT;
2589 break;
2590 }
2591 }
2592 }
2593 break;
2594 default:
2595 r = -ENOIOCTLCMD;
2596 break;
2597 }
2598
2599 return r;
2600}
2601
2602static long amstream_do_ioctl_old(struct port_priv_s *priv,
2603 unsigned int cmd, ulong arg)
2604{
2605 struct stream_port_s *this = priv->port;
2606 long r = 0;
2607
2608 switch (cmd) {
2609
2610 case AMSTREAM_IOC_VB_START:
2611 if ((this->type & PORT_TYPE_VIDEO) &&
2612 ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) {
2613 if (has_hevc_vdec())
2614 bufs[BUF_TYPE_HEVC].buf_start = arg;
2615 bufs[BUF_TYPE_VIDEO].buf_start = arg;
2616 } else
2617 r = -EINVAL;
2618 break;
2619
2620 case AMSTREAM_IOC_VB_SIZE:
2621 if ((this->type & PORT_TYPE_VIDEO) &&
2622 ((bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_IN_USE) == 0)) {
2623 if (bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_ALLOC) {
2624 if (has_hevc_vdec()) {
2625 r = stbuf_change_size(
2626 &bufs[BUF_TYPE_HEVC],
2627 arg, false);
2628 }
2629 r += stbuf_change_size(
2630 &bufs[BUF_TYPE_VIDEO],
2631 arg, false);
2632 }
2633 } else
2634 r = -EINVAL;
2635 break;
2636
2637 case AMSTREAM_IOC_AB_START:
2638 if ((this->type & PORT_TYPE_AUDIO) &&
2639 ((bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_IN_USE) == 0))
2640 bufs[BUF_TYPE_AUDIO].buf_start = arg;
2641 else
2642 r = -EINVAL;
2643 break;
2644
2645 case AMSTREAM_IOC_AB_SIZE:
2646 if ((this->type & PORT_TYPE_AUDIO) &&
2647 ((bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_IN_USE) == 0)) {
2648 if (bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_ALLOC) {
2649 r = stbuf_change_size(
2650 &bufs[BUF_TYPE_AUDIO], arg, false);
2651 }
2652 } else
2653 r = -EINVAL;
2654 break;
2655
2656 case AMSTREAM_IOC_VFORMAT:
2657 if ((this->type & PORT_TYPE_VIDEO) && (arg < VFORMAT_MAX)) {
2658 this->vformat = (enum vformat_e)arg;
2659 this->flag |= PORT_FLAG_VFORMAT;
2660
2661 vdec_set_format(priv->vdec, this->vformat);
2662 } else
2663 r = -EINVAL;
2664 break;
2665
2666 case AMSTREAM_IOC_AFORMAT:
2667 if ((this->type & PORT_TYPE_AUDIO) && (arg < AFORMAT_MAX)) {
2668 memset(&audio_dec_info, 0,
2669 sizeof(struct audio_info));
2670 /* for new format,reset the audio info. */
2671 this->aformat = (enum aformat_e)arg;
2672 this->flag |= PORT_FLAG_AFORMAT;
2673 } else
2674 r = -EINVAL;
2675 break;
2676
2677 case AMSTREAM_IOC_VID:
2678 if (this->type & PORT_TYPE_VIDEO) {
2679 this->vid = (u32) arg;
2680 this->flag |= PORT_FLAG_VID;
2681 } else
2682 r = -EINVAL;
2683
2684 break;
2685
2686 case AMSTREAM_IOC_AID:
2687 if (this->type & PORT_TYPE_AUDIO) {
2688 this->aid = (u32) arg;
2689 this->flag |= PORT_FLAG_AID;
2690
2691 if (port_get_inited(priv)) {
2692 tsync_audio_break(1);
2693 amstream_change_avid(this);
2694 }
2695 } else
2696 r = -EINVAL;
2697 break;
2698
2699 case AMSTREAM_IOC_SID:
2700 if (this->type & PORT_TYPE_SUB) {
2701 this->sid = (u32) arg;
2702 this->flag |= PORT_FLAG_SID;
2703
2704 if (port_get_inited(priv))
2705 amstream_change_sid(this);
2706 } else
2707 r = -EINVAL;
2708
2709 break;
2710
2711 case AMSTREAM_IOC_PCRID:
2712 this->pcrid = (u32) arg;
2713 this->pcr_inited = 1;
2714 pr_err("set pcrid = 0x%x\n", this->pcrid);
2715 break;
2716
2717 case AMSTREAM_IOC_VB_STATUS:
2718 if (this->type & PORT_TYPE_VIDEO) {
2719 struct am_io_param para;
2720 struct am_io_param *p = &para;
2721 struct stream_buf_s *buf = NULL;
2722
2723 buf = (this->vformat == VFORMAT_HEVC ||
2724 this->vformat == VFORMAT_AVS2 ||
2725 this->vformat == VFORMAT_VP9) ?
2726 &bufs[BUF_TYPE_HEVC] :
2727 &bufs[BUF_TYPE_VIDEO];
2728
2729 if (this->type & PORT_TYPE_FRAME) {
2730 struct vdec_input_status_s status;
2731
2732 /*
2733 *todo: check upper layer for decoder
2734 * handler lifecycle
2735 */
2736 if (priv->vdec == NULL) {
2737 r = -EINVAL;
2738 break;
2739 }
2740
2741 r = vdec_input_get_status(&priv->vdec->input,
2742 &status);
2743 if (r == 0) {
2744 p->status.size = status.size;
2745 p->status.data_len = status.data_len;
2746 p->status.free_len = status.free_len;
2747 p->status.read_pointer =
2748 status.read_pointer;
2749 if (copy_to_user((void *)arg, p,
2750 sizeof(para)))
2751 r = -EFAULT;
2752 }
2753 break;
2754 }
2755
2756 p->status.size = stbuf_canusesize(buf);
2757 p->status.data_len = stbuf_level(buf);
2758 p->status.free_len = stbuf_space(buf);
2759 p->status.read_pointer = stbuf_rp(buf);
2760 if (copy_to_user((void *)arg, p, sizeof(para)))
2761 r = -EFAULT;
2762 return r;
2763 }
2764 r = -EINVAL;
2765 break;
2766
2767 case AMSTREAM_IOC_AB_STATUS:
2768 if (this->type & PORT_TYPE_AUDIO) {
2769 struct am_io_param para;
2770 struct am_io_param *p = &para;
2771 struct stream_buf_s *buf = &bufs[BUF_TYPE_AUDIO];
2772
2773 p->status.size = stbuf_canusesize(buf);
2774 p->status.data_len = stbuf_level(buf);
2775 p->status.free_len = stbuf_space(buf);
2776 p->status.read_pointer = stbuf_rp(buf);
2777 if (copy_to_user((void *)arg, p, sizeof(para)))
2778 r = -EFAULT;
2779 return r;
2780 }
2781 r = -EINVAL;
2782 break;
2783
2784 case AMSTREAM_IOC_SYSINFO:
2785 if (this->type & PORT_TYPE_VIDEO)
2786 r = vdec_set_decinfo(priv->vdec, (void *)arg);
2787 else
2788 r = -EINVAL;
2789 break;
2790
2791 case AMSTREAM_IOC_ACHANNEL:
2792 if (this->type & PORT_TYPE_AUDIO) {
2793 this->achanl = (u32) arg;
2794 set_ch_num_info((u32) arg);
2795 } else
2796 r = -EINVAL;
2797 break;
2798
2799 case AMSTREAM_IOC_SAMPLERATE:
2800 if (this->type & PORT_TYPE_AUDIO) {
2801 this->asamprate = (u32) arg;
2802 set_sample_rate_info((u32) arg);
2803 } else
2804 r = -EINVAL;
2805 break;
2806
2807 case AMSTREAM_IOC_DATAWIDTH:
2808 if (this->type & PORT_TYPE_AUDIO)
2809 this->adatawidth = (u32) arg;
2810 else
2811 r = -EINVAL;
2812 break;
2813
2814 case AMSTREAM_IOC_TSTAMP:
2815 if ((this->type & (PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)) ==
2816 ((PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)))
2817 r = -EINVAL;
2818 else if (this->type & PORT_TYPE_FRAME)
2819 r = vdec_set_pts(priv->vdec, arg);
2820 else if (has_hevc_vdec() && this->type & PORT_TYPE_HEVC)
2821 r = es_vpts_checkin(&bufs[BUF_TYPE_HEVC], arg);
2822 else if (this->type & PORT_TYPE_VIDEO)
2823 r = es_vpts_checkin(&bufs[BUF_TYPE_VIDEO], arg);
2824 else if (this->type & PORT_TYPE_AUDIO)
2825 r = es_apts_checkin(&bufs[BUF_TYPE_AUDIO], arg);
2826 break;
2827
2828 case AMSTREAM_IOC_TSTAMP_uS64:
2829 if ((this->type & (PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)) ==
2830 ((PORT_TYPE_AUDIO | PORT_TYPE_VIDEO)))
2831 r = -EINVAL;
2832 else {
2833 u64 pts;
2834
2835 if (copy_from_user
2836 ((void *)&pts, (void *)arg, sizeof(u64)))
2837 return -EFAULT;
2838 if (this->type & PORT_TYPE_FRAME) {
2839 /*
2840 *todo: check upper layer for decoder handler
2841 * life sequence or multi-tasking management
2842 */
2843 if (priv->vdec)
2844 r = vdec_set_pts64(priv->vdec, pts);
2845 } else if (has_hevc_vdec()) {
2846 if (this->type & PORT_TYPE_HEVC) {
2847 r = es_vpts_checkin_us64(
2848 &bufs[BUF_TYPE_HEVC], pts);
2849 } else if (this->type & PORT_TYPE_VIDEO) {
2850 r = es_vpts_checkin_us64(
2851 &bufs[BUF_TYPE_VIDEO], pts);
2852 } else if (this->type & PORT_TYPE_AUDIO) {
2853 r = es_vpts_checkin_us64(
2854 &bufs[BUF_TYPE_AUDIO], pts);
2855 }
2856 } else {
2857 if (this->type & PORT_TYPE_VIDEO) {
2858 r = es_vpts_checkin_us64(
2859 &bufs[BUF_TYPE_VIDEO], pts);
2860 } else if (this->type & PORT_TYPE_AUDIO) {
2861 r = es_vpts_checkin_us64(
2862 &bufs[BUF_TYPE_AUDIO], pts);
2863 }
2864 }
2865 }
2866 break;
2867
2868 case AMSTREAM_IOC_VDECSTAT:
2869 if ((this->type & PORT_TYPE_VIDEO) == 0)
2870 return -EINVAL;
2871 {
2872 struct vdec_info vstatus;
2873 struct am_io_param para;
2874 struct am_io_param *p = &para;
2875
2876 memset(&vstatus, 0, sizeof(vstatus));
2877
2878 mutex_lock(&priv->mutex);
2879 if (vdec_status(priv->vdec, &vstatus) == -1) {
2880 mutex_unlock(&priv->mutex);
2881 return -ENODEV;
2882 }
2883 mutex_unlock(&priv->mutex);
2884
2885 p->vstatus.width = vstatus.frame_width;
2886 p->vstatus.height = vstatus.frame_height;
2887 p->vstatus.fps = vstatus.frame_rate;
2888 p->vstatus.error_count = vstatus.error_count;
2889 p->vstatus.status = vstatus.status;
2890 p->vstatus.euAspectRatio =
2891 get_normalized_aspect_ratio(
2892 vstatus.ratio_control);
2893
2894 if (copy_to_user((void *)arg, p, sizeof(para)))
2895 r = -EFAULT;
2896 return r;
2897 }
2898
2899 case AMSTREAM_IOC_VDECINFO:
2900 if ((this->type & PORT_TYPE_VIDEO) == 0)
2901 return -EINVAL;
2902 {
2903 struct vdec_info vinfo;
2904 struct am_io_info para;
2905
2906 memset(&para, 0x0, sizeof(struct am_io_info));
2907
2908 mutex_lock(&priv->mutex);
2909 if (vdec_status(priv->vdec, &vinfo) == -1) {
2910 mutex_unlock(&priv->mutex);
2911 return -ENODEV;
2912 }
2913 mutex_unlock(&priv->mutex);
2914
2915 memcpy(&para.vinfo, &vinfo, sizeof(struct vdec_info));
2916 if (copy_to_user((void *)arg, &para, sizeof(para)))
2917 r = -EFAULT;
2918 return r;
2919 }
2920
2921 case AMSTREAM_IOC_ADECSTAT:
2922 if ((this->type & PORT_TYPE_AUDIO) == 0)
2923 return -EINVAL;
2924 if (amstream_adec_status == NULL)
2925 return -ENODEV;
2926 else {
2927 struct adec_status astatus;
2928 struct am_io_param para;
2929 struct am_io_param *p = &para;
2930
2931 amstream_adec_status(&astatus);
2932 p->astatus.channels = astatus.channels;
2933 p->astatus.sample_rate = astatus.sample_rate;
2934 p->astatus.resolution = astatus.resolution;
2935 p->astatus.error_count = astatus.error_count;
2936 p->astatus.status = astatus.status;
2937 if (copy_to_user((void *)arg, p, sizeof(para)))
2938 r = -EFAULT;
2939 return r;
2940 }
2941 case AMSTREAM_IOC_PORT_INIT:
2942 r = amstream_port_init(priv);
2943 break;
2944
2945 case AMSTREAM_IOC_VDEC_RESET:
2946 if ((this->type & PORT_TYPE_VIDEO) == 0)
2947 return -EINVAL;
2948
2949 if (priv->vdec == NULL)
2950 return -ENODEV;
2951
2952 r = vdec_reset(priv->vdec);
2953 break;
2954
2955 case AMSTREAM_IOC_TRICKMODE:
2956 if ((this->type & PORT_TYPE_VIDEO) == 0)
2957 return -EINVAL;
2958 r = vdec_set_trickmode(priv->vdec, arg);
2959 if (r == -1)
2960 return -ENODEV;
2961 break;
2962
2963 case AMSTREAM_IOC_AUDIO_INFO:
2964 if ((this->type & PORT_TYPE_VIDEO)
2965 || (this->type & PORT_TYPE_AUDIO)) {
2966 if (copy_from_user
2967 (&audio_dec_info, (void __user *)arg,
2968 sizeof(audio_dec_info)))
2969 r = -EFAULT;
2970 } else
2971 r = -EINVAL;
2972 break;
2973
2974 case AMSTREAM_IOC_AUDIO_RESET:
2975 if (this->type & PORT_TYPE_AUDIO) {
2976 struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO];
2977
2978 r = audio_port_reset(this, pabuf);
2979 } else
2980 r = -EINVAL;
2981
2982 break;
2983
2984 case AMSTREAM_IOC_SUB_RESET:
2985 if (this->type & PORT_TYPE_SUB) {
2986 struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE];
2987
2988 r = sub_port_reset(this, psbuf);
2989 } else
2990 r = -EINVAL;
2991 break;
2992
2993 case AMSTREAM_IOC_SUB_LENGTH:
2994 if ((this->type & PORT_TYPE_SUB) ||
2995 (this->type & PORT_TYPE_SUB_RD)) {
2996 u32 sub_wp, sub_rp;
2997 struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE];
2998 int val;
2999
3000 sub_wp = stbuf_sub_wp_get();
3001 sub_rp = stbuf_sub_rp_get();
3002
3003 if (sub_wp == sub_rp)
3004 val = 0;
3005 else if (sub_wp > sub_rp)
3006 val = sub_wp - sub_rp;
3007 else
3008 val = psbuf->buf_size - (sub_rp - sub_wp);
3009 put_user(val, (int __user *)arg);
3010 } else
3011 r = -EINVAL;
3012 break;
3013
3014 case AMSTREAM_IOC_UD_LENGTH:
3015 if (this->type & PORT_TYPE_USERDATA) {
3016 /* *((u32 *)arg) = userdata_length; */
3017 put_user(userdata_length, (unsigned long __user *)arg);
3018 userdata_length = 0;
3019 } else
3020 r = -EINVAL;
3021 break;
3022
3023 case AMSTREAM_IOC_UD_POC:
3024 if (this->type & PORT_TYPE_USERDATA) {
3025 /* *((u32 *)arg) = userdata_length; */
3026 int ri;
3027#ifdef DEBUG_USER_DATA
3028 int wi;
3029#endif
3030 int bDataAvail = 0;
3031
3032 mutex_lock(&userdata_mutex);
3033 if (userdata_poc_wi != userdata_poc_ri) {
3034 bDataAvail = 1;
3035 ri = userdata_poc_ri;
3036#ifdef DEBUG_USER_DATA
3037 wi = userdata_poc_wi;
3038#endif
3039 userdata_poc_ri++;
3040 if (userdata_poc_ri >= USERDATA_FIFO_NUM)
3041 userdata_poc_ri = 0;
3042 }
3043 mutex_unlock(&userdata_mutex);
3044 if (bDataAvail) {
3045 int res;
3046 struct userdata_poc_info_t userdata_poc =
3047 userdata_poc_info[ri];
3048#ifdef DEBUG_USER_DATA
3049 pr_info("read poc: ri=%d, wi=%d, poc=%d, last_wi=%d\n",
3050 ri, wi,
3051 userdata_poc.poc_number,
3052 last_read_wi);
3053#endif
3054 res =
3055 copy_to_user((unsigned long __user *)arg,
3056 &userdata_poc,
3057 sizeof(struct userdata_poc_info_t));
3058 if (res < 0)
3059 r = -EFAULT;
3060 } else {
3061 r = -EFAULT;
3062 }
3063 } else {
3064 r = -EINVAL;
3065 }
3066 break;
3067
3068 case AMSTREAM_IOC_UD_BUF_READ:
3069 {
3070 if (this->type & PORT_TYPE_USERDATA) {
3071 struct userdata_param_t param;
3072 struct userdata_param_t *p_userdata_param;
3073 struct vdec_s *vdec;
3074
3075 p_userdata_param = &param;
3076 if (copy_from_user(p_userdata_param,
3077 (void __user *)arg,
3078 sizeof(struct userdata_param_t))) {
3079 r = -EFAULT;
3080 break;
3081 }
3082 mutex_lock(&amstream_mutex);
3083 vdec = vdec_get_vdec_by_id(p_userdata_param->instance_id);
3084 if (vdec) {
3085 if (vdec_read_user_data(vdec,
3086 p_userdata_param) == 0) {
3087 r = -EFAULT;
3088 mutex_unlock(&amstream_mutex);
3089 break;
3090 }
3091
3092 if (copy_to_user((void *)arg,
3093 p_userdata_param,
3094 sizeof(struct userdata_param_t)))
3095 r = -EFAULT;
3096 } else
3097 r = -EINVAL;
3098 mutex_unlock(&amstream_mutex);
3099 }
3100 }
3101 break;
3102
3103 case AMSTREAM_IOC_UD_AVAILABLE_VDEC:
3104 {
3105 unsigned int ready_vdec;
3106
3107 mutex_lock(&userdata_mutex);
3108 ready_vdec = ud_ready_vdec_flag;
3109 ud_ready_vdec_flag = 0;
3110 mutex_unlock(&userdata_mutex);
3111
3112 put_user(ready_vdec, (uint32_t __user *)arg);
3113 }
3114 break;
3115
3116 case AMSTREAM_IOC_GET_VDEC_ID:
3117 if (this->type & PORT_TYPE_VIDEO && priv->vdec) {
3118 put_user(priv->vdec->id, (int32_t __user *)arg);
3119 } else
3120 r = -EINVAL;
3121 break;
3122
3123
3124 case AMSTREAM_IOC_UD_FLUSH_USERDATA:
3125 if (this->type & PORT_TYPE_USERDATA) {
3126 struct vdec_s *vdec;
3127 int vdec_id;
3128
3129 mutex_lock(&amstream_mutex);
3130 get_user(vdec_id, (int __user *)arg);
3131 vdec = vdec_get_vdec_by_id(vdec_id);
3132 if (vdec) {
3133 vdec_reset_userdata_fifo(vdec, 0);
3134 pr_info("reset_userdata_fifo for vdec: %d\n", vdec_id);
3135 }
3136 mutex_unlock(&amstream_mutex);
3137 } else
3138 r = -EINVAL;
3139 break;
3140
3141 case AMSTREAM_IOC_SET_DEC_RESET:
3142 tsync_set_dec_reset();
3143 break;
3144
3145 case AMSTREAM_IOC_TS_SKIPBYTE:
3146 if ((int)arg >= 0)
3147 tsdemux_set_skipbyte(arg);
3148 else
3149 r = -EINVAL;
3150 break;
3151
3152 case AMSTREAM_IOC_SUB_TYPE:
3153 sub_type = (int)arg;
3154 break;
3155
3156 case AMSTREAM_IOC_APTS_LOOKUP:
3157 if (this->type & PORT_TYPE_AUDIO) {
3158 u32 pts = 0, frame_size, offset;
3159
3160 get_user(offset, (unsigned long __user *)arg);
3161 pts_lookup_offset(PTS_TYPE_AUDIO, offset, &pts,
3162 &frame_size, 300);
3163 put_user(pts, (int __user *)arg);
3164 }
3165 return 0;
3166 case GET_FIRST_APTS_FLAG:
3167 if (this->type & PORT_TYPE_AUDIO) {
3168 put_user(first_pts_checkin_complete(PTS_TYPE_AUDIO),
3169 (int __user *)arg);
3170 }
3171 break;
3172
3173 case AMSTREAM_IOC_APTS:
3174 put_user(timestamp_apts_get(), (int __user *)arg);
3175 break;
3176
3177 case AMSTREAM_IOC_VPTS:
3178 put_user(timestamp_vpts_get(), (int __user *)arg);
3179 break;
3180
3181 case AMSTREAM_IOC_PCRSCR:
3182 put_user(timestamp_pcrscr_get(), (int __user *)arg);
3183 break;
3184
3185 case AMSTREAM_IOC_SET_PCRSCR:
3186 timestamp_pcrscr_set(arg);
3187 break;
3188 case AMSTREAM_IOC_GET_LAST_CHECKIN_APTS:
3189 put_user(get_last_checkin_pts(PTS_TYPE_AUDIO), (int *)arg);
3190 break;
3191 case AMSTREAM_IOC_GET_LAST_CHECKIN_VPTS:
3192 put_user(get_last_checkin_pts(PTS_TYPE_VIDEO), (int *)arg);
3193 break;
3194 case AMSTREAM_IOC_GET_LAST_CHECKOUT_APTS:
3195 put_user(get_last_checkout_pts(PTS_TYPE_AUDIO), (int *)arg);
3196 break;
3197 case AMSTREAM_IOC_GET_LAST_CHECKOUT_VPTS:
3198 put_user(get_last_checkout_pts(PTS_TYPE_VIDEO), (int *)arg);
3199 break;
3200 case AMSTREAM_IOC_SUB_NUM:
3201 put_user(psparser_get_sub_found_num(), (int *)arg);
3202 break;
3203
3204 case AMSTREAM_IOC_SUB_INFO:
3205 if (arg > 0) {
3206 struct subtitle_info msub_info[MAX_SUB_NUM];
3207 struct subtitle_info *psub_info[MAX_SUB_NUM];
3208 int i;
3209
3210 for (i = 0; i < MAX_SUB_NUM; i++)
3211 psub_info[i] = &msub_info[i];
3212
3213 r = psparser_get_sub_info(psub_info);
3214
3215 if (r == 0) {
3216 if (copy_to_user((void __user *)arg, msub_info,
3217 sizeof(struct subtitle_info) * MAX_SUB_NUM))
3218 r = -EFAULT;
3219 }
3220 }
3221 break;
3222 case AMSTREAM_IOC_SET_DEMUX:
3223 tsdemux_set_demux((int)arg);
3224 break;
3225 case AMSTREAM_IOC_SET_VIDEO_DELAY_LIMIT_MS:
3226 if (has_hevc_vdec())
3227 bufs[BUF_TYPE_HEVC].max_buffer_delay_ms = (int)arg;
3228 bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms = (int)arg;
3229 break;
3230 case AMSTREAM_IOC_SET_AUDIO_DELAY_LIMIT_MS:
3231 bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms = (int)arg;
3232 break;
3233 case AMSTREAM_IOC_GET_VIDEO_DELAY_LIMIT_MS:
3234 put_user(bufs[BUF_TYPE_VIDEO].max_buffer_delay_ms, (int *)arg);
3235 break;
3236 case AMSTREAM_IOC_GET_AUDIO_DELAY_LIMIT_MS:
3237 put_user(bufs[BUF_TYPE_AUDIO].max_buffer_delay_ms, (int *)arg);
3238 break;
3239 case AMSTREAM_IOC_GET_VIDEO_CUR_DELAY_MS: {
3240 int delay;
3241
3242 delay = calculation_stream_delayed_ms(
3243 PTS_TYPE_VIDEO, NULL, NULL);
3244 if (delay >= 0)
3245 put_user(delay, (int *)arg);
3246 else
3247 put_user(0, (int *)arg);
3248 }
3249 break;
3250
3251 case AMSTREAM_IOC_GET_AUDIO_CUR_DELAY_MS: {
3252 int delay;
3253
3254 delay = calculation_stream_delayed_ms(PTS_TYPE_AUDIO, NULL,
3255 NULL);
3256 if (delay >= 0)
3257 put_user(delay, (int *)arg);
3258 else
3259 put_user(0, (int *)arg);
3260 }
3261 break;
3262 case AMSTREAM_IOC_GET_AUDIO_AVG_BITRATE_BPS: {
3263 int delay;
3264 u32 avgbps;
3265
3266 delay = calculation_stream_delayed_ms(PTS_TYPE_AUDIO, NULL,
3267 &avgbps);
3268 if (delay >= 0)
3269 put_user(avgbps, (int *)arg);
3270 else
3271 put_user(0, (int *)arg);
3272 break;
3273 }
3274 case AMSTREAM_IOC_GET_VIDEO_AVG_BITRATE_BPS: {
3275 int delay;
3276 u32 avgbps;
3277
3278 delay = calculation_stream_delayed_ms(PTS_TYPE_VIDEO, NULL,
3279 &avgbps);
3280 if (delay >= 0)
3281 put_user(avgbps, (int *)arg);
3282 else
3283 put_user(0, (int *)arg);
3284 break;
3285 }
3286 case AMSTREAM_IOC_SET_DRMMODE:
3287 if ((u32) arg == 1) {
3288 pr_err("set drmmode, input must be secure buffer\n");
3289 this->flag |= PORT_FLAG_DRM;
3290 if ((this->type & PORT_TYPE_VIDEO) &&
3291 (priv->vdec))
3292 priv->vdec->port_flag |= PORT_FLAG_DRM;
3293 } else if ((u32)arg == 2) {
3294 pr_err("set drmmode, input must be normal buffer\n");
3295 if ((this->type & PORT_TYPE_VIDEO) &&
3296 (priv->vdec)) {
3297 pr_err("vdec port_flag with drmmode\n");
3298 priv->vdec->port_flag |= PORT_FLAG_DRM;
3299 }
3300 } else {
3301 this->flag &= (~PORT_FLAG_DRM);
3302 pr_err("no drmmode\n");
3303 }
3304 break;
3305 case AMSTREAM_IOC_SET_APTS: {
3306 unsigned long pts;
3307
3308 if (get_user(pts, (unsigned long __user *)arg)) {
3309 pr_err
3310 ("Get audio pts from user space fault!\n");
3311 return -EFAULT;
3312 }
3313 if (tsync_get_mode() == TSYNC_MODE_PCRMASTER)
3314 tsync_pcr_set_apts(pts);
3315 else
3316 tsync_set_apts(pts);
3317 break;
3318 }
3319 case AMSTREAM_IOC_SET_CRC: {
3320 struct usr_crc_info_t crc_info;
3321 struct vdec_s *vdec;
3322
3323 if (copy_from_user(&crc_info, (void __user *)arg,
3324 sizeof(struct usr_crc_info_t))) {
3325 return -EFAULT;
3326 }
3327 /*
3328 pr_info("id %d, frame %d, y_crc: %08x, uv_crc: %08x\n", crc_info.id,
3329 crc_info.pic_num, crc_info.y_crc, crc_info.uv_crc);
3330 */
3331 vdec = vdec_get_vdec_by_id(crc_info.id);
3332 if (vdec == NULL)
3333 return -ENODEV;
3334 if (vdec->vfc.cmp_pool == NULL) {
3335 vdec->vfc.cmp_pool =
3336 vmalloc(USER_CMP_POOL_MAX_SIZE *
3337 sizeof(struct usr_crc_info_t));
3338 if (vdec->vfc.cmp_pool == NULL)
3339 return -ENOMEM;
3340 }
3341 if (vdec->vfc.usr_cmp_num >= USER_CMP_POOL_MAX_SIZE) {
3342 pr_info("warn: could not write any more, max %d",
3343 USER_CMP_POOL_MAX_SIZE);
3344 return -EFAULT;
3345 }
3346 memcpy(&vdec->vfc.cmp_pool[vdec->vfc.usr_cmp_num], &crc_info,
3347 sizeof(struct usr_crc_info_t));
3348 vdec->vfc.usr_cmp_num++;
3349 break;
3350 }
3351 case AMSTREAM_IOC_GET_CRC_CMP_RESULT: {
3352 int val, vdec_id;
3353 struct vdec_s *vdec;
3354
3355 if (get_user(val, (int __user *)arg)) {
3356 return -EFAULT;
3357 }
3358 vdec_id = val & 0x00ff;
3359 vdec = vdec_get_vdec_by_id(vdec_id);
3360 if (vdec == NULL)
3361 return -ENODEV;
3362 if (val & 0xff00)
3363 put_user(vdec->vfc.usr_cmp_num, (int *)arg);
3364 else
3365 put_user(vdec->vfc.usr_cmp_result, (int *)arg);
3366 /*
3367 pr_info("amstream get crc32 cmpare num %d result: %d\n",
3368 vdec->vfc.usr_cmp_num, vdec->vfc.usr_cmp_result);
3369 */
3370 break;
3371 }
3372 default:
3373 r = -ENOIOCTLCMD;
3374 break;
3375 }
3376
3377 return r;
3378}
3379
3380static long amstream_do_ioctl(struct port_priv_s *priv,
3381 unsigned int cmd, ulong arg)
3382{
3383 long r = 0;
3384
3385 switch (cmd) {
3386 case AMSTREAM_IOC_GET_VERSION:
3387 case AMSTREAM_IOC_GET:
3388 case AMSTREAM_IOC_SET:
3389 case AMSTREAM_IOC_GET_EX:
3390 case AMSTREAM_IOC_SET_EX:
3391 case AMSTREAM_IOC_GET_PTR:
3392 case AMSTREAM_IOC_SET_PTR:
3393 case AMSTREAM_IOC_SYSINFO:
3394 case AMSTREAM_IOC_GET_QOSINFO:
3395 r = amstream_do_ioctl_new(priv, cmd, arg);
3396 break;
3397 default:
3398 r = amstream_do_ioctl_old(priv, cmd, arg);
3399 break;
3400 }
3401 if (r != 0)
3402 pr_err("amstream_do_ioctl error :%lx, %x\n", r, cmd);
3403
3404 return r;
3405}
3406static long amstream_ioctl(struct file *file, unsigned int cmd, ulong arg)
3407{
3408 struct port_priv_s *priv = (struct port_priv_s *)file->private_data;
3409 struct stream_port_s *this = priv->port;
3410
3411 if (!this)
3412 return -ENODEV;
3413
3414 return amstream_do_ioctl(priv, cmd, arg);
3415}
3416
3417#ifdef CONFIG_COMPAT
3418struct dec_sysinfo32 {
3419
3420 u32 format;
3421
3422 u32 width;
3423
3424 u32 height;
3425
3426 u32 rate;
3427
3428 u32 extra;
3429
3430 u32 status;
3431
3432 u32 ratio;
3433
3434 compat_uptr_t param;
3435
3436 u64 ratio64;
3437};
3438
3439struct am_ioctl_parm_ptr32 {
3440 union {
3441 compat_uptr_t pdata_audio_info;
3442 compat_uptr_t pdata_sub_info;
3443 compat_uptr_t pointer;
3444 char data[8];
3445 };
3446 u32 cmd;
3447 u32 len;
3448};
3449
3450static long amstream_ioc_setget_ptr(struct port_priv_s *priv,
3451 unsigned int cmd, struct am_ioctl_parm_ptr32 __user *arg)
3452{
3453 struct am_ioctl_parm_ptr __user *data;
3454 struct am_ioctl_parm_ptr32 param;
3455 int ret;
3456
3457 if (copy_from_user(&param,
3458 (void __user *)arg,
3459 sizeof(struct am_ioctl_parm_ptr32)))
3460 return -EFAULT;
3461
3462 data = compat_alloc_user_space(sizeof(*data));
3463 if (!access_ok(VERIFY_WRITE, data, sizeof(*data)))
3464 return -EFAULT;
3465
3466 if (put_user(param.cmd, &data->cmd) ||
3467 put_user(compat_ptr(param.pointer), &data->pointer) ||
3468 put_user(param.len, &data->len))
3469 return -EFAULT;
3470
3471 ret = amstream_do_ioctl(priv, cmd, (unsigned long)data);
3472 if (ret < 0)
3473 return ret;
3474 return 0;
3475
3476}
3477
3478static long amstream_set_sysinfo(struct port_priv_s *priv,
3479 struct dec_sysinfo32 __user *arg)
3480{
3481 struct dec_sysinfo __user *data;
3482 struct dec_sysinfo32 __user *data32 = arg;
3483 int ret;
3484 struct dec_sysinfo32 param;
3485
3486 if (copy_from_user(&param,
3487 (void __user *)arg,
3488 sizeof(struct dec_sysinfo32)))
3489 return -EFAULT;
3490
3491 data = compat_alloc_user_space(sizeof(*data));
3492 if (!access_ok(VERIFY_WRITE, data, sizeof(*data)))
3493 return -EFAULT;
3494 if (copy_in_user(data, data32, 7 * sizeof(u32)))
3495 return -EFAULT;
3496 if (put_user(compat_ptr(param.param), &data->param))
3497 return -EFAULT;
3498 if (copy_in_user(&data->ratio64, &data32->ratio64,
3499 sizeof(data->ratio64)))
3500 return -EFAULT;
3501
3502 ret = amstream_do_ioctl(priv, AMSTREAM_IOC_SYSINFO,
3503 (unsigned long)data);
3504 if (ret < 0)
3505 return ret;
3506
3507 if (copy_in_user(&arg->format, &data->format, 7 * sizeof(u32)) ||
3508 copy_in_user(&arg->ratio64, &data->ratio64,
3509 sizeof(arg->ratio64)))
3510 return -EFAULT;
3511
3512 return 0;
3513}
3514
3515
3516struct userdata_param32_t {
3517 uint32_t version;
3518 uint32_t instance_id; /*input, 0~9*/
3519 uint32_t buf_len; /*input*/
3520 uint32_t data_size; /*output*/
3521 compat_uptr_t pbuf_addr; /*input*/
3522 struct userdata_meta_info_t meta_info; /*output*/
3523};
3524
3525
3526static long amstream_ioc_get_userdata(struct port_priv_s *priv,
3527 struct userdata_param32_t __user *arg)
3528{
3529 struct userdata_param_t __user *data;
3530 struct userdata_param32_t __user *data32 = arg;
3531 int ret;
3532 struct userdata_param32_t param;
3533
3534
3535 if (copy_from_user(&param,
3536 (void __user *)arg,
3537 sizeof(struct userdata_param32_t)))
3538 return -EFAULT;
3539
3540 data = compat_alloc_user_space(sizeof(*data));
3541 if (!access_ok(VERIFY_WRITE, data, sizeof(*data)))
3542 return -EFAULT;
3543
3544 if (copy_in_user(data, data32, 4 * sizeof(u32)))
3545 return -EFAULT;
3546
3547 if (copy_in_user(&data->meta_info, &data32->meta_info,
3548 sizeof(data->meta_info)))
3549 return -EFAULT;
3550
3551 if (put_user(compat_ptr(param.pbuf_addr), &data->pbuf_addr))
3552 return -EFAULT;
3553
3554 ret = amstream_do_ioctl(priv, AMSTREAM_IOC_UD_BUF_READ,
3555 (unsigned long)data);
3556 if (ret < 0)
3557 return ret;
3558
3559 if (copy_in_user(&data32->version, &data->version, 4 * sizeof(u32)) ||
3560 copy_in_user(&data32->meta_info, &data->meta_info,
3561 sizeof(data32->meta_info)))
3562 return -EFAULT;
3563
3564 return 0;
3565}
3566
3567
3568static long amstream_compat_ioctl(struct file *file,
3569 unsigned int cmd, ulong arg)
3570{
3571 s32 r = 0;
3572 struct port_priv_s *priv = (struct port_priv_s *)file->private_data;
3573
3574 switch (cmd) {
3575 case AMSTREAM_IOC_GET_VERSION:
3576 case AMSTREAM_IOC_GET:
3577 case AMSTREAM_IOC_SET:
3578 case AMSTREAM_IOC_GET_EX:
3579 case AMSTREAM_IOC_SET_EX:
3580 return amstream_do_ioctl(priv, cmd, (ulong)compat_ptr(arg));
3581 case AMSTREAM_IOC_GET_PTR:
3582 case AMSTREAM_IOC_SET_PTR:
3583 return amstream_ioc_setget_ptr(priv, cmd, compat_ptr(arg));
3584 case AMSTREAM_IOC_SYSINFO:
3585 return amstream_set_sysinfo(priv, compat_ptr(arg));
3586 case AMSTREAM_IOC_UD_BUF_READ:
3587 return amstream_ioc_get_userdata(priv, compat_ptr(arg));
3588 default:
3589 return amstream_do_ioctl(priv, cmd, (ulong)compat_ptr(arg));
3590 }
3591
3592 return r;
3593}
3594#endif
3595
3596static ssize_t ports_show(struct class *class, struct class_attribute *attr,
3597 char *buf)
3598{
3599 int i;
3600 char *pbuf = buf;
3601 struct stream_port_s *p = NULL;
3602
3603 for (i = 0; i < amstream_port_num; i++) {
3604 p = &ports[i];
3605 /*name */
3606 pbuf += sprintf(pbuf, "%s\t:\n", p->name);
3607 /*type */
3608 pbuf += sprintf(pbuf, "\ttype:%d( ", p->type);
3609 if (p->type & PORT_TYPE_VIDEO)
3610 pbuf += sprintf(pbuf, "%s ", "Video");
3611 if (p->type & PORT_TYPE_AUDIO)
3612 pbuf += sprintf(pbuf, "%s ", "Audio");
3613 if (p->type & PORT_TYPE_MPTS)
3614 pbuf += sprintf(pbuf, "%s ", "TS");
3615 if (p->type & PORT_TYPE_MPPS)
3616 pbuf += sprintf(pbuf, "%s ", "PS");
3617 if (p->type & PORT_TYPE_ES)
3618 pbuf += sprintf(pbuf, "%s ", "ES");
3619 if (p->type & PORT_TYPE_RM)
3620 pbuf += sprintf(pbuf, "%s ", "RM");
3621 if (p->type & PORT_TYPE_SUB)
3622 pbuf += sprintf(pbuf, "%s ", "Subtitle");
3623 if (p->type & PORT_TYPE_SUB_RD)
3624 pbuf += sprintf(pbuf, "%s ", "Subtitle_Read");
3625 if (p->type & PORT_TYPE_USERDATA)
3626 pbuf += sprintf(pbuf, "%s ", "userdata");
3627 pbuf += sprintf(pbuf, ")\n");
3628 /*flag */
3629 pbuf += sprintf(pbuf, "\tflag:%d( ", p->flag);
3630 if (p->flag & PORT_FLAG_IN_USE)
3631 pbuf += sprintf(pbuf, "%s ", "Used");
3632 else
3633 pbuf += sprintf(pbuf, "%s ", "Unused");
3634 if ((p->type & PORT_TYPE_VIDEO) == 0) {
3635 if (p->flag & PORT_FLAG_INITED)
3636 pbuf += sprintf(pbuf, "%s ", "inited");
3637 else
3638 pbuf += sprintf(pbuf, "%s ", "uninited");
3639 }
3640 pbuf += sprintf(pbuf, ")\n");
3641 /*others */
3642 pbuf += sprintf(pbuf, "\tVformat:%d\n",
3643 (p->flag & PORT_FLAG_VFORMAT) ? p->vformat : -1);
3644 pbuf += sprintf(pbuf, "\tAformat:%d\n",
3645 (p->flag & PORT_FLAG_AFORMAT) ? p->aformat : -1);
3646 pbuf += sprintf(pbuf, "\tVid:%d\n",
3647 (p->flag & PORT_FLAG_VID) ? p->vid : -1);
3648 pbuf += sprintf(pbuf, "\tAid:%d\n",
3649 (p->flag & PORT_FLAG_AID) ? p->aid : -1);
3650 pbuf += sprintf(pbuf, "\tSid:%d\n",
3651 (p->flag & PORT_FLAG_SID) ? p->sid : -1);
3652 pbuf += sprintf(pbuf, "\tPCRid:%d\n",
3653 (p->pcr_inited == 1) ? p->pcrid : -1);
3654 pbuf += sprintf(pbuf, "\tachannel:%d\n", p->achanl);
3655 pbuf += sprintf(pbuf, "\tasamprate:%d\n", p->asamprate);
3656 pbuf += sprintf(pbuf, "\tadatawidth:%d\n\n", p->adatawidth);
3657 }
3658 return pbuf - buf;
3659}
3660
3661static ssize_t bufs_show(struct class *class, struct class_attribute *attr,
3662 char *buf)
3663{
3664 int i;
3665 char *pbuf = buf;
3666 struct stream_buf_s *p = NULL;
3667 char buf_type[][12] = { "Video", "Audio", "Subtitle",
3668 "UserData", "HEVC" };
3669
3670 for (i = 0; i < amstream_buf_num; i++) {
3671 p = &bufs[i];
3672 /*type */
3673 pbuf += sprintf(pbuf, "%s buffer:", buf_type[p->type]);
3674 /*flag */
3675 pbuf += sprintf(pbuf, "\tflag:%d( ", p->flag);
3676 if (p->flag & BUF_FLAG_ALLOC)
3677 pbuf += sprintf(pbuf, "%s ", "Alloc");
3678 else
3679 pbuf += sprintf(pbuf, "%s ", "Unalloc");
3680 if (p->flag & BUF_FLAG_IN_USE)
3681 pbuf += sprintf(pbuf, "%s ", "Used");
3682 else
3683 pbuf += sprintf(pbuf, "%s ", "Noused");
3684 if (p->flag & BUF_FLAG_PARSER)
3685 pbuf += sprintf(pbuf, "%s ", "Parser");
3686 else
3687 pbuf += sprintf(pbuf, "%s ", "noParser");
3688 if (p->flag & BUF_FLAG_FIRST_TSTAMP)
3689 pbuf += sprintf(pbuf, "%s ", "firststamp");
3690 else
3691 pbuf += sprintf(pbuf, "%s ", "nofirststamp");
3692 pbuf += sprintf(pbuf, ")\n");
3693 /*buf stats */
3694
3695 pbuf += sprintf(pbuf, "\tbuf addr:%p\n", (void *)p->buf_start);
3696
3697 if (p->type != BUF_TYPE_SUBTITLE) {
3698 pbuf += sprintf(pbuf, "\tbuf size:%#x\n", p->buf_size);
3699 pbuf += sprintf(pbuf,
3700 "\tbuf canusesize:%#x\n",
3701 p->canusebuf_size);
3702 pbuf += sprintf(pbuf,
3703 "\tbuf regbase:%#lx\n", p->reg_base);
3704
3705 if (p->reg_base && p->flag & BUF_FLAG_IN_USE) {
3706 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
3707 /* TODO: mod gate */
3708 /* switch_mod_gate_by_name("vdec", 1);*/
3709 amports_switch_gate("vdec", 1);
3710 }
3711 pbuf += sprintf(pbuf, "\tbuf level:%#x\n",
3712 stbuf_level(p));
3713 pbuf += sprintf(pbuf, "\tbuf space:%#x\n",
3714 stbuf_space(p));
3715 pbuf += sprintf(pbuf,
3716 "\tbuf read pointer:%#x\n",
3717 stbuf_rp(p));
3718 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
3719 /* TODO: mod gate */
3720 /* switch_mod_gate_by_name("vdec", 0);*/
3721 amports_switch_gate("vdec", 0);
3722 }
3723 } else
3724 pbuf += sprintf(pbuf, "\tbuf no used.\n");
3725
3726 if (p->type == BUF_TYPE_USERDATA) {
3727 pbuf += sprintf(pbuf,
3728 "\tbuf write pointer:%#x\n",
3729 p->buf_wp);
3730 pbuf += sprintf(pbuf,
3731 "\tbuf read pointer:%#x\n",
3732 p->buf_rp);
3733 }
3734 } else {
3735 u32 sub_wp, sub_rp, data_size;
3736
3737 sub_wp = stbuf_sub_wp_get();
3738 sub_rp = stbuf_sub_rp_get();
3739 if (sub_wp >= sub_rp)
3740 data_size = sub_wp - sub_rp;
3741 else
3742 data_size = p->buf_size - sub_rp + sub_wp;
3743 pbuf += sprintf(pbuf, "\tbuf size:%#x\n", p->buf_size);
3744 pbuf +=
3745 sprintf(pbuf, "\tbuf canusesize:%#x\n",
3746 p->canusebuf_size);
3747 pbuf +=
3748 sprintf(pbuf, "\tbuf start:%#x\n",
3749 stbuf_sub_start_get());
3750 pbuf += sprintf(pbuf,
3751 "\tbuf write pointer:%#x\n", sub_wp);
3752 pbuf += sprintf(pbuf,
3753 "\tbuf read pointer:%#x\n", sub_rp);
3754 pbuf += sprintf(pbuf, "\tbuf level:%#x\n", data_size);
3755 }
3756
3757 pbuf += sprintf(pbuf, "\tbuf first_stamp:%#x\n",
3758 p->first_tstamp);
3759 pbuf += sprintf(pbuf, "\tbuf wcnt:%#x\n\n", p->wcnt);
3760 pbuf += sprintf(pbuf, "\tbuf max_buffer_delay_ms:%dms\n",
3761 p->max_buffer_delay_ms);
3762
3763 if (p->reg_base && p->flag & BUF_FLAG_IN_USE) {
3764 int calc_delayms = 0;
3765 u32 bitrate = 0, avg_bitrate = 0;
3766
3767 calc_delayms = calculation_stream_delayed_ms(
3768 (p->type == BUF_TYPE_AUDIO) ? PTS_TYPE_AUDIO :
3769 PTS_TYPE_VIDEO,
3770 &bitrate,
3771 &avg_bitrate);
3772
3773 if (calc_delayms >= 0) {
3774 pbuf += sprintf(pbuf,
3775 "\tbuf current delay:%dms\n",
3776 calc_delayms);
3777 pbuf += sprintf(pbuf,
3778 "\tbuf bitrate latest:%dbps,avg:%dbps\n",
3779 bitrate, avg_bitrate);
3780 pbuf += sprintf(pbuf,
3781 "\tbuf time after last pts:%d ms\n",
3782 calculation_stream_ext_delayed_ms
3783 ((p->type == BUF_TYPE_AUDIO) ? PTS_TYPE_AUDIO :
3784 PTS_TYPE_VIDEO));
3785
3786 pbuf += sprintf(pbuf,
3787 "\tbuf time after last write data :%d ms\n",
3788 (int)(jiffies_64 -
3789 p->last_write_jiffies64) * 1000 / HZ);
3790 }
3791 }
3792 if (p->write_thread) {
3793 pbuf += sprintf(pbuf,
3794 "\twrite thread:%d/%d,fifo %d:%d,passed:%d\n",
3795 threadrw_buffer_level(p),
3796 threadrw_buffer_size(p),
3797 threadrw_datafifo_len(p),
3798 threadrw_freefifo_len(p),
3799 threadrw_passed_len(p)
3800 );
3801 }
3802 }
3803
3804 return pbuf - buf;
3805}
3806
3807static ssize_t videobufused_show(struct class *class,
3808 struct class_attribute *attr, char *buf)
3809{
3810 char *pbuf = buf;
3811 struct stream_buf_s *p = NULL;
3812 struct stream_buf_s *p_hevc = NULL;
3813
3814 p = &bufs[0];
3815 if (has_hevc_vdec())
3816 p_hevc = &bufs[BUF_TYPE_HEVC];
3817
3818 if (p->flag & BUF_FLAG_IN_USE)
3819 pbuf += sprintf(pbuf, "%d ", 1);
3820 else if (has_hevc_vdec() && (p_hevc->flag & BUF_FLAG_IN_USE))
3821 pbuf += sprintf(pbuf, "%d ", 1);
3822 else
3823 pbuf += sprintf(pbuf, "%d ", 0);
3824 return 1;
3825}
3826
3827static ssize_t vcodec_profile_show(struct class *class,
3828 struct class_attribute *attr, char *buf)
3829{
3830 return vcodec_profile_read(buf);
3831}
3832
3833static int reset_canuse_buferlevel(int levelx10000)
3834{
3835 int i;
3836 struct stream_buf_s *p = NULL;
3837
3838 if (levelx10000 >= 0 && levelx10000 <= 10000)
3839 use_bufferlevelx10000 = levelx10000;
3840 else
3841 use_bufferlevelx10000 = 10000;
3842 for (i = 0; i < amstream_buf_num; i++) {
3843 p = &bufs[i];
3844 p->canusebuf_size = ((p->buf_size / 1024) *
3845 use_bufferlevelx10000 / 10000) * 1024;
3846 p->canusebuf_size += 1023;
3847 p->canusebuf_size &= ~1023;
3848 if (p->canusebuf_size > p->buf_size)
3849 p->canusebuf_size = p->buf_size;
3850 }
3851 return 0;
3852}
3853
3854static ssize_t show_canuse_buferlevel(struct class *class,
3855 struct class_attribute *attr, char *buf)
3856{
3857 ssize_t size = sprintf(buf,
3858 "use_bufferlevel=%d/10000[=(set range[ 0~10000])=\n",
3859 use_bufferlevelx10000);
3860 return size;
3861}
3862
3863static ssize_t store_canuse_buferlevel(struct class *class,
3864 struct class_attribute *attr,
3865 const char *buf, size_t size)
3866{
3867 unsigned int val;
3868 ssize_t ret;
3869
3870 /*ret = sscanf(buf, "%d", &val);*/
3871 ret = kstrtoint(buf, 0, &val);
3872
3873 if (ret != 0)
3874 return -EINVAL;
3875 val = val;
3876 reset_canuse_buferlevel(val);
3877 return size;
3878}
3879
3880static ssize_t store_maxdelay(struct class *class,
3881 struct class_attribute *attr,
3882 const char *buf, size_t size)
3883{
3884 unsigned int val;
3885 ssize_t ret;
3886 int i;
3887
3888 /*ret = sscanf(buf, "%d", &val);*/
3889 ret = kstrtoint(buf, 0, &val);
3890 if (ret != 0)
3891 return -EINVAL;
3892 for (i = 0; i < amstream_buf_num; i++)
3893 bufs[i].max_buffer_delay_ms = val;
3894 return size;
3895}
3896
3897static ssize_t show_maxdelay(struct class *class,
3898 struct class_attribute *attr,
3899 char *buf)
3900{
3901 ssize_t size = 0;
3902
3903 size += sprintf(buf, "%dms video max buffered data delay ms\n",
3904 bufs[0].max_buffer_delay_ms);
3905 size += sprintf(buf, "%dms audio max buffered data delay ms\n",
3906 bufs[1].max_buffer_delay_ms);
3907 return size;
3908}
3909
3910static ssize_t audio_path_store(struct class *class,
3911 struct class_attribute *attr,
3912 const char *buf, size_t size)
3913{
3914 unsigned int val = 0;
3915 int i;
3916 ssize_t ret;
3917 struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO];
3918 struct stream_port_s *this;
3919 ret = kstrtoint(buf, 0, &val);
3920 if (ret != 0)
3921 return -EINVAL;
3922 if (val != 1)
3923 return -EINVAL;
3924 for (i = 0; i < MAX_AMSTREAM_PORT_NUM; i++) {
3925 if (strcmp(ports[i].name, "amstream_mpts") == 0 ||
3926 strcmp(ports[i].name, "amstream_mpts_sched") == 0) {
3927 this = &ports[i];
3928 if ((this->flag & PORT_FLAG_AFORMAT) != 0) {
3929 pr_info("audio_port_reset %s\n", ports[i].name);
3930 audio_port_reset(this, pabuf);
3931 }
3932 }
3933 }
3934 return size;
3935}
3936
3937static struct class_attribute amstream_class_attrs[] = {
3938 __ATTR_RO(ports),
3939 __ATTR_RO(bufs),
3940 __ATTR_RO(vcodec_profile),
3941 __ATTR_RO(videobufused),
3942 __ATTR(canuse_buferlevel, S_IRUGO | S_IWUSR | S_IWGRP,
3943 show_canuse_buferlevel, store_canuse_buferlevel),
3944 __ATTR(max_buffer_delay_ms, S_IRUGO | S_IWUSR | S_IWGRP, show_maxdelay,
3945 store_maxdelay),
3946 __ATTR(reset_audio_port, S_IRUGO | S_IWUSR | S_IWGRP,
3947 NULL, audio_path_store),
3948 __ATTR_NULL
3949};
3950
3951static struct class amstream_class = {
3952 .name = "amstream",
3953 .class_attrs = amstream_class_attrs,
3954};
3955
3956int amstream_request_firmware_from_sys(const char *file_name,
3957 char *buf, int size)
3958{
3959 const struct firmware *firmware;
3960 int err = 0;
3961 struct device *micro_dev;
3962
3963 pr_info("try load %s ...", file_name);
3964 micro_dev = device_create(&amstream_class,
3965 NULL, MKDEV(AMSTREAM_MAJOR, 100),
3966 NULL, "videodec");
3967 if (micro_dev == NULL) {
3968 pr_err("device_create failed =%d\n", err);
3969 return -1;
3970 }
3971 err = request_firmware(&firmware, file_name, micro_dev);
3972 if (err < 0) {
3973 pr_err("can't load the %s,err=%d\n", file_name, err);
3974 goto error1;
3975 }
3976 if (firmware->size > size) {
3977 pr_err("not enough memory size for audiodsp code\n");
3978 err = -ENOMEM;
3979 goto release;
3980 }
3981
3982 memcpy(buf, (char *)firmware->data, firmware->size);
3983 /*mb(); don't need it*/
3984 pr_err("load mcode size=%zd\n mcode name %s\n", firmware->size,
3985 file_name);
3986 err = firmware->size;
3987release:
3988 release_firmware(firmware);
3989error1:
3990 device_destroy(&amstream_class, MKDEV(AMSTREAM_MAJOR, 100));
3991 return err;
3992}
3993
3994int videobufused_show_fun(const char *trigger, int id, char *sbuf, int size)
3995{
3996 int ret = -1;
3997 void *buf, *getbuf = NULL;
3998 if (size < PAGE_SIZE) {
3999 getbuf = (void *)__get_free_page(GFP_KERNEL);
4000 if (!getbuf)
4001 return -ENOMEM;
4002 buf = getbuf;
4003 } else {
4004 buf = sbuf;
4005 }
4006
4007 switch (id) {
4008 case 0:
4009 ret = videobufused_show(NULL, NULL , buf);
4010 break;
4011 default:
4012 ret = -1;
4013 }
4014 if (ret > 0 && getbuf != NULL) {
4015 ret = min_t(int, ret, size);
4016 strncpy(sbuf, buf, ret);
4017 }
4018 if (getbuf != NULL)
4019 free_page((unsigned long)getbuf);
4020 return ret;
4021}
4022
4023static struct mconfig amports_configs[] = {
4024 MC_PI32("def_4k_vstreambuf_sizeM", &def_4k_vstreambuf_sizeM),
4025 MC_PI32("def_vstreambuf_sizeM", &def_vstreambuf_sizeM),
4026 MC_PI32("slow_input", &slow_input),
4027 MC_FUN_ID("videobufused", videobufused_show_fun, NULL, 0),
4028};
4029
4030
4031
4032/*static struct resource memobj;*/
4033static int amstream_probe(struct platform_device *pdev)
4034{
4035 int i;
4036 int r;
4037 struct stream_port_s *st;
4038
4039 pr_err("Amlogic A/V streaming port init\n");
4040
4041 amstream_port_num = MAX_AMSTREAM_PORT_NUM;
4042 amstream_buf_num = BUF_MAX_NUM;
4043/*
4044 * r = of_reserved_mem_device_init(&pdev->dev);
4045 * if (r == 0)
4046 * pr_info("of probe done");
4047 * else {
4048 * r = -ENOMEM;
4049 * return r;
4050 * }
4051 */
4052 r = class_register(&amstream_class);
4053 if (r) {
4054 pr_err("amstream class create fail.\n");
4055 return r;
4056 }
4057
4058 r = astream_dev_register();
4059 if (r)
4060 return r;
4061
4062 r = register_chrdev(AMSTREAM_MAJOR, "amstream", &amstream_fops);
4063 if (r < 0) {
4064 pr_err("Can't allocate major for amstreaming device\n");
4065
4066 goto error2;
4067 }
4068
4069 amstream_dev_class = class_create(THIS_MODULE, DEVICE_NAME);
4070
4071 for (st = &ports[0], i = 0; i < amstream_port_num; i++, st++) {
4072 st->class_dev = device_create(amstream_dev_class, NULL,
4073 MKDEV(AMSTREAM_MAJOR, i), NULL,
4074 ports[i].name);
4075 }
4076
4077 amstream_adec_status = NULL;
4078 if (tsdemux_class_register() != 0) {
4079 r = (-EIO);
4080 goto error3;
4081 }
4082 tsdemux_tsync_func_init();
4083 init_waitqueue_head(&amstream_sub_wait);
4084 init_waitqueue_head(&amstream_userdata_wait);
4085 reset_canuse_buferlevel(10000);
4086 amstream_pdev = pdev;
4087 amports_clock_gate_init(&amstream_pdev->dev);
4088
4089 /*prealloc fetch buf to avoid no continue buffer later...*/
4090 stbuf_fetch_init();
4091 REG_PATH_CONFIGS("media.amports", amports_configs);
4092
4093 /* poweroff the decode core because dos can not be reset when reboot */
4094 if (get_cpu_major_id() == AM_MESON_CPU_MAJOR_ID_G12A)
4095 vdec_power_reset();
4096
4097 return 0;
4098
4099 /*
4100 * error4:
4101 * tsdemux_class_unregister();
4102 */
4103error3:
4104 for (st = &ports[0], i = 0; i < amstream_port_num; i++, st++)
4105 device_destroy(amstream_dev_class, MKDEV(AMSTREAM_MAJOR, i));
4106 class_destroy(amstream_dev_class);
4107error2:
4108 unregister_chrdev(AMSTREAM_MAJOR, "amstream");
4109 /* error1: */
4110 astream_dev_unregister();
4111 return r;
4112}
4113
4114static int amstream_remove(struct platform_device *pdev)
4115{
4116 int i;
4117 struct stream_port_s *st;
4118
4119 if (bufs[BUF_TYPE_VIDEO].flag & BUF_FLAG_ALLOC)
4120 stbuf_change_size(&bufs[BUF_TYPE_VIDEO], 0, false);
4121 if (bufs[BUF_TYPE_AUDIO].flag & BUF_FLAG_ALLOC)
4122 stbuf_change_size(&bufs[BUF_TYPE_AUDIO], 0, false);
4123 stbuf_fetch_release();
4124 tsdemux_class_unregister();
4125 for (st = &ports[0], i = 0; i < amstream_port_num; i++, st++)
4126 device_destroy(amstream_dev_class, MKDEV(AMSTREAM_MAJOR, i));
4127
4128 class_destroy(amstream_dev_class);
4129
4130 unregister_chrdev(AMSTREAM_MAJOR, "amstream");
4131
4132 class_unregister(&amstream_class);
4133
4134 astream_dev_unregister();
4135
4136 amstream_adec_status = NULL;
4137
4138 pr_err("Amlogic A/V streaming port release\n");
4139
4140 return 0;
4141}
4142
4143void set_adec_func(int (*adec_func)(struct adec_status *))
4144{
4145 amstream_adec_status = adec_func;
4146}
4147
4148void wakeup_sub_poll(void)
4149{
4150 atomic_inc(&subdata_ready);
4151 wake_up_interruptible(&amstream_sub_wait);
4152}
4153
4154int get_sub_type(void)
4155{
4156 return sub_type;
4157}
4158
4159u32 get_audio_reset(void)
4160{
4161 return amstream_audio_reset;
4162}
4163
4164/*get pes buffers */
4165
4166struct stream_buf_s *get_stream_buffer(int id)
4167{
4168 if (id >= BUF_MAX_NUM)
4169 return 0;
4170 return &bufs[id];
4171}
4172EXPORT_SYMBOL(get_stream_buffer);
4173static const struct of_device_id amlogic_mesonstream_dt_match[] = {
4174 {
4175 .compatible = "amlogic, codec, streambuf",
4176 },
4177 {},
4178};
4179
4180static struct platform_driver amstream_driver = {
4181 .probe = amstream_probe,
4182 .remove = amstream_remove,
4183 .driver = {
4184 .owner = THIS_MODULE,
4185 .name = "mesonstream",
4186 .of_match_table = amlogic_mesonstream_dt_match,
4187 }
4188};
4189
4190static int __init amstream_module_init(void)
4191{
4192 if (platform_driver_register(&amstream_driver)) {
4193 pr_err("failed to register amstream module\n");
4194 return -ENODEV;
4195 }
4196
4197 if (subtitle_init()) {
4198 pr_err("failed to init subtitle\n");
4199 return -ENODEV;
4200 }
4201
4202 return 0;
4203}
4204
4205static void __exit amstream_module_exit(void)
4206{
4207 platform_driver_unregister(&amstream_driver);
4208 subtitle_exit();
4209}
4210
4211module_init(amstream_module_init);
4212module_exit(amstream_module_exit);
4213
4214module_param(def_4k_vstreambuf_sizeM, uint, 0664);
4215MODULE_PARM_DESC(def_4k_vstreambuf_sizeM,
4216 "\nDefault video Stream buf size for 4K MByptes\n");
4217
4218module_param(def_vstreambuf_sizeM, uint, 0664);
4219MODULE_PARM_DESC(def_vstreambuf_sizeM,
4220 "\nDefault video Stream buf size for < 1080p MByptes\n");
4221
4222module_param(slow_input, uint, 0664);
4223MODULE_PARM_DESC(slow_input, "\n amstream slow_input\n");
4224
4225
4226MODULE_DESCRIPTION("AMLOGIC streaming port driver");
4227MODULE_LICENSE("GPL");
4228MODULE_AUTHOR("Tim Yao <timyao@amlogic.com>");
4229