以在mtk6737平臺移植匯頂的GT910舉例,建議正式除錯的前一天把代碼完整編譯一遍,假如時間來不及,至少要先編譯內核,編譯
eng或者userdebug版本,一般要提前準備:主板、TP模組、串口線、硬體原理圖,供應商提供芯片手冊、規格書、驅動代碼和cfg引數
等,除錯最開始首先要了解TP芯片的型號、螢屏解析度、主板上面TP座子位置、供電方式、中斷和復位腳的GPIO號、用到哪組i2c總線
核對主板座子和規格書里面排線線序是否一致,接下來第一個小目標就是調通i2c,讀到正確的ID值,
TP(觸摸屏)的大致作業流程是:主控芯片與TP芯片通過i2c總線通訊,它們之間一般有6個引腳相連接,分別是VDD、RESET、SCL、
SDA、INT、GND,開機程序中系統會對TP芯片進行上電初始化,之后TP處于待命狀態,當TP模組表面有觸摸時,會產生中斷,接著
在中斷處理函式中喚醒觸摸事件的執行緒,在執行緒里面通過i2c讀取點坐標資訊上報給系統層,
1、移植芯片driver驅動代碼
把廠家提供的GT910的代碼復制到以下目錄,有時候要把另外提供的CFG引數替換到gt9xx_config.h的CTP_CFG_GROUP1中
kernel-3.18/drivers/input/touchscreen/mediatek/
驅動代碼gt9xx_driver.c中需要重點關注的一些函式:
static int __init tpd_driver_init(void); /*一般閱讀驅動的代碼是從最下面的module_init里面的函式開始*/
void tpd_get_dts_info(void); /*讀取設備樹touch節點的屬性*/
static int tpd_local_init(void); /*在這里添加i2c driver*/
static s32 tpd_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id); /*i2c driver與device匹配成功才呼叫這個函式*/
static int tpd_power_on(struct i2c_client *client); /*上電和復位*/
s32 gtp_read_version(struct i2c_client *client, u16 *version); /*讀取版本號,在這里可以確認i2c通訊是否成功*/
static s32 gtp_init_panel(struct i2c_client *client); /*TP芯片的初始化*/
static int tpd_irq_registration(void); /*申請中斷*/
static int touch_event_handler(void *unused); /*觸摸事件處理執行緒,中斷產生時會喚醒這個執行緒*/
static void tpd_down(s32 x, s32 y, s32 size, s32 id); /*上報點坐標*/
如果感興趣,可以等驅動調通后再更加仔細地閱讀代碼,在內核中用dump_stack(); 函式可以查看當前函式被哪些函式呼叫,對
跟讀代碼很有幫助,
供電方面要注意,確認是采用pmic輸出2.8V,還是外部獨立的LDO供電,根據硬體原理圖來定,
//pmic輸出2.8V的部分控制代碼
tpd->reg = regulator_get(tpd->tpd_dev, "vtouch");
ret = regulator_set_voltage(tpd->reg, 2800000, 2800000); /*set 2.8v*/
if (ret) {
printk("regulator_set_voltage(%d) failed!\n", ret);
return -1;
}
ret = regulator_enable(tpd->reg); /*使能電源*/
//獨立的LDO供電方式,則是控制某個gpio輸出高、低電平
#define GTP_POWER_PORT (GPIO22 | 0x80000000)
/*MTK舊的平臺可以直接這樣呼叫GPIO,Android7.0及以后建議改用從dts里面讀取*/
mt_set_gpio_mode(GTP_POWER_PORT, GPIO_MODE_00);
mt_set_gpio_dir(GTP_POWER_PORT, GPIO_DIR_OUT);
mt_set_gpio_out (GTP_POWER_PORT, 1); //輸出高電平,使能LDO的2.8V
2、修改Makefile和Kconfig
kernel-3.18/arch/arm/configs/產品_debug_defconfig (注意:64位系統選擇arm64目錄,32位系統選擇arm目錄)
+CONFIG_TOUCHSCREEN_MTK_GT910=y
-CONFIG_TOUCHSCREEN_MTK_FT5X0X=y
+# CONFIG_TOUCHSCREEN_MTK_FT5X0X is not set #把舊型號的config注釋掉,前面加# 末尾改成is not set
kernel-3.18/arch/arm/configs/產品_defconfig
+CONFIG_TOUCHSCREEN_MTK_GT910=y
-CONFIG_TOUCHSCREEN_MTK_FT5X0X=y
+# CONFIG_TOUCHSCREEN_MTK_FT5X0X is not set
kernel-3.18/drivers/input/touchscreen/mediatek/Makefile
+obj-$(CONFIG_TOUCHSCREEN_MTK_GT910) += GT910/
kernel-3.18/drivers/input/touchscreen/mediatek/Kconfig
+source "drivers/input/touchscreen/mediatek/GT910/Kconfig"
注意:凡是修改了config檔案,編譯前要洗掉out目錄中的.config檔案(下面的產品名稱根據自己的專案來定)
rm -rf out/target/product/產品/obj/KERNEL_OBJ/.config
3、修改設備樹dts檔案
kernel-3.18/arch/arm/boot/dts/產品.dts
&touch { # tpd_get_dts_info函式里面會讀取這里的一些引數
tpd-resolution = <480 800>; #修改解析度,與LCD的一致
use-tpd-button = <0>; #TP的底部是否帶觸摸按鍵,配置為0表示不帶
tpd-key-num = <3>;
tpd-key-local= <139 172 158 0>;
tpd-key-dim-local = <90 883 100 40 230 883 100 40 370 883 100 40 0 0 0 0>;
tpd-max-touch-num = <5>; #最多支持5點觸摸
tpd-filter-enable = <0>;
tpd-filter-pixel-density = <146>;
tpd-filter-custom-prameters = <0 0 0 0 0 0 0 0 0 0 0 0>;
tpd-filter-custom-speed = <0 0 0>;
pinctrl-names = "default", "state_eint_as_int", "state_eint_output0", "state_eint_output1",
"state_rst_output0", "state_rst_output1"; #mtk_tpd.c里面會根據這些名稱來匹配pinctrl_state,用來控制gpio
pinctrl-0 = <&CTP_pins_default>;
pinctrl-1 = <&CTP_pins_eint_as_int>;
pinctrl-2 = <&CTP_pins_eint_output0>;
pinctrl-3 = <&CTP_pins_eint_output1>;
pinctrl-4 = <&CTP_pins_rst_output0>;
pinctrl-5 = <&CTP_pins_rst_output1>;
status = "okay";
};
&pio {
CTP_pins_default: eint0default {
};
CTP_pins_eint_as_int: eint@0 {
pins_cmd_dat {
pins = <PINMUX_GPIO124__FUNC_GPIO124>; #根據原理圖修改中斷腳的gpio號
slew-rate = <0>; #配置成0表示輸入
bias-disable; #取消內部上下拉
};
};
CTP_pins_eint_output0: eintoutput0 {
pins_cmd_dat {
pins = <PINMUX_GPIO124__FUNC_GPIO124>;
slew-rate = <1>; #配置成1表示輸出
output-low; #輸出低
};
};
CTP_pins_eint_output1: eintoutput1 {
pins_cmd_dat {
pins = <PINMUX_GPIO124__FUNC_GPIO124>;
slew-rate = <1>;
output-high; #輸出高
};
};
CTP_pins_rst_output0: rstoutput0 {
pins_cmd_dat {
pins = <PINMUX_GPIO123__FUNC_GPIO123>; #根據原理圖修改復位腳的gpio號
slew-rate = <1>;
output-low;
};
};
CTP_pins_rst_output1: rstoutput1 {
pins_cmd_dat {
pins = <PINMUX_GPIO123__FUNC_GPIO123>;
slew-rate = <1>;
output-high;
};
};
};
凡是dts有修改的,編譯bootimage前要先洗掉下面目錄(不是每次編譯前都要洗掉,有修改了才需要刪)
rm -rf out/target/product/產品/obj/KERNEL_OBJ/arch/arm/boot/dts/
4、配置dws檔案
DCT編輯工具位置:
vendor\mediatek\proprietary\bootable\bootloader\preloader\tools\dct\old_dct\DrvGen.exe
DWS檔案位置:
vendor\mediatek\proprietary\bootable\bootloader\preloader\custom\產品\dct\dct\codegen.dws
vendor\mediatek\proprietary\bootable\bootloader\lk\target\產品\dct\dct\codegen.dws
kernel-3.18\drivers\misc\mediatek\mach\平臺\產品\dct\dct\codegen.dws
a、打開I2C選項欄,選擇TP的i2c設備名稱、i2c總線、填入i2c地址,
dws中的Slave Device名稱要與驅動代碼中.compatible的“cap_touch”名稱一致,dws中的設備名稱一般用大寫如下圖所示,
TP芯片用到哪組i2c總線,根據硬體原理圖來確定,TP的i2c地址可以在資料手冊里面找到或者直接問FAE,


如果Slave Device名稱找不到,可以在下面的檔案中自定義增加名稱,然后重新打開dct編輯工具,就可以在Slave Device下拉
串列中找到,
vendor/mediatek/proprietary/bootable/bootloader/preloader/tools/dct/old_dct/I2C_YuSu.cmp
b、打開GPIO選項欄,配置gpio默認屬性
gpio124是中斷腳,勾選中斷、內部上下拉使能、上拉高電平;
gpio123是復位腳,配置成普通GPIO(Def.Mode選0:),勾選內部上下拉使能,由于沒有勾選上拉所以默認是下拉輸出低電平,

c、打開EINT選項欄,配置中斷名稱、防抖時間、極性、觸發型別、是否有防抖

d、修改dws后的編譯注意
凡是dws有修改的,要先洗掉下面的3個目錄,再重新編譯pl、lk、bootimage
rm -rf out/target/product/產品/obj/KERNEL_OBJ/arch/arm/boot/dts/
rm -rf out/target/product/產品/obj/BOOTLOADER_OBJ/
rm -rf out/target/product/產品/obj/PRELOADER_OBJ/
make pl -j16 ; make lk -j16 ; make bootimage -j16
5、排除編譯報錯, boot、pl、lk編譯通過后刷機測驗
移植GT910驅動代碼后的第一次編譯,先洗掉下面的目錄再編譯,里面有其它舊型號的驅動.o檔案
rm -rf out/target/product/產品/obj/KERNEL_OBJ/drivers/input/touchscreen/
查看開機串口log里面,有沒有呼叫tpd_i2c_probe函式,probe匹配原理是:驅動代碼中tpd_of_match的compatible名稱與dws
編譯出來的I2C Slave Device compatible名稱對比,看到呼叫probe后,接著看上電、復位、讀取芯片ID、芯片初始化、申請中斷
等有沒有成功,確認開機初始化通過后,觸摸TP看看界面是否回應,除錯程序可以在代碼中多增加printk列印log,方便了解驅動
代碼運行到哪一步,
6、除錯程序遇到一些問題的處理方法
a、開機程序沒有呼叫probe函式
檢查驅動代碼有沒有編譯到,tpd_of_match中compatible里逗號后面的名稱是否與dws中的I2C Slave Device名稱一致,檢查上
面提到的一些注意事項,凡是config、dws或dts有修改,編譯前要洗掉out目錄中的一些編譯輸出檔案,
b、開機程序中i2c報錯
檢查供電、復位腳時序、軟體中i2c總線有沒有選對,核對i2c地址,核對座子和TP排線的線序,如果有必要可以使用示波器測
量波形,有時候可更換主板或TP模組試試,排除硬體物料問題,實在找不到問題點,可以找硬體設計人員、FAE一起協助分析,
c、開機初始化沒有報錯,讀ID正常,但觸摸無回應
在中斷函式里面加log列印或者使用示波器測量中斷腳波形,看有沒有中斷產生,檢查驅動代碼里面中斷腳有沒有配置正確,有
時候要更新cfg引數或者韌體,多跟FAE溝通,
d、報點錯亂、劃線斷線(系統設定開發者選項里面開啟”指標位置”后,在螢屏劃線時會有點軌跡)、觸摸不靈敏等效果問題
需要找FAE協助優化,更新cfg引數或者韌體,
7、開機初始化時tpd_i2c_probe的呼叫程序
驅動代碼gt9xx_driver.c:
static int tpd_local_init(void)
\if (i2c_add_driver(&tpd_i2c_driver) != 0) {
\int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
\int driver_register(struct device_driver *drv)
\int bus_add_driver(struct device_driver *drv)
\int driver_attach(struct device_driver *drv)
\int bus_for_each_dev(struct bus_type *bus, struct device *start, /*在這里遍歷所有的設備*/
\static int __driver_attach(struct device *dev, void *data)
\ if (!driver_match_device(drv, dev)) /*如果這里匹配不成功,則直接回傳0,不會往下呼叫driver_probe_device*/
\ static inline int driver_match_device(struct device_driver *drv,
\static int i2c_device_match(struct device *dev, struct device_driver *drv)
\ static inline int of_driver_match_device(struct device *dev,
\ const struct of_device_id *__of_match_node(const struct of_device_id *matches,
\ static int __of_device_is_compatible(const struct device_node *device, /*最終對比compatible名稱*/
\int driver_probe_device(struct device_driver *drv, struct device *dev)
\static int really_probe(struct device *dev, struct device_driver *drv)
\ret = dev->bus->probe(dev);
\static s32 tpd_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/239572.html
標籤:其他
