2020-09-30 17:12:29 +02:00

502 lines
9.9 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) 1991 Microsoft Corporation
Module Name:
snd.c
Abstract:
This module contains code for communicating with the MIPSSND
(the MIPS sound card)
Author:
Nigel Thompson (NigelT) 7-March-1991
Environment:
Kernel mode
Revision History:
Robin Speed (RobinSp) 29-Jan-1992
- Add MIDI, support for soundblaster 1,
Sameer Dekate (sameer@mips.com) 19-Aug-1992
- Changes to support the MIPS sound board.
--*/
#include "sound.h"
#ifdef MIPSSND_TAIL_BUG
BOOLEAN
sndMute(
IN PVOID Context
)
/*++
Routine Description:
Turn off the volume. This is the work around for the MIPSSND
Tail Bug.
Arguments:
Context - Our device global data
Return Value:
TRUE if succeeds, FALSE otherwise
--*/
{
PGLOBAL_DEVICE_INFO pGDI;
PSOUND_REGISTERS pSoundRegisters;
UCHAR RightOutRegisterValue, LeftOutRegisterValue;
//
// MIPSSND - BUG WORKAROUND; The click at the end is too audible
// should just turn down volume since we are doing last
// blank block anyway.
//
// Later on when we want to play again we use the pGDI->WaveOutVol
// structure to turn up the volume in sndSetOutputVolume().
pGDI = (PGLOBAL_DEVICE_INFO)Context;
//
// Get the base address of audio registers
//
pSoundRegisters = pGDI->SoundHardware.SoundVirtualBase;
//
// Set to FULL attenuation
//
RightOutRegisterValue = READAUDIO_ROCNTRL(&pSoundRegisters);
RightOutRegisterValue |= RIGHT_OUTPUT_ATTN_MASK;
WRITEAUDIO_ROCNTRL(&pSoundRegisters, RightOutRegisterValue);
LeftOutRegisterValue = READAUDIO_LOCNTRL(&pSoundRegisters);
LeftOutRegisterValue |= LEFT_OUTPUT_ATTN_MASK;
WRITEAUDIO_LOCNTRL(&pSoundRegisters, LeftOutRegisterValue);
return TRUE;
}
#endif // MIPSSND_TAIL_BUG
BOOLEAN
sndSetOutputVolume(
IN PVOID Context
)
/*++
Routine Description:
Set the volume for wave output (MIPS sound board)
Arguments:
Context - Our device global data
Return Value:
TRUE if succeeds, FALSE otherwise
--*/
{
PGLOBAL_DEVICE_INFO pGDI;
PSOUND_REGISTERS pSoundRegisters;
UCHAR RightOutRegisterValue, LeftOutRegisterValue;
UCHAR RightVolume, LeftVolume;
UCHAR RightAttn, LeftAttn;
pGDI = (PGLOBAL_DEVICE_INFO)Context;
//
// Get the base address of audio registers
//
pSoundRegisters = pGDI->SoundHardware.SoundVirtualBase;
//
// Look at only the 6 Most Significant Bits.
//
LeftVolume = (UCHAR) (pGDI->WaveOutVol.Left >> 26);
RightVolume = (UCHAR) (pGDI->WaveOutVol.Right >> 26);
// If we are in MONO mode and since the CODEC is always in 16bit
// Stereo then the right volume should set to be the same as left
// Volume. The board hardware will take care of the rest.
if (pGDI->Channels == 1)
RightVolume = LeftVolume;
dprintf3("BDOutVol:Rt=0x%x Lt=0x%x",
pGDI->WaveOutVol.Right, pGDI->WaveOutVol.Left );
//
// Since the Board requires Attenuation, Convert volume to
// attenuation by taking a NOT of the 6 bits
//
RightAttn = (~RightVolume) & RIGHT_OUTPUT_ATTN_MASK;
LeftAttn = (~LeftVolume ) & LEFT_OUTPUT_ATTN_MASK;
//
// Right Output Data Register
// Set the attenuation to that provided by the user
//
RightOutRegisterValue = READAUDIO_ROCNTRL(&pSoundRegisters);
RightOutRegisterValue &= ~RIGHT_OUTPUT_ATTN_MASK;
RightOutRegisterValue |= (RightAttn & RIGHT_OUTPUT_ATTN_MASK);
WRITEAUDIO_ROCNTRL(&pSoundRegisters, RightOutRegisterValue);
//
// Left Output Data Register
// Set the attenuation to that provided by the user
//
LeftOutRegisterValue = READAUDIO_LOCNTRL(&pSoundRegisters);
LeftOutRegisterValue &= ~LEFT_OUTPUT_ATTN_MASK;
LeftOutRegisterValue |= (LeftAttn & LEFT_OUTPUT_ATTN_MASK);
WRITEAUDIO_LOCNTRL(&pSoundRegisters, LeftOutRegisterValue);
//
// Don't have to force any shifting into CODEC. Happens automatically
// along with wave data given to the CODEC.
//
return TRUE;
}
BOOLEAN
sndSetInputVolume(
IN PGLOBAL_DEVICE_INFO pGDI
)
/*++
Routine Description:
Set the volume for Inputs (MIPS sound board)
1) CDROM
2) LINEIN
3) MICR IN
Arguments:
Context - Our device Local data
Return Value:
TRUE if succeeds, FALSE otherwise
--*/
{
PSOUND_REGISTERS pSoundRegisters;
UCHAR RightInRegisterValue, LeftInRegisterValue;
UCHAR RightVolume, LeftVolume;
BOOLEAN MicSource = FALSE;
//
// Get the base address of audio registers
//
pSoundRegisters = pGDI->SoundHardware.SoundVirtualBase;
//
// Look at only the 4 Most Significant Bits.
//
if (pGDI->InputSource == SoundCdRomIn)
sndInputDeviceSelect( pGDI, CDROM_SELECT );
//
// If Microphone is selected and we're not recording then
// set line in as the input. Note that start record and end
// record call us to toggle the status.
//
else if (pGDI->InputSource == SoundLineIn ||
pGDI->Usage != SoundInterruptUsageWaveIn)
sndInputDeviceSelect( pGDI, LINEIN_SELECT );
else {
MicSource = TRUE;
sndInputDeviceSelect( pGDI, MICROPHONE_SELECT );
}
// Turn OFF the Monitor if the volume requested was 0
// Or we're doing the microphone (which is prone to feedback
if ((pGDI->AuxVol.Left == 0) && (pGDI->AuxVol.Right == 0) ||
MicSource)
sndMonitorControl( pGDI, OFF );
else
sndMonitorControl( pGDI, ON );
// Get the remembered volume
LeftVolume = (UCHAR) (pGDI->AuxVol.Left >> 28);
RightVolume = (UCHAR) (pGDI->AuxVol.Right >> 28);
dprintf3("BDInVol:Rt=0x%x Lt=0x%x", RightVolume, LeftVolume);
#ifdef MIPSSND_TAIL_BUG
// Playing of a wave file might have turned off
// the Output Volume. Turn it on.
sndSetOutputVolume( pGDI );
#endif //MIPSSND_TAIL_BUG
//
// Right Input Data Register
// Set the gain to that provided by the user
//
RightInRegisterValue = READAUDIO_RICNTRL(&pSoundRegisters);
RightInRegisterValue &= ~RIGHT_INPUT_GAIN_MASK;
RightInRegisterValue |= (RightVolume & RIGHT_INPUT_GAIN_MASK);
WRITEAUDIO_RICNTRL(&pSoundRegisters, RightInRegisterValue);
//
// Left Input Data Register
// Set the gain to that provided by the user
//
LeftInRegisterValue = READAUDIO_LICNTRL(&pSoundRegisters);
LeftInRegisterValue &= ~LEFT_INPUT_GAIN_MASK;
LeftInRegisterValue |= (LeftVolume & LEFT_INPUT_GAIN_MASK);
WRITEAUDIO_LICNTRL(&pSoundRegisters, LeftInRegisterValue);
//
// Don't have to force any shifting into CODEC. Happens automatically
// along with wave data given to the CODEC.
//
return TRUE;
}
BOOLEAN
sndHeadphoneControl(
IN PVOID Context,
IN ULONG WhatToDo
)
/*++
Routine Description:
Turn the Headphone On or Off.
Arguments:
Context - Supplies pointer to global devices info
WhatToDo- to turn ON or OFF
Return Value:
TRUE if succeeds, FALSE otherwise
--*/
{
PGLOBAL_DEVICE_INFO pGDI;
UCHAR regval;
PSOUND_REGISTERS pSoundRegisters;
pGDI = (PGLOBAL_DEVICE_INFO)Context;
pSoundRegisters = pGDI->SoundHardware.SoundVirtualBase;
regval = READAUDIO_LOCNTRL(&pSoundRegisters);
if (WhatToDo == ON){
regval |= HEADPHONE_ENABLE;
} else {
regval &= ~HEADPHONE_ENABLE;
}
WRITEAUDIO_LOCNTRL(&pSoundRegisters, regval);
return TRUE;
}
BOOLEAN
sndMonitorControl(
IN PVOID Context,
IN ULONG WhatToDo
)
/*++
Routine Description:
Turn the Monitor Attenuation On or Off.
Arguments:
Context - Supplies pointer to global devices info
WhatToDo- ON - saying allow things to pass through
OFF- Full attenuation/ nothing to pass through
Return Value:
TRUE if succeeds, FALSE otherwise
--*/
{
PGLOBAL_DEVICE_INFO pGDI;
UCHAR regval;
PSOUND_REGISTERS pSoundRegisters;
pGDI = (PGLOBAL_DEVICE_INFO)Context;
pSoundRegisters = pGDI->SoundHardware.SoundVirtualBase;
regval = READAUDIO_RICNTRL(&pSoundRegisters);
regval &= ~MON_ATTN_MASK;
if (WhatToDo == OFF){
regval |= MON_ATTN_MASK;
}
WRITEAUDIO_RICNTRL(&pSoundRegisters, regval);
return TRUE;
}
BOOLEAN
sndLineoutControl(
IN PVOID Context,
IN ULONG WhatToDo
)
/*++
Routine Description:
Turn the Lineout On or Off.
Arguments:
Context - Supplies pointer to globla devices info
WhatToDo- to turn ON or OFF
Return Value:
TRUE if succeeds, FALSE otherwise
--*/
{
PGLOBAL_DEVICE_INFO pGDI;
UCHAR regval;
PSOUND_REGISTERS pSoundRegisters;
pGDI = (PGLOBAL_DEVICE_INFO)Context;
pSoundRegisters = pGDI->SoundHardware.SoundVirtualBase;
regval = READAUDIO_LOCNTRL(&pSoundRegisters);
if (WhatToDo == ON){
regval |= LINEOUT_ENABLE;
} else {
regval &= ~LINEOUT_ENABLE;
}
WRITEAUDIO_LOCNTRL(&pSoundRegisters, regval);
return TRUE;
}
BOOLEAN
sndInputDeviceSelect(
IN PVOID Context,
IN ULONG Device
)
/*++
Routine Description:
Select between CDROM or Linein or Microphone input
Can select only ONE of the three possible inputs
Arguments:
Context - Supplies pointer to globla devices info
Device - CDROM_SELECT or LINEIN_SELECT or MICROPHONE_SELECT
Return Value:
TRUE if succeeds, FALSE otherwise
--*/
{
PGLOBAL_DEVICE_INFO pGDI;
UCHAR regval;
PSOUND_REGISTERS pSoundRegisters;
pGDI = (PGLOBAL_DEVICE_INFO)Context;
pSoundRegisters = pGDI->SoundHardware.SoundVirtualBase;
regval = READAUDIO_LICNTRL(&pSoundRegisters);
regval &= ~(PARALLELIO_MASK | MIC_LEVEL_INPUT);
if (Device == MICROPHONE_SELECT) {
regval |= MICROPHONE_ENABLE;
} else {
// Basically select Linein-level and PIO bits
if (Device == LINEIN_SELECT) {
regval |= LINEIN_ENABLE;
} else {
regval |= CDROM_ENABLE;
}
}
WRITEAUDIO_LICNTRL(&pSoundRegisters, regval);
return TRUE;
}