MTK平台ATA测试LCM出现Not Support
2016-11-26 13:03
806 查看
一、问题描述:
使用MTK的ATA测试工具测试LCM时提示“Not Support”
ATA是指:Assembly(安装) Test Assistant Tool
背景介绍:
一供LCD:TCL模组,IC:ILI9806E
二供LCD:BOYI模组,IC:OTM8019A
二、问题分析:
1. 我司对ATA测试LCM有过客制化,即:只要Probe成功,就立即返回Pass,所以从次入手查看,由于需要调用lcm的disp_lcm_probe函数,打印串口log来分析,从打印出来的log来看,进行测试的时候发现并未走到probe函数,即PC机和手机并未通信,此时怀疑是否有测试LCM的开关未开启,提交Eservice咨询MTK,发现果真如此,如下是MTK给出的答复:
LCM需要客制化,所以将此项注释掉了,如果需要测试此项,需要添加:
在factory.ini里面添加
MenuItem=显示屏;
/vendor/mediatek/proprietary/custom/$project$/factory/inc/cust.h
#define FEATURE_FTM_LCM
所以是测试LCM的开关未开启,导致提示Not Supprot,将开关开启进行测试,测试Pass
2. 开关开启后在测试过程中又遇到了另外的一个问题,不插入LCD进行测试的时候竟然也能测试Pass??
由于我司只有两款LCD,所以在遍历LCD驱动只遍历两个,当都Probe失败时给默认的ili9806e的驱动;下面是抓取的拔掉LCD时的串口log:
[ 1.394421] <1>.(1)[1:swapper/0][kernel]:get_lcm_id=83.
[ 1.395068] <1>.(1)[1:swapper/0][kernel]:disp_lcm_probe ,lcm_ic_id=0x83.
[ 1.395903] <1>.(1)[1:swapper/0][kernel]:disp_lcm_probe ,lcd_id_voltage=3._lcm_count()=2
[ 1.396912] <1>.(1)[1:swapper/0][kernel]:disp_lcm_probe ,check lcd:ili9806e_dsi_vdo_tcl_blu5039.lcd_id_voltage=3.
[ 1.398192] <1>.(1)[1:swapper/0][kernel]:disp_lcm_probe ,detect lcd successfully.lcd_name=ili9806e_dsi_vdo_tcl_blu5039.
在未接入LCD时竟然能Probe成功,真是很神奇啊!
下面查看log打印所对应的代码片段:
代码逻辑是通过读取GPIO口的状态来获取IC的ID;
从log看LCD_ID=3,所以lcd_id0=1,lcd_id1=1,即从GPIO口读取的电压状态是高电平,查看ili9806e的驱动发现,ili9806e的ID默认是3,导致识别错误,下面是ili9806e的驱动注册代码:
未插入LCD时GPIO口处于悬空状态,即高阻态,所以输出的是高电平,导致驱动识别LCD出现错误的现象;
三、问题解决方式
每个LCD IC内部还有一个IC ID,通过读取此ID进一步获知外接LCD的类型和是否存在;
现在的想法是在LK阶段获取IC ID,将IC ID写入到cmdline,启动到Kernel阶段时,一是读取GPIO获取ID,二是读取cmdline这个条件,通过获知这两个判断条件就可以区分出是哪款屏;
代码实现如下:
vendor/mediatek/proprietary/bootable/bootloader/lk/dev/lcm/ili9806e_dsi_vdo_tcl_blu5039/ili9806e_dsi_vdo_tcl_blu5039.c
增加获取IC ID的接口,并将获取到的ID写入到lcm_id变量中,方便将IC ID外传,即:
vendor/mediatek/proprietary/bootable/bootloader/lk/app/mt_boot/mt_boot.c
这样在kernel阶段会自动解析cmdline,并在里面识别lcm_id字段:
kernel-3.18/drivers/misc/mediatek/mach/mt6735/bootinfo.c
__setup会在Kernel阶段自动解析cmdline,即lcm_id_setup()函数来解析cmdline中的“lcm_id”
备注:
有些人会问为何要在lk阶段读取寄存器,而不是在Kernel阶段,之所以这样做是因为之前有过这样做过,但是从寄存器里面读取的是空,导致读取异常,估计是Kernel阶段刚刚启动,虽然LK已经将硬件环境初始化的差不多了,但是此时软件环境还未搭建好,导致异常的发生,暂时只能从这个方面去猜测了
使用MTK的ATA测试工具测试LCM时提示“Not Support”
ATA是指:Assembly(安装) Test Assistant Tool
背景介绍:
一供LCD:TCL模组,IC:ILI9806E
二供LCD:BOYI模组,IC:OTM8019A
二、问题分析:
1. 我司对ATA测试LCM有过客制化,即:只要Probe成功,就立即返回Pass,所以从次入手查看,由于需要调用lcm的disp_lcm_probe函数,打印串口log来分析,从打印出来的log来看,进行测试的时候发现并未走到probe函数,即PC机和手机并未通信,此时怀疑是否有测试LCM的开关未开启,提交Eservice咨询MTK,发现果真如此,如下是MTK给出的答复:
LCM需要客制化,所以将此项注释掉了,如果需要测试此项,需要添加:
在factory.ini里面添加
MenuItem=显示屏;
/vendor/mediatek/proprietary/custom/$project$/factory/inc/cust.h
#define FEATURE_FTM_LCM
所以是测试LCM的开关未开启,导致提示Not Supprot,将开关开启进行测试,测试Pass
2. 开关开启后在测试过程中又遇到了另外的一个问题,不插入LCD进行测试的时候竟然也能测试Pass??
由于我司只有两款LCD,所以在遍历LCD驱动只遍历两个,当都Probe失败时给默认的ili9806e的驱动;下面是抓取的拔掉LCD时的串口log:
[ 1.394421] <1>.(1)[1:swapper/0][kernel]:get_lcm_id=83.
[ 1.395068] <1>.(1)[1:swapper/0][kernel]:disp_lcm_probe ,lcm_ic_id=0x83.
[ 1.395903] <1>.(1)[1:swapper/0][kernel]:disp_lcm_probe ,lcd_id_voltage=3._lcm_count()=2
[ 1.396912] <1>.(1)[1:swapper/0][kernel]:disp_lcm_probe ,check lcd:ili9806e_dsi_vdo_tcl_blu5039.lcd_id_voltage=3.
[ 1.398192] <1>.(1)[1:swapper/0][kernel]:disp_lcm_probe ,detect lcd successfully.lcd_name=ili9806e_dsi_vdo_tcl_blu5039.
在未接入LCD时竟然能Probe成功,真是很神奇啊!
下面查看log打印所对应的代码片段:
disp_lcm_handle* disp_lcm_probe(char* plcm_name, LCM_INTERFACE_ID lcm_id) { DISPFUNC(); unsigned int v_i; unsigned int lcmindex = 0; bool isLCMFound = false; bool isLCMInited = false; int lcd_id0=0,lcd_id1=0,lcd_id=0; LCM_DRIVER *lcm_drv = NULL; LCM_PARAMS *lcm_param = NULL; disp_lcm_handle *plcm = NULL; //int is_need_read_ic_id=0; //printk("[kernel]:%s,start .\n",__func__); #ifdef GPIO_LCD_ID0_PIN mt_set_gpio_mode(GPIO_LCD_ID0_PIN, GPIO_MODE_00); mt_set_gpio_dir(GPIO_LCD_ID0_PIN, GPIO_DIR_IN); mt_set_gpio_pull_select(GPIO_LCD_ID0_PIN,GPIO_PULL_UP); mt_set_gpio_pull_enable(GPIO_LCD_ID0_PIN, GPIO_PULL_ENABLE); mdelay(10); lcd_id0 = mt_get_gpio_in(GPIO_LCD_ID0_PIN); mt_set_gpio_pull_select(GPIO_LCD_ID0_PIN,GPIO_PULL_DISABLE); #endif #ifdef GPIO_LCD_ID1_PIN mt_set_gpio_mode(GPIO_LCD_ID1_PIN, GPIO_MODE_00); mt_set_gpio_dir(GPIO_LCD_ID1_PIN, GPIO_DIR_IN); mt_set_gpio_pull_select(GPIO_LCD_ID1_PIN,GPIO_PULL_UP); mt_set_gpio_pull_enable(GPIO_LCD_ID1_PIN, GPIO_PULL_ENABLE); mdelay(10); lcd_id1 = mt_get_gpio_in(GPIO_LCD_ID1_PIN); mt_set_gpio_pull_select(GPIO_LCD_ID1_PIN,GPIO_PULL_DISABLE); #endif lcd_id=(lcd_id1<<1)|lcd_id0; printk("[kernel]:%s ,lcm_ic_id=0x%x.\n",__func__,get_lcm_id()); printk("[kernel]:%s ,lcd_id_voltage=%d._lcm_count()=%d\n",__func__,lcd_id,_lcm_count()); for(v_i=0;v_i<_lcm_count();v_i++) { printk("[kernel]:%s ,check lcd:%s.lcd_id_voltage=%d.\n",__func__,lcm_driver_list[v_i]->name,lcm_driver_list[v_i]->lcd_id_voltage); if(lcm_driver_list[v_i]->lcd_id_voltage == lcd_id) { lcm_drv = lcm_driver_list[v_i]; if(lcm_drv->get_lcd_id_register) { if(lcm_drv->get_lcd_id_register()== get_lcm_id()) { printk("[kernel]:%s ,detect lcd with read ic id success.lcd_name=%s.\n",__func__,lcm_driver_list[v_i]->name); isLCMFound = true; } } else { isLCMFound = true; } if (isLCMFound) { lcm_kernel_detect_drv=lcm_driver_list[v_i]; isLCMInited = true; lcmindex=v_i; break; } } } if(isLCMFound==false) { lcm_drv = lcm_driver_list[0]; lcm_kernel_detect_drv=lcm_driver_list[0]; isLCMFound = false; isLCMInited = true; lcmindex=0; } if(isLCMFound == false) { lcd_find_success=0; printk(KERN_ERR "[kernel]:%s ,detect lcd fail,use default.lcd_name=%s.\n",__func__,lcm_kernel_detect_drv->name); } else { lcd_find_success=1; printk(KERN_ERR "[kernel]:%s ,detect lcd successfully.lcd_name=%s.\n",__func__,lcm_kernel_detect_drv->name); } plcm = kzalloc(sizeof(uint8_t*) *sizeof(disp_lcm_handle), GFP_KERNEL); lcm_param = kzalloc(sizeof(uint8_t*) *sizeof(LCM_PARAMS), GFP_KERNEL); if(plcm && lcm_param) { plcm->params = lcm_param; plcm->drv = lcm_drv; plcm->is_inited = isLCMInited; plcm->index = lcmindex; } else { DISPERR("FATAL ERROR!!!kzalloc plcm and plcm->params failed\n"); goto FAIL; } { plcm->drv->get_params(plcm->params); plcm->lcm_if_id = plcm->params->lcm_if; // below code is for lcm driver forward compatible if(plcm->params->type == LCM_TYPE_DSI && plcm->params->lcm_if == LCM_INTERFACE_NOTDEFINED) plcm->lcm_if_id = LCM_INTERFACE_DSI0; if(plcm->params->type == LCM_TYPE_DPI && plcm->params->lcm_if == LCM_INTERFACE_NOTDEFINED) plcm->lcm_if_id = LCM_INTERFACE_DPI0; if(plcm->params->type == LCM_TYPE_DBI && plcm->params->lcm_if == LCM_INTERFACE_NOTDEFINED) plcm->lcm_if_id = LCM_INTERFACE_DBI0; if((lcm_id == LCM_INTERFACE_NOTDEFINED) || lcm_id == plcm->lcm_if_id) { plcm->lcm_original_width = plcm->params->width; plcm->lcm_original_height = plcm->params->height; _dump_lcm_info(plcm); return plcm; } else { DISPERR("the specific LCM Interface [%d] didn't define any lcm driver\n", lcm_id); goto FAIL; } } FAIL: if(plcm) kfree(plcm); if(lcm_param) kfree(lcm_param); return NULL; }
代码逻辑是通过读取GPIO口的状态来获取IC的ID;
lcd_id0 = mt_get_gpio_in(GPIO_LCD_ID0_PIN);
lcd_id1 = mt_get_gpio_in(GPIO_LCD_ID1_PIN);
lcd_id=(lcd_id1<<1)|lcd_id0;
从log看LCD_ID=3,所以lcd_id0=1,lcd_id1=1,即从GPIO口读取的电压状态是高电平,查看ili9806e的驱动发现,ili9806e的ID默认是3,导致识别错误,下面是ili9806e的驱动注册代码:
LCM_DRIVER ili9806e_dsi_vdo_tcl_blu5039_drv = { .name = "ili9806e_dsi_vdo_tcl_blu5039", .set_util_funcs = lcm_set_util_funcs, .compare_id = lcm_compare_id, .get_params = lcm_get_params, .init = lcm_init, .suspend = lcm_suspend, .resume = lcm_resume, .set_backlight = lcm_setbacklight_tcl, #if defined(LCM_DSI_CMD_MODE) .update = lcm_update, #endif .init_power = lcm_init_power, .lcd_id_voltage = 3, .lcm_ic_id = get_lcm_id, };
未插入LCD时GPIO口处于悬空状态,即高阻态,所以输出的是高电平,导致驱动识别LCD出现错误的现象;
三、问题解决方式
每个LCD IC内部还有一个IC ID,通过读取此ID进一步获知外接LCD的类型和是否存在;
现在的想法是在LK阶段获取IC ID,将IC ID写入到cmdline,启动到Kernel阶段时,一是读取GPIO获取ID,二是读取cmdline这个条件,通过获知这两个判断条件就可以区分出是哪款屏;
代码实现如下:
vendor/mediatek/proprietary/bootable/bootloader/lk/dev/lcm/ili9806e_dsi_vdo_tcl_blu5039/ili9806e_dsi_vdo_tcl_blu5039.c
增加获取IC ID的接口,并将获取到的ID写入到lcm_id变量中,方便将IC ID外传,即:
static unsigned int lcm_compare_id(void) { int array[4]; char buffer[3]; int id0=0; int id1=0; //char id2=0; int id=0; lcm_init_power(); mt_set_gpio_mode(GPIO_LCD_RST_PIN, 0); mt_set_gpio_out(GPIO_LCD_RST_PIN, GPIO_OUT_ONE); mdelay(10);; mt_set_gpio_out(GPIO_LCD_RST_PIN, GPIO_OUT_ZERO); MDELAY(10); mt_set_gpio_out(GPIO_LCD_RST_PIN, GPIO_OUT_ONE); mdelay(120); array[0]=0x00063902; array[1]=0x0698ffff; array[2]=0x00000104; dsi_set_cmdq(array, 3, 1); MDELAY(10); array[0]=0x00013700;//0x00023700; dsi_set_cmdq(array, 1, 1); read_reg_v2(0x00, &id0, 1); array[0]=0x00013700;//0x00023700; dsi_set_cmdq(array, 1, 1); read_reg_v2(0x01, &id1, 1); id = (id0<<8)|id1; lcm_id = id; #ifdef BUILD_LK printf("[uboot] %s, id0 = 0x%08x, id1 = 0x%08x, id = 0x%08x\n", __func__, id0, id1, id); #endif if(id == ILI9806E_ID) return 1; else return 0; }
static int get_lcm_id(void) { return lcm_id; }中间是怎么传到cmdline中的过程比较简单,自己写方可,也可以参看附件代码,最后写到cmdline中的代码如下:
vendor/mediatek/proprietary/bootable/bootloader/lk/app/mt_boot/mt_boot.c
sprintf(cmdline_tmpbuf, "%s%s%d", CMDLINE_TMP_CONCAT_SIZE, " lcm_id=", mt_disp_get_lcm_ic_id()); cmdline_append(cmdline_tmpbuf);
这样在kernel阶段会自动解析cmdline,并在里面识别lcm_id字段:
kernel-3.18/drivers/misc/mediatek/mach/mt6735/bootinfo.c
int lcm_id=0x83; static int __init lcm_id_setup(char *str) { int en; if(!get_option(&str, &en)) return 0; lcm_id = en; return 1; } int get_lcm_id(void) { printk("[kernel]:get_lcm_id=%x.\n",lcm_id); return lcm_id; } __setup("lcm_id=", lcm_id_setup);
__setup会在Kernel阶段自动解析cmdline,即lcm_id_setup()函数来解析cmdline中的“lcm_id”
备注:
有些人会问为何要在lk阶段读取寄存器,而不是在Kernel阶段,之所以这样做是因为之前有过这样做过,但是从寄存器里面读取的是空,导致读取异常,估计是Kernel阶段刚刚启动,虽然LK已经将硬件环境初始化的差不多了,但是此时软件环境还未搭建好,导致异常的发生,暂时只能从这个方面去猜测了
相关文章推荐
- MTK平台LCM驱动移植
- 2017.7.3--2017.7.7高通8909平台工厂测试模式出现的挂机Fatal signal 11 (SIGSEGV)问题
- MTK平台安卓手机性能测试方法
- MTK平台安卓手机性能测试方法
- MTK平台安卓手机性能测试方法
- MTK平台上读取LCM error report
- MTK平台LCM驱动详细分析(一)
- 对MTK安卓平台LCM驱动的理解
- MTK平台LCM驱动详细分析(二)
- 找出字符串中第一个只出现一次的字符——来自华为OJ平台测试基础篇
- MTK手机平台无法测试FT,无法写入IMEI号
- LCD显示原理 && MTK平台LCM显存大小的计算 && mtk6589LCD显示子系统
- [MTK] [LCM]ili9806c和ili9805c开启ESD机制使用过程概率性出现上方闪线
- MTK平台lcm移植流程
- MTK平台8127摄像头更换后,flash_led出现问题
- [lcm] MTK平台移植屏幕lcd过程要点
- MTK 平台lcm驱动框架分析1
- MTK平台,自定义编译开关
- 三星平台上的测试心得