* 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).