18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci#include <linux/delay.h> 48c2ecf20Sopenharmony_ci#include <linux/i2c.h> 58c2ecf20Sopenharmony_ci#include <linux/input.h> 68c2ecf20Sopenharmony_ci#include <linux/input/mt.h> 78c2ecf20Sopenharmony_ci#include <linux/input/touchscreen.h> 88c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 98c2ecf20Sopenharmony_ci#include <linux/irq.h> 108c2ecf20Sopenharmony_ci#include <linux/kernel.h> 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/of.h> 138c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/* Register Map */ 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define BT541_SWRESET_CMD 0x0000 198c2ecf20Sopenharmony_ci#define BT541_WAKEUP_CMD 0x0001 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define BT541_IDLE_CMD 0x0004 228c2ecf20Sopenharmony_ci#define BT541_SLEEP_CMD 0x0005 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define BT541_CLEAR_INT_STATUS_CMD 0x0003 258c2ecf20Sopenharmony_ci#define BT541_CALIBRATE_CMD 0x0006 268c2ecf20Sopenharmony_ci#define BT541_SAVE_STATUS_CMD 0x0007 278c2ecf20Sopenharmony_ci#define BT541_SAVE_CALIBRATION_CMD 0x0008 288c2ecf20Sopenharmony_ci#define BT541_RECALL_FACTORY_CMD 0x000f 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define BT541_THRESHOLD 0x0020 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define BT541_LARGE_PALM_REJECT_AREA_TH 0x003F 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define BT541_DEBUG_REG 0x0115 /* 0~7 */ 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#define BT541_TOUCH_MODE 0x0010 378c2ecf20Sopenharmony_ci#define BT541_CHIP_REVISION 0x0011 388c2ecf20Sopenharmony_ci#define BT541_FIRMWARE_VERSION 0x0012 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#define ZINITIX_USB_DETECT 0x116 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#define BT541_MINOR_FW_VERSION 0x0121 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#define BT541_VENDOR_ID 0x001C 458c2ecf20Sopenharmony_ci#define BT541_HW_ID 0x0014 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#define BT541_DATA_VERSION_REG 0x0013 488c2ecf20Sopenharmony_ci#define BT541_SUPPORTED_FINGER_NUM 0x0015 498c2ecf20Sopenharmony_ci#define BT541_EEPROM_INFO 0x0018 508c2ecf20Sopenharmony_ci#define BT541_INITIAL_TOUCH_MODE 0x0019 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#define BT541_TOTAL_NUMBER_OF_X 0x0060 538c2ecf20Sopenharmony_ci#define BT541_TOTAL_NUMBER_OF_Y 0x0061 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci#define BT541_DELAY_RAW_FOR_HOST 0x007f 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci#define BT541_BUTTON_SUPPORTED_NUM 0x00B0 588c2ecf20Sopenharmony_ci#define BT541_BUTTON_SENSITIVITY 0x00B2 598c2ecf20Sopenharmony_ci#define BT541_DUMMY_BUTTON_SENSITIVITY 0X00C8 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci#define BT541_X_RESOLUTION 0x00C0 628c2ecf20Sopenharmony_ci#define BT541_Y_RESOLUTION 0x00C1 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci#define BT541_POINT_STATUS_REG 0x0080 658c2ecf20Sopenharmony_ci#define BT541_ICON_STATUS_REG 0x00AA 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci#define BT541_POINT_COORD_REG (BT541_POINT_STATUS_REG + 2) 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci#define BT541_AFE_FREQUENCY 0x0100 708c2ecf20Sopenharmony_ci#define BT541_DND_N_COUNT 0x0122 718c2ecf20Sopenharmony_ci#define BT541_DND_U_COUNT 0x0135 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci#define BT541_RAWDATA_REG 0x0200 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci#define BT541_EEPROM_INFO_REG 0x0018 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci#define BT541_INT_ENABLE_FLAG 0x00f0 788c2ecf20Sopenharmony_ci#define BT541_PERIODICAL_INTERRUPT_INTERVAL 0x00f1 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci#define BT541_BTN_WIDTH 0x016d 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci#define BT541_CHECKSUM_RESULT 0x012c 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci#define BT541_INIT_FLASH 0x01d0 858c2ecf20Sopenharmony_ci#define BT541_WRITE_FLASH 0x01d1 868c2ecf20Sopenharmony_ci#define BT541_READ_FLASH 0x01d2 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci#define ZINITIX_INTERNAL_FLAG_02 0x011e 898c2ecf20Sopenharmony_ci#define ZINITIX_INTERNAL_FLAG_03 0x011f 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci#define ZINITIX_I2C_CHECKSUM_WCNT 0x016a 928c2ecf20Sopenharmony_ci#define ZINITIX_I2C_CHECKSUM_RESULT 0x016c 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci/* Interrupt & status register flags */ 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci#define BIT_PT_CNT_CHANGE BIT(0) 978c2ecf20Sopenharmony_ci#define BIT_DOWN BIT(1) 988c2ecf20Sopenharmony_ci#define BIT_MOVE BIT(2) 998c2ecf20Sopenharmony_ci#define BIT_UP BIT(3) 1008c2ecf20Sopenharmony_ci#define BIT_PALM BIT(4) 1018c2ecf20Sopenharmony_ci#define BIT_PALM_REJECT BIT(5) 1028c2ecf20Sopenharmony_ci#define BIT_RESERVED_0 BIT(6) 1038c2ecf20Sopenharmony_ci#define BIT_RESERVED_1 BIT(7) 1048c2ecf20Sopenharmony_ci#define BIT_WEIGHT_CHANGE BIT(8) 1058c2ecf20Sopenharmony_ci#define BIT_PT_NO_CHANGE BIT(9) 1068c2ecf20Sopenharmony_ci#define BIT_REJECT BIT(10) 1078c2ecf20Sopenharmony_ci#define BIT_PT_EXIST BIT(11) 1088c2ecf20Sopenharmony_ci#define BIT_RESERVED_2 BIT(12) 1098c2ecf20Sopenharmony_ci#define BIT_ERROR BIT(13) 1108c2ecf20Sopenharmony_ci#define BIT_DEBUG BIT(14) 1118c2ecf20Sopenharmony_ci#define BIT_ICON_EVENT BIT(15) 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci#define SUB_BIT_EXIST BIT(0) 1148c2ecf20Sopenharmony_ci#define SUB_BIT_DOWN BIT(1) 1158c2ecf20Sopenharmony_ci#define SUB_BIT_MOVE BIT(2) 1168c2ecf20Sopenharmony_ci#define SUB_BIT_UP BIT(3) 1178c2ecf20Sopenharmony_ci#define SUB_BIT_UPDATE BIT(4) 1188c2ecf20Sopenharmony_ci#define SUB_BIT_WAIT BIT(5) 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci#define DEFAULT_TOUCH_POINT_MODE 2 1218c2ecf20Sopenharmony_ci#define MAX_SUPPORTED_FINGER_NUM 5 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci#define CHIP_ON_DELAY 15 // ms 1248c2ecf20Sopenharmony_ci#define FIRMWARE_ON_DELAY 40 // ms 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_cistruct point_coord { 1278c2ecf20Sopenharmony_ci __le16 x; 1288c2ecf20Sopenharmony_ci __le16 y; 1298c2ecf20Sopenharmony_ci u8 width; 1308c2ecf20Sopenharmony_ci u8 sub_status; 1318c2ecf20Sopenharmony_ci // currently unused, but needed as padding: 1328c2ecf20Sopenharmony_ci u8 minor_width; 1338c2ecf20Sopenharmony_ci u8 angle; 1348c2ecf20Sopenharmony_ci}; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistruct touch_event { 1378c2ecf20Sopenharmony_ci __le16 status; 1388c2ecf20Sopenharmony_ci u8 finger_mask; 1398c2ecf20Sopenharmony_ci u8 time_stamp; 1408c2ecf20Sopenharmony_ci struct point_coord point_coord[MAX_SUPPORTED_FINGER_NUM]; 1418c2ecf20Sopenharmony_ci}; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_cistruct bt541_ts_data { 1448c2ecf20Sopenharmony_ci struct i2c_client *client; 1458c2ecf20Sopenharmony_ci struct input_dev *input_dev; 1468c2ecf20Sopenharmony_ci struct touchscreen_properties prop; 1478c2ecf20Sopenharmony_ci struct regulator_bulk_data supplies[2]; 1488c2ecf20Sopenharmony_ci u32 zinitix_mode; 1498c2ecf20Sopenharmony_ci}; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistatic int zinitix_read_data(struct i2c_client *client, 1528c2ecf20Sopenharmony_ci u16 reg, void *values, size_t length) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci __le16 reg_le = cpu_to_le16(reg); 1558c2ecf20Sopenharmony_ci int ret; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* A single i2c_transfer() transaction does not work here. */ 1588c2ecf20Sopenharmony_ci ret = i2c_master_send(client, (u8 *)®_le, sizeof(reg_le)); 1598c2ecf20Sopenharmony_ci if (ret != sizeof(reg_le)) 1608c2ecf20Sopenharmony_ci return ret < 0 ? ret : -EIO; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci ret = i2c_master_recv(client, (u8 *)values, length); 1638c2ecf20Sopenharmony_ci if (ret != length) 1648c2ecf20Sopenharmony_ci return ret < 0 ? ret : -EIO; ; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci return 0; 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic int zinitix_write_u16(struct i2c_client *client, u16 reg, u16 value) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci __le16 packet[2] = {cpu_to_le16(reg), cpu_to_le16(value)}; 1728c2ecf20Sopenharmony_ci int ret; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci ret = i2c_master_send(client, (u8 *)packet, sizeof(packet)); 1758c2ecf20Sopenharmony_ci if (ret != sizeof(packet)) 1768c2ecf20Sopenharmony_ci return ret < 0 ? ret : -EIO; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci return 0; 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistatic int zinitix_write_cmd(struct i2c_client *client, u16 reg) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci __le16 reg_le = cpu_to_le16(reg); 1848c2ecf20Sopenharmony_ci int ret; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci ret = i2c_master_send(client, (u8 *)®_le, sizeof(reg_le)); 1878c2ecf20Sopenharmony_ci if (ret != sizeof(reg_le)) 1888c2ecf20Sopenharmony_ci return ret < 0 ? ret : -EIO; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci return 0; 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cistatic int zinitix_init_touch(struct bt541_ts_data *bt541) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci struct i2c_client *client = bt541->client; 1968c2ecf20Sopenharmony_ci int i; 1978c2ecf20Sopenharmony_ci int error; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci error = zinitix_write_cmd(client, BT541_SWRESET_CMD); 2008c2ecf20Sopenharmony_ci if (error) { 2018c2ecf20Sopenharmony_ci dev_err(&client->dev, "Failed to write reset command\n"); 2028c2ecf20Sopenharmony_ci return error; 2038c2ecf20Sopenharmony_ci } 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci error = zinitix_write_u16(client, BT541_INT_ENABLE_FLAG, 0x0); 2068c2ecf20Sopenharmony_ci if (error) { 2078c2ecf20Sopenharmony_ci dev_err(&client->dev, 2088c2ecf20Sopenharmony_ci "Failed to reset interrupt enable flag\n"); 2098c2ecf20Sopenharmony_ci return error; 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci /* initialize */ 2138c2ecf20Sopenharmony_ci error = zinitix_write_u16(client, BT541_X_RESOLUTION, 2148c2ecf20Sopenharmony_ci bt541->prop.max_x); 2158c2ecf20Sopenharmony_ci if (error) 2168c2ecf20Sopenharmony_ci return error; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci error = zinitix_write_u16(client, BT541_Y_RESOLUTION, 2198c2ecf20Sopenharmony_ci bt541->prop.max_y); 2208c2ecf20Sopenharmony_ci if (error) 2218c2ecf20Sopenharmony_ci return error; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci error = zinitix_write_u16(client, BT541_SUPPORTED_FINGER_NUM, 2248c2ecf20Sopenharmony_ci MAX_SUPPORTED_FINGER_NUM); 2258c2ecf20Sopenharmony_ci if (error) 2268c2ecf20Sopenharmony_ci return error; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci error = zinitix_write_u16(client, BT541_INITIAL_TOUCH_MODE, 2298c2ecf20Sopenharmony_ci bt541->zinitix_mode); 2308c2ecf20Sopenharmony_ci if (error) 2318c2ecf20Sopenharmony_ci return error; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci error = zinitix_write_u16(client, BT541_TOUCH_MODE, 2348c2ecf20Sopenharmony_ci bt541->zinitix_mode); 2358c2ecf20Sopenharmony_ci if (error) 2368c2ecf20Sopenharmony_ci return error; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci error = zinitix_write_u16(client, BT541_INT_ENABLE_FLAG, 2398c2ecf20Sopenharmony_ci BIT_PT_CNT_CHANGE | BIT_DOWN | BIT_MOVE | 2408c2ecf20Sopenharmony_ci BIT_UP); 2418c2ecf20Sopenharmony_ci if (error) 2428c2ecf20Sopenharmony_ci return error; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci /* clear queue */ 2458c2ecf20Sopenharmony_ci for (i = 0; i < 10; i++) { 2468c2ecf20Sopenharmony_ci zinitix_write_cmd(client, BT541_CLEAR_INT_STATUS_CMD); 2478c2ecf20Sopenharmony_ci udelay(10); 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci return 0; 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic int zinitix_init_regulators(struct bt541_ts_data *bt541) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci struct i2c_client *client = bt541->client; 2568c2ecf20Sopenharmony_ci int error; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci bt541->supplies[0].supply = "vdd"; 2598c2ecf20Sopenharmony_ci bt541->supplies[1].supply = "vddo"; 2608c2ecf20Sopenharmony_ci error = devm_regulator_bulk_get(&client->dev, 2618c2ecf20Sopenharmony_ci ARRAY_SIZE(bt541->supplies), 2628c2ecf20Sopenharmony_ci bt541->supplies); 2638c2ecf20Sopenharmony_ci if (error < 0) { 2648c2ecf20Sopenharmony_ci dev_err(&client->dev, "Failed to get regulators: %d\n", error); 2658c2ecf20Sopenharmony_ci return error; 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci return 0; 2698c2ecf20Sopenharmony_ci} 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_cistatic int zinitix_send_power_on_sequence(struct bt541_ts_data *bt541) 2728c2ecf20Sopenharmony_ci{ 2738c2ecf20Sopenharmony_ci int error; 2748c2ecf20Sopenharmony_ci struct i2c_client *client = bt541->client; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci error = zinitix_write_u16(client, 0xc000, 0x0001); 2778c2ecf20Sopenharmony_ci if (error) { 2788c2ecf20Sopenharmony_ci dev_err(&client->dev, 2798c2ecf20Sopenharmony_ci "Failed to send power sequence(vendor cmd enable)\n"); 2808c2ecf20Sopenharmony_ci return error; 2818c2ecf20Sopenharmony_ci } 2828c2ecf20Sopenharmony_ci udelay(10); 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci error = zinitix_write_cmd(client, 0xc004); 2858c2ecf20Sopenharmony_ci if (error) { 2868c2ecf20Sopenharmony_ci dev_err(&client->dev, 2878c2ecf20Sopenharmony_ci "Failed to send power sequence (intn clear)\n"); 2888c2ecf20Sopenharmony_ci return error; 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci udelay(10); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci error = zinitix_write_u16(client, 0xc002, 0x0001); 2938c2ecf20Sopenharmony_ci if (error) { 2948c2ecf20Sopenharmony_ci dev_err(&client->dev, 2958c2ecf20Sopenharmony_ci "Failed to send power sequence (nvm init)\n"); 2968c2ecf20Sopenharmony_ci return error; 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci mdelay(2); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci error = zinitix_write_u16(client, 0xc001, 0x0001); 3018c2ecf20Sopenharmony_ci if (error) { 3028c2ecf20Sopenharmony_ci dev_err(&client->dev, 3038c2ecf20Sopenharmony_ci "Failed to send power sequence (program start)\n"); 3048c2ecf20Sopenharmony_ci return error; 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci msleep(FIRMWARE_ON_DELAY); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci return 0; 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_cistatic void zinitix_report_finger(struct bt541_ts_data *bt541, int slot, 3128c2ecf20Sopenharmony_ci const struct point_coord *p) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci u16 x, y; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci if (unlikely(!(p->sub_status & 3178c2ecf20Sopenharmony_ci (SUB_BIT_UP | SUB_BIT_DOWN | SUB_BIT_MOVE)))) { 3188c2ecf20Sopenharmony_ci dev_dbg(&bt541->client->dev, "unknown finger event %#02x\n", 3198c2ecf20Sopenharmony_ci p->sub_status); 3208c2ecf20Sopenharmony_ci return; 3218c2ecf20Sopenharmony_ci } 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci x = le16_to_cpu(p->x); 3248c2ecf20Sopenharmony_ci y = le16_to_cpu(p->y); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci input_mt_slot(bt541->input_dev, slot); 3278c2ecf20Sopenharmony_ci if (input_mt_report_slot_state(bt541->input_dev, MT_TOOL_FINGER, 3288c2ecf20Sopenharmony_ci !(p->sub_status & SUB_BIT_UP))) { 3298c2ecf20Sopenharmony_ci touchscreen_report_pos(bt541->input_dev, 3308c2ecf20Sopenharmony_ci &bt541->prop, x, y, true); 3318c2ecf20Sopenharmony_ci input_report_abs(bt541->input_dev, 3328c2ecf20Sopenharmony_ci ABS_MT_TOUCH_MAJOR, p->width); 3338c2ecf20Sopenharmony_ci dev_dbg(&bt541->client->dev, "finger %d %s (%u, %u)\n", 3348c2ecf20Sopenharmony_ci slot, p->sub_status & SUB_BIT_DOWN ? "down" : "move", 3358c2ecf20Sopenharmony_ci x, y); 3368c2ecf20Sopenharmony_ci } else { 3378c2ecf20Sopenharmony_ci dev_dbg(&bt541->client->dev, "finger %d up (%u, %u)\n", 3388c2ecf20Sopenharmony_ci slot, x, y); 3398c2ecf20Sopenharmony_ci } 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cistatic irqreturn_t zinitix_ts_irq_handler(int irq, void *bt541_handler) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci struct bt541_ts_data *bt541 = bt541_handler; 3458c2ecf20Sopenharmony_ci struct i2c_client *client = bt541->client; 3468c2ecf20Sopenharmony_ci struct touch_event touch_event; 3478c2ecf20Sopenharmony_ci unsigned long finger_mask; 3488c2ecf20Sopenharmony_ci int error; 3498c2ecf20Sopenharmony_ci int i; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci memset(&touch_event, 0, sizeof(struct touch_event)); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci error = zinitix_read_data(bt541->client, BT541_POINT_STATUS_REG, 3548c2ecf20Sopenharmony_ci &touch_event, sizeof(struct touch_event)); 3558c2ecf20Sopenharmony_ci if (error) { 3568c2ecf20Sopenharmony_ci dev_err(&client->dev, "Failed to read in touchpoint struct\n"); 3578c2ecf20Sopenharmony_ci goto out; 3588c2ecf20Sopenharmony_ci } 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci finger_mask = touch_event.finger_mask; 3618c2ecf20Sopenharmony_ci for_each_set_bit(i, &finger_mask, MAX_SUPPORTED_FINGER_NUM) { 3628c2ecf20Sopenharmony_ci const struct point_coord *p = &touch_event.point_coord[i]; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci /* Only process contacts that are actually reported */ 3658c2ecf20Sopenharmony_ci if (p->sub_status & SUB_BIT_EXIST) 3668c2ecf20Sopenharmony_ci zinitix_report_finger(bt541, i, p); 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci input_mt_sync_frame(bt541->input_dev); 3708c2ecf20Sopenharmony_ci input_sync(bt541->input_dev); 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ciout: 3738c2ecf20Sopenharmony_ci zinitix_write_cmd(bt541->client, BT541_CLEAR_INT_STATUS_CMD); 3748c2ecf20Sopenharmony_ci return IRQ_HANDLED; 3758c2ecf20Sopenharmony_ci} 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_cistatic int zinitix_start(struct bt541_ts_data *bt541) 3788c2ecf20Sopenharmony_ci{ 3798c2ecf20Sopenharmony_ci int error; 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci error = regulator_bulk_enable(ARRAY_SIZE(bt541->supplies), 3828c2ecf20Sopenharmony_ci bt541->supplies); 3838c2ecf20Sopenharmony_ci if (error) { 3848c2ecf20Sopenharmony_ci dev_err(&bt541->client->dev, 3858c2ecf20Sopenharmony_ci "Failed to enable regulators: %d\n", error); 3868c2ecf20Sopenharmony_ci return error; 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci msleep(CHIP_ON_DELAY); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci error = zinitix_send_power_on_sequence(bt541); 3928c2ecf20Sopenharmony_ci if (error) { 3938c2ecf20Sopenharmony_ci dev_err(&bt541->client->dev, 3948c2ecf20Sopenharmony_ci "Error while sending power-on sequence: %d\n", error); 3958c2ecf20Sopenharmony_ci return error; 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci error = zinitix_init_touch(bt541); 3998c2ecf20Sopenharmony_ci if (error) { 4008c2ecf20Sopenharmony_ci dev_err(&bt541->client->dev, 4018c2ecf20Sopenharmony_ci "Error while configuring touch IC\n"); 4028c2ecf20Sopenharmony_ci return error; 4038c2ecf20Sopenharmony_ci } 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci enable_irq(bt541->client->irq); 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci return 0; 4088c2ecf20Sopenharmony_ci} 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_cistatic int zinitix_stop(struct bt541_ts_data *bt541) 4118c2ecf20Sopenharmony_ci{ 4128c2ecf20Sopenharmony_ci int error; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci disable_irq(bt541->client->irq); 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci error = regulator_bulk_disable(ARRAY_SIZE(bt541->supplies), 4178c2ecf20Sopenharmony_ci bt541->supplies); 4188c2ecf20Sopenharmony_ci if (error) { 4198c2ecf20Sopenharmony_ci dev_err(&bt541->client->dev, 4208c2ecf20Sopenharmony_ci "Failed to disable regulators: %d\n", error); 4218c2ecf20Sopenharmony_ci return error; 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci return 0; 4258c2ecf20Sopenharmony_ci} 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_cistatic int zinitix_input_open(struct input_dev *dev) 4288c2ecf20Sopenharmony_ci{ 4298c2ecf20Sopenharmony_ci struct bt541_ts_data *bt541 = input_get_drvdata(dev); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci return zinitix_start(bt541); 4328c2ecf20Sopenharmony_ci} 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_cistatic void zinitix_input_close(struct input_dev *dev) 4358c2ecf20Sopenharmony_ci{ 4368c2ecf20Sopenharmony_ci struct bt541_ts_data *bt541 = input_get_drvdata(dev); 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci zinitix_stop(bt541); 4398c2ecf20Sopenharmony_ci} 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_cistatic int zinitix_init_input_dev(struct bt541_ts_data *bt541) 4428c2ecf20Sopenharmony_ci{ 4438c2ecf20Sopenharmony_ci struct input_dev *input_dev; 4448c2ecf20Sopenharmony_ci int error; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci input_dev = devm_input_allocate_device(&bt541->client->dev); 4478c2ecf20Sopenharmony_ci if (!input_dev) { 4488c2ecf20Sopenharmony_ci dev_err(&bt541->client->dev, 4498c2ecf20Sopenharmony_ci "Failed to allocate input device."); 4508c2ecf20Sopenharmony_ci return -ENOMEM; 4518c2ecf20Sopenharmony_ci } 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci input_set_drvdata(input_dev, bt541); 4548c2ecf20Sopenharmony_ci bt541->input_dev = input_dev; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci input_dev->name = "Zinitix Capacitive TouchScreen"; 4578c2ecf20Sopenharmony_ci input_dev->phys = "input/ts"; 4588c2ecf20Sopenharmony_ci input_dev->id.bustype = BUS_I2C; 4598c2ecf20Sopenharmony_ci input_dev->open = zinitix_input_open; 4608c2ecf20Sopenharmony_ci input_dev->close = zinitix_input_close; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X); 4638c2ecf20Sopenharmony_ci input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y); 4648c2ecf20Sopenharmony_ci input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0); 4658c2ecf20Sopenharmony_ci input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci touchscreen_parse_properties(input_dev, true, &bt541->prop); 4688c2ecf20Sopenharmony_ci if (!bt541->prop.max_x || !bt541->prop.max_y) { 4698c2ecf20Sopenharmony_ci dev_err(&bt541->client->dev, 4708c2ecf20Sopenharmony_ci "Touchscreen-size-x and/or touchscreen-size-y not set in dts\n"); 4718c2ecf20Sopenharmony_ci return -EINVAL; 4728c2ecf20Sopenharmony_ci } 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci error = input_mt_init_slots(input_dev, MAX_SUPPORTED_FINGER_NUM, 4758c2ecf20Sopenharmony_ci INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); 4768c2ecf20Sopenharmony_ci if (error) { 4778c2ecf20Sopenharmony_ci dev_err(&bt541->client->dev, 4788c2ecf20Sopenharmony_ci "Failed to initialize MT slots: %d", error); 4798c2ecf20Sopenharmony_ci return error; 4808c2ecf20Sopenharmony_ci } 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci error = input_register_device(input_dev); 4838c2ecf20Sopenharmony_ci if (error) { 4848c2ecf20Sopenharmony_ci dev_err(&bt541->client->dev, 4858c2ecf20Sopenharmony_ci "Failed to register input device: %d", error); 4868c2ecf20Sopenharmony_ci return error; 4878c2ecf20Sopenharmony_ci } 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci return 0; 4908c2ecf20Sopenharmony_ci} 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_cistatic int zinitix_ts_probe(struct i2c_client *client) 4938c2ecf20Sopenharmony_ci{ 4948c2ecf20Sopenharmony_ci struct bt541_ts_data *bt541; 4958c2ecf20Sopenharmony_ci int error; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 4988c2ecf20Sopenharmony_ci dev_err(&client->dev, 4998c2ecf20Sopenharmony_ci "Failed to assert adapter's support for plain I2C.\n"); 5008c2ecf20Sopenharmony_ci return -ENXIO; 5018c2ecf20Sopenharmony_ci } 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci bt541 = devm_kzalloc(&client->dev, sizeof(*bt541), GFP_KERNEL); 5048c2ecf20Sopenharmony_ci if (!bt541) 5058c2ecf20Sopenharmony_ci return -ENOMEM; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci bt541->client = client; 5088c2ecf20Sopenharmony_ci i2c_set_clientdata(client, bt541); 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci error = zinitix_init_regulators(bt541); 5118c2ecf20Sopenharmony_ci if (error) { 5128c2ecf20Sopenharmony_ci dev_err(&client->dev, 5138c2ecf20Sopenharmony_ci "Failed to initialize regulators: %d\n", error); 5148c2ecf20Sopenharmony_ci return error; 5158c2ecf20Sopenharmony_ci } 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci error = devm_request_threaded_irq(&client->dev, client->irq, 5188c2ecf20Sopenharmony_ci NULL, zinitix_ts_irq_handler, 5198c2ecf20Sopenharmony_ci IRQF_ONESHOT, 5208c2ecf20Sopenharmony_ci client->name, bt541); 5218c2ecf20Sopenharmony_ci if (error) { 5228c2ecf20Sopenharmony_ci dev_err(&client->dev, "Failed to request IRQ: %d\n", error); 5238c2ecf20Sopenharmony_ci return error; 5248c2ecf20Sopenharmony_ci } 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci error = zinitix_init_input_dev(bt541); 5278c2ecf20Sopenharmony_ci if (error) { 5288c2ecf20Sopenharmony_ci dev_err(&client->dev, 5298c2ecf20Sopenharmony_ci "Failed to initialize input device: %d\n", error); 5308c2ecf20Sopenharmony_ci return error; 5318c2ecf20Sopenharmony_ci } 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci error = device_property_read_u32(&client->dev, "zinitix,mode", 5348c2ecf20Sopenharmony_ci &bt541->zinitix_mode); 5358c2ecf20Sopenharmony_ci if (error < 0) { 5368c2ecf20Sopenharmony_ci /* fall back to mode 2 */ 5378c2ecf20Sopenharmony_ci bt541->zinitix_mode = DEFAULT_TOUCH_POINT_MODE; 5388c2ecf20Sopenharmony_ci } 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci if (bt541->zinitix_mode != 2) { 5418c2ecf20Sopenharmony_ci /* 5428c2ecf20Sopenharmony_ci * If there are devices that don't support mode 2, support 5438c2ecf20Sopenharmony_ci * for other modes (0, 1) will be needed. 5448c2ecf20Sopenharmony_ci */ 5458c2ecf20Sopenharmony_ci dev_err(&client->dev, 5468c2ecf20Sopenharmony_ci "Malformed zinitix,mode property, must be 2 (supplied: %d)\n", 5478c2ecf20Sopenharmony_ci bt541->zinitix_mode); 5488c2ecf20Sopenharmony_ci return -EINVAL; 5498c2ecf20Sopenharmony_ci } 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci irq_set_status_flags(client->irq, IRQ_NOAUTOEN); 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci return 0; 5548c2ecf20Sopenharmony_ci} 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_cistatic int __maybe_unused zinitix_suspend(struct device *dev) 5578c2ecf20Sopenharmony_ci{ 5588c2ecf20Sopenharmony_ci struct i2c_client *client = to_i2c_client(dev); 5598c2ecf20Sopenharmony_ci struct bt541_ts_data *bt541 = i2c_get_clientdata(client); 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci mutex_lock(&bt541->input_dev->mutex); 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci if (bt541->input_dev->users) 5648c2ecf20Sopenharmony_ci zinitix_stop(bt541); 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci mutex_unlock(&bt541->input_dev->mutex); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci return 0; 5698c2ecf20Sopenharmony_ci} 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_cistatic int __maybe_unused zinitix_resume(struct device *dev) 5728c2ecf20Sopenharmony_ci{ 5738c2ecf20Sopenharmony_ci struct i2c_client *client = to_i2c_client(dev); 5748c2ecf20Sopenharmony_ci struct bt541_ts_data *bt541 = i2c_get_clientdata(client); 5758c2ecf20Sopenharmony_ci int ret = 0; 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci mutex_lock(&bt541->input_dev->mutex); 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci if (bt541->input_dev->users) 5808c2ecf20Sopenharmony_ci ret = zinitix_start(bt541); 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci mutex_unlock(&bt541->input_dev->mutex); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci return ret; 5858c2ecf20Sopenharmony_ci} 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(zinitix_pm_ops, zinitix_suspend, zinitix_resume); 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 5908c2ecf20Sopenharmony_cistatic const struct of_device_id zinitix_of_match[] = { 5918c2ecf20Sopenharmony_ci { .compatible = "zinitix,bt541" }, 5928c2ecf20Sopenharmony_ci { } 5938c2ecf20Sopenharmony_ci}; 5948c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, zinitix_of_match); 5958c2ecf20Sopenharmony_ci#endif 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_cistatic struct i2c_driver zinitix_ts_driver = { 5988c2ecf20Sopenharmony_ci .probe_new = zinitix_ts_probe, 5998c2ecf20Sopenharmony_ci .driver = { 6008c2ecf20Sopenharmony_ci .name = "Zinitix-TS", 6018c2ecf20Sopenharmony_ci .pm = &zinitix_pm_ops, 6028c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(zinitix_of_match), 6038c2ecf20Sopenharmony_ci }, 6048c2ecf20Sopenharmony_ci}; 6058c2ecf20Sopenharmony_cimodule_i2c_driver(zinitix_ts_driver); 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ciMODULE_AUTHOR("Michael Srba <Michael.Srba@seznam.cz>"); 6088c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Zinitix touchscreen driver"); 6098c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 610