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] - Diff between revs 199 and 1765

Only display areas with differences | Details | Blame | View Log

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

powered by: WebSVN 2.1.0

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