2105 lines
75 KiB
C++
2105 lines
75 KiB
C++
/********************************************************************************
|
|
** Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
|
|
**
|
|
** Portions Copyright (c) 1998-1999 Intel Corporation
|
|
**
|
|
********************************************************************************/
|
|
|
|
// Every debug output has "Modulname text".
|
|
static char STR_MODULENAME[] = "ICH Topology: ";
|
|
|
|
#include "mintopo.h"
|
|
|
|
/*****************************************************************************
|
|
* AC97 topology miniport tables
|
|
*/
|
|
|
|
/*****************************************************************************
|
|
* PinDataRangesBridge
|
|
*****************************************************************************
|
|
* Structures indicating range of valid format values for bridge pins.
|
|
*/
|
|
static KSDATARANGE PinDataRangesAnalogBridge[] =
|
|
{
|
|
{
|
|
sizeof(KSDATARANGE),
|
|
0,
|
|
0,
|
|
0,
|
|
STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
|
|
STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
|
|
STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
|
|
}
|
|
};
|
|
|
|
/*****************************************************************************
|
|
* PinDataRangePointersBridge
|
|
*****************************************************************************
|
|
* List of pointers to structures indicating range of valid format values
|
|
* for audio bridge pins.
|
|
*/
|
|
static PKSDATARANGE PinDataRangePointersAnalogBridge[] =
|
|
{
|
|
(PKSDATARANGE)&PinDataRangesAnalogBridge[0]
|
|
};
|
|
|
|
|
|
/*****************************************************************************
|
|
* PropertiesVolume
|
|
*****************************************************************************
|
|
* Properties for volume controls.
|
|
*/
|
|
static PCPROPERTY_ITEM PropertiesVolume[] =
|
|
{
|
|
{
|
|
&KSPROPSETID_Audio,
|
|
KSPROPERTY_AUDIO_VOLUMELEVEL,
|
|
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
|
|
CMiniportTopologyICH::PropertyHandler_Level
|
|
},
|
|
{
|
|
&KSPROPSETID_Audio,
|
|
KSPROPERTY_AUDIO_CPU_RESOURCES,
|
|
KSPROPERTY_TYPE_GET,
|
|
CMiniportTopologyICH::PropertyHandler_CpuResources
|
|
}
|
|
};
|
|
|
|
/*****************************************************************************
|
|
* AutomationVolume
|
|
*****************************************************************************
|
|
* Automation table for volume controls.
|
|
*/
|
|
DEFINE_PCAUTOMATION_TABLE_PROP (AutomationVolume, PropertiesVolume);
|
|
|
|
/*****************************************************************************
|
|
* PropertiesMute
|
|
*****************************************************************************
|
|
* Properties for mute controls.
|
|
*/
|
|
static PCPROPERTY_ITEM PropertiesMute[] =
|
|
{
|
|
{
|
|
&KSPROPSETID_Audio,
|
|
KSPROPERTY_AUDIO_MUTE,
|
|
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET,
|
|
CMiniportTopologyICH::PropertyHandler_OnOff
|
|
},
|
|
{
|
|
&KSPROPSETID_Audio,
|
|
KSPROPERTY_AUDIO_CPU_RESOURCES,
|
|
KSPROPERTY_TYPE_GET,
|
|
CMiniportTopologyICH::PropertyHandler_CpuResources
|
|
}
|
|
};
|
|
|
|
/*****************************************************************************
|
|
* AutomationMute
|
|
*****************************************************************************
|
|
* Automation table for mute controls.
|
|
*/
|
|
DEFINE_PCAUTOMATION_TABLE_PROP (AutomationMute, PropertiesMute);
|
|
|
|
/*****************************************************************************
|
|
* PropertiesMux
|
|
*****************************************************************************
|
|
* Properties for mux controls.
|
|
*/
|
|
static PCPROPERTY_ITEM PropertiesMux[] =
|
|
{
|
|
{
|
|
&KSPROPSETID_Audio,
|
|
KSPROPERTY_AUDIO_MUX_SOURCE,
|
|
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET,
|
|
CMiniportTopologyICH::PropertyHandler_Ulong
|
|
},
|
|
{
|
|
&KSPROPSETID_Audio,
|
|
KSPROPERTY_AUDIO_CPU_RESOURCES,
|
|
KSPROPERTY_TYPE_GET,
|
|
CMiniportTopologyICH::PropertyHandler_CpuResources
|
|
}
|
|
};
|
|
|
|
/*****************************************************************************
|
|
* AutomationMux
|
|
*****************************************************************************
|
|
* Automation table for mux controls.
|
|
*/
|
|
DEFINE_PCAUTOMATION_TABLE_PROP (AutomationMux, PropertiesMux);
|
|
|
|
/*****************************************************************************
|
|
* PropertiesSpecial
|
|
*****************************************************************************
|
|
* Properties for Special controls like fake loudness and fake agc.
|
|
*/
|
|
static PCPROPERTY_ITEM PropertiesSpecial[] =
|
|
{
|
|
{
|
|
&KSPROPSETID_Audio,
|
|
KSPROPERTY_AUDIO_AGC,
|
|
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET,
|
|
CMiniportTopologyICH::PropertyHandler_OnOff
|
|
},
|
|
{
|
|
&KSPROPSETID_Audio,
|
|
KSPROPERTY_AUDIO_LOUDNESS,
|
|
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET,
|
|
CMiniportTopologyICH::PropertyHandler_OnOff
|
|
},
|
|
{
|
|
&KSPROPSETID_Audio,
|
|
KSPROPERTY_AUDIO_CPU_RESOURCES,
|
|
KSPROPERTY_TYPE_GET,
|
|
CMiniportTopologyICH::PropertyHandler_CpuResources
|
|
}
|
|
};
|
|
|
|
/*****************************************************************************
|
|
* AutomationAgc
|
|
*****************************************************************************
|
|
* Automation table for agc controls.
|
|
*/
|
|
DEFINE_PCAUTOMATION_TABLE_PROP (AutomationSpecial, PropertiesSpecial);
|
|
|
|
/*****************************************************************************
|
|
* PropertiesTone
|
|
*****************************************************************************
|
|
* Properties for tone controls.
|
|
*/
|
|
static PCPROPERTY_ITEM PropertiesTone[] =
|
|
{
|
|
{
|
|
&KSPROPSETID_Audio,
|
|
KSPROPERTY_AUDIO_BASS,
|
|
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
|
|
CMiniportTopologyICH::PropertyHandler_Tone
|
|
},
|
|
{
|
|
&KSPROPSETID_Audio,
|
|
KSPROPERTY_AUDIO_TREBLE,
|
|
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
|
|
CMiniportTopologyICH::PropertyHandler_Tone
|
|
},
|
|
{
|
|
&KSPROPSETID_Audio,
|
|
KSPROPERTY_AUDIO_CPU_RESOURCES,
|
|
KSPROPERTY_TYPE_GET,
|
|
CMiniportTopologyICH::PropertyHandler_CpuResources
|
|
}
|
|
};
|
|
|
|
/*****************************************************************************
|
|
* AutomationTone
|
|
*****************************************************************************
|
|
* Automation table for tone controls.
|
|
*/
|
|
DEFINE_PCAUTOMATION_TABLE_PROP (AutomationTone, PropertiesTone);
|
|
|
|
/*****************************************************************************
|
|
* Properties3D
|
|
*****************************************************************************
|
|
* Properties for 3D controls.
|
|
*/
|
|
static PCPROPERTY_ITEM Properties3D[] =
|
|
{
|
|
// are faky volume controls.
|
|
{
|
|
&KSPROPSETID_Audio,
|
|
KSPROPERTY_AUDIO_VOLUMELEVEL,
|
|
KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
|
|
CMiniportTopologyICH::PropertyHandler_Tone
|
|
},
|
|
{
|
|
&KSPROPSETID_Audio,
|
|
KSPROPERTY_AUDIO_CPU_RESOURCES,
|
|
KSPROPERTY_TYPE_GET,
|
|
CMiniportTopologyICH::PropertyHandler_CpuResources
|
|
}
|
|
};
|
|
|
|
/*****************************************************************************
|
|
* Automation3D
|
|
*****************************************************************************
|
|
* Automation table for 3D controls.
|
|
*/
|
|
DEFINE_PCAUTOMATION_TABLE_PROP (Automation3D, Properties3D);
|
|
|
|
#ifdef INCLUDE_PRIVATE_PROPERTY
|
|
/*****************************************************************************
|
|
* FilterPropertiesPrivate
|
|
*****************************************************************************
|
|
* Properties for AC97 features.
|
|
*/
|
|
static PCPROPERTY_ITEM FilterPropertiesPrivate[] =
|
|
{
|
|
// This is a private property for getting the AC97 codec features.
|
|
{
|
|
&KSPROPSETID_Private,
|
|
KSPROPERTY_AC97_FEATURES,
|
|
KSPROPERTY_TYPE_GET,
|
|
CMiniportTopologyICH::PropertyHandler_Private
|
|
}
|
|
#ifdef PROPERTY_SHOW_SET
|
|
,
|
|
// This is a private property for getting the AC97 codec features.
|
|
{
|
|
&KSPROPSETID_Private,
|
|
KSPROPERTY_AC97_SAMPLE_SET,
|
|
KSPROPERTY_TYPE_SET,
|
|
CMiniportTopologyICH::PropertyHandler_Private
|
|
}
|
|
#endif
|
|
};
|
|
|
|
/*****************************************************************************
|
|
* FilterAutomationPrivate
|
|
*****************************************************************************
|
|
* Filter's automation table for private property controls.
|
|
*/
|
|
DEFINE_PCAUTOMATION_TABLE_PROP (FilterAutomationPrivate, FilterPropertiesPrivate);
|
|
#endif
|
|
|
|
#pragma code_seg("PAGE")
|
|
|
|
/*****************************************************************************
|
|
* CreateMiniportTopologyICH
|
|
*****************************************************************************
|
|
* Creates a topology miniport object for the ICH audio adapter. This uses a
|
|
* macro from STDUNK.H to do all the work.
|
|
*/
|
|
NTSTATUS CreateMiniportTopologyICH
|
|
(
|
|
OUT PUNKNOWN * Unknown,
|
|
IN REFCLSID,
|
|
IN PUNKNOWN UnknownOuter OPTIONAL,
|
|
IN POOL_TYPE PoolType
|
|
)
|
|
{
|
|
PAGED_CODE ();
|
|
|
|
ASSERT (Unknown);
|
|
|
|
STD_CREATE_BODY (CMiniportTopologyICH, Unknown, UnknownOuter, PoolType);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* CMiniportTopologyICH::NonDelegatingQueryInterface
|
|
*****************************************************************************
|
|
* Obtains an interface. This function works just like a COM QueryInterface
|
|
* call and is used if the object is not being aggregated.
|
|
* We basically just check any GUID we know and return this object in case we
|
|
* know it.
|
|
*/
|
|
STDMETHODIMP_(NTSTATUS) CMiniportTopologyICH::NonDelegatingQueryInterface
|
|
(
|
|
IN REFIID Interface,
|
|
OUT PVOID * Object
|
|
)
|
|
{
|
|
PAGED_CODE ();
|
|
|
|
ASSERT (Object);
|
|
|
|
DOUT (DBG_PRINT, ("[CMiniportTopologyICH::NonDelegatingQueryInterface]"));
|
|
|
|
// Is it IID_IUnknown?
|
|
if (IsEqualGUIDAligned (Interface, IID_IUnknown))
|
|
{
|
|
*Object = (PVOID)(PUNKNOWN)this;
|
|
}
|
|
else
|
|
// or IID_IMiniport ...
|
|
if (IsEqualGUIDAligned (Interface, IID_IMiniport))
|
|
{
|
|
*Object = (PVOID)(PMINIPORT)this;
|
|
}
|
|
else
|
|
// or IID_IMiniportTopology ...
|
|
if (IsEqualGUIDAligned (Interface, IID_IMiniportTopology))
|
|
{
|
|
*Object = (PVOID)(PMINIPORTTOPOLOGY)this;
|
|
}
|
|
else
|
|
// or maybe our IID_IMiniportTopologyICH ...
|
|
if (IsEqualGUIDAligned (Interface, IID_IMiniportTopologyICH))
|
|
{
|
|
*Object = (PVOID)(PMINIPORTTOPOLOGYICH)this;
|
|
}
|
|
else
|
|
{
|
|
// nothing found, must be an unknown interface.
|
|
*Object = NULL;
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// We reference the interface for the caller.
|
|
//
|
|
((PUNKNOWN)(*Object))->AddRef ();
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* CMiniportTopologyICH::~CMiniportTopologyICH
|
|
*****************************************************************************
|
|
* Destructor.
|
|
*/
|
|
CMiniportTopologyICH::~CMiniportTopologyICH ()
|
|
{
|
|
PAGED_CODE ();
|
|
|
|
DOUT (DBG_PRINT, ("[CMiniportTopologyICH::~CMiniportTopologyICH]"));
|
|
|
|
// release all the stuff that we had referenced or allocated.
|
|
if (AdapterCommon)
|
|
{
|
|
// Notify the AdapterCommon that we go away.
|
|
AdapterCommon->SetMiniportTopology (NULL);
|
|
AdapterCommon->Release ();
|
|
AdapterCommon = NULL;
|
|
}
|
|
|
|
if (FilterDescriptor)
|
|
{
|
|
ExFreePool (FilterDescriptor);
|
|
FilterDescriptor = NULL;
|
|
}
|
|
|
|
if (ConnectionDescriptors)
|
|
{
|
|
ExFreePool (ConnectionDescriptors);
|
|
ConnectionDescriptors = NULL;
|
|
}
|
|
|
|
if (NodeDescriptors)
|
|
{
|
|
ExFreePool (NodeDescriptors);
|
|
NodeDescriptors = NULL;
|
|
}
|
|
|
|
if (PinDescriptors)
|
|
{
|
|
ExFreePool (PinDescriptors);
|
|
PinDescriptors = NULL;
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* CMiniportTopologyICH::DataRangeIntersection
|
|
*****************************************************************************
|
|
* Is defined in the IMiniportTopology interface. We just return
|
|
* STATUS_NOT_IMPLEMENTED and portcls will use a default handler for this.
|
|
*/
|
|
STDMETHODIMP_(NTSTATUS) CMiniportTopologyICH::DataRangeIntersection
|
|
(
|
|
IN ULONG PinId,
|
|
IN PKSDATARANGE DataRange,
|
|
IN PKSDATARANGE MatchingDataRange,
|
|
IN ULONG OutputBufferLength,
|
|
OUT PVOID ResultantFormat OPTIONAL,
|
|
OUT PULONG ResultantFormatLength
|
|
)
|
|
{
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
};
|
|
|
|
/*****************************************************************************
|
|
* CMiniportTopologyICH::Init
|
|
*****************************************************************************
|
|
* Initializes the miniport.
|
|
* We initialize the translation tables, add reference to the port driver and
|
|
* build the topology.
|
|
*/
|
|
STDMETHODIMP_(NTSTATUS) CMiniportTopologyICH::Init
|
|
(
|
|
IN PUNKNOWN UnknownAdapter,
|
|
IN PRESOURCELIST ResourceList,
|
|
IN PPORTTOPOLOGY Port_
|
|
)
|
|
{
|
|
PAGED_CODE ();
|
|
|
|
ASSERT (UnknownAdapter);
|
|
ASSERT (Port_);
|
|
|
|
DOUT (DBG_PRINT, ("[CMiniportTopologyICH::Init]"));
|
|
|
|
//
|
|
// Set the copy protect flag to FALSE.
|
|
//
|
|
m_bCopyProtectFlag = FALSE;
|
|
|
|
//
|
|
// get the IAdapterCommon interface from the adapter.
|
|
//
|
|
NTSTATUS ntStatus = UnknownAdapter->QueryInterface (IID_IAdapterCommon,
|
|
(PVOID *) &AdapterCommon);
|
|
|
|
//
|
|
// initialize translation tables
|
|
//
|
|
for (int i = 0; i < PIN_TOP_ELEMENT; i++)
|
|
{
|
|
stPinTrans[i].PinDef = PIN_INVALID;
|
|
stPinTrans[i].PinNr = -1;
|
|
}
|
|
|
|
for (i = 0; i < NODE_TOP_ELEMENT; i++)
|
|
{
|
|
stNodeTrans[i].NodeDef = NODE_INVALID;
|
|
stNodeTrans[i].NodeNr = -1;
|
|
}
|
|
|
|
// build the topology (means register pins, nodes, connections).
|
|
if (NT_SUCCESS (ntStatus))
|
|
{
|
|
ntStatus = BuildTopology ();
|
|
}
|
|
|
|
if (NT_SUCCESS (ntStatus))
|
|
{
|
|
//
|
|
// Notify AdapterCommon that we are ready now.
|
|
//
|
|
AdapterCommon->SetMiniportTopology (this);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// clean up our mess
|
|
//
|
|
|
|
// clean up AdapterCommon
|
|
if (AdapterCommon)
|
|
{
|
|
AdapterCommon->Release ();
|
|
AdapterCommon = NULL;
|
|
}
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* CMiniportTopologyICH::GetDescription
|
|
*****************************************************************************
|
|
* Gets/returns the topology to the system.
|
|
*/
|
|
STDMETHODIMP_(NTSTATUS) CMiniportTopologyICH::GetDescription
|
|
(
|
|
OUT PPCFILTER_DESCRIPTOR * OutFilterDescriptor
|
|
)
|
|
{
|
|
PAGED_CODE ();
|
|
|
|
ASSERT (OutFilterDescriptor);
|
|
|
|
DOUT (DBG_PRINT, ("[CMiniportTopologyICH::GetDescription]"));
|
|
|
|
#if (DBG)
|
|
// Dump it here. The system requests the topology only once.
|
|
DumpTopology ();
|
|
#endif
|
|
|
|
if (FilterDescriptor)
|
|
{
|
|
*OutFilterDescriptor = FilterDescriptor;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
else
|
|
return STATUS_DEVICE_CONFIGURATION_ERROR;
|
|
}
|
|
|
|
#if (DBG)
|
|
/*****************************************************************************
|
|
* CMiniportTopologyICH::DumpTopology
|
|
*****************************************************************************
|
|
* Dumps the topology for debugging.
|
|
* See the defines at the beginning of this file?
|
|
*/
|
|
void CMiniportTopologyICH::DumpTopology (void)
|
|
{
|
|
PAGED_CODE ();
|
|
|
|
if (FilterDescriptor)
|
|
{
|
|
// dump the pins
|
|
DOUT (DBG_PINS, ("TOPOLOGY MINIPORT PINS"));
|
|
for(ULONG index = 0; index < FilterDescriptor->PinCount; index++)
|
|
{
|
|
DOUT (DBG_PINS, (" %2d %s", index,
|
|
TopoPinStrings[TransPinNrToPinDef (index)]));
|
|
}
|
|
|
|
// dump the nodes
|
|
DOUT (DBG_NODES, ("TOPOLOGY MINIPORT NODES"));
|
|
for(index = 0; index < FilterDescriptor->NodeCount; index++)
|
|
{
|
|
DOUT (DBG_NODES, (" %2d %s", index,
|
|
NodeStrings[TransNodeNrToNodeDef (index)]));
|
|
}
|
|
|
|
// dump the connections
|
|
DOUT (DBG_CONNS, ("TOPOLOGY MINIPORT CONNECTIONS"));
|
|
for(index = 0; index < FilterDescriptor->ConnectionCount; index++)
|
|
{
|
|
DOUT (DBG_CONNS, (" %2d (%d,%d)->(%d,%d)", index,
|
|
FilterDescriptor->Connections[index].FromNode,
|
|
FilterDescriptor->Connections[index].FromNodePin,
|
|
FilterDescriptor->Connections[index].ToNode,
|
|
FilterDescriptor->Connections[index].ToNodePin));
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
/*****************************************************************************
|
|
* Miniport Topology V = Volume, M = Mute, L = Loudness, A = AGC
|
|
*==================== T = Treble, B = Bass, 0-9 = PinNr of node
|
|
*
|
|
* PCBEEP ---> V ---> M -----------------------------\
|
|
* PHONE ---> V ---> M ----------------------------\ \
|
|
* \ \
|
|
* WaveOut -------> V --> M --------------> 1+-----+ \ \
|
|
* MIC1 or MIC2 --> L --> A --> V --> M --> 2| SUM | \ \
|
|
* LineIn -------> V --> M --------------> 3| | \ \
|
|
* CD -------> V --> M --------------> 4| |0--->SUM--> T --> B --> L --> V --> M (MasterOut)
|
|
* Video -------> V --> M --------------> 5| |
|
|
* AUX -------> V --> M --------------> 6| |
|
|
* 3D Depth -----> V --> L --> A --------> 7| |
|
|
* 3D Center -----> V --> L --> A --------> 8| |
|
|
* Headphone -----> V --> M --------------> 9| |
|
|
* Front Speaker -> V --> M -------------->10| |
|
|
* Surround ------> V --> M -------------->11| |
|
|
* Center ------> V --> M -------------->12| |
|
|
* LFE ------> V --> M -------------->13+-----+
|
|
*
|
|
*
|
|
* virt. Pin: Tone mix mono ---> V --> M ---> 7+-------+
|
|
* virt. Pin: Tone mix stereo ---> V --> M ---> 6| |
|
|
* Phone ---> V --> M ---> 8| M |
|
|
* Mic (after AGC) ---> V --> M ---> 1| |0-----> (WaveIn)
|
|
* LineIn ---> V --> M ---> 5| U |
|
|
* CD ---> V --> M ---> 2| |
|
|
* Video ---> V --> M ---> 3| X |
|
|
* AUX ---> V --> M ---> 4+-------+
|
|
*
|
|
*
|
|
* virt. Pin: 3D mix mono ---> V ---> M ---> 1+-----+
|
|
* | MUX |0----> (MonoOut)
|
|
* Mic (after AGC) ---> V ---> M ---> 2+-----+
|
|
*
|
|
*
|
|
* Mic (after AGC) ----> V ----> M -----> (MicIn)
|
|
*
|
|
*----------------------------------------------------------------------------
|
|
*
|
|
* As you can see, the exposed topology is somewhat different from the real AC97
|
|
* topology. This is because the system that translates the topology to "mixer
|
|
* lines" gets confused if it has to deal with all the mess. So we have to make it
|
|
* plain and simple for the system.
|
|
* Some issues block us from exposing a nice plain and simple topology. The prg.
|
|
* which displayes the "Volume Control Panel" (sndvol32) does _only_ display
|
|
* Volumes, Mutes (only one "in a row"), Treble, Bass, Loudness and AGC under
|
|
* Advanced control panel. We don't have 3D controls, and before we go into a
|
|
* Muxer, there has to be Volume controls in front.
|
|
* So what do we do?
|
|
* 1) We fake 3D controls as Volume controls. The Mutes represent 3D bypass and
|
|
* 3D on/off
|
|
* 2) All inputs (including the 3D controls) go staight into a SUM. Important is
|
|
* that there are not 2 Volumes, Mutes in a row, e.g. ---> V ---> M ---> V ---> M
|
|
* In that case, only one Volume/Mute would be displayed.
|
|
* 3) We can't make a connection from the tone controls to the Wave In muxer (even
|
|
* with Volumes in front), so we create fake pins that we name user friendly.
|
|
* Same with the connection from the 3D mixer to the Mono output.
|
|
* 4) We discard all supermixer controls that would convert stereo to mono or vice
|
|
* versa. Instead, we just connect the lines and when the control is queried we
|
|
* fail a right channel request (mono has only left channel).
|
|
* 5) We have to make virtual volume and mute controls in front of each muxer.
|
|
* As you can see, these controls can be mono or stereo and there is only one
|
|
* HW register for them, so we have to cache the values and prg. the register
|
|
* each time the select changes or the selected volume control changes.
|
|
*/
|
|
|
|
/*****************************************************************************
|
|
* CMiniportTopologyICH::BuildTopology
|
|
*****************************************************************************
|
|
* Builds the topology descriptors based on hardware configuration info
|
|
* obtained from the adapter.
|
|
*/
|
|
NTSTATUS CMiniportTopologyICH::BuildTopology (void)
|
|
{
|
|
PAGED_CODE ();
|
|
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
|
|
DOUT (DBG_PRINT, ("[CMiniportTopologyICH::BuildTopology]"));
|
|
|
|
// allocate our filter descriptor
|
|
FilterDescriptor = (PPCFILTER_DESCRIPTOR) ExAllocatePool (PagedPool,
|
|
sizeof(PCFILTER_DESCRIPTOR));
|
|
if (FilterDescriptor)
|
|
{
|
|
// clear out the filter descriptor
|
|
RtlZeroMemory (FilterDescriptor, sizeof(PCFILTER_DESCRIPTOR));
|
|
|
|
#ifdef INCLUDE_PRIVATE_PROPERTY
|
|
// Set the Filter automation table.
|
|
FilterDescriptor->AutomationTable = &FilterAutomationPrivate;
|
|
#endif
|
|
|
|
// build the pin list
|
|
ntStatus = BuildPinDescriptors ();
|
|
if (NT_SUCCESS (ntStatus))
|
|
{
|
|
// build the node list
|
|
ntStatus = BuildNodeDescriptors ();
|
|
if (NT_SUCCESS (ntStatus))
|
|
{
|
|
// build the connection list
|
|
ntStatus = BuildConnectionDescriptors ();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
// that's whatever one of these build... functions returned.
|
|
return ntStatus;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* CMiniportTopologyICH::BuildPinDescriptors
|
|
*****************************************************************************
|
|
* Builds the topology pin descriptors.
|
|
*/
|
|
NTSTATUS CMiniportTopologyICH::BuildPinDescriptors (void)
|
|
{
|
|
// Improvement would be to not use a Macro, use (inline) function instead.
|
|
#define INIT_PIN( pin, pinptr, category, name, index ) \
|
|
pinptr->KsPinDescriptor.Category = (GUID*) category; \
|
|
pinptr->KsPinDescriptor.Name = (GUID*) name; \
|
|
SetPinTranslation (index++, pin); \
|
|
pinptr++
|
|
|
|
PAGED_CODE ();
|
|
|
|
ULONG Index;
|
|
PPCPIN_DESCRIPTOR CurrentPin;
|
|
|
|
DOUT (DBG_PRINT, ("[CMiniportTopologyICH::BuildPinDescriptors]"));
|
|
|
|
// allocate our descriptor memory
|
|
PinDescriptors = PPCPIN_DESCRIPTOR (ExAllocatePool (PagedPool,
|
|
PIN_TOP_ELEMENT * sizeof(PCPIN_DESCRIPTOR)));
|
|
if (!PinDescriptors)
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
//
|
|
// set default pin descriptor parameters
|
|
//
|
|
RtlZeroMemory (PinDescriptors, PIN_TOP_ELEMENT * sizeof(PCPIN_DESCRIPTOR));
|
|
|
|
// spend some more time and set the pin descriptors to expected values.
|
|
for (CurrentPin = PinDescriptors, Index = 0; Index < PIN_TOP_ELEMENT;
|
|
CurrentPin++, Index++)
|
|
{
|
|
CurrentPin->KsPinDescriptor.DataRangesCount = SIZEOF_ARRAY(PinDataRangePointersAnalogBridge);
|
|
CurrentPin->KsPinDescriptor.DataRanges = PinDataRangePointersAnalogBridge;
|
|
CurrentPin->KsPinDescriptor.DataFlow = KSPIN_DATAFLOW_IN;
|
|
CurrentPin->KsPinDescriptor.Communication = KSPIN_COMMUNICATION_NONE;
|
|
}
|
|
|
|
//
|
|
// modify the individual pin descriptors
|
|
//
|
|
CurrentPin = PinDescriptors;
|
|
Index = 0;
|
|
|
|
// add the PIN_WAVEOUT_SOURCE pin descriptor (not optional)
|
|
INIT_PIN (PIN_WAVEOUT_SOURCE,
|
|
CurrentPin,
|
|
&KSCATEGORY_AUDIO,
|
|
NULL,
|
|
Index);
|
|
|
|
// add the PIN_PCBEEP_SOURCE pin descriptor (optional)
|
|
if (AdapterCommon->GetPinConfig (PINC_PCBEEP_PRESENT))
|
|
{
|
|
INIT_PIN (PIN_PCBEEP_SOURCE,
|
|
CurrentPin,
|
|
&KSNODETYPE_SPEAKER,
|
|
&KSAUDFNAME_PC_SPEAKER,
|
|
Index);
|
|
}
|
|
|
|
// add the PIN_PHONE_SOURCE pin descriptor (optional)
|
|
if (AdapterCommon->GetPinConfig (PINC_PHONE_PRESENT))
|
|
{
|
|
INIT_PIN (PIN_PHONE_SOURCE,
|
|
CurrentPin,
|
|
&KSNODETYPE_PHONE_LINE,
|
|
NULL,
|
|
Index);
|
|
}
|
|
|
|
// add the PIN_MIC_SOURCE pin descriptor (could be disabled)
|
|
if (AdapterCommon->GetPinConfig (PINC_MIC_PRESENT))
|
|
{
|
|
INIT_PIN (PIN_MIC_SOURCE,
|
|
CurrentPin,
|
|
&KSNODETYPE_MICROPHONE,
|
|
NULL,
|
|
Index);
|
|
}
|
|
|
|
// add the PIN_LINEIN_SOURCE pin descriptor (could be disabled)
|
|
if (AdapterCommon->GetPinConfig (PINC_LINEIN_PRESENT))
|
|
{
|
|
INIT_PIN (PIN_LINEIN_SOURCE,
|
|
CurrentPin,
|
|
&KSNODETYPE_LINE_CONNECTOR,
|
|
&KSAUDFNAME_LINE_IN,
|
|
Index);
|
|
}
|
|
|
|
// add the PIN_CD_SOURCE pin descriptor (could be disabled)
|
|
if (AdapterCommon->GetPinConfig (PINC_CD_PRESENT))
|
|
{
|
|
INIT_PIN (PIN_CD_SOURCE,
|
|
CurrentPin,
|
|
&KSNODETYPE_CD_PLAYER,
|
|
&KSAUDFNAME_CD_AUDIO,
|
|
Index);
|
|
}
|
|
|
|
// add the PIN_VIDEO_SOURCE pin descriptor (optional)
|
|
if (AdapterCommon->GetPinConfig (PINC_VIDEO_PRESENT))
|
|
{
|
|
INIT_PIN (PIN_VIDEO_SOURCE,
|
|
CurrentPin,
|
|
&KSNODETYPE_ANALOG_CONNECTOR,
|
|
&KSAUDFNAME_VIDEO,
|
|
Index);
|
|
}
|
|
|
|
// add the PIN_AUX_SOURCE pin descriptor (optional)
|
|
if (AdapterCommon->GetPinConfig (PINC_AUX_PRESENT))
|
|
{
|
|
INIT_PIN (PIN_AUX_SOURCE,
|
|
CurrentPin,
|
|
&KSNODETYPE_ANALOG_CONNECTOR,
|
|
&KSAUDFNAME_AUX,
|
|
Index);
|
|
}
|
|
|
|
// add the PIN_VIRT_TONE_MIX_SOURCE pin descriptor (not optional)
|
|
INIT_PIN (PIN_VIRT_TONE_MIX_SOURCE,
|
|
CurrentPin,
|
|
&KSNODETYPE_ANALOG_CONNECTOR,
|
|
&KSAUDFNAME_STEREO_MIX,
|
|
Index);
|
|
|
|
// add the PIN_VIRT_TONE_MIX_MONO_SOURCE pin descriptor (not optional)
|
|
INIT_PIN (PIN_VIRT_TONE_MIX_MONO_SOURCE,
|
|
CurrentPin,
|
|
&KSNODETYPE_ANALOG_CONNECTOR,
|
|
&KSAUDFNAME_MONO_MIX,
|
|
Index);
|
|
|
|
// create a virt. pin for the 3D controls
|
|
if (AdapterCommon->GetNodeConfig (NODEC_3D_PRESENT))
|
|
{
|
|
if (AdapterCommon->GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE))
|
|
{
|
|
INIT_PIN (PIN_VIRT_3D_CENTER_SOURCE,
|
|
CurrentPin,
|
|
&KSNODETYPE_ANALOG_CONNECTOR,
|
|
&KSAUDFNAME_3D_CENTER,
|
|
Index);
|
|
}
|
|
|
|
// A weird way would be to have 3D but only fixed sliders. In that case,
|
|
// display one fixed slider (3D depth).
|
|
if (AdapterCommon->GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE) ||
|
|
(!AdapterCommon->GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE) &&
|
|
!AdapterCommon->GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE)))
|
|
{
|
|
INIT_PIN (PIN_VIRT_3D_DEPTH_SOURCE,
|
|
CurrentPin,
|
|
&KSNODETYPE_ANALOG_CONNECTOR,
|
|
&KSAUDFNAME_3D_DEPTH,
|
|
Index);
|
|
}
|
|
}
|
|
|
|
// Add a "Front speaker" pin if we have multichannel or headphones.
|
|
// We use a master mono then ...
|
|
if (AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT) ||
|
|
AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
|
|
{
|
|
// Add a "Front speaker" pin, because in multichannel we want
|
|
// to display a master mono that effects all channels.
|
|
INIT_PIN (PIN_VIRT_FRONT_SOURCE,
|
|
CurrentPin,
|
|
&KSNODETYPE_ANALOG_CONNECTOR,
|
|
&ICHFNAME_FRONT,
|
|
Index);
|
|
}
|
|
|
|
// check for multichannel
|
|
if (AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT))
|
|
{
|
|
// Add the Rear Speaker Volume pin.
|
|
INIT_PIN (PIN_VIRT_SURROUND_SOURCE,
|
|
CurrentPin,
|
|
&KSNODETYPE_ANALOG_CONNECTOR,
|
|
&ICHFNAME_SURROUND,
|
|
Index);
|
|
|
|
// add the Center Volume pin if we support at least 6 channel.
|
|
if (AdapterCommon->GetPinConfig (PINC_CENTER_LFE_PRESENT))
|
|
{
|
|
INIT_PIN (PIN_VIRT_CENTER_SOURCE,
|
|
CurrentPin,
|
|
&KSNODETYPE_ANALOG_CONNECTOR,
|
|
&ICHFNAME_CENTER,
|
|
Index);
|
|
|
|
INIT_PIN (PIN_VIRT_LFE_SOURCE,
|
|
CurrentPin,
|
|
&KSNODETYPE_ANALOG_CONNECTOR,
|
|
&ICHFNAME_LFE,
|
|
Index);
|
|
}
|
|
}
|
|
|
|
// add the PIN_MASTEROUT_DEST pin descriptor (not optional)
|
|
CurrentPin->KsPinDescriptor.DataFlow = KSPIN_DATAFLOW_OUT;
|
|
INIT_PIN (PIN_MASTEROUT_DEST,
|
|
CurrentPin,
|
|
&KSNODETYPE_SPEAKER,
|
|
&KSAUDFNAME_VOLUME_CONTROL,
|
|
Index);
|
|
|
|
// add the PIN_HPOUT_SOURCE pin descriptor (optional)
|
|
if (AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
|
|
{
|
|
INIT_PIN (PIN_HPOUT_SOURCE,
|
|
CurrentPin,
|
|
&KSNODETYPE_HEADPHONES,
|
|
NULL,
|
|
Index);
|
|
}
|
|
|
|
// add the PIN_WAVEIN_DEST pin descriptor (not optional)
|
|
CurrentPin->KsPinDescriptor.DataFlow = KSPIN_DATAFLOW_OUT;
|
|
INIT_PIN (PIN_WAVEIN_DEST,
|
|
CurrentPin,
|
|
&KSCATEGORY_AUDIO,
|
|
NULL,
|
|
Index);
|
|
|
|
// add the PIN_MICIN_DEST pin descriptor (optional)
|
|
if (AdapterCommon->GetPinConfig (PINC_MICIN_PRESENT) &&
|
|
AdapterCommon->GetPinConfig (PINC_MIC_PRESENT))
|
|
{
|
|
CurrentPin->KsPinDescriptor.DataFlow = KSPIN_DATAFLOW_OUT;
|
|
INIT_PIN (PIN_MICIN_DEST,
|
|
CurrentPin,
|
|
&KSCATEGORY_AUDIO,
|
|
NULL,
|
|
Index);
|
|
}
|
|
|
|
// add the PIN_MONOOUT_DEST pin descriptor (optional)
|
|
if (AdapterCommon->GetPinConfig (PINC_MONOOUT_PRESENT))
|
|
{
|
|
// add the PIN_VIRT_3D_MIX_MONO_SOURCE pin descriptor
|
|
INIT_PIN (PIN_VIRT_3D_MIX_MONO_SOURCE,
|
|
CurrentPin,
|
|
&KSNODETYPE_ANALOG_CONNECTOR,
|
|
&KSAUDFNAME_MONO_MIX,
|
|
Index);
|
|
|
|
CurrentPin->KsPinDescriptor.DataFlow = KSPIN_DATAFLOW_OUT;
|
|
// and the normal output pin
|
|
INIT_PIN (PIN_MONOOUT_DEST,
|
|
CurrentPin,
|
|
&KSNODETYPE_PHONE_LINE,
|
|
&KSAUDFNAME_MONO_OUT,
|
|
Index);
|
|
}
|
|
|
|
// add the pin descriptor informatin to the filter descriptor
|
|
FilterDescriptor->PinCount = Index;
|
|
FilterDescriptor->PinSize = sizeof (PCPIN_DESCRIPTOR);
|
|
FilterDescriptor->Pins = PinDescriptors;
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
#undef INIT_PIN
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* CMiniportTopologyICH::BuildNodeDescriptors
|
|
*****************************************************************************
|
|
* Builds the topology node descriptors.
|
|
*/
|
|
NTSTATUS CMiniportTopologyICH::BuildNodeDescriptors (void)
|
|
{
|
|
// Improvement would be to not use a Macro, use (inline) function instead.
|
|
#define INIT_NODE( node, nodeptr, type, name, automation, index ) \
|
|
nodeptr->Type = (GUID*) type; \
|
|
nodeptr->Name = (GUID*) name; \
|
|
nodeptr->AutomationTable = automation; \
|
|
SetNodeTranslation (index++, node); \
|
|
nodeptr++
|
|
|
|
PAGED_CODE ();
|
|
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
|
|
DOUT (DBG_PRINT, ("[CMiniportTopologyICH::BuildNodeDescriptors]"));
|
|
|
|
// allocate our descriptor memory
|
|
NodeDescriptors = PPCNODE_DESCRIPTOR (ExAllocatePool (PagedPool,
|
|
NODE_TOP_ELEMENT * sizeof(PCNODE_DESCRIPTOR)));
|
|
if (NodeDescriptors)
|
|
{
|
|
PPCNODE_DESCRIPTOR CurrentNode = NodeDescriptors;
|
|
ULONG Index = 0;
|
|
|
|
//
|
|
// set default node descriptor parameters
|
|
//
|
|
RtlZeroMemory (NodeDescriptors, NODE_TOP_ELEMENT *
|
|
sizeof(PCNODE_DESCRIPTOR));
|
|
|
|
// We don't have loopback mode currently. It is only used for testing anyway.
|
|
|
|
// Add the NODE_WAVEOUT_VOLUME node
|
|
INIT_NODE (NODE_WAVEOUT_VOLUME,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_WAVE_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// add the NODE_WAVEOUT_MUTE node
|
|
INIT_NODE (NODE_WAVEOUT_MUTE,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUTE,
|
|
&KSAUDFNAME_WAVE_MUTE,
|
|
&AutomationMute,
|
|
Index);
|
|
|
|
// add the PCBEEP nodes
|
|
if (AdapterCommon->GetPinConfig (PINC_PCBEEP_PRESENT))
|
|
{
|
|
// add the NODE_PCBEEP_VOLUME node
|
|
INIT_NODE (NODE_PCBEEP_VOLUME,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_PC_SPEAKER_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// add the NODE_PCBEEP_MUTE node
|
|
INIT_NODE (NODE_PCBEEP_MUTE,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUTE,
|
|
&KSAUDFNAME_PC_SPEAKER_MUTE,
|
|
&AutomationMute,
|
|
Index);
|
|
}
|
|
|
|
// add the PHONE nodes
|
|
if (AdapterCommon->GetPinConfig (PINC_PHONE_PRESENT))
|
|
{
|
|
// add the NODE_PHONE_VOLUME node
|
|
INIT_NODE (NODE_PHONE_VOLUME,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&ICHFNAME_PHONE_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// add the NODE_PHONE_MUTE node
|
|
INIT_NODE (NODE_PHONE_MUTE,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUTE,
|
|
&ICHFNAME_PHONE_MUTE,
|
|
&AutomationMute,
|
|
Index);
|
|
}
|
|
|
|
// add the MIC nodes
|
|
if (AdapterCommon->GetPinConfig (PINC_MIC_PRESENT))
|
|
{
|
|
if (AdapterCommon->GetPinConfig (PINC_MIC2_PRESENT))
|
|
{
|
|
// add the NODE_MIC_SELECT node
|
|
INIT_NODE (NODE_MIC_SELECT,
|
|
CurrentNode,
|
|
&KSNODETYPE_LOUDNESS,
|
|
&KSAUDFNAME_ALTERNATE_MICROPHONE,
|
|
&AutomationSpecial,
|
|
Index);
|
|
}
|
|
|
|
// add the NODE_MIC_BOOST node
|
|
INIT_NODE (NODE_MIC_BOOST,
|
|
CurrentNode,
|
|
&KSNODETYPE_AGC,
|
|
&KSAUDFNAME_MICROPHONE_BOOST,
|
|
&AutomationSpecial,
|
|
Index);
|
|
|
|
// add the NODE_MIC_VOLUME node
|
|
INIT_NODE (NODE_MIC_VOLUME,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_MIC_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// add the NODE_MIC_MUTE node
|
|
INIT_NODE (NODE_MIC_MUTE,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUTE,
|
|
&KSAUDFNAME_MIC_MUTE,
|
|
&AutomationMute,
|
|
Index);
|
|
}
|
|
|
|
if (AdapterCommon->GetPinConfig (PINC_LINEIN_PRESENT))
|
|
{
|
|
// add the NODE_LINEIN_VOLUME node
|
|
INIT_NODE (NODE_LINEIN_VOLUME,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_LINE_IN_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// add the NODE_LINEIN_MUTE node
|
|
INIT_NODE (NODE_LINEIN_MUTE,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUTE,
|
|
&ICHFNAME_LINEIN_MUTE,
|
|
&AutomationMute,
|
|
Index);
|
|
}
|
|
|
|
if (AdapterCommon->GetPinConfig (PINC_CD_PRESENT))
|
|
{
|
|
// add the NODE_CD_VOLUME node
|
|
INIT_NODE (NODE_CD_VOLUME,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_CD_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// add the NODE_CD_MUTE node
|
|
INIT_NODE (NODE_CD_MUTE,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUTE,
|
|
&KSAUDFNAME_CD_MUTE,
|
|
&AutomationMute,
|
|
Index);
|
|
}
|
|
|
|
// add the VIDEO nodes
|
|
if (AdapterCommon->GetPinConfig (PINC_VIDEO_PRESENT))
|
|
{
|
|
// add the NODE_VIDEO_VOLUME node
|
|
INIT_NODE (NODE_VIDEO_VOLUME,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_VIDEO_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// add the NODE_VIDEO_MUTE node
|
|
INIT_NODE (NODE_VIDEO_MUTE,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUTE,
|
|
&KSAUDFNAME_VIDEO_MUTE,
|
|
&AutomationMute,
|
|
Index);
|
|
}
|
|
|
|
// add the AUX nodes
|
|
if (AdapterCommon->GetPinConfig (PINC_AUX_PRESENT))
|
|
{
|
|
// add the NODE_AUX_VOLUME node
|
|
INIT_NODE (NODE_AUX_VOLUME,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_AUX_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// add the NODE_AUX_MUTE node
|
|
INIT_NODE (NODE_AUX_MUTE,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUTE,
|
|
&KSAUDFNAME_AUX_MUTE,
|
|
&AutomationMute,
|
|
Index);
|
|
}
|
|
|
|
// add the NODE_MAIN_MIX node
|
|
INIT_NODE (NODE_MAIN_MIX,
|
|
CurrentNode,
|
|
&KSNODETYPE_SUM,
|
|
&ICHFNAME_MAIN_MIX,
|
|
NULL,
|
|
Index);
|
|
|
|
// add the 3D nodes
|
|
if (AdapterCommon->GetNodeConfig (NODEC_3D_PRESENT))
|
|
{
|
|
if (AdapterCommon->GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE))
|
|
{
|
|
// add the NODE_VIRT_3D_CENTER node
|
|
INIT_NODE (NODE_VIRT_3D_CENTER,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_3D_CENTER,
|
|
&Automation3D,
|
|
Index);
|
|
}
|
|
|
|
if (AdapterCommon->GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE) ||
|
|
(!AdapterCommon->GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE) &&
|
|
!AdapterCommon->GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE)))
|
|
{
|
|
// add the NODE_VIRT_3D_DEPTH node
|
|
INIT_NODE (NODE_VIRT_3D_DEPTH,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_3D_DEPTH,
|
|
&Automation3D,
|
|
Index);
|
|
}
|
|
|
|
// add the NODE_VIRT_3D_ENABLE node
|
|
INIT_NODE (NODE_VIRT_3D_ENABLE,
|
|
CurrentNode,
|
|
&KSNODETYPE_LOUDNESS,
|
|
&ICHFNAME_3D_ENABLE,
|
|
&AutomationSpecial,
|
|
Index);
|
|
|
|
// add the NODE_VIRT_WAVEOUT_3D_BYPASS node
|
|
INIT_NODE (NODE_VIRT_WAVEOUT_3D_BYPASS,
|
|
CurrentNode,
|
|
&KSNODETYPE_AGC,
|
|
&ICHFNAME_WAVEOUT_3D_BYPASS,
|
|
&AutomationSpecial,
|
|
Index);
|
|
}
|
|
|
|
if (AdapterCommon->GetPinConfig (PINC_PCBEEP_PRESENT) ||
|
|
AdapterCommon->GetPinConfig (PINC_PHONE_PRESENT))
|
|
{
|
|
// add the NODE_BEEP_MIX node
|
|
INIT_NODE (NODE_BEEP_MIX,
|
|
CurrentNode,
|
|
&KSNODETYPE_SUM,
|
|
&ICHFNAME_BEEP_MIX,
|
|
NULL,
|
|
Index);
|
|
}
|
|
|
|
// add the tone nodes
|
|
if (AdapterCommon->GetNodeConfig (NODEC_TONE_PRESENT))
|
|
{
|
|
// add the NODE_BASS node
|
|
INIT_NODE (NODE_BASS,
|
|
CurrentNode,
|
|
&KSNODETYPE_TONE,
|
|
&KSAUDFNAME_BASS,
|
|
&AutomationTone,
|
|
Index);
|
|
|
|
// add the NODE_TREBLE node
|
|
INIT_NODE (NODE_TREBLE,
|
|
CurrentNode,
|
|
&KSNODETYPE_TONE,
|
|
&KSAUDFNAME_TREBLE,
|
|
&AutomationTone,
|
|
Index);
|
|
|
|
if (AdapterCommon->GetNodeConfig (NODEC_LOUDNESS_PRESENT))
|
|
{
|
|
// add the NODE_LOUDNESS node
|
|
INIT_NODE (NODE_LOUDNESS,
|
|
CurrentNode,
|
|
&KSNODETYPE_LOUDNESS,
|
|
NULL,
|
|
&AutomationSpecial,
|
|
Index);
|
|
}
|
|
|
|
if (AdapterCommon->GetNodeConfig (NODEC_SIMUL_STEREO_PRESENT))
|
|
{
|
|
// add the NODE_SIMUL_STEREO node
|
|
INIT_NODE (NODE_SIMUL_STEREO,
|
|
CurrentNode,
|
|
&KSNODETYPE_AGC,
|
|
&ICHFNAME_SIMUL_STEREO,
|
|
&AutomationSpecial,
|
|
Index);
|
|
}
|
|
}
|
|
|
|
// Add a "Front Speaker" volume/mute if we have surround or headphones.
|
|
// The "Master" volume/mute will be mono then
|
|
if (AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT) ||
|
|
AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
|
|
{
|
|
// Add the front speaker volume.
|
|
INIT_NODE (NODE_FRONT_VOLUME,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&ICHFNAME_FRONT_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// Add the front speaker mute.
|
|
INIT_NODE (NODE_FRONT_MUTE,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUTE,
|
|
&ICHFNAME_FRONT_MUTE,
|
|
&AutomationMute,
|
|
Index);
|
|
|
|
// Add the master mono out volume.
|
|
INIT_NODE (NODE_VIRT_MASTERMONO_VOLUME,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_MASTER_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// Add the master mono out volume.
|
|
INIT_NODE (NODE_VIRT_MASTERMONO_MUTE,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUTE,
|
|
&KSAUDFNAME_MASTER_MUTE,
|
|
&AutomationMute,
|
|
Index);
|
|
}
|
|
else
|
|
{
|
|
// add the NODE_MASTEROUT_VOLUME node
|
|
INIT_NODE (NODE_MASTEROUT_VOLUME,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_MASTER_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// add the NODE_MASTEROUT_MUTE node
|
|
INIT_NODE (NODE_MASTEROUT_MUTE,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUTE,
|
|
&KSAUDFNAME_MASTER_MUTE,
|
|
&AutomationMute,
|
|
Index);
|
|
}
|
|
|
|
// Add the surround control if we have one.
|
|
if (AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT))
|
|
{
|
|
// Add the surround volume.
|
|
INIT_NODE (NODE_SURROUND_VOLUME,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&ICHFNAME_SURROUND_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// Add the surround mute.
|
|
INIT_NODE (NODE_SURROUND_MUTE,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUTE,
|
|
&ICHFNAME_SURROUND_MUTE,
|
|
&AutomationMute,
|
|
Index);
|
|
|
|
// Add the center and LFE control if we have one.
|
|
if (AdapterCommon->GetPinConfig (PINC_CENTER_LFE_PRESENT))
|
|
{
|
|
// Add the center volume.
|
|
INIT_NODE (NODE_CENTER_VOLUME,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&ICHFNAME_CENTER_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// Add the center mute.
|
|
INIT_NODE (NODE_CENTER_MUTE,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUTE,
|
|
&ICHFNAME_CENTER_MUTE,
|
|
&AutomationMute,
|
|
Index);
|
|
|
|
// Add the LFE volume.
|
|
INIT_NODE (NODE_LFE_VOLUME,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&ICHFNAME_LFE_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// Add the LFE mute.
|
|
INIT_NODE (NODE_LFE_MUTE,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUTE,
|
|
&ICHFNAME_LFE_MUTE,
|
|
&AutomationMute,
|
|
Index);
|
|
}
|
|
}
|
|
|
|
// add the HPOUT nodes
|
|
if (AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
|
|
{
|
|
// add the NODE_HPOUT_VOLUME node
|
|
INIT_NODE (NODE_HPOUT_VOLUME,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&ICHFNAME_HPOUT_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// add the NODE_HPOUT_MUTE node
|
|
INIT_NODE (NODE_HPOUT_MUTE,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUTE,
|
|
&ICHFNAME_HPOUT_MUTE,
|
|
&AutomationMute,
|
|
Index);
|
|
}
|
|
|
|
// add the NODE_WAVEIN_SELECT node
|
|
INIT_NODE (NODE_WAVEIN_SELECT,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUX,
|
|
&ICHFNAME_WAVEIN_SELECT,
|
|
&AutomationMux,
|
|
Index);
|
|
|
|
if (AdapterCommon->GetPinConfig (PINC_MIC_PRESENT))
|
|
{
|
|
// add the NODE_VIRT_MASTER_INPUT_VOLUME1 node
|
|
INIT_NODE (NODE_VIRT_MASTER_INPUT_VOLUME1,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_MIC_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
}
|
|
|
|
if (AdapterCommon->GetPinConfig (PINC_CD_PRESENT))
|
|
{
|
|
// add the NODE_VIRT_MASTER_INPUT_VOLUME2 node
|
|
INIT_NODE (NODE_VIRT_MASTER_INPUT_VOLUME2,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_CD_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
}
|
|
|
|
if (AdapterCommon->GetPinConfig (PINC_VIDEO_PRESENT))
|
|
{
|
|
// add the NODE_VIRT_MASTER_INPUT_VOLUME3 node
|
|
INIT_NODE (NODE_VIRT_MASTER_INPUT_VOLUME3,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_VIDEO_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
}
|
|
|
|
if (AdapterCommon->GetPinConfig (PINC_AUX_PRESENT))
|
|
{
|
|
// add the NODE_VIRT_MASTER_INPUT_VOLUME4 node
|
|
INIT_NODE (NODE_VIRT_MASTER_INPUT_VOLUME4,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_AUX_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
}
|
|
|
|
if (AdapterCommon->GetPinConfig (PINC_LINEIN_PRESENT))
|
|
{
|
|
// add the NODE_VIRT_MASTER_INPUT_VOLUME5 node
|
|
INIT_NODE (NODE_VIRT_MASTER_INPUT_VOLUME5,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_LINE_IN_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
}
|
|
|
|
// add the NODE_VIRT_MASTER_INPUT_VOLUME6 node
|
|
INIT_NODE (NODE_VIRT_MASTER_INPUT_VOLUME6,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_STEREO_MIX_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// add the NODE_VIRT_MASTER_INPUT_VOLUME7 node
|
|
INIT_NODE (NODE_VIRT_MASTER_INPUT_VOLUME7,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_MONO_MIX_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
if (AdapterCommon->GetPinConfig (PINC_PHONE_PRESENT))
|
|
{
|
|
// add the NODE_VIRT_MASTER_INPUT_VOLUME8 node
|
|
INIT_NODE (NODE_VIRT_MASTER_INPUT_VOLUME8,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&ICHFNAME_MASTER_INPUT_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
}
|
|
|
|
// add the MICIN nodes
|
|
if (AdapterCommon->GetPinConfig (PINC_MIC_PRESENT) &&
|
|
AdapterCommon->GetPinConfig (PINC_MICIN_PRESENT))
|
|
{
|
|
// add the NODE_MICIN_VOLUME node
|
|
INIT_NODE (NODE_MICIN_VOLUME,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&ICHFNAME_MICIN_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// add the NODE_MICIN_MUTE node
|
|
INIT_NODE (NODE_MICIN_MUTE,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUTE,
|
|
&ICHFNAME_MICIN_MUTE,
|
|
&AutomationMute,
|
|
Index);
|
|
}
|
|
|
|
// add the MONOOUT nodes
|
|
if (AdapterCommon->GetPinConfig (PINC_MONOOUT_PRESENT))
|
|
{
|
|
// add the NODE_MONOOUT_SELECT node
|
|
INIT_NODE (NODE_MONOOUT_SELECT,
|
|
CurrentNode,
|
|
&KSNODETYPE_MUX,
|
|
&ICHFNAME_MONOOUT_SELECT,
|
|
&AutomationMux,
|
|
Index);
|
|
|
|
// add the NODE_VIRT_MONOOUT_VOLUME1 node
|
|
INIT_NODE (NODE_VIRT_MONOOUT_VOLUME1,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_MONO_MIX_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
|
|
// add the NODE_VIRT_MONOOUT_VOLUME2 node
|
|
INIT_NODE (NODE_VIRT_MONOOUT_VOLUME2,
|
|
CurrentNode,
|
|
&KSNODETYPE_VOLUME,
|
|
&KSAUDFNAME_MIC_VOLUME,
|
|
&AutomationVolume,
|
|
Index);
|
|
}
|
|
|
|
// add the nodes to the filter descriptor
|
|
FilterDescriptor->NodeCount = Index;
|
|
FilterDescriptor->NodeSize = sizeof(PCNODE_DESCRIPTOR);
|
|
FilterDescriptor->Nodes = NodeDescriptors;
|
|
}
|
|
else
|
|
{
|
|
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
return ntStatus;
|
|
|
|
#undef INIT_NODE
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* CMiniportTopologyICH::BuildConnectionDescriptors
|
|
*****************************************************************************
|
|
* Builds the topology connection descriptors.
|
|
*/
|
|
NTSTATUS CMiniportTopologyICH::BuildConnectionDescriptors (void)
|
|
{
|
|
// Improvement would be to not use a Macro, use (inline) function instead.
|
|
|
|
// for node to node connections
|
|
#define INIT_NN_CONN( cptr, fnode, fpin, tnode, tpin ) \
|
|
cptr->FromNode = TransNodeDefToNodeNr (fnode); \
|
|
cptr->FromNodePin = fpin; \
|
|
cptr->ToNode = TransNodeDefToNodeNr (tnode); \
|
|
cptr->ToNodePin = tpin; \
|
|
cptr++,ConnectionCount++
|
|
|
|
// for filter pin to node connections
|
|
#define INIT_FN_CONN( cptr, fpin, tnode, tpin ) \
|
|
cptr->FromNode = KSFILTER_NODE; \
|
|
cptr->FromNodePin = TransPinDefToPinNr (fpin); \
|
|
cptr->ToNode = TransNodeDefToNodeNr (tnode); \
|
|
cptr->ToNodePin = tpin; \
|
|
cptr++,ConnectionCount++
|
|
|
|
// for node to filter pin connections
|
|
#define INIT_NF_CONN( cptr, fnode, fpin, tpin ) \
|
|
cptr->FromNode = TransNodeDefToNodeNr (fnode); \
|
|
cptr->FromNodePin = fpin; \
|
|
cptr->ToNode = KSFILTER_NODE; \
|
|
cptr->ToNodePin = TransPinDefToPinNr (tpin); \
|
|
cptr++,ConnectionCount++
|
|
|
|
PAGED_CODE ();
|
|
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
ULONG ConnectionCount = 0;
|
|
|
|
DOUT (DBG_PRINT, ("[CMiniportTopologyICH::BuildConnectionDescriptors]"));
|
|
|
|
// allocate our descriptor memory
|
|
ConnectionDescriptors = PPCCONNECTION_DESCRIPTOR (ExAllocatePool (PagedPool,
|
|
TOPO_MAX_CONNECTIONS * sizeof(PCCONNECTION_DESCRIPTOR)));
|
|
if (ConnectionDescriptors)
|
|
{
|
|
PPCCONNECTION_DESCRIPTOR CurrentConnection = ConnectionDescriptors;
|
|
|
|
// build the wave out (coming in) path
|
|
|
|
// PIN_WAVEOUT_SOURCE -> NODE_WAVEOUT_VOLUME
|
|
INIT_FN_CONN (CurrentConnection, PIN_WAVEOUT_SOURCE, NODE_WAVEOUT_VOLUME, 1);
|
|
|
|
// NODE_WAVEOUT_VOLUME -> NODE_WAVEOUT_MUTE
|
|
INIT_NN_CONN (CurrentConnection, NODE_WAVEOUT_VOLUME, 0, NODE_WAVEOUT_MUTE, 1);
|
|
|
|
// NODE_WAVEOUT_MUTE -> NODE_MAIN_MIX
|
|
INIT_NN_CONN (CurrentConnection, NODE_WAVEOUT_MUTE, 0, NODE_MAIN_MIX, 1);
|
|
|
|
// build the PC beeper path
|
|
if (AdapterCommon->GetPinConfig (PINC_PCBEEP_PRESENT))
|
|
{
|
|
// PIN_PCBEEP_SOURCE -> NODE_PCBEEP_VOLUME
|
|
INIT_FN_CONN (CurrentConnection, PIN_PCBEEP_SOURCE, NODE_PCBEEP_VOLUME, 1);
|
|
|
|
// NODE_PCBEEP_VOLUME -> NODE_PCBEEP_MUTE
|
|
INIT_NN_CONN (CurrentConnection, NODE_PCBEEP_VOLUME, 0, NODE_PCBEEP_MUTE, 1);
|
|
|
|
// NODE_PCBEEP_MUTE -> NODE_BEEP_MIX
|
|
INIT_NN_CONN (CurrentConnection, NODE_PCBEEP_MUTE, 0, NODE_BEEP_MIX, 2);
|
|
}
|
|
|
|
// build the phone path
|
|
if (AdapterCommon->GetPinConfig (PINC_PHONE_PRESENT))
|
|
{
|
|
// PIN_PHONE_SOURCE -> NODE_PHONE_VOLUME
|
|
INIT_FN_CONN (CurrentConnection, PIN_PHONE_SOURCE, NODE_PHONE_VOLUME, 1);
|
|
|
|
// NODE_PHONE_VOLUME -> NODE_PHONE_MUTE
|
|
INIT_NN_CONN (CurrentConnection, NODE_PHONE_VOLUME, 0, NODE_PHONE_MUTE, 1);
|
|
|
|
// NODE_PHONE_MUTE -> LINEOUT_BEEP_MIX
|
|
INIT_NN_CONN (CurrentConnection, NODE_PHONE_MUTE, 0, NODE_BEEP_MIX, 3);
|
|
|
|
// PIN_PHONE_SOURCE pin -> NODE_VIRT_MASTER_INPUT_VOLUME8
|
|
INIT_FN_CONN (CurrentConnection, PIN_PHONE_SOURCE, NODE_VIRT_MASTER_INPUT_VOLUME8, 1);
|
|
|
|
// NODE_VIRT_MASTER_INPUT_VOLUME8 -> NODE_WAVEIN_SELECT
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTER_INPUT_VOLUME8, 0, NODE_WAVEIN_SELECT, 8);
|
|
}
|
|
|
|
// build MIC path
|
|
if (AdapterCommon->GetPinConfig (PINC_MIC_PRESENT))
|
|
{
|
|
// build the MIC selector in case we have 2 MICs
|
|
if (AdapterCommon->GetPinConfig (PINC_MIC2_PRESENT))
|
|
{
|
|
// PIN_MIC_SOURCE pin -> NODE_MIC_SELECT
|
|
INIT_FN_CONN (CurrentConnection, PIN_MIC_SOURCE, NODE_MIC_SELECT, 1);
|
|
|
|
// NODE_MIC_SELECT -> NODE_MIC_BOOST
|
|
INIT_NN_CONN (CurrentConnection, NODE_MIC_SELECT, 0, NODE_MIC_BOOST, 1);
|
|
}
|
|
else
|
|
{
|
|
// PIN_MIC_SOURCE pin -> NODE_MIC_SELECT
|
|
INIT_FN_CONN (CurrentConnection, PIN_MIC_SOURCE, NODE_MIC_BOOST, 1);
|
|
}
|
|
|
|
// NODE_MIC_BOOST -> NODE_MIC_VOLUME
|
|
INIT_NN_CONN (CurrentConnection, NODE_MIC_BOOST, 0, NODE_MIC_VOLUME, 1);
|
|
|
|
// NODE_MIC_VOLUME -> NODE_MIC_MUTE
|
|
INIT_NN_CONN (CurrentConnection, NODE_MIC_VOLUME, 0, NODE_MIC_MUTE, 1);
|
|
|
|
// NODE_MIC_MUTE -> NODE_MAIN_MIX
|
|
INIT_NN_CONN (CurrentConnection, NODE_MIC_MUTE, 0, NODE_MAIN_MIX, 2);
|
|
|
|
// NODE_MIC_BOOST -> NODE_VIRT_MASTER_INPUT_VOLUME1
|
|
INIT_NN_CONN (CurrentConnection, NODE_MIC_BOOST, 0, NODE_VIRT_MASTER_INPUT_VOLUME1, 1);
|
|
|
|
// NODE_VIRT_MASTER_INPUT_VOLUME1 -> NODE_WAVEIN_SELECT
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTER_INPUT_VOLUME1, 0, NODE_WAVEIN_SELECT, 1);
|
|
}
|
|
|
|
// build the line in path
|
|
if (AdapterCommon->GetPinConfig (PINC_LINEIN_PRESENT))
|
|
{
|
|
// PIN_LINEIN_SOURCE -> NODE_LINEIN_VOLUME
|
|
INIT_FN_CONN (CurrentConnection, PIN_LINEIN_SOURCE, NODE_LINEIN_VOLUME, 1);
|
|
|
|
// NODE_LINEIN_VOLUME -> NODE_LINEIN_MUTE
|
|
INIT_NN_CONN (CurrentConnection, NODE_LINEIN_VOLUME, 0, NODE_LINEIN_MUTE, 1);
|
|
|
|
// NODE_LINEIN_MUTE -> NODE_MAIN_MIX
|
|
INIT_NN_CONN (CurrentConnection, NODE_LINEIN_MUTE, 0, NODE_MAIN_MIX, 3);
|
|
|
|
// PIN_LINEIN_SOURCE pin -> NODE_VIRT_MASTER_INPUT_VOLUME5
|
|
INIT_FN_CONN (CurrentConnection, PIN_LINEIN_SOURCE, NODE_VIRT_MASTER_INPUT_VOLUME5, 1);
|
|
|
|
// NODE_VIRT_MASTER_INPUT_VOLUME5 -> NODE_WAVEIN_SELECT
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTER_INPUT_VOLUME5, 0, NODE_WAVEIN_SELECT, 5);
|
|
}
|
|
|
|
// build the CD path
|
|
if (AdapterCommon->GetPinConfig (PINC_CD_PRESENT))
|
|
{
|
|
// PIN_CD_SOURCE -> NODE_CD_VOLUME
|
|
INIT_FN_CONN (CurrentConnection, PIN_CD_SOURCE, NODE_CD_VOLUME, 1);
|
|
|
|
// NODE_CD_VOLUME -> NODE_CD_MUTE
|
|
INIT_NN_CONN (CurrentConnection, NODE_CD_VOLUME, 0, NODE_CD_MUTE, 1);
|
|
|
|
// NODE_CD_MUTE -> NODE_MAIN_MIX
|
|
INIT_NN_CONN (CurrentConnection, NODE_CD_MUTE, 0, NODE_MAIN_MIX, 4);
|
|
|
|
// PIN_CD_SOURCE pin -> NODE_VIRT_MASTER_INPUT_VOLUME2
|
|
INIT_FN_CONN (CurrentConnection, PIN_CD_SOURCE, NODE_VIRT_MASTER_INPUT_VOLUME2, 1);
|
|
|
|
// NODE_VIRT_MASTER_INPUT_VOLUME2 -> NODE_WAVEIN_SELECT
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTER_INPUT_VOLUME2, 0, NODE_WAVEIN_SELECT, 2);
|
|
}
|
|
|
|
// build the video path
|
|
if (AdapterCommon->GetPinConfig (PINC_VIDEO_PRESENT))
|
|
{
|
|
// PIN_VIDEO_SOURCE -> NODE_VIDEO_VOLUME
|
|
INIT_FN_CONN (CurrentConnection, PIN_VIDEO_SOURCE, NODE_VIDEO_VOLUME, 1);
|
|
|
|
// NODE_VIDEO_VOLUME -> NODE_VIDEO_MUTE
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIDEO_VOLUME, 0, NODE_VIDEO_MUTE, 1);
|
|
|
|
// NODE_VIDEO_MUTE -> NODE_MAIN_MIX
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIDEO_MUTE, 0, NODE_MAIN_MIX, 5);
|
|
|
|
// PIN_VIDEO_SOURCE pin -> NODE_VIRT_MASTER_INPUT_VOLUME3
|
|
INIT_FN_CONN (CurrentConnection, PIN_VIDEO_SOURCE, NODE_VIRT_MASTER_INPUT_VOLUME3, 1);
|
|
|
|
// NODE_VIRT_MASTER_INPUT_VOLUME3 -> NODE_WAVEIN_SELECT
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTER_INPUT_VOLUME3, 0, NODE_WAVEIN_SELECT, 3);
|
|
}
|
|
|
|
// build the AUX path
|
|
if (AdapterCommon->GetPinConfig (PINC_AUX_PRESENT))
|
|
{
|
|
// PIN_AUX_SOURCE pin -> NODE_AUX_VOLUME
|
|
INIT_FN_CONN (CurrentConnection, PIN_AUX_SOURCE, NODE_AUX_VOLUME, 1);
|
|
|
|
// NODE_AUX_VOLUME -> NODE_AUX_MUTE
|
|
INIT_NN_CONN (CurrentConnection, NODE_AUX_VOLUME, 0, NODE_AUX_MUTE, 1);
|
|
|
|
// NODE_AUX_MUTE -> NODE_MAIN_MIX
|
|
INIT_NN_CONN (CurrentConnection, NODE_AUX_MUTE, 0, NODE_MAIN_MIX, 6);
|
|
|
|
// PIN_AUX_SOURCE pin -> NODE_VIRT_MASTER_INPUT_VOLUME4
|
|
INIT_FN_CONN (CurrentConnection, PIN_AUX_SOURCE, NODE_VIRT_MASTER_INPUT_VOLUME4, 1);
|
|
|
|
// NODE_VIRT_MASTER_INPUT_VOLUME4 -> NODE_WAVEIN_SELECT
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTER_INPUT_VOLUME4, 0, NODE_WAVEIN_SELECT, 4);
|
|
}
|
|
|
|
// and build the head phone output.
|
|
// we connect the headphones like an input so that it's in the playback panel.
|
|
if (AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
|
|
{
|
|
// from whatever -> NODE_HPOUT_VOLUME
|
|
INIT_FN_CONN (CurrentConnection, PIN_HPOUT_SOURCE, NODE_HPOUT_VOLUME, 1);
|
|
|
|
// NODE_HPOUT_VOLUME -> NODE_HPOUT_MUTE
|
|
INIT_NN_CONN (CurrentConnection, NODE_HPOUT_VOLUME, 0, NODE_HPOUT_MUTE, 1);
|
|
|
|
// NODE_HPOUT_MUTE -> PIN_HPOUT_DEST pin
|
|
INIT_NN_CONN( CurrentConnection, NODE_HPOUT_MUTE, 0, NODE_MAIN_MIX, 9);
|
|
}
|
|
|
|
// build the 3D path
|
|
if (AdapterCommon->GetNodeConfig (NODEC_3D_PRESENT))
|
|
{
|
|
// Figure out what the main 3D line is.
|
|
if (AdapterCommon->GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE))
|
|
{
|
|
if (AdapterCommon->GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE))
|
|
{
|
|
// PIN_VIRT_3D_DEPTH_SOURCE -> NODE_VIRT_3D_ENABLE
|
|
INIT_FN_CONN (CurrentConnection, PIN_VIRT_3D_DEPTH_SOURCE, NODE_VIRT_3D_ENABLE, 1);
|
|
|
|
// NODE_VIRT_3D_ENABLE -> NODE_VIRT_WAVEOUT_3D_BYPASS
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_3D_ENABLE, 0, NODE_VIRT_WAVEOUT_3D_BYPASS, 1);
|
|
|
|
// NODE_VIRT_WAVEOUT_3D_BYPASS -> NODE_VIRT_3D_DEPTH
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_WAVEOUT_3D_BYPASS, 0, NODE_VIRT_3D_DEPTH, 1);
|
|
|
|
// NODE_VIRT_3D_DEPTH -> NODE_MAIN_MIX
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_3D_DEPTH, 0, NODE_MAIN_MIX, 7);
|
|
|
|
// PIN_VIRT_3D_CENTER_SOURCE -> NODE_VIRT_3D_CENTER
|
|
INIT_FN_CONN (CurrentConnection, PIN_VIRT_3D_CENTER_SOURCE, NODE_VIRT_3D_CENTER, 1);
|
|
|
|
// NODE_VIRT_3D_CENTER -> NODE_MAIN_MIX
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_3D_CENTER, 0, NODE_MAIN_MIX, 8);
|
|
}
|
|
else
|
|
{
|
|
// PIN_VIRT_3D_CENTER_SOURCE -> NODE_VIRT_3D_ENABLE
|
|
INIT_FN_CONN (CurrentConnection, PIN_VIRT_3D_CENTER_SOURCE, NODE_VIRT_3D_ENABLE, 1);
|
|
|
|
// NODE_VIRT_3D_ENABLE -> NODE_VIRT_WAVEOUT_3D_BYPASS
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_3D_ENABLE, 0, NODE_VIRT_WAVEOUT_3D_BYPASS, 1);
|
|
|
|
// NODE_VIRT_WAVEOUT_3D_BYPASS -> NODE_VIRT_3D_CENTER
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_WAVEOUT_3D_BYPASS, 0, NODE_VIRT_3D_CENTER, 1);
|
|
|
|
// NODE_VIRT_3D_CENTER -> NODE_MAIN_MIX
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_3D_CENTER, 0, NODE_MAIN_MIX, 8);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// PIN_VIRT_3D_DEPTH_SOURCE -> NODE_VIRT_3D_ENABLE
|
|
INIT_FN_CONN (CurrentConnection, PIN_VIRT_3D_DEPTH_SOURCE, NODE_VIRT_3D_ENABLE, 1);
|
|
|
|
// NODE_VIRT_3D_ENABLE -> NODE_VIRT_WAVEOUT_3D_BYPASS
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_3D_ENABLE, 0, NODE_VIRT_WAVEOUT_3D_BYPASS, 1);
|
|
|
|
// NODE_VIRT_WAVEOUT_3D_BYPASS -> NODE_VIRT_3D_DEPTH
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_WAVEOUT_3D_BYPASS, 0, NODE_VIRT_3D_DEPTH, 1);
|
|
|
|
// NODE_VIRT_3D_DEPTH -> NODE_MAIN_MIX
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_3D_DEPTH, 0, NODE_MAIN_MIX, 7);
|
|
}
|
|
}
|
|
|
|
// build the 4 or 6 channel controls
|
|
|
|
// In case of multichannel or headphone we have "front speakers" volume/mute.
|
|
if (AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT) ||
|
|
AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
|
|
{
|
|
// PIN_VIRT_FRONT_SOURCE -> NODE_FRONT_VOLUME
|
|
INIT_FN_CONN (CurrentConnection, PIN_VIRT_FRONT_SOURCE, NODE_FRONT_VOLUME, 1);
|
|
|
|
// NODE_FRONT_VOLUME -> NODE_FRONT_MUTE
|
|
INIT_NN_CONN (CurrentConnection, NODE_FRONT_VOLUME, 0, NODE_FRONT_MUTE, 1);
|
|
|
|
// NODE_FRONT_MUTE -> NODE_MAIN_MIX
|
|
INIT_NN_CONN (CurrentConnection, NODE_FRONT_MUTE, 0, NODE_MAIN_MIX, 10);
|
|
}
|
|
|
|
// Check for surround volumes
|
|
if (AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT))
|
|
{
|
|
// PIN_VIRT_SURROUND -> NODE_SURROUND_VOLUME
|
|
INIT_FN_CONN (CurrentConnection, PIN_VIRT_SURROUND_SOURCE, NODE_SURROUND_VOLUME, 1);
|
|
|
|
// NODE_SURROUND_VOLUME -> NODE_SURROUND_MUTE
|
|
INIT_NN_CONN (CurrentConnection, NODE_SURROUND_VOLUME, 0, NODE_SURROUND_MUTE, 1);
|
|
|
|
// NODE_SURROUND_MUTE -> NODE_MAIN_MIX
|
|
INIT_NN_CONN (CurrentConnection, NODE_SURROUND_MUTE, 0, NODE_MAIN_MIX, 11);
|
|
|
|
// check also for the center and LFE volumes
|
|
if (AdapterCommon->GetPinConfig (PINC_CENTER_LFE_PRESENT))
|
|
{
|
|
// PIN_VIRT_CENTER -> NODE_CENTER_VOLUME
|
|
INIT_FN_CONN (CurrentConnection, PIN_VIRT_CENTER_SOURCE, NODE_CENTER_VOLUME, 1);
|
|
|
|
// NODE_CENTER_VOLUME -> NODE_CENTER_MUTE
|
|
INIT_NN_CONN (CurrentConnection, NODE_CENTER_VOLUME, 0, NODE_CENTER_MUTE, 1);
|
|
|
|
// NODE_CENTER_MUTE -> NODE_MAIN_MIX
|
|
INIT_NN_CONN (CurrentConnection, NODE_CENTER_MUTE, 0, NODE_MAIN_MIX, 12);
|
|
|
|
// PIN_VIRT_LFE -> NODE_LFE_VOLUME
|
|
INIT_FN_CONN (CurrentConnection, PIN_VIRT_LFE_SOURCE, NODE_LFE_VOLUME, 1);
|
|
|
|
// NODE_LFE_VOLUME -> NODE_LFE_MUTE
|
|
INIT_NN_CONN (CurrentConnection, NODE_LFE_VOLUME, 0, NODE_LFE_MUTE, 1);
|
|
|
|
// NODE_LFE_MUTE -> NODE_MAIN_MIX
|
|
INIT_NN_CONN (CurrentConnection, NODE_LFE_MUTE, 0, NODE_MAIN_MIX, 13);
|
|
}
|
|
}
|
|
|
|
// helper node variable.
|
|
TopoNodes ConnectFromNode;
|
|
|
|
// all connections go from this one
|
|
ConnectFromNode = NODE_MAIN_MIX;
|
|
|
|
// build the beeper & phone mix
|
|
if (AdapterCommon->GetPinConfig (PINC_PCBEEP_PRESENT) ||
|
|
AdapterCommon->GetPinConfig (PINC_PHONE_PRESENT))
|
|
{
|
|
// last node -> NODE_BEEP_MIX
|
|
INIT_NN_CONN (CurrentConnection, ConnectFromNode, 0, NODE_BEEP_MIX, 1);
|
|
|
|
// next connection from this point.
|
|
ConnectFromNode = NODE_BEEP_MIX;
|
|
}
|
|
|
|
// build the tone control path
|
|
if (AdapterCommon->GetNodeConfig (NODEC_TONE_PRESENT))
|
|
{
|
|
// last node -> NODE_BASS
|
|
INIT_NN_CONN (CurrentConnection, ConnectFromNode, 0, NODE_BASS, 1);
|
|
|
|
// NODE_BASS -> NODE_TREBLE
|
|
INIT_NN_CONN (CurrentConnection, NODE_BASS, 0, NODE_TREBLE, 1);
|
|
|
|
// remember the last node
|
|
ConnectFromNode = NODE_TREBLE;
|
|
|
|
// build the loudness control
|
|
if (AdapterCommon->GetNodeConfig (NODEC_LOUDNESS_PRESENT))
|
|
{
|
|
// last node -> NODE_LOUDNESS
|
|
INIT_NN_CONN (CurrentConnection, ConnectFromNode, 0, NODE_LOUDNESS, 1);
|
|
|
|
// remember the last node
|
|
ConnectFromNode = NODE_LOUDNESS;
|
|
}
|
|
|
|
// build the simulated stereo control
|
|
if (AdapterCommon->GetNodeConfig (NODEC_SIMUL_STEREO_PRESENT))
|
|
{
|
|
// last node -> NODE_SIMUL_STEREO
|
|
INIT_NN_CONN (CurrentConnection, ConnectFromNode, 0, NODE_SIMUL_STEREO, 1);
|
|
|
|
// remember the last node
|
|
ConnectFromNode = NODE_SIMUL_STEREO;
|
|
}
|
|
}
|
|
|
|
//build the master volume output.
|
|
|
|
// In case of multichannel or headphone we use a master mono control.
|
|
if (AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT) ||
|
|
AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
|
|
{
|
|
// build the connection from whatever to NODE_VIRT_MASTERMONO_VOLUME
|
|
INIT_NN_CONN (CurrentConnection, ConnectFromNode, 0, NODE_VIRT_MASTERMONO_VOLUME, 1);
|
|
|
|
// NODE_VIRT_MASTERMONO_VOLUME -> NODE_VIRT_MASTERMONO_MUTE
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTERMONO_VOLUME, 0, NODE_VIRT_MASTERMONO_MUTE, 1);
|
|
|
|
// NODE_VIRT_MASTERMONO_MUTE -> PIN_MASTEROUT_DEST pin
|
|
INIT_NF_CONN( CurrentConnection, NODE_VIRT_MASTERMONO_MUTE, 0, PIN_MASTEROUT_DEST);
|
|
}
|
|
else
|
|
{
|
|
// build the connection from whatever to NODE_MASTEROUT_VOLUME
|
|
INIT_NN_CONN (CurrentConnection, ConnectFromNode, 0, NODE_MASTEROUT_VOLUME, 1);
|
|
|
|
// NODE_MASTEROUT_VOLUME -> NODE_MASTEROUT_MUTE
|
|
INIT_NN_CONN (CurrentConnection, NODE_MASTEROUT_VOLUME, 0, NODE_MASTEROUT_MUTE, 1);
|
|
|
|
// NODE_MASTEROUT_MUTE -> PIN_MASTEROUT_DEST pin
|
|
INIT_NF_CONN( CurrentConnection, NODE_MASTEROUT_MUTE, 0, PIN_MASTEROUT_DEST);
|
|
}
|
|
|
|
// now complete the input muxer path
|
|
|
|
// PIN_VIRT_TONE_MIX_MONO_SOURCE -> NODE_VIRT_MASTER_INPUT_VOLUME7
|
|
INIT_FN_CONN (CurrentConnection, PIN_VIRT_TONE_MIX_MONO_SOURCE, NODE_VIRT_MASTER_INPUT_VOLUME7, 1);
|
|
|
|
// NODE_VIRT_MASTER_INPUT_VOLUME7 -> NODE_WAVEIN_SELECT
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTER_INPUT_VOLUME7, 0, NODE_WAVEIN_SELECT, 7);
|
|
|
|
// PIN_VIRT_TONE_MIX_SOURCE -> NODE_VIRT_MASTER_INPUT_VOLUME6
|
|
INIT_FN_CONN (CurrentConnection, PIN_VIRT_TONE_MIX_SOURCE, NODE_VIRT_MASTER_INPUT_VOLUME6, 1);
|
|
|
|
// NODE_VIRT_MASTER_INPUT_VOLUME6 -> NODE_WAVEIN_SELECT
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTER_INPUT_VOLUME6, 0, NODE_WAVEIN_SELECT, 6);
|
|
|
|
// NODE_WAVEIN_SELECT -> PIN_WAVEIN_DEST
|
|
INIT_NF_CONN( CurrentConnection, NODE_WAVEIN_SELECT, 0, PIN_WAVEIN_DEST);
|
|
|
|
// build the mic output path (for record control)
|
|
if (AdapterCommon->GetPinConfig (PINC_MIC_PRESENT) &&
|
|
AdapterCommon->GetPinConfig (PINC_MICIN_PRESENT))
|
|
{
|
|
// NODE_MIC_BOOST -> NODE_MICIN_VOLUME
|
|
INIT_NN_CONN (CurrentConnection, NODE_MIC_BOOST, 0, NODE_MICIN_VOLUME, 1);
|
|
|
|
// NODE_MICIN_VOLUME -> NODE_MICIN_MUTE
|
|
INIT_NN_CONN (CurrentConnection, NODE_MICIN_VOLUME, 0, NODE_MICIN_MUTE, 1);
|
|
|
|
// NODE_MICIN_MUTE -> PIN_MICIN_DEST
|
|
INIT_NF_CONN( CurrentConnection, NODE_MICIN_MUTE, 0, PIN_MICIN_DEST);
|
|
}
|
|
|
|
// build the mono path
|
|
if (AdapterCommon->GetPinConfig (PINC_MONOOUT_PRESENT))
|
|
{
|
|
// PIN_VIRT_3D_MIX_MONO_SOURCE -> NODE_MONOOUT_SMIX
|
|
INIT_FN_CONN (CurrentConnection, PIN_VIRT_3D_MIX_MONO_SOURCE, NODE_VIRT_MONOOUT_VOLUME1, 1);
|
|
|
|
// NODE_VIRT_MONOOUT_VOLUME1 -> NODE_MONOOUT_SELECT
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_MONOOUT_VOLUME1, 0, NODE_MONOOUT_SELECT, 1);
|
|
|
|
if (AdapterCommon->GetPinConfig (PINC_MIC_PRESENT))
|
|
{
|
|
// NODE_MIC_BOOST -> NODE_VIRT_MONOOUT_VOLUME2
|
|
INIT_NN_CONN (CurrentConnection, NODE_MIC_BOOST, 0, NODE_VIRT_MONOOUT_VOLUME2, 1);
|
|
|
|
// NODE_VIRT_MONOOUT_VOLUME2 -> NODE_MONOOUT_SELECT
|
|
INIT_NN_CONN (CurrentConnection, NODE_VIRT_MONOOUT_VOLUME2, 0, NODE_MONOOUT_SELECT, 2);
|
|
}
|
|
|
|
// NODE_MONOOUT_SELECT -> PIN_MONOOUT_DEST
|
|
INIT_NF_CONN( CurrentConnection, NODE_MONOOUT_SELECT, 0, PIN_MONOOUT_DEST);
|
|
}
|
|
|
|
// add the connections to the filter descriptor
|
|
FilterDescriptor->ConnectionCount = ConnectionCount;
|
|
FilterDescriptor->Connections = ConnectionDescriptors;
|
|
} else
|
|
{
|
|
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
return ntStatus;
|
|
|
|
#undef INIT_NN_CONN
|
|
#undef INIT_FN_CONN
|
|
#undef INIT_NF_CONN
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* CMiniportTopologyICH::UpdateRecordMute
|
|
*****************************************************************************
|
|
* Updates the record mute control. This is used to have DRM functionality.
|
|
* In the case that we play a DRM file that is copy protected, we have to
|
|
* mute the record if stereo or mono mix is selected. We also have to update
|
|
* the record mute every time the DRM content changes or the playback stream
|
|
* goes away. The property handler also calls this function to update the
|
|
* record mute in case stereo or mono mix is selected.
|
|
*/
|
|
void CMiniportTopologyICH::UpdateRecordMute (void)
|
|
{
|
|
PAGED_CODE ();
|
|
|
|
WORD wRegister;
|
|
TopoNodes Node;
|
|
|
|
DOUT (DBG_PRINT, ("[CMiniportTopologyICH::UpdateRecordMute]"));
|
|
|
|
// Get the record muxer setting.
|
|
if (!NT_SUCCESS (AdapterCommon->ReadCodecRegister (
|
|
AdapterCommon->GetNodeReg (NODE_WAVEIN_SELECT), &wRegister)))
|
|
return;
|
|
|
|
// Mask out every unused bit.
|
|
wRegister &= (AdapterCommon->GetNodeMask (NODE_WAVEIN_SELECT) & AC97REG_MASK_RIGHT);
|
|
|
|
// Calculate how we would program the mute.
|
|
switch (wRegister)
|
|
{
|
|
// This is stereo mix.
|
|
case 5:
|
|
Node = NODE_VIRT_MASTER_INPUT_VOLUME6;
|
|
break;
|
|
|
|
// This is mono mix.
|
|
case 6:
|
|
Node = NODE_VIRT_MASTER_INPUT_VOLUME7;
|
|
break;
|
|
|
|
// Something else selected than stereo mix or mono mix.
|
|
default:
|
|
return;
|
|
}
|
|
|
|
// Program the mute.
|
|
AdapterCommon->WriteCodecRegister (AC97REG_RECORD_GAIN,
|
|
(m_bCopyProtectFlag ? AC97REG_MASK_MUTE : 0), AC97REG_MASK_MUTE);
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* CMiniportTopologyICH::GetPhysicalConnectionPins
|
|
*****************************************************************************
|
|
* Returns the system pin IDs of the bridge pins that are connected with the
|
|
* wave miniport.
|
|
* If one pin is not used, the value is -1, that could only happen for MinInDest.
|
|
*/
|
|
STDMETHODIMP CMiniportTopologyICH::GetPhysicalConnectionPins
|
|
(
|
|
OUT PULONG WaveOutSource,
|
|
OUT PULONG WaveInDest,
|
|
OUT PULONG MicInDest
|
|
)
|
|
{
|
|
PAGED_CODE ();
|
|
|
|
ASSERT (WaveOutSource);
|
|
ASSERT (WaveInDest);
|
|
ASSERT (MicInDest);
|
|
|
|
DOUT (DBG_PRINT, ("[CMiniportTopologyICH::GetPhysicalConnectionPins]"));
|
|
|
|
// set the pin IDs.
|
|
*WaveOutSource = TransPinDefToPinNr (PIN_WAVEOUT_SOURCE);
|
|
*WaveInDest = TransPinDefToPinNr (PIN_WAVEIN_DEST);
|
|
// this is optional
|
|
if (AdapterCommon->GetPinConfig (PINC_MICIN_PRESENT))
|
|
*MicInDest = TransPinDefToPinNr (PIN_MICIN_DEST);
|
|
else
|
|
*MicInDest = -1;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|