1 /* 2 ReactOS Sound System 3 Sound Blaster DSP support 4 Mixer routines 5 6 Author: 7 Andrew Greenwood (silverblade@reactos.org) 8 9 History: 10 2 July 2008 - Created 11 12 Notes: 13 Functions documented in sbdsp.h 14 15 Currently, input/output switches and PC speaker volume 16 level are not supported. 17 18 The I/O switches are used for muting/unmuting mic, etc. 19 */ 20 21 #include "precomp.h" 22 23 VOID 24 SbMixerReset(IN PUCHAR BasePort) 25 { 26 WRITE_SB_MIXER_REGISTER(BasePort, SB_MIX_RESET); 27 /* Are we meant to send anything else? */ 28 } 29 30 NTSTATUS 31 SbMixerPackLevelData( 32 IN UCHAR Line, 33 IN UCHAR Level, 34 OUT PUCHAR PackedLevel) 35 { 36 if ( ! PackedLevel ) 37 return STATUS_INVALID_PARAMETER_3; 38 39 switch ( Line ) 40 { 41 case SB_MIX_MASTER_LEFT_LEVEL : 42 case SB_MIX_MASTER_RIGHT_LEVEL : 43 case SB_MIX_VOC_LEFT_LEVEL : 44 case SB_MIX_VOC_RIGHT_LEVEL : 45 case SB_MIX_MIDI_LEFT_LEVEL : 46 case SB_MIX_MIDI_RIGHT_LEVEL : 47 case SB_MIX_CD_LEFT_LEVEL : 48 case SB_MIX_CD_RIGHT_LEVEL : 49 case SB_MIX_LINE_LEFT_LEVEL : 50 case SB_MIX_LINE_RIGHT_LEVEL : 51 case SB_MIX_MIC_LEVEL : 52 case SB_MIX_LEGACY_MIC_LEVEL : /* is this correct? */ 53 { 54 if ( Level >= 0x20 ) 55 return STATUS_INVALID_PARAMETER_2; 56 57 *PackedLevel = Level << 3; 58 return STATUS_SUCCESS; 59 } 60 61 case SB_MIX_INPUT_LEFT_GAIN : 62 case SB_MIX_INPUT_RIGHT_GAIN : 63 case SB_MIX_OUTPUT_LEFT_GAIN : 64 case SB_MIX_OUTPUT_RIGHT_GAIN : 65 { 66 if ( Level >= 0x04 ) 67 return STATUS_INVALID_PARAMETER_2; 68 69 *PackedLevel = Level << 6; 70 return STATUS_SUCCESS; 71 } 72 73 case SB_MIX_VOC_LEVEL : /* legacy */ 74 case SB_MIX_MASTER_LEVEL : 75 case SB_MIX_FM_LEVEL : 76 case SB_MIX_CD_LEVEL : 77 case SB_MIX_LINE_LEVEL : 78 case SB_MIX_TREBLE_LEFT_LEVEL : /* bass/treble */ 79 case SB_MIX_TREBLE_RIGHT_LEVEL : 80 case SB_MIX_BASS_LEFT_LEVEL : 81 case SB_MIX_BASS_RIGHT_LEVEL : 82 { 83 if ( Level >= 0x10 ) 84 return STATUS_INVALID_PARAMETER_2; 85 86 *PackedLevel = Level << 4; 87 return STATUS_SUCCESS; 88 } 89 90 default : 91 return STATUS_INVALID_PARAMETER_1; 92 }; 93 } 94 95 NTSTATUS 96 SbMixerUnpackLevelData( 97 IN UCHAR Line, 98 IN UCHAR PackedLevel, 99 OUT PUCHAR Level) 100 { 101 if ( ! Level ) 102 return STATUS_INVALID_PARAMETER_3; 103 104 switch ( Line ) 105 { 106 case SB_MIX_MASTER_LEFT_LEVEL : 107 case SB_MIX_MASTER_RIGHT_LEVEL : 108 case SB_MIX_VOC_LEFT_LEVEL : 109 case SB_MIX_VOC_RIGHT_LEVEL : 110 case SB_MIX_MIDI_LEFT_LEVEL : 111 case SB_MIX_MIDI_RIGHT_LEVEL : 112 case SB_MIX_CD_LEFT_LEVEL : 113 case SB_MIX_CD_RIGHT_LEVEL : 114 case SB_MIX_LINE_LEFT_LEVEL : 115 case SB_MIX_LINE_RIGHT_LEVEL : 116 case SB_MIX_MIC_LEVEL : 117 { 118 *Level = PackedLevel >> 3; 119 return STATUS_SUCCESS; 120 } 121 122 case SB_MIX_INPUT_LEFT_GAIN : 123 case SB_MIX_INPUT_RIGHT_GAIN : 124 case SB_MIX_OUTPUT_LEFT_GAIN : 125 case SB_MIX_OUTPUT_RIGHT_GAIN : 126 { 127 *Level = PackedLevel >> 6; 128 return STATUS_SUCCESS; 129 } 130 131 case SB_MIX_VOC_LEVEL : /* legacy */ 132 case SB_MIX_MASTER_LEVEL : 133 case SB_MIX_FM_LEVEL : 134 case SB_MIX_CD_LEVEL : 135 case SB_MIX_LINE_LEVEL : 136 case SB_MIX_TREBLE_LEFT_LEVEL : /* bass/treble */ 137 case SB_MIX_TREBLE_RIGHT_LEVEL : 138 case SB_MIX_BASS_LEFT_LEVEL : 139 case SB_MIX_BASS_RIGHT_LEVEL : 140 { 141 *Level = PackedLevel >> 4; 142 return STATUS_SUCCESS; 143 } 144 145 default : 146 return STATUS_INVALID_PARAMETER_1; 147 }; 148 } 149 150 NTSTATUS 151 SbMixerSetLevel( 152 IN PUCHAR BasePort, 153 IN UCHAR Line, 154 IN UCHAR Level) 155 { 156 UCHAR PackedLevel = 0; 157 NTSTATUS Status; 158 159 Status = SbMixerPackLevelData(Line, Level, &PackedLevel); 160 161 switch ( Status ) 162 { 163 case STATUS_SUCCESS : 164 break; 165 166 case STATUS_INVALID_PARAMETER_1 : 167 return STATUS_INVALID_PARAMETER_2; 168 169 case STATUS_INVALID_PARAMETER_2 : 170 return STATUS_INVALID_PARAMETER_3; 171 172 default : 173 return Status; 174 }; 175 176 DbgPrint("SbMixerSetLevel: Line 0x%x, raw level 0x%x, packed 0x%x\n", Line, Level, PackedLevel); 177 178 WRITE_SB_MIXER_REGISTER(BasePort, Line); 179 WRITE_SB_MIXER_DATA(BasePort, PackedLevel); 180 181 return STATUS_SUCCESS; 182 } 183 184 NTSTATUS 185 SbMixerGetLevel( 186 IN PUCHAR BasePort, 187 IN UCHAR Line, 188 OUT PUCHAR Level) 189 { 190 UCHAR PackedLevel = 0; 191 NTSTATUS Status; 192 193 if ( ! Level ) 194 return STATUS_INVALID_PARAMETER_3; 195 196 WRITE_SB_MIXER_REGISTER(BasePort, Line); 197 PackedLevel = READ_SB_MIXER_DATA(BasePort); 198 199 Status = SbMixerUnpackLevelData(Line, PackedLevel, Level); 200 201 switch ( Status ) 202 { 203 case STATUS_SUCCESS : 204 break; 205 206 case STATUS_INVALID_PARAMETER_1 : 207 return STATUS_INVALID_PARAMETER_2; 208 209 case STATUS_INVALID_PARAMETER_2 : 210 return STATUS_INVALID_PARAMETER_3; 211 212 default : 213 return Status; 214 }; 215 216 DbgPrint("SbMixerGetLevel: Line 0x%x, raw level 0x%x, packed 0x%x\n", Line, Level, PackedLevel); 217 218 return STATUS_SUCCESS; 219 } 220 221 VOID 222 SbMixerEnableAGC(IN PUCHAR BasePort) 223 { 224 /* Untested... */ 225 WRITE_SB_MIXER_REGISTER(BasePort, SB_MIX_AGC); 226 WRITE_SB_MIXER_DATA(BasePort, 1); 227 } 228 229 VOID 230 SbMixerDisableAGC(IN PUCHAR BasePort) 231 { 232 /* Untested... */ 233 WRITE_SB_MIXER_REGISTER(BasePort, SB_MIX_AGC); 234 WRITE_SB_MIXER_DATA(BasePort, 0); 235 } 236 237 BOOLEAN 238 SbMixerIsAGCEnabled(IN PUCHAR BasePort) 239 { 240 /* Untested... */ 241 WRITE_SB_MIXER_REGISTER(BasePort, SB_MIX_AGC); 242 return (READ_SB_MIXER_DATA(BasePort) != 0); 243 } 244