soc:rk3368
Android:6.0
现象:接触摸屏后进recovery无显示,进Android系统正常;不接触摸屏正常显示recovery UI。
串口信息:
locale is [(null)]
stage is []
reason is [(null)]
cannot find/open a drm device: No such file or directory
fb0 reports (possibly inaccurate):
vi.bits_per_pixel = 16
vi.red.offset = 11 .length = 5
vi.green.offset = 5 .length = 6
vi.blue.offset = 0 .length = 5
fi.line_length = 2048
framebuffer: 0 (1024 x 600) double_buffer 1
跟踪recovery代码发现打开fb正常,但阻塞在fbdev_blank里面的ioctl没有出来:
static void fbdev_blank(minui_backend* backend __unused, bool blank)
{
int ret;
ret = ioctl(fb_fd, FBIOBLANK, blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK);
if (ret < 0)
perror("ioctl(): blank");
}
最后经过问题排查,将原因锁定到触摸屏驱动drivers/input/touchscreen/gt9xx。在resume和suspend中操作regulator时卡在wile循环中没有出来。所有导致kernel的驱动没有完整跑完,fb的ioctl也就没有返回。将触摸屏驱动resume和suspend代码修改一下解决。
- regulator_tp = regulator_get(NULL,"vcc_tp");
- if(regulator_tp ==NULL)
- {
- printk("!!!!%s:%d:get regulator_tp failed\n",__func__,__LINE__);
- return 0;
- }
- while(regulator_is_enabled(regulator_tp))
- {
- reg = regulator_disable(regulator_tp);
- msleep(10);
- }
- regulator_put(regulator_tp);
+
+ reg = regulator_disable(ts->tp_regulator);
+ if (reg < 0)
+ GTP_ERROR("failed to disable tp regulator\n");
msleep(20);
return 0;
为什么触摸屏和显示有关联呢?因为tp驱动的suspend与resume与fb关联在一起了。当fb BLANK时会回调tp的resume或者suspend.
ts->tp.tp_resume = goodix_ts_early_resume;
ts->tp.tp_suspend = goodix_ts_early_suspend;
tp_register_fb(&ts->tp);
static inline int fb_notifier_callback(struct notifier_block *self,
unsigned long action, void *data)
{
struct tp_device *tp;
struct fb_event *event = data;
int blank_mode = *((int *)event->data);
int ret = 0;
tp = container_of(self, struct tp_device, fb_notif);
//printk("%s.....lin=%d tp->status=%x,blank_mode=%x\n",__func__,__LINE__,tp->status,blank_mode);
mutex_lock(&tp->ops_lock);
if (action == FB_EARLY_EVENT_BLANK) {
switch (blank_mode) {
case FB_BLANK_UNBLANK:
break;
default:
ret = tp->tp_suspend(tp);
break;
}
}
else if (action == FB_EVENT_BLANK) {
switch (blank_mode) {
case FB_BLANK_UNBLANK:
tp->tp_resume(tp);
break;
default:
break;
}
}
mutex_unlock(&tp->ops_lock);
if (ret < 0)
{
printk("TP_notifier_callback error action=%x,blank_mode=%x\n",(int)action,blank_mode);
return ret;
}
return NOTIFY_OK;
}
static inline int tp_register_fb(struct tp_device *tp)
{
memset(&tp->fb_notif, 0, sizeof(tp->fb_notif));
tp->fb_notif.notifier_call = fb_notifier_callback;
mutex_init(&tp->ops_lock);
return fb_register_client(&tp->fb_notif);
}