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