目前A83T支持单屏显示,首屏为LCD或者首屏为hdmi,都使用无论使用SCREEN0还是SCREEN1都是使用FB0作为framebuffer,在android下可以实现LCD和HDMI同样屏幕显示,而我们需要LCD和HDMI分别显示。
FrameBuffer采用的是linux下的framebuffer分层驱动,fbmem.c作为通用层,然后驱动层实现对fb操作的可选部分,包括一系列的fb_ops。A83T硬件上有一个DE,然后通过TCON0和TCON1实现对显示的输出,其中TCON0控制LCD,实现对lvds,dsi,rgb接口的LCD控制,TCON1实现对HDMI的控制,整体的硬件框架如图。
从框架上来看是可以实现双屏异显的,目前系统无法实现可能还和以前一样硬件上为了和android配合接下来抽丝剥茧把驱动撸一遍,应该就能找到原因。
驱动层上共注册了两个设备,一个是disp,另一个是hdmi,通过disp的probe对全盘进行初始化,通过hdmi的probe进行hdmi的底层初始化。
[ 0.750562] [dev_disp]disp_module_init
[ 0.750989] [dev_disp]disp probe function
[ 0.751092] [dev_disp]start disp_init
[ 0.751297] [dev_disp]display mode is 0
[ 0.751398] [dev_disp]disp_mode is 0,base=0xf1000000, size=0x400000, irq=0
[ 0.751665] [dev_disp]disp_mode is 1,base=0xf1c0c000, size=0x3fc, irq=118
[ 0.751767] [dev_disp]disp_mode is 2,base=0xf1c0d000, size=0x3fc, irq=119
[ 0.751947] [dev_disp]disp_mode is 3,base=0x0, size=0x0, irq=0
[ 0.752048] [dev_disp]disp_mode is 4,base=0xf1c26000, size=0x2fc, irq=0
[ 0.752227] [dev_disp]disp_mode is 5,base=0x0, size=0x0, irq=0
[ 0.752325] [dev_disp]disp_mode is 6,base=0x0, size=0x0, irq=0
[ 0.752503] [dev_disp]disp_mode is 7,base=0x0, size=0x0, irq=0
[ 0.752692] [dev_disp]boot para type is 1,mode is 0
[ 0.752791] [disp_display]start bsp_disp_init
[ 0.753406] [disp_display]start init hdmi
[ 0.753592] [disp_hdmi]hdmi is used,start disp_init_hdmi
[ 0.753692] [disp_hdmi]disp number is 0
[ 0.753868] [disp_hdmi]disp number is 1
[ 0.753965] [disp_hdmi]disp 1 is output by hdmi
[ 0.754064] [disp_hdmi]mode is 4,irq number is 119
[ 0.754243] [disp_hdmi]start check hdmi is supported and register
[ 0.754429] [disp_hdmi]start hdmi init call clk init
[ 0.754605] [disp_hdmi]start hdmi clk init
[ 0.754710] [disp_hdmi]init hdmi and register
[ 0.754954] [dev_disp]total screens is 2
[ 0.792619] [dev_disp]start work
[ 0.792728] [dev_disp]bsp disp sync with hw
[ 0.793464] [dev_disp]output type is not hdmi or hdmi is registed
[ 1.256339] [dev_hdmi]start hdmi module init
[ 1.261716] [drv_hdmi]start hdmi_init
[ 1.266445] [drv_hdmi]start hdmi thread hdmi_run_thread
[ 1.272615] [dev_disp]start work
[ 1.276419] [dev_disp]output type is not hdmi or hdmi is registed
LCD作为首屏和hdmi作为首屏有两个不一样的地方,LCD作为首屏使用的是syn=1,貌似是通过硬件进行显示同步;hdmi时并不这样做,差异表现在disp的初始化后的start_work函数。
Start_work函数解析。
首先等待初始化完成,如果50ms还没初始化完成,则报异常。
然后判断启动参数,启动参数为sync=1时,则根据启动时对应的屏幕是不是一致的,不一致则切换,并且设置硬件sync函数;如果sync不是1时,则分别对不同的屏幕做初始化。启动时的屏幕配置则从command line中获取,经过验证,lcd为主屏是设置为100,hdmi为主屏时设置为00.
从而在start_work中导致了不同,如果是LCD启动,则如果输出类型是hdmi且HDMI没有注册(也就是没有初始化)则退出,否则判断启动时对应的disp也就是fb是否和控制器对应,不对应则调用bsp_disp_sync_with_hw
bsp_disp_sync_with_hw函数,在启动时syn=1并且启动类型不是DISP_OUTPUT_TYPE_NONE时才可以。先获取fb对应的控制器,然后调用disp_device_attached,从两个screen里找到一个disp_device_attached可以成功的。然后调用控制器,调用控制器对应的设备的sw_enable。
在sync为0时,如果设置的是使用screen0,id=0或者screen1,id=1时,如果输出类型是lcd,lcd已经注册且当前id对应的显示类型不是lcd,调用bsp_disp_device_switch进行切换,hdmi时也如此操作,如果既不是lcd,也不是hdmi,则直接调用切换。
bsp_disp_device_switch函数就是直接用disp_device_attached函数进行绑定,如果不成功,则从两个screen里找一个能绑定成功的。
disp_device_attached,找到id对应的mgr,设备存在,类型不为0,则表示已经绑定成功了。
对应设备是enabled同时,enable和disable都存在,disable设备,unsetmanger函数存在时,unsetmanager。根究disp_dev和output_type找到设备,设备具有set_manager时,设置mgr,设备存在set_mode函数时,设置mode。
Fb_init
首先初始化8个framebuffer,其中有一个fb_num的变量,写死为1,此处做的操作为从设备的信息获取长宽等信息,填入fb的结构体信息。然后调用display_fb_request函数。
display_fb_request函数。
通过fb_id和fb_para设置fb对应的参数,然后调用Fb_map_video_memory,然后获取mgr并且通过mgr把参数设置到g_fbi的参数内。
Fb_map_video_memory函数
函数会根据传入的info内容申请内存并把内存记录到info的变量内。
把syn=1去掉,换成syn=0;然后在注册时保证lcd注册成功;fb_number设置为2,startwork时分别switch一下屏幕,再看日志,再看日志,解决了。
从代码结构上看,应该是能够够实现channel和layer的,但貌似没怎么好好弄,反正我们也不用这么高级的功能,算了,不研究了。