MTK LCM的添加
对于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各项参数;
- LCM_DRIVER ili9806e_drv =
- {
- .name = "ili9806e_txd_dsi_cmd_sp13_lcm_drv", //设备名
- .set_util_funcs = lcm_set_util_funcs, //获取LCM_DRIVER结构
- .get_params = lcm_get_params, //获取lcm参数
- .init = lcm_init, //lcm初始化函数
- .suspend = lcm_suspend, //lcm挂起
- .resume = lcm_resume, //lcm恢复
- .compare_id = lcm_compare_id, //设备id匹配
- };
以上函数接口是为MTK框架中的几个重要接口;
/* 获取设备的LCM_DRIVER结构 */
- static void lcm_set_util_funcs(const LCM_UTIL_FUNCS *util)
- {
- memcpy(&lcm_util, util, sizeof(LCM_UTIL_FUNCS));
- }
- /* 获取lcm各个参数 */
- static void lcm_get_params(LCM_PARAMS *params)
- {
- memset(params, 0, sizeof(LCM_PARAMS)); //先将LCM_PARAMS结构清空
- params->type = LCM_TYPE_DSI; //lcm接口类型
- params->width = FRAME_WIDTH; //lcm显示宽度
- params->height = FRAME_HEIGHT; //lcm显示高度
- /* 设置通信模式 */
- // enable tearing-free
- params->dbi.te_mode = LCM_DBI_TE_MODE_DISABLED;
- params->dbi.te_edge_polarity = LCM_POLARITY_RISING;
- /* dsi分两种模式,一种是cmd模式,一种是video模式 */
- #if (LCM_DSI_CMD_MODE)
- params->dsi.mode = CMD_MODE;
- #else
- params->dsi.mode = SYNC_PULSE_VDO_MODE;
- #endif
- /* 设置数据格式 */
- // DSI
- /* Command mode setting */
- params->dsi.LANE_NUM = LCM_TWO_LANE; //两通道MIPI
- //The following defined the fomat for data coming from LCD engine.
- params->dsi.data_format.color_order = LCM_COLOR_ORDER_RGB;
- params->dsi.data_format.trans_seq = LCM_DSI_TRANS_SEQ_MSB_FIRST;
- params->dsi.data_format.padding = LCM_DSI_PADDING_ON_LSB;
- params->dsi.data_format.format = LCM_DSI_FORMAT_RGB888;
- // Highly depends on LCD driver capability.
- // Not support in MT6573
- params->dsi.packet_size = 256;
- // Video mode setting
- params->dsi.intermediat_buffer_num = 0;
- params->dsi.PS = LCM_PACKED_PS_24BIT_RGB888;
- params->dsi.word_count = 480 * 3;
- /* 垂直参数设置 */
- params->dsi.vertical_sync_active = 4; //垂直同步信号的宽度
- params->dsi.vertical_backporch = 16;//10 //垂直同步信号的后沿
- params->dsi.vertical_frontporch = 20;//8 //垂直同步信号的前沿
- params->dsi.vertical_active_line = FRAME_HEIGHT;
- /* 水平参数设置 */
- params->dsi.horizontal_sync_active = 10; //水平同步信号的宽度
- params->dsi.horizontal_backporch = 50; //水平同步信号的后沿
- params->dsi.horizontal_frontporch = 60; //水平同步信号的前沿
- params->dsi.horizontal_active_pixel = FRAME_WIDTH;
- /* 时钟频率 */
- params->dsi.PLL_CLOCK= 200;
- }
//复位引脚
#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)
/* 初始化参数及函数接口 */
- static struct LCM_setting_table lcm_initialization_setting[] = {
- /* 数据格式:命令,数据个数,数据 */ //命令一般是对应寄存器地址
- {0xFF, 5,{0xFF,0x98,0x06,0x04,0x01}},
- {0x08, 1, {0x10}},
- {0x21, 1, {0x01}},
- {0x30, 1, {0x02}},
- {0x31, 1, {0x02}},
- {0x40, 1, {0x16}},
- {0x41, 1, {0x22}},
- ......
- {0x53, 1, {0x1A}}, //10
- {0xFF, 5,{0xFF,0x98,0x06,0x04,0x07}},
- {0x17, 1, {0x12}}, //22
- {0x02, 1, {0x77}},
- {0xFF, 5,{0xFF,0x98,0x06,0x04,0x00}},
- {0x35,1, {0x00}},
- {0x36,1, {0x03}}, //翻转180度
- {0x11, 1, {0x00}},
- {REGFLAG_DELAY, 120, {}},
- {0x29, 1, {0x00}},
- {REGFLAG_DELAY, 50, {}},
- {REGFLAG_END_OF_TABLE, 0x00, {}} //数据结束必须使用REGFLAG_END_OF_TABLE
- };
- static void lcm_init(void)
- {
- /* 复位 */
- SET_RESET_PIN(1);
- MDELAY(10);
- SET_RESET_PIN(0);
- /* Third change Lava */
- MDELAY(10);//10
- SET_RESET_PIN(1);
- MDELAY(120); // 150
- /* 初始化数据 */
- push_table(lcm_initialization_setting, sizeof(lcm_initialization_setting) / sizeof(struct LCM_setting_table), 1);
- }
/* 设备挂起 */
- static void lcm_suspend(void)
- {
- #ifdef BUILD_LK
- printf("%s, ALS/PS bbbbbbbbbbbbbbb \n", __func__);
- #else
- printk("%s, ALS/PS bbbbbbbbbbbbbb \n", __func__);
- #endif
- push_table(lcm_deep_sleep_mode_in_setting, sizeof(lcm_deep_sleep_mode_in_setting) / sizeof(struct LCM_setting_table), 1);
- SET_RESET_PIN(0);
- MDELAY(20);//10
- SET_RESET_PIN(1);
- MDELAY(50);
- }
因为lcm驱动被映射到lk层,在lk层只能使用printf进行调试,但在kernel层中只能printk进行打印调试,所以可以使用宏进行BUILD_LK区分;
挂起的机制一般有两种:简单睡眠或深度睡眠;
简单睡眠:设备还处于工作状态,可以被唤醒,但是此时也会存在待机功耗等问题;
深度睡眠:设备处于休眠状态,基本处于不工作状态,因此无法被唤醒;
一般程序设计都是使用深度睡眠,在唤醒时进行重新初始化;
/* 设备恢复 */
- static void lcm_resume(void)
- {
- lcm_init();
- //push_table(lcm_sleep_out_setting, sizeof(lcm_sleep_out_setting) / sizeof(struct LCM_setting_table), 1);
- }
重新初始化设备
/* 设备id匹配 */
- static unsigned int lcm_compare_id()
- {
- unsigned int array[4];
- unsigned char buffer[4] = {0,0,0,0};
- unsigned char id_high=0;
- unsigned char id_low=0;
- unsigned char id_low0=0;
- unsigned int id=0;
- /* 先进行复位操作 */
- SET_RESET_PIN(1);
- MDELAY(10);
- SET_RESET_PIN(0);
- MDELAY(10);
- SET_RESET_PIN(1);
- MDELAY(200);
- //*************Enable CMD2 Page1 *******************//
- array[0]=0x00063902;
- array[1]=0x0698ffff;
- array[2]=0x00000104;
- dsi_set_cmdq(array, 3, 1);
- array[0] = 0x00043700;
- dsi_set_cmdq(array, 1, 1);
- MDELAY(10);
- read_reg_v2(0x00, buffer, 4);
- id_high = buffer[0]; //98
- array[0] = 0x00043700;
- dsi_set_cmdq(array, 1, 1);
- MDELAY(10);
- read_reg_v2(0x01, buffer, 4);
- id_low = buffer[0]; //06
- array[0] = 0x00043700;
- dsi_set_cmdq(array, 1, 1);
- MDELAY(10);
- read_reg_v2(0x02, buffer, 4);
- id_low0 = buffer[0]; //04
- id = (id_high<<16) | (id_low<<8)|id_low0;
- #ifdef BUILD_LK
- printf("ILI9806e:id2=%x.\n",id);
- printf("ILI9806e:id4=%x.\n",id_high);
- printf("ILI9806e:id5=%x.\n",id_low);
- printf("ILI9806e:id5=%x.\n",id_low0);
- #else
- printk("ILI9806e:id=%x.\n",id);
- printk("ILI9806e:id_high=%x.\n",id_high);
- printk("ILI9806e:id_low=%x.\n",id_low);
- printk("ILI9806e:id_low=%x.\n",id_low0);
- #endif
- return (0x980604 == id) ? 1 : 0;
- }
数据编写格式是遵循MIPI协议进行编写的
注:如果系统只配置一个lcm设备,lcm_compare_id接口不会调用,只有系统存在多个设备的是才会调用该接口进行匹配;
MTK LCM的添加的更多相关文章
- mtk lcm驱动加载流程 (转载)
平台:mt6582 + Android 4.4 前面就说过,在mtk代码中支持屏是可兼容的,通过调用驱动中的compare_id函数来匹配驱动和屏,这里来细看一下代码. 1. LK部分(mediate ...
- MTK 自定义按键添加广播
一.给自定义按键添加广播 修改PhoneWindowManager.java中的interceptKeyBeforeDispatching方法 /frameworks/base/policy/src/ ...
- MTK LCM帧率设置公式
clk=(width + W total porch)x(height + H total porch)x (6<18bit>或者x8<24bit>)x fps/ lane n ...
- MTK TP手势添加
old: #include "tpd.h" #include "tpd_custom_gt9xx.h" #ifndef TPD_NO_GPIO #include ...
- MTK-TP(触屏)解读一
MTK中的TP代码结构并不复杂,相比于其他的系统更为的简单些.它使用的是input子系统,通过该系统来上报触摸按键. 首先我们来看看TP的文件夹下的各代码文件的功能. 文件名 具体功能 关系文件 tp ...
- 1、硬件IO口配置;
对于MTK TP驱动移植一般分为六部分: 1.硬件IO口配置: 2.TP驱动移植. 3.I2C通信: 4.中断触发: 5.数据上报: 6.虚拟按键. 硬件电路: 1.GPIO配置 打开 mediate ...
- 123_Power Pivot&Power BI DAX函数说明速查
博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 说明 1.基于DAX Studio 2.9.2版本导出整理: 2.DAX Studio网站,及时更新下载,DAX学习利器: ...
- mtk android lcm调试
参考MTK 文档LCM_Customer_document_MT6575.pdf The following shows the steps to add a new LCM driver: (1) ...
- MTK Android4.0.3 ICS 添加缅甸语Myanmar
最近几个项目需要添加缅甸语,借助网络资源,同时结合自身实践,成功添加缅甸语,现分享经验如下. 一. 前期工作: 准备Myanmar字库,下载地址:http://www.myordbok.com/mya ...
随机推荐
- 11-22 JS中级复习
1.this js的关键字, 用途:指向某一个对象. 如何判断this指向 函数(方法)内 一种以函数的方式调用(不带.) this指向winodw 一种以方法的形式调用(函数名前面带.)this指向 ...
- python每日笔记
9.28 查看python包路径: sys.path 9.4 sorted高级用法: >>> class Student: def __init__(self, name, gra ...
- JS膏集02
JS膏集02 1.复习 函数也是对象 2.贪食蛇案例 <!DOCTYPE html> <html lang="en"> <head> <m ...
- Unity中InitializeOnLoad属性的妙用
InitializeOnLoad 属性应用的对象是 静态构造函数,它可以保证在编辑器启动的时候调用此函数.根据这个特性,可以在编辑器中设置定期的回调(帧更新),来实现类似watchFile的功能.这里 ...
- Data type conversion in MongoDB
[问题] I have a collection called Document in MongoDB. Documents in this collection have a field calle ...
- KVM之CPU虚拟化
1.1 为什么要虚拟化CPU 虚拟化技术是指在x86的系统中,一个或以上的客操作系统(Guest Operating System,简称:Guest OS)在一个主操作系统(Host Operatin ...
- 在Ubuntu下添加自定义服务
https://blog.csdn.net/xkjcf/article/details/78698232 在Ubuntu系统中添加自定义服务需要遵从设计启动脚本的模式,下面就是如何编写启动脚本的示例程 ...
- android编码学习
虽然以下博客有点老,但很清晰,有不明白的基础知识,可以来这里找找. 2015年最新Android基础入门教程目录(完结版) 1. 环境配置 Android stodio gradle配置踩过的坑 An ...
- Win10一直弹出 用户账户控制 解决
目录 问题 解决方法一 将appwiz.cpl加入UAC白名单 解决方法二 问题 自从更新了Windows后,就出现了一个问题,隔一段时间就弹出一次下面的对话框,而且如果时间稍长,会弹出多个. 解决方 ...
- 基于R语言的时间序列指数模型
时间序列: (或称动态数列)是指将同一统计指标的数值按其发生的时间先后顺序排列而成的数列.时间序列分析的主要目的是根据已有的历史数据对未来进行预测.(百度百科) 主要考虑的因素: 1.长期趋势(Lon ...