]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/media/video/cx23885/cx23885-input.c
V4L/DVB: cx23885, cx25840: Report the actual length of an IR Rx timeout event
[mv-sheeva.git] / drivers / media / video / cx23885 / cx23885-input.c
1 /*
2  *  Driver for the Conexant CX23885/7/8 PCIe bridge
3  *
4  *  Infrared remote control input device
5  *
6  *  Most of this file is
7  *
8  *  Copyright (C) 2009  Andy Walls <awalls@md.metrocast.net>
9  *
10  *  However, the cx23885_input_{init,fini} functions contained herein are
11  *  derived from Linux kernel files linux/media/video/.../...-input.c marked as:
12  *
13  *  Copyright (C) 2008 <srinivasa.deevi at conexant dot com>
14  *  Copyright (C) 2005 Ludovico Cavedon <cavedon@sssup.it>
15  *                     Markus Rechberger <mrechberger@gmail.com>
16  *                     Mauro Carvalho Chehab <mchehab@infradead.org>
17  *                     Sascha Sommer <saschasommer@freenet.de>
18  *  Copyright (C) 2004, 2005 Chris Pascoe
19  *  Copyright (C) 2003, 2004 Gerd Knorr
20  *  Copyright (C) 2003 Pavel Machek
21  *
22  *  This program is free software; you can redistribute it and/or
23  *  modify it under the terms of the GNU General Public License
24  *  as published by the Free Software Foundation; either version 2
25  *  of the License, or (at your option) any later version.
26  *
27  *  This program is distributed in the hope that it will be useful,
28  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
29  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30  *  GNU General Public License for more details.
31  *
32  *  You should have received a copy of the GNU General Public License
33  *  along with this program; if not, write to the Free Software
34  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
35  *  02110-1301, USA.
36  */
37
38 #include <linux/input.h>
39 #include <linux/slab.h>
40 #include <media/ir-core.h>
41 #include <media/v4l2-subdev.h>
42
43 #include "cx23885.h"
44
45 #define MODULE_NAME "cx23885"
46
47 static void convert_measurement(u32 x, struct ir_raw_event *y)
48 {
49         y->pulse = (x & V4L2_SUBDEV_IR_PULSE_LEVEL_MASK) ? true : false;
50         y->duration = x & V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
51 }
52
53 static void cx23885_input_process_measurements(struct cx23885_dev *dev,
54                                                bool overrun)
55 {
56         struct cx23885_kernel_ir *kernel_ir = dev->kernel_ir;
57         struct ir_raw_event kernel_ir_event;
58
59         u32 sd_ir_data[64];
60         ssize_t num;
61         int count, i;
62         bool handle = false;
63
64         do {
65                 num = 0;
66                 v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) sd_ir_data,
67                                  sizeof(sd_ir_data), &num);
68
69                 count = num / sizeof(u32);
70
71                 for (i = 0; i < count; i++) {
72                         convert_measurement(sd_ir_data[i], &kernel_ir_event);
73                         ir_raw_event_store(kernel_ir->inp_dev,
74                                            &kernel_ir_event);
75                         handle = true;
76                 }
77         } while (num != 0);
78
79         if (overrun)
80                 ir_raw_event_reset(kernel_ir->inp_dev);
81         else if (handle)
82                 ir_raw_event_handle(kernel_ir->inp_dev);
83 }
84
85 void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
86 {
87         struct v4l2_subdev_ir_parameters params;
88         int overrun, data_available;
89
90         if (dev->sd_ir == NULL || events == 0)
91                 return;
92
93         switch (dev->board) {
94         case CX23885_BOARD_HAUPPAUGE_HVR1850:
95         case CX23885_BOARD_HAUPPAUGE_HVR1290:
96         case CX23885_BOARD_TEVII_S470:
97         case CX23885_BOARD_HAUPPAUGE_HVR1250:
98                 /*
99                  * The only boards we handle right now.  However other boards
100                  * using the CX2388x integrated IR controller should be similar
101                  */
102                 break;
103         default:
104                 return;
105         }
106
107         overrun = events & (V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN |
108                             V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN);
109
110         data_available = events & (V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED |
111                                    V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ);
112
113         if (overrun) {
114                 /* If there was a FIFO overrun, stop the device */
115                 v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
116                 params.enable = false;
117                 /* Mitigate race with cx23885_input_ir_stop() */
118                 params.shutdown = atomic_read(&dev->ir_input_stopping);
119                 v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
120         }
121
122         if (data_available)
123                 cx23885_input_process_measurements(dev, overrun);
124
125         if (overrun) {
126                 /* If there was a FIFO overrun, clear & restart the device */
127                 params.enable = true;
128                 /* Mitigate race with cx23885_input_ir_stop() */
129                 params.shutdown = atomic_read(&dev->ir_input_stopping);
130                 v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
131         }
132 }
133
134 static int cx23885_input_ir_start(struct cx23885_dev *dev)
135 {
136         struct v4l2_subdev_ir_parameters params;
137
138         if (dev->sd_ir == NULL)
139                 return -ENODEV;
140
141         atomic_set(&dev->ir_input_stopping, 0);
142
143         v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
144         switch (dev->board) {
145         case CX23885_BOARD_HAUPPAUGE_HVR1850:
146         case CX23885_BOARD_HAUPPAUGE_HVR1290:
147         case CX23885_BOARD_HAUPPAUGE_HVR1250:
148                 /*
149                  * The IR controller on this board only returns pulse widths.
150                  * Any other mode setting will fail to set up the device.
151                 */
152                 params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
153                 params.enable = true;
154                 params.interrupt_enable = true;
155                 params.shutdown = false;
156
157                 /* Setup for baseband compatible with both RC-5 and RC-6A */
158                 params.modulation = false;
159                 /* RC-5:  2,222,222 ns = 1/36 kHz * 32 cycles * 2 marks * 1.25*/
160                 /* RC-6A: 3,333,333 ns = 1/36 kHz * 16 cycles * 6 marks * 1.25*/
161                 params.max_pulse_width = 3333333; /* ns */
162                 /* RC-5:    666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */
163                 /* RC-6A:   333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */
164                 params.noise_filter_min_width = 333333; /* ns */
165                 /*
166                  * This board has inverted receive sense:
167                  * mark is received as low logic level;
168                  * falling edges are detected as rising edges; etc.
169                  */
170                 params.invert_level = true;
171                 break;
172         case CX23885_BOARD_TEVII_S470:
173                 /*
174                  * The IR controller on this board only returns pulse widths.
175                  * Any other mode setting will fail to set up the device.
176                  */
177                 params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
178                 params.enable = true;
179                 params.interrupt_enable = true;
180                 params.shutdown = false;
181
182                 /* Setup for a standard NEC protocol */
183                 params.carrier_freq = 37917; /* Hz, 455 kHz/12 for NEC */
184                 params.carrier_range_lower = 33000; /* Hz */
185                 params.carrier_range_upper = 43000; /* Hz */
186                 params.duty_cycle = 33; /* percent, 33 percent for NEC */
187
188                 /*
189                  * NEC max pulse width: (64/3)/(455 kHz/12) * 16 nec_units
190                  * (64/3)/(455 kHz/12) * 16 nec_units * 1.375 = 12378022 ns
191                  */
192                 params.max_pulse_width = 12378022; /* ns */
193
194                 /*
195                  * NEC noise filter min width: (64/3)/(455 kHz/12) * 1 nec_unit
196                  * (64/3)/(455 kHz/12) * 1 nec_units * 0.625 = 351648 ns
197                  */
198                 params.noise_filter_min_width = 351648; /* ns */
199
200                 params.modulation = false;
201                 params.invert_level = true;
202                 break;
203         }
204         v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
205         return 0;
206 }
207
208 static int cx23885_input_ir_open(void *priv)
209 {
210         struct cx23885_kernel_ir *kernel_ir = priv;
211
212         if (kernel_ir->cx == NULL)
213                 return -ENODEV;
214
215         return cx23885_input_ir_start(kernel_ir->cx);
216 }
217
218 static void cx23885_input_ir_stop(struct cx23885_dev *dev)
219 {
220         struct v4l2_subdev_ir_parameters params;
221
222         if (dev->sd_ir == NULL)
223                 return;
224
225         /*
226          * Stop the sd_ir subdevice from generating notifications and
227          * scheduling work.
228          * It is shutdown this way in order to mitigate a race with
229          * cx23885_input_rx_work_handler() in the overrun case, which could
230          * re-enable the subdevice.
231          */
232         atomic_set(&dev->ir_input_stopping, 1);
233         v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
234         while (params.shutdown == false) {
235                 params.enable = false;
236                 params.interrupt_enable = false;
237                 params.shutdown = true;
238                 v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
239                 v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
240         }
241
242         flush_scheduled_work();
243 }
244
245 static void cx23885_input_ir_close(void *priv)
246 {
247         struct cx23885_kernel_ir *kernel_ir = priv;
248
249         if (kernel_ir->cx != NULL)
250                 cx23885_input_ir_stop(kernel_ir->cx);
251 }
252
253 int cx23885_input_init(struct cx23885_dev *dev)
254 {
255         struct cx23885_kernel_ir *kernel_ir;
256         struct input_dev *inp_dev;
257         struct ir_dev_props *props;
258
259         char *rc_map;
260         enum rc_driver_type driver_type;
261         unsigned long allowed_protos;
262
263         int ret;
264
265         /*
266          * If the IR device (hardware registers, chip, GPIO lines, etc.) isn't
267          * encapsulated in a v4l2_subdev, then I'm not going to deal with it.
268          */
269         if (dev->sd_ir == NULL)
270                 return -ENODEV;
271
272         switch (dev->board) {
273         case CX23885_BOARD_HAUPPAUGE_HVR1850:
274         case CX23885_BOARD_HAUPPAUGE_HVR1290:
275         case CX23885_BOARD_HAUPPAUGE_HVR1250:
276                 /* Integrated CX2388[58] IR controller */
277                 driver_type = RC_DRIVER_IR_RAW;
278                 allowed_protos = IR_TYPE_ALL;
279                 /* The grey Hauppauge RC-5 remote */
280                 rc_map = RC_MAP_RC5_HAUPPAUGE_NEW;
281                 break;
282         case CX23885_BOARD_TEVII_S470:
283                 /* Integrated CX23885 IR controller */
284                 driver_type = RC_DRIVER_IR_RAW;
285                 allowed_protos = IR_TYPE_ALL;
286                 /* A guess at the remote */
287                 rc_map = RC_MAP_TEVII_NEC;
288                 break;
289         default:
290                 return -ENODEV;
291         }
292
293         /* cx23885 board instance kernel IR state */
294         kernel_ir = kzalloc(sizeof(struct cx23885_kernel_ir), GFP_KERNEL);
295         if (kernel_ir == NULL)
296                 return -ENOMEM;
297
298         kernel_ir->cx = dev;
299         kernel_ir->name = kasprintf(GFP_KERNEL, "cx23885 IR (%s)",
300                                     cx23885_boards[dev->board].name);
301         kernel_ir->phys = kasprintf(GFP_KERNEL, "pci-%s/ir0",
302                                     pci_name(dev->pci));
303
304         /* input device */
305         inp_dev = input_allocate_device();
306         if (inp_dev == NULL) {
307                 ret = -ENOMEM;
308                 goto err_out_free;
309         }
310
311         kernel_ir->inp_dev = inp_dev;
312         inp_dev->name = kernel_ir->name;
313         inp_dev->phys = kernel_ir->phys;
314         inp_dev->id.bustype = BUS_PCI;
315         inp_dev->id.version = 1;
316         if (dev->pci->subsystem_vendor) {
317                 inp_dev->id.vendor  = dev->pci->subsystem_vendor;
318                 inp_dev->id.product = dev->pci->subsystem_device;
319         } else {
320                 inp_dev->id.vendor  = dev->pci->vendor;
321                 inp_dev->id.product = dev->pci->device;
322         }
323         inp_dev->dev.parent = &dev->pci->dev;
324
325         /* kernel ir device properties */
326         props = &kernel_ir->props;
327         props->driver_type = driver_type;
328         props->allowed_protos = allowed_protos;
329         props->priv = kernel_ir;
330         props->open = cx23885_input_ir_open;
331         props->close = cx23885_input_ir_close;
332
333         /* Go */
334         dev->kernel_ir = kernel_ir;
335         ret = ir_input_register(inp_dev, rc_map, props, MODULE_NAME);
336         if (ret)
337                 goto err_out_stop;
338
339         return 0;
340
341 err_out_stop:
342         cx23885_input_ir_stop(dev);
343         dev->kernel_ir = NULL;
344         /* TODO: double check clean-up of kernel_ir->inp_dev */
345 err_out_free:
346         kfree(kernel_ir->phys);
347         kfree(kernel_ir->name);
348         kfree(kernel_ir);
349         return ret;
350 }
351
352 void cx23885_input_fini(struct cx23885_dev *dev)
353 {
354         /* Always stop the IR hardware from generating interrupts */
355         cx23885_input_ir_stop(dev);
356
357         if (dev->kernel_ir == NULL)
358                 return;
359         ir_input_unregister(dev->kernel_ir->inp_dev);
360         kfree(dev->kernel_ir->phys);
361         kfree(dev->kernel_ir->name);
362         kfree(dev->kernel_ir);
363         dev->kernel_ir = NULL;
364 }