patch-2.4.10 linux/drivers/sound/btaudio.c
Next file: linux/drivers/sound/cmpci.c
Previous file: linux/drivers/sound/awe_wave.c
Back to the patch index
Back to the overall index
- Lines: 515
- Date:
Thu Sep 20 14:20:14 2001
- Orig file:
v2.4.9/linux/drivers/sound/btaudio.c
- Orig date:
Mon Aug 27 12:41:45 2001
diff -u --recursive --new-file v2.4.9/linux/drivers/sound/btaudio.c linux/drivers/sound/btaudio.c
@@ -1,7 +1,7 @@
/*
btaudio - bt878 audio dma driver for linux 2.4.x
- (c) 2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+ (c) 2000 Gerd Knorr <kraxel@bytesex.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -91,7 +91,6 @@
#define RISC_SYNC_VRO 0x0c
#define HWBASE_AD (448000)
-#define HWBASE_DA 31928 /* 48000 */
/* -------------------------------------------------------------- */
@@ -100,7 +99,8 @@
struct btaudio *next;
/* device info */
- int dsp_dev;
+ int dsp_digital;
+ int dsp_analog;
int mixer_dev;
struct pci_dev *pci;
unsigned int irq;
@@ -142,14 +142,18 @@
int mixcount;
int sampleshift;
int channels;
+ int analog;
};
static struct btaudio *btaudios = NULL;
-static unsigned int dsp = -1;
+static unsigned int dsp1 = -1;
+static unsigned int dsp2 = -1;
static unsigned int mixer = -1;
static unsigned int debug = 0;
static unsigned int irq_debug = 0;
-static int analog = 0;
+static int digital = 1;
+static int analog = 1;
+static int rate = 32000;
/* -------------------------------------------------------------- */
@@ -210,7 +214,8 @@
if (bta->line_count > 255)
return -EINVAL;
if (debug)
- printk("btaudio: bufsize=%d - bs=%d bc=%d - ls=%d, lc=%d\n",
+ printk(KERN_DEBUG
+ "btaudio: bufsize=%d - bs=%d bc=%d - ls=%d, lc=%d\n",
bta->buf_size,bta->block_bytes,bta->block_count,
bta->line_bytes,bta->line_count);
rp = 0; bp = 0;
@@ -250,7 +255,7 @@
btwrite((bta->line_count << 16) | bta->line_bytes,
REG_PACKET_LEN);
btwrite(IRQ_BTAUDIO, REG_INT_MASK);
- if (analog) {
+ if (bta->analog) {
btwrite(DMA_CTL_ACAP_EN |
DMA_CTL_RISC_EN |
DMA_CTL_FIFO_EN |
@@ -278,7 +283,7 @@
bta->read_count = 0;
bta->recording = 1;
if (debug)
- printk("btaudio: recording started\n");
+ printk(KERN_DEBUG "btaudio: recording started\n");
return 0;
}
@@ -287,15 +292,9 @@
btand(~15, REG_GPIO_DMA_CTL);
bta->recording = 0;
if (debug)
- printk("btaudio: recording stopped\n");
+ printk(KERN_DEBUG "btaudio: recording stopped\n");
}
-/* -------------------------------------------------------------- */
-
-static loff_t btaudio_llseek(struct file *file, loff_t offset, int origin)
-{
- return -ESPIPE;
-}
/* -------------------------------------------------------------- */
@@ -310,6 +309,8 @@
if (NULL == bta)
return -ENODEV;
+ if (debug)
+ printk("btaudio: open mixer [%d]\n",minor);
file->private_data = bta;
return 0;
}
@@ -327,8 +328,9 @@
if (cmd == SOUND_MIXER_INFO) {
mixer_info info;
- strncpy(info.id, "bt878", sizeof(info.id));
- strncpy(info.name, "Brooktree Bt878 audio", sizeof(info.name));
+ memset(&info,0,sizeof(info));
+ strncpy(info.id,"bt878",sizeof(info.id)-1);
+ strncpy(info.name,"Brooktree Bt878 audio",sizeof(info.name)-1);
info.modify_counter = bta->mixcount;
if (copy_to_user((void *)arg, &info, sizeof(info)))
return -EFAULT;
@@ -336,8 +338,9 @@
}
if (cmd == SOUND_OLD_MIXER_INFO) {
_old_mixer_info info;
- strncpy(info.id, "bt878", sizeof(info.id));
- strncpy(info.name, "Brooktree Bt878 audio", sizeof(info.name));
+ memset(&info,0,sizeof(info));
+ strncpy(info.id,"bt878",sizeof(info.id)-1);
+ strncpy(info.name,"Brooktree Bt878 audio",sizeof(info.name)-1);
if (copy_to_user((void *)arg, &info, sizeof(info)))
return -EFAULT;
return 0;
@@ -423,7 +426,7 @@
static struct file_operations btaudio_mixer_fops = {
owner: THIS_MODULE,
- llseek: btaudio_llseek,
+ llseek: no_llseek,
open: btaudio_mixer_open,
release: btaudio_mixer_release,
ioctl: btaudio_mixer_ioctl,
@@ -431,23 +434,16 @@
/* -------------------------------------------------------------- */
-static int btaudio_dsp_open(struct inode *inode, struct file *file)
+static int btaudio_dsp_open(struct inode *inode, struct file *file,
+ struct btaudio *bta, int analog)
{
- int minor = MINOR(inode->i_rdev);
- struct btaudio *bta;
-
- for (bta = btaudios; bta != NULL; bta = bta->next)
- if (bta->dsp_dev == minor)
- break;
- if (NULL == bta)
- return -ENODEV;
-
down(&bta->lock);
if (bta->users)
goto busy;
bta->users++;
file->private_data = bta;
+ bta->analog = analog;
bta->dma_block = 0;
bta->read_offset = 0;
bta->read_count = 0;
@@ -461,6 +457,38 @@
return -EBUSY;
}
+static int btaudio_dsp_open_digital(struct inode *inode, struct file *file)
+{
+ int minor = MINOR(inode->i_rdev);
+ struct btaudio *bta;
+
+ for (bta = btaudios; bta != NULL; bta = bta->next)
+ if (bta->dsp_digital == minor)
+ break;
+ if (NULL == bta)
+ return -ENODEV;
+
+ if (debug)
+ printk("btaudio: open digital dsp [%d]\n",minor);
+ return btaudio_dsp_open(inode,file,bta,0);
+}
+
+static int btaudio_dsp_open_analog(struct inode *inode, struct file *file)
+{
+ int minor = MINOR(inode->i_rdev);
+ struct btaudio *bta;
+
+ for (bta = btaudios; bta != NULL; bta = bta->next)
+ if (bta->dsp_analog == minor)
+ break;
+ if (NULL == bta)
+ return -ENODEV;
+
+ if (debug)
+ printk("btaudio: open analog dsp [%d]\n",minor);
+ return btaudio_dsp_open(inode,file,bta,1);
+}
+
static int btaudio_dsp_release(struct inode *inode, struct file *file)
{
struct btaudio *bta = file->private_data;
@@ -511,9 +539,9 @@
if (nsrc > bta->buf_size - bta->read_offset)
nsrc = bta->buf_size - bta->read_offset;
ndst = nsrc >> bta->sampleshift;
-
- if ((analog && 0 == bta->sampleshift) ||
- (!analog && 2 == bta->channels)) {
+
+ if ((bta->analog && 0 == bta->sampleshift) ||
+ (!bta->analog && 2 == bta->channels)) {
/* just copy */
if (copy_to_user(buffer + ret, bta->buf_cpu + bta->read_offset, nsrc)) {
if (0 == ret)
@@ -521,11 +549,11 @@
break;
}
- } else if (!analog) {
+ } else if (!bta->analog) {
/* stereo => mono (digital audio) */
- __u16 *src = (__u16*)(bta->buf_cpu + bta->read_offset);
- __u16 *dst = (__u16*)(buffer + ret);
- __u16 avg;
+ __s16 *src = (__s16*)(bta->buf_cpu + bta->read_offset);
+ __s16 *dst = (__s16*)(buffer + ret);
+ __s16 avg;
int n = ndst>>1;
if (0 != verify_area(VERIFY_WRITE,dst,ndst)) {
if (0 == ret)
@@ -533,9 +561,9 @@
break;
}
for (; n; n--, dst++) {
- avg = *(src++) >> 1;
- avg += *(src++) >> 1;
- __put_user(avg,(__u16*)(dst));
+ avg = (__s16)le16_to_cpu(*src) / 2; src++;
+ avg += (__s16)le16_to_cpu(*src) / 2; src++;
+ __put_user(cpu_to_le16(avg),(__u16*)(dst));
}
} else if (8 == bta->bits) {
@@ -600,7 +628,7 @@
case SNDCTL_DSP_SPEED:
if (get_user(val, (int*)arg))
return -EFAULT;
- if (analog) {
+ if (bta->analog) {
for (s = 0; s < 16; s++)
if (val << s >= HWBASE_AD*4/15)
break;
@@ -610,7 +638,8 @@
bta->sampleshift = s;
bta->decimation = i;
if (debug)
- printk("btaudio: rate: req=%d dec=%d shift=%d hwrate=%d swrate=%d\n",
+ printk(KERN_DEBUG "btaudio: rate: req=%d "
+ "dec=%d shift=%d hwrate=%d swrate=%d\n",
val,i,s,(HWBASE_AD*4/i),(HWBASE_AD*4/i)>>s);
} else {
bta->sampleshift = (bta->channels == 2) ? 0 : 1;
@@ -624,26 +653,30 @@
}
/* fall through */
case SOUND_PCM_READ_RATE:
- if (analog) {
+ if (bta->analog) {
return put_user(HWBASE_AD*4/bta->decimation>>bta->sampleshift, (int*)arg);
} else {
- return put_user(HWBASE_DA, (int*)arg);
+ return put_user(rate, (int*)arg);
}
case SNDCTL_DSP_STEREO:
- if (!analog) {
+ if (!bta->analog) {
if (get_user(val, (int*)arg))
return -EFAULT;
bta->channels = (val > 0) ? 2 : 1;
bta->sampleshift = (bta->channels == 2) ? 0 : 1;
- printk("btaudio: stereo=%d channels=%d\n",
- val,bta->channels);
+ if (debug)
+ printk(KERN_INFO
+ "btaudio: stereo=%d channels=%d\n",
+ val,bta->channels);
} else {
if (val == 1)
return -EFAULT;
else {
bta->channels = 1;
- printk("btaudio: stereo=0 channels=1\n");
+ if (debug)
+ printk(KERN_INFO
+ "btaudio: stereo=0 channels=1\n");
}
}
return put_user((bta->channels)-1, (int *)arg);
@@ -654,8 +687,10 @@
return -EFAULT;
bta->channels = (val > 1) ? 2 : 1;
bta->sampleshift = (bta->channels == 2) ? 0 : 1;
- printk("btaudio: val=%d channels=%d\n",
- val,bta->channels);
+ if (debug)
+ printk(KERN_DEBUG
+ "btaudio: val=%d channels=%d\n",
+ val,bta->channels);
}
/* fall through */
case SOUND_PCM_READ_CHANNELS:
@@ -683,7 +718,7 @@
}
}
if (debug)
- printk("btaudio: fmt: bits=%d\n",bta->bits);
+ printk(KERN_DEBUG "btaudio: fmt: bits=%d\n",bta->bits);
return put_user((bta->bits==16) ? AFMT_S16_LE : AFMT_S8,
(int*)arg);
break;
@@ -736,10 +771,21 @@
return mask;
}
-static struct file_operations btaudio_dsp_fops = {
+static struct file_operations btaudio_digital_dsp_fops = {
owner: THIS_MODULE,
- llseek: btaudio_llseek,
- open: btaudio_dsp_open,
+ llseek: no_llseek,
+ open: btaudio_dsp_open_digital,
+ release: btaudio_dsp_release,
+ read: btaudio_dsp_read,
+ write: btaudio_dsp_write,
+ ioctl: btaudio_dsp_ioctl,
+ poll: btaudio_dsp_poll,
+};
+
+static struct file_operations btaudio_analog_dsp_fops = {
+ owner: THIS_MODULE,
+ llseek: no_llseek,
+ open: btaudio_dsp_open_analog,
release: btaudio_dsp_release,
read: btaudio_dsp_read,
write: btaudio_dsp_write,
@@ -769,7 +815,7 @@
if (irq_debug) {
int i;
- printk("btaudio: irq loop=%d risc=%x, bits:",
+ printk(KERN_DEBUG "btaudio: irq loop=%d risc=%x, bits:",
count, stat>>28);
for (i = 0; i < (sizeof(irq_name)/sizeof(char*)); i++) {
if (stat & (1 << i))
@@ -787,7 +833,7 @@
bta->dma_block = stat >> 28;
if (bta->read_count + 2*bta->block_bytes > bta->buf_size) {
stop_recording(bta);
- printk("btaudio: buffer overrun\n");
+ printk(KERN_INFO "btaudio: buffer overrun\n");
}
if (blocks > 0) {
bta->read_count += blocks * bta->block_bytes;
@@ -795,7 +841,8 @@
}
}
if (count > 10) {
- printk("btaudio: Oops - irq mask cleared\n");
+ printk(KERN_WARNING
+ "btaudio: Oops - irq mask cleared\n");
btwrite(0, REG_INT_MASK);
}
}
@@ -831,7 +878,7 @@
bta->source = 1;
bta->bits = 8;
bta->channels = 1;
- if (analog) {
+ if (bta->analog) {
bta->decimation = 15;
} else {
bta->decimation = 0;
@@ -843,7 +890,7 @@
pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &latency);
- printk("btaudio: Bt%x (rev %d) at %02x:%02x.%x, ",
+ printk(KERN_INFO "btaudio: Bt%x (rev %d) at %02x:%02x.%x, ",
pci_dev->device,revision,pci_dev->bus->number,
PCI_SLOT(pci_dev->devfn),PCI_FUNC(pci_dev->devfn));
printk("irq: %d, latency: %d, memory: 0x%lx\n",
@@ -852,31 +899,44 @@
/* init hw */
btwrite(0, REG_GPIO_DMA_CTL);
btwrite(0, REG_INT_MASK);
- btwrite(~(u32)0x0, REG_INT_STAT);
+ btwrite(~0x0UL, REG_INT_STAT);
pci_set_master(pci_dev);
if ((rc = request_irq(bta->irq, btaudio_irq, SA_SHIRQ|SA_INTERRUPT,
"btaudio",(void *)bta)) < 0) {
- printk("btaudio: can't request irq (rc=%d)\n",rc);
+ printk(KERN_WARNING
+ "btaudio: can't request irq (rc=%d)\n",rc);
goto fail1;
}
/* register devices */
- rc = bta->dsp_dev = register_sound_dsp(&btaudio_dsp_fops,dsp);
- if (rc < 0) {
- printk("btaudio: can't register dsp (rc=%d)\n",rc);
- goto fail2;
+ if (digital) {
+ rc = bta->dsp_digital =
+ register_sound_dsp(&btaudio_digital_dsp_fops,dsp1);
+ if (rc < 0) {
+ printk(KERN_WARNING
+ "btaudio: can't register digital dsp (rc=%d)\n",rc);
+ goto fail2;
+ }
}
if (analog) {
- rc = bta->mixer_dev = register_sound_mixer(&btaudio_mixer_fops,mixer);
+ rc = bta->dsp_analog =
+ register_sound_dsp(&btaudio_analog_dsp_fops,dsp2);
if (rc < 0) {
- printk("btaudio: can't register mixer (rc=%d)\n",rc);
+ printk(KERN_WARNING
+ "btaudio: can't register analog dsp (rc=%d)\n",rc);
goto fail3;
}
+ rc = bta->mixer_dev = register_sound_mixer(&btaudio_mixer_fops,mixer);
+ if (rc < 0) {
+ printk(KERN_WARNING
+ "btaudio: can't register mixer (rc=%d)\n",rc);
+ goto fail4;
+ }
}
if (debug)
- printk("btaudio: dsp: minor=%d, mixer: minor=%d\n",
- bta->dsp_dev,bta->mixer_dev);
+ printk(KERN_DEBUG "btaudio: minors: digital=%d, analog=%d, mixer=%d\n",
+ bta->dsp_digital, bta->dsp_analog, bta->mixer_dev);
/* hook into linked list */
bta->next = btaudios;
@@ -885,8 +945,11 @@
pci_set_drvdata(pci_dev,bta);
return 0;
+ fail4:
+ unregister_sound_dsp(bta->dsp_analog);
fail3:
- unregister_sound_dsp(bta->dsp_dev);
+ if (digital)
+ unregister_sound_dsp(bta->dsp_digital);
fail2:
free_irq(bta->irq,bta);
fail1:
@@ -904,12 +967,16 @@
/* turn off all DMA / IRQs */
btand(~15, REG_GPIO_DMA_CTL);
btwrite(0, REG_INT_MASK);
- btwrite(~(u32)0x0, REG_INT_STAT);
+ btwrite(~0x0UL, REG_INT_STAT);
/* unregister devices */
- unregister_sound_dsp(bta->dsp_dev);
- if (analog)
+ if (digital) {
+ unregister_sound_dsp(bta->dsp_digital);
+ }
+ if (analog) {
+ unregister_sound_dsp(bta->dsp_analog);
unregister_sound_mixer(bta->mixer_dev);
+ }
/* free resources */
free_buffer(bta);
@@ -950,8 +1017,10 @@
int btaudio_init_module(void)
{
- printk("btaudio: driver version 0.5 loaded [%s mode]\n",
- analog ? "audio A/D" : "digital audio");
+ printk(KERN_INFO "btaudio: driver version 0.6 loaded [%s%s%s]\n",
+ analog ? "analog" : "",
+ analog && digital ? "+" : "",
+ digital ? "digital" : "");
return pci_module_init(&btaudio_pci_driver);
}
@@ -964,15 +1033,19 @@
module_init(btaudio_init_module);
module_exit(btaudio_cleanup_module);
-MODULE_PARM(dsp,"i");
+MODULE_PARM(dsp1,"i");
+MODULE_PARM(dsp2,"i");
MODULE_PARM(mixer,"i");
MODULE_PARM(debug,"i");
MODULE_PARM(irq_debug,"i");
+MODULE_PARM(digital,"i");
MODULE_PARM(analog,"i");
+MODULE_PARM(rate,"i");
MODULE_DEVICE_TABLE(pci, btaudio_pci_tbl);
-MODULE_DESCRIPTION("btaudio - bt878 audio dma driver");
+MODULE_DESCRIPTION("bt878 audio dma driver");
MODULE_AUTHOR("Gerd Knorr");
+MODULE_LICENSE("GPL");
/*
* Local variables:
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)