Fork me on GitHub

ft6236 触摸屏驱动

在目录下amp\a53_linux\drv\extdrv\touchpad\ft6236下可以看到ft6236.c的文件

1. init函数

static int __init ft_init(void)
{
    int ret = 0;
    hi_gpio_groupbit_info stIntInfo;
    hi_gpio_groupbit_info stRstInfo;

    stIntInfo.group_num = INT_GPIO_CHIP;
    stIntInfo.bit_num = INT_GPIO_OFFSET;
    stIntInfo.value = 0;

    stRstInfo.group_num = RST_GPIO_CHIP;
    stRstInfo.bit_num = RST_GPIO_OFFSET;
    stRstInfo.value = 1;

    ret = i2cdev_init();
    if (ret)
    {
        dev_err(NULL, " i2cdev_init fail!\n");
        goto error_end;
    }

    hi_gpio_set_dir(&stIntInfo);
    hi_gpio_set_dir(&stRstInfo);

    ret = ft_reset(&stRstInfo);
    if (ret)
    {
        dev_err(NULL, " ft_reset fail!\n");
        goto error_end;
    }
    ret = devinput_init();
    if (ret)
    {
        dev_err(NULL, " devinput_init fail!\n");
        goto error_end;
    }

    return 0;
error_end:
    return -1;
}

INT_GPIO_CHIPINT_GPIO_OFFSET都是在宏定义
#elif (defined(BOARD_DEMB) && (defined(HI3556AV100) || defined(HI3519AV100)))下定义的

#define RST_GPIO_CHIP (2)
#define RST_GPIO_OFFSET (6)
#define INT_GPIO_CHIP (2)
#define INT_GPIO_OFFSET (5)

这些管脚可以在这里《Hi3556AV100 Demo 单板使用指南.pdf》中看到,分别得出触摸屏的中断和复位管脚

1.1 对触摸屏进行复位

static int ft_reset(hi_gpio_groupbit_info* pstRstInfo)
{
    pstRstInfo->value = 1;
    hi_gpio_write_bit(pstRstInfo);
    pstRstInfo->value = 0;
    hi_gpio_write_bit(pstRstInfo);
    msleep(5);
    pstRstInfo->value = 1;
    hi_gpio_write_bit(pstRstInfo);
    return 0;
}

对触摸屏进行复位;

1.2 input系统初始化

static int devinput_init(void)
{
    int error = 0;
    /* 1. distribution a "input_dev" structure */
    ft_ts_dev = input_allocate_device();
    if (ft_ts_dev == NULL)
    {
        printk(" func:%s line:%d \r\n", __FUNCTION__, __LINE__);
        return -1;
    }
    ft_ts_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
    set_bit(EV_SYN, ft_ts_dev->evbit);
    set_bit(EV_KEY, ft_ts_dev->evbit);
    set_bit(EV_ABS, ft_ts_dev->evbit);
    set_bit(INPUT_PROP_DIRECT, ft_ts_dev->propbit);
    input_set_abs_params(ft_ts_dev, ABS_MT_POSITION_X, 0 , FT_SCREEN_WIDTH_NUM, 0, 0);
    input_set_abs_params(ft_ts_dev, ABS_MT_POSITION_Y, 0, FT_SCREEN_HEIGHT_NUM, 0, 0);
    input_set_abs_params(ft_ts_dev, ABS_MT_TOUCH_MAJOR,
                         0, 0xff, 0, 0);
    input_set_abs_params(ft_ts_dev, ABS_MT_PRESSURE,
                         0, 0xff, 0, 0);
    input_set_abs_params(ft_ts_dev, ABS_MT_TRACKING_ID,
                         0, 0xff, 0, 0);

    error = input_mt_init_slots(ft_ts_dev, FT_MAX_TOUCH_POINTS,
                                INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);

    if (error)
    { return error; }
    ft_ts_dev->name = "ft";
    ft_ts_dev->id.bustype = BUS_I2C;

    error = input_register_device(ft_ts_dev);
    if (error)
    {
        dev_err(NULL, "failed to register input device: %d\n", error);
        return error;
    }

    /**request_threaded_irq(unsigned int irq,irq_handler_t handler,irq_handler_t thread_fn,unsigned long irqflags,const char * devname,void * dev_id)*/
    error = fts_irq_register();
    if(error)
    {
        dev_err(NULL, "failed to register input device: %d\n", error);
        return error;
    }
    /**Clear INT*/
    touch_set_reg(0x045f241C, 0x20);
    return 0;
}
  1. set_bit()告诉input输入子系统支持哪些按键

evbit:

事件类型(包括EV_RST,EV_REL,EV_MSC,EV_KEY,EV_ABS,EV_REP等)

propbit:

set_bit(INPUT_PROP_DIRECT,dev->propbit);//表明设备的坐标直接和屏幕坐标向对应

  1. input_set_abs_params

给设备的input_dev结构体初始化,这些input_dev如果想被当成多点屏处理的话,只需要给input_dev额外增加以下几个参数:

input_set_abs_params(ft_ts_dev, ABS_MT_POSITION_X, 0 , FT_SCREEN_WIDTH_NUM, 0, 0);
input_set_abs_params(ft_ts_dev, ABS_MT_POSITION_Y, 0, FT_SCREEN_HEIGHT_NUM, 0, 0);
input_set_abs_params(ft_ts_dev, ABS_MT_TOUCH_MAJOR,
                     0, 0xff, 0, 0);
 //相当于单点屏的ABX_PRESSURE
input_set_abs_params(ft_ts_dev, ABS_MT_PRESSURE,
                     0, 0xff, 0, 0);
input_set_abs_params(ft_ts_dev, ABS_MT_TRACKING_ID,
                     0, 0xff, 0, 0);
//确定第几手指来上报的数据

input_set_abs_params(idev, ABS_X, -64, 64, 4, 0);

对于X轴范围是-64到+64,数据误差是-4到+4,中心平滑位置是0

  1. input_mt_init_slots

报告最大支持的点数

  1. input_register_device

注册input子系统

  1. 通过注册中断管脚

fts_irq_register注册中断

2. 中断函数处理

static irqreturn_t ftint_irq(int irq, void *data)
{
    int i;
    bool act;
    struct input_dev* input = ft_ts_dev;
    ts_event event;
    int ret = touch_event_handler(&event);
    if(ret)
        printk( "\n buffer_read failed \n");
    if(event.point_num != 0)
    {
        for(i = 0; i < event.touch_point; i++)
        {
            input_mt_slot(input, i);
            act = (event.au8_touch_event[i] == FT_EVENT_PRESS_DOWN || event.au8_touch_event[i] == FT_EVENT_CONTACT);
            input_mt_report_slot_state(input, MT_TOOL_FINGER, act);
            if (!act)
                continue;
            input_report_abs(input, ABS_MT_POSITION_X, event.au16_x[i]);
            input_report_abs(input, ABS_MT_POSITION_Y, event.au16_y[i]);
        }
    }
    input_mt_sync_frame(input);
    input_sync(input);
    return IRQ_HANDLED;
}
  1. touch_event_handler函数
ret = hi_i2c_read(0x0, buf, FT_MAX_BUFUSED_NUM);

在这里,使用了hi_i2c_read,在文件i2cdev.c中,注意i2c_board_info的一般是8位从地址;

一般来说,触摸屏有固件的,然后每一个固件都代表类似的协议,由于我们没有相应的协议,所以按照下面的来看:

for (i = 0; i < FT_MAX_TOUCH_POINTS; i++)
    {
        event->touch_point++;

        /**Notice the  array bound !!*/
        /* 获取x坐标 */
        event->au16_x[i] =
            (s16) (buf[FT_TOUCH_X_H_POS + 6 * i] & 0x0F) << 8 | (s16) buf[FT_TOUCH_X_L_POS + 6 * i];
        /* 获取y坐标 */
        event->au16_y[i] =
            (s16) (buf[FT_TOUCH_Y_H_POS + 6 * i] & 0x0F) << 8 | (s16) buf[FT_TOUCH_Y_L_POS + 6 * i];
        /* 按下,松开,触摸 */
        event->au8_touch_event[i] =
            buf[FT_TOUCH_EVENT_POS + 6 * i] >> 6;
        event->au8_finger_id[i] =
            (buf[FT_TOUCH_FINGER_POS + 6 * i]) >> 4;

        /**pressure and area not used !!*/
#if 0
        event->area[i] =
            (buf[FT_TOUCH_AREA_POS + 6 * i]) >> 4;
        event->pressure[i] =
            (s16) buf[FTS_TOUCH_PRE_POS + 6 * i];

        if (0 == event->area[i])
            event->area[i] = 0x09;

        if (0 == event->pressure[i])
            event->pressure[i] = 0x3f;
#endif
        if ((event->au8_touch_event[i]==0 || event->au8_touch_event[i]==2)&&(event->point_num==0))
        {
            printk("abnormal touch data from fw");
            return -1;
        }
    }
  1. 中断函数:
static irqreturn_t ftint_irq(int irq, void *data)
{
    int i;
    bool act;
    struct input_dev* input = ft_ts_dev;
    ts_event event;
    int ret = touch_event_handler(&event);
    if(ret)
        printk( "\n buffer_read failed \n");
    if(event.point_num != 0)
    {
        for(i = 0; i < event.touch_point; i++)
        {
            input_mt_slot(input, i);
            act = (event.au8_touch_event[i] == FT_EVENT_PRESS_DOWN || event.au8_touch_event[i] == FT_EVENT_CONTACT);
            input_mt_report_slot_state(input, MT_TOOL_FINGER, act);
            if (!act)
                continue;
            input_report_abs(input, ABS_MT_POSITION_X, event.au16_x[i]);
            input_report_abs(input, ABS_MT_POSITION_Y, event.au16_y[i]);
        }
    }
    input_mt_sync_frame(input);
    input_sync(input);
    return IRQ_HANDLED;
}
posted @ 2019-06-18 17:36  yooooooo  阅读(2781)  评论(0编辑  收藏  举报