mtk设备模型之LCM

1、Linux设备模型

站在BSP的角度来看,整个系统可以由三部分组成:设备、总线、驱动。

Linux kernel有一些总线,比如USB、I2C等。对于每一个总线都会有一些设备和驱动挂在上面。驱动服务于匹配的设备,使Linux正确的操作硬件设备。当一个设备或者驱动注册到特定的总线上的时候就会触发总线匹配函数,比如一个设备注册到了总线,所有的该总线的驱动都会被枚举,判断是不是可以服务于新添加的设备(一般通过name来匹配),反之亦然。

如果总线匹配成功,就会调用驱动的probe函数,检查指定的硬件确实存在,然后确定是否所需的资源都能够从系统申请。

事实上,设备或者驱动能够正确的合作,在probe之后,模块初始化顺序决定于probe的执行顺序,可以由BSP函数中注册设备的顺序控制。MT6572平台,L版本的BSP文件放在kernel/arch/arm/mach-mt6572/mt_devs.c,mt_board_init()函数控制着probe的顺序。

2、LCM设备模型

对于方案公司的驱动开发人员来说,对于LCM的工作主要是在Mediatek的代码架构下进行兼容和优化。和其他的所有的模块一样,Mediatek的软件架构尽可能的把所有的无需客制化的代码划分出来,从而减少对下游开发人员的工作量。

Mediatek封装了一个结构体给开发人员,包含了所有可能需要克制化的函数指针,对于不同的IC,只需要对应实现相应的函数就可以了。

LCM_DRIVER 结构体的各个成员的介绍如下:

l  在LCM_UTIL_FUNCS这个类型中,主要定义了一些接口函数,这些接口函数是mtk提供给lcm驱动开发者使用的;

l  lcm_compare_id函数中主要是通过读寄存器获取硬件的id号判断和此驱动支持的硬件lcm是否一致,如果一致就选择这个驱动。实现了驱动和设备正确匹配。在后面分析lcm的设备模型中会讲到。

l  lcm_get_params函数中主要是一些参数定义,例如屏的分辨率,屏的接口类型等;

l  下面三个函数主要和上电时序有关

  // for power-onsequence refinement
     void (*init_power)(void);
     void (*suspend_power)(void);
         void(*resume_power)(void);

l  下面几个函数和ESD有关

   /////////////ESD_RECOVERY//////////////////////
    unsigned int(*esd_check)(void);
    unsigned int  (*esd_recover)(void);
    unsigned int(*check_status)(void);
    unsigned int(*ata_check)(unsigned char *buffer);

言归正传,LCM的设备模型也是遵守设备总线驱动结构的,只不过在这个基础上MTK又做了一些工作,封装出LCM_DRIVER 结构体。

总线

platform虚拟总线,关在该总线的设备和驱动通过name来匹配。

设备

在文件Mt_devs.c (arch\arm\mach-mt6572)中定义了LCM设备和资源,代码如下:

驱动

驱动文件出了MTK抽象出来的具体设备驱动文件外,这里指的是挂在platform上的驱动文件。Mtkfb.c (drivers\misc\mediatek\video\mt6572) 。

驱动的名字和设备匹配后,调用驱动的probe进行探测设备,并完成资源申请,sysfs文件系统操作等。最终在/dev/下生成设备文件节点。系统通过uevent通知udev,udev会收集在sysfs/class下面的文件信息,自动创建文件节点。

mtk_fb_probe函数主要做的工作如下:

/* Called by LDM binding to probe andattach a new device.

*Initialization sequence:

*   1.allocate system fb_info structure

*     select panel type according to machine type

*   2.init LCD panel

*   3.init LCD controller and LCD DMA

*   4.init system fb_info structure

*   5.init gfx DMA

*   6.enable LCD panel

*     start LCD frame transfer

*   7.register system fb_info structure

*/

比较关键的函数是mtkfb_find_lcm_driver,这个函数调用具体设备驱动里面的函数和数据(例如:St7796s_hvga_dsi_ivo_txd.c (drivers\misc\mediatek\lcm\st7796s_hvga_dsi_ivo_txd))。

下面对其进行分析:

BOOL mtkfb_find_lcm_driver(void)
{
         p = strstr(saved_command_line, "lcm=");
         if(p== NULL)
         {
                   //we can't find lcm string in the command line, the uboot should be old version
                   returnDISP_SelectDevice(NULL);
         }
         if(DISP_SelectDevice(mtkfb_lcm_name))
                   ret= TRUE;
done:
         returnret;
}

p =strstr(saved_command_line, "lcm=");获取从lk(uboot)传入的cmdline中的"lcm="数据,为LCM设备的名称。众所周知,uboot把控制权交给kernel之后会传入一些参数,其中cmdline为uboot传入kernel参数命令行。可以通过如下指令获得:cat /proc/cmdline .

<< /proc/cmdline >>:

console=tty0 console=ttyMT0,921600n1 root=/dev/ram vmalloc=496Mslub_max_order=0 slub_debug=O 
lcm=1-st7796s_hvga_dsi_ivo_txd fps=5480 vram=4194304bootprof.pl_t=1830 bootprof.lk_t=1628 printk.disable_uart=0ddebug_query="file *mediatek* +p ; file *gpu* =_" boot_reason=0androidboot.serialno=0123456789ABCDEF androidboot.bootreason=power_key

获得LCM名称以后就会调用if(DISP_SelectDevice(mtkfb_lcm_name))
函数根据mtkfb_lcm_name 从LCM_DRIVER链表中获取对应的结构体指针,然后就传入了上面介绍的MTK客制化的一些LCM函数。

问题来了,uboot(LK)是怎么知道LCM的名字的呢?

在LK中也会有和kernel具体LCM驱动相同的设备驱动文件如

St7796s_hvga_dsi_ivo_txd.c(dev\lcm\st7796s_hvga_dsi_ivo_txd)。

LK也会把一系列LCM_DRIVER放入链表中,然后通过调用LCM_DRIVER里面的lcm_compare_id函数进行ID匹配,如果读到硬件的id和此驱动支持的id匹配,则选择此驱动。下面是对LK代码中LCM驱动的选择流程分析。

首先是LK总体代码执行的流程图:

在Kmain()函数中会有以下的函数调用流程:

在函数platform_early_init()函数里进行一系列的硬件初始化,看代码(精简):

void platform_early_init(void)
{
   //preloader won't reach max speed. It will done by LK.
   if (g_boot_arg->boot_mode != DOWNLOAD_BOOT)
    {
    mtk_set_arm_clock();//设置时钟
    }
   /* initialize the uart */
   uart_init_early();//串口初始化
   platform_init_interrupts();//中断
   platform_early_init_timer();//时钟
   mt_gpio_set_default();//gpio
   mt_i2c_init();//i2c
   clk_init();//clk
   mtk_wdt_init();//看门狗
   isink0_init();              //turnon PMIC6329 isink0
    mt_disp_init((void *)g_fb_base);//LCM
#ifdef CONFIG_CFB_CONSOLE
   drv_video_init();
#endif
#if defined(TARGET_S4)
   pmic_init();//pmu
#endif
}

mt_disp_init((void *)g_fb_base);函数会调用

DISP_CHECK_RET(DISP_Init((UINT32)lcdbase, (UINT32)lcdbase, FALSE));

DISP_Init函数在Disp_drv.c(platform\mt6572)    中定义,然后继续调用disp_drv_init_context()函数--》

if(!isLCMFound)

DISP_DetectDevice();

--》

lcm_drv = disp_drv_get_lcm_driver(NULL);

--》判断LCM_DRIVER链表中lcm驱动的数量,如果为1个就直接拿来用给设备,不需要调用compare_id函数,如果多个就需要匹配硬件id号了。

if(lcm_count ==1)
   {
     // we need to verify whether the lcm is connected
     // even there is only one lcm type defined
     lcm = lcm_driver_list[0];
     lcm->set_util_funcs(&lcm_utils);
     lcm->get_params(&s_lcm_params);
     u4IndexOfLCMList = 0;

     lcm_params = &s_lcm_params;
     lcm_drv = lcm;
                   isLCMFound= TRUE;
}
for(i = 0;i < lcm_count;i++)
     {
        ……
           if(lcm->compare_id != NULL && lcm->compare_id())
           {
              printk("\t\t[success]\n");
               isLCMFound = TRUE;
               lcm_drv = lcm;
               u4IndexOfLCMList = i;
               goto done;
           }
         }

驱动找到会把LCD_DRIVER结构体指针赋值到全局变量lcm_drv中。通过调用文件Mt_boot.c (app\mt_boot)中的intboot_linux_from_storage(void)函数

   strlen += sprintf(commanline, "%s lcm=%1d-%s", commanline,DISP_IsLcmFound(), mt_disp_get_lcm_id());
   strlen += sprintf(commanline, "%s fps=%1d", commanline,mt_disp_get_lcd_time());
   strlen += sprintf(commanline, "%s vram=%1d", commanline,DISP_GetVRamSize());

将lcm相关的信息,写到cmdline中,传递给kernel。

时间: 2024-10-09 09:13:55

mtk设备模型之LCM的相关文章

转 Linux设备模型 (1)

作者:wwang 出处:http://www.cnblogs.com/wwang 本文采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接. 随着计算机的周边外设越来越丰富,设备管理已经成为现代操作系统的一项重要任务,这对于Linux来说也是同样的情况.每次Linux内核新版本的发布,都会伴随着一批设备驱动进入内核.在Linux内核里,驱动程序的代码量占有了相当大的比重.下图是我在网络上搜索到的

【linux设备模型】之platform设备驱动

一.platform总线.设备和驱动 platform是一种虚拟总线,对应的设备称为platform_device,对应的驱动称为platform_driver. platform_device定义在<linux/platform_device.h>中: 1 struct platform_device { 2 const char * name; 3 int id; 4 struct device dev; 5 u32 num_resources; 6 struct resource * r

设备模型的基础---kobject,kset

设备模型的基础是kobject,kset,kobj_type.kobject本身并没有什么意义,真正有用的地方在于嵌入了kobject的结构体(对象),kobject可以看成是一个最小单元,sysfs的层次结构中的元素都是由kobject构成. kset与kobject的关系:kset会包含一类的kobject对象(内核链表串起来),而这些对象对应在sysfs中就是同一级的各个子目录,每一个kobject对象有自己的属性,这些属性就对应于各自子目录的文件.如此,就会构成一个有层次的组织结构.ks

Linux设备模型——设备驱动模型和sysfs文件系统解读

本文将对Linux系统中的sysfs进行简单的分析,要分析sysfs就必须分析内核的driver-model(驱动模型),两者是紧密联系的.在分析过程中,本文将以platform总线和spi主控制器的platform驱动为例来进行讲解.其实,platform机制是基于driver-model的,通过本文,也会对platform机制有个简单的了解. 内核版本:2.6.30 1. What is sysfs? 个人理解:sysfs向用户空间展示了驱动设备的层次结构.我们都知道设备和对应的驱动都是由内

转 linux设备模型(4)

作者:wwang 出处:http://www.cnblogs.com/wwang 本文采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接. <Linux设备模型 (2)>和<Linux设备模型 (3)>主要通过一些简单的实作介绍了kobject.kset.kobj_type.attribute等数据结构的用法,但这些实作并没有涉及到实际环境下的设备模型和sysfs.本文将以/sy

分析USB平台设备模型框架(1)

start_kernel rest_init(); kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND); do_basic_setup(); driver_init(); void __init driver_init(void) void __init driver_init(void) { /* These are the core pieces */ devices_init(); 表示在/sys/devices /sys/

设备模型(device-model)之平台总线(bus),驱动(driver),设备(device)

关于关于驱动设备模型相关概念请参考<Linux Device Drivers>等相关书籍,和内核源码目录...\Documentation\driver-model 简单来说总线(bus),驱动(driver),设备(device)这三者之间的关系就是:驱动开发者可以通过总线(bus)来将驱动(driver)和设备(device)进行隔离,这样的好处就是开发者可以将相对稳定不变的驱动(driver)独立起来,可以通过总线(bus)来桥接与之匹配的设备(device).设备(device)只需要

linux设备模型之led子系统(转载)

linux设备模型之led子系统 本文来自转载: http://www.cnblogs.com/gdt-a20 时代不同了,连led都成子系统了,针对内核提供的通用模型,分析一下,好久没写文章了也! 代码位于drivers/leds下,看一下Makefile 模型文件主要是: # LED Core obj-$(CONFIG_NEW_LEDS)            += led-core.o obj-$(CONFIG_LEDS_CLASS)        += led-class.o obj-$

Linux设备模型(3)_Uevent

转自:http://www.wowotech.net/linux_kenrel/uevent.html 1. Uevent的功能 Uevent是Kobject的一部分,用于在Kobject状态发生改变时,例如增加.移除等,通知用户空间程序.用户空间程序收到这样的事件后,会做相应的处理. 该机制通常是用来支持热拔插设备的,例如U盘插入后,USB相关的驱动软件会动态创建用于表示该U盘的device结构(相应的也包括其中的kobject),并告知用户空间程序,为该U盘动态的创建/dev/目录下的设备节