TP code analysis of Qualcomm platform

TP driver chip manufacturers mainly include: Goodix (Huiding), FocalTech (Duntai Technology), cypress (Cypress), synaptics (Synaptics).
TP-driven debugging is mainly to adjust the interface.
Obtain drivers and configuration information from the TP manufacturer.
4.2.1. Integrate or use the TP driver that comes with the system

Find kernel/drivers/input/touchscreen to see if there is a corresponding driver. If not, you can download the driver from Qualcomm's website or ask the manufacturer for the driver

Since the TP communicates with the processor through I2C, as long as the I2C is turned on, the TP debugging work is basically completed.
Check the execution of these probe functions through the kernel log: goodix_ts_probe(), cyttsp5_probe(), synaptics_rmi4_probe() to see where the problem lies.
I2C mainly depends on whether the address is correct. Also use an oscilloscope to measure the waveform on the I2C line. I2C is pulled high when not in use, and there is a pull-down signal when data is transmitted. If the log says that I2C is busy, it is possible that I2C is not pulled high.


TP touch screen should be a relatively simple module in driver development and suitable for beginners. However, although it is simple, it involves a lot of content. Among them, the main mechanisms related to linux are:

1. Input mechanism

2. Interrupts, timers

3. I2C

1. The principle of TP: TP is generally a capacitive or resistive screen, but now it is basically a capacitive screen, maybe some WINCE devices will also use a resistive screen, but Android is now basically a capacitive screen, and multi-touch and gloves The touches are all integrated in the TP's IC. When the user touches the capacitive screen, due to the electric field of the human body, a coupling capacitor is formed between the user's finger and the work surface. Because the work surface is connected to a high-frequency signal , the finger absorbs a small current, which flows from the four corners of the screen respectively. In theory, the current flowing through the four electrodes is proportional to the distance from the finger to the four corners. The controller obtains the position through precise calculation of the ratio of the four currents. It can reach 99% accuracy and has a response speed of less than 3ms. In the actual product, when the screen senses the touch or approach of the finger, an external interrupt will be generated to the CPU. In the interrupt, the lower half is generally interrupted, and the relevant information is read from the TP IC through the I2C bus. data processing, reporting X, Y coordinate values.

 2.linux input mechanism:

The linux input subsystem is implemented by three layers from top to bottom, namely: the input subsystem event processing layer (EventHandler), the input subsystem core layer (InputCore) and the input subsystem device driver layer.

For the input subsystem device driver layer, it mainly implements read and write access to hardware devices, interrupt setting, and converts the events generated by the hardware into the specifications defined by the core layer and submits them to the event processing layer . (The main thing that engineers do)

For the core layer, specifications and interfaces are provided for the device driver layer. The device driver layer only needs to care about how to drive the hardware and obtain hardware data (such as pressed key data), and then call the interface provided by the core layer, and the core layer will automatically submit the data to the event processing layer.

For the event processing layer, it is the user programming interface (device node), and handles the data processing submitted by the driver layer.

3.  Interruption

Interrupt means that during the normal operation of the CPU, the CPU temporarily stops the running program due to internal and external events or events prearranged by the program, and turns to the program that serves the internal or external events or prearranged events. After finishing, go back to continue running the program that was temporarily interrupted. Linux is usually divided into external interrupts (also called hardware interrupts) and internal interrupts (also called exceptions).

Linux interrupts are divided into two halves: the top half and the bottom half. The function of the upper half is to "register interrupts". When an interrupt occurs, it will hang the lower half of the interrupt routine into the execution queue of the lower half of the device after corresponding hardware reading and writing. As a result, the top half executes very fast and can service more interrupt requests. However, simply "registering an interruption" is not enough, because the events of the interruption can be complex. Therefore, Linux introduced a lower half to complete most of the tasks of the interrupt event. The biggest difference between the lower half and the upper half is that the lower half is interruptible, while the upper half is uninterruptible, the lower half does almost everything the interrupt handler does, and can be interrupted by new interrupts! The lower part is relatively not very urgent, and is usually time-consuming, so the system arranges the running time by itself and is not executed in the context of interrupt service.

4. Timer

Two devices are used for timing: the system timer and the real-time clock.

Real Time Clock (RTC) : A device used to store system time persistently, even after the system is turned off, powered by a tiny battery on the motherboard to keep the system timed. The system boot kernel initializes the wall time by reading the RTC, and the modified time is stored in the xtime variable.

System timer : kernel timing mechanism, registering interrupt handlers, periodically triggering interrupts, responding to interrupt handlers, and processing to perform the following tasks:

5.  I2C protocol

2 bidirectional serial lines, one data line SDA, one clock line SCL.

SDA传输数据是大端传输,每次传输8bit,即一字节。
   支持多主控(multimastering),任何时间点只能有一个主控。
   总线上每个设备都有自己的一个addr,共7个bit,广播地址全0.
   系统中可能有多个同种芯片,为此addr分为固定部分和可编程部份,细节视芯片而定,看datasheet。

上一篇主要讲的与TP相关的知识点,讲这个主要是,你对这一模块有个基本的概念,知道其工作原理,这样在实际开发过程中,你才知道怎么去写起的驱动,碰到问题时,出现在哪一块,该怎么去解决。

      这一篇,主要根据代码来讲上一篇涉及到的相关机制。TP的连线很简单,一路I2C,一根中断线,VCC、GND,reset。

1. TP主要相关demo:

驱动demo:\kernel\drivers\input\touchscreen\Ft5x06_ts.c 

    \kernel\drivers\input\touchscreen\Ft5x06_ts.h

dtsi文件:\kernel\arch\arm\boot\dts\qcom\Msm8X16-qrd.dtsi

2. dtsi的相关解释

i2c@f9923000{ //TP所连的I2C的寄存器
focaltech@38{ 
compatible = "focaltech,5x06"; //I2C驱动match的内容
reg = <0x38>; //I2C地址
interrupt-parent = <&msmgpio>;  //中断引脚
interrupts = <1 0x2>;
vdd-supply = <&pm8110_l19>;     //I2C供电的电影控制
vcc_i2c-supply = <&pm8110_l14>;
focaltech,name = "ft6x06";     //tp类型
focaltech,family-id = <0x06>;   
focaltech,reset-gpio = <&msmgpio 0 0x00>; //复位引脚,,用于初始化时序
focaltech,irq-gpio = <&msmgpio 1 0x00>;   //中断引脚
focaltech,display-coords = <0 0 480 800>; //TP的触点范围
focaltech,panel-coords = <0 0 480 800>;
focaltech,button-map= <139 102 158>;     //虚拟按键
focaltech,no-force-update;
focaltech,i2c-pull-up;
focaltech,group-id = <1>;
focaltech,hard-reset-delay-ms = <20>;
focaltech,soft-reset-delay-ms = <150>;
focaltech,num-max-touches = <2>;
focaltech,fw-name = "ft_8610_qrd_fw.bin"; //TP固件
focaltech,fw-delay-aa-ms = <100>;
focaltech,fw-delay-55-ms = <30>;
focaltech,fw-upgrade-id1 = <0x79>;
focaltech,fw-upgrade-id2 = <0x08>;
focaltech,fw-delay-readid-ms = <10>;
focaltech,fw-delay-era-flsh-ms = <2000>;
};
}; 

3. 驱动文件

3.1 I2C驱动注册

static int __init ft5x06_ts_init(void)
{
pr_err("start \n");
return i2c_add_driver(&ft5x06_ts_driver); //I2C驱动注册
pr_err("end \n");
}

3.2 文件接口,of_match_table,需要DTSI中compatible定义的一致。

static struct i2c_driver ft5x06_ts_driver = {
.probe = ft5x06_ts_probe,
.remove = ft5x06_ts_remove,
.driver = {
  .name = "ft5x06_ts",
  .owner = THIS_MODULE,
.of_match_table = ft5x06_match_tabl
#ifdef CONFIG_PM
  .pm = &ft5x06_ts_pm_ops,
#endif
  },
.id_table = ft5x06_ts_id,
};

3.3 probe

这个里面代码量太多,就不详细一一说明,这里主要讲解一些基本的步骤。

一般,先给相关的结构体分配存储空间,然后从dt设备树中读取相关的信息,测试I2C是否通。

input_dev = input_allocate_device();//分配输入子系统

data->input_dev = input_dev;
data->client = client;
data->pdata = pdata;
input_dev->name = "ft5x06_ts";
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev;
input_set_drvdata(input_dev, data);
i2c_set_clientdata(client, data);
__set_bit(EV_KEY, input_dev->evbit);  //设置有什么事件 按键事件 tp虚拟按键
__set_bit(EV_ABS, input_dev->evbit);  //绝对事件 
__set_bit(BTN_TOUCH, input_dev->keybit);
__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
input_mt_init_slots(input_dev, pdata->num_max_touches, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min, //X坐标事件
    pdata->x_max, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min, //Y坐标事件
    pdata->y_max, 0, 0);

ft5x06_power_init(data, true); //电源、GPIO相关的初始化

ft5x06_power_on(data, true); // 上电,时序初始化

err = request_threaded_irq(client->irq, NULL,ft5x06_ts_interrupt,IRQF_ONESHOT,
client->dev.driver->name, data); //请求中断,并把事件处理放在下半部。

psensor_input_dev = input_allocate_device(); 分配子输入设备

err = input_register_device(psensor_input_dev);

ft5x06_update_fw_ver(data); //导入固件信息
ft5x06_update_fw_vendor_id(data); //获取固件版本ID


3.4 中断处理程序 ft5x06_ts_interrupt

static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id)

这个里面主要是读I2C,根据芯片手册,进行数据出来,然后上报事件。

input_report_abs(ip_dev, ABS_MT_POSITION_X, x);
input_report_abs(ip_dev, ABS_MT_POSITION_Y, y);

input_sync(ip_dev);

当然有些TP,如GT9xxxx,会申请工作队列,然后中断产生会在上半部,启动工作队列,然后屏蔽当前中断,在工作队列事件处理完后,使能中断。有些还会当中断请求失败时,申请一个高精度的定时器,会一直轮询启动工作线程,上报事件。


4. 调试相关经验

4.1 一般TP驱动开发,屏产都会给驱动代码或者PATCH,这时主要合代码进去。

一般找代码内现有的一个TP驱动,按它的添加。主要:

1. 把驱动文件放入kernel\drivers\input\touchscreen\,

2. 修改kconfig和Makefile,加入需要根据宏才能编进去,那么需要在deconfig配置文件中设置为Y.

3. 在DTSI中加入该TP的配置。


 4.2 编译boot,在out/target/product/msmXXX/obj/KERNEL_OBJ/driver/input/touchscreen/下,看是否有.o文件没有,有则编译成功。

4.3 把新的boot文件刷入板子,查看内核log,cat proc/kmsg,看是否有该TP驱动的打印信息。

4.4 根据打印信息,判断出错的问题。

一般问题,中断注册不上,资源分配不成功,I2C设备通信失败。

一些经验,I2C总线不通,可能是因为I2C供电的电源没有供电,或者该总线上挂的设备太多影响的,前期调最好I2C总线上,只挂一个设备。

若probe成功,可在中断或者工作线程里面加一些打印log。在adb shell进入终端,输入getevent,手按TP,查看是否有数据打出,对于该TP的输入设备。


5. 查看I2C设备:

root@Android:/sys/bus/i2c # cd devices
cd devices
root@android:/sys/bus/i2c/devices # ls
ls
0-0020
0-0022
0-0036
0-0078
1-000c
1-000d
1-001d
1-0028
1-0029
1-002a
1-0038
1-0060
1-0068
2-001c
i2c-0
i2c-1
i2c-2
root@android:/sys/bus/i2c/devices # cd 0-0036
cd 0-0036
root@android:/sys/bus/i2c/devices/0-0036 # ls
ls
driver
modalias
name
power
subsystem
uevent
root@android:/sys/bus/i2c/devices/0-0036 # cat name
cat name
msm_actuator
root@android:/sys/bus/i2c/devices/0-0036 #


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324809728&siteId=291194637