diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-12-06 23:51:34 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-12-06 23:51:34 +0000 |
commit | 230e5ab6a084ed50470f101934782dbf54b0d06b (patch) | |
tree | 5dd821c8d33f450470588e7a543f74bf74306e9e /drivers/sound/ics2101.c | |
parent | c9b1c8a64c6444d189856f1e26bdcb8b4cd0113a (diff) |
Merge with Linux 2.1.67.
Diffstat (limited to 'drivers/sound/ics2101.c')
-rw-r--r-- | drivers/sound/ics2101.c | 354 |
1 files changed, 169 insertions, 185 deletions
diff --git a/drivers/sound/ics2101.c b/drivers/sound/ics2101.c index 07666ec29..3c47f5a50 100644 --- a/drivers/sound/ics2101.c +++ b/drivers/sound/ics2101.c @@ -14,7 +14,7 @@ #include "sound_config.h" -#if defined(CONFIG_GUSHW) +#if defined(CONFIG_GUSHW) || defined(MODULE) #include <linux/ultrasound.h> #include "gus_hw.h" @@ -31,222 +31,206 @@ static int left_fix[ICS_MIXDEVS] = static int right_fix[ICS_MIXDEVS] = {2, 2, 2, 1, 2, 1}; -static int -scale_vol (int vol) +static int scale_vol(int vol) { - /* - * Experimental volume scaling by Risto Kankkunen. - * This should give smoother volume response than just - * a plain multiplication. - */ - int e; - - if (vol < 0) - vol = 0; - if (vol > 100) - vol = 100; - vol = (31 * vol + 50) / 100; - e = 0; - if (vol) - { - while (vol < 16) + /* + * Experimental volume scaling by Risto Kankkunen. + * This should give smoother volume response than just + * a plain multiplication. + */ + + int e; + + if (vol < 0) + vol = 0; + if (vol > 100) + vol = 100; + vol = (31 * vol + 50) / 100; + e = 0; + if (vol) { - vol <<= 1; - e--; + while (vol < 16) + { + vol <<= 1; + e--; + } + vol -= 16; + e += 7; } - vol -= 16; - e += 7; - } - return ((e << 4) + vol); + return ((e << 4) + vol); } -static void -write_mix (int dev, int chn, int vol) +static void write_mix(int dev, int chn, int vol) { - int *selector; - unsigned long flags; - int ctrl_addr = dev << 3; - int attn_addr = dev << 3; - - vol = scale_vol (vol); - - if (chn == CHN_LEFT) - { - selector = left_fix; - ctrl_addr |= 0x00; - attn_addr |= 0x02; - } - else - { - selector = right_fix; - ctrl_addr |= 0x01; - attn_addr |= 0x03; - } - - save_flags (flags); - cli (); - outb ((ctrl_addr), u_MixSelect); - outb ((selector[dev]), u_MixData); - outb ((attn_addr), u_MixSelect); - outb (((unsigned char) vol), u_MixData); - restore_flags (flags); + int *selector; + unsigned long flags; + int ctrl_addr = dev << 3; + int attn_addr = dev << 3; + + vol = scale_vol(vol); + + if (chn == CHN_LEFT) + { + selector = left_fix; + ctrl_addr |= 0x00; + attn_addr |= 0x02; + } + else + { + selector = right_fix; + ctrl_addr |= 0x01; + attn_addr |= 0x03; + } + + save_flags(flags); + cli(); + outb((ctrl_addr), u_MixSelect); + outb((selector[dev]), u_MixData); + outb((attn_addr), u_MixSelect); + outb(((unsigned char) vol), u_MixData); + restore_flags(flags); } -static int -set_volumes (int dev, int vol) +static int set_volumes(int dev, int vol) { - int left = vol & 0x00ff; - int right = (vol >> 8) & 0x00ff; - - if (left < 0) - left = 0; - if (left > 100) - left = 100; - if (right < 0) - right = 0; - if (right > 100) - right = 100; - - write_mix (dev, CHN_LEFT, left); - write_mix (dev, CHN_RIGHT, right); - - vol = left + (right << 8); - volumes[dev] = vol; - return vol; + int left = vol & 0x00ff; + int right = (vol >> 8) & 0x00ff; + + if (left < 0) + left = 0; + if (left > 100) + left = 100; + if (right < 0) + right = 0; + if (right > 100) + right = 100; + + write_mix(dev, CHN_LEFT, left); + write_mix(dev, CHN_RIGHT, right); + + vol = left + (right << 8); + volumes[dev] = vol; + return vol; } -static int -ics2101_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg) +static int ics2101_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg) { - if (((cmd >> 8) & 0xff) == 'M') - { - if (_SIOC_DIR (cmd) & _SIOC_WRITE) + if (((cmd >> 8) & 0xff) == 'M') { - int val; + if (_SIOC_DIR(cmd) & _SIOC_WRITE) + { + int val; + + val = *(int *) arg; + + switch (cmd & 0xff) + { + case SOUND_MIXER_RECSRC: + return gus_default_mixer_ioctl(dev, cmd, arg); + + case SOUND_MIXER_MIC: + return (*(int *) arg = set_volumes(DEV_MIC, val)); + + case SOUND_MIXER_CD: + return (*(int *) arg = set_volumes(DEV_CD, val)); - val = *(int *) arg; + case SOUND_MIXER_LINE: + return (*(int *) arg = set_volumes(DEV_LINE, val)); - switch (cmd & 0xff) - { - case SOUND_MIXER_RECSRC: - return gus_default_mixer_ioctl (dev, cmd, arg); - break; + case SOUND_MIXER_SYNTH: + return (*(int *) arg = set_volumes(DEV_GF1, val)); - case SOUND_MIXER_MIC: - return (*(int *) arg = set_volumes (DEV_MIC, val)); - break; + case SOUND_MIXER_VOLUME: + return (*(int *) arg = set_volumes(DEV_VOL, val)); - case SOUND_MIXER_CD: - return (*(int *) arg = set_volumes (DEV_CD, val)); - break; + default: + return -EINVAL; + } + } + else + { + switch (cmd & 0xff) /* + * Return parameters + */ + { - case SOUND_MIXER_LINE: - return (*(int *) arg = set_volumes (DEV_LINE, val)); - break; + case SOUND_MIXER_RECSRC: + return gus_default_mixer_ioctl(dev, cmd, arg); - case SOUND_MIXER_SYNTH: - return (*(int *) arg = set_volumes (DEV_GF1, val)); - break; + case SOUND_MIXER_DEVMASK: + return (*(int *) arg = MIX_DEVS); - case SOUND_MIXER_VOLUME: - return (*(int *) arg = set_volumes (DEV_VOL, val)); - break; + case SOUND_MIXER_STEREODEVS: + return (*(int *) arg = SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_SYNTH | SOUND_MASK_VOLUME | SOUND_MASK_MIC); - default: - return -EINVAL; - } + case SOUND_MIXER_RECMASK: + return (*(int *) arg = SOUND_MASK_MIC | SOUND_MASK_LINE); + + case SOUND_MIXER_CAPS: + return (*(int *) arg = 0); + break; + + case SOUND_MIXER_MIC: + return (*(int *) arg = volumes[DEV_MIC]); + + case SOUND_MIXER_LINE: + return (*(int *) arg = volumes[DEV_LINE]); + + case SOUND_MIXER_CD: + return (*(int *) arg = volumes[DEV_CD]); + + case SOUND_MIXER_VOLUME: + return (*(int *) arg = volumes[DEV_VOL]); + + case SOUND_MIXER_SYNTH: + return (*(int *) arg = volumes[DEV_GF1]); + + default: + return -EINVAL; + } + } } - else - switch (cmd & 0xff) /* - * Return parameters - */ - { - - case SOUND_MIXER_RECSRC: - return gus_default_mixer_ioctl (dev, cmd, arg); - break; - - case SOUND_MIXER_DEVMASK: - return (*(int *) arg = MIX_DEVS); - break; - - case SOUND_MIXER_STEREODEVS: - return (*(int *) arg = SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_SYNTH | SOUND_MASK_VOLUME | SOUND_MASK_MIC); - break; - - case SOUND_MIXER_RECMASK: - return (*(int *) arg = SOUND_MASK_MIC | SOUND_MASK_LINE); - break; - - case SOUND_MIXER_CAPS: - return (*(int *) arg = 0); - break; - - case SOUND_MIXER_MIC: - return (*(int *) arg = volumes[DEV_MIC]); - break; - - case SOUND_MIXER_LINE: - return (*(int *) arg = volumes[DEV_LINE]); - break; - - case SOUND_MIXER_CD: - return (*(int *) arg = volumes[DEV_CD]); - break; - - case SOUND_MIXER_VOLUME: - return (*(int *) arg = volumes[DEV_VOL]); - break; - - case SOUND_MIXER_SYNTH: - return (*(int *) arg = volumes[DEV_GF1]); - break; - - default: - return -EINVAL; - } - } - - return -EINVAL; + return -EINVAL; } static struct mixer_operations ics2101_mixer_operations = { - "ICS2101", - "ICS2101 Multimedia Mixer", - ics2101_mixer_ioctl + "ICS2101", + "ICS2101 Multimedia Mixer", + ics2101_mixer_ioctl }; -void -ics2101_mixer_init (void) +int +ics2101_mixer_init(void) { - int i; - - if (num_mixers < MAX_MIXER_DEV) - { - mixer_devs[num_mixers++] = &ics2101_mixer_operations; - - /* - * Some GUS v3.7 cards had some channels flipped. Disable - * the flipping feature if the model id is other than 5. - */ + int i; + int n; - if (inb (u_MixSelect) != 5) + if ((n = sound_alloc_mixerdev()) != -1) { - for (i = 0; i < ICS_MIXDEVS; i++) - left_fix[i] = 1; - for (i = 0; i < ICS_MIXDEVS; i++) - right_fix[i] = 2; + n = num_mixers; + mixer_devs[n] = &ics2101_mixer_operations; + + /* + * Some GUS v3.7 cards had some channels flipped. Disable + * the flipping feature if the model id is other than 5. + */ + + if (inb(u_MixSelect) != 5) + { + for (i = 0; i < ICS_MIXDEVS; i++) + left_fix[i] = 1; + for (i = 0; i < ICS_MIXDEVS; i++) + right_fix[i] = 2; + } + set_volumes(DEV_GF1, 0x5a5a); + set_volumes(DEV_CD, 0x5a5a); + set_volumes(DEV_MIC, 0x0000); + set_volumes(DEV_LINE, 0x5a5a); + set_volumes(DEV_VOL, 0x5a5a); + set_volumes(DEV_UNUSED, 0x0000); } - - set_volumes (DEV_GF1, 0x5a5a); - set_volumes (DEV_CD, 0x5a5a); - set_volumes (DEV_MIC, 0x0000); - set_volumes (DEV_LINE, 0x5a5a); - set_volumes (DEV_VOL, 0x5a5a); - set_volumes (DEV_UNUSED, 0x0000); - } - + return n; } #endif |