summaryrefslogtreecommitdiff
path: root/drivers/stream_input/parser/tsdemux.c (plain)
blob: 600c44a4773097cb5e3a90bc9cab8b537782f7a2
1/*
2 * drivers/amlogic/media/stream_input/parser/tsdemux.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
18#include <linux/kernel.h>
19#include <linux/types.h>
20#include <linux/errno.h>
21#include <linux/interrupt.h>
22#include <linux/wait.h>
23#include <linux/sched.h>
24#include <linux/fs.h>
25#include <linux/dma-mapping.h>
26#include <linux/amlogic/media/frame_sync/ptsserv.h>
27#include <linux/amlogic/media/utils/amstream.h>
28#include <linux/amlogic/media/vfm/vframe_provider.h>
29#include <linux/device.h>
30#include <linux/delay.h>
31
32#include <linux/uaccess.h>
33/* #include <mach/am_regs.h> */
34#include <linux/clk.h>
35/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
36/* #include <mach/mod_gate.h> */
37/* #endif */
38
39#include "../../frame_provider/decoder/utils/vdec.h"
40#include <linux/amlogic/media/utils/vdec_reg.h>
41#include "streambuf_reg.h"
42#include "streambuf.h"
43#include <linux/amlogic/media/utils/amports_config.h>
44
45#include "tsdemux.h"
46#include <linux/reset.h>
47#include "../amports/amports_priv.h"
48
49
50static const char tsdemux_fetch_id[] = "tsdemux-fetch-id";
51static const char tsdemux_irq_id[] = "tsdemux-irq-id";
52
53static u32 curr_pcr_num = 0xffff;
54static u32 curr_vid_id = 0xffff;
55static u32 curr_aud_id = 0xffff;
56static u32 curr_sub_id = 0xffff;
57static u32 curr_pcr_id = 0xffff;
58
59static DECLARE_WAIT_QUEUE_HEAD(wq);
60static u32 fetch_done;
61static u32 discontinued_counter;
62static u32 first_pcr;
63static u8 pcrscr_valid;
64
65static int demux_skipbyte;
66
67static struct tsdemux_ops *demux_ops;
68static DEFINE_SPINLOCK(demux_ops_lock);
69
70static int enable_demux_driver(void)
71{
72#ifdef ENABLE_DEMUX_DRIVER
73 return demux_ops ? 1 : 0;
74#else
75 return 0;
76#endif
77}
78
79void tsdemux_set_ops(struct tsdemux_ops *ops)
80{
81 unsigned long flags;
82
83 spin_lock_irqsave(&demux_ops_lock, flags);
84 demux_ops = ops;
85 spin_unlock_irqrestore(&demux_ops_lock, flags);
86}
87EXPORT_SYMBOL(tsdemux_set_ops);
88
89int tsdemux_set_reset_flag_ext(void)
90{
91 int r = 0;
92
93 if (demux_ops && demux_ops->set_reset_flag)
94 r = demux_ops->set_reset_flag();
95
96 return r;
97}
98
99int tsdemux_set_reset_flag(void)
100{
101 unsigned long flags;
102 int r;
103
104 spin_lock_irqsave(&demux_ops_lock, flags);
105 r = tsdemux_set_reset_flag_ext();
106 spin_unlock_irqrestore(&demux_ops_lock, flags);
107
108 return r;
109}
110
111static int tsdemux_reset(void)
112{
113 unsigned long flags;
114 int r;
115
116 spin_lock_irqsave(&demux_ops_lock, flags);
117 if (demux_ops && demux_ops->reset) {
118 tsdemux_set_reset_flag_ext();
119 r = demux_ops->reset();
120 }
121 spin_unlock_irqrestore(&demux_ops_lock, flags);
122
123 return r;
124}
125
126static int tsdemux_request_irq(irq_handler_t handler, void *data)
127{
128 unsigned long flags;
129 int r;
130
131 spin_lock_irqsave(&demux_ops_lock, flags);
132 if (demux_ops && demux_ops->request_irq)
133 r = demux_ops->request_irq(handler, data);
134 spin_unlock_irqrestore(&demux_ops_lock, flags);
135
136 return r;
137}
138
139static int tsdemux_free_irq(void)
140{
141 unsigned long flags;
142 int r;
143
144 spin_lock_irqsave(&demux_ops_lock, flags);
145 if (demux_ops && demux_ops->free_irq)
146 r = demux_ops->free_irq();
147 spin_unlock_irqrestore(&demux_ops_lock, flags);
148
149 return r;
150}
151
152static int tsdemux_set_vid(int vpid)
153{
154 unsigned long flags;
155 int r = 0;
156
157 spin_lock_irqsave(&demux_ops_lock, flags);
158 if (demux_ops && demux_ops->set_vid)
159 r = demux_ops->set_vid(vpid);
160 spin_unlock_irqrestore(&demux_ops_lock, flags);
161
162 return r;
163}
164
165static int tsdemux_set_aid(int apid)
166{
167 unsigned long flags;
168 int r = 0;
169
170 spin_lock_irqsave(&demux_ops_lock, flags);
171 if (demux_ops && demux_ops->set_aid)
172 r = demux_ops->set_aid(apid);
173 spin_unlock_irqrestore(&demux_ops_lock, flags);
174
175 return r;
176}
177
178static int tsdemux_set_sid(int spid)
179{
180 unsigned long flags;
181 int r = 0;
182
183 spin_lock_irqsave(&demux_ops_lock, flags);
184 if (demux_ops && demux_ops->set_sid)
185 r = demux_ops->set_sid(spid);
186 spin_unlock_irqrestore(&demux_ops_lock, flags);
187
188 return r;
189}
190
191static int tsdemux_set_pcrid(int pcrpid)
192{
193 unsigned long flags;
194 int r = 0;
195
196 spin_lock_irqsave(&demux_ops_lock, flags);
197 if (demux_ops && demux_ops->set_pcrid)
198 r = demux_ops->set_pcrid(pcrpid);
199 spin_unlock_irqrestore(&demux_ops_lock, flags);
200
201 return r;
202}
203
204static int tsdemux_set_skip_byte(int skipbyte)
205{
206 unsigned long flags;
207 int r = 0;
208
209 spin_lock_irqsave(&demux_ops_lock, flags);
210 if (demux_ops && demux_ops->set_skipbyte)
211 r = demux_ops->set_skipbyte(skipbyte);
212 spin_unlock_irqrestore(&demux_ops_lock, flags);
213
214 return r;
215}
216
217static int tsdemux_config(void)
218{
219 return 0;
220}
221
222/*TODO irq*/
223static irqreturn_t tsdemux_isr(int irq, void *dev_id)
224{
225 u32 int_status = 0;
226 int id = (long)dev_id;
227
228 if (!enable_demux_driver()) {
229 int_status = READ_DEMUX_REG(STB_INT_STATUS);
230 } else {
231 if (id == 0)
232 int_status = READ_DEMUX_REG(STB_INT_STATUS);
233 else if (id == 1)
234 int_status = READ_DEMUX_REG(STB_INT_STATUS_2);
235 else if (id == 2)
236 int_status = READ_DEMUX_REG(STB_INT_STATUS_3);
237 }
238
239 if (int_status & (1 << NEW_PDTS_READY)) {
240 if (!enable_demux_driver()) {
241 u32 pdts_status = READ_DEMUX_REG(STB_PTS_DTS_STATUS);
242
243 if (pdts_status & (1 << VIDEO_PTS_READY))
244 pts_checkin_wrptr(PTS_TYPE_VIDEO,
245 READ_DEMUX_REG(VIDEO_PDTS_WR_PTR),
246 READ_DEMUX_REG(VIDEO_PTS_DEMUX));
247
248 if (pdts_status & (1 << AUDIO_PTS_READY))
249 pts_checkin_wrptr(PTS_TYPE_AUDIO,
250 READ_DEMUX_REG(AUDIO_PDTS_WR_PTR),
251 READ_DEMUX_REG(AUDIO_PTS_DEMUX));
252
253 WRITE_DEMUX_REG(STB_PTS_DTS_STATUS, pdts_status);
254 } else {
255#define DMX_READ_REG(i, r)\
256 ((i) ? ((i == 1) ? READ_DEMUX_REG(r##_2) : \
257 READ_DEMUX_REG(r##_3)) : READ_DEMUX_REG(r))
258
259 u32 pdts_status = DMX_READ_REG(id, STB_PTS_DTS_STATUS);
260
261 if (pdts_status & (1 << VIDEO_PTS_READY))
262 pts_checkin_wrptr(PTS_TYPE_VIDEO,
263 DMX_READ_REG(id, VIDEO_PDTS_WR_PTR),
264 DMX_READ_REG(id, VIDEO_PTS_DEMUX));
265
266 if (pdts_status & (1 << AUDIO_PTS_READY))
267 pts_checkin_wrptr(PTS_TYPE_AUDIO,
268 DMX_READ_REG(id, AUDIO_PDTS_WR_PTR),
269 DMX_READ_REG(id, AUDIO_PTS_DEMUX));
270
271 if (id == 1)
272 WRITE_DEMUX_REG(STB_PTS_DTS_STATUS_2,
273 pdts_status);
274 else if (id == 2)
275 WRITE_DEMUX_REG(STB_PTS_DTS_STATUS_3,
276 pdts_status);
277 else
278 WRITE_DEMUX_REG(STB_PTS_DTS_STATUS,
279 pdts_status);
280 }
281 }
282 if (int_status & (1 << DIS_CONTINUITY_PACKET)) {
283 discontinued_counter++;
284 /* pr_info("discontinued counter=%d\n",discontinued_counter); */
285 }
286 if (int_status & (1 << SUB_PES_READY)) {
287 /* TODO: put data to somewhere */
288 /* pr_info("subtitle pes ready\n"); */
289 wakeup_sub_poll();
290 }
291
292 if (!enable_demux_driver())
293 WRITE_DEMUX_REG(STB_INT_STATUS, int_status);
294
295 return IRQ_HANDLED;
296}
297
298static irqreturn_t parser_isr(int irq, void *dev_id)
299{
300 u32 int_status = READ_PARSER_REG(PARSER_INT_STATUS);
301
302 WRITE_PARSER_REG(PARSER_INT_STATUS, int_status);
303
304 if (int_status & PARSER_INTSTAT_FETCH_CMD) {
305 fetch_done = 1;
306
307 wake_up_interruptible(&wq);
308 }
309
310 return IRQ_HANDLED;
311}
312
313static ssize_t _tsdemux_write(const char __user *buf, size_t count,
314 int isphybuf)
315{
316 size_t r = count;
317 const char __user *p = buf;
318 u32 len;
319 int ret;
320 dma_addr_t dma_addr = 0;
321
322 if (r > 0) {
323 if (isphybuf)
324 len = count;
325 else {
326 len = min_t(size_t, r, FETCHBUF_SIZE);
327 if (copy_from_user(fetchbuf, p, len))
328 return -EFAULT;
329
330 dma_addr =
331 dma_map_single(amports_get_dma_device(),
332 fetchbuf,
333 FETCHBUF_SIZE, DMA_TO_DEVICE);
334 if (dma_mapping_error(amports_get_dma_device(),
335 dma_addr))
336 return -EFAULT;
337
338
339 }
340
341 fetch_done = 0;
342
343 wmb(); /* Ensure fetchbuf contents visible */
344
345 if (isphybuf) {
346 u32 buf_32 = (unsigned long)buf & 0xffffffff;
347 WRITE_PARSER_REG(PARSER_FETCH_ADDR, buf_32);
348 } else {
349 WRITE_PARSER_REG(PARSER_FETCH_ADDR, dma_addr);
350 dma_unmap_single(amports_get_dma_device(), dma_addr,
351 FETCHBUF_SIZE, DMA_TO_DEVICE);
352 }
353
354 WRITE_PARSER_REG(PARSER_FETCH_CMD, (7 << FETCH_ENDIAN) | len);
355
356
357 ret =
358 wait_event_interruptible_timeout(wq, fetch_done != 0,
359 HZ / 2);
360 if (ret == 0) {
361 WRITE_PARSER_REG(PARSER_FETCH_CMD, 0);
362 pr_info("write timeout, retry\n");
363 return -EAGAIN;
364 } else if (ret < 0)
365 return -ERESTARTSYS;
366
367 p += len;
368 r -= len;
369 }
370
371 return count - r;
372}
373
374static int reset_pcr_regs(void)
375{
376 u32 pcr_num;
377
378 if (curr_pcr_id >= 0x1FFF)
379 return 0;
380
381 /* set parameter to fetch pcr */
382 pcr_num = 0;
383 if (curr_pcr_id == curr_vid_id)
384 pcr_num = 0;
385 else if (curr_pcr_id == curr_aud_id)
386 pcr_num = 1;
387 else if (curr_pcr_id == curr_sub_id)
388 pcr_num = 2;
389 else
390 pcr_num = 3;
391
392 if (pcr_num != curr_pcr_num) {
393 u32 clk_unit = 0;
394 u32 clk_81 = 0;
395 struct clk *clk;
396
397 clk = clk_get_sys("clk81", "clk81");
398 if (IS_ERR(clk) || clk == 0) {
399 pr_info("[%s:%d] error clock\n", __func__,
400 __LINE__);
401 return 0;
402 }
403
404 clk_81 = clk_get_rate(clk);
405 clk_unit = clk_81 / 80000;
406
407 pr_info("[%s:%d] clk_81 = %x clk_unit =%x\n", __func__,
408 __LINE__, clk_81, clk_unit);
409
410 if (READ_DEMUX_REG(TS_HIU_CTL_2) & 0x80) {
411 WRITE_DEMUX_REG(PCR90K_CTL_2, (12 << 1) | clk_unit);
412 WRITE_DEMUX_REG(ASSIGN_PID_NUMBER_2, pcr_num);
413 pr_info("[tsdemux_init] To use device 2,pcr_num=%d\n",
414 pcr_num);
415 } else if (READ_DEMUX_REG(TS_HIU_CTL_3) & 0x80) {
416 WRITE_DEMUX_REG(PCR90K_CTL_3, (12 << 1) | clk_unit);
417 WRITE_DEMUX_REG(ASSIGN_PID_NUMBER_3, pcr_num);
418 pr_info("[tsdemux_init] To use device 3,pcr_num=%d\n",
419 pcr_num);
420 } else {
421 WRITE_DEMUX_REG(PCR90K_CTL, (12 << 1) | clk_unit);
422 WRITE_DEMUX_REG(ASSIGN_PID_NUMBER, pcr_num);
423 pr_info("[tsdemux_init] To use device 1,pcr_num=%d\n",
424 pcr_num);
425 }
426
427 curr_pcr_num = pcr_num;
428 }
429
430 return 1;
431}
432
433s32 tsdemux_init(u32 vid, u32 aid, u32 sid, u32 pcrid, bool is_hevc,
434 struct vdec_s *vdec)
435{
436 s32 r;
437 u32 parser_sub_start_ptr;
438 u32 parser_sub_end_ptr;
439 u32 parser_sub_rp;
440
441 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
442 /*TODO clk */
443 /*
444 *switch_mod_gate_by_type(MOD_DEMUX, 1);
445 */
446 /* #endif */
447
448 amports_switch_gate("demux", 1);
449
450 parser_sub_start_ptr = READ_PARSER_REG(PARSER_SUB_START_PTR);
451 parser_sub_end_ptr = READ_PARSER_REG(PARSER_SUB_END_PTR);
452 parser_sub_rp = READ_PARSER_REG(PARSER_SUB_RP);
453
454 WRITE_RESET_REG(RESET1_REGISTER, RESET_PARSER);
455
456 if (enable_demux_driver()) {
457 tsdemux_reset();
458 } else {
459 WRITE_RESET_REG(RESET1_REGISTER, RESET_PARSER | RESET_DEMUXSTB);
460
461 WRITE_DEMUX_REG(STB_TOP_CONFIG, 0);
462 WRITE_DEMUX_REG(DEMUX_CONTROL, 0);
463 }
464
465 /* set PID filter */
466 pr_info
467 ("tsdemux video_pid = 0x%x, audio_pid = 0x%x,",
468 vid, aid);
469 pr_info
470 ("sub_pid = 0x%x, pcrid = 0x%x\n",
471 sid, pcrid);
472
473 if (!enable_demux_driver()) {
474 WRITE_DEMUX_REG(FM_WR_DATA,
475 (((vid < 0x1fff)
476 ? (vid & 0x1fff) | (VIDEO_PACKET << 13)
477 : 0xffff) << 16)
478 | ((aid < 0x1fff)
479 ? (aid & 0x1fff) | (AUDIO_PACKET << 13)
480 : 0xffff));
481 WRITE_DEMUX_REG(FM_WR_ADDR, 0x8000);
482 while (READ_DEMUX_REG(FM_WR_ADDR) & 0x8000)
483 ;
484
485 WRITE_DEMUX_REG(FM_WR_DATA,
486 (((sid < 0x1fff)
487 ? (sid & 0x1fff) | (SUB_PACKET << 13)
488 : 0xffff) << 16)
489 | 0xffff);
490 WRITE_DEMUX_REG(FM_WR_ADDR, 0x8001);
491 while (READ_DEMUX_REG(FM_WR_ADDR) & 0x8000)
492 ;
493
494 WRITE_DEMUX_REG(MAX_FM_COMP_ADDR, 1);
495
496 WRITE_DEMUX_REG(STB_INT_MASK, 0);
497 WRITE_DEMUX_REG(STB_INT_STATUS, 0xffff);
498
499 /* TS data path */
500 WRITE_DEMUX_REG(FEC_INPUT_CONTROL, 0x7000);
501 WRITE_DEMUX_REG(DEMUX_MEM_REQ_EN,
502 (1 << VIDEO_PACKET) |
503 (1 << AUDIO_PACKET) | (1 << SUB_PACKET));
504 WRITE_DEMUX_REG(DEMUX_ENDIAN,
505 (7 << OTHER_ENDIAN) |
506 (7 << BYPASS_ENDIAN) | (0 << SECTION_ENDIAN));
507 WRITE_DEMUX_REG(TS_HIU_CTL, 1 << USE_HI_BSF_INTERFACE);
508 WRITE_DEMUX_REG(TS_FILE_CONFIG,
509 (demux_skipbyte << 16) |
510 (6 << DES_OUT_DLY) |
511 (3 << TRANSPORT_SCRAMBLING_CONTROL_ODD) |
512 (1 << TS_HIU_ENABLE) | (4 << FEC_FILE_CLK_DIV));
513
514 /* enable TS demux */
515 WRITE_DEMUX_REG(DEMUX_CONTROL,
516 (1 << STB_DEMUX_ENABLE) |
517 (1 << KEEP_DUPLICATE_PACKAGE));
518 }
519
520 if (fetchbuf == 0) {
521 pr_info("%s: no fetchbuf\n", __func__);
522 return -ENOMEM;
523 }
524
525 /* hook stream buffer with PARSER */
526 if (has_hevc_vdec() && is_hevc) {
527 WRITE_PARSER_REG(PARSER_VIDEO_START_PTR, vdec->input.start);
528 WRITE_PARSER_REG(PARSER_VIDEO_END_PTR, vdec->input.start +
529 vdec->input.size - 8);
530
531 if (vdec_single(vdec)) {
532 CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL,
533 ES_VID_MAN_RD_PTR);
534 /* set vififo_vbuf_rp_sel=>hevc */
535 WRITE_VREG(DOS_GEN_CTRL0, 3 << 1);
536 /* set use_parser_vbuf_wp */
537 SET_VREG_MASK(HEVC_STREAM_CONTROL,
538 (1 << 3) | (0 << 4));
539 /* set stream_fetch_enable */
540 SET_VREG_MASK(HEVC_STREAM_CONTROL, 1);
541 /* set stream_buffer_hole with 256 bytes */
542 SET_VREG_MASK(HEVC_STREAM_FIFO_CTL,
543 (1 << 29));
544 } else {
545 SET_PARSER_REG_MASK(PARSER_ES_CONTROL,
546 ES_VID_MAN_RD_PTR);
547 WRITE_PARSER_REG(PARSER_VIDEO_WP, vdec->input.start);
548 WRITE_PARSER_REG(PARSER_VIDEO_RP, vdec->input.start);
549 }
550 } else {
551 WRITE_PARSER_REG(PARSER_VIDEO_START_PTR, vdec->input.start);
552 WRITE_PARSER_REG(PARSER_VIDEO_END_PTR, vdec->input.start +
553 vdec->input.size - 8);
554
555 if (vdec_single(vdec)) {
556 CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL,
557 ES_VID_MAN_RD_PTR);
558
559 WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
560 CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL,
561 MEM_BUFCTRL_INIT);
562 /* set vififo_vbuf_rp_sel=>vdec */
563 if (has_hevc_vdec())
564 WRITE_VREG(DOS_GEN_CTRL0, 0);
565 } else {
566 SET_PARSER_REG_MASK(PARSER_ES_CONTROL,
567 ES_VID_MAN_RD_PTR);
568 WRITE_PARSER_REG(PARSER_VIDEO_WP, vdec->input.start);
569 WRITE_PARSER_REG(PARSER_VIDEO_RP, vdec->input.start);
570 }
571 }
572
573 WRITE_PARSER_REG(PARSER_AUDIO_START_PTR,
574 READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
575 WRITE_PARSER_REG(PARSER_AUDIO_END_PTR,
576 READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR));
577 CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR);
578
579 WRITE_PARSER_REG(PARSER_CONFIG,
580 (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) |
581 (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) |
582 (16 << PS_CFG_MAX_FETCH_CYCLE_BIT));
583
584 WRITE_AIU_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
585 CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
586
587 WRITE_PARSER_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr);
588 WRITE_PARSER_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr);
589 WRITE_PARSER_REG(PARSER_SUB_RP, parser_sub_rp);
590 SET_PARSER_REG_MASK(PARSER_ES_CONTROL,
591 (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR);
592
593 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
594 if (has_hevc_vdec())
595 r = pts_start((is_hevc) ? PTS_TYPE_HEVC : PTS_TYPE_VIDEO);
596 else
597 /* #endif */
598 r = pts_start(PTS_TYPE_VIDEO);
599
600 if (r < 0) {
601 pr_info("Video pts start failed.(%d)\n", r);
602 goto err1;
603 }
604 r = pts_start(PTS_TYPE_AUDIO);
605 if (r < 0) {
606 pr_info("Audio pts start failed.(%d)\n", r);
607 goto err2;
608 }
609 /*TODO irq */
610
611 r = vdec_request_irq(PARSER_IRQ, parser_isr,
612 "tsdemux-fetch", (void *)tsdemux_fetch_id);
613
614 if (r)
615 goto err3;
616
617 WRITE_PARSER_REG(PARSER_INT_STATUS, 0xffff);
618 WRITE_PARSER_REG(PARSER_INT_ENABLE,
619 PARSER_INTSTAT_FETCH_CMD << PARSER_INT_HOST_EN_BIT);
620
621 WRITE_PARSER_REG(PARSER_VIDEO_HOLE, 0x400);
622 WRITE_PARSER_REG(PARSER_AUDIO_HOLE, 0x400);
623
624 discontinued_counter = 0;
625
626 if (!enable_demux_driver()) {
627 /*TODO irq */
628
629 r = vdec_request_irq(DEMUX_IRQ, tsdemux_isr,
630 "tsdemux-irq", (void *)tsdemux_irq_id);
631
632 WRITE_DEMUX_REG(STB_INT_MASK, (1 << SUB_PES_READY)
633 | (1 << NEW_PDTS_READY)
634 | (1 << DIS_CONTINUITY_PACKET));
635 if (r)
636 goto err4;
637 } else {
638 tsdemux_config();
639 tsdemux_request_irq(tsdemux_isr, (void *)tsdemux_irq_id);
640 if (vid < 0x1FFF) {
641 curr_vid_id = vid;
642 tsdemux_set_vid(vid);
643 }
644 if (aid < 0x1FFF) {
645 curr_aud_id = aid;
646 tsdemux_set_aid(aid);
647 }
648 if (sid < 0x1FFF) {
649 curr_sub_id = sid;
650 tsdemux_set_sid(sid);
651 }
652
653 curr_pcr_id = pcrid;
654 if ((pcrid < 0x1FFF) && (pcrid != vid) && (pcrid != aid)
655 && (pcrid != sid))
656 tsdemux_set_pcrid(pcrid);
657 }
658
659 pcrscr_valid = reset_pcr_regs();
660 first_pcr = 0;
661
662 return 0;
663
664err4:
665 /*TODO irq */
666
667 if (!enable_demux_driver())
668 vdec_free_irq(PARSER_IRQ, (void *)tsdemux_fetch_id);
669
670err3:
671 pts_stop(PTS_TYPE_AUDIO);
672err2:
673 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
674 if (has_hevc_vdec())
675 pts_stop((is_hevc) ? PTS_TYPE_HEVC : PTS_TYPE_VIDEO);
676 else
677 /* #endif */
678 pts_stop(PTS_TYPE_VIDEO);
679err1:
680 pr_info("TS Demux init failed.\n");
681 return -ENOENT;
682}
683
684void tsdemux_release(void)
685{
686 pcrscr_valid = 0;
687 first_pcr = 0;
688
689 WRITE_PARSER_REG(PARSER_INT_ENABLE, 0);
690 WRITE_PARSER_REG(PARSER_VIDEO_HOLE, 0);
691 WRITE_PARSER_REG(PARSER_AUDIO_HOLE, 0);
692
693#ifdef CONFIG_AMLOGIC_MEDIA_MULTI_DEC
694 SET_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR);
695 WRITE_PARSER_REG(PARSER_VIDEO_WP, 0);
696 WRITE_PARSER_REG(PARSER_VIDEO_RP, 0);
697#endif
698
699 /*TODO irq */
700
701 vdec_free_irq(PARSER_IRQ, (void *)tsdemux_fetch_id);
702
703 if (!enable_demux_driver()) {
704 WRITE_DEMUX_REG(STB_INT_MASK, 0);
705 /*TODO irq */
706
707 vdec_free_irq(DEMUX_IRQ, (void *)tsdemux_irq_id);
708 } else {
709
710 tsdemux_set_aid(0xffff);
711 tsdemux_set_vid(0xffff);
712 tsdemux_set_sid(0xffff);
713 tsdemux_set_pcrid(0xffff);
714 tsdemux_free_irq();
715
716 curr_vid_id = 0xffff;
717 curr_aud_id = 0xffff;
718 curr_sub_id = 0xffff;
719 curr_pcr_id = 0xffff;
720 curr_pcr_num = 0xffff;
721 }
722
723 pts_stop(PTS_TYPE_VIDEO);
724 pts_stop(PTS_TYPE_AUDIO);
725
726 WRITE_RESET_REG(RESET1_REGISTER, RESET_PARSER);
727#ifdef CONFIG_MULTI_DEC
728 SET_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR);
729 WRITE_PARSER_REG(PARSER_VIDEO_WP, 0);
730 WRITE_PARSER_REG(PARSER_VIDEO_RP, 0);
731#endif
732
733 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
734 /*TODO clk */
735 /*
736 *switch_mod_gate_by_type(MOD_DEMUX, 0);
737 */
738 /* #endif */
739 amports_switch_gate("demux", 0);
740}
741
742static int limited_delay_check(struct file *file,
743 struct stream_buf_s *vbuf,
744 struct stream_buf_s *abuf,
745 const char __user *buf, size_t count)
746{
747 int write_size;
748
749 if (vbuf->max_buffer_delay_ms > 0 && abuf->max_buffer_delay_ms > 0 &&
750 stbuf_level(vbuf) > 1024 && stbuf_level(abuf) > 256) {
751 int vdelay =
752 calculation_stream_delayed_ms(PTS_TYPE_VIDEO,
753 NULL, NULL);
754 int adelay =
755 calculation_stream_delayed_ms(PTS_TYPE_AUDIO,
756 NULL, NULL);
757 /*max wait 100ms,if timeout,try again top level. */
758 int maxretry = 10;
759 /*too big delay,do wait now. */
760 /*if noblock mode,don't do wait. */
761 if (!(file->f_flags & O_NONBLOCK)) {
762 while (vdelay > vbuf->max_buffer_delay_ms
763 && adelay > abuf->max_buffer_delay_ms
764 && maxretry-- > 0) {
765 msleep(20);
766 vdelay =
767 calculation_stream_delayed_ms
768 (PTS_TYPE_VIDEO, NULL, NULL);
769 adelay =
770 calculation_stream_delayed_ms
771 (PTS_TYPE_AUDIO, NULL, NULL);
772 }
773 }
774 if (vdelay > vbuf->max_buffer_delay_ms
775 && adelay > abuf->max_buffer_delay_ms)
776 return 0;
777 }
778 write_size = min(stbuf_space(vbuf), stbuf_space(abuf));
779 write_size = min_t(int, count, write_size);
780 return write_size;
781}
782
783ssize_t drm_tswrite(struct file *file,
784 struct stream_buf_s *vbuf,
785 struct stream_buf_s *abuf,
786 const char __user *buf, size_t count)
787{
788 s32 r;
789 u32 realcount = count;
790 u32 re_count = count;
791 u32 havewritebytes = 0;
792
793 struct drm_info tmpmm;
794 struct drm_info *drm = &tmpmm;
795 u32 res = 0;
796 int isphybuf = 0;
797 unsigned long realbuf;
798
799 struct port_priv_s *priv = (struct port_priv_s *)file->private_data;
800 struct stream_port_s *port = priv->port;
801 size_t wait_size, write_size;
802
803 if (buf == NULL || count == 0)
804 return -EINVAL;
805
806 res = copy_from_user(drm, buf, sizeof(struct drm_info));
807 if (res) {
808 pr_info("drm kmalloc failed res[%d]\n", res);
809 return -EFAULT;
810 }
811
812 if (drm->drm_flag == TYPE_DRMINFO && drm->drm_level == DRM_LEVEL1) {
813 /* buf only has drminfo not have esdata; */
814 realcount = drm->drm_pktsize;
815 realbuf = drm->drm_phy;
816 isphybuf = 1;
817 } else
818 realbuf = (unsigned long)buf;
819 /* pr_info("drm->drm_flag = 0x%x,realcount = %d , buf = 0x%x ",*/
820 /*drm->drm_flag,realcount, buf); */
821
822 count = realcount;
823
824 while (count > 0) {
825 if ((stbuf_space(vbuf) < count) ||
826 (stbuf_space(abuf) < count)) {
827 if (file->f_flags & O_NONBLOCK) {
828 int v_stbuf_space = stbuf_space(vbuf);
829 int a_stbuf_space = stbuf_space(abuf);
830
831 write_size = min(v_stbuf_space, a_stbuf_space);
832 /*have 188 bytes,write now., */
833 if (write_size <= 188)
834 return -EAGAIN;
835 } else {
836 wait_size =
837 min(stbuf_canusesize(vbuf) / 8,
838 stbuf_canusesize(abuf) / 4);
839 if ((port->flag & PORT_FLAG_VID)
840 && (stbuf_space(vbuf) < wait_size)) {
841 r = stbuf_wait_space(vbuf, wait_size);
842
843 if (r < 0) {
844 pr_info
845 ("write no space--- ");
846 pr_info
847 ("no space,%d--%d,r-%d\n",
848 stbuf_space(vbuf),
849 stbuf_space(abuf), r);
850 return r;
851 }
852 }
853
854 if ((port->flag & PORT_FLAG_AID)
855 && (stbuf_space(abuf) < wait_size)) {
856 r = stbuf_wait_space(abuf, wait_size);
857
858 if (r < 0) {
859 pr_info
860 ("write no stbuf_wait_space--");
861 pr_info
862 ("no space,%d--%d,r-%d\n",
863 stbuf_space(vbuf),
864 stbuf_space(abuf), r);
865 return r;
866 }
867 }
868 }
869 }
870
871 write_size = min(stbuf_space(vbuf), stbuf_space(abuf));
872 write_size = min(count, write_size);
873 /* pr_info("write_size = %d,count = %d,\n",*/
874 /*write_size, count); */
875 if (write_size > 0)
876 r = _tsdemux_write((const char __user *)realbuf,
877 write_size, isphybuf);
878 else
879 return -EAGAIN;
880
881 havewritebytes += r;
882
883 /* pr_info("havewritebytes = %d, r = %d,\n",*/
884 /*havewritebytes, r); */
885 if (havewritebytes == realcount)
886 break; /* write ok; */
887 else if (havewritebytes > realcount)
888 pr_info(" error ! write too much\n");
889
890 count -= r;
891 }
892 return re_count;
893}
894
895ssize_t tsdemux_write(struct file *file,
896 struct stream_buf_s *vbuf,
897 struct stream_buf_s *abuf,
898 const char __user *buf, size_t count)
899{
900 s32 r;
901 struct port_priv_s *priv = (struct port_priv_s *)file->private_data;
902 struct stream_port_s *port = priv->port;
903 size_t wait_size, write_size;
904
905 if ((stbuf_space(vbuf) < count) || (stbuf_space(abuf) < count)) {
906 if (file->f_flags & O_NONBLOCK) {
907 write_size = min(stbuf_space(vbuf), stbuf_space(abuf));
908 if (write_size <= 188) /*have 188 bytes,write now., */
909 return -EAGAIN;
910 } else {
911 wait_size =
912 min(stbuf_canusesize(vbuf) / 8,
913 stbuf_canusesize(abuf) / 4);
914 if ((port->flag & PORT_FLAG_VID)
915 && (stbuf_space(vbuf) < wait_size)) {
916 r = stbuf_wait_space(vbuf, wait_size);
917
918 if (r < 0) {
919 /* pr_info("write no space--- ");
920 * pr_info("no space,%d--%d,r-%d\n",
921 * stbuf_space(vbuf),
922 * stbuf_space(abuf),r);
923 */
924 return r;
925 }
926 }
927
928 if ((port->flag & PORT_FLAG_AID)
929 && (stbuf_space(abuf) < wait_size)) {
930 r = stbuf_wait_space(abuf, wait_size);
931
932 if (r < 0) {
933 /* pr_info("write no stbuf_wait_space")'
934 * pr_info{"---no space,%d--%d,r-%d\n",
935 * stbuf_space(vbuf),
936 * stbuf_space(abuf),r);
937 */
938 return r;
939 }
940 }
941 }
942 }
943 vbuf->last_write_jiffies64 = jiffies_64;
944 abuf->last_write_jiffies64 = jiffies_64;
945 write_size = limited_delay_check(file, vbuf, abuf, buf, count);
946 if (write_size > 0)
947 return _tsdemux_write(buf, write_size, 0);
948 else
949 return -EAGAIN;
950}
951
952static ssize_t show_discontinue_counter(struct class *class,
953 struct class_attribute *attr, char *buf)
954{
955 return sprintf(buf, "%d\n", discontinued_counter);
956}
957
958static struct class_attribute tsdemux_class_attrs[] = {
959 __ATTR(discontinue_counter, S_IRUGO, show_discontinue_counter, NULL),
960 __ATTR_NULL
961};
962
963static struct class tsdemux_class = {
964 .name = "tsdemux",
965 .class_attrs = tsdemux_class_attrs,
966 };
967
968int tsdemux_class_register(void)
969{
970 int r = class_register(&tsdemux_class);
971
972 if (r < 0)
973 pr_info("register tsdemux class error!\n");
974 discontinued_counter = 0;
975 return r;
976}
977
978void tsdemux_class_unregister(void)
979{
980 class_unregister(&tsdemux_class);
981}
982
983void tsdemux_change_avid(unsigned int vid, unsigned int aid)
984{
985 if (!enable_demux_driver()) {
986 WRITE_DEMUX_REG(FM_WR_DATA,
987 (((vid & 0x1fff) | (VIDEO_PACKET << 13)) << 16)
988 | ((aid & 0x1fff) | (AUDIO_PACKET << 13)));
989 WRITE_DEMUX_REG(FM_WR_ADDR, 0x8000);
990 while (READ_DEMUX_REG(FM_WR_ADDR) & 0x8000)
991 ;
992 } else {
993 curr_vid_id = vid;
994 curr_aud_id = aid;
995
996 tsdemux_set_vid(vid);
997 tsdemux_set_aid(aid);
998
999 reset_pcr_regs();
1000 }
1001
1002}
1003
1004void tsdemux_change_sid(unsigned int sid)
1005{
1006 if (!enable_demux_driver()) {
1007 WRITE_DEMUX_REG(FM_WR_DATA,
1008 (((sid & 0x1fff) | (SUB_PACKET << 13)) << 16)
1009 | 0xffff);
1010 WRITE_DEMUX_REG(FM_WR_ADDR, 0x8001);
1011 while (READ_DEMUX_REG(FM_WR_ADDR) & 0x8000)
1012 ;
1013 } else {
1014 curr_sub_id = sid;
1015
1016 tsdemux_set_sid(sid);
1017
1018 reset_pcr_regs();
1019 }
1020
1021}
1022
1023void tsdemux_audio_reset(void)
1024{
1025 ulong flags;
1026
1027 DEFINE_SPINLOCK(lock);
1028
1029 spin_lock_irqsave(&lock, flags);
1030
1031 WRITE_PARSER_REG(PARSER_AUDIO_WP,
1032 READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
1033 WRITE_PARSER_REG(PARSER_AUDIO_RP,
1034 READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
1035
1036 WRITE_PARSER_REG(PARSER_AUDIO_START_PTR,
1037 READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
1038 WRITE_PARSER_REG(PARSER_AUDIO_END_PTR,
1039 READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR));
1040 CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR);
1041
1042 WRITE_AIU_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
1043 CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
1044
1045 spin_unlock_irqrestore(&lock, flags);
1046
1047}
1048
1049void tsdemux_sub_reset(void)
1050{
1051 ulong flags;
1052 DEFINE_SPINLOCK(lock);
1053 u32 parser_sub_start_ptr;
1054 u32 parser_sub_end_ptr;
1055
1056 spin_lock_irqsave(&lock, flags);
1057
1058 parser_sub_start_ptr = READ_PARSER_REG(PARSER_SUB_START_PTR);
1059 parser_sub_end_ptr = READ_PARSER_REG(PARSER_SUB_END_PTR);
1060
1061 WRITE_PARSER_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr);
1062 WRITE_PARSER_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr);
1063 WRITE_PARSER_REG(PARSER_SUB_RP, parser_sub_start_ptr);
1064 WRITE_PARSER_REG(PARSER_SUB_WP, parser_sub_start_ptr);
1065 SET_PARSER_REG_MASK(PARSER_ES_CONTROL,
1066 (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR);
1067
1068 spin_unlock_irqrestore(&lock, flags);
1069
1070}
1071
1072void tsdemux_set_skipbyte(int skipbyte)
1073{
1074 if (!enable_demux_driver())
1075 demux_skipbyte = skipbyte;
1076 else
1077 tsdemux_set_skip_byte(skipbyte);
1078
1079}
1080
1081void tsdemux_set_demux(int dev)
1082{
1083 if (enable_demux_driver()) {
1084 unsigned long flags;
1085 int r = 0;
1086
1087 spin_lock_irqsave(&demux_ops_lock, flags);
1088 if (demux_ops && demux_ops->set_demux)
1089 r = demux_ops->set_demux(dev);
1090 spin_unlock_irqrestore(&demux_ops_lock, flags);
1091 }
1092}
1093
1094u32 tsdemux_pcrscr_get(void)
1095{
1096 u32 pcr = 0;
1097
1098 if (pcrscr_valid == 0)
1099 return 0;
1100
1101 if (READ_DEMUX_REG(TS_HIU_CTL_2) & 0x80)
1102 pcr = READ_DEMUX_REG(PCR_DEMUX_2);
1103 else if (READ_DEMUX_REG(TS_HIU_CTL_3) & 0x80)
1104 pcr = READ_DEMUX_REG(PCR_DEMUX_3);
1105 else
1106 pcr = READ_DEMUX_REG(PCR_DEMUX);
1107 if (first_pcr == 0)
1108 first_pcr = pcr;
1109 return pcr;
1110}
1111
1112u32 tsdemux_first_pcrscr_get(void)
1113{
1114 if (pcrscr_valid == 0)
1115 return 0;
1116
1117 if (first_pcr == 0) {
1118 u32 pcr;
1119 if (READ_DEMUX_REG(TS_HIU_CTL_2) & 0x80)
1120 pcr = READ_DEMUX_REG(PCR_DEMUX_2);
1121 else if (READ_DEMUX_REG(TS_HIU_CTL_3) & 0x80)
1122 pcr = READ_DEMUX_REG(PCR_DEMUX_3);
1123 else
1124 pcr = READ_DEMUX_REG(PCR_DEMUX);
1125 first_pcr = pcr;
1126 /* pr_info("set first_pcr = 0x%x\n", pcr); */
1127 }
1128
1129 return first_pcr;
1130}
1131
1132u8 tsdemux_pcrscr_valid(void)
1133{
1134 return pcrscr_valid;
1135}
1136