Recovery模式下进行重启或者关机LCD会闪一下白屏

现象描述:

Recovery模式下进行重启或者关机或者恢复出厂设置后都会闪一下白屏

抓取kernel log未发现明显异常:

[   40.137930] <0>.(0)[1:init]******** battery driver shutdown!! ********
[   40.141461] <0>.(0)[58:kworker/0:1]EXT4-fs (mmcblk0p24): re-mounted. Opts: (null)
[   40.143458] <0>.(0)[58:kworker/0:1]Emergency Remount complete
[   40.272535] <0>.(0)[181:mtk charger_hv_][charging_get_battery_status] battery exist for bring up.
[   40.273685] <0>.(0)[181:mtk charger_hv_][charging_get_battery_status] battery exist for bring up.
[   40.274822] <0>.(0)[181:mtk charger_hv_][charging_get_battery_status] battery exist for bring up.
[   40.749289] <0>.(0)[1:init][battery_meter_shutdown]
[   40.751221] <0>.(0)[1:init][MUSB]musb_shutdown 1356: shut down
[   40.752132] <0>-(0)[1:init][MUSB]mt_usb_disable 340: <1,1>,<3,5,3,2>
[   40.753801] <0>-(0)[1:init][MUSB]usb_phy_savecurrent 534: usb save current success
[   40.754777] <0>-(0)[1:init][MUSB]mt_usb_disable 358: <3,5,3,3>
[   40.756254] <0>-(0)[0:swapper/0][Power/swap]SODI: blocking by uptime count = 14
[   40.970074] <0>.(0)[1:init]kernel lcm_suspend
[   40.976840] <0>.(0)[1:init][gps]null pointer!!
[   40.978227] <0>.(0)[1:init]reboot: Restarting system with command ''
[   40.979052] <0>-(0)[1:init]machine_restart, arm_pm_restart(  (null))
[   40.979871] <0>-(0)[1:init]ARCH_RESET happen!!!
[   40.980461] <0>-(0)[1:init]arch_reset: cmd = 
[   40.981046] <0>-(0)[1:init]CPU: 0 PID: 1 Comm: init Tainted: G        W      3.18.19 #12

只能看到一行和LCD相关的log信息;


分析过程:

1. log里面看不出来,没辙,想其他办法吧,闲着没事看一下 [   40.970074] <0>.(0)[1:init]kernel lcm_suspend 看一下这个log是从哪里打印的吧,既然是lcm_suspend就到LCD驱动里卖弄看一下,在lcm_suspend()函数里面添加log信息,发现确实走的是kernel里面我们自己添加的LCD驱动,开机lcd probe驱动log如下:

[    1.239771] <3>.(3)[1:swapper/0][kernel]:get_lcm_id=83.
[    1.240421] <3>.(3)[1:swapper/0][kernel]:disp_lcm_probe ,lcm_ic_id=0x83.
[    1.241256] <3>.(3)[1:swapper/0][kernel]:disp_lcm_probe ,lcd_id_voltage=3._lcm_count()=1
[    1.242264] <3>.(3)[1:swapper/0][kernel]:disp_lcm_probe ,check lcd:DiJing-ili9806e.lcd_id_voltage=3.
[    1.243403] <3>.(3)[1:swapper/0][kernel]:disp_lcm_probe ,detect lcd successfully.lcd_name=DiJing-ili9806e.

suspend时没有对屏幕进行灭背光动作,没辙,想其他版本

2. 想到调节LCD亮度有对应的文件节点,通过直接往文件里面echo数值,直接修改亮度,看看是否好使

设备文件节点路径(recovery模式下adb开启需要单独调试出来):

/sys/class/leds/lcd-backlight/brightness

先cat出来brigthness节点初始默认值是多少,

cat /sys/class/leds/lcd-backlight/brightness 后发现为0

echo 200>/sys/class/leds/lcd-backlight/brightness

之后再进行重启或者关机白屏现象不复现,现在有点眉目了,看来和亮度初始值有关


3. 在dts里面找到设置的/sys/class/leds/lcd-backlight/brightness文件节点内容的位置如下:

dts路径:kernel-3.18/arch/arm/boot/dts/$(project).dts

led6:led@6 {
compatible = "mediatek,lcd-backlight";
led_mode = <4>;
data = <1>;
pwm_config = <0 0 0 0 0>;
};

找到解析dts文件内容的位置:

kernel-3.18/drivers/misc/mediatek/leds/mt6735/leds.c


enum mt65xx_led_mode {
MT65XX_LED_MODE_NONE,
MT65XX_LED_MODE_PWM,
MT65XX_LED_MODE_GPIO,
MT65XX_LED_MODE_PMIC,
MT65XX_LED_MODE_CUST_LCM,
MT65XX_LED_MODE_CUST_BLS_PWM
};


struct cust_mt65xx_led *get_cust_led_dtsi(void)
{
struct device_node *led_node = NULL;
bool isSupportDTS = false;
int i, ret;
int mode, data;
int pwm_config[5] = { 0 };


/*LEDS_DEBUG("get_cust_led_dtsi: get the leds info from device tree\n");*/
if (pled_dtsi == NULL) {
/* this can allocat an new struct array */
pled_dtsi = kmalloc(MT65XX_LED_TYPE_TOTAL *
     sizeof(struct
    cust_mt65xx_led),
     GFP_KERNEL);
if (pled_dtsi == NULL) {
LEDS_DEBUG("get_cust_led_dtsi kmalloc fail\n");
goto out;
}


for (i = 0; i < MT65XX_LED_TYPE_TOTAL; i++) {


char node_name[32] = "mediatek,";


pled_dtsi[i].name = leds_name[i];


led_node =
   of_find_compatible_node(NULL, NULL,
   strcat(node_name,
  leds_name[i]));
if (!led_node) {
LEDS_DEBUG("Cannot find LED node from dts\n");
pled_dtsi[i].mode = 0;
pled_dtsi[i].data = -1;
} else {
isSupportDTS = true;
ret =
   of_property_read_u32(led_node, "led_mode",
&mode);
if (!ret) {
pled_dtsi[i].mode = mode;
LEDS_DEBUG
   ("The %s's led mode is : %d\n",
    pled_dtsi[i].name,
    pled_dtsi[i].mode);
} else {
LEDS_DEBUG
   ("led dts can not get led mode");
pled_dtsi[i].mode = 0;
}


ret =
   of_property_read_u32(led_node, "data",
&data);
if (!ret) {
pled_dtsi[i].data = data;
LEDS_DEBUG
   ("The %s's led data is : %ld\n",
    pled_dtsi[i].name,
    pled_dtsi[i].data);
} else {
LEDS_DEBUG
   ("led dts can not get led data");
pled_dtsi[i].data = -1;
}


ret =
   of_property_read_u32_array(led_node,
      "pwm_config",
      pwm_config,
      ARRAY_SIZE
      (pwm_config));
if (!ret) {
LEDS_DEBUG
   ("The %s's pwm config data is %d %d %d %d %d\n",
    pled_dtsi[i].name, pwm_config[0],
    pwm_config[1], pwm_config[2],
    pwm_config[3], pwm_config[4]);
pled_dtsi[i].config_data.clock_source =
   pwm_config[0];
pled_dtsi[i].config_data.div =
   pwm_config[1];
pled_dtsi[i].config_data.low_duration =
   pwm_config[2];
pled_dtsi[i].config_data.High_duration =
   pwm_config[3];
pled_dtsi[i].config_data.pmic_pad =
   pwm_config[4];


} else
LEDS_DEBUG
   ("led dts can not get pwm config data.\n");


switch (pled_dtsi[i].mode) {
case MT65XX_LED_MODE_CUST_LCM:
pled_dtsi[i].data =
   (long)mtkfb_set_backlight_level;

LEDS_DEBUG
   ("kernel:the backlight hw mode is LCM.\n");
break;
case MT65XX_LED_MODE_CUST_BLS_PWM:
pled_dtsi[i].data =
   (long)disp_bls_set_backlight;
LEDS_DEBUG
   ("kernel:the backlight hw mode is BLS.\n");
break;
default:
break;
}
}
}


if (!isSupportDTS) {
kfree(pled_dtsi);
pled_dtsi = NULL;
}
}
 out:
return pled_dtsi;
}


通过查看dts,发现compatible = "mediatek,lcd-backlight";对应的led_mode为4,对应的枚举变量为MT65XX_LED_MODE_CUST_LCM ,所走的函数为mtkfb_set_backlight_level(),函数对应的实现在/kernel-3.18/drivers/misc/mediatek/video/common/mtkfb.c文件中:

int mtkfb_set_backlight_level(unsigned int level)
{
MTKFB_FUNC();
pr_debug("mtkfb_set_backlight_level:%d Start\n", level);
primary_display_setbacklight(level);
pr_debug("mtkfb_set_backlight_level End\n");
return 0;
}


里面调用的又是:primary_display_setbacklight(level);对应的代码路径如下:kernel-3.18/drivers/misc/mediatek/video/mt6735/videox/primary_display.c

int primary_display_setbacklight(unsigned int level)
{
int ret = 0;
static unsigned int last_level;


DISPFUNC();


if (last_level == level)
return 0;


MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagStart, 0, 0);
#ifdef DISP_SWITCH_DST_MODE
_primary_path_switch_dst_lock();
#endif
_primary_path_cmd_lock();
_primary_path_lock(__func__);
if (pgc->state == DISP_SLEPT) {
DISPCHECK("Sleep State set backlight invald\n");
} else {
disp_update_trigger_time();
if (primary_display_cmdq_enabled()) {
if (primary_display_is_video_mode()) {
MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl,
      MMProfileFlagPulse, 0, 7);
disp_lcm_set_backlight(pgc->plcm, level);
} else {
#ifdef MTK_DISP_IDLE_LP
/* CMD mode need to exit top clock off idle mode */
_disp_primary_path_exit_idle("primary_display_setbacklight", 0);
#endif
_set_backlight_by_cmdq(level);
}
} else {
#ifdef MTK_DISP_IDLE_LP
if (primary_display_is_video_mode() == 0)
_disp_primary_path_exit_idle("primary_display_setbacklight", 0);
#endif
_set_backlight_by_cpu(level);
}
last_level = level;
}
#ifndef CONFIG_FPGA_EARLY_PORTING
#ifdef GPIO_LCM_LED_EN
if (0 == level)
mt_set_gpio_out(GPIO_LCM_LED_EN, GPIO_OUT_ZERO);
else
mt_set_gpio_out(GPIO_LCM_LED_EN, GPIO_OUT_ONE);
#endif
#endif
#if 0 /* check writed success? for test after CABC */
{
/* extern uint32_t DSI_dcs_read_lcm_reg_v2(DISP_MODULE_ENUM module, cmdqRecHandle cmdq,
     uint8_t cmd, uint8_t *buffer, uint8_t buffer_size);
*/
uint8_t buffer[2];


if (primary_display_is_video_mode())
dpmgr_path_ioctl(pgc->dpmgr_handle, NULL, DDP_STOP_VIDEO_MODE, NULL);


DSI_dcs_read_lcm_reg_v2(DISP_MODULE_DSI0, NULL, 0x51, buffer, 1);
pr_debug("[CABC check result 0x51 = 0x%x,0x%x]\n", buffer[0], buffer[1]);
dpmgr_path_start(pgc->dpmgr_handle, CMDQ_DISABLE);
if (primary_display_is_video_mode()) {
/* for video mode, we need to force trigger here */
/* for cmd mode, just set DPREC_EVENT_CMDQ_SET_EVENT_ALLOW when trigger loop start */
dpmgr_path_trigger(pgc->dpmgr_handle, NULL, CMDQ_DISABLE);
}
}
#endif
_primary_path_unlock(__func__);
_primary_path_cmd_unlock();
#ifdef DISP_SWITCH_DST_MODE
_primary_path_switch_dst_unlock();
#endif
MMProfileLogEx(ddp_mmp_get_events()->primary_set_bl, MMProfileFlagEnd, 0, 0);
return ret;
}

通过查看此函数发现,函数参数level 是从设备节点/sys/class/leds/lcd-backlight/brightness读取过来的,默认为0,

和内部static变量last_level(初始值为0)  相等,代码逻辑如函数体红色标识所示,相等时不再往下走背光流程,所以导致代码没有往下走下去,因为关机时是要关闭背光的,

由于recovery模式里未做熄屏再亮屏的动作,导致recovery里一直使用的是lk里面的亮度,导致kernel里面的brightness默认为0,此时关机,默认值和static变量都为0,导致没有走灭屏动作,所以会亮屏







猜你喜欢

转载自blog.csdn.net/u012900947/article/details/52881618