~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/media/video/cx23885/cx23885-input.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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/slab.h>
 
39
#include <media/rc-core.h>
 
40
#include <media/v4l2-subdev.h>
 
41
 
 
42
#include "cx23885.h"
 
43
 
 
44
#define MODULE_NAME "cx23885"
 
45
 
 
46
static void cx23885_input_process_measurements(struct cx23885_dev *dev,
 
47
                                               bool overrun)
 
48
{
 
49
        struct cx23885_kernel_ir *kernel_ir = dev->kernel_ir;
 
50
 
 
51
        ssize_t num;
 
52
        int count, i;
 
53
        bool handle = false;
 
54
        struct ir_raw_event ir_core_event[64];
 
55
 
 
56
        do {
 
57
                num = 0;
 
58
                v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ir_core_event,
 
59
                                 sizeof(ir_core_event), &num);
 
60
 
 
61
                count = num / sizeof(struct ir_raw_event);
 
62
 
 
63
                for (i = 0; i < count; i++) {
 
64
                        ir_raw_event_store(kernel_ir->rc,
 
65
                                           &ir_core_event[i]);
 
66
                        handle = true;
 
67
                }
 
68
        } while (num != 0);
 
69
 
 
70
        if (overrun)
 
71
                ir_raw_event_reset(kernel_ir->rc);
 
72
        else if (handle)
 
73
                ir_raw_event_handle(kernel_ir->rc);
 
74
}
 
75
 
 
76
void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
 
77
{
 
78
        struct v4l2_subdev_ir_parameters params;
 
79
        int overrun, data_available;
 
80
 
 
81
        if (dev->sd_ir == NULL || events == 0)
 
82
                return;
 
83
 
 
84
        switch (dev->board) {
 
85
        case CX23885_BOARD_HAUPPAUGE_HVR1270:
 
86
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
 
87
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
 
88
        case CX23885_BOARD_TEVII_S470:
 
89
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
 
90
                /*
 
91
                 * The only boards we handle right now.  However other boards
 
92
                 * using the CX2388x integrated IR controller should be similar
 
93
                 */
 
94
                break;
 
95
        default:
 
96
                return;
 
97
        }
 
98
 
 
99
        overrun = events & (V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN |
 
100
                            V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN);
 
101
 
 
102
        data_available = events & (V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED |
 
103
                                   V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ);
 
104
 
 
105
        if (overrun) {
 
106
                /* If there was a FIFO overrun, stop the device */
 
107
                v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
 
108
                params.enable = false;
 
109
                /* Mitigate race with cx23885_input_ir_stop() */
 
110
                params.shutdown = atomic_read(&dev->ir_input_stopping);
 
111
                v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
 
112
        }
 
113
 
 
114
        if (data_available)
 
115
                cx23885_input_process_measurements(dev, overrun);
 
116
 
 
117
        if (overrun) {
 
118
                /* If there was a FIFO overrun, clear & restart the device */
 
119
                params.enable = true;
 
120
                /* Mitigate race with cx23885_input_ir_stop() */
 
121
                params.shutdown = atomic_read(&dev->ir_input_stopping);
 
122
                v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
 
123
        }
 
124
}
 
125
 
 
126
static int cx23885_input_ir_start(struct cx23885_dev *dev)
 
127
{
 
128
        struct v4l2_subdev_ir_parameters params;
 
129
 
 
130
        if (dev->sd_ir == NULL)
 
131
                return -ENODEV;
 
132
 
 
133
        atomic_set(&dev->ir_input_stopping, 0);
 
134
 
 
135
        v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
 
136
        switch (dev->board) {
 
137
        case CX23885_BOARD_HAUPPAUGE_HVR1270:
 
138
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
 
139
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
 
140
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
 
141
                /*
 
142
                 * The IR controller on this board only returns pulse widths.
 
143
                 * Any other mode setting will fail to set up the device.
 
144
                */
 
145
                params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
 
146
                params.enable = true;
 
147
                params.interrupt_enable = true;
 
148
                params.shutdown = false;
 
149
 
 
150
                /* Setup for baseband compatible with both RC-5 and RC-6A */
 
151
                params.modulation = false;
 
152
                /* RC-5:  2,222,222 ns = 1/36 kHz * 32 cycles * 2 marks * 1.25*/
 
153
                /* RC-6A: 3,333,333 ns = 1/36 kHz * 16 cycles * 6 marks * 1.25*/
 
154
                params.max_pulse_width = 3333333; /* ns */
 
155
                /* RC-5:    666,667 ns = 1/36 kHz * 32 cycles * 1 mark * 0.75 */
 
156
                /* RC-6A:   333,333 ns = 1/36 kHz * 16 cycles * 1 mark * 0.75 */
 
157
                params.noise_filter_min_width = 333333; /* ns */
 
158
                /*
 
159
                 * This board has inverted receive sense:
 
160
                 * mark is received as low logic level;
 
161
                 * falling edges are detected as rising edges; etc.
 
162
                 */
 
163
                params.invert_level = true;
 
164
                break;
 
165
        case CX23885_BOARD_TEVII_S470:
 
166
                /*
 
167
                 * The IR controller on this board only returns pulse widths.
 
168
                 * Any other mode setting will fail to set up the device.
 
169
                 */
 
170
                params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH;
 
171
                params.enable = true;
 
172
                params.interrupt_enable = true;
 
173
                params.shutdown = false;
 
174
 
 
175
                /* Setup for a standard NEC protocol */
 
176
                params.carrier_freq = 37917; /* Hz, 455 kHz/12 for NEC */
 
177
                params.carrier_range_lower = 33000; /* Hz */
 
178
                params.carrier_range_upper = 43000; /* Hz */
 
179
                params.duty_cycle = 33; /* percent, 33 percent for NEC */
 
180
 
 
181
                /*
 
182
                 * NEC max pulse width: (64/3)/(455 kHz/12) * 16 nec_units
 
183
                 * (64/3)/(455 kHz/12) * 16 nec_units * 1.375 = 12378022 ns
 
184
                 */
 
185
                params.max_pulse_width = 12378022; /* ns */
 
186
 
 
187
                /*
 
188
                 * NEC noise filter min width: (64/3)/(455 kHz/12) * 1 nec_unit
 
189
                 * (64/3)/(455 kHz/12) * 1 nec_units * 0.625 = 351648 ns
 
190
                 */
 
191
                params.noise_filter_min_width = 351648; /* ns */
 
192
 
 
193
                params.modulation = false;
 
194
                params.invert_level = true;
 
195
                break;
 
196
        }
 
197
        v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
 
198
        return 0;
 
199
}
 
200
 
 
201
static int cx23885_input_ir_open(struct rc_dev *rc)
 
202
{
 
203
        struct cx23885_kernel_ir *kernel_ir = rc->priv;
 
204
 
 
205
        if (kernel_ir->cx == NULL)
 
206
                return -ENODEV;
 
207
 
 
208
        return cx23885_input_ir_start(kernel_ir->cx);
 
209
}
 
210
 
 
211
static void cx23885_input_ir_stop(struct cx23885_dev *dev)
 
212
{
 
213
        struct v4l2_subdev_ir_parameters params;
 
214
 
 
215
        if (dev->sd_ir == NULL)
 
216
                return;
 
217
 
 
218
        /*
 
219
         * Stop the sd_ir subdevice from generating notifications and
 
220
         * scheduling work.
 
221
         * It is shutdown this way in order to mitigate a race with
 
222
         * cx23885_input_rx_work_handler() in the overrun case, which could
 
223
         * re-enable the subdevice.
 
224
         */
 
225
        atomic_set(&dev->ir_input_stopping, 1);
 
226
        v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
 
227
        while (params.shutdown == false) {
 
228
                params.enable = false;
 
229
                params.interrupt_enable = false;
 
230
                params.shutdown = true;
 
231
                v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, &params);
 
232
                v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, &params);
 
233
        }
 
234
        flush_work_sync(&dev->cx25840_work);
 
235
        flush_work_sync(&dev->ir_rx_work);
 
236
        flush_work_sync(&dev->ir_tx_work);
 
237
}
 
238
 
 
239
static void cx23885_input_ir_close(struct rc_dev *rc)
 
240
{
 
241
        struct cx23885_kernel_ir *kernel_ir = rc->priv;
 
242
 
 
243
        if (kernel_ir->cx != NULL)
 
244
                cx23885_input_ir_stop(kernel_ir->cx);
 
245
}
 
246
 
 
247
int cx23885_input_init(struct cx23885_dev *dev)
 
248
{
 
249
        struct cx23885_kernel_ir *kernel_ir;
 
250
        struct rc_dev *rc;
 
251
        char *rc_map;
 
252
        enum rc_driver_type driver_type;
 
253
        unsigned long allowed_protos;
 
254
 
 
255
        int ret;
 
256
 
 
257
        /*
 
258
         * If the IR device (hardware registers, chip, GPIO lines, etc.) isn't
 
259
         * encapsulated in a v4l2_subdev, then I'm not going to deal with it.
 
260
         */
 
261
        if (dev->sd_ir == NULL)
 
262
                return -ENODEV;
 
263
 
 
264
        switch (dev->board) {
 
265
        case CX23885_BOARD_HAUPPAUGE_HVR1270:
 
266
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
 
267
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
 
268
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
 
269
                /* Integrated CX2388[58] IR controller */
 
270
                driver_type = RC_DRIVER_IR_RAW;
 
271
                allowed_protos = RC_TYPE_ALL;
 
272
                /* The grey Hauppauge RC-5 remote */
 
273
                rc_map = RC_MAP_HAUPPAUGE;
 
274
                break;
 
275
        case CX23885_BOARD_TEVII_S470:
 
276
                /* Integrated CX23885 IR controller */
 
277
                driver_type = RC_DRIVER_IR_RAW;
 
278
                allowed_protos = RC_TYPE_ALL;
 
279
                /* A guess at the remote */
 
280
                rc_map = RC_MAP_TEVII_NEC;
 
281
                break;
 
282
        default:
 
283
                return -ENODEV;
 
284
        }
 
285
 
 
286
        /* cx23885 board instance kernel IR state */
 
287
        kernel_ir = kzalloc(sizeof(struct cx23885_kernel_ir), GFP_KERNEL);
 
288
        if (kernel_ir == NULL)
 
289
                return -ENOMEM;
 
290
 
 
291
        kernel_ir->cx = dev;
 
292
        kernel_ir->name = kasprintf(GFP_KERNEL, "cx23885 IR (%s)",
 
293
                                    cx23885_boards[dev->board].name);
 
294
        kernel_ir->phys = kasprintf(GFP_KERNEL, "pci-%s/ir0",
 
295
                                    pci_name(dev->pci));
 
296
 
 
297
        /* input device */
 
298
        rc = rc_allocate_device();
 
299
        if (!rc) {
 
300
                ret = -ENOMEM;
 
301
                goto err_out_free;
 
302
        }
 
303
 
 
304
        kernel_ir->rc = rc;
 
305
        rc->input_name = kernel_ir->name;
 
306
        rc->input_phys = kernel_ir->phys;
 
307
        rc->input_id.bustype = BUS_PCI;
 
308
        rc->input_id.version = 1;
 
309
        if (dev->pci->subsystem_vendor) {
 
310
                rc->input_id.vendor  = dev->pci->subsystem_vendor;
 
311
                rc->input_id.product = dev->pci->subsystem_device;
 
312
        } else {
 
313
                rc->input_id.vendor  = dev->pci->vendor;
 
314
                rc->input_id.product = dev->pci->device;
 
315
        }
 
316
        rc->dev.parent = &dev->pci->dev;
 
317
        rc->driver_type = driver_type;
 
318
        rc->allowed_protos = allowed_protos;
 
319
        rc->priv = kernel_ir;
 
320
        rc->open = cx23885_input_ir_open;
 
321
        rc->close = cx23885_input_ir_close;
 
322
        rc->map_name = rc_map;
 
323
        rc->driver_name = MODULE_NAME;
 
324
 
 
325
        /* Go */
 
326
        dev->kernel_ir = kernel_ir;
 
327
        ret = rc_register_device(rc);
 
328
        if (ret)
 
329
                goto err_out_stop;
 
330
 
 
331
        return 0;
 
332
 
 
333
err_out_stop:
 
334
        cx23885_input_ir_stop(dev);
 
335
        dev->kernel_ir = NULL;
 
336
        rc_free_device(rc);
 
337
err_out_free:
 
338
        kfree(kernel_ir->phys);
 
339
        kfree(kernel_ir->name);
 
340
        kfree(kernel_ir);
 
341
        return ret;
 
342
}
 
343
 
 
344
void cx23885_input_fini(struct cx23885_dev *dev)
 
345
{
 
346
        /* Always stop the IR hardware from generating interrupts */
 
347
        cx23885_input_ir_stop(dev);
 
348
 
 
349
        if (dev->kernel_ir == NULL)
 
350
                return;
 
351
        rc_unregister_device(dev->kernel_ir->rc);
 
352
        kfree(dev->kernel_ir->phys);
 
353
        kfree(dev->kernel_ir->name);
 
354
        kfree(dev->kernel_ir);
 
355
        dev->kernel_ir = NULL;
 
356
}