Commit 9c950971 authored by Oleksij Rempel's avatar Oleksij Rempel Committed by Dmitry Torokhov

Input: ads7846 - convert to full duplex

Starting with 3eac5c7e ("Input: ads7846 - extend the driver for ads7845
controller support"), the ads7845 was partially converted to full duplex
mode.

Since it is not touchscreen controller specific, it is better to extend
this conversion to cover entire driver. This will reduce CPU load and make
driver more readable.
Signed-off-by: default avatarOleksij Rempel <o.rempel@pengutronix.de>
Link: https://lore.kernel.org/r/20201110085041.16303-2-o.rempel@pengutronix.deSigned-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent e52cd628
......@@ -62,19 +62,26 @@
/* this driver doesn't aim at the peak continuous sample rate */
#define SAMPLE_BITS (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */)
struct ts_event {
struct ads7846_buf {
u8 cmd;
/*
* For portability, we can't read 12 bit values using SPI (which
* would make the controller deliver them as native byte order u16
* with msbs zeroed). Instead, we read them as two 8-bit values,
* *** WHICH NEED BYTESWAPPING *** and range adjustment.
* This union is a temporary hack. The driver does an in-place
* endianness conversion. This will be cleaned up in the next
* patch.
*/
u16 x;
u16 y;
u16 z1, z2;
bool ignore;
u8 x_buf[3];
u8 y_buf[3];
union {
__be16 data_be16;
u16 data;
};
} __packed;
struct ts_event {
bool ignore;
struct ads7846_buf x;
struct ads7846_buf y;
struct ads7846_buf z1;
struct ads7846_buf z2;
};
/*
......@@ -83,11 +90,12 @@ struct ts_event {
* systems where main memory is not DMA-coherent (most non-x86 boards).
*/
struct ads7846_packet {
u8 read_x, read_y, read_z1, read_z2, pwrdown;
u16 dummy; /* for the pwrdown read */
struct ts_event tc;
/* for ads7845 with mpc5121 psc spi we use 3-byte buffers */
u8 read_x_cmd[3], read_y_cmd[3], pwrdown_cmd[3];
struct ts_event tc;
struct ads7846_buf read_x_cmd;
struct ads7846_buf read_y_cmd;
struct ads7846_buf read_z1_cmd;
struct ads7846_buf read_z2_cmd;
struct ads7846_buf pwrdown_cmd;
};
struct ads7846 {
......@@ -686,16 +694,9 @@ static int ads7846_get_value(struct ads7846 *ts, struct spi_message *m)
int value;
struct spi_transfer *t =
list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
struct ads7846_buf *buf = t->rx_buf;
if (ts->model == 7845) {
value = be16_to_cpup((__be16 *)&(((char *)t->rx_buf)[1]));
} else {
/*
* adjust: on-wire is a must-ignore bit, a BE12 value, then
* padding; built from two 8 bit values written msb-first.
*/
value = be16_to_cpup((__be16 *)t->rx_buf);
}
value = be16_to_cpup(&buf->data_be16);
/* enforce ADC output is 12 bits width */
return (value >> 3) & 0xfff;
......@@ -705,8 +706,9 @@ static void ads7846_update_value(struct spi_message *m, int val)
{
struct spi_transfer *t =
list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
struct ads7846_buf *buf = t->rx_buf;
*(u16 *)t->rx_buf = val;
buf->data = val;
}
static void ads7846_read_state(struct ads7846 *ts)
......@@ -774,16 +776,14 @@ static void ads7846_report_state(struct ads7846 *ts)
* from on-the-wire format as part of debouncing to get stable
* readings.
*/
x = packet->tc.x.data;
y = packet->tc.y.data;
if (ts->model == 7845) {
x = *(u16 *)packet->tc.x_buf;
y = *(u16 *)packet->tc.y_buf;
z1 = 0;
z2 = 0;
} else {
x = packet->tc.x;
y = packet->tc.y;
z1 = packet->tc.z1;
z2 = packet->tc.z2;
z1 = packet->tc.z1.data;
z2 = packet->tc.z2.data;
}
/* range filtering */
......@@ -1000,26 +1000,11 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
spi_message_init(m);
m->context = ts;
if (ts->model == 7845) {
packet->read_y_cmd[0] = READ_Y(vref);
packet->read_y_cmd[1] = 0;
packet->read_y_cmd[2] = 0;
x->tx_buf = &packet->read_y_cmd[0];
x->rx_buf = &packet->tc.y_buf[0];
x->len = 3;
spi_message_add_tail(x, m);
} else {
/* y- still on; turn on only y+ (and ADC) */
packet->read_y = READ_Y(vref);
x->tx_buf = &packet->read_y;
x->len = 1;
spi_message_add_tail(x, m);
x++;
x->rx_buf = &packet->tc.y;
x->len = 2;
spi_message_add_tail(x, m);
}
packet->read_y_cmd.cmd = READ_Y(vref);
x->tx_buf = &packet->read_y_cmd;
x->rx_buf = &packet->tc.y;
x->len = 3;
spi_message_add_tail(x, m);
/*
* The first sample after switching drivers can be low quality;
......@@ -1029,15 +1014,11 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
if (pdata->settle_delay_usecs) {
x->delay.value = pdata->settle_delay_usecs;
x->delay.unit = SPI_DELAY_UNIT_USECS;
x++;
x->tx_buf = &packet->read_y;
x->len = 1;
spi_message_add_tail(x, m);
x++;
x->tx_buf = &packet->read_y_cmd;
x->rx_buf = &packet->tc.y;
x->len = 2;
x->len = 3;
spi_message_add_tail(x, m);
}
......@@ -1046,28 +1027,13 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
spi_message_init(m);
m->context = ts;
if (ts->model == 7845) {
x++;
packet->read_x_cmd[0] = READ_X(vref);
packet->read_x_cmd[1] = 0;
packet->read_x_cmd[2] = 0;
x->tx_buf = &packet->read_x_cmd[0];
x->rx_buf = &packet->tc.x_buf[0];
x->len = 3;
spi_message_add_tail(x, m);
} else {
/* turn y- off, x+ on, then leave in lowpower */
x++;
packet->read_x = READ_X(vref);
x->tx_buf = &packet->read_x;
x->len = 1;
spi_message_add_tail(x, m);
x++;
x->rx_buf = &packet->tc.x;
x->len = 2;
spi_message_add_tail(x, m);
}
/* turn y- off, x+ on, then leave in lowpower */
x++;
packet->read_x_cmd.cmd = READ_X(vref);
x->tx_buf = &packet->read_x_cmd;
x->rx_buf = &packet->tc.x;
x->len = 3;
spi_message_add_tail(x, m);
/* ... maybe discard first sample ... */
if (pdata->settle_delay_usecs) {
......@@ -1075,13 +1041,9 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
x->delay.unit = SPI_DELAY_UNIT_USECS;
x++;
x->tx_buf = &packet->read_x;
x->len = 1;
spi_message_add_tail(x, m);
x++;
x->tx_buf = &packet->read_x_cmd;
x->rx_buf = &packet->tc.x;
x->len = 2;
x->len = 3;
spi_message_add_tail(x, m);
}
......@@ -1093,14 +1055,10 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
m->context = ts;
x++;
packet->read_z1 = READ_Z1(vref);
x->tx_buf = &packet->read_z1;
x->len = 1;
spi_message_add_tail(x, m);
x++;
packet->read_z1_cmd.cmd = READ_Z1(vref);
x->tx_buf = &packet->read_z1_cmd;
x->rx_buf = &packet->tc.z1;
x->len = 2;
x->len = 3;
spi_message_add_tail(x, m);
/* ... maybe discard first sample ... */
......@@ -1109,13 +1067,9 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
x->delay.unit = SPI_DELAY_UNIT_USECS;
x++;
x->tx_buf = &packet->read_z1;
x->len = 1;
spi_message_add_tail(x, m);
x++;
x->tx_buf = &packet->read_z1_cmd;
x->rx_buf = &packet->tc.z1;
x->len = 2;
x->len = 3;
spi_message_add_tail(x, m);
}
......@@ -1125,14 +1079,10 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
m->context = ts;
x++;
packet->read_z2 = READ_Z2(vref);
x->tx_buf = &packet->read_z2;
x->len = 1;
spi_message_add_tail(x, m);
x++;
packet->read_z2_cmd.cmd = READ_Z2(vref);
x->tx_buf = &packet->read_z2_cmd;
x->rx_buf = &packet->tc.z2;
x->len = 2;
x->len = 3;
spi_message_add_tail(x, m);
/* ... maybe discard first sample ... */
......@@ -1141,13 +1091,9 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
x->delay.unit = SPI_DELAY_UNIT_USECS;
x++;
x->tx_buf = &packet->read_z2;
x->len = 1;
spi_message_add_tail(x, m);
x++;
x->tx_buf = &packet->read_z2_cmd;
x->rx_buf = &packet->tc.z2;
x->len = 2;
x->len = 3;
spi_message_add_tail(x, m);
}
}
......@@ -1158,24 +1104,10 @@ static void ads7846_setup_spi_msg(struct ads7846 *ts,
spi_message_init(m);
m->context = ts;
if (ts->model == 7845) {
x++;
packet->pwrdown_cmd[0] = PWRDOWN;
packet->pwrdown_cmd[1] = 0;
packet->pwrdown_cmd[2] = 0;
x->tx_buf = &packet->pwrdown_cmd[0];
x->len = 3;
} else {
x++;
packet->pwrdown = PWRDOWN;
x->tx_buf = &packet->pwrdown;
x->len = 1;
spi_message_add_tail(x, m);
x++;
x->rx_buf = &packet->dummy;
x->len = 2;
}
x++;
packet->pwrdown_cmd.cmd = PWRDOWN;
x->tx_buf = &packet->pwrdown_cmd;
x->len = 3;
CS_CHANGE(*x);
spi_message_add_tail(x, m);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment