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