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 performing 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 transmission data is big endian transmission, each transmission 8bit, that is, one byte.    Multimastering is supported, and there can only be one master at any point in time.    Each device on the bus has its own addr, a total of 7 bits, and the broadcast address is all 0.    There may be multiple chips of the same type in the system. For this reason, the addr is divided into a fixed part and a programmable part, and the details depend on the chip. , see datasheet.


The last article mainly talked about the knowledge points related to TP. This is mainly because you have a basic concept of this module and know its working principle, so that in the actual development process, you will know how to write the driver. , When encountering a problem, where does it appear and how to solve it.

      This article is mainly based on the code to talk about the relevant mechanisms involved in the previous article. The connection of TP is very simple, all the way I2C, one interrupt line, VCC, GND, reset.

1. TP main related demos:

驱动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. Interpretation of dtsi

i2c@f9923000{ //The I2C register
focaltech@38 connected to the TP{ 
compatible = "focaltech,5x06"; //The content of the I2C driver match
reg = <0x38>; //I2C address
interrupt-parent = <&msmgpio>; //Interrupt pin
interrupts = <1 0x2>;
vdd-supply = <&pm8110_l19>; //I2C powered movie control
vcc_i2c-supply = <&pm8110_l14>;
focaltech,name = "ft6x06"; //tp type
focaltech,family-id = <0x06>;   
focaltech,reset-gpio = <&msmgpio 0 0x00>; //Reset pin, for initialization timing
focaltech,irq-gpio = <&msmgpio 1 0x00>; //Interrupt pin
focaltech,display-coords = <0 0 480 800>; //TP contact range
focaltech,panel-coords = <0 0 480 800>;
focaltech,button-map= <139 102 158>; //Virtual key
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. Driver files

3.1 I2C driver registration

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 The file interface, of_match_table , needs to be consistent with the compatible definition in DTSI .

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

There is too much code in this, so I will not explain them in detail. Here are some basic steps.

Generally, first allocate storage space to the relevant structure, and then read the relevant information from the dt device tree to test whether the I2C is connected.

input_dev = input_allocate_device(); //Allocate the input subsystem

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); //Initialization related to power and GPIO

ft5x06_power_on(data, true);  // Power on, sequence initialization

err = request_threaded_irq(client->irq, NULL,ft5x06_ts_interrupt,IRQF_ONESHOT,
client->dev.driver->name, data); //Request an interrupt and place event processing in the lower half.

psensor_input_dev = input_allocate_device();  allocate child input device

err = input_register_device(psensor_input_dev);

ft5x06_update_fw_ver(data); //Import firmware information
ft5x06_update_fw_vendor_id(data); //Get firmware version ID


3.4 Interrupt handler ft5x06_ts_interrupt 

static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id)

This is mainly to read I2C, according to the chip manual, to output the data, and then report the event.

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

input_sync(ip_dev);

Of course, some TPs, such as GT9xxxx, will apply for the work queue, and then the interrupt will be generated in the upper half, start the work queue, and then block the current interrupt, and enable the interrupt after the work queue event is processed. Some will also apply for a high-precision timer when the interrupt request fails, and will always poll to start the worker thread and report the event.


4. Debug related experience

4.1 In general TP driver development, screen production will give driver code or PATCH, and then the main code is combined.

Generally look for an existing TP driver in the code, and press it to add. main:

1. Put the driver file into kernel\drivers\input\touchscreen\,

2. Modify kconfig and Makefile, and add macros that need to be compiled in, then you need to set it to Y in the deconfig configuration file.

3. Add the TP configuration to DTSI.


 4.2 Compile boot, under out/target/product/msmXXX/obj/KERNEL_OBJ/driver/input/ touchscreen/, see if there is no .o file, if there is, the compilation is successful.

4.3 Brush the new boot file into the board, check the kernel log, cat proc/kmsg, and see if there is any printing information of the TP driver.

4.4 According to the printed information, determine the error problem.

The general problem is that the interrupt registration fails, the resource allocation is unsuccessful, and the I2C device communication fails.

According to some experience, the I2C bus is not connected, it may be because the power supply of the I2C power supply does not supply power, or there are too many devices hanging on the bus, and it is best to connect only one device on the I2C bus in the early adjustment.

If the probe is successful, you can add some print logs to the interrupt or worker thread. Enter the terminal in adb shell, enter getevent, and press TP to see if there is data to be typed, for the input device of the TP.


5. View I2C devices:

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=324809692&siteId=291194637