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/multi…
==============================================================================
--- 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/react…
==============================================================================
--- 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/s…
==============================================================================
--- 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;
+}