OpenCores
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.