diff -urN linux-2.4.18/drivers/sound/emu10k1/8010.h linux/drivers/sound/emu10k1/8010.h --- linux-2.4.18/drivers/sound/emu10k1/8010.h Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/8010.h Fri Mar 1 20:55:19 2002 @@ -1,7 +1,7 @@ /* ********************************************************************** * 8010.h - * Copyright 1999, 2000 Creative Labs, Inc. + * Copyright 1999-2001 Creative Labs, Inc. * ********************************************************************** * @@ -11,6 +11,8 @@ * November 2, 1999 Alan Cox Cleaned of 8bit chars, DOS * line endings * December 8, 1999 Jon Taylor Added lots of new register info + * May 16, 2001 Daniel Bertrand Added unofficial DBG register info + * Oct-Nov 2001 D.B. Added unofficial Audigy registers * ********************************************************************** * @@ -39,6 +41,14 @@ #include +// Driver version: +#define MAJOR_VER 0 +#define MINOR_VER 19 +#define DRIVER_VERSION "0.19" + + +// Audigy specify registers are prefixed with 'A_' + /************************************************************************************************/ /* PCI function 0 registers, address = + PCIBASE0 */ /************************************************************************************************/ @@ -57,6 +67,11 @@ #define IPR 0x08 /* Global interrupt pending register */ /* Clear pending interrupts by writing a 1 to */ /* the relevant bits and zero to the other bits */ + +/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1) */ +#define IPR_A_MIDITRANSBUFEMPTY2 0x10000000 /* MIDI UART transmit buffer empty */ +#define IPR_A_MIDIRECVBUFEMPTY2 0x08000000 /* MIDI UART receive buffer empty */ + #define IPR_SAMPLERATETRACKER 0x01000000 /* Sample rate tracker lock status change */ #define IPR_FXDSP 0x00800000 /* Enable FX DSP interrupts */ #define IPR_FORCEINT 0x00400000 /* Force Sound Blaster interrupt */ @@ -81,6 +96,10 @@ /* IP is written with CL set, the bit in CLIPL */ /* or CLIPH corresponding to the CIN value */ /* written will be cleared. */ +#define IPR_A_MIDITRANSBUFEMPTY1 IPR_MIDITRANSBUFEMPTY /* MIDI UART transmit buffer empty */ +#define IPR_A_MIDIRECVBUFEMPTY1 IPR_MIDIRECVBUFEMPTY /* MIDI UART receive buffer empty */ + + #define INTE 0x0c /* Interrupt enable register */ #define INTE_VIRTUALSB_MASK 0xc0000000 /* Virtual Soundblaster I/O port capture */ @@ -108,6 +127,11 @@ /* behavior and possibly random segfaults and */ /* lockups if enabled. */ +/* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1) */ +#define INTE_A_MIDITXENABLE2 0x00020000 /* Enable MIDI transmit-buffer-empty interrupts */ +#define INTE_A_MIDIRXENABLE2 0x00010000 /* Enable MIDI receive-buffer-empty interrupts */ + + #define INTE_SAMPLERATETRACKER 0x00002000 /* Enable sample rate tracker interrupts */ /* NOTE: This bit must always be enabled */ #define INTE_FXDSPENABLE 0x00001000 /* Enable FX DSP interrupts */ @@ -124,6 +148,10 @@ #define INTE_MIDITXENABLE 0x00000002 /* Enable MIDI transmit-buffer-empty interrupts */ #define INTE_MIDIRXENABLE 0x00000001 /* Enable MIDI receive-buffer-empty interrupts */ +/* The next two interrupts are for the midi port on the Audigy (A_MPU2) */ +#define INTE_A_MIDITXENABLE1 INTE_MIDITXENABLE +#define INTE_A_MIDIRXENABLE1 INTE_MIDIRXENABLE + #define WC 0x10 /* Wall Clock register */ #define WC_SAMPLECOUNTER_MASK 0x03FFFFC0 /* Sample periods elapsed since reset */ #define WC_SAMPLECOUNTER 0x14060010 @@ -186,6 +214,8 @@ /* Should be set to 1 when the EMU10K1 is */ /* completely initialized. */ +//For Audigy, MPU port move to 0x70-0x74 ptr register + #define MUDATA 0x18 /* MPU401 data register (8 bits) */ #define MUCMD 0x19 /* MPU401 command register (8 bits) */ @@ -197,6 +227,10 @@ #define MUSTAT_IRDYN 0x80 /* 0 = MIDI data or command ACK */ #define MUSTAT_ORDYN 0x40 /* 0 = MUDATA can accept a command or data */ +#define A_IOCFG 0x18 /* GPIO on Audigy card (16bits) */ +#define A_GPINPUT_MASK 0xff00 +#define A_GPOUTPUT_MASK 0x00ff + #define TIMER 0x1a /* Timer terminal count register */ /* NOTE: After the rate is changed, a maximum */ /* of 1024 sample periods should be allowed */ @@ -386,6 +420,8 @@ #define TREMFRQ 0x1c /* Tremolo amount and modulation LFO frequency register */ #define TREMFRQ_DEPTH 0x0000ff00 /* Tremolo depth */ /* Signed 2's complement, with +/- 12dB extremes */ +#define TREMFRQ_FREQUENCY 0x000000ff /* Tremolo LFO frequency */ + /* ??Hz steps, maximum of ?? Hz. */ #define FM2FRQ2 0x1d /* Vibrato amount and vibrato LFO frequency register */ #define FM2FRQ2_DEPTH 0x0000ff00 /* Vibrato LFO vibrato depth */ @@ -426,7 +462,12 @@ #define ADCCR_LCHANENABLE 0x00000008 /* Enables left channel for writing to the host */ /* NOTE: To guarantee phase coherency, both channels */ /* must be disabled prior to enabling both channels. */ +#define A_ADCCR_RCHANENABLE 0x00000020 +#define A_ADCCR_LCHANENABLE 0x00000010 + +#define A_ADCCR_SAMPLERATE_MASK 0x0000000F /* Audigy sample rate convertor output rate */ #define ADCCR_SAMPLERATE_MASK 0x00000007 /* Sample rate convertor output rate */ + #define ADCCR_SAMPLERATE_48 0x00000000 /* 48kHz sample rate */ #define ADCCR_SAMPLERATE_44 0x00000001 /* 44.1kHz sample rate */ #define ADCCR_SAMPLERATE_32 0x00000002 /* 32kHz sample rate */ @@ -436,6 +477,10 @@ #define ADCCR_SAMPLERATE_11 0x00000006 /* 11.025kHz sample rate */ #define ADCCR_SAMPLERATE_8 0x00000007 /* 8kHz sample rate */ +#define A_ADCCR_SAMPLERATE_12 0x00000006 /* 12kHz sample rate */ +#define A_ADCCR_SAMPLERATE_11 0x00000007 /* 11.025kHz sample rate */ +#define A_ADCCR_SAMPLERATE_8 0x00000008 /* 8kHz sample rate */ + #define FXWC 0x43 /* FX output write channels register */ /* When set, each bit enables the writing of the */ /* corresponding FX output channel into host memory */ @@ -519,6 +564,13 @@ #define REG53 0x53 /* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */ +#define A_DBG 0x53 +#define A_DBG_SINGLE_STEP 0x00020000 /* Set to zero to start dsp */ +#define A_DBG_ZC 0x40000000 /* zero tram counter */ +#define A_DBG_STEP_ADDR 0x000003ff +#define A_DBG_SATURATION_OCCURED 0x20000000 +#define A_DBG_SATURATION_ADDR 0x0ffc0000 + #define SPCS0 0x54 /* SPDIF output Channel Status 0 register */ #define SPCS1 0x55 /* SPDIF output Channel Status 1 register */ @@ -582,10 +634,19 @@ #define SRCS_RATELOCKED 0x01000000 /* Sample rate locked */ #define SRCS_ESTSAMPLERATE 0x0007ffff /* Do not modify this field. */ + +/* Note that these values can vary +/- by a small amount */ +#define SRCS_SPDIFRATE_44 0x0003acd9 +#define SRCS_SPDIFRATE_48 0x00040000 +#define SRCS_SPDIFRATE_96 0x00080000 + #define MICIDX 0x63 /* Microphone recording buffer index register */ #define MICIDX_MASK 0x0000ffff /* 16-bit value */ #define MICIDX_IDX 0x10000063 +#define A_ADCIDX 0x63 +#define A_ADCIDX_IDX 0x10000063 + #define ADCIDX 0x64 /* ADC recording buffer index register */ #define ADCIDX_MASK 0x0000ffff /* 16 bit index field */ #define ADCIDX_IDX 0x10000064 @@ -594,9 +655,44 @@ #define FXIDX_MASK 0x0000ffff /* 16-bit value */ #define FXIDX_IDX 0x10000065 +/* This is the MPU port on the card (via the game port) */ +#define A_MUDATA1 0x70 +#define A_MUCMD1 0x71 +#define A_MUSTAT1 A_MUCMD1 + +/* This is the MPU port on the Audigy Drive */ +#define A_MUDATA2 0x72 +#define A_MUCMD2 0x73 +#define A_MUSTAT2 A_MUCMD2 + +#define A_SPDIF_SAMPLERATE 0x76 /* Set the sample rate of SPDIF output */ +#define A_SPDIF_48000 0x00000080 +#define A_SPDIF_44100 0x00000000 +#define A_SPDIF_96000 0x00000040 + +#define A_FXRT2 0x7c +#define A_FXRT_CHANNELE 0x0000003f /* Effects send bus number for channel's effects send E */ +#define A_FXRT_CHANNELF 0x00003f00 /* Effects send bus number for channel's effects send F */ +#define A_FXRT_CHANNELG 0x003f0000 /* Effects send bus number for channel's effects send G */ +#define A_FXRT_CHANNELH 0x3f000000 /* Effects send bus number for channel's effects send H */ + +#define A_SENDAMOUNTS 0x7d +#define A_FXSENDAMOUNT_E_MASK 0xFF000000 +#define A_FXSENDAMOUNT_F_MASK 0x00FF0000 +#define A_FXSENDAMOUNT_G_MASK 0x0000FF00 +#define A_FXSENDAMOUNT_H_MASK 0x000000FF + +/* The send amounts for this one are the same as used with the emu10k1 */ +#define A_FXRT1 0x7e +#define A_FXRT_CHANNELA 0x0000003f +#define A_FXRT_CHANNELB 0x00003f00 +#define A_FXRT_CHANNELC 0x003f0000 +#define A_FXRT_CHANNELD 0x3f000000 + + /* Each FX general purpose register is 32 bits in length, all bits are used */ #define FXGPREGBASE 0x100 /* FX general purpose registers base */ - +#define A_FXGPREGBASE 0x400 /* Audigy GPRs, 0x400 to 0x5ff */ /* Tank audio data is logarithmically compressed down to 16 bits before writing to TRAM and is */ /* decompressed back to 20 bits on a read. There are a total of 160 locations, the last 32 */ /* locations are for external TRAM. */ @@ -621,4 +717,14 @@ #define HIWORD_RESULT_MASK 0x000ffc00 /* Instruction result */ #define HIWORD_OPA_MASK 0x000003ff /* Instruction operand A */ + +/* Audigy Soundcard have a different instruction format */ +#define AUDIGY_CODEBASE 0x600 +#define A_LOWORD_OPY_MASK 0x000007ff +#define A_LOWORD_OPX_MASK 0x007ff000 +#define A_HIWORD_OPCODE_MASK 0x0f000000 +#define A_HIWORD_RESULT_MASK 0x007ff000 +#define A_HIWORD_OPA_MASK 0x000007ff + + #endif /* _8010_H */ diff -urN linux-2.4.18/drivers/sound/emu10k1/audio.c linux/drivers/sound/emu10k1/audio.c --- linux-2.4.18/drivers/sound/emu10k1/audio.c Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/audio.c Fri Mar 1 20:57:00 2002 @@ -50,6 +50,7 @@ #include "audio.h" #include "8010.h" + static void calculate_ofrag(struct woinst *); static void calculate_ifrag(struct wiinst *); @@ -144,6 +145,7 @@ static ssize_t emu10k1_audio_write(struct file *file, const char *buffer, size_t count, loff_t * ppos) { struct emu10k1_wavedevice *wave_dev = (struct emu10k1_wavedevice *) file->private_data; + struct woinst *woinst = wave_dev->woinst; ssize_t ret; unsigned long flags; @@ -162,8 +164,8 @@ spin_unlock_irqrestore(&woinst->lock, flags); return -ENXIO; } - - if (woinst->format.passthrough) { + // This is for emu10k1 revs less than 7, we need to go through tram + if (woinst->format.passthrough == 1 ) { int r; woinst->buffer.ossfragshift = PT_BLOCKSIZE_LOG2; @@ -354,8 +356,9 @@ case SNDCTL_DSP_GETCAPS: DPF(2, "SNDCTL_DSP_GETCAPS:\n"); - return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP | DSP_CAP_COPROC, (int *) arg); - + return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | + DSP_CAP_TRIGGER | DSP_CAP_MMAP | + DSP_CAP_COPROC| DSP_CAP_MULTI, (int *) arg); case SNDCTL_DSP_SPEED: DPF(2, "SNDCTL_DSP_SPEED:\n"); @@ -532,8 +535,8 @@ else if (file->f_mode & FMODE_WRITE) { val = AFMT_S16_LE | AFMT_U8; if (emu10k1_find_control_gpr(&wave_dev->card->mgr, - wave_dev->card->pt.patch_name, - wave_dev->card->pt.enable_gpr_name) >= 0) + wave_dev->card->pt.patch_name, + wave_dev->card->pt.enable_gpr_name) >= 0) val |= AFMT_AC3; } return put_user(val, (int *) arg); @@ -815,9 +818,9 @@ spin_lock_irqsave(&woinst->lock, flags); if (woinst->state & WAVE_STATE_OPEN || - (woinst->format.passthrough && wave_dev->card->pt.state)) { + ((woinst->format.passthrough == 1) && wave_dev->card->pt.state)) { int num_fragments; - if (woinst->format.passthrough) { + if (woinst->format.passthrough==1) { emu10k1_pt_waveout_update(wave_dev); cinfo.bytes = woinst->total_played; } else { @@ -903,7 +906,7 @@ if (file->f_mode & FMODE_WRITE) { /* digital pass-through fragment count and size are fixed values */ - if (woinst->state & WAVE_STATE_OPEN || woinst->format.passthrough) + if (woinst->state & WAVE_STATE_OPEN || (woinst->format.passthrough==1)) return -EINVAL; /* too late to change */ woinst->buffer.ossfragshift = val & 0xffff; @@ -940,19 +943,34 @@ kfree (buf); return -EINVAL; } + if(buf->command == CMD_WRITE){ + #ifdef DBGEMU - if ( (buf->offs < 0) || (buf->offs + buf->len > 0x800) || (buf->len > 1000)) { + if ( (buf->offs < 0) || (buf->offs + buf->len > 0xe00) || (buf->len > 1000)) { #else - if ( ((buf->offs < 0x100 ) || (buf->offs + buf->len > 0x800) || (buf->len > 1000)) - && !( ( buf->offs == DBG) && (buf->len ==1) )){ -#endif - kfree(buf); - return -EINVAL; + if ( ((buf->offs < 0x100 ) || (buf->offs + buf->len > (wave_dev->card->audigy? 0xe00:0x800)) || (buf->len > 1000) + ) && !( + //any register allowed raw access to users goes here: + ( buf->offs == DBG|| + buf->offs == A_DBG) + && (buf->len ==1) )){ +#endif + kfree(buf); + return -EINVAL; + } + }else{ + if ( (buf->offs < 0) || (buf->offs + buf->len > 0xe00) || (buf->len > 1000)) { + kfree(buf); + return -EINVAL; + } } - + + + if( ((unsigned)buf->flags) >0x3f) + buf->flags=0; if (buf->command == CMD_READ) { for (i = 0; i < buf->len; i++) - ((u32 *) buf->data)[i] = sblive_readptr(wave_dev->card, buf->offs + i, 0); + ((u32 *) buf->data)[i] = sblive_readptr(wave_dev->card, buf->offs + i, buf->flags); if (copy_to_user((copr_buffer *) arg, buf, sizeof(copr_buffer))) { kfree(buf); @@ -960,7 +978,7 @@ } } else { for (i = 0; i < buf->len; i++) - sblive_writeptr(wave_dev->card, buf->offs + i, 0, ((u32 *) buf->data)[i]); + sblive_writeptr(wave_dev->card, buf->offs + i, buf->flags, ((u32 *) buf->data)[i]); } kfree (buf); @@ -1244,8 +1262,9 @@ struct woinst *woinst = wave_dev->woinst; spin_lock_irqsave(&woinst->lock, flags); - - if (woinst->format.passthrough && card->pt.state != PT_STATE_INACTIVE) { + if(woinst->format.passthrough==2) + card->pt.state=PT_STATE_PLAYING; + if (woinst->format.passthrough && card->pt.state != PT_STATE_INACTIVE){ spin_lock(&card->pt.lock); emu10k1_pt_stop(card); spin_unlock(&card->pt.lock); diff -urN linux-2.4.18/drivers/sound/emu10k1/cardmi.c linux/drivers/sound/emu10k1/cardmi.c --- linux-2.4.18/drivers/sound/emu10k1/cardmi.c Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/cardmi.c Fri Mar 1 20:55:19 2002 @@ -113,7 +113,7 @@ } /* Disable RX interrupt */ - emu10k1_irq_disable(card, INTE_MIDIRXENABLE); + emu10k1_irq_disable(card, card->audigy? INTE_A_MIDIRXENABLE:INTE_MIDIRXENABLE); emu10k1_mpu_release(card); @@ -189,7 +189,7 @@ card_mpuin->qhead = 0; card_mpuin->qtail = 0; - emu10k1_irq_enable(card, INTE_MIDIRXENABLE); + emu10k1_irq_enable(card, card->audigy? INTE_A_MIDIRXENABLE:INTE_MIDIRXENABLE); } return 0; @@ -207,7 +207,7 @@ DPF(2, "emu10k1_mpuin_stop()\n"); - emu10k1_irq_disable(card, INTE_MIDIRXENABLE); + emu10k1_irq_disable(card, card->audigy? INTE_A_MIDIRXENABLE:INTE_MIDIRXENABLE); card_mpuin->status &= ~FLAGS_MIDM_STARTED; /* clear */ @@ -246,7 +246,7 @@ DPF(2, "emu10k1_mpuin_reset()\n"); - emu10k1_irq_disable(card, INTE_MIDIRXENABLE); + emu10k1_irq_disable(card, card->audigy? INTE_A_MIDIRXENABLE:INTE_MIDIRXENABLE); while (card_mpuin->firstmidiq) { midiq = card_mpuin->firstmidiq; diff -urN linux-2.4.18/drivers/sound/emu10k1/cardmo.c linux/drivers/sound/emu10k1/cardmo.c --- linux-2.4.18/drivers/sound/emu10k1/cardmo.c Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/cardmo.c Fri Mar 1 20:55:19 2002 @@ -72,7 +72,7 @@ DPF(2, "emu10k1_mpuout_close()\n"); - emu10k1_irq_disable(card, INTE_MIDITXENABLE); + emu10k1_irq_disable(card, card->audigy? INTE_A_MIDITXENABLE:INTE_MIDITXENABLE); spin_lock_irqsave(&card_mpuout->lock, flags); @@ -142,7 +142,7 @@ card_mpuout->intr = 0; - emu10k1_irq_enable(card, INTE_MIDITXENABLE); + emu10k1_irq_enable(card, card->audigy? INTE_A_MIDITXENABLE:INTE_MIDITXENABLE); spin_unlock_irqrestore(&card_mpuout->lock, flags); @@ -206,7 +206,7 @@ if ((card_mpuout->firstmidiq != NULL) || cByteSent) { card_mpuout->intr = 0; - emu10k1_irq_enable(card, INTE_MIDITXENABLE); + emu10k1_irq_enable(card, card->audigy? INTE_A_MIDITXENABLE:INTE_MIDITXENABLE); } spin_unlock_irqrestore(&card_mpuout->lock, flags); @@ -221,7 +221,7 @@ DPF(4, "emu10k1_mpuout_irqhandler\n"); card_mpuout->intr = 1; - emu10k1_irq_disable(card, INTE_MIDITXENABLE); + emu10k1_irq_disable(card, card->audigy? INTE_A_MIDITXENABLE:INTE_MIDITXENABLE); tasklet_hi_schedule(&card_mpuout->tasklet); diff -urN linux-2.4.18/drivers/sound/emu10k1/cardwo.c linux/drivers/sound/emu10k1/cardwo.c --- linux-2.4.18/drivers/sound/emu10k1/cardwo.c Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/cardwo.c Fri Mar 1 20:55:19 2002 @@ -85,25 +85,36 @@ break; } if (do_passthrough) { - i = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.intr_gpr_name); - j = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.enable_gpr_name); /* currently only one waveout instance may use pass-through */ - if (i < 0 || j < 0 || woinst->state != WAVE_STATE_CLOSED || - card->pt.state != PT_STATE_INACTIVE || - (wave_fmt->samplingrate != 48000 && !is_ac3) || - (wave_fmt->samplingrate != 48000 && !is_ac3)) { + if(woinst->state != WAVE_STATE_CLOSED || + card->pt.state != PT_STATE_INACTIVE || + (wave_fmt->samplingrate != 48000 && !is_ac3)) { DPF(2, "unable to set pass-through mode\n"); - } else { - wave_fmt->samplingrate = 48000; - wave_fmt->channels = 2; - wave_fmt->passthrough = 1; - card->pt.intr_gpr = i; - card->pt.enable_gpr = j; - card->pt.state = PT_STATE_INACTIVE; - card->pt.pos_gpr = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.pos_gpr_name); - DPD(2, "is_ac3 is %d\n", is_ac3); - card->pt.ac3data = is_ac3; - wave_fmt->bitsperchannel = 16; + }else if(USE_PT_METHOD1){ + i = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.intr_gpr_name); + j = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, card->pt.enable_gpr_name); + if(i < 0 || j < 0) + DPF(2, "unable to set pass-through mode\n"); + else{ + wave_fmt->samplingrate = 48000; + wave_fmt->channels = 2; + card->pt.pos_gpr = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, + card->pt.pos_gpr_name); + wave_fmt->passthrough = 1; + card->pt.intr_gpr = i; + card->pt.enable_gpr = j; + card->pt.state = PT_STATE_INACTIVE; + + DPD(2, "is_ac3 is %d\n", is_ac3); + card->pt.ac3data = is_ac3; + wave_fmt->bitsperchannel = 16; + } + }else{ + DPF(2, "Using Passthrough Method 2\n"); + card->pt.enable_gpr = emu10k1_find_control_gpr(&card->mgr, card->pt.patch_name, + card->pt.enable_gpr_name); + wave_fmt->passthrough = 2; + wave_fmt->bitsperchannel = 16; } } @@ -149,33 +160,36 @@ voice->endloop = voice->startloop + woinst->buffer.size / woinst->format.bytespervoicesample; voice->start = voice->startloop; - if (voice->flags & VOICE_FLAGS_STEREO) { - voice->params[0].send_a = card->waveout.send_a[1]; - voice->params[0].send_b = card->waveout.send_b[1]; - voice->params[0].send_c = card->waveout.send_c[1]; - voice->params[0].send_d = card->waveout.send_d[1]; - - if (woinst->device) - voice->params[0].send_routing = 0x7654; - else - voice->params[0].send_routing = card->waveout.send_routing[1]; - - voice->params[0].volume_target = 0xffff; - voice->params[0].initial_fc = 0xff; - voice->params[0].initial_attn = 0x00; - voice->params[0].byampl_env_sustain = 0x7f; - voice->params[0].byampl_env_decay = 0x7f; - - voice->params[1].send_a = card->waveout.send_a[2]; - voice->params[1].send_b = card->waveout.send_b[2]; - voice->params[1].send_c = card->waveout.send_c[2]; - voice->params[1].send_d = card->waveout.send_d[2]; - - if (woinst->device) - voice->params[1].send_routing = 0x7654; - else - voice->params[1].send_routing = card->waveout.send_routing[2]; + + voice->params[0].volume_target = 0xffff; + voice->params[0].initial_fc = 0xff; + voice->params[0].initial_attn = 0x00; + voice->params[0].byampl_env_sustain = 0x7f; + voice->params[0].byampl_env_decay = 0x7f; + + if (voice->flags & VOICE_FLAGS_STEREO) { + if(woinst->format.passthrough == 2){ + voice->params[0].send_routing = voice->params[1].send_routing = card->waveout.send_routing[ROUTE_PT]; + voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PT]; + voice->params[0].send_dcba=0xff; + voice->params[1].send_dcba=0xff00; + voice->params[0].send_hgfe=voice->params[1].send_hgfe=0; + }else{ + voice->params[0].send_dcba=card->waveout.send_dcba[SEND_LEFT]; + voice->params[0].send_hgfe=card->waveout.send_hgfe[SEND_LEFT]; + voice->params[1].send_dcba=card->waveout.send_dcba[SEND_RIGHT]; + voice->params[1].send_hgfe=card->waveout.send_hgfe[SEND_RIGHT]; + + if (woinst->device){// /dev/dps1 + voice->params[0].send_routing = voice->params[1].send_routing = card->waveout.send_routing[ROUTE_PCM1]; + voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PCM1]; + }else{ + voice->params[0].send_routing = voice->params[1].send_routing = card->waveout.send_routing[ROUTE_PCM]; + voice->params[0].send_routing2 = voice->params[1].send_routing2 = card->waveout.send_routing2[ROUTE_PCM]; + } + } + voice->params[1].volume_target = 0xffff; voice->params[1].initial_fc = 0xff; voice->params[1].initial_attn = 0x00; @@ -183,30 +197,28 @@ voice->params[1].byampl_env_decay = 0x7f; } else { if (woinst->num_voices > 1) { - voice->params[0].send_a = 0xff; - voice->params[0].send_b = 0; - voice->params[0].send_c = 0; - voice->params[0].send_d = 0; - - voice->params[0].send_routing = - 0xfff0 + card->mchannel_fx + voicenum; + // Multichannel pcm + voice->params[0].send_dcba=0xff; + voice->params[0].send_hgfe=0; + if(IS_EMU10K1) + voice->params[0].send_routing = 0xfff0 + card->mchannel_fx + voicenum; + else{ + voice->params[0].send_routing = 0x3f3f3f00 + card->mchannel_fx + voicenum; + voice->params[0].send_routing2 = 0x3f3f3f3f; + } + } else { - voice->params[0].send_a = card->waveout.send_a[0]; - voice->params[0].send_b = card->waveout.send_b[0]; - voice->params[0].send_c = card->waveout.send_c[0]; - voice->params[0].send_d = card->waveout.send_d[0]; - - if (woinst->device) - voice->params[0].send_routing = 0x7654; - else - voice->params[0].send_routing = card->waveout.send_routing[0]; - } - - voice->params[0].volume_target = 0xffff; - voice->params[0].initial_fc = 0xff; - voice->params[0].initial_attn = 0x00; - voice->params[0].byampl_env_sustain = 0x7f; - voice->params[0].byampl_env_decay = 0x7f; + voice->params[0].send_dcba = card->waveout.send_dcba[SEND_MONO]; + voice->params[0].send_hgfe = card->waveout.send_hgfe[SEND_MONO]; + + if (woinst->device){ + voice->params[0].send_routing = card->waveout.send_routing[ROUTE_PCM1]; + voice->params[0].send_routing2 = card->waveout.send_routing2[ROUTE_PCM1]; + }else{ + voice->params[0].send_routing = card->waveout.send_routing[ROUTE_PCM]; + voice->params[0].send_routing2 = card->waveout.send_routing2[ROUTE_PCM]; + } + } } DPD(2, "voice: startloop=%#x, endloop=%#x\n", voice->startloop, voice->endloop); @@ -280,9 +292,16 @@ { struct emu10k1_card *card = wave_dev->card; struct woinst *woinst = wave_dev->woinst; + struct pt_data *pt = &card->pt; DPF(2, "emu10k1_waveout_start()\n"); + if (woinst->format.passthrough == 2 ) { + emu10k1_pt_setup(wave_dev); + sblive_writeptr(card, (IS_AUDIGY?A_GPR_BASE:GPR_BASE) + pt->enable_gpr, 0, 1); + pt->state = PT_STATE_PLAYING; + } + /* Actual start */ emu10k1_voices_start(woinst->voice, woinst->num_voices, woinst->total_played); diff -urN linux-2.4.18/drivers/sound/emu10k1/efxmgr.c linux/drivers/sound/emu10k1/efxmgr.c --- linux-2.4.18/drivers/sound/emu10k1/efxmgr.c Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/efxmgr.c Fri Mar 1 20:55:19 2002 @@ -79,16 +79,20 @@ if (addr < 0 || addr >= NUM_GPRS) return; - + //fixme: once patch manager is up, remember to fix this for the audigy + if(card->audigy){ + sblive_writeptr(card, A_GPR_BASE + addr, 0, val); + }else{ if (flag) val += sblive_readptr(card, GPR_BASE + addr, 0); - if (val > mgr->gpr[addr].max) val = mgr->gpr[addr].max; else if (val < mgr->gpr[addr].min) val = mgr->gpr[addr].min; - sblive_writeptr(card, GPR_BASE + addr, 0, val); + } + + } //TODO: make this configurable: @@ -171,7 +175,7 @@ { struct patch_manager *mgr = &card->mgr; unsigned long flags; - int muting; + static const s32 log2lin[4] ={ // attenuation (dB) 0x7fffffff, // 0.0 @@ -183,12 +187,10 @@ if (addr < 0) return; - muting = (scale == 0x10) ? 0x7f: scale; - vol = (100 - vol ) * scale / 100; // Thanks to the comp.dsp newsgroup for this neat trick: - vol = (vol >= muting) ? 0 : (log2lin[vol & 3] >> (vol >> 2)); + vol = (vol >= scale) ? 0 : (log2lin[vol & 3] >> (vol >> 2)); spin_lock_irqsave(&mgr->lock, flags); emu10k1_set_control_gpr(card, addr, vol, 0); diff -urN linux-2.4.18/drivers/sound/emu10k1/efxmgr.h linux/drivers/sound/emu10k1/efxmgr.h --- linux-2.4.18/drivers/sound/emu10k1/efxmgr.h Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/efxmgr.h Fri Mar 1 20:55:19 2002 @@ -32,16 +32,30 @@ #ifndef _EFXMGR_H #define _EFXMGR_H -#define WRITE_EFX(a, b, c) sblive_writeptr((a), MICROCODEBASE + (b), 0, (c)) +struct emu_efx_info_t{ + int opcode_shift; + int high_operand_shift; + int instruction_start; + int gpr_base; + int output_base; +}; + + +#define WRITE_EFX(a, b, c) sblive_writeptr((a), emu_efx_info[card->audigy].instruction_start + (b), 0, (c)) #define OP(op, z, w, x, y) \ - do { WRITE_EFX(card, (pc) * 2, ((x) << 10) | (y)); \ - WRITE_EFX(card, (pc) * 2 + 1, ((op) << 20) | ((z) << 10) | (w)); \ + do { WRITE_EFX(card, (pc) * 2, ((x) << emu_efx_info[card->audigy].high_operand_shift) | (y)); \ + WRITE_EFX(card, (pc) * 2 + 1, ((op) << emu_efx_info[card->audigy].opcode_shift ) | ((z) << emu_efx_info[card->audigy].high_operand_shift) | (w)); \ ++pc; } while (0) #define NUM_INPUTS 0x20 #define NUM_OUTPUTS 0x20 #define NUM_GPRS 0x100 + +#define A_NUM_INPUTS 0x60 +#define A_NUM_OUTPUTS 0x60 //fixme: this may or may not be true +#define A_NUM_GPRS 0x200 + #define GPR_NAME_SIZE 32 #define PATCH_NAME_SIZE 32 @@ -98,6 +112,9 @@ #define GPR_BASE 0x100 #define OUTPUT_BASE 0x20 +#define A_GPR_BASE 0x400 +#define A_OUTPUT_BASE 0x60 + #define MAX_PATCHES_PAGES 32 struct patch_manager { @@ -109,7 +126,6 @@ s16 ctrl_gpr[SOUND_MIXER_NRDEVICES][2]; }; - #define PATCHES_PER_PAGE (PAGE_SIZE / sizeof(struct dsp_patch)) #define PATCH(mgr, i) ((struct dsp_patch *) (mgr)->patch[(i) / PATCHES_PER_PAGE] + (i) % PATCHES_PER_PAGE) diff -urN linux-2.4.18/drivers/sound/emu10k1/hwaccess.c linux/drivers/sound/emu10k1/hwaccess.c --- linux-2.4.18/drivers/sound/emu10k1/hwaccess.c Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/hwaccess.c Fri Mar 1 20:55:19 2002 @@ -159,6 +159,20 @@ return; } +void emu10k1_writefn0_2(struct emu10k1_card *card, u32 reg, u32 data, int size) +{ + unsigned long flags; + spin_lock_irqsave(&card->lock, flags); + + if(size==32) + outl(data, card->iobase + (reg&0x1F)); + else if(size==16) + outw(data, card->iobase + (reg&0x1F)); + else + outw(data, card->iobase + (reg&0x1F)); + spin_unlock_irqrestore(&card->lock, flags); + return; +} u32 emu10k1_readfn0(struct emu10k1_card * card, u32 reg) { @@ -191,12 +205,13 @@ * write/read Emu10k1 pointer-offset register set, accessed through * * the PTR and DATA registers * *************************************************************************/ +#define A_PTR_ADDRESS_MASK 0x0fff0000 void sblive_writeptr(struct emu10k1_card *card, u32 reg, u32 channel, u32 data) { u32 regptr; unsigned long flags; - regptr = ((reg << 16) & PTR_ADDRESS_MASK) | (channel & PTR_CHANNELNUM_MASK); + regptr = ((reg << 16) & A_PTR_ADDRESS_MASK) | (channel & PTR_CHANNELNUM_MASK); if (reg & 0xff000000) { u32 mask; @@ -233,7 +248,7 @@ spin_lock_irqsave(&card->lock, flags); while ((reg = va_arg(args, u32)) != TAGLIST_END) { u32 data = va_arg(args, u32); - u32 regptr = (((reg << 16) & PTR_ADDRESS_MASK) + u32 regptr = (((reg << 16) & A_PTR_ADDRESS_MASK) | (channel & PTR_CHANNELNUM_MASK)); outl(regptr, card->iobase + PTR); if (reg & 0xff000000) { @@ -258,7 +273,7 @@ u32 regptr, val; unsigned long flags; - regptr = ((reg << 16) & PTR_ADDRESS_MASK) | (channel & PTR_CHANNELNUM_MASK); + regptr = ((reg << 16) & A_PTR_ADDRESS_MASK) | (channel & PTR_CHANNELNUM_MASK); if (reg & 0xff000000) { u32 mask; @@ -380,7 +395,7 @@ outb(reg, card->iobase + AC97ADDRESS); outw(value, card->iobase + AC97DATA); - + outb( AC97_EXTENDED_ID, card->iobase + AC97ADDRESS); spin_unlock_irqrestore(&card->lock, flags); } @@ -393,15 +408,21 @@ unsigned long flags; int ret; - spin_lock_irqsave(&card->lock, flags); - - if ((inb(card->iobase + MUSTAT) & MUSTAT_ORDYN) == 0) { - outb(data, card->iobase + MUDATA); - ret = 0; - } else - ret = -1; - - spin_unlock_irqrestore(&card->lock, flags); + if(card->audigy){ + if ((sblive_readptr(card, A_MUSTAT,0) & MUSTAT_ORDYN) == 0) { + sblive_writeptr(card, A_MUDATA, 0, data); + ret = 0; + } else + ret = -1; + }else{ + spin_lock_irqsave(&card->lock, flags); + if ((inb(card->iobase + MUSTAT) & MUSTAT_ORDYN) == 0) { + outb(data, card->iobase + MUDATA); + ret = 0; + } else + ret = -1; + spin_unlock_irqrestore(&card->lock, flags); + } return ret; } @@ -411,15 +432,21 @@ unsigned long flags; int ret; - spin_lock_irqsave(&card->lock, flags); - - if ((inb(card->iobase + MUSTAT) & MUSTAT_IRDYN) == 0) { - *data = inb(card->iobase + MUDATA); - ret = 0; - } else - ret = -1; - - spin_unlock_irqrestore(&card->lock, flags); + if(card->audigy){ + if ((sblive_readptr(card, A_MUSTAT,0) & MUSTAT_IRDYN) == 0) { + *data = sblive_readptr(card, A_MUDATA,0); + ret = 0; + } else + ret = -1; + }else{ + spin_lock_irqsave(&card->lock, flags); + if ((inb(card->iobase + MUSTAT) & MUSTAT_IRDYN) == 0) { + *data = inb(card->iobase + MUDATA); + ret = 0; + } else + ret = -1; + spin_unlock_irqrestore(&card->lock, flags); + } return ret; } @@ -430,37 +457,55 @@ unsigned long flags; DPF(2, "emu10k1_mpu_reset()\n"); - - if (card->mpuacqcount == 0) { - spin_lock_irqsave(&card->lock, flags); - outb(MUCMD_RESET, card->iobase + MUCMD); - spin_unlock_irqrestore(&card->lock, flags); - - sblive_wcwait(card, 8); - - spin_lock_irqsave(&card->lock, flags); - outb(MUCMD_RESET, card->iobase + MUCMD); - spin_unlock_irqrestore(&card->lock, flags); - - sblive_wcwait(card, 8); - - spin_lock_irqsave(&card->lock, flags); - outb(MUCMD_ENTERUARTMODE, card->iobase + MUCMD); - spin_unlock_irqrestore(&card->lock, flags); - - sblive_wcwait(card, 8); - - spin_lock_irqsave(&card->lock, flags); - status = inb(card->iobase + MUDATA); - spin_unlock_irqrestore(&card->lock, flags); - - if (status == 0xfe) - return 0; - else - return -1; + if(card->audigy){ + + if (card->mpuacqcount == 0) { + sblive_writeptr(card, A_MUCMD, 0, MUCMD_RESET); + sblive_wcwait(card, 8); + sblive_writeptr(card, A_MUCMD, 0, MUCMD_RESET); + sblive_wcwait(card, 8); + sblive_writeptr(card, A_MUCMD, 0, MUCMD_ENTERUARTMODE); + sblive_wcwait(card, 8); + status = sblive_readptr(card, A_MUDATA, 0); + if (status == 0xfe) + return 0; + else + return -1; + } + return 0; + }else{ + + + if (card->mpuacqcount == 0) { + spin_lock_irqsave(&card->lock, flags); + outb(MUCMD_RESET, card->iobase + MUCMD); + spin_unlock_irqrestore(&card->lock, flags); + + sblive_wcwait(card, 8); + + spin_lock_irqsave(&card->lock, flags); + outb(MUCMD_RESET, card->iobase + MUCMD); + spin_unlock_irqrestore(&card->lock, flags); + + sblive_wcwait(card, 8); + + spin_lock_irqsave(&card->lock, flags); + outb(MUCMD_ENTERUARTMODE, card->iobase + MUCMD); + spin_unlock_irqrestore(&card->lock, flags); + + sblive_wcwait(card, 8); + + spin_lock_irqsave(&card->lock, flags); + status = inb(card->iobase + MUDATA); + spin_unlock_irqrestore(&card->lock, flags); + + if (status == 0xfe) + return 0; + else + return -1; + } + return 0; } - - return 0; } int emu10k1_mpu_acquire(struct emu10k1_card *card) diff -urN linux-2.4.18/drivers/sound/emu10k1/hwaccess.h linux/drivers/sound/emu10k1/hwaccess.h --- linux-2.4.18/drivers/sound/emu10k1/hwaccess.h Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/hwaccess.h Fri Mar 1 20:57:00 2002 @@ -79,13 +79,21 @@ struct emu10k1_waveout { - u16 send_routing[3]; - - u8 send_a[3]; - u8 send_b[3]; - u8 send_c[3]; - u8 send_d[3]; + u32 send_routing[3]; + // audigy only: + u32 send_routing2[3]; + + u32 send_dcba[3]; + // audigy only: + u32 send_hgfe[3]; }; +#define ROUTE_PCM 0 +#define ROUTE_PT 1 +#define ROUTE_PCM1 2 + +#define SEND_MONO 0 +#define SEND_LEFT 1 +#define SEND_RIGHT 2 struct emu10k1_wavein { @@ -129,7 +137,7 @@ #define CMD_AC97_BOOST _IOW('D', 20, struct mixer_private_ioctl) //up this number when breaking compatibility -#define PRIVATE3_VERSION 1 +#define PRIVATE3_VERSION 2 struct emu10k1_card { @@ -181,13 +189,18 @@ u32 has_toslink; // TOSLink detection u8 chiprev; /* Chip revision */ - - int isaps; + u8 audigy; + u8 isaps; struct patch_manager mgr; struct pt_data pt; }; +#define IS_AUDIGY card->audigy==1 +#define IS_EMU10K1 card->audigy==0 +#define IS_APS card->isaps==0 + + int emu10k1_addxmgr_alloc(u32, struct emu10k1_card *); void emu10k1_addxmgr_free(struct emu10k1_card *, int); @@ -213,6 +226,7 @@ /* Hardware Abstraction Layer access functions */ void emu10k1_writefn0(struct emu10k1_card *, u32 , u32 ); +void emu10k1_writefn0_2(struct emu10k1_card *card, u32 reg, u32 data, int size); u32 emu10k1_readfn0(struct emu10k1_card *, u32 ); void sblive_writeptr(struct emu10k1_card *, u32 , u32 , u32 ); diff -urN linux-2.4.18/drivers/sound/emu10k1/irqmgr.c linux/drivers/sound/emu10k1/irqmgr.c --- linux-2.4.18/drivers/sound/emu10k1/irqmgr.c Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/irqmgr.c Fri Mar 1 20:55:19 2002 @@ -97,7 +97,7 @@ } if (irqstatus){ - printk(KERN_ERR "emu10k1: Warning, unhandled interrupt: %#08x\n", irqstatus); + printk(KERN_ERR "emu10k1: Warning, unhandled interrupt: 0x%08x\n", irqstatus); //make sure any interrupts we don't handle are disabled: emu10k1_irq_disable(card, ~(INTE_MIDIRXENABLE | INTE_MIDITXENABLE | INTE_INTERVALTIMERENB | INTE_VOLDECRENABLE | INTE_VOLINCRENABLE | INTE_MUTEENABLE | diff -urN linux-2.4.18/drivers/sound/emu10k1/irqmgr.h linux/drivers/sound/emu10k1/irqmgr.h --- linux-2.4.18/drivers/sound/emu10k1/irqmgr.h Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/irqmgr.h Fri Mar 1 20:55:19 2002 @@ -37,8 +37,8 @@ #define IRQTYPE_MIXERBUTTON (IPR_VOLINCR | IPR_VOLDECR | IPR_MUTE) #define IRQTYPE_VOICE (IPR_CHANNELLOOP | IPR_CHANNELNUMBERMASK) #define IRQTYPE_RECORD (IPR_ADCBUFFULL | IPR_ADCBUFHALFFULL | IPR_MICBUFFULL | IPR_MICBUFHALFFULL | IPR_EFXBUFFULL | IPR_EFXBUFHALFFULL) -#define IRQTYPE_MPUOUT IPR_MIDITRANSBUFEMPTY -#define IRQTYPE_MPUIN IPR_MIDIRECVBUFEMPTY +#define IRQTYPE_MPUOUT (IPR_MIDITRANSBUFEMPTY | IPR_A_MIDITRANSBUFEMPTY2) +#define IRQTYPE_MPUIN (IPR_MIDIRECVBUFEMPTY | IPR_A_MIDIRECVBUFEMPTY2) #define IRQTYPE_TIMER IPR_INTERVALTIMER #define IRQTYPE_SPDIF (IPR_GPSPDIFSTATUSCHANGE | IPR_CDROMSTATUSCHANGE) #define IRQTYPE_DSP IPR_FXDSP diff -urN linux-2.4.18/drivers/sound/emu10k1/main.c linux/drivers/sound/emu10k1/main.c --- linux-2.4.18/drivers/sound/emu10k1/main.c Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/main.c Fri Mar 1 20:58:10 2002 @@ -78,6 +78,7 @@ * Cleaned up poll() functions (audio and midi). Don't start input. * Restrict DMA pages used to 512Mib range. * New AC97_BOOST mixer ioctl. + * 0.19 Added Support for Audigy Cards * *********************************************************************/ @@ -111,10 +112,9 @@ #define SNDCARD_EMU10K1 46 #endif -#define DRIVER_VERSION "0.18" - /* the emu10k1 _seems_ to only supports 29 bit (512MiB) bit bus master */ #define EMU10K1_DMA_MASK 0x1fffffff /* DMA buffer mask for pci_alloc_consist */ +#define AUDIGY_DMA_MASK 0xffffffff /* I hope this is correct - DB */ #ifndef PCI_VENDOR_ID_CREATIVE #define PCI_VENDOR_ID_CREATIVE 0x1102 @@ -123,20 +123,27 @@ #ifndef PCI_DEVICE_ID_CREATIVE_EMU10K1 #define PCI_DEVICE_ID_CREATIVE_EMU10K1 0x0002 #endif +#ifndef PCI_DEVICE_ID_CREATIVE_AUDIGY +#define PCI_DEVICE_ID_CREATIVE_AUDIGY 0x0004 +#endif #define EMU_APS_SUBID 0x40011102 enum { EMU10K1 = 0, + AUDIGY, }; static char *card_names[] __devinitdata = { "EMU10K1", + "Audigy", }; static struct pci_device_id emu10k1_pci_tbl[] = { {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_EMU10K1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, EMU10K1}, + {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_AUDIGY, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, AUDIGY}, {0,} }; @@ -171,29 +178,48 @@ } /* Assign default playback voice parameters */ - card->mchannel_fx = 8; - /* mono voice */ - card->waveout.send_a[0] = 0xff; - card->waveout.send_b[0] = 0xff; - card->waveout.send_c[0] = 0x00; - card->waveout.send_d[0] = 0x00; - card->waveout.send_routing[0] = 0x3210; - - /* stereo voice */ - /* left */ - card->waveout.send_a[1] = 0xff; - card->waveout.send_b[1] = 0x00; - card->waveout.send_c[1] = 0x00; - card->waveout.send_d[1] = 0x00; - card->waveout.send_routing[1] = 0x3210; - - /* right */ - card->waveout.send_a[2] = 0x00; - card->waveout.send_b[2] = 0xff; - card->waveout.send_c[2] = 0x00; - card->waveout.send_d[2] = 0x00; - card->waveout.send_routing[2] = 0x3210; + if(IS_EMU10K1) + card->mchannel_fx = 8; + else + card->mchannel_fx = 0; + + if(card->audigy){ + /* mono voice */ + card->waveout.send_dcba[SEND_MONO] = 0xffffffff; + card->waveout.send_hgfe[SEND_MONO] = 0x0000ffff; + + /* stereo voice */ + /* left */ + card->waveout.send_dcba[SEND_LEFT] = 0x00ff00ff; + card->waveout.send_hgfe[SEND_LEFT] = 0x00007f7f; + /* right */ + card->waveout.send_dcba[SEND_RIGHT] = 0xff00ff00; + card->waveout.send_hgfe[SEND_RIGHT] = 0x00007f7f; + + card->waveout.send_routing[ROUTE_PCM] = 0x03020100; // Regular pcm + card->waveout.send_routing2[ROUTE_PCM] = 0x07060504; + + card->waveout.send_routing[ROUTE_PT] = 0x3f3f3d3c; // Passthrough + card->waveout.send_routing2[ROUTE_PT] = 0x3f3f3f3f; + + card->waveout.send_routing[ROUTE_PCM1] = 0x03020100; // Spare + card->waveout.send_routing2[ROUTE_PCM1] = 0x07060404; + + }else{ + /* mono voice */ + card->waveout.send_dcba[SEND_MONO] = 0x0000ffff; + + /* stereo voice */ + /* left */ + card->waveout.send_dcba[SEND_LEFT] = 0x000000ff; + /* right */ + card->waveout.send_dcba[SEND_RIGHT] = 0x0000ff00; + + card->waveout.send_routing[ROUTE_PCM] = 0x3210; // pcm + card->waveout.send_routing[ROUTE_PT] = 0x3210; // passthrough + card->waveout.send_routing[ROUTE_PCM1] = 0x7654; // /dev/dsp1 + } /* Assign default recording parameters */ /* FIXME */ if(card->isaps) @@ -449,24 +475,27 @@ s32 left, right; int i; u32 pc = 0; - u32 patch_n; + u32 patch_n=0; + struct emu_efx_info_t emu_efx_info[2]= + {{ 20, 10, 0x400, 0x100, 0x20 }, + { 24, 12, 0x600, 0x400, 0x60 }, + }; + for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) { mgr->ctrl_gpr[i][0] = -1; mgr->ctrl_gpr[i][1] = -1; } - for (i = 0; i < 512; i++) - OP(6, 0x40, 0x40, 0x40, 0x40); - - for (i = 0; i < 256; i++) - sblive_writeptr_tag(card, 0, - FXGPREGBASE + i, 0, - TANKMEMADDRREGBASE + i, 0, - TAGLIST_END); - /* !! The number bellow must equal the number of patches, currently 11 !! */ - mgr->current_pages = (11 + PATCHES_PER_PAGE - 1) / PATCHES_PER_PAGE; + if(IS_AUDIGY) + /* audigy */ + mgr->current_pages = (2 + PATCHES_PER_PAGE - 1) / PATCHES_PER_PAGE; + else + /* emu10k1 */ + /* !! The number below must equal the number of patches, currently 11 !! */ + mgr->current_pages = (11 + PATCHES_PER_PAGE - 1) / PATCHES_PER_PAGE; + for (i = 0; i < mgr->current_pages; i++) { mgr->patch[i] = (void *)__get_free_page(GFP_KERNEL); if (mgr->patch[i] == NULL) { @@ -477,215 +506,290 @@ memset(mgr->patch[i], 0, PAGE_SIZE); } - pc = 0; - patch_n = 0; - //first free GPR = 0x11b - - /* FX volume correction and Volume control*/ - INPUT_PATCH_START(patch, "Pcm L vol", 0x0, 0); - GET_OUTPUT_GPR(patch, 0x100, 0x0); - GET_CONTROL_GPR(patch, 0x106, "Vol", 0, 0x7fffffff); - GET_DYNAMIC_GPR(patch, 0x112); - - OP(4, 0x112, 0x40, PCM_IN_L, 0x44); //*4 - OP(0, 0x100, 0x040, 0x112, 0x106); //*vol - INPUT_PATCH_END(patch); - - - INPUT_PATCH_START(patch, "Pcm R vol", 0x1, 0); - GET_OUTPUT_GPR(patch, 0x101, 0x1); - GET_CONTROL_GPR(patch, 0x107, "Vol", 0, 0x7fffffff); - GET_DYNAMIC_GPR(patch, 0x112); - - OP(4, 0x112, 0x40, PCM_IN_R, 0x44); - OP(0, 0x101, 0x040, 0x112, 0x107); - - INPUT_PATCH_END(patch); - - - // CD-Digital In Volume control - INPUT_PATCH_START(patch, "CD-Digital Vol L", 0x12, 0); - GET_OUTPUT_GPR(patch, 0x10c, 0x12); - GET_CONTROL_GPR(patch, 0x10d, "Vol", 0, 0x7fffffff); - - OP(0, 0x10c, 0x040, SPDIF_CD_L, 0x10d); - INPUT_PATCH_END(patch); - - INPUT_PATCH_START(patch, "CD-Digital Vol R", 0x13, 0); - GET_OUTPUT_GPR(patch, 0x10e, 0x13); - GET_CONTROL_GPR(patch, 0x10f, "Vol", 0, 0x7fffffff); - - OP(0, 0x10e, 0x040, SPDIF_CD_R, 0x10f); - INPUT_PATCH_END(patch); - - //Volume Correction for Multi-channel Inputs - INPUT_PATCH_START(patch, "Multi-Channel Gain", 0x08, 0); - patch->input=patch->output=0x3F00; - - GET_OUTPUT_GPR(patch, 0x113, MULTI_FRONT_L); - GET_OUTPUT_GPR(patch, 0x114, MULTI_FRONT_R); - GET_OUTPUT_GPR(patch, 0x115, MULTI_REAR_L); - GET_OUTPUT_GPR(patch, 0x116, MULTI_REAR_R); - GET_OUTPUT_GPR(patch, 0x117, MULTI_CENTER); - GET_OUTPUT_GPR(patch, 0x118, MULTI_LFE); - - OP(4, 0x113, 0x40, MULTI_FRONT_L, 0x44); - OP(4, 0x114, 0x40, MULTI_FRONT_R, 0x44); - OP(4, 0x115, 0x40, MULTI_REAR_L, 0x44); - OP(4, 0x116, 0x40, MULTI_REAR_R, 0x44); - OP(4, 0x117, 0x40, MULTI_CENTER, 0x44); - OP(4, 0x118, 0x40, MULTI_LFE, 0x44); - - INPUT_PATCH_END(patch); - - - //Routing patch start - ROUTING_PATCH_START(rpatch, "Routing"); - GET_INPUT_GPR(rpatch, 0x100, 0x0); - GET_INPUT_GPR(rpatch, 0x101, 0x1); - GET_INPUT_GPR(rpatch, 0x10c, 0x12); - GET_INPUT_GPR(rpatch, 0x10e, 0x13); - GET_INPUT_GPR(rpatch, 0x113, MULTI_FRONT_L); - GET_INPUT_GPR(rpatch, 0x114, MULTI_FRONT_R); - GET_INPUT_GPR(rpatch, 0x115, MULTI_REAR_L); - GET_INPUT_GPR(rpatch, 0x116, MULTI_REAR_R); - GET_INPUT_GPR(rpatch, 0x117, MULTI_CENTER); - GET_INPUT_GPR(rpatch, 0x118, MULTI_LFE); - - GET_DYNAMIC_GPR(rpatch, 0x102); - GET_DYNAMIC_GPR(rpatch, 0x103); - - GET_OUTPUT_GPR(rpatch, 0x104, 0x8); - GET_OUTPUT_GPR(rpatch, 0x105, 0x9); - GET_OUTPUT_GPR(rpatch, 0x10a, 0x2); - GET_OUTPUT_GPR(rpatch, 0x10b, 0x3); - - - /* input buffer */ - OP(6, 0x102, AC97_IN_L, 0x40, 0x40); - OP(6, 0x103, AC97_IN_R, 0x40, 0x40); - - - /* Digital In + PCM + MULTI_FRONT-> AC97 out (front speakers)*/ - OP(6, AC97_FRONT_L, 0x100, 0x10c, 0x113); - - CONNECT(MULTI_FRONT_L, AC97_FRONT_L); - CONNECT(PCM_IN_L, AC97_FRONT_L); - CONNECT(SPDIF_CD_L, AC97_FRONT_L); - - OP(6, AC97_FRONT_R, 0x101, 0x10e, 0x114); - - CONNECT(MULTI_FRONT_R, AC97_FRONT_R); - CONNECT(PCM_IN_R, AC97_FRONT_R); - CONNECT(SPDIF_CD_R, AC97_FRONT_R); - - /* Digital In + PCM + AC97 In + PCM1 + MULTI_REAR --> Rear Channel */ - OP(6, 0x104, PCM1_IN_L, 0x100, 0x115); - OP(6, 0x104, 0x104, 0x10c, 0x102); - - CONNECT(MULTI_REAR_L, ANALOG_REAR_L); - CONNECT(AC97_IN_L, ANALOG_REAR_L); - CONNECT(PCM_IN_L, ANALOG_REAR_L); - CONNECT(SPDIF_CD_L, ANALOG_REAR_L); - CONNECT(PCM1_IN_L, ANALOG_REAR_L); - - OP(6, 0x105, PCM1_IN_R, 0x101, 0x116); - OP(6, 0x105, 0x105, 0x10e, 0x103); - - CONNECT(MULTI_REAR_R, ANALOG_REAR_R); - CONNECT(AC97_IN_R, ANALOG_REAR_R); - CONNECT(PCM_IN_R, ANALOG_REAR_R); - CONNECT(SPDIF_CD_R, ANALOG_REAR_R); - CONNECT(PCM1_IN_R, ANALOG_REAR_R); - - /* Digital In + PCM + AC97 In + MULTI_FRONT --> Digital out */ - OP(6, 0x10a, 0x100, 0x102, 0x10c); - OP(6, 0x10a, 0x10a, 0x113, 0x40); - - CONNECT(MULTI_FRONT_L, DIGITAL_OUT_L); - CONNECT(PCM_IN_L, DIGITAL_OUT_L); - CONNECT(AC97_IN_L, DIGITAL_OUT_L); - CONNECT(SPDIF_CD_L, DIGITAL_OUT_L); - - OP(6, 0x10b, 0x101, 0x103, 0x10e); - OP(6, 0x10b, 0x10b, 0x114, 0x40); - - CONNECT(MULTI_FRONT_R, DIGITAL_OUT_R); - CONNECT(PCM_IN_R, DIGITAL_OUT_R); - CONNECT(AC97_IN_R, DIGITAL_OUT_R); - CONNECT(SPDIF_CD_R, DIGITAL_OUT_R); - - /* AC97 In --> ADC Recording Buffer */ - OP(6, ADC_REC_L, 0x102, 0x40, 0x40); - - CONNECT(AC97_IN_L, ADC_REC_L); - - OP(6, ADC_REC_R, 0x103, 0x40, 0x40); - - CONNECT(AC97_IN_R, ADC_REC_R); + if(card->audigy){ + for (i = 0; i < 1024; i++) + OP(0xf, 0x0c0, 0x0c0, 0x0cf, 0x0c0); + for (i = 0; i < 512 ; i++) + sblive_writeptr(card, A_GPR_BASE+i,0,0); + + pc=0; + //Pcm input volume + OP(0, 0x402, 0x0c0, 0x406, 0x000); + OP(0, 0x403, 0x0c0, 0x407, 0x001); + //CD-Digital input Volume + OP(0, 0x404, 0x0c0, 0x40d, 0x42); + OP(0, 0x405, 0x0c0, 0x40f, 0x43); + // CD + PCM + OP(6, 0x400, 0x0c0, 0x402, 0x404); + OP(6, 0x401, 0x0c0, 0x403, 0x405); + + // Front Output + Master Volume + OP(0, 0x68, 0x0c0, 0x408, 0x400); + OP(0, 0x69, 0x0c0, 0x409, 0x401); + + // Add-in analog inputs for other speakers + OP(6, 0x400, 0x40, 0x400, 0xc0); + OP(6, 0x401, 0x41, 0x401, 0xc0); + + // Digital Front + Master Volume + OP(0, 0x60, 0x0c0, 0x408, 0x400); + OP(0, 0x61, 0x0c0, 0x409, 0x401); + // Rear Output + Rear Volume + OP(0, 0x06e, 0x0c0, 0x419, 0x400); + OP(0, 0x06f, 0x0c0, 0x41a, 0x401); + // Digital Rear Output + Rear Volume + OP(0, 0x066, 0x0c0, 0x419, 0x400); + OP(0, 0x067, 0x0c0, 0x41a, 0x401); + + // Audigy Drive, Headphone out + OP(6, 0x64, 0x0c0, 0x0c0, 0x400); + OP(6, 0x65, 0x0c0, 0x0c0, 0x401); + + // ac97 Recording + OP(6, 0x76, 0x0c0, 0x0c0, 0x40); + OP(6, 0x77, 0x0c0, 0x0c0, 0x41); + + // Center = sub = Left/2 + Right/2 + OP(0xe, 0x400, 0x401, 0xcd, 0x400); + // center/sub Volume (master) + OP(0, 0x06a, 0x0c0, 0x408, 0x400); + OP(0, 0x06b, 0x0c0, 0x409, 0x400); + + // Digital center/sub Volume (master) + OP(0, 0x062, 0x0c0, 0x408, 0x400); + OP(0, 0x063, 0x0c0, 0x409, 0x400); + + ROUTING_PATCH_START(rpatch, "Routing"); + ROUTING_PATCH_END(rpatch); + + /* delimiter patch */ + patch = PATCH(mgr, patch_n); + patch->code_size = 0; + + sblive_writeptr(card, 0x53, 0, 0); + }else{ + for (i = 0; i < 512 ; i++) + OP(6, 0x40, 0x40, 0x40, 0x40); + for (i = 0; i < 256; i++) + sblive_writeptr_tag(card, 0, + FXGPREGBASE + i, 0, + TANKMEMADDRREGBASE + i, 0, + TAGLIST_END); - /* fx12:Analog-Center */ - OP(6, ANALOG_CENTER, 0x117, 0x40, 0x40); - CONNECT(MULTI_CENTER, ANALOG_CENTER); + + pc = 0; - /* fx11:Analog-LFE */ - OP(6, ANALOG_LFE, 0x118, 0x40, 0x40); - CONNECT(MULTI_LFE, ANALOG_LFE); + //first free GPR = 0x11b + + + /* FX volume correction and Volume control*/ + INPUT_PATCH_START(patch, "Pcm L vol", 0x0, 0); + GET_OUTPUT_GPR(patch, 0x100, 0x0); + GET_CONTROL_GPR(patch, 0x106, "Vol", 0, 0x7fffffff); + GET_DYNAMIC_GPR(patch, 0x112); + + OP(4, 0x112, 0x40, PCM_IN_L, 0x44); //*4 + OP(0, 0x100, 0x040, 0x112, 0x106); //*vol + INPUT_PATCH_END(patch); + + + INPUT_PATCH_START(patch, "Pcm R vol", 0x1, 0); + GET_OUTPUT_GPR(patch, 0x101, 0x1); + GET_CONTROL_GPR(patch, 0x107, "Vol", 0, 0x7fffffff); + GET_DYNAMIC_GPR(patch, 0x112); + + OP(4, 0x112, 0x40, PCM_IN_R, 0x44); + OP(0, 0x101, 0x040, 0x112, 0x107); + + INPUT_PATCH_END(patch); + + + // CD-Digital In Volume control + INPUT_PATCH_START(patch, "CD-Digital Vol L", 0x12, 0); + GET_OUTPUT_GPR(patch, 0x10c, 0x12); + GET_CONTROL_GPR(patch, 0x10d, "Vol", 0, 0x7fffffff); + + OP(0, 0x10c, 0x040, SPDIF_CD_L, 0x10d); + INPUT_PATCH_END(patch); + + INPUT_PATCH_START(patch, "CD-Digital Vol R", 0x13, 0); + GET_OUTPUT_GPR(patch, 0x10e, 0x13); + GET_CONTROL_GPR(patch, 0x10f, "Vol", 0, 0x7fffffff); + + OP(0, 0x10e, 0x040, SPDIF_CD_R, 0x10f); + INPUT_PATCH_END(patch); + + //Volume Correction for Multi-channel Inputs + INPUT_PATCH_START(patch, "Multi-Channel Gain", 0x08, 0); + patch->input=patch->output=0x3F00; + + GET_OUTPUT_GPR(patch, 0x113, MULTI_FRONT_L); + GET_OUTPUT_GPR(patch, 0x114, MULTI_FRONT_R); + GET_OUTPUT_GPR(patch, 0x115, MULTI_REAR_L); + GET_OUTPUT_GPR(patch, 0x116, MULTI_REAR_R); + GET_OUTPUT_GPR(patch, 0x117, MULTI_CENTER); + GET_OUTPUT_GPR(patch, 0x118, MULTI_LFE); + + OP(4, 0x113, 0x40, MULTI_FRONT_L, 0x44); + OP(4, 0x114, 0x40, MULTI_FRONT_R, 0x44); + OP(4, 0x115, 0x40, MULTI_REAR_L, 0x44); + OP(4, 0x116, 0x40, MULTI_REAR_R, 0x44); + OP(4, 0x117, 0x40, MULTI_CENTER, 0x44); + OP(4, 0x118, 0x40, MULTI_LFE, 0x44); + + INPUT_PATCH_END(patch); - /* fx12:Digital-Center */ - OP(6, DIGITAL_CENTER, 0x117, 0x40, 0x40); - CONNECT(MULTI_CENTER, DIGITAL_CENTER); - /* fx11:Analog-LFE */ - OP(6, DIGITAL_LFE, 0x118, 0x40, 0x40); - CONNECT(MULTI_LFE, DIGITAL_LFE); + //Routing patch start + ROUTING_PATCH_START(rpatch, "Routing"); + GET_INPUT_GPR(rpatch, 0x100, 0x0); + GET_INPUT_GPR(rpatch, 0x101, 0x1); + GET_INPUT_GPR(rpatch, 0x10c, 0x12); + GET_INPUT_GPR(rpatch, 0x10e, 0x13); + GET_INPUT_GPR(rpatch, 0x113, MULTI_FRONT_L); + GET_INPUT_GPR(rpatch, 0x114, MULTI_FRONT_R); + GET_INPUT_GPR(rpatch, 0x115, MULTI_REAR_L); + GET_INPUT_GPR(rpatch, 0x116, MULTI_REAR_R); + GET_INPUT_GPR(rpatch, 0x117, MULTI_CENTER); + GET_INPUT_GPR(rpatch, 0x118, MULTI_LFE); + + GET_DYNAMIC_GPR(rpatch, 0x102); + GET_DYNAMIC_GPR(rpatch, 0x103); + + GET_OUTPUT_GPR(rpatch, 0x104, 0x8); + GET_OUTPUT_GPR(rpatch, 0x105, 0x9); + GET_OUTPUT_GPR(rpatch, 0x10a, 0x2); + GET_OUTPUT_GPR(rpatch, 0x10b, 0x3); + + + /* input buffer */ + OP(6, 0x102, AC97_IN_L, 0x40, 0x40); + OP(6, 0x103, AC97_IN_R, 0x40, 0x40); + + + /* Digital In + PCM + MULTI_FRONT-> AC97 out (front speakers)*/ + OP(6, AC97_FRONT_L, 0x100, 0x10c, 0x113); + + CONNECT(MULTI_FRONT_L, AC97_FRONT_L); + CONNECT(PCM_IN_L, AC97_FRONT_L); + CONNECT(SPDIF_CD_L, AC97_FRONT_L); + + OP(6, AC97_FRONT_R, 0x101, 0x10e, 0x114); + + CONNECT(MULTI_FRONT_R, AC97_FRONT_R); + CONNECT(PCM_IN_R, AC97_FRONT_R); + CONNECT(SPDIF_CD_R, AC97_FRONT_R); + + /* Digital In + PCM + AC97 In + PCM1 + MULTI_REAR --> Rear Channel */ + OP(6, 0x104, PCM1_IN_L, 0x100, 0x115); + OP(6, 0x104, 0x104, 0x10c, 0x102); + + CONNECT(MULTI_REAR_L, ANALOG_REAR_L); + CONNECT(AC97_IN_L, ANALOG_REAR_L); + CONNECT(PCM_IN_L, ANALOG_REAR_L); + CONNECT(SPDIF_CD_L, ANALOG_REAR_L); + CONNECT(PCM1_IN_L, ANALOG_REAR_L); + + OP(6, 0x105, PCM1_IN_R, 0x101, 0x116); + OP(6, 0x105, 0x105, 0x10e, 0x103); + + CONNECT(MULTI_REAR_R, ANALOG_REAR_R); + CONNECT(AC97_IN_R, ANALOG_REAR_R); + CONNECT(PCM_IN_R, ANALOG_REAR_R); + CONNECT(SPDIF_CD_R, ANALOG_REAR_R); + CONNECT(PCM1_IN_R, ANALOG_REAR_R); + + /* Digital In + PCM + AC97 In + MULTI_FRONT --> Digital out */ + OP(6, 0x10b, 0x100, 0x102, 0x10c); + OP(6, 0x10b, 0x10b, 0x113, 0x40); + + CONNECT(MULTI_FRONT_L, DIGITAL_OUT_L); + CONNECT(PCM_IN_L, DIGITAL_OUT_L); + CONNECT(AC97_IN_L, DIGITAL_OUT_L); + CONNECT(SPDIF_CD_L, DIGITAL_OUT_L); + + OP(6, 0x10a, 0x101, 0x103, 0x10e); + OP(6, 0x10b, 0x10b, 0x114, 0x40); + + CONNECT(MULTI_FRONT_R, DIGITAL_OUT_R); + CONNECT(PCM_IN_R, DIGITAL_OUT_R); + CONNECT(AC97_IN_R, DIGITAL_OUT_R); + CONNECT(SPDIF_CD_R, DIGITAL_OUT_R); + + /* AC97 In --> ADC Recording Buffer */ + OP(6, ADC_REC_L, 0x102, 0x40, 0x40); + + CONNECT(AC97_IN_L, ADC_REC_L); + + OP(6, ADC_REC_R, 0x103, 0x40, 0x40); + + CONNECT(AC97_IN_R, ADC_REC_R); + + + /* fx12:Analog-Center */ + OP(6, ANALOG_CENTER, 0x117, 0x40, 0x40); + CONNECT(MULTI_CENTER, ANALOG_CENTER); + + /* fx11:Analog-LFE */ + OP(6, ANALOG_LFE, 0x118, 0x40, 0x40); + CONNECT(MULTI_LFE, ANALOG_LFE); + + /* fx12:Digital-Center */ + OP(6, DIGITAL_CENTER, 0x117, 0x40, 0x40); + CONNECT(MULTI_CENTER, DIGITAL_CENTER); + + /* fx11:Analog-LFE */ + OP(6, DIGITAL_LFE, 0x118, 0x40, 0x40); + CONNECT(MULTI_LFE, DIGITAL_LFE); - ROUTING_PATCH_END(rpatch); + ROUTING_PATCH_END(rpatch); - // Rear volume control - OUTPUT_PATCH_START(patch, "Vol Rear L", 0x8, 0); - GET_INPUT_GPR(patch, 0x104, 0x8); - GET_CONTROL_GPR(patch, 0x119, "Vol", 0, 0x7fffffff); + // Rear volume control + OUTPUT_PATCH_START(patch, "Vol Rear L", 0x8, 0); + GET_INPUT_GPR(patch, 0x104, 0x8); + GET_CONTROL_GPR(patch, 0x119, "Vol", 0, 0x7fffffff); - OP(0, ANALOG_REAR_L, 0x040, 0x104, 0x119); - OUTPUT_PATCH_END(patch); + OP(0, ANALOG_REAR_L, 0x040, 0x104, 0x119); + OUTPUT_PATCH_END(patch); + OUTPUT_PATCH_START(patch, "Vol Rear R", 0x9, 0); + GET_INPUT_GPR(patch, 0x105, 0x9); + GET_CONTROL_GPR(patch, 0x11a, "Vol", 0, 0x7fffffff); - OUTPUT_PATCH_START(patch, "Vol Rear R", 0x9, 0); - GET_INPUT_GPR(patch, 0x105, 0x9); - GET_CONTROL_GPR(patch, 0x11a, "Vol", 0, 0x7fffffff); + OP(0, ANALOG_REAR_R, 0x040, 0x105, 0x11a); + OUTPUT_PATCH_END(patch); - OP(0, ANALOG_REAR_R, 0x040, 0x105, 0x11a); - OUTPUT_PATCH_END(patch); + //Master volume control on front-digital + OUTPUT_PATCH_START(patch, "Vol Master L", 0x2, 1); + GET_INPUT_GPR(patch, 0x10a, 0x2); + GET_CONTROL_GPR(patch, 0x108, "Vol", 0, 0x7fffffff); - //Master volume control on front-digital - OUTPUT_PATCH_START(patch, "Vol Master L", 0x2, 1); - GET_INPUT_GPR(patch, 0x10a, 0x2); - GET_CONTROL_GPR(patch, 0x108, "Vol", 0, 0x7fffffff); + OP(0, DIGITAL_OUT_L, 0x040, 0x10a, 0x108); + OUTPUT_PATCH_END(patch); - OP(0, DIGITAL_OUT_L, 0x040, 0x10a, 0x108); - OUTPUT_PATCH_END(patch); + OUTPUT_PATCH_START(patch, "Vol Master R", 0x3, 1); + GET_INPUT_GPR(patch, 0x10b, 0x3); + GET_CONTROL_GPR(patch, 0x109, "Vol", 0, 0x7fffffff); - OUTPUT_PATCH_START(patch, "Vol Master R", 0x3, 1); - GET_INPUT_GPR(patch, 0x10b, 0x3); - GET_CONTROL_GPR(patch, 0x109, "Vol", 0, 0x7fffffff); + OP(0, DIGITAL_OUT_R, 0x040, 0x10b, 0x109); + OUTPUT_PATCH_END(patch); - OP(0, DIGITAL_OUT_R, 0x040, 0x10b, 0x109); - OUTPUT_PATCH_END(patch); + /* delimiter patch */ + patch = PATCH(mgr, patch_n); + patch->code_size = 0; - /* delimiter patch */ - patch = PATCH(mgr, patch_n); - patch->code_size = 0; - - sblive_writeptr(card, DBG, 0, 0); + + sblive_writeptr(card, DBG, 0, 0); + } mgr->lock = SPIN_LOCK_UNLOCKED; + // Set up Volume controls, try to keep this the same for both Audigy and Live //Master volume mgr->ctrl_gpr[SOUND_MIXER_VOLUME][0] = 8; @@ -733,8 +837,15 @@ emu10k1_set_volume_gpr(card, 0xd, left, VOL_5BIT); emu10k1_set_volume_gpr(card, 0xf, right, VOL_5BIT); - //hard wire the ac97's pcm, we'll do that in dsp code instead. - emu10k1_ac97_write(&card->ac97, 0x18, 0x0); + + //hard wire the ac97's pcm, pcm volume is done above using dsp code. + if(card->audigy) + //for Audigy, we mute it and use the philips 6 channel DAC instead + emu10k1_ac97_write(&card->ac97, 0x18, 0x8000); + else + //For the Live we hardwire it to full volume + emu10k1_ac97_write(&card->ac97, 0x18, 0x0); + //remove it from the ac97_codec's control card->ac97_supported_mixers &= ~SOUND_MASK_PCM; card->ac97_stereo_mixers &= ~SOUND_MASK_PCM; @@ -772,6 +883,12 @@ SOLEL, 0, SOLEH, 0, TAGLIST_END); + if(card->audigy){ + sblive_writeptr_tag(card,0, + 0x5e,0xf00, + 0x5f,0x3, + TAGLIST_END); + } /* Init envelope engine */ for (nCh = 0; nCh < NUM_G; nCh++) { @@ -807,7 +924,23 @@ ENVVOL, 0, ENVVAL, 0, TAGLIST_END); + sblive_writeptr(card, CPF, nCh, 0); + /* + Audigy FXRT initialization + reversed eng'd, may not be accurate. + */ + if(card->audigy){ + sblive_writeptr_tag(card,nCh, + 0x4c,0x0, + 0x4d,0x0, + 0x4e,0x0, + 0x4f,0x0, + A_FXRT1, 0x3f3f3f3f, + A_FXRT2, 0x3f3f3f3f, + A_SENDAMOUNTS, 0, + TAGLIST_END); + } } @@ -867,19 +1000,20 @@ } for (pagecount = 0; pagecount < MAXPAGES; pagecount++) - ((u32 *) card->virtualpagetable.addr)[pagecount] = cpu_to_le32((card->silentpage.dma_handle * 2) | pagecount); + ((u32 *) card->virtualpagetable.addr)[pagecount] = cpu_to_le32(( (u32)card->silentpage.dma_handle * 2) | +pagecount); /* Init page table & tank memory base register */ sblive_writeptr_tag(card, 0, - PTB, card->virtualpagetable.dma_handle, + PTB,(u32) card->virtualpagetable.dma_handle, TCB, 0, TCBS, 0, TAGLIST_END); for (nCh = 0; nCh < NUM_G; nCh++) { sblive_writeptr_tag(card, nCh, - MAPA, MAP_PTI_MASK | (card->silentpage.dma_handle * 2), - MAPB, MAP_PTI_MASK | (card->silentpage.dma_handle * 2), + MAPA, MAP_PTI_MASK | ((u32)card->silentpage.dma_handle * 2), + MAPB, MAP_PTI_MASK | ((u32)card->silentpage.dma_handle * 2), TAGLIST_END); } @@ -889,8 +1023,9 @@ /* Lock Tank Memory = 1 */ /* Lock Sound Memory = 0 */ /* Auto Mute = 1 */ - - if (card->model == 0x20 || card->model == 0xc400 || + if(card->audigy) + emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE | HCFG_AUTOMUTE | HCFG_JOYENABLE); + else if (card->model == 0x20 || card->model == 0xc400 || (card->model == 0x21 && card->chiprev < 6)) emu10k1_writefn0(card, HCFG, HCFG_AUDIOENABLE | HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE); else @@ -995,6 +1130,8 @@ SOLEL, 0, SOLEH, 0, TAGLIST_END); + if(card->audigy) + sblive_writeptr(card, 0, A_DBG, A_DBG_SINGLE_STEP); pci_free_consistent(card->pci_dev, card->virtualpagetable.size, card->virtualpagetable.addr, card->virtualpagetable.dma_handle); @@ -1014,9 +1151,17 @@ u32 subsysvid; int ret; - if (pci_set_dma_mask(pci_dev, EMU10K1_DMA_MASK)) { - printk(KERN_ERR "emu10k1: architecture does not support 32bit PCI busmaster DMA\n"); - return -ENODEV; + + if(pci_id->driver_data){ + if (pci_set_dma_mask(pci_dev, AUDIGY_DMA_MASK)) { + printk(KERN_ERR "emu10k1: architecture does not support 32bit PCI busmaster DMA\n"); + return -ENODEV; + } + else + if (pci_set_dma_mask(pci_dev, EMU10K1_DMA_MASK)) { + printk(KERN_ERR "emu10k1: architecture does not support 32bit PCI busmaster DMA\n"); + return -ENODEV; + } } if (pci_enable_device(pci_dev)) @@ -1032,7 +1177,7 @@ card->iobase = pci_resource_start(pci_dev, 0); card->length = pci_resource_len(pci_dev, 0); - + card->audigy = pci_id->driver_data; if (request_region(card->iobase, card->length, card_names[pci_id->driver_data]) == NULL) { printk(KERN_ERR "emu10k1: IO space in use\n"); ret = -EBUSY; @@ -1135,7 +1280,7 @@ pci_set_drvdata(pci_dev, NULL); } -MODULE_AUTHOR("Bertrand Lee, Cai Ying. (Email to: emu10k1-devel@opensource.creative.com)"); +MODULE_AUTHOR("Bertrand Lee, Cai Ying. (Email to: emu10k1-devel@lists.sourceforge.net)"); MODULE_DESCRIPTION("Creative EMU10K1 PCI Audio Driver v" DRIVER_VERSION "\nCopyright (C) 1999 Creative Technology Ltd."); MODULE_LICENSE("GPL"); diff -urN linux-2.4.18/drivers/sound/emu10k1/midi.h linux/drivers/sound/emu10k1/midi.h --- linux-2.4.18/drivers/sound/emu10k1/midi.h Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/midi.h Fri Mar 1 20:55:19 2002 @@ -52,4 +52,27 @@ struct list_head mid_hdrs; }; +/* uncomment next line to use midi port on Audigy drive */ +//#define USE_AUDIGY_DRIVE_MIDI + +#ifdef USE_AUDIGY_DRIVE_MIDI +#define A_MUDATA A_MUDATA2 +#define A_MUCMD A_MUCMD2 +#define A_MUSTAT A_MUCMD2 +#define IPR_A_MIDITRANSBUFEMPTY IPR_A_MIDITRANSBUFEMPTY2 +#define IPR_A_MIDIRECVBUFEMPTY IPR_A_MIDIRECVBUFEMPTY2 +#define INTE_A_MIDITXENABLE INTE_A_MIDITXENABLE2 +#define INTE_A_MIDIRXENABLE INTE_A_MIDIRXENABLE2 +#else +#define A_MUDATA A_MUDATA1 +#define A_MUCMD A_MUCMD1 +#define A_MUSTAT A_MUCMD1 +#define IPR_A_MIDITRANSBUFEMPTY IPR_A_MIDITRANSBUFEMPTY1 +#define IPR_A_MIDIRECVBUFEMPTY IPR_A_MIDIRECVBUFEMPTY1 +#define INTE_A_MIDITXENABLE INTE_A_MIDITXENABLE1 +#define INTE_A_MIDIRXENABLE INTE_A_MIDIRXENABLE1 +#endif + + #endif /* _MIDI_H */ + diff -urN linux-2.4.18/drivers/sound/emu10k1/mixer.c linux/drivers/sound/emu10k1/mixer.c --- linux-2.4.18/drivers/sound/emu10k1/mixer.c Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/mixer.c Fri Mar 1 20:57:00 2002 @@ -138,7 +138,7 @@ r = (r * 40 + 50) / 100; for (i = 0; i < 5; i++) - sblive_writeptr(card, GPR_BASE + card->mgr.ctrl_gpr[SOUND_MIXER_BASS][0] + i, 0, bass_table[l][i]); + sblive_writeptr(card, IS_EMU10K1?GPR_BASE:A_GPR_BASE + card->mgr.ctrl_gpr[SOUND_MIXER_BASS][0] + i, 0, bass_table[l][i]); } static void set_treble(struct emu10k1_card *card, int l, int r) @@ -149,7 +149,7 @@ r = (r * 40 + 50) / 100; for (i = 0; i < 5; i++) - sblive_writeptr(card, GPR_BASE + card->mgr.ctrl_gpr[SOUND_MIXER_TREBLE][0] + i , 0, treble_table[l][i]); + sblive_writeptr(card, IS_EMU10K1?GPR_BASE:A_GPR_BASE + card->mgr.ctrl_gpr[SOUND_MIXER_TREBLE][0] + i , 0, treble_table[l][i]); } const char volume_params[SOUND_MIXER_NRDEVICES]= { @@ -208,22 +208,26 @@ switch (ctl->cmd) { #ifdef DBGEMU case CMD_WRITEFN0: - emu10k1_writefn0(card, ctl->val[0], ctl->val[1]); + + emu10k1_writefn0_2(card, ctl->val[0], ctl->val[1], ctl->val[2]); break; - +#endif case CMD_WRITEPTR: - if (ctl->val[1] >= 0x40 || ctl->val[0] > 0xff) { +#ifdef DBGEMU + if (ctl->val[1] >= 0x40 || ctl->val[0] >= 0x1000) { +#else + if (ctl->val[1] >= 0x40 || ctl->val[0] >= 0x1000 || ((ctl->val[0] < 0x100 ) && + //Any register allowed raw access goes here: + (ctl->val[0] != A_SPDIF_SAMPLERATE) && (ctl->val[0] != A_DBG) + ) + ) { +#endif ret = -EINVAL; break; } - - if ((ctl->val[0] & 0x7ff) > 0x3f) - ctl->val[1] = 0x00; - sblive_writeptr(card, ctl->val[0], ctl->val[1], ctl->val[2]); - break; -#endif + case CMD_READFN0: ctl->val[2] = emu10k1_readfn0(card, ctl->val[0]); @@ -288,16 +292,13 @@ case CMD_GETVOICEPARAM: ctl->val[0] = card->waveout.send_routing[0]; - ctl->val[1] = card->waveout.send_a[0] | card->waveout.send_b[0] << 8 | - card->waveout.send_c[0] << 16 | card->waveout.send_d[0] << 24; + ctl->val[1] = card->waveout.send_dcba[0]; ctl->val[2] = card->waveout.send_routing[1]; - ctl->val[3] = card->waveout.send_a[1] | card->waveout.send_b[1] << 8 | - card->waveout.send_c[1] << 16 | card->waveout.send_d[1] << 24; + ctl->val[3] = card->waveout.send_dcba[1]; ctl->val[4] = card->waveout.send_routing[2]; - ctl->val[5] = card->waveout.send_a[2] | card->waveout.send_b[2] << 8 | - card->waveout.send_c[2] << 16 | card->waveout.send_d[2] << 24; + ctl->val[5] =card->waveout.send_dcba[2]; if (copy_to_user((void *) arg, ctl, sizeof(struct mixer_private_ioctl))) ret = -EFAULT; @@ -305,23 +306,14 @@ break; case CMD_SETVOICEPARAM: - card->waveout.send_routing[0] = ctl->val[0] & 0xffff; - card->waveout.send_a[0] = ctl->val[1] & 0xff; - card->waveout.send_b[0] = (ctl->val[1] >> 8) & 0xff; - card->waveout.send_c[0] = (ctl->val[1] >> 16) & 0xff; - card->waveout.send_d[0] = (ctl->val[1] >> 24) & 0xff; - - card->waveout.send_routing[1] = ctl->val[2] & 0xffff; - card->waveout.send_a[1] = ctl->val[3] & 0xff; - card->waveout.send_b[1] = (ctl->val[3] >> 8) & 0xff; - card->waveout.send_c[1] = (ctl->val[3] >> 16) & 0xff; - card->waveout.send_d[1] = (ctl->val[3] >> 24) & 0xff; - - card->waveout.send_routing[2] = ctl->val[4] & 0xffff; - card->waveout.send_a[2] = ctl->val[5] & 0xff; - card->waveout.send_b[2] = (ctl->val[5] >> 8) & 0xff; - card->waveout.send_c[2] = (ctl->val[5] >> 16) & 0xff; - card->waveout.send_d[2] = (ctl->val[5] >> 24) & 0xff; + card->waveout.send_routing[0] = ctl->val[0]; + card->waveout.send_dcba[0] = ctl->val[1]; + + card->waveout.send_routing[1] = ctl->val[2]; + card->waveout.send_dcba[1] = ctl->val[3]; + + card->waveout.send_routing[2] = ctl->val[4]; + card->waveout.send_dcba[2] = ctl->val[5]; break; @@ -418,12 +410,15 @@ break; case CMD_SETGPOUT: - if (ctl->val[0] > 2 || ctl->val[1] > 1) { + if ( (ctl->val[0] > 2) &(!card->audigy) + || (ctl->val[0] > 16) || ctl->val[1] > 1){ ret= -EINVAL; break; } - - emu10k1_writefn0(card, (1 << 24) | (((ctl->val[0]) + 10) << 16) | HCFG, ctl->val[1]); + if(card->audigy) + emu10k1_writefn0(card, (1 << 24) | ((ctl->val[0]) << 16) | A_IOCFG, ctl->val[1]); + else + emu10k1_writefn0(card, (1 << 24) | (((ctl->val[0]) + 10) << 16) | HCFG, ctl->val[1]); break; case CMD_GETGPR2OSS: @@ -493,9 +488,14 @@ card->pt.spcs_to_use = ctl->val[0] & 0x07; break; - + case CMD_PRIVATE3_VERSION: - ctl->val[0]=PRIVATE3_VERSION; + ctl->val[0]=PRIVATE3_VERSION;//private3 version + ctl->val[1]=MAJOR_VER;//major driver version + ctl->val[2]=MINOR_VER;//minor driver version + ctl->val[3]=card->audigy;//1=card is audigy + if(card->audigy) + ctl->val[4]=emu10k1_readfn0(card, 0x18); if (copy_to_user((void *) arg, ctl, sizeof(struct mixer_private_ioctl))) ret = -EFAULT; break; @@ -558,7 +558,8 @@ card->tankmem.size = size; - sblive_writeptr_tag(card, 0, TCB, card->tankmem.dma_handle, TCBS, size_reg, TAGLIST_END); + sblive_writeptr_tag(card, 0, TCB,(u32) card->tankmem.dma_handle, TCBS,(u32) size_reg, +TAGLIST_END); emu10k1_writefn0(card, HCFG_LOCKTANKCACHE, 0); } @@ -626,7 +627,11 @@ mixer_info info; strncpy(info.id, card->ac97.name, sizeof(info.id)); - strncpy(info.name, "Creative SBLive - Emu10k1", sizeof(info.name)); + if(card->audigy) + strncpy(info.name, "Audigy - Emu10k1", sizeof(info.name)); + else + strncpy(info.name, "Creative SBLive - Emu10k1", sizeof(info.name)); + info.modify_counter = card->ac97.modcnt; if (copy_to_user((void *)arg, &info, sizeof(info))) diff -urN linux-2.4.18/drivers/sound/emu10k1/passthrough.c linux/drivers/sound/emu10k1/passthrough.c --- linux-2.4.18/drivers/sound/emu10k1/passthrough.c Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/passthrough.c Fri Mar 1 20:55:19 2002 @@ -112,7 +112,7 @@ return 0; } -static int pt_setup(struct emu10k1_wavedevice *wave_dev) +int emu10k1_pt_setup(struct emu10k1_wavedevice *wave_dev) { u32 bits; struct emu10k1_card *card = wave_dev->card; @@ -158,7 +158,7 @@ pt->prepend_size = 0; if (pt->buf == NULL) return -ENOMEM; - pt_setup(wave_dev); + emu10k1_pt_setup(wave_dev); } if (pt->prepend_size) { int needed = PT_BLOCKSIZE - pt->prepend_size; @@ -211,13 +211,14 @@ if (pt->state != PT_STATE_INACTIVE) { DPF(2, "digital pass-through stopped\n"); - sblive_writeptr(card, GPR_BASE + pt->enable_gpr, 0, 0); + sblive_writeptr(card, (IS_AUDIGY?A_GPR_BASE:GPR_BASE) + pt->enable_gpr, 0, 0); for (i = 0; i < 3; i++) { if (pt->spcs_to_use & (1 << i)) sblive_writeptr(card, SPCS0 + i, 0, pt->old_spcs[i]); } pt->state = PT_STATE_INACTIVE; - kfree(pt->buf); + if(pt->buf) + kfree(pt->buf); } } diff -urN linux-2.4.18/drivers/sound/emu10k1/passthrough.h linux/drivers/sound/emu10k1/passthrough.h --- linux-2.4.18/drivers/sound/emu10k1/passthrough.h Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/passthrough.h Fri Mar 1 20:55:19 2002 @@ -63,7 +63,36 @@ spinlock_t lock; }; +/* + Passthrough can be done in two methods: + + Method 1 : tram + In original emu10k1, we couldn't bypass the sample rate converters. Even at 48kHz + (the internal sample rate of the emu10k1) the samples would get messed up. + To over come this, samples are copied into the tram and a special dsp patch copies + the samples out and generates interrupts when a block has finnished playing. + + Method 2 : Interpolator bypass + + Creative fixed the sample rate convert problem in emu10k1 rev 7 and higher + (including the the emu10k2 (audigy)). This allows us to use the regular, and much simpler + playback method. + + + In both methods, dsp code is used to mux audio and passthrough. This ensures that the spdif + doesn't receive audio and pasthrough data at the same time. The spdif flag SPCS_NOTAUDIODATA + is set to tell + + */ + +// emu10k1 revs greater than or equal to 7 can use method2 + +#define USE_PT_METHOD2 (IS_AUDIGY) +#define USE_PT_METHOD1 !USE_PT_METHOD2 + ssize_t emu10k1_pt_write(struct file *file, const char *buf, size_t count); + +int emu10k1_pt_setup(struct emu10k1_wavedevice *wave_dev); void emu10k1_pt_stop(struct emu10k1_card *card); void emu10k1_pt_waveout_update(struct emu10k1_wavedevice *wave_dev); diff -urN linux-2.4.18/drivers/sound/emu10k1/recmgr.c linux/drivers/sound/emu10k1/recmgr.c --- linux-2.4.18/drivers/sound/emu10k1/recmgr.c Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/recmgr.c Fri Mar 1 20:55:19 2002 @@ -69,7 +69,7 @@ DPF(2, "recording source: AC97\n"); buffer->sizereg = ADCBS; buffer->addrreg = ADCBA; - buffer->idxreg = ADCIDX_IDX; + buffer->idxreg = card->audigy? A_ADCIDX_IDX:ADCIDX_IDX; switch (wiinst->format.samplingrate) { case 0xBB80: @@ -90,21 +90,27 @@ case 0x3E80: buffer->adcctl = ADCCR_SAMPLERATE_16; break; +// FIXME: audigy supports 12kHz recording + /* + case ????: + buffer->adcctl = A_ADCCR_SAMPLERATE_12; + break; + */ case 0x2B11: - buffer->adcctl = ADCCR_SAMPLERATE_11; + buffer->adcctl = card->audigy? A_ADCCR_SAMPLERATE_11: ADCCR_SAMPLERATE_11; break; case 0x1F40: - buffer->adcctl = ADCCR_SAMPLERATE_8; + buffer->adcctl = card->audigy? A_ADCCR_SAMPLERATE_8: ADCCR_SAMPLERATE_8; break; default: BUG(); break; } - - buffer->adcctl |= ADCCR_LCHANENABLE; + + buffer->adcctl |= card->audigy? A_ADCCR_LCHANENABLE: ADCCR_LCHANENABLE; if (wiinst->format.channels == 2) - buffer->adcctl |= ADCCR_RCHANENABLE; + buffer->adcctl |= card->audigy? A_ADCCR_RCHANENABLE: ADCCR_RCHANENABLE; break; @@ -132,7 +138,7 @@ DPD(2, "bus addx: %#lx\n", (unsigned long) buffer->dma_handle); - sblive_writeptr(card, buffer->addrreg, 0, buffer->dma_handle); + sblive_writeptr(card, buffer->addrreg, 0, (u32)buffer->dma_handle); return; } diff -urN linux-2.4.18/drivers/sound/emu10k1/voicemgr.c linux/drivers/sound/emu10k1/voicemgr.c --- linux-2.4.18/drivers/sound/emu10k1/voicemgr.c Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/voicemgr.c Fri Mar 1 20:55:19 2002 @@ -32,6 +32,34 @@ #include "voicemgr.h" #include "8010.h" +#define PITCH_48000 0x00004000 +#define PITCH_96000 0x00008000 +#define PITCH_85000 0x00007155 +#define PITCH_80726 0x00006ba2 +#define PITCH_67882 0x00005a82 +#define PITCH_57081 0x00004c1c + +u32 emu10k1_select_interprom(struct emu10k1_card *card, struct emu_voice *voice) +{ + if(voice->pitch_target==PITCH_48000) + return CCCA_INTERPROM_0; + else if(voice->pitch_targetpitch_target>=PITCH_96000) + return CCCA_INTERPROM_0; + else if(voice->pitch_target>=PITCH_85000) + return CCCA_INTERPROM_6; + else if(voice->pitch_target>=PITCH_80726) + return CCCA_INTERPROM_5; + else if(voice->pitch_target>=PITCH_67882) + return CCCA_INTERPROM_4; + else if(voice->pitch_target>=PITCH_57081) + return CCCA_INTERPROM_3; + else + return CCCA_INTERPROM_2; +} + + /** * emu10k1_voice_alloc_buffer - * @@ -66,7 +94,7 @@ DPD(2, "Virtual Addx: %p\n", mem->addr[pagecount]); for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) { - busaddx = mem->dma_handle[pagecount] + i * EMUPAGESIZE; + busaddx = (u32)(mem->dma_handle[pagecount]) + i * EMUPAGESIZE; DPD(3, "Bus Addx: %#lx\n", busaddx); @@ -102,7 +130,7 @@ for (i = 0; i < PAGE_SIZE / EMUPAGESIZE; i++) { pageindex = mem->emupageindex + pagecount * PAGE_SIZE / EMUPAGESIZE + i; ((u32 *) card->virtualpagetable.addr)[pageindex] = - cpu_to_le32((card->silentpage.dma_handle * 2) | pageindex); + cpu_to_le32(((u32)card->silentpage.dma_handle * 2) | pageindex); } } @@ -216,23 +244,32 @@ voice->start += start; for (i = 0; i < (voice->flags & VOICE_FLAGS_STEREO ? 2 : 1); i++) { - sblive_writeptr(card, FXRT, voice->num + i, voice->params[i].send_routing << 16); + if(!card->audigy){ + sblive_writeptr(card, FXRT, voice->num + i, voice->params[i].send_routing << 16); + }else{ + sblive_writeptr(card, A_FXRT1, voice->num + i, voice->params[i].send_routing); + sblive_writeptr(card, A_FXRT2, voice->num + i, voice->params[i].send_routing2); + sblive_writeptr(card, A_SENDAMOUNTS, voice->num + i, voice->params[i].send_hgfe); + } + /* Stop CA */ /* Assumption that PT is already 0 so no harm overwriting */ - sblive_writeptr(card, PTRX, voice->num + i, (voice->params[i].send_a << 8) | voice->params[i].send_b); + sblive_writeptr(card, PTRX, voice->num + i, ((voice->params[i].send_dcba&0xff) << 8) + | ((voice->params[i].send_dcba&0xff00)>>8)); sblive_writeptr_tag(card, voice->num + i, /* CSL, ST, CA */ - DSL, voice->endloop | (voice->params[i].send_d << 24), - PSST, voice->startloop | (voice->params[i].send_c << 24), - CCCA, (voice->start) | CCCA_INTERPROM_0 | ((voice->flags & VOICE_FLAGS_16BIT) ? 0 : CCCA_8BITSELECT), + DSL, voice->endloop | (voice->params[i].send_dcba & 0xff000000), + PSST, voice->startloop | ((voice->params[i].send_dcba &0x00ff0000)<< 8), + CCCA, (voice->start) | emu10k1_select_interprom(card,voice) | + ((voice->flags & VOICE_FLAGS_16BIT) ? 0 : CCCA_8BITSELECT), /* Clear filter delay memory */ Z1, 0, Z2, 0, /* Invalidate maps */ - MAPA, MAP_PTI_MASK | (card->silentpage.dma_handle * 2), - MAPB, MAP_PTI_MASK | (card->silentpage.dma_handle * 2), + MAPA, MAP_PTI_MASK | ((u32)card->silentpage.dma_handle * 2), + MAPB, MAP_PTI_MASK | ((u32)card->silentpage.dma_handle * 2), /* modulation envelope */ CVCF, 0x0000ffff, VTFT, 0x0000ffff, diff -urN linux-2.4.18/drivers/sound/emu10k1/voicemgr.h linux/drivers/sound/emu10k1/voicemgr.h --- linux-2.4.18/drivers/sound/emu10k1/voicemgr.h Fri Mar 1 20:49:45 2002 +++ linux/drivers/sound/emu10k1/voicemgr.h Fri Mar 1 20:55:19 2002 @@ -48,11 +48,13 @@ /* FX bus amount send */ u32 send_routing; + // audigy only: + u32 send_routing2; + + u32 send_dcba; + // audigy only: + u32 send_hgfe; - u32 send_a; - u32 send_b; - u32 send_c; - u32 send_d; u32 initial_fc; u32 fc_target;