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