patch-2.1.94 linux/drivers/sound/ad1848.c
Next file: linux/drivers/sound/ad1848_mixer.h
Previous file: linux/drivers/sound/README.C931
Back to the patch index
Back to the overall index
- Lines: 224
- Date:
Wed Apr 8 17:24:48 1998
- Orig file:
v2.1.93/linux/drivers/sound/ad1848.c
- Orig date:
Tue Mar 17 22:18:14 1998
diff -u --recursive --new-file v2.1.93/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c
@@ -12,16 +12,16 @@
*
* CS4232 is a PnP audio chip which contains a CS4231A (and SB, MPU).
* CS4232A is an improved version of CS4232.
- */
-
-/*
+ *
+ *
+ *
* 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)
* general sleep/wakeup clean up.
* Alan Cox : reformatted. Fixed SMP bugs. Moved to kernel alloc/free
@@ -84,7 +84,6 @@
int irq_ok;
mixer_ents *mix_devices;
int mixer_output_port;
- int c930_password_port;
} ad1848_info;
typedef struct ad1848_port_info
@@ -561,6 +560,12 @@
val = devc->mixer_output_port;
return put_user(val, (int *)arg);
}
+ if (cmd == SOUND_MIXER_PRIVATE2)
+ {
+ if (get_user(val, (int *)arg))
+ return -EFAULT;
+ return(ad1848_control(AD1848_MIXER_REROUTE, val));
+ }
if (((cmd >> 8) & 0xff) == 'M')
{
if (_SIOC_DIR(cmd) & _SIOC_WRITE)
@@ -1409,7 +1414,6 @@
devc->chip_name = devc->name = "AD1848";
devc->model = MD_1848; /* AD1848 or CS4248 */
devc->levels = NULL;
- devc->c930_password_port = 0;
devc->debug_flag = 0;
/*
@@ -1789,11 +1793,15 @@
if (request_irq(devc->irq, adintr, 0, devc->name, (void *)my_dev) < 0)
{
printk(KERN_WARNING "ad1848: Unable to allocate IRQ\n");
+ /* Don't free it either then.. */
+ devc->irq = 0;
}
if (devc->model != MD_1848 && devc->model != MD_C930)
{
+#ifndef __SMP__
int x;
unsigned char tmp = ad_read(devc, 16);
+#endif
devc->timer_ticks = 0;
@@ -1843,16 +1851,15 @@
{
audio_devs[my_dev]->mixer_dev = e;
}
- MOD_INC_USE_COUNT;
return my_dev;
}
-void ad1848_control(int cmd, int arg)
+int ad1848_control(int cmd, int arg)
{
ad1848_info *devc;
if (nr_ad1848_devs < 1)
- return;
+ return -ENODEV;
devc = &adev_info[nr_ad1848_devs - 1];
@@ -1860,7 +1867,7 @@
{
case AD1848_SET_XTAL: /* Change clock frequency of AD1845 (only ) */
if (devc->model != MD_1845)
- return;
+ return -EINVAL;
ad_enter_MCE(devc);
ad_write(devc, 29, (ad_read(devc, 29) & 0x1f) | (arg << 5));
ad_leave_MCE(devc);
@@ -1871,32 +1878,37 @@
int o = (arg >> 8) & 0xff;
int n = arg & 0xff;
+ if (o < 0 || o >= SOUND_MIXER_NRDEVICES)
+ return -EINVAL;
+
+ if (!(devc->supported_devices & (1 << o)) &&
+ !(devc->supported_rec_devices & (1 << o)))
+ return -EINVAL;
+
if (n == SOUND_MIXER_NONE)
{ /* Just hide this control */
ad1848_mixer_set(devc, o, 0); /* Shut up it */
devc->supported_devices &= ~(1 << o);
devc->supported_rec_devices &= ~(1 << o);
- return;
+ break;
}
- /* Make the mixer control identified by o to appear as n */
- if (o < 0 || o > SOUND_MIXER_NRDEVICES)
- return;
- if (n < 0 || n > SOUND_MIXER_NRDEVICES)
- return;
- if (!(devc->supported_devices & (1 << o)))
- return; /* Not supported */
+ /* Make the mixer control identified by o to appear as n */
+ if (n < 0 || n >= SOUND_MIXER_NRDEVICES)
+ return -EINVAL;
devc->mixer_reroute[n] = o; /* Rename the control */
- devc->supported_devices &= ~(1 << o);
- devc->supported_devices |= (1 << n);
+ if (devc->supported_devices & (1 << o))
+ devc->supported_devices |= (1 << n);
if (devc->supported_rec_devices & (1 << o))
devc->supported_rec_devices |= (1 << n);
+
+ devc->supported_devices &= ~(1 << o);
devc->supported_rec_devices &= ~(1 << o);
}
break;
}
- return;
+ return 0;
}
void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int share_dma)
@@ -1932,7 +1944,6 @@
}
else
printk(KERN_ERR "ad1848: Can't find device to be unloaded. Base=%x\n", io_base);
- MOD_DEC_USE_COUNT;
}
void adintr(int irq, void *dev_id, struct pt_regs *dummy)
@@ -1965,37 +1976,22 @@
save_flags(flags);
cli();
- alt_stat = 0;
-
- if (devc->c930_password_port)
- outb((0xe4), devc->c930_password_port); /* Password */
+ /* 0xe0e is C930 address port
+ * 0xe0f is C930 data port
+ */
outb(11, 0xe0e);
c930_stat = inb(0xe0f);
+ outb((~c930_stat), 0xe0f);
- if (c930_stat & 0x04)
- alt_stat |= 0x10; /* Playback intr */
- if (c930_stat & 0x08)
- alt_stat |= 0x20; /* Playback intr */
restore_flags(flags);
- } else if (devc->model != MD_1848)
- alt_stat = ad_read(devc, 24);
-
- /* Acknowledge the intr before proceeding */
- if (devc->model == MD_C930)
- { /* 82C930 has interrupt status register in MAD16 register MC11 */
- unsigned long flags;
-
- save_flags(flags);
- cli();
- if (devc->c930_password_port)
- outb((0xe4), devc->c930_password_port); /* Password */
- outb((11), 0xe0e);
- outb((~c930_stat), 0xe0f);
- restore_flags(flags);
+ alt_stat = (c930_stat << 2) & 0x30;
}
else if (devc->model != MD_1848)
+ {
+ alt_stat = ad_read(devc, 24);
ad_write(devc, 24, ad_read(devc, 24) & ~alt_stat); /* Selective ack */
+ }
if (devc->open_mode & OPEN_READ && devc->audio_mode & PCM_ENABLE_INPUT && alt_stat & 0x20)
{
@@ -2550,11 +2546,10 @@
struct address_info hw_config;
-
int init_module(void)
{
printk(KERN_INFO "ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996\n");
- if(io!=-1)
+ if(io != -1)
{
if(irq == -1 || dma == -1)
{
@@ -2581,12 +2576,5 @@
if(loaded)
unload_ms_sound(&hw_config);
}
-
-#else
-
-void export_ad1848_syms(void)
-{
-}
-
#endif
#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov