Re: [PATCH 2/2] iio: exynos-adc: add experimental touchscreen support

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

 



On Sunday 20 July 2014 23:37:18 Hartmut Knaack wrote:
> Jonathan Cameron schrieb:
> > On 18/07/14 20:29, Arnd Bergmann wrote:
> >> - 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).

Ok, I see. That's exactly the information I was looking for.

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

Ok.

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

Ok.

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

I expected the input stuff to just be left out by the compiler
if CONFIG_INPUT is not set. I'll try it out and change it if necessary.

> >>   	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;

Ok.


> >>   	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;
> Since info->read_ts is of type bool, use true/false.

Ok

> >> +
> >> +	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?

I'm not entirely sure about why we pass 0 here, it's either channel zero
being used for touchscreen, or the channel number being ignore after
we write to the TSC register above. I copied it from the original driver,
but it might be helpful if someone with access to the specs could comment
here.

I'll add a macro for now.

> >> +
> >> +	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.

Ok, adding ts_x and ts_y members.

> >> +		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.

Agreed. I thought about it, but then kept it as it was in the original
driver. Will change now.

> >> +		writel(ADC_TSC_WAIT4INT | ADC_S3C2443_TSC_UD_SEN, ADC_V1_TSC(info->regs));
> > Perhaps the above is cryptic enough to warrant a comment?

This is also taken directly from the old driver, I have no idea what
it really does...

> >> +	/* 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;
> Just return ret, without goto (and get rid of label err).

ok

> >> +	}
> >> +
> >> +	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;
> >> +
> Probably better to get rid of the labels and move the code up, as it is only used once.

Ok. I try not to mix goto and early return, so I've removed all the labels
here.

> >>   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;
> What about other possible error codes?

We handle them later, in the request_threaded_irq call. In particular,
if the touchscreen is not used because either the "has-touchscreen" flag
is not set or because the input layer is not available, failing to get
the irq line should not be treated as an error.

Checking -EPROBE_DEFER however makes sense, so we get out of the probe function
early and don't have to undo and later retry everything.

Thanks everybody for the review!

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-doc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux FS]     [Yosemite Forum]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux