URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [arch/] [armnommu/] [drivers/] [sound/] [vidc_audio.c] - Rev 199
Go to most recent revision | Compare with Previous | Blame | View Log
/* * sound/vidc_audio.c * * Audio routines for the VIDC * * Copyright (C) 1997 Russell King */ #include <linux/config.h> #include "sound_config.h" #include "vidc.h" /* * VIDC sound * * When using SERIAL SOUND mode (external DAC), the number of physical * channels is fixed at 2. Therefore, the sample rate = vidc sample rate. */ #if defined(CONFIG_VIDC) static int vidc_adev; static int vidc_audio_volume; static int vidc_audio_rate; static char vidc_audio_bits; static char vidc_audio_channels; extern void vidc_update_filler (int bits, int channels); int vidc_audio_get_volume (void) { return vidc_audio_volume; } int vidc_audio_set_volume (int newvol) { vidc_audio_volume = newvol; return vidc_audio_volume; } static int vidc_audio_set_bits (int bits) { switch (bits) { case AFMT_QUERY: break; case AFMT_U8: case AFMT_S8: case AFMT_S16_LE: vidc_audio_bits = bits; vidc_update_filler (vidc_audio_bits, vidc_audio_channels); break; default: vidc_audio_bits = AFMT_S16_LE; vidc_update_filler (vidc_audio_bits, vidc_audio_channels); break; } return vidc_audio_bits; } static int vidc_audio_set_rate (int rate) { if (rate) { int newsize, new2size; vidc_audio_rate = ((500000 / rate) + 1) >> 1; if (vidc_audio_rate < 3) vidc_audio_rate = 3; if (vidc_audio_rate > 255) vidc_audio_rate = 255; outl ((vidc_audio_rate - 2) | 0xb0000000, IO_VIDC_BASE); outl (0xb1000003, IO_VIDC_BASE); newsize = (10000 / vidc_audio_rate) & ~3; if (newsize< 208) newsize = 208; if (newsize > 4096) newsize = 4096; for (new2size = 128; new2size < newsize; new2size <<= 1); if (new2size - newsize > newsize - (new2size >> 1)) new2size >>= 1; dma_bufsize = new2size; } return 250000 / vidc_audio_rate; } static int vidc_audio_set_channels (int channels) { switch (channels) { case 0: break; case 1: case 2: vidc_audio_channels = channels; vidc_update_filler (vidc_audio_bits, vidc_audio_channels); break; default: vidc_audio_channels = 2; vidc_update_filler (vidc_audio_bits, vidc_audio_channels); break; } return vidc_audio_channels; } /* * Open the device * * dev - device * mode - mode to open device (logical OR of OPEN_READ and OPEN_WRITE) * * Called when opening the DMAbuf (dmabuf.c:259) */ static int vidc_audio_open (int dev, int mode) { if (vidc_busy) return -EBUSY; if (mode & OPEN_READ && !mode & OPEN_WRITE) { printk ("VIDCsound: This audio device doesn't have recording capability\n"); return -EIO; } vidc_busy = 1; return 0; } /* * Close the device * * dev - device * * Called when closing the DMAbuf (dmabuf.c:477) * after halt_xfer */ static void vidc_audio_close (int dev) { vidc_busy = 0; } static int vidc_audio_ioctl (int dev, unsigned int cmd, caddr_t arg, int local) { int ret; switch (cmd) { case SOUND_PCM_WRITE_RATE: if (local) ret = vidc_audio_set_rate ((int) arg); else ret = vidc_audio_set_rate (get_user ((int *)arg)); break; case SOUND_PCM_READ_RATE: ret = vidc_audio_set_rate (0); break; case SNDCTL_DSP_STEREO: if (local) ret = vidc_audio_set_channels ((int) arg + 1) - 1; else ret = vidc_audio_set_channels (get_user ((int *)arg) + 1) - 1; break; case SOUND_PCM_WRITE_CHANNELS: if (local) ret = vidc_audio_set_channels ((int) arg); else ret = vidc_audio_set_channels (get_user ((int *)arg)); break; case SOUND_PCM_READ_CHANNELS: ret = vidc_audio_set_channels (0); break; case SNDCTL_DSP_SETFMT: if (local) ret = vidc_audio_set_bits ((int) arg); else ret = vidc_audio_set_bits (get_user ((int *)arg)); break; case SOUND_PCM_READ_BITS: ret = vidc_audio_set_bits (0); break; case SOUND_PCM_WRITE_FILTER: case SOUND_PCM_READ_FILTER: ret = -EINVAL; break; default: ret = -EINVAL; break; } if (local) return ret; else return snd_ioctl_return ((int *)arg, ret); } /* * Output a block via DMA to sound device * * dev - device number * buf - physical address of buffer * total_count - total byte count in buffer * intrflag - set if this has been called from an interrupt (via DMAbuf_outputintr) * restart_dma - set if DMA needs to be re-initialised * * Called when: * 1. Starting output (dmabuf.c:1327) * 2. (dmabuf.c:1504) * 3. A new buffer needs to be sent to the device (dmabuf.c:1579) */ static void vidc_audio_dma_interrupt (void) { DMAbuf_outputintr (vidc_adev, 1); } static void vidc_audio_output_block (int dev, unsigned long buf, int total_count, int intrflag, int restart_dma) { dma_start = (unsigned long)bus_to_virt(buf); dma_count = total_count; if (restart_dma && !intrflag) { dma_interrupt = vidc_audio_dma_interrupt; vidc_sound_dma_irq (0, NULL, NULL); outb (0x30, IOMD_SD0CR); } } static void vidc_audio_start_input (int dev, unsigned long buf, int count, int intrflag, int restart_dma) { } static int vidc_audio_prepare_for_input (int dev, int bsize, int bcount) { return -EINVAL; } /* * Prepare for outputting samples to `dev' * * Each buffer that will be passed will be `bsize' bytes long, * with a total of `bcount' buffers. * * Called when: * 1. A trigger enables audio output (dmabuf.c:978) * 2. We get a write buffer without dma_mode setup (dmabuf.c:1152) * 3. We restart a transfer (dmabuf.c:1324) */ static int vidc_audio_prepare_for_output (int dev, int bsize, int bcount) { return 0; } static void vidc_audio_reset (int dev) { } /* * Halt a DMA transfer to `dev' * * Called when: * 1. We close the DMAbuf (dmabuf.c:476) * 2. We run out of output buffers to output to the device. (dmabuf.c:1456) * 3. We run out of output buffers and we're closing down. (dmabuf.c:1546) * 4. We run out of input buffers in AUTOMODE. (dmabuf.c:1651) */ static void vidc_audio_halt_xfer (int dev) { dma_count = 0; } static int vidc_audio_local_qlen (int dev) { return dma_count != 0; } static struct audio_driver vidc_audio_driver = { vidc_audio_open, /* open */ vidc_audio_close, /* close */ vidc_audio_output_block, /* output_block */ vidc_audio_start_input, /* start_input */ vidc_audio_ioctl, /* ioctl */ vidc_audio_prepare_for_input, /* prepare_for_input */ vidc_audio_prepare_for_output, /* prepare_for_output */ vidc_audio_reset, /* reset */ vidc_audio_halt_xfer, /* halt_xfer */ vidc_audio_local_qlen, /*+local_qlen */ NULL, /*+copy_from_user */ NULL, /*+halt_input */ NULL, /*+halt_output */ NULL, /*+trigger */ NULL, /*+set_speed */ NULL, /*+set_bits */ NULL, /*+set_channels */ }; static struct audio_operations vidc_audio_operations = { "VIDCsound", 0, AFMT_U8 | AFMT_S16_LE, NULL, &vidc_audio_driver }; void vidc_audio_init (struct address_info *hw_config) { vidc_audio_volume = 100 | (100 << 8); if (num_audiodevs < MAX_AUDIO_DEV) { audio_devs[vidc_adev = num_audiodevs++] = &vidc_audio_operations; audio_devs[vidc_adev]->dmachan1 = hw_config->dma; /* size of the total DMA buffer */ audio_devs[vidc_adev]->buffsize = DSP_BUFFSIZE; audio_devs[vidc_adev]->min_fragment = 10; /* 1024 bytes => 64 buffers */ audio_devs[vidc_adev]->mixer_dev = num_mixers; audio_devs[vidc_adev]->flags |= 0; } else printk ("VIDCsound: Too many PCM devices available\n"); } #endif
Go to most recent revision | Compare with Previous | Blame | View Log