[PATCH 3/3] Input: mms114 - add support for mms345l

From: Stephan Gerhold
Date: Mon Oct 07 2019 - 16:51:44 EST


MMS345L is another first generation touch screen from Melfas,
which uses the same registers as MMS152.

However, using I2C_M_NOSTART for it causes errors when reading:

i2c i2c-0: sendbytes: NAK bailout.
mms114 0-0048: __mms114_read_reg: i2c transfer failed (-5)

The driver works fine as soon as I2C_M_NOSTART is removed.

Add a separate melfas,mms345l binding, and make use of I2C_M_NOSTART
only for MMS114 and MMS152.

Signed-off-by: Stephan Gerhold <stephan@xxxxxxxxxxx>
---
Note: I was not able to find a datasheet for any of the models,
so this change is merely based on testing and comparison with
the downstream driver [1].

There was a related patch [2] that removes I2C_M_NOSTART for all models,
but it seems abandoned and I do not have any other model for testing.
Therefore, this patch implements the least instrusive solution
and only removes I2C_M_NOSTART for MMS345L.

[1]: https://github.com/msm8916-mainline/android_kernel_qcom_msm8916/blob/SM-A500FU/drivers/input/touchscreen/mms300_a.c
[2]: https://patchwork.kernel.org/patch/10189541/
---
drivers/input/touchscreen/mms114.c | 43 +++++++++++++++++++++---------
1 file changed, 31 insertions(+), 12 deletions(-)

diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c
index 69c6d559eeb0..d9f45755d073 100644
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -54,6 +54,7 @@
enum mms_type {
TYPE_MMS114 = 114,
TYPE_MMS152 = 152,
+ TYPE_MMS345L = 345,
};

struct mms114_data {
@@ -91,9 +92,14 @@ static int __mms114_read_reg(struct mms114_data *data, unsigned int reg,
if (reg <= MMS114_MODE_CONTROL && reg + len > MMS114_MODE_CONTROL)
BUG();

- /* Write register: use repeated start */
+ /* Write register */
xfer[0].addr = client->addr;
- xfer[0].flags = I2C_M_TEN | I2C_M_NOSTART;
+ if (data->type != TYPE_MMS345L)
+ /* use repeated start */
+ xfer[0].flags = I2C_M_TEN | I2C_M_NOSTART;
+ else
+ xfer[0].flags = client->flags & I2C_M_TEN;
+
xfer[0].len = 1;
xfer[0].buf = &buf;

@@ -250,6 +256,15 @@ static int mms114_get_version(struct mms114_data *data)
int error;

switch (data->type) {
+ case TYPE_MMS345L:
+ error = __mms114_read_reg(data, MMS152_FW_REV, 3, buf);
+ if (error)
+ return error;
+
+ dev_info(dev, "TSP FW Rev: bootloader 0x%x / core 0x%x / config 0x%x\n",
+ buf[0], buf[1], buf[2]);
+ break;
+
case TYPE_MMS152:
error = __mms114_read_reg(data, MMS152_FW_REV, 3, buf);
if (error)
@@ -287,8 +302,8 @@ static int mms114_setup_regs(struct mms114_data *data)
if (error < 0)
return error;

- /* MMS152 has no configuration or power on registers */
- if (data->type == TYPE_MMS152)
+ /* Only MMS114 has configuration and power on registers */
+ if (data->type != TYPE_MMS114)
return 0;

error = mms114_set_active(data, true);
@@ -425,11 +440,16 @@ static int mms114_probe(struct i2c_client *client,
{
struct mms114_data *data;
struct input_dev *input_dev;
- const void *match_data;
+ enum mms_type type;
int error;

- if (!i2c_check_functionality(client->adapter,
- I2C_FUNC_PROTOCOL_MANGLING)) {
+ type = (enum mms_type)device_get_match_data(&client->dev);
+ if (!type)
+ return -EINVAL;
+
+ if (type != TYPE_MMS345L &&
+ !i2c_check_functionality(client->adapter,
+ I2C_FUNC_PROTOCOL_MANGLING)) {
dev_err(&client->dev,
"Need i2c bus that supports protocol mangling\n");
return -ENODEV;
@@ -446,11 +466,7 @@ static int mms114_probe(struct i2c_client *client,
data->client = client;
data->input_dev = input_dev;

- match_data = device_get_match_data(&client->dev);
- if (!match_data)
- return -EINVAL;
-
- data->type = (enum mms_type)match_data;
+ data->type = type;

input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X);
input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y);
@@ -599,6 +615,9 @@ static const struct of_device_id mms114_dt_match[] = {
}, {
.compatible = "melfas,mms152",
.data = (void *)TYPE_MMS152,
+ }, {
+ .compatible = "melfas,mms345l",
+ .data = (void *)TYPE_MMS345L,
},
{ }
};
--
2.23.0