历史上的今天
返回首页

历史上的今天

今天是:2025年04月25日(星期五)

正在发生

2020年04月25日 | 《韦东山视频第二期》——LCD驱动

2020-04-25 来源:eefocus

一、LCD驱动程序框架分析


app: open("/dev/fb0", ...)     主设备号:29, 次设备号:0


————————————————————————————————————————————————————

kernel:(核心文件/drivers/video/fbmem.c)


                fb_open


                          int fbidx = iminor(inode);

                          struct fb_info *info;


                          info = registered_fb[fbidx];      //根据次设备号获得从底层注册的struct fb_info结构体中


                         file->private_data = info;

                         if (info->fbops->fb_open) {                         //调用底层struct fb_info结构体中的fb_open函数

                                 res = info->fbops->fb_open(info,1);

                                 if (res)

                                 module_put(info->fbops->owner);

                         }


———————————————————————————————————————————————————


app:    read()


_____________________________________________________________________________________


kernel:


                fb_read


                            struct inode *inode = file->f_path.dentry->d_inode;

                            int fbidx = iminor(inode);

                            struct fb_info *info = registered_fb[fbidx];


                            if (info->fbops->fb_read)

                           return info->fbops->fb_read(info, buf, count, ppos);




                          src = (u32 __iomem *) (info->screen_base + p);

                          dst = buffer;

                         *dst++ = fb_readl(src++);

                         copy_to_user(buf, buffer, c)          


怎么写LCD驱动程序?


1.分配一个fb_info结构体:framebuffer_alloc()


2.设置


3.注册:register_framebuffer


4.硬件相关的操作  


#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

 

#include

#include

#include

 

#include

#include

#include

#include

 

struct lcd_regs {

    unsigned long    lcdcon1;

    unsigned long    lcdcon2;

    unsigned long    lcdcon3;

    unsigned long    lcdcon4;

    unsigned long    lcdcon5;

    unsigned long    lcdsaddr1;

    unsigned long    lcdsaddr2;

    unsigned long    lcdsaddr3;

    unsigned long    redlut;

    unsigned long    greenlut;

    unsigned long    bluelut;

    unsigned long    reserved[9];

    unsigned long    dithmode;

    unsigned long    tpal;

    unsigned long    lcdintpnd;

    unsigned long    lcdsrcpnd;

    unsigned long    lcdintmsk;

    unsigned long    lpcsel;

};

 

static struct fb_ops* s3c_lcdfb_ops = {

    .owner          = THIS_MODULE,

//  .fb_setcplreg = atmel_lcdfb_setolreg,

    .fb_fillrect  = cfb_fillrect,

    .fb_copyarea  = cfb_copyarea,

    .fb_imageblit = cfb_imageblit,

};

 

static struct fb_info* s3c_lcd;

 

static volatile unsigned long *gpbcon;

static volatile unsigned long *gpbdat;

static volatile unsigned long *gpccon;

static volatile unsigned long *gpdcon;

static volatile unsigned long *gpgcon;

static volatile struct lcd_regs* lcd_regs;

 

static u32 pseudo_palette[16];    //为了兼容,设置假的调色板

/* from pxafb.c */

static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)

{

    chan &= 0xffff;

    chan >>= 16 - bf->length;

    return chan << bf->offset;

}

 

 

static int s3c_lcdfb_setcolreg(unsigned int regno, unsigned int red,

                 unsigned int green, unsigned int blue,

                 unsigned int transp, struct fb_info *info)

{

    unsigned int val;

    

    if (regno > 16)

        return 1;

 

    /* 用red,green,blue三原色构造出val */

    val  = chan_to_field(red,    &info->var.red);

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

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

    

    //((u32 *)(info->pseudo_palette))[regno] = val;

    pseudo_palette[regno] = val;

    return 0;

}

 

static int lcd_init(void)

{

    /* 1. 分配一个fb_info结构体 */

 

    s3c_lcd = framebuffer_alloc(0, NULL);

 

    /* 2. 设置 */

    /* 2.1 设置固定的参数 */

    strcpy(s3c_lcd->fix.id, "mylcd");

    s3c_lcd->fix.smem_len    = 320*240*32/8; /* MINI2440的LCD位宽是24,但是2440里会分配4字节即32位(浪费1字节) */

    s3c_lcd->fix.type        = FB_TYPE_PACKED_PIXELS;

    s3c_lcd->fix.visual      = FB_VISUAL_TRUECOLOR;     /* 真彩色 */

    s3c_lcd->fix.line_length = 320 * 4;    /* 1行的字节数 */

    

    /* 2.2 设置可变的参数 */

    s3c_lcd->var.xres          = 320;

    s3c_lcd->var.yres          = 240;

    s3c_lcd->var.xres_virtual  = 320;

    s3c_lcd->var.yres_virtual  = 240;

    s3c_lcd->var.bits_per_pixel = 32;    /* 每个像素所占的位数 */

 

    /* RGB: 565 */

    s3c_lcd->var.red.offset    = 16;

    s3c_lcd->var.red.length    = 8;

 

    s3c_lcd->var.green.offset  = 8;

    s3c_lcd->var.green.length  = 8;

 

    s3c_lcd->var.blue.offset   = 0;

    s3c_lcd->var.blue.length   = 0;

 

    s3c_lcd->var.activate      = FB_ACTIVATE_NOW;

    

    

    /* 2.3 设置操作函数 */

    s3c_lcd->fops   = &s3c_lcdfb_ops;

        

    /* 2.4 其他设置 */

    //s3c_lcd->pseudo_palette =; //

    //s3c_lcd->screen_base  = ;  /* 显存的虚拟地址 */ 

    s3c_lcd->screen_size   = 320*240*32/8;

 

    /* 3. 硬件相关的操作 */

    /* 3.1 配置GPIO用于LCD */

    gpbcon = ioremap(0x56000010, 8);

    gpbdat = gpbcon+1;

    gpccon = ioremap(0x56000020, 4);

    gpdcon = ioremap(0x56000030, 4);

    gpgcon = ioremap(0x56000060, 4);

 

    *gpccon  = 0xaaaaaaaa;   /* GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND */

    *gpdcon  = 0xaaaaaaaa;   /* GPIO管脚用于VD[23:8] */

    

//    *gpbcon &= ~(3);  /* GPB0设置为输出引脚 */

//    *gpbcon |= 1;

//    *gpbdat &= ~1;     /* 输出低电平 */

 

    *gpgcon |= (3<<8); /* GPG4用作LCD_PWREN */

 

 

    /* 3.2 根据LCD手册设置LCD控制器,比如VCLK的频率等 */

    lcd_regs = ioremap(0x4D000000, sizeof(struct lcd_regs));

    

    /*

     * MINI2440 LCD 3.5英寸 ZQ3506_V0 SPEC.pdf 第11、12页

     *

     * LCD手册11,12页和2440手册"Figure 15-6. TFT LCD Timing Example"一对比就知道参数含义了

     */

 

    /* bit[17:8]: VCLK = HCLK / [(CLKVAL+1) x 2], LCD手册11 (Dclk=6.4MHz~11MHz)

     *            7.1MHz = 100MHz / [(CLKVAL+1) x 2]

     *            CLKVAL = 6

     * bit[6:5]: 0b11, TFT LCD

     * bit[4:1]: 0b1101, 24 bpp for TFT

     * bit[0]  : 0 = Disable the video output and the LCD control signal.

     */

    lcd_regs->lcdcon1  = (6<<8) | (3<<5) | (0x0d<<1);

 

    /* 垂直方向的时间参数

     * 根据数据手册

     * bit[31:24]: VBPD, VSYNC之后再过多长时间才能发出第1行数据

推荐阅读

史海拾趣

Harris公司的发展小趣事

在过去的四十年中,Hammond将业务重心扩展到了美国和国际市场。通过在全球各地设立办事处和建立分销网络,Hammond成功地将其产品和服务推广到了世界各地。这一战略转型不仅极大地提升了Hammond的品牌影响力,还为其带来了更加广阔的市场空间和增长潜力。

General Instrument Optoelectronics公司的发展小趣事
用于拆卸电子琴的外壳和固定电路板。
HDP_Power公司的发展小趣事
用于测量电压、电流和电阻等参数,帮助诊断电路故障。
DDK公司的发展小趣事

人才是企业发展的根本。DDK公司深知人才的重要性,因此一直致力于人才培养和引进。公司建立了完善的人才培养机制,通过内部培训、外部引进等多种方式,不断吸引和培养了一批批优秀的电子工程师、研发人员和管理人才。这些人才为公司的发展提供了强大的智力支持和人才保障。

Alpha Semiconductor公司的发展小趣事

Alpha Semiconductor位于美国加州硅谷的研发与生产基地是公司发展的重要支撑。在这里,公司拥有一流的研发团队和先进的生产设备,能够为客户提供高质量的产品和服务。硅谷作为全球科技创新的中心之一,为Alpha Semiconductor提供了丰富的技术资源和人才支持,使得公司能够不断推陈出新,保持在半导体行业的领先地位。

通过以上五个故事,我们可以看到Alpha Semiconductor公司在电子行业中的发展历程。从初创时期的代工服务起步,到后来的OEM定制产品、自主研发电源管理产品,再到高性能标准模拟和混合信号IC的制造实力,以及在美国硅谷的研发与生产基地的建立,每一个阶段都见证了公司的成长和进步。Alpha Semiconductor凭借着不断的技术创新和市场拓展,已经成为了半导体行业中的佼佼者。

EPC公司的发展小趣事

最后一家EPC公司深知创新是企业发展的核心动力。公司注重研发投入和人才培养,建立了专业的研发团队和完善的研发体系。公司不断跟踪行业发展趋势和技术动态,积极引进新技术、新工艺和新材料,推动产品升级和产业升级。同时,公司注重创新成果的转化和应用,将新技术、新工艺和新材料应用于实际项目中,提高了项目的竞争力和附加值。通过持续的创新和积累,公司逐渐在电子行业中形成了独特的技术优势和核心竞争力。

请注意,以上故事仅为框架性描述,并未包含具体的公司名称、项目细节和具体数字。您可以根据这些框架性描述进一步深入了解相关公司的发展情况,并结合实际案例进行具体分析和撰写。

问答坊 | AI 解惑

关于方波到三角波的转换!!!!

我想做一个方波到三角波的信号发生器,但在从方波到三角波的过程中。如果从周期NT开始转换刚输出都是正的。如果从T/2开始转换则输出的是正负对称的波形。我现在想要一个正负对称的波形。但是怎么样才能保证一定会是正负对称的呢。望高人指教一下!…

查看全部问答>

BMP图片格式解析

本帖最后由 paulhyde 于 2014-9-15 09:20 编辑 …

查看全部问答>

LM的官方网站发布了新的手册,新版本的LM3S芯片引脚能够承受5V电压。

什么时间生产的芯片才算新版本的呢?B版本或以上就可承受5VLM3S单片机B版本或以上的IO口就可承受5V。版本号在单片机的第二行文字内,如B版本为“1RN20B4X”中的B,C版本为“1RN20C0X”中的C。…

查看全部问答>

vc2005与evc4比较

我用vc2005开发,在设备上,觉得速度没有evc4快,大家有类似的感觉吗? 尤其显示地图数据,无论如何优化,速度还是比较慢…

查看全部问答>

嘿嘿~~定时器中断~是我呀帮我再看看吧~大家快来

上次发的帖子,大家可能以为我放弃了或者已经不在弄了~~~~~ 非常感谢大家的帮助~~~因为一直很忙也没结贴~~感谢googleman ,咸蛋超人,and wangxin_801115,还有其他进来回帖的大家~~~ 呵呵~~~但是现在还没弄出来啊~~~中断还是进不了,但是比之前有 ...…

查看全部问答>

CYPRESS EZ-USB 旧问题解决,新问题又来

前面问题详见:http://blog.ednchina.com/huoyumutou/解决问题的办法主要是通过改CY68013A的固件来完成的,在CYPRESS/USB/Applicatoin目录下会有个例子叫SlaveFIFO,但是这个例子是异步传输,可以通过以下几个改动来实现同步传输。1. 对照寄存器表 ...…

查看全部问答>

最近在单片机遇到岔路

本人学生,学习单片机有2.3月了,有下面俩问题: 1、单片机应用广不广泛 2、出去后能不能在工作中应用 本人学习51的,用的是MedWinV3.0来编程的,期望大家回答下我的问题…

查看全部问答>

allegro pcb中画封装时以芯片第一脚为坐标原点还是芯片物理中心为坐标原点?

1.两者在贴片时有什么区别? 2.能不能在同一块PCB板上使用这两种不同方式的封装? 3.是否可以很方便地互改(坐标原点在封装画成后改动)?…

查看全部问答>

关于2440 demo 板的进展。

目前demo 板上已经移植好了 QP, LWIP, UIP, UCGUI 以及用串口中断接收的两个中断下半部模型例子。 demo 板同时支持mini 2440 和tq 2440 的开发板。…

查看全部问答>

关于2013 D题一个下限频率的看法

本帖最后由 paulhyde 于 2014-9-15 03:23 编辑 今年D题基础和发挥有个题目条件是有同学总是纠结于这个条件,要做高通滤波之类的,其实我认为不要做什么滤波,可以说是画蛇添足,下限频率小于0.3MHZ,表示要比这个值小,小到多少?0当然最好了,也 ...…

查看全部问答>