blob: 752ca908ccb13761c2dadc0b15be2593518d555e [file] [log] [blame]
Hans Verkuil1c1e45d2008-04-28 20:24:33 -03001/*
2 * cx18 driver initialization and card probing
3 *
4 * Derived from ivtv-driver.c
5 *
6 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl>
Andy Wallsc641d092008-09-01 00:40:41 -03007 * Copyright (C) 2008 Andy Walls <awalls@radix.net>
Hans Verkuil1c1e45d2008-04-28 20:24:33 -03008 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22 * 02111-1307 USA
23 */
24
25#include "cx18-driver.h"
Andy Wallsb1526422008-08-30 16:03:44 -030026#include "cx18-io.h"
Hans Verkuil1c1e45d2008-04-28 20:24:33 -030027#include "cx18-version.h"
28#include "cx18-cards.h"
29#include "cx18-i2c.h"
30#include "cx18-irq.h"
31#include "cx18-gpio.h"
32#include "cx18-firmware.h"
33#include "cx18-streams.h"
34#include "cx18-av-core.h"
35#include "cx18-scb.h"
36#include "cx18-mailbox.h"
37#include "cx18-ioctl.h"
38#include "tuner-xc2028.h"
39
40#include <media/tveeprom.h>
41
42
43/* var to keep track of the number of array elements in use */
44int cx18_cards_active;
45
46/* If you have already X v4l cards, then set this to X. This way
47 the device numbers stay matched. Example: you have a WinTV card
48 without radio and a Compro H900 with. Normally this would give a
49 video1 device together with a radio0 device for the Compro. By
50 setting this to 1 you ensure that radio0 is now also radio1. */
51int cx18_first_minor;
52
53/* Master variable for all cx18 info */
54struct cx18 *cx18_cards[CX18_MAX_CARDS];
55
56/* Protects cx18_cards_active */
57DEFINE_SPINLOCK(cx18_cards_lock);
58
Andy Walls18b5dc22008-11-16 17:15:01 -030059/* Queue for deferrable IRQ handling work for all cx18 cards in system */
60struct workqueue_struct *cx18_work_queue;
61
Hans Verkuil1c1e45d2008-04-28 20:24:33 -030062/* add your revision and whatnot here */
63static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
64 {PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418,
65 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
66 {0,}
67};
68
69MODULE_DEVICE_TABLE(pci, cx18_pci_tbl);
70
71/* Parameter declarations */
72static int cardtype[CX18_MAX_CARDS];
73static int tuner[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
74 -1, -1, -1, -1, -1, -1, -1, -1,
75 -1, -1, -1, -1, -1, -1, -1, -1,
76 -1, -1, -1, -1, -1, -1, -1, -1 };
77static int radio[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
78 -1, -1, -1, -1, -1, -1, -1, -1,
79 -1, -1, -1, -1, -1, -1, -1, -1,
80 -1, -1, -1, -1, -1, -1, -1, -1 };
Andy Wallsc641d092008-09-01 00:40:41 -030081static int mmio_ndelay[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
82 -1, -1, -1, -1, -1, -1, -1, -1,
83 -1, -1, -1, -1, -1, -1, -1, -1,
84 -1, -1, -1, -1, -1, -1, -1, -1 };
Hans Verkuilc6eb8ea2008-09-03 17:11:54 -030085static unsigned cardtype_c = 1;
86static unsigned tuner_c = 1;
87static unsigned radio_c = 1;
Hans Verkuil27960732008-09-06 14:02:43 -030088static unsigned mmio_ndelay_c = 1;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -030089static char pal[] = "--";
90static char secam[] = "--";
91static char ntsc[] = "-";
92
93/* Buffers */
94static int enc_mpg_buffers = CX18_DEFAULT_ENC_MPG_BUFFERS;
95static int enc_ts_buffers = CX18_DEFAULT_ENC_TS_BUFFERS;
96static int enc_yuv_buffers = CX18_DEFAULT_ENC_YUV_BUFFERS;
97static int enc_vbi_buffers = CX18_DEFAULT_ENC_VBI_BUFFERS;
98static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS;
99
100static int cx18_pci_latency = 1;
101
Andy Wallsd267d852008-09-28 21:46:02 -0300102int cx18_retry_mmio = 1;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300103int cx18_debug;
104
105module_param_array(tuner, int, &tuner_c, 0644);
106module_param_array(radio, bool, &radio_c, 0644);
107module_param_array(cardtype, int, &cardtype_c, 0644);
Andy Wallsc641d092008-09-01 00:40:41 -0300108module_param_array(mmio_ndelay, int, &mmio_ndelay_c, 0644);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300109module_param_string(pal, pal, sizeof(pal), 0644);
110module_param_string(secam, secam, sizeof(secam), 0644);
111module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
112module_param_named(debug, cx18_debug, int, 0644);
Andy Wallsd267d852008-09-28 21:46:02 -0300113module_param_named(retry_mmio, cx18_retry_mmio, int, 0644);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300114module_param(cx18_pci_latency, int, 0644);
115module_param(cx18_first_minor, int, 0644);
116
117module_param(enc_mpg_buffers, int, 0644);
118module_param(enc_ts_buffers, int, 0644);
119module_param(enc_yuv_buffers, int, 0644);
120module_param(enc_vbi_buffers, int, 0644);
121module_param(enc_pcm_buffers, int, 0644);
122
123MODULE_PARM_DESC(tuner, "Tuner type selection,\n"
124 "\t\t\tsee tuner.h for values");
125MODULE_PARM_DESC(radio,
126 "Enable or disable the radio. Use only if autodetection\n"
127 "\t\t\tfails. 0 = disable, 1 = enable");
128MODULE_PARM_DESC(cardtype,
129 "Only use this option if your card is not detected properly.\n"
130 "\t\tSpecify card type:\n"
131 "\t\t\t 1 = Hauppauge HVR 1600 (ESMT memory)\n"
132 "\t\t\t 2 = Hauppauge HVR 1600 (Samsung memory)\n"
133 "\t\t\t 3 = Compro VideoMate H900\n"
134 "\t\t\t 4 = Yuan MPC718\n"
Sri Deevi03c28082008-06-21 11:06:44 -0300135 "\t\t\t 5 = Conexant Raptor PAL/SECAM\n"
Andy Walls9eee4fb2008-10-04 20:28:40 -0300136 "\t\t\t 6 = Toshiba Qosmio DVB-T/Analog\n"
137 "\t\t\t 7 = Leadtek WinFast PVR2100\n"
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300138 "\t\t\t 0 = Autodetect (default)\n"
139 "\t\t\t-1 = Ignore this card\n\t\t");
140MODULE_PARM_DESC(pal, "Set PAL standard: B, G, H, D, K, I, M, N, Nc, 60");
141MODULE_PARM_DESC(secam, "Set SECAM standard: B, G, H, D, K, L, LC");
142MODULE_PARM_DESC(ntsc, "Set NTSC standard: M, J, K");
143MODULE_PARM_DESC(debug,
144 "Debug level (bitmask). Default: 0\n"
145 "\t\t\t 1/0x0001: warning\n"
146 "\t\t\t 2/0x0002: info\n"
147 "\t\t\t 4/0x0004: mailbox\n"
148 "\t\t\t 8/0x0008: dma\n"
149 "\t\t\t 16/0x0010: ioctl\n"
150 "\t\t\t 32/0x0020: file\n"
151 "\t\t\t 64/0x0040: i2c\n"
152 "\t\t\t128/0x0080: irq\n"
153 "\t\t\t256/0x0100: high volume\n");
154MODULE_PARM_DESC(cx18_pci_latency,
155 "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n"
156 "\t\t\tDefault: Yes");
Andy Wallsd267d852008-09-28 21:46:02 -0300157MODULE_PARM_DESC(retry_mmio,
158 "Check and retry memory mapped IO accesses\n"
159 "\t\t\tDefault: 1 [Yes]");
Andy Wallsc641d092008-09-01 00:40:41 -0300160MODULE_PARM_DESC(mmio_ndelay,
161 "Delay (ns) for each CX23418 memory mapped IO access.\n"
162 "\t\t\tTry larger values that are close to a multiple of the\n"
163 "\t\t\tPCI clock period, 30.3 ns, if your card doesn't work.\n"
164 "\t\t\tDefault: " __stringify(CX18_DEFAULT_MMIO_NDELAY));
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300165MODULE_PARM_DESC(enc_mpg_buffers,
166 "Encoder MPG Buffers (in MB)\n"
167 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_MPG_BUFFERS));
168MODULE_PARM_DESC(enc_ts_buffers,
169 "Encoder TS Buffers (in MB)\n"
170 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_TS_BUFFERS));
171MODULE_PARM_DESC(enc_yuv_buffers,
172 "Encoder YUV Buffers (in MB)\n"
173 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_YUV_BUFFERS));
174MODULE_PARM_DESC(enc_vbi_buffers,
175 "Encoder VBI Buffers (in MB)\n"
176 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_VBI_BUFFERS));
177MODULE_PARM_DESC(enc_pcm_buffers,
178 "Encoder PCM buffers (in MB)\n"
179 "\t\t\tDefault: " __stringify(CX18_DEFAULT_ENC_PCM_BUFFERS));
180
Hans Verkuildd896012008-10-04 08:36:54 -0300181MODULE_PARM_DESC(cx18_first_minor, "Set kernel number assigned to first card");
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300182
183MODULE_AUTHOR("Hans Verkuil");
184MODULE_DESCRIPTION("CX23418 driver");
185MODULE_SUPPORTED_DEVICE("CX23418 MPEG2 encoder");
186MODULE_LICENSE("GPL");
187
188MODULE_VERSION(CX18_VERSION);
189
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300190/* Generic utility functions */
191int cx18_msleep_timeout(unsigned int msecs, int intr)
192{
Andy Walls330c6ec2008-11-08 14:19:37 -0300193 long int timeout = msecs_to_jiffies(msecs);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300194 int sig;
195
196 do {
197 set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
198 timeout = schedule_timeout(timeout);
199 sig = intr ? signal_pending(current) : 0;
200 } while (!sig && timeout);
201 return sig;
202}
203
204/* Release ioremapped memory */
205static void cx18_iounmap(struct cx18 *cx)
206{
207 if (cx == NULL)
208 return;
209
210 /* Release io memory */
211 if (cx->enc_mem != NULL) {
212 CX18_DEBUG_INFO("releasing enc_mem\n");
213 iounmap(cx->enc_mem);
214 cx->enc_mem = NULL;
215 }
216}
217
218/* Hauppauge card? get values from tveeprom */
219void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv)
220{
221 u8 eedata[256];
222
223 cx->i2c_client[0].addr = 0xA0 >> 1;
224 tveeprom_read(&cx->i2c_client[0], eedata, sizeof(eedata));
225 tveeprom_hauppauge_analog(&cx->i2c_client[0], tv, eedata);
226}
227
228static void cx18_process_eeprom(struct cx18 *cx)
229{
230 struct tveeprom tv;
231
232 cx18_read_eeprom(cx, &tv);
233
234 /* Many thanks to Steven Toth from Hauppauge for providing the
235 model numbers */
Hans Verkuil1d081602008-05-12 14:45:19 -0300236 /* Note: the Samsung memory models cannot be reliably determined
237 from the model number. Use the cardtype module option if you
238 have one of these preproduction models. */
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300239 switch (tv.model) {
Hans Verkuil1d081602008-05-12 14:45:19 -0300240 case 74000 ... 74999:
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300241 cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
242 break;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300243 case 0:
244 CX18_ERR("Invalid EEPROM\n");
245 return;
246 default:
247 CX18_ERR("Unknown model %d, defaulting to HVR-1600\n", tv.model);
248 cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
249 break;
250 }
251
252 cx->v4l2_cap = cx->card->v4l2_capabilities;
253 cx->card_name = cx->card->name;
254 cx->card_i2c = cx->card->i2c;
255
256 CX18_INFO("Autodetected %s\n", cx->card_name);
257
258 if (tv.tuner_type == TUNER_ABSENT)
259 CX18_ERR("tveeprom cannot autodetect tuner!");
260
261 if (cx->options.tuner == -1)
262 cx->options.tuner = tv.tuner_type;
263 if (cx->options.radio == -1)
264 cx->options.radio = (tv.has_radio != 0);
265
266 if (cx->std != 0)
267 /* user specified tuner standard */
268 return;
269
270 /* autodetect tuner standard */
271 if (tv.tuner_formats & V4L2_STD_PAL) {
272 CX18_DEBUG_INFO("PAL tuner detected\n");
273 cx->std |= V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
274 } else if (tv.tuner_formats & V4L2_STD_NTSC) {
275 CX18_DEBUG_INFO("NTSC tuner detected\n");
276 cx->std |= V4L2_STD_NTSC_M;
277 } else if (tv.tuner_formats & V4L2_STD_SECAM) {
278 CX18_DEBUG_INFO("SECAM tuner detected\n");
279 cx->std |= V4L2_STD_SECAM_L;
280 } else {
281 CX18_INFO("No tuner detected, default to NTSC-M\n");
282 cx->std |= V4L2_STD_NTSC_M;
283 }
284}
285
286static v4l2_std_id cx18_parse_std(struct cx18 *cx)
287{
288 switch (pal[0]) {
289 case '6':
290 return V4L2_STD_PAL_60;
291 case 'b':
292 case 'B':
293 case 'g':
294 case 'G':
295 return V4L2_STD_PAL_BG;
296 case 'h':
297 case 'H':
298 return V4L2_STD_PAL_H;
299 case 'n':
300 case 'N':
301 if (pal[1] == 'c' || pal[1] == 'C')
302 return V4L2_STD_PAL_Nc;
303 return V4L2_STD_PAL_N;
304 case 'i':
305 case 'I':
306 return V4L2_STD_PAL_I;
307 case 'd':
308 case 'D':
309 case 'k':
310 case 'K':
311 return V4L2_STD_PAL_DK;
312 case 'M':
313 case 'm':
314 return V4L2_STD_PAL_M;
315 case '-':
316 break;
317 default:
318 CX18_WARN("pal= argument not recognised\n");
319 return 0;
320 }
321
322 switch (secam[0]) {
323 case 'b':
324 case 'B':
325 case 'g':
326 case 'G':
327 case 'h':
328 case 'H':
329 return V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
330 case 'd':
331 case 'D':
332 case 'k':
333 case 'K':
334 return V4L2_STD_SECAM_DK;
335 case 'l':
336 case 'L':
337 if (secam[1] == 'C' || secam[1] == 'c')
338 return V4L2_STD_SECAM_LC;
339 return V4L2_STD_SECAM_L;
340 case '-':
341 break;
342 default:
343 CX18_WARN("secam= argument not recognised\n");
344 return 0;
345 }
346
347 switch (ntsc[0]) {
348 case 'm':
349 case 'M':
350 return V4L2_STD_NTSC_M;
351 case 'j':
352 case 'J':
353 return V4L2_STD_NTSC_M_JP;
354 case 'k':
355 case 'K':
356 return V4L2_STD_NTSC_M_KR;
357 case '-':
358 break;
359 default:
360 CX18_WARN("ntsc= argument not recognised\n");
361 return 0;
362 }
363
364 /* no match found */
365 return 0;
366}
367
368static void cx18_process_options(struct cx18 *cx)
369{
370 int i, j;
371
372 cx->options.megabytes[CX18_ENC_STREAM_TYPE_MPG] = enc_mpg_buffers;
373 cx->options.megabytes[CX18_ENC_STREAM_TYPE_TS] = enc_ts_buffers;
374 cx->options.megabytes[CX18_ENC_STREAM_TYPE_YUV] = enc_yuv_buffers;
375 cx->options.megabytes[CX18_ENC_STREAM_TYPE_VBI] = enc_vbi_buffers;
376 cx->options.megabytes[CX18_ENC_STREAM_TYPE_PCM] = enc_pcm_buffers;
377 cx->options.cardtype = cardtype[cx->num];
378 cx->options.tuner = tuner[cx->num];
379 cx->options.radio = radio[cx->num];
380
Andy Wallsc641d092008-09-01 00:40:41 -0300381 if (mmio_ndelay[cx->num] < 0)
382 cx->options.mmio_ndelay = CX18_DEFAULT_MMIO_NDELAY;
383 else
384 cx->options.mmio_ndelay = mmio_ndelay[cx->num];
385
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300386 cx->std = cx18_parse_std(cx);
387 if (cx->options.cardtype == -1) {
388 CX18_INFO("Ignore card\n");
389 return;
390 }
391 cx->card = cx18_get_card(cx->options.cardtype - 1);
392 if (cx->card)
393 CX18_INFO("User specified %s card\n", cx->card->name);
394 else if (cx->options.cardtype != 0)
395 CX18_ERR("Unknown user specified type, trying to autodetect card\n");
396 if (cx->card == NULL) {
397 if (cx->dev->subsystem_vendor == CX18_PCI_ID_HAUPPAUGE) {
398 cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
399 CX18_INFO("Autodetected Hauppauge card\n");
400 }
401 }
402 if (cx->card == NULL) {
403 for (i = 0; (cx->card = cx18_get_card(i)); i++) {
404 if (cx->card->pci_list == NULL)
405 continue;
406 for (j = 0; cx->card->pci_list[j].device; j++) {
407 if (cx->dev->device !=
408 cx->card->pci_list[j].device)
409 continue;
410 if (cx->dev->subsystem_vendor !=
411 cx->card->pci_list[j].subsystem_vendor)
412 continue;
413 if (cx->dev->subsystem_device !=
414 cx->card->pci_list[j].subsystem_device)
415 continue;
416 CX18_INFO("Autodetected %s card\n", cx->card->name);
417 goto done;
418 }
419 }
420 }
421done:
422
423 if (cx->card == NULL) {
424 cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT);
Bjorn Helgaas29e66a62008-09-04 17:24:51 -0300425 CX18_ERR("Unknown card: vendor/device: [%04x:%04x]\n",
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300426 cx->dev->vendor, cx->dev->device);
Bjorn Helgaas29e66a62008-09-04 17:24:51 -0300427 CX18_ERR(" subsystem vendor/device: [%04x:%04x]\n",
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300428 cx->dev->subsystem_vendor, cx->dev->subsystem_device);
429 CX18_ERR("Defaulting to %s card\n", cx->card->name);
430 CX18_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n");
431 CX18_ERR("card you have to the ivtv-devel mailinglist (www.ivtvdriver.org)\n");
432 CX18_ERR("Prefix your subject line with [UNKNOWN CX18 CARD].\n");
433 }
434 cx->v4l2_cap = cx->card->v4l2_capabilities;
435 cx->card_name = cx->card->name;
436 cx->card_i2c = cx->card->i2c;
437}
438
439/* Precondition: the cx18 structure has been memset to 0. Only
440 the dev and num fields have been filled in.
441 No assumptions on the card type may be made here (see cx18_init_struct2
442 for that).
443 */
444static int __devinit cx18_init_struct1(struct cx18 *cx)
445{
Andy Wallsee2d64f2008-11-16 01:38:19 -0300446 int i;
447
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300448 cx->base_addr = pci_resource_start(cx->dev, 0);
449
450 mutex_init(&cx->serialize_lock);
451 mutex_init(&cx->i2c_bus_lock[0]);
452 mutex_init(&cx->i2c_bus_lock[1]);
Andy Walls8abdd002008-07-13 19:05:25 -0300453 mutex_init(&cx->gpio_lock);
Andy Walls72c2d6d2008-11-06 01:15:41 -0300454 mutex_init(&cx->epu2apu_mb_lock);
455 mutex_init(&cx->epu2cpu_mb_lock);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300456
457 spin_lock_init(&cx->lock);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300458
Andy Wallsee2d64f2008-11-16 01:38:19 -0300459 for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++) {
460 cx->epu_work_order[i].cx = cx;
461 cx->epu_work_order[i].str = cx->epu_debug_str;
462 INIT_WORK(&cx->epu_work_order[i].work, cx18_epu_work_handler);
463 }
Andy Walls1d6782b2008-11-05 00:49:14 -0300464
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300465 /* start counting open_id at 1 */
466 cx->open_id = 1;
467
468 /* Initial settings */
469 cx2341x_fill_defaults(&cx->params);
470 cx->temporal_strength = cx->params.video_temporal_filter;
471 cx->spatial_strength = cx->params.video_spatial_filter;
472 cx->filter_mode = cx->params.video_spatial_filter_mode |
473 (cx->params.video_temporal_filter_mode << 1) |
474 (cx->params.video_median_filter_type << 2);
475 cx->params.port = CX2341X_PORT_MEMORY;
Hans Verkuile8b934d2008-06-28 20:57:56 -0300476 cx->params.capabilities = CX2341X_CAP_HAS_TS;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300477 init_waitqueue_head(&cx->cap_w);
478 init_waitqueue_head(&cx->mb_apu_waitq);
479 init_waitqueue_head(&cx->mb_cpu_waitq);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300480 init_waitqueue_head(&cx->dma_waitq);
481
482 /* VBI */
483 cx->vbi.in.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
484 cx->vbi.sliced_in = &cx->vbi.in.fmt.sliced;
485 cx->vbi.raw_size = 1456;
486 cx->vbi.raw_decoder_line_size = 1456;
487 cx->vbi.raw_decoder_sav_odd_field = 0x20;
488 cx->vbi.raw_decoder_sav_even_field = 0x60;
489 cx->vbi.sliced_decoder_line_size = 272;
490 cx->vbi.sliced_decoder_sav_odd_field = 0xB0;
491 cx->vbi.sliced_decoder_sav_even_field = 0xF0;
492 return 0;
493}
494
495/* Second initialization part. Here the card type has been
496 autodetected. */
497static void __devinit cx18_init_struct2(struct cx18 *cx)
498{
499 int i;
500
501 for (i = 0; i < CX18_CARD_MAX_VIDEO_INPUTS; i++)
502 if (cx->card->video_inputs[i].video_type == 0)
503 break;
504 cx->nof_inputs = i;
505 for (i = 0; i < CX18_CARD_MAX_AUDIO_INPUTS; i++)
506 if (cx->card->audio_inputs[i].audio_type == 0)
507 break;
508 cx->nof_audio_inputs = i;
509
510 /* Find tuner input */
511 for (i = 0; i < cx->nof_inputs; i++) {
512 if (cx->card->video_inputs[i].video_type ==
513 CX18_CARD_INPUT_VID_TUNER)
514 break;
515 }
516 if (i == cx->nof_inputs)
517 i = 0;
518 cx->active_input = i;
519 cx->audio_input = cx->card->video_inputs[i].audio_index;
520 cx->av_state.vid_input = CX18_AV_COMPOSITE7;
521 cx->av_state.aud_input = CX18_AV_AUDIO8;
522 cx->av_state.audclk_freq = 48000;
523 cx->av_state.audmode = V4L2_TUNER_MODE_LANG1;
524 cx->av_state.vbi_line_offset = 8;
525}
526
527static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev,
528 const struct pci_device_id *pci_id)
529{
530 u16 cmd;
531 unsigned char pci_latency;
532
533 CX18_DEBUG_INFO("Enabling pci device\n");
534
535 if (pci_enable_device(dev)) {
536 CX18_ERR("Can't enable device %d!\n", cx->num);
537 return -EIO;
538 }
539 if (pci_set_dma_mask(dev, 0xffffffff)) {
540 CX18_ERR("No suitable DMA available on card %d.\n", cx->num);
541 return -EIO;
542 }
543 if (!request_mem_region(cx->base_addr, CX18_MEM_SIZE, "cx18 encoder")) {
544 CX18_ERR("Cannot request encoder memory region on card %d.\n", cx->num);
545 return -EIO;
546 }
547
Andy Walls45190642008-08-29 16:10:21 -0300548 /* Enable bus mastering and memory mapped IO for the CX23418 */
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300549 pci_read_config_word(dev, PCI_COMMAND, &cmd);
Andy Walls45190642008-08-29 16:10:21 -0300550 cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300551 pci_write_config_word(dev, PCI_COMMAND, cmd);
552
553 pci_read_config_byte(dev, PCI_CLASS_REVISION, &cx->card_rev);
554 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
555
556 if (pci_latency < 64 && cx18_pci_latency) {
557 CX18_INFO("Unreasonably low latency timer, "
558 "setting to 64 (was %d)\n", pci_latency);
559 pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
560 pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
561 }
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300562
563 CX18_DEBUG_INFO("cx%d (rev %d) at %02x:%02x.%x, "
564 "irq: %d, latency: %d, memory: 0x%lx\n",
565 cx->dev->device, cx->card_rev, dev->bus->number,
566 PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
567 cx->dev->irq, pci_latency, (unsigned long)cx->base_addr);
568
569 return 0;
570}
571
Hans Verkuil6a4a7932008-05-01 09:34:54 -0300572#ifdef MODULE
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300573static u32 cx18_request_module(struct cx18 *cx, u32 hw,
574 const char *name, u32 id)
575{
576 if ((hw & id) == 0)
577 return hw;
578 if (request_module(name) != 0) {
579 CX18_ERR("Failed to load module %s\n", name);
580 return hw & ~id;
581 }
582 CX18_DEBUG_INFO("Loaded module %s\n", name);
583 return hw;
584}
Hans Verkuil6a4a7932008-05-01 09:34:54 -0300585#endif
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300586
587static void cx18_load_and_init_modules(struct cx18 *cx)
588{
589 u32 hw = cx->card->hw_all;
590 int i;
591
Hans Verkuil6a4a7932008-05-01 09:34:54 -0300592#ifdef MODULE
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300593 /* load modules */
Hans Verkuil58ae1c22008-11-03 08:06:51 -0300594#ifdef CONFIG_MEDIA_TUNER_MODULE
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300595 hw = cx18_request_module(cx, hw, "tuner", CX18_HW_TUNER);
596#endif
Hans Verkuil58ae1c22008-11-03 08:06:51 -0300597#ifdef CONFIG_VIDEO_CS5345_MODULE
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300598 hw = cx18_request_module(cx, hw, "cs5345", CX18_HW_CS5345);
599#endif
Hans Verkuil6a4a7932008-05-01 09:34:54 -0300600#endif
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300601
602 /* check which i2c devices are actually found */
603 for (i = 0; i < 32; i++) {
604 u32 device = 1 << i;
605
606 if (!(device & hw))
607 continue;
608 if (device == CX18_HW_GPIO || device == CX18_HW_TVEEPROM ||
609 device == CX18_HW_CX23418 || device == CX18_HW_DVB) {
610 /* These 'devices' do not use i2c probing */
611 cx->hw_flags |= device;
612 continue;
613 }
614 cx18_i2c_register(cx, i);
615 if (cx18_i2c_hw_addr(cx, device) > 0)
616 cx->hw_flags |= device;
617 }
618
619 hw = cx->hw_flags;
620}
621
622static int __devinit cx18_probe(struct pci_dev *dev,
623 const struct pci_device_id *pci_id)
624{
625 int retval = 0;
Andy Wallsff086572008-10-18 08:51:28 -0300626 int i;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300627 int vbi_buf_size;
628 u32 devtype;
629 struct cx18 *cx;
630
631 spin_lock(&cx18_cards_lock);
632
633 /* Make sure we've got a place for this card */
634 if (cx18_cards_active == CX18_MAX_CARDS) {
635 printk(KERN_ERR "cx18: Maximum number of cards detected (%d).\n",
636 cx18_cards_active);
637 spin_unlock(&cx18_cards_lock);
638 return -ENOMEM;
639 }
640
641 cx = kzalloc(sizeof(struct cx18), GFP_ATOMIC);
Harvey Harrisoncb6969e2008-05-06 20:42:32 -0700642 if (!cx) {
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300643 spin_unlock(&cx18_cards_lock);
644 return -ENOMEM;
645 }
646 cx18_cards[cx18_cards_active] = cx;
647 cx->dev = dev;
648 cx->num = cx18_cards_active++;
Jean Delvareb4ac3c82008-05-13 18:27:15 -0300649 snprintf(cx->name, sizeof(cx->name), "cx18-%d", cx->num);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300650 CX18_INFO("Initializing card #%d\n", cx->num);
651
652 spin_unlock(&cx18_cards_lock);
653
654 cx18_process_options(cx);
655 if (cx->options.cardtype == -1) {
656 retval = -ENODEV;
657 goto err;
658 }
659 if (cx18_init_struct1(cx)) {
660 retval = -ENOMEM;
661 goto err;
662 }
663
664 CX18_DEBUG_INFO("base addr: 0x%08x\n", cx->base_addr);
665
666 /* PCI Device Setup */
667 retval = cx18_setup_pci(cx, dev, pci_id);
668 if (retval != 0) {
669 if (retval == -EIO)
670 goto free_workqueue;
671 else if (retval == -ENXIO)
672 goto free_mem;
673 }
674 /* save cx in the pci struct for later use */
675 pci_set_drvdata(dev, cx);
676
677 /* map io memory */
678 CX18_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n",
679 cx->base_addr + CX18_MEM_OFFSET, CX18_MEM_SIZE);
680 cx->enc_mem = ioremap_nocache(cx->base_addr + CX18_MEM_OFFSET,
681 CX18_MEM_SIZE);
682 if (!cx->enc_mem) {
683 CX18_ERR("ioremap failed, perhaps increasing __VMALLOC_RESERVE in page.h\n");
684 CX18_ERR("or disabling CONFIG_HIGHMEM4G into the kernel would help\n");
685 retval = -ENOMEM;
686 goto free_mem;
687 }
688 cx->reg_mem = cx->enc_mem + CX18_REG_OFFSET;
Andy Wallsb1526422008-08-30 16:03:44 -0300689 devtype = cx18_read_reg(cx, 0xC72028);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300690 switch (devtype & 0xff000000) {
691 case 0xff000000:
692 CX18_INFO("cx23418 revision %08x (A)\n", devtype);
693 break;
694 case 0x01000000:
695 CX18_INFO("cx23418 revision %08x (B)\n", devtype);
696 break;
697 default:
698 CX18_INFO("cx23418 revision %08x (Unknown)\n", devtype);
699 break;
700 }
701
702 cx18_init_power(cx, 1);
703 cx18_init_memory(cx);
704
Al Viro990c81c2008-05-21 00:32:01 -0300705 cx->scb = (struct cx18_scb __iomem *)(cx->enc_mem + SCB_OFFSET);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300706 cx18_init_scb(cx);
707
708 cx18_gpio_init(cx);
709
710 /* active i2c */
711 CX18_DEBUG_INFO("activating i2c...\n");
Andy Walls9b4a7c82008-10-18 10:20:25 -0300712 retval = init_cx18_i2c(cx);
713 if (retval) {
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300714 CX18_ERR("Could not initialize i2c\n");
715 goto free_map;
716 }
717
718 CX18_DEBUG_INFO("Active card count: %d.\n", cx18_cards_active);
719
720 if (cx->card->hw_all & CX18_HW_TVEEPROM) {
721 /* Based on the model number the cardtype may be changed.
722 The PCI IDs are not always reliable. */
723 cx18_process_eeprom(cx);
724 }
725 if (cx->card->comment)
726 CX18_INFO("%s", cx->card->comment);
727 if (cx->card->v4l2_capabilities == 0) {
728 retval = -ENODEV;
729 goto free_i2c;
730 }
731 cx18_init_memory(cx);
732
733 /* Register IRQ */
734 retval = request_irq(cx->dev->irq, cx18_irq_handler,
735 IRQF_SHARED | IRQF_DISABLED, cx->name, (void *)cx);
736 if (retval) {
737 CX18_ERR("Failed to register irq %d\n", retval);
738 goto free_i2c;
739 }
740
741 if (cx->std == 0)
742 cx->std = V4L2_STD_NTSC_M;
743
744 if (cx->options.tuner == -1) {
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300745 for (i = 0; i < CX18_CARD_MAX_TUNERS; i++) {
746 if ((cx->std & cx->card->tuners[i].std) == 0)
747 continue;
748 cx->options.tuner = cx->card->tuners[i].tuner;
749 break;
750 }
751 }
752 /* if no tuner was found, then pick the first tuner in the card list */
753 if (cx->options.tuner == -1 && cx->card->tuners[0].std) {
754 cx->std = cx->card->tuners[0].std;
Hans Verkuilc3cb4d92008-06-27 23:27:25 -0300755 if (cx->std & V4L2_STD_PAL)
756 cx->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H;
757 else if (cx->std & V4L2_STD_NTSC)
758 cx->std = V4L2_STD_NTSC_M;
759 else if (cx->std & V4L2_STD_SECAM)
760 cx->std = V4L2_STD_SECAM_L;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300761 cx->options.tuner = cx->card->tuners[0].tuner;
762 }
763 if (cx->options.radio == -1)
764 cx->options.radio = (cx->card->radio_input.audio_type != 0);
765
766 /* The card is now fully identified, continue with card-specific
767 initialization. */
768 cx18_init_struct2(cx);
769
770 cx18_load_and_init_modules(cx);
771
772 if (cx->std & V4L2_STD_525_60) {
773 cx->is_60hz = 1;
774 cx->is_out_60hz = 1;
775 } else {
776 cx->is_50hz = 1;
777 cx->is_out_50hz = 1;
778 }
779 cx->params.video_gop_size = cx->is_60hz ? 15 : 12;
780
781 cx->stream_buf_size[CX18_ENC_STREAM_TYPE_MPG] = 0x08000;
782 cx->stream_buf_size[CX18_ENC_STREAM_TYPE_TS] = 0x08000;
783 cx->stream_buf_size[CX18_ENC_STREAM_TYPE_PCM] = 0x01200;
784 cx->stream_buf_size[CX18_ENC_STREAM_TYPE_YUV] = 0x20000;
785 vbi_buf_size = cx->vbi.raw_size * (cx->is_60hz ? 24 : 36) / 2;
786 cx->stream_buf_size[CX18_ENC_STREAM_TYPE_VBI] = vbi_buf_size;
787
788 if (cx->options.radio > 0)
789 cx->v4l2_cap |= V4L2_CAP_RADIO;
790
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300791 if (cx->options.tuner > -1) {
792 struct tuner_setup setup;
793
794 setup.addr = ADDR_UNSET;
795 setup.type = cx->options.tuner;
796 setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */
797 setup.tuner_callback = (setup.type == TUNER_XC2028) ?
798 cx18_reset_tuner_gpio : NULL;
799 cx18_call_i2c_clients(cx, TUNER_SET_TYPE_ADDR, &setup);
800 if (setup.type == TUNER_XC2028) {
801 static struct xc2028_ctrl ctrl = {
802 .fname = XC2028_DEFAULT_FIRMWARE,
803 .max_len = 64,
804 };
805 struct v4l2_priv_tun_config cfg = {
806 .tuner = cx->options.tuner,
807 .priv = &ctrl,
808 };
809 cx18_call_i2c_clients(cx, TUNER_SET_CONFIG, &cfg);
810 }
811 }
812
813 /* The tuner is fixed to the standard. The other inputs (e.g. S-Video)
814 are not. */
815 cx->tuner_std = cx->std;
816
Hans Verkuil5e7fdc52008-05-30 10:51:53 -0300817 retval = cx18_streams_setup(cx);
818 if (retval) {
819 CX18_ERR("Error %d setting up streams\n", retval);
820 goto free_irq;
821 }
822 retval = cx18_streams_register(cx);
823 if (retval) {
824 CX18_ERR("Error %d registering devices\n", retval);
825 goto free_streams;
826 }
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300827
828 CX18_INFO("Initialized card #%d: %s\n", cx->num, cx->card_name);
829
830 return 0;
831
832free_streams:
Hans Verkuil3f983872008-05-01 10:31:12 -0300833 cx18_streams_cleanup(cx, 1);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300834free_irq:
835 free_irq(cx->dev->irq, (void *)cx);
836free_i2c:
837 exit_cx18_i2c(cx);
838free_map:
839 cx18_iounmap(cx);
840free_mem:
841 release_mem_region(cx->base_addr, CX18_MEM_SIZE);
842free_workqueue:
843err:
844 if (retval == 0)
845 retval = -ENODEV;
846 CX18_ERR("Error %d on initialization\n", retval);
Andy Wallsd267d852008-09-28 21:46:02 -0300847 cx18_log_statistics(cx);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300848
Andy Wallsff086572008-10-18 08:51:28 -0300849 i = cx->num;
850 spin_lock(&cx18_cards_lock);
851 kfree(cx18_cards[i]);
852 cx18_cards[i] = NULL;
853 spin_unlock(&cx18_cards_lock);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300854 return retval;
855}
856
857int cx18_init_on_first_open(struct cx18 *cx)
858{
859 int video_input;
860 int fw_retry_count = 3;
861 struct v4l2_frequency vf;
Andy Walls3b6fe582008-06-21 08:36:31 -0300862 struct cx18_open_id fh;
863
864 fh.cx = cx;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300865
866 if (test_bit(CX18_F_I_FAILED, &cx->i_flags))
867 return -ENXIO;
868
869 if (test_and_set_bit(CX18_F_I_INITED, &cx->i_flags))
870 return 0;
871
872 while (--fw_retry_count > 0) {
873 /* load firmware */
874 if (cx18_firmware_init(cx) == 0)
875 break;
876 if (fw_retry_count > 1)
877 CX18_WARN("Retry loading firmware\n");
878 }
879
880 if (fw_retry_count == 0) {
881 set_bit(CX18_F_I_FAILED, &cx->i_flags);
882 return -ENXIO;
883 }
884 set_bit(CX18_F_I_LOADED_FW, &cx->i_flags);
885
886 /* Init the firmware twice to work around a silicon bug
887 * transport related. */
888
889 fw_retry_count = 3;
890 while (--fw_retry_count > 0) {
891 /* load firmware */
892 if (cx18_firmware_init(cx) == 0)
893 break;
894 if (fw_retry_count > 1)
895 CX18_WARN("Retry loading firmware\n");
896 }
897
898 if (fw_retry_count == 0) {
899 set_bit(CX18_F_I_FAILED, &cx->i_flags);
900 return -ENXIO;
901 }
902
903 vf.tuner = 0;
904 vf.type = V4L2_TUNER_ANALOG_TV;
905 vf.frequency = 6400; /* the tuner 'baseline' frequency */
906
907 /* Set initial frequency. For PAL/SECAM broadcasts no
908 'default' channel exists AFAIK. */
909 if (cx->std == V4L2_STD_NTSC_M_JP)
910 vf.frequency = 1460; /* ch. 1 91250*16/1000 */
911 else if (cx->std & V4L2_STD_NTSC_M)
912 vf.frequency = 1076; /* ch. 4 67250*16/1000 */
913
914 video_input = cx->active_input;
915 cx->active_input++; /* Force update of input */
Andy Walls3b6fe582008-06-21 08:36:31 -0300916 cx18_s_input(NULL, &fh, video_input);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300917
918 /* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
919 in one place. */
920 cx->std++; /* Force full standard initialization */
Andy Walls3b6fe582008-06-21 08:36:31 -0300921 cx18_s_std(NULL, &fh, &cx->tuner_std);
922 cx18_s_frequency(NULL, &fh, &vf);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300923 return 0;
924}
925
Andy Walls18b5dc22008-11-16 17:15:01 -0300926static void cx18_cancel_epu_work_orders(struct cx18 *cx)
927{
928 int i;
929 for (i = 0; i < CX18_MAX_EPU_WORK_ORDERS; i++)
930 cancel_work_sync(&cx->epu_work_order[i].work);
931}
932
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300933static void cx18_remove(struct pci_dev *pci_dev)
934{
935 struct cx18 *cx = pci_get_drvdata(pci_dev);
936
937 CX18_DEBUG_INFO("Removing Card #%d\n", cx->num);
938
939 /* Stop all captures */
940 CX18_DEBUG_INFO("Stopping all streams\n");
Hans Verkuil31554ae2008-05-25 11:21:27 -0300941 if (atomic_read(&cx->tot_capturing) > 0)
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300942 cx18_stop_all_captures(cx);
943
944 /* Interrupts */
Andy Wallsb1526422008-08-30 16:03:44 -0300945 cx18_sw1_irq_disable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
946 cx18_sw2_irq_disable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300947
948 cx18_halt_firmware(cx);
949
Andy Walls18b5dc22008-11-16 17:15:01 -0300950 cx18_cancel_epu_work_orders(cx);
Andy Walls1d6782b2008-11-05 00:49:14 -0300951
Hans Verkuil3f983872008-05-01 10:31:12 -0300952 cx18_streams_cleanup(cx, 1);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300953
954 exit_cx18_i2c(cx);
955
956 free_irq(cx->dev->irq, (void *)cx);
957
Hans Verkuilcba627a2008-05-12 14:48:26 -0300958 cx18_iounmap(cx);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300959
960 release_mem_region(cx->base_addr, CX18_MEM_SIZE);
961
962 pci_disable_device(cx->dev);
963
Andy Wallsd267d852008-09-28 21:46:02 -0300964 cx18_log_statistics(cx);
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300965 CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num);
966}
967
968/* define a pci_driver for card detection */
969static struct pci_driver cx18_pci_driver = {
970 .name = "cx18",
971 .id_table = cx18_pci_tbl,
972 .probe = cx18_probe,
973 .remove = cx18_remove,
974};
975
976static int module_start(void)
977{
978 printk(KERN_INFO "cx18: Start initialization, version %s\n", CX18_VERSION);
979
980 memset(cx18_cards, 0, sizeof(cx18_cards));
981
982 /* Validate parameters */
983 if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) {
Hans Verkuildd896012008-10-04 08:36:54 -0300984 printk(KERN_ERR "cx18: Exiting, cx18_first_minor must be between 0 and %d\n",
Hans Verkuil1c1e45d2008-04-28 20:24:33 -0300985 CX18_MAX_CARDS - 1);
986 return -1;
987 }
988
989 if (cx18_debug < 0 || cx18_debug > 511) {
990 cx18_debug = 0;
991 printk(KERN_INFO "cx18: Debug value must be >= 0 and <= 511!\n");
992 }
993
Andy Walls18b5dc22008-11-16 17:15:01 -0300994 cx18_work_queue = create_singlethread_workqueue("cx18");
995 if (cx18_work_queue == NULL) {
996 printk(KERN_ERR
997 "cx18: Unable to create work hander thread\n");
998 return -ENOMEM;
999 }
1000
Hans Verkuil1c1e45d2008-04-28 20:24:33 -03001001 if (pci_register_driver(&cx18_pci_driver)) {
1002 printk(KERN_ERR "cx18: Error detecting PCI card\n");
Andy Walls18b5dc22008-11-16 17:15:01 -03001003 destroy_workqueue(cx18_work_queue);
1004 cx18_work_queue = NULL;
Hans Verkuil1c1e45d2008-04-28 20:24:33 -03001005 return -ENODEV;
1006 }
1007 printk(KERN_INFO "cx18: End initialization\n");
1008 return 0;
1009}
1010
1011static void module_cleanup(void)
1012{
1013 int i;
1014
1015 pci_unregister_driver(&cx18_pci_driver);
1016
Andy Walls18b5dc22008-11-16 17:15:01 -03001017 destroy_workqueue(cx18_work_queue);
1018 cx18_work_queue = NULL;
1019
Hans Verkuil1c1e45d2008-04-28 20:24:33 -03001020 for (i = 0; i < cx18_cards_active; i++) {
1021 if (cx18_cards[i] == NULL)
1022 continue;
1023 kfree(cx18_cards[i]);
1024 }
Andy Walls18b5dc22008-11-16 17:15:01 -03001025
Hans Verkuil1c1e45d2008-04-28 20:24:33 -03001026}
1027
1028module_init(module_start);
1029module_exit(module_cleanup);