Android 自定义休眠及唤醒

一、开发环境及需求

平台:			RK3368
系统版本:		Android8.1
内核版本:  		Linux4.4

按瑞芯微默认的休眠方式来看,二级休眠可以关闭背光功能,一级休眠才能够完全关闭LCD屏幕的运行,如何在不关闭其他外设的情况下,只对LCD屏幕进行完全关闭,那么就需要在二级休眠中增加对LCD的初始化。

二、二级休眠

走pm runtime通路,这个就不详述了,驱动中实现pm这个方法就行了。

三、一级休眠

drm原生只支持pm runtime的二级休眠方式,不支持一级二级休眠,为了支持android的一级休眠功能,瑞芯微提供了可操作的sys文件节点

1、使能CONFIG_DRM_FBDEV_EMULATION
2、echo 3 > /sys/class/graphics/fb0/blank //进入一级待机
   echo  0 > /sys/class/graphics/fb0/blank //退出一级待机

四、代码跟踪及修改

使用fbdev的blank时,kernel会发notify到需要一级待机的外设,如touchscreen,keyboard等

drivers/video/fbdev/core/fbsysfs.c这个文件中声明了blank这个文件节点

/* When cmap is added back in it should be a binary attribute
 * not a text one. Consideration should also be given to converting
 * fbdev to use configfs instead of sysfs */
static struct device_attribute device_attrs[] = {
        __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
        __ATTR_URW(blank, S_IRUGO|S_IWUGO, show_blank, store_blank),
        __ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console),
        __ATTR(cursor, S_IRUGO|S_IWUSR, show_cursor, store_cursor),
        __ATTR(mode, S_IRUGO|S_IWUSR, show_mode, store_mode),
        __ATTR(modes, S_IRUGO|S_IWUSR, show_modes, store_modes),
        __ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan),
        __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual),
        __ATTR(name, S_IRUGO, show_name, NULL),
        __ATTR(stride, S_IRUGO, show_stride, NULL),
        __ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
        __ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate),
#ifdef CONFIG_FB_BACKLIGHT
        __ATTR(bl_curve, S_IRUGO|S_IWUSR, show_bl_curve, store_bl_curve),
#endif
};

然后实现echo的方法

static ssize_t store_blank(struct device *device,
                           struct device_attribute *attr,
                           const char *buf, size_t count)
{
        struct fb_info *fb_info = dev_get_drvdata(device);
        char *last = NULL;
        int err;

        console_lock();
        fb_info->flags |= FBINFO_MISC_USEREVENT;
        err = fb_blank(fb_info, simple_strtoul(buf, &last, 0));
        fb_info->flags &= ~FBINFO_MISC_USEREVENT;
        console_unlock();
        if (err < 0)
                return err;
        return count;
}

在fb_blank中回调 Notifier机制的handle

int fb_blank(struct fb_info *info, int blank)
{       
        struct fb_event event;
        int ret = -EINVAL, early_ret;
        
        if (blank > FB_BLANK_POWERDOWN)
                blank = FB_BLANK_POWERDOWN;
        
        event.info = info;
        event.data = &blank;
        
        early_ret = fb_notifier_call_chain(FB_EARLY_EVENT_BLANK, &event);
        
        if (info->fbops->fb_blank)
                ret = info->fbops->fb_blank(blank, info);
        
        if (!ret)
                fb_notifier_call_chain(FB_EVENT_BLANK, &event);
        else {  
                /*
                 * if fb_blank is failed then revert effects of
                 * the early blank event.
                 */
                if (!early_ret)
                        fb_notifier_call_chain(FB_R_EARLY_EVENT_BLANK, &event);
        }
        
        return ret;
}
EXPORT_SYMBOL(fb_blank);

在这个函数中可以看到是通过fb_notifier_list这个链表唤醒相对应的handle

int fb_notifier_call_chain(unsigned long val, void *v)
{
        return blocking_notifier_call_chain(&fb_notifier_list, val, v);
}
EXPORT_SYMBOL_GPL(fb_notifier_call_chain);

在显示框架的probe中注册回调

dsi->fb_notif.notifier_call = fb_mipi_notifier_callback;
ret = fb_register_client(&dsi->fb_notif);
int fb_register_client(struct notifier_block *nb)
{       
        return blocking_notifier_chain_register(&fb_notifier_list, nb);
}       
EXPORT_SYMBOL(fb_register_client);

最后是回调函数的实现

static int fb_mipi_notifier_callback(struct notifier_block *self,
				unsigned long event, void *data)
{
	int fb_blank = 0;
	struct dw_mipi_dsi *pdsi;
	struct drm_encoder *encoder;
	struct fb_event *evdata = data;

	pdsi = container_of(self, struct dw_mipi_dsi, fb_notif);
	encoder = &pdsi->encoder;

	if(event != FB_EVENT_BLANK)
		return 0;

	fb_blank = *(int *)evdata->data;
	
	if(fb_blank == FB_BLANK_UNBLANK)
		dw_mipi_dsi_encoder_enable(encoder);
	else
		dw_mipi_dsi_encoder_disable(encoder);
		
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值