1 /*
2 * drivers/amlogic/media/stream_input/parser/streambuf.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 #define DEBUG
18 #include <linux/kernel.h>
19 #include <linux/spinlock.h>
20 #include <linux/timer.h>
21 #include <linux/sched.h>
22 #include <linux/fs.h>
23 #include <linux/io.h>
24 #include <linux/amlogic/media/frame_sync/ptsserv.h>
25 #include <linux/amlogic/media/utils/vformat.h>
26 #include <linux/amlogic/iomap.h>
27 #include <asm/cacheflush.h>
28 #include <linux/uaccess.h>
29 #include <linux/vmalloc.h>
30 /* #include <mach/am_regs.h> */
31
32 #include <linux/amlogic/media/utils/vdec_reg.h>
33 #include "../../frame_provider/decoder/utils/vdec.h"
34 #include "streambuf_reg.h"
35 #include "streambuf.h"
36 #include <linux/amlogic/media/utils/amports_config.h>
37 #include "../amports/amports_priv.h"
38 #include <linux/dma-mapping.h>
39 #include <linux/dma-contiguous.h>
40 #include <linux/amlogic/media/codec_mm/codec_mm.h>
41
42 #define STBUF_SIZE (64*1024)
43 #define STBUF_WAIT_INTERVAL (HZ/100)
44 #define MEM_NAME "streambuf"
45
46 void *fetchbuf = 0;
47
_stbuf_alloc(struct stream_buf_s * buf,bool is_secure)48 static s32 _stbuf_alloc(struct stream_buf_s *buf, bool is_secure)
49 {
50 if (buf->buf_size == 0)
51 return -ENOBUFS;
52
53 while (buf->buf_start == 0) {
54 int flags = CODEC_MM_FLAGS_DMA;
55
56 buf->buf_page_num = PAGE_ALIGN(buf->buf_size) / PAGE_SIZE;
57 if (buf->type == BUF_TYPE_SUBTITLE)
58 flags = CODEC_MM_FLAGS_DMA_CPU;
59
60 /*
61 *if 4k,
62 *used cma first,for less mem fragments.
63 */
64 if (((buf->type == BUF_TYPE_HEVC) ||
65 (buf->type == BUF_TYPE_VIDEO)) &&
66 buf->for_4k)
67 flags |= CODEC_MM_FLAGS_CMA_FIRST;
68 if (buf->buf_size > 20 * 1024 * 1024)
69 flags |= CODEC_MM_FLAGS_CMA_FIRST;
70
71 if ((buf->type == BUF_TYPE_HEVC) ||
72 (buf->type == BUF_TYPE_VIDEO)) {
73 flags |= CODEC_MM_FLAGS_FOR_VDECODER;
74 } else if (buf->type == BUF_TYPE_AUDIO) {
75 flags |= CODEC_MM_FLAGS_FOR_ADECODER;
76 flags |= CODEC_MM_FLAGS_DMA_CPU;
77 }
78
79 if (is_secure)
80 flags |= CODEC_MM_FLAGS_TVP;
81
82 buf->buf_start = codec_mm_alloc_for_dma(MEM_NAME,
83 buf->buf_page_num, 4+PAGE_SHIFT, flags);
84 if (!buf->buf_start) {
85 int is_video = (buf->type == BUF_TYPE_HEVC) ||
86 (buf->type == BUF_TYPE_VIDEO);
87 if (is_video && buf->buf_size >= 9 * SZ_1M) {/*min 6M*/
88 int old_size = buf->buf_size;
89
90 buf->buf_size =
91 PAGE_ALIGN(buf->buf_size * 2/3);
92 pr_info("%s stbuf alloced size = %d failed try small %d size\n",
93 (buf->type == BUF_TYPE_HEVC) ? "HEVC" :
94 (buf->type == BUF_TYPE_VIDEO) ? "Video" :
95 (buf->type == BUF_TYPE_AUDIO) ? "Audio" :
96 "Subtitle", old_size, buf->buf_size);
97 continue;
98 }
99 pr_info("%s stbuf alloced size = %d failed\n",
100 (buf->type == BUF_TYPE_HEVC) ? "HEVC" :
101 (buf->type == BUF_TYPE_VIDEO) ? "Video" :
102 (buf->type == BUF_TYPE_AUDIO) ? "Audio" :
103 "Subtitle", buf->buf_size);
104 return -ENOMEM;
105 }
106
107 buf->is_secure = is_secure;
108
109 pr_debug("%s stbuf alloced at %p, secure = %d, size = %d\n",
110 (buf->type == BUF_TYPE_HEVC) ? "HEVC" :
111 (buf->type == BUF_TYPE_VIDEO) ? "Video" :
112 (buf->type == BUF_TYPE_AUDIO) ? "Audio" :
113 "Subtitle", (void *)buf->buf_start,
114 buf->is_secure,
115 buf->buf_size);
116 }
117
118 buf->canusebuf_size = buf->buf_size;
119 buf->flag |= BUF_FLAG_ALLOC;
120
121 return 0;
122 }
123
stbuf_change_size(struct stream_buf_s * buf,int size,bool is_secure)124 int stbuf_change_size(struct stream_buf_s *buf, int size, bool is_secure)
125 {
126 unsigned long old_buf;
127 int old_size, old_pagenum;
128 int ret;
129
130 pr_info("buffersize=%d,%d,start=%p, secure=%d\n", size, buf->buf_size,
131 (void *)buf->buf_start, is_secure);
132
133 if (buf->buf_size == size && buf->buf_start != 0)
134 return 0;
135
136 old_buf = buf->buf_start;
137 old_size = buf->buf_size;
138 old_pagenum = buf->buf_page_num;
139 buf->buf_start = 0;
140 buf->buf_size = size;
141 ret = size;
142
143 if (size == 0 ||
144 _stbuf_alloc(buf, is_secure) == 0) {
145 /*
146 * size=0:We only free the old memory;
147 * alloc ok,changed to new buffer
148 */
149 if (old_buf != 0) {
150 codec_mm_free_for_dma(MEM_NAME, old_buf);
151 }
152
153 if (size == 0)
154 buf->is_secure = false;
155
156 pr_info("changed the (%d) buffer size from %d to %d\n",
157 buf->type, old_size, size);
158 return 0;
159 } else {
160 /* alloc failed */
161 buf->buf_start = old_buf;
162 buf->buf_size = old_size;
163 buf->buf_page_num = old_pagenum;
164 pr_info("changed the (%d) buffer size from %d to %d,failed\n",
165 buf->type, old_size, size);
166 }
167
168 return ret;
169 }
170
stbuf_fetch_init(void)171 int stbuf_fetch_init(void)
172 {
173 if (NULL != fetchbuf)
174 return 0;
175
176 fetchbuf = (void *)__get_free_pages(GFP_KERNEL,
177 get_order(FETCHBUF_SIZE));
178
179 if (!fetchbuf) {
180 pr_info("%s: Can not allocate fetch working buffer\n",
181 __func__);
182 return -ENOMEM;
183 }
184 return 0;
185 }
186 EXPORT_SYMBOL(stbuf_fetch_init);
187
stbuf_fetch_release(void)188 void stbuf_fetch_release(void)
189 {
190 if (0 && fetchbuf) {
191 /* always don't free.for safe alloc/free*/
192 free_pages((unsigned long)fetchbuf, get_order(FETCHBUF_SIZE));
193 fetchbuf = 0;
194 }
195 }
196
_stbuf_timer_func(unsigned long arg)197 static void _stbuf_timer_func(unsigned long arg)
198 {
199 struct stream_buf_s *p = (struct stream_buf_s *)arg;
200
201 if (stbuf_space(p) < p->wcnt) {
202 p->timer.expires = jiffies + STBUF_WAIT_INTERVAL;
203
204 add_timer(&p->timer);
205 } else
206 wake_up_interruptible(&p->wq);
207
208 }
209
stbuf_level(struct stream_buf_s * buf)210 u32 stbuf_level(struct stream_buf_s *buf)
211 {
212 if ((buf->type == BUF_TYPE_HEVC) || (buf->type == BUF_TYPE_VIDEO)) {
213 if (buf->no_parser) {
214 int level = buf->buf_wp - buf->buf_rp;
215 if (level < 0)
216 level += buf->buf_size;
217 return level;
218 } else {
219 if (READ_PARSER_REG(PARSER_ES_CONTROL) & 1) {
220 int level = READ_PARSER_REG(PARSER_VIDEO_WP) -
221 READ_PARSER_REG(PARSER_VIDEO_RP);
222 if (level < 0)
223 level += READ_PARSER_REG(PARSER_VIDEO_END_PTR) -
224 READ_PARSER_REG(PARSER_VIDEO_START_PTR) + 8;
225 return (u32)level;
226 } else
227 return (buf->type == BUF_TYPE_HEVC) ?
228 READ_VREG(HEVC_STREAM_LEVEL) :
229 _READ_ST_REG(LEVEL);
230 }
231 }
232
233 return _READ_ST_REG(LEVEL);
234 }
235
stbuf_rp(struct stream_buf_s * buf)236 u32 stbuf_rp(struct stream_buf_s *buf)
237 {
238 if ((buf->type == BUF_TYPE_HEVC) || (buf->type == BUF_TYPE_VIDEO)) {
239 if (buf->no_parser)
240 return buf->buf_rp;
241 else {
242 if (READ_PARSER_REG(PARSER_ES_CONTROL) & 1)
243 return READ_PARSER_REG(PARSER_VIDEO_RP);
244 else
245 return (buf->type == BUF_TYPE_HEVC) ?
246 READ_VREG(HEVC_STREAM_RD_PTR) :
247 _READ_ST_REG(RP);
248 }
249 }
250
251 return _READ_ST_REG(RP);
252 }
253
stbuf_space(struct stream_buf_s * buf)254 u32 stbuf_space(struct stream_buf_s *buf)
255 {
256 /* reserved space for safe write,
257 * the parser fifo size is 1024byts, so reserve it
258 */
259 int size;
260
261 size = buf->canusebuf_size - stbuf_level(buf);
262
263 if (buf->canusebuf_size >= buf->buf_size / 2) {
264 /* old reversed value,tobe full, reversed only... */
265 size = size - 6 * 1024;
266 }
267
268 if ((buf->type == BUF_TYPE_VIDEO)
269 || (has_hevc_vdec() && buf->type == BUF_TYPE_HEVC))
270 size -= READ_PARSER_REG(PARSER_VIDEO_HOLE);
271
272 return size > 0 ? size : 0;
273 }
274
stbuf_size(struct stream_buf_s * buf)275 u32 stbuf_size(struct stream_buf_s *buf)
276 {
277 return buf->buf_size;
278 }
279
stbuf_canusesize(struct stream_buf_s * buf)280 u32 stbuf_canusesize(struct stream_buf_s *buf)
281 {
282 return buf->canusebuf_size;
283 }
284
stbuf_init(struct stream_buf_s * buf,struct vdec_s * vdec)285 s32 stbuf_init(struct stream_buf_s *buf, struct vdec_s *vdec)
286 {
287 s32 r;
288 u32 dummy;
289 u32 addr32;
290
291 VDEC_PRINT_FUN_LINENO(__func__, __LINE__);
292
293 if (!buf->buf_start) {
294 r = _stbuf_alloc(buf, (vdec) ?
295 vdec->port_flag & PORT_FLAG_DRM : 0);
296 if (r < 0)
297 return r;
298 }
299 addr32 = buf->buf_start & 0xffffffff;
300 init_waitqueue_head(&buf->wq);
301
302 /*
303 * For multidec, do not touch HW stream buffers during port
304 * init and release.
305 */
306 if ((buf->type == BUF_TYPE_VIDEO) || (buf->type == BUF_TYPE_HEVC)) {
307 if (vdec) {
308 if (vdec_stream_based(vdec))
309 vdec_set_input_buffer(vdec, addr32,
310 buf->buf_size);
311 else
312 return vdec_set_input_buffer(vdec, addr32,
313 buf->buf_size);
314 }
315 }
316
317 buf->write_thread = 0;
318 if (((vdec && !vdec_single(vdec)) || (buf->is_multi_inst)) &&
319 (vdec_get_debug_flags() & 0x2) == 0)
320 return 0;
321 if (has_hevc_vdec() && buf->type == BUF_TYPE_HEVC) {
322 CLEAR_VREG_MASK(HEVC_STREAM_CONTROL, 1);
323 WRITE_VREG(HEVC_STREAM_START_ADDR, addr32);
324 WRITE_VREG(HEVC_STREAM_END_ADDR, addr32 + buf->buf_size);
325 WRITE_VREG(HEVC_STREAM_RD_PTR, addr32);
326 WRITE_VREG(HEVC_STREAM_WR_PTR, addr32);
327
328 return 0;
329 }
330
331 if (buf->type == BUF_TYPE_VIDEO) {
332 VDEC_PRINT_FUN_LINENO(__func__, __LINE__);
333
334 _WRITE_ST_REG(CONTROL, 0);
335 /* reset VLD before setting all pointers */
336 WRITE_VREG(VLD_MEM_VIFIFO_WRAP_COUNT, 0);
337 /*TODO: only > m6*/
338 #if 1/* MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
339 WRITE_VREG(DOS_SW_RESET0, (1 << 4));
340 WRITE_VREG(DOS_SW_RESET0, 0);
341 #else
342 WRITE_RESET_REG(RESET0_REGISTER, RESET_VLD);
343 #endif
344
345 dummy = READ_RESET_REG(RESET0_REGISTER);
346 WRITE_VREG(POWER_CTL_VLD, 1 << 4);
347 } else if (buf->type == BUF_TYPE_AUDIO) {
348 _WRITE_ST_REG(CONTROL, 0);
349
350 WRITE_AIU_REG(AIU_AIFIFO_GBIT, 0x80);
351 }
352
353 if (buf->type == BUF_TYPE_SUBTITLE) {
354 WRITE_PARSER_REG(PARSER_SUB_RP, addr32);
355 WRITE_PARSER_REG(PARSER_SUB_START_PTR, addr32);
356 WRITE_PARSER_REG(PARSER_SUB_END_PTR,
357 addr32 + buf->buf_size - 8);
358
359 return 0;
360 }
361
362 _WRITE_ST_REG(START_PTR, addr32);
363 _WRITE_ST_REG(CURR_PTR, addr32);
364 _WRITE_ST_REG(END_PTR, addr32 + buf->buf_size - 8);
365
366 _SET_ST_REG_MASK(CONTROL, MEM_BUFCTRL_INIT);
367 _CLR_ST_REG_MASK(CONTROL, MEM_BUFCTRL_INIT);
368
369 _WRITE_ST_REG(BUF_CTRL, MEM_BUFCTRL_MANUAL);
370 _WRITE_ST_REG(WP, addr32);
371
372 _SET_ST_REG_MASK(BUF_CTRL, MEM_BUFCTRL_INIT);
373 _CLR_ST_REG_MASK(BUF_CTRL, MEM_BUFCTRL_INIT);
374
375 _SET_ST_REG_MASK(CONTROL,
376 (0x11 << 16) | MEM_FILL_ON_LEVEL | MEM_CTRL_FILL_EN |
377 MEM_CTRL_EMPTY_EN);
378
379 if (buf->no_parser)
380 _SET_ST_REG_MASK(CONTROL, 7 << 3);
381
382 return 0;
383 }
384 EXPORT_SYMBOL(stbuf_init);
385
stbuf_vdec2_init(struct stream_buf_s * buf)386 void stbuf_vdec2_init(struct stream_buf_s *buf)
387 {
388
389 _WRITE_VDEC2_ST_REG(CONTROL, 0);
390
391 _WRITE_VDEC2_ST_REG(START_PTR, _READ_ST_REG(START_PTR));
392 _WRITE_VDEC2_ST_REG(END_PTR, _READ_ST_REG(END_PTR));
393 _WRITE_VDEC2_ST_REG(CURR_PTR, _READ_ST_REG(CURR_PTR));
394
395 _WRITE_VDEC2_ST_REG(CONTROL, MEM_FILL_ON_LEVEL | MEM_BUFCTRL_INIT);
396 _WRITE_VDEC2_ST_REG(CONTROL, MEM_FILL_ON_LEVEL);
397
398 _WRITE_VDEC2_ST_REG(BUF_CTRL, MEM_BUFCTRL_INIT);
399 _WRITE_VDEC2_ST_REG(BUF_CTRL, 0);
400
401 _WRITE_VDEC2_ST_REG(CONTROL,
402 (0x11 << 16) | MEM_FILL_ON_LEVEL | MEM_CTRL_FILL_EN
403 | MEM_CTRL_EMPTY_EN);
404 }
405
stbuf_wait_space(struct stream_buf_s * stream_buf,size_t count)406 s32 stbuf_wait_space(struct stream_buf_s *stream_buf, size_t count)
407 {
408 struct stream_buf_s *p = stream_buf;
409 long time_out = 200;
410
411 p->wcnt = count;
412
413 setup_timer(&p->timer, _stbuf_timer_func, (ulong) p);
414
415 mod_timer(&p->timer, jiffies + STBUF_WAIT_INTERVAL);
416
417 if (wait_event_interruptible_timeout
418 (p->wq, stbuf_space(p) >= count,
419 msecs_to_jiffies(time_out)) == 0) {
420 del_timer_sync(&p->timer);
421
422 return -EAGAIN;
423 }
424
425 del_timer_sync(&p->timer);
426
427 return 0;
428 }
429
stbuf_release(struct stream_buf_s * buf)430 void stbuf_release(struct stream_buf_s *buf)
431 {
432 int r;
433
434 buf->first_tstamp = INVALID_PTS;
435
436 r = stbuf_init(buf, NULL);/* reinit buffer */
437 if (r < 0)
438 pr_err("stbuf_release %d, stbuf_init failed\n", __LINE__);
439
440 if (buf->flag & BUF_FLAG_ALLOC && buf->buf_start) {
441 codec_mm_free_for_dma(MEM_NAME, buf->buf_start);
442 buf->flag &= ~BUF_FLAG_ALLOC;
443 buf->buf_start = 0;
444 buf->is_secure = false;
445 }
446 buf->flag &= ~BUF_FLAG_IN_USE;
447 }
448 EXPORT_SYMBOL(stbuf_release);
449
stbuf_sub_rp_get(void)450 u32 stbuf_sub_rp_get(void)
451 {
452 return READ_PARSER_REG(PARSER_SUB_RP);
453 }
454
stbuf_sub_rp_set(unsigned int sub_rp)455 void stbuf_sub_rp_set(unsigned int sub_rp)
456 {
457 WRITE_PARSER_REG(PARSER_SUB_RP, sub_rp);
458 return;
459 }
460
stbuf_sub_wp_get(void)461 u32 stbuf_sub_wp_get(void)
462 {
463 return READ_PARSER_REG(PARSER_SUB_WP);
464 }
465
stbuf_sub_start_get(void)466 u32 stbuf_sub_start_get(void)
467 {
468 return READ_PARSER_REG(PARSER_SUB_START_PTR);
469 }
470
parser_get_wp(struct stream_buf_s * vb)471 u32 parser_get_wp(struct stream_buf_s *vb)
472 {
473 return READ_PARSER_REG(PARSER_VIDEO_WP);
474 }
475 EXPORT_SYMBOL(parser_get_wp);
476
parser_set_wp(struct stream_buf_s * vb,u32 val)477 void parser_set_wp(struct stream_buf_s *vb, u32 val)
478 {
479 WRITE_PARSER_REG(PARSER_VIDEO_WP, val);
480 }
481 EXPORT_SYMBOL(parser_set_wp);
482
parser_get_rp(struct stream_buf_s * vb)483 u32 parser_get_rp(struct stream_buf_s *vb)
484 {
485 return READ_PARSER_REG(PARSER_VIDEO_RP);
486 }
487 EXPORT_SYMBOL(parser_get_rp);
488
parser_set_rp(struct stream_buf_s * vb,u32 val)489 void parser_set_rp(struct stream_buf_s *vb, u32 val)
490 {
491 WRITE_PARSER_REG(PARSER_VIDEO_RP, val);
492 }
493 EXPORT_SYMBOL(parser_set_rp);
494
495