blob: 60da963f40dca448b0cab7269de5e11724fa6a03 [file] [log] [blame]
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001/*
Maxim Levitsky11b64d32010-09-06 18:26:11 -03002 * driver for ENE KB3926 B/C/D/E/F CIR (pnp id: ENE0XXX)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03003 *
4 * Copyright (C) 2010 Maxim Levitsky <maximlevitsky@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
Maxim Levitsky11b64d32010-09-06 18:26:11 -030016 * Special thanks to:
17 * Sami R. <maesesami@gmail.com> for lot of help in debugging and therefore
18 * bringing to life support for transmission & learning mode.
19 *
20 * Charlie Andrews <charliethepilot@googlemail.com> for lots of help in
21 * bringing up the support of new firmware buffer that is popular
22 * on latest notebooks
23 *
24 * ENE for partial device documentation
25 *
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030026 */
27
Joe Perches7de34612011-08-21 19:56:46 -030028#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
29
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030030#include <linux/kernel.h>
31#include <linux/module.h>
32#include <linux/pnp.h>
33#include <linux/io.h>
34#include <linux/interrupt.h>
35#include <linux/sched.h>
Maxim Levitsky931e39a2010-07-31 11:59:26 -030036#include <linux/slab.h>
Mauro Carvalho Chehab6bda9642010-11-17 13:28:38 -030037#include <media/rc-core.h>
Maxim Levitsky931e39a2010-07-31 11:59:26 -030038#include "ene_ir.h"
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030039
Maxim Levitsky11b64d32010-09-06 18:26:11 -030040static int sample_period;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -030041static bool learning_mode_force;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030042static int debug;
Maxim Levitsky11b64d32010-09-06 18:26:11 -030043static bool txsim;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030044
Maxim Levitsky11b64d32010-09-06 18:26:11 -030045static void ene_set_reg_addr(struct ene_device *dev, u16 reg)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030046{
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030047 outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
48 outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
Maxim Levitsky11b64d32010-09-06 18:26:11 -030049}
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030050
Maxim Levitsky11b64d32010-09-06 18:26:11 -030051/* read a hardware register */
52static u8 ene_read_reg(struct ene_device *dev, u16 reg)
53{
54 u8 retval;
55 ene_set_reg_addr(dev, reg);
56 retval = inb(dev->hw_io + ENE_IO);
57 dbg_regs("reg %04x == %02x", reg, retval);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030058 return retval;
59}
60
61/* write a hardware register */
Maxim Levitsky11b64d32010-09-06 18:26:11 -030062static void ene_write_reg(struct ene_device *dev, u16 reg, u8 value)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030063{
Maxim Levitsky11b64d32010-09-06 18:26:11 -030064 dbg_regs("reg %04x <- %02x", reg, value);
65 ene_set_reg_addr(dev, reg);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030066 outb(value, dev->hw_io + ENE_IO);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030067}
68
Maxim Levitsky11b64d32010-09-06 18:26:11 -030069/* Set bits in hardware register */
70static void ene_set_reg_mask(struct ene_device *dev, u16 reg, u8 mask)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030071{
Maxim Levitsky11b64d32010-09-06 18:26:11 -030072 dbg_regs("reg %04x |= %02x", reg, mask);
73 ene_set_reg_addr(dev, reg);
74 outb(inb(dev->hw_io + ENE_IO) | mask, dev->hw_io + ENE_IO);
75}
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030076
Maxim Levitsky11b64d32010-09-06 18:26:11 -030077/* Clear bits in hardware register */
78static void ene_clear_reg_mask(struct ene_device *dev, u16 reg, u8 mask)
79{
80 dbg_regs("reg %04x &= ~%02x ", reg, mask);
81 ene_set_reg_addr(dev, reg);
82 outb(inb(dev->hw_io + ENE_IO) & ~mask, dev->hw_io + ENE_IO);
83}
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030084
Maxim Levitsky11b64d32010-09-06 18:26:11 -030085/* A helper to set/clear a bit in register according to boolean variable */
86static void ene_set_clear_reg_mask(struct ene_device *dev, u16 reg, u8 mask,
87 bool set)
88{
89 if (set)
90 ene_set_reg_mask(dev, reg, mask);
91 else
92 ene_clear_reg_mask(dev, reg, mask);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030093}
94
95/* detect hardware features */
96static int ene_hw_detect(struct ene_device *dev)
97{
98 u8 chip_major, chip_minor;
99 u8 hw_revision, old_ver;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300100 u8 fw_reg2, fw_reg1;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300101
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300102 ene_clear_reg_mask(dev, ENE_ECSTS, ENE_ECSTS_RSRVD);
103 chip_major = ene_read_reg(dev, ENE_ECVER_MAJOR);
104 chip_minor = ene_read_reg(dev, ENE_ECVER_MINOR);
105 ene_set_reg_mask(dev, ENE_ECSTS, ENE_ECSTS_RSRVD);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300106
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300107 hw_revision = ene_read_reg(dev, ENE_ECHV);
108 old_ver = ene_read_reg(dev, ENE_HW_VER_OLD);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300109
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300110 dev->pll_freq = (ene_read_reg(dev, ENE_PLLFRH) << 4) +
111 (ene_read_reg(dev, ENE_PLLFRL) >> 4);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300112
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300113 if (sample_period != ENE_DEFAULT_SAMPLE_PERIOD)
114 dev->rx_period_adjust =
115 dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 2 : 4;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300116
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300117 if (hw_revision == 0xFF) {
Joe Perches7de34612011-08-21 19:56:46 -0300118 pr_warn("device seems to be disabled\n");
119 pr_warn("send a mail to lirc-list@lists.sourceforge.net\n");
120 pr_warn("please attach output of acpidump and dmidecode\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300121 return -ENODEV;
122 }
123
Joe Perches7de34612011-08-21 19:56:46 -0300124 pr_notice("chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x\n",
125 chip_major, chip_minor, old_ver, hw_revision);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300126
Joe Perches7de34612011-08-21 19:56:46 -0300127 pr_notice("PLL freq = %d\n", dev->pll_freq);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300128
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300129 if (chip_major == 0x33) {
Joe Perches7de34612011-08-21 19:56:46 -0300130 pr_warn("chips 0x33xx aren't supported\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300131 return -ENODEV;
132 }
133
134 if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) {
135 dev->hw_revision = ENE_HW_C;
Joe Perches7de34612011-08-21 19:56:46 -0300136 pr_notice("KB3926C detected\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300137 } else if (old_ver == 0x24 && hw_revision == 0xC0) {
138 dev->hw_revision = ENE_HW_B;
Joe Perches7de34612011-08-21 19:56:46 -0300139 pr_notice("KB3926B detected\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300140 } else {
141 dev->hw_revision = ENE_HW_D;
Joe Perches7de34612011-08-21 19:56:46 -0300142 pr_notice("KB3926D or higher detected\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300143 }
144
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300145 /* detect features hardware supports */
146 if (dev->hw_revision < ENE_HW_C)
147 return 0;
148
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300149 fw_reg1 = ene_read_reg(dev, ENE_FW1);
150 fw_reg2 = ene_read_reg(dev, ENE_FW2);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300151
Joe Perches7de34612011-08-21 19:56:46 -0300152 pr_notice("Firmware regs: %02x %02x\n", fw_reg1, fw_reg2);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300153
Maxim Levitskya06423c2010-10-15 13:06:37 -0300154 dev->hw_use_gpio_0a = !!(fw_reg2 & ENE_FW2_GP0A);
155 dev->hw_learning_and_tx_capable = !!(fw_reg2 & ENE_FW2_LEARNING);
156 dev->hw_extra_buffer = !!(fw_reg1 & ENE_FW1_HAS_EXTRA_BUF);
157
158 if (dev->hw_learning_and_tx_capable)
159 dev->hw_fan_input = !!(fw_reg2 & ENE_FW2_FAN_INPUT);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300160
Joe Perches7de34612011-08-21 19:56:46 -0300161 pr_notice("Hardware features:\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300162
163 if (dev->hw_learning_and_tx_capable) {
Joe Perches7de34612011-08-21 19:56:46 -0300164 pr_notice("* Supports transmitting & learning mode\n");
165 pr_notice(" This feature is rare and therefore,\n");
166 pr_notice(" you are welcome to test it,\n");
167 pr_notice(" and/or contact the author via:\n");
168 pr_notice(" lirc-list@lists.sourceforge.net\n");
169 pr_notice(" or maximlevitsky@gmail.com\n");
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300170
Joe Perches7de34612011-08-21 19:56:46 -0300171 pr_notice("* Uses GPIO %s for IR raw input\n",
172 dev->hw_use_gpio_0a ? "40" : "0A");
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300173
174 if (dev->hw_fan_input)
Joe Perches7de34612011-08-21 19:56:46 -0300175 pr_notice("* Uses unused fan feedback input as source of demodulated IR data\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300176 }
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300177
178 if (!dev->hw_fan_input)
Joe Perches7de34612011-08-21 19:56:46 -0300179 pr_notice("* Uses GPIO %s for IR demodulated input\n",
180 dev->hw_use_gpio_0a ? "0A" : "40");
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300181
182 if (dev->hw_extra_buffer)
Joe Perches7de34612011-08-21 19:56:46 -0300183 pr_notice("* Uses new style input buffer\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300184 return 0;
185}
186
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300187/* Read properities of hw sample buffer */
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300188static void ene_rx_setup_hw_buffer(struct ene_device *dev)
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300189{
190 u16 tmp;
191
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300192 ene_rx_read_hw_pointer(dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300193 dev->r_pointer = dev->w_pointer;
194
195 if (!dev->hw_extra_buffer) {
196 dev->buffer_len = ENE_FW_PACKET_SIZE * 2;
197 return;
198 }
199
200 tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER);
201 tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER+1) << 8;
202 dev->extra_buf1_address = tmp;
203
204 dev->extra_buf1_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 2);
205
206 tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 3);
207 tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 4) << 8;
208 dev->extra_buf2_address = tmp;
209
210 dev->extra_buf2_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 5);
211
212 dev->buffer_len = dev->extra_buf1_len + dev->extra_buf2_len + 8;
213
Joe Perches7de34612011-08-21 19:56:46 -0300214 pr_notice("Hardware uses 2 extended buffers:\n");
215 pr_notice(" 0x%04x - len : %d\n",
216 dev->extra_buf1_address, dev->extra_buf1_len);
217 pr_notice(" 0x%04x - len : %d\n",
218 dev->extra_buf2_address, dev->extra_buf2_len);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300219
Joe Perches7de34612011-08-21 19:56:46 -0300220 pr_notice("Total buffer len = %d\n", dev->buffer_len);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300221
222 if (dev->buffer_len > 64 || dev->buffer_len < 16)
223 goto error;
224
225 if (dev->extra_buf1_address > 0xFBFC ||
226 dev->extra_buf1_address < 0xEC00)
227 goto error;
228
229 if (dev->extra_buf2_address > 0xFBFC ||
230 dev->extra_buf2_address < 0xEC00)
231 goto error;
232
233 if (dev->r_pointer > dev->buffer_len)
234 goto error;
235
236 ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
237 return;
238error:
Joe Perches7de34612011-08-21 19:56:46 -0300239 pr_warn("Error validating extra buffers, device probably won't work\n");
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300240 dev->hw_extra_buffer = false;
241 ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
242}
243
244
245/* Restore the pointers to extra buffers - to make module reload work*/
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300246static void ene_rx_restore_hw_buffer(struct ene_device *dev)
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300247{
248 if (!dev->hw_extra_buffer)
249 return;
250
251 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 0,
252 dev->extra_buf1_address & 0xFF);
253 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 1,
254 dev->extra_buf1_address >> 8);
255 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 2, dev->extra_buf1_len);
256
257 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 3,
258 dev->extra_buf2_address & 0xFF);
259 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 4,
260 dev->extra_buf2_address >> 8);
261 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 5,
262 dev->extra_buf2_len);
263 ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
264}
265
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300266/* Read hardware write pointer */
267static void ene_rx_read_hw_pointer(struct ene_device *dev)
268{
269 if (dev->hw_extra_buffer)
270 dev->w_pointer = ene_read_reg(dev, ENE_FW_RX_POINTER);
271 else
272 dev->w_pointer = ene_read_reg(dev, ENE_FW2)
273 & ENE_FW2_BUF_WPTR ? 0 : ENE_FW_PACKET_SIZE;
274
275 dbg_verbose("RB: HW write pointer: %02x, driver read pointer: %02x",
276 dev->w_pointer, dev->r_pointer);
277}
278
279/* Gets address of next sample from HW ring buffer */
280static int ene_rx_get_sample_reg(struct ene_device *dev)
281{
282 int r_pointer;
283
284 if (dev->r_pointer == dev->w_pointer) {
285 dbg_verbose("RB: hit end, try update w_pointer");
286 ene_rx_read_hw_pointer(dev);
287 }
288
289 if (dev->r_pointer == dev->w_pointer) {
290 dbg_verbose("RB: end of data at %d", dev->r_pointer);
291 return 0;
292 }
293
294 dbg_verbose("RB: reading at offset %d", dev->r_pointer);
295 r_pointer = dev->r_pointer;
296
297 dev->r_pointer++;
298 if (dev->r_pointer == dev->buffer_len)
299 dev->r_pointer = 0;
300
301 dbg_verbose("RB: next read will be from offset %d", dev->r_pointer);
302
303 if (r_pointer < 8) {
304 dbg_verbose("RB: read at main buffer at %d", r_pointer);
305 return ENE_FW_SAMPLE_BUFFER + r_pointer;
306 }
307
308 r_pointer -= 8;
309
310 if (r_pointer < dev->extra_buf1_len) {
311 dbg_verbose("RB: read at 1st extra buffer at %d", r_pointer);
312 return dev->extra_buf1_address + r_pointer;
313 }
314
315 r_pointer -= dev->extra_buf1_len;
316
317 if (r_pointer < dev->extra_buf2_len) {
318 dbg_verbose("RB: read at 2nd extra buffer at %d", r_pointer);
319 return dev->extra_buf2_address + r_pointer;
320 }
321
Paul Bolle90802ed2011-12-05 13:00:34 +0100322 dbg("attempt to read beyond ring buffer end");
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300323 return 0;
324}
325
326/* Sense current received carrier */
Mauro Carvalho Chehabe03cd642012-10-27 13:46:53 -0300327static void ene_rx_sense_carrier(struct ene_device *dev)
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300328{
329 DEFINE_IR_RAW_EVENT(ev);
330
331 int carrier, duty_cycle;
332 int period = ene_read_reg(dev, ENE_CIRCAR_PRD);
333 int hperiod = ene_read_reg(dev, ENE_CIRCAR_HPRD);
334
335 if (!(period & ENE_CIRCAR_PRD_VALID))
336 return;
337
338 period &= ~ENE_CIRCAR_PRD_VALID;
339
340 if (!period)
341 return;
342
343 dbg("RX: hardware carrier period = %02x", period);
344 dbg("RX: hardware carrier pulse period = %02x", hperiod);
345
346 carrier = 2000000 / period;
347 duty_cycle = (hperiod * 100) / period;
348 dbg("RX: sensed carrier = %d Hz, duty cycle %d%%",
349 carrier, duty_cycle);
350 if (dev->carrier_detect_enabled) {
351 ev.carrier_report = true;
352 ev.carrier = carrier;
353 ev.duty_cycle = duty_cycle;
David Härdemand8b4b582010-10-29 16:08:23 -0300354 ir_raw_event_store(dev->rdev, &ev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300355 }
356}
357
358/* this enables/disables the CIR RX engine */
359static void ene_rx_enable_cir_engine(struct ene_device *dev, bool enable)
360{
361 ene_set_clear_reg_mask(dev, ENE_CIRCFG,
362 ENE_CIRCFG_RX_EN | ENE_CIRCFG_RX_IRQ, enable);
363}
364
365/* this selects input for CIR engine. Ether GPIO 0A or GPIO40*/
366static void ene_rx_select_input(struct ene_device *dev, bool gpio_0a)
367{
368 ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_GPIO0A, gpio_0a);
369}
370
371/*
372 * this enables alternative input via fan tachometer sensor and bypasses
373 * the hw CIR engine
374 */
375static void ene_rx_enable_fan_input(struct ene_device *dev, bool enable)
376{
377 if (!dev->hw_fan_input)
378 return;
379
380 if (!enable)
381 ene_write_reg(dev, ENE_FAN_AS_IN1, 0);
382 else {
383 ene_write_reg(dev, ENE_FAN_AS_IN1, ENE_FAN_AS_IN1_EN);
384 ene_write_reg(dev, ENE_FAN_AS_IN2, ENE_FAN_AS_IN2_EN);
385 }
386}
387
388/* setup the receiver for RX*/
389static void ene_rx_setup(struct ene_device *dev)
390{
391 bool learning_mode = dev->learning_mode_enabled ||
392 dev->carrier_detect_enabled;
393 int sample_period_adjust = 0;
394
395 dbg("RX: setup receiver, learning mode = %d", learning_mode);
396
397
398 /* This selects RLC input and clears CFG2 settings */
399 ene_write_reg(dev, ENE_CIRCFG2, 0x00);
400
401 /* set sample period*/
402 if (sample_period == ENE_DEFAULT_SAMPLE_PERIOD)
403 sample_period_adjust =
404 dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 1 : 2;
405
406 ene_write_reg(dev, ENE_CIRRLC_CFG,
407 (sample_period + sample_period_adjust) |
408 ENE_CIRRLC_CFG_OVERFLOW);
409 /* revB doesn't support inputs */
410 if (dev->hw_revision < ENE_HW_C)
411 goto select_timeout;
412
413 if (learning_mode) {
414
415 WARN_ON(!dev->hw_learning_and_tx_capable);
416
417 /* Enable the opposite of the normal input
418 That means that if GPIO40 is normally used, use GPIO0A
419 and vice versa.
420 This input will carry non demodulated
421 signal, and we will tell the hw to demodulate it itself */
422 ene_rx_select_input(dev, !dev->hw_use_gpio_0a);
423 dev->rx_fan_input_inuse = false;
424
425 /* Enable carrier demodulation */
426 ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD);
427
428 /* Enable carrier detection */
429 ene_write_reg(dev, ENE_CIRCAR_PULS, 0x63);
430 ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT,
431 dev->carrier_detect_enabled || debug);
432 } else {
433 if (dev->hw_fan_input)
434 dev->rx_fan_input_inuse = true;
435 else
436 ene_rx_select_input(dev, dev->hw_use_gpio_0a);
437
438 /* Disable carrier detection & demodulation */
439 ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD);
440 ene_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT);
441 }
442
443select_timeout:
444 if (dev->rx_fan_input_inuse) {
Jarod Wilson5aad7242011-01-06 16:59:36 -0300445 dev->rdev->rx_resolution = US_TO_NS(ENE_FW_SAMPLE_PERIOD_FAN);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300446
447 /* Fan input doesn't support timeouts, it just ends the
448 input with a maximum sample */
David Härdemand8b4b582010-10-29 16:08:23 -0300449 dev->rdev->min_timeout = dev->rdev->max_timeout =
Jarod Wilson5aad7242011-01-06 16:59:36 -0300450 US_TO_NS(ENE_FW_SMPL_BUF_FAN_MSK *
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300451 ENE_FW_SAMPLE_PERIOD_FAN);
452 } else {
Jarod Wilson5aad7242011-01-06 16:59:36 -0300453 dev->rdev->rx_resolution = US_TO_NS(sample_period);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300454
455 /* Theoreticly timeout is unlimited, but we cap it
456 * because it was seen that on one device, it
457 * would stop sending spaces after around 250 msec.
458 * Besides, this is close to 2^32 anyway and timeout is u32.
459 */
Jarod Wilson5aad7242011-01-06 16:59:36 -0300460 dev->rdev->min_timeout = US_TO_NS(127 * sample_period);
461 dev->rdev->max_timeout = US_TO_NS(200000);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300462 }
463
464 if (dev->hw_learning_and_tx_capable)
Jarod Wilson5aad7242011-01-06 16:59:36 -0300465 dev->rdev->tx_resolution = US_TO_NS(sample_period);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300466
David Härdemand8b4b582010-10-29 16:08:23 -0300467 if (dev->rdev->timeout > dev->rdev->max_timeout)
468 dev->rdev->timeout = dev->rdev->max_timeout;
469 if (dev->rdev->timeout < dev->rdev->min_timeout)
470 dev->rdev->timeout = dev->rdev->min_timeout;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300471}
472
473/* Enable the device for receive */
Maxim Levitskyb5daad22013-07-07 20:22:46 -0300474static void ene_rx_enable_hw(struct ene_device *dev)
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300475{
476 u8 reg_value;
477
478 /* Enable system interrupt */
479 if (dev->hw_revision < ENE_HW_C) {
480 ene_write_reg(dev, ENEB_IRQ, dev->irq << 1);
481 ene_write_reg(dev, ENEB_IRQ_UNK1, 0x01);
482 } else {
483 reg_value = ene_read_reg(dev, ENE_IRQ) & 0xF0;
484 reg_value |= ENE_IRQ_UNK_EN;
485 reg_value &= ~ENE_IRQ_STATUS;
486 reg_value |= (dev->irq & ENE_IRQ_MASK);
487 ene_write_reg(dev, ENE_IRQ, reg_value);
488 }
489
490 /* Enable inputs */
491 ene_rx_enable_fan_input(dev, dev->rx_fan_input_inuse);
492 ene_rx_enable_cir_engine(dev, !dev->rx_fan_input_inuse);
493
494 /* ack any pending irqs - just in case */
495 ene_irq_status(dev);
496
497 /* enable firmware bits */
498 ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ);
499
500 /* enter idle mode */
David Härdemand8b4b582010-10-29 16:08:23 -0300501 ir_raw_event_set_idle(dev->rdev, true);
Maxim Levitskyb5daad22013-07-07 20:22:46 -0300502}
503
504/* Enable the device for receive - wrapper to track the state*/
505static void ene_rx_enable(struct ene_device *dev)
506{
507 ene_rx_enable_hw(dev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300508 dev->rx_enabled = true;
509}
510
511/* Disable the device receiver */
Maxim Levitskyb5daad22013-07-07 20:22:46 -0300512static void ene_rx_disable_hw(struct ene_device *dev)
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300513{
514 /* disable inputs */
515 ene_rx_enable_cir_engine(dev, false);
516 ene_rx_enable_fan_input(dev, false);
517
518 /* disable hardware IRQ and firmware flag */
519 ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ);
David Härdemand8b4b582010-10-29 16:08:23 -0300520 ir_raw_event_set_idle(dev->rdev, true);
Maxim Levitskyb5daad22013-07-07 20:22:46 -0300521}
522
523/* Disable the device receiver - wrapper to track the state */
524static void ene_rx_disable(struct ene_device *dev)
525{
526 ene_rx_disable_hw(dev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300527 dev->rx_enabled = false;
528}
529
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300530/* This resets the receiver. Useful to stop stream of spaces at end of
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300531 * transmission
532 */
533static void ene_rx_reset(struct ene_device *dev)
534{
535 ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
536 ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
537}
538
539/* Set up the TX carrier frequency and duty cycle */
540static void ene_tx_set_carrier(struct ene_device *dev)
541{
542 u8 tx_puls_width;
543 unsigned long flags;
544
545 spin_lock_irqsave(&dev->hw_lock, flags);
546
547 ene_set_clear_reg_mask(dev, ENE_CIRCFG,
548 ENE_CIRCFG_TX_CARR, dev->tx_period > 0);
549
550 if (!dev->tx_period)
551 goto unlock;
552
553 BUG_ON(dev->tx_duty_cycle >= 100 || dev->tx_duty_cycle <= 0);
554
555 tx_puls_width = dev->tx_period / (100 / dev->tx_duty_cycle);
556
557 if (!tx_puls_width)
558 tx_puls_width = 1;
559
560 dbg("TX: pulse distance = %d * 500 ns", dev->tx_period);
561 dbg("TX: pulse width = %d * 500 ns", tx_puls_width);
562
563 ene_write_reg(dev, ENE_CIRMOD_PRD, dev->tx_period | ENE_CIRMOD_PRD_POL);
564 ene_write_reg(dev, ENE_CIRMOD_HPRD, tx_puls_width);
565unlock:
566 spin_unlock_irqrestore(&dev->hw_lock, flags);
567}
568
569/* Enable/disable transmitters */
570static void ene_tx_set_transmitters(struct ene_device *dev)
571{
572 unsigned long flags;
573
574 spin_lock_irqsave(&dev->hw_lock, flags);
575 ene_set_clear_reg_mask(dev, ENE_GPIOFS8, ENE_GPIOFS8_GPIO41,
576 !!(dev->transmitter_mask & 0x01));
577 ene_set_clear_reg_mask(dev, ENE_GPIOFS1, ENE_GPIOFS1_GPIO0D,
578 !!(dev->transmitter_mask & 0x02));
579 spin_unlock_irqrestore(&dev->hw_lock, flags);
580}
581
582/* prepare transmission */
583static void ene_tx_enable(struct ene_device *dev)
584{
585 u8 conf1 = ene_read_reg(dev, ENE_CIRCFG);
586 u8 fwreg2 = ene_read_reg(dev, ENE_FW2);
587
588 dev->saved_conf1 = conf1;
589
590 /* Show information about currently connected transmitter jacks */
591 if (fwreg2 & ENE_FW2_EMMITER1_CONN)
592 dbg("TX: Transmitter #1 is connected");
593
594 if (fwreg2 & ENE_FW2_EMMITER2_CONN)
595 dbg("TX: Transmitter #2 is connected");
596
597 if (!(fwreg2 & (ENE_FW2_EMMITER1_CONN | ENE_FW2_EMMITER2_CONN)))
Joe Perches7de34612011-08-21 19:56:46 -0300598 pr_warn("TX: transmitter cable isn't connected!\n");
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300599
600 /* disable receive on revc */
601 if (dev->hw_revision == ENE_HW_C)
602 conf1 &= ~ENE_CIRCFG_RX_EN;
603
604 /* Enable TX engine */
605 conf1 |= ENE_CIRCFG_TX_EN | ENE_CIRCFG_TX_IRQ;
606 ene_write_reg(dev, ENE_CIRCFG, conf1);
607}
608
609/* end transmission */
610static void ene_tx_disable(struct ene_device *dev)
611{
612 ene_write_reg(dev, ENE_CIRCFG, dev->saved_conf1);
613 dev->tx_buffer = NULL;
614}
615
616
617/* TX one sample - must be called with dev->hw_lock*/
618static void ene_tx_sample(struct ene_device *dev)
619{
620 u8 raw_tx;
621 u32 sample;
622 bool pulse = dev->tx_sample_pulse;
623
624 if (!dev->tx_buffer) {
Joe Perches7de34612011-08-21 19:56:46 -0300625 pr_warn("TX: BUG: attempt to transmit NULL buffer\n");
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300626 return;
627 }
628
629 /* Grab next TX sample */
630 if (!dev->tx_sample) {
631
632 if (dev->tx_pos == dev->tx_len) {
633 if (!dev->tx_done) {
634 dbg("TX: no more data to send");
635 dev->tx_done = true;
636 goto exit;
637 } else {
638 dbg("TX: last sample sent by hardware");
639 ene_tx_disable(dev);
640 complete(&dev->tx_complete);
641 return;
642 }
643 }
644
645 sample = dev->tx_buffer[dev->tx_pos++];
646 dev->tx_sample_pulse = !dev->tx_sample_pulse;
647
648 dev->tx_sample = DIV_ROUND_CLOSEST(sample, sample_period);
649
650 if (!dev->tx_sample)
651 dev->tx_sample = 1;
652 }
653
654 raw_tx = min(dev->tx_sample , (unsigned int)ENE_CIRRLC_OUT_MASK);
655 dev->tx_sample -= raw_tx;
656
657 dbg("TX: sample %8d (%s)", raw_tx * sample_period,
658 pulse ? "pulse" : "space");
659 if (pulse)
660 raw_tx |= ENE_CIRRLC_OUT_PULSE;
661
662 ene_write_reg(dev,
663 dev->tx_reg ? ENE_CIRRLC_OUT1 : ENE_CIRRLC_OUT0, raw_tx);
664
665 dev->tx_reg = !dev->tx_reg;
666exit:
667 /* simulate TX done interrupt */
668 if (txsim)
669 mod_timer(&dev->tx_sim_timer, jiffies + HZ / 500);
670}
671
672/* timer to simulate tx done interrupt */
673static void ene_tx_irqsim(unsigned long data)
674{
675 struct ene_device *dev = (struct ene_device *)data;
676 unsigned long flags;
677
678 spin_lock_irqsave(&dev->hw_lock, flags);
679 ene_tx_sample(dev);
680 spin_unlock_irqrestore(&dev->hw_lock, flags);
681}
682
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300683
684/* read irq status and ack it */
685static int ene_irq_status(struct ene_device *dev)
686{
687 u8 irq_status;
688 u8 fw_flags1, fw_flags2;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300689 int retval = 0;
690
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300691 fw_flags2 = ene_read_reg(dev, ENE_FW2);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300692
693 if (dev->hw_revision < ENE_HW_C) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300694 irq_status = ene_read_reg(dev, ENEB_IRQ_STATUS);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300695
696 if (!(irq_status & ENEB_IRQ_STATUS_IR))
697 return 0;
698
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300699 ene_clear_reg_mask(dev, ENEB_IRQ_STATUS, ENEB_IRQ_STATUS_IR);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300700 return ENE_IRQ_RX;
701 }
702
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300703 irq_status = ene_read_reg(dev, ENE_IRQ);
704 if (!(irq_status & ENE_IRQ_STATUS))
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300705 return 0;
706
707 /* original driver does that twice - a workaround ? */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300708 ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS);
709 ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300710
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300711 /* check RX interrupt */
712 if (fw_flags2 & ENE_FW2_RXIRQ) {
713 retval |= ENE_IRQ_RX;
714 ene_write_reg(dev, ENE_FW2, fw_flags2 & ~ENE_FW2_RXIRQ);
715 }
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300716
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300717 /* check TX interrupt */
718 fw_flags1 = ene_read_reg(dev, ENE_FW1);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300719 if (fw_flags1 & ENE_FW1_TXIRQ) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300720 ene_write_reg(dev, ENE_FW1, fw_flags1 & ~ENE_FW1_TXIRQ);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300721 retval |= ENE_IRQ_TX;
722 }
723
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300724 return retval;
725}
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300726
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300727/* interrupt handler */
728static irqreturn_t ene_isr(int irq, void *data)
729{
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300730 u16 hw_value, reg;
731 int hw_sample, irq_status;
732 bool pulse;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300733 unsigned long flags;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300734 irqreturn_t retval = IRQ_NONE;
735 struct ene_device *dev = (struct ene_device *)data;
Maxim Levitsky46519182010-10-16 19:56:28 -0300736 DEFINE_IR_RAW_EVENT(ev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300737
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300738 spin_lock_irqsave(&dev->hw_lock, flags);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300739
740 dbg_verbose("ISR called");
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300741 ene_rx_read_hw_pointer(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300742 irq_status = ene_irq_status(dev);
743
744 if (!irq_status)
745 goto unlock;
746
747 retval = IRQ_HANDLED;
748
749 if (irq_status & ENE_IRQ_TX) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300750 dbg_verbose("TX interrupt");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300751 if (!dev->hw_learning_and_tx_capable) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300752 dbg("TX interrupt on unsupported device!");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300753 goto unlock;
754 }
755 ene_tx_sample(dev);
756 }
757
758 if (!(irq_status & ENE_IRQ_RX))
759 goto unlock;
760
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300761 dbg_verbose("RX interrupt");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300762
Maxim Levitskye1b1ddb2010-10-16 19:56:29 -0300763 if (dev->hw_learning_and_tx_capable)
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300764 ene_rx_sense_carrier(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300765
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300766 /* On hardware that don't support extra buffer we need to trust
767 the interrupt and not track the read pointer */
768 if (!dev->hw_extra_buffer)
769 dev->r_pointer = dev->w_pointer == 0 ? ENE_FW_PACKET_SIZE : 0;
770
771 while (1) {
772
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300773 reg = ene_rx_get_sample_reg(dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300774
775 dbg_verbose("next sample to read at: %04x", reg);
776 if (!reg)
777 break;
778
779 hw_value = ene_read_reg(dev, reg);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300780
781 if (dev->rx_fan_input_inuse) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300782
783 int offset = ENE_FW_SMPL_BUF_FAN - ENE_FW_SAMPLE_BUFFER;
784
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300785 /* read high part of the sample */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300786 hw_value |= ene_read_reg(dev, reg + offset) << 8;
787 pulse = hw_value & ENE_FW_SMPL_BUF_FAN_PLS;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300788
789 /* clear space bit, and other unused bits */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300790 hw_value &= ENE_FW_SMPL_BUF_FAN_MSK;
791 hw_sample = hw_value * ENE_FW_SAMPLE_PERIOD_FAN;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300792
793 } else {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300794 pulse = !(hw_value & ENE_FW_SAMPLE_SPACE);
795 hw_value &= ~ENE_FW_SAMPLE_SPACE;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300796 hw_sample = hw_value * sample_period;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300797
798 if (dev->rx_period_adjust) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300799 hw_sample *= 100;
800 hw_sample /= (100 + dev->rx_period_adjust);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300801 }
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300802 }
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300803
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300804 if (!dev->hw_extra_buffer && !hw_sample) {
805 dev->r_pointer = dev->w_pointer;
806 continue;
807 }
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300808
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300809 dbg("RX: %d (%s)", hw_sample, pulse ? "pulse" : "space");
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300810
Jarod Wilson5aad7242011-01-06 16:59:36 -0300811 ev.duration = US_TO_NS(hw_sample);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300812 ev.pulse = pulse;
David Härdemand8b4b582010-10-29 16:08:23 -0300813 ir_raw_event_store_with_filter(dev->rdev, &ev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300814 }
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300815
David Härdemand8b4b582010-10-29 16:08:23 -0300816 ir_raw_event_handle(dev->rdev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300817unlock:
818 spin_unlock_irqrestore(&dev->hw_lock, flags);
819 return retval;
820}
821
822/* Initialize default settings */
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300823static void ene_setup_default_settings(struct ene_device *dev)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300824{
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300825 dev->tx_period = 32;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300826 dev->tx_duty_cycle = 50; /*%*/
827 dev->transmitter_mask = 0x03;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300828 dev->learning_mode_enabled = learning_mode_force;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300829
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300830 /* Set reasonable default timeout */
Jarod Wilson5aad7242011-01-06 16:59:36 -0300831 dev->rdev->timeout = US_TO_NS(150000);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300832}
833
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300834/* Upload all hardware settings at once. Used at load and resume time */
835static void ene_setup_hw_settings(struct ene_device *dev)
836{
837 if (dev->hw_learning_and_tx_capable) {
838 ene_tx_set_carrier(dev);
839 ene_tx_set_transmitters(dev);
840 }
841
842 ene_rx_setup(dev);
843}
844
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300845/* outside interface: called on first open*/
David Härdemand8b4b582010-10-29 16:08:23 -0300846static int ene_open(struct rc_dev *rdev)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300847{
David Härdemand8b4b582010-10-29 16:08:23 -0300848 struct ene_device *dev = rdev->priv;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300849 unsigned long flags;
850
851 spin_lock_irqsave(&dev->hw_lock, flags);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300852 ene_rx_enable(dev);
853 spin_unlock_irqrestore(&dev->hw_lock, flags);
854 return 0;
855}
856
857/* outside interface: called on device close*/
David Härdemand8b4b582010-10-29 16:08:23 -0300858static void ene_close(struct rc_dev *rdev)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300859{
David Härdemand8b4b582010-10-29 16:08:23 -0300860 struct ene_device *dev = rdev->priv;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300861 unsigned long flags;
862 spin_lock_irqsave(&dev->hw_lock, flags);
863
864 ene_rx_disable(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300865 spin_unlock_irqrestore(&dev->hw_lock, flags);
866}
867
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300868/* outside interface: set transmitter mask */
David Härdemand8b4b582010-10-29 16:08:23 -0300869static int ene_set_tx_mask(struct rc_dev *rdev, u32 tx_mask)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300870{
David Härdemand8b4b582010-10-29 16:08:23 -0300871 struct ene_device *dev = rdev->priv;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300872 dbg("TX: attempt to set transmitter mask %02x", tx_mask);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300873
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300874 /* invalid txmask */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300875 if (!tx_mask || tx_mask & ~0x03) {
876 dbg("TX: invalid mask");
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300877 /* return count of transmitters */
878 return 2;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300879 }
880
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300881 dev->transmitter_mask = tx_mask;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300882 ene_tx_set_transmitters(dev);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300883 return 0;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300884}
885
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300886/* outside interface : set tx carrier */
David Härdemand8b4b582010-10-29 16:08:23 -0300887static int ene_set_tx_carrier(struct rc_dev *rdev, u32 carrier)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300888{
David Härdemand8b4b582010-10-29 16:08:23 -0300889 struct ene_device *dev = rdev->priv;
Dan Carpenter48cafec2012-09-11 07:11:24 -0300890 u32 period;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300891
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300892 dbg("TX: attempt to set tx carrier to %d kHz", carrier);
Dan Carpenter48cafec2012-09-11 07:11:24 -0300893 if (carrier == 0)
894 return -EINVAL;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300895
Dan Carpenter48cafec2012-09-11 07:11:24 -0300896 period = 2000000 / carrier;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300897 if (period && (period > ENE_CIRMOD_PRD_MAX ||
898 period < ENE_CIRMOD_PRD_MIN)) {
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300899
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300900 dbg("TX: out of range %d-%d kHz carrier",
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300901 2000 / ENE_CIRMOD_PRD_MIN, 2000 / ENE_CIRMOD_PRD_MAX);
Sean Young14d81882016-07-10 13:34:33 -0300902 return -EINVAL;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300903 }
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300904
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300905 dev->tx_period = period;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300906 ene_tx_set_carrier(dev);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300907 return 0;
908}
909
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300910/*outside interface : set tx duty cycle */
David Härdemand8b4b582010-10-29 16:08:23 -0300911static int ene_set_tx_duty_cycle(struct rc_dev *rdev, u32 duty_cycle)
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300912{
David Härdemand8b4b582010-10-29 16:08:23 -0300913 struct ene_device *dev = rdev->priv;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300914 dbg("TX: setting duty cycle to %d%%", duty_cycle);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300915 dev->tx_duty_cycle = duty_cycle;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300916 ene_tx_set_carrier(dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300917 return 0;
918}
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300919
920/* outside interface: enable learning mode */
David Härdemand8b4b582010-10-29 16:08:23 -0300921static int ene_set_learning_mode(struct rc_dev *rdev, int enable)
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300922{
David Härdemand8b4b582010-10-29 16:08:23 -0300923 struct ene_device *dev = rdev->priv;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300924 unsigned long flags;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300925 if (enable == dev->learning_mode_enabled)
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300926 return 0;
927
928 spin_lock_irqsave(&dev->hw_lock, flags);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300929 dev->learning_mode_enabled = enable;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300930 ene_rx_disable(dev);
931 ene_rx_setup(dev);
932 ene_rx_enable(dev);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300933 spin_unlock_irqrestore(&dev->hw_lock, flags);
934 return 0;
935}
936
David Härdemand8b4b582010-10-29 16:08:23 -0300937static int ene_set_carrier_report(struct rc_dev *rdev, int enable)
Maxim Levitskye1b1ddb2010-10-16 19:56:29 -0300938{
David Härdemand8b4b582010-10-29 16:08:23 -0300939 struct ene_device *dev = rdev->priv;
Maxim Levitskye1b1ddb2010-10-16 19:56:29 -0300940 unsigned long flags;
941
942 if (enable == dev->carrier_detect_enabled)
943 return 0;
944
945 spin_lock_irqsave(&dev->hw_lock, flags);
946 dev->carrier_detect_enabled = enable;
947 ene_rx_disable(dev);
948 ene_rx_setup(dev);
949 ene_rx_enable(dev);
950 spin_unlock_irqrestore(&dev->hw_lock, flags);
951 return 0;
952}
953
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300954/* outside interface: enable or disable idle mode */
David Härdemand8b4b582010-10-29 16:08:23 -0300955static void ene_set_idle(struct rc_dev *rdev, bool idle)
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300956{
David Härdemand8b4b582010-10-29 16:08:23 -0300957 struct ene_device *dev = rdev->priv;
958
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300959 if (idle) {
David Härdemand8b4b582010-10-29 16:08:23 -0300960 ene_rx_reset(dev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300961 dbg("RX: end of data");
962 }
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300963}
964
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300965/* outside interface: transmit */
David Härdeman5588dc22011-04-28 12:13:58 -0300966static int ene_transmit(struct rc_dev *rdev, unsigned *buf, unsigned n)
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300967{
David Härdemand8b4b582010-10-29 16:08:23 -0300968 struct ene_device *dev = rdev->priv;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300969 unsigned long flags;
970
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300971 dev->tx_buffer = buf;
David Härdeman5588dc22011-04-28 12:13:58 -0300972 dev->tx_len = n;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300973 dev->tx_pos = 0;
974 dev->tx_reg = 0;
975 dev->tx_done = 0;
976 dev->tx_sample = 0;
Mauro Carvalho Chehab2816cc32014-09-03 16:01:36 -0300977 dev->tx_sample_pulse = false;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300978
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300979 dbg("TX: %d samples", dev->tx_len);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300980
981 spin_lock_irqsave(&dev->hw_lock, flags);
982
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300983 ene_tx_enable(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300984
985 /* Transmit first two samples */
986 ene_tx_sample(dev);
987 ene_tx_sample(dev);
988
989 spin_unlock_irqrestore(&dev->hw_lock, flags);
990
991 if (wait_for_completion_timeout(&dev->tx_complete, 2 * HZ) == 0) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300992 dbg("TX: timeout");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300993 spin_lock_irqsave(&dev->hw_lock, flags);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300994 ene_tx_disable(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300995 spin_unlock_irqrestore(&dev->hw_lock, flags);
996 } else
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300997 dbg("TX: done");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300998 return n;
999}
1000
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001001/* probe entry */
1002static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001003{
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001004 int error = -ENOMEM;
David Härdemand8b4b582010-10-29 16:08:23 -03001005 struct rc_dev *rdev;
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001006 struct ene_device *dev;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001007
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001008 /* allocate memory */
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001009 dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL);
Andi Shyti0f7499f2016-12-16 06:50:58 -02001010 rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
David Härdemand8b4b582010-10-29 16:08:23 -03001011 if (!dev || !rdev)
Matthijs Kooijman70ef6992012-11-02 09:13:54 -03001012 goto exit_free_dev_rdev;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001013
1014 /* validate resources */
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001015 error = -ENODEV;
1016
Kyle McMartin2e4c5562011-01-06 16:59:33 -03001017 /* init these to -1, as 0 is valid for both */
1018 dev->hw_io = -1;
1019 dev->irq = -1;
1020
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001021 if (!pnp_port_valid(pnp_dev, 0) ||
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001022 pnp_port_len(pnp_dev, 0) < ENE_IO_SIZE)
Matthijs Kooijman70ef6992012-11-02 09:13:54 -03001023 goto exit_free_dev_rdev;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001024
1025 if (!pnp_irq_valid(pnp_dev, 0))
Matthijs Kooijman70ef6992012-11-02 09:13:54 -03001026 goto exit_free_dev_rdev;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001027
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001028 spin_lock_init(&dev->hw_lock);
1029
Luis Henriquesb31b0212012-06-19 11:29:49 -03001030 dev->hw_io = pnp_port_start(pnp_dev, 0);
Maxim Levitsky1de6ebb2013-07-07 20:22:45 -03001031 dev->irq = pnp_irq(pnp_dev, 0);
1032
Luis Henriquesb31b0212012-06-19 11:29:49 -03001033
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001034 pnp_set_drvdata(pnp_dev, dev);
1035 dev->pnp_dev = pnp_dev;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001036
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001037 /* don't allow too short/long sample periods */
1038 if (sample_period < 5 || sample_period > 0x7F)
1039 sample_period = ENE_DEFAULT_SAMPLE_PERIOD;
1040
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001041 /* detect hardware version and features */
1042 error = ene_hw_detect(dev);
1043 if (error)
Matthijs Kooijman70ef6992012-11-02 09:13:54 -03001044 goto exit_free_dev_rdev;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001045
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001046 if (!dev->hw_learning_and_tx_capable && txsim) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001047 dev->hw_learning_and_tx_capable = true;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001048 setup_timer(&dev->tx_sim_timer, ene_tx_irqsim,
1049 (long unsigned int)dev);
Joe Perches7de34612011-08-21 19:56:46 -03001050 pr_warn("Simulation of TX activated\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001051 }
1052
Maxim Levitskya06423c2010-10-15 13:06:37 -03001053 if (!dev->hw_learning_and_tx_capable)
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -03001054 learning_mode_force = false;
Maxim Levitskya06423c2010-10-15 13:06:37 -03001055
Sean Young8c34b5c2016-12-03 08:55:56 -02001056 rdev->allowed_protocols = RC_BIT_ALL_IR_DECODER;
David Härdemand8b4b582010-10-29 16:08:23 -03001057 rdev->priv = dev;
1058 rdev->open = ene_open;
1059 rdev->close = ene_close;
1060 rdev->s_idle = ene_set_idle;
1061 rdev->driver_name = ENE_DRIVER_NAME;
1062 rdev->map_name = RC_MAP_RC6_MCE;
1063 rdev->input_name = "ENE eHome Infrared Remote Receiver";
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001064
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001065 if (dev->hw_learning_and_tx_capable) {
David Härdemand8b4b582010-10-29 16:08:23 -03001066 rdev->s_learning_mode = ene_set_learning_mode;
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001067 init_completion(&dev->tx_complete);
David Härdemand8b4b582010-10-29 16:08:23 -03001068 rdev->tx_ir = ene_transmit;
1069 rdev->s_tx_mask = ene_set_tx_mask;
1070 rdev->s_tx_carrier = ene_set_tx_carrier;
1071 rdev->s_tx_duty_cycle = ene_set_tx_duty_cycle;
1072 rdev->s_carrier_report = ene_set_carrier_report;
1073 rdev->input_name = "ENE eHome Infrared Remote Transceiver";
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001074 }
1075
Kyle McMartin2e4c5562011-01-06 16:59:33 -03001076 dev->rdev = rdev;
1077
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -03001078 ene_rx_setup_hw_buffer(dev);
1079 ene_setup_default_settings(dev);
1080 ene_setup_hw_settings(dev);
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001081
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001082 device_set_wakeup_capable(&pnp_dev->dev, true);
1083 device_set_wakeup_enable(&pnp_dev->dev, true);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001084
Matthijs Kooijman9fa35202012-11-02 09:13:56 -03001085 error = rc_register_device(rdev);
1086 if (error < 0)
1087 goto exit_free_dev_rdev;
1088
Luis Henriques9ef449c2012-04-21 12:25:21 -03001089 /* claim the resources */
1090 error = -EBUSY;
Luis Henriques9ef449c2012-04-21 12:25:21 -03001091 if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
Matthijs Kooijman9fa35202012-11-02 09:13:56 -03001092 goto exit_unregister_device;
Luis Henriques9ef449c2012-04-21 12:25:21 -03001093 }
1094
Luis Henriques9ef449c2012-04-21 12:25:21 -03001095 if (request_irq(dev->irq, ene_isr,
1096 IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) {
Matthijs Kooijman70ef6992012-11-02 09:13:54 -03001097 goto exit_release_hw_io;
Luis Henriques9ef449c2012-04-21 12:25:21 -03001098 }
1099
Joe Perches7de34612011-08-21 19:56:46 -03001100 pr_notice("driver has been successfully loaded\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001101 return 0;
Matthijs Kooijman56411c02012-10-15 07:13:44 -03001102
Matthijs Kooijman70ef6992012-11-02 09:13:54 -03001103exit_release_hw_io:
Matthijs Kooijman56411c02012-10-15 07:13:44 -03001104 release_region(dev->hw_io, ENE_IO_SIZE);
Matthijs Kooijman9fa35202012-11-02 09:13:56 -03001105exit_unregister_device:
1106 rc_unregister_device(rdev);
Wei Yongjundbcd3712013-04-09 05:47:42 -03001107 rdev = NULL;
Matthijs Kooijman70ef6992012-11-02 09:13:54 -03001108exit_free_dev_rdev:
David Härdemand8b4b582010-10-29 16:08:23 -03001109 rc_free_device(rdev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001110 kfree(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001111 return error;
1112}
1113
1114/* main unload function */
1115static void ene_remove(struct pnp_dev *pnp_dev)
1116{
1117 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
1118 unsigned long flags;
1119
1120 spin_lock_irqsave(&dev->hw_lock, flags);
1121 ene_rx_disable(dev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -03001122 ene_rx_restore_hw_buffer(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001123 spin_unlock_irqrestore(&dev->hw_lock, flags);
1124
1125 free_irq(dev->irq, dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001126 release_region(dev->hw_io, ENE_IO_SIZE);
David Härdemand8b4b582010-10-29 16:08:23 -03001127 rc_unregister_device(dev->rdev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001128 kfree(dev);
1129}
1130
1131/* enable wake on IR (wakes on specific button on original remote) */
Maxim Levitskyb5daad22013-07-07 20:22:46 -03001132static void ene_enable_wake(struct ene_device *dev, bool enable)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001133{
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001134 dbg("wake on IR %s", enable ? "enabled" : "disabled");
1135 ene_set_clear_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, enable);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001136}
1137
1138#ifdef CONFIG_PM
1139static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
1140{
1141 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
Maxim Levitskyb5daad22013-07-07 20:22:46 -03001142 bool wake = device_may_wakeup(&dev->pnp_dev->dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001143
Maxim Levitskyb5daad22013-07-07 20:22:46 -03001144 if (!wake && dev->rx_enabled)
1145 ene_rx_disable_hw(dev);
1146
1147 ene_enable_wake(dev, wake);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001148 return 0;
1149}
1150
1151static int ene_resume(struct pnp_dev *pnp_dev)
1152{
1153 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -03001154 ene_setup_hw_settings(dev);
1155
1156 if (dev->rx_enabled)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001157 ene_rx_enable(dev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -03001158
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001159 ene_enable_wake(dev, false);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001160 return 0;
1161}
1162#endif
1163
1164static void ene_shutdown(struct pnp_dev *pnp_dev)
1165{
1166 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001167 ene_enable_wake(dev, true);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001168}
1169
1170static const struct pnp_device_id ene_ids[] = {
1171 {.id = "ENE0100",},
1172 {.id = "ENE0200",},
1173 {.id = "ENE0201",},
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001174 {.id = "ENE0202",},
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001175 {},
1176};
1177
1178static struct pnp_driver ene_driver = {
1179 .name = ENE_DRIVER_NAME,
1180 .id_table = ene_ids,
1181 .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
1182
1183 .probe = ene_probe,
Greg Kroah-Hartman4c62e972012-12-21 13:17:53 -08001184 .remove = ene_remove,
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001185#ifdef CONFIG_PM
1186 .suspend = ene_suspend,
1187 .resume = ene_resume,
1188#endif
1189 .shutdown = ene_shutdown,
1190};
1191
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001192module_param(sample_period, int, S_IRUGO);
1193MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)");
1194
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -03001195module_param(learning_mode_force, bool, S_IRUGO);
1196MODULE_PARM_DESC(learning_mode_force, "Enable learning mode by default");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001197
1198module_param(debug, int, S_IRUGO | S_IWUSR);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001199MODULE_PARM_DESC(debug, "Debug level");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001200
1201module_param(txsim, bool, S_IRUGO);
1202MODULE_PARM_DESC(txsim,
1203 "Simulate TX features on unsupported hardware (dangerous)");
1204
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001205MODULE_DEVICE_TABLE(pnp, ene_ids);
1206MODULE_DESCRIPTION
Mauro Carvalho Chehab25ec5872016-10-18 17:44:25 -02001207 ("Infrared input driver for KB3926B/C/D/E/F (aka ENE0100/ENE0200/ENE0201/ENE0202) CIR port");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001208
1209MODULE_AUTHOR("Maxim Levitsky");
1210MODULE_LICENSE("GPL");
1211
Peter Hueweaf638a02015-03-16 21:46:34 +01001212module_pnp_driver(ene_driver);