Re: [PATCH 3/4] Input: icn8318 - Add support for ACPI enumeration

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Jun 18 2017 or thereabouts, Hans de Goede wrote:
> Hi,
> 
> On 17-06-17 22:09, Hans de Goede wrote:
> > Hi,
> > 
> > Self-nack see comment inline.
> > 
> > On 17-06-17 12:58, Hans de Goede wrote:
> > > The icn8505 variant is found on some x86 tablets, which use ACPI
> > > enumeration, add support for ACPI enumeration.
> > > 
> > > Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx>
> > > ---
> > >   drivers/input/touchscreen/Kconfig           |  2 +-
> > >   drivers/input/touchscreen/chipone_icn8318.c | 67 ++++++++++++++++++++++++++++-
> > >   2 files changed, 67 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
> > > index fff1467506e7..e3b52d356e13 100644
> > > --- a/drivers/input/touchscreen/Kconfig
> > > +++ b/drivers/input/touchscreen/Kconfig
> > > @@ -155,7 +155,7 @@ config TOUCHSCREEN_CHIPONE_ICN8318
> > >       tristate "chipone icn8318 touchscreen controller"
> > >       depends on GPIOLIB || COMPILE_TEST
> > >       depends on I2C
> > > -    depends on OF
> > > +    depends on OF || ACPI
> > >       help
> > >         Say Y here if you have a ChipOne icn8318 or icn8505 based
> > >         I2C touchscreen.
> > > diff --git a/drivers/input/touchscreen/chipone_icn8318.c b/drivers/input/touchscreen/chipone_icn8318.c
> > > index 993df804883f..b209872954f7 100644
> > > --- a/drivers/input/touchscreen/chipone_icn8318.c
> > > +++ b/drivers/input/touchscreen/chipone_icn8318.c
> > > @@ -12,6 +12,7 @@
> > >    * Hans de Goede <hdegoede@xxxxxxxxxx>
> > >    */
> > > +#include <linux/acpi.h>
> > >   #include <linux/gpio/consumer.h>
> > >   #include <linux/interrupt.h>
> > >   #include <linux/i2c.h>
> > > @@ -232,6 +233,66 @@ static int icn8318_probe_of(struct icn8318_data *data, struct device *dev)
> > >   }
> > >   #endif
> > > +#ifdef CONFIG_ACPI
> > > +static const struct acpi_device_id icn8318_acpi_match[] = {
> > > +    { "CHPN0001", ICN8505 },
> > > +    { }
> > > +};
> > > +MODULE_DEVICE_TABLE(acpi, icn8318_acpi_match);
> > > +
> > > +static int icn8318_probe_acpi(struct icn8318_data *data, struct device *dev)
> > > +{
> > > +    struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
> > > +    struct input_dev *input = data->input;
> > > +    const struct acpi_device_id *id;
> > > +    struct acpi_device *adev;
> > > +    acpi_status status;
> > > +    const char *sub;
> > > +
> > > +    adev = ACPI_COMPANION(dev);
> > > +    id = acpi_match_device(icn8318_acpi_match, dev);
> > > +    if (!adev || !id)
> > > +        return -ENODEV;
> > > +
> > > +    data->model = id->driver_data;
> > > +
> > > +    /* The _SUB ACPI object describes the touchscreen model */
> > > +    status = acpi_evaluate_object_typed(adev->handle, "_SUB", NULL,
> > > +                        &buf, ACPI_TYPE_STRING);
> > > +    if (ACPI_FAILURE(status)) {
> > > +        dev_err(dev, "ACPI _SUB object not found\n");
> > > +        return -ENODEV;
> > > +    }
> > > +    sub = ((union acpi_object *)buf.pointer)->string.pointer;
> > > +
> > > +    if (strcmp(sub, "HAMP0002") == 0) {
> > > +        input_set_abs_params(input, ABS_MT_POSITION_X, 0, 1199, 0, 0);
> > > +        input_set_abs_params(input, ABS_MT_POSITION_Y, 0, 1919, 0, 0);
> > > +    } else {
> > > +        dev_err(dev, "Unknown model _SUB: %s\n", sub);
> > > +        kfree(buf.pointer);
> > > +        return -ENODEV;
> > > +    }
> > > +    kfree(buf.pointer);
> > > +
> > > +    /*
> > > +     * Disable ACPI power management the _PS3 method is empty, so
> > > +     * there is no powersaving when using ACPI power management.
> > > +     * The _PS0 method resets the controller causing it to loose its
> > > +     * firmware, which has been loaded by the BIOS and we do not
> > > +     * know how to restore the firmware.
> > > +     */
> > > +    adev->flags.power_manageable = 0;
> > 
> > Ok, so unfortunately this is not that easy :|  The ACPI node
> > has a _CID, "PNP0C50" causing i2c-hid to bind, even though the
> > device has its own device specific protocol. I had i2c-hid
> > blacklisted for testing, with the plan to add a quirk to it for this
> > device, but with the quirk if i2c-hid loads earlier then the icn8318
> > driver and i2c-hid's probe returns -ENODEV due to the quirk, the
> > device gets turned off by the ACPI core, causing a reset + loss
> > of the loaded firmware when the icn8313 driver loads. So there
> > are 2 solutions here:
> > 
> > 1) Set adev->flags.power_manageable earlier, somewhere in the
> > ACPI core
> > 
> > 2) Figure out how to load the firmware to make the controller
> > functional again
> 
> While working on a 3th option, I did a web-search for "CHPN0001"
> instead of for icn8505 which found me this:
> 
> https://github.com/Dax89/chuwi-dev/tree/master/drivers/chipone_ts
> 
> Which seemed to be based on the same android code as I already
> found, but which claims to have firmware loading working again,
> so assuming that is true (I've not tested) that gives is us
> 2 options, either avoid the controller reset, or load the
> firmware.
> 
> As said I've been working on a 3th option:
> 
> 3) Still add a quirk to i2c-hid but do the check at module_init
> time, rather then add probe time, so that the i2c-hid driver never
> registers avoiding the problem of the APCI PS3 / PS0 methods
> getting called after the failed i2c-hid probe / before the icn8318
> probe.
> 
> I've implemented this now and it works well. Although not pretty, it
> is only 2 lines of code (and a 5 line block comment), so I hope that
> Jiri and Benjamin can live with this.
> 
> 
> I personally prefer this 3th option (avoiding controller reset)
> over adding firmware upload support for 3 reasons:
> 
> 1) It is a lot less code it requires the following in i2c-hid:
> 
>  static int __init i2c_hid_init(void)
>  {
> +       /*
> +        * The CHPN0001 ACPI device has a _CID of PNP0C50 but is not HID
> +        * compatible, just probing it puts the device in an unusable state due
> +        * to it also have ACPI power management issues.
> +        */
> +       if (acpi_dev_present("CHPN0001", NULL, -1))
> +               return -ENODEV;
> +
>         return i2c_add_driver(&i2c_hid_driver);
>  }

I am not a big fan of this for several reasons (most can be worked
around):
- it's a hack for a specific device and is not generic enough
- it prevents i2c-hid to be loaded on a platform that exports such
  device, even if other devices are legitimately using i2c-hid
- what if the chipone_icn8318 is not compiled in? Or in other words,
  does the touchscreen works somehow with i2c-hid?

I think the biggest issue is that you are blacklisting a driver based on
a single peripheral while other devices might want to use it.

I have a couple of questions for you:
- is the device working with i2c-hid (in degraded mode)?
- assuming the devices works with i2c-hid, will an rmmod/modprobe of
  hid-generic/hid-chipony-icn8318 (to be written) introduce the PS3/PS0
  issues?

If both are yes, I think we better have a hid specific driver for it
(which could reuse part of the current input driver).

Cheers,
Benjamin


> 
> And the following in the icn8318 code:
> 
>         /*
>          * Disable ACPI power management the _PS3 method is empty, so
>          * there is no powersaving when using ACPI power management.
>          * The _PS0 method resets the controller causing it to loose its
>          * firmware, which has been loaded by the BIOS and we do not
>          * know how to restore the firmware.
>          */
>         adev->flags.power_manageable = 0;
> 
> Versus significantly more code to get firmware uploading to work
> 
> 2) It avoids the need for users to get their controller firmware
> from somewhere, it likely is going to be hard to get permission to
> add this to linux-firmware, so this is going to be a real issue for
> users
> 
> 3) Much faster resume, the firmware is 40k, uploading that over
> i2c at 100Khz takes multiple seconds.
> 
> So I'm going to post the i2c-hid changes and see what
> Jiri and Benjamin think of those and then we will see
> from there.
> 
> Regards,
> 
> Hans
> 
> 
> 
> 
> > 
> > Regards,
> > 
> > Hans
> > 
> > 
> > > +
> > > +    return 0;
> > > +}
> > > +#else
> > > +static int icn8318_probe_acpi(struct icn8318_data *data, struct device *dev)
> > > +{
> > > +    return -ENODEV;
> > > +}
> > > +#endif
> > > +
> > >   static int icn8318_probe(struct i2c_client *client)
> > >   {
> > >       struct device *dev = &client->dev;
> > > @@ -264,7 +325,10 @@ static int icn8318_probe(struct i2c_client *client)
> > >       input_set_capability(input, EV_ABS, ABS_MT_POSITION_X);
> > >       input_set_capability(input, EV_ABS, ABS_MT_POSITION_Y);
> > > -    error = icn8318_probe_of(data, dev);
> > > +    if (client->dev.of_node)
> > > +        error = icn8318_probe_of(data, dev);
> > > +    else
> > > +        error = icn8318_probe_acpi(data, dev);
> > >       if (error)
> > >           return error;
> > > @@ -318,6 +382,7 @@ static struct i2c_driver icn8318_driver = {
> > >       .driver = {
> > >           .name    = "chipone_icn8318",
> > >           .pm    = &icn8318_pm_ops,
> > > +        .acpi_match_table = ACPI_PTR(icn8318_acpi_match),
> > >           .of_match_table = icn8318_of_match,
> > >       },
> > >       .probe_new = icn8318_probe,
> > > 
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux