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