• linux


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

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

  • 相关阅读:
    POJ-2018 Best Cow Fences(二分加DP)
    POJ-2039 To and Fro
    POJ-2029 Get Many Persimmon Trees(动态规划)
    POJ-2081 Recaman's Sequence
    POJ-2081 Terrible Sets(暴力,单调栈)
    Java实现 LeetCode 740 删除与获得点数(递推 || 动态规划?打家劫舍Ⅳ)
    Java实现 LeetCode 739 每日温度(暴力循环)
    Java实现 LeetCode 739 每日温度(暴力循环)
    Java实现 LeetCode 739 每日温度(暴力循环)
    Java实现 LeetCode 738 单调递增的数字(暴力)
  • 原文地址:https://www.cnblogs.com/zym0805/p/4309599.html
Copyright © 2020-2023  润新知