• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * drivers/amlogic/media/stream_input/parser/esparser.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/mutex.h>
26 #include <linux/slab.h>
27 #include <linux/dma-mapping.h>
28 #include <linux/amlogic/media/frame_sync/ptsserv.h>
29 
30 #include <linux/uaccess.h>
31 #include <linux/atomic.h>
32 
33 /* #include <mach/am_regs.h> */
34 #include <linux/delay.h>
35 
36 #include "../../frame_provider/decoder/utils/vdec.h"
37 #include <linux/amlogic/media/utils/vdec_reg.h>
38 #include "../amports/streambuf_reg.h"
39 #include "../amports/streambuf.h"
40 #include "esparser.h"
41 #include "../amports/amports_priv.h"
42 #include "../amports/thread_rw.h"
43 
44 #include <linux/amlogic/media/codec_mm/codec_mm.h>
45 
46 
47 
48 #define SAVE_SCR 0
49 
50 #define ES_START_CODE_PATTERN 0x00000100
51 #define ES_START_CODE_MASK    0xffffff00
52 #define SEARCH_PATTERN_LEN   512
53 #define ES_PARSER_POP      READ_PARSER_REG(PFIFO_DATA)
54 
55 #define PARSER_WRITE        (ES_WRITE | ES_PARSER_START)
56 #define PARSER_VIDEO        (ES_TYPE_VIDEO)
57 #define PARSER_AUDIO        (ES_TYPE_AUDIO)
58 #define PARSER_SUBPIC       (ES_TYPE_SUBTITLE)
59 #define PARSER_PASSTHROUGH  (ES_PASSTHROUGH | ES_PARSER_START)
60 #define PARSER_AUTOSEARCH   (ES_SEARCH | ES_PARSER_START)
61 #define PARSER_DISCARD      (ES_DISCARD | ES_PARSER_START)
62 #define PARSER_BUSY         (ES_PARSER_BUSY)
63 
64 #define MAX_DRM_PACKAGE_SIZE 0x500000
65 
66 
67 static unsigned char *search_pattern;
68 static dma_addr_t search_pattern_map;
69 static u32 audio_real_wp;
70 static u32 audio_buf_start;
71 static u32 audio_buf_end;
72 
73 static const char esparser_id[] = "esparser-id";
74 
75 static DECLARE_WAIT_QUEUE_HEAD(wq);
76 
77 
78 static u32 search_done;
79 static u32 video_data_parsed;
80 static u32 audio_data_parsed;
81 static atomic_t esparser_use_count = ATOMIC_INIT(0);
82 static DEFINE_MUTEX(esparser_mutex);
83 
get_buf_wp(u32 type)84 static inline u32 get_buf_wp(u32 type)
85 {
86 	if (type == BUF_TYPE_AUDIO)
87 		return audio_real_wp;
88 	else
89 		return 0;
90 }
get_buf_start(u32 type)91 static inline u32 get_buf_start(u32 type)
92 {
93 	if (type == BUF_TYPE_AUDIO)
94 		return audio_buf_start;
95 	else
96 		return 0;
97 }
get_buf_end(u32 type)98 static inline u32 get_buf_end(u32 type)
99 {
100 	if (type == BUF_TYPE_AUDIO)
101 		return audio_buf_end;
102 	else
103 		return 0;
104 }
set_buf_wp(u32 type,u32 wp)105 static void set_buf_wp(u32 type, u32 wp)
106 {
107 	if (type == BUF_TYPE_AUDIO) {
108 		audio_real_wp = wp;
109 		WRITE_AIU_REG(AIU_MEM_AIFIFO_MAN_WP, wp/* & 0xffffff00*/);
110 	}
111 	return;
112 }
113 
esparser_isr(int irq,void * dev_id)114 static irqreturn_t esparser_isr(int irq, void *dev_id)
115 {
116 	u32 int_status = READ_PARSER_REG(PARSER_INT_STATUS);
117 
118 	WRITE_PARSER_REG(PARSER_INT_STATUS, int_status);
119 
120 	if (int_status & PARSER_INTSTAT_SC_FOUND) {
121 		WRITE_PARSER_REG(PFIFO_RD_PTR, 0);
122 		WRITE_PARSER_REG(PFIFO_WR_PTR, 0);
123 		search_done = 1;
124 		wake_up_interruptible(&wq);
125 	}
126 	return IRQ_HANDLED;
127 }
128 
buf_wp(u32 type)129 static inline u32 buf_wp(u32 type)
130 {
131 	u32 wp;
132 
133 	if ((READ_PARSER_REG(PARSER_ES_CONTROL) & ES_VID_MAN_RD_PTR) == 0) {
134 		wp =
135 #if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
136 		(type == BUF_TYPE_HEVC) ? READ_VREG(HEVC_STREAM_WR_PTR) :
137 #endif
138 		(type == BUF_TYPE_VIDEO) ? READ_VREG(VLD_MEM_VIFIFO_WP) :
139 		(type == BUF_TYPE_AUDIO) ?
140 		READ_AIU_REG(AIU_MEM_AIFIFO_MAN_WP) :
141 		READ_PARSER_REG(PARSER_SUB_START_PTR);
142 	} else {
143 		wp =
144 #if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
145 		(type == BUF_TYPE_HEVC) ? READ_PARSER_REG(PARSER_VIDEO_WP) :
146 #endif
147 		(type == BUF_TYPE_VIDEO) ? READ_PARSER_REG(PARSER_VIDEO_WP) :
148 		(type == BUF_TYPE_AUDIO) ?
149 			READ_AIU_REG(AIU_MEM_AIFIFO_MAN_WP) :
150 			READ_PARSER_REG(PARSER_SUB_START_PTR);
151 	}
152 
153 	return wp;
154 }
155 
esparser_stbuf_write(struct stream_buf_s * stbuf,const u8 * buf,u32 count)156 static int esparser_stbuf_write(struct stream_buf_s *stbuf, const u8 *buf, u32 count)
157 {
158 	size_t r = count;
159 	const char __user *p = buf;
160 
161 	u32 len = 0;
162 	u32 parser_type;
163 	int ret;
164 	u32 wp;
165 	dma_addr_t dma_addr = 0;
166 	u32 type = stbuf->type;
167 
168 	VDEC_PRINT_FUN_LINENO(__func__, __LINE__);
169 	if (type == BUF_TYPE_HEVC)
170 		parser_type = PARSER_VIDEO;
171 	else if (type == BUF_TYPE_VIDEO)
172 		parser_type = PARSER_VIDEO;
173 	else if (type == BUF_TYPE_AUDIO)
174 		parser_type = PARSER_AUDIO;
175 	else
176 		parser_type = PARSER_SUBPIC;
177 
178 	wp = buf_wp(type);
179 
180 	if (r > 0) {
181 		if (stbuf->is_phybuf)
182 			len = count;
183 		else {
184 			len = min_t(size_t, r, (size_t) FETCHBUF_SIZE);
185 
186 			if (copy_from_user(fetchbuf, p, len))
187 				return -EFAULT;
188 			dma_addr = dma_map_single(
189 					amports_get_dma_device(), fetchbuf,
190 					FETCHBUF_SIZE, DMA_TO_DEVICE);
191 			if (dma_mapping_error(amports_get_dma_device(),
192 						(dma_addr_t) dma_addr))
193 				return -EFAULT;
194 
195 		}
196 
197 		/* wmb(); don't need */
198 		/* reset the Write and read pointer to zero again */
199 		WRITE_PARSER_REG(PFIFO_RD_PTR, 0);
200 		WRITE_PARSER_REG(PFIFO_WR_PTR, 0);
201 
202 		WRITE_PARSER_REG_BITS(PARSER_CONTROL, len, ES_PACK_SIZE_BIT,
203 							ES_PACK_SIZE_WID);
204 		WRITE_PARSER_REG_BITS(PARSER_CONTROL,
205 				parser_type | PARSER_WRITE |
206 				PARSER_AUTOSEARCH, ES_CTRL_BIT,
207 				ES_CTRL_WID);
208 
209 		if (stbuf->is_phybuf) {
210 			u32 buf_32 = (unsigned long)buf & 0xffffffff;
211 			WRITE_PARSER_REG(PARSER_FETCH_ADDR, buf_32);
212 		} else {
213 			WRITE_PARSER_REG(PARSER_FETCH_ADDR, dma_addr);
214 			dma_unmap_single(amports_get_dma_device(), dma_addr,
215 					FETCHBUF_SIZE, DMA_TO_DEVICE);
216 		}
217 
218 		search_done = 0;
219 		if (!(stbuf->drm_flag & TYPE_PATTERN)) {
220 			WRITE_PARSER_REG(PARSER_FETCH_CMD,
221 				(7 << FETCH_ENDIAN) | len);
222 			WRITE_PARSER_REG(PARSER_FETCH_ADDR, search_pattern_map);
223 			WRITE_PARSER_REG(PARSER_FETCH_CMD,
224 				(7 << FETCH_ENDIAN) | SEARCH_PATTERN_LEN);
225 		} else {
226 			WRITE_PARSER_REG(PARSER_FETCH_CMD,
227 				(7 << FETCH_ENDIAN) | (len + 512));
228 		}
229 
230 		ret = wait_event_interruptible_timeout(wq, search_done != 0,
231 			HZ / 5);
232 		if (ret == 0) {
233 			WRITE_PARSER_REG(PARSER_FETCH_CMD, 0);
234 
235 			if (wp == buf_wp(type)) {
236 				/*no data fetched */
237 				return -EAGAIN;
238 			} else {
239 				pr_info("W Timeout, but fetch ok,");
240 				pr_info("type %d len=%d,wpdiff=%d, isphy %x\n",
241 				 type, len, wp - buf_wp(type), stbuf->is_phybuf);
242 			}
243 		} else if (ret < 0)
244 			return -ERESTARTSYS;
245 	}
246 
247 	if ((type == BUF_TYPE_VIDEO)
248 		|| (has_hevc_vdec() && (type == BUF_TYPE_HEVC)))
249 		video_data_parsed += len;
250 	else if (type == BUF_TYPE_AUDIO)
251 		audio_data_parsed += len;
252 
253 	threadrw_update_buffer_level(stbuf, len);
254 	VDEC_PRINT_FUN_LINENO(__func__, __LINE__);
255 
256 	return len;
257 }
258 
_esparser_write(const char __user * buf,size_t count,struct stream_buf_s * stbuf,int isphybuf)259 static ssize_t _esparser_write(const char __user *buf,
260 		size_t count, struct stream_buf_s *stbuf, int isphybuf)
261 {
262 	return esparser_stbuf_write(stbuf, buf, count);
263 }
264 
_esparser_write_s(const char __user * buf,size_t count,struct stream_buf_s * stbuf)265 static ssize_t _esparser_write_s(const char __user *buf,
266 			size_t count, struct stream_buf_s *stbuf)
267 {
268 	size_t r = count;
269 	const char __user *p = buf;
270 	u32 len = 0;
271 	int ret;
272 	u32 wp, buf_start, buf_end;
273 	u32 type = stbuf->type;
274 	void *vaddr = NULL;
275 
276 	if (type != BUF_TYPE_AUDIO)
277 		BUG();
278 	wp = get_buf_wp(type);
279 	buf_end = get_buf_end(type) + 8;
280 	buf_start = get_buf_start(type);
281 	/*pr_info("write wp 0x%x, count %d, start 0x%x, end 0x%x\n",
282 	*		 wp, (u32)count, buf_start, buf_end);*/
283 	if (wp + count > buf_end) {
284 		if (wp == buf_end) {
285 			wp = buf_start;
286 			set_buf_wp(type, wp);
287 			return -EAGAIN;
288 		}
289 		vaddr = codec_mm_phys_to_virt(wp);
290 		ret = copy_from_user(vaddr, p, buf_end - wp);
291 		if (ret > 0) {
292 			len +=  buf_end - wp - ret;
293 			codec_mm_dma_flush(vaddr, len, DMA_TO_DEVICE);
294 			wp += len;
295 			pr_info("copy from user not finished\n");
296 			set_buf_wp(type, wp);
297 			goto end_write;
298 		} else if (ret == 0) {
299 			len += buf_end - wp;
300 			codec_mm_dma_flush(vaddr, len, DMA_TO_DEVICE);
301 			wp = buf_start;
302 			r = count - len;
303 			set_buf_wp(type, wp);
304 		} else {
305 			pr_info("copy from user failed 1\n");
306 			pr_info("w wp 0x%x, count %d, start 0x%x end 0x%x\n",
307 				 wp, (u32)count, buf_start, buf_end);
308 			return -EAGAIN;
309 		}
310 	}
311 
312 	vaddr = codec_mm_phys_to_virt(wp);
313 	ret = copy_from_user(vaddr, p + len, r);
314 	if (ret >= 0) {
315 		len += r - ret;
316 		codec_mm_dma_flush(vaddr, r - ret, DMA_TO_DEVICE);
317 		if (ret > 0)
318 			pr_info("copy from user not finished 2\n");
319 		wp += r - ret;
320 		set_buf_wp(type, wp);
321 	} else {
322 		pr_info("copy from user failed 2\n");
323 		return -EAGAIN;
324 	}
325 
326 end_write:
327 	if (type == BUF_TYPE_AUDIO)
328 	{
329 		audio_data_parsed += len;
330 		threadrw_update_buffer_level(stbuf, len);
331 	}
332 
333 	return len;
334 }
335 
es_vpts_checkin_us64(struct stream_buf_s * buf,u64 us64)336 s32 es_vpts_checkin_us64(struct stream_buf_s *buf, u64 us64)
337 {
338 	u32 passed;
339 
340 	if (buf->write_thread)
341 		passed = threadrw_dataoffset(buf);
342 	else
343 		passed = video_data_parsed;
344 	return pts_checkin_offset_us64(PTS_TYPE_VIDEO, passed, us64);
345 
346 }
347 
es_apts_checkin_us64(struct stream_buf_s * buf,u64 us64)348 s32 es_apts_checkin_us64(struct stream_buf_s *buf, u64 us64)
349 {
350 	u32 passed;
351 
352 	if (buf->write_thread)
353 		passed = threadrw_dataoffset(buf);
354 	else
355 		passed = audio_data_parsed;
356 	return pts_checkin_offset_us64(PTS_TYPE_AUDIO, passed, us64);
357 }
358 
es_vpts_checkin(struct stream_buf_s * buf,u32 pts)359 s32 es_vpts_checkin(struct stream_buf_s *buf, u32 pts)
360 {
361 #if 0
362 	if (buf->first_tstamp == INVALID_PTS) {
363 		buf->flag |= BUF_FLAG_FIRST_TSTAMP;
364 		buf->first_tstamp = pts;
365 		return 0;
366 	}
367 #endif
368 	u32 passed = 0;
369 
370 	mutex_lock(&esparser_mutex);
371 	passed = video_data_parsed + threadrw_buffer_level(buf);
372 	mutex_unlock(&esparser_mutex);
373 
374 	return pts_checkin_offset(PTS_TYPE_VIDEO, passed, pts);
375 
376 }
377 
es_apts_checkin(struct stream_buf_s * buf,u32 pts)378 s32 es_apts_checkin(struct stream_buf_s *buf, u32 pts)
379 {
380 #if 0
381 	if (buf->first_tstamp == INVALID_PTS) {
382 		buf->flag |= BUF_FLAG_FIRST_TSTAMP;
383 		buf->first_tstamp = pts;
384 
385 		return 0;
386 	}
387 #endif
388 	u32 passed = 0;
389 	mutex_lock(&esparser_mutex);
390 	passed = audio_data_parsed + threadrw_buffer_level(buf);
391 	mutex_unlock(&esparser_mutex);
392 
393 	return pts_checkin_offset(PTS_TYPE_AUDIO, passed, pts);
394 }
395 
esparser_init(struct stream_buf_s * buf,struct vdec_s * vdec)396 s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec)
397 {
398 	s32 r = 0;
399 	u32 pts_type;
400 	u32 parser_sub_start_ptr;
401 	u32 parser_sub_end_ptr;
402 	u32 parser_sub_rp;
403 	bool first_use = false;
404 	/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
405 	VDEC_PRINT_FUN_LINENO(__func__, __LINE__);
406 
407 	if (has_hevc_vdec() && (buf->type == BUF_TYPE_HEVC))
408 		pts_type = PTS_TYPE_HEVC;
409 	else
410 		/* #endif */
411 		if (buf->type == BUF_TYPE_VIDEO)
412 			pts_type = PTS_TYPE_VIDEO;
413 		else if (buf->type == BUF_TYPE_AUDIO)
414 			pts_type = PTS_TYPE_AUDIO;
415 		else if (buf->type == BUF_TYPE_SUBTITLE)
416 			pts_type = PTS_TYPE_MAX;
417 		else
418 			return -EINVAL;
419 	mutex_lock(&esparser_mutex);
420 	parser_sub_start_ptr = READ_PARSER_REG(PARSER_SUB_START_PTR);
421 	parser_sub_end_ptr = READ_PARSER_REG(PARSER_SUB_END_PTR);
422 	parser_sub_rp = READ_PARSER_REG(PARSER_SUB_RP);
423 
424 	buf->flag |= BUF_FLAG_PARSER;
425 
426 	if (atomic_add_return(1, &esparser_use_count) == 1) {
427 		first_use = true;
428 
429 		if (fetchbuf == 0) {
430 			pr_info("%s: no fetchbuf\n", __func__);
431 			r = -ENOMEM;
432 			goto Err_1;
433 		}
434 
435 		if (search_pattern == NULL) {
436 			search_pattern = kcalloc(1,
437 				SEARCH_PATTERN_LEN,
438 				GFP_KERNEL);
439 
440 			if (search_pattern == NULL) {
441 				pr_err("%s: no search_pattern\n", __func__);
442 				r = -ENOMEM;
443 				goto Err_1;
444 			}
445 
446 			/* build a fake start code to get parser interrupt */
447 			search_pattern[0] = 0x00;
448 			search_pattern[1] = 0x00;
449 			search_pattern[2] = 0x01;
450 			search_pattern[3] = 0xff;
451 
452 			search_pattern_map = dma_map_single(
453 					amports_get_dma_device(),
454 					search_pattern,
455 					SEARCH_PATTERN_LEN,
456 					DMA_TO_DEVICE);
457 		}
458 
459 		/* reset PARSER with first esparser_init() call */
460 		WRITE_RESET_REG(RESET1_REGISTER, RESET_PARSER);
461 /* for recorded file and local play, this can't change the input source*/
462 /* TS data path */
463 /*
464 #ifndef CONFIG_AM_DVB
465 		WRITE_DEMUX_REG(FEC_INPUT_CONTROL, 0);
466 #else
467 		tsdemux_set_reset_flag();
468 #endif  */
469 
470 		CLEAR_DEMUX_REG_MASK(TS_HIU_CTL, 1 << USE_HI_BSF_INTERFACE);
471 		CLEAR_DEMUX_REG_MASK(TS_HIU_CTL_2, 1 << USE_HI_BSF_INTERFACE);
472 		CLEAR_DEMUX_REG_MASK(TS_HIU_CTL_3, 1 << USE_HI_BSF_INTERFACE);
473 
474 		CLEAR_DEMUX_REG_MASK(TS_FILE_CONFIG, (1 << TS_HIU_ENABLE));
475 
476 		WRITE_PARSER_REG(PARSER_CONFIG,
477 					   (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) |
478 					   (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) |
479 					   (16 << PS_CFG_MAX_FETCH_CYCLE_BIT));
480 
481 		WRITE_PARSER_REG(PFIFO_RD_PTR, 0);
482 		WRITE_PARSER_REG(PFIFO_WR_PTR, 0);
483 
484 		WRITE_PARSER_REG(PARSER_SEARCH_PATTERN, ES_START_CODE_PATTERN);
485 		WRITE_PARSER_REG(PARSER_SEARCH_MASK, ES_START_CODE_MASK);
486 
487 		WRITE_PARSER_REG(PARSER_CONFIG,
488 					   (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) |
489 					   (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) |
490 					   PS_CFG_STARTCODE_WID_24 |
491 					   PS_CFG_PFIFO_ACCESS_WID_8 |
492 					   /* single byte pop */
493 					   (16 << PS_CFG_MAX_FETCH_CYCLE_BIT));
494 
495 		WRITE_PARSER_REG(PARSER_CONTROL, PARSER_AUTOSEARCH);
496 
497 	}
498 
499 	/* hook stream buffer with PARSER */
500 	if (has_hevc_vdec() && (pts_type == PTS_TYPE_HEVC)) {
501 		WRITE_PARSER_REG(PARSER_VIDEO_START_PTR, vdec->input.start);
502 		WRITE_PARSER_REG(PARSER_VIDEO_END_PTR, vdec->input.start
503 			+ vdec->input.size - 8);
504 
505 		if (vdec_single(vdec)) {
506 			CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL,
507 				ES_VID_MAN_RD_PTR);
508 
509 			/* set vififo_vbuf_rp_sel=>hevc */
510 			WRITE_VREG(DOS_GEN_CTRL0, 3 << 1);
511 
512 			/* set use_parser_vbuf_wp */
513 			SET_VREG_MASK(HEVC_STREAM_CONTROL,
514 					(1 << 3) | (0 << 4));
515 			/* set stream_fetch_enable */
516 			SET_VREG_MASK(HEVC_STREAM_CONTROL, 1);
517 
518 			if (buf->no_parser) {
519 				/*set endian for non-parser mode */
520 				SET_VREG_MASK(HEVC_STREAM_CONTROL, 7 << 4);
521 			}
522 
523 			/* set stream_buffer_hole with 256 bytes */
524 			SET_VREG_MASK(HEVC_STREAM_FIFO_CTL, (1 << 29));
525 		} else {
526 			SET_PARSER_REG_MASK(PARSER_ES_CONTROL,
527 					ES_VID_MAN_RD_PTR);
528 			WRITE_PARSER_REG(PARSER_VIDEO_WP, vdec->input.start);
529 			WRITE_PARSER_REG(PARSER_VIDEO_RP, vdec->input.start);
530 		}
531 		video_data_parsed = 0;
532 	} else if (pts_type == PTS_TYPE_VIDEO) {
533 		WRITE_PARSER_REG(PARSER_VIDEO_START_PTR,
534 			vdec->input.start);
535 		WRITE_PARSER_REG(PARSER_VIDEO_END_PTR,
536 			vdec->input.start + vdec->input.size - 8);
537 
538 		if (vdec_single(vdec) || (vdec_get_debug_flags() & 0x2)) {
539 			if (vdec_get_debug_flags() & 0x2)
540 				pr_info("%s %d\n", __func__, __LINE__);
541 			CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL,
542 				ES_VID_MAN_RD_PTR);
543 
544 			WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
545 			CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL,
546 				MEM_BUFCTRL_INIT);
547 
548 			if (has_hevc_vdec()) {
549 				/* set vififo_vbuf_rp_sel=>vdec */
550 				WRITE_VREG(DOS_GEN_CTRL0, 0);
551 			}
552 		} else {
553 			SET_PARSER_REG_MASK(PARSER_ES_CONTROL,
554 					ES_VID_MAN_RD_PTR);
555 			WRITE_PARSER_REG(PARSER_VIDEO_WP,
556 					vdec->input.start);
557 			WRITE_PARSER_REG(PARSER_VIDEO_RP,
558 					vdec->input.start);
559 		}
560 		video_data_parsed = 0;
561 	} else if (pts_type == PTS_TYPE_AUDIO) {
562 		/* set wp as buffer start */
563 		SET_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL,
564 			MEM_BUFCTRL_MANUAL);
565 		WRITE_AIU_REG(AIU_MEM_AIFIFO_MAN_RP,
566 			READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
567 		WRITE_AIU_REG_BITS(AIU_MEM_AIFIFO_CONTROL, 7, 3, 3);
568 		SET_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL,
569 			MEM_BUFCTRL_INIT);
570 		CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL,
571 			MEM_BUFCTRL_INIT);
572 		WRITE_AIU_REG(AIU_MEM_AIFIFO_MAN_WP,
573 			READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
574 		audio_data_parsed = 0;
575 		audio_buf_start =
576 			READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR);
577 		audio_real_wp = audio_buf_start;
578 		audio_buf_end = READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR);
579 	} else if (buf->type == BUF_TYPE_SUBTITLE) {
580 		WRITE_PARSER_REG(PARSER_SUB_START_PTR,
581 			parser_sub_start_ptr);
582 		WRITE_PARSER_REG(PARSER_SUB_END_PTR,
583 			parser_sub_end_ptr);
584 		WRITE_PARSER_REG(PARSER_SUB_RP, parser_sub_rp);
585 		SET_PARSER_REG_MASK(PARSER_ES_CONTROL,
586 			(7 << ES_SUB_WR_ENDIAN_BIT) |
587 			ES_SUB_MAN_RD_PTR);
588 	}
589 
590 	if (pts_type < PTS_TYPE_MAX) {
591 		r = pts_start(pts_type);
592 
593 		if (r < 0) {
594 			pr_info("esparser_init: pts_start failed\n");
595 			goto Err_1;
596 		}
597 	}
598 #if 0
599 	if (buf->flag & BUF_FLAG_FIRST_TSTAMP) {
600 		if (buf->type == BUF_TYPE_VIDEO)
601 			es_vpts_checkin(buf, buf->first_tstamp);
602 		else if (buf->type == BUF_TYPE_AUDIO)
603 			es_apts_checkin(buf, buf->first_tstamp);
604 
605 		buf->flag &= ~BUF_FLAG_FIRST_TSTAMP;
606 	}
607 #endif
608 
609 	if (first_use) {
610 		/*TODO irq */
611 		r = vdec_request_irq(PARSER_IRQ, esparser_isr,
612 			"parser", (void *)esparser_id);
613 
614 		if (r) {
615 			pr_info("esparser_init: irq register failed.\n");
616 			goto Err_2;
617 		}
618 		VDEC_PRINT_FUN_LINENO(__func__, __LINE__);
619 
620 		WRITE_PARSER_REG(PARSER_INT_STATUS, 0xffff);
621 		WRITE_PARSER_REG(PARSER_INT_ENABLE,
622 					   PARSER_INTSTAT_SC_FOUND <<
623 					   PARSER_INT_HOST_EN_BIT);
624 	}
625 	mutex_unlock(&esparser_mutex);
626 
627 	if (!(vdec_get_debug_flags() & 1) &&
628 		!codec_mm_video_tvp_enabled()) {
629 		int block_size = (buf->type == BUF_TYPE_AUDIO) ?
630 			PAGE_SIZE : PAGE_SIZE << 4;
631 		int buf_num = (buf->type == BUF_TYPE_AUDIO) ?
632 			20 : (2 * SZ_1M)/(PAGE_SIZE << 4);
633 		if (!(buf->type == BUF_TYPE_SUBTITLE))
634 			buf->write_thread = threadrw_alloc(buf_num,
635 				block_size,
636 				esparser_write_ex,
637 			(buf->type == BUF_TYPE_AUDIO) ? 1 : 0);
638 			/*manul mode for audio*/
639 	}
640 
641 	return 0;
642 
643 Err_2:
644 	pts_stop(pts_type);
645 
646 Err_1:
647 	atomic_dec(&esparser_use_count);
648 	buf->flag &= ~BUF_FLAG_PARSER;
649 	mutex_unlock(&esparser_mutex);
650 	return r;
651 }
652 EXPORT_SYMBOL(esparser_init);
653 
esparser_audio_reset_s(struct stream_buf_s * buf)654 void esparser_audio_reset_s(struct stream_buf_s *buf)
655 {
656 	ulong flags;
657 	DEFINE_SPINLOCK(lock);
658 
659 	spin_lock_irqsave(&lock, flags);
660 
661 	SET_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_MANUAL);
662 	WRITE_AIU_REG(AIU_MEM_AIFIFO_MAN_RP,
663 			READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
664 	WRITE_AIU_REG_BITS(AIU_MEM_AIFIFO_CONTROL, 7, 3, 3);
665 	SET_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
666 	CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
667 	WRITE_AIU_REG(AIU_MEM_AIFIFO_MAN_WP,
668 			READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
669 
670 	buf->flag |= BUF_FLAG_PARSER;
671 
672 	audio_data_parsed = 0;
673 	audio_real_wp = READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR);
674 	audio_buf_start = READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR);
675 	audio_buf_end = READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR);
676 	spin_unlock_irqrestore(&lock, flags);
677 
678 	return;
679 }
680 
esparser_audio_reset(struct stream_buf_s * buf)681 void esparser_audio_reset(struct stream_buf_s *buf)
682 {
683 	ulong flags;
684 	DEFINE_SPINLOCK(lock);
685 
686 	spin_lock_irqsave(&lock, flags);
687 
688 	WRITE_PARSER_REG(PARSER_AUDIO_WP,
689 				   READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
690 	WRITE_PARSER_REG(PARSER_AUDIO_RP,
691 				   READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
692 
693 	WRITE_PARSER_REG(PARSER_AUDIO_START_PTR,
694 				   READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
695 	WRITE_PARSER_REG(PARSER_AUDIO_END_PTR,
696 				   READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR));
697 	CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR);
698 
699 	WRITE_AIU_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
700 	CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
701 
702 	buf->flag |= BUF_FLAG_PARSER;
703 
704 	audio_data_parsed = 0;
705 	audio_real_wp = 0;
706 	audio_buf_start = 0;
707 	audio_buf_end = 0;
708 	spin_unlock_irqrestore(&lock, flags);
709 
710 }
711 
esparser_release(struct stream_buf_s * buf)712 void esparser_release(struct stream_buf_s *buf)
713 {
714 	u32 pts_type;
715 
716 	/* check if esparser_init() is ever called */
717 	if ((buf->flag & BUF_FLAG_PARSER) == 0)
718 		return;
719 
720 	if (atomic_read(&esparser_use_count) == 0) {
721 		pr_info
722 		("[%s:%d]###warning, esparser has been released already\n",
723 		 __func__, __LINE__);
724 		return;
725 	}
726 	if (buf->write_thread)
727 		threadrw_release(buf);
728 	if (atomic_dec_and_test(&esparser_use_count)) {
729 		WRITE_PARSER_REG(PARSER_INT_ENABLE, 0);
730 		/*TODO irq */
731 
732 		vdec_free_irq(PARSER_IRQ, (void *)esparser_id);
733 
734 		if (search_pattern) {
735 			dma_unmap_single(amports_get_dma_device(),
736 				search_pattern_map,
737 				SEARCH_PATTERN_LEN, DMA_TO_DEVICE);
738 			kfree(search_pattern);
739 			search_pattern = NULL;
740 		}
741 	}
742 
743 	if (has_hevc_vdec() && (buf->type == BUF_TYPE_HEVC))
744 		pts_type = PTS_TYPE_VIDEO;
745 	else if (buf->type == BUF_TYPE_VIDEO)
746 		pts_type = PTS_TYPE_VIDEO;
747 	else if (buf->type == BUF_TYPE_AUDIO)
748 		pts_type = PTS_TYPE_AUDIO;
749 	else if (buf->type == BUF_TYPE_SUBTITLE) {
750 		buf->flag &= ~BUF_FLAG_PARSER;
751 		return;
752 	} else
753 		return;
754 
755 	buf->flag &= ~BUF_FLAG_PARSER;
756 	pts_stop(pts_type);
757 }
758 EXPORT_SYMBOL(esparser_release);
759 
drm_write(struct file * file,struct stream_buf_s * stbuf,const char __user * buf,size_t count)760 ssize_t drm_write(struct file *file, struct stream_buf_s *stbuf,
761 				  const char __user *buf, size_t count)
762 {
763 	s32 r;
764 	u32 len;
765 	u32 realcount, totalcount;
766 	u32 havewritebytes = 0;
767 	u32 leftcount = 0;
768 
769 	struct drm_info tmpmm;
770 	struct drm_info *drm = &tmpmm;
771 	u32 res = 0;
772 	int drm_flag = 0;
773 	unsigned long realbuf;
774 
775 	if (buf == NULL || count == 0)
776 		return -EINVAL;
777 	if (stbuf->write_thread) {
778 		r = threadrw_flush_buffers(stbuf);
779 		if (r < 0)
780 			pr_info("Warning. drm flush threadrw failed[%d]\n", r);
781 	}
782 	res = copy_from_user(drm, buf, sizeof(struct drm_info));
783 	if (res) {
784 		pr_info("drm kmalloc failed res[%d]\n", res);
785 		return -EFAULT;
786 	}
787 
788 	if ((drm->drm_flag & TYPE_DRMINFO) && (drm->drm_hasesdata == 0)) {
789 		if (drm->drm_pktsize > MAX_DRM_PACKAGE_SIZE) {
790 			pr_err("drm package size is error, size is %u\n", drm->drm_pktsize);
791 			return -EINVAL;
792 		}
793 		/* buf only has drminfo not have esdata; */
794 		realbuf = drm->drm_phy;
795 		realcount = drm->drm_pktsize;
796 		drm_flag = drm->drm_flag;
797 		/* DRM_PRNT("drm_get_rawdata
798 		 *onlydrminfo drm->drm_hasesdata[0x%x]
799 		 * stbuf->type %d buf[0x%x]\n",
800 		 *drm->drm_hasesdata,stbuf->type,buf);
801 		 */
802 	} else if (drm->drm_hasesdata == 1) {	/* buf is drminfo+es; */
803 		if (drm->drm_pktsize > MAX_DRM_PACKAGE_SIZE) {
804 			pr_err("drm package size is error, size is %u\n", drm->drm_pktsize);
805 			return -EINVAL;
806 		}
807 		realcount = drm->drm_pktsize;
808 		realbuf = (unsigned long)buf + sizeof(struct drm_info);
809 		drm_flag = 0;
810 		/* DRM_PRNT("drm_get_rawdata
811 		 *   drminfo+es drm->drm_hasesdata[0x%x]
812 		 * stbuf->type %d\n",drm->drm_hasesdata,stbuf->type);
813 		 */
814 	} else {		/* buf is hwhead; */
815 		realcount = count;
816 		drm_flag = 0;
817 		realbuf = (unsigned long)buf;
818 		/* DRM_PRNT("drm_get_rawdata
819 		 *  drm->drm_hasesdata[0x%x]
820 		 * len[%d] count[%d] realcout[%d]\n",
821 		 * drm->drm_hasesdata,len,count,realcount);
822 		 */
823 	}
824 
825 	len = realcount;
826 	count = realcount;
827 	totalcount = realcount;
828 	stbuf->drm_flag = drm_flag;
829 	stbuf->is_phybuf = drm_flag ? 1 : 0;
830 
831 	while (len > 0) {
832 		if (stbuf->type != BUF_TYPE_SUBTITLE
833 			&& stbuf_space(stbuf) < count) {
834 			/*should not write partial data in drm mode*/
835 			r = stbuf_wait_space(stbuf, count);
836 			if (r < 0)
837 				return r;
838 			if (stbuf_space(stbuf) < count)
839 				return -EAGAIN;
840 		}
841 		len = min_t(u32, len, count);
842 
843 		mutex_lock(&esparser_mutex);
844 
845 		if (stbuf->type != BUF_TYPE_AUDIO)
846 			r = _esparser_write((const char __user *)realbuf, len,
847 					stbuf, drm_flag);
848 		else
849 			r = _esparser_write_s((const char __user *)realbuf, len,
850 					stbuf);
851 		if (r < 0) {
852 			pr_info("drm_write _esparser_write failed [%d]\n", r);
853 			mutex_unlock(&esparser_mutex);
854 			return r;
855 		}
856 		havewritebytes += r;
857 		leftcount = totalcount - havewritebytes;
858 		if (havewritebytes == totalcount) {
859 
860 			mutex_unlock(&esparser_mutex);
861 			break;	/* write ok; */
862 		} else if ((len > 0) && (havewritebytes < totalcount)) {
863 			DRM_PRNT
864 			("d writebytes[%d] want[%d] total[%d] real[%d]\n",
865 			 havewritebytes, len, totalcount, realcount);
866 			len = len - r;	/* write again; */
867 			realbuf = realbuf + r;
868 		} else {
869 			pr_info
870 			("e writebytes[%d] want[%d] total[%d] real[%d]\n",
871 			 havewritebytes, len, totalcount, realcount);
872 		}
873 		mutex_unlock(&esparser_mutex);
874 	}
875 
876 	if ((drm->drm_flag & TYPE_DRMINFO) && (drm->drm_hasesdata == 0)) {
877 		havewritebytes = sizeof(struct drm_info);
878 	} else if (drm->drm_hasesdata == 1) {
879 		havewritebytes += sizeof(struct drm_info);
880 	}
881 	return havewritebytes;
882 }
883 EXPORT_SYMBOL(drm_write);
884 
885 /*
886  *flags:
887  *1:phy
888  *2:noblock
889  */
esparser_write_ex(struct file * file,struct stream_buf_s * stbuf,const char __user * buf,size_t count,int flags)890 ssize_t esparser_write_ex(struct file *file,
891 			struct stream_buf_s *stbuf,
892 			const char __user *buf, size_t count,
893 			int flags)
894 {
895 
896 	s32 r;
897 	u32 len = count;
898 
899 	if (buf == NULL || count == 0)
900 		return -EINVAL;
901 
902 	/*subtitle have no level to check, */
903 	if (stbuf->type != BUF_TYPE_SUBTITLE && stbuf_space(stbuf) < count) {
904 		if ((flags & 2) || ((file != NULL) &&
905 				(file->f_flags & O_NONBLOCK))) {
906 			len = stbuf_space(stbuf);
907 
908 			if (len < 256)	/* <1k.do eagain, */
909 				return -EAGAIN;
910 		} else {
911 			len = min(stbuf_canusesize(stbuf) / 8, len);
912 
913 			if (stbuf_space(stbuf) < len) {
914 				r = stbuf_wait_space(stbuf, len);
915 				if (r < 0)
916 					return r;
917 			}
918 		}
919 	}
920 
921 	stbuf->last_write_jiffies64 = jiffies_64;
922 
923 	len = min_t(u32, len, count);
924 
925 	mutex_lock(&esparser_mutex);
926 
927 	if (flags & 1)
928 		stbuf->is_phybuf = true;
929 
930 	if (stbuf->type == BUF_TYPE_AUDIO)
931 		r = _esparser_write_s(buf, len, stbuf);
932 	else
933 		r = _esparser_write(buf, len, stbuf, flags & 1);
934 
935 	mutex_unlock(&esparser_mutex);
936 
937 	return r;
938 }
esparser_write(struct file * file,struct stream_buf_s * stbuf,const char __user * buf,size_t count)939 ssize_t esparser_write(struct file *file,
940 			struct stream_buf_s *stbuf,
941 			const char __user *buf, size_t count)
942 {
943 	if (stbuf->write_thread) {
944 		ssize_t ret;
945 
946 		ret = threadrw_write(file, stbuf, buf, count);
947 		if (ret == -EAGAIN) {
948 			u32 a, b;
949 			int vdelay, adelay;
950 
951 			if ((stbuf->type != BUF_TYPE_VIDEO) &&
952 				(stbuf->type != BUF_TYPE_HEVC))
953 				return ret;
954 			if (stbuf->buf_size > (SZ_1M * 30) ||
955 				(threadrw_buffer_size(stbuf) > SZ_1M * 10) ||
956 				!threadrw_support_more_buffers(stbuf))
957 				return ret;
958 			/*only chang buffer for video.*/
959 			vdelay = calculation_stream_delayed_ms(
960 					PTS_TYPE_VIDEO, &a, &b);
961 			adelay = calculation_stream_delayed_ms(
962 					PTS_TYPE_AUDIO, &a, &b);
963 			if ((vdelay > 100 && vdelay < 2000) && /*vdelay valid.*/
964 				((vdelay < 500) ||/*video delay is short!*/
965 				(adelay > 0 && adelay < 1000))/*audio is low.*/
966 				) {
967 				/*on buffer fulled.
968 				 *if delay is less than 100ms we think errors,
969 				 *And we add more buffer on delay < 2s.
970 				 */
971 				int new_size = 2 * 1024 * 1024;
972 
973 				threadrw_alloc_more_buffer_size(
974 						stbuf, new_size);
975 			}
976 		}
977 		return ret;
978 	}
979 	return esparser_write_ex(file, stbuf, buf, count, 0);
980 }
981 EXPORT_SYMBOL(esparser_write);
982 
esparser_sub_reset(void)983 void esparser_sub_reset(void)
984 {
985 	ulong flags;
986 	DEFINE_SPINLOCK(lock);
987 	u32 parser_sub_start_ptr;
988 	u32 parser_sub_end_ptr;
989 
990 	spin_lock_irqsave(&lock, flags);
991 
992 	parser_sub_start_ptr = READ_PARSER_REG(PARSER_SUB_START_PTR);
993 	parser_sub_end_ptr = READ_PARSER_REG(PARSER_SUB_END_PTR);
994 
995 	WRITE_PARSER_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr);
996 	WRITE_PARSER_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr);
997 	WRITE_PARSER_REG(PARSER_SUB_RP, parser_sub_start_ptr);
998 	WRITE_PARSER_REG(PARSER_SUB_WP, parser_sub_start_ptr);
999 	SET_PARSER_REG_MASK(PARSER_ES_CONTROL,
1000 		(7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR);
1001 
1002 	spin_unlock_irqrestore(&lock, flags);
1003 }
1004 
esparser_stbuf_init(struct stream_buf_s * stbuf,struct vdec_s * vdec)1005 static int esparser_stbuf_init(struct stream_buf_s *stbuf,
1006 			       struct vdec_s *vdec)
1007 {
1008 	int ret = -1;
1009 
1010 	ret = stbuf_init(stbuf, vdec);
1011 	if (ret)
1012 		goto out;
1013 
1014 	ret = esparser_init(stbuf, vdec);
1015 	if (!ret)
1016 		stbuf->flag |= BUF_FLAG_IN_USE;
1017 out:
1018 	return ret;
1019 }
1020 
esparser_stbuf_release(struct stream_buf_s * stbuf)1021 static void esparser_stbuf_release(struct stream_buf_s *stbuf)
1022 {
1023 	esparser_release(stbuf);
1024 
1025 	stbuf_release(stbuf);
1026 }
1027 
1028 static struct stream_buf_ops esparser_stbuf_ops = {
1029 	.init	= esparser_stbuf_init,
1030 	.release = esparser_stbuf_release,
1031 	.write	= esparser_stbuf_write,
1032 	.get_wp	= parser_get_wp,
1033 	.set_wp	= parser_set_wp,
1034 	.get_rp	= parser_get_rp,
1035 	.set_rp	= parser_set_rp,
1036 };
1037 
get_esparser_stbuf_ops(void)1038 struct stream_buf_ops *get_esparser_stbuf_ops(void)
1039 {
1040 	return &esparser_stbuf_ops;
1041 }
1042 EXPORT_SYMBOL(get_esparser_stbuf_ops);
1043 
1044