diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-06-17 13:25:08 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-06-17 13:25:08 +0000 |
commit | 59223edaa18759982db0a8aced0e77457d10c68e (patch) | |
tree | 89354903b01fa0a447bffeefe00df3044495db2e /drivers/sound/sb_ess.c | |
parent | db7d4daea91e105e3859cf461d7e53b9b77454b2 (diff) |
Merge with Linux 2.3.6. Sorry, this isn't tested on silicon, I don't
have a MIPS box at hand.
Diffstat (limited to 'drivers/sound/sb_ess.c')
-rw-r--r-- | drivers/sound/sb_ess.c | 1018 |
1 files changed, 427 insertions, 591 deletions
diff --git a/drivers/sound/sb_ess.c b/drivers/sound/sb_ess.c index 635be8a11..c6eb5c8d5 100644 --- a/drivers/sound/sb_ess.c +++ b/drivers/sound/sb_ess.c @@ -40,6 +40,10 @@ * recording problems for high samplerates. I * fixed this by removing ess_calc_best_speed () * and just doing what the documentation says. + *Javier Achirica(May 15 1999): Major cleanup, MPU IRQ sharing, hardware + * volume support, PNP chip configuration, + * full duplex in most cards, sample rate fine + * tuning. * * 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 @@ -192,12 +196,27 @@ int esstype = ESSTYPE_LIKE20; /* module parameter in sb_card.c */ +#define SUBMDL_ES688 0x00 /* Subtype ES688 for specific handling */ +#define SUBMDL_ES1688 0x08 /* Subtype ES1688 for specific handling */ #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 */ +#define SUBMDL_ES1879 0x14 /* Subtype ES1879 for specific handling */ +#define SUBMDL_ES1887 0x15 /* Subtype ES1887 for specific handling */ +#define SUBMDL_ES1888 0x16 /* Subtype ES1888 for specific handling */ + + /* Recording mixer, stereo full duplex */ +#define ESSCAP_NEW 0x00000100 + /* ISA PnP configuration */ +#define ESSCAP_PNP 0x00000200 + /* Full duplex, 6-bit volume, hardware volume controls */ +#define ESSCAP_ES18 0x00000400 + /* New interrupt handling system (ESS 1887) */ +#define ESSCAP_IRQ 0x00000800 + +#define ESSFMT_16 0x00000001 +#define ESSFMT_SIGNED 0x00000004 #ifdef FKS_LOGGING static void ess_show_mixerregs (sb_devc *devc); @@ -213,52 +232,6 @@ static void ess_chgmixer * * ****************************************************************************/ -struct ess_command {short cmd; short data;}; - -/* - * Commands for initializing Audio 1 for input (record) - */ -static struct ess_command ess_i08m[] = /* input 8 bit mono */ - { {0xb7, 0x51}, {0xb7, 0xd0}, {-1, 0} }; -static struct ess_command ess_i16m[] = /* input 16 bit mono */ - { {0xb7, 0x71}, {0xb7, 0xf4}, {-1, 0} }; -static struct ess_command ess_i08s[] = /* input 8 bit stereo */ - { {0xb7, 0x51}, {0xb7, 0x98}, {-1, 0} }; -static struct ess_command ess_i16s[] = /* input 16 bit stereo */ - { {0xb7, 0x71}, {0xb7, 0xbc}, {-1, 0} }; - -static struct ess_command *ess_inp_cmds[] = - { ess_i08m, ess_i16m, ess_i08s, ess_i16s }; - - -/* - * Commands for initializing Audio 1 for output (playback) - */ -static struct ess_command ess_o08m[] = /* output 8 bit mono */ - { {0xb6, 0x80}, {0xb7, 0x51}, {0xb7, 0xd0}, {-1, 0} }; -static struct ess_command ess_o16m[] = /* output 16 bit mono */ - { {0xb6, 0x00}, {0xb7, 0x71}, {0xb7, 0xf4}, {-1, 0} }; -static struct ess_command ess_o08s[] = /* output 8 bit stereo */ - { {0xb6, 0x80}, {0xb7, 0x51}, {0xb7, 0x98}, {-1, 0} }; -static struct ess_command ess_o16s[] = /* output 16 bit stereo */ - { {0xb6, 0x00}, {0xb7, 0x71}, {0xb7, 0xbc}, {-1, 0} }; - -static struct ess_command *ess_out_cmds[] = - { ess_o08m, ess_o16m, ess_o08s, ess_o16s }; - -static void ess_exec_commands - (sb_devc *devc, struct ess_command *cmdtab[]) -{ - struct ess_command *cmd; - - cmd = cmdtab [ ((devc->channels != 1) << 1) + (devc->bits != AFMT_U8) ]; - - while (cmd->cmd != -1) { - ess_write (devc, cmd->cmd, cmd->data); - cmd++; - } -} - static void ess_change (sb_devc *devc, unsigned int reg, unsigned int mask, unsigned int val) { @@ -298,56 +271,22 @@ static void ess_set_input_parms devc->irq_mode = IMODE_INPUT; } -static int ess_calc_div (int clock, int revert, int *speedp, int *diffp) +static int ess_calc_div (int clock, int *speedp, int *diffp) { int divider; int speed, diff; - int retval; speed = *speedp; divider = (clock + speed / 2) / speed; - retval = revert - divider; - if (retval > revert - 1) { - retval = revert - 1; - divider = revert - retval; + if (divider > 127) { + divider = 127; } - /* This line is suggested. Must be wrong I think - *speedp = (clock + divider / 2) / divider; - So I chose the next one */ - *speedp = clock / divider; diff = speed - *speedp; - if (diff < 0) diff =-diff; - *diffp = diff; - - return retval; -} - -#ifdef OBSOLETE -static int ess_calc_best_speed - (int clock1, int rev1, int clock2, int rev2, int *divp, int *speedp) -{ - int speed1 = *speedp, speed2 = *speedp; - int div1, div2; - int diff1, diff2; - int retval; - - div1 = ess_calc_div (clock1, rev1, &speed1, &diff1); - div2 = ess_calc_div (clock2, rev2, &speed2, &diff2); + *diffp = diff < 0 ? -diff : diff; - if (diff1 < diff2) { - *divp = div1; - *speedp = speed1; - retval = 1; - } else { - *divp = div2; - *speedp = speed2; - retval = 2; - } - - return retval; + return 128 - divider; } -#endif /* * Depending on the audiochannel ESS devices can @@ -359,21 +298,30 @@ static int ess_calc_best_speed */ static void ess_common_speed (sb_devc *devc, int *speedp, int *divp) { - int diff = 0, div; + int speed1 = *speedp, speed2 = *speedp; + int div1, div2; + int diff1, diff2; - if (devc->duplex) { - /* - * The 0x80 is important for the first audio channel - */ - div = 0x80 | ess_calc_div (795500, 128, speedp, &diff); + if (devc->caps & ESSCAP_NEW) { + div1 = 0x000 | ess_calc_div (793800, &speed1, &diff1); + div2 = 0x080 | ess_calc_div (768000, &speed2, &diff2); } else { if (*speedp > 22000) { - div = 0x80 | ess_calc_div (795500, 256, speedp, &diff); + div1 = 0x080 | ess_calc_div (795444, &speed1, &diff1); + div2 = 0x180 | ess_calc_div (793800, &speed2, &diff2); } else { - div = 0x00 | ess_calc_div (397700, 128, speedp, &diff); + div1 = 0x000 | ess_calc_div (397722, &speed1, &diff1); + div2 = 0x100 | ess_calc_div (396900, &speed2, &diff2); } } - *divp = div; + + if (diff1 < diff2) { + *divp = div1; + *speedp = speed1; + } else { + *divp = div2; + *speedp = speed2; + } } static void ess_speed (sb_devc *devc, int audionum) @@ -392,21 +340,13 @@ printk (KERN_INFO "FKS: ess_speed (%d) b speed = %d, div=%x\n", audionum, devc-> div2 = 256 - 7160000 / (speed * 82); - if (!devc->duplex) audionum = 1; - - if (audionum == 1) { - /* Change behaviour of register A1 * - sb_chg_mixer(devc, 0x71, 0x20, 0x20) - * For ES1869 only??? */ - ess_write (devc, 0xa1, div); - ess_write (devc, 0xa2, div2); - } else { + if ((devc->caps & ESSCAP_NEW) && audionum != 1) { ess_setmixer (devc, 0x70, div); - /* - * FKS: fascinating: 0x72 doesn't seem to work. - */ - ess_write (devc, 0xa2, div2); ess_setmixer (devc, 0x72, div2); + } else { + ess_change (devc, 0xba, 0x40, (div & 0x100) ? 0x40 : 0x00); + ess_write (devc, 0xa1, div & 0xff); + ess_write (devc, 0xa2, div2); } } @@ -414,77 +354,14 @@ static int ess_audio_prepare_for_input(int dev, int bsize, int bcount) { sb_devc *devc = audio_devs[dev]->devc; - ess_speed(devc, 1); - - sb_dsp_command(devc, DSP_CMD_SPKOFF); - ess_write (devc, 0xb8, 0x0e); /* Auto init DMA mode */ - ess_change (devc, 0xa8, 0x03, 3 - devc->channels); /* Mono/stereo */ - ess_write (devc, 0xb9, 2); /* Demand mode (4 bytes/DMA request) */ - - ess_exec_commands (devc, ess_inp_cmds); + ess_change (devc, 0xa8, 0x0b, 3 - devc->channels); /* Mono/stereo */ - ess_change (devc, 0xb1, 0xf0, 0x50); - ess_change (devc, 0xb2, 0xf0, 0x50); - - devc->trigger_bits = 0; - return 0; -} - -static int ess_audio_prepare_for_output_audio1 (int dev, int bsize, int bcount) -{ - sb_devc *devc = audio_devs[dev]->devc; - - sb_dsp_reset(devc); ess_speed(devc, 1); - ess_write (devc, 0xb8, 4); /* Auto init DMA mode */ - ess_change (devc, 0xa8, 0x03, 3 - devc->channels); /* Mono/stereo */ - ess_write (devc, 0xb9, 2); /* Demand mode (4 bytes/request) */ - - ess_exec_commands (devc, ess_out_cmds); - - ess_change (devc, 0xb1, 0xf0, 0x50); /* Enable DMA */ - ess_change (devc, 0xb2, 0xf0, 0x50); /* Enable IRQ */ - - sb_dsp_command(devc, DSP_CMD_SPKON); /* There be sound! */ - devc->trigger_bits = 0; - return 0; -} - -static int ess_audio_prepare_for_output_audio2 (int dev, int bsize, int bcount) -{ - sb_devc *devc = audio_devs[dev]->devc; - unsigned char bits; - -/* FKS: qqq - sb_dsp_reset(devc); -*/ - - /* - * Auto-Initialize: - * DMA mode + demand mode (8 bytes/request, yes I want it all!) - * But leave 16-bit DMA bit untouched! - */ - ess_chgmixer (devc, 0x78, 0xd0, 0xd0); - - ess_speed(devc, 2); - - /* bits 4:3 on ES1887 represent recording source. Keep them! */ - bits = ess_getmixer (devc, 0x7a) & 0x18; - - /* Set stereo/mono */ - if (devc->channels != 1) bits |= 0x02; - - /* Init DACs; UNSIGNED mode for 8 bit; SIGNED mode for 16 bit */ - if (devc->bits != AFMT_U8) bits |= 0x05; /* 16 bit */ - - /* Enable DMA, IRQ will be shared (hopefully)*/ - bits |= 0x60; - - ess_setmixer (devc, 0x7a, bits); - - ess_mixer_reload (devc, SOUND_MIXER_PCM); /* There be sound! */ + ess_write (devc, 0xb7, (devc->bits & ESSFMT_SIGNED) ? 0x71 : 0x51); + ess_write (devc, 0xb7, 0x90 | ((devc->bits & ESSFMT_SIGNED) ? 0x20 : 0) | + ((devc->bits & ESSFMT_16) ? 4 : 0) | ((devc->channels > 1) ? 8 : 0x40)); devc->trigger_bits = 0; return 0; @@ -500,144 +377,79 @@ printk(KERN_INFO "ess_audio_prepare_for_output: dma_out=%d,dma_in=%d\n" #endif if (devc->duplex) { - return ess_audio_prepare_for_output_audio2 (dev, bsize, bcount); - } else { - return ess_audio_prepare_for_output_audio1 (dev, bsize, bcount); - } -} + ess_speed(devc, 2); -static void ess_audio_halt_xfer(int dev) -{ - unsigned long flags; - sb_devc *devc = audio_devs[dev]->devc; - - save_flags(flags); - cli(); - sb_dsp_reset(devc); - restore_flags(flags); - - /* - * Audio 2 may still be operational! Creates awful sounds! - */ - if (devc->duplex) ess_chgmixer(devc, 0x78, 0x03, 0x00); -} - -static void ess_audio_start_input - (int dev, unsigned long buf, int nr_bytes, int intrflag) -{ - int count = nr_bytes; - sb_devc *devc = audio_devs[dev]->devc; - short c = -nr_bytes; - - /* - * Start a DMA input to the buffer pointed by dmaqtail - */ - - if (audio_devs[dev]->dmap_in->dma > 3) count >>= 1; - count--; - - devc->irq_mode = IMODE_INPUT; - - ess_write (devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff)); - ess_write (devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff)); - - ess_change (devc, 0xb8, 0x0f, 0x0f); /* Go */ - devc->intr_active = 1; -} - -static void ess_audio_output_block_audio1 - (int dev, unsigned long buf, int nr_bytes, int intrflag) -{ - int count = nr_bytes; - sb_devc *devc = audio_devs[dev]->devc; - short c = -nr_bytes; + ess_chgmixer (devc, 0x7a, 0x07, ((devc->bits & ESSFMT_SIGNED) ? 4 : 0) | + ((devc->bits & ESSFMT_16) ? 1 : 0) | ((devc->channels > 1) ? 2 : 0)); - if (audio_devs[dev]->dmap_out->dma > 3) - count >>= 1; - count--; + if (devc->caps & ESSCAP_NEW) + ess_mixer_reload (devc, SOUND_MIXER_PCM); /* There be sound! */ + else + sb_dsp_command(devc, DSP_CMD_SPKON); /* There be sound! */ + } else { + ess_write (devc, 0xb8, 4); /* Auto init DMA mode */ + ess_change (devc, 0xa8, 0x03, 3 - devc->channels); /* Mono/stereo */ - devc->irq_mode = IMODE_OUTPUT; + ess_speed(devc, 1); - ess_write (devc, 0xa4, (unsigned char) ((unsigned short) c & 0xff)); - ess_write (devc, 0xa5, (unsigned char) (((unsigned short) c >> 8) & 0xff)); + ess_write (devc, 0xb6, (devc->bits & ESSFMT_SIGNED) ? 0 : 0x80); + ess_write (devc, 0xb7, (devc->bits & ESSFMT_SIGNED) ? 0x71 : 0x51); + ess_write (devc, 0xb7, 0x90 | ((devc->bits & ESSFMT_SIGNED) ? 0x20 : 0) | + ((devc->bits & ESSFMT_16) ? 4 : 0) | ((devc->channels > 1) ? 8 : 0x40)); - ess_change (devc, 0xb8, 0x05, 0x05); /* Go */ - devc->intr_active = 1; + sb_dsp_command(devc, DSP_CMD_SPKON); /* There be sound! */ + } + devc->trigger_bits = 0; + return 0; } -static void ess_audio_output_block_audio2 - (int dev, unsigned long buf, int nr_bytes, int intrflag) +static void ess_audio_halt_xfer(int dev) { - int count = nr_bytes; sb_devc *devc = audio_devs[dev]->devc; - short c = -nr_bytes; - if (audio_devs[dev]->dmap_out->dma > 3) count >>= 1; - count--; + sb_dsp_command (devc, DSP_CMD_SPKOFF); - ess_setmixer (devc, 0x74, (unsigned char) ((unsigned short) c & 0xff)); - ess_setmixer (devc, 0x76, (unsigned char) (((unsigned short) c >> 8) & 0xff)); - ess_chgmixer (devc, 0x78, 0x03, 0x03); /* Go */ - - devc->irq_mode_16 = IMODE_OUTPUT; - devc->intr_active_16 = 1; -} + if (devc->caps & ESSCAP_NEW) { + ess_setmixer (devc, 0x7c, 0); + } -static void ess_audio_output_block - (int dev, unsigned long buf, int nr_bytes, int intrflag) -{ - sb_devc *devc = audio_devs[dev]->devc; + ess_change (devc, 0xb8, 0x0f, 0x00); /* Stop */ - if (devc->duplex) { - ess_audio_output_block_audio2 (dev, buf, nr_bytes, intrflag); - } else { - ess_audio_output_block_audio1 (dev, buf, nr_bytes, intrflag); + if (devc->duplex) { /* Audio 2 may still be operational! */ + ess_chgmixer (devc, 0x78, 0x03, 0x00); } } -/* - * FKS: the if-statements for both bits and bits_16 are quite alike. - * Combine this... - */ static void ess_audio_trigger(int dev, int bits) { sb_devc *devc = audio_devs[dev]->devc; - int bits_16 = bits & devc->irq_mode_16; + int bits_16 = bits & devc->irq_mode_16 & IMODE_OUTPUT; bits &= devc->irq_mode; if (!bits && !bits_16) { - /* FKS oh oh.... wrong?? for dma 16? */ - sb_dsp_command(devc, 0xd0); /* Halt DMA */ + sb_dsp_command (devc, 0xd0); /* Halt DMA */ + ess_chgmixer (devc, 0x78, 0x04, 0x00); /* Halt DMA 2 */ } if (bits) { - switch (devc->irq_mode) - { - case IMODE_INPUT: - ess_audio_start_input(dev, devc->trg_buf, devc->trg_bytes, - devc->trg_intrflag); - break; + short c = -devc->trg_bytes; - case IMODE_OUTPUT: - ess_audio_output_block(dev, devc->trg_buf, devc->trg_bytes, - devc->trg_intrflag); - break; - } + ess_write (devc, 0xa4, (unsigned char)((unsigned short) c & 0xff)); + ess_write (devc, 0xa5, (unsigned char)((unsigned short) c >> 8)); + ess_change (devc, 0xb8, 0x0f, (devc->irq_mode==IMODE_INPUT)?0x0f:0x05); + + devc->intr_active = 1; } if (bits_16) { - switch (devc->irq_mode_16) { - case IMODE_INPUT: - ess_audio_start_input(dev, devc->trg_buf_16, devc->trg_bytes_16, - devc->trg_intrflag_16); - break; + short c = -devc->trg_bytes_16; - case IMODE_OUTPUT: - ess_audio_output_block(dev, devc->trg_buf_16, devc->trg_bytes_16, - devc->trg_intrflag_16); - break; - } + ess_setmixer (devc, 0x74, (unsigned char)((unsigned short) c & 0xff)); + ess_setmixer (devc, 0x76, (unsigned char)((unsigned short) c >> 8)); + ess_chgmixer (devc, 0x78, 0x03, 0x03); /* Go */ + + devc->intr_active_16 = 1; } devc->trigger_bits = bits | bits_16; @@ -649,8 +461,8 @@ static int ess_audio_set_speed(int dev, int speed) int minspeed, maxspeed, dummydiv; if (speed > 0) { - minspeed = (devc->duplex ? 6215 : 5000 ); - maxspeed = (devc->duplex ? 44100 : 48000); + minspeed = (devc->caps & ESSCAP_NEW) ? 6047 : 3125; + maxspeed = 48000; if (speed < minspeed) speed = minspeed; if (speed > maxspeed) speed = maxspeed; @@ -661,38 +473,46 @@ static int ess_audio_set_speed(int dev, int speed) return devc->speed; } -/* - * FKS: This is a one-on-one copy of sb1_audio_set_bits - */ static unsigned int ess_audio_set_bits(int dev, unsigned int bits) { sb_devc *devc = audio_devs[dev]->devc; - if (bits != 0) { - if (bits == AFMT_U8 || bits == AFMT_S16_LE) { - devc->bits = bits; - } else { - devc->bits = AFMT_U8; - } + switch (bits) { + case 0: + break; + case AFMT_S16_LE: + devc->bits = ESSFMT_16 | ESSFMT_SIGNED; + break; + case AFMT_U16_LE: + devc->bits = ESSFMT_16; + break; + case AFMT_S8: + devc->bits = ESSFMT_SIGNED; + break; + default: + devc->bits = 0; + break; } return devc->bits; } -/* - * FKS: This is a one-on-one copy of sbpro_audio_set_channels - * (*) Modified it!! - */ static short ess_audio_set_channels(int dev, short channels) { sb_devc *devc = audio_devs[dev]->devc; - if (channels == 1 || channels == 2) devc->channels = channels; + if (devc->fullduplex && !(devc->caps & ESSCAP_NEW)) { + devc->channels = 1; + } else { + if (channels == 1 || channels == 2) { + devc->channels = channels; + } + } return devc->channels; } -static struct audio_driver ess_audio_driver = /* ESS ES688/1688 */ +static struct audio_driver ess_audio_driver = /* ESS ES688/1688/18xx */ { sb_audio_open, sb_audio_close, @@ -719,7 +539,7 @@ struct audio_driver *ess_audio_init (sb_devc *devc, int *audio_flags, int *format_mask) { *audio_flags = DMA_AUTOMODE; - *format_mask |= AFMT_S16_LE; + *format_mask |= AFMT_S16_LE | AFMT_U16_LE | AFMT_S8; if (devc->duplex) { int tmp_dma; @@ -742,10 +562,8 @@ struct audio_driver *ess_audio_init * ESS common * * * ****************************************************************************/ -static void ess_handle_channel - (char *channel, int dev, int intr_active, unsigned char flag, int irq_mode) +static void ess_handle_channel (int dev, int irq_mode) { - if (!intr_active || !flag) return; #ifdef FKS_REG_LOGGING printk(KERN_INFO "FKS: ess_handle_channel %s irq_mode=%d\n", channel, irq_mode); #endif @@ -767,48 +585,77 @@ printk(KERN_INFO "FKS: ess_handle_channel %s irq_mode=%d\n", channel, irq_mode); } /* - * FKS: TODO!!! Finish this! - * - * I think midi stuff uses uart401, without interrupts. - * So IMODE_MIDI isn't a value for devc->irq_mode. + * In the ESS 1888 model, how do we found out if the MPU interrupted ??? */ void ess_intr (sb_devc *devc) { int status; unsigned char src; - if (devc->submodel == SUBMDL_ES1887) { + if (devc->caps & ESSCAP_PNP) { + outb (devc->pcibase + 7, 0); /* Mask IRQs */ + src = inb (devc->pcibase + 6) & 0x0f; + } else if (devc->caps & ESSCAP_IRQ) { src = ess_getmixer (devc, 0x7f) >> 4; } else { - src = 0xff; + src = inb (DSP_STATUS) & 0x01; + if (devc->duplex && (ess_getmixer (devc, 0x7a) & 0x80)) { + src |= 0x02; + } + if ((devc->caps & ESSCAP_ES18) && (ess_getmixer (devc, 0x64) & 0x10)) { + src |= 0x04; + } +#if defined(CONFIG_MIDI) && defined(CONFIG_SOUND_MPU401) + /* + * This should work if dev_conf wasn't local to mpu401.c + */ +#if 0 + if ((int)devc->midi_irq_cookie >= 0 && + !(inb(dev_conf[(int)devc->midi_irq_cookie].base + 1) & 0x80)) { + src |= 0x08; + } +#endif +#endif } #ifdef FKS_REG_LOGGING printk(KERN_INFO "FKS: sbintr src=%x\n",(int)src); #endif - ess_handle_channel - ( "Audio 1" - , devc->dev, devc->intr_active , src & 0x01, devc->irq_mode ); - ess_handle_channel - ( "Audio 2" - , devc->dev, devc->intr_active_16, src & 0x02, devc->irq_mode_16); - /* - * Acknowledge interrupts - */ - if (devc->submodel == SUBMDL_ES1887 && (src & 0x02)) { - ess_chgmixer (devc, 0x7a, 0x80, 0x00); + if (src & 0x01) { + status = inb(DSP_DATA_AVAIL); /* Acknowledge interrupt */ + if (devc->intr_active) + ess_handle_channel (devc->dev, devc->irq_mode ); } - if (src & 0x01) { - status = inb(DSP_DATA_AVAIL); + if (src & 0x02) { + ess_chgmixer (devc, 0x7a, 0x80, 0x00); /* Acknowledge interrupt */ + if (devc->intr_active_16) + ess_handle_channel (devc->dev, devc->irq_mode_16); } -} -static void ess_extended (sb_devc * devc) -{ - /* Enable extended mode */ + if (src & 0x04) { + int left, right; + + ess_setmixer (devc, 0x66, 0x00); /* Hardware volume IRQ ack */ + + left = ess_getmixer (devc, 0x60); + right = ess_getmixer (devc, 0x62); - sb_dsp_command(devc, 0xc6); + left = (left & 0x40) ? 0 : ((left * 100 + 31)/ 63); /* Mute or scale */ + right = (right & 0x40) ? 0 : ((right * 100 + 31)/ 63); + + devc->levels[SOUND_MIXER_VOLUME] = left | (right << 8); + } + +#if defined(CONFIG_MIDI) && defined(CONFIG_SOUND_MPU401) + if ((int)devc->midi_irq_cookie >= 0 && (src & 0x08)) { + mpuintr (devc->irq, devc->midi_irq_cookie, NULL); + } +#endif + + if (devc->caps & ESSCAP_PNP) { + outb (devc->pcibase + 7, 0xff); /* Unmask IRQs */ + } } static int ess_write (sb_devc * devc, unsigned char reg, unsigned char data) @@ -838,7 +685,7 @@ static int ess_read (sb_devc * devc, unsigned char reg) int ess_dsp_reset(sb_devc * devc) { - int loopc; + int loopc, val; #ifdef FKS_REG_LOGGING printk(KERN_INFO "FKS: ess_dsp_reset 1\n"); @@ -859,77 +706,100 @@ ess_show_mixerregs (devc); DDB(printk("sb: No response to RESET\n")); return 0; /* Sorry */ } - ess_extended (devc); - - DEB(printk("sb_dsp_reset() OK\n")); - -#ifdef FKS_LOGGING -printk(KERN_INFO "FKS: dsp_reset 2\n"); -ess_show_mixerregs (devc); -#endif - return 1; -} + sb_dsp_command(devc, 0xc6); /* Enable extended mode */ + if (!(devc->caps & ESSCAP_PNP)) { + ess_setmixer (devc, 0x40, 0x03); /* Enable joystick and OPL3 */ -static int ess_irq_bits (int irq) -{ - switch (irq) { - case 2: - case 9: - return 0; - - case 5: - return 1; + switch (devc->irq) { + case 2: + case 9: + val = 1; + break; + case 5: + val = 2; + break; + case 7: + val = 3; + break; + case 10: + val = 4; + break; + case 11: + val = 5; + break; + default: + val = 0; + } /* IRQ config */ + ess_write (devc, 0xb1, 0xf0 | ((val && val != 5) ? val - 1 : 0)); - case 7: - return 2; + if (devc->caps & ESSCAP_IRQ) { + ess_setmixer (devc, 0x7f, 0x01 | (val << 1)); /* IRQ config */ + } - case 10: - return 3; + switch ((devc->duplex) ? devc->dma16 : devc->dma8) { + case 0: + val = 0x54; + break; + case 1: + val = 0x58; + break; + case 3: + val = 0x5c; + break; + default: + val = 0; + } + ess_write (devc, 0xb2, val); /* DMA1 config */ - default: - printk(KERN_ERR "ESS1688: Invalid IRQ %d\n", irq); - return -1; + if (devc->duplex) { + switch (devc->dma8) { + case 0: + val = 0x04; + break; + case 1: + val = 0x05; + break; + case 3: + val = 0x06; + break; + case 5: + val = 0x07; + break; + default: + val = 0; + } + ess_write (devc, 0x7d, val); /* DMA2 config */ + } } -} - -/* - * Set IRQ configuration register for all ESS models - */ -static int ess_common_set_irq_hw (sb_devc * devc) -{ - int irq_bits; - - if ((irq_bits = ess_irq_bits (devc->irq)) == -1) return 0; - - if (!ess_write (devc, 0xb1, 0x50 | (irq_bits << 2))) { - printk(KERN_ERR "ES1688: Failed to write to IRQ config register\n"); - return 0; + ess_change (devc, 0xb1, 0xf0, 0x50); /* Enable IRQ 1 */ + ess_change (devc, 0xb2, 0xf0, 0x50); /* Enable DMA 1 */ + ess_write (devc, 0xb9, 2); /* Demand mode (4 bytes/DMA request) */ + ess_setmixer (devc, 0x7a, 0x40); /* Enable IRQ 2 */ + /* Auto-Initialize DMA mode + demand mode (8 bytes/request) */ + if (devc->caps & ESSCAP_PNP) { + ess_setmixer (devc, 0x78, 0xd0); + ess_setmixer (devc, 0x64, 0x82); /* Enable HW volume interrupt */ + } else { + ess_setmixer (devc, 0x78, (devc->dma8 > 4) ? 0xf0 : 0xd0); + ess_setmixer (devc, 0x64, 0x42); /* Enable HW volume interrupt */ } - return 1; -} -/* - * I wanna use modern ES1887 mixer irq handling. Funny is the - * fact that my BIOS wants the same. But suppose someone's BIOS - * doesn't do this! - * This is independent of duplex. If there's a 1887 this will - * prevent it from going into 1888 mode. - */ -static void ess_es1887_set_irq_hw (sb_devc * devc) -{ - int irq_bits; - - if ((irq_bits = ess_irq_bits (devc->irq)) == -1) return; + if (devc->caps & ESSCAP_NEW) { + ess_setmixer (devc, 0x71, 0x32); /* Change behaviour of register A1 */ + ess_setmixer (devc, 0x1c, 0x05); /* Recording source is mixer */ + } else { + ess_change (devc, 0xb7, 0x80, 0x80); /* Enable DMA FIFO */ + } - ess_chgmixer (devc, 0x7f, 0x0f, 0x01 | ((irq_bits + 1) << 1)); -} + DEB(printk("sb_dsp_reset() OK\n")); -static int ess_set_irq_hw (sb_devc * devc) -{ - if (devc->submodel == SUBMDL_ES1887) ess_es1887_set_irq_hw (devc); +#ifdef FKS_LOGGING +printk(KERN_INFO "FKS: dsp_reset 2\n"); +ess_show_mixerregs (devc); +#endif - return ess_common_set_irq_hw (devc); + return 1; } #ifdef FKS_TEST @@ -955,7 +825,7 @@ printk (KERN_INFO "FKS: FKS_test %02x, %02x\n", (val1 & 0x0ff), (val2 & 0x0ff)); }; #endif -static unsigned int ess_identify (sb_devc * devc) +static unsigned int ess_identify (sb_devc * devc, int *control) { unsigned int val; unsigned long flags; @@ -969,8 +839,15 @@ static unsigned int ess_identify (sb_devc * devc) udelay(20); val |= inb(MIXER_DATA); udelay(20); + *control = inb(MIXER_DATA) << 8; + udelay(20); + *control |= inb(MIXER_DATA); + udelay(20); restore_flags(flags); + if (*control < 0 || *control > 0x3ff || check_region (*control, 8)) + *control = 0; + return val; } @@ -997,7 +874,6 @@ static int ess_probe (sb_devc * devc, int reg, int xorval) int ess_init(sb_devc * devc, struct address_info *hw_config) { - unsigned char cfg; int ess_major = 0, ess_minor = 0; int i; static char name[100], modelname[10]; @@ -1005,6 +881,7 @@ int ess_init(sb_devc * devc, struct address_info *hw_config) /* * Try to detect ESS chips. */ + devc->pcibase = 0; sb_dsp_command(devc, 0xe7); /* Return identification */ @@ -1056,10 +933,10 @@ int ess_init(sb_devc * devc, struct address_info *hw_config) case ESSTYPE_LIKE20: break; case 688: - submodel = 0x00; + submodel = SUBMDL_ES688; break; case 1688: - submodel = 0x08; + submodel = SUBMDL_ES1688; break; case 1868: submodel = SUBMDL_ES1868; @@ -1070,6 +947,12 @@ int ess_init(sb_devc * devc, struct address_info *hw_config) case 1788: submodel = SUBMDL_ES1788; break; + case 1878: + submodel = SUBMDL_ES1878; + break; + case 1879: + submodel = SUBMDL_ES1879; + break; case 1887: submodel = SUBMDL_ES1887; break; @@ -1102,7 +985,7 @@ FKS_test (devc); if (chip == NULL) { int type; - type = ess_identify (devc); + type = ess_identify (devc, &devc->pcibase); switch (type) { case 0x1868: @@ -1117,6 +1000,10 @@ FKS_test (devc); chip = "ES1878"; devc->submodel = SUBMDL_ES1878; break; + case 0x1879: + chip = "ES1879"; + devc->submodel = SUBMDL_ES1879; + break; default: if ((type & 0x00ff) != ((type >> 8) & 0x00ff)) { printk ("ess_init: Unrecognized %04x\n", type); @@ -1175,130 +1062,72 @@ FKS_test (devc); strcpy(name, "Jazz16"); } - hw_config->name = name; - /* FKS: sb_dsp_reset to enable extended mode???? */ - sb_dsp_reset(devc); /* Turn on extended mode */ - - /* - * Enable joystick and OPL3 - */ - cfg = ess_getmixer (devc, 0x40); - ess_setmixer (devc, 0x40, cfg | 0x03); - if (devc->submodel >= 8) { /* ES1688 */ - devc->caps |= SB_NO_MIDI; /* ES1688 uses MPU401 MIDI mode */ + switch (devc->submodel) { + case SUBMDL_ES1869: + case SUBMDL_ES1879: + devc->caps |= ESSCAP_NEW; + case SUBMDL_ES1868: + case SUBMDL_ES1878: + devc->caps |= ESSCAP_PNP | ESSCAP_ES18; + break; + case SUBMDL_ES1887: + devc->caps |= ESSCAP_IRQ; + case SUBMDL_ES1888: + devc->caps |= ESSCAP_NEW | ESSCAP_ES18; } - sb_dsp_reset (devc); - - /* - * This is important! If it's not done, the IRQ probe in sb_dsp_init - * may fail. - */ - return ess_set_irq_hw (devc); -} - -static int ess_set_dma_hw(sb_devc * devc) -{ - unsigned char cfg, dma_bits = 0, dma16_bits; - int dma; - -#ifdef FKS_LOGGING -printk(KERN_INFO "ess_set_dma_hw: dma8=%d,dma16=%d,dup=%d\n" -, devc->dma8, devc->dma16, devc->duplex); -#endif - - /* - * FKS: It seems as if this duplex flag isn't set yet. Check it. - */ - dma = devc->dma8; - - if (dma > 3 || dma < 0 || dma == 2) { - dma_bits = 0; - printk(KERN_ERR "ESS1688: Invalid DMA8 %d\n", dma); - return 0; - } else { - /* Extended mode DMA enable */ - cfg = 0x50; - - if (dma == 3) { - dma_bits = 3; - } else { - dma_bits = dma + 1; + if (devc->caps & ESSCAP_PNP) { + if (!devc->pcibase) { + printk (KERN_ERR "ESS PnP chip without PnP registers. Ignored\n"); + return 0; } + request_region (devc->pcibase, 8, "ESS18xx ctrl"); + + outb (0x07, devc->pcibase); /* Selects logical device #1 */ + outb (0x01, devc->pcibase + 1); + outb (0x28, devc->pcibase); + i = inb (devc->pcibase + 1) & 0x0f; + outb (0x28, devc->pcibase); /* Sets HW volume IRQ */ + outb (devc->irq << 4 | i, devc->pcibase + 1); + outb (0x70, devc->pcibase); /* Sets IRQ 1 */ + outb (devc->irq, devc->pcibase + 1); + outb (0x72, devc->pcibase); /* Sets IRQ 2 */ + outb (devc->irq, devc->pcibase + 1); + outb (0x74, devc->pcibase); /* Sets DMA 1 */ + outb (hw_config->dma, devc->pcibase + 1); + outb (0x75, devc->pcibase); /* Sets DMA 2 */ + outb (hw_config->dma2 >= 0 ? hw_config->dma2 : 4, devc->pcibase + 1); + } else if (devc->pcibase) { + printk (KERN_INFO "Non-PnP ESS card with PnP registers at %04Xh, ignoring them.\n", devc->pcibase); + devc->pcibase = 0; } - if (!ess_write (devc, 0xb2, cfg | (dma_bits << 2))) { - printk(KERN_ERR "ESS1688: Failed to write to DMA config register\n"); - return 0; - } + devc->caps |= SB_NO_MIDI; /* ES1688 uses MPU401 MIDI mode */ - if (devc->duplex) { - dma = devc->dma16; - dma16_bits = 0; + hw_config->name = name; + + sb_dsp_reset(devc); /* Turn on extended mode */ + + ess_setmixer (devc, 0x00, 0x00); /* Reset mixer registers */ - if (dma >= 0) { - switch (dma) { - case 0: - dma_bits = 0x04; - break; - case 1: - dma_bits = 0x05; - break; - case 3: - dma_bits = 0x06; - break; - case 5: - dma_bits = 0x07; - dma16_bits = 0x20; - break; - default: - printk(KERN_ERR "ESS1887: Invalid DMA16 %d\n", dma); - return 0; - }; - ess_chgmixer (devc, 0x78, 0x20, dma16_bits); - ess_chgmixer (devc, 0x7d, 0x07, dma_bits); - } - } return 1; } /* * This one is called from sb_dsp_init. - * - * Return values: - * 0: Failed - * 1: Succeeded or doesn't apply (not SUBMDL_ES1887) */ int ess_dsp_init (sb_devc *devc, struct address_info *hw_config) { /* - * This for ES1887 to run Full Duplex. Actually ES1888 - * is allowed to do so too. I have no idea yet if this - * will work for ES1888 however. - * * For SB16 having both dma8 and dma16 means enable - * Full Duplex. Let's try this for ES1887 too - * + * Full Duplex. Let's try this too */ - if (devc->submodel == SUBMDL_ES1887) { - if (hw_config->dma2 != -1) { - devc->dma16 = hw_config->dma2; - } - /* - * devc->duplex initialization is put here, cause - * ess_set_dma_hw needs it. - */ - if (devc->dma8 != devc->dma16 && devc->dma16 != -1) { + if ((devc->caps & ESSCAP_ES18) && hw_config->dma2 >= 0) { + devc->dma16 = hw_config->dma2; + if (devc->dma8 != devc->dma16) { devc->duplex = 1; } - - if (!ess_set_dma_hw (devc)) { - free_irq(devc->irq, devc); - return 0; - } - return 1; - } else { - return -1; } + return 1; } /**************************************************************************** @@ -1319,13 +1148,13 @@ int ess_dsp_init (sb_devc *devc, struct address_info *hw_config) #define ES1688_MIXER_DEVICES \ ( ES688_MIXER_DEVICES | SOUND_MASK_RECLEV ) -#define ES1887_RECORDING_DEVICES \ +#define ES_NEW_RECORDING_DEVICES \ ( ES1688_RECORDING_DEVICES | SOUND_MASK_LINE2 | SOUND_MASK_SYNTH) -#define ES1887_MIXER_DEVICES \ +#define ES_NEW_MIXER_DEVICES \ ( ES1688_MIXER_DEVICES ) /* - * Mixer registers of ES1887 + * Mixer registers of ES18xx with new capabilities * * These registers specifically take care of recording levels. To make the * mapping from playback devices to recording devices every recording @@ -1455,11 +1284,11 @@ MIX_ENT(ES_REC_MIXER_RECLINE3, 0x00, 0, 0, 0x00, 0, 0) }; /* - * This one is for ES1887. It's little different from es_rec_mix: it - * has 0x7c for PCM playback level. This is because ES1887 uses + * This one is for new ES's. It's little different from es_rec_mix: it + * has 0x7c for PCM playback level. This is because uses * Audio 2 for playback. */ -static mixer_tab es1887_mix = { +static mixer_tab es_new_mix = { MIX_ENT(SOUND_MIXER_VOLUME, 0x60, 5, 6, 0x62, 5, 6), MIX_ENT(SOUND_MIXER_BASS, 0x00, 0, 0, 0x00, 0, 0), MIX_ENT(SOUND_MIXER_TREBLE, 0x00, 0, 0, 0x00, 0, 0), @@ -1493,16 +1322,6 @@ MIX_ENT(ES_REC_MIXER_RECLINE2, 0x6c, 7, 4, 0x6c, 3, 4), MIX_ENT(ES_REC_MIXER_RECLINE3, 0x00, 0, 0, 0x00, 0, 0) }; -static int ess_has_rec_mixer (int submodel) -{ - switch (submodel) { - case SUBMDL_ES1887: - return 1; - default: - return 0; - }; -}; - #ifdef FKS_LOGGING static int ess_mixer_mon_regs[] = { 0x70, 0x71, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7d, 0x7f @@ -1533,15 +1352,13 @@ printk(KERN_INFO "FKS: write mixer %x: %x\n", port, value); save_flags(flags); cli(); - if (port >= 0xa0) { - ess_write (devc, port, value); - } else { - outb(((unsigned char) (port & 0xff)), MIXER_ADDR); - udelay(20); - outb(((unsigned char) (value & 0xff)), MIXER_DATA); - udelay(20); - }; + outb(((unsigned char) (port & 0xff)), MIXER_ADDR); + + udelay(20); + outb(((unsigned char) (value & 0xff)), MIXER_DATA); + udelay(20); + restore_flags(flags); } @@ -1553,15 +1370,12 @@ unsigned int ess_getmixer (sb_devc * devc, unsigned int port) save_flags(flags); cli(); - if (port >= 0xa0) { - val = ess_read (devc, port); - } else { - outb(((unsigned char) (port & 0xff)), MIXER_ADDR); + outb(((unsigned char) (port & 0xff)), MIXER_ADDR); + + udelay(20); + val = inb(MIXER_DATA); + udelay(20); - udelay(20); - val = inb(MIXER_DATA); - udelay(20); - } restore_flags(flags); return val; @@ -1585,23 +1399,21 @@ void ess_mixer_init (sb_devc * devc) devc->mixer_caps = SOUND_CAP_EXCL_INPUT; /* - * Take care of ES1887 specifics... + * Take care of new ES's specifics... */ - switch (devc->submodel) { - case SUBMDL_ES1887: - devc->supported_devices = ES1887_MIXER_DEVICES; - devc->supported_rec_devices = ES1887_RECORDING_DEVICES; + if (devc->caps & ESSCAP_NEW) { + devc->supported_devices = ES_NEW_MIXER_DEVICES; + devc->supported_rec_devices = ES_NEW_RECORDING_DEVICES; #ifdef FKS_LOGGING printk (KERN_INFO "FKS: ess_mixer_init dup = %d\n", devc->duplex); #endif if (devc->duplex) { - devc->iomap = &es1887_mix; + devc->iomap = &es_new_mix; } else { devc->iomap = &es_rec_mix; } - break; - default: - if (devc->submodel < 8) { + } else { + if (devc->submodel == SUBMDL_ES688) { devc->supported_devices = ES688_MIXER_DEVICES; devc->supported_rec_devices = ES688_RECORDING_DEVICES; devc->iomap = &es688_mix; @@ -1612,10 +1424,10 @@ printk (KERN_INFO "FKS: ess_mixer_init dup = %d\n", devc->duplex); */ devc->supported_devices = ES1688_MIXER_DEVICES; devc->supported_rec_devices = ES1688_RECORDING_DEVICES; - if (devc->submodel < 0x10) { - devc->iomap = &es1688_mix; - } else { + if (devc->caps & ESSCAP_ES18) { devc->iomap = &es1688later_mix; + } else { + devc->iomap = &es1688_mix; } } } @@ -1627,9 +1439,15 @@ printk (KERN_INFO "FKS: ess_mixer_init dup = %d\n", devc->duplex); */ int ess_mixer_set(sb_devc *devc, int dev, int left, int right) { - if (ess_has_rec_mixer (devc->submodel) && (devc->recmask & (1 << dev))) { + if ((devc->caps & ESSCAP_NEW) && (devc->recmask & (1 << dev))) { sb_common_mixer_set (devc, dev + ES_REC_MIXER_RECDIFF, left, right); } + /* Set & unmute master volume */ + if ((devc->caps & ESSCAP_ES18) && (dev == SOUND_MIXER_VOLUME)) { + ess_chgmixer (devc, 0x60, 0x7f, 0x3f & ((left * 0x3f + 50) / 100)); + ess_chgmixer (devc, 0x62, 0x7f, 0x3f & ((right * 0x3f + 50) / 100)); + return left | (right << 8); + } return sb_common_mixer_set (devc, dev, left, right); } @@ -1675,7 +1493,6 @@ printk (KERN_INFO "FKS: es_rec_set_recmask mask = %x\n", mask); right = (value & 0x0000ff00) >> 8; } else { /* Turn it off (3) */ left = 0; - left = 0; right = 0; } sb_common_mixer_set(devc, i + ES_REC_MIXER_RECDIFF, left, right); @@ -1688,7 +1505,7 @@ int ess_set_recmask(sb_devc * devc, int *mask) { /* This applies to ESS chips with record mixers only! */ - if (ess_has_rec_mixer (devc->submodel)) { + if (devc->caps & ESSCAP_NEW) { *mask = es_rec_set_recmask (devc, *mask); return 1; /* Applied */ } else { @@ -1704,18 +1521,7 @@ int ess_mixer_reset (sb_devc * devc) /* * Separate actions for ESS chips with a record mixer: */ - if (ess_has_rec_mixer (devc->submodel)) { - switch (devc->submodel) { - case SUBMDL_ES1887: - /* - * Separate actions for ES1887: - * Change registers 7a and 1c to make the record mixer the - * actual recording source. - */ - ess_chgmixer(devc, 0x7a, 0x18, 0x08); - ess_chgmixer(devc, 0x1c, 0x07, 0x07); - break; - }; + if (devc->caps & ESSCAP_NEW) { /* * Call set_recmask for proper initialization */ @@ -1735,50 +1541,80 @@ int ess_mixer_reset (sb_devc * devc) * * ****************************************************************************/ -/* - * FKS: IRQ may be shared. Hm. And if so? Then What? - */ int ess_midi_init(sb_devc * devc, struct address_info *hw_config) { - unsigned char cfg, tmp; + int val; - cfg = ess_getmixer (devc, 0x40) & 0x03; - - if (devc->submodel < 8) { - ess_setmixer (devc, 0x40, cfg | 0x03); /* Enable OPL3 & joystick */ - return 0; /* ES688 doesn't support MPU401 mode */ + if (devc->submodel == SUBMDL_ES688) { + return 0; /* ES688 doesn't support MPU401 mode */ } - tmp = (hw_config->io_base & 0x0f0) >> 4; - if (tmp > 3) { - ess_setmixer (devc, 0x40, cfg); - return 0; + if (hw_config->irq < 2) { + hw_config->irq = devc->irq; } - cfg |= tmp << 3; - - tmp = 1; /* MPU enabled without interrupts */ - /* May be shared: if so the value is -ve */ + if (devc->caps & ESSCAP_PNP) { + outb (0x07, devc->pcibase); /* Selects logical device #1 */ + outb (0x01, devc->pcibase + 1); + outb (0x28, devc->pcibase); + val = inb (devc->pcibase + 1) & 0xf0; + outb (0x28, devc->pcibase); /* Sets MPU IRQ */ + outb (hw_config->irq | val, devc->pcibase + 1); + if (hw_config->io_base) { + outb (0x64, devc->pcibase); /* Sets MPU I/O address */ + outb ((hw_config->io_base & 0xf00) >> 8, devc->pcibase + 1); + outb (0x65, devc->pcibase); /* Sets MPU I/O address */ + outb (hw_config->io_base & 0xfc, devc->pcibase + 1); + } else { + outb (0x64, devc->pcibase); /* Read MPU I/O address */ + hw_config->io_base = (inb (devc->pcibase + 1) & 0x0f) << 8; + outb (0x65, devc->pcibase); /* Read MPU I/O address */ + hw_config->io_base |= inb (devc->pcibase + 1) & 0xfc; + } - switch (abs(hw_config->irq)) { - case 9: - tmp = 0x4; - break; - case 5: - tmp = 0x5; - break; - case 7: - tmp = 0x6; - break; - case 10: - tmp = 0x7; - break; - default: - return 0; + ess_setmixer (devc, 0x64, 0xc2); /* Enable MPU interrupt */ + } else { + if (devc->irq == hw_config->irq && (devc->caps & ESSCAP_IRQ)) { + val = 0x43; + } + else switch (hw_config->irq) { + case 11: + if (!(devc->caps & ESSCAP_IRQ)) { + return 0; + } + val = 0x63; + break; + case 2: + case 9: + val = 0x83; + break; + case 5: + val = 0xa3; + break; + case 7: + val = 0xc3; + break; + case 10: + val = 0xe3; + break; + default: + return 0; + } + switch (hw_config->io_base) { + case 0x300: + case 0x310: + case 0x320: + case 0x330: + ess_setmixer (devc, 0x40, val + | ((hw_config->io_base & 0x0f0) >> 1)); + break; + default: + return 0; + } } - cfg |= tmp << 5; - ess_setmixer (devc, 0x40, cfg | 0x03); + if (devc->irq == hw_config->irq) /* Shared IRQ */ + hw_config->irq = -devc->irq; return 1; } |