Hey Dmitry!

Thanks, I've been testing it for 2+ weeks. Works like a charm so far.

On Wed, 13 Jul 2016 12:22:47 -0700
Dmitry Torokhov <[email protected]> wrote:

> [ Resending to actually CC people I asked to try the patch ]
> 
> On Wed, Jul 13, 2016 at 09:30:29PM +0800, KT Liao wrote:
> > Fix some Asus touchapod which casue TP no funciton sometimes, the patch 
> > detect some specific touchpad and run a special initialize
> > 
> > Signed-off-by: KT Liao <[email protected]>
> > ---
> >  drivers/input/mouse/elan_i2c_core.c | 93 
> > ++++++++++++++++++++++++++++---------
> >  1 file changed, 71 insertions(+), 22 deletions(-)
> > 
> > diff --git a/drivers/input/mouse/elan_i2c_core.c 
> > b/drivers/input/mouse/elan_i2c_core.c
> > index 2f58985..36a69d2 100644
> > --- a/drivers/input/mouse/elan_i2c_core.c
> > +++ b/drivers/input/mouse/elan_i2c_core.c
> > @@ -3,8 +3,8 @@
> >   *
> >   * Copyright (c) 2013 ELAN Microelectronics Corp.
> >   *
> > - * Author: 林政維 (Duson Lin) <[email protected]>
> 
> Let's not remove Duson's name, he did quite a bit of work on the driver.
> 
> > - * Version: 1.6.0
> > + * Author: KT Liao <[email protected]>
> > + * Version: 1.6.2
> >   *
> >   * Based on cyapa driver:
> >   * copyright (c) 2011-2012 Cypress Semiconductor, Inc.
> > @@ -40,7 +40,7 @@
> >  #include "elan_i2c.h"
> >  
> >  #define DRIVER_NAME                "elan_i2c"
> > -#define ELAN_DRIVER_VERSION        "1.6.1"
> > +#define ELAN_DRIVER_VERSION        "1.6.2"
> >  #define ELAN_VENDOR_ID             0x04f3
> >  #define ETP_MAX_PRESSURE   255
> >  #define ETP_FWIDTH_REDUCE  90
> > @@ -95,6 +95,8 @@ struct elan_tp_data {
> >     bool                    baseline_ready;
> >  };
> >  
> > +static int check_ASUS_special_fw(struct elan_tp_data *data);
> > +
> >  static int elan_get_fwinfo(u8 iap_version, u16 *validpage_count,
> >                        u16 *signature_address)
> >  {
> > @@ -210,21 +212,40 @@ static int __elan_initialize(struct elan_tp_data 
> > *data)
> >             return error;
> >     }
> >  
> > -   data->mode |= ETP_ENABLE_ABS;
> > -   error = data->ops->set_mode(client, data->mode);
> > -   if (error) {
> > -           dev_err(&client->dev,
> > -                   "failed to switch to absolute mode: %d\n", error);
> > -           return error;
> > -   }
> > +   /* If it's the special FW, it need a different flow for mode change.*/
> > +   if (check_ASUS_special_fw(data)) {
> > +           error = data->ops->sleep_control(client, false);
> > +           if (error) {
> > +                   dev_err(&client->dev,
> > +                           "failed to wake device up: %d\n", error);
> > +                   return error;
> > +           }
> >  
> > -   error = data->ops->sleep_control(client, false);
> > -   if (error) {
> > -           dev_err(&client->dev,
> > -                   "failed to wake device up: %d\n", error);
> > -           return error;
> > -   }
> > +           msleep(200);
> >  
> > +           data->mode |= ETP_ENABLE_ABS;
> > +           error = data->ops->set_mode(client, data->mode);
> > +           if (error) {
> > +                   dev_err(&client->dev,
> > +                           "failed to switch to absolute mode: %d\n", 
> > error);
> > +                   return error;
> > +           }
> > +   } else {
> > +           data->mode |= ETP_ENABLE_ABS;
> > +           error = data->ops->set_mode(client, data->mode);
> > +           if (error) {
> > +                   dev_err(&client->dev,
> > +                           "failed to switch to absolute mode: %d\n", 
> > error);
> > +                   return error;
> > +           }
> > +
> > +           error = data->ops->sleep_control(client, false);
> > +           if (error) {
> > +                   dev_err(&client->dev,
> > +                           "failed to wake device up: %d\n", error);
> > +                   return error;
> > +           }
> > +   }
> >     return 0;
> >  }
> >  
> > @@ -244,7 +265,7 @@ static int elan_initialize(struct elan_tp_data *data)
> >     return error;
> >  }
> >  
> > -static int elan_query_device_info(struct elan_tp_data *data)
> > +static int elan_query_device_pid_smver(struct elan_tp_data *data)
> >  {
> >     int error;
> >  
> > @@ -252,17 +273,24 @@ static int elan_query_device_info(struct elan_tp_data 
> > *data)
> >     if (error)
> >             return error;
> >  
> > -   error = data->ops->get_version(data->client, false, &data->fw_version);
> > +   error = data->ops->get_sm_version(data->client, &data->ic_type,
> > +                                     &data->sm_version);
> >     if (error)
> >             return error;
> >  
> > -   error = data->ops->get_checksum(data->client, false,
> > -                                   &data->fw_checksum);
> > +   return 0;
> > +}
> > +
> > +static int elan_query_device_info(struct elan_tp_data *data)
> > +{
> > +   int error;
> > +
> > +   error = data->ops->get_version(data->client, false, &data->fw_version);
> >     if (error)
> >             return error;
> >  
> > -   error = data->ops->get_sm_version(data->client, &data->ic_type,
> > -                                     &data->sm_version);
> > +   error = data->ops->get_checksum(data->client, false,
> > +                                   &data->fw_checksum);
> >     if (error)
> >             return error;
> >  
> > @@ -419,6 +447,7 @@ static int elan_update_firmware(struct elan_tp_data 
> > *data,
> >             data->ops->iap_reset(client);
> >     } else {
> >             /* Reinitialize TP after fw is updated */
> > +           elan_query_device_pid_smver(data);
> >             elan_initialize(data);
> >             elan_query_device_info(data);
> >     }
> > @@ -757,6 +786,22 @@ out:
> >     return retval;
> >  }
> >  
> > +static int check_ASUS_special_fw(struct elan_tp_data *data)
> > +{
> > +   if (data->ic_type != 0x0E)
> > +           return false;
> > +
> > +   switch (data->product_id) {
> > +   case 0x05:
> > +   case 0x06:
> > +   case 0x07:
> > +   case 0x09:
> > +   case 0x013:
> > +           return true;
> > +   default:
> > +           return false;
> > +   }
> > +}
> >  
> >  static DEVICE_ATTR_WO(acquire);
> >  static DEVICE_ATTR_RO(min);
> > @@ -1033,6 +1078,10 @@ static int elan_probe(struct i2c_client *client,
> >             return error;
> >     }
> >  
> > +   error = elan_query_device_pid_smver(data);
> > +   if (error)
> > +           return error;
> 
> The original code was fetching product ID and IC type after calling the
> transport "initialize" function; I'd prefer if we kept this order.
> 
> Could you tell me if the following version of the patch looks OK to you?
> 
> Vlad, Chris, Jonathan, could you please tell me if this version of the
> patch fixes your touchpad issue?
> 
> Thanks!
> 
> -- 
> Dmitry
> 
> 
> Input: elan_i2c - properly wake up touchpad on ASUS laptops
> 
> From: KT Liao <[email protected]>
> 
> Some ASUS laptops were shipped with touchpads that require to be woken up
> first, before trying to switch them into absolute reporting mode, otherwise
> touchpad would fail to work while flooding the logs with:
> 
>       elan_i2c i2c-ELAN1000:00: invalid report id data (1)
> 
> Among affected devices are Asus E202SA, N552VW, X456UF, UX305CA, and
> others. We detect such devices by checking the IC type and product ID
> numbers and adjusting order of operations accordingly.
> 
> Signed-off-by: KT Liao <[email protected]>
> Reported-by: Chris Chiu <[email protected]>
> Reported-by: Vlad Glagolev <[email protected]>
> Cc: [email protected]
> Signed-off-by: Dmitry Torokhov <[email protected]>
> ---
>  drivers/input/mouse/elan_i2c_core.c |   79 
> ++++++++++++++++++++++++++++-------
>  1 file changed, 63 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/input/mouse/elan_i2c_core.c 
> b/drivers/input/mouse/elan_i2c_core.c
> index 2f58985..d15b338 100644
> --- a/drivers/input/mouse/elan_i2c_core.c
> +++ b/drivers/input/mouse/elan_i2c_core.c
> @@ -4,7 +4,8 @@
>   * Copyright (c) 2013 ELAN Microelectronics Corp.
>   *
>   * Author: 林政維 (Duson Lin) <[email protected]>
> - * Version: 1.6.0
> + * Author: KT Liao <[email protected]>
> + * Version: 1.6.2
>   *
>   * Based on cyapa driver:
>   * copyright (c) 2011-2012 Cypress Semiconductor, Inc.
> @@ -40,7 +41,7 @@
>  #include "elan_i2c.h"
>  
>  #define DRIVER_NAME          "elan_i2c"
> -#define ELAN_DRIVER_VERSION  "1.6.1"
> +#define ELAN_DRIVER_VERSION  "1.6.2"
>  #define ELAN_VENDOR_ID               0x04f3
>  #define ETP_MAX_PRESSURE     255
>  #define ETP_FWIDTH_REDUCE    90
> @@ -199,9 +200,41 @@ static int elan_sleep(struct elan_tp_data *data)
>       return error;
>  }
>  
> +static int elan_query_product(struct elan_tp_data *data)
> +{
> +     int error;
> +
> +     error = data->ops->get_product_id(data->client, &data->product_id);
> +     if (error)
> +             return error;
> +
> +     error = data->ops->get_sm_version(data->client, &data->ic_type,
> +                                       &data->sm_version);
> +     if (error)
> +             return error;
> +
> +     return 0;
> +}
> +
> +static int elan_check_ASUS_special_fw(struct elan_tp_data *data)
> +{
> +     if (data->ic_type != 0x0E)
> +             return false;
> +
> +     switch (data->product_id) {
> +     case 0x05 ... 0x07:
> +     case 0x09:
> +     case 0x13:
> +             return true;
> +     default:
> +             return false;
> +     }
> +}
> +
>  static int __elan_initialize(struct elan_tp_data *data)
>  {
>       struct i2c_client *client = data->client;
> +     bool woken_up = false;
>       int error;
>  
>       error = data->ops->initialize(client);
> @@ -210,6 +243,27 @@ static int __elan_initialize(struct elan_tp_data *data)
>               return error;
>       }
>  
> +     error = elan_query_product(data);
> +     if (error)
> +             return error;
> +
> +     /*
> +      * Some ASUS devices were shipped with firmware that requires
> +      * touchpads to be woken up first, before attempting to switch
> +      * them into absolute reporting mode.
> +      */
> +     if (elan_check_ASUS_special_fw(data)) {
> +             error = data->ops->sleep_control(client, false);
> +             if (error) {
> +                     dev_err(&client->dev,
> +                             "failed to wake device up: %d\n", error);
> +                     return error;
> +             }
> +
> +             msleep(200);
> +             woken_up = true;
> +     }
> +
>       data->mode |= ETP_ENABLE_ABS;
>       error = data->ops->set_mode(client, data->mode);
>       if (error) {
> @@ -218,11 +272,13 @@ static int __elan_initialize(struct elan_tp_data *data)
>               return error;
>       }
>  
> -     error = data->ops->sleep_control(client, false);
> -     if (error) {
> -             dev_err(&client->dev,
> -                     "failed to wake device up: %d\n", error);
> -             return error;
> +     if (!woken_up) {
> +             error = data->ops->sleep_control(client, false);
> +             if (error) {
> +                     dev_err(&client->dev,
> +                             "failed to wake device up: %d\n", error);
> +                     return error;
> +             }
>       }
>  
>       return 0;
> @@ -248,10 +304,6 @@ static int elan_query_device_info(struct elan_tp_data 
> *data)
>  {
>       int error;
>  
> -     error = data->ops->get_product_id(data->client, &data->product_id);
> -     if (error)
> -             return error;
> -
>       error = data->ops->get_version(data->client, false, &data->fw_version);
>       if (error)
>               return error;
> @@ -261,11 +313,6 @@ static int elan_query_device_info(struct elan_tp_data 
> *data)
>       if (error)
>               return error;
>  
> -     error = data->ops->get_sm_version(data->client, &data->ic_type,
> -                                       &data->sm_version);
> -     if (error)
> -             return error;
> -
>       error = data->ops->get_version(data->client, true, &data->iap_version);
>       if (error)
>               return error;


--
Vlad Glagolev <[email protected]>

Attachment: pgpsF_bfYeZNf.pgp
Description: PGP signature

Reply via email to