* mfd: STMPExxxx fixes and touch screen support
[not found] <20100622135635.GA30720@bnru02.bnr.st.com>
@ 2010-06-24 11:13 ` Luotao Fu
2010-06-24 11:13 ` [PATCH 1/6] gpio/stmpe-gpio: set GPIO alternate function while requesting Luotao Fu
` (5 subsequent siblings)
6 siblings, 0 replies; 31+ messages in thread
From: Luotao Fu @ 2010-06-24 11:13 UTC (permalink / raw)
To: Rabin VINCENT, Samuel Ortiz, Dmitry Torokhov
Cc: Linus WALLEIJ, linux-kernel, linux-input,
STEricsson_nomadik_linux
Hi Rabin,
I merged your stmpexxx patches and tested them on my board with a stmpe811 chip
(gpio + touchscreen).
In the following are few fixes for the gpio driver. In the serie is also the V4
of my stmpe touchscreen driver, which is now converted to the stmpexxx core.
There appears to be two stmpe variants with a touchscreen controller: stmpe811
and stmpe610. I checked briefly the datasheet of stmpe610. It appears to be, as
far as I can see, identical with stmpe811. Hence I think that the stmpe-ts should
work for the stmpe610 too. Since I don't have a stmpe610 here, I didn't add the
stmpe610 support to the core. Maybe someone out there has possiblities to test
stmpe610, should not be too hard to add support for the chip to the core.
cheers
Luotao Fu
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 1/6] gpio/stmpe-gpio: set GPIO alternate function while requesting
[not found] <20100622135635.GA30720@bnru02.bnr.st.com>
2010-06-24 11:13 ` mfd: STMPExxxx fixes and touch screen support Luotao Fu
@ 2010-06-24 11:13 ` Luotao Fu
2010-06-24 12:43 ` Rabin VINCENT
2010-06-24 11:13 ` [PATCH 2/6] gpio/stmpe-gpio: fix set direction input Luotao Fu
` (4 subsequent siblings)
6 siblings, 1 reply; 31+ messages in thread
From: Luotao Fu @ 2010-06-24 11:13 UTC (permalink / raw)
To: Rabin VINCENT, Samuel Ortiz, Dmitry Torokhov
Cc: Linus WALLEIJ, linux-kernel, linux-input,
STEricsson_nomadik_linux, Luotao Fu
add reuqest hook to the gpio chip, so that we can make sure that the GPIO pin is
setted to the correct GPIO alternate function after we have requested the GPIO
pin.
Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
---
drivers/gpio/stmpe-gpio.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/drivers/gpio/stmpe-gpio.c b/drivers/gpio/stmpe-gpio.c
index bd49a3a..a4de271 100644
--- a/drivers/gpio/stmpe-gpio.c
+++ b/drivers/gpio/stmpe-gpio.c
@@ -98,6 +98,14 @@ static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
return stmpe_gpio->irq_base + offset;
}
+static int stmpe_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ struct stmpe_gpio *stmpe_gpio = to_stmpe_gpio(chip);
+ struct stmpe *stmpe = stmpe_gpio->stmpe;
+
+ return stmpe_set_altfunc(stmpe, 1 << offset, STMPE_BLOCK_GPIO);
+}
+
static struct gpio_chip template_chip = {
.label = "stmpe",
.owner = THIS_MODULE,
@@ -106,6 +114,7 @@ static struct gpio_chip template_chip = {
.direction_output = stmpe_gpio_direction_output,
.set = stmpe_gpio_set,
.to_irq = stmpe_gpio_to_irq,
+ .request = stmpe_gpio_request,
.can_sleep = 1,
};
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 1/6] gpio/stmpe-gpio: set GPIO alternate function while requesting
2010-06-24 11:13 ` [PATCH 1/6] gpio/stmpe-gpio: set GPIO alternate function while requesting Luotao Fu
@ 2010-06-24 12:43 ` Rabin VINCENT
0 siblings, 0 replies; 31+ messages in thread
From: Rabin VINCENT @ 2010-06-24 12:43 UTC (permalink / raw)
To: Luotao Fu
Cc: Samuel Ortiz, Dmitry Torokhov, Linus WALLEIJ,
linux-kernel@vger.kernel.org, linux-input@vger.kernel.org,
STEricsson_nomadik_linux
On Thu, Jun 24, 2010 at 13:13:36 +0200, Luotao Fu wrote:
> add reuqest hook to the gpio chip, so that we can make sure that the GPIO pin is
> setted to the correct GPIO alternate function after we have requested the GPIO
> pin.
>
> Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
Acked-by: Rabin Vincent <rabin.vincent@stericsson.com>
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 2/6] gpio/stmpe-gpio: fix set direction input
[not found] <20100622135635.GA30720@bnru02.bnr.st.com>
2010-06-24 11:13 ` mfd: STMPExxxx fixes and touch screen support Luotao Fu
2010-06-24 11:13 ` [PATCH 1/6] gpio/stmpe-gpio: set GPIO alternate function while requesting Luotao Fu
@ 2010-06-24 11:13 ` Luotao Fu
2010-06-24 12:03 ` Rabin VINCENT
2010-06-24 11:13 ` [PATCH 3/6] mfd/stmpexxx: add touchscreen platform data Luotao Fu
` (3 subsequent siblings)
6 siblings, 1 reply; 31+ messages in thread
From: Luotao Fu @ 2010-06-24 11:13 UTC (permalink / raw)
To: Rabin VINCENT, Samuel Ortiz, Dmitry Torokhov
Cc: Linus WALLEIJ, linux-kernel, linux-input,
STEricsson_nomadik_linux, Luotao Fu
to set an GPIO pin to input, the corresponding bit in GPDR needs to be cleared
instead of set. fixed with this patch.
Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
---
drivers/gpio/stmpe-gpio.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/gpio/stmpe-gpio.c b/drivers/gpio/stmpe-gpio.c
index a4de271..4e1f1b9 100644
--- a/drivers/gpio/stmpe-gpio.c
+++ b/drivers/gpio/stmpe-gpio.c
@@ -88,7 +88,7 @@ static int stmpe_gpio_direction_input(struct gpio_chip *chip,
u8 reg = stmpe->regs[STMPE_IDX_GPDR_LSB] - (offset / 8);
u8 mask = 1 << (offset % 8);
- return stmpe_set_bits(stmpe, reg, mask, mask);
+ return stmpe_set_bits(stmpe, reg, mask, 0);
}
static int stmpe_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 2/6] gpio/stmpe-gpio: fix set direction input
2010-06-24 11:13 ` [PATCH 2/6] gpio/stmpe-gpio: fix set direction input Luotao Fu
@ 2010-06-24 12:03 ` Rabin VINCENT
0 siblings, 0 replies; 31+ messages in thread
From: Rabin VINCENT @ 2010-06-24 12:03 UTC (permalink / raw)
To: Luotao Fu
Cc: Samuel Ortiz, Dmitry Torokhov, Linus WALLEIJ,
linux-kernel@vger.kernel.org, linux-input@vger.kernel.org,
STEricsson_nomadik_linux
On Thu, Jun 24, 2010 at 13:13:37 +0200, Luotao Fu wrote:
> to set an GPIO pin to input, the corresponding bit in GPDR needs to be cleared
> instead of set. fixed with this patch.
>
> Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
Acked-by: Rabin Vincent <rabin.vincent@stericsson.com>
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 3/6] mfd/stmpexxx: add touchscreen platform data
[not found] <20100622135635.GA30720@bnru02.bnr.st.com>
` (2 preceding siblings ...)
2010-06-24 11:13 ` [PATCH 2/6] gpio/stmpe-gpio: fix set direction input Luotao Fu
@ 2010-06-24 11:13 ` Luotao Fu
2010-06-24 11:13 ` [PATCH 4/6] mfd/stmpexxx: change touchscreen irq Luotao Fu
` (2 subsequent siblings)
6 siblings, 0 replies; 31+ messages in thread
From: Luotao Fu @ 2010-06-24 11:13 UTC (permalink / raw)
To: Rabin VINCENT, Samuel Ortiz, Dmitry Torokhov
Cc: Linus WALLEIJ, linux-kernel, linux-input,
STEricsson_nomadik_linux, Luotao Fu
Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
---
include/linux/mfd/stmpe.h | 43 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 43 insertions(+), 0 deletions(-)
diff --git a/include/linux/mfd/stmpe.h b/include/linux/mfd/stmpe.h
index cf2155f..3d319a1 100644
--- a/include/linux/mfd/stmpe.h
+++ b/include/linux/mfd/stmpe.h
@@ -124,6 +124,47 @@ struct stmpe_gpio_platform_data {
};
/**
+ * struct stmpe_ts_platform_data - stmpe811 touch screen controller platform
+ * data
+ * @sample_time: ADC converstion time in number of clock.
+ * (0 -> 36 clocks, 1 -> 44 clocks, 2 -> 56 clocks, 3 -> 64 clocks,
+ * 4 -> 80 clocks, 5 -> 96 clocks, 6 -> 144 clocks),
+ * recommended is 4.
+ * @mod_12b: ADC Bit mode (0 -> 10bit ADC, 1 -> 12bit ADC)
+ * @ref_sel: ADC reference source
+ * (0 -> internal reference, 1 -> external reference)
+ * @adc_freq: ADC Clock speed
+ * (0 -> 1.625 MHz, 1 -> 3.25 MHz, 2 || 3 -> 6.5 MHz)
+ * @ave_ctrl: Sample average control
+ * (0 -> 1 sample, 1 -> 2 samples, 2 -> 4 samples, 3 -> 8 samples)
+ * @touch_det_delay: Touch detect interrupt delay
+ * (0 -> 10 us, 1 -> 50 us, 2 -> 100 us, 3 -> 500 us,
+ * 4-> 1 ms, 5 -> 5 ms, 6 -> 10 ms, 7 -> 50 ms)
+ * recommended is 3
+ * @settling: Panel driver settling time
+ * (0 -> 10 us, 1 -> 100 us, 2 -> 500 us, 3 -> 1 ms,
+ * 4 -> 5 ms, 5 -> 10 ms, 6 for 50 ms, 7 -> 100 ms)
+ * recommended is 2
+ * @fraction_z: Length of the fractional part in z
+ * (fraction_z ([0..7]) = Count of the fractional part)
+ * recommended is 7
+ * @i_drive: current limit value of the touchscreen drivers
+ * (0 -> 20 mA typical 35 mA max, 1 -> 50 mA typical 80 mA max)
+ *
+ * */
+struct stmpe_ts_platform_data {
+ u8 sample_time;
+ u8 mod_12b;
+ u8 ref_sel;
+ u8 adc_freq;
+ u8 ave_ctrl;
+ u8 touch_det_delay;
+ u8 settling;
+ u8 fraction_z;
+ u8 i_drive;
+};
+
+/**
* struct stmpe_platform_data - STMPE platform data
* @id: device id to distinguish between multiple STMPEs on the same board
* @blocks: bitmask of blocks to enable (use STMPE_BLOCK_*)
@@ -133,6 +174,7 @@ struct stmpe_gpio_platform_data {
* %STMPE_NR_INTERNAL_IRQS if the GPIO driver is not used.
* @gpio: GPIO-specific platform data
* @keypad: keypad-specific platform data
+ * @ts: touchscreen-specific platform data
*/
struct stmpe_platform_data {
int id;
@@ -143,6 +185,7 @@ struct stmpe_platform_data {
struct stmpe_gpio_platform_data *gpio;
struct stmpe_keypad_platform_data *keypad;
+ struct stmpe_ts_platform_data *ts;
};
#define STMPE_NR_INTERNAL_IRQS 9
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 4/6] mfd/stmpexxx: change touchscreen irq
[not found] <20100622135635.GA30720@bnru02.bnr.st.com>
` (3 preceding siblings ...)
2010-06-24 11:13 ` [PATCH 3/6] mfd/stmpexxx: add touchscreen platform data Luotao Fu
@ 2010-06-24 11:13 ` Luotao Fu
2010-06-24 13:09 ` Rabin VINCENT
2010-06-24 11:13 ` [PATCH 5/6] mfd/stmpexxx: fix stmpe811 enable hook Luotao Fu
2010-06-24 11:13 ` [PATCH 6/6 V4] input: STMPE touch controller support Luotao Fu
6 siblings, 1 reply; 31+ messages in thread
From: Luotao Fu @ 2010-06-24 11:13 UTC (permalink / raw)
To: Rabin VINCENT, Samuel Ortiz, Dmitry Torokhov
Cc: Linus WALLEIJ, linux-kernel, linux-input,
STEricsson_nomadik_linux, Luotao Fu
the stmpe touchscreen driver uses fifo threshold irq to trigger data fetching.
The touch_det irq bit is only used while polling for release. Change the
platform resource and the irq definition in the variant block.
---
drivers/mfd/stmpe-devices.c | 12 +++---------
1 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/drivers/mfd/stmpe-devices.c b/drivers/mfd/stmpe-devices.c
index fa6934d..3e21c26 100644
--- a/drivers/mfd/stmpe-devices.c
+++ b/drivers/mfd/stmpe-devices.c
@@ -59,17 +59,11 @@ static struct mfd_cell stmpe_keypad_cell = {
static struct resource stmpe_ts_resources[] = {
{
- .name = "TOUCH_DET",
+ .name = "FIFO_TH",
.start = 0,
.end = 0,
.flags = IORESOURCE_IRQ,
- },
- {
- .name = "FIFO_TH",
- .start = 1,
- .end = 1,
- .flags = IORESOURCE_IRQ,
- },
+ }
};
static struct mfd_cell stmpe_ts_cell = {
@@ -107,7 +101,7 @@ static struct stmpe_variant_block stmpe811_blocks[] = {
},
{
.cell = &stmpe_ts_cell,
- .irq = STMPE811_IRQ_TOUCH_DET,
+ .irq = STMPE811_IRQ_FIFO_TH,
.block = STMPE_BLOCK_TOUCHSCREEN,
},
};
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 4/6] mfd/stmpexxx: change touchscreen irq
2010-06-24 11:13 ` [PATCH 4/6] mfd/stmpexxx: change touchscreen irq Luotao Fu
@ 2010-06-24 13:09 ` Rabin VINCENT
2010-06-24 13:17 ` Luotao Fu
0 siblings, 1 reply; 31+ messages in thread
From: Rabin VINCENT @ 2010-06-24 13:09 UTC (permalink / raw)
To: Luotao Fu
Cc: Samuel Ortiz, Dmitry Torokhov, Linus WALLEIJ,
linux-kernel@vger.kernel.org, linux-input@vger.kernel.org,
STEricsson_nomadik_linux
On Thu, Jun 24, 2010 at 13:13:39 +0200, Luotao Fu wrote:
> the stmpe touchscreen driver uses fifo threshold irq to trigger data fetching.
> The touch_det irq bit is only used while polling for release. Change the
> platform resource and the irq definition in the variant block.
> ---
> drivers/mfd/stmpe-devices.c | 12 +++---------
> 1 files changed, 3 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/mfd/stmpe-devices.c b/drivers/mfd/stmpe-devices.c
> index fa6934d..3e21c26 100644
> --- a/drivers/mfd/stmpe-devices.c
> +++ b/drivers/mfd/stmpe-devices.c
> @@ -59,17 +59,11 @@ static struct mfd_cell stmpe_keypad_cell = {
>
> static struct resource stmpe_ts_resources[] = {
> {
> - .name = "TOUCH_DET",
> + .name = "FIFO_TH",
> .start = 0,
> .end = 0,
> .flags = IORESOURCE_IRQ,
> - },
> - {
> - .name = "FIFO_TH",
> - .start = 1,
> - .end = 1,
> - .flags = IORESOURCE_IRQ,
> - },
> + }
> };
>
> static struct mfd_cell stmpe_ts_cell = {
> @@ -107,7 +101,7 @@ static struct stmpe_variant_block stmpe811_blocks[] = {
> },
> {
> .cell = &stmpe_ts_cell,
> - .irq = STMPE811_IRQ_TOUCH_DET,
> + .irq = STMPE811_IRQ_FIFO_TH,
> .block = STMPE_BLOCK_TOUCHSCREEN,
> },
> };
Would it be clearer if you leave this as-is, and instead use
platform_get_irq_byname("FIFO_TH") in the stmpe-ts driver, since I think
the TSC block has a whole bunch of irqs?
Rabin
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 4/6] mfd/stmpexxx: change touchscreen irq
2010-06-24 13:09 ` Rabin VINCENT
@ 2010-06-24 13:17 ` Luotao Fu
0 siblings, 0 replies; 31+ messages in thread
From: Luotao Fu @ 2010-06-24 13:17 UTC (permalink / raw)
To: Rabin VINCENT
Cc: Luotao Fu, Samuel Ortiz, Dmitry Torokhov, Linus WALLEIJ,
linux-kernel@vger.kernel.org, linux-input@vger.kernel.org,
STEricsson_nomadik_linux
[-- Attachment #1: Type: text/plain, Size: 2345 bytes --]
On Thu, Jun 24, 2010 at 06:39:43PM +0530, Rabin VINCENT wrote:
> On Thu, Jun 24, 2010 at 13:13:39 +0200, Luotao Fu wrote:
> > the stmpe touchscreen driver uses fifo threshold irq to trigger data fetching.
> > The touch_det irq bit is only used while polling for release. Change the
> > platform resource and the irq definition in the variant block.
> > ---
> > drivers/mfd/stmpe-devices.c | 12 +++---------
> > 1 files changed, 3 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/mfd/stmpe-devices.c b/drivers/mfd/stmpe-devices.c
> > index fa6934d..3e21c26 100644
> > --- a/drivers/mfd/stmpe-devices.c
> > +++ b/drivers/mfd/stmpe-devices.c
> > @@ -59,17 +59,11 @@ static struct mfd_cell stmpe_keypad_cell = {
> >
> > static struct resource stmpe_ts_resources[] = {
> > {
> > - .name = "TOUCH_DET",
> > + .name = "FIFO_TH",
> > .start = 0,
> > .end = 0,
> > .flags = IORESOURCE_IRQ,
> > - },
> > - {
> > - .name = "FIFO_TH",
> > - .start = 1,
> > - .end = 1,
> > - .flags = IORESOURCE_IRQ,
> > - },
> > + }
> > };
> >
> > static struct mfd_cell stmpe_ts_cell = {
> > @@ -107,7 +101,7 @@ static struct stmpe_variant_block stmpe811_blocks[] = {
> > },
> > {
> > .cell = &stmpe_ts_cell,
> > - .irq = STMPE811_IRQ_TOUCH_DET,
> > + .irq = STMPE811_IRQ_FIFO_TH,
> > .block = STMPE_BLOCK_TOUCHSCREEN,
> > },
> > };
>
> Would it be clearer if you leave this as-is, and instead use
> platform_get_irq_byname("FIFO_TH") in the stmpe-ts driver, since I think
> the TSC block has a whole bunch of irqs?
most of them belong to the ADC/FIFO and are actually of less use for the
touch driver as it is now. However, I agree with you on this. This way
the core can leave the driver to pick irqs as it wants and we are more
flexible if we want to change the algrorithmus later. You
can drop this patch than. I'll add the needed change to the ts driver
together with the register settings into V6 of the ts driver.
thanks
cheers
Luotao Fu
--
Pengutronix e.K. | Dipl.-Ing. Luotao Fu |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 5/6] mfd/stmpexxx: fix stmpe811 enable hook
[not found] <20100622135635.GA30720@bnru02.bnr.st.com>
` (4 preceding siblings ...)
2010-06-24 11:13 ` [PATCH 4/6] mfd/stmpexxx: change touchscreen irq Luotao Fu
@ 2010-06-24 11:13 ` Luotao Fu
2010-06-24 12:11 ` Rabin VINCENT
2010-06-24 11:13 ` [PATCH 6/6 V4] input: STMPE touch controller support Luotao Fu
6 siblings, 1 reply; 31+ messages in thread
From: Luotao Fu @ 2010-06-24 11:13 UTC (permalink / raw)
To: Rabin VINCENT, Samuel Ortiz, Dmitry Torokhov
Cc: Linus WALLEIJ, linux-kernel, linux-input,
STEricsson_nomadik_linux, Luotao Fu
Fix the stmpe811 enable hook so that we can activate the needed clocks for the
touchscreen controller.
Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
---
drivers/mfd/stmpe-devices.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/mfd/stmpe-devices.c b/drivers/mfd/stmpe-devices.c
index 3e21c26..25941ea 100644
--- a/drivers/mfd/stmpe-devices.c
+++ b/drivers/mfd/stmpe-devices.c
@@ -117,8 +117,9 @@ static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
if (blocks & STMPE_BLOCK_ADC)
mask |= STMPE811_SYS_CTRL2_ADC_OFF;
- if (blocks & STMPE_BLOCK_KEYPAD)
- mask |= STMPE811_SYS_CTRL2_TSC_OFF;
+ if (blocks & STMPE_BLOCK_TOUCHSCREEN)
+ mask |= STMPE811_SYS_CTRL2_ADC_OFF
+ | STMPE811_SYS_CTRL2_TSC_OFF;
return stmpe_set_bits(stmpe, STMPE811_REG_SYS_CTRL2, mask,
enable ? 0 : mask);
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 5/6] mfd/stmpexxx: fix stmpe811 enable hook
2010-06-24 11:13 ` [PATCH 5/6] mfd/stmpexxx: fix stmpe811 enable hook Luotao Fu
@ 2010-06-24 12:11 ` Rabin VINCENT
2010-06-24 12:32 ` Luotao Fu
0 siblings, 1 reply; 31+ messages in thread
From: Rabin VINCENT @ 2010-06-24 12:11 UTC (permalink / raw)
To: Luotao Fu
Cc: Samuel Ortiz, Dmitry Torokhov, Linus WALLEIJ,
linux-kernel@vger.kernel.org, linux-input@vger.kernel.org,
STEricsson_nomadik_linux
On Thu, Jun 24, 2010 at 13:13:40 +0200, Luotao Fu wrote:
> Fix the stmpe811 enable hook so that we can activate the needed clocks for the
> touchscreen controller.
>
> Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
> ---
> drivers/mfd/stmpe-devices.c | 5 +++--
> 1 files changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mfd/stmpe-devices.c b/drivers/mfd/stmpe-devices.c
> index 3e21c26..25941ea 100644
> --- a/drivers/mfd/stmpe-devices.c
> +++ b/drivers/mfd/stmpe-devices.c
> @@ -117,8 +117,9 @@ static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
> if (blocks & STMPE_BLOCK_ADC)
> mask |= STMPE811_SYS_CTRL2_ADC_OFF;
>
> - if (blocks & STMPE_BLOCK_KEYPAD)
> - mask |= STMPE811_SYS_CTRL2_TSC_OFF;
> + if (blocks & STMPE_BLOCK_TOUCHSCREEN)
> + mask |= STMPE811_SYS_CTRL2_ADC_OFF
> + | STMPE811_SYS_CTRL2_TSC_OFF;
The KEYPAD -> TOUCHSCREEN fix is fine, but for the ADC, wouldn't it be
better to pass in STMPE_BLOCK_ADC in your stmpe_enable() call instead?
You wouldn't need to add another call, you can just pass in
(STMPE_BLOCK_TOUCHSCREEN | STMPE_BLOCK_ADC) as the argument.
Rabin
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 5/6] mfd/stmpexxx: fix stmpe811 enable hook
2010-06-24 12:11 ` Rabin VINCENT
@ 2010-06-24 12:32 ` Luotao Fu
2010-06-24 12:47 ` [PATCH 5/6 V3] " Luotao Fu
0 siblings, 1 reply; 31+ messages in thread
From: Luotao Fu @ 2010-06-24 12:32 UTC (permalink / raw)
To: Rabin VINCENT
Cc: Luotao Fu, Samuel Ortiz, Dmitry Torokhov, Linus WALLEIJ,
linux-kernel@vger.kernel.org, linux-input@vger.kernel.org,
STEricsson_nomadik_linux
[-- Attachment #1: Type: text/plain, Size: 1843 bytes --]
On Thu, Jun 24, 2010 at 05:41:00PM +0530, Rabin VINCENT wrote:
> On Thu, Jun 24, 2010 at 13:13:40 +0200, Luotao Fu wrote:
> > Fix the stmpe811 enable hook so that we can activate the needed clocks for the
> > touchscreen controller.
> >
> > Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
> > ---
> > drivers/mfd/stmpe-devices.c | 5 +++--
> > 1 files changed, 3 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/mfd/stmpe-devices.c b/drivers/mfd/stmpe-devices.c
> > index 3e21c26..25941ea 100644
> > --- a/drivers/mfd/stmpe-devices.c
> > +++ b/drivers/mfd/stmpe-devices.c
> > @@ -117,8 +117,9 @@ static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
> > if (blocks & STMPE_BLOCK_ADC)
> > mask |= STMPE811_SYS_CTRL2_ADC_OFF;
> >
> > - if (blocks & STMPE_BLOCK_KEYPAD)
> > - mask |= STMPE811_SYS_CTRL2_TSC_OFF;
> > + if (blocks & STMPE_BLOCK_TOUCHSCREEN)
> > + mask |= STMPE811_SYS_CTRL2_ADC_OFF
> > + | STMPE811_SYS_CTRL2_TSC_OFF;
>
> The KEYPAD -> TOUCHSCREEN fix is fine, but for the ADC, wouldn't it be
> better to pass in STMPE_BLOCK_ADC in your stmpe_enable() call instead?
> You wouldn't need to add another call, you can just pass in
> (STMPE_BLOCK_TOUCHSCREEN | STMPE_BLOCK_ADC) as the argument.
agreed, this would be more clear. Just sent the V2 of this fix and V5 of
the ts driver. I Btw mixed message IDs up and the V2 of the enable hook fix
went out with the same "reply to" ID as the ts driver. doh! sorry for the
confusion.
cheers
Luotao Fu
--
Pengutronix e.K. | Dipl.-Ing. Luotao Fu |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 5/6 V3] mfd/stmpexxx: fix stmpe811 enable hook
2010-06-24 12:32 ` Luotao Fu
@ 2010-06-24 12:47 ` Luotao Fu
2010-06-24 13:05 ` Rabin VINCENT
0 siblings, 1 reply; 31+ messages in thread
From: Luotao Fu @ 2010-06-24 12:47 UTC (permalink / raw)
To: Rabin VINCENT, Samuel Ortiz, Dmitry Torokhov
Cc: Linus WALLEIJ, linux-kernel, linux-input,
STEricsson_nomadik_linux, Luotao Fu
Fix the stmpe811 enable hook so that we can activate the needed clocks for the
touchscreen controller.
Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
---
V2 Changes:
separate ADC block enable and ts block enable.
V3 Changes:
fixed silly typo
drivers/mfd/stmpe-devices.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/mfd/stmpe-devices.c b/drivers/mfd/stmpe-devices.c
index 3e21c26..066cab5 100644
--- a/drivers/mfd/stmpe-devices.c
+++ b/drivers/mfd/stmpe-devices.c
@@ -117,7 +117,7 @@ static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
if (blocks & STMPE_BLOCK_ADC)
mask |= STMPE811_SYS_CTRL2_ADC_OFF;
- if (blocks & STMPE_BLOCK_KEYPAD)
+ if (blocks & STMPE_BLOCK_TOUCHSCREEN)
mask |= STMPE811_SYS_CTRL2_TSC_OFF;
return stmpe_set_bits(stmpe, STMPE811_REG_SYS_CTRL2, mask,
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 6/6 V4] input: STMPE touch controller support
[not found] <20100622135635.GA30720@bnru02.bnr.st.com>
` (5 preceding siblings ...)
2010-06-24 11:13 ` [PATCH 5/6] mfd/stmpexxx: fix stmpe811 enable hook Luotao Fu
@ 2010-06-24 11:13 ` Luotao Fu
2010-06-24 12:27 ` [PATCH 5/6 V2] mfd/stmpexxx: fix stmpe811 enable hook Luotao Fu
` (2 more replies)
6 siblings, 3 replies; 31+ messages in thread
From: Luotao Fu @ 2010-06-24 11:13 UTC (permalink / raw)
To: Rabin VINCENT, Samuel Ortiz, Dmitry Torokhov
Cc: Linus WALLEIJ, linux-kernel, linux-input,
STEricsson_nomadik_linux, Luotao Fu
This one adds a driver for STMPE touchscreen controllers. This driver depends on
stmpexxx mfd core driver.
Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
---
V2 Changes:
* include subsystem headers since they are now remove from the mfd
core header file
* use genirq to register threaded isr. The stmpe811 own irq callbacks
are dropped in the core driver.
* use STMPE811_TS_NAME for name all over the place
* wait for completion of core IO operation before cancelling polling of
release event.
* switch to platform data for configuration parameters.
* add FIFO reset to open callback, also reset FIFO before reporting
release.
V3 Changes:
* reformated platform data comments to kernel-doc style
V4 Changes:
* converted to stmpexxx core by Rabin Vincent <rabin.vincent@stericsson.com>
* wait for running workqueue callback to finish while canceling the queue
* add i_drive configuration support
drivers/input/touchscreen/Kconfig | 10 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/stmpe-ts.c | 380 ++++++++++++++++++++++++++++++++++
3 files changed, 391 insertions(+), 0 deletions(-)
create mode 100644 drivers/input/touchscreen/stmpe-ts.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 3b9d5e2..96a9954 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -603,4 +603,14 @@ config TOUCHSCREEN_TPS6507X
To compile this driver as a module, choose M here: the
module will be called tps6507x_ts.
+config TOUCHSCREEN_STMPE
+ tristate "STMicroelectronics STMPE touchscreens"
+ depends on MFD_STMPE
+ help
+ Say Y here if you want support for STMicroelectronics
+ STMPE touchscreen controllers.
+
+ To compile this driver as a module, choose M here: the
+ module will be called stmpe-ts.
+
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 497964a..2691c62 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -47,3 +47,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
+obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c
new file mode 100644
index 0000000..260b175
--- /dev/null
+++ b/drivers/input/touchscreen/stmpe-ts.c
@@ -0,0 +1,380 @@
+/* STMicroelectronics STMPE811 Touchscreen Driver
+ *
+ * (C) 2010 Luotao Fu <l.fu@pengutronix.de>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+
+#include <linux/mfd/stmpe.h>
+
+/* Register layouts and functionalities are identical on all stmpexxx variants
+ * with touchscreen controller
+ */
+#define STMPE_REG_INT_STA 0x0B
+#define STMPE_REG_ADC_CTRL1 0x20
+#define STMPE_REG_ADC_CTRL2 0x21
+#define STMPE_REG_TSC_CTRL 0x40
+#define STMPE_REG_TSC_CFG 0x41
+#define STMPE_REG_FIFO_TH 0x4A
+#define STMPE_REG_FIFO_STA 0x4B
+#define STMPE_REG_FIFO_SIZE 0x4C
+#define STMPE_REG_TSC_DATA_XYZ 0x52
+#define STMPE_REG_TSC_FRACTION_Z 0x56
+#define STMPE_REG_TSC_I_DRIVE 0x58
+
+#define STMPE_TSC_CTRL_OP_MOD_XYZ (0<<1)
+
+#define STMPE_TSC_CTRL_TSC_EN (1<<0)
+
+#define STMPE_FIFO_STA_RESET (1<<0)
+
+#define STMPE_IRQ_TOUCH_DET 0
+
+#define SAMPLE_TIME(x) ((x & 0xf) << 4)
+#define MOD_12B(x) ((x & 0x1) << 3)
+#define REF_SEL(x) ((x & 0x1) << 1)
+#define ADC_FREQ(x) (x & 0x3)
+#define AVE_CTRL(x) ((x & 0x3) << 6)
+#define DET_DELAY(x) ((x & 0x7) << 3)
+#define SETTLING(x) (x & 0x7)
+#define FRACTION_Z(x) (x & 0x7)
+#define I_DRIVE(x) (x & 0x1)
+
+#define STMPE_TS_NAME "stmpe-ts"
+#define XY_MASK 0xfff
+
+struct stmpe_touch {
+ struct stmpe *stmpe;
+ struct input_dev *idev;
+ struct delayed_work work;
+ u8 sample_time;
+ u8 mod_12b;
+ u8 ref_sel;
+ u8 adc_freq;
+ u8 ave_ctrl;
+ u8 touch_det_delay;
+ u8 settling;
+ u8 fraction_z;
+ u8 i_drive;
+};
+
+static void stmpe_work(struct work_struct *work)
+{
+ int int_sta;
+ u32 timeout = 40;
+
+ struct stmpe_touch *ts =
+ container_of(work, struct stmpe_touch, work.work);
+
+ int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA);
+
+ /* touch_det sometimes get desasserted or just get stuck. This appears
+ * to be a silicon bug, We still have to clearify this with the
+ * manufacture. As a workaround We release the key anyway if the
+ * touch_det keeps coming in after 4ms, while the FIFO contains no value
+ * during the whole time. */
+ while ((int_sta & (1 << STMPE_IRQ_TOUCH_DET)) && (timeout > 0)) {
+ timeout--;
+ int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA);
+ udelay(100);
+ }
+
+ /* reset the FIFO before we report release event */
+ stmpe_set_bits(ts->stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, STMPE_FIFO_STA_RESET);
+ stmpe_set_bits(ts->stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, 0);
+
+ input_report_abs(ts->idev, ABS_PRESSURE, 0);
+ input_sync(ts->idev);
+}
+
+static irqreturn_t stmpe_ts_handler(int irq, void *data)
+{
+ u8 data_set[4];
+ int x, y, z;
+ struct stmpe_touch *ts = data;
+
+ /* Cancel scheduled polling for release if we have new value
+ * available. Wait if the polling is already running. */
+ cancel_delayed_work_sync(&ts->work);
+
+ /*
+ * The FIFO sometimes just crashes and stops generating interrupts. This
+ * appears to be a silicon bug. We still have to clearify this with
+ * the manufacture. As a workaround we disable the TSC while we are
+ * collecting data and flush the FIFO after reading
+ */
+ stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, 0);
+
+ stmpe_block_read(ts->stmpe, STMPE_REG_TSC_DATA_XYZ, 4, data_set);
+
+ x = (data_set[0] << 4) | (data_set[1] >> 4);
+ y = ((data_set[1] & 0xf) << 8) | data_set[2];
+ z = data_set[3];
+
+ input_report_abs(ts->idev, ABS_X, x);
+ input_report_abs(ts->idev, ABS_Y, y);
+ input_report_abs(ts->idev, ABS_PRESSURE, z);
+ input_sync(ts->idev);
+
+ /* flush the FIFO after we have read out our values. */
+ stmpe_set_bits(ts->stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, STMPE_FIFO_STA_RESET);
+ stmpe_set_bits(ts->stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, 0);
+
+ /* reenable the tsc */
+ stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN);
+
+ /* start polling for touch_det to detect release */
+ schedule_delayed_work(&ts->work, HZ / 50);
+
+ return IRQ_HANDLED;
+}
+
+static int stmpe_ts_open(struct input_dev *dev)
+{
+ struct stmpe_touch *ts = input_get_drvdata(dev);
+ int ret = 0;
+
+ ret = stmpe_set_bits(ts->stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, STMPE_FIFO_STA_RESET);
+ if (ret)
+ goto out;
+
+ ret = stmpe_set_bits(ts->stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, 0);
+ if (ret)
+ goto out;
+
+ ret = stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN);
+ if (ret)
+ goto out;
+
+out:
+ return ret;
+}
+
+static void stmpe_ts_close(struct input_dev *dev)
+{
+ struct stmpe_touch *ts = input_get_drvdata(dev);
+
+ stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, 0);
+}
+
+static int __devinit stmpe_input_probe(struct platform_device *pdev)
+{
+ struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
+ struct stmpe_platform_data *pdata = stmpe->pdata;
+ struct stmpe_touch *ts;
+ struct input_dev *idev;
+ struct stmpe_ts_platform_data *ts_pdata = NULL;
+ int ret = 0;
+ unsigned int ts_irq;
+ u8 adc_ctrl1, tsc_cfg;
+
+ ts_irq = platform_get_irq(pdev, 0);
+ if (ts_irq < 0)
+ return ts_irq;
+
+ ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+ if (!ts)
+ goto err_out;
+
+ idev = input_allocate_device();
+ if (!idev)
+ goto err_free_ts;
+
+ platform_set_drvdata(pdev, ts);
+ ts->stmpe = stmpe;
+ ts->idev = idev;
+
+ if (pdata)
+ ts_pdata = pdata->ts;
+
+ if (ts_pdata) {
+ ts->sample_time = ts_pdata->sample_time;
+ ts->mod_12b = ts_pdata->mod_12b;
+ ts->ref_sel = ts_pdata->ref_sel;
+ ts->adc_freq = ts_pdata->adc_freq;
+ ts->ave_ctrl = ts_pdata->ave_ctrl;
+ ts->touch_det_delay = ts_pdata->touch_det_delay;
+ ts->settling = ts_pdata->settling;
+ ts->fraction_z = ts_pdata->fraction_z;
+ ts->i_drive = ts_pdata->i_drive;
+ }
+
+ INIT_DELAYED_WORK(&ts->work, stmpe_work);
+
+ ret = request_threaded_irq(ts_irq, NULL, stmpe_ts_handler,
+ IRQF_ONESHOT, STMPE_TS_NAME, ts);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request IRQ %d\n", ts_irq);
+ goto err_free_input;
+ }
+
+ ret = stmpe_enable(stmpe, STMPE_BLOCK_TOUCHSCREEN);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not enable clock for ADC and TS\n");
+ goto err_free_irq;
+ }
+
+ adc_ctrl1 = SAMPLE_TIME(ts->sample_time) | MOD_12B(ts->mod_12b) |
+ REF_SEL(ts->ref_sel);
+ ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1,
+ adc_ctrl1, adc_ctrl1);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not setup ADC\n");
+ goto err_free_irq;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2,
+ ADC_FREQ(ts->adc_freq), ADC_FREQ(ts->adc_freq));
+ if (ret) {
+ dev_err(&pdev->dev, "Could not setup ADC\n");
+ goto err_free_irq;
+ }
+
+ tsc_cfg = AVE_CTRL(ts->ave_ctrl) | DET_DELAY(ts->touch_det_delay) |
+ SETTLING(ts->settling);
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CFG, tsc_cfg, tsc_cfg);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not config touch\n");
+ goto err_free_irq;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z,
+ FRACTION_Z(ts->fraction_z),
+ FRACTION_Z(ts->fraction_z));
+ if (ret) {
+ dev_err(&pdev->dev, "Could not config touch\n");
+ goto err_free_irq;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_I_DRIVE,
+ I_DRIVE(ts->i_drive), I_DRIVE(ts->i_drive));
+ if (ret) {
+ dev_err(&pdev->dev, "Could not config touch\n");
+ goto err_free_irq;
+ }
+
+ /* set FIFO to 1 for single point reading */
+ ret = stmpe_reg_write(stmpe, STMPE_REG_FIFO_TH, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not set FIFO\n");
+ goto err_free_irq;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_OP_MOD_XYZ,
+ STMPE_TSC_CTRL_OP_MOD_XYZ);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not set mode\n");
+ goto err_free_irq;
+ }
+
+ idev->name = STMPE_TS_NAME;
+ idev->id.bustype = BUS_I2C;
+ idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ idev->open = stmpe_ts_open;
+ idev->close = stmpe_ts_close;
+
+ input_set_drvdata(idev, ts);
+
+ ret = input_register_device(idev);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not register input device\n");
+ goto err_free_irq;
+ }
+
+ input_set_abs_params(idev, ABS_X, 0, XY_MASK, 0, 0);
+ input_set_abs_params(idev, ABS_Y, 0, XY_MASK, 0, 0);
+ input_set_abs_params(idev, ABS_PRESSURE, 0x0, 0xff, 0, 0);
+
+ return ret;
+
+err_free_irq:
+ free_irq(ts_irq, ts);
+err_free_input:
+ input_free_device(idev);
+ platform_set_drvdata(pdev, NULL);
+err_free_ts:
+ kfree(ts);
+err_out:
+ return ret;
+}
+
+static int __devexit stmpe_ts_remove(struct platform_device *pdev)
+{
+ struct stmpe_touch *ts = platform_get_drvdata(pdev);
+ unsigned int ts_irq = platform_get_irq(pdev, 0);
+
+ cancel_delayed_work(&ts->work);
+
+ stmpe_reg_write(ts->stmpe, STMPE_REG_FIFO_TH, 0);
+
+ stmpe_disable(ts->stmpe, STMPE_BLOCK_TOUCHSCREEN);
+
+ free_irq(ts_irq, ts);
+
+ platform_set_drvdata(pdev, NULL);
+
+ input_unregister_device(ts->idev);
+ input_free_device(ts->idev);
+
+ kfree(ts);
+
+ return 0;
+}
+
+static struct platform_driver stmpe_ts_driver = {
+ .driver = {
+ .name = STMPE_TS_NAME,
+ },
+ .probe = stmpe_input_probe,
+ .remove = __devexit_p(stmpe_ts_remove),
+};
+
+static int __init stmpe_ts_init(void)
+{
+ return platform_driver_register(&stmpe_ts_driver);
+}
+
+module_init(stmpe_ts_init);
+
+static void __exit stmpe_ts_exit(void)
+{
+ platform_driver_unregister(&stmpe_ts_driver);
+}
+
+module_exit(stmpe_ts_exit);
+
+MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");
+MODULE_DESCRIPTION("STMPEXXX touchscreen driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" STMPE_TS_NAME);
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 5/6 V2] mfd/stmpexxx: fix stmpe811 enable hook
2010-06-24 11:13 ` [PATCH 6/6 V4] input: STMPE touch controller support Luotao Fu
@ 2010-06-24 12:27 ` Luotao Fu
2010-06-24 12:35 ` Rabin VINCENT
2010-06-24 12:28 ` [PATCH 6/6 V5] input: STMPE touch controller support Luotao Fu
2010-06-24 12:31 ` [PATCH 6/6 V4] " Rabin VINCENT
2 siblings, 1 reply; 31+ messages in thread
From: Luotao Fu @ 2010-06-24 12:27 UTC (permalink / raw)
To: Rabin VINCENT, Samuel Ortiz, Dmitry Torokhov
Cc: Linus WALLEIJ, linux-kernel, linux-input,
STEricsson_nomadik_linux, Luotao Fu
Fix the stmpe811 enable hook so that we can activate the needed clocks for the
touchscreen controller.
Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
---
V2 Changes:
separate ADC block enable and ts block enable.
drivers/mfd/stmpe-devices.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mfd/stmpe-devices.c b/drivers/mfd/stmpe-devices.c
index 3e21c26..ded9dcb 100644
--- a/drivers/mfd/stmpe-devices.c
+++ b/drivers/mfd/stmpe-devices.c
@@ -117,8 +117,8 @@ static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
if (blocks & STMPE_BLOCK_ADC)
mask |= STMPE811_SYS_CTRL2_ADC_OFF;
- if (blocks & STMPE_BLOCK_KEYPAD)
- mask |= STMPE811_SYS_CTRL2_TSC_OFF;
+ if (blocks & STMPE_BLOCK_TOUCHSCREEN)
+ mask |= STMPE811_SYS_CTRL2_ADC_OFF;
return stmpe_set_bits(stmpe, STMPE811_REG_SYS_CTRL2, mask,
enable ? 0 : mask);
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 5/6 V2] mfd/stmpexxx: fix stmpe811 enable hook
2010-06-24 12:27 ` [PATCH 5/6 V2] mfd/stmpexxx: fix stmpe811 enable hook Luotao Fu
@ 2010-06-24 12:35 ` Rabin VINCENT
2010-06-24 12:46 ` Luotao Fu
0 siblings, 1 reply; 31+ messages in thread
From: Rabin VINCENT @ 2010-06-24 12:35 UTC (permalink / raw)
To: Luotao Fu
Cc: Samuel Ortiz, Dmitry Torokhov, Linus WALLEIJ,
linux-kernel@vger.kernel.org, linux-input@vger.kernel.org,
STEricsson_nomadik_linux
On Thu, Jun 24, 2010 at 14:27:46 +0200, Luotao Fu wrote:
> diff --git a/drivers/mfd/stmpe-devices.c b/drivers/mfd/stmpe-devices.c
> index 3e21c26..ded9dcb 100644
> --- a/drivers/mfd/stmpe-devices.c
> +++ b/drivers/mfd/stmpe-devices.c
> @@ -117,8 +117,8 @@ static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
> if (blocks & STMPE_BLOCK_ADC)
> mask |= STMPE811_SYS_CTRL2_ADC_OFF;
>
> - if (blocks & STMPE_BLOCK_KEYPAD)
> - mask |= STMPE811_SYS_CTRL2_TSC_OFF;
> + if (blocks & STMPE_BLOCK_TOUCHSCREEN)
> + mask |= STMPE811_SYS_CTRL2_ADC_OFF;
>
You shouldn't be changing TSC_OFF to ADC_OFF, since you're making this
for the touchscreen.
Rabin
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 5/6 V2] mfd/stmpexxx: fix stmpe811 enable hook
2010-06-24 12:35 ` Rabin VINCENT
@ 2010-06-24 12:46 ` Luotao Fu
0 siblings, 0 replies; 31+ messages in thread
From: Luotao Fu @ 2010-06-24 12:46 UTC (permalink / raw)
To: Rabin VINCENT
Cc: Luotao Fu, Samuel Ortiz, Dmitry Torokhov, Linus WALLEIJ,
linux-kernel@vger.kernel.org, linux-input@vger.kernel.org,
STEricsson_nomadik_linux
[-- Attachment #1: Type: text/plain, Size: 1198 bytes --]
On Thu, Jun 24, 2010 at 06:05:42PM +0530, Rabin VINCENT wrote:
> On Thu, Jun 24, 2010 at 14:27:46 +0200, Luotao Fu wrote:
> > diff --git a/drivers/mfd/stmpe-devices.c b/drivers/mfd/stmpe-devices.c
> > index 3e21c26..ded9dcb 100644
> > --- a/drivers/mfd/stmpe-devices.c
> > +++ b/drivers/mfd/stmpe-devices.c
> > @@ -117,8 +117,8 @@ static int stmpe811_enable(struct stmpe *stmpe, unsigned int blocks,
> > if (blocks & STMPE_BLOCK_ADC)
> > mask |= STMPE811_SYS_CTRL2_ADC_OFF;
> >
> > - if (blocks & STMPE_BLOCK_KEYPAD)
> > - mask |= STMPE811_SYS_CTRL2_TSC_OFF;
> > + if (blocks & STMPE_BLOCK_TOUCHSCREEN)
> > + mask |= STMPE811_SYS_CTRL2_ADC_OFF;
> >
>
> You shouldn't be changing TSC_OFF to ADC_OFF, since you're making this
> for the touchscreen.
>
doh! I need more coffee. This is truly embarassing. :-) Proper fix in
following.
cheers
Luotao Fu
--
Pengutronix e.K. | Dipl.-Ing. Luotao Fu |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 6/6 V5] input: STMPE touch controller support
2010-06-24 11:13 ` [PATCH 6/6 V4] input: STMPE touch controller support Luotao Fu
2010-06-24 12:27 ` [PATCH 5/6 V2] mfd/stmpexxx: fix stmpe811 enable hook Luotao Fu
@ 2010-06-24 12:28 ` Luotao Fu
2010-06-24 14:26 ` [PATCH 5/5] " Luotao Fu
2010-06-24 12:31 ` [PATCH 6/6 V4] " Rabin VINCENT
2 siblings, 1 reply; 31+ messages in thread
From: Luotao Fu @ 2010-06-24 12:28 UTC (permalink / raw)
To: Rabin VINCENT, Samuel Ortiz, Dmitry Torokhov
Cc: Linus WALLEIJ, linux-kernel, linux-input,
STEricsson_nomadik_linux, Luotao Fu
This one adds a driver for STMPE touchscreen controllers. This driver depends on
stmpexxx mfd core driver.
Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
---
V2 Changes:
* include subsystem headers since they are now remove from the mfd
core header file
* use genirq to register threaded isr. The stmpe811 own irq callbacks
are dropped in the core driver.
* use STMPE811_TS_NAME for name all over the place
* wait for completion of core IO operation before cancelling polling of
release event.
* switch to platform data for configuration parameters.
* add FIFO reset to open callback, also reset FIFO before reporting
release.
V3 Changes:
* reformated platform data comments to kernel-doc style
V4 Changes:
* converted to stmpexxx core by Rabin Vincent <rabin.vincent@stericsson.com>
* wait for running workqueue callback to finish while canceling the queue
* add i_drive configuration support
V5 Changes:
* add ADC block enable to stmpe_enable call.
drivers/input/touchscreen/Kconfig | 10 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/stmpe-ts.c | 380 ++++++++++++++++++++++++++++++++++
3 files changed, 391 insertions(+), 0 deletions(-)
create mode 100644 drivers/input/touchscreen/stmpe-ts.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 3b9d5e2..96a9954 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -603,4 +603,14 @@ config TOUCHSCREEN_TPS6507X
To compile this driver as a module, choose M here: the
module will be called tps6507x_ts.
+config TOUCHSCREEN_STMPE
+ tristate "STMicroelectronics STMPE touchscreens"
+ depends on MFD_STMPE
+ help
+ Say Y here if you want support for STMicroelectronics
+ STMPE touchscreen controllers.
+
+ To compile this driver as a module, choose M here: the
+ module will be called stmpe-ts.
+
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 497964a..2691c62 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -47,3 +47,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
+obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c
new file mode 100644
index 0000000..5094a33
--- /dev/null
+++ b/drivers/input/touchscreen/stmpe-ts.c
@@ -0,0 +1,380 @@
+/* STMicroelectronics STMPE811 Touchscreen Driver
+ *
+ * (C) 2010 Luotao Fu <l.fu@pengutronix.de>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+
+#include <linux/mfd/stmpe.h>
+
+/* Register layouts and functionalities are identical on all stmpexxx variants
+ * with touchscreen controller
+ */
+#define STMPE_REG_INT_STA 0x0B
+#define STMPE_REG_ADC_CTRL1 0x20
+#define STMPE_REG_ADC_CTRL2 0x21
+#define STMPE_REG_TSC_CTRL 0x40
+#define STMPE_REG_TSC_CFG 0x41
+#define STMPE_REG_FIFO_TH 0x4A
+#define STMPE_REG_FIFO_STA 0x4B
+#define STMPE_REG_FIFO_SIZE 0x4C
+#define STMPE_REG_TSC_DATA_XYZ 0x52
+#define STMPE_REG_TSC_FRACTION_Z 0x56
+#define STMPE_REG_TSC_I_DRIVE 0x58
+
+#define STMPE_TSC_CTRL_OP_MOD_XYZ (0<<1)
+
+#define STMPE_TSC_CTRL_TSC_EN (1<<0)
+
+#define STMPE_FIFO_STA_RESET (1<<0)
+
+#define STMPE_IRQ_TOUCH_DET 0
+
+#define SAMPLE_TIME(x) ((x & 0xf) << 4)
+#define MOD_12B(x) ((x & 0x1) << 3)
+#define REF_SEL(x) ((x & 0x1) << 1)
+#define ADC_FREQ(x) (x & 0x3)
+#define AVE_CTRL(x) ((x & 0x3) << 6)
+#define DET_DELAY(x) ((x & 0x7) << 3)
+#define SETTLING(x) (x & 0x7)
+#define FRACTION_Z(x) (x & 0x7)
+#define I_DRIVE(x) (x & 0x1)
+
+#define STMPE_TS_NAME "stmpe-ts"
+#define XY_MASK 0xfff
+
+struct stmpe_touch {
+ struct stmpe *stmpe;
+ struct input_dev *idev;
+ struct delayed_work work;
+ u8 sample_time;
+ u8 mod_12b;
+ u8 ref_sel;
+ u8 adc_freq;
+ u8 ave_ctrl;
+ u8 touch_det_delay;
+ u8 settling;
+ u8 fraction_z;
+ u8 i_drive;
+};
+
+static void stmpe_work(struct work_struct *work)
+{
+ int int_sta;
+ u32 timeout = 40;
+
+ struct stmpe_touch *ts =
+ container_of(work, struct stmpe_touch, work.work);
+
+ int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA);
+
+ /* touch_det sometimes get desasserted or just get stuck. This appears
+ * to be a silicon bug, We still have to clearify this with the
+ * manufacture. As a workaround We release the key anyway if the
+ * touch_det keeps coming in after 4ms, while the FIFO contains no value
+ * during the whole time. */
+ while ((int_sta & (1 << STMPE_IRQ_TOUCH_DET)) && (timeout > 0)) {
+ timeout--;
+ int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA);
+ udelay(100);
+ }
+
+ /* reset the FIFO before we report release event */
+ stmpe_set_bits(ts->stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, STMPE_FIFO_STA_RESET);
+ stmpe_set_bits(ts->stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, 0);
+
+ input_report_abs(ts->idev, ABS_PRESSURE, 0);
+ input_sync(ts->idev);
+}
+
+static irqreturn_t stmpe_ts_handler(int irq, void *data)
+{
+ u8 data_set[4];
+ int x, y, z;
+ struct stmpe_touch *ts = data;
+
+ /* Cancel scheduled polling for release if we have new value
+ * available. Wait if the polling is already running. */
+ cancel_delayed_work_sync(&ts->work);
+
+ /*
+ * The FIFO sometimes just crashes and stops generating interrupts. This
+ * appears to be a silicon bug. We still have to clearify this with
+ * the manufacture. As a workaround we disable the TSC while we are
+ * collecting data and flush the FIFO after reading
+ */
+ stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, 0);
+
+ stmpe_block_read(ts->stmpe, STMPE_REG_TSC_DATA_XYZ, 4, data_set);
+
+ x = (data_set[0] << 4) | (data_set[1] >> 4);
+ y = ((data_set[1] & 0xf) << 8) | data_set[2];
+ z = data_set[3];
+
+ input_report_abs(ts->idev, ABS_X, x);
+ input_report_abs(ts->idev, ABS_Y, y);
+ input_report_abs(ts->idev, ABS_PRESSURE, z);
+ input_sync(ts->idev);
+
+ /* flush the FIFO after we have read out our values. */
+ stmpe_set_bits(ts->stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, STMPE_FIFO_STA_RESET);
+ stmpe_set_bits(ts->stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, 0);
+
+ /* reenable the tsc */
+ stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN);
+
+ /* start polling for touch_det to detect release */
+ schedule_delayed_work(&ts->work, HZ / 50);
+
+ return IRQ_HANDLED;
+}
+
+static int stmpe_ts_open(struct input_dev *dev)
+{
+ struct stmpe_touch *ts = input_get_drvdata(dev);
+ int ret = 0;
+
+ ret = stmpe_set_bits(ts->stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, STMPE_FIFO_STA_RESET);
+ if (ret)
+ goto out;
+
+ ret = stmpe_set_bits(ts->stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, 0);
+ if (ret)
+ goto out;
+
+ ret = stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN);
+ if (ret)
+ goto out;
+
+out:
+ return ret;
+}
+
+static void stmpe_ts_close(struct input_dev *dev)
+{
+ struct stmpe_touch *ts = input_get_drvdata(dev);
+
+ stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, 0);
+}
+
+static int __devinit stmpe_input_probe(struct platform_device *pdev)
+{
+ struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
+ struct stmpe_platform_data *pdata = stmpe->pdata;
+ struct stmpe_touch *ts;
+ struct input_dev *idev;
+ struct stmpe_ts_platform_data *ts_pdata = NULL;
+ int ret = 0;
+ unsigned int ts_irq;
+ u8 adc_ctrl1, tsc_cfg;
+
+ ts_irq = platform_get_irq(pdev, 0);
+ if (ts_irq < 0)
+ return ts_irq;
+
+ ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+ if (!ts)
+ goto err_out;
+
+ idev = input_allocate_device();
+ if (!idev)
+ goto err_free_ts;
+
+ platform_set_drvdata(pdev, ts);
+ ts->stmpe = stmpe;
+ ts->idev = idev;
+
+ if (pdata)
+ ts_pdata = pdata->ts;
+
+ if (ts_pdata) {
+ ts->sample_time = ts_pdata->sample_time;
+ ts->mod_12b = ts_pdata->mod_12b;
+ ts->ref_sel = ts_pdata->ref_sel;
+ ts->adc_freq = ts_pdata->adc_freq;
+ ts->ave_ctrl = ts_pdata->ave_ctrl;
+ ts->touch_det_delay = ts_pdata->touch_det_delay;
+ ts->settling = ts_pdata->settling;
+ ts->fraction_z = ts_pdata->fraction_z;
+ ts->i_drive = ts_pdata->i_drive;
+ }
+
+ INIT_DELAYED_WORK(&ts->work, stmpe_work);
+
+ ret = request_threaded_irq(ts_irq, NULL, stmpe_ts_handler,
+ IRQF_ONESHOT, STMPE_TS_NAME, ts);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request IRQ %d\n", ts_irq);
+ goto err_free_input;
+ }
+
+ ret = stmpe_enable(stmpe, STMPE_BLOCK_TOUCHSCREEN | STMPE_BLOCK_ADC);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not enable clock for ADC and TS\n");
+ goto err_free_irq;
+ }
+
+ adc_ctrl1 = SAMPLE_TIME(ts->sample_time) | MOD_12B(ts->mod_12b) |
+ REF_SEL(ts->ref_sel);
+ ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1,
+ adc_ctrl1, adc_ctrl1);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not setup ADC\n");
+ goto err_free_irq;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2,
+ ADC_FREQ(ts->adc_freq), ADC_FREQ(ts->adc_freq));
+ if (ret) {
+ dev_err(&pdev->dev, "Could not setup ADC\n");
+ goto err_free_irq;
+ }
+
+ tsc_cfg = AVE_CTRL(ts->ave_ctrl) | DET_DELAY(ts->touch_det_delay) |
+ SETTLING(ts->settling);
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CFG, tsc_cfg, tsc_cfg);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not config touch\n");
+ goto err_free_irq;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z,
+ FRACTION_Z(ts->fraction_z),
+ FRACTION_Z(ts->fraction_z));
+ if (ret) {
+ dev_err(&pdev->dev, "Could not config touch\n");
+ goto err_free_irq;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_I_DRIVE,
+ I_DRIVE(ts->i_drive), I_DRIVE(ts->i_drive));
+ if (ret) {
+ dev_err(&pdev->dev, "Could not config touch\n");
+ goto err_free_irq;
+ }
+
+ /* set FIFO to 1 for single point reading */
+ ret = stmpe_reg_write(stmpe, STMPE_REG_FIFO_TH, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not set FIFO\n");
+ goto err_free_irq;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_OP_MOD_XYZ,
+ STMPE_TSC_CTRL_OP_MOD_XYZ);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not set mode\n");
+ goto err_free_irq;
+ }
+
+ idev->name = STMPE_TS_NAME;
+ idev->id.bustype = BUS_I2C;
+ idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ idev->open = stmpe_ts_open;
+ idev->close = stmpe_ts_close;
+
+ input_set_drvdata(idev, ts);
+
+ ret = input_register_device(idev);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not register input device\n");
+ goto err_free_irq;
+ }
+
+ input_set_abs_params(idev, ABS_X, 0, XY_MASK, 0, 0);
+ input_set_abs_params(idev, ABS_Y, 0, XY_MASK, 0, 0);
+ input_set_abs_params(idev, ABS_PRESSURE, 0x0, 0xff, 0, 0);
+
+ return ret;
+
+err_free_irq:
+ free_irq(ts_irq, ts);
+err_free_input:
+ input_free_device(idev);
+ platform_set_drvdata(pdev, NULL);
+err_free_ts:
+ kfree(ts);
+err_out:
+ return ret;
+}
+
+static int __devexit stmpe_ts_remove(struct platform_device *pdev)
+{
+ struct stmpe_touch *ts = platform_get_drvdata(pdev);
+ unsigned int ts_irq = platform_get_irq(pdev, 0);
+
+ cancel_delayed_work(&ts->work);
+
+ stmpe_reg_write(ts->stmpe, STMPE_REG_FIFO_TH, 0);
+
+ stmpe_disable(ts->stmpe, STMPE_BLOCK_TOUCHSCREEN);
+
+ free_irq(ts_irq, ts);
+
+ platform_set_drvdata(pdev, NULL);
+
+ input_unregister_device(ts->idev);
+ input_free_device(ts->idev);
+
+ kfree(ts);
+
+ return 0;
+}
+
+static struct platform_driver stmpe_ts_driver = {
+ .driver = {
+ .name = STMPE_TS_NAME,
+ },
+ .probe = stmpe_input_probe,
+ .remove = __devexit_p(stmpe_ts_remove),
+};
+
+static int __init stmpe_ts_init(void)
+{
+ return platform_driver_register(&stmpe_ts_driver);
+}
+
+module_init(stmpe_ts_init);
+
+static void __exit stmpe_ts_exit(void)
+{
+ platform_driver_unregister(&stmpe_ts_driver);
+}
+
+module_exit(stmpe_ts_exit);
+
+MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");
+MODULE_DESCRIPTION("STMPEXXX touchscreen driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" STMPE_TS_NAME);
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 5/5] input: STMPE touch controller support
2010-06-24 12:28 ` [PATCH 6/6 V5] input: STMPE touch controller support Luotao Fu
@ 2010-06-24 14:26 ` Luotao Fu
2010-06-24 16:24 ` Dmitry Torokhov
0 siblings, 1 reply; 31+ messages in thread
From: Luotao Fu @ 2010-06-24 14:26 UTC (permalink / raw)
To: Rabin VINCENT, Samuel Ortiz, Dmitry Torokhov
Cc: Linus WALLEIJ, linux-kernel, linux-input,
STEricsson_nomadik_linux, Luotao Fu
This one adds a driver for STMPE touchscreen controllers. This driver depends on
stmpexxx mfd core driver.
Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
---
V2 Changes:
* include subsystem headers since they are now remove from the mfd
core header file
* use genirq to register threaded isr. The stmpe811 own irq callbacks
are dropped in the core driver.
* use STMPE811_TS_NAME for name all over the place
* wait for completion of core IO operation before cancelling polling of
release event.
* switch to platform data for configuration parameters.
* add FIFO reset to open callback, also reset FIFO before reporting
release.
V3 Changes:
* reformated platform data comments to kernel-doc style
V4 Changes:
* converted to stmpexxx core by Rabin Vincent <rabin.vincent@stericsson.com>
* wait for running workqueue callback to finish while canceling the queue
* add i_drive configuration support
V5 Changes:
* add ADC block enable to stmpe_enable call.
V6 Changes:
* add _reset_fifo callback to reduce duplicated code.
* fix mask usage while setting bits in probe.
* acquire platform irq by name
drivers/input/touchscreen/Kconfig | 10 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/stmpe-ts.c | 378 ++++++++++++++++++++++++++++++++++
3 files changed, 389 insertions(+), 0 deletions(-)
create mode 100644 drivers/input/touchscreen/stmpe-ts.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 3b9d5e2..96a9954 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -603,4 +603,14 @@ config TOUCHSCREEN_TPS6507X
To compile this driver as a module, choose M here: the
module will be called tps6507x_ts.
+config TOUCHSCREEN_STMPE
+ tristate "STMicroelectronics STMPE touchscreens"
+ depends on MFD_STMPE
+ help
+ Say Y here if you want support for STMicroelectronics
+ STMPE touchscreen controllers.
+
+ To compile this driver as a module, choose M here: the
+ module will be called stmpe-ts.
+
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 497964a..2691c62 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -47,3 +47,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
+obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c
new file mode 100644
index 0000000..7742e63
--- /dev/null
+++ b/drivers/input/touchscreen/stmpe-ts.c
@@ -0,0 +1,378 @@
+/* STMicroelectronics STMPE811 Touchscreen Driver
+ *
+ * (C) 2010 Luotao Fu <l.fu@pengutronix.de>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+
+#include <linux/mfd/stmpe.h>
+
+/* Register layouts and functionalities are identical on all stmpexxx variants
+ * with touchscreen controller
+ */
+#define STMPE_REG_INT_STA 0x0B
+#define STMPE_REG_ADC_CTRL1 0x20
+#define STMPE_REG_ADC_CTRL2 0x21
+#define STMPE_REG_TSC_CTRL 0x40
+#define STMPE_REG_TSC_CFG 0x41
+#define STMPE_REG_FIFO_TH 0x4A
+#define STMPE_REG_FIFO_STA 0x4B
+#define STMPE_REG_FIFO_SIZE 0x4C
+#define STMPE_REG_TSC_DATA_XYZ 0x52
+#define STMPE_REG_TSC_FRACTION_Z 0x56
+#define STMPE_REG_TSC_I_DRIVE 0x58
+
+#define OP_MOD_XYZ 0
+
+#define STMPE_TSC_CTRL_TSC_EN (1<<0)
+
+#define STMPE_FIFO_STA_RESET (1<<0)
+
+#define STMPE_IRQ_TOUCH_DET 0
+
+#define SAMPLE_TIME(x) ((x & 0xf) << 4)
+#define MOD_12B(x) ((x & 0x1) << 3)
+#define REF_SEL(x) ((x & 0x1) << 1)
+#define ADC_FREQ(x) (x & 0x3)
+#define AVE_CTRL(x) ((x & 0x3) << 6)
+#define DET_DELAY(x) ((x & 0x7) << 3)
+#define SETTLING(x) (x & 0x7)
+#define FRACTION_Z(x) (x & 0x7)
+#define I_DRIVE(x) (x & 0x1)
+#define OP_MODE(x) ((x & 0x7) << 1)
+
+#define STMPE_TS_NAME "stmpe-ts"
+#define XY_MASK 0xfff
+
+struct stmpe_touch {
+ struct stmpe *stmpe;
+ struct input_dev *idev;
+ struct delayed_work work;
+ u8 sample_time;
+ u8 mod_12b;
+ u8 ref_sel;
+ u8 adc_freq;
+ u8 ave_ctrl;
+ u8 touch_det_delay;
+ u8 settling;
+ u8 fraction_z;
+ u8 i_drive;
+};
+
+static int inline __stmpe_reset_fifo(struct stmpe *stmpe)
+{
+ int ret;
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, STMPE_FIFO_STA_RESET);
+ if (ret)
+ return ret;
+
+ return stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, 0);
+}
+
+static void stmpe_work(struct work_struct *work)
+{
+ int int_sta;
+ u32 timeout = 40;
+
+ struct stmpe_touch *ts =
+ container_of(work, struct stmpe_touch, work.work);
+
+ int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA);
+
+ /* touch_det sometimes get desasserted or just get stuck. This appears
+ * to be a silicon bug, We still have to clearify this with the
+ * manufacture. As a workaround We release the key anyway if the
+ * touch_det keeps coming in after 4ms, while the FIFO contains no value
+ * during the whole time. */
+ while ((int_sta & (1 << STMPE_IRQ_TOUCH_DET)) && (timeout > 0)) {
+ timeout--;
+ int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA);
+ udelay(100);
+ }
+
+ /* reset the FIFO before we report release event */
+ __stmpe_reset_fifo(ts->stmpe);
+
+ input_report_abs(ts->idev, ABS_PRESSURE, 0);
+ input_sync(ts->idev);
+}
+
+static irqreturn_t stmpe_ts_handler(int irq, void *data)
+{
+ u8 data_set[4];
+ int x, y, z;
+ struct stmpe_touch *ts = data;
+
+ /* Cancel scheduled polling for release if we have new value
+ * available. Wait if the polling is already running. */
+ cancel_delayed_work_sync(&ts->work);
+
+ /*
+ * The FIFO sometimes just crashes and stops generating interrupts. This
+ * appears to be a silicon bug. We still have to clearify this with
+ * the manufacture. As a workaround we disable the TSC while we are
+ * collecting data and flush the FIFO after reading
+ */
+ stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, 0);
+
+ stmpe_block_read(ts->stmpe, STMPE_REG_TSC_DATA_XYZ, 4, data_set);
+
+ x = (data_set[0] << 4) | (data_set[1] >> 4);
+ y = ((data_set[1] & 0xf) << 8) | data_set[2];
+ z = data_set[3];
+
+ input_report_abs(ts->idev, ABS_X, x);
+ input_report_abs(ts->idev, ABS_Y, y);
+ input_report_abs(ts->idev, ABS_PRESSURE, z);
+ input_sync(ts->idev);
+
+ /* flush the FIFO after we have read out our values. */
+ __stmpe_reset_fifo(ts->stmpe);
+
+ /* reenable the tsc */
+ stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN);
+
+ /* start polling for touch_det to detect release */
+ schedule_delayed_work(&ts->work, HZ / 50);
+
+ return IRQ_HANDLED;
+}
+
+static int stmpe_ts_open(struct input_dev *dev)
+{
+ struct stmpe_touch *ts = input_get_drvdata(dev);
+ int ret = 0;
+
+ ret = __stmpe_reset_fifo(ts->stmpe);
+ if (ret)
+ return ret;
+
+ return stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN);
+}
+
+static void stmpe_ts_close(struct input_dev *dev)
+{
+ struct stmpe_touch *ts = input_get_drvdata(dev);
+
+ stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, 0);
+}
+
+static int __devinit stmpe_input_probe(struct platform_device *pdev)
+{
+ struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
+ struct stmpe_platform_data *pdata = stmpe->pdata;
+ struct stmpe_touch *ts;
+ struct input_dev *idev;
+ struct stmpe_ts_platform_data *ts_pdata = NULL;
+ int ret = 0;
+ unsigned int ts_irq;
+ u8 adc_ctrl1, adc_ctrl1_mask, tsc_cfg, tsc_cfg_mask;
+
+ ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
+ if (ts_irq < 0)
+ return ts_irq;
+
+ ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+ if (!ts)
+ goto err_out;
+
+ idev = input_allocate_device();
+ if (!idev)
+ goto err_free_ts;
+
+ platform_set_drvdata(pdev, ts);
+ ts->stmpe = stmpe;
+ ts->idev = idev;
+
+ if (pdata)
+ ts_pdata = pdata->ts;
+
+ if (ts_pdata) {
+ ts->sample_time = ts_pdata->sample_time;
+ ts->mod_12b = ts_pdata->mod_12b;
+ ts->ref_sel = ts_pdata->ref_sel;
+ ts->adc_freq = ts_pdata->adc_freq;
+ ts->ave_ctrl = ts_pdata->ave_ctrl;
+ ts->touch_det_delay = ts_pdata->touch_det_delay;
+ ts->settling = ts_pdata->settling;
+ ts->fraction_z = ts_pdata->fraction_z;
+ ts->i_drive = ts_pdata->i_drive;
+ }
+
+ INIT_DELAYED_WORK(&ts->work, stmpe_work);
+
+ ret = request_threaded_irq(ts_irq, NULL, stmpe_ts_handler,
+ IRQF_ONESHOT, STMPE_TS_NAME, ts);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request IRQ %d\n", ts_irq);
+ goto err_free_input;
+ }
+
+ ret = stmpe_enable(stmpe, STMPE_BLOCK_TOUCHSCREEN | STMPE_BLOCK_ADC);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not enable clock for ADC and TS\n");
+ goto err_free_irq;
+ }
+
+ adc_ctrl1 = SAMPLE_TIME(ts->sample_time) | MOD_12B(ts->mod_12b) |
+ REF_SEL(ts->ref_sel);
+ adc_ctrl1_mask = SAMPLE_TIME(0xff) | MOD_12B(0xff) | REF_SEL(0xff);
+ ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1,
+ adc_ctrl1_mask, adc_ctrl1);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not setup ADC\n");
+ goto err_free_irq;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2,
+ ADC_FREQ(0xff), ADC_FREQ(ts->adc_freq));
+ if (ret) {
+ dev_err(&pdev->dev, "Could not setup ADC\n");
+ goto err_free_irq;
+ }
+
+ tsc_cfg = AVE_CTRL(ts->ave_ctrl) | DET_DELAY(ts->touch_det_delay) |
+ SETTLING(ts->settling);
+ tsc_cfg_mask = AVE_CTRL(0xff) | DET_DELAY(0xff) | SETTLING(0xff);
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CFG, tsc_cfg_mask, tsc_cfg);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not config touch\n");
+ goto err_free_irq;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z,
+ FRACTION_Z(0xff), FRACTION_Z(ts->fraction_z));
+ if (ret) {
+ dev_err(&pdev->dev, "Could not config touch\n");
+ goto err_free_irq;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_I_DRIVE,
+ I_DRIVE(0xff), I_DRIVE(ts->i_drive));
+ if (ret) {
+ dev_err(&pdev->dev, "Could not config touch\n");
+ goto err_free_irq;
+ }
+
+ /* set FIFO to 1 for single point reading */
+ ret = stmpe_reg_write(stmpe, STMPE_REG_FIFO_TH, 1);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not set FIFO\n");
+ goto err_free_irq;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CTRL,
+ OP_MODE(0xff), OP_MODE(OP_MOD_XYZ));
+ if (ret) {
+ dev_err(&pdev->dev, "Could not set mode\n");
+ goto err_free_irq;
+ }
+
+ idev->name = STMPE_TS_NAME;
+ idev->id.bustype = BUS_I2C;
+ idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ idev->open = stmpe_ts_open;
+ idev->close = stmpe_ts_close;
+
+ input_set_drvdata(idev, ts);
+
+ ret = input_register_device(idev);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not register input device\n");
+ goto err_free_irq;
+ }
+
+ input_set_abs_params(idev, ABS_X, 0, XY_MASK, 0, 0);
+ input_set_abs_params(idev, ABS_Y, 0, XY_MASK, 0, 0);
+ input_set_abs_params(idev, ABS_PRESSURE, 0x0, 0xff, 0, 0);
+
+ return ret;
+
+err_free_irq:
+ free_irq(ts_irq, ts);
+err_free_input:
+ input_free_device(idev);
+ platform_set_drvdata(pdev, NULL);
+err_free_ts:
+ kfree(ts);
+err_out:
+ return ret;
+}
+
+static int __devexit stmpe_ts_remove(struct platform_device *pdev)
+{
+ struct stmpe_touch *ts = platform_get_drvdata(pdev);
+ unsigned int ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
+
+ cancel_delayed_work(&ts->work);
+
+ stmpe_reg_write(ts->stmpe, STMPE_REG_FIFO_TH, 0);
+
+ stmpe_disable(ts->stmpe, STMPE_BLOCK_TOUCHSCREEN);
+
+ free_irq(ts_irq, ts);
+
+ platform_set_drvdata(pdev, NULL);
+
+ input_unregister_device(ts->idev);
+ input_free_device(ts->idev);
+
+ kfree(ts);
+
+ return 0;
+}
+
+static struct platform_driver stmpe_ts_driver = {
+ .driver = {
+ .name = STMPE_TS_NAME,
+ },
+ .probe = stmpe_input_probe,
+ .remove = __devexit_p(stmpe_ts_remove),
+};
+
+static int __init stmpe_ts_init(void)
+{
+ return platform_driver_register(&stmpe_ts_driver);
+}
+
+module_init(stmpe_ts_init);
+
+static void __exit stmpe_ts_exit(void)
+{
+ platform_driver_unregister(&stmpe_ts_driver);
+}
+
+module_exit(stmpe_ts_exit);
+
+MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");
+MODULE_DESCRIPTION("STMPEXXX touchscreen driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" STMPE_TS_NAME);
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 5/5] input: STMPE touch controller support
2010-06-24 14:26 ` [PATCH 5/5] " Luotao Fu
@ 2010-06-24 16:24 ` Dmitry Torokhov
2010-06-24 16:57 ` Luotao Fu
2010-06-25 8:37 ` [PATCH 5/5 V7] " Luotao Fu
0 siblings, 2 replies; 31+ messages in thread
From: Dmitry Torokhov @ 2010-06-24 16:24 UTC (permalink / raw)
To: Luotao Fu
Cc: Rabin VINCENT, Samuel Ortiz, Linus WALLEIJ, linux-kernel,
linux-input, STEricsson_nomadik_linux
Hi Luotao,
On Thu, Jun 24, 2010 at 04:26:15PM +0200, Luotao Fu wrote:
> diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
> index 497964a..2691c62 100644
> --- a/drivers/input/touchscreen/Makefile
> +++ b/drivers/input/touchscreen/Makefile
> @@ -47,3 +47,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
> obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
> obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
> obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
> +obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
Please keep Makefile ordered alphabetically, it makes it easier to merge
stuff. Might try to do the same for Kconfig as well.
> +
> +static int inline __stmpe_reset_fifo(struct stmpe *stmpe)
Do not mark private function inline unless absolutely necessary - let
compiler figure out whether it makes sense to inline and what.
> +{
> + int ret;
> +
> + ret = stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA,
> + STMPE_FIFO_STA_RESET, STMPE_FIFO_STA_RESET);
> + if (ret)
> + return ret;
> +
> + return stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA,
> + STMPE_FIFO_STA_RESET, 0);
> +}
> +
> +static void stmpe_work(struct work_struct *work)
> +{
> + int int_sta;
> + u32 timeout = 40;
> +
> + struct stmpe_touch *ts =
> + container_of(work, struct stmpe_touch, work.work);
> +
> + int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA);
> +
> + /* touch_det sometimes get desasserted or just get stuck. This appears
> + * to be a silicon bug, We still have to clearify this with the
> + * manufacture. As a workaround We release the key anyway if the
> + * touch_det keeps coming in after 4ms, while the FIFO contains no value
> + * during the whole time. */
I would appreciate if we could maintain the following format for
multiline comments (within input at least):
/*
* This is a long long
* long comment.
*/
> + while ((int_sta & (1 << STMPE_IRQ_TOUCH_DET)) && (timeout > 0)) {
> + timeout--;
> + int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA);
> + udelay(100);
> + }
> +
> + /* reset the FIFO before we report release event */
> + __stmpe_reset_fifo(ts->stmpe);
> +
> + input_report_abs(ts->idev, ABS_PRESSURE, 0);
> + input_sync(ts->idev);
Hmm, this function appears to be always reporting release, no matter
what the state of hardware is. I do not think this was the intention...
or was it?
> +}
> +
> +static irqreturn_t stmpe_ts_handler(int irq, void *data)
> +{
> + u8 data_set[4];
> + int x, y, z;
> + struct stmpe_touch *ts = data;
> +
> + /* Cancel scheduled polling for release if we have new value
> + * available. Wait if the polling is already running. */
> + cancel_delayed_work_sync(&ts->work);
> +
> + /*
> + * The FIFO sometimes just crashes and stops generating interrupts. This
> + * appears to be a silicon bug. We still have to clearify this with
> + * the manufacture. As a workaround we disable the TSC while we are
> + * collecting data and flush the FIFO after reading
> + */
> + stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
> + STMPE_TSC_CTRL_TSC_EN, 0);
> +
> + stmpe_block_read(ts->stmpe, STMPE_REG_TSC_DATA_XYZ, 4, data_set);
> +
> + x = (data_set[0] << 4) | (data_set[1] >> 4);
> + y = ((data_set[1] & 0xf) << 8) | data_set[2];
> + z = data_set[3];
> +
> + input_report_abs(ts->idev, ABS_X, x);
> + input_report_abs(ts->idev, ABS_Y, y);
> + input_report_abs(ts->idev, ABS_PRESSURE, z);
> + input_sync(ts->idev);
> +
> + /* flush the FIFO after we have read out our values. */
> + __stmpe_reset_fifo(ts->stmpe);
> +
> + /* reenable the tsc */
> + stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
> + STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN);
> +
> + /* start polling for touch_det to detect release */
> + schedule_delayed_work(&ts->work, HZ / 50);
> +
> + return IRQ_HANDLED;
> +}
> +
> +static int stmpe_ts_open(struct input_dev *dev)
> +{
> + struct stmpe_touch *ts = input_get_drvdata(dev);
> + int ret = 0;
> +
> + ret = __stmpe_reset_fifo(ts->stmpe);
> + if (ret)
> + return ret;
> +
> + return stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
> + STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN);
> +}
> +
> +static void stmpe_ts_close(struct input_dev *dev)
> +{
> + struct stmpe_touch *ts = input_get_drvdata(dev);
> +
> + stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
> + STMPE_TSC_CTRL_TSC_EN, 0);
> +}
> +
> +static int __devinit stmpe_input_probe(struct platform_device *pdev)
> +{
> + struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
> + struct stmpe_platform_data *pdata = stmpe->pdata;
> + struct stmpe_touch *ts;
> + struct input_dev *idev;
> + struct stmpe_ts_platform_data *ts_pdata = NULL;
> + int ret = 0;
> + unsigned int ts_irq;
> + u8 adc_ctrl1, adc_ctrl1_mask, tsc_cfg, tsc_cfg_mask;
> +
> + ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
> + if (ts_irq < 0)
> + return ts_irq;
> +
> + ts = kzalloc(sizeof(*ts), GFP_KERNEL);
> + if (!ts)
> + goto err_out;
> +
> + idev = input_allocate_device();
> + if (!idev)
> + goto err_free_ts;
> +
> + platform_set_drvdata(pdev, ts);
> + ts->stmpe = stmpe;
> + ts->idev = idev;
> +
> + if (pdata)
> + ts_pdata = pdata->ts;
> +
> + if (ts_pdata) {
> + ts->sample_time = ts_pdata->sample_time;
> + ts->mod_12b = ts_pdata->mod_12b;
> + ts->ref_sel = ts_pdata->ref_sel;
> + ts->adc_freq = ts_pdata->adc_freq;
> + ts->ave_ctrl = ts_pdata->ave_ctrl;
> + ts->touch_det_delay = ts_pdata->touch_det_delay;
> + ts->settling = ts_pdata->settling;
> + ts->fraction_z = ts_pdata->fraction_z;
> + ts->i_drive = ts_pdata->i_drive;
> + }
> +
> + INIT_DELAYED_WORK(&ts->work, stmpe_work);
> +
> + ret = request_threaded_irq(ts_irq, NULL, stmpe_ts_handler,
> + IRQF_ONESHOT, STMPE_TS_NAME, ts);
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to request IRQ %d\n", ts_irq);
> + goto err_free_input;
> + }
> +
> + ret = stmpe_enable(stmpe, STMPE_BLOCK_TOUCHSCREEN | STMPE_BLOCK_ADC);
> + if (ret) {
> + dev_err(&pdev->dev, "Could not enable clock for ADC and TS\n");
> + goto err_free_irq;
> + }
> +
> + adc_ctrl1 = SAMPLE_TIME(ts->sample_time) | MOD_12B(ts->mod_12b) |
> + REF_SEL(ts->ref_sel);
> + adc_ctrl1_mask = SAMPLE_TIME(0xff) | MOD_12B(0xff) | REF_SEL(0xff);
> + ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1,
> + adc_ctrl1_mask, adc_ctrl1);
> + if (ret) {
> + dev_err(&pdev->dev, "Could not setup ADC\n");
> + goto err_free_irq;
> + }
> +
> + ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2,
> + ADC_FREQ(0xff), ADC_FREQ(ts->adc_freq));
> + if (ret) {
> + dev_err(&pdev->dev, "Could not setup ADC\n");
> + goto err_free_irq;
> + }
> +
> + tsc_cfg = AVE_CTRL(ts->ave_ctrl) | DET_DELAY(ts->touch_det_delay) |
> + SETTLING(ts->settling);
> + tsc_cfg_mask = AVE_CTRL(0xff) | DET_DELAY(0xff) | SETTLING(0xff);
> +
> + ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CFG, tsc_cfg_mask, tsc_cfg);
> + if (ret) {
> + dev_err(&pdev->dev, "Could not config touch\n");
> + goto err_free_irq;
> + }
> +
> + ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z,
> + FRACTION_Z(0xff), FRACTION_Z(ts->fraction_z));
> + if (ret) {
> + dev_err(&pdev->dev, "Could not config touch\n");
> + goto err_free_irq;
> + }
> +
> + ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_I_DRIVE,
> + I_DRIVE(0xff), I_DRIVE(ts->i_drive));
> + if (ret) {
> + dev_err(&pdev->dev, "Could not config touch\n");
> + goto err_free_irq;
> + }
> +
> + /* set FIFO to 1 for single point reading */
> + ret = stmpe_reg_write(stmpe, STMPE_REG_FIFO_TH, 1);
> + if (ret) {
> + dev_err(&pdev->dev, "Could not set FIFO\n");
> + goto err_free_irq;
> + }
> +
> + ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CTRL,
> + OP_MODE(0xff), OP_MODE(OP_MOD_XYZ));
> + if (ret) {
> + dev_err(&pdev->dev, "Could not set mode\n");
> + goto err_free_irq;
> + }
Could we pull all these stmpe_set_bits(...) settig up the hardware into
a separate function?
> +
> + idev->name = STMPE_TS_NAME;
> + idev->id.bustype = BUS_I2C;
> + idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
> + idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
> +
> + idev->open = stmpe_ts_open;
> + idev->close = stmpe_ts_close;
> +
> + input_set_drvdata(idev, ts);
> +
> + ret = input_register_device(idev);
> + if (ret) {
> + dev_err(&pdev->dev, "Could not register input device\n");
> + goto err_free_irq;
> + }
> +
> + input_set_abs_params(idev, ABS_X, 0, XY_MASK, 0, 0);
> + input_set_abs_params(idev, ABS_Y, 0, XY_MASK, 0, 0);
> + input_set_abs_params(idev, ABS_PRESSURE, 0x0, 0xff, 0, 0);
These calls better happen before registering the device.
> +
> + return ret;
> +
> +err_free_irq:
> + free_irq(ts_irq, ts);
> +err_free_input:
> + input_free_device(idev);
> + platform_set_drvdata(pdev, NULL);
> +err_free_ts:
> + kfree(ts);
> +err_out:
> + return ret;
> +}
> +
> +static int __devexit stmpe_ts_remove(struct platform_device *pdev)
> +{
> + struct stmpe_touch *ts = platform_get_drvdata(pdev);
> + unsigned int ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
> +
> + cancel_delayed_work(&ts->work);
cancel_delayed_work_sync().
> +
> + stmpe_reg_write(ts->stmpe, STMPE_REG_FIFO_TH, 0);
> +
> + stmpe_disable(ts->stmpe, STMPE_BLOCK_TOUCHSCREEN);
> +
I'd expect the 3 calls above being part of stmpe_ts_close().
> + free_irq(ts_irq, ts);
> +
> + platform_set_drvdata(pdev, NULL);
> +
> + input_unregister_device(ts->idev);
> + input_free_device(ts->idev);
> +
> + kfree(ts);
> +
> + return 0;
> +}
> +
> +static struct platform_driver stmpe_ts_driver = {
> + .driver = {
> + .name = STMPE_TS_NAME,
.owner = THIS_MODULE,
> + },
> + .probe = stmpe_input_probe,
> + .remove = __devexit_p(stmpe_ts_remove),
No PM? Or simply not yet?
> +};
> +
> +static int __init stmpe_ts_init(void)
> +{
> + return platform_driver_register(&stmpe_ts_driver);
> +}
> +
> +module_init(stmpe_ts_init);
> +
> +static void __exit stmpe_ts_exit(void)
> +{
> + platform_driver_unregister(&stmpe_ts_driver);
> +}
> +
> +module_exit(stmpe_ts_exit);
> +
> +MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");
> +MODULE_DESCRIPTION("STMPEXXX touchscreen driver");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:" STMPE_TS_NAME);
> --
> 1.7.1
>
Thanks.
--
Dmitry
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 5/5] input: STMPE touch controller support
2010-06-24 16:24 ` Dmitry Torokhov
@ 2010-06-24 16:57 ` Luotao Fu
2010-06-25 8:37 ` [PATCH 5/5 V7] " Luotao Fu
1 sibling, 0 replies; 31+ messages in thread
From: Luotao Fu @ 2010-06-24 16:57 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Luotao Fu, Rabin VINCENT, Samuel Ortiz, Linus WALLEIJ,
linux-kernel, linux-input, STEricsson_nomadik_linux
[-- Attachment #1: Type: text/plain, Size: 12490 bytes --]
Hi Dmitry,
thanks for reviewing the patch.
On Thu, Jun 24, 2010 at 09:24:07AM -0700, Dmitry Torokhov wrote:
> Hi Luotao,
>
> On Thu, Jun 24, 2010 at 04:26:15PM +0200, Luotao Fu wrote:
> > diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
> > index 497964a..2691c62 100644
> > --- a/drivers/input/touchscreen/Makefile
> > +++ b/drivers/input/touchscreen/Makefile
> > @@ -47,3 +47,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
> > obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
> > obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
> > obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
> > +obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
>
> Please keep Makefile ordered alphabetically, it makes it easier to merge
> stuff. Might try to do the same for Kconfig as well.
>
OK, will fix.
> > +
> > +static int inline __stmpe_reset_fifo(struct stmpe *stmpe)
>
> Do not mark private function inline unless absolutely necessary - let
> compiler figure out whether it makes sense to inline and what.
>
OK, will fix.
> > +{
> > + int ret;
> > +
> > + ret = stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA,
> > + STMPE_FIFO_STA_RESET, STMPE_FIFO_STA_RESET);
> > + if (ret)
> > + return ret;
> > +
> > + return stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA,
> > + STMPE_FIFO_STA_RESET, 0);
> > +}
> > +
> > +static void stmpe_work(struct work_struct *work)
> > +{
> > + int int_sta;
> > + u32 timeout = 40;
> > +
> > + struct stmpe_touch *ts =
> > + container_of(work, struct stmpe_touch, work.work);
> > +
> > + int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA);
> > +
> > + /* touch_det sometimes get desasserted or just get stuck. This appears
> > + * to be a silicon bug, We still have to clearify this with the
> > + * manufacture. As a workaround We release the key anyway if the
> > + * touch_det keeps coming in after 4ms, while the FIFO contains no value
> > + * during the whole time. */
>
> I would appreciate if we could maintain the following format for
> multiline comments (within input at least):
>
> /*
> * This is a long long
> * long comment.
> */
>
OK, will fix.
> > + while ((int_sta & (1 << STMPE_IRQ_TOUCH_DET)) && (timeout > 0)) {
> > + timeout--;
> > + int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA);
> > + udelay(100);
> > + }
> > +
> > + /* reset the FIFO before we report release event */
> > + __stmpe_reset_fifo(ts->stmpe);
> > +
> > + input_report_abs(ts->idev, ABS_PRESSURE, 0);
> > + input_sync(ts->idev);
>
> Hmm, this function appears to be always reporting release, no matter
> what the state of hardware is. I do not think this was the intention...
> or was it?
>
It unfortunately is. The original idea was polling for touch_det
and only report a release if the timeout was not reached. Unfortunately
the chip just sometime runs amok and never clears the touch_det
carelessly what happend. The only way here is report release any way
both after successed poll or timeout. This works fine, though the
polling sure looks unneccessary. I, however, would like to keep this
since I suppose a silicon bug here. Until the issue is cleared with the
vendor. Hence I'd like to have the polling for wait_det here though it
is sometimes useless.
> > +}
> > +
> > +static irqreturn_t stmpe_ts_handler(int irq, void *data)
> > +{
> > + u8 data_set[4];
> > + int x, y, z;
> > + struct stmpe_touch *ts = data;
> > +
> > + /* Cancel scheduled polling for release if we have new value
> > + * available. Wait if the polling is already running. */
> > + cancel_delayed_work_sync(&ts->work);
> > +
> > + /*
> > + * The FIFO sometimes just crashes and stops generating interrupts. This
> > + * appears to be a silicon bug. We still have to clearify this with
> > + * the manufacture. As a workaround we disable the TSC while we are
> > + * collecting data and flush the FIFO after reading
> > + */
> > + stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
> > + STMPE_TSC_CTRL_TSC_EN, 0);
> > +
> > + stmpe_block_read(ts->stmpe, STMPE_REG_TSC_DATA_XYZ, 4, data_set);
> > +
> > + x = (data_set[0] << 4) | (data_set[1] >> 4);
> > + y = ((data_set[1] & 0xf) << 8) | data_set[2];
> > + z = data_set[3];
> > +
> > + input_report_abs(ts->idev, ABS_X, x);
> > + input_report_abs(ts->idev, ABS_Y, y);
> > + input_report_abs(ts->idev, ABS_PRESSURE, z);
> > + input_sync(ts->idev);
> > +
> > + /* flush the FIFO after we have read out our values. */
> > + __stmpe_reset_fifo(ts->stmpe);
> > +
> > + /* reenable the tsc */
> > + stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
> > + STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN);
> > +
> > + /* start polling for touch_det to detect release */
> > + schedule_delayed_work(&ts->work, HZ / 50);
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static int stmpe_ts_open(struct input_dev *dev)
> > +{
> > + struct stmpe_touch *ts = input_get_drvdata(dev);
> > + int ret = 0;
> > +
> > + ret = __stmpe_reset_fifo(ts->stmpe);
> > + if (ret)
> > + return ret;
> > +
> > + return stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
> > + STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN);
> > +}
> > +
> > +static void stmpe_ts_close(struct input_dev *dev)
> > +{
> > + struct stmpe_touch *ts = input_get_drvdata(dev);
> > +
> > + stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
> > + STMPE_TSC_CTRL_TSC_EN, 0);
> > +}
> > +
> > +static int __devinit stmpe_input_probe(struct platform_device *pdev)
> > +{
> > + struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
> > + struct stmpe_platform_data *pdata = stmpe->pdata;
> > + struct stmpe_touch *ts;
> > + struct input_dev *idev;
> > + struct stmpe_ts_platform_data *ts_pdata = NULL;
> > + int ret = 0;
> > + unsigned int ts_irq;
> > + u8 adc_ctrl1, adc_ctrl1_mask, tsc_cfg, tsc_cfg_mask;
> > +
> > + ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
> > + if (ts_irq < 0)
> > + return ts_irq;
> > +
> > + ts = kzalloc(sizeof(*ts), GFP_KERNEL);
> > + if (!ts)
> > + goto err_out;
> > +
> > + idev = input_allocate_device();
> > + if (!idev)
> > + goto err_free_ts;
> > +
> > + platform_set_drvdata(pdev, ts);
> > + ts->stmpe = stmpe;
> > + ts->idev = idev;
> > +
> > + if (pdata)
> > + ts_pdata = pdata->ts;
> > +
> > + if (ts_pdata) {
> > + ts->sample_time = ts_pdata->sample_time;
> > + ts->mod_12b = ts_pdata->mod_12b;
> > + ts->ref_sel = ts_pdata->ref_sel;
> > + ts->adc_freq = ts_pdata->adc_freq;
> > + ts->ave_ctrl = ts_pdata->ave_ctrl;
> > + ts->touch_det_delay = ts_pdata->touch_det_delay;
> > + ts->settling = ts_pdata->settling;
> > + ts->fraction_z = ts_pdata->fraction_z;
> > + ts->i_drive = ts_pdata->i_drive;
> > + }
> > +
> > + INIT_DELAYED_WORK(&ts->work, stmpe_work);
> > +
> > + ret = request_threaded_irq(ts_irq, NULL, stmpe_ts_handler,
> > + IRQF_ONESHOT, STMPE_TS_NAME, ts);
> > + if (ret) {
> > + dev_err(&pdev->dev, "Failed to request IRQ %d\n", ts_irq);
> > + goto err_free_input;
> > + }
> > +
> > + ret = stmpe_enable(stmpe, STMPE_BLOCK_TOUCHSCREEN | STMPE_BLOCK_ADC);
> > + if (ret) {
> > + dev_err(&pdev->dev, "Could not enable clock for ADC and TS\n");
> > + goto err_free_irq;
> > + }
> > +
> > + adc_ctrl1 = SAMPLE_TIME(ts->sample_time) | MOD_12B(ts->mod_12b) |
> > + REF_SEL(ts->ref_sel);
> > + adc_ctrl1_mask = SAMPLE_TIME(0xff) | MOD_12B(0xff) | REF_SEL(0xff);
> > + ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1,
> > + adc_ctrl1_mask, adc_ctrl1);
> > + if (ret) {
> > + dev_err(&pdev->dev, "Could not setup ADC\n");
> > + goto err_free_irq;
> > + }
> > +
> > + ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2,
> > + ADC_FREQ(0xff), ADC_FREQ(ts->adc_freq));
> > + if (ret) {
> > + dev_err(&pdev->dev, "Could not setup ADC\n");
> > + goto err_free_irq;
> > + }
> > +
> > + tsc_cfg = AVE_CTRL(ts->ave_ctrl) | DET_DELAY(ts->touch_det_delay) |
> > + SETTLING(ts->settling);
> > + tsc_cfg_mask = AVE_CTRL(0xff) | DET_DELAY(0xff) | SETTLING(0xff);
> > +
> > + ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CFG, tsc_cfg_mask, tsc_cfg);
> > + if (ret) {
> > + dev_err(&pdev->dev, "Could not config touch\n");
> > + goto err_free_irq;
> > + }
> > +
> > + ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z,
> > + FRACTION_Z(0xff), FRACTION_Z(ts->fraction_z));
> > + if (ret) {
> > + dev_err(&pdev->dev, "Could not config touch\n");
> > + goto err_free_irq;
> > + }
> > +
> > + ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_I_DRIVE,
> > + I_DRIVE(0xff), I_DRIVE(ts->i_drive));
> > + if (ret) {
> > + dev_err(&pdev->dev, "Could not config touch\n");
> > + goto err_free_irq;
> > + }
> > +
> > + /* set FIFO to 1 for single point reading */
> > + ret = stmpe_reg_write(stmpe, STMPE_REG_FIFO_TH, 1);
> > + if (ret) {
> > + dev_err(&pdev->dev, "Could not set FIFO\n");
> > + goto err_free_irq;
> > + }
> > +
> > + ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CTRL,
> > + OP_MODE(0xff), OP_MODE(OP_MOD_XYZ));
> > + if (ret) {
> > + dev_err(&pdev->dev, "Could not set mode\n");
> > + goto err_free_irq;
> > + }
>
>
> Could we pull all these stmpe_set_bits(...) settig up the hardware into
> a separate function?
>
OK, will add a call ala stmpe_init_hw().
> > +
> > + idev->name = STMPE_TS_NAME;
> > + idev->id.bustype = BUS_I2C;
> > + idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
> > + idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
> > +
> > + idev->open = stmpe_ts_open;
> > + idev->close = stmpe_ts_close;
> > +
> > + input_set_drvdata(idev, ts);
> > +
> > + ret = input_register_device(idev);
> > + if (ret) {
> > + dev_err(&pdev->dev, "Could not register input device\n");
> > + goto err_free_irq;
> > + }
> > +
> > + input_set_abs_params(idev, ABS_X, 0, XY_MASK, 0, 0);
> > + input_set_abs_params(idev, ABS_Y, 0, XY_MASK, 0, 0);
> > + input_set_abs_params(idev, ABS_PRESSURE, 0x0, 0xff, 0, 0);
>
> These calls better happen before registering the device.
>
OK. will fix.
> > +
> > + return ret;
> > +
> > +err_free_irq:
> > + free_irq(ts_irq, ts);
> > +err_free_input:
> > + input_free_device(idev);
> > + platform_set_drvdata(pdev, NULL);
> > +err_free_ts:
> > + kfree(ts);
> > +err_out:
> > + return ret;
> > +}
> > +
> > +static int __devexit stmpe_ts_remove(struct platform_device *pdev)
> > +{
> > + struct stmpe_touch *ts = platform_get_drvdata(pdev);
> > + unsigned int ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
> > +
> > + cancel_delayed_work(&ts->work);
>
> cancel_delayed_work_sync().
>
Ah, forgot this, will fix.
> > +
> > + stmpe_reg_write(ts->stmpe, STMPE_REG_FIFO_TH, 0);
> > +
> > + stmpe_disable(ts->stmpe, STMPE_BLOCK_TOUCHSCREEN);
> > +
>
> I'd expect the 3 calls above being part of stmpe_ts_close().
>
OK, will fix.
> > + free_irq(ts_irq, ts);
> > +
> > + platform_set_drvdata(pdev, NULL);
> > +
> > + input_unregister_device(ts->idev);
> > + input_free_device(ts->idev);
> > +
> > + kfree(ts);
> > +
> > + return 0;
> > +}
> > +
> > +static struct platform_driver stmpe_ts_driver = {
> > + .driver = {
> > + .name = STMPE_TS_NAME,
>
> .owner = THIS_MODULE,
>
> > + },
> > + .probe = stmpe_input_probe,
> > + .remove = __devexit_p(stmpe_ts_remove),
>
> No PM? Or simply not yet?
>
not yet. ;-) will add this in a later patch.
> > +};
> > +
> > +static int __init stmpe_ts_init(void)
> > +{
> > + return platform_driver_register(&stmpe_ts_driver);
> > +}
> > +
> > +module_init(stmpe_ts_init);
> > +
> > +static void __exit stmpe_ts_exit(void)
> > +{
> > + platform_driver_unregister(&stmpe_ts_driver);
> > +}
> > +
> > +module_exit(stmpe_ts_exit);
> > +
> > +MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");
> > +MODULE_DESCRIPTION("STMPEXXX touchscreen driver");
> > +MODULE_LICENSE("GPL");
> > +MODULE_ALIAS("platform:" STMPE_TS_NAME);
> > --
> > 1.7.1
> >
>
> Thanks.
thanks
>
> --
> Dmitry
cheers
Luotao Fu
--
Pengutronix e.K. | Dipl.-Ing. Luotao Fu |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 5/5 V7] input: STMPE touch controller support
2010-06-24 16:24 ` Dmitry Torokhov
2010-06-24 16:57 ` Luotao Fu
@ 2010-06-25 8:37 ` Luotao Fu
2010-06-25 9:11 ` Dmitry Torokhov
2010-06-25 9:34 ` [PATCH 5/5 V8] " Luotao Fu
1 sibling, 2 replies; 31+ messages in thread
From: Luotao Fu @ 2010-06-25 8:37 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Rabin VINCENT, Samuel Ortiz, Linus WALLEIJ, linux-kernel,
linux-input, STEricsson_nomadik_linux, Luotao Fu
This one adds a driver for STMPE touchscreen controllers. This driver depends on
stmpexxx mfd core driver.
Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
---
V2 Changes:
* include subsystem headers since they are now remove from the mfd
core header file
* use genirq to register threaded isr. The stmpe811 own irq callbacks
are dropped in the core driver.
* use STMPE811_TS_NAME for name all over the place
* wait for completion of core IO operation before cancelling polling of
release event.
* switch to platform data for configuration parameters.
* add FIFO reset to open callback, also reset FIFO before reporting
release.
V3 Changes:
* reformated platform data comments to kernel-doc style
V4 Changes:
* converted to stmpexxx core by Rabin Vincent <rabin.vincent@stericsson.com>
* wait for running workqueue callback to finish while canceling the queue
* add i_drive configuration support
V5 Changes:
* add ADC block enable to stmpe_enable call.
V6 Changes:
* add _reset_fifo callback to reduce duplicated code.
* fix mask usage while setting bits in probe.
* acquire platform irq by name
V7 Changes:
* reranged entry makefile in alphabetical order
* move hw init stuff into a own function
* fix queue canceling in close. remove uneccessary register settings from remove
* removed inline declaration
* add driver owner
* set input params before registering the device
drivers/input/touchscreen/Kconfig | 10 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/stmpe-ts.c | 397 ++++++++++++++++++++++++++++++++++
3 files changed, 408 insertions(+), 0 deletions(-)
create mode 100644 drivers/input/touchscreen/stmpe-ts.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 3b9d5e2..96a9954 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -603,4 +603,14 @@ config TOUCHSCREEN_TPS6507X
To compile this driver as a module, choose M here: the
module will be called tps6507x_ts.
+config TOUCHSCREEN_STMPE
+ tristate "STMicroelectronics STMPE touchscreens"
+ depends on MFD_STMPE
+ help
+ Say Y here if you want support for STMicroelectronics
+ STMPE touchscreen controllers.
+
+ To compile this driver as a module, choose M here: the
+ module will be called stmpe-ts.
+
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 497964a..10fb163 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o
obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o
obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
+obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c
new file mode 100644
index 0000000..f5c1d88
--- /dev/null
+++ b/drivers/input/touchscreen/stmpe-ts.c
@@ -0,0 +1,397 @@
+/* STMicroelectronics STMPE811 Touchscreen Driver
+ *
+ * (C) 2010 Luotao Fu <l.fu@pengutronix.de>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+
+#include <linux/mfd/stmpe.h>
+
+/* Register layouts and functionalities are identical on all stmpexxx variants
+ * with touchscreen controller
+ */
+#define STMPE_REG_INT_STA 0x0B
+#define STMPE_REG_ADC_CTRL1 0x20
+#define STMPE_REG_ADC_CTRL2 0x21
+#define STMPE_REG_TSC_CTRL 0x40
+#define STMPE_REG_TSC_CFG 0x41
+#define STMPE_REG_FIFO_TH 0x4A
+#define STMPE_REG_FIFO_STA 0x4B
+#define STMPE_REG_FIFO_SIZE 0x4C
+#define STMPE_REG_TSC_DATA_XYZ 0x52
+#define STMPE_REG_TSC_FRACTION_Z 0x56
+#define STMPE_REG_TSC_I_DRIVE 0x58
+
+#define OP_MOD_XYZ 0
+
+#define STMPE_TSC_CTRL_TSC_EN (1<<0)
+
+#define STMPE_FIFO_STA_RESET (1<<0)
+
+#define STMPE_IRQ_TOUCH_DET 0
+
+#define SAMPLE_TIME(x) ((x & 0xf) << 4)
+#define MOD_12B(x) ((x & 0x1) << 3)
+#define REF_SEL(x) ((x & 0x1) << 1)
+#define ADC_FREQ(x) (x & 0x3)
+#define AVE_CTRL(x) ((x & 0x3) << 6)
+#define DET_DELAY(x) ((x & 0x7) << 3)
+#define SETTLING(x) (x & 0x7)
+#define FRACTION_Z(x) (x & 0x7)
+#define I_DRIVE(x) (x & 0x1)
+#define OP_MODE(x) ((x & 0x7) << 1)
+
+#define STMPE_TS_NAME "stmpe-ts"
+#define XY_MASK 0xfff
+
+struct stmpe_touch {
+ struct stmpe *stmpe;
+ struct input_dev *idev;
+ struct delayed_work work;
+ struct device *dev;
+ u8 sample_time;
+ u8 mod_12b;
+ u8 ref_sel;
+ u8 adc_freq;
+ u8 ave_ctrl;
+ u8 touch_det_delay;
+ u8 settling;
+ u8 fraction_z;
+ u8 i_drive;
+};
+
+static int __stmpe_reset_fifo(struct stmpe *stmpe)
+{
+ int ret;
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, STMPE_FIFO_STA_RESET);
+ if (ret)
+ return ret;
+
+ return stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, 0);
+}
+
+static void stmpe_work(struct work_struct *work)
+{
+ int int_sta;
+ u32 timeout = 40;
+
+ struct stmpe_touch *ts =
+ container_of(work, struct stmpe_touch, work.work);
+
+ int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA);
+
+ /*
+ * touch_det sometimes get desasserted or just get stuck. This appears
+ * to be a silicon bug, We still have to clearify this with the
+ * manufacture. As a workaround We release the key anyway if the
+ * touch_det keeps coming in after 4ms, while the FIFO contains no value
+ * during the whole time.
+ */
+ while ((int_sta & (1 << STMPE_IRQ_TOUCH_DET)) && (timeout > 0)) {
+ timeout--;
+ int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA);
+ udelay(100);
+ }
+
+ /* reset the FIFO before we report release event */
+ __stmpe_reset_fifo(ts->stmpe);
+
+ input_report_abs(ts->idev, ABS_PRESSURE, 0);
+ input_sync(ts->idev);
+}
+
+static irqreturn_t stmpe_ts_handler(int irq, void *data)
+{
+ u8 data_set[4];
+ int x, y, z;
+ struct stmpe_touch *ts = data;
+
+ /*
+ * Cancel scheduled polling for release if we have new value
+ * available. Wait if the polling is already running.
+ */
+ cancel_delayed_work_sync(&ts->work);
+
+ /*
+ * The FIFO sometimes just crashes and stops generating interrupts. This
+ * appears to be a silicon bug. We still have to clearify this with
+ * the manufacture. As a workaround we disable the TSC while we are
+ * collecting data and flush the FIFO after reading
+ */
+ stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, 0);
+
+ stmpe_block_read(ts->stmpe, STMPE_REG_TSC_DATA_XYZ, 4, data_set);
+
+ x = (data_set[0] << 4) | (data_set[1] >> 4);
+ y = ((data_set[1] & 0xf) << 8) | data_set[2];
+ z = data_set[3];
+
+ input_report_abs(ts->idev, ABS_X, x);
+ input_report_abs(ts->idev, ABS_Y, y);
+ input_report_abs(ts->idev, ABS_PRESSURE, z);
+ input_sync(ts->idev);
+
+ /* flush the FIFO after we have read out our values. */
+ __stmpe_reset_fifo(ts->stmpe);
+
+ /* reenable the tsc */
+ stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN);
+
+ /* start polling for touch_det to detect release */
+ schedule_delayed_work(&ts->work, HZ / 50);
+
+ return IRQ_HANDLED;
+}
+
+static int stmpe_init_hw(struct stmpe_touch *ts)
+{
+ int ret;
+ u8 adc_ctrl1, adc_ctrl1_mask, tsc_cfg, tsc_cfg_mask;
+ struct stmpe *stmpe = ts->stmpe;
+ struct device *dev = ts->dev;
+
+ ret = stmpe_enable(stmpe, STMPE_BLOCK_TOUCHSCREEN | STMPE_BLOCK_ADC);
+ if (ret) {
+ dev_err(dev, "Could not enable clock for ADC and TS\n");
+ return ret;
+ }
+
+ adc_ctrl1 = SAMPLE_TIME(ts->sample_time) | MOD_12B(ts->mod_12b) |
+ REF_SEL(ts->ref_sel);
+ adc_ctrl1_mask = SAMPLE_TIME(0xff) | MOD_12B(0xff) | REF_SEL(0xff);
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1,
+ adc_ctrl1_mask, adc_ctrl1);
+ if (ret) {
+ dev_err(dev, "Could not setup ADC\n");
+ return ret;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2,
+ ADC_FREQ(0xff), ADC_FREQ(ts->adc_freq));
+ if (ret) {
+ dev_err(dev, "Could not setup ADC\n");
+ return ret;
+ }
+
+ tsc_cfg = AVE_CTRL(ts->ave_ctrl) | DET_DELAY(ts->touch_det_delay) |
+ SETTLING(ts->settling);
+ tsc_cfg_mask = AVE_CTRL(0xff) | DET_DELAY(0xff) | SETTLING(0xff);
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CFG, tsc_cfg_mask, tsc_cfg);
+ if (ret) {
+ dev_err(dev, "Could not config touch\n");
+ return ret;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z,
+ FRACTION_Z(0xff), FRACTION_Z(ts->fraction_z));
+ if (ret) {
+ dev_err(dev, "Could not config touch\n");
+ return ret;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_I_DRIVE,
+ I_DRIVE(0xff), I_DRIVE(ts->i_drive));
+ if (ret) {
+ dev_err(dev, "Could not config touch\n");
+ return ret;
+ }
+
+ /* set FIFO to 1 for single point reading */
+ ret = stmpe_reg_write(stmpe, STMPE_REG_FIFO_TH, 1);
+ if (ret) {
+ dev_err(dev, "Could not set FIFO\n");
+ return ret;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CTRL,
+ OP_MODE(0xff), OP_MODE(OP_MOD_XYZ));
+ if (ret) {
+ dev_err(dev, "Could not set mode\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int stmpe_ts_open(struct input_dev *dev)
+{
+ struct stmpe_touch *ts = input_get_drvdata(dev);
+ int ret = 0;
+
+ ret = __stmpe_reset_fifo(ts->stmpe);
+ if (ret)
+ return ret;
+
+ return stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN);
+}
+
+static void stmpe_ts_close(struct input_dev *dev)
+{
+ struct stmpe_touch *ts = input_get_drvdata(dev);
+
+ cancel_delayed_work_sync(&ts->work);
+
+ stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, 0);
+}
+
+static int __devinit stmpe_input_probe(struct platform_device *pdev)
+{
+ struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
+ struct stmpe_platform_data *pdata = stmpe->pdata;
+ struct stmpe_touch *ts;
+ struct input_dev *idev;
+ struct stmpe_ts_platform_data *ts_pdata = NULL;
+ int ret = 0;
+ unsigned int ts_irq;
+
+ ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
+ if (ts_irq < 0)
+ return ts_irq;
+
+ ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+ if (!ts)
+ goto err_out;
+
+ idev = input_allocate_device();
+ if (!idev)
+ goto err_free_ts;
+
+ platform_set_drvdata(pdev, ts);
+ ts->stmpe = stmpe;
+ ts->idev = idev;
+ ts->dev = &pdev->dev;
+
+ if (pdata)
+ ts_pdata = pdata->ts;
+
+ if (ts_pdata) {
+ ts->sample_time = ts_pdata->sample_time;
+ ts->mod_12b = ts_pdata->mod_12b;
+ ts->ref_sel = ts_pdata->ref_sel;
+ ts->adc_freq = ts_pdata->adc_freq;
+ ts->ave_ctrl = ts_pdata->ave_ctrl;
+ ts->touch_det_delay = ts_pdata->touch_det_delay;
+ ts->settling = ts_pdata->settling;
+ ts->fraction_z = ts_pdata->fraction_z;
+ ts->i_drive = ts_pdata->i_drive;
+ }
+
+ INIT_DELAYED_WORK(&ts->work, stmpe_work);
+
+ ret = request_threaded_irq(ts_irq, NULL, stmpe_ts_handler,
+ IRQF_ONESHOT, STMPE_TS_NAME, ts);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request IRQ %d\n", ts_irq);
+ goto err_free_input;
+ }
+
+ ret = stmpe_init_hw(ts);
+ if (ret)
+ goto err_free_irq;
+
+ idev->name = STMPE_TS_NAME;
+ idev->id.bustype = BUS_I2C;
+ idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ idev->open = stmpe_ts_open;
+ idev->close = stmpe_ts_close;
+
+ input_set_drvdata(idev, ts);
+
+ input_set_abs_params(idev, ABS_X, 0, XY_MASK, 0, 0);
+ input_set_abs_params(idev, ABS_Y, 0, XY_MASK, 0, 0);
+ input_set_abs_params(idev, ABS_PRESSURE, 0x0, 0xff, 0, 0);
+
+ ret = input_register_device(idev);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not register input device\n");
+ goto err_free_irq;
+ }
+
+ return ret;
+
+err_free_irq:
+ free_irq(ts_irq, ts);
+err_free_input:
+ input_free_device(idev);
+ platform_set_drvdata(pdev, NULL);
+err_free_ts:
+ kfree(ts);
+err_out:
+ return ret;
+}
+
+static int __devexit stmpe_ts_remove(struct platform_device *pdev)
+{
+ struct stmpe_touch *ts = platform_get_drvdata(pdev);
+ unsigned int ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
+
+ stmpe_disable(ts->stmpe, STMPE_BLOCK_TOUCHSCREEN);
+
+ free_irq(ts_irq, ts);
+
+ platform_set_drvdata(pdev, NULL);
+
+ input_unregister_device(ts->idev);
+ input_free_device(ts->idev);
+
+ kfree(ts);
+
+ return 0;
+}
+
+static struct platform_driver stmpe_ts_driver = {
+ .driver = {
+ .name = STMPE_TS_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = stmpe_input_probe,
+ .remove = __devexit_p(stmpe_ts_remove),
+};
+
+static int __init stmpe_ts_init(void)
+{
+ return platform_driver_register(&stmpe_ts_driver);
+}
+
+module_init(stmpe_ts_init);
+
+static void __exit stmpe_ts_exit(void)
+{
+ platform_driver_unregister(&stmpe_ts_driver);
+}
+
+module_exit(stmpe_ts_exit);
+
+MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");
+MODULE_DESCRIPTION("STMPEXXX touchscreen driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" STMPE_TS_NAME);
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 5/5 V7] input: STMPE touch controller support
2010-06-25 8:37 ` [PATCH 5/5 V7] " Luotao Fu
@ 2010-06-25 9:11 ` Dmitry Torokhov
2010-06-25 9:32 ` Luotao Fu
2010-06-27 21:24 ` Samuel Ortiz
2010-06-25 9:34 ` [PATCH 5/5 V8] " Luotao Fu
1 sibling, 2 replies; 31+ messages in thread
From: Dmitry Torokhov @ 2010-06-25 9:11 UTC (permalink / raw)
To: Luotao Fu
Cc: Rabin VINCENT, Samuel Ortiz, Linus WALLEIJ, linux-kernel,
linux-input, STEricsson_nomadik_linux
On Fri, Jun 25, 2010 at 10:37:51AM +0200, Luotao Fu wrote:
> +
> + /*
Trailing whitespace.
> + * touch_det sometimes get desasserted or just get stuck. This appears
> + * to be a silicon bug, We still have to clearify this with the
> + * manufacture. As a workaround We release the key anyway if the
> + * touch_det keeps coming in after 4ms, while the FIFO contains no value
> + * during the whole time.
Trailing whitespace.
> +
> +static int stmpe_init_hw(struct stmpe_touch *ts)
__devinit.
Otherwise:
Acked-by: Dmitry Torokhov <dtor@mail.ru>
I assume it will be merged through MFD tree?
--
Dmitry
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 5/5 V7] input: STMPE touch controller support
2010-06-25 9:11 ` Dmitry Torokhov
@ 2010-06-25 9:32 ` Luotao Fu
2010-06-27 21:24 ` Samuel Ortiz
1 sibling, 0 replies; 31+ messages in thread
From: Luotao Fu @ 2010-06-25 9:32 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Luotao Fu, Rabin VINCENT, Samuel Ortiz, Linus WALLEIJ,
linux-kernel, linux-input, STEricsson_nomadik_linux
[-- Attachment #1: Type: text/plain, Size: 1601 bytes --]
On Fri, Jun 25, 2010 at 02:11:16AM -0700, Dmitry Torokhov wrote:
> On Fri, Jun 25, 2010 at 10:37:51AM +0200, Luotao Fu wrote:
> > +
> > + /*
>
> Trailing whitespace.
>
> > + * touch_det sometimes get desasserted or just get stuck. This appears
> > + * to be a silicon bug, We still have to clearify this with the
> > + * manufacture. As a workaround We release the key anyway if the
> > + * touch_det keeps coming in after 4ms, while the FIFO contains no value
> > + * during the whole time.
>
> Trailing whitespace.
>
> > +
> > +static int stmpe_init_hw(struct stmpe_touch *ts)
>
> __devinit.
>
doh! Note to myself: never forget checkpatch.pl
> Otherwise:
>
> Acked-by: Dmitry Torokhov <dtor@mail.ru>
>
thx
> I assume it will be merged through MFD tree?
>
to be very honest: no idea... ;-) Samuel once asked Rabin and me to
merge the stmpe stuffs since I once posted a serie exclusively for
stmpe811, now it's so far done(V8 with white space fixes is coming).
Rabin's patch series also contains input stuffs like keypad etc. I don't
know whether Rabin is going to rebase the serie to merge some other
fixes or one of you (Samuel and you) would prefer the patch serie
"as it is".
Rabin, what do you think?
Cheers
Luotao Fu
--
Pengutronix e.K. | Dipl.-Ing. Luotao Fu |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 5/5 V7] input: STMPE touch controller support
2010-06-25 9:11 ` Dmitry Torokhov
2010-06-25 9:32 ` Luotao Fu
@ 2010-06-27 21:24 ` Samuel Ortiz
1 sibling, 0 replies; 31+ messages in thread
From: Samuel Ortiz @ 2010-06-27 21:24 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Luotao Fu, Rabin VINCENT, Linus WALLEIJ, linux-kernel,
linux-input, STEricsson_nomadik_linux
Hi Dmitry,
On Fri, Jun 25, 2010 at 02:11:16AM -0700, Dmitry Torokhov wrote:
> On Fri, Jun 25, 2010 at 10:37:51AM +0200, Luotao Fu wrote:
> > +
> > + /*
>
> Trailing whitespace.
>
> > + * touch_det sometimes get desasserted or just get stuck. This appears
> > + * to be a silicon bug, We still have to clearify this with the
> > + * manufacture. As a workaround We release the key anyway if the
> > + * touch_det keeps coming in after 4ms, while the FIFO contains no value
> > + * during the whole time.
>
> Trailing whitespace.
>
> > +
> > +static int stmpe_init_hw(struct stmpe_touch *ts)
>
> __devinit.
>
> Otherwise:
>
> Acked-by: Dmitry Torokhov <dtor@mail.ru>
>
> I assume it will be merged through MFD tree?
Yes, that's correct.
Cheers,
Samuel.
> --
> Dmitry
--
Intel Open Source Technology Centre
http://oss.intel.com/
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 5/5 V8] input: STMPE touch controller support
2010-06-25 8:37 ` [PATCH 5/5 V7] " Luotao Fu
2010-06-25 9:11 ` Dmitry Torokhov
@ 2010-06-25 9:34 ` Luotao Fu
1 sibling, 0 replies; 31+ messages in thread
From: Luotao Fu @ 2010-06-25 9:34 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Rabin VINCENT, Samuel Ortiz, Linus WALLEIJ, linux-kernel,
linux-input, STEricsson_nomadik_linux, Luotao Fu
This one adds a driver for STMPE touchscreen controllers. This driver depends on
stmpexxx mfd core driver.
Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
Acked-by: Dmitry Torokhov <dtor@mail.ru>
---
V2 Changes:
* include subsystem headers since they are now remove from the mfd
core header file
* use genirq to register threaded isr. The stmpe811 own irq callbacks
are dropped in the core driver.
* use STMPE811_TS_NAME for name all over the place
* wait for completion of core IO operation before cancelling polling of
release event.
* switch to platform data for configuration parameters.
* add FIFO reset to open callback, also reset FIFO before reporting
release.
V3 Changes:
* reformated platform data comments to kernel-doc style
V4 Changes:
* converted to stmpexxx core by Rabin Vincent <rabin.vincent@stericsson.com>
* wait for running workqueue callback to finish while canceling the queue
* add i_drive configuration support
V5 Changes:
* add ADC block enable to stmpe_enable call.
V6 Changes:
* add _reset_fifo callback to reduce duplicated code.
* fix mask usage while setting bits in probe.
* acquire platform irq by name
V7 Changes:
* reranged entry makefile in alphabetical order
* move hw init stuff into a own function
* fix queue canceling in close. remove uneccessary register settings from remove
* removed inline declaration
* add driver owner
* set input params before registering the device
V8 Changes:
* fixed trailing whitespaces
* mark init_hw function as __devinit
drivers/input/touchscreen/Kconfig | 10 +
drivers/input/touchscreen/Makefile | 1 +
drivers/input/touchscreen/stmpe-ts.c | 397 ++++++++++++++++++++++++++++++++++
3 files changed, 408 insertions(+), 0 deletions(-)
create mode 100644 drivers/input/touchscreen/stmpe-ts.c
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 3b9d5e2..96a9954 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -603,4 +603,14 @@ config TOUCHSCREEN_TPS6507X
To compile this driver as a module, choose M here: the
module will be called tps6507x_ts.
+config TOUCHSCREEN_STMPE
+ tristate "STMicroelectronics STMPE touchscreens"
+ depends on MFD_STMPE
+ help
+ Say Y here if you want support for STMicroelectronics
+ STMPE touchscreen controllers.
+
+ To compile this driver as a module, choose M here: the
+ module will be called stmpe-ts.
+
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 497964a..10fb163 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o
obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o
obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
+obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
diff --git a/drivers/input/touchscreen/stmpe-ts.c b/drivers/input/touchscreen/stmpe-ts.c
new file mode 100644
index 0000000..77f4374
--- /dev/null
+++ b/drivers/input/touchscreen/stmpe-ts.c
@@ -0,0 +1,397 @@
+/* STMicroelectronics STMPE811 Touchscreen Driver
+ *
+ * (C) 2010 Luotao Fu <l.fu@pengutronix.de>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+
+#include <linux/mfd/stmpe.h>
+
+/* Register layouts and functionalities are identical on all stmpexxx variants
+ * with touchscreen controller
+ */
+#define STMPE_REG_INT_STA 0x0B
+#define STMPE_REG_ADC_CTRL1 0x20
+#define STMPE_REG_ADC_CTRL2 0x21
+#define STMPE_REG_TSC_CTRL 0x40
+#define STMPE_REG_TSC_CFG 0x41
+#define STMPE_REG_FIFO_TH 0x4A
+#define STMPE_REG_FIFO_STA 0x4B
+#define STMPE_REG_FIFO_SIZE 0x4C
+#define STMPE_REG_TSC_DATA_XYZ 0x52
+#define STMPE_REG_TSC_FRACTION_Z 0x56
+#define STMPE_REG_TSC_I_DRIVE 0x58
+
+#define OP_MOD_XYZ 0
+
+#define STMPE_TSC_CTRL_TSC_EN (1<<0)
+
+#define STMPE_FIFO_STA_RESET (1<<0)
+
+#define STMPE_IRQ_TOUCH_DET 0
+
+#define SAMPLE_TIME(x) ((x & 0xf) << 4)
+#define MOD_12B(x) ((x & 0x1) << 3)
+#define REF_SEL(x) ((x & 0x1) << 1)
+#define ADC_FREQ(x) (x & 0x3)
+#define AVE_CTRL(x) ((x & 0x3) << 6)
+#define DET_DELAY(x) ((x & 0x7) << 3)
+#define SETTLING(x) (x & 0x7)
+#define FRACTION_Z(x) (x & 0x7)
+#define I_DRIVE(x) (x & 0x1)
+#define OP_MODE(x) ((x & 0x7) << 1)
+
+#define STMPE_TS_NAME "stmpe-ts"
+#define XY_MASK 0xfff
+
+struct stmpe_touch {
+ struct stmpe *stmpe;
+ struct input_dev *idev;
+ struct delayed_work work;
+ struct device *dev;
+ u8 sample_time;
+ u8 mod_12b;
+ u8 ref_sel;
+ u8 adc_freq;
+ u8 ave_ctrl;
+ u8 touch_det_delay;
+ u8 settling;
+ u8 fraction_z;
+ u8 i_drive;
+};
+
+static int __stmpe_reset_fifo(struct stmpe *stmpe)
+{
+ int ret;
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, STMPE_FIFO_STA_RESET);
+ if (ret)
+ return ret;
+
+ return stmpe_set_bits(stmpe, STMPE_REG_FIFO_STA,
+ STMPE_FIFO_STA_RESET, 0);
+}
+
+static void stmpe_work(struct work_struct *work)
+{
+ int int_sta;
+ u32 timeout = 40;
+
+ struct stmpe_touch *ts =
+ container_of(work, struct stmpe_touch, work.work);
+
+ int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA);
+
+ /*
+ * touch_det sometimes get desasserted or just get stuck. This appears
+ * to be a silicon bug, We still have to clearify this with the
+ * manufacture. As a workaround We release the key anyway if the
+ * touch_det keeps coming in after 4ms, while the FIFO contains no value
+ * during the whole time.
+ */
+ while ((int_sta & (1 << STMPE_IRQ_TOUCH_DET)) && (timeout > 0)) {
+ timeout--;
+ int_sta = stmpe_reg_read(ts->stmpe, STMPE_REG_INT_STA);
+ udelay(100);
+ }
+
+ /* reset the FIFO before we report release event */
+ __stmpe_reset_fifo(ts->stmpe);
+
+ input_report_abs(ts->idev, ABS_PRESSURE, 0);
+ input_sync(ts->idev);
+}
+
+static irqreturn_t stmpe_ts_handler(int irq, void *data)
+{
+ u8 data_set[4];
+ int x, y, z;
+ struct stmpe_touch *ts = data;
+
+ /*
+ * Cancel scheduled polling for release if we have new value
+ * available. Wait if the polling is already running.
+ */
+ cancel_delayed_work_sync(&ts->work);
+
+ /*
+ * The FIFO sometimes just crashes and stops generating interrupts. This
+ * appears to be a silicon bug. We still have to clearify this with
+ * the manufacture. As a workaround we disable the TSC while we are
+ * collecting data and flush the FIFO after reading
+ */
+ stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, 0);
+
+ stmpe_block_read(ts->stmpe, STMPE_REG_TSC_DATA_XYZ, 4, data_set);
+
+ x = (data_set[0] << 4) | (data_set[1] >> 4);
+ y = ((data_set[1] & 0xf) << 8) | data_set[2];
+ z = data_set[3];
+
+ input_report_abs(ts->idev, ABS_X, x);
+ input_report_abs(ts->idev, ABS_Y, y);
+ input_report_abs(ts->idev, ABS_PRESSURE, z);
+ input_sync(ts->idev);
+
+ /* flush the FIFO after we have read out our values. */
+ __stmpe_reset_fifo(ts->stmpe);
+
+ /* reenable the tsc */
+ stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN);
+
+ /* start polling for touch_det to detect release */
+ schedule_delayed_work(&ts->work, HZ / 50);
+
+ return IRQ_HANDLED;
+}
+
+static int __devinit stmpe_init_hw(struct stmpe_touch *ts)
+{
+ int ret;
+ u8 adc_ctrl1, adc_ctrl1_mask, tsc_cfg, tsc_cfg_mask;
+ struct stmpe *stmpe = ts->stmpe;
+ struct device *dev = ts->dev;
+
+ ret = stmpe_enable(stmpe, STMPE_BLOCK_TOUCHSCREEN | STMPE_BLOCK_ADC);
+ if (ret) {
+ dev_err(dev, "Could not enable clock for ADC and TS\n");
+ return ret;
+ }
+
+ adc_ctrl1 = SAMPLE_TIME(ts->sample_time) | MOD_12B(ts->mod_12b) |
+ REF_SEL(ts->ref_sel);
+ adc_ctrl1_mask = SAMPLE_TIME(0xff) | MOD_12B(0xff) | REF_SEL(0xff);
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1,
+ adc_ctrl1_mask, adc_ctrl1);
+ if (ret) {
+ dev_err(dev, "Could not setup ADC\n");
+ return ret;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2,
+ ADC_FREQ(0xff), ADC_FREQ(ts->adc_freq));
+ if (ret) {
+ dev_err(dev, "Could not setup ADC\n");
+ return ret;
+ }
+
+ tsc_cfg = AVE_CTRL(ts->ave_ctrl) | DET_DELAY(ts->touch_det_delay) |
+ SETTLING(ts->settling);
+ tsc_cfg_mask = AVE_CTRL(0xff) | DET_DELAY(0xff) | SETTLING(0xff);
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CFG, tsc_cfg_mask, tsc_cfg);
+ if (ret) {
+ dev_err(dev, "Could not config touch\n");
+ return ret;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z,
+ FRACTION_Z(0xff), FRACTION_Z(ts->fraction_z));
+ if (ret) {
+ dev_err(dev, "Could not config touch\n");
+ return ret;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_I_DRIVE,
+ I_DRIVE(0xff), I_DRIVE(ts->i_drive));
+ if (ret) {
+ dev_err(dev, "Could not config touch\n");
+ return ret;
+ }
+
+ /* set FIFO to 1 for single point reading */
+ ret = stmpe_reg_write(stmpe, STMPE_REG_FIFO_TH, 1);
+ if (ret) {
+ dev_err(dev, "Could not set FIFO\n");
+ return ret;
+ }
+
+ ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CTRL,
+ OP_MODE(0xff), OP_MODE(OP_MOD_XYZ));
+ if (ret) {
+ dev_err(dev, "Could not set mode\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int stmpe_ts_open(struct input_dev *dev)
+{
+ struct stmpe_touch *ts = input_get_drvdata(dev);
+ int ret = 0;
+
+ ret = __stmpe_reset_fifo(ts->stmpe);
+ if (ret)
+ return ret;
+
+ return stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, STMPE_TSC_CTRL_TSC_EN);
+}
+
+static void stmpe_ts_close(struct input_dev *dev)
+{
+ struct stmpe_touch *ts = input_get_drvdata(dev);
+
+ cancel_delayed_work_sync(&ts->work);
+
+ stmpe_set_bits(ts->stmpe, STMPE_REG_TSC_CTRL,
+ STMPE_TSC_CTRL_TSC_EN, 0);
+}
+
+static int __devinit stmpe_input_probe(struct platform_device *pdev)
+{
+ struct stmpe *stmpe = dev_get_drvdata(pdev->dev.parent);
+ struct stmpe_platform_data *pdata = stmpe->pdata;
+ struct stmpe_touch *ts;
+ struct input_dev *idev;
+ struct stmpe_ts_platform_data *ts_pdata = NULL;
+ int ret = 0;
+ unsigned int ts_irq;
+
+ ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
+ if (ts_irq < 0)
+ return ts_irq;
+
+ ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+ if (!ts)
+ goto err_out;
+
+ idev = input_allocate_device();
+ if (!idev)
+ goto err_free_ts;
+
+ platform_set_drvdata(pdev, ts);
+ ts->stmpe = stmpe;
+ ts->idev = idev;
+ ts->dev = &pdev->dev;
+
+ if (pdata)
+ ts_pdata = pdata->ts;
+
+ if (ts_pdata) {
+ ts->sample_time = ts_pdata->sample_time;
+ ts->mod_12b = ts_pdata->mod_12b;
+ ts->ref_sel = ts_pdata->ref_sel;
+ ts->adc_freq = ts_pdata->adc_freq;
+ ts->ave_ctrl = ts_pdata->ave_ctrl;
+ ts->touch_det_delay = ts_pdata->touch_det_delay;
+ ts->settling = ts_pdata->settling;
+ ts->fraction_z = ts_pdata->fraction_z;
+ ts->i_drive = ts_pdata->i_drive;
+ }
+
+ INIT_DELAYED_WORK(&ts->work, stmpe_work);
+
+ ret = request_threaded_irq(ts_irq, NULL, stmpe_ts_handler,
+ IRQF_ONESHOT, STMPE_TS_NAME, ts);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request IRQ %d\n", ts_irq);
+ goto err_free_input;
+ }
+
+ ret = stmpe_init_hw(ts);
+ if (ret)
+ goto err_free_irq;
+
+ idev->name = STMPE_TS_NAME;
+ idev->id.bustype = BUS_I2C;
+ idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ idev->open = stmpe_ts_open;
+ idev->close = stmpe_ts_close;
+
+ input_set_drvdata(idev, ts);
+
+ input_set_abs_params(idev, ABS_X, 0, XY_MASK, 0, 0);
+ input_set_abs_params(idev, ABS_Y, 0, XY_MASK, 0, 0);
+ input_set_abs_params(idev, ABS_PRESSURE, 0x0, 0xff, 0, 0);
+
+ ret = input_register_device(idev);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not register input device\n");
+ goto err_free_irq;
+ }
+
+ return ret;
+
+err_free_irq:
+ free_irq(ts_irq, ts);
+err_free_input:
+ input_free_device(idev);
+ platform_set_drvdata(pdev, NULL);
+err_free_ts:
+ kfree(ts);
+err_out:
+ return ret;
+}
+
+static int __devexit stmpe_ts_remove(struct platform_device *pdev)
+{
+ struct stmpe_touch *ts = platform_get_drvdata(pdev);
+ unsigned int ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
+
+ stmpe_disable(ts->stmpe, STMPE_BLOCK_TOUCHSCREEN);
+
+ free_irq(ts_irq, ts);
+
+ platform_set_drvdata(pdev, NULL);
+
+ input_unregister_device(ts->idev);
+ input_free_device(ts->idev);
+
+ kfree(ts);
+
+ return 0;
+}
+
+static struct platform_driver stmpe_ts_driver = {
+ .driver = {
+ .name = STMPE_TS_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = stmpe_input_probe,
+ .remove = __devexit_p(stmpe_ts_remove),
+};
+
+static int __init stmpe_ts_init(void)
+{
+ return platform_driver_register(&stmpe_ts_driver);
+}
+
+module_init(stmpe_ts_init);
+
+static void __exit stmpe_ts_exit(void)
+{
+ platform_driver_unregister(&stmpe_ts_driver);
+}
+
+module_exit(stmpe_ts_exit);
+
+MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");
+MODULE_DESCRIPTION("STMPEXXX touchscreen driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" STMPE_TS_NAME);
--
1.7.1
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [PATCH 6/6 V4] input: STMPE touch controller support
2010-06-24 11:13 ` [PATCH 6/6 V4] input: STMPE touch controller support Luotao Fu
2010-06-24 12:27 ` [PATCH 5/6 V2] mfd/stmpexxx: fix stmpe811 enable hook Luotao Fu
2010-06-24 12:28 ` [PATCH 6/6 V5] input: STMPE touch controller support Luotao Fu
@ 2010-06-24 12:31 ` Rabin VINCENT
2010-06-24 12:42 ` Luotao Fu
2 siblings, 1 reply; 31+ messages in thread
From: Rabin VINCENT @ 2010-06-24 12:31 UTC (permalink / raw)
To: Luotao Fu
Cc: Samuel Ortiz, Dmitry Torokhov, Linus WALLEIJ,
linux-kernel@vger.kernel.org, linux-input@vger.kernel.org,
STEricsson_nomadik_linux
On Thu, Jun 24, 2010 at 13:13:41 +0200, Luotao Fu wrote:
> + adc_ctrl1 = SAMPLE_TIME(ts->sample_time) | MOD_12B(ts->mod_12b) |
> + REF_SEL(ts->ref_sel);
> + ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1,
> + adc_ctrl1, adc_ctrl1);
> + if (ret) {
> + dev_err(&pdev->dev, "Could not setup ADC\n");
> + goto err_free_irq;
> + }
> +
> + ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2,
> + ADC_FREQ(ts->adc_freq), ADC_FREQ(ts->adc_freq));
> + if (ret) {
> + dev_err(&pdev->dev, "Could not setup ADC\n");
> + goto err_free_irq;
> + }
> +
> + tsc_cfg = AVE_CTRL(ts->ave_ctrl) | DET_DELAY(ts->touch_det_delay) |
> + SETTLING(ts->settling);
> + ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CFG, tsc_cfg, tsc_cfg);
> + if (ret) {
> + dev_err(&pdev->dev, "Could not config touch\n");
> + goto err_free_irq;
> + }
> +
> + ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z,
> + FRACTION_Z(ts->fraction_z),
> + FRACTION_Z(ts->fraction_z));
I think your earlier revisions had this same behaviour, but this only
writes the bits you are trying to set, and it may be a problem if there
are other bits already set in this field. I don't know if this is a
concern with this block, but if it is, you can do something like the
following to clear out the field before writing:
stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2,
ADC_FREQ(0xff), ADC_FREQ(ts->adc_freq));
or perhaps:
stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2,
0xff, ADC_FREQ(ts->adc_freq));
Rabin
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 6/6 V4] input: STMPE touch controller support
2010-06-24 12:31 ` [PATCH 6/6 V4] " Rabin VINCENT
@ 2010-06-24 12:42 ` Luotao Fu
2010-06-24 13:01 ` Rabin VINCENT
[not found] ` <20100624130108.GE26189@bnru02.bnr.st.com>
0 siblings, 2 replies; 31+ messages in thread
From: Luotao Fu @ 2010-06-24 12:42 UTC (permalink / raw)
To: Rabin VINCENT
Cc: Luotao Fu, Samuel Ortiz, Dmitry Torokhov, Linus WALLEIJ,
linux-kernel@vger.kernel.org, linux-input@vger.kernel.org,
STEricsson_nomadik_linux
[-- Attachment #1: Type: text/plain, Size: 2419 bytes --]
Hi Rabin,
On Thu, Jun 24, 2010 at 06:01:53PM +0530, Rabin VINCENT wrote:
> On Thu, Jun 24, 2010 at 13:13:41 +0200, Luotao Fu wrote:
> > + adc_ctrl1 = SAMPLE_TIME(ts->sample_time) | MOD_12B(ts->mod_12b) |
> > + REF_SEL(ts->ref_sel);
> > + ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL1,
> > + adc_ctrl1, adc_ctrl1);
> > + if (ret) {
> > + dev_err(&pdev->dev, "Could not setup ADC\n");
> > + goto err_free_irq;
> > + }
> > +
> > + ret = stmpe_set_bits(stmpe, STMPE_REG_ADC_CTRL2,
> > + ADC_FREQ(ts->adc_freq), ADC_FREQ(ts->adc_freq));
> > + if (ret) {
> > + dev_err(&pdev->dev, "Could not setup ADC\n");
> > + goto err_free_irq;
> > + }
> > +
> > + tsc_cfg = AVE_CTRL(ts->ave_ctrl) | DET_DELAY(ts->touch_det_delay) |
> > + SETTLING(ts->settling);
> > + ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_CFG, tsc_cfg, tsc_cfg);
> > + if (ret) {
> > + dev_err(&pdev->dev, "Could not config touch\n");
> > + goto err_free_irq;
> > + }
> > +
> > + ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z,
> > + FRACTION_Z(ts->fraction_z),
> > + FRACTION_Z(ts->fraction_z));
>
> I think your earlier revisions had this same behaviour, but this only
> writes the bits you are trying to set, and it may be a problem if there
> are other bits already set in this field. I don't know if this is a
> concern with this block, but if it is, you can do something like the
> following to clear out the field before writing:
>
This is done intentionally to leave the bits alone which I don't want.
Most of the registers here are used exclusively for the touchscreen.
Some others are shared with the ADC. The ADC however doesn't have any
own configuration and has to go with the configuration of the touch
screen. Hence it's OK, even probably better not to touch the bits we
don't need.
cheers
Luotao Fu
--
Pengutronix e.K. | Dipl.-Ing. Luotao Fu |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [PATCH 6/6 V4] input: STMPE touch controller support
2010-06-24 12:42 ` Luotao Fu
@ 2010-06-24 13:01 ` Rabin VINCENT
[not found] ` <20100624130108.GE26189@bnru02.bnr.st.com>
1 sibling, 0 replies; 31+ messages in thread
From: Rabin VINCENT @ 2010-06-24 13:01 UTC (permalink / raw)
To: Luotao Fu, Samuel Ortiz, Dmitry Torokhov, Linus WALLEIJ,
linux-kernel
On Thu, Jun 24, 2010 at 14:42:10 +0200, Luotao Fu wrote:
> On Thu, Jun 24, 2010 at 06:01:53PM +0530, Rabin VINCENT wrote:
> > On Thu, Jun 24, 2010 at 13:13:41 +0200, Luotao Fu wrote:
> > > + ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z,
> > > + FRACTION_Z(ts->fraction_z),
> > > + FRACTION_Z(ts->fraction_z));
> >
> > I think your earlier revisions had this same behaviour, but this only
> > writes the bits you are trying to set, and it may be a problem if there
> > are other bits already set in this field. I don't know if this is a
> > concern with this block, but if it is, you can do something like the
> > following to clear out the field before writing:
> >
>
> This is done intentionally to leave the bits alone which I don't want.
> Most of the registers here are used exclusively for the touchscreen.
> Some others are shared with the ADC. The ADC however doesn't have any
> own configuration and has to go with the configuration of the touch
> screen. Hence it's OK, even probably better not to touch the bits we
> don't need.
I meant something like: let's say you want to change the "count of the
fractional part" (I quote from your platdata). It (the FRACTION_Z
field, I assume) has a default value of (say) 2. Say you want to change
the count to 1. The above write will change it to 3 instead. If this
is really the behaviour you need, it should be OK then.
Rabin
^ permalink raw reply [flat|nested] 31+ messages in thread
[parent not found: <20100624130108.GE26189@bnru02.bnr.st.com>]
* Re: [PATCH 6/6 V4] input: STMPE touch controller support
[not found] ` <20100624130108.GE26189@bnru02.bnr.st.com>
@ 2010-06-24 13:11 ` Luotao Fu
0 siblings, 0 replies; 31+ messages in thread
From: Luotao Fu @ 2010-06-24 13:11 UTC (permalink / raw)
To: Rabin VINCENT
Cc: Luotao Fu, Samuel Ortiz, Dmitry Torokhov, Linus WALLEIJ,
linux-kernel@vger.kernel.org, linux-input@vger.kernel.org,
STEricsson_nomadik_linux
[-- Attachment #1: Type: text/plain, Size: 2230 bytes --]
On Thu, Jun 24, 2010 at 06:31:09PM +0530, Rabin VINCENT wrote:
> On Thu, Jun 24, 2010 at 14:42:10 +0200, Luotao Fu wrote:
> > On Thu, Jun 24, 2010 at 06:01:53PM +0530, Rabin VINCENT wrote:
> > > On Thu, Jun 24, 2010 at 13:13:41 +0200, Luotao Fu wrote:
> > > > + ret = stmpe_set_bits(stmpe, STMPE_REG_TSC_FRACTION_Z,
> > > > + FRACTION_Z(ts->fraction_z),
> > > > + FRACTION_Z(ts->fraction_z));
> > >
> > > I think your earlier revisions had this same behaviour, but this only
> > > writes the bits you are trying to set, and it may be a problem if there
> > > are other bits already set in this field. I don't know if this is a
> > > concern with this block, but if it is, you can do something like the
> > > following to clear out the field before writing:
> > >
> >
> > This is done intentionally to leave the bits alone which I don't want.
> > Most of the registers here are used exclusively for the touchscreen.
> > Some others are shared with the ADC. The ADC however doesn't have any
> > own configuration and has to go with the configuration of the touch
> > screen. Hence it's OK, even probably better not to touch the bits we
> > don't need.
>
> I meant something like: let's say you want to change the "count of the
> fractional part" (I quote from your platdata). It (the FRACTION_Z
> field, I assume) has a default value of (say) 2. Say you want to change
> the count to 1. The above write will change it to 3 instead. If this
> is really the behaviour you need, it should be OK then.
hmm, good catch. I didn't think about this. Actually nobody else should
touch these registers and they are only written while doing probe,
directly after the chip get resetted. However, it is still theoretically
troublesome, if one of them get written previously by accident. I'll
fix it. Thanks for the catch.
cheers
Luotao Fu
--
Pengutronix e.K. | Dipl.-Ing. Luotao Fu |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 31+ messages in thread