linux - fpga-framebuff驱动
* linux/drivers/video/fpga_fb.c --fpga graphics adaptor frame buffer device
* Created 16 Sep2011
* Based on dnfb.c
*
* History:
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <asm/setup.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <linux/clk.h>
#include <linux/fb.h>
#include <linux/module.h>
#define LCD_WIDTH 320
#define LCD_HEIGHT 240
#define DISPRAMBUFLSZ (LCD_WIDTH/8)
#define DISPRAMBUFSIZE (DISPRAMBUFLSZ*LCD_HEIGHT)
/* display_ video definitions */
static void __iomem *io_data=NULL;
static void __iomem *io_cmd=NULL;
static void __iomem *io_ctrl=NULL;
static unsigned long ioo_data=0;
static unsigned char *rambuf_org = NULL;
static unsigned char *rambuf_cur = NULL;
/* frame buffer operations */
// zydzfb_blank控制屏幕开关
static int zydzfb_blank(int blank, struct fb_info *info);
static struct fb_ops zydzfb_ops = {
.owner = THIS_MODULE,
//.fb_blank = zydzfb_blank,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
};
struct fb_var_screeninfo zydzfb_var __devinitdata = {
.xres = 320,//实际x轴分辨率
.yres = 240,//实际y轴分辨率
.xres_virtual = 320,//虚拟x轴分辨率
.yres_virtual = 240,//虚拟y轴分辨率
.bits_per_pixel= 1, //定义每个点用多少位表示
.height = -1,
.width = -1,
//.vmode = FB_VMODE_NONINTERLACED,
};
static struct fb_fix_screeninfo zydzfb_fix __devinitdata = {
.id = "zydzfb",//设备名称
.type = FB_TYPE_PACKED_PIXELS,
.visual = FB_VISUAL_MONO01 ,/* Monochr. 1=Black 0=White */
.line_length = DISPRAMBUFLSZ,
};
/*
* Initialization
*/
static int __devinit zydzfb_probe(struct platform_device *dev)
{
struct fb_info *info;
int err = 0;
info = framebuffer_alloc(0, &dev->dev);
if (!info)
return -ENOMEM;
info->fbops = &zydzfb_ops;
info->fix = zydzfb_fix;
info->fix.smem_start = virt_to_phys(rambuf_cur);
info->fix.smem_len = DISPRAMBUFSIZE;
info->var = zydzfb_var;
/* Virtual address */
info->screen_base = rambuf_cur;
info->screen_size = DISPRAMBUFSIZE;
err = fb_alloc_cmap(&info->cmap, 2, 0);
if (err < 0) {
framebuffer_release(info);
return err;
}
err = register_framebuffer(info);
if (err < 0) {
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
return err;
}
platform_set_drvdata(dev, info);
/* now we have registered we can safely setup the hardware */
printk("display_ frame buffer alive and kicking !\n");
return err;
}
void disp_init( )
{
static int inited=0;
if(inited)return;
io_data=ioremap_nocache(LCD_DATA_PORT,32);
io_cmd=ioremap_nocache(LCD_CTRL_PORT,32);
io_ctrl=ioremap_nocache(LCD_PERH_PORT,32);
rambuf_org = kmalloc(DISPRAMBUFSIZE,GFP_KERNEL);
rambuf_cur = kmalloc(DISPRAMBUFSIZE,GFP_KERNEL);
lcd_reset();
inited=1;
}
unsigned char re_uc(unsigned char x)
{
x = (x&0x0f)<<4 |(x&0xf0)>>4;
x = (x&0x33)<<2 |(x&0xcc)>>2;
x = (x&0x55)<<1 |(x&0xaa)>>1;
return x;
}
static struct timer_list timer_key;
void fb_timer_func(unsigned long pa)
{
int i;
for(i=0;i<LCD_HEIGHT*DISPRAMBUFLSZ;i++)
{
if(rambuf_org[i]!=rambuf_cur[i])
{
WriteLCDCmd(SRCSET_CMD);
WriteLCDData(i%0x100);
WriteLCDData(i/0x100);
WriteLCDCmd(MEMWRITE_CMD);
WriteLCDData(re_uc(rambuf_cur[i]));
rambuf_org[i]=rambuf_cur[i];
}
}
mod_timer(&timer_key,jiffies+20);
}
static struct platform_driver zydzfb_driver = {
.probe = zydzfb_probe,
.driver = {
.name = "zydzfb",
},
};
static struct platform_device zydzfb_device = {
.name = "zydzfb",
};
int __init zydzfb_init(void)
{
int ret,i,j;
disp_init( );
ret = platform_driver_register(&zydzfb_driver);
if (!ret) {
ret = platform_device_register(&zydzfb_device);
if (ret)
platform_driver_unregister(&zydzfb_driver);
}
init_timer(&timer_key);
timer_key.function=&fb_timer_func;
timer_key.expires=jiffies+10;
timer_key.data = 0;
add_timer(&timer_key);
return ret;
}
static void __exit zydzfb_exit(void)
{
del_timer(&timer_key);
platform_device_unregister(&zydzfb_device);
platform_driver_unregister(&zydzfb_driver);
if (rambuf_org)
kfree(rambuf_org);
if (rambuf_cur)
kfree(rambuf_cur);
}
module_init(zydzfb_init);
module_exit(zydzfb_exit);
MODULE_LICENSE("GPL");