The patch also fixes a number of deadlocks from the cli/sti conversions
Please apply
Index: linux-2.5.52/sound/oss/ad1848.c
===================================================================
RCS file: /build/cvsroot/linux-2.5.52/sound/oss/ad1848.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 ad1848.c
--- linux-2.5.52/sound/oss/ad1848.c 16 Dec 2002 05:17:07 -0000 1.1.1.1
+++ linux-2.5.52/sound/oss/ad1848.c 16 Dec 2002 07:10:16 -0000
@@ -33,6 +33,7 @@
* Alan Cox : Added CS4236->4239 identification
* Daniel T. Cobra : Alernate config/mixer for later chips
* Alan Cox : Merged chip idents and config code
+ * Zwane Mwaikambo : Converted to 2.5 PnP API
*
* TODO
* APM save restore assist code on IBM thinkpad
@@ -47,7 +48,6 @@
#include <linux/module.h>
#include <linux/stddef.h>
#include <linux/pm.h>
-#include <linux/isapnp.h>
#include <linux/pnp.h>
#include <linux/spinlock.h>
@@ -107,6 +107,9 @@
/* Power management */
struct pm_dev *pmdev;
+#ifdef CONFIG_PNP
+ struct pnp_dev *pnp_dev;
+#endif
} ad1848_info;
typedef struct ad1848_port_info
@@ -180,16 +183,11 @@
#ifdef CONFIG_PNP
static int isapnp = 1;
-static int isapnpjump = 0;
-static int reverse = 0;
-
static int audio_activated = 0;
#else
static int isapnp = 0;
#endif
-
-
static int ad1848_open(int dev, int mode);
static void ad1848_close(int dev);
static void ad1848_output_block(int dev, unsigned long buf, int count, int intrflag);
@@ -207,17 +205,15 @@
static void ad1848_tmr_reprogram(int dev);
#endif
+/* has to be called with devc->lock held */
static int ad_read(ad1848_info * devc, int reg)
{
- unsigned long flags;
int x;
int timeout = 900000;
while (timeout > 0 && inb(devc->base) == 0x80) /*Are we initializing */
timeout--;
- spin_lock_irqsave(&devc->lock,flags);
-
if(reg < 32)
{
outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
@@ -233,21 +229,18 @@
outb(((unsigned char) (xra & 0xff)), io_Indexed_Data(devc));
x = inb(io_Indexed_Data(devc));
}
- spin_unlock_irqrestore(&devc->lock,flags);
return x;
}
+/* has to be called with the devc->lock held */
static void ad_write(ad1848_info * devc, int reg, int data)
{
- unsigned long flags;
int timeout = 900000;
while (timeout > 0 && inb(devc->base) == 0x80) /* Are we initializing */
timeout--;
- spin_lock_irqsave(&devc->lock,flags);
-
if(reg < 32)
{
outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
@@ -263,7 +256,6 @@
outb(((unsigned char) (xra & 0xff)), io_Indexed_Data(devc));
outb((unsigned char) (data & 0xff), io_Indexed_Data(devc));
}
- spin_unlock_irqrestore(&devc->lock,flags);
}
static void wait_for_calibration(ad1848_info * devc)
@@ -307,10 +299,7 @@
*/
for (i = 6; i < 8; i++)
- {
prev = devc->saved_regs[i] = ad_read(devc, i);
- }
-
}
static void ad_unmute(ad1848_info * devc)
@@ -319,37 +308,28 @@
static void ad_enter_MCE(ad1848_info * devc)
{
- unsigned long flags;
int timeout = 1000;
unsigned short prev;
while (timeout > 0 && inb(devc->base) == 0x80) /*Are we initializing */
timeout--;
- spin_lock_irqsave(&devc->lock,flags);
-
devc->MCE_bit = 0x40;
prev = inb(io_Index_Addr(devc));
if (prev & 0x40)
- {
- spin_unlock_irqrestore(&devc->lock,flags);
return;
- }
+
outb((devc->MCE_bit), io_Index_Addr(devc));
- spin_unlock_irqrestore(&devc->lock,flags);
}
static void ad_leave_MCE(ad1848_info * devc)
{
- unsigned long flags;
unsigned char prev, acal;
int timeout = 1000;
while (timeout > 0 && inb(devc->base) == 0x80) /*Are we initializing */
timeout--;
- spin_lock_irqsave(&devc->lock,flags);
-
acal = ad_read(devc, 9);
devc->MCE_bit = 0x00;
@@ -357,14 +337,11 @@
outb((0x00), io_Index_Addr(devc)); /* Clear the MCE bit */
if ((prev & 0x40) == 0) /* Not in MCE mode */
- {
- spin_unlock_irqrestore(&devc->lock,flags);
return;
- }
+
outb((0x00), io_Index_Addr(devc)); /* Clear the MCE bit */
if (acal & 0x08) /* Auto calibration is enabled */
wait_for_calibration(devc);
- spin_unlock_irqrestore(&devc->lock,flags);
}
static int ad1848_set_recmask(ad1848_info * devc, int mask)
@@ -375,12 +352,9 @@
mask &= devc->supported_rec_devices;
/* Rename the mixer bits if necessary */
- for (i = 0; i < 32; i++)
- {
- if (devc->mixer_reroute[i] != i)
- {
- if (mask & (1 << i))
- {
+ for (i = 0; i < 32; i++) {
+ if (devc->mixer_reroute[i] != i) {
+ if (mask & (1 << i)) {
mask &= ~(1 << i);
mask |= (1 << devc->mixer_reroute[i]);
}
@@ -462,12 +436,9 @@
}
/* Rename the mixer bits back if necessary */
- for (i = 0; i < 32; i++)
- {
- if (devc->mixer_reroute[i] != i)
- {
- if (mask & (1 << devc->mixer_reroute[i]))
- {
+ for (i = 0; i < 32; i++) {
+ if (devc->mixer_reroute[i] != i) {
+ if (mask & (1 << devc->mixer_reroute[i])) {
mask &= ~(1 << devc->mixer_reroute[i]);
mask |= (1 << i);
}
@@ -494,13 +465,11 @@
mask = (1 << devc->mix_devices[dev][chn].nbits) - 1;
shift = devc->mix_devices[dev][chn].bitpos;
- if (devc->mix_devices[dev][chn].mutepos == 8)
- { /* if there is no mute bit */
+ if (devc->mix_devices[dev][chn].mutepos == 8) {
+ /* if there is no mute bit */
mute = 0; /* No mute bit; do nothing special */
mutemask = ~0; /* No mute bit; do nothing special */
- }
- else
- {
+ } else {
mute = (set_mute_bit << devc->mix_devices[dev][chn].mutepos);
mutemask = ~(1 << devc->mix_devices[dev][chn].mutepos);
}
@@ -600,9 +569,10 @@
{
int i;
char name[32];
+ unsigned long flags;
+ spin_lock_irqsave(&devc->lock, flags);
devc->mix_devices = &(ad1848_mix_devices[0]);
-
sprintf(name, "%s_%d", devc->chip_name, nr_ad1848_devs);
for (i = 0; i < 32; i++)
@@ -656,12 +626,11 @@
devc->levels = load_mixer_volumes(name, default_mixer_levels, 1);
- for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
- {
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
if (devc->supported_devices & (1 << i))
ad1848_mixer_set(devc, i, devc->levels[i]);
}
-
+
ad1848_set_recmask(devc, SOUND_MASK_MIC);
devc->mixer_output_port = devc->levels[31] | AUDIO_HEADPHONE | AUDIO_LINE_OUT;
@@ -679,13 +648,15 @@
/* Enable surround mode and SB16 mixer */
ad_write(devc, 16, 0x60);
}
+ spin_unlock_irqrestore(&devc->lock, flags);
}
static int ad1848_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
{
ad1848_info *devc = mixer_devs[dev]->devc;
+ unsigned long flags;
int val;
-
+
if (cmd == SOUND_MIXER_PRIVATE1)
{
if (get_user(val, (int *)arg))
@@ -697,10 +668,12 @@
devc->mixer_output_port = val;
val |= AUDIO_HEADPHONE | AUDIO_LINE_OUT; /* Always on */
devc->mixer_output_port = val;
+ spin_lock_irqsave(&devc->lock, flags);
if (val & AUDIO_SPEAKER)
ad_write(devc, 26, ad_read(devc, 26) & ~0x40); /* Unmute mono out */
else
ad_write(devc, 26, ad_read(devc, 26) | 0x40); /* Mute mono out */
+ spin_unlock_irqrestore(&devc->lock, flags);
}
val = devc->mixer_output_port;
return put_user(val, (int *)arg);
@@ -720,13 +693,17 @@
case SOUND_MIXER_RECSRC:
if (get_user(val, (int *)arg))
return -EFAULT;
+ spin_lock_irqsave(&devc->lock, flags);
val = ad1848_set_recmask(devc, val);
+ spin_unlock_irqrestore(&devc->lock, flags);
break;
default:
if (get_user(val, (int *)arg))
return -EFAULT;
+ spin_lock_irqsave(&devc->lock, flags);
val = ad1848_mixer_set(devc, cmd & 0xff, val);
+ spin_unlock_irqrestore(&devc->lock, flags);
break;
}
return put_user(val, (int *)arg);
@@ -977,7 +954,7 @@
{
ad1848_info *devc;
ad1848_port_info *portc;
- unsigned long flags;
+ unsigned long flags;
if (dev < 0 || dev >= num_audiodevs)
return -ENXIO;
@@ -985,18 +962,16 @@
devc = (ad1848_info *) audio_devs[dev]->devc;
portc = (ad1848_port_info *) audio_devs[dev]->portc;
- spin_lock_irqsave(&devc->lock,flags);
- if (portc->open_mode || (devc->open_mode & mode))
- {
- spin_unlock_irqrestore(&devc->lock,flags);
+ spin_lock_irqsave(&devc->lock, flags);
+ if (portc->open_mode || (devc->open_mode & mode)) {
+ spin_unlock_irqrestore(&devc->lock, flags);
return -EBUSY;
}
devc->dual_dma = 0;
if (audio_devs[dev]->flags & DMA_DUPLEX)
- {
devc->dual_dma = 1;
- }
+
devc->intr_active = 0;
devc->audio_mode = 0;
devc->open_mode |= mode;
@@ -1007,10 +982,10 @@
devc->record_dev = dev;
if (mode & OPEN_WRITE)
devc->playback_dev = dev;
- spin_unlock_irqrestore(&devc->lock,flags);
/*
* Mute output until the playback really starts. This decreases clicking (hope so).
*/
+ spin_unlock_irqrestore(&devc->lock, flags);
ad_mute(devc);
return 0;
@@ -1018,23 +993,24 @@
static void ad1848_close(int dev)
{
- unsigned long flags;
ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc;
+ unsigned long flags;
DEB(printk("ad1848_close(void)\n"));
-
- spin_lock_irqsave(&devc->lock,flags);
-
+
+ spin_lock_irqsave(&devc->lock, flags);
devc->intr_active = 0;
+ spin_unlock_irqrestore(&devc->lock, flags);
+
ad1848_halt(dev);
+ spin_lock_irqsave(&devc->lock, flags);
devc->audio_mode = 0;
devc->open_mode &= ~portc->open_mode;
portc->open_mode = 0;
-
+ spin_unlock_irqrestore(&devc->lock, flags);
ad_unmute(devc);
- spin_unlock_irqrestore(&devc->lock,flags);
}
static void ad1848_output_block(int dev, unsigned long buf, int count, int intrflag)
@@ -1111,13 +1087,10 @@
}
spin_lock_irqsave(&devc->lock,flags);
- if (devc->model == MD_1848)
- {
+ if (devc->model == MD_1848) {
ad_write(devc, 15, (unsigned char) (cnt & 0xff));
ad_write(devc, 14, (unsigned char) ((cnt >> 8) & 0xff));
- }
- else
- {
+ } else {
ad_write(devc, 31, (unsigned char) (cnt & 0xff));
ad_write(devc, 30, (unsigned char) ((cnt >> 8) & 0xff));
}
@@ -1184,15 +1157,13 @@
ad_leave_MCE(devc); /*
* Starts the calibration process.
*/
- spin_unlock_irqrestore(&devc->lock,flags);
devc->xfer_count = 0;
+ spin_unlock_irqrestore(&devc->lock,flags);
#ifndef EXCLUDE_TIMERS
if (dev == timer_installed && devc->timer_running)
if ((fs & 0x01) != (old_fs & 0x01))
- {
ad1848_tmr_reprogram(dev);
- }
#endif
ad1848_halt_output(dev);
return 0;
@@ -1336,9 +1307,8 @@
if (!(ad_read(devc, 9) & 0x02))
return; /* Capture not enabled */
- spin_lock_irqsave(&devc->lock,flags);
-
ad_mute(devc);
+ spin_lock_irqsave(&devc->lock,flags);
{
int tmout;
@@ -1372,9 +1342,9 @@
if (!(ad_read(devc, 9) & 0x01))
return; /* Playback not enabled */
+ ad_mute(devc);
spin_lock_irqsave(&devc->lock,flags);
- ad_mute(devc);
{
int tmout;
@@ -1404,35 +1374,28 @@
{
ad1848_info *devc = (ad1848_info *) audio_devs[dev]->devc;
ad1848_port_info *portc = (ad1848_port_info *) audio_devs[dev]->portc;
- unsigned long flags;
unsigned char tmp, old;
- spin_lock_irqsave(&devc->lock,flags);
state &= devc->audio_mode;
-
tmp = old = ad_read(devc, 9);
- if (portc->open_mode & OPEN_READ)
- {
+ if (portc->open_mode & OPEN_READ) {
if (state & PCM_ENABLE_INPUT)
tmp |= 0x02;
else
tmp &= ~0x02;
}
- if (portc->open_mode & OPEN_WRITE)
- {
+ if (portc->open_mode & OPEN_WRITE) {
if (state & PCM_ENABLE_OUTPUT)
tmp |= 0x01;
else
tmp &= ~0x01;
}
/* ad_mute(devc); */
- if (tmp != old)
- {
+ if (tmp != old) {
ad_write(devc, 9, tmp);
ad_unmute(devc);
}
- spin_unlock_irqrestore(&devc->lock,flags);
}
static void ad1848_init_hw(ad1848_info * devc)
@@ -1580,11 +1543,7 @@
printk(KERN_ERR "ad1848 - Too many audio devices\n");
return 0;
}
- if (check_region(io_base, 4))
- {
- printk(KERN_ERR "ad1848.c: Port %x not free.\n", io_base);
- return 0;
- }
+
devc->base = io_base;
devc->irq_ok = 0;
devc->timer_running = 0;
@@ -1736,15 +1695,13 @@
*ad_flags = 0;
tmp1 = ad_read(devc, 12);
- if (tmp1 & 0x80)
- {
+ if (tmp1 & 0x80) {
if (ad_flags)
*ad_flags |= AD_F_CS4248;
devc->chip_name = "CS4248"; /* Our best knowledge just now */
}
- if (optiC930 || (tmp1 & 0xc0) == (0x80 | 0x40))
- {
+ if (optiC930 || (tmp1 & 0xc0) == (0x80 | 0x40)) {
/*
* CS4231 detected - is it?
*
@@ -1935,8 +1892,7 @@
}
DDB(printk("ad1848_detect() - step L\n"));
- if (ad_flags)
- {
+ if (ad_flags) {
if (devc->model != MD_1848)
*ad_flags |= AD_F_CS4231;
}
@@ -1945,7 +1901,6 @@
if (devc->model == MD_1848 && ad1847_flag)
devc->chip_name = "AD1847";
-
if (sscape_flag == 1)
devc->model = MD_1845_SSCAPE;
@@ -1969,7 +1924,6 @@
ad1848_port_info *portc = NULL;
- spin_lock_init(&devc->lock);
devc->irq = (irq > 0) ? irq : 0;
devc->open_mode = 0;
devc->timer_ticks = 0;
@@ -2039,17 +1993,14 @@
ad1848_init_hw(devc);
- if (irq > 0)
- {
+ if (irq > 0) {
devc->dev_no = my_dev;
- if (request_irq(devc->irq, adintr, 0, devc->name, (void *)my_dev) < 0)
- {
+ 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 (capabilities[devc->model].flags & CAP_F_TIMER)
- {
+ if (capabilities[devc->model].flags & CAP_F_TIMER) {
#ifndef CONFIG_SMP
int x;
unsigned char tmp = ad_read(devc, 16);
@@ -2066,8 +2017,7 @@
if (devc->timer_ticks == 0)
printk(KERN_WARNING "ad1848: Interrupt test failed (IRQ%d)\n", irq);
- else
- {
+ else {
DDB(printk("Interrupt test OK\n"));
devc->irq_ok = 1;
}
@@ -2086,8 +2036,7 @@
ad1848_tmr_install(my_dev);
#endif
- if (!share_dma)
- {
+ if (!share_dma) {
if (sound_alloc_dma(dma_playback, devc->name))
printk(KERN_WARNING "ad1848.c: Can't allocate DMA%d\n", dma_playback);
@@ -2100,8 +2049,7 @@
dev_name,
&ad1848_mixer_operations,
sizeof(struct mixer_operations),
- devc)) >= 0)
- {
+ devc)) >= 0) {
audio_devs[my_dev]->mixer_dev = e;
if (owner)
mixer_devs[e]->owner = owner;
@@ -2112,6 +2060,7 @@
int ad1848_control(int cmd, int arg)
{
ad1848_info *devc;
+ unsigned long flags;
if (nr_ad1848_devs < 1)
return -ENODEV;
@@ -2123,9 +2072,11 @@
case AD1848_SET_XTAL: /* Change clock frequency of AD1845 (only ) */
if (devc->model != MD_1845 || devc->model != MD_1845_SSCAPE)
return -EINVAL;
+ spin_lock_irqsave(&devc->lock, flags);
ad_enter_MCE(devc);
ad_write(devc, 29, (ad_read(devc, 29) & 0x1f) | (arg << 5));
ad_leave_MCE(devc);
+ spin_unlock_irqrestore(&devc->lock, flags);
break;
case AD1848_MIXER_REROUTE:
@@ -2140,11 +2091,13 @@
!(devc->supported_rec_devices & (1 << o)))
return -EINVAL;
- if (n == SOUND_MIXER_NONE)
- { /* Just hide this control */
+ if (n == SOUND_MIXER_NONE) {
+ /* Just hide this control */
+ spin_lock_irqsave(&devc->lock, flags);
ad1848_mixer_set(devc, o, 0); /* Shut up it */
devc->supported_devices &= ~(1 << o);
devc->supported_rec_devices &= ~(1 << o);
+ spin_unlock_irqrestore(&devc->lock, flags);
break;
}
@@ -2171,23 +2124,19 @@
int i, mixer, dev = 0;
ad1848_info *devc = NULL;
- for (i = 0; devc == NULL && i < nr_ad1848_devs; i++)
- {
- if (adev_info[i].base == io_base)
- {
+ for (i = 0; devc == NULL && i < nr_ad1848_devs; i++) {
+ if (adev_info[i].base == io_base) {
devc = &adev_info[i];
dev = devc->dev_no;
}
}
- if (devc != NULL)
- {
+ if (devc != NULL) {
if(audio_devs[dev]->portc!=NULL)
kfree(audio_devs[dev]->portc);
release_region(devc->base, 4);
- if (!share_dma)
- {
+ if (!share_dma) {
if (devc->irq > 0) /* There is no point in freeing irq, if it wasn't allocated */
free_irq(devc->irq, (void *)devc->dev_no);
@@ -2198,12 +2147,14 @@
}
mixer = audio_devs[devc->dev_no]->mixer_dev;
- if(mixer>=0)
+ if (mixer>=0)
sound_unload_mixerdev(mixer);
if (devc->pmdev)
pm_unregister(devc->pmdev);
-
+#ifdef CONFIG_PNP
+ put_device(&devc->pnp_dev->dev);
+#endif
nr_ad1848_devs--;
for ( ; i < nr_ad1848_devs ; i++)
adev_info[i] = adev_info[i+1];
@@ -2223,6 +2174,7 @@
dev = (int)dev_id;
devc = (ad1848_info *) audio_devs[dev]->devc;
+ spin_lock(&devc->lock);
interrupt_again: /* Jump back here if int status doesn't reset */
@@ -2237,18 +2189,12 @@
{
if (devc->model == MD_C930)
{ /* 82C930 has interrupt status register in MAD16 register MC11 */
-
- spin_lock(&devc->lock);
-
/* 0xe0e is C930 address port
* 0xe0f is C930 data port
*/
outb(11, 0xe0e);
c930_stat = inb(0xe0f);
outb((~c930_stat), 0xe0f);
-
- spin_unlock(&devc->lock);
-
alt_stat = (c930_stat << 2) & 0x30;
}
else if (devc->model != MD_1848)
@@ -2285,6 +2231,7 @@
{
goto interrupt_again;
}
+ spin_unlock(&devc->lock);
}
/*
@@ -2524,11 +2471,6 @@
DDB(printk("Entered probe_ms_sound(%x, %d)\n", hw_config->io_base, hw_config->card_subtype));
- if (check_region(hw_config->io_base, 8))
- {
- printk(KERN_ERR "MSS: I/O port conflict\n");
- return 0;
- }
if (hw_config->card_subtype == 1) /* Has no IRQ/DMA registers */
{
/* check_opl3(0x388, hw_config); */
@@ -2723,8 +2665,6 @@
unsigned long xtal_nsecs; /* nanoseconds per xtal oscillator tick */
unsigned long divider;
- spin_lock_irqsave(&devc->lock,flags);
-
/*
* Length of the timer interval (in nanoseconds) depends on the
* selected crystal oscillator. Check this from bit 0x01 of I8.
@@ -2751,6 +2691,7 @@
if (divider > 65535) /* Overflow check */
divider = 65535;
+ spin_lock_irqsave(&devc->lock,flags);
ad_write(devc, 21, (divider >> 8) & 0xff); /* Set upper bits */
ad_write(devc, 20, divider & 0xff); /* Set lower bits */
ad_write(devc, 16, ad_read(devc, 16) | 0x40); /* Start the timer */
@@ -2819,13 +2760,8 @@
static int ad1848_suspend(ad1848_info *devc)
{
- unsigned long flags;
-
- spin_lock_irqsave(&devc->lock,flags);
-
ad_mute(devc);
- spin_unlock_irqrestore(&devc->lock,flags);
return 0;
}
@@ -2833,9 +2769,8 @@
{
unsigned long flags;
int mixer_levels[32], i;
-
- spin_lock_irqsave(&devc->lock,flags);
+ local_irq_save(flags);
/* Thinkpad is a bit more of PITA than normal. The BIOS tends to
restore it in a different config to the one we use. Need to
fix this somehow */
@@ -2860,7 +2795,7 @@
bits = interrupt_bits[devc->irq];
if (bits == -1) {
printk(KERN_ERR "MSS: Bad IRQ %d\n", devc->irq);
- spin_unlock_irqrestore(&devc->lock,flags);
+ local_irq_restore(flags);
return -1;
}
@@ -2875,7 +2810,7 @@
outb((bits | dma_bits[devc->dma1] | dma2_bit), config_port);
}
- spin_unlock_irqrestore(&devc->lock,flags);
+ local_irq_restore(flags);
return 0;
}
@@ -2924,13 +2859,7 @@
#ifdef CONFIG_PNP
MODULE_PARM(isapnp, "i");
-MODULE_PARM(isapnpjump, "i");
-MODULE_PARM(reverse, "i");
MODULE_PARM_DESC(isapnp, "When set to 0, Plug & Play support will be disabled");
-MODULE_PARM_DESC(isapnpjump, "Jumps to a specific slot in the driver's PnP table. Use the source, Luke.");
-MODULE_PARM_DESC(reverse, "When set to 1, will reverse ISAPnP search order");
-
-struct pnp_dev *ad1848_dev = NULL;
/* Please add new entries at the end of the table */
static struct {
@@ -2952,10 +2881,12 @@
ISAPNP_ANY_ID, ISAPNP_ANY_ID,
ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0100),
0, 0, 0, 1, 0},
- {"OPL3-SA2 WSS mode",
+ /* This is handled by the opl3sa2 driver
+ {"OPL3-SA2 WSS mode",
ISAPNP_ANY_ID, ISAPNP_ANY_ID,
ISAPNP_VENDOR('Y','M','H'), ISAPNP_FUNCTION(0x0021),
1, 0, 0, 1, 1},
+ */
{"Advanced Gravis InterWave Audio",
ISAPNP_VENDOR('G','R','V'), ISAPNP_DEVICE(0x0001),
ISAPNP_VENDOR('G','R','V'), ISAPNP_FUNCTION(0x0000),
@@ -2963,137 +2894,90 @@
{0}
};
-static struct isapnp_device_id id_table[] __devinitdata = {
- { ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001),
- ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
- ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0000), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
- ISAPNP_VENDOR('C','S','C'), ISAPNP_FUNCTION(0x0100), 0 },
- { ISAPNP_ANY_ID, ISAPNP_ANY_ID,
- ISAPNP_VENDOR('Y','M','H'), ISAPNP_FUNCTION(0x0021), 0 },
- { ISAPNP_VENDOR('G','R','V'), ISAPNP_DEVICE(0x0001),
- ISAPNP_VENDOR('G','R','V'), ISAPNP_FUNCTION(0x0000), 0 },
- {0}
+static const struct pnp_device_id ad1848_id_table[] __devinitdata = {
+ {.id = "CMI0001" },
+ {.id = "@@@0001" },
+ {.id = "CSC0000" },
+ {.id = "CSC0100" },
+ /* {.id = "YMH0021" }, */
+ {.id = "GRV0001" },
+ {.id = "GRV0000" },
+ {.id = ""}
};
-MODULE_DEVICE_TABLE(isapnp, id_table);
+MODULE_DEVICE_TABLE(pnp, ad1848_id_table);
-static struct pnp_dev *activate_dev(char *devname, char *resname, struct pnp_dev *dev)
+static int ad1848_isapnp_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *dev_id)
{
- int err;
+ ad1848_info *priv;
+ int mss_io_index, irq_index, dma_index, dma2_index;
- /* Device already active? Let's use it */
- if(dev->active)
- return(dev);
+ if (nr_ad1848_devs >= MAX_AUDIO_DEV)
+ return -ENOSPC;
- if((err = pnp_activate_dev(dev)) < 0) {
- printk(KERN_ERR "ad1848: %s %s config failed (out of resources?)[%d]\n", devname, resname, err);
+ priv = &adev_info[nr_ad1848_devs];
+ priv->pnp_dev = pnp_dev;
+ pnp_set_drvdata(pnp_dev, priv);
+ get_device(&pnp_dev->dev);
+
+ mss_io_index = ad1848_isapnp_list[nr_ad1848_devs].mss_io;
+ irq_index = ad1848_isapnp_list[nr_ad1848_devs].irq;
+ dma_index = ad1848_isapnp_list[nr_ad1848_devs].dma;
+ dma2_index = ad1848_isapnp_list[nr_ad1848_devs].dma2;
+
+ cfg.io_base = pnp_dev->resource[mss_io_index].start;
+ cfg.irq = pnp_dev->irq_resource[irq_index].start;
+ cfg.dma = pnp_dev->dma_resource[dma_index].start;
- pnp_disable_dev(dev);
+ if (dma2_index != -1)
+ cfg.dma2 = pnp_dev->dma_resource[dma2_index].start;
+ else
+ cfg.dma2 = -1;
- return(NULL);
- }
+ printk(KERN_NOTICE "ad1848: ISAPnP reports '%s' at i/o %#x, irq %d, dma %d, %d\n",
+ pnp_dev->name, cfg.io_base, cfg.irq, cfg.dma, cfg.dma2);
audio_activated = 1;
- return(dev);
-}
-
-static struct pnp_dev *ad1848_init_generic(struct pnp_card *bus, struct address_info *hw_config, int slot)
-{
-
- /* Configure Audio device */
- if((ad1848_dev = pnp_find_dev(bus, ad1848_isapnp_list[slot].vendor, ad1848_isapnp_list[slot].function, NULL)))
- {
- if((ad1848_dev = activate_dev(ad1848_isapnp_list[slot].name, "ad1848", ad1848_dev)))
- {
- get_device(&ad1848_dev->dev);
- hw_config->io_base = ad1848_dev->resource[ad1848_isapnp_list[slot].mss_io].start;
- hw_config->irq = ad1848_dev->irq_resource[ad1848_isapnp_list[slot].irq].start;
- hw_config->dma = ad1848_dev->dma_resource[ad1848_isapnp_list[slot].dma].start;
- if(ad1848_isapnp_list[slot].dma2 != -1)
- hw_config->dma2 = ad1848_dev->dma_resource[ad1848_isapnp_list[slot].dma2].start;
- else
- hw_config->dma2 = -1;
- hw_config->card_subtype = ad1848_isapnp_list[slot].type;
- } else
- return(NULL);
- } else
- return(NULL);
-
- return(ad1848_dev);
-}
-static int __init ad1848_isapnp_init(struct address_info *hw_config, struct pnp_card *bus, int slot)
-{
- char *busname = bus->name[0] ? bus->name : ad1848_isapnp_list[slot].name;
-
- /* Initialize this baby. */
-
- if(ad1848_init_generic(bus, hw_config, slot)) {
- /* We got it. */
-
- printk(KERN_NOTICE "ad1848: ISAPnP reports '%s' at i/o %#x, irq %d, dma %d, %d\n",
- busname,
- hw_config->io_base, hw_config->irq, hw_config->dma,
- hw_config->dma2);
- return 1;
- }
return 0;
}
-static int __init ad1848_isapnp_probe(struct address_info *hw_config)
+static void ad1848_isapnp_remove(struct pnp_dev *pnp_dev)
{
- static int first = 1;
- int i;
-
- /* Count entries in sb_isapnp_list */
- for (i = 0; ad1848_isapnp_list[i].card_vendor != 0; i++);
- i--;
-
- /* Check and adjust isapnpjump */
- if( isapnpjump < 0 || isapnpjump > i) {
- isapnpjump = reverse ? i : 0;
- printk(KERN_ERR "ad1848: Valid range for isapnpjump is 0-%d. Adjusted to %d.\n", i, isapnpjump);
- }
-
- if(!first || !reverse)
- i = isapnpjump;
- first = 0;
- while(ad1848_isapnp_list[i].card_vendor != 0) {
- static struct pnp_card *bus = NULL;
-
- while ((bus = pnp_find_card(
- ad1848_isapnp_list[i].card_vendor,
- ad1848_isapnp_list[i].card_device,
- bus))) {
-
- if(ad1848_isapnp_init(hw_config, bus, i)) {
- isapnpjump = i; /* start next search from here */
- return 0;
- }
- }
- i += reverse ? -1 : 1;
- }
-
- return -ENODEV;
+ put_device(&pnp_dev->dev);
+ /* pnp_disable_dev(pnp_dev); does this belong here? -Zwane */
+ nr_ad1848_devs--;
}
+
+static struct pnp_driver ad1848_driver = {
+ .name = "ad1848",
+ .id_table = ad1848_id_table,
+ .probe = ad1848_isapnp_probe,
+ .remove = ad1848_isapnp_remove,
+};
#endif
static int __init init_ad1848(void)
{
+ int i;
printk(KERN_INFO "ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996\n");
+ for (i = 0; i < MAX_AUDIO_DEV; i++)
+ spin_lock_init(&adev_info[i].lock);
+
#ifdef CONFIG_PNP
- if(isapnp && (ad1848_isapnp_probe(&cfg) < 0) ) {
- printk(KERN_NOTICE "ad1848: No ISAPnP cards found, trying standard ones...\n");
- isapnp = 0;
+ if (isapnp) { /* FIXME I don't think this override can work anymore... -Zwane */
+ /* On return our settings are in cfg */
+ pnp_register_driver(&ad1848_driver);
+ if (audio_activated == 0) {
+ printk(KERN_NOTICE "ad1848: No ISAPnP cards found, trying standard ones...\n");
+ isapnp = 0;
+ }
}
#endif
- if(io != -1) {
- if( isapnp == 0 )
- {
+ if (io != -1) {
+ if ( isapnp == 0 ) {
if(irq == -1 || dma == -1) {
printk(KERN_WARNING "ad1848: must give I/O , IRQ and DMA.\n");
return -EINVAL;
@@ -3106,7 +2990,7 @@
cfg.card_subtype = type;
}
- if(!probe_ms_sound(&cfg))
+ if (!probe_ms_sound(&cfg))
return -ENODEV;
attach_ms_sound(&cfg, THIS_MODULE);
loaded = 1;
@@ -3116,15 +3000,11 @@
static void __exit cleanup_ad1848(void)
{
- if(loaded)
+ if (loaded)
unload_ms_sound(&cfg);
#ifdef CONFIG_PNP
- if(ad1848_dev){
- if(audio_activated)
- pnp_disable_dev(ad1848_dev);
- put_device(&ad1848_dev->dev);
- }
+ pnp_unregister_driver(&ad1848_driver);
#endif
}
Index: linux-2.5.52/sound/oss/Makefile
===================================================================
RCS file: /build/cvsroot/linux-2.5.52/sound/oss/Makefile,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 Makefile
--- linux-2.5.52/sound/oss/Makefile 16 Dec 2002 05:17:05 -0000 1.1.1.1
+++ linux-2.5.52/sound/oss/Makefile 16 Dec 2002 05:52:23 -0000
@@ -13,6 +13,7 @@
# Each configuration option enables a list of files.
obj-$(CONFIG_SOUND_OSS) += sound.o
+obj-$(CONFIG_SOUND_MSS) += ad1848.o
obj-$(CONFIG_SOUND_CS4232) += cs4232.o ad1848.o
# Please leave it as is, cause the link order is significant !
@@ -24,7 +25,6 @@
obj-$(CONFIG_SOUND_SSCAPE) += sscape.o ad1848.o mpu401.o
obj-$(CONFIG_SOUND_MAD16) += mad16.o ad1848.o sb_lib.o uart401.o
obj-$(CONFIG_SOUND_CS4232) += cs4232.o uart401.o
-obj-$(CONFIG_SOUND_MSS) += ad1848.o
obj-$(CONFIG_SOUND_OPL3SA2) += opl3sa2.o ad1848.o mpu401.o
obj-$(CONFIG_SOUND_PAS) += pas2.o sb.o sb_lib.o uart401.o
obj-$(CONFIG_SOUND_SB) += sb.o sb_lib.o uart401.o
-- function.linuxpower.ca - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/