]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.19.2/iio-mxs-lradc-separate-touchscreen-and-buffer-virtual-channels.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.19.2 / iio-mxs-lradc-separate-touchscreen-and-buffer-virtual-channels.patch
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
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 From: Kristina Martšenko <kristina.martsenko@gmail.com>
10
11 commit f81197b8a31b8fb287ae57f597b5b6841e1ece92 upstream.
12
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.
18
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.
23
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.
28
29 This makes the touchscreen continue to work during buffered capture. It
30 has been tested on i.MX28, but not on i.MX23.
31
32 [1] 06ddd353f5c8 ("iio: mxs: Implement support for touchscreen")
33 [2] dee05308f602 ("Staging/iio/adc/touchscreen/MXS: add interrupt driven
34 touch detection")
35
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>
40
41 ---
42 drivers/staging/iio/adc/mxs-lradc.c | 166 ++++++++++++++++--------------------
43 1 file changed, 75 insertions(+), 91 deletions(-)
44
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;
49
50 /*
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
54 - * touchscreen.
55 - *
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.
59 + */
60 +#define TOUCHSCREEN_VCHANNEL1 7
61 +#define TOUCHSCREEN_VCHANNEL2 6
62 +
63 + /*
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))
74
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);
79 }
80
81 +static void mxs_lradc_map_channel(struct mxs_lradc *lradc, unsigned vch,
82 + unsigned ch)
83 +{
84 + mxs_lradc_reg_clear(lradc, LRADC_CTRL4_LRADCSELECT_MASK(vch),
85 + LRADC_CTRL4);
86 + mxs_lradc_reg_set(lradc, LRADC_CTRL4_LRADCSELECT(vch, ch), LRADC_CTRL4);
87 +}
88 +
89 static void mxs_lradc_setup_ts_channel(struct mxs_lradc *lradc, unsigned ch)
90 {
91 /*
92 @@ -443,12 +457,8 @@ static void mxs_lradc_setup_ts_channel(s
93 LRADC_DELAY_DELAY(lradc->over_sample_delay - 1),
94 LRADC_DELAY(3));
95
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);
100
101 - /* wake us again, when the complete conversion is done */
102 - mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch), LRADC_CTRL1);
103 /*
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),
108 LRADC_DELAY(3));
109
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);
114
115 - /* wake us again, when the conversions are done */
116 - mxs_lradc_reg_set(lradc, LRADC_CTRL1_LRADC_IRQ_EN(ch2), LRADC_CTRL1);
117 /*
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
121 #define TS_CH_XM 4
122 #define TS_CH_YM 5
123
124 -static int mxs_lradc_read_ts_channel(struct mxs_lradc *lradc)
125 -{
126 - u32 reg;
127 - int val;
128 -
129 - reg = readl(lradc->base + LRADC_CTRL1);
130 -
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);
144 - } else {
145 - return -EIO;
146 - }
147 -
148 - mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(2));
149 - mxs_lradc_reg_wrt(lradc, 0, LRADC_DELAY(3));
150 -
151 - return val;
152 -}
153 -
154 /*
155 * YP(open)--+-------------+
156 * | |--+
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);
159
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);
164 }
165
166 /*
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);
169
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);
174 }
175
176 /*
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);
179
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);
186 }
187
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);
191 }
192
193 +static void mxs_lradc_start_touch_event(struct mxs_lradc *lradc)
194 +{
195 + mxs_lradc_reg_clear(lradc, LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
196 + LRADC_CTRL1);
197 + mxs_lradc_reg_set(lradc,
198 + LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1), LRADC_CTRL1);
199 + /*
200 + * start with the Y-pos, because it uses nearly the same plate
201 + * settings like the touch detection
202 + */
203 + mxs_lradc_prepare_y_pos(lradc);
204 +}
205 +
206 static void mxs_lradc_report_ts_event(struct mxs_lradc *lradc)
207 {
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
212 */
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 */
224 LRADC_DELAY(2));
225 }
226 @@ -753,59 +749,45 @@ static void mxs_lradc_finish_touch_event
227
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);
237 }
238
239 /* touchscreen's state machine */
240 static void mxs_lradc_handle_touch(struct mxs_lradc *lradc)
241 {
242 - int val;
243 -
244 switch (lradc->cur_plate) {
245 case LRADC_TOUCH:
246 - /*
247 - * start with the Y-pos, because it uses nearly the same plate
248 - * settings like the touch detection
249 - */
250 - if (mxs_lradc_check_touch_event(lradc)) {
251 - mxs_lradc_reg_clear(lradc,
252 - LRADC_CTRL1_TOUCH_DETECT_IRQ_EN,
253 - LRADC_CTRL1);
254 - mxs_lradc_prepare_y_pos(lradc);
255 - }
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,
259 LRADC_CTRL1);
260 return;
261
262 case LRADC_SAMPLE_Y:
263 - val = mxs_lradc_read_ts_channel(lradc);
264 - if (val < 0) {
265 - mxs_lradc_enable_touch_detection(lradc); /* re-start */
266 - return;
267 - }
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);
272 return;
273
274 case LRADC_SAMPLE_X:
275 - val = mxs_lradc_read_ts_channel(lradc);
276 - if (val < 0) {
277 - mxs_lradc_enable_touch_detection(lradc); /* re-start */
278 - return;
279 - }
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);
284 return;
285
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);
293 return;
294
295 case LRADC_SAMPLE_VALID:
296 - val = mxs_lradc_read_ts_channel(lradc); /* ignore the value */
297 mxs_lradc_finish_touch_event(lradc, 1);
298 break;
299 }
300 @@ -1083,9 +1065,8 @@ static void mxs_lradc_disable_ts(struct
301 {
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),
306 - LRADC_CTRL1);
307 + LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL1) |
308 + LRADC_CTRL1_LRADC_IRQ_EN(TOUCHSCREEN_VCHANNEL2), LRADC_CTRL1);
309
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);
325
326 if (!(reg & mxs_lradc_irq_mask(lradc)))
327 return IRQ_NONE;
328
329 - if (lradc->use_touchscreen && (reg & ts_irq_mask))
330 + if (lradc->use_touchscreen && (reg & ts_irq_mask)) {
331 mxs_lradc_handle_touch(lradc);
332
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));
336 + }
337 +
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);
342
343 - mxs_lradc_reg_clear(lradc, reg & mxs_lradc_irq_mask(lradc),
344 - LRADC_CTRL1);
345 + mxs_lradc_reg_clear(lradc, reg & clr_irq, LRADC_CTRL1);
346
347 return IRQ_HANDLED;
348 }
349 @@ -1346,7 +1330,7 @@ static bool mxs_lradc_validate_scan_mask
350 if (lradc->use_touchbutton)
351 rsvd_chans++;
352 if (lradc->use_touchscreen)
353 - rsvd_chans++;
354 + rsvd_chans += 2;
355
356 /* Test for attempts to map channels with special mode of operation. */
357 if (bitmap_intersects(mask, &rsvd_mask, LRADC_MAX_TOTAL_CHANS))