Support both hardware and software calibration on the Zinitix touchscreens. This is lifted from the vendor driver but rewritten to use the chip revision number in the hardware instead of compile-time defines. Use defines for the new "calibration mode" and add a new define for the default touchpoint mode. The registers for reading the EEPROM status actually differs between BT5x2 and BT4x3+ so create very unique defines for those registers and use a register variable in the state to keep track of the right one to use. Signed-off-by: Linus Walleij <linus.walleij@xxxxxxxxxx> --- drivers/input/touchscreen/zinitix.c | 138 ++++++++++++++++++++++++++-- 1 file changed, 132 insertions(+), 6 deletions(-) diff --git a/drivers/input/touchscreen/zinitix.c b/drivers/input/touchscreen/zinitix.c index ea807b972f26..440ffc7c9b32 100644 --- a/drivers/input/touchscreen/zinitix.c +++ b/drivers/input/touchscreen/zinitix.c @@ -34,6 +34,8 @@ #define ZINITIX_DEBUG_REG 0x0115 /* 0~7 */ #define ZINITIX_TOUCH_MODE 0x0010 +#define ZINITIX_MODE_TOUCH_POINT 0x02 +#define ZINITIX_MODE_CALIBRATION 0x07 #define ZINITIX_CHIP_REVISION 0x0011 #define ZINITIX_CHIP_BT404 0x4040 #define ZINITIX_CHIP_BT532 0x5320 @@ -49,7 +51,11 @@ #define ZINITIX_DATA_VERSION_REG 0x0013 #define ZINITIX_SUPPORTED_FINGER_NUM 0x0015 -#define ZINITIX_EEPROM_INFO 0x0018 + +#define BT4X2_EEPROM_INFO 0x0014 +#define BT4X3_EEPROM_INFO 0x0018 +#define ZINITIX_EEPROM_HW_CALIB BIT(0) + #define ZINITIX_INITIAL_TOUCH_MODE 0x0019 #define ZINITIX_TOTAL_NUMBER_OF_X 0x0060 @@ -57,6 +63,8 @@ #define ZINITIX_DELAY_RAW_FOR_HOST 0x007f +#define BT4X2_EEPROM_INFO_REG 0x00aa + #define ZINITIX_BUTTON_SUPPORTED_NUM 0x00B0 #define ZINITIX_BUTTON_SENSITIVITY 0x00B2 #define ZINITIX_DUMMY_BUTTON_SENSITIVITY 0X00C8 @@ -75,8 +83,6 @@ #define ZINITIX_RAWDATA_REG 0x0200 -#define ZINITIX_EEPROM_INFO_REG 0x0018 - #define ZINITIX_INT_ENABLE_FLAG 0x00f0 #define ZINITIX_PERIODICAL_INTERRUPT_INTERVAL 0x00f1 @@ -120,7 +126,6 @@ #define SUB_BIT_UPDATE BIT(4) #define SUB_BIT_WAIT BIT(5) -#define DEFAULT_TOUCH_POINT_MODE 2 #define MAX_SUPPORTED_FINGER_NUM 5 #define CHIP_ON_DELAY 15 // ms @@ -153,8 +158,33 @@ struct bt541_ts_data { u16 chip_revision; u16 firmware_version; u16 regdata_version; + u16 eeprom_info_reg; }; +static bool zinitix_is_4x2(struct bt541_ts_data *bt541) +{ + u16 ver; + + /* The revision is the high nybbles so shift down */ + ver = bt541->chip_revision >> 4; + /* Skip middle digit */ + ver &= 0xf0f; + + return (ver == 0x402); +} + +static bool zinitix_is_4x3_and_above(struct bt541_ts_data *bt541) +{ + u16 ver; + + /* The revision is the high nybbles so shift down */ + ver = bt541->chip_revision >> 4; + /* Skip middle digit */ + ver &= 0xf0f; + + return (ver >= 0x403); +} + static int zinitix_read_data(struct i2c_client *client, u16 reg, void *values, size_t length) { @@ -209,12 +239,92 @@ static u16 zinitix_get_u16_reg(struct bt541_ts_data *bt541, u16 vreg) return le16_to_cpu(val); } +static int zinitix_calibrate(struct bt541_ts_data *bt541) +{ + struct i2c_client *client = bt541->client; + int maxsec = 10; + int error; + u16 val; + + dev_info(bt541->dev, "HW calibration - calibrating\n"); + + error = zinitix_write_u16(client, ZINITIX_TOUCH_MODE, + ZINITIX_MODE_CALIBRATION); + if (error) + return error; + error = zinitix_write_cmd(client, ZINITIX_CALIBRATE_CMD); + if (error) + return error; + error = zinitix_write_cmd(client, ZINITIX_SWRESET_CMD); + if (error) + return error; + msleep(1); + error = zinitix_write_cmd(client, ZINITIX_CLEAR_INT_STATUS_CMD); + if (error) + return error; + + /* Wait for hardware calibration to commence */ + do { + msleep(1000); + val = zinitix_get_u16_reg(bt541, bt541->eeprom_info_reg); + maxsec --; + } while ((val & ZINITIX_EEPROM_HW_CALIB) && maxsec); + + if (!maxsec) { + dev_err(bt541->dev, "timeout waiting for HW calibration\n"); + return -ETIMEDOUT; + } + + /* Get out of calibration mode */ + error = zinitix_write_u16(client, ZINITIX_TOUCH_MODE, + bt541->zinitix_mode); + if (error) + return error; + + error = zinitix_write_u16(client, ZINITIX_INT_ENABLE_FLAG, 0x0); + if (error) + return error; + + msleep(10); + + error = zinitix_write_cmd(client, ZINITIX_SWRESET_CMD); + if (error) + return error; + + if (zinitix_is_4x3_and_above(bt541)) { + error = zinitix_write_cmd(client, ZINITIX_SAVE_CALIBRATION_CMD); + if (error) + return error; + msleep(500); + } + + if (zinitix_is_4x2(bt541)) { + error = zinitix_write_cmd(client, ZINITIX_SAVE_STATUS_CMD); + if (error) + return error; + /* Wait for fusing EEPROM */ + msleep(1000); + error = zinitix_write_cmd(client, ZINITIX_SWRESET_CMD); + if (error) + return error; + } + + error = zinitix_write_u16(client, ZINITIX_INT_ENABLE_FLAG, 0x0); + if (error) + return error; + + dev_info(bt541->dev, "HW calibration complete\n"); + + return 0; +} + static int zinitix_init_touch(struct bt541_ts_data *bt541) { struct i2c_client *client = bt541->client; int i; int error; static bool read_static = false; + u16 val; error = zinitix_write_cmd(client, ZINITIX_SWRESET_CMD); if (error) { @@ -237,9 +347,20 @@ static int zinitix_init_touch(struct bt541_ts_data *bt541) "chip revision %04x firmware version %04x regdata version %04x\n", bt541->chip_revision, bt541->firmware_version, bt541->regdata_version); + if (zinitix_is_4x2(bt541)) + bt541->eeprom_info_reg = BT4X2_EEPROM_INFO_REG; + else + bt541->eeprom_info_reg = BT4X3_EEPROM_INFO; read_static = true; } + val = zinitix_get_u16_reg(bt541, bt541->eeprom_info_reg); + if (val & ZINITIX_EEPROM_HW_CALIB) { + error = zinitix_calibrate(bt541); + if (error) + return error; + } + error = zinitix_write_u16(client, ZINITIX_INT_ENABLE_FLAG, 0x0); if (error) { dev_err(bt541->dev, @@ -273,6 +394,11 @@ static int zinitix_init_touch(struct bt541_ts_data *bt541) if (error) return error; + /* Software calibration */ + error = zinitix_write_cmd(client, ZINITIX_CALIBRATE_CMD); + if (error) + return error; + error = zinitix_write_u16(client, ZINITIX_INT_ENABLE_FLAG, BIT_PT_CNT_CHANGE | BIT_DOWN | BIT_MOVE | BIT_UP); @@ -584,10 +710,10 @@ static int zinitix_ts_probe(struct i2c_client *client) &bt541->zinitix_mode); if (error < 0) { /* fall back to mode 2 */ - bt541->zinitix_mode = DEFAULT_TOUCH_POINT_MODE; + bt541->zinitix_mode = ZINITIX_MODE_TOUCH_POINT; } - if (bt541->zinitix_mode != 2) { + if (bt541->zinitix_mode != ZINITIX_MODE_TOUCH_POINT) { /* * If there are devices that don't support mode 2, support * for other modes (0, 1) will be needed. -- 2.35.1