reactos/sdk/lib/drivers/sound/soundblaster/mixer.c

244 lines
5.8 KiB
C

/*
ReactOS Sound System
Sound Blaster DSP support
Mixer routines
Author:
Andrew Greenwood (silverblade@reactos.org)
History:
2 July 2008 - Created
Notes:
Functions documented in sbdsp.h
Currently, input/output switches and PC speaker volume
level are not supported.
The I/O switches are used for muting/unmuting mic, etc.
*/
#include "precomp.h"
VOID
SbMixerReset(IN PUCHAR BasePort)
{
WRITE_SB_MIXER_REGISTER(BasePort, SB_MIX_RESET);
/* Are we meant to send anything else? */
}
NTSTATUS
SbMixerPackLevelData(
IN UCHAR Line,
IN UCHAR Level,
OUT PUCHAR PackedLevel)
{
if ( ! PackedLevel )
return STATUS_INVALID_PARAMETER_3;
switch ( Line )
{
case SB_MIX_MASTER_LEFT_LEVEL :
case SB_MIX_MASTER_RIGHT_LEVEL :
case SB_MIX_VOC_LEFT_LEVEL :
case SB_MIX_VOC_RIGHT_LEVEL :
case SB_MIX_MIDI_LEFT_LEVEL :
case SB_MIX_MIDI_RIGHT_LEVEL :
case SB_MIX_CD_LEFT_LEVEL :
case SB_MIX_CD_RIGHT_LEVEL :
case SB_MIX_LINE_LEFT_LEVEL :
case SB_MIX_LINE_RIGHT_LEVEL :
case SB_MIX_MIC_LEVEL :
case SB_MIX_LEGACY_MIC_LEVEL : /* is this correct? */
{
if ( Level >= 0x20 )
return STATUS_INVALID_PARAMETER_2;
*PackedLevel = Level << 3;
return STATUS_SUCCESS;
}
case SB_MIX_INPUT_LEFT_GAIN :
case SB_MIX_INPUT_RIGHT_GAIN :
case SB_MIX_OUTPUT_LEFT_GAIN :
case SB_MIX_OUTPUT_RIGHT_GAIN :
{
if ( Level >= 0x04 )
return STATUS_INVALID_PARAMETER_2;
*PackedLevel = Level << 6;
return STATUS_SUCCESS;
}
case SB_MIX_VOC_LEVEL : /* legacy */
case SB_MIX_MASTER_LEVEL :
case SB_MIX_FM_LEVEL :
case SB_MIX_CD_LEVEL :
case SB_MIX_LINE_LEVEL :
case SB_MIX_TREBLE_LEFT_LEVEL : /* bass/treble */
case SB_MIX_TREBLE_RIGHT_LEVEL :
case SB_MIX_BASS_LEFT_LEVEL :
case SB_MIX_BASS_RIGHT_LEVEL :
{
if ( Level >= 0x10 )
return STATUS_INVALID_PARAMETER_2;
*PackedLevel = Level << 4;
return STATUS_SUCCESS;
}
default :
return STATUS_INVALID_PARAMETER_1;
};
}
NTSTATUS
SbMixerUnpackLevelData(
IN UCHAR Line,
IN UCHAR PackedLevel,
OUT PUCHAR Level)
{
if ( ! Level )
return STATUS_INVALID_PARAMETER_3;
switch ( Line )
{
case SB_MIX_MASTER_LEFT_LEVEL :
case SB_MIX_MASTER_RIGHT_LEVEL :
case SB_MIX_VOC_LEFT_LEVEL :
case SB_MIX_VOC_RIGHT_LEVEL :
case SB_MIX_MIDI_LEFT_LEVEL :
case SB_MIX_MIDI_RIGHT_LEVEL :
case SB_MIX_CD_LEFT_LEVEL :
case SB_MIX_CD_RIGHT_LEVEL :
case SB_MIX_LINE_LEFT_LEVEL :
case SB_MIX_LINE_RIGHT_LEVEL :
case SB_MIX_MIC_LEVEL :
{
*Level = PackedLevel >> 3;
return STATUS_SUCCESS;
}
case SB_MIX_INPUT_LEFT_GAIN :
case SB_MIX_INPUT_RIGHT_GAIN :
case SB_MIX_OUTPUT_LEFT_GAIN :
case SB_MIX_OUTPUT_RIGHT_GAIN :
{
*Level = PackedLevel >> 6;
return STATUS_SUCCESS;
}
case SB_MIX_VOC_LEVEL : /* legacy */
case SB_MIX_MASTER_LEVEL :
case SB_MIX_FM_LEVEL :
case SB_MIX_CD_LEVEL :
case SB_MIX_LINE_LEVEL :
case SB_MIX_TREBLE_LEFT_LEVEL : /* bass/treble */
case SB_MIX_TREBLE_RIGHT_LEVEL :
case SB_MIX_BASS_LEFT_LEVEL :
case SB_MIX_BASS_RIGHT_LEVEL :
{
*Level = PackedLevel >> 4;
return STATUS_SUCCESS;
}
default :
return STATUS_INVALID_PARAMETER_1;
};
}
NTSTATUS
SbMixerSetLevel(
IN PUCHAR BasePort,
IN UCHAR Line,
IN UCHAR Level)
{
UCHAR PackedLevel = 0;
NTSTATUS Status;
Status = SbMixerPackLevelData(Line, Level, &PackedLevel);
switch ( Status )
{
case STATUS_SUCCESS :
break;
case STATUS_INVALID_PARAMETER_1 :
return STATUS_INVALID_PARAMETER_2;
case STATUS_INVALID_PARAMETER_2 :
return STATUS_INVALID_PARAMETER_3;
default :
return Status;
};
DbgPrint("SbMixerSetLevel: Line 0x%x, raw level 0x%x, packed 0x%x\n", Line, Level, PackedLevel);
WRITE_SB_MIXER_REGISTER(BasePort, Line);
WRITE_SB_MIXER_DATA(BasePort, PackedLevel);
return STATUS_SUCCESS;
}
NTSTATUS
SbMixerGetLevel(
IN PUCHAR BasePort,
IN UCHAR Line,
OUT PUCHAR Level)
{
UCHAR PackedLevel = 0;
NTSTATUS Status;
if ( ! Level )
return STATUS_INVALID_PARAMETER_3;
WRITE_SB_MIXER_REGISTER(BasePort, Line);
PackedLevel = READ_SB_MIXER_DATA(BasePort);
Status = SbMixerUnpackLevelData(Line, PackedLevel, Level);
switch ( Status )
{
case STATUS_SUCCESS :
break;
case STATUS_INVALID_PARAMETER_1 :
return STATUS_INVALID_PARAMETER_2;
case STATUS_INVALID_PARAMETER_2 :
return STATUS_INVALID_PARAMETER_3;
default :
return Status;
};
DbgPrint("SbMixerGetLevel: Line 0x%x, raw level 0x%x, packed 0x%x\n", Line, Level, PackedLevel);
return STATUS_SUCCESS;
}
VOID
SbMixerEnableAGC(IN PUCHAR BasePort)
{
/* Untested... */
WRITE_SB_MIXER_REGISTER(BasePort, SB_MIX_AGC);
WRITE_SB_MIXER_DATA(BasePort, 1);
}
VOID
SbMixerDisableAGC(IN PUCHAR BasePort)
{
/* Untested... */
WRITE_SB_MIXER_REGISTER(BasePort, SB_MIX_AGC);
WRITE_SB_MIXER_DATA(BasePort, 0);
}
BOOLEAN
SbMixerIsAGCEnabled(IN PUCHAR BasePort)
{
/* Untested... */
WRITE_SB_MIXER_REGISTER(BasePort, SB_MIX_AGC);
return (READ_SB_MIXER_DATA(BasePort) != 0);
}