Merge remote-tracking branch 'stable/linux-3.0.y' into develop-3.0
[firefly-linux-kernel-4.4.55.git] / arch / arm / plat-rk / vpu_service.c
1 /* arch/arm/mach-rk29/vpu.c
2  *
3  * Copyright (C) 2010 ROCKCHIP, Inc.
4  * author: chenhengming chm@rock-chips.com
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  */
16
17 #ifdef CONFIG_RK29_VPU_DEBUG
18 #define DEBUG
19 #define pr_fmt(fmt) "VPU_SERVICE: %s: " fmt, __func__
20 #else
21 #define pr_fmt(fmt) "VPU_SERVICE: " fmt
22 #endif
23
24
25 #include <linux/clk.h>
26 #include <linux/delay.h>
27 #include <linux/init.h>
28 #include <linux/interrupt.h>
29 #include <linux/io.h>
30 #include <linux/kernel.h>
31 #include <linux/module.h>
32 #include <linux/fs.h>
33 #include <linux/ioport.h>
34 #include <linux/miscdevice.h>
35 #include <linux/mm.h>
36 #include <linux/poll.h>
37 #include <linux/platform_device.h>
38 #include <linux/sched.h>
39 #include <linux/slab.h>
40 #include <linux/timer.h>
41
42 #include <asm/uaccess.h>
43
44 #include <mach/irqs.h>
45 #include <plat/vpu_service.h>
46 #include <mach/pmu.h>
47 #include <mach/cru.h>
48
49 typedef enum {
50         VPU_DEC_ID_9190         = 0x6731,
51         VPU_ID_8270             = 0x8270,
52         VPU_ID_4831             = 0x4831,
53 } VPU_HW_ID;
54
55 typedef enum {
56         VPU_DEC_TYPE_9190       = 0,
57         VPU_ENC_TYPE_8270       = 0x100,
58         VPU_ENC_TYPE_4831       ,
59 } VPU_HW_TYPE_E;
60
61 typedef struct {
62         VPU_HW_ID               hw_id;
63         unsigned long           hw_addr;
64         unsigned long           enc_offset;
65         unsigned long           enc_reg_num;
66         unsigned long           enc_io_size;
67         unsigned long           dec_offset;
68         unsigned long           dec_reg_num;
69         unsigned long           dec_io_size;
70 } VPU_HW_INFO_E;
71
72 #define VCODEC_PHYS                             (0x10104000)
73
74 #define REG_NUM_9190_DEC                        (60)
75 #define REG_NUM_9190_PP                         (41)
76 #define REG_NUM_9190_DEC_PP                     (REG_NUM_9190_DEC+REG_NUM_9190_PP)
77
78 #define REG_NUM_DEC_PP                          (REG_NUM_9190_DEC+REG_NUM_9190_PP)
79
80 #define REG_NUM_ENC_8270                        (96)
81 #define REG_SIZE_ENC_8270                       (0x200)
82 #define REG_NUM_ENC_4831                        (164)
83 #define REG_SIZE_ENC_4831                       (0x400)
84
85 #define SIZE_REG(reg)                           ((reg)*4)
86
87 VPU_HW_INFO_E vpu_hw_set[] = {
88         [0] = {
89                 .hw_id          = VPU_ID_8270,
90                 .hw_addr        = VCODEC_PHYS,
91                 .enc_offset     = 0x0,
92                 .enc_reg_num    = REG_NUM_ENC_8270,
93                 .enc_io_size    = REG_NUM_ENC_8270 * 4,
94                 .dec_offset     = REG_SIZE_ENC_8270,
95                 .dec_reg_num    = REG_NUM_9190_DEC_PP,
96                 .dec_io_size    = REG_NUM_9190_DEC_PP * 4,
97         },
98         [1] = {
99                 .hw_id          = VPU_ID_4831,
100                 .hw_addr        = VCODEC_PHYS,
101                 .enc_offset     = 0x0,
102                 .enc_reg_num    = REG_NUM_ENC_4831,
103                 .enc_io_size    = REG_NUM_ENC_4831 * 4,
104                 .dec_offset     = REG_SIZE_ENC_4831,
105                 .dec_reg_num    = REG_NUM_9190_DEC_PP,
106                 .dec_io_size    = REG_NUM_9190_DEC_PP * 4,
107         },
108 };
109
110
111 #define DEC_INTERRUPT_REGISTER                  1
112 #define PP_INTERRUPT_REGISTER                   60
113 #define ENC_INTERRUPT_REGISTER                  1
114
115 #define DEC_INTERRUPT_BIT                        0x100
116 #define PP_INTERRUPT_BIT                         0x100
117 #define ENC_INTERRUPT_BIT                        0x1
118
119 #define VPU_REG_EN_ENC                          14
120 #define VPU_REG_ENC_GATE                        2
121 #define VPU_REG_ENC_GATE_BIT                    (1<<4)
122
123 #define VPU_REG_EN_DEC                          1
124 #define VPU_REG_DEC_GATE                        2
125 #define VPU_REG_DEC_GATE_BIT                    (1<<10)
126 #define VPU_REG_EN_PP                           0
127 #define VPU_REG_PP_GATE                         1
128 #define VPU_REG_PP_GATE_BIT                     (1<<8)
129 #define VPU_REG_EN_DEC_PP                       1
130 #define VPU_REG_DEC_PP_GATE                     61
131 #define VPU_REG_DEC_PP_GATE_BIT                 (1<<8)
132
133
134 /**
135  * struct for process session which connect to vpu
136  *
137  * @author ChenHengming (2011-5-3)
138  */
139 typedef struct vpu_session {
140         VPU_CLIENT_TYPE         type;
141         /* a linked list of data so we can access them for debugging */
142         struct list_head        list_session;
143         /* a linked list of register data waiting for process */
144         struct list_head        waiting;
145         /* a linked list of register data in processing */
146         struct list_head        running;
147         /* a linked list of register data processed */
148         struct list_head        done;
149         wait_queue_head_t       wait;
150         pid_t                   pid;
151         atomic_t                task_running;
152 } vpu_session;
153
154 /**
155  * struct for process register set
156  *
157  * @author ChenHengming (2011-5-4)
158  */
159 typedef struct vpu_reg {
160         VPU_CLIENT_TYPE         type;
161         vpu_session             *session;
162         struct list_head        session_link;           /* link to vpu service session */
163         struct list_head        status_link;            /* link to register set list */
164         unsigned long           size;
165         unsigned long           *reg;
166 } vpu_reg;
167
168 typedef struct vpu_device {
169         unsigned long           iobaseaddr;
170         unsigned int            iosize;
171         volatile u32            *hwregs;
172 } vpu_device;
173
174 typedef struct vpu_service_info {
175         spinlock_t              lock;
176         spinlock_t              lock_power;
177         struct timer_list       timer;                  /* timer for power off */
178         struct list_head        waiting;                /* link to link_reg in struct vpu_reg */
179         struct list_head        running;                /* link to link_reg in struct vpu_reg */
180         struct list_head        done;                   /* link to link_reg in struct vpu_reg */
181         struct list_head        session;                /* link to list_session in struct vpu_session */
182         atomic_t                total_running;
183         bool                    enabled;
184         vpu_reg                 *reg_codec;
185         vpu_reg                 *reg_pproc;
186         vpu_reg                 *reg_resev;
187         VPUHwDecConfig_t        dec_config;
188         VPUHwEncConfig_t        enc_config;
189         VPU_HW_INFO_E           *hw_info;
190         unsigned long           reg_size;
191 } vpu_service_info;
192
193 typedef struct vpu_request
194 {
195         unsigned long   *req;
196         unsigned long   size;
197 } vpu_request;
198
199 static struct clk *pd_video;
200 static struct clk *clk_vpu; /* for power on notify */
201 static struct clk *aclk_vepu;
202 static struct clk *hclk_vepu;
203 static struct clk *aclk_ddr_vepu;
204 static struct clk *hclk_cpu_vcodec;
205 static vpu_service_info service;
206 static vpu_device       dec_dev;
207 static vpu_device       enc_dev;
208
209 #define POWER_OFF_DELAY 4*HZ /* 4s */
210 #define TIMEOUT_DELAY   2*HZ /* 2s */
211
212 static void vpu_get_clk(void)
213 {
214         pd_video        = clk_get(NULL, "pd_video");
215         clk_vpu         = clk_get(NULL, "vpu");
216         aclk_vepu       = clk_get(NULL, "aclk_vepu");
217         hclk_vepu       = clk_get(NULL, "hclk_vepu");
218         aclk_ddr_vepu   = clk_get(NULL, "aclk_ddr_vepu");
219         hclk_cpu_vcodec = clk_get(NULL, "hclk_cpu_vcodec");
220 }
221
222 static void vpu_put_clk(void)
223 {
224         clk_put(pd_video);
225         clk_put(clk_vpu);
226         clk_put(aclk_vepu);
227         clk_put(hclk_vepu);
228         clk_put(aclk_ddr_vepu);
229         clk_put(hclk_cpu_vcodec);
230 }
231
232 static void vpu_reset(void)
233 {
234 #if defined(CONFIG_ARCH_RK29)
235         clk_disable(aclk_ddr_vepu);
236         cru_set_soft_reset(SOFT_RST_CPU_VODEC_A2A_AHB, true);
237         cru_set_soft_reset(SOFT_RST_DDR_VCODEC_PORT, true);
238         cru_set_soft_reset(SOFT_RST_VCODEC_AHB_BUS, true);
239         cru_set_soft_reset(SOFT_RST_VCODEC_AXI_BUS, true);
240         mdelay(10);
241         cru_set_soft_reset(SOFT_RST_VCODEC_AXI_BUS, false);
242         cru_set_soft_reset(SOFT_RST_VCODEC_AHB_BUS, false);
243         cru_set_soft_reset(SOFT_RST_DDR_VCODEC_PORT, false);
244         cru_set_soft_reset(SOFT_RST_CPU_VODEC_A2A_AHB, false);
245         clk_enable(aclk_ddr_vepu);
246 #elif defined(CONFIG_ARCH_RK30)
247         pmu_set_idle_request(IDLE_REQ_VIDEO, true);
248         cru_set_soft_reset(SOFT_RST_CPU_VCODEC, true);
249         cru_set_soft_reset(SOFT_RST_VCODEC_NIU_AXI, true);
250         cru_set_soft_reset(SOFT_RST_VCODEC_AHB, true);
251         cru_set_soft_reset(SOFT_RST_VCODEC_AXI, true);
252         mdelay(1);
253         cru_set_soft_reset(SOFT_RST_VCODEC_AXI, false);
254         cru_set_soft_reset(SOFT_RST_VCODEC_AHB, false);
255         cru_set_soft_reset(SOFT_RST_VCODEC_NIU_AXI, false);
256         cru_set_soft_reset(SOFT_RST_CPU_VCODEC, false);
257         pmu_set_idle_request(IDLE_REQ_VIDEO, false);
258 #endif
259         service.reg_codec = NULL;
260         service.reg_pproc = NULL;
261         service.reg_resev = NULL;
262 }
263
264 static void reg_deinit(vpu_reg *reg);
265 static void vpu_service_session_clear(vpu_session *session)
266 {
267         vpu_reg *reg, *n;
268         list_for_each_entry_safe(reg, n, &session->waiting, session_link) {
269                 reg_deinit(reg);
270         }
271         list_for_each_entry_safe(reg, n, &session->running, session_link) {
272                 reg_deinit(reg);
273         }
274         list_for_each_entry_safe(reg, n, &session->done, session_link) {
275                 reg_deinit(reg);
276         }
277 }
278
279 static void vpu_service_dump(void)
280 {
281         int running;
282         vpu_reg *reg, *reg_tmp;
283         vpu_session *session, *session_tmp;
284
285         running = atomic_read(&service.total_running);
286         printk("total_running %d\n", running);
287
288         printk("reg_codec 0x%.8x\n", (unsigned int)service.reg_codec);
289         printk("reg_pproc 0x%.8x\n", (unsigned int)service.reg_pproc);
290         printk("reg_resev 0x%.8x\n", (unsigned int)service.reg_resev);
291
292         list_for_each_entry_safe(session, session_tmp, &service.session, list_session) {
293                 printk("session pid %d type %d:\n", session->pid, session->type);
294                 running = atomic_read(&session->task_running);
295                 printk("task_running %d\n", running);
296                 list_for_each_entry_safe(reg, reg_tmp, &session->waiting, session_link) {
297                         printk("waiting register set 0x%.8x\n", (unsigned int)reg);
298                 }
299                 list_for_each_entry_safe(reg, reg_tmp, &session->running, session_link) {
300                         printk("running register set 0x%.8x\n", (unsigned int)reg);
301                 }
302                 list_for_each_entry_safe(reg, reg_tmp, &session->done, session_link) {
303                         printk("done    register set 0x%.8x\n", (unsigned int)reg);
304                 }
305         }
306 }
307
308 static void vpu_service_power_off(void)
309 {
310         int total_running;
311
312         spin_lock_bh(&service.lock_power);
313         if (!service.enabled) {
314                 spin_unlock_bh(&service.lock_power);
315                 return;
316         }
317
318         service.enabled = false;
319         total_running = atomic_read(&service.total_running);
320         if (total_running) {
321                 pr_alert("alert: power off when %d task running!!\n", total_running);
322                 mdelay(50);
323                 pr_alert("alert: delay 50 ms for running task\n");
324                 vpu_service_dump();
325         }
326
327         printk("vpu: power off...");
328 #ifdef CONFIG_ARCH_RK29
329         pmu_set_power_domain(PD_VCODEC, false);
330 #else
331         clk_disable(pd_video);
332 #endif
333         udelay(10);
334         clk_disable(hclk_cpu_vcodec);
335         clk_disable(aclk_ddr_vepu);
336         clk_disable(hclk_vepu);
337         clk_disable(aclk_vepu);
338         clk_disable(clk_vpu);
339         printk("done\n");
340         spin_unlock_bh(&service.lock_power);
341 }
342
343 static void vpu_service_power_off_work_func(unsigned long data)
344 {
345         printk("delayed ");
346         vpu_service_power_off();
347 }
348
349 static void vpu_service_power_maintain(void)
350 {
351         if (service.enabled) {
352                 mod_timer(&service.timer, jiffies + POWER_OFF_DELAY);
353         } else {
354                 pr_err("error: maintain power when power is off!\n");
355         }
356 }
357
358 static void vpu_service_power_on(void)
359 {
360         clk_enable(clk_vpu); /* notify vpu on without lock. */
361
362         spin_lock_bh(&service.lock_power);
363         if (!service.enabled) {
364                 service.enabled = true;
365                 printk("vpu: power on\n");
366
367                 clk_enable(clk_vpu);
368                 clk_enable(aclk_vepu);
369                 clk_enable(hclk_vepu);
370                 clk_enable(hclk_cpu_vcodec);
371                 udelay(10);
372 #ifdef CONFIG_ARCH_RK29
373                 pmu_set_power_domain(PD_VCODEC, true);
374 #else
375                 clk_enable(pd_video);
376 #endif
377                 udelay(10);
378                 clk_enable(aclk_ddr_vepu);
379                 mod_timer(&service.timer, jiffies + POWER_OFF_DELAY);
380                 spin_unlock_bh(&service.lock_power);
381         } else {
382                 spin_unlock_bh(&service.lock_power);
383                 vpu_service_power_maintain();
384         }
385
386         clk_disable(clk_vpu);
387 }
388
389 static vpu_reg *reg_init(vpu_session *session, void __user *src, unsigned long size)
390 {
391         unsigned long flag;
392         vpu_reg *reg = kmalloc(sizeof(vpu_reg)+service.reg_size, GFP_KERNEL);
393         if (NULL == reg) {
394                 pr_err("error: kmalloc fail in reg_init\n");
395                 return NULL;
396         }
397
398         reg->session = session;
399         reg->type = session->type;
400         reg->size = size;
401         reg->reg = (unsigned long *)&reg[1];
402         INIT_LIST_HEAD(&reg->session_link);
403         INIT_LIST_HEAD(&reg->status_link);
404
405         if (copy_from_user(&reg->reg[0], (void __user *)src, size)) {
406                 pr_err("error: copy_from_user failed in reg_init\n");
407                 kfree(reg);
408                 return NULL;
409         }
410
411         spin_lock_irqsave(&service.lock, flag);
412         list_add_tail(&reg->status_link, &service.waiting);
413         list_add_tail(&reg->session_link, &session->waiting);
414         spin_unlock_irqrestore(&service.lock, flag);
415
416         return reg;
417 }
418
419 static void reg_deinit(vpu_reg *reg)
420 {
421         list_del_init(&reg->session_link);
422         list_del_init(&reg->status_link);
423         if (reg == service.reg_codec) service.reg_codec = NULL;
424         if (reg == service.reg_pproc) service.reg_pproc = NULL;
425         kfree(reg);
426 }
427
428 static void reg_from_wait_to_run(vpu_reg *reg)
429 {
430         list_del_init(&reg->status_link);
431         list_add_tail(&reg->status_link, &service.running);
432
433         list_del_init(&reg->session_link);
434         list_add_tail(&reg->session_link, &reg->session->running);
435 }
436
437 static void reg_copy_from_hw(vpu_reg *reg, volatile u32 *src, u32 count)
438 {
439         int i;
440         u32 *dst = (u32 *)&reg->reg[0];
441         for (i = 0; i < count; i++)
442                 *dst++ = *src++;
443 }
444
445 static void reg_from_run_to_done(vpu_reg *reg)
446 {
447         list_del_init(&reg->status_link);
448         list_add_tail(&reg->status_link, &service.done);
449
450         list_del_init(&reg->session_link);
451         list_add_tail(&reg->session_link, &reg->session->done);
452
453         switch (reg->type) {
454         case VPU_ENC : {
455                 service.reg_codec = NULL;
456                 reg_copy_from_hw(reg, enc_dev.hwregs, service.hw_info->enc_reg_num);
457                 break;
458         }
459         case VPU_DEC : {
460                 service.reg_codec = NULL;
461                 reg_copy_from_hw(reg, dec_dev.hwregs, REG_NUM_9190_DEC);
462                 break;
463         }
464         case VPU_PP : {
465                 service.reg_pproc = NULL;
466                 reg_copy_from_hw(reg, dec_dev.hwregs + PP_INTERRUPT_REGISTER, REG_NUM_9190_PP);
467                 dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0;
468                 break;
469         }
470         case VPU_DEC_PP : {
471                 service.reg_codec = NULL;
472                 service.reg_pproc = NULL;
473                 reg_copy_from_hw(reg, dec_dev.hwregs, REG_NUM_9190_DEC_PP);
474                 dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0;
475                 break;
476         }
477         default : {
478                 pr_err("error: copy reg from hw with unknown type %d\n", reg->type);
479                 break;
480         }
481         }
482         atomic_sub(1, &reg->session->task_running);
483         atomic_sub(1, &service.total_running);
484         wake_up_interruptible_sync(&reg->session->wait);
485 }
486
487 void reg_copy_to_hw(vpu_reg *reg)
488 {
489         int i;
490         u32 *src = (u32 *)&reg->reg[0];
491         atomic_add(1, &service.total_running);
492         atomic_add(1, &reg->session->task_running);
493         switch (reg->type) {
494         case VPU_ENC : {
495                 int enc_count = service.hw_info->enc_reg_num;
496                 u32 *dst = (u32 *)enc_dev.hwregs;
497 #if defined(CONFIG_ARCH_RK30)
498                 cru_set_soft_reset(SOFT_RST_CPU_VCODEC, true);
499                 cru_set_soft_reset(SOFT_RST_VCODEC_AHB, true);
500                 cru_set_soft_reset(SOFT_RST_VCODEC_AHB, false);
501                 cru_set_soft_reset(SOFT_RST_CPU_VCODEC, false);
502 #endif
503                 service.reg_codec = reg;
504
505                 dst[VPU_REG_EN_ENC] = src[VPU_REG_EN_ENC] & 0x6;
506
507                 for (i = 0; i < VPU_REG_EN_ENC; i++)
508                         dst[i] = src[i];
509
510                 for (i = VPU_REG_EN_ENC + 1; i < enc_count; i++)
511                         dst[i] = src[i];
512
513                 dsb();
514
515                 dst[VPU_REG_ENC_GATE] = src[VPU_REG_ENC_GATE] | VPU_REG_ENC_GATE_BIT;
516                 dst[VPU_REG_EN_ENC]   = src[VPU_REG_EN_ENC];
517         } break;
518         case VPU_DEC : {
519                 u32 *dst = (u32 *)dec_dev.hwregs;
520                 service.reg_codec = reg;
521
522                 for (i = REG_NUM_9190_DEC - 1; i > VPU_REG_DEC_GATE; i--)
523                         dst[i] = src[i];
524
525                 dsb();
526
527                 dst[VPU_REG_DEC_GATE] = src[VPU_REG_DEC_GATE] | VPU_REG_DEC_GATE_BIT;
528                 dst[VPU_REG_EN_DEC]   = src[VPU_REG_EN_DEC];
529         } break;
530         case VPU_PP : {
531                 u32 *dst = (u32 *)dec_dev.hwregs + PP_INTERRUPT_REGISTER;
532                 service.reg_pproc = reg;
533
534                 dst[VPU_REG_PP_GATE] = src[VPU_REG_PP_GATE] | VPU_REG_PP_GATE_BIT;
535
536                 for (i = VPU_REG_PP_GATE + 1; i < REG_NUM_9190_PP; i++)
537                         dst[i] = src[i];
538
539                 dsb();
540
541                 dst[VPU_REG_EN_PP] = src[VPU_REG_EN_PP];
542         } break;
543         case VPU_DEC_PP : {
544                 u32 *dst = (u32 *)dec_dev.hwregs;
545                 service.reg_codec = reg;
546                 service.reg_pproc = reg;
547
548                 for (i = VPU_REG_EN_DEC_PP + 1; i < REG_NUM_9190_DEC_PP; i++)
549                         dst[i] = src[i];
550
551                 dst[VPU_REG_EN_DEC_PP]   = src[VPU_REG_EN_DEC_PP] | 0x2;
552                 dsb();
553
554                 dst[VPU_REG_DEC_PP_GATE] = src[VPU_REG_DEC_PP_GATE] | VPU_REG_PP_GATE_BIT;
555                 dst[VPU_REG_DEC_GATE]    = src[VPU_REG_DEC_GATE]    | VPU_REG_DEC_GATE_BIT;
556                 dst[VPU_REG_EN_DEC]      = src[VPU_REG_EN_DEC];
557         } break;
558         default : {
559                 pr_err("error: unsupport session type %d", reg->type);
560                 atomic_sub(1, &service.total_running);
561                 atomic_sub(1, &reg->session->task_running);
562                 break;
563         }
564         }
565 }
566
567 static void try_set_reg(void)
568 {
569         unsigned long flag;
570         // first get reg from reg list
571         spin_lock_irqsave(&service.lock, flag);
572         if (!list_empty(&service.waiting)) {
573                 int can_set = 0;
574                 vpu_reg *reg = list_entry(service.waiting.next, vpu_reg, status_link);
575
576                 vpu_service_power_maintain();
577                 switch (reg->type) {
578                 case VPU_ENC : {
579                         if ((NULL == service.reg_codec) &&  (NULL == service.reg_pproc))
580                         can_set = 1;
581                 } break;
582                 case VPU_DEC : {
583                         if (NULL == service.reg_codec)
584                                 can_set = 1;
585                 } break;
586                 case VPU_PP : {
587                         if (NULL == service.reg_codec) {
588                                 if (NULL == service.reg_pproc)
589                                         can_set = 1;
590                         } else {
591                                 if ((VPU_DEC == service.reg_codec->type) && (NULL == service.reg_pproc))
592                                         can_set = 1;
593                         }
594                 } break;
595                 case VPU_DEC_PP : {
596                         if ((NULL == service.reg_codec) && (NULL == service.reg_pproc))
597                                 can_set = 1;
598                         } break;
599                 default : {
600                         printk("undefined reg type %d\n", reg->type);
601                 } break;
602                 }
603                 if (can_set) {
604                         reg_from_wait_to_run(reg);
605                         reg_copy_to_hw(reg);
606                 }
607         }
608         spin_unlock_irqrestore(&service.lock, flag);
609 }
610
611 static int return_reg(vpu_reg *reg, u32 __user *dst)
612 {
613         int ret = 0;
614         switch (reg->type) {
615         case VPU_ENC : {
616                 if (copy_to_user(dst, &reg->reg[0], service.hw_info->enc_io_size))
617                         ret = -EFAULT;
618                 break;
619         }
620         case VPU_DEC : {
621                 if (copy_to_user(dst, &reg->reg[0], SIZE_REG(REG_NUM_9190_DEC)))
622                         ret = -EFAULT;
623                 break;
624         }
625         case VPU_PP : {
626                 if (copy_to_user(dst, &reg->reg[0], SIZE_REG(REG_NUM_9190_PP)))
627                         ret = -EFAULT;
628                 break;
629         }
630         case VPU_DEC_PP : {
631                 if (copy_to_user(dst, &reg->reg[0], SIZE_REG(REG_NUM_9190_DEC_PP)))
632                         ret = -EFAULT;
633                 break;
634         }
635         default : {
636                 ret = -EFAULT;
637                 pr_err("error: copy reg to user with unknown type %d\n", reg->type);
638                 break;
639         }
640         }
641         reg_deinit(reg);
642         return ret;
643 }
644
645 static long vpu_service_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
646 {
647         vpu_session *session = (vpu_session *)filp->private_data;
648         if (NULL == session) {
649                 return -EINVAL;
650         }
651
652         switch (cmd) {
653         case VPU_IOC_SET_CLIENT_TYPE : {
654                 session->type = (VPU_CLIENT_TYPE)arg;
655                 break;
656         }
657         case VPU_IOC_GET_HW_FUSE_STATUS : {
658                 vpu_request req;
659                 if (copy_from_user(&req, (void __user *)arg, sizeof(vpu_request))) {
660                         pr_err("error: VPU_IOC_GET_HW_FUSE_STATUS copy_from_user failed\n");
661                         return -EFAULT;
662                 } else {
663                         if (VPU_ENC != session->type) {
664                                 if (copy_to_user((void __user *)req.req, &service.dec_config, sizeof(VPUHwDecConfig_t))) {
665                                         pr_err("error: VPU_IOC_GET_HW_FUSE_STATUS copy_to_user failed type %d\n", session->type);
666                                         return -EFAULT;
667                                 }
668                         } else {
669                                 if (copy_to_user((void __user *)req.req, &service.enc_config, sizeof(VPUHwEncConfig_t))) {
670                                         pr_err("error: VPU_IOC_GET_HW_FUSE_STATUS copy_to_user failed type %d\n", session->type);
671                                         return -EFAULT;
672                                 }
673                         }
674                 }
675
676                 break;
677         }
678         case VPU_IOC_SET_REG : {
679                 vpu_request req;
680                 vpu_reg *reg;
681                 if (copy_from_user(&req, (void __user *)arg, sizeof(vpu_request))) {
682                         pr_err("error: VPU_IOC_SET_REG copy_from_user failed\n");
683                         return -EFAULT;
684                 }
685
686                 reg = reg_init(session, (void __user *)req.req, req.size);
687                 if (NULL == reg) {
688                         return -EFAULT;
689                 } else {
690                         vpu_service_power_on();
691                         try_set_reg();
692                 }
693
694                 break;
695         }
696         case VPU_IOC_GET_REG : {
697                 vpu_request req;
698                 vpu_reg *reg;
699                 unsigned long flag;
700                 if (copy_from_user(&req, (void __user *)arg, sizeof(vpu_request))) {
701                         pr_err("error: VPU_IOC_GET_REG copy_from_user failed\n");
702                         return -EFAULT;
703                 } else {
704                         int ret = wait_event_interruptible_timeout(session->wait, !list_empty(&session->done), TIMEOUT_DELAY);
705                         if (!list_empty(&session->done)) {
706                                 if (ret < 0) {
707                                         pr_err("warning: pid %d wait task sucess but wait_evernt ret %d\n", session->pid, ret);
708                                 }
709                                 ret = 0;
710                         } else {
711                                 if (unlikely(ret < 0)) {
712                                         pr_err("error: pid %d wait task ret %d\n", session->pid, ret);
713                                 } else if (0 == ret) {
714                                         pr_err("error: pid %d wait %d task done timeout\n", session->pid, atomic_read(&session->task_running));
715                                         ret = -ETIMEDOUT;
716                                 }
717                         }
718                         spin_lock_irqsave(&service.lock, flag);
719                         if (ret < 0) {
720                                 int task_running = atomic_read(&session->task_running);
721                                 vpu_service_dump();
722                                 if (task_running) {
723                                         atomic_set(&session->task_running, 0);
724                                         atomic_sub(task_running, &service.total_running);
725                                         printk("%d task is running but not return, reset hardware...", task_running);
726                                         vpu_reset();
727                                         printk("done\n");
728                                 }
729                                 vpu_service_session_clear(session);
730                                 spin_unlock_irqrestore(&service.lock, flag);
731                                 return ret;
732                         }
733                         spin_unlock_irqrestore(&service.lock, flag);
734                 }
735                 spin_lock_irqsave(&service.lock, flag);
736                 reg = list_entry(session->done.next, vpu_reg, session_link);
737                 return_reg(reg, (u32 __user *)req.req);
738                 spin_unlock_irqrestore(&service.lock, flag);
739                 break;
740         }
741         default : {
742                 pr_err("error: unknow vpu service ioctl cmd %x\n", cmd);
743                 break;
744         }
745         }
746
747         return 0;
748 }
749
750 static int vpu_service_check_hw(vpu_service_info *p, unsigned long hw_addr)
751 {
752         int ret = -EINVAL, i = 0;
753         volatile u32 *tmp = (volatile u32 *)ioremap_nocache(hw_addr, 0x4);
754         u32 enc_id = *tmp;
755         enc_id = (enc_id >> 16) & 0xFFFF;
756         pr_info("checking hw id %x\n", enc_id);
757         p->hw_info = NULL;
758         for (i = 0; i < ARRAY_SIZE(vpu_hw_set); i++) {
759                 if (enc_id == vpu_hw_set[i].hw_id) {
760                         p->hw_info = &vpu_hw_set[i];
761                         ret = 0;
762                         break;
763                 }
764         }
765         iounmap((void *)tmp);
766         return ret;
767 }
768
769 static void vpu_service_release_io(void)
770 {
771         if (dec_dev.hwregs) {
772                 iounmap((void *)dec_dev.hwregs);
773                 dec_dev.hwregs = NULL;
774         }
775         if (dec_dev.iobaseaddr) {
776                 release_mem_region(dec_dev.iobaseaddr, dec_dev.iosize);
777                 dec_dev.iobaseaddr = 0;
778                 dec_dev.iosize = 0;
779         }
780
781         if (enc_dev.hwregs) {
782                 iounmap((void *)enc_dev.hwregs);
783                 enc_dev.hwregs = NULL;
784         }
785         if (enc_dev.iobaseaddr) {
786                 release_mem_region(enc_dev.iobaseaddr, enc_dev.iosize);
787                 enc_dev.iobaseaddr = 0;
788                 enc_dev.iosize = 0;
789         }
790 }
791
792 static int vpu_service_reserve_io(void)
793 {
794         unsigned long iobaseaddr;
795         unsigned long iosize;
796
797         iobaseaddr      = dec_dev.iobaseaddr;
798         iosize          = dec_dev.iosize;
799
800         if (!request_mem_region(iobaseaddr, iosize, "vdpu_io")) {
801                 pr_info("failed to reserve dec HW regs\n");
802                 return -EBUSY;
803         }
804
805         dec_dev.hwregs = (volatile u32 *)ioremap_nocache(iobaseaddr, iosize);
806
807         if (dec_dev.hwregs == NULL) {
808                 pr_info("failed to ioremap dec HW regs\n");
809                 goto err;
810         }
811
812         iobaseaddr      = enc_dev.iobaseaddr;
813         iosize          = enc_dev.iosize;
814
815         if (!request_mem_region(iobaseaddr, iosize, "vepu_io")) {
816                 pr_info("failed to reserve enc HW regs\n");
817                 goto err;
818         }
819
820         enc_dev.hwregs = (volatile u32 *)ioremap_nocache(iobaseaddr, iosize);
821
822         if (enc_dev.hwregs == NULL) {
823                 pr_info("failed to ioremap enc HW regs\n");
824                 goto err;
825         }
826
827         return 0;
828
829 err:
830         return -EBUSY;
831 }
832
833 static int vpu_service_open(struct inode *inode, struct file *filp)
834 {
835         unsigned long flag;
836         vpu_session *session = (vpu_session *)kmalloc(sizeof(vpu_session), GFP_KERNEL);
837         if (NULL == session) {
838                 pr_err("error: unable to allocate memory for vpu_session.");
839                 return -ENOMEM;
840         }
841
842         session->type   = VPU_TYPE_BUTT;
843         session->pid    = current->pid;
844         INIT_LIST_HEAD(&session->waiting);
845         INIT_LIST_HEAD(&session->running);
846         INIT_LIST_HEAD(&session->done);
847         INIT_LIST_HEAD(&session->list_session);
848         init_waitqueue_head(&session->wait);
849         atomic_set(&session->task_running, 0);
850         spin_lock_irqsave(&service.lock, flag);
851         list_add_tail(&session->list_session, &service.session);
852         filp->private_data = (void *)session;
853         spin_unlock_irqrestore(&service.lock, flag);
854
855         pr_debug("dev opened\n");
856         return nonseekable_open(inode, filp);
857 }
858
859 static int vpu_service_release(struct inode *inode, struct file *filp)
860 {
861         int task_running;
862         unsigned long flag;
863         vpu_session *session = (vpu_session *)filp->private_data;
864         if (NULL == session)
865                 return -EINVAL;
866
867         task_running = atomic_read(&session->task_running);
868         if (task_running) {
869                 pr_err("error: vpu_service session %d still has %d task running when closing\n", session->pid, task_running);
870                 msleep(50);
871         }
872         wake_up_interruptible_sync(&session->wait);
873
874         spin_lock_irqsave(&service.lock, flag);
875         /* remove this filp from the asynchronusly notified filp's */
876         //vpu_service_fasync(-1, filp, 0);
877         list_del_init(&session->list_session);
878         vpu_service_session_clear(session);
879         kfree(session);
880         filp->private_data = NULL;
881         spin_unlock_irqrestore(&service.lock, flag);
882
883         pr_debug("dev closed\n");
884         return 0;
885 }
886
887 static const struct file_operations vpu_service_fops = {
888         .unlocked_ioctl = vpu_service_ioctl,
889         .open           = vpu_service_open,
890         .release        = vpu_service_release,
891         //.fasync       = vpu_service_fasync,
892 };
893
894 static struct miscdevice vpu_service_misc_device = {
895         .minor          = MISC_DYNAMIC_MINOR,
896         .name           = "vpu_service",
897         .fops           = &vpu_service_fops,
898 };
899
900 static void vpu_service_shutdown(struct platform_device *pdev)
901 {
902         pr_cont("shutdown...");
903         del_timer(&service.timer);
904         vpu_service_power_off();
905         pr_cont("done\n");
906 }
907
908 static int vpu_service_suspend(struct platform_device *pdev, pm_message_t state)
909 {
910         bool enabled;
911         pr_info("suspend...");
912         del_timer(&service.timer);
913         enabled = service.enabled;
914         vpu_service_power_off();
915         service.enabled = enabled;
916         return 0;
917 }
918
919 static int vpu_service_resume(struct platform_device *pdev)
920 {
921         pr_info("resume...");
922         if (service.enabled) {
923                 service.enabled = false;
924                 vpu_service_power_on();
925                 try_set_reg();
926         }
927         return 0;
928 }
929
930 static struct platform_device vpu_service_device = {
931         .name              = "vpu_service",
932         .id                = -1,
933 };
934
935 static struct platform_driver vpu_service_driver = {
936         .driver    = {
937                 .name  = "vpu_service",
938                 .owner = THIS_MODULE,
939         },
940         .shutdown  = vpu_service_shutdown,
941         .suspend   = vpu_service_suspend,
942         .resume    = vpu_service_resume,
943 };
944
945 static void get_hw_info(void)
946 {
947         VPUHwDecConfig_t *dec = &service.dec_config;
948         VPUHwEncConfig_t *enc = &service.enc_config;
949         u32 configReg   = dec_dev.hwregs[VPU_DEC_HWCFG0];
950         u32 asicID      = dec_dev.hwregs[0];
951
952         dec->h264Support    = (configReg >> DWL_H264_E) & 0x3U;
953         dec->jpegSupport    = (configReg >> DWL_JPEG_E) & 0x01U;
954         if (dec->jpegSupport && ((configReg >> DWL_PJPEG_E) & 0x01U))
955                 dec->jpegSupport = JPEG_PROGRESSIVE;
956         dec->mpeg4Support   = (configReg >> DWL_MPEG4_E) & 0x3U;
957         dec->vc1Support     = (configReg >> DWL_VC1_E) & 0x3U;
958         dec->mpeg2Support   = (configReg >> DWL_MPEG2_E) & 0x01U;
959         dec->sorensonSparkSupport = (configReg >> DWL_SORENSONSPARK_E) & 0x01U;
960         dec->refBufSupport  = (configReg >> DWL_REF_BUFF_E) & 0x01U;
961         dec->vp6Support     = (configReg >> DWL_VP6_E) & 0x01U;
962         dec->maxDecPicWidth = configReg & 0x07FFU;
963
964         /* 2nd Config register */
965         configReg   = dec_dev.hwregs[VPU_DEC_HWCFG1];
966         if (dec->refBufSupport) {
967                 if ((configReg >> DWL_REF_BUFF_ILACE_E) & 0x01U)
968                         dec->refBufSupport |= 2;
969                 if ((configReg >> DWL_REF_BUFF_DOUBLE_E) & 0x01U)
970                         dec->refBufSupport |= 4;
971         }
972         dec->customMpeg4Support = (configReg >> DWL_MPEG4_CUSTOM_E) & 0x01U;
973         dec->vp7Support     = (configReg >> DWL_VP7_E) & 0x01U;
974         dec->vp8Support     = (configReg >> DWL_VP8_E) & 0x01U;
975         dec->avsSupport     = (configReg >> DWL_AVS_E) & 0x01U;
976
977         /* JPEG xtensions */
978         if (((asicID >> 16) >= 0x8190U) || ((asicID >> 16) == 0x6731U)) {
979                 dec->jpegESupport = (configReg >> DWL_JPEG_EXT_E) & 0x01U;
980         } else {
981                 dec->jpegESupport = JPEG_EXT_NOT_SUPPORTED;
982         }
983
984         if (((asicID >> 16) >= 0x9170U) || ((asicID >> 16) == 0x6731U) ) {
985                 dec->rvSupport = (configReg >> DWL_RV_E) & 0x03U;
986         } else {
987                 dec->rvSupport = RV_NOT_SUPPORTED;
988         }
989
990         dec->mvcSupport = (configReg >> DWL_MVC_E) & 0x03U;
991
992         if (dec->refBufSupport && (asicID >> 16) == 0x6731U ) {
993                 dec->refBufSupport |= 8; /* enable HW support for offset */
994         }
995
996         {
997         VPUHwFuseStatus_t hwFuseSts;
998         /* Decoder fuse configuration */
999         u32 fuseReg = dec_dev.hwregs[VPU_DEC_HW_FUSE_CFG];
1000
1001         hwFuseSts.h264SupportFuse = (fuseReg >> DWL_H264_FUSE_E) & 0x01U;
1002         hwFuseSts.mpeg4SupportFuse = (fuseReg >> DWL_MPEG4_FUSE_E) & 0x01U;
1003         hwFuseSts.mpeg2SupportFuse = (fuseReg >> DWL_MPEG2_FUSE_E) & 0x01U;
1004         hwFuseSts.sorensonSparkSupportFuse = (fuseReg >> DWL_SORENSONSPARK_FUSE_E) & 0x01U;
1005         hwFuseSts.jpegSupportFuse = (fuseReg >> DWL_JPEG_FUSE_E) & 0x01U;
1006         hwFuseSts.vp6SupportFuse = (fuseReg >> DWL_VP6_FUSE_E) & 0x01U;
1007         hwFuseSts.vc1SupportFuse = (fuseReg >> DWL_VC1_FUSE_E) & 0x01U;
1008         hwFuseSts.jpegProgSupportFuse = (fuseReg >> DWL_PJPEG_FUSE_E) & 0x01U;
1009         hwFuseSts.rvSupportFuse = (fuseReg >> DWL_RV_FUSE_E) & 0x01U;
1010         hwFuseSts.avsSupportFuse = (fuseReg >> DWL_AVS_FUSE_E) & 0x01U;
1011         hwFuseSts.vp7SupportFuse = (fuseReg >> DWL_VP7_FUSE_E) & 0x01U;
1012         hwFuseSts.vp8SupportFuse = (fuseReg >> DWL_VP8_FUSE_E) & 0x01U;
1013         hwFuseSts.customMpeg4SupportFuse = (fuseReg >> DWL_CUSTOM_MPEG4_FUSE_E) & 0x01U;
1014         hwFuseSts.mvcSupportFuse = (fuseReg >> DWL_MVC_FUSE_E) & 0x01U;
1015
1016         /* check max. decoder output width */
1017
1018         if (fuseReg & 0x8000U)
1019                 hwFuseSts.maxDecPicWidthFuse = 1920;
1020         else if (fuseReg & 0x4000U)
1021                 hwFuseSts.maxDecPicWidthFuse = 1280;
1022         else if (fuseReg & 0x2000U)
1023                 hwFuseSts.maxDecPicWidthFuse = 720;
1024         else if (fuseReg & 0x1000U)
1025                 hwFuseSts.maxDecPicWidthFuse = 352;
1026         else    /* remove warning */
1027                 hwFuseSts.maxDecPicWidthFuse = 352;
1028
1029         hwFuseSts.refBufSupportFuse = (fuseReg >> DWL_REF_BUFF_FUSE_E) & 0x01U;
1030
1031         /* Pp configuration */
1032         configReg = dec_dev.hwregs[VPU_PP_HW_SYNTH_CFG];
1033
1034         if ((configReg >> DWL_PP_E) & 0x01U) {
1035                 dec->ppSupport = 1;
1036                 dec->maxPpOutPicWidth = configReg & 0x07FFU;
1037                 /*pHwCfg->ppConfig = (configReg >> DWL_CFG_E) & 0x0FU; */
1038                 dec->ppConfig = configReg;
1039         } else {
1040                 dec->ppSupport = 0;
1041                 dec->maxPpOutPicWidth = 0;
1042                 dec->ppConfig = 0;
1043         }
1044
1045         /* check the HW versio */
1046         if (((asicID >> 16) >= 0x8190U) || ((asicID >> 16) == 0x6731U)) {
1047                 /* Pp configuration */
1048                 configReg = dec_dev.hwregs[VPU_DEC_HW_FUSE_CFG];
1049
1050                 if ((configReg >> DWL_PP_E) & 0x01U) {
1051                         /* Pp fuse configuration */
1052                         u32 fuseRegPp = dec_dev.hwregs[VPU_PP_HW_FUSE_CFG];
1053
1054                         if ((fuseRegPp >> DWL_PP_FUSE_E) & 0x01U) {
1055                                 hwFuseSts.ppSupportFuse = 1;
1056                                 /* check max. pp output width */
1057                                 if      (fuseRegPp & 0x8000U) hwFuseSts.maxPpOutPicWidthFuse = 1920;
1058                                 else if (fuseRegPp & 0x4000U) hwFuseSts.maxPpOutPicWidthFuse = 1280;
1059                                 else if (fuseRegPp & 0x2000U) hwFuseSts.maxPpOutPicWidthFuse = 720;
1060                                 else if (fuseRegPp & 0x1000U) hwFuseSts.maxPpOutPicWidthFuse = 352;
1061                                 else                          hwFuseSts.maxPpOutPicWidthFuse = 352;
1062                                 hwFuseSts.ppConfigFuse = fuseRegPp;
1063                         } else {
1064                                 hwFuseSts.ppSupportFuse = 0;
1065                                 hwFuseSts.maxPpOutPicWidthFuse = 0;
1066                                 hwFuseSts.ppConfigFuse = 0;
1067                         }
1068                 } else {
1069                         hwFuseSts.ppSupportFuse = 0;
1070                         hwFuseSts.maxPpOutPicWidthFuse = 0;
1071                         hwFuseSts.ppConfigFuse = 0;
1072                 }
1073
1074                 if (dec->maxDecPicWidth > hwFuseSts.maxDecPicWidthFuse)
1075                         dec->maxDecPicWidth = hwFuseSts.maxDecPicWidthFuse;
1076                 if (dec->maxPpOutPicWidth > hwFuseSts.maxPpOutPicWidthFuse)
1077                         dec->maxPpOutPicWidth = hwFuseSts.maxPpOutPicWidthFuse;
1078                 if (!hwFuseSts.h264SupportFuse) dec->h264Support = H264_NOT_SUPPORTED;
1079                 if (!hwFuseSts.mpeg4SupportFuse) dec->mpeg4Support = MPEG4_NOT_SUPPORTED;
1080                 if (!hwFuseSts.customMpeg4SupportFuse) dec->customMpeg4Support = MPEG4_CUSTOM_NOT_SUPPORTED;
1081                 if (!hwFuseSts.jpegSupportFuse) dec->jpegSupport = JPEG_NOT_SUPPORTED;
1082                 if ((dec->jpegSupport == JPEG_PROGRESSIVE) && !hwFuseSts.jpegProgSupportFuse)
1083                         dec->jpegSupport = JPEG_BASELINE;
1084                 if (!hwFuseSts.mpeg2SupportFuse) dec->mpeg2Support = MPEG2_NOT_SUPPORTED;
1085                 if (!hwFuseSts.vc1SupportFuse) dec->vc1Support = VC1_NOT_SUPPORTED;
1086                 if (!hwFuseSts.vp6SupportFuse) dec->vp6Support = VP6_NOT_SUPPORTED;
1087                 if (!hwFuseSts.vp7SupportFuse) dec->vp7Support = VP7_NOT_SUPPORTED;
1088                 if (!hwFuseSts.vp8SupportFuse) dec->vp8Support = VP8_NOT_SUPPORTED;
1089                 if (!hwFuseSts.ppSupportFuse) dec->ppSupport = PP_NOT_SUPPORTED;
1090
1091                 /* check the pp config vs fuse status */
1092                 if ((dec->ppConfig & 0xFC000000) && ((hwFuseSts.ppConfigFuse & 0xF0000000) >> 5)) {
1093                         u32 deInterlace = ((dec->ppConfig & PP_DEINTERLACING) >> 25);
1094                         u32 alphaBlend  = ((dec->ppConfig & PP_ALPHA_BLENDING) >> 24);
1095                         u32 deInterlaceFuse = (((hwFuseSts.ppConfigFuse >> 5) & PP_DEINTERLACING) >> 25);
1096                         u32 alphaBlendFuse  = (((hwFuseSts.ppConfigFuse >> 5) & PP_ALPHA_BLENDING) >> 24);
1097
1098                         if (deInterlace && !deInterlaceFuse) dec->ppConfig &= 0xFD000000;
1099                         if (alphaBlend && !alphaBlendFuse) dec->ppConfig &= 0xFE000000;
1100                 }
1101                 if (!hwFuseSts.sorensonSparkSupportFuse) dec->sorensonSparkSupport = SORENSON_SPARK_NOT_SUPPORTED;
1102                 if (!hwFuseSts.refBufSupportFuse)   dec->refBufSupport = REF_BUF_NOT_SUPPORTED;
1103                 if (!hwFuseSts.rvSupportFuse)       dec->rvSupport = RV_NOT_SUPPORTED;
1104                 if (!hwFuseSts.avsSupportFuse)      dec->avsSupport = AVS_NOT_SUPPORTED;
1105                 if (!hwFuseSts.mvcSupportFuse)      dec->mvcSupport = MVC_NOT_SUPPORTED;
1106         }
1107         }
1108         configReg = enc_dev.hwregs[63];
1109         enc->maxEncodedWidth = configReg & ((1 << 11) - 1);
1110         enc->h264Enabled = (configReg >> 27) & 1;
1111         enc->mpeg4Enabled = (configReg >> 26) & 1;
1112         enc->jpegEnabled = (configReg >> 25) & 1;
1113         enc->vsEnabled = (configReg >> 24) & 1;
1114         enc->rgbEnabled = (configReg >> 28) & 1;
1115         //enc->busType = (configReg >> 20) & 15;
1116         //enc->synthesisLanguage = (configReg >> 16) & 15;
1117         //enc->busWidth = (configReg >> 12) & 15;
1118         enc->reg_size = service.reg_size;
1119         enc->reserv[0] = enc->reserv[1] = 0;
1120 }
1121
1122 static irqreturn_t vdpu_isr(int irq, void *dev_id)
1123 {
1124         vpu_device *dev = (vpu_device *) dev_id;
1125         u32 irq_status_dec = readl(dev->hwregs + DEC_INTERRUPT_REGISTER);
1126         u32 irq_status_pp  = readl(dev->hwregs + PP_INTERRUPT_REGISTER);
1127
1128         pr_debug("vdpu_isr dec %x pp %x\n", irq_status_dec, irq_status_pp);
1129
1130         if (irq_status_dec & DEC_INTERRUPT_BIT) {
1131                 irq_status_dec = readl(dev->hwregs + DEC_INTERRUPT_REGISTER);
1132                 if ((irq_status_dec & 0x40001) == 0x40001)
1133                 {
1134                         do {
1135                                 irq_status_dec = readl(dev->hwregs + DEC_INTERRUPT_REGISTER);
1136                         } while ((irq_status_dec & 0x40001) == 0x40001);
1137                 }
1138                 /* clear dec IRQ */
1139                 writel(irq_status_dec & (~DEC_INTERRUPT_BIT), dev->hwregs + DEC_INTERRUPT_REGISTER);
1140                 pr_debug("DEC IRQ received!\n");
1141                 spin_lock(&service.lock);
1142                 if (NULL == service.reg_codec) {
1143                         pr_err("error: dec isr with no task waiting\n");
1144                 } else {
1145                         reg_from_run_to_done(service.reg_codec);
1146                 }
1147                 spin_unlock(&service.lock);
1148         }
1149
1150         if (irq_status_pp & PP_INTERRUPT_BIT) {
1151                 /* clear pp IRQ */
1152                 writel(irq_status_pp & (~DEC_INTERRUPT_BIT), dev->hwregs + PP_INTERRUPT_REGISTER);
1153                 pr_debug("PP IRQ received!\n");
1154                 spin_lock(&service.lock);
1155                 if (NULL == service.reg_pproc) {
1156                         pr_err("error: pp isr with no task waiting\n");
1157                 } else {
1158                         reg_from_run_to_done(service.reg_pproc);
1159                 }
1160                 spin_unlock(&service.lock);
1161         }
1162         try_set_reg();
1163         return IRQ_HANDLED;
1164 }
1165
1166 static irqreturn_t vepu_isr(int irq, void *dev_id)
1167 {
1168         struct vpu_device *dev = (struct vpu_device *) dev_id;
1169         u32 irq_status = readl(dev->hwregs + ENC_INTERRUPT_REGISTER);
1170
1171         pr_debug("enc_isr\n");
1172
1173         if (likely(irq_status & ENC_INTERRUPT_BIT)) {
1174                 /* clear enc IRQ */
1175                 writel(irq_status & (~ENC_INTERRUPT_BIT), dev->hwregs + ENC_INTERRUPT_REGISTER);
1176                 pr_debug("ENC IRQ received!\n");
1177                 spin_lock(&service.lock);
1178                 if (NULL == service.reg_codec) {
1179                         pr_err("error: enc isr with no task waiting\n");
1180                 } else {
1181                         reg_from_run_to_done(service.reg_codec);
1182                 }
1183                 spin_unlock(&service.lock);
1184         }
1185         try_set_reg();
1186         return IRQ_HANDLED;
1187 }
1188
1189 static int __init vpu_service_proc_init(void);
1190 static int __init vpu_service_init(void)
1191 {
1192         int ret;
1193
1194         pr_debug("baseaddr = 0x%08x vdpu irq = %d vepu irq = %d\n", VCODEC_PHYS, IRQ_VDPU, IRQ_VEPU);
1195
1196         INIT_LIST_HEAD(&service.waiting);
1197         INIT_LIST_HEAD(&service.running);
1198         INIT_LIST_HEAD(&service.done);
1199         INIT_LIST_HEAD(&service.session);
1200         spin_lock_init(&service.lock);
1201         spin_lock_init(&service.lock_power);
1202         service.reg_codec       = NULL;
1203         service.reg_pproc       = NULL;
1204         atomic_set(&service.total_running, 0);
1205         service.enabled         = false;
1206
1207         vpu_get_clk();
1208         init_timer(&service.timer);
1209         service.timer.expires = jiffies + POWER_OFF_DELAY;
1210         service.timer.function = vpu_service_power_off_work_func;
1211         vpu_service_power_on();
1212         ret = vpu_service_check_hw(&service, VCODEC_PHYS);
1213         if (ret < 0) {
1214                 pr_err("error: hw info check faild\n");
1215                 goto err_hw_id_check;
1216         }
1217
1218         dec_dev.iobaseaddr      = service.hw_info->hw_addr + service.hw_info->dec_offset;
1219         dec_dev.iosize          = service.hw_info->dec_io_size;
1220         enc_dev.iobaseaddr      = service.hw_info->hw_addr + service.hw_info->enc_offset;
1221         enc_dev.iosize          = service.hw_info->enc_io_size;;
1222         service.reg_size        = max(dec_dev.iosize, enc_dev.iosize);
1223
1224         ret = vpu_service_reserve_io();
1225         if (ret < 0) {
1226                 pr_err("error: reserve io failed\n");
1227                 goto err_reserve_io;
1228         }
1229
1230         /* get the IRQ line */
1231         ret = request_irq(IRQ_VDPU, vdpu_isr, IRQF_SHARED, "vdpu", (void *)&dec_dev);
1232         if (ret) {
1233                 pr_err("error: can't request vdpu irq %d\n", IRQ_VDPU);
1234                 goto err_req_vdpu_irq;
1235         }
1236
1237         ret = request_irq(IRQ_VEPU, vepu_isr, IRQF_SHARED, "vepu", (void *)&enc_dev);
1238         if (ret) {
1239                 pr_err("error: can't request vepu irq %d\n", IRQ_VEPU);
1240                 goto err_req_vepu_irq;
1241         }
1242
1243         ret = misc_register(&vpu_service_misc_device);
1244         if (ret) {
1245                 pr_err("error: misc_register failed\n");
1246                 goto err_register;
1247         }
1248
1249         platform_device_register(&vpu_service_device);
1250         platform_driver_probe(&vpu_service_driver, NULL);
1251         get_hw_info();
1252         del_timer(&service.timer);
1253         vpu_service_power_off();
1254         pr_info("init success\n");
1255
1256         vpu_service_proc_init();
1257         return 0;
1258
1259 err_register:
1260         free_irq(IRQ_VEPU, (void *)&enc_dev);
1261 err_req_vepu_irq:
1262         free_irq(IRQ_VDPU, (void *)&dec_dev);
1263 err_req_vdpu_irq:
1264         pr_info("init failed\n");
1265 err_reserve_io:
1266         vpu_service_release_io();
1267 err_hw_id_check:
1268         vpu_service_power_off();
1269         vpu_put_clk();
1270         pr_info("init failed\n");
1271         return ret;
1272 }
1273
1274 static void __exit vpu_service_proc_release(void);
1275 static void __exit vpu_service_exit(void)
1276 {
1277         vpu_service_proc_release();
1278         del_timer(&service.timer);
1279         vpu_service_power_off();
1280         platform_device_unregister(&vpu_service_device);
1281         platform_driver_unregister(&vpu_service_driver);
1282         misc_deregister(&vpu_service_misc_device);
1283         free_irq(IRQ_VEPU, (void *)&enc_dev);
1284         free_irq(IRQ_VDPU, (void *)&dec_dev);
1285         vpu_service_release_io();
1286         vpu_put_clk();
1287 }
1288
1289 module_init(vpu_service_init);
1290 module_exit(vpu_service_exit);
1291
1292 #ifdef CONFIG_PROC_FS
1293 #include <linux/proc_fs.h>
1294 #include <linux/seq_file.h>
1295
1296 static int proc_vpu_service_show(struct seq_file *s, void *v)
1297 {
1298         unsigned int i, n;
1299         unsigned long flag;
1300         vpu_reg *reg, *reg_tmp;
1301         vpu_session *session, *session_tmp;
1302
1303         vpu_service_power_on();
1304         seq_printf(s, "\nENC Registers:\n");
1305         n = enc_dev.iosize >> 2;
1306         for (i = 0; i < n; i++) {
1307                 seq_printf(s, "\tswreg%d = %08X\n", i, readl(enc_dev.hwregs + i));
1308         }
1309         seq_printf(s, "\nDEC Registers:\n");
1310         n = dec_dev.iosize >> 2;
1311         for (i = 0; i < n; i++) {
1312                 seq_printf(s, "\tswreg%d = %08X\n", i, readl(dec_dev.hwregs + i));
1313         }
1314
1315         seq_printf(s, "\nvpu service status:\n");
1316         spin_lock_irqsave(&service.lock, flag);
1317         list_for_each_entry_safe(session, session_tmp, &service.session, list_session) {
1318                 seq_printf(s, "session pid %d type %d:\n", session->pid, session->type);
1319                 //seq_printf(s, "waiting reg set %d\n");
1320                 list_for_each_entry_safe(reg, reg_tmp, &session->waiting, session_link) {
1321                         seq_printf(s, "waiting register set\n");
1322                 }
1323                 list_for_each_entry_safe(reg, reg_tmp, &session->running, session_link) {
1324                         seq_printf(s, "running register set\n");
1325                 }
1326                 list_for_each_entry_safe(reg, reg_tmp, &session->done, session_link) {
1327                         seq_printf(s, "done    register set\n");
1328                 }
1329         }
1330         spin_unlock_irqrestore(&service.lock, flag);
1331
1332         return 0;
1333 }
1334
1335 static int proc_vpu_service_open(struct inode *inode, struct file *file)
1336 {
1337         return single_open(file, proc_vpu_service_show, NULL);
1338 }
1339
1340 static const struct file_operations proc_vpu_service_fops = {
1341         .open           = proc_vpu_service_open,
1342         .read           = seq_read,
1343         .llseek         = seq_lseek,
1344         .release        = single_release,
1345 };
1346
1347 static int __init vpu_service_proc_init(void)
1348 {
1349         proc_create("vpu_service", 0, NULL, &proc_vpu_service_fops);
1350         return 0;
1351
1352 }
1353 static void __exit vpu_service_proc_release(void)
1354 {
1355         remove_proc_entry("vpu_service", NULL);
1356 }
1357 #endif /* CONFIG_PROC_FS */
1358