MTK LCM驱动移植

2024-05-09 21:32
文章标签 驱动 移植 mtk lcm

本文主要是介绍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-freeparams->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;
#elseparams->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 MT6573params->dsi.packet_size = 256;// Video mode settingparams->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__); 
#elseprintk("%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];     //98array[0] = 0x00043700;dsi_set_cmdq(array, 1, 1);MDELAY(10);read_reg_v2(0x01, buffer, 4);id_low = buffer[0];     //06array[0] = 0x00043700;dsi_set_cmdq(array, 1, 1);MDELAY(10);read_reg_v2(0x02, buffer, 4);id_low0 = buffer[0];   //04id = (id_high<<16) | (id_low<<8)|id_low0;#ifdef BUILD_LKprintf("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);
#elseprintk("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);
#endifreturn (0x980604 == id) ? 1 : 0;
}

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

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










这篇关于MTK LCM驱动移植的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/974555

相关文章

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

Android 10.0 mtk平板camera2横屏预览旋转90度横屏拍照图片旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,在上一篇已经实现了横屏预览功能,然后发现横屏预览后,拍照保存的图片 依然是竖屏的,所以说同样需要将图片也保存为横屏图标了,所以就需要看下mtk的camera2的相关横屏保存图片功能, 如何实现实现横屏保存图片功能 如图所示: 2.mtk

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

驱动(RK3588S)第七课时:单节点设备树

目录 需求一、设备树的概念1、设备树的后缀名:2、设备树的语法格式3、设备树的属性(重要)4、设备树格式举例 二、设备树所用函数1、如何在内核层种获取设备树节点:2、从设备树上获取 gpio 口的属性3、获取节点上的属性只针对于字符串属性的4、函数读取 np 结点中的 propname 属性的值,并将读取到的 u32 类型的值保存在 out_value 指向的内存中,函数的返回值表示读取到的

驱动安装注册表指令

HKCR: HKEY_CLASSES_ROOT HKCU: HKEY_CURRENT_USER HKLM: HKEY_LOCAL_MACHINE HKU: HEKY_USER HER: 相对根键

UMDF驱动安装

VS2013 + WDF8.1,UMDF驱动选择User Mode Driver,不要选User Mode Driver 2.0,否则Win7安装有问题,如图 另外,在驱动安装时不要忘记WUDFUpdate_<主版本号><次版本号>.dll文件,具体文件名在INF中查找。此文件可在WDF的安装目录中找到。注意:在WDF的安装目录中会有3个WUDFUpdate_xxx.dll文件,x86,x6

MTK Android P/Q system/vendor/super快速打包

一、Android 新版本默认开启了动态分区,把system vendor  product等分区打包成一个super分区。这对于我们使用替换分区的方法来排查问题不是很方便,直接替换一个super也不知道到底是哪个部分导致的。所以我们需要自己制作super.img来缩小范围。下面讲讲如何快速生成system、vendor、super,以及vbmeta(校验image,不匹配可能会导致不开机) 二

MTK平台AndroidP/Q快速生成dtb.img和dtbo.img(2秒生成)

背景: MTK升级新的Android版本后,无法快速编译dtbo image,当我们修改DWS和PROJECT DTS后验证问题非常麻烦,必须删除out下KERNEL_OBJ才能生成新的dtbo.img,而且必须整编。 所以跟据编译流程,写了下面这个脚本,可以快速生成dtbo和dtb image,可以几秒钟完成 使用方法: (1)将脚本放在工程跟目录 (2)修改脚本开头的几个变量,改为你

MTK AndroidP/Q快速打包ramdisk

一、Android P/Q ramdisk与老版本的差异 Android老版本的ramdisk是out下的root/ramdisk打包而来,里面包含了init  /sbin  init.rc   default.prop等文件。是一个完整的ramdisk Android新版本ramdisk分为了out 下的ramdisk目录和root目录,init ,init.rc等文件大部分都放到了syst

Android P/Q MTK平台无依赖打包boot.img

背景:        有时排查版本问题,需要用到替换img的方式来查找问题出现在哪个img,若出现在bootimg,那到底是kernel、DTB 还是ramdisk。此时就需要单独替换其中一个的方式来打包,之前直接make bootimage-nodeps就可以了,但现在发现执行这个命令无效了。下面就分析下新版本如何找到正确的打包命令。 一、找到编译boot的命令 之前Android编译lo