1187 lines
53 KiB
C
1187 lines
53 KiB
C
/*++
|
|
*******************************************************************************
|
|
* Copyright (c) 1995 IBM Corporation
|
|
*
|
|
* Module Name: mixdvc.c
|
|
*
|
|
* Abstract: support for MIXER device
|
|
*
|
|
* Author: Jim Bozek [IBM]
|
|
*
|
|
* Environment:
|
|
*
|
|
* Comments:
|
|
*
|
|
* Rev History: Creation 09.25.95
|
|
*
|
|
*******************************************************************************
|
|
--*/
|
|
|
|
#include "common.h"
|
|
|
|
VOID cs423xWOLineChanged(PLOCAL_DEVICE_INFO pLDI, UCHAR Code);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(INIT, cs423xMixerInit)
|
|
#pragma alloc_text(PAGE, cs423xMixerGetConfig)
|
|
|
|
#pragma alloc_text(PAGE, cs423xMixerGetLineFlags)
|
|
#pragma alloc_text(PAGE, cs423xMixerGetControl)
|
|
#pragma alloc_text(PAGE, cs423xMixerGetCombCtrl)
|
|
#pragma alloc_text(PAGE, cs423xMixerSetControl)
|
|
#pragma alloc_text(PAGE, cs423xWOLineChanged)
|
|
|
|
#endif
|
|
|
|
MIXER_REGISTRY_DATA default_mregdata = {
|
|
{IBM_CS423X_DRIVER_VERSION}, {
|
|
{0xe000, 0xe000}, /* ControlMixerOutAtten */
|
|
{0x0000, 0x0000}, /* ControlMixerOutMute */
|
|
{0x0000, 0x0000}, /* ControlSpeakerMute */
|
|
|
|
{0xc000, 0xc000}, /* ControlWaveinGain */
|
|
{0x0001, 0x0000}, /* ControlHighPassFilter */
|
|
{0x0003, 0x0000}, /* ControlMux */
|
|
|
|
{0xc000, 0xc000}, /* ControlMixerInputAux1Gain */
|
|
{0x0000, 0x0000}, /* ControlMixerInputAux1Mute */
|
|
{0xc000, 0xc000}, /* ControlMixerInputLineinGain */
|
|
{0x0000, 0x0000}, /* ControlMixerInputLineinMute */
|
|
{0xc000, 0xc000}, /* ControlMixerInputAux2Gain */
|
|
{0x0000, 0x0000}, /* ControlMixerInputAux2Mute */
|
|
{0x0000, 0x0000}, /* ControlMixerInputMonoinAtten */
|
|
{0x0000, 0x0000}, /* ControlMixerInputMonoinMute */
|
|
{0xe000, 0xe000}, /* ControlMixerInputWaveoutAtten */
|
|
{0x0000, 0x0000}, /* ControlMixerInputWaveoutMute */
|
|
{0x0000, 0x0000}, /* ControlWaveoutPeak */
|
|
{0x0000, 0x0000}, /* ControlWaveinMonitorAtten */
|
|
{0x0000, 0x0000}, /* ControlWaveinMonitorEnable */
|
|
|
|
{0x0000, 0x0000}, /* ControlMuxSelectMic */
|
|
{0x0000, 0x0000}, /* ControlMicBoost */
|
|
{0x0000, 0x0000}, /* ControlMuxSelectLinein */
|
|
{0x0000, 0x0000}, /* ControlMuxSelectAux1 */
|
|
{0x0000, 0x0000},} /* ControlMuxSelectMixer */
|
|
};
|
|
|
|
/*
|
|
*********************************************************************************
|
|
* Ultimately, this routine needs to fill in all possibilities, but we'll
|
|
* start with the following:
|
|
*
|
|
* 1. The default defined in mix_objs.c is for the cs4232
|
|
* on the IBM-6070 Personal Power System (Carolina)
|
|
* 2. The cs4231 on the IBM-6015 Personal Power System (Sandalfoot)
|
|
*
|
|
*********************************************************************************
|
|
*/
|
|
VOID kpcMixerFixer(PSOUND_CONFIG_DATA pscd)
|
|
{
|
|
int index;
|
|
|
|
_dbgprint((_PRT_DBUG, "enter kpcMixerFixer(pscd: 0x%08x)\n", pscd));
|
|
|
|
/* connect the AUX1 input pin on the chip to the specified system signal */
|
|
switch (pscd->Aux1InputSignal) {
|
|
/* the AUX1 input pin on the chip is connected to both the Mixer and the MUX */
|
|
case SignalNull:
|
|
/* not defined in registry - use default definition - cs4232 on IBM PPS */
|
|
case SignalLinein:
|
|
/* default definition in mix_objs.c */
|
|
break;
|
|
case SignalNotUsed:
|
|
break;
|
|
case SignalMic:
|
|
break;
|
|
case SignalSynth:
|
|
/* a synthesizer is connected to the AUX1 input pin */
|
|
index = SourceMixerAux1;
|
|
MixerLineData[index].ShortNameStringId = IDS_SRCSYNTH_SHORT_NAME;
|
|
MixerLineData[index].LongNameStringId = IDS_SRCSYNTH_LONG_NAME;
|
|
MixerLineData[index].dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
|
|
MixerLineData[index].Type = MIXERLINE_TARGETTYPE_MIDIOUT;
|
|
MixerLineData[index].wPid = MM_MSFT_GENERIC_MIDIOUT;
|
|
MixerLineData[index].PnameStringId = IDS_MIDIOUT_PNAME;
|
|
|
|
index = SourceMuxAux1;
|
|
MixerLineData[index].ShortNameStringId = IDS_SRCSYNTH_SHORT_NAME;
|
|
MixerLineData[index].LongNameStringId = IDS_SRCSYNTH_LONG_NAME;
|
|
MixerLineData[index].dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
|
|
MixerLineData[index].Type = MIXERLINE_TARGETTYPE_MIDIOUT;
|
|
MixerLineData[index].wPid = MM_MSFT_GENERIC_MIDIOUT;
|
|
MixerLineData[index].PnameStringId = IDS_MIDIOUT_PNAME;
|
|
|
|
index = ControlMixerInputAux1Gain;
|
|
MixerControlData[index].ShortNameStringId = IDS_CONTROL_VOLMIXSYNTH_SHORT_NAME;
|
|
MixerControlData[index].LongNameStringId = IDS_CONTROL_VOLMIXSYNTH_LONG_NAME;
|
|
|
|
index = ControlMixerInputAux1Mute;
|
|
MixerControlData[index].ShortNameStringId = IDS_CONTROL_MUTEMIXSYNTH_SHORT_NAME;
|
|
MixerControlData[index].LongNameStringId = IDS_CONTROL_MUTEMIXSYNTH_LONG_NAME;
|
|
|
|
index = ControlMuxSelectAux1;
|
|
MixerControlData[index].ShortNameStringId = IDS_CONTROL_VOLMUXSYNTH_SHORT_NAME;
|
|
MixerControlData[index].LongNameStringId = IDS_CONTROL_VOLMUXSYNTH_LONG_NAME;
|
|
|
|
index = MuxAux1;
|
|
MixerTextData[index].dwParam2 = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
|
|
MixerTextData[index].SubControlTextStringId =IDS_SRCSYNTH_LONG_NAME;
|
|
break;
|
|
case SignalCD:
|
|
/* a CDROM audio signal is connected to the AUX1 input pin */
|
|
index = SourceMixerAux1;
|
|
MixerLineData[index].ShortNameStringId = IDS_SRCCD_SHORT_NAME;
|
|
MixerLineData[index].LongNameStringId = IDS_SRCCD_LONG_NAME;
|
|
MixerLineData[index].dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
|
|
MixerLineData[index].Type = MIXERLINE_TARGETTYPE_AUX;
|
|
MixerLineData[index].wPid = MM_MSFT_GENERIC_AUX_CD;
|
|
MixerLineData[index].PnameStringId = IDS_AUX_CD_PNAME;
|
|
|
|
index = SourceMuxAux1;
|
|
MixerLineData[index].ShortNameStringId = IDS_SRCCD_SHORT_NAME;
|
|
MixerLineData[index].LongNameStringId = IDS_SRCCD_LONG_NAME;
|
|
MixerLineData[index].dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
|
|
MixerLineData[index].Type = MIXERLINE_TARGETTYPE_AUX;
|
|
MixerLineData[index].wPid = MM_MSFT_GENERIC_AUX_CD;
|
|
MixerLineData[index].PnameStringId = IDS_AUX_CD_PNAME;
|
|
|
|
index = ControlMixerInputAux1Gain;
|
|
MixerControlData[index].ShortNameStringId = IDS_CONTROL_VOLMIXCDROM_SHORT_NAME;
|
|
MixerControlData[index].LongNameStringId = IDS_CONTROL_VOLMIXCDROM_LONG_NAME;
|
|
|
|
index = ControlMixerInputAux1Mute;
|
|
MixerControlData[index].ShortNameStringId = IDS_CONTROL_MUTEMIXCDROM_SHORT_NAME;
|
|
MixerControlData[index].LongNameStringId = IDS_CONTROL_MUTEMIXCDROM_LONG_NAME;
|
|
|
|
index = ControlMuxSelectAux1;
|
|
MixerControlData[index].ShortNameStringId = IDS_CONTROL_VOLMIXCDROM_SHORT_NAME;
|
|
MixerControlData[index].LongNameStringId = IDS_CONTROL_VOLMIXCDROM_LONG_NAME;
|
|
|
|
index = MuxAux1;
|
|
MixerTextData[index].dwParam2 = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
|
|
MixerTextData[index].SubControlTextStringId = IDS_SRCCD_LONG_NAME;
|
|
break;
|
|
case SignalModem:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
switch (pscd->Aux2InputSignal) {
|
|
/* the AUX2 input pin on the chip is connected to the Mixer only - not the MUX */
|
|
case SignalNull:
|
|
/* not defined in registry - use default definition - cs4232 on IBM PPS */
|
|
case SignalCD:
|
|
/* default definition in mix_objs.c */
|
|
break;
|
|
case SignalNotUsed:
|
|
break;
|
|
case SignalLinein:
|
|
break;
|
|
case SignalMic:
|
|
break;
|
|
case SignalSynth:
|
|
break;
|
|
case SignalModem:
|
|
/* a MODEM signal is connected to the AUX2 input pin */
|
|
index = SourceMixerAux2;
|
|
MixerLineData[index].ShortNameStringId = IDS_SRCMODEM_SHORT_NAME;
|
|
MixerLineData[index].LongNameStringId = IDS_SRCMODEM_LONG_NAME;
|
|
MixerLineData[index].dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE;
|
|
MixerLineData[index].Type = MIXERLINE_TARGETTYPE_AUX;
|
|
MixerLineData[index].wPid = MM_MSFT_GENERIC_AUX_LINE;
|
|
MixerLineData[index].PnameStringId = IDS_AUX_PNAME;
|
|
|
|
index = ControlMixerInputAux2Gain;
|
|
MixerControlData[index].ShortNameStringId = IDS_CONTROL_VOLMIXMODEM_SHORT_NAME;
|
|
MixerControlData[index].LongNameStringId = IDS_CONTROL_VOLMIXMODEM_LONG_NAME;
|
|
|
|
index = ControlMixerInputAux2Mute;
|
|
MixerControlData[index].ShortNameStringId = IDS_CONTROL_MUTEMIXMODEM_SHORT_NAME;
|
|
MixerControlData[index].LongNameStringId = IDS_CONTROL_MUTEMIXMODEM_LONG_NAME;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
switch (pscd->LineInputSignal) {
|
|
/* the AUX1 input pin on the chip is connected to both the Mixer and the MUX */
|
|
case SignalNull:
|
|
/* not defined in registry - use default definition - cs4232 on IBM PPS */
|
|
case SignalSynth:
|
|
/* default definition in mix_objs.c */
|
|
break;
|
|
case SignalNotUsed:
|
|
break;
|
|
case SignalLinein:
|
|
/* a Line Level input signal is connected to the LINEIN input pin */
|
|
index = SourceMixerLinein;
|
|
MixerLineData[index].ShortNameStringId = IDS_SRCLINEIN_SHORT_NAME;
|
|
MixerLineData[index].LongNameStringId = IDS_SRCLINEIN_LONG_NAME;
|
|
MixerLineData[index].dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY;
|
|
MixerLineData[index].Type = MIXERLINE_TARGETTYPE_AUX;
|
|
MixerLineData[index].wPid = MM_MSFT_GENERIC_AUX_LINE;
|
|
MixerLineData[index].PnameStringId = IDS_AUX_PNAME;
|
|
|
|
index = SourceMuxLinein;
|
|
MixerLineData[index].ShortNameStringId = IDS_SRCLINEIN_SHORT_NAME;
|
|
MixerLineData[index].LongNameStringId = IDS_SRCLINEIN_LONG_NAME;
|
|
MixerLineData[index].dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY;
|
|
MixerLineData[index].Type = MIXERLINE_TARGETTYPE_AUX;
|
|
MixerLineData[index].wPid = MM_MSFT_GENERIC_AUX_LINE;
|
|
MixerLineData[index].PnameStringId = IDS_AUX_PNAME;
|
|
|
|
index = ControlMixerInputLineinGain;
|
|
MixerControlData[index].ShortNameStringId = IDS_CONTROL_VOLMIXLINEIN_SHORT_NAME;
|
|
MixerControlData[index].LongNameStringId = IDS_CONTROL_VOLMIXLINEIN_LONG_NAME;
|
|
|
|
index = ControlMixerInputLineinMute;
|
|
MixerControlData[index].ShortNameStringId = IDS_CONTROL_MUTEMIXLINEIN_SHORT_NAME;
|
|
MixerControlData[index].LongNameStringId = IDS_CONTROL_MUTEMIXLINEIN_LONG_NAME;
|
|
|
|
index = MuxLinein;
|
|
MixerTextData[index].dwParam2 = MIXERLINE_COMPONENTTYPE_SRC_AUXILIARY;
|
|
MixerTextData[index].SubControlTextStringId =IDS_SRCLINEIN_LONG_NAME;
|
|
break;
|
|
case SignalMic:
|
|
break;
|
|
case SignalCD:
|
|
break;
|
|
case SignalModem:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
switch (pscd->MicInputSignal) {
|
|
/* the MIC input pin on the chip is connected to the MUX only - not the Mixer */
|
|
case SignalNull:
|
|
/* not defined in registry - use default definition - cs4232 on IBM PPS */
|
|
case SignalMic:
|
|
/* default definition in mix_objs.c */
|
|
break;
|
|
case SignalNotUsed:
|
|
break;
|
|
case SignalLinein:
|
|
break;
|
|
case SignalSynth:
|
|
break;
|
|
case SignalCD:
|
|
break;
|
|
case SignalModem:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
switch (pscd->MonoInputSignal) {
|
|
/* the MONOIN input pin on the chip is connected to the Mixer only - not the MUX */
|
|
case SignalNull:
|
|
/* not defined in registry - use default definition - cs4232 on IBM PPS */
|
|
case SignalMic:
|
|
/* default definition in mix_objs.c */
|
|
break;
|
|
case SignalNotUsed:
|
|
break;
|
|
case SignalLinein:
|
|
break;
|
|
case SignalSynth:
|
|
break;
|
|
case SignalCD:
|
|
break;
|
|
case SignalModem:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
_dbgprint((_PRT_DBUG, "exit kpcMixerFixer()\n"));
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
*********************************************************************************
|
|
*
|
|
*********************************************************************************
|
|
*/
|
|
NTSTATUS cs423xMixerInit(PLOCAL_DEVICE_INFO pLDI,
|
|
PMIXER_REGISTRY_DATA RegControlData,
|
|
BOOLEAN MixerSettingsInRegistry)
|
|
{
|
|
INT i;
|
|
PGLOBAL_DEVICE_INFO pGDI;
|
|
PLOCAL_DEVICE_INFO pLDIDev;
|
|
PMIXER_INFO pMI;
|
|
PLOCAL_MIXER_DATA LMData;
|
|
PDEVICE_OBJECT pDObj;
|
|
PSOUND_HARDWARE pHW;
|
|
PKMUTEX pKM;
|
|
PMIXER_REGISTRY_DATA pmrd;
|
|
|
|
_dbgprint((_PRT_DBUG, "cs423xMixerInit(pLDI: 0x%08x, RCData: 0x%08x, Found: 0x%08x)\n",
|
|
pLDI, RegControlData, MixerSettingsInRegistry));
|
|
|
|
/* initialize local vars */
|
|
pGDI = pLDI->pGlobalInfo;
|
|
pMI = &pGDI->MixerInfo;
|
|
pHW = &pGDI->Hw;
|
|
pKM = &pHW->HwMutex;
|
|
|
|
/* serialize on the hardware mutex */
|
|
HW_CLAIM(pKM);
|
|
|
|
/* setup callbacks for the mixer */
|
|
SoundInitMixerInfo(pMI, cs423xMixerGetLineFlags, cs423xMixerGetControl,
|
|
cs423xMixerGetCombCtrl, cs423xMixerSetControl);
|
|
|
|
/* set up the device with its mixer data */
|
|
pLDI->DeviceType = MIXER_DEVICE;
|
|
pLDI->DeviceSpecificData = (PVOID)pMI;
|
|
|
|
/* make sure each device can reference the mixer device */
|
|
pDObj = pGDI->DeviceObject[WaveInDevice]->DriverObject->DeviceObject;
|
|
for (pDObj = pDObj; pDObj != NULL; pDObj = pDObj->NextDevice) {
|
|
pLDIDev = (PLOCAL_DEVICE_INFO)pDObj->DeviceExtension;
|
|
if (pLDIDev->pGlobalInfo == pGDI)
|
|
pLDIDev->MixerDevice = pLDI;
|
|
}
|
|
|
|
/* get address of internal mixer data representation */
|
|
LMData = &pGDI->LocalMixerData;
|
|
|
|
/* if necessary, initialize internal mixer data representation from default data */
|
|
if (!MixerSettingsInRegistry) {
|
|
RtlCopyMemory(&pGDI->MixerSettings, &default_mregdata, sizeof(MIXER_REGISTRY_DATA));
|
|
cs423xSaveMixerSettings(pGDI);
|
|
}
|
|
|
|
/* initialize control notification elements of internal mixer data */
|
|
/* we do this only for settable controls, i.e., not PEAK meters */
|
|
for (i = 0; i < NumberOfMixerControls; i++) {
|
|
if ((MixerControlData[i].dwControlType & MIXERCONTROL_CT_CLASS_MASK) !=
|
|
MIXERCONTROL_CT_CLASS_METER) {
|
|
SoundInitDataItem(pMI, &LMData->ControlNotification[i],
|
|
(USHORT)MM_MIXM_CONTROL_CHANGE, (USHORT)i);
|
|
}
|
|
}
|
|
|
|
/* initialize line notification elements of internal mixer data */
|
|
for (i = 0; i < NumberOfMixerLines; i++) {
|
|
SoundInitDataItem(pMI, &LMData->LineNotification[i],
|
|
(USHORT)MM_MIXM_LINE_CHANGE, (USHORT)i);
|
|
}
|
|
|
|
/* release the hardware mutex */
|
|
HW_DISCLAIM(pKM);
|
|
|
|
/* set the chip to a known state */
|
|
pmrd = &pGDI->MixerSettings;
|
|
|
|
/* Mixer input and output attenuation, gain and mute settings */
|
|
cs423xSetSpeakerMute(pHW, (BOOLEAN)pmrd->ControlData[ControlSpeakerMute].v[MUTE].u);
|
|
if (pHW->Type == hwtype_cs4231) {
|
|
cs4231SetOutputAttenuation(pHW, pmrd,
|
|
(ULONG)pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u,
|
|
(ULONG)pmrd->ControlData[ControlMixerOutAtten].v[RIGHT].u);
|
|
cs4231SetOutputMute(pHW, pmrd,
|
|
(BOOLEAN)pmrd->ControlData[ControlMixerOutMute].v[MUTE].u);
|
|
}
|
|
else {
|
|
/* first do the mutes */
|
|
cs423xSetMixerInputAux2Mute(pHW,
|
|
(BOOLEAN)pmrd->ControlData[ControlMixerInputAux2Mute].v[MUTE].u);
|
|
cs423xSetMixerInputWaveoutMute(pHW,
|
|
(BOOLEAN)pmrd->ControlData[ControlMixerInputWaveoutMute].v[MUTE].u);
|
|
cs423xSetMixerInputLineinMute(pHW,
|
|
(BOOLEAN)pmrd->ControlData[ControlMixerInputLineinMute].v[MUTE].u);
|
|
cs423xSetMixerInputAux1Mute(pHW,
|
|
(BOOLEAN)pmrd->ControlData[ControlMixerInputAux1Mute].v[MUTE].u);
|
|
cs423xSetMixerInputMonoinMute(pHW,
|
|
(BOOLEAN)pmrd->ControlData[ControlMixerInputMonoinMute].v[MUTE].u);
|
|
cs423xSetOutputMute(pHW, (BOOLEAN)pmrd->ControlData[ControlMixerOutMute].v[MUTE].u);
|
|
|
|
/* now do the gain/attenuation */
|
|
cs423xSetMixerInputAux2Gain(pHW,
|
|
(USHORT)pmrd->ControlData[ControlMixerInputAux2Gain].v[LEFT].u,
|
|
(USHORT)pmrd->ControlData[ControlMixerInputAux2Gain].v[RIGHT].u);
|
|
cs423xSetMixerInputWaveoutAttenuation(pHW,
|
|
(USHORT)pmrd->ControlData[ControlMixerInputWaveoutAtten].v[LEFT].u,
|
|
(USHORT)pmrd->ControlData[ControlMixerInputWaveoutAtten].v[RIGHT].u);
|
|
cs423xSetMixerInputLineinGain(pHW,
|
|
(USHORT)pmrd->ControlData[ControlMixerInputLineinGain].v[LEFT].u,
|
|
(USHORT)pmrd->ControlData[ControlMixerInputLineinGain].v[RIGHT].u);
|
|
cs423xSetMixerInputAux1Gain(pHW,
|
|
(USHORT)pmrd->ControlData[ControlMixerInputAux1Gain].v[LEFT].u,
|
|
(USHORT)pmrd->ControlData[ControlMixerInputAux1Gain].v[RIGHT].u);
|
|
cs423xSetMixerInputMonoinAttenuation(pHW,
|
|
(USHORT)pmrd->ControlData[ControlMixerInputMonoinAtten].v[LEFT].u);
|
|
cs423xSetOutputAttenuation(pHW,
|
|
(USHORT)pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u,
|
|
(USHORT)pmrd->ControlData[ControlMixerOutAtten].v[RIGHT].u);
|
|
}
|
|
|
|
cs423xSetWaveinMonitorAttenuation(pHW,
|
|
(USHORT)pmrd->ControlData[ControlWaveinMonitorAtten].v[LEFT].u);
|
|
cs423xSetWaveinMonitorEnable(pHW,
|
|
(BOOLEAN)pmrd->ControlData[ControlWaveinMonitorEnable].v[ENABLE].u);
|
|
|
|
/* MUX selection, gain, and mode settings */
|
|
cs423xSetMuxSelect(pHW, (ULONG)pmrd->ControlData[ControlMux].v[MUXSEL].u);
|
|
cs423xSetMicBoost(pHW, (BOOLEAN)pmrd->ControlData[ControlMicBoost].v[BOOST].u);
|
|
cs423xSetHPF(pHW, (BOOLEAN)pmrd->ControlData[ControlHighPassFilter].v[FILTER].u);
|
|
cs423xSetWaveinGain(pHW, (USHORT)pmrd->ControlData[ControlWaveinGain].v[LEFT].u,
|
|
(USHORT)pmrd->ControlData[ControlWaveinGain].v[RIGHT].u);
|
|
|
|
SoundSetLineNotify(
|
|
(PLOCAL_DEVICE_INFO)pGDI->DeviceObject[WaveOutDevice]->DeviceExtension,
|
|
cs423xWOLineChanged);
|
|
|
|
/* Set up volume control ids for non-mixer devices - WaveOut */
|
|
SoundSetVolumeControlId(
|
|
(PLOCAL_DEVICE_INFO)pGDI->DeviceObject[WaveOutDevice]->DeviceExtension,
|
|
ControlMixerOutAtten);
|
|
|
|
/* Set up volume control ids for non-mixer devices - WaveIn */
|
|
SoundSetVolumeControlId(
|
|
(PLOCAL_DEVICE_INFO)pGDI->DeviceObject[WaveInDevice]->DeviceExtension,
|
|
ControlWaveinGain);
|
|
|
|
/* Set up volume control ids for non-mixer devices - Aux */
|
|
SoundSetVolumeControlId(
|
|
(PLOCAL_DEVICE_INFO)pGDI->DeviceObject[AuxDevice]->DeviceExtension,
|
|
ControlMixerInputMonoinAtten);
|
|
|
|
_dbgprint((_PRT_DBUG, "exit cs423xMixerInit(STATUS_SUCCESS)\n"));
|
|
|
|
return(STATUS_SUCCESS);
|
|
} /* cs423xMixerInit() */
|
|
|
|
/*
|
|
*********************************************************************************
|
|
*
|
|
*********************************************************************************
|
|
*/
|
|
NTSTATUS
|
|
cs423xMixerGetConfig(PLOCAL_DEVICE_INFO pLDI, PIRP pIrp, PIO_STACK_LOCATION IrpStack)
|
|
{
|
|
int i;
|
|
ULONG Length;
|
|
PCFDATA pcfData;
|
|
PMIXER_DD_CONTROL_LISTTEXT pLT;
|
|
PMIXER_DD_CONTROL_CONFIGURATION_DATA pCD;
|
|
|
|
_dbgprint((_PRT_DBUG,
|
|
"enter cs423xMixerGetConfig(pLDI: 0x%08x pIrp: 0x%08x IrpStack: 0x%08x)\n",
|
|
pLDI, pIrp, IrpStack));
|
|
|
|
/* allocate and initialize a temporary configuration data structure */
|
|
if ((pcfData = (PCFDATA)ExAllocatePool(PagedPool, sizeof(CFDATA))) == NULL) {
|
|
_dbgprint((_PRT_STAT, "exit cs423xMixerGetConfig(STATUS_INSUFFICIENT_RESOURCES)\n"));
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
RtlZeroMemory(pcfData, sizeof(CFDATA));
|
|
pcfData->Header.cbSize = sizeof(*pcfData);
|
|
|
|
/* copy the line, control, and text data from the constants to the local structure */
|
|
RtlCopyMemory(pcfData->LineData, MixerLineData, sizeof(MixerLineData));
|
|
RtlCopyMemory(pcfData->ControlData, MixerControlData, sizeof(MixerControlData));
|
|
RtlCopyMemory(pcfData->TextData, MixerTextData, sizeof(MixerTextData));
|
|
|
|
/* set the generic capabilities info */
|
|
pcfData->Header.DeviceCaps.wMid = MM_IBM;
|
|
pcfData->Header.DeviceCaps.wPid = MM_MSFT_WSS_OEM_MIXER;
|
|
pcfData->Header.DeviceCaps.vDriverVersion = IBM_CS423X_DRIVER_VERSION;
|
|
pcfData->Header.DeviceCaps.PnameStringId = SR_STR_DRIVER_MIXER;
|
|
pcfData->Header.DeviceCaps.fdwSupport = 0;
|
|
|
|
/* setup number of Lines and Controls */
|
|
pcfData->Header.NumberOfLines = NumberOfMixerLines;
|
|
pcfData->Header.NumberOfControls = NumberOfMixerControls;
|
|
|
|
/* compute number of destinations */
|
|
for (i = 0; i < NumberOfMixerLines; i++) {
|
|
if (MixerLineData[i].cConnections == 0) {
|
|
break;
|
|
}
|
|
}
|
|
pcfData->Header.DeviceCaps.cDestinations = i;
|
|
|
|
/* setup the text data offsets */
|
|
for (pLT = &pcfData->TextData[NumberOfTextItems - 1], pCD = pcfData->ControlData, i = 0;
|
|
i < NumberOfTextItems; pLT--, i++) {
|
|
pCD[pLT->ControlId].TextDataOffset = (PBYTE)pLT - (PBYTE)pcfData;
|
|
}
|
|
|
|
/* set the size of returned data */
|
|
Length = min(sizeof(*pcfData), IrpStack->Parameters.DeviceIoControl.OutputBufferLength);
|
|
pIrp->IoStatus.Information = Length;
|
|
|
|
/* copy our data for return to the user side caller */
|
|
RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer, pcfData, pIrp->IoStatus.Information);
|
|
|
|
/* free the allocated memory */
|
|
ExFreePool(pcfData);
|
|
|
|
_dbgprint((_PRT_DBUG, "exit cs423xMixerGetConfig(STATUS_SUCCESS)\n"));
|
|
|
|
return(STATUS_SUCCESS);
|
|
} /* cs423xMixerGetConfig() */
|
|
|
|
/*
|
|
*********************************************************************************
|
|
*
|
|
*********************************************************************************
|
|
*/
|
|
NTSTATUS cs423xMixerGetLineFlags(PMIXER_INFO MixerInfo, ULONG LineId, ULONG Length,
|
|
PVOID pData)
|
|
{
|
|
PULONG fdwLine;
|
|
|
|
_dbgprint((_PRT_DBUG, "enter cs423xMixerGetLineFlags(LId: %d Len: %d pData: 0x%08x)\n",
|
|
LineId, Length, pData));
|
|
|
|
if (LineId >= NumberOfMixerLines)
|
|
return(STATUS_INVALID_PARAMETER);
|
|
|
|
/* initialize local pointer */
|
|
fdwLine = pData;
|
|
|
|
/* fetch default - line is a source */
|
|
*fdwLine = MixerLineData[LineId].cConnections == 0 ? MIXERLINE_LINEF_SOURCE : 0;
|
|
|
|
/* determine if line is active */
|
|
*fdwLine |= MIXERLINE_LINEF_ACTIVE;
|
|
|
|
_dbgprint((_PRT_DBUG, "exit cs423xMixerGetLineFlags(STATUS_SUCCESS)\n"));
|
|
return(STATUS_SUCCESS);
|
|
} /* cs423xMixerGetLineFlags() */
|
|
|
|
/*
|
|
*********************************************************************************
|
|
*
|
|
*********************************************************************************
|
|
*/
|
|
NTSTATUS cs423xMixerGetCombCtrl(PMIXER_INFO MixerInfo, ULONG CtrlId, ULONG Length,
|
|
PVOID pData)
|
|
{
|
|
PULONG vol;
|
|
|
|
_dbgprint((_PRT_DBUG, "enter cs423xMixerGetCombCtrl(CId: %d Len: %d pData: 0x%08x)\n",
|
|
CtrlId, Length, pData));
|
|
|
|
vol = pData;
|
|
vol[0] = 0xFFFF;
|
|
vol[1] = 0xFFFF;
|
|
|
|
_dbgprint((_PRT_DBUG, "exit cs423xMixerGetCombCtrl(STATUS_SUCCESS)\n"));
|
|
return(STATUS_SUCCESS);
|
|
} /* cs423xMixerGetCombCtrl() */
|
|
|
|
/*
|
|
*********************************************************************************
|
|
*
|
|
*********************************************************************************
|
|
*/
|
|
NTSTATUS cs423xMixerGetControl(PMIXER_INFO MixerInfo, ULONG cid, ULONG Length, PVOID pData)
|
|
{
|
|
PGLOBAL_DEVICE_INFO pGDI;
|
|
INT i;
|
|
PMIXER_REGISTRY_DATA pmrd;
|
|
ULONG values[NumberOfMixerControls];
|
|
|
|
_dbgprint((_PRT_DBUG, "enter cs423xMixerGetControl(cid: %d Len: %d pData: 0x%08x)\n",
|
|
cid, Length, pData));
|
|
|
|
/* check for valid control ID */
|
|
if (cid >= NumberOfMixerControls)
|
|
return(STATUS_INVALID_PARAMETER);
|
|
|
|
/* obtain global device pointer */
|
|
pGDI = CONTAINING_RECORD(MixerInfo, GLOBAL_DEVICE_INFO, MixerInfo);
|
|
pmrd = &pGDI->MixerSettings;
|
|
|
|
/**************************************************************/
|
|
/* determine which control value is being requested */
|
|
/* In each case: */
|
|
/* If the DataLength is valid for the Control: */
|
|
/* - fetch the value from the memory representation */
|
|
/**************************************************************/
|
|
switch (cid) {
|
|
case ControlMixerOutAtten:
|
|
if (Length < (sizeof(ULONG) * 2))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[LEFT] = pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u;
|
|
values[RIGHT] = pmrd->ControlData[ControlMixerOutAtten].v[RIGHT].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlMixerOutMute:
|
|
if (Length < sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[MUTE] = pmrd->ControlData[ControlMixerOutMute].v[MUTE].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlSpeakerMute:
|
|
if (Length < sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[MUTE] = pmrd->ControlData[ControlSpeakerMute].v[MUTE].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlWaveinGain:
|
|
if (Length < (sizeof(ULONG) * 2))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[LEFT] = pmrd->ControlData[ControlWaveinGain].v[LEFT].u;
|
|
values[RIGHT] = pmrd->ControlData[ControlWaveinGain].v[RIGHT].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlHighPassFilter:
|
|
if (Length < sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[FILTER] = pmrd->ControlData[ControlHighPassFilter].v[FILTER].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlMux:
|
|
if (Length < MixerControlData[ControlMux].cMultipleItems * sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
for (i = 0; i < MixerControlData[ControlMux].cMultipleItems; i++) {
|
|
values[i] = FALSE;
|
|
if (i == (INT)(pmrd->ControlData[ControlMux].v[MUXSEL].u))
|
|
values[i] = TRUE;
|
|
}
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlMixerInputAux1Gain:
|
|
if (Length < (sizeof(ULONG) * 2))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[LEFT] = pmrd->ControlData[ControlMixerInputAux1Gain].v[LEFT].u;
|
|
values[RIGHT] = pmrd->ControlData[ControlMixerInputAux1Gain].v[RIGHT].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlMixerInputAux1Mute:
|
|
if (Length < sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[MUTE] = pmrd->ControlData[ControlMixerInputAux1Mute].v[MUTE].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlMixerInputLineinGain:
|
|
if (Length < (sizeof(ULONG) * 2))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[LEFT] = pmrd->ControlData[ControlMixerInputLineinGain].v[LEFT].u;
|
|
values[RIGHT] = pmrd->ControlData[ControlMixerInputLineinGain].v[RIGHT].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlMixerInputLineinMute:
|
|
if (Length < sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[MUTE] = pmrd->ControlData[ControlMixerInputLineinMute].v[MUTE].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlMixerInputAux2Gain:
|
|
if (Length < (sizeof(ULONG) * 2))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[LEFT] = pmrd->ControlData[ControlMixerInputAux2Gain].v[LEFT].u;
|
|
values[RIGHT] = pmrd->ControlData[ControlMixerInputAux2Gain].v[RIGHT].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlMixerInputAux2Mute:
|
|
if (Length < sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[MUTE] = pmrd->ControlData[ControlMixerInputAux2Mute].v[MUTE].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlMixerInputMonoinAtten:
|
|
if (Length < sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[LEFT] = pmrd->ControlData[ControlMixerInputMonoinAtten].v[LEFT].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlMixerInputMonoinMute:
|
|
if (Length < sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[MUTE] = pmrd->ControlData[ControlMixerInputMonoinMute].v[MUTE].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlMixerInputWaveoutAtten:
|
|
if (Length < (sizeof(ULONG) * 2))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[LEFT] = pmrd->ControlData[ControlMixerInputWaveoutAtten].v[LEFT].u;
|
|
values[RIGHT] = pmrd->ControlData[ControlMixerInputWaveoutAtten].v[RIGHT].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlMixerInputWaveoutMute:
|
|
if (Length < sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[MUTE] = pmrd->ControlData[ControlMixerInputWaveoutMute].v[MUTE].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlWaveoutPeak:
|
|
if (Length < sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
SoundPeakMeter(&pGDI->WaveOutInfo, values);
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlWaveinMonitorAtten:
|
|
if (Length < sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[LEFT] = pmrd->ControlData[ControlWaveinMonitorAtten].v[LEFT].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlWaveinMonitorEnable:
|
|
if (Length < sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[ENABLE] = pmrd->ControlData[ControlWaveinMonitorEnable].v[ENABLE].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlMuxSelectMic:
|
|
if ((INT)pmrd->ControlData[ControlMux].v[MUXSEL].u == 2){
|
|
if (Length < sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
SoundPeakMeter(&pGDI->WaveInInfo, values);
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
}
|
|
break;
|
|
case ControlMicBoost:
|
|
if (Length < sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
values[BOOST] = pmrd->ControlData[ControlMicBoost].v[BOOST].u;
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
case ControlMuxSelectLinein:
|
|
if ((INT)pmrd->ControlData[ControlMux].v[MUXSEL].u == 0){
|
|
if (Length < sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
SoundPeakMeter(&pGDI->WaveInInfo, values);
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
}
|
|
break;
|
|
case ControlMuxSelectAux1:
|
|
if ((INT)pmrd->ControlData[ControlMux].v[MUXSEL].u == 1){
|
|
if (Length < sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
SoundPeakMeter(&pGDI->WaveInInfo, values);
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
}
|
|
break;
|
|
case ControlMuxSelectMixer:
|
|
if ((INT)pmrd->ControlData[ControlMux].v[MUXSEL].u == 3){
|
|
if (Length < sizeof(ULONG))
|
|
return(STATUS_BUFFER_TOO_SMALL);
|
|
SoundPeakMeter(&pGDI->WaveInInfo, values);
|
|
RtlCopyMemory((PVOID)pData, (PVOID)values, Length);
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
_dbgprint((_PRT_ERRO, "cs423xMixerGetControl: unknown control device\n"));
|
|
break;
|
|
}
|
|
|
|
_dbgprint((_PRT_DBUG, "exit cs423xMixerGetControl(STATUS_SUCCESS)\n"));
|
|
return(STATUS_SUCCESS);
|
|
} /* cs423xMixerGetControl() */
|
|
|
|
/*
|
|
*********************************************************************************
|
|
* Since the 4231 does not have an attenuator at the output of the mixer,
|
|
* we must fake it by scaling the gain/attenuation of each input
|
|
*********************************************************************************
|
|
*/
|
|
VOID cs4231SetOutputAttenuation(PSOUND_HARDWARE pHW, PMIXER_REGISTRY_DATA pmrd,
|
|
ULONG left, ULONG right)
|
|
{
|
|
ULONG tl;
|
|
ULONG tr;
|
|
|
|
_dbgprint((_PRT_DBUG,
|
|
"enter cs4231SetOutputAttenuation(pHW: 0x%08x pmrd: %d left: %d right: %d)\n",
|
|
pHW, pmrd, left, right));
|
|
|
|
tl = ((ULONG)pmrd->ControlData[ControlMixerInputAux1Gain].v[LEFT].u * left) / USSMAX;
|
|
tr = ((ULONG)pmrd->ControlData[ControlMixerInputAux1Gain].v[RIGHT].u * right) / USSMAX;
|
|
cs423xSetMixerInputAux1Gain(pHW, (USHORT)(tl & 0xffff), (USHORT)(tr & 0xffff));
|
|
|
|
tl = ((ULONG)pmrd->ControlData[ControlMixerInputLineinGain].v[LEFT].u * left) / USSMAX;
|
|
tr = ((ULONG)pmrd->ControlData[ControlMixerInputLineinGain].v[RIGHT].u * right) / USSMAX;
|
|
cs423xSetMixerInputLineinGain(pHW, (USHORT)(tl & 0xffff), (USHORT)(tr & 0xffff));
|
|
|
|
tl = ((ULONG)pmrd->ControlData[ControlMixerInputAux2Gain].v[LEFT].u * left) / USSMAX;
|
|
tr = ((ULONG)pmrd->ControlData[ControlMixerInputAux2Gain].v[RIGHT].u * right) / USSMAX;
|
|
cs423xSetMixerInputAux2Gain(pHW, (USHORT)(tl & 0xffff), (USHORT)(tr & 0xffff));
|
|
|
|
tl = ((ULONG)pmrd->ControlData[ControlMixerInputMonoinAtten].v[LEFT].u * left) / USSMAX;
|
|
cs423xSetMixerInputMonoinAttenuation(pHW, (USHORT)(tl & 0xffff));
|
|
|
|
tl = ((ULONG)pmrd->ControlData[ControlMixerInputWaveoutAtten].v[LEFT].u * left) / USSMAX;
|
|
tr = ((ULONG)pmrd->ControlData[ControlMixerInputWaveoutAtten].v[RIGHT].u * right) / USSMAX;
|
|
cs423xSetMixerInputWaveoutAttenuation(pHW, (USHORT)(tl & 0xffff), (USHORT)(tr & 0xffff));
|
|
|
|
_dbgprint((_PRT_DBUG, "exit cs4231SetOutputAttenuation(VOID)\n"));
|
|
|
|
return;
|
|
} /* cs4231SetOutputAttenuation() */
|
|
|
|
/*
|
|
*********************************************************************************
|
|
* Since the 4231 does not have a Mute at the output of the mixer,
|
|
* we must fake it by Muting each input
|
|
*********************************************************************************
|
|
*/
|
|
VOID cs4231SetOutputMute(PSOUND_HARDWARE pHW, PMIXER_REGISTRY_DATA pmrd, BOOLEAN set)
|
|
{
|
|
ULONG tl;
|
|
ULONG tr;
|
|
|
|
_dbgprint((_PRT_DBUG,
|
|
"enter cs4231SetOutputMute(pHW: 0x%08x pmrd: %d set: 0x%04x)\n", pHW, pmrd, set));
|
|
|
|
if (set) {
|
|
cs423xSetMixerInputAux1Mute(pHW, set);
|
|
cs423xSetMixerInputLineinMute(pHW, set);
|
|
cs423xSetMixerInputAux2Mute(pHW, set);
|
|
cs423xSetMixerInputMonoinMute(pHW, set);
|
|
cs423xSetMixerInputWaveoutMute(pHW, set);
|
|
}
|
|
else {
|
|
cs423xSetMixerInputAux1Mute(pHW,
|
|
(BOOLEAN)(pmrd->ControlData[ControlMixerInputAux1Mute].v[MUTE].u));
|
|
cs423xSetMixerInputLineinMute(pHW,
|
|
(BOOLEAN)(pmrd->ControlData[ControlMixerInputLineinMute].v[MUTE].u));
|
|
cs423xSetMixerInputAux2Mute(pHW,
|
|
(BOOLEAN)(pmrd->ControlData[ControlMixerInputAux2Mute].v[MUTE].u));
|
|
cs423xSetMixerInputMonoinMute(pHW,
|
|
(BOOLEAN)(pmrd->ControlData[ControlMixerInputMonoinMute].v[MUTE].u));
|
|
cs423xSetMixerInputWaveoutMute(pHW,
|
|
(BOOLEAN)(pmrd->ControlData[ControlMixerInputWaveoutMute].v[MUTE].u));
|
|
}
|
|
|
|
_dbgprint((_PRT_DBUG, "exit cs4231SetOutputMute(VOID)\n"));
|
|
|
|
return;
|
|
} /* cs4231SetOutputMute() */
|
|
|
|
/*
|
|
*********************************************************************************
|
|
*
|
|
*********************************************************************************
|
|
*/
|
|
NTSTATUS cs423xMixerSetControl(PMIXER_INFO MixerInfo, ULONG cid, ULONG Length, PVOID pData)
|
|
{
|
|
PGLOBAL_DEVICE_INFO pGDI;
|
|
PULONG pul;
|
|
INT i;
|
|
PMIXER_REGISTRY_DATA pmrd;
|
|
ULONG tleft;
|
|
ULONG tright;
|
|
|
|
_dbgprint((_PRT_DBUG,
|
|
"enter cs423xMixerSetControl(pMI: 0x%08x cid: %d DLen: %d pData: 0x%08x)\n",
|
|
MixerInfo, cid, Length, pData));
|
|
|
|
/* obtain global device pointer */
|
|
pGDI = CONTAINING_RECORD(MixerInfo, GLOBAL_DEVICE_INFO, MixerInfo);
|
|
pmrd = &pGDI->MixerSettings;
|
|
|
|
/**************************************************************/
|
|
/* determine which control change is being requested */
|
|
/* In each case: */
|
|
/* If the DataLength is valid for the Control: */
|
|
/* - change it on the hardware */
|
|
/* - store the new value in the memory representation */
|
|
/* - send a ntofication */
|
|
/**************************************************************/
|
|
pul = pData;
|
|
switch (cid) {
|
|
case ControlMixerOutAtten:
|
|
if (Length != (sizeof(ULONG) * 2))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
if (pGDI->Hw.Type == hwtype_cs4231)
|
|
cs4231SetOutputAttenuation(&pGDI->Hw, pmrd, pul[LEFT], pul[RIGHT]);
|
|
else
|
|
cs423xSetOutputAttenuation(&pGDI->Hw, (USHORT)(pul[LEFT] & 0xffff),
|
|
(USHORT)(pul[RIGHT] & 0xffff));
|
|
pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u = (USHORT)pul[LEFT];
|
|
pmrd->ControlData[ControlMixerOutAtten].v[RIGHT].u = (USHORT)pul[RIGHT];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlMixerOutAtten]);
|
|
break;
|
|
case ControlMixerOutMute:
|
|
if (Length != sizeof(ULONG))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
if (pGDI->Hw.Type == hwtype_cs4231)
|
|
cs4231SetOutputMute(&pGDI->Hw, pmrd, (BOOLEAN)(pul[MUTE] & 0xffff));
|
|
else
|
|
cs423xSetOutputMute(&pGDI->Hw, (BOOLEAN)(pul[MUTE] & 0xffff));
|
|
pmrd->ControlData[ControlMixerOutMute].v[MUTE].u = (USHORT)pul[MUTE];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlMixerOutMute]);
|
|
break;
|
|
case ControlSpeakerMute:
|
|
if (Length != sizeof(ULONG))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
cs423xSetSpeakerMute(&pGDI->Hw, (BOOLEAN)(pul[MUTE] & 0xffff));
|
|
pmrd->ControlData[ControlSpeakerMute].v[MUTE].u = (USHORT)pul[MUTE];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlSpeakerMute]);
|
|
break;
|
|
case ControlWaveinGain:
|
|
if (Length != (sizeof(ULONG) * 2))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
cs423xSetWaveinGain(&pGDI->Hw, (USHORT)(pul[LEFT] & 0xffff),
|
|
(USHORT)(pul[RIGHT] & 0xffff));
|
|
pmrd->ControlData[ControlWaveinGain].v[LEFT].u = (USHORT)pul[LEFT];
|
|
pmrd->ControlData[ControlWaveinGain].v[RIGHT].u = (USHORT)pul[RIGHT];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlWaveinGain]);
|
|
break;
|
|
case ControlHighPassFilter:
|
|
if (Length != sizeof(ULONG))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
cs423xSetHPF(&pGDI->Hw, (BOOLEAN)(pul[FILTER] & 0xffff));
|
|
pmrd->ControlData[ControlHighPassFilter].v[FILTER].u = (USHORT)pul[FILTER];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlHighPassFilter]);
|
|
break;
|
|
case ControlMux:
|
|
if (Length != MixerControlData[ControlMux].cMultipleItems * sizeof(ULONG))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
pmrd->ControlData[ControlMux].v[MUXSEL].u = 0;
|
|
for (i = 0; i < MixerControlData[ControlMux].cMultipleItems; i++) {
|
|
if (pul[i]) {
|
|
pmrd->ControlData[ControlMux].v[MUXSEL].u = i;
|
|
cs423xSetMuxSelect(&pGDI->Hw, (ULONG)i);
|
|
}
|
|
}
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlMux]);
|
|
break;
|
|
case ControlMixerInputAux1Gain:
|
|
if (Length != (sizeof(ULONG) * 2))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
if (pGDI->Hw.Type == hwtype_cs4231) {
|
|
tleft = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u *
|
|
(ULONG)pul[LEFT]) / (ULONG)USSMAX;
|
|
tright = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[RIGHT].u *
|
|
(ULONG)pul[RIGHT]) / (ULONG)USSMAX;
|
|
cs423xSetMixerInputAux1Gain(&pGDI->Hw, (USHORT)(tleft & 0xffff),
|
|
(USHORT)(tright & 0xffff));
|
|
}
|
|
else
|
|
cs423xSetMixerInputAux1Gain(&pGDI->Hw, (USHORT)(pul[LEFT] & 0xffff),
|
|
(USHORT)(pul[RIGHT] & 0xffff));
|
|
pmrd->ControlData[ControlMixerInputAux1Gain].v[LEFT].u = (USHORT)pul[LEFT];
|
|
pmrd->ControlData[ControlMixerInputAux1Gain].v[RIGHT].u = (USHORT)pul[RIGHT];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputAux1Gain]);
|
|
break;
|
|
case ControlMixerInputAux1Mute:
|
|
if (Length != sizeof(ULONG))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
if (pmrd->ControlData[ControlMixerOutMute].v[MUTE].u || (pul[MUTE] & 0xffff))
|
|
cs423xSetMixerInputAux1Mute(&pGDI->Hw, TRUE);
|
|
else
|
|
cs423xSetMixerInputAux1Mute(&pGDI->Hw, FALSE);
|
|
pmrd->ControlData[ControlMixerInputAux1Mute].v[MUTE].u = (USHORT)pul[MUTE];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputAux1Mute]);
|
|
break;
|
|
case ControlMixerInputLineinGain:
|
|
if (Length != (sizeof(ULONG) * 2))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
if (pGDI->Hw.Type == hwtype_cs4231) {
|
|
tleft = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u *
|
|
(ULONG)pul[LEFT]) / (ULONG)USSMAX;
|
|
tright = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[RIGHT].u *
|
|
(ULONG)pul[RIGHT]) / (ULONG)USSMAX;
|
|
cs423xSetMixerInputLineinGain(&pGDI->Hw, (USHORT)(tleft & 0xffff),
|
|
(USHORT)(tright & 0xffff));
|
|
}
|
|
else
|
|
cs423xSetMixerInputLineinGain(&pGDI->Hw, (USHORT)(pul[LEFT] & 0xffff),
|
|
(USHORT)(pul[RIGHT] & 0xffff));
|
|
pmrd->ControlData[ControlMixerInputLineinGain].v[LEFT].u = (USHORT)pul[LEFT];
|
|
pmrd->ControlData[ControlMixerInputLineinGain].v[RIGHT].u = (USHORT)pul[RIGHT];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputLineinGain]);
|
|
break;
|
|
case ControlMixerInputLineinMute:
|
|
if (Length != sizeof(ULONG))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
if (pmrd->ControlData[ControlMixerOutMute].v[MUTE].u || (pul[MUTE] & 0xffff))
|
|
cs423xSetMixerInputLineinMute(&pGDI->Hw, TRUE);
|
|
else
|
|
cs423xSetMixerInputLineinMute(&pGDI->Hw, FALSE);
|
|
pmrd->ControlData[ControlMixerInputLineinMute].v[MUTE].u = (USHORT)pul[MUTE];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputLineinMute]);
|
|
break;
|
|
case ControlMixerInputAux2Gain:
|
|
if (Length != (sizeof(ULONG) * 2))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
if (pGDI->Hw.Type == hwtype_cs4231) {
|
|
tleft = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u *
|
|
(ULONG)pul[LEFT]) / (ULONG)USSMAX;
|
|
tright = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[RIGHT].u *
|
|
(ULONG)pul[RIGHT]) / (ULONG)USSMAX;
|
|
cs423xSetMixerInputAux2Gain(&pGDI->Hw, (USHORT)(tleft & 0xffff),
|
|
(USHORT)(tright & 0xffff));
|
|
}
|
|
else
|
|
cs423xSetMixerInputAux2Gain(&pGDI->Hw, (USHORT)(pul[LEFT] & 0xffff),
|
|
(USHORT)(pul[RIGHT] & 0xffff));
|
|
pmrd->ControlData[ControlMixerInputAux2Gain].v[LEFT].u = (USHORT)pul[LEFT];
|
|
pmrd->ControlData[ControlMixerInputAux2Gain].v[RIGHT].u = (USHORT)pul[RIGHT];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputAux2Gain]);
|
|
break;
|
|
case ControlMixerInputAux2Mute:
|
|
if (Length != sizeof(ULONG))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
if (pmrd->ControlData[ControlMixerOutMute].v[MUTE].u || (pul[MUTE] & 0xffff))
|
|
cs423xSetMixerInputAux2Mute(&pGDI->Hw, TRUE);
|
|
else
|
|
cs423xSetMixerInputAux2Mute(&pGDI->Hw, FALSE);
|
|
pmrd->ControlData[ControlMixerInputAux2Mute].v[MUTE].u = (USHORT)pul[MUTE];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputAux2Mute]);
|
|
break;
|
|
case ControlMixerInputMonoinAtten:
|
|
if (Length != sizeof(ULONG))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
if (pGDI->Hw.Type == hwtype_cs4231) {
|
|
tleft = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u *
|
|
(ULONG)pul[LEFT]) / (ULONG)USSMAX;
|
|
cs423xSetMixerInputMonoinAttenuation(&pGDI->Hw, (USHORT)(tleft & 0xffff));
|
|
}
|
|
else
|
|
cs423xSetMixerInputMonoinAttenuation(&pGDI->Hw, (USHORT)(pul[LEFT] & 0xffff));
|
|
pmrd->ControlData[ControlMixerInputMonoinAtten].v[LEFT].u = (USHORT)pul[LEFT];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputMonoinAtten]);
|
|
break;
|
|
case ControlMixerInputMonoinMute:
|
|
if (Length != sizeof(ULONG))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
if (pmrd->ControlData[ControlMixerOutMute].v[MUTE].u || (pul[MUTE] & 0xffff))
|
|
cs423xSetMixerInputMonoinMute(&pGDI->Hw, TRUE);
|
|
else
|
|
cs423xSetMixerInputMonoinMute(&pGDI->Hw, FALSE);
|
|
pmrd->ControlData[ControlMixerInputMonoinMute].v[MUTE].u = (USHORT)pul[MUTE];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputMonoinMute]);
|
|
break;
|
|
case ControlMixerInputWaveoutAtten:
|
|
if (Length != (sizeof(ULONG) * 2))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
if (pGDI->Hw.Type == hwtype_cs4231) {
|
|
tleft = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[LEFT].u *
|
|
(ULONG)pul[LEFT]) / (ULONG)USSMAX;
|
|
tright = ((ULONG)pmrd->ControlData[ControlMixerOutAtten].v[RIGHT].u *
|
|
(ULONG)pul[RIGHT]) / (ULONG)USSMAX;
|
|
cs423xSetMixerInputWaveoutAttenuation(&pGDI->Hw, (USHORT)(tleft & 0xffff),
|
|
(USHORT)(tright & 0xffff));
|
|
}
|
|
else
|
|
cs423xSetMixerInputWaveoutAttenuation(&pGDI->Hw, (USHORT)(pul[LEFT] & 0xffff),
|
|
(USHORT)(pul[RIGHT] & 0xffff));
|
|
pmrd->ControlData[ControlMixerInputWaveoutAtten].v[LEFT].u = (USHORT)pul[LEFT];
|
|
pmrd->ControlData[ControlMixerInputWaveoutAtten].v[RIGHT].u = (USHORT)pul[RIGHT];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputWaveoutAtten]);
|
|
break;
|
|
case ControlMixerInputWaveoutMute:
|
|
if (Length != sizeof(ULONG))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
if (pmrd->ControlData[ControlMixerOutMute].v[MUTE].u || (pul[MUTE] & 0xffff))
|
|
cs423xSetMixerInputWaveoutMute(&pGDI->Hw, TRUE);
|
|
else
|
|
cs423xSetMixerInputWaveoutMute(&pGDI->Hw, FALSE);
|
|
pmrd->ControlData[ControlMixerInputWaveoutMute].v[MUTE].u = (USHORT)pul[MUTE];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlMixerInputWaveoutMute]);
|
|
break;
|
|
case ControlWaveoutPeak:
|
|
return(STATUS_INVALID_PARAMETER);
|
|
break;
|
|
case ControlWaveinMonitorAtten:
|
|
if (Length != sizeof(ULONG))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
cs423xSetWaveinMonitorAttenuation(&pGDI->Hw, (USHORT)(pul[LEFT] & 0xffff));
|
|
pmrd->ControlData[ControlWaveinMonitorAtten].v[LEFT].u = (USHORT)pul[LEFT];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlWaveinMonitorAtten]);
|
|
break;
|
|
case ControlWaveinMonitorEnable:
|
|
if (Length != sizeof(ULONG))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
cs423xSetWaveinMonitorEnable(&pGDI->Hw, (BOOLEAN)(pul[ENABLE] & 0xffff));
|
|
pmrd->ControlData[ControlWaveinMonitorEnable].v[ENABLE].u = (USHORT)pul[ENABLE];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlWaveinMonitorEnable]);
|
|
break;
|
|
case ControlMuxSelectMic:
|
|
return(STATUS_INVALID_PARAMETER);
|
|
break;
|
|
case ControlMicBoost:
|
|
if (Length != sizeof(ULONG))
|
|
return(STATUS_INVALID_PARAMETER);
|
|
cs423xSetMicBoost(&pGDI->Hw, (BOOLEAN)(pul[BOOST] & 0xffff));
|
|
pmrd->ControlData[ControlMicBoost].v[BOOST].u = (USHORT)pul[BOOST];
|
|
SoundMixerChangedItem(&pGDI->MixerInfo,
|
|
&pGDI->LocalMixerData.ControlNotification[ControlMicBoost]);
|
|
break;
|
|
case ControlMuxSelectLinein:
|
|
return(STATUS_INVALID_PARAMETER);
|
|
break;
|
|
case ControlMuxSelectAux1:
|
|
return(STATUS_INVALID_PARAMETER);
|
|
break;
|
|
case ControlMuxSelectMixer:
|
|
return(STATUS_INVALID_PARAMETER);
|
|
break;
|
|
default:
|
|
_dbgprint((_PRT_ERRO, "cs423xMixerSetControl: unknown control device\n"));
|
|
break;
|
|
}
|
|
|
|
_dbgprint((_PRT_DBUG, "exit cs423xMixerSetControl(STATUS_SUCCESS)\n"));
|
|
|
|
return(STATUS_SUCCESS);
|
|
} /* cs423xMixerSetControl() */
|
|
|
|
/*
|
|
*********************************************************************************
|
|
*
|
|
*********************************************************************************
|
|
*/
|
|
VOID cs423xSaveMixerSettings(PGLOBAL_DEVICE_INFO pGDI)
|
|
{
|
|
_dbgprint((_PRT_DBUG, "enter cs423xSaveMixerSettings(pGDI: 0x%08x)\n", pGDI));
|
|
|
|
RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, pGDI->RegPathName, SOUND_MIXER_SETTINGS_NAME,
|
|
REG_BINARY, (PVOID)&pGDI->MixerSettings, sizeof(MIXER_REGISTRY_DATA));
|
|
|
|
_dbgprint((_PRT_DBUG, "exit cs423xSaveMixerSettings()\n"));
|
|
|
|
return;
|
|
} /* cs423xSaveMixerSettings() */
|
|
|
|
/*
|
|
*********************************************************************************
|
|
*
|
|
*********************************************************************************
|
|
*/
|
|
VOID cs423xWOLineChanged(PLOCAL_DEVICE_INFO pLDI, UCHAR Code)
|
|
{
|
|
PLOCAL_MIXER_DATA LocalMixerData;
|
|
|
|
LocalMixerData = &((PGLOBAL_DEVICE_INFO)pLDI->pGlobalInfo)->LocalMixerData;
|
|
|
|
SoundMixerChangedItem(
|
|
&((PGLOBAL_DEVICE_INFO)pLDI->pGlobalInfo)->MixerInfo,
|
|
&LocalMixerData->LineNotification[SourceMixerWaveOut]);
|
|
|
|
}
|