Hi Rafael,

Could you help give some advice on how to apply the function to put the 
trackpad device into low power mode with LID in current kernel?
or it's just a policy and should not be submitted to kernel right now?

Thanks,
Dudley

>
> -----Original Message-----
> From: Dmitry Torokhov [mailto:dmitry.torok...@gmail.com]
> Sent: Tuesday, May 20, 2014 11:43 AM
> To: Dudley Du
> Cc: Benson Leung; Daniel Kurtz; David Solda; linux-in...@vger.kernel.org; 
> linux-kernel@vger.kernel.org
> Subject: Re: [PATCH 4/6] input: cyapa: enable/disable trackpad device based 
> on LID state
>
> Hi Dudley,
>
> On Wed, Apr 16, 2014 at 08:39:34AM +0000, Dudley Du wrote:
> > Rely on EV_SW and SW_LID bits to identify a LID device, and hook up
> > our filter to listen for SW_LID events to enable/disable touchpad when
> > LID is open/closed.
> > TEST=test on Chomebooks.
>
> This is a policy and it does not belong in the kernel. Please work with 
> Rafael to establish generic interface to put devices into low power mode 
> (like accelerating runtime PM idle timeout) and use it when userspace detects 
> that lid is closed.
>
> Thanks.
>
> >
> > Signed-off-by: Du, Dudley <d...@cypress.com>
> > ---
> > diff --git a/drivers/input/mouse/cyapa.c b/drivers/input/mouse/cyapa.c
> > index 6820b3f..da03427 100644
> > --- a/drivers/input/mouse/cyapa.c
> > +++ b/drivers/input/mouse/cyapa.c
> > @@ -523,6 +523,9 @@ struct cyapa {
> >         int physical_size_x;
> >         int physical_size_y;
> >
> > +       bool lid_handler_registered;
> > +       struct input_handler lid_handler;
> > +
> >         /* used in ttsp and truetouch based trackpad devices. */
> >         u8 x_origin;  /* X Axis Origin: 0 = left side; 1 = rigth side. */
> >         u8 y_origin;  /* Y Axis Origin: 0 = top; 1 = bottom. */ @@
> > -3107,6 +3110,125 @@ static void cyapa_start_runtime(struct cyapa
> > *cyapa)  static void cyapa_start_runtime(struct cyapa *cyapa) {}
> > #endif /* CONFIG_PM_RUNTIME */
> >
> > +
> > +/*
> > + * We rely on EV_SW and SW_LID bits to identify a LID device, and
> > +hook
> > + * up our filter to listen for SW_LID events to enable/disable
> > +touchpad when
> > + * LID is open/closed.
> > + */
> > +static const struct input_device_id lid_device_ids[] = {
> > +       {
> > +               .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
> > +                        INPUT_DEVICE_ID_MATCH_SWBIT,
> > +               .evbit = { BIT_MASK(EV_SW) },
> > +               .swbit = { BIT_MASK(SW_LID) },
> > +       },
> > +       { },
> > +};
> > +
> > +static int lid_device_connect(struct input_handler *handler,
> > +                             struct input_dev *dev,
> > +                             const struct input_device_id *id) {
> > +       struct input_handle *lid_handle;
> > +       int error;
> > +
> > +       lid_handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
> > +       if (!lid_handle)
> > +               return -ENOMEM;
> > +
> > +       lid_handle->dev = dev;
> > +       lid_handle->handler = handler;
> > +       lid_handle->name = "lid_event_handler";
> > +       lid_handle->private = handler->private;
> > +
> > +       error = input_register_handle(lid_handle);
> > +       if (error)
> > +               goto err_free;
> > +
> > +       error = input_open_device(lid_handle);
> > +       if (error)
> > +               goto err_unregister;
> > +
> > +       return 0;
> > +err_unregister:
> > +       input_unregister_handle(lid_handle);
> > +err_free:
> > +       kfree(lid_handle);
> > +       return error;
> > +}
> > +
> > +static void lid_device_disconnect(struct input_handle *handle) {
> > +       input_close_device(handle);
> > +       input_unregister_handle(handle);
> > +       kfree(handle);
> > +}
> > +
> > +static bool lid_event_filter(struct input_handle *handle,
> > +                            unsigned int type, unsigned int code, int
> > +value) {
> > +       struct cyapa *cyapa = handle->private;
> > +       struct device *dev = &cyapa->client->dev;
> > +
> > +       if (type == EV_SW && code == SW_LID) {
> > +               if (cyapa->suspended) {
> > +                       /*
> > +                        * If the lid event filter is called while 
> > suspended,
> > +                        * there is no guarantee that the underlying i2cs 
> > are
> > +                        * resumed at this point, so it is not safe to issue
> > +                        * the command to change power modes.
> > +                        * Instead, rely on cyapa_resume to set us back to
> > +                        * PWR_MODE_FULL_ACTIVE.
> > +                        */
> > +                       return false;
> > +               }
> > +               if (value == 0) {
> > +                       if (cyapa->cyapa_set_power_mode)
> > +                               cyapa->cyapa_set_power_mode(cyapa,
> > +                                               PWR_MODE_FULL_ACTIVE, 0);
> > +                       pm_runtime_set_active(dev);
> > +                       pm_runtime_enable(dev);
> > +               } else {
> > +                       pm_runtime_disable(dev);
> > +                       if (cyapa->cyapa_set_power_mode)
> > +                               cyapa->cyapa_set_power_mode(cyapa,
> > +                                               PWR_MODE_OFF, 0);
> > +               }
> > +       }
> > +
> > +       return false;
> > +}
> > +
> > +static void lid_event_register_handler(struct cyapa *cyapa) {
> > +       int error;
> > +       struct input_handler *lid_handler = &cyapa->lid_handler;
> > +
> > +       if (cyapa->lid_handler_registered)
> > +               return;
> > +
> > +       lid_handler->filter     = lid_event_filter;
> > +       lid_handler->connect    = lid_device_connect;
> > +       lid_handler->disconnect = lid_device_disconnect;
> > +       lid_handler->name       = "cyapa_lid_event_handler";
> > +       lid_handler->id_table   = lid_device_ids;
> > +       lid_handler->private    = cyapa;
> > +
> > +       error = input_register_handler(lid_handler);
> > +       if (error)
> > +               return;
> > +       cyapa->lid_handler_registered = true; }
> > +
> > +static void lid_event_unregister_handler(struct cyapa *cyapa) {
> > +       if (cyapa->lid_handler_registered) {
> > +               input_unregister_handler(&cyapa->lid_handler);
> > +               cyapa->lid_handler_registered = false;
> > +       }
> > +}
> > +
> >  static void cyapa_detect_async(void *data, async_cookie_t cookie)  {
> >         struct cyapa *cyapa = (struct cyapa *)data; @@ -3126,6 +3248,7
> > @@ static void cyapa_detect_and_start(void *data, async_cookie_t cookie)
> >         cyapa_detect_async(data, cookie);
> >
> >         cyapa_start_runtime(cyapa);
> > +       lid_event_register_handler(cyapa);
> >  }
> >
> >  static int cyapa_probe(struct i2c_client *client, @@ -3221,7 +3344,7
> > @@ static int cyapa_remove(struct i2c_client *client)
> >
> >         free_irq(cyapa->irq, cyapa);
> >         input_unregister_device(cyapa->input);
> > -
> > +       lid_event_unregister_handler(cyapa);
> >         if (cyapa->cyapa_set_power_mode)
> >                 cyapa->cyapa_set_power_mode(cyapa, PWR_MODE_OFF, 0);
> >         i2c_set_clientdata(client, NULL); This message and any
> > attachments may contain Cypress (or its subsidiaries) confidential 
> > information. If it has been received in error, please advise the sender and 
> > immediately delete this message.
>
> --
> Dmitry
This message and any attachments may contain Cypress (or its subsidiaries) 
confidential information. If it has been received in error, please advise the 
sender and immediately delete this message.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to