Release 4.7 sound/oss/pas2_pcm.c
/*
* pas2_pcm.c Audio routines for PAS16
*
*
* Copyright (C) by Hannu Savolainen 1993-1997
*
* OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
* Version 2 (June 1991). See the "COPYING" file distributed with this software
* for more info.
*
*
* Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
* Alan Cox : Swatted a double allocation of device bug. Made a few
* more things module options.
* Bartlomiej Zolnierkiewicz : Added __init to pas_pcm_init()
*/
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/timex.h>
#include "sound_config.h"
#include "pas2.h"
#define PAS_PCM_INTRBITS (0x08)
/*
* Sample buffer timer interrupt enable
*/
#define PCM_NON 0
#define PCM_DAC 1
#define PCM_ADC 2
static unsigned long pcm_speed;
/* sampling rate */
static unsigned char pcm_channels = 1;
/* channels (1 or 2) */
static unsigned char pcm_bits = 8;
/* bits/sample (8 or 16) */
static unsigned char pcm_filter;
/* filter FLAG */
static unsigned char pcm_mode = PCM_NON;
static unsigned long pcm_count;
static unsigned short pcm_bitsok = 8;
/* mask of OK bits */
static int pcm_busy;
int pas_audiodev = -1;
static int open_mode;
extern spinlock_t pas_lock;
static int pcm_set_speed(int arg)
{
int foo, tmp;
unsigned long flags;
if (arg == 0)
return pcm_speed;
if (arg > 44100)
arg = 44100;
if (arg < 5000)
arg = 5000;
if (pcm_channels & 2)
{
foo = ((PIT_TICK_RATE / 2) + (arg / 2)) / arg;
arg = ((PIT_TICK_RATE / 2) + (foo / 2)) / foo;
}
else
{
foo = (PIT_TICK_RATE + (arg / 2)) / arg;
arg = (PIT_TICK_RATE + (foo / 2)) / foo;
}
pcm_speed = arg;
tmp = pas_read(0x0B8A);
/*
* Set anti-aliasing filters according to sample rate. You really *NEED*
* to enable this feature for all normal recording unless you want to
* experiment with aliasing effects.
* These filters apply to the selected "recording" source.
* I (pfw) don't know the encoding of these 5 bits. The values shown
* come from the SDK found on ftp.uwp.edu:/pub/msdos/proaudio/.
*
* I cleared bit 5 of these values, since that bit controls the master
* mute flag. (Olav Wölfelschneider)
*
*/
#if !defined NO_AUTO_FILTER_SET
tmp &= 0xe0;
if (pcm_speed >= 2 * 17897)
tmp |= 0x01;
else if (pcm_speed >= 2 * 15909)
tmp |= 0x02;
else if (pcm_speed >= 2 * 11931)
tmp |= 0x09;
else if (pcm_speed >= 2 * 8948)
tmp |= 0x11;
else if (pcm_speed >= 2 * 5965)
tmp |= 0x19;
else if (pcm_speed >= 2 * 2982)
tmp |= 0x04;
pcm_filter = tmp;
#endif
spin_lock_irqsave(&pas_lock, flags);
pas_write(tmp & ~(0x40 | 0x80), 0x0B8A);
pas_write(0x00 | 0x30 | 0x04, 0x138B);
pas_write(foo & 0xff, 0x1388);
pas_write((foo >> 8) & 0xff, 0x1388);
pas_write(tmp, 0x0B8A);
spin_unlock_irqrestore(&pas_lock, flags);
return pcm_speed;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 278 | 92.98% | 7 | 58.33% |
andrew morton | andrew morton | 8 | 2.68% | 1 | 8.33% |
peter waechtler | peter waechtler | 6 | 2.01% | 1 | 8.33% |
deepak saxena | deepak saxena | 4 | 1.34% | 1 | 8.33% |
rusty russell | rusty russell | 2 | 0.67% | 1 | 8.33% |
john anthony kazos jr | john anthony kazos jr | 1 | 0.33% | 1 | 8.33% |
| Total | 299 | 100.00% | 12 | 100.00% |
static int pcm_set_channels(int arg)
{
if ((arg != 1) && (arg != 2))
return pcm_channels;
if (arg != pcm_channels)
{
pas_write(pas_read(0xF8A) ^ 0x20, 0xF8A);
pcm_channels = arg;
pcm_set_speed(pcm_speed); /* The speed must be reinitialized */
}
return pcm_channels;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 59 | 100.00% | 3 | 100.00% |
| Total | 59 | 100.00% | 3 | 100.00% |
static int pcm_set_bits(int arg)
{
if (arg == 0)
return pcm_bits;
if ((arg & pcm_bitsok) != arg)
return pcm_bits;
if (arg != pcm_bits)
{
pas_write(pas_read(0x8389) ^ 0x04, 0x8389);
pcm_bits = arg;
}
return pcm_bits;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 58 | 100.00% | 4 | 100.00% |
| Total | 58 | 100.00% | 4 | 100.00% |
static int pas_audio_ioctl(int dev, unsigned int cmd, void __user *arg)
{
int val, ret;
int __user *p = arg;
switch (cmd)
{
case SOUND_PCM_WRITE_RATE:
if (get_user(val, p))
return -EFAULT;
ret = pcm_set_speed(val);
break;
case SOUND_PCM_READ_RATE:
ret = pcm_speed;
break;
case SNDCTL_DSP_STEREO:
if (get_user(val, p))
return -EFAULT;
ret = pcm_set_channels(val + 1) - 1;
break;
case SOUND_PCM_WRITE_CHANNELS:
if (get_user(val, p))
return -EFAULT;
ret = pcm_set_channels(val);
break;
case SOUND_PCM_READ_CHANNELS:
ret = pcm_channels;
break;
case SNDCTL_DSP_SETFMT:
if (get_user(val, p))
return -EFAULT;
ret = pcm_set_bits(val);
break;
case SOUND_PCM_READ_BITS:
ret = pcm_bits;
break;
default:
return -EINVAL;
}
return put_user(ret, p);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 158 | 91.33% | 8 | 88.89% |
al viro | al viro | 15 | 8.67% | 1 | 11.11% |
| Total | 173 | 100.00% | 9 | 100.00% |
static void pas_audio_reset(int dev)
{
pas_write(pas_read(0xF8A) & ~0x40, 0xF8A); /* Disable PCM */
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 23 | 100.00% | 3 | 100.00% |
| Total | 23 | 100.00% | 3 | 100.00% |
static int pas_audio_open(int dev, int mode)
{
int err;
unsigned long flags;
spin_lock_irqsave(&pas_lock, flags);
if (pcm_busy)
{
spin_unlock_irqrestore(&pas_lock, flags);
return -EBUSY;
}
pcm_busy = 1;
spin_unlock_irqrestore(&pas_lock, flags);
if ((err = pas_set_intr(PAS_PCM_INTRBITS)) < 0)
return err;
pcm_count = 0;
open_mode = mode;
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 72 | 85.71% | 4 | 66.67% |
peter waechtler | peter waechtler | 9 | 10.71% | 1 | 16.67% |
rusty russell | rusty russell | 3 | 3.57% | 1 | 16.67% |
| Total | 84 | 100.00% | 6 | 100.00% |
static void pas_audio_close(int dev)
{
unsigned long flags;
spin_lock_irqsave(&pas_lock, flags);
pas_audio_reset(dev);
pas_remove_intr(PAS_PCM_INTRBITS);
pcm_mode = PCM_NON;
pcm_busy = 0;
spin_unlock_irqrestore(&pas_lock, flags);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 39 | 82.98% | 3 | 60.00% |
peter waechtler | peter waechtler | 6 | 12.77% | 1 | 20.00% |
rusty russell | rusty russell | 2 | 4.26% | 1 | 20.00% |
| Total | 47 | 100.00% | 5 | 100.00% |
static void pas_audio_output_block(int dev, unsigned long buf, int count,
int intrflag)
{
unsigned long flags, cnt;
cnt = count;
if (audio_devs[dev]->dmap_out->dma > 3)
cnt >>= 1;
if (audio_devs[dev]->flags & DMA_AUTOMODE &&
intrflag &&
cnt == pcm_count)
return;
spin_lock_irqsave(&pas_lock, flags);
pas_write(pas_read(0xF8A) & ~0x40,
0xF8A);
/* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */
if (audio_devs[dev]->dmap_out->dma > 3)
count >>= 1;
if (count != pcm_count)
{
pas_write(pas_read(0x0B8A) & ~0x80, 0x0B8A);
pas_write(0x40 | 0x30 | 0x04, 0x138B);
pas_write(count & 0xff, 0x1389);
pas_write((count >> 8) & 0xff, 0x1389);
pas_write(pas_read(0x0B8A) | 0x80, 0x0B8A);
pcm_count = count;
}
pas_write(pas_read(0x0B8A) | 0x80 | 0x40, 0x0B8A);
#ifdef NO_TRIGGER
pas_write(pas_read(0xF8A) | 0x40 | 0x10, 0xF8A);
#endif
pcm_mode = PCM_DAC;
spin_unlock_irqrestore(&pas_lock, flags);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 210 | 96.33% | 5 | 71.43% |
peter waechtler | peter waechtler | 6 | 2.75% | 1 | 14.29% |
rusty russell | rusty russell | 2 | 0.92% | 1 | 14.29% |
| Total | 218 | 100.00% | 7 | 100.00% |
static void pas_audio_start_input(int dev, unsigned long buf, int count,
int intrflag)
{
unsigned long flags;
int cnt;
cnt = count;
if (audio_devs[dev]->dmap_out->dma > 3)
cnt >>= 1;
if (audio_devs[pas_audiodev]->flags & DMA_AUTOMODE &&
intrflag &&
cnt == pcm_count)
return;
spin_lock_irqsave(&pas_lock, flags);
/* DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); */
if (audio_devs[dev]->dmap_out->dma > 3)
count >>= 1;
if (count != pcm_count)
{
pas_write(pas_read(0x0B8A) & ~0x80, 0x0B8A);
pas_write(0x40 | 0x30 | 0x04, 0x138B);
pas_write(count & 0xff, 0x1389);
pas_write((count >> 8) & 0xff, 0x1389);
pas_write(pas_read(0x0B8A) | 0x80, 0x0B8A);
pcm_count = count;
}
pas_write(pas_read(0x0B8A) | 0x80 | 0x40, 0x0B8A);
#ifdef NO_TRIGGER
pas_write((pas_read(0xF8A) | 0x40) & ~0x10, 0xF8A);
#endif
pcm_mode = PCM_ADC;
spin_unlock_irqrestore(&pas_lock, flags);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 201 | 96.17% | 6 | 75.00% |
peter waechtler | peter waechtler | 6 | 2.87% | 1 | 12.50% |
rusty russell | rusty russell | 2 | 0.96% | 1 | 12.50% |
| Total | 209 | 100.00% | 8 | 100.00% |
#ifndef NO_TRIGGER
static void pas_audio_trigger(int dev, int state)
{
unsigned long flags;
spin_lock_irqsave(&pas_lock, flags);
state &= open_mode;
if (state & PCM_ENABLE_OUTPUT)
pas_write(pas_read(0xF8A) | 0x40 | 0x10, 0xF8A);
else if (state & PCM_ENABLE_INPUT)
pas_write((pas_read(0xF8A) | 0x40) & ~0x10, 0xF8A);
else
pas_write(pas_read(0xF8A) & ~0x40, 0xF8A);
spin_unlock_irqrestore(&pas_lock, flags);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 86 | 91.49% | 3 | 60.00% |
peter waechtler | peter waechtler | 6 | 6.38% | 1 | 20.00% |
rusty russell | rusty russell | 2 | 2.13% | 1 | 20.00% |
| Total | 94 | 100.00% | 5 | 100.00% |
#endif
static int pas_audio_prepare_for_input(int dev, int bsize, int bcount)
{
pas_audio_reset(dev);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 23 | 100.00% | 3 | 100.00% |
| Total | 23 | 100.00% | 3 | 100.00% |
static int pas_audio_prepare_for_output(int dev, int bsize, int bcount)
{
pas_audio_reset(dev);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 23 | 100.00% | 3 | 100.00% |
| Total | 23 | 100.00% | 3 | 100.00% |
static struct audio_driver pas_audio_driver =
{
.owner = THIS_MODULE,
.open = pas_audio_open,
.close = pas_audio_close,
.output_block = pas_audio_output_block,
.start_input = pas_audio_start_input,
.ioctl = pas_audio_ioctl,
.prepare_for_input = pas_audio_prepare_for_input,
.prepare_for_output = pas_audio_prepare_for_output,
.halt_io = pas_audio_reset,
.trigger = pas_audio_trigger
};
void __init pas_pcm_init(struct address_info *hw_config)
{
pcm_bitsok = 8;
if (pas_read(0xEF8B) & 0x08)
pcm_bitsok |= 16;
pcm_set_speed(DSP_DEFAULT_SPEED);
if ((pas_audiodev = sound_install_audiodrv(AUDIO_DRIVER_VERSION,
"Pro Audio Spectrum",
&pas_audio_driver,
sizeof(struct audio_driver),
DMA_AUTOMODE,
AFMT_U8 | AFMT_S16_LE,
NULL,
hw_config->dma,
hw_config->dma)) < 0)
printk(KERN_WARNING "PAS16: Too many PCM devices available\n");
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 79 | 100.00% | 7 | 100.00% |
| Total | 79 | 100.00% | 7 | 100.00% |
void pas_pcm_interrupt(unsigned char status, int cause)
{
if (cause == 1)
{
/*
* Halt the PCM first. Otherwise we don't have time to start a new
* block before the PCM chip proceeds to the next sample
*/
if (!(audio_devs[pas_audiodev]->flags & DMA_AUTOMODE))
pas_write(pas_read(0xF8A) & ~0x40, 0xF8A);
switch (pcm_mode)
{
case PCM_DAC:
DMAbuf_outputintr(pas_audiodev, 1);
break;
case PCM_ADC:
DMAbuf_inputintr(pas_audiodev);
break;
default:
printk(KERN_WARNING "PAS: Unexpected PCM interrupt\n");
}
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 81 | 100.00% | 5 | 100.00% |
| Total | 81 | 100.00% | 5 | 100.00% |
Overall Contributors
| Person | Tokens | Prop | Commits | CommitProp |
pre-git | pre-git | 1521 | 93.26% | 21 | 72.41% |
peter waechtler | peter waechtler | 45 | 2.76% | 1 | 3.45% |
alan cox | alan cox | 20 | 1.23% | 1 | 3.45% |
al viro | al viro | 15 | 0.92% | 1 | 3.45% |
rusty russell | rusty russell | 14 | 0.86% | 1 | 3.45% |
andrew morton | andrew morton | 10 | 0.61% | 1 | 3.45% |
deepak saxena | deepak saxena | 4 | 0.25% | 1 | 3.45% |
arnd bergmann | arnd bergmann | 1 | 0.06% | 1 | 3.45% |
john anthony kazos jr | john anthony kazos jr | 1 | 0.06% | 1 | 3.45% |
| Total | 1631 | 100.00% | 29 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.