1 /* arch/arm/mach-rk29/vpu.c
3 * Copyright (C) 2010 ROCKCHIP, Inc.
4 * author: chenhengming chm@rock-chips.com
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.
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.
17 #ifdef CONFIG_RK29_VPU_DEBUG
19 #define pr_fmt(fmt) "VPU_SERVICE: %s: " fmt, __func__
21 #define pr_fmt(fmt) "VPU_SERVICE: " fmt
25 #include <linux/clk.h>
26 #include <linux/delay.h>
27 #include <linux/init.h>
28 #include <linux/interrupt.h>
30 #include <linux/kernel.h>
31 #include <linux/module.h>
33 #include <linux/ioport.h>
34 #include <linux/miscdevice.h>
36 #include <linux/poll.h>
37 #include <linux/platform_device.h>
38 #include <linux/slab.h>
39 #include <linux/timer.h>
41 #include <asm/uaccess.h>
43 #include <mach/irqs.h>
44 #include <mach/vpu_service.h>
45 #include <mach/rk29_iomap.h>
50 #define DEC_INTERRUPT_REGISTER 1
51 #define PP_INTERRUPT_REGISTER 60
52 #define ENC_INTERRUPT_REGISTER 1
54 #define DEC_INTERRUPT_BIT 0x100
55 #define PP_INTERRUPT_BIT 0x100
56 #define ENC_INTERRUPT_BIT 0x1
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)
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 static const u16 enc_hw_ids[] = { 0x6280, 0x7280, 0x8270 };
69 #define VPU_REG_EN_ENC 14
70 #define VPU_REG_ENC_GATE 2
71 #define VPU_REG_ENC_GATE_BIT (1<<4)
73 #define VPU_REG_EN_DEC 1
74 #define VPU_REG_DEC_GATE 2
75 #define VPU_REG_DEC_GATE_BIT (1<<10)
76 #define VPU_REG_EN_PP 0
77 #define VPU_REG_PP_GATE 1
78 #define VPU_REG_PP_GATE_BIT (1<<8)
79 #define VPU_REG_EN_DEC_PP 1
80 #define VPU_REG_DEC_PP_GATE 61
81 #define VPU_REG_DEC_PP_GATE_BIT (1<<8)
85 * struct for process session which connect to vpu
87 * @author ChenHengming (2011-5-3)
89 typedef struct vpu_session {
91 /* a linked list of data so we can access them for debugging */
92 struct list_head list_session;
93 /* a linked list of register data waiting for process */
94 struct list_head waiting;
95 /* a linked list of register data in processing */
96 struct list_head running;
97 /* a linked list of register data processed */
98 struct list_head done;
99 wait_queue_head_t wait;
101 atomic_t task_running;
105 * struct for process register set
107 * @author ChenHengming (2011-5-4)
109 typedef struct vpu_reg {
110 VPU_CLIENT_TYPE type;
111 vpu_session *session;
112 struct list_head session_link; /* link to vpu service session */
113 struct list_head status_link; /* link to register set list */
115 unsigned long reg[VPU_REG_NUM_DEC_PP];
118 typedef struct vpu_device {
119 unsigned long iobaseaddr;
121 volatile u32 *hwregs;
124 typedef struct vpu_service_info {
126 struct timer_list timer; /* timer for power off */
127 struct list_head waiting; /* link to link_reg in struct vpu_reg */
128 struct list_head running; /* link to link_reg in struct vpu_reg */
129 struct list_head done; /* link to link_reg in struct vpu_reg */
130 struct list_head session; /* link to list_session in struct vpu_session */
131 atomic_t total_running;
136 VPUHwDecConfig_t dec_config;
137 VPUHwEncConfig_t enc_config;
140 typedef struct vpu_request
146 static struct clk *aclk_vepu;
147 static struct clk *hclk_vepu;
148 static struct clk *aclk_ddr_vepu;
149 static struct clk *hclk_cpu_vcodec;
150 static vpu_service_info service;
151 static vpu_device dec_dev;
152 static vpu_device enc_dev;
154 #define POWER_OFF_DELAY 4*HZ /* 4s */
155 #define TIMEOUT_DELAY 2*HZ /* 2s */
157 static void vpu_get_clk(void)
159 aclk_vepu = clk_get(NULL, "aclk_vepu");
160 hclk_vepu = clk_get(NULL, "hclk_vepu");
161 aclk_ddr_vepu = clk_get(NULL, "aclk_ddr_vepu");
162 hclk_cpu_vcodec = clk_get(NULL, "hclk_cpu_vcodec");
165 static void vpu_put_clk(void)
169 clk_put(aclk_ddr_vepu);
170 clk_put(hclk_cpu_vcodec);
173 static void vpu_reset(void)
175 clk_disable(aclk_ddr_vepu);
176 cru_set_soft_reset(SOFT_RST_CPU_VODEC_A2A_AHB, true);
177 cru_set_soft_reset(SOFT_RST_DDR_VCODEC_PORT, true);
178 cru_set_soft_reset(SOFT_RST_VCODEC_AHB_BUS, true);
179 cru_set_soft_reset(SOFT_RST_VCODEC_AXI_BUS, true);
181 cru_set_soft_reset(SOFT_RST_VCODEC_AXI_BUS, false);
182 cru_set_soft_reset(SOFT_RST_VCODEC_AHB_BUS, false);
183 cru_set_soft_reset(SOFT_RST_DDR_VCODEC_PORT, false);
184 cru_set_soft_reset(SOFT_RST_CPU_VODEC_A2A_AHB, false);
185 clk_enable(aclk_ddr_vepu);
186 service.reg_codec = NULL;
187 service.reg_pproc = NULL;
188 service.reg_resev = NULL;
191 static void reg_deinit(vpu_reg *reg);
192 static void vpu_service_session_clear(vpu_session *session)
195 list_for_each_entry_safe(reg, n, &session->waiting, session_link) {
198 list_for_each_entry_safe(reg, n, &session->running, session_link) {
201 list_for_each_entry_safe(reg, n, &session->done, session_link) {
206 static void vpu_service_dump(void)
209 vpu_reg *reg, *reg_tmp;
210 vpu_session *session, *session_tmp;
212 running = atomic_read(&service.total_running);
213 printk("total_running %d\n", running);
215 printk("reg_codec 0x%.8x\n", (unsigned int)service.reg_codec);
216 printk("reg_pproc 0x%.8x\n", (unsigned int)service.reg_pproc);
217 printk("reg_resev 0x%.8x\n", (unsigned int)service.reg_resev);
219 list_for_each_entry_safe(session, session_tmp, &service.session, list_session) {
220 printk("session pid %d type %d:\n", session->pid, session->type);
221 running = atomic_read(&session->task_running);
222 printk("task_running %d\n", running);
223 list_for_each_entry_safe(reg, reg_tmp, &session->waiting, session_link) {
224 printk("waiting register set 0x%.8x\n", (unsigned int)reg);
226 list_for_each_entry_safe(reg, reg_tmp, &session->running, session_link) {
227 printk("running register set 0x%.8x\n", (unsigned int)reg);
229 list_for_each_entry_safe(reg, reg_tmp, &session->done, session_link) {
230 printk("done register set 0x%.8x\n", (unsigned int)reg);
235 static void vpu_service_power_off(void)
239 if (!service.enabled)
242 service.enabled = false;
243 total_running = atomic_read(&service.total_running);
245 pr_alert("power off when %d task running!!\n", total_running);
247 pr_alert("delay 50 ms for running task\n");
251 printk("vpu: power off...");
252 pmu_set_power_domain(PD_VCODEC, false);
254 clk_disable(hclk_cpu_vcodec);
255 clk_disable(aclk_ddr_vepu);
256 clk_disable(hclk_vepu);
257 clk_disable(aclk_vepu);
261 static void vpu_service_power_off_work_func(unsigned long data)
264 vpu_service_power_off();
267 static void vpu_service_power_maintain(void)
269 if (service.enabled) {
270 mod_timer(&service.timer, jiffies + POWER_OFF_DELAY);
272 pr_err("maintain power when power is off!\n");
276 static void vpu_service_power_on(void)
278 if (!service.enabled) {
279 service.enabled = true;
280 printk("vpu: power on\n");
282 clk_enable(aclk_vepu);
283 clk_enable(hclk_vepu);
284 clk_enable(hclk_cpu_vcodec);
286 pmu_set_power_domain(PD_VCODEC, true);
288 clk_enable(aclk_ddr_vepu);
289 init_timer(&service.timer);
290 service.timer.expires = jiffies + POWER_OFF_DELAY;
291 service.timer.function = vpu_service_power_off_work_func;
292 add_timer(&service.timer);
294 vpu_service_power_maintain();
298 static vpu_reg *reg_init(vpu_session *session, void __user *src, unsigned long size)
301 vpu_reg *reg = kmalloc(sizeof(vpu_reg), GFP_KERNEL);
303 pr_err("kmalloc fail in reg_init\n");
307 reg->session = session;
308 reg->type = session->type;
310 INIT_LIST_HEAD(®->session_link);
311 INIT_LIST_HEAD(®->status_link);
313 if (copy_from_user(®->reg[0], (void __user *)src, size)) {
314 pr_err("copy_from_user failed in reg_init\n");
319 spin_lock_irqsave(&service.lock, flag);
320 list_add_tail(®->status_link, &service.waiting);
321 list_add_tail(®->session_link, &session->waiting);
322 spin_unlock_irqrestore(&service.lock, flag);
327 static void reg_deinit(vpu_reg *reg)
329 list_del_init(®->session_link);
330 list_del_init(®->status_link);
332 if (reg == service.reg_codec) service.reg_codec = NULL;
333 if (reg == service.reg_pproc) service.reg_pproc = NULL;
336 static void reg_from_wait_to_run(vpu_reg *reg)
338 list_del_init(®->status_link);
339 list_add_tail(®->status_link, &service.running);
341 list_del_init(®->session_link);
342 list_add_tail(®->session_link, ®->session->running);
345 static void reg_copy_from_hw(vpu_reg *reg, volatile u32 *src, u32 count)
348 u32 *dst = (u32 *)®->reg[0];
349 for (i = 0; i < count; i++)
353 static void reg_from_run_to_done(vpu_reg *reg)
355 spin_lock(&service.lock);
356 list_del_init(®->status_link);
357 list_add_tail(®->status_link, &service.done);
359 list_del_init(®->session_link);
360 list_add_tail(®->session_link, ®->session->done);
364 service.reg_codec = NULL;
365 reg_copy_from_hw(reg, enc_dev.hwregs, REG_NUM_ENC);
369 service.reg_codec = NULL;
370 reg_copy_from_hw(reg, dec_dev.hwregs, REG_NUM_DEC);
374 service.reg_pproc = NULL;
375 reg_copy_from_hw(reg, dec_dev.hwregs + PP_INTERRUPT_REGISTER, REG_NUM_PP);
376 dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0;
380 service.reg_codec = NULL;
381 service.reg_pproc = NULL;
382 reg_copy_from_hw(reg, dec_dev.hwregs, REG_NUM_DEC_PP);
383 dec_dev.hwregs[PP_INTERRUPT_REGISTER] = 0;
387 pr_err("copy reg from hw with unknown type %d\n", reg->type);
391 atomic_sub(1, ®->session->task_running);
392 atomic_sub(1, &service.total_running);
393 wake_up_interruptible_sync(®->session->wait);
394 spin_unlock(&service.lock);
397 void reg_copy_to_hw(vpu_reg *reg)
400 u32 *src = (u32 *)®->reg[0];
401 atomic_add(1, &service.total_running);
402 atomic_add(1, ®->session->task_running);
405 u32 *dst = (u32 *)enc_dev.hwregs;
406 service.reg_codec = reg;
408 dst[VPU_REG_EN_ENC] = src[VPU_REG_EN_ENC] & 0x6;
410 for (i = 0; i < VPU_REG_EN_ENC; i++)
413 for (i = VPU_REG_EN_ENC + 1; i < REG_NUM_ENC; i++)
418 dst[VPU_REG_ENC_GATE] = src[VPU_REG_ENC_GATE] | VPU_REG_ENC_GATE_BIT;
419 dst[VPU_REG_EN_ENC] = src[VPU_REG_EN_ENC];
422 u32 *dst = (u32 *)dec_dev.hwregs;
423 service.reg_codec = reg;
425 for (i = REG_NUM_DEC - 1; i > VPU_REG_DEC_GATE; i--)
430 dst[VPU_REG_DEC_GATE] = src[VPU_REG_DEC_GATE] | VPU_REG_DEC_GATE_BIT;
431 dst[VPU_REG_EN_DEC] = src[VPU_REG_EN_DEC];
434 u32 *dst = (u32 *)dec_dev.hwregs + PP_INTERRUPT_REGISTER;
435 service.reg_pproc = reg;
437 dst[VPU_REG_PP_GATE] = src[VPU_REG_PP_GATE] | VPU_REG_PP_GATE_BIT;
439 for (i = VPU_REG_PP_GATE + 1; i < REG_NUM_PP; i++)
444 dst[VPU_REG_EN_PP] = src[VPU_REG_EN_PP];
447 u32 *dst = (u32 *)dec_dev.hwregs;
448 service.reg_codec = reg;
449 service.reg_pproc = reg;
451 for (i = VPU_REG_EN_DEC_PP + 1; i < REG_NUM_DEC_PP; i++)
454 dst[VPU_REG_EN_DEC_PP] = src[VPU_REG_EN_DEC_PP] | 0x2;
457 dst[VPU_REG_DEC_PP_GATE] = src[VPU_REG_DEC_PP_GATE] | VPU_REG_PP_GATE_BIT;
458 dst[VPU_REG_DEC_GATE] = src[VPU_REG_DEC_GATE] | VPU_REG_DEC_GATE_BIT;
459 dst[VPU_REG_EN_DEC] = src[VPU_REG_EN_DEC];
462 pr_err("unsupport session type %d", reg->type);
463 atomic_sub(1, &service.total_running);
464 atomic_sub(1, ®->session->task_running);
470 static void try_set_reg(void)
473 // first get reg from reg list
474 spin_lock_irqsave(&service.lock, flag);
475 if (!list_empty(&service.waiting)) {
476 vpu_reg *reg = list_entry(service.waiting.next, vpu_reg, status_link);
478 vpu_service_power_maintain();
479 if (((VPU_DEC_PP == reg->type) && (NULL == service.reg_codec) && (NULL == service.reg_pproc)) ||
480 ((VPU_DEC == reg->type) && (NULL == service.reg_codec)) ||
481 ((VPU_PP == reg->type) && (NULL == service.reg_pproc)) ||
482 ((VPU_ENC == reg->type) && (NULL == service.reg_codec))) {
483 reg_from_wait_to_run(reg);
487 spin_unlock_irqrestore(&service.lock, flag);
490 static int return_reg(vpu_reg *reg, u32 __user *dst)
495 if (copy_to_user(dst, ®->reg[0], SIZE_REG(REG_NUM_ENC)))
500 if (copy_to_user(dst, ®->reg[0], SIZE_REG(REG_NUM_DEC)))
505 if (copy_to_user(dst, ®->reg[0], SIZE_REG(REG_NUM_PP)))
510 if (copy_to_user(dst, ®->reg[0], SIZE_REG(REG_NUM_DEC_PP)))
516 pr_err("copy reg to user with unknown type %d\n", reg->type);
524 static long vpu_service_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
526 vpu_session *session = (vpu_session *)filp->private_data;
527 if (NULL == session) {
532 case VPU_IOC_SET_CLIENT_TYPE : {
533 session->type = (VPU_CLIENT_TYPE)arg;
536 case VPU_IOC_GET_HW_FUSE_STATUS : {
538 if (copy_from_user(&req, (void __user *)arg, sizeof(vpu_request))) {
539 pr_err("VPU_IOC_GET_HW_FUSE_STATUS copy_from_user failed\n");
542 if (VPU_ENC != session->type) {
543 if (copy_to_user((void __user *)req.req, &service.dec_config, sizeof(VPUHwDecConfig_t))) {
544 pr_err("VPU_IOC_GET_HW_FUSE_STATUS copy_to_user failed type %d\n", session->type);
548 if (copy_to_user((void __user *)req.req, &service.enc_config, sizeof(VPUHwEncConfig_t))) {
549 pr_err("VPU_IOC_GET_HW_FUSE_STATUS copy_to_user failed type %d\n", session->type);
557 case VPU_IOC_SET_REG : {
560 if (copy_from_user(&req, (void __user *)arg, sizeof(vpu_request))) {
561 pr_err("VPU_IOC_SET_REG copy_from_user failed\n");
565 reg = reg_init(session, (void __user *)req.req, req.size);
569 vpu_service_power_on();
575 case VPU_IOC_GET_REG : {
579 if (copy_from_user(&req, (void __user *)arg, sizeof(vpu_request))) {
580 pr_err("VPU_IOC_GET_REG copy_from_user failed\n");
583 int ret = wait_event_interruptible_timeout(session->wait, !list_empty(&session->done), TIMEOUT_DELAY);
584 if (unlikely(ret < 0)) {
585 pr_err("pid %d wait task ret %d\n", session->pid, ret);
586 } else if (0 == ret) {
587 pr_err("pid %d wait %d task done timeout\n", session->pid, atomic_read(&session->task_running));
590 spin_lock_irqsave(&service.lock, flag);
592 int task_running = atomic_read(&session->task_running);
595 atomic_set(&session->task_running, 0);
596 atomic_sub(task_running, &service.total_running);
597 printk("%d task is running but not return, reset hardware...", task_running);
601 vpu_service_session_clear(session);
602 spin_unlock_irqrestore(&service.lock, flag);
605 spin_unlock_irqrestore(&service.lock, flag);
607 spin_lock_irqsave(&service.lock, flag);
608 reg = list_entry(session->done.next, vpu_reg, session_link);
609 return_reg(reg, (u32 __user *)req.req);
610 spin_unlock_irqrestore(&service.lock, flag);
614 pr_err("unknow vpu service ioctl cmd %x\n", cmd);
622 static int vpu_service_check_hw_id(struct vpu_device * dev, const u16 *hwids, size_t num)
624 u32 hwid = readl(dev->hwregs);
625 pr_info("HW ID = 0x%08x\n", hwid);
627 hwid = (hwid >> 16) & 0xFFFF; /* product version only */
630 if (hwid == hwids[num]) {
631 pr_info("Compatible HW found at 0x%08lx\n", dev->iobaseaddr);
636 pr_info("No Compatible HW found at 0x%08lx\n", dev->iobaseaddr);
640 static void vpu_service_release_io(void)
643 iounmap((void *)dec_dev.hwregs);
644 release_mem_region(dec_dev.iobaseaddr, dec_dev.iosize);
647 iounmap((void *)enc_dev.hwregs);
648 release_mem_region(enc_dev.iobaseaddr, enc_dev.iosize);
651 static int vpu_service_reserve_io(void)
653 unsigned long iobaseaddr;
654 unsigned long iosize;
656 iobaseaddr = dec_dev.iobaseaddr;
657 iosize = dec_dev.iosize;
659 if (!request_mem_region(iobaseaddr, iosize, "vdpu_io")) {
660 pr_info("failed to reserve dec HW regs\n");
664 dec_dev.hwregs = (volatile u32 *)ioremap_nocache(iobaseaddr, iosize);
666 if (dec_dev.hwregs == NULL) {
667 pr_info("failed to ioremap dec HW regs\n");
671 /* check for correct HW */
672 if (!vpu_service_check_hw_id(&dec_dev, dec_hw_ids, ARRAY_SIZE(dec_hw_ids))) {
676 iobaseaddr = enc_dev.iobaseaddr;
677 iosize = enc_dev.iosize;
679 if (!request_mem_region(iobaseaddr, iosize, "hx280enc")) {
680 pr_info("failed to reserve enc HW regs\n");
684 enc_dev.hwregs = (volatile u32 *)ioremap_nocache(iobaseaddr, iosize);
686 if (enc_dev.hwregs == NULL) {
687 pr_info("failed to ioremap enc HW regs\n");
691 /* check for correct HW */
692 if (!vpu_service_check_hw_id(&enc_dev, enc_hw_ids, ARRAY_SIZE(enc_hw_ids))) {
698 vpu_service_release_io();
702 static int vpu_service_open(struct inode *inode, struct file *filp)
704 vpu_session *session = (vpu_session *)kmalloc(sizeof(vpu_session), GFP_KERNEL);
705 if (NULL == session) {
706 pr_err("unable to allocate memory for vpu_session.");
710 session->type = VPU_TYPE_BUTT;
711 session->pid = current->pid;
712 INIT_LIST_HEAD(&session->waiting);
713 INIT_LIST_HEAD(&session->running);
714 INIT_LIST_HEAD(&session->done);
715 INIT_LIST_HEAD(&session->list_session);
716 init_waitqueue_head(&session->wait);
717 /* no need to protect */
718 list_add_tail(&session->list_session, &service.session);
719 atomic_set(&session->task_running, 0);
720 filp->private_data = (void *)session;
722 pr_debug("dev opened\n");
723 return nonseekable_open(inode, filp);
726 static int vpu_service_release(struct inode *inode, struct file *filp)
730 vpu_session *session = (vpu_session *)filp->private_data;
734 task_running = atomic_read(&session->task_running);
736 pr_err("vpu_service session %d still has %d task running when closing\n", session->pid, task_running);
739 wake_up_interruptible_sync(&session->wait);
741 spin_lock_irqsave(&service.lock, flag);
742 /* remove this filp from the asynchronusly notified filp's */
743 //vpu_service_fasync(-1, filp, 0);
744 list_del(&session->list_session);
746 vpu_service_session_clear(session);
749 spin_unlock_irqrestore(&service.lock, flag);
751 pr_debug("dev closed\n");
755 static const struct file_operations vpu_service_fops = {
756 .unlocked_ioctl = vpu_service_ioctl,
757 .open = vpu_service_open,
758 .release = vpu_service_release,
759 //.fasync = vpu_service_fasync,
762 static struct miscdevice vpu_service_misc_device = {
763 .minor = MISC_DYNAMIC_MINOR,
764 .name = "vpu_service",
765 .fops = &vpu_service_fops,
768 static void vpu_service_shutdown(struct platform_device *pdev)
770 pr_cont("shutdown...");
771 del_timer(&service.timer);
772 vpu_service_power_off();
776 static int vpu_service_suspend(struct platform_device *pdev, pm_message_t state)
779 pr_info("suspend...");
780 del_timer(&service.timer);
781 enabled = service.enabled;
782 vpu_service_power_off();
783 service.enabled = enabled;
787 static int vpu_service_resume(struct platform_device *pdev)
789 pr_info("resume...");
790 if (service.enabled) {
791 service.enabled = false;
792 vpu_service_power_on();
798 static struct platform_device vpu_service_device = {
799 .name = "vpu_service",
803 static struct platform_driver vpu_service_driver = {
805 .name = "vpu_service",
806 .owner = THIS_MODULE,
808 .shutdown = vpu_service_shutdown,
809 .suspend = vpu_service_suspend,
810 .resume = vpu_service_resume,
813 static void get_hw_info(void)
815 VPUHwDecConfig_t *dec = &service.dec_config;
816 VPUHwEncConfig_t *enc = &service.enc_config;
817 u32 configReg = dec_dev.hwregs[VPU_DEC_HWCFG0];
818 u32 asicID = dec_dev.hwregs[0];
820 dec->h264Support = (configReg >> DWL_H264_E) & 0x3U;
821 dec->jpegSupport = (configReg >> DWL_JPEG_E) & 0x01U;
822 if (dec->jpegSupport && ((configReg >> DWL_PJPEG_E) & 0x01U))
823 dec->jpegSupport = JPEG_PROGRESSIVE;
824 dec->mpeg4Support = (configReg >> DWL_MPEG4_E) & 0x3U;
825 dec->vc1Support = (configReg >> DWL_VC1_E) & 0x3U;
826 dec->mpeg2Support = (configReg >> DWL_MPEG2_E) & 0x01U;
827 dec->sorensonSparkSupport = (configReg >> DWL_SORENSONSPARK_E) & 0x01U;
828 dec->refBufSupport = (configReg >> DWL_REF_BUFF_E) & 0x01U;
829 dec->vp6Support = (configReg >> DWL_VP6_E) & 0x01U;
830 dec->maxDecPicWidth = configReg & 0x07FFU;
832 /* 2nd Config register */
833 configReg = dec_dev.hwregs[VPU_DEC_HWCFG1];
834 if (dec->refBufSupport) {
835 if ((configReg >> DWL_REF_BUFF_ILACE_E) & 0x01U)
836 dec->refBufSupport |= 2;
837 if ((configReg >> DWL_REF_BUFF_DOUBLE_E) & 0x01U)
838 dec->refBufSupport |= 4;
840 dec->customMpeg4Support = (configReg >> DWL_MPEG4_CUSTOM_E) & 0x01U;
841 dec->vp7Support = (configReg >> DWL_VP7_E) & 0x01U;
842 dec->vp8Support = (configReg >> DWL_VP8_E) & 0x01U;
843 dec->avsSupport = (configReg >> DWL_AVS_E) & 0x01U;
846 if (((asicID >> 16) >= 0x8190U) || ((asicID >> 16) == 0x6731U)) {
847 dec->jpegESupport = (configReg >> DWL_JPEG_EXT_E) & 0x01U;
849 dec->jpegESupport = JPEG_EXT_NOT_SUPPORTED;
852 if (((asicID >> 16) >= 0x9170U) || ((asicID >> 16) == 0x6731U) ) {
853 dec->rvSupport = (configReg >> DWL_RV_E) & 0x03U;
855 dec->rvSupport = RV_NOT_SUPPORTED;
858 dec->mvcSupport = (configReg >> DWL_MVC_E) & 0x03U;
860 if (dec->refBufSupport && (asicID >> 16) == 0x6731U ) {
861 dec->refBufSupport |= 8; /* enable HW support for offset */
865 VPUHwFuseStatus_t hwFuseSts;
866 /* Decoder fuse configuration */
867 u32 fuseReg = dec_dev.hwregs[VPU_DEC_HW_FUSE_CFG];
869 hwFuseSts.h264SupportFuse = (fuseReg >> DWL_H264_FUSE_E) & 0x01U;
870 hwFuseSts.mpeg4SupportFuse = (fuseReg >> DWL_MPEG4_FUSE_E) & 0x01U;
871 hwFuseSts.mpeg2SupportFuse = (fuseReg >> DWL_MPEG2_FUSE_E) & 0x01U;
872 hwFuseSts.sorensonSparkSupportFuse = (fuseReg >> DWL_SORENSONSPARK_FUSE_E) & 0x01U;
873 hwFuseSts.jpegSupportFuse = (fuseReg >> DWL_JPEG_FUSE_E) & 0x01U;
874 hwFuseSts.vp6SupportFuse = (fuseReg >> DWL_VP6_FUSE_E) & 0x01U;
875 hwFuseSts.vc1SupportFuse = (fuseReg >> DWL_VC1_FUSE_E) & 0x01U;
876 hwFuseSts.jpegProgSupportFuse = (fuseReg >> DWL_PJPEG_FUSE_E) & 0x01U;
877 hwFuseSts.rvSupportFuse = (fuseReg >> DWL_RV_FUSE_E) & 0x01U;
878 hwFuseSts.avsSupportFuse = (fuseReg >> DWL_AVS_FUSE_E) & 0x01U;
879 hwFuseSts.vp7SupportFuse = (fuseReg >> DWL_VP7_FUSE_E) & 0x01U;
880 hwFuseSts.vp8SupportFuse = (fuseReg >> DWL_VP8_FUSE_E) & 0x01U;
881 hwFuseSts.customMpeg4SupportFuse = (fuseReg >> DWL_CUSTOM_MPEG4_FUSE_E) & 0x01U;
882 hwFuseSts.mvcSupportFuse = (fuseReg >> DWL_MVC_FUSE_E) & 0x01U;
884 /* check max. decoder output width */
886 if (fuseReg & 0x8000U)
887 hwFuseSts.maxDecPicWidthFuse = 1920;
888 else if (fuseReg & 0x4000U)
889 hwFuseSts.maxDecPicWidthFuse = 1280;
890 else if (fuseReg & 0x2000U)
891 hwFuseSts.maxDecPicWidthFuse = 720;
892 else if (fuseReg & 0x1000U)
893 hwFuseSts.maxDecPicWidthFuse = 352;
894 else /* remove warning */
895 hwFuseSts.maxDecPicWidthFuse = 352;
897 hwFuseSts.refBufSupportFuse = (fuseReg >> DWL_REF_BUFF_FUSE_E) & 0x01U;
899 /* Pp configuration */
900 configReg = dec_dev.hwregs[VPU_PP_HW_SYNTH_CFG];
902 if ((configReg >> DWL_PP_E) & 0x01U) {
904 dec->maxPpOutPicWidth = configReg & 0x07FFU;
905 /*pHwCfg->ppConfig = (configReg >> DWL_CFG_E) & 0x0FU; */
906 dec->ppConfig = configReg;
909 dec->maxPpOutPicWidth = 0;
913 /* check the HW versio */
914 if (((asicID >> 16) >= 0x8190U) || ((asicID >> 16) == 0x6731U)) {
915 /* Pp configuration */
916 configReg = dec_dev.hwregs[VPU_DEC_HW_FUSE_CFG];
918 if ((configReg >> DWL_PP_E) & 0x01U) {
919 /* Pp fuse configuration */
920 u32 fuseRegPp = dec_dev.hwregs[VPU_PP_HW_FUSE_CFG];
922 if ((fuseRegPp >> DWL_PP_FUSE_E) & 0x01U) {
923 hwFuseSts.ppSupportFuse = 1;
924 /* check max. pp output width */
925 if (fuseRegPp & 0x8000U) hwFuseSts.maxPpOutPicWidthFuse = 1920;
926 else if (fuseRegPp & 0x4000U) hwFuseSts.maxPpOutPicWidthFuse = 1280;
927 else if (fuseRegPp & 0x2000U) hwFuseSts.maxPpOutPicWidthFuse = 720;
928 else if (fuseRegPp & 0x1000U) hwFuseSts.maxPpOutPicWidthFuse = 352;
929 else hwFuseSts.maxPpOutPicWidthFuse = 352;
930 hwFuseSts.ppConfigFuse = fuseRegPp;
932 hwFuseSts.ppSupportFuse = 0;
933 hwFuseSts.maxPpOutPicWidthFuse = 0;
934 hwFuseSts.ppConfigFuse = 0;
937 hwFuseSts.ppSupportFuse = 0;
938 hwFuseSts.maxPpOutPicWidthFuse = 0;
939 hwFuseSts.ppConfigFuse = 0;
942 if (dec->maxDecPicWidth > hwFuseSts.maxDecPicWidthFuse)
943 dec->maxDecPicWidth = hwFuseSts.maxDecPicWidthFuse;
944 if (dec->maxPpOutPicWidth > hwFuseSts.maxPpOutPicWidthFuse)
945 dec->maxPpOutPicWidth = hwFuseSts.maxPpOutPicWidthFuse;
946 if (!hwFuseSts.h264SupportFuse) dec->h264Support = H264_NOT_SUPPORTED;
947 if (!hwFuseSts.mpeg4SupportFuse) dec->mpeg4Support = MPEG4_NOT_SUPPORTED;
948 if (!hwFuseSts.customMpeg4SupportFuse) dec->customMpeg4Support = MPEG4_CUSTOM_NOT_SUPPORTED;
949 if (!hwFuseSts.jpegSupportFuse) dec->jpegSupport = JPEG_NOT_SUPPORTED;
950 if ((dec->jpegSupport == JPEG_PROGRESSIVE) && !hwFuseSts.jpegProgSupportFuse)
951 dec->jpegSupport = JPEG_BASELINE;
952 if (!hwFuseSts.mpeg2SupportFuse) dec->mpeg2Support = MPEG2_NOT_SUPPORTED;
953 if (!hwFuseSts.vc1SupportFuse) dec->vc1Support = VC1_NOT_SUPPORTED;
954 if (!hwFuseSts.vp6SupportFuse) dec->vp6Support = VP6_NOT_SUPPORTED;
955 if (!hwFuseSts.vp7SupportFuse) dec->vp7Support = VP7_NOT_SUPPORTED;
956 if (!hwFuseSts.vp8SupportFuse) dec->vp8Support = VP8_NOT_SUPPORTED;
957 if (!hwFuseSts.ppSupportFuse) dec->ppSupport = PP_NOT_SUPPORTED;
959 /* check the pp config vs fuse status */
960 if ((dec->ppConfig & 0xFC000000) && ((hwFuseSts.ppConfigFuse & 0xF0000000) >> 5)) {
961 u32 deInterlace = ((dec->ppConfig & PP_DEINTERLACING) >> 25);
962 u32 alphaBlend = ((dec->ppConfig & PP_ALPHA_BLENDING) >> 24);
963 u32 deInterlaceFuse = (((hwFuseSts.ppConfigFuse >> 5) & PP_DEINTERLACING) >> 25);
964 u32 alphaBlendFuse = (((hwFuseSts.ppConfigFuse >> 5) & PP_ALPHA_BLENDING) >> 24);
966 if (deInterlace && !deInterlaceFuse) dec->ppConfig &= 0xFD000000;
967 if (alphaBlend && !alphaBlendFuse) dec->ppConfig &= 0xFE000000;
969 if (!hwFuseSts.sorensonSparkSupportFuse) dec->sorensonSparkSupport = SORENSON_SPARK_NOT_SUPPORTED;
970 if (!hwFuseSts.refBufSupportFuse) dec->refBufSupport = REF_BUF_NOT_SUPPORTED;
971 if (!hwFuseSts.rvSupportFuse) dec->rvSupport = RV_NOT_SUPPORTED;
972 if (!hwFuseSts.avsSupportFuse) dec->avsSupport = AVS_NOT_SUPPORTED;
973 if (!hwFuseSts.mvcSupportFuse) dec->mvcSupport = MVC_NOT_SUPPORTED;
976 configReg = enc_dev.hwregs[63];
977 enc->maxEncodedWidth = configReg & ((1 << 11) - 1);
978 enc->h264Enabled = (configReg >> 27) & 1;
979 enc->mpeg4Enabled = (configReg >> 26) & 1;
980 enc->jpegEnabled = (configReg >> 25) & 1;
981 enc->vsEnabled = (configReg >> 24) & 1;
982 enc->rgbEnabled = (configReg >> 28) & 1;
983 enc->busType = (configReg >> 20) & 15;
984 enc->synthesisLanguage = (configReg >> 16) & 15;
985 enc->busWidth = (configReg >> 12) & 15;
988 static irqreturn_t vdpu_isr(int irq, void *dev_id)
990 vpu_device *dev = (vpu_device *) dev_id;
991 u32 irq_status_dec = readl(dev->hwregs + DEC_INTERRUPT_REGISTER);
992 u32 irq_status_pp = readl(dev->hwregs + PP_INTERRUPT_REGISTER);
994 pr_debug("vdpu_isr dec %x pp %x\n", irq_status_dec, irq_status_pp);
996 if (irq_status_dec & DEC_INTERRUPT_BIT) {
997 irq_status_dec = readl(dev->hwregs + DEC_INTERRUPT_REGISTER);
998 if ((irq_status_dec & 0x40001) == 0x40001)
1001 irq_status_dec = readl(dev->hwregs + DEC_INTERRUPT_REGISTER);
1002 } while ((irq_status_dec & 0x40001) == 0x40001);
1005 writel(irq_status_dec & (~DEC_INTERRUPT_BIT), dev->hwregs + DEC_INTERRUPT_REGISTER);
1006 pr_debug("DEC IRQ received!\n");
1007 if (NULL == service.reg_codec) {
1008 pr_err("dec isr with no task waiting\n");
1010 reg_from_run_to_done(service.reg_codec);
1014 if (irq_status_pp & PP_INTERRUPT_BIT) {
1016 writel(irq_status_pp & (~DEC_INTERRUPT_BIT), dev->hwregs + PP_INTERRUPT_REGISTER);
1017 pr_debug("PP IRQ received!\n");
1018 if (NULL == service.reg_pproc) {
1019 pr_err("pp isr with no task waiting\n");
1021 reg_from_run_to_done(service.reg_pproc);
1028 static irqreturn_t vepu_isr(int irq, void *dev_id)
1030 struct vpu_device *dev = (struct vpu_device *) dev_id;
1031 u32 irq_status = readl(dev->hwregs + ENC_INTERRUPT_REGISTER);
1033 pr_debug("enc_isr\n");
1035 if (likely(irq_status & ENC_INTERRUPT_BIT)) {
1037 writel(irq_status & (~ENC_INTERRUPT_BIT), dev->hwregs + ENC_INTERRUPT_REGISTER);
1038 pr_debug("ENC IRQ received!\n");
1039 if (NULL == service.reg_codec) {
1040 pr_err("enc isr with no task waiting\n");
1042 reg_from_run_to_done(service.reg_codec);
1049 static int __init vpu_service_init(void)
1053 pr_debug("baseaddr = 0x%08x vdpu irq = %d vepu irq = %d\n", RK29_VCODEC_PHYS, IRQ_VDPU, IRQ_VEPU);
1055 dec_dev.iobaseaddr = RK29_VCODEC_PHYS + 0x200;
1056 dec_dev.iosize = DEC_IO_SIZE;
1057 enc_dev.iobaseaddr = RK29_VCODEC_PHYS;
1058 enc_dev.iosize = ENC_IO_SIZE;
1060 INIT_LIST_HEAD(&service.waiting);
1061 INIT_LIST_HEAD(&service.running);
1062 INIT_LIST_HEAD(&service.done);
1063 INIT_LIST_HEAD(&service.session);
1064 spin_lock_init(&service.lock);
1065 service.reg_codec = NULL;
1066 service.reg_pproc = NULL;
1067 atomic_set(&service.total_running, 0);
1068 service.enabled = false;
1071 vpu_service_power_on();
1073 ret = vpu_service_reserve_io();
1075 pr_err("reserve io failed\n");
1076 goto err_reserve_io;
1079 /* get the IRQ line */
1080 ret = request_irq(IRQ_VDPU, vdpu_isr, IRQF_SHARED, "vdpu", (void *)&dec_dev);
1082 pr_err("can't request vdpu irq %d\n", IRQ_VDPU);
1083 goto err_req_vdpu_irq;
1086 ret = request_irq(IRQ_VEPU, vepu_isr, IRQF_SHARED, "vepu", (void *)&enc_dev);
1088 pr_err("can't request vepu irq %d\n", IRQ_VEPU);
1089 goto err_req_vepu_irq;
1092 ret = misc_register(&vpu_service_misc_device);
1094 pr_err("misc_register failed\n");
1098 platform_device_register(&vpu_service_device);
1099 platform_driver_probe(&vpu_service_driver, NULL);
1101 del_timer(&service.timer);
1102 vpu_service_power_off();
1103 pr_info("init success\n");
1108 free_irq(IRQ_VEPU, (void *)&enc_dev);
1110 free_irq(IRQ_VDPU, (void *)&dec_dev);
1112 pr_info("init failed\n");
1114 del_timer(&service.timer);
1115 vpu_service_power_off();
1116 vpu_service_release_io();
1118 pr_info("init failed\n");
1122 static void __exit vpu_service_exit(void)
1124 del_timer(&service.timer);
1125 vpu_service_power_off();
1126 platform_device_unregister(&vpu_service_device);
1127 platform_driver_unregister(&vpu_service_driver);
1128 misc_deregister(&vpu_service_misc_device);
1129 free_irq(IRQ_VEPU, (void *)&enc_dev);
1130 free_irq(IRQ_VDPU, (void *)&dec_dev);
1134 module_init(vpu_service_init);
1135 module_exit(vpu_service_exit);
1136 MODULE_LICENSE("GPL");
1138 #ifdef CONFIG_PROC_FS
1139 #include <linux/proc_fs.h>
1140 #include <linux/seq_file.h>
1142 static int proc_vpu_service_show(struct seq_file *s, void *v)
1146 vpu_reg *reg, *reg_tmp;
1147 vpu_session *session, *session_tmp;
1149 vpu_service_power_on();
1150 seq_printf(s, "\nENC Registers:\n");
1151 n = enc_dev.iosize >> 2;
1152 for (i = 0; i < n; i++) {
1153 seq_printf(s, "\tswreg%d = %08X\n", i, readl(enc_dev.hwregs + i));
1155 seq_printf(s, "\nDEC Registers:\n");
1156 n = dec_dev.iosize >> 2;
1157 for (i = 0; i < n; i++) {
1158 seq_printf(s, "\tswreg%d = %08X\n", i, readl(dec_dev.hwregs + i));
1161 seq_printf(s, "\nvpu service status:\n");
1162 spin_lock_irqsave(&service.lock, flag);
1163 list_for_each_entry_safe(session, session_tmp, &service.session, list_session) {
1164 seq_printf(s, "session pid %d type %d:\n", session->pid, session->type);
1165 //seq_printf(s, "waiting reg set %d\n");
1166 list_for_each_entry_safe(reg, reg_tmp, &session->waiting, session_link) {
1167 seq_printf(s, "waiting register set\n");
1169 list_for_each_entry_safe(reg, reg_tmp, &session->running, session_link) {
1170 seq_printf(s, "running register set\n");
1172 list_for_each_entry_safe(reg, reg_tmp, &session->done, session_link) {
1173 seq_printf(s, "done register set\n");
1176 spin_unlock_irqrestore(&service.lock, flag);
1181 static int proc_vpu_service_open(struct inode *inode, struct file *file)
1183 return single_open(file, proc_vpu_service_show, NULL);
1186 static const struct file_operations proc_vpu_service_fops = {
1187 .open = proc_vpu_service_open,
1189 .llseek = seq_lseek,
1190 .release = single_release,
1193 static int __init vpu_service_proc_init(void)
1195 proc_create("vpu_service", 0, NULL, &proc_vpu_service_fops);
1199 late_initcall(vpu_service_proc_init);
1200 #endif /* CONFIG_PROC_FS */