]>
Commit | Line | Data |
---|---|---|
635abb70 JH |
1 | /* |
2 | * ImgTec IR Decoder setup for NEC protocol. | |
3 | * | |
4 | * Copyright 2010-2014 Imagination Technologies Ltd. | |
2ac6f630 JH |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by the | |
8 | * Free Software Foundation; either version 2 of the License, or (at your | |
9 | * option) any later version. | |
635abb70 JH |
10 | */ |
11 | ||
12 | #include "img-ir-hw.h" | |
42f5e630 | 13 | #include <linux/bitrev.h> |
0751d33c | 14 | #include <linux/log2.h> |
635abb70 JH |
15 | |
16 | /* Convert NEC data to a scancode */ | |
ab93ce06 SN |
17 | static int img_ir_nec_scancode(int len, u64 raw, u64 enabled_protocols, |
18 | struct img_ir_scancode_req *request) | |
635abb70 JH |
19 | { |
20 | unsigned int addr, addr_inv, data, data_inv; | |
21 | /* a repeat code has no data */ | |
22 | if (!len) | |
23 | return IMG_IR_REPEATCODE; | |
24 | if (len != 32) | |
25 | return -EINVAL; | |
26 | /* raw encoding: ddDDaaAA */ | |
27 | addr = (raw >> 0) & 0xff; | |
28 | addr_inv = (raw >> 8) & 0xff; | |
29 | data = (raw >> 16) & 0xff; | |
30 | data_inv = (raw >> 24) & 0xff; | |
31 | if ((data_inv ^ data) != 0xff) { | |
32 | /* 32-bit NEC (used by Apple and TiVo remotes) */ | |
42f5e630 | 33 | /* scan encoding: as transmitted, MSBit = first received bit */ |
ab93ce06 SN |
34 | request->scancode = bitrev8(addr) << 24 | |
35 | bitrev8(addr_inv) << 16 | | |
36 | bitrev8(data) << 8 | | |
37 | bitrev8(data_inv); | |
2ceeca04 | 38 | request->protocol = RC_TYPE_NEC32; |
635abb70 JH |
39 | } else if ((addr_inv ^ addr) != 0xff) { |
40 | /* Extended NEC */ | |
41 | /* scan encoding: AAaaDD */ | |
ab93ce06 SN |
42 | request->scancode = addr << 16 | |
43 | addr_inv << 8 | | |
44 | data; | |
2ceeca04 | 45 | request->protocol = RC_TYPE_NECX; |
635abb70 JH |
46 | } else { |
47 | /* Normal NEC */ | |
48 | /* scan encoding: AADD */ | |
ab93ce06 SN |
49 | request->scancode = addr << 8 | |
50 | data; | |
2ceeca04 | 51 | request->protocol = RC_TYPE_NEC; |
635abb70 JH |
52 | } |
53 | return IMG_IR_SCANCODE; | |
54 | } | |
55 | ||
56 | /* Convert NEC scancode to NEC data filter */ | |
57 | static int img_ir_nec_filter(const struct rc_scancode_filter *in, | |
58 | struct img_ir_filter *out, u64 protocols) | |
59 | { | |
60 | unsigned int addr, addr_inv, data, data_inv; | |
61 | unsigned int addr_m, addr_inv_m, data_m, data_inv_m; | |
62 | ||
63 | data = in->data & 0xff; | |
64 | data_m = in->mask & 0xff; | |
65 | ||
0751d33c SY |
66 | protocols &= RC_BIT_NEC | RC_BIT_NECX | RC_BIT_NEC32; |
67 | ||
68 | /* | |
69 | * If only one bit is set, we were requested to do an exact | |
70 | * protocol. This should be the case for wakeup filters; for | |
71 | * normal filters, guess the protocol from the scancode. | |
72 | */ | |
73 | if (!is_power_of_2(protocols)) { | |
74 | if ((in->data | in->mask) & 0xff000000) | |
75 | protocols = RC_BIT_NEC32; | |
76 | else if ((in->data | in->mask) & 0x00ff0000) | |
77 | protocols = RC_BIT_NECX; | |
78 | else | |
79 | protocols = RC_BIT_NEC; | |
80 | } | |
81 | ||
82 | if (protocols == RC_BIT_NEC32) { | |
635abb70 | 83 | /* 32-bit NEC (used by Apple and TiVo remotes) */ |
42f5e630 DH |
84 | /* scan encoding: as transmitted, MSBit = first received bit */ |
85 | addr = bitrev8(in->data >> 24); | |
86 | addr_m = bitrev8(in->mask >> 24); | |
87 | addr_inv = bitrev8(in->data >> 16); | |
88 | addr_inv_m = bitrev8(in->mask >> 16); | |
89 | data = bitrev8(in->data >> 8); | |
90 | data_m = bitrev8(in->mask >> 8); | |
91 | data_inv = bitrev8(in->data >> 0); | |
92 | data_inv_m = bitrev8(in->mask >> 0); | |
0751d33c | 93 | } else if (protocols == RC_BIT_NECX) { |
635abb70 JH |
94 | /* Extended NEC */ |
95 | /* scan encoding AAaaDD */ | |
96 | addr = (in->data >> 16) & 0xff; | |
97 | addr_m = (in->mask >> 16) & 0xff; | |
98 | addr_inv = (in->data >> 8) & 0xff; | |
99 | addr_inv_m = (in->mask >> 8) & 0xff; | |
100 | data_inv = data ^ 0xff; | |
101 | data_inv_m = data_m; | |
102 | } else { | |
103 | /* Normal NEC */ | |
104 | /* scan encoding: AADD */ | |
105 | addr = (in->data >> 8) & 0xff; | |
106 | addr_m = (in->mask >> 8) & 0xff; | |
107 | addr_inv = addr ^ 0xff; | |
108 | addr_inv_m = addr_m; | |
109 | data_inv = data ^ 0xff; | |
110 | data_inv_m = data_m; | |
111 | } | |
112 | ||
113 | /* raw encoding: ddDDaaAA */ | |
114 | out->data = data_inv << 24 | | |
115 | data << 16 | | |
116 | addr_inv << 8 | | |
117 | addr; | |
118 | out->mask = data_inv_m << 24 | | |
119 | data_m << 16 | | |
120 | addr_inv_m << 8 | | |
121 | addr_m; | |
122 | return 0; | |
123 | } | |
124 | ||
125 | /* | |
126 | * NEC decoder | |
127 | * See also http://www.sbprojects.com/knowledge/ir/nec.php | |
128 | * http://wiki.altium.com/display/ADOH/NEC+Infrared+Transmission+Protocol | |
129 | */ | |
130 | struct img_ir_decoder img_ir_nec = { | |
2ceeca04 | 131 | .type = RC_BIT_NEC | RC_BIT_NECX | RC_BIT_NEC32, |
635abb70 JH |
132 | .control = { |
133 | .decoden = 1, | |
134 | .code_type = IMG_IR_CODETYPE_PULSEDIST, | |
135 | }, | |
136 | /* main timings */ | |
137 | .unit = 562500, /* 562.5 us */ | |
138 | .timings = { | |
139 | /* leader symbol */ | |
140 | .ldr = { | |
141 | .pulse = { 16 /* 9ms */ }, | |
142 | .space = { 8 /* 4.5ms */ }, | |
143 | }, | |
144 | /* 0 symbol */ | |
145 | .s00 = { | |
146 | .pulse = { 1 /* 562.5 us */ }, | |
147 | .space = { 1 /* 562.5 us */ }, | |
148 | }, | |
149 | /* 1 symbol */ | |
150 | .s01 = { | |
151 | .pulse = { 1 /* 562.5 us */ }, | |
152 | .space = { 3 /* 1687.5 us */ }, | |
153 | }, | |
154 | /* free time */ | |
155 | .ft = { | |
156 | .minlen = 32, | |
157 | .maxlen = 32, | |
158 | .ft_min = 10, /* 5.625 ms */ | |
159 | }, | |
160 | }, | |
161 | /* repeat codes */ | |
162 | .repeat = 108, /* 108 ms */ | |
163 | .rtimings = { | |
164 | /* leader symbol */ | |
165 | .ldr = { | |
166 | .space = { 4 /* 2.25 ms */ }, | |
167 | }, | |
168 | /* free time */ | |
169 | .ft = { | |
170 | .minlen = 0, /* repeat code has no data */ | |
171 | .maxlen = 0, | |
172 | }, | |
173 | }, | |
174 | /* scancode logic */ | |
175 | .scancode = img_ir_nec_scancode, | |
176 | .filter = img_ir_nec_filter, | |
177 | }; |