/*
* Copyright (c) 2013. Internet Technology Laboratory, ITLAB
* Dept. of Electrical Engineering & Inst. of Computer and Communication Engineering
* National Cheng Kung University, Tainan, Taiwan
* All Right Reserved
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/ioctl.h>
#include <linux/wait.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/io.h>
#include <asm/page.h>
#include <linux/device.h>
#include <asm/irq.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/irqflags.h>
#include <linux/wait.h>
/* hardware device setting value */
#define DRIVER_NAME "vdec_hw"
#define DEVICE_NAME "vdec"
#define VDEC_MAJOR 256
#define VDEC_MINOR 0
#define IRQ_VIC_BRIDGE 30
#define PIC_BASE 32
#define VDEC_BASE 0x80000000
#define MEMSIZE 0x1000
#define BUFSIZE 384
/* command */
#define OP_SET 1
#define GO 5
/* address offset */
#define operator_offset 0x4
#define ibuffer_offset 0xC
#define obuffer_offset 0x614
#define CHECKFLAG_OFFSET 0x60C
#define SIZECOUNT_OFFSET 0x610
#define interrupt_offset 0xD00
MODULE_AUTHOR("Drunkard");
MODULE_LICENSE("GPL");
static DECLARE_WAIT_QUEUE_HEAD(wq);
static int flag = 0;
static int vdec_major = VDEC_MAJOR;
static int vdec_minor = VDEC_MINOR;
static int buffer[BUFSIZE+2];
void __iomem *base;
static int vdec_open(struct inode *inode, struct file *file)
{
return 0;
}
static int vdec_release(struct inode *inode, struct file *file)
{
return 0;
}
static ssize_t vdec_read(struct file *filp, char *buff, size_t len, loff_t *off)
{
int i;
/* Only result is readable memory address */
if(len > BUFSIZE*4)
len = BUFSIZE*4;
for(i=0;i<len/4;i++)
buffer[i] = readl(base + obuffer_offset + i*4);
buffer[BUFSIZE] = readl(base + SIZECOUNT_OFFSET);
buffer[BUFSIZE+1] = readl(base + CHECKFLAG_OFFSET);
i = copy_to_user(buff, buffer, len+8);
return len;
}
static ssize_t vdec_write(struct file *filp, const char *buff, size_t len, loff_t *off)
{
int i;
if(len > BUFSIZE*4)
len = BUFSIZE*4;
i = copy_from_user(buffer, buff, len);
for(i=0;i<len/4;i++)
{
writel(buffer[i], base + ibuffer_offset + i*4);
}
return len;
}
static long vdec_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
switch(cmd)
{
case OP_SET:
writel((unsigned int)arg, base + operator_offset);
break;
case GO:
writel((unsigned int)arg, base);
wait_event_interruptible(wq, flag != 0);
flag = 0;
break;
default:
printk("Unknown COMMAND!!!\n");
}
return 0;
}
static void allocate_memory_region(void)
{
base = ioremap_nocache(VDEC_BASE , MEMSIZE);
printk("Physical address: %08X-%08X (%dKB)\n", VDEC_BASE, VDEC_BASE+MEMSIZE, MEMSIZE/1024);
printk("After ioremap: %08X-%08X (%dKB)\n", (int)base, (int)base+MEMSIZE, MEMSIZE/1024);
}
static void free_allocated_memory(void)
{
iounmap((unsigned long*) base);
}
static struct file_operations vdec_fops = {
.owner = THIS_MODULE,
.read = vdec_read,
.write = vdec_write,
.unlocked_ioctl = vdec_unlocked_ioctl,
.open = vdec_open,
.release = vdec_release
};
static struct cdev vdec_cdev = {
.kobj = { .name = DRIVER_NAME },
.owner = THIS_MODULE,
};
static irqreturn_t vdec_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
//printk("received interrupt from SC_LINK\n");
if(irq == IRQ_VIC_BRIDGE+PIC_BASE)
{
//printk("received interrupt from MP3EN HW\n");
writel(0, base+interrupt_offset);
//printk("Release interrupt\n");
flag = 1;
wake_up_interruptible(&wq);
}
return IRQ_HANDLED;
}
static int __init vdec_init(void)
{
dev_t dev = 0;
int result;
/* register char device */
if(VDEC_MAJOR)
{
dev = MKDEV(vdec_major, vdec_minor);
result = register_chrdev_region(dev, 1, DRIVER_NAME);
}
else
{
result = alloc_chrdev_region(&dev, vdec_minor, 1, DRIVER_NAME);
vdec_major = MAJOR(dev);
}
if(result < 0)
{
printk(KERN_ERR DRIVER_NAME "Can't allocate major number %d for %s\n", vdec_major, DEVICE_NAME);
return -EAGAIN;
}
cdev_init(&vdec_cdev, &vdec_fops);
result = cdev_add(&vdec_cdev, dev, 1);
if(result < 0)
{
printk(KERN_ERR DRIVER_NAME "Can't add device %d\n", dev);
return -EAGAIN;
}
/* allocate memory */
allocate_memory_region();
/* request irq and bind ISR*/
result = request_irq(IRQ_VIC_BRIDGE+PIC_BASE, (void*)vdec_interrupt, IRQF_DISABLED, DEVICE_NAME, NULL);
if(result)
printk(KERN_ERR DRIVER_NAME "Can't request IRQ\n");
return 0;
}
static void __exit vdec_exit(void){
dev_t dev;
free_allocated_memory();
dev = MKDEV(vdec_major, vdec_minor);
unregister_chrdev_region(dev, 1);
cdev_del(&vdec_cdev);
free_irq(IRQ_VIC_BRIDGE+PIC_BASE, NULL);
printk("VDEC driver exit\n");
}
module_init(vdec_init);
module_exit(vdec_exit);
vdec_drv.zip_vdec_video decoder
版权申诉
188 浏览量
2022-09-20
20:08:00
上传
评论
收藏 2KB ZIP 举报
weixin_42651887
- 粉丝: 80
- 资源: 1万+
最新资源
- 基于Javascript和Vue的微信小程序抽奖打地鼠游戏设计源码 - 抽奖打地鼠
- 基于Python和Javascript的车展大屏演示前后端web应用设计源码 - autoshow
- 基于Javascript和微信小程序的Anna设计源码
- 基于Java的仿制品设计源码 - bilibili
- 基于Javascript的影视动画设计源码 - cad
- 基于Java和深度学习的瓦斯浓度预测系统后端设计源码 - 瓦斯浓度预测后端
- Screenshot_20240528_103010.jpg
- 基于Python的新能源承载力计算及界面设计源码 - HAINING-DG
- 基于Java的本科探索学习项目设计源码 - 本科探索
- 基于Javascript和Python的微商城项目设计源码 - MicroMall
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈