Commit | Line | Data |
---|---|---|
30dd9e0c JH |
1 | /* |
2 | * ImgTec IR Hardware Decoder found in PowerDown Controller. | |
3 | * | |
4 | * Copyright 2010-2014 Imagination Technologies Ltd. | |
5 | * | |
6 | * This ties into the input subsystem using the RC-core. Protocol support is | |
7 | * provided in separate modules which provide the parameters and scancode | |
8 | * translation functions to set up the hardware decoder and interpret the | |
9 | * resulting input. | |
10 | */ | |
11 | ||
12 | #include <linux/bitops.h> | |
13 | #include <linux/clk.h> | |
14 | #include <linux/interrupt.h> | |
15 | #include <linux/spinlock.h> | |
16 | #include <linux/timer.h> | |
17 | #include <media/rc-core.h> | |
18 | #include "img-ir.h" | |
19 | ||
20 | /* Decoders lock (only modified to preprocess them) */ | |
21 | static DEFINE_SPINLOCK(img_ir_decoders_lock); | |
22 | ||
23 | static bool img_ir_decoders_preprocessed; | |
24 | static struct img_ir_decoder *img_ir_decoders[] = { | |
25 | NULL | |
26 | }; | |
27 | ||
28 | #define IMG_IR_F_FILTER BIT(RC_FILTER_NORMAL) /* enable filtering */ | |
29 | #define IMG_IR_F_WAKE BIT(RC_FILTER_WAKEUP) /* enable waking */ | |
30 | ||
31 | /* code type quirks */ | |
32 | ||
33 | #define IMG_IR_QUIRK_CODE_BROKEN 0x1 /* Decode is broken */ | |
34 | #define IMG_IR_QUIRK_CODE_LEN_INCR 0x2 /* Bit length needs increment */ | |
35 | ||
36 | /* functions for preprocessing timings, ensuring max is set */ | |
37 | ||
38 | static void img_ir_timing_preprocess(struct img_ir_timing_range *range, | |
39 | unsigned int unit) | |
40 | { | |
41 | if (range->max < range->min) | |
42 | range->max = range->min; | |
43 | if (unit) { | |
44 | /* multiply by unit and convert to microseconds */ | |
45 | range->min = (range->min*unit)/1000; | |
46 | range->max = (range->max*unit + 999)/1000; /* round up */ | |
47 | } | |
48 | } | |
49 | ||
50 | static void img_ir_symbol_timing_preprocess(struct img_ir_symbol_timing *timing, | |
51 | unsigned int unit) | |
52 | { | |
53 | img_ir_timing_preprocess(&timing->pulse, unit); | |
54 | img_ir_timing_preprocess(&timing->space, unit); | |
55 | } | |
56 | ||
57 | static void img_ir_timings_preprocess(struct img_ir_timings *timings, | |
58 | unsigned int unit) | |
59 | { | |
60 | img_ir_symbol_timing_preprocess(&timings->ldr, unit); | |
61 | img_ir_symbol_timing_preprocess(&timings->s00, unit); | |
62 | img_ir_symbol_timing_preprocess(&timings->s01, unit); | |
63 | img_ir_symbol_timing_preprocess(&timings->s10, unit); | |
64 | img_ir_symbol_timing_preprocess(&timings->s11, unit); | |
65 | /* default s10 and s11 to s00 and s01 if no leader */ | |
66 | if (unit) | |
67 | /* multiply by unit and convert to microseconds (round up) */ | |
68 | timings->ft.ft_min = (timings->ft.ft_min*unit + 999)/1000; | |
69 | } | |
70 | ||
71 | /* functions for filling empty fields with defaults */ | |
72 | ||
73 | static void img_ir_timing_defaults(struct img_ir_timing_range *range, | |
74 | struct img_ir_timing_range *defaults) | |
75 | { | |
76 | if (!range->min) | |
77 | range->min = defaults->min; | |
78 | if (!range->max) | |
79 | range->max = defaults->max; | |
80 | } | |
81 | ||
82 | static void img_ir_symbol_timing_defaults(struct img_ir_symbol_timing *timing, | |
83 | struct img_ir_symbol_timing *defaults) | |
84 | { | |
85 | img_ir_timing_defaults(&timing->pulse, &defaults->pulse); | |
86 | img_ir_timing_defaults(&timing->space, &defaults->space); | |
87 | } | |
88 | ||
89 | static void img_ir_timings_defaults(struct img_ir_timings *timings, | |
90 | struct img_ir_timings *defaults) | |
91 | { | |
92 | img_ir_symbol_timing_defaults(&timings->ldr, &defaults->ldr); | |
93 | img_ir_symbol_timing_defaults(&timings->s00, &defaults->s00); | |
94 | img_ir_symbol_timing_defaults(&timings->s01, &defaults->s01); | |
95 | img_ir_symbol_timing_defaults(&timings->s10, &defaults->s10); | |
96 | img_ir_symbol_timing_defaults(&timings->s11, &defaults->s11); | |
97 | if (!timings->ft.ft_min) | |
98 | timings->ft.ft_min = defaults->ft.ft_min; | |
99 | } | |
100 | ||
101 | /* functions for converting timings to register values */ | |
102 | ||
103 | /** | |
104 | * img_ir_control() - Convert control struct to control register value. | |
105 | * @control: Control data | |
106 | * | |
107 | * Returns: The control register value equivalent of @control. | |
108 | */ | |
109 | static u32 img_ir_control(const struct img_ir_control *control) | |
110 | { | |
111 | u32 ctrl = control->code_type << IMG_IR_CODETYPE_SHIFT; | |
112 | if (control->decoden) | |
113 | ctrl |= IMG_IR_DECODEN; | |
114 | if (control->hdrtog) | |
115 | ctrl |= IMG_IR_HDRTOG; | |
116 | if (control->ldrdec) | |
117 | ctrl |= IMG_IR_LDRDEC; | |
118 | if (control->decodinpol) | |
119 | ctrl |= IMG_IR_DECODINPOL; | |
120 | if (control->bitorien) | |
121 | ctrl |= IMG_IR_BITORIEN; | |
122 | if (control->d1validsel) | |
123 | ctrl |= IMG_IR_D1VALIDSEL; | |
124 | if (control->bitinv) | |
125 | ctrl |= IMG_IR_BITINV; | |
126 | if (control->decodend2) | |
127 | ctrl |= IMG_IR_DECODEND2; | |
128 | if (control->bitoriend2) | |
129 | ctrl |= IMG_IR_BITORIEND2; | |
130 | if (control->bitinvd2) | |
131 | ctrl |= IMG_IR_BITINVD2; | |
132 | return ctrl; | |
133 | } | |
134 | ||
135 | /** | |
136 | * img_ir_timing_range_convert() - Convert microsecond range. | |
137 | * @out: Output timing range in clock cycles with a shift. | |
138 | * @in: Input timing range in microseconds. | |
139 | * @tolerance: Tolerance as a fraction of 128 (roughly percent). | |
140 | * @clock_hz: IR clock rate in Hz. | |
141 | * @shift: Shift of output units. | |
142 | * | |
143 | * Converts min and max from microseconds to IR clock cycles, applies a | |
144 | * tolerance, and shifts for the register, rounding in the right direction. | |
145 | * Note that in and out can safely be the same object. | |
146 | */ | |
147 | static void img_ir_timing_range_convert(struct img_ir_timing_range *out, | |
148 | const struct img_ir_timing_range *in, | |
149 | unsigned int tolerance, | |
150 | unsigned long clock_hz, | |
151 | unsigned int shift) | |
152 | { | |
153 | unsigned int min = in->min; | |
154 | unsigned int max = in->max; | |
155 | /* add a tolerance */ | |
156 | min = min - (min*tolerance >> 7); | |
157 | max = max + (max*tolerance >> 7); | |
158 | /* convert from microseconds into clock cycles */ | |
159 | min = min*clock_hz / 1000000; | |
160 | max = (max*clock_hz + 999999) / 1000000; /* round up */ | |
161 | /* apply shift and copy to output */ | |
162 | out->min = min >> shift; | |
163 | out->max = (max + ((1 << shift) - 1)) >> shift; /* round up */ | |
164 | } | |
165 | ||
166 | /** | |
167 | * img_ir_symbol_timing() - Convert symbol timing struct to register value. | |
168 | * @timing: Symbol timing data | |
169 | * @tolerance: Timing tolerance where 0-128 represents 0-100% | |
170 | * @clock_hz: Frequency of source clock in Hz | |
171 | * @pd_shift: Shift to apply to symbol period | |
172 | * @w_shift: Shift to apply to symbol width | |
173 | * | |
174 | * Returns: Symbol timing register value based on arguments. | |
175 | */ | |
176 | static u32 img_ir_symbol_timing(const struct img_ir_symbol_timing *timing, | |
177 | unsigned int tolerance, | |
178 | unsigned long clock_hz, | |
179 | unsigned int pd_shift, | |
180 | unsigned int w_shift) | |
181 | { | |
182 | struct img_ir_timing_range hw_pulse, hw_period; | |
183 | /* we calculate period in hw_period, then convert in place */ | |
184 | hw_period.min = timing->pulse.min + timing->space.min; | |
185 | hw_period.max = timing->pulse.max + timing->space.max; | |
186 | img_ir_timing_range_convert(&hw_period, &hw_period, | |
187 | tolerance, clock_hz, pd_shift); | |
188 | img_ir_timing_range_convert(&hw_pulse, &timing->pulse, | |
189 | tolerance, clock_hz, w_shift); | |
190 | /* construct register value */ | |
191 | return (hw_period.max << IMG_IR_PD_MAX_SHIFT) | | |
192 | (hw_period.min << IMG_IR_PD_MIN_SHIFT) | | |
193 | (hw_pulse.max << IMG_IR_W_MAX_SHIFT) | | |
194 | (hw_pulse.min << IMG_IR_W_MIN_SHIFT); | |
195 | } | |
196 | ||
197 | /** | |
198 | * img_ir_free_timing() - Convert free time timing struct to register value. | |
199 | * @timing: Free symbol timing data | |
200 | * @clock_hz: Source clock frequency in Hz | |
201 | * | |
202 | * Returns: Free symbol timing register value. | |
203 | */ | |
204 | static u32 img_ir_free_timing(const struct img_ir_free_timing *timing, | |
205 | unsigned long clock_hz) | |
206 | { | |
207 | unsigned int minlen, maxlen, ft_min; | |
208 | /* minlen is only 5 bits, and round minlen to multiple of 2 */ | |
209 | if (timing->minlen < 30) | |
210 | minlen = timing->minlen & -2; | |
211 | else | |
212 | minlen = 30; | |
213 | /* maxlen has maximum value of 48, and round maxlen to multiple of 2 */ | |
214 | if (timing->maxlen < 48) | |
215 | maxlen = (timing->maxlen + 1) & -2; | |
216 | else | |
217 | maxlen = 48; | |
218 | /* convert and shift ft_min, rounding upwards */ | |
219 | ft_min = (timing->ft_min*clock_hz + 999999) / 1000000; | |
220 | ft_min = (ft_min + 7) >> 3; | |
221 | /* construct register value */ | |
222 | return (timing->maxlen << IMG_IR_MAXLEN_SHIFT) | | |
223 | (timing->minlen << IMG_IR_MINLEN_SHIFT) | | |
224 | (ft_min << IMG_IR_FT_MIN_SHIFT); | |
225 | } | |
226 | ||
227 | /** | |
228 | * img_ir_free_timing_dynamic() - Update free time register value. | |
229 | * @st_ft: Static free time register value from img_ir_free_timing. | |
230 | * @filter: Current filter which may additionally restrict min/max len. | |
231 | * | |
232 | * Returns: Updated free time register value based on the current filter. | |
233 | */ | |
234 | static u32 img_ir_free_timing_dynamic(u32 st_ft, struct img_ir_filter *filter) | |
235 | { | |
236 | unsigned int minlen, maxlen, newminlen, newmaxlen; | |
237 | ||
238 | /* round minlen, maxlen to multiple of 2 */ | |
239 | newminlen = filter->minlen & -2; | |
240 | newmaxlen = (filter->maxlen + 1) & -2; | |
241 | /* extract min/max len from register */ | |
242 | minlen = (st_ft & IMG_IR_MINLEN) >> IMG_IR_MINLEN_SHIFT; | |
243 | maxlen = (st_ft & IMG_IR_MAXLEN) >> IMG_IR_MAXLEN_SHIFT; | |
244 | /* if the new values are more restrictive, update the register value */ | |
245 | if (newminlen > minlen) { | |
246 | st_ft &= ~IMG_IR_MINLEN; | |
247 | st_ft |= newminlen << IMG_IR_MINLEN_SHIFT; | |
248 | } | |
249 | if (newmaxlen < maxlen) { | |
250 | st_ft &= ~IMG_IR_MAXLEN; | |
251 | st_ft |= newmaxlen << IMG_IR_MAXLEN_SHIFT; | |
252 | } | |
253 | return st_ft; | |
254 | } | |
255 | ||
256 | /** | |
257 | * img_ir_timings_convert() - Convert timings to register values | |
258 | * @regs: Output timing register values | |
259 | * @timings: Input timing data | |
260 | * @tolerance: Timing tolerance where 0-128 represents 0-100% | |
261 | * @clock_hz: Source clock frequency in Hz | |
262 | */ | |
263 | static void img_ir_timings_convert(struct img_ir_timing_regvals *regs, | |
264 | const struct img_ir_timings *timings, | |
265 | unsigned int tolerance, | |
266 | unsigned int clock_hz) | |
267 | { | |
268 | /* leader symbol timings are divided by 16 */ | |
269 | regs->ldr = img_ir_symbol_timing(&timings->ldr, tolerance, clock_hz, | |
270 | 4, 4); | |
271 | /* other symbol timings, pd fields only are divided by 2 */ | |
272 | regs->s00 = img_ir_symbol_timing(&timings->s00, tolerance, clock_hz, | |
273 | 1, 0); | |
274 | regs->s01 = img_ir_symbol_timing(&timings->s01, tolerance, clock_hz, | |
275 | 1, 0); | |
276 | regs->s10 = img_ir_symbol_timing(&timings->s10, tolerance, clock_hz, | |
277 | 1, 0); | |
278 | regs->s11 = img_ir_symbol_timing(&timings->s11, tolerance, clock_hz, | |
279 | 1, 0); | |
280 | regs->ft = img_ir_free_timing(&timings->ft, clock_hz); | |
281 | } | |
282 | ||
283 | /** | |
284 | * img_ir_decoder_preprocess() - Preprocess timings in decoder. | |
285 | * @decoder: Decoder to be preprocessed. | |
286 | * | |
287 | * Ensures that the symbol timing ranges are valid with respect to ordering, and | |
288 | * does some fixed conversion on them. | |
289 | */ | |
290 | static void img_ir_decoder_preprocess(struct img_ir_decoder *decoder) | |
291 | { | |
292 | /* default tolerance */ | |
293 | if (!decoder->tolerance) | |
294 | decoder->tolerance = 10; /* percent */ | |
295 | /* and convert tolerance to fraction out of 128 */ | |
296 | decoder->tolerance = decoder->tolerance * 128 / 100; | |
297 | ||
298 | /* fill in implicit fields */ | |
299 | img_ir_timings_preprocess(&decoder->timings, decoder->unit); | |
300 | ||
301 | /* do the same for repeat timings if applicable */ | |
302 | if (decoder->repeat) { | |
303 | img_ir_timings_preprocess(&decoder->rtimings, decoder->unit); | |
304 | img_ir_timings_defaults(&decoder->rtimings, &decoder->timings); | |
305 | } | |
306 | } | |
307 | ||
308 | /** | |
309 | * img_ir_decoder_convert() - Generate internal timings in decoder. | |
310 | * @decoder: Decoder to be converted to internal timings. | |
311 | * @timings: Timing register values. | |
312 | * @clock_hz: IR clock rate in Hz. | |
313 | * | |
314 | * Fills out the repeat timings and timing register values for a specific clock | |
315 | * rate. | |
316 | */ | |
317 | static void img_ir_decoder_convert(const struct img_ir_decoder *decoder, | |
318 | struct img_ir_reg_timings *reg_timings, | |
319 | unsigned int clock_hz) | |
320 | { | |
321 | /* calculate control value */ | |
322 | reg_timings->ctrl = img_ir_control(&decoder->control); | |
323 | ||
324 | /* fill in implicit fields and calculate register values */ | |
325 | img_ir_timings_convert(®_timings->timings, &decoder->timings, | |
326 | decoder->tolerance, clock_hz); | |
327 | ||
328 | /* do the same for repeat timings if applicable */ | |
329 | if (decoder->repeat) | |
330 | img_ir_timings_convert(®_timings->rtimings, | |
331 | &decoder->rtimings, decoder->tolerance, | |
332 | clock_hz); | |
333 | } | |
334 | ||
335 | /** | |
336 | * img_ir_write_timings() - Write timings to the hardware now | |
337 | * @priv: IR private data | |
338 | * @regs: Timing register values to write | |
339 | * @type: RC filter type (RC_FILTER_*) | |
340 | * | |
341 | * Write timing register values @regs to the hardware, taking into account the | |
342 | * current filter which may impose restrictions on the length of the expected | |
343 | * data. | |
344 | */ | |
345 | static void img_ir_write_timings(struct img_ir_priv *priv, | |
346 | struct img_ir_timing_regvals *regs, | |
347 | enum rc_filter_type type) | |
348 | { | |
349 | struct img_ir_priv_hw *hw = &priv->hw; | |
350 | ||
351 | /* filter may be more restrictive to minlen, maxlen */ | |
352 | u32 ft = regs->ft; | |
353 | if (hw->flags & BIT(type)) | |
354 | ft = img_ir_free_timing_dynamic(regs->ft, &hw->filters[type]); | |
355 | /* write to registers */ | |
356 | img_ir_write(priv, IMG_IR_LEAD_SYMB_TIMING, regs->ldr); | |
357 | img_ir_write(priv, IMG_IR_S00_SYMB_TIMING, regs->s00); | |
358 | img_ir_write(priv, IMG_IR_S01_SYMB_TIMING, regs->s01); | |
359 | img_ir_write(priv, IMG_IR_S10_SYMB_TIMING, regs->s10); | |
360 | img_ir_write(priv, IMG_IR_S11_SYMB_TIMING, regs->s11); | |
361 | img_ir_write(priv, IMG_IR_FREE_SYMB_TIMING, ft); | |
362 | dev_dbg(priv->dev, "timings: ldr=%#x, s=[%#x, %#x, %#x, %#x], ft=%#x\n", | |
363 | regs->ldr, regs->s00, regs->s01, regs->s10, regs->s11, ft); | |
364 | } | |
365 | ||
366 | static void img_ir_write_filter(struct img_ir_priv *priv, | |
367 | struct img_ir_filter *filter) | |
368 | { | |
369 | if (filter) { | |
370 | dev_dbg(priv->dev, "IR filter=%016llx & %016llx\n", | |
371 | (unsigned long long)filter->data, | |
372 | (unsigned long long)filter->mask); | |
373 | img_ir_write(priv, IMG_IR_IRQ_MSG_DATA_LW, (u32)filter->data); | |
374 | img_ir_write(priv, IMG_IR_IRQ_MSG_DATA_UP, (u32)(filter->data | |
375 | >> 32)); | |
376 | img_ir_write(priv, IMG_IR_IRQ_MSG_MASK_LW, (u32)filter->mask); | |
377 | img_ir_write(priv, IMG_IR_IRQ_MSG_MASK_UP, (u32)(filter->mask | |
378 | >> 32)); | |
379 | } else { | |
380 | dev_dbg(priv->dev, "IR clearing filter\n"); | |
381 | img_ir_write(priv, IMG_IR_IRQ_MSG_MASK_LW, 0); | |
382 | img_ir_write(priv, IMG_IR_IRQ_MSG_MASK_UP, 0); | |
383 | } | |
384 | } | |
385 | ||
386 | /* caller must have lock */ | |
387 | static void _img_ir_set_filter(struct img_ir_priv *priv, | |
388 | struct img_ir_filter *filter) | |
389 | { | |
390 | struct img_ir_priv_hw *hw = &priv->hw; | |
391 | u32 irq_en, irq_on; | |
392 | ||
393 | irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE); | |
394 | if (filter) { | |
395 | /* Only use the match interrupt */ | |
396 | hw->filters[RC_FILTER_NORMAL] = *filter; | |
397 | hw->flags |= IMG_IR_F_FILTER; | |
398 | irq_on = IMG_IR_IRQ_DATA_MATCH; | |
399 | irq_en &= ~(IMG_IR_IRQ_DATA_VALID | IMG_IR_IRQ_DATA2_VALID); | |
400 | } else { | |
401 | /* Only use the valid interrupt */ | |
402 | hw->flags &= ~IMG_IR_F_FILTER; | |
403 | irq_en &= ~IMG_IR_IRQ_DATA_MATCH; | |
404 | irq_on = IMG_IR_IRQ_DATA_VALID | IMG_IR_IRQ_DATA2_VALID; | |
405 | } | |
406 | irq_en |= irq_on; | |
407 | ||
408 | img_ir_write_filter(priv, filter); | |
409 | /* clear any interrupts we're enabling so we don't handle old ones */ | |
410 | img_ir_write(priv, IMG_IR_IRQ_CLEAR, irq_on); | |
411 | img_ir_write(priv, IMG_IR_IRQ_ENABLE, irq_en); | |
412 | } | |
413 | ||
414 | /* caller must have lock */ | |
415 | static void _img_ir_set_wake_filter(struct img_ir_priv *priv, | |
416 | struct img_ir_filter *filter) | |
417 | { | |
418 | struct img_ir_priv_hw *hw = &priv->hw; | |
419 | if (filter) { | |
420 | /* Enable wake, and copy filter for later */ | |
421 | hw->filters[RC_FILTER_WAKEUP] = *filter; | |
422 | hw->flags |= IMG_IR_F_WAKE; | |
423 | } else { | |
424 | /* Disable wake */ | |
425 | hw->flags &= ~IMG_IR_F_WAKE; | |
426 | } | |
427 | } | |
428 | ||
429 | /* Callback for setting scancode filter */ | |
430 | static int img_ir_set_filter(struct rc_dev *dev, enum rc_filter_type type, | |
431 | struct rc_scancode_filter *sc_filter) | |
432 | { | |
433 | struct img_ir_priv *priv = dev->priv; | |
434 | struct img_ir_priv_hw *hw = &priv->hw; | |
435 | struct img_ir_filter filter, *filter_ptr = &filter; | |
436 | int ret = 0; | |
437 | ||
438 | dev_dbg(priv->dev, "IR scancode %sfilter=%08x & %08x\n", | |
439 | type == RC_FILTER_WAKEUP ? "wake " : "", | |
440 | sc_filter->data, | |
441 | sc_filter->mask); | |
442 | ||
443 | spin_lock_irq(&priv->lock); | |
444 | ||
445 | /* filtering can always be disabled */ | |
446 | if (!sc_filter->mask) { | |
447 | filter_ptr = NULL; | |
448 | goto set_unlock; | |
449 | } | |
450 | ||
451 | /* current decoder must support scancode filtering */ | |
452 | if (!hw->decoder || !hw->decoder->filter) { | |
453 | ret = -EINVAL; | |
454 | goto unlock; | |
455 | } | |
456 | ||
457 | /* convert scancode filter to raw filter */ | |
458 | filter.minlen = 0; | |
459 | filter.maxlen = ~0; | |
460 | ret = hw->decoder->filter(sc_filter, &filter, hw->enabled_protocols); | |
461 | if (ret) | |
462 | goto unlock; | |
463 | dev_dbg(priv->dev, "IR raw %sfilter=%016llx & %016llx\n", | |
464 | type == RC_FILTER_WAKEUP ? "wake " : "", | |
465 | (unsigned long long)filter.data, | |
466 | (unsigned long long)filter.mask); | |
467 | ||
468 | set_unlock: | |
469 | /* apply raw filters */ | |
470 | switch (type) { | |
471 | case RC_FILTER_NORMAL: | |
472 | _img_ir_set_filter(priv, filter_ptr); | |
473 | break; | |
474 | case RC_FILTER_WAKEUP: | |
475 | _img_ir_set_wake_filter(priv, filter_ptr); | |
476 | break; | |
477 | default: | |
478 | ret = -EINVAL; | |
479 | }; | |
480 | ||
481 | unlock: | |
482 | spin_unlock_irq(&priv->lock); | |
483 | return ret; | |
484 | } | |
485 | ||
486 | /** | |
487 | * img_ir_set_decoder() - Set the current decoder. | |
488 | * @priv: IR private data. | |
489 | * @decoder: Decoder to use with immediate effect. | |
490 | * @proto: Protocol bitmap (or 0 to use decoder->type). | |
491 | */ | |
492 | static void img_ir_set_decoder(struct img_ir_priv *priv, | |
493 | const struct img_ir_decoder *decoder, | |
494 | u64 proto) | |
495 | { | |
496 | struct img_ir_priv_hw *hw = &priv->hw; | |
497 | struct rc_dev *rdev = hw->rdev; | |
498 | u32 ir_status, irq_en; | |
499 | spin_lock_irq(&priv->lock); | |
500 | ||
501 | /* switch off and disable interrupts */ | |
502 | img_ir_write(priv, IMG_IR_CONTROL, 0); | |
503 | irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE); | |
504 | img_ir_write(priv, IMG_IR_IRQ_ENABLE, irq_en & IMG_IR_IRQ_EDGE); | |
505 | img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_ALL & ~IMG_IR_IRQ_EDGE); | |
506 | ||
507 | /* ack any data already detected */ | |
508 | ir_status = img_ir_read(priv, IMG_IR_STATUS); | |
509 | if (ir_status & (IMG_IR_RXDVAL | IMG_IR_RXDVALD2)) { | |
510 | ir_status &= ~(IMG_IR_RXDVAL | IMG_IR_RXDVALD2); | |
511 | img_ir_write(priv, IMG_IR_STATUS, ir_status); | |
512 | img_ir_read(priv, IMG_IR_DATA_LW); | |
513 | img_ir_read(priv, IMG_IR_DATA_UP); | |
514 | } | |
515 | ||
516 | /* stop the end timer and switch back to normal mode */ | |
517 | del_timer_sync(&hw->end_timer); | |
518 | hw->mode = IMG_IR_M_NORMAL; | |
519 | ||
520 | /* clear the wakeup scancode filter */ | |
521 | rdev->scancode_filters[RC_FILTER_WAKEUP].data = 0; | |
522 | rdev->scancode_filters[RC_FILTER_WAKEUP].mask = 0; | |
523 | ||
524 | /* clear raw filters */ | |
525 | _img_ir_set_filter(priv, NULL); | |
526 | _img_ir_set_wake_filter(priv, NULL); | |
527 | ||
528 | /* clear the enabled protocols */ | |
529 | hw->enabled_protocols = 0; | |
530 | ||
531 | /* switch decoder */ | |
532 | hw->decoder = decoder; | |
533 | if (!decoder) | |
534 | goto unlock; | |
535 | ||
536 | /* set the enabled protocols */ | |
537 | if (!proto) | |
538 | proto = decoder->type; | |
539 | hw->enabled_protocols = proto; | |
540 | ||
541 | /* write the new timings */ | |
542 | img_ir_decoder_convert(decoder, &hw->reg_timings, hw->clk_hz); | |
543 | img_ir_write_timings(priv, &hw->reg_timings.timings, RC_FILTER_NORMAL); | |
544 | ||
545 | /* set up and enable */ | |
546 | img_ir_write(priv, IMG_IR_CONTROL, hw->reg_timings.ctrl); | |
547 | ||
548 | ||
549 | unlock: | |
550 | spin_unlock_irq(&priv->lock); | |
551 | } | |
552 | ||
553 | /** | |
554 | * img_ir_decoder_compatable() - Find whether a decoder will work with a device. | |
555 | * @priv: IR private data. | |
556 | * @dec: Decoder to check. | |
557 | * | |
558 | * Returns: true if @dec is compatible with the device @priv refers to. | |
559 | */ | |
560 | static bool img_ir_decoder_compatible(struct img_ir_priv *priv, | |
561 | const struct img_ir_decoder *dec) | |
562 | { | |
563 | unsigned int ct; | |
564 | ||
565 | /* don't accept decoders using code types which aren't supported */ | |
566 | ct = dec->control.code_type; | |
567 | if (priv->hw.ct_quirks[ct] & IMG_IR_QUIRK_CODE_BROKEN) | |
568 | return false; | |
569 | ||
570 | return true; | |
571 | } | |
572 | ||
573 | /** | |
574 | * img_ir_allowed_protos() - Get allowed protocols from global decoder list. | |
575 | * @priv: IR private data. | |
576 | * | |
577 | * Returns: Mask of protocols supported by the device @priv refers to. | |
578 | */ | |
579 | static u64 img_ir_allowed_protos(struct img_ir_priv *priv) | |
580 | { | |
581 | u64 protos = 0; | |
582 | struct img_ir_decoder **decp; | |
583 | ||
584 | for (decp = img_ir_decoders; *decp; ++decp) { | |
585 | const struct img_ir_decoder *dec = *decp; | |
586 | if (img_ir_decoder_compatible(priv, dec)) | |
587 | protos |= dec->type; | |
588 | } | |
589 | return protos; | |
590 | } | |
591 | ||
592 | /* Callback for changing protocol using sysfs */ | |
593 | static int img_ir_change_protocol(struct rc_dev *dev, u64 *ir_type) | |
594 | { | |
595 | struct img_ir_priv *priv = dev->priv; | |
596 | struct img_ir_priv_hw *hw = &priv->hw; | |
597 | struct rc_dev *rdev = hw->rdev; | |
598 | struct img_ir_decoder **decp; | |
599 | u64 wakeup_protocols; | |
600 | ||
601 | if (!*ir_type) { | |
602 | /* disable all protocols */ | |
603 | img_ir_set_decoder(priv, NULL, 0); | |
604 | goto success; | |
605 | } | |
606 | for (decp = img_ir_decoders; *decp; ++decp) { | |
607 | const struct img_ir_decoder *dec = *decp; | |
608 | if (!img_ir_decoder_compatible(priv, dec)) | |
609 | continue; | |
610 | if (*ir_type & dec->type) { | |
611 | *ir_type &= dec->type; | |
612 | img_ir_set_decoder(priv, dec, *ir_type); | |
613 | goto success; | |
614 | } | |
615 | } | |
616 | return -EINVAL; | |
617 | ||
618 | success: | |
619 | /* | |
620 | * Only allow matching wakeup protocols for now, and only if filtering | |
621 | * is supported. | |
622 | */ | |
623 | wakeup_protocols = *ir_type; | |
624 | if (!hw->decoder || !hw->decoder->filter) | |
625 | wakeup_protocols = 0; | |
626 | rc_set_allowed_wakeup_protocols(rdev, wakeup_protocols); | |
627 | rc_set_enabled_wakeup_protocols(rdev, wakeup_protocols); | |
628 | return 0; | |
629 | } | |
630 | ||
631 | /* Changes ir-core protocol device attribute */ | |
632 | static void img_ir_set_protocol(struct img_ir_priv *priv, u64 proto) | |
633 | { | |
634 | struct rc_dev *rdev = priv->hw.rdev; | |
635 | ||
636 | spin_lock_irq(&rdev->rc_map.lock); | |
637 | rdev->rc_map.rc_type = __ffs64(proto); | |
638 | spin_unlock_irq(&rdev->rc_map.lock); | |
639 | ||
640 | mutex_lock(&rdev->lock); | |
641 | rc_set_enabled_protocols(rdev, proto); | |
642 | rc_set_allowed_wakeup_protocols(rdev, proto); | |
643 | rc_set_enabled_wakeup_protocols(rdev, proto); | |
644 | mutex_unlock(&rdev->lock); | |
645 | } | |
646 | ||
647 | /* Set up IR decoders */ | |
648 | static void img_ir_init_decoders(void) | |
649 | { | |
650 | struct img_ir_decoder **decp; | |
651 | ||
652 | spin_lock(&img_ir_decoders_lock); | |
653 | if (!img_ir_decoders_preprocessed) { | |
654 | for (decp = img_ir_decoders; *decp; ++decp) | |
655 | img_ir_decoder_preprocess(*decp); | |
656 | img_ir_decoders_preprocessed = true; | |
657 | } | |
658 | spin_unlock(&img_ir_decoders_lock); | |
659 | } | |
660 | ||
661 | #ifdef CONFIG_PM_SLEEP | |
662 | /** | |
663 | * img_ir_enable_wake() - Switch to wake mode. | |
664 | * @priv: IR private data. | |
665 | * | |
666 | * Returns: non-zero if the IR can wake the system. | |
667 | */ | |
668 | static int img_ir_enable_wake(struct img_ir_priv *priv) | |
669 | { | |
670 | struct img_ir_priv_hw *hw = &priv->hw; | |
671 | int ret = 0; | |
672 | ||
673 | spin_lock_irq(&priv->lock); | |
674 | if (hw->flags & IMG_IR_F_WAKE) { | |
675 | /* interrupt only on a match */ | |
676 | hw->suspend_irqen = img_ir_read(priv, IMG_IR_IRQ_ENABLE); | |
677 | img_ir_write(priv, IMG_IR_IRQ_ENABLE, IMG_IR_IRQ_DATA_MATCH); | |
678 | img_ir_write_filter(priv, &hw->filters[RC_FILTER_WAKEUP]); | |
679 | img_ir_write_timings(priv, &hw->reg_timings.timings, | |
680 | RC_FILTER_WAKEUP); | |
681 | hw->mode = IMG_IR_M_WAKE; | |
682 | ret = 1; | |
683 | } | |
684 | spin_unlock_irq(&priv->lock); | |
685 | return ret; | |
686 | } | |
687 | ||
688 | /** | |
689 | * img_ir_disable_wake() - Switch out of wake mode. | |
690 | * @priv: IR private data | |
691 | * | |
692 | * Returns: 1 if the hardware should be allowed to wake from a sleep state. | |
693 | * 0 otherwise. | |
694 | */ | |
695 | static int img_ir_disable_wake(struct img_ir_priv *priv) | |
696 | { | |
697 | struct img_ir_priv_hw *hw = &priv->hw; | |
698 | int ret = 0; | |
699 | ||
700 | spin_lock_irq(&priv->lock); | |
701 | if (hw->flags & IMG_IR_F_WAKE) { | |
702 | /* restore normal filtering */ | |
703 | if (hw->flags & IMG_IR_F_FILTER) { | |
704 | img_ir_write(priv, IMG_IR_IRQ_ENABLE, | |
705 | (hw->suspend_irqen & IMG_IR_IRQ_EDGE) | | |
706 | IMG_IR_IRQ_DATA_MATCH); | |
707 | img_ir_write_filter(priv, | |
708 | &hw->filters[RC_FILTER_NORMAL]); | |
709 | } else { | |
710 | img_ir_write(priv, IMG_IR_IRQ_ENABLE, | |
711 | (hw->suspend_irqen & IMG_IR_IRQ_EDGE) | | |
712 | IMG_IR_IRQ_DATA_VALID | | |
713 | IMG_IR_IRQ_DATA2_VALID); | |
714 | img_ir_write_filter(priv, NULL); | |
715 | } | |
716 | img_ir_write_timings(priv, &hw->reg_timings.timings, | |
717 | RC_FILTER_NORMAL); | |
718 | hw->mode = IMG_IR_M_NORMAL; | |
719 | ret = 1; | |
720 | } | |
721 | spin_unlock_irq(&priv->lock); | |
722 | return ret; | |
723 | } | |
724 | #endif /* CONFIG_PM_SLEEP */ | |
725 | ||
726 | /* lock must be held */ | |
727 | static void img_ir_begin_repeat(struct img_ir_priv *priv) | |
728 | { | |
729 | struct img_ir_priv_hw *hw = &priv->hw; | |
730 | if (hw->mode == IMG_IR_M_NORMAL) { | |
731 | /* switch to repeat timings */ | |
732 | img_ir_write(priv, IMG_IR_CONTROL, 0); | |
733 | hw->mode = IMG_IR_M_REPEATING; | |
734 | img_ir_write_timings(priv, &hw->reg_timings.rtimings, | |
735 | RC_FILTER_NORMAL); | |
736 | img_ir_write(priv, IMG_IR_CONTROL, hw->reg_timings.ctrl); | |
737 | } | |
738 | } | |
739 | ||
740 | /* lock must be held */ | |
741 | static void img_ir_end_repeat(struct img_ir_priv *priv) | |
742 | { | |
743 | struct img_ir_priv_hw *hw = &priv->hw; | |
744 | if (hw->mode == IMG_IR_M_REPEATING) { | |
745 | /* switch to normal timings */ | |
746 | img_ir_write(priv, IMG_IR_CONTROL, 0); | |
747 | hw->mode = IMG_IR_M_NORMAL; | |
748 | img_ir_write_timings(priv, &hw->reg_timings.timings, | |
749 | RC_FILTER_NORMAL); | |
750 | img_ir_write(priv, IMG_IR_CONTROL, hw->reg_timings.ctrl); | |
751 | } | |
752 | } | |
753 | ||
754 | /* lock must be held */ | |
755 | static void img_ir_handle_data(struct img_ir_priv *priv, u32 len, u64 raw) | |
756 | { | |
757 | struct img_ir_priv_hw *hw = &priv->hw; | |
758 | const struct img_ir_decoder *dec = hw->decoder; | |
759 | int ret = IMG_IR_SCANCODE; | |
760 | int scancode; | |
761 | if (dec->scancode) | |
762 | ret = dec->scancode(len, raw, &scancode, hw->enabled_protocols); | |
763 | else if (len >= 32) | |
764 | scancode = (u32)raw; | |
765 | else if (len < 32) | |
766 | scancode = (u32)raw & ((1 << len)-1); | |
767 | dev_dbg(priv->dev, "data (%u bits) = %#llx\n", | |
768 | len, (unsigned long long)raw); | |
769 | if (ret == IMG_IR_SCANCODE) { | |
770 | dev_dbg(priv->dev, "decoded scan code %#x\n", scancode); | |
771 | rc_keydown(hw->rdev, scancode, 0); | |
772 | img_ir_end_repeat(priv); | |
773 | } else if (ret == IMG_IR_REPEATCODE) { | |
774 | if (hw->mode == IMG_IR_M_REPEATING) { | |
775 | dev_dbg(priv->dev, "decoded repeat code\n"); | |
776 | rc_repeat(hw->rdev); | |
777 | } else { | |
778 | dev_dbg(priv->dev, "decoded unexpected repeat code, ignoring\n"); | |
779 | } | |
780 | } else { | |
781 | dev_dbg(priv->dev, "decode failed (%d)\n", ret); | |
782 | return; | |
783 | } | |
784 | ||
785 | ||
786 | if (dec->repeat) { | |
787 | unsigned long interval; | |
788 | ||
789 | img_ir_begin_repeat(priv); | |
790 | ||
791 | /* update timer, but allowing for 1/8th tolerance */ | |
792 | interval = dec->repeat + (dec->repeat >> 3); | |
793 | mod_timer(&hw->end_timer, | |
794 | jiffies + msecs_to_jiffies(interval)); | |
795 | } | |
796 | } | |
797 | ||
798 | /* timer function to end waiting for repeat. */ | |
799 | static void img_ir_end_timer(unsigned long arg) | |
800 | { | |
801 | struct img_ir_priv *priv = (struct img_ir_priv *)arg; | |
802 | ||
803 | spin_lock_irq(&priv->lock); | |
804 | img_ir_end_repeat(priv); | |
805 | spin_unlock_irq(&priv->lock); | |
806 | } | |
807 | ||
808 | #ifdef CONFIG_COMMON_CLK | |
809 | static void img_ir_change_frequency(struct img_ir_priv *priv, | |
810 | struct clk_notifier_data *change) | |
811 | { | |
812 | struct img_ir_priv_hw *hw = &priv->hw; | |
813 | ||
814 | dev_dbg(priv->dev, "clk changed %lu HZ -> %lu HZ\n", | |
815 | change->old_rate, change->new_rate); | |
816 | ||
817 | spin_lock_irq(&priv->lock); | |
818 | if (hw->clk_hz == change->new_rate) | |
819 | goto unlock; | |
820 | hw->clk_hz = change->new_rate; | |
821 | /* refresh current timings */ | |
822 | if (hw->decoder) { | |
823 | img_ir_decoder_convert(hw->decoder, &hw->reg_timings, | |
824 | hw->clk_hz); | |
825 | switch (hw->mode) { | |
826 | case IMG_IR_M_NORMAL: | |
827 | img_ir_write_timings(priv, &hw->reg_timings.timings, | |
828 | RC_FILTER_NORMAL); | |
829 | break; | |
830 | case IMG_IR_M_REPEATING: | |
831 | img_ir_write_timings(priv, &hw->reg_timings.rtimings, | |
832 | RC_FILTER_NORMAL); | |
833 | break; | |
834 | #ifdef CONFIG_PM_SLEEP | |
835 | case IMG_IR_M_WAKE: | |
836 | img_ir_write_timings(priv, &hw->reg_timings.timings, | |
837 | RC_FILTER_WAKEUP); | |
838 | break; | |
839 | #endif | |
840 | } | |
841 | } | |
842 | unlock: | |
843 | spin_unlock_irq(&priv->lock); | |
844 | } | |
845 | ||
846 | static int img_ir_clk_notify(struct notifier_block *self, unsigned long action, | |
847 | void *data) | |
848 | { | |
849 | struct img_ir_priv *priv = container_of(self, struct img_ir_priv, | |
850 | hw.clk_nb); | |
851 | switch (action) { | |
852 | case POST_RATE_CHANGE: | |
853 | img_ir_change_frequency(priv, data); | |
854 | break; | |
855 | default: | |
856 | break; | |
857 | } | |
858 | return NOTIFY_OK; | |
859 | } | |
860 | #endif /* CONFIG_COMMON_CLK */ | |
861 | ||
862 | /* called with priv->lock held */ | |
863 | void img_ir_isr_hw(struct img_ir_priv *priv, u32 irq_status) | |
864 | { | |
865 | struct img_ir_priv_hw *hw = &priv->hw; | |
866 | u32 ir_status, len, lw, up; | |
867 | unsigned int ct; | |
868 | ||
869 | /* use the current decoder */ | |
870 | if (!hw->decoder) | |
871 | return; | |
872 | ||
873 | ir_status = img_ir_read(priv, IMG_IR_STATUS); | |
874 | if (!(ir_status & (IMG_IR_RXDVAL | IMG_IR_RXDVALD2))) | |
875 | return; | |
876 | ir_status &= ~(IMG_IR_RXDVAL | IMG_IR_RXDVALD2); | |
877 | img_ir_write(priv, IMG_IR_STATUS, ir_status); | |
878 | ||
879 | len = (ir_status & IMG_IR_RXDLEN) >> IMG_IR_RXDLEN_SHIFT; | |
880 | /* some versions report wrong length for certain code types */ | |
881 | ct = hw->decoder->control.code_type; | |
882 | if (hw->ct_quirks[ct] & IMG_IR_QUIRK_CODE_LEN_INCR) | |
883 | ++len; | |
884 | ||
885 | lw = img_ir_read(priv, IMG_IR_DATA_LW); | |
886 | up = img_ir_read(priv, IMG_IR_DATA_UP); | |
887 | img_ir_handle_data(priv, len, (u64)up << 32 | lw); | |
888 | } | |
889 | ||
890 | void img_ir_setup_hw(struct img_ir_priv *priv) | |
891 | { | |
892 | struct img_ir_decoder **decp; | |
893 | ||
894 | if (!priv->hw.rdev) | |
895 | return; | |
896 | ||
897 | /* Use the first available decoder (or disable stuff if NULL) */ | |
898 | for (decp = img_ir_decoders; *decp; ++decp) { | |
899 | const struct img_ir_decoder *dec = *decp; | |
900 | if (img_ir_decoder_compatible(priv, dec)) { | |
901 | img_ir_set_protocol(priv, dec->type); | |
902 | img_ir_set_decoder(priv, dec, 0); | |
903 | return; | |
904 | } | |
905 | } | |
906 | img_ir_set_decoder(priv, NULL, 0); | |
907 | } | |
908 | ||
909 | /** | |
910 | * img_ir_probe_hw_caps() - Probe capabilities of the hardware. | |
911 | * @priv: IR private data. | |
912 | */ | |
913 | static void img_ir_probe_hw_caps(struct img_ir_priv *priv) | |
914 | { | |
915 | struct img_ir_priv_hw *hw = &priv->hw; | |
916 | /* | |
917 | * When a version of the block becomes available without these quirks, | |
918 | * they'll have to depend on the core revision. | |
919 | */ | |
920 | hw->ct_quirks[IMG_IR_CODETYPE_PULSELEN] | |
921 | |= IMG_IR_QUIRK_CODE_LEN_INCR; | |
922 | hw->ct_quirks[IMG_IR_CODETYPE_BIPHASE] | |
923 | |= IMG_IR_QUIRK_CODE_BROKEN; | |
924 | hw->ct_quirks[IMG_IR_CODETYPE_2BITPULSEPOS] | |
925 | |= IMG_IR_QUIRK_CODE_BROKEN; | |
926 | } | |
927 | ||
928 | int img_ir_probe_hw(struct img_ir_priv *priv) | |
929 | { | |
930 | struct img_ir_priv_hw *hw = &priv->hw; | |
931 | struct rc_dev *rdev; | |
932 | int error; | |
933 | ||
934 | /* Ensure hardware decoders have been preprocessed */ | |
935 | img_ir_init_decoders(); | |
936 | ||
937 | /* Probe hardware capabilities */ | |
938 | img_ir_probe_hw_caps(priv); | |
939 | ||
940 | /* Set up the end timer */ | |
941 | setup_timer(&hw->end_timer, img_ir_end_timer, (unsigned long)priv); | |
942 | ||
943 | /* Register a clock notifier */ | |
944 | if (!IS_ERR(priv->clk)) { | |
945 | hw->clk_hz = clk_get_rate(priv->clk); | |
946 | #ifdef CONFIG_COMMON_CLK | |
947 | hw->clk_nb.notifier_call = img_ir_clk_notify; | |
948 | error = clk_notifier_register(priv->clk, &hw->clk_nb); | |
949 | if (error) | |
950 | dev_warn(priv->dev, | |
951 | "failed to register clock notifier\n"); | |
952 | #endif | |
953 | } else { | |
954 | hw->clk_hz = 32768; | |
955 | } | |
956 | ||
957 | /* Allocate hardware decoder */ | |
958 | hw->rdev = rdev = rc_allocate_device(); | |
959 | if (!rdev) { | |
960 | dev_err(priv->dev, "cannot allocate input device\n"); | |
961 | error = -ENOMEM; | |
962 | goto err_alloc_rc; | |
963 | } | |
964 | rdev->priv = priv; | |
965 | rdev->map_name = RC_MAP_EMPTY; | |
966 | rc_set_allowed_protocols(rdev, img_ir_allowed_protos(priv)); | |
967 | rdev->input_name = "IMG Infrared Decoder"; | |
968 | rdev->s_filter = img_ir_set_filter; | |
969 | ||
970 | /* Register hardware decoder */ | |
971 | error = rc_register_device(rdev); | |
972 | if (error) { | |
973 | dev_err(priv->dev, "failed to register IR input device\n"); | |
974 | goto err_register_rc; | |
975 | } | |
976 | ||
977 | /* | |
978 | * Set this after rc_register_device as no protocols have been | |
979 | * registered yet. | |
980 | */ | |
981 | rdev->change_protocol = img_ir_change_protocol; | |
982 | ||
983 | device_init_wakeup(priv->dev, 1); | |
984 | ||
985 | return 0; | |
986 | ||
987 | err_register_rc: | |
988 | img_ir_set_decoder(priv, NULL, 0); | |
989 | hw->rdev = NULL; | |
990 | rc_free_device(rdev); | |
991 | err_alloc_rc: | |
992 | #ifdef CONFIG_COMMON_CLK | |
993 | if (!IS_ERR(priv->clk)) | |
994 | clk_notifier_unregister(priv->clk, &hw->clk_nb); | |
995 | #endif | |
996 | return error; | |
997 | } | |
998 | ||
999 | void img_ir_remove_hw(struct img_ir_priv *priv) | |
1000 | { | |
1001 | struct img_ir_priv_hw *hw = &priv->hw; | |
1002 | struct rc_dev *rdev = hw->rdev; | |
1003 | if (!rdev) | |
1004 | return; | |
1005 | img_ir_set_decoder(priv, NULL, 0); | |
1006 | hw->rdev = NULL; | |
1007 | rc_unregister_device(rdev); | |
1008 | #ifdef CONFIG_COMMON_CLK | |
1009 | if (!IS_ERR(priv->clk)) | |
1010 | clk_notifier_unregister(priv->clk, &hw->clk_nb); | |
1011 | #endif | |
1012 | } | |
1013 | ||
1014 | #ifdef CONFIG_PM_SLEEP | |
1015 | int img_ir_suspend(struct device *dev) | |
1016 | { | |
1017 | struct img_ir_priv *priv = dev_get_drvdata(dev); | |
1018 | ||
1019 | if (device_may_wakeup(dev) && img_ir_enable_wake(priv)) | |
1020 | enable_irq_wake(priv->irq); | |
1021 | return 0; | |
1022 | } | |
1023 | ||
1024 | int img_ir_resume(struct device *dev) | |
1025 | { | |
1026 | struct img_ir_priv *priv = dev_get_drvdata(dev); | |
1027 | ||
1028 | if (device_may_wakeup(dev) && img_ir_disable_wake(priv)) | |
1029 | disable_irq_wake(priv->irq); | |
1030 | return 0; | |
1031 | } | |
1032 | #endif /* CONFIG_PM_SLEEP */ |