1 /*
2 * drivers/amlogic/media/frame_provider/decoder/utils/amvdec.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/types.h>
20 #include <linux/errno.h>
21 #include <linux/platform_device.h>
22 #include <linux/sched.h>
23 #include <linux/slab.h>
24 #include <linux/dma-mapping.h>
25 #include <linux/amlogic/media/utils/vformat.h>
26 #include <linux/module.h>
27 #include <linux/delay.h>
28 #include <linux/vmalloc.h>
29 #include "vdec.h"
30
31 #ifdef CONFIG_PM
32 #include <linux/pm.h>
33 #endif
34
35 #ifdef CONFIG_WAKELOCK
36 #include <linux/wakelock.h>
37 #endif
38 #include "../../../stream_input/amports/amports_priv.h"
39
40 /* #include <mach/am_regs.h> */
41 /* #include <mach/power_gate.h> */
42 #include <linux/amlogic/media/utils/vdec_reg.h>
43 #include "amvdec.h"
44 #include <linux/amlogic/media/utils/amports_config.h>
45 #include "firmware.h"
46 #ifdef CONFIG_AMLOGIC_TEE
47 #include <linux/amlogic/tee.h>
48 #else
tee_enabled(void)49 static inline bool tee_enabled(void)
50 {
51 return false;
52 }
53
tee_protect_tvp_mem(uint32_t start,uint32_t size,uint32_t * handle)54 static inline uint32_t tee_protect_tvp_mem(uint32_t start, uint32_t size,
55 uint32_t *handle)
56 {
57 return 0xFFFFFFFF;
58 }
59
is_secload_get(void)60 static inline int is_secload_get(void)
61 {
62 return 0;
63 }
64
tee_unprotect_tvp_mem(uint32_t handle)65 static inline void tee_unprotect_tvp_mem(uint32_t handle)
66 {
67 }
68
tee_load_video_fw_swap(uint32_t index,uint32_t vdec,bool is_swap)69 static inline int tee_load_video_fw_swap(uint32_t index, uint32_t vdec, bool is_swap)
70 {
71 return -1;
72 }
73
tee_load_video_fw(uint32_t index,uint32_t vdec)74 static inline int tee_load_video_fw(uint32_t index, uint32_t vdec)
75 {
76 return -1;
77 }
78 #endif
79 #include "../../../common/chips/decoder_cpu_ver_info.h"
80
81 #define MC_SIZE (4096 * 16)
82
83 #ifdef CONFIG_WAKELOCK
84 static struct wake_lock amvdec_lock;
85 struct timer_list amvdevtimer;
86 #define WAKE_CHECK_INTERVAL (100*HZ/100)
87 #endif
88 #define AMVDEC_USE_STATIC_MEMORY
89 static void *mc_addr;
90 static dma_addr_t mc_addr_map;
91
92 #ifdef CONFIG_WAKELOCK
93 static int video_running;
94 static int video_stated_changed = 1;
95 #endif
96
amvdec_pg_enable(bool enable)97 static void amvdec_pg_enable(bool enable)
98 {
99 ulong timeout;
100
101 if (enable) {
102 AMVDEC_CLK_GATE_ON(MDEC_CLK_PIC_DC);
103 AMVDEC_CLK_GATE_ON(MDEC_CLK_DBLK);
104 AMVDEC_CLK_GATE_ON(MC_CLK);
105 AMVDEC_CLK_GATE_ON(IQIDCT_CLK);
106 /* AMVDEC_CLK_GATE_ON(VLD_CLK); */
107 AMVDEC_CLK_GATE_ON(AMRISC);
108 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */
109 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8)
110 WRITE_VREG(GCLK_EN, 0x3ff);
111 /* #endif */
112 CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 31);
113 } else {
114
115 AMVDEC_CLK_GATE_OFF(AMRISC);
116 timeout = jiffies + HZ / 100;
117
118 while (READ_VREG(MDEC_PIC_DC_STATUS) != 0) {
119 if (time_after(jiffies, timeout)) {
120 WRITE_VREG_BITS(MDEC_PIC_DC_CTRL, 1, 0, 1);
121 WRITE_VREG_BITS(MDEC_PIC_DC_CTRL, 0, 0, 1);
122 READ_VREG(MDEC_PIC_DC_STATUS);
123 READ_VREG(MDEC_PIC_DC_STATUS);
124 READ_VREG(MDEC_PIC_DC_STATUS);
125 break;
126 }
127 }
128
129 AMVDEC_CLK_GATE_OFF(MDEC_CLK_PIC_DC);
130 timeout = jiffies + HZ / 100;
131
132 while (READ_VREG(DBLK_STATUS) & 1) {
133 if (time_after(jiffies, timeout)) {
134 WRITE_VREG(DBLK_CTRL, 3);
135 WRITE_VREG(DBLK_CTRL, 0);
136 READ_VREG(DBLK_STATUS);
137 READ_VREG(DBLK_STATUS);
138 READ_VREG(DBLK_STATUS);
139 break;
140 }
141 }
142 AMVDEC_CLK_GATE_OFF(MDEC_CLK_DBLK);
143 timeout = jiffies + HZ / 100;
144
145 while (READ_VREG(MC_STATUS0) & 1) {
146 if (time_after(jiffies, timeout)) {
147 SET_VREG_MASK(MC_CTRL1, 0x9);
148 CLEAR_VREG_MASK(MC_CTRL1, 0x9);
149 READ_VREG(MC_STATUS0);
150 READ_VREG(MC_STATUS0);
151 READ_VREG(MC_STATUS0);
152 break;
153 }
154 }
155 AMVDEC_CLK_GATE_OFF(MC_CLK);
156 timeout = jiffies + HZ / 100;
157 while (READ_VREG(DCAC_DMA_CTRL) & 0x8000) {
158 if (time_after(jiffies, timeout))
159 break;
160 }
161 AMVDEC_CLK_GATE_OFF(IQIDCT_CLK);
162 /* AMVDEC_CLK_GATE_OFF(VLD_CLK); */
163 }
164 }
165
amvdec2_pg_enable(bool enable)166 static void amvdec2_pg_enable(bool enable)
167 {
168 if (has_vdec2()) {
169 ulong timeout;
170
171 if (!vdec_on(VDEC_2))
172 return;
173 if (enable) {
174 /* WRITE_VREG(VDEC2_GCLK_EN, 0x3ff); */
175 } else {
176 timeout = jiffies + HZ / 10;
177
178 while (READ_VREG(VDEC2_MDEC_PIC_DC_STATUS) != 0) {
179 if (time_after(jiffies, timeout)) {
180 WRITE_VREG_BITS(VDEC2_MDEC_PIC_DC_CTRL,
181 1, 0, 1);
182 WRITE_VREG_BITS(VDEC2_MDEC_PIC_DC_CTRL,
183 0, 0, 1);
184 READ_VREG(VDEC2_MDEC_PIC_DC_STATUS);
185 READ_VREG(VDEC2_MDEC_PIC_DC_STATUS);
186 READ_VREG(VDEC2_MDEC_PIC_DC_STATUS);
187 break;
188 }
189 }
190
191 timeout = jiffies + HZ / 10;
192
193 while (READ_VREG(VDEC2_DBLK_STATUS) & 1) {
194 if (time_after(jiffies, timeout)) {
195 WRITE_VREG(VDEC2_DBLK_CTRL, 3);
196 WRITE_VREG(VDEC2_DBLK_CTRL, 0);
197 READ_VREG(VDEC2_DBLK_STATUS);
198 READ_VREG(VDEC2_DBLK_STATUS);
199 READ_VREG(VDEC2_DBLK_STATUS);
200 break;
201 }
202 }
203
204 timeout = jiffies + HZ / 10;
205
206 while (READ_VREG(VDEC2_DCAC_DMA_CTRL) & 0x8000) {
207 if (time_after(jiffies, timeout))
208 break;
209 }
210 }
211 }
212 }
213
amhevc_pg_enable(bool enable)214 static void amhevc_pg_enable(bool enable)
215 {
216 if (has_hevc_vdec()) {
217 ulong timeout;
218
219 if (!vdec_on(VDEC_HEVC))
220 return;
221 if (enable) {
222 /* WRITE_VREG(VDEC2_GCLK_EN, 0x3ff); */
223 } else {
224 timeout = jiffies + HZ / 10;
225
226 while (READ_VREG(HEVC_MDEC_PIC_DC_STATUS) != 0) {
227 if (time_after(jiffies, timeout)) {
228 WRITE_VREG_BITS(HEVC_MDEC_PIC_DC_CTRL,
229 1, 0, 1);
230 WRITE_VREG_BITS(HEVC_MDEC_PIC_DC_CTRL,
231 0, 0, 1);
232 READ_VREG(HEVC_MDEC_PIC_DC_STATUS);
233 READ_VREG(HEVC_MDEC_PIC_DC_STATUS);
234 READ_VREG(HEVC_MDEC_PIC_DC_STATUS);
235 break;
236 }
237 }
238
239 timeout = jiffies + HZ / 10;
240
241 while (READ_VREG(HEVC_DBLK_STATUS) & 1) {
242 if (time_after(jiffies, timeout)) {
243 WRITE_VREG(HEVC_DBLK_CTRL, 3);
244 WRITE_VREG(HEVC_DBLK_CTRL, 0);
245 READ_VREG(HEVC_DBLK_STATUS);
246 READ_VREG(HEVC_DBLK_STATUS);
247 READ_VREG(HEVC_DBLK_STATUS);
248 break;
249 }
250 }
251
252 timeout = jiffies + HZ / 10;
253
254 while (READ_VREG(HEVC_DCAC_DMA_CTRL) & 0x8000) {
255 if (time_after(jiffies, timeout))
256 break;
257 }
258 }
259 }
260 }
261
262 #ifdef CONFIG_WAKELOCK
amvdec_wake_lock(void)263 int amvdec_wake_lock(void)
264 {
265 wake_lock(&amvdec_lock);
266 return 0;
267 }
268
amvdec_wake_unlock(void)269 int amvdec_wake_unlock(void)
270 {
271 wake_unlock(&amvdec_lock);
272 return 0;
273 }
274 #else
275 #define amvdec_wake_lock()
276 #define amvdec_wake_unlock()
277 #endif
278
am_vdec_loadmc_ex(struct vdec_s * vdec,const char * name,char * def,s32 (* load)(const u32 *))279 static s32 am_vdec_loadmc_ex(struct vdec_s *vdec,
280 const char *name, char *def, s32(*load)(const u32 *))
281 {
282 int err;
283
284 if (!vdec->mc_loaded) {
285 if (!def) {
286 err = get_decoder_firmware_data(vdec->format,
287 name, (u8 *)(vdec->mc),
288 (4096 * 4 * 4));
289 if (err <= 0)
290 return -1;
291 } else
292 memcpy((char *)vdec->mc, def, sizeof(vdec->mc));
293
294 vdec->mc_loaded = true;
295 }
296
297 err = (*load)(vdec->mc);
298 if (err < 0) {
299 pr_err("loading firmware %s to vdec ram failed!\n", name);
300 return err;
301 }
302
303 return err;
304 }
305
am_vdec_loadmc_buf_ex(struct vdec_s * vdec,char * buf,int size,s32 (* load)(const u32 *))306 static s32 am_vdec_loadmc_buf_ex(struct vdec_s *vdec,
307 char *buf, int size, s32(*load)(const u32 *))
308 {
309 int err;
310
311 if (!vdec->mc_loaded) {
312 memcpy((u8 *)(vdec->mc), buf, size);
313 vdec->mc_loaded = true;
314 }
315
316 err = (*load)(vdec->mc);
317 if (err < 0) {
318 pr_err("loading firmware to vdec ram failed!\n");
319 return err;
320 }
321
322 return err;
323 }
324
am_loadmc_ex(enum vformat_e type,const char * name,char * def,s32 (* load)(const u32 *))325 static s32 am_loadmc_ex(enum vformat_e type,
326 const char *name, char *def, s32(*load)(const u32 *))
327 {
328 char *mc_addr = vmalloc(4096 * 16);
329 char *pmc_addr = def;
330 int err;
331
332 if (!def && mc_addr) {
333 int loaded;
334
335 loaded = get_decoder_firmware_data(type,
336 name, mc_addr, (4096 * 16));
337 if (loaded > 0)
338 pmc_addr = mc_addr;
339 }
340 if (!pmc_addr) {
341 vfree(mc_addr);
342 return -1;
343 }
344 err = (*load)((u32 *) pmc_addr);
345 if (err < 0) {
346 pr_err("loading firmware %s to vdec ram failed!\n", name);
347 vfree(mc_addr);
348 return err;
349 }
350 vfree(mc_addr);
351
352 return err;
353 }
354
amvdec_loadmc(const u32 * p)355 static s32 amvdec_loadmc(const u32 *p)
356 {
357 ulong timeout;
358 s32 ret = 0;
359
360 #ifdef AMVDEC_USE_STATIC_MEMORY
361 if (mc_addr == NULL) {
362 #else
363 {
364 #endif
365 mc_addr = kmalloc(MC_SIZE, GFP_KERNEL);
366 }
367
368 if (!mc_addr)
369 return -ENOMEM;
370
371 memcpy(mc_addr, p, MC_SIZE);
372
373 mc_addr_map = dma_map_single(get_vdec_device(),
374 mc_addr, MC_SIZE, DMA_TO_DEVICE);
375
376 WRITE_VREG(MPSR, 0);
377 WRITE_VREG(CPSR, 0);
378
379 /* Read CBUS register for timing */
380 timeout = READ_VREG(MPSR);
381 timeout = READ_VREG(MPSR);
382
383 timeout = jiffies + HZ;
384
385 WRITE_VREG(IMEM_DMA_ADR, mc_addr_map);
386 WRITE_VREG(IMEM_DMA_COUNT, 0x1000);
387 WRITE_VREG(IMEM_DMA_CTRL, (0x8000 | (7 << 16)));
388
389 while (READ_VREG(IMEM_DMA_CTRL) & 0x8000) {
390 if (time_before(jiffies, timeout))
391 schedule();
392 else {
393 pr_err("vdec load mc error\n");
394 ret = -EBUSY;
395 break;
396 }
397 }
398
399 dma_unmap_single(get_vdec_device(),
400 mc_addr_map, MC_SIZE, DMA_TO_DEVICE);
401
402 #ifndef AMVDEC_USE_STATIC_MEMORY
403 kfree(mc_addr);
404 mc_addr = NULL;
405 #endif
406
407 return ret;
408 }
409
410 s32 optee_load_fw(enum vformat_e type, const char *fw_name)
411 {
412 s32 ret = -1;
413 unsigned int format = FIRMWARE_MAX;
414 unsigned int vdec = OPTEE_VDEC_LEGENCY;
415 char *name = __getname();
416 bool is_swap = false;
417
418 sprintf(name, "%s", fw_name ? fw_name : "null");
419
420 switch ((u32)type) {
421 case VFORMAT_VC1:
422 format = VIDEO_DEC_VC1;
423 break;
424
425 case VFORMAT_AVS:
426 if (!strcmp(name, "avs_no_cabac"))
427 format = VIDEO_DEC_AVS_NOCABAC;
428 else if (!strcmp(name, "avs_multi"))
429 format = VIDEO_DEC_AVS_MULTI;
430 else
431 format = VIDEO_DEC_AVS;
432 break;
433
434 case VFORMAT_MPEG12:
435 if (!strcmp(name, "mpeg12"))
436 format = VIDEO_DEC_MPEG12;
437 else if (!strcmp(name, "mmpeg12"))
438 format = VIDEO_DEC_MPEG12_MULTI;
439 break;
440
441 case VFORMAT_MJPEG:
442 if (!strcmp(name, "mmjpeg"))
443 format = VIDEO_DEC_MJPEG_MULTI;
444 else
445 format = VIDEO_DEC_MJPEG;
446 break;
447
448 case VFORMAT_VP9:
449 if (!strcmp(name, "vp9_mc"))
450 format = VIDEO_DEC_VP9;
451 else
452 format = VIDEO_DEC_VP9_MMU;
453 break;
454
455 case VFORMAT_AVS2:
456 format = VIDEO_DEC_AVS2_MMU;
457 vdec = OPTEE_VDEC_HEVC;
458 break;
459
460 case VFORMAT_AV1:
461 format = VIDEO_DEC_AV1_MMU;
462 vdec = OPTEE_VDEC_HEVC;
463 break;
464
465 case VFORMAT_HEVC:
466 if (!strcmp(name, "h265_mmu"))
467 format = VIDEO_DEC_HEVC_MMU;
468 else if (!strcmp(name, "hevc_mmu_swap")) {
469 format = VIDEO_DEC_HEVC_MMU_SWAP;
470 vdec = OPTEE_VDEC_HEVC;
471 is_swap = true;
472 } else
473 format = VIDEO_DEC_HEVC;
474 break;
475
476 case VFORMAT_REAL:
477 if (!strcmp(name, "vreal_mc_8"))
478 format = VIDEO_DEC_REAL_V8;
479 else if (!strcmp(name, "vreal_mc_9"))
480 format = VIDEO_DEC_REAL_V9;
481 break;
482
483 case VFORMAT_MPEG4:
484 if (!strcmp(name, "mmpeg4_mc_5"))
485 format = VIDEO_DEC_MPEG4_5_MULTI;
486 else if ((!strcmp(name, "mh263_mc")))
487 format = VIDEO_DEC_H263_MULTI;
488 else if (!strcmp(name, "vmpeg4_mc_5"))
489 format = VIDEO_DEC_MPEG4_5;
490 else if (!strcmp(name, "h263_mc"))
491 format = VIDEO_DEC_H263;
492 /*not support now*/
493 else if (!strcmp(name, "vmpeg4_mc_311"))
494 format = VIDEO_DEC_MPEG4_3;
495 else if (!strcmp(name, "vmpeg4_mc_4"))
496 format = VIDEO_DEC_MPEG4_4;
497 break;
498
499 case VFORMAT_H264_4K2K:
500 if (!strcmp(name, "single_core"))
501 format = VIDEO_DEC_H264_4k2K_SINGLE;
502 else
503 format = VIDEO_DEC_H264_4k2K;
504 break;
505
506 case VFORMAT_H264MVC:
507 format = VIDEO_DEC_H264_MVC;
508 break;
509
510 case VFORMAT_H264:
511 if (!strcmp(name, "mh264"))
512 format = VIDEO_DEC_H264_MULTI;
513 else if (!strcmp(name, "mh264_mmu")) {
514 format = VIDEO_DEC_H264_MULTI_MMU;
515 vdec = OPTEE_VDEC_HEVC;
516 } else
517 format = VIDEO_DEC_H264;
518 break;
519
520 default:
521 pr_info("Unknow vdec format!\n");
522 break;
523 }
524
525 if (format < FIRMWARE_MAX) {
526 if (is_swap)
527 ret = tee_load_video_fw_swap(format, vdec, is_swap);
528 else
529 ret = tee_load_video_fw(format, vdec);
530 }
531
532 __putname(name);
533
534 return ret;
535 }
536 EXPORT_SYMBOL(optee_load_fw);
537
538 s32 amvdec_loadmc_ex(enum vformat_e type, const char *name, char *def)
539 {
540 if (tee_enabled())
541 return optee_load_fw(type, name);
542 else
543 return am_loadmc_ex(type, name, def, &amvdec_loadmc);
544 }
545 EXPORT_SYMBOL(amvdec_loadmc_ex);
546
547 s32 amvdec_vdec_loadmc_ex(enum vformat_e type, const char *name,
548 struct vdec_s *vdec, char *def)
549 {
550 if (tee_enabled())
551 return optee_load_fw(type, name);
552 else
553 return am_vdec_loadmc_ex(vdec, name, def, &amvdec_loadmc);
554 }
555 EXPORT_SYMBOL(amvdec_vdec_loadmc_ex);
556
557 s32 amvdec_vdec_loadmc_buf_ex(enum vformat_e type, const char *name,
558 struct vdec_s *vdec, char *buf, int size)
559 {
560 if (tee_enabled())
561 return optee_load_fw(type, name);
562 else
563 return am_vdec_loadmc_buf_ex(vdec, buf, size, &amvdec_loadmc);
564 }
565 EXPORT_SYMBOL(amvdec_vdec_loadmc_buf_ex);
566
567 static s32 amvdec2_loadmc(const u32 *p)
568 {
569 if (has_vdec2()) {
570 ulong timeout;
571 s32 ret = 0;
572
573 #ifdef AMVDEC_USE_STATIC_MEMORY
574 if (mc_addr == NULL) {
575 #else
576 {
577 #endif
578 mc_addr = kmalloc(MC_SIZE, GFP_KERNEL);
579 }
580
581 if (!mc_addr)
582 return -ENOMEM;
583
584 memcpy(mc_addr, p, MC_SIZE);
585
586 mc_addr_map = dma_map_single(get_vdec_device(),
587 mc_addr, MC_SIZE, DMA_TO_DEVICE);
588
589 WRITE_VREG(VDEC2_MPSR, 0);
590 WRITE_VREG(VDEC2_CPSR, 0);
591
592 /* Read CBUS register for timing */
593 timeout = READ_VREG(VDEC2_MPSR);
594 timeout = READ_VREG(VDEC2_MPSR);
595
596 timeout = jiffies + HZ;
597
598 WRITE_VREG(VDEC2_IMEM_DMA_ADR, mc_addr_map);
599 WRITE_VREG(VDEC2_IMEM_DMA_COUNT, 0x1000);
600 WRITE_VREG(VDEC2_IMEM_DMA_CTRL, (0x8000 | (7 << 16)));
601
602 while (READ_VREG(VDEC2_IMEM_DMA_CTRL) & 0x8000) {
603 if (time_before(jiffies, timeout))
604 schedule();
605 else {
606 pr_err("vdec2 load mc error\n");
607 ret = -EBUSY;
608 break;
609 }
610 }
611
612 dma_unmap_single(get_vdec_device(),
613 mc_addr_map, MC_SIZE, DMA_TO_DEVICE);
614
615 #ifndef AMVDEC_USE_STATIC_MEMORY
616 kfree(mc_addr);
617 mc_addr = NULL;
618 #endif
619
620 return ret;
621 } else
622 return 0;
623 }
624
625 s32 amvdec2_loadmc_ex(enum vformat_e type, const char *name, char *def)
626 {
627 if (has_vdec2())
628 return am_loadmc_ex(type, name, def, &amvdec2_loadmc);
629 else
630 return 0;
631 }
632 EXPORT_SYMBOL(amvdec2_loadmc_ex);
633
634 s32 amhcodec_loadmc(const u32 *p)
635 {
636 #ifdef AMVDEC_USE_STATIC_MEMORY
637 if (mc_addr == NULL) {
638 #else
639 {
640 #endif
641 mc_addr = kmalloc(MC_SIZE, GFP_KERNEL);
642 }
643
644 if (!mc_addr)
645 return -ENOMEM;
646
647 memcpy(mc_addr, p, MC_SIZE);
648
649 mc_addr_map = dma_map_single(get_vdec_device(),
650 mc_addr, MC_SIZE, DMA_TO_DEVICE);
651
652 WRITE_VREG(HCODEC_IMEM_DMA_ADR, mc_addr_map);
653 WRITE_VREG(HCODEC_IMEM_DMA_COUNT, 0x100);
654 WRITE_VREG(HCODEC_IMEM_DMA_CTRL, (0x8000 | (7 << 16)));
655
656 while (READ_VREG(HCODEC_IMEM_DMA_CTRL) & 0x8000)
657 udelay(1000);
658
659 dma_unmap_single(get_vdec_device(),
660 mc_addr_map, MC_SIZE, DMA_TO_DEVICE);
661
662 #ifndef AMVDEC_USE_STATIC_MEMORY
663 kfree(mc_addr);
664 #endif
665
666 return 0;
667 }
668 EXPORT_SYMBOL(amhcodec_loadmc);
669
670 s32 amhcodec_loadmc_ex(enum vformat_e type, const char *name, char *def)
671 {
672 return am_loadmc_ex(type, name, def, &amhcodec_loadmc);
673 }
674 EXPORT_SYMBOL(amhcodec_loadmc_ex);
675
676 static s32 amhevc_loadmc(const u32 *p)
677 {
678 ulong timeout;
679 s32 ret = 0;
680
681 if (has_hevc_vdec()) {
682 #ifdef AMVDEC_USE_STATIC_MEMORY
683 if (mc_addr == NULL) {
684 #else
685 {
686 #endif
687 mc_addr = kmalloc(MC_SIZE, GFP_KERNEL);
688 }
689
690 if (!mc_addr)
691 return -ENOMEM;
692
693 memcpy(mc_addr, p, MC_SIZE);
694
695 mc_addr_map =
696 dma_map_single(get_vdec_device(),
697 mc_addr, MC_SIZE, DMA_TO_DEVICE);
698
699 WRITE_VREG(HEVC_MPSR, 0);
700 WRITE_VREG(HEVC_CPSR, 0);
701
702 /* Read CBUS register for timing */
703 timeout = READ_VREG(HEVC_MPSR);
704 timeout = READ_VREG(HEVC_MPSR);
705
706 timeout = jiffies + HZ;
707
708 WRITE_VREG(HEVC_IMEM_DMA_ADR, mc_addr_map);
709 WRITE_VREG(HEVC_IMEM_DMA_COUNT, 0x1000);
710 WRITE_VREG(HEVC_IMEM_DMA_CTRL, (0x8000 | (7 << 16)));
711
712 while (READ_VREG(HEVC_IMEM_DMA_CTRL) & 0x8000) {
713 if (time_before(jiffies, timeout))
714 schedule();
715 else {
716 pr_err("vdec2 load mc error\n");
717 ret = -EBUSY;
718 break;
719 }
720 }
721
722 dma_unmap_single(get_vdec_device(),
723 mc_addr_map, MC_SIZE, DMA_TO_DEVICE);
724
725 #ifndef AMVDEC_USE_STATIC_MEMORY
726 kfree(mc_addr);
727 mc_addr = NULL;
728 #endif
729 }
730
731 return ret;
732 }
733
734 s32 amhevc_loadmc_ex(enum vformat_e type, const char *name, char *def)
735 {
736 if (has_hevc_vdec())
737 if (tee_enabled())
738 return optee_load_fw(type, name);
739 else
740 return am_loadmc_ex(type, name, def, &amhevc_loadmc);
741 else
742 return -1;
743 }
744 EXPORT_SYMBOL(amhevc_loadmc_ex);
745
746 s32 amhevc_vdec_loadmc_ex(enum vformat_e type, struct vdec_s *vdec,
747 const char *name, char *def)
748 {
749 if (has_hevc_vdec())
750 if (tee_enabled())
751 return optee_load_fw(type, name);
752 else
753 return am_vdec_loadmc_ex(vdec, name, def, &amhevc_loadmc);
754 else
755 return -1;
756 }
757 EXPORT_SYMBOL(amhevc_vdec_loadmc_ex);
758
759 void amvdec_start(void)
760 {
761 #ifdef CONFIG_WAKELOCK
762 amvdec_wake_lock();
763 #endif
764
765 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
766 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
767 READ_VREG(DOS_SW_RESET0);
768 READ_VREG(DOS_SW_RESET0);
769 READ_VREG(DOS_SW_RESET0);
770
771 WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11));
772 WRITE_VREG(DOS_SW_RESET0, 0);
773
774 READ_VREG(DOS_SW_RESET0);
775 READ_VREG(DOS_SW_RESET0);
776 READ_VREG(DOS_SW_RESET0);
777 } else {
778 /* #else */
779 /* additional cbus dummy register reading for timing control */
780 READ_RESET_REG(RESET0_REGISTER);
781 READ_RESET_REG(RESET0_REGISTER);
782 READ_RESET_REG(RESET0_REGISTER);
783 READ_RESET_REG(RESET0_REGISTER);
784
785 WRITE_RESET_REG(RESET0_REGISTER, RESET_VCPU | RESET_CCPU);
786
787 READ_RESET_REG(RESET0_REGISTER);
788 READ_RESET_REG(RESET0_REGISTER);
789 READ_RESET_REG(RESET0_REGISTER);
790 }
791 /* #endif */
792
793 WRITE_VREG(MPSR, 0x0001);
794 }
795 EXPORT_SYMBOL(amvdec_start);
796
797 void amvdec2_start(void)
798 {
799 if (has_vdec2()) {
800 #ifdef CONFIG_WAKELOCK
801 amvdec_wake_lock();
802 #endif
803
804 READ_VREG(DOS_SW_RESET2);
805 READ_VREG(DOS_SW_RESET2);
806 READ_VREG(DOS_SW_RESET2);
807
808 WRITE_VREG(DOS_SW_RESET2, (1 << 12) | (1 << 11));
809 WRITE_VREG(DOS_SW_RESET2, 0);
810
811 READ_VREG(DOS_SW_RESET2);
812 READ_VREG(DOS_SW_RESET2);
813 READ_VREG(DOS_SW_RESET2);
814
815 WRITE_VREG(VDEC2_MPSR, 0x0001);
816 }
817 }
818 EXPORT_SYMBOL(amvdec2_start);
819
820 void amhcodec_start(void)
821 {
822 WRITE_VREG(HCODEC_MPSR, 0x0001);
823 }
824 EXPORT_SYMBOL(amhcodec_start);
825
826 void amhevc_start(void)
827 {
828
829 if (has_hevc_vdec()) {
830 #ifdef CONFIG_WAKELOCK
831 amvdec_wake_lock();
832 #endif
833
834 READ_VREG(DOS_SW_RESET3);
835 READ_VREG(DOS_SW_RESET3);
836 READ_VREG(DOS_SW_RESET3);
837
838 WRITE_VREG(DOS_SW_RESET3, (1 << 12) | (1 << 11));
839 WRITE_VREG(DOS_SW_RESET3, 0);
840
841 READ_VREG(DOS_SW_RESET3);
842 READ_VREG(DOS_SW_RESET3);
843 READ_VREG(DOS_SW_RESET3);
844
845 WRITE_VREG(HEVC_MPSR, 0x0001);
846 }
847 }
848 EXPORT_SYMBOL(amhevc_start);
849
850 void amvdec_stop(void)
851 {
852 ulong timeout = jiffies + HZ/10;
853
854 WRITE_VREG(MPSR, 0);
855 WRITE_VREG(CPSR, 0);
856
857 while (READ_VREG(IMEM_DMA_CTRL) & 0x8000) {
858 if (time_after(jiffies, timeout))
859 break;
860 }
861
862 timeout = jiffies + HZ/10;
863 while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) {
864 if (time_after(jiffies, timeout))
865 break;
866 }
867
868 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
869 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
870 READ_VREG(DOS_SW_RESET0);
871 READ_VREG(DOS_SW_RESET0);
872 READ_VREG(DOS_SW_RESET0);
873
874 WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11));
875 WRITE_VREG(DOS_SW_RESET0, 0);
876
877 READ_VREG(DOS_SW_RESET0);
878 READ_VREG(DOS_SW_RESET0);
879 READ_VREG(DOS_SW_RESET0);
880 } else {
881 /* #else */
882 WRITE_RESET_REG(RESET0_REGISTER, RESET_VCPU | RESET_CCPU);
883
884 /* additional cbus dummy register reading for timing control */
885 READ_RESET_REG(RESET0_REGISTER);
886 READ_RESET_REG(RESET0_REGISTER);
887 READ_RESET_REG(RESET0_REGISTER);
888 READ_RESET_REG(RESET0_REGISTER);
889 }
890 /* #endif */
891
892 #ifdef CONFIG_WAKELOCK
893 amvdec_wake_unlock();
894 #endif
895 }
896 EXPORT_SYMBOL(amvdec_stop);
897
898 void amvdec2_stop(void)
899 {
900 if (has_vdec2()) {
901 ulong timeout = jiffies + HZ/10;
902
903 WRITE_VREG(VDEC2_MPSR, 0);
904 WRITE_VREG(VDEC2_CPSR, 0);
905
906 while (READ_VREG(VDEC2_IMEM_DMA_CTRL) & 0x8000) {
907 if (time_after(jiffies, timeout))
908 break;
909 }
910
911 READ_VREG(DOS_SW_RESET2);
912 READ_VREG(DOS_SW_RESET2);
913 READ_VREG(DOS_SW_RESET2);
914
915 #ifdef CONFIG_WAKELOCK
916 amvdec_wake_unlock();
917 #endif
918 }
919 }
920 EXPORT_SYMBOL(amvdec2_stop);
921
922 void amhcodec_stop(void)
923 {
924 WRITE_VREG(HCODEC_MPSR, 0);
925 }
926 EXPORT_SYMBOL(amhcodec_stop);
927
928 void amhevc_stop(void)
929 {
930 if (has_hevc_vdec()) {
931 ulong timeout = jiffies + HZ/10;
932
933 WRITE_VREG(HEVC_MPSR, 0);
934 WRITE_VREG(HEVC_CPSR, 0);
935
936 while (READ_VREG(HEVC_IMEM_DMA_CTRL) & 0x8000) {
937 if (time_after(jiffies, timeout))
938 break;
939 }
940
941 timeout = jiffies + HZ/10;
942 while (READ_VREG(HEVC_LMEM_DMA_CTRL) & 0x8000) {
943 if (time_after(jiffies, timeout))
944 break;
945 }
946
947 READ_VREG(DOS_SW_RESET3);
948 READ_VREG(DOS_SW_RESET3);
949 READ_VREG(DOS_SW_RESET3);
950
951 #ifdef CONFIG_WAKELOCK
952 amvdec_wake_unlock();
953 #endif
954 }
955 }
956 EXPORT_SYMBOL(amhevc_stop);
957
958 void amvdec_enable(void)
959 {
960 amvdec_pg_enable(true);
961 }
962 EXPORT_SYMBOL(amvdec_enable);
963
964 void amvdec_disable(void)
965 {
966 amvdec_pg_enable(false);
967 }
968 EXPORT_SYMBOL(amvdec_disable);
969
970 void amvdec2_enable(void)
971 {
972 if (has_vdec2())
973 amvdec2_pg_enable(true);
974 }
975 EXPORT_SYMBOL(amvdec2_enable);
976
977 void amvdec2_disable(void)
978 {
979 if (has_vdec2())
980 amvdec2_pg_enable(false);
981 }
982 EXPORT_SYMBOL(amvdec2_disable);
983
984 void amhevc_enable(void)
985 {
986 if (has_hevc_vdec())
987 amhevc_pg_enable(true);
988 }
989 EXPORT_SYMBOL(amhevc_enable);
990
991 void amhevc_disable(void)
992 {
993 if (has_hevc_vdec())
994 amhevc_pg_enable(false);
995 }
996 EXPORT_SYMBOL(amhevc_disable);
997
998 #ifdef CONFIG_PM
999 int amvdec_suspend(struct platform_device *dev, pm_message_t event)
1000 {
1001 amvdec_pg_enable(false);
1002
1003 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */
1004 if (has_vdec2())
1005 amvdec2_pg_enable(false);
1006 /* #endif */
1007
1008 if (has_hevc_vdec())
1009 amhevc_pg_enable(false);
1010 /*vdec_set_suspend_clk(1, 0);*//*DEBUG_TMP*/
1011 return 0;
1012 }
1013 EXPORT_SYMBOL(amvdec_suspend);
1014
1015 int amvdec_resume(struct platform_device *dev)
1016 {
1017 amvdec_pg_enable(true);
1018
1019 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */
1020 if (has_vdec2())
1021 amvdec2_pg_enable(true);
1022 /* #endif */
1023
1024 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
1025 if (has_hevc_vdec())
1026 amhevc_pg_enable(true);
1027 /* #endif */
1028 /*vdec_set_suspend_clk(0, 0);*//*DEBUG_TMP*/
1029 return 0;
1030 }
1031 EXPORT_SYMBOL(amvdec_resume);
1032
1033 int amhevc_suspend(struct platform_device *dev, pm_message_t event)
1034 {
1035 if (has_hevc_vdec()) {
1036 amhevc_pg_enable(false);
1037 /*vdec_set_suspend_clk(1, 1);*//*DEBUG_TMP*/
1038 }
1039 return 0;
1040 }
1041 EXPORT_SYMBOL(amhevc_suspend);
1042
1043 int amhevc_resume(struct platform_device *dev)
1044 {
1045 if (has_hevc_vdec()) {
1046 amhevc_pg_enable(true);
1047 /*vdec_set_suspend_clk(0, 1);*//*DEBUG_TMP*/
1048 }
1049 return 0;
1050 }
1051 EXPORT_SYMBOL(amhevc_resume);
1052
1053
1054 #endif
1055
1056 #ifdef CONFIG_WAKELOCK
1057
1058 static int vdec_is_paused(void)
1059 {
1060 static unsigned long old_wp = -1, old_rp = -1, old_level = -1;
1061 unsigned long wp, rp, level;
1062 static int paused_time;
1063
1064 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
1065 if (has_hevc_vdec()) {
1066 if ((vdec_on(VDEC_HEVC))
1067 && (READ_VREG(HEVC_STREAM_CONTROL) & 1)) {
1068 wp = READ_VREG(HEVC_STREAM_WR_PTR);
1069 rp = READ_VREG(HEVC_STREAM_RD_PTR);
1070 level = READ_VREG(HEVC_STREAM_LEVEL);
1071 } else {
1072 wp = READ_VREG(VLD_MEM_VIFIFO_WP);
1073 rp = READ_VREG(VLD_MEM_VIFIFO_RP);
1074 level = READ_VREG(VLD_MEM_VIFIFO_LEVEL);
1075 }
1076 } else
1077 /* #endif */
1078 {
1079 wp = READ_VREG(VLD_MEM_VIFIFO_WP);
1080 rp = READ_VREG(VLD_MEM_VIFIFO_RP);
1081 level = READ_VREG(VLD_MEM_VIFIFO_LEVEL);
1082 }
1083 /*have data,but output buffer is full */
1084 if ((rp == old_rp && level > 1024) ||
1085 (rp == old_rp && wp == old_wp && level == old_level)) {
1086 /*no write && not read */
1087 paused_time++;
1088 } else {
1089 paused_time = 0;
1090 }
1091 old_wp = wp; old_rp = rp; old_level = level;
1092 if (paused_time > 10)
1093 return 1;
1094 return 0;
1095 }
1096
1097 int amvdev_pause(void)
1098 {
1099 video_running = 0;
1100 video_stated_changed = 1;
1101 return 0;
1102 }
1103 EXPORT_SYMBOL(amvdev_pause);
1104
1105 int amvdev_resume(void)
1106 {
1107 video_running = 1;
1108 video_stated_changed = 1;
1109 return 0;
1110 }
1111 EXPORT_SYMBOL(amvdev_resume);
1112
1113 static void vdec_paused_check_timer(unsigned long arg)
1114 {
1115 if (video_stated_changed) {
1116 if (!video_running) {
1117 if (vdec_is_paused()) {
1118 pr_info("vdec paused and release wakelock now\n");
1119 amvdec_wake_unlock();
1120 video_stated_changed = 0;
1121 }
1122 } else {
1123 amvdec_wake_lock();
1124 video_stated_changed = 0;
1125 }
1126 }
1127 mod_timer(&amvdevtimer, jiffies + WAKE_CHECK_INTERVAL);
1128 }
1129 #else
1130 int amvdev_pause(void)
1131 {
1132 return 0;
1133 }
1134
1135 int amvdev_resume(void)
1136 {
1137 return 0;
1138 }
1139 #endif
1140
1141 int amvdec_init(void)
1142 {
1143 #ifdef CONFIG_WAKELOCK
1144 /*
1145 *wake_lock_init(&amvdec_lock, WAKE_LOCK_IDLE, "amvdec_lock");
1146 *tmp mark for compile, no "WAKE_LOCK_IDLE" definition in kernel 3.8
1147 */
1148 wake_lock_init(&amvdec_lock, /*WAKE_LOCK_IDLE */ WAKE_LOCK_SUSPEND,
1149 "amvdec_lock");
1150
1151 init_timer(&amvdevtimer);
1152
1153 amvdevtimer.data = (ulong) &amvdevtimer;
1154 amvdevtimer.function = vdec_paused_check_timer;
1155 #endif
1156 return 0;
1157 }
1158 EXPORT_SYMBOL(amvdec_init);
1159
1160 void amvdec_exit(void)
1161 {
1162 #ifdef CONFIG_WAKELOCK
1163 del_timer_sync(&amvdevtimer);
1164 #endif
1165 }
1166 EXPORT_SYMBOL(amvdec_exit);
1167
1168 #if 0
1169 int __init amvdec_init(void)
1170 {
1171 #ifdef CONFIG_WAKELOCK
1172 /*
1173 *wake_lock_init(&amvdec_lock, WAKE_LOCK_IDLE, "amvdec_lock");
1174 *tmp mark for compile, no "WAKE_LOCK_IDLE" definition in kernel 3.8
1175 */
1176 wake_lock_init(&amvdec_lock, /*WAKE_LOCK_IDLE */ WAKE_LOCK_SUSPEND,
1177 "amvdec_lock");
1178
1179 init_timer(&amvdevtimer);
1180
1181 amvdevtimer.data = (ulong) &amvdevtimer;
1182 amvdevtimer.function = vdec_paused_check_timer;
1183 #endif
1184 return 0;
1185 }
1186
1187 static void __exit amvdec_exit(void)
1188 {
1189 #ifdef CONFIG_WAKELOCK
1190 del_timer_sync(&amvdevtimer);
1191 #endif
1192 }
1193
1194 module_init(amvdec_init);
1195 module_exit(amvdec_exit);
1196 #endif
1197
1198 MODULE_DESCRIPTION("Amlogic Video Decoder Utility Driver");
1199 MODULE_LICENSE("GPL");
1200 MODULE_AUTHOR("Tim Yao <timyao@amlogic.com>");
1201