Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2104 lines
75 KiB

  1. /********************************************************************************
  2. ** Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
  3. **
  4. ** Portions Copyright (c) 1998-1999 Intel Corporation
  5. **
  6. ********************************************************************************/
  7. // Every debug output has "Modulname text".
  8. static char STR_MODULENAME[] = "ICH Topology: ";
  9. #include "mintopo.h"
  10. /*****************************************************************************
  11. * AC97 topology miniport tables
  12. */
  13. /*****************************************************************************
  14. * PinDataRangesBridge
  15. *****************************************************************************
  16. * Structures indicating range of valid format values for bridge pins.
  17. */
  18. static KSDATARANGE PinDataRangesAnalogBridge[] =
  19. {
  20. {
  21. sizeof(KSDATARANGE),
  22. 0,
  23. 0,
  24. 0,
  25. STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO),
  26. STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG),
  27. STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE)
  28. }
  29. };
  30. /*****************************************************************************
  31. * PinDataRangePointersBridge
  32. *****************************************************************************
  33. * List of pointers to structures indicating range of valid format values
  34. * for audio bridge pins.
  35. */
  36. static PKSDATARANGE PinDataRangePointersAnalogBridge[] =
  37. {
  38. (PKSDATARANGE)&PinDataRangesAnalogBridge[0]
  39. };
  40. /*****************************************************************************
  41. * PropertiesVolume
  42. *****************************************************************************
  43. * Properties for volume controls.
  44. */
  45. static PCPROPERTY_ITEM PropertiesVolume[] =
  46. {
  47. {
  48. &KSPROPSETID_Audio,
  49. KSPROPERTY_AUDIO_VOLUMELEVEL,
  50. KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
  51. CMiniportTopologyICH::PropertyHandler_Level
  52. },
  53. {
  54. &KSPROPSETID_Audio,
  55. KSPROPERTY_AUDIO_CPU_RESOURCES,
  56. KSPROPERTY_TYPE_GET,
  57. CMiniportTopologyICH::PropertyHandler_CpuResources
  58. }
  59. };
  60. /*****************************************************************************
  61. * AutomationVolume
  62. *****************************************************************************
  63. * Automation table for volume controls.
  64. */
  65. DEFINE_PCAUTOMATION_TABLE_PROP (AutomationVolume, PropertiesVolume);
  66. /*****************************************************************************
  67. * PropertiesMute
  68. *****************************************************************************
  69. * Properties for mute controls.
  70. */
  71. static PCPROPERTY_ITEM PropertiesMute[] =
  72. {
  73. {
  74. &KSPROPSETID_Audio,
  75. KSPROPERTY_AUDIO_MUTE,
  76. KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET,
  77. CMiniportTopologyICH::PropertyHandler_OnOff
  78. },
  79. {
  80. &KSPROPSETID_Audio,
  81. KSPROPERTY_AUDIO_CPU_RESOURCES,
  82. KSPROPERTY_TYPE_GET,
  83. CMiniportTopologyICH::PropertyHandler_CpuResources
  84. }
  85. };
  86. /*****************************************************************************
  87. * AutomationMute
  88. *****************************************************************************
  89. * Automation table for mute controls.
  90. */
  91. DEFINE_PCAUTOMATION_TABLE_PROP (AutomationMute, PropertiesMute);
  92. /*****************************************************************************
  93. * PropertiesMux
  94. *****************************************************************************
  95. * Properties for mux controls.
  96. */
  97. static PCPROPERTY_ITEM PropertiesMux[] =
  98. {
  99. {
  100. &KSPROPSETID_Audio,
  101. KSPROPERTY_AUDIO_MUX_SOURCE,
  102. KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET,
  103. CMiniportTopologyICH::PropertyHandler_Ulong
  104. },
  105. {
  106. &KSPROPSETID_Audio,
  107. KSPROPERTY_AUDIO_CPU_RESOURCES,
  108. KSPROPERTY_TYPE_GET,
  109. CMiniportTopologyICH::PropertyHandler_CpuResources
  110. }
  111. };
  112. /*****************************************************************************
  113. * AutomationMux
  114. *****************************************************************************
  115. * Automation table for mux controls.
  116. */
  117. DEFINE_PCAUTOMATION_TABLE_PROP (AutomationMux, PropertiesMux);
  118. /*****************************************************************************
  119. * PropertiesSpecial
  120. *****************************************************************************
  121. * Properties for Special controls like fake loudness and fake agc.
  122. */
  123. static PCPROPERTY_ITEM PropertiesSpecial[] =
  124. {
  125. {
  126. &KSPROPSETID_Audio,
  127. KSPROPERTY_AUDIO_AGC,
  128. KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET,
  129. CMiniportTopologyICH::PropertyHandler_OnOff
  130. },
  131. {
  132. &KSPROPSETID_Audio,
  133. KSPROPERTY_AUDIO_LOUDNESS,
  134. KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET,
  135. CMiniportTopologyICH::PropertyHandler_OnOff
  136. },
  137. {
  138. &KSPROPSETID_Audio,
  139. KSPROPERTY_AUDIO_CPU_RESOURCES,
  140. KSPROPERTY_TYPE_GET,
  141. CMiniportTopologyICH::PropertyHandler_CpuResources
  142. }
  143. };
  144. /*****************************************************************************
  145. * AutomationAgc
  146. *****************************************************************************
  147. * Automation table for agc controls.
  148. */
  149. DEFINE_PCAUTOMATION_TABLE_PROP (AutomationSpecial, PropertiesSpecial);
  150. /*****************************************************************************
  151. * PropertiesTone
  152. *****************************************************************************
  153. * Properties for tone controls.
  154. */
  155. static PCPROPERTY_ITEM PropertiesTone[] =
  156. {
  157. {
  158. &KSPROPSETID_Audio,
  159. KSPROPERTY_AUDIO_BASS,
  160. KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
  161. CMiniportTopologyICH::PropertyHandler_Tone
  162. },
  163. {
  164. &KSPROPSETID_Audio,
  165. KSPROPERTY_AUDIO_TREBLE,
  166. KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
  167. CMiniportTopologyICH::PropertyHandler_Tone
  168. },
  169. {
  170. &KSPROPSETID_Audio,
  171. KSPROPERTY_AUDIO_CPU_RESOURCES,
  172. KSPROPERTY_TYPE_GET,
  173. CMiniportTopologyICH::PropertyHandler_CpuResources
  174. }
  175. };
  176. /*****************************************************************************
  177. * AutomationTone
  178. *****************************************************************************
  179. * Automation table for tone controls.
  180. */
  181. DEFINE_PCAUTOMATION_TABLE_PROP (AutomationTone, PropertiesTone);
  182. /*****************************************************************************
  183. * Properties3D
  184. *****************************************************************************
  185. * Properties for 3D controls.
  186. */
  187. static PCPROPERTY_ITEM Properties3D[] =
  188. {
  189. // are faky volume controls.
  190. {
  191. &KSPROPSETID_Audio,
  192. KSPROPERTY_AUDIO_VOLUMELEVEL,
  193. KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT,
  194. CMiniportTopologyICH::PropertyHandler_Tone
  195. },
  196. {
  197. &KSPROPSETID_Audio,
  198. KSPROPERTY_AUDIO_CPU_RESOURCES,
  199. KSPROPERTY_TYPE_GET,
  200. CMiniportTopologyICH::PropertyHandler_CpuResources
  201. }
  202. };
  203. /*****************************************************************************
  204. * Automation3D
  205. *****************************************************************************
  206. * Automation table for 3D controls.
  207. */
  208. DEFINE_PCAUTOMATION_TABLE_PROP (Automation3D, Properties3D);
  209. #ifdef INCLUDE_PRIVATE_PROPERTY
  210. /*****************************************************************************
  211. * FilterPropertiesPrivate
  212. *****************************************************************************
  213. * Properties for AC97 features.
  214. */
  215. static PCPROPERTY_ITEM FilterPropertiesPrivate[] =
  216. {
  217. // This is a private property for getting the AC97 codec features.
  218. {
  219. &KSPROPSETID_Private,
  220. KSPROPERTY_AC97_FEATURES,
  221. KSPROPERTY_TYPE_GET,
  222. CMiniportTopologyICH::PropertyHandler_Private
  223. }
  224. #ifdef PROPERTY_SHOW_SET
  225. ,
  226. // This is a private property for getting the AC97 codec features.
  227. {
  228. &KSPROPSETID_Private,
  229. KSPROPERTY_AC97_SAMPLE_SET,
  230. KSPROPERTY_TYPE_SET,
  231. CMiniportTopologyICH::PropertyHandler_Private
  232. }
  233. #endif
  234. };
  235. /*****************************************************************************
  236. * FilterAutomationPrivate
  237. *****************************************************************************
  238. * Filter's automation table for private property controls.
  239. */
  240. DEFINE_PCAUTOMATION_TABLE_PROP (FilterAutomationPrivate, FilterPropertiesPrivate);
  241. #endif
  242. #pragma code_seg("PAGE")
  243. /*****************************************************************************
  244. * CreateMiniportTopologyICH
  245. *****************************************************************************
  246. * Creates a topology miniport object for the ICH audio adapter. This uses a
  247. * macro from STDUNK.H to do all the work.
  248. */
  249. NTSTATUS CreateMiniportTopologyICH
  250. (
  251. OUT PUNKNOWN * Unknown,
  252. IN REFCLSID,
  253. IN PUNKNOWN UnknownOuter OPTIONAL,
  254. IN POOL_TYPE PoolType
  255. )
  256. {
  257. PAGED_CODE ();
  258. ASSERT (Unknown);
  259. STD_CREATE_BODY (CMiniportTopologyICH, Unknown, UnknownOuter, PoolType);
  260. }
  261. /*****************************************************************************
  262. * CMiniportTopologyICH::NonDelegatingQueryInterface
  263. *****************************************************************************
  264. * Obtains an interface. This function works just like a COM QueryInterface
  265. * call and is used if the object is not being aggregated.
  266. * We basically just check any GUID we know and return this object in case we
  267. * know it.
  268. */
  269. STDMETHODIMP_(NTSTATUS) CMiniportTopologyICH::NonDelegatingQueryInterface
  270. (
  271. IN REFIID Interface,
  272. OUT PVOID * Object
  273. )
  274. {
  275. PAGED_CODE ();
  276. ASSERT (Object);
  277. DOUT (DBG_PRINT, ("[CMiniportTopologyICH::NonDelegatingQueryInterface]"));
  278. // Is it IID_IUnknown?
  279. if (IsEqualGUIDAligned (Interface, IID_IUnknown))
  280. {
  281. *Object = (PVOID)(PUNKNOWN)this;
  282. }
  283. else
  284. // or IID_IMiniport ...
  285. if (IsEqualGUIDAligned (Interface, IID_IMiniport))
  286. {
  287. *Object = (PVOID)(PMINIPORT)this;
  288. }
  289. else
  290. // or IID_IMiniportTopology ...
  291. if (IsEqualGUIDAligned (Interface, IID_IMiniportTopology))
  292. {
  293. *Object = (PVOID)(PMINIPORTTOPOLOGY)this;
  294. }
  295. else
  296. // or maybe our IID_IMiniportTopologyICH ...
  297. if (IsEqualGUIDAligned (Interface, IID_IMiniportTopologyICH))
  298. {
  299. *Object = (PVOID)(PMINIPORTTOPOLOGYICH)this;
  300. }
  301. else
  302. {
  303. // nothing found, must be an unknown interface.
  304. *Object = NULL;
  305. return STATUS_INVALID_PARAMETER;
  306. }
  307. //
  308. // We reference the interface for the caller.
  309. //
  310. ((PUNKNOWN)(*Object))->AddRef ();
  311. return STATUS_SUCCESS;
  312. }
  313. /*****************************************************************************
  314. * CMiniportTopologyICH::~CMiniportTopologyICH
  315. *****************************************************************************
  316. * Destructor.
  317. */
  318. CMiniportTopologyICH::~CMiniportTopologyICH ()
  319. {
  320. PAGED_CODE ();
  321. DOUT (DBG_PRINT, ("[CMiniportTopologyICH::~CMiniportTopologyICH]"));
  322. // release all the stuff that we had referenced or allocated.
  323. if (AdapterCommon)
  324. {
  325. // Notify the AdapterCommon that we go away.
  326. AdapterCommon->SetMiniportTopology (NULL);
  327. AdapterCommon->Release ();
  328. AdapterCommon = NULL;
  329. }
  330. if (FilterDescriptor)
  331. {
  332. ExFreePool (FilterDescriptor);
  333. FilterDescriptor = NULL;
  334. }
  335. if (ConnectionDescriptors)
  336. {
  337. ExFreePool (ConnectionDescriptors);
  338. ConnectionDescriptors = NULL;
  339. }
  340. if (NodeDescriptors)
  341. {
  342. ExFreePool (NodeDescriptors);
  343. NodeDescriptors = NULL;
  344. }
  345. if (PinDescriptors)
  346. {
  347. ExFreePool (PinDescriptors);
  348. PinDescriptors = NULL;
  349. }
  350. }
  351. /*****************************************************************************
  352. * CMiniportTopologyICH::DataRangeIntersection
  353. *****************************************************************************
  354. * Is defined in the IMiniportTopology interface. We just return
  355. * STATUS_NOT_IMPLEMENTED and portcls will use a default handler for this.
  356. */
  357. STDMETHODIMP_(NTSTATUS) CMiniportTopologyICH::DataRangeIntersection
  358. (
  359. IN ULONG PinId,
  360. IN PKSDATARANGE DataRange,
  361. IN PKSDATARANGE MatchingDataRange,
  362. IN ULONG OutputBufferLength,
  363. OUT PVOID ResultantFormat OPTIONAL,
  364. OUT PULONG ResultantFormatLength
  365. )
  366. {
  367. return STATUS_NOT_IMPLEMENTED;
  368. };
  369. /*****************************************************************************
  370. * CMiniportTopologyICH::Init
  371. *****************************************************************************
  372. * Initializes the miniport.
  373. * We initialize the translation tables, add reference to the port driver and
  374. * build the topology.
  375. */
  376. STDMETHODIMP_(NTSTATUS) CMiniportTopologyICH::Init
  377. (
  378. IN PUNKNOWN UnknownAdapter,
  379. IN PRESOURCELIST ResourceList,
  380. IN PPORTTOPOLOGY Port_
  381. )
  382. {
  383. PAGED_CODE ();
  384. ASSERT (UnknownAdapter);
  385. ASSERT (Port_);
  386. DOUT (DBG_PRINT, ("[CMiniportTopologyICH::Init]"));
  387. //
  388. // Set the copy protect flag to FALSE.
  389. //
  390. m_bCopyProtectFlag = FALSE;
  391. //
  392. // get the IAdapterCommon interface from the adapter.
  393. //
  394. NTSTATUS ntStatus = UnknownAdapter->QueryInterface (IID_IAdapterCommon,
  395. (PVOID *) &AdapterCommon);
  396. //
  397. // initialize translation tables
  398. //
  399. for (int i = 0; i < PIN_TOP_ELEMENT; i++)
  400. {
  401. stPinTrans[i].PinDef = PIN_INVALID;
  402. stPinTrans[i].PinNr = -1;
  403. }
  404. for (i = 0; i < NODE_TOP_ELEMENT; i++)
  405. {
  406. stNodeTrans[i].NodeDef = NODE_INVALID;
  407. stNodeTrans[i].NodeNr = -1;
  408. }
  409. // build the topology (means register pins, nodes, connections).
  410. if (NT_SUCCESS (ntStatus))
  411. {
  412. ntStatus = BuildTopology ();
  413. }
  414. if (NT_SUCCESS (ntStatus))
  415. {
  416. //
  417. // Notify AdapterCommon that we are ready now.
  418. //
  419. AdapterCommon->SetMiniportTopology (this);
  420. }
  421. else
  422. {
  423. //
  424. // clean up our mess
  425. //
  426. // clean up AdapterCommon
  427. if (AdapterCommon)
  428. {
  429. AdapterCommon->Release ();
  430. AdapterCommon = NULL;
  431. }
  432. }
  433. return ntStatus;
  434. }
  435. /*****************************************************************************
  436. * CMiniportTopologyICH::GetDescription
  437. *****************************************************************************
  438. * Gets/returns the topology to the system.
  439. */
  440. STDMETHODIMP_(NTSTATUS) CMiniportTopologyICH::GetDescription
  441. (
  442. OUT PPCFILTER_DESCRIPTOR * OutFilterDescriptor
  443. )
  444. {
  445. PAGED_CODE ();
  446. ASSERT (OutFilterDescriptor);
  447. DOUT (DBG_PRINT, ("[CMiniportTopologyICH::GetDescription]"));
  448. #if (DBG)
  449. // Dump it here. The system requests the topology only once.
  450. DumpTopology ();
  451. #endif
  452. if (FilterDescriptor)
  453. {
  454. *OutFilterDescriptor = FilterDescriptor;
  455. return STATUS_SUCCESS;
  456. }
  457. else
  458. return STATUS_DEVICE_CONFIGURATION_ERROR;
  459. }
  460. #if (DBG)
  461. /*****************************************************************************
  462. * CMiniportTopologyICH::DumpTopology
  463. *****************************************************************************
  464. * Dumps the topology for debugging.
  465. * See the defines at the beginning of this file?
  466. */
  467. void CMiniportTopologyICH::DumpTopology (void)
  468. {
  469. PAGED_CODE ();
  470. if (FilterDescriptor)
  471. {
  472. // dump the pins
  473. DOUT (DBG_PINS, ("TOPOLOGY MINIPORT PINS"));
  474. for(ULONG index = 0; index < FilterDescriptor->PinCount; index++)
  475. {
  476. DOUT (DBG_PINS, (" %2d %s", index,
  477. TopoPinStrings[TransPinNrToPinDef (index)]));
  478. }
  479. // dump the nodes
  480. DOUT (DBG_NODES, ("TOPOLOGY MINIPORT NODES"));
  481. for(index = 0; index < FilterDescriptor->NodeCount; index++)
  482. {
  483. DOUT (DBG_NODES, (" %2d %s", index,
  484. NodeStrings[TransNodeNrToNodeDef (index)]));
  485. }
  486. // dump the connections
  487. DOUT (DBG_CONNS, ("TOPOLOGY MINIPORT CONNECTIONS"));
  488. for(index = 0; index < FilterDescriptor->ConnectionCount; index++)
  489. {
  490. DOUT (DBG_CONNS, (" %2d (%d,%d)->(%d,%d)", index,
  491. FilterDescriptor->Connections[index].FromNode,
  492. FilterDescriptor->Connections[index].FromNodePin,
  493. FilterDescriptor->Connections[index].ToNode,
  494. FilterDescriptor->Connections[index].ToNodePin));
  495. }
  496. }
  497. }
  498. #endif
  499. /*****************************************************************************
  500. * Miniport Topology V = Volume, M = Mute, L = Loudness, A = AGC
  501. *==================== T = Treble, B = Bass, 0-9 = PinNr of node
  502. *
  503. * PCBEEP ---> V ---> M -----------------------------\
  504. * PHONE ---> V ---> M ----------------------------\ \
  505. * \ \
  506. * WaveOut -------> V --> M --------------> 1+-----+ \ \
  507. * MIC1 or MIC2 --> L --> A --> V --> M --> 2| SUM | \ \
  508. * LineIn -------> V --> M --------------> 3| | \ \
  509. * CD -------> V --> M --------------> 4| |0--->SUM--> T --> B --> L --> V --> M (MasterOut)
  510. * Video -------> V --> M --------------> 5| |
  511. * AUX -------> V --> M --------------> 6| |
  512. * 3D Depth -----> V --> L --> A --------> 7| |
  513. * 3D Center -----> V --> L --> A --------> 8| |
  514. * Headphone -----> V --> M --------------> 9| |
  515. * Front Speaker -> V --> M -------------->10| |
  516. * Surround ------> V --> M -------------->11| |
  517. * Center ------> V --> M -------------->12| |
  518. * LFE ------> V --> M -------------->13+-----+
  519. *
  520. *
  521. * virt. Pin: Tone mix mono ---> V --> M ---> 7+-------+
  522. * virt. Pin: Tone mix stereo ---> V --> M ---> 6| |
  523. * Phone ---> V --> M ---> 8| M |
  524. * Mic (after AGC) ---> V --> M ---> 1| |0-----> (WaveIn)
  525. * LineIn ---> V --> M ---> 5| U |
  526. * CD ---> V --> M ---> 2| |
  527. * Video ---> V --> M ---> 3| X |
  528. * AUX ---> V --> M ---> 4+-------+
  529. *
  530. *
  531. * virt. Pin: 3D mix mono ---> V ---> M ---> 1+-----+
  532. * | MUX |0----> (MonoOut)
  533. * Mic (after AGC) ---> V ---> M ---> 2+-----+
  534. *
  535. *
  536. * Mic (after AGC) ----> V ----> M -----> (MicIn)
  537. *
  538. *----------------------------------------------------------------------------
  539. *
  540. * As you can see, the exposed topology is somewhat different from the real AC97
  541. * topology. This is because the system that translates the topology to "mixer
  542. * lines" gets confused if it has to deal with all the mess. So we have to make it
  543. * plain and simple for the system.
  544. * Some issues block us from exposing a nice plain and simple topology. The prg.
  545. * which displayes the "Volume Control Panel" (sndvol32) does _only_ display
  546. * Volumes, Mutes (only one "in a row"), Treble, Bass, Loudness and AGC under
  547. * Advanced control panel. We don't have 3D controls, and before we go into a
  548. * Muxer, there has to be Volume controls in front.
  549. * So what do we do?
  550. * 1) We fake 3D controls as Volume controls. The Mutes represent 3D bypass and
  551. * 3D on/off
  552. * 2) All inputs (including the 3D controls) go staight into a SUM. Important is
  553. * that there are not 2 Volumes, Mutes in a row, e.g. ---> V ---> M ---> V ---> M
  554. * In that case, only one Volume/Mute would be displayed.
  555. * 3) We can't make a connection from the tone controls to the Wave In muxer (even
  556. * with Volumes in front), so we create fake pins that we name user friendly.
  557. * Same with the connection from the 3D mixer to the Mono output.
  558. * 4) We discard all supermixer controls that would convert stereo to mono or vice
  559. * versa. Instead, we just connect the lines and when the control is queried we
  560. * fail a right channel request (mono has only left channel).
  561. * 5) We have to make virtual volume and mute controls in front of each muxer.
  562. * As you can see, these controls can be mono or stereo and there is only one
  563. * HW register for them, so we have to cache the values and prg. the register
  564. * each time the select changes or the selected volume control changes.
  565. */
  566. /*****************************************************************************
  567. * CMiniportTopologyICH::BuildTopology
  568. *****************************************************************************
  569. * Builds the topology descriptors based on hardware configuration info
  570. * obtained from the adapter.
  571. */
  572. NTSTATUS CMiniportTopologyICH::BuildTopology (void)
  573. {
  574. PAGED_CODE ();
  575. NTSTATUS ntStatus = STATUS_SUCCESS;
  576. DOUT (DBG_PRINT, ("[CMiniportTopologyICH::BuildTopology]"));
  577. // allocate our filter descriptor
  578. FilterDescriptor = (PPCFILTER_DESCRIPTOR) ExAllocatePool (PagedPool,
  579. sizeof(PCFILTER_DESCRIPTOR));
  580. if (FilterDescriptor)
  581. {
  582. // clear out the filter descriptor
  583. RtlZeroMemory (FilterDescriptor, sizeof(PCFILTER_DESCRIPTOR));
  584. #ifdef INCLUDE_PRIVATE_PROPERTY
  585. // Set the Filter automation table.
  586. FilterDescriptor->AutomationTable = &FilterAutomationPrivate;
  587. #endif
  588. // build the pin list
  589. ntStatus = BuildPinDescriptors ();
  590. if (NT_SUCCESS (ntStatus))
  591. {
  592. // build the node list
  593. ntStatus = BuildNodeDescriptors ();
  594. if (NT_SUCCESS (ntStatus))
  595. {
  596. // build the connection list
  597. ntStatus = BuildConnectionDescriptors ();
  598. }
  599. }
  600. }
  601. else
  602. {
  603. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  604. }
  605. // that's whatever one of these build... functions returned.
  606. return ntStatus;
  607. }
  608. /*****************************************************************************
  609. * CMiniportTopologyICH::BuildPinDescriptors
  610. *****************************************************************************
  611. * Builds the topology pin descriptors.
  612. */
  613. NTSTATUS CMiniportTopologyICH::BuildPinDescriptors (void)
  614. {
  615. // Improvement would be to not use a Macro, use (inline) function instead.
  616. #define INIT_PIN( pin, pinptr, category, name, index ) \
  617. pinptr->KsPinDescriptor.Category = (GUID*) category; \
  618. pinptr->KsPinDescriptor.Name = (GUID*) name; \
  619. SetPinTranslation (index++, pin); \
  620. pinptr++
  621. PAGED_CODE ();
  622. ULONG Index;
  623. PPCPIN_DESCRIPTOR CurrentPin;
  624. DOUT (DBG_PRINT, ("[CMiniportTopologyICH::BuildPinDescriptors]"));
  625. // allocate our descriptor memory
  626. PinDescriptors = PPCPIN_DESCRIPTOR (ExAllocatePool (PagedPool,
  627. PIN_TOP_ELEMENT * sizeof(PCPIN_DESCRIPTOR)));
  628. if (!PinDescriptors)
  629. return STATUS_INSUFFICIENT_RESOURCES;
  630. //
  631. // set default pin descriptor parameters
  632. //
  633. RtlZeroMemory (PinDescriptors, PIN_TOP_ELEMENT * sizeof(PCPIN_DESCRIPTOR));
  634. // spend some more time and set the pin descriptors to expected values.
  635. for (CurrentPin = PinDescriptors, Index = 0; Index < PIN_TOP_ELEMENT;
  636. CurrentPin++, Index++)
  637. {
  638. CurrentPin->KsPinDescriptor.DataRangesCount = SIZEOF_ARRAY(PinDataRangePointersAnalogBridge);
  639. CurrentPin->KsPinDescriptor.DataRanges = PinDataRangePointersAnalogBridge;
  640. CurrentPin->KsPinDescriptor.DataFlow = KSPIN_DATAFLOW_IN;
  641. CurrentPin->KsPinDescriptor.Communication = KSPIN_COMMUNICATION_NONE;
  642. }
  643. //
  644. // modify the individual pin descriptors
  645. //
  646. CurrentPin = PinDescriptors;
  647. Index = 0;
  648. // add the PIN_WAVEOUT_SOURCE pin descriptor (not optional)
  649. INIT_PIN (PIN_WAVEOUT_SOURCE,
  650. CurrentPin,
  651. &KSCATEGORY_AUDIO,
  652. NULL,
  653. Index);
  654. // add the PIN_PCBEEP_SOURCE pin descriptor (optional)
  655. if (AdapterCommon->GetPinConfig (PINC_PCBEEP_PRESENT))
  656. {
  657. INIT_PIN (PIN_PCBEEP_SOURCE,
  658. CurrentPin,
  659. &KSNODETYPE_SPEAKER,
  660. &KSAUDFNAME_PC_SPEAKER,
  661. Index);
  662. }
  663. // add the PIN_PHONE_SOURCE pin descriptor (optional)
  664. if (AdapterCommon->GetPinConfig (PINC_PHONE_PRESENT))
  665. {
  666. INIT_PIN (PIN_PHONE_SOURCE,
  667. CurrentPin,
  668. &KSNODETYPE_PHONE_LINE,
  669. NULL,
  670. Index);
  671. }
  672. // add the PIN_MIC_SOURCE pin descriptor (could be disabled)
  673. if (AdapterCommon->GetPinConfig (PINC_MIC_PRESENT))
  674. {
  675. INIT_PIN (PIN_MIC_SOURCE,
  676. CurrentPin,
  677. &KSNODETYPE_MICROPHONE,
  678. NULL,
  679. Index);
  680. }
  681. // add the PIN_LINEIN_SOURCE pin descriptor (could be disabled)
  682. if (AdapterCommon->GetPinConfig (PINC_LINEIN_PRESENT))
  683. {
  684. INIT_PIN (PIN_LINEIN_SOURCE,
  685. CurrentPin,
  686. &KSNODETYPE_LINE_CONNECTOR,
  687. &KSAUDFNAME_LINE_IN,
  688. Index);
  689. }
  690. // add the PIN_CD_SOURCE pin descriptor (could be disabled)
  691. if (AdapterCommon->GetPinConfig (PINC_CD_PRESENT))
  692. {
  693. INIT_PIN (PIN_CD_SOURCE,
  694. CurrentPin,
  695. &KSNODETYPE_CD_PLAYER,
  696. &KSAUDFNAME_CD_AUDIO,
  697. Index);
  698. }
  699. // add the PIN_VIDEO_SOURCE pin descriptor (optional)
  700. if (AdapterCommon->GetPinConfig (PINC_VIDEO_PRESENT))
  701. {
  702. INIT_PIN (PIN_VIDEO_SOURCE,
  703. CurrentPin,
  704. &KSNODETYPE_ANALOG_CONNECTOR,
  705. &KSAUDFNAME_VIDEO,
  706. Index);
  707. }
  708. // add the PIN_AUX_SOURCE pin descriptor (optional)
  709. if (AdapterCommon->GetPinConfig (PINC_AUX_PRESENT))
  710. {
  711. INIT_PIN (PIN_AUX_SOURCE,
  712. CurrentPin,
  713. &KSNODETYPE_ANALOG_CONNECTOR,
  714. &KSAUDFNAME_AUX,
  715. Index);
  716. }
  717. // add the PIN_VIRT_TONE_MIX_SOURCE pin descriptor (not optional)
  718. INIT_PIN (PIN_VIRT_TONE_MIX_SOURCE,
  719. CurrentPin,
  720. &KSNODETYPE_ANALOG_CONNECTOR,
  721. &KSAUDFNAME_STEREO_MIX,
  722. Index);
  723. // add the PIN_VIRT_TONE_MIX_MONO_SOURCE pin descriptor (not optional)
  724. INIT_PIN (PIN_VIRT_TONE_MIX_MONO_SOURCE,
  725. CurrentPin,
  726. &KSNODETYPE_ANALOG_CONNECTOR,
  727. &KSAUDFNAME_MONO_MIX,
  728. Index);
  729. // create a virt. pin for the 3D controls
  730. if (AdapterCommon->GetNodeConfig (NODEC_3D_PRESENT))
  731. {
  732. if (AdapterCommon->GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE))
  733. {
  734. INIT_PIN (PIN_VIRT_3D_CENTER_SOURCE,
  735. CurrentPin,
  736. &KSNODETYPE_ANALOG_CONNECTOR,
  737. &KSAUDFNAME_3D_CENTER,
  738. Index);
  739. }
  740. // A weird way would be to have 3D but only fixed sliders. In that case,
  741. // display one fixed slider (3D depth).
  742. if (AdapterCommon->GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE) ||
  743. (!AdapterCommon->GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE) &&
  744. !AdapterCommon->GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE)))
  745. {
  746. INIT_PIN (PIN_VIRT_3D_DEPTH_SOURCE,
  747. CurrentPin,
  748. &KSNODETYPE_ANALOG_CONNECTOR,
  749. &KSAUDFNAME_3D_DEPTH,
  750. Index);
  751. }
  752. }
  753. // Add a "Front speaker" pin if we have multichannel or headphones.
  754. // We use a master mono then ...
  755. if (AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT) ||
  756. AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
  757. {
  758. // Add a "Front speaker" pin, because in multichannel we want
  759. // to display a master mono that effects all channels.
  760. INIT_PIN (PIN_VIRT_FRONT_SOURCE,
  761. CurrentPin,
  762. &KSNODETYPE_ANALOG_CONNECTOR,
  763. &ICHFNAME_FRONT,
  764. Index);
  765. }
  766. // check for multichannel
  767. if (AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT))
  768. {
  769. // Add the Rear Speaker Volume pin.
  770. INIT_PIN (PIN_VIRT_SURROUND_SOURCE,
  771. CurrentPin,
  772. &KSNODETYPE_ANALOG_CONNECTOR,
  773. &ICHFNAME_SURROUND,
  774. Index);
  775. // add the Center Volume pin if we support at least 6 channel.
  776. if (AdapterCommon->GetPinConfig (PINC_CENTER_LFE_PRESENT))
  777. {
  778. INIT_PIN (PIN_VIRT_CENTER_SOURCE,
  779. CurrentPin,
  780. &KSNODETYPE_ANALOG_CONNECTOR,
  781. &ICHFNAME_CENTER,
  782. Index);
  783. INIT_PIN (PIN_VIRT_LFE_SOURCE,
  784. CurrentPin,
  785. &KSNODETYPE_ANALOG_CONNECTOR,
  786. &ICHFNAME_LFE,
  787. Index);
  788. }
  789. }
  790. // add the PIN_MASTEROUT_DEST pin descriptor (not optional)
  791. CurrentPin->KsPinDescriptor.DataFlow = KSPIN_DATAFLOW_OUT;
  792. INIT_PIN (PIN_MASTEROUT_DEST,
  793. CurrentPin,
  794. &KSNODETYPE_SPEAKER,
  795. &KSAUDFNAME_VOLUME_CONTROL,
  796. Index);
  797. // add the PIN_HPOUT_SOURCE pin descriptor (optional)
  798. if (AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
  799. {
  800. INIT_PIN (PIN_HPOUT_SOURCE,
  801. CurrentPin,
  802. &KSNODETYPE_HEADPHONES,
  803. NULL,
  804. Index);
  805. }
  806. // add the PIN_WAVEIN_DEST pin descriptor (not optional)
  807. CurrentPin->KsPinDescriptor.DataFlow = KSPIN_DATAFLOW_OUT;
  808. INIT_PIN (PIN_WAVEIN_DEST,
  809. CurrentPin,
  810. &KSCATEGORY_AUDIO,
  811. NULL,
  812. Index);
  813. // add the PIN_MICIN_DEST pin descriptor (optional)
  814. if (AdapterCommon->GetPinConfig (PINC_MICIN_PRESENT) &&
  815. AdapterCommon->GetPinConfig (PINC_MIC_PRESENT))
  816. {
  817. CurrentPin->KsPinDescriptor.DataFlow = KSPIN_DATAFLOW_OUT;
  818. INIT_PIN (PIN_MICIN_DEST,
  819. CurrentPin,
  820. &KSCATEGORY_AUDIO,
  821. NULL,
  822. Index);
  823. }
  824. // add the PIN_MONOOUT_DEST pin descriptor (optional)
  825. if (AdapterCommon->GetPinConfig (PINC_MONOOUT_PRESENT))
  826. {
  827. // add the PIN_VIRT_3D_MIX_MONO_SOURCE pin descriptor
  828. INIT_PIN (PIN_VIRT_3D_MIX_MONO_SOURCE,
  829. CurrentPin,
  830. &KSNODETYPE_ANALOG_CONNECTOR,
  831. &KSAUDFNAME_MONO_MIX,
  832. Index);
  833. CurrentPin->KsPinDescriptor.DataFlow = KSPIN_DATAFLOW_OUT;
  834. // and the normal output pin
  835. INIT_PIN (PIN_MONOOUT_DEST,
  836. CurrentPin,
  837. &KSNODETYPE_PHONE_LINE,
  838. &KSAUDFNAME_MONO_OUT,
  839. Index);
  840. }
  841. // add the pin descriptor informatin to the filter descriptor
  842. FilterDescriptor->PinCount = Index;
  843. FilterDescriptor->PinSize = sizeof (PCPIN_DESCRIPTOR);
  844. FilterDescriptor->Pins = PinDescriptors;
  845. return STATUS_SUCCESS;
  846. #undef INIT_PIN
  847. }
  848. /*****************************************************************************
  849. * CMiniportTopologyICH::BuildNodeDescriptors
  850. *****************************************************************************
  851. * Builds the topology node descriptors.
  852. */
  853. NTSTATUS CMiniportTopologyICH::BuildNodeDescriptors (void)
  854. {
  855. // Improvement would be to not use a Macro, use (inline) function instead.
  856. #define INIT_NODE( node, nodeptr, type, name, automation, index ) \
  857. nodeptr->Type = (GUID*) type; \
  858. nodeptr->Name = (GUID*) name; \
  859. nodeptr->AutomationTable = automation; \
  860. SetNodeTranslation (index++, node); \
  861. nodeptr++
  862. PAGED_CODE ();
  863. NTSTATUS ntStatus = STATUS_SUCCESS;
  864. DOUT (DBG_PRINT, ("[CMiniportTopologyICH::BuildNodeDescriptors]"));
  865. // allocate our descriptor memory
  866. NodeDescriptors = PPCNODE_DESCRIPTOR (ExAllocatePool (PagedPool,
  867. NODE_TOP_ELEMENT * sizeof(PCNODE_DESCRIPTOR)));
  868. if (NodeDescriptors)
  869. {
  870. PPCNODE_DESCRIPTOR CurrentNode = NodeDescriptors;
  871. ULONG Index = 0;
  872. //
  873. // set default node descriptor parameters
  874. //
  875. RtlZeroMemory (NodeDescriptors, NODE_TOP_ELEMENT *
  876. sizeof(PCNODE_DESCRIPTOR));
  877. // We don't have loopback mode currently. It is only used for testing anyway.
  878. // Add the NODE_WAVEOUT_VOLUME node
  879. INIT_NODE (NODE_WAVEOUT_VOLUME,
  880. CurrentNode,
  881. &KSNODETYPE_VOLUME,
  882. &KSAUDFNAME_WAVE_VOLUME,
  883. &AutomationVolume,
  884. Index);
  885. // add the NODE_WAVEOUT_MUTE node
  886. INIT_NODE (NODE_WAVEOUT_MUTE,
  887. CurrentNode,
  888. &KSNODETYPE_MUTE,
  889. &KSAUDFNAME_WAVE_MUTE,
  890. &AutomationMute,
  891. Index);
  892. // add the PCBEEP nodes
  893. if (AdapterCommon->GetPinConfig (PINC_PCBEEP_PRESENT))
  894. {
  895. // add the NODE_PCBEEP_VOLUME node
  896. INIT_NODE (NODE_PCBEEP_VOLUME,
  897. CurrentNode,
  898. &KSNODETYPE_VOLUME,
  899. &KSAUDFNAME_PC_SPEAKER_VOLUME,
  900. &AutomationVolume,
  901. Index);
  902. // add the NODE_PCBEEP_MUTE node
  903. INIT_NODE (NODE_PCBEEP_MUTE,
  904. CurrentNode,
  905. &KSNODETYPE_MUTE,
  906. &KSAUDFNAME_PC_SPEAKER_MUTE,
  907. &AutomationMute,
  908. Index);
  909. }
  910. // add the PHONE nodes
  911. if (AdapterCommon->GetPinConfig (PINC_PHONE_PRESENT))
  912. {
  913. // add the NODE_PHONE_VOLUME node
  914. INIT_NODE (NODE_PHONE_VOLUME,
  915. CurrentNode,
  916. &KSNODETYPE_VOLUME,
  917. &ICHFNAME_PHONE_VOLUME,
  918. &AutomationVolume,
  919. Index);
  920. // add the NODE_PHONE_MUTE node
  921. INIT_NODE (NODE_PHONE_MUTE,
  922. CurrentNode,
  923. &KSNODETYPE_MUTE,
  924. &ICHFNAME_PHONE_MUTE,
  925. &AutomationMute,
  926. Index);
  927. }
  928. // add the MIC nodes
  929. if (AdapterCommon->GetPinConfig (PINC_MIC_PRESENT))
  930. {
  931. if (AdapterCommon->GetPinConfig (PINC_MIC2_PRESENT))
  932. {
  933. // add the NODE_MIC_SELECT node
  934. INIT_NODE (NODE_MIC_SELECT,
  935. CurrentNode,
  936. &KSNODETYPE_LOUDNESS,
  937. &KSAUDFNAME_ALTERNATE_MICROPHONE,
  938. &AutomationSpecial,
  939. Index);
  940. }
  941. // add the NODE_MIC_BOOST node
  942. INIT_NODE (NODE_MIC_BOOST,
  943. CurrentNode,
  944. &KSNODETYPE_AGC,
  945. &KSAUDFNAME_MICROPHONE_BOOST,
  946. &AutomationSpecial,
  947. Index);
  948. // add the NODE_MIC_VOLUME node
  949. INIT_NODE (NODE_MIC_VOLUME,
  950. CurrentNode,
  951. &KSNODETYPE_VOLUME,
  952. &KSAUDFNAME_MIC_VOLUME,
  953. &AutomationVolume,
  954. Index);
  955. // add the NODE_MIC_MUTE node
  956. INIT_NODE (NODE_MIC_MUTE,
  957. CurrentNode,
  958. &KSNODETYPE_MUTE,
  959. &KSAUDFNAME_MIC_MUTE,
  960. &AutomationMute,
  961. Index);
  962. }
  963. if (AdapterCommon->GetPinConfig (PINC_LINEIN_PRESENT))
  964. {
  965. // add the NODE_LINEIN_VOLUME node
  966. INIT_NODE (NODE_LINEIN_VOLUME,
  967. CurrentNode,
  968. &KSNODETYPE_VOLUME,
  969. &KSAUDFNAME_LINE_IN_VOLUME,
  970. &AutomationVolume,
  971. Index);
  972. // add the NODE_LINEIN_MUTE node
  973. INIT_NODE (NODE_LINEIN_MUTE,
  974. CurrentNode,
  975. &KSNODETYPE_MUTE,
  976. &ICHFNAME_LINEIN_MUTE,
  977. &AutomationMute,
  978. Index);
  979. }
  980. if (AdapterCommon->GetPinConfig (PINC_CD_PRESENT))
  981. {
  982. // add the NODE_CD_VOLUME node
  983. INIT_NODE (NODE_CD_VOLUME,
  984. CurrentNode,
  985. &KSNODETYPE_VOLUME,
  986. &KSAUDFNAME_CD_VOLUME,
  987. &AutomationVolume,
  988. Index);
  989. // add the NODE_CD_MUTE node
  990. INIT_NODE (NODE_CD_MUTE,
  991. CurrentNode,
  992. &KSNODETYPE_MUTE,
  993. &KSAUDFNAME_CD_MUTE,
  994. &AutomationMute,
  995. Index);
  996. }
  997. // add the VIDEO nodes
  998. if (AdapterCommon->GetPinConfig (PINC_VIDEO_PRESENT))
  999. {
  1000. // add the NODE_VIDEO_VOLUME node
  1001. INIT_NODE (NODE_VIDEO_VOLUME,
  1002. CurrentNode,
  1003. &KSNODETYPE_VOLUME,
  1004. &KSAUDFNAME_VIDEO_VOLUME,
  1005. &AutomationVolume,
  1006. Index);
  1007. // add the NODE_VIDEO_MUTE node
  1008. INIT_NODE (NODE_VIDEO_MUTE,
  1009. CurrentNode,
  1010. &KSNODETYPE_MUTE,
  1011. &KSAUDFNAME_VIDEO_MUTE,
  1012. &AutomationMute,
  1013. Index);
  1014. }
  1015. // add the AUX nodes
  1016. if (AdapterCommon->GetPinConfig (PINC_AUX_PRESENT))
  1017. {
  1018. // add the NODE_AUX_VOLUME node
  1019. INIT_NODE (NODE_AUX_VOLUME,
  1020. CurrentNode,
  1021. &KSNODETYPE_VOLUME,
  1022. &KSAUDFNAME_AUX_VOLUME,
  1023. &AutomationVolume,
  1024. Index);
  1025. // add the NODE_AUX_MUTE node
  1026. INIT_NODE (NODE_AUX_MUTE,
  1027. CurrentNode,
  1028. &KSNODETYPE_MUTE,
  1029. &KSAUDFNAME_AUX_MUTE,
  1030. &AutomationMute,
  1031. Index);
  1032. }
  1033. // add the NODE_MAIN_MIX node
  1034. INIT_NODE (NODE_MAIN_MIX,
  1035. CurrentNode,
  1036. &KSNODETYPE_SUM,
  1037. &ICHFNAME_MAIN_MIX,
  1038. NULL,
  1039. Index);
  1040. // add the 3D nodes
  1041. if (AdapterCommon->GetNodeConfig (NODEC_3D_PRESENT))
  1042. {
  1043. if (AdapterCommon->GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE))
  1044. {
  1045. // add the NODE_VIRT_3D_CENTER node
  1046. INIT_NODE (NODE_VIRT_3D_CENTER,
  1047. CurrentNode,
  1048. &KSNODETYPE_VOLUME,
  1049. &KSAUDFNAME_3D_CENTER,
  1050. &Automation3D,
  1051. Index);
  1052. }
  1053. if (AdapterCommon->GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE) ||
  1054. (!AdapterCommon->GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE) &&
  1055. !AdapterCommon->GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE)))
  1056. {
  1057. // add the NODE_VIRT_3D_DEPTH node
  1058. INIT_NODE (NODE_VIRT_3D_DEPTH,
  1059. CurrentNode,
  1060. &KSNODETYPE_VOLUME,
  1061. &KSAUDFNAME_3D_DEPTH,
  1062. &Automation3D,
  1063. Index);
  1064. }
  1065. // add the NODE_VIRT_3D_ENABLE node
  1066. INIT_NODE (NODE_VIRT_3D_ENABLE,
  1067. CurrentNode,
  1068. &KSNODETYPE_LOUDNESS,
  1069. &ICHFNAME_3D_ENABLE,
  1070. &AutomationSpecial,
  1071. Index);
  1072. // add the NODE_VIRT_WAVEOUT_3D_BYPASS node
  1073. INIT_NODE (NODE_VIRT_WAVEOUT_3D_BYPASS,
  1074. CurrentNode,
  1075. &KSNODETYPE_AGC,
  1076. &ICHFNAME_WAVEOUT_3D_BYPASS,
  1077. &AutomationSpecial,
  1078. Index);
  1079. }
  1080. if (AdapterCommon->GetPinConfig (PINC_PCBEEP_PRESENT) ||
  1081. AdapterCommon->GetPinConfig (PINC_PHONE_PRESENT))
  1082. {
  1083. // add the NODE_BEEP_MIX node
  1084. INIT_NODE (NODE_BEEP_MIX,
  1085. CurrentNode,
  1086. &KSNODETYPE_SUM,
  1087. &ICHFNAME_BEEP_MIX,
  1088. NULL,
  1089. Index);
  1090. }
  1091. // add the tone nodes
  1092. if (AdapterCommon->GetNodeConfig (NODEC_TONE_PRESENT))
  1093. {
  1094. // add the NODE_BASS node
  1095. INIT_NODE (NODE_BASS,
  1096. CurrentNode,
  1097. &KSNODETYPE_TONE,
  1098. &KSAUDFNAME_BASS,
  1099. &AutomationTone,
  1100. Index);
  1101. // add the NODE_TREBLE node
  1102. INIT_NODE (NODE_TREBLE,
  1103. CurrentNode,
  1104. &KSNODETYPE_TONE,
  1105. &KSAUDFNAME_TREBLE,
  1106. &AutomationTone,
  1107. Index);
  1108. if (AdapterCommon->GetNodeConfig (NODEC_LOUDNESS_PRESENT))
  1109. {
  1110. // add the NODE_LOUDNESS node
  1111. INIT_NODE (NODE_LOUDNESS,
  1112. CurrentNode,
  1113. &KSNODETYPE_LOUDNESS,
  1114. NULL,
  1115. &AutomationSpecial,
  1116. Index);
  1117. }
  1118. if (AdapterCommon->GetNodeConfig (NODEC_SIMUL_STEREO_PRESENT))
  1119. {
  1120. // add the NODE_SIMUL_STEREO node
  1121. INIT_NODE (NODE_SIMUL_STEREO,
  1122. CurrentNode,
  1123. &KSNODETYPE_AGC,
  1124. &ICHFNAME_SIMUL_STEREO,
  1125. &AutomationSpecial,
  1126. Index);
  1127. }
  1128. }
  1129. // Add a "Front Speaker" volume/mute if we have surround or headphones.
  1130. // The "Master" volume/mute will be mono then
  1131. if (AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT) ||
  1132. AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
  1133. {
  1134. // Add the front speaker volume.
  1135. INIT_NODE (NODE_FRONT_VOLUME,
  1136. CurrentNode,
  1137. &KSNODETYPE_VOLUME,
  1138. &ICHFNAME_FRONT_VOLUME,
  1139. &AutomationVolume,
  1140. Index);
  1141. // Add the front speaker mute.
  1142. INIT_NODE (NODE_FRONT_MUTE,
  1143. CurrentNode,
  1144. &KSNODETYPE_MUTE,
  1145. &ICHFNAME_FRONT_MUTE,
  1146. &AutomationMute,
  1147. Index);
  1148. // Add the master mono out volume.
  1149. INIT_NODE (NODE_VIRT_MASTERMONO_VOLUME,
  1150. CurrentNode,
  1151. &KSNODETYPE_VOLUME,
  1152. &KSAUDFNAME_MASTER_VOLUME,
  1153. &AutomationVolume,
  1154. Index);
  1155. // Add the master mono out volume.
  1156. INIT_NODE (NODE_VIRT_MASTERMONO_MUTE,
  1157. CurrentNode,
  1158. &KSNODETYPE_MUTE,
  1159. &KSAUDFNAME_MASTER_MUTE,
  1160. &AutomationMute,
  1161. Index);
  1162. }
  1163. else
  1164. {
  1165. // add the NODE_MASTEROUT_VOLUME node
  1166. INIT_NODE (NODE_MASTEROUT_VOLUME,
  1167. CurrentNode,
  1168. &KSNODETYPE_VOLUME,
  1169. &KSAUDFNAME_MASTER_VOLUME,
  1170. &AutomationVolume,
  1171. Index);
  1172. // add the NODE_MASTEROUT_MUTE node
  1173. INIT_NODE (NODE_MASTEROUT_MUTE,
  1174. CurrentNode,
  1175. &KSNODETYPE_MUTE,
  1176. &KSAUDFNAME_MASTER_MUTE,
  1177. &AutomationMute,
  1178. Index);
  1179. }
  1180. // Add the surround control if we have one.
  1181. if (AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT))
  1182. {
  1183. // Add the surround volume.
  1184. INIT_NODE (NODE_SURROUND_VOLUME,
  1185. CurrentNode,
  1186. &KSNODETYPE_VOLUME,
  1187. &ICHFNAME_SURROUND_VOLUME,
  1188. &AutomationVolume,
  1189. Index);
  1190. // Add the surround mute.
  1191. INIT_NODE (NODE_SURROUND_MUTE,
  1192. CurrentNode,
  1193. &KSNODETYPE_MUTE,
  1194. &ICHFNAME_SURROUND_MUTE,
  1195. &AutomationMute,
  1196. Index);
  1197. // Add the center and LFE control if we have one.
  1198. if (AdapterCommon->GetPinConfig (PINC_CENTER_LFE_PRESENT))
  1199. {
  1200. // Add the center volume.
  1201. INIT_NODE (NODE_CENTER_VOLUME,
  1202. CurrentNode,
  1203. &KSNODETYPE_VOLUME,
  1204. &ICHFNAME_CENTER_VOLUME,
  1205. &AutomationVolume,
  1206. Index);
  1207. // Add the center mute.
  1208. INIT_NODE (NODE_CENTER_MUTE,
  1209. CurrentNode,
  1210. &KSNODETYPE_MUTE,
  1211. &ICHFNAME_CENTER_MUTE,
  1212. &AutomationMute,
  1213. Index);
  1214. // Add the LFE volume.
  1215. INIT_NODE (NODE_LFE_VOLUME,
  1216. CurrentNode,
  1217. &KSNODETYPE_VOLUME,
  1218. &ICHFNAME_LFE_VOLUME,
  1219. &AutomationVolume,
  1220. Index);
  1221. // Add the LFE mute.
  1222. INIT_NODE (NODE_LFE_MUTE,
  1223. CurrentNode,
  1224. &KSNODETYPE_MUTE,
  1225. &ICHFNAME_LFE_MUTE,
  1226. &AutomationMute,
  1227. Index);
  1228. }
  1229. }
  1230. // add the HPOUT nodes
  1231. if (AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
  1232. {
  1233. // add the NODE_HPOUT_VOLUME node
  1234. INIT_NODE (NODE_HPOUT_VOLUME,
  1235. CurrentNode,
  1236. &KSNODETYPE_VOLUME,
  1237. &ICHFNAME_HPOUT_VOLUME,
  1238. &AutomationVolume,
  1239. Index);
  1240. // add the NODE_HPOUT_MUTE node
  1241. INIT_NODE (NODE_HPOUT_MUTE,
  1242. CurrentNode,
  1243. &KSNODETYPE_MUTE,
  1244. &ICHFNAME_HPOUT_MUTE,
  1245. &AutomationMute,
  1246. Index);
  1247. }
  1248. // add the NODE_WAVEIN_SELECT node
  1249. INIT_NODE (NODE_WAVEIN_SELECT,
  1250. CurrentNode,
  1251. &KSNODETYPE_MUX,
  1252. &ICHFNAME_WAVEIN_SELECT,
  1253. &AutomationMux,
  1254. Index);
  1255. if (AdapterCommon->GetPinConfig (PINC_MIC_PRESENT))
  1256. {
  1257. // add the NODE_VIRT_MASTER_INPUT_VOLUME1 node
  1258. INIT_NODE (NODE_VIRT_MASTER_INPUT_VOLUME1,
  1259. CurrentNode,
  1260. &KSNODETYPE_VOLUME,
  1261. &KSAUDFNAME_MIC_VOLUME,
  1262. &AutomationVolume,
  1263. Index);
  1264. }
  1265. if (AdapterCommon->GetPinConfig (PINC_CD_PRESENT))
  1266. {
  1267. // add the NODE_VIRT_MASTER_INPUT_VOLUME2 node
  1268. INIT_NODE (NODE_VIRT_MASTER_INPUT_VOLUME2,
  1269. CurrentNode,
  1270. &KSNODETYPE_VOLUME,
  1271. &KSAUDFNAME_CD_VOLUME,
  1272. &AutomationVolume,
  1273. Index);
  1274. }
  1275. if (AdapterCommon->GetPinConfig (PINC_VIDEO_PRESENT))
  1276. {
  1277. // add the NODE_VIRT_MASTER_INPUT_VOLUME3 node
  1278. INIT_NODE (NODE_VIRT_MASTER_INPUT_VOLUME3,
  1279. CurrentNode,
  1280. &KSNODETYPE_VOLUME,
  1281. &KSAUDFNAME_VIDEO_VOLUME,
  1282. &AutomationVolume,
  1283. Index);
  1284. }
  1285. if (AdapterCommon->GetPinConfig (PINC_AUX_PRESENT))
  1286. {
  1287. // add the NODE_VIRT_MASTER_INPUT_VOLUME4 node
  1288. INIT_NODE (NODE_VIRT_MASTER_INPUT_VOLUME4,
  1289. CurrentNode,
  1290. &KSNODETYPE_VOLUME,
  1291. &KSAUDFNAME_AUX_VOLUME,
  1292. &AutomationVolume,
  1293. Index);
  1294. }
  1295. if (AdapterCommon->GetPinConfig (PINC_LINEIN_PRESENT))
  1296. {
  1297. // add the NODE_VIRT_MASTER_INPUT_VOLUME5 node
  1298. INIT_NODE (NODE_VIRT_MASTER_INPUT_VOLUME5,
  1299. CurrentNode,
  1300. &KSNODETYPE_VOLUME,
  1301. &KSAUDFNAME_LINE_IN_VOLUME,
  1302. &AutomationVolume,
  1303. Index);
  1304. }
  1305. // add the NODE_VIRT_MASTER_INPUT_VOLUME6 node
  1306. INIT_NODE (NODE_VIRT_MASTER_INPUT_VOLUME6,
  1307. CurrentNode,
  1308. &KSNODETYPE_VOLUME,
  1309. &KSAUDFNAME_STEREO_MIX_VOLUME,
  1310. &AutomationVolume,
  1311. Index);
  1312. // add the NODE_VIRT_MASTER_INPUT_VOLUME7 node
  1313. INIT_NODE (NODE_VIRT_MASTER_INPUT_VOLUME7,
  1314. CurrentNode,
  1315. &KSNODETYPE_VOLUME,
  1316. &KSAUDFNAME_MONO_MIX_VOLUME,
  1317. &AutomationVolume,
  1318. Index);
  1319. if (AdapterCommon->GetPinConfig (PINC_PHONE_PRESENT))
  1320. {
  1321. // add the NODE_VIRT_MASTER_INPUT_VOLUME8 node
  1322. INIT_NODE (NODE_VIRT_MASTER_INPUT_VOLUME8,
  1323. CurrentNode,
  1324. &KSNODETYPE_VOLUME,
  1325. &ICHFNAME_MASTER_INPUT_VOLUME,
  1326. &AutomationVolume,
  1327. Index);
  1328. }
  1329. // add the MICIN nodes
  1330. if (AdapterCommon->GetPinConfig (PINC_MIC_PRESENT) &&
  1331. AdapterCommon->GetPinConfig (PINC_MICIN_PRESENT))
  1332. {
  1333. // add the NODE_MICIN_VOLUME node
  1334. INIT_NODE (NODE_MICIN_VOLUME,
  1335. CurrentNode,
  1336. &KSNODETYPE_VOLUME,
  1337. &ICHFNAME_MICIN_VOLUME,
  1338. &AutomationVolume,
  1339. Index);
  1340. // add the NODE_MICIN_MUTE node
  1341. INIT_NODE (NODE_MICIN_MUTE,
  1342. CurrentNode,
  1343. &KSNODETYPE_MUTE,
  1344. &ICHFNAME_MICIN_MUTE,
  1345. &AutomationMute,
  1346. Index);
  1347. }
  1348. // add the MONOOUT nodes
  1349. if (AdapterCommon->GetPinConfig (PINC_MONOOUT_PRESENT))
  1350. {
  1351. // add the NODE_MONOOUT_SELECT node
  1352. INIT_NODE (NODE_MONOOUT_SELECT,
  1353. CurrentNode,
  1354. &KSNODETYPE_MUX,
  1355. &ICHFNAME_MONOOUT_SELECT,
  1356. &AutomationMux,
  1357. Index);
  1358. // add the NODE_VIRT_MONOOUT_VOLUME1 node
  1359. INIT_NODE (NODE_VIRT_MONOOUT_VOLUME1,
  1360. CurrentNode,
  1361. &KSNODETYPE_VOLUME,
  1362. &KSAUDFNAME_MONO_MIX_VOLUME,
  1363. &AutomationVolume,
  1364. Index);
  1365. // add the NODE_VIRT_MONOOUT_VOLUME2 node
  1366. INIT_NODE (NODE_VIRT_MONOOUT_VOLUME2,
  1367. CurrentNode,
  1368. &KSNODETYPE_VOLUME,
  1369. &KSAUDFNAME_MIC_VOLUME,
  1370. &AutomationVolume,
  1371. Index);
  1372. }
  1373. // add the nodes to the filter descriptor
  1374. FilterDescriptor->NodeCount = Index;
  1375. FilterDescriptor->NodeSize = sizeof(PCNODE_DESCRIPTOR);
  1376. FilterDescriptor->Nodes = NodeDescriptors;
  1377. }
  1378. else
  1379. {
  1380. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1381. }
  1382. return ntStatus;
  1383. #undef INIT_NODE
  1384. }
  1385. /*****************************************************************************
  1386. * CMiniportTopologyICH::BuildConnectionDescriptors
  1387. *****************************************************************************
  1388. * Builds the topology connection descriptors.
  1389. */
  1390. NTSTATUS CMiniportTopologyICH::BuildConnectionDescriptors (void)
  1391. {
  1392. // Improvement would be to not use a Macro, use (inline) function instead.
  1393. // for node to node connections
  1394. #define INIT_NN_CONN( cptr, fnode, fpin, tnode, tpin ) \
  1395. cptr->FromNode = TransNodeDefToNodeNr (fnode); \
  1396. cptr->FromNodePin = fpin; \
  1397. cptr->ToNode = TransNodeDefToNodeNr (tnode); \
  1398. cptr->ToNodePin = tpin; \
  1399. cptr++,ConnectionCount++
  1400. // for filter pin to node connections
  1401. #define INIT_FN_CONN( cptr, fpin, tnode, tpin ) \
  1402. cptr->FromNode = KSFILTER_NODE; \
  1403. cptr->FromNodePin = TransPinDefToPinNr (fpin); \
  1404. cptr->ToNode = TransNodeDefToNodeNr (tnode); \
  1405. cptr->ToNodePin = tpin; \
  1406. cptr++,ConnectionCount++
  1407. // for node to filter pin connections
  1408. #define INIT_NF_CONN( cptr, fnode, fpin, tpin ) \
  1409. cptr->FromNode = TransNodeDefToNodeNr (fnode); \
  1410. cptr->FromNodePin = fpin; \
  1411. cptr->ToNode = KSFILTER_NODE; \
  1412. cptr->ToNodePin = TransPinDefToPinNr (tpin); \
  1413. cptr++,ConnectionCount++
  1414. PAGED_CODE ();
  1415. NTSTATUS ntStatus = STATUS_SUCCESS;
  1416. ULONG ConnectionCount = 0;
  1417. DOUT (DBG_PRINT, ("[CMiniportTopologyICH::BuildConnectionDescriptors]"));
  1418. // allocate our descriptor memory
  1419. ConnectionDescriptors = PPCCONNECTION_DESCRIPTOR (ExAllocatePool (PagedPool,
  1420. TOPO_MAX_CONNECTIONS * sizeof(PCCONNECTION_DESCRIPTOR)));
  1421. if (ConnectionDescriptors)
  1422. {
  1423. PPCCONNECTION_DESCRIPTOR CurrentConnection = ConnectionDescriptors;
  1424. // build the wave out (coming in) path
  1425. // PIN_WAVEOUT_SOURCE -> NODE_WAVEOUT_VOLUME
  1426. INIT_FN_CONN (CurrentConnection, PIN_WAVEOUT_SOURCE, NODE_WAVEOUT_VOLUME, 1);
  1427. // NODE_WAVEOUT_VOLUME -> NODE_WAVEOUT_MUTE
  1428. INIT_NN_CONN (CurrentConnection, NODE_WAVEOUT_VOLUME, 0, NODE_WAVEOUT_MUTE, 1);
  1429. // NODE_WAVEOUT_MUTE -> NODE_MAIN_MIX
  1430. INIT_NN_CONN (CurrentConnection, NODE_WAVEOUT_MUTE, 0, NODE_MAIN_MIX, 1);
  1431. // build the PC beeper path
  1432. if (AdapterCommon->GetPinConfig (PINC_PCBEEP_PRESENT))
  1433. {
  1434. // PIN_PCBEEP_SOURCE -> NODE_PCBEEP_VOLUME
  1435. INIT_FN_CONN (CurrentConnection, PIN_PCBEEP_SOURCE, NODE_PCBEEP_VOLUME, 1);
  1436. // NODE_PCBEEP_VOLUME -> NODE_PCBEEP_MUTE
  1437. INIT_NN_CONN (CurrentConnection, NODE_PCBEEP_VOLUME, 0, NODE_PCBEEP_MUTE, 1);
  1438. // NODE_PCBEEP_MUTE -> NODE_BEEP_MIX
  1439. INIT_NN_CONN (CurrentConnection, NODE_PCBEEP_MUTE, 0, NODE_BEEP_MIX, 2);
  1440. }
  1441. // build the phone path
  1442. if (AdapterCommon->GetPinConfig (PINC_PHONE_PRESENT))
  1443. {
  1444. // PIN_PHONE_SOURCE -> NODE_PHONE_VOLUME
  1445. INIT_FN_CONN (CurrentConnection, PIN_PHONE_SOURCE, NODE_PHONE_VOLUME, 1);
  1446. // NODE_PHONE_VOLUME -> NODE_PHONE_MUTE
  1447. INIT_NN_CONN (CurrentConnection, NODE_PHONE_VOLUME, 0, NODE_PHONE_MUTE, 1);
  1448. // NODE_PHONE_MUTE -> LINEOUT_BEEP_MIX
  1449. INIT_NN_CONN (CurrentConnection, NODE_PHONE_MUTE, 0, NODE_BEEP_MIX, 3);
  1450. // PIN_PHONE_SOURCE pin -> NODE_VIRT_MASTER_INPUT_VOLUME8
  1451. INIT_FN_CONN (CurrentConnection, PIN_PHONE_SOURCE, NODE_VIRT_MASTER_INPUT_VOLUME8, 1);
  1452. // NODE_VIRT_MASTER_INPUT_VOLUME8 -> NODE_WAVEIN_SELECT
  1453. INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTER_INPUT_VOLUME8, 0, NODE_WAVEIN_SELECT, 8);
  1454. }
  1455. // build MIC path
  1456. if (AdapterCommon->GetPinConfig (PINC_MIC_PRESENT))
  1457. {
  1458. // build the MIC selector in case we have 2 MICs
  1459. if (AdapterCommon->GetPinConfig (PINC_MIC2_PRESENT))
  1460. {
  1461. // PIN_MIC_SOURCE pin -> NODE_MIC_SELECT
  1462. INIT_FN_CONN (CurrentConnection, PIN_MIC_SOURCE, NODE_MIC_SELECT, 1);
  1463. // NODE_MIC_SELECT -> NODE_MIC_BOOST
  1464. INIT_NN_CONN (CurrentConnection, NODE_MIC_SELECT, 0, NODE_MIC_BOOST, 1);
  1465. }
  1466. else
  1467. {
  1468. // PIN_MIC_SOURCE pin -> NODE_MIC_SELECT
  1469. INIT_FN_CONN (CurrentConnection, PIN_MIC_SOURCE, NODE_MIC_BOOST, 1);
  1470. }
  1471. // NODE_MIC_BOOST -> NODE_MIC_VOLUME
  1472. INIT_NN_CONN (CurrentConnection, NODE_MIC_BOOST, 0, NODE_MIC_VOLUME, 1);
  1473. // NODE_MIC_VOLUME -> NODE_MIC_MUTE
  1474. INIT_NN_CONN (CurrentConnection, NODE_MIC_VOLUME, 0, NODE_MIC_MUTE, 1);
  1475. // NODE_MIC_MUTE -> NODE_MAIN_MIX
  1476. INIT_NN_CONN (CurrentConnection, NODE_MIC_MUTE, 0, NODE_MAIN_MIX, 2);
  1477. // NODE_MIC_BOOST -> NODE_VIRT_MASTER_INPUT_VOLUME1
  1478. INIT_NN_CONN (CurrentConnection, NODE_MIC_BOOST, 0, NODE_VIRT_MASTER_INPUT_VOLUME1, 1);
  1479. // NODE_VIRT_MASTER_INPUT_VOLUME1 -> NODE_WAVEIN_SELECT
  1480. INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTER_INPUT_VOLUME1, 0, NODE_WAVEIN_SELECT, 1);
  1481. }
  1482. // build the line in path
  1483. if (AdapterCommon->GetPinConfig (PINC_LINEIN_PRESENT))
  1484. {
  1485. // PIN_LINEIN_SOURCE -> NODE_LINEIN_VOLUME
  1486. INIT_FN_CONN (CurrentConnection, PIN_LINEIN_SOURCE, NODE_LINEIN_VOLUME, 1);
  1487. // NODE_LINEIN_VOLUME -> NODE_LINEIN_MUTE
  1488. INIT_NN_CONN (CurrentConnection, NODE_LINEIN_VOLUME, 0, NODE_LINEIN_MUTE, 1);
  1489. // NODE_LINEIN_MUTE -> NODE_MAIN_MIX
  1490. INIT_NN_CONN (CurrentConnection, NODE_LINEIN_MUTE, 0, NODE_MAIN_MIX, 3);
  1491. // PIN_LINEIN_SOURCE pin -> NODE_VIRT_MASTER_INPUT_VOLUME5
  1492. INIT_FN_CONN (CurrentConnection, PIN_LINEIN_SOURCE, NODE_VIRT_MASTER_INPUT_VOLUME5, 1);
  1493. // NODE_VIRT_MASTER_INPUT_VOLUME5 -> NODE_WAVEIN_SELECT
  1494. INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTER_INPUT_VOLUME5, 0, NODE_WAVEIN_SELECT, 5);
  1495. }
  1496. // build the CD path
  1497. if (AdapterCommon->GetPinConfig (PINC_CD_PRESENT))
  1498. {
  1499. // PIN_CD_SOURCE -> NODE_CD_VOLUME
  1500. INIT_FN_CONN (CurrentConnection, PIN_CD_SOURCE, NODE_CD_VOLUME, 1);
  1501. // NODE_CD_VOLUME -> NODE_CD_MUTE
  1502. INIT_NN_CONN (CurrentConnection, NODE_CD_VOLUME, 0, NODE_CD_MUTE, 1);
  1503. // NODE_CD_MUTE -> NODE_MAIN_MIX
  1504. INIT_NN_CONN (CurrentConnection, NODE_CD_MUTE, 0, NODE_MAIN_MIX, 4);
  1505. // PIN_CD_SOURCE pin -> NODE_VIRT_MASTER_INPUT_VOLUME2
  1506. INIT_FN_CONN (CurrentConnection, PIN_CD_SOURCE, NODE_VIRT_MASTER_INPUT_VOLUME2, 1);
  1507. // NODE_VIRT_MASTER_INPUT_VOLUME2 -> NODE_WAVEIN_SELECT
  1508. INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTER_INPUT_VOLUME2, 0, NODE_WAVEIN_SELECT, 2);
  1509. }
  1510. // build the video path
  1511. if (AdapterCommon->GetPinConfig (PINC_VIDEO_PRESENT))
  1512. {
  1513. // PIN_VIDEO_SOURCE -> NODE_VIDEO_VOLUME
  1514. INIT_FN_CONN (CurrentConnection, PIN_VIDEO_SOURCE, NODE_VIDEO_VOLUME, 1);
  1515. // NODE_VIDEO_VOLUME -> NODE_VIDEO_MUTE
  1516. INIT_NN_CONN (CurrentConnection, NODE_VIDEO_VOLUME, 0, NODE_VIDEO_MUTE, 1);
  1517. // NODE_VIDEO_MUTE -> NODE_MAIN_MIX
  1518. INIT_NN_CONN (CurrentConnection, NODE_VIDEO_MUTE, 0, NODE_MAIN_MIX, 5);
  1519. // PIN_VIDEO_SOURCE pin -> NODE_VIRT_MASTER_INPUT_VOLUME3
  1520. INIT_FN_CONN (CurrentConnection, PIN_VIDEO_SOURCE, NODE_VIRT_MASTER_INPUT_VOLUME3, 1);
  1521. // NODE_VIRT_MASTER_INPUT_VOLUME3 -> NODE_WAVEIN_SELECT
  1522. INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTER_INPUT_VOLUME3, 0, NODE_WAVEIN_SELECT, 3);
  1523. }
  1524. // build the AUX path
  1525. if (AdapterCommon->GetPinConfig (PINC_AUX_PRESENT))
  1526. {
  1527. // PIN_AUX_SOURCE pin -> NODE_AUX_VOLUME
  1528. INIT_FN_CONN (CurrentConnection, PIN_AUX_SOURCE, NODE_AUX_VOLUME, 1);
  1529. // NODE_AUX_VOLUME -> NODE_AUX_MUTE
  1530. INIT_NN_CONN (CurrentConnection, NODE_AUX_VOLUME, 0, NODE_AUX_MUTE, 1);
  1531. // NODE_AUX_MUTE -> NODE_MAIN_MIX
  1532. INIT_NN_CONN (CurrentConnection, NODE_AUX_MUTE, 0, NODE_MAIN_MIX, 6);
  1533. // PIN_AUX_SOURCE pin -> NODE_VIRT_MASTER_INPUT_VOLUME4
  1534. INIT_FN_CONN (CurrentConnection, PIN_AUX_SOURCE, NODE_VIRT_MASTER_INPUT_VOLUME4, 1);
  1535. // NODE_VIRT_MASTER_INPUT_VOLUME4 -> NODE_WAVEIN_SELECT
  1536. INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTER_INPUT_VOLUME4, 0, NODE_WAVEIN_SELECT, 4);
  1537. }
  1538. // and build the head phone output.
  1539. // we connect the headphones like an input so that it's in the playback panel.
  1540. if (AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
  1541. {
  1542. // from whatever -> NODE_HPOUT_VOLUME
  1543. INIT_FN_CONN (CurrentConnection, PIN_HPOUT_SOURCE, NODE_HPOUT_VOLUME, 1);
  1544. // NODE_HPOUT_VOLUME -> NODE_HPOUT_MUTE
  1545. INIT_NN_CONN (CurrentConnection, NODE_HPOUT_VOLUME, 0, NODE_HPOUT_MUTE, 1);
  1546. // NODE_HPOUT_MUTE -> PIN_HPOUT_DEST pin
  1547. INIT_NN_CONN( CurrentConnection, NODE_HPOUT_MUTE, 0, NODE_MAIN_MIX, 9);
  1548. }
  1549. // build the 3D path
  1550. if (AdapterCommon->GetNodeConfig (NODEC_3D_PRESENT))
  1551. {
  1552. // Figure out what the main 3D line is.
  1553. if (AdapterCommon->GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE))
  1554. {
  1555. if (AdapterCommon->GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE))
  1556. {
  1557. // PIN_VIRT_3D_DEPTH_SOURCE -> NODE_VIRT_3D_ENABLE
  1558. INIT_FN_CONN (CurrentConnection, PIN_VIRT_3D_DEPTH_SOURCE, NODE_VIRT_3D_ENABLE, 1);
  1559. // NODE_VIRT_3D_ENABLE -> NODE_VIRT_WAVEOUT_3D_BYPASS
  1560. INIT_NN_CONN (CurrentConnection, NODE_VIRT_3D_ENABLE, 0, NODE_VIRT_WAVEOUT_3D_BYPASS, 1);
  1561. // NODE_VIRT_WAVEOUT_3D_BYPASS -> NODE_VIRT_3D_DEPTH
  1562. INIT_NN_CONN (CurrentConnection, NODE_VIRT_WAVEOUT_3D_BYPASS, 0, NODE_VIRT_3D_DEPTH, 1);
  1563. // NODE_VIRT_3D_DEPTH -> NODE_MAIN_MIX
  1564. INIT_NN_CONN (CurrentConnection, NODE_VIRT_3D_DEPTH, 0, NODE_MAIN_MIX, 7);
  1565. // PIN_VIRT_3D_CENTER_SOURCE -> NODE_VIRT_3D_CENTER
  1566. INIT_FN_CONN (CurrentConnection, PIN_VIRT_3D_CENTER_SOURCE, NODE_VIRT_3D_CENTER, 1);
  1567. // NODE_VIRT_3D_CENTER -> NODE_MAIN_MIX
  1568. INIT_NN_CONN (CurrentConnection, NODE_VIRT_3D_CENTER, 0, NODE_MAIN_MIX, 8);
  1569. }
  1570. else
  1571. {
  1572. // PIN_VIRT_3D_CENTER_SOURCE -> NODE_VIRT_3D_ENABLE
  1573. INIT_FN_CONN (CurrentConnection, PIN_VIRT_3D_CENTER_SOURCE, NODE_VIRT_3D_ENABLE, 1);
  1574. // NODE_VIRT_3D_ENABLE -> NODE_VIRT_WAVEOUT_3D_BYPASS
  1575. INIT_NN_CONN (CurrentConnection, NODE_VIRT_3D_ENABLE, 0, NODE_VIRT_WAVEOUT_3D_BYPASS, 1);
  1576. // NODE_VIRT_WAVEOUT_3D_BYPASS -> NODE_VIRT_3D_CENTER
  1577. INIT_NN_CONN (CurrentConnection, NODE_VIRT_WAVEOUT_3D_BYPASS, 0, NODE_VIRT_3D_CENTER, 1);
  1578. // NODE_VIRT_3D_CENTER -> NODE_MAIN_MIX
  1579. INIT_NN_CONN (CurrentConnection, NODE_VIRT_3D_CENTER, 0, NODE_MAIN_MIX, 8);
  1580. }
  1581. }
  1582. else
  1583. {
  1584. // PIN_VIRT_3D_DEPTH_SOURCE -> NODE_VIRT_3D_ENABLE
  1585. INIT_FN_CONN (CurrentConnection, PIN_VIRT_3D_DEPTH_SOURCE, NODE_VIRT_3D_ENABLE, 1);
  1586. // NODE_VIRT_3D_ENABLE -> NODE_VIRT_WAVEOUT_3D_BYPASS
  1587. INIT_NN_CONN (CurrentConnection, NODE_VIRT_3D_ENABLE, 0, NODE_VIRT_WAVEOUT_3D_BYPASS, 1);
  1588. // NODE_VIRT_WAVEOUT_3D_BYPASS -> NODE_VIRT_3D_DEPTH
  1589. INIT_NN_CONN (CurrentConnection, NODE_VIRT_WAVEOUT_3D_BYPASS, 0, NODE_VIRT_3D_DEPTH, 1);
  1590. // NODE_VIRT_3D_DEPTH -> NODE_MAIN_MIX
  1591. INIT_NN_CONN (CurrentConnection, NODE_VIRT_3D_DEPTH, 0, NODE_MAIN_MIX, 7);
  1592. }
  1593. }
  1594. // build the 4 or 6 channel controls
  1595. // In case of multichannel or headphone we have "front speakers" volume/mute.
  1596. if (AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT) ||
  1597. AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
  1598. {
  1599. // PIN_VIRT_FRONT_SOURCE -> NODE_FRONT_VOLUME
  1600. INIT_FN_CONN (CurrentConnection, PIN_VIRT_FRONT_SOURCE, NODE_FRONT_VOLUME, 1);
  1601. // NODE_FRONT_VOLUME -> NODE_FRONT_MUTE
  1602. INIT_NN_CONN (CurrentConnection, NODE_FRONT_VOLUME, 0, NODE_FRONT_MUTE, 1);
  1603. // NODE_FRONT_MUTE -> NODE_MAIN_MIX
  1604. INIT_NN_CONN (CurrentConnection, NODE_FRONT_MUTE, 0, NODE_MAIN_MIX, 10);
  1605. }
  1606. // Check for surround volumes
  1607. if (AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT))
  1608. {
  1609. // PIN_VIRT_SURROUND -> NODE_SURROUND_VOLUME
  1610. INIT_FN_CONN (CurrentConnection, PIN_VIRT_SURROUND_SOURCE, NODE_SURROUND_VOLUME, 1);
  1611. // NODE_SURROUND_VOLUME -> NODE_SURROUND_MUTE
  1612. INIT_NN_CONN (CurrentConnection, NODE_SURROUND_VOLUME, 0, NODE_SURROUND_MUTE, 1);
  1613. // NODE_SURROUND_MUTE -> NODE_MAIN_MIX
  1614. INIT_NN_CONN (CurrentConnection, NODE_SURROUND_MUTE, 0, NODE_MAIN_MIX, 11);
  1615. // check also for the center and LFE volumes
  1616. if (AdapterCommon->GetPinConfig (PINC_CENTER_LFE_PRESENT))
  1617. {
  1618. // PIN_VIRT_CENTER -> NODE_CENTER_VOLUME
  1619. INIT_FN_CONN (CurrentConnection, PIN_VIRT_CENTER_SOURCE, NODE_CENTER_VOLUME, 1);
  1620. // NODE_CENTER_VOLUME -> NODE_CENTER_MUTE
  1621. INIT_NN_CONN (CurrentConnection, NODE_CENTER_VOLUME, 0, NODE_CENTER_MUTE, 1);
  1622. // NODE_CENTER_MUTE -> NODE_MAIN_MIX
  1623. INIT_NN_CONN (CurrentConnection, NODE_CENTER_MUTE, 0, NODE_MAIN_MIX, 12);
  1624. // PIN_VIRT_LFE -> NODE_LFE_VOLUME
  1625. INIT_FN_CONN (CurrentConnection, PIN_VIRT_LFE_SOURCE, NODE_LFE_VOLUME, 1);
  1626. // NODE_LFE_VOLUME -> NODE_LFE_MUTE
  1627. INIT_NN_CONN (CurrentConnection, NODE_LFE_VOLUME, 0, NODE_LFE_MUTE, 1);
  1628. // NODE_LFE_MUTE -> NODE_MAIN_MIX
  1629. INIT_NN_CONN (CurrentConnection, NODE_LFE_MUTE, 0, NODE_MAIN_MIX, 13);
  1630. }
  1631. }
  1632. // helper node variable.
  1633. TopoNodes ConnectFromNode;
  1634. // all connections go from this one
  1635. ConnectFromNode = NODE_MAIN_MIX;
  1636. // build the beeper & phone mix
  1637. if (AdapterCommon->GetPinConfig (PINC_PCBEEP_PRESENT) ||
  1638. AdapterCommon->GetPinConfig (PINC_PHONE_PRESENT))
  1639. {
  1640. // last node -> NODE_BEEP_MIX
  1641. INIT_NN_CONN (CurrentConnection, ConnectFromNode, 0, NODE_BEEP_MIX, 1);
  1642. // next connection from this point.
  1643. ConnectFromNode = NODE_BEEP_MIX;
  1644. }
  1645. // build the tone control path
  1646. if (AdapterCommon->GetNodeConfig (NODEC_TONE_PRESENT))
  1647. {
  1648. // last node -> NODE_BASS
  1649. INIT_NN_CONN (CurrentConnection, ConnectFromNode, 0, NODE_BASS, 1);
  1650. // NODE_BASS -> NODE_TREBLE
  1651. INIT_NN_CONN (CurrentConnection, NODE_BASS, 0, NODE_TREBLE, 1);
  1652. // remember the last node
  1653. ConnectFromNode = NODE_TREBLE;
  1654. // build the loudness control
  1655. if (AdapterCommon->GetNodeConfig (NODEC_LOUDNESS_PRESENT))
  1656. {
  1657. // last node -> NODE_LOUDNESS
  1658. INIT_NN_CONN (CurrentConnection, ConnectFromNode, 0, NODE_LOUDNESS, 1);
  1659. // remember the last node
  1660. ConnectFromNode = NODE_LOUDNESS;
  1661. }
  1662. // build the simulated stereo control
  1663. if (AdapterCommon->GetNodeConfig (NODEC_SIMUL_STEREO_PRESENT))
  1664. {
  1665. // last node -> NODE_SIMUL_STEREO
  1666. INIT_NN_CONN (CurrentConnection, ConnectFromNode, 0, NODE_SIMUL_STEREO, 1);
  1667. // remember the last node
  1668. ConnectFromNode = NODE_SIMUL_STEREO;
  1669. }
  1670. }
  1671. //build the master volume output.
  1672. // In case of multichannel or headphone we use a master mono control.
  1673. if (AdapterCommon->GetPinConfig (PINC_SURROUND_PRESENT) ||
  1674. AdapterCommon->GetPinConfig (PINC_HPOUT_PRESENT))
  1675. {
  1676. // build the connection from whatever to NODE_VIRT_MASTERMONO_VOLUME
  1677. INIT_NN_CONN (CurrentConnection, ConnectFromNode, 0, NODE_VIRT_MASTERMONO_VOLUME, 1);
  1678. // NODE_VIRT_MASTERMONO_VOLUME -> NODE_VIRT_MASTERMONO_MUTE
  1679. INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTERMONO_VOLUME, 0, NODE_VIRT_MASTERMONO_MUTE, 1);
  1680. // NODE_VIRT_MASTERMONO_MUTE -> PIN_MASTEROUT_DEST pin
  1681. INIT_NF_CONN( CurrentConnection, NODE_VIRT_MASTERMONO_MUTE, 0, PIN_MASTEROUT_DEST);
  1682. }
  1683. else
  1684. {
  1685. // build the connection from whatever to NODE_MASTEROUT_VOLUME
  1686. INIT_NN_CONN (CurrentConnection, ConnectFromNode, 0, NODE_MASTEROUT_VOLUME, 1);
  1687. // NODE_MASTEROUT_VOLUME -> NODE_MASTEROUT_MUTE
  1688. INIT_NN_CONN (CurrentConnection, NODE_MASTEROUT_VOLUME, 0, NODE_MASTEROUT_MUTE, 1);
  1689. // NODE_MASTEROUT_MUTE -> PIN_MASTEROUT_DEST pin
  1690. INIT_NF_CONN( CurrentConnection, NODE_MASTEROUT_MUTE, 0, PIN_MASTEROUT_DEST);
  1691. }
  1692. // now complete the input muxer path
  1693. // PIN_VIRT_TONE_MIX_MONO_SOURCE -> NODE_VIRT_MASTER_INPUT_VOLUME7
  1694. INIT_FN_CONN (CurrentConnection, PIN_VIRT_TONE_MIX_MONO_SOURCE, NODE_VIRT_MASTER_INPUT_VOLUME7, 1);
  1695. // NODE_VIRT_MASTER_INPUT_VOLUME7 -> NODE_WAVEIN_SELECT
  1696. INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTER_INPUT_VOLUME7, 0, NODE_WAVEIN_SELECT, 7);
  1697. // PIN_VIRT_TONE_MIX_SOURCE -> NODE_VIRT_MASTER_INPUT_VOLUME6
  1698. INIT_FN_CONN (CurrentConnection, PIN_VIRT_TONE_MIX_SOURCE, NODE_VIRT_MASTER_INPUT_VOLUME6, 1);
  1699. // NODE_VIRT_MASTER_INPUT_VOLUME6 -> NODE_WAVEIN_SELECT
  1700. INIT_NN_CONN (CurrentConnection, NODE_VIRT_MASTER_INPUT_VOLUME6, 0, NODE_WAVEIN_SELECT, 6);
  1701. // NODE_WAVEIN_SELECT -> PIN_WAVEIN_DEST
  1702. INIT_NF_CONN( CurrentConnection, NODE_WAVEIN_SELECT, 0, PIN_WAVEIN_DEST);
  1703. // build the mic output path (for record control)
  1704. if (AdapterCommon->GetPinConfig (PINC_MIC_PRESENT) &&
  1705. AdapterCommon->GetPinConfig (PINC_MICIN_PRESENT))
  1706. {
  1707. // NODE_MIC_BOOST -> NODE_MICIN_VOLUME
  1708. INIT_NN_CONN (CurrentConnection, NODE_MIC_BOOST, 0, NODE_MICIN_VOLUME, 1);
  1709. // NODE_MICIN_VOLUME -> NODE_MICIN_MUTE
  1710. INIT_NN_CONN (CurrentConnection, NODE_MICIN_VOLUME, 0, NODE_MICIN_MUTE, 1);
  1711. // NODE_MICIN_MUTE -> PIN_MICIN_DEST
  1712. INIT_NF_CONN( CurrentConnection, NODE_MICIN_MUTE, 0, PIN_MICIN_DEST);
  1713. }
  1714. // build the mono path
  1715. if (AdapterCommon->GetPinConfig (PINC_MONOOUT_PRESENT))
  1716. {
  1717. // PIN_VIRT_3D_MIX_MONO_SOURCE -> NODE_MONOOUT_SMIX
  1718. INIT_FN_CONN (CurrentConnection, PIN_VIRT_3D_MIX_MONO_SOURCE, NODE_VIRT_MONOOUT_VOLUME1, 1);
  1719. // NODE_VIRT_MONOOUT_VOLUME1 -> NODE_MONOOUT_SELECT
  1720. INIT_NN_CONN (CurrentConnection, NODE_VIRT_MONOOUT_VOLUME1, 0, NODE_MONOOUT_SELECT, 1);
  1721. if (AdapterCommon->GetPinConfig (PINC_MIC_PRESENT))
  1722. {
  1723. // NODE_MIC_BOOST -> NODE_VIRT_MONOOUT_VOLUME2
  1724. INIT_NN_CONN (CurrentConnection, NODE_MIC_BOOST, 0, NODE_VIRT_MONOOUT_VOLUME2, 1);
  1725. // NODE_VIRT_MONOOUT_VOLUME2 -> NODE_MONOOUT_SELECT
  1726. INIT_NN_CONN (CurrentConnection, NODE_VIRT_MONOOUT_VOLUME2, 0, NODE_MONOOUT_SELECT, 2);
  1727. }
  1728. // NODE_MONOOUT_SELECT -> PIN_MONOOUT_DEST
  1729. INIT_NF_CONN( CurrentConnection, NODE_MONOOUT_SELECT, 0, PIN_MONOOUT_DEST);
  1730. }
  1731. // add the connections to the filter descriptor
  1732. FilterDescriptor->ConnectionCount = ConnectionCount;
  1733. FilterDescriptor->Connections = ConnectionDescriptors;
  1734. } else
  1735. {
  1736. ntStatus = STATUS_INSUFFICIENT_RESOURCES;
  1737. }
  1738. return ntStatus;
  1739. #undef INIT_NN_CONN
  1740. #undef INIT_FN_CONN
  1741. #undef INIT_NF_CONN
  1742. }
  1743. /*****************************************************************************
  1744. * CMiniportTopologyICH::UpdateRecordMute
  1745. *****************************************************************************
  1746. * Updates the record mute control. This is used to have DRM functionality.
  1747. * In the case that we play a DRM file that is copy protected, we have to
  1748. * mute the record if stereo or mono mix is selected. We also have to update
  1749. * the record mute every time the DRM content changes or the playback stream
  1750. * goes away. The property handler also calls this function to update the
  1751. * record mute in case stereo or mono mix is selected.
  1752. */
  1753. void CMiniportTopologyICH::UpdateRecordMute (void)
  1754. {
  1755. PAGED_CODE ();
  1756. WORD wRegister;
  1757. TopoNodes Node;
  1758. DOUT (DBG_PRINT, ("[CMiniportTopologyICH::UpdateRecordMute]"));
  1759. // Get the record muxer setting.
  1760. if (!NT_SUCCESS (AdapterCommon->ReadCodecRegister (
  1761. AdapterCommon->GetNodeReg (NODE_WAVEIN_SELECT), &wRegister)))
  1762. return;
  1763. // Mask out every unused bit.
  1764. wRegister &= (AdapterCommon->GetNodeMask (NODE_WAVEIN_SELECT) & AC97REG_MASK_RIGHT);
  1765. // Calculate how we would program the mute.
  1766. switch (wRegister)
  1767. {
  1768. // This is stereo mix.
  1769. case 5:
  1770. Node = NODE_VIRT_MASTER_INPUT_VOLUME6;
  1771. break;
  1772. // This is mono mix.
  1773. case 6:
  1774. Node = NODE_VIRT_MASTER_INPUT_VOLUME7;
  1775. break;
  1776. // Something else selected than stereo mix or mono mix.
  1777. default:
  1778. return;
  1779. }
  1780. // Program the mute.
  1781. AdapterCommon->WriteCodecRegister (AC97REG_RECORD_GAIN,
  1782. (m_bCopyProtectFlag ? AC97REG_MASK_MUTE : 0), AC97REG_MASK_MUTE);
  1783. }
  1784. /*****************************************************************************
  1785. * CMiniportTopologyICH::GetPhysicalConnectionPins
  1786. *****************************************************************************
  1787. * Returns the system pin IDs of the bridge pins that are connected with the
  1788. * wave miniport.
  1789. * If one pin is not used, the value is -1, that could only happen for MinInDest.
  1790. */
  1791. STDMETHODIMP CMiniportTopologyICH::GetPhysicalConnectionPins
  1792. (
  1793. OUT PULONG WaveOutSource,
  1794. OUT PULONG WaveInDest,
  1795. OUT PULONG MicInDest
  1796. )
  1797. {
  1798. PAGED_CODE ();
  1799. ASSERT (WaveOutSource);
  1800. ASSERT (WaveInDest);
  1801. ASSERT (MicInDest);
  1802. DOUT (DBG_PRINT, ("[CMiniportTopologyICH::GetPhysicalConnectionPins]"));
  1803. // set the pin IDs.
  1804. *WaveOutSource = TransPinDefToPinNr (PIN_WAVEOUT_SOURCE);
  1805. *WaveInDest = TransPinDefToPinNr (PIN_WAVEIN_DEST);
  1806. // this is optional
  1807. if (AdapterCommon->GetPinConfig (PINC_MICIN_PRESENT))
  1808. *MicInDest = TransPinDefToPinNr (PIN_MICIN_DEST);
  1809. else
  1810. *MicInDest = -1;
  1811. return STATUS_SUCCESS;
  1812. }