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");

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。