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 <[email protected]>
---
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

Reply via email to