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

我们设置好了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:%08x\n",
info->screen_base, map_size);
memset(info->screen_base, 0x00, map_size);


info->fix.smem_start = map_dma;


dprintk("map_video_memory: dma=%08lx cpu=%p size=%08x\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 }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值