LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
From: Nicolas FERRE <nicolas.ferre@rfo.atmel.com>
To: David Brownell <d-b@pacbell.net>
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH] input/spi: add ads7843 support to ads7846 touchscreen driver
Date: Fri, 15 Dec 2006 15:45:08 +0100	[thread overview]
Message-ID: <4582B4F4.2050106@rfo.atmel.com> (raw)

Add support for the ads7843 touchscreen controller to the ads7846
driver code.
The "pen down" information is managed quite differently as we
do not have a touch-pressure measurement on the ads7843.

Signed-off-by: Nicolas Ferre <nicolas.ferre@rfo.atmel.com>
---

I add a ads7843_rx function to manage the end of a measurement cycle.
As for ads7846_rx, it does the real work and communicates with the
input subsystem.
The timer function is responsible of taking the pen up/pen down state
through the board specific get_pendown_state() callback.

As the SPI underlying code behaves quite differently from a controller
driver to another while not having a tx_buf filled, I have add a
zeroed buffer to give to the SPI layer while receiving data.

===================================================================
--- a/input/touchscreen/ads7846.c	(.../linux-2.6.19-at91/drivers)	(revision 634)
+++ b/input/touchscreen/ads7846.c	(.../linux-2.6.19-atmel-devel/drivers)	(revision 634)
@@ -4,6 +4,7 @@
  * Copyright (c) 2005 David Brownell
  * Copyright (c) 2006 Nokia Corporation
  * Various changes: Imre Deak <imre.deak@nokia.com>
+ * Ads7843 support: Atmel, Nicolas Ferre <nicolas.ferre@rfo.atmel.com>
  *
  * Using code from:
  *  - corgi_ts.c
@@ -38,7 +39,8 @@
 /*
  * This code has been heavily tested on a Nokia 770, and lightly
  * tested on other ads7846 devices (OSK/Mistral, Lubbock).
- * Support for ads7843 and ads7845 has only been stubbed in.
+ * Support for ads7843 tested on Atmel at91sam926x-EK.
+ * Support for ads7845 has only been stubbed in.
  *
  * IRQ handling needs a workaround because of a shortcoming in handling
  * edge triggered IRQs on some platforms like the OMAP1/2. These
@@ -82,6 +84,7 @@ struct ads7846 {
 	u16			pressure_max;
 
 	u8			read_x, read_y, read_z1, read_z2, pwrdown;
+	u16			zerro;		/* to send zerros while receiving */
 	u16			dummy;		/* for the pwrdown read */
 	struct ts_event		tc;
 
@@ -151,6 +154,10 @@ struct ads7846 {
 #define	READ_X	(READ_12BIT_DFR(x)  | ADS_PD10_ADC_ON)
 #define	PWRDOWN	(READ_12BIT_DFR(y)  | ADS_PD10_PDOWN)	/* LAST */
 
+/* alternate ads7843 commands */
+#define	ALT_READ_Y	(READ_12BIT_DFR(y)  | ADS_PD10_ALL_ON)
+#define	ALT_READ_X	(READ_12BIT_DFR(x)  | ADS_PD10_ALL_ON)
+
 /* single-ended samples need to first power up reference voltage;
  * we leave both ADC and VREF powered
  */
@@ -171,6 +178,7 @@ struct ser_req {
 	u8			command;
 	u8			ref_off;
 	u16			scratch;
+	u16			zerro;
 	__be16			sample;
 	struct spi_message	msg;
 	struct spi_transfer	xfer[6];
@@ -203,6 +211,7 @@ static int ads7846_read12_ser(struct dev
 	req->ref_on = REF_ON;
 	req->xfer[0].tx_buf = &req->ref_on;
 	req->xfer[0].len = 1;
+	req->xfer[1].tx_buf = &req->zerro;
 	req->xfer[1].rx_buf = &req->scratch;
 	req->xfer[1].len = 2;
 
@@ -217,6 +226,7 @@ static int ads7846_read12_ser(struct dev
 	req->command = (u8) command;
 	req->xfer[2].tx_buf = &req->command;
 	req->xfer[2].len = 1;
+	req->xfer[3].tx_buf = &req->zerro;
 	req->xfer[3].rx_buf = &req->sample;
 	req->xfer[3].len = 2;
 
@@ -226,6 +236,7 @@ static int ads7846_read12_ser(struct dev
 	req->ref_off = REF_OFF;
 	req->xfer[4].tx_buf = &req->ref_off;
 	req->xfer[4].len = 1;
+	req->xfer[3].tx_buf = &req->zerro;
 	req->xfer[5].rx_buf = &req->scratch;
 	req->xfer[5].len = 2;
 
@@ -410,6 +421,50 @@ static void ads7846_rx(void *ads)
 	spin_unlock_irqrestore(&ts->lock, flags);
 }
 
+static void ads7843_rx(void *ads)
+{
+	struct ads7846		*ts = ads;
+	struct input_dev	*input_dev = ts->input;
+	u16			x, y;
+	unsigned long		flags;
+
+	
+	/* adjust:  on-wire is a must-ignore bit, a BE12 value, then padding;
+	 * built from two 8 bit values written msb-first.
+	 */
+	x = (be16_to_cpu(ts->tc.x) >> 3) & 0x0fff;
+	y = (be16_to_cpu(ts->tc.y) >> 3) & 0x0fff;
+
+	/* range filtering */
+	if (x == MAX_12BIT)
+		x = 0;
+
+	if (ts->pendown) {
+		input_report_key(input_dev, BTN_TOUCH, 1);
+		input_report_abs(input_dev, ABS_PRESSURE, ts->pressure_max / 2);
+		input_report_abs(input_dev, ABS_X, x);
+		input_report_abs(input_dev, ABS_Y, y);
+	} else {
+		input_report_key(input_dev, BTN_TOUCH, 0);
+		input_report_abs(input_dev, ABS_PRESSURE, 0);
+	}
+
+	input_sync(input_dev);
+
+#ifdef	VERBOSE
+	pr_debug("%s: %d/%d%s\n", ts->spi->dev.bus_id,
+		x, y, ts->pendown ? "" : " UP");
+#endif
+
+	if (ts->pendown) {
+		spin_lock_irqsave(&ts->lock, flags);
+
+		mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD);
+
+		spin_unlock_irqrestore(&ts->lock, flags);
+	}
+}
+
 static void ads7846_debounce(void *ads)
 {
 	struct ads7846		*ts = ads;
@@ -465,11 +520,25 @@ static void ads7846_timer(unsigned long 
 {
 	struct ads7846	*ts = (void *)handle;
 	int		status = 0;
+	int		alt_end_cycle = 0; /* ads7843 alternative cycle end */
+
+	if (ts->model == 7843) {
+		/* get sample */
+		ts->pendown = ts->get_pendown_state();
+		alt_end_cycle = ts->pending;
+	}
 
 	spin_lock_irq(&ts->lock);
 
-	if (unlikely(ts->msg_idx && !ts->pendown)) {
+	if (unlikely(!ts->pendown && (ts->msg_idx || alt_end_cycle))) {
 		/* measurement cycle ended */
+		if (ts->model == 7843) {
+			status = spi_async(ts->spi, ts->last_msg);
+			if (status)
+				dev_err(&ts->spi->dev,
+					"spi_async --> %d\n", status);
+		}
+
 		if (!device_suspended(&ts->spi->dev)) {
 			ts->irq_disabled = 0;
 			enable_irq(ts->spi->irq);
@@ -684,12 +753,17 @@ static int __devinit ads7846_probe(struc
 	spi_message_init(m);
 
 	/* y- still on; turn on only y+ (and ADC) */
-	ts->read_y = READ_Y;
+	if (ts->model == 7843) {
+		ts->read_y = ALT_READ_Y;
+	} else {
+		ts->read_y = READ_Y;
+	}
 	x->tx_buf = &ts->read_y;
 	x->len = 1;
 	spi_message_add_tail(x, m);
 
 	x++;
+	x->tx_buf = &ts->zerro;
 	x->rx_buf = &ts->tc.y;
 	x->len = 2;
 	spi_message_add_tail(x, m);
@@ -702,12 +776,17 @@ static int __devinit ads7846_probe(struc
 
 	/* turn y- off, x+ on, then leave in lowpower */
 	x++;
-	ts->read_x = READ_X;
+	if (ts->model == 7843) {
+		ts->read_x = ALT_READ_X;
+	} else {
+		ts->read_x = READ_X;
+	}
 	x->tx_buf = &ts->read_x;
 	x->len = 1;
 	spi_message_add_tail(x, m);
 
 	x++;
+	x->tx_buf = &ts->zerro;
 	x->rx_buf = &ts->tc.x;
 	x->len = 2;
 	spi_message_add_tail(x, m);
@@ -763,12 +842,17 @@ static int __devinit ads7846_probe(struc
 	spi_message_add_tail(x, m);
 
 	x++;
+	x->tx_buf = &ts->zerro;
 	x->rx_buf = &ts->dummy;
 	x->len = 2;
 	CS_CHANGE(*x);
 	spi_message_add_tail(x, m);
 
-	m->complete = ads7846_rx;
+	if (ts->model == 7843) {
+		m->complete = ads7843_rx;
+	} else {
+		m->complete = ads7846_rx;
+	}
 	m->context = ts;
 
 	ts->last_msg = m;
@@ -782,11 +866,16 @@ static int __devinit ads7846_probe(struc
 
 	dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq);
 
-	/* take a first sample, leaving nPENIRQ active; avoid
-	 * the touchscreen, in case it's not connected.
-	 */
-	(void) ads7846_read12_ser(&spi->dev,
-			  READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON);
+	if (ts->model != 7843) {
+		/* take a first sample, leaving nPENIRQ active; avoid
+		 * the touchscreen, in case it's not connected.
+		 */
+		(void) ads7846_read12_ser(&spi->dev,
+				  READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON);
+	} else {
+		(void) ads7846_read12_ser(&spi->dev,
+				  READ_12BIT_DFR(y) | ADS_PD10_ALL_ON);
+	}
 
 	/* ads7843/7845 don't have temperature sensors, and
 	 * use the other sensors a bit differently too
@@ -795,12 +884,14 @@ static int __devinit ads7846_probe(struc
 		device_create_file(&spi->dev, &dev_attr_temp0);
 		device_create_file(&spi->dev, &dev_attr_temp1);
 	}
-	if (ts->model != 7845)
+	if (ts->model != 7845 && ts->model != 7843)
 		device_create_file(&spi->dev, &dev_attr_vbatt);
-	device_create_file(&spi->dev, &dev_attr_vaux);
 
-	device_create_file(&spi->dev, &dev_attr_pen_down);
+	if (ts->model != 7843) {
+		device_create_file(&spi->dev, &dev_attr_vaux);
+	}
 
+	device_create_file(&spi->dev, &dev_attr_pen_down);
 	device_create_file(&spi->dev, &dev_attr_disable);
 
 	err = input_register_device(input_dev);
@@ -816,9 +907,12 @@ static int __devinit ads7846_probe(struc
 		device_remove_file(&spi->dev, &dev_attr_temp1);
 		device_remove_file(&spi->dev, &dev_attr_temp0);
 	}
-	if (ts->model != 7845)
+	if (ts->model != 7845 && ts->model != 7843)
 		device_remove_file(&spi->dev, &dev_attr_vbatt);
-	device_remove_file(&spi->dev, &dev_attr_vaux);
+
+	if (ts->model != 7843) {
+		device_remove_file(&spi->dev, &dev_attr_vaux);
+	}
 
 	free_irq(spi->irq, ts);
  err_free_mem:
@@ -841,9 +935,12 @@ static int __devexit ads7846_remove(stru
 		device_remove_file(&spi->dev, &dev_attr_temp1);
 		device_remove_file(&spi->dev, &dev_attr_temp0);
 	}
-	if (ts->model != 7845)
+	if (ts->model != 7845 && ts->model != 7843)
 		device_remove_file(&spi->dev, &dev_attr_vbatt);
-	device_remove_file(&spi->dev, &dev_attr_vaux);
+
+	if (ts->model != 7843) {
+		device_remove_file(&spi->dev, &dev_attr_vaux);
+	}
 
 	free_irq(ts->spi->irq, ts);
 	/* suspend left the IRQ disabled */



             reply	other threads:[~2006-12-15 15:16 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-12-15 14:45 Nicolas FERRE [this message]
2006-12-20 22:03 ` Andrew Morton
2006-12-21  9:57   ` Nicolas Ferre
     [not found] <4582BD29.4020203@rfo.atmel.com>
2006-12-20 23:13 ` David Brownell
2006-12-21 13:08   ` Nicolas Ferre
2006-12-21 14:40     ` Nicolas Ferre
2006-12-22 20:05       ` David Brownell
2006-12-22 19:31     ` David Brownell
2006-12-22 20:14       ` Dmitry Torokhov
2006-12-22 19:25 [patch 2.6.20-rc1 6/6] input: ads7846 directly senses PENUP state David Brownell
2006-12-28 22:37 ` David Brownell
2006-12-29  6:22   ` Dmitry Torokhov
2006-12-29 20:26     ` David Brownell
2007-02-16 17:37       ` [PATCH] input/spi: add ads7843 support to ads7846 touchscreen driver Nicolas Ferre
2007-02-16 19:08         ` David Brownell
2007-02-19 12:48           ` Nicolas Ferre
2007-02-19 18:46             ` David Brownell
2007-02-20  9:19               ` Nicolas Ferre
2007-03-01  4:49                 ` Dmitry Torokhov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4582B4F4.2050106@rfo.atmel.com \
    --to=nicolas.ferre@rfo.atmel.com \
    --cc=d-b@pacbell.net \
    --cc=linux-kernel@vger.kernel.org \
    --subject='Re: [PATCH] input/spi: add ads7843 support to ads7846 touchscreen driver' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

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