1 /********************************************************************************
2 ** Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
3 **
4 ** Portions Copyright (c) 1998-1999 Intel Corporation
5 **
6 ********************************************************************************/
7
8 /* The file common.cpp was reviewed by LCA in June 2011 and is acceptable for use by Microsoft. */
9
10 // Every debug output has "Modulname text"
11 #define STR_MODULENAME "AC97 Common: "
12
13 #include "common.h"
14
15
16 /*****************************************************************************
17 * Static Members
18 *****************************************************************************
19 */
20
21 //
22 // This is the register cache including registry names and default values. The
23 // first WORD contains the register value and the second WORD contains a flag.
24 // Currently, we only set SHREG_INVALID if we have to read the register at
25 // startup (that's true when there is no constant default value for the
26 // register). Note that we cache the registers only to prevent read access to
27 // the AC97 CoDec during runtime, because this is slow (40us).
28 // We only set SHREG_INIT if we want to set the register to default at driver
29 // startup. If needed, the third field contains the registry name and the
30 // forth field contains a default value that is used when there is no registry
31 // entry.
32 // The flag SHREG_NOCACHE is used when we don't want to cache the register
33 // at all. This is neccessary for status registers and sample rate registers.
34 //
35 tAC97Registers CAC97AdapterCommon::m_stAC97Registers[] =
36 {
37 {0x0000, SHREG_INVALID, NULL, 0}, // AC97REG_RESET
38 {0x8000, SHREG_INIT, L"MasterVolume", 0x0000}, // AC97REG_MASTER_VOLUME
39 {0x8000, SHREG_INIT, L"HeadphoneVolume", 0x0000}, // AC97REG_HPHONE_VOLUME
40 {0x8000, SHREG_INIT, L"MonooutVolume", 0x0000}, // AC97REG_MMONO_VOLUME
41 {0x0F0F, SHREG_INIT, L"ToneControls", 0x0F0F}, // AC97REG_MASTER_TONE
42 {0x0000, SHREG_INVALID |
43 SHREG_INIT, L"BeepVolume", 0x0000}, // AC97REG_BEEP_VOLUME
44 {0x8008, SHREG_INIT, L"PhoneVolume", 0x8008}, // AC97REG_PHONE_VOLUME
45 {0x8008, SHREG_INIT, L"MicVolume", 0x8008}, // AC97REG_MIC_VOLUME
46 {0x8808, SHREG_INIT, L"LineInVolume", 0x0808}, // AC97REG_LINE_IN_VOLUME
47 {0x8808, SHREG_INIT, L"CDVolume", 0x0808}, // AC97REG_CD_VOLUME
48 {0x8808, SHREG_INIT, L"VideoVolume", 0x0808}, // AC97REG_VIDEO_VOLUME
49 {0x8808, SHREG_INIT, L"AUXVolume", 0x0808}, // AC97REG_AUX_VOLUME
50 {0x8808, SHREG_INIT, L"WaveOutVolume", 0x0808}, // AC97REG_PCM_OUT_VOLUME
51 {0x0000, SHREG_INIT, L"RecordSelect", 0x0404}, // AC97REG_RECORD_SELECT
52 {0x8000, SHREG_INIT, L"RecordGain", 0x0000}, // AC97REG_RECORD_GAIN
53 {0x8000, SHREG_INIT, L"RecordGainMic", 0x0000}, // AC97REG_RECORD_GAIN_MIC
54 {0x0000, SHREG_INIT, L"GeneralPurpose", 0x0000}, // AC97REG_GENERAL
55 {0x0000, SHREG_INIT, L"3DControl", 0x0000}, // AC97REG_3D_CONTROL
56 {0x0000, SHREG_NOCACHE, NULL, 0}, // AC97REG_RESERVED
57 {0x0000, SHREG_NOCACHE |
58 SHREG_INIT, L"PowerDown", 0}, // AC97REG_POWERDOWN
59 // AC97-2.0 registers
60 {0x0000, SHREG_INVALID, NULL, 0}, // AC97REG_EXT_AUDIO_ID
61 {0x0000, SHREG_NOCACHE |
62 SHREG_INIT, L"ExtAudioCtrl", 0x4001}, // AC97REG_EXT_AUDIO_CTRL
63 {0xBB80, SHREG_NOCACHE, NULL, 0}, // AC97REG_FRONT_SAMPLERATE
64 {0xBB80, SHREG_NOCACHE, NULL, 0}, // AC97REG_SURROUND_SAMPLERATE
65 {0xBB80, SHREG_NOCACHE, NULL, 0}, // AC97REG_LFE_SAMPLERATE
66 {0xBB80, SHREG_NOCACHE, NULL, 0}, // AC97REG_RECORD_SAMPLERATE
67 {0xBB80, SHREG_NOCACHE, NULL, 0}, // AC97REG_MIC_SAMPLERATE
68 {0x8080, SHREG_INIT, L"CenterLFEVolume", 0x0000}, // AC97REG_CENTER_LFE_VOLUME
69 {0x8080, SHREG_INIT, L"SurroundVolume", 0x0000}, // AC97REG_SURROUND_VOLUME
70 {0x0000, SHREG_NOCACHE, NULL, 0} // AC97REG_RESERVED2
71
72 // We leave the other values blank. There would be a huge gap with 31
73 // elements that are currently unused, and then there would be 2 other
74 // (used) values, the vendor IDs. We just force a read from the vendor
75 // IDs in the end of ProbeHWConfig to fill the cache.
76 };
77
78
79 //
80 // This is the hardware configuration information. The first struct is for
81 // nodes, which we default to FALSE. The second struct is for Pins, which
82 // contains the configuration (FALSE) and the registry string which is the
83 // reason for making a static struct so we can just fill in the name.
84 //
85 tHardwareConfig CAC97AdapterCommon::m_stHardwareConfig =
86 {
87 // Nodes
88 {{FALSE}, {FALSE}, {FALSE}, {FALSE}, {FALSE}, {FALSE}, {FALSE}, {FALSE},
89 {FALSE}, {FALSE}, {FALSE}, {FALSE}, {FALSE}, {FALSE}, {FALSE}, {FALSE},
90 {FALSE}},
91 // Pins
92 {{FALSE, L"DisablePCBeep"}, // PINC_PCBEEP_PRESENT
93 {FALSE, L"DisablePhone"}, // PINC_PHONE_PRESENT
94 {FALSE, L"DisableMic2"}, // PINC_MIC2_PRESENT
95 {FALSE, L"DisableVideo"}, // PINC_VIDEO_PRESENT
96 {FALSE, L"DisableAUX"}, // PINC_AUX_PRESENT
97 {FALSE, L"DisableHeadphone"}, // PINC_HPOUT_PRESENT
98 {FALSE, L"DisableMonoOut"}, // PINC_MONOOUT_PRESENT
99 {FALSE, L"DisableMicIn"}, // PINC_MICIN_PRESENT
100 {FALSE, L"DisableMic"}, // PINC_MIC_PRESENT
101 {FALSE, L"DisableLineIn"}, // PINC_LINEIN_PRESENT
102 {FALSE, L"DisableCD"}, // PINC_CD_PRESENT
103 {FALSE, L"DisableSurround"}, // PINC_SURROUND_PRESENT
104 {FALSE, L"DisableCenterLFE"}} // PINC_CENTER_LFE_PRESENT
105 };
106
107
108 #ifdef _MSC_VER
109 #pragma code_seg("PAGE")
110 #endif
111 /*****************************************************************************
112 * NewAdapterCommon
113 *****************************************************************************
114 * Create a new adapter common object.
115 */
116 NTSTATUS NewAdapterCommon
117 (
118 OUT PUNKNOWN *Unknown,
119 IN REFCLSID,
120 IN PUNKNOWN UnknownOuter OPTIONAL,
121 _When_((PoolType & NonPagedPoolMustSucceed) != 0,
122 __drv_reportError("Must succeed pool allocations are forbidden. "
123 "Allocation failures cause a system crash"))
124 IN POOL_TYPE PoolType
125 )
126 {
127 PAGED_CODE ();
128
129 ASSERT (Unknown);
130
131 DOUT (DBG_PRINT, ("[NewAdapterCommon]"));
132
133 STD_CREATE_BODY_WITH_TAG_(CAC97AdapterCommon,Unknown,UnknownOuter,PoolType,
134 PoolTag, PADAPTERCOMMON);
135 }
136
137
138 /*****************************************************************************
139 * CAC97AdapterCommon::Init
140 *****************************************************************************
141 * Initialize the adapter common object -> initialize and probe HW.
142 * Pass only checked resources.
143 */
STDMETHODIMP_(NTSTATUS)144 STDMETHODIMP_(NTSTATUS) CAC97AdapterCommon::Init
145 (
146 IN PRESOURCELIST ResourceList,
147 IN PDEVICE_OBJECT DeviceObject
148 )
149 {
150 PAGED_CODE ();
151
152 ASSERT (ResourceList);
153 ASSERT (DeviceObject);
154
155 NTSTATUS ntStatus = STATUS_SUCCESS;
156
157 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::Init]"));
158
159 //
160 // Set the topology pointer to NULL.
161 //
162 m_Topology = NULL;
163
164 //
165 // Save the device object
166 //
167 m_pDeviceObject = DeviceObject;
168
169 //
170 // Get the base address for the AC97 codec and bus master.
171 //
172 ASSERT (ResourceList->FindTranslatedPort (0));
173 m_pCodecBase = (PUSHORT)ResourceList->FindTranslatedPort (0)->
174 u.Port.Start.QuadPart;
175
176 ASSERT (ResourceList->FindTranslatedPort (1));
177 m_pBusMasterBase = (PUCHAR)ResourceList->FindTranslatedPort (1)->
178 u.Port.Start.QuadPart;
179
180 DOUT (DBG_SYSINFO, ("Configuration:\n"
181 " Bus Master = 0x%p\n"
182 " Codec = 0x%p",
183 m_pBusMasterBase, m_pCodecBase));
184
185 //
186 // Set m_bDirectRead to TRUE so that all AC97 register read and
187 // writes are going directly to the HW
188 //
189 m_bDirectRead = TRUE;
190
191 //
192 // Initialize the hardware.
193 //
194 ntStatus = InitAC97 ();
195 if (!NT_SUCCESS (ntStatus))
196 return ntStatus;
197
198 //
199 // Probe hardware configuration
200 //
201 ntStatus = ProbeHWConfig ();
202 if (!NT_SUCCESS (ntStatus))
203 {
204 DOUT (DBG_ERROR, ("Probing of hardware configuration failed!"));
205 return ntStatus;
206 }
207
208 //
209 // Now, every AC97 read access goes to the cache.
210 //
211 m_bDirectRead = FALSE;
212
213 //
214 // Restore the AC97 registers now.
215 //
216 #if (DBG)
217 DumpConfig ();
218 #endif
219 ntStatus = SetAC97Default ();
220
221 //
222 // Initialize the device state.
223 //
224 m_PowerState = PowerDeviceD0;
225
226 return ntStatus;
227 }
228
229
230 /*****************************************************************************
231 * CAC97AdapterCommon::~CAC97AdapterCommon
232 *****************************************************************************
233 * Destructor.
234 */
~CAC97AdapterCommon()235 CAC97AdapterCommon::~CAC97AdapterCommon ()
236 {
237 PAGED_CODE ();
238
239 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::~CAC97AdapterCommon]"));
240 }
241
242
243 #if (DBG)
244 /*****************************************************************************
245 * CAC97AdapterCommon::DumpConfig
246 *****************************************************************************
247 * Dumps the HW configuration for the AC97 codec.
248 */
DumpConfig(void)249 void CAC97AdapterCommon::DumpConfig (void)
250 {
251 PAGED_CODE ();
252
253 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::DumpConfig]"));
254
255 //
256 // Print debug output for MICIN.
257 //
258 if (GetPinConfig (PINC_MICIN_PRESENT))
259 {
260 DOUT (DBG_PROBE, ("MICIN found"));
261 }
262 else
263 {
264 DOUT (DBG_PROBE, ("No MICIN found"));
265 }
266
267 //
268 // Print debug output for tone controls.
269 //
270 if (GetNodeConfig (NODEC_TONE_PRESENT))
271 {
272 DOUT (DBG_PROBE, ("Tone controls found"));
273 }
274 else
275 {
276 DOUT (DBG_PROBE, ("No tone controls found"));
277 }
278
279 //
280 // Print debug output for mono out.
281 //
282 if (!GetPinConfig (PINC_MONOOUT_PRESENT))
283 {
284 DOUT (DBG_PROBE, ("No mono out found"));
285 }
286
287 //
288 // Print debug output for headphones.
289 //
290 if (!GetPinConfig (PINC_HPOUT_PRESENT))
291 {
292 DOUT (DBG_PROBE, ("No headphone out found"));
293 }
294
295 //
296 // Print debug output for loudness.
297 //
298 if (GetNodeConfig (NODEC_LOUDNESS_PRESENT))
299 {
300 DOUT (DBG_PROBE, ("Loudness found"));
301 }
302 else
303 {
304 DOUT (DBG_PROBE, ("No Loudness found"));
305 }
306
307 //
308 // Print debug output for 3D.
309 //
310 if (GetNodeConfig (NODEC_3D_PRESENT))
311 {
312 DOUT (DBG_PROBE, ("3D controls found"));
313 }
314 else
315 {
316 DOUT (DBG_PROBE, ("No 3D controls found"));
317 }
318
319 //
320 // Print debug output for pc beep.
321 //
322 if (GetPinConfig (PINC_PCBEEP_PRESENT))
323 {
324 DOUT (DBG_PROBE, ("PC beep found"));
325 }
326 else
327 {
328 DOUT (DBG_PROBE, ("No PC beep found"));
329 }
330
331 //
332 // Print debug output for phone line (or mono line input).
333 //
334 if (GetPinConfig (PINC_PHONE_PRESENT))
335 {
336 DOUT (DBG_PROBE, ("Phone found"));
337 }
338 else
339 {
340 DOUT (DBG_PROBE, ("No Phone found"));
341 }
342
343 //
344 // Print debug output for video.
345 //
346 if (GetPinConfig (PINC_VIDEO_PRESENT))
347 {
348 DOUT (DBG_PROBE, ("Video in found"));
349 }
350 else
351 {
352 DOUT (DBG_PROBE, ("No Video in found"));
353 }
354
355 //
356 // Print debug output for AUX.
357 //
358 if (GetPinConfig (PINC_AUX_PRESENT))
359 {
360 DOUT (DBG_PROBE, ("AUX in found"));
361 }
362 else
363 {
364 DOUT (DBG_PROBE, ("No AUX in found"));
365 }
366
367 //
368 // Print debug output for second miorophone.
369 //
370 if (GetPinConfig (PINC_MIC2_PRESENT))
371 {
372 DOUT (DBG_PROBE, ("MIC2 found"));
373 }
374 else
375 {
376 DOUT (DBG_PROBE, ("No MIC2 found"));
377 }
378
379 //
380 // Print debug output for 3D stuff.
381 //
382 if (GetNodeConfig (NODEC_3D_PRESENT))
383 {
384 if (GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE))
385 {
386 DOUT (DBG_PROBE, ("Adjustable 3D center control found"));
387 }
388 if (GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE))
389 {
390 DOUT (DBG_PROBE, ("Nonadjustable 3D depth control found"));
391 }
392 }
393
394 //
395 // Print debug output for quality of master volume.
396 //
397 if (GetNodeConfig (NODEC_6BIT_MASTER_VOLUME))
398 {
399 DOUT (DBG_PROBE, ("6bit master out found"));
400 }
401 else
402 {
403 DOUT (DBG_PROBE, ("5bit master out found"));
404 }
405
406 //
407 // Print debug output for quality of headphones volume.
408 //
409 if (GetPinConfig (PINC_HPOUT_PRESENT))
410 {
411 if (GetNodeConfig (NODEC_6BIT_HPOUT_VOLUME))
412 {
413 DOUT (DBG_PROBE, ("6bit headphone out found"));
414 }
415 else
416 {
417 DOUT (DBG_PROBE, ("5bit headphone out found"));
418 }
419 }
420
421 //
422 // Print debug output for quality of mono out volume.
423 //
424 if (GetPinConfig (PINC_MONOOUT_PRESENT))
425 {
426 if (GetNodeConfig (NODEC_6BIT_MONOOUT_VOLUME))
427 {
428 DOUT (DBG_PROBE, ("6bit mono out found"));
429 }
430 else
431 {
432 DOUT (DBG_PROBE, ("5bit mono out found"));
433 }
434 }
435
436 //
437 // Print sample rate information.
438 //
439 if (GetNodeConfig (NODEC_PCM_VARIABLERATE_SUPPORTED))
440 {
441 DOUT (DBG_PROBE, ("PCM variable sample rate supported"));
442 }
443 else
444 {
445 DOUT (DBG_PROBE, ("only 48KHz PCM supported"));
446 }
447
448 //
449 // Print double rate information.
450 //
451 if (GetNodeConfig (NODEC_PCM_DOUBLERATE_SUPPORTED))
452 {
453 DOUT (DBG_PROBE, ("PCM double sample rate supported"));
454 }
455
456 //
457 // Print mic rate information.
458 //
459 if (GetNodeConfig (NODEC_MIC_VARIABLERATE_SUPPORTED))
460 {
461 DOUT (DBG_PROBE, ("MIC variable sample rate supported"));
462 }
463 else
464 {
465 DOUT (DBG_PROBE, ("only 48KHz MIC supported"));
466 }
467
468 // print DAC information
469 if (GetNodeConfig (NODEC_CENTER_DAC_PRESENT))
470 {
471 DOUT (DBG_PROBE, ("center DAC found"));
472 }
473 if (GetNodeConfig (NODEC_SURROUND_DAC_PRESENT))
474 {
475 DOUT (DBG_PROBE, ("surround DAC found"));
476 }
477 if (GetNodeConfig (NODEC_LFE_DAC_PRESENT))
478 {
479 DOUT (DBG_PROBE, ("LFE DAC found"));
480 }
481 }
482 #endif
483
484 /*****************************************************************************
485 * CAC97AdapterCommon::NonDelegatingQueryInterface
486 *****************************************************************************
487 * Obtains an interface. This function works just like a COM QueryInterface
488 * call and is used if the object is not being aggregated.
489 * We basically just check any GUID we know and return this object in case we
490 * know it.
491 */
STDMETHODIMP_(NTSTATUS)492 STDMETHODIMP_(NTSTATUS) CAC97AdapterCommon::NonDelegatingQueryInterface
493 (
494 _In_ REFIID Interface,
495 _COM_Outptr_ PVOID * Object
496 )
497 {
498 PAGED_CODE ();
499
500 ASSERT (Object);
501
502 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::NonDelegatingQueryInterface]"));
503
504 // Is it IID_IUnknown?
505 if (IsEqualGUIDAligned (Interface, IID_IUnknown))
506 {
507 *Object = (PVOID)(PUNKNOWN)(PADAPTERCOMMON)this;
508 }
509 else
510 // or IID_IAC97AdapterCommon ...
511 if (IsEqualGUIDAligned (Interface, IID_IAC97AdapterCommon))
512 {
513 *Object = (PVOID)(PADAPTERCOMMON)this;
514 }
515 else
516 // or IID_IAdapterPowerManagement ...
517 if (IsEqualGUIDAligned (Interface, IID_IAdapterPowerManagement))
518 {
519 *Object = (PVOID)(PADAPTERPOWERMANAGEMENT)this;
520 }
521 else
522 {
523 // nothing found, must be an unknown interface.
524 *Object = NULL;
525 return STATUS_INVALID_PARAMETER;
526 }
527
528 //
529 // We reference the interface for the caller.
530 //
531 ((PUNKNOWN)*Object)->AddRef ();
532 return STATUS_SUCCESS;
533 }
534
535 /*****************************************************************************
536 * CAC97AdapterCommon::InitAC97
537 *****************************************************************************
538 * Initialize the AC97 (without hosing the modem if it got installed first).
539 */
InitAC97(void)540 NTSTATUS CAC97AdapterCommon::InitAC97 (void)
541 {
542 PAGED_CODE ();
543
544 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::InitAC97]"));
545
546 //
547 // First check if there is an AC link to the primary CoDec.
548 //
549 NTSTATUS ntStatus = PrimaryCodecReady ();
550 if (NT_SUCCESS (ntStatus))
551 {
552 //
553 // Second, reset this primary CoDec; If this is a AMC97 CoDec, only
554 // the audio registers are reset. If this is a MC97 CoDec, the CoDec
555 // should ignore the reset (according to the spec).
556 //
557 WriteCodecRegister (AC97REG_RESET, 0x00, 0xFFFF);
558
559 ntStatus = PowerUpCodec ();
560 }
561 else
562 {
563 DOUT (DBG_ERROR, ("Initialization of AC97 CoDec failed."));
564 }
565
566 return ntStatus;
567 }
568
569 /*****************************************************************************
570 * CAC97AdapterCommon::Check6thBitSupport
571 *****************************************************************************
572 * Probes for 6th bit volume control support.
573 * The passed parameters are the AC97 register that has the volume control and
574 * the node config that should be set in this case.
575 */
Check6thBitSupport(IN AC97Register AC97Reg,IN TopoNodeConfig Config)576 NTSTATUS CAC97AdapterCommon::Check6thBitSupport
577 (
578 IN AC97Register AC97Reg,
579 IN TopoNodeConfig Config
580 )
581 {
582 PAGED_CODE();
583
584 NTSTATUS ntStatus;
585 WORD wCodecReg;
586 WORD wOriginal;
587
588 // Read the current value.
589 ntStatus = ReadCodecRegister (AC97Reg, &wOriginal);
590 if (!NT_SUCCESS (ntStatus))
591 return ntStatus;
592
593 // Write the 6th bit; for mono controls we write 0x20, for stereo
594 // controls 0x2020.
595 ntStatus = WriteCodecRegister (AC97Reg,
596 (AC97Reg == AC97REG_MMONO_VOLUME) ? 0x0020 : 0x2020, 0xFFFF);
597 if (!NT_SUCCESS (ntStatus))
598 return ntStatus;
599
600 // And read back.
601 ntStatus = ReadCodecRegister (AC97Reg, &wCodecReg);
602 if (!NT_SUCCESS (ntStatus))
603 return ntStatus;
604
605 // Check return. For mono 0x20 and for stereo 0x2020.
606 if (((wCodecReg & 0x0020) && (AC97Reg == AC97REG_MMONO_VOLUME)) ||
607 (wCodecReg & 0x2020))
608 {
609 SetNodeConfig (Config, TRUE);
610 }
611 else
612 {
613 SetNodeConfig (Config, FALSE);
614 }
615
616 // Restore original value.
617 WriteCodecRegister (AC97Reg, wOriginal, 0xFFFF);
618
619 return ntStatus;
620 }
621
622 /*****************************************************************************
623 * CAC97AdapterCommon::ProbeHWConfig
624 *****************************************************************************
625 * Probes the hardware configuration.
626 * If this function returns with an error, then the configuration is not
627 * complete! Probing the registers is done by reading them (and comparing with
628 * the HW default value) or when the default is unknown, writing to them and
629 * reading back + restoring.
630 * Additionally, we read the registry so that a HW vendor can overwrite (means
631 * disable) found registers in case the adapter (e.g. video) is not visible to
632 * the user (he can't plug in a video audio there).
633 *
634 * This is a very long function with all of the error checking!
635 */
ProbeHWConfig(void)636 NTSTATUS CAC97AdapterCommon::ProbeHWConfig (void)
637 {
638 PAGED_CODE ();
639
640 NTSTATUS ntStatus = STATUS_SUCCESS;
641 DWORD dwGlobalStatus;
642 WORD wCodecID;
643 WORD wCodecReg;
644
645 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::ProbeHWConfig]"));
646
647 //
648 // Wait for the whatever 97 to complete reset and establish a link.
649 //
650 ntStatus = PrimaryCodecReady ();
651 if (!NT_SUCCESS (ntStatus))
652 return ntStatus;
653
654 //
655 // Master volume is one of the supported registers on an AC97
656 //
657 ntStatus = ReadCodecRegister (AC97REG_MASTER_VOLUME, &wCodecReg);
658 if (!NT_SUCCESS (ntStatus))
659 return ntStatus;
660
661 // Default is x8000.
662 if (wCodecReg != 0x8000)
663 return STATUS_NO_SUCH_DEVICE;
664
665 //
666 // This gives us information about the AC97 CoDec
667 //
668 ntStatus = ReadCodecRegister (AC97REG_RESET, &wCodecID);
669 if (!NT_SUCCESS (ntStatus))
670 return ntStatus;
671
672 //
673 // Fill out the configuration stuff.
674 //
675
676 SetPinConfig (PINC_MICIN_PRESENT, wCodecID & 0x0001);
677
678 // Check if OEM wants to disable MIC record line.
679 if (DisableAC97Pin (PINC_MICIN_PRESENT))
680 SetPinConfig (PINC_MICIN_PRESENT, FALSE);
681
682 // If we still have MIC record line, enable the DAC in ext. audio register.
683 if (GetPinConfig (PINC_MICIN_PRESENT))
684 // Enable ADC MIC.
685 WriteCodecRegister (AC97REG_EXT_AUDIO_CTRL, 0, 0x4000);
686 else
687 // Disable ADC MIC.
688 WriteCodecRegister (AC97REG_EXT_AUDIO_CTRL, 0x4000, 0x4000);
689
690 //
691 // Continue setting configuration information.
692 //
693
694 SetNodeConfig (NODEC_TONE_PRESENT, wCodecID & 0x0004);
695 SetNodeConfig (NODEC_SIMUL_STEREO_PRESENT, wCodecID & 0x0008);
696 SetPinConfig (PINC_HPOUT_PRESENT, wCodecID & 0x0010);
697
698 // Check if OEM wants to disable headphone output.
699 if (DisableAC97Pin (PINC_HPOUT_PRESENT))
700 SetPinConfig (PINC_HPOUT_PRESENT, FALSE);
701
702 SetNodeConfig (NODEC_LOUDNESS_PRESENT, wCodecID & 0x0020);
703 SetNodeConfig (NODEC_3D_PRESENT, wCodecID & 0x7C00);
704
705 //
706 // Test for the input pins that are always there but could be disabled
707 // by the HW vender
708 //
709
710 // Check if OEM wants to disable mic input.
711 SetPinConfig (PINC_MIC_PRESENT, !DisableAC97Pin (PINC_MIC_PRESENT));
712
713 // Check if OEM wants to disable line input.
714 SetPinConfig (PINC_LINEIN_PRESENT, !DisableAC97Pin (PINC_LINEIN_PRESENT));
715
716 // Check if OEM wants to disable CD input.
717 SetPinConfig (PINC_CD_PRESENT, !DisableAC97Pin (PINC_CD_PRESENT));
718
719
720 //
721 // For the rest, we have to probe the registers.
722 //
723
724 //
725 // Test for Mono out.
726 //
727 ntStatus = ReadCodecRegister (AC97REG_MMONO_VOLUME, &wCodecReg);
728 if (!NT_SUCCESS (ntStatus))
729 return ntStatus;
730
731 // Default is x8000.
732 SetPinConfig (PINC_MONOOUT_PRESENT, (wCodecReg == 0x8000));
733
734 // Check if OEM wants to disable mono output.
735 if (DisableAC97Pin (PINC_MONOOUT_PRESENT))
736 SetPinConfig (PINC_MONOOUT_PRESENT, FALSE);
737
738 //
739 // Test for PC beeper support.
740 //
741 ntStatus = ReadCodecRegister (AC97REG_BEEP_VOLUME, &wCodecReg);
742 if (!NT_SUCCESS (ntStatus))
743 return ntStatus;
744
745 // default is x0 or x8000. If it's 0x8000 then we know for sure that the
746 // CoDec has a PcBeep, otherwise we have to check the register
747 if (wCodecReg == 0x8000)
748 SetPinConfig (PINC_PCBEEP_PRESENT, TRUE);
749 else if (!wCodecReg)
750 {
751 // mute the pc beeper.
752 ntStatus = WriteCodecRegister (AC97REG_BEEP_VOLUME, 0x8000, 0xFFFF);
753 if (!NT_SUCCESS (ntStatus))
754 return ntStatus;
755
756 // read back
757 ntStatus = ReadCodecRegister (AC97REG_BEEP_VOLUME, &wCodecReg);
758 if (!NT_SUCCESS (ntStatus))
759 return ntStatus;
760
761 if (wCodecReg == 0x8000)
762 {
763 // yep, we have support.
764 SetPinConfig (PINC_PCBEEP_PRESENT, TRUE);
765 // reset to default value.
766 WriteCodecRegister (AC97REG_BEEP_VOLUME, 0x0, 0xFFFF);
767 }
768 else
769 // nope, not present
770 SetPinConfig (PINC_PCBEEP_PRESENT, FALSE);
771 }
772 else
773 // any other value then 0x0 and 0x8000.
774 SetPinConfig (PINC_PCBEEP_PRESENT, FALSE);
775
776 // Check if OEM wants to disable beeper support.
777 if (DisableAC97Pin (PINC_PCBEEP_PRESENT))
778 SetPinConfig (PINC_PCBEEP_PRESENT, FALSE);
779
780 //
781 // Test for phone support.
782 //
783 ntStatus = ReadCodecRegister (AC97REG_PHONE_VOLUME, &wCodecReg);
784 if (!NT_SUCCESS (ntStatus))
785 return ntStatus;
786
787 // Default is x8008.
788 SetPinConfig (PINC_PHONE_PRESENT, (wCodecReg == 0x8008));
789
790 // Check if OEM wants to disable phone input.
791 if (DisableAC97Pin (PINC_PHONE_PRESENT))
792 SetPinConfig (PINC_PHONE_PRESENT, FALSE);
793
794 //
795 // Test for video support.
796 //
797 ntStatus = ReadCodecRegister (AC97REG_VIDEO_VOLUME, &wCodecReg);
798 if (!NT_SUCCESS (ntStatus))
799 return ntStatus;
800
801 // Default is x8808.
802 SetPinConfig (PINC_VIDEO_PRESENT, (wCodecReg == 0x8808));
803
804 // Check if OEM wants to disable video input.
805 if (DisableAC97Pin (PINC_VIDEO_PRESENT))
806 SetPinConfig (PINC_VIDEO_PRESENT, FALSE);
807
808 //
809 // Test for Aux support.
810 //
811 ntStatus = ReadCodecRegister (AC97REG_AUX_VOLUME, &wCodecReg);
812 if (!NT_SUCCESS (ntStatus))
813 return ntStatus;
814
815 // Default is 0x8808.
816 SetPinConfig (PINC_AUX_PRESENT, (wCodecReg == 0x8808));
817
818 // Check if OEM wants to disable aux input.
819 if (DisableAC97Pin (PINC_AUX_PRESENT))
820 SetPinConfig (PINC_AUX_PRESENT, FALSE);
821
822 //
823 // Test for Mic2 source.
824 //
825 ntStatus = ReadCodecRegister (AC97REG_GENERAL, &wCodecReg);
826 if (!NT_SUCCESS (ntStatus))
827 return ntStatus;
828
829 // Test for Mic2 select bit.
830 if (wCodecReg & 0x0100)
831 SetPinConfig (PINC_MIC2_PRESENT, TRUE);
832 else
833 {
834 // Select Mic2 as source.
835 ntStatus = WriteCodecRegister (AC97REG_GENERAL, 0x0100, 0x0100);
836 if (!NT_SUCCESS (ntStatus))
837 return ntStatus;
838
839 // Read back.
840 ntStatus = ReadCodecRegister (AC97REG_GENERAL, &wCodecReg);
841 if (!NT_SUCCESS (ntStatus))
842 return ntStatus;
843
844 if (wCodecReg & 0x0100)
845 {
846 // Yep, we have support so set it to the default value.
847 SetPinConfig (PINC_MIC2_PRESENT, TRUE);
848 // reset to default value.
849 WriteCodecRegister (AC97REG_GENERAL, 0, 0x0100);
850 }
851 else
852 SetPinConfig (PINC_MIC2_PRESENT, FALSE);
853 }
854
855 // Check if OEM wants to disable mic2 input.
856 if (DisableAC97Pin (PINC_MIC2_PRESENT))
857 SetPinConfig (PINC_MIC2_PRESENT, FALSE);
858
859 //
860 // Test the 3D controls.
861 //
862 if (GetNodeConfig (NODEC_3D_PRESENT))
863 {
864 //
865 // First test for fixed 3D controls. Write default value ...
866 //
867 ntStatus = WriteCodecRegister (AC97REG_3D_CONTROL, 0, 0xFFFF);
868 if (!NT_SUCCESS (ntStatus))
869 return ntStatus;
870
871 // Read 3D register. Default is 0 when adjustable, otherwise it is
872 // a fixed value.
873 ntStatus = ReadCodecRegister (AC97REG_3D_CONTROL, &wCodecReg);
874 if (!NT_SUCCESS (ntStatus))
875 return ntStatus;
876
877 //
878 // Check center and depth separately.
879 //
880
881 // For center
882 SetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE, !(wCodecReg & 0x0F00));
883
884 // For depth
885 SetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE, !(wCodecReg & 0x000F));
886
887 //
888 // Test for adjustable controls.
889 //
890 WriteCodecRegister (AC97REG_3D_CONTROL, 0x0A0A, 0xFFFF);
891
892 // Read 3D register. Now it should be 0x0A0A for adjustable controls,
893 // otherwise it is a fixed control or simply not there.
894 ReadCodecRegister (AC97REG_3D_CONTROL, &wCodecReg);
895
896 // Restore the default value
897 WriteCodecRegister (AC97REG_3D_CONTROL, 0, 0xFFFF);
898
899 // Check the center control for beeing adjustable
900 if (GetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE) &&
901 (wCodecReg & 0x0F00) != 0x0A00)
902 {
903 SetNodeConfig (NODEC_3D_CENTER_ADJUSTABLE, FALSE);
904 }
905
906 // Check the depth control for beeing adjustable
907 if (GetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE) &&
908 (wCodecReg & 0x000F) != 0x000A)
909 {
910 SetNodeConfig (NODEC_3D_DEPTH_ADJUSTABLE, FALSE);
911 }
912 }
913
914 //
915 // Check for 6th bit support in volume controls. To check the 6th bit,
916 // we first have to write a value (with 6th bit set) and then read it
917 // back. After that, we should restore the register to its default value.
918 //
919
920 //
921 // Start with the master volume.
922 //
923 Check6thBitSupport (AC97REG_MASTER_VOLUME, NODEC_6BIT_MASTER_VOLUME);
924
925 //
926 // Check for a headphone volume control.
927 //
928 if (GetPinConfig (PINC_HPOUT_PRESENT))
929 {
930 Check6thBitSupport (AC97REG_HPHONE_VOLUME, NODEC_6BIT_HPOUT_VOLUME);
931 }
932
933 //
934 // Mono out there?
935 //
936 if (GetPinConfig (PINC_MONOOUT_PRESENT))
937 {
938 Check6thBitSupport (AC97REG_MMONO_VOLUME, NODEC_6BIT_MONOOUT_VOLUME);
939 }
940
941 //
942 // Get extended AC97 V2.0 information
943 //
944 ntStatus = ReadCodecRegister (AC97REG_EXT_AUDIO_ID, &wCodecReg);
945 if (!NT_SUCCESS (ntStatus))
946 return ntStatus;
947
948 //
949 // Store the information
950 //
951 SetNodeConfig (NODEC_PCM_VARIABLERATE_SUPPORTED, wCodecReg & 0x0001);
952 SetNodeConfig (NODEC_PCM_DOUBLERATE_SUPPORTED, wCodecReg & 0x0002);
953 SetNodeConfig (NODEC_MIC_VARIABLERATE_SUPPORTED, wCodecReg & 0x0008);
954 SetNodeConfig (NODEC_CENTER_DAC_PRESENT, wCodecReg & 0x0040);
955 SetNodeConfig (NODEC_SURROUND_DAC_PRESENT, wCodecReg & 0x0080);
956 SetNodeConfig (NODEC_LFE_DAC_PRESENT, wCodecReg & 0x0100);
957
958 //
959 // In case we have some features get some more information and program
960 // the codec.
961 //
962 if (wCodecReg)
963 {
964 //
965 // Enable variable sample rate in the control register and disable
966 // double rate. Also enable all DACs.
967 //
968 WriteCodecRegister (AC97REG_EXT_AUDIO_CTRL, wCodecReg & 0x0009, 0x380B);
969
970 //
971 // Check for codecs that have only one sample rate converter. These
972 // codecs will stick registers AC97REG_FRONT_SAMPLERATE and
973 // AC97REG_RECORD_SAMPLERATE together.
974 //
975 if (GetNodeConfig (NODEC_PCM_VARIABLERATE_SUPPORTED))
976 {
977 // The default of the sample rate registers should be 0xBB80.
978 WriteCodecRegister (AC97REG_FRONT_SAMPLERATE, 0xBB80, 0xFFFF);
979
980 // Write 44.1KHz into record VSR, then check playback again.
981 WriteCodecRegister (AC97REG_RECORD_SAMPLERATE, 0xAC44, 0xFFFF);
982 ntStatus = ReadCodecRegister (AC97REG_FRONT_SAMPLERATE, &wCodecReg);
983 WriteCodecRegister (AC97REG_RECORD_SAMPLERATE, 0xBB80, 0xFFFF);
984 if (!NT_SUCCESS (ntStatus))
985 return ntStatus;
986
987 //
988 // Set the flag accordingly
989 //
990 SetNodeConfig (NODEC_PCM_VSR_INDEPENDENT_RATES, (wCodecReg == 0xBB80));
991 }
992
993 //
994 // Check multichanel support on the AC97.
995 //
996 if (GetNodeConfig (NODEC_SURROUND_DAC_PRESENT))
997 {
998 dwGlobalStatus = ReadBMControlRegister32 (GLOB_STA);
999
1000 //
1001 // Codec supports >2 chanel, does AC97 too?
1002 //
1003 if ((GetNodeConfig (NODEC_CENTER_DAC_PRESENT) ||
1004 GetNodeConfig (NODEC_LFE_DAC_PRESENT)) &&
1005 (dwGlobalStatus & GLOB_STA_MC6))
1006 {
1007 SetPinConfig (PINC_CENTER_LFE_PRESENT, TRUE);
1008 }
1009 else
1010 {
1011 SetPinConfig (PINC_CENTER_LFE_PRESENT, FALSE);
1012 }
1013
1014 //
1015 // Do we support at least 4 channels?
1016 //
1017 SetPinConfig (PINC_SURROUND_PRESENT, (dwGlobalStatus & GLOB_STA_MC4));
1018 }
1019 else
1020 {
1021 //
1022 // Only 2 channel (stereo) support.
1023 //
1024 SetPinConfig (PINC_CENTER_LFE_PRESENT, FALSE);
1025 SetPinConfig (PINC_SURROUND_PRESENT, FALSE);
1026 }
1027 }
1028
1029 // Check if OEM wants to disable surround output.
1030 if (DisableAC97Pin (PINC_SURROUND_PRESENT))
1031 SetPinConfig (PINC_SURROUND_PRESENT, FALSE);
1032
1033 // Check if OEM wants to disable center and LFE output.
1034 if (DisableAC97Pin (PINC_CENTER_LFE_PRESENT))
1035 SetPinConfig (PINC_CENTER_LFE_PRESENT, FALSE);
1036
1037 //
1038 // Check the 6th bit support for the additional channels.
1039 //
1040 if (GetPinConfig (PINC_SURROUND_PRESENT))
1041 Check6thBitSupport (AC97REG_SURROUND_VOLUME, NODEC_6BIT_SURROUND_VOLUME);
1042
1043 if (GetPinConfig (PINC_CENTER_LFE_PRESENT))
1044 Check6thBitSupport (AC97REG_CENTER_LFE_VOLUME, NODEC_6BIT_CENTER_LFE_VOLUME);
1045
1046 //
1047 // We read these registers because they are dependent on the codec.
1048 //
1049 ReadCodecRegister (AC97REG_VENDOR_ID1, &wCodecReg);
1050 ReadCodecRegister (AC97REG_VENDOR_ID2, &wCodecReg);
1051
1052 return STATUS_SUCCESS;
1053 }
1054
1055
1056 /*****************************************************************************
1057 * CAC97AdapterCommon::AcquireCodecSemiphore
1058 *****************************************************************************
1059 * Acquires the AC97 semiphore. This can not be called at dispatch level
1060 * because it can timeout if a lower IRQL thread has the semaphore.
1061 */
AcquireCodecSemiphore()1062 NTSTATUS CAC97AdapterCommon::AcquireCodecSemiphore ()
1063 {
1064 PAGED_CODE ();
1065
1066 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::AcquireCodecSemiphore]"));
1067
1068 ULONG ulCount = 0;
1069 while (READ_PORT_UCHAR (m_pBusMasterBase + CAS) & CAS_CAS)
1070 {
1071 //
1072 // Do we want to give up??
1073 //
1074 if (ulCount++ > 100)
1075 {
1076 DOUT (DBG_ERROR, ("Cannot acquire semaphore."));
1077 return STATUS_IO_TIMEOUT;
1078 }
1079
1080 //
1081 // Let's wait a little, 40us and then try again.
1082 //
1083 KeStallExecutionProcessor (40L);
1084 }
1085
1086 return STATUS_SUCCESS;
1087 }
1088
1089
1090 /*****************************************************************************
1091 * CAC97AdapterCommon::ReadCodecRegister
1092 *****************************************************************************
1093 * Reads a AC97 register. Don't call at PASSIVE_LEVEL.
1094 */
STDMETHODIMP_(NTSTATUS)1095 STDMETHODIMP_(NTSTATUS) CAC97AdapterCommon::ReadCodecRegister
1096 (
1097 _In_range_(0, AC97REG_INVALID) AC97Register reg,
1098 _Out_ PWORD wData
1099 )
1100 {
1101 PAGED_CODE ();
1102
1103 ASSERT (wData);
1104 ASSERT (reg < AC97REG_INVALID); // audio can only be in the primary codec
1105 _Analysis_assume_(reg < AC97REG_INVALID);
1106
1107 NTSTATUS ntStatus;
1108 ULONG Status;
1109
1110 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::ReadCodecRegister]"));
1111
1112 //
1113 // Check if we have to access the HW directly.
1114 //
1115 if (m_bDirectRead || (m_stAC97Registers[reg].wFlags & SHREG_INVALID) ||
1116 (m_stAC97Registers[reg].wFlags & SHREG_NOCACHE))
1117 {
1118 //
1119 // Grab the codec access semiphore.
1120 //
1121 ntStatus = AcquireCodecSemiphore ();
1122 if (!NT_SUCCESS (ntStatus))
1123 {
1124 DOUT (DBG_ERROR, ("ReadCodecRegister couldn't acquire the semiphore"
1125 " for reg. %s", reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
1126 reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
1127 reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" :
1128 "REG_INVALID"));
1129 return ntStatus;
1130 }
1131
1132 //
1133 // Read the data.
1134 //
1135 *wData = READ_PORT_USHORT (m_pCodecBase + reg);
1136
1137 //
1138 // Check to see if the read was successful.
1139 //
1140 Status = READ_PORT_ULONG ((PULONG)(m_pBusMasterBase + GLOB_STA));
1141 if (Status & GLOB_STA_RCS)
1142 {
1143 //
1144 // clear the timeout bit
1145 //
1146 WRITE_PORT_ULONG ((PULONG)(m_pBusMasterBase + GLOB_STA), Status);
1147 *wData = 0;
1148 DOUT (DBG_ERROR, ("ReadCodecRegister timed out for register %s",
1149 reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
1150 reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
1151 reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" :
1152 "REG_INVALID"));
1153 return STATUS_IO_TIMEOUT;
1154 }
1155
1156 //
1157 // Clear invalid flag
1158 //
1159 m_stAC97Registers[reg].wCache = *wData;
1160 m_stAC97Registers[reg].wFlags &= ~SHREG_INVALID;
1161
1162 DOUT (DBG_REGS, ("AC97READ: %s = 0x%04x (HW)",
1163 reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
1164 reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
1165 reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" :
1166 "REG_INVALID", *wData));
1167 }
1168 else
1169 {
1170 //
1171 // Otherwise, use the value in the cache.
1172 //
1173 *wData = m_stAC97Registers[reg].wCache;
1174 DOUT (DBG_REGS, ("AC97READ: %s = 0x%04x (C)",
1175 reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
1176 reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
1177 reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" :
1178 "REG_INVALID", *wData));
1179 }
1180
1181 return STATUS_SUCCESS;
1182 }
1183
1184
1185 /*****************************************************************************
1186 * CAC97AdapterCommon::WriteCodecRegister
1187 *****************************************************************************
1188 * Writes to a AC97 register. This can only be done at passive level because
1189 * the AcquireCodecSemiphore call could fail!
1190 */
STDMETHODIMP_(NTSTATUS)1191 STDMETHODIMP_(NTSTATUS) CAC97AdapterCommon::WriteCodecRegister
1192 (
1193 _In_range_(0, AC97REG_INVALID) AC97Register reg,
1194 _In_ WORD wData,
1195 _In_ WORD wMask
1196 )
1197 {
1198 PAGED_CODE ();
1199
1200 ASSERT (reg < AC97REG_INVALID); // audio can only be in the primary codec
1201
1202 WORD TempData = 0;
1203 NTSTATUS ntStatus = STATUS_SUCCESS;
1204
1205 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::WriteCodecRegister]"));
1206
1207 //
1208 // No mask? Could happen when you try to prg. left channel of a
1209 // mono volume.
1210 //
1211 if (!wMask)
1212 return STATUS_SUCCESS;
1213
1214 //
1215 // Check to see if we are only writing specific bits. If so, we want
1216 // to leave some bits in the register alone.
1217 //
1218 if (wMask != 0xffff)
1219 {
1220 //
1221 // Read the current register contents.
1222 //
1223 ntStatus = ReadCodecRegister (reg, &TempData);
1224 if (!NT_SUCCESS (ntStatus))
1225 {
1226 DOUT (DBG_ERROR, ("WriteCodecRegiser read for mask failed"));
1227 return ntStatus;
1228 }
1229
1230 //
1231 // Do the masking.
1232 //
1233 TempData &= ~wMask;
1234 TempData |= (wMask & wData);
1235 }
1236 else
1237 {
1238 TempData = wData;
1239 }
1240
1241
1242 //
1243 // Grab the codec access semiphore.
1244 //
1245 ntStatus = AcquireCodecSemiphore ();
1246 if (!NT_SUCCESS (ntStatus))
1247 {
1248 DOUT (DBG_ERROR, ("WriteCodecRegister failed for register %s",
1249 reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
1250 reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
1251 reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" : "REG_INVALID"));
1252 return ntStatus;
1253 }
1254
1255 //
1256 // Write the data.
1257 //
1258 WRITE_PORT_USHORT (m_pCodecBase + reg, TempData);
1259
1260 //
1261 // Update cache.
1262 //
1263 _Analysis_assume_(reg < AC97REG_INVALID);
1264 m_stAC97Registers[reg].wCache = TempData;
1265
1266 DOUT (DBG_REGS, ("AC97WRITE: %s -> 0x%04x",
1267 reg <= AC97REG_RESERVED2 ? RegStrings[reg] :
1268 reg == AC97REG_VENDOR_ID1 ? "REG_VENDOR_ID1" :
1269 reg == AC97REG_VENDOR_ID2 ? "REG_VENDOR_ID2" :
1270 "REG_INVALID", TempData));
1271
1272
1273 return STATUS_SUCCESS;
1274 }
1275
1276
1277 /*****************************************************************************
1278 * CAC97AdapterCommon::PrimaryCodecReady
1279 *****************************************************************************
1280 * Checks whether the primary codec is present and ready. This may take
1281 * awhile if we are bringing it up from a cold reset so give it a second
1282 * before giving up.
1283 */
PrimaryCodecReady(void)1284 NTSTATUS CAC97AdapterCommon::PrimaryCodecReady (void)
1285 {
1286 PAGED_CODE ();
1287
1288 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::PrimaryCodecReady]"));
1289
1290
1291 //
1292 // Enable the AC link and raise the reset line.
1293 //
1294 DWORD dwRegValue = ReadBMControlRegister32 (GLOB_CNT);
1295
1296 // If someone enabled GPI Interrupt Enable, then he hopefully handles that
1297 // too.
1298 dwRegValue = (dwRegValue | GLOB_CNT_COLD) & ~(GLOB_CNT_ACLOFF | GLOB_CNT_PRIE);
1299 WriteBMControlRegister (GLOB_CNT, dwRegValue);
1300
1301 //
1302 // Wait for the Codec to be ready.
1303 //
1304 ULONG WaitCycles = 200;
1305 LARGE_INTEGER WaitTime;
1306
1307 WaitTime.QuadPart = (-50000); // wait 5000us (5ms) relative
1308
1309 do
1310 {
1311 if (READ_PORT_ULONG ((PULONG)(m_pBusMasterBase + GLOB_STA)) &
1312 GLOB_STA_PCR)
1313 {
1314 return STATUS_SUCCESS;
1315 }
1316
1317 KeDelayExecutionThread (KernelMode, FALSE, &WaitTime);
1318 } while (WaitCycles--);
1319
1320 DOUT (DBG_ERROR, ("PrimaryCodecReady timed out!"));
1321 return STATUS_IO_TIMEOUT;
1322 }
1323
1324
1325 /*****************************************************************************
1326 * CAC97AdapterCommon::PowerUpCodec
1327 *****************************************************************************
1328 * Sets the Codec to the highest power state and waits until the Codec reports
1329 * that the power state is reached.
1330 */
PowerUpCodec(void)1331 NTSTATUS CAC97AdapterCommon::PowerUpCodec (void)
1332 {
1333 PAGED_CODE ();
1334
1335 WORD wCodecReg;
1336 NTSTATUS ntStatus;
1337
1338 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::PowerUpCodec]"));
1339
1340 //
1341 // Power up the Codec.
1342 //
1343 WriteCodecRegister (AC97REG_POWERDOWN, 0x00, 0xFFFF);
1344
1345 //
1346 // Wait for the Codec to be powered up.
1347 //
1348 ULONG WaitCycles = 200;
1349 LARGE_INTEGER WaitTime;
1350
1351 WaitTime.QuadPart = (-50000); // wait 5000us (5ms) relative
1352
1353 do
1354 {
1355 //
1356 // Read the power management register.
1357 //
1358 ntStatus = ReadCodecRegister (AC97REG_POWERDOWN, &wCodecReg);
1359 if (!NT_SUCCESS (ntStatus))
1360 {
1361 wCodecReg = 0; // Will cause an error.
1362 break;
1363 }
1364
1365 //
1366 // Check the power state. Should be ready.
1367 //
1368 if ((wCodecReg & 0x0f) == 0x0f)
1369 break;
1370
1371 //
1372 // Let's wait a little, 5ms and then try again.
1373 //
1374 KeDelayExecutionThread (KernelMode, FALSE, &WaitTime);
1375 } while (WaitCycles--);
1376
1377 // Check if we timed out.
1378 if ((wCodecReg & 0x0f) != 0x0f)
1379 {
1380 DOUT (DBG_ERROR, ("PowerUpCodec timed out. CoDec not powered up."));
1381 ntStatus = STATUS_DEVICE_NOT_READY;
1382 }
1383
1384 return ntStatus;
1385 }
1386
1387
1388 /*****************************************************************************
1389 * CAC97AdapterCommon::ProgramSampleRate
1390 *****************************************************************************
1391 * Programs the sample rate. If the rate cannot be programmed, the routine
1392 * restores the register and returns STATUS_UNSUCCESSFUL.
1393 * We don't handle double rate sample rates here, because the Intel AC97 con-
1394 * troller cannot serve CoDecs with double rate or surround sound. If you want
1395 * to modify this driver for another AC97 controller, then you might want to
1396 * change this function too.
1397 */
STDMETHODIMP_(NTSTATUS)1398 STDMETHODIMP_(NTSTATUS) CAC97AdapterCommon::ProgramSampleRate
1399 (
1400 IN AC97Register Register,
1401 IN DWORD dwSampleRate
1402 )
1403 {
1404 PAGED_CODE ();
1405
1406 WORD wOldRateReg, wCodecReg;
1407 NTSTATUS ntStatus;
1408
1409 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::ProgramSampleRate]"));
1410
1411 //
1412 // Check if we support variable sample rate.
1413 //
1414 switch(Register)
1415 {
1416 case AC97REG_MIC_SAMPLERATE:
1417 //
1418 // Variable sample rate supported?
1419 //
1420 if (GetNodeConfig (NODEC_MIC_VARIABLERATE_SUPPORTED))
1421 {
1422 // Range supported?
1423 if (dwSampleRate > 48000ul)
1424 {
1425 // Not possible.
1426 DOUT (DBG_VSR, ("Samplerate %d not supported", dwSampleRate));
1427 return STATUS_NOT_SUPPORTED;
1428 }
1429 }
1430 else
1431 {
1432 // Only 48000KHz possible.
1433 if (dwSampleRate != 48000ul)
1434 {
1435 DOUT (DBG_VSR, ("Samplerate %d not supported", dwSampleRate));
1436 return STATUS_NOT_SUPPORTED;
1437 }
1438
1439 return STATUS_SUCCESS;
1440 }
1441 break;
1442
1443 case AC97REG_FRONT_SAMPLERATE:
1444 case AC97REG_SURROUND_SAMPLERATE:
1445 case AC97REG_LFE_SAMPLERATE:
1446 case AC97REG_RECORD_SAMPLERATE:
1447 //
1448 // Variable sample rate supported?
1449 //
1450 if (GetNodeConfig (NODEC_PCM_VARIABLERATE_SUPPORTED))
1451 {
1452 //
1453 // Check range supported
1454 //
1455 if (dwSampleRate > 48000ul)
1456 {
1457 DOUT (DBG_VSR, ("Samplerate %d not supported", dwSampleRate));
1458 return STATUS_NOT_SUPPORTED;
1459 }
1460 }
1461 else
1462 {
1463 // Only 48KHz possible.
1464 if (dwSampleRate != 48000ul)
1465 {
1466 DOUT (DBG_VSR, ("Samplerate %d not supported", dwSampleRate));
1467 return STATUS_NOT_SUPPORTED;
1468 }
1469
1470 return STATUS_SUCCESS;
1471 }
1472 break;
1473
1474 default:
1475 DOUT (DBG_ERROR, ("Invalid sample rate register!"));
1476 return STATUS_UNSUCCESSFUL;
1477 }
1478
1479
1480 //
1481 // Save the old sample rate register.
1482 //
1483 ntStatus = ReadCodecRegister (Register, &wOldRateReg);
1484 if (!NT_SUCCESS (ntStatus))
1485 return ntStatus;
1486
1487 //
1488 // program the rate.
1489 //
1490 ntStatus = WriteCodecRegister (Register, (WORD)dwSampleRate, 0xFFFF);
1491 if (!NT_SUCCESS (ntStatus))
1492 {
1493 DOUT (DBG_ERROR, ("Cannot program sample rate."));
1494 return ntStatus;
1495 }
1496
1497 //
1498 // Read it back.
1499 //
1500 ntStatus = ReadCodecRegister (Register, &wCodecReg);
1501 if (!NT_SUCCESS (ntStatus))
1502 {
1503 DOUT (DBG_ERROR, ("Cannot read sample rate."));
1504 return ntStatus;
1505 }
1506
1507 //
1508 // Validate.
1509 //
1510 if (wCodecReg != dwSampleRate)
1511 {
1512 //
1513 // restore sample rate and ctrl register.
1514 //
1515 WriteCodecRegister (Register, wOldRateReg, 0xFFFF);
1516
1517 DOUT (DBG_VSR, ("Samplerate %d not supported", dwSampleRate));
1518 return STATUS_NOT_SUPPORTED;
1519 }
1520
1521 DOUT (DBG_VSR, ("Samplerate changed to %d.", dwSampleRate));
1522 return STATUS_SUCCESS;
1523 }
1524
1525
1526 /*****************************************************************************
1527 * CAC97AdapterCommon::PowerChangeState
1528 *****************************************************************************
1529 * Change power state for the device. We handle the codec, PowerChangeNotify
1530 * in the wave miniport handles the DMA registers.
1531 */
STDMETHODIMP_(void)1532 STDMETHODIMP_(void) CAC97AdapterCommon::PowerChangeState
1533 (
1534 _In_ POWER_STATE NewState
1535 )
1536 {
1537 PAGED_CODE ();
1538
1539 NTSTATUS ntStatus = STATUS_SUCCESS;
1540
1541 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::PowerChangeNotify]"));
1542
1543 //
1544 // Check to see if this is the current power state.
1545 //
1546 if (NewState.DeviceState == m_PowerState)
1547 {
1548 DOUT (DBG_POWER, ("New device state equals old state."));
1549 return;
1550 }
1551
1552 //
1553 // Check the new device state.
1554 //
1555 if ((NewState.DeviceState < PowerDeviceD0) ||
1556 (NewState.DeviceState > PowerDeviceD3))
1557 {
1558 DOUT (DBG_ERROR, ("Unknown device state: D%d.",
1559 (ULONG)NewState.DeviceState - (ULONG)PowerDeviceD0));
1560 return;
1561 }
1562
1563 DOUT (DBG_POWER, ("Changing state to D%d.", (ULONG)NewState.DeviceState -
1564 (ULONG)PowerDeviceD0));
1565
1566 //
1567 // Switch on new state.
1568 //
1569 switch (NewState.DeviceState)
1570 {
1571 case PowerDeviceD0:
1572 //
1573 // If we are coming from D2 or D3 we have to restore the registers cause
1574 // there might have been a power loss.
1575 //
1576 if ((m_PowerState == PowerDeviceD3) || (m_PowerState == PowerDeviceD2))
1577 {
1578 //
1579 // Reset AD3 to indicate that we are now awake.
1580 // Because the system has only one power irp at a time, we are sure
1581 // that the modem driver doesn't get called while we are restoring
1582 // power.
1583 //
1584 WriteBMControlRegister (GLOB_STA,
1585 ReadBMControlRegister32 (GLOB_STA) & ~GLOB_STA_AD3);
1586
1587 //
1588 // Restore codec registers.
1589 //
1590 ntStatus = RestoreCodecRegisters ();
1591 }
1592 else // We are coming from power state D1
1593 {
1594 ntStatus = PowerUpCodec ();
1595 }
1596
1597 // Print error code.
1598 if (!NT_SUCCESS (ntStatus))
1599 {
1600 DOUT (DBG_ERROR, ("PowerChangeState failed to restore the codec."));
1601 }
1602 break;
1603
1604 case PowerDeviceD1:
1605 //
1606 // This sleep state is the lowest latency sleep state with respect
1607 // to the latency time required to return to D0. If the
1608 // driver is not being used an inactivity timer in portcls will
1609 // place the driver in this state after a timeout period
1610 // controllable via the registry.
1611 //
1612
1613 // Let's power down the DAC/ADC's and analog mixer.
1614 WriteCodecRegister (AC97REG_POWERDOWN, 0x0700, 0xFFFF);
1615 break;
1616
1617 case PowerDeviceD2:
1618 case PowerDeviceD3:
1619 //
1620 // This is a full hibernation state and is the longest latency sleep
1621 // state. In this modes the power could be removed or reduced that
1622 // much that the AC97 controller looses information, so we save
1623 // whatever we have to save.
1624 //
1625
1626 //
1627 // Powerdown ADC, DAC, Mixer, Vref, HP amp, and Exernal Amp but not
1628 // AC-link and Clk
1629 //
1630 WriteCodecRegister (AC97REG_POWERDOWN, 0xCF00, 0xFFFF);
1631
1632 //
1633 // Only in D3 mode we set the AD3 bit and evtl. shut off the AC link.
1634 //
1635 if (NewState.DeviceState == PowerDeviceD3)
1636 {
1637 //
1638 // Set the AD3 bit.
1639 //
1640 ULONG ulReg = ReadBMControlRegister32 (GLOB_STA);
1641 WriteBMControlRegister (GLOB_STA, ulReg | GLOB_STA_AD3);
1642
1643 //
1644 // We check if the modem is sleeping. If it is, we can shut off the
1645 // AC link also. We shut off the AC link also if the modem is not
1646 // there.
1647 //
1648 if ((ulReg & GLOB_STA_MD3) || !(ulReg & GLOB_STA_SCR))
1649 {
1650 // Set Codec to super sleep
1651 WriteCodecRegister (AC97REG_POWERDOWN, 0xFF00, 0xFFFF);
1652
1653 // Disable the AC-link signals
1654 ulReg = ReadBMControlRegister32 (GLOB_CNT);
1655 WriteBMControlRegister (GLOB_CNT, (ulReg | GLOB_CNT_ACLOFF) & ~GLOB_CNT_COLD);
1656 }
1657 }
1658 break;
1659 }
1660
1661 //
1662 // Save the new state. This local value is used to determine when to
1663 // cache property accesses and when to permit the driver from accessing
1664 // the hardware.
1665 //
1666 m_PowerState = NewState.DeviceState;
1667 DOUT (DBG_POWER, ("Entering D%d", (ULONG)m_PowerState -
1668 (ULONG)PowerDeviceD0));
1669 }
1670
1671
1672 /*****************************************************************************
1673 * CAC97AdapterCommon::QueryPowerChangeState
1674 *****************************************************************************
1675 * Query to see if the device can change to this power state
1676 */
STDMETHODIMP_(NTSTATUS)1677 STDMETHODIMP_(NTSTATUS) CAC97AdapterCommon::QueryPowerChangeState
1678 (
1679 _In_ POWER_STATE NewState
1680 )
1681 {
1682 PAGED_CODE ();
1683
1684 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::QueryPowerChangeState]"));
1685
1686 // Check here to see of a legitimate state is being requested
1687 // based on the device state and fail the call if the device/driver
1688 // cannot support the change requested. Otherwise, return STATUS_SUCCESS.
1689 // Note: A QueryPowerChangeState() call is not guaranteed to always preceed
1690 // a PowerChangeState() call.
1691
1692 // check the new state being requested
1693 switch (NewState.DeviceState)
1694 {
1695 case PowerDeviceD0:
1696 case PowerDeviceD1:
1697 case PowerDeviceD2:
1698 case PowerDeviceD3:
1699 return STATUS_SUCCESS;
1700
1701 default:
1702 DOUT (DBG_ERROR, ("Unknown device state: D%d.",
1703 (ULONG)NewState.DeviceState - (ULONG)PowerDeviceD0));
1704 return STATUS_NOT_IMPLEMENTED;
1705 }
1706 }
1707
1708
1709 /*****************************************************************************
1710 * CAC97AdapterCommon::QueryDeviceCapabilities
1711 *****************************************************************************
1712 * Called at startup to get the caps for the device. This structure provides
1713 * the system with the mappings between system power state and device power
1714 * state. This typically will not need modification by the driver.
1715 * If the driver modifies these mappings then the driver is not allowed to
1716 * change the mapping to a weaker power state (e.g. from S1->D3 to S1->D1).
1717 *
1718 */
1719 _Use_decl_annotations_
STDMETHODIMP_(NTSTATUS)1720 STDMETHODIMP_(NTSTATUS) CAC97AdapterCommon::QueryDeviceCapabilities
1721 (
1722 PDEVICE_CAPABILITIES PowerDeviceCaps
1723 )
1724 {
1725 PAGED_CODE ();
1726
1727 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::QueryDeviceCapabilities]"));
1728
1729 UNREFERENCED_PARAMETER(PowerDeviceCaps);
1730
1731 return STATUS_SUCCESS;
1732 }
1733
1734
1735 /*****************************************************************************
1736 * CAC97AdapterCommon::RestoreAC97Registers
1737 *****************************************************************************
1738 * Preset the AC97 registers with default values. The routine first checks if
1739 * There are registry entries for the default values. If not, we have hard
1740 * coded values too ;)
1741 */
SetAC97Default(void)1742 NTSTATUS CAC97AdapterCommon::SetAC97Default (void)
1743 {
1744 PAGED_CODE ();
1745
1746 PREGISTRYKEY DriverKey;
1747 PREGISTRYKEY SettingsKey;
1748 UNICODE_STRING sKeyName;
1749 ULONG ulDisposition;
1750 ULONG ulResultLength;
1751 PVOID KeyInfo = NULL;
1752
1753 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::SetAC97Default]"));
1754
1755 // open the driver registry key
1756 NTSTATUS ntStatus = PcNewRegistryKey (&DriverKey, // IRegistryKey
1757 NULL, // OuterUnknown
1758 DriverRegistryKey, // Registry key type
1759 KEY_READ, // Access flags
1760 m_pDeviceObject, // Device object
1761 NULL, // Subdevice
1762 NULL, // ObjectAttributes
1763 0, // Create options
1764 NULL); // Disposition
1765 if (NT_SUCCESS (ntStatus))
1766 {
1767 // make a unicode string for the subkey name
1768 RtlInitUnicodeString (&sKeyName, L"Settings");
1769
1770 // open the settings subkey
1771 ntStatus = DriverKey->NewSubKey (&SettingsKey, // Subkey
1772 NULL, // OuterUnknown
1773 KEY_READ, // Access flags
1774 &sKeyName, // Subkey name
1775 REG_OPTION_NON_VOLATILE, // Create options
1776 &ulDisposition);
1777
1778 if (NT_SUCCESS (ntStatus))
1779 {
1780 // allocate data to hold key info
1781 KeyInfo = ExAllocatePoolWithTag (PagedPool,
1782 sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
1783 sizeof(WORD), PoolTag);
1784 if (NULL != KeyInfo)
1785 {
1786 // loop through all mixer settings
1787 for (AC97Register i = AC97REG_RESET; i <= AC97REG_RESERVED2;
1788 i = (AC97Register)(i + 1))
1789 {
1790 if (m_stAC97Registers[i].wFlags & SHREG_INIT)
1791 {
1792 // init key name
1793 RtlInitUnicodeString (&sKeyName,
1794 m_stAC97Registers[i].sRegistryName);
1795
1796 // query the value key
1797 ntStatus = SettingsKey->QueryValueKey (&sKeyName,
1798 KeyValuePartialInformation,
1799 KeyInfo,
1800 sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
1801 sizeof(WORD),
1802 &ulResultLength);
1803 if (NT_SUCCESS (ntStatus))
1804 {
1805 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo =
1806 (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo;
1807
1808 if (PartialInfo->DataLength == sizeof(WORD))
1809 {
1810 // set mixer register to registry value
1811 WriteCodecRegister
1812 (i, *(PWORD)PartialInfo->Data, 0xFFFF);
1813 }
1814 else // write the hard coded default
1815 {
1816 // if key access failed, set to default
1817 WriteCodecRegister
1818 (i, m_stAC97Registers[i].wWantedDefault, 0xFFFF);
1819 }
1820 }
1821 else // write the hard coded default
1822 {
1823 // if key access failed, set to default
1824 WriteCodecRegister
1825 (i, m_stAC97Registers[i].wWantedDefault, 0xFFFF);
1826 }
1827 }
1828 }
1829
1830 // we want to return status success even if the last QueryValueKey
1831 // failed.
1832 ntStatus = STATUS_SUCCESS;
1833
1834 // free the key info
1835 ExFreePoolWithTag (KeyInfo,PoolTag);
1836 }
1837 else
1838 {
1839 ntStatus = STATUS_INSUFFICIENT_RESOURCES;
1840 }
1841
1842 // release the settings key
1843 SettingsKey->Release ();
1844 }
1845
1846 // release the driver key
1847 DriverKey->Release ();
1848 }
1849
1850
1851 // in case we did not query the registry (cause of lack of resources)
1852 // restore default values and return insufficient resources.
1853 if (!NT_SUCCESS (ntStatus))
1854 {
1855 // copy hard coded default settings
1856 for (AC97Register i = AC97REG_RESET; i < AC97REG_RESERVED2;
1857 i = (AC97Register)(i + 1))
1858 {
1859 if (m_stAC97Registers[i].wFlags & SHREG_INIT)
1860 {
1861 WriteCodecRegister (i, m_stAC97Registers[i].wWantedDefault, 0xFFFF);
1862 }
1863 }
1864 }
1865
1866 return ntStatus;
1867 }
1868
1869
1870 /*****************************************************************************
1871 * CAC97AdapterCommon::DisableAC97Pin
1872 *****************************************************************************
1873 * Returns TRUE when the HW vendor wants to disable the pin. A disabled pin is
1874 * not shown to the user (means it is not included in the topology). The
1875 * reason for doing this could be that some of the input lines like Aux or
1876 * Video are not available to the user (to plug in something) but the codec
1877 * can handle those lines.
1878 */
DisableAC97Pin(IN TopoPinConfig pin)1879 BOOL CAC97AdapterCommon::DisableAC97Pin
1880 (
1881 IN TopoPinConfig pin
1882 )
1883 {
1884 PAGED_CODE ();
1885
1886 PREGISTRYKEY DriverKey;
1887 PREGISTRYKEY SettingsKey;
1888 UNICODE_STRING sKeyName;
1889 ULONG ulDisposition;
1890 ULONG ulResultLength;
1891 PVOID KeyInfo = NULL;
1892 BOOL bDisable = FALSE;
1893
1894 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::DisableAC97Pin]"));
1895
1896 // open the driver registry key
1897 NTSTATUS ntStatus = PcNewRegistryKey (&DriverKey, // IRegistryKey
1898 NULL, // OuterUnknown
1899 DriverRegistryKey, // Registry key type
1900 KEY_READ, // Access flags
1901 m_pDeviceObject, // Device object
1902 NULL, // Subdevice
1903 NULL, // ObjectAttributes
1904 0, // Create options
1905 NULL); // Disposition
1906 if (NT_SUCCESS (ntStatus))
1907 {
1908 // make a unicode string for the subkey name
1909 RtlInitUnicodeString (&sKeyName, L"Settings");
1910
1911 // open the settings subkey
1912 ntStatus = DriverKey->NewSubKey (&SettingsKey, // Subkey
1913 NULL, // OuterUnknown
1914 KEY_READ, // Access flags
1915 &sKeyName, // Subkey name
1916 REG_OPTION_NON_VOLATILE, // Create options
1917 &ulDisposition);
1918
1919 if (NT_SUCCESS (ntStatus))
1920 {
1921 // allocate data to hold key info
1922 KeyInfo = ExAllocatePoolWithTag (PagedPool,
1923 sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
1924 sizeof(BYTE), PoolTag);
1925 if (NULL != KeyInfo)
1926 {
1927 // init key name
1928 RtlInitUnicodeString (&sKeyName, m_stHardwareConfig.
1929 Pins[pin].sRegistryName);
1930
1931 // query the value key
1932 ntStatus = SettingsKey->QueryValueKey (&sKeyName,
1933 KeyValuePartialInformation,
1934 KeyInfo,
1935 sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
1936 sizeof(BYTE),
1937 &ulResultLength );
1938 if (NT_SUCCESS (ntStatus))
1939 {
1940 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo =
1941 (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo;
1942
1943 if (PartialInfo->DataLength == sizeof(BYTE))
1944 {
1945 // store the value
1946 if (*(PBYTE)PartialInfo->Data)
1947 bDisable = TRUE;
1948 else
1949 bDisable = FALSE;
1950 }
1951 }
1952
1953 // free the key info
1954 ExFreePoolWithTag (KeyInfo,PoolTag);
1955 }
1956
1957 // release the settings key
1958 SettingsKey->Release ();
1959 }
1960
1961 // release the driver key
1962 DriverKey->Release ();
1963 }
1964
1965 // if one of the stuff above fails we return the default, which is FALSE.
1966 return bDisable;
1967 }
1968
1969
1970 /*****************************************************************************
1971 * CAC97AdapterCommon::RestoreCodecRegisters
1972 *****************************************************************************
1973 * write back cached mixer values to codec registers
1974 */
RestoreCodecRegisters(void)1975 NTSTATUS CAC97AdapterCommon::RestoreCodecRegisters (void)
1976 {
1977 PAGED_CODE ();
1978
1979 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::RestoreCodecRegisters]"));
1980
1981 //
1982 // Initialize the AC97 codec.
1983 //
1984 NTSTATUS ntStatus = InitAC97 ();
1985 if (!NT_SUCCESS (ntStatus))
1986 return ntStatus;
1987
1988 //
1989 // Restore all codec registers. Failure is not critical.
1990 //
1991 for (AC97Register i = AC97REG_MASTER_VOLUME; i < AC97REG_RESERVED2;
1992 i = (AC97Register)(i + 1))
1993 {
1994 WriteCodecRegister (i, m_stAC97Registers[i].wCache, 0xFFFF);
1995 }
1996
1997 return STATUS_SUCCESS;
1998 }
1999
2000 /*****************************************************************************
2001 * CAC97AdapterCommon::ReadChannelConfigDefault
2002 *****************************************************************************
2003 * This function reads the default channel config from the registry. The
2004 * registry entry "ChannelConfig" is set every every time we get a
2005 * KSPROPERTY_AUDIO_CHANNEL_CONFIG for the DAC node.
2006 * In case the key doesn't exist we assume a channel config of stereo speakers,
2007 * cause that is the default of DSOUND.
2008 */
STDMETHODIMP_(void)2009 STDMETHODIMP_(void) CAC97AdapterCommon::ReadChannelConfigDefault
2010 (
2011 PDWORD pdwChannelConfig,
2012 PWORD pwChannels
2013 )
2014 {
2015 PAGED_CODE ();
2016
2017 PREGISTRYKEY DriverKey;
2018 PREGISTRYKEY SettingsKey;
2019 UNICODE_STRING sKeyName;
2020 ULONG ulDisposition;
2021 ULONG ulResultLength;
2022 PVOID KeyInfo = NULL;
2023
2024 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::ReadChannelConfigDefault]"));
2025
2026 // This is the default: 2 speakers, stereo.
2027 *pdwChannelConfig = KSAUDIO_SPEAKER_STEREO;
2028 *pwChannels = 2;
2029
2030 // open the driver registry key
2031 NTSTATUS ntStatus = PcNewRegistryKey (&DriverKey, // IRegistryKey
2032 NULL, // OuterUnknown
2033 DriverRegistryKey, // Registry key type
2034 KEY_READ, // Access flags
2035 m_pDeviceObject, // Device object
2036 NULL, // Subdevice
2037 NULL, // ObjectAttributes
2038 0, // Create options
2039 NULL); // Disposition
2040 if (NT_SUCCESS (ntStatus))
2041 {
2042 // make a unicode string for the subkey name
2043 RtlInitUnicodeString (&sKeyName, L"Settings");
2044
2045 // open the settings subkey
2046 ntStatus = DriverKey->NewSubKey (&SettingsKey, // Subkey
2047 NULL, // OuterUnknown
2048 KEY_READ, // Access flags
2049 &sKeyName, // Subkey name
2050 REG_OPTION_NON_VOLATILE, // Create options
2051 &ulDisposition);
2052
2053 if (NT_SUCCESS (ntStatus))
2054 {
2055 // allocate data to hold key info
2056 KeyInfo = ExAllocatePoolWithTag (PagedPool,
2057 sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
2058 sizeof(DWORD), PoolTag);
2059 if (NULL != KeyInfo)
2060 {
2061 // init key name
2062 RtlInitUnicodeString (&sKeyName, L"ChannelConfig");
2063
2064 // query the value key
2065 ntStatus = SettingsKey->QueryValueKey (&sKeyName,
2066 KeyValuePartialInformation,
2067 KeyInfo,
2068 sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
2069 sizeof(DWORD),
2070 &ulResultLength );
2071 if (NT_SUCCESS (ntStatus))
2072 {
2073 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo =
2074 (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo;
2075
2076 if (PartialInfo->DataLength == sizeof(DWORD))
2077 {
2078 switch (*(PLONG)PartialInfo->Data)
2079 {
2080 case KSAUDIO_SPEAKER_QUAD:
2081 case KSAUDIO_SPEAKER_SURROUND:
2082 if (GetPinConfig (PINC_SURROUND_PRESENT))
2083 {
2084 *pdwChannelConfig = *(PDWORD)PartialInfo->Data;
2085 *pwChannels = 4;
2086 }
2087 break;
2088
2089 case KSAUDIO_SPEAKER_5POINT1:
2090 if (GetPinConfig (PINC_SURROUND_PRESENT) &&
2091 GetPinConfig (PINC_CENTER_LFE_PRESENT))
2092 {
2093 *pdwChannelConfig = *(PDWORD)PartialInfo->Data;
2094 *pwChannels = 6;
2095 }
2096 break;
2097 }
2098 }
2099 }
2100
2101 // free the key info
2102 ExFreePoolWithTag (KeyInfo,PoolTag);
2103 }
2104
2105 // release the settings key
2106 SettingsKey->Release ();
2107 }
2108
2109 // release the driver key
2110 DriverKey->Release ();
2111 }
2112 }
2113
2114 /*****************************************************************************
2115 * CAC97AdapterCommon::WriteChannelConfigDefault
2116 *****************************************************************************
2117 * This function writes the default channel config to the registry. The
2118 * registry entry "ChannelConfig" is set every every time we get a
2119 * KSPROPERTY_AUDIO_CHANNEL_CONFIG for the DAC node.
2120 */
STDMETHODIMP_(void)2121 STDMETHODIMP_(void) CAC97AdapterCommon::WriteChannelConfigDefault (DWORD dwChannelConfig)
2122 {
2123 PAGED_CODE ();
2124
2125 PREGISTRYKEY DriverKey;
2126 PREGISTRYKEY SettingsKey;
2127 UNICODE_STRING sKeyName;
2128 ULONG ulDisposition;
2129
2130 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::WriteChannelConfigDefault]"));
2131
2132 // open the driver registry key
2133 NTSTATUS ntStatus = PcNewRegistryKey (&DriverKey, // IRegistryKey
2134 NULL, // OuterUnknown
2135 DriverRegistryKey, // Registry key type
2136 KEY_WRITE, // Access flags
2137 m_pDeviceObject, // Device object
2138 NULL, // Subdevice
2139 NULL, // ObjectAttributes
2140 0, // Create options
2141 NULL); // Disposition
2142 if (NT_SUCCESS (ntStatus))
2143 {
2144 // make a unicode string for the subkey name
2145 RtlInitUnicodeString (&sKeyName, L"Settings");
2146
2147 // open the settings subkey
2148 ntStatus = DriverKey->NewSubKey (&SettingsKey, // Subkey
2149 NULL, // OuterUnknown
2150 KEY_WRITE, // Access flags
2151 &sKeyName, // Subkey name
2152 REG_OPTION_NON_VOLATILE, // Create options
2153 &ulDisposition);
2154
2155 if (NT_SUCCESS (ntStatus))
2156 {
2157 // init key name
2158 RtlInitUnicodeString (&sKeyName, L"ChannelConfig");
2159
2160 // query the value key
2161 ntStatus = SettingsKey->SetValueKey (&sKeyName,
2162 REG_DWORD,
2163 &dwChannelConfig,
2164 sizeof (DWORD));
2165 if (!NT_SUCCESS (ntStatus))
2166 {
2167 DOUT (DBG_ERROR, ("Could not write the ChannelConfig to registry."));
2168 }
2169
2170 // release the settings key
2171 SettingsKey->Release ();
2172 }
2173
2174 // release the driver key
2175 DriverKey->Release ();
2176 }
2177 }
2178
2179 /*****************************************************************************
2180 * Non paged code begins here
2181 *****************************************************************************
2182 */
2183
2184 #ifdef _MSC_VER
2185 #pragma code_seg()
2186 #endif
2187 /*****************************************************************************
2188 * CAC97AdapterCommon::WriteBMControlRegister
2189 *****************************************************************************
2190 * Writes a byte (UCHAR) to BusMaster Control register.
2191 */
STDMETHODIMP_(void)2192 STDMETHODIMP_(void) CAC97AdapterCommon::WriteBMControlRegister
2193 (
2194 IN ULONG ulOffset,
2195 IN UCHAR ucValue
2196 )
2197 {
2198 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::WriteBMControlRegister] (UCHAR)"));
2199
2200 WRITE_PORT_UCHAR ((PUCHAR)(m_pBusMasterBase + ulOffset), ucValue);
2201
2202 DOUT (DBG_REGS, ("WriteBMControlRegister wrote 0x%2x to 0x%4p.",
2203 ucValue, m_pBusMasterBase + ulOffset));
2204 }
2205
2206 /*****************************************************************************
2207 * CAC97AdapterCommon::WriteBMControlRegister
2208 *****************************************************************************
2209 * Writes a word (USHORT) to BusMaster Control register.
2210 */
STDMETHODIMP_(void)2211 STDMETHODIMP_(void) CAC97AdapterCommon::WriteBMControlRegister
2212 (
2213 IN ULONG ulOffset,
2214 IN USHORT usValue
2215 )
2216 {
2217 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::WriteBMControlRegister (USHORT)]"));
2218
2219 WRITE_PORT_USHORT ((PUSHORT)(m_pBusMasterBase + ulOffset), usValue);
2220
2221 DOUT (DBG_REGS, ("WriteBMControlRegister wrote 0x%4x to 0x%4p",
2222 usValue, m_pBusMasterBase + ulOffset));
2223 }
2224
2225 /*****************************************************************************
2226 * CAC97AdapterCommon::WriteBMControlRegister
2227 *****************************************************************************
2228 * Writes a DWORD (ULONG) to BusMaster Control register.
2229 */
STDMETHODIMP_(void)2230 STDMETHODIMP_(void) CAC97AdapterCommon::WriteBMControlRegister
2231 (
2232 IN ULONG ulOffset,
2233 IN ULONG ulValue
2234 )
2235 {
2236 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::WriteBMControlRegister (ULONG)]"));
2237
2238 WRITE_PORT_ULONG ((PULONG)(m_pBusMasterBase + ulOffset), ulValue);
2239
2240 DOUT (DBG_REGS, ("WriteBMControlRegister wrote 0x%8x to 0x%4p.",
2241 ulValue, m_pBusMasterBase + ulOffset));
2242 }
2243
2244 /*****************************************************************************
2245 * CAC97AdapterCommon::ReadBMControlRegister8
2246 *****************************************************************************
2247 * Read a byte (UCHAR) from BusMaster Control register.
2248 */
STDMETHODIMP_(UCHAR)2249 STDMETHODIMP_(UCHAR) CAC97AdapterCommon::ReadBMControlRegister8
2250 (
2251 IN ULONG ulOffset
2252 )
2253 {
2254 UCHAR ucValue = UCHAR(-1);
2255
2256 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::ReadBMControlRegister8]"));
2257
2258 ucValue = READ_PORT_UCHAR ((PUCHAR)(m_pBusMasterBase + ulOffset));
2259
2260 DOUT (DBG_REGS, ("ReadBMControlRegister read 0x%2x from 0x%4p.", ucValue,
2261 m_pBusMasterBase + ulOffset));
2262
2263 return ucValue;
2264 }
2265
2266 /*****************************************************************************
2267 * CAC97AdapterCommon::ReadBMControlRegister16
2268 *****************************************************************************
2269 * Read a word (USHORT) from BusMaster Control register.
2270 */
STDMETHODIMP_(USHORT)2271 STDMETHODIMP_(USHORT) CAC97AdapterCommon::ReadBMControlRegister16
2272 (
2273 IN ULONG ulOffset
2274 )
2275 {
2276 USHORT usValue = USHORT(-1);
2277
2278 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::ReadBMControlRegister16]"));
2279
2280 usValue = READ_PORT_USHORT ((PUSHORT)(m_pBusMasterBase + ulOffset));
2281
2282 DOUT (DBG_REGS, ("ReadBMControlRegister read 0x%4x = 0x%4p", usValue,
2283 m_pBusMasterBase + ulOffset));
2284
2285 return usValue;
2286 }
2287
2288 /*****************************************************************************
2289 * CAC97AdapterCommon::ReadBMControlRegister32
2290 *****************************************************************************
2291 * Read a dword (ULONG) from BusMaster Control register.
2292 */
STDMETHODIMP_(ULONG)2293 STDMETHODIMP_(ULONG) CAC97AdapterCommon::ReadBMControlRegister32
2294 (
2295 IN ULONG ulOffset
2296 )
2297 {
2298 ULONG ulValue = ULONG(-1);
2299
2300 DOUT (DBG_PRINT, ("[CAC97AdapterCommon::ReadBMControlRegister32]"));
2301
2302 ulValue = READ_PORT_ULONG ((PULONG)(m_pBusMasterBase + ulOffset));
2303
2304 DOUT (DBG_REGS, ("ReadBMControlRegister read 0x%8x = 0x%4p", ulValue,
2305 m_pBusMasterBase + ulOffset));
2306
2307 return ulValue;
2308 }
2309
2310