Author: silverblade Date: Wed Jul 2 05:23:18 2008 New Revision: 34257
URL: http://svn.reactos.org/svn/reactos?rev=34257&view=rev Log: Implemented Sound Blaster mixer register read/write. Tested ability to set and get the master volume level, under VirtualBox. Appears to function correctly. Temporary test code added to sb16_nt4.
Modified: branches/silverblade-audio/drivers/multimedia/audio/sb16_nt4/main.c branches/silverblade-audio/include/reactos/libs/sound/sbdsp.h branches/silverblade-audio/lib/drivers/sound/soundblaster/mixer.c
Modified: branches/silverblade-audio/drivers/multimedia/audio/sb16_nt4/main.c URL: http://svn.reactos.org/svn/reactos/branches/silverblade-audio/drivers/multim... ============================================================================== --- branches/silverblade-audio/drivers/multimedia/audio/sb16_nt4/main.c [iso-8859-1] (original) +++ branches/silverblade-audio/drivers/multimedia/audio/sb16_nt4/main.c [iso-8859-1] Wed Jul 2 05:23:18 2008 @@ -164,6 +164,7 @@ NTSTATUS result; BOOLEAN speaker_state = TRUE; UCHAR major = 0x69, minor = 0x96; + UCHAR level = 0;
/*CreateSoundDeviceWithDefaultName(DriverObject, 0, 69, 0, &device);*/
@@ -213,6 +214,20 @@ result == STATUS_SUCCESS ? "succeeded" : "failed"); DbgPrint("Speaker state is now %s\n", speaker_state ? "ENABLED" : "DISABLED"); + + DbgPrint("Resetting SB Mixer\n"); + SbMixerReset((PUCHAR)0x220); + + DbgPrint("Setting master level to 0F\n"); + result = SbMixerSetLevel((PUCHAR)0x220, SB_MIX_MASTER_LEVEL, 0x0f); + DbgPrint("Request %s\n", + result == STATUS_SUCCESS ? "succeeded" : "failed"); + + DbgPrint("Getting master level\n"); + result = SbMixerGetLevel((PUCHAR)0x220, SB_MIX_MASTER_LEVEL, &level); + DbgPrint("Request %s\n", + result == STATUS_SUCCESS ? "succeeded" : "failed"); + DbgPrint("Level is 0x%x\n", level);
return STATUS_SUCCESS; }
Modified: branches/silverblade-audio/include/reactos/libs/sound/sbdsp.h URL: http://svn.reactos.org/svn/reactos/branches/silverblade-audio/include/reacto... ============================================================================== --- branches/silverblade-audio/include/reactos/libs/sound/sbdsp.h [iso-8859-1] (original) +++ branches/silverblade-audio/include/reactos/libs/sound/sbdsp.h [iso-8859-1] Wed Jul 2 05:23:18 2008 @@ -90,6 +90,7 @@ /* Mixer lines */ +#define SB_MIX_RESET 0x00 #define SB_MIX_MASTER_LEFT_LEVEL 0x30 #define SB_MIX_MASTER_RIGHT_LEVEL 0x31 #define SB_MIX_VOC_LEFT_LEVEL 0x32 @@ -103,8 +104,8 @@ #define SB_MIX_MIC_LEVEL 0x3A #define SB_MIX_PC_SPEAKER_LEVEL 0x3B #define SB_MIX_OUTPUT_SWITCHES 0x3C -#define SB_MIX_INPUT_LEFT_LEVEL 0x3D -#define SB_MIX_INPUT_RIGHT_LEVEL 0x3E +#define SB_MIX_INPUT_LEFT_SWITCHES 0x3D +#define SB_MIX_INPUT_RIGHT_SWITCHES 0x3E #define SB_MIX_INPUT_LEFT_GAIN 0x3F #define SB_MIX_INPUT_RIGHT_GAIN 0x40 #define SB_MIX_OUTPUT_LEFT_GAIN 0x41 @@ -247,4 +248,47 @@ IN ULONG Timeout);
+/* + Reset the mixer +*/ +VOID +SbMixerReset(IN PUCHAR BasePort); + +/* + Pack mixer level data +*/ +NTSTATUS +SbMixerPackLevelData( + IN UCHAR Line, + IN UCHAR Level, + OUT PUCHAR PackedLevel); + +/* + Unpack mixer level data +*/ +NTSTATUS +SbMixerUnpackLevelData( + IN UCHAR Line, + IN UCHAR PackedLevel, + OUT PUCHAR Level); + +/* + Set a mixer line level +*/ +NTSTATUS +SbMixerSetLevel( + IN PUCHAR BasePort, + IN UCHAR Line, + IN UCHAR Level); + +/* + Get a mixer line level +*/ +NTSTATUS +SbMixerGetLevel( + IN PUCHAR BasePort, + IN UCHAR Line, + OUT PUCHAR Level); + + #endif
Modified: branches/silverblade-audio/lib/drivers/sound/soundblaster/mixer.c URL: http://svn.reactos.org/svn/reactos/branches/silverblade-audio/lib/drivers/so... ============================================================================== --- branches/silverblade-audio/lib/drivers/sound/soundblaster/mixer.c [iso-8859-1] (original) +++ branches/silverblade-audio/lib/drivers/sound/soundblaster/mixer.c [iso-8859-1] Wed Jul 2 05:23:18 2008 @@ -11,6 +11,9 @@
Notes: Functions documented in sbdsp.h + + Currently, input/output switches and AGC are not + supported. Nor is PC speaker volume. */
#include <ntddk.h> @@ -18,4 +21,200 @@
#include <sbdsp.h>
-/* Stub... */ +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; +}