summaryrefslogtreecommitdiff
path: root/drivers/frame_provider/decoder/utils/amvdec.c (plain)
blob: c37b473bc5479565042f64e2fc1f75f163de6889
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_AV1:
429 format = VIDEO_DEC_AV1_MMU;
430 vdec = OPTEE_VDEC_HEVC;
431 break;
432
433 case VFORMAT_HEVC:
434 if (!strcmp(name, "h265_mmu"))
435 format = VIDEO_DEC_HEVC_MMU;
436 else if (!strcmp(name, "hevc_mmu_swap")) {
437 format = VIDEO_DEC_HEVC_MMU_SWAP;
438 vdec = OPTEE_VDEC_HEVC;
439 is_swap = true;
440 } else
441 format = VIDEO_DEC_HEVC;
442 break;
443
444 case VFORMAT_REAL:
445 if (!strcmp(name, "vreal_mc_8"))
446 format = VIDEO_DEC_REAL_V8;
447 else if (!strcmp(name, "vreal_mc_9"))
448 format = VIDEO_DEC_REAL_V9;
449 break;
450
451 case VFORMAT_MPEG4:
452 if (!strcmp(name, "mmpeg4_mc_5"))
453 format = VIDEO_DEC_MPEG4_5_MULTI;
454 else if ((!strcmp(name, "mh263_mc")))
455 format = VIDEO_DEC_H263_MULTI;
456 else if (!strcmp(name, "vmpeg4_mc_5"))
457 format = VIDEO_DEC_MPEG4_5;
458 else if (!strcmp(name, "h263_mc"))
459 format = VIDEO_DEC_H263;
460 /*not support now*/
461 else if (!strcmp(name, "vmpeg4_mc_311"))
462 format = VIDEO_DEC_MPEG4_3;
463 else if (!strcmp(name, "vmpeg4_mc_4"))
464 format = VIDEO_DEC_MPEG4_4;
465 break;
466
467 case VFORMAT_H264_4K2K:
468 if (!strcmp(name, "single_core"))
469 format = VIDEO_DEC_H264_4k2K_SINGLE;
470 else
471 format = VIDEO_DEC_H264_4k2K;
472 break;
473
474 case VFORMAT_H264MVC:
475 format = VIDEO_DEC_H264_MVC;
476 break;
477
478 case VFORMAT_H264:
479 if (!strcmp(name, "mh264"))
480 format = VIDEO_DEC_H264_MULTI;
481 else if (!strcmp(name, "mh264_mmu")) {
482 format = VIDEO_DEC_H264_MULTI_MMU;
483 vdec = OPTEE_VDEC_HEVC;
484 } else
485 format = VIDEO_DEC_H264;
486 break;
487
488 default:
489 pr_info("Unknow vdec format!\n");
490 break;
491 }
492
493 if (format < FIRMWARE_MAX) {
494 if (is_swap)
495 ret = tee_load_video_fw_swap(format, vdec, is_swap);
496 else
497 ret = tee_load_video_fw(format, vdec);
498 }
499
500 __putname(name);
501
502 return ret;
503}
504EXPORT_SYMBOL(optee_load_fw);
505
506s32 amvdec_loadmc_ex(enum vformat_e type, const char *name, char *def)
507{
508 if (tee_enabled())
509 return optee_load_fw(type, name);
510 else
511 return am_loadmc_ex(type, name, def, &amvdec_loadmc);
512}
513EXPORT_SYMBOL(amvdec_loadmc_ex);
514
515s32 amvdec_vdec_loadmc_ex(enum vformat_e type, const char *name,
516 struct vdec_s *vdec, char *def)
517{
518 if (tee_enabled())
519 return optee_load_fw(type, name);
520 else
521 return am_vdec_loadmc_ex(vdec, name, def, &amvdec_loadmc);
522}
523EXPORT_SYMBOL(amvdec_vdec_loadmc_ex);
524
525s32 amvdec_vdec_loadmc_buf_ex(enum vformat_e type, const char *name,
526 struct vdec_s *vdec, char *buf, int size)
527{
528 if (tee_enabled())
529 return optee_load_fw(type, name);
530 else
531 return am_vdec_loadmc_buf_ex(vdec, buf, size, &amvdec_loadmc);
532}
533EXPORT_SYMBOL(amvdec_vdec_loadmc_buf_ex);
534
535static s32 amvdec2_loadmc(const u32 *p)
536{
537 if (has_vdec2()) {
538 ulong timeout;
539 s32 ret = 0;
540
541#ifdef AMVDEC_USE_STATIC_MEMORY
542 if (mc_addr == NULL) {
543#else
544 {
545#endif
546 mc_addr = kmalloc(MC_SIZE, GFP_KERNEL);
547 }
548
549 if (!mc_addr)
550 return -ENOMEM;
551
552 memcpy(mc_addr, p, MC_SIZE);
553
554 mc_addr_map = dma_map_single(get_vdec_device(),
555 mc_addr, MC_SIZE, DMA_TO_DEVICE);
556
557 WRITE_VREG(VDEC2_MPSR, 0);
558 WRITE_VREG(VDEC2_CPSR, 0);
559
560 /* Read CBUS register for timing */
561 timeout = READ_VREG(VDEC2_MPSR);
562 timeout = READ_VREG(VDEC2_MPSR);
563
564 timeout = jiffies + HZ;
565
566 WRITE_VREG(VDEC2_IMEM_DMA_ADR, mc_addr_map);
567 WRITE_VREG(VDEC2_IMEM_DMA_COUNT, 0x1000);
568 WRITE_VREG(VDEC2_IMEM_DMA_CTRL, (0x8000 | (7 << 16)));
569
570 while (READ_VREG(VDEC2_IMEM_DMA_CTRL) & 0x8000) {
571 if (time_before(jiffies, timeout))
572 schedule();
573 else {
574 pr_err("vdec2 load mc error\n");
575 ret = -EBUSY;
576 break;
577 }
578 }
579
580 dma_unmap_single(get_vdec_device(),
581 mc_addr_map, MC_SIZE, DMA_TO_DEVICE);
582
583#ifndef AMVDEC_USE_STATIC_MEMORY
584 kfree(mc_addr);
585 mc_addr = NULL;
586#endif
587
588 return ret;
589 } else
590 return 0;
591}
592
593s32 amvdec2_loadmc_ex(enum vformat_e type, const char *name, char *def)
594{
595 if (has_vdec2())
596 return am_loadmc_ex(type, name, def, &amvdec2_loadmc);
597 else
598 return 0;
599}
600EXPORT_SYMBOL(amvdec2_loadmc_ex);
601
602s32 amhcodec_loadmc(const u32 *p)
603{
604#ifdef AMVDEC_USE_STATIC_MEMORY
605 if (mc_addr == NULL) {
606#else
607 {
608#endif
609 mc_addr = kmalloc(MC_SIZE, GFP_KERNEL);
610 }
611
612 if (!mc_addr)
613 return -ENOMEM;
614
615 memcpy(mc_addr, p, MC_SIZE);
616
617 mc_addr_map = dma_map_single(get_vdec_device(),
618 mc_addr, MC_SIZE, DMA_TO_DEVICE);
619
620 WRITE_VREG(HCODEC_IMEM_DMA_ADR, mc_addr_map);
621 WRITE_VREG(HCODEC_IMEM_DMA_COUNT, 0x100);
622 WRITE_VREG(HCODEC_IMEM_DMA_CTRL, (0x8000 | (7 << 16)));
623
624 while (READ_VREG(HCODEC_IMEM_DMA_CTRL) & 0x8000)
625 udelay(1000);
626
627 dma_unmap_single(get_vdec_device(),
628 mc_addr_map, MC_SIZE, DMA_TO_DEVICE);
629
630#ifndef AMVDEC_USE_STATIC_MEMORY
631 kfree(mc_addr);
632#endif
633
634 return 0;
635}
636EXPORT_SYMBOL(amhcodec_loadmc);
637
638s32 amhcodec_loadmc_ex(enum vformat_e type, const char *name, char *def)
639{
640 return am_loadmc_ex(type, name, def, &amhcodec_loadmc);
641}
642EXPORT_SYMBOL(amhcodec_loadmc_ex);
643
644static s32 amhevc_loadmc(const u32 *p)
645{
646 ulong timeout;
647 s32 ret = 0;
648
649 if (has_hevc_vdec()) {
650#ifdef AMVDEC_USE_STATIC_MEMORY
651 if (mc_addr == NULL) {
652#else
653 {
654#endif
655 mc_addr = kmalloc(MC_SIZE, GFP_KERNEL);
656 }
657
658 if (!mc_addr)
659 return -ENOMEM;
660
661 memcpy(mc_addr, p, MC_SIZE);
662
663 mc_addr_map =
664 dma_map_single(get_vdec_device(),
665 mc_addr, MC_SIZE, DMA_TO_DEVICE);
666
667 WRITE_VREG(HEVC_MPSR, 0);
668 WRITE_VREG(HEVC_CPSR, 0);
669
670 /* Read CBUS register for timing */
671 timeout = READ_VREG(HEVC_MPSR);
672 timeout = READ_VREG(HEVC_MPSR);
673
674 timeout = jiffies + HZ;
675
676 WRITE_VREG(HEVC_IMEM_DMA_ADR, mc_addr_map);
677 WRITE_VREG(HEVC_IMEM_DMA_COUNT, 0x1000);
678 WRITE_VREG(HEVC_IMEM_DMA_CTRL, (0x8000 | (7 << 16)));
679
680 while (READ_VREG(HEVC_IMEM_DMA_CTRL) & 0x8000) {
681 if (time_before(jiffies, timeout))
682 schedule();
683 else {
684 pr_err("vdec2 load mc error\n");
685 ret = -EBUSY;
686 break;
687 }
688 }
689
690 dma_unmap_single(get_vdec_device(),
691 mc_addr_map, MC_SIZE, DMA_TO_DEVICE);
692
693#ifndef AMVDEC_USE_STATIC_MEMORY
694 kfree(mc_addr);
695 mc_addr = NULL;
696#endif
697 }
698
699 return ret;
700}
701
702s32 amhevc_loadmc_ex(enum vformat_e type, const char *name, char *def)
703{
704 if (has_hevc_vdec())
705 if (tee_enabled())
706 return optee_load_fw(type, name);
707 else
708 return am_loadmc_ex(type, name, def, &amhevc_loadmc);
709 else
710 return -1;
711}
712EXPORT_SYMBOL(amhevc_loadmc_ex);
713
714s32 amhevc_vdec_loadmc_ex(enum vformat_e type, struct vdec_s *vdec,
715 const char *name, char *def)
716{
717 if (has_hevc_vdec())
718 if (tee_enabled())
719 return optee_load_fw(type, name);
720 else
721 return am_vdec_loadmc_ex(vdec, name, def, &amhevc_loadmc);
722 else
723 return -1;
724}
725EXPORT_SYMBOL(amhevc_vdec_loadmc_ex);
726
727void amvdec_start(void)
728{
729#ifdef CONFIG_WAKELOCK
730 amvdec_wake_lock();
731#endif
732
733 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
734 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
735 READ_VREG(DOS_SW_RESET0);
736 READ_VREG(DOS_SW_RESET0);
737 READ_VREG(DOS_SW_RESET0);
738
739 WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11));
740 WRITE_VREG(DOS_SW_RESET0, 0);
741
742 READ_VREG(DOS_SW_RESET0);
743 READ_VREG(DOS_SW_RESET0);
744 READ_VREG(DOS_SW_RESET0);
745 } else {
746 /* #else */
747 /* additional cbus dummy register reading for timing control */
748 READ_RESET_REG(RESET0_REGISTER);
749 READ_RESET_REG(RESET0_REGISTER);
750 READ_RESET_REG(RESET0_REGISTER);
751 READ_RESET_REG(RESET0_REGISTER);
752
753 WRITE_RESET_REG(RESET0_REGISTER, RESET_VCPU | RESET_CCPU);
754
755 READ_RESET_REG(RESET0_REGISTER);
756 READ_RESET_REG(RESET0_REGISTER);
757 READ_RESET_REG(RESET0_REGISTER);
758 }
759 /* #endif */
760
761 WRITE_VREG(MPSR, 0x0001);
762}
763EXPORT_SYMBOL(amvdec_start);
764
765void amvdec2_start(void)
766{
767 if (has_vdec2()) {
768#ifdef CONFIG_WAKELOCK
769 amvdec_wake_lock();
770#endif
771
772 READ_VREG(DOS_SW_RESET2);
773 READ_VREG(DOS_SW_RESET2);
774 READ_VREG(DOS_SW_RESET2);
775
776 WRITE_VREG(DOS_SW_RESET2, (1 << 12) | (1 << 11));
777 WRITE_VREG(DOS_SW_RESET2, 0);
778
779 READ_VREG(DOS_SW_RESET2);
780 READ_VREG(DOS_SW_RESET2);
781 READ_VREG(DOS_SW_RESET2);
782
783 WRITE_VREG(VDEC2_MPSR, 0x0001);
784 }
785}
786EXPORT_SYMBOL(amvdec2_start);
787
788void amhcodec_start(void)
789{
790 WRITE_VREG(HCODEC_MPSR, 0x0001);
791}
792EXPORT_SYMBOL(amhcodec_start);
793
794void amhevc_start(void)
795{
796
797 if (has_hevc_vdec()) {
798#ifdef CONFIG_WAKELOCK
799 amvdec_wake_lock();
800#endif
801
802 READ_VREG(DOS_SW_RESET3);
803 READ_VREG(DOS_SW_RESET3);
804 READ_VREG(DOS_SW_RESET3);
805
806 WRITE_VREG(DOS_SW_RESET3, (1 << 12) | (1 << 11));
807 WRITE_VREG(DOS_SW_RESET3, 0);
808
809 READ_VREG(DOS_SW_RESET3);
810 READ_VREG(DOS_SW_RESET3);
811 READ_VREG(DOS_SW_RESET3);
812
813 WRITE_VREG(HEVC_MPSR, 0x0001);
814 }
815}
816EXPORT_SYMBOL(amhevc_start);
817
818void amvdec_stop(void)
819{
820 ulong timeout = jiffies + HZ/10;
821
822 WRITE_VREG(MPSR, 0);
823 WRITE_VREG(CPSR, 0);
824
825 while (READ_VREG(IMEM_DMA_CTRL) & 0x8000) {
826 if (time_after(jiffies, timeout))
827 break;
828 }
829
830 timeout = jiffies + HZ/10;
831 while (READ_VREG(LMEM_DMA_CTRL) & 0x8000) {
832 if (time_after(jiffies, timeout))
833 break;
834 }
835
836 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
837 if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M6) {
838 READ_VREG(DOS_SW_RESET0);
839 READ_VREG(DOS_SW_RESET0);
840 READ_VREG(DOS_SW_RESET0);
841
842 WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11));
843 WRITE_VREG(DOS_SW_RESET0, 0);
844
845 READ_VREG(DOS_SW_RESET0);
846 READ_VREG(DOS_SW_RESET0);
847 READ_VREG(DOS_SW_RESET0);
848 } else {
849 /* #else */
850 WRITE_RESET_REG(RESET0_REGISTER, RESET_VCPU | RESET_CCPU);
851
852 /* additional cbus dummy register reading for timing control */
853 READ_RESET_REG(RESET0_REGISTER);
854 READ_RESET_REG(RESET0_REGISTER);
855 READ_RESET_REG(RESET0_REGISTER);
856 READ_RESET_REG(RESET0_REGISTER);
857 }
858 /* #endif */
859
860#ifdef CONFIG_WAKELOCK
861 amvdec_wake_unlock();
862#endif
863}
864EXPORT_SYMBOL(amvdec_stop);
865
866void amvdec2_stop(void)
867{
868 if (has_vdec2()) {
869 ulong timeout = jiffies + HZ/10;
870
871 WRITE_VREG(VDEC2_MPSR, 0);
872 WRITE_VREG(VDEC2_CPSR, 0);
873
874 while (READ_VREG(VDEC2_IMEM_DMA_CTRL) & 0x8000) {
875 if (time_after(jiffies, timeout))
876 break;
877 }
878
879 READ_VREG(DOS_SW_RESET2);
880 READ_VREG(DOS_SW_RESET2);
881 READ_VREG(DOS_SW_RESET2);
882
883#ifdef CONFIG_WAKELOCK
884 amvdec_wake_unlock();
885#endif
886 }
887}
888EXPORT_SYMBOL(amvdec2_stop);
889
890void amhcodec_stop(void)
891{
892 WRITE_VREG(HCODEC_MPSR, 0);
893}
894EXPORT_SYMBOL(amhcodec_stop);
895
896void amhevc_stop(void)
897{
898 if (has_hevc_vdec()) {
899 ulong timeout = jiffies + HZ/10;
900
901 WRITE_VREG(HEVC_MPSR, 0);
902 WRITE_VREG(HEVC_CPSR, 0);
903
904 while (READ_VREG(HEVC_IMEM_DMA_CTRL) & 0x8000) {
905 if (time_after(jiffies, timeout))
906 break;
907 }
908
909 timeout = jiffies + HZ/10;
910 while (READ_VREG(HEVC_LMEM_DMA_CTRL) & 0x8000) {
911 if (time_after(jiffies, timeout))
912 break;
913 }
914
915 READ_VREG(DOS_SW_RESET3);
916 READ_VREG(DOS_SW_RESET3);
917 READ_VREG(DOS_SW_RESET3);
918
919#ifdef CONFIG_WAKELOCK
920 amvdec_wake_unlock();
921#endif
922 }
923}
924EXPORT_SYMBOL(amhevc_stop);
925
926void amvdec_enable(void)
927{
928 amvdec_pg_enable(true);
929}
930EXPORT_SYMBOL(amvdec_enable);
931
932void amvdec_disable(void)
933{
934 amvdec_pg_enable(false);
935}
936EXPORT_SYMBOL(amvdec_disable);
937
938void amvdec2_enable(void)
939{
940 if (has_vdec2())
941 amvdec2_pg_enable(true);
942}
943EXPORT_SYMBOL(amvdec2_enable);
944
945void amvdec2_disable(void)
946{
947 if (has_vdec2())
948 amvdec2_pg_enable(false);
949}
950EXPORT_SYMBOL(amvdec2_disable);
951
952void amhevc_enable(void)
953{
954 if (has_hevc_vdec())
955 amhevc_pg_enable(true);
956}
957EXPORT_SYMBOL(amhevc_enable);
958
959void amhevc_disable(void)
960{
961 if (has_hevc_vdec())
962 amhevc_pg_enable(false);
963}
964EXPORT_SYMBOL(amhevc_disable);
965
966#ifdef CONFIG_PM
967int amvdec_suspend(struct platform_device *dev, pm_message_t event)
968{
969 amvdec_pg_enable(false);
970
971 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */
972 if (has_vdec2())
973 amvdec2_pg_enable(false);
974 /* #endif */
975
976 if (has_hevc_vdec())
977 amhevc_pg_enable(false);
978 /*vdec_set_suspend_clk(1, 0);*//*DEBUG_TMP*/
979 return 0;
980}
981EXPORT_SYMBOL(amvdec_suspend);
982
983int amvdec_resume(struct platform_device *dev)
984{
985 amvdec_pg_enable(true);
986
987 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6TVD */
988 if (has_vdec2())
989 amvdec2_pg_enable(true);
990 /* #endif */
991
992 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
993 if (has_hevc_vdec())
994 amhevc_pg_enable(true);
995 /* #endif */
996 /*vdec_set_suspend_clk(0, 0);*//*DEBUG_TMP*/
997 return 0;
998}
999EXPORT_SYMBOL(amvdec_resume);
1000
1001int amhevc_suspend(struct platform_device *dev, pm_message_t event)
1002{
1003 if (has_hevc_vdec()) {
1004 amhevc_pg_enable(false);
1005 /*vdec_set_suspend_clk(1, 1);*//*DEBUG_TMP*/
1006 }
1007 return 0;
1008}
1009EXPORT_SYMBOL(amhevc_suspend);
1010
1011int amhevc_resume(struct platform_device *dev)
1012{
1013 if (has_hevc_vdec()) {
1014 amhevc_pg_enable(true);
1015 /*vdec_set_suspend_clk(0, 1);*//*DEBUG_TMP*/
1016 }
1017 return 0;
1018}
1019EXPORT_SYMBOL(amhevc_resume);
1020
1021
1022#endif
1023
1024#ifdef CONFIG_WAKELOCK
1025
1026static int vdec_is_paused(void)
1027{
1028 static unsigned long old_wp = -1, old_rp = -1, old_level = -1;
1029 unsigned long wp, rp, level;
1030 static int paused_time;
1031
1032 /* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON8 */
1033 if (has_hevc_vdec()) {
1034 if ((vdec_on(VDEC_HEVC))
1035 && (READ_VREG(HEVC_STREAM_CONTROL) & 1)) {
1036 wp = READ_VREG(HEVC_STREAM_WR_PTR);
1037 rp = READ_VREG(HEVC_STREAM_RD_PTR);
1038 level = READ_VREG(HEVC_STREAM_LEVEL);
1039 } else {
1040 wp = READ_VREG(VLD_MEM_VIFIFO_WP);
1041 rp = READ_VREG(VLD_MEM_VIFIFO_RP);
1042 level = READ_VREG(VLD_MEM_VIFIFO_LEVEL);
1043 }
1044 } else
1045 /* #endif */
1046 {
1047 wp = READ_VREG(VLD_MEM_VIFIFO_WP);
1048 rp = READ_VREG(VLD_MEM_VIFIFO_RP);
1049 level = READ_VREG(VLD_MEM_VIFIFO_LEVEL);
1050 }
1051 /*have data,but output buffer is full */
1052 if ((rp == old_rp && level > 1024) ||
1053 (rp == old_rp && wp == old_wp && level == old_level)) {
1054 /*no write && not read */
1055 paused_time++;
1056 } else {
1057 paused_time = 0;
1058 }
1059 old_wp = wp; old_rp = rp; old_level = level;
1060 if (paused_time > 10)
1061 return 1;
1062 return 0;
1063}
1064
1065int amvdev_pause(void)
1066{
1067 video_running = 0;
1068 video_stated_changed = 1;
1069 return 0;
1070}
1071EXPORT_SYMBOL(amvdev_pause);
1072
1073int amvdev_resume(void)
1074{
1075 video_running = 1;
1076 video_stated_changed = 1;
1077 return 0;
1078}
1079EXPORT_SYMBOL(amvdev_resume);
1080
1081static void vdec_paused_check_timer(unsigned long arg)
1082{
1083 if (video_stated_changed) {
1084 if (!video_running) {
1085 if (vdec_is_paused()) {
1086 pr_info("vdec paused and release wakelock now\n");
1087 amvdec_wake_unlock();
1088 video_stated_changed = 0;
1089 }
1090 } else {
1091 amvdec_wake_lock();
1092 video_stated_changed = 0;
1093 }
1094 }
1095 mod_timer(&amvdevtimer, jiffies + WAKE_CHECK_INTERVAL);
1096}
1097#else
1098int amvdev_pause(void)
1099{
1100 return 0;
1101}
1102
1103int amvdev_resume(void)
1104{
1105 return 0;
1106}
1107#endif
1108
1109int amvdec_init(void)
1110{
1111#ifdef CONFIG_WAKELOCK
1112 /*
1113 *wake_lock_init(&amvdec_lock, WAKE_LOCK_IDLE, "amvdec_lock");
1114 *tmp mark for compile, no "WAKE_LOCK_IDLE" definition in kernel 3.8
1115 */
1116 wake_lock_init(&amvdec_lock, /*WAKE_LOCK_IDLE */ WAKE_LOCK_SUSPEND,
1117 "amvdec_lock");
1118
1119 init_timer(&amvdevtimer);
1120
1121 amvdevtimer.data = (ulong) &amvdevtimer;
1122 amvdevtimer.function = vdec_paused_check_timer;
1123#endif
1124 return 0;
1125}
1126EXPORT_SYMBOL(amvdec_init);
1127
1128void amvdec_exit(void)
1129{
1130#ifdef CONFIG_WAKELOCK
1131 del_timer_sync(&amvdevtimer);
1132#endif
1133}
1134EXPORT_SYMBOL(amvdec_exit);
1135
1136#if 0
1137int __init amvdec_init(void)
1138{
1139#ifdef CONFIG_WAKELOCK
1140 /*
1141 *wake_lock_init(&amvdec_lock, WAKE_LOCK_IDLE, "amvdec_lock");
1142 *tmp mark for compile, no "WAKE_LOCK_IDLE" definition in kernel 3.8
1143 */
1144 wake_lock_init(&amvdec_lock, /*WAKE_LOCK_IDLE */ WAKE_LOCK_SUSPEND,
1145 "amvdec_lock");
1146
1147 init_timer(&amvdevtimer);
1148
1149 amvdevtimer.data = (ulong) &amvdevtimer;
1150 amvdevtimer.function = vdec_paused_check_timer;
1151#endif
1152 return 0;
1153}
1154
1155static void __exit amvdec_exit(void)
1156{
1157#ifdef CONFIG_WAKELOCK
1158 del_timer_sync(&amvdevtimer);
1159#endif
1160}
1161
1162module_init(amvdec_init);
1163module_exit(amvdec_exit);
1164#endif
1165
1166MODULE_DESCRIPTION("Amlogic Video Decoder Utility Driver");
1167MODULE_LICENSE("GPL");
1168MODULE_AUTHOR("Tim Yao <timyao@amlogic.com>");
1169