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

1、硬件IO口配置;

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

3、LCM驱动移植;

硬件电路:

  

1、GPIO配置

打开 mediatek\dct\DrvGen.exe

选择 mediatek\custom\xiaoxi\kernel\dct\dct\codegen.dws 配置文件

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

2、背光灯

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

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

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

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

(3)、打开mediatek\config\prj\ProjectConfig.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找到mediatek\custom\common\kernel\lcm\ili9806目录,拷贝mediatek\custom\out\pro\kernel\lcm目录,参与系统的编译,所以对于驱动文件名有没命名要求;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. /* 获取lcm各个参数 */
  6. static void lcm_get_params(LCM_PARAMS *params)
  7. {
  8. memset(params, 0, sizeof(LCM_PARAMS));  //先将LCM_PARAMS结构清空
  9. params->type = LCM_TYPE_DSI;   //lcm接口类型
  10. params->width = FRAME_WIDTH;   //lcm显示宽度
  11. params->height = FRAME_HEIGHT; //lcm显示高度
  12. /* 设置通信模式 */
  13. // enable tearing-free
  14. params->dbi.te_mode = LCM_DBI_TE_MODE_DISABLED;
  15. params->dbi.te_edge_polarity = LCM_POLARITY_RISING;
  16. /* dsi分两种模式,一种是cmd模式,一种是video模式 */
  17. #if (LCM_DSI_CMD_MODE)
  18. params->dsi.mode = CMD_MODE;
  19. #else
  20. params->dsi.mode   = SYNC_PULSE_VDO_MODE;
  21. #endif
  22. /* 设置数据格式 */
  23. // DSI
  24. /* Command mode setting */
  25. params->dsi.LANE_NUM             = LCM_TWO_LANE;   //两通道MIPI
  26. //The following defined the fomat for data coming from LCD engine.
  27. params->dsi.data_format.color_order = LCM_COLOR_ORDER_RGB;
  28. params->dsi.data_format.trans_seq   = LCM_DSI_TRANS_SEQ_MSB_FIRST;
  29. params->dsi.data_format.padding     = LCM_DSI_PADDING_ON_LSB;
  30. params->dsi.data_format.format      = LCM_DSI_FORMAT_RGB888;
  31. // Highly depends on LCD driver capability.
  32. // Not support in MT6573
  33. params->dsi.packet_size = 256;
  34. // Video mode setting
  35. params->dsi.intermediat_buffer_num = 0;
  36. params->dsi.PS = LCM_PACKED_PS_24BIT_RGB888;
  37. params->dsi.word_count = 480 * 3;
  38. /* 垂直参数设置 */
  39. params->dsi.vertical_sync_active = 4;      //垂直同步信号的宽度
  40. params->dsi.vertical_backporch = 16;//10   //垂直同步信号的后沿
  41. params->dsi.vertical_frontporch = 20;//8   //垂直同步信号的前沿
  42. params->dsi.vertical_active_line = FRAME_HEIGHT;
  43. /* 水平参数设置 */
  44. params->dsi.horizontal_sync_active = 10;   //水平同步信号的宽度
  45. params->dsi.horizontal_backporch = 50;     //水平同步信号的后沿
  46. params->dsi.horizontal_frontporch = 60;    //水平同步信号的前沿
  47. params->dsi.horizontal_active_pixel = FRAME_WIDTH;
  48. /* 时钟频率 */
  49. params->dsi.PLL_CLOCK= 200;
  50. }

//复位引脚
#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. static void lcm_init(void)
  25. {
  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 \n", __func__);
  5. #else
  6. printk("%s, ALS/PS bbbbbbbbbbbbbb  \n", __func__);
  7. #endif
  8. push_table(lcm_deep_sleep_mode_in_setting, sizeof(lcm_deep_sleep_mode_in_setting) / sizeof(struct LCM_setting_table), 1);
  9. SET_RESET_PIN(0);
  10. MDELAY(20);//10
  11. SET_RESET_PIN(1);
  12. MDELAY(50);
  13. }

因为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. SET_RESET_PIN(1);
  11. MDELAY(10);
  12. SET_RESET_PIN(0);
  13. MDELAY(10);
  14. SET_RESET_PIN(1);
  15. MDELAY(200);
  16. //*************Enable CMD2 Page1  *******************//
  17. array[0]=0x00063902;
  18. array[1]=0x0698ffff;
  19. array[2]=0x00000104;
  20. dsi_set_cmdq(array, 3, 1);
  21. array[0] = 0x00043700;
  22. dsi_set_cmdq(array, 1, 1);
  23. MDELAY(10);
  24. read_reg_v2(0x00, buffer, 4);
  25. id_high = buffer[0];     //98
  26. array[0] = 0x00043700;
  27. dsi_set_cmdq(array, 1, 1);
  28. MDELAY(10);
  29. read_reg_v2(0x01, buffer, 4);
  30. id_low = buffer[0];     //06
  31. array[0] = 0x00043700;
  32. dsi_set_cmdq(array, 1, 1);
  33. MDELAY(10);
  34. read_reg_v2(0x02, buffer, 4);
  35. id_low0 = buffer[0];   //04
  36. id = (id_high<<16) | (id_low<<8)|id_low0;
  37. #ifdef BUILD_LK
  38. printf("ILI9806e:id2=%x.\n",id);
  39. printf("ILI9806e:id4=%x.\n",id_high);
  40. printf("ILI9806e:id5=%x.\n",id_low);
  41. printf("ILI9806e:id5=%x.\n",id_low0);
  42. #else
  43. printk("ILI9806e:id=%x.\n",id);
  44. printk("ILI9806e:id_high=%x.\n",id_high);
  45. printk("ILI9806e:id_low=%x.\n",id_low);
  46. printk("ILI9806e:id_low=%x.\n",id_low0);
  47. #endif
  48. return (0x980604 == id) ? 1 : 0;
  49. }

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

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

MTK LCM的添加的更多相关文章

  1. mtk lcm驱动加载流程 (转载)

    平台:mt6582 + Android 4.4 前面就说过,在mtk代码中支持屏是可兼容的,通过调用驱动中的compare_id函数来匹配驱动和屏,这里来细看一下代码. 1. LK部分(mediate ...

  2. MTK 自定义按键添加广播

    一.给自定义按键添加广播 修改PhoneWindowManager.java中的interceptKeyBeforeDispatching方法 /frameworks/base/policy/src/ ...

  3. MTK LCM帧率设置公式

    clk=(width + W total porch)x(height + H total porch)x (6<18bit>或者x8<24bit>)x fps/ lane n ...

  4. MTK TP手势添加

    old: #include "tpd.h" #include "tpd_custom_gt9xx.h" #ifndef TPD_NO_GPIO #include ...

  5. MTK-TP(触屏)解读一

    MTK中的TP代码结构并不复杂,相比于其他的系统更为的简单些.它使用的是input子系统,通过该系统来上报触摸按键. 首先我们来看看TP的文件夹下的各代码文件的功能. 文件名 具体功能 关系文件 tp ...

  6. 1、硬件IO口配置;

    对于MTK TP驱动移植一般分为六部分: 1.硬件IO口配置: 2.TP驱动移植. 3.I2C通信: 4.中断触发: 5.数据上报: 6.虚拟按键. 硬件电路: 1.GPIO配置 打开 mediate ...

  7. 123_Power Pivot&Power BI DAX函数说明速查

    博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 说明 1.基于DAX Studio 2.9.2版本导出整理: 2.DAX Studio网站,及时更新下载,DAX学习利器: ...

  8. mtk android lcm调试

    参考MTK 文档LCM_Customer_document_MT6575.pdf The following shows the steps to add a new LCM driver: (1)  ...

  9. MTK Android4.0.3 ICS 添加缅甸语Myanmar

    最近几个项目需要添加缅甸语,借助网络资源,同时结合自身实践,成功添加缅甸语,现分享经验如下. 一. 前期工作: 准备Myanmar字库,下载地址:http://www.myordbok.com/mya ...

随机推荐

  1. Android Studio 2.3 解决小米手机调试安装apk失败问题

    在开发者选项里面,拉到底,把miui优化选项去掉就好了. 参考资料 [问题反馈] Android Studio 2.3 在红米note3手机中 调试安装Apk失败

  2. learning to generate question headlines 讲座

    渣排版预警! 出发点 新闻用户为什么会点: 主观:用户兴趣/热点事件 客观:新闻标题(新闻入口)/新闻内容(更简单,更有趣) 标题分类: surprise,好奇,负例,数字,你,客观的描述,问题的形式 ...

  3. 穷举法、for循环、函数、作用域、斐波那契数

    1.穷举法 枚举所有可能性,直到得到正确的答案或者尝试完所有值. 穷举法经常是解决问题的最实用的方法,它实现起来热别容易,并且易于理解. 2.for循环 for语句一般形式如下: for variab ...

  4. 微信小程序中的单位

    vw:viewpoint width,视窗宽度,1vw等于视窗宽度的1%. vh:viewpoint height,视窗高度,1vh等于视窗高度的1%. rpx:rpx单位是微信小程序中css的尺寸单 ...

  5. Servlet(4)—一个简单的Servlet实例

    简单实例 页面请求登陆,提交表单数据 <body> <form action="loginServlet" method="get"> ...

  6. 20170711 通过阿里云与国家气象局合作的api读取历史辐照数据

    一.概述     今天收到阿里云推送的试用通知,就迫不及待的申请了一个试用key,开始试用.     初步使用之后发现基本可用,至于最后是否适合商用还要看他的收费情况.           接口的使用 ...

  7. JavaScript中Object值合并方法

    原文:https://www.cnblogs.com/fullstack-yang/p/8085206.html ------------------------------------ 前言:在日常 ...

  8. HOWTO: Avizo/Amira使用前的显卡设置(Volume Rendering,Volren不显示)

    关于Avizo或Amira中体渲染不显示的问题,常常有人在问,有人甚至怀疑软件有问题,今天就这个话题总结如下: 首先我们要清楚像Avizo或Amira之类的三维可视化软件,必须是在配有专业显卡的工作站 ...

  9. js 图片base64转file文件的两种方式

    js 图片base64转file文件的两种方式 https://blog.csdn.net/yin13037173186/article/details/83302628 //将base64转换为bl ...

  10. 众里寻他千百度?No!这项技术只需走两步就能“看穿”你!

    电影<碟中谍5>中阿汤哥带上了面具,顺利通过指纹锁,三重物理等重重关卡,却最终仍旧功亏一篑,正是由于“ 火眼金睛 ”——步态识别 .   (图片来源:碟中谍) 中国科学院自动化所的专家日前 ...