This commit is contained in:
刘可亮
2024-09-03 11:16:08 +08:00
parent cf270df8d6
commit 803cac77d5
2931 changed files with 614364 additions and 31222 deletions

View File

@@ -0,0 +1,5 @@
menu "Touch Panel Support"
depends on AIC_USING_TOUCH
source "bsp/artinchip/drv_bare/touch/gt911/Kconfig"
endmenu

View File

@@ -0,0 +1,24 @@
menu "Gt911 touch panel options"
config AIC_TOUCH_GT911
bool "Using touch panel gt911"
default n
select AIC_I2C_DRV
config AIC_TOUCH_GT911_I2C_CHA
string "gt911 using i2c channel index"
default "i2c3"
depends on AIC_TOUCH_GT911
config AIC_TOUCH_GT911_RST_PIN
string "gt911 reset pin"
default "PA.8"
depends on AIC_TOUCH_GT911
config AIC_TOUCH_GT911_INT_PIN
string "gt911 irq pin"
default "PA.9"
depends on AIC_TOUCH_GT911
endmenu

View File

@@ -0,0 +1,388 @@
/*
* Copyright (c) 2024, Artinchip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "gt911.h"
#define TOUCH_NAME "gt911"
#define I2C_BASE(n) (I2C0_BASE + (n * 0x1000))
aic_i2c_ctrl g_i2c_dev;
static struct aic_i2c_msg g_msgs;
static uint8_t g_buf[40];
static int gt911_write_reg(aic_i2c_ctrl *i2c_dev)
{
uint32_t bytes_cnt = 0;
bytes_cnt = hal_i2c_master_send_msg(i2c_dev, i2c_dev->msg, 1);
if (bytes_cnt != i2c_dev->msg->len) {
printf("i2c write gt911 error\n");
return TOUCH_ERROR;
} else {
return TOUCH_OK;
}
}
static int gt911_read_reg(aic_i2c_ctrl *i2c_dev)
{
uint32_t bytes_cnt = 0;
bytes_cnt = hal_i2c_master_receive_msg(i2c_dev, i2c_dev->msg, 1);
if (bytes_cnt != i2c_dev->msg->len) {
printf("i2c read gt911 error\n");
return TOUCH_ERROR;
} else {
return TOUCH_OK;
}
}
static int gt911_get_id(aic_i2c_ctrl *i2c_dev, uint8_t *data)
{
uint8_t reg[2];
reg[0] = (uint8_t)(GT911_PRODUCT_ID >> 8);
reg[1] = (uint8_t)(GT911_PRODUCT_ID & 0xff);
memset(&g_msgs, 0, sizeof(g_msgs));
memset(&g_buf, 0, sizeof(g_buf));
g_msgs.buf = g_buf;
/* write operation */
g_msgs.buf[0] = reg[0];
g_msgs.buf[1] = reg[1];
g_msgs.len = 2;
g_msgs.addr = GT911_ADDRESS_HIGH;
i2c_dev->msg = &g_msgs;
gt911_write_reg(i2c_dev);
/* read operation */
memset(&g_buf, 0, sizeof(g_buf));
g_msgs.len = 6;
g_msgs.buf = data;
i2c_dev->msg = &g_msgs;
if (gt911_read_reg(i2c_dev)) {
printf("i2c read gt911 product id fail\n");
return TOUCH_ERROR;
}
return TOUCH_OK;
}
static int gt911_get_info(aic_i2c_ctrl *i2c_dev, struct touch_info *info)
{
uint8_t reg[2];
uint8_t out_info[7];
reg[0] = (uint8_t)(GT911_CONFIG_REG >> 8);
reg[1] = (uint8_t)(GT911_CONFIG_REG & 0xff);
memset(&g_msgs, 0, sizeof(g_msgs));
memset(&g_buf, 0, sizeof(g_buf));
g_msgs.buf = g_buf;
/* write operation */
g_msgs.buf[0] = reg[0];
g_msgs.buf[1] = reg[1];
g_msgs.len = 2;
g_msgs.addr = GT911_ADDRESS_HIGH;
i2c_dev->msg = &g_msgs;
gt911_write_reg(i2c_dev);
/* read operation */
memset(&g_buf, 0, sizeof(g_buf));
g_msgs.len = 7;
g_msgs.buf = out_info;
i2c_dev->msg = &g_msgs;
if (gt911_read_reg(i2c_dev)) {
printf("i2c read gt911 product id fail\n");
return TOUCH_ERROR;
}
info->range_x = (out_info[2] << 8) | out_info[1];
info->range_y = (out_info[4] << 8) | out_info[3];
info->point_num = out_info[5] & 0x0f;
return TOUCH_OK;
}
static int16_t pre_x[GT911_MAX_TOUCH] = { -1, -1, -1, -1, -1 };
static int16_t pre_y[GT911_MAX_TOUCH] = { -1, -1, -1, -1, -1 };
static int16_t pre_w[GT911_MAX_TOUCH] = { -1, -1, -1, -1, -1 };
static uint8_t s_tp_dowm[GT911_MAX_TOUCH];
static struct touch_data *read_data;
static void gt911_touch_up(void *buf, int8_t id)
{
read_data = (struct touch_data *)buf;
if (s_tp_dowm[id] == 1) {
s_tp_dowm[id] = 0;
read_data[id].event = TOUCH_EVENT_UP;
} else {
read_data[id].event = TOUCH_EVENT_NONE;
}
read_data[id].width = pre_w[id];
read_data[id].x_coordinate = pre_x[id];
read_data[id].y_coordinate = pre_y[id];
read_data[id].track_id = id;
pre_x[id] = -1; /* last point is none */
pre_y[id] = -1;
pre_w[id] = -1;
}
static void gt911_touch_down(void *buf, int8_t id, int16_t x, int16_t y,
int16_t w)
{
read_data = (struct touch_data *)buf;
if (s_tp_dowm[id] == 1) {
read_data[id].event = TOUCH_EVENT_MOVE;
} else {
read_data[id].event = TOUCH_EVENT_DOWN;
s_tp_dowm[id] = 1;
}
read_data[id].width = w;
read_data[id].x_coordinate = x;
read_data[id].y_coordinate = y;
read_data[id].track_id = id;
pre_x[id] = x; /* save last point */
pre_y[id] = y;
pre_w[id] = w;
}
static int gt911_read_point(struct touch *touch, void *buf,
unsigned int read_num)
{
uint8_t point_status = 0;
uint8_t touch_num = 0;
uint8_t write_buf[3];
uint8_t reg[2];
uint8_t read_buf[8 * GT911_MAX_TOUCH] = { 0 };
uint8_t read_index;
int8_t read_id = 0;
int16_t input_x = 0;
int16_t input_y = 0;
int16_t input_w = 0;
static uint8_t pre_touch = 0;
static int8_t pre_id[GT911_MAX_TOUCH] = { 0 };
memset(buf, 0, sizeof(struct touch_data) * read_num);
memset(&g_msgs, 0, sizeof(g_msgs));
memset(&g_buf, 0, sizeof(g_buf));
g_msgs.buf = g_buf;
/* point status register */
reg[0] = (uint8_t)((GT911_READ_STATUS >> 8) & 0xFF);
reg[1] = (uint8_t)(GT911_READ_STATUS & 0xFF);
g_msgs.buf[0] = reg[0];
g_msgs.buf[1] = reg[1];
g_msgs.len = 2;
g_msgs.addr = GT911_ADDRESS_HIGH;
g_i2c_dev.msg = &g_msgs;
gt911_write_reg(&g_i2c_dev);
/* read operation */
memset(&g_buf, 0, sizeof(g_buf));
g_msgs.len = 1;
g_msgs.buf = &point_status;
g_i2c_dev.msg = &g_msgs;
if (gt911_read_reg(&g_i2c_dev)) {
printf("read point failed\n");
read_num = 0;
goto exit_;
}
if (point_status == 0) { /* no data */
read_num = 0;
goto exit_;
}
if ((point_status & 0x80) == 0) { /* data is not ready */
read_num = 0;
goto exit_;
}
touch_num = point_status & 0x0f; /* get point num */
if (touch_num > GT911_MAX_TOUCH) /* point num is not correct */
{
read_num = 0;
goto exit_;
}
reg[0] = (uint8_t)((GT911_POINT1_REG >> 8) & 0xFF);
reg[1] = (uint8_t)(GT911_POINT1_REG & 0xFF);
memset(&g_buf, 0, sizeof(g_buf));
g_msgs.buf[0] = reg[0];
g_msgs.buf[1] = reg[1];
g_msgs.len = 2;
g_msgs.addr = GT911_ADDRESS_HIGH;
g_i2c_dev.msg = &g_msgs;
gt911_write_reg(&g_i2c_dev);
memset(&g_buf, 0, sizeof(g_buf));
g_msgs.len = 40;
g_msgs.buf = read_buf;
g_i2c_dev.msg = &g_msgs;
/* read point num is touch_num */
if (gt911_read_reg(&g_i2c_dev)) {
printf("read point failed\n");
read_num = 0;
goto exit_;
}
if (pre_touch > touch_num) /* point up */
{
for (read_index = 0; read_index < pre_touch; read_index++) {
uint8_t j;
for (j = 0; j < touch_num; j++) /* this time touch num */
{
read_id = read_buf[j * 8] & 0x0F;
if (pre_id[read_index] == read_id) /* this id is not free */
break;
if (j >= touch_num - 1) {
uint8_t up_id;
up_id = pre_id[read_index];
gt911_touch_up(buf, up_id);
}
}
}
}
if (touch_num) /* point down */
{
uint8_t off_set;
for (read_index = 0; read_index < touch_num; read_index++) {
off_set = read_index * 8;
read_id = read_buf[off_set] & 0x0f;
pre_id[read_index] = read_id;
input_x =
read_buf[off_set + 1] | (read_buf[off_set + 2] << 8); /* x */
input_y =
read_buf[off_set + 3] | (read_buf[off_set + 4] << 8); /* y */
input_w =
read_buf[off_set + 5] | (read_buf[off_set + 6] << 8); /* size */
gt911_touch_down(buf, read_id, input_x, input_y, input_w);
}
} else if (pre_touch) {
for (read_index = 0; read_index < pre_touch; read_index++) {
gt911_touch_up(buf, pre_id[read_index]);
}
}
pre_touch = touch_num;
exit_:
write_buf[0] = (uint8_t)((GT911_READ_STATUS >> 8) & 0xFF);
write_buf[1] = (uint8_t)(GT911_READ_STATUS & 0xFF);
write_buf[2] = 0x00;
memset(&g_buf, 0, sizeof(g_buf));
g_msgs.buf[0] = write_buf[0];
g_msgs.buf[1] = write_buf[1];
g_msgs.buf[2] = write_buf[2];
g_msgs.len = 3;
g_msgs.addr = GT911_ADDRESS_HIGH;
g_i2c_dev.msg = &g_msgs;
gt911_write_reg(&g_i2c_dev);
return read_num;
}
static int gt911_control(struct touch *touch, int cmd, void *arg)
{
if (cmd == TOUCH_CTRL_GET_ID) {
return gt911_get_id(&g_i2c_dev, arg);
}
if (cmd == TOUCH_CTRL_GET_INFO) {
return gt911_get_info(&g_i2c_dev, arg);
}
return TOUCH_OK;
}
static struct touch_ops gt911_ops = {
.control = gt911_control,
.readpoint = gt911_read_point,
};
int gt911_init(struct touch *touch)
{
int id, ret;
long rst_pin,irq_pin;
memset(&g_msgs, 0, sizeof(g_msgs));
memset(&g_buf, 0, sizeof(g_buf));
ret = strcmp(touch->name, TOUCH_NAME);
if (ret) {
ret = TOUCH_ERROR;
printf("can not find %s\n", touch->name);
return TOUCH_ERROR;
}
id = touch_get_i2c_chan_id(GT911_I2C_CHAN);
g_msgs.buf = g_buf;
g_i2c_dev.index = id;
g_i2c_dev.reg_base = I2C_BASE(id);
g_i2c_dev.msg = &g_msgs;
g_i2c_dev.addr_bit = I2C_7BIT_ADDR;
g_i2c_dev.speed_mode = I2C_400K_SPEED;
g_i2c_dev.bus_mode = I2C_MASTER_MODE;
hal_i2c_init(&g_i2c_dev);
rst_pin = touch_pin_get(GT911_RST_PIN);
irq_pin = touch_pin_get(GT911_INT_PIN);
/* hw init */
touch_set_pin_mode(rst_pin, PIN_OUTPUT_MODE);
touch_pin_write(rst_pin, LOW_POWER);
aicos_mdelay(10);
touch_set_pin_mode(irq_pin, PIN_OUTPUT_MODE);
touch_pin_write(irq_pin, LOW_POWER);
aicos_mdelay(10);
touch_pin_write(rst_pin, HIGH_POWER);
aicos_mdelay(10);
touch_set_pin_mode(rst_pin, PIN_INPUT_MODE);
touch_pin_write(irq_pin, LOW_POWER);
aicos_mdelay(50);
touch_set_pin_mode(irq_pin, PIN_INPUT_MODE);
touch->info.type = TOUCH_TYPE_CAPACITANCE;
touch->info.type = TOUCH_VENDOR_GT;
touch->ops = &gt911_ops;
touch_register(touch);
return ret;
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2024, Artinchip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __GT911_H__
#define __GT911_H__
#include <aic_core.h>
#include "../touch.h"
#include "hal_i2c.h"
#define GT911_ADDR_LEN 2
#define GT911_REGITER_LEN 2
#define GT911_MAX_TOUCH 5
#define GT911_POINT_INFO_NUM 5
#define GT911_ADDRESS_HIGH 0x5D
#define GT911_ADDRESS_LOW 0x14
#define GT911_COMMAND_REG 0x8040
#define GT911_CONFIG_REG 0x8047
#define GT911_MOD_SWT_REG 0x804D
#define GT911_PRODUCT_ID 0x8140
#define GT911_VENDOR_ID 0x814A
#define GT911_READ_STATUS 0x814E
#define GT911_POINT1_REG 0x814F
#define GT911_POINT2_REG 0x8157
#define GT911_POINT3_REG 0x815F
#define GT911_POINT4_REG 0x8167
#define GT911_POINT5_REG 0x816F
#define GT911_CHECK_SUM 0x80FF
#define GT911_I2C_CHAN AIC_TOUCH_GT911_I2C_CHA
#define GT911_RST_PIN AIC_TOUCH_GT911_RST_PIN
#define GT911_INT_PIN AIC_TOUCH_GT911_INT_PIN
int gt911_init(struct touch *touch);
#endif /* gt911.h */

View File

@@ -0,0 +1,116 @@
/*
* Copyright (c) 2024, Artinchip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "touch.h"
struct touch *register_touch = NULL;
int touch_control(struct touch *touch, int cmd, void *arg)
{
CHECK_PARAM(touch, -1);
if (touch->ops->control)
return touch->ops->control(touch, cmd , arg);
return TOUCH_OK;
}
int touch_readpoint(struct touch *touch, void *buf, unsigned int len)
{
CHECK_PARAM(touch, -1);
if (touch->ops->readpoint)
return touch->ops->readpoint(touch, buf, len);
return TOUCH_OK;
}
int touch_get_i2c_chan_id(const char *name)
{
uint8_t name_len;
int chan_id = -1;
name_len = strlen(name);
if (name_len != 4)
return TOUCH_ERROR;
if ((name[0] != 'i') || (name[1] != '2') || (name[2] != 'c'))
return TOUCH_ERROR;
chan_id = (int)(name[3] - '0');
return chan_id;
}
long touch_pin_get(const char *name)
{
return hal_gpio_name2pin(name);
}
void touch_set_pin_mode(long pin, long mode)
{
unsigned int g = GPIO_GROUP(pin);
unsigned int p = GPIO_GROUP_PIN(pin);
hal_gpio_set_func(g, p, 1);
switch (mode)
{
case PIN_INPUT_MODE:
hal_gpio_set_bias_pull(g, p, PIN_PULL_DIS);
hal_gpio_direction_input(g, p);
break;
case PIN_INPUT_PULLUP_MODE:
hal_gpio_set_bias_pull(g, p, PIN_PULL_UP);
hal_gpio_direction_input(g, p);
break;
case PIN_INPUT_PULLDOWN_MODE:
hal_gpio_set_bias_pull(g, p, PIN_PULL_DOWN);
hal_gpio_direction_input(g, p);
break;
case PIN_OUTPUT_MODE:
case PIN_OUTPUT_OD_MODE:
default:
hal_gpio_set_bias_pull(g, p, PIN_PULL_DIS);
hal_gpio_direction_output(g, p);
break;
}
}
void touch_pin_write(long pin, long value)
{
int ret;
unsigned int g = GPIO_GROUP(pin);
unsigned int p = GPIO_GROUP_PIN(pin);
if (LOW_POWER == value)
{
hal_gpio_clr_output(g, p);
}
else
{
hal_gpio_set_output(g, p);
ret = hal_gpio_get_pincfg(g, p, GPIO_CHECK_PIN_GEN_OE);
if (ret < 0) {
pr_err("Set the output pin failed\n");
} else {
pr_debug("Set the output pin successfully\n");
}
}
}
void touch_register(struct touch *touch)
{
CHECK_PARAM_RET(touch);
register_touch = touch;
}
void touch_unregister(void)
{
register_touch = NULL;
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (c) 2024, Artinchip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __TOUCH_H__
#define __TOUCH_H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <aic_core.h>
#include <aic_hal.h>
#define TOUCH_OK 0
#define TOUCH_ERROR -1
#define PIN_OUTPUT_MODE 0x00
#define PIN_INPUT_MODE 0x01
#define PIN_INPUT_PULLUP_MODE 0x02
#define PIN_INPUT_PULLDOWN_MODE 0x03
#define PIN_OUTPUT_OD_MODE 0x04
#define IRQ_PIN_MODE_RISING 0x00
#define IRQ_PIN_MODE_FALLING 0x01
#define IRQ_PIN_MODE_RISING_FALLING 0x02
#define IRQ_PIN_MODE_HIGH_LEVEL 0x03
#define IRQ_PIN_MODE_LOW_LEVEL 0x04
#define IRQ_PIN_DISABLE 0x0
#define IRQ_PIN_ENABLE 0x1
#define IRQ_PIN_NONE -1
#define TOUCH_EVENT_NONE (0) /* Touch none */
#define TOUCH_EVENT_UP (1) /* Touch up event */
#define TOUCH_EVENT_DOWN (2) /* Touch down event */
#define TOUCH_EVENT_MOVE (3) /* Touch move event */
/* Touch control cmd types */
#define TOUCH_CTRL_GET_ID 0
#define TOUCH_CTRL_GET_INFO 1
#define LOW_POWER 0x00
#define HIGH_POWER 0x01
/* Touch ic type */
#define TOUCH_TYPE_NODE 0
#define TOUCH_TYPE_CAPACITANCE 1
#define TOUCH_TYPE_RESISTANCE 2
/* Touch vendor types */
#define TOUCH_VENDOR_UNKNOWN 0
#define TOUCH_VENDOR_GT 1
#define TOUCH_VENDOR_FT 2
#define TOUCH_VENDOR_ST 3
#define TOUCH_VENDOR_CST 4
struct touch_info {
uint8_t type;
uint8_t vendor;
uint8_t point_num;
uint8_t range_x;
uint8_t range_y;
};
struct touch {
char *name;
struct touch_ops *ops;
struct touch_info info;
};
struct touch_data {
uint8_t event; /* The touch event of the data */
uint8_t track_id; /* Track id of point */
uint8_t width; /* Point of width */
uint16_t x_coordinate; /* Point of x coordinate */
uint16_t y_coordinate; /* Point of y coordinate */
};
struct touch_ops {
int (*control)(struct touch *touch, int cmd, void *arg);
int (*readpoint)(struct touch *touch, void *buf, unsigned int len);
};
int touch_control(struct touch *touch, int cmd, void *arg);
int touch_readpoint(struct touch *touch, void *buf, unsigned int len);
int touch_get_i2c_chan_id(const char *name);
long touch_pin_get(const char *name);
void touch_set_pin_mode(long pin, long mode);
void touch_pin_write(long pin, long value);
void touch_register(struct touch *touch);
void touch_unregister(void);
#endif