Linux-2.6.32.67内核裁剪与移植之LCD驱动的移植(2)

2023-05-16

               Linux-2.6.32.67内核裁剪与移植之LCD驱动的移植

                                                                      作者:赵凯

                                                                      QQ: 1205958201

注:转载请注明出处哦

内核源码中的“drivers/video/s3c2410fb.c”就是LCD的驱动了。

在该文件中找到函数static void s3c2410fb_activate_var(struct fb_info *info),修改如下:

static void s3c2410fb_activate_var(struct fb_info *info)

{

    struct s3c2410fb_info *fbi = info->par;

    void __iomem *regs = fbi->io;

    int type = fbi->regs.lcdcon1 & S3C2410_LCDCON1_TFT;

    struct fb_var_screeninfo *var = &info->var;

   struct s3c2410fb_mach_info *mach_info = fbi->dev->platform_data;

   struct s3c2410fb_display *default_display = mach_info->displays +

   mach_info->default_display;

    int clkdiv;

    clkdiv = DIV_ROUND_UP(s3c2410fb_calc_pixclk(fbi, var->pixclock), 2);

 

    dprintk("%s: var->xres  = %d\n", __func__, var->xres);

    dprintk("%s: var->yres  = %d\n", __func__, var->yres);

    dprintk("%s: var->bpp   = %d\n", __func__, var->bits_per_pixel);

 

    if (type == S3C2410_LCDCON1_TFT) {

       s3c2410fb_calculate_tft_lcd_regs(info, &fbi->regs);

       --clkdiv;

       if (clkdiv < 0)

           clkdiv = 0;

    } else {

       s3c2410fb_calculate_stn_lcd_regs(info, &fbi->regs);

       if (clkdiv < 2)

           clkdiv = 2;

    }

 

// fbi->regs.lcdcon1 |=  S3C2410_LCDCON1_CLKVAL(clkdiv);

fbi->regs.lcdcon1|=S3C2410_LCDCON1_CLKVAL(default_display->setclkval);

    /* write new registers */

 

    dprintk("new register set:\n");

    dprintk("lcdcon[1] = 0x%08lx\n", fbi->regs.lcdcon1);

    dprintk("lcdcon[2] = 0x%08lx\n", fbi->regs.lcdcon2);

    dprintk("lcdcon[3] = 0x%08lx\n", fbi->regs.lcdcon3);

    dprintk("lcdcon[4] = 0x%08lx\n", fbi->regs.lcdcon4);

    dprintk("lcdcon[5] = 0x%08lx\n", fbi->regs.lcdcon5);

 

    writel(fbi->regs.lcdcon1 & ~S3C2410_LCDCON1_ENVID,

       regs + S3C2410_LCDCON1);

    writel(fbi->regs.lcdcon2, regs + S3C2410_LCDCON2);

    writel(fbi->regs.lcdcon3, regs + S3C2410_LCDCON3);

    writel(fbi->regs.lcdcon4, regs + S3C2410_LCDCON4);

    writel(fbi->regs.lcdcon5, regs + S3C2410_LCDCON5);

 

    /* set lcd address pointers */

    s3c2410fb_set_lcdaddr(info);

 

    fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID,

    writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1);

}

这几句是在 s3c2410fb_display结构体中加入了setclkval变量,我们需要在结构体原型中加入这个变量,在arch/arm/mach-s3c2410/include/mach/fb.h中的s3c2410fb_display结构体中加入一行:

unsigned setclkval; /*clkval*/

然后需要修改LCD的参数设置

修改 arch/arm/mach-s3c2440/mach-smdk2440.c 文件中的static struct s3c2410fb_display smdk2440_lcd_cfg __initdata结构体:

修改结果如下:

static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = {

 

    .lcdcon5   = S3C2410_LCDCON5_FRM565 |

             S3C2410_LCDCON5_INVVLINE |

             S3C2410_LCDCON5_INVVFRAME |

             S3C2410_LCDCON5_PWREN |

             S3C2410_LCDCON5_HWSWP,

 

    .type      = S3C2410_LCDCON1_TFT,

 

    .width    = 320,

    .height       = 240,

    .pixclock  = 100000, /* HCLK 60 MHz, divisor 10 */

   .setclkval      =0x3,

    .xres      = 320,

    .yres      = 240,

    .bpp       = 16,

    .left_margin  = 33,

    .right_margin = 22,

    .hsync_len = 44,

    .upper_margin = 9,

    .lower_margin = 3,

    .vsync_len =15,

};

static struct s3c2410fb_mach_info smdk2440_fb_info __initdata = {

    .displays  = &smdk2440_lcd_cfg,

    .num_displays = 1,

    .default_display = 0,

 

#if 0

    /* currently setup by downloader */

    .gpccon       = 0xaa940659,

    .gpccon_mask  = 0xffffffff,

    .gpcup     = 0x0000ffff,

    .gpcup_mask   = 0xffffffff,

    .gpdcon       = 0xaa84aaa0,

    .gpdcon_mask  = 0xffffffff,

    .gpdup     = 0x0000faff,

    .gpdup_mask   = 0xffffffff,

#endif

 

   //.lpcsel   = ((0xCE6) & ~7) | 1<<4,

};

然后配置内核,支持LCD

键入:make menuconfig,然后配置如下:

Device Drivers:

Graphics Support --->

<*>support for frame buffer devices --->

[*] Enable frameware EDID

[*] Enable Vidoe Mode Handling Helpers

<*> S3C24X0 LCD framebuffer support

Console display driver support --->

<*> Framebuffer Console Support

 

[*] Bootup Logo --->

<*> Standard 224-color Linux logo

然后make uImage生成uImage文件,拷贝到tftp目录下:

[root@localhost linux-2.6.32.67]# cp  arch/arm/boot/uImage /var/lib/tftpboot

下载到开发板中:

tftp 0x32000000 uImage;nand erase 0 400000

nand write.jffs2 0x32000000 0 $filesize

在输出结果中关于LCD出现以下错误:

s3c2410-lcd s3c2410-lcd: no platform data for lcd, cannot attach

s3c2410-lcd: probe of s3c2410-lcd failed with error -22

搜索下该错误:

 

[root@localhost linux-2.6.32.67]# grep 'no platform data for lcd, cannot attach' * -nR

得到的结果如下:

drivers/video/s3c2410fb.c:838:         "no platform data for lcd, cannot attach\n");

进入该文件查看下上下文:

static int __init s3c24xxfb_probe(struct platform_device *pdev,

                enum s3c_drv_type drv_type)

{

    struct s3c2410fb_info *info;

    struct s3c2410fb_display *display;

    struct fb_info *fbinfo;

    struct s3c2410fb_mach_info *mach_info;

    struct resource *res;

    int ret;

    int irq;

    int i;

    int size;

    u32 lcdcon1;

 

    mach_info = pdev->dev.platform_data;

    if (mach_info == NULL) {

       dev_err(&pdev->dev,

           "no platform data for lcd, cannot attach\n");

       return -EINVAL;

    }

然后看下s3c2410fb_mach_info的定义:arch/arm/mach-s3c2410/include/mach/fb.h文件里面

struct s3c2410fb_mach_info {

 

    struct s3c2410fb_display *displays;    /* attached diplays info */

    unsigned num_displays;          /* number of defined displays */

    unsigned default_display;

 

    /* GPIOs */

 

    unsigned long gpcup;

    unsigned long gpcup_mask;

    unsigned long gpccon;

    unsigned long gpccon_mask;

    unsigned long gpdup;

    unsigned long gpdup_mask;

    unsigned long gpdcon;

    unsigned long gpdcon_mask;

 

    /* lpc3600 control register */

    unsigned long lpcsel;

};

再看下s3c2410fb_display的定义,也是在该文件中

/* LCD description */

struct s3c2410fb_display {

    /* LCD type */

    unsigned type;

 

    /* Screen size */

    unsigned short width;

    unsigned short height;

 

    /* Screen info */

    unsigned short xres;

    unsigned short yres;

    unsigned short bpp;

        unsigned setclkval; /*clkval*/

    unsigned pixclock;       /* pixclock in picoseconds */

    unsigned short left_margin;  /* value in pixels (TFT) or HCLKs (STN) */

    unsigned short right_margin; /* value in pixels (TFT) or HCLKs (STN) */

    unsigned short hsync_len;    /* value in pixels (TFT) or HCLKs (STN) */

    unsigned short upper_margin;    /* value in lines (TFT) or 0 (STN) */

    unsigned short lower_margin;    /* value in lines (TFT) or 0 (STN) */

    unsigned short vsync_len;   /* value in lines (TFT) or 0 (STN) */

 

    /* lcd configuration registers */

    unsigned long lcdcon5;

};

。。。。。。

这个问题暂时无法解决,先放到一边。

添加对4.3LCD7LCD的支持:

我们使用的3.5寸屏分辨率是320x2404.3寸屏分辨率是480x2727寸屏分辨率是800x480。同样修改arch/arm/mach-s3c2440/mach-smdk2440.c中第107行的结构体,加入4.3寸屏和7寸屏的配置参数。

static struct s3c2410fb_display smdk2440_lcd_cfg __initdata = {

 

   .lcdcon5   = S3C2410_LCDCON5_FRM565 |

            S3C2410_LCDCON5_INVVLINE |

            S3C2410_LCDCON5_INVVFRAME |

            S3C2410_LCDCON5_PWREN |

            S3C2410_LCDCON5_HWSWP,

 

   .type      = S3C2410_LCDCON1_TFT,

 

#if defined(CONFIG_FB_S3C2410_W35)

   .width     = 320,

   .height       = 240,

 

   .pixclock  = 100000, /* HCLK 60 MHz, divisor 10 */

        .setclkval      =0x3,

   .xres      = 320,

   .yres      = 240,

   .bpp       = 16,

   .left_margin  = 33,

   .right_margin = 22,

   .hsync_len = 44,

   .upper_margin = 9,

   .lower_margin = 3,

   .vsync_len =15,

#elif defined(CONFIG_FB_S3C2410_W43)

   .width = 480,

   .height = 272,

   .pixclock = 40000,

   .setclkval = 0x4,

   .xres = 480,

   .yres = 272,

   .bpp = 16,

   .left_margin = 19,

   .right_margin = 10,

   .hsync_len = 30,

   .upper_margin = 4,

   .lower_margin = 2,

   .vsync_len = 8,

#elif defined(CONFIG_FB_S3C2410_Q70)

   .width = 800,

   .height = 480,

   .pixclock = 40000,

   .setclkval = 0x1,

   .xres = 800,

   .yres = 480,

   .bpp = 16,

   .left_margin = 40,

   .right_margin = 40,

   .hsync_len = 48,

   .upper_margin = 13,

   .lower_margin = 29,

   .vsync_len = 3,

#endif

};

 

 

修改 drivers/video/Kconfig文件,在1923行加入:

choice

    prompt "LCD size select"

    depends on FB_S3C2410

    help

    s3c2410 lcd size select

config FB_S3C2410_W35

    boolean"The 3.5 inch LCD with resolution 320X240"

    depends on FB_S3C2410

    help

    3.5 inch LCD 320X240

config FB_S3C2410_W43

    boolean "The 4.3 inch LCD with resolution 480X272"

    depends on FB_S3C2410

    help

    4.3 inch LCD 480X272

config FB_S3C2410_Q70

    boolean"The 7 inch LCD with resolution 800X480"

    depends on FB_S3C2410

    help

    7 inch LCD 800X480

endchoice

config FB_S3C2410_DEBUG

    bool "S3C2410 lcd debug messages"

    depends on FB_S3C2410

    help

      Turn on debugging messages. Note that you can set/unset at run time

      through sysfs

配置内核,支持4.3LCD7LCD

Device Drivers:

Graphics Support --->

<*>support for frame buffer devices --->

<*> S3C24X0 LCD framebuffer support

LCD size select(The 3.5 inch LCD with resolution 320X240) --->

进入"LCD size select(The 3.5 inch LCD with resolution 320X240)--->"选项,在这里选择不同的LCD类型,按空格键即可选中,前面有"X"的表示选中的,如果我们要选择4.3寸屏,将光标移至第二行,按空格键,就选中了对4.3寸屏的支持。

( )The 3.5 inch LCD with resolution 320X240

XThe 4.3 inch LCD with resolution 480X272tq2440开发板使用的LCD大小)

( )The 7 inch LCD with resolution 800X480

然后将生成的uImage下载到开发板上运行。

同样的错误:

s3c2410-lcd s3c2410-lcd: no platform data for lcd, cannot attach

s3c2410-lcd: probe of s3c2410-lcd failed with error -22

说明内核没成功加载LCD驱动,为什么会出现这种情况呢,下面详细分析下:

首先看下LCD控制器的平台设备定义:arch/arm/plat-s3c24xx/devs.c文件

struct platform_device s3c_device_lcd = {

    .name     = "s3c2410-lcd",

    .id      = -1,

    .num_resources      = ARRAY_SIZE(s3c_lcd_resource),

    .resource    = s3c_lcd_resource,

    .dev              = {

       .dma_mask     = &s3c_device_lcd_dmamask,

       .coherent_dma_mask   = 0xffffffffUL

    }

};

这个s3c_device_lcd结构,在linux内核中已经分别加入了s3c2440、s3c2410开发板的设备列表中了。

在arch/arm/mach-s3c2410/mach-smdk2410.c文件中如下:

static struct platform_device *smdk2410_devices[] __initdata = {

    &s3c_device_usb,

    &s3c_device_lcd,

    &s3c_device_wdt,

    &s3c_device_i2c0,

    &s3c_device_iis,

};

在arch/arm/mach-s3c2440/mach-smdk2440.c文件中如下:

static struct platform_device *smdk2440_devices[] __initdata = {

    &s3c_device_usb,

    &s3c_device_lcd,

    &s3c_device_wdt,

    &s3c_device_i2c0,

    &s3c_device_iis,

};

LCD控制器驱动程序drivers/video/s3c2410fb.c的入口函数为:

static struct platform_driver s3c2410fb_driver = {

    .probe     = s3c2410fb_probe,

    .remove       = s3c2410fb_remove,

    .suspend   = s3c2410fb_suspend,

    .resume       = s3c2410fb_resume,

    .driver       = {

       .name  = "s3c2410-lcd",

       .owner = THIS_MODULE,

    },

};

。。。。。

int __init s3c2410fb_init(void)

{

    int ret = platform_driver_register(&s3c2410fb_driver);

    if (ret == 0)

       ret = platform_driver_register(&s3c2412fb_driver);

 

    return ret;

 

}

从上面的代码段可以看出平台设备s3c_device_lcd和平台驱动s3c2410fb_drivers的名字都是“s3c2410-lcd”,所以当注册了s3c2410fb_drivers之后,它的s3c2410fb_probe函数将被调用来设置LCD控制器。

下面再看看刚刚出错的那段代码段:

static int __init s3c24xxfb_probe(struct platform_device *pdev,

                enum s3c_drv_type drv_type)

{

    struct s3c2410fb_info *info;

    struct s3c2410fb_display *display;

    struct fb_info *fbinfo;

    struct s3c2410fb_mach_info *mach_info;

    struct resource *res;

    int ret;

    int irq;

    int i;

    int size;

    u32 lcdcon1;

 

    mach_info = pdev->dev.platform_data;

    if (mach_info == NULL) {

       dev_err(&pdev->dev,

           "no platform data for lcd, cannot attach\n");

       return -EINVAL;

    }

pdev就是指向了一个设备注册的指针,很明显该成员的dev.platform_data为空才会报错,这里需要配置一下内核,去掉与s3c2410相关的东东。。。

make menuconfig如下

System type-->

     S3C2410 Machines-->

这个目录下的内容全部取消不选,然后生成uImage文件下载到开发板中即可看到美丽的切啦啦。

下一步制作开机启动LOGO

这时候需要替换“drivers/video/logo/logo_linux_clut224.ppm”文件,首先复制开机的logo到linux系统中,然后使用GIMP工具进行编辑,由于我的redhat系统中没有该工具,需要安装。这里省去安装步骤。

图片的处理过程主要包括设置颜色数为224,保存为ppm文件,以ASII码的形式保存等等,具体可以参照tq开发板手册。

当图片处理完毕自后,将该文件复制到drivers/video/logo/文件夹下面替换原有的logo_linux_clut224.ppm文件即可。

然后重新生成uImage文件,下载到开发板上运行,即可看到我准备的开机LOGO。

总结:通过这次安装GIMP软件,我发现当安装一个软件需要另外安装许多依赖的时候,可以先到光盘里面找是否有这些依赖包,当然查询的依赖包的名字一定要正确,可以先到百度上搜下这个依赖包,然后再从光盘里面找;而从网上直接找该依赖包放到linux系统中安装是最后应该考虑的。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux-2.6.32.67内核裁剪与移植之LCD驱动的移植(2) 的相关文章

随机推荐