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