AM335x(TQ335x)學習筆記——LCD驅動移植
TI的LCD控制器驅動是非常完善的,共通的地方已經由驅動封裝好了,與按鍵一樣,我們可以通過DTS配置完成LCD的顯示。下面,我們來討論下使用DTS方式配置核心完成LCD驅動的思路。
(1)初步分析
由於TQ335x使用的晶片是AM335x,故仍然可以參考am335x-evm.dts。當然,am335x-evmsk.dts、am335x-beagbone.dts都可以。本文以am335x-evm.dts為例。大體上瀏覽下DTS檔案,可以發現兩個醒目的節點:一個是panel,一個是backlight。接下來我們逐個分析。
(2)panel節點資訊分析及配置
從panel節點可以獲得如下資訊:
其中,panel-info和display-times需要去LCD手冊中查詢,管腳配置需要根據AM335x的晶片手冊、資料手冊及TQ335x的原理圖確定,驅動則需要去核心的driver目錄下查詢。下面,我一一解決上述幾個問題:1. 匹配核心驅動的關鍵詞是:"ti,tilcdc,panel",可以通過這個關鍵字找到相應的驅動。 2. 管腳配置在節點lcd_pins_s0內 3. panel-info中可以配置LCD的硬體資訊,如LCD的解析度等 4. display-times中記錄了LCD刷屏的相關時序。
首先是設定panel-info和display-times。我的TQ335x是用的我除錯TQ210時使用的觸控式螢幕,型號是TN92,這個屏是800*480的解析度,因此,panel-info與evm開發板的配置是相同的,可以不做任何修改。但是,不同螢幕的display-times一般是不相同的,因此,需要查閱觸控式螢幕的手冊來確認display-times。
TN92的水平掃描時序如下表:
垂直掃描時序如下圖:
但是,如果對LCD各引數不怎麼熟悉的話,很難建立這兩個表與DTS中display-times的關係,這時應該去查閱一下linux核心的文件和晶片手冊。在核心文件:”Documentation/devicetree/bindings/video/display-timing.txt"有相關的記載,該檔案中有形象的描述,具體如下:
AM335x的技術參考手冊中可以找到相關的暫存器解釋,如下:+----------+-------------------------------------+----------+-------+ | | ↑ | | | | | |vback_porch | | | | | ↓ | | | +----------#######################################----------+-------+ | # ↑ # | | | # | # | | | hback # | # hfront | hsync | | porch # | hactive # porch | len | |<-------->#<-------+--------------------------->#<-------->|<----->| | # | # | | | # |vactive # | | | # | # | | | # ↓ # | | +----------#######################################----------+-------+ | | ↑ | | | | | |vfront_porch | | | | | ↓ | | | +----------+-------------------------------------+----------+-------+ | | ↑ | | | | | |vsync_len | | | | | ↓ | | | +----------+-------------------------------------+----------+-------+
綜合這三份資料,很容易確定下LCD的屏的時序引數的範圍(需要強調的是,上述引數不一定精確,還需要使用圖片實機測下效果),經過多次實驗,最終確定下了LCD的時序引數,詳情如下:
panel {
compatible = "ti,tilcdc,panel";
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&lcd_pins_s0>;
panel-info {
ac-bias = <255>;
ac-bias-intrpt = <0>;
dma-burst-sz = <16>;
bpp = <32>;
fdd = <0x80>;
sync-edge = <0>;
sync-ctrl = <1>;
raster-order = <0>;
fifo-th = <0>;
};
display-timings {
800x480p62 {
clock-frequency = <30000000>;
hactive = <800>;
vactive = <480>;
hfront-porch = <214>;
hback-porch = <40>;
hsync-len = <4>;
vback-porch = <20>;
vfront-porch = <23>;
vsync-len = <4>;
hsync-active = <0>;
vsync-active = <0>;
};
};
};
時序確定下來之後需要關注的就是管腳配置,由於am335x集成了LCD控制,該控制器與LCD的連線方式是通過GPIO管腳複用實現的,而evm開發板與TQ335x的LCD都接在了同一個LCD控制器上,因此,直接使用原有的管腳配置即可。這一點也可以通過閱讀TQ335x的原理圖確認,這裡我就不再分析了。
(3)backlight節點分析及配置
從backlight節點中可以獲得如下資訊:
1. 匹配核心驅動的關鍵詞是"pwm-backlight"。
2. 使用的ECAP0進行PWM輸出。
3. 有8個亮度等級。
4. 預設的亮度等級是8,也就是最亮。
瞭解以上資訊後需要查閱TQ335x手冊,弄清楚backlight控制管腳是如何連線的。通過分析TQ335x的原理圖可知,TQ335x的背光控制也是使用PWM方式控制,且該引腳接到AM335x的ECAP2_IN_PWM2_OUT管腳上,而evm開發板是接在ECAP0_IN_PWM0_OUT管腳上的,因此,需要修改DTS配置才能正常使用TQ335x的背光功能。思路是將DTS中的背光配置由EACP0改為EACP2,下面是修改的步驟:
Step1. 將backlight節點中&eacp0改為&eacp2。
Step2. 將&epwmss0改為&epwmss2,並將該節點內的ecap0: [email protected]改成ecap0:[email protected],然後將該節點中的&ecap0_pins改成&ecap2_pins。
Step3. 將ecap0_pins節點改名為ecap2_pins,然後將pinctrl-single,pins內的內容改為:0x19c MUX_MODE4。
最後修改後的DTS相關部分如下:
backlight {
compatible = "pwm-backlight";
pwms = <&ecap2 0 50000 0>;
brightness-levels = <0 51 53 56 62 75 101 152 255>;
default-brightness-level = <8>;
};
&epwmss2 {
status = "okay";
ecap2: [email protected] {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&ecap2_pins>;
};
};
ecap2_pins: backlight_pins {
pinctrl-single,pins = <
0x19c MUX_MODE4 /* MCASP0_AHCLKR.eCAP2_in_PWM2_out MODE4 */
>;
};
這樣就完成了背光功能的DTS配置。
(4)配置核心驅動
由於evm開發板的程式碼是使用ATAGS方式啟動的,沒有配置pwm-backlight和基於TI LCD控制器的通用panel驅動,需要通過menuconfig開啟相應的配置項。通過DTS中的compatible屬性可以找到pwm-backlight驅動是在drivers/video/backlight/pwm-bl.c中實現的,而panel驅動則是在drivers/gpu/drm/tilcdc/tilcdc_panel.c中實現的,閱讀相應目錄下的Makefile和Kconfig就可以確定出如何配置menuconfig。Makefile和Kconfig的分析過程很簡單,我就不多寫了,下面是通過menuconfig開啟相應功能的步驟。
Step1. 執行menuconfig指令:
make ARCH=arm menuconfig
Step2. 開啟通用pwm-backlight驅動和基於TI LCD控制器的通用panel驅動,配置內容如下:Graphics support --->
[*] Pulse-Width Modulation (PWM) Support --->
<*> ECAP PWM support
<*> EHRPWM PWM support
-*- Backlight & LCD device support --->
<*> Generic PWM based Backlight Driver
Graphics support --->
Direct Rendering Manager --->
<*> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) --->
<*> DRM Support for TI LCDC Display Controller
(5)編譯DTB和核心
執行DTB編譯指令:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- tq335x.dtb
執行核心編譯指令:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- -j8
(6)用新核心啟動開發板將新編譯好的tq335x.dtb和zImage拷貝到SD卡的boot目錄下,然後用SD啟動開發板到u-boot命令列模式,通過u-boot指令啟動核心(每次都這樣啟動會比較麻煩,可以通過設定u-boot的bootcmd環境變數並儲存來簡化此動作),啟動核心的指令與前一篇文章的命令是相同的:
load mmc 0 0x88000000 /boot/tq335x.dtb
load mmc 0 0x82000000 /boot/zImage
load mmc 0 0x88080000 /boot/ramdisk.img
bootz 0x82000000 0x88080000 0x88000000
這時,可以看到開發板正常啟動並且能看到熟悉的Linux小企鵝Logo,至此,就完成了am335x的LCD驅動移植,實際上是不需要我們寫程式碼的,但需要了解核心的組織方式和DTS配置的方法。(7)pinmux配置引數的確定方法
相信有些人看完這幾篇文章之後有個疑問,就是配置pinmux的時候offset是如何確定的。配置GPIO管腳複用功能時經常用到pinctrl-single,pins = <offset, function>屬性,核心解析該屬性後根據offset和function配置對應的暫存器,是GPIO管腳配置為指定的複用功能。
講offset的確定方法之前需要指出的是,TI的GPIO控制與三星的晶片不同,三星的晶片管腳複用功能是放在GPIO暫存器中的,而TI的晶片則有個專門的控制模組叫Control Module,該模組可以控制所有的GPIO管腳功能複用;另外,與三星晶片的另外一個不同是TI的晶片分為技術參考手冊和資料手冊,技術參考手冊非常詳細的講述同family的晶片功能及使用方法,資料手冊則用來講述同family中不同晶片特有的屬性。因此,除錯TI晶片時需要結合技術參考手冊和資料手冊,而配置GPIO則需要閱讀技術手冊的GPIO、Control Module兩章和資料手冊中相關的部分。
從am33xx.dtsi中可以看到pinmux的基地址是0x44e10800,我們先來看這個地址是怎麼來的。從技術參考手冊的記憶體對映表可以確定該地址位於L4_WKUP段內,如下圖:
點選L4_WKUP超連結,可以切換到L4_WKUP的地址對映表,從該表中可以確定,該地址位於Control Module,如下圖:
點選Control Module的超連結,可以切換到Control Module的地址對映表,從該表中可以找到0x44e10800地址,實際上就是conf_gpmc_ad0控制暫存器的地址,也就是說,pinmux配置時的offset都基於這個地址的。
以PWM背光控制為例。該功能引腳是接在ECAP2_IN_PWM_OUT上的,實際上就是AM335x的MCASP0_AHCLKR管腳,該管腳的地址也可以在Control Module的地址對映表中找到,該管腳的地址是0x44e1099c(表中是基於Control Module的offset,這個值是計算之後的),因此,在pinmux中配置該引腳時使用的offset應該是0x19c,這樣就確定出了offset。 pinctrl-single,pins的第二項是function,用來指定GPIO管腳是輸入還是輸出,當前處於哪種模式。輸入輸出很容易配置,但是AM335x技術參考手冊中只提到每個管腳有8中模式,即MODE0~MODE7,其中,MODE0是主模式,但是沒有具體講每個引腳的每個MODE是什麼功能,這時,就需要查閱AM335x資料手冊了。在AM335x資料手冊MCASP0_AHCLKR的八種模式的含義,如下圖:由於我們使用的是eCAP2_in_PWM2_out功能,故使用MUX_MODE4。這就是backlight的pinmux配置時使用pinctrl-single,pins = <0x19c MUX_MODE4>的原因。
(8)效果展示
到這裡LCD的移植工作就算完成了,下面是TQ335x驅動LCD後的效果圖:
(9)總結
使用DTB方式配置核心驅動一般需要以下幾個步驟:
Step1. 設定pinmux,配置的GPIO為相應的功能。
Step2. 設定相應的節點,關聯對應的驅動。
Step3. 檢查核心配置項,確保開啟對應的驅動選項。
本文作者:girlkoo