blob: d546b5ef331be3899fb23236a3a63870789f5632 [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 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 * USA
Maxim Levitsky11b64d32010-09-06 18:26:11 -030020 *
21 * Special thanks to:
22 * Sami R. <maesesami@gmail.com> for lot of help in debugging and therefore
23 * bringing to life support for transmission & learning mode.
24 *
25 * Charlie Andrews <charliethepilot@googlemail.com> for lots of help in
26 * bringing up the support of new firmware buffer that is popular
27 * on latest notebooks
28 *
29 * ENE for partial device documentation
30 *
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030031 */
32
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/pnp.h>
36#include <linux/io.h>
37#include <linux/interrupt.h>
38#include <linux/sched.h>
Maxim Levitsky931e39a2010-07-31 11:59:26 -030039#include <linux/slab.h>
40#include <linux/input.h>
41#include <media/ir-core.h>
42#include <media/ir-common.h>
43#include "ene_ir.h"
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030044
Maxim Levitsky11b64d32010-09-06 18:26:11 -030045static int sample_period;
46static bool learning_mode;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030047static int debug;
Maxim Levitsky11b64d32010-09-06 18:26:11 -030048static bool txsim;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030049
Maxim Levitsky11b64d32010-09-06 18:26:11 -030050static void ene_set_reg_addr(struct ene_device *dev, u16 reg)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030051{
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030052 outb(reg >> 8, dev->hw_io + ENE_ADDR_HI);
53 outb(reg & 0xFF, dev->hw_io + ENE_ADDR_LO);
Maxim Levitsky11b64d32010-09-06 18:26:11 -030054}
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030055
Maxim Levitsky11b64d32010-09-06 18:26:11 -030056/* read a hardware register */
57static u8 ene_read_reg(struct ene_device *dev, u16 reg)
58{
59 u8 retval;
60 ene_set_reg_addr(dev, reg);
61 retval = inb(dev->hw_io + ENE_IO);
62 dbg_regs("reg %04x == %02x", reg, retval);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030063 return retval;
64}
65
66/* write a hardware register */
Maxim Levitsky11b64d32010-09-06 18:26:11 -030067static void ene_write_reg(struct ene_device *dev, u16 reg, u8 value)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030068{
Maxim Levitsky11b64d32010-09-06 18:26:11 -030069 dbg_regs("reg %04x <- %02x", reg, value);
70 ene_set_reg_addr(dev, reg);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030071 outb(value, dev->hw_io + ENE_IO);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030072}
73
Maxim Levitsky11b64d32010-09-06 18:26:11 -030074/* Set bits in hardware register */
75static void ene_set_reg_mask(struct ene_device *dev, u16 reg, u8 mask)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030076{
Maxim Levitsky11b64d32010-09-06 18:26:11 -030077 dbg_regs("reg %04x |= %02x", reg, mask);
78 ene_set_reg_addr(dev, reg);
79 outb(inb(dev->hw_io + ENE_IO) | mask, dev->hw_io + ENE_IO);
80}
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030081
Maxim Levitsky11b64d32010-09-06 18:26:11 -030082/* Clear bits in hardware register */
83static void ene_clear_reg_mask(struct ene_device *dev, u16 reg, u8 mask)
84{
85 dbg_regs("reg %04x &= ~%02x ", reg, mask);
86 ene_set_reg_addr(dev, reg);
87 outb(inb(dev->hw_io + ENE_IO) & ~mask, dev->hw_io + ENE_IO);
88}
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030089
Maxim Levitsky11b64d32010-09-06 18:26:11 -030090/* A helper to set/clear a bit in register according to boolean variable */
91static void ene_set_clear_reg_mask(struct ene_device *dev, u16 reg, u8 mask,
92 bool set)
93{
94 if (set)
95 ene_set_reg_mask(dev, reg, mask);
96 else
97 ene_clear_reg_mask(dev, reg, mask);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030098}
99
100/* detect hardware features */
101static int ene_hw_detect(struct ene_device *dev)
102{
103 u8 chip_major, chip_minor;
104 u8 hw_revision, old_ver;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300105 u8 fw_reg2, fw_reg1;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300106
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300107 ene_clear_reg_mask(dev, ENE_ECSTS, ENE_ECSTS_RSRVD);
108 chip_major = ene_read_reg(dev, ENE_ECVER_MAJOR);
109 chip_minor = ene_read_reg(dev, ENE_ECVER_MINOR);
110 ene_set_reg_mask(dev, ENE_ECSTS, ENE_ECSTS_RSRVD);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300111
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300112 hw_revision = ene_read_reg(dev, ENE_ECHV);
113 old_ver = ene_read_reg(dev, ENE_HW_VER_OLD);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300114
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300115 dev->pll_freq = (ene_read_reg(dev, ENE_PLLFRH) << 4) +
116 (ene_read_reg(dev, ENE_PLLFRL) >> 4);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300117
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300118 if (sample_period != ENE_DEFAULT_SAMPLE_PERIOD)
119 dev->rx_period_adjust =
120 dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 2 : 4;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300121
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300122 if (hw_revision == 0xFF) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300123 ene_warn("device seems to be disabled");
124 ene_warn("send a mail to lirc-list@lists.sourceforge.net");
125 ene_warn("please attach output of acpidump and dmidecode");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300126 return -ENODEV;
127 }
128
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300129 ene_notice("chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x",
130 chip_major, chip_minor, old_ver, hw_revision);
131
132 ene_notice("PLL freq = %d", dev->pll_freq);
133
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300134 if (chip_major == 0x33) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300135 ene_warn("chips 0x33xx aren't supported");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300136 return -ENODEV;
137 }
138
139 if (chip_major == 0x39 && chip_minor == 0x26 && hw_revision == 0xC0) {
140 dev->hw_revision = ENE_HW_C;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300141 ene_notice("KB3926C detected");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300142 } else if (old_ver == 0x24 && hw_revision == 0xC0) {
143 dev->hw_revision = ENE_HW_B;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300144 ene_notice("KB3926B detected");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300145 } else {
146 dev->hw_revision = ENE_HW_D;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300147 ene_notice("KB3926D or higher detected");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300148 }
149
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300150 /* detect features hardware supports */
151 if (dev->hw_revision < ENE_HW_C)
152 return 0;
153
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300154 fw_reg1 = ene_read_reg(dev, ENE_FW1);
155 fw_reg2 = ene_read_reg(dev, ENE_FW2);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300156
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300157 ene_notice("Firmware regs: %02x %02x", fw_reg1, fw_reg2);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300158
Maxim Levitskya06423c2010-10-15 13:06:37 -0300159 dev->hw_use_gpio_0a = !!(fw_reg2 & ENE_FW2_GP0A);
160 dev->hw_learning_and_tx_capable = !!(fw_reg2 & ENE_FW2_LEARNING);
161 dev->hw_extra_buffer = !!(fw_reg1 & ENE_FW1_HAS_EXTRA_BUF);
162
163 if (dev->hw_learning_and_tx_capable)
164 dev->hw_fan_input = !!(fw_reg2 & ENE_FW2_FAN_INPUT);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300165
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300166 ene_notice("Hardware features:");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300167
168 if (dev->hw_learning_and_tx_capable) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300169 ene_notice("* Supports transmitting & learning mode");
170 ene_notice(" This feature is rare and therefore,");
171 ene_notice(" you are welcome to test it,");
172 ene_notice(" and/or contact the author via:");
173 ene_notice(" lirc-list@lists.sourceforge.net");
174 ene_notice(" or maximlevitsky@gmail.com");
175
176 ene_notice("* Uses GPIO %s for IR raw input",
177 dev->hw_use_gpio_0a ? "40" : "0A");
178
179 if (dev->hw_fan_input)
180 ene_notice("* Uses unused fan feedback input as source"
181 " of demodulated IR data");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300182 }
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300183
184 if (!dev->hw_fan_input)
185 ene_notice("* Uses GPIO %s for IR demodulated input",
186 dev->hw_use_gpio_0a ? "0A" : "40");
187
188 if (dev->hw_extra_buffer)
189 ene_notice("* Uses new style input buffer");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300190 return 0;
191}
192
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300193/* Sense current received carrier */
194void ene_rx_sense_carrier(struct ene_device *dev)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300195{
Maxim Levitskye1b1ddb2010-10-16 19:56:29 -0300196 DEFINE_IR_RAW_EVENT(ev);
197
198 int carrier, duty_cycle;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300199 int period = ene_read_reg(dev, ENE_CIRCAR_PRD);
200 int hperiod = ene_read_reg(dev, ENE_CIRCAR_HPRD);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300201
202 if (!(period & ENE_CIRCAR_PRD_VALID))
203 return;
204
205 period &= ~ENE_CIRCAR_PRD_VALID;
206
207 if (!period)
208 return;
209
210 dbg("RX: hardware carrier period = %02x", period);
211 dbg("RX: hardware carrier pulse period = %02x", hperiod);
212
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300213 carrier = 2000000 / period;
214 duty_cycle = (hperiod * 100) / period;
215 dbg("RX: sensed carrier = %d Hz, duty cycle %d%%",
Maxim Levitskye1b1ddb2010-10-16 19:56:29 -0300216 carrier, duty_cycle);
217 if (dev->carrier_detect_enabled) {
218 ev.carrier_report = true;
219 ev.carrier = carrier;
220 ev.duty_cycle = duty_cycle;
221 ir_raw_event_store(dev->idev, &ev);
222 }
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300223}
224
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300225/* this enables/disables the CIR RX engine */
226static void ene_enable_cir_engine(struct ene_device *dev, bool enable)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300227{
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300228 ene_set_clear_reg_mask(dev, ENE_CIRCFG,
229 ENE_CIRCFG_RX_EN | ENE_CIRCFG_RX_IRQ, enable);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300230}
231
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300232/* this selects input for CIR engine. Ether GPIO 0A or GPIO40*/
233static void ene_select_rx_input(struct ene_device *dev, bool gpio_0a)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300234{
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300235 ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_GPIO0A, gpio_0a);
236}
237
238/*
239 * this enables alternative input via fan tachometer sensor and bypasses
240 * the hw CIR engine
241 */
242static void ene_enable_fan_input(struct ene_device *dev, bool enable)
243{
244 if (!dev->hw_fan_input)
245 return;
246
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300247 if (!enable)
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300248 ene_write_reg(dev, ENE_FAN_AS_IN1, 0);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300249 else {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300250 ene_write_reg(dev, ENE_FAN_AS_IN1, ENE_FAN_AS_IN1_EN);
251 ene_write_reg(dev, ENE_FAN_AS_IN2, ENE_FAN_AS_IN2_EN);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300252 }
253 dev->rx_fan_input_inuse = enable;
254}
255
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300256/* setup the receiver for RX*/
257static void ene_rx_setup(struct ene_device *dev)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300258{
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300259 bool learning_mode = dev->learning_enabled ||
260 dev->carrier_detect_enabled;
261 int sample_period_adjust = 0;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300262
Maxim Levitskya06423c2010-10-15 13:06:37 -0300263 /* This selects RLC input and clears CFG2 settings */
264 ene_write_reg(dev, ENE_CIRCFG2, 0x00);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300265
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300266 /* set sample period*/
267 if (sample_period == ENE_DEFAULT_SAMPLE_PERIOD)
268 sample_period_adjust =
269 dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 1 : 2;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300270
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300271 ene_write_reg(dev, ENE_CIRRLC_CFG,
272 (sample_period + sample_period_adjust) |
273 ENE_CIRRLC_CFG_OVERFLOW);
274 /* revB doesn't support inputs */
275 if (dev->hw_revision < ENE_HW_C)
276 goto select_timeout;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300277
Maxim Levitskya06423c2010-10-15 13:06:37 -0300278 if (learning_mode) {
279
280 WARN_ON(!dev->hw_learning_and_tx_capable);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300281
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300282 /* Enable the opposite of the normal input
283 That means that if GPIO40 is normally used, use GPIO0A
284 and vice versa.
285 This input will carry non demodulated
286 signal, and we will tell the hw to demodulate it itself */
287 ene_select_rx_input(dev, !dev->hw_use_gpio_0a);
288 dev->rx_fan_input_inuse = false;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300289
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300290 /* Enable carrier demodulation */
291 ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300292
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300293 /* Enable carrier detection */
Maxim Levitskya06423c2010-10-15 13:06:37 -0300294 ene_write_reg(dev, ENE_CIRCAR_PULS, 0x63);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300295 ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT,
296 dev->carrier_detect_enabled || debug);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300297 } else {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300298 if (dev->hw_fan_input)
299 dev->rx_fan_input_inuse = true;
300 else
301 ene_select_rx_input(dev, dev->hw_use_gpio_0a);
302
303 /* Disable carrier detection & demodulation */
304 ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD);
305 ene_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300306 }
307
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300308select_timeout:
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300309 if (dev->rx_fan_input_inuse) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300310 dev->props->rx_resolution = MS_TO_NS(ENE_FW_SAMPLE_PERIOD_FAN);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300311
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300312 /* Fan input doesn't support timeouts, it just ends the
313 input with a maximum sample */
314 dev->props->min_timeout = dev->props->max_timeout =
315 MS_TO_NS(ENE_FW_SMPL_BUF_FAN_MSK *
316 ENE_FW_SAMPLE_PERIOD_FAN);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300317 } else {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300318 dev->props->rx_resolution = MS_TO_NS(sample_period);
319
320 /* Theoreticly timeout is unlimited, but we cap it
321 * because it was seen that on one device, it
322 * would stop sending spaces after around 250 msec.
323 * Besides, this is close to 2^32 anyway and timeout is u32.
324 */
325 dev->props->min_timeout = MS_TO_NS(127 * sample_period);
326 dev->props->max_timeout = MS_TO_NS(200000);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300327 }
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300328
329 if (dev->hw_learning_and_tx_capable)
330 dev->props->tx_resolution = MS_TO_NS(sample_period);
331
332 if (dev->props->timeout > dev->props->max_timeout)
333 dev->props->timeout = dev->props->max_timeout;
334 if (dev->props->timeout < dev->props->min_timeout)
335 dev->props->timeout = dev->props->min_timeout;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300336}
337
338/* Enable the device for receive */
339static void ene_rx_enable(struct ene_device *dev)
340{
341 u8 reg_value;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300342 dbg("RX: setup receiver, learning mode = %d", learning_mode);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300343
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300344 /* Enable system interrupt */
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300345 if (dev->hw_revision < ENE_HW_C) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300346 ene_write_reg(dev, ENEB_IRQ, dev->irq << 1);
347 ene_write_reg(dev, ENEB_IRQ_UNK1, 0x01);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300348 } else {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300349 reg_value = ene_read_reg(dev, ENE_IRQ) & 0xF0;
350 reg_value |= ENE_IRQ_UNK_EN;
351 reg_value &= ~ENE_IRQ_STATUS;
352 reg_value |= (dev->irq & ENE_IRQ_MASK);
353 ene_write_reg(dev, ENE_IRQ, reg_value);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300354 }
355
Maxim Levitskya06423c2010-10-15 13:06:37 -0300356 /* Enable inputs */
357 ene_enable_fan_input(dev, dev->rx_fan_input_inuse);
358 ene_enable_cir_engine(dev, !dev->rx_fan_input_inuse);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300359
360 /* ack any pending irqs - just in case */
361 ene_irq_status(dev);
362
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300363 /* enable firmware bits */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300364 ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300365
366 /* enter idle mode */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300367 ir_raw_event_set_idle(dev->idev, true);
368 dev->rx_enabled = true;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300369}
370
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300371/* Disable the device receiver */
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300372static void ene_rx_disable(struct ene_device *dev)
373{
374 /* disable inputs */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300375 ene_enable_cir_engine(dev, false);
376 ene_enable_fan_input(dev, false);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300377
378 /* disable hardware IRQ and firmware flag */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300379 ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300380
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300381 ir_raw_event_set_idle(dev->idev, true);
382 dev->rx_enabled = false;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300383}
384
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300385/* prepare transmission */
386static void ene_tx_prepare(struct ene_device *dev)
387{
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300388 u8 conf1 = ene_read_reg(dev, ENE_CIRCFG);
389 u8 fwreg2 = ene_read_reg(dev, ENE_FW2);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300390
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300391 dev->saved_conf1 = conf1;
392
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300393 /* Show information about currently connected transmitter jacks */
394 if (fwreg2 & ENE_FW2_EMMITER1_CONN)
395 dbg("TX: Transmitter #1 is connected");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300396
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300397 if (fwreg2 & ENE_FW2_EMMITER2_CONN)
398 dbg("TX: Transmitter #2 is connected");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300399
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300400 if (!(fwreg2 & (ENE_FW2_EMMITER1_CONN | ENE_FW2_EMMITER2_CONN)))
401 ene_warn("TX: transmitter cable isn't connected!");
402
403 /* Set transmitter mask */
404 ene_set_clear_reg_mask(dev, ENE_GPIOFS8, ENE_GPIOFS8_GPIO41,
405 !!(dev->transmitter_mask & 0x01));
406 ene_set_clear_reg_mask(dev, ENE_GPIOFS1, ENE_GPIOFS1_GPIO0D,
407 !!(dev->transmitter_mask & 0x02));
408
409 /* Set the carrier period && duty cycle */
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300410 if (dev->tx_period) {
411
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300412 int tx_puls_width = dev->tx_period / (100 / dev->tx_duty_cycle);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300413
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300414 if (!tx_puls_width)
415 tx_puls_width = 1;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300416
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300417 dbg("TX: pulse distance = %d * 500 ns", dev->tx_period);
418 dbg("TX: pulse width = %d * 500 ns", tx_puls_width);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300419
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300420 ene_write_reg(dev, ENE_CIRMOD_PRD, ENE_CIRMOD_PRD_POL |
421 dev->tx_period);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300422
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300423 ene_write_reg(dev, ENE_CIRMOD_HPRD, tx_puls_width);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300424
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300425 conf1 |= ENE_CIRCFG_TX_CARR;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300426 } else
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300427 conf1 &= ~ENE_CIRCFG_TX_CARR;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300428
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300429 /* disable receive on revc */
430 if (dev->hw_revision == ENE_HW_C)
431 conf1 &= ~ENE_CIRCFG_RX_EN;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300432
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300433 /* Enable TX engine */
434 conf1 |= ENE_CIRCFG_TX_EN | ENE_CIRCFG_TX_IRQ;
435 ene_write_reg(dev, ENE_CIRCFG, conf1);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300436}
437
438/* end transmission */
439static void ene_tx_complete(struct ene_device *dev)
440{
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300441 ene_write_reg(dev, ENE_CIRCFG, dev->saved_conf1);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300442 dev->tx_buffer = NULL;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300443}
444
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300445
446/* TX one sample - must be called with dev->hw_lock*/
447static void ene_tx_sample(struct ene_device *dev)
448{
449 u8 raw_tx;
450 u32 sample;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300451 bool pulse = dev->tx_sample_pulse;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300452
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300453 if (!dev->tx_buffer) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300454 ene_warn("TX: BUG: attempt to transmit NULL buffer");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300455 return;
456 }
457
458 /* Grab next TX sample */
459 if (!dev->tx_sample) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300460
461 if (dev->tx_pos == dev->tx_len) {
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300462 if (!dev->tx_done) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300463 dbg("TX: no more data to send");
464 dev->tx_done = true;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300465 goto exit;
466 } else {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300467 dbg("TX: last sample sent by hardware");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300468 ene_tx_complete(dev);
469 complete(&dev->tx_complete);
470 return;
471 }
472 }
473
474 sample = dev->tx_buffer[dev->tx_pos++];
475 dev->tx_sample_pulse = !dev->tx_sample_pulse;
476
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300477 dev->tx_sample = DIV_ROUND_CLOSEST(sample, sample_period);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300478
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300479 if (!dev->tx_sample)
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300480 dev->tx_sample = 1;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300481 }
482
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300483 raw_tx = min(dev->tx_sample , (unsigned int)ENE_CIRRLC_OUT_MASK);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300484 dev->tx_sample -= raw_tx;
485
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300486 dbg("TX: sample %8d (%s)", raw_tx * sample_period,
487 pulse ? "pulse" : "space");
488 if (pulse)
489 raw_tx |= ENE_CIRRLC_OUT_PULSE;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300490
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300491 ene_write_reg(dev,
492 dev->tx_reg ? ENE_CIRRLC_OUT1 : ENE_CIRRLC_OUT0, raw_tx);
493
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300494 dev->tx_reg = !dev->tx_reg;
495exit:
496 /* simulate TX done interrupt */
497 if (txsim)
498 mod_timer(&dev->tx_sim_timer, jiffies + HZ / 500);
499}
500
501/* timer to simulate tx done interrupt */
502static void ene_tx_irqsim(unsigned long data)
503{
504 struct ene_device *dev = (struct ene_device *)data;
505 unsigned long flags;
506
507 spin_lock_irqsave(&dev->hw_lock, flags);
508 ene_tx_sample(dev);
509 spin_unlock_irqrestore(&dev->hw_lock, flags);
510}
511
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300512/* Read properities of hw sample buffer */
513static void ene_setup_hw_buffer(struct ene_device *dev)
514{
515 u16 tmp;
516
517 ene_read_hw_pointer(dev);
518 dev->r_pointer = dev->w_pointer;
519
520 if (!dev->hw_extra_buffer) {
521 dev->buffer_len = ENE_FW_PACKET_SIZE * 2;
522 return;
523 }
524
525 tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER);
526 tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER+1) << 8;
527 dev->extra_buf1_address = tmp;
528
529 dev->extra_buf1_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 2);
530
531 tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 3);
532 tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 4) << 8;
533 dev->extra_buf2_address = tmp;
534
535 dev->extra_buf2_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 5);
536
537 dev->buffer_len = dev->extra_buf1_len + dev->extra_buf2_len + 8;
538
539 ene_notice("Hardware uses 2 extended buffers:");
540 ene_notice(" 0x%04x - len : %d", dev->extra_buf1_address,
541 dev->extra_buf1_len);
542 ene_notice(" 0x%04x - len : %d", dev->extra_buf2_address,
543 dev->extra_buf2_len);
544
545 ene_notice("Total buffer len = %d", dev->buffer_len);
546
547 if (dev->buffer_len > 64 || dev->buffer_len < 16)
548 goto error;
549
550 if (dev->extra_buf1_address > 0xFBFC ||
551 dev->extra_buf1_address < 0xEC00)
552 goto error;
553
554 if (dev->extra_buf2_address > 0xFBFC ||
555 dev->extra_buf2_address < 0xEC00)
556 goto error;
557
558 if (dev->r_pointer > dev->buffer_len)
559 goto error;
560
561 ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
562 return;
563error:
564 ene_warn("Error validating extra buffers, device probably won't work");
565 dev->hw_extra_buffer = false;
566 ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
567}
568
569
570/* Restore the pointers to extra buffers - to make module reload work*/
571static void ene_restore_extra_buffer(struct ene_device *dev)
572{
573 if (!dev->hw_extra_buffer)
574 return;
575
576 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 0,
577 dev->extra_buf1_address & 0xFF);
578 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 1,
579 dev->extra_buf1_address >> 8);
580 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 2, dev->extra_buf1_len);
581
582 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 3,
583 dev->extra_buf2_address & 0xFF);
584 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 4,
585 dev->extra_buf2_address >> 8);
586 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 5,
587 dev->extra_buf2_len);
588 ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
589}
590
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300591
592/* read irq status and ack it */
593static int ene_irq_status(struct ene_device *dev)
594{
595 u8 irq_status;
596 u8 fw_flags1, fw_flags2;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300597 int retval = 0;
598
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300599 fw_flags2 = ene_read_reg(dev, ENE_FW2);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300600
601 if (dev->hw_revision < ENE_HW_C) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300602 irq_status = ene_read_reg(dev, ENEB_IRQ_STATUS);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300603
604 if (!(irq_status & ENEB_IRQ_STATUS_IR))
605 return 0;
606
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300607 ene_clear_reg_mask(dev, ENEB_IRQ_STATUS, ENEB_IRQ_STATUS_IR);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300608 return ENE_IRQ_RX;
609 }
610
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300611 irq_status = ene_read_reg(dev, ENE_IRQ);
612 if (!(irq_status & ENE_IRQ_STATUS))
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300613 return 0;
614
615 /* original driver does that twice - a workaround ? */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300616 ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS);
617 ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300618
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300619 /* check RX interrupt */
620 if (fw_flags2 & ENE_FW2_RXIRQ) {
621 retval |= ENE_IRQ_RX;
622 ene_write_reg(dev, ENE_FW2, fw_flags2 & ~ENE_FW2_RXIRQ);
623 }
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300624
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300625 /* check TX interrupt */
626 fw_flags1 = ene_read_reg(dev, ENE_FW1);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300627 if (fw_flags1 & ENE_FW1_TXIRQ) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300628 ene_write_reg(dev, ENE_FW1, fw_flags1 & ~ENE_FW1_TXIRQ);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300629 retval |= ENE_IRQ_TX;
630 }
631
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300632 return retval;
633}
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300634
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300635/* Read hardware write pointer */
636static void ene_read_hw_pointer(struct ene_device *dev)
637{
638 if (dev->hw_extra_buffer)
639 dev->w_pointer = ene_read_reg(dev, ENE_FW_RX_POINTER);
640 else
641 dev->w_pointer = ene_read_reg(dev, ENE_FW2)
642 & ENE_FW2_BUF_WPTR ? 0 : ENE_FW_PACKET_SIZE;
643
644 dbg_verbose("RB: HW write pointer: %02x, driver read pointer: %02x",
645 dev->w_pointer, dev->r_pointer);
646}
647
648/* Gets address of next sample from HW ring buffer */
649static int ene_get_sample_reg(struct ene_device *dev)
650{
651 int r_pointer;
652
653 if (dev->r_pointer == dev->w_pointer) {
654 dbg_verbose("RB: hit end, try update w_pointer");
655 ene_read_hw_pointer(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300656 }
657
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300658 if (dev->r_pointer == dev->w_pointer) {
659 dbg_verbose("RB: end of data at %d", dev->r_pointer);
660 return 0;
661 }
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300662
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300663 dbg_verbose("RB: reading at offset %d", dev->r_pointer);
664 r_pointer = dev->r_pointer;
665
666 dev->r_pointer++;
667 if (dev->r_pointer == dev->buffer_len)
668 dev->r_pointer = 0;
669
670 dbg_verbose("RB: next read will be from offset %d", dev->r_pointer);
671
672 if (r_pointer < 8) {
673 dbg_verbose("RB: read at main buffer at %d", r_pointer);
674 return ENE_FW_SAMPLE_BUFFER + r_pointer;
675 }
676
677 r_pointer -= 8;
678
679 if (r_pointer < dev->extra_buf1_len) {
680 dbg_verbose("RB: read at 1st extra buffer at %d", r_pointer);
681 return dev->extra_buf1_address + r_pointer;
682 }
683
684 r_pointer -= dev->extra_buf1_len;
685
686 if (r_pointer < dev->extra_buf2_len) {
687 dbg_verbose("RB: read at 2nd extra buffer at %d", r_pointer);
688 return dev->extra_buf2_address + r_pointer;
689 }
690
691 dbg("attempt to read beyong ring bufer end");
692 return 0;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300693}
694
695/* interrupt handler */
696static irqreturn_t ene_isr(int irq, void *data)
697{
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300698 u16 hw_value, reg;
699 int hw_sample, irq_status;
700 bool pulse;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300701 unsigned long flags;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300702 irqreturn_t retval = IRQ_NONE;
703 struct ene_device *dev = (struct ene_device *)data;
Maxim Levitsky46519182010-10-16 19:56:28 -0300704 DEFINE_IR_RAW_EVENT(ev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300705
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300706 spin_lock_irqsave(&dev->hw_lock, flags);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300707
708 dbg_verbose("ISR called");
709 ene_read_hw_pointer(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300710 irq_status = ene_irq_status(dev);
711
712 if (!irq_status)
713 goto unlock;
714
715 retval = IRQ_HANDLED;
716
717 if (irq_status & ENE_IRQ_TX) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300718 dbg_verbose("TX interrupt");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300719 if (!dev->hw_learning_and_tx_capable) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300720 dbg("TX interrupt on unsupported device!");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300721 goto unlock;
722 }
723 ene_tx_sample(dev);
724 }
725
726 if (!(irq_status & ENE_IRQ_RX))
727 goto unlock;
728
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300729 dbg_verbose("RX interrupt");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300730
Maxim Levitskye1b1ddb2010-10-16 19:56:29 -0300731 if (dev->hw_learning_and_tx_capable)
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300732 ene_rx_sense_carrier(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300733
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300734 /* On hardware that don't support extra buffer we need to trust
735 the interrupt and not track the read pointer */
736 if (!dev->hw_extra_buffer)
737 dev->r_pointer = dev->w_pointer == 0 ? ENE_FW_PACKET_SIZE : 0;
738
739 while (1) {
740
741 reg = ene_get_sample_reg(dev);
742
743 dbg_verbose("next sample to read at: %04x", reg);
744 if (!reg)
745 break;
746
747 hw_value = ene_read_reg(dev, reg);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300748
749 if (dev->rx_fan_input_inuse) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300750
751 int offset = ENE_FW_SMPL_BUF_FAN - ENE_FW_SAMPLE_BUFFER;
752
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300753 /* read high part of the sample */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300754 hw_value |= ene_read_reg(dev, reg + offset) << 8;
755 pulse = hw_value & ENE_FW_SMPL_BUF_FAN_PLS;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300756
757 /* clear space bit, and other unused bits */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300758 hw_value &= ENE_FW_SMPL_BUF_FAN_MSK;
759 hw_sample = hw_value * ENE_FW_SAMPLE_PERIOD_FAN;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300760
761 } else {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300762 pulse = !(hw_value & ENE_FW_SAMPLE_SPACE);
763 hw_value &= ~ENE_FW_SAMPLE_SPACE;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300764 hw_sample = hw_value * sample_period;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300765
766 if (dev->rx_period_adjust) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300767 hw_sample *= 100;
768 hw_sample /= (100 + dev->rx_period_adjust);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300769 }
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300770 }
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300771
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300772 if (!dev->hw_extra_buffer && !hw_sample) {
773 dev->r_pointer = dev->w_pointer;
774 continue;
775 }
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300776
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300777 dbg("RX: %d (%s)", hw_sample, pulse ? "pulse" : "space");
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300778
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300779 ev.duration = MS_TO_NS(hw_sample);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300780 ev.pulse = pulse;
781 ir_raw_event_store_with_filter(dev->idev, &ev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300782 }
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300783
784 ir_raw_event_handle(dev->idev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300785unlock:
786 spin_unlock_irqrestore(&dev->hw_lock, flags);
787 return retval;
788}
789
790/* Initialize default settings */
791static void ene_setup_settings(struct ene_device *dev)
792{
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300793 dev->tx_period = 32;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300794 dev->tx_duty_cycle = 50; /*%*/
795 dev->transmitter_mask = 0x03;
Maxim Levitskya06423c2010-10-15 13:06:37 -0300796 dev->learning_enabled = learning_mode;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300797
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300798 /* Set reasonable default timeout */
Maxim Levitskya06423c2010-10-15 13:06:37 -0300799 dev->props->timeout = MS_TO_NS(150000);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300800}
801
802/* outside interface: called on first open*/
803static int ene_open(void *data)
804{
805 struct ene_device *dev = (struct ene_device *)data;
806 unsigned long flags;
807
808 spin_lock_irqsave(&dev->hw_lock, flags);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300809 ene_rx_enable(dev);
810 spin_unlock_irqrestore(&dev->hw_lock, flags);
811 return 0;
812}
813
814/* outside interface: called on device close*/
815static void ene_close(void *data)
816{
817 struct ene_device *dev = (struct ene_device *)data;
818 unsigned long flags;
819 spin_lock_irqsave(&dev->hw_lock, flags);
820
821 ene_rx_disable(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300822 spin_unlock_irqrestore(&dev->hw_lock, flags);
823}
824
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300825/* outside interface: set transmitter mask */
826static int ene_set_tx_mask(void *data, u32 tx_mask)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300827{
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300828 struct ene_device *dev = (struct ene_device *)data;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300829 unsigned long flags;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300830 dbg("TX: attempt to set transmitter mask %02x", tx_mask);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300831
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300832 /* invalid txmask */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300833 if (!tx_mask || tx_mask & ~0x03) {
834 dbg("TX: invalid mask");
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300835 /* return count of transmitters */
836 return 2;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300837 }
838
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300839 spin_lock_irqsave(&dev->hw_lock, flags);
840 dev->transmitter_mask = tx_mask;
841 spin_unlock_irqrestore(&dev->hw_lock, flags);
842 return 0;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300843}
844
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300845/* outside interface : set tx carrier */
846static int ene_set_tx_carrier(void *data, u32 carrier)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300847{
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300848 struct ene_device *dev = (struct ene_device *)data;
849 unsigned long flags;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300850 u32 period = 2000000 / carrier;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300851
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300852 dbg("TX: attempt to set tx carrier to %d kHz", carrier);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300853
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300854 if (period && (period > ENE_CIRMOD_PRD_MAX ||
855 period < ENE_CIRMOD_PRD_MIN)) {
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300856
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300857 dbg("TX: out of range %d-%d kHz carrier",
858 2000 / ENE_CIRMOD_PRD_MIN,
859 2000 / ENE_CIRMOD_PRD_MAX);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300860
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300861 return -1;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300862 }
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300863
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300864 dbg("TX: set carrier to %d kHz", carrier);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300865 spin_lock_irqsave(&dev->hw_lock, flags);
866 dev->tx_period = period;
867 spin_unlock_irqrestore(&dev->hw_lock, flags);
868 return 0;
869}
870
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300871/*outside interface : set tx duty cycle */
872static int ene_set_tx_duty_cycle(void *data, u32 duty_cycle)
873{
874 struct ene_device *dev = (struct ene_device *)data;
875 unsigned long flags;
876
877 dbg("TX: setting duty cycle to %d%%", duty_cycle);
878
879 BUG_ON(!duty_cycle || duty_cycle >= 100);
880
881 spin_lock_irqsave(&dev->hw_lock, flags);
882 dev->tx_duty_cycle = duty_cycle;
883 spin_unlock_irqrestore(&dev->hw_lock, flags);
884 return 0;
885}
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300886
887/* outside interface: enable learning mode */
888static int ene_set_learning_mode(void *data, int enable)
889{
890 struct ene_device *dev = (struct ene_device *)data;
891 unsigned long flags;
892 if (enable == dev->learning_enabled)
893 return 0;
894
895 spin_lock_irqsave(&dev->hw_lock, flags);
896 dev->learning_enabled = enable;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300897 ene_rx_disable(dev);
898 ene_rx_setup(dev);
899 ene_rx_enable(dev);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300900 spin_unlock_irqrestore(&dev->hw_lock, flags);
901 return 0;
902}
903
Maxim Levitskye1b1ddb2010-10-16 19:56:29 -0300904static int ene_set_carrier_report(void *data, int enable)
905{
906 struct ene_device *dev = (struct ene_device *)data;
907 unsigned long flags;
908
909 if (enable == dev->carrier_detect_enabled)
910 return 0;
911
912 spin_lock_irqsave(&dev->hw_lock, flags);
913 dev->carrier_detect_enabled = enable;
914 ene_rx_disable(dev);
915 ene_rx_setup(dev);
916 ene_rx_enable(dev);
917 spin_unlock_irqrestore(&dev->hw_lock, flags);
918 return 0;
919}
920
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300921/* outside interface: enable or disable idle mode */
Maxim Levitsky46519182010-10-16 19:56:28 -0300922static void ene_rx_set_idle(void *data, bool idle)
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300923{
924 struct ene_device *dev = (struct ene_device *)data;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300925
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300926 if (!idle)
927 return;
928
929 dbg("RX: stopping the receiver");
930 ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
931 ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300932}
933
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300934/* outside interface: transmit */
935static int ene_transmit(void *data, int *buf, u32 n)
936{
937 struct ene_device *dev = (struct ene_device *)data;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300938 unsigned long flags;
939
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300940 dev->tx_buffer = buf;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300941 dev->tx_len = n / sizeof(int);
942 dev->tx_pos = 0;
943 dev->tx_reg = 0;
944 dev->tx_done = 0;
945 dev->tx_sample = 0;
946 dev->tx_sample_pulse = 0;
947
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300948 dbg("TX: %d samples", dev->tx_len);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300949
950 spin_lock_irqsave(&dev->hw_lock, flags);
951
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300952 ene_tx_prepare(dev);
953
954 /* Transmit first two samples */
955 ene_tx_sample(dev);
956 ene_tx_sample(dev);
957
958 spin_unlock_irqrestore(&dev->hw_lock, flags);
959
960 if (wait_for_completion_timeout(&dev->tx_complete, 2 * HZ) == 0) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300961 dbg("TX: timeout");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300962 spin_lock_irqsave(&dev->hw_lock, flags);
963 ene_tx_complete(dev);
964 spin_unlock_irqrestore(&dev->hw_lock, flags);
965 } else
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300966 dbg("TX: done");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300967 return n;
968}
969
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300970/* probe entry */
971static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300972{
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300973 int error = -ENOMEM;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300974 struct ir_dev_props *ir_props;
975 struct input_dev *input_dev;
976 struct ene_device *dev;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300977
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300978 /* allocate memory */
979 input_dev = input_allocate_device();
980 ir_props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300981 dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL);
982
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300983 if (!input_dev || !ir_props || !dev)
Jiri Slaby2e75bce2010-10-01 18:13:40 -0300984 goto error1;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300985
986 /* validate resources */
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300987 error = -ENODEV;
988
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300989 if (!pnp_port_valid(pnp_dev, 0) ||
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300990 pnp_port_len(pnp_dev, 0) < ENE_IO_SIZE)
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300991 goto error;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300992
993 if (!pnp_irq_valid(pnp_dev, 0))
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300994 goto error;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300995
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300996 spin_lock_init(&dev->hw_lock);
997
998 /* claim the resources */
999 error = -EBUSY;
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001000 dev->hw_io = pnp_port_start(pnp_dev, 0);
1001 if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
1002 dev->hw_io = -1;
1003 dev->irq = -1;
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001004 goto error;
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001005 }
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001006
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001007 dev->irq = pnp_irq(pnp_dev, 0);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001008 if (request_irq(dev->irq, ene_isr,
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001009 IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) {
1010 dev->irq = -1;
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001011 goto error;
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001012 }
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001013
1014 pnp_set_drvdata(pnp_dev, dev);
1015 dev->pnp_dev = pnp_dev;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001016
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001017 /* don't allow too short/long sample periods */
1018 if (sample_period < 5 || sample_period > 0x7F)
1019 sample_period = ENE_DEFAULT_SAMPLE_PERIOD;
1020
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001021 /* detect hardware version and features */
1022 error = ene_hw_detect(dev);
1023 if (error)
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001024 goto error;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001025
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001026 if (!dev->hw_learning_and_tx_capable && txsim) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001027 dev->hw_learning_and_tx_capable = true;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001028 setup_timer(&dev->tx_sim_timer, ene_tx_irqsim,
1029 (long unsigned int)dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001030 ene_warn("Simulation of TX activated");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001031 }
1032
Maxim Levitskya06423c2010-10-15 13:06:37 -03001033 if (!dev->hw_learning_and_tx_capable)
1034 learning_mode = false;
1035
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001036 ir_props->driver_type = RC_DRIVER_IR_RAW;
1037 ir_props->allowed_protos = IR_TYPE_ALL;
1038 ir_props->priv = dev;
1039 ir_props->open = ene_open;
1040 ir_props->close = ene_close;
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001041 ir_props->s_idle = ene_rx_set_idle;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001042
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001043 dev->props = ir_props;
1044 dev->idev = input_dev;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001045
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001046 if (dev->hw_learning_and_tx_capable) {
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001047 ir_props->s_learning_mode = ene_set_learning_mode;
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001048 init_completion(&dev->tx_complete);
1049 ir_props->tx_ir = ene_transmit;
1050 ir_props->s_tx_mask = ene_set_tx_mask;
1051 ir_props->s_tx_carrier = ene_set_tx_carrier;
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001052 ir_props->s_tx_duty_cycle = ene_set_tx_duty_cycle;
Maxim Levitskye1b1ddb2010-10-16 19:56:29 -03001053 ir_props->s_carrier_report = ene_set_carrier_report;
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001054 }
1055
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001056 ene_setup_hw_buffer(dev);
1057 ene_setup_settings(dev);
1058 ene_rx_setup(dev);
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001059
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001060 device_set_wakeup_capable(&pnp_dev->dev, true);
1061 device_set_wakeup_enable(&pnp_dev->dev, true);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001062
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001063 if (dev->hw_learning_and_tx_capable)
1064 input_dev->name = "ENE eHome Infrared Remote Transceiver";
1065 else
1066 input_dev->name = "ENE eHome Infrared Remote Receiver";
1067
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001068 error = -ENODEV;
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001069 if (ir_input_register(input_dev, RC_MAP_RC6_MCE, ir_props,
1070 ENE_DRIVER_NAME))
1071 goto error;
1072
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001073 ene_notice("driver has been succesfully loaded");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001074 return 0;
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001075error:
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001076 if (dev && dev->irq >= 0)
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001077 free_irq(dev->irq, dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001078 if (dev && dev->hw_io >= 0)
1079 release_region(dev->hw_io, ENE_IO_SIZE);
Jiri Slaby2e75bce2010-10-01 18:13:40 -03001080error1:
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001081 input_free_device(input_dev);
1082 kfree(ir_props);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001083 kfree(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001084 return error;
1085}
1086
1087/* main unload function */
1088static void ene_remove(struct pnp_dev *pnp_dev)
1089{
1090 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
1091 unsigned long flags;
1092
1093 spin_lock_irqsave(&dev->hw_lock, flags);
1094 ene_rx_disable(dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001095 ene_restore_extra_buffer(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001096 spin_unlock_irqrestore(&dev->hw_lock, flags);
1097
1098 free_irq(dev->irq, dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001099 release_region(dev->hw_io, ENE_IO_SIZE);
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001100 ir_input_unregister(dev->idev);
1101 kfree(dev->props);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001102 kfree(dev);
1103}
1104
1105/* enable wake on IR (wakes on specific button on original remote) */
1106static void ene_enable_wake(struct ene_device *dev, int enable)
1107{
1108 enable = enable && device_may_wakeup(&dev->pnp_dev->dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001109 dbg("wake on IR %s", enable ? "enabled" : "disabled");
1110 ene_set_clear_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, enable);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001111}
1112
1113#ifdef CONFIG_PM
1114static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
1115{
1116 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001117 ene_enable_wake(dev, true);
1118
1119 /* TODO: add support for wake pattern */
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001120 return 0;
1121}
1122
1123static int ene_resume(struct pnp_dev *pnp_dev)
1124{
1125 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001126 if (dev->rx_enabled) {
1127 ene_rx_setup(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001128 ene_rx_enable(dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001129 }
1130 ene_enable_wake(dev, false);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001131 return 0;
1132}
1133#endif
1134
1135static void ene_shutdown(struct pnp_dev *pnp_dev)
1136{
1137 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001138 ene_enable_wake(dev, true);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001139}
1140
1141static const struct pnp_device_id ene_ids[] = {
1142 {.id = "ENE0100",},
1143 {.id = "ENE0200",},
1144 {.id = "ENE0201",},
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001145 {.id = "ENE0202",},
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001146 {},
1147};
1148
1149static struct pnp_driver ene_driver = {
1150 .name = ENE_DRIVER_NAME,
1151 .id_table = ene_ids,
1152 .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
1153
1154 .probe = ene_probe,
1155 .remove = __devexit_p(ene_remove),
1156#ifdef CONFIG_PM
1157 .suspend = ene_suspend,
1158 .resume = ene_resume,
1159#endif
1160 .shutdown = ene_shutdown,
1161};
1162
1163static int __init ene_init(void)
1164{
1165 return pnp_register_driver(&ene_driver);
1166}
1167
1168static void ene_exit(void)
1169{
1170 pnp_unregister_driver(&ene_driver);
1171}
1172
1173module_param(sample_period, int, S_IRUGO);
1174MODULE_PARM_DESC(sample_period, "Hardware sample period (50 us default)");
1175
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001176module_param(learning_mode, bool, S_IRUGO);
1177MODULE_PARM_DESC(learning_mode, "Enable learning mode by default");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001178
1179module_param(debug, int, S_IRUGO | S_IWUSR);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001180MODULE_PARM_DESC(debug, "Debug level");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001181
1182module_param(txsim, bool, S_IRUGO);
1183MODULE_PARM_DESC(txsim,
1184 "Simulate TX features on unsupported hardware (dangerous)");
1185
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001186MODULE_DEVICE_TABLE(pnp, ene_ids);
1187MODULE_DESCRIPTION
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001188 ("Infrared input driver for KB3926B/C/D/E/F "
1189 "(aka ENE0100/ENE0200/ENE0201/ENE0202) CIR port");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001190
1191MODULE_AUTHOR("Maxim Levitsky");
1192MODULE_LICENSE("GPL");
1193
1194module_init(ene_init);
1195module_exit(ene_exit);