1128 lines
32 KiB
C
1128 lines
32 KiB
C
/******************************************************************************
|
||
|
||
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 ***********************************/
|
||
|