LCD驱动程序(1)初步编写LCD驱动程序

    xiaoxiao2021-03-25  206

    先参考内核里面自带的驱动程序,我们只是参考它的头文件而已

     /*1.分配一个fb_info结构体*/  30     s5p_lcd=framebuffer_alloc(sizeof(struct s5p_lcd), &pdev->dev);  31     //这里为什么需要一个大小,内核里面有个经常有个取巧的办法,分配一个结构体     ,本来这个结构体只有这么大,它会额外分配一部分空间给你,然后你原本那个大小的     里面有个私有指针,指向它。你可以往里面存一些你觉得有意义的数据

    不信的话我们可以看一下framebuffer_alloc的源代码

    struct fb_info *framebuffer_alloc(size_t size, struct device *dev)

    { #define BYTES_PER_LONG (BITS_PER_LONG/8) #define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG)) int fb_info_size = sizeof(struct fb_info); struct fb_info *info; char *p; if (size) fb_info_size += PADDING; p = kzalloc(fb_info_size + size, GFP_KERNEL);//看这里  fb_info_size还要加一个size。 if (!p) return NULL; info = (struct fb_info *) p; if (size) info->par = p + fb_info_size; //par指向额外分配的一段空间 info->device = dev; #ifdef CONFIG_FB_BACKLIGHT mutex_init(&info->bl_curve_mutex); #endif return info; #undef PADDING #undef BYTES_PER_LONG }

    在我们驱动程序中要设置fb_info这个结构体,我们来看看这个结构体中有什么东西

    我们前面说了固定参数

    struct fb_fix_screeninfo fix;/* Current fix */    //这里的意思是固定的参数

    我们来看看这个结构体里面有什么东西

    __u32 visual; /* see FB_VISUAL_* */                   //我们来看看这个宏

    我们在来看可变信息

    看看可变信息里面有什么

    struct fb_bitfield blue; //看看这个结构体struct fb_bitfield struct fb_bitfield transp;/* transparency*///透明色,我们没有透明度 struct fb_bitfield { __u32 offset; /* beginning of bitfield */ __u32 length; /* length of bitfield */ __u32 msb_right;/* != 0 : Most significant bit is */  /* right */  }; 第一个是从哪一位开始,第二个是长度,第三个是  最重要的一位,如果最重要的一位在最右边 那么这里应该设置为不等于0;

    下面我们来设置我们的fops

    我们看其他的驱动程序,会发现一个共同点

    static struct fb_ops tiny_lcdfb_ops = { .owner = THIS_MODULE, .fb_fillrect = cfb_fillrect, //这一个是什么意思呢,从英文名字可以看出是填充矩形的意思。 .fb_copyarea = cfb_copyarea, //拷贝一个区域 .fb_imageblit = cfb_imageblit, }; 这几个fops基本上在每个lcd驱动上都会出现,共用的

    所以我们也来参照一下

    很明显是对显存的一些操作。

    经过上面这些操作,我们驱动程序变成这样的

    #include <linux/module.h> #include <linux/kernel.h> #include <linux/err.h> #include <linux/errno.h> #include <linux/string.h> #include <linux/mm.h> #include <linux/slab.h> #include <linux/delay.h> #include <linux/fb.h> #include <linux/init.h> #include <linux/dma-mapping.h> #include <linux/interrupt.h> #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/cpufreq.h> #include <asm/io.h> #include <asm/div64.h> #include <asm/mach/map.h> #include <mach/regs-lcd.h> #include <mach/regs-gpio.h> #include <mach/fb.h> static struct fb_info *s5p_info; static struct fb_ops s5p_lcdfb_ops = { .owner = THIS_MODULE, //.fb_setcolreg= tiny_lcdfb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, }; static int lcd_init(void) { int res; /*1.分配一个fb_info结构体*/ s5p_info=framebuffer_alloc(0,NULL); if (!s5p_info) { printk("framebuffer_alloc error"); return -ENOMEM; } //这里为什么需要一个大小,内核里面有个经常有个取巧的办法,分配一个结构体,本来这个结构体只有这么大,它会额外分配一部分空间给你,然后你原本那个大小的里面有个私有指针,指向它。你可以往里面存一些你觉得有意义的数据。 //但是这里我们不需要额外的那段空间,所以这里写为0,后面写为NULL /*2.设置*/ /*2.1设置固定的参数*/ /*2.1.1名字*/ strcpy(s5p_info->fix.id,"ghlcd"); /*2.1.2 设置显存的长度*/ /*这里需要我们去看LCD的手册*/ s5p_info->fix.len=800*480*4; /*2.1.3 type*/ s5p_info->fix.type=FB_TYPE_PACKED_PIXELS; /*2.1.4  visual*/ s5p_info->fix.visual=VISUAL_TRUECOLOR; /*2.1.5 一行的长度单位是字节*/ s5p_info->fix.line_length=800*4; /*2.2设置可变的参数*/ /*2.2.1 x方向的分辨率*/ s5p_info->var.xres=800; /*2.2.2 y方向的分辨率*/ s5p_info->var.yres=480; /*2.2.3  x方向的虚拟分辨率*/ s5p_info->var.xres_virtual=800; /*2.2.4  y方向的虚拟分辨率*/ s5p_info->var.yres_virtual=480; /*2.2.5 每个像素用多少位*/ s5p_info->var.bits_per_pixel=32; /*2.2.6 红色从那一位开始*/ //RGB 8:8:8 s5p_info->var.red.offset = 16; /*2.2.7 长度*/ s5p_info->var.red.length =8; s5p_info>var.green.offset= 8; s5p_info->var.green.length = 8; s5p_info->var.blue.offset  = 0; s5p_info->var.blue.length  = 8; /*2.2.8 activate */ s5p_info->var.activate = FB_ACTIVATE_NOW; /*2.3设置fops操作函数*/ s5p_info->fbfops=&s5p_lcdfb_ops; /*2.4其他的设置*/ //tiny_lcd->screen_base = ; /*显存的虚拟起始地址*/ s5p_info->screen_size = 800*480*4; s5p_info->pseudo_palette = pseudo_pal; //这个是假的调色板 /*3.硬件相关的操作*/ /*3.1配置相应的GPIO为LCD管脚*/ /*3.2根据LCD手册设置LCD控制器,让它可以发出正确的信号*/ /*3.3分配framebuffer,并把物理地址告诉LCD控制器*/ //s5p_info->var.smem_start=xxxxx; /*4.注册*/ res = register_framebuffer(s5p_info); if (ret < 0) { printk(KERN_ERR "Failed to register framebuffer device: %d\n",ret); return ENOMEM; } return 0; } static void lcd_exit(void) { } module_init(lcd_init); module_exit(lcd_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("EIGHT");

    转载请注明原文地址: https://ju.6miu.com/read-4161.html

    最新回复(0)