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