NT4/private/ntos/dd/sound/mvaudio/mvmix.c
2020-09-30 17:12:29 +02:00

1128 lines
32 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******************************************************************************
Copyright (c) 1993 Media Vision Inc. All Rights Reserved
Module Name:
mvmix.c
Abstract:
This module contains code for controlling the Media Vision Mixer
hardware. Media Vision has used only two software-controllable
mixer chips so far. The MV 508 is used on the PAS 16 only. All
other chips use the National part XXXX. Programming the
Nationial mixer chip is VOODOO BLACK MAGIC and will be very slow
under NT.
Environment:
Kernel mode
Revision History:
27-Sep-1992
Initial revision
*****************************************************************************/
#include "sound.h"
void NationalMix( IN OUT PGLOBAL_DEVICE_INFO pGDI,
USHORT wData );
void NationalVolume( IN OUT PGLOBAL_DEVICE_INFO pGDI,
USHORT wVolume,
UCHAR wVolumeRegister );
ULONG Scale100ToFFFF( USHORT wVal );
BYTE ScaleFFFFTo100( USHORT wVal );
#ifdef ALLOC_PRAGMA
#endif
//-------------------------========================---------------------------
//------------------------====< DATA SECTION >====---------------------------
//-------------------------========================---------------------------
//
// Filter Table indexed by SampleFilterSetting
// Used in SetFilter()
//
// a linear table of filter values - from mute to high
//
CONST UCHAR FilterTable[]=
{
0x00, // 000000b mute - goes to PC speaker
0x24, // 100100b 20hz to 2.9khz
0x39, // 111001b 20hz to 5.9khz
0x31, // 110001b 20hz to 8.9khz
0x29, // 101001b 20hz to 11.9khz
0x22, // 100010b 20hz to 15.9khz
0x21, // 100001b 20hz to 17.8khz
};
//
// Tables for use by the Mixer
//
//
//Mixer settings (0 - 12)
//
CONST UCHAR mixersettings[]=
{
0x00, // level 0
0x20, // level 1
0x10, // level 2
0x08, // level 3
0x04, // level 4
0x02, // level 5
0x12, // level 6
0x2A, // level 7
0x16, // level 8
0x01, // level 9
0x29, // level A
0x1D, // level B
0x2F // level C
};
//
// Volume settings (0 - 12)
//
CONST UCHAR volsettings[]=
{
0x00, // level 0
0x60, // level 1
0x50, // level 2
0x48, // level 3
0x44, // level 4
0x42, // level 5
0x52, // level 6
0x6A, // level 7
0x56, // level 8
0x41, // level 9
0x69, // level A
0x5D, // level B
0x6F // level C
};
//
// Xlat table lookup= 0-31
// result= 0-12
//
CONST UCHAR Scale32To12[]=
{
0 , 1, 1, 2, 2, 3, 3, 3, // 0- 7
4 , 4, 4, 5, 5, 5, 6, 6, // 8-15
6 , 7, 7, 7, 8, 8, 8, 9, // 16-23
9 , 9,10,10,11,11,12,12 // 24-31
};
CONST UCHAR Scale64To40[]=
{
0 , 1, 2, 3, 4, 5, 6, 7, // 0- 7
8 , 8, 9,10,10,11,12,12, // 8-15
13,14,14,15,16,16,17,18, // 16-23
18,19,20,20,21,22,22,23, // 24-31
24,24,25,26,26,27,28,28, // 32-39
29,29,30,30,31,31,32,32, // 40-47
32,33,33,34,34,35,35,35, // 48-55
36,36,37,37,38,38,39,40 // 56-63
};
CONST UCHAR BassTreb32to13[]=
{
0 , 1, 1, 2, 2, 3, 3, 3, // 0- 7
4 , 4, 4, 5, 5, 5, 6, 6, // 8-15
6 , 7, 7, 7, 8, 8, 8, 9, // 16-23
9 , 9,10,10,11,11,12,12 // 24-31
};
//
// This table scales the Mixer Volume settings better!
//
CONST UCHAR ScaleMixerVolume[]=
{
0 , 8,12,14,16,17,18,18, // 0- 7
19,19,20,20,21,21,22,22, // 8-15
22,23,23,23,24,24,24,25, // 16-23
25,25,26,26,27,27,29,31 // 24-31
};
//
// MV508B scale for Volume settings
//
// for Attenuation
// 0 = full attenuation
// 31 = 0dB attenuation
//
// for Gain
// 31 = +2dB gain
// 22 = +20db gain
// 0 = Max gain
//
// Line 0 - FM ==> +26dB of gain; Max Gain on this input line
//
CONST UCHAR Scale508BMixerL0Volume[] =
{
0 , 8,13,16,17,18,19,20, // 0- 7
21,22,23,24,25,26,27,28, // 8-15
29,30,31,31,30,29,28,27, // 16-23
26,25,24,23,22,21,20,19 // 24-31
};
//
// Line 1 - Mix input ==> NO Gain!!
//
CONST UCHAR Scale508BMixerL1Volume[] =
{
0 , 8,12,14,16,17,18,18, // 0- 7
19,19,20,20,21,21,22,22, // 8-15
22,23,23,23,24,24,24,25, // 16-23
25,26,26,27,28,29,30,31 // 24-31
};
//
// Line 2 - Line In ==> +20db of gain; -6dB of Gain compared to FM
//
CONST UCHAR Scale508BMixerL2Volume[] =
{
0 , 8,12,13,14,15,16,17, // 0- 7
18,19,20,21,22,23,24,25, // 8-15
26,27,28,29,30,31,31,30, // 16-23
29,28,27,26,25,24,23,22 // 24-31
};
//
// Line 3 - CD-ROM ==> +20db of gain; -6dB of Gain compared to FM
//
CONST UCHAR Scale508BMixerL3Volume[] =
{
0 , 8,12,13,14,15,16,17, // 0- 7
18,19,20,21,22,23,24,25, // 8-15
26,27,28,29,30,31,31,30, // 16-23
29,28,27,26,25,24,23,22 // 24-31
};
//
// Line 4 - MIC ==> +20db of gain; -6dB of Gain compared to FM
//
CONST UCHAR Scale508BMixerL4Volume[] =
{
0 , 8,12,13,14,15,16,17, // 0- 7
18,19,20,21,22,23,24,25, // 8-15
26,27,28,29,30,31,31,30, // 16-23
29,28,27,26,25,24,23,22 // 24-31
};
//
// Line 5 - Wave Out ==> +20db of gain; -6dB of Gain compared to FM
//
CONST UCHAR Scale508BMixerL5Volume[] =
{
0 , 8,12,13,14,15,16,17, // 0- 7
18,19,20,21,22,23,24,25, // 8-15
26,27,28,29,30,31,31,30, // 16-23
29,28,27,26,25,24,23,22 // 24-31
};
//
// Line 6 - PC Speaker ==> +20db of gain; -6dB of Gain compared to FM
//
CONST UCHAR Scale508BMixerL6Volume[] =
{
0 , 8,12,13,14,15,16,17, // 0- 7
18,19,20,21,22,23,24,25, // 8-15
26,27,28,29,30,31,31,30, // 16-23
29,28,27,26,25,24,23,22 // 24-31
};
//
// Line 7 - SoundBlaster ==> +20db of gain; -6dB of Gain compared to FM
//
CONST UCHAR Scale508BMixerL7Volume[] =
{
0 , 8,12,13,14,15,16,17, // 0- 7
18,19,20,21,22,23,24,25, // 8-15
26,27,28,29,30,31,31,30, // 16-23
29,28,27,26,25,24,23,22 // 24-31
};
//
// This is the table for bit D6
// 0 = attenuation
// 1 = gain
//
// Line 0 - FM
//
CONST UCHAR Scale508BMixerL0VolumeD6[] =
{
0 , 0, 0, 0, 0, 0, 0, 0, // 0- 7
0 , 0, 0, 0, 0, 0, 0, 0, // 8-15
0 , 0, 0, 1, 1, 1, 1, 1, // 16-23
1 , 1, 1, 1, 1, 1, 1, 1 // 24-31
};
//
// Line 1 - Mix
//
CONST UCHAR Scale508BMixerL1VolumeD6[] =
{
0 , 0, 0, 0, 0, 0, 0, 0, // 0- 7
0 , 0, 0, 0, 0, 0, 0, 0, // 8-15
0 , 0, 0, 0, 0, 0, 0, 0, // 16-23
0 , 0, 0, 0, 0, 0, 0, 0 // 24-31
};
//
// Line 2 - Line In
//
CONST UCHAR Scale508BMixerL2VolumeD6[] =
{
0 , 0, 0, 0, 0, 0, 0, 0, // 0- 7
0 , 0, 0, 0, 0, 0, 0, 0, // 8-15
0 , 0, 0, 0, 0, 0, 1, 1, // 16-23
1 , 1, 1, 1, 1, 1, 1, 1 // 24-31
};
//
// Line 3 - CD-ROM
//
CONST UCHAR Scale508BMixerL3VolumeD6[] =
{
0 , 0, 0, 0, 0, 0, 0, 0, // 0- 7
0 , 0, 0, 0, 0, 0, 0, 0, // 8-15
0 , 0, 0, 0, 0, 0, 1, 1, // 16-23
1 , 1, 1, 1, 1, 1, 1, 1 // 24-31
};
//
// Line 4 - Mic
//
CONST UCHAR Scale508BMixerL4VolumeD6[] =
{
0 , 0, 0, 0, 0, 0, 0, 0, // 0- 7
0 , 0, 0, 0, 0, 0, 0, 0, // 8-15
0 , 0, 0, 0, 0, 0, 1, 1, // 16-23
1 , 1, 1, 1, 1, 1, 1, 1 // 24-31
};
//
// Line 5 - Wave Out
//
CONST UCHAR Scale508BMixerL5VolumeD6[] =
{
0 , 0, 0, 0, 0, 0, 0, 0, // 0- 7
0 , 0, 0, 0, 0, 0, 0, 0, // 8-15
0 , 0, 0, 0, 0, 0, 1, 1, // 16-23
1 , 1, 1, 1, 1, 1, 1, 1 // 24-31
};
//
// Line 6 - PC Speaker
//
CONST UCHAR Scale508BMixerL6VolumeD6[] =
{
0 , 0, 0, 0, 0, 0, 0, 0, // 0- 7
0 , 0, 0, 0, 0, 0, 0, 0, // 8-15
0 , 0, 0, 0, 0, 0, 1, 1, // 16-23
1 , 1, 1, 1, 1, 1, 1, 1 // 24-31
};
//
// Line 7 - SoundBlaster
//
CONST UCHAR Scale508BMixerL7VolumeD6[] =
{
0 , 0, 0, 0, 0, 0, 0, 0, // 0- 7
0 , 0, 0, 0, 0, 0, 0, 0, // 8-15
0 , 0, 0, 0, 0, 0, 1, 1, // 16-23
1 , 1, 1, 1, 1, 1, 1, 1 // 24-31
};
//-------------------------========================---------------------------
//-------------------------====< CODE SECTION >====---------------------------
//-------------------------========================---------------------------
/***************************************************************************
;---|*|---------------====< SetFilter() >====---------------
;---|*|
;---|*|
;---|*|
;---|*| Entry Conditions:
;---|*| IN OUT PGLOBAL_DEVICE_INFO pGDI
;---|*| BYTE bIndex
;---|*|
;---|*| Exit Conditions:
;---|*| Nothing
;---|*|
***************************************************************************/
VOID SetFilter( IN OUT PGLOBAL_DEVICE_INFO pGDI,
BYTE bIndex )
{ // Begin SetFilter()
/***** Local Variables *****/
PSOUND_HARDWARE pHw;
BYTE bFilterValue;
BYTE bFilterReg;
BYTE bTempFilterValue;
/***** Start *****/
dprintf3(("SetFilter(): SampleFilterSetting = %XH ", bIndex ));
//
// SampleFilterSetting is the index into the table of values
//
// bIndex = pGDI->PasRegs.SampleFilterSetting;
// Validate
if ( bIndex > FILTERMAX )
{
dprintf1(("ERROR: SetFilter(): Bad value - SampleFilterSetting = %XH ", bIndex ));
return;
}
// Get the value from the table
bFilterValue = FilterTable[bIndex];
// EnterCrit
pHw = pGDI->WaveInfo.HwContext;
HwEnter( pHw ); // KeAcquireSpinLock macro
// Get the current value
bFilterReg = pGDI->PasRegs._audiofilt;
// Save everything but the filter and mute bites
bFilterReg = bFilterReg & (~(fFIdatabits + fFImutebits));
// combine the values
bTempFilterValue = bFilterValue | bFilterReg | bFImute;
// Save the value
pGDI->PasRegs._audiofilt = bTempFilterValue;
// Send it out
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)),
AUDIOFILT,
bTempFilterValue );
KeStallExecutionProcessor(6); // wait 6 us
// LeaveCrit
HwLeave( pHw ); // KeReleaseSpinLock macro
dprintf3((" SetFilter(): 0x0B8A - Filter setting = %XH ", bTempFilterValue ));
} // End SetFilter()
/*****************************************************************************
;---|*|-=< void SetInput (USHORT P_input_num, USHORT P_volume_lvl,USHORT P_channel,
;---|*| USHORT P_crossover,USHORT P_output_num )
;---|*|
;---|*| Set the selected channel within the Input Mixer
;---|*|
;---|*| Entry Conditions:
;---|*| P_input_num = Input # (0-6 for serial mixer, 0-7 for 508)
;---|*| P_volume_lvl = volume level (0-FFFF)
;---|*| P_channel = LEFT, RIGHT or BOTH
;---|*| P_crossover = Crossover Info (required onlby for 508)
;---|*| P_output_num = Output # (0-1 for either mixer)
;---|*|
;---|*| Exit Conditions:
;---|*| None
;---|*|
*****************************************************************************/
void SetInput( IN OUT PGLOBAL_DEVICE_INFO pGDI,
UCHAR P_input_num,
USHORT P_volume_lvl,
USHORT P_channel,
USHORT P_crossover,
UCHAR P_output_num )
{
/***** Local Variables *****/
UCHAR bTemp;
UCHAR bTemp1;
UCHAR bLevel508B;
UCHAR bBitD6508B;
UCHAR bLevelSetting508B;
/***** Start *****/
dprintf4(("SetInput(): Start"));
//
// convert 0-ffff to 0-31 for input level
//
P_volume_lvl >>= (16-5);
//
// Do we have a 508 Mixer?
//
if ( IS_MIXER_508(pGDI) )
{
//
// 508 Mixer
//
bTemp = (UCHAR) P_input_num; // Channel #
bTemp |= (P_channel<<5); // get left/right
bTemp |= MV_508_ADDRESS; // 508 ADDRESS BIT
bTemp |= MV_508_INPUT; // 508 INPUT BIT
dprintf4((" SetInput(): 0x078B - Input Mixer 508 Address : %04XH",
bTemp));
PASX_508_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)),
bTemp );
//
// Do we have a 508-B Mixer?
//
if (IS_MIXER_508B(pGDI))
{
// ***********
// 508-B Mixer
// ***********
//
// Scale the level on a per input channel basis
//
switch ( P_input_num )
{
case IN_SYNTHESIZER:
//
// Line 0
//
// Scale the volume setting - bits 0-4
//
bLevel508B = Scale508BMixerL0Volume[P_volume_lvl];
//
// Get the Gain/Attenuation bit - D6
//
bBitD6508B = Scale508BMixerL0VolumeD6[P_volume_lvl];
break;
case IN_MIXER:
//
// Line 1
//
// Scale the volume setting - bits 0-4
//
bLevel508B = Scale508BMixerL1Volume[P_volume_lvl];
//
// Get the Gain/Attenuation bit - D6
//
bBitD6508B = Scale508BMixerL1VolumeD6[P_volume_lvl];
break;
case IN_EXTERNAL:
//
// Line 2
//
// Scale the volume setting - bits 0-4
//
bLevel508B = Scale508BMixerL2Volume[P_volume_lvl];
//
// Get the Gain/Attenuation bit - D6
//
bBitD6508B = Scale508BMixerL2VolumeD6[P_volume_lvl];
break;
case IN_INTERNAL:
//
// Line 3
//
// Scale the volume setting - bits 0-4
//
bLevel508B = Scale508BMixerL3Volume[P_volume_lvl];
//
// Get the Gain/Attenuation bit - D6
//
bBitD6508B = Scale508BMixerL3VolumeD6[P_volume_lvl];
break;
case IN_MICROPHONE:
//
// Line 4
//
// Scale the volume setting - bits 0-4
//
bLevel508B = Scale508BMixerL4Volume[P_volume_lvl];
//
// Get the Gain/Attenuation bit - D6
//
bBitD6508B = Scale508BMixerL4VolumeD6[P_volume_lvl];
break;
case IN_PCM:
//
// Line 5
//
// Scale the volume setting - bits 0-4
//
bLevel508B = Scale508BMixerL5Volume[P_volume_lvl];
//
// Get the Gain/Attenuation bit - D6
//
bBitD6508B = Scale508BMixerL5VolumeD6[P_volume_lvl];
break;
case IN_PC_SPEAKER:
//
// Line 6
//
// Scale the volume setting - bits 0-4
//
bLevel508B = Scale508BMixerL6Volume[P_volume_lvl];
//
// Get the Gain/Attenuation bit - D6
//
bBitD6508B = Scale508BMixerL6VolumeD6[P_volume_lvl];
break;
case IN_SNDBLASTER:
//
// Line 7
//
// Scale the volume setting - bits 0-4
//
bLevel508B = Scale508BMixerL7Volume[P_volume_lvl];
//
// Get the Gain/Attenuation bit - D6
//
bBitD6508B = Scale508BMixerL7VolumeD6[P_volume_lvl];
break;
} // End SWITCH (P_input_num)
//
// Move it into bit D6
//
bBitD6508B = bBitD6508B << 6;
//
// Get the total level
//
bLevelSetting508B = bLevel508B | bBitD6508B;
bLevelSetting508B|=((P_output_num & 1 )<<5); // select output number
dprintf4((" SetInput(): 0x078B - Input Mixer 508-B Data : %04XH",
bLevelSetting508B));
PASX_508_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)),
bLevelSetting508B );
} // End IF (508-B Mixer)
else
{
// *********
// 508 Mixer
// *********
//
// Scale the volume setting
//
P_volume_lvl = ScaleMixerVolume[P_volume_lvl];
bTemp = (UCHAR) P_volume_lvl; // get volume level reduced to (0-31 range)
bTemp1 = (UCHAR) P_crossover; // get CROSSOVER
if ( bTemp1==MIXCROSSCAPS_NORMAL_STEREO )
{
}
else
if (bTemp1 & MIXCROSSCAPS_REVERSE_STEREO)
{
bTemp |= MV_508_SWAP; // this channel's swapped
}
else
{
if (P_channel==_LEFT)
{
if (bTemp1 & MIXCROSSCAPS_LEFT_TO_RIGHT)
bTemp |= MV_508_SWAP; // this channel's swapped
}
else
{
if (bTemp1 & MIXCROSSCAPS_LEFT_TO_RIGHT)
bTemp |= MV_508_SWAP; // this channel's swapped
}
} // End ELSE
bTemp|=((P_output_num & 1 )<<5); // select output number
dprintf4((" SetInput(): 0x078B - Input Mixer 508 Data : %04XH", bTemp));
PASX_508_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)),
bTemp );
} // End ELSE (!508-B Mixer)
} // End ELSE (508 Mixer)
else
{
//
// National (serially programmed) mixer
//
dprintf2((" SetInput(): ----------- Using Serial Mixer!"));
//
// send out the mixer channel #
//
bTemp=P_input_num; // Channel #
bTemp++; // channel 0 was XXX
if (P_channel==_RIGHT)
bTemp+=7; // this magic number is the offset to right channel
bTemp|=NATIONAL_COMMAND;
NationalMix(pGDI, bTemp);
// select the correct mixer
bTemp1=P_output_num<<6; // get output number
//
// send out the mixer data
//
bTemp = (UCHAR) (P_volume_lvl & 0x1F); // limit to 31
bTemp = Scale32To12[bTemp];
bTemp = mixersettings[bTemp];
NationalMix(pGDI, bTemp);
}
}
/*****************************************************************************
;---|*|--------====< void SetOutput (line, level, channel ) >====--------
;---|*|
;---|*| This routine outputs a new setting for a volume channel.
;---|*|
;---|*| Entry Conditions:
;---|*| WParm1 is a value from 0 - 1
;---|*| WParm2 is a value to be written to the control (0-63)
;---|*| WParm3 signifies left or right
;---|*|
;---|*| Exit Conditions:
;---|*| None
;---|*|
*****************************************************************************/
void SetOutput( IN OUT PGLOBAL_DEVICE_INFO pGDI,
UCHAR P_output_num,
USHORT P_volume_lvl,
USHORT P_channel )
{
/***** Local Variables *****/
PSOUND_HARDWARE pHw;
UCHAR bTemp;
/***** Start *****/
dprintf2(("SetOutput(): Start "));
P_volume_lvl>>=(16-6); // convert 0-ffff to 0-63
if ( IS_MIXER_508(pGDI) )
{
// EnterCrit
pHw = pGDI->WaveInfo.HwContext;
HwEnter( pHw ); // KeAcquireSpinLock macro
bTemp=(UCHAR) P_output_num;
bTemp++; // Output number need to be 1 based
bTemp|=(P_channel<<5); // get left/right
bTemp|=MV_508_ADDRESS;
PASX_508_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)),
bTemp );
dprintf4((" SetOutput(): 0x078B - Output Mixer 508 Address : %04XH", bTemp));
if (pGDI->MixerState.Mute)
{
bTemp=0;
}
else
{
bTemp = (UCHAR) P_volume_lvl; // get volume level (0-63 range)
if (P_output_num!=OUT_AMPLIFIER)
bTemp>>=2; // output B of MV508 has 0-15 range
}
PASX_508_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)),
bTemp );
dprintf4((" SetOutput(): 0x078B - Mixer 508 Data : %04XH", bTemp));
// LeaveCrit
HwLeave( pHw ); // KeReleaseSpinLock macro
} // End IF (pGDI->PASInfo.Caps.CapsBits.Mixer_508)
else // NATIONAL (SERIAL PROGRAMMED) MIXER
{
dprintf2((" SetOutput(): ----------Using Serial Mixer!"));
if (P_output_num==0) // serial device has volume on output 0 only
{
if (pGDI->MixerState.Mute)
{
bTemp=0;
}
else
{
bTemp=Scale64To40[P_volume_lvl];
}
// see Pas-1 spec p.15 (LEFT VOLUME CONTROL)
NationalVolume( pGDI,
(USHORT) bTemp,
(UCHAR)((P_channel&1) + NATIONAL_LEFT_VOL_REG) );
}
}
}
/*****************************************************************************
;---|*|--------====< void SetEQ (line, EQ, level ) >====--------
;---|*|
;---|*| This routine outputs a new setting for a volume channel.
;---|*|
;---|*| Entry Conditions:
;---|*| WParm1 is line number (range 0 - 1; 1 is don't care)
;---|*| WParm2 is EQ type (ie. Loudness, Stereo Enhance, BMT)
;---|*| WParm3 is level (range 0-31)
;---|*|
;---|*| Exit Conditions:
;---|*| None
;---|*|
*****************************************************************************/
void SetEQ( IN OUT PGLOBAL_DEVICE_INFO pGDI,
USHORT P_output,
USHORT P_EQtype,
USHORT P_level )
{
/***** Local Variables *****/
UCHAR bTemp;
/***** Start *****/
dprintf2(("SetEq(): Start "));
if (P_output!=0)
return;
if ( IS_MIXER_508(pGDI) )
{
switch (P_EQtype)
{
case _BASS:
PASX_508_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)),
MV_508_ADDRESS + MV_508_BASS);
PASX_508_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)),
BassTreb32to13[P_level]);
break;
case _TREBLE:
PASX_508_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)),
MV_508_ADDRESS + MV_508_TREBLE);
PASX_508_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)),
BassTreb32to13[P_level]);
break;
} // End SWITCH (P_EQtype)
} // End IF (pGDI->PASInfo.Caps.CapsBits.Mixer_508)
else // NATIONAL (SERIAL PROGRAMMED) MIXER
{
bTemp=Scale32To12[P_level];
// see Pas-1 spec p.15 (LEFT VOLUME CONTROL)
NationalVolume( pGDI,
(USHORT)bTemp,
(UCHAR)((P_EQtype&1) + NATIONAL_BASS_REG) );
}
}
/*****************************************************************************
;---|*|--------====< void SetEqMode (Loudness, Enhance ) >====--------
;---|*|
;---|*| This routine sets loundess and stereo enhance modes
;---|*|
;---|*| Entry Conditions:
;---|*| loudness (Z vs NZ)
;---|*| Stereo Enhance (range 0-3)
;---|*|
;---|*| Exit Conditions:
;---|*| None
;---|*|
*****************************************************************************/
void SetEqMode( IN OUT PGLOBAL_DEVICE_INFO pGDI,
USHORT P_loudness,
USHORT P_enhance )
{
/***** Local Variables *****/
UCHAR bTemp=0;
/***** Start *****/
dprintf2(("SetEqMode(): Start "));
if ( IS_MIXER_508(pGDI) )
{
PASX_508_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)),
MV_508_ADDRESS + MV_508_EQMODE );
if (P_loudness)
bTemp+=MV_508_LOUDNESS;
bTemp+=P_enhance & MV_508_ENHANCE;
PASX_508_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)),
bTemp);
} // End IF (pGDI->PASInfo.Caps.CapsBits.Mixer_508)
else
{
if (P_loudness)
bTemp=NATIONAL_LOUDNESS; // Loudness bit
if (P_enhance)
bTemp|=NATIONAL_ENHANCE; // stereo enhance bit
// see Pas-1 spec p.15 (LEFT VOLUME CONTROL)
NationalVolume( pGDI,
bTemp,
NATIONAL_LOUD_ENH_REG);
}
}
/*****************************************************************************
-----------------------====< NationalMix >====--------------------------
; /*\ |
;---|*| NationalMix -- Load The National Mixer |
;---|*| |
;---|*| Entry Conditions |
;---|*| wData = index/data |
;---|*| |
*****************************************************************************/
void NationalMix( IN OUT PGLOBAL_DEVICE_INFO pGDI,
USHORT wData)
{
USHORT i,bTemp=0;
dprintf2(("NationalMix(): Start "));
// EnterCrit
// get current hardware state
bTemp = pGDI->PasRegs._audiomixr;
// bTemp &= SERIAL_MIX_REALSOUND+SERIAL_MIX_DUALFM; // save state of only these bits
bTemp|=~(SERIAL_MIX_REALSOUND+SERIAL_MIX_DUALFM); // turn on all other bits
// all clocks and strobes should be 1
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)), SERIAL_MIXER,bTemp);
KeStallExecutionProcessor(5); // wait 5 us
for (i=0; i<8; i++) {
// output clock is 0
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)), SERIAL_MIXER,bTemp & (~SERIAL_MIX_CLOCK));
KeStallExecutionProcessor(5); // wait 5 us
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)), SERIAL_MIXER,(wData>>i)& 1); //send data, clock is 0
KeStallExecutionProcessor(5); // wait 5 us
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)), SERIAL_MIXER,
((wData>>i)& 1)^SERIAL_MIX_CLOCK); //send data, clock is 1
KeStallExecutionProcessor(5); // wait 5 us
}
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)), SERIAL_MIXER,
((wData>>i)& 1)|SERIAL_MIX_CLOCK|SERIAL_MIX_STROBE); //strobe it in
KeStallExecutionProcessor(5); // wait 5 us
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)), SERIAL_MIXER,bTemp);
pGDI->PasRegs._audiomixr = (BYTE) bTemp; // save the last state
KeStallExecutionProcessor(5); // wait 5 us
}
/*****************************************************************************
-------------------------====< NationalVolume >====---------------------------
; /*\;
;---|*|; NationalVolume -- Load Volume control Register
;---|*|;
;---|*|; Entry Conditions:
;---|*|; bl = parameter register (volume control channel 0-7)
;---|*|; ah = data to transfer (new channel setting)
*****************************************************************************/
void NationalVolume( IN OUT PGLOBAL_DEVICE_INFO pGDI,
USHORT wVolume,
UCHAR wLeftRight )
{
//
// pass everything, but left/right volume directly to the device
//
// left & right volume are presented
// to the logical level as 0 - 40,
// where 0 is the lowest, and 40 is
// the highest. In reality, this
// is backwards, that is, 40 is the
// lowest, and 0 is the highest. We will
// correct the value here...
USHORT bTemp,i;
short sVolume=wVolume;
dprintf2(("NationalVolume(): Start "));
// Perform the volume control output
if (( wLeftRight==NATIONAL_LEFT_VOL_REG) ||
(wLeftRight==NATIONAL_RIGHT_VOL_REG ))
{
sVolume -=0x40; // is backwards, that is, 40 is the
sVolume = -sVolume; // lowest, and 0 is the highest. We will
// correct the value here...
}
//
// all 1s but volume enable and clock
//
bTemp=pGDI->PasRegs._audiomixr; // save the realsound & dual fm bits
bTemp &= SERIAL_MIX_REALSOUND+SERIAL_MIX_DUALFM;
bTemp |= ~ (SERIAL_MIX_REALSOUND+SERIAL_MIX_DUALFM+SERIAL_MIX_MASTER+SERIAL_MIX_CLOCK);
// EnterCrit
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)), SERIAL_MIXER,bTemp); // note: clock is off
for (i=0; i<8; i++) {
bTemp=(wLeftRight>>i)& 1;
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)), SERIAL_MIXER,(bTemp | SERIAL_MIX_CLOCK)); // clock's on
KeStallExecutionProcessor(5); // wait 5 us
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)), SERIAL_MIXER,(bTemp)); // clock's off
KeStallExecutionProcessor(5); // wait 5 us
}
// write with volume control enable
// which starts data loading
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)), SERIAL_MIXER,bTemp|SERIAL_MIX_MASTER);
KeStallExecutionProcessor(6); // wait 6 us
for (i=0; i<8; i++) {
bTemp=bTemp & (~D0); // mask off D0
bTemp |= ((sVolume>>i) & D0); // move current bit into D0
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)), SERIAL_MIXER,bTemp+SERIAL_MIX_CLOCK);
KeStallExecutionProcessor(6); // wait 6 us
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)), SERIAL_MIXER,bTemp);
KeStallExecutionProcessor(6); // wait 5 us
}
for (i=0; i<12; i++) {
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)), SERIAL_MIXER,bTemp);
KeStallExecutionProcessor(6); // wait 6 us
}
// toggle volume control enable
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)), SERIAL_MIXER,bTemp|SERIAL_MIX_MASTER);
KeStallExecutionProcessor(6); // wait 6 us
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)), SERIAL_MIXER,bTemp|SERIAL_MIX_MASTER);
KeStallExecutionProcessor(6); // wait 6 us
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)), SERIAL_MIXER,bTemp|SERIAL_MIX_MASTER);
KeStallExecutionProcessor(6); // wait 6 us
PASX_OUT( ((FOUNDINFO *)(&pGDI->PASInfo)), SERIAL_MIXER,bTemp);
KeStallExecutionProcessor(6); // wait 6 us
pGDI->PasRegs._audiomixr = (BYTE) bTemp; // save the last state
}
#if 0
ULONG
Scale100ToFFFF(WORD wVal)
{
ULONG dwScaled;
dwScaled=((ULONG)wVal) * (0xFFFFL/100L);
dwScaled=(dwScaled & 0xff00L)+ (dwScaled >>8);
return(dwScaled);
}
UCHAR
ScaleFFFFTo100(WORD wVal)
{
UCHAR bScaled;
bScaled=((wVal>>8)*100)/255;
return(bScaled);
}
#endif
/************************************ END ***********************************/