1 /*
2 * drivers/amlogic/media/stream_input/parser/psparser.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/slab.h>
26 #include <linux/dma-mapping.h>
27 #include <linux/amlogic/media/frame_sync/ptsserv.h>
28 #include <linux/amlogic/media/utils/amstream.h>
29
30 #include <linux/uaccess.h>
31 /* #include <mach/am_regs.h> */
32 #include <linux/amlogic/media/utils/vdec_reg.h>
33 #include "../amports/streambuf_reg.h"
34 #include "../amports/streambuf.h"
35 #include "psparser.h"
36 #include "../amports/amports_priv.h"
37
38
39 #define TIMESTAMP_IONLY 1
40 #define SAVE_SCR 0
41
42 #define MPEG_START_CODE_PATTERN (0x00000100L)
43 #define MPEG_START_CODE_MASK (0xffffff00L)
44 #define MAX_MPG_AUDIOPK_SIZE 0x1000
45
46 #define SUB_INSERT_START_CODE_HIGH 0x414d4c55
47 #define SUB_INSERT_START_CODE_LOW 0xaa000000
48
49 #define PARSER_WRITE (ES_WRITE | ES_PARSER_START)
50 #define PARSER_VIDEO (ES_TYPE_VIDEO)
51 #define PARSER_AUDIO (ES_TYPE_AUDIO)
52 #define PARSER_SUBPIC (ES_TYPE_SUBTITLE)
53 #define PARSER_PASSTHROUGH (ES_PASSTHROUGH | ES_PARSER_START)
54 #define PARSER_AUTOSEARCH (ES_SEARCH | ES_PARSER_START)
55 #define PARSER_DISCARD (ES_DISCARD | ES_PARSER_START)
56 #define PARSER_BUSY (ES_PARSER_BUSY)
57
58 #define PARSER_PARAMETER_LENGTH_BIT 16
59 #define PARSER_PARAMETER_LOOP_BIT 24
60
61 #define PARSER_POP READ_PARSER_REG(PFIFO_DATA)
62 #define SET_BLOCK(size) \
63 WRITE_PARSER_REG_BITS(PARSER_CONTROL, size, ES_PACK_SIZE_BIT, ES_PACK_SIZE_WID)
64 #define SET_DISCARD_SIZE(size) WRITE_PARSER_REG(PARSER_PARAMETER, size)
65
66 #define VIDEO_AUTO_FLUSH
67 #ifdef VIDEO_AUTO_FLUSH
68 static u32 video_auto_flush_state;
69 #define VIDEO_AUTO_FLUSH_IDLE 0
70 #define VIDEO_AUTO_FLUSH_MONITOR 1
71 #define VIDEO_AUTO_FLUSH_TRIGGER 2
72 #define VIDEO_AUTO_FLUSH_DONE 3
73 #define VIDEO_AUTO_FLUSH_PTS_THRESHOLD 90000
74 #define VIDEO_AUTO_FLUSH_BYTE_COUNT 1024
75
76 static s32 audio_last_pts;
77 static s32 audio_monitor_pts;
78 #endif
79
80 enum {
81 SEARCH_START_CODE = 0,
82 SEND_VIDEO_SEARCH,
83 SEND_AUDIO_SEARCH,
84 SEND_SUBPIC_SEARCH,
85 DISCARD_SEARCH,
86 DISCARD_ONLY
87 #ifdef VIDEO_AUTO_FLUSH
88 ,
89 SEARCH_START_CODE_VIDEO_FLUSH
90 #endif
91 };
92
93 enum {
94 AUDIO_FIRST_ACCESS_ARM = 0,
95 AUDIO_FIRST_ACCESS_POPING,
96 AUDIO_FIRST_ACCESS_DONE
97 };
98
99 static const char psparser_id[] = "psparser-id";
100
101 static DECLARE_WAIT_QUEUE_HEAD(wq);
102
103 static struct tasklet_struct psparser_tasklet;
104 static u32 fetch_done;
105 static u8 audio_id, video_id, sub_id, sub_id_max;
106 static u32 audio_first_access;
107 static u32 packet_remaining;
108 static u32 video_data_parsed;
109 static u32 audio_data_parsed;
110 static u32 pts_equ_dts_flag;
111
112 static unsigned int first_apts, first_vpts;
113 static unsigned int audio_got_first_pts, video_got_first_dts, sub_got_first_pts;
114 atomic_t sub_block_found = ATOMIC_INIT(0);
115
116 #define DEBUG_VOB_SUB
117 #ifdef DEBUG_VOB_SUB
118 static u8 sub_found_num;
119 static struct subtitle_info *sub_info[MAX_SUB_NUM];
120 #endif
121
ptsmgr_first_vpts_ready(void)122 static bool ptsmgr_first_vpts_ready(void)
123 {
124 return (video_got_first_dts != 0) ? true : false;
125 }
126
ptsmgr_first_apts_ready(void)127 static bool ptsmgr_first_apts_ready(void)
128 {
129 return (audio_got_first_pts != 0) ? true : false;
130 }
131
ptsmgr_vpts_checkin(u32 pts)132 static void ptsmgr_vpts_checkin(u32 pts)
133 {
134 if (video_got_first_dts == 0) {
135 video_got_first_dts = 1;
136 first_vpts = pts;
137 }
138
139 pts_checkin_offset(PTS_TYPE_VIDEO, video_data_parsed, pts);
140 }
141
ptsmgr_apts_checkin(u32 pts)142 static void ptsmgr_apts_checkin(u32 pts)
143 {
144 if (audio_got_first_pts == 0) {
145 audio_got_first_pts = 1;
146 first_apts = pts;
147 }
148 /* apts_checkin(pts); */
149 pts_checkin_offset(PTS_TYPE_AUDIO, audio_data_parsed, pts);
150
151 #ifdef VIDEO_AUTO_FLUSH
152 audio_last_pts = pts;
153
154 if ((video_auto_flush_state == VIDEO_AUTO_FLUSH_IDLE)
155 && ptsmgr_first_vpts_ready()) {
156 video_auto_flush_state = VIDEO_AUTO_FLUSH_MONITOR;
157 audio_monitor_pts = pts;
158 }
159
160 if (video_auto_flush_state == VIDEO_AUTO_FLUSH_MONITOR) {
161 if ((audio_last_pts - audio_monitor_pts) >
162 VIDEO_AUTO_FLUSH_PTS_THRESHOLD)
163 video_auto_flush_state = VIDEO_AUTO_FLUSH_TRIGGER;
164 }
165 #endif
166 }
167
parser_process(s32 type,s32 packet_len)168 static u32 parser_process(s32 type, s32 packet_len)
169 {
170 s16 temp, header_len, misc_flags, i;
171 u32 pts = 0, dts = 0;
172 u32 pts_dts_flag = 0;
173 u16 invalid_pts = 0;
174
175 temp = PARSER_POP;
176 packet_len--;
177
178 if ((temp >> 6) == 0x02) {
179 /* mpeg-2 system */
180 misc_flags = PARSER_POP;
181 header_len = PARSER_POP;
182 packet_len -= 2;
183 packet_len -= header_len;
184
185 if ((misc_flags >> 6) > 1) {
186 /* PTS exist */
187 pts = ((PARSER_POP >> 1) & 7) << 30; /* bit 32-30 */
188 pts |= PARSER_POP << 22; /* bit 29-22 */
189 pts |= (PARSER_POP >> 1) << 15; /* bit 21-15 */
190 pts |= (PARSER_POP << 7); /* bit 14-07 */
191 pts |= (PARSER_POP >> 1); /* bit 06-00 */
192 header_len -= 5;
193 pts_dts_flag |= 2;
194 }
195
196 if ((misc_flags >> 6) > 2) {
197 /* DTS exist */
198 dts = ((PARSER_POP >> 1) & 7) << 30; /* bit 32-30 */
199 dts |= PARSER_POP << 22; /* bit 29-22 */
200 dts |= (PARSER_POP >> 1) << 15; /* bit 21-15 */
201 dts |= (PARSER_POP << 7); /* bit 14-07 */
202 dts |= (PARSER_POP >> 1); /* bit 06-00 */
203 header_len -= 5;
204 pts_dts_flag |= 1;
205 }
206
207 if (misc_flags & 0x20) {
208 /* ESCR_flag */
209 PARSER_POP;
210 PARSER_POP;
211 PARSER_POP;
212 PARSER_POP;
213 PARSER_POP;
214 PARSER_POP;
215 header_len -= 5;
216 }
217
218 if (misc_flags & 0x10) {
219 /* ES_rate_flag */
220 PARSER_POP;
221 PARSER_POP;
222 PARSER_POP;
223 header_len -= 3;
224 }
225
226 if (misc_flags & 0x08) {
227 /* DSM_trick_mode_flag */
228 PARSER_POP;
229 header_len -= 1;
230 }
231
232 if (misc_flags & 0x04) {
233 /* additional_copy_info_flag */
234 PARSER_POP;
235 header_len -= 1;
236 }
237
238 if (misc_flags & 0x02) {
239 /* PES_CRC_flag */
240 PARSER_POP;
241 PARSER_POP;
242 header_len -= 2;
243 }
244
245 if (misc_flags & 0x01) {
246 /* PES_extension_flag */
247 misc_flags = PARSER_POP;
248 header_len--;
249
250 if ((misc_flags & 0x80) && (header_len >= 128)) {
251 /* PES_private_data_flag */
252 for (i = 0; i < 128; i++)
253 PARSER_POP;
254
255 header_len -= 128;
256 }
257 #if 0
258 if (misc_flags & 0x40) {
259 /* pack_header_field_flag */
260 /* Invalid case */
261 }
262 #endif
263 if (misc_flags & 0x20) {
264 /* program_packet_sequence_counter_flag */
265 PARSER_POP;
266 PARSER_POP;
267 header_len -= 2;
268 }
269
270 if (misc_flags & 0x10) {
271 /* PSTD_buffer_flag */
272 PARSER_POP;
273 PARSER_POP;
274 header_len -= 2;
275 }
276
277 if (misc_flags & 1) {
278 /* PES_extension_flag_2 */
279 temp = PARSER_POP & 0x7f;
280
281 while (temp) {
282 PARSER_POP;
283 temp--;
284 header_len--;
285 }
286 }
287
288 while (header_len) {
289 PARSER_POP;
290 header_len--;
291 }
292 }
293
294 while (header_len) {
295 PARSER_POP;
296 header_len--;
297 }
298
299 } else {
300 /* mpeg-1 system */
301 while (temp == 0xff) {
302 temp = PARSER_POP;
303 packet_len--;
304 }
305
306 if ((temp >> 6) == 1) {
307 PARSER_POP; /* STD buffer size */
308 temp = PARSER_POP;
309 packet_len -= 2;
310 }
311
312 if (((temp >> 4) == 2) || ((temp >> 4) == 3)) {
313 pts = ((temp >> 1) & 7) << 30; /* bit 32-30 */
314 pts |= PARSER_POP << 22; /* bit 29-22 */
315 pts |= (PARSER_POP >> 1) << 15; /* bit 21-15 */
316 pts |= (PARSER_POP << 7); /* bit 14-07 */
317 pts |= (PARSER_POP >> 1); /* bit 06-00 */
318 packet_len -= 4;
319 pts_dts_flag |= 2;
320 }
321
322 if ((temp >> 4) == 3) {
323 dts = ((PARSER_POP >> 1) & 7) << 30; /* bit 32-30 */
324 dts |= PARSER_POP << 22; /* bit 29-22 */
325 dts |= (PARSER_POP >> 1) << 15; /* bit 21-15 */
326 dts |= (PARSER_POP << 7); /* bit 14-07 */
327 dts |= (PARSER_POP >> 1); /* bit 06-00 */
328 packet_len -= 5;
329 pts_dts_flag |= 1;
330 }
331 }
332
333 if ((pts == 0) && (dts == 0xffffffff)) {
334 invalid_pts = 1;
335 pr_info("invalid pts\n");
336 }
337
338 if (!packet_len)
339 return SEARCH_START_CODE;
340
341 else if (type == 0) {
342 #ifdef VIDEO_AUTO_FLUSH
343 if (video_auto_flush_state == VIDEO_AUTO_FLUSH_MONITOR)
344 audio_monitor_pts = audio_last_pts;
345 #endif
346
347 if ((pts_dts_flag) && (!invalid_pts)) {
348 #if TIMESTAMP_IONLY
349 if (!ptsmgr_first_vpts_ready()) {
350 if (pts_dts_flag & 2)
351 ptsmgr_vpts_checkin(pts);
352 else
353 ptsmgr_vpts_checkin(dts);
354 } else if ((pts_dts_flag & 3) == 3) {
355 if (pts_equ_dts_flag) {
356 if (dts == pts)
357 ptsmgr_vpts_checkin(pts);
358 } else {
359 if (dts == pts)
360 pts_equ_dts_flag = 1;
361 ptsmgr_vpts_checkin(pts);
362 }
363 }
364 #else
365 if (!ptsmgr_first_vpts_ready()) {
366 if (pts_dts_flag & 2)
367 ptsmgr_vpts_checkin(pts);
368 else
369 ptsmgr_vpts_checkin(dts);
370 } else if (pts_dts_flag & 2)
371 ptsmgr_vpts_checkin(pts);
372 #endif
373 }
374
375 if (ptsmgr_first_vpts_ready() || invalid_pts) {
376 SET_BLOCK(packet_len);
377 video_data_parsed += packet_len;
378 return SEND_VIDEO_SEARCH;
379
380 } else {
381 SET_DISCARD_SIZE(packet_len);
382 return DISCARD_SEARCH;
383 }
384
385 } else if (type == 1) {
386 /* mpeg audio */
387 if (pts_dts_flag & 2)
388 ptsmgr_apts_checkin(pts);
389
390 if (ptsmgr_first_apts_ready()) {
391 SET_BLOCK(packet_len);
392 audio_data_parsed += packet_len;
393 return SEND_AUDIO_SEARCH;
394
395 } else {
396 SET_DISCARD_SIZE(packet_len);
397 return DISCARD_SEARCH;
398 }
399
400 } else if (type == 2) {
401 /* Private stream */
402 temp = PARSER_POP; /* sub_stream_id */
403 packet_len--;
404
405 if (((temp & 0xf8) == 0xa0) && (temp == audio_id)) {
406 /* DVD_VIDEO Audio LPCM data */
407 PARSER_POP;
408 temp = (PARSER_POP << 8) | PARSER_POP;
409 if (temp == 0)
410 temp = 4;
411 temp--;
412 packet_len -= 3;
413
414 if (audio_first_access == AUDIO_FIRST_ACCESS_ARM) {
415 if (temp) {
416 packet_remaining = packet_len - temp;
417 SET_DISCARD_SIZE(temp);
418 audio_first_access =
419 AUDIO_FIRST_ACCESS_POPING;
420 return DISCARD_ONLY;
421 }
422
423 audio_first_access = AUDIO_FIRST_ACCESS_DONE;
424
425 if (packet_len) {
426 SET_BLOCK(packet_len);
427 audio_data_parsed += packet_len;
428 return SEND_AUDIO_SEARCH;
429
430 } else
431 return SEARCH_START_CODE;
432
433 } else {
434 PARSER_POP;
435 PARSER_POP;
436 PARSER_POP;
437 packet_len -= 3;
438 }
439
440 if (pts_dts_flag & 2)
441 ptsmgr_apts_checkin(pts);
442
443 if (ptsmgr_first_apts_ready()) {
444 SET_BLOCK(packet_len);
445 audio_data_parsed += packet_len;
446 return SEND_AUDIO_SEARCH;
447
448 } else {
449 SET_DISCARD_SIZE(packet_len);
450 return DISCARD_SEARCH;
451 }
452
453 } else if (((temp & 0xf8) == 0x80) && (temp == audio_id)) {
454 /* Audio AC3 data */
455 PARSER_POP;
456 temp = (PARSER_POP << 8) | PARSER_POP;
457 packet_len -= 3;
458
459 if (audio_first_access == AUDIO_FIRST_ACCESS_ARM) {
460 if (pts_dts_flag & 2)
461 ptsmgr_apts_checkin(pts);
462
463 if ((temp > 2) && (packet_len > (temp - 2))) {
464 temp -= 2;
465 packet_remaining = packet_len - temp;
466 SET_DISCARD_SIZE(temp);
467 audio_first_access =
468 AUDIO_FIRST_ACCESS_POPING;
469 return DISCARD_ONLY;
470 }
471
472 audio_first_access = AUDIO_FIRST_ACCESS_DONE;
473
474 if (packet_len) {
475 SET_BLOCK(packet_len);
476 audio_data_parsed += packet_len;
477 return SEND_AUDIO_SEARCH;
478
479 } else
480 return SEARCH_START_CODE;
481 }
482
483 if (pts_dts_flag & 2)
484 ptsmgr_apts_checkin(pts);
485
486 if (ptsmgr_first_apts_ready()) {
487 SET_BLOCK(packet_len);
488 audio_data_parsed += packet_len;
489 return SEND_AUDIO_SEARCH;
490
491 } else {
492 SET_DISCARD_SIZE(packet_len);
493 return DISCARD_SEARCH;
494 }
495
496 } else if (((temp & 0xf8) == 0x88) && (temp == audio_id)) {
497 /* Audio DTS data */
498 PARSER_POP;
499 PARSER_POP;
500 PARSER_POP;
501 packet_len -= 3;
502
503 if (audio_first_access == AUDIO_FIRST_ACCESS_ARM)
504 audio_first_access = AUDIO_FIRST_ACCESS_DONE;
505
506 if (pts_dts_flag & 2)
507 ptsmgr_apts_checkin(pts);
508
509 if (ptsmgr_first_apts_ready()) {
510 SET_BLOCK(packet_len);
511 audio_data_parsed += packet_len;
512 return SEND_AUDIO_SEARCH;
513
514 } else {
515 SET_DISCARD_SIZE(packet_len);
516 return DISCARD_SEARCH;
517 }
518 } else if ((temp & 0xe0) == 0x20) {
519 if (temp > sub_id_max)
520 sub_id_max = temp;
521 #ifdef DEBUG_VOB_SUB
522 for (i = 0; i < sub_found_num; i++) {
523 if (!sub_info[i])
524 break;
525 if (temp == sub_info[i]->id)
526 break;
527 }
528 if (i == sub_found_num && i < MAX_SUB_NUM) {
529 if (sub_info[sub_found_num]) {
530 sub_info[sub_found_num]->id = temp;
531 sub_found_num++;
532 pr_info
533 ("[%s]found new sub_id=0x%x (num %d)\n",
534 __func__, temp, sub_found_num);
535 } else {
536 pr_info
537 ("[%s]sub info NULL!\n", __func__);
538 }
539 }
540 #endif
541
542 if (temp == sub_id) {
543 /* DVD sub-picture data */
544 if (!packet_len)
545 return SEARCH_START_CODE;
546
547 else {
548 #if 0
549 if (pts_dts_flag & 2)
550 ptsmgr_spts_checkin(pts);
551
552 if (ptsmgr_first_spts_ready()) {
553 SET_BLOCK(packet_len);
554 return SEND_SUBPIC_SEARCH;
555
556 } else {
557 SET_DISCARD_SIZE(packet_len);
558 return DISCARD_SEARCH;
559 }
560 #else
561 if (pts_dts_flag & 2)
562 sub_got_first_pts = 1;
563
564 if (sub_got_first_pts) {
565 pr_info
566 ("sub pts 0x%x, len %d\n",
567 pts, packet_len);
568 SET_BLOCK(packet_len);
569 WRITE_PARSER_REG
570 (PARSER_PARAMETER,
571 16 <<
572 PARSER_PARAMETER_LENGTH_BIT);
573 WRITE_PARSER_REG
574 (PARSER_INSERT_DATA,
575 SUB_INSERT_START_CODE_HIGH);
576 WRITE_PARSER_REG
577 (PARSER_INSERT_DATA,
578 SUB_INSERT_START_CODE_LOW |
579 get_sub_type());
580 WRITE_PARSER_REG
581 (PARSER_INSERT_DATA,
582 packet_len);
583 WRITE_PARSER_REG
584 (PARSER_INSERT_DATA, pts);
585 atomic_set(&sub_block_found, 1);
586 return SEND_SUBPIC_SEARCH;
587 }
588
589 SET_DISCARD_SIZE(packet_len);
590 return DISCARD_SEARCH;
591 #endif
592 }
593 } else {
594 SET_DISCARD_SIZE(packet_len);
595 return DISCARD_SEARCH;
596 }
597 } else {
598 SET_DISCARD_SIZE(packet_len);
599 return DISCARD_SEARCH;
600 }
601 }
602
603 return SEARCH_START_CODE;
604 }
605
on_start_code_found(int start_code)606 static void on_start_code_found(int start_code)
607 {
608 unsigned short packet_len;
609 unsigned short temp;
610 unsigned int next_action;
611 #if SAVE_SCR
612 unsigned int scr;
613 #endif
614
615 if (atomic_read(&sub_block_found)) {
616 wakeup_sub_poll();
617 atomic_set(&sub_block_found, 0);
618 }
619
620 if (audio_first_access == AUDIO_FIRST_ACCESS_POPING) {
621 /*
622 *we are in the procedure of poping data for audio first
623 * access, continue with last packet
624 */
625 audio_first_access = AUDIO_FIRST_ACCESS_DONE;
626
627 if (packet_remaining) {
628 next_action = SEND_AUDIO_SEARCH;
629 SET_BLOCK(packet_remaining);
630
631 } else
632 next_action = SEARCH_START_CODE;
633
634 } else if (start_code == 0xba) { /* PACK_START_CODE */
635 temp = PARSER_POP;
636
637 if ((temp >> 6) == 0x01) {
638 #if SAVE_SCR
639 scr = ((temp >> 3) & 0x3) << 30; /* bit 31-30 */
640 scr |= (temp & 0x3) << 28; /* bit 29-28 */
641 scr |= (PARSER_POP) << 20; /* bit 27-20 */
642 temp = PARSER_POP;
643 scr |= (temp >> 4) << 16; /* bit 19-16 */
644 scr |= (temp & 7) << 13; /* bit 15-13 */
645 scr |= (PARSER_POP) << 5; /* bit 12-05 */
646 scr |= (PARSER_POP) >> 3; /* bit 04-00 */
647 #else
648 PARSER_POP;
649 PARSER_POP;
650 PARSER_POP;
651 PARSER_POP;
652 #endif
653 PARSER_POP;
654 PARSER_POP;
655 PARSER_POP;
656 PARSER_POP;
657 temp = PARSER_POP & 7;
658
659 while (temp) { /* stuff byte */
660 PARSER_POP;
661 temp--;
662 }
663
664 } else {
665 /* mpeg-1 Pack Header */
666 #if SAVE_SCR
667 scr = ((temp >> 1) & 0x3) << 30; /* bit 31-30 */
668 scr |= (PARSER_POP) << 22; /* bit 29-22 */
669 scr |= (PARSER_POP >> 1) << 15; /* bit 21-15 */
670 scr |= (PARSER_POP) << 7; /* bit 14-07 */
671 scr |= (PARSER_POP >> 1); /* bit 06-00 */
672 #else
673 PARSER_POP;
674 PARSER_POP;
675 PARSER_POP;
676 PARSER_POP;
677 #endif
678 }
679
680 #ifdef VIDEO_AUTO_FLUSH
681 if (video_auto_flush_state == VIDEO_AUTO_FLUSH_TRIGGER) {
682 next_action = SEARCH_START_CODE_VIDEO_FLUSH;
683 video_auto_flush_state = VIDEO_AUTO_FLUSH_DONE;
684 } else
685 #endif
686
687 next_action = SEARCH_START_CODE;
688
689 } else {
690 packet_len = (PARSER_POP << 8) | PARSER_POP;
691
692 if (start_code == video_id)
693 next_action = parser_process(0, packet_len);
694
695 else if (start_code == audio_id) {
696 /* add mpeg audio packet length check */
697 if (packet_len > MAX_MPG_AUDIOPK_SIZE)
698 next_action = SEARCH_START_CODE;
699
700 else
701 next_action = parser_process(1, packet_len);
702
703 } else if (start_code == 0xbb) {
704 SET_DISCARD_SIZE(packet_len);
705 next_action = DISCARD_SEARCH;
706 } else if (start_code == 0xbd)
707 next_action = parser_process(2, packet_len);
708
709 else if (start_code == 0xbf) {
710 SET_DISCARD_SIZE(packet_len);
711 next_action = DISCARD_SEARCH;
712 } else if ((start_code < 0xc0) || (start_code > 0xc8))
713 next_action = SEARCH_START_CODE;
714
715 else if (packet_len) {
716 SET_DISCARD_SIZE(packet_len);
717 next_action = DISCARD_SEARCH;
718
719 } else
720 next_action = SEARCH_START_CODE;
721 }
722
723 switch (next_action) {
724 case SEARCH_START_CODE:
725 WRITE_PARSER_REG(PARSER_CONTROL, PARSER_AUTOSEARCH);
726 break;
727
728 case SEND_VIDEO_SEARCH:
729 WRITE_PARSER_REG_BITS(PARSER_CONTROL,
730 PARSER_AUTOSEARCH | PARSER_VIDEO |
731 PARSER_WRITE, ES_CTRL_BIT, ES_CTRL_WID);
732 break;
733
734 case SEND_AUDIO_SEARCH:
735 WRITE_PARSER_REG_BITS(PARSER_CONTROL,
736 PARSER_AUTOSEARCH | PARSER_AUDIO |
737 PARSER_WRITE, ES_CTRL_BIT, ES_CTRL_WID);
738 break;
739
740 case SEND_SUBPIC_SEARCH:
741 WRITE_PARSER_REG_BITS(PARSER_CONTROL,
742 PARSER_AUTOSEARCH | PARSER_SUBPIC |
743 PARSER_WRITE | ES_INSERT_BEFORE_ES_WRITE,
744 ES_CTRL_BIT, ES_CTRL_WID);
745 break;
746
747 case DISCARD_SEARCH:
748 WRITE_PARSER_REG_BITS(PARSER_CONTROL,
749 PARSER_AUTOSEARCH | PARSER_DISCARD,
750 ES_CTRL_BIT, ES_CTRL_WID);
751 break;
752
753 case DISCARD_ONLY:
754 WRITE_PARSER_REG_BITS(PARSER_CONTROL,
755 PARSER_DISCARD, ES_CTRL_BIT, ES_CTRL_WID);
756 break;
757
758 #ifdef VIDEO_AUTO_FLUSH
759 case SEARCH_START_CODE_VIDEO_FLUSH:
760 WRITE_PARSER_REG(PARSER_INSERT_DATA, 0xffffffff);
761 WRITE_PARSER_REG(PARSER_INSERT_DATA, 0xffffffff);
762 WRITE_PARSER_REG(PARSER_PARAMETER,
763 ((VIDEO_AUTO_FLUSH_BYTE_COUNT /
764 8) << PARSER_PARAMETER_LOOP_BIT) | (8 <<
765 PARSER_PARAMETER_LENGTH_BIT));
766 WRITE_PARSER_REG(PARSER_CONTROL,
767 PARSER_AUTOSEARCH | PARSER_VIDEO | PARSER_WRITE |
768 ES_INSERT_BEFORE_ES_WRITE);
769 break;
770 #endif
771 }
772 }
773
parser_tasklet(ulong data)774 static void parser_tasklet(ulong data)
775 {
776 s32 sc;
777 u32 int_status = READ_PARSER_REG(PARSER_INT_STATUS);
778
779 WRITE_PARSER_REG(PARSER_INT_STATUS, int_status);
780
781 if (int_status & PARSER_INTSTAT_FETCH_CMD) {
782 fetch_done = 1;
783
784 wake_up_interruptible(&wq);
785 }
786
787 if (int_status & PARSER_INTSTAT_SC_FOUND) {
788 sc = PARSER_POP;
789
790 on_start_code_found(sc);
791
792 } else if (int_status & PARSER_INTSTAT_DISCARD)
793 on_start_code_found(0);
794 }
795
parser_isr(int irq,void * dev_id)796 static irqreturn_t parser_isr(int irq, void *dev_id)
797 {
798 tasklet_schedule(&psparser_tasklet);
799
800 return IRQ_HANDLED;
801 }
802
_psparser_write(const char __user * buf,size_t count)803 static ssize_t _psparser_write(const char __user *buf, size_t count)
804 {
805 size_t r = count;
806 const char __user *p = buf;
807 u32 len;
808 int ret;
809 dma_addr_t dma_addr = 0;
810
811 if (r > 0) {
812 len = min_t(size_t, r, FETCHBUF_SIZE);
813 if (copy_from_user(fetchbuf, p, len))
814 return -EFAULT;
815
816 dma_addr =
817 dma_map_single(amports_get_dma_device(),
818 fetchbuf, FETCHBUF_SIZE, DMA_TO_DEVICE);
819 if (dma_mapping_error(amports_get_dma_device(), dma_addr))
820 return -EFAULT;
821
822
823 fetch_done = 0;
824
825 wmb(); /* Ensure fetchbuf contents visible */
826
827 WRITE_PARSER_REG(PARSER_FETCH_ADDR, dma_addr);
828
829 WRITE_PARSER_REG(PARSER_FETCH_CMD, (7 << FETCH_ENDIAN) | len);
830 dma_unmap_single(amports_get_dma_device(), dma_addr,
831 FETCHBUF_SIZE, DMA_TO_DEVICE);
832 ret =
833 wait_event_interruptible_timeout(wq, fetch_done != 0,
834 HZ / 10);
835 if (ret == 0) {
836 WRITE_PARSER_REG(PARSER_FETCH_CMD, 0);
837 pr_info("write timeout, retry\n");
838 return -EAGAIN;
839 } else if (ret < 0)
840 return -ERESTARTSYS;
841
842 p += len;
843 r -= len;
844 }
845
846 return count - r;
847 }
848
psparser_init(u32 vid,u32 aid,u32 sid,struct vdec_s * vdec)849 s32 psparser_init(u32 vid, u32 aid, u32 sid, struct vdec_s *vdec)
850 {
851 s32 r;
852 u32 parser_sub_start_ptr;
853 u32 parser_sub_end_ptr;
854 u32 parser_sub_rp;
855
856 #ifdef DEBUG_VOB_SUB
857 u8 i;
858
859 for (i = 0; i < MAX_SUB_NUM; i++) {
860 sub_info[i] = kzalloc(sizeof(struct subtitle_info), GFP_KERNEL);
861 if (!sub_info[i]) {
862 pr_info
863 ("[psparser_init]alloc for subtitle info failed\n");
864 } else
865 sub_info[i]->id = -1;
866 }
867 sub_found_num = 0;
868 #endif
869 parser_sub_start_ptr = READ_PARSER_REG(PARSER_SUB_START_PTR);
870 parser_sub_end_ptr = READ_PARSER_REG(PARSER_SUB_END_PTR);
871 parser_sub_rp = READ_PARSER_REG(PARSER_SUB_RP);
872
873 video_id = vid;
874 audio_id = aid;
875 sub_id = sid;
876 audio_got_first_pts = 0;
877 video_got_first_dts = 0;
878 sub_got_first_pts = 0;
879 first_apts = 0;
880 first_vpts = 0;
881 pts_equ_dts_flag = 0;
882
883 #ifdef VIDEO_AUTO_FLUSH
884 video_auto_flush_state = VIDEO_AUTO_FLUSH_IDLE;
885 #endif
886
887 pr_info("video 0x%x, audio 0x%x, sub 0x%x\n", video_id, audio_id,
888 sub_id);
889 if (fetchbuf == 0) {
890 pr_info("%s: no fetchbuf\n", __func__);
891 return -ENOMEM;
892 }
893
894 WRITE_RESET_REG(RESET1_REGISTER, RESET_PARSER);
895
896 /* for recorded file and local play, this can't change the input source*/
897 /* TS data path */
898 /*
899 #ifndef CONFIG_AM_DVB
900 WRITE_DEMUX_REG(FEC_INPUT_CONTROL, 0);
901 #else
902 tsdemux_set_reset_flag();
903 #endif */
904
905 CLEAR_DEMUX_REG_MASK(TS_HIU_CTL, 1 << USE_HI_BSF_INTERFACE);
906 CLEAR_DEMUX_REG_MASK(TS_HIU_CTL_2, 1 << USE_HI_BSF_INTERFACE);
907 CLEAR_DEMUX_REG_MASK(TS_HIU_CTL_3, 1 << USE_HI_BSF_INTERFACE);
908 CLEAR_DEMUX_REG_MASK(TS_FILE_CONFIG, (1 << TS_HIU_ENABLE));
909
910 /* hook stream buffer with PARSER */
911 WRITE_PARSER_REG(PARSER_VIDEO_START_PTR, vdec->input.start);
912 WRITE_PARSER_REG(PARSER_VIDEO_END_PTR,
913 vdec->input.start + vdec->input.size - 8);
914
915 if (vdec_single(vdec)) {
916 CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR);
917 WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
918 CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
919 } else {
920 SET_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_VID_MAN_RD_PTR);
921 WRITE_PARSER_REG(PARSER_VIDEO_WP, vdec->input.start);
922 WRITE_PARSER_REG(PARSER_VIDEO_RP, vdec->input.start);
923 }
924
925 WRITE_PARSER_REG(PARSER_AUDIO_START_PTR,
926 READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
927 WRITE_PARSER_REG(PARSER_AUDIO_END_PTR,
928 READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR));
929 CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR);
930
931 WRITE_PARSER_REG(PARSER_CONFIG,
932 (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) |
933 (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) |
934 (16 << PS_CFG_MAX_FETCH_CYCLE_BIT));
935
936 if (vdec_single(vdec)) {
937 WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
938 CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
939 }
940
941 WRITE_AIU_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
942 CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
943
944 WRITE_PARSER_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr);
945 WRITE_PARSER_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr);
946 WRITE_PARSER_REG(PARSER_SUB_RP, parser_sub_start_ptr);
947 WRITE_PARSER_REG(PARSER_SUB_WP, parser_sub_start_ptr);
948 SET_PARSER_REG_MASK(PARSER_ES_CONTROL,
949 (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR);
950
951 WRITE_PARSER_REG(PFIFO_RD_PTR, 0);
952 WRITE_PARSER_REG(PFIFO_WR_PTR, 0);
953
954 WRITE_PARSER_REG(PARSER_SEARCH_PATTERN, MPEG_START_CODE_PATTERN);
955 WRITE_PARSER_REG(PARSER_SEARCH_MASK, MPEG_START_CODE_MASK);
956
957 WRITE_PARSER_REG(PARSER_CONFIG,
958 (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) |
959 (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) |
960 PS_CFG_STARTCODE_WID_24 |
961 PS_CFG_PFIFO_ACCESS_WID_8 | /* single byte pop */
962 (16 << PS_CFG_MAX_FETCH_CYCLE_BIT));
963 WRITE_PARSER_REG(PARSER_CONTROL, PARSER_AUTOSEARCH);
964
965 tasklet_init(&psparser_tasklet, parser_tasklet, 0);
966 r = pts_start(PTS_TYPE_VIDEO);
967 if (r < 0)
968 goto Err_1;
969 r = pts_start(PTS_TYPE_AUDIO);
970 if (r < 0)
971 goto Err_2;
972
973 video_data_parsed = 0;
974 audio_data_parsed = 0;
975 /*TODO irq */
976
977 r = vdec_request_irq(PARSER_IRQ, parser_isr,
978 "psparser", (void *)psparser_id);
979
980 if (r) {
981 pr_info("PS Demux irq register failed.\n");
982
983 r = -ENOENT;
984 goto Err_3;
985 }
986
987 WRITE_PARSER_REG(PARSER_INT_STATUS, 0xffff);
988 WRITE_PARSER_REG(PARSER_INT_ENABLE,
989 PARSER_INT_ALL << PARSER_INT_HOST_EN_BIT);
990
991 return 0;
992
993 Err_3:
994 pts_stop(PTS_TYPE_AUDIO);
995
996 Err_2:
997 pts_stop(PTS_TYPE_VIDEO);
998
999 Err_1:
1000 return r;
1001 }
1002
psparser_release(void)1003 void psparser_release(void)
1004 {
1005 u8 i;
1006
1007 pr_info("psparser_release\n");
1008
1009 WRITE_PARSER_REG(PARSER_INT_ENABLE, 0);
1010 /*TODO irq */
1011
1012 vdec_free_irq(PARSER_IRQ, (void *)psparser_id);
1013
1014 pts_stop(PTS_TYPE_VIDEO);
1015 pts_stop(PTS_TYPE_AUDIO);
1016 #ifdef DEBUG_VOB_SUB
1017 for (i = 0; i < MAX_SUB_NUM; i++)
1018 kfree(sub_info[i]);
1019 pr_info("psparser release subtitle info\n");
1020 #endif
1021 }
1022 EXPORT_SYMBOL(psparser_release);
1023
psparser_write(struct file * file,struct stream_buf_s * vbuf,struct stream_buf_s * abuf,const char __user * buf,size_t count)1024 ssize_t psparser_write(struct file *file,
1025 struct stream_buf_s *vbuf,
1026 struct stream_buf_s *abuf,
1027 const char __user *buf, size_t count)
1028 {
1029 s32 r;
1030
1031 struct port_priv_s *priv = (struct port_priv_s *)file->private_data;
1032 struct stream_port_s *port = priv->port;
1033
1034 if ((stbuf_space(vbuf) < count) || (stbuf_space(abuf) < count)) {
1035 if (file->f_flags & O_NONBLOCK)
1036 return -EAGAIN;
1037
1038 if ((port->flag & PORT_FLAG_VID)
1039 && (stbuf_space(vbuf) < count)) {
1040 r = stbuf_wait_space(vbuf, count);
1041 if (r < 0)
1042 return r;
1043 }
1044 if ((port->flag & PORT_FLAG_AID)
1045 && (stbuf_space(abuf) < count)) {
1046 r = stbuf_wait_space(abuf, count);
1047 if (r < 0)
1048 return r;
1049 }
1050 }
1051
1052 return _psparser_write(buf, count);
1053 }
1054
psparser_change_avid(unsigned int vid,unsigned int aid)1055 void psparser_change_avid(unsigned int vid, unsigned int aid)
1056 {
1057 video_id = vid;
1058 audio_id = aid;
1059 }
1060
psparser_change_sid(unsigned int sid)1061 void psparser_change_sid(unsigned int sid)
1062 {
1063 sub_id = sid;
1064 }
1065
psparser_audio_reset(void)1066 void psparser_audio_reset(void)
1067 {
1068 ulong flags;
1069
1070 DEFINE_SPINLOCK(lock);
1071
1072 spin_lock_irqsave(&lock, flags);
1073
1074 WRITE_PARSER_REG(PARSER_AUDIO_WP,
1075 READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
1076 WRITE_PARSER_REG(PARSER_AUDIO_RP,
1077 READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
1078
1079 WRITE_PARSER_REG(PARSER_AUDIO_START_PTR,
1080 READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
1081 WRITE_PARSER_REG(PARSER_AUDIO_END_PTR,
1082 READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR));
1083 CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR);
1084
1085 WRITE_AIU_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
1086 CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
1087
1088 audio_data_parsed = 0;
1089
1090 spin_unlock_irqrestore(&lock, flags);
1091
1092 }
1093
psparser_sub_reset(void)1094 void psparser_sub_reset(void)
1095 {
1096 ulong flags;
1097
1098 DEFINE_SPINLOCK(lock);
1099 u32 parser_sub_start_ptr;
1100 u32 parser_sub_end_ptr;
1101
1102 spin_lock_irqsave(&lock, flags);
1103
1104 parser_sub_start_ptr = READ_PARSER_REG(PARSER_SUB_START_PTR);
1105 parser_sub_end_ptr = READ_PARSER_REG(PARSER_SUB_END_PTR);
1106
1107 WRITE_PARSER_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr);
1108 WRITE_PARSER_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr);
1109 WRITE_PARSER_REG(PARSER_SUB_RP, parser_sub_start_ptr);
1110 WRITE_PARSER_REG(PARSER_SUB_WP, parser_sub_start_ptr);
1111 SET_PARSER_REG_MASK(PARSER_ES_CONTROL,
1112 (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR);
1113
1114 spin_unlock_irqrestore(&lock, flags);
1115
1116 }
1117
psparser_get_sub_found_num(void)1118 u8 psparser_get_sub_found_num(void)
1119 {
1120 #ifdef DEBUG_VOB_SUB
1121 return sub_found_num;
1122 #else
1123 return 0;
1124 #endif
1125 }
1126
psparser_get_sub_info(struct subtitle_info ** sub_infos)1127 u8 psparser_get_sub_info(struct subtitle_info **sub_infos)
1128 {
1129 #ifdef DEBUG_VOB_SUB
1130 u8 i = 0;
1131 int ret = 0;
1132 u8 size = sizeof(struct subtitle_info);
1133
1134 for (i = 0; i < sub_found_num; i++) {
1135 if (!sub_info[i]) {
1136 pr_info
1137 ("[psparser_get_sub_info:%d] sub_info[%d] NULL\n",
1138 __LINE__, i);
1139 ret = -1;
1140 break;
1141 }
1142 if (!sub_infos[i]) {
1143 pr_info
1144 ("[psparser_get_sub_info:%d] sub_infos[%d] NULL\n",
1145 __LINE__, i);
1146 ret = -2;
1147 break;
1148 }
1149 memcpy(sub_infos[i], sub_info[i], size);
1150 }
1151 return ret;
1152 #else
1153 return 0;
1154 #endif
1155 }
1156
psparser_stbuf_init(struct stream_buf_s * stbuf,struct vdec_s * vdec)1157 static int psparser_stbuf_init(struct stream_buf_s *stbuf,
1158 struct vdec_s *vdec)
1159 {
1160 int ret = -1;
1161
1162 ret = stbuf_init(stbuf, vdec);
1163 if (ret)
1164 goto out;
1165
1166 ret = psparser_init(stbuf->pars.vid,
1167 stbuf->pars.aid,
1168 stbuf->pars.sid,
1169 vdec);
1170 if (ret)
1171 goto out;
1172
1173 stbuf->flag |= BUF_FLAG_IN_USE;
1174 out:
1175 return ret;
1176 }
1177
psparser_stbuf_release(struct stream_buf_s * stbuf)1178 static void psparser_stbuf_release(struct stream_buf_s *stbuf)
1179 {
1180 psparser_release();
1181
1182 stbuf_release(stbuf);
1183 }
1184
1185 static struct stream_buf_ops psparser_stbuf_ops = {
1186 .init = psparser_stbuf_init,
1187 .release = psparser_stbuf_release,
1188 .get_wp = parser_get_wp,
1189 .set_wp = parser_set_wp,
1190 .get_rp = parser_get_rp,
1191 .set_rp = parser_set_rp,
1192 };
1193
get_psparser_stbuf_ops(void)1194 struct stream_buf_ops *get_psparser_stbuf_ops(void)
1195 {
1196 return &psparser_stbuf_ops;
1197 }
1198 EXPORT_SYMBOL(get_psparser_stbuf_ops);
1199
1200