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