706m:
D14 - GPIO83 - VLCD_AVDD_EN - LCM_STBY
AA25 - GPIO70 - LCM_RESET
VGP1 - VGP1_PMU - LCM_VDD
863:
AA3 - GPIO17 - LCM_VDD_EN - LCM_VDD33
AA4 - GPIO18 - GPIO_LCM_PWR_EN
AA24 - GPIO68 - LPTE - LCM_STBY
AA25 - GPIO70 - LCM_RESET
VGP1 - VGP1_PMU - LCM_VDD18
屏的数据接口一般的有RGB TTL、LVDS、MIPI、EDP
RGB TTL接口信号类型是TTL电平,信号的内容是RGB666或者RGB888还有行场同步和时钟;
LVDS接口信号类型是LVDS信号(低电压差分对),信号的内容是RGB数据还有行场同步和时钟;
MIPI DSI接口信号类型是LVDS信号,信号的内容是视频流数据和控制指令。
EDP接口在笔记本行业广泛使用,支持超高分辨率(>1080P)
RGB TTL 接口,数据传输速率不高,传输距离较短,且抗电磁干扰能力也比较差,排线数量多,不符合智能设备轻薄的要求,用的很少
一般不用下初始化代码,只需填充对应屏驱动中lcm_get_params的参数即可,如下:
RGB params
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | static void lcm_get_params(LCM_PARAMS *params) { memset(params, 0, sizeof(LCM_PARAMS));
params->type = LCM_TYPE_DPI;
params->width = FRAME_WIDTH; params->height = FRAME_HEIGHT; //params->ctrl = LCM_CTRL_SERIAL_DBI; //params->io_select_mode = 0; params->density = 160; params->dpi.format = LCM_DPI_FORMAT_RGB888; //LCM_DPI_FORMAT_RGB666; //LCM_DPI_FORMAT_RGB565 params->dpi.rgb_order = LCM_COLOR_ORDER_RGB;
params->dpi.clk_pol = LCM_POLARITY_RISING; params->dpi.de_pol = LCM_POLARITY_RISING; params->dpi.vsync_pol = LCM_POLARITY_RISING; //LCM_POLARITY_FALLING; params->dpi.hsync_pol = LCM_POLARITY_RISING; //LCM_POLARITY_FALLING;
params->dpi.hsync_pulse_width = 48; //48 params->dpi.hsync_back_porch = 40; //112 params->dpi.hsync_front_porch = 40; //160
params->dpi.vsync_pulse_width = 2; //10 params->dpi.vsync_back_porch = 31; //13 params->dpi.vsync_front_porch = 13; //12 params->dpi.width = FRAME_WIDTH; params->dpi.height = FRAME_HEIGHT; //params->dpi.is_serial_output = 0; //params->dpi.intermediat_buffer_num = 0;
params->dpi.PLL_CLOCK = 29; //51; params->dpi.ssc_disable = 1;
params->dpi.lvds_tx_en = 0;
params->dpi.io_driving_current = LCM_DRIVING_CURRENT_2MA; //LCM_DRIVING_CURRENT_4MA //LCM_DRIVING_CURRENT_8MA } |
EDP 一般需要外挂IC,此类屏驱动一律由驱动工程师负责。
LVDS 一般不用下初始化代码,只需填充对应屏驱动中lcm_get_params的参数即可,如下:
LVDS params
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | static void lcm_get_params(struct LCM_PARAMS *params) { memset(params, 0, sizeof(struct LCM_PARAMS)); params->type = LCM_TYPE_DPI; params->width = FRAME_WIDTH; params->height = FRAME_HEIGHT; params->dpi.format = LCM_DPI_FORMAT_RGB888; //LCM_DPI_FORMAT_RGB666; //LCM_DPI_FORMAT_RGB565 params->dpi.rgb_order = LCM_COLOR_ORDER_RGB; params->dpi.clk_pol = LCM_POLARITY_FALLING; params->dpi.de_pol = LCM_POLARITY_RISING; params->dpi.vsync_pol = LCM_POLARITY_FALLING; params->dpi.hsync_pol = LCM_POLARITY_FALLING; params->dpi.hsync_pulse_width = 16; params->dpi.hsync_back_porch = 16; params->dpi.hsync_front_porch = 32; params->dpi.vsync_pulse_width = 2; params->dpi.vsync_back_porch = 2; params->dpi.vsync_front_porch = 4; params->dpi.width = FRAME_WIDTH; params->dpi.height = FRAME_HEIGHT; params->dpi.PLL_CLOCK = 67; params->dsi.PLL_CLOCK = 150; params->dpi.ssc_disable = 1; params->dpi.lvds_tx_en = 1; } |
我们用的绝大多数还是MIPI屏
新平台和新板型的点屏工作统一由驱动工程师/公版负责人完成。
首先介绍的是如何在公版版型已经OK的情况下,添加一个屏驱动,以8321 8638 SAT080AT30I21BR3_MIPI屏为例
1.拿到LCD规格书,确定屏的分辨率、数据接口类型、通道数

2.Android代码拉下来之后,执行脚本./clone_project.sh tb8321p2_bsp_8638
我们查看tb8321p2_bsp.mk里面,公版默认配置了K080_IM2B801_B_MIPI这个屏,里面的供电引脚和上下电时序都是配置好了的
/vendor/mediatek/proprietary/bootable/bootloader/lk/project/tb8321p2_bsp.mk
1 | CUSTOM_LK_LCM = "K080_IM2B801_B_MIPI" |
3.我们将这个屏驱动复制一份,将文件夹和文件名都改成 SAT080AT30I21BR3_MIPI
--->>> 
--->>> 
4.把lk和kernel驱动的6个文件都用notepad++打开,替换掉所有文件里面的名字

注意是将"K080_IM2B801_B"替换成"SAT080AT30I21BR3",不是将"K080_IM2B801_B_MIPI"替换成"SAT080AT30I21BR3_MIPI"
因为有些相关变量是没有"MIPI"字符串的,比如:

5.打开两个文件,将以下截图高亮字符串改成小写字母(不改也可以,只是为了统一)
\vendor\mediatek\proprietary\bootable\bootloader\lk\dev\lcm\SAT080AT30I21BR3_MIPI\SAT080AT30I21BR3_MIPI.c
\kernel-4.9-lc\drivers\misc\mediatek\lcm\SAT080AT30I21BR3_MIPI\SAT080AT30I21BR3_MIPI.c
--->>> 
6.添加至lcm_driver_list
\vendor\mediatek\proprietary\bootable\bootloader\lk\dev\lcm\mt65xx_lcm_list.c
1 2 3 4 5 6 7 | extern LCM_DRIVER sat080at30i21br3_mipi_drv; //这个是第5步高亮的字符串
LCM_DRIVER *lcm_driver_list[] = { #if defined(SAT080AT30I21BR3_MIPI) //这个是驱动文件夹的名字 &sat080at30i21br3_mipi_drv, //这个是第5步高亮的字符串 #endif } |
\kernel-4.9-lc\drivers\misc\mediatek\lcm\mt65xx_lcm_list.h
1 | extern struct LCM_DRIVER sat080at30i21br3_mipi_drv; //这个是第5步高亮的字符串 |
\kernel-4.9-lc\drivers\misc\mediatek\lcm\mt65xx_lcm_list.c
1 2 3 4 5 | struct LCM_DRIVER *lcm_driver_list[] = { #if defined(SAT080AT30I21BR3_MIPI) //这个是驱动文件夹的名字 &sat080at30i21br3_mipi_drv, //这个是第5步高亮的字符串 #endif } |
7.检查分辨率是否正确
\vendor\mediatek\proprietary\bootable\bootloader\lk\dev\lcm\SAT080AT30I21BR3_MIPI\SAT080AT30I21BR3_MIPI.c
\kernel-4.9-lc\drivers\misc\mediatek\lcm\SAT080AT30I21BR3_MIPI\SAT080AT30I21BR3_MIPI.c
1 2 | #define FRAME_WIDTH (800) #define FRAME_HEIGHT (1280) |
8.填写前后肩参数

\vendor\mediatek\proprietary\bootable\bootloader\lk\dev\lcm\SAT080AT30I21BR3_MIPI\SAT080AT30I21BR3_MIPI.c
\kernel-4.9-lc\drivers\misc\mediatek\lcm\SAT080AT30I21BR3_MIPI\SAT080AT30I21BR3_MIPI.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | static void lcm_get_params(struct LCM_PARAMS *params) { memset(params, 0, sizeof(struct LCM_PARAMS)); params->type = LCM_TYPE_DSI; params->width = FRAME_WIDTH; params->height = FRAME_HEIGHT; params->dsi.mode = SYNC_PULSE_VDO_MODE; //SYNC_EVENT_VDO_MODE; //BURST_VDO_MODE; //CMD_MODE; // DSI /* Command mode setting */ params->dsi.LANE_NUM = LCM_THREE_LANE; //LCM_TWO_LANE; //LCM_FOUR_LANE; //The following defined the fomat for data coming from LCD engine. params->dsi.data_format.format = LCM_DSI_FORMAT_RGB888; //LCM_DSI_FORMAT_RGB666; //LCM_DSI_FORMAT_RGB565; // Video mode setting params->dsi.PS = LCM_PACKED_PS_24BIT_RGB888; //LCM_PACKED_PS_18BIT_RGB666; //LCM_PACKED_PS_16BIT_RGB565; params->dsi.vertical_sync_active = 4; //4; params->dsi.vertical_backporch = 8; //20; params->dsi.vertical_frontporch = 30; //10; params->dsi.vertical_active_line = FRAME_HEIGHT; params->dsi.horizontal_sync_active = 20; //20; params->dsi.horizontal_backporch = 20; //20; params->dsi.horizontal_frontporch = 20; //20; params->dsi.horizontal_active_pixel = FRAME_WIDTH; // Bit rate calculation //params->dsi.pll_div1 = 0; //params->dsi.pll_div2 = 1; //params->dsi.fbk_div = 21; params->dsi.PLL_CLOCK = 280; //300; //230; //260; //params->dsi.cont_clock = 1; //params->dpi.io_driving_current = LCM_DRIVING_CURRENT_8MA; //chy add //params->dsi.horizontal_bllp = 0x115; //word count=0x340 } |
Video模式又分三种子模式:
1 Non-burst Mode Sync pulses: 在这种模式下,DSI基于各类不一样的同步数据包来作数据同步。这种数据包括:重构,时间校准等。更具体的请参考DSI协议标准。
2 Non-burst Mode Sync event: 这种模式和第一种模式很像,可是这种模式不会发重构和时间校准的数据包,它们只发送一种叫作”Sync event”的包。
3 Burst mode: 在horizontal 的时序是同样的状况下DSI会把链接的速度提高到Panel支持的最大速度。在这种模式下发送RGB数据包的时间被压缩,以留出更多的时间用来传送其余的数据。
9.拿到LCD初始化参数,并转换为MTK驱动的代码格式
屏幕初始化根据供应商的不同代码格式也不同,但都是寄存器在前,寄存器的值在后,类似下面的文件
1 2 3 4 5 6 7 8 9 10 11 | DCS_Long_Write_3P(0xFF,0x98,0x81,0x03); //寄存器0xFF 寄存器的值0x98,0x81,0x03 DCS_Long_Write_1P(0x01,0x00); //寄存器0x01 寄存器的值0x00
Solomon_REG_WR(0xD6,0x05); //寄存器0xD6 寄存器的值0x05 Solomon_REG_WR(0xB9,0xC0); //寄存器0xD6 寄存器的值0xC0 Solomon_REG_WR(0xB3,0x01,0x02,0x03,0x04,0x07,0x0B,0x1E,0x1E,0x1C); //寄存器0xB3 后面都是值
DCS_Short_Write_NP(0x11); //11、29都是固定的,基本每个mipi屏都要下 Delay(120); DCS_Short_Write_NP(0x29); Delay(20); |
MTK驱动代码格式一:
使用notepad++手动将以上代码改成下面这种形式
C Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | static struct LCM_setting_table lcm_initialization_setting[] = { {0xFF, 3, {0X98,0X81,0X03}}, //寄存器0xFF,下3个参数:0X98,0X81,0X03 {0x01, 1, {0x00}}, //寄存器0x01,下1个参数:0x00
{0xD6, 1, {0x05}}, {0xB9, 1, {0xC0}}, {0xB3, 9, {0x01,0x02,0x03,0x04,0x07,0x0B,0x1E,0x1E,0x1C}}, //SLP OUT {0x11, 0, {0x00}}, {REGFLAG_DELAY, 120, {}}, //DISP ON {0x29, 0, {0x00}}, {REGFLAG_DELAY, 20, {}}, //--- TE----// //{0x35, 0, {0x00}}, //{REGFLAG_END_OF_TABLE, 0x00, {}} } |
然后在lcm_init()函数中使用push_table下参数
C Code
1 2 3 4 5 6 | static void lcm_init(void) { printf("[LK/LCM] lcm_init() enter\n"); //init_lcm_registers(); push_table(lcm_initialization_setting, sizeof(lcm_initialization_setting) / sizeof(struct LCM_setting_table), 1); } |
MTK驱动代码格式二:
使用CodeConvert工具将"MTK驱动代码格式一" 转换为 "MTK驱动代码格式二":

转换之后,将右边所有的"&data_array"都替换成"data_array"
然后将右边所有代码复制到init_lcm_registers()函数中:
C Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | static void init_lcm_registers(void) { unsigned int data_array[16]; data_array[0]=0x00043902; data_array[1]=0x038198FF; dsi_set_cmdq(data_array,2,1); data_array[0]=0x00023902; data_array[1]=0x00000001; dsi_set_cmdq(data_array,2,1); data_array[0]=0x00023902; data_array[1]=0x000005D6; dsi_set_cmdq(data_array,2,1); data_array[0]=0x00023902; data_array[1]=0x0000C0B9; dsi_set_cmdq(data_array,2,1); data_array[0]=0x000A3902; data_array[1]=0x030201B3; data_array[2]=0x1E0B0704; data_array[3]=0x00001C1E; dsi_set_cmdq(data_array,4,1); //SLP OUT data_array[0]=0x00110500; //记得最后加上11、29 dsi_set_cmdq(data_array,1,1); MDELAY(120); //DISP ON data_array[0]=0x00290500; dsi_set_cmdq(data_array,1,1); MDELAY(20); //--- TE----// //data_array[0]=0x00350500; //dsi_set_cmdq(data_array,1,1); } |
然后在lcm_init()函数中调用init_lcm_registers()下参数
C Code
1 2 3 4 5 6 | static void lcm_init(void) { printf("[LK/LCM] lcm_init() enter\n"); init_lcm_registers(); //push_table(lcm_initialization_setting, sizeof(lcm_initialization_setting) / sizeof(struct LCM_setting_table), 1); } |
举例说明,格式一是如何转换为格式二的:
{0xB3, 9, {0x01,0x02,0x03,0x04,0x07,0x0B,0x1E,0x1E,0x1C}}, //9代表参数的个数
data_array[0]=0x000A3902; //0x0A 代表所有数据的个数(1个寄存器+9个参数)。"3902"代表下参数的格式,这个是固定的
data_array[1]=0x030201B3; //从低8位开始,从右往左填充数据(第一个为寄存器,然后紧跟着参数)
data_array[2]=0x1E0B0704; //继续从右往左填充数据
data_array[3]=0x00001C1E; //参数填充之后,如果不够32位,那么最后的数据补上0
dsi_set_cmdq(data_array,4,1); //4代表以上data_array数组的个数
注意:
1. 8321只支持2lanes或者3lanes,一般客户给过来的初始化参数都是4lanes的,要询问FAE如何更改成3lanes
2. 8321必须使用"MTK驱动代码格式二",如果用"MTK驱动代码格式一",可能会存在初始化参数丢失的情况
3. 使用CodeConvert工具的时候,需要用UE或者Notepad++统计转换前的寄存器个数和转换后的是否一致
因为该工具有个bug,碰到以下两种情况,转换就会出问题:
3.1 如下图左边第2行红框,如果寄存器是0x00,那么CodeConvert无法转换,直接丢弃该数据
3.2 如下图左边第4行
{0x0C, 10, {0x01,0x02,0x03,0x00,0x00,0x00,0x00,0x08,0x09,0x0A}}; 正确转换之后应该是:
data_array[0]=0x000B3902;
data_array[1]=0x0302010C;
data_array[2]=0x00000000; //但这一行的数据全是0,所以CodeConvert就会丢弃这一行及下面所有的数据
data_array[3]=0x000A0908;
dsi_set_cmdq(data_array,4,1);
于是就形成以下残缺的参数:
data_array[0]=0x000B3902;
data_array[1]=0x0302010C;
dsi_set_cmdq(data_array,2,1);

所以,在使用CodeConvert工具的是要要格外留意0x00的情况,并且统计转换前后的参数个数是否一致,如果发现漏数据或者残缺数据,需要手动修正。
10.如果确定要修改供电引脚,那么请参考以下修改,否则可以跳过这一步。
如果不清楚要操作哪个引脚,请与硬件工程师确定,现以LCM_VDD33为例,查看原理图:

LCM_VDD33是受U1202的LDO VOUT控制,LCM_VDD_EN 使能LDO之后LCM_VDD33就会出来3.3V

而LCM_VDD_EN对应着CPU的AA3接口

查看GPIO LIST表可得AA3对应着GPIO17

使用DrvGen.exe打开codegen.dw,修改GPIO配置 (\vendor\mediatek\proprietary\scripts\dct\old_dct\DrvGen.exe)
\kernel-4.9-lc\drivers\misc\mediatek\dws\mt6580\tb8321p2_bsp.dws
\vendor\mediatek\proprietary\bootable\bootloader\preloader\custom\tb8321p2_bsp\dct\dct\codegen.dws
\vendor\mediatek\proprietary\bootable\bootloader\lk\target\tb8321p2_bsp\dct\dct\codegen.dws
\vendor\mediatek\proprietary\custom\tb8321p2_bsp\kernel\dct\dct\codegen.dws

LK部分:
在屏驱动定义GPIO_LCD_PWER_EN引脚,GPIO17这个枚举可以直接使用,因为已经定义在gpio_const.h了
\vendor\mediatek\proprietary\bootable\bootloader\lk\dev\lcm\SAT080AT30I21BR3_MIPI\SAT080AT30I21BR3_MIPI.c
1 2 3 4 5 6 7 8 | #ifdef MT8321_TB_8638_PROJECT #ifdef GPIO_LCM_PWR_EN #define GPIO_LCD_PWR_EN GPIO_LCM_PWR_EN #else #define GPIO_LCD_PWR_EN (GPIO17 | 0x80000000) #endif
... ... |
\vendor\mediatek\proprietary\bootable\bootloader\lk\platform\mt6580\include\platform\gpio_const.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /****************************************************************************** * Enumeration for GPIO pin ******************************************************************************/ typedef enum GPIO_PIN { GPIO_UNSUPPORTED = -1,
GPIO0 , GPIO1 , GPIO2 , GPIO3 , GPIO4 , GPIO5 , GPIO6 , GPIO7 , GPIO8 , GPIO9 , GPIO10 , GPIO11 , GPIO12 , GPIO13 , GPIO14 , GPIO15 , GPIO16 , GPIO17 , GPIO18 , GPIO19 , GPIO20 , GPIO21 , GPIO22 , GPIO23 , GPIO24 , GPIO25 , GPIO26 , GPIO27 , GPIO28 , GPIO29 , GPIO30 , GPIO31 , GPIO32 , GPIO33 , GPIO34 , GPIO35 , GPIO36 , GPIO37 , GPIO38 , GPIO39 , GPIO40 , GPIO41 , GPIO42 , GPIO43 , GPIO44 , GPIO45 , GPIO46 , GPIO47 , GPIO48 , GPIO49 , GPIO50 , GPIO51 , GPIO52 , GPIO53 , GPIO54 , GPIO55 , GPIO56 , GPIO57 , GPIO58 , GPIO59 , GPIO60 , GPIO61 , GPIO62 , GPIO63 , GPIO64 , GPIO65 , GPIO66 , GPIO67 , GPIO68 , GPIO69 , GPIO70 , GPIO71 , GPIO72 , GPIO73 , GPIO74 , GPIO75 , GPIO76 , GPIO77 , GPIO78 , GPIO79 , GPIO80 , GPIO81 , GPIO82 , GPIO83 , GPIO84 , GPIO85 , GPIO86 , GPIO87 , GPIO88 , GPIO89 , GPIO90 , GPIO91 , GPIO92 , MT_GPIO_BASE_MAX }GPIO_PIN; |
开机时,在lcm_init_power中调用lcd_power_en(1)->lcm_set_gpio_output(GPIO_LCD_PWR_EN, GPIO_OUT_ONE),拉高GPIO17引脚
\vendor\mediatek\proprietary\bootable\bootloader\lk\dev\lcm\SAT080AT30I21BR3_MIPI\SAT080AT30I21BR3_MIPI.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | static void lcd_power_en(unsigned char enabled) { if (enabled){ #ifdef MT8321_TB_8638_PROJECT lcm_set_gpio_output(GPIO_LCD_PWR_EN, GPIO_OUT_ONE); MDELAY(10); #endif } else{ #ifdef MT8321_TB_8638_PROJECT lcm_set_gpio_output(GPIO_LCD_PWR_EN, GPIO_OUT_ZERO); MDELAY(2); #endif } } |
\vendor\mediatek\proprietary\bootable\bootloader\lk\dev\lcm\SAT080AT30I21BR3_MIPI\SAT080AT30I21BR3_MIPI.c
1 2 3 4 5 6 | static void lcm_set_gpio_output(unsigned int GPIO, unsigned int output) { mt_set_gpio_mode(GPIO, GPIO_MODE_00); mt_set_gpio_dir(GPIO, GPIO_DIR_OUT); mt_set_gpio_out(GPIO, (output>0)? GPIO_OUT_ONE: GPIO_OUT_ZERO); } |
KERNEL部分:
kernel不能像LK一样直接使用GPIO17,必须在dts设备树统一配置,如下,在lcm节点配置GPIO17
\kernel-4.9-lc\arch\arm\boot\dts\mt6580.dts
1 2 3 4 5 6 7 8 9 10 | bus: bus { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges = <0 0 0 0xffffffff>; ... ... lcm: lcm { compatible = "mediatek,mt6580-lcm"; //该名字对应lcm_drv_SAT080AT30I21BR3_MIPI.c中的of_device_id }; //platform总线通过of_device_id匹配到lcm节点,从而可以获取lcm节点的资源(GPIO、LDO等) }; |
\kernel-4.9-lc\arch\arm\boot\dts\tb8321p2_bsp.dts
1 2 3 | &lcm { gpio_lcm_pwr_en = <&pio 17 0>; //GPIO17 }; |
定义SAT080AT30I21BR3_GPIO_LCD_PWR_EN;
\kernel-4.9-lc\drivers\misc\mediatek\lcm\SAT080AT30I21BR3_MIPI\SAT080AT30I21BR3_MIPI.c
1 2 3 | #ifdef CONFIG_MT8321_TB_8638_PROJECT unsigned int SAT080AT30I21BR3_GPIO_LCD_PWR_EN; ... ... |
声明SAT080AT30I21BR3_GPIO_LCD_PWR_EN;
\kernel-4.9-lc\drivers\misc\mediatek\lcm\SAT080AT30I21BR3_MIPI\SAT080AT30I21BR3_MIPI.h
1 2 3 | #ifdef CONFIG_MT8321_TB_8638_PROJECT extern unsigned int SAT080AT30I21BR3_GPIO_LCD_PWR_EN; ... ... |
从dts获取SAT080AT30I21BR3_GPIO_LCD_PWR_EN;
\kernel-4.9-lc\drivers\misc\mediatek\lcm\SAT080AT30I21BR3_MIPI\lcm_drv_SAT080AT30I21BR3_MIPI.c
1 2 3 4 5 6 7 | static void lcm_request_gpio_control(struct device *dev) { printk("[Kernel/LCM] lcm_request_gpio_control() enter"); #ifdef CONFIG_MT8321_TB_8638_PROJECT SAT080AT30I21BR3_GPIO_LCD_PWR_EN = of_get_named_gpio(dev->of_node, "gpio_lcm_pwr_en", 0); //获取dts中对应的GPIO17 ... ... } |
然后,和LK阶段一样,在lcm_init_power中调用lcd_power_en(1)->lcm_set_gpio_output(GPIO_LCD_PWR_EN, GPIO_OUT_ONE),拉高GPIO17引脚
\kernel-4.9-lc\drivers\misc\mediatek\lcm\SAT080AT30I21BR3_MIPI\SAT080AT30I21BR3_MIPI.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | static void lcd_power_en(unsigned char enabled) { if (enabled){ #ifdef CONFIG_MT8321_TB_8638_PROJECT lcm_set_gpio_output(SAT080AT30I21BR3_GPIO_LCD_PWR_EN, GPIO_OUT_ONE); MDELAY(10); #endif } else{ #ifdef CONFIG_MT8321_TB_8638_PROJECT lcm_set_gpio_output(SAT080AT30I21BR3_GPIO_LCD_PWR_EN, GPIO_OUT_ZERO); MDELAY(2); #endif } } |
\kernel-4.9-lc\drivers\misc\mediatek\lcm\SAT080AT30I21BR3_MIPI\SAT080AT30I21BR3_MIPI.c
1 2 3 4 5 6 7 | static void lcm_set_gpio_output(unsigned int GPIO, unsigned int output) { if (GPIO == 0xFFFFFFFF) { return; } gpio_set_value(GPIO, (output > 0) ? GPIO_OUT_ONE : GPIO_OUT_ZERO); } |
11.最后在ProjectConfig、KernelConfig、LKConfig配置对应的屏驱动名字即可
12.打印开机的uart log,查看实际帧率,一般55 ~ 60都是正常的,这里就是57HZ
1 2 3 4 5 6 7 | (200801_11:05:06.165)[1773] mt_disp_get_lcd_time, fps=5709 (200801_11:05:06.165)[1773] videolfb - fb_base = 0xbf200000 (200801_11:05:06.165)[1774] videolfb - islcmfound = 1 (200801_11:05:06.244)[1843] mt_disp_get_lcd_time, fps=5726 (200801_11:05:06.244)[1843] videolfb - fps = 5726 (200801_11:05:06.244)[1843] videolfb - vram = 14680064 (200801_11:05:06.244)[1844] videolfb - lcmname = SAT080AT30I21BR3_MIPI |
或者安装DisplayTester.apk也可以查看实际帧率。
在前后肩不变的情况下,直接调整params->dsi.PLL_CLOCK就可以改变帧率
假如PLL_CLOCK = 200,读出来的fps=40HZ,那么PLL_CLOCK改成300,读出来的fps就会变成60HZ
\vendor\mediatek\proprietary\bootable\bootloader\lk\dev\lcm\SAT080AT30I21BR3_MIPI\SAT080AT30I21BR3_MIPI.c
1 2 3 4 5 6 7 8 9 10 11 | params->dsi.vertical_sync_active = 3; params->dsi.vertical_backporch = 5; params->dsi.vertical_frontporch = 8; params->dsi.vertical_active_line = FRAME_HEIGHT; params->dsi.horizontal_sync_active = 4; params->dsi.horizontal_backporch = 4; params->dsi.horizontal_frontporch = 80; params->dsi.horizontal_active_pixel = FRAME_WIDTH;
params->dsi.PLL_CLOCK = 280; |
另外,如果一些屏在高帧率存在显示不正常的情况,可以配合FAE将帧率降低到50以下试试
13.如果屏幕点不亮,首先确保前面所有的步骤配置正确,然后找硬件工程师检查排线和上电。如果硬件工程师检查OK后还是无法点亮,请联系屏FAE过来联调。
14.如果屏点亮了,也找硬件工程师确认上下电,分别查看开机、休眠、唤醒状态的VDD/STBY/RESET等脚位是否正常。