drm/rockchip: Don't change hdmi reference clock rate
[drm/drm-misc.git] / drivers / media / rc / ir-sharp-decoder.c
blob3311099cbd573b840e1fce402df9a2c3bc2a0506
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* ir-sharp-decoder.c - handle Sharp IR Pulse/Space protocol
4 * Copyright (C) 2013-2014 Imagination Technologies Ltd.
6 * Based on NEC decoder:
7 * Copyright (C) 2010 by Mauro Carvalho Chehab
8 */
10 #include <linux/bitrev.h>
11 #include <linux/module.h>
12 #include "rc-core-priv.h"
14 #define SHARP_NBITS 15
15 #define SHARP_UNIT 40 /* us */
16 #define SHARP_BIT_PULSE (8 * SHARP_UNIT) /* 320us */
17 #define SHARP_BIT_0_PERIOD (25 * SHARP_UNIT) /* 1ms (680us space) */
18 #define SHARP_BIT_1_PERIOD (50 * SHARP_UNIT) /* 2ms (1680us space) */
19 #define SHARP_BIT_0_SPACE (17 * SHARP_UNIT) /* 680us space */
20 #define SHARP_BIT_1_SPACE (42 * SHARP_UNIT) /* 1680us space */
21 #define SHARP_ECHO_SPACE (1000 * SHARP_UNIT) /* 40 ms */
22 #define SHARP_TRAILER_SPACE (125 * SHARP_UNIT) /* 5 ms (even longer) */
24 enum sharp_state {
25 STATE_INACTIVE,
26 STATE_BIT_PULSE,
27 STATE_BIT_SPACE,
28 STATE_TRAILER_PULSE,
29 STATE_ECHO_SPACE,
30 STATE_TRAILER_SPACE,
33 /**
34 * ir_sharp_decode() - Decode one Sharp pulse or space
35 * @dev: the struct rc_dev descriptor of the device
36 * @ev: the struct ir_raw_event descriptor of the pulse/space
38 * This function returns -EINVAL if the pulse violates the state machine
40 static int ir_sharp_decode(struct rc_dev *dev, struct ir_raw_event ev)
42 struct sharp_dec *data = &dev->raw->sharp;
43 u32 msg, echo, address, command, scancode;
45 if (!is_timing_event(ev)) {
46 if (ev.overflow)
47 data->state = STATE_INACTIVE;
48 return 0;
51 dev_dbg(&dev->dev, "Sharp decode started at state %d (%uus %s)\n",
52 data->state, ev.duration, TO_STR(ev.pulse));
54 switch (data->state) {
56 case STATE_INACTIVE:
57 if (!ev.pulse)
58 break;
60 if (!eq_margin(ev.duration, SHARP_BIT_PULSE,
61 SHARP_BIT_PULSE / 2))
62 break;
64 data->count = 0;
65 data->pulse_len = ev.duration;
66 data->state = STATE_BIT_SPACE;
67 return 0;
69 case STATE_BIT_PULSE:
70 if (!ev.pulse)
71 break;
73 if (!eq_margin(ev.duration, SHARP_BIT_PULSE,
74 SHARP_BIT_PULSE / 2))
75 break;
77 data->pulse_len = ev.duration;
78 data->state = STATE_BIT_SPACE;
79 return 0;
81 case STATE_BIT_SPACE:
82 if (ev.pulse)
83 break;
85 data->bits <<= 1;
86 if (eq_margin(data->pulse_len + ev.duration, SHARP_BIT_1_PERIOD,
87 SHARP_BIT_PULSE * 2))
88 data->bits |= 1;
89 else if (!eq_margin(data->pulse_len + ev.duration,
90 SHARP_BIT_0_PERIOD, SHARP_BIT_PULSE * 2))
91 break;
92 data->count++;
94 if (data->count == SHARP_NBITS ||
95 data->count == SHARP_NBITS * 2)
96 data->state = STATE_TRAILER_PULSE;
97 else
98 data->state = STATE_BIT_PULSE;
100 return 0;
102 case STATE_TRAILER_PULSE:
103 if (!ev.pulse)
104 break;
106 if (!eq_margin(ev.duration, SHARP_BIT_PULSE,
107 SHARP_BIT_PULSE / 2))
108 break;
110 if (data->count == SHARP_NBITS) {
111 /* exp,chk bits should be 1,0 */
112 if ((data->bits & 0x3) != 0x2 &&
113 /* DENON variant, both chk bits 0 */
114 (data->bits & 0x3) != 0x0)
115 break;
116 data->state = STATE_ECHO_SPACE;
117 } else {
118 data->state = STATE_TRAILER_SPACE;
120 return 0;
122 case STATE_ECHO_SPACE:
123 if (ev.pulse)
124 break;
126 if (!eq_margin(ev.duration, SHARP_ECHO_SPACE,
127 SHARP_ECHO_SPACE / 4))
128 break;
130 data->state = STATE_BIT_PULSE;
132 return 0;
134 case STATE_TRAILER_SPACE:
135 if (ev.pulse)
136 break;
138 if (!geq_margin(ev.duration, SHARP_TRAILER_SPACE,
139 SHARP_BIT_PULSE / 2))
140 break;
142 /* Validate - command, ext, chk should be inverted in 2nd */
143 msg = (data->bits >> 15) & 0x7fff;
144 echo = data->bits & 0x7fff;
145 if ((msg ^ echo) != 0x3ff) {
146 dev_dbg(&dev->dev,
147 "Sharp checksum error: received 0x%04x, 0x%04x\n",
148 msg, echo);
149 break;
152 address = bitrev8((msg >> 7) & 0xf8);
153 command = bitrev8((msg >> 2) & 0xff);
155 scancode = address << 8 | command;
156 dev_dbg(&dev->dev, "Sharp scancode 0x%04x\n", scancode);
158 rc_keydown(dev, RC_PROTO_SHARP, scancode, 0);
159 data->state = STATE_INACTIVE;
160 return 0;
163 dev_dbg(&dev->dev, "Sharp decode failed at count %d state %d (%uus %s)\n",
164 data->count, data->state, ev.duration, TO_STR(ev.pulse));
165 data->state = STATE_INACTIVE;
166 return -EINVAL;
169 static const struct ir_raw_timings_pd ir_sharp_timings = {
170 .header_pulse = 0,
171 .header_space = 0,
172 .bit_pulse = SHARP_BIT_PULSE,
173 .bit_space[0] = SHARP_BIT_0_SPACE,
174 .bit_space[1] = SHARP_BIT_1_SPACE,
175 .trailer_pulse = SHARP_BIT_PULSE,
176 .trailer_space = SHARP_ECHO_SPACE,
177 .msb_first = 1,
181 * ir_sharp_encode() - Encode a scancode as a stream of raw events
183 * @protocol: protocol to encode
184 * @scancode: scancode to encode
185 * @events: array of raw ir events to write into
186 * @max: maximum size of @events
188 * Returns: The number of events written.
189 * -ENOBUFS if there isn't enough space in the array to fit the
190 * encoding. In this case all @max events will have been written.
192 static int ir_sharp_encode(enum rc_proto protocol, u32 scancode,
193 struct ir_raw_event *events, unsigned int max)
195 struct ir_raw_event *e = events;
196 int ret;
197 u32 raw;
199 raw = (((bitrev8(scancode >> 8) >> 3) << 8) & 0x1f00) |
200 bitrev8(scancode);
201 ret = ir_raw_gen_pd(&e, max, &ir_sharp_timings, SHARP_NBITS,
202 (raw << 2) | 2);
203 if (ret < 0)
204 return ret;
206 max -= ret;
208 raw = (((bitrev8(scancode >> 8) >> 3) << 8) & 0x1f00) |
209 bitrev8(~scancode);
210 ret = ir_raw_gen_pd(&e, max, &ir_sharp_timings, SHARP_NBITS,
211 (raw << 2) | 1);
212 if (ret < 0)
213 return ret;
215 return e - events;
218 static struct ir_raw_handler sharp_handler = {
219 .protocols = RC_PROTO_BIT_SHARP,
220 .decode = ir_sharp_decode,
221 .encode = ir_sharp_encode,
222 .carrier = 38000,
223 .min_timeout = SHARP_ECHO_SPACE + SHARP_ECHO_SPACE / 4,
226 static int __init ir_sharp_decode_init(void)
228 ir_raw_handler_register(&sharp_handler);
230 pr_info("IR Sharp protocol handler initialized\n");
231 return 0;
234 static void __exit ir_sharp_decode_exit(void)
236 ir_raw_handler_unregister(&sharp_handler);
239 module_init(ir_sharp_decode_init);
240 module_exit(ir_sharp_decode_exit);
242 MODULE_LICENSE("GPL");
243 MODULE_AUTHOR("James Hogan <jhogan@kernel.org>");
244 MODULE_DESCRIPTION("Sharp IR protocol decoder");