blob: cf10ecf5acecab604a8b81de83748d64acd05104 [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
Joe Perches7de34612011-08-21 19:56:46 -030033#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
34
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030035#include <linux/kernel.h>
36#include <linux/module.h>
37#include <linux/pnp.h>
38#include <linux/io.h>
39#include <linux/interrupt.h>
40#include <linux/sched.h>
Maxim Levitsky931e39a2010-07-31 11:59:26 -030041#include <linux/slab.h>
Mauro Carvalho Chehab6bda9642010-11-17 13:28:38 -030042#include <media/rc-core.h>
Maxim Levitsky931e39a2010-07-31 11:59:26 -030043#include "ene_ir.h"
Maxim Levitsky9ea53b72010-07-31 11:59:25 -030044
Maxim Levitsky11b64d32010-09-06 18:26:11 -030045static int sample_period;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -030046static bool learning_mode_force;
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) {
Joe Perches7de34612011-08-21 19:56:46 -0300123 pr_warn("device seems to be disabled\n");
124 pr_warn("send a mail to lirc-list@lists.sourceforge.net\n");
125 pr_warn("please attach output of acpidump and dmidecode\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300126 return -ENODEV;
127 }
128
Joe Perches7de34612011-08-21 19:56:46 -0300129 pr_notice("chip is 0x%02x%02x - kbver = 0x%02x, rev = 0x%02x\n",
130 chip_major, chip_minor, old_ver, hw_revision);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300131
Joe Perches7de34612011-08-21 19:56:46 -0300132 pr_notice("PLL freq = %d\n", dev->pll_freq);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300133
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300134 if (chip_major == 0x33) {
Joe Perches7de34612011-08-21 19:56:46 -0300135 pr_warn("chips 0x33xx aren't supported\n");
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;
Joe Perches7de34612011-08-21 19:56:46 -0300141 pr_notice("KB3926C detected\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300142 } else if (old_ver == 0x24 && hw_revision == 0xC0) {
143 dev->hw_revision = ENE_HW_B;
Joe Perches7de34612011-08-21 19:56:46 -0300144 pr_notice("KB3926B detected\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300145 } else {
146 dev->hw_revision = ENE_HW_D;
Joe Perches7de34612011-08-21 19:56:46 -0300147 pr_notice("KB3926D or higher detected\n");
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
Joe Perches7de34612011-08-21 19:56:46 -0300157 pr_notice("Firmware regs: %02x %02x\n", 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
Joe Perches7de34612011-08-21 19:56:46 -0300166 pr_notice("Hardware features:\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300167
168 if (dev->hw_learning_and_tx_capable) {
Joe Perches7de34612011-08-21 19:56:46 -0300169 pr_notice("* Supports transmitting & learning mode\n");
170 pr_notice(" This feature is rare and therefore,\n");
171 pr_notice(" you are welcome to test it,\n");
172 pr_notice(" and/or contact the author via:\n");
173 pr_notice(" lirc-list@lists.sourceforge.net\n");
174 pr_notice(" or maximlevitsky@gmail.com\n");
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300175
Joe Perches7de34612011-08-21 19:56:46 -0300176 pr_notice("* Uses GPIO %s for IR raw input\n",
177 dev->hw_use_gpio_0a ? "40" : "0A");
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300178
179 if (dev->hw_fan_input)
Joe Perches7de34612011-08-21 19:56:46 -0300180 pr_notice("* Uses unused fan feedback input as source of demodulated IR data\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300181 }
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300182
183 if (!dev->hw_fan_input)
Joe Perches7de34612011-08-21 19:56:46 -0300184 pr_notice("* Uses GPIO %s for IR demodulated input\n",
185 dev->hw_use_gpio_0a ? "0A" : "40");
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300186
187 if (dev->hw_extra_buffer)
Joe Perches7de34612011-08-21 19:56:46 -0300188 pr_notice("* Uses new style input buffer\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300189 return 0;
190}
191
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300192/* Read properities of hw sample buffer */
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300193static void ene_rx_setup_hw_buffer(struct ene_device *dev)
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300194{
195 u16 tmp;
196
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300197 ene_rx_read_hw_pointer(dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300198 dev->r_pointer = dev->w_pointer;
199
200 if (!dev->hw_extra_buffer) {
201 dev->buffer_len = ENE_FW_PACKET_SIZE * 2;
202 return;
203 }
204
205 tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER);
206 tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER+1) << 8;
207 dev->extra_buf1_address = tmp;
208
209 dev->extra_buf1_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 2);
210
211 tmp = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 3);
212 tmp |= ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 4) << 8;
213 dev->extra_buf2_address = tmp;
214
215 dev->extra_buf2_len = ene_read_reg(dev, ENE_FW_SAMPLE_BUFFER + 5);
216
217 dev->buffer_len = dev->extra_buf1_len + dev->extra_buf2_len + 8;
218
Joe Perches7de34612011-08-21 19:56:46 -0300219 pr_notice("Hardware uses 2 extended buffers:\n");
220 pr_notice(" 0x%04x - len : %d\n",
221 dev->extra_buf1_address, dev->extra_buf1_len);
222 pr_notice(" 0x%04x - len : %d\n",
223 dev->extra_buf2_address, dev->extra_buf2_len);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300224
Joe Perches7de34612011-08-21 19:56:46 -0300225 pr_notice("Total buffer len = %d\n", dev->buffer_len);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300226
227 if (dev->buffer_len > 64 || dev->buffer_len < 16)
228 goto error;
229
230 if (dev->extra_buf1_address > 0xFBFC ||
231 dev->extra_buf1_address < 0xEC00)
232 goto error;
233
234 if (dev->extra_buf2_address > 0xFBFC ||
235 dev->extra_buf2_address < 0xEC00)
236 goto error;
237
238 if (dev->r_pointer > dev->buffer_len)
239 goto error;
240
241 ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
242 return;
243error:
Joe Perches7de34612011-08-21 19:56:46 -0300244 pr_warn("Error validating extra buffers, device probably won't work\n");
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300245 dev->hw_extra_buffer = false;
246 ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
247}
248
249
250/* Restore the pointers to extra buffers - to make module reload work*/
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300251static void ene_rx_restore_hw_buffer(struct ene_device *dev)
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300252{
253 if (!dev->hw_extra_buffer)
254 return;
255
256 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 0,
257 dev->extra_buf1_address & 0xFF);
258 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 1,
259 dev->extra_buf1_address >> 8);
260 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 2, dev->extra_buf1_len);
261
262 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 3,
263 dev->extra_buf2_address & 0xFF);
264 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 4,
265 dev->extra_buf2_address >> 8);
266 ene_write_reg(dev, ENE_FW_SAMPLE_BUFFER + 5,
267 dev->extra_buf2_len);
268 ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_EXTRA_BUF_HND);
269}
270
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300271/* Read hardware write pointer */
272static void ene_rx_read_hw_pointer(struct ene_device *dev)
273{
274 if (dev->hw_extra_buffer)
275 dev->w_pointer = ene_read_reg(dev, ENE_FW_RX_POINTER);
276 else
277 dev->w_pointer = ene_read_reg(dev, ENE_FW2)
278 & ENE_FW2_BUF_WPTR ? 0 : ENE_FW_PACKET_SIZE;
279
280 dbg_verbose("RB: HW write pointer: %02x, driver read pointer: %02x",
281 dev->w_pointer, dev->r_pointer);
282}
283
284/* Gets address of next sample from HW ring buffer */
285static int ene_rx_get_sample_reg(struct ene_device *dev)
286{
287 int r_pointer;
288
289 if (dev->r_pointer == dev->w_pointer) {
290 dbg_verbose("RB: hit end, try update w_pointer");
291 ene_rx_read_hw_pointer(dev);
292 }
293
294 if (dev->r_pointer == dev->w_pointer) {
295 dbg_verbose("RB: end of data at %d", dev->r_pointer);
296 return 0;
297 }
298
299 dbg_verbose("RB: reading at offset %d", dev->r_pointer);
300 r_pointer = dev->r_pointer;
301
302 dev->r_pointer++;
303 if (dev->r_pointer == dev->buffer_len)
304 dev->r_pointer = 0;
305
306 dbg_verbose("RB: next read will be from offset %d", dev->r_pointer);
307
308 if (r_pointer < 8) {
309 dbg_verbose("RB: read at main buffer at %d", r_pointer);
310 return ENE_FW_SAMPLE_BUFFER + r_pointer;
311 }
312
313 r_pointer -= 8;
314
315 if (r_pointer < dev->extra_buf1_len) {
316 dbg_verbose("RB: read at 1st extra buffer at %d", r_pointer);
317 return dev->extra_buf1_address + r_pointer;
318 }
319
320 r_pointer -= dev->extra_buf1_len;
321
322 if (r_pointer < dev->extra_buf2_len) {
323 dbg_verbose("RB: read at 2nd extra buffer at %d", r_pointer);
324 return dev->extra_buf2_address + r_pointer;
325 }
326
327 dbg("attempt to read beyong ring bufer end");
328 return 0;
329}
330
331/* Sense current received carrier */
332void ene_rx_sense_carrier(struct ene_device *dev)
333{
334 DEFINE_IR_RAW_EVENT(ev);
335
336 int carrier, duty_cycle;
337 int period = ene_read_reg(dev, ENE_CIRCAR_PRD);
338 int hperiod = ene_read_reg(dev, ENE_CIRCAR_HPRD);
339
340 if (!(period & ENE_CIRCAR_PRD_VALID))
341 return;
342
343 period &= ~ENE_CIRCAR_PRD_VALID;
344
345 if (!period)
346 return;
347
348 dbg("RX: hardware carrier period = %02x", period);
349 dbg("RX: hardware carrier pulse period = %02x", hperiod);
350
351 carrier = 2000000 / period;
352 duty_cycle = (hperiod * 100) / period;
353 dbg("RX: sensed carrier = %d Hz, duty cycle %d%%",
354 carrier, duty_cycle);
355 if (dev->carrier_detect_enabled) {
356 ev.carrier_report = true;
357 ev.carrier = carrier;
358 ev.duty_cycle = duty_cycle;
David Härdemand8b4b582010-10-29 16:08:23 -0300359 ir_raw_event_store(dev->rdev, &ev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300360 }
361}
362
363/* this enables/disables the CIR RX engine */
364static void ene_rx_enable_cir_engine(struct ene_device *dev, bool enable)
365{
366 ene_set_clear_reg_mask(dev, ENE_CIRCFG,
367 ENE_CIRCFG_RX_EN | ENE_CIRCFG_RX_IRQ, enable);
368}
369
370/* this selects input for CIR engine. Ether GPIO 0A or GPIO40*/
371static void ene_rx_select_input(struct ene_device *dev, bool gpio_0a)
372{
373 ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_GPIO0A, gpio_0a);
374}
375
376/*
377 * this enables alternative input via fan tachometer sensor and bypasses
378 * the hw CIR engine
379 */
380static void ene_rx_enable_fan_input(struct ene_device *dev, bool enable)
381{
382 if (!dev->hw_fan_input)
383 return;
384
385 if (!enable)
386 ene_write_reg(dev, ENE_FAN_AS_IN1, 0);
387 else {
388 ene_write_reg(dev, ENE_FAN_AS_IN1, ENE_FAN_AS_IN1_EN);
389 ene_write_reg(dev, ENE_FAN_AS_IN2, ENE_FAN_AS_IN2_EN);
390 }
391}
392
393/* setup the receiver for RX*/
394static void ene_rx_setup(struct ene_device *dev)
395{
396 bool learning_mode = dev->learning_mode_enabled ||
397 dev->carrier_detect_enabled;
398 int sample_period_adjust = 0;
399
400 dbg("RX: setup receiver, learning mode = %d", learning_mode);
401
402
403 /* This selects RLC input and clears CFG2 settings */
404 ene_write_reg(dev, ENE_CIRCFG2, 0x00);
405
406 /* set sample period*/
407 if (sample_period == ENE_DEFAULT_SAMPLE_PERIOD)
408 sample_period_adjust =
409 dev->pll_freq == ENE_DEFAULT_PLL_FREQ ? 1 : 2;
410
411 ene_write_reg(dev, ENE_CIRRLC_CFG,
412 (sample_period + sample_period_adjust) |
413 ENE_CIRRLC_CFG_OVERFLOW);
414 /* revB doesn't support inputs */
415 if (dev->hw_revision < ENE_HW_C)
416 goto select_timeout;
417
418 if (learning_mode) {
419
420 WARN_ON(!dev->hw_learning_and_tx_capable);
421
422 /* Enable the opposite of the normal input
423 That means that if GPIO40 is normally used, use GPIO0A
424 and vice versa.
425 This input will carry non demodulated
426 signal, and we will tell the hw to demodulate it itself */
427 ene_rx_select_input(dev, !dev->hw_use_gpio_0a);
428 dev->rx_fan_input_inuse = false;
429
430 /* Enable carrier demodulation */
431 ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD);
432
433 /* Enable carrier detection */
434 ene_write_reg(dev, ENE_CIRCAR_PULS, 0x63);
435 ene_set_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT,
436 dev->carrier_detect_enabled || debug);
437 } else {
438 if (dev->hw_fan_input)
439 dev->rx_fan_input_inuse = true;
440 else
441 ene_rx_select_input(dev, dev->hw_use_gpio_0a);
442
443 /* Disable carrier detection & demodulation */
444 ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_CARR_DEMOD);
445 ene_clear_reg_mask(dev, ENE_CIRCFG2, ENE_CIRCFG2_CARR_DETECT);
446 }
447
448select_timeout:
449 if (dev->rx_fan_input_inuse) {
Jarod Wilson5aad7242011-01-06 16:59:36 -0300450 dev->rdev->rx_resolution = US_TO_NS(ENE_FW_SAMPLE_PERIOD_FAN);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300451
452 /* Fan input doesn't support timeouts, it just ends the
453 input with a maximum sample */
David Härdemand8b4b582010-10-29 16:08:23 -0300454 dev->rdev->min_timeout = dev->rdev->max_timeout =
Jarod Wilson5aad7242011-01-06 16:59:36 -0300455 US_TO_NS(ENE_FW_SMPL_BUF_FAN_MSK *
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300456 ENE_FW_SAMPLE_PERIOD_FAN);
457 } else {
Jarod Wilson5aad7242011-01-06 16:59:36 -0300458 dev->rdev->rx_resolution = US_TO_NS(sample_period);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300459
460 /* Theoreticly timeout is unlimited, but we cap it
461 * because it was seen that on one device, it
462 * would stop sending spaces after around 250 msec.
463 * Besides, this is close to 2^32 anyway and timeout is u32.
464 */
Jarod Wilson5aad7242011-01-06 16:59:36 -0300465 dev->rdev->min_timeout = US_TO_NS(127 * sample_period);
466 dev->rdev->max_timeout = US_TO_NS(200000);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300467 }
468
469 if (dev->hw_learning_and_tx_capable)
Jarod Wilson5aad7242011-01-06 16:59:36 -0300470 dev->rdev->tx_resolution = US_TO_NS(sample_period);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300471
David Härdemand8b4b582010-10-29 16:08:23 -0300472 if (dev->rdev->timeout > dev->rdev->max_timeout)
473 dev->rdev->timeout = dev->rdev->max_timeout;
474 if (dev->rdev->timeout < dev->rdev->min_timeout)
475 dev->rdev->timeout = dev->rdev->min_timeout;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300476}
477
478/* Enable the device for receive */
479static void ene_rx_enable(struct ene_device *dev)
480{
481 u8 reg_value;
482
483 /* Enable system interrupt */
484 if (dev->hw_revision < ENE_HW_C) {
485 ene_write_reg(dev, ENEB_IRQ, dev->irq << 1);
486 ene_write_reg(dev, ENEB_IRQ_UNK1, 0x01);
487 } else {
488 reg_value = ene_read_reg(dev, ENE_IRQ) & 0xF0;
489 reg_value |= ENE_IRQ_UNK_EN;
490 reg_value &= ~ENE_IRQ_STATUS;
491 reg_value |= (dev->irq & ENE_IRQ_MASK);
492 ene_write_reg(dev, ENE_IRQ, reg_value);
493 }
494
495 /* Enable inputs */
496 ene_rx_enable_fan_input(dev, dev->rx_fan_input_inuse);
497 ene_rx_enable_cir_engine(dev, !dev->rx_fan_input_inuse);
498
499 /* ack any pending irqs - just in case */
500 ene_irq_status(dev);
501
502 /* enable firmware bits */
503 ene_set_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ);
504
505 /* enter idle mode */
David Härdemand8b4b582010-10-29 16:08:23 -0300506 ir_raw_event_set_idle(dev->rdev, true);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300507 dev->rx_enabled = true;
508}
509
510/* Disable the device receiver */
511static void ene_rx_disable(struct ene_device *dev)
512{
513 /* disable inputs */
514 ene_rx_enable_cir_engine(dev, false);
515 ene_rx_enable_fan_input(dev, false);
516
517 /* disable hardware IRQ and firmware flag */
518 ene_clear_reg_mask(dev, ENE_FW1, ENE_FW1_ENABLE | ENE_FW1_IRQ);
519
David Härdemand8b4b582010-10-29 16:08:23 -0300520 ir_raw_event_set_idle(dev->rdev, true);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300521 dev->rx_enabled = false;
522}
523
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300524/* This resets the receiver. Useful to stop stream of spaces at end of
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300525 * transmission
526 */
527static void ene_rx_reset(struct ene_device *dev)
528{
529 ene_clear_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
530 ene_set_reg_mask(dev, ENE_CIRCFG, ENE_CIRCFG_RX_EN);
531}
532
533/* Set up the TX carrier frequency and duty cycle */
534static void ene_tx_set_carrier(struct ene_device *dev)
535{
536 u8 tx_puls_width;
537 unsigned long flags;
538
539 spin_lock_irqsave(&dev->hw_lock, flags);
540
541 ene_set_clear_reg_mask(dev, ENE_CIRCFG,
542 ENE_CIRCFG_TX_CARR, dev->tx_period > 0);
543
544 if (!dev->tx_period)
545 goto unlock;
546
547 BUG_ON(dev->tx_duty_cycle >= 100 || dev->tx_duty_cycle <= 0);
548
549 tx_puls_width = dev->tx_period / (100 / dev->tx_duty_cycle);
550
551 if (!tx_puls_width)
552 tx_puls_width = 1;
553
554 dbg("TX: pulse distance = %d * 500 ns", dev->tx_period);
555 dbg("TX: pulse width = %d * 500 ns", tx_puls_width);
556
557 ene_write_reg(dev, ENE_CIRMOD_PRD, dev->tx_period | ENE_CIRMOD_PRD_POL);
558 ene_write_reg(dev, ENE_CIRMOD_HPRD, tx_puls_width);
559unlock:
560 spin_unlock_irqrestore(&dev->hw_lock, flags);
561}
562
563/* Enable/disable transmitters */
564static void ene_tx_set_transmitters(struct ene_device *dev)
565{
566 unsigned long flags;
567
568 spin_lock_irqsave(&dev->hw_lock, flags);
569 ene_set_clear_reg_mask(dev, ENE_GPIOFS8, ENE_GPIOFS8_GPIO41,
570 !!(dev->transmitter_mask & 0x01));
571 ene_set_clear_reg_mask(dev, ENE_GPIOFS1, ENE_GPIOFS1_GPIO0D,
572 !!(dev->transmitter_mask & 0x02));
573 spin_unlock_irqrestore(&dev->hw_lock, flags);
574}
575
576/* prepare transmission */
577static void ene_tx_enable(struct ene_device *dev)
578{
579 u8 conf1 = ene_read_reg(dev, ENE_CIRCFG);
580 u8 fwreg2 = ene_read_reg(dev, ENE_FW2);
581
582 dev->saved_conf1 = conf1;
583
584 /* Show information about currently connected transmitter jacks */
585 if (fwreg2 & ENE_FW2_EMMITER1_CONN)
586 dbg("TX: Transmitter #1 is connected");
587
588 if (fwreg2 & ENE_FW2_EMMITER2_CONN)
589 dbg("TX: Transmitter #2 is connected");
590
591 if (!(fwreg2 & (ENE_FW2_EMMITER1_CONN | ENE_FW2_EMMITER2_CONN)))
Joe Perches7de34612011-08-21 19:56:46 -0300592 pr_warn("TX: transmitter cable isn't connected!\n");
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300593
594 /* disable receive on revc */
595 if (dev->hw_revision == ENE_HW_C)
596 conf1 &= ~ENE_CIRCFG_RX_EN;
597
598 /* Enable TX engine */
599 conf1 |= ENE_CIRCFG_TX_EN | ENE_CIRCFG_TX_IRQ;
600 ene_write_reg(dev, ENE_CIRCFG, conf1);
601}
602
603/* end transmission */
604static void ene_tx_disable(struct ene_device *dev)
605{
606 ene_write_reg(dev, ENE_CIRCFG, dev->saved_conf1);
607 dev->tx_buffer = NULL;
608}
609
610
611/* TX one sample - must be called with dev->hw_lock*/
612static void ene_tx_sample(struct ene_device *dev)
613{
614 u8 raw_tx;
615 u32 sample;
616 bool pulse = dev->tx_sample_pulse;
617
618 if (!dev->tx_buffer) {
Joe Perches7de34612011-08-21 19:56:46 -0300619 pr_warn("TX: BUG: attempt to transmit NULL buffer\n");
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300620 return;
621 }
622
623 /* Grab next TX sample */
624 if (!dev->tx_sample) {
625
626 if (dev->tx_pos == dev->tx_len) {
627 if (!dev->tx_done) {
628 dbg("TX: no more data to send");
629 dev->tx_done = true;
630 goto exit;
631 } else {
632 dbg("TX: last sample sent by hardware");
633 ene_tx_disable(dev);
634 complete(&dev->tx_complete);
635 return;
636 }
637 }
638
639 sample = dev->tx_buffer[dev->tx_pos++];
640 dev->tx_sample_pulse = !dev->tx_sample_pulse;
641
642 dev->tx_sample = DIV_ROUND_CLOSEST(sample, sample_period);
643
644 if (!dev->tx_sample)
645 dev->tx_sample = 1;
646 }
647
648 raw_tx = min(dev->tx_sample , (unsigned int)ENE_CIRRLC_OUT_MASK);
649 dev->tx_sample -= raw_tx;
650
651 dbg("TX: sample %8d (%s)", raw_tx * sample_period,
652 pulse ? "pulse" : "space");
653 if (pulse)
654 raw_tx |= ENE_CIRRLC_OUT_PULSE;
655
656 ene_write_reg(dev,
657 dev->tx_reg ? ENE_CIRRLC_OUT1 : ENE_CIRRLC_OUT0, raw_tx);
658
659 dev->tx_reg = !dev->tx_reg;
660exit:
661 /* simulate TX done interrupt */
662 if (txsim)
663 mod_timer(&dev->tx_sim_timer, jiffies + HZ / 500);
664}
665
666/* timer to simulate tx done interrupt */
667static void ene_tx_irqsim(unsigned long data)
668{
669 struct ene_device *dev = (struct ene_device *)data;
670 unsigned long flags;
671
672 spin_lock_irqsave(&dev->hw_lock, flags);
673 ene_tx_sample(dev);
674 spin_unlock_irqrestore(&dev->hw_lock, flags);
675}
676
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300677
678/* read irq status and ack it */
679static int ene_irq_status(struct ene_device *dev)
680{
681 u8 irq_status;
682 u8 fw_flags1, fw_flags2;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300683 int retval = 0;
684
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300685 fw_flags2 = ene_read_reg(dev, ENE_FW2);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300686
687 if (dev->hw_revision < ENE_HW_C) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300688 irq_status = ene_read_reg(dev, ENEB_IRQ_STATUS);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300689
690 if (!(irq_status & ENEB_IRQ_STATUS_IR))
691 return 0;
692
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300693 ene_clear_reg_mask(dev, ENEB_IRQ_STATUS, ENEB_IRQ_STATUS_IR);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300694 return ENE_IRQ_RX;
695 }
696
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300697 irq_status = ene_read_reg(dev, ENE_IRQ);
698 if (!(irq_status & ENE_IRQ_STATUS))
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300699 return 0;
700
701 /* original driver does that twice - a workaround ? */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300702 ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS);
703 ene_write_reg(dev, ENE_IRQ, irq_status & ~ENE_IRQ_STATUS);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300704
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300705 /* check RX interrupt */
706 if (fw_flags2 & ENE_FW2_RXIRQ) {
707 retval |= ENE_IRQ_RX;
708 ene_write_reg(dev, ENE_FW2, fw_flags2 & ~ENE_FW2_RXIRQ);
709 }
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300710
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300711 /* check TX interrupt */
712 fw_flags1 = ene_read_reg(dev, ENE_FW1);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300713 if (fw_flags1 & ENE_FW1_TXIRQ) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300714 ene_write_reg(dev, ENE_FW1, fw_flags1 & ~ENE_FW1_TXIRQ);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300715 retval |= ENE_IRQ_TX;
716 }
717
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300718 return retval;
719}
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300720
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300721/* interrupt handler */
722static irqreturn_t ene_isr(int irq, void *data)
723{
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300724 u16 hw_value, reg;
725 int hw_sample, irq_status;
726 bool pulse;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300727 unsigned long flags;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300728 irqreturn_t retval = IRQ_NONE;
729 struct ene_device *dev = (struct ene_device *)data;
Maxim Levitsky46519182010-10-16 19:56:28 -0300730 DEFINE_IR_RAW_EVENT(ev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300731
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300732 spin_lock_irqsave(&dev->hw_lock, flags);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300733
734 dbg_verbose("ISR called");
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300735 ene_rx_read_hw_pointer(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300736 irq_status = ene_irq_status(dev);
737
738 if (!irq_status)
739 goto unlock;
740
741 retval = IRQ_HANDLED;
742
743 if (irq_status & ENE_IRQ_TX) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300744 dbg_verbose("TX interrupt");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300745 if (!dev->hw_learning_and_tx_capable) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300746 dbg("TX interrupt on unsupported device!");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300747 goto unlock;
748 }
749 ene_tx_sample(dev);
750 }
751
752 if (!(irq_status & ENE_IRQ_RX))
753 goto unlock;
754
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300755 dbg_verbose("RX interrupt");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300756
Maxim Levitskye1b1ddb2010-10-16 19:56:29 -0300757 if (dev->hw_learning_and_tx_capable)
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300758 ene_rx_sense_carrier(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300759
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300760 /* On hardware that don't support extra buffer we need to trust
761 the interrupt and not track the read pointer */
762 if (!dev->hw_extra_buffer)
763 dev->r_pointer = dev->w_pointer == 0 ? ENE_FW_PACKET_SIZE : 0;
764
765 while (1) {
766
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300767 reg = ene_rx_get_sample_reg(dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300768
769 dbg_verbose("next sample to read at: %04x", reg);
770 if (!reg)
771 break;
772
773 hw_value = ene_read_reg(dev, reg);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300774
775 if (dev->rx_fan_input_inuse) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300776
777 int offset = ENE_FW_SMPL_BUF_FAN - ENE_FW_SAMPLE_BUFFER;
778
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300779 /* read high part of the sample */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300780 hw_value |= ene_read_reg(dev, reg + offset) << 8;
781 pulse = hw_value & ENE_FW_SMPL_BUF_FAN_PLS;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300782
783 /* clear space bit, and other unused bits */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300784 hw_value &= ENE_FW_SMPL_BUF_FAN_MSK;
785 hw_sample = hw_value * ENE_FW_SAMPLE_PERIOD_FAN;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300786
787 } else {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300788 pulse = !(hw_value & ENE_FW_SAMPLE_SPACE);
789 hw_value &= ~ENE_FW_SAMPLE_SPACE;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300790 hw_sample = hw_value * sample_period;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300791
792 if (dev->rx_period_adjust) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300793 hw_sample *= 100;
794 hw_sample /= (100 + dev->rx_period_adjust);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300795 }
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300796 }
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300797
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300798 if (!dev->hw_extra_buffer && !hw_sample) {
799 dev->r_pointer = dev->w_pointer;
800 continue;
801 }
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300802
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300803 dbg("RX: %d (%s)", hw_sample, pulse ? "pulse" : "space");
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300804
Jarod Wilson5aad7242011-01-06 16:59:36 -0300805 ev.duration = US_TO_NS(hw_sample);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300806 ev.pulse = pulse;
David Härdemand8b4b582010-10-29 16:08:23 -0300807 ir_raw_event_store_with_filter(dev->rdev, &ev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300808 }
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300809
David Härdemand8b4b582010-10-29 16:08:23 -0300810 ir_raw_event_handle(dev->rdev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300811unlock:
812 spin_unlock_irqrestore(&dev->hw_lock, flags);
813 return retval;
814}
815
816/* Initialize default settings */
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300817static void ene_setup_default_settings(struct ene_device *dev)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300818{
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300819 dev->tx_period = 32;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300820 dev->tx_duty_cycle = 50; /*%*/
821 dev->transmitter_mask = 0x03;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300822 dev->learning_mode_enabled = learning_mode_force;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300823
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300824 /* Set reasonable default timeout */
Jarod Wilson5aad7242011-01-06 16:59:36 -0300825 dev->rdev->timeout = US_TO_NS(150000);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300826}
827
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300828/* Upload all hardware settings at once. Used at load and resume time */
829static void ene_setup_hw_settings(struct ene_device *dev)
830{
831 if (dev->hw_learning_and_tx_capable) {
832 ene_tx_set_carrier(dev);
833 ene_tx_set_transmitters(dev);
834 }
835
836 ene_rx_setup(dev);
837}
838
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300839/* outside interface: called on first open*/
David Härdemand8b4b582010-10-29 16:08:23 -0300840static int ene_open(struct rc_dev *rdev)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300841{
David Härdemand8b4b582010-10-29 16:08:23 -0300842 struct ene_device *dev = rdev->priv;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300843 unsigned long flags;
844
845 spin_lock_irqsave(&dev->hw_lock, flags);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300846 ene_rx_enable(dev);
847 spin_unlock_irqrestore(&dev->hw_lock, flags);
848 return 0;
849}
850
851/* outside interface: called on device close*/
David Härdemand8b4b582010-10-29 16:08:23 -0300852static void ene_close(struct rc_dev *rdev)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300853{
David Härdemand8b4b582010-10-29 16:08:23 -0300854 struct ene_device *dev = rdev->priv;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300855 unsigned long flags;
856 spin_lock_irqsave(&dev->hw_lock, flags);
857
858 ene_rx_disable(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300859 spin_unlock_irqrestore(&dev->hw_lock, flags);
860}
861
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300862/* outside interface: set transmitter mask */
David Härdemand8b4b582010-10-29 16:08:23 -0300863static int ene_set_tx_mask(struct rc_dev *rdev, u32 tx_mask)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300864{
David Härdemand8b4b582010-10-29 16:08:23 -0300865 struct ene_device *dev = rdev->priv;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300866 dbg("TX: attempt to set transmitter mask %02x", tx_mask);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300867
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300868 /* invalid txmask */
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300869 if (!tx_mask || tx_mask & ~0x03) {
870 dbg("TX: invalid mask");
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300871 /* return count of transmitters */
872 return 2;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300873 }
874
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300875 dev->transmitter_mask = tx_mask;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300876 ene_tx_set_transmitters(dev);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300877 return 0;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300878}
879
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300880/* outside interface : set tx carrier */
David Härdemand8b4b582010-10-29 16:08:23 -0300881static int ene_set_tx_carrier(struct rc_dev *rdev, u32 carrier)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300882{
David Härdemand8b4b582010-10-29 16:08:23 -0300883 struct ene_device *dev = rdev->priv;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300884 u32 period = 2000000 / carrier;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300885
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300886 dbg("TX: attempt to set tx carrier to %d kHz", carrier);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300887
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300888 if (period && (period > ENE_CIRMOD_PRD_MAX ||
889 period < ENE_CIRMOD_PRD_MIN)) {
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300890
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300891 dbg("TX: out of range %d-%d kHz carrier",
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300892 2000 / ENE_CIRMOD_PRD_MIN, 2000 / ENE_CIRMOD_PRD_MAX);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300893 return -1;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300894 }
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300895
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300896 dev->tx_period = period;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300897 ene_tx_set_carrier(dev);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300898 return 0;
899}
900
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300901/*outside interface : set tx duty cycle */
David Härdemand8b4b582010-10-29 16:08:23 -0300902static int ene_set_tx_duty_cycle(struct rc_dev *rdev, u32 duty_cycle)
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300903{
David Härdemand8b4b582010-10-29 16:08:23 -0300904 struct ene_device *dev = rdev->priv;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300905 dbg("TX: setting duty cycle to %d%%", duty_cycle);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300906 dev->tx_duty_cycle = duty_cycle;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300907 ene_tx_set_carrier(dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300908 return 0;
909}
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300910
911/* outside interface: enable learning mode */
David Härdemand8b4b582010-10-29 16:08:23 -0300912static int ene_set_learning_mode(struct rc_dev *rdev, int enable)
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300913{
David Härdemand8b4b582010-10-29 16:08:23 -0300914 struct ene_device *dev = rdev->priv;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300915 unsigned long flags;
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300916 if (enable == dev->learning_mode_enabled)
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300917 return 0;
918
919 spin_lock_irqsave(&dev->hw_lock, flags);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300920 dev->learning_mode_enabled = enable;
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300921 ene_rx_disable(dev);
922 ene_rx_setup(dev);
923 ene_rx_enable(dev);
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300924 spin_unlock_irqrestore(&dev->hw_lock, flags);
925 return 0;
926}
927
David Härdemand8b4b582010-10-29 16:08:23 -0300928static int ene_set_carrier_report(struct rc_dev *rdev, int enable)
Maxim Levitskye1b1ddb2010-10-16 19:56:29 -0300929{
David Härdemand8b4b582010-10-29 16:08:23 -0300930 struct ene_device *dev = rdev->priv;
Maxim Levitskye1b1ddb2010-10-16 19:56:29 -0300931 unsigned long flags;
932
933 if (enable == dev->carrier_detect_enabled)
934 return 0;
935
936 spin_lock_irqsave(&dev->hw_lock, flags);
937 dev->carrier_detect_enabled = enable;
938 ene_rx_disable(dev);
939 ene_rx_setup(dev);
940 ene_rx_enable(dev);
941 spin_unlock_irqrestore(&dev->hw_lock, flags);
942 return 0;
943}
944
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300945/* outside interface: enable or disable idle mode */
David Härdemand8b4b582010-10-29 16:08:23 -0300946static void ene_set_idle(struct rc_dev *rdev, bool idle)
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300947{
David Härdemand8b4b582010-10-29 16:08:23 -0300948 struct ene_device *dev = rdev->priv;
949
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300950 if (idle) {
David Härdemand8b4b582010-10-29 16:08:23 -0300951 ene_rx_reset(dev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300952 dbg("RX: end of data");
953 }
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300954}
955
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300956/* outside interface: transmit */
David Härdeman5588dc22011-04-28 12:13:58 -0300957static int ene_transmit(struct rc_dev *rdev, unsigned *buf, unsigned n)
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300958{
David Härdemand8b4b582010-10-29 16:08:23 -0300959 struct ene_device *dev = rdev->priv;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300960 unsigned long flags;
961
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300962 dev->tx_buffer = buf;
David Härdeman5588dc22011-04-28 12:13:58 -0300963 dev->tx_len = n;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300964 dev->tx_pos = 0;
965 dev->tx_reg = 0;
966 dev->tx_done = 0;
967 dev->tx_sample = 0;
968 dev->tx_sample_pulse = 0;
969
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300970 dbg("TX: %d samples", dev->tx_len);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300971
972 spin_lock_irqsave(&dev->hw_lock, flags);
973
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300974 ene_tx_enable(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300975
976 /* Transmit first two samples */
977 ene_tx_sample(dev);
978 ene_tx_sample(dev);
979
980 spin_unlock_irqrestore(&dev->hw_lock, flags);
981
982 if (wait_for_completion_timeout(&dev->tx_complete, 2 * HZ) == 0) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300983 dbg("TX: timeout");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300984 spin_lock_irqsave(&dev->hw_lock, flags);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -0300985 ene_tx_disable(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300986 spin_unlock_irqrestore(&dev->hw_lock, flags);
987 } else
Maxim Levitsky11b64d32010-09-06 18:26:11 -0300988 dbg("TX: done");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300989 return n;
990}
991
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300992/* probe entry */
993static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300994{
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300995 int error = -ENOMEM;
David Härdemand8b4b582010-10-29 16:08:23 -0300996 struct rc_dev *rdev;
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300997 struct ene_device *dev;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -0300998
Maxim Levitsky931e39a2010-07-31 11:59:26 -0300999 /* allocate memory */
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001000 dev = kzalloc(sizeof(struct ene_device), GFP_KERNEL);
David Härdemand8b4b582010-10-29 16:08:23 -03001001 rdev = rc_allocate_device();
1002 if (!dev || !rdev)
Jiri Slaby2e75bce2010-10-01 18:13:40 -03001003 goto error1;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001004
1005 /* validate resources */
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001006 error = -ENODEV;
1007
Kyle McMartin2e4c5562011-01-06 16:59:33 -03001008 /* init these to -1, as 0 is valid for both */
1009 dev->hw_io = -1;
1010 dev->irq = -1;
1011
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001012 if (!pnp_port_valid(pnp_dev, 0) ||
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001013 pnp_port_len(pnp_dev, 0) < ENE_IO_SIZE)
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001014 goto error;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001015
1016 if (!pnp_irq_valid(pnp_dev, 0))
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001017 goto error;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001018
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001019 spin_lock_init(&dev->hw_lock);
1020
1021 /* claim the resources */
1022 error = -EBUSY;
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001023 dev->hw_io = pnp_port_start(pnp_dev, 0);
1024 if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
1025 dev->hw_io = -1;
1026 dev->irq = -1;
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001027 goto error;
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001028 }
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001029
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001030 dev->irq = pnp_irq(pnp_dev, 0);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001031 if (request_irq(dev->irq, ene_isr,
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001032 IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) {
1033 dev->irq = -1;
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001034 goto error;
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001035 }
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001036
1037 pnp_set_drvdata(pnp_dev, dev);
1038 dev->pnp_dev = pnp_dev;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001039
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001040 /* don't allow too short/long sample periods */
1041 if (sample_period < 5 || sample_period > 0x7F)
1042 sample_period = ENE_DEFAULT_SAMPLE_PERIOD;
1043
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001044 /* detect hardware version and features */
1045 error = ene_hw_detect(dev);
1046 if (error)
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001047 goto error;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001048
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001049 if (!dev->hw_learning_and_tx_capable && txsim) {
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001050 dev->hw_learning_and_tx_capable = true;
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001051 setup_timer(&dev->tx_sim_timer, ene_tx_irqsim,
1052 (long unsigned int)dev);
Joe Perches7de34612011-08-21 19:56:46 -03001053 pr_warn("Simulation of TX activated\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001054 }
1055
Maxim Levitskya06423c2010-10-15 13:06:37 -03001056 if (!dev->hw_learning_and_tx_capable)
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -03001057 learning_mode_force = false;
Maxim Levitskya06423c2010-10-15 13:06:37 -03001058
David Härdemand8b4b582010-10-29 16:08:23 -03001059 rdev->driver_type = RC_DRIVER_IR_RAW;
Mauro Carvalho Chehab52b66142010-11-17 14:20:52 -03001060 rdev->allowed_protos = RC_TYPE_ALL;
David Härdemand8b4b582010-10-29 16:08:23 -03001061 rdev->priv = dev;
1062 rdev->open = ene_open;
1063 rdev->close = ene_close;
1064 rdev->s_idle = ene_set_idle;
1065 rdev->driver_name = ENE_DRIVER_NAME;
1066 rdev->map_name = RC_MAP_RC6_MCE;
1067 rdev->input_name = "ENE eHome Infrared Remote Receiver";
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001068
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001069 if (dev->hw_learning_and_tx_capable) {
David Härdemand8b4b582010-10-29 16:08:23 -03001070 rdev->s_learning_mode = ene_set_learning_mode;
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001071 init_completion(&dev->tx_complete);
David Härdemand8b4b582010-10-29 16:08:23 -03001072 rdev->tx_ir = ene_transmit;
1073 rdev->s_tx_mask = ene_set_tx_mask;
1074 rdev->s_tx_carrier = ene_set_tx_carrier;
1075 rdev->s_tx_duty_cycle = ene_set_tx_duty_cycle;
1076 rdev->s_carrier_report = ene_set_carrier_report;
1077 rdev->input_name = "ENE eHome Infrared Remote Transceiver";
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001078 }
1079
Kyle McMartin2e4c5562011-01-06 16:59:33 -03001080 dev->rdev = rdev;
1081
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -03001082 ene_rx_setup_hw_buffer(dev);
1083 ene_setup_default_settings(dev);
1084 ene_setup_hw_settings(dev);
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001085
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001086 device_set_wakeup_capable(&pnp_dev->dev, true);
1087 device_set_wakeup_enable(&pnp_dev->dev, true);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001088
David Härdemand8b4b582010-10-29 16:08:23 -03001089 error = rc_register_device(rdev);
1090 if (error < 0)
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001091 goto error;
1092
Joe Perches7de34612011-08-21 19:56:46 -03001093 pr_notice("driver has been successfully loaded\n");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001094 return 0;
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001095error:
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001096 if (dev && dev->irq >= 0)
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001097 free_irq(dev->irq, dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001098 if (dev && dev->hw_io >= 0)
1099 release_region(dev->hw_io, ENE_IO_SIZE);
Jiri Slaby2e75bce2010-10-01 18:13:40 -03001100error1:
David Härdemand8b4b582010-10-29 16:08:23 -03001101 rc_free_device(rdev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001102 kfree(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001103 return error;
1104}
1105
1106/* main unload function */
1107static void ene_remove(struct pnp_dev *pnp_dev)
1108{
1109 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
1110 unsigned long flags;
1111
1112 spin_lock_irqsave(&dev->hw_lock, flags);
1113 ene_rx_disable(dev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -03001114 ene_rx_restore_hw_buffer(dev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001115 spin_unlock_irqrestore(&dev->hw_lock, flags);
1116
1117 free_irq(dev->irq, dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001118 release_region(dev->hw_io, ENE_IO_SIZE);
David Härdemand8b4b582010-10-29 16:08:23 -03001119 rc_unregister_device(dev->rdev);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001120 kfree(dev);
1121}
1122
1123/* enable wake on IR (wakes on specific button on original remote) */
1124static void ene_enable_wake(struct ene_device *dev, int enable)
1125{
1126 enable = enable && device_may_wakeup(&dev->pnp_dev->dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001127 dbg("wake on IR %s", enable ? "enabled" : "disabled");
1128 ene_set_clear_reg_mask(dev, ENE_FW1, ENE_FW1_WAKE, enable);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001129}
1130
1131#ifdef CONFIG_PM
1132static int ene_suspend(struct pnp_dev *pnp_dev, pm_message_t state)
1133{
1134 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001135 ene_enable_wake(dev, true);
1136
1137 /* TODO: add support for wake pattern */
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001138 return 0;
1139}
1140
1141static int ene_resume(struct pnp_dev *pnp_dev)
1142{
1143 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -03001144 ene_setup_hw_settings(dev);
1145
1146 if (dev->rx_enabled)
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001147 ene_rx_enable(dev);
Maxim Levitskyc29bc4d2010-10-16 19:56:30 -03001148
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001149 ene_enable_wake(dev, false);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001150 return 0;
1151}
1152#endif
1153
1154static void ene_shutdown(struct pnp_dev *pnp_dev)
1155{
1156 struct ene_device *dev = pnp_get_drvdata(pnp_dev);
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001157 ene_enable_wake(dev, true);
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001158}
1159
1160static const struct pnp_device_id ene_ids[] = {
1161 {.id = "ENE0100",},
1162 {.id = "ENE0200",},
1163 {.id = "ENE0201",},
Maxim Levitsky931e39a2010-07-31 11:59:26 -03001164 {.id = "ENE0202",},
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001165 {},
1166};
1167
1168static struct pnp_driver ene_driver = {
1169 .name = ENE_DRIVER_NAME,
1170 .id_table = ene_ids,
1171 .flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
1172
1173 .probe = ene_probe,
1174 .remove = __devexit_p(ene_remove),
1175#ifdef CONFIG_PM
1176 .suspend = ene_suspend,
1177 .resume = ene_resume,
1178#endif
1179 .shutdown = ene_shutdown,
1180};
1181
1182static int __init ene_init(void)
1183{
1184 return pnp_register_driver(&ene_driver);
1185}
1186
1187static void ene_exit(void)
1188{
1189 pnp_unregister_driver(&ene_driver);
1190}
1191
1192module_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
Maxim Levitsky11b64d32010-09-06 18:26:11 -03001207 ("Infrared input driver for KB3926B/C/D/E/F "
1208 "(aka ENE0100/ENE0200/ENE0201/ENE0202) CIR port");
Maxim Levitsky9ea53b72010-07-31 11:59:25 -03001209
1210MODULE_AUTHOR("Maxim Levitsky");
1211MODULE_LICENSE("GPL");
1212
1213module_init(ene_init);
1214module_exit(ene_exit);