blob: 82867a2a60b0e3645874b623c37a1f58d599cfb4 [file] [log] [blame]
Thomas Gleixnerc942fdd2019-05-27 08:55:06 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03002/*
Maxim Levitsky11b64d32010-09-06 18:26:11 -03003 * driver for ENE KB3926 B/C/D/E/F CIR (pnp id: ENE0XXX)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03004 *
5 * Copyright (C) 2010 Maxim Levitsky <maximlevitsky@gmail.com>
6 *
Maxim Levitsky11b64d32010-09-06 18:26:11 -03007 * Special thanks to:
8 * Sami R. <maesesami@gmail.com> for lot of help in debugging and therefore
9 * bringing to life support for transmission & learning mode.
10 *
11 * Charlie Andrews <charliethepilot@googlemail.com> for lots of help in
12 * bringing up the support of new firmware buffer that is popular
13 * on latest notebooks
14 *
15 * ENE for partial device documentation
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030016 */
17
Joe Perches7de34612011-08-21 19:56:46 -030018#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030020#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/pnp.h>
23#include <linux/io.h>
24#include <linux/interrupt.h>
25#include <linux/sched.h>
Maxim Levitsky931e39a2010-07-31 11:59:26 -030026#include <linux/slab.h>
Mauro Carvalho Chehab6bda9642010-11-17 13:28:38 -030027#include <media/rc-core.h>
Maxim Levitsky931e39a2010-07-31 11:59:26 -030028#include "ene_ir.h"
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030029
Maxim Levitsky11b64d32010-09-06 18:26:11 -030030static int sample_period;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -030031static bool learning_mode_force;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030032static int debug;
Maxim Levitsky11b64d32010-09-06 18:26:11 -030033static bool txsim;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030034
Maxim Levitsky11b64d32010-09-06 18:26:11 -030035static void ene_set_reg_addr(struct ene_device *dev, u16 reg)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030036{
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030037 outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
38 outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
Maxim Levitsky11b64d32010-09-06 18:26:11 -030039}
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030040
Maxim Levitsky11b64d32010-09-06 18:26:11 -030041/* read a hardware register */
42static u8 ene_read_reg(struct ene_device *dev, u16 reg)
43{
44 u8 retval;
45 ene_set_reg_addr(dev, reg);
46 retval = inb(dev->hw_io + ENE_IO);
47 dbg_regs("reg %04x == %02x", reg, retval);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030048 return retval;
49}
50
51/* write a hardware register */
Maxim Levitsky11b64d32010-09-06 18:26:11 -030052static void ene_write_reg(struct ene_device *dev, u16 reg, u8 value)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030053{
Maxim Levitsky11b64d32010-09-06 18:26:11 -030054 dbg_regs("reg %04x <- %02x", reg, value);
55 ene_set_reg_addr(dev, reg);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030056 outb(value, dev->hw_io + ENE_IO);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030057}
58
Maxim Levitsky11b64d32010-09-06 18:26:11 -030059/* Set bits in hardware register */
60static void ene_set_reg_mask(struct ene_device *dev, u16 reg, u8 mask)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030061{
Maxim Levitsky11b64d32010-09-06 18:26:11 -030062 dbg_regs("reg %04x |= %02x", reg, mask);
63 ene_set_reg_addr(dev, reg);
64 outb(inb(dev->hw_io + ENE_IO) | mask, dev->hw_io + ENE_IO);
65}
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030066
Maxim Levitsky11b64d32010-09-06 18:26:11 -030067/* Clear bits in hardware register */
68static void ene_clear_reg_mask(struct ene_device *dev, u16 reg, u8 mask)
69{
70 dbg_regs("reg %04x &= ~%02x ", reg, mask);
71 ene_set_reg_addr(dev, reg);
72 outb(inb(dev->hw_io + ENE_IO) & ~mask, dev->hw_io + ENE_IO);
73}
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030074
Maxim Levitsky11b64d32010-09-06 18:26:11 -030075/* A helper to set/clear a bit in register according to boolean variable */
76static void ene_set_clear_reg_mask(struct ene_device *dev, u16 reg, u8 mask,
77 bool set)
78{
79 if (set)
80 ene_set_reg_mask(dev, reg, mask);
81 else
82 ene_clear_reg_mask(dev, reg, mask);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030083}
84
85/* detect hardware features */
86static int ene_hw_detect(struct ene_device *dev)
87{
88 u8 chip_major, chip_minor;
89 u8 hw_revision, old_ver;
Maxim Levitsky11b64d32010-09-06 18:26:11 -030090 u8 fw_reg2, fw_reg1;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030091
Maxim Levitsky11b64d32010-09-06 18:26:11 -030092 ene_clear_reg_mask(dev, ENE_ECSTS, ENE_ECSTS_RSRVD);
93 chip_major = ene_read_reg(dev, ENE_ECVER_MAJOR);
94 chip_minor = ene_read_reg(dev, ENE_ECVER_MINOR);
95 ene_set_reg_mask(dev, ENE_ECSTS, ENE_ECSTS_RSRVD);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030096
Maxim Levitsky11b64d32010-09-06 18:26:11 -030097 hw_revision = ene_read_reg(dev, ENE_ECHV);
98 old_ver = ene_read_reg(dev, ENE_HW_VER_OLD);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030099
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300100 dev->pll_freq = (ene_read_reg(dev, ENE_PLLFRH) << 4) +
101 (ene_read_reg(dev, ENE_PLLFRL) >> 4);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300102
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300103 if (sample_period != ENE_DEFAULT_SAMPLE_PERIOD)
104 dev->rx_period_adjust =
105 dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 2 : 4;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300106
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300107 if (hw_revision == 0xFF) {
Joe Perches7de34612011-08-21 19:56:46 -0300108 pr_warn("device seems to be disabled\n");
109 pr_warn("send a mail to lirc-list@lists.sourceforge.net\n");
110 pr_warn("please attach output of acpidump and dmidecode\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300111 return -ENODEV;
112 }
113
Joe Perches7de34612011-08-21 19:56:46 -0300114 pr_notice("chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x\n",
115 chip_major, chip_minor, old_ver, hw_revision);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300116
Joe Perches7de34612011-08-21 19:56:46 -0300117 pr_notice("PLL freq = %d\n", dev->pll_freq);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300118
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300119 if (chip_major == 0x33) {
Joe Perches7de34612011-08-21 19:56:46 -0300120 pr_warn("chips 0x33xx aren't supported\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300121 return -ENODEV;
122 }
123
124 if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) {
125 dev->hw_revision = ENE_HW_C;
Joe Perches7de34612011-08-21 19:56:46 -0300126 pr_notice("KB3926C detected\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300127 } else if (old_ver == 0x24 && hw_revision == 0xC0) {
128 dev->hw_revision = ENE_HW_B;
Joe Perches7de34612011-08-21 19:56:46 -0300129 pr_notice("KB3926B detected\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300130 } else {
131 dev->hw_revision = ENE_HW_D;
Joe Perches7de34612011-08-21 19:56:46 -0300132 pr_notice("KB3926D or higher detected\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300133 }
134
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300135 /* detect features hardware supports */
136 if (dev->hw_revision < ENE_HW_C)
137 return 0;
138
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300139 fw_reg1 = ene_read_reg(dev, ENE_FW1);
140 fw_reg2 = ene_read_reg(dev, ENE_FW2);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300141
Joe Perches7de34612011-08-21 19:56:46 -0300142 pr_notice("Firmware regs: %02x %02x\n", fw_reg1, fw_reg2);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300143
Maxim Levitskya06423c2010-10-15 13:06:37 -0300144 dev->hw_use_gpio_0a = !!(fw_reg2 & ENE_FW2_GP0A);
145 dev->hw_learning_and_tx_capable = !!(fw_reg2 & ENE_FW2_LEARNING);
146 dev->hw_extra_buffer = !!(fw_reg1 & ENE_FW1_HAS_EXTRA_BUF);
147
148 if (dev->hw_learning_and_tx_capable)
149 dev->hw_fan_input = !!(fw_reg2 & ENE_FW2_FAN_INPUT);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300150
Joe Perches7de34612011-08-21 19:56:46 -0300151 pr_notice("Hardware features:\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300152
153 if (dev->hw_learning_and_tx_capable) {
Joe Perches7de34612011-08-21 19:56:46 -0300154 pr_notice("* Supports transmitting & learning mode\n");
155 pr_notice(" This feature is rare and therefore,\n");
156 pr_notice(" you are welcome to test it,\n");
157 pr_notice(" and/or contact the author via:\n");
158 pr_notice(" lirc-list@lists.sourceforge.net\n");
159 pr_notice(" or maximlevitsky@gmail.com\n");
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300160
Joe Perches7de34612011-08-21 19:56:46 -0300161 pr_notice("* Uses GPIO %s for IR raw input\n",
162 dev->hw_use_gpio_0a ? "40" : "0A");
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300163
164 if (dev->hw_fan_input)
Joe Perches7de34612011-08-21 19:56:46 -0300165 pr_notice("* Uses unused fan feedback input as source of demodulated IR data\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300166 }
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300167
168 if (!dev->hw_fan_input)
Joe Perches7de34612011-08-21 19:56:46 -0300169 pr_notice("* Uses GPIO %s for IR demodulated input\n",
170 dev->hw_use_gpio_0a ? "0A" : "40");
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300171
172 if (dev->hw_extra_buffer)
Joe Perches7de34612011-08-21 19:56:46 -0300173 pr_notice("* Uses new style input buffer\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300174 return 0;
175}
176
Mauro Carvalho Chehab04ad3012019-02-18 14:29:01 -0500177/* Read properties of hw sample buffer */
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300178static void ene_rx_setup_hw_buffer(struct ene_device *dev)
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300179{
180 u16 tmp;
181
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300182 ene_rx_read_hw_pointer(dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300183 dev->r_pointer = dev->w_pointer;
184
185 if (!dev->hw_extra_buffer) {
186 dev->buffer_len = ENE_FW_PACKET_SIZE * 2;
187 return;
188 }
189
190 tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER);
191 tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER+1) << 8;
192 dev->extra_buf1_address = tmp;
193
194 dev->extra_buf1_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 2);
195
196 tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 3);
197 tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 4) << 8;
198 dev->extra_buf2_address = tmp;
199
200 dev->extra_buf2_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 5);
201
202 dev->buffer_len = dev->extra_buf1_len + dev->extra_buf2_len + 8;
203
Joe Perches7de34612011-08-21 19:56:46 -0300204 pr_notice("Hardware uses 2 extended buffers:\n");
205 pr_notice(" 0x%04x - len : %d\n",
206 dev->extra_buf1_address, dev->extra_buf1_len);
207 pr_notice(" 0x%04x - len : %d\n",
208 dev->extra_buf2_address, dev->extra_buf2_len);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300209
Joe Perches7de34612011-08-21 19:56:46 -0300210 pr_notice("Total buffer len = %d\n", dev->buffer_len);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300211
212 if (dev->buffer_len > 64 || dev->buffer_len < 16)
213 goto error;
214
215 if (dev->extra_buf1_address > 0xFBFC ||
216 dev->extra_buf1_address < 0xEC00)
217 goto error;
218
219 if (dev->extra_buf2_address > 0xFBFC ||
220 dev->extra_buf2_address < 0xEC00)
221 goto error;
222
223 if (dev->r_pointer > dev->buffer_len)
224 goto error;
225
226 ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
227 return;
228error:
Joe Perches7de34612011-08-21 19:56:46 -0300229 pr_warn("Error validating extra buffers, device probably won't work\n");
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300230 dev->hw_extra_buffer = false;
231 ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
232}
233
234
235/* Restore the pointers to extra buffers - to make module reload work*/
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300236static void ene_rx_restore_hw_buffer(struct ene_device *dev)
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300237{
238 if (!dev->hw_extra_buffer)
239 return;
240
241 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 0,
242 dev->extra_buf1_address & 0xFF);
243 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 1,
244 dev->extra_buf1_address >> 8);
245 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 2, dev->extra_buf1_len);
246
247 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 3,
248 dev->extra_buf2_address & 0xFF);
249 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 4,
250 dev->extra_buf2_address >> 8);
251 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 5,
252 dev->extra_buf2_len);
253 ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
254}
255
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300256/* Read hardware write pointer */
257static void ene_rx_read_hw_pointer(struct ene_device *dev)
258{
259 if (dev->hw_extra_buffer)
260 dev->w_pointer = ene_read_reg(dev, ENE_FW_RX_POINTER);
261 else
262 dev->w_pointer = ene_read_reg(dev, ENE_FW2)
263 & ENE_FW2_BUF_WPTR ? 0 : ENE_FW_PACKET_SIZE;
264
265 dbg_verbose("RB: HW write pointer: %02x, driver read pointer: %02x",
266 dev->w_pointer, dev->r_pointer);
267}
268
269/* Gets address of next sample from HW ring buffer */
270static int ene_rx_get_sample_reg(struct ene_device *dev)
271{
272 int r_pointer;
273
274 if (dev->r_pointer == dev->w_pointer) {
275 dbg_verbose("RB: hit end, try update w_pointer");
276 ene_rx_read_hw_pointer(dev);
277 }
278
279 if (dev->r_pointer == dev->w_pointer) {
280 dbg_verbose("RB: end of data at %d", dev->r_pointer);
281 return 0;
282 }
283
284 dbg_verbose("RB: reading at offset %d", dev->r_pointer);
285 r_pointer = dev->r_pointer;
286
287 dev->r_pointer++;
288 if (dev->r_pointer == dev->buffer_len)
289 dev->r_pointer = 0;
290
291 dbg_verbose("RB: next read will be from offset %d", dev->r_pointer);
292
293 if (r_pointer < 8) {
294 dbg_verbose("RB: read at main buffer at %d", r_pointer);
295 return ENE_FW_SAMPLE_BUFFER + r_pointer;
296 }
297
298 r_pointer -= 8;
299
300 if (r_pointer < dev->extra_buf1_len) {
301 dbg_verbose("RB: read at 1st extra buffer at %d", r_pointer);
302 return dev->extra_buf1_address + r_pointer;
303 }
304
305 r_pointer -= dev->extra_buf1_len;
306
307 if (r_pointer < dev->extra_buf2_len) {
308 dbg_verbose("RB: read at 2nd extra buffer at %d", r_pointer);
309 return dev->extra_buf2_address + r_pointer;
310 }
311
Paul Bolle90802ed2011-12-05 13:00:34 +0100312 dbg("attempt to read beyond ring buffer end");
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300313 return 0;
314}
315
316/* Sense current received carrier */
Mauro Carvalho Chehabe03cd642012-10-27 13:46:53 -0300317static void ene_rx_sense_carrier(struct ene_device *dev)
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300318{
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300319 int carrier, duty_cycle;
320 int period = ene_read_reg(dev, ENE_CIRCAR_PRD);
321 int hperiod = ene_read_reg(dev, ENE_CIRCAR_HPRD);
322
323 if (!(period & ENE_CIRCAR_PRD_VALID))
324 return;
325
326 period &= ~ENE_CIRCAR_PRD_VALID;
327
328 if (!period)
329 return;
330
331 dbg("RX: hardware carrier period = %02x", period);
332 dbg("RX: hardware carrier pulse period = %02x", hperiod);
333
334 carrier = 2000000 / period;
335 duty_cycle = (hperiod * 100) / period;
336 dbg("RX: sensed carrier = %d Hz, duty cycle %d%%",
337 carrier, duty_cycle);
338 if (dev->carrier_detect_enabled) {
Sean Young183e19f2018-08-21 15:57:52 -0400339 struct ir_raw_event ev = {
340 .carrier_report = true,
341 .carrier = carrier,
342 .duty_cycle = duty_cycle
343 };
David Härdemand8b4b582010-10-29 16:08:23 -0300344 ir_raw_event_store(dev->rdev, &ev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300345 }
346}
347
348/* this enables/disables the CIR RX engine */
349static void ene_rx_enable_cir_engine(struct ene_device *dev, bool enable)
350{
351 ene_set_clear_reg_mask(dev, ENE_CIRCFG,
352 ENE_CIRCFG_RX_EN | ENE_CIRCFG_RX_IRQ, enable);
353}
354
355/* this selects input for CIR engine. Ether GPIO 0A or GPIO40*/
356static void ene_rx_select_input(struct ene_device *dev, bool gpio_0a)
357{
358 ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_GPIO0A, gpio_0a);
359}
360
361/*
362 * this enables alternative input via fan tachometer sensor and bypasses
363 * the hw CIR engine
364 */
365static void ene_rx_enable_fan_input(struct ene_device *dev, bool enable)
366{
367 if (!dev->hw_fan_input)
368 return;
369
370 if (!enable)
371 ene_write_reg(dev, ENE_FAN_AS_IN1, 0);
372 else {
373 ene_write_reg(dev, ENE_FAN_AS_IN1, ENE_FAN_AS_IN1_EN);
374 ene_write_reg(dev, ENE_FAN_AS_IN2, ENE_FAN_AS_IN2_EN);
375 }
376}
377
378/* setup the receiver for RX*/
379static void ene_rx_setup(struct ene_device *dev)
380{
381 bool learning_mode = dev->learning_mode_enabled ||
382 dev->carrier_detect_enabled;
383 int sample_period_adjust = 0;
384
385 dbg("RX: setup receiver, learning mode = %d", learning_mode);
386
387
388 /* This selects RLC input and clears CFG2 settings */
389 ene_write_reg(dev, ENE_CIRCFG2, 0x00);
390
391 /* set sample period*/
392 if (sample_period == ENE_DEFAULT_SAMPLE_PERIOD)
393 sample_period_adjust =
394 dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 1 : 2;
395
396 ene_write_reg(dev, ENE_CIRRLC_CFG,
397 (sample_period + sample_period_adjust) |
398 ENE_CIRRLC_CFG_OVERFLOW);
399 /* revB doesn't support inputs */
400 if (dev->hw_revision < ENE_HW_C)
401 goto select_timeout;
402
403 if (learning_mode) {
404
405 WARN_ON(!dev->hw_learning_and_tx_capable);
406
407 /* Enable the opposite of the normal input
408 That means that if GPIO40 is normally used, use GPIO0A
409 and vice versa.
410 This input will carry non demodulated
411 signal, and we will tell the hw to demodulate it itself */
412 ene_rx_select_input(dev, !dev->hw_use_gpio_0a);
413 dev->rx_fan_input_inuse = false;
414
415 /* Enable carrier demodulation */
416 ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD);
417
418 /* Enable carrier detection */
419 ene_write_reg(dev, ENE_CIRCAR_PULS, 0x63);
420 ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT,
421 dev->carrier_detect_enabled || debug);
422 } else {
423 if (dev->hw_fan_input)
424 dev->rx_fan_input_inuse = true;
425 else
426 ene_rx_select_input(dev, dev->hw_use_gpio_0a);
427
428 /* Disable carrier detection & demodulation */
429 ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD);
430 ene_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT);
431 }
432
433select_timeout:
434 if (dev->rx_fan_input_inuse) {
Jarod Wilson5aad7242011-01-06 16:59:36 -0300435 dev->rdev->rx_resolution = US_TO_NS(ENE_FW_SAMPLE_PERIOD_FAN);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300436
437 /* Fan input doesn't support timeouts, it just ends the
438 input with a maximum sample */
David Härdemand8b4b582010-10-29 16:08:23 -0300439 dev->rdev->min_timeout = dev->rdev->max_timeout =
Jarod Wilson5aad7242011-01-06 16:59:36 -0300440 US_TO_NS(ENE_FW_SMPL_BUF_FAN_MSK *
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300441 ENE_FW_SAMPLE_PERIOD_FAN);
442 } else {
Jarod Wilson5aad7242011-01-06 16:59:36 -0300443 dev->rdev->rx_resolution = US_TO_NS(sample_period);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300444
445 /* Theoreticly timeout is unlimited, but we cap it
446 * because it was seen that on one device, it
447 * would stop sending spaces after around 250 msec.
448 * Besides, this is close to 2^32 anyway and timeout is u32.
449 */
Jarod Wilson5aad7242011-01-06 16:59:36 -0300450 dev->rdev->min_timeout = US_TO_NS(127 * sample_period);
451 dev->rdev->max_timeout = US_TO_NS(200000);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300452 }
453
454 if (dev->hw_learning_and_tx_capable)
Jarod Wilson5aad7242011-01-06 16:59:36 -0300455 dev->rdev->tx_resolution = US_TO_NS(sample_period);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300456
David Härdemand8b4b582010-10-29 16:08:23 -0300457 if (dev->rdev->timeout > dev->rdev->max_timeout)
458 dev->rdev->timeout = dev->rdev->max_timeout;
459 if (dev->rdev->timeout < dev->rdev->min_timeout)
460 dev->rdev->timeout = dev->rdev->min_timeout;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300461}
462
463/* Enable the device for receive */
Maxim Levitskyb5daad22013-07-07 20:22:46 -0300464static void ene_rx_enable_hw(struct ene_device *dev)
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300465{
466 u8 reg_value;
467
468 /* Enable system interrupt */
469 if (dev->hw_revision < ENE_HW_C) {
470 ene_write_reg(dev, ENEB_IRQ, dev->irq << 1);
471 ene_write_reg(dev, ENEB_IRQ_UNK1, 0x01);
472 } else {
473 reg_value = ene_read_reg(dev, ENE_IRQ) & 0xF0;
474 reg_value |= ENE_IRQ_UNK_EN;
475 reg_value &= ~ENE_IRQ_STATUS;
476 reg_value |= (dev->irq & ENE_IRQ_MASK);
477 ene_write_reg(dev, ENE_IRQ, reg_value);
478 }
479
480 /* Enable inputs */
481 ene_rx_enable_fan_input(dev, dev->rx_fan_input_inuse);
482 ene_rx_enable_cir_engine(dev, !dev->rx_fan_input_inuse);
483
484 /* ack any pending irqs - just in case */
485 ene_irq_status(dev);
486
487 /* enable firmware bits */
488 ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ);
489
490 /* enter idle mode */
David Härdemand8b4b582010-10-29 16:08:23 -0300491 ir_raw_event_set_idle(dev->rdev, true);
Maxim Levitskyb5daad22013-07-07 20:22:46 -0300492}
493
494/* Enable the device for receive - wrapper to track the state*/
495static void ene_rx_enable(struct ene_device *dev)
496{
497 ene_rx_enable_hw(dev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300498 dev->rx_enabled = true;
499}
500
501/* Disable the device receiver */
Maxim Levitskyb5daad22013-07-07 20:22:46 -0300502static void ene_rx_disable_hw(struct ene_device *dev)
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300503{
504 /* disable inputs */
505 ene_rx_enable_cir_engine(dev, false);
506 ene_rx_enable_fan_input(dev, false);
507
508 /* disable hardware IRQ and firmware flag */
509 ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ);
David Härdemand8b4b582010-10-29 16:08:23 -0300510 ir_raw_event_set_idle(dev->rdev, true);
Maxim Levitskyb5daad22013-07-07 20:22:46 -0300511}
512
513/* Disable the device receiver - wrapper to track the state */
514static void ene_rx_disable(struct ene_device *dev)
515{
516 ene_rx_disable_hw(dev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300517 dev->rx_enabled = false;
518}
519
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300520/* This resets the receiver. Useful to stop stream of spaces at end of
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300521 * transmission
522 */
523static void ene_rx_reset(struct ene_device *dev)
524{
525 ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
526 ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
527}
528
529/* Set up the TX carrier frequency and duty cycle */
530static void ene_tx_set_carrier(struct ene_device *dev)
531{
532 u8 tx_puls_width;
533 unsigned long flags;
534
535 spin_lock_irqsave(&dev->hw_lock, flags);
536
537 ene_set_clear_reg_mask(dev, ENE_CIRCFG,
538 ENE_CIRCFG_TX_CARR, dev->tx_period > 0);
539
540 if (!dev->tx_period)
541 goto unlock;
542
543 BUG_ON(dev->tx_duty_cycle >= 100 || dev->tx_duty_cycle <= 0);
544
545 tx_puls_width = dev->tx_period / (100 / dev->tx_duty_cycle);
546
547 if (!tx_puls_width)
548 tx_puls_width = 1;
549
550 dbg("TX: pulse distance = %d * 500 ns", dev->tx_period);
551 dbg("TX: pulse width = %d * 500 ns", tx_puls_width);
552
553 ene_write_reg(dev, ENE_CIRMOD_PRD, dev->tx_period | ENE_CIRMOD_PRD_POL);
554 ene_write_reg(dev, ENE_CIRMOD_HPRD, tx_puls_width);
555unlock:
556 spin_unlock_irqrestore(&dev->hw_lock, flags);
557}
558
559/* Enable/disable transmitters */
560static void ene_tx_set_transmitters(struct ene_device *dev)
561{
562 unsigned long flags;
563
564 spin_lock_irqsave(&dev->hw_lock, flags);
565 ene_set_clear_reg_mask(dev, ENE_GPIOFS8, ENE_GPIOFS8_GPIO41,
566 !!(dev->transmitter_mask & 0x01));
567 ene_set_clear_reg_mask(dev, ENE_GPIOFS1, ENE_GPIOFS1_GPIO0D,
568 !!(dev->transmitter_mask & 0x02));
569 spin_unlock_irqrestore(&dev->hw_lock, flags);
570}
571
572/* prepare transmission */
573static void ene_tx_enable(struct ene_device *dev)
574{
575 u8 conf1 = ene_read_reg(dev, ENE_CIRCFG);
576 u8 fwreg2 = ene_read_reg(dev, ENE_FW2);
577
578 dev->saved_conf1 = conf1;
579
580 /* Show information about currently connected transmitter jacks */
581 if (fwreg2 & ENE_FW2_EMMITER1_CONN)
582 dbg("TX: Transmitter #1 is connected");
583
584 if (fwreg2 & ENE_FW2_EMMITER2_CONN)
585 dbg("TX: Transmitter #2 is connected");
586
587 if (!(fwreg2 & (ENE_FW2_EMMITER1_CONN | ENE_FW2_EMMITER2_CONN)))
Joe Perches7de34612011-08-21 19:56:46 -0300588 pr_warn("TX: transmitter cable isn't connected!\n");
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300589
590 /* disable receive on revc */
591 if (dev->hw_revision == ENE_HW_C)
592 conf1 &= ~ENE_CIRCFG_RX_EN;
593
594 /* Enable TX engine */
595 conf1 |= ENE_CIRCFG_TX_EN | ENE_CIRCFG_TX_IRQ;
596 ene_write_reg(dev, ENE_CIRCFG, conf1);
597}
598
599/* end transmission */
600static void ene_tx_disable(struct ene_device *dev)
601{
602 ene_write_reg(dev, ENE_CIRCFG, dev->saved_conf1);
603 dev->tx_buffer = NULL;
604}
605
606
607/* TX one sample - must be called with dev->hw_lock*/
608static void ene_tx_sample(struct ene_device *dev)
609{
610 u8 raw_tx;
611 u32 sample;
612 bool pulse = dev->tx_sample_pulse;
613
614 if (!dev->tx_buffer) {
Joe Perches7de34612011-08-21 19:56:46 -0300615 pr_warn("TX: BUG: attempt to transmit NULL buffer\n");
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300616 return;
617 }
618
619 /* Grab next TX sample */
620 if (!dev->tx_sample) {
621
622 if (dev->tx_pos == dev->tx_len) {
623 if (!dev->tx_done) {
624 dbg("TX: no more data to send");
625 dev->tx_done = true;
626 goto exit;
627 } else {
628 dbg("TX: last sample sent by hardware");
629 ene_tx_disable(dev);
630 complete(&dev->tx_complete);
631 return;
632 }
633 }
634
635 sample = dev->tx_buffer[dev->tx_pos++];
636 dev->tx_sample_pulse = !dev->tx_sample_pulse;
637
638 dev->tx_sample = DIV_ROUND_CLOSEST(sample, sample_period);
639
640 if (!dev->tx_sample)
641 dev->tx_sample = 1;
642 }
643
644 raw_tx = min(dev->tx_sample , (unsigned int)ENE_CIRRLC_OUT_MASK);
645 dev->tx_sample -= raw_tx;
646
647 dbg("TX: sample %8d (%s)", raw_tx * sample_period,
648 pulse ? "pulse" : "space");
649 if (pulse)
650 raw_tx |= ENE_CIRRLC_OUT_PULSE;
651
652 ene_write_reg(dev,
653 dev->tx_reg ? ENE_CIRRLC_OUT1 : ENE_CIRRLC_OUT0, raw_tx);
654
655 dev->tx_reg = !dev->tx_reg;
656exit:
657 /* simulate TX done interrupt */
658 if (txsim)
659 mod_timer(&dev->tx_sim_timer, jiffies + HZ / 500);
660}
661
662/* timer to simulate tx done interrupt */
Kees Cookb17ec782017-10-24 11:23:14 -0400663static void ene_tx_irqsim(struct timer_list *t)
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300664{
Kees Cookb17ec782017-10-24 11:23:14 -0400665 struct ene_device *dev = from_timer(dev, t, tx_sim_timer);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300666 unsigned long flags;
667
668 spin_lock_irqsave(&dev->hw_lock, flags);
669 ene_tx_sample(dev);
670 spin_unlock_irqrestore(&dev->hw_lock, flags);
671}
672
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300673
674/* read irq status and ack it */
675static int ene_irq_status(struct ene_device *dev)
676{
677 u8 irq_status;
678 u8 fw_flags1, fw_flags2;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300679 int retval = 0;
680
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300681 fw_flags2 = ene_read_reg(dev, ENE_FW2);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300682
683 if (dev->hw_revision < ENE_HW_C) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300684 irq_status = ene_read_reg(dev, ENEB_IRQ_STATUS);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300685
686 if (!(irq_status & ENEB_IRQ_STATUS_IR))
687 return 0;
688
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300689 ene_clear_reg_mask(dev, ENEB_IRQ_STATUS, ENEB_IRQ_STATUS_IR);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300690 return ENE_IRQ_RX;
691 }
692
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300693 irq_status = ene_read_reg(dev, ENE_IRQ);
694 if (!(irq_status & ENE_IRQ_STATUS))
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300695 return 0;
696
697 /* original driver does that twice - a workaround ? */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300698 ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS);
699 ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300700
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300701 /* check RX interrupt */
702 if (fw_flags2 & ENE_FW2_RXIRQ) {
703 retval |= ENE_IRQ_RX;
704 ene_write_reg(dev, ENE_FW2, fw_flags2 & ~ENE_FW2_RXIRQ);
705 }
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300706
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300707 /* check TX interrupt */
708 fw_flags1 = ene_read_reg(dev, ENE_FW1);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300709 if (fw_flags1 & ENE_FW1_TXIRQ) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300710 ene_write_reg(dev, ENE_FW1, fw_flags1 & ~ENE_FW1_TXIRQ);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300711 retval |= ENE_IRQ_TX;
712 }
713
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300714 return retval;
715}
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300716
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300717/* interrupt handler */
718static irqreturn_t ene_isr(int irq, void *data)
719{
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300720 u16 hw_value, reg;
721 int hw_sample, irq_status;
722 bool pulse;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300723 unsigned long flags;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300724 irqreturn_t retval = IRQ_NONE;
725 struct ene_device *dev = (struct ene_device *)data;
Sean Young183e19f2018-08-21 15:57:52 -0400726 struct ir_raw_event ev = {};
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300727
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300728 spin_lock_irqsave(&dev->hw_lock, flags);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300729
730 dbg_verbose("ISR called");
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300731 ene_rx_read_hw_pointer(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300732 irq_status = ene_irq_status(dev);
733
734 if (!irq_status)
735 goto unlock;
736
737 retval = IRQ_HANDLED;
738
739 if (irq_status & ENE_IRQ_TX) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300740 dbg_verbose("TX interrupt");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300741 if (!dev->hw_learning_and_tx_capable) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300742 dbg("TX interrupt on unsupported device!");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300743 goto unlock;
744 }
745 ene_tx_sample(dev);
746 }
747
748 if (!(irq_status & ENE_IRQ_RX))
749 goto unlock;
750
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300751 dbg_verbose("RX interrupt");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300752
Maxim Levitskye1b1ddb2010-10-16 19:56:29 -0300753 if (dev->hw_learning_and_tx_capable)
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300754 ene_rx_sense_carrier(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300755
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300756 /* On hardware that don't support extra buffer we need to trust
757 the interrupt and not track the read pointer */
758 if (!dev->hw_extra_buffer)
759 dev->r_pointer = dev->w_pointer == 0 ? ENE_FW_PACKET_SIZE : 0;
760
761 while (1) {
762
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300763 reg = ene_rx_get_sample_reg(dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300764
765 dbg_verbose("next sample to read at: %04x", reg);
766 if (!reg)
767 break;
768
769 hw_value = ene_read_reg(dev, reg);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300770
771 if (dev->rx_fan_input_inuse) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300772
773 int offset = ENE_FW_SMPL_BUF_FAN - ENE_FW_SAMPLE_BUFFER;
774
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300775 /* read high part of the sample */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300776 hw_value |= ene_read_reg(dev, reg + offset) << 8;
777 pulse = hw_value & ENE_FW_SMPL_BUF_FAN_PLS;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300778
779 /* clear space bit, and other unused bits */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300780 hw_value &= ENE_FW_SMPL_BUF_FAN_MSK;
781 hw_sample = hw_value * ENE_FW_SAMPLE_PERIOD_FAN;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300782
783 } else {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300784 pulse = !(hw_value & ENE_FW_SAMPLE_SPACE);
785 hw_value &= ~ENE_FW_SAMPLE_SPACE;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300786 hw_sample = hw_value * sample_period;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300787
788 if (dev->rx_period_adjust) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300789 hw_sample *= 100;
790 hw_sample /= (100 + dev->rx_period_adjust);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300791 }
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300792 }
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300793
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300794 if (!dev->hw_extra_buffer && !hw_sample) {
795 dev->r_pointer = dev->w_pointer;
796 continue;
797 }
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300798
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300799 dbg("RX: %d (%s)", hw_sample, pulse ? "pulse" : "space");
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300800
Jarod Wilson5aad7242011-01-06 16:59:36 -0300801 ev.duration = US_TO_NS(hw_sample);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300802 ev.pulse = pulse;
David Härdemand8b4b582010-10-29 16:08:23 -0300803 ir_raw_event_store_with_filter(dev->rdev, &ev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300804 }
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300805
David Härdemand8b4b582010-10-29 16:08:23 -0300806 ir_raw_event_handle(dev->rdev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300807unlock:
808 spin_unlock_irqrestore(&dev->hw_lock, flags);
809 return retval;
810}
811
812/* Initialize default settings */
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300813static void ene_setup_default_settings(struct ene_device *dev)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300814{
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300815 dev->tx_period = 32;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300816 dev->tx_duty_cycle = 50; /*%*/
817 dev->transmitter_mask = 0x03;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300818 dev->learning_mode_enabled = learning_mode_force;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300819
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300820 /* Set reasonable default timeout */
Jarod Wilson5aad7242011-01-06 16:59:36 -0300821 dev->rdev->timeout = US_TO_NS(150000);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300822}
823
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300824/* Upload all hardware settings at once. Used at load and resume time */
825static void ene_setup_hw_settings(struct ene_device *dev)
826{
827 if (dev->hw_learning_and_tx_capable) {
828 ene_tx_set_carrier(dev);
829 ene_tx_set_transmitters(dev);
830 }
831
832 ene_rx_setup(dev);
833}
834
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300835/* outside interface: called on first open*/
David Härdemand8b4b582010-10-29 16:08:23 -0300836static int ene_open(struct rc_dev *rdev)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300837{
David Härdemand8b4b582010-10-29 16:08:23 -0300838 struct ene_device *dev = rdev->priv;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300839 unsigned long flags;
840
841 spin_lock_irqsave(&dev->hw_lock, flags);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300842 ene_rx_enable(dev);
843 spin_unlock_irqrestore(&dev->hw_lock, flags);
844 return 0;
845}
846
847/* outside interface: called on device close*/
David Härdemand8b4b582010-10-29 16:08:23 -0300848static void ene_close(struct rc_dev *rdev)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300849{
David Härdemand8b4b582010-10-29 16:08:23 -0300850 struct ene_device *dev = rdev->priv;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300851 unsigned long flags;
852 spin_lock_irqsave(&dev->hw_lock, flags);
853
854 ene_rx_disable(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300855 spin_unlock_irqrestore(&dev->hw_lock, flags);
856}
857
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300858/* outside interface: set transmitter mask */
David Härdemand8b4b582010-10-29 16:08:23 -0300859static int ene_set_tx_mask(struct rc_dev *rdev, u32 tx_mask)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300860{
David Härdemand8b4b582010-10-29 16:08:23 -0300861 struct ene_device *dev = rdev->priv;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300862 dbg("TX: attempt to set transmitter mask %02x", tx_mask);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300863
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300864 /* invalid txmask */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300865 if (!tx_mask || tx_mask & ~0x03) {
866 dbg("TX: invalid mask");
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300867 /* return count of transmitters */
868 return 2;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300869 }
870
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300871 dev->transmitter_mask = tx_mask;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300872 ene_tx_set_transmitters(dev);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300873 return 0;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300874}
875
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300876/* outside interface : set tx carrier */
David Härdemand8b4b582010-10-29 16:08:23 -0300877static int ene_set_tx_carrier(struct rc_dev *rdev, u32 carrier)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300878{
David Härdemand8b4b582010-10-29 16:08:23 -0300879 struct ene_device *dev = rdev->priv;
Dan Carpenter48cafec2012-09-11 07:11:24 -0300880 u32 period;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300881
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300882 dbg("TX: attempt to set tx carrier to %d kHz", carrier);
Dan Carpenter48cafec2012-09-11 07:11:24 -0300883 if (carrier == 0)
884 return -EINVAL;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300885
Dan Carpenter48cafec2012-09-11 07:11:24 -0300886 period = 2000000 / carrier;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300887 if (period && (period > ENE_CIRMOD_PRD_MAX ||
888 period < ENE_CIRMOD_PRD_MIN)) {
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300889
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300890 dbg("TX: out of range %d-%d kHz carrier",
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300891 2000 / ENE_CIRMOD_PRD_MIN, 2000 / ENE_CIRMOD_PRD_MAX);
Sean Young14d81882016-07-10 13:34:33 -0300892 return -EINVAL;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300893 }
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300894
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300895 dev->tx_period = period;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300896 ene_tx_set_carrier(dev);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300897 return 0;
898}
899
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300900/*outside interface : set tx duty cycle */
David Härdemand8b4b582010-10-29 16:08:23 -0300901static int ene_set_tx_duty_cycle(struct rc_dev *rdev, u32 duty_cycle)
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300902{
David Härdemand8b4b582010-10-29 16:08:23 -0300903 struct ene_device *dev = rdev->priv;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300904 dbg("TX: setting duty cycle to %d%%", duty_cycle);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300905 dev->tx_duty_cycle = duty_cycle;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300906 ene_tx_set_carrier(dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300907 return 0;
908}
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300909
910/* outside interface: enable learning mode */
David Härdemand8b4b582010-10-29 16:08:23 -0300911static int ene_set_learning_mode(struct rc_dev *rdev, int enable)
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300912{
David Härdemand8b4b582010-10-29 16:08:23 -0300913 struct ene_device *dev = rdev->priv;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300914 unsigned long flags;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300915 if (enable == dev->learning_mode_enabled)
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300916 return 0;
917
918 spin_lock_irqsave(&dev->hw_lock, flags);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300919 dev->learning_mode_enabled = enable;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300920 ene_rx_disable(dev);
921 ene_rx_setup(dev);
922 ene_rx_enable(dev);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300923 spin_unlock_irqrestore(&dev->hw_lock, flags);
924 return 0;
925}
926
David Härdemand8b4b582010-10-29 16:08:23 -0300927static int ene_set_carrier_report(struct rc_dev *rdev, int enable)
Maxim Levitskye1b1ddb2010-10-16 19:56:29 -0300928{
David Härdemand8b4b582010-10-29 16:08:23 -0300929 struct ene_device *dev = rdev->priv;
Maxim Levitskye1b1ddb2010-10-16 19:56:29 -0300930 unsigned long flags;
931
932 if (enable == dev->carrier_detect_enabled)
933 return 0;
934
935 spin_lock_irqsave(&dev->hw_lock, flags);
936 dev->carrier_detect_enabled = enable;
937 ene_rx_disable(dev);
938 ene_rx_setup(dev);
939 ene_rx_enable(dev);
940 spin_unlock_irqrestore(&dev->hw_lock, flags);
941 return 0;
942}
943
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300944/* outside interface: enable or disable idle mode */
David Härdemand8b4b582010-10-29 16:08:23 -0300945static void ene_set_idle(struct rc_dev *rdev, bool idle)
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300946{
David Härdemand8b4b582010-10-29 16:08:23 -0300947 struct ene_device *dev = rdev->priv;
948
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300949 if (idle) {
David Härdemand8b4b582010-10-29 16:08:23 -0300950 ene_rx_reset(dev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300951 dbg("RX: end of data");
952 }
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300953}
954
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300955/* outside interface: transmit */
David Härdeman5588dc22011-04-28 12:13:58 -0300956static int ene_transmit(struct rc_dev *rdev, unsigned *buf, unsigned n)
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300957{
David Härdemand8b4b582010-10-29 16:08:23 -0300958 struct ene_device *dev = rdev->priv;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300959 unsigned long flags;
960
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300961 dev->tx_buffer = buf;
David Härdeman5588dc22011-04-28 12:13:58 -0300962 dev->tx_len = n;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300963 dev->tx_pos = 0;
964 dev->tx_reg = 0;
965 dev->tx_done = 0;
966 dev->tx_sample = 0;
Mauro Carvalho Chehab2816cc32014-09-03 16:01:36 -0300967 dev->tx_sample_pulse = false;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300968
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300969 dbg("TX: %d samples", dev->tx_len);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300970
971 spin_lock_irqsave(&dev->hw_lock, flags);
972
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300973 ene_tx_enable(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300974
975 /* Transmit first two samples */
976 ene_tx_sample(dev);
977 ene_tx_sample(dev);
978
979 spin_unlock_irqrestore(&dev->hw_lock, flags);
980
981 if (wait_for_completion_timeout(&dev->tx_complete, 2 * HZ) == 0) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300982 dbg("TX: timeout");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300983 spin_lock_irqsave(&dev->hw_lock, flags);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300984 ene_tx_disable(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300985 spin_unlock_irqrestore(&dev->hw_lock, flags);
986 } else
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300987 dbg("TX: done");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300988 return n;
989}
990
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300991/* probe entry */
992static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300993{
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300994 int error = -ENOMEM;
David Härdemand8b4b582010-10-29 16:08:23 -0300995 struct rc_dev *rdev;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300996 struct ene_device *dev;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300997
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300998 /* allocate memory */
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300999 dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL);
Andi Shyti0f7499f2016-12-16 06:50:58 -02001000 rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
David Härdemand8b4b582010-10-29 16:08:23 -03001001 if (!dev || !rdev)
Matthijs Kooijman70ef6992012-11-02 09:13:54 -03001002 goto exit_free_dev_rdev;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001003
1004 /* validate resources */
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001005 error = -ENODEV;
1006
Kyle McMartin2e4c5562011-01-06 16:59:33 -03001007 /* init these to -1, as 0 is valid for both */
1008 dev->hw_io = -1;
1009 dev->irq = -1;
1010
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001011 if (!pnp_port_valid(pnp_dev, 0) ||
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001012 pnp_port_len(pnp_dev, 0) < ENE_IO_SIZE)
Matthijs Kooijman70ef6992012-11-02 09:13:54 -03001013 goto exit_free_dev_rdev;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001014
1015 if (!pnp_irq_valid(pnp_dev, 0))
Matthijs Kooijman70ef6992012-11-02 09:13:54 -03001016 goto exit_free_dev_rdev;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001017
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001018 spin_lock_init(&dev->hw_lock);
1019
Luis Henriquesb31b0212012-06-19 11:29:49 -03001020 dev->hw_io = pnp_port_start(pnp_dev, 0);
Maxim Levitsky1de6ebb2013-07-07 20:22:45 -03001021 dev->irq = pnp_irq(pnp_dev, 0);
1022
Luis Henriquesb31b0212012-06-19 11:29:49 -03001023
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001024 pnp_set_drvdata(pnp_dev, dev);
1025 dev->pnp_dev = pnp_dev;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001026
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001027 /* don't allow too short/long sample periods */
1028 if (sample_period < 5 || sample_period > 0x7F)
1029 sample_period = ENE_DEFAULT_SAMPLE_PERIOD;
1030
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001031 /* detect hardware version and features */
1032 error = ene_hw_detect(dev);
1033 if (error)
Matthijs Kooijman70ef6992012-11-02 09:13:54 -03001034 goto exit_free_dev_rdev;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001035
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001036 if (!dev->hw_learning_and_tx_capable && txsim) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001037 dev->hw_learning_and_tx_capable = true;
Kees Cookb17ec782017-10-24 11:23:14 -04001038 timer_setup(&dev->tx_sim_timer, ene_tx_irqsim, 0);
Joe Perches7de34612011-08-21 19:56:46 -03001039 pr_warn("Simulation of TX activated\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001040 }
1041
Maxim Levitskya06423c2010-10-15 13:06:37 -03001042 if (!dev->hw_learning_and_tx_capable)
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -03001043 learning_mode_force = false;
Maxim Levitskya06423c2010-10-15 13:06:37 -03001044
Sean Young6d741bf2017-08-07 16:20:58 -04001045 rdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
David Härdemand8b4b582010-10-29 16:08:23 -03001046 rdev->priv = dev;
1047 rdev->open = ene_open;
1048 rdev->close = ene_close;
1049 rdev->s_idle = ene_set_idle;
1050 rdev->driver_name = ENE_DRIVER_NAME;
1051 rdev->map_name = RC_MAP_RC6_MCE;
Sean Young518f4b22017-07-01 12:13:19 -04001052 rdev->device_name = "ENE eHome Infrared Remote Receiver";
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001053
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001054 if (dev->hw_learning_and_tx_capable) {
David Härdemand8b4b582010-10-29 16:08:23 -03001055 rdev->s_learning_mode = ene_set_learning_mode;
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001056 init_completion(&dev->tx_complete);
David Härdemand8b4b582010-10-29 16:08:23 -03001057 rdev->tx_ir = ene_transmit;
1058 rdev->s_tx_mask = ene_set_tx_mask;
1059 rdev->s_tx_carrier = ene_set_tx_carrier;
1060 rdev->s_tx_duty_cycle = ene_set_tx_duty_cycle;
1061 rdev->s_carrier_report = ene_set_carrier_report;
Sean Young518f4b22017-07-01 12:13:19 -04001062 rdev->device_name = "ENE eHome Infrared Remote Transceiver";
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001063 }
1064
Kyle McMartin2e4c5562011-01-06 16:59:33 -03001065 dev->rdev = rdev;
1066
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -03001067 ene_rx_setup_hw_buffer(dev);
1068 ene_setup_default_settings(dev);
1069 ene_setup_hw_settings(dev);
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001070
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001071 device_set_wakeup_capable(&pnp_dev->dev, true);
1072 device_set_wakeup_enable(&pnp_dev->dev, true);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001073
Matthijs Kooijman9fa35202012-11-02 09:13:56 -03001074 error = rc_register_device(rdev);
1075 if (error < 0)
1076 goto exit_free_dev_rdev;
1077
Luis Henriques9ef449c2012-04-21 12:25:21 -03001078 /* claim the resources */
1079 error = -EBUSY;
Luis Henriques9ef449c2012-04-21 12:25:21 -03001080 if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
Matthijs Kooijman9fa35202012-11-02 09:13:56 -03001081 goto exit_unregister_device;
Luis Henriques9ef449c2012-04-21 12:25:21 -03001082 }
1083
Luis Henriques9ef449c2012-04-21 12:25:21 -03001084 if (request_irq(dev->irq, ene_isr,
1085 IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) {
Matthijs Kooijman70ef6992012-11-02 09:13:54 -03001086 goto exit_release_hw_io;
Luis Henriques9ef449c2012-04-21 12:25:21 -03001087 }
1088
Joe Perches7de34612011-08-21 19:56:46 -03001089 pr_notice("driver has been successfully loaded\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001090 return 0;
Matthijs Kooijman56411c02012-10-15 07:13:44 -03001091
Matthijs Kooijman70ef6992012-11-02 09:13:54 -03001092exit_release_hw_io:
Matthijs Kooijman56411c02012-10-15 07:13:44 -03001093 release_region(dev->hw_io, ENE_IO_SIZE);
Matthijs Kooijman9fa35202012-11-02 09:13:56 -03001094exit_unregister_device:
1095 rc_unregister_device(rdev);
Wei Yongjundbcd3712013-04-09 05:47:42 -03001096 rdev = NULL;
Matthijs Kooijman70ef6992012-11-02 09:13:54 -03001097exit_free_dev_rdev:
David Härdemand8b4b582010-10-29 16:08:23 -03001098 rc_free_device(rdev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001099 kfree(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001100 return error;
1101}
1102
1103/* main unload function */
1104static void ene_remove(struct pnp_dev *pnp_dev)
1105{
1106 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
1107 unsigned long flags;
1108
1109 spin_lock_irqsave(&dev->hw_lock, flags);
1110 ene_rx_disable(dev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -03001111 ene_rx_restore_hw_buffer(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001112 spin_unlock_irqrestore(&dev->hw_lock, flags);
1113
1114 free_irq(dev->irq, dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001115 release_region(dev->hw_io, ENE_IO_SIZE);
David Härdemand8b4b582010-10-29 16:08:23 -03001116 rc_unregister_device(dev->rdev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001117 kfree(dev);
1118}
1119
1120/* enable wake on IR (wakes on specific button on original remote) */
Maxim Levitskyb5daad22013-07-07 20:22:46 -03001121static void ene_enable_wake(struct ene_device *dev, bool enable)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001122{
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001123 dbg("wake on IR %s", enable ? "enabled" : "disabled");
1124 ene_set_clear_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, enable);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001125}
1126
1127#ifdef CONFIG_PM
1128static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
1129{
1130 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
Maxim Levitskyb5daad22013-07-07 20:22:46 -03001131 bool wake = device_may_wakeup(&dev->pnp_dev->dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001132
Maxim Levitskyb5daad22013-07-07 20:22:46 -03001133 if (!wake && dev->rx_enabled)
1134 ene_rx_disable_hw(dev);
1135
1136 ene_enable_wake(dev, wake);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001137 return 0;
1138}
1139
1140static int ene_resume(struct pnp_dev *pnp_dev)
1141{
1142 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -03001143 ene_setup_hw_settings(dev);
1144
1145 if (dev->rx_enabled)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001146 ene_rx_enable(dev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -03001147
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001148 ene_enable_wake(dev, false);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001149 return 0;
1150}
1151#endif
1152
1153static void ene_shutdown(struct pnp_dev *pnp_dev)
1154{
1155 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001156 ene_enable_wake(dev, true);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001157}
1158
1159static const struct pnp_device_id ene_ids[] = {
1160 {.id = "ENE0100",},
1161 {.id = "ENE0200",},
1162 {.id = "ENE0201",},
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001163 {.id = "ENE0202",},
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001164 {},
1165};
1166
1167static struct pnp_driver ene_driver = {
1168 .name = ENE_DRIVER_NAME,
1169 .id_table = ene_ids,
1170 .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
1171
1172 .probe = ene_probe,
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -08001173 .remove = ene_remove,
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001174#ifdef CONFIG_PM
1175 .suspend = ene_suspend,
1176 .resume = ene_resume,
1177#endif
1178 .shutdown = ene_shutdown,
1179};
1180
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001181module_param(sample_period, int, S_IRUGO);
1182MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)");
1183
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -03001184module_param(learning_mode_force, bool, S_IRUGO);
1185MODULE_PARM_DESC(learning_mode_force, "Enable learning mode by default");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001186
1187module_param(debug, int, S_IRUGO | S_IWUSR);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001188MODULE_PARM_DESC(debug, "Debug level");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001189
1190module_param(txsim, bool, S_IRUGO);
1191MODULE_PARM_DESC(txsim,
1192 "Simulate TX features on unsupported hardware (dangerous)");
1193
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001194MODULE_DEVICE_TABLE(pnp, ene_ids);
1195MODULE_DESCRIPTION
Mauro Carvalho Chehab25ec5872016-10-18 17:44:25 -02001196 ("Infrared input driver for KB3926B/C/D/E/F (aka ENE0100/ENE0200/ENE0201/ENE0202) CIR port");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001197
1198MODULE_AUTHOR("Maxim Levitsky");
1199MODULE_LICENSE("GPL");
1200
Peter Hueweaf638a02015-03-16 21:46:34 +01001201module_pnp_driver(ene_driver);