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