1 From f81197b8a31b8fb287ae57f597b5b6841e1ece92 Mon Sep 17 00:00:00 2001
2 From: Kristina Martšenko <kristina.martsenko@gmail.com>
3 Date: Sun, 25 Jan 2015 18:28:19 +0200
4 Subject: iio: mxs-lradc: separate touchscreen and buffer virtual channels
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
9 From: Kristina Martšenko <kristina.martsenko@gmail.com>
11 commit f81197b8a31b8fb287ae57f597b5b6841e1ece92 upstream.
13 The touchscreen was initially designed [1] to map all of its physical
14 channels to one virtual channel, leaving buffered capture to use the
15 remaining 7 virtual channels. When the touchscreen was reimplemented
16 [2], it was made to use four virtual channels, which overlap and
17 conflict with the channels the buffer uses.
19 As a result, when the buffer is enabled, the touchscreen's virtual
20 channels are remapped to whichever physical channels the buffer was
21 configured with, causing the touchscreen to read those instead of the
22 touch measurement channels. Effectively the touchscreen stops working.
24 So here we separate the channels again, giving the touchscreen 2 virtual
25 channels and the buffer 6. We can't give the touchscreen just 1 channel
26 as before, as the current pressure calculation requires 2 channels to be
27 read at the same time.
29 This makes the touchscreen continue to work during buffered capture. It
30 has been tested on i.MX28, but not on i.MX23.
32 [1] 06ddd353f5c8 ("iio: mxs: Implement support for touchscreen")
33 [2] dee05308f602 ("Staging/iio/adc/touchscreen/MXS: add interrupt driven
36 Signed-off-by: Kristina Martšenko <kristina.martsenko@gmail.com>
37 Reviewed-by: Marek Vasut <marex@denx.de>
38 Signed-off-by: Jonathan Cameron <jic23@kernel.org>
39 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
42 drivers/staging/iio/adc/mxs-lradc.c | 166 ++++++++++++++++--------------------
43 1 file changed, 75 insertions(+), 91 deletions(-)
45 --- a/drivers/staging/iio/adc/mxs-lradc.c
46 +++ b/drivers/staging/iio/adc/mxs-lradc.c
47 @@ -214,11 +214,14 @@ struct mxs_lradc {
48 unsigned long is_divided;
51 - * Touchscreen LRADC channels receives a private slot in the CTRL4
52 - * register, the slot #7. Therefore only 7 slots instead of 8 in the
53 - * CTRL4 register can be mapped to LRADC channels when using the
56 + * When the touchscreen is enabled, we give it two private virtual
57 + * channels: #6 and #7. This means that only 6 virtual channels (instead
58 + * of 8) will be available for buffered capture.
60 +#define TOUCHSCREEN_VCHANNEL1 7
61 +#define TOUCHSCREEN_VCHANNEL2 6
64 * Furthermore, certain LRADC channels are shared between touchscreen
65 * and/or touch-buttons and generic LRADC block. Therefore when using
66 * either of these, these channels are not available for the regular
67 @@ -342,6 +345,9 @@ struct mxs_lradc {
68 #define LRADC_CTRL4 0x140
69 #define LRADC_CTRL4_LRADCSELECT_MASK(n) (0xf << ((n) * 4))
70 #define LRADC_CTRL4_LRADCSELECT_OFFSET(n) ((n) * 4)
71 +#define LRADC_CTRL4_LRADCSELECT(n, x) \
72 + (((x) << LRADC_CTRL4_LRADCSELECT_OFFSET(n)) & \
73 + LRADC_CTRL4_LRADCSELECT_MASK(n))
75 #define LRADC_RESOLUTION 12
76 #define LRADC_SINGLE_SAMPLE_MASK ((1 << LRADC_RESOLUTION) - 1)
77 @@ -416,6 +422,14 @@ static bool mxs_lradc_check_touch_event(
78 LRADC_STATUS_TOUCH_DETECT_RAW);
81 +static void mxs_lradc_map_channel(struct mxs_lradc *lradc, unsigned vch,
84 + mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(vch),
86 + mxs_lradc_reg_set(lradc, LRADC_CTRL4_LRADCSELECT(vch, ch), LRADC_CTRL4);
89 static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch)
92 @@ -443,12 +457,8 @@ static void mxs_lradc_setup_ts_channel(s
93 LRADC_DELAY_DELAY(lradc->over_sample_delay - 1),
96 - mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) |
97 - LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) |
98 - LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
99 + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch), LRADC_CTRL1);
101 - /* wake us again, when the complete conversion is done */
102 - mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch), LRADC_CTRL1);
104 * after changing the touchscreen plates setting
105 * the signals need some initial time to settle. Start the
106 @@ -502,12 +512,8 @@ static void mxs_lradc_setup_ts_pressure(
107 LRADC_DELAY_DELAY(lradc->over_sample_delay - 1),
110 - mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(2) |
111 - LRADC_CTRL1_LRADC_IRQ(3) | LRADC_CTRL1_LRADC_IRQ(4) |
112 - LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
113 + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(ch2), LRADC_CTRL1);
115 - /* wake us again, when the conversions are done */
116 - mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch2), LRADC_CTRL1);
118 * after changing the touchscreen plates setting
119 * the signals need some initial time to settle. Start the
120 @@ -573,36 +579,6 @@ static unsigned mxs_lradc_read_ts_pressu
124 -static int mxs_lradc_read_ts_channel(struct mxs_lradc *lradc)
129 - reg = readl(lradc->base + LRADC_CTRL1);
131 - /* only channels 3 to 5 are of interest here */
132 - if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YP)) {
133 - mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YP) |
134 - LRADC_CTRL1_LRADC_IRQ(TS_CH_YP), LRADC_CTRL1);
135 - val = mxs_lradc_read_raw_channel(lradc, TS_CH_YP);
136 - } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_XM)) {
137 - mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_XM) |
138 - LRADC_CTRL1_LRADC_IRQ(TS_CH_XM), LRADC_CTRL1);
139 - val = mxs_lradc_read_raw_channel(lradc, TS_CH_XM);
140 - } else if (reg & LRADC_CTRL1_LRADC_IRQ(TS_CH_YM)) {
141 - mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ_EN(TS_CH_YM) |
142 - LRADC_CTRL1_LRADC_IRQ(TS_CH_YM), LRADC_CTRL1);
143 - val = mxs_lradc_read_raw_channel(lradc, TS_CH_YM);
148 - mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
149 - mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
155 * YP(open)--+-------------+
157 @@ -646,7 +622,8 @@ static void mxs_lradc_prepare_x_pos(stru
158 mxs_lradc_reg_set(lradc, mxs_lradc_drive_x_plate(lradc), LRADC_CTRL0);
160 lradc->cur_plate = LRADC_SAMPLE_X;
161 - mxs_lradc_setup_ts_channel(lradc, TS_CH_YP);
162 + mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YP);
163 + mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1);
167 @@ -667,7 +644,8 @@ static void mxs_lradc_prepare_y_pos(stru
168 mxs_lradc_reg_set(lradc, mxs_lradc_drive_y_plate(lradc), LRADC_CTRL0);
170 lradc->cur_plate = LRADC_SAMPLE_Y;
171 - mxs_lradc_setup_ts_channel(lradc, TS_CH_XM);
172 + mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_XM);
173 + mxs_lradc_setup_ts_channel(lradc, TOUCHSCREEN_VCHANNEL1);
177 @@ -688,7 +666,10 @@ static void mxs_lradc_prepare_pressure(s
178 mxs_lradc_reg_set(lradc, mxs_lradc_drive_pressure(lradc), LRADC_CTRL0);
180 lradc->cur_plate = LRADC_SAMPLE_PRESSURE;
181 - mxs_lradc_setup_ts_pressure(lradc, TS_CH_XP, TS_CH_YM);
182 + mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL1, TS_CH_YM);
183 + mxs_lradc_map_channel(lradc, TOUCHSCREEN_VCHANNEL2, TS_CH_XP);
184 + mxs_lradc_setup_ts_pressure(lradc, TOUCHSCREEN_VCHANNEL2,
185 + TOUCHSCREEN_VCHANNEL1);
188 static void mxs_lradc_enable_touch_detection(struct mxs_lradc *lradc)
189 @@ -701,6 +682,19 @@ static void mxs_lradc_enable_touch_detec
190 mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
193 +static void mxs_lradc_start_touch_event(struct mxs_lradc *lradc)
195 + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
197 + mxs_lradc_reg_set(lradc,
198 + LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1), LRADC_CTRL1);
200 + * start with the Y-pos, because it uses nearly the same plate
201 + * settings like the touch detection
203 + mxs_lradc_prepare_y_pos(lradc);
206 static void mxs_lradc_report_ts_event(struct mxs_lradc *lradc)
208 input_report_abs(lradc->ts_input, ABS_X, lradc->ts_x_pos);
209 @@ -718,10 +712,12 @@ static void mxs_lradc_complete_touch_eve
210 * start a dummy conversion to burn time to settle the signals
211 * note: we are not interested in the conversion's value
213 - mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(5));
214 - mxs_lradc_reg_clear(lradc, LRADC_CTRL1_LRADC_IRQ(5), LRADC_CTRL1);
215 - mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(5), LRADC_CTRL1);
216 - mxs_lradc_reg_wrt(lradc, LRADC_DELAY_TRIGGER(1 << 5) |
217 + mxs_lradc_reg_wrt(lradc, 0, LRADC_CH(TOUCHSCREEN_VCHANNEL1));
218 + mxs_lradc_reg_clear(lradc,
219 + LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) |
220 + LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2), LRADC_CTRL1);
221 + mxs_lradc_reg_wrt(lradc,
222 + LRADC_DELAY_TRIGGER(1 << TOUCHSCREEN_VCHANNEL1) |
223 LRADC_DELAY_KICK | LRADC_DELAY_DELAY(10), /* waste 5 ms */
226 @@ -753,59 +749,45 @@ static void mxs_lradc_finish_touch_event
228 /* if it is released, wait for the next touch via IRQ */
229 lradc->cur_plate = LRADC_TOUCH;
230 - mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ, LRADC_CTRL1);
231 + mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
232 + mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
233 + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ |
234 + LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) |
235 + LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1), LRADC_CTRL1);
236 mxs_lradc_reg_set(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN, LRADC_CTRL1);
239 /* touchscreen's state machine */
240 static void mxs_lradc_handle_touch(struct mxs_lradc *lradc)
244 switch (lradc->cur_plate) {
247 - * start with the Y-pos, because it uses nearly the same plate
248 - * settings like the touch detection
250 - if (mxs_lradc_check_touch_event(lradc)) {
251 - mxs_lradc_reg_clear(lradc,
252 - LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
254 - mxs_lradc_prepare_y_pos(lradc);
256 + if (mxs_lradc_check_touch_event(lradc))
257 + mxs_lradc_start_touch_event(lradc);
258 mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ,
263 - val = mxs_lradc_read_ts_channel(lradc);
265 - mxs_lradc_enable_touch_detection(lradc); /* re-start */
268 - lradc->ts_y_pos = val;
269 + lradc->ts_y_pos = mxs_lradc_read_raw_channel(lradc,
270 + TOUCHSCREEN_VCHANNEL1);
271 mxs_lradc_prepare_x_pos(lradc);
275 - val = mxs_lradc_read_ts_channel(lradc);
277 - mxs_lradc_enable_touch_detection(lradc); /* re-start */
280 - lradc->ts_x_pos = val;
281 + lradc->ts_x_pos = mxs_lradc_read_raw_channel(lradc,
282 + TOUCHSCREEN_VCHANNEL1);
283 mxs_lradc_prepare_pressure(lradc);
286 case LRADC_SAMPLE_PRESSURE:
287 - lradc->ts_pressure =
288 - mxs_lradc_read_ts_pressure(lradc, TS_CH_XP, TS_CH_YM);
289 + lradc->ts_pressure = mxs_lradc_read_ts_pressure(lradc,
290 + TOUCHSCREEN_VCHANNEL2,
291 + TOUCHSCREEN_VCHANNEL1);
292 mxs_lradc_complete_touch_event(lradc);
295 case LRADC_SAMPLE_VALID:
296 - val = mxs_lradc_read_ts_channel(lradc); /* ignore the value */
297 mxs_lradc_finish_touch_event(lradc, 1);
300 @@ -1083,9 +1065,8 @@ static void mxs_lradc_disable_ts(struct
302 /* stop all interrupts from firing */
303 mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN |
304 - LRADC_CTRL1_LRADC_IRQ_EN(2) | LRADC_CTRL1_LRADC_IRQ_EN(3) |
305 - LRADC_CTRL1_LRADC_IRQ_EN(4) | LRADC_CTRL1_LRADC_IRQ_EN(5),
307 + LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) |
308 + LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL2), LRADC_CTRL1);
310 /* Power-down touchscreen touch-detect circuitry. */
311 mxs_lradc_reg_clear(lradc, mxs_lradc_plate_mask(lradc), LRADC_CTRL0);
312 @@ -1151,26 +1132,29 @@ static irqreturn_t mxs_lradc_handle_irq(
313 struct iio_dev *iio = data;
314 struct mxs_lradc *lradc = iio_priv(iio);
315 unsigned long reg = readl(lradc->base + LRADC_CTRL1);
316 + uint32_t clr_irq = mxs_lradc_irq_mask(lradc);
317 const uint32_t ts_irq_mask =
318 LRADC_CTRL1_TOUCH_DETECT_IRQ |
319 - LRADC_CTRL1_LRADC_IRQ(2) |
320 - LRADC_CTRL1_LRADC_IRQ(3) |
321 - LRADC_CTRL1_LRADC_IRQ(4) |
322 - LRADC_CTRL1_LRADC_IRQ(5);
323 + LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) |
324 + LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2);
326 if (!(reg & mxs_lradc_irq_mask(lradc)))
329 - if (lradc->use_touchscreen && (reg & ts_irq_mask))
330 + if (lradc->use_touchscreen && (reg & ts_irq_mask)) {
331 mxs_lradc_handle_touch(lradc);
333 + /* Make sure we don't clear the next conversion's interrupt. */
334 + clr_irq &= ~(LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL1) |
335 + LRADC_CTRL1_LRADC_IRQ(TOUCHSCREEN_VCHANNEL2));
338 if (iio_buffer_enabled(iio))
339 iio_trigger_poll(iio->trig);
340 else if (reg & LRADC_CTRL1_LRADC_IRQ(0))
341 complete(&lradc->completion);
343 - mxs_lradc_reg_clear(lradc, reg & mxs_lradc_irq_mask(lradc),
345 + mxs_lradc_reg_clear(lradc, reg & clr_irq, LRADC_CTRL1);
349 @@ -1346,7 +1330,7 @@ static bool mxs_lradc_validate_scan_mask
350 if (lradc->use_touchbutton)
352 if (lradc->use_touchscreen)
356 /* Test for attempts to map channels with special mode of operation. */
357 if (bitmap_intersects(mask, &rsvd_mask, LRADC_MAX_TOTAL_CHANS))