• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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