LCD驱动程序(3)显存与调色板

    xiaoxiao2021-03-25  162

    我们设置好了LCD控制器,它就会自动的从显存里面取出一个像素的值,然后发送到LCD上去,然后再取出第二个......取到最后面之后有返回到第一个,周而复始。

    显存必须物理地址连续,LCD没那么聪明,你这个显存必须是连续的。怎么分配呢,我们就不能有kmalloc这种函数了。就要用专用的函数来分配这块内存。来看一看内核自带的一些驱动是怎么来分配这块内存的。

    我们参考我们内核里面的S3c2410fd.c这个文件

    ret = s3c2410fb_map_video_memory(fbinfo);里面有个这个函数,进入这个函数里面去看一看

    static int __devinit s3c2410fb_map_video_memory(struct fb_info *info) { struct s3c2410fb_info *fbi = info->par; dma_addr_t map_dma; unsigned map_size = PAGE_ALIGN(info->fix.smem_len); dprintk("map_video_memory(fbi=%p) map_size %u\n", fbi, map_size); info->screen_base = dma_alloc_writecombine(fbi->dev, map_size,    &map_dma, GFP_KERNEL);                        //就是这个函数分配的 if (info->screen_base) { /* prevent initial garbage on screen */ dprintk("map_video_memory: clear %p:x\n", info->screen_base, map_size); memset(info->screen_base, 0x00, map_size); info->fix.smem_start = map_dma; dprintk("map_video_memory: dma=lx cpu=%p size=x\n", info->fix.smem_start, info->screen_base, map_size); } return info->screen_base ? 0 : -ENOMEM; }

    dma_alloc_writecombine来看一下它需要什么参数

    void *dma_alloc_writecombine(struct device *dev, size_t size,dma_addr_t *handle, gfp_t gfp) 第一个参数是设备,第二个是大小,第三个参数是物理地址dma_addr_t,实际上就是个u32.物理地址我们不是想存到var.smem_start这里吗,所以我们把这里的参数设置为这个就行了。还一个就是标记,标记很简单,就一个flage就行了

    返回值就是返回这块内存的虚拟地址。

    现在我们还只是分配了,但是我们还要把这个告诉我们LCD控制器

    什么是调色板:我们这里每个像素需要24位的数据,如果显存里面留3个字节,刚好16位,刚好够。LCD控制器直接把这个数据拿过来用就好了,但是我如果想节省一下内存,我这里只想用1个字节8位,那怎么办呢,我们LCD控制器取到这8位之后它怎么转换成24位的数据呢,怎么转换就是调色板。LCD控制器得到这个8位的数据并不是直接发送给LCD的,而是把8位的数据经过调色板,调色板就是一块内存,调色板里面真正有24位数据,LCD得到数据之后,以这8位作为索引,它就想个数组一样,假如这8位是100,那么LCD就会找到这个100项,把里面的16位数据取出来给LCD。

    我们假的调色板由谁来设置呢

     由fops里面的//.fb_setcolreg = tiny_lcdfb_setcolreg,这个来设置

    我们小时候调颜色就是把红绿蓝透明色放到一个碟子里面,

    代码如下

    static int s5p_lcdfb_setcolreg(unsigned int regno, unsigned int red,unsigned     int green, unsigned int blue,unsigned int transp, struct fb_info *info) { }

    unsigned int regno这个意思是指明是哪个碟子

     static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfie    ld *bf) 131 { 132         chan &= 0xffff;//保留16位 133         chan >>= 16 - bf->length;//我们的长度是888,16-8=8 //得到高8位 134         return chan << bf->offset;//左移之后得到一个值,这个值就是给你用的 135 } 136  137 static int s5p_lcdfb_setcolreg(unsigned int regno, unsigned int red,unsigned     int green, unsigned int blue,unsigned int transp, struct fb_info *info) 138 { 139     unsigned int val; 140     /*因为我那个数组里面只有16个*/ 141     if (regno > 16) 142         return 1; 143  144     /*用红绿蓝三个颜色达到一个值*/ 145     val  = chan_to_field(red, &info->var.red);

    146   val |= chan_to_field(green, &info->var.green);

    147     val |= chan_to_field(blue, &info->var.blue); 148     /*把这个值放到碟子里面去*/ 149     pseudo_pal[regno] = val; 150 }

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

    最新回复(0)