• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * drivers\media\cedar_ve
3  * (C) Copyright 2010-2016
4  * Reuuimlla Technology Co., Ltd. <www.allwinnertech.com>
5  * fangning<fangning@allwinnertech.com>
6  *
7  * some simple description for this code
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  */
15 
16 #include <linux/init.h>
17 #include <linux/module.h>
18 #include <linux/ioctl.h>
19 #include <linux/fs.h>
20 #include <linux/device.h>
21 #include <linux/err.h>
22 #include <linux/list.h>
23 #include <linux/errno.h>
24 #include <linux/mutex.h>
25 #include <linux/slab.h>
26 #include <linux/preempt.h>
27 #include <linux/cdev.h>
28 #include <linux/platform_device.h>
29 #include <linux/interrupt.h>
30 #include <linux/clk.h>
31 #include <linux/rmap.h>
32 #include <linux/wait.h>
33 #include <linux/semaphore.h>
34 #include <linux/poll.h>
35 #include <linux/spinlock.h>
36 #include <linux/sched.h>
37 #include <linux/signal.h>
38 #include <linux/sched/signal.h>
39 #include <linux/kthread.h>
40 #include <linux/delay.h>
41 #include <linux/scatterlist.h>
42 #include <asm/uaccess.h>
43 #include <asm/io.h>
44 #include <asm/dma.h>
45 #include <linux/mm.h>
46 #include <asm/siginfo.h>
47 #include <asm/signal.h>
48 #include <sunxi-clk.h>
49 #include <linux/debugfs.h>
50 #include <linux/pm_runtime.h>
51 
52 #if IS_ENABLED(CONFIG_SUNXI_MPP)
53 #include <linux/mpp.h>
54 #endif
55 
56 #include <linux/of.h>
57 #include <linux/of_address.h>
58 #include <linux/of_irq.h>
59 
60 #include "cedar_ve.h"
61 #include "ve_mem_list.h"
62 #include <linux/regulator/consumer.h>
63 #include <linux/dma-mapping.h>
64 #include <linux/dma-buf.h>
65 //#include <linux/sunxi_mbus.h>
66 #include <linux/reset.h>
67 #include <asm/cacheflush.h>
68 #include <linux/dma-mapping.h>
69 struct regulator *regu;
70 
71 #define DRV_VERSION "0.01alpha"
72 
73 #undef USE_CEDAR_ENGINE
74 
75 #ifndef CEDARDEV_MAJOR
76 #define CEDARDEV_MAJOR (150)
77 #endif
78 #ifndef CEDARDEV_MINOR
79 #define CEDARDEV_MINOR (0)
80 #endif
81 
82 #define MACC_REGS_BASE		(0x01C0E000)
83 
84 #ifndef CONFIG_OF
85 #define SUNXI_IRQ_VE		(90)
86 #endif
87 
88 /* just for decoder case with v5v200*/
89 #if IS_ENABLED(CONFIG_ARCH_SUN8IW16P1)
90 	#define VE_POWER_MANAGE_VALID (1)
91 #else
92 	#define VE_POWER_MANAGE_VALID (0)
93 #endif
94 
95 #define CEDAR_DEBUG
96 #define cedar_ve_printk(level, msg...) printk(level "cedar_ve: " msg)
97 
98 #define VE_LOGD(fmt, arg...) printk(KERN_DEBUG"VE: "fmt"\n", ##arg)
99 #define VE_LOGI(fmt, arg...) printk(KERN_INFO"VE: "fmt"\n", ##arg)
100 #define VE_LOGW(fmt, arg...) printk(KERN_WARNING"VE: "fmt"\n", ##arg)
101 #define VE_LOGE(fmt, arg...) printk(KERN_ERR"VE: "fmt"\n", ##arg)
102 
103 #define VE_CLK_HIGH_WATER  (900)
104 #define VE_CLK_LOW_WATER   (100)
105 
106 #define PRINTK_IOMMU_ADDR 0
107 #define MAX_VE_DEBUG_INFO_NUM (16)
108 
109 /* the struct must be same with cedarc/ve/veAw/veAw.h*/
110 struct debug_head_info {
111 	unsigned int pid;
112 	unsigned int tid;
113 	unsigned int length;
114 };
115 struct ve_debug_info {
116 	struct debug_head_info head_info;
117 	char *data;
118 };
119 
120 #define VE_DEBUGFS_MAX_CHANNEL 16
121 #define VE_DEBUGFS_BUF_SIZE 1024
122 
123 struct ve_debugfs_proc {
124 	unsigned int	len;
125 	char			data[VE_DEBUGFS_BUF_SIZE * VE_DEBUGFS_MAX_CHANNEL];
126 };
127 
128 struct ve_debugfs_buffer {
129 	unsigned char	 cur_channel_id;
130 	unsigned int	proc_len[VE_DEBUGFS_MAX_CHANNEL];
131 	char			*proc_buf[VE_DEBUGFS_MAX_CHANNEL];
132 	char			*data;
133 	struct mutex lock_proc;
134 };
135 struct ve_debugfs_buffer ve_debug_proc_info;
136 
137 struct __cedarv_task {
138 	int task_prio;
139 	int ID;
140 	unsigned long timeout;
141 	unsigned int frametime;
142 	unsigned int block_mode;
143 };
144 
145 struct cedarv_engine_task {
146 	struct __cedarv_task t;
147 	struct list_head list;
148 	struct task_struct *task_handle;
149 	unsigned int status;
150 	unsigned int running;
151 	unsigned int is_first_task;
152 };
153 
154 struct cedarv_engine_task_info {
155 	int task_prio;
156 	unsigned int frametime;
157 	unsigned int total_time;
158 };
159 
160 struct cedarv_regop {
161 	unsigned long addr;
162 	unsigned int value;
163 };
164 
165 struct cedarv_env_infomation_compat {
166 	unsigned int phymem_start;
167 	int	 phymem_total_size;
168 	u32	 address_macc;
169 };
170 
171 struct __cedarv_task_compat {
172 	int task_prio;
173 	int ID;
174 	u32 timeout;
175 	unsigned int frametime;
176 	unsigned int block_mode;
177 };
178 
179 struct cedarv_regop_compat {
180 	u32 addr;
181 	unsigned int value;
182 };
183 
184 struct VE_PROC_INFO {
185 	unsigned char   channel_id;
186 	unsigned int	proc_info_len;
187 };
188 
189 int g_dev_major = CEDARDEV_MAJOR;
190 int g_dev_minor = CEDARDEV_MINOR;
191 /*S_IRUGO represent that g_dev_major can be read,but canot be write*/
192 module_param(g_dev_major, int, 0444);
193 module_param(g_dev_minor, int, 0444);
194 
195 struct iomap_para {
196 	volatile char *regs_ve;
197 	volatile char *regs_sys_cfg;
198 	volatile unsigned int *regs_ccmu;
199 	unsigned int *prcm_bass_vir;/*  PRCM: power reset clock management*/
200 };
201 
202 static DECLARE_WAIT_QUEUE_HEAD(wait_ve);
203 
204 struct cedar_dev {
205 	struct cdev cdev;				 /* char device struct				   */
206 	struct device *dev;				 /* ptr to class device struct		   */
207 	struct device *plat_dev;	     /* ptr to class device struct		   */
208 	struct class  *class;			 /* class for auto create device node  */
209 
210 	struct semaphore sem;			 /* mutual exclusion semaphore		   */
211 	spinlock_t lock;
212 	wait_queue_head_t wq;			 /* wait queue for poll ops			   */
213 
214 	struct iomap_para iomap_addrs;	 /* io remap addrs					   */
215 
216 	struct timer_list cedar_engine_timer;
217 	struct timer_list cedar_engine_timer_rel;
218 
219 	u32 irq;						 /* cedar video engine irq number	   */
220 	u32 de_irq_flag;					/* flag of video decoder engine irq generated */
221 	u32 de_irq_value;					/* value of video decoder engine irq		  */
222 	u32 en_irq_flag;					/* flag of video encoder engine irq generated */
223 	u32 en_irq_value;					/* value of video encoder engine irq		  */
224 	u32 irq_has_enable;
225 	int ref_count;
226 	int last_min_freq;
227 
228 	u32 jpeg_irq_flag;					  /* flag of video jpeg dec irq generated */
229 	u32 jpeg_irq_value;					  /* value of video jpeg dec  irq */
230 
231 	struct mutex lock_vdec;
232 	struct mutex lock_jdec;
233 	struct mutex lock_venc;
234 	struct mutex lock_00_reg;
235 	struct mutex lock_04_reg;
236 	struct aw_mem_list_head	   list;		/* buffer list */
237 	struct mutex lock_mem;
238 	unsigned char bMemDevAttachFlag;
239 	u32 power_manage_request_ref;
240 	struct ve_debug_info  debug_info[MAX_VE_DEBUG_INFO_NUM];
241 	int debug_info_cur_index;
242 	struct mutex lock_debug_info;
243 	struct reset_control *reset;
244 	struct clk *ve_clk;
245 #if defined CONFIG_ARCH_SUN50IW12P1
246 	struct reset_control *reset_ve;
247 	struct clk *bus_ve3_clk;
248 	struct clk *bus_ve_clk;
249 	struct clk *mbus_ve3_clk;
250 #else
251 	struct clk *bus_clk;
252 	struct clk *mbus_clk;
253 #endif
254 	struct clk *parent_clk;
255 	struct clk *power_clk;
256 	struct dentry *debug_root;
257 };
258 
259 struct ve_info { /* each object will bind a new file handler */
260 	unsigned int set_vol_flag;
261 
262 	struct mutex lock_flag_io;
263 	u32 lock_flags; /* if flags is 0, means unlock status */
264 };
265 
266 struct user_iommu_param {
267 	int				fd;
268 	unsigned int	iommu_addr;
269 };
270 
271 struct dma_buf_info {
272 	struct aw_mem_list_head i_list;
273 	int				fd;
274 	unsigned long	addr;
275 	struct dma_buf	*dma_buf;
276 	struct dma_buf_attachment *attachment;
277 	struct sg_table	*sgt;
278 	int    p_id;
279 	struct file *filp;
280 };
281 
282 static struct cedar_dev *cedar_devp;
283 
284 /*
285  * Video engine interrupt service routine
286  * To wake up ve wait queue
287  */
288 
289 
290 
291 extern void cedar_dma_flush_range(const void *, size_t);
292 static int map_dma_buf_addr(int fd, unsigned int *addr, struct file *filp);
293 static void unmap_dma_buf_addr(int unmap_all, int fd, struct file *filp);
294 
VideoEngineInterupt(int irq,void * dev)295 static irqreturn_t VideoEngineInterupt(int irq, void *dev)
296 {
297 	unsigned long ve_int_status_reg;
298 	unsigned long ve_int_ctrl_reg;
299 	unsigned int status;
300 	volatile int val;
301 	int modual_sel;
302 	unsigned int interrupt_enable;
303 	struct iomap_para addrs = cedar_devp->iomap_addrs;
304 
305 	modual_sel = readl(addrs.regs_ve + 0x0);
306 #if defined CONFIG_ARCH_SUN3IW1P1
307 	if (modual_sel&0xa) {
308 		if ((modual_sel&0xb) == 0xb) {
309 			/*jpg enc*/
310 			ve_int_status_reg = (unsigned long)(addrs.regs_ve + 0xb00 + 0x1c);
311 			ve_int_ctrl_reg = (unsigned long)(addrs.regs_ve + 0xb00 + 0x14);
312 			interrupt_enable = readl((void *)ve_int_ctrl_reg) & (0x7);
313 			status = readl((void *)ve_int_status_reg);
314 			status &= 0xf;
315 		} else {
316 			/*isp*/
317 			ve_int_status_reg = (unsigned long)(addrs.regs_ve + 0xa00 + 0x10);
318 			ve_int_ctrl_reg = (unsigned long)(addrs.regs_ve + 0xa00 + 0x08);
319 			interrupt_enable = readl((void *)ve_int_ctrl_reg) & (0x1);
320 			status = readl((void *)ve_int_status_reg);
321 			status &= 0x1;
322 		}
323 
324 		if (status && interrupt_enable) {
325 			/*disable interrupt*/
326 			if ((modual_sel & 0xb) == 0xb) {
327 				ve_int_ctrl_reg = (unsigned long)(addrs.regs_ve + 0xb00 + 0x14);
328 				val = readl((void *)ve_int_ctrl_reg);
329 				writel(val & (~0x7), (void *)ve_int_ctrl_reg);
330 			} else {
331 				ve_int_ctrl_reg = (unsigned long)(addrs.regs_ve + 0xa00 + 0x08);
332 				val = readl((void *)ve_int_ctrl_reg);
333 				writel(val & (~0x1), (void *)ve_int_ctrl_reg);
334 			}
335 
336 			cedar_devp->en_irq_value = 1;	/*hx modify 2011-8-1 16:08:47*/
337 			cedar_devp->en_irq_flag = 1;
338 			/*any interrupt will wake up wait queue*/
339 			wake_up(&wait_ve);		  /*ioctl*/
340 		}
341 	}
342 #else
343 	if (modual_sel&(3<<6)) {
344 		if (modual_sel&(1<<7)) {
345 			/*avc enc*/
346 			ve_int_status_reg = (unsigned long)(addrs.regs_ve + 0xb00 + 0x1c);
347 			ve_int_ctrl_reg = (unsigned long)(addrs.regs_ve + 0xb00 + 0x14);
348 			interrupt_enable = readl((void *)ve_int_ctrl_reg) & (0x7);
349 			status = readl((void *)ve_int_status_reg);
350 			status &= 0xf;
351 		} else {
352 			/*isp*/
353 			ve_int_status_reg = (unsigned long)(addrs.regs_ve + 0xa00 + 0x10);
354 			ve_int_ctrl_reg = (unsigned long)(addrs.regs_ve + 0xa00 + 0x08);
355 			interrupt_enable = readl((void *)ve_int_ctrl_reg) & (0x1);
356 			status = readl((void *)ve_int_status_reg);
357 			status &= 0x1;
358 		}
359 
360 		/*modify by fangning 2013-05-22*/
361 		if (status && interrupt_enable) {
362 			/*disable interrupt*/
363 			/*avc enc*/
364 			if (modual_sel&(1<<7)) {
365 				ve_int_ctrl_reg = (unsigned long)(addrs.regs_ve + 0xb00 + 0x14);
366 				val = readl((void *)ve_int_ctrl_reg);
367 				writel(val & (~0x7), (void *)ve_int_ctrl_reg);
368 			} else {
369 				/*isp*/
370 				ve_int_ctrl_reg = (unsigned long)(addrs.regs_ve + 0xa00 + 0x08);
371 				val = readl((void *)ve_int_ctrl_reg);
372 				writel(val & (~0x1), (void *)ve_int_ctrl_reg);
373 			}
374 			/*hx modify 2011-8-1 16:08:47*/
375 			cedar_devp->en_irq_value = 1;
376 			cedar_devp->en_irq_flag = 1;
377 			/*any interrupt will wake up wait queue*/
378 			wake_up(&wait_ve);
379 		}
380 	}
381 #endif
382 
383 #if ((defined CONFIG_ARCH_SUN8IW8P1) || (defined CONFIG_ARCH_SUN50I) || \
384 	(defined CONFIG_ARCH_SUN8IW12P1) || (defined CONFIG_ARCH_SUN8IW17P1) \
385 	|| (defined CONFIG_ARCH_SUN8IW16P1) || (defined CONFIG_ARCH_SUN8IW19P1))
386 	if (modual_sel&(0x20)) {
387 		ve_int_status_reg = (unsigned long)(addrs.regs_ve + 0xe00 + 0x1c);
388 		ve_int_ctrl_reg = (unsigned long)(addrs.regs_ve + 0xe00 + 0x14);
389 		interrupt_enable = readl((void *)ve_int_ctrl_reg) & (0x38);
390 
391 		status = readl((void *)ve_int_status_reg);
392 
393 		if ((status&0x7) && interrupt_enable) {
394 			/*disable interrupt*/
395 			val = readl((void *)ve_int_ctrl_reg);
396 			writel(val & (~0x38), (void *)ve_int_ctrl_reg);
397 
398 			cedar_devp->jpeg_irq_value = 1;
399 			cedar_devp->jpeg_irq_flag = 1;
400 
401 			/*any interrupt will wake up wait queue*/
402 			wake_up(&wait_ve);
403 		}
404 	}
405 #endif
406 
407 	modual_sel &= 0xf;
408 	if (modual_sel <= 6) {
409 		/*estimate Which video format*/
410 		switch (modual_sel) {
411 		case 0: /*mpeg124*/
412 			ve_int_status_reg = (unsigned long)
413 				(addrs.regs_ve + 0x100 + 0x1c);
414 			ve_int_ctrl_reg = (unsigned long)(addrs.regs_ve + 0x100 + 0x14);
415 			interrupt_enable = readl((void *)ve_int_ctrl_reg) & (0x7c);
416 			break;
417 		case 1: /*h264*/
418 			ve_int_status_reg = (unsigned long)
419 				(addrs.regs_ve + 0x200 + 0x28);
420 			ve_int_ctrl_reg = (unsigned long)(addrs.regs_ve + 0x200 + 0x20);
421 			interrupt_enable = readl((void *)ve_int_ctrl_reg) & (0xf);
422 			break;
423 		case 2: /*vc1*/
424 			ve_int_status_reg = (unsigned long)(addrs.regs_ve +
425 				0x300 + 0x2c);
426 			ve_int_ctrl_reg = (unsigned long)(addrs.regs_ve + 0x300 + 0x24);
427 			interrupt_enable = readl((void *)ve_int_ctrl_reg) & (0xf);
428 			break;
429 		case 3: /*rv*/
430 			ve_int_status_reg = (unsigned long)
431 				(addrs.regs_ve + 0x400 + 0x1c);
432 			ve_int_ctrl_reg = (unsigned long)(addrs.regs_ve + 0x400 + 0x14);
433 			interrupt_enable = readl((void *)ve_int_ctrl_reg) & (0xf);
434 			break;
435 		case 4: /*hevc*/
436 			ve_int_status_reg = (unsigned long)
437 				(addrs.regs_ve + 0x500 + 0x38);
438 			ve_int_ctrl_reg = (unsigned long)(addrs.regs_ve + 0x500 + 0x30);
439 			interrupt_enable = readl((void *)ve_int_ctrl_reg) & (0xf);
440 			break;
441 		case 6: /*scaledown*/
442 			ve_int_status_reg = (unsigned long)(addrs.regs_ve + 0xF00 +0x08);
443 			ve_int_ctrl_reg = (unsigned long)(addrs.regs_ve + 0xF00 + 0x04);
444 			interrupt_enable = readl((void *)ve_int_ctrl_reg) & (0x1);
445 			break;
446 		default:
447 			ve_int_status_reg = (unsigned long)(addrs.regs_ve + 0x100 + 0x1c);
448 			ve_int_ctrl_reg = (unsigned long)(addrs.regs_ve + 0x100 + 0x14);
449 			interrupt_enable = readl((void *)ve_int_ctrl_reg) & (0xf);
450 			VE_LOGW("ve mode :%x " "not defined!\n", modual_sel);
451 			break;
452 		}
453 
454 		status = readl((void *)ve_int_status_reg);
455 
456 		/*modify by fangning 2013-05-22*/
457 		if ((status&0xf) && interrupt_enable) {
458 			/*disable interrupt*/
459 			if (modual_sel == 0) {
460 				val = readl((void *)ve_int_ctrl_reg);
461 				writel(val & (~0x7c), (void *)ve_int_ctrl_reg);
462 			} else if (modual_sel == 6) {
463 				val = readl((void *)ve_int_ctrl_reg);
464 				writel(val & (~0x1), (void *)ve_int_ctrl_reg);
465 			} else {
466 				val = readl((void *)ve_int_ctrl_reg);
467 				writel(val & (~0xf), (void *)ve_int_ctrl_reg);
468 			}
469 			cedar_devp->de_irq_value = 1;
470 			cedar_devp->de_irq_flag = 1;
471 			/*any interrupt will wake up wait queue*/
472 			wake_up(&wait_ve);
473 		}
474 	}
475 
476 	return IRQ_HANDLED;
477 }
478 
479 static int clk_status;
480 static LIST_HEAD(run_task_list);
481 static LIST_HEAD(del_task_list);
482 #define CEDAR_RUN_LIST_NONULL	-1
483 #define CEDAR_NONBLOCK_TASK	 0
484 #define CEDAR_BLOCK_TASK 1
485 #define CLK_REL_TIME 10000
486 #define TIMER_CIRCLE 50
487 #define TASK_INIT	   0x00
488 #define TASK_TIMEOUT   0x55
489 #define TASK_RELEASE   0xaa
490 #define SIG_CEDAR		35
491 
enable_cedar_hw_clk(void)492 int enable_cedar_hw_clk(void)
493 {
494 	unsigned long flags;
495 	int res = 0;
496 	VE_LOGD("enable hw clock");
497 	spin_lock_irqsave(&cedar_devp->lock, flags);
498 
499 	if (clk_status == 1)
500 		goto out;
501 
502 	clk_status = 1;
503 
504 	spin_unlock_irqrestore(&cedar_devp->lock, flags);
505 
506 #if defined CONFIG_ARCH_SUN50IW12P1
507 	reset_control_deassert(cedar_devp->reset_ve);
508 #endif
509 	reset_control_deassert(cedar_devp->reset);
510 
511 #if defined CONFIG_ARCH_SUN50IW12P1
512 	if (clk_prepare_enable(cedar_devp->bus_ve_clk)) {
513 		VE_LOGW("enable bus clk gating failed;\n");
514 		res = -EINVAL;
515 		goto out;
516 	}
517 
518 	if (clk_prepare_enable(cedar_devp->bus_ve3_clk)) {
519 		VE_LOGW("enable bus clk gating failed;\n");
520 		res = -EINVAL;
521 		goto out;
522 	}
523 
524 	if (clk_prepare_enable(cedar_devp->mbus_ve3_clk)) {
525 		VE_LOGW("enable mbus clk gating failed;\n");
526 		res = -EINVAL;
527 		goto out;
528 	}
529 #else
530 	if (clk_prepare_enable(cedar_devp->bus_clk)) {
531 		VE_LOGW("enable bus clk gating failed;\n");
532 		res = -EINVAL;
533 		goto out;
534 	}
535 
536 	if (clk_prepare_enable(cedar_devp->mbus_clk)) {
537 		VE_LOGW("enable mbus clk gating failed;\n");
538 		res = -EINVAL;
539 		goto out;
540 	}
541 #endif
542 
543 	if (clk_prepare_enable(cedar_devp->ve_clk)) {
544 		VE_LOGW("enable ve clk gating failed;\n");
545 		res = -EINVAL;
546 		goto out;
547 	}
548 
549 	AW_MEM_INIT_LIST_HEAD(&cedar_devp->list);
550 
551 #ifdef CEDAR_DEBUG
552 	printk("%s,%d\n", __func__, __LINE__);
553 #endif
554 
555 out:
556 	return res;
557 }
558 
disable_cedar_hw_clk(void)559 int disable_cedar_hw_clk(void)
560 {
561 	unsigned long flags;
562 	int res = 0;
563 
564 	VE_LOGD("disable hw clock");
565 	spin_lock_irqsave(&cedar_devp->lock, flags);
566 
567 	if (clk_status == 0) {
568 		spin_unlock_irqrestore(&cedar_devp->lock, flags);
569 		goto out;
570 	}
571 	clk_status = 0;
572 
573 	spin_unlock_irqrestore(&cedar_devp->lock, flags);
574 
575 	clk_disable_unprepare(cedar_devp->ve_clk);
576 #if defined CONFIG_ARCH_SUN50IW12P1
577 	clk_disable_unprepare(cedar_devp->mbus_ve3_clk);
578 	clk_disable_unprepare(cedar_devp->bus_ve3_clk);
579 	clk_disable_unprepare(cedar_devp->bus_ve_clk);
580 #else
581 	clk_disable_unprepare(cedar_devp->mbus_clk);
582 	clk_disable_unprepare(cedar_devp->bus_clk);
583 #endif
584 	reset_control_assert(cedar_devp->reset);
585 #if defined CONFIG_ARCH_SUN50IW12P1
586 	reset_control_assert(cedar_devp->reset_ve);
587 #endif
588 
589 	//unmap_dma_buf_addr(1, 0, filp);
590 
591 #ifdef CEDAR_DEBUG
592 	printk("%s,%d\n", __func__, __LINE__);
593 #endif
594 
595 out:
596 	return res;
597 }
598 
cedardev_insert_task(struct cedarv_engine_task * new_task)599 void cedardev_insert_task(struct cedarv_engine_task *new_task)
600 {
601 	struct cedarv_engine_task *task_entry;
602 	unsigned long flags;
603 
604 	spin_lock_irqsave(&cedar_devp->lock, flags);
605 
606 	if (list_empty(&run_task_list))
607 		new_task->is_first_task = 1;
608 
609 
610 	list_for_each_entry(task_entry, &run_task_list, list) {
611 		if ((task_entry->is_first_task == 0) && (task_entry->running == 0) && (task_entry->t.task_prio < new_task->t.task_prio)) {
612 			break;
613 		}
614 	}
615 
616 	list_add(&new_task->list, task_entry->list.prev);
617 
618 #ifdef CEDAR_DEBUG
619 	printk("%s,%d, TASK_ID:", __func__, __LINE__);
620 	list_for_each_entry(task_entry, &run_task_list, list) {
621 		printk("%d!", task_entry->t.ID);
622 	}
623 	printk("\n");
624 #endif
625 
626 	mod_timer(&cedar_devp->cedar_engine_timer, jiffies + 0);
627 
628 	spin_unlock_irqrestore(&cedar_devp->lock, flags);
629 }
630 
cedardev_del_task(int task_id)631 int cedardev_del_task(int task_id)
632 {
633 	struct cedarv_engine_task *task_entry;
634 	unsigned long flags;
635 
636 	spin_lock_irqsave(&cedar_devp->lock, flags);
637 
638 	list_for_each_entry(task_entry, &run_task_list, list) {
639 		if (task_entry->t.ID == task_id && task_entry->status != TASK_RELEASE) {
640 			task_entry->status = TASK_RELEASE;
641 
642 			spin_unlock_irqrestore(&cedar_devp->lock, flags);
643 			mod_timer(&cedar_devp->cedar_engine_timer, jiffies + 0);
644 			return 0;
645 		}
646 	}
647 	spin_unlock_irqrestore(&cedar_devp->lock, flags);
648 
649 	return -1;
650 }
651 
cedardev_check_delay(int check_prio)652 int cedardev_check_delay(int check_prio)
653 {
654 	struct cedarv_engine_task *task_entry;
655 	int timeout_total = 0;
656 	unsigned long flags;
657 
658 	spin_lock_irqsave(&cedar_devp->lock, flags);
659 	list_for_each_entry(task_entry, &run_task_list, list) {
660 		if ((task_entry->t.task_prio >= check_prio) || (task_entry->running == 1) || (task_entry->is_first_task == 1))
661 			timeout_total = timeout_total + task_entry->t.frametime;
662 	}
663 
664 	spin_unlock_irqrestore(&cedar_devp->lock, flags);
665 #ifdef CEDAR_DEBUG
666 	printk("%s,%d,%d\n", __func__, __LINE__, timeout_total);
667 #endif
668 	return timeout_total;
669 }
670 
cedar_engine_for_timer_rel(struct timer_list * list)671 static void cedar_engine_for_timer_rel(struct timer_list *list)
672 {
673 	unsigned long flags;
674 	int ret = 0;
675 
676 	spin_lock_irqsave(&cedar_devp->lock, flags);
677 
678 	if (list_empty(&run_task_list)) {
679 		ret = disable_cedar_hw_clk();
680 		if (ret < 0) {
681 			VE_LOGW("clk disable error!\n");
682 		}
683 	} else {
684 		VE_LOGW("clk disable time out but task left\n");
685 		mod_timer(&cedar_devp->cedar_engine_timer, jiffies + msecs_to_jiffies(TIMER_CIRCLE));
686 	}
687 
688 	spin_unlock_irqrestore(&cedar_devp->lock, flags);
689 }
690 
cedar_engine_for_events(struct timer_list * list)691 static void cedar_engine_for_events(struct timer_list *list)
692 {
693 	struct cedarv_engine_task *task_entry, *task_entry_tmp;
694 	struct kernel_siginfo sig_info;
695 	unsigned long flags;
696 
697 	spin_lock_irqsave(&cedar_devp->lock, flags);
698 
699 	list_for_each_entry_safe(task_entry, task_entry_tmp, &run_task_list, list) {
700 		mod_timer(&cedar_devp->cedar_engine_timer_rel, jiffies + msecs_to_jiffies(CLK_REL_TIME));
701 		if (task_entry->status == TASK_RELEASE ||
702 				time_after(jiffies, task_entry->t.timeout)) {
703 			if (task_entry->status == TASK_INIT)
704 				task_entry->status = TASK_TIMEOUT;
705 			list_move(&task_entry->list, &del_task_list);
706 		}
707 	}
708 
709 	list_for_each_entry_safe(task_entry, task_entry_tmp, &del_task_list, list) {
710 		sig_info.si_signo = SIG_CEDAR;
711 		sig_info.si_code = task_entry->t.ID;
712 		if (task_entry->status == TASK_TIMEOUT) {
713 			sig_info.si_errno = TASK_TIMEOUT;
714 			send_sig_info(SIG_CEDAR, &sig_info, task_entry->task_handle);
715 		} else if (task_entry->status == TASK_RELEASE) {
716 			sig_info.si_errno = TASK_RELEASE;
717 			send_sig_info(SIG_CEDAR, &sig_info, task_entry->task_handle);
718 		}
719 		list_del(&task_entry->list);
720 		kfree(task_entry);
721 	}
722 
723 	if (!list_empty(&run_task_list)) {
724 		task_entry = list_entry(run_task_list.next, struct cedarv_engine_task, list);
725 		if (task_entry->running == 0) {
726 			task_entry->running = 1;
727 			sig_info.si_signo = SIG_CEDAR;
728 			sig_info.si_code = task_entry->t.ID;
729 			sig_info.si_errno = TASK_INIT;
730 			send_sig_info(SIG_CEDAR, &sig_info, task_entry->task_handle);
731 		}
732 
733 		mod_timer(&cedar_devp->cedar_engine_timer, jiffies + msecs_to_jiffies(TIMER_CIRCLE));
734 	}
735 
736 	spin_unlock_irqrestore(&cedar_devp->lock, flags);
737 }
738 
739 #if 0/*(defined CONFIG_ARCH_SUN8IW16P1)*/
740 static int setVeFreqByReg(int fq)
741 {
742 	int max_count = 10000;
743 	int count = 0;
744 	unsigned int reg;
745 	int dst_freq = fq;
746 	unsigned int offset = (0x58/sizeof(unsigned int *));
747 
748 	reg = readl(cedar_devp->iomap_addrs.regs_ccmu + offset);
749 
750 	/*set VE freq*/
751 	reg = readl(cedar_devp->iomap_addrs.regs_ccmu + offset);
752 	reg &= 0x7ffa0000;
753 	fq = (fq/6) - 1;
754 
755 	/* step 0  lock enable write 0  */
756 	reg = reg & (~(1 << 29));
757 	writel(reg, cedar_devp->iomap_addrs.regs_ccmu + offset);
758 
759 	/* step 1 write clock parameter*/
760 	reg = readl(cedar_devp->iomap_addrs.regs_ccmu + offset);
761 	reg = reg | (fq<<8) | (1<<1) | (1<<0);
762 
763 	writel(reg, cedar_devp->iomap_addrs.regs_ccmu + offset);
764 
765 	/* step 2 write PLL enable */
766 	reg = readl(cedar_devp->iomap_addrs.regs_ccmu + offset);
767 	reg = reg | (1<<31);
768 	writel(reg, cedar_devp->iomap_addrs.regs_ccmu + offset);
769 
770 	/* step 3  lock enable write 1 */
771 	reg = readl(cedar_devp->iomap_addrs.regs_ccmu + offset);
772 	reg = reg | (1<<29);
773 	writel(reg, cedar_devp->iomap_addrs.regs_ccmu + offset);
774 
775 	reg = readl(cedar_devp->iomap_addrs.regs_ccmu + offset);
776 
777 	/* step 4  check bit28(lock) is 1 or not  */
778 	do {
779 		count++;
780 		if (count > max_count) {
781 			VE_LOGE("set ve freq failed, bit28 = 0x%x", reg);
782 			break;
783 		}
784 		udelay(5);
785 		reg = readl(cedar_devp->iomap_addrs.regs_ccmu + offset);
786 		reg = reg & (1 << 28);
787 	} while (reg == 0);
788 
789 	reg = readl(cedar_devp->iomap_addrs.regs_ccmu + offset);
790 
791 	VE_LOGW("ve freq reg = %x, dstFq = %d MHz, cout = %d, max = %d\n",
792 			reg, dst_freq, count, max_count);
793 	udelay(20);
794 
795 	return 0;
796 }
797 #endif
798 
799 #if VE_POWER_MANAGE_VALID
ve_power_manage_setup(void)800 static int ve_power_manage_setup(void)
801 {
802 	int ret = 0;
803 	unsigned int reg;
804 	unsigned int power_off_gating_reg_offset = 0;
805 	unsigned int power_switch_reg_offset = 0;
806 
807 	power_off_gating_reg_offset = (0x258/sizeof(unsigned int *));
808 	power_switch_reg_offset = (0x264/sizeof(unsigned int *));
809 
810 	/* set VE Power Switch Reg bit[15:0] to 0*/
811 	reg = readl(cedar_devp->prcm_bass_vir + power_switch_reg_offset);
812 	reg = reg >> 16;
813 	reg = reg << 16;
814 	writel(reg, cedar_devp->prcm_bass_vir + power_switch_reg_offset);
815 
816 	/* if VE Power Switch Reg bit[31:16] == 1, means setup sucees*/
817 	reg = readl(cedar_devp->prcm_bass_vir + power_switch_reg_offset);
818 
819 	if ((reg >> 16) == 0)
820 		ret = 0;
821 	else
822 		ret = -1;
823 
824 	/*VE_LOGI("setup: power_switch_reg = 0x%x, ret = %d",reg, ret);*/
825 
826 	/* set VE Power off Gating Reg bit[0] to 0*/
827 	reg = readl(cedar_devp->prcm_bass_vir + power_off_gating_reg_offset);
828 	reg = reg & ~1;
829 	writel(reg, cedar_devp->prcm_bass_vir + power_off_gating_reg_offset);
830 
831 	reg = readl(cedar_devp->prcm_bass_vir + power_off_gating_reg_offset);
832 	/*VE_LOGI("setup: power_off_reg = 0x%x",reg);*/
833 
834 	/* reset ve gating */
835 	reset_control_deassert(cedar_devp->reset);
836 	reset_control_assert(cedar_devp->reset);
837 	return ret;
838 }
839 
ve_power_manage_shutdown(void)840 static int ve_power_manage_shutdown(void)
841 {
842 	int max_count = 1000;
843 	int count = 0;
844 	int ret = 0;
845 	unsigned int reg;
846 	unsigned int power_off_gating_reg_offset = 0;
847 	unsigned int power_switch_reg_offset = 0;
848 
849 	power_off_gating_reg_offset	= (0x258/sizeof(unsigned int *));
850 	power_switch_reg_offset = (0x264/sizeof(unsigned int *));
851 
852 	/* reset ve gating */
853 	reset_control_deassert(cedar_devp->reset);
854 	reset_control_assert(cedar_devp->reset);
855 
856 	/* set VE Power off Gating Reg bit[0] to 1*/
857 	reg = readl(cedar_devp->prcm_bass_vir + power_off_gating_reg_offset);
858 	reg = reg | 1;
859 	writel(reg, cedar_devp->prcm_bass_vir + power_off_gating_reg_offset);
860 
861 	reg = readl(cedar_devp->prcm_bass_vir + power_off_gating_reg_offset);
862 	/*VE_LOGI("shutdown: power_off_reg = 0x%x",reg); */
863 
864 	/* set VE Power Switch Reg bit[15:0] to 0xffff*/
865 	reg = readl(cedar_devp->prcm_bass_vir + power_switch_reg_offset);
866 	reg = reg >> 16;
867 	reg = reg << 16;
868 	reg = reg | 0xffff;
869 	writel(reg, cedar_devp->prcm_bass_vir + power_switch_reg_offset);
870 
871 	/* if VE Power Switch Reg bit[31:16] == 0xffff, means shutdown sucees*/
872 	reg = 0;
873 	do {
874 		count++;
875 		if (count > max_count) {
876 			VE_LOGE("shutdown ve power failed, power_switch_reg = 0x%x",
877 					reg);
878 			break;
879 		}
880 
881 		udelay(5);
882 		reg = readl(cedar_devp->prcm_bass_vir + power_switch_reg_offset);
883 	} while ((reg >> 16) != 0xffff);
884 
885 	if ((reg >> 16) == 0xffff)
886 		ret = 0;
887 	else
888 		ret = -1;
889 
890 
891 	/*VE_LOGI("shutdown: power_switch_reg = 0x%x, ret = %d, count = %d, max = %d", */
892 	/*		reg, ret, count, max_count);*/
893 
894 	return ret;
895 }
896 
897 #endif
898 
map_dma_buf_addr(int fd,unsigned int * addr,struct file * filp)899 static int map_dma_buf_addr(int fd, unsigned int *addr, struct file *filp)
900 {
901 	struct sg_table *sgt;
902 	struct dma_buf_info *buf_info;
903 
904 	buf_info = (struct dma_buf_info *)kmalloc(sizeof(struct dma_buf_info), GFP_KERNEL);
905 	if (buf_info == NULL) {
906 		VE_LOGE("malloc dma_buf_info error\n");
907 		return -1;
908 	}
909 
910 	memset(buf_info, 0, sizeof(struct dma_buf_info));
911 	buf_info->dma_buf = dma_buf_get(fd);
912 	if (IS_ERR_OR_NULL(buf_info->dma_buf)) {
913 		VE_LOGE("ve get dma_buf error");
914 		goto BUF_FREE;
915 	}
916 
917 	buf_info->attachment = dma_buf_attach(buf_info->dma_buf, cedar_devp->plat_dev);
918 	if (IS_ERR_OR_NULL(buf_info->attachment)) {
919 		VE_LOGE("ve get dma_buf_attachment error");
920 		goto BUF_PUT;
921 	}
922 
923 	sgt = dma_buf_map_attachment(buf_info->attachment, DMA_BIDIRECTIONAL);
924 
925 	buf_info->sgt = sgt;
926 	if (IS_ERR_OR_NULL(buf_info->sgt)) {
927 		VE_LOGE("ve get sg_table error\n");
928 		goto BUF_DETATCH;
929 	}
930 
931 	buf_info->addr = sg_dma_address(buf_info->sgt->sgl);
932 	buf_info->fd = fd;
933 	buf_info->p_id = current->tgid;
934 	buf_info->filp = filp;
935 	#if PRINTK_IOMMU_ADDR
936 	VE_LOGI("fd:%d, buf_info:%p addr:%lx, dma_buf:%p, \
937 			dma_buf_attach:%p, sg_table:%p, nents:%d, pid:%d\n",
938 			buf_info->fd,
939 			buf_info,
940 			buf_info->addr,
941 			buf_info->dma_buf,
942 			buf_info->attachment,
943 			buf_info->sgt,
944 			buf_info->sgt->nents,
945 			buf_info->p_id);
946 	#endif
947 
948 	mutex_lock(&cedar_devp->lock_mem);
949 	aw_mem_list_add_tail(&buf_info->i_list, &cedar_devp->list);
950 	mutex_unlock(&cedar_devp->lock_mem);
951 
952 	*addr = buf_info->addr;
953 	return 0;
954 
955 	dma_buf_unmap_attachment(buf_info->attachment, buf_info->sgt,
956 							DMA_BIDIRECTIONAL);
957 BUF_DETATCH:
958 	dma_buf_detach(buf_info->dma_buf, buf_info->attachment);
959 BUF_PUT:
960 	dma_buf_put(buf_info->dma_buf);
961 BUF_FREE:
962 	kfree(buf_info);
963 	return -1;
964 }
965 
unmap_dma_buf_addr(int unmap_all,int fd,struct file * filp)966 static void unmap_dma_buf_addr(int unmap_all, int fd, struct file *filp)
967 {
968 	struct dma_buf_info *buf_info;
969 	struct aw_mem_list_head *pos;
970 	struct aw_mem_list_head *next;
971 	int tmp_fd;
972 
973 	mutex_lock(&cedar_devp->lock_mem);
974 	/*
975 	aw_mem_list_for_each_entry(buf_info, &cedar_devp->list, i_list) {
976 		#if PRINTK_IOMMU_ADDR
977 		VE_LOGI("list2 fd:%d, buf_info:%p addr:%lx, dma_buf:%p,
978 				dma_buf_attach:%p, sg_table:%p, nents:%d, pid:%d\n",
979 			buf_info->fd,
980 			buf_info,
981 			buf_info->addr,
982 			buf_info->dma_buf,
983 			buf_info->attachment,
984 			buf_info->sgt,
985 			buf_info->sgt->nents,
986 			buf_info->p_id);
987 		#endif
988 	}
989 	*/
990 	if (cedar_devp->bMemDevAttachFlag) {
991 		aw_mem_list_for_each_safe(pos, next, &cedar_devp->list) {
992 			buf_info = (struct dma_buf_info *)pos;
993 			if (unmap_all) {
994 				tmp_fd = buf_info->fd;
995 			} else {
996 				tmp_fd = fd;
997 			}
998 
999 			if (buf_info->fd == tmp_fd && buf_info->p_id == current->tgid && filp == buf_info->filp) {
1000 				#if PRINTK_IOMMU_ADDR
1001 				VE_LOGI("free: fd:%d, buf_info:%p iommu_addr:%lx, dma_buf:%p, \
1002 					dma_buf_attach:%p, sg_table:%p nets:%d, pid:%d unmapall:%d filp:%p\n",
1003 				buf_info->fd,
1004 				buf_info,
1005 				buf_info->addr,
1006 				buf_info->dma_buf,
1007 				buf_info->attachment,
1008 				buf_info->sgt,
1009 				buf_info->sgt->nents,
1010 				buf_info->p_id,
1011 				unmap_all,
1012 				filp);
1013 				#endif
1014 
1015 				if (buf_info->dma_buf > 0) {
1016 					if (buf_info->attachment > 0) {
1017 						if (buf_info->sgt > 0) {
1018 							dma_buf_unmap_attachment(buf_info->attachment,
1019 												buf_info->sgt,
1020 													DMA_BIDIRECTIONAL);
1021 						}
1022 						dma_buf_detach(buf_info->dma_buf, buf_info->attachment);
1023 					}
1024 					dma_buf_put(buf_info->dma_buf);
1025 				}
1026 				aw_mem_list_del(&buf_info->i_list);
1027 				kfree(buf_info);
1028 				if (unmap_all == 0)
1029 					break;
1030 			}
1031 		}
1032 	}
1033 	mutex_unlock(&cedar_devp->lock_mem);
1034 }
1035 
compat_cedardev_ioctl(struct file * filp,unsigned int cmd,unsigned long arg)1036 static long compat_cedardev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1037 {
1038 	long  ret = 0;
1039 	int ve_timeout = 0;
1040 	/*struct cedar_dev *devp;*/
1041 #ifdef USE_CEDAR_ENGINE
1042 	int rel_taskid = 0;
1043 	struct __cedarv_task task_ret;
1044 	struct cedarv_engine_task *task_ptr = NULL;
1045 #endif
1046 	unsigned long flags;
1047 	struct ve_info *info;
1048 
1049 	info = filp->private_data;
1050 
1051 	switch (cmd) {
1052 	case IOCTL_PROC_INFO_COPY:
1053 	{
1054 		int i = 0;
1055 		struct ve_debug_info *debug_info = NULL;
1056 		struct debug_head_info head_info;
1057 
1058 		/* parser head info */
1059 		cedar_devp->debug_info_cur_index = -1;
1060 		if (copy_from_user(&head_info, (void __user *)arg,
1061 			sizeof(struct debug_head_info))) {
1062 			VE_LOGW("SET_DEBUG_INFO copy_from_user fail\n");
1063 			return -EFAULT;
1064 		}
1065 
1066 
1067 		/*VE_LOGD("size of debug_head_info: %d", (int)sizeof(struct debug_head_info)); */
1068 		/*VE_LOGD("head_info: %d, %d, %d", head_info.pid, head_info.tid,head_info.length);*/
1069 
1070 
1071 		mutex_lock(&cedar_devp->lock_debug_info);
1072 		/* match debug info by pid and tid*/
1073 		for (i = 0; i < MAX_VE_DEBUG_INFO_NUM; i++) {
1074 			if (cedar_devp->debug_info[i].head_info.pid == head_info.pid
1075 			&& cedar_devp->debug_info[i].head_info.tid == head_info.tid)
1076 				break;
1077 		}
1078 
1079 		if (i >= MAX_VE_DEBUG_INFO_NUM) {
1080 			for (i = 0; i < MAX_VE_DEBUG_INFO_NUM; i++) {
1081 				if (cedar_devp->debug_info[i].head_info.pid == 0
1082 				&& cedar_devp->debug_info[i].head_info.tid == 0)
1083 					break;
1084 			}
1085 
1086 			if (i >= MAX_VE_DEBUG_INFO_NUM) {
1087 				VE_LOGW("SET_DEBUG_INFO  overflow  MAX_VE_DEBUG_INFO_NUM[%d]\n",
1088 								MAX_VE_DEBUG_INFO_NUM);
1089 			} else {
1090 				cedar_devp->debug_info_cur_index = i;
1091 				cedar_devp->debug_info[i].head_info.pid    = head_info.pid;
1092 				cedar_devp->debug_info[i].head_info.tid    = head_info.tid;
1093 				cedar_devp->debug_info[i].head_info.length = head_info.length;
1094 			}
1095 		} else {
1096 			cedar_devp->debug_info_cur_index = i;
1097 			cedar_devp->debug_info[i].head_info.length = head_info.length;
1098 		}
1099 
1100 
1101 		if (cedar_devp->debug_info_cur_index < 0) {
1102 			VE_LOGE("COPY_DEBUG_INFO, cur_index[%d] is invalided\n",
1103 					cedar_devp->debug_info_cur_index);
1104 			mutex_unlock(&cedar_devp->lock_debug_info);
1105 			return -EFAULT;
1106 		}
1107 
1108 		/* copy data of debug info */
1109 		debug_info = &cedar_devp->debug_info[cedar_devp->debug_info_cur_index];
1110 
1111 
1112 		/*VE_LOGD("COPY_DEBUG_INFO, index = %d, pid = %d, tid = %d, len = %d, data = %p\n", */
1113 		/*    cedar_devp->debug_info_cur_index, debug_info->head_info.pid, */
1114 		/*    debug_info->head_info.tid, debug_info->head_info.length, debug_info->data);*/
1115 
1116 
1117 		if (debug_info->data)
1118 			vfree(debug_info->data);
1119 
1120 		debug_info->data = vmalloc(debug_info->head_info.length);
1121 
1122 
1123 		/*VE_LOGD("vmalloc: data = %p, len = %d\n",*/
1124 		/*    debug_info->data, debug_info->head_info.length);*/
1125 
1126 
1127 		if (debug_info->data == NULL) {
1128 			mutex_unlock(&cedar_devp->lock_debug_info);
1129 			VE_LOGE("vmalloc for debug_info->data failed");
1130 			return -EFAULT;
1131 		}
1132 
1133 		if (copy_from_user(debug_info->data, (void __user *)(arg + sizeof(struct debug_head_info)),
1134 			debug_info->head_info.length)) {
1135 			mutex_unlock(&cedar_devp->lock_debug_info);
1136 			VE_LOGE("COPY_DEBUG_INFO copy_from_user fail\n");
1137 			return -EFAULT;
1138 		}
1139 
1140 		mutex_unlock(&cedar_devp->lock_debug_info);
1141 
1142 		break;
1143 	}
1144 	case IOCTL_PROC_INFO_STOP:
1145 	{
1146 		int i = 0;
1147 		struct debug_head_info head_info;
1148 
1149 		if (copy_from_user(&head_info, (void __user *)arg, sizeof(struct debug_head_info))) {
1150 			VE_LOGW("SET_DEBUG_INFO copy_from_user fail\n");
1151 			return -EFAULT;
1152 		}
1153 
1154 		/*VE_LOGD("STOP_DEBUG_INFO, pid = %d, tid = %d\n",*/
1155 		/*		head_info.pid, head_info.tid); */
1156 
1157 		mutex_lock(&cedar_devp->lock_debug_info);
1158 		for (i = 0; i < MAX_VE_DEBUG_INFO_NUM; i++) {
1159 			if (cedar_devp->debug_info[i].head_info.pid == head_info.pid
1160 				&& cedar_devp->debug_info[i].head_info.tid == head_info.tid)
1161 				break;
1162 		}
1163 
1164 		VE_LOGI("STOP_DEBUG_INFO, i = %d\n", i);
1165 		if (i >= MAX_VE_DEBUG_INFO_NUM) {
1166 			VE_LOGE("STOP_DEBUG_INFO: can not find the match pid[%d] and tid[%d]\n",
1167 				head_info.pid, head_info.tid);
1168 		} else {
1169 			if (cedar_devp->debug_info[i].data)
1170 				vfree(cedar_devp->debug_info[i].data);
1171 
1172 			cedar_devp->debug_info[i].data = NULL;
1173 			cedar_devp->debug_info[i].head_info.pid = 0;
1174 			cedar_devp->debug_info[i].head_info.tid = 0;
1175 			cedar_devp->debug_info[i].head_info.length = 0;
1176 		}
1177 
1178 		mutex_unlock(&cedar_devp->lock_debug_info);
1179 
1180 		break;
1181 	}
1182 	case IOCTL_ENGINE_REQ:
1183 #ifdef USE_CEDAR_ENGINE
1184 			if (copy_from_user(&task_ret, (void __user *)arg,
1185 				sizeof(struct __cedarv_task))) {
1186 				VE_LOGW("USE_CEDAR_ENGINE copy_from_user fail\n");
1187 				return -EFAULT;
1188 			}
1189 			spin_lock_irqsave(&cedar_devp->lock, flags);
1190 
1191 			if (!list_empty(&run_task_list) &&
1192 				(task_ret.block_mode == CEDAR_NONBLOCK_TASK)) {
1193 				spin_unlock_irqrestore(&cedar_devp->lock, flags);
1194 				return CEDAR_RUN_LIST_NONULL;
1195 			}
1196 			spin_unlock_irqrestore(&cedar_devp->lock, flags);
1197 
1198 			task_ptr = kmalloc(sizeof(struct cedarv_engine_task), GFP_KERNEL);
1199 			if (!task_ptr) {
1200 				VE_LOGW("get task_ptr error\n");
1201 				return PTR_ERR(task_ptr);
1202 			}
1203 			task_ptr->task_handle = current;
1204 			task_ptr->t.ID = task_ret.ID;
1205 			/*ms to jiffies*/
1206 			task_ptr->t.timeout = jiffies +
1207 				msecs_to_jiffies(1000*task_ret.timeout);
1208 			task_ptr->t.frametime = task_ret.frametime;
1209 			task_ptr->t.task_prio = task_ret.task_prio;
1210 			task_ptr->running = 0;
1211 			task_ptr->is_first_task = 0;
1212 			task_ptr->status = TASK_INIT;
1213 
1214 			cedardev_insert_task(task_ptr);
1215 
1216 			ret = enable_cedar_hw_clk();
1217 			if (ret < 0) {
1218 				VE_LOGW("IOCTL_ENGINE_REQ clk enable error!\n");
1219 				return -EFAULT;
1220 			}
1221 			return task_ptr->is_first_task;
1222 #else
1223 			if (down_interruptible(&cedar_devp->sem))
1224 				return -ERESTARTSYS;
1225 
1226 			if (cedar_devp->ref_count < 0) {
1227 				VE_LOGW("request ve ref count error!");
1228 				up(&cedar_devp->sem);
1229 				return -EFAULT;
1230 			}
1231 
1232 			cedar_devp->ref_count++;
1233 			if (cedar_devp->ref_count == 1) {
1234 				cedar_devp->last_min_freq = 0;
1235 				enable_cedar_hw_clk();
1236 			}
1237 			up(&cedar_devp->sem);
1238 			break;
1239 #endif
1240 		case IOCTL_ENGINE_REL:
1241 #ifdef USE_CEDAR_ENGINE
1242 			rel_taskid = (int)arg;
1243 
1244 			ret = cedardev_del_task(rel_taskid);
1245 #else
1246 			if (down_interruptible(&cedar_devp->sem))
1247 				return -ERESTARTSYS;
1248 			cedar_devp->ref_count--;
1249 
1250 			if (cedar_devp->ref_count < 0) {
1251 				VE_LOGW("relsese ve ref count error!");
1252 				up(&cedar_devp->sem);
1253 				return -EFAULT;
1254 			}
1255 
1256 			if (cedar_devp->ref_count == 0) {
1257 				ret = disable_cedar_hw_clk();
1258 				if (ret < 0) {
1259 					VE_LOGW("IOCTL_ENGINE_REL clk disable error!\n");
1260 					up(&cedar_devp->sem);
1261 					return -EFAULT;
1262 				}
1263 			}
1264 			up(&cedar_devp->sem);
1265 #endif
1266 			return ret;
1267 		case IOCTL_ENGINE_CHECK_DELAY:
1268 			{
1269 				struct cedarv_engine_task_info task_info;
1270 
1271 				if (copy_from_user(&task_info, (void __user *)arg,
1272 					sizeof(struct cedarv_engine_task_info))) {
1273 					VE_LOGW("%d copy_from_user fail\n",
1274 						IOCTL_ENGINE_CHECK_DELAY);
1275 					return -EFAULT;
1276 				}
1277 				task_info.total_time = cedardev_check_delay(task_info.task_prio);
1278 #ifdef CEDAR_DEBUG
1279 				printk("%s,%d,%d\n", __func__, __LINE__, task_info.total_time);
1280 #endif
1281 				task_info.frametime = 0;
1282 				spin_lock_irqsave(&cedar_devp->lock, flags);
1283 				if (!list_empty(&run_task_list)) {
1284 
1285 					struct cedarv_engine_task *task_entry;
1286 #ifdef CEDAR_DEBUG
1287 					printk("%s,%d\n", __func__, __LINE__);
1288 #endif
1289 					task_entry = list_entry(run_task_list.next, struct cedarv_engine_task, list);
1290 					if (task_entry->running == 1)
1291 						task_info.frametime = task_entry->t.frametime;
1292 #ifdef CEDAR_DEBUG
1293 					printk("%s,%d,%d\n", __func__, __LINE__, task_info.frametime);
1294 #endif
1295 				}
1296 				spin_unlock_irqrestore(&cedar_devp->lock, flags);
1297 
1298 				if (copy_to_user((void *)arg, &task_info, sizeof(struct cedarv_engine_task_info))) {
1299 					VE_LOGW("%d copy_to_user fail\n",
1300 						IOCTL_ENGINE_CHECK_DELAY);
1301 					return -EFAULT;
1302 				}
1303 			}
1304 			break;
1305 		case IOCTL_WAIT_VE_DE:
1306 			ve_timeout = (int)arg;
1307 			cedar_devp->de_irq_value = 0;
1308 
1309 			spin_lock_irqsave(&cedar_devp->lock, flags);
1310 			if (cedar_devp->de_irq_flag)
1311 				cedar_devp->de_irq_value = 1;
1312 			spin_unlock_irqrestore(&cedar_devp->lock, flags);
1313 			wait_event_timeout(wait_ve, cedar_devp->de_irq_flag, ve_timeout*HZ);
1314 			cedar_devp->de_irq_flag = 0;
1315 
1316 			return cedar_devp->de_irq_value;
1317 
1318 		case IOCTL_WAIT_VE_EN:
1319 
1320 			ve_timeout = (int)arg;
1321 			cedar_devp->en_irq_value = 0;
1322 
1323 			spin_lock_irqsave(&cedar_devp->lock, flags);
1324 			if (cedar_devp->en_irq_flag)
1325 				cedar_devp->en_irq_value = 1;
1326 			spin_unlock_irqrestore(&cedar_devp->lock, flags);
1327 
1328 			wait_event_timeout(wait_ve, cedar_devp->en_irq_flag, ve_timeout*HZ);
1329 			cedar_devp->en_irq_flag = 0;
1330 
1331 			return cedar_devp->en_irq_value;
1332 
1333 #if ((defined CONFIG_ARCH_SUN8IW8P1) || (defined CONFIG_ARCH_SUN50I) || \
1334 	(defined CONFIG_ARCH_SUN8IW12P1) || (defined CONFIG_ARCH_SUN8IW17P1) \
1335 	|| (defined CONFIG_ARCH_SUN8IW16P1) || (defined CONFIG_ARCH_SUN8IW19P1))
1336 
1337 		case IOCTL_WAIT_JPEG_DEC:
1338 			ve_timeout = (int)arg;
1339 			cedar_devp->jpeg_irq_value = 0;
1340 
1341 			spin_lock_irqsave(&cedar_devp->lock, flags);
1342 			if (cedar_devp->jpeg_irq_flag)
1343 				cedar_devp->jpeg_irq_value = 1;
1344 			spin_unlock_irqrestore(&cedar_devp->lock, flags);
1345 
1346 			wait_event_timeout(wait_ve, cedar_devp->jpeg_irq_flag, ve_timeout*HZ);
1347 			cedar_devp->jpeg_irq_flag = 0;
1348 			return cedar_devp->jpeg_irq_value;
1349 #endif
1350 		case IOCTL_ENABLE_VE:
1351 			if (clk_prepare_enable(cedar_devp->ve_clk)) {
1352 				VE_LOGW("IOCTL_ENABLE_VE enable cedar_devp->ve_clk failed!\n");
1353 			}
1354 			break;
1355 
1356 		case IOCTL_DISABLE_VE:
1357 			if ((cedar_devp->ve_clk == NULL) || IS_ERR(cedar_devp->ve_clk)) {
1358 				VE_LOGW("IOCTL_DISABLE_VE cedar_devp->ve_clk is invalid\n");
1359 				return -EFAULT;
1360 			} else {
1361 				clk_disable_unprepare(cedar_devp->ve_clk);
1362 			}
1363 			break;
1364 
1365 		case IOCTL_RESET_VE:
1366 			reset_control_reset(cedar_devp->reset);
1367 			break;
1368 
1369 		case IOCTL_SET_DRAM_HIGH_CHANNAL:
1370 		{
1371 			/*
1372 			int flag = (int)arg;
1373 
1374 			if (flag == 1)
1375 			    mbus_port_setpri(26, 1);
1376 			else
1377 			    mbus_port_setpri(26, 0);
1378 			*/
1379 			VE_LOGW("this kernel version not supproti!\n");
1380 			break;
1381 		}
1382 
1383 		case IOCTL_SET_VE_FREQ:
1384 			{
1385 				int arg_rate = (int)arg;
1386 				//note now we not support set parent clk
1387 				if (arg_rate >= VE_CLK_LOW_WATER && arg_rate <= VE_CLK_HIGH_WATER) {
1388 					if (clk_set_rate(cedar_devp->ve_clk, arg_rate*1000000)) {
1389 						VE_LOGW("set clock failed\n");
1390 					}
1391 				}
1392 				ret = clk_get_rate(cedar_devp->ve_clk);
1393 				VE_LOGW("VE real_freq=%ld\n", ret);
1394 				break;
1395 			}
1396 		case IOCTL_GETVALUE_AVS2:
1397 		case IOCTL_ADJUST_AVS2:
1398 		case IOCTL_ADJUST_AVS2_ABS:
1399 		case IOCTL_CONFIG_AVS2:
1400 		case IOCTL_RESET_AVS2:
1401 		case IOCTL_PAUSE_AVS2:
1402 		case IOCTL_START_AVS2:
1403 			VE_LOGW("do not supprot this ioctrl now\n");
1404 			break;
1405 
1406 		case IOCTL_GET_ENV_INFO:
1407 			{
1408 				struct cedarv_env_infomation_compat env_info;
1409 
1410 				env_info.phymem_start = 0;
1411 				env_info.phymem_total_size = 0;
1412 				env_info.address_macc = 0;
1413 				if (copy_to_user((char *)arg, &env_info,
1414 					sizeof(struct cedarv_env_infomation_compat)))
1415 					return -EFAULT;
1416 			}
1417 			break;
1418 		case IOCTL_GET_IC_VER:
1419 			{
1420 				return 0;
1421 			}
1422 		case IOCTL_SET_REFCOUNT:
1423 			cedar_devp->ref_count = (int)arg;
1424 			break;
1425 		case IOCTL_SET_VOL:
1426 			{
1427 
1428 #if defined CONFIG_ARCH_SUN9IW1P1
1429 				int ret;
1430 				int vol = (int)arg;
1431 
1432 				if (down_interruptible(&cedar_devp->sem)) {
1433 					return -ERESTARTSYS;
1434 				}
1435 				info->set_vol_flag = 1;
1436 
1437 				/*set output voltage to arg mV*/
1438 				ret = regulator_set_voltage(regu, vol*1000, 3300000);
1439 				if (IS_ERR(regu)) {
1440 					VE_LOGW(\
1441 						"fail to set axp15_dcdc4 regulator voltage!\n");
1442 				}
1443 				up(&cedar_devp->sem);
1444 #endif
1445 				break;
1446 			}
1447 			case IOCTL_GET_LOCK: {
1448 				int lock_ctl_ret = 0;
1449 				u32 lock_type = arg;
1450 				struct ve_info *vi = filp->private_data;
1451 
1452 				if (lock_type == VE_LOCK_VDEC)
1453 					mutex_lock(&cedar_devp->lock_vdec);
1454 				else if (lock_type == VE_LOCK_VENC)
1455 					mutex_lock(&cedar_devp->lock_venc);
1456 				else if (lock_type == VE_LOCK_JDEC)
1457 					mutex_lock(&cedar_devp->lock_jdec);
1458 				else if (lock_type == VE_LOCK_00_REG)
1459 					mutex_lock(&cedar_devp->lock_00_reg);
1460 				else if (lock_type == VE_LOCK_04_REG)
1461 					mutex_lock(&cedar_devp->lock_04_reg);
1462 				else
1463 					VE_LOGE("invalid lock type '%d'", lock_type);
1464 
1465 				if ((vi->lock_flags&lock_type) != 0)
1466 						VE_LOGE("when get lock, this should be 0!!!");
1467 
1468 				mutex_lock(&vi->lock_flag_io);
1469 				vi->lock_flags |= lock_type;
1470 				mutex_unlock(&vi->lock_flag_io);
1471 
1472 				return lock_ctl_ret;
1473 			}
1474 			case IOCTL_SET_PROC_INFO:
1475 			{
1476 				struct VE_PROC_INFO ve_info;
1477 				unsigned char channel_id = 0;
1478 				u32 lock_type = VE_LOCK_PROC_INFO;
1479 				struct ve_info *vi = filp->private_data;
1480 
1481 				if (cedar_devp->debug_root == NULL)
1482 					return 0;
1483 
1484 				mutex_lock(&ve_debug_proc_info.lock_proc);
1485 				if (copy_from_user(&ve_info, (void __user *)arg, sizeof(struct VE_PROC_INFO))) {
1486 					VE_LOGW("IOCTL_SET_PROC_INFO copy_from_user fail\n");
1487 					mutex_unlock(&ve_debug_proc_info.lock_proc);
1488 					return -EFAULT;
1489 				}
1490 
1491 				channel_id = ve_info.channel_id;
1492 				if (channel_id >= VE_DEBUGFS_MAX_CHANNEL) {
1493 					VE_LOGW("set channel[%c] is bigger than max channel[%d]\n",
1494 											channel_id, VE_DEBUGFS_MAX_CHANNEL);
1495 					mutex_unlock(&ve_debug_proc_info.lock_proc);
1496 					return -EFAULT;
1497 				}
1498 
1499 				mutex_lock(&vi->lock_flag_io);
1500 				vi->lock_flags |= lock_type;
1501 				mutex_unlock(&vi->lock_flag_io);
1502 
1503 				ve_debug_proc_info.cur_channel_id = ve_info.channel_id;
1504 				ve_debug_proc_info.proc_len[channel_id] = ve_info.proc_info_len;
1505 				ve_debug_proc_info.proc_buf[channel_id] = ve_debug_proc_info.data +
1506 													channel_id * VE_DEBUGFS_BUF_SIZE;
1507 				break;
1508 			}
1509 			case IOCTL_COPY_PROC_INFO:
1510 			{
1511 				unsigned char channel_id;
1512 				u32 lock_type = VE_LOCK_PROC_INFO;
1513 				struct ve_info *vi = filp->private_data;
1514 
1515 				if (cedar_devp->debug_root == NULL)
1516 					return 0;
1517 
1518 				mutex_lock(&vi->lock_flag_io);
1519 				vi->lock_flags &= (~lock_type);
1520 				mutex_unlock(&vi->lock_flag_io);
1521 
1522 				channel_id = ve_debug_proc_info.cur_channel_id;
1523 				if (copy_from_user(ve_debug_proc_info.proc_buf[channel_id],
1524 								  (void __user *)arg,
1525 								ve_debug_proc_info.proc_len[channel_id])) {
1526 					VE_LOGW("IOCTL_COPY_PROC_INFO copy_from_user fail\n");
1527 							mutex_unlock(&ve_debug_proc_info.lock_proc);
1528 					return -EFAULT;
1529 				}
1530 
1531 				mutex_unlock(&ve_debug_proc_info.lock_proc);
1532 				break;
1533 			}
1534 			case IOCTL_STOP_PROC_INFO:
1535 			{
1536 				unsigned char channel_id;
1537 
1538 				if (cedar_devp->debug_root == NULL)
1539 					return 0;
1540 
1541 				channel_id = arg;
1542 				ve_debug_proc_info.proc_buf[channel_id] = NULL;
1543 
1544 				break;
1545 			}
1546 			case IOCTL_RELEASE_LOCK: {
1547 				int lock_ctl_ret = 0;
1548 
1549 				do {
1550 						u32 lock_type = arg;
1551 						struct ve_info *vi = filp->private_data;
1552 
1553 						if (!(vi->lock_flags & lock_type)) {
1554 								VE_LOGE("Not lock? flags: '%x/%x'.", vi->lock_flags,
1555 								lock_type);
1556 								lock_ctl_ret = -1;
1557 								break; /* break 'do...while' */
1558 						}
1559 
1560 						mutex_lock(&vi->lock_flag_io);
1561 						vi->lock_flags &= (~lock_type);
1562 						mutex_unlock(&vi->lock_flag_io);
1563 
1564 						if (lock_type == VE_LOCK_VDEC)
1565 							mutex_unlock(&cedar_devp->lock_vdec);
1566 						else if (lock_type == VE_LOCK_VENC)
1567 							mutex_unlock(&cedar_devp->lock_venc);
1568 						else if (lock_type == VE_LOCK_JDEC)
1569 							mutex_unlock(&cedar_devp->lock_jdec);
1570 						else if (lock_type == VE_LOCK_00_REG)
1571 							mutex_unlock(&cedar_devp->lock_00_reg);
1572 						else if (lock_type == VE_LOCK_04_REG)
1573 							mutex_unlock(&cedar_devp->lock_04_reg);
1574 						else
1575 							VE_LOGE("invalid lock type '%d'", lock_type);
1576 				} while (0);
1577 				return lock_ctl_ret;
1578 		}
1579 		case IOCTL_GET_IOMMU_ADDR:
1580 		{
1581 			/* just for compatible, kernel 5.4 should not use it*/
1582 			struct user_iommu_param parm;
1583 			cedar_devp->bMemDevAttachFlag = 1;
1584 
1585 			if (copy_from_user(&parm, (void __user *)arg,
1586 				sizeof(struct user_iommu_param))) {
1587 				VE_LOGE("IOCTL_GET_IOMMU_ADDR copy_from_user error");
1588 				return -EFAULT;
1589 			}
1590 			if (map_dma_buf_addr(parm.fd, &parm.iommu_addr, filp) != 0) {
1591 				VE_LOGE("IOCTL_GET_IOMMU_ADDR map dma buf fail");
1592 				return -EFAULT;
1593 			}
1594 
1595 			if (copy_to_user((void __user *)arg, &parm,
1596 				sizeof(struct user_iommu_param))) {
1597 				VE_LOGE("ve get iommu copy_to_user error\n");
1598 				return -EFAULT;
1599 			}
1600 			break;
1601 		}
1602 		case IOCTL_FREE_IOMMU_ADDR:
1603 		{
1604 			/* just for compatible, kernel 5.4 should not use it*/
1605 			struct user_iommu_param parm;
1606 
1607 			if (copy_from_user(&parm, (void __user *)arg,
1608 				sizeof(struct user_iommu_param))) {
1609 				VE_LOGE("IOCTL_FREE_IOMMU_ADDR copy_from_user error");
1610 				return -EFAULT;
1611 			}
1612 
1613 			unmap_dma_buf_addr(0, parm.fd, filp);
1614 			break;
1615 		}
1616 		case IOCTL_MAP_DMA_BUF:
1617 		{
1618 			struct dma_buf_param parm;
1619 			cedar_devp->bMemDevAttachFlag = 1;
1620 
1621 			if (copy_from_user(&parm, (void __user *)arg, sizeof(struct dma_buf_param))) {
1622 				VE_LOGE("IOCTL_GET_IOMMU_ADDR copy_from_user error");
1623 				return -EFAULT;
1624 			}
1625 			if (map_dma_buf_addr(parm.fd, &parm.phy_addr, filp) != 0) {
1626 				VE_LOGE("IOCTL_GET_IOMMU_ADDR map dma buf fail");
1627 				return -EFAULT;
1628 			}
1629 			if (copy_to_user((void __user *)arg, &parm, sizeof(struct dma_buf_param))) {
1630 				VE_LOGE("ve get iommu copy_to_user error\n");
1631 				return -EFAULT;
1632 			}
1633 			break;
1634 		}
1635 		case IOCTL_UNMAP_DMA_BUF:
1636 		{
1637 			struct dma_buf_param parm;
1638 
1639 			if (copy_from_user(&parm, (void __user *)arg, sizeof(struct dma_buf_param))) {
1640 				VE_LOGE("IOCTL_FREE_IOMMU_ADDR copy_from_user error");
1641 				return -EFAULT;
1642 			}
1643 
1644 			unmap_dma_buf_addr(0, parm.fd, filp);
1645 			break;
1646 		}
1647 		case IOCTL_FLUSH_CACHE_RANGE:
1648 		{
1649 #if IS_ENABLED(CONFIG_ARM64) || IS_ENABLED(CONFIG_64BIT)
1650 			struct cache_range data;
1651 #else
1652 			struct cache_range data;
1653 			u32 addr_start = 0;
1654 			u32 addr_end = 0;
1655 #endif
1656 
1657 			if (copy_from_user(&data, (void __user *)arg, sizeof(struct cache_range)))
1658 				return -EFAULT;
1659 
1660 #if IS_ENABLED(CONFIG_ARM64) || IS_ENABLED(CONFIG_64BIT)
1661 
1662 			if (IS_ERR_OR_NULL((void *)data.start) || IS_ERR_OR_NULL((void *)data.end)) {
1663 				VE_LOGE("flush 0x%x, end 0x%x fault user virt address!\n",
1664 					   (u32)data.start, (u32)data.end);
1665 				return -EFAULT;
1666 			}
1667 #else
1668 			addr_start = (u32)(data.start & 0xffffffff);
1669 			addr_end = (u32)(data.end & 0xffffffff);
1670 
1671 			if (IS_ERR_OR_NULL((void *)addr_start) || IS_ERR_OR_NULL((void *)addr_end)) {
1672 				VE_LOGE("flush 0x%x, end 0x%x fault user virt address!\n",
1673 					(u32)data.start, (u32)data.end);
1674 				return -EFAULT;
1675 			}
1676 #endif
1677 
1678 				//VE_LOGI("ion flush_range start:%lx end:%lx size:%lx\n",
1679 					//data.start, data.end, data.end - data.start);
1680 #if IS_ENABLED(CONFIG_ARM64)
1681 				//VE_LOGE("flush 0x%x, end 0x%x fault user virt address!\n",
1682 					//(u32)data.start, (u32)data.end);
1683 				cedar_dma_flush_range((void *)data.start, data.end - data.start);
1684 				//dma_sync_single_for_cpu(cedar_devp->plat_dev,(u32)data.start,data.end - data.start,DMA_BIDIRECTIONAL);
1685 #else
1686 #if IS_ENABLED(CONFIG_64BIT) && IS_ENABLED(CONFIG_RISCV)
1687 			dma_usr_va_wb_range((void *)data.start, (unsigned long)(data.end - data.start));
1688 #else
1689 			dmac_flush_range((void *)addr_start, (void *)addr_end);
1690 #endif
1691 #endif
1692 			if (copy_to_user((void __user *)arg, &data, sizeof(data)))
1693 				return -EFAULT;
1694 			break;
1695 		}
1696 		case IOCTL_POWER_SETUP:
1697 		{
1698 #if VE_POWER_MANAGE_VALID
1699 			if (cedar_devp->power_manage_request_ref == 0) {
1700 				/* ensure ve is not work, or will cause error */
1701 				mutex_lock(&cedar_devp->lock_vdec);
1702 				mutex_lock(&cedar_devp->lock_venc);
1703 				mutex_lock(&cedar_devp->lock_jdec);
1704 				mutex_lock(&cedar_devp->lock_00_reg);
1705 				mutex_lock(&cedar_devp->lock_04_reg);
1706 
1707 				ve_power_manage_setup();
1708 
1709 				mutex_unlock(&cedar_devp->lock_vdec);
1710 				mutex_unlock(&cedar_devp->lock_venc);
1711 				mutex_unlock(&cedar_devp->lock_jdec);
1712 				mutex_unlock(&cedar_devp->lock_00_reg);
1713 				mutex_unlock(&cedar_devp->lock_04_reg);
1714 			}
1715 
1716 			cedar_devp->power_manage_request_ref++;
1717 #endif
1718 			break;
1719 		}
1720 		case IOCTL_POWER_SHUTDOWN:
1721 		{
1722 #if VE_POWER_MANAGE_VALID
1723 			cedar_devp->power_manage_request_ref--;
1724 
1725 			if (cedar_devp->power_manage_request_ref == 0) {
1726 				/* ensure ve is not work, or will cause error */
1727 				mutex_lock(&cedar_devp->lock_vdec);
1728 				mutex_lock(&cedar_devp->lock_venc);
1729 				mutex_lock(&cedar_devp->lock_jdec);
1730 				mutex_lock(&cedar_devp->lock_00_reg);
1731 				mutex_lock(&cedar_devp->lock_04_reg);
1732 
1733 				ve_power_manage_shutdown();
1734 
1735 				mutex_unlock(&cedar_devp->lock_vdec);
1736 				mutex_unlock(&cedar_devp->lock_venc);
1737 				mutex_unlock(&cedar_devp->lock_jdec);
1738 				mutex_unlock(&cedar_devp->lock_00_reg);
1739 				mutex_unlock(&cedar_devp->lock_04_reg);
1740 			}
1741 #endif
1742 			break;
1743 		}
1744 		default:
1745 			VE_LOGW("not support the ioctl cmd = 0x%x", cmd);
1746 			return -1;
1747 	}
1748 	return ret;
1749 }
1750 
1751 
1752 
cedardev_open(struct inode * inode,struct file * filp)1753 static int cedardev_open(struct inode *inode, struct file *filp)
1754 {
1755 	struct ve_info *info;
1756 
1757 	info = kmalloc(sizeof(struct ve_info), GFP_KERNEL);
1758 	if (!info)
1759 		return -ENOMEM;
1760 
1761 	info->set_vol_flag = 0;
1762 
1763 	filp->private_data = info;
1764 	if (down_interruptible(&cedar_devp->sem)) {
1765 		return -ERESTARTSYS;
1766 	}
1767 
1768 	/* init other resource here */
1769 	if (cedar_devp->ref_count == 0) {
1770 		cedar_devp->de_irq_flag = 0;
1771 		cedar_devp->en_irq_flag = 0;
1772 		cedar_devp->jpeg_irq_flag = 0;
1773 	}
1774 
1775 	up(&cedar_devp->sem);
1776 	nonseekable_open(inode, filp);
1777 
1778 	mutex_init(&info->lock_flag_io);
1779 	info->lock_flags = 0;
1780 
1781 	return 0;
1782 }
1783 
cedardev_release(struct inode * inode,struct file * filp)1784 static int cedardev_release(struct inode *inode, struct file *filp)
1785 {
1786 	struct ve_info *info;
1787 
1788 	info = filp->private_data;
1789 	mutex_lock(&info->lock_flag_io);
1790 	//if the process abort, this will free iommu_buffer
1791 	unmap_dma_buf_addr(1, 0, filp);
1792 
1793 	/* lock status */
1794 	if (info->lock_flags) {
1795 			VE_LOGW("release lost-lock...");
1796 			if (info->lock_flags & VE_LOCK_VDEC)
1797 				mutex_unlock(&cedar_devp->lock_vdec);
1798 
1799 			if (info->lock_flags & VE_LOCK_VENC)
1800 				mutex_unlock(&cedar_devp->lock_venc);
1801 
1802 			if (info->lock_flags & VE_LOCK_JDEC)
1803 				mutex_unlock(&cedar_devp->lock_jdec);
1804 
1805 			if (info->lock_flags & VE_LOCK_00_REG)
1806 				mutex_unlock(&cedar_devp->lock_00_reg);
1807 
1808 			if (info->lock_flags & VE_LOCK_04_REG)
1809 				mutex_unlock(&cedar_devp->lock_04_reg);
1810 
1811 			if (info->lock_flags & VE_LOCK_PROC_INFO)
1812 				mutex_unlock(&ve_debug_proc_info.lock_proc);
1813 
1814 			info->lock_flags = 0;
1815 		}
1816 
1817 	mutex_unlock(&info->lock_flag_io);
1818 	mutex_destroy(&info->lock_flag_io);
1819 
1820 	if (down_interruptible(&cedar_devp->sem)) {
1821 		return -ERESTARTSYS;
1822 	}
1823 
1824 #if defined CONFIG_ARCH_SUN9IW1P1
1825 
1826 	if (info->set_vol_flag == 1) {
1827 		regulator_set_voltage(regu, 900000, 3300000);
1828 		if (IS_ERR(regu)) {
1829 			VE_LOGW(\
1830 				"some error happen, fail to set axp15_dcdc4 regulator voltage!\n");
1831 			return -EINVAL;
1832 		}
1833 	}
1834 #endif
1835 
1836 	/* release other resource here */
1837 	if (cedar_devp->ref_count == 0) {
1838 		cedar_devp->de_irq_flag = 1;
1839 		cedar_devp->en_irq_flag = 1;
1840 		cedar_devp->jpeg_irq_flag = 1;
1841 	}
1842 	up(&cedar_devp->sem);
1843 
1844 	kfree(info);
1845 	return 0;
1846 }
1847 
cedardev_vma_open(struct vm_area_struct * vma)1848 static void cedardev_vma_open(struct vm_area_struct *vma)
1849 {
1850 }
1851 
cedardev_vma_close(struct vm_area_struct * vma)1852 static void cedardev_vma_close(struct vm_area_struct *vma)
1853 {
1854 }
1855 
1856 static struct vm_operations_struct cedardev_remap_vm_ops = {
1857 	.open  = cedardev_vma_open,
1858 	.close = cedardev_vma_close,
1859 };
1860 
cedardev_mmap(struct file * filp,struct vm_area_struct * vma)1861 static int cedardev_mmap(struct file *filp, struct vm_area_struct *vma)
1862 {
1863 	unsigned long temp_pfn;
1864 
1865 	if (vma->vm_end - vma->vm_start == 0) {
1866 		VE_LOGW("vma->vm_end is equal vma->vm_start : %lx\n",\
1867 			vma->vm_start);
1868 		return 0;
1869 	}
1870 	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) {
1871 		VE_LOGW(\
1872 			"the vma->vm_pgoff is %lx,it is large than the largest page number\n", vma->vm_pgoff);
1873 		return -EINVAL;
1874 	}
1875 
1876 
1877 	temp_pfn = MACC_REGS_BASE >> 12;
1878 
1879 
1880 	/* Set reserved and I/O flag for the area. */
1881 	vma->vm_flags |= /*VM_RESERVED | */VM_IO;
1882 	/* Select uncached access. */
1883 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
1884 
1885 	if (io_remap_pfn_range(vma, vma->vm_start, temp_pfn,
1886 				vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
1887 		return -EAGAIN;
1888 	}
1889 
1890 
1891 	vma->vm_ops = &cedardev_remap_vm_ops;
1892 	cedardev_vma_open(vma);
1893 
1894 	return 0;
1895 }
1896 
sunxi_cedar_suspend(struct device * dev)1897 static int sunxi_cedar_suspend(struct device *dev)
1898 {
1899 	int ret = 0;
1900 
1901 #if defined CONFIG_ARCH_SUN8IW20
1902 	VE_LOGD("[cedar] standby suspend");
1903 	pm_runtime_put_sync(dev);
1904 #endif
1905 	ret = disable_cedar_hw_clk();
1906 
1907 #if defined CONFIG_ARCH_SUN9IW1P1
1908 	clk_disable_unprepare(cedar_devp->power_clk);
1909 #endif
1910 
1911 	if (ret < 0) {
1912 		VE_LOGW("cedar clk disable somewhere error!\n");
1913 		return -EFAULT;
1914 	}
1915 
1916 	return 0;
1917 }
1918 
sunxi_cedar_resume(struct device * dev)1919 static int sunxi_cedar_resume(struct device *dev)
1920 {
1921 	int ret = 0;
1922 
1923 #if defined CONFIG_ARCH_SUN8IW20
1924 	VE_LOGD("[cedar] standby resume");
1925 	pm_runtime_get_sync(dev);
1926 #endif
1927 
1928 #if defined CONFIG_ARCH_SUN9IW1P1
1929 	clk_prepare_enable(cedar_devp->power_clk);
1930 #endif
1931 
1932 	if (cedar_devp->ref_count == 0) {
1933 		return 0;
1934 	}
1935 
1936 	ret = enable_cedar_hw_clk();
1937 	if (ret < 0) {
1938 		VE_LOGW("cedar clk enable somewhere error!\n");
1939 		return -EFAULT;
1940 	}
1941 	return 0;
1942 }
1943 
1944 
1945 static SIMPLE_DEV_PM_OPS(sunxi_cedar_pm_ops, sunxi_cedar_suspend, sunxi_cedar_resume);
1946 
1947 
1948 #if IS_ENABLED(CONFIG_DEBUG_FS)
ve_debugfs_open(struct inode * inode,struct file * file)1949 static int ve_debugfs_open(struct inode *inode, struct file *file)
1950 {
1951 	int i = 0;
1952 	char *pData;
1953 	struct ve_debugfs_proc *pVeProc;
1954 
1955 	pVeProc = kmalloc(sizeof(struct ve_debugfs_proc), GFP_KERNEL);
1956 	if (pVeProc == NULL) {
1957 		VE_LOGE("kmalloc pVeProc fail\n");
1958 		return -ENOMEM;
1959 	}
1960 	pVeProc->len = 0;
1961 	memset(pVeProc->data, 0, VE_DEBUGFS_BUF_SIZE * VE_DEBUGFS_MAX_CHANNEL);
1962 
1963 	pData = pVeProc->data;
1964 	mutex_lock(&ve_debug_proc_info.lock_proc);
1965 	for (i = 0; i < VE_DEBUGFS_MAX_CHANNEL; i++) {
1966 		if (ve_debug_proc_info.proc_buf[i] != NULL) {
1967 			memcpy(pData, ve_debug_proc_info.proc_buf[i], ve_debug_proc_info.proc_len[i]);
1968 			pData += ve_debug_proc_info.proc_len[i];
1969 			pVeProc->len += ve_debug_proc_info.proc_len[i];
1970 		}
1971 	}
1972     mutex_unlock(&ve_debug_proc_info.lock_proc);
1973 
1974 	file->private_data = pVeProc;
1975 	return 0;
1976 }
1977 
ve_debugfs_read(struct file * file,char __user * user_buf,size_t nbytes,loff_t * ppos)1978 static ssize_t ve_debugfs_read(struct file *file, char __user *user_buf,
1979 					  size_t nbytes, loff_t *ppos)
1980 {
1981 	struct ve_debugfs_proc *pVeProc = file->private_data;
1982 
1983 	if (pVeProc->len == 0) {
1984 	    VE_LOGD("there is no any codec working currently\n");
1985 	return 0;
1986     }
1987 
1988 	return simple_read_from_buffer(user_buf, nbytes, ppos, pVeProc->data,
1989 					   pVeProc->len);
1990 }
1991 
ve_debugfs_release(struct inode * inode,struct file * file)1992 static int ve_debugfs_release(struct inode *inode, struct file *file)
1993 {
1994 	struct ve_debugfs_proc *pVeProc = file->private_data;
1995 
1996 	kfree(pVeProc);
1997 	pVeProc = NULL;
1998 	file->private_data = NULL;
1999 
2000 	return 0;
2001 }
2002 
2003 static const struct file_operations ve_debugfs_fops = {
2004 	.owner = THIS_MODULE,
2005 	.open = ve_debugfs_open,
2006 	.llseek = no_llseek,
2007 	.read = ve_debugfs_read,
2008 	.release = ve_debugfs_release,
2009 };
2010 
sunxi_ve_debug_register_driver(void)2011 int sunxi_ve_debug_register_driver(void)
2012 {
2013 	struct dentry *dent;
2014 
2015 	//debugfs_mpp_root defined out of this module
2016 #if IS_ENABLED(CONFIG_SUNXI_MPP)
2017 	cedar_devp->debug_root = debugfs_mpp_root;
2018 #else
2019 	cedar_devp->debug_root = debugfs_create_dir("enc_test", NULL);
2020 #endif
2021 
2022 	if (IS_ERR_OR_NULL(cedar_devp->debug_root)) {
2023 		VE_LOGE("debugfs root is null please check!");
2024 		return -ENOENT;
2025 	}
2026 	dent = debugfs_create_file("ve", 0444, cedar_devp->debug_root,
2027 				   NULL, &ve_debugfs_fops);
2028 	if (IS_ERR_OR_NULL(dent)) {
2029 		VE_LOGE("Unable to create debugfs status file.\n");
2030 		debugfs_remove_recursive(cedar_devp->debug_root);
2031 		cedar_devp->debug_root = NULL;
2032 		return -ENODEV;
2033 	}
2034 
2035 	return 0;
2036 }
2037 
sunxi_ve_debug_unregister_driver(void)2038 void sunxi_ve_debug_unregister_driver(void)
2039 {
2040 	if (cedar_devp->debug_root == NULL) {
2041 		VE_LOGW("note: debug root already is null");
2042 		return;
2043 	}
2044 	debugfs_remove_recursive(cedar_devp->debug_root);
2045 	cedar_devp->debug_root = NULL;
2046 }
2047 #endif
2048 
2049 #if (defined CONFIG_ARCH_SUNIVW1P1 || defined CONFIG_ARCH_SUN3IW1P1)
set_ccmu_by_self(void)2050 static void set_ccmu_by_self(void)
2051 {
2052 	unsigned int val;
2053 
2054 	if (cedar_devp->iomap_addrs.regs_ccmu == NULL) {
2055 		VE_LOGW("ccmu regs addr is null");
2056 		return;
2057 	}
2058 	val = readl(cedar_devp->iomap_addrs.regs_ccmu+6);
2059 	val &= 0x7fff80f0;
2060 #if (defined CONFIG_ARCH_SUNIVW1P1) /* for 1663*/
2061 	val = val | (1<<31) | (8<<8);
2062 #elif (defined CONFIG_ARCH_SUN3IW1P1)
2063 	val = val | (1<<31) | (49<<8) | (3<<0);
2064 #endif
2065 	writel(val, cedar_devp->iomap_addrs.regs_ccmu+6);
2066 
2067 	/*set VE clock dividor*/
2068 	val = readl(cedar_devp->iomap_addrs.regs_ccmu+79);
2069 	val |= (1<<31);
2070 	writel(val, cedar_devp->iomap_addrs.regs_ccmu+79);
2071 
2072 	/*Active AHB bus to MACC*/
2073 	val = readl(cedar_devp->iomap_addrs.regs_ccmu+25);
2074 	val |= (1<<0);
2075 	writel(val, cedar_devp->iomap_addrs.regs_ccmu+25);
2076 
2077 	/*Power on and release reset ve*/
2078 	val = readl(cedar_devp->iomap_addrs.regs_ccmu+177);
2079 	val &= ~(1<<0); /*reset ve*/
2080 	writel(val, cedar_devp->iomap_addrs.regs_ccmu+177);
2081 
2082 	val = readl(cedar_devp->iomap_addrs.regs_ccmu+177);
2083 	val |= (1<<0);
2084 	writel(val, cedar_devp->iomap_addrs.regs_ccmu+177);
2085 
2086 	/*gate on the bus to SDRAM*/
2087 	val = readl(cedar_devp->iomap_addrs.regs_ccmu+64);
2088 	val |= (1<<0);
2089 	writel(val, cedar_devp->iomap_addrs.regs_ccmu+64);
2090 }
2091 #endif
2092 
set_sys_cfg_by_self(void)2093 static void set_sys_cfg_by_self(void)
2094 {
2095 	unsigned int val;
2096 	if (cedar_devp->iomap_addrs.regs_sys_cfg == NULL) {
2097 	VE_LOGW("sys config regs addr is null");
2098 		return;
2099 	}
2100 	// remapping SRAM to MACC for codec test
2101 	val = readl(cedar_devp->iomap_addrs.regs_sys_cfg);
2102 	val &= 0xfffffffe;
2103 	writel(val, cedar_devp->iomap_addrs.regs_sys_cfg);
2104 	//clear bootmode bit for give sram to ve
2105 	val = readl((cedar_devp->iomap_addrs.regs_sys_cfg + 0x4));
2106 	val &= 0xfeffffff;
2107 	writel(val, (cedar_devp->iomap_addrs.regs_sys_cfg + 0x4));
2108 }
2109 
set_system_register(void)2110 static void set_system_register(void)
2111 {
2112 	//modify ccmu and sys_config register config
2113 #if (defined CONFIG_ARCH_SUNIVW1P1 || defined CONFIG_ARCH_SUN3IW1P1)
2114 	set_ccmu_by_self();
2115 #endif
2116 	set_sys_cfg_by_self();
2117 }
2118 
deal_with_resouce(struct platform_device * pdev)2119 static int deal_with_resouce(struct platform_device *pdev)
2120 {
2121 	int ret = 0;
2122 	struct device_node *node = pdev->dev.of_node;
2123 
2124 	/*4.register irq function*/
2125 	cedar_devp->irq = irq_of_parse_and_map(node, 0);
2126 	VE_LOGI("cedar-ve the get irq is %d\n", cedar_devp->irq);
2127 
2128 	ret = request_irq(cedar_devp->irq, VideoEngineInterupt, 0, "cedar_dev", NULL);
2129 	if (ret < 0) {
2130 		VE_LOGW("request irq err\n");
2131 		return -1;
2132 	}
2133 
2134 	memset(&cedar_devp->iomap_addrs, 0, sizeof(struct iomap_para));
2135 	// map for macc io space
2136 	cedar_devp->iomap_addrs.regs_ve = of_iomap(node, 0);
2137 	if (!cedar_devp->iomap_addrs.regs_ve) {
2138 		VE_LOGW("ve Can't map registers");
2139 		return -1;
2140 	}
2141 
2142 	//map for sys_config io space
2143 	cedar_devp->iomap_addrs.regs_sys_cfg = (char *)of_iomap(node, 1);
2144 	if (!cedar_devp->iomap_addrs.regs_sys_cfg) {
2145 		VE_LOGW("ve Can't map regs_sys_cfg registers, maybe no use");
2146 	}
2147 
2148 	//map for ccmu io space
2149 	cedar_devp->iomap_addrs.regs_ccmu = (unsigned int *)of_iomap(node, 2);
2150 	if (!cedar_devp->iomap_addrs.regs_ccmu) {
2151 		VE_LOGW("ve Can't map regs_ccmu registers, maybe no use");
2152 	}
2153 #if VE_POWER_MANAGE_VALID
2154 	cedar_devp->iomap_addrs.prcm_bass_vir = (unsigned int *)of_iomap(node, 3);
2155 	if (!cedar_devp->iomap_addrs.prcm_bass_vir) {
2156 		VE_LOGW("ve Can't map prcm_bass_vir registers");
2157 	}
2158 #endif
2159 
2160 	//get clk
2161 	cedar_devp->ve_clk = devm_clk_get(cedar_devp->plat_dev, "ve");
2162 	if (IS_ERR(cedar_devp->ve_clk)) {
2163 		VE_LOGW("try to get ve clk fail\n");
2164 		return -1;
2165 	}
2166 
2167 #if defined CONFIG_ARCH_SUN50IW12P1
2168 	cedar_devp->bus_ve_clk = devm_clk_get(cedar_devp->plat_dev, "bus_ve");
2169 	if (IS_ERR(cedar_devp->bus_ve_clk)) {
2170 		VE_LOGW("try to get ve clk fail\n");
2171 		return -1;
2172 	}
2173 
2174 	cedar_devp->bus_ve3_clk = devm_clk_get(cedar_devp->plat_dev, "bus_ve3");
2175 	if (IS_ERR(cedar_devp->bus_ve3_clk)) {
2176 		VE_LOGW("try to get bus clk fail\n");
2177 		return -1;
2178 	}
2179 
2180 	cedar_devp->mbus_ve3_clk = devm_clk_get(cedar_devp->plat_dev, "mbus_ve3");
2181 	if (IS_ERR(cedar_devp->mbus_ve3_clk)) {
2182 		VE_LOGW("try to get mbus clk fail\n");
2183 		return -1;
2184 	}
2185 #else
2186 	cedar_devp->bus_clk = devm_clk_get(cedar_devp->plat_dev, "bus_ve");
2187 	if (IS_ERR(cedar_devp->bus_clk)) {
2188 		VE_LOGW("try to get bus clk fail\n");
2189 		return -1;
2190 	}
2191 
2192 	cedar_devp->mbus_clk = devm_clk_get(cedar_devp->plat_dev, "mbus_ve");
2193 	if (IS_ERR(cedar_devp->mbus_clk)) {
2194 		VE_LOGW("try to get mbus clk fail\n");
2195 		return -1;
2196 	}
2197 #endif
2198 
2199 	cedar_devp->parent_clk = clk_get_parent(cedar_devp->ve_clk);
2200 	if (IS_ERR(cedar_devp->parent_clk)) {
2201 		VE_LOGW("try to get parent clk fail\n");
2202 		return -1;
2203 	}
2204 	//todo: you maybe need to change parent
2205 	#if defined(CONFIG_ARCH_SUN8IW19P1)
2206 	if (clk_set_parent(cedar_devp->ve_clk, cedar_devp->parent_clk)) {
2207 		VE_LOGW("set ve clk and parent clk failed;\n");
2208 		return -1;
2209 	}
2210 	#endif
2211 
2212 #if defined CONFIG_ARCH_SUN50IW12P1
2213 	cedar_devp->reset = devm_reset_control_get(cedar_devp->plat_dev, "reset_ve3");
2214 	if (IS_ERR(cedar_devp->reset)) {
2215 		VE_LOGE("get reset ve3 fail\n");
2216 		return -1;
2217 	}
2218 
2219 	cedar_devp->reset_ve = devm_reset_control_get_shared(cedar_devp->plat_dev, "reset_ve");
2220 	if (IS_ERR(cedar_devp->reset_ve)) {
2221 		VE_LOGE("get reset ve fail\n");
2222 		return -1;
2223 	}
2224 #else
2225 		cedar_devp->reset = devm_reset_control_get(cedar_devp->plat_dev, NULL);
2226 		if (IS_ERR(cedar_devp->reset)) {
2227 			VE_LOGE("get reset fail\n");
2228 			return -1;
2229 		}
2230 #endif
2231 
2232 
2233 	set_system_register();
2234 
2235 	return 0;
2236 }
2237 
2238 static const struct file_operations cedardev_fops = {
2239 	.owner	 = THIS_MODULE,
2240 	.mmap	 = cedardev_mmap,
2241 	.open	 = cedardev_open,
2242 	.release = cedardev_release,
2243 	.llseek	 = no_llseek,
2244 	.unlocked_ioctl	= compat_cedardev_ioctl,
2245 	.compat_ioctl   = compat_cedardev_ioctl,
2246 };
2247 
2248 
create_char_device(void)2249 static int create_char_device(void)
2250 {
2251 	dev_t dev = 0;
2252 	int ret = 0;
2253 	int devno;
2254 
2255 	//1.register or alloc the device number.
2256 	if (g_dev_major) {
2257 		dev = MKDEV(g_dev_major, g_dev_minor);
2258 		ret = register_chrdev_region(dev, 1, "cedar_dev");
2259 	} else {
2260 		ret = alloc_chrdev_region(&dev, g_dev_minor, 1, "cedar_dev");
2261 		g_dev_major = MAJOR(dev);
2262 		g_dev_minor = MINOR(dev);
2263 	}
2264 
2265 	if (ret < 0) {
2266 		VE_LOGE("cedar_dev: can't get major %d\n", g_dev_major);
2267 		return ret;
2268 	}
2269 
2270 	//2.create char device
2271 	devno = MKDEV(g_dev_major, g_dev_minor);
2272 	cdev_init(&cedar_devp->cdev, &cedardev_fops);
2273 	cedar_devp->cdev.owner = THIS_MODULE;
2274 	ret = cdev_add(&cedar_devp->cdev, devno, 1);
2275 	if (ret) {
2276 		VE_LOGE("Err:%d add cedar-dev fail\n", ret);
2277 		goto region_del;
2278 	}
2279 	//3.create class and new device for auto device node
2280 	cedar_devp->class = class_create(THIS_MODULE, "cedar_ve");
2281 	if (IS_ERR_OR_NULL(cedar_devp->class)) {
2282 		VE_LOGE("class create fail\n");
2283 		ret = -EINVAL;
2284 		goto dev_del;
2285 	}
2286 	cedar_devp->dev	  = device_create(cedar_devp->class, NULL, devno, NULL, "cedar_dev");
2287 	if (IS_ERR_OR_NULL(cedar_devp->dev)) {
2288 		VE_LOGE("device create fail\n");
2289 		ret = -EINVAL;
2290 		goto class_del;
2291 	}
2292 	return ret;
2293 
2294 class_del:
2295 	class_destroy(cedar_devp->class);
2296 dev_del:
2297 	cdev_del(&cedar_devp->cdev);
2298 region_del:
2299 	unregister_chrdev_region(dev, 1);
2300 
2301 	return ret;
2302 }
2303 
ve_info_show(struct device * dev,struct device_attribute * attr,char * buf)2304 static ssize_t ve_info_show(struct device *dev,
2305 				struct device_attribute *attr, char *buf)
2306 {
2307 	ssize_t count = 0;
2308 	int i = 0;
2309 	int nTotalSize = 0;
2310 
2311 	/* VE_LOGD("show: buf = %p\n",buf); */
2312 
2313 	count += sprintf(buf + count, "********* ve proc info **********\n");
2314 
2315 	mutex_lock(&cedar_devp->lock_debug_info);
2316 	for (i = 0; i < MAX_VE_DEBUG_INFO_NUM; i++) {
2317 		if (cedar_devp->debug_info[i].head_info.pid != 0
2318 		&& cedar_devp->debug_info[i].head_info.tid != 0) {
2319 			nTotalSize += cedar_devp->debug_info[i].head_info.length;
2320 
2321 			#if 0
2322 			VE_LOGD("cpy-show: i = %d, size = %d, total size = %d, data = %p, cout = %d, id = %d, %d\n",
2323 					i,
2324 					cedar_devp->debug_info[i].head_info.length,
2325 					nTotalSize,
2326 					cedar_devp->debug_info[i].data, (int)count,
2327 					cedar_devp->debug_info[i].head_info.pid,
2328 					cedar_devp->debug_info[i].head_info.tid);
2329 			#endif
2330 
2331 			if (nTotalSize > PAGE_SIZE)
2332 				break;
2333 
2334 			memcpy(buf + count, cedar_devp->debug_info[i].data,
2335 					cedar_devp->debug_info[i].head_info.length);
2336 
2337 			count += cedar_devp->debug_info[i].head_info.length;
2338 		}
2339 
2340 	}
2341 
2342 	mutex_unlock(&cedar_devp->lock_debug_info);
2343 	/*VE_LOGD("return count = %d\n",(int)count);*/
2344 	return count;
2345 }
2346 
2347 /*sysfs create file, just support show*/
2348 static DEVICE_ATTR(ve_info, 0664, ve_info_show, NULL);
2349 
2350 static struct attribute *ve_attributes[] = {
2351 	&dev_attr_ve_info.attr,
2352 	NULL
2353 };
2354 
2355 static struct attribute_group ve_attribute_group = {
2356 	.name = "attr",
2357 	.attrs = ve_attributes
2358 };
2359 
cedardev_init(struct platform_device * pdev)2360 static int cedardev_init(struct platform_device *pdev)
2361 {
2362 	int ret = 0;
2363 	int i = 0;
2364 
2365 	VE_LOGD("install start!!!\n");
2366 
2367 	(void)i;
2368 	cedar_devp = kmalloc(sizeof(struct cedar_dev), GFP_KERNEL);
2369 	if (cedar_devp == NULL) {
2370 		VE_LOGW("malloc mem for cedar device err\n");
2371 		return -ENOMEM;
2372 	}
2373 	memset(cedar_devp, 0, sizeof(struct cedar_dev));
2374 
2375 	//1.register cdev
2376 	if (create_char_device() != 0) {
2377 		ret = -EINVAL;
2378 		goto free_devp;
2379 	}
2380 	//2.init some data
2381 	spin_lock_init(&cedar_devp->lock);
2382 	cedar_devp->plat_dev = &pdev->dev;
2383 	sema_init(&cedar_devp->sem, 1);
2384 	init_waitqueue_head(&cedar_devp->wq);
2385 
2386 	timer_setup(&cedar_devp->cedar_engine_timer, cedar_engine_for_events, TIMER_DEFERRABLE);
2387 	timer_setup(&cedar_devp->cedar_engine_timer_rel, cedar_engine_for_timer_rel, TIMER_DEFERRABLE);
2388 
2389 	mutex_init(&cedar_devp->lock_vdec);
2390 	mutex_init(&cedar_devp->lock_venc);
2391 	mutex_init(&cedar_devp->lock_jdec);
2392 	mutex_init(&cedar_devp->lock_00_reg);
2393 	mutex_init(&cedar_devp->lock_04_reg);
2394 	mutex_init(&cedar_devp->lock_mem);
2395 	mutex_init(&cedar_devp->lock_debug_info);
2396 
2397 	//3.config some register
2398 	if (deal_with_resouce(pdev)) {
2399 		ret = -EINVAL;
2400 		goto free_devp;
2401 	}
2402 
2403 	//4.create sysfs file on new device
2404 	if (sysfs_create_group(&cedar_devp->dev->kobj, &ve_attribute_group)) {
2405 		VE_LOGW("sysfs create group failed, maybe ok!");
2406 		ret = -EINVAL;
2407 		goto free_devp;
2408 	}
2409 
2410 	//5.create debugfs file
2411 #if IS_ENABLED(CONFIG_DEBUG_FS)
2412 	ret = sunxi_ve_debug_register_driver();
2413 	if (ret) {
2414 		VE_LOGW("sunxi ve debug register fail");
2415 		ret = -EINVAL;
2416 		goto free_devp;
2417 	}
2418 
2419 	memset(&ve_debug_proc_info, 0, sizeof(struct ve_debugfs_buffer));
2420 	for (i = 0; i < VE_DEBUGFS_MAX_CHANNEL; i++)
2421 		ve_debug_proc_info.proc_buf[i] = NULL;
2422 
2423 	ve_debug_proc_info.data =
2424 		kmalloc(VE_DEBUGFS_BUF_SIZE*VE_DEBUGFS_MAX_CHANNEL, GFP_KERNEL);
2425 	if (!ve_debug_proc_info.data) {
2426 		VE_LOGE("kmalloc proc buffer failed!\n");
2427 		ret = -ENOMEM;
2428 		goto free_devp;
2429 	}
2430 	mutex_init(&ve_debug_proc_info.lock_proc);
2431 	VE_LOGI("ve_debug_proc_info:%p, data:%p, lock:%p\n",
2432 			&ve_debug_proc_info,
2433 			ve_debug_proc_info.data,
2434 			&ve_debug_proc_info.lock_proc);
2435 
2436 #endif
2437 
2438 	VE_LOGD("install end!!!\n");
2439 	return 0;
2440 
2441 free_devp:
2442 	kfree(cedar_devp);
2443 	return ret;
2444 }
2445 
cedardev_exit(void)2446 static void cedardev_exit(void)
2447 {
2448 	int i = 0;
2449 	dev_t dev;
2450 
2451 	dev = MKDEV(g_dev_major, g_dev_minor);
2452 
2453 	free_irq(cedar_devp->irq, NULL);
2454 	iounmap(cedar_devp->iomap_addrs.regs_ve);
2455 	/* Destroy char device */
2456 
2457 	cdev_del(&cedar_devp->cdev);
2458 	device_destroy(cedar_devp->class, dev);
2459 	class_destroy(cedar_devp->class);
2460 	unregister_chrdev_region(dev, 1);
2461 
2462 	//todo: power clk not support
2463 #if defined CONFIG_ARCH_SUN9IW1P1
2464 	regulator_put(regu);
2465 
2466 	if (NULL == cedar_devp->power_clk || IS_ERR(cedar_devp->power_clk)) {
2467 		VE_LOGW("cedar_devp->power_clk handle is invalid,just return!\n");
2468 	} else {
2469 		clk_disable_unprepare(cedar_devp->power_clk);
2470 		clk_put(cedar_devp->power_clk);
2471 		cedar_devp->power_clk = NULL;
2472 	}
2473 #endif
2474 
2475 	//check whether free debug buffer
2476 	for (i = 0; i < MAX_VE_DEBUG_INFO_NUM; i++) {
2477 		if (cedar_devp->debug_info[i].data != NULL) {
2478 			VE_LOGW("vfree : debug_info[%d].data = %p", i, cedar_devp->debug_info[i].data);
2479 			vfree(cedar_devp->debug_info[i].data);
2480 		}
2481 	}
2482 
2483 #if IS_ENABLED(CONFIG_DEBUG_FS)
2484 	sunxi_ve_debug_unregister_driver();
2485 	kfree(ve_debug_proc_info.data);
2486 #endif
2487 
2488 	kfree(cedar_devp);
2489 
2490 	VE_LOGD("cedar-ve exit");
2491 }
2492 
sunxi_cedar_remove(struct platform_device * pdev)2493 static int	sunxi_cedar_remove(struct platform_device *pdev)
2494 {
2495 	struct device_node *np = pdev->dev.of_node;
2496 	VE_LOGD("sunxi_cedar_remove");
2497 	pdev->id = of_alias_get_id(np, "ve");
2498 	if (pdev->id < 0) {
2499 		VE_LOGD("failed to get alias ve id\n");
2500 	} else if (pdev->id == 1) {
2501 		VE_LOGI("device ve1 just return");
2502 		return 0;
2503 	}
2504 #if defined CONFIG_ARCH_SUN8IW20
2505        pm_runtime_disable(&pdev->dev);
2506 #endif
2507 	cedardev_exit();
2508 	return 0;
2509 }
2510 
sunxi_cedar_probe(struct platform_device * pdev)2511 static int	sunxi_cedar_probe(struct platform_device *pdev)
2512 {
2513 	struct device_node *np = pdev->dev.of_node;
2514 	pdev->id = of_alias_get_id(np, "ve");
2515 	if (pdev->id < 0) {
2516 		VE_LOGD("failed to get alias ve id\n");
2517 	} else if (pdev->id == 1) {
2518 		VE_LOGI("device ve1 just use to add iommu master");
2519 		return 0;
2520 	}
2521 #if defined CONFIG_ARCH_SUN8IW20
2522 	VE_LOGD("sunxi_cedar_probe power-domain init!!!");
2523 	//add for R528 sleep and awaken
2524 	pm_runtime_set_active(&pdev->dev);
2525 	pm_runtime_enable(&pdev->dev);
2526 	pm_runtime_get_sync(&pdev->dev);
2527 #endif
2528 	cedardev_init(pdev);
2529 	VE_LOGD("sunxi_cedar_probe");
2530 	return 0;
2531 }
2532 
2533 static struct of_device_id sunxi_cedar_match[] = {
2534 	{ .compatible = "allwinner,sunxi-cedar-ve",},
2535 	{}
2536 };
2537 MODULE_DEVICE_TABLE(of, sunxi_cedar_match);
2538 
2539 static struct platform_driver sunxi_cedar_driver = {
2540 	.probe		= sunxi_cedar_probe,
2541 	.remove		= sunxi_cedar_remove,
2542 	.driver		= {
2543 		.pm	= &sunxi_cedar_pm_ops,
2544 		.name	= "sunxi-cedar",
2545 		.owner	= THIS_MODULE,
2546 		.of_match_table = sunxi_cedar_match,
2547 	},
2548 };
2549 
sunxi_cedar_init(void)2550 static int __init sunxi_cedar_init(void)
2551 {
2552 	/* we don't register device which is registered by device tree */
2553 	/* platform_device_register(&sunxi_device_cedar);              */
2554 	printk("sunxi cedar version 1.1\n");
2555 	return platform_driver_register(&sunxi_cedar_driver);
2556 }
2557 
sunxi_cedar_exit(void)2558 static void __exit sunxi_cedar_exit(void)
2559 {
2560 	platform_driver_unregister(&sunxi_cedar_driver);
2561 }
2562 
2563 module_init(sunxi_cedar_init);
2564 module_exit(sunxi_cedar_exit);
2565 
2566 
2567 MODULE_AUTHOR("Soft-Reuuimlla");
2568 MODULE_DESCRIPTION("User mode CEDAR device interface");
2569 MODULE_LICENSE("GPL");
2570 MODULE_VERSION(DRV_VERSION);
2571 MODULE_ALIAS("platform:cedarx-sunxi");
2572