Skip to content

Commit

Permalink
input: elants: read touchscreen size for EKTF3624
Browse files Browse the repository at this point in the history
EKTF3624 as present in Asus TF300T tablet has touchscreen size encoded
in different registers.

Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
Tested-by: Dmitry Osipenko <digetx@gmail.com>
  • Loading branch information
osctobe authored and intel-lab-lkp committed Sep 19, 2020
1 parent dc6c6a5 commit 394cc41
Showing 1 changed file with 79 additions and 5 deletions.
84 changes: 79 additions & 5 deletions drivers/input/touchscreen/elants_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,18 @@
#include <linux/input/mt.h>
#include <linux/input/touchscreen.h>
#include <linux/acpi.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/gpio/consumer.h>
#include <linux/regulator/consumer.h>
#include <asm/unaligned.h>

/* Device, Driver information */
#define DEVICE_NAME "elants_i2c"

/* Device IDs */
#define EKTH3500 0
#define EKTF3624 1

/* Convert from rows or columns into resolution */
#define ELAN_TS_RESOLUTION(n, m) (((n) - 1) * (m))

Expand Down Expand Up @@ -94,6 +98,8 @@
#define E_ELAN_INFO_REK 0xD0
#define E_ELAN_INFO_TEST_VER 0xE0
#define E_ELAN_INFO_FW_ID 0xF0
#define E_INFO_X_RES 0x60
#define E_INFO_Y_RES 0x63
#define E_INFO_OSR 0xD6
#define E_INFO_PHY_SCAN 0xD7
#define E_INFO_PHY_DRIVER 0xD8
Expand Down Expand Up @@ -157,6 +163,7 @@ struct elants_data {

bool wake_irq_enabled;
bool keep_power_in_suspend;
u8 chip_id;

/* Must be last to be used for DMA operations */
u8 buf[MAX_PACKET_SIZE] ____cacheline_aligned;
Expand Down Expand Up @@ -434,7 +441,58 @@ static int elants_i2c_query_bc_version(struct elants_data *ts)
return 0;
}

static int elants_i2c_query_ts_info(struct elants_data *ts)
static int elants_i2c_query_ts_info_ektf(struct elants_data *ts)
{
struct i2c_client *client = ts->client;
int error;
u8 resp[4];
u16 phy_x, phy_y;
const u8 get_xres_cmd[] = {
CMD_HEADER_READ, E_INFO_X_RES, 0x00, 0x00
};
const u8 get_yres_cmd[] = {
CMD_HEADER_READ, E_INFO_Y_RES, 0x00, 0x00
};

/* Get X/Y size in mm */
error = elants_i2c_execute_command(client, get_xres_cmd,
sizeof(get_xres_cmd),
resp, sizeof(resp), 1,
"get X size");
if (error)
return error;

phy_x = resp[2] | ((resp[3] & 0xF0) << 4);

error = elants_i2c_execute_command(client, get_yres_cmd,
sizeof(get_yres_cmd),
resp, sizeof(resp), 1,
"get Y size");
if (error)
return error;

phy_y = resp[2] | ((resp[3] & 0xF0) << 4);

if (!phy_x || !phy_y) {
dev_warn(&client->dev,
"invalid size data: %d x %d mm\n",
phy_x, phy_y);
return 0;
}

dev_dbg(&client->dev, "phy_x=%d, phy_y=%d\n", phy_x, phy_y);

/* calculate resolution from size */
ts->x_max = 2240-1;
ts->x_res = DIV_ROUND_CLOSEST(ts->prop.max_x, phy_x);

ts->y_max = 1408-1;
ts->y_res = DIV_ROUND_CLOSEST(ts->prop.max_y, phy_y);

return 0;
}

static int elants_i2c_query_ts_info_ekth(struct elants_data *ts)
{
struct i2c_client *client = ts->client;
int error;
Expand Down Expand Up @@ -588,8 +646,20 @@ static int elants_i2c_initialize(struct elants_data *ts)
error = elants_i2c_query_fw_version(ts);
if (!error)
error = elants_i2c_query_test_version(ts);
if (!error)
error = elants_i2c_query_ts_info(ts);

switch (ts->chip_id) {
case EKTH3500:
if (!error)
error = elants_i2c_query_ts_info_ekth(ts);
break;
case EKTF3624:
if (!error)
error = elants_i2c_query_ts_info_ektf(ts);
break;
default:
unreachable();
break;
}

if (error)
ts->iap_mode = ELAN_IAP_RECOVERY;
Expand Down Expand Up @@ -1266,6 +1336,9 @@ static int elants_i2c_probe(struct i2c_client *client,
ts->client = client;
i2c_set_clientdata(client, ts);

if (client->dev.of_node)
ts->chip_id = (uintptr_t)of_device_get_match_data(&client->dev);

ts->vcc33 = devm_regulator_get(&client->dev, "vcc33");
if (IS_ERR(ts->vcc33)) {
error = PTR_ERR(ts->vcc33);
Expand Down Expand Up @@ -1495,7 +1568,8 @@ MODULE_DEVICE_TABLE(acpi, elants_acpi_id);

#ifdef CONFIG_OF
static const struct of_device_id elants_of_match[] = {
{ .compatible = "elan,ekth3500" },
{ .compatible = "elan,ekth3500", .data = (void *)EKTH3500 },
{ .compatible = "elan,ektf3624", .data = (void *)EKTF3624 },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, elants_of_match);
Expand Down

0 comments on commit 394cc41

Please sign in to comment.