2019-12-16
關鍵字:雙屏異顯
筆者手里有一塊運行着 Android 5.1 的 rk3288 開發板。
最近接到一個需求:在這塊開發板上實現 MIPI + EDP 雙屏異顯功能。
筆者手里的這塊開發板默認是不支持雙屏異顯的,不過好在 rk 有官方補丁,合入補丁后可以支持雙屏異顯功能。
筆者是在網上找到的這份補丁程序,主要參考了以下兩篇博客,感謝這兩位博主的無私奉獻:
https://www.cnblogs.com/lialong1st/p/9149213.html
https://blog.csdn.net/lb5761311/article/details/90024470
其實這兩篇博客中所記載的補丁已經是將雙屏異顯的核心功能給支持上的了。一般來講,合入博客中的補丁后都能成功實現雙屏異顯功能。但偏偏筆者就是那個“特殊情況”,筆者在仔細登入補丁后,仍然發現了一些問題,導致不能實現雙異異顯功能。這篇博客,就來記述一下這些問題以及解決辦法。
當然,以下記載的問題現象首先都必須要保證補丁程序被正確無誤地合並進去,一定要仔細檢查每一行補丁代碼,確保不是由於合補丁失誤引發的問題。
1、主屏點不亮
上面兩篇博客中都有提到,要將 uboot logo 關掉:
至少筆者手里的 MIPI 屏,或者說主屏,是在 uboot 階段而不是在 kernel 階段點亮的。在 uboot 階段也會去解析 dts 配置,並根據 rockchip,uboot-logo-on 屬性的值來決定是否跑 uboot 階段的點屏操作。所以,如果你發現你在正確合入補丁以后出現了連主屏都點不亮的情況,可以嘗試着將這個屬性配置為1,讓uboot去點一下屏。需要注意的是,rk3288不能直接燒 uboot 分區,需要編譯大包才能應用到 uboot 的修改。但如果僅僅是改一下 kernel 層的 dts 文件,則可以通過燒 resource.img 來驗證。
uboot 階段的點屏流程大致如下:
./u-boot/board/rockchip/common/rkboot/fastboot.c
board_fbt_preboot();
./u-boot/common/lcd.c
drv_lcd_init();
lcd_init();
./u-boot/driver/video/rockchip_fb.c
lcd_ctrl_init();
對了,uboot 階段點屏時解析的屏參 dts 是必須記載在根 dts 下的,即我們除了要像補丁程序中那樣,在 rk_screen 節點下增加主屏參信息配置,也得在根 dts 下繼續引用完整的屏參文件:
如果沒有像上圖那樣 include 進來完整的 MIPI 屏參文件,uboot階段點屏時會報找不到 display-timing 節點錯誤的。
一般來說,按照上面的步驟操作以后都能點亮主屏。
2、副屏不亮
副屏是無法在 uboot 階段點亮的。或者說 uboot 默認只點了一塊屏幕,如果你硬要像點主屏一樣在 uboot 階段副屏也點亮,那只能你自己去研究修改 uboot 代碼了。
筆者的副屏不亮就沒有動過 uboot 的代碼。
在筆者的 rk3288 中,主屏的視頻數據是來自於 fb0 的,而副屏的是來自於 fb4 的:dev/graphics/fb4。我們首先來查一下 fb4 的基礎屏參信息:
cat /sys/class/graphics/fb4/screen_info
這里要確保副屏的分辨率與幀率與我們手里實際的屏幕對的上。如果對不上,比如筆者的之前就出現過副屏解析成 480x320 的情況。這樣就當然點不亮了。如果出現了分辨率被解析錯了的情況,修改以下這個文件:
./kernel/drivers/video/rockchip/lcdc/rk3288_lcdc.c
將 lcdc_read_reg_defalut_cfg 函數的設置屏幕分辨率的代碼注釋掉,如下圖所示:
注掉這兩段代碼,可以解決分辨率被修改的問題。
如果發現分辨率與幀率都正確了,仍然點不亮,則可以查一下副屏的時鍾,即 lcdc1 的時鍾。
查詢方式有好幾種,第一種是看開機打印:
第二種方式是直接查詢時鍾配置表:
cat /d/clk/clk_summary | grep lcdc
lcdc1 的時鍾必須在副屏的可接受范圍以內,否則相當於副屏的屏參不正確,當然點不亮了。
如果發現 lcdc1 的時鍾頻率不對,與自己在 dtsi 中填寫的不一致,則要修改 dtsi。
系統是在哪里強制將你設定在 dtsi 中的時鍾頻率給修改掉的呢?在以下代碼中的 set_dclk 函數中。
./kernel/drivers/video/rockchip/lcdc/rk3288_lcdc.c
當初始化副屏時,這個函數會去執行上圖紅箭頭所指的函數,並在里面根據一些條件來應用或修改你設定的頻率值。有興趣的可以加打印跟蹤一下這個函數流程,它並不復雜,不過筆者就不在這里貼出來了。
總而言之,解決時鍾頻率被修改的辦法就是加打印跟蹤,並將副屏 dtsi 中的時鍾頻率設置成系統強制設給你的頻率的倍數,當然這個倍數也得在你的屏幕的可接受范圍之內才行。
3、HDMI不插副屏不亮
可能有些同學是沒有嚴格按照補丁程序將 dts 中的 hdmi 節點給關閉掉的。
關不關 hdmi 本身不會影響雙屏異顯功能,但有的同學可能會發現一個神奇的現象:HDMI不插時副屏死活點不亮。
這其實是 rk3288 的機制為之。這個板子默認就將 lcdc1 與 HDMI 綁定死了的。沒有HDMI時就不給 lcdc1 送視頻數據。更過分的是當插了 HDMI 時,副屏雖然亮了,但使用的屏參卻是 HDMI 顯示器的。換句話說,如果你所接的 HDMI 顯示器的屏參與你要點的副屏的屏參差異較大,是有可能出現插了 HDMI 后副屏黑掉的情況的。所以嚴格來講,應該是當要用雙屏異顯時就關掉 HDMI 功能,當要使用 HDMI 時就不要用雙屏異顯功能。
不過如果我們不考慮兼容性而非要同時使用雙屏異顯與 HDMI 怎么辦呢?
也簡單,在確保了 fb4/screen_info 中的分辨率與 lcdc1 的時鍾正確以后,在 android 系統中設置一條屬性:
ro.htg.force=1
即可。即在 /system/build.prop 上添加上這條屬性,重啟即可。
4、HDMI撥掉導致副屏熄滅
前面有提到,rk3288 默認將 lcdc1 與 HDMI 綁定死了。當檢測到撥掉 HDMI 時就不往 lcdc1 送視頻數據。
所以最簡單的解決辦法就是不上報 HDMI 的撥出事件。只需修改一處代碼即可,如下圖所示:
5、副屏花屏
修改副屏的屏參,如果屏參正確了,則將上面第 3 步提到的 ro.htg.force=1 配置一下基本也能解決的了。