summaryrefslogtreecommitdiffstats
path: root/drivers/sound
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sound')
-rw-r--r--drivers/sound/Config.in7
-rw-r--r--drivers/sound/ad1816.c30
-rw-r--r--drivers/sound/ad1848.c206
-rw-r--r--drivers/sound/ad1848_mixer.h64
-rw-r--r--drivers/sound/audio.c7
-rw-r--r--drivers/sound/awacs_defs.h64
-rw-r--r--drivers/sound/dev_table.c1
-rw-r--r--drivers/sound/dev_table.h1
-rw-r--r--drivers/sound/dmabuf.c11
-rw-r--r--drivers/sound/dmasound.c654
-rw-r--r--drivers/sound/es1370.c71
-rw-r--r--drivers/sound/es1371.c61
-rw-r--r--drivers/sound/gus_card.c5
-rw-r--r--drivers/sound/lowlevel/awe_compat.h23
-rw-r--r--drivers/sound/lowlevel/awe_wave.c68
-rw-r--r--drivers/sound/mad16.c2
-rw-r--r--drivers/sound/midi_synth.c19
-rw-r--r--drivers/sound/sb.h25
-rw-r--r--drivers/sound/sb_card.c25
-rw-r--r--drivers/sound/sb_common.c71
-rw-r--r--drivers/sound/sb_ess.c241
-rw-r--r--drivers/sound/sb_mixer.c2
-rw-r--r--drivers/sound/sequencer.c6
-rw-r--r--drivers/sound/sonicvibes.c88
-rw-r--r--drivers/sound/sound_core.c11
-rw-r--r--drivers/sound/soundcard.c27
-rw-r--r--drivers/sound/sscape.c4
-rw-r--r--drivers/sound/sys_timer.c13
-rw-r--r--drivers/sound/trix.c2
29 files changed, 1327 insertions, 482 deletions
diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in
index 6b176afb8..ebc695d0c 100644
--- a/drivers/sound/Config.in
+++ b/drivers/sound/Config.in
@@ -13,7 +13,7 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
dep_tristate 'Ensoniq AudioPCI (ES1370)' CONFIG_SOUND_ES1370 $CONFIG_SOUND
if [ "$CONFIG_SOUND_ES1370" = "y" ]; then
bool 'Joystick support at boot time' CONFIG_SOUND_ES1370_JOYPORT_BOOT
- fi
+ fi
dep_tristate 'Creative Ensoniq AudioPCI 97 (ES1371)' CONFIG_SOUND_ES1371 $CONFIG_SOUND
fi
dep_tristate 'S3 SonicVibes' CONFIG_SOUND_SONICVIBES $CONFIG_SOUND
@@ -71,6 +71,10 @@ fi
dep_tristate 'OSS sound modules' CONFIG_SOUND_OSS $CONFIG_SOUND
if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
+ if [ "$CONFIG_SOUND_OSS" = "y" ]; then
+ bool 'Persistent DMA buffers' CONFIG_SOUND_DMAP
+ fi
+
dep_tristate 'ProAudioSpectrum 16 support' CONFIG_SOUND_PAS $CONFIG_SOUND_OSS
if [ "$CONFIG_SOUND_PAS" = "y" ]; then
int 'PAS16 IRQ 3, 4, 5, 7, 9, 10, 11, 12, 14 or 15' CONFIG_PAS_IRQ 10
@@ -134,6 +138,7 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
dep_tristate 'Microsoft Sound System support' CONFIG_SOUND_MSS $CONFIG_SOUND_OSS
if [ "$CONFIG_SOUND_MSS" = "y" ]; then
+ bool 'Enable support for the SoundPro mixer' CONFIG_SOUND_SPRO
hex 'MSS/WSS I/O base 530, 604, E80 or F40' CONFIG_MSS_BASE 530
int 'MSS/WSS IRQ 7, 9, 10 or 11' CONFIG_MSS_IRQ 11
int 'MSS/WSS DMA 0, 1 or 3' CONFIG_MSS_DMA 3
diff --git a/drivers/sound/ad1816.c b/drivers/sound/ad1816.c
index 6d7c2e13e..c94481524 100644
--- a/drivers/sound/ad1816.c
+++ b/drivers/sound/ad1816.c
@@ -32,10 +32,10 @@ Please report any bugs to: tek@rbg.informatik.tu-darmstadt.de
-------------------------------------------------------------------------------
-version: 1.2
-cvs: $Header: /home/tek/tmp/CVSROOT/sound21/ad1816.c,v 1.28 1999/01/16 19:01:36 tek Exp $
+version: 1.3
+cvs: $Header: /home/tek/CVSROOT/sound22/ad1816.c,v 1.3 1999/04/18 16:41:41 tek Exp $
status: experimental
-date: 1999/01/16
+date: 1999/4/18
Changes:
Oleg Drokin: Some cleanup of load/unload functions. 1998/11/24
@@ -44,6 +44,13 @@ Changes:
some argument checks added 1998/11/30
Thorsten Knabe: Buggy isa bridge workaround added 1999/01/16
+
+ David Moews/Thorsten Knabe: Introduced options
+ parameter. Added slightly modified patch from
+ David Moews to disable dsp audio sources by setting
+ bit 0 of options parameter. This seems to be
+ required by some Aztech/Newcom SC-16 cards. 1999/04/18
+
*/
#include <linux/config.h>
@@ -100,6 +107,8 @@ static int nr_ad1816_devs = 0;
static int ad1816_clockfreq=33000;
+static int options=0;
+
/* for backward mapping of irq to sound device */
static volatile char irq2dev[17] = {-1, -1, -1, -1, -1, -1, -1, -1,
@@ -1091,12 +1100,14 @@ int probe_ad1816 ( struct address_info *hw_config )
int tmp;
printk("ad1816: AD1816 sounddriver Copyright (C) 1998 by Thorsten Knabe\n");
- printk("ad1816: $Header: /home/tek/tmp/CVSROOT/sound21/ad1816.c,v 1.28 1999/01/16 19:01:36 tek Exp $\n");
- printk("ad1816: io=0x%x, irq=%d, dma=%d, dma2=%d, isadmabug=%d\n",
+ printk("ad1816: $Header: /home/tek/CVSROOT/sound22/ad1816.c,v 1.3 1999/04/18 16:41:41 tek Exp $\n");
+ printk("ad1816: io=0x%x, irq=%d, dma=%d, dma2=%d, clockfreq=%d, options=%d isadmabug=%d\n",
hw_config->io_base,
hw_config->irq,
hw_config->dma,
hw_config->dma2,
+ ad1816_clockfreq,
+ options,
isa_dma_bridge_buggy);
if (check_region (io_base, 16)) {
@@ -1264,7 +1275,11 @@ void attach_ad1816 (struct address_info *hw_config)
nr_ad1816_devs++;
ad_write(devc,32,0x80f0); /* sound system mode */
- ad_write(devc,33,0x03f8); /* enable all audiosources for dsp */
+ if (options&1) {
+ ad_write(devc,33,0); /* disable all audiosources for dsp */
+ } else {
+ ad_write(devc,33,0x03f8); /* enable all audiosources for dsp */
+ }
ad_write(devc,4,0x8080); /* default values for volumes (muted)*/
ad_write(devc,5,0x8080);
ad_write(devc,6,0x8080);
@@ -1274,7 +1289,7 @@ void attach_ad1816 (struct address_info *hw_config)
ad_write(devc,17,0x8888);
ad_write(devc,18,0x8888);
ad_write(devc,19,0xc888); /* +20db mic active */
- ad_write(devc,14,0x0000); /* Master volume unmuted full power */
+ ad_write(devc,14,0x0000); /* Master volume unmuted */
ad_write(devc,39,0x009f); /* 3D effect on 0% phone out muted */
ad_write(devc,44,0x0080); /* everything on power, 3d enabled for d/a */
outb(0x10,devc->base+8); /* set dma mode */
@@ -1382,6 +1397,7 @@ MODULE_PARM(irq,"i");
MODULE_PARM(dma,"i");
MODULE_PARM(dma2,"i");
MODULE_PARM(ad1816_clockfreq,"i");
+MODULE_PARM(options,"i");
struct address_info cfg;
diff --git a/drivers/sound/ad1848.c b/drivers/sound/ad1848.c
index 709d7f2ed..baa090771 100644
--- a/drivers/sound/ad1848.c
+++ b/drivers/sound/ad1848.c
@@ -100,6 +100,11 @@ ad1848_port_info;
static int nr_ad1848_devs = 0;
int deskpro_xl = 0;
+#ifdef CONFIG_SOUND_SPRO
+int soundpro = 1;
+#else
+int soundpro = 0;
+#endif
static volatile char irq2dev[17] = {
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -132,6 +137,21 @@ static ad1848_info adev_info[MAX_AUDIO_DEV];
#define io_Status(d) ((d)->base+2)
#define io_Polled_IO(d) ((d)->base+3)
+static struct {
+ unsigned char flags;
+#define CAP_F_TIMER 0x01
+} capabilities [9 /*devc->model */ ] = {
+ {0}
+ ,{0} /* MD_1848 */
+ ,{CAP_F_TIMER} /* MD_4231 */
+ ,{CAP_F_TIMER} /* MD_4231A */
+ ,{CAP_F_TIMER} /* MD_1845 */
+ ,{CAP_F_TIMER} /* MD_4232 */
+ ,{0} /* MD_C930 */
+ ,{CAP_F_TIMER} /* MD_IWAVE */
+ ,{0} /* MD_4235 */
+};
+
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);
@@ -312,22 +332,21 @@ static int ad1848_set_recmask(ad1848_info * devc, int mask)
if (mask & (1 << i))
n++;
- if (n == 0)
- mask = SOUND_MASK_MIC;
- else if (n != 1) /* Too many devices selected */
- {
- mask &= ~devc->recmask; /* Filter out active settings */
+ if (!soundpro) {
+ if (n == 0)
+ mask = SOUND_MASK_MIC;
+ else if (n != 1) { /* Too many devices selected */
+ mask &= ~devc->recmask; /* Filter out active settings */
- n = 0;
- for (i = 0; i < 32; i++) /* Count selected device bits */
- if (mask & (1 << i))
- n++;
+ n = 0;
+ for (i = 0; i < 32; i++) /* Count selected device bits */
+ if (mask & (1 << i))
+ n++;
- if (n != 1)
- mask = SOUND_MASK_MIC;
- }
- switch (mask)
- {
+ if (n != 1)
+ mask = SOUND_MASK_MIC;
+ }
+ switch (mask) {
case SOUND_MASK_MIC:
recdev = 2;
break;
@@ -349,11 +368,38 @@ static int ad1848_set_recmask(ad1848_info * devc, int mask)
default:
mask = SOUND_MASK_MIC;
recdev = 2;
- }
+ }
+
+ recdev <<= 6;
+ ad_write(devc, 0, (ad_read(devc, 0) & 0x3f) | recdev);
+ ad_write(devc, 1, (ad_read(devc, 1) & 0x3f) | recdev);
+ } else { /* soundpro */
+ unsigned char val;
+ int set_rec_bit;
+ int j;
+
+ for (i = 0; i < 32; i++) { /* For each bit */
+ if ((devc->supported_rec_devices & (1 << i)) == 0)
+ continue; /* Device not supported */
+
+ for (j = LEFT_CHN; j <= RIGHT_CHN; j++) {
+ if (devc->mix_devices[i][j].nbits == 0) /* Inexistent channel */
+ continue;
+
+ /*
+ * This is tricky:
+ * set_rec_bit becomes 1 if the corresponding bit in mask is set
+ * then it gets flipped if the polarity is inverse
+ */
+ set_rec_bit = ((mask & (1 << i)) != 0) ^ devc->mix_devices[i][j].recpol;
- recdev <<= 6;
- ad_write(devc, 0, (ad_read(devc, 0) & 0x3f) | recdev);
- ad_write(devc, 1, (ad_read(devc, 1) & 0x3f) | recdev);
+ val = ad_read(devc, devc->mix_devices[i][j].recreg);
+ val &= ~(1 << devc->mix_devices[i][j].recpos);
+ val |= (set_rec_bit << devc->mix_devices[i][j].recpos);
+ ad_write(devc, devc->mix_devices[i][j].recreg, val);
+ }
+ }
+ }
/* Rename the mixer bits back if necessary */
for (i = 0; i < 32; i++)
@@ -371,7 +417,8 @@ static int ad1848_set_recmask(ad1848_info * devc, int mask)
return mask;
}
-static void change_bits(ad1848_info * devc, unsigned char *regval, int dev, int chn, int newval)
+static void change_bits(ad1848_info * devc, unsigned char *regval,
+ unsigned char *muteval, int dev, int chn, int newval)
{
unsigned char mask;
int shift;
@@ -379,7 +426,7 @@ static void change_bits(ad1848_info * devc, unsigned char *regval, int dev, int
int mutemask;
int set_mute_bit;
- set_mute_bit = (newval == 0);
+ set_mute_bit = (newval == 0) ^ devc->mix_devices[dev][chn].mutepol;
if (devc->mix_devices[dev][chn].polarity == 1) /* Reverse */
newval = 100 - newval;
@@ -399,8 +446,11 @@ static void change_bits(ad1848_info * devc, unsigned char *regval, int dev, int
}
newval = (int) ((newval * mask) + 50) / 100; /* Scale it */
- *regval &= (~(mask << shift)) & (mutemask); /* Clear bits */
- *regval |= ((newval & mask) << shift) | mute; /* Set new value */
+ *regval &= ~(mask << shift); /* Clear bits */
+ *regval |= (newval & mask) << shift; /* Set new value */
+
+ *muteval &= mutemask;
+ *muteval |= mute;
}
static int ad1848_mixer_get(ad1848_info * devc, int dev)
@@ -413,15 +463,36 @@ static int ad1848_mixer_get(ad1848_info * devc, int dev)
return devc->levels[dev];
}
+static void ad1848_mixer_set_channel(ad1848_info *devc, int dev, int value, int channel)
+{
+ int regoffs, muteregoffs;
+ unsigned char val, muteval;
+
+ regoffs = devc->mix_devices[dev][channel].regno;
+ muteregoffs = devc->mix_devices[dev][channel].mutereg;
+ val = ad_read(devc, regoffs);
+
+ if (muteregoffs != regoffs) {
+ muteval = ad_read(devc, muteregoffs);
+ change_bits(devc, &val, &muteval, dev, channel, value);
+ }
+ else
+ change_bits(devc, &val, &val, dev, channel, value);
+
+ ad_write(devc, regoffs, val);
+ devc->saved_regs[regoffs] = val;
+ if (muteregoffs != regoffs) {
+ ad_write(devc, muteregoffs, muteval);
+ devc->saved_regs[muteregoffs] = muteval;
+ }
+}
+
static int ad1848_mixer_set(ad1848_info * devc, int dev, int value)
{
int left = value & 0x000000ff;
int right = (value & 0x0000ff00) >> 8;
int retvol;
- int regoffs;
- unsigned char val;
-
if (dev > 31)
return -EINVAL;
@@ -430,6 +501,9 @@ static int ad1848_mixer_set(ad1848_info * devc, int dev, int value)
dev = devc->mixer_reroute[dev];
+ if (devc->mix_devices[dev][LEFT_CHN].nbits == 0)
+ return -EINVAL;
+
if (left > 100)
left = 100;
if (right > 100)
@@ -444,34 +518,21 @@ static int ad1848_mixer_set(ad1848_info * devc, int dev, int value)
left = mix_cvt[left];
right = mix_cvt[right];
- if (devc->mix_devices[dev][LEFT_CHN].nbits == 0)
- return -EINVAL;
-
devc->levels[dev] = retvol;
/*
* Set the left channel
*/
-
- regoffs = devc->mix_devices[dev][LEFT_CHN].regno;
- val = ad_read(devc, regoffs);
- change_bits(devc, &val, dev, LEFT_CHN, left);
- ad_write(devc, regoffs, val);
- devc->saved_regs[regoffs] = val;
+ ad1848_mixer_set_channel(devc, dev, left, LEFT_CHN);
/*
* Set the right channel
*/
-
if (devc->mix_devices[dev][RIGHT_CHN].nbits == 0)
- return retvol; /* Was just a mono channel */
-
- regoffs = devc->mix_devices[dev][RIGHT_CHN].regno;
- val = ad_read(devc, regoffs);
- change_bits(devc, &val, dev, RIGHT_CHN, right);
- ad_write(devc, regoffs, val);
- devc->saved_regs[regoffs] = val;
+ goto out;
+ ad1848_mixer_set_channel(devc, dev, right, RIGHT_CHN);
+ out:
return retvol;
}
@@ -487,6 +548,8 @@ static void ad1848_mixer_reset(ad1848_info * devc)
for (i = 0; i < 32; i++)
devc->mixer_reroute[i] = i;
+ devc->supported_rec_devices = MODE1_REC_DEVICES;
+
switch (devc->model)
{
case MD_4231:
@@ -509,11 +572,18 @@ static void ad1848_mixer_reset(ad1848_info * devc)
devc->supported_devices = MODE3_MIXER_DEVICES;
break;
+ case MD_1848:
+ if (soundpro) {
+ devc->supported_devices = SPRO_MIXER_DEVICES;
+ devc->supported_rec_devices = SPRO_REC_DEVICES;
+ devc->mix_devices = &(spro_mix_devices[0]);
+ break;
+ }
+
default:
devc->supported_devices = MODE1_MIXER_DEVICES;
}
- devc->supported_rec_devices = MODE1_REC_DEVICES;
devc->orig_devices = devc->supported_devices;
devc->orig_rec_devices = devc->supported_rec_devices;
@@ -528,10 +598,20 @@ static void ad1848_mixer_reset(ad1848_info * devc)
ad1848_set_recmask(devc, SOUND_MASK_MIC);
devc->mixer_output_port = devc->levels[31] | AUDIO_HEADPHONE | AUDIO_LINE_OUT;
- if (devc->mixer_output_port & 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 */
+
+ if (!soundpro) {
+ if (devc->mixer_output_port & 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 */
+ } else {
+ /*
+ * From the "wouldn't it be nice if the mixer API had (better)
+ * support for custom stuff" category
+ */
+ /* Enable surround mode and SB16 mixer */
+ ad_write(devc, 16, 0x60);
+ }
}
static int ad1848_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
@@ -1357,6 +1437,8 @@ static void ad1848_init_hw(ad1848_info * devc)
{
devc->audio_flags &= ~DMA_DUPLEX;
ad_write(devc, 9, ad_read(devc, 9) | 0x04); /* Single DMA mode */
+ if (soundpro)
+ ad_write(devc, 12, ad_read(devc, 12) | 0x40); /* Mode2 = enabled */
}
outb((0), io_Status(devc)); /* Clear pending interrupts */
@@ -1706,7 +1788,27 @@ int ad1848_detect(int io_base, int *ad_flags, int *osp)
DDB(printk("ad1848_detect() - step K\n"));
}
+ } else if (tmp1 == 0x0a) {
+ /*
+ * Is it perhaps a SoundPro CMI8330?
+ * If so, then we should be able to change indirect registers
+ * greater than I15 after activating MODE2, even though reading
+ * back I12 does not show it.
+ */
+
+ /*
+ * Let's try comparing register values
+ */
+ for (i = 0; i < 16; i++) {
+ if ((tmp1 = ad_read(devc, i)) != (tmp2 = ad_read(devc, i + 16))) {
+ DDB(printk("ad1848 detect step H(%d/%x/%x) - SoundPro chip?\n", i, tmp1, tmp2));
+ soundpro = 1;
+ devc->chip_name = "SoundPro CMI 8330";
+ break;
+ }
+ }
}
+
DDB(printk("ad1848_detect() - step L\n"));
if (ad_flags)
{
@@ -1807,7 +1909,7 @@ int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capt
/* Don't free it either then.. */
devc->irq = 0;
}
- if (devc->model != MD_1848 && devc->model != MD_C930)
+ if (capabilities[devc->model].flags & CAP_F_TIMER)
{
#ifndef __SMP__
int x;
@@ -1840,8 +1942,8 @@ int ad1848_init(char *name, int io_base, int irq, int dma_playback, int dma_capt
irq2dev[-irq] = devc->dev_no = my_dev;
#if defined(CONFIG_SEQUENCER) && !defined(EXCLUDE_TIMERS)
- if (devc->model != MD_1848 &&
- devc->model != MD_C930 && devc->irq_ok)
+ if ((capabilities[devc->model].flags & CAP_F_TIMER) &&
+ devc->irq_ok)
ad1848_tmr_install(my_dev);
#endif
@@ -2302,7 +2404,8 @@ int probe_ms_sound(struct address_info *hw_config)
(hw_config->irq != 7) &&
(hw_config->irq != 9) &&
(hw_config->irq != 10) &&
- (hw_config->irq != 11))
+ (hw_config->irq != 11) &&
+ (hw_config->irq != 12))
{
printk(KERN_ERR "MSS: Bad IRQ %d\n", hw_config->irq);
return 0;
@@ -2555,6 +2658,7 @@ MODULE_PARM(dma, "i"); /* First DMA channel */
MODULE_PARM(dma2, "i"); /* Second DMA channel */
MODULE_PARM(type, "i"); /* Card type */
MODULE_PARM(deskpro_xl, "i"); /* Special magic for Deskpro XL boxen */
+MODULE_PARM(soundpro, "i"); /* More special magic for SoundPro chips */
int io = -1;
int irq = -1;
diff --git a/drivers/sound/ad1848_mixer.h b/drivers/sound/ad1848_mixer.h
index 5768420a9..fdd06e499 100644
--- a/drivers/sound/ad1848_mixer.h
+++ b/drivers/sound/ad1848_mixer.h
@@ -24,7 +24,10 @@
* solution).
*/
#define MODE1_REC_DEVICES (SOUND_MASK_LINE3 | SOUND_MASK_MIC | \
- SOUND_MASK_LINE1|SOUND_MASK_IMIX)
+ SOUND_MASK_LINE1 | SOUND_MASK_IMIX)
+
+#define SPRO_REC_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \
+ SOUND_MASK_CD | SOUND_MASK_LINE1)
#define MODE1_MIXER_DEVICES (SOUND_MASK_LINE1 | SOUND_MASK_MIC | \
SOUND_MASK_LINE2 | \
@@ -47,16 +50,27 @@
SOUND_MASK_LINE3 | \
SOUND_MASK_IGAIN | SOUND_MASK_PCM)
+#define SPRO_MIXER_DEVICES (SOUND_MASK_VOLUME | SOUND_MASK_PCM | \
+ SOUND_MASK_LINE | SOUND_MASK_SYNTH | \
+ SOUND_MASK_CD | SOUND_MASK_MIC | \
+ SOUND_MASK_SPEAKER | SOUND_MASK_LINE1 | \
+ SOUND_MASK_OGAIN)
+
struct mixer_def {
- unsigned int regno: 5;
- unsigned int polarity:1; /* 0=normal, 1=reversed */
- unsigned int bitpos:3;
- unsigned int nbits:3;
- unsigned int mutepos:4;
+ unsigned int regno:5; /* register number for volume */
+ unsigned int polarity:1; /* volume polarity: 0=normal, 1=reversed */
+ unsigned int bitpos:3; /* position of bits in register for volume */
+ unsigned int nbits:3; /* number of bits in register for volume */
+ unsigned int mutereg:5; /* register number for mute bit */
+ unsigned int mutepol:1; /* mute polarity: 0=normal, 1=reversed */
+ unsigned int mutepos:4; /* position of mute bit in register */
+ unsigned int recreg:5; /* register number for recording bit */
+ unsigned int recpol:1; /* recording polarity: 0=normal, 1=reversed */
+ unsigned int recpos:4; /* position of recording bit in register */
};
static char mix_cvt[101] = {
- 0, 0,3,7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
+ 0, 0, 3, 7,10,13,16,19,21,23,26,28,30,32,34,35,37,39,40,42,
43,45,46,47,49,50,51,52,53,55,56,57,58,59,60,61,62,63,64,65,
65,66,67,68,69,70,70,71,72,73,73,74,75,75,76,77,77,78,79,79,
80,81,81,82,82,83,84,84,85,85,86,86,87,87,88,88,89,89,90,90,
@@ -77,7 +91,17 @@ typedef mixer_ent mixer_ents[2];
*/
#define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r, mute_bit) \
- {{reg_l, pola_l, pos_l, len_l, mute_bit}, {reg_r, pola_r, pos_r, len_r, mute_bit}}
+ [name] = {{reg_l, pola_l, pos_l, len_l, reg_l, 0, mute_bit, 0, 0, 8}, \
+ {reg_r, pola_r, pos_r, len_r, reg_r, 0, mute_bit, 0, 0, 8}}
+
+#define MIX_ENT2(name, reg_l, pola_l, pos_l, len_l, mute_reg_l, mute_pola_l, mute_pos_l, \
+ rec_reg_l, rec_pola_l, rec_pos_l, \
+ reg_r, pola_r, pos_r, len_r, mute_reg_r, mute_pola_r, mute_pos_r, \
+ rec_reg_r, rec_pola_r, rec_pos_r) \
+ [name] = {{reg_l, pola_l, pos_l, len_l, mute_reg_l, mute_pola_l, mute_pos_l, \
+ rec_reg_l, rec_pola_l, rec_pos_l}, \
+ {reg_r, pola_r, pos_r, len_r, mute_reg_r, mute_pola_r, mute_pos_r, \
+ rec_reg_r, rec_pola_r, rec_pos_r}}
static mixer_ents ad1848_mix_devices[32] = {
MIX_ENT(SOUND_MIXER_VOLUME, 27, 1, 0, 4, 29, 1, 0, 4, 8),
@@ -144,6 +168,30 @@ MIX_ENT(SOUND_MIXER_LINE2, 4, 1, 1, 4, 5, 1, 1, 4, 7),
MIX_ENT(SOUND_MIXER_LINE3, 18, 1, 1, 4, 19, 1, 1, 4, 7)
};
+static mixer_ents spro_mix_devices[32] = {
+MIX_ENT (SOUND_MIXER_VOLUME, 19, 0, 4, 4, 19, 0, 0, 4, 8),
+MIX_ENT (SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT (SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT2(SOUND_MIXER_SYNTH, 4, 1, 1, 4, 23, 0, 3, 0, 0, 8,
+ 5, 1, 1, 4, 23, 0, 3, 0, 0, 8),
+MIX_ENT (SOUND_MIXER_PCM, 6, 1, 1, 4, 7, 1, 1, 4, 8),
+MIX_ENT (SOUND_MIXER_SPEAKER, 18, 0, 3, 2, 0, 0, 0, 0, 8),
+MIX_ENT2(SOUND_MIXER_LINE, 20, 0, 4, 4, 17, 1, 4, 16, 0, 2,
+ 20, 0, 0, 4, 17, 1, 3, 16, 0, 1),
+MIX_ENT2(SOUND_MIXER_MIC, 18, 0, 0, 3, 17, 1, 0, 16, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
+MIX_ENT2(SOUND_MIXER_CD, 21, 0, 4, 4, 17, 1, 2, 16, 0, 4,
+ 21, 0, 0, 4, 17, 1, 1, 16, 0, 3),
+MIX_ENT (SOUND_MIXER_IMIX, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT (SOUND_MIXER_ALTPCM, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT (SOUND_MIXER_RECLEV, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT (SOUND_MIXER_IGAIN, 0, 0, 0, 0, 0, 0, 0, 0, 8),
+MIX_ENT (SOUND_MIXER_OGAIN, 17, 1, 6, 1, 0, 0, 0, 0, 8),
+/* This is external wavetable */
+MIX_ENT2(SOUND_MIXER_LINE1, 22, 0, 4, 4, 23, 1, 1, 23, 0, 4,
+ 22, 0, 0, 4, 23, 1, 0, 23, 0, 5),
+};
+
static int default_mixer_levels[32] =
{
0x3232, /* Master Volume */
diff --git a/drivers/sound/audio.c b/drivers/sound/audio.c
index 605a03ba5..ac2b6d40a 100644
--- a/drivers/sound/audio.c
+++ b/drivers/sound/audio.c
@@ -60,7 +60,10 @@ static int set_format(int dev, int fmt)
else
return audio_devs[dev]->local_format;
- return audio_devs[dev]->local_format;
+ if (audio_devs[dev]->local_conversion)
+ return audio_devs[dev]->local_conversion;
+ else
+ return audio_devs[dev]->local_format;
}
int audio_open(int dev, struct file *file)
@@ -387,7 +390,7 @@ int audio_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
return 0;
case SNDCTL_DSP_GETFMTS:
- val = audio_devs[dev]->format_mask;
+ val = audio_devs[dev]->format_mask | AFMT_MU_LAW;
break;
case SNDCTL_DSP_SETFMT:
diff --git a/drivers/sound/awacs_defs.h b/drivers/sound/awacs_defs.h
index c84e24ff0..e30bb608c 100644
--- a/drivers/sound/awacs_defs.h
+++ b/drivers/sound/awacs_defs.h
@@ -157,4 +157,68 @@ struct awacs_regs {
#define RATE_LOW 1 /* HIGH = 48kHz, etc; LOW = 44.1kHz, etc. */
+
+/* Burgundy values */
+
+#define MASK_ADDR_BURGUNDY_INPSEL21 (0x11 << 12)
+#define MASK_ADDR_BURGUNDY_INPSEL3 (0x12 << 12)
+
+#define MASK_ADDR_BURGUNDY_GAINCH1 (0x13 << 12)
+#define MASK_ADDR_BURGUNDY_GAINCH2 (0x14 << 12)
+#define MASK_ADDR_BURGUNDY_GAINCH3 (0x15 << 12)
+#define MASK_ADDR_BURGUNDY_GAINCH4 (0x16 << 12)
+
+#define MASK_ADDR_BURGUNDY_VOLCH1 (0x20 << 12)
+#define MASK_ADDR_BURGUNDY_VOLCH2 (0x21 << 12)
+#define MASK_ADDR_BURGUNDY_VOLCH3 (0x22 << 12)
+#define MASK_ADDR_BURGUNDY_VOLCH4 (0x23 << 12)
+
+#define MASK_ADDR_BURGUNDY_OUTPUTSELECTS (0x2B << 12)
+#define MASK_ADDR_BURGUNDY_OUTPUTENABLES (0x2F << 12)
+
+#define MASK_ADDR_BURGUNDY_MASTER_VOLUME (0x30 << 12)
+
+#define MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES (0x60 << 12)
+
+#define MASK_ADDR_BURGUNDY_ATTENSPEAKER (0x62 << 12)
+#define MASK_ADDR_BURGUNDY_ATTENLINEOUT (0x63 << 12)
+#define MASK_ADDR_BURGUNDY_ATTENHP (0x64 << 12)
+
+#define MASK_ADDR_BURGUNDY_VOLCD (MASK_ADDR_BURGUNDY_VOLCH1)
+#define MASK_ADDR_BURGUNDY_VOLLINE (MASK_ADDR_BURGUNDY_VOLCH2)
+#define MASK_ADDR_BURGUNDY_VOLMIC (MASK_ADDR_BURGUNDY_VOLCH3)
+#define MASK_ADDR_BURGUNDY_VOLMODEM (MASK_ADDR_BURGUNDY_VOLCH4)
+
+#define MASK_ADDR_BURGUNDY_GAINCD (MASK_ADDR_BURGUNDY_GAINCH1)
+#define MASK_ADDR_BURGUNDY_GAINLINE (MASK_ADDR_BURGUNDY_GAINCH2)
+#define MASK_ADDR_BURGUNDY_GAINMIC (MASK_ADDR_BURGUNDY_GAINCH3)
+#define MASK_ADDR_BURGUNDY_GAINMODEM (MASK_ADDR_BURGUNDY_VOLCH4)
+
+
+/* These are all default values for the burgundy */
+#define DEF_BURGUNDY_INPSEL21 (0xAA)
+#define DEF_BURGUNDY_INPSEL3 (0x0A)
+
+#define DEF_BURGUNDY_GAINCD (0x33)
+#define DEF_BURGUNDY_GAINLINE (0x44)
+#define DEF_BURGUNDY_GAINMIC (0x44)
+#define DEF_BURGUNDY_GAINMODEM (0x06)
+
+/* Remember: lowest volume here is 0x9b */
+#define DEF_BURGUNDY_VOLCD (0xCCCCCCCC)
+#define DEF_BURGUNDY_VOLLINE (0x00000000)
+#define DEF_BURGUNDY_VOLMIC (0x00000000)
+#define DEF_BURGUNDY_VOLMODEM (0xCCCCCCCC)
+
+#define DEF_BURGUNDY_OUTPUTSELECTS (0x010f010f)
+#define DEF_BURGUNDY_OUTPUTENABLES (0x0A)
+
+#define DEF_BURGUNDY_MASTER_VOLUME (0xFFFFFFFF)
+
+#define DEF_BURGUNDY_MORE_OUTPUTENABLES (0x7E)
+
+#define DEF_BURGUNDY_ATTENSPEAKER (0x44)
+#define DEF_BURGUNDY_ATTENLINEOUT (0xCC)
+#define DEF_BURGUNDY_ATTENHP (0xCC)
+
#endif /* _AWACS_DEFS_H_ */
diff --git a/drivers/sound/dev_table.c b/drivers/sound/dev_table.c
index 9a6b4c72f..dd12a0c68 100644
--- a/drivers/sound/dev_table.c
+++ b/drivers/sound/dev_table.c
@@ -437,6 +437,7 @@ int sound_install_audiodrv(int vers, char *name, struct audio_driver *driver,
memset((char *) op, 0, sizeof(struct audio_operations));
init_waitqueue(&op->in_sleeper);
init_waitqueue(&op->out_sleeper);
+ init_waitqueue(&op->poll_sleeper);
if (driver_size < sizeof(struct audio_driver))
memset((char *) d, 0, sizeof(struct audio_driver));
diff --git a/drivers/sound/dev_table.h b/drivers/sound/dev_table.h
index 019b915c5..cf6475662 100644
--- a/drivers/sound/dev_table.h
+++ b/drivers/sound/dev_table.h
@@ -236,6 +236,7 @@ struct audio_operations
/* fields formerly in dmabuf.c */
struct wait_queue *in_sleeper;
struct wait_queue *out_sleeper;
+ struct wait_queue *poll_sleeper;
/* fields formerly in audio.c */
int audio_mode;
diff --git a/drivers/sound/dmabuf.c b/drivers/sound/dmabuf.c
index ccde8519a..85bde7d48 100644
--- a/drivers/sound/dmabuf.c
+++ b/drivers/sound/dmabuf.c
@@ -935,6 +935,7 @@ static void finish_output_interrupt(int dev, struct dma_buffparms *dmap)
if (dmap->audio_callback != NULL)
dmap->audio_callback(dev, dmap->callback_parm);
wake_up(&adev->out_sleeper);
+ wake_up(&adev->poll_sleeper);
}
static void do_outputintr(int dev, int dummy)
@@ -1103,7 +1104,10 @@ static void do_inputintr(int dev)
}
dmap->flags |= DMA_ACTIVE;
if (dmap->qlen > 0)
+ {
wake_up(&adev->in_sleeper);
+ wake_up(&adev->poll_sleeper);
+ }
}
void DMAbuf_inputintr(int dev)
@@ -1217,7 +1221,6 @@ static unsigned int poll_input(struct file * file, int dev, poll_table *wait)
if (!(adev->open_mode & OPEN_READ))
return 0;
if (dmap->mapping_flags & DMA_MAP_MAPPED) {
- poll_wait(file, &adev->in_sleeper, wait);
if (dmap->qlen)
return POLLIN | POLLRDNORM;
return 0;
@@ -1228,7 +1231,6 @@ static unsigned int poll_input(struct file * file, int dev, poll_table *wait)
!dmap->qlen && adev->go) {
unsigned long flags;
- poll_wait(file, &adev->in_sleeper, wait);
save_flags(flags);
cli();
DMAbuf_activate_recording(dev, dmap);
@@ -1236,7 +1238,6 @@ static unsigned int poll_input(struct file * file, int dev, poll_table *wait)
}
return 0;
}
- poll_wait(file, &adev->in_sleeper, wait);
if (!dmap->qlen)
return 0;
return POLLIN | POLLRDNORM;
@@ -1250,14 +1251,12 @@ static unsigned int poll_output(struct file * file, int dev, poll_table *wait)
if (!(adev->open_mode & OPEN_WRITE))
return 0;
if (dmap->mapping_flags & DMA_MAP_MAPPED) {
- poll_wait(file, &adev->out_sleeper, wait);
if (dmap->qlen)
return POLLOUT | POLLWRNORM;
return 0;
}
if (dmap->dma_mode == DMODE_INPUT)
return 0;
- poll_wait(file, &adev->out_sleeper, wait);
if (dmap->dma_mode == DMODE_NONE)
return POLLOUT | POLLWRNORM;
if (!DMAbuf_space_in_queue(dev))
@@ -1267,6 +1266,8 @@ static unsigned int poll_output(struct file * file, int dev, poll_table *wait)
unsigned int DMAbuf_poll(struct file * file, int dev, poll_table *wait)
{
+ struct audio_operations *adev = audio_devs[dev];
+ poll_wait(file, &adev->poll_sleeper, wait);
return poll_input(file, dev, wait) | poll_output(file, dev, wait);
}
diff --git a/drivers/sound/dmasound.c b/drivers/sound/dmasound.c
index 43b419817..5f96b3a42 100644
--- a/drivers/sound/dmasound.c
+++ b/drivers/sound/dmasound.c
@@ -173,9 +173,11 @@ static volatile struct awacs_regs *awacs;
static volatile struct dbdma_regs *awacs_txdma, *awacs_rxdma;
static int awacs_rate_index;
static int awacs_subframe;
-static int awacs_revision;
static int awacs_spkr_vol;
+static int awacs_revision;
+#define AWACS_BURGUNDY 100 /* fake revision # for burgundy */
+
/*
* Space for the DBDMA command blocks.
*/
@@ -184,6 +186,7 @@ static volatile struct dbdma_cmd *awacs_tx_cmds;
/*
* Cached values of AWACS registers (we can't read them).
+ * Except on the burgundy. XXX
*/
int awacs_reg[5];
@@ -240,6 +243,14 @@ static short *beep_buf;
static volatile struct dbdma_cmd *beep_dbdma_cmd;
static void (*orig_mksound)(unsigned int, unsigned int);
+/* Burgundy functions */
+static void awacs_burgundy_wcw(unsigned addr,unsigned newval);
+static unsigned awacs_burgundy_rcw(unsigned addr);
+static void awacs_burgundy_write_volume(unsigned address, int volume);
+static int awacs_burgundy_read_volume(unsigned address);
+static void awacs_burgundy_write_mvolume(unsigned address, int volume);
+static int awacs_burgundy_read_mvolume(unsigned address);
+
#ifdef CONFIG_PMAC_PBOOK
/*
* Stuff for restoring after a sleep.
@@ -3007,6 +3018,9 @@ static void PMacIrqCleanup(void)
if (beep_buf)
kfree(beep_buf);
kd_mksound = orig_mksound;
+#ifdef CONFIG_PMAC_PBOOK
+ notifier_chain_unregister(&sleep_notifier_list, &awacs_sleep_notifier);
+#endif
}
#endif /* MODULE */
@@ -3040,8 +3054,9 @@ static void PMacInit(void)
* If we have a sample rate which is within catchRadius percent
* of the requested value, we don't have to expand the samples.
* Otherwise choose the next higher rate.
+ * N.B.: burgundy awacs (iMac and later) only works at 44100 Hz.
*/
- i = 8;
+ i = (awacs_revision >= AWACS_BURGUNDY)? 1: 8;
do {
tolerance = catchRadius * awacs_freqs[--i] / 100;
} while (sound.soft.speed > awacs_freqs[i] + tolerance && i > 0);
@@ -3053,7 +3068,9 @@ static void PMacInit(void)
awacs_rate_index = i;
PMacSilence();
- out_le32(&awacs->control, MASK_IEPC | MASK_IEE | (i << 8) | 0x11);
+ /* XXX disable error interrupt on burgundy for now */
+ out_le32(&awacs->control, MASK_IEPC | (i << 8) | 0x11
+ | (awacs_revision < AWACS_BURGUNDY? MASK_IEE: 0));
awacs_reg[1] = (awacs_reg[1] & ~MASK_SAMPLERATE) | (i << 3);
awacs_write(awacs_reg[1] | MASK_ADDR1);
out_le32(&awacs->byteswap, sound.hard.format != AFMT_S16_BE);
@@ -3213,8 +3230,9 @@ pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs)
/* do something when headphone is plugged/unplugged? */
}
if (ctrl & MASK_CNTLERR) {
- printk(KERN_ERR "AWACS: error, status = %x\n",
- in_le32(&awacs->codec_stat));
+ int err = (in_le32(&awacs->codec_stat) & MASK_ERRCODE) >> 16;
+ if (err != 0 && awacs_revision < AWACS_BURGUNDY)
+ printk(KERN_ERR "AWACS: error %x\n", err);
}
/* Writing 1s to the CNTLERR and PORTCHG bits clears them... */
out_le32(&awacs->control, ctrl);
@@ -3223,6 +3241,8 @@ pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs)
static void
awacs_write(int val)
{
+ if (awacs_revision >= AWACS_BURGUNDY)
+ return;
while (in_le32(&awacs->codec_ctrl) & MASK_NEWECMD)
; /* XXX should have timeout */
out_le32(&awacs->codec_ctrl, val | (awacs_subframe << 22));
@@ -3247,7 +3267,8 @@ static struct timer_list beep_timer = {
static void awacs_mksound(unsigned int hz, unsigned int ticks)
{
unsigned long flags;
- int srate = awacs_freqs[BEEP_SPEED];
+ int beep_speed = (awacs_revision < AWACS_BURGUNDY)? BEEP_SPEED: 0;
+ int srate = awacs_freqs[beep_speed];
int period, ncycles, nsamples;
int i, j, f;
short *p;
@@ -3308,7 +3329,7 @@ static void awacs_mksound(unsigned int hz, unsigned int ticks)
out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16);
out_le32(&awacs->control,
(in_le32(&awacs->control) & ~0x1f00)
- | (BEEP_SPEED << 8));
+ | (beep_speed << 8));
out_le32(&awacs->byteswap, 0);
out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd));
out_le32(&awacs_txdma->control, RUN | (RUN << 16));
@@ -3330,8 +3351,9 @@ static int awacs_sleep_notify(struct notifier_block *this,
PMacSilence();
break;
case PBOOK_WAKE:
- out_le32(&awacs->control, MASK_IEPC | MASK_IEE |
- (awacs_rate_index << 8) | 0x11);
+ out_le32(&awacs->control, MASK_IEPC
+ | (awacs_rate_index << 8) | 0x11
+ | (awacs_revision < AWACS_BURGUNDY? MASK_IEE: 0));
awacs_write(awacs_reg[0] | MASK_ADDR0);
awacs_write(awacs_reg[1] | MASK_ADDR1);
awacs_write(awacs_reg[2] | MASK_ADDR2);
@@ -3342,6 +3364,220 @@ static int awacs_sleep_notify(struct notifier_block *this,
}
#endif /* CONFIG_PMAC_PBOOK */
+
+/* All the burgundy functions: */
+
+/* Waits for busy flag to clear */
+inline static void
+awacs_burgundy_busy_wait(void)
+{
+ while (in_le32(&awacs->codec_ctrl) & MASK_NEWECMD)
+ ;
+}
+
+inline static void
+awacs_burgundy_extend_wait(void)
+{
+ while (!(in_le32(&awacs->codec_stat) & MASK_EXTEND))
+ ;
+ while (in_le32(&awacs->codec_stat) & MASK_EXTEND)
+ ;
+}
+
+static void
+awacs_burgundy_wcw(unsigned addr, unsigned val)
+{
+ out_le32(&awacs->codec_ctrl, addr + 0x200c00 + (val & 0xff));
+ awacs_burgundy_busy_wait();
+ out_le32(&awacs->codec_ctrl, addr + 0x200d00 +((val>>8) & 0xff));
+ awacs_burgundy_busy_wait();
+ out_le32(&awacs->codec_ctrl, addr + 0x200e00 +((val>>16) & 0xff));
+ awacs_burgundy_busy_wait();
+ out_le32(&awacs->codec_ctrl, addr + 0x200f00 +((val>>24) & 0xff));
+ awacs_burgundy_busy_wait();
+}
+
+static unsigned
+awacs_burgundy_rcw(unsigned addr)
+{
+ unsigned val = 0;
+ int flags;
+
+ /* should have timeouts here */
+ save_flags(flags); cli();
+
+ out_le32(&awacs->codec_ctrl, addr + 0x100000);
+ awacs_burgundy_busy_wait();
+ awacs_burgundy_extend_wait();
+ val += (in_le32(&awacs->codec_stat) >> 4) & 0xff;
+
+ out_le32(&awacs->codec_ctrl, addr + 0x100100);
+ awacs_burgundy_busy_wait();
+ awacs_burgundy_extend_wait();
+ val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<8;
+
+ out_le32(&awacs->codec_ctrl, addr + 0x100200);
+ awacs_burgundy_busy_wait();
+ awacs_burgundy_extend_wait();
+ val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<16;
+
+ out_le32(&awacs->codec_ctrl, addr + 0x100300);
+ awacs_burgundy_busy_wait();
+ awacs_burgundy_extend_wait();
+ val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<24;
+
+ restore_flags(flags);
+
+ return val;
+}
+
+
+static void
+awacs_burgundy_wcb(unsigned addr, unsigned val)
+{
+ out_le32(&awacs->codec_ctrl, addr + 0x300000 + (val & 0xff));
+ awacs_burgundy_busy_wait();
+}
+
+static unsigned
+awacs_burgundy_rcb(unsigned addr)
+{
+ unsigned val = 0;
+ int flags;
+
+ /* should have timeouts here */
+ save_flags(flags); cli();
+
+ out_le32(&awacs->codec_ctrl, addr + 0x100000);
+ awacs_burgundy_busy_wait();
+ awacs_burgundy_extend_wait();
+ val += (in_le32(&awacs->codec_stat) >> 4) & 0xff;
+
+ restore_flags(flags);
+
+ return val;
+}
+
+static int
+awacs_burgundy_check(void)
+{
+ /* Checks to see the chip is alive and kicking */
+ int error = in_le32(&awacs->codec_ctrl) & MASK_ERRCODE;
+
+ return error == 0xf0000;
+}
+
+static int
+awacs_burgundy_init(void)
+{
+ if (awacs_burgundy_check()) {
+ printk(KERN_WARNING "AWACS: disabled by MacOS :-(\n");
+ return 1;
+ }
+
+ awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_OUTPUTENABLES,
+ DEF_BURGUNDY_OUTPUTENABLES);
+ awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+ DEF_BURGUNDY_MORE_OUTPUTENABLES);
+ awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_OUTPUTSELECTS,
+ DEF_BURGUNDY_OUTPUTSELECTS);
+
+ awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_INPSEL21,
+ DEF_BURGUNDY_INPSEL21);
+ awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_INPSEL3,
+ DEF_BURGUNDY_INPSEL3);
+ awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINCD,
+ DEF_BURGUNDY_GAINCD);
+ awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINLINE,
+ DEF_BURGUNDY_GAINLINE);
+ awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINMIC,
+ DEF_BURGUNDY_GAINMIC);
+ awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINMODEM,
+ DEF_BURGUNDY_GAINMODEM);
+
+ awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER,
+ DEF_BURGUNDY_ATTENSPEAKER);
+ awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENLINEOUT,
+ DEF_BURGUNDY_ATTENLINEOUT);
+ awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENHP,
+ DEF_BURGUNDY_ATTENHP);
+
+ awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_MASTER_VOLUME,
+ DEF_BURGUNDY_MASTER_VOLUME);
+ awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLCD,
+ DEF_BURGUNDY_VOLCD);
+ awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLLINE,
+ DEF_BURGUNDY_VOLLINE);
+ awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLMIC,
+ DEF_BURGUNDY_VOLMIC);
+ return 0;
+}
+
+static void
+awacs_burgundy_write_volume(unsigned address, int volume)
+{
+ int hardvolume,lvolume,rvolume;
+
+ lvolume = (volume & 0xff) ? (volume & 0xff) + 155 : 0;
+ rvolume = ((volume >>8)&0xff) ? ((volume >> 8)&0xff ) + 155 : 0;
+
+ hardvolume = lvolume + (rvolume << 16);
+
+ awacs_burgundy_wcw(address, hardvolume);
+}
+
+static int
+awacs_burgundy_read_volume(unsigned address)
+{
+ int softvolume,wvolume;
+
+ wvolume = awacs_burgundy_rcw(address);
+
+ softvolume = (wvolume & 0xff) - 155;
+ softvolume += (((wvolume >> 16) & 0xff) - 155)<<8;
+
+ return softvolume > 0 ? softvolume : 0;
+}
+
+
+
+
+static int
+awacs_burgundy_read_mvolume(unsigned address)
+{
+ int lvolume,rvolume,wvolume;
+
+ wvolume = awacs_burgundy_rcw(address);
+
+ wvolume &= 0xffff;
+
+ rvolume = (wvolume & 0xff) - 155;
+ lvolume = ((wvolume & 0xff00)>>8) - 155;
+
+ return lvolume + (rvolume << 8);
+}
+
+
+static void
+awacs_burgundy_write_mvolume(unsigned address, int volume)
+{
+ int lvolume,rvolume,hardvolume;
+
+ lvolume = (volume &0xff) ? (volume & 0xff) + 155 :0;
+ rvolume = ((volume >>8) & 0xff) ? (volume >> 8) + 155 :0;
+
+ hardvolume = lvolume + (rvolume << 8);
+ hardvolume += (hardvolume << 16);
+
+ awacs_burgundy_wcw(address, hardvolume);
+}
+
+/* End burgundy functions */
+
+
+
+
+
/* Turn on sound output, needed on G3 desktop powermacs */
static void
awacs_enable_amp(int spkr_vol)
@@ -3715,117 +3951,244 @@ static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
#ifdef CONFIG_PPC
case DMASND_AWACS:
- switch (cmd) {
- case SOUND_MIXER_READ_DEVMASK:
- data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
- | SOUND_MASK_LINE | SOUND_MASK_MIC
- | SOUND_MASK_CD | SOUND_MASK_RECLEV
- | SOUND_MASK_ALTPCM;
- return IOCTL_OUT(arg, data);
- case SOUND_MIXER_READ_RECMASK:
- data = SOUND_MASK_LINE | SOUND_MASK_MIC
- | SOUND_MASK_CD;
- return IOCTL_OUT(arg, data);
- case SOUND_MIXER_READ_RECSRC:
- data = 0;
- if (awacs_reg[0] & MASK_MUX_AUDIN)
- data |= SOUND_MASK_LINE;
- if (awacs_reg[0] & MASK_MUX_MIC)
- data |= SOUND_MASK_MIC;
- if (awacs_reg[0] & MASK_MUX_CD)
- data |= SOUND_MASK_CD;
- return IOCTL_OUT(arg, data);
- case SOUND_MIXER_WRITE_RECSRC:
- IOCTL_IN(arg, data);
- data &= (SOUND_MASK_LINE
- | SOUND_MASK_MIC | SOUND_MASK_CD);
- awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC
- | MASK_MUX_AUDIN);
- if (data & SOUND_MASK_LINE)
- awacs_reg[0] |= MASK_MUX_AUDIN;
- if (data & SOUND_MASK_MIC)
- awacs_reg[0] |= MASK_MUX_MIC;
- if (data & SOUND_MASK_CD)
- awacs_reg[0] |= MASK_MUX_CD;
- awacs_write(awacs_reg[0] | MASK_ADDR0);
- return IOCTL_OUT(arg, data);
- case SOUND_MIXER_READ_STEREODEVS:
- data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
- | SOUND_MASK_RECLEV;
- return IOCTL_OUT(arg, data);
- case SOUND_MIXER_READ_CAPS:
- return IOCTL_OUT(arg, 0);
- case SOUND_MIXER_READ_VOLUME:
- data = (awacs_reg[1] & MASK_AMUTE)? 0:
- awacs_get_volume(awacs_reg[2], 6);
- return IOCTL_OUT(arg, data);
- case SOUND_MIXER_WRITE_VOLUME:
- IOCTL_IN(arg, data);
- return IOCTL_OUT(arg, sound_set_volume(data));
- case SOUND_MIXER_READ_SPEAKER:
- if (awacs_revision >= 3 && adb_hardware == ADB_VIACUDA)
- data = awacs_spkr_vol;
- else
- data = (awacs_reg[1] & MASK_CMUTE)? 0:
- awacs_get_volume(awacs_reg[4], 6);
- return IOCTL_OUT(arg, data);
- case SOUND_MIXER_WRITE_SPEAKER:
- IOCTL_IN(arg, data);
- if (awacs_revision >= 3 && adb_hardware == ADB_VIACUDA)
- awacs_enable_amp(data);
- else
- data = awacs_volume_setter(data, 4, MASK_CMUTE, 6);
- return IOCTL_OUT(arg, data);
- case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */
- IOCTL_IN(arg, data);
- beep_volume = data & 0xff;
- /* fall through */
- case SOUND_MIXER_READ_ALTPCM:
- return IOCTL_OUT(arg, beep_volume);
- case SOUND_MIXER_WRITE_LINE:
- IOCTL_IN(arg, data);
- awacs_reg[0] &= ~MASK_MUX_AUDIN;
- if ((data & 0xff) >= 50)
- awacs_reg[0] |= MASK_MUX_AUDIN;
- awacs_write(MASK_ADDR0 | awacs_reg[0]);
- /* fall through */
- case SOUND_MIXER_READ_LINE:
- data = (awacs_reg[0] & MASK_MUX_AUDIN)? 100: 0;
- return IOCTL_OUT(arg, data);
- case SOUND_MIXER_WRITE_MIC:
- IOCTL_IN(arg, data);
- data &= 0xff;
- awacs_reg[0] &= ~(MASK_MUX_MIC | MASK_GAINLINE);
- if (data >= 25) {
- awacs_reg[0] |= MASK_MUX_MIC;
- if (data >= 75)
- awacs_reg[0] |= MASK_GAINLINE;
+ if (awacs_revision<AWACS_BURGUNDY) { /* Different IOCTLS for burgundy*/
+ switch (cmd) {
+ case SOUND_MIXER_READ_DEVMASK:
+ data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
+ | SOUND_MASK_LINE | SOUND_MASK_MIC
+ | SOUND_MASK_CD | SOUND_MASK_RECLEV
+ | SOUND_MASK_ALTPCM;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_RECMASK:
+ data = SOUND_MASK_LINE | SOUND_MASK_MIC
+ | SOUND_MASK_CD;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_RECSRC:
+ data = 0;
+ if (awacs_reg[0] & MASK_MUX_AUDIN)
+ data |= SOUND_MASK_LINE;
+ if (awacs_reg[0] & MASK_MUX_MIC)
+ data |= SOUND_MASK_MIC;
+ if (awacs_reg[0] & MASK_MUX_CD)
+ data |= SOUND_MASK_CD;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_RECSRC:
+ IOCTL_IN(arg, data);
+ data &= (SOUND_MASK_LINE
+ | SOUND_MASK_MIC | SOUND_MASK_CD);
+ awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC
+ | MASK_MUX_AUDIN);
+ if (data & SOUND_MASK_LINE)
+ awacs_reg[0] |= MASK_MUX_AUDIN;
+ if (data & SOUND_MASK_MIC)
+ awacs_reg[0] |= MASK_MUX_MIC;
+ if (data & SOUND_MASK_CD)
+ awacs_reg[0] |= MASK_MUX_CD;
+ awacs_write(awacs_reg[0] | MASK_ADDR0);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_STEREODEVS:
+ data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
+ | SOUND_MASK_RECLEV;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_CAPS:
+ return IOCTL_OUT(arg, 0);
+ case SOUND_MIXER_READ_VOLUME:
+ data = (awacs_reg[1] & MASK_AMUTE)? 0:
+ awacs_get_volume(awacs_reg[2], 6);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_VOLUME:
+ IOCTL_IN(arg, data);
+ return IOCTL_OUT(arg, sound_set_volume(data));
+ case SOUND_MIXER_READ_SPEAKER:
+ if (awacs_revision == 3 && adb_hardware == ADB_VIACUDA)
+ data = awacs_spkr_vol;
+ else
+ data = (awacs_reg[1] & MASK_CMUTE)? 0:
+ awacs_get_volume(awacs_reg[4], 6);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_SPEAKER:
+ IOCTL_IN(arg, data);
+ if (awacs_revision == 3 && adb_hardware == ADB_VIACUDA)
+ awacs_enable_amp(data);
+ else
+ data = awacs_volume_setter(data, 4, MASK_CMUTE, 6);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */
+ IOCTL_IN(arg, data);
+ beep_volume = data & 0xff;
+ /* fall through */
+ case SOUND_MIXER_READ_ALTPCM:
+ return IOCTL_OUT(arg, beep_volume);
+ case SOUND_MIXER_WRITE_LINE:
+ IOCTL_IN(arg, data);
+ awacs_reg[0] &= ~MASK_MUX_AUDIN;
+ if ((data & 0xff) >= 50)
+ awacs_reg[0] |= MASK_MUX_AUDIN;
+ awacs_write(MASK_ADDR0 | awacs_reg[0]);
+ /* fall through */
+ case SOUND_MIXER_READ_LINE:
+ data = (awacs_reg[0] & MASK_MUX_AUDIN)? 100: 0;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_MIC:
+ IOCTL_IN(arg, data);
+ data &= 0xff;
+ awacs_reg[0] &= ~(MASK_MUX_MIC | MASK_GAINLINE);
+ if (data >= 25) {
+ awacs_reg[0] |= MASK_MUX_MIC;
+ if (data >= 75)
+ awacs_reg[0] |= MASK_GAINLINE;
+ }
+ awacs_write(MASK_ADDR0 | awacs_reg[0]);
+ /* fall through */
+ case SOUND_MIXER_READ_MIC:
+ data = (awacs_reg[0] & MASK_MUX_MIC)?
+ (awacs_reg[0] & MASK_GAINLINE? 100: 50): 0;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_CD:
+ IOCTL_IN(arg, data);
+ awacs_reg[0] &= ~MASK_MUX_CD;
+ if ((data & 0xff) >= 50)
+ awacs_reg[0] |= MASK_MUX_CD;
+ awacs_write(MASK_ADDR0 | awacs_reg[0]);
+ /* fall through */
+ case SOUND_MIXER_READ_CD:
+ data = (awacs_reg[0] & MASK_MUX_CD)? 100: 0;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_RECLEV:
+ IOCTL_IN(arg, data);
+ data = awacs_volume_setter(data, 0, 0, 4);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_RECLEV:
+ data = awacs_get_volume(awacs_reg[0], 4);
+ return IOCTL_OUT(arg, data);
}
- awacs_write(MASK_ADDR0 | awacs_reg[0]);
- /* fall through */
- case SOUND_MIXER_READ_MIC:
- data = (awacs_reg[0] & MASK_MUX_MIC)?
- (awacs_reg[0] & MASK_GAINLINE? 100: 50): 0;
- return IOCTL_OUT(arg, data);
- case SOUND_MIXER_WRITE_CD:
- IOCTL_IN(arg, data);
- awacs_reg[0] &= ~MASK_MUX_CD;
- if ((data & 0xff) >= 50)
- awacs_reg[0] |= MASK_MUX_CD;
- awacs_write(MASK_ADDR0 | awacs_reg[0]);
- /* fall through */
- case SOUND_MIXER_READ_CD:
- data = (awacs_reg[0] & MASK_MUX_CD)? 100: 0;
- return IOCTL_OUT(arg, data);
- case SOUND_MIXER_WRITE_RECLEV:
- IOCTL_IN(arg, data);
- data = awacs_volume_setter(data, 0, 0, 4);
- return IOCTL_OUT(arg, data);
- case SOUND_MIXER_READ_RECLEV:
- data = awacs_get_volume(awacs_reg[0], 4);
- return IOCTL_OUT(arg, data);
+ break;
+ } else {
+ /* We are, we are, we are... Burgundy or better */
+ switch(cmd) {
+ case SOUND_MIXER_READ_DEVMASK:
+ data = SOUND_MASK_VOLUME | SOUND_MASK_CD |
+ SOUND_MASK_LINE | SOUND_MASK_MIC |
+ SOUND_MASK_SPEAKER | SOUND_MASK_ALTPCM;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_RECMASK:
+ data = SOUND_MASK_LINE | SOUND_MASK_MIC
+ | SOUND_MASK_CD;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_RECSRC:
+ data = 0;
+ if (awacs_reg[0] & MASK_MUX_AUDIN)
+ data |= SOUND_MASK_LINE;
+ if (awacs_reg[0] & MASK_MUX_MIC)
+ data |= SOUND_MASK_MIC;
+ if (awacs_reg[0] & MASK_MUX_CD)
+ data |= SOUND_MASK_CD;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_RECSRC:
+ IOCTL_IN(arg, data);
+ data &= (SOUND_MASK_LINE
+ | SOUND_MASK_MIC | SOUND_MASK_CD);
+ awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC
+ | MASK_MUX_AUDIN);
+ if (data & SOUND_MASK_LINE)
+ awacs_reg[0] |= MASK_MUX_AUDIN;
+ if (data & SOUND_MASK_MIC)
+ awacs_reg[0] |= MASK_MUX_MIC;
+ if (data & SOUND_MASK_CD)
+ awacs_reg[0] |= MASK_MUX_CD;
+ awacs_write(awacs_reg[0] | MASK_ADDR0);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_STEREODEVS:
+ data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
+ | SOUND_MASK_RECLEV | SOUND_MASK_CD
+ | SOUND_MASK_LINE;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_CAPS:
+ return IOCTL_OUT(arg, 0);
+ case SOUND_MIXER_WRITE_VOLUME:
+ IOCTL_IN(arg, data);
+ awacs_burgundy_write_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME, data);
+ /* Fall through */
+ case SOUND_MIXER_READ_VOLUME:
+ return IOCTL_OUT(arg, awacs_burgundy_read_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME));
+ case SOUND_MIXER_WRITE_SPEAKER:
+ IOCTL_IN(arg, data);
+
+ if (!(data & 0xff)) {
+ /* Mute the left speaker */
+ awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+ awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x2);
+ } else {
+ /* Unmute the left speaker */
+ awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+ awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x2);
+ }
+ if (!(data & 0xff00)) {
+ /* Mute the right speaker */
+ awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+ awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x4);
+ } else {
+ /* Unmute the right speaker */
+ awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+ awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x4);
+ }
+
+ data = (((data&0xff)*16)/100 > 0xf ? 0xf :
+ (((data&0xff)*16)/100)) +
+ ((((data>>8)*16)/100 > 0xf ? 0xf :
+ ((((data>>8)*16)/100)))<<4);
+
+ awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER, ~data);
+ /* Fall through */
+ case SOUND_MIXER_READ_SPEAKER:
+ data = awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER);
+ data = (((data & 0xf)*100)/16) + ((((data>>4)*100)/16)<<8);
+ return IOCTL_OUT(arg, ~data);
+ case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */
+ IOCTL_IN(arg, data);
+ beep_volume = data & 0xff;
+ /* fall through */
+ case SOUND_MIXER_READ_ALTPCM:
+ return IOCTL_OUT(arg, beep_volume);
+ case SOUND_MIXER_WRITE_LINE:
+ IOCTL_IN(arg, data);
+ awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLLINE, data);
+
+ /* fall through */
+ case SOUND_MIXER_READ_LINE:
+ data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLLINE);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_MIC:
+ IOCTL_IN(arg, data);
+ /* Mic is mono device */
+ data = (data << 8) + (data << 24);
+ awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLMIC, data);
+ /* fall through */
+ case SOUND_MIXER_READ_MIC:
+ data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLMIC);
+ data <<= 24;
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_CD:
+ IOCTL_IN(arg, data);
+ awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLCD, data);
+ /* fall through */
+ case SOUND_MIXER_READ_CD:
+ data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLCD);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_WRITE_RECLEV:
+ IOCTL_IN(arg, data);
+ data = awacs_volume_setter(data, 0, 0, 4);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_READ_RECLEV:
+ data = awacs_get_volume(awacs_reg[0], 4);
+ return IOCTL_OUT(arg, data);
+ case SOUND_MIXER_OUTMASK:
+ break;
+ case SOUND_MIXER_OUTSRC:
+ break;
+ }
+ break;
}
- break;
#endif
}
@@ -3946,9 +4309,7 @@ static void sq_setup(int numBufs, int bufSize, char **buffers)
sq.front = sq.count = 0;
sq.rear = -1;
- sq.write_queue = sq.open_queue = sq.sync_queue = 0;
sq.syncing = 0;
-
sq.playing = 0;
#ifdef CONFIG_ATARI
@@ -4129,21 +4490,21 @@ static int sq_fsync(struct file *filp, struct dentry *dentry)
static int sq_release(struct inode *inode, struct file *file)
{
int rc = 0;
- if (sq.busy) {
+
+ if (sq.busy)
rc = sq_fsync(file, file->f_dentry);
- sq.busy = 0;
- WAKE_UP(sq.open_queue);
- /* Wake up a process waiting for the queue being released.
- * Note: There may be several processes waiting for a call
- * to open() returning. */
- }
sound.soft = sound.dsp;
sound.hard = sound.dsp;
sound_silence();
- if (rc == 0) {
- sq_release_buffers();
- MOD_DEC_USE_COUNT;
- }
+ sq_release_buffers();
+ MOD_DEC_USE_COUNT;
+
+ sq.busy = 0;
+ WAKE_UP(sq.open_queue);
+ /* Wake up a process waiting for the queue being released.
+ * Note: There may be several processes waiting for a call
+ * to open() returning. */
+
return rc;
}
@@ -4262,6 +4623,9 @@ static void __init sq_init(void)
if (sq_unit < 0)
return;
+ sq.write_queue = sq.open_queue = sq.sync_queue = 0;
+ sq.busy = 0;
+
/* whatever you like as startup mode for /dev/dsp,
* (/dev/audio hasn't got a startup mode). note that
* once changed a new open() will *not* restore these!
@@ -4332,7 +4696,7 @@ static int state_open(struct inode *inode, struct file *file)
#endif /* CONFIG_AMIGA */
#ifdef CONFIG_PPC
case DMASND_AWACS:
- mach = "PowerMac ";
+ sprintf(mach, "PowerMac (AWACS rev %d) ", awacs_revision);
break;
#endif /* CONFIG_PPC */
}
@@ -4510,6 +4874,7 @@ void __init dmasound_init(void)
#ifdef CONFIG_PPC
awacs_subframe = 0;
+ awacs_revision = 0;
np = find_devices("awacs");
if (np == 0) {
/*
@@ -4524,6 +4889,8 @@ void __init dmasound_init(void)
sfprop = (int *) get_property(sound, "sub-frame", 0);
if (sfprop != 0 && *sfprop >= 0 && *sfprop < 16)
awacs_subframe = *sfprop;
+ if (device_is_compatible(sound, "burgundy"))
+ awacs_revision = AWACS_BURGUNDY;
}
}
if (np != NULL && np->n_addrs >= 3 && np->n_intrs >= 3) {
@@ -4542,7 +4909,7 @@ void __init dmasound_init(void)
awacs_tx_cmd_space = kmalloc((numBufs + 4) * sizeof(struct dbdma_cmd),
GFP_KERNEL);
if (awacs_tx_cmd_space == NULL) {
- printk("DMA sound driver: Not enough buffer memory, driver disabled!\n");
+ printk(KERN_ERR "DMA sound driver: Not enough buffer memory, driver disabled!\n");
return;
}
awacs_tx_cmds = (volatile struct dbdma_cmd *)
@@ -4560,17 +4927,22 @@ void __init dmasound_init(void)
awacs_write(awacs_reg[4] + MASK_ADDR4);
/* Initialize recent versions of the awacs */
- awacs_revision = (in_le32(&awacs->codec_stat) >> 12) & 0xf;
- if (awacs_revision >= 3) {
- awacs_write(0x6000);
- awacs_enable_amp(100 * 0x101);
+ if (awacs_revision == 0) {
+ awacs_revision =
+ (in_le32(&awacs->codec_stat) >> 12) & 0xf;
+ if (awacs_revision == 3) {
+ awacs_write(0x6000);
+ awacs_enable_amp(100 * 0x101);
+ }
}
+ if (awacs_revision >= AWACS_BURGUNDY)
+ awacs_burgundy_init();
/* Initialize beep stuff */
beep_dbdma_cmd = awacs_tx_cmds + (numBufs + 1);
orig_mksound = kd_mksound;
kd_mksound = awacs_mksound;
- beep_buf = (short *) kmalloc(BEEP_BUFLEN * 2, GFP_KERNEL);
+ beep_buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
if (beep_buf == NULL)
printk(KERN_WARNING "dmasound: no memory for "
"beep buffer\n");
@@ -4596,15 +4968,15 @@ void __init dmasound_init(void)
mixer_init();
if (!sound.mach.irqinit()) {
- printk("DMA sound driver: Interrupt initialization failed\n");
+ printk(KERN_ERR "DMA sound driver: Interrupt initialization failed\n");
return;
}
#ifdef MODULE
irq_installed = 1;
#endif
- printk("DMA sound driver installed, using %d buffers of %dk.\n", numBufs,
- bufSize);
+ printk(KERN_INFO "DMA sound driver installed, using %d buffers of %dk.\n",
+ numBufs, bufSize);
return;
}
diff --git a/drivers/sound/es1370.c b/drivers/sound/es1370.c
index 37d1fc38f..1ce70dc7b 100644
--- a/drivers/sound/es1370.c
+++ b/drivers/sound/es1370.c
@@ -3,7 +3,7 @@
/*
* es1370.c -- Ensoniq ES1370/Asahi Kasei AK4531 audio driver.
*
- * Copyright (C) 1998 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * Copyright (C) 1998-1999 Thomas Sailer (sailer@ife.ee.ethz.ch)
*
* 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
@@ -83,6 +83,15 @@
* 16.12.98 0.16 Don't wake up app until there are fragsize bytes to read/write
* 06.01.99 0.17 remove the silly SA_INTERRUPT flag.
* hopefully killed the egcs section type conflict
+ * 12.03.99 0.18 cinfo.blocks should be reset after GETxPTR ioctl.
+ * reported by Johan Maes <joma@telindus.be>
+ * 22.03.99 0.19 return EAGAIN instead of EBUSY when O_NONBLOCK
+ * read/write cannot be executed
+ * 07.04.99 0.20 implemented the following ioctl's: SOUND_PCM_READ_RATE,
+ * SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS;
+ * Alpha fixes reported by Peter Jones <pjones@redhat.com>
+ * Note: joystick address handling might still be wrong on archs
+ * other than i386
*
* some important things missing in Ensoniq documentation:
*
@@ -127,6 +136,8 @@
/* --------------------------------------------------------------------- */
#undef OSS_DOCUMENTED_MIXER_SEMANTICS
+#define DBG(x) {}
+/*#define DBG(x) {x}*/
/* --------------------------------------------------------------------- */
@@ -281,7 +292,8 @@ struct es1370_state {
int dev_midi;
/* hardware resources */
- unsigned int io, irq;
+ unsigned long io; /* long for SPARC */
+ unsigned int irq;
/* mixer registers; there is no HW readback */
struct {
@@ -1019,7 +1031,7 @@ static int drain_dac1(struct es1370_state *s, int nonblock)
tmo = (count * HZ) / dac1_samplerate[(s->ctrl & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL];
tmo >>= sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT];
if (!schedule_timeout(tmo ? : 1) && tmo)
- printk(KERN_DEBUG "es1370: dma timed out??\n");
+ DBG(printk(KERN_DEBUG "es1370: dma timed out??\n");)
}
remove_wait_queue(&s->dma_dac1.wait, &wait);
current->state = TASK_RUNNING;
@@ -1054,7 +1066,7 @@ static int drain_dac2(struct es1370_state *s, int nonblock)
tmo = (count * HZ) / DAC2_DIVTOSR((s->ctrl & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV);
tmo >>= sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT];
if (!schedule_timeout(tmo ? : 1) && tmo)
- printk(KERN_DEBUG "es1370: dma timed out??\n");
+ DBG(printk(KERN_DEBUG "es1370: dma timed out??\n");)
}
remove_wait_queue(&s->dma_dac2.wait, &wait);
current->state = TASK_RUNNING;
@@ -1095,7 +1107,7 @@ static ssize_t es1370_read(struct file *file, char *buffer, size_t count, loff_t
if (cnt <= 0) {
start_adc(s);
if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EBUSY;
+ return ret ? ret : -EAGAIN;
interruptible_sleep_on(&s->dma_adc.wait);
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
@@ -1150,7 +1162,7 @@ static ssize_t es1370_write(struct file *file, const char *buffer, size_t count,
if (cnt <= 0) {
start_dac2(s);
if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EBUSY;
+ return ret ? ret : -EAGAIN;
interruptible_sleep_on(&s->dma_dac2.wait);
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
@@ -1228,8 +1240,6 @@ static int es1370_mmap(struct file *file, struct vm_area_struct *vma)
if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
return -EAGAIN;
db->mapped = 1;
- vma->vm_file = file;
- file->f_count++;
return 0;
}
@@ -1455,7 +1465,7 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
spin_lock_irqsave(&s->lock, flags);
es1370_update_ptr(s);
cinfo.bytes = s->dma_adc.total_bytes;
- cinfo.blocks = s->dma_adc.total_bytes >> s->dma_adc.fragshift;
+ cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
cinfo.ptr = s->dma_adc.hwptr;
if (s->dma_adc.mapped)
s->dma_adc.count &= s->dma_adc.fragsize-1;
@@ -1468,7 +1478,7 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
spin_lock_irqsave(&s->lock, flags);
es1370_update_ptr(s);
cinfo.bytes = s->dma_dac2.total_bytes;
- cinfo.blocks = s->dma_dac2.total_bytes >> s->dma_dac2.fragshift;
+ cinfo.blocks = s->dma_dac2.count >> s->dma_dac2.fragshift;
cinfo.ptr = s->dma_dac2.hwptr;
if (s->dma_dac2.mapped)
s->dma_dac2.count &= s->dma_dac2.fragsize-1;
@@ -1522,11 +1532,19 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
s->dma_dac2.subdivision = val;
return 0;
- case SOUND_PCM_WRITE_FILTER:
- case SNDCTL_DSP_SETSYNCRO:
case SOUND_PCM_READ_RATE:
+ return put_user(DAC2_DIVTOSR((s->ctrl & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV), (int *)arg);
+
case SOUND_PCM_READ_CHANNELS:
+ return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SMB : SCTRL_P2SMB)) ?
+ 2 : 1, (int *)arg);
+
case SOUND_PCM_READ_BITS:
+ return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SEB : SCTRL_P2SEB)) ?
+ 16 : 8, (int *)arg);
+
+ case SOUND_PCM_WRITE_FILTER:
+ case SNDCTL_DSP_SETSYNCRO:
case SOUND_PCM_READ_FILTER:
return -EINVAL;
@@ -1597,6 +1615,7 @@ static int es1370_release(struct inode *inode, struct file *file)
down(&s->open_sem);
if (file->f_mode & FMODE_WRITE) {
stop_dac2(s);
+ synchronize_irq();
dealloc_dmabuf(&s->dma_dac2);
}
if (file->f_mode & FMODE_READ) {
@@ -1663,7 +1682,7 @@ static ssize_t es1370_write_dac(struct file *file, const char *buffer, size_t co
if (cnt <= 0) {
start_dac1(s);
if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EBUSY;
+ return ret ? ret : -EAGAIN;
interruptible_sleep_on(&s->dma_dac1.wait);
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
@@ -1725,8 +1744,6 @@ static int es1370_mmap_dac(struct file *file, struct vm_area_struct *vma)
if (remap_page_range(vma->vm_start, virt_to_phys(s->dma_dac1.rawbuf), size, vma->vm_page_prot))
return -EAGAIN;
s->dma_dac1.mapped = 1;
- vma->vm_file = file;
- file->f_count++;
return 0;
}
@@ -1867,7 +1884,7 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int
spin_lock_irqsave(&s->lock, flags);
es1370_update_ptr(s);
cinfo.bytes = s->dma_dac1.total_bytes;
- cinfo.blocks = s->dma_dac1.total_bytes >> s->dma_dac1.fragshift;
+ cinfo.blocks = s->dma_dac1.count >> s->dma_dac1.fragshift;
cinfo.ptr = s->dma_dac1.hwptr;
if (s->dma_dac1.mapped)
s->dma_dac1.count &= s->dma_dac1.fragsize-1;
@@ -1900,11 +1917,17 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int
s->dma_dac1.subdivision = val;
return 0;
- case SOUND_PCM_WRITE_FILTER:
- case SNDCTL_DSP_SETSYNCRO:
case SOUND_PCM_READ_RATE:
+ return put_user(dac1_samplerate[(s->ctrl & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL], (int *)arg);
+
case SOUND_PCM_READ_CHANNELS:
+ return put_user((s->sctrl & SCTRL_P1SMB) ? 2 : 1, (int *)arg);
+
case SOUND_PCM_READ_BITS:
+ return put_user((s->sctrl & SCTRL_P1SEB) ? 16 : 8, (int *)arg);
+
+ case SOUND_PCM_WRITE_FILTER:
+ case SNDCTL_DSP_SETSYNCRO:
case SOUND_PCM_READ_FILTER:
return -EINVAL;
@@ -2022,7 +2045,7 @@ static ssize_t es1370_midi_read(struct file *file, char *buffer, size_t count, l
cnt = count;
if (cnt <= 0) {
if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EBUSY;
+ return ret ? ret : -EAGAIN;
interruptible_sleep_on(&s->midi.iwait);
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
@@ -2069,7 +2092,7 @@ static ssize_t es1370_midi_write(struct file *file, const char *buffer, size_t c
cnt = count;
if (cnt <= 0) {
if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EBUSY;
+ return ret ? ret : -EAGAIN;
interruptible_sleep_on(&s->midi.owait);
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
@@ -2192,7 +2215,7 @@ static int es1370_midi_release(struct inode *inode, struct file *file)
}
tmo = (count * HZ) / 3100;
if (!schedule_timeout(tmo ? : 1) && tmo)
- printk(KERN_DEBUG "es1370: midi timed out??\n");
+ DBG(printk(KERN_DEBUG "es1370: midi timed out??\n");)
}
remove_wait_queue(&s->midi.owait, &wait);
current->state = TASK_RUNNING;
@@ -2272,7 +2295,7 @@ __initfunc(int init_es1370(void))
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "es1370: version v0.17 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "es1370: version v0.20 time " __TIME__ " " __DATE__ "\n");
while (index < NR_DEVICE &&
(pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
if (pcidev->base_address[0] == 0 ||
@@ -2296,7 +2319,7 @@ __initfunc(int init_es1370(void))
s->io = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
s->irq = pcidev->irq;
if (check_region(s->io, ES1370_EXTENT)) {
- printk(KERN_ERR "es1370: io ports %#x-%#x in use\n", s->io, s->io+ES1370_EXTENT-1);
+ printk(KERN_ERR "es1370: io ports %#lx-%#lx in use\n", s->io, s->io+ES1370_EXTENT-1);
goto err_region;
}
request_region(s->io, ES1370_EXTENT, "es1370");
@@ -2317,7 +2340,7 @@ __initfunc(int init_es1370(void))
if (micz[index])
s->ctrl |= CTRL_XCTL1;
s->sctrl = 0;
- printk(KERN_INFO "es1370: found adapter at io %#06x irq %u\n"
+ printk(KERN_INFO "es1370: found adapter at io %#lx irq %u\n"
KERN_INFO "es1370: features: joystick %s, line %s, mic impedance %s\n",
s->io, s->irq, (s->ctrl & CTRL_JYSTK_EN) ? "on" : "off",
(s->ctrl & CTRL_XCTL0) ? "out" : "in",
diff --git a/drivers/sound/es1371.c b/drivers/sound/es1371.c
index e52f47d14..fa2efd25f 100644
--- a/drivers/sound/es1371.c
+++ b/drivers/sound/es1371.c
@@ -54,6 +54,17 @@
* Don't wake up app until there are fragsize bytes to read/write
* 06.01.99 0.8 remove the silly SA_INTERRUPT flag.
* hopefully killed the egcs section type conflict
+ * 12.03.99 0.9 cinfo.blocks should be reset after GETxPTR ioctl.
+ * reported by Johan Maes <joma@telindus.be>
+ * 22.03.99 0.10 return EAGAIN instead of EBUSY when O_NONBLOCK
+ * read/write cannot be executed
+ * 07.04.99 0.11 implemented the following ioctl's: SOUND_PCM_READ_RATE,
+ * SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS;
+ * Alpha fixes reported by Peter Jones <pjones@redhat.com>
+ * Another Alpha fix (wait_src_ready in init routine)
+ * reported by "Ivan N. Kokshaysky" <ink@jurassic.park.msu.ru>
+ * Note: joystick address handling might still be wrong on archs
+ * other than i386
*
*/
@@ -330,7 +341,8 @@ struct es1371_state {
int dev_midi;
/* hardware resources */
- unsigned int io, irq;
+ unsigned long io; /* long for SPARC */
+ unsigned int irq;
/* mixer registers; there is no HW readback */
struct {
@@ -1542,7 +1554,7 @@ static ssize_t es1371_read(struct file *file, char *buffer, size_t count, loff_t
if (cnt <= 0) {
start_adc(s);
if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EBUSY;
+ return ret ? ret : -EAGAIN;
interruptible_sleep_on(&s->dma_adc.wait);
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
@@ -1597,7 +1609,7 @@ static ssize_t es1371_write(struct file *file, const char *buffer, size_t count,
if (cnt <= 0) {
start_dac2(s);
if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EBUSY;
+ return ret ? ret : -EAGAIN;
interruptible_sleep_on(&s->dma_dac2.wait);
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
@@ -1675,8 +1687,6 @@ static int es1371_mmap(struct file *file, struct vm_area_struct *vma)
if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
return -EAGAIN;
db->mapped = 1;
- vma->vm_file = file;
- file->f_count++;
return 0;
}
@@ -1899,7 +1909,7 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
spin_lock_irqsave(&s->lock, flags);
es1371_update_ptr(s);
cinfo.bytes = s->dma_adc.total_bytes;
- cinfo.blocks = s->dma_adc.total_bytes >> s->dma_adc.fragshift;
+ cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
cinfo.ptr = s->dma_adc.hwptr;
if (s->dma_adc.mapped)
s->dma_adc.count &= s->dma_adc.fragsize-1;
@@ -1912,7 +1922,7 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
spin_lock_irqsave(&s->lock, flags);
es1371_update_ptr(s);
cinfo.bytes = s->dma_dac2.total_bytes;
- cinfo.blocks = s->dma_dac2.total_bytes >> s->dma_dac2.fragshift;
+ cinfo.blocks = s->dma_dac2.count >> s->dma_dac2.fragshift;
cinfo.ptr = s->dma_dac2.hwptr;
if (s->dma_dac2.mapped)
s->dma_dac2.count &= s->dma_dac2.fragsize-1;
@@ -1966,11 +1976,17 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
s->dma_dac2.subdivision = val;
return 0;
- case SOUND_PCM_WRITE_FILTER:
- case SNDCTL_DSP_SETSYNCRO:
case SOUND_PCM_READ_RATE:
+ return put_user((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, (int *)arg);
+
case SOUND_PCM_READ_CHANNELS:
+ return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SMB : SCTRL_P2SMB)) ? 2 : 1, (int *)arg);
+
case SOUND_PCM_READ_BITS:
+ return put_user((s->sctrl & ((file->f_mode & FMODE_READ) ? SCTRL_R1SEB : SCTRL_P2SEB)) ? 16 : 8, (int *)arg);
+
+ case SOUND_PCM_WRITE_FILTER:
+ case SNDCTL_DSP_SETSYNCRO:
case SOUND_PCM_READ_FILTER:
return -EINVAL;
@@ -2110,7 +2126,7 @@ static ssize_t es1371_write_dac(struct file *file, const char *buffer, size_t co
if (cnt <= 0) {
start_dac1(s);
if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EBUSY;
+ return ret ? ret : -EAGAIN;
interruptible_sleep_on(&s->dma_dac1.wait);
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
@@ -2172,8 +2188,6 @@ static int es1371_mmap_dac(struct file *file, struct vm_area_struct *vma)
if (remap_page_range(vma->vm_start, virt_to_phys(s->dma_dac1.rawbuf), size, vma->vm_page_prot))
return -EAGAIN;
s->dma_dac1.mapped = 1;
- vma->vm_file = file;
- file->f_count++;
return 0;
}
@@ -2305,7 +2319,7 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int
spin_lock_irqsave(&s->lock, flags);
es1371_update_ptr(s);
cinfo.bytes = s->dma_dac1.total_bytes;
- cinfo.blocks = s->dma_dac1.total_bytes >> s->dma_dac1.fragshift;
+ cinfo.blocks = s->dma_dac1.count >> s->dma_dac1.fragshift;
cinfo.ptr = s->dma_dac1.hwptr;
if (s->dma_dac1.mapped)
s->dma_dac1.count &= s->dma_dac1.fragsize-1;
@@ -2338,11 +2352,17 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int
s->dma_dac1.subdivision = val;
return 0;
- case SOUND_PCM_WRITE_FILTER:
- case SNDCTL_DSP_SETSYNCRO:
case SOUND_PCM_READ_RATE:
+ return put_user(s->dac1rate, (int *)arg);
+
case SOUND_PCM_READ_CHANNELS:
+ return put_user((s->sctrl & SCTRL_P1SMB) ? 2 : 1, (int *)arg);
+
case SOUND_PCM_READ_BITS:
+ return put_user((s->sctrl & SCTRL_P1SEB) ? 16 : 8, (int *)arg);
+
+ case SOUND_PCM_WRITE_FILTER:
+ case SNDCTL_DSP_SETSYNCRO:
case SOUND_PCM_READ_FILTER:
return -EINVAL;
@@ -2459,7 +2479,7 @@ static ssize_t es1371_midi_read(struct file *file, char *buffer, size_t count, l
cnt = count;
if (cnt <= 0) {
if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EBUSY;
+ return ret ? ret : -EAGAIN;
interruptible_sleep_on(&s->midi.iwait);
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
@@ -2506,7 +2526,7 @@ static ssize_t es1371_midi_write(struct file *file, const char *buffer, size_t c
cnt = count;
if (cnt <= 0) {
if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EBUSY;
+ return ret ? ret : -EAGAIN;
interruptible_sleep_on(&s->midi.owait);
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
@@ -2712,7 +2732,7 @@ __initfunc(int init_es1371(void))
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "es1371: version v0.8 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "es1371: version v0.11 time " __TIME__ " " __DATE__ "\n");
while (index < NR_DEVICE &&
(pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) {
if (pcidev->base_address[0] == 0 ||
@@ -2736,7 +2756,7 @@ __initfunc(int init_es1371(void))
s->io = pcidev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK;
s->irq = pcidev->irq;
if (check_region(s->io, ES1371_EXTENT)) {
- printk(KERN_ERR "es1371: io ports %#x-%#x in use\n", s->io, s->io+ES1371_EXTENT-1);
+ printk(KERN_ERR "es1371: io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1);
goto err_region;
}
request_region(s->io, ES1371_EXTENT, "es1371");
@@ -2744,7 +2764,7 @@ __initfunc(int init_es1371(void))
printk(KERN_ERR "es1371: irq %u in use\n", s->irq);
goto err_irq;
}
- printk(KERN_INFO "es1371: found adapter at io %#06x irq %u\n"
+ printk(KERN_INFO "es1371: found adapter at io %#lx irq %u\n"
KERN_INFO "es1371: features: joystick 0x%x\n", s->io, s->irq, joystick[index]);
/* register devices */
if ((s->dev_audio = register_sound_dsp(&es1371_audio_fops, -1)) < 0)
@@ -2796,6 +2816,7 @@ __initfunc(int init_es1371(void))
* be stuck high, and I've found no way to rectify this other than
* power cycle)
*/
+ wait_src_ready(s);
outl(0, s->io+ES1371_REG_SRCONV);
/* codec init */
wrcodec(s, 0x00, 0); /* reset codec */
diff --git a/drivers/sound/gus_card.c b/drivers/sound/gus_card.c
index a00ffb63a..f1ab09179 100644
--- a/drivers/sound/gus_card.c
+++ b/drivers/sound/gus_card.c
@@ -44,8 +44,6 @@ static int db16 = 0; /* Has a Gus16 AD1848 on it */
void attach_gus_card(struct address_info *hw_config)
{
- if(request_irq(hw_config->irq, gusintr, 0, "Gravis Ultrasound", hw_config)<0)
- printk(KERN_ERR "gus_card.c: Unable to allocate IRQ %d\n", hw_config->irq);
gus_wave_init(hw_config);
@@ -60,6 +58,9 @@ void attach_gus_card(struct address_info *hw_config)
#ifdef CONFIG_MIDI
gus_midi_init(hw_config);
#endif
+ if(request_irq(hw_config->irq, gusintr, 0, "Gravis Ultrasound", hw_config)<0)
+ printk(KERN_ERR "gus_card.c: Unable to allocate IRQ %d\n", hw_config->irq);
+
}
int probe_gus(struct address_info *hw_config)
diff --git a/drivers/sound/lowlevel/awe_compat.h b/drivers/sound/lowlevel/awe_compat.h
index 0ad4fb062..9f9c57039 100644
--- a/drivers/sound/lowlevel/awe_compat.h
+++ b/drivers/sound/lowlevel/awe_compat.h
@@ -54,7 +54,7 @@
#include "../soundvers.h"
#endif
-#if SOUND_INTERNAL_VERSION >= 0x30803
+#if defined(SOUND_INTERNAL_VERSION) && SOUND_INTERNAL_VERSION >= 0x30803
/* OSS/Free-3.8 */
#define AWE_NO_PATCHMGR
#define AWE_OSS38
@@ -151,18 +151,9 @@ static int _mem_start; /* memory pointer for permanent buffers */
#define my_malloc_memptr() _mem_start
#define my_free(ptr) /* do nothing */
-static void *my_malloc(int size)
-{
- char *ptr;
- PERMANENT_MALLOC(ptr, char*, size, _mem_start);
- return (void*)ptr;
-}
-#define my_kmalloc(size) my_malloc(size)
-#define kfree(ptr) /* do nothing */
-
/* allocate buffer only once */
#define INIT_TABLE(buffer,index,nums,type) {\
-buffer = my_malloc(sizeof(type) * (nums)); index = (nums);\
+PERMANENT_MALLOC(buffer, char*, size, _mem_start); index = (nums);\
}
#else
@@ -173,8 +164,6 @@ buffer = my_malloc(sizeof(type) * (nums)); index = (nums);\
#define my_malloc_memptr() 0
#define my_malloc(size) vmalloc(size)
#define my_free(ptr) if (ptr) {vfree(ptr);}
-#define my_kmalloc(size) kmalloc(size,GFP_KERNEL)
-#define my_kfree(ptr) kfree(ptr)
/* do not allocate buffer at beginning */
#define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;}
@@ -255,6 +244,14 @@ buffer = my_malloc(sizeof(type) * (nums)); index = (nums);\
#endif /* AWE_MODULE_SUPPORT */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
+inline static void interruptible_sleep_on_timeout(struct wait_queue **q, unsigned long timeout)
+{
+ current->timeout = jiffies + timeout;
+ interruptible_sleep_on(q);
+}
+#endif
+
#endif /* CONFIG_AWE32_SYNTH */
#endif /* AWE_COMPAT_H_DEF */
diff --git a/drivers/sound/lowlevel/awe_wave.c b/drivers/sound/lowlevel/awe_wave.c
index 1c2472049..8fd5431e6 100644
--- a/drivers/sound/lowlevel/awe_wave.c
+++ b/drivers/sound/lowlevel/awe_wave.c
@@ -2,9 +2,9 @@
* sound/awe_wave.c
*
* The low level driver for the AWE32/SB32/AWE64 wave table synth.
- * version 0.4.3; Nov. 1, 1998
+ * version 0.4.3; Feb. 1, 1999
*
- * Copyright (C) 1996-1998 Takashi Iwai
+ * Copyright (C) 1996-1999 Takashi Iwai
*
* 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
@@ -204,16 +204,20 @@ static awe_chan_info channels[AWE_MAX_CHANNELS];
#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
/* replace awe_port variable with exported variable */
#define awe_port io
-#define BASEVAR_DECL /**/
+#define awe_mem_size memsize
+int io = AWE_DEFAULT_BASE_ADDR; /* Emu8000 base address */
+int memsize = AWE_DEFAULT_MEM_SIZE; /* memory size in Kbytes */
+#ifdef MODULE_PARM
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "base i/o port of Emu8000");
+MODULE_PARM(memsize, "i");
+MODULE_PARM_DESC(memsize, "onboard DRAM size in Kbytes");
+#endif
#else
-#define BASEVAR_DECL static
+static int awe_port = AWE_DEFAULT_BASE_ADDR;
+static int awe_mem_size = AWE_DEFAULT_MEM_SIZE;
#endif /* module */
-/* awe32 base address (overwritten at initialization) */
-BASEVAR_DECL int awe_port = AWE_DEFAULT_BASE_ADDR;
-/* memory byte size */
-BASEVAR_DECL int memsize = AWE_DEFAULT_MEM_SIZE; /* for module option */
-static int awe_mem_size = -1;
/* DRAM start offset */
static int awe_mem_start = AWE_DRAM_OFFSET;
@@ -669,7 +673,7 @@ static void _unload_awe(void)
#include <linux/pnp.h>
-BASEVAR_DECL int pnp = 1; /* use PnP as default */
+static int pnp = 1; /* use PnP as default */
#define AWE_NUM_CHIPS 3
static unsigned int pnp_ids[AWE_NUM_CHIPS] = {
@@ -812,6 +816,7 @@ void cleanup_module(void)
}
#ifdef MODULE_PARM
+EXPORT_NO_SYMBOLS;
MODULE_AUTHOR("Takashi Iwai <iwai@ww.uni-erlangen.de>");
MODULE_DESCRIPTION("SB AWE32/64 WaveTable driver");
MODULE_SUPPORTED_DEVICE("sound");
@@ -975,23 +980,9 @@ awe_wait(unsigned short delay)
#else
static struct wait_queue *awe_sleeper = NULL;
-static void awe_wakeup(unsigned long dummy)
-{
- wake_up(&awe_sleeper);
-}
-
-static struct timer_list awe_timer =
-{NULL, NULL, 0, 0, awe_wakeup};
-
static void awe_wait(unsigned short delay)
{
- unsigned long flags;
- awe_timer.expires = jiffies + (HZ * (unsigned long)delay + 44099) / 44100;
- add_timer(&awe_timer);
- save_flags (flags);
- cli();
- sleep_on(&awe_sleeper);
- restore_flags(flags);
+ interruptible_sleep_on_timeout(&awe_sleeper, (HZ * (unsigned long)delay + 44099) / 44100);
}
#endif /* wait by loop */
@@ -1553,7 +1544,7 @@ awe_note_on(int voice)
vp->parm.moddcysus));
if (parm->volatk >= 0x80 && parm->voldelay >= 0x8000) {
- awe_poke(AWE_ENVVAL(voice), 0xBFFF);
+ awe_poke(AWE_ENVVOL(voice), 0xBFFF);
vtarget = voltarget[voices[voice].avol%0x10]>>(voices[voice].avol>>4);
} else {
awe_poke(AWE_ENVVOL(voice),
@@ -3268,7 +3259,7 @@ static int info_duplicated(awe_voice_list *rec)
sf_list *sf;
/* search for all sharing lists */
- for (sf_id = rec->v.sf_id; sf_id > 0; sf_id = sf->shared) {
+ for (sf_id = rec->v.sf_id; sf_id > 0 && sf_id <= current_sf_id; sf_id = sf->shared) {
sf = &sflists[sf_id - 1];
for (j = sf->infos; j >= 0; j = infos[j].next) {
awe_voice_list *p = &infos[j];
@@ -4201,7 +4192,7 @@ static int is_identical_id(int id1, int id2)
if (id1 < id2) { /* make sure id1 > id2 */
int tmp; tmp = id1; id1 = id2; id2 = tmp;
}
- for (i = sflists[id1-1].shared; i > 0; i = sflists[i-1].shared) {
+ for (i = sflists[id1-1].shared; i > 0 && i <= current_sf_id; i = sflists[i-1].shared) {
if (i == id2)
return TRUE;
}
@@ -4223,10 +4214,10 @@ static int search_sample_index(int sf, int sample, int level)
return i;
}
#ifdef AWE_ALLOW_SAMPLE_SHARING
- if (sflists[sf-1].shared) { /* search recursively */
+ if ((i = sflists[sf-1].shared) > 0 && i <= current_sf_id) { /* search recursively */
if (level > current_sf_id)
return -1; /* strange sharing loop.. quit */
- return search_sample_index(sflists[sf-1].shared, sample, level + 1);
+ return search_sample_index(i, sample, level + 1);
}
#endif
return -1;
@@ -4272,10 +4263,12 @@ awe_search_multi_voices(int rec, int note, int velocity, awe_voice_info **vlist)
note <= infos[rec].v.high &&
velocity >= infos[rec].v.vellow &&
velocity <= infos[rec].v.velhigh) {
- vlist[nvoices] = &infos[rec].v;
- if (infos[rec].type == V_ST_MAPPED) /* mapper */
+ if (infos[rec].type == V_ST_MAPPED) {
+ /* mapper */
+ vlist[0] = &infos[rec].v;
return -1;
- nvoices++;
+ }
+ vlist[nvoices++] = &infos[rec].v;
if (nvoices >= AWE_MAX_VOICES)
break;
}
@@ -5009,8 +5002,6 @@ awe_detect(void)
DEBUG(0,printk("AWE32 not found\n"));
return 0;
}
- if (memsize >= 0) /* given by config file or module option */
- awe_mem_size = memsize * 1024; /* convert to Kbytes */
return 1;
}
@@ -5028,9 +5019,14 @@ awe_detect(void)
static void
awe_check_dram(void)
{
- if (awe_mem_size >= 0) /* already initialized */
+ if (awe_present) /* already initialized */
return;
+ if (awe_mem_size >= 0) { /* given by config file or module option */
+ awe_mem_size *= 1024; /* convert to Kbytes */
+ return;
+ }
+
awe_open_dram_for_check();
awe_mem_size = 0;
diff --git a/drivers/sound/mad16.c b/drivers/sound/mad16.c
index 41533aeda..649c9861f 100644
--- a/drivers/sound/mad16.c
+++ b/drivers/sound/mad16.c
@@ -800,7 +800,7 @@ int probe_mad16_mpu(struct address_info *hw_config)
mad_write(MC3_PORT, tmp | 0x04);
hw_config->driver_use_1 = SB_MIDI_ONLY;
- return sb_dsp_detect(hw_config);
+ return sb_dsp_detect(hw_config, 0, 0);
#else
return 0;
#endif
diff --git a/drivers/sound/midi_synth.c b/drivers/sound/midi_synth.c
index 8848f410e..03d7d284f 100644
--- a/drivers/sound/midi_synth.c
+++ b/drivers/sound/midi_synth.c
@@ -12,6 +12,7 @@
*/
/*
* Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
+ * Andrew Veliath : fixed running status in MIDI input state machine
*/
#include <linux/config.h>
@@ -83,7 +84,7 @@ do_midi_msg(int synthno, unsigned char *msg, int mlen)
case 0xE0:
STORE(SEQ_BENDER(synthno, msg[0] & 0x0f,
- (msg[1] % 0x7f) | ((msg[2] & 0x7f) << 7)));
+ (msg[1] & 0x7f) | ((msg[2] & 0x7f) << 7)));
break;
default:
@@ -196,13 +197,19 @@ midi_synth_input(int orig_dev, unsigned char data)
inc->m_left = len_tab[(data >> 4) - 8];
inc->m_buf[0] = inc->m_prev_status = data;
}
- } else if (inc->m_prev_status & 0x80) /* Ignore if no previous status (yet) */
- { /* Data byte (use running status) */
- inc->m_state = MST_DATA;
+ } else if (inc->m_prev_status & 0x80) {
+ /* Data byte (use running status) */
inc->m_ptr = 2;
- inc->m_left = len_tab[(data >> 4) - 8] - 1;
- inc->m_buf[0] = inc->m_prev_status;
inc->m_buf[1] = data;
+ inc->m_buf[0] = inc->m_prev_status;
+ inc->m_left = len_tab[(inc->m_buf[0] >> 4) - 8] - 1;
+ if (inc->m_left > 0)
+ inc->m_state = MST_DATA; /* Not done yet */
+ else {
+ inc->m_state = MST_INIT;
+ do_midi_msg(dev, inc->m_buf, inc->m_ptr);
+ inc->m_ptr = 0;
+ }
}
break; /* MST_INIT */
diff --git a/drivers/sound/sb.h b/drivers/sound/sb.h
index 72ede3fab..2cb785565 100644
--- a/drivers/sound/sb.h
+++ b/drivers/sound/sb.h
@@ -47,17 +47,14 @@
#define MDL_AZTECH 13 /* Aztech Sound Galaxy family */
#define MDL_ES1868MIDI 14 /* MIDI port of ESS1868 */
#define MDL_AEDSP 15 /* Audio Excel DSP 16 */
+#define MDL_ESSPCI 16 /* ESS PCI card */
+#define MDL_YMPCI 17 /* Yamaha PCI sb in emulation */
-#define SUBMDL_ES1788 0x10 /* Subtype ES1788 for specific handling */
-#define SUBMDL_ES1868 0x11 /* Subtype ES1868 for specific handling */
-#define SUBMDL_ES1869 0x12 /* Subtype ES1869 for specific handling */
-#define SUBMDL_ES1878 0x13 /* Subtype ES1878 for specific handling */
-#define SUBMDL_ES1887 0x14 /* Subtype ES1887 for specific handling */
-#define SUBMDL_ES1888 0x14 /* Subtype ES1888 for specific handling */
#define SUBMDL_ALS007 42 /* ALS-007 differs from SB16 only in mixer */
/* register assignment */
#define SUBMDL_ALS100 43 /* ALS-100 allows sampling rates of up */
/* to 48kHz */
+
/*
* Config flags
*/
@@ -66,6 +63,7 @@
#define SB_NO_AUDIO 0x00000004
#define SB_NO_RECORDING 0x00000008 /* No audio recording */
#define SB_MIDI_ONLY (SB_NO_AUDIO|SB_NO_MIXER)
+#define SB_PCI_IRQ 0x00000010 /* PCI shared IRQ */
struct mixer_def {
unsigned int regno: 8;
@@ -92,6 +90,8 @@ typedef struct sb_devc {
int base;
int irq;
int dma8, dma16;
+
+ int pcibase; /* For ESS Maestro etc */
/* State variables */
int opened;
@@ -134,13 +134,24 @@ typedef struct sb_devc {
void (*midi_input_intr) (int dev, unsigned char data);
void *midi_irq_cookie; /* IRQ cookie for the midi */
} sb_devc;
+
+/*
+ * PCI card types
+ */
+#define SB_PCI_ESSMAESTRO 1 /* ESS Maestro Legacy */
+#define SB_PCI_YAMAHA 2 /* Yamaha Legacy */
+
+/*
+ * Functions
+ */
+
int sb_dsp_command (sb_devc *devc, unsigned char val);
int sb_dsp_get_byte(sb_devc * devc);
int sb_dsp_reset (sb_devc *devc);
void sb_setmixer (sb_devc *devc, unsigned int port, unsigned int value);
unsigned int sb_getmixer (sb_devc *devc, unsigned int port);
-int sb_dsp_detect (struct address_info *hw_config);
+int sb_dsp_detect (struct address_info *hw_config, int pci, int pciio);
int sb_dsp_init (struct address_info *hw_config);
void sb_dsp_unload(struct address_info *hw_config, int sbmpu);
int sb_mixer_init(sb_devc *devc);
diff --git a/drivers/sound/sb_card.c b/drivers/sound/sb_card.c
index b85db519c..44b40e736 100644
--- a/drivers/sound/sb_card.c
+++ b/drivers/sound/sb_card.c
@@ -103,7 +103,7 @@ iobase=0x%x irq=%d lo_dma=%d hi_dma=%d\n",
printk(KERN_ERR "sb_card: I/O port %x is already in use\n\n", hw_config->io_base);
return 0;
}
- return sb_dsp_detect(hw_config);
+ return sb_dsp_detect(hw_config, 0, 0);
}
void unload_sb(struct address_info *hw_config)
@@ -113,7 +113,7 @@ void unload_sb(struct address_info *hw_config)
}
int sb_be_quiet=0;
-int esstype = 0; /* ESS chip type */
+extern int esstype; /* ESS chip type */
#ifdef MODULE
@@ -130,13 +130,14 @@ int mpu_io = 0;
int io = -1;
int irq = -1;
int dma = -1;
-int dma16 = -1; /* Set this for modules that need it */
-int type = 0; /* Can set this to a specific card type */
-int mad16 = 0; /* Set mad16=1 to load this as support for mad16 */
-int trix = 0; /* Set trix=1 to load this as support for trix */
-int pas2 = 0; /* Set pas2=1 to load this as support for pas2 */
+int dma16 = -1; /* Set this for modules that need it */
+int type = 0; /* Can set this to a specific card type */
+int mad16 = 0; /* Set mad16=1 to load this as support for mad16 */
+int trix = 0; /* Set trix=1 to load this as support for trix */
+int pas2 = 0; /* Set pas2=1 to load this as support for pas2 */
+int support = 0; /* Set support to load this as a support module */
int sm_games = 0; /* Mixer - see sb_mixer.c */
-int acer = 0; /* Do acer notebook init */
+int acer = 0; /* Do acer notebook init */
MODULE_PARM(io, "i");
MODULE_PARM(irq, "i");
@@ -145,6 +146,7 @@ MODULE_PARM(dma16, "i");
MODULE_PARM(mpu_io, "i");
MODULE_PARM(type, "i");
MODULE_PARM(mad16, "i");
+MODULE_PARM(support, "i");
MODULE_PARM(trix, "i");
MODULE_PARM(pas2, "i");
MODULE_PARM(sm_games, "i");
@@ -156,7 +158,7 @@ int init_module(void)
{
printk(KERN_INFO "Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
- if (mad16 == 0 && trix == 0 && pas2 == 0)
+ if (mad16 == 0 && trix == 0 && pas2 == 0 && support == 0)
{
if (io == -1 || dma == -1 || irq == -1)
{
@@ -191,7 +193,7 @@ void cleanup_module(void)
{
if (smw_free)
vfree(smw_free);
- if (!mad16 && !trix && !pas2)
+ if (!mad16 && !trix && !pas2 && !support)
unload_sb(&config);
if (sbmpu)
unload_sbmpu(&config_mpu);
@@ -220,5 +222,8 @@ EXPORT_SYMBOL(attach_sb_card);
EXPORT_SYMBOL(probe_sb);
EXPORT_SYMBOL(unload_sb);
EXPORT_SYMBOL(sb_be_quiet);
+EXPORT_SYMBOL(attach_sbmpu);
+EXPORT_SYMBOL(probe_sbmpu);
+EXPORT_SYMBOL(unload_sbmpu);
#endif
diff --git a/drivers/sound/sb_common.c b/drivers/sound/sb_common.c
index 907250981..d162e470d 100644
--- a/drivers/sound/sb_common.c
+++ b/drivers/sound/sb_common.c
@@ -179,13 +179,25 @@ static void sb_intr (sb_devc *devc)
status = inb(DSP_DATA_AVL16);
}
+static void pci_intr(sb_devc *devc)
+{
+ int src = inb(devc->pcibase+0x1A);
+ src&=3;
+ if(src)
+ sb_intr(devc);
+}
+
static void sbintr(int irq, void *dev_id, struct pt_regs *dummy)
{
- sb_devc *devc = dev_id;
+ sb_devc *devc = dev_id;
devc->irq_ok = 1;
switch (devc->model) {
+ case MDL_ESSPCI:
+ pci_intr (devc);
+ break;
+
case MDL_ESS:
ess_intr (devc);
break;
@@ -249,7 +261,7 @@ static void dsp_get_vers(sb_devc * devc)
}
}
}
- DDB(printk("DSP version %d.%d\n", devc->major, devc->minor));
+ DDB(printk("DSP version %d.%02d\n", devc->major, devc->minor));
restore_flags(flags);
}
@@ -478,7 +490,7 @@ static void relocate_ess1688(sb_devc * devc)
#endif
}
-int sb_dsp_detect(struct address_info *hw_config)
+int sb_dsp_detect(struct address_info *hw_config, int pci, int pciio)
{
sb_devc sb_info;
sb_devc *devc = &sb_info;
@@ -508,7 +520,26 @@ int sb_dsp_detect(struct address_info *hw_config)
devc->dma8 = hw_config->dma;
devc->dma16 = -1;
-
+ devc->pcibase = pciio;
+
+ if(pci == SB_PCI_ESSMAESTRO)
+ {
+ devc->model = MDL_ESSPCI;
+ devc->caps |= SB_PCI_IRQ;
+ hw_config->driver_use_1 |= SB_PCI_IRQ;
+ hw_config->card_subtype = MDL_ESSPCI;
+ }
+
+ if(pci == SB_PCI_YAMAHA)
+ {
+ devc->model = MDL_YMPCI;
+ devc->caps |= SB_PCI_IRQ;
+ hw_config->driver_use_1 |= SB_PCI_IRQ;
+ hw_config->card_subtype = MDL_YMPCI;
+
+ printk("Yamaha PCI mode.\n");
+ }
+
if (acer)
{
cli();
@@ -569,6 +600,16 @@ int sb_dsp_detect(struct address_info *hw_config)
}
}
}
+
+ if(devc->type == MDL_ESSPCI)
+ devc->model = MDL_ESSPCI;
+
+ if(devc->type == MDL_YMPCI)
+ {
+ printk("YMPCI selected\n");
+ devc->model = MDL_YMPCI;
+ }
+
/*
* Save device information for sb_dsp_init()
*/
@@ -581,7 +622,7 @@ int sb_dsp_detect(struct address_info *hw_config)
return 0;
}
memcpy((char *) detected_devc, (char *) devc, sizeof(sb_devc));
- MDB(printk(KERN_INFO "SB %d.%d detected OK (%x)\n", devc->major, devc->minor, hw_config->io_base));
+ MDB(printk(KERN_INFO "SB %d.%02d detected OK (%x)\n", devc->major, devc->minor, hw_config->io_base));
return 1;
}
@@ -617,9 +658,17 @@ int sb_dsp_init(struct address_info *hw_config)
devc->caps = hw_config->driver_use_1;
- if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI) && hw_config->irq > 0)
+ if (!((devc->caps & SB_NO_AUDIO) && (devc->caps & SB_NO_MIDI)) && hw_config->irq > 0)
{ /* IRQ setup */
- if (request_irq(hw_config->irq, sbintr, 0, "soundblaster", devc) < 0)
+
+ /*
+ * ESS PCI cards do shared PCI IRQ stuff. Since they
+ * will get shared PCI irq lines we must cope.
+ */
+
+ int i=(devc->caps&SB_PCI_IRQ)?SA_SHIRQ:0;
+
+ if (request_irq(hw_config->irq, sbintr, i, "soundblaster", devc) < 0)
{
printk(KERN_ERR "SB: Can't allocate IRQ%d\n", hw_config->irq);
return 0;
@@ -768,7 +817,7 @@ int sb_dsp_init(struct address_info *hw_config)
if (hw_config->name == NULL)
hw_config->name = "Sound Blaster (8 BIT/MONO ONLY)";
- sprintf(name, "%s (%d.%d)", hw_config->name, devc->major, devc->minor);
+ sprintf(name, "%s (%d.%02d)", hw_config->name, devc->major, devc->minor);
conf_printf(name, hw_config);
/*
@@ -789,7 +838,7 @@ int sb_dsp_init(struct address_info *hw_config)
}
else if (!sb_be_quiet && devc->model == MDL_SBPRO)
{
- printk(KERN_INFO "SB DSP version is just %d.%d which means that your card is\n", devc->major, devc->minor);
+ printk(KERN_INFO "SB DSP version is just %d.%02d which means that your card is\n", devc->major, devc->minor);
printk(KERN_INFO "several years old (8 bit only device) or alternatively the sound driver\n");
printk(KERN_INFO "is incorrectly configured.\n");
}
@@ -1194,6 +1243,10 @@ int probe_sbmpu(struct address_info *hw_config)
return 0;
break;
+ case MDL_YMPCI:
+ hw_config->name = "Yamaha PCI Legacy";
+ printk("Yamaha PCI legacy UART401 check.\n");
+ break;
default:
return 0;
}
diff --git a/drivers/sound/sb_ess.c b/drivers/sound/sb_ess.c
index d1fdd4ccb..635be8a11 100644
--- a/drivers/sound/sb_ess.c
+++ b/drivers/sound/sb_ess.c
@@ -1,9 +1,46 @@
+#undef FKS_LOGGING
+#undef FKS_TEST
+
/*
- * Created: 9-Jan-1999
+ * tabs should be 4 spaces, in vi(m): set tabstop=4
*
* TODO: consistency speed calculations!!
+ * cleanup!
* ????: Did I break MIDI support?
*
+ * History:
+ *
+ * Rolf Fokkens (Dec 20 1998): ES188x recording level support on a per
+ * fokkensr@vertis.nl input basis.
+ * (Dec 24 1998): Recognition of ES1788, ES1887, ES1888,
+ * ES1868, ES1869 and ES1878. Could be used for
+ * specific handling in the future. All except
+ * ES1887 and ES1888 and ES688 are handled like
+ * ES1688.
+ * (Dec 27 1998): RECLEV for all (?) ES1688+ chips. ES188x now
+ * have the "Dec 20" support + RECLEV
+ * (Jan 2 1999): Preparation for Full Duplex. This means
+ * Audio 2 is now used for playback when dma16
+ * is specified. The next step would be to use
+ * Audio 1 and Audio 2 at the same time.
+ * (Jan 9 1999): Put all ESS stuff into sb_ess.[ch], this
+ * includes both the ESS stuff that has been in
+ * sb_*[ch] before I touched it and the ESS support
+ * I added later
+ * (Jan 23 1999): Full Duplex seems to work. I wrote a small
+ * test proggy which works OK. Haven't found
+ * any applications to test it though. So why did
+ * I bother to create it anyway?? :) Just for
+ * fun.
+ * (May 2 1999): I tried to be too smart by "introducing"
+ * ess_calc_best_speed (). The idea was that two
+ * dividers could be used to setup a samplerate,
+ * ess_calc_best_speed () would choose the best.
+ * This works for playback, but results in
+ * recording problems for high samplerates. I
+ * fixed this by removing ess_calc_best_speed ()
+ * and just doing what the documentation says.
+ *
* This files contains ESS chip specifics. It's based on the existing ESS
* handling as it resided in sb_common.c, sb_mixer.c and sb_audio.c. This
* file adds features like:
@@ -19,27 +56,13 @@
*
* ESS detection isn't full proof (yet). If it fails an additional module
* parameter esstype can be specified to be one of the following:
- * 688, 1688, 1868, 1869, 1788, 1887, 1888
- *
- * History:
- *
- * Rolf Fokkens (Dec 20 1998): ES188x recording level support on a per
- * input basis.
- * (Dec 24 1998): Recognition of ES1788, ES1887, ES1888,
- * ES1868, ES1869 and ES1878. Could be used for
- * specific handling in the future. All except
- * ES1887 and ES1888 and ES688 are handled like
- * ES1688.
- * (Dec 27 1998): RECLEV for all (?) ES1688+ chips. ES188x now
- * have the "Dec 20" support + RECLEV
- * (jan 2 1999): Preparation for Full Duplex. This means
- * Audio 2 is now used for playback when dma16
- * is specified. The next step would be to use
- * Audio 1 and Audio 2 at the same time.
+ * -1, 0, 688, 1688, 1868, 1869, 1788, 1887, 1888
+ * -1 means: mimic 2.0 behaviour,
+ * 0 means: auto detect.
+ * others: explicitly specify chip
+ * -1 is default, cause auto detect still doesn't work.
*/
-#undef FKS_LOGGING
-
/*
* About the documentation
*
@@ -156,13 +179,25 @@
* ES1946 yes This is a PCI chip; not handled by this driver
*/
+#include <linux/delay.h>
+
#include "sound_config.h"
#include "sb_mixer.h"
#include "sb.h"
#include "sb_ess.h"
-extern int esstype; /* module parameter in sb_card.c */
+#define ESSTYPE_LIKE20 -1 /* Mimic 2.0 behaviour */
+#define ESSTYPE_DETECT 0 /* Mimic 2.0 behaviour */
+
+int esstype = ESSTYPE_LIKE20; /* module parameter in sb_card.c */
+
+#define SUBMDL_ES1788 0x10 /* Subtype ES1788 for specific handling */
+#define SUBMDL_ES1868 0x11 /* Subtype ES1868 for specific handling */
+#define SUBMDL_ES1869 0x12 /* Subtype ES1869 for specific handling */
+#define SUBMDL_ES1878 0x13 /* Subtype ES1878 for specific handling */
+#define SUBMDL_ES1887 0x14 /* Subtype ES1887 for specific handling */
+#define SUBMDL_ES1888 0x15 /* Subtype ES1888 for specific handling */
#ifdef FKS_LOGGING
static void ess_show_mixerregs (sb_devc *devc);
@@ -288,6 +323,7 @@ static int ess_calc_div (int clock, int revert, int *speedp, int *diffp)
return retval;
}
+#ifdef OBSOLETE
static int ess_calc_best_speed
(int clock1, int rev1, int clock2, int rev2, int *divp, int *speedp)
{
@@ -311,6 +347,7 @@ static int ess_calc_best_speed
return retval;
}
+#endif
/*
* Depending on the audiochannel ESS devices can
@@ -322,7 +359,7 @@ static int ess_calc_best_speed
*/
static void ess_common_speed (sb_devc *devc, int *speedp, int *divp)
{
- int diff = 0, div, choice;
+ int diff = 0, div;
if (devc->duplex) {
/*
@@ -330,8 +367,11 @@ static void ess_common_speed (sb_devc *devc, int *speedp, int *divp)
*/
div = 0x80 | ess_calc_div (795500, 128, speedp, &diff);
} else {
- choice = ess_calc_best_speed (397700, 128, 795500, 256, &div, speedp);
- if (choice == 2) div |= 0x80;
+ if (*speedp > 22000) {
+ div = 0x80 | ess_calc_div (795500, 256, speedp, &diff);
+ } else {
+ div = 0x00 | ess_calc_div (397700, 128, speedp, &diff);
+ }
}
*divp = div;
}
@@ -370,45 +410,6 @@ printk (KERN_INFO "FKS: ess_speed (%d) b speed = %d, div=%x\n", audionum, devc->
}
}
-#if 0
-static void ess_speed(sb_devc * devc)
-{
- int divider;
- unsigned char bits = 0;
- int speed = devc->speed;
-
- if (speed < 4000)
- speed = 4000;
- else if (speed > 48000)
- speed = 48000;
-
- if (speed > 22000)
- {
- bits = 0x80;
- divider = 256 - (795500 + speed / 2) / speed;
- }
- else
- {
- divider = 128 - (397700 + speed / 2) / speed;
- }
-
- bits |= (unsigned char) divider;
-
- ess_write (devc, 0xa1, bits);
-
- /*
- * Set filter divider register
- */
-
- speed = (speed * 9) / 20; /* Set filter roll-off to 90% of speed/2 */
- divider = 256 - 7160000 / (speed * 82);
-
- ess_write (devc, 0xa2, divider);
-
- return;
-}
-#endif
-
static int ess_audio_prepare_for_input(int dev, int bsize, int bcount)
{
sb_devc *devc = audio_devs[dev]->devc;
@@ -931,6 +932,29 @@ static int ess_set_irq_hw (sb_devc * devc)
return ess_common_set_irq_hw (devc);
}
+#ifdef FKS_TEST
+
+/*
+ * FKS_test:
+ * for ES1887: 00, 18, non wr bits: 0001 1000
+ * for ES1868: 00, b8, non wr bits: 1011 1000
+ * for ES1888: 00, f8, non wr bits: 1111 1000
+ * for ES1688: 00, f8, non wr bits: 1111 1000
+ * + ES968
+ */
+
+static void FKS_test (sb_devc * devc)
+{
+ int val1, val2;
+ val1 = ess_getmixer (devc, 0x64);
+ ess_setmixer (devc, 0x64, ~val1);
+ val2 = ess_getmixer (devc, 0x64) ^ ~val1;
+ ess_setmixer (devc, 0x64, val1);
+ val1 ^= ess_getmixer (devc, 0x64);
+printk (KERN_INFO "FKS: FKS_test %02x, %02x\n", (val1 & 0x0ff), (val2 & 0x0ff));
+};
+#endif
+
static unsigned int ess_identify (sb_devc * devc)
{
unsigned int val;
@@ -1025,42 +1049,55 @@ int ess_init(sb_devc * devc, struct address_info *hw_config)
if (ess_major == 0x68 && (ess_minor & 0xf0) == 0x80) {
char *chip = NULL;
+ int submodel = -1;
- if (esstype) {
- int submodel = -1;
-
- switch (esstype) {
- case 688:
- submodel = 0x00;
- break;
- case 1688:
- submodel = 0x08;
- break;
- case 1868:
- submodel = SUBMDL_ES1868;
- break;
- case 1869:
- submodel = SUBMDL_ES1869;
- break;
- case 1788:
- submodel = SUBMDL_ES1788;
- break;
- case 1887:
- submodel = SUBMDL_ES1887;
- break;
- case 1888:
- submodel = SUBMDL_ES1888;
- break;
- };
- if (submodel != -1) {
- devc->submodel = submodel;
- sprintf (modelname, "ES%d", esstype);
- chip = modelname;
- };
+ switch (esstype) {
+ case ESSTYPE_DETECT:
+ case ESSTYPE_LIKE20:
+ break;
+ case 688:
+ submodel = 0x00;
+ break;
+ case 1688:
+ submodel = 0x08;
+ break;
+ case 1868:
+ submodel = SUBMDL_ES1868;
+ break;
+ case 1869:
+ submodel = SUBMDL_ES1869;
+ break;
+ case 1788:
+ submodel = SUBMDL_ES1788;
+ break;
+ case 1887:
+ submodel = SUBMDL_ES1887;
+ break;
+ case 1888:
+ submodel = SUBMDL_ES1888;
+ break;
+ default:
+ printk (KERN_ERR "Invalid esstype=%d specified\n", esstype);
+ return 0;
+ };
+ if (submodel != -1) {
+ devc->submodel = submodel;
+ sprintf (modelname, "ES%d", esstype);
+ chip = modelname;
};
if (chip == NULL && (ess_minor & 0x0f) < 8) {
chip = "ES688";
};
+#ifdef FKS_TEST
+FKS_test (devc);
+#endif
+ /*
+ * If Nothing detected yet, and we want 2.0 behaviour...
+ * Then let's assume it's ES1688.
+ */
+ if (chip == NULL && esstype == ESSTYPE_LIKE20) {
+ chip = "ES1688";
+ };
if (chip == NULL) {
int type;
@@ -1080,6 +1117,10 @@ int ess_init(sb_devc * devc, struct address_info *hw_config)
chip = "ES1878";
devc->submodel = SUBMDL_ES1878;
break;
+ default:
+ if ((type & 0x00ff) != ((type >> 8) & 0x00ff)) {
+ printk ("ess_init: Unrecognized %04x\n", type);
+ }
};
};
#if 0
@@ -1117,6 +1158,18 @@ int ess_init(sb_devc * devc, struct address_info *hw_config)
chip = "ES1688";
};
+ printk ( KERN_INFO "ESS chip %s %s%s\n"
+ , chip
+ , ( esstype == ESSTYPE_DETECT || esstype == ESSTYPE_LIKE20
+ ? "detected"
+ : "specified"
+ )
+ , ( esstype == ESSTYPE_LIKE20
+ ? " (kernel 2.0 compatible)"
+ : ""
+ )
+ );
+
sprintf(name,"ESS %s AudioDrive (rev %d)", chip, ess_minor & 0x0f);
} else {
strcpy(name, "Jazz16");
diff --git a/drivers/sound/sb_mixer.c b/drivers/sound/sb_mixer.c
index 97ce1b39d..06af0f434 100644
--- a/drivers/sound/sb_mixer.c
+++ b/drivers/sound/sb_mixer.c
@@ -673,6 +673,8 @@ int sb_mixer_init(sb_devc * devc)
switch (devc->model)
{
+ case MDL_ESSPCI:
+ case MDL_YMPCI:
case MDL_SBPRO:
case MDL_AZTECH:
case MDL_JAZZ:
diff --git a/drivers/sound/sequencer.c b/drivers/sound/sequencer.c
index 44207cb62..af40a2117 100644
--- a/drivers/sound/sequencer.c
+++ b/drivers/sound/sequencer.c
@@ -1105,7 +1105,7 @@ int sequencer_open(int dev, struct file *file)
*/
for (i = 0; i < max_mididev; i++)
- if (!midi_opened[i])
+ if (!midi_opened[i] && midi_devs[i])
{
if ((retval = midi_devs[i]->open(i, mode,
sequencer_midi_input, sequencer_midi_output)) >= 0)
@@ -1411,7 +1411,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
case SNDCTL_SEQ_TESTMIDI:
if (__get_user(midi_dev, (int *)arg))
return -EFAULT;
- if (midi_dev < 0 || midi_dev >= max_mididev)
+ if (midi_dev < 0 || midi_dev >= max_mididev || !midi_devs[midi_dev])
return -ENXIO;
if (!midi_opened[midi_dev] &&
@@ -1529,7 +1529,7 @@ int sequencer_ioctl(int dev, struct file *file, unsigned int cmd, caddr_t arg)
case SNDCTL_MIDI_INFO:
if (get_user(dev, (int *)(&(((struct midi_info *)arg)->device))))
return -EFAULT;
- if (dev < 0 || dev >= max_mididev)
+ if (dev < 0 || dev >= max_mididev || !midi_devs[dev])
return -ENXIO;
midi_devs[dev]->info.device = dev;
return copy_to_user(arg, &midi_devs[dev]->info, sizeof(struct midi_info))?-EFAULT:0;
diff --git a/drivers/sound/sonicvibes.c b/drivers/sound/sonicvibes.c
index b1899e143..c6d30d43f 100644
--- a/drivers/sound/sonicvibes.c
+++ b/drivers/sound/sonicvibes.c
@@ -3,7 +3,7 @@
/*
* sonicvibes.c -- S3 Sonic Vibes audio driver.
*
- * Copyright (C) 1998 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * Copyright (C) 1998-1999 Thomas Sailer (sailer@ife.ee.ethz.ch)
*
* 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
@@ -51,6 +51,23 @@
* 16.12.98 0.9 Fix a few f_file & FMODE_ bugs
* 06.01.99 0.10 remove the silly SA_INTERRUPT flag.
* hopefully killed the egcs section type conflict
+ * 12.03.99 0.11 cinfo.blocks should be reset after GETxPTR ioctl.
+ * reported by Johan Maes <joma@telindus.be>
+ * 22.03.99 0.12 return EAGAIN instead of EBUSY when O_NONBLOCK
+ * read/write cannot be executed
+ * 05.04.99 0.13 added code to sv_read and sv_write which should detect
+ * lockups of the sound chip and revive it. This is basically
+ * an ugly hack, but at least applications using this driver
+ * won't hang forever. I don't know why these lockups happen,
+ * it might well be the motherboard chipset (an early 486 PCI
+ * board with ALI chipset), since every busmastering 100MB
+ * ethernet card I've tried (Realtek 8139 and Macronix tulip clone)
+ * exhibit similar behaviour (they work for a couple of packets
+ * and then lock up and can be revived by ifconfig down/up).
+ * 07.04.99 0.14 implemented the following ioctl's: SOUND_PCM_READ_RATE,
+ * SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS;
+ * Alpha fixes reported by Peter Jones <pjones@redhat.com>
+ * Note: dmaio hack might still be wrong on archs other than i386
*
*/
@@ -251,7 +268,8 @@ struct sv_state {
int dev_dmfm;
/* hardware resources */
- unsigned int iosb, ioenh, iosynth, iomidi, iogame, iodmaa, iodmac, irq;
+ unsigned long iosb, ioenh, iosynth, iomidi, iogame; /* long for SPARC */
+ unsigned int iodmaa, iodmac, irq;
/* mixer stuff */
struct {
@@ -1293,8 +1311,20 @@ static ssize_t sv_read(struct file *file, char *buffer, size_t count, loff_t *pp
if (cnt <= 0) {
start_adc(s);
if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EBUSY;
- interruptible_sleep_on(&s->dma_adc.wait);
+ return ret ? ret : -EAGAIN;
+ if (!interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ)) {
+ printk(KERN_DEBUG "sv: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
+ s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count,
+ s->dma_adc.hwptr, s->dma_adc.swptr);
+ stop_adc(s);
+ spin_lock_irqsave(&s->lock, flags);
+ set_dmac(s, virt_to_bus(s->dma_adc.rawbuf), s->dma_adc.numfrag << s->dma_adc.fragshift);
+ /* program enhanced mode registers */
+ wrindir(s, SV_CIDMACBASECOUNT1, (s->dma_adc.fragsamples-1) >> 8);
+ wrindir(s, SV_CIDMACBASECOUNT0, s->dma_adc.fragsamples-1);
+ s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0;
+ spin_unlock_irqrestore(&s->lock, flags);
+ }
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
continue;
@@ -1353,8 +1383,20 @@ static ssize_t sv_write(struct file *file, const char *buffer, size_t count, lof
if (cnt <= 0) {
start_dac(s);
if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EBUSY;
- interruptible_sleep_on(&s->dma_dac.wait);
+ return ret ? ret : -EAGAIN;
+ if (!interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ)) {
+ printk(KERN_DEBUG "sv: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
+ s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count,
+ s->dma_dac.hwptr, s->dma_dac.swptr);
+ stop_dac(s);
+ spin_lock_irqsave(&s->lock, flags);
+ set_dmaa(s, virt_to_bus(s->dma_dac.rawbuf), s->dma_dac.numfrag << s->dma_dac.fragshift);
+ /* program enhanced mode registers */
+ wrindir(s, SV_CIDMAABASECOUNT1, (s->dma_dac.fragsamples-1) >> 8);
+ wrindir(s, SV_CIDMAABASECOUNT0, s->dma_dac.fragsamples-1);
+ s->dma_dac.count = s->dma_dac.hwptr = s->dma_dac.swptr = 0;
+ spin_unlock_irqrestore(&s->lock, flags);
+ }
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
continue;
@@ -1431,8 +1473,6 @@ static int sv_mmap(struct file *file, struct vm_area_struct *vma)
if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
return -EAGAIN;
db->mapped = 1;
- vma->vm_file = file;
- file->f_count++;
return 0;
}
@@ -1648,7 +1688,7 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
spin_lock_irqsave(&s->lock, flags);
sv_update_ptr(s);
cinfo.bytes = s->dma_adc.total_bytes;
- cinfo.blocks = s->dma_adc.total_bytes >> s->dma_adc.fragshift;
+ cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
cinfo.ptr = s->dma_adc.hwptr;
if (s->dma_adc.mapped)
s->dma_adc.count &= s->dma_adc.fragsize-1;
@@ -1661,7 +1701,7 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
spin_lock_irqsave(&s->lock, flags);
sv_update_ptr(s);
cinfo.bytes = s->dma_dac.total_bytes;
- cinfo.blocks = s->dma_dac.total_bytes >> s->dma_dac.fragshift;
+ cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift;
cinfo.ptr = s->dma_dac.hwptr;
if (s->dma_dac.mapped)
s->dma_dac.count &= s->dma_dac.fragsize-1;
@@ -1715,11 +1755,19 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
s->dma_dac.subdivision = val;
return 0;
- case SOUND_PCM_WRITE_FILTER:
- case SNDCTL_DSP_SETSYNCRO:
case SOUND_PCM_READ_RATE:
+ return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
+
case SOUND_PCM_READ_CHANNELS:
+ return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (SV_CFMT_STEREO << SV_CFMT_CSHIFT)
+ : (SV_CFMT_STEREO << SV_CFMT_ASHIFT))) ? 2 : 1, (int *)arg);
+
case SOUND_PCM_READ_BITS:
+ return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (SV_CFMT_16BIT << SV_CFMT_CSHIFT)
+ : (SV_CFMT_16BIT << SV_CFMT_ASHIFT))) ? 16 : 8, (int *)arg);
+
+ case SOUND_PCM_WRITE_FILTER:
+ case SNDCTL_DSP_SETSYNCRO:
case SOUND_PCM_READ_FILTER:
return -EINVAL;
@@ -1841,7 +1889,7 @@ static ssize_t sv_midi_read(struct file *file, char *buffer, size_t count, loff_
cnt = count;
if (cnt <= 0) {
if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EBUSY;
+ return ret ? ret : -EAGAIN;
interruptible_sleep_on(&s->midi.iwait);
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
@@ -1888,7 +1936,7 @@ static ssize_t sv_midi_write(struct file *file, const char *buffer, size_t count
cnt = count;
if (cnt <= 0) {
if (file->f_flags & O_NONBLOCK)
- return ret ? ret : -EBUSY;
+ return ret ? ret : -EAGAIN;
interruptible_sleep_on(&s->midi.owait);
if (signal_pending(current))
return ret ? ret : -ERESTARTSYS;
@@ -2273,7 +2321,7 @@ __initfunc(int init_sonicvibes(void))
if (!pci_present()) /* No PCI bus in this machine! */
return -ENODEV;
- printk(KERN_INFO "sv: version v0.10 time " __TIME__ " " __DATE__ "\n");
+ printk(KERN_INFO "sv: version v0.14 time " __TIME__ " " __DATE__ "\n");
#if 0
if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
@@ -2327,7 +2375,7 @@ __initfunc(int init_sonicvibes(void))
}
pci_write_config_dword(pcidev, 0x40, s->iodmaa | 9); /* enable and use extended mode */
pci_write_config_dword(pcidev, 0x48, s->iodmac | 9); /* enable */
- printk(KERN_DEBUG "sv: io ports: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+ printk(KERN_DEBUG "sv: io ports: %#lx %#lx %#lx %#lx %#lx %#x %#x\n",
s->iosb, s->ioenh, s->iosynth, s->iomidi, s->iogame, s->iodmaa, s->iodmac);
if (s->ioenh == 0 || s->iodmaa == 0 || s->iodmac == 0)
continue;
@@ -2337,7 +2385,7 @@ __initfunc(int init_sonicvibes(void))
pci_write_config_dword(pcidev, 0x60, wavetable_mem >> 12); /* wavetable base address */
if (check_region(s->ioenh, SV_EXTENT_ENH)) {
- printk(KERN_ERR "sv: io ports %#x-%#x in use\n", s->ioenh, s->ioenh+SV_EXTENT_ENH-1);
+ printk(KERN_ERR "sv: io ports %#lx-%#lx in use\n", s->ioenh, s->ioenh+SV_EXTENT_ENH-1);
goto err_region5;
}
request_region(s->ioenh, SV_EXTENT_ENH, "S3 SonicVibes PCM");
@@ -2352,12 +2400,12 @@ __initfunc(int init_sonicvibes(void))
}
request_region(s->iodmac, SV_EXTENT_DMA, "S3 SonicVibes DMAC");
if (check_region(s->iomidi, SV_EXTENT_MIDI)) {
- printk(KERN_ERR "sv: io ports %#x-%#x in use\n", s->iomidi, s->iomidi+SV_EXTENT_MIDI-1);
+ printk(KERN_ERR "sv: io ports %#lx-%#lx in use\n", s->iomidi, s->iomidi+SV_EXTENT_MIDI-1);
goto err_region2;
}
request_region(s->iomidi, SV_EXTENT_MIDI, "S3 SonicVibes Midi");
if (check_region(s->iosynth, SV_EXTENT_SYNTH)) {
- printk(KERN_ERR "sv: io ports %#x-%#x in use\n", s->iosynth, s->iosynth+SV_EXTENT_SYNTH-1);
+ printk(KERN_ERR "sv: io ports %#lx-%#lx in use\n", s->iosynth, s->iosynth+SV_EXTENT_SYNTH-1);
goto err_region1;
}
request_region(s->iosynth, SV_EXTENT_SYNTH, "S3 SonicVibes Synth");
@@ -2388,7 +2436,7 @@ __initfunc(int init_sonicvibes(void))
printk(KERN_ERR "sv: irq %u in use\n", s->irq);
goto err_irq;
}
- printk(KERN_INFO "sv: found adapter at io %#06x irq %u dmaa %#06x dmac %#06x revision %u\n",
+ printk(KERN_INFO "sv: found adapter at io %#lx irq %u dmaa %#06x dmac %#06x revision %u\n",
s->ioenh, s->irq, s->iodmaa, s->iodmac, rdindir(s, SV_CIREVISION));
/* register devices */
if ((s->dev_audio = register_sound_dsp(&sv_audio_fops, -1)) < 0)
diff --git a/drivers/sound/sound_core.c b/drivers/sound/sound_core.c
index 95c332208..9bc08fbd0 100644
--- a/drivers/sound/sound_core.c
+++ b/drivers/sound/sound_core.c
@@ -39,7 +39,6 @@
#include <linux/malloc.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/malloc.h>
#include <linux/fs.h>
#include <linux/sound.h>
#include <linux/major.h>
@@ -63,6 +62,10 @@ static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list,
int n=low;
if (index < 0) { /* first free */
+
+ while (*list && (*list)->unit_minor<n)
+ list=&((*list)->next);
+
while(n<top)
{
/* Found a hole ? */
@@ -73,7 +76,7 @@ static int __sound_insert_unit(struct sound_unit * s, struct sound_unit **list,
}
if(n>=top)
- return -ENOMEM;
+ return -ENOENT;
} else {
n = low+(index*16);
while (*list) {
@@ -141,13 +144,13 @@ static int sound_insert_unit(struct sound_unit **list, struct file_operations *f
int r;
struct sound_unit *s=(struct sound_unit *)kmalloc(sizeof(struct sound_unit), GFP_KERNEL);
if(s==NULL)
- return -1;
+ return -ENOMEM;
spin_lock(&sound_loader_lock);
r=__sound_insert_unit(s,list,fops,index,low,top);
spin_unlock(&sound_loader_lock);
- if(r==-1)
+ if(r<0)
kfree(s);
return r;
}
diff --git a/drivers/sound/soundcard.c b/drivers/sound/soundcard.c
index cf3b70fea..6731180b4 100644
--- a/drivers/sound/soundcard.c
+++ b/drivers/sound/soundcard.c
@@ -67,7 +67,11 @@ caddr_t sound_mem_blocks[1024];
int sound_nblocks = 0;
/* Persistent DMA buffers */
-int sound_dmap_flag = 0; /* Off by default */
+#ifdef CONFIG_SOUND_DMAP
+int sound_dmap_flag = 1;
+#else
+int sound_dmap_flag = 0;
+#endif
static int soundcard_configured = 0;
@@ -751,9 +755,6 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
vma->vm_page_prot))
return -EAGAIN;
- vma->vm_file = file;
- file->f_count++;
-
dmap->mapping_flags |= DMA_MAP_MAPPED;
if( audio_devs[dev]->d->mmap)
@@ -802,13 +803,6 @@ bad1:
return -1;
}
-static void destroy_special_devices(void)
-{
- unregister_sound_special(6);
- unregister_sound_special(1);
- unregister_sound_special(8);
-}
-
#ifdef MODULE
static void
#else
@@ -849,12 +843,19 @@ soundcard_init(void)
#endif
}
+#ifdef MODULE
+
+static void destroy_special_devices(void)
+{
+ unregister_sound_special(6);
+ unregister_sound_special(1);
+ unregister_sound_special(8);
+}
+
static int sound[20] = {
0
};
-#ifdef MODULE
-
int traceinit = 0;
static int dmabuf = 0;
MODULE_PARM(traceinit, "i");
diff --git a/drivers/sound/sscape.c b/drivers/sound/sscape.c
index 48017eeed..25bfaf3a7 100644
--- a/drivers/sound/sscape.c
+++ b/drivers/sound/sscape.c
@@ -943,7 +943,9 @@ int init_module(void)
mpu_config.irq = mpu_irq;
mpu_config.io_base = mpu_io;
-
+ /* WEH - Try to get right dma channel */
+ mpu_config.dma = dma;
+
if(spea != -1)
{
old_hardware = spea;
diff --git a/drivers/sound/sys_timer.c b/drivers/sound/sys_timer.c
index 2e74b6055..e7ca0c84b 100644
--- a/drivers/sound/sys_timer.c
+++ b/drivers/sound/sys_timer.c
@@ -13,6 +13,7 @@
*/
/*
* Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
+ * Andrew Veliath : adapted tmr2ticks from level 1 sequencer (avoid overflow)
*/
#include <linux/config.h>
@@ -39,11 +40,17 @@ static unsigned long
tmr2ticks(int tmr_value)
{
/*
- * Convert system timer ticks (HZ) to MIDI ticks
- * (divide # of MIDI ticks/minute by # of system ticks/minute).
+ * Convert timer ticks to MIDI ticks
*/
- return ((tmr_value * curr_tempo * curr_timebase) + (30 * 100)) / (60 * HZ);
+ unsigned long tmp;
+ unsigned long scale;
+
+ /* tmr_value (ticks per sec) *
+ 1000000 (usecs per sec) / HZ (ticks per sec) -=> usecs */
+ tmp = tmr_value * (1000000 / HZ);
+ scale = (60 * 1000000) / (curr_tempo * curr_timebase); /* usecs per MIDI tick */
+ return (tmp + scale / 2) / scale;
}
static void
diff --git a/drivers/sound/trix.c b/drivers/sound/trix.c
index 1a6b79c76..70b4af6d3 100644
--- a/drivers/sound/trix.c
+++ b/drivers/sound/trix.c
@@ -323,7 +323,7 @@ int probe_trix_sb(struct address_info *hw_config)
hw_config->name = "AudioTrix SB";
#ifdef CONFIG_SBDSP
- return sb_dsp_detect(hw_config);
+ return sb_dsp_detect(hw_config, 0, 0);
#else
return 0;
#endif