• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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