diff options
author | Ricardo Cerqueira <v4l@cerqueira.org> | 2005-11-09 00:37:14 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-09 10:56:16 -0500 |
commit | b2c15ea9b23c216bb49303c076bbdcef7e7ba278 (patch) | |
tree | df02f03b2952947b8eaba6128d176781699b10b3 | |
parent | c06f57f55a0e499ec38fbb62812ad3fe08ad246e (diff) |
[PATCH] v4l: 725: fixed kernel oops when hotswapping pc cards
- Fixed kernel oops when hotswapping PC Cards
Signed-off-by: Ricardo Cerqueira <v4l@cerqueira.org>
Signed-off-by: Nickolay V. Shmyrev <nshmyrev@yandex.ru>
Signed-off-by: Mauro Carvalho Chehab <mchehab@brturbo.com.br>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/media/video/saa7134/saa7134-alsa.c | 270 |
1 files changed, 210 insertions, 60 deletions
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 84eeeba21d74..cf4ee6d6ef64 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c | |||
@@ -4,15 +4,7 @@ | |||
4 | * | 4 | * |
5 | * | 5 | * |
6 | * Caveats: | 6 | * Caveats: |
7 | * I still haven't got the mixer settings right. | ||
8 | * | ||
9 | * - Volume doesn't work (it's always at max) | 7 | * - Volume doesn't work (it's always at max) |
10 | * - There's no "memory" of the capture channel. It can be changed, | ||
11 | * but alsamixer doesn't show it after a module restart (rmmod/insmod) | ||
12 | * | ||
13 | * Hotswapping DOES NOT work yet! Please remove the module before | ||
14 | * inserting cardbus cards. pcmcia-cs or pccardd should load it | ||
15 | * properly after insertion, and things will work | ||
16 | * | 8 | * |
17 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
18 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
@@ -49,6 +41,10 @@ static unsigned int alsa_debug = 0; | |||
49 | module_param(alsa_debug, int, 0644); | 41 | module_param(alsa_debug, int, 0644); |
50 | MODULE_PARM_DESC(alsa_debug,"enable debug messages [alsa]"); | 42 | MODULE_PARM_DESC(alsa_debug,"enable debug messages [alsa]"); |
51 | 43 | ||
44 | /* | ||
45 | * Configuration macros | ||
46 | */ | ||
47 | |||
52 | #define MAX_PCM_DEVICES 1 | 48 | #define MAX_PCM_DEVICES 1 |
53 | #define MAX_PCM_SUBSTREAMS 1 | 49 | #define MAX_PCM_SUBSTREAMS 1 |
54 | 50 | ||
@@ -67,20 +63,21 @@ MODULE_PARM_DESC(alsa_debug,"enable debug messages [alsa]"); | |||
67 | #define USE_PERIODS_MAX 1024 | 63 | #define USE_PERIODS_MAX 1024 |
68 | #endif | 64 | #endif |
69 | 65 | ||
70 | 66 | #define MIXER_ADDR_TVTUNER 0 | |
71 | #define dprintk(fmt, arg...) if (alsa_debug) \ | 67 | #define MIXER_ADDR_LINE1 1 |
72 | printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ## arg) | 68 | #define MIXER_ADDR_LINE2 2 |
73 | 69 | #define MIXER_ADDR_LAST 2 | |
74 | 70 | ||
75 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 71 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
76 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ | 72 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ |
77 | static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; | 73 | static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; |
78 | 74 | ||
79 | #define MIXER_ADDR_TVTUNER 0 | 75 | #define dprintk(fmt, arg...) if (alsa_debug) \ |
80 | #define MIXER_ADDR_LINE1 1 | 76 | printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ## arg) |
81 | #define MIXER_ADDR_LINE2 2 | ||
82 | #define MIXER_ADDR_LAST 2 | ||
83 | 77 | ||
78 | /* | ||
79 | * Main chip structure | ||
80 | */ | ||
84 | typedef struct snd_card_saa7134 { | 81 | typedef struct snd_card_saa7134 { |
85 | snd_card_t *card; | 82 | snd_card_t *card; |
86 | spinlock_t mixer_lock; | 83 | spinlock_t mixer_lock; |
@@ -95,6 +92,10 @@ typedef struct snd_card_saa7134 { | |||
95 | spinlock_t lock; | 92 | spinlock_t lock; |
96 | } snd_card_saa7134_t; | 93 | } snd_card_saa7134_t; |
97 | 94 | ||
95 | /* | ||
96 | * PCM structure | ||
97 | */ | ||
98 | |||
98 | typedef struct snd_card_saa7134_pcm { | 99 | typedef struct snd_card_saa7134_pcm { |
99 | struct saa7134_dev *saadev; | 100 | struct saa7134_dev *saadev; |
100 | 101 | ||
@@ -107,13 +108,34 @@ typedef struct snd_card_saa7134_pcm { | |||
107 | 108 | ||
108 | static snd_card_t *snd_saa7134_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; | 109 | static snd_card_t *snd_saa7134_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; |
109 | 110 | ||
111 | /* | ||
112 | * saa7134 DMA audio stop | ||
113 | * | ||
114 | * Called when the capture device is released or the buffer overflows | ||
115 | * | ||
116 | * - Copied verbatim from saa7134-oss's dsp_dma_stop. Can be dropped | ||
117 | * if we just share dsp_dma_stop and use it here | ||
118 | * | ||
119 | */ | ||
120 | |||
110 | static void saa7134_dma_stop(struct saa7134_dev *dev) | 121 | static void saa7134_dma_stop(struct saa7134_dev *dev) |
122 | |||
111 | { | 123 | { |
112 | dev->oss.dma_blk = -1; | 124 | dev->oss.dma_blk = -1; |
113 | dev->oss.dma_running = 0; | 125 | dev->oss.dma_running = 0; |
114 | saa7134_set_dmabits(dev); | 126 | saa7134_set_dmabits(dev); |
115 | } | 127 | } |
116 | 128 | ||
129 | /* | ||
130 | * saa7134 DMA audio start | ||
131 | * | ||
132 | * Called when preparing the capture device for use | ||
133 | * | ||
134 | * - Copied verbatim from saa7134-oss's dsp_dma_start. Can be dropped | ||
135 | * if we just share dsp_dma_start and use it here | ||
136 | * | ||
137 | */ | ||
138 | |||
117 | static void saa7134_dma_start(struct saa7134_dev *dev) | 139 | static void saa7134_dma_start(struct saa7134_dev *dev) |
118 | { | 140 | { |
119 | dev->oss.dma_blk = 0; | 141 | dev->oss.dma_blk = 0; |
@@ -121,6 +143,17 @@ static void saa7134_dma_start(struct saa7134_dev *dev) | |||
121 | saa7134_set_dmabits(dev); | 143 | saa7134_set_dmabits(dev); |
122 | } | 144 | } |
123 | 145 | ||
146 | /* | ||
147 | * saa7134 audio DMA IRQ handler | ||
148 | * | ||
149 | * Called whenever we get an SAA7134_IRQ_REPORT_DONE_RA3 interrupt | ||
150 | * Handles shifting between the 2 buffers, manages the read counters, | ||
151 | * and notifies ALSA when periods elapse | ||
152 | * | ||
153 | * - Mostly copied from saa7134-oss's saa7134_irq_oss_done. | ||
154 | * | ||
155 | */ | ||
156 | |||
124 | void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) | 157 | void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) |
125 | { | 158 | { |
126 | int next_blk, reg = 0; | 159 | int next_blk, reg = 0; |
@@ -179,6 +212,15 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) | |||
179 | 212 | ||
180 | } | 213 | } |
181 | 214 | ||
215 | /* | ||
216 | * ALSA capture trigger | ||
217 | * | ||
218 | * - One of the ALSA capture callbacks. | ||
219 | * | ||
220 | * Called whenever a capture is started or stopped. Must be defined, | ||
221 | * but there's nothing we want to do here | ||
222 | * | ||
223 | */ | ||
182 | 224 | ||
183 | static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream, | 225 | static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream, |
184 | int cmd) | 226 | int cmd) |
@@ -186,6 +228,18 @@ static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream, | |||
186 | return 0; | 228 | return 0; |
187 | } | 229 | } |
188 | 230 | ||
231 | /* | ||
232 | * DMA buffer config | ||
233 | * | ||
234 | * Sets the values that will later be used as the size of the buffer, | ||
235 | * size of the fragments, and total number of fragments. | ||
236 | * Must be called during the preparation stage, before memory is | ||
237 | * allocated | ||
238 | * | ||
239 | * - Copied verbatim from saa7134-oss. Can be dropped | ||
240 | * if we just share dsp_buffer_conf from OSS. | ||
241 | */ | ||
242 | |||
189 | static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) | 243 | static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) |
190 | { | 244 | { |
191 | if (blksize < 0x100) | 245 | if (blksize < 0x100) |
@@ -207,6 +261,17 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) | |||
207 | return 0; | 261 | return 0; |
208 | } | 262 | } |
209 | 263 | ||
264 | /* | ||
265 | * DMA buffer initialization | ||
266 | * | ||
267 | * Uses V4L functions to initialize the DMA. Shouldn't be necessary in | ||
268 | * ALSA, but I was unable to use ALSA's own DMA, and had to force the | ||
269 | * usage of V4L's | ||
270 | * | ||
271 | * - Copied verbatim from saa7134-oss. Can be dropped | ||
272 | * if we just share dsp_buffer_init from OSS. | ||
273 | */ | ||
274 | |||
210 | static int dsp_buffer_init(struct saa7134_dev *dev) | 275 | static int dsp_buffer_init(struct saa7134_dev *dev) |
211 | { | 276 | { |
212 | int err; | 277 | int err; |
@@ -221,8 +286,19 @@ static int dsp_buffer_init(struct saa7134_dev *dev) | |||
221 | return 0; | 286 | return 0; |
222 | } | 287 | } |
223 | 288 | ||
289 | /* | ||
290 | * ALSA PCM preparation | ||
291 | * | ||
292 | * - One of the ALSA capture callbacks. | ||
293 | * | ||
294 | * Called right after the capture device is opened, this function configures | ||
295 | * the buffer using the previously defined functions, allocates the memory, | ||
296 | * sets up the hardware registers, and then starts the DMA. When this function | ||
297 | * returns, the audio should be flowing. | ||
298 | * | ||
299 | */ | ||
224 | 300 | ||
225 | static int snd_card_saa7134_pcm_prepare(snd_pcm_substream_t * substream) | 301 | static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) |
226 | { | 302 | { |
227 | snd_pcm_runtime_t *runtime = substream->runtime; | 303 | snd_pcm_runtime_t *runtime = substream->runtime; |
228 | int err, bswap, sign; | 304 | int err, bswap, sign; |
@@ -329,7 +405,6 @@ static int snd_card_saa7134_pcm_prepare(snd_pcm_substream_t * substream) | |||
329 | fmt |= (2 << 4); | 405 | fmt |= (2 << 4); |
330 | if (!sign) | 406 | if (!sign) |
331 | fmt |= 0x04; | 407 | fmt |= 0x04; |
332 | //saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -1); | ||
333 | saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -1); | 408 | saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -1); |
334 | saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); | 409 | saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); |
335 | //saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210); | 410 | //saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210); |
@@ -346,7 +421,12 @@ static int snd_card_saa7134_pcm_prepare(snd_pcm_substream_t * substream) | |||
346 | if (bswap) | 421 | if (bswap) |
347 | control |= SAA7134_RS_CONTROL_BSWAP; | 422 | control |= SAA7134_RS_CONTROL_BSWAP; |
348 | 423 | ||
424 | /* I should be able to use runtime->dma_addr in the control | ||
425 | byte, but it doesn't work. So I allocate the DMA using the | ||
426 | V4L functions, and force ALSA to use that as the DMA area */ | ||
427 | |||
349 | runtime->dma_area = dev->oss.dma.vmalloc; | 428 | runtime->dma_area = dev->oss.dma.vmalloc; |
429 | |||
350 | saa_writel(SAA7134_RS_BA1(6),0); | 430 | saa_writel(SAA7134_RS_BA1(6),0); |
351 | saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize); | 431 | saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize); |
352 | saa_writel(SAA7134_RS_PITCH(6),0); | 432 | saa_writel(SAA7134_RS_PITCH(6),0); |
@@ -368,12 +448,18 @@ static int snd_card_saa7134_pcm_prepare(snd_pcm_substream_t * substream) | |||
368 | 448 | ||
369 | } | 449 | } |
370 | 450 | ||
371 | static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) | 451 | /* |
372 | { | 452 | * ALSA pointer fetching |
373 | return snd_card_saa7134_pcm_prepare(substream); | 453 | * |
374 | } | 454 | * - One of the ALSA capture callbacks. |
455 | * | ||
456 | * Called whenever a period elapses, it must return the current hardware | ||
457 | * position of the buffer. | ||
458 | * Also resets the read counter used to prevent overruns | ||
459 | * | ||
460 | */ | ||
375 | 461 | ||
376 | static snd_pcm_uframes_t snd_card_saa7134_pointer(snd_pcm_substream_t * substream) | 462 | static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * substream) |
377 | { | 463 | { |
378 | snd_pcm_runtime_t *runtime = substream->runtime; | 464 | snd_pcm_runtime_t *runtime = substream->runtime; |
379 | snd_card_saa7134_pcm_t *saapcm = runtime->private_data; | 465 | snd_card_saa7134_pcm_t *saapcm = runtime->private_data; |
@@ -388,15 +474,12 @@ static snd_pcm_uframes_t snd_card_saa7134_pointer(snd_pcm_substream_t * substrea | |||
388 | dev->oss.read_offset = 0; | 474 | dev->oss.read_offset = 0; |
389 | } | 475 | } |
390 | 476 | ||
391 | //return bytes_to_frames(runtime, saa_readl(dev->oss.recording_on)); | ||
392 | return bytes_to_frames(runtime, dev->oss.read_offset); | 477 | return bytes_to_frames(runtime, dev->oss.read_offset); |
393 | } | 478 | } |
394 | 479 | ||
395 | 480 | /* | |
396 | static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * substream) | 481 | * ALSA hardware capabilities definition |
397 | { | 482 | */ |
398 | return snd_card_saa7134_pointer(substream); | ||
399 | } | ||
400 | 483 | ||
401 | static snd_pcm_hardware_t snd_card_saa7134_capture = | 484 | static snd_pcm_hardware_t snd_card_saa7134_capture = |
402 | { | 485 | { |
@@ -425,6 +508,17 @@ static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime) | |||
425 | } | 508 | } |
426 | 509 | ||
427 | 510 | ||
511 | /* | ||
512 | * ALSA hardware params | ||
513 | * | ||
514 | * - One of the ALSA capture callbacks. | ||
515 | * | ||
516 | * Called on initialization, right before the PCM preparation | ||
517 | * Usually used in ALSA to allocate the DMA, but since we don't use the | ||
518 | * ALSA DMA I'm almost sure this isn't necessary. | ||
519 | * | ||
520 | */ | ||
521 | |||
428 | static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, | 522 | static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, |
429 | snd_pcm_hw_params_t * hw_params) | 523 | snd_pcm_hw_params_t * hw_params) |
430 | { | 524 | { |
@@ -434,11 +528,29 @@ static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream, | |||
434 | 528 | ||
435 | } | 529 | } |
436 | 530 | ||
531 | /* | ||
532 | * ALSA hardware release | ||
533 | * | ||
534 | * - One of the ALSA capture callbacks. | ||
535 | * | ||
536 | * Called after closing the device, but before snd_card_saa7134_capture_close | ||
537 | * Usually used in ALSA to free the DMA, but since we don't use the | ||
538 | * ALSA DMA I'm almost sure this isn't necessary. | ||
539 | * | ||
540 | */ | ||
541 | |||
437 | static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) | 542 | static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) |
438 | { | 543 | { |
439 | return snd_pcm_lib_free_pages(substream); | 544 | return snd_pcm_lib_free_pages(substream); |
440 | } | 545 | } |
441 | 546 | ||
547 | /* | ||
548 | * DMA buffer release | ||
549 | * | ||
550 | * Called after closing the device, during snd_card_saa7134_capture_close | ||
551 | * | ||
552 | */ | ||
553 | |||
442 | static int dsp_buffer_free(struct saa7134_dev *dev) | 554 | static int dsp_buffer_free(struct saa7134_dev *dev) |
443 | { | 555 | { |
444 | if (!dev->oss.blksize) | 556 | if (!dev->oss.blksize) |
@@ -453,9 +565,20 @@ static int dsp_buffer_free(struct saa7134_dev *dev) | |||
453 | return 0; | 565 | return 0; |
454 | } | 566 | } |
455 | 567 | ||
568 | /* | ||
569 | * ALSA capture finish | ||
570 | * | ||
571 | * - One of the ALSA capture callbacks. | ||
572 | * | ||
573 | * Called after closing the device. It stops the DMA audio and releases | ||
574 | * the buffers | ||
575 | * | ||
576 | */ | ||
456 | 577 | ||
457 | static int saa7134_cap_close(struct saa7134_dev *dev) | 578 | static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) |
458 | { | 579 | { |
580 | snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream); | ||
581 | struct saa7134_dev *dev = chip->saadev; | ||
459 | unsigned long flags; | 582 | unsigned long flags; |
460 | 583 | ||
461 | /* stop dma */ | 584 | /* stop dma */ |
@@ -471,8 +594,23 @@ static int saa7134_cap_close(struct saa7134_dev *dev) | |||
471 | return 0; | 594 | return 0; |
472 | } | 595 | } |
473 | 596 | ||
597 | /* | ||
598 | * ALSA capture start | ||
599 | * | ||
600 | * - One of the ALSA capture callbacks. | ||
601 | * | ||
602 | * Called when opening the device. It creates and populates the PCM | ||
603 | * structure | ||
604 | * | ||
605 | */ | ||
474 | 606 | ||
475 | static int saa7134_cap_open(struct saa7134_dev *dev) { | 607 | static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) |
608 | { | ||
609 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
610 | snd_card_saa7134_pcm_t *saapcm; | ||
611 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); | ||
612 | struct saa7134_dev *dev = saa7134->saadev; | ||
613 | int err; | ||
476 | 614 | ||
477 | down(&dev->oss.lock); | 615 | down(&dev->oss.lock); |
478 | 616 | ||
@@ -483,18 +621,6 @@ static int saa7134_cap_open(struct saa7134_dev *dev) { | |||
483 | 621 | ||
484 | up(&dev->oss.lock); | 622 | up(&dev->oss.lock); |
485 | 623 | ||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) | ||
490 | { | ||
491 | snd_pcm_runtime_t *runtime = substream->runtime; | ||
492 | snd_card_saa7134_pcm_t *saapcm; | ||
493 | snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); | ||
494 | int err; | ||
495 | |||
496 | saa7134_cap_open(saa7134->saadev); | ||
497 | |||
498 | saapcm = kcalloc(1, sizeof(*saapcm), GFP_KERNEL); | 624 | saapcm = kcalloc(1, sizeof(*saapcm), GFP_KERNEL); |
499 | if (saapcm == NULL) | 625 | if (saapcm == NULL) |
500 | return -ENOMEM; | 626 | return -ENOMEM; |
@@ -513,13 +639,9 @@ static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) | |||
513 | return 0; | 639 | return 0; |
514 | } | 640 | } |
515 | 641 | ||
516 | static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) | 642 | /* |
517 | { | 643 | * ALSA capture callbacks definition |
518 | snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream); | 644 | */ |
519 | |||
520 | saa7134_cap_close(chip->saadev); | ||
521 | return 0; | ||
522 | } | ||
523 | 645 | ||
524 | static snd_pcm_ops_t snd_card_saa7134_capture_ops = { | 646 | static snd_pcm_ops_t snd_card_saa7134_capture_ops = { |
525 | .open = snd_card_saa7134_capture_open, | 647 | .open = snd_card_saa7134_capture_open, |
@@ -532,7 +654,15 @@ static snd_pcm_ops_t snd_card_saa7134_capture_ops = { | |||
532 | .pointer = snd_card_saa7134_capture_pointer, | 654 | .pointer = snd_card_saa7134_capture_pointer, |
533 | }; | 655 | }; |
534 | 656 | ||
535 | static int __init snd_card_saa7134_pcm(snd_card_saa7134_t *saa7134, int device) | 657 | /* |
658 | * ALSA PCM setup | ||
659 | * | ||
660 | * Called when initializing the board. Sets up the name and hooks up | ||
661 | * the callbacks | ||
662 | * | ||
663 | */ | ||
664 | |||
665 | static int snd_card_saa7134_pcm(snd_card_saa7134_t *saa7134, int device) | ||
536 | { | 666 | { |
537 | snd_pcm_t *pcm; | 667 | snd_pcm_t *pcm; |
538 | int err; | 668 | int err; |
@@ -612,7 +742,7 @@ static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ | |||
612 | static int snd_saa7134_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo) | 742 | static int snd_saa7134_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo) |
613 | { | 743 | { |
614 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | 744 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; |
615 | uinfo->count = 1; | 745 | uinfo->count = 2; |
616 | uinfo->value.integer.min = 0; | 746 | uinfo->value.integer.min = 0; |
617 | uinfo->value.integer.max = 1; | 747 | uinfo->value.integer.max = 1; |
618 | return 0; | 748 | return 0; |
@@ -647,7 +777,7 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ | |||
647 | right = ucontrol->value.integer.value[1] & 1; | 777 | right = ucontrol->value.integer.value[1] & 1; |
648 | spin_lock_irqsave(&chip->mixer_lock, flags); | 778 | spin_lock_irqsave(&chip->mixer_lock, flags); |
649 | 779 | ||
650 | change = chip->capture_source[addr][0] != left && | 780 | change = chip->capture_source[addr][0] != left || |
651 | chip->capture_source[addr][1] != right; | 781 | chip->capture_source[addr][1] != right; |
652 | chip->capture_source[addr][0] = left; | 782 | chip->capture_source[addr][0] = left; |
653 | chip->capture_source[addr][1] = right; | 783 | chip->capture_source[addr][1] = right; |
@@ -655,7 +785,8 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ | |||
655 | spin_unlock_irqrestore(&chip->mixer_lock, flags); | 785 | spin_unlock_irqrestore(&chip->mixer_lock, flags); |
656 | 786 | ||
657 | 787 | ||
658 | switch (dev->pci->device) { | 788 | if (change) { |
789 | switch (dev->pci->device) { | ||
659 | 790 | ||
660 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | 791 | case PCI_DEVICE_ID_PHILIPS_SAA7134: |
661 | switch (addr) { | 792 | switch (addr) { |
@@ -702,7 +833,8 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ | |||
702 | saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, 0); | 833 | saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, 0); |
703 | saa_writel(SAA7133_ANALOG_IO_SELECT, 0); | 834 | saa_writel(SAA7133_ANALOG_IO_SELECT, 0); |
704 | } | 835 | } |
705 | } | 836 | } |
837 | } | ||
706 | 838 | ||
707 | return change; | 839 | return change; |
708 | } | 840 | } |
@@ -716,7 +848,15 @@ SAA713x_VOLUME("Line Volume", 2, MIXER_ADDR_LINE2), | |||
716 | SAA713x_CAPSRC("Line Capture Switch", 2, MIXER_ADDR_LINE2), | 848 | SAA713x_CAPSRC("Line Capture Switch", 2, MIXER_ADDR_LINE2), |
717 | }; | 849 | }; |
718 | 850 | ||
719 | static int __init snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) | 851 | /* |
852 | * ALSA mixer setup | ||
853 | * | ||
854 | * Called when initializing the board. Sets up the name and hooks up | ||
855 | * the callbacks | ||
856 | * | ||
857 | */ | ||
858 | |||
859 | static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip) | ||
720 | { | 860 | { |
721 | snd_card_t *card = chip->card; | 861 | snd_card_t *card = chip->card; |
722 | unsigned int idx; | 862 | unsigned int idx; |
@@ -743,11 +883,19 @@ static int snd_saa7134_dev_free(snd_device_t *device) | |||
743 | return snd_saa7134_free(chip); | 883 | return snd_saa7134_free(chip); |
744 | } | 884 | } |
745 | 885 | ||
886 | /* | ||
887 | * ALSA initialization | ||
888 | * | ||
889 | * Called by saa7134-core, it creates the basic structures and registers | ||
890 | * the ALSA devices | ||
891 | * | ||
892 | */ | ||
893 | |||
746 | int alsa_card_saa7134_create(struct saa7134_dev *saadev) | 894 | int alsa_card_saa7134_create(struct saa7134_dev *saadev) |
747 | { | 895 | { |
748 | static int dev; | 896 | static int dev; |
749 | snd_card_t *card; | 897 | snd_card_t *card; |
750 | struct snd_card_saa7134 *chip; | 898 | snd_card_saa7134_t *chip; |
751 | int err; | 899 | int err; |
752 | static snd_device_ops_t ops = { | 900 | static snd_device_ops_t ops = { |
753 | .dev_free = snd_saa7134_dev_free, | 901 | .dev_free = snd_saa7134_dev_free, |
@@ -757,14 +905,16 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev) | |||
757 | return -ENODEV; | 905 | return -ENODEV; |
758 | if (!enable[dev]) | 906 | if (!enable[dev]) |
759 | return -ENODEV; | 907 | return -ENODEV; |
908 | |||
760 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, | 909 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, |
761 | sizeof(struct snd_card_saa7134)); | 910 | 0); |
762 | if (card == NULL) | 911 | if (card == NULL) |
763 | return -ENOMEM; | 912 | return -ENOMEM; |
764 | 913 | ||
765 | strcpy(card->driver, "SAA7134"); | 914 | strcpy(card->driver, "SAA7134"); |
766 | 915 | ||
767 | /* Card "creation" */ | 916 | /* Card "creation" */ |
917 | |||
768 | chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); | 918 | chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); |
769 | if (chip == NULL) { | 919 | if (chip == NULL) { |
770 | return -ENOMEM; | 920 | return -ENOMEM; |
@@ -775,6 +925,7 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev) | |||
775 | chip->saadev = saadev; | 925 | chip->saadev = saadev; |
776 | 926 | ||
777 | chip->card = card; | 927 | chip->card = card; |
928 | |||
778 | chip->pci = saadev->pci; | 929 | chip->pci = saadev->pci; |
779 | chip->irq = saadev->pci->irq; | 930 | chip->irq = saadev->pci->irq; |
780 | chip->iobase = pci_resource_start(saadev->pci, 0); | 931 | chip->iobase = pci_resource_start(saadev->pci, 0); |
@@ -784,12 +935,12 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev) | |||
784 | return err; | 935 | return err; |
785 | } | 936 | } |
786 | 937 | ||
787 | |||
788 | if ((err = snd_card_saa7134_new_mixer(chip)) < 0) | 938 | if ((err = snd_card_saa7134_new_mixer(chip)) < 0) |
789 | goto __nodev; | 939 | goto __nodev; |
790 | 940 | ||
791 | if ((err = snd_card_saa7134_pcm(chip, 0)) < 0) | 941 | if ((err = snd_card_saa7134_pcm(chip, 0)) < 0) |
792 | goto __nodev; | 942 | goto __nodev; |
943 | |||
793 | spin_lock_init(&chip->mixer_lock); | 944 | spin_lock_init(&chip->mixer_lock); |
794 | 945 | ||
795 | snd_card_set_dev(card, &chip->pci->dev); | 946 | snd_card_set_dev(card, &chip->pci->dev); |
@@ -800,7 +951,6 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev) | |||
800 | sprintf(card->longname, "%s at 0x%lx irq %d", | 951 | sprintf(card->longname, "%s at 0x%lx irq %d", |
801 | card->shortname, chip->iobase, chip->irq); | 952 | card->shortname, chip->iobase, chip->irq); |
802 | 953 | ||
803 | |||
804 | if ((err = snd_card_register(card)) == 0) { | 954 | if ((err = snd_card_register(card)) == 0) { |
805 | snd_saa7134_cards[dev] = card; | 955 | snd_saa7134_cards[dev] = card; |
806 | return 0; | 956 | return 0; |