162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#include <linux/delay.h> 462306a36Sopenharmony_ci#include <linux/i2c.h> 562306a36Sopenharmony_ci#include <linux/input.h> 662306a36Sopenharmony_ci#include <linux/input/mt.h> 762306a36Sopenharmony_ci#include <linux/input/touchscreen.h> 862306a36Sopenharmony_ci#include <linux/interrupt.h> 962306a36Sopenharmony_ci#include <linux/irq.h> 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <linux/of.h> 1362306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 1462306a36Sopenharmony_ci#include <linux/slab.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/* Register Map */ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define ZINITIX_SWRESET_CMD 0x0000 1962306a36Sopenharmony_ci#define ZINITIX_WAKEUP_CMD 0x0001 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define ZINITIX_IDLE_CMD 0x0004 2262306a36Sopenharmony_ci#define ZINITIX_SLEEP_CMD 0x0005 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define ZINITIX_CLEAR_INT_STATUS_CMD 0x0003 2562306a36Sopenharmony_ci#define ZINITIX_CALIBRATE_CMD 0x0006 2662306a36Sopenharmony_ci#define ZINITIX_SAVE_STATUS_CMD 0x0007 2762306a36Sopenharmony_ci#define ZINITIX_SAVE_CALIBRATION_CMD 0x0008 2862306a36Sopenharmony_ci#define ZINITIX_RECALL_FACTORY_CMD 0x000f 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define ZINITIX_THRESHOLD 0x0020 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#define ZINITIX_LARGE_PALM_REJECT_AREA_TH 0x003F 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define ZINITIX_DEBUG_REG 0x0115 /* 0~7 */ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define ZINITIX_TOUCH_MODE 0x0010 3762306a36Sopenharmony_ci#define ZINITIX_CHIP_REVISION 0x0011 3862306a36Sopenharmony_ci#define ZINITIX_FIRMWARE_VERSION 0x0012 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define ZINITIX_USB_DETECT 0x116 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci#define ZINITIX_MINOR_FW_VERSION 0x0121 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define ZINITIX_VENDOR_ID 0x001C 4562306a36Sopenharmony_ci#define ZINITIX_HW_ID 0x0014 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define ZINITIX_DATA_VERSION_REG 0x0013 4862306a36Sopenharmony_ci#define ZINITIX_SUPPORTED_FINGER_NUM 0x0015 4962306a36Sopenharmony_ci#define ZINITIX_EEPROM_INFO 0x0018 5062306a36Sopenharmony_ci#define ZINITIX_INITIAL_TOUCH_MODE 0x0019 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#define ZINITIX_TOTAL_NUMBER_OF_X 0x0060 5362306a36Sopenharmony_ci#define ZINITIX_TOTAL_NUMBER_OF_Y 0x0061 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define ZINITIX_DELAY_RAW_FOR_HOST 0x007f 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#define ZINITIX_BUTTON_SUPPORTED_NUM 0x00B0 5862306a36Sopenharmony_ci#define ZINITIX_BUTTON_SENSITIVITY 0x00B2 5962306a36Sopenharmony_ci#define ZINITIX_DUMMY_BUTTON_SENSITIVITY 0X00C8 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci#define ZINITIX_X_RESOLUTION 0x00C0 6262306a36Sopenharmony_ci#define ZINITIX_Y_RESOLUTION 0x00C1 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci#define ZINITIX_POINT_STATUS_REG 0x0080 6562306a36Sopenharmony_ci#define ZINITIX_ICON_STATUS_REG 0x00AA 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci#define ZINITIX_POINT_COORD_REG (ZINITIX_POINT_STATUS_REG + 2) 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci#define ZINITIX_AFE_FREQUENCY 0x0100 7062306a36Sopenharmony_ci#define ZINITIX_DND_N_COUNT 0x0122 7162306a36Sopenharmony_ci#define ZINITIX_DND_U_COUNT 0x0135 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci#define ZINITIX_RAWDATA_REG 0x0200 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci#define ZINITIX_EEPROM_INFO_REG 0x0018 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci#define ZINITIX_INT_ENABLE_FLAG 0x00f0 7862306a36Sopenharmony_ci#define ZINITIX_PERIODICAL_INTERRUPT_INTERVAL 0x00f1 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci#define ZINITIX_BTN_WIDTH 0x016d 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci#define ZINITIX_CHECKSUM_RESULT 0x012c 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci#define ZINITIX_INIT_FLASH 0x01d0 8562306a36Sopenharmony_ci#define ZINITIX_WRITE_FLASH 0x01d1 8662306a36Sopenharmony_ci#define ZINITIX_READ_FLASH 0x01d2 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci#define ZINITIX_INTERNAL_FLAG_02 0x011e 8962306a36Sopenharmony_ci#define ZINITIX_INTERNAL_FLAG_03 0x011f 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci#define ZINITIX_I2C_CHECKSUM_WCNT 0x016a 9262306a36Sopenharmony_ci#define ZINITIX_I2C_CHECKSUM_RESULT 0x016c 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci/* Interrupt & status register flags */ 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci#define BIT_PT_CNT_CHANGE BIT(0) 9762306a36Sopenharmony_ci#define BIT_DOWN BIT(1) 9862306a36Sopenharmony_ci#define BIT_MOVE BIT(2) 9962306a36Sopenharmony_ci#define BIT_UP BIT(3) 10062306a36Sopenharmony_ci#define BIT_PALM BIT(4) 10162306a36Sopenharmony_ci#define BIT_PALM_REJECT BIT(5) 10262306a36Sopenharmony_ci#define BIT_RESERVED_0 BIT(6) 10362306a36Sopenharmony_ci#define BIT_RESERVED_1 BIT(7) 10462306a36Sopenharmony_ci#define BIT_WEIGHT_CHANGE BIT(8) 10562306a36Sopenharmony_ci#define BIT_PT_NO_CHANGE BIT(9) 10662306a36Sopenharmony_ci#define BIT_REJECT BIT(10) 10762306a36Sopenharmony_ci#define BIT_PT_EXIST BIT(11) 10862306a36Sopenharmony_ci#define BIT_RESERVED_2 BIT(12) 10962306a36Sopenharmony_ci#define BIT_ERROR BIT(13) 11062306a36Sopenharmony_ci#define BIT_DEBUG BIT(14) 11162306a36Sopenharmony_ci#define BIT_ICON_EVENT BIT(15) 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci#define SUB_BIT_EXIST BIT(0) 11462306a36Sopenharmony_ci#define SUB_BIT_DOWN BIT(1) 11562306a36Sopenharmony_ci#define SUB_BIT_MOVE BIT(2) 11662306a36Sopenharmony_ci#define SUB_BIT_UP BIT(3) 11762306a36Sopenharmony_ci#define SUB_BIT_UPDATE BIT(4) 11862306a36Sopenharmony_ci#define SUB_BIT_WAIT BIT(5) 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci#define DEFAULT_TOUCH_POINT_MODE 2 12162306a36Sopenharmony_ci#define MAX_SUPPORTED_FINGER_NUM 5 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci#define CHIP_ON_DELAY 15 // ms 12462306a36Sopenharmony_ci#define FIRMWARE_ON_DELAY 40 // ms 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistruct point_coord { 12762306a36Sopenharmony_ci __le16 x; 12862306a36Sopenharmony_ci __le16 y; 12962306a36Sopenharmony_ci u8 width; 13062306a36Sopenharmony_ci u8 sub_status; 13162306a36Sopenharmony_ci // currently unused, but needed as padding: 13262306a36Sopenharmony_ci u8 minor_width; 13362306a36Sopenharmony_ci u8 angle; 13462306a36Sopenharmony_ci}; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistruct touch_event { 13762306a36Sopenharmony_ci __le16 status; 13862306a36Sopenharmony_ci u8 finger_mask; 13962306a36Sopenharmony_ci u8 time_stamp; 14062306a36Sopenharmony_ci struct point_coord point_coord[MAX_SUPPORTED_FINGER_NUM]; 14162306a36Sopenharmony_ci}; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistruct bt541_ts_data { 14462306a36Sopenharmony_ci struct i2c_client *client; 14562306a36Sopenharmony_ci struct input_dev *input_dev; 14662306a36Sopenharmony_ci struct touchscreen_properties prop; 14762306a36Sopenharmony_ci struct regulator_bulk_data supplies[2]; 14862306a36Sopenharmony_ci u32 zinitix_mode; 14962306a36Sopenharmony_ci}; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cistatic int zinitix_read_data(struct i2c_client *client, 15262306a36Sopenharmony_ci u16 reg, void *values, size_t length) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci __le16 reg_le = cpu_to_le16(reg); 15562306a36Sopenharmony_ci int ret; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci /* A single i2c_transfer() transaction does not work here. */ 15862306a36Sopenharmony_ci ret = i2c_master_send(client, (u8 *)®_le, sizeof(reg_le)); 15962306a36Sopenharmony_ci if (ret != sizeof(reg_le)) 16062306a36Sopenharmony_ci return ret < 0 ? ret : -EIO; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci ret = i2c_master_recv(client, (u8 *)values, length); 16362306a36Sopenharmony_ci if (ret != length) 16462306a36Sopenharmony_ci return ret < 0 ? ret : -EIO; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci return 0; 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_cistatic int zinitix_write_u16(struct i2c_client *client, u16 reg, u16 value) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci __le16 packet[2] = {cpu_to_le16(reg), cpu_to_le16(value)}; 17262306a36Sopenharmony_ci int ret; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci ret = i2c_master_send(client, (u8 *)packet, sizeof(packet)); 17562306a36Sopenharmony_ci if (ret != sizeof(packet)) 17662306a36Sopenharmony_ci return ret < 0 ? ret : -EIO; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci return 0; 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic int zinitix_write_cmd(struct i2c_client *client, u16 reg) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci __le16 reg_le = cpu_to_le16(reg); 18462306a36Sopenharmony_ci int ret; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci ret = i2c_master_send(client, (u8 *)®_le, sizeof(reg_le)); 18762306a36Sopenharmony_ci if (ret != sizeof(reg_le)) 18862306a36Sopenharmony_ci return ret < 0 ? ret : -EIO; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci return 0; 19162306a36Sopenharmony_ci} 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_cistatic int zinitix_init_touch(struct bt541_ts_data *bt541) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci struct i2c_client *client = bt541->client; 19662306a36Sopenharmony_ci int i; 19762306a36Sopenharmony_ci int error; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci error = zinitix_write_cmd(client, ZINITIX_SWRESET_CMD); 20062306a36Sopenharmony_ci if (error) { 20162306a36Sopenharmony_ci dev_err(&client->dev, "Failed to write reset command\n"); 20262306a36Sopenharmony_ci return error; 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci error = zinitix_write_u16(client, ZINITIX_INT_ENABLE_FLAG, 0x0); 20662306a36Sopenharmony_ci if (error) { 20762306a36Sopenharmony_ci dev_err(&client->dev, 20862306a36Sopenharmony_ci "Failed to reset interrupt enable flag\n"); 20962306a36Sopenharmony_ci return error; 21062306a36Sopenharmony_ci } 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci /* initialize */ 21362306a36Sopenharmony_ci error = zinitix_write_u16(client, ZINITIX_X_RESOLUTION, 21462306a36Sopenharmony_ci bt541->prop.max_x); 21562306a36Sopenharmony_ci if (error) 21662306a36Sopenharmony_ci return error; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci error = zinitix_write_u16(client, ZINITIX_Y_RESOLUTION, 21962306a36Sopenharmony_ci bt541->prop.max_y); 22062306a36Sopenharmony_ci if (error) 22162306a36Sopenharmony_ci return error; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci error = zinitix_write_u16(client, ZINITIX_SUPPORTED_FINGER_NUM, 22462306a36Sopenharmony_ci MAX_SUPPORTED_FINGER_NUM); 22562306a36Sopenharmony_ci if (error) 22662306a36Sopenharmony_ci return error; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci error = zinitix_write_u16(client, ZINITIX_INITIAL_TOUCH_MODE, 22962306a36Sopenharmony_ci bt541->zinitix_mode); 23062306a36Sopenharmony_ci if (error) 23162306a36Sopenharmony_ci return error; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci error = zinitix_write_u16(client, ZINITIX_TOUCH_MODE, 23462306a36Sopenharmony_ci bt541->zinitix_mode); 23562306a36Sopenharmony_ci if (error) 23662306a36Sopenharmony_ci return error; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci error = zinitix_write_u16(client, ZINITIX_INT_ENABLE_FLAG, 23962306a36Sopenharmony_ci BIT_PT_CNT_CHANGE | BIT_DOWN | BIT_MOVE | 24062306a36Sopenharmony_ci BIT_UP); 24162306a36Sopenharmony_ci if (error) 24262306a36Sopenharmony_ci return error; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci /* clear queue */ 24562306a36Sopenharmony_ci for (i = 0; i < 10; i++) { 24662306a36Sopenharmony_ci zinitix_write_cmd(client, ZINITIX_CLEAR_INT_STATUS_CMD); 24762306a36Sopenharmony_ci udelay(10); 24862306a36Sopenharmony_ci } 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci return 0; 25162306a36Sopenharmony_ci} 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_cistatic int zinitix_init_regulators(struct bt541_ts_data *bt541) 25462306a36Sopenharmony_ci{ 25562306a36Sopenharmony_ci struct device *dev = &bt541->client->dev; 25662306a36Sopenharmony_ci int error; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci /* 25962306a36Sopenharmony_ci * Some older device trees have erroneous names for the regulators, 26062306a36Sopenharmony_ci * so check if "vddo" is present and in that case use these names. 26162306a36Sopenharmony_ci * Else use the proper supply names on the component. 26262306a36Sopenharmony_ci */ 26362306a36Sopenharmony_ci if (of_property_present(dev->of_node, "vddo-supply")) { 26462306a36Sopenharmony_ci bt541->supplies[0].supply = "vdd"; 26562306a36Sopenharmony_ci bt541->supplies[1].supply = "vddo"; 26662306a36Sopenharmony_ci } else { 26762306a36Sopenharmony_ci /* Else use the proper supply names */ 26862306a36Sopenharmony_ci bt541->supplies[0].supply = "vcca"; 26962306a36Sopenharmony_ci bt541->supplies[1].supply = "vdd"; 27062306a36Sopenharmony_ci } 27162306a36Sopenharmony_ci error = devm_regulator_bulk_get(dev, 27262306a36Sopenharmony_ci ARRAY_SIZE(bt541->supplies), 27362306a36Sopenharmony_ci bt541->supplies); 27462306a36Sopenharmony_ci if (error < 0) { 27562306a36Sopenharmony_ci dev_err(dev, "Failed to get regulators: %d\n", error); 27662306a36Sopenharmony_ci return error; 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci return 0; 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cistatic int zinitix_send_power_on_sequence(struct bt541_ts_data *bt541) 28362306a36Sopenharmony_ci{ 28462306a36Sopenharmony_ci int error; 28562306a36Sopenharmony_ci struct i2c_client *client = bt541->client; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci error = zinitix_write_u16(client, 0xc000, 0x0001); 28862306a36Sopenharmony_ci if (error) { 28962306a36Sopenharmony_ci dev_err(&client->dev, 29062306a36Sopenharmony_ci "Failed to send power sequence(vendor cmd enable)\n"); 29162306a36Sopenharmony_ci return error; 29262306a36Sopenharmony_ci } 29362306a36Sopenharmony_ci udelay(10); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci error = zinitix_write_cmd(client, 0xc004); 29662306a36Sopenharmony_ci if (error) { 29762306a36Sopenharmony_ci dev_err(&client->dev, 29862306a36Sopenharmony_ci "Failed to send power sequence (intn clear)\n"); 29962306a36Sopenharmony_ci return error; 30062306a36Sopenharmony_ci } 30162306a36Sopenharmony_ci udelay(10); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci error = zinitix_write_u16(client, 0xc002, 0x0001); 30462306a36Sopenharmony_ci if (error) { 30562306a36Sopenharmony_ci dev_err(&client->dev, 30662306a36Sopenharmony_ci "Failed to send power sequence (nvm init)\n"); 30762306a36Sopenharmony_ci return error; 30862306a36Sopenharmony_ci } 30962306a36Sopenharmony_ci mdelay(2); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci error = zinitix_write_u16(client, 0xc001, 0x0001); 31262306a36Sopenharmony_ci if (error) { 31362306a36Sopenharmony_ci dev_err(&client->dev, 31462306a36Sopenharmony_ci "Failed to send power sequence (program start)\n"); 31562306a36Sopenharmony_ci return error; 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci msleep(FIRMWARE_ON_DELAY); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci return 0; 32062306a36Sopenharmony_ci} 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic void zinitix_report_finger(struct bt541_ts_data *bt541, int slot, 32362306a36Sopenharmony_ci const struct point_coord *p) 32462306a36Sopenharmony_ci{ 32562306a36Sopenharmony_ci u16 x, y; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci if (unlikely(!(p->sub_status & 32862306a36Sopenharmony_ci (SUB_BIT_UP | SUB_BIT_DOWN | SUB_BIT_MOVE)))) { 32962306a36Sopenharmony_ci dev_dbg(&bt541->client->dev, "unknown finger event %#02x\n", 33062306a36Sopenharmony_ci p->sub_status); 33162306a36Sopenharmony_ci return; 33262306a36Sopenharmony_ci } 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci x = le16_to_cpu(p->x); 33562306a36Sopenharmony_ci y = le16_to_cpu(p->y); 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci input_mt_slot(bt541->input_dev, slot); 33862306a36Sopenharmony_ci if (input_mt_report_slot_state(bt541->input_dev, MT_TOOL_FINGER, 33962306a36Sopenharmony_ci !(p->sub_status & SUB_BIT_UP))) { 34062306a36Sopenharmony_ci touchscreen_report_pos(bt541->input_dev, 34162306a36Sopenharmony_ci &bt541->prop, x, y, true); 34262306a36Sopenharmony_ci input_report_abs(bt541->input_dev, 34362306a36Sopenharmony_ci ABS_MT_TOUCH_MAJOR, p->width); 34462306a36Sopenharmony_ci dev_dbg(&bt541->client->dev, "finger %d %s (%u, %u)\n", 34562306a36Sopenharmony_ci slot, p->sub_status & SUB_BIT_DOWN ? "down" : "move", 34662306a36Sopenharmony_ci x, y); 34762306a36Sopenharmony_ci } else { 34862306a36Sopenharmony_ci dev_dbg(&bt541->client->dev, "finger %d up (%u, %u)\n", 34962306a36Sopenharmony_ci slot, x, y); 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_cistatic irqreturn_t zinitix_ts_irq_handler(int irq, void *bt541_handler) 35462306a36Sopenharmony_ci{ 35562306a36Sopenharmony_ci struct bt541_ts_data *bt541 = bt541_handler; 35662306a36Sopenharmony_ci struct i2c_client *client = bt541->client; 35762306a36Sopenharmony_ci struct touch_event touch_event; 35862306a36Sopenharmony_ci unsigned long finger_mask; 35962306a36Sopenharmony_ci int error; 36062306a36Sopenharmony_ci int i; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci memset(&touch_event, 0, sizeof(struct touch_event)); 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci error = zinitix_read_data(bt541->client, ZINITIX_POINT_STATUS_REG, 36562306a36Sopenharmony_ci &touch_event, sizeof(struct touch_event)); 36662306a36Sopenharmony_ci if (error) { 36762306a36Sopenharmony_ci dev_err(&client->dev, "Failed to read in touchpoint struct\n"); 36862306a36Sopenharmony_ci goto out; 36962306a36Sopenharmony_ci } 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci finger_mask = touch_event.finger_mask; 37262306a36Sopenharmony_ci for_each_set_bit(i, &finger_mask, MAX_SUPPORTED_FINGER_NUM) { 37362306a36Sopenharmony_ci const struct point_coord *p = &touch_event.point_coord[i]; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci /* Only process contacts that are actually reported */ 37662306a36Sopenharmony_ci if (p->sub_status & SUB_BIT_EXIST) 37762306a36Sopenharmony_ci zinitix_report_finger(bt541, i, p); 37862306a36Sopenharmony_ci } 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci input_mt_sync_frame(bt541->input_dev); 38162306a36Sopenharmony_ci input_sync(bt541->input_dev); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ciout: 38462306a36Sopenharmony_ci zinitix_write_cmd(bt541->client, ZINITIX_CLEAR_INT_STATUS_CMD); 38562306a36Sopenharmony_ci return IRQ_HANDLED; 38662306a36Sopenharmony_ci} 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_cistatic int zinitix_start(struct bt541_ts_data *bt541) 38962306a36Sopenharmony_ci{ 39062306a36Sopenharmony_ci int error; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci error = regulator_bulk_enable(ARRAY_SIZE(bt541->supplies), 39362306a36Sopenharmony_ci bt541->supplies); 39462306a36Sopenharmony_ci if (error) { 39562306a36Sopenharmony_ci dev_err(&bt541->client->dev, 39662306a36Sopenharmony_ci "Failed to enable regulators: %d\n", error); 39762306a36Sopenharmony_ci return error; 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci msleep(CHIP_ON_DELAY); 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci error = zinitix_send_power_on_sequence(bt541); 40362306a36Sopenharmony_ci if (error) { 40462306a36Sopenharmony_ci dev_err(&bt541->client->dev, 40562306a36Sopenharmony_ci "Error while sending power-on sequence: %d\n", error); 40662306a36Sopenharmony_ci return error; 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci error = zinitix_init_touch(bt541); 41062306a36Sopenharmony_ci if (error) { 41162306a36Sopenharmony_ci dev_err(&bt541->client->dev, 41262306a36Sopenharmony_ci "Error while configuring touch IC\n"); 41362306a36Sopenharmony_ci return error; 41462306a36Sopenharmony_ci } 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci enable_irq(bt541->client->irq); 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci return 0; 41962306a36Sopenharmony_ci} 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_cistatic int zinitix_stop(struct bt541_ts_data *bt541) 42262306a36Sopenharmony_ci{ 42362306a36Sopenharmony_ci int error; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci disable_irq(bt541->client->irq); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci error = regulator_bulk_disable(ARRAY_SIZE(bt541->supplies), 42862306a36Sopenharmony_ci bt541->supplies); 42962306a36Sopenharmony_ci if (error) { 43062306a36Sopenharmony_ci dev_err(&bt541->client->dev, 43162306a36Sopenharmony_ci "Failed to disable regulators: %d\n", error); 43262306a36Sopenharmony_ci return error; 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci return 0; 43662306a36Sopenharmony_ci} 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_cistatic int zinitix_input_open(struct input_dev *dev) 43962306a36Sopenharmony_ci{ 44062306a36Sopenharmony_ci struct bt541_ts_data *bt541 = input_get_drvdata(dev); 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci return zinitix_start(bt541); 44362306a36Sopenharmony_ci} 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_cistatic void zinitix_input_close(struct input_dev *dev) 44662306a36Sopenharmony_ci{ 44762306a36Sopenharmony_ci struct bt541_ts_data *bt541 = input_get_drvdata(dev); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci zinitix_stop(bt541); 45062306a36Sopenharmony_ci} 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_cistatic int zinitix_init_input_dev(struct bt541_ts_data *bt541) 45362306a36Sopenharmony_ci{ 45462306a36Sopenharmony_ci struct input_dev *input_dev; 45562306a36Sopenharmony_ci int error; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci input_dev = devm_input_allocate_device(&bt541->client->dev); 45862306a36Sopenharmony_ci if (!input_dev) { 45962306a36Sopenharmony_ci dev_err(&bt541->client->dev, 46062306a36Sopenharmony_ci "Failed to allocate input device."); 46162306a36Sopenharmony_ci return -ENOMEM; 46262306a36Sopenharmony_ci } 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci input_set_drvdata(input_dev, bt541); 46562306a36Sopenharmony_ci bt541->input_dev = input_dev; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci input_dev->name = "Zinitix Capacitive TouchScreen"; 46862306a36Sopenharmony_ci input_dev->phys = "input/ts"; 46962306a36Sopenharmony_ci input_dev->id.bustype = BUS_I2C; 47062306a36Sopenharmony_ci input_dev->open = zinitix_input_open; 47162306a36Sopenharmony_ci input_dev->close = zinitix_input_close; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X); 47462306a36Sopenharmony_ci input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y); 47562306a36Sopenharmony_ci input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); 47662306a36Sopenharmony_ci input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci touchscreen_parse_properties(input_dev, true, &bt541->prop); 47962306a36Sopenharmony_ci if (!bt541->prop.max_x || !bt541->prop.max_y) { 48062306a36Sopenharmony_ci dev_err(&bt541->client->dev, 48162306a36Sopenharmony_ci "Touchscreen-size-x and/or touchscreen-size-y not set in dts\n"); 48262306a36Sopenharmony_ci return -EINVAL; 48362306a36Sopenharmony_ci } 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci error = input_mt_init_slots(input_dev, MAX_SUPPORTED_FINGER_NUM, 48662306a36Sopenharmony_ci INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 48762306a36Sopenharmony_ci if (error) { 48862306a36Sopenharmony_ci dev_err(&bt541->client->dev, 48962306a36Sopenharmony_ci "Failed to initialize MT slots: %d", error); 49062306a36Sopenharmony_ci return error; 49162306a36Sopenharmony_ci } 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci error = input_register_device(input_dev); 49462306a36Sopenharmony_ci if (error) { 49562306a36Sopenharmony_ci dev_err(&bt541->client->dev, 49662306a36Sopenharmony_ci "Failed to register input device: %d", error); 49762306a36Sopenharmony_ci return error; 49862306a36Sopenharmony_ci } 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci return 0; 50162306a36Sopenharmony_ci} 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_cistatic int zinitix_ts_probe(struct i2c_client *client) 50462306a36Sopenharmony_ci{ 50562306a36Sopenharmony_ci struct bt541_ts_data *bt541; 50662306a36Sopenharmony_ci int error; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 50962306a36Sopenharmony_ci dev_err(&client->dev, 51062306a36Sopenharmony_ci "Failed to assert adapter's support for plain I2C.\n"); 51162306a36Sopenharmony_ci return -ENXIO; 51262306a36Sopenharmony_ci } 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci bt541 = devm_kzalloc(&client->dev, sizeof(*bt541), GFP_KERNEL); 51562306a36Sopenharmony_ci if (!bt541) 51662306a36Sopenharmony_ci return -ENOMEM; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci bt541->client = client; 51962306a36Sopenharmony_ci i2c_set_clientdata(client, bt541); 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci error = zinitix_init_regulators(bt541); 52262306a36Sopenharmony_ci if (error) { 52362306a36Sopenharmony_ci dev_err(&client->dev, 52462306a36Sopenharmony_ci "Failed to initialize regulators: %d\n", error); 52562306a36Sopenharmony_ci return error; 52662306a36Sopenharmony_ci } 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci error = devm_request_threaded_irq(&client->dev, client->irq, 52962306a36Sopenharmony_ci NULL, zinitix_ts_irq_handler, 53062306a36Sopenharmony_ci IRQF_ONESHOT | IRQF_NO_AUTOEN, 53162306a36Sopenharmony_ci client->name, bt541); 53262306a36Sopenharmony_ci if (error) { 53362306a36Sopenharmony_ci dev_err(&client->dev, "Failed to request IRQ: %d\n", error); 53462306a36Sopenharmony_ci return error; 53562306a36Sopenharmony_ci } 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci error = zinitix_init_input_dev(bt541); 53862306a36Sopenharmony_ci if (error) { 53962306a36Sopenharmony_ci dev_err(&client->dev, 54062306a36Sopenharmony_ci "Failed to initialize input device: %d\n", error); 54162306a36Sopenharmony_ci return error; 54262306a36Sopenharmony_ci } 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci error = device_property_read_u32(&client->dev, "zinitix,mode", 54562306a36Sopenharmony_ci &bt541->zinitix_mode); 54662306a36Sopenharmony_ci if (error < 0) { 54762306a36Sopenharmony_ci /* fall back to mode 2 */ 54862306a36Sopenharmony_ci bt541->zinitix_mode = DEFAULT_TOUCH_POINT_MODE; 54962306a36Sopenharmony_ci } 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci if (bt541->zinitix_mode != 2) { 55262306a36Sopenharmony_ci /* 55362306a36Sopenharmony_ci * If there are devices that don't support mode 2, support 55462306a36Sopenharmony_ci * for other modes (0, 1) will be needed. 55562306a36Sopenharmony_ci */ 55662306a36Sopenharmony_ci dev_err(&client->dev, 55762306a36Sopenharmony_ci "Malformed zinitix,mode property, must be 2 (supplied: %d)\n", 55862306a36Sopenharmony_ci bt541->zinitix_mode); 55962306a36Sopenharmony_ci return -EINVAL; 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci return 0; 56362306a36Sopenharmony_ci} 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_cistatic int zinitix_suspend(struct device *dev) 56662306a36Sopenharmony_ci{ 56762306a36Sopenharmony_ci struct i2c_client *client = to_i2c_client(dev); 56862306a36Sopenharmony_ci struct bt541_ts_data *bt541 = i2c_get_clientdata(client); 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci mutex_lock(&bt541->input_dev->mutex); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci if (input_device_enabled(bt541->input_dev)) 57362306a36Sopenharmony_ci zinitix_stop(bt541); 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci mutex_unlock(&bt541->input_dev->mutex); 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci return 0; 57862306a36Sopenharmony_ci} 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_cistatic int zinitix_resume(struct device *dev) 58162306a36Sopenharmony_ci{ 58262306a36Sopenharmony_ci struct i2c_client *client = to_i2c_client(dev); 58362306a36Sopenharmony_ci struct bt541_ts_data *bt541 = i2c_get_clientdata(client); 58462306a36Sopenharmony_ci int ret = 0; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci mutex_lock(&bt541->input_dev->mutex); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci if (input_device_enabled(bt541->input_dev)) 58962306a36Sopenharmony_ci ret = zinitix_start(bt541); 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci mutex_unlock(&bt541->input_dev->mutex); 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci return ret; 59462306a36Sopenharmony_ci} 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_cistatic DEFINE_SIMPLE_DEV_PM_OPS(zinitix_pm_ops, zinitix_suspend, zinitix_resume); 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci#ifdef CONFIG_OF 59962306a36Sopenharmony_cistatic const struct of_device_id zinitix_of_match[] = { 60062306a36Sopenharmony_ci { .compatible = "zinitix,bt402" }, 60162306a36Sopenharmony_ci { .compatible = "zinitix,bt403" }, 60262306a36Sopenharmony_ci { .compatible = "zinitix,bt404" }, 60362306a36Sopenharmony_ci { .compatible = "zinitix,bt412" }, 60462306a36Sopenharmony_ci { .compatible = "zinitix,bt413" }, 60562306a36Sopenharmony_ci { .compatible = "zinitix,bt431" }, 60662306a36Sopenharmony_ci { .compatible = "zinitix,bt432" }, 60762306a36Sopenharmony_ci { .compatible = "zinitix,bt531" }, 60862306a36Sopenharmony_ci { .compatible = "zinitix,bt532" }, 60962306a36Sopenharmony_ci { .compatible = "zinitix,bt538" }, 61062306a36Sopenharmony_ci { .compatible = "zinitix,bt541" }, 61162306a36Sopenharmony_ci { .compatible = "zinitix,bt548" }, 61262306a36Sopenharmony_ci { .compatible = "zinitix,bt554" }, 61362306a36Sopenharmony_ci { .compatible = "zinitix,at100" }, 61462306a36Sopenharmony_ci { } 61562306a36Sopenharmony_ci}; 61662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, zinitix_of_match); 61762306a36Sopenharmony_ci#endif 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_cistatic struct i2c_driver zinitix_ts_driver = { 62062306a36Sopenharmony_ci .probe = zinitix_ts_probe, 62162306a36Sopenharmony_ci .driver = { 62262306a36Sopenharmony_ci .name = "Zinitix-TS", 62362306a36Sopenharmony_ci .pm = pm_sleep_ptr(&zinitix_pm_ops), 62462306a36Sopenharmony_ci .of_match_table = of_match_ptr(zinitix_of_match), 62562306a36Sopenharmony_ci }, 62662306a36Sopenharmony_ci}; 62762306a36Sopenharmony_cimodule_i2c_driver(zinitix_ts_driver); 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ciMODULE_AUTHOR("Michael Srba <Michael.Srba@seznam.cz>"); 63062306a36Sopenharmony_ciMODULE_DESCRIPTION("Zinitix touchscreen driver"); 63162306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 632