aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx88/cx88-alsa.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/cx88/cx88-alsa.c')
-rw-r--r--drivers/media/video/cx88/cx88-alsa.c168
1 files changed, 73 insertions, 95 deletions
diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c
index 8d19d33c8b32..33dd4cb5e877 100644
--- a/drivers/media/video/cx88/cx88-alsa.c
+++ b/drivers/media/video/cx88/cx88-alsa.c
@@ -3,6 +3,7 @@
3 * Support for audio capture 3 * Support for audio capture
4 * PCI function #1 of the cx2388x. 4 * PCI function #1 of the cx2388x.
5 * 5 *
6 * (c) 2007 Trent Piepho <xyzzy@speakeasy.org>
6 * (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org> 7 * (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org>
7 * (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org> 8 * (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org>
8 * Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org> 9 * Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org>
@@ -47,7 +48,6 @@
47#define dprintk_core(level,fmt, arg...) if (debug >= level) \ 48#define dprintk_core(level,fmt, arg...) if (debug >= level) \
48 printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg) 49 printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg)
49 50
50
51/**************************************************************************** 51/****************************************************************************
52 Data type declarations - Can be moded to a header file later 52 Data type declarations - Can be moded to a header file later
53 ****************************************************************************/ 53 ****************************************************************************/
@@ -58,6 +58,7 @@
58struct cx88_audio_dev { 58struct cx88_audio_dev {
59 struct cx88_core *core; 59 struct cx88_core *core;
60 struct cx88_dmaqueue q; 60 struct cx88_dmaqueue q;
61 u64 starttime;
61 62
62 /* pci i/o */ 63 /* pci i/o */
63 struct pci_dev *pci; 64 struct pci_dev *pci;
@@ -68,24 +69,20 @@ struct cx88_audio_dev {
68 struct snd_card *card; 69 struct snd_card *card;
69 70
70 spinlock_t reg_lock; 71 spinlock_t reg_lock;
72 atomic_t count;
71 73
72 unsigned int dma_size; 74 unsigned int dma_size;
73 unsigned int period_size; 75 unsigned int period_size;
74 unsigned int num_periods; 76 unsigned int num_periods;
75 77
76 struct videobuf_dmabuf dma_risc; 78 struct videobuf_dmabuf dma_risc;
77 79
78 int mixer_volume[MIXER_ADDR_LAST+1][2]; 80 int mixer_volume[MIXER_ADDR_LAST+1][2];
79 int capture_source[MIXER_ADDR_LAST+1][2]; 81 int capture_source[MIXER_ADDR_LAST+1][2];
80 82
81 long int read_count; 83 struct cx88_buffer *buf;
82 long int read_offset;
83
84 struct cx88_buffer *buf;
85
86 long opened;
87 struct snd_pcm_substream *substream;
88 84
85 struct snd_pcm_substream *substream;
89}; 86};
90typedef struct cx88_audio_dev snd_cx88_card_t; 87typedef struct cx88_audio_dev snd_cx88_card_t;
91 88
@@ -146,16 +143,13 @@ static int _cx88_start_audio_dma(snd_cx88_card_t *chip)
146 cx_write(MO_AUDD_LNGTH, buf->bpl); 143 cx_write(MO_AUDD_LNGTH, buf->bpl);
147 144
148 /* reset counter */ 145 /* reset counter */
149 cx_write(MO_AUDD_GPCNTRL,GP_COUNT_CONTROL_RESET); 146 cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET);
147 atomic_set(&chip->count, 0);
150 148
151 dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d lines/irq, " 149 dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d "
152 "%d B/irq\n", buf->bpl, cx_read(audio_ch->cmds_start + 8)>>1, 150 "byte buffer\n", buf->bpl, cx_read(audio_ch->cmds_start + 8)>>1,
153 chip->num_periods, buf->bpl * chip->num_periods); 151 chip->num_periods, buf->bpl * chip->num_periods);
154 152
155 dprintk(1, "Enabling IRQ, setting mask from 0x%x to 0x%x\n",
156 chip->core->pci_irqmask,
157 chip->core->pci_irqmask | PCI_INT_AUDINT);
158
159 /* Enables corresponding bits at AUD_INT_STAT */ 153 /* Enables corresponding bits at AUD_INT_STAT */
160 cx_write(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | 154 cx_write(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
161 AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1); 155 AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1);
@@ -198,7 +192,7 @@ static int _cx88_stop_audio_dma(snd_cx88_card_t *chip)
198 return 0; 192 return 0;
199} 193}
200 194
201#define MAX_IRQ_LOOP 10 195#define MAX_IRQ_LOOP 50
202 196
203/* 197/*
204 * BOARD Specific: IRQ dma bits 198 * BOARD Specific: IRQ dma bits
@@ -223,14 +217,11 @@ static void cx8801_aud_irq(snd_cx88_card_t *chip)
223{ 217{
224 struct cx88_core *core = chip->core; 218 struct cx88_core *core = chip->core;
225 u32 status, mask; 219 u32 status, mask;
226 u32 count;
227 220
228 status = cx_read(MO_AUD_INTSTAT); 221 status = cx_read(MO_AUD_INTSTAT);
229 mask = cx_read(MO_AUD_INTMSK); 222 mask = cx_read(MO_AUD_INTMSK);
230 if (0 == (status & mask)) { 223 if (0 == (status & mask))
231 spin_unlock(&chip->reg_lock);
232 return; 224 return;
233 }
234 cx_write(MO_AUD_INTSTAT, status); 225 cx_write(MO_AUD_INTSTAT, status);
235 if (debug > 1 || (status & mask & ~0xff)) 226 if (debug > 1 || (status & mask & ~0xff))
236 cx88_print_irqbits(core->name, "irq aud", 227 cx88_print_irqbits(core->name, "irq aud",
@@ -238,27 +229,20 @@ static void cx8801_aud_irq(snd_cx88_card_t *chip)
238 status, mask); 229 status, mask);
239 /* risc op code error */ 230 /* risc op code error */
240 if (status & AUD_INT_OPC_ERR) { 231 if (status & AUD_INT_OPC_ERR) {
241 printk(KERN_WARNING "%s/0: audio risc op code error\n",core->name); 232 printk(KERN_WARNING "%s/1: Audio risc op code error\n",core->name);
242 cx_clear(MO_AUD_DMACNTRL, 0x11); 233 cx_clear(MO_AUD_DMACNTRL, 0x11);
243 cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]); 234 cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]);
244 } 235 }
245 236 if (status & AUD_INT_DN_SYNC) {
237 dprintk(1, "Downstream sync error\n");
238 cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET);
239 return;
240 }
246 /* risc1 downstream */ 241 /* risc1 downstream */
247 if (status & AUD_INT_DN_RISCI1) { 242 if (status & AUD_INT_DN_RISCI1) {
248 spin_lock(&chip->reg_lock); 243 atomic_set(&chip->count, cx_read(MO_AUDD_GPCNT));
249 count = cx_read(MO_AUDD_GPCNT);
250 spin_unlock(&chip->reg_lock);
251 if (chip->read_count == 0)
252 chip->read_count += chip->dma_size;
253 }
254
255 if (chip->read_count >= chip->period_size) {
256 dprintk(2, "Elapsing period\n");
257 snd_pcm_period_elapsed(chip->substream); 244 snd_pcm_period_elapsed(chip->substream);
258 } 245 }
259
260 dprintk(3,"Leaving audio IRQ handler...\n");
261
262 /* FIXME: Any other status should deserve a special handling? */ 246 /* FIXME: Any other status should deserve a special handling? */
263} 247}
264 248
@@ -277,23 +261,20 @@ static irqreturn_t cx8801_irq(int irq, void *dev_id)
277 (core->pci_irqmask | PCI_INT_AUDINT); 261 (core->pci_irqmask | PCI_INT_AUDINT);
278 if (0 == status) 262 if (0 == status)
279 goto out; 263 goto out;
280 dprintk( 3, "cx8801_irq\n" ); 264 dprintk(3, "cx8801_irq loop %d/%d, status %x\n",
281 dprintk( 3, " loop: %d/%d\n", loop, MAX_IRQ_LOOP ); 265 loop, MAX_IRQ_LOOP, status);
282 dprintk( 3, " status: %d\n", status );
283 handled = 1; 266 handled = 1;
284 cx_write(MO_PCI_INTSTAT, status); 267 cx_write(MO_PCI_INTSTAT, status);
285 268
286 if (status & core->pci_irqmask) 269 if (status & core->pci_irqmask)
287 cx88_core_irq(core, status); 270 cx88_core_irq(core, status);
288 if (status & PCI_INT_AUDINT) { 271 if (status & PCI_INT_AUDINT)
289 dprintk( 2, " ALSA IRQ handling\n" );
290 cx8801_aud_irq(chip); 272 cx8801_aud_irq(chip);
291 } 273 }
292 };
293 274
294 if (MAX_IRQ_LOOP == loop) { 275 if (MAX_IRQ_LOOP == loop) {
295 dprintk( 0, "clearing mask\n" ); 276 printk(KERN_ERR
296 dprintk(1,"%s/0: irq loop -- clearing mask\n", 277 "%s/1: IRQ loop detected, disabling interrupts\n",
297 core->name); 278 core->name);
298 cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT); 279 cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT);
299 } 280 }
@@ -315,7 +296,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip)
315 296
316 chip->dma_size = 0; 297 chip->dma_size = 0;
317 298
318 return 0; 299 return 0;
319} 300}
320 301
321/**************************************************************************** 302/****************************************************************************
@@ -325,6 +306,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip)
325/* 306/*
326 * Digital hardware definition 307 * Digital hardware definition
327 */ 308 */
309#define DEFAULT_FIFO_SIZE 4096
328static struct snd_pcm_hardware snd_cx88_digital_hw = { 310static struct snd_pcm_hardware snd_cx88_digital_hw = {
329 .info = SNDRV_PCM_INFO_MMAP | 311 .info = SNDRV_PCM_INFO_MMAP |
330 SNDRV_PCM_INFO_INTERLEAVED | 312 SNDRV_PCM_INFO_INTERLEAVED |
@@ -337,20 +319,16 @@ static struct snd_pcm_hardware snd_cx88_digital_hw = {
337 .rate_max = 48000, 319 .rate_max = 48000,
338 .channels_min = 2, 320 .channels_min = 2,
339 .channels_max = 2, 321 .channels_max = 2,
340 .buffer_bytes_max = (2*2048), 322 /* Analog audio output will be full of clicks and pops if there
341 .period_bytes_min = 2048, 323 are not exactly four lines in the SRAM FIFO buffer. */
342 .period_bytes_max = 2048, 324 .period_bytes_min = DEFAULT_FIFO_SIZE/4,
343 .periods_min = 2, 325 .period_bytes_max = DEFAULT_FIFO_SIZE/4,
344 .periods_max = 2, 326 .periods_min = 1,
327 .periods_max = 1024,
328 .buffer_bytes_max = (1024*1024),
345}; 329};
346 330
347/* 331/*
348 * audio pcm capture runtime free
349 */
350static void snd_card_cx88_runtime_free(struct snd_pcm_runtime *runtime)
351{
352}
353/*
354 * audio pcm capture open callback 332 * audio pcm capture open callback
355 */ 333 */
356static int snd_cx88_pcm_open(struct snd_pcm_substream *substream) 334static int snd_cx88_pcm_open(struct snd_pcm_substream *substream)
@@ -359,26 +337,24 @@ static int snd_cx88_pcm_open(struct snd_pcm_substream *substream)
359 struct snd_pcm_runtime *runtime = substream->runtime; 337 struct snd_pcm_runtime *runtime = substream->runtime;
360 int err; 338 int err;
361 339
362 if (test_and_set_bit(0, &chip->opened)) 340 err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS);
363 return -EBUSY;
364
365 err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
366 if (err < 0) 341 if (err < 0)
367 goto _error; 342 goto _error;
368 343
369 chip->substream = substream; 344 chip->substream = substream;
370 345
371 chip->read_count = 0;
372 chip->read_offset = 0;
373
374 runtime->private_free = snd_card_cx88_runtime_free;
375 runtime->hw = snd_cx88_digital_hw; 346 runtime->hw = snd_cx88_digital_hw;
376 347
348 if (cx88_sram_channels[SRAM_CH25].fifo_size != DEFAULT_FIFO_SIZE) {
349 unsigned int bpl = cx88_sram_channels[SRAM_CH25].fifo_size / 4;
350 bpl &= ~7; /* must be multiple of 8 */
351 runtime->hw.period_bytes_min = bpl;
352 runtime->hw.period_bytes_max = bpl;
353 }
354
377 return 0; 355 return 0;
378_error: 356_error:
379 dprintk(1,"Error opening PCM!\n"); 357 dprintk(1,"Error opening PCM!\n");
380 clear_bit(0, &chip->opened);
381 smp_mb__after_clear_bit();
382 return err; 358 return err;
383} 359}
384 360
@@ -387,11 +363,6 @@ _error:
387 */ 363 */
388static int snd_cx88_close(struct snd_pcm_substream *substream) 364static int snd_cx88_close(struct snd_pcm_substream *substream)
389{ 365{
390 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
391
392 clear_bit(0, &chip->opened);
393 smp_mb__after_clear_bit();
394
395 return 0; 366 return 0;
396} 367}
397 368
@@ -403,54 +374,61 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
403{ 374{
404 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); 375 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
405 struct cx88_buffer *buf; 376 struct cx88_buffer *buf;
377 int ret;
406 378
407 if (substream->runtime->dma_area) { 379 if (substream->runtime->dma_area) {
408 dsp_buffer_free(chip); 380 dsp_buffer_free(chip);
409 substream->runtime->dma_area = NULL; 381 substream->runtime->dma_area = NULL;
410 } 382 }
411 383
412
413 chip->period_size = params_period_bytes(hw_params); 384 chip->period_size = params_period_bytes(hw_params);
414 chip->num_periods = params_periods(hw_params); 385 chip->num_periods = params_periods(hw_params);
415 chip->dma_size = chip->period_size * params_periods(hw_params); 386 chip->dma_size = chip->period_size * params_periods(hw_params);
416 387
417 BUG_ON(!chip->dma_size); 388 BUG_ON(!chip->dma_size);
389 BUG_ON(chip->num_periods & (chip->num_periods-1));
418 390
419 dprintk(1,"Setting buffer\n"); 391 buf = kzalloc(sizeof(*buf), GFP_KERNEL);
420
421 buf = kzalloc(sizeof(*buf),GFP_KERNEL);
422 if (NULL == buf) 392 if (NULL == buf)
423 return -ENOMEM; 393 return -ENOMEM;
424 394
425 buf->vb.memory = V4L2_MEMORY_MMAP; 395 buf->vb.memory = V4L2_MEMORY_MMAP;
396 buf->vb.field = V4L2_FIELD_NONE;
426 buf->vb.width = chip->period_size; 397 buf->vb.width = chip->period_size;
398 buf->bpl = chip->period_size;
427 buf->vb.height = chip->num_periods; 399 buf->vb.height = chip->num_periods;
428 buf->vb.size = chip->dma_size; 400 buf->vb.size = chip->dma_size;
429 buf->vb.field = V4L2_FIELD_NONE;
430 401
431 videobuf_dma_init(&buf->vb.dma); 402 videobuf_dma_init(&buf->vb.dma);
432 videobuf_dma_init_kernel(&buf->vb.dma,PCI_DMA_FROMDEVICE, 403 ret = videobuf_dma_init_kernel(&buf->vb.dma, PCI_DMA_FROMDEVICE,
433 (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT)); 404 (PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT));
405 if (ret < 0)
406 goto error;
434 407
435 videobuf_pci_dma_map(chip->pci,&buf->vb.dma); 408 ret = videobuf_pci_dma_map(chip->pci,&buf->vb.dma);
436 409 if (ret < 0)
410 goto error;
437 411
438 cx88_risc_databuffer(chip->pci, &buf->risc, 412 ret = cx88_risc_databuffer(chip->pci, &buf->risc, buf->vb.dma.sglist,
439 buf->vb.dma.sglist, 413 buf->vb.width, buf->vb.height, 1);
440 buf->vb.width, buf->vb.height); 414 if (ret < 0)
415 goto error;
441 416
442 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); 417 /* Loop back to start of program */
418 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
443 buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); 419 buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
444 420
445 buf->vb.state = STATE_PREPARED; 421 buf->vb.state = STATE_PREPARED;
446 422
447 buf->bpl = chip->period_size;
448 chip->buf = buf; 423 chip->buf = buf;
449 chip->dma_risc = buf->vb.dma; 424 chip->dma_risc = buf->vb.dma;
450 425
451 dprintk(1,"Buffer ready at %u\n",chip->dma_risc.nr_pages);
452 substream->runtime->dma_area = chip->dma_risc.vmalloc; 426 substream->runtime->dma_area = chip->dma_risc.vmalloc;
453 return 0; 427 return 0;
428
429error:
430 kfree(buf);
431 return ret;
454} 432}
455 433
456/* 434/*
@@ -477,7 +455,6 @@ static int snd_cx88_prepare(struct snd_pcm_substream *substream)
477 return 0; 455 return 0;
478} 456}
479 457
480
481/* 458/*
482 * trigger callback 459 * trigger callback
483 */ 460 */
@@ -486,6 +463,7 @@ static int snd_cx88_card_trigger(struct snd_pcm_substream *substream, int cmd)
486 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); 463 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
487 int err; 464 int err;
488 465
466 /* Local interrupts are already disabled by ALSA */
489 spin_lock(&chip->reg_lock); 467 spin_lock(&chip->reg_lock);
490 468
491 switch (cmd) { 469 switch (cmd) {
@@ -512,17 +490,14 @@ static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream)
512{ 490{
513 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); 491 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
514 struct snd_pcm_runtime *runtime = substream->runtime; 492 struct snd_pcm_runtime *runtime = substream->runtime;
493 u16 count;
515 494
516 if (chip->read_count) { 495 count = atomic_read(&chip->count);
517 chip->read_count -= snd_pcm_lib_period_bytes(substream);
518 chip->read_offset += snd_pcm_lib_period_bytes(substream);
519 if (chip->read_offset == chip->dma_size)
520 chip->read_offset = 0;
521 }
522
523 dprintk(2, "Pointer time, will return %li, read %li\n",chip->read_offset,chip->read_count);
524 return bytes_to_frames(runtime, chip->read_offset);
525 496
497// dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __FUNCTION__,
498// count, new, count & (runtime->periods-1),
499// runtime->period_size * (count & (runtime->periods-1)));
500 return runtime->period_size * (count & (runtime->periods-1));
526} 501}
527 502
528/* 503/*
@@ -592,10 +567,13 @@ static int snd_cx88_capture_volume_put(struct snd_kcontrol *kcontrol,
592 int v; 567 int v;
593 u32 old_control; 568 u32 old_control;
594 569
570 /* Do we really know this will always be called with IRQs on? */
595 spin_lock_irq(&chip->reg_lock); 571 spin_lock_irq(&chip->reg_lock);
572
596 old_control = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f); 573 old_control = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f);
597 v = 0x3f - (value->value.integer.value[0] & 0x3f); 574 v = 0x3f - (value->value.integer.value[0] & 0x3f);
598 cx_andor(AUD_VOL_CTL, 0x3f, v); 575 cx_andor(AUD_VOL_CTL, 0x3f, v);
576
599 spin_unlock_irq(&chip->reg_lock); 577 spin_unlock_irq(&chip->reg_lock);
600 578
601 return v != old_control; 579 return v != old_control;