linux 自带LCD驱动框架(三)

Table of Contents

一、驱动框架图

二、LCD驱动工作原理

2.1、驱动入口(内核自带 fbmem.c)

2.2、平台驱动platform_driver (三星自带 s3c-fb.c)(可以自行编写)

2.2.1、 s3c_fb_probe函数

2.2.2、时间参数设置s3c_fb_set_rgb_timing

2.2.3、LCD固定参数设置s3c_fb_probe_win

2.2.4、显存分配s3c_fb_alloc_memory

2.3、平台设备(platform_device) mach-tiny4412.c

2.3.1、struct platform_device  s5p_device_fimd0

2.3.2、平台资源struct resource

2.3.3、平台数据platform_data

2.3.4、屏幕参数设备信息(一般就是修改这里)

2.4、应用程序读写LCD解析


一、驱动框架图

 核心层是通用的,不需要做任何修改。驱动开发者只需要实现硬件驱动层。

1. 帧缓冲设备可以一个完整的子系统,主要由核心层的 fbmem.c 和硬件设备驱动层构成
2. 核心层代码 fbmem.c 向上提供了完整的字符设备操作接口,也就是实现注册字符设备,提供通用的open,read,write,ioctl,mmap 等接口;向下给硬件设备驱动层提供标准的驱动编程接口;
3. 在 Linux 系统中,一个硬件 LCD 控制器(显卡)抽象为一个 fb_info 结构,要实现一个 LCD 驱动谅是要实现这个结构,并且使用核心层提供的注册函数注册。
4. fb_info 中通过其中的 fb_ops 结构指针提供了实际硬件操作方法。
5. fb_info 中通过其中的 fb_var_screeninfo 结构和 fb_fix_screeninfo 结构提供了具体 lcd 屏基本信息。
6.注册: register_framebuffer
7. 注销: unregister_framebuffer

二、LCD驱动工作原理

2.1、驱动入口(内核自带 fbmem.c

 linux/drivers/video/fbmem.c

static int __init  fbmem_init(void)
{

    if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) //FB_MAJOR   29
        printk("unable to get major %d for fb devs\n", FB_MAJOR);

  、、、、、、、、、
    return 0;
}

static const struct file_operations fb_fops = {
    .owner =    THIS_MODULE,
    .read =        fb_read,
    .write =    fb_write,
    .unlocked_ioctl = fb_ioctl,
、、、、、、、、、、、、、、、
    .mmap =        fb_mmap,
   、、、、、、、、、、、、
};

2.2、平台驱动platform_driver (三星自带 s3c-fb.c)(可以自行编写)

2.2.1、 s3c_fb_probe函数

linux/drivers/video/s3c-fb.c

static struct platform_driver s3c_fb_driver = {
    .probe        = s3c_fb_probe,
   、、、、、、
};

static int __devinit s3c_fb_probe(struct platform_device *pdev)

{

、、、、、、、、、、、、、、、

       pd = pdev->dev.platform_data//获取平台数据

       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  //得到内存资源

       sfb->regs = devm_request_and_ioremap(dev, res);

       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);  //得到中断资源

       /* setup gpio and output polarity controls */

       pd->setup_gpio(); //gpio初始化

       writel(pd->vidcon1, sfb->regs + VIDCON1);

       s3c_fb_set_rgb_timing(sfb);  //时间参数设置

              ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win],   &sfb->windows[win]); //屏幕固定参数设置,显存设置,注册LCD

 }

2.2.2、时间参数设置s3c_fb_set_rgb_timing

static void s3c_fb_set_rgb_timing(struct s3c_fb *sfb)
{
  、、、、、、、、、、

    data = VIDTCON0_VBPD(vmode->upper_margin - 1) |
           VIDTCON0_VFPD(vmode->lower_margin - 1) |
           VIDTCON0_VSPW(vmode->vsync_len - 1);
    writel(data, regs + sfb->variant.vidtcon);

    data = VIDTCON1_HBPD(vmode->left_margin - 1) |
           VIDTCON1_HFPD(vmode->right_margin - 1) |
           VIDTCON1_HSPW(vmode->hsync_len - 1);
    writel(data, regs + sfb->variant.vidtcon + 4);

    data = VIDTCON2_LINEVAL(vmode->yres - 1) |
           VIDTCON2_HOZVAL(vmode->xres - 1) |
           VIDTCON2_LINEVAL_E(vmode->yres - 1) |
           VIDTCON2_HOZVAL_E(vmode->xres - 1);
    writel(data, regs + sfb->variant.vidtcon + 8);
}

2.2.3、LCD固定参数设置s3c_fb_probe_win

tatic int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
       struct s3c_fb_win_variant *variant,
        struct s3c_fb_win **res)

{

、、、、、、、、、、、、、、、、、、、、、、、 

   ret = s3c_fb_alloc_memory(sfb, win);

    、、、、、、、、、、、、、、、
        /* Set 8bpp or 8bpp and 1bit alpha */
        win->palette.r.offset = 16;
        win->palette.r.length = 8;
        win->palette.g.offset = 8;
        win->palette.g.length = 8;
        win->palette.b.offset = 0;
        win->palette.b.length = 8;

 、、、、、、、、、、、、、、、、、、、

    fbinfo->var.width    = windata->width;
    fbinfo->var.height    = windata->height;

    fbinfo->fix.type    = FB_TYPE_PACKED_PIXELS;
    fbinfo->fix.accel    = FB_ACCEL_NONE;
    fbinfo->var.activate    = FB_ACTIVATE_NOW;
    fbinfo->var.vmode    = FB_VMODE_NONINTERLACED;
    fbinfo->var.bits_per_pixel = windata->default_bpp;
    fbinfo->fbops        = &s3c_fb_ops;
    fbinfo->flags        = FBINFO_FLAG_DEFAULT;

    fbinfo->pseudo_palette = &win->pseudo_palette;

    /* prepare to actually start the framebuffer */

    ret = s3c_fb_check_var(&fbinfo->var, fbinfo);
    、、、、、、、、、、、、、、、

    s3c_fb_set_par(fbinfo);

    /* run the check_var and set_par on our configuration. */

    ret = register_framebuffer(fbinfo);

、、、、、、、、、、、、

    return 0;
}

2.2.4、显存分配s3c_fb_alloc_memory

static int __devinit s3c_fb_alloc_memory(struct s3c_fb *sfb,
        struct s3c_fb_win *win)
{
 
    struct fb_info *fbi = win->fbinfo;
 、、、、、、、、、、、、、、、、、
    fbi->screen_base = dma_alloc_writecombine(sfb->dev, size,&map_dma, GFP_KERNEL);

    return 0;
}
 

2.3、平台设备(platform_device) mach-tiny4412.c

2.3.1、struct platform_device  s5p_device_fimd0

 linux/arch/arm/plat-samsung/devs.c

struct platform_device s5p_device_fimd0 = {
    .name        = "exynos4-fb",
    .id        = 0,
    .num_resources    = ARRAY_SIZE(s5p_fimd0_resource),
    .resource    = s5p_fimd0_resource,
    .dev        = {
        .dma_mask        = &samsung_device_dma_mask,
        .coherent_dma_mask    = DMA_BIT_MASK(32),
    },
};

void __init s5p_fimd0_set_platdata(struct s3c_fb_platdata *pd)
{

//s5p_device_fimd0->dev->platform_data = smdk4x12_lcd0_pdata  (smdk4x12_lcd0_pdata将下面解析)
    s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata), &s5p_device_fimd0);
}

2.3.2、平台资源struct resource

static struct resource s5p_fimd0_resource[] = {
    [0] = DEFINE_RES_MEM(S5P_PA_FIMD0, SZ_32K),
    [1] = DEFINE_RES_IRQ(IRQ_FIMD0_VSYNC),
    [2] = DEFINE_RES_IRQ(IRQ_FIMD0_FIFO),
    [3] = DEFINE_RES_IRQ(IRQ_FIMD0_SYSTEM),
};

2.3.3、平台数据platform_data

static struct s3c_fb_platdata smdk4x12_lcd0_pdata __initdata = {
    .win[0]        = &smdk4x12_fb_win0,
    .win[1]        = &smdk4x12_fb_win1,
    .win[2]        = &smdk4x12_fb_win2,
    .win[3]        = &smdk4x12_fb_win3,
    .win[4]        = &smdk4x12_fb_win4,
    .vtiming    = &smdk4x12_lcd_timing,
    .vidcon0    = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,//重要寄存器设置
    .vidcon1    = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,        
    .setup_gpio    = exynos4_fimd0_gpio_setup_24bpp, //管脚设置函数
};

static void __init smdk4x12_machine_init(void)
{

、、、、、、、、、、、、、
    tiny4412_fb_init_pdata(&smdk4x12_lcd0_pdata);
    s5p_fimd0_set_platdata(&smdk4x12_lcd0_pdata);  //设置platform_data成员为smdk4x12_lcd0_pdata
、、、、、、、、、、、、、、
}

static void __init tiny4412_fb_init_pdata(struct s3c_fb_platdata *pd) {
    
、、、、、、、、、、、、、、、、、、、、、、、、、、、
    lcd = tiny4412_get_lcd();

  、、、、、、、、、、、、、、、、、、
}

struct s3cfb_lcd *tiny4412_get_lcd(void)
{
    return tiny4412_lcd_config[lcd_idx].lcd;
}

 tiny4412_lcd_config[] = {
    { "S70",    &wvga_s70,   1 },
   、、、、、、、、、
};

2.3.4、屏幕参数设备信息(一般就是修改这里)

static struct s3cfb_lcd wvga_s70 = {
    .width = 800,
    .height = 480,
    .p_width = 155,
    .p_height = 93,
    .bpp = 24,
    .freq = 63,

    .timing = {
        .h_fp = 80,
        .h_bp = 36,
        .h_sw = 10,
        .v_fp = 22,
        .v_fpe = 1,
        .v_bp = 15,
        .v_bpe = 1,
        .v_sw = 8,
    },
    .polarity = {
        .rise_vclk = 1,
        .inv_hsync = 1,
        .inv_vsync = 1,
        .inv_vden = 0,
    },

};
 

2.4、应用程序读写LCD解析

--------------------------------------------------------------

假设
app:  open("/dev/fb0", ...)   主设备号: 29, 次设备号: 0
--------------------------------------------------------------
kernel:
         fb_open
             int fbidx = iminor(inode);
             struct fb_info *info = = registered_fb[fbidx ];

app:  read()
---------------------------------------------------------------
kernel:
        fb_read
            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)   

 

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值