patch-2.3.22 linux/drivers/sound/maestro.c
Next file: linux/drivers/usb/Makefile
Previous file: linux/drivers/sound/dmasound.c
Back to the patch index
Back to the overall index
- Lines: 1417
- Date:
Wed Oct 13 10:32:35 1999
- Orig file:
v2.3.21/linux/drivers/sound/maestro.c
- Orig date:
Mon Oct 4 15:49:30 1999
diff -u --recursive --new-file v2.3.21/linux/drivers/sound/maestro.c linux/drivers/sound/maestro.c
@@ -40,14 +40,14 @@
* channels. They can take data from a number of sources and perform
* basic encodings of the data. The wavecache is a storehouse for
* PCM data. Typically it deals with PCI and interracts with the
- * APUs. The ASP is a wacky DSP like device that ESS is loathe
+ * APUs. The ASP is a wacky DSP like device that ESS is loth
* to release docs on. Thankfully it isn't required on the Maestro
* until you start doing insane things like FM emulation and surround
* encoding. The codecs are almost always AC-97 compliant codecs,
* but it appears that early Maestros may have had PT101 (an ESS
* part?) wired to them. The only real difference in the Maestro
* families is external goop like docking capability, memory for
- * the ASP, and trivial initialization differences.
+ * the ASP, and initialization differences.
*
* Driver Operation
*
@@ -70,7 +70,7 @@
* the client and complicates the buffer maths tremendously. Ick.
*
* This also pollutes the recording paths as well. We have to use
- * 2 l/r incoming APUs that are fixed at 16bit/48khz. We then pipe
+ * 2 L/R incoming APUs that are fixed at 16bit/48khz. We then pipe
* these through 2 rate converion apus that mix them down to the
* requested frequency and write them to memory through the wavecache.
* We also apparently need a 512byte region thats used as temp space
@@ -79,21 +79,39 @@
* The wavecache makes our life even more fun. First off, it can
* only address the first 28 bits of PCI address space, making it
* useless on quite a few architectures. Secondly, its insane.
- * It can only fetch from 4 regions of PCI space, each 2 meg in length
- * and 4k aligned. It then uses high bits of the address in the APU
- * to decide which buffer to use, but as far as I can tell can only
- * choose between 2 of the 4 available when you really want to hit
- * PCI space. So all the memory we're touching has to fit in 2 regions
- * of 4 meg under 256meg. So much for dynamic allocation of multiple
- * /dev/dsps. So we force only 1 /dev/dsp, allocate both its read
- * and write buffers contiguously at open(), and allocate the weird
- * mixbuf input APU buffers on another page. The first 2meg region
- * goes to the input/output buffers, and the second region goes to
- * the weird mixbuf. Long term fixes? Get an allocator that lets
- * us try and allocate from zones. Alleviate pain by putting the mixbuf
- * in onboard ram rather than in system memory. Buy a real sound card.
+ * It claims to only fetch from 4 regions of PCI space, each 4 meg in length.
+ * But that doesn't really work. You can only use 1 region. So all our
+ * allocations have to be in 4meg of each other. Booo. Hiss.
+ * So we have a module parameter, dsps_order, that is the order of
+ * the number of dsps to provide. All their buffer space is allocated
+ * on open time. The sonicvibes oss routines we inherited really want
+ * power of 2 buffers, so we have all those next to each other, then
+ * 512 byte regions for the recording wavecaches. This ends up
+ * wasting quite a bit of memory. The only fixes I can see would be
+ * getting a kernel allocator that could work in zones, or figuring out
+ * just how to coerce the WP into doing what we want.
+ *
+ * The indirection of the various registers means we have to spinlock
+ * nearly all register accesses. We have the main register indirection
+ * like the wave cache, maestro registers, etc. Then we have beasts
+ * like the APU interface that is indirect registers gotten at through
+ * the main maestro indirection. Ouch. We spinlock around the actual
+ * ports on a per card basis. This means spinlock activity at each IO
+ * operation, but the only IO operation clusters are in non critical
+ * paths and it makes the code far easier to follow. Interrupts are
+ * blocked while holding the locks because the int handler has to
+ * get at some of them :(. The mixer interface doesn't, however.
+ * We also have an OSS state lock that is thrown around in a few
+ * places.
*
* History
+ * v0.07 - Oct 4 1999 - Zach Brown <zab@redhat.com>
+ * tweak adc/dac, formating, and stuff to allow full duplex
+ * allocate dsps memory at open() so we can fit in the wavecache window
+ * fix wavecache braindamage. again. no more scribbling?
+ * fix ess 1921 codec bug on some laptops.
+ * fix dumb pci scanning bug
+ * started 2.3 cleanup, redid spinlocks, little cleanups
* v0.06 - Sep 20 1999 - Zach Brown <zab@redhat.com>
* fix wavecache thinkos. limit to 1 /dev/dsp.
* eric is wearing his thinking toque this week.
@@ -125,20 +143,10 @@
* look really hard at the apu/bob/dma buffer code paths.
* fix bob frequency
* do smart things with ac97 2.0 bits.
- * fix wavecache so multiple /dev/dsps work
* test different sized writes
* fixup latencies ?
* get apm save/restore working?
- * allocate dma bounce page
- * start_adc is called way too often
* sort out 0x34->0x36 crap in init
- * wavecache needs to be looked at, multiple
- * dsps and recording seem confused
- *
- * the entire issue of smp safety needs to be looked at. cli() needs
- * to be replaced with spinlock_irqsave, being very careful of call
- * paths avoiding deadlock. if lock hold times are quick just
- * use one big ass per device spinlock..
*
* apm is kind of a mess. I doubt we can rely on the machine keeping
* power to the maestro/codecs when we suspend. This means we have
@@ -187,13 +195,14 @@
#ifdef M_DEBUG
static int debug=0;
+static int dsps_order=0;
#define M_printk(args...) {if (debug) printk(args);}
#else
#define M_printk(x)
#endif
/* --------------------------------------------------------------------- */
-#define DRIVER_VERSION "0.06"
+#define DRIVER_VERSION "0.07"
#ifndef PCI_VENDOR_ESS
#define PCI_VENDOR_ESS 0x125D
@@ -208,7 +217,6 @@
#define ESS_CHAN_HARD 0x100
-#undef CONFIG_APM /* see notes above */
/* changed so that I could actually find all the
references and fix them up. its a little more readable now. */
@@ -218,16 +226,15 @@
#define ESS_DAC_SHIFT 0
#define ESS_ADC_SHIFT 4
-#define ESS_ENABLE_PE 1
-#define ESS_ENABLE_RE 2
-
#define ESS_STATE_MAGIC 0x125D1968
#define ESS_CARD_MAGIC 0x19283746
#define DAC_RUNNING 1
#define ADC_RUNNING 2
-#define NR_DSPS 1 /* our wavecache setup demands this. */
+#define MAX_DSP_ORDER 3
+#define MAX_DSPS (1<<3)
+#define NR_DSPS (1<<dsps_order)
#define SND_DEV_DSP16 5
@@ -260,10 +267,14 @@
unsigned int rateadc, ratedac;
unsigned char fmt, enable;
+ int index;
+
+ /* this locks around the oss state in the driver */
spinlock_t lock;
+ /* only let 1 be opening at a time */
struct semaphore open_sem;
- mode_t open_mode;
wait_queue_head_t open_wait;
+ mode_t open_mode;
/* soundcore stuff */
int dev_audio;
@@ -286,7 +297,7 @@
unsigned fragsamples;
/* OSS stuff */
unsigned mapped:1;
- unsigned ready:1;
+ unsigned ready:1; /* our oss buffers are ready to go */
unsigned endcleared:1;
unsigned ossfragshift;
int ossmaxfrags;
@@ -294,7 +305,6 @@
u16 base; /* Offset for ptr */
} dma_dac, dma_adc;
-
/* pointer to each dsp?s piece of the apu->src buffer page */
void *mixbuf;
};
@@ -323,7 +333,7 @@
unsigned int mixer_state[SOUND_MIXER_NRDEVICES];
} mix;
- struct ess_state channels[NR_DSPS];
+ struct ess_state channels[MAX_DSPS];
u16 maestro_map[32]; /* Register map */
#ifdef CONFIG_APM
/* we have to store this junk so that we can come back from a
@@ -331,16 +341,19 @@
u16 apu_map[64][16]; /* contents of apu regs */
#endif
- /* 1 page of DMA-able memory for mixer apu buffers,
- shared amongst dsp?s. */
- void *mixpage;
+ /* this locks around the physical registers on the card */
+ spinlock_t lock;
+
+ /* memory for this card.. wavecache limited :(*/
+ void *dmapages;
+ int dmaorder;
/* hardware resources */
u32 iobase;
u32 irq;
int bob_freq;
- char bob_running;
+ char dsps_open;
};
extern __inline__ unsigned ld2(unsigned int x)
@@ -454,7 +467,6 @@
be sure to fill it in if you add oss mixers
to anyone's supported mixer defines */
-/* possible __init */
static struct mixer_defaults {
int mixer;
unsigned int value;
@@ -721,42 +733,21 @@
card->mix.supported_mixers &= ~(SOUND_MASK_MIC);
card->mix.record_sources = 0;
card->mix.recmask_io = NULL;
- /* no idea what these do */
+#if 0 /* don't ask. I have yet to see what these actually do. */
maestro_ac97_set(iobase,0x76,0xABBA); /* o/~ Take a chance on me o/~ */
udelay(20);
maestro_ac97_set(iobase,0x78,0x3002);
udelay(20);
maestro_ac97_set(iobase,0x78,0x3802);
udelay(20);
+#endif
break;
default: break;
}
-#if 0 /* used to be set, lets try using the codec defaults */
- /* always set headphones to max unmuted, OSS won't
- let us change it :( */
- maestro_ac97_set(iobase, 0x04, 0x0000);
- maestro_ac97_set(iobase, 0x06, 0x0000);
- maestro_ac97_set(iobase, 0x0C, 0x1F1F);
- /* null record select */
- maestro_ac97_set(iobase, 0x1A, 0x0000);
-#endif
maestro_ac97_set(iobase, 0x1E, 0x0404);
/* null misc stuff */
maestro_ac97_set(iobase, 0x20, 0x0000);
- /* the regs are read only, duh :) */
-/* maestro_ac97_set(iobase, 0x26, 0x000F);*/
-
-#if 0 /* this is a really good way to hang
- codecs. we need a better way. */
- if(maestro_ac97_get(iobase,0x36) ==0x8080) {
- int reg;
- printk("maestro: your ac97 might be 2.0, see if this makes sense:\n");
- for(reg = 0x28; reg <= 0x58 ; reg += 2) {
- printk(" 0x%2x: %4x\n",reg,maestro_ac97_get(iobase,reg));
- }
- }
-#endif
return 0;
}
@@ -837,30 +828,46 @@
* The Maestro engineers were a little indirection happy. These indirected
* registers themselves include indirect registers at another layer
*/
+
+static void __maestro_write(struct ess_card *card, u16 reg, u16 data)
+{
+ long ioaddr = card->iobase;
+
+ outw(reg, ioaddr+0x02);
+ outw(data, ioaddr+0x00);
+ card->maestro_map[reg]=data;
+
+}
static void maestro_write(struct ess_state *ess, u16 reg, u16 data)
{
- long ioaddr = ess->card->iobase;
unsigned long flags;
- save_flags(flags);
- cli();
+
+ spin_lock_irqsave(&ess->card->lock,flags);
+
+ __maestro_write(ess->card,reg,data);
+
+ spin_unlock_irqrestore(&card->lock,flags);
+}
+
+static u16 __maestro_read(struct ess_card *card, u16 reg)
+{
+ long ioaddr = card->iobase;
+
outw(reg, ioaddr+0x02);
- outw(data, ioaddr+0x00);
- ess->card->maestro_map[reg]=data;
- restore_flags(flags);
+ return card->maestro_map[reg]=inw(ioaddr+0x00);
}
static u16 maestro_read(struct ess_state *ess, u16 reg)
{
- long ioaddr = ess->card->iobase;
if(READABLE_MAP & (1<<reg))
{
unsigned long flags;
- save_flags(flags);
- cli();
- outw(reg, ioaddr+0x02);
- ess->card->maestro_map[reg]=inw(ioaddr+0x00);
- restore_flags(flags);
+ spin_lock_irqsave(&ess->card->lock,flags);
+
+ __maestro_read(ess->card,reg);
+
+ spin_unlock_irqrestore(&ess->card->lock,flags);
}
return ess->card->maestro_map[reg];
}
@@ -883,24 +890,24 @@
#define IDR6_TIMER_CTRL 0x06
#define IDR7_WAVE_ROMRAM 0x07
-static void apu_index_set(struct ess_state *ess, u16 index)
+static void apu_index_set(struct ess_card *card, u16 index)
{
int i;
- maestro_write(ess, IDR1_CRAM_POINTER, index);
+ __maestro_write(card, IDR1_CRAM_POINTER, index);
for(i=0;i<1000;i++)
- if(maestro_read(ess, IDR1_CRAM_POINTER)==index)
+ if(__maestro_read(card, IDR1_CRAM_POINTER)==index)
return;
printk(KERN_WARNING "maestro: APU register select failed.\n");
}
-static void apu_data_set(struct ess_state *ess, u16 data)
+static void apu_data_set(struct ess_card *card, u16 data)
{
int i;
for(i=0;i<1000;i++)
{
- if(maestro_read(ess, IDR0_DATA_PORT)==data)
+ if(__maestro_read(card, IDR0_DATA_PORT)==data)
return;
- maestro_write(ess, IDR0_DATA_PORT, data);
+ __maestro_write(card, IDR0_DATA_PORT, data);
}
}
@@ -929,11 +936,13 @@
#endif
reg|=(channel<<4);
- save_flags(flags);
- cli();
- apu_index_set(ess, reg);
- apu_data_set(ess, data);
- restore_flags(flags);
+ /* hooray for double indirection!! */
+ spin_lock_irqsave(&ess->card->lock,flags);
+
+ apu_index_set(ess->card, reg);
+ apu_data_set(ess->card, data);
+
+ spin_unlock_irqrestore(&ess->card->lock,flags);
}
static u16 apu_get_register(struct ess_state *ess, u16 channel, u8 reg)
@@ -948,11 +957,12 @@
reg|=(channel<<4);
- save_flags(flags);
- cli();
- apu_index_set(ess, reg);
- v=maestro_read(ess, IDR0_DATA_PORT);
- restore_flags(flags);
+ spin_lock_irqsave(&ess->card->lock,flags);
+
+ apu_index_set(ess->card, reg);
+ v=__maestro_read(ess->card, IDR0_DATA_PORT);
+
+ spin_unlock_irqrestore(&ess->card->lock,flags);
return v;
}
@@ -967,11 +977,12 @@
long ioaddr = ess->card->iobase;
unsigned long flags;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&ess->card->lock,flags);
+
outw(reg, ioaddr+0x10);
outw(value, ioaddr+0x12);
- restore_flags(flags);
+
+ spin_unlock_irqrestore(&ess->card->lock,flags);
}
static u16 wave_get_register(struct ess_state *ess, u16 reg)
@@ -980,11 +991,10 @@
unsigned long flags;
u16 value;
- save_flags(flags);
- cli();
+ spin_lock_irqsave(&ess->card->lock,flags);
outw(reg, ioaddr+0x10);
value=inw(ioaddr+0x12);
- restore_flags(flags);
+ spin_unlock_irqrestore(&ess->card->lock,flags);
return value;
}
@@ -1085,6 +1095,70 @@
apu_set_register(s, 5, 3, freq>>8);
}
+/* Stop our host of recording apus */
+extern inline void stop_adc(struct ess_state *s)
+{
+ /* XXX lets hope we don't have to lock around this */
+ if (! (s->enable & ADC_RUNNING)) return;
+
+ s->enable &= ~ADC_RUNNING;
+ apu_set_register(s, 2, 0, apu_get_register(s, 2, 0)&0xFF0F);
+ apu_set_register(s, 3, 0, apu_get_register(s, 3, 0)&0xFF0F);
+ apu_set_register(s, 4, 0, apu_get_register(s, 2, 0)&0xFF0F);
+ apu_set_register(s, 5, 0, apu_get_register(s, 3, 0)&0xFF0F);
+}
+
+/* stop output apus */
+extern inline void stop_dac(struct ess_state *s)
+{
+ /* XXX have to lock around this? */
+ if (! (s->enable & DAC_RUNNING)) return;
+
+ s->enable &= ~DAC_RUNNING;
+ apu_set_register(s, 0, 0, apu_get_register(s, 0, 0)&0xFF0F);
+ apu_set_register(s, 1, 0, apu_get_register(s, 1, 0)&0xFF0F);
+}
+
+static void start_dac(struct ess_state *s)
+{
+ /* XXX locks? */
+ if ( (s->dma_dac.mapped || s->dma_dac.count > 0) &&
+ s->dma_dac.ready &&
+ (! (s->enable & DAC_RUNNING)) ) {
+
+ s->enable |= DAC_RUNNING;
+
+ apu_set_register(s, 0, 0,
+ (apu_get_register(s, 0, 0)&0xFF0F)|s->apu_mode[0]);
+
+ if((s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_STEREO)
+ apu_set_register(s, 1, 0,
+ (apu_get_register(s, 1, 0)&0xFF0F)|s->apu_mode[1]);
+ }
+}
+
+static void start_adc(struct ess_state *s)
+{
+ /* XXX locks? */
+ if ((s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize))
+ && s->dma_adc.ready && (! (s->enable & ADC_RUNNING)) ) {
+
+ s->enable |= ADC_RUNNING;
+ apu_set_register(s, 2, 0,
+ (apu_get_register(s, 2, 0)&0xFF0F)|s->apu_mode[2]);
+ apu_set_register(s, 4, 0,
+ (apu_get_register(s, 4, 0)&0xFF0F)|s->apu_mode[4]);
+
+ if( s->fmt & (ESS_FMT_STEREO << ESS_ADC_SHIFT)) {
+ apu_set_register(s, 3, 0,
+ (apu_get_register(s, 3, 0)&0xFF0F)|s->apu_mode[3]);
+ apu_set_register(s, 5, 0,
+ (apu_get_register(s, 5, 0)&0xFF0F)|s->apu_mode[5]);
+ }
+
+ }
+}
+
/*
* Native play back driver
@@ -1115,29 +1189,6 @@
{
int i;
- /*
- * To understand this it helps to know how the
- * wave cache works. There are 4 DSP wavecache
- * blocks which are 0x1FC->0x1FF. They are selected
- * by setting bits 22,21,20 of the address to
- * 1 X Y where X Y select the block.
- *
- * In addition stereo pairing is supported. This is
- * set in the wave cache control for the channel as is
- * 8bit unsigned.
- *
- * Note that this causes a problem. With our limit of
- * about 12 full duplex pairs (48 channels active) we
- * will need to do a lot of juggling to get all the
- * memory we want sufficiently close together.
- *
- * Even with 64K blocks that means
- * 24 channel pairs
- * 6 pairs/block
- *
- * 10K per channel pair = 5000 samples.
- */
-
if(!channel)
pa = virt_to_bus(buffer);
else
@@ -1145,9 +1196,6 @@
*2 accomodates for rampant shifting earlier */
pa = virt_to_bus(buffer + size*2);
- /* play bufs are in the same first region as record bufs */
- wave_set_register(ess, 0x01FC , (pa&0xFFE00000)>>12);
-
/* set the wavecache control reg */
tmpval = (pa - 0x10) & 0xFFF8;
#if 0
@@ -1200,6 +1248,10 @@
else
apu_set_register(ess, channel, 10, 0x8F08);
+ if(mode&ESS_FMT_16BIT)
+ ess->apu_mode[channel]=0x10;
+ else
+ ess->apu_mode[channel]=0x30;
}
/* clear WP interupts */
@@ -1207,24 +1259,9 @@
/* enable WP ints */
outw(inw(ess->card->iobase+0x18)|4, ess->card->iobase+0x18);
+ /* go team! */
set_dac_rate(ess,rate);
-
- for(channel=0; channel<=high_apu; channel++)
- {
- /* Turn on the DMA */
- if(mode&ESS_FMT_16BIT)
- {
- apu_set_register(ess, channel, 0,
- (apu_get_register(ess, channel, 0)&0xFF0F)|0x10);
- ess->apu_mode[channel]=0x10;
- }
- else
- {
- apu_set_register(ess, channel, 0,
- (apu_get_register(ess, channel, 0)&0xFF0F)|0x30);
- ess->apu_mode[channel]=0x30;
- }
- }
+ start_dac(ess);
}
/*
@@ -1232,11 +1269,11 @@
*/
/* again, passed mode is alrady shifted/masked */
-static void ess_rec_setup(struct ess_state *ess, int mode, u32 rate, void *buffer, int size)
+static void
+ess_rec_setup(struct ess_state *ess, int mode, u32 rate, void *buffer, int size)
{
int apu_step = 2;
int channel;
- u8 apu_type;
M_printk("maestro: ess_rec_setup: mode=%d rate=%d buf=0x%p len=%d.\n",
mode, rate, buffer, size);
@@ -1279,6 +1316,7 @@
/* we source from a 'magic' apu */
bsize = PAGE_SIZE >> 5; /* half of this channels alloc, in words */
route = 0x14 + (channel - 4); /* parallel in crap, see maestro reg 0xC [8-11] */
+ ess->apu_mode[channel] = 0x90; /* Input Mixer */
} else {
/* we're a rate converter taking
@@ -1292,6 +1330,8 @@
pa = virt_to_bus(buffer + size*2);
}
+ ess->apu_mode[channel] = 0xB0; /* Sample Rate Converter */
+
bsize = size;
/* get input from inputing apu */
route = channel + 2;
@@ -1299,9 +1339,6 @@
M_printk("maestro: ess_rec_setup: getting pa 0x%x from %d\n",pa,channel);
- /* put our base address in the right region */
- wave_set_register(ess, 0x01FC + (channel >> 2), (pa&0xFFE00000)>>12);
-
/* set the wavecache control reg */
tmpval = (pa - 0x10) & 0xFFF8;
wave_set_register(ess, ess->apu[channel]<<3, tmpval);
@@ -1315,9 +1352,6 @@
pa|=0x00400000; /* bit 22 -> System RAM */
- if ( channel & 4)
- pa|=0x00200000; /* bit 21 -> second region for mixbuf */
-
M_printk("maestro: ess_rec_setup: APU[%d] pa = 0x%x size = 0x%x route = 0x%x\n",
ess->apu[channel], pa, bsize, route);
@@ -1356,20 +1390,9 @@
/* enable WP ints */
outw(inw(ess->card->iobase+0x18)|4, ess->card->iobase+0x18);
+ /* let 'er rip */
set_adc_rate(ess,rate);
-
- for(channel=2; channel<6; channel+=apu_step)
- {
- if(channel & 0x04) {
- apu_type = 0x90; /* Input Mixer */
- } else {
- apu_type = 0xB0; /* Sample Rate Converter */
- }
-
- apu_set_register(ess, channel, 0,
- (apu_get_register(ess, channel, 0)&0xFF0F) | apu_type);
- ess->apu_mode[channel] = apu_type;
- }
+ start_adc(ess);
}
/* --------------------------------------------------------------------- */
@@ -1388,12 +1411,17 @@
{
long ioport = s->card->iobase;
int offset;
+ unsigned long flags;
+
+ spin_lock_irqsave(&s->card->lock,flags);
outw(1, ioport+2);
outw(s->apu[0]<<4|5, ioport);
outw(0, ioport+2);
offset=inw(ioport);
+ spin_unlock_irqrestore(&s->card->lock,flags);
+
/* M_printk("dmaa: offset: %d, base: %d\n",offset,s->dma_dac.base); */
offset-=s->dma_dac.base;
@@ -1406,12 +1434,17 @@
{
long ioport = s->card->iobase;
int offset;
+ unsigned long flags;
+
+ spin_lock_irqsave(&s->card->lock,flags);
outw(1, ioport+2);
outw(s->apu[2]<<4|5, ioport);
outw(0, ioport+2);
offset=inw(ioport);
+ spin_unlock_irqrestore(&s->card->lock,flags);
+
/* M_printk("dmac: offset: %d, base: %d\n",offset,s->dma_adc.base); */
/* The offset is an address not a position relative to base */
@@ -1527,113 +1560,23 @@
}
-/* Stop our host of recording apus */
-extern inline void stop_adc(struct ess_state *s)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&s->lock, flags);
- s->enable &= ~ADC_RUNNING;
- apu_set_register(s, 2, 0, apu_get_register(s, 2, 0)&0xFF0F);
- apu_set_register(s, 3, 0, apu_get_register(s, 3, 0)&0xFF0F);
- apu_set_register(s, 4, 0, apu_get_register(s, 2, 0)&0xFF0F);
- apu_set_register(s, 5, 0, apu_get_register(s, 3, 0)&0xFF0F);
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
-/* stop output apus */
-extern inline void stop_dac(struct ess_state *s)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&s->lock, flags);
- s->enable &= ~DAC_RUNNING;
- apu_set_register(s, 0, 0, apu_get_register(s, 0, 0)&0xFF0F);
- apu_set_register(s, 1, 0, apu_get_register(s, 1, 0)&0xFF0F);
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
-static void start_dac(struct ess_state *s)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&s->lock, flags);
- if ((s->dma_dac.mapped || s->dma_dac.count > 0) && s->dma_dac.ready) {
- s->enable |= DAC_RUNNING;
-
- apu_set_register(s, 0, 0,
- (apu_get_register(s, 0, 0)&0xFF0F)|s->apu_mode[0]);
-
- if((s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_STEREO)
- apu_set_register(s, 1, 0,
- (apu_get_register(s, 1, 0)&0xFF0F)|s->apu_mode[1]);
- }
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
-static void start_adc(struct ess_state *s)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&s->lock, flags);
- if ((s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize))
- && s->dma_adc.ready) {
- s->enable |= ADC_RUNNING;
- apu_set_register(s, 2, 0,
- (apu_get_register(s, 2, 0)&0xFF0F)|s->apu_mode[2]);
- apu_set_register(s, 4, 0,
- (apu_get_register(s, 4, 0)&0xFF0F)|s->apu_mode[4]);
- if( s->fmt & (ESS_FMT_STEREO << ESS_ADC_SHIFT)) {
- apu_set_register(s, 3, 0,
- (apu_get_register(s, 3, 0)&0xFF0F)|s->apu_mode[3]);
- apu_set_register(s, 5, 0,
- (apu_get_register(s, 5, 0)&0xFF0F)|s->apu_mode[5]);
- }
-
- }
- spin_unlock_irqrestore(&s->lock, flags);
-}
-
-/* --------------------------------------------------------------------- */
-
-/* we allocate both buffers at once */
-#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT)
-#define DMABUF_MINORDER 2
-
-static void dealloc_dmabuf(struct dmabuf *db)
-{
- unsigned long map, mapend;
-
- if (db->rawbuf) {
- M_printk("maestro: freeing %p\n",db->rawbuf);
- /* undo marking the pages as reserved */
- mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
- for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
- clear_bit(PG_reserved, &mem_map[map].flags);
- free_pages((unsigned long)db->rawbuf, db->buforder);
- }
- db->rawbuf = NULL;
- db->mapped = db->ready = 0;
-}
-
-static int prog_dmabuf(struct ess_state *s, unsigned rec)
+static int
+prog_dmabuf(struct ess_state *s, unsigned rec)
{
struct dmabuf *db = rec ? &s->dma_adc : &s->dma_dac;
unsigned rate = rec ? s->rateadc : s->ratedac;
- int order;
unsigned bytepersec;
unsigned bufs;
- unsigned long map, mapend;
unsigned char fmt;
unsigned long flags;
spin_lock_irqsave(&s->lock, flags);
fmt = s->fmt;
if (rec) {
- s->enable &= ~ESS_ENABLE_RE;
+ stop_adc(s);
fmt >>= ESS_ADC_SHIFT;
} else {
- s->enable &= ~ESS_ENABLE_PE;
+ stop_dac(s);
fmt >>= ESS_DAC_SHIFT;
}
spin_unlock_irqrestore(&s->lock, flags);
@@ -1641,47 +1584,6 @@
db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0;
- if (!db->rawbuf) {
- void *rawbuf;
- /* haha, this thing is hacked to hell and back.
- this is so ugly. */
- s->dma_dac.ready = s->dma_dac.mapped = 0;
- s->dma_adc.ready = s->dma_adc.mapped = 0;
-
- /* alloc as big a chunk as we can */
- for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
- if((rawbuf = (void *)__get_free_pages(GFP_KERNEL|GFP_DMA, order)))
-
- break;
-
- if (!rawbuf)
- return -ENOMEM;
-
-
- /* we allocated both buffers */
- s->dma_adc.rawbuf = rawbuf;
- s->dma_dac.rawbuf = rawbuf + ( PAGE_SIZE << (order - 1) );
-
- M_printk("maestro: allocated %ld bytes at %p\n",PAGE_SIZE<<order, db->rawbuf);
-
- s->dma_adc.buforder = s->dma_dac.buforder = order - 1;
-
- /* XXX these checks are silly now */
-#if 0
- if ((virt_to_bus(db->rawbuf) ^ (virt_to_bus(db->rawbuf) + (PAGE_SIZE << order) - 1)) & ~0xffff)
- printk(KERN_DEBUG "maestro: DMA buffer crosses 64k boundary: busaddr 0x%lx size %ld\n",
- virt_to_bus(db->rawbuf), PAGE_SIZE << order);
-
-#endif
- if ((virt_to_bus(db->rawbuf) + (PAGE_SIZE << order) - 1) & ~0xffffff)
- printk(KERN_DEBUG "maestro: DMA buffer beyond 16MB: busaddr 0x%lx size %ld\n",
- virt_to_bus(db->rawbuf), PAGE_SIZE << order);
-
- /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
- mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << order) - 1);
- for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
- set_bit(PG_reserved, &mem_map[map].flags);
- }
bytepersec = rate << sample_shift[fmt];
bufs = PAGE_SIZE << db->buforder;
if (db->ossfragshift) {
@@ -1691,12 +1593,12 @@
db->fragshift = db->ossfragshift;
} else {
/* lets hand out reasonable big ass buffers by default */
- db->fragshift = (db->buforder + PAGE_SHIFT -2);
+ db->fragshift = (db->buforder - 2);
#if 0
db->fragshift = ld2(bytepersec/100/(db->subdivision ? db->subdivision : 1));
+#endif
if (db->fragshift < 3)
db->fragshift = 3;
-#endif
}
db->numfrag = bufs >> db->fragshift;
while (db->numfrag < 4 && db->fragshift > 3) {
@@ -1709,6 +1611,8 @@
db->fragsamples = db->fragsize >> sample_shift[fmt];
db->dmasize = db->numfrag << db->fragshift;
+ M_printk("maestro: setup oss: numfrag: %d fragsize: %d dmasize: %d\n",db->numfrag,db->fragsize,db->dmasize);
+
memset(db->rawbuf, (fmt & ESS_FMT_16BIT) ? 0 : 0x80, db->dmasize);
spin_lock_irqsave(&s->lock, flags);
@@ -1727,7 +1631,8 @@
/* XXX haha, way broken with our split stereo setup. giggle. */
/* only called by ess_write (dac ness ) */
-extern __inline__ void clear_advance(struct ess_state *s)
+static __inline__ void
+clear_advance(struct ess_state *s)
{
unsigned char c = ((s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_16BIT) ? 0 : 0x80;
unsigned char *buf = s->dma_dac.rawbuf;
@@ -1746,7 +1651,8 @@
}
/* call with spinlock held! */
-static void ess_update_ptr(struct ess_state *s)
+static void
+ess_update_ptr(struct ess_state *s)
{
unsigned hwptr;
int diff;
@@ -1771,7 +1677,6 @@
wake_up(&s->dma_adc.wait);
if (!s->dma_adc.mapped) {
if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) {
- s->enable &= ~ESS_ENABLE_RE;
/* FILL ME
wrindir(s, SV_CIENABLE, s->enable); */
stop_adc(s);
@@ -1796,7 +1701,6 @@
s->dma_dac.count -= diff;
/* M_printk("maestro: ess_update_ptr: diff: %d, count: %d\n", diff, s->dma_dac.count); */
if (s->dma_dac.count <= 0) {
- s->enable &= ~ESS_ENABLE_PE;
/* FILL ME
wrindir(s, SV_CIENABLE, s->enable); */
/* XXX how on earth can calling this with the lock held work.. */
@@ -1889,9 +1793,7 @@
static int mixer_ioctl(struct ess_card *card, unsigned int cmd, unsigned long arg)
{
- unsigned long flags;
int i, val=0;
- struct ess_state *s = &card->channels[0];
VALIDATE_CARD(card);
if (cmd == SOUND_MIXER_INFO) {
@@ -1924,9 +1826,9 @@
if(!card->mix.recmask_io) {
val = 0;
} else {
- spin_lock_irqsave(&s->lock, flags);
+ spin_lock(&card->lock);
val = card->mix.recmask_io(card,1,0);
- spin_unlock_irqrestore(&s->lock, flags);
+ spin_unlock(&card->lock);
}
break;
@@ -1953,9 +1855,9 @@
return -EINVAL;
/* do we ever want to touch the hardware? */
-/* spin_lock_irqsave(&s->lock, flags);
+/* spin_lock(&card->lock);
val = card->mix.read_mixer(card,i);
- spin_unlock_irqrestore(&s->lock, flags);*/
+ spin_unlock(&card->lock);*/
val = card->mix.mixer_state[i];
/* M_printk("returned 0x%x for mixer %d\n",val,i);*/
@@ -1978,9 +1880,9 @@
if (!card->mix.recmask_io) return -EINVAL;
if(! (val &= card->mix.record_sources)) return -EINVAL;
- spin_lock_irqsave(&s->lock, flags);
+ spin_lock(&card->lock);
card->mix.recmask_io(card,0,val);
- spin_unlock_irqrestore(&s->lock, flags);
+ spin_unlock(&card->lock);
return 0;
default:
@@ -1989,9 +1891,9 @@
if ( ! supported_mixer(card,i))
return -EINVAL;
- spin_lock_irqsave(&s->lock, flags);
+ spin_lock(&card->lock);
set_mixer(card,i,val);
- spin_unlock_irqrestore(&s->lock, flags);
+ spin_unlock(&card->lock);
return 0;
}
@@ -2062,16 +1964,17 @@
static int drain_dac(struct ess_state *s, int nonblock)
{
- DECLARE_WAITQUEUE(wait, current);
+ DECLARE_WAITQUEUE(wait,current);
unsigned long flags;
int count;
signed long tmo;
if (s->dma_dac.mapped || !s->dma_dac.ready)
return 0;
- current->state = TASK_INTERRUPTIBLE;
+ current->state = TASK_INTERRUPTIBLE;
add_wait_queue(&s->dma_dac.wait, &wait);
for (;;) {
+ /* XXX uhm.. questionable locking*/
spin_lock_irqsave(&s->lock, flags);
count = s->dma_dac.count;
spin_unlock_irqrestore(&s->lock, flags);
@@ -2081,7 +1984,7 @@
break;
if (nonblock) {
remove_wait_queue(&s->dma_dac.wait, &wait);
- current->state = TASK_RUNNING;
+ current->state = TASK_RUNNING;
return -EBUSY;
}
tmo = (count * HZ) / s->ratedac;
@@ -2092,7 +1995,7 @@
M_printk(KERN_DEBUG "maestro: dma timed out?? %ld\n",jiffies);
}
remove_wait_queue(&s->dma_dac.wait, &wait);
- current->state = TASK_RUNNING;
+ current->state = TASK_RUNNING;
if (signal_pending(current))
return -ERESTARTSYS;
return 0;
@@ -2100,7 +2003,8 @@
/* --------------------------------------------------------------------- */
/* Zach sez: "god this is gross.." */
-int comb_stereo(unsigned char *real_buffer,unsigned char *tmp_buffer, int offset,
+static int
+comb_stereo(unsigned char *real_buffer,unsigned char *tmp_buffer, int offset,
int count, int bufsize)
{
/* No such thing as stereo recording, so we
@@ -2232,7 +2136,8 @@
/* god this is gross..*/
/* again, the mode passed is shifted/masked */
-int split_stereo(unsigned char *real_buffer,unsigned char *tmp_buffer, int offset,
+static int
+split_stereo(unsigned char *real_buffer,unsigned char *tmp_buffer, int offset,
int count, int bufsize, int mode)
{
/* oh, bother. stereo decoding APU's don't work in 16bit so we
@@ -2474,7 +2379,7 @@
return 0;
case SNDCTL_DSP_GETCAPS:
- return put_user(0/*DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP*/, (int *)arg);
+ return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER /*| DSP_CAP_MMAP*/, (int *)arg);
case SNDCTL_DSP_RESET:
if (file->f_mode & FMODE_WRITE) {
@@ -2596,9 +2501,9 @@
case SNDCTL_DSP_GETTRIGGER:
val = 0;
- if (file->f_mode & FMODE_READ && s->enable & ESS_ENABLE_RE)
+ if ((file->f_mode & FMODE_READ) && (s->enable & ADC_RUNNING))
val |= PCM_ENABLE_INPUT;
- if (file->f_mode & FMODE_WRITE && s->enable & ESS_ENABLE_PE)
+ if ((file->f_mode & FMODE_WRITE) && (s->enable & DAC_RUNNING))
val |= PCM_ENABLE_OUTPUT;
return put_user(val, (int *)arg);
@@ -2625,7 +2530,7 @@
case SNDCTL_DSP_GETOSPACE:
if (!(file->f_mode & FMODE_WRITE))
return -EINVAL;
- if (!(s->enable & ESS_ENABLE_PE) && (val = prog_dmabuf(s, 0)) != 0)
+ if (!(s->enable & DAC_RUNNING) && (val = prog_dmabuf(s, 0)) != 0)
return val;
spin_lock_irqsave(&s->lock, flags);
ess_update_ptr(s);
@@ -2639,7 +2544,7 @@
case SNDCTL_DSP_GETISPACE:
if (!(file->f_mode & FMODE_READ))
return -EINVAL;
- if (!(s->enable & ESS_ENABLE_RE) && (val = prog_dmabuf(s, 1)) != 0)
+ if (!(s->enable & ADC_RUNNING) && (val = prog_dmabuf(s, 1)) != 0)
return val;
spin_lock_irqsave(&s->lock, flags);
ess_update_ptr(s);
@@ -2756,7 +2661,87 @@
return -EINVAL;
}
-static int ess_open(struct inode *inode, struct file *file)
+static int
+allocate_buffers(struct ess_state *s)
+{
+ void *rawbuf=NULL;
+ int order,i;
+ unsigned long mapend,map;
+
+ /* alloc as big a chunk as we can */
+ for (order = (dsps_order + (15-PAGE_SHIFT) + 1); order >= (dsps_order + 2 + 1); order--)
+ if((rawbuf = (void *)__get_free_pages(GFP_KERNEL|GFP_DMA, order)))
+ break;
+
+ if (!rawbuf)
+ return 1;
+
+ M_printk("maestro: allocated %ld (%d) bytes at %p\n",PAGE_SIZE<<order,order, rawbuf);
+
+ if ((virt_to_bus(rawbuf) + (PAGE_SIZE << order) - 1) & ~((1<<28)-1)) /* silly limited pci poop */
+ printk(KERN_DEBUG "maestro: DMA buffer beyond 256MB: busaddr 0x%lx size %ld\n",
+ virt_to_bus(rawbuf), PAGE_SIZE << order);
+
+ if ((PAGE_SIZE<<order) > (1<<22))
+ printk(KERN_DEBUG "maestro: %ld byte DMA buffer longer than APU can express!\n",PAGE_SIZE<<order);
+
+ s->card->dmapages = rawbuf;
+ s->card->dmaorder = order;
+
+ /* play bufs are in the same first region as record bufs */
+ wave_set_register(s, 0x01FC , ((virt_to_bus(rawbuf))&0xFFE00000)>>12);
+
+ M_printk("maestro: writing %lx (%lx) to the wp\n",virt_to_bus(rawbuf),
+ ((virt_to_bus(rawbuf))&0xFFE00000)>>12);
+
+ for(i=0;i<NR_DSPS;i++) {
+ struct ess_state *ess = &s->card->channels[i];
+
+ if(ess->dev_audio == -1)
+ continue;
+
+ ess->dma_dac.ready = s->dma_dac.mapped = 0;
+ ess->dma_adc.ready = s->dma_adc.mapped = 0;
+ ess->dma_adc.buforder = ess->dma_dac.buforder = order - 1 - dsps_order - 1;
+ ess->dma_dac.rawbuf = rawbuf + (i * ( PAGE_SIZE << (ess->dma_dac.buforder + 1 )));
+ ess->dma_adc.rawbuf = ess->dma_dac.rawbuf + ( PAGE_SIZE << ess->dma_dac.buforder);
+ ess->mixbuf = rawbuf + (PAGE_SIZE<<order) - (512 * (i+1));
+
+ M_printk("maestro: setup apu %d: %p %p %p\n",i,ess->dma_dac.rawbuf,
+ ess->dma_adc.rawbuf, ess->mixbuf);
+
+ }
+
+ /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
+ mapend = MAP_NR(rawbuf + (PAGE_SIZE << order) - 1);
+ for (map = MAP_NR(rawbuf); map <= mapend; map++) {
+ set_bit(PG_reserved, &mem_map[map].flags);
+ }
+
+ return 0;
+}
+static void
+free_buffers(struct ess_state *s)
+{
+ unsigned long map, mapend;
+
+ s->dma_dac.rawbuf = s->dma_adc.rawbuf = NULL;
+ s->dma_dac.mapped = s->dma_adc.mapped = 0;
+ s->dma_dac.ready = s->dma_adc.ready = 0;
+
+ M_printk("maestro: freeing %p\n",s->card->dmapages);
+ /* undo marking the pages as reserved */
+
+ mapend = MAP_NR(s->card->dmapages + (PAGE_SIZE << s->card->dmaorder) - 1);
+ for (map = MAP_NR(s->card->dmapages); map <= mapend; map++)
+ clear_bit(PG_reserved, &mem_map[map].flags);
+
+ free_pages((unsigned long)s->card->dmapages,s->card->dmaorder);
+ s->card->dmapages = NULL;
+}
+
+static int
+ess_open(struct inode *inode, struct file *file)
{
int minor = MINOR(inode->i_rdev);
struct ess_card *c = devs;
@@ -2801,13 +2786,21 @@
return -ERESTARTSYS;
down(&s->open_sem);
}
+
+ /* under semaphore.. */
+ if ((s->card->dmapages==NULL) && allocate_buffers(s)) {
+ up(&s->open_sem);
+ return -ENOMEM;
+ }
+
if (file->f_mode & FMODE_READ) {
/*
fmtm &= ~((ESS_FMT_STEREO | ESS_FMT_16BIT) << ESS_ADC_SHIFT);
if ((minor & 0xf) == SND_DEV_DSP16)
fmts |= ESS_FMT_16BIT << ESS_ADC_SHIFT; */
- fmtm = (ESS_FMT_STEREO|ESS_FMT_16BIT) << ESS_ADC_SHIFT;
+ fmtm &= ~((ESS_FMT_STEREO|ESS_FMT_16BIT) << ESS_ADC_SHIFT);
+ fmts = (ESS_FMT_STEREO|ESS_FMT_16BIT) << ESS_ADC_SHIFT;
s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0;
set_adc_rate(s, 8000);
@@ -2816,6 +2809,7 @@
fmtm &= ~((ESS_FMT_STEREO | ESS_FMT_16BIT) << ESS_DAC_SHIFT);
if ((minor & 0xf) == SND_DEV_DSP16)
fmts |= ESS_FMT_16BIT << ESS_DAC_SHIFT;
+
s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = s->dma_dac.subdivision = 0;
set_dac_rate(s, 8000);
}
@@ -2823,17 +2817,19 @@
s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
/* we're covered by the open_sem */
- if( ! s->card->bob_running )
+ if( ! s->card->dsps_open ) {
start_bob(s);
- s->card->bob_running++;
- M_printk("maestro: open, %d bobs now\n",s->card->bob_running);
+ }
+ s->card->dsps_open++;
+ M_printk("maestro: open, %d bobs now\n",s->card->dsps_open);
up(&s->open_sem);
MOD_INC_USE_COUNT;
return 0;
}
-static int ess_release(struct inode *inode, struct file *file)
+static int
+ess_release(struct inode *inode, struct file *file)
{
struct ess_state *s = (struct ess_state *)file->private_data;
@@ -2847,16 +2843,13 @@
if (file->f_mode & FMODE_READ) {
stop_adc(s);
}
-
- /* free our shared dma buffers */
- dealloc_dmabuf(&s->dma_adc);
- dealloc_dmabuf(&s->dma_dac);
s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
/* we're covered by the open_sem */
- M_printk("maestro: %d -1 bob clients\n",s->card->bob_running);
- if( --s->card->bob_running <= 0) {
+ M_printk("maestro: %d dsps now alive\n",s->card->dsps_open-1);
+ if( --s->card->dsps_open <= 0) {
stop_bob(s);
+ free_buffers(s);
}
up(&s->open_sem);
wake_up(&s->open_wait);
@@ -2864,7 +2857,7 @@
return 0;
}
-static /*const*/ struct file_operations ess_audio_fops = {
+static struct file_operations ess_audio_fops = {
&ess_llseek,
&ess_read,
&ess_write,
@@ -2919,17 +2912,10 @@
}
#endif
-void free_mixpage(struct ess_card *card) {
- if (card->mixpage) {
- /* undo marking the page as reserved */
- clear_bit(PG_reserved, &mem_map[MAP_NR(card->mixpage)].flags);
- /* free mixpage */
- free_pages((unsigned long)card->mixpage, 1);
- }
-}
/* --------------------------------------------------------------------- */
-static int maestro_install(struct pci_dev *pcidev, int card_type)
+static int
+maestro_install(struct pci_dev *pcidev, int card_type)
{
u16 w;
u32 n;
@@ -2970,26 +2956,16 @@
memset(card, 0, sizeof(*card));
- /* allocate a page for the input mixer APUs
- 512 * NR_DSPS must fit in here !!*/
- if(!(card->mixpage = (void *)__get_free_pages(GFP_KERNEL|GFP_DMA, 1)))
- {
- printk(KERN_WARNING "maestro: can't allocate mixer page.\n");
- kfree(card);
- return 0;
- }
-
#ifdef CONFIG_APM
printk("reg_callback: %d\n",apm_register_callback(maestro_apm_callback));
#endif
- /* mark the page reserved */
- set_bit(PG_reserved, &mem_map[MAP_NR(card->mixpage)].flags);
card->iobase = iobase;
card->card_type = card_type;
card->irq = pcidev->irq;
card->next = devs;
card->magic = ESS_CARD_MAGIC;
+ spin_lock_init(&card->lock);
devs = card;
/* init our groups of 6 apus */
@@ -2997,10 +2973,13 @@
{
struct ess_state *s=&card->channels[i];
+ s->index = i;
+
s->card = card;
init_waitqueue_head(&s->dma_adc.wait);
init_waitqueue_head(&s->dma_dac.wait);
init_waitqueue_head(&s->open_wait);
+ spin_lock_init(&ess->lock);
init_MUTEX(&s->open_sem);
s->magic = ESS_STATE_MAGIC;
@@ -3016,8 +2995,6 @@
/* register devices */
if ((s->dev_audio = register_sound_dsp(&ess_audio_fops, -1)) < 0)
break;
- /* divide the page into smaller chunks */
- s->mixbuf = card->mixpage + (i * 512);
}
num = i;
@@ -3174,7 +3151,6 @@
n&=~0x000F; /* ASSP off */
outl(n, iobase+0x34);
-
n=inl(iobase+0x34);
n|=(1<<29); /* Enable ring bus */
outl(n, iobase+0x34);
@@ -3220,7 +3196,6 @@
w|=(1<<0); /* SB IRQ on */
outw(w, iobase+0x18);
-
#if 0 /* asp crap */
outb(0, iobase+0xA4);
outb(3, iobase+0xA2);
@@ -3324,7 +3299,6 @@
if(s->dev_audio != -1)
unregister_sound_dsp(s->dev_audio);
}
- free_mixpage(card);
release_region(card->iobase, 256);
kfree(card);
return 0;
@@ -3334,6 +3308,7 @@
return 1;
}
+/* XXX __init ? */
#ifdef MODULE
int init_module(void)
#else
@@ -3349,13 +3324,21 @@
pcidev = NULL;
+ if (dsps_order < 0) {
+ dsps_order = 1;
+ printk(KERN_WARNING "maestro: clipping dsps_order to %d\n",dsps_order);
+ }
+ else if (dsps_order > MAX_DSP_ORDER) {
+ dsps_order = MAX_DSP_ORDER;
+ printk(KERN_WARNING "maestro: clipping dsps_order to %d\n",dsps_order);
+ }
+
/*
* Find the ESS Maestro 2.
*/
- while( (pcidev = pci_find_device(PCI_VENDOR_ESS, PCI_DEVICE_ID_ESS_ESS1968, pcidev))!=NULL
- &&
- ( maestro_install(pcidev, TYPE_MAESTRO2) )) {
+ while( (pcidev = pci_find_device(PCI_VENDOR_ESS, PCI_DEVICE_ID_ESS_ESS1968, pcidev))!=NULL ) {
+ if (maestro_install(pcidev, TYPE_MAESTRO2))
foundone=1;
}
@@ -3363,9 +3346,8 @@
* Find the ESS Maestro 2E
*/
- while((pcidev = pci_find_device(PCI_VENDOR_ESS, PCI_DEVICE_ID_ESS_ESS1978, pcidev))!=NULL
- &&
- ( maestro_install(pcidev, TYPE_MAESTRO2E) )) {
+ while( (pcidev = pci_find_device(PCI_VENDOR_ESS, PCI_DEVICE_ID_ESS_ESS1978, pcidev))!=NULL) {
+ if (maestro_install(pcidev, TYPE_MAESTRO2E))
foundone=1;
}
@@ -3373,24 +3355,25 @@
* ESS Maestro 1
*/
- while((pcidev = pci_find_device(PCI_VENDOR_ESS_OLD, PCI_DEVICE_ID_ESS_ESS0100, pcidev))!=NULL
- &&
- ( maestro_install(pcidev, TYPE_MAESTRO) )) {
+ while((pcidev = pci_find_device(PCI_VENDOR_ESS_OLD, PCI_DEVICE_ID_ESS_ESS0100, pcidev))!=NULL) {
+ if (maestro_install(pcidev, TYPE_MAESTRO))
foundone=1;
}
- if( ! foundone )
+ if( ! foundone ) {
+ printk("maestro: no devices found.\n");
return -ENODEV;
+ }
return 0;
}
/* --------------------------------------------------------------------- */
#ifdef MODULE
-
MODULE_AUTHOR("Zach Brown <zab@redhat.com>, Alan Cox <alan@redhat.com>");
MODULE_DESCRIPTION("ESS Maestro Driver");
#ifdef M_DEBUG
MODULE_PARM(debug,"i");
+MODULE_PARM(dsps_order,"i");
#endif
void cleanup_module(void)
@@ -3414,7 +3397,6 @@
if(ess->dev_audio != -1)
unregister_sound_dsp(ess->dev_audio);
}
- free_mixpage(s);
release_region(s->iobase, 256);
kfree(s);
}
@@ -3422,4 +3404,3 @@
}
#endif /* MODULE */
-
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)