7.9.5. 设计说明

7.9.5.1. 源码说明

源代码位于:linux-5.x/drivers/input/touchscreen/zx.c

7.9.5.2. 模块架构

RTP驱动基于Linux内核中的input子系统实现,其关系如下图:

../../../_images/input_system.png

图 7.44 Linux Input子系统架构图

7.9.5.3. 关键流程设计

7.9.5.3.1. 初始化流程

RTP模块完全遵循platform_driver的通用初始化流程,申请regs资源、clk、reset, 还需要注册一个input设备,使用input子系统提供的注册接口input_register_device():

int __must_check input_register_device(struct input_dev *);

参数struct input_dev记录了该input设备的信息,其中关键信息有:设备名称、 open/close接口、KEY类型、坐标范围等。RTP控制器的input信息注册如下:

rtp->idev = idev;
idev->name = pdev->name;
idev->phys = AIC_RTP_NAME "/input0";
idev->open = aic_rtp_open;
idev->close = aic_rtp_close;
idev->id.bustype = BUS_HOST;
idev->evbit[0] =  BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);
input_set_capability(idev, EV_KEY, BTN_TOUCH);
input_set_abs_params(idev, ABS_X, 0, AIC_RTP_MAX_VAL, rtp->fuzz, 0);
input_set_abs_params(idev, ABS_Y, 0, AIC_RTP_MAX_VAL, rtp->fuzz, 0);
if (rtp->pressure_det)
        input_set_abs_params(idev, ABS_PRESSURE, 0, AIC_RTP_MAX_VAL,
                             rtp->fuzz, 0);

7.9.5.3.2. 中断处理流程

RTP控制器采集的数据完全依赖中断来上报给用户态,包括触摸位置、按下、抬起信息。 流程如下图:

../../../_images/irq_flow1.png

“启动manual worker”和“启动smp worker”分别是对应手动模式、非周期模式的采样流程,因为这两种情况下都会有一些延迟操作,所以使用worker方式来处理。实际运行期间RTP只可能工作在一种单一模式,所以运行中只会有一个worker在参与调度。

其中,检查的异常事件类型及处理方式如下图:

../../../_images/abnormal_event_type.png

其中,“数据不完整”仅在自动模式才会出现,实际上有三种原因导致不完整:

  1. 采样循环不完整:Sample Cycle Incomplete,一组采样点还没有完成就发生了抬起事件;

  2. 数据超限:Data Over Uncertain Range,数据超出了有效范围;

  3. FIFO下溢:FIFO上溢意味着数据有效、软件读慢了,所以还可以继续数据;如果是下溢,意味着FIFO中的数据分组排列已经乱了,所以直接丢弃。

7.9.5.3.3. 手动模式的采样流程

手动模式,需要通过软件触发的方式告诉RTP控制器要采集什么样的数据,所以采集样本的电信号配置、采集间隔、是否打开按压检测等,都需要在驱动中来妥善安排。 因为每次中断来了后,手动模式需要做的处理较多,而且有一些延迟处理,所以在驱动中使用了一个worker专门处理手动模式的流程(接口aic_rtp_manual_worker())。 手动模式的处理流程较复杂,建议通常情况下采样自动模式。

../../../_images/manual_mode.png

图 7.45 手动模式的状态切换流程

上图中,在蓝色方框的后面都会有一个判断:如果当前是否抬起状态,如果是就打开按压检测。为了流程的主干更加清晰,所以图中未标注出来。

7.9.5.4. 数据结构设计

7.9.5.4.1. aic_rtp_dev

管理RTP控制器的设备资源。

struct aic_rtp_dev {
    struct platform_device *pdev;
    struct attribute_group attrs;
    struct clk *clk;
    struct reset_control *rst;

    struct device *dev;
    struct input_dev *idev;
    void __iomem *regs;
    u32 irq;
    u32 pclk_rate;

    bool two_points;
    bool pressure_det;
    bool ignore_fifo_data;
    enum aic_rtp_mode mode;
    u32 max_press;
    u32 smp_period;
    u32 x_plate;
    u32 y_plate;
    u32 fuzz;

    struct workqueue_struct *workq;
    struct work_struct event_work;
    u32 intr;
    u32 fcr;
    struct aic_rtp_dat latest;
    enum aic_rtp_manual_mode_status mms;
};

7.9.5.5. 接口设计

以下接口是Input子系统需要的标准接口。

7.9.5.5.1. aic_rtp_open

函数原型

static int aic_rtp_open(struct input_dev *dev)

功能说明

打开RTP设备,驱动会使能RTP控制器

参数定义

dev - 指向当前的input设备

返回值

0,成功; < 0,失败

注意事项

7.9.5.5.2. aic_rtp_close

函数原型

static void aic_rtp_close(struct input_dev *dev)

功能说明

关闭RTP设备,驱动会关闭RTP控制器

参数定义

dev - 指向当前的input设备

返回值

注意事项