blob: afa0cfce657802983553c66e4bd35450afe38de3 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 *
3 * device driver for philips saa7134 based TV cards
4 * driver core
5 *
6 * (c) 2001-03 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23#include <linux/config.h>
24#include <linux/init.h>
25#include <linux/list.h>
26#include <linux/module.h>
27#include <linux/moduleparam.h>
28#include <linux/kernel.h>
29#include <linux/slab.h>
30#include <linux/kmod.h>
31#include <linux/sound.h>
32#include <linux/interrupt.h>
33#include <linux/delay.h>
34
35#include "saa7134-reg.h"
36#include "saa7134.h"
37
38MODULE_DESCRIPTION("v4l2 driver module for saa7130/34 based TV cards");
39MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
40MODULE_LICENSE("GPL");
41
42/* ------------------------------------------------------------------ */
43
44static unsigned int irq_debug = 0;
45module_param(irq_debug, int, 0644);
46MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
47
48static unsigned int core_debug = 0;
49module_param(core_debug, int, 0644);
50MODULE_PARM_DESC(core_debug,"enable debug messages [core]");
51
52static unsigned int gpio_tracking = 0;
53module_param(gpio_tracking, int, 0644);
54MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]");
55
56static unsigned int oss = 0;
57module_param(oss, int, 0444);
58MODULE_PARM_DESC(oss,"register oss devices (default: no)");
59
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -080060static unsigned int alsa = 0;
61module_param(alsa, int, 0444);
62MODULE_PARM_DESC(alsa,"register alsa devices (default: no)");
63
Linus Torvalds1da177e2005-04-16 15:20:36 -070064static unsigned int latency = UNSET;
65module_param(latency, int, 0444);
66MODULE_PARM_DESC(latency,"pci latency timer");
67
68static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
69static unsigned int vbi_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
70static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
71static unsigned int dsp_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
72static unsigned int mixer_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
73static unsigned int tuner[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
74static unsigned int card[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
75
76module_param_array(video_nr, int, NULL, 0444);
77module_param_array(vbi_nr, int, NULL, 0444);
78module_param_array(radio_nr, int, NULL, 0444);
79module_param_array(dsp_nr, int, NULL, 0444);
80module_param_array(mixer_nr, int, NULL, 0444);
81module_param_array(tuner, int, NULL, 0444);
82module_param_array(card, int, NULL, 0444);
83
84MODULE_PARM_DESC(video_nr, "video device number");
85MODULE_PARM_DESC(vbi_nr, "vbi device number");
86MODULE_PARM_DESC(radio_nr, "radio device number");
87MODULE_PARM_DESC(dsp_nr, "oss dsp device number");
88MODULE_PARM_DESC(mixer_nr, "oss mixer device number");
89MODULE_PARM_DESC(tuner, "tuner type");
90MODULE_PARM_DESC(card, "card type");
91
92static DECLARE_MUTEX(devlist_lock);
93LIST_HEAD(saa7134_devlist);
94static LIST_HEAD(mops_list);
95static unsigned int saa7134_devcount;
96
97#define dprintk(fmt, arg...) if (core_debug) \
98 printk(KERN_DEBUG "%s/core: " fmt, dev->name , ## arg)
99
100/* ------------------------------------------------------------------ */
101/* debug help functions */
102
103static const char *v4l1_ioctls[] = {
104 "0", "GCAP", "GCHAN", "SCHAN", "GTUNER", "STUNER", "GPICT", "SPICT",
105 "CCAPTURE", "GWIN", "SWIN", "GFBUF", "SFBUF", "KEY", "GFREQ",
106 "SFREQ", "GAUDIO", "SAUDIO", "SYNC", "MCAPTURE", "GMBUF", "GUNIT",
107 "GCAPTURE", "SCAPTURE", "SPLAYMODE", "SWRITEMODE", "GPLAYINFO",
108 "SMICROCODE", "GVBIFMT", "SVBIFMT" };
109#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
110
111static const char *v4l2_ioctls[] = {
112 "QUERYCAP", "1", "ENUM_PIXFMT", "ENUM_FBUFFMT", "G_FMT", "S_FMT",
113 "G_COMP", "S_COMP", "REQBUFS", "QUERYBUF", "G_FBUF", "S_FBUF",
114 "G_WIN", "S_WIN", "PREVIEW", "QBUF", "16", "DQBUF", "STREAMON",
115 "STREAMOFF", "G_PERF", "G_PARM", "S_PARM", "G_STD", "S_STD",
116 "ENUMSTD", "ENUMINPUT", "G_CTRL", "S_CTRL", "G_TUNER", "S_TUNER",
117 "G_FREQ", "S_FREQ", "G_AUDIO", "S_AUDIO", "35", "QUERYCTRL",
118 "QUERYMENU", "G_INPUT", "S_INPUT", "ENUMCVT", "41", "42", "43",
119 "44", "45", "G_OUTPUT", "S_OUTPUT", "ENUMOUTPUT", "G_AUDOUT",
120 "S_AUDOUT", "ENUMFX", "G_EFFECT", "S_EFFECT", "G_MODULATOR",
121 "S_MODULATOR"
122};
123#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
124
125static const char *osspcm_ioctls[] = {
126 "RESET", "SYNC", "SPEED", "STEREO", "GETBLKSIZE", "SETFMT",
127 "CHANNELS", "?", "POST", "SUBDIVIDE", "SETFRAGMENT", "GETFMTS",
128 "GETOSPACE", "GETISPACE", "NONBLOCK", "GETCAPS", "GET/SETTRIGGER",
129 "GETIPTR", "GETOPTR", "MAPINBUF", "MAPOUTBUF", "SETSYNCRO",
130 "SETDUPLEX", "GETODELAY"
131};
132#define OSSPCM_IOCTLS ARRAY_SIZE(v4l2_ioctls)
133
134void saa7134_print_ioctl(char *name, unsigned int cmd)
135{
136 char *dir;
137
138 switch (_IOC_DIR(cmd)) {
139 case _IOC_NONE: dir = "--"; break;
140 case _IOC_READ: dir = "r-"; break;
141 case _IOC_WRITE: dir = "-w"; break;
142 case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
143 default: dir = "??"; break;
144 }
145 switch (_IOC_TYPE(cmd)) {
146 case 'v':
147 printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l1, %s, VIDIOC%s)\n",
148 name, cmd, dir, (_IOC_NR(cmd) < V4L1_IOCTLS) ?
149 v4l1_ioctls[_IOC_NR(cmd)] : "???");
150 break;
151 case 'V':
152 printk(KERN_DEBUG "%s: ioctl 0x%08x (v4l2, %s, VIDIOC_%s)\n",
153 name, cmd, dir, (_IOC_NR(cmd) < V4L2_IOCTLS) ?
154 v4l2_ioctls[_IOC_NR(cmd)] : "???");
155 break;
156 case 'P':
157 printk(KERN_DEBUG "%s: ioctl 0x%08x (oss dsp, %s, SNDCTL_DSP_%s)\n",
158 name, cmd, dir, (_IOC_NR(cmd) < OSSPCM_IOCTLS) ?
159 osspcm_ioctls[_IOC_NR(cmd)] : "???");
160 break;
161 case 'M':
162 printk(KERN_DEBUG "%s: ioctl 0x%08x (oss mixer, %s, #%d)\n",
163 name, cmd, dir, _IOC_NR(cmd));
164 break;
165 default:
166 printk(KERN_DEBUG "%s: ioctl 0x%08x (???, %s, #%d)\n",
167 name, cmd, dir, _IOC_NR(cmd));
168 }
169}
170
171void saa7134_track_gpio(struct saa7134_dev *dev, char *msg)
172{
173 unsigned long mode,status;
174
175 if (!gpio_tracking)
176 return;
177 /* rising SAA7134_GPIO_GPRESCAN reads the status */
178 saa_andorb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN,0);
179 saa_andorb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN,SAA7134_GPIO_GPRESCAN);
180 mode = saa_readl(SAA7134_GPIO_GPMODE0 >> 2) & 0xfffffff;
181 status = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & 0xfffffff;
182 printk(KERN_DEBUG
183 "%s: gpio: mode=0x%07lx in=0x%07lx out=0x%07lx [%s]\n",
184 dev->name, mode, (~mode) & status, mode & status, msg);
185}
186
187/* ------------------------------------------------------------------ */
188
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
190/* ----------------------------------------------------------- */
191/* delayed request_module */
192
193#ifdef CONFIG_MODULES
194
195static int need_empress;
196static int need_dvb;
197
198static int pending_call(struct notifier_block *self, unsigned long state,
199 void *module)
200{
201 if (module != THIS_MODULE || state != MODULE_STATE_LIVE)
202 return NOTIFY_DONE;
203
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800204 if (need_empress)
205 request_module("saa7134-empress");
206 if (need_dvb)
207 request_module("saa7134-dvb");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 return NOTIFY_DONE;
209}
210
211static int pending_registered;
212static struct notifier_block pending_notifier = {
213 .notifier_call = pending_call,
214};
215
216static void request_module_depend(char *name, int *flag)
217{
218 switch (THIS_MODULE->state) {
219 case MODULE_STATE_COMING:
220 if (!pending_registered) {
221 register_module_notifier(&pending_notifier);
222 pending_registered = 1;
223 }
224 *flag = 1;
225 break;
226 case MODULE_STATE_LIVE:
227 request_module(name);
228 break;
229 default:
230 /* nothing */;
231 break;
232 }
233}
234
235#else
236
237#define request_module_depend(name,flag)
238
239#endif /* CONFIG_MODULES */
240
241/* ------------------------------------------------------------------ */
242
243/* nr of (saa7134-)pages for the given buffer size */
244static int saa7134_buffer_pages(int size)
245{
246 size = PAGE_ALIGN(size);
247 size += PAGE_SIZE; /* for non-page-aligned buffers */
248 size /= 4096;
249 return size;
250}
251
252/* calc max # of buffers from size (must not exceed the 4MB virtual
253 * address space per DMA channel) */
254int saa7134_buffer_count(unsigned int size, unsigned int count)
255{
256 unsigned int maxcount;
257
258 maxcount = 1024 / saa7134_buffer_pages(size);
259 if (count > maxcount)
260 count = maxcount;
261 return count;
262}
263
264int saa7134_buffer_startpage(struct saa7134_buf *buf)
265{
266 return saa7134_buffer_pages(buf->vb.bsize) * buf->vb.i;
267}
268
269unsigned long saa7134_buffer_base(struct saa7134_buf *buf)
270{
271 unsigned long base;
272
273 base = saa7134_buffer_startpage(buf) * 4096;
274 base += buf->vb.dma.sglist[0].offset;
275 return base;
276}
277
278/* ------------------------------------------------------------------ */
279
280int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt)
281{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800282 __le32 *cpu;
283 dma_addr_t dma_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
285 cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr);
286 if (NULL == cpu)
287 return -ENOMEM;
288 pt->size = SAA7134_PGTABLE_SIZE;
289 pt->cpu = cpu;
290 pt->dma = dma_addr;
291 return 0;
292}
293
294int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
295 struct scatterlist *list, unsigned int length,
296 unsigned int startpage)
297{
Alexey Dobriyanc9c12b72005-06-23 22:04:37 -0700298 __le32 *ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 unsigned int i,p;
300
301 BUG_ON(NULL == pt || NULL == pt->cpu);
302
303 ptr = pt->cpu + startpage;
304 for (i = 0; i < length; i++, list++)
305 for (p = 0; p * 4096 < list->length; p++, ptr++)
Gerd Knorra20758f2005-06-23 22:04:34 -0700306 *ptr = cpu_to_le32(sg_dma_address(list) - list->offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 return 0;
308}
309
310void saa7134_pgtable_free(struct pci_dev *pci, struct saa7134_pgtable *pt)
311{
312 if (NULL == pt->cpu)
313 return;
314 pci_free_consistent(pci, pt->size, pt->cpu, pt->dma);
315 pt->cpu = NULL;
316}
317
318/* ------------------------------------------------------------------ */
319
320void saa7134_dma_free(struct saa7134_dev *dev,struct saa7134_buf *buf)
321{
322 if (in_interrupt())
323 BUG();
324
325 videobuf_waiton(&buf->vb,0,0);
326 videobuf_dma_pci_unmap(dev->pci, &buf->vb.dma);
327 videobuf_dma_free(&buf->vb.dma);
328 buf->vb.state = STATE_NEEDS_INIT;
329}
330
331/* ------------------------------------------------------------------ */
332
333int saa7134_buffer_queue(struct saa7134_dev *dev,
334 struct saa7134_dmaqueue *q,
335 struct saa7134_buf *buf)
336{
337 struct saa7134_buf *next = NULL;
338
339 assert_spin_locked(&dev->slock);
340 dprintk("buffer_queue %p\n",buf);
341 if (NULL == q->curr) {
342 if (!q->need_two) {
343 q->curr = buf;
344 buf->activate(dev,buf,NULL);
345 } else if (list_empty(&q->queue)) {
346 list_add_tail(&buf->vb.queue,&q->queue);
347 buf->vb.state = STATE_QUEUED;
348 } else {
349 next = list_entry(q->queue.next,struct saa7134_buf,
350 vb.queue);
351 q->curr = buf;
352 buf->activate(dev,buf,next);
353 }
354 } else {
355 list_add_tail(&buf->vb.queue,&q->queue);
356 buf->vb.state = STATE_QUEUED;
357 }
358 return 0;
359}
360
361void saa7134_buffer_finish(struct saa7134_dev *dev,
362 struct saa7134_dmaqueue *q,
363 unsigned int state)
364{
365 assert_spin_locked(&dev->slock);
366 dprintk("buffer_finish %p\n",q->curr);
367
368 /* finish current buffer */
369 q->curr->vb.state = state;
370 do_gettimeofday(&q->curr->vb.ts);
371 wake_up(&q->curr->vb.done);
372 q->curr = NULL;
373}
374
375void saa7134_buffer_next(struct saa7134_dev *dev,
376 struct saa7134_dmaqueue *q)
377{
378 struct saa7134_buf *buf,*next = NULL;
379
380 assert_spin_locked(&dev->slock);
381 BUG_ON(NULL != q->curr);
382
383 if (!list_empty(&q->queue)) {
384 /* activate next one from queue */
385 buf = list_entry(q->queue.next,struct saa7134_buf,vb.queue);
386 dprintk("buffer_next %p [prev=%p/next=%p]\n",
387 buf,q->queue.prev,q->queue.next);
388 list_del(&buf->vb.queue);
389 if (!list_empty(&q->queue))
390 next = list_entry(q->queue.next,struct saa7134_buf,
391 vb.queue);
392 q->curr = buf;
393 buf->activate(dev,buf,next);
394 dprintk("buffer_next #2 prev=%p/next=%p\n",
395 q->queue.prev,q->queue.next);
396 } else {
397 /* nothing to do -- just stop DMA */
398 dprintk("buffer_next %p\n",NULL);
399 saa7134_set_dmabits(dev);
400 del_timer(&q->timeout);
401 }
402}
403
404void saa7134_buffer_timeout(unsigned long data)
405{
406 struct saa7134_dmaqueue *q = (struct saa7134_dmaqueue*)data;
407 struct saa7134_dev *dev = q->dev;
408 unsigned long flags;
409
410 spin_lock_irqsave(&dev->slock,flags);
411
412 /* try to reset the hardware (SWRST) */
413 saa_writeb(SAA7134_REGION_ENABLE, 0x00);
414 saa_writeb(SAA7134_REGION_ENABLE, 0x80);
415 saa_writeb(SAA7134_REGION_ENABLE, 0x00);
416
417 /* flag current buffer as failed,
418 try to start over with the next one. */
419 if (q->curr) {
420 dprintk("timeout on %p\n",q->curr);
421 saa7134_buffer_finish(dev,q,STATE_ERROR);
422 }
423 saa7134_buffer_next(dev,q);
424 spin_unlock_irqrestore(&dev->slock,flags);
425}
426
427/* ------------------------------------------------------------------ */
428
429int saa7134_set_dmabits(struct saa7134_dev *dev)
430{
431 u32 split, task=0, ctrl=0, irq=0;
432 enum v4l2_field cap = V4L2_FIELD_ANY;
433 enum v4l2_field ov = V4L2_FIELD_ANY;
434
435 assert_spin_locked(&dev->slock);
436
437 /* video capture -- dma 0 + video task A */
438 if (dev->video_q.curr) {
439 task |= 0x01;
440 ctrl |= SAA7134_MAIN_CTRL_TE0;
441 irq |= SAA7134_IRQ1_INTE_RA0_1 |
442 SAA7134_IRQ1_INTE_RA0_0;
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800443 cap = dev->video_q.curr->vb.field;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 }
445
446 /* video capture -- dma 1+2 (planar modes) */
447 if (dev->video_q.curr &&
448 dev->video_q.curr->fmt->planar) {
449 ctrl |= SAA7134_MAIN_CTRL_TE4 |
450 SAA7134_MAIN_CTRL_TE5;
451 }
452
453 /* screen overlay -- dma 0 + video task B */
454 if (dev->ovenable) {
455 task |= 0x10;
456 ctrl |= SAA7134_MAIN_CTRL_TE1;
457 ov = dev->ovfield;
458 }
459
460 /* vbi capture -- dma 0 + vbi task A+B */
461 if (dev->vbi_q.curr) {
462 task |= 0x22;
463 ctrl |= SAA7134_MAIN_CTRL_TE2 |
464 SAA7134_MAIN_CTRL_TE3;
465 irq |= SAA7134_IRQ1_INTE_RA0_7 |
466 SAA7134_IRQ1_INTE_RA0_6 |
467 SAA7134_IRQ1_INTE_RA0_5 |
468 SAA7134_IRQ1_INTE_RA0_4;
469 }
470
471 /* audio capture -- dma 3 */
472 if (dev->oss.dma_running) {
473 ctrl |= SAA7134_MAIN_CTRL_TE6;
474 irq |= SAA7134_IRQ1_INTE_RA3_1 |
475 SAA7134_IRQ1_INTE_RA3_0;
476 }
477
478 /* TS capture -- dma 5 */
479 if (dev->ts_q.curr) {
480 ctrl |= SAA7134_MAIN_CTRL_TE5;
481 irq |= SAA7134_IRQ1_INTE_RA2_3 |
482 SAA7134_IRQ1_INTE_RA2_2 |
483 SAA7134_IRQ1_INTE_RA2_1 |
484 SAA7134_IRQ1_INTE_RA2_0;
485 }
486
487 /* set task conditions + field handling */
488 if (V4L2_FIELD_HAS_BOTH(cap) || V4L2_FIELD_HAS_BOTH(ov) || cap == ov) {
489 /* default config -- use full frames */
490 saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0d);
491 saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0d);
492 saa_writeb(SAA7134_FIELD_HANDLING(TASK_A), 0x02);
493 saa_writeb(SAA7134_FIELD_HANDLING(TASK_B), 0x02);
494 split = 0;
495 } else {
496 /* split fields between tasks */
497 if (V4L2_FIELD_TOP == cap) {
498 /* odd A, even B, repeat */
499 saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0d);
500 saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0e);
501 } else {
502 /* odd B, even A, repeat */
503 saa_writeb(SAA7134_TASK_CONDITIONS(TASK_A), 0x0e);
504 saa_writeb(SAA7134_TASK_CONDITIONS(TASK_B), 0x0d);
505 }
506 saa_writeb(SAA7134_FIELD_HANDLING(TASK_A), 0x01);
507 saa_writeb(SAA7134_FIELD_HANDLING(TASK_B), 0x01);
508 split = 1;
509 }
510
511 /* irqs */
512 saa_writeb(SAA7134_REGION_ENABLE, task);
513 saa_writel(SAA7134_IRQ1, irq);
514 saa_andorl(SAA7134_MAIN_CTRL,
515 SAA7134_MAIN_CTRL_TE0 |
516 SAA7134_MAIN_CTRL_TE1 |
517 SAA7134_MAIN_CTRL_TE2 |
518 SAA7134_MAIN_CTRL_TE3 |
519 SAA7134_MAIN_CTRL_TE4 |
520 SAA7134_MAIN_CTRL_TE5 |
521 SAA7134_MAIN_CTRL_TE6,
522 ctrl);
523 dprintk("dmabits: task=0x%02x ctrl=0x%02x irq=0x%x split=%s\n",
524 task, ctrl, irq, split ? "no" : "yes");
525
526 return 0;
527}
528
529/* ------------------------------------------------------------------ */
530/* IRQ handler + helpers */
531
532static char *irqbits[] = {
533 "DONE_RA0", "DONE_RA1", "DONE_RA2", "DONE_RA3",
534 "AR", "PE", "PWR_ON", "RDCAP", "INTL", "FIDT", "MMC",
535 "TRIG_ERR", "CONF_ERR", "LOAD_ERR",
536 "GPIO16?", "GPIO18", "GPIO22", "GPIO23"
537};
538#define IRQBITS ARRAY_SIZE(irqbits)
539
540static void print_irqstatus(struct saa7134_dev *dev, int loop,
541 unsigned long report, unsigned long status)
542{
543 unsigned int i;
544
545 printk(KERN_DEBUG "%s/irq[%d,%ld]: r=0x%lx s=0x%02lx",
546 dev->name,loop,jiffies,report,status);
547 for (i = 0; i < IRQBITS; i++) {
548 if (!(report & (1 << i)))
549 continue;
550 printk(" %s",irqbits[i]);
551 }
552 if (report & SAA7134_IRQ_REPORT_DONE_RA0) {
553 printk(" | RA0=%s,%s,%s,%ld",
554 (status & 0x40) ? "vbi" : "video",
555 (status & 0x20) ? "b" : "a",
556 (status & 0x10) ? "odd" : "even",
557 (status & 0x0f));
558 }
559 printk("\n");
560}
561
562static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
563{
564 struct saa7134_dev *dev = (struct saa7134_dev*) dev_id;
565 unsigned long report,status;
566 int loop, handled = 0;
567
568 for (loop = 0; loop < 10; loop++) {
569 report = saa_readl(SAA7134_IRQ_REPORT);
570 status = saa_readl(SAA7134_IRQ_STATUS);
571 if (0 == report) {
572 if (irq_debug > 1)
573 printk(KERN_DEBUG "%s/irq: no (more) work\n",
574 dev->name);
575 goto out;
576 }
577 handled = 1;
578 saa_writel(SAA7134_IRQ_REPORT,report);
579 if (irq_debug)
580 print_irqstatus(dev,loop,report,status);
581
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582
583 if (report & SAA7134_IRQ_REPORT_RDCAP /* _INTL */)
584 saa7134_irq_video_intl(dev);
585
586 if ((report & SAA7134_IRQ_REPORT_DONE_RA0) &&
587 (status & 0x60) == 0)
588 saa7134_irq_video_done(dev,status);
589
590 if ((report & SAA7134_IRQ_REPORT_DONE_RA0) &&
591 (status & 0x40) == 0x40)
592 saa7134_irq_vbi_done(dev,status);
593
594 if ((report & SAA7134_IRQ_REPORT_DONE_RA2) &&
595 card_has_mpeg(dev))
596 saa7134_irq_ts_done(dev,status);
597
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800598 if ((report & SAA7134_IRQ_REPORT_DONE_RA3)) {
599 if (oss) {
600 saa7134_irq_oss_done(dev,status);
601 } else if (alsa) {
602 saa7134_irq_alsa_done(dev,status);
603 }
604 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605
606 if ((report & (SAA7134_IRQ_REPORT_GPIO16 |
607 SAA7134_IRQ_REPORT_GPIO18)) &&
608 dev->remote)
609 saa7134_input_irq(dev);
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -0800610
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 }
612
613 if (10 == loop) {
614 print_irqstatus(dev,loop,report,status);
615 if (report & SAA7134_IRQ_REPORT_PE) {
616 /* disable all parity error */
617 printk(KERN_WARNING "%s/irq: looping -- "
618 "clearing PE (parity error!) enable bit\n",dev->name);
619 saa_clearl(SAA7134_IRQ2,SAA7134_IRQ2_INTE_PE);
620 } else if (report & (SAA7134_IRQ_REPORT_GPIO16 |
621 SAA7134_IRQ_REPORT_GPIO18)) {
622 /* disable gpio IRQs */
623 printk(KERN_WARNING "%s/irq: looping -- "
624 "clearing GPIO enable bits\n",dev->name);
625 saa_clearl(SAA7134_IRQ2, (SAA7134_IRQ2_INTE_GPIO16 |
626 SAA7134_IRQ2_INTE_GPIO18));
627 } else {
628 /* disable all irqs */
629 printk(KERN_WARNING "%s/irq: looping -- "
630 "clearing all enable bits\n",dev->name);
631 saa_writel(SAA7134_IRQ1,0);
632 saa_writel(SAA7134_IRQ2,0);
633 }
634 }
635
636 out:
637 return IRQ_RETVAL(handled);
638}
639
640/* ------------------------------------------------------------------ */
641
642/* early init (no i2c, no irq) */
643static int saa7134_hwinit1(struct saa7134_dev *dev)
644{
645 dprintk("hwinit1\n");
646
647 saa_writel(SAA7134_IRQ1, 0);
648 saa_writel(SAA7134_IRQ2, 0);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800649 init_MUTEX(&dev->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 spin_lock_init(&dev->slock);
651
652 saa7134_track_gpio(dev,"pre-init");
653 saa7134_video_init1(dev);
654 saa7134_vbi_init1(dev);
655 if (card_has_mpeg(dev))
656 saa7134_ts_init1(dev);
657 saa7134_input_init1(dev);
658
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 /* RAM FIFO config */
660 saa_writel(SAA7134_FIFO_SIZE, 0x08070503);
661 saa_writel(SAA7134_THRESHOULD,0x02020202);
662
663 /* enable audio + video processing */
664 saa_writel(SAA7134_MAIN_CTRL,
665 SAA7134_MAIN_CTRL_VPLLE |
666 SAA7134_MAIN_CTRL_APLLE |
667 SAA7134_MAIN_CTRL_EXOSC |
668 SAA7134_MAIN_CTRL_EVFE1 |
669 SAA7134_MAIN_CTRL_EVFE2 |
670 SAA7134_MAIN_CTRL_ESFE |
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 SAA7134_MAIN_CTRL_EBDAC);
672
Nickolay V. Shmyrev17a05ef2005-11-08 21:36:36 -0800673 /*
674 * Initialize OSS _after_ enabling audio clock PLL and audio processing.
675 * OSS initialization writes to registers via the audio DSP; these
676 * writes will fail unless the audio clock has been started. At worst,
677 * audio will not work.
678 */
679
680 switch (dev->pci->device) {
681 case PCI_DEVICE_ID_PHILIPS_SAA7134:
682 case PCI_DEVICE_ID_PHILIPS_SAA7133:
683 case PCI_DEVICE_ID_PHILIPS_SAA7135:
684 saa7134_oss_init1(dev);
685 break;
686 }
687
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 /* enable peripheral devices */
689 saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
690
691 /* set vertical line numbering start (vbi needs this) */
692 saa_writeb(SAA7134_SOURCE_TIMING2, 0x20);
693
694 return 0;
695}
696
697/* late init (with i2c + irq) */
698static int saa7134_hwinit2(struct saa7134_dev *dev)
699{
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700700 unsigned int irq2_mask;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 dprintk("hwinit2\n");
702
703 saa7134_video_init2(dev);
704 saa7134_tvaudio_init2(dev);
705
706 /* enable IRQ's */
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800707 irq2_mask =
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700708 SAA7134_IRQ2_INTE_DEC3 |
709 SAA7134_IRQ2_INTE_DEC2 |
710 SAA7134_IRQ2_INTE_DEC1 |
711 SAA7134_IRQ2_INTE_DEC0 |
712 SAA7134_IRQ2_INTE_PE |
713 SAA7134_IRQ2_INTE_AR;
714
715 if (dev->has_remote)
716 irq2_mask |= (SAA7134_IRQ2_INTE_GPIO18 |
717 SAA7134_IRQ2_INTE_GPIO18A |
718 SAA7134_IRQ2_INTE_GPIO16 );
719
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 saa_writel(SAA7134_IRQ1, 0);
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700721 saa_writel(SAA7134_IRQ2, irq2_mask);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722
723 return 0;
724}
725
726/* shutdown */
727static int saa7134_hwfini(struct saa7134_dev *dev)
728{
729 dprintk("hwfini\n");
730
731 switch (dev->pci->device) {
732 case PCI_DEVICE_ID_PHILIPS_SAA7134:
733 case PCI_DEVICE_ID_PHILIPS_SAA7133:
734 case PCI_DEVICE_ID_PHILIPS_SAA7135:
735 saa7134_oss_fini(dev);
736 break;
737 }
738 if (card_has_mpeg(dev))
739 saa7134_ts_fini(dev);
740 saa7134_input_fini(dev);
741 saa7134_vbi_fini(dev);
742 saa7134_video_fini(dev);
743 saa7134_tvaudio_fini(dev);
744 return 0;
745}
746
747static void __devinit must_configure_manually(void)
748{
749 unsigned int i,p;
750
751 printk(KERN_WARNING
752 "saa7134: <rant>\n"
753 "saa7134: Congratulations! Your TV card vendor saved a few\n"
754 "saa7134: cents for a eeprom, thus your pci board has no\n"
755 "saa7134: subsystem ID and I can't identify it automatically\n"
756 "saa7134: </rant>\n"
757 "saa7134: I feel better now. Ok, here are the good news:\n"
758 "saa7134: You can use the card=<nr> insmod option to specify\n"
759 "saa7134: which board do you have. The list:\n");
760 for (i = 0; i < saa7134_bcount; i++) {
761 printk(KERN_WARNING "saa7134: card=%d -> %-40.40s",
762 i,saa7134_boards[i].name);
763 for (p = 0; saa7134_pci_tbl[p].driver_data; p++) {
764 if (saa7134_pci_tbl[p].driver_data != i)
765 continue;
766 printk(" %04x:%04x",
767 saa7134_pci_tbl[p].subvendor,
768 saa7134_pci_tbl[p].subdevice);
769 }
770 printk("\n");
771 }
772}
773
774static struct video_device *vdev_init(struct saa7134_dev *dev,
775 struct video_device *template,
776 char *type)
777{
778 struct video_device *vfd;
779
780 vfd = video_device_alloc();
781 if (NULL == vfd)
782 return NULL;
783 *vfd = *template;
784 vfd->minor = -1;
785 vfd->dev = &dev->pci->dev;
786 vfd->release = video_device_release;
787 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
788 dev->name, type, saa7134_boards[dev->board].name);
789 return vfd;
790}
791
792static void saa7134_unregister_video(struct saa7134_dev *dev)
793{
794 if (dev->video_dev) {
795 if (-1 != dev->video_dev->minor)
796 video_unregister_device(dev->video_dev);
797 else
798 video_device_release(dev->video_dev);
799 dev->video_dev = NULL;
800 }
801 if (dev->vbi_dev) {
802 if (-1 != dev->vbi_dev->minor)
803 video_unregister_device(dev->vbi_dev);
804 else
805 video_device_release(dev->vbi_dev);
806 dev->vbi_dev = NULL;
807 }
808 if (dev->radio_dev) {
809 if (-1 != dev->radio_dev->minor)
810 video_unregister_device(dev->radio_dev);
811 else
812 video_device_release(dev->radio_dev);
813 dev->radio_dev = NULL;
814 }
815}
816
817static void mpeg_ops_attach(struct saa7134_mpeg_ops *ops,
818 struct saa7134_dev *dev)
819{
820 int err;
821
822 if (NULL != dev->mops)
823 return;
824 if (saa7134_boards[dev->board].mpeg != ops->type)
825 return;
826 err = ops->init(dev);
827 if (0 != err)
828 return;
829 dev->mops = ops;
830}
831
832static void mpeg_ops_detach(struct saa7134_mpeg_ops *ops,
833 struct saa7134_dev *dev)
834{
835 if (NULL == dev->mops)
836 return;
837 if (dev->mops != ops)
838 return;
839 dev->mops->fini(dev);
840 dev->mops = NULL;
841}
842
843static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
844 const struct pci_device_id *pci_id)
845{
846 struct saa7134_dev *dev;
847 struct list_head *item;
848 struct saa7134_mpeg_ops *mops;
849 int err;
850
851 dev = kmalloc(sizeof(*dev),GFP_KERNEL);
852 if (NULL == dev)
853 return -ENOMEM;
854 memset(dev,0,sizeof(*dev));
855
856 /* pci init */
857 dev->pci = pci_dev;
858 if (pci_enable_device(pci_dev)) {
859 err = -EIO;
860 goto fail1;
861 }
862
863 dev->nr = saa7134_devcount;
864 sprintf(dev->name,"saa%x[%d]",pci_dev->device,dev->nr);
865
866 /* pci quirks */
867 if (pci_pci_problems) {
868 if (pci_pci_problems & PCIPCI_TRITON)
869 printk(KERN_INFO "%s: quirk: PCIPCI_TRITON\n", dev->name);
870 if (pci_pci_problems & PCIPCI_NATOMA)
871 printk(KERN_INFO "%s: quirk: PCIPCI_NATOMA\n", dev->name);
872 if (pci_pci_problems & PCIPCI_VIAETBF)
873 printk(KERN_INFO "%s: quirk: PCIPCI_VIAETBF\n", dev->name);
874 if (pci_pci_problems & PCIPCI_VSFX)
875 printk(KERN_INFO "%s: quirk: PCIPCI_VSFX\n",dev->name);
876#ifdef PCIPCI_ALIMAGIK
877 if (pci_pci_problems & PCIPCI_ALIMAGIK) {
878 printk(KERN_INFO "%s: quirk: PCIPCI_ALIMAGIK -- latency fixup\n",
879 dev->name);
880 latency = 0x0A;
881 }
882#endif
883 }
884 if (UNSET != latency) {
885 printk(KERN_INFO "%s: setting pci latency timer to %d\n",
886 dev->name,latency);
887 pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, latency);
888 }
889
890 /* print pci info */
891 pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev);
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800892 pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat);
893 printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 "latency: %d, mmio: 0x%lx\n", dev->name,
895 pci_name(pci_dev), dev->pci_rev, pci_dev->irq,
896 dev->pci_lat,pci_resource_start(pci_dev,0));
897 pci_set_master(pci_dev);
898 if (!pci_dma_supported(pci_dev,0xffffffff)) {
899 printk("%s: Oops: no 32bit PCI DMA ???\n",dev->name);
900 err = -EIO;
901 goto fail1;
902 }
903
904 /* board config */
905 dev->board = pci_id->driver_data;
906 if (card[dev->nr] >= 0 &&
907 card[dev->nr] < saa7134_bcount)
908 dev->board = card[dev->nr];
909 if (SAA7134_BOARD_NOAUTO == dev->board) {
910 must_configure_manually();
911 dev->board = SAA7134_BOARD_UNKNOWN;
912 }
913 dev->tuner_type = saa7134_boards[dev->board].tuner_type;
914 dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf;
915 if (UNSET != tuner[dev->nr])
916 dev->tuner_type = tuner[dev->nr];
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800917 printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 dev->name,pci_dev->subsystem_vendor,
919 pci_dev->subsystem_device,saa7134_boards[dev->board].name,
920 dev->board, card[dev->nr] == dev->board ?
921 "insmod option" : "autodetected");
922
923 /* get mmio */
924 if (!request_mem_region(pci_resource_start(pci_dev,0),
925 pci_resource_len(pci_dev,0),
926 dev->name)) {
927 err = -EBUSY;
928 printk(KERN_ERR "%s: can't get MMIO memory @ 0x%lx\n",
929 dev->name,pci_resource_start(pci_dev,0));
930 goto fail1;
931 }
932 dev->lmmio = ioremap(pci_resource_start(pci_dev,0), 0x1000);
933 dev->bmmio = (__u8 __iomem *)dev->lmmio;
934 if (NULL == dev->lmmio) {
935 err = -EIO;
936 printk(KERN_ERR "%s: can't ioremap() MMIO memory\n",
937 dev->name);
938 goto fail2;
939 }
940
941 /* initialize hardware #1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 saa7134_board_init1(dev);
943 saa7134_hwinit1(dev);
944
945 /* get irq */
946 err = request_irq(pci_dev->irq, saa7134_irq,
947 SA_SHIRQ | SA_INTERRUPT, dev->name, dev);
948 if (err < 0) {
949 printk(KERN_ERR "%s: can't get IRQ %d\n",
950 dev->name,pci_dev->irq);
951 goto fail3;
952 }
953
954 /* wait a bit, register i2c bus */
955 msleep(100);
956 saa7134_i2c_register(dev);
957
958 /* initialize hardware #2 */
959 saa7134_board_init2(dev);
960 saa7134_hwinit2(dev);
961
962 /* load i2c helpers */
963 if (TUNER_ABSENT != dev->tuner_type)
964 request_module("tuner");
965 if (dev->tda9887_conf)
966 request_module("tda9887");
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800967 if (card_is_empress(dev)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 request_module("saa6752hs");
969 request_module_depend("saa7134-empress",&need_empress);
970 }
Mauro Carvalho Chehab330a1152005-07-12 13:59:01 -0700971
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -0800972 if (card_is_dvb(dev))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 request_module_depend("saa7134-dvb",&need_dvb);
974
975 v4l2_prio_init(&dev->prio);
976
977 /* register v4l devices */
978 dev->video_dev = vdev_init(dev,&saa7134_video_template,"video");
979 err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
980 video_nr[dev->nr]);
981 if (err < 0) {
982 printk(KERN_INFO "%s: can't register video device\n",
983 dev->name);
984 goto fail4;
985 }
986 printk(KERN_INFO "%s: registered device video%d [v4l2]\n",
987 dev->name,dev->video_dev->minor & 0x1f);
988
989 dev->vbi_dev = vdev_init(dev,&saa7134_vbi_template,"vbi");
990 err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
991 vbi_nr[dev->nr]);
992 if (err < 0)
993 goto fail4;
994 printk(KERN_INFO "%s: registered device vbi%d\n",
995 dev->name,dev->vbi_dev->minor & 0x1f);
996
997 if (card_has_radio(dev)) {
998 dev->radio_dev = vdev_init(dev,&saa7134_radio_template,"radio");
999 err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
1000 radio_nr[dev->nr]);
1001 if (err < 0)
1002 goto fail4;
1003 printk(KERN_INFO "%s: registered device radio%d\n",
1004 dev->name,dev->radio_dev->minor & 0x1f);
1005 }
1006
1007 /* register oss devices */
1008 switch (dev->pci->device) {
1009 case PCI_DEVICE_ID_PHILIPS_SAA7134:
1010 case PCI_DEVICE_ID_PHILIPS_SAA7133:
1011 case PCI_DEVICE_ID_PHILIPS_SAA7135:
1012 if (oss) {
1013 err = dev->oss.minor_dsp =
1014 register_sound_dsp(&saa7134_dsp_fops,
1015 dsp_nr[dev->nr]);
1016 if (err < 0) {
1017 goto fail4;
1018 }
1019 printk(KERN_INFO "%s: registered device dsp%d\n",
1020 dev->name,dev->oss.minor_dsp >> 4);
1021
1022 err = dev->oss.minor_mixer =
1023 register_sound_mixer(&saa7134_mixer_fops,
1024 mixer_nr[dev->nr]);
1025 if (err < 0)
1026 goto fail5;
1027 printk(KERN_INFO "%s: registered device mixer%d\n",
1028 dev->name,dev->oss.minor_mixer >> 4);
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -08001029 } else if (alsa) {
Ricardo Cerqueiraa8666232005-11-08 21:37:14 -08001030 alsa_card_saa7134_create(dev,dsp_nr[dev->nr]);
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -08001031 printk(KERN_INFO "%s: registered ALSA devices\n",
1032 dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 }
1034 break;
1035 }
1036
1037 /* everything worked */
1038 pci_set_drvdata(pci_dev,dev);
1039 saa7134_devcount++;
1040
1041 down(&devlist_lock);
1042 list_for_each(item,&mops_list) {
1043 mops = list_entry(item, struct saa7134_mpeg_ops, next);
1044 mpeg_ops_attach(mops, dev);
1045 }
1046 list_add_tail(&dev->devlist,&saa7134_devlist);
1047 up(&devlist_lock);
1048
1049 /* check for signal */
1050 saa7134_irq_video_intl(dev);
1051 return 0;
1052
1053 fail5:
1054 switch (dev->pci->device) {
1055 case PCI_DEVICE_ID_PHILIPS_SAA7134:
1056 case PCI_DEVICE_ID_PHILIPS_SAA7133:
1057 case PCI_DEVICE_ID_PHILIPS_SAA7135:
1058 if (oss)
1059 unregister_sound_dsp(dev->oss.minor_dsp);
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -08001060 else if (alsa)
1061 alsa_card_saa7134_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 break;
1063 }
1064 fail4:
1065 saa7134_unregister_video(dev);
1066 saa7134_i2c_unregister(dev);
1067 free_irq(pci_dev->irq, dev);
1068 fail3:
1069 saa7134_hwfini(dev);
1070 iounmap(dev->lmmio);
1071 fail2:
1072 release_mem_region(pci_resource_start(pci_dev,0),
1073 pci_resource_len(pci_dev,0));
1074 fail1:
1075 kfree(dev);
1076 return err;
1077}
1078
1079static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
1080{
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001081 struct saa7134_dev *dev = pci_get_drvdata(pci_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 struct list_head *item;
1083 struct saa7134_mpeg_ops *mops;
1084
1085 /* debugging ... */
1086 if (irq_debug) {
1087 u32 report = saa_readl(SAA7134_IRQ_REPORT);
1088 u32 status = saa_readl(SAA7134_IRQ_STATUS);
1089 print_irqstatus(dev,42,report,status);
1090 }
1091
1092 /* disable peripheral devices */
1093 saa_writeb(SAA7134_SPECIAL_MODE,0);
1094
1095 /* shutdown hardware */
1096 saa_writel(SAA7134_IRQ1,0);
1097 saa_writel(SAA7134_IRQ2,0);
1098 saa_writel(SAA7134_MAIN_CTRL,0);
1099
1100 /* shutdown subsystems */
1101 saa7134_hwfini(dev);
1102
1103 /* unregister */
1104 down(&devlist_lock);
1105 list_del(&dev->devlist);
1106 list_for_each(item,&mops_list) {
1107 mops = list_entry(item, struct saa7134_mpeg_ops, next);
1108 mpeg_ops_detach(mops, dev);
1109 }
1110 up(&devlist_lock);
1111 saa7134_devcount--;
1112
1113 saa7134_i2c_unregister(dev);
1114 switch (dev->pci->device) {
1115 case PCI_DEVICE_ID_PHILIPS_SAA7134:
1116 case PCI_DEVICE_ID_PHILIPS_SAA7133:
1117 case PCI_DEVICE_ID_PHILIPS_SAA7135:
1118 if (oss) {
1119 unregister_sound_mixer(dev->oss.minor_mixer);
1120 unregister_sound_dsp(dev->oss.minor_dsp);
Ricardo Cerqueirabd15eba2005-11-08 21:37:11 -08001121 } else if (alsa)
1122 alsa_card_saa7134_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 break;
1124 }
1125 saa7134_unregister_video(dev);
1126
1127 /* release ressources */
1128 free_irq(pci_dev->irq, dev);
1129 iounmap(dev->lmmio);
1130 release_mem_region(pci_resource_start(pci_dev,0),
1131 pci_resource_len(pci_dev,0));
1132
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 pci_set_drvdata(pci_dev, NULL);
1134
1135 /* free memory */
1136 kfree(dev);
1137}
1138
1139/* ----------------------------------------------------------- */
1140
1141int saa7134_ts_register(struct saa7134_mpeg_ops *ops)
1142{
1143 struct list_head *item;
1144 struct saa7134_dev *dev;
1145
1146 down(&devlist_lock);
1147 list_for_each(item,&saa7134_devlist) {
1148 dev = list_entry(item, struct saa7134_dev, devlist);
1149 mpeg_ops_attach(ops, dev);
1150 }
1151 list_add_tail(&ops->next,&mops_list);
1152 up(&devlist_lock);
1153 return 0;
1154}
1155
1156void saa7134_ts_unregister(struct saa7134_mpeg_ops *ops)
1157{
1158 struct list_head *item;
1159 struct saa7134_dev *dev;
1160
1161 down(&devlist_lock);
1162 list_del(&ops->next);
1163 list_for_each(item,&saa7134_devlist) {
1164 dev = list_entry(item, struct saa7134_dev, devlist);
1165 mpeg_ops_detach(ops, dev);
1166 }
1167 up(&devlist_lock);
1168}
1169
1170EXPORT_SYMBOL(saa7134_ts_register);
1171EXPORT_SYMBOL(saa7134_ts_unregister);
1172
1173/* ----------------------------------------------------------- */
1174
1175static struct pci_driver saa7134_pci_driver = {
Mauro Carvalho Chehab4ac97912005-11-08 21:37:43 -08001176 .name = "saa7134",
1177 .id_table = saa7134_pci_tbl,
1178 .probe = saa7134_initdev,
1179 .remove = __devexit_p(saa7134_finidev),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180};
1181
1182static int saa7134_init(void)
1183{
1184 INIT_LIST_HEAD(&saa7134_devlist);
1185 printk(KERN_INFO "saa7130/34: v4l2 driver version %d.%d.%d loaded\n",
1186 (SAA7134_VERSION_CODE >> 16) & 0xff,
1187 (SAA7134_VERSION_CODE >> 8) & 0xff,
1188 SAA7134_VERSION_CODE & 0xff);
1189#ifdef SNAPSHOT
1190 printk(KERN_INFO "saa7130/34: snapshot date %04d-%02d-%02d\n",
1191 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100);
1192#endif
1193 return pci_module_init(&saa7134_pci_driver);
1194}
1195
1196static void saa7134_fini(void)
1197{
1198#ifdef CONFIG_MODULES
1199 if (pending_registered)
1200 unregister_module_notifier(&pending_notifier);
1201#endif
1202 pci_unregister_driver(&saa7134_pci_driver);
1203}
1204
1205module_init(saa7134_init);
1206module_exit(saa7134_fini);
1207
1208/* ----------------------------------------------------------- */
1209
1210EXPORT_SYMBOL(saa7134_print_ioctl);
1211EXPORT_SYMBOL(saa7134_i2c_call_clients);
1212EXPORT_SYMBOL(saa7134_devlist);
1213EXPORT_SYMBOL(saa7134_boards);
1214
1215/* ----------------------------------------------------------- */
1216/*
1217 * Local variables:
1218 * c-basic-offset: 8
1219 * End:
1220 */