Touch screen driver for the SuperH MigoR board
Subsystems (3)
PATCH 1/1 Touch screen driver for the SuperH MigoR board
This patch adds a touch screen driver for the MigoR board. The chip we interface to is unfortunately a custom designed microcontroller speaking some undocumented protocol over i2c.
The board specific code is expected to register this device as an i2c chip using struct i2c_board_info [] and i2c_register_board_info().
---
drivers/input/touchscreen/Kconfig | 12 ++ drivers/input/touchscreen/Makefile | 1 drivers/input/touchscreen/migor_ts.c | 196 ++++++++++++++++++++++++++++++++++ 3 files changed, 209 insertions(+)
drivers/input/touchscreen/Kconfig +12 -0
@@ -134,6 +134,18 @@ config TOUCHSCREEN_HP7XX To compile this driver as a module, choose M here: the module will be called jornada720_ts. +config TOUCHSCREEN_MIGOR + tristate "Renesas MIGO-R touchscreen" + depends on SH_MIGOR + default n + help + Say Y here to enable MIGO-R touchscreen support. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called migor_ts. + config TOUCHSCREEN_PENMOUNT tristate "Penmount serial touchscreen" select SERIO
drivers/input/touchscreen/Makefile +1 -0
@@ -19,3 +19,4 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += pe obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o +obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
drivers/input/touchscreen/migor_ts.c new file +196 -0
196 lines not on this page · raw message
Quoted 49 lines · On Fri, 21 Mar 2008 20:16:30 +0900 Magnus Damm <[email protected]> wrote:
This patch adds a touch screen driver for the MigoR board. The chip we interface to is unfortunately a custom designed microcontroller speaking some undocumented protocol over i2c.
The board specific code is expected to register this device as an i2c chip using struct
i2c_board_info[] andi2c_register_board_info()....
drivers/input/touchscreen/migor_ts.c new file +40
-0+static void migor_ts_poscheck (struct work_struct *work) +{ +struct migor_ts_priv *priv =container_of (work, + struct migor_ts_priv, + work.work); +unsigned short xpos, ypos; +unsigned char event; +u_int8_t buf[16 ]; + +memset (buf,0 ,sizeof (buf)); + +/* Set Index 0 */ + buf[0 ] =0 ; +if (i2c_master_send (priv->client, buf,1 ) !=1 ) { +dev_err (&priv->client->dev,"Unable to write i2c index\n" ); + goto out; + } + +/* Now do Page Read */ +if (i2c_master_recv (priv->client, buf,sizeof (buf)) !=sizeof (buf)) { +dev_err (&priv->client->dev,"Unable to read i2c page\n" ); + goto out; + } + + ypos = ((buf[9 ] &0x03 ) <<8 | buf[8 ]); + xpos = ((buf[11 ] &0x03 ) <<8 | buf[10 ]); + event = buf[12 ]; + +if ((event ==EVENT_PENDOWN ) || (event ==EVENT_REPEAT )) { +input_report_key (priv->input,BTN_TOUCH ,1 ); +input_report_abs (priv->input,ABS_X , ypos);/*X-Y swap*/ +input_report_abs (priv->input,ABS_Y , xpos); +input_report_abs (priv->input,ABS_PRESSURE ,120 ); +input_sync (priv->input); + }else if (event ==EVENT_PENUP ) { +input_report_abs (priv->input,ABS_PRESSURE ,0 ); +input_sync (priv->input); + } + out: +enable_irq (priv->irq);
drivers/input/touchscreen/migor_ts.c line 94
Quoted 10 lines
drivers/input/touchscreen/migor_ts.c new file +10
-0+} + +static irqreturn_t migor_ts_isr (int irq,void *dev_id) +{ +struct migor_ts_priv *priv = dev_id; + +disable_irq_nosync (irq); +schedule_delayed_work (&priv->work,HZ /20 ); +return IRQ_HANDLED ; +}
eww. Doing a disable_irq() on each interrupt and reenabling interrupts later isn't very nice. And it might cause havoc if that interrupt is shared.
Why is this code like this?
No, don't answer that question. If I wanted to know this when reading the code, then others will want to know it also. It needs to be fully explained in code comments, please.
Can we not pull the data out of the hardware at interrupt time and then queue that data up for the keventd processing?
drivers/input/touchscreen/migor_ts.c line 171
Quoted 12 lines
drivers/input/touchscreen/migor_ts.c new file +12
-0+static int migor_ts_remove (struct i2c_client *client) +{ +struct migor_ts_priv *priv =dev_get_drvdata (&client->dev); + +/* disable controller */ +i2c_master_send (client, migor_ts_dis_seq,sizeof (migor_ts_dis_seq)); + +free_irq (priv->irq, priv); +input_unregister_device (priv->input); +kfree (priv); +return 0 ; +}
Might a delayed work still be scheduled when we run this? A cancel_delayed_work_sync() would set minds at rest.
Quoted 6 lines · Andrew Morton
Quoted 3 lines · On Fri, 21 Mar 2008 20:16:30 +0900 Magnus Damm <[email protected]> wrote:
This patch adds a touch screen driver for the MigoR board. The chip we interface to is unfortunately a custom designed microcontroller speaking some undocumented protocol over i2c.
[snip]
Quoted 13 lines
drivers/input/touchscreen/migor_ts.c line 94
Quoted 8 lines
drivers/input/touchscreen/migor_ts.c new file +8
-0+static irqreturn_t migor_ts_isr (int irq,void *dev_id) +{ +struct migor_ts_priv *priv = dev_id; + +disable_irq_nosync (irq); +schedule_delayed_work (&priv->work,HZ /20 ); +return IRQ_HANDLED ; +}eww. Doing a
disable_irq()on each interrupt and reenabling interrupts later isn't very nice. And it might cause havoc if that interrupt is shared.
Quoted 1 line
Why is this code like this?
The code is more or less doing the same thing as the ads7846 driver, except this one is communicating over i2c instead of spi. This means is because of great hardware design with interrupts that needs to be acked over an extremely slow serial bus. So we just disable the interrupt and handle everything from a different context. Apart from avoiding serious latency issues, doing things from interrupt context simply won't work since the i2c bus driver may be interrupt driven and may sleep while waiting for the serial bus data to be sent.
And you are right, this won't work with shared interrupts.
Quoted 3 lines
No, don't answer that question. If I wanted to know this when reading the code, then others will want to know it also. It needs to be fully explained in code comments, please.
Yeah, having a comment in there would certainly help.
Quoted 2 lines
Can we not pull the data out of the hardware at interrupt time and then queue that data up for the keventd processing?
No can do, the serial bus is too slow.
Quoted 7 lines
Quoted 7 lines
drivers/input/touchscreen/migor_ts.c new file +7
-0+static int migor_ts_remove (struct i2c_client *client) +{ +struct migor_ts_priv *priv =dev_get_drvdata (&client->dev); + +/* disable controller */ +i2c_master_send (client, migor_ts_dis_seq,sizeof (migor_ts_dis_seq)); +
Quoted 8 lines
drivers/input/touchscreen/migor_ts.c line 171
Quoted 5 lines
drivers/input/touchscreen/migor_ts.c new file +5
-0+free_irq (priv->irq, priv); +input_unregister_device (priv->input); +kfree (priv); +return 0 ; +}Might a delayed work still be scheduled when we run this? A
cancel_delayed_work_sync()would set minds at rest.
Good catch. I'll fix this up and repost.
Thanks!
/ magnus
Quoted 4 lines · Magnus Damm
interrupt and handle everything from a different context. Apart from avoiding serious latency issues, doing things from interrupt context simply won't work since the i2c bus driver may be interrupt driven and may sleep while waiting for the serial bus data to be sent.
Given that having devices that generate interrupts that need to be serviced over interrupt driven buses is a fairly common pattern it seems like it would be worth adding some helper code - if nothing else, it would help with the documentation.
Signature · 1 line
"You grabbed my hand and we fell into it, like a daydream - or a fever."