| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578 |
- #include <stdio.h>
- #include <math.h>
- #include <stdlib.h>
- #include "FreeRTOS.h"
- #include "chip.h"
- #include "board.h"
- #ifdef TP_USE_GT9XX
- #include <xm_base.h>
- #include <xm_event.h>
- #define GOODIX_GPIO_INT_NAME "irq"
- #define GOODIX_GPIO_RST_NAME "reset"
- #define GOODIX_MAX_HEIGHT 4096
- #define GOODIX_MAX_WIDTH 4096
- #define GOODIX_INT_TRIGGER 1
- #define GOODIX_CONTACT_SIZE 8
- #define GOODIX_MAX_CONTACTS 10
- #define GOODIX_CONFIG_MAX_LENGTH 240
- #define GOODIX_CONFIG_911_LENGTH 186
- #define GOODIX_CONFIG_967_LENGTH 228
- /* Register defines */
- #define GOODIX_REG_COMMAND 0x8040
- #define GOODIX_CMD_SCREEN_OFF 0x05
- #define GOODIX_READ_COOR_ADDR 0x814E
- #define GOODIX_GT1X_REG_CONFIG_DATA 0x8050
- #define GOODIX_GT9X_REG_CONFIG_DATA 0x8047
- #define GOODIX_REG_ID 0x8140
- #define GOODIX_BUFFER_STATUS_READY BIT(7)
- #define GOODIX_BUFFER_STATUS_TIMEOUT 20
- #define RESOLUTION_LOC 1
- #define MAX_CONTACTS_LOC 5
- #define TRIGGER_LOC 6
- #define GT9XX_SLAVE_ADDR 0x5d
- #define GT9XX_GPIO_INT TP_GPIO_INT
- #define GT9XX_GPIO_RST TP_GPIO_RST
- #define GT9XX_INVERTED_X TP_INV_X
- #define GT9XX_INVERTED_Y TP_INV_Y
- #define GT9XX_MT_TOUCH TP_MT_TOUCH//支持多点触摸
- struct goodix_ts_data;
- struct goodix_chip_data {
- u16 config_addr;
- int config_len;
- };
- struct goodix_ts_data {
- struct i2c_adapter *adap;
- const struct goodix_chip_data *chip;
- unsigned int max_touch_num;
- unsigned int x_max;
- unsigned int y_max;
- unsigned int int_trigger_type;
- int gpio_int;
- int gpio_rst;
- u16 id;
- u16 version;
- const char cfg_name[32];
- unsigned long irq_flags;
- TaskHandle_t irq_task;
- };
- static const struct goodix_chip_data gt1x_chip_data = {
- .config_addr = GOODIX_GT1X_REG_CONFIG_DATA,
- .config_len = GOODIX_CONFIG_MAX_LENGTH,
- };
- static const struct goodix_chip_data gt911_chip_data = {
- .config_addr = GOODIX_GT9X_REG_CONFIG_DATA,
- .config_len = GOODIX_CONFIG_911_LENGTH,
- };
- static const struct goodix_chip_data gt967_chip_data = {
- .config_addr = GOODIX_GT9X_REG_CONFIG_DATA,
- .config_len = GOODIX_CONFIG_967_LENGTH,
- };
- static const struct goodix_chip_data gt9x_chip_data = {
- .config_addr = GOODIX_GT9X_REG_CONFIG_DATA,
- .config_len = GOODIX_CONFIG_MAX_LENGTH,
- };
- static const unsigned long goodix_irq_flags[] = {
- IRQ_TYPE_EDGE_RISING,
- IRQ_TYPE_EDGE_FALLING,
- IRQ_TYPE_LEVEL_LOW,
- IRQ_TYPE_LEVEL_HIGH,
- };
- static int last_input_x, last_input_y;
- static inline int get_unaligned_le16(void *p)
- {
- u8 *tmp = (u8*)p;
- return (tmp[1] << 8) | tmp[0];
- }
- /**
- * goodix_i2c_read - read data from a register of the i2c slave device.
- *
- * @adap: i2c device.
- * @reg: the register to read from.
- * @buf: raw write data buffer.
- * @len: length of the buffer to write
- */
- static int goodix_i2c_read(struct i2c_adapter *adap,
- u16 reg, u8 *buf, int len)
- {
- struct i2c_msg msgs[2];
- u8 wbuf[2];
- int ret;
- wbuf[0] = reg >> 8;
- wbuf[1] = reg & 0xFF;
- msgs[0].flags = 0;
- msgs[0].addr = GT9XX_SLAVE_ADDR;
- msgs[0].len = 2;
- msgs[0].buf = (u8 *)&wbuf;
- msgs[1].flags = I2C_M_RD;
- msgs[1].addr = GT9XX_SLAVE_ADDR;
- msgs[1].len = len;
- msgs[1].buf = buf;
- ret = i2c_transfer(adap, msgs, 2);
- return ret < 0 ? ret : (ret != ARRAY_SIZE(msgs) ? -EIO : 0);
- }
- /**
- * goodix_i2c_write - write data to a register of the i2c slave device.
- *
- * @adap: i2c device.
- * @reg: the register to write to.
- * @buf: raw data buffer to write.
- * @len: length of the buffer to write
- */
- static int goodix_i2c_write(struct i2c_adapter *adap, u16 reg, const u8 *buf,
- unsigned len)
- {
- u8 *addr_buf;
- struct i2c_msg msg;
- int ret;
- addr_buf = pvPortMalloc(len + 2);
- if (!addr_buf)
- return -ENOMEM;
- addr_buf[0] = reg >> 8;
- addr_buf[1] = reg & 0xFF;
- memcpy(&addr_buf[2], buf, len);
- msg.flags = 0;
- msg.addr = GT9XX_SLAVE_ADDR;
- msg.buf = addr_buf;
- msg.len = len + 2;
- ret = i2c_transfer(adap, &msg, 1);
- vPortFree(addr_buf);
- return ret < 0 ? ret : (ret != 1 ? -EIO : 0);
- }
- static int goodix_i2c_write_u8(struct i2c_adapter *adap, u16 reg, u8 value)
- {
- return goodix_i2c_write(adap, reg, &value, sizeof(value));
- }
- static const struct goodix_chip_data *goodix_get_chip_data(u16 id)
- {
- switch (id) {
- case 1151:
- return >1x_chip_data;
- case 911:
- case 9271:
- case 9110:
- case 927:
- case 928:
- return >911_chip_data;
- case 912:
- case 967:
- return >967_chip_data;
- default:
- return >9x_chip_data;
- }
- }
- static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data)
- {
- unsigned long max_timeout;
- int touch_num;
- int error;
- /*
- * The 'buffer status' bit, which indicates that the data is valid, is
- * not set as soon as the interrupt is raised, but slightly after.
- * This takes around 10 ms to happen, so we poll for 20 ms.
- */
- max_timeout = xTaskGetTickCount() + pdMS_TO_TICKS(GOODIX_BUFFER_STATUS_TIMEOUT);
- do {
- error = goodix_i2c_read(ts->adap, GOODIX_READ_COOR_ADDR,
- data, GOODIX_CONTACT_SIZE + 1);
- if (error) {
- TRACE_ERROR("I2C transfer error: %d\n", error);
- return error;
- }
- if (data[0] & GOODIX_BUFFER_STATUS_READY) {
- touch_num = data[0] & 0x0f;
- if (touch_num > ts->max_touch_num)
- return -EPROTO;
- #if GT9XX_MT_TOUCH
- if (touch_num > 1) {
- data += 1 + GOODIX_CONTACT_SIZE;
- error = goodix_i2c_read(ts->adap,
- GOODIX_READ_COOR_ADDR +
- 1 + GOODIX_CONTACT_SIZE,
- data,
- GOODIX_CONTACT_SIZE *
- (touch_num - 1));
- if (error)
- return error;
- }
- return touch_num;
- #else
- return touch_num > 0 ? 1 : 0;
- #endif
- }
- vTaskDelay(pdMS_TO_TICKS(1)); /* Poll every 1 - 2 ms */
- } while (xTaskGetTickCount() < max_timeout);
- /*
- * The Goodix panel will send spurious interrupts after a
- * 'finger up' event, which will always cause a timeout.
- */
- return 0;
- }
- static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data)
- {
- //int id = coor_data[0] & 0x0F;
- int input_x = get_unaligned_le16(&coor_data[1]);
- int input_y = get_unaligned_le16(&coor_data[3]);
- int input_w = get_unaligned_le16(&coor_data[5]);
- /* printf("id=0x%x, input_x=%d, input_y=%d, input_w=%d.\n", id, input_x,
- input_y, input_w); */
- #if GT9XX_INVERTED_X
- input_x = ts->x_max - input_x;
- #endif
- #if GT9XX_INVERTED_Y
- input_y = ts->y_max - input_y;
- #endif
- //send press event
- XM_TpEventProc (XM_EVENT_TOUCHDOWN, input_x, input_y, 0);
- last_input_x = input_x;
- last_input_y = input_y;
- }
- /**
- * goodix_process_events - Process incoming events
- *
- * @ts: our goodix_ts_data pointer
- *
- * Called when the IRQ is triggered. Read the current device state, and push
- * the input events to the user space.
- */
- static void goodix_process_events(struct goodix_ts_data *ts)
- {
- u8 point_data[1 + GOODIX_CONTACT_SIZE * GOODIX_MAX_CONTACTS];
- int touch_num;
- int i;
- touch_num = goodix_ts_read_input_report(ts, point_data);
- if (touch_num < 0)
- return;
- /*
- * Bit 4 of the first byte reports the status of the capacitive
- * Windows/Home button.
- */
- //input_report_key(ts->input_dev, KEY_LEFTMETA, point_data[0] & BIT(4));
- for (i = 0; i < touch_num; i++)
- goodix_ts_report_touch(ts,
- &point_data[1 + GOODIX_CONTACT_SIZE * i]);
- if (touch_num == 0) {
- //send release event
- XM_TpEventProc (XM_EVENT_TOUCHUP, last_input_x, last_input_y, 0);
- }
- /* input_mt_sync_frame(ts->input_dev);
- input_sync(ts->input_dev); */
- }
- static void goodix_ts_irq_task(void *param)
- {
- uint32_t ulNotifiedValue;
- struct goodix_ts_data *ts;
- for (;;) {
- xTaskNotifyWait( 0x00, /* Don't clear any notification bits on entry. */
- 0xffffffff, /* Reset the notification value to 0 on exit. */
- &ulNotifiedValue, /* Notified value pass out in ulNotifiedValue. */
- portMAX_DELAY);
- ts = (struct goodix_ts_data *)ulNotifiedValue;
- goodix_process_events(ts);
- if (goodix_i2c_write_u8(ts->adap, GOODIX_READ_COOR_ADDR, 0) < 0)
- TRACE_ERROR("I2C write end_cmd error\n");
- }
- }
- /**
- * goodix_ts_irq_handler - The IRQ handler
- *
- * @param: private data pointer.
- */
- static void goodix_ts_irq_handler(void *param)
- {
- struct goodix_ts_data *ts = param;
- xTaskNotifyFromISR(ts->irq_task, (uint32_t)ts, eSetValueWithOverwrite, 0);
- return;
- }
- static int goodix_request_irq(struct goodix_ts_data *ts)
- {
- if (xTaskCreate(goodix_ts_irq_task, "gt9xx", 1024, ts,
- 10, &ts->irq_task) != pdPASS) {
- printf("create gt9xx irq task fail.\n");
- }
- return gpio_irq_request(ts->gpio_int, ts->irq_flags, goodix_ts_irq_handler, ts);
- }
- static int goodix_int_sync(struct goodix_ts_data *ts)
- {
- gpio_direction_output(ts->gpio_int, 0);
- vTaskDelay(pdMS_TO_TICKS(50)); /* T5: 50ms */
- gpio_direction_input(ts->gpio_int);
- return 0;
- }
- /**
- * goodix_reset - Reset device during power on
- *
- * @ts: goodix_ts_data pointer
- */
- static int goodix_reset(struct goodix_ts_data *ts)
- {
- int error;
- /* begin select I2C slave addr */
- gpio_direction_output(ts->gpio_rst, 0);
- vTaskDelay(pdMS_TO_TICKS(20)); /* T2: > 10ms */
- /* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */
- gpio_direction_output(ts->gpio_int, GT9XX_SLAVE_ADDR == 0x14);
- vTaskDelay(pdMS_TO_TICKS(1)); /* T3: > 100us */
- gpio_direction_output(ts->gpio_rst, 1);
- vTaskDelay(pdMS_TO_TICKS(6)); /* T4: > 5ms */
- /* end select I2C slave addr */
- gpio_direction_input(ts->gpio_rst);
- error = goodix_int_sync(ts);
- if (error)
- return error;
- return 0;
- }
- /**
- * goodix_read_config - Read the embedded configuration of the panel
- *
- * @ts: our goodix_ts_data pointer
- *
- * Must be called during probe
- */
- static void goodix_read_config(struct goodix_ts_data *ts)
- {
- u8 config[GOODIX_CONFIG_MAX_LENGTH];
- int error;
- error = goodix_i2c_read(ts->adap, ts->chip->config_addr,
- config, ts->chip->config_len);
- if (error) {
- TRACE_WARNING("Error reading config: %d\n", error);
- ts->int_trigger_type = GOODIX_INT_TRIGGER;
- ts->max_touch_num = GOODIX_MAX_CONTACTS;
- return;
- }
- ts->int_trigger_type = config[TRIGGER_LOC] & 0x03;
- ts->max_touch_num = config[MAX_CONTACTS_LOC] & 0x0f;
- ts->x_max = get_unaligned_le16(&config[RESOLUTION_LOC]);
- ts->y_max = get_unaligned_le16(&config[RESOLUTION_LOC + 2]);
- }
- /**
- * goodix_read_version - Read goodix touchscreen version
- *
- * @ts: our goodix_ts_data pointer
- */
- static int goodix_read_version(struct goodix_ts_data *ts)
- {
- int error;
- u8 buf[6];
- char id_str[5];
- error = goodix_i2c_read(ts->adap, GOODIX_REG_ID, buf, sizeof(buf));
- if (error) {
- TRACE_ERROR("read version failed: %d\n", error);
- return error;
- }
- memcpy(id_str, buf, 4);
- id_str[4] = 0;
- char *ptr;
- ts->id = strtoul(id_str, &ptr, 10);
- if (ts->id == 0xffff)
- ts->id = 0x1001;
- ts->version = get_unaligned_le16(&buf[4]);
- TRACE_INFO("ID %d, version: %04x\n", ts->id, ts->version);
- return 0;
- }
- /**
- * goodix_i2c_test - I2C test function to check if the device answers.
- *
- * @adap: the i2c adapter
- */
- static int goodix_i2c_test(struct i2c_adapter *adap)
- {
- int retry = 0;
- int error;
- u8 test;
- while (retry++ < 2) {
- error = goodix_i2c_read(adap, GOODIX_REG_ID,
- &test, 1);
- if (!error)
- return 0;
- TRACE_ERROR("i2c test failed attempt %d: %d\n",
- retry, error);
- vTaskDelay(pdMS_TO_TICKS(20));
- }
- return error;
- }
- /**
- * goodix_configure_dev - Finish device initialization
- *
- * @ts: our goodix_ts_data pointer
- *
- * Must be called from probe to finish initialization of the device.
- * Contains the common initialization code for both devices that
- * declare gpio pins and devices that do not. It is either called
- * directly from probe or from request_firmware_wait callback.
- */
- static int goodix_configure_dev(struct goodix_ts_data *ts)
- {
- int error;
- ts->int_trigger_type = GOODIX_INT_TRIGGER;
- ts->max_touch_num = GOODIX_MAX_CONTACTS;
- /* Read configuration and apply touchscreen parameters */
- goodix_read_config(ts);
- ts->irq_flags = goodix_irq_flags[ts->int_trigger_type];
- error = goodix_request_irq(ts);
- if (error) {
- TRACE_ERROR("request IRQ failed: %d\n", error);
- return error;
- }
- return 0;
- }
- int goodix_ts_probe(struct i2c_adapter *adap)
- {
- struct goodix_ts_data *ts;
- int error;
- TRACE_DEBUG("I2C Address: 0x%02x\n", GT9XX_SLAVE_ADDR);
- ts = pvPortMalloc(sizeof(*ts));
- if (!ts)
- return -ENOMEM;
- memset(ts, 0, sizeof(*ts));
- ts->adap = adap;
- ts->gpio_int = GT9XX_GPIO_INT;
- ts->gpio_rst = GT9XX_GPIO_RST;
- if (ts->gpio_int && ts->gpio_rst) {
- /* reset the controller */
- error = goodix_reset(ts);
- if (error) {
- TRACE_ERROR("Controller reset failed.\n");
- return error;
- }
- }
- error = goodix_i2c_test(adap);
- if (error) {
- TRACE_ERROR("I2C communication failure: %d\n", error);
- return error;
- }
- error = goodix_read_version(ts);
- if (error) {
- TRACE_ERROR("Read version failed.\n");
- return error;
- }
- ts->chip = goodix_get_chip_data(ts->id);
- error = goodix_configure_dev(ts);
- if (error)
- return error;
- return 0;
- }
- int goodix_init(void)
- {
- struct i2c_adapter *adap = NULL;
- if (!(adap = i2c_open("i2c0"))) {
- printf("open i2c0 fail.\n");
- return -1;
- }
- goodix_ts_probe(adap);
- return 0;
- }
- #endif
|