• MTK LCM的添加


    对于LCM驱动移植,一般分为三部曲:

    1、硬件IO口配置;

    2、确保LCM背光能够正常点亮;

    3、LCM驱动移植;

    硬件电路:

     

      

     

     

     

    1、GPIO配置

    打开 mediatekdctDrvGen.exe 

    选择 mediatekcustomxiaoxikerneldctdctcodegen.dws 配置文件

    配置LCM PWM引脚、RST复位引脚、DISP_PWM引脚和LCM电源控制引脚



    2、背光灯

    编译烧录后启动系统,验证LCM背光是否能正常点亮,否则无法继续调试LCD;

    3、LCM驱动移植(以ili9806e为例)

    (1)、在mediatekcustomcommonkernellcm目录下创建ili9806目录,将驱动文件拷贝到驱动文件ili9806.c到新创建的目录中;代码自动将lcm软链接到mediatekcustomcommonlk和mediatekcustomcommonuboot目录,因此无需拷贝驱动文件到lk和uboot中;

    (2)、修改mediatekcustomcommonkernellcmmt65xx_lcm_list.c, 在lcm_driver_list 数组中增加:
        extern LCM_DRIVER ili9806e_lcm_drv;
        #if defined(ILI9806)   
             &ili9806e_lcm_drv,  //就是ili9488.c中的LCM_DRIVER结构
        #endif

    (3)、打开mediatekconfigprjProjectConfig.mk修改:
        BUILD_LK=yes 
        CUSTOM_KERNEL_LCM=ili9806   //对应lcm目录驱动的子目录名
        CUSTOM_LK_LCM=ili9806           //对应lcm目录驱动的子目录名
        CUSTOM_UBOOT_LCM=ili9806   //对应lcm目录驱动的子目录名
        LCM_WIDTH=480
        LCM_HEIGHT=800

    系统编译的时候,编译器会根据CUSTOM_KERNEL_LCM、CUSTOM_LK_LCM、CUSTOM_UBOOT_LCM找到mediatekcustomcommonkernellcmili9806目录,拷贝mediatekcustomoutprokernellcm目录,参与系统的编译,所以对于驱动文件名有没命名要求;lk和uboot同理;

    注:系统此时也会产生ILI9806的环境变量,这就是mt65xx_lcm_list.c中的 #if defined(ILI9806) 可以进行预编译处理;

    4、LCM驱动简要解析

    LCM_DRIVER结构表示一个LCM对象,里边包含LCM各项参数;

    1. LCM_DRIVER ili9806e_drv =   
    2. {  
    3.     .name          = "ili9806e_txd_dsi_cmd_sp13_lcm_drv",   //设备名  
    4.     .set_util_funcs = lcm_set_util_funcs,    //获取LCM_DRIVER结构  
    5.     .get_params     = lcm_get_params,  //获取lcm参数  
    6.     .init           = lcm_init,      //lcm初始化函数  
    7.     .suspend        = lcm_suspend,   //lcm挂起  
    8.     .resume         = lcm_resume,    //lcm恢复  
    9.     .compare_id     = lcm_compare_id,  //设备id匹配  
    10. };  

    以上函数接口是为MTK框架中的几个重要接口;

    /* 获取设备的LCM_DRIVER结构 */

    1. static void lcm_set_util_funcs(const LCM_UTIL_FUNCS *util)  
    2. {  
    3.     memcpy(&lcm_util, util, sizeof(LCM_UTIL_FUNCS));  
    4. }  
    5.   
    6. /* 获取lcm各个参数 */  
    7. static void lcm_get_params(LCM_PARAMS *params)  
    8. {  
    9.     memset(params, 0, sizeof(LCM_PARAMS));  //先将LCM_PARAMS结构清空  
    10.       
    11.     params->type = LCM_TYPE_DSI;   //lcm接口类型  
    12.     params->width = FRAME_WIDTH;   //lcm显示宽度  
    13.     params->height = FRAME_HEIGHT; //lcm显示高度  
    14.         /* 设置通信模式 */  
    15.     // enable tearing-free  
    16.     params->dbi.te_mode = LCM_DBI_TE_MODE_DISABLED;  
    17.     params->dbi.te_edge_polarity = LCM_POLARITY_RISING;  
    18.         /* dsi分两种模式,一种是cmd模式,一种是video模式 */  
    19. #if (LCM_DSI_CMD_MODE)  
    20.     params->dsi.mode = CMD_MODE;  
    21. #else  
    22.     params->dsi.mode   = SYNC_PULSE_VDO_MODE;  
    23. #endif  
    24.         /* 设置数据格式 */  
    25.     // DSI  
    26.     /* Command mode setting */  
    27.     params->dsi.LANE_NUM             = LCM_TWO_LANE;   //两通道MIPI  
    28.     //The following defined the fomat for data coming from LCD engine.  
    29.     params->dsi.data_format.color_order = LCM_COLOR_ORDER_RGB;     
    30.     params->dsi.data_format.trans_seq   = LCM_DSI_TRANS_SEQ_MSB_FIRST;  
    31.     params->dsi.data_format.padding     = LCM_DSI_PADDING_ON_LSB;  
    32.     params->dsi.data_format.format      = LCM_DSI_FORMAT_RGB888;   
    33.   
    34.     // Highly depends on LCD driver capability.  
    35.     // Not support in MT6573  
    36.     params->dsi.packet_size = 256;  
    37.   
    38.     // Video mode setting  
    39.     params->dsi.intermediat_buffer_num = 0;  
    40.   
    41.     params->dsi.PS = LCM_PACKED_PS_24BIT_RGB888;  
    42.     params->dsi.word_count = 480 * 3;  
    43.         /* 垂直参数设置 */  
    44.     params->dsi.vertical_sync_active = 4;      //垂直同步信号的宽度  
    45.     params->dsi.vertical_backporch = 16;//10   //垂直同步信号的后沿  
    46.     params->dsi.vertical_frontporch = 20;//8   //垂直同步信号的前沿  
    47.     params->dsi.vertical_active_line = FRAME_HEIGHT;  
    48.         /* 水平参数设置 */  
    49.     params->dsi.horizontal_sync_active = 10;   //水平同步信号的宽度  
    50.     params->dsi.horizontal_backporch = 50;     //水平同步信号的后沿  
    51.     params->dsi.horizontal_frontporch = 60;    //水平同步信号的前沿  
    52.     params->dsi.horizontal_active_pixel = FRAME_WIDTH;  
    53.         /* 时钟频率 */  
    54.     params->dsi.PLL_CLOCK= 200;  
    55. }  

     

    //复位引脚
    #define SET_RESET_PIN(v) (lcm_util.set_reset_pin((v)))     //这里就会直接使用GPIO_LCD_RST硬引脚
    //延时函数   
    #define UDELAY(n) (lcm_util.udelay(n))  
    #define MDELAY(n) (lcm_util.mdelay(n))  

     

    /* 数据传输接口 */
    //long packet 操作接口
    #define dsi_set_cmdq_V3(para_tbl, size, force_update)       lcm_util.dsi_set_cmdq_V3(para_tbl, size, force_update)     //para_tbl:LCM_setting_table结构, size:大小, force_update:强制更新标志
    #define dsi_set_cmdq_V2(cmd, count, ppara, force_update)     lcm_util.dsi_set_cmdq_V2(cmd, count, ppare, force_update) //cmd:命令, count:大小, ppara:参数,force_update:强制更新标志
    //short packet 操作接口
    #define dsi_set_cmdq(pdata, queue_size, force_update)       lcm_util.dsi_set_cmdq(pdata, queue_size, force_update)  


    //读写寄存器等操作
    #define write_cmd(cmd)                      lcm_util.dsi_write_cmd(cmd)  
    #define write_regs(addr, pdata, byte_nums)          lcm_util.dsi_write_regs(addr, pdata, bytes_nums)  
    #define read_reg(cmd)                       lcm_util.dsi_dcs_read_lcm_reg(cmd)  
    #define read_reg_v2(cmd, buffer, buffer_size)           lcm_util.dsi_dcs_read_lcm_reg_v2(cmd, buffer, buffer_size)  

    /* 初始化参数及函数接口 */

    1. static struct LCM_setting_table lcm_initialization_setting[] = {  
    2.         /* 数据格式:命令,数据个数,数据 */  //命令一般是对应寄存器地址  
    3.     {0xFF, 5,{0xFF,0x98,0x06,0x04,0x01}},     
    4.     {0x08, 1, {0x10}},  
    5.     {0x21, 1, {0x01}},  
    6.     {0x30, 1, {0x02}},  
    7.     {0x31, 1, {0x02}},  
    8.     {0x40, 1, {0x16}},    
    9.     {0x41, 1, {0x22}},    
    10.      ......  
    11.     {0x53, 1, {0x1A}}, //10     
    12.     {0xFF, 5,{0xFF,0x98,0x06,0x04,0x07}},  
    13.     {0x17, 1, {0x12}}, //22  
    14.     {0x02, 1, {0x77}},  
    15.     {0xFF, 5,{0xFF,0x98,0x06,0x04,0x00}},  
    16.     {0x35,1,    {0x00}},  
    17.     {0x36,1,    {0x03}},  //翻转180度  
    18.     {0x11,  1,  {0x00}},  
    19.     {REGFLAG_DELAY, 120, {}},  
    20.     {0x29,  1,  {0x00}},  
    21.     {REGFLAG_DELAY, 50, {}},  
    22.     {REGFLAG_END_OF_TABLE, 0x00, {}}  //数据结束必须使用REGFLAG_END_OF_TABLE  
    23. };  
    24.   
    25. static void lcm_init(void)  
    26. {  
    1.         /* 复位 */  
    2.     SET_RESET_PIN(1);     
    3.     MDELAY(10);  
    4.     SET_RESET_PIN(0);  
    5.     /* Third change Lava */  
    6.     MDELAY(10);//10   
    7.     SET_RESET_PIN(1);  
    8.     MDELAY(120);    // 150  
    9.         /* 初始化数据 */  
    10.     push_table(lcm_initialization_setting, sizeof(lcm_initialization_setting) / sizeof(struct LCM_setting_table), 1);  
    11. }  


    /* 设备挂起 */

    1. static void lcm_suspend(void)  
    2. {  
    3. #ifdef BUILD_LK     
    4.     printf("%s, ALS/PS bbbbbbbbbbbbbbb  ", __func__);   
    5. #else  
    6.     printk("%s, ALS/PS bbbbbbbbbbbbbb   ", __func__);     
    7. #endif    
    8.   
    9.     push_table(lcm_deep_sleep_mode_in_setting, sizeof(lcm_deep_sleep_mode_in_setting) / sizeof(struct LCM_setting_table), 1);  
    10.     SET_RESET_PIN(0);  
    11.     MDELAY(20);//10   
    12.     SET_RESET_PIN(1);  
    13.     MDELAY(50);  
    14. }  

     因为lcm驱动被映射到lk层,在lk层只能使用printf进行调试,但在kernel层中只能printk进行打印调试,所以可以使用宏进行BUILD_LK区分;

    挂起的机制一般有两种:简单睡眠或深度睡眠;

    简单睡眠:设备还处于工作状态,可以被唤醒,但是此时也会存在待机功耗等问题;

    深度睡眠:设备处于休眠状态,基本处于不工作状态,因此无法被唤醒;

    一般程序设计都是使用深度睡眠,在唤醒时进行重新初始化;


    /* 设备恢复 */

    1. static void lcm_resume(void)  
    2. {  
    3.     lcm_init();  
    4.     //push_table(lcm_sleep_out_setting, sizeof(lcm_sleep_out_setting) / sizeof(struct LCM_setting_table), 1);  
    5. }  

    重新初始化设备

    /* 设备id匹配 */

    1. static unsigned int lcm_compare_id()  
    2. {  
    3.     unsigned int array[4];  
    4.     unsigned char buffer[4] = {0,0,0,0};  
    5.     unsigned char id_high=0;  
    6.     unsigned char id_low=0;  
    7.     unsigned char id_low0=0;  
    8.     unsigned int id=0;  
    9.   
    10.     /* 先进行复位操作 */  
    11.     SET_RESET_PIN(1);  
    12.     MDELAY(10);  
    13.     SET_RESET_PIN(0);  
    14.     MDELAY(10);  
    15.     SET_RESET_PIN(1);  
    16.     MDELAY(200);  
    17.       
    18. //*************Enable CMD2 Page1  *******************//  
    19.     array[0]=0x00063902;  
    20.     array[1]=0x0698ffff;  
    21.     array[2]=0x00000104;  
    22.     dsi_set_cmdq(array, 3, 1);  
    23.   
    24.     array[0] = 0x00043700;  
    25.     dsi_set_cmdq(array, 1, 1);  
    26.     MDELAY(10);  
    27.     read_reg_v2(0x00, buffer, 4);  
    28.     id_high = buffer[0];     //98  
    29.   
    30.     array[0] = 0x00043700;  
    31.     dsi_set_cmdq(array, 1, 1);  
    32.     MDELAY(10);  
    33.     read_reg_v2(0x01, buffer, 4);  
    34.     id_low = buffer[0];     //06  
    35.   
    36.     array[0] = 0x00043700;  
    37.     dsi_set_cmdq(array, 1, 1);  
    38.     MDELAY(10);  
    39.     read_reg_v2(0x02, buffer, 4);  
    40.     id_low0 = buffer[0];   //04  
    41.   
    42.     id = (id_high<<16) | (id_low<<8)|id_low0;  
    43.   
    44. #ifdef BUILD_LK  
    45.     printf("ILI9806e:id2=%x. ",id);  
    46.     printf("ILI9806e:id4=%x. ",id_high);  
    47.     printf("ILI9806e:id5=%x. ",id_low);  
    48.     printf("ILI9806e:id5=%x. ",id_low0);  
    49. #else  
    50.     printk("ILI9806e:id=%x. ",id);  
    51.     printk("ILI9806e:id_high=%x. ",id_high);  
    52.     printk("ILI9806e:id_low=%x. ",id_low);  
    53.     printk("ILI9806e:id_low=%x. ",id_low0);  
    54. #endif  
    55.              
    56.     return (0x980604 == id) ? 1 : 0;  
    57. }  

    数据编写格式是遵循MIPI协议进行编写的

    注:如果系统只配置一个lcm设备,lcm_compare_id接口不会调用,只有系统存在多个设备的是才会调用该接口进行匹配;

  • 相关阅读:
    JS鼠标滚动事件
    [Harbor]Harbor简要介绍
    [Kubernetes]yaml文件详解
    [Kubernetes]安装和配置kubectl
    [Docker]如何批量删除镜像
    [Kubernetes]如何使用yaml文件使得可以向外暴露服务
    [Jenkins]CentOS7下Jenkins搭建
    [Docker]Docker拉取,上传镜像到Harbor仓库
    [Harbor]Docker登录Harbor仓库(HTTP方式)
    [Docker]CentOS7通过rpm包安装Docker
  • 原文地址:https://www.cnblogs.com/zxouxuewei/p/8670397.html
Copyright © 2020-2023  润新知