summaryrefslogtreecommitdiff
path: root/drivers/stream_input/parser/esparser.c (plain)
blob: 1cc3ac9b2ac07543b6aff4209cc32e2db23a030a
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 "streambuf_reg.h"
39#include "streambuf.h"
40#include "esparser.h"
41#include "../amports/amports_priv.h"
42#include "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
67static unsigned char *search_pattern;
68static dma_addr_t search_pattern_map;
69static u32 audio_real_wp;
70static u32 audio_buf_start;
71static u32 audio_buf_end;
72
73static const char esparser_id[] = "esparser-id";
74
75static DECLARE_WAIT_QUEUE_HEAD(wq);
76
77
78static u32 search_done;
79static u32 video_data_parsed;
80static u32 audio_data_parsed;
81static atomic_t esparser_use_count = ATOMIC_INIT(0);
82static DEFINE_MUTEX(esparser_mutex);
83
84static 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}
91static 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}
98static 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}
105static 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
114static 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
129static 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
156static ssize_t _esparser_write(const char __user *buf,
157 size_t count, struct stream_buf_s *stbuf, int isphybuf)
158{
159 size_t r = count;
160 const char __user *p = buf;
161
162 u32 len = 0;
163 u32 parser_type;
164 int ret;
165 u32 wp;
166 dma_addr_t dma_addr = 0;
167 u32 type = stbuf->type;
168
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 (isphybuf)
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 (isphybuf) {
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 (!(isphybuf & 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 ret = wait_event_interruptible_timeout(wq, search_done != 0,
230 HZ / 5);
231 if (ret == 0) {
232 WRITE_PARSER_REG(PARSER_FETCH_CMD, 0);
233
234 if (wp == buf_wp(type)) {
235 /*no data fetched */
236 return -EAGAIN;
237 } else {
238 pr_info("W Timeout, but fetch ok,");
239 pr_info("type %d len=%d,wpdiff=%d, isphy %x\n",
240 type, len, wp - buf_wp(type), isphybuf);
241 }
242 } else if (ret < 0)
243 return -ERESTARTSYS;
244 }
245
246 if ((type == BUF_TYPE_VIDEO)
247 || (has_hevc_vdec() && (type == BUF_TYPE_HEVC)))
248 video_data_parsed += len;
249 else if (type == BUF_TYPE_AUDIO)
250 audio_data_parsed += len;
251
252 threadrw_update_buffer_level(stbuf, len);
253 return len;
254}
255
256static ssize_t _esparser_write_s(const char __user *buf,
257 size_t count, struct stream_buf_s *stbuf)
258{
259 size_t r = count;
260 const char __user *p = buf;
261 u32 len = 0;
262 int ret;
263 u32 wp, buf_start, buf_end;
264 u32 type = stbuf->type;
265 void *vaddr = NULL;
266
267 if (type != BUF_TYPE_AUDIO)
268 BUG();
269 wp = get_buf_wp(type);
270 buf_end = get_buf_end(type) + 8;
271 buf_start = get_buf_start(type);
272 /*pr_info("write wp 0x%x, count %d, start 0x%x, end 0x%x\n",
273 * wp, (u32)count, buf_start, buf_end);*/
274 if (wp + count > buf_end) {
275 if (wp == buf_end) {
276 wp = buf_start;
277 set_buf_wp(type, wp);
278 return -EAGAIN;
279 }
280 vaddr = codec_mm_phys_to_virt(wp);
281 ret = copy_from_user(vaddr, p, buf_end - wp);
282 if (ret > 0) {
283 len += buf_end - wp - ret;
284 codec_mm_dma_flush(vaddr, len, DMA_TO_DEVICE);
285 wp += len;
286 pr_info("copy from user not finished\n");
287 set_buf_wp(type, wp);
288 goto end_write;
289 } else if (ret == 0) {
290 len += buf_end - wp;
291 codec_mm_dma_flush(vaddr, len, DMA_TO_DEVICE);
292 wp = buf_start;
293 r = count - len;
294 set_buf_wp(type, wp);
295 } else {
296 pr_info("copy from user failed 1\n");
297 pr_info("w wp 0x%x, count %d, start 0x%x end 0x%x\n",
298 wp, (u32)count, buf_start, buf_end);
299 return -EAGAIN;
300 }
301 }
302
303 vaddr = codec_mm_phys_to_virt(wp);
304 ret = copy_from_user(vaddr, p + len, r);
305 if (ret >= 0) {
306 len += r - ret;
307 codec_mm_dma_flush(vaddr, r - ret, DMA_TO_DEVICE);
308 if (ret > 0)
309 pr_info("copy from user not finished 2\n");
310 wp += r - ret;
311 set_buf_wp(type, wp);
312 } else {
313 pr_info("copy from user failed 2\n");
314 return -EAGAIN;
315 }
316
317end_write:
318 if (type == BUF_TYPE_AUDIO)
319 {
320 audio_data_parsed += len;
321 threadrw_update_buffer_level(stbuf, len);
322 }
323
324 return len;
325}
326
327s32 es_vpts_checkin_us64(struct stream_buf_s *buf, u64 us64)
328{
329 u32 passed;
330
331 if (buf->write_thread)
332 passed = threadrw_dataoffset(buf);
333 else
334 passed = video_data_parsed;
335 return pts_checkin_offset_us64(PTS_TYPE_VIDEO, passed, us64);
336
337}
338
339s32 es_apts_checkin_us64(struct stream_buf_s *buf, u64 us64)
340{
341 u32 passed;
342
343 if (buf->write_thread)
344 passed = threadrw_dataoffset(buf);
345 else
346 passed = audio_data_parsed;
347 return pts_checkin_offset_us64(PTS_TYPE_AUDIO, passed, us64);
348}
349
350s32 es_vpts_checkin(struct stream_buf_s *buf, u32 pts)
351{
352#if 0
353 if (buf->first_tstamp == INVALID_PTS) {
354 buf->flag |= BUF_FLAG_FIRST_TSTAMP;
355 buf->first_tstamp = pts;
356 return 0;
357 }
358#endif
359 u32 passed = 0;
360
361 mutex_lock(&esparser_mutex);
362 passed = video_data_parsed + threadrw_buffer_level(buf);
363 mutex_unlock(&esparser_mutex);
364
365 return pts_checkin_offset(PTS_TYPE_VIDEO, passed, pts);
366
367}
368
369s32 es_apts_checkin(struct stream_buf_s *buf, u32 pts)
370{
371#if 0
372 if (buf->first_tstamp == INVALID_PTS) {
373 buf->flag |= BUF_FLAG_FIRST_TSTAMP;
374 buf->first_tstamp = pts;
375
376 return 0;
377 }
378#endif
379 u32 passed = 0;
380 mutex_lock(&esparser_mutex);
381 passed = audio_data_parsed + threadrw_buffer_level(buf);
382 mutex_unlock(&esparser_mutex);
383
384 return pts_checkin_offset(PTS_TYPE_AUDIO, passed, pts);
385}
386
387s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec)
388{
389 s32 r = 0;
390 u32 pts_type;
391 u32 parser_sub_start_ptr;
392 u32 parser_sub_end_ptr;
393 u32 parser_sub_rp;
394 bool first_use = false;
395 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
396 if (has_hevc_vdec() && (buf->type == BUF_TYPE_HEVC))
397 pts_type = PTS_TYPE_HEVC;
398 else
399 /* #endif */
400 if (buf->type == BUF_TYPE_VIDEO)
401 pts_type = PTS_TYPE_VIDEO;
402 else if (buf->type == BUF_TYPE_AUDIO)
403 pts_type = PTS_TYPE_AUDIO;
404 else if (buf->type == BUF_TYPE_SUBTITLE)
405 pts_type = PTS_TYPE_MAX;
406 else
407 return -EINVAL;
408 mutex_lock(&esparser_mutex);
409 parser_sub_start_ptr = READ_PARSER_REG(PARSER_SUB_START_PTR);
410 parser_sub_end_ptr = READ_PARSER_REG(PARSER_SUB_END_PTR);
411 parser_sub_rp = READ_PARSER_REG(PARSER_SUB_RP);
412
413 buf->flag |= BUF_FLAG_PARSER;
414
415 if (atomic_add_return(1, &esparser_use_count) == 1) {
416 first_use = true;
417
418 if (fetchbuf == 0) {
419 pr_info("%s: no fetchbuf\n", __func__);
420 r = -ENOMEM;
421 goto Err_1;
422 }
423
424 if (search_pattern == NULL) {
425 search_pattern = kcalloc(1,
426 SEARCH_PATTERN_LEN,
427 GFP_KERNEL);
428
429 if (search_pattern == NULL) {
430 pr_err("%s: no search_pattern\n", __func__);
431 r = -ENOMEM;
432 goto Err_1;
433 }
434
435 /* build a fake start code to get parser interrupt */
436 search_pattern[0] = 0x00;
437 search_pattern[1] = 0x00;
438 search_pattern[2] = 0x01;
439 search_pattern[3] = 0xff;
440
441 search_pattern_map = dma_map_single(
442 amports_get_dma_device(),
443 search_pattern,
444 SEARCH_PATTERN_LEN,
445 DMA_TO_DEVICE);
446 }
447
448 /* reset PARSER with first esparser_init() call */
449 WRITE_RESET_REG(RESET1_REGISTER, RESET_PARSER);
450/* for recorded file and local play, this can't change the input source*/
451/* TS data path */
452/*
453#ifndef CONFIG_AM_DVB
454 WRITE_DEMUX_REG(FEC_INPUT_CONTROL, 0);
455#else
456 tsdemux_set_reset_flag();
457#endif */
458
459 CLEAR_DEMUX_REG_MASK(TS_HIU_CTL, 1 << USE_HI_BSF_INTERFACE);
460 CLEAR_DEMUX_REG_MASK(TS_HIU_CTL_2, 1 << USE_HI_BSF_INTERFACE);
461 CLEAR_DEMUX_REG_MASK(TS_HIU_CTL_3, 1 << USE_HI_BSF_INTERFACE);
462
463 CLEAR_DEMUX_REG_MASK(TS_FILE_CONFIG, (1 << TS_HIU_ENABLE));
464
465 WRITE_PARSER_REG(PARSER_CONFIG,
466 (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) |
467 (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) |
468 (16 << PS_CFG_MAX_FETCH_CYCLE_BIT));
469
470 WRITE_PARSER_REG(PFIFO_RD_PTR, 0);
471 WRITE_PARSER_REG(PFIFO_WR_PTR, 0);
472
473 WRITE_PARSER_REG(PARSER_SEARCH_PATTERN, ES_START_CODE_PATTERN);
474 WRITE_PARSER_REG(PARSER_SEARCH_MASK, ES_START_CODE_MASK);
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 PS_CFG_STARTCODE_WID_24 |
480 PS_CFG_PFIFO_ACCESS_WID_8 |
481 /* single byte pop */
482 (16 << PS_CFG_MAX_FETCH_CYCLE_BIT));
483
484 WRITE_PARSER_REG(PARSER_CONTROL, PARSER_AUTOSEARCH);
485
486 }
487
488 /* hook stream buffer with PARSER */
489 if (has_hevc_vdec() && (pts_type == PTS_TYPE_HEVC)) {
490 WRITE_PARSER_REG(PARSER_VIDEO_START_PTR, vdec->input.start);
491 WRITE_PARSER_REG(PARSER_VIDEO_END_PTR, vdec->input.start
492 + vdec->input.size - 8);
493
494 if (vdec_single(vdec)) {
495 CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL,
496 ES_VID_MAN_RD_PTR);
497
498 /* set vififo_vbuf_rp_sel=>hevc */
499 WRITE_VREG(DOS_GEN_CTRL0, 3 << 1);
500
501 /* set use_parser_vbuf_wp */
502 SET_VREG_MASK(HEVC_STREAM_CONTROL,
503 (1 << 3) | (0 << 4));
504 /* set stream_fetch_enable */
505 SET_VREG_MASK(HEVC_STREAM_CONTROL, 1);
506
507 /* set stream_buffer_hole with 256 bytes */
508 SET_VREG_MASK(HEVC_STREAM_FIFO_CTL, (1 << 29));
509 } else {
510 SET_PARSER_REG_MASK(PARSER_ES_CONTROL,
511 ES_VID_MAN_RD_PTR);
512 WRITE_PARSER_REG(PARSER_VIDEO_WP, vdec->input.start);
513 WRITE_PARSER_REG(PARSER_VIDEO_RP, vdec->input.start);
514 }
515 video_data_parsed = 0;
516 } else if (pts_type == PTS_TYPE_VIDEO) {
517 WRITE_PARSER_REG(PARSER_VIDEO_START_PTR,
518 vdec->input.start);
519 WRITE_PARSER_REG(PARSER_VIDEO_END_PTR,
520 vdec->input.start + vdec->input.size - 8);
521 if (vdec_single(vdec)) {
522 CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL,
523 ES_VID_MAN_RD_PTR);
524
525 WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
526 CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL,
527 MEM_BUFCTRL_INIT);
528
529 if (has_hevc_vdec()) {
530 /* set vififo_vbuf_rp_sel=>vdec */
531 WRITE_VREG(DOS_GEN_CTRL0, 0);
532 }
533 } else {
534 SET_PARSER_REG_MASK(PARSER_ES_CONTROL,
535 ES_VID_MAN_RD_PTR);
536 WRITE_PARSER_REG(PARSER_VIDEO_WP,
537 vdec->input.start);
538 WRITE_PARSER_REG(PARSER_VIDEO_RP,
539 vdec->input.start);
540 }
541 video_data_parsed = 0;
542 } else if (pts_type == PTS_TYPE_AUDIO) {
543 /* set wp as buffer start */
544 SET_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL,
545 MEM_BUFCTRL_MANUAL);
546 WRITE_AIU_REG(AIU_MEM_AIFIFO_MAN_RP,
547 READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
548 WRITE_AIU_REG_BITS(AIU_MEM_AIFIFO_CONTROL, 7, 3, 3);
549 SET_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL,
550 MEM_BUFCTRL_INIT);
551 CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL,
552 MEM_BUFCTRL_INIT);
553 WRITE_AIU_REG(AIU_MEM_AIFIFO_MAN_WP,
554 READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
555 audio_data_parsed = 0;
556 audio_buf_start =
557 READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR);
558 audio_real_wp = audio_buf_start;
559 audio_buf_end = READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR);
560 } else if (buf->type == BUF_TYPE_SUBTITLE) {
561 WRITE_PARSER_REG(PARSER_SUB_START_PTR,
562 parser_sub_start_ptr);
563 WRITE_PARSER_REG(PARSER_SUB_END_PTR,
564 parser_sub_end_ptr);
565 WRITE_PARSER_REG(PARSER_SUB_RP, parser_sub_rp);
566 SET_PARSER_REG_MASK(PARSER_ES_CONTROL,
567 (7 << ES_SUB_WR_ENDIAN_BIT) |
568 ES_SUB_MAN_RD_PTR);
569 }
570
571 if (pts_type < PTS_TYPE_MAX) {
572 r = pts_start(pts_type);
573
574 if (r < 0) {
575 pr_info("esparser_init: pts_start failed\n");
576 goto Err_1;
577 }
578 }
579#if 0
580 if (buf->flag & BUF_FLAG_FIRST_TSTAMP) {
581 if (buf->type == BUF_TYPE_VIDEO)
582 es_vpts_checkin(buf, buf->first_tstamp);
583 else if (buf->type == BUF_TYPE_AUDIO)
584 es_apts_checkin(buf, buf->first_tstamp);
585
586 buf->flag &= ~BUF_FLAG_FIRST_TSTAMP;
587 }
588#endif
589
590 if (first_use) {
591 /*TODO irq */
592 r = vdec_request_irq(PARSER_IRQ, esparser_isr,
593 "parser", (void *)esparser_id);
594
595 if (r) {
596 pr_info("esparser_init: irq register failed.\n");
597 goto Err_2;
598 }
599
600 WRITE_PARSER_REG(PARSER_INT_STATUS, 0xffff);
601 WRITE_PARSER_REG(PARSER_INT_ENABLE,
602 PARSER_INTSTAT_SC_FOUND <<
603 PARSER_INT_HOST_EN_BIT);
604 }
605 mutex_unlock(&esparser_mutex);
606 if (!(vdec_get_debug_flags() & 1) &&
607 !codec_mm_video_tvp_enabled()) {
608 int block_size = (buf->type == BUF_TYPE_AUDIO) ?
609 PAGE_SIZE : PAGE_SIZE << 4;
610 int buf_num = (buf->type == BUF_TYPE_AUDIO) ?
611 20 : (2 * SZ_1M)/(PAGE_SIZE << 4);
612 if (!(buf->type == BUF_TYPE_SUBTITLE))
613 buf->write_thread = threadrw_alloc(buf_num,
614 block_size,
615 esparser_write_ex,
616 (buf->type == BUF_TYPE_AUDIO) ? 1 : 0);
617 /*manul mode for audio*/
618 }
619 return 0;
620
621Err_2:
622 pts_stop(pts_type);
623
624Err_1:
625 atomic_dec(&esparser_use_count);
626 buf->flag &= ~BUF_FLAG_PARSER;
627 mutex_unlock(&esparser_mutex);
628 return r;
629}
630EXPORT_SYMBOL(esparser_init);
631
632void esparser_audio_reset_s(struct stream_buf_s *buf)
633{
634 ulong flags;
635 DEFINE_SPINLOCK(lock);
636
637 spin_lock_irqsave(&lock, flags);
638
639 SET_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_MANUAL);
640 WRITE_AIU_REG(AIU_MEM_AIFIFO_MAN_RP,
641 READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
642 WRITE_AIU_REG_BITS(AIU_MEM_AIFIFO_CONTROL, 7, 3, 3);
643 SET_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
644 CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
645 WRITE_AIU_REG(AIU_MEM_AIFIFO_MAN_WP,
646 READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
647
648 buf->flag |= BUF_FLAG_PARSER;
649
650 audio_data_parsed = 0;
651 audio_real_wp = READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR);
652 audio_buf_start = READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR);
653 audio_buf_end = READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR);
654 spin_unlock_irqrestore(&lock, flags);
655
656 return;
657}
658
659void esparser_audio_reset(struct stream_buf_s *buf)
660{
661 ulong flags;
662 DEFINE_SPINLOCK(lock);
663
664 spin_lock_irqsave(&lock, flags);
665
666 WRITE_PARSER_REG(PARSER_AUDIO_WP,
667 READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
668 WRITE_PARSER_REG(PARSER_AUDIO_RP,
669 READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
670
671 WRITE_PARSER_REG(PARSER_AUDIO_START_PTR,
672 READ_AIU_REG(AIU_MEM_AIFIFO_START_PTR));
673 WRITE_PARSER_REG(PARSER_AUDIO_END_PTR,
674 READ_AIU_REG(AIU_MEM_AIFIFO_END_PTR));
675 CLEAR_PARSER_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR);
676
677 WRITE_AIU_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
678 CLEAR_AIU_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
679
680 buf->flag |= BUF_FLAG_PARSER;
681
682 audio_data_parsed = 0;
683 audio_real_wp = 0;
684 audio_buf_start = 0;
685 audio_buf_end = 0;
686 spin_unlock_irqrestore(&lock, flags);
687
688}
689
690void esparser_release(struct stream_buf_s *buf)
691{
692 u32 pts_type;
693
694 /* check if esparser_init() is ever called */
695 if ((buf->flag & BUF_FLAG_PARSER) == 0)
696 return;
697
698 if (atomic_read(&esparser_use_count) == 0) {
699 pr_info
700 ("[%s:%d]###warning, esparser has been released already\n",
701 __func__, __LINE__);
702 return;
703 }
704 if (buf->write_thread)
705 threadrw_release(buf);
706 if (atomic_dec_and_test(&esparser_use_count)) {
707 WRITE_PARSER_REG(PARSER_INT_ENABLE, 0);
708 /*TODO irq */
709
710 vdec_free_irq(PARSER_IRQ, (void *)esparser_id);
711
712 if (search_pattern) {
713 dma_unmap_single(amports_get_dma_device(),
714 search_pattern_map,
715 SEARCH_PATTERN_LEN, DMA_TO_DEVICE);
716 kfree(search_pattern);
717 search_pattern = NULL;
718 }
719 }
720
721 if (has_hevc_vdec() && (buf->type == BUF_TYPE_HEVC))
722 pts_type = PTS_TYPE_VIDEO;
723 else if (buf->type == BUF_TYPE_VIDEO)
724 pts_type = PTS_TYPE_VIDEO;
725 else if (buf->type == BUF_TYPE_AUDIO)
726 pts_type = PTS_TYPE_AUDIO;
727 else if (buf->type == BUF_TYPE_SUBTITLE) {
728 buf->flag &= ~BUF_FLAG_PARSER;
729 return;
730 } else
731 return;
732
733 buf->flag &= ~BUF_FLAG_PARSER;
734 pts_stop(pts_type);
735}
736EXPORT_SYMBOL(esparser_release);
737
738ssize_t drm_write(struct file *file, struct stream_buf_s *stbuf,
739 const char __user *buf, size_t count)
740{
741 s32 r;
742 u32 len;
743 u32 realcount, totalcount;
744 u32 havewritebytes = 0;
745 u32 leftcount = 0;
746
747 struct drm_info tmpmm;
748 struct drm_info *drm = &tmpmm;
749 u32 res = 0;
750 int isphybuf = 0;
751 unsigned long realbuf;
752
753 if (buf == NULL || count == 0)
754 return -EINVAL;
755 if (stbuf->write_thread) {
756 r = threadrw_flush_buffers(stbuf);
757 if (r < 0)
758 pr_info("Warning. drm flush threadrw failed[%d]\n", r);
759 }
760 res = copy_from_user(drm, buf, sizeof(struct drm_info));
761 if (res) {
762 pr_info("drm kmalloc failed res[%d]\n", res);
763 return -EFAULT;
764 }
765
766 if ((drm->drm_flag & TYPE_DRMINFO) && (drm->drm_hasesdata == 0)) {
767 if (drm->drm_pktsize > MAX_DRM_PACKAGE_SIZE) {
768 pr_err("drm package size is error, size is %u\n", drm->drm_pktsize);
769 return -EINVAL;
770 }
771 /* buf only has drminfo not have esdata; */
772 realbuf = drm->drm_phy;
773 realcount = drm->drm_pktsize;
774 isphybuf = drm->drm_flag;
775 /* DRM_PRNT("drm_get_rawdata
776 *onlydrminfo drm->drm_hasesdata[0x%x]
777 * stbuf->type %d buf[0x%x]\n",
778 *drm->drm_hasesdata,stbuf->type,buf);
779 */
780 } else if (drm->drm_hasesdata == 1) { /* buf is drminfo+es; */
781 if (drm->drm_pktsize > MAX_DRM_PACKAGE_SIZE) {
782 pr_err("drm package size is error, size is %u\n", drm->drm_pktsize);
783 return -EINVAL;
784 }
785 realcount = drm->drm_pktsize;
786 realbuf = (unsigned long)buf + sizeof(struct drm_info);
787 isphybuf = 0;
788 /* DRM_PRNT("drm_get_rawdata
789 * drminfo+es drm->drm_hasesdata[0x%x]
790 * stbuf->type %d\n",drm->drm_hasesdata,stbuf->type);
791 */
792 } else { /* buf is hwhead; */
793 realcount = count;
794 isphybuf = 0;
795 realbuf = (unsigned long)buf;
796 /* DRM_PRNT("drm_get_rawdata
797 * drm->drm_hasesdata[0x%x]
798 * len[%d] count[%d] realcout[%d]\n",
799 * drm->drm_hasesdata,len,count,realcount);
800 */
801 }
802
803 len = realcount;
804 count = realcount;
805 totalcount = realcount;
806
807 while (len > 0) {
808 if (stbuf->type != BUF_TYPE_SUBTITLE
809 && stbuf_space(stbuf) < count) {
810 /*should not write partial data in drm mode*/
811 r = stbuf_wait_space(stbuf, count);
812 if (r < 0)
813 return r;
814 if (stbuf_space(stbuf) < count)
815 return -EAGAIN;
816 }
817 len = min_t(u32, len, count);
818
819 mutex_lock(&esparser_mutex);
820
821 if (stbuf->type != BUF_TYPE_AUDIO)
822 r = _esparser_write((const char __user *)realbuf, len,
823 stbuf, isphybuf);
824 else
825 r = _esparser_write_s((const char __user *)realbuf, len,
826 stbuf);
827 if (r < 0) {
828 pr_info("drm_write _esparser_write failed [%d]\n", r);
829 mutex_unlock(&esparser_mutex);
830 return r;
831 }
832 havewritebytes += r;
833 leftcount = totalcount - havewritebytes;
834 if (havewritebytes == totalcount) {
835
836 mutex_unlock(&esparser_mutex);
837 break; /* write ok; */
838 } else if ((len > 0) && (havewritebytes < totalcount)) {
839 DRM_PRNT
840 ("d writebytes[%d] want[%d] total[%d] real[%d]\n",
841 havewritebytes, len, totalcount, realcount);
842 len = len - r; /* write again; */
843 realbuf = realbuf + r;
844 } else {
845 pr_info
846 ("e writebytes[%d] want[%d] total[%d] real[%d]\n",
847 havewritebytes, len, totalcount, realcount);
848 }
849 mutex_unlock(&esparser_mutex);
850 }
851
852 return havewritebytes;
853}
854EXPORT_SYMBOL(drm_write);
855
856/*
857 *flags:
858 *1:phy
859 *2:noblock
860 */
861ssize_t esparser_write_ex(struct file *file,
862 struct stream_buf_s *stbuf,
863 const char __user *buf, size_t count,
864 int flags)
865{
866
867 s32 r;
868 u32 len = count;
869
870 if (buf == NULL || count == 0)
871 return -EINVAL;
872
873 /*subtitle have no level to check, */
874 if (stbuf->type != BUF_TYPE_SUBTITLE && stbuf_space(stbuf) < count) {
875 if ((flags & 2) || ((file != NULL) &&
876 (file->f_flags & O_NONBLOCK))) {
877 len = stbuf_space(stbuf);
878
879 if (len < 256) /* <1k.do eagain, */
880 return -EAGAIN;
881 } else {
882 len = min(stbuf_canusesize(stbuf) / 8, len);
883
884 if (stbuf_space(stbuf) < len) {
885 r = stbuf_wait_space(stbuf, len);
886 if (r < 0)
887 return r;
888 }
889 }
890 }
891
892 stbuf->last_write_jiffies64 = jiffies_64;
893
894 len = min_t(u32, len, count);
895
896 mutex_lock(&esparser_mutex);
897
898 if (stbuf->type == BUF_TYPE_AUDIO)
899 r = _esparser_write_s(buf, len, stbuf);
900 else
901 r = _esparser_write(buf, len, stbuf, flags & 1);
902
903 mutex_unlock(&esparser_mutex);
904
905 return r;
906}
907ssize_t esparser_write(struct file *file,
908 struct stream_buf_s *stbuf,
909 const char __user *buf, size_t count)
910{
911 if (stbuf->write_thread) {
912 ssize_t ret;
913
914 ret = threadrw_write(file, stbuf, buf, count);
915 if (ret == -EAGAIN) {
916 u32 a, b;
917 int vdelay, adelay;
918
919 if ((stbuf->type != BUF_TYPE_VIDEO) &&
920 (stbuf->type != BUF_TYPE_HEVC))
921 return ret;
922 if (stbuf->buf_size > (SZ_1M * 30) ||
923 (threadrw_buffer_size(stbuf) > SZ_1M * 10) ||
924 !threadrw_support_more_buffers(stbuf))
925 return ret;
926 /*only chang buffer for video.*/
927 vdelay = calculation_stream_delayed_ms(
928 PTS_TYPE_VIDEO, &a, &b);
929 adelay = calculation_stream_delayed_ms(
930 PTS_TYPE_AUDIO, &a, &b);
931 if ((vdelay > 100 && vdelay < 2000) && /*vdelay valid.*/
932 ((vdelay < 500) ||/*video delay is short!*/
933 (adelay > 0 && adelay < 1000))/*audio is low.*/
934 ) {
935 /*on buffer fulled.
936 *if delay is less than 100ms we think errors,
937 *And we add more buffer on delay < 2s.
938 */
939 int new_size = 2 * 1024 * 1024;
940
941 threadrw_alloc_more_buffer_size(
942 stbuf, new_size);
943 }
944 }
945 return ret;
946 }
947 return esparser_write_ex(file, stbuf, buf, count, 0);
948}
949EXPORT_SYMBOL(esparser_write);
950
951void esparser_sub_reset(void)
952{
953 ulong flags;
954 DEFINE_SPINLOCK(lock);
955 u32 parser_sub_start_ptr;
956 u32 parser_sub_end_ptr;
957
958 spin_lock_irqsave(&lock, flags);
959
960 parser_sub_start_ptr = READ_PARSER_REG(PARSER_SUB_START_PTR);
961 parser_sub_end_ptr = READ_PARSER_REG(PARSER_SUB_END_PTR);
962
963 WRITE_PARSER_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr);
964 WRITE_PARSER_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr);
965 WRITE_PARSER_REG(PARSER_SUB_RP, parser_sub_start_ptr);
966 WRITE_PARSER_REG(PARSER_SUB_WP, parser_sub_start_ptr);
967 SET_PARSER_REG_MASK(PARSER_ES_CONTROL,
968 (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR);
969
970 spin_unlock_irqrestore(&lock, flags);
971}
972