summaryrefslogtreecommitdiff
path: root/drivers/stream_input/parser/esparser.c (plain)
blob: d9de02c1b3236398f19c055b178cd1025aa625ae
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_MPEG_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
64static unsigned char *search_pattern;
65static dma_addr_t search_pattern_map;
66static u32 audio_real_wp;
67static u32 audio_buf_start;
68static u32 audio_buf_end;
69
70static const char esparser_id[] = "esparser-id";
71
72static DECLARE_WAIT_QUEUE_HEAD(wq);
73
74
75static u32 search_done;
76static u32 video_data_parsed;
77static u32 audio_data_parsed;
78static atomic_t esparser_use_count = ATOMIC_INIT(0);
79static DEFINE_MUTEX(esparser_mutex);
80
81static inline u32 get_buf_wp(u32 type)
82{
83 if (type == BUF_TYPE_AUDIO)
84 return audio_real_wp;
85 else
86 return 0;
87}
88static inline u32 get_buf_start(u32 type)
89{
90 if (type == BUF_TYPE_AUDIO)
91 return audio_buf_start;
92 else
93 return 0;
94}
95static inline u32 get_buf_end(u32 type)
96{
97 if (type == BUF_TYPE_AUDIO)
98 return audio_buf_end;
99 else
100 return 0;
101}
102static void set_buf_wp(u32 type, u32 wp)
103{
104 if (type == BUF_TYPE_AUDIO) {
105 audio_real_wp = wp;
106 WRITE_MPEG_REG(AIU_MEM_AIFIFO_MAN_WP, wp/* & 0xffffff00*/);
107 }
108}
109
110static irqreturn_t esparser_isr(int irq, void *dev_id)
111{
112 u32 int_status = READ_MPEG_REG(PARSER_INT_STATUS);
113
114 WRITE_MPEG_REG(PARSER_INT_STATUS, int_status);
115
116 if (int_status & PARSER_INTSTAT_SC_FOUND) {
117 WRITE_MPEG_REG(PFIFO_RD_PTR, 0);
118 WRITE_MPEG_REG(PFIFO_WR_PTR, 0);
119 search_done = 1;
120 wake_up_interruptible(&wq);
121 }
122 return IRQ_HANDLED;
123}
124
125static inline u32 buf_wp(u32 type)
126{
127 u32 wp;
128
129 if ((READ_MPEG_REG(PARSER_ES_CONTROL) & ES_VID_MAN_RD_PTR) == 0) {
130 wp =
131#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
132 (type == BUF_TYPE_HEVC) ? READ_VREG(HEVC_STREAM_WR_PTR) :
133#endif
134 (type == BUF_TYPE_VIDEO) ? READ_VREG(VLD_MEM_VIFIFO_WP) :
135 (type == BUF_TYPE_AUDIO) ?
136 READ_MPEG_REG(AIU_MEM_AIFIFO_MAN_WP) :
137 READ_MPEG_REG(PARSER_SUB_START_PTR);
138 } else {
139 wp =
140#if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
141 (type == BUF_TYPE_HEVC) ? READ_MPEG_REG(PARSER_VIDEO_WP) :
142#endif
143 (type == BUF_TYPE_VIDEO) ? READ_MPEG_REG(PARSER_VIDEO_WP) :
144 (type == BUF_TYPE_AUDIO) ?
145 READ_MPEG_REG(AIU_MEM_AIFIFO_MAN_WP) :
146 READ_MPEG_REG(PARSER_SUB_START_PTR);
147 }
148
149 return wp;
150}
151
152static ssize_t _esparser_write(const char __user *buf,
153 size_t count, u32 type, int isphybuf)
154{
155 size_t r = count;
156 const char __user *p = buf;
157
158 u32 len = 0;
159 u32 parser_type;
160 int ret;
161 u32 wp;
162 dma_addr_t dma_addr = 0;
163
164 if (type == BUF_TYPE_HEVC)
165 parser_type = PARSER_VIDEO;
166 else if (type == BUF_TYPE_VIDEO)
167 parser_type = PARSER_VIDEO;
168 else if (type == BUF_TYPE_AUDIO)
169 parser_type = PARSER_AUDIO;
170 else
171 parser_type = PARSER_SUBPIC;
172
173 wp = buf_wp(type);
174
175 if (r > 0) {
176 if (isphybuf)
177 len = count;
178 else {
179 len = min_t(size_t, r, (size_t) FETCHBUF_SIZE);
180
181 if (copy_from_user(fetchbuf, p, len))
182 return -EFAULT;
183 dma_addr = dma_map_single(
184 amports_get_dma_device(), fetchbuf,
185 FETCHBUF_SIZE, DMA_TO_DEVICE);
186 if (dma_mapping_error(amports_get_dma_device(),
187 (dma_addr_t) dma_addr))
188 return -EFAULT;
189
190 }
191
192 /* wmb(); don't need */
193 /* reset the Write and read pointer to zero again */
194 WRITE_MPEG_REG(PFIFO_RD_PTR, 0);
195 WRITE_MPEG_REG(PFIFO_WR_PTR, 0);
196
197 WRITE_MPEG_REG_BITS(PARSER_CONTROL, len, ES_PACK_SIZE_BIT,
198 ES_PACK_SIZE_WID);
199 WRITE_MPEG_REG_BITS(PARSER_CONTROL,
200 parser_type | PARSER_WRITE |
201 PARSER_AUTOSEARCH, ES_CTRL_BIT,
202 ES_CTRL_WID);
203
204 if (isphybuf) {
205 u32 buf_32 = (unsigned long)buf & 0xffffffff;
206
207 WRITE_MPEG_REG(PARSER_FETCH_ADDR, buf_32);
208 } else {
209 WRITE_MPEG_REG(PARSER_FETCH_ADDR, dma_addr);
210 dma_unmap_single(amports_get_dma_device(), dma_addr,
211 FETCHBUF_SIZE, DMA_TO_DEVICE);
212 }
213
214 search_done = 0;
215 if (!(isphybuf & TYPE_PATTERN)) {
216 WRITE_MPEG_REG(PARSER_FETCH_CMD,
217 (7 << FETCH_ENDIAN) | len);
218 WRITE_MPEG_REG(PARSER_FETCH_ADDR, search_pattern_map);
219 WRITE_MPEG_REG(PARSER_FETCH_CMD,
220 (7 << FETCH_ENDIAN) | SEARCH_PATTERN_LEN);
221 } else {
222 WRITE_MPEG_REG(PARSER_FETCH_CMD,
223 (7 << FETCH_ENDIAN) | (len + 512));
224 }
225 ret = wait_event_interruptible_timeout(wq, search_done != 0,
226 HZ / 5);
227 if (ret == 0) {
228 WRITE_MPEG_REG(PARSER_FETCH_CMD, 0);
229
230 if (wp == buf_wp(type))
231 /*no data fetched */
232 return -EAGAIN;
233
234 pr_info("W Timeout, but fetch ok,");
235 pr_info("type %d len=%d,wpdiff=%d, isphy %x\n",
236 type, len, wp - buf_wp(type), isphybuf);
237
238 } else if (ret < 0)
239 return -ERESTARTSYS;
240 }
241
242 if ((type == BUF_TYPE_VIDEO)
243 || (has_hevc_vdec() && (type == BUF_TYPE_HEVC)))
244 video_data_parsed += len;
245 else if (type == BUF_TYPE_AUDIO)
246 audio_data_parsed += len;
247
248 return len;
249}
250
251static ssize_t _esparser_write_s(const char __user *buf,
252 size_t count, u32 type)
253{
254 size_t r = count;
255 const char __user *p = buf;
256 u32 len = 0;
257 int ret;
258 u32 wp, buf_start, buf_end;
259 dma_addr_t buf_wp_map;
260
261 if (type != BUF_TYPE_AUDIO)
262 WARN_ON(1);/*BUG();*/
263 wp = get_buf_wp(type);
264 buf_end = get_buf_end(type) + 8;
265 buf_start = get_buf_start(type);
266 /*pr_info("write wp 0x%x, count %d, start 0x%x, end 0x%x\n",*/
267 /* wp, (u32)count, buf_start, buf_end);*/
268 if (wp + count > buf_end) {
269 ret = copy_from_user(codec_mm_phys_to_virt(wp),
270 p, buf_end - wp);
271 if (ret > 0) {
272 len += buf_end - wp - ret;
273 buf_wp_map = dma_map_single(amports_get_dma_device(),
274 codec_mm_phys_to_virt(wp), len, DMA_TO_DEVICE);
275 wp += len;
276 pr_info("copy from user not finished\n");
277 dma_unmap_single(NULL, buf_wp_map, len, DMA_TO_DEVICE);
278 set_buf_wp(type, wp);
279 goto end_write;
280 } else if (ret == 0) {
281 len += buf_end - wp;
282 buf_wp_map = dma_map_single(amports_get_dma_device(),
283 codec_mm_phys_to_virt(wp), len, DMA_TO_DEVICE);
284 wp = buf_start;
285 r = count - len;
286 dma_unmap_single(NULL, buf_wp_map, len, DMA_TO_DEVICE);
287 set_buf_wp(type, wp);
288 } else {
289 pr_info("copy from user failed 1\n");
290 pr_info("w wp 0x%x, count %d, start 0x%x end 0x%x\n",
291 wp, (u32)count, buf_start, buf_end);
292 return -EAGAIN;
293 }
294 }
295 ret = copy_from_user(codec_mm_phys_to_virt(wp), p + len, r);
296 if (ret >= 0) {
297 len += r - ret;
298 buf_wp_map = dma_map_single(amports_get_dma_device(),
299 codec_mm_phys_to_virt(wp), r - ret, DMA_TO_DEVICE);
300
301 if (ret > 0)
302 pr_info("copy from user not finished 2\n");
303 wp += r - ret;
304 dma_unmap_single(NULL, buf_wp_map, r - ret, DMA_TO_DEVICE);
305 set_buf_wp(type, wp);
306 } else {
307 pr_info("copy from user failed 2\n");
308 return -EAGAIN;
309 }
310
311end_write:
312 if (type == BUF_TYPE_AUDIO)
313 audio_data_parsed += len;
314
315 return len;
316}
317
318s32 es_vpts_checkin_us64(struct stream_buf_s *buf, u64 us64)
319{
320 u32 passed;
321
322 if (buf->write_thread)
323 passed = threadrw_dataoffset(buf);
324 else
325 passed = video_data_parsed;
326 return pts_checkin_offset_us64(PTS_TYPE_VIDEO, passed, us64);
327
328}
329
330s32 es_apts_checkin_us64(struct stream_buf_s *buf, u64 us64)
331{
332 u32 passed;
333
334 if (buf->write_thread)
335 passed = threadrw_dataoffset(buf);
336 else
337 passed = audio_data_parsed;
338 return pts_checkin_offset_us64(PTS_TYPE_AUDIO, passed, us64);
339}
340
341s32 es_vpts_checkin(struct stream_buf_s *buf, u32 pts)
342{
343#if 0
344 if (buf->first_tstamp == INVALID_PTS) {
345 buf->flag |= BUF_FLAG_FIRST_TSTAMP;
346 buf->first_tstamp = pts;
347 return 0;
348 }
349#endif
350 u32 passed = video_data_parsed + threadrw_buffer_level(buf);
351
352 return pts_checkin_offset(PTS_TYPE_VIDEO, passed, pts);
353
354}
355
356s32 es_apts_checkin(struct stream_buf_s *buf, u32 pts)
357{
358#if 0
359 if (buf->first_tstamp == INVALID_PTS) {
360 buf->flag |= BUF_FLAG_FIRST_TSTAMP;
361 buf->first_tstamp = pts;
362
363 return 0;
364 }
365#endif
366 u32 passed = audio_data_parsed + threadrw_buffer_level(buf);
367
368 return pts_checkin_offset(PTS_TYPE_AUDIO, passed, pts);
369}
370
371s32 esparser_init(struct stream_buf_s *buf, struct vdec_s *vdec)
372{
373 s32 r = 0;
374 u32 pts_type;
375 u32 parser_sub_start_ptr;
376 u32 parser_sub_end_ptr;
377 u32 parser_sub_rp;
378 bool first_use = false;
379 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
380 if (has_hevc_vdec() && (buf->type == BUF_TYPE_HEVC))
381 pts_type = PTS_TYPE_HEVC;
382 else
383 /* #endif */
384 if (buf->type == BUF_TYPE_VIDEO)
385 pts_type = PTS_TYPE_VIDEO;
386 else if (buf->type == BUF_TYPE_AUDIO)
387 pts_type = PTS_TYPE_AUDIO;
388 else if (buf->type == BUF_TYPE_SUBTITLE)
389 pts_type = PTS_TYPE_MAX;
390 else
391 return -EINVAL;
392 mutex_lock(&esparser_mutex);
393 parser_sub_start_ptr = READ_MPEG_REG(PARSER_SUB_START_PTR);
394 parser_sub_end_ptr = READ_MPEG_REG(PARSER_SUB_END_PTR);
395 parser_sub_rp = READ_MPEG_REG(PARSER_SUB_RP);
396
397 buf->flag |= BUF_FLAG_PARSER;
398
399 if (atomic_add_return(1, &esparser_use_count) == 1) {
400 first_use = true;
401
402 if (fetchbuf == 0) {
403 pr_info("%s: no fetchbuf\n", __func__);
404 r = -ENOMEM;
405 goto Err_1;
406 }
407
408 if (search_pattern == NULL) {
409 search_pattern = kcalloc(1,
410 SEARCH_PATTERN_LEN,
411 GFP_KERNEL);
412
413 if (search_pattern == NULL) {
414 pr_err("%s: no search_pattern\n", __func__);
415 r = -ENOMEM;
416 goto Err_1;
417 }
418
419 /* build a fake start code to get parser interrupt */
420 search_pattern[0] = 0x00;
421 search_pattern[1] = 0x00;
422 search_pattern[2] = 0x01;
423 search_pattern[3] = 0xff;
424
425 search_pattern_map = dma_map_single(
426 amports_get_dma_device(),
427 search_pattern,
428 SEARCH_PATTERN_LEN,
429 DMA_TO_DEVICE);
430 }
431
432 /* reset PARSER with first esparser_init() call */
433 WRITE_MPEG_REG(RESET1_REGISTER, RESET_PARSER);
434
435 /* TS data path */
436#ifndef CONFIG_AM_DVB
437 WRITE_MPEG_REG(FEC_INPUT_CONTROL, 0);
438#else
439 tsdemux_set_reset_flag();
440#endif
441 CLEAR_MPEG_REG_MASK(TS_HIU_CTL, 1 << USE_HI_BSF_INTERFACE);
442 CLEAR_MPEG_REG_MASK(TS_HIU_CTL_2, 1 << USE_HI_BSF_INTERFACE);
443 CLEAR_MPEG_REG_MASK(TS_HIU_CTL_3, 1 << USE_HI_BSF_INTERFACE);
444
445 CLEAR_MPEG_REG_MASK(TS_FILE_CONFIG, (1 << TS_HIU_ENABLE));
446
447 WRITE_MPEG_REG(PARSER_CONFIG,
448 (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) |
449 (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) |
450 (16 << PS_CFG_MAX_FETCH_CYCLE_BIT));
451
452 WRITE_MPEG_REG(PFIFO_RD_PTR, 0);
453 WRITE_MPEG_REG(PFIFO_WR_PTR, 0);
454
455 WRITE_MPEG_REG(PARSER_SEARCH_PATTERN, ES_START_CODE_PATTERN);
456 WRITE_MPEG_REG(PARSER_SEARCH_MASK, ES_START_CODE_MASK);
457
458 WRITE_MPEG_REG(PARSER_CONFIG,
459 (10 << PS_CFG_PFIFO_EMPTY_CNT_BIT) |
460 (1 << PS_CFG_MAX_ES_WR_CYCLE_BIT) |
461 PS_CFG_STARTCODE_WID_24 |
462 PS_CFG_PFIFO_ACCESS_WID_8 |
463 /* single byte pop */
464 (16 << PS_CFG_MAX_FETCH_CYCLE_BIT));
465
466 WRITE_MPEG_REG(PARSER_CONTROL, PARSER_AUTOSEARCH);
467
468 }
469 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
470 /* hook stream buffer with PARSER */
471 if (has_hevc_vdec() && (pts_type == PTS_TYPE_HEVC)) {
472 WRITE_MPEG_REG(PARSER_VIDEO_START_PTR, vdec->input.start);
473 WRITE_MPEG_REG(PARSER_VIDEO_END_PTR, vdec->input.start
474 + vdec->input.size - 8);
475
476 if (vdec_stream_auto(vdec)) {
477 CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL,
478 ES_VID_MAN_RD_PTR);
479
480 /* set vififo_vbuf_rp_sel=>hevc */
481 WRITE_VREG(DOS_GEN_CTRL0, 3 << 1);
482
483 /* set use_parser_vbuf_wp */
484 SET_VREG_MASK(HEVC_STREAM_CONTROL,
485 (1 << 3) | (0 << 4));
486 /* set stream_fetch_enable */
487 SET_VREG_MASK(HEVC_STREAM_CONTROL, 1);
488
489 /* set stream_buffer_hole with 256 bytes */
490 SET_VREG_MASK(HEVC_STREAM_FIFO_CTL,
491 (1 << 29));
492 } else {
493 SET_MPEG_REG_MASK(PARSER_ES_CONTROL,
494 ES_VID_MAN_RD_PTR);
495 WRITE_MPEG_REG(PARSER_VIDEO_WP, vdec->input.start);
496 WRITE_MPEG_REG(PARSER_VIDEO_RP, vdec->input.start);
497 }
498 video_data_parsed = 0;
499 } else
500 /* #endif */
501 if (pts_type == PTS_TYPE_VIDEO) {
502 WRITE_MPEG_REG(PARSER_VIDEO_START_PTR,
503 vdec->input.start);
504 WRITE_MPEG_REG(PARSER_VIDEO_END_PTR,
505 vdec->input.start + vdec->input.size - 8);
506 if (vdec_stream_auto(vdec)) {
507 CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL,
508 ES_VID_MAN_RD_PTR);
509 WRITE_VREG(VLD_MEM_VIFIFO_BUF_CNTL,
510 MEM_BUFCTRL_INIT);
511 CLEAR_VREG_MASK(VLD_MEM_VIFIFO_BUF_CNTL,
512 MEM_BUFCTRL_INIT);
513
514 if (has_hevc_vdec()) {
515 /* set vififo_vbuf_rp_sel=>vdec */
516 WRITE_VREG(DOS_GEN_CTRL0, 0);
517
518 }
519 } else {
520 SET_MPEG_REG_MASK(PARSER_ES_CONTROL,
521 ES_VID_MAN_RD_PTR);
522 WRITE_MPEG_REG(PARSER_VIDEO_WP,
523 vdec->input.start);
524 WRITE_MPEG_REG(PARSER_VIDEO_RP,
525 vdec->input.start);
526 }
527 video_data_parsed = 0;
528 } else if (pts_type == PTS_TYPE_AUDIO) {
529 /* set wp as buffer start */
530 SET_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL,
531 MEM_BUFCTRL_MANUAL);
532 WRITE_MPEG_REG(AIU_MEM_AIFIFO_MAN_RP,
533 READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR));
534 WRITE_MPEG_REG_BITS(AIU_MEM_AIFIFO_CONTROL, 7, 3, 3);
535 SET_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL,
536 MEM_BUFCTRL_INIT);
537 CLEAR_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL,
538 MEM_BUFCTRL_INIT);
539 WRITE_MPEG_REG(AIU_MEM_AIFIFO_MAN_WP,
540 READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR));
541 audio_data_parsed = 0;
542 audio_buf_start =
543 READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR);
544 audio_real_wp = audio_buf_start;
545 audio_buf_end = READ_MPEG_REG(AIU_MEM_AIFIFO_END_PTR);
546 } else if (buf->type == BUF_TYPE_SUBTITLE) {
547 WRITE_MPEG_REG(PARSER_SUB_START_PTR,
548 parser_sub_start_ptr);
549 WRITE_MPEG_REG(PARSER_SUB_END_PTR,
550 parser_sub_end_ptr);
551 WRITE_MPEG_REG(PARSER_SUB_RP, parser_sub_rp);
552 SET_MPEG_REG_MASK(PARSER_ES_CONTROL,
553 (7 << ES_SUB_WR_ENDIAN_BIT) |
554 ES_SUB_MAN_RD_PTR);
555 }
556
557 if (pts_type < PTS_TYPE_MAX) {
558 r = pts_start(pts_type);
559
560 if (r < 0) {
561 pr_info("esparser_init: pts_start failed\n");
562 goto Err_1;
563 }
564 }
565#if 0
566 if (buf->flag & BUF_FLAG_FIRST_TSTAMP) {
567 if (buf->type == BUF_TYPE_VIDEO)
568 es_vpts_checkin(buf, buf->first_tstamp);
569 else if (buf->type == BUF_TYPE_AUDIO)
570 es_apts_checkin(buf, buf->first_tstamp);
571
572 buf->flag &= ~BUF_FLAG_FIRST_TSTAMP;
573 }
574#endif
575
576 if (first_use) {
577 /*TODO irq */
578 r = vdec_request_irq(PARSER_IRQ, esparser_isr,
579 "parser", (void *)esparser_id);
580
581 if (r) {
582 pr_info("esparser_init: irq register failed.\n");
583 goto Err_2;
584 }
585
586 WRITE_MPEG_REG(PARSER_INT_STATUS, 0xffff);
587 WRITE_MPEG_REG(PARSER_INT_ENABLE,
588 PARSER_INTSTAT_SC_FOUND <<
589 PARSER_INT_HOST_EN_BIT);
590 }
591 mutex_unlock(&esparser_mutex);
592 if (!(amports_get_debug_flags() & 1) &&
593 !codec_mm_video_tvp_enabled()) {
594 int block_size = (buf->type == BUF_TYPE_AUDIO) ?
595 PAGE_SIZE << 2 : PAGE_SIZE << 4;
596 int buf_num = (buf->type == BUF_TYPE_AUDIO) ?
597 5 : 10;
598 if (!(buf->type == BUF_TYPE_SUBTITLE))
599 buf->write_thread = threadrw_alloc(buf_num,
600 block_size,
601 esparser_write_ex,
602 (buf->type == BUF_TYPE_AUDIO) ? 1 : 0);
603 /*manul mode for audio*/
604 }
605 return 0;
606
607Err_2:
608 pts_stop(pts_type);
609
610Err_1:
611 atomic_dec(&esparser_use_count);
612 buf->flag &= ~BUF_FLAG_PARSER;
613 mutex_unlock(&esparser_mutex);
614 return r;
615}
616
617void esparser_audio_reset_s(struct stream_buf_s *buf)
618{
619 ulong flags;
620 DEFINE_SPINLOCK(lock);
621
622 spin_lock_irqsave(&lock, flags);
623
624 SET_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_MANUAL);
625 WRITE_MPEG_REG(AIU_MEM_AIFIFO_MAN_RP,
626 READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR));
627 WRITE_MPEG_REG_BITS(AIU_MEM_AIFIFO_CONTROL, 7, 3, 3);
628 SET_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
629 CLEAR_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
630 WRITE_MPEG_REG(AIU_MEM_AIFIFO_MAN_WP,
631 READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR));
632
633 buf->flag |= BUF_FLAG_PARSER;
634
635 audio_data_parsed = 0;
636 audio_real_wp = READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR);
637 spin_unlock_irqrestore(&lock, flags);
638
639}
640
641void esparser_audio_reset(struct stream_buf_s *buf)
642{
643 ulong flags;
644 DEFINE_SPINLOCK(lock);
645
646 spin_lock_irqsave(&lock, flags);
647
648 WRITE_MPEG_REG(PARSER_AUDIO_WP,
649 READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR));
650 WRITE_MPEG_REG(PARSER_AUDIO_RP,
651 READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR));
652
653 WRITE_MPEG_REG(PARSER_AUDIO_START_PTR,
654 READ_MPEG_REG(AIU_MEM_AIFIFO_START_PTR));
655 WRITE_MPEG_REG(PARSER_AUDIO_END_PTR,
656 READ_MPEG_REG(AIU_MEM_AIFIFO_END_PTR));
657 CLEAR_MPEG_REG_MASK(PARSER_ES_CONTROL, ES_AUD_MAN_RD_PTR);
658
659 WRITE_MPEG_REG(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
660 CLEAR_MPEG_REG_MASK(AIU_MEM_AIFIFO_BUF_CNTL, MEM_BUFCTRL_INIT);
661
662 buf->flag |= BUF_FLAG_PARSER;
663
664 audio_data_parsed = 0;
665 audio_real_wp = 0;
666 audio_buf_start = 0;
667 audio_buf_end = 0;
668 spin_unlock_irqrestore(&lock, flags);
669
670}
671
672void esparser_release(struct stream_buf_s *buf)
673{
674 u32 pts_type;
675
676 /* check if esparser_init() is ever called */
677 if ((buf->flag & BUF_FLAG_PARSER) == 0)
678 return;
679
680 if (atomic_read(&esparser_use_count) == 0) {
681 pr_info
682 ("[%s:%d]###warning, esparser has been released already\n",
683 __func__, __LINE__);
684 return;
685 }
686 if (buf->write_thread)
687 threadrw_release(buf);
688 if (atomic_dec_and_test(&esparser_use_count)) {
689 WRITE_MPEG_REG(PARSER_INT_ENABLE, 0);
690 /*TODO irq */
691
692 vdec_free_irq(PARSER_IRQ, (void *)esparser_id);
693
694 if (search_pattern) {
695 dma_unmap_single(amports_get_dma_device(),
696 search_pattern_map,
697 SEARCH_PATTERN_LEN, DMA_TO_DEVICE);
698 kfree(search_pattern);
699 search_pattern = NULL;
700 }
701 }
702
703 if (has_hevc_vdec() && (buf->type == BUF_TYPE_HEVC))
704 pts_type = PTS_TYPE_VIDEO;
705 else if (buf->type == BUF_TYPE_VIDEO)
706 pts_type = PTS_TYPE_VIDEO;
707 else if (buf->type == BUF_TYPE_AUDIO)
708 pts_type = PTS_TYPE_AUDIO;
709 else if (buf->type == BUF_TYPE_SUBTITLE) {
710 buf->flag &= ~BUF_FLAG_PARSER;
711 return;
712 } else
713 return;
714
715 buf->flag &= ~BUF_FLAG_PARSER;
716 pts_stop(pts_type);
717}
718
719ssize_t drm_write(struct file *file, struct stream_buf_s *stbuf,
720 const char __user *buf, size_t count)
721{
722 s32 r;
723 u32 len;
724 u32 realcount, totalcount;
725 u32 re_count = count;
726 u32 havewritebytes = 0;
727 u32 leftcount = 0;
728
729 struct drm_info tmpmm;
730 struct drm_info *drm = &tmpmm;
731 u32 res = 0;
732 int isphybuf = 0;
733 unsigned long realbuf;
734
735 if (buf == NULL || count == 0)
736 return -EINVAL;
737 if (stbuf->write_thread) {
738 r = threadrw_flush_buffers(stbuf);
739 if (r < 0)
740 pr_info("Warning. drm flush threadrw failed[%d]\n", r);
741 }
742 res = copy_from_user(drm, buf, sizeof(struct drm_info));
743 if (res) {
744 pr_info("drm kmalloc failed res[%d]\n", res);
745 return -EFAULT;
746 }
747
748 if ((drm->drm_flag & TYPE_DRMINFO) && (drm->drm_hasesdata == 0)) {
749 /* buf only has drminfo not have esdata; */
750 realbuf = drm->drm_phy;
751 realcount = drm->drm_pktsize;
752 isphybuf = drm->drm_flag;
753 /* DRM_PRNT("drm_get_rawdata
754 *onlydrminfo drm->drm_hasesdata[0x%x]
755 * stbuf->type %d buf[0x%x]\n",
756 *drm->drm_hasesdata,stbuf->type,buf);
757 */
758 } else if (drm->drm_hasesdata == 1) { /* buf is drminfo+es; */
759 realcount = drm->drm_pktsize;
760 realbuf = (unsigned long)buf + sizeof(struct drm_info);
761 isphybuf = 0;
762 /* DRM_PRNT("drm_get_rawdata
763 * drminfo+es drm->drm_hasesdata[0x%x]
764 * stbuf->type %d\n",drm->drm_hasesdata,stbuf->type);
765 */
766 } else { /* buf is hwhead; */
767 realcount = count;
768 isphybuf = 0;
769 realbuf = (unsigned long)buf;
770 /* DRM_PRNT("drm_get_rawdata
771 * drm->drm_hasesdata[0x%x]
772 * len[%d] count[%d] realcout[%d]\n",
773 * drm->drm_hasesdata,len,count,realcount);
774 */
775 }
776
777 len = realcount;
778 count = realcount;
779 totalcount = realcount;
780
781 while (len > 0) {
782 if (stbuf->type != BUF_TYPE_SUBTITLE
783 && stbuf_space(stbuf) < count) {
784 len = min(stbuf_canusesize(stbuf) / 8, len);
785 if (stbuf_space(stbuf) < len) {
786 r = stbuf_wait_space(stbuf, len);
787 /* write part data , not allow return ; */
788 if ((r < leftcount) && (leftcount > 0))
789 continue;
790 else if ((r < 0) && (leftcount == 0))/*full; */
791 return -EAGAIN;
792 }
793 }
794 len = min_t(u32, len, count);
795
796 mutex_lock(&esparser_mutex);
797
798 if (stbuf->type != BUF_TYPE_AUDIO)
799 r = _esparser_write((const char __user *)realbuf, len,
800 stbuf->type, isphybuf);
801 else
802 r = _esparser_write_s((const char __user *)realbuf, len,
803 stbuf->type);
804 if (r < 0) {
805 pr_info("drm_write _esparser_write failed [%d]\n", r);
806 return r;
807 }
808 havewritebytes += r;
809 leftcount = totalcount - havewritebytes;
810 if (havewritebytes == totalcount) {
811
812 mutex_unlock(&esparser_mutex);
813 break; /* write ok; */
814 } else if ((len > 0) && (havewritebytes < totalcount)) {
815 DRM_PRNT
816 ("d writebytes[%d] want[%d] total[%d] real[%d]\n",
817 havewritebytes, len, totalcount, realcount);
818 len = len - r; /* write again; */
819 realbuf = realbuf + r;
820 } else {
821 pr_info
822 ("e writebytes[%d] want[%d] total[%d] real[%d]\n",
823 havewritebytes, len, totalcount, realcount);
824 }
825 mutex_unlock(&esparser_mutex);
826 }
827
828 return re_count;
829}
830/*
831*flags:
832*1:phy
833*2:noblock
834*/
835ssize_t esparser_write_ex(struct file *file,
836 struct stream_buf_s *stbuf,
837 const char __user *buf, size_t count,
838 int flags)
839{
840
841 s32 r;
842 u32 len = count;
843
844 if (buf == NULL || count == 0)
845 return -EINVAL;
846
847 /*subtitle have no level to check, */
848 if (stbuf->type != BUF_TYPE_SUBTITLE && stbuf_space(stbuf) < count) {
849 if ((flags & 2) || ((file != NULL) &&
850 (file->f_flags & O_NONBLOCK))) {
851 len = stbuf_space(stbuf);
852
853 if (len < 256) /* <1k.do eagain, */
854 return -EAGAIN;
855 } else {
856 len = min(stbuf_canusesize(stbuf) / 8, len);
857
858 if (stbuf_space(stbuf) < len) {
859 r = stbuf_wait_space(stbuf, len);
860 if (r < 0)
861 return r;
862 }
863 }
864 }
865
866 stbuf->last_write_jiffies64 = jiffies_64;
867
868 len = min_t(u32, len, count);
869
870 mutex_lock(&esparser_mutex);
871
872 if (stbuf->type == BUF_TYPE_AUDIO)
873 r = _esparser_write_s(buf, len, stbuf->type);
874 else
875 r = _esparser_write(buf, len, stbuf->type, flags & 1);
876
877 mutex_unlock(&esparser_mutex);
878
879 return r;
880}
881ssize_t esparser_write(struct file *file,
882 struct stream_buf_s *stbuf,
883 const char __user *buf, size_t count)
884{
885 if (stbuf->write_thread)
886 return threadrw_write(file, stbuf, buf, count);
887 return esparser_write_ex(file, stbuf, buf, count, 0);
888}
889
890
891void esparser_sub_reset(void)
892{
893 ulong flags;
894 DEFINE_SPINLOCK(lock);
895 u32 parser_sub_start_ptr;
896 u32 parser_sub_end_ptr;
897
898 spin_lock_irqsave(&lock, flags);
899
900 parser_sub_start_ptr = READ_MPEG_REG(PARSER_SUB_START_PTR);
901 parser_sub_end_ptr = READ_MPEG_REG(PARSER_SUB_END_PTR);
902
903 WRITE_MPEG_REG(PARSER_SUB_START_PTR, parser_sub_start_ptr);
904 WRITE_MPEG_REG(PARSER_SUB_END_PTR, parser_sub_end_ptr);
905 WRITE_MPEG_REG(PARSER_SUB_RP, parser_sub_start_ptr);
906 WRITE_MPEG_REG(PARSER_SUB_WP, parser_sub_start_ptr);
907 SET_MPEG_REG_MASK(PARSER_ES_CONTROL,
908 (7 << ES_SUB_WR_ENDIAN_BIT) | ES_SUB_MAN_RD_PTR);
909
910 spin_unlock_irqrestore(&lock, flags);
911}
912