• FL2440驱动添加(3)LCD驱动添加学习笔记


    FL2440 LCD内置控制器,320*240 TFT型LCD。

    自我理解总结的两种添加驱动模式:

    非platform方式添加驱动:

    加载驱动:

    1,硬件初始化,申请内存,并作地址映射

    2,分配设备号,分配结构体

    3,注册设备

    卸载驱动:

    1,释放内存

    2,释放结构体,返还设备号

    3,注销设备

    platform总线方式添加驱动(主流方式):

    1.编写设备链 

    struct platform_device

    {

           const chat *name;

           u32 id;

           struct device dev;

           u32 num_resources;

           struct resources * resources;

    };


    2,编写驱动链

    static struct platform_driver

    {

          int (*probe)( struct platform_device*),//探测函数

          int (*remove)( structplatform_device*),//删除函数

           ……

           struct device_driver driver;

    };


    3,在设备链注册设备和在驱动链注册驱动

    int __init xxx_init()

    {

    .....

    platform_device_register();

    platform_driver_register();

    .....

    }

    4,反向在驱动链注销驱动,在设备链注销设备

    void __exit  xxx_exit()

    {

    .....

    platform_driver_unregister();

    platform_device_unregister();

    .....

    }



    开始添加LCD驱动:内核版本linux-3.8.0

    1,在arch/arm/mach-s3c24xx/mach-smdk2440.c中修改相关信息平台数据

    /* LCD driver info */

    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  = 111111, /* HCLK 60 MHz, divisor 10 */

        .xres      = 480,

        .yres      = 272,

        .bpp       = 16,

        .left_margin    = 38,

        .right_margin   = 20,

        .hsync_len = 30,

        .upper_margin   = 15,

        .lower_margin   = 12,

        .vsync_len = 3,

    };

     

    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<<1,

    };


    2,由于在arch/arm/plat-samsung/devs.c已经定义了LCD的设备以及平台添加函数,如下

    /* LCD Controller */

    #ifdef CONFIG_PLAT_S3C24XX

    static struct resource s3c_lcd_resource[]= {

        [0] = DEFINE_RES_MEM(S3C24XX_PA_LCD, S3C24XX_SZ_LCD),

        [1] = DEFINE_RES_IRQ(IRQ_LCD),

    };

     

    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       = &samsung_device_dma_mask,

            .coherent_dma_mask  = DMA_BIT_MASK(32),

        }

    };


    //平台添加函数

    void __init s3c24xx_fb_set_platdata(structs3c2410fb_mach_info *pd)

    {  

        struct s3c2410fb_mach_info *npd;

     

        npd = s3c_set_platdata(pd, sizeof(*npd), &s3c_device_lcd);

        if (npd) {

            npd->displays =kmemdup(pd->displays,

                sizeof(struct s3c2410fb_display) * npd->num_displays,

                GFP_KERNEL);

            if (!npd->displays)

                printk(KERN_ERR "no memory forLCD display data ");

        } else {

            printk(KERN_ERR "no memory for LCDplatform data ");

        }

    }

    #endif /*CONFIG_PLAT_S3C24XX */

     

     

    所以在arch/arm/mach-s3c24xx/mach-smdk2440.c只需注册设备:

    static struct platform_device *smdk2440_devices[] __initdata = {

        &s3c_device_ohci,

        &s3c_device_lcd,

        &s3c_device_wdt,

        &s3c_device_i2c0,

        &s3c_device_iis,

        &s3c_device_dm9000,

        &s3c_device_adc,   

        &s3c_device_ts,

        &s3c_device_rtc,

        &globalfifo_device

    };

     

    通过调用smdk2440_machine_init添加到设备链,

    static void __init smdk2440_machine_init(void)

    {

        //调用该函数将上面定义的LCD硬件信息保存到平台数据中

        s3c24xx_fb_set_platdata(&smdk2440_fb_info); 

        s3c_i2c0_set_platdata(NULL);

       

        platform_add_devices(smdk2440_devices,ARRAY_SIZE(smdk2440_devices));

        smdk_machine_init();

    }

     

    跟踪platform_add_devices函数,其实际调用了platform_device_register和platform_device_unregister函数,如下:

    在drivers/base/platform.c下定义:

    int platform_add_devices(struct platform_device **devs, int num)
    {   
        int i, ret = 0;
        
        for (i = 0; i < num; i++) {
            ret = platform_device_register(devs[i]);
            if (ret) { 
                while (--i >= 0)
                    platform_device_unregister(devs[i]);
                break;
            }
        }
        
        return ret;
    }
    EXPORT_SYMBOL_GPL(platform_add_devices);
        


    补充:  lcd驱动分析: http://blog.csdn.net/jmq_0000/article/details/7104793

        struct device结构体:http://blog.csdn.net/abo8888882006/article/details/5424363

           lcd原理和驱动:http://blog.csdn.net/luoamforever/article/details/5515564




  • 相关阅读:
    2018/08/23 cstring中memset()函数的运用
    HDU 6446 Tree and Permutation(赛后补题)
    51NOD 1154 回文串的划分(DP)
    第七章小结_查找
    列出连通集的邻接表解题
    第六章学习小结_初识图
    图的邻接矩阵和邻接表及深度优先搜索
    第五章学习小结
    深深深深深深入虎穴
    括号匹配_进阶篇 ( 7-2 符号配对 )
  • 原文地址:https://www.cnblogs.com/xiaoxing/p/3933595.html
Copyright © 2020-2023  润新知