linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH 2/2] iio: exynos-adc: add experimental touchscreen support
       [not found]     ` <53CBC8D6.6020509@kernel.org>
@ 2014-07-20 13:51       ` Jonathan Cameron
  2014-07-20 20:28         ` Dmitry Torokhov
  0 siblings, 1 reply; 7+ messages in thread
From: Jonathan Cameron @ 2014-07-20 13:51 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Chanwoo Choi, ch.naveen, mark.rutland, devicetree, kgene.kim,
	pawel.moll, ijc+devicetree, linux-iio, t.figa, rdunlap, linux-doc,
	linux-kernel, linux-samsung-soc, kyungmin.park, robh+dt, galak,
	heiko.stuebner, Ben Dooks, linux-input, Dmitry Torokhov

On 20/07/14 14:49, Jonathan Cameron wrote:
> On 18/07/14 20:29, Arnd Bergmann wrote:
>> This adds support for the touchscreen on Samsung s3c64xx.
>> The driver is completely untested but shows roughly how
>> it could be done, following the example of the at91 driver.
>>
> Hi Arnd,
Cc'd linux-input and Dmitry.
>
>> Open questions include:
>>
>> - compared to the old plat-samsung/adc driver, there is
>>    no support for prioritizing ts over other clients, nor
>>    for oversampling. From my reading of the code, the
>>    priorities didn't actually have any effect at all, but
>>    the oversampling might be needed. Maybe the original
>>    authors have some insight.
>>
>> - I simply register the input device from the adc driver
>>    itself, as the at91 code does. The driver also supports
>>    sub-nodes, but I don't understand how they are meant
>>    to be used, so using those might be better.
> So, the alternative you are (I think) referring to is to use
> the buffered in kernel client interface.  That way a separate
> touch screen driver can use the output channels provided by IIO
> in much the same way you might use a regulator or similar.
> Note that whilst this is similar to the simple polled interface
> used for things like the iio_hwmon driver, the data flow is
> quite different (clearly the polled interfce would be
> inappropriate here).
>
> Whilst we've discussed it in the past for touch screen drivers
> like this, usually the hardware isn't generic enough to be
> of any real use if not being used as a touch screen.  As such
> it's often simpler to just have the support directly in the
> driver (as you've observed the at91 driver does this).
>
> Whilst the interface has been there a while, it's not really had
> all that much use.  The original target was the simpler case
> of 3D accelerometer where we have a generic iio to input
> bridge driver. Time constraints meant that I haven't yet actually
> formally submitted the input side of this. Whilst there are lots
> of other things that can use this interface, right now nothing
> actually does so.
>
>>
>> - The new exynos_read_s3c64xx_ts() function is intentionally
>>    very similar to the existing exynos_read_raw() functions.
>>    It should probably be changed, either by merging the two
>>    into one, or by simplifying the exynos_read_s3c64xx_ts()
>>    function. This depends a bit on the answers to the questions
>>    above.
> I'd be tempted to not bother keeping them that similar.  It's
> not a generic IIO channel so simplify it where possible.
>>
>> - We probably need to add support for platform_data as well,
>>    I've skipped this so far.
>>
>> - Is anybody able to debug this driver on real hardware?
>>    While it's possible that it actually works, it's more
>>    likely that I made a few subtle mistakes.
>>
>> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Looks pretty good to me.  A few symantic bits and pieces and
> one bug spotted.  Short and sweet.
>>
>> diff --git a/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt b/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
>> index e1b74828f413..4329bf3c3326 100644
>> --- a/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
>> +++ b/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
>> @@ -41,6 +41,10 @@ Required properties:
>>                          and compatible ADC block)
>>   - vdd-supply        VDD input supply.
>>
>> +Optional properties:
>> +- has-touchscreen:    If present, indicates that a touchscreen is
>> +            connected an usable.
>> +
>>   Note: child nodes can be added for auto probing from device tree.
>>
>>   Example: adding device info in dtsi file
>> diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
>> index 5f95638513d2..cf1d9f3e2492 100644
>> --- a/drivers/iio/adc/exynos_adc.c
>> +++ b/drivers/iio/adc/exynos_adc.c
>> @@ -34,6 +34,7 @@
>>   #include <linux/regulator/consumer.h>
>>   #include <linux/of_platform.h>
>>   #include <linux/err.h>
>> +#include <linux/input.h>
> Might want to make the input side optional at compile time...
> I supose the existing parts are unlikely to be used much in headless
> devices, but you never know.  Maybe we just leave this until someone
> shouts they want to be able to avoid compiling it in.
>>
>>   #include <linux/iio/iio.h>
>>   #include <linux/iio/machine.h>
>> @@ -103,6 +104,7 @@
>>
>>   /* Bit definitions common for ADC_V1 and ADC_V2 */
>>   #define ADC_CON_EN_START    (1u << 0)
>> +#define ADC_DATX_PRESSED    (1u << 15)
>>   #define ADC_DATX_MASK        0xFFF
>>
>>   #define EXYNOS_ADC_TIMEOUT    (msecs_to_jiffies(100))
>> @@ -110,16 +112,20 @@
>>   struct exynos_adc {
>>       struct exynos_adc_data    *data;
>>       struct device        *dev;
>> +    struct input_dev    *input;
>>       void __iomem        *regs;
>>       void __iomem        *enable_reg;
>>       struct clk        *clk;
>>       struct clk        *sclk;
>>       unsigned int        irq;
>> +    unsigned int        tsirq;
>>       struct regulator    *vdd;
>>
>>       struct completion    completion;
>>
>> +    bool            read_ts;
>>       u32            value;
>> +    u32            value2;
> As I state further down, I'd rather keep a little
> clear of the naming used in IIO for bits that aren't
> going through IIO (less confusing!). Maybe just
> have
>      u32 x, y;
>>       unsigned int            version;
>>   };
>>
>> @@ -390,12 +396,61 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
>>       return ret;
>>   }
>>
>> +static int exynos_read_s3c64xx_ts(struct iio_dev *indio_dev,
>> +                struct iio_chan_spec const *chan,
>> +                int *val,
>> +                int *val2,
>> +                long mask)
>> +{
>> +    struct exynos_adc *info = iio_priv(indio_dev);
>> +    unsigned long timeout;
>> +    int ret;
>> +
>> +    if (mask != IIO_CHAN_INFO_RAW)
>> +        return -EINVAL;
>> +
>> +    mutex_lock(&indio_dev->mlock);
>> +    info->read_ts = 1;
>> +
>> +    reinit_completion(&info->completion);
>> +
>> +    writel(ADC_S3C2410_TSC_PULL_UP_DISABLE | ADC_TSC_AUTOPST,
>> +           ADC_V1_TSC(info->regs));
>> +
>> +    /* Select the ts channel to be used and Trigger conversion */
>> +    info->data->start_conv(info, 0);
> 0 is a rather magic value.  A define perhaps?
>> +
>> +    timeout = wait_for_completion_timeout
>> +            (&info->completion, EXYNOS_ADC_TIMEOUT);
>> +    if (timeout == 0) {
>> +        dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n");
>> +        if (info->data->init_hw)
>> +            info->data->init_hw(info);
>> +        ret = -ETIMEDOUT;
>> +    } else {
>> +        *val = info->value;
>> +        *val2 = info->value2;
> This is definitely abuse as those two values are not intended for
> different values.  If you want to do this please use different naming
> and don't try to fiddle it into the IIO read raw framework.
> As you've suggested above, better to simplify this code and drop the
> bits cloned from the other handler.
>> +        ret = IIO_VAL_INT;
>> +    }
>> +
>> +    info->read_ts = 0;
>> +    mutex_unlock(&indio_dev->mlock);
>> +
>> +    return ret;
>> +}
>> +
>>   static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
>>   {
>>       struct exynos_adc *info = (struct exynos_adc *)dev_id;
>>
>>       /* Read value */
>> -    info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK;
>> +    if (info->read_ts) {
>> +        info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK;
>> +        info->value2 = readl(ADC_V1_DATY(info->regs)) & ADC_DATX_MASK;
> ADC_DATY_MASK would be more obviously correct.
>
>> +        writel(ADC_TSC_WAIT4INT | ADC_S3C2443_TSC_UD_SEN, ADC_V1_TSC(info->regs));
> Perhaps the above is cryptic enough to warrant a comment?
>> +    } else {
>> +        info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK;
>> +    }
>>
>>       /* clear irq */
>>       if (info->data->clear_irq)
>> @@ -406,6 +461,46 @@ static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
>>       return IRQ_HANDLED;
>>   }
>>
>> +/*
>> + * Here we (ab)use a threaded interrupt handler to stay running
>> + * for as long as the touchscreen remains pressed, we report
>> + * a new event with the latest data and then sleep until the
>> + * next timer tick. This mirrors the behavior of the old
>> + * driver, with much less code.
>> + */
>> +static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
>> +{
>> +    struct exynos_adc *info = dev_id;
>> +    struct iio_dev *dev = dev_get_drvdata(info->dev);
>> +    u32 x, y;
>> +    bool pressed;
>> +    int ret;
>> +
>> +    do {
>> +        ret =exynos_read_s3c64xx_ts(dev, NULL, &x, &y, IIO_CHAN_INFO_RAW);
> = exynos
>> +        if (ret == -ETIMEDOUT)
>> +            break;
>> +
>> +        pressed = x & y & ADC_DATX_PRESSED;
>> +        if (!pressed)
>> +            break;
>> +
>> +        input_report_abs(info->input, ABS_X, x & ADC_DATX_MASK);
>> +        input_report_abs(info->input, ABS_Y, y & ADC_DATX_MASK);
>> +        input_report_key(info->input, BTN_TOUCH, 1);
>> +        input_sync(info->input);
>> +
>> +        msleep(1);
>> +    } while (1);
>> +
>> +    input_report_key(info->input, BTN_TOUCH, 0);
>> +    input_sync(info->input);
>> +
>> +    writel(0, ADC_V1_CLRINTPNDNUP(info->regs));
>> +
>> +    return IRQ_HANDLED;
>> +}
>> +
>>   static int exynos_adc_reg_access(struct iio_dev *indio_dev,
>>                     unsigned reg, unsigned writeval,
>>                     unsigned *readval)
>> @@ -457,12 +552,57 @@ static int exynos_adc_remove_devices(struct device *dev, void *c)
>>       return 0;
>>   }
>>
>> +static int exynos_adc_ts_init(struct exynos_adc *info)
>> +{
>> +    int ret;
>> +
>> +    info->input = input_allocate_device();
>> +    if (!info->input)
>> +        return -ENOMEM;
>> +
>> +    info->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
>> +    info->input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
>> +
>> +    input_set_abs_params(info->input, ABS_X, 0, 0x3FF, 0, 0);
>> +    input_set_abs_params(info->input, ABS_Y, 0, 0x3FF, 0, 0);
>> +
>> +    /* data from s3c2410_ts driver */
>> +    info->input->name = "S3C24xx TouchScreen";
>> +    info->input->id.bustype = BUS_HOST;
>> +    info->input->id.vendor = 0xDEAD;
>> +    info->input->id.product = 0xBEEF;
>> +    info->input->id.version = 0x0200;
>> +
>> +    ret = input_register_device(info->input);
>> +    if (ret) {
>> +        input_free_device(info->input);
>> +        goto err;
>> +    }
>> +
>> +    if (info->tsirq > 0)
>> +        ret = request_threaded_irq(info->irq, NULL, exynos_ts_isr,
>> +                    0, "touchscreen", info);
> info->tsirq
> (that had me really confused for a moment ;)
> Also, perhaps a more specific name.  touchscreen_updown or similar as the
> main interrupt is also used during touchscreen operation.
>> +    if (ret < 0) {
>> +        dev_err(info->dev, "failed requesting touchsccreen irq, irq = %d\n",
>> +                            info->irq);
>> +        goto err_input;
>> +    }
>> +
>> +    return 0;
>> +
>> +err_input:
>> +    input_unregister_device(info->input);
>> +err:
>> +    return ret;
>> +}
>> +
>>   static int exynos_adc_probe(struct platform_device *pdev)
>>   {
>>       struct exynos_adc *info = NULL;
>>       struct device_node *np = pdev->dev.of_node;
>>       struct iio_dev *indio_dev = NULL;
>>       struct resource    *mem;
>> +    bool has_ts;
>>       int ret = -ENODEV;
>>       int irq;
>>
>> @@ -498,8 +638,14 @@ static int exynos_adc_probe(struct platform_device *pdev)
>>           dev_err(&pdev->dev, "no irq resource?\n");
>>           return irq;
>>       }
>> -
>>       info->irq = irq;
>> +
>> +    irq = platform_get_irq(pdev, 1);
>> +    if (irq == -EPROBE_DEFER)
>> +        return irq;
>> +
>> +    info->tsirq = irq;
>> +
>>       info->dev = &pdev->dev;
>>
>>       init_completion(&info->completion);
>> @@ -565,6 +711,12 @@ static int exynos_adc_probe(struct platform_device *pdev)
>>       if (info->data->init_hw)
>>           info->data->init_hw(info);
>>
>> +    has_ts = of_property_read_bool(pdev->dev.of_node, "has-touchscreen");
>> +    if (has_ts)
>> +        ret = exynos_adc_ts_init(info);
>> +    if (ret)
>> +        goto err_iio;
>> +
>>       ret = of_platform_populate(np, exynos_adc_match, NULL, &indio_dev->dev);
>>       if (ret < 0) {
>>           dev_err(&pdev->dev, "failed adding child nodes\n");
>> @@ -576,6 +728,11 @@ static int exynos_adc_probe(struct platform_device *pdev)
>>   err_of_populate:
>>       device_for_each_child(&indio_dev->dev, NULL,
>>                   exynos_adc_remove_devices);
>> +    if (has_ts) {
>> +        input_unregister_device(info->input);
>> +        free_irq(info->tsirq, info);
>> +    }
>> +err_iio:
>>       iio_device_unregister(indio_dev);
>>   err_irq:
>>       free_irq(info->irq, info);
>> @@ -595,9 +752,12 @@ static int exynos_adc_remove(struct platform_device *pdev)
>>       struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>>       struct exynos_adc *info = iio_priv(indio_dev);
>>
>> +    input_free_device(info->input);
>>       device_for_each_child(&indio_dev->dev, NULL,
>>                   exynos_adc_remove_devices);
>>       iio_device_unregister(indio_dev);
>> +    if (info->tsirq > 0)
>> +        free_irq(info->tsirq, info);
>>       free_irq(info->irq, info);
>>       if (info->data->exit_hw)
>>           info->data->exit_hw(info);
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] iio: exynos-adc: add experimental touchscreen support
  2014-07-20 13:51       ` [PATCH 2/2] iio: exynos-adc: add experimental touchscreen support Jonathan Cameron
@ 2014-07-20 20:28         ` Dmitry Torokhov
  2014-07-21 10:23           ` Arnd Bergmann
  0 siblings, 1 reply; 7+ messages in thread
From: Dmitry Torokhov @ 2014-07-20 20:28 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Arnd Bergmann, linux-arm-kernel, Chanwoo Choi, ch.naveen,
	mark.rutland, devicetree, kgene.kim, pawel.moll, ijc+devicetree,
	linux-iio, t.figa, rdunlap, linux-doc, linux-kernel,
	linux-samsung-soc, kyungmin.park, robh+dt, galak, heiko.stuebner,
	Ben Dooks, linux-input

On Sun, Jul 20, 2014 at 02:51:37PM +0100, Jonathan Cameron wrote:
> On 20/07/14 14:49, Jonathan Cameron wrote:
> >On 18/07/14 20:29, Arnd Bergmann wrote:
> >>This adds support for the touchscreen on Samsung s3c64xx.
> >>The driver is completely untested but shows roughly how
> >>it could be done, following the example of the at91 driver.
> >>
> >Hi Arnd,
> Cc'd linux-input and Dmitry.
> >
> >>Open questions include:
> >>
> >>- compared to the old plat-samsung/adc driver, there is
> >>   no support for prioritizing ts over other clients, nor
> >>   for oversampling. From my reading of the code, the
> >>   priorities didn't actually have any effect at all, but
> >>   the oversampling might be needed. Maybe the original
> >>   authors have some insight.
> >>
> >>- I simply register the input device from the adc driver
> >>   itself, as the at91 code does. The driver also supports
> >>   sub-nodes, but I don't understand how they are meant
> >>   to be used, so using those might be better.
> >So, the alternative you are (I think) referring to is to use
> >the buffered in kernel client interface.  That way a separate
> >touch screen driver can use the output channels provided by IIO
> >in much the same way you might use a regulator or similar.
> >Note that whilst this is similar to the simple polled interface
> >used for things like the iio_hwmon driver, the data flow is
> >quite different (clearly the polled interfce would be
> >inappropriate here).
> >
> >Whilst we've discussed it in the past for touch screen drivers
> >like this, usually the hardware isn't generic enough to be
> >of any real use if not being used as a touch screen.  As such
> >it's often simpler to just have the support directly in the
> >driver (as you've observed the at91 driver does this).
> >
> >Whilst the interface has been there a while, it's not really had
> >all that much use.  The original target was the simpler case
> >of 3D accelerometer where we have a generic iio to input
> >bridge driver. Time constraints meant that I haven't yet actually
> >formally submitted the input side of this. Whilst there are lots
> >of other things that can use this interface, right now nothing
> >actually does so.
> >
> >>
> >>- The new exynos_read_s3c64xx_ts() function is intentionally
> >>   very similar to the existing exynos_read_raw() functions.
> >>   It should probably be changed, either by merging the two
> >>   into one, or by simplifying the exynos_read_s3c64xx_ts()
> >>   function. This depends a bit on the answers to the questions
> >>   above.
> >I'd be tempted to not bother keeping them that similar.  It's
> >not a generic IIO channel so simplify it where possible.
> >>
> >>- We probably need to add support for platform_data as well,
> >>   I've skipped this so far.
> >>
> >>- Is anybody able to debug this driver on real hardware?
> >>   While it's possible that it actually works, it's more
> >>   likely that I made a few subtle mistakes.
> >>
> >>Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> >Looks pretty good to me.  A few symantic bits and pieces and
> >one bug spotted.  Short and sweet.
> >>
> >>diff --git a/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt b/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
> >>index e1b74828f413..4329bf3c3326 100644
> >>--- a/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
> >>+++ b/Documentation/devicetree/bindings/arm/samsung/exynos-adc.txt
> >>@@ -41,6 +41,10 @@ Required properties:
> >>                         and compatible ADC block)
> >>  - vdd-supply        VDD input supply.
> >>
> >>+Optional properties:
> >>+- has-touchscreen:    If present, indicates that a touchscreen is
> >>+            connected an usable.
> >>+
> >>  Note: child nodes can be added for auto probing from device tree.
> >>
> >>  Example: adding device info in dtsi file
> >>diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
> >>index 5f95638513d2..cf1d9f3e2492 100644
> >>--- a/drivers/iio/adc/exynos_adc.c
> >>+++ b/drivers/iio/adc/exynos_adc.c
> >>@@ -34,6 +34,7 @@
> >>  #include <linux/regulator/consumer.h>
> >>  #include <linux/of_platform.h>
> >>  #include <linux/err.h>
> >>+#include <linux/input.h>
> >Might want to make the input side optional at compile time...
> >I supose the existing parts are unlikely to be used much in headless
> >devices, but you never know.  Maybe we just leave this until someone
> >shouts they want to be able to avoid compiling it in.
> >>
> >>  #include <linux/iio/iio.h>
> >>  #include <linux/iio/machine.h>
> >>@@ -103,6 +104,7 @@
> >>
> >>  /* Bit definitions common for ADC_V1 and ADC_V2 */
> >>  #define ADC_CON_EN_START    (1u << 0)
> >>+#define ADC_DATX_PRESSED    (1u << 15)
> >>  #define ADC_DATX_MASK        0xFFF
> >>
> >>  #define EXYNOS_ADC_TIMEOUT    (msecs_to_jiffies(100))
> >>@@ -110,16 +112,20 @@
> >>  struct exynos_adc {
> >>      struct exynos_adc_data    *data;
> >>      struct device        *dev;
> >>+    struct input_dev    *input;
> >>      void __iomem        *regs;
> >>      void __iomem        *enable_reg;
> >>      struct clk        *clk;
> >>      struct clk        *sclk;
> >>      unsigned int        irq;
> >>+    unsigned int        tsirq;
> >>      struct regulator    *vdd;
> >>
> >>      struct completion    completion;
> >>
> >>+    bool            read_ts;
> >>      u32            value;
> >>+    u32            value2;
> >As I state further down, I'd rather keep a little
> >clear of the naming used in IIO for bits that aren't
> >going through IIO (less confusing!). Maybe just
> >have
> >     u32 x, y;
> >>      unsigned int            version;
> >>  };
> >>
> >>@@ -390,12 +396,61 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
> >>      return ret;
> >>  }
> >>
> >>+static int exynos_read_s3c64xx_ts(struct iio_dev *indio_dev,
> >>+                struct iio_chan_spec const *chan,
> >>+                int *val,
> >>+                int *val2,
> >>+                long mask)
> >>+{
> >>+    struct exynos_adc *info = iio_priv(indio_dev);
> >>+    unsigned long timeout;
> >>+    int ret;
> >>+
> >>+    if (mask != IIO_CHAN_INFO_RAW)
> >>+        return -EINVAL;
> >>+
> >>+    mutex_lock(&indio_dev->mlock);
> >>+    info->read_ts = 1;
> >>+
> >>+    reinit_completion(&info->completion);
> >>+
> >>+    writel(ADC_S3C2410_TSC_PULL_UP_DISABLE | ADC_TSC_AUTOPST,
> >>+           ADC_V1_TSC(info->regs));
> >>+
> >>+    /* Select the ts channel to be used and Trigger conversion */
> >>+    info->data->start_conv(info, 0);
> >0 is a rather magic value.  A define perhaps?
> >>+
> >>+    timeout = wait_for_completion_timeout
> >>+            (&info->completion, EXYNOS_ADC_TIMEOUT);
> >>+    if (timeout == 0) {
> >>+        dev_warn(&indio_dev->dev, "Conversion timed out! Resetting\n");
> >>+        if (info->data->init_hw)
> >>+            info->data->init_hw(info);
> >>+        ret = -ETIMEDOUT;
> >>+    } else {
> >>+        *val = info->value;
> >>+        *val2 = info->value2;
> >This is definitely abuse as those two values are not intended for
> >different values.  If you want to do this please use different naming
> >and don't try to fiddle it into the IIO read raw framework.
> >As you've suggested above, better to simplify this code and drop the
> >bits cloned from the other handler.
> >>+        ret = IIO_VAL_INT;
> >>+    }
> >>+
> >>+    info->read_ts = 0;
> >>+    mutex_unlock(&indio_dev->mlock);
> >>+
> >>+    return ret;
> >>+}
> >>+
> >>  static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
> >>  {
> >>      struct exynos_adc *info = (struct exynos_adc *)dev_id;
> >>
> >>      /* Read value */
> >>-    info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK;
> >>+    if (info->read_ts) {
> >>+        info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK;
> >>+        info->value2 = readl(ADC_V1_DATY(info->regs)) & ADC_DATX_MASK;
> >ADC_DATY_MASK would be more obviously correct.
> >
> >>+        writel(ADC_TSC_WAIT4INT | ADC_S3C2443_TSC_UD_SEN, ADC_V1_TSC(info->regs));
> >Perhaps the above is cryptic enough to warrant a comment?
> >>+    } else {
> >>+        info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK;
> >>+    }
> >>
> >>      /* clear irq */
> >>      if (info->data->clear_irq)
> >>@@ -406,6 +461,46 @@ static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
> >>      return IRQ_HANDLED;
> >>  }
> >>
> >>+/*
> >>+ * Here we (ab)use a threaded interrupt handler to stay running
> >>+ * for as long as the touchscreen remains pressed, we report
> >>+ * a new event with the latest data and then sleep until the
> >>+ * next timer tick. This mirrors the behavior of the old
> >>+ * driver, with much less code.
> >>+ */
> >>+static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
> >>+{
> >>+    struct exynos_adc *info = dev_id;
> >>+    struct iio_dev *dev = dev_get_drvdata(info->dev);
> >>+    u32 x, y;
> >>+    bool pressed;
> >>+    int ret;
> >>+
> >>+    do {
> >>+        ret =exynos_read_s3c64xx_ts(dev, NULL, &x, &y, IIO_CHAN_INFO_RAW);
> >= exynos
> >>+        if (ret == -ETIMEDOUT)
> >>+            break;
> >>+
> >>+        pressed = x & y & ADC_DATX_PRESSED;
> >>+        if (!pressed)
> >>+            break;
> >>+
> >>+        input_report_abs(info->input, ABS_X, x & ADC_DATX_MASK);
> >>+        input_report_abs(info->input, ABS_Y, y & ADC_DATX_MASK);
> >>+        input_report_key(info->input, BTN_TOUCH, 1);
> >>+        input_sync(info->input);
> >>+
> >>+        msleep(1);
> >>+    } while (1);

It would be nice to actually close the device even if someone is
touching screen. Please implement open/close methods and have them set a
flag that you would check here.


> >>+
> >>+    input_report_key(info->input, BTN_TOUCH, 0);
> >>+    input_sync(info->input);
> >>+
> >>+    writel(0, ADC_V1_CLRINTPNDNUP(info->regs));
> >>+
> >>+    return IRQ_HANDLED;
> >>+}
> >>+
> >>  static int exynos_adc_reg_access(struct iio_dev *indio_dev,
> >>                    unsigned reg, unsigned writeval,
> >>                    unsigned *readval)
> >>@@ -457,12 +552,57 @@ static int exynos_adc_remove_devices(struct device *dev, void *c)
> >>      return 0;
> >>  }
> >>
> >>+static int exynos_adc_ts_init(struct exynos_adc *info)
> >>+{
> >>+    int ret;
> >>+
> >>+    info->input = input_allocate_device();
> >>+    if (!info->input)
> >>+        return -ENOMEM;
> >>+
> >>+    info->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
> >>+    info->input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
> >>+
> >>+    input_set_abs_params(info->input, ABS_X, 0, 0x3FF, 0, 0);
> >>+    input_set_abs_params(info->input, ABS_Y, 0, 0x3FF, 0, 0);
> >>+
> >>+    /* data from s3c2410_ts driver */
> >>+    info->input->name = "S3C24xx TouchScreen";
> >>+    info->input->id.bustype = BUS_HOST;
> >>+    info->input->id.vendor = 0xDEAD;
> >>+    info->input->id.product = 0xBEEF;

You do not need to fill these entries with fake data.

> >>+    info->input->id.version = 0x0200;
> >>+
> >>+    ret = input_register_device(info->input);
> >>+    if (ret) {
> >>+        input_free_device(info->input);
> >>+        goto err;
> >>+    }
> >>+
> >>+    if (info->tsirq > 0)
> >>+        ret = request_threaded_irq(info->irq, NULL, exynos_ts_isr,
> >>+                    0, "touchscreen", info);
> >info->tsirq
> >(that had me really confused for a moment ;)
> >Also, perhaps a more specific name.  touchscreen_updown or similar as the
> >main interrupt is also used during touchscreen operation.
> >>+    if (ret < 0) {
> >>+        dev_err(info->dev, "failed requesting touchsccreen irq, irq = %d\n",
> >>+                            info->irq);
> >>+        goto err_input;
> >>+    }
> >>+
> >>+    return 0;
> >>+
> >>+err_input:
> >>+    input_unregister_device(info->input);
> >>+err:
> >>+    return ret;
> >>+}
> >>+
> >>  static int exynos_adc_probe(struct platform_device *pdev)
> >>  {
> >>      struct exynos_adc *info = NULL;
> >>      struct device_node *np = pdev->dev.of_node;
> >>      struct iio_dev *indio_dev = NULL;
> >>      struct resource    *mem;
> >>+    bool has_ts;
> >>      int ret = -ENODEV;
> >>      int irq;
> >>
> >>@@ -498,8 +638,14 @@ static int exynos_adc_probe(struct platform_device *pdev)
> >>          dev_err(&pdev->dev, "no irq resource?\n");
> >>          return irq;
> >>      }
> >>-
> >>      info->irq = irq;
> >>+
> >>+    irq = platform_get_irq(pdev, 1);
> >>+    if (irq == -EPROBE_DEFER)
> >>+        return irq;
> >>+
> >>+    info->tsirq = irq;
> >>+
> >>      info->dev = &pdev->dev;
> >>
> >>      init_completion(&info->completion);
> >>@@ -565,6 +711,12 @@ static int exynos_adc_probe(struct platform_device *pdev)
> >>      if (info->data->init_hw)
> >>          info->data->init_hw(info);
> >>
> >>+    has_ts = of_property_read_bool(pdev->dev.of_node, "has-touchscreen");
> >>+    if (has_ts)
> >>+        ret = exynos_adc_ts_init(info);
> >>+    if (ret)
> >>+        goto err_iio;
> >>+
> >>      ret = of_platform_populate(np, exynos_adc_match, NULL, &indio_dev->dev);
> >>      if (ret < 0) {
> >>          dev_err(&pdev->dev, "failed adding child nodes\n");
> >>@@ -576,6 +728,11 @@ static int exynos_adc_probe(struct platform_device *pdev)
> >>  err_of_populate:
> >>      device_for_each_child(&indio_dev->dev, NULL,
> >>                  exynos_adc_remove_devices);
> >>+    if (has_ts) {
> >>+        input_unregister_device(info->input);
> >>+        free_irq(info->tsirq, info);

Are we sure that device is quiesced here and interrupt won't arrive
between input_unregister_device() and free_irq()? I guess if you
properly implement open/close it won't matter.

> >>+    }
> >>+err_iio:
> >>      iio_device_unregister(indio_dev);
> >>  err_irq:
> >>      free_irq(info->irq, info);
> >>@@ -595,9 +752,12 @@ static int exynos_adc_remove(struct platform_device *pdev)
> >>      struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> >>      struct exynos_adc *info = iio_priv(indio_dev);
> >>
> >>+    input_free_device(info->input);

Should be unregister, not free.

> >>      device_for_each_child(&indio_dev->dev, NULL,
> >>                  exynos_adc_remove_devices);
> >>      iio_device_unregister(indio_dev);
> >>+    if (info->tsirq > 0)
> >>+        free_irq(info->tsirq, info);
> >>      free_irq(info->irq, info);
> >>      if (info->data->exit_hw)
> >>          info->data->exit_hw(info);
> >>

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] iio: exynos-adc: add experimental touchscreen support
  2014-07-20 20:28         ` Dmitry Torokhov
@ 2014-07-21 10:23           ` Arnd Bergmann
  2014-07-21 10:26             ` Arnd Bergmann
  2014-07-21 14:44             ` Dmitry Torokhov
  0 siblings, 2 replies; 7+ messages in thread
From: Arnd Bergmann @ 2014-07-21 10:23 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Jonathan Cameron, linux-arm-kernel, Chanwoo Choi, ch.naveen,
	mark.rutland, devicetree, kgene.kim, pawel.moll, ijc+devicetree,
	linux-iio, t.figa, rdunlap, linux-doc, linux-kernel,
	linux-samsung-soc, kyungmin.park, robh+dt, galak, heiko.stuebner,
	Ben Dooks, linux-input

On Sunday 20 July 2014 13:28:42 Dmitry Torokhov wrote:
> On Sun, Jul 20, 2014 at 02:51:37PM +0100, Jonathan Cameron wrote:
> > >>+
> > >>+    do {
> > >>+        ret =exynos_read_s3c64xx_ts(dev, NULL, &x, &y, IIO_CHAN_INFO_RAW);
> > >= exynos
> > >>+        if (ret == -ETIMEDOUT)
> > >>+            break;
> > >>+
> > >>+        pressed = x & y & ADC_DATX_PRESSED;
> > >>+        if (!pressed)
> > >>+            break;
> > >>+
> > >>+        input_report_abs(info->input, ABS_X, x & ADC_DATX_MASK);
> > >>+        input_report_abs(info->input, ABS_Y, y & ADC_DATX_MASK);
> > >>+        input_report_key(info->input, BTN_TOUCH, 1);
> > >>+        input_sync(info->input);
> > >>+
> > >>+        msleep(1);
> > >>+    } while (1);
> 
> It would be nice to actually close the device even if someone is
> touching screen. Please implement open/close methods and have them set a
> flag that you would check here.

Ok. I think it's even better to move the request_irq() into the open function,
which will avoid the flag and defer the error handling into the actual opening,
as well as syncing the running irq with the close function.

> > >>+    /* data from s3c2410_ts driver */
> > >>+    info->input->name = "S3C24xx TouchScreen";
> > >>+    info->input->id.bustype = BUS_HOST;
> > >>+    info->input->id.vendor = 0xDEAD;
> > >>+    info->input->id.product = 0xBEEF;
> 
> You do not need to fill these entries with fake data.

Ok, I wondered about this, but didn't want to change too much from
the old driver (I changed the version number).

> > >>+    info->input->id.version = 0x0200;

Do I need this?

> > >>@@ -576,6 +728,11 @@ static int exynos_adc_probe(struct platform_device *pdev)
> > >>  err_of_populate:
> > >>      device_for_each_child(&indio_dev->dev, NULL,
> > >>                  exynos_adc_remove_devices);
> > >>+    if (has_ts) {
> > >>+        input_unregister_device(info->input);
> > >>+        free_irq(info->tsirq, info);
> 
> Are we sure that device is quiesced here and interrupt won't arrive
> between input_unregister_device() and free_irq()? I guess if you
> properly implement open/close it won't matter.
 
Should be fixed now.

> > >>+err_iio:
> > >>      iio_device_unregister(indio_dev);
> > >>  err_irq:
> > >>      free_irq(info->irq, info);
> > >>@@ -595,9 +752,12 @@ static int exynos_adc_remove(struct platform_device *pdev)
> > >>      struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> > >>      struct exynos_adc *info = iio_priv(indio_dev);
> > >>
> > >>+    input_free_device(info->input);
> 
> Should be unregister, not free.

Ok.

Thanks a lot for the review! I'll send out the new version after some build testing.

	Arnd

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] iio: exynos-adc: add experimental touchscreen support
  2014-07-21 10:23           ` Arnd Bergmann
@ 2014-07-21 10:26             ` Arnd Bergmann
  2014-07-21 14:44             ` Dmitry Torokhov
  1 sibling, 0 replies; 7+ messages in thread
From: Arnd Bergmann @ 2014-07-21 10:26 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Jonathan Cameron, linux-arm-kernel, Chanwoo Choi, ch.naveen,
	mark.rutland, devicetree, kgene.kim, pawel.moll, ijc+devicetree,
	linux-iio, t.figa, rdunlap, linux-doc, linux-kernel,
	linux-samsung-soc, kyungmin.park, robh+dt, galak, heiko.stuebner,
	Ben Dooks, linux-input

On Monday 21 July 2014 12:23:58 Arnd Bergmann wrote:
> 
> Thanks a lot for the review! I'll send out the new version after some build testing.

Here are the changes I did to the adc driver based on the review comments.
I'll start a new thread for the updated version that includes the changes.

diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index 3d2caea05977..823d7ebc7f52 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -67,6 +67,9 @@
 
 #define ADC_S3C2410_CON_SELMUX(x) (((x)&0x7)<<3)
 
+/* touch screen always uses channel 0 */
+#define ADC_S3C2410_MUX_TS	0
+
 /* ADCTSC Register Bits */
 #define ADC_S3C2443_TSC_UD_SEN		(1u << 8)
 #define ADC_S3C2410_TSC_YM_SEN		(1u << 7)
@@ -106,6 +109,7 @@
 #define ADC_CON_EN_START	(1u << 0)
 #define ADC_DATX_PRESSED	(1u << 15)
 #define ADC_DATX_MASK		0xFFF
+#define ADC_DATY_MASK		0xFFF
 
 #define EXYNOS_ADC_TIMEOUT	(msecs_to_jiffies(100))
 
@@ -123,10 +127,12 @@ struct exynos_adc {
 
 	struct completion	completion;
 
-	bool			read_ts;
 	u32			value;
-	u32			value2;
 	unsigned int            version;
+
+	bool			read_ts;
+	u32			ts_x;
+	u32			ts_y;
 };
 
 struct exynos_adc_data {
@@ -396,21 +402,14 @@ static int exynos_read_raw(struct iio_dev *indio_dev,
 	return ret;
 }
 
-static int exynos_read_s3c64xx_ts(struct iio_dev *indio_dev,
-				struct iio_chan_spec const *chan,
-				int *val,
-				int *val2,
-				long mask)
+static int exynos_read_s3c64xx_ts(struct iio_dev *indio_dev, int *x, int *y)
 {
 	struct exynos_adc *info = iio_priv(indio_dev);
 	unsigned long timeout;
 	int ret;
 
-	if (mask != IIO_CHAN_INFO_RAW)
-		return -EINVAL;
-
 	mutex_lock(&indio_dev->mlock);
-	info->read_ts = 1;
+	info->read_ts = true;
 
 	reinit_completion(&info->completion);
 
@@ -418,7 +417,7 @@ static int exynos_read_s3c64xx_ts(struct iio_dev *indio_dev,
 	       ADC_V1_TSC(info->regs));
 
 	/* Select the ts channel to be used and Trigger conversion */
-	info->data->start_conv(info, 0);
+	info->data->start_conv(info, ADC_S3C2410_MUX_TS);
 
 	timeout = wait_for_completion_timeout
 			(&info->completion, EXYNOS_ADC_TIMEOUT);
@@ -428,12 +427,12 @@ static int exynos_read_s3c64xx_ts(struct iio_dev *indio_dev,
 			info->data->init_hw(info);
 		ret = -ETIMEDOUT;
 	} else {
-		*val = info->value;
-		*val2 = info->value2;
-		ret = IIO_VAL_INT;
+		*x = info->ts_x;
+		*y = info->ts_y;
+		ret = 0;
 	}
 
-	info->read_ts = 0;
+	info->read_ts = false;
 	mutex_unlock(&indio_dev->mlock);
 
 	return ret;
@@ -445,8 +444,8 @@ static irqreturn_t exynos_adc_isr(int irq, void *dev_id)
 
 	/* Read value */
 	if (info->read_ts) {
-		info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK;
-		info->value2 = readl(ADC_V1_DATY(info->regs)) & ADC_DATX_MASK;
+		info->ts_x = readl(ADC_V1_DATX(info->regs));
+		info->ts_y = readl(ADC_V1_DATY(info->regs));
 		writel(ADC_TSC_WAIT4INT | ADC_S3C2443_TSC_UD_SEN, ADC_V1_TSC(info->regs));
 	} else {
 		info->value = readl(ADC_V1_DATX(info->regs)) & ADC_DATX_MASK;
@@ -477,7 +476,7 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
 	int ret;
 
 	do {
-		ret =exynos_read_s3c64xx_ts(dev, NULL, &x, &y, IIO_CHAN_INFO_RAW);
+		ret = exynos_read_s3c64xx_ts(dev, &x, &y);
 		if (ret == -ETIMEDOUT)
 			break;
 
@@ -486,11 +485,15 @@ static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
 			break;
 
 		input_report_abs(info->input, ABS_X, x & ADC_DATX_MASK);
-		input_report_abs(info->input, ABS_Y, y & ADC_DATX_MASK);
+		input_report_abs(info->input, ABS_Y, y & ADC_DATY_MASK);
 		input_report_key(info->input, BTN_TOUCH, 1);
 		input_sync(info->input);
 
 		msleep(1);
+
+		/* device may have been closed while touched */
+		if (!info->input->users)
+			return IRQ_HANDLED;
 	} while (1);
 
 	input_report_key(info->input, BTN_TOUCH, 0);
@@ -552,10 +555,28 @@ static int exynos_adc_remove_devices(struct device *dev, void *c)
 	return 0;
 }
 
+static int exynos_adc_ts_open(struct input_dev *dev)
+{
+	struct exynos_adc *info = input_get_drvdata(dev);
+
+	return request_threaded_irq(info->tsirq, NULL, exynos_ts_isr,
+				    0, "touchscreen", info);
+}
+
+static void exynos_adc_ts_close(struct input_dev *dev)
+{
+	struct exynos_adc *info = input_get_drvdata(dev);
+
+	free_irq(info->tsirq, info);
+}
+
 static int exynos_adc_ts_init(struct exynos_adc *info)
 {
 	int ret;
 
+	if (info->tsirq <= 0)
+		return -ENODEV;
+
 	info->input = input_allocate_device();
 	if (!info->input)
 		return -ENOMEM;
@@ -566,33 +587,17 @@ static int exynos_adc_ts_init(struct exynos_adc *info)
 	input_set_abs_params(info->input, ABS_X, 0, 0x3FF, 0, 0);
 	input_set_abs_params(info->input, ABS_Y, 0, 0x3FF, 0, 0);
 
-	/* data from s3c2410_ts driver */
 	info->input->name = "S3C24xx TouchScreen";
 	info->input->id.bustype = BUS_HOST;
-	info->input->id.vendor = 0xDEAD;
-	info->input->id.product = 0xBEEF;
-	info->input->id.version = 0x0200;
+	info->input->open = exynos_adc_ts_open;
+	info->input->close = exynos_adc_ts_close;
+	
+	input_set_drvdata(info->input, info);
 
 	ret = input_register_device(info->input);
-	if (ret) {
+	if (ret)
 		input_free_device(info->input);
-		goto err;
-	}
-
-	if (info->tsirq > 0)
-		ret = request_threaded_irq(info->irq, NULL, exynos_ts_isr,
-					0, "touchscreen", info);
-	if (ret < 0) {
-		dev_err(info->dev, "failed requesting touchsccreen irq, irq = %d\n",
-							info->irq);
-		goto err_input;
-	}
-
-	return 0;
 
-err_input:
-	input_unregister_device(info->input);
-err:
 	return ret;
 }
 
@@ -602,7 +607,7 @@ static int exynos_adc_probe(struct platform_device *pdev)
 	struct device_node *np = pdev->dev.of_node;
 	struct iio_dev *indio_dev = NULL;
 	struct resource	*mem;
-	bool has_ts;
+	bool has_ts = false;
 	int ret = -ENODEV;
 	int irq;
 
@@ -711,7 +716,10 @@ static int exynos_adc_probe(struct platform_device *pdev)
 	if (info->data->init_hw)
 		info->data->init_hw(info);
 
-	has_ts = of_property_read_bool(pdev->dev.of_node, "has-touchscreen");
+	/* leave out any TS related code if unreachable */
+	if (IS_BUILTIN(CONFIG_INPUT) ||
+	    (IS_MODULE(CONFIG_INPUT) && config_enabled(MODULE)))
+		has_ts = of_property_read_bool(pdev->dev.of_node, "has-touchscreen");
 	if (has_ts)
 		ret = exynos_adc_ts_init(info);
 	if (ret)
@@ -752,7 +760,7 @@ static int exynos_adc_remove(struct platform_device *pdev)
 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
 	struct exynos_adc *info = iio_priv(indio_dev);
 
-	input_free_device(info->input);	
+	input_unregister_device(info->input);	
 	device_for_each_child(&indio_dev->dev, NULL,
 				exynos_adc_remove_devices);
 	iio_device_unregister(indio_dev);


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] iio: exynos-adc: add experimental touchscreen support
  2014-07-21 10:23           ` Arnd Bergmann
  2014-07-21 10:26             ` Arnd Bergmann
@ 2014-07-21 14:44             ` Dmitry Torokhov
  2014-07-21 15:11               ` Arnd Bergmann
  1 sibling, 1 reply; 7+ messages in thread
From: Dmitry Torokhov @ 2014-07-21 14:44 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Jonathan Cameron, linux-arm-kernel, Chanwoo Choi, ch.naveen,
	mark.rutland, devicetree, kgene.kim, pawel.moll, ijc+devicetree,
	linux-iio, t.figa, rdunlap, linux-doc, linux-kernel,
	linux-samsung-soc, kyungmin.park, robh+dt, galak, heiko.stuebner,
	Ben Dooks, linux-input

On Mon, Jul 21, 2014 at 12:23:58PM +0200, Arnd Bergmann wrote:
> On Sunday 20 July 2014 13:28:42 Dmitry Torokhov wrote:
> > On Sun, Jul 20, 2014 at 02:51:37PM +0100, Jonathan Cameron wrote:
> > > >>+
> > > >>+    do {
> > > >>+        ret =exynos_read_s3c64xx_ts(dev, NULL, &x, &y, IIO_CHAN_INFO_RAW);
> > > >= exynos
> > > >>+        if (ret == -ETIMEDOUT)
> > > >>+            break;
> > > >>+
> > > >>+        pressed = x & y & ADC_DATX_PRESSED;
> > > >>+        if (!pressed)
> > > >>+            break;
> > > >>+
> > > >>+        input_report_abs(info->input, ABS_X, x & ADC_DATX_MASK);
> > > >>+        input_report_abs(info->input, ABS_Y, y & ADC_DATX_MASK);
> > > >>+        input_report_key(info->input, BTN_TOUCH, 1);
> > > >>+        input_sync(info->input);
> > > >>+
> > > >>+        msleep(1);
> > > >>+    } while (1);
> > 
> > It would be nice to actually close the device even if someone is
> > touching screen. Please implement open/close methods and have them set a
> > flag that you would check here.
> 
> Ok. I think it's even better to move the request_irq() into the open function,
> which will avoid the flag and defer the error handling into the actual opening,
> as well as syncing the running irq with the close function.

I do not quite like acquiring resources needed in open. I think drivers should
do all resource acquisition in probe() and leave open()/close() to
activate/quiesce devices.

> 
> > > >>+    /* data from s3c2410_ts driver */
> > > >>+    info->input->name = "S3C24xx TouchScreen";
> > > >>+    info->input->id.bustype = BUS_HOST;
> > > >>+    info->input->id.vendor = 0xDEAD;
> > > >>+    info->input->id.product = 0xBEEF;
> > 
> > You do not need to fill these entries with fake data.
> 
> Ok, I wondered about this, but didn't want to change too much from
> the old driver (I changed the version number).
> 
> > > >>+    info->input->id.version = 0x0200;
> 
> Do I need this?

Not really.

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] iio: exynos-adc: add experimental touchscreen support
  2014-07-21 14:44             ` Dmitry Torokhov
@ 2014-07-21 15:11               ` Arnd Bergmann
  2014-07-21 16:19                 ` Dmitry Torokhov
  0 siblings, 1 reply; 7+ messages in thread
From: Arnd Bergmann @ 2014-07-21 15:11 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: mark.rutland, devicetree, kgene.kim, pawel.moll, ijc+devicetree,
	linux-iio, t.figa, Dmitry Torokhov, linux-doc, linux-kernel,
	Jonathan Cameron, Chanwoo Choi, kyungmin.park, robh+dt, rdunlap,
	Ben Dooks, galak, ch.naveen, linux-input, linux-samsung-soc,
	heiko.stuebner

On Monday 21 July 2014 07:44:42 Dmitry Torokhov wrote:
> > > 
> > > It would be nice to actually close the device even if someone is
> > > touching screen. Please implement open/close methods and have them set a
> > > flag that you would check here.
> > 
> > Ok. I think it's even better to move the request_irq() into the open function,
> > which will avoid the flag and defer the error handling into the actual opening,
> > as well as syncing the running irq with the close function.
> 
> I do not quite like acquiring resources needed in open. I think drivers should
> do all resource acquisition in probe() and leave open()/close() to
> activate/quiesce devices.

Ok, I'll move it back then. I'm not sure what I'm supposed to do
in open/close then. Isn't it enough to check info->input->users
like this?

static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
{
        struct exynos_adc *info = dev_id;
        struct iio_dev *dev = dev_get_drvdata(info->dev);
        u32 x, y;
        bool pressed;
        int ret;

        while (info->input->users) {
                ret = exynos_read_s3c64xx_ts(dev, &x, &y);
                if (ret == -ETIMEDOUT)
                        break;

                pressed = x & y & ADC_DATX_PRESSED;
                if (!pressed) {
                        input_report_key(info->input, BTN_TOUCH, 0);
                        input_sync(info->input);
                        break;
                }

                input_report_abs(info->input, ABS_X, x & ADC_DATX_MASK);
                input_report_abs(info->input, ABS_Y, y & ADC_DATY_MASK);
                input_report_key(info->input, BTN_TOUCH, 1);
                input_sync(info->input);

                msleep(1);
        };

        writel(0, ADC_V1_CLRINTPNDNUP(info->regs));

        return IRQ_HANDLED;
}

I could do enable_irq()/disable_irq(), but that leaves a small
race at startup where we request the irq line and then immediately
disable it again.

	Arnd

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] iio: exynos-adc: add experimental touchscreen support
  2014-07-21 15:11               ` Arnd Bergmann
@ 2014-07-21 16:19                 ` Dmitry Torokhov
  0 siblings, 0 replies; 7+ messages in thread
From: Dmitry Torokhov @ 2014-07-21 16:19 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, mark.rutland, devicetree, kgene.kim, pawel.moll,
	ijc+devicetree, linux-iio, t.figa, rdunlap, linux-doc,
	linux-kernel, robh+dt, Chanwoo Choi, kyungmin.park,
	linux-samsung-soc, Jonathan Cameron, Ben Dooks, galak, ch.naveen,
	linux-input, heiko.stuebner

On Mon, Jul 21, 2014 at 05:11:27PM +0200, Arnd Bergmann wrote:
> On Monday 21 July 2014 07:44:42 Dmitry Torokhov wrote:
> > > > 
> > > > It would be nice to actually close the device even if someone is
> > > > touching screen. Please implement open/close methods and have them set a
> > > > flag that you would check here.
> > > 
> > > Ok. I think it's even better to move the request_irq() into the open function,
> > > which will avoid the flag and defer the error handling into the actual opening,
> > > as well as syncing the running irq with the close function.
> > 
> > I do not quite like acquiring resources needed in open. I think drivers should
> > do all resource acquisition in probe() and leave open()/close() to
> > activate/quiesce devices.
> 
> Ok, I'll move it back then. I'm not sure what I'm supposed to do
> in open/close then. Isn't it enough to check info->input->users
> like this?
> 
> static irqreturn_t exynos_ts_isr(int irq, void *dev_id)
> {
>         struct exynos_adc *info = dev_id;
>         struct iio_dev *dev = dev_get_drvdata(info->dev);
>         u32 x, y;
>         bool pressed;
>         int ret;
> 
>         while (info->input->users) {
>                 ret = exynos_read_s3c64xx_ts(dev, &x, &y);
>                 if (ret == -ETIMEDOUT)
>                         break;
> 
>                 pressed = x & y & ADC_DATX_PRESSED;
>                 if (!pressed) {
>                         input_report_key(info->input, BTN_TOUCH, 0);
>                         input_sync(info->input);
>                         break;
>                 }
> 
>                 input_report_abs(info->input, ABS_X, x & ADC_DATX_MASK);
>                 input_report_abs(info->input, ABS_Y, y & ADC_DATY_MASK);
>                 input_report_key(info->input, BTN_TOUCH, 1);
>                 input_sync(info->input);
> 
>                 msleep(1);
>         };
> 
>         writel(0, ADC_V1_CLRINTPNDNUP(info->regs));
> 
>         return IRQ_HANDLED;
> }
> 
> I could do enable_irq()/disable_irq(), but that leaves a small
> race at startup where we request the irq line and then immediately
> disable it again.

I think the above (or a separate flag in driver structure) coupled with
enable/disable IRQ is fine - input core can deal with calls to input_report_*
on devices that have been properly allocated but have not been registered yet.

drivers/input/keyboard/samsung-keypad.c does similar handling.

Thanks.

-- 
Dmitry

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2014-07-21 16:19 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <1405663186-26464-1-git-send-email-cw00.choi@samsung.com>
     [not found] ` <5186890.aLtladpMgD@wuerfel>
     [not found]   ` <5456679.XxlLIvc3Q6@wuerfel>
     [not found]     ` <53CBC8D6.6020509@kernel.org>
2014-07-20 13:51       ` [PATCH 2/2] iio: exynos-adc: add experimental touchscreen support Jonathan Cameron
2014-07-20 20:28         ` Dmitry Torokhov
2014-07-21 10:23           ` Arnd Bergmann
2014-07-21 10:26             ` Arnd Bergmann
2014-07-21 14:44             ` Dmitry Torokhov
2014-07-21 15:11               ` Arnd Bergmann
2014-07-21 16:19                 ` Dmitry Torokhov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).