2 Copyright (c) 2006-2007 dogbert <dogber1@gmail.com>
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
8 1. Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 3. The name of the author may not be used to endorse or promote products
14 derived from this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "minwave.hpp"
29 #include "minwavetables.hpp"
32 #pragma code_seg("PAGE")
34 HRESULT NTAPI
CreateMiniportWaveCMI(PUNKNOWN
*Unknown
, REFCLSID
, PUNKNOWN UnknownOuter
, POOL_TYPE PoolType
)
39 STD_CREATE_BODY_(CMiniportWaveCMI
,Unknown
,UnknownOuter
,PoolType
,PMINIPORTWAVERT
);
41 STD_CREATE_BODY_(CMiniportWaveCMI
,Unknown
,UnknownOuter
,PoolType
,PMINIPORTWAVECYCLIC
);
45 NTSTATUS
CMiniportWaveCMI::processResources(PRESOURCELIST resourceList
)
48 //ASSERT (resourceList);
49 DBGPRINT(("CMiniportWaveCMI[%p]::ProcessResources(%p)", this, resourceList
));
51 if (resourceList
->NumberOfInterrupts() < 1) {
52 DBGPRINT(("Unknown configuration for wave miniport"));
53 return STATUS_DEVICE_CONFIGURATION_ERROR
;
55 return STATUS_SUCCESS
;
59 NTSTATUS
CMiniportWaveCMI::newDMAChannel(PDMACHANNEL
*dmaChannel
, UInt32 bufferLength
)
63 DBGPRINT(("CMiniportWaveCMI[%p]::newDMAChannel(%p)", this, dmaChannel
));
67 ntStatus
= Port
->NewMasterDmaChannel(dmaChannel
, NULL
, NULL
, bufferLength
, TRUE
, FALSE
, (DMA_WIDTH
)(-1), (DMA_SPEED
)(-1));
68 if (NT_SUCCESS(ntStatus
)) {
69 ULONG lDMABufferLength
= bufferLength
;
71 ntStatus
= (*dmaChannel
)->AllocateBuffer(lDMABufferLength
,NULL
);
72 lDMABufferLength
>>= 1;
73 } while (!NT_SUCCESS(ntStatus
) && (lDMABufferLength
> (PAGE_SIZE
/ 2)));
80 STDMETHODIMP
CMiniportWaveCMI::QueryInterface(REFIID Interface
, PVOID
*Object
)
84 DBGPRINT(("CMiniportWaveCMI[%p]::NonDelegatingQueryInterface"));
86 if (IsEqualGUIDAligned(Interface
,IID_IUnknown
)) {
88 *Object
= PVOID(PUNKNOWN(PMINIPORTWAVERT(this)));
90 *Object
= PVOID(PUNKNOWN(PMINIPORTWAVECYCLIC(this)));
92 } else if (IsEqualGUIDAligned(Interface
,IID_IMiniport
)) {
93 *Object
= PVOID(PMINIPORT(this));
95 } else if (IsEqualGUIDAligned(Interface
,IID_IMiniportWaveRT
)) {
96 *Object
= PVOID(PMINIPORTWAVERT(this));
98 } else if (IsEqualGUIDAligned(Interface
,IID_IMiniportWaveCyclic
)) {
99 *Object
= PVOID(PMINIPORTWAVECYCLIC(this));
106 // We reference the interface for the caller.
107 PUNKNOWN(*Object
)->AddRef();
108 return STATUS_SUCCESS
;
111 return STATUS_INVALID_PARAMETER
;
114 CMiniportWaveCMI::~CMiniportWaveCMI(void)
117 DBGPRINT(("CMiniportWaveCMI[%p]::~CMiniportWaveCMI", this));
119 storeChannelConfigToRegistry(); //or not. during system shutdown, this doesn't seem to work.
122 CMIAdapter
->Release();
126 for (int i
=0;i
<3;i
++) {
129 DMAChannel
[i
]->Release();
130 DMAChannel
[i
] = NULL
;
133 if (isStreamRunning
[i
]) {
134 isStreamRunning
[i
] = false;
135 stream
[i
]->Release();
147 STDMETHODIMP
CMiniportWaveCMI::Init(PUNKNOWN UnknownAdapter
, PRESOURCELIST ResourceList
, PPORTWAVERT Port_
)
149 STDMETHODIMP
CMiniportWaveCMI::Init(PUNKNOWN UnknownAdapter
, PRESOURCELIST ResourceList
, PPORTWAVECYCLIC Port_
)
154 //ASSERT(UnknownAdapter);
155 //ASSERT(ResourceList);
158 DBGPRINT(("CMiniportWaveCMI[%p]::Init(%p, %p, %p)", this, UnknownAdapter
, ResourceList
, Port_
));
163 NTSTATUS ntStatus
= UnknownAdapter
->QueryInterface(IID_ICMIAdapter
, (PVOID
*) &CMIAdapter
);
164 if (!NT_SUCCESS(ntStatus
)) {
165 DBGPRINT(("QueryInterface(CMIAdapter) failed"));
169 //check for Vista, set the AC3 stuff accordingly
170 if (IoIsWdmVersionAvailable(0x06,0x00)) {
171 WavePinDataRangesAC3Stream
[1].MinimumSampleFrequency
= MIN_SAMPLE_RATE
;
172 WavePinDataRangesAC3Stream
[1].MaximumSampleFrequency
= MAX_SAMPLE_RATE
;
173 WavePinDataRangesAC3Stream
[1].DataRange
.SubFormat
= KSDATAFORMAT_SUBTYPE_PCM
;
174 WavePinDataRangesAC3Stream
[1].DataRange
.Specifier
= KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
;
177 cm
= CMIAdapter
->getCMI8738Info();
179 cm
->WaveMiniport
= this;
181 loadChannelConfigFromRegistry();
183 for (int i
=0;i
<3;i
++)
185 isStreamRunning
[i
] = false;
188 ntStatus
= newDMAChannel(&DMAChannel
[i
], MAXLEN_DMA_BUFFER
);
189 if (!NT_SUCCESS(ntStatus
)) {
190 DBGPRINT(("NewDmaChannel() failed"));
196 KeInitializeMutex(&mutex
, 1);
198 return processResources(ResourceList
);
202 STDMETHODIMP_(NTSTATUS
) CMiniportWaveCMI::GetDeviceDescription(PDEVICE_DESCRIPTION OutDeviceDescriptor
)
205 //ASSERT(OutDeviceDescriptor);
206 DBGPRINT(("CMiniportWaveCMI[%p]::GetDeviceDescription(%p)", this, OutDeviceDescriptor
));
208 RtlZeroMemory(OutDeviceDescriptor
, sizeof(DEVICE_DESCRIPTION
));
209 OutDeviceDescriptor
->ScatterGather
= false;
210 OutDeviceDescriptor
->Master
= true;
211 OutDeviceDescriptor
->Dma32BitAddresses
= true;
212 OutDeviceDescriptor
->InterfaceType
= PCIBus
;
213 OutDeviceDescriptor
->MaximumLength
= MAXLEN_DMA_BUFFER
-2;
215 return STATUS_SUCCESS
;
219 STDMETHODIMP
CMiniportWaveCMI::GetDescription(PPCFILTER_DESCRIPTOR
*OutFilterDescriptor
)
222 //ASSERT(OutFilterDescriptor);
223 DBGPRINT(("CMiniportWaveCMI[%p]::GetDescription(%p)", this, OutFilterDescriptor
));
225 *OutFilterDescriptor
= &WaveMiniportFilterDescriptor
;
227 return STATUS_SUCCESS
;
230 NTSTATUS
CMiniportWaveCMI::loadChannelConfigFromRegistry()
233 PREGISTRYKEY DriverKey
;
234 PREGISTRYKEY SettingsKey
;
235 UNICODE_STRING KeyName
;
236 DWORD Value
, ResultLength
;
239 DBGPRINT(("CMiniportWaveCMI::loadChannelConfigFromRegistry()"));
241 if ((!CMIAdapter
) || (!(CMIAdapter
->getDeviceObject()))) {
242 return STATUS_UNSUCCESSFUL
;
245 NTSTATUS ntStatus
= PcNewRegistryKey(&DriverKey
, NULL
, DriverRegistryKey
, KEY_ALL_ACCESS
, CMIAdapter
->getDeviceObject(), NULL
, NULL
, 0, NULL
);
247 if(!NT_SUCCESS(ntStatus
)) {
248 DBGPRINT(("PcNewRegistryKey() failed"));
249 return STATUS_UNSUCCESSFUL
;
252 RtlInitUnicodeString(&KeyName
, L
"Settings");
254 ntStatus
= DriverKey
->NewSubKey(&SettingsKey
, NULL
, KEY_ALL_ACCESS
, &KeyName
, REG_OPTION_NON_VOLATILE
, NULL
);
255 if(!NT_SUCCESS(ntStatus
)) {
256 DBGPRINT(("DriverKey->NewSubKey() failed"));
257 return STATUS_UNSUCCESSFUL
;
260 KeyInfo
= ExAllocatePoolWithTag(PagedPool
, sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(DWORD
), 'gnaa');
262 RtlInitUnicodeString(&KeyName
, L
"ChannelCount");
263 ntStatus
= SettingsKey
->QueryValueKey(&KeyName
, KeyValuePartialInformation
, KeyInfo
, sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(DWORD
), &ResultLength
);
264 if (NT_SUCCESS (ntStatus
)) {
265 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)KeyInfo
;
266 if (PartialInfo
->DataLength
== sizeof(DWORD
)) {
267 requestedChannelCount
= (*(PLONG
)PartialInfo
->Data
);
270 requestedChannelCount
= 2;
273 RtlInitUnicodeString(&KeyName
, L
"ChannelMask");
274 ntStatus
= SettingsKey
->QueryValueKey(&KeyName
, KeyValuePartialInformation
, KeyInfo
, sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(DWORD
), &ResultLength
);
275 if (NT_SUCCESS (ntStatus
)) {
276 PKEY_VALUE_PARTIAL_INFORMATION PartialInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)KeyInfo
;
277 if (PartialInfo
->DataLength
== sizeof(DWORD
)) {
278 requestedChannelMask
= (*(PLONG
)PartialInfo
->Data
);
281 requestedChannelMask
= KSAUDIO_SPEAKER_STEREO
;
284 ExFreePoolWithTag(KeyInfo
,'gnaa');
286 SettingsKey
->Release();
287 DriverKey
->Release();
289 return STATUS_SUCCESS
;
292 NTSTATUS
CMiniportWaveCMI::storeChannelConfigToRegistry()
295 PREGISTRYKEY DriverKey
;
296 PREGISTRYKEY SettingsKey
;
297 UNICODE_STRING KeyName
;
299 DBGPRINT(("CMiniportWaveCMI::storeChannelConfigToRegistry()"));
301 if ((!CMIAdapter
) || (!(CMIAdapter
->getDeviceObject()))) {
302 return STATUS_UNSUCCESSFUL
;
305 NTSTATUS ntStatus
= PcNewRegistryKey(&DriverKey
, NULL
, DriverRegistryKey
, KEY_ALL_ACCESS
, CMIAdapter
->getDeviceObject(), NULL
, NULL
, 0, NULL
);
307 if(!NT_SUCCESS(ntStatus
)) {
308 DBGPRINT(("PcNewRegistryKey() failed"));
309 return STATUS_UNSUCCESSFUL
;
312 RtlInitUnicodeString(&KeyName
, L
"Settings");
314 ntStatus
= DriverKey
->NewSubKey(&SettingsKey
, NULL
, KEY_ALL_ACCESS
, &KeyName
, REG_OPTION_NON_VOLATILE
, NULL
);
315 if(!NT_SUCCESS(ntStatus
)) {
316 DBGPRINT(("DriverKey->NewSubKey() failed"));
317 return STATUS_UNSUCCESSFUL
;
320 Value
= requestedChannelCount
;
321 RtlInitUnicodeString(&KeyName
, L
"ChannelCount");
322 ntStatus
= SettingsKey
->SetValueKey(&KeyName
, REG_DWORD
, PVOID(&Value
), sizeof(DWORD
));
323 if (!NT_SUCCESS(ntStatus
)) {
324 DBGPRINT(("SetValueKey() failed"));
326 Value
= requestedChannelMask
;
327 RtlInitUnicodeString(&KeyName
, L
"ChannelMask");
328 ntStatus
= SettingsKey
->SetValueKey(&KeyName
, REG_DWORD
, PVOID(&Value
), sizeof(DWORD
));
329 if (!NT_SUCCESS(ntStatus
)) {
330 DBGPRINT(("SetValueKey() failed"));
333 SettingsKey
->Release();
334 DriverKey
->Release();
336 return STATUS_SUCCESS
;
340 STDMETHODIMP_(void) CMiniportWaveCMI::powerUp(void)
343 DBGPRINT(("CMiniportWaveCMI[%p]::powerUp()", this));
346 for (int i
=0;i
<3;i
++) {
347 if (isStreamRunning
[i
]) {
348 oldState
[i
] = stream
[i
]->state
;
349 stream
[i
]->SetState(KSSTATE_STOP
);
353 if (cm
->TopoMiniport
) {
354 cm
->TopoMiniport
->loadMixerSettingsFromMemory();
357 for (int i
=0;i
<3;i
++) {
358 if (isStreamRunning
[i
]) {
359 stream
[i
]->prepareStream();
360 stream
[i
]->SetState(KSSTATE_ACQUIRE
);
361 stream
[i
]->SetState(oldState
[i
]);
366 STDMETHODIMP_(void) CMiniportWaveCMI::powerDown(void)
369 DBGPRINT(("CMiniportWaveCMI[%p]::powerDown()", this));
371 if (cm
->TopoMiniport
) {
372 cm
->TopoMiniport
->storeMixerSettingsToMemory();
378 NTSTATUS
CMiniportWaveCMI::isFormatAllowed(UInt32 sampleRate
, BOOLEAN multiChan
, BOOLEAN AC3
)
381 //ASSERT(sampleRate);
382 DBGPRINT(("CMiniportWaveCMI[%p]::isFormatAllowed(%d, %d, %d)", this, sampleRate
, multiChan
, AC3
));
385 switch (sampleRate
) {
386 case 44100: if (cm
->formatMask
& FMT_441_MULTI_PCM
) return STATUS_SUCCESS
; break;
387 case 48000: if (cm
->formatMask
& FMT_480_MULTI_PCM
) return STATUS_SUCCESS
; break;
388 case 88200: if (cm
->formatMask
& FMT_882_MULTI_PCM
) return STATUS_SUCCESS
; break;
389 case 96000: if (cm
->formatMask
& FMT_960_MULTI_PCM
) return STATUS_SUCCESS
; break;
391 return STATUS_INVALID_PARAMETER
;
394 switch (sampleRate
) {
395 case 44100: if (cm
->formatMask
& FMT_441_DOLBY
) return STATUS_SUCCESS
; break;
396 case 48000: if (cm
->formatMask
& FMT_480_DOLBY
) return STATUS_SUCCESS
; break;
397 case 88200: if (cm
->formatMask
& FMT_882_DOLBY
) return STATUS_SUCCESS
; break;
398 case 96000: if (cm
->formatMask
& FMT_960_DOLBY
) return STATUS_SUCCESS
; break;
400 return STATUS_INVALID_PARAMETER
;
402 switch (sampleRate
) {
403 case 44100: if (cm
->formatMask
& FMT_441_PCM
) return STATUS_SUCCESS
; break;
404 case 48000: if (cm
->formatMask
& FMT_480_PCM
) return STATUS_SUCCESS
; break;
405 case 88200: if (cm
->formatMask
& FMT_882_PCM
) return STATUS_SUCCESS
; break;
406 case 96000: if (cm
->formatMask
& FMT_960_PCM
) return STATUS_SUCCESS
; break;
408 return STATUS_INVALID_PARAMETER
;
411 NTSTATUS
CMiniportWaveCMI::validateFormat(PKSDATAFORMAT format
, ULONG PinID
, BOOLEAN capture
)
415 DBGPRINT(("CMiniportWaveCMI[%p]::validateFormat(%p, %d, %d)", this, format
, PinID
, capture
));
417 PWAVEFORMATEX waveFormat
= PWAVEFORMATEX(format
+ 1);
418 DBGPRINT(("---channels: %d, resolution: %d, sample rate: %d, pin: %d, formatMask: %x", waveFormat
->nChannels
, waveFormat
->wBitsPerSample
, waveFormat
->nSamplesPerSec
, PinID
, cm
->formatMask
));
421 if ( ( format
->FormatSize
>= sizeof(KSDATAFORMAT_WAVEFORMATEX
))
422 && IsEqualGUIDAligned(format
->MajorFormat
,KSDATAFORMAT_TYPE_AUDIO
)
423 && IsEqualGUIDAligned(format
->Specifier
,KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
) ) {
424 switch (EXTRACT_WAVEFORMATEX_ID(&format
->SubFormat
)) {
425 case WAVE_FORMAT_PCM
:
426 if ((PinID
!= PIN_WAVE_RENDER_SINK
) && (PinID
!= PIN_WAVE_CAPTURE_SOURCE
) && (PinID
!= -1)) {
427 if ((PinID
== PIN_WAVE_AC3_RENDER_SINK
) && !IoIsWdmVersionAvailable(6,0)) {
428 return STATUS_INVALID_PARAMETER
;
432 if ( ((waveFormat
->wBitsPerSample
== 16) || (waveFormat
->wBitsPerSample
== 24))
433 && ((waveFormat
->nSamplesPerSec
== 44100) || (waveFormat
->nSamplesPerSec
== 48000) || (waveFormat
->nSamplesPerSec
== 88200) || (waveFormat
->nSamplesPerSec
== 96000))
434 && (waveFormat
->nChannels
== 2) ) {
435 if ((capture
) && (waveFormat
->nSamplesPerSec
> 48000) ) {
436 return STATUS_INVALID_PARAMETER
;
438 return isFormatAllowed(waveFormat
->nSamplesPerSec
, FALSE
, FALSE
);
440 if ( (waveFormat
->wBitsPerSample
== 16)
441 && ((waveFormat
->nChannels
>= 4) && (waveFormat
->nChannels
<= cm
->maxChannels
))
442 && ((waveFormat
->nSamplesPerSec
== 44100) || (waveFormat
->nSamplesPerSec
== 48000)) ) {
444 if ((PinID
== PIN_WAVE_RENDER_SINK
) || (PinID
== -1)) {
445 return isFormatAllowed(waveFormat
->nSamplesPerSec
, TRUE
, FALSE
);
448 return STATUS_INVALID_PARAMETER
;
452 case WAVE_FORMAT_DOLBY_AC3_SPDIF
:
453 if ((PinID
!= PIN_WAVE_AC3_RENDER_SINK
) && (PinID
!= -1)) {
454 return STATUS_INVALID_PARAMETER
;
456 if ( ((waveFormat
->wBitsPerSample
>= MIN_BITS_PER_SAMPLE_AC3
) && (waveFormat
->wBitsPerSample
<= MAX_BITS_PER_SAMPLE_AC3
))
457 && ((waveFormat
->nSamplesPerSec
>= MIN_SAMPLE_RATE_AC3
) && (waveFormat
->nSamplesPerSec
<= MAX_SAMPLE_RATE_AC3
))
458 && (waveFormat
->nChannels
== MAX_CHANNELS_AC3
) ) {
459 return isFormatAllowed(waveFormat
->nSamplesPerSec
, FALSE
, TRUE
);
465 return STATUS_INVALID_PARAMETER
;
468 // Tests a data range intersection
469 STDMETHODIMP
CMiniportWaveCMI::DataRangeIntersection(ULONG PinId
, PKSDATARANGE ClientDataRange
, PKSDATARANGE MyDataRange
, ULONG OutputBufferLength
, PVOID ResultantFormat
, PULONG ResultantFormatLength
)
472 DBGPRINT(("CMiniportWaveCMI[%p]::DataRangeIntersection(%d, %p, %p, %d, %p, %p)", this, PinId
, ClientDataRange
, MyDataRange
, OutputBufferLength
, ResultantFormat
, ResultantFormatLength
));
474 if (PinId
== PIN_WAVE_AC3_RENDER_SINK
) {
475 bool isAC3Pin
= true;
476 // Under Windows 2000 and XP, the client's DataRange should be AC3 only.
477 // The AC3 pin is the SPDIF pin in Windows Vista, so 2ch stereo is going to be allowed.
479 if (!IsEqualGUIDAligned(ClientDataRange
->MajorFormat
, KSDATAFORMAT_TYPE_AUDIO
)
480 && !IsEqualGUIDAligned(ClientDataRange
->MajorFormat
, KSDATAFORMAT_TYPE_WILDCARD
)) {
481 return STATUS_NO_MATCH
;
485 if (!IsEqualGUIDAligned(ClientDataRange
->SubFormat
, GUID_NULL
)//KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF) //HACK
486 && !IsEqualGUIDAligned(ClientDataRange
->SubFormat
, KSDATAFORMAT_SUBTYPE_WILDCARD
)) {
489 if (IoIsWdmVersionAvailable(0x06,0x00)) {
490 if (!IsEqualGUIDAligned(ClientDataRange
->SubFormat
, KSDATAFORMAT_SUBTYPE_PCM
)
491 && !IsEqualGUIDAligned(ClientDataRange
->SubFormat
, KSDATAFORMAT_SUBTYPE_WILDCARD
)) {
492 return STATUS_NO_MATCH
;
495 return STATUS_NO_MATCH
;
499 if (IsEqualGUIDAligned(ClientDataRange
->Specifier
, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
)
500 || IsEqualGUIDAligned(ClientDataRange
->Specifier
, KSDATAFORMAT_SPECIFIER_WILDCARD
)) {
501 *ResultantFormatLength
= sizeof(KSDATAFORMAT_WAVEFORMATEX
);
503 if (IsEqualGUIDAligned(ClientDataRange
->Specifier
, KSDATAFORMAT_SPECIFIER_DSOUND
)) {
504 *ResultantFormatLength
= sizeof(KSDATAFORMAT_DSOUND
);
506 return STATUS_NO_MATCH
;
509 // Validate return buffer size, if the request is only for the
510 // size of the resultant structure, return it now.
511 if (!OutputBufferLength
) {
512 *ResultantFormatLength
= sizeof(KSDATAFORMAT_WAVEFORMATEX
);
513 return STATUS_BUFFER_OVERFLOW
;
515 if (OutputBufferLength
< sizeof(KSDATAFORMAT_WAVEFORMATEX
)) {
516 return STATUS_BUFFER_TOO_SMALL
;
519 PKSDATAFORMAT_WAVEFORMATEX resultantFormatWFX
= (PKSDATAFORMAT_WAVEFORMATEX
) ResultantFormat
;
520 PWAVEFORMATEX pWaveFormatEx
;
522 // Return the best (only) available format.
523 resultantFormatWFX
->DataFormat
.FormatSize
= *ResultantFormatLength
;
524 resultantFormatWFX
->DataFormat
.Flags
= 0;
525 resultantFormatWFX
->DataFormat
.SampleSize
= 4; // must match nBlockAlign
526 resultantFormatWFX
->DataFormat
.Reserved
= 0;
528 resultantFormatWFX
->DataFormat
.MajorFormat
= KSDATAFORMAT_TYPE_AUDIO
;
529 INIT_WAVEFORMATEX_GUID(&resultantFormatWFX
->DataFormat
.SubFormat
, WAVE_FORMAT_DOLBY_AC3_SPDIF
);
531 // Extra space for the DSound specifier
532 if (IsEqualGUIDAligned(ClientDataRange
->Specifier
, KSDATAFORMAT_SPECIFIER_DSOUND
)) {
534 PKSDATAFORMAT_DSOUND resultantFormatDSound
= (PKSDATAFORMAT_DSOUND
)ResultantFormat
;
536 resultantFormatDSound
->DataFormat
.Specifier
= KSDATAFORMAT_SPECIFIER_DSOUND
;
538 // DSound format capabilities are not expressed
539 // this way in KS, so we express no capabilities.
540 resultantFormatDSound
->BufferDesc
.Flags
= 0 ;
541 resultantFormatDSound
->BufferDesc
.Control
= 0 ;
543 pWaveFormatEx
= &resultantFormatDSound
->BufferDesc
.WaveFormatEx
;
545 // WAVEFORMATEX or WILDCARD (WAVEFORMATEX)
546 resultantFormatWFX
->DataFormat
.Specifier
= KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
;
548 pWaveFormatEx
= (PWAVEFORMATEX
)((PKSDATAFORMAT
)resultantFormatWFX
+ 1);
551 pWaveFormatEx
->nChannels
= 2;
552 pWaveFormatEx
->wBitsPerSample
= 16; // SPDIF
553 pWaveFormatEx
->cbSize
= 0;
555 pWaveFormatEx
->wFormatTag
= WAVE_FORMAT_DOLBY_AC3_SPDIF
;
556 pWaveFormatEx
->nSamplesPerSec
= 48000;
558 pWaveFormatEx
->wFormatTag
= WAVE_FORMAT_PCM
;
559 pWaveFormatEx
->nSamplesPerSec
= min( ((PKSDATARANGE_AUDIO
)ClientDataRange
)->MaximumSampleFrequency
, MAX_SAMPLE_RATE
);
561 pWaveFormatEx
->nBlockAlign
= pWaveFormatEx
->nChannels
* pWaveFormatEx
->wBitsPerSample
/ 8;
562 pWaveFormatEx
->nAvgBytesPerSec
= pWaveFormatEx
->nSamplesPerSec
* pWaveFormatEx
->nBlockAlign
;
564 return STATUS_SUCCESS
;
566 if ((PinId
== PIN_WAVE_RENDER_SINK
) || (PinId
== PIN_WAVE_CAPTURE_SINK
)) {
568 if (!IsEqualGUIDAligned(ClientDataRange
->SubFormat
, KSDATAFORMAT_SUBTYPE_PCM
) &&
569 !IsEqualGUIDAligned(ClientDataRange
->SubFormat
, KSDATAFORMAT_SUBTYPE_WILDCARD
)) {
570 return STATUS_NO_MATCH
;
573 if (!IsEqualGUIDAligned(ClientDataRange
->MajorFormat
, KSDATAFORMAT_TYPE_AUDIO
) &&
574 !IsEqualGUIDAligned(ClientDataRange
->MajorFormat
, KSDATAFORMAT_TYPE_WILDCARD
)) {
575 return STATUS_NO_MATCH
;
578 if (IsEqualGUIDAligned(ClientDataRange
->Specifier
, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
) ||
579 IsEqualGUIDAligned(ClientDataRange
->Specifier
, KSDATAFORMAT_SPECIFIER_WILDCARD
)) {
580 *ResultantFormatLength
= sizeof(KSDATAFORMAT_WAVEFORMATEX
);
582 if (IsEqualGUIDAligned(ClientDataRange
->Specifier
, KSDATAFORMAT_SPECIFIER_DSOUND
)) {
583 *ResultantFormatLength
= sizeof(KSDATAFORMAT_DSOUND
);
585 return STATUS_NO_MATCH
;
589 ULONG sampleRate
= 0;
590 ULONG nMaxChannels
= min(((PKSDATARANGE_AUDIO
)ClientDataRange
)->MaximumChannels
, requestedChannelCount
);
593 if (IoIsWdmVersionAvailable(6,0) && (PinId
== PIN_WAVE_RENDER_SINK
)) {
594 nMaxChannels
= ((PKSDATARANGE_AUDIO
)ClientDataRange
)->MaximumChannels
;
596 if (nMaxChannels
& 0x01) {
600 return STATUS_NO_MATCH
;
603 if (isStreamRunning
[PCM_OUT_STREAM
]) {
604 sampleRate
= stream
[PCM_OUT_STREAM
]->currentSampleRate
;
606 if (isStreamRunning
[PCM_IN_STREAM
]) {
607 sampleRate
= stream
[PCM_IN_STREAM
]->currentSampleRate
;
609 if (sampleRate
== 0) {
610 if ((nMaxChannels
> 2) && (((PKSDATARANGE_AUDIO
)ClientDataRange
)->MaximumSampleFrequency
> MAX_SAMPLE_RATE_MULTI
)) {
611 sampleRate
= MAX_SAMPLE_RATE_MULTI
;
613 if ((nMaxChannels
== 2) && (((PKSDATARANGE_AUDIO
)ClientDataRange
)->MaximumSampleFrequency
> MAX_SAMPLE_RATE
)) {
614 sampleRate
= MAX_SAMPLE_RATE
;
616 sampleRate
= ((PKSDATARANGE_AUDIO
)ClientDataRange
)->MaximumSampleFrequency
;
620 if ((((PKSDATARANGE_AUDIO
)ClientDataRange
)->MaximumSampleFrequency
< sampleRate
)
621 || (((PKSDATARANGE_AUDIO
)ClientDataRange
)->MinimumSampleFrequency
> sampleRate
)) {
622 return STATUS_NO_MATCH
;
625 if (PinId
== PIN_WAVE_RENDER_SINK
) {
626 if (!OutputBufferLength
) {
627 *ResultantFormatLength
= sizeof(KSDATAFORMAT
) + sizeof(WAVEFORMATPCMEX
);
628 return STATUS_BUFFER_OVERFLOW
;
630 if (OutputBufferLength
< sizeof(KSDATAFORMAT
) + sizeof(WAVEFORMATPCMEX
)) {
631 return STATUS_BUFFER_TOO_SMALL
;
634 if (((PKSDATARANGE_AUDIO
)ClientDataRange
)->MaximumChannels
< 2) {
635 DBGPRINT(("[[DataRangeIntersection] mono format not supported"));
636 return STATUS_NO_MATCH
;
639 PWAVEFORMATPCMEX WaveFormat
= (PWAVEFORMATPCMEX
)((PKSDATAFORMAT
)ResultantFormat
+ 1);
640 if (IsEqualGUIDAligned(ClientDataRange
->Specifier
, KSDATAFORMAT_SPECIFIER_DSOUND
)) {
641 return STATUS_NOT_SUPPORTED
;
643 *(PKSDATAFORMAT
)ResultantFormat
= *MyDataRange
;
644 ((PKSDATAFORMAT
)ResultantFormat
)->FormatSize
= sizeof(KSDATAFORMAT
) + sizeof(WAVEFORMATPCMEX
);
647 WaveFormat
->Format
.wFormatTag
= WAVE_FORMAT_EXTENSIBLE
;
648 WaveFormat
->SubFormat
= KSDATAFORMAT_SUBTYPE_PCM
;
649 WaveFormat
->Format
.nChannels
= (WORD
)nMaxChannels
;
650 WaveFormat
->Format
.wBitsPerSample
= 16;
651 WaveFormat
->Format
.nBlockAlign
= (WaveFormat
->Format
.wBitsPerSample
>> 3) * WaveFormat
->Format
.nChannels
;
652 WaveFormat
->Format
.nAvgBytesPerSec
= WaveFormat
->Format
.nSamplesPerSec
* WaveFormat
->Format
.nBlockAlign
;
653 WaveFormat
->Format
.cbSize
= sizeof(WAVEFORMATEXTENSIBLE
) - sizeof(WAVEFORMATEX
);
654 WaveFormat
->Format
.nSamplesPerSec
= sampleRate
;
655 WaveFormat
->Samples
.wValidBitsPerSample
= WaveFormat
->Format
.wBitsPerSample
;
656 switch (nMaxChannels
) {
657 case 8: WaveFormat
->dwChannelMask
= KSAUDIO_SPEAKER_7POINT1
; break;
658 case 6: WaveFormat
->dwChannelMask
= KSAUDIO_SPEAKER_5POINT1
; break;
659 case 4: WaveFormat
->dwChannelMask
= KSAUDIO_SPEAKER_QUAD
; break;
660 case 2: WaveFormat
->dwChannelMask
= KSAUDIO_SPEAKER_STEREO
; break;
662 if (nMaxChannels
== requestedChannelCount
) {
663 WaveFormat
->dwChannelMask
= requestedChannelMask
;
665 ((PKSDATAFORMAT
)ResultantFormat
)->SampleSize
= WaveFormat
->Format
.nBlockAlign
;
667 *ResultantFormatLength
= sizeof(KSDATAFORMAT
) + sizeof(WAVEFORMATPCMEX
);
668 DBGPRINT(("[DataRangeIntersection] MultiChannel Renderer: SampleRate: %d, ClientDataRange->MaxChans: %d, Channels: %d, BitPerSample: %d, BlockAlign: %d, AvgBytesPerSec: %d, ChannelMask: %08X", WaveFormat
->Format
.nSamplesPerSec
, ((PKSDATARANGE_AUDIO
)ClientDataRange
)->MaximumChannels
, WaveFormat
->Format
.nChannels
, WaveFormat
->Format
.wBitsPerSample
, WaveFormat
->Format
.nBlockAlign
, WaveFormat
->Format
.nAvgBytesPerSec
, WaveFormat
->dwChannelMask
));
670 if (PinId
== PIN_WAVE_CAPTURE_SINK
) {
671 PKSDATAFORMAT_WAVEFORMATEX resultantFormatWFX
;
672 PWAVEFORMATEX pWaveFormatEx
;
674 if (!OutputBufferLength
) {
675 *ResultantFormatLength
= sizeof(KSDATAFORMAT_WAVEFORMATEX
);
676 return STATUS_BUFFER_OVERFLOW
;
678 if (OutputBufferLength
< sizeof(KSDATAFORMAT_WAVEFORMATEX
)) {
679 return STATUS_BUFFER_TOO_SMALL
;
682 if (nMaxChannels
> 2) {
686 resultantFormatWFX
= (PKSDATAFORMAT_WAVEFORMATEX
) ResultantFormat
;
687 resultantFormatWFX
->DataFormat
.FormatSize
= *ResultantFormatLength
;
688 resultantFormatWFX
->DataFormat
.Flags
= 0;
689 resultantFormatWFX
->DataFormat
.SampleSize
= 4;
690 resultantFormatWFX
->DataFormat
.Reserved
= 0;
691 resultantFormatWFX
->DataFormat
.MajorFormat
= KSDATAFORMAT_TYPE_AUDIO
;
692 INIT_WAVEFORMATEX_GUID(&resultantFormatWFX
->DataFormat
.SubFormat
, WAVE_FORMAT_PCM
);
694 if (IsEqualGUIDAligned(ClientDataRange
->Specifier
, KSDATAFORMAT_SPECIFIER_DSOUND
)) {
695 PKSDATAFORMAT_DSOUND resultantFormatDSound
;
696 resultantFormatDSound
= (PKSDATAFORMAT_DSOUND
)ResultantFormat
;
697 resultantFormatDSound
->DataFormat
.Specifier
= KSDATAFORMAT_SPECIFIER_DSOUND
;
698 resultantFormatDSound
->BufferDesc
.Flags
= 0 ;
699 resultantFormatDSound
->BufferDesc
.Control
= 0 ;
700 pWaveFormatEx
= &resultantFormatDSound
->BufferDesc
.WaveFormatEx
;
702 resultantFormatWFX
->DataFormat
.Specifier
= KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
;
703 pWaveFormatEx
= (PWAVEFORMATEX
)((PKSDATAFORMAT
)resultantFormatWFX
+ 1);
705 pWaveFormatEx
->wFormatTag
= WAVE_FORMAT_PCM
;
706 pWaveFormatEx
->nChannels
= nMaxChannels
;
707 pWaveFormatEx
->nSamplesPerSec
= sampleRate
;
708 pWaveFormatEx
->wBitsPerSample
= 16;
709 pWaveFormatEx
->cbSize
= 0;
710 pWaveFormatEx
->nBlockAlign
= 4;
711 pWaveFormatEx
->nAvgBytesPerSec
= 192000;
713 return STATUS_SUCCESS
;
715 return STATUS_NO_MATCH
;
718 //from IMiniportWaveCyclic::NewStream()
720 STDMETHODIMP
CMiniportWaveCMI::NewStream(PMINIPORTWAVERTSTREAM
*OutStream
, PPORTWAVERTSTREAM OuterUnknown
, ULONG PinID
, BOOLEAN Capture
, PKSDATAFORMAT DataFormat
)
722 STDMETHODIMP
CMiniportWaveCMI::NewStream(PMINIPORTWAVECYCLICSTREAM
*OutStream
, PUNKNOWN OuterUnknown
, POOL_TYPE PoolType
, ULONG PinID
, BOOLEAN Capture
, PKSDATAFORMAT DataFormat
, PDMACHANNEL
* OutDmaChannel
, PSERVICEGROUP
* OutServiceGroup
)
727 //ASSERT(DataFormat);
729 DBGPRINT(("CMiniportWaveCMI[%p]::NewStream(%p, %p, %d, %d, %p)", this, OutStream
, OuterUnknown
, PinID
, Capture
, DataFormat
));
731 //ASSERT(OutDmaChannel);
732 //ASSERT(OutServiceGroup);
733 DBGPRINT(("CMiniportWaveCMI[%p]::NewStream(%p, %p, %p, %d, %d, %p, %p, %p)", this, OutStream
, OuterUnknown
, PoolType
, PinID
, Capture
, DataFormat
, OutDmaChannel
, OutServiceGroup
));
736 NTSTATUS ntStatus
= STATUS_SUCCESS
;
737 PWAVEFORMATEX waveFormat
= PWAVEFORMATEX(DataFormat
+ 1);
738 UInt32 streamIndex
= PCM_OUT_STREAM
;
740 ntStatus
= validateFormat(DataFormat
, PinID
, Capture
);
741 if (!NT_SUCCESS(ntStatus
)) {
742 DBGPRINT(("invalid stream format"));
743 return STATUS_UNSUCCESSFUL
;
746 CMIAdapter
->setUInt8Bit(REG_MIXER1
, EN_SPDI2DAC
);
749 streamIndex
= PCM_IN_STREAM
;
750 } else if (WAVE_FORMAT_DOLBY_AC3_SPDIF
== EXTRACT_WAVEFORMATEX_ID(&DataFormat
->SubFormat
)) {
751 streamIndex
= AC3_OUT_STREAM
;
754 // make sure the hardware is not already in use
755 if (isStreamRunning
[streamIndex
]) {
756 DBGPRINT(("Stream %d running, exiting...", streamIndex
));
757 return STATUS_UNSUCCESSFUL
;
759 if ((streamIndex
== AC3_OUT_STREAM
) && isStreamRunning
[PCM_OUT_STREAM
]) {
760 stream
[PCM_OUT_STREAM
]->SetState(KSSTATE_STOP_AC3
);
762 if ((streamIndex
== PCM_OUT_STREAM
) && isStreamRunning
[AC3_OUT_STREAM
]) {
763 return STATUS_UNSUCCESSFUL
;
766 DBGPRINT(("---StreamNo: %d, Bits: %d, Sample Rate: %d, Channels: %d, AC3: %d", streamIndex
,
767 waveFormat
->wBitsPerSample
, waveFormat
->nSamplesPerSec
, waveFormat
->nChannels
,
768 (WAVE_FORMAT_DOLBY_AC3_SPDIF
== EXTRACT_WAVEFORMATEX_ID(&DataFormat
->SubFormat
))));
770 // the DAC and ADC can only run at the same sample rate simultaneously
771 if ((streamIndex
== PCM_IN_STREAM
) && isStreamRunning
[PCM_OUT_STREAM
]) {
772 if (waveFormat
->nSamplesPerSec
!= stream
[PCM_OUT_STREAM
]->currentSampleRate
) {
773 return STATUS_UNSUCCESSFUL
;
776 if ((streamIndex
== PCM_OUT_STREAM
) && isStreamRunning
[PCM_IN_STREAM
]) {
777 if (waveFormat
->nSamplesPerSec
!= stream
[PCM_IN_STREAM
]->currentSampleRate
) {
778 return STATUS_UNSUCCESSFUL
;
782 // instantiate a stream
784 ntStatus
= CreateMiniportWaveStreamCMI(&stream
[streamIndex
], OuterUnknown
, NonPagedPool
);
786 ntStatus
= CreateMiniportWaveStreamCMI(&stream
[streamIndex
], OuterUnknown
, PoolType
);
788 if (!NT_SUCCESS (ntStatus
)) {
789 DBGPRINT(("Failed to create stream"));
795 ntStatus
= stream
[streamIndex
]->Init(this, streamIndex
, Capture
, DataFormat
, OuterUnknown
);
797 ntStatus
= stream
[streamIndex
]->Init(this, streamIndex
, Capture
, DataFormat
, DMAChannel
[streamIndex
], OutServiceGroup
);
799 if (!NT_SUCCESS(ntStatus
)) {
800 DBGPRINT(("Failed to init stream"));
801 stream
[streamIndex
]->Release();
802 stream
[streamIndex
] = NULL
;
805 *OutServiceGroup
= NULL
;
806 *OutDmaChannel
= NULL
;
812 //this has been referenced in CreateMiniportWaveStreamCMI() already
813 *OutStream
= (PMINIPORTWAVERTSTREAM
)stream
[streamIndex
];
815 *OutDmaChannel
= DMAChannel
[streamIndex
];
816 DMAChannel
[streamIndex
]->AddRef();
817 *OutStream
= (PMINIPORTWAVECYCLICSTREAM
)stream
[streamIndex
];
823 NTSTATUS NTAPI
PropertyHandler_ChannelConfig(PPCPROPERTY_REQUEST PropertyRequest
)
826 //ASSERT(PropertyRequest);
827 DBGPRINT(("[PropertyHandler_ChannelConfig]"));
830 CMiniportWaveCMI
*that
= (CMiniportWaveCMI
*) ((PMINIPORTWAVERT
)PropertyRequest
->MajorTarget
);
832 CMiniportWaveCMI
*that
= (CMiniportWaveCMI
*) ((PMINIPORTWAVECYCLIC
)PropertyRequest
->MajorTarget
);
835 if (PropertyRequest
->Node
== KSNODE_WAVE_DAC
) {
837 if (PropertyRequest
->ValueSize
== 0) {
838 PropertyRequest
->ValueSize
= sizeof(LONG
);
839 return STATUS_BUFFER_OVERFLOW
;
840 } else if (PropertyRequest
->ValueSize
< sizeof (LONG
)) {
841 PropertyRequest
->ValueSize
= 0;
842 return STATUS_BUFFER_TOO_SMALL
;
845 if (PropertyRequest
->Verb
& KSPROPERTY_TYPE_GET
) {
846 *(PLONG
)PropertyRequest
->Value
= that
->requestedChannelMask
;
847 PropertyRequest
->ValueSize
= sizeof(ULONG
);
848 return STATUS_SUCCESS
;
849 } else if (PropertyRequest
->Verb
& KSPROPERTY_TYPE_SET
) {
850 if (*(PLONG
)PropertyRequest
->Value
== KSAUDIO_SPEAKER_7POINT1
) {
851 that
->requestedChannelMask
= *(PLONG
)PropertyRequest
->Value
;
852 that
->requestedChannelCount
= 8;
853 return STATUS_SUCCESS
;
855 if (*(PLONG
)PropertyRequest
->Value
== KSAUDIO_SPEAKER_5POINT1
) {
856 that
->requestedChannelMask
= *(PLONG
)PropertyRequest
->Value
;
857 that
->requestedChannelCount
= 6;
858 return STATUS_SUCCESS
;
860 if ((*(PLONG
)PropertyRequest
->Value
== KSAUDIO_SPEAKER_QUAD
) || (*(PLONG
)PropertyRequest
->Value
== KSAUDIO_SPEAKER_SURROUND
)) {
861 that
->requestedChannelMask
= *(PLONG
)PropertyRequest
->Value
;
862 that
->requestedChannelCount
= 4;
863 return STATUS_SUCCESS
;
865 if (*(PLONG
)PropertyRequest
->Value
== KSAUDIO_SPEAKER_STEREO
) {
866 that
->requestedChannelMask
= *(PLONG
)PropertyRequest
->Value
;
867 that
->requestedChannelCount
= 2;
868 return STATUS_SUCCESS
;
870 } else if (PropertyRequest
->Verb
& KSPROPERTY_TYPE_BASICSUPPORT
) {
871 PULONG AccessFlags
= PULONG(PropertyRequest
->Value
);
872 *AccessFlags
= KSPROPERTY_TYPE_BASICSUPPORT
| KSPROPERTY_TYPE_GET
| KSPROPERTY_TYPE_SET
;
873 PropertyRequest
->ValueSize
= sizeof(ULONG
);
874 return STATUS_SUCCESS
;
877 return STATUS_INVALID_PARAMETER
;
880 ///////////////////////////
882 NTSTATUS
CreateMiniportWaveStreamCMI(CMiniportWaveStreamCMI
**MiniportWaveStreamCMI
, PUNKNOWN pUnknownOuter
, POOL_TYPE PoolType
)
885 DBGPRINT(("CreateMiniportWaveStreamCMI"));
888 *MiniportWaveStreamCMI
= new (PoolType
, 'gnaa') CMiniportWaveStreamCMI(NULL
);
890 *MiniportWaveStreamCMI
= new (PoolType
, 'gnaa') CMiniportWaveStreamCMI(pUnknownOuter
);
892 if (*MiniportWaveStreamCMI
) {
893 (*MiniportWaveStreamCMI
)->AddRef();
894 return STATUS_SUCCESS
;
897 return STATUS_INSUFFICIENT_RESOURCES
;
900 NTSTATUS
CMiniportWaveStreamCMI::prepareStream()
903 DBGPRINT(("CMiniportWaveStreamCMI[%p]::prepareStream()", this));
904 DBGPRINT(("---streamIndex: %d, channelNumber: %d", streamIndex
, channelNumber
));
910 if (state
== KSSTATE_RUN
) {
911 return STATUS_INVALID_DEVICE_REQUEST
;
914 if (!(Miniport
->cm
)) {
915 DBGPRINT(("Miniport not set"));
916 return STATUS_INVALID_DEVICE_REQUEST
;
919 enableSPDIF
= ((currentSampleRate
== 44100 || currentSampleRate
== 48000 || currentSampleRate
== 88200 || currentSampleRate
== 96000) &&
920 ((currentResolution
== 16) || (currentResolution
== 24)) && (currentChannelCount
== 2)) &&
921 (Miniport
->cm
->enableSPDIFOut
);
923 ntStatus
= setupSPDIFPlayback(enableSPDIF
);
924 if (!NT_SUCCESS(ntStatus
)) {
928 if (!isCaptureStream
) {
929 ntStatus
= setDACChannels();
930 if (!NT_SUCCESS(ntStatus
)) {
935 KeWaitForSingleObject(&Miniport
->mutex
, Executive
, KernelMode
, false, NULL
);
937 val
= channelNumber
? ADC_CH1
: ADC_CH0
;
938 if (isCaptureStream
) {
939 Miniport
->cm
->regFUNCTRL0
|= val
; // 1->Recording
941 Miniport
->cm
->regFUNCTRL0
&= ~val
; // 0->Playback
943 Miniport
->CMIAdapter
->writeUInt32(REG_FUNCTRL0
, Miniport
->cm
->regFUNCTRL0
);
945 //set sampling frequency
946 val
= Miniport
->CMIAdapter
->readUInt32(REG_FUNCTRL1
);
947 if ((currentSampleRate
== 88200) || (currentSampleRate
== 44100)) {
949 val
&= ~SFC_CH1_MASK
;
952 val
&= ~SFC_CH0_MASK
;
955 } else if ((currentSampleRate
== 96000) || (currentSampleRate
== 48000)) {
957 val
&= ~SFC_CH1_MASK
;
960 val
&= ~SFC_CH0_MASK
;
964 KeReleaseMutex(&Miniport
->mutex
, FALSE
);
965 return STATUS_INVALID_DEVICE_REQUEST
;
967 Miniport
->CMIAdapter
->writeUInt32(REG_FUNCTRL1
, val
);
970 val
= Miniport
->CMIAdapter
->readUInt32(REG_CHFORMAT
);
976 Miniport
->CMIAdapter
->writeUInt32(REG_CHFORMAT
, val
);
978 KeReleaseMutex(&Miniport
->mutex
, false);
980 return STATUS_SUCCESS
;
983 NTSTATUS
CMiniportWaveStreamCMI::setDACChannels()
986 DBGPRINT(("CMiniportWaveStreamCMI[%p]::setDACChannels()", this));
987 NTSTATUS ntStatus
= STATUS_SUCCESS
;
989 if (currentChannelCount
> 2) {
990 if (Miniport
->cm
->maxChannels
< currentChannelCount
) {
991 return STATUS_INVALID_DEVICE_REQUEST
;
993 if ((currentResolution
!= 16) || (currentChannelCount
< 2)) {
994 return STATUS_INVALID_DEVICE_REQUEST
;
997 return STATUS_INVALID_DEVICE_REQUEST
;
999 KeWaitForSingleObject(&Miniport
->mutex
, Executive
, KernelMode
, FALSE
, NULL
);
1000 Miniport
->CMIAdapter
->setUInt32Bit(REG_LEGACY
, DWORD_MAPPING
);
1001 Miniport
->CMIAdapter
->setUInt32Bit(REG_MISCCTRL
, XCHG_DAC
);
1003 switch (currentChannelCount
) {
1005 Miniport
->CMIAdapter
->setUInt32Bit(REG_CHFORMAT
, EN_4CH_CH1
);
1006 Miniport
->CMIAdapter
->clearUInt32Bit(REG_CHFORMAT
, EN_5CH_CH1
);
1007 Miniport
->CMIAdapter
->clearUInt32Bit(REG_LEGACY
, EN_6CH_CH1
);
1008 Miniport
->CMIAdapter
->clearUInt32Bit(REG_MISCCTRL
, EN_CENTER
);
1011 Miniport
->CMIAdapter
->clearUInt32Bit(REG_CHFORMAT
, EN_4CH_CH1
);
1012 Miniport
->CMIAdapter
->setUInt32Bit(REG_CHFORMAT
, EN_5CH_CH1
);
1013 Miniport
->CMIAdapter
->setUInt32Bit(REG_LEGACY
, EN_6CH_CH1
);
1014 Miniport
->CMIAdapter
->setUInt32Bit(REG_MISCCTRL
, EN_CENTER
);
1017 if (Miniport
->cm
->chipVersion
== 68) {
1018 Miniport
->CMIAdapter
->clearUInt32Bit(REG_CHFORMAT
, EN_4CH_CH1
);
1019 Miniport
->CMIAdapter
->setUInt32Bit(REG_CHFORMAT
, EN_5CH_CH1
);
1020 Miniport
->CMIAdapter
->setUInt32Bit(REG_LEGACY
, EN_6CH_CH1
);
1021 Miniport
->CMIAdapter
->setUInt32Bit(REG_MISCCTRL
, EN_CENTER
);
1022 Miniport
->CMIAdapter
->setUInt32Bit(REG_MISCCTRL2
, EN_8CH_CH1
);
1025 ntStatus
= STATUS_INVALID_DEVICE_REQUEST
;
1028 ntStatus
= STATUS_INVALID_DEVICE_REQUEST
;
1030 KeReleaseMutex(&Miniport
->mutex
, FALSE
);
1032 if (Miniport
->cm
->canMultiChannel
) {
1033 KeWaitForSingleObject(&Miniport
->mutex
, Executive
, KernelMode
, FALSE
, NULL
);
1034 Miniport
->CMIAdapter
->clearUInt32Bit(REG_CHFORMAT
, EN_5CH_CH1
| EN_4CH_CH1
);
1035 Miniport
->CMIAdapter
->clearUInt32Bit(REG_LEGACY
, EN_6CH_CH1
| DWORD_MAPPING
);
1036 Miniport
->CMIAdapter
->clearUInt32Bit(REG_MISCCTRL
, EN_CENTER
);
1037 Miniport
->CMIAdapter
->clearUInt32Bit(REG_MISCCTRL
, XCHG_DAC
);
1038 if (Miniport
->cm
->chipVersion
== 68) {
1039 Miniport
->CMIAdapter
->clearUInt32Bit(REG_MISCCTRL2
, EN_8CH_CH1
);
1041 KeReleaseMutex(&Miniport
->mutex
, FALSE
);
1047 NTSTATUS
CMiniportWaveStreamCMI::setupSPDIFPlayback(bool enableSPDIF
)
1050 DBGPRINT(("CMiniportWaveStreamCMI[%p]::setupSPDIFPlayback(%d)", this, enableSPDIF
));
1054 KeWaitForSingleObject(&Miniport
->mutex
, Executive
, KernelMode
, false, NULL
);
1057 Miniport
->CMIAdapter
->setUInt32Bit(REG_LEGACY
, EN_SPDIF_OUT
);
1058 Miniport
->CMIAdapter
->setUInt32Bit(REG_FUNCTRL1
, SPDO2DAC
);
1059 #if OUT_CHANNEL == 0
1060 Miniport
->CMIAdapter
->setUInt32Bit(REG_FUNCTRL1
, SPDF_0
);
1062 Miniport
->CMIAdapter
->setUInt32Bit(REG_FUNCTRL1
, SPDF_1
);
1066 if ( (currentSampleRate
== 48000) || (currentSampleRate
== 96000) ) {
1067 Miniport
->CMIAdapter
->setUInt32Bit(REG_MISCCTRL
, EN_SPDIF_48
);
1069 Miniport
->CMIAdapter
->clearUInt32Bit(REG_MISCCTRL
, EN_SPDIF_48
);
1072 if (currentSampleRate
== 96000) {
1073 #if OUT_CHANNEL == 0
1074 Miniport
->CMIAdapter
->setUInt32Bit(REG_CHFORMAT
, SPD96_CH0
);
1076 Miniport
->CMIAdapter
->setUInt32Bit(REG_CHFORMAT
, SPD96_CH1
);
1078 Miniport
->CMIAdapter
->setUInt32Bit(REG_CHFORMAT
, DBLSPDS
);
1079 } else if (currentSampleRate
== 88200) {
1080 #if OUT_CHANNEL == 0
1081 Miniport
->CMIAdapter
->setUInt32Bit(REG_CHFORMAT
, SPD88_CH0
);
1083 Miniport
->CMIAdapter
->setUInt32Bit(REG_CHFORMAT
, SPD88_CH1
);
1085 Miniport
->CMIAdapter
->setUInt32Bit(REG_CHFORMAT
, DBLSPDS
);
1087 #if OUT_CHANNEL == 0
1088 Miniport
->CMIAdapter
->clearUInt32Bit(REG_CHFORMAT
, SPD88_CH0
| SPD96_CH0
);
1090 Miniport
->CMIAdapter
->clearUInt32Bit(REG_CHFORMAT
, SPD88_CH1
| SPD96_CH1
);
1092 Miniport
->CMIAdapter
->clearUInt32Bit(REG_CHFORMAT
, DBLSPDS
);
1096 Miniport
->CMIAdapter
->clearUInt32Bit(REG_LEGACY
, EN_SPDIF_OUT
);
1097 Miniport
->CMIAdapter
->clearUInt32Bit(REG_FUNCTRL1
, SPDO2DAC
);
1098 #if OUT_CHANNEL == 0
1099 Miniport
->CMIAdapter
->clearUInt32Bit(REG_FUNCTRL1
, SPDF_0
);
1101 Miniport
->CMIAdapter
->clearUInt32Bit(REG_FUNCTRL1
, SPDF_1
);
1103 #if OUT_CHANNEL == 0
1104 Miniport
->CMIAdapter
->clearUInt32Bit(REG_CHFORMAT
, SPD88_CH0
| SPD96_CH0
);
1106 Miniport
->CMIAdapter
->clearUInt32Bit(REG_CHFORMAT
, SPD88_CH1
| SPD96_CH1
);
1108 Miniport
->CMIAdapter
->clearUInt32Bit(REG_CHFORMAT
, DBLSPDS
);
1112 KeReleaseMutex(&Miniport
->mutex
, false);
1113 return STATUS_SUCCESS
;
1116 NTSTATUS
CMiniportWaveStreamCMI::setupAC3Passthru()
1119 DBGPRINT(("CMiniportWaveStreamCMI[%p]::setupAC3Passthru()"));
1121 if (enableAC3Passthru
) {
1122 Miniport
->CMIAdapter
->writeUInt8(REG_MIXER1
, Miniport
->CMIAdapter
->readUInt8(REG_MIXER1
) | MUTE_WAVE
);
1124 Miniport
->CMIAdapter
->setUInt32Bit(REG_CHFORMAT
, EN_SPDO_AC3_1
);
1125 Miniport
->CMIAdapter
->setUInt32Bit(REG_MISCCTRL
, EN_SPDO_AC3_2
);
1127 if (Miniport
->cm
->canAC3HW
) {
1128 Miniport
->CMIAdapter
->setUInt32Bit(REG_CHFORMAT
, EN_SPDO_AC3_3
);
1129 Miniport
->CMIAdapter
->clearUInt32Bit(REG_MISCCTRL
, SPD32SEL
);
1130 if (Miniport
->cm
->chipVersion
>= 39) {
1131 Miniport
->CMIAdapter
->clearUInt8Bit(REG_MIXER1
, EN_SPDI2DAC
);
1134 Miniport
->CMIAdapter
->setUInt32Bit(REG_MISCCTRL
, SPD32SEL
);
1135 if (Miniport
->cm
->chipVersion
== 33) {
1136 if (currentSampleRate
>= 48000) {
1137 #if OUT_CHANNEL == 0
1138 Miniport
->CMIAdapter
->setUInt32Bit(REG_CHFORMAT
, SPD96_CH0
);
1140 Miniport
->CMIAdapter
->setUInt32Bit(REG_CHFORMAT
, SPD96_CH1
);
1143 #if OUT_CHANNEL == 0
1144 Miniport
->CMIAdapter
->clearUInt32Bit(REG_CHFORMAT
, SPD96_CH0
);
1146 Miniport
->CMIAdapter
->clearUInt32Bit(REG_CHFORMAT
, SPD96_CH1
);
1152 Miniport
->CMIAdapter
->setUInt8Bit(REG_MIXER1
, EN_SPDI2DAC
);
1154 Miniport
->CMIAdapter
->clearUInt32Bit(REG_CHFORMAT
, EN_SPDO_AC3_1
);
1155 Miniport
->CMIAdapter
->clearUInt32Bit(REG_MISCCTRL
, EN_SPDO_AC3_2
);
1157 if (Miniport
->cm
->canAC3HW
) {
1158 Miniport
->CMIAdapter
->clearUInt32Bit(REG_CHFORMAT
, EN_SPDO_AC3_3
);
1159 if (currentResolution
> 16) {
1160 Miniport
->CMIAdapter
->setUInt32Bit(REG_MISCCTRL
, SPD32SEL
);
1161 Miniport
->CMIAdapter
->setUInt32Bit(REG_CHFORMAT
, SPD24SEL
);
1163 Miniport
->CMIAdapter
->clearUInt32Bit(REG_MISCCTRL
, SPD32SEL
);
1164 Miniport
->CMIAdapter
->clearUInt32Bit(REG_CHFORMAT
, SPD24SEL
);
1167 Miniport
->CMIAdapter
->clearUInt32Bit(REG_MISCCTRL
, SPD32SEL
);
1168 #if OUT_CHANNEL == 0
1169 Miniport
->CMIAdapter
->clearUInt32Bit(REG_CHFORMAT
, SPD96_CH0
);
1171 Miniport
->CMIAdapter
->clearUInt32Bit(REG_CHFORMAT
, SPD96_CH1
);
1175 return STATUS_SUCCESS
;
1178 CMiniportWaveStreamCMI::~CMiniportWaveStreamCMI(void)
1182 DBGPRINT(("CMiniportWaveStreamCMI[%p]::~CMiniportWaveStreamCMI", this));
1191 DMAChannel
->Release();
1196 ServiceGroup
->Release();
1197 ServiceGroup
= NULL
;
1201 Miniport
->isStreamRunning
[streamIndex
] = false;
1203 if ((streamIndex
== AC3_OUT_STREAM
) && Miniport
->isStreamRunning
[PCM_OUT_STREAM
]) {
1204 KSSTATE temp
= Miniport
->stream
[PCM_OUT_STREAM
]->state
;
1205 Miniport
->stream
[PCM_OUT_STREAM
]->state
= KSSTATE_STOP
;
1206 Miniport
->stream
[PCM_OUT_STREAM
]->prepareStream();
1207 Miniport
->stream
[PCM_OUT_STREAM
]->SetState(KSSTATE_ACQUIRE
);
1208 Miniport
->stream
[PCM_OUT_STREAM
]->state
= temp
;
1209 Miniport
->stream
[PCM_OUT_STREAM
]->SetState(KSSTATE_RUN_AC3
);
1213 Miniport
->Release();
1218 STDMETHODIMP
CMiniportWaveStreamCMI::QueryInterface(REFIID Interface
, PVOID
*Object
)
1222 DBGPRINT(("CMiniportWaveStreamCMI[%p]::NonDelegatingQueryInterface(%p, %p)", this, Interface
, Object
));
1224 if (IsEqualGUIDAligned(Interface
,IID_IUnknown
)) {
1225 *Object
= PVOID(PUNKNOWN(PMINIPORTWAVECYCLICSTREAM(this)));
1227 } else if (IsEqualGUIDAligned(Interface
,IID_IMiniportWaveRTStream
)) {
1228 *Object
= PVOID(PMINIPORTWAVERTSTREAM(this));
1230 } else if (IsEqualGUIDAligned(Interface
,IID_IMiniportWaveCyclicStream
)) {
1231 *Object
= PVOID(PMINIPORTWAVECYCLICSTREAM(this));
1233 } else if (IsEqualGUIDAligned (Interface
, IID_IDrmAudioStream
)) {
1234 *Object
= (PVOID
)(PDRMAUDIOSTREAM(this));
1240 PUNKNOWN(*Object
)->AddRef();
1241 return STATUS_SUCCESS
;
1244 return STATUS_INVALID_PARAMETER
;
1248 NTSTATUS
CMiniportWaveStreamCMI::Init(CMiniportWaveCMI
* Miniport_
, UInt32 streamIndex_
, bool isCaptureStream_
, PKSDATAFORMAT DataFormat
, PPORTWAVERTSTREAM Port_
)
1250 NTSTATUS
CMiniportWaveStreamCMI::Init(CMiniportWaveCMI
* Miniport_
, UInt32 streamIndex_
, bool isCaptureStream_
, PKSDATAFORMAT DataFormat
, PDMACHANNEL DMAChannel_
, PSERVICEGROUP
* OutServiceGroup
)
1254 //ASSERT(Miniport_);
1255 //ASSERT(DataFormat);
1261 DBGPRINT(("CMiniportWaveStreamCMI[%p]::Init(%p, %d, %d, %p, %p)", this, Miniport_
, streamIndex_
, isCaptureStream_
, DataFormat
, Port_
));
1265 DBGPRINT(("CMiniportWaveStreamCMI[%p]::Init(%p, %d, %d, %p, %p, %p)", this, Miniport_
, streamIndex_
, isCaptureStream_
, DataFormat
, DMAChannel_
, OutServiceGroup
));
1266 DMAChannel
= DMAChannel_
;
1267 DMAChannel
->AddRef();
1270 Miniport
= Miniport_
;
1273 streamIndex
= streamIndex_
;
1274 isCaptureStream
= isCaptureStream_
;
1275 state
= KSSTATE_STOP
;
1277 if ( (streamIndex
== PCM_OUT_STREAM
) || (streamIndex
== AC3_OUT_STREAM
) ) {
1278 channelNumber
= OUT_CHANNEL
;
1280 channelNumber
= IN_CHANNEL
;
1284 ntStatus
= PcNewServiceGroup(&ServiceGroup
,NULL
);
1285 if (!NT_SUCCESS(ntStatus
)) {
1286 DBGPRINT(("PcNewServiceGroup() or NewMasterDmaChannel() failed"));
1289 *OutServiceGroup
= ServiceGroup
;
1290 ServiceGroup
->AddRef();
1293 ntStatus
= SetFormat(DataFormat
);
1294 if (!NT_SUCCESS(ntStatus
)) {
1295 DBGPRINT(("SetFormat() failed"));
1299 Miniport
->isStreamRunning
[streamIndex
] = true;
1304 NTSTATUS
CMiniportWaveStreamCMI::SetFormat(PKSDATAFORMAT Format
)
1307 DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetFormat(%p)", this, Format
));
1308 PWAVEFORMATEX waveFormat
= PWAVEFORMATEX(Format
+ 1);
1309 NTSTATUS ntStatus
= Miniport
->validateFormat(Format
, -1, isCaptureStream
);
1310 if (!NT_SUCCESS(ntStatus
)) {
1313 // the DAC and ADC can only run at the same sample rate simultaneously
1314 if ((streamIndex
== PCM_IN_STREAM
) && Miniport
->isStreamRunning
[PCM_OUT_STREAM
]) {
1315 if (waveFormat
->nSamplesPerSec
!= Miniport
->stream
[PCM_OUT_STREAM
]->currentSampleRate
) {
1316 return STATUS_UNSUCCESSFUL
;
1319 if ((streamIndex
== PCM_IN_STREAM
) && Miniport
->isStreamRunning
[AC3_OUT_STREAM
]) {
1320 if (waveFormat
->nSamplesPerSec
!= Miniport
->stream
[AC3_OUT_STREAM
]->currentSampleRate
) {
1321 return STATUS_UNSUCCESSFUL
;
1324 if ((streamIndex
== PCM_OUT_STREAM
) && Miniport
->isStreamRunning
[PCM_IN_STREAM
]) {
1325 if (waveFormat
->nSamplesPerSec
!= Miniport
->stream
[PCM_IN_STREAM
]->currentSampleRate
) {
1326 return STATUS_UNSUCCESSFUL
;
1329 if ((streamIndex
== PCM_OUT_STREAM
) && Miniport
->isStreamRunning
[AC3_OUT_STREAM
]) {
1330 return STATUS_UNSUCCESSFUL
;
1333 KeWaitForSingleObject(&Miniport
->mutex
, Executive
, KernelMode
, false, NULL
);
1334 currentSampleRate
= waveFormat
->nSamplesPerSec
;
1335 currentChannelCount
= waveFormat
->nChannels
;
1336 currentResolution
= waveFormat
->wBitsPerSample
;
1337 enableAC3Passthru
= (WAVE_FORMAT_DOLBY_AC3_SPDIF
== EXTRACT_WAVEFORMATEX_ID(&Format
->SubFormat
));
1338 KeReleaseMutex(&Miniport
->mutex
, false);
1339 ntStatus
= prepareStream();
1344 // DRM crap - we're supposed to disable every digital interface here
1345 STDMETHODIMP_(NTSTATUS
) CMiniportWaveStreamCMI::SetContentId(ULONG contentId
, PCDRMRIGHTS drmRights
)
1348 DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetContentId(%d, %p)", this, contentId
, drmRights
));
1350 return STATUS_SUCCESS
;
1355 STDMETHODIMP_(NTSTATUS
) CMiniportWaveStreamCMI::AllocateAudioBuffer(ULONG size
, PMDL
*userModeBuffer
, ULONG
*bufferSize
, ULONG
*bufferOffset
, MEMORY_CACHING_TYPE
*cacheType
)
1359 PHYSICAL_ADDRESS low
;
1360 PHYSICAL_ADDRESS high
;
1361 DBGPRINT(("CMiniportWaveStreamCMI[%p]::AllocateAudioBuffer(%x, %p, %p, %p, %p)", this, size
, userModeBuffer
, bufferSize
, bufferOffset
, cacheType
));
1363 if (size
<= size
% (currentChannelCount
* 2)) {
1364 return STATUS_UNSUCCESSFUL
;
1366 size
-= size
% (currentChannelCount
* 2);
1369 return STATUS_UNSUCCESSFUL
;
1373 high
.HighPart
= 0, high
.LowPart
= MAXULONG
;
1375 audioBufferMDL
= Port
->AllocateContiguousPagesForMdl(low
, high
, size
);
1377 if (!audioBufferMDL
) {
1378 DBGPRINT(("AllocateContiguousPagesForMdl() failed"));
1379 return STATUS_UNSUCCESSFUL
;
1382 dmaAddress
= Port
->GetPhysicalPageAddress(audioBufferMDL
, 0).LowPart
;
1383 dmaMemorySize
= size
;
1385 *userModeBuffer
= audioBufferMDL
;
1388 *cacheType
= MmCached
;
1390 return STATUS_SUCCESS
;
1394 STDMETHODIMP_(VOID
) CMiniportWaveStreamCMI::FreeAudioBuffer(PMDL Mdl
, ULONG Size
)
1397 DBGPRINT(("CMiniportWaveStreamCMI[%p]::FreeAudioBuffer(%p, %x)", this, Mdl
, Size
));
1399 Port
->FreePagesFromMdl(Mdl
);
1400 audioBufferMDL
= NULL
;
1405 STDMETHODIMP_(void) CMiniportWaveStreamCMI::GetHWLatency(PKSRTAUDIO_HWLATENCY hwLatency
) {
1407 DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetHWLatency(%p)", this, hwLatency
));
1408 hwLatency
->FifoSize
= 32;
1409 hwLatency
->ChipsetDelay
= 0;
1410 hwLatency
->CodecDelay
= 4;
1413 STDMETHODIMP_(NTSTATUS
) CMiniportWaveStreamCMI::GetPositionRegister(PKSRTAUDIO_HWREGISTER hwRegister
)
1416 DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetPositionRegister(%p)", this, hwRegister
));
1418 return STATUS_UNSUCCESSFUL
;
1421 STDMETHODIMP_(NTSTATUS
) CMiniportWaveStreamCMI::GetClockRegister(PKSRTAUDIO_HWREGISTER hwRegister
)
1424 DBGPRINT(("CMiniportWaveStreamCMI[%p]::GetClockRegister(%p)", this, hwRegister
));
1426 return STATUS_UNSUCCESSFUL
;
1432 ** non-paged code below
1436 STDMETHODIMP
CMiniportWaveStreamCMI::SetState(KSSTATE NewState
)
1438 DBGPRINT(("CMiniportWaveStreamCMI[%p]::SetState(%d)", this, NewState
));
1440 UInt32 inthld
, chen
, reset
, pause
;
1443 inthld
= EN_CH0_INT
<< channelNumber
;
1444 chen
= EN_CH0
<< channelNumber
;
1445 reset
= RST_CH0
<< channelNumber
;
1446 pause
= PAUSE_CH0
<< channelNumber
;
1448 NTSTATUS ntStatus
= STATUS_SUCCESS
;
1450 if ((streamIndex
== PCM_OUT_STREAM
) && Miniport
->isStreamRunning
[AC3_OUT_STREAM
]) {
1451 return STATUS_INVALID_PARAMETER
;
1454 if (NewState
== KSSTATE_RUN_AC3
) {
1456 state
= KSSTATE_STOP
;
1459 // STOP -> ACQUIRE -> PAUSE -> PLAY -> PAUSE -> ACQUIRE -> STOP
1460 if (state
!= NewState
) {
1462 case KSSTATE_ACQUIRE
:
1463 DBGPRINT(("---KSSTATE_ACQUIRE: previous state: %d", state
));
1464 if (state
== KSSTATE_PAUSE
) {
1469 if ((dmaMemorySize
== 0) || (dmaAddress
== 0)) {
1470 return STATUS_UNSUCCESSFUL
;
1472 dmaSize
= (dmaMemorySize
/ (2 * (currentResolution
>> 3)) );
1473 periodSize
= dmaSize
;
1474 DBGPRINT(("---dmaAddress: %x, dmaMemorySize: %x, dmaSize: %x", dmaAddress
, dmaMemorySize
, dmaSize
));
1476 if (currentResolution
== 24) {
1477 dmaSize
= (DMAChannel
->BufferSize() / (2 * (24 >> 3)) );
1479 dmaSize
= (DMAChannel
->BufferSize() / (2 * (currentResolution
>> 3)) );
1482 DBGPRINT(("---streamIndex: %d, channelNumber: %d", streamIndex
, channelNumber
));
1483 DBGPRINT(("---SampleRate: %d, Resolution: %d, Channels: %d", currentSampleRate
, currentResolution
, currentChannelCount
));
1485 if (periodSize
> dmaSize
) {
1486 periodSize
= dmaSize
;
1489 // set address of the DMA buffer
1490 KeWaitForSingleObject(&Miniport
->mutex
, Executive
, KernelMode
, FALSE
, NULL
);
1491 reg
= channelNumber
? REG_CH1_FRAME1
: REG_CH0_FRAME1
;
1493 Miniport
->CMIAdapter
->writeUInt32(reg
, dmaAddress
);
1495 Miniport
->CMIAdapter
->writeUInt32(reg
, DMAChannel
->PhysicalAddress().u
.LowPart
);
1498 reg
= channelNumber
? REG_CH1_FRAME2
: REG_CH0_FRAME2
;
1499 Miniport
->CMIAdapter
->writeUInt16(reg
, dmaSize
-1);
1500 Miniport
->CMIAdapter
->writeUInt16(reg
+ 2, periodSize
-1);
1501 DBGPRINT(("---DMA Size: 0x%04X, Period Size: 0x%04X, enableSPDIFIn: %d", dmaSize
, periodSize
, Miniport
->cm
->enableSPDIFIn
));
1502 if (isCaptureStream
&& (Miniport
->cm
->enableSPDIFIn
)) {
1504 Miniport
->CMIAdapter
->setUInt32Bit(REG_FUNCTRL1
, SPDF_1
);
1506 Miniport
->CMIAdapter
->setUInt32Bit(REG_FUNCTRL1
, SPDF_0
);
1509 KeReleaseMutex(&Miniport
->mutex
, false);
1513 DBGPRINT(("---KSSTATE_PAUSE: previous state: %d", state
));
1514 if (state
== KSSTATE_RUN
) {
1515 KeWaitForSingleObject(&Miniport
->mutex
, Executive
, KernelMode
, false, NULL
);
1516 Miniport
->cm
->regFUNCTRL0
|= pause
;
1517 Miniport
->CMIAdapter
->writeUInt32(REG_FUNCTRL0
, Miniport
->cm
->regFUNCTRL0
);
1518 KeReleaseMutex(&Miniport
->mutex
, FALSE
);
1520 if (state
== KSSTATE_STOP
) {
1521 KeWaitForSingleObject(&Miniport
->mutex
, Executive
, KernelMode
, false, NULL
);
1522 Miniport
->cm
->regFUNCTRL0
&= ~pause
;
1523 Miniport
->CMIAdapter
->writeUInt32(REG_FUNCTRL0
, Miniport
->cm
->regFUNCTRL0
);
1524 KeReleaseMutex(&Miniport
->mutex
, false);
1529 DBGPRINT(("---KSSTATE_RUN: previous state: %d", state
));
1531 KeWaitForSingleObject(&Miniport
->mutex
, Executive
, KernelMode
, FALSE
, NULL
);
1533 Miniport
->CMIAdapter
->setUInt32Bit(REG_INTHLDCLR
, inthld
);
1534 Miniport
->cm
->regFUNCTRL0
&= ~pause
;
1535 Miniport
->cm
->regFUNCTRL0
|= chen
;
1536 // and enable the channel
1537 Miniport
->CMIAdapter
->writeUInt32(REG_FUNCTRL0
, Miniport
->cm
->regFUNCTRL0
);
1539 DBGPRINT(("---FUNCTRL0: 0x%08X", Miniport
->cm
->regFUNCTRL0
));
1540 DBGPRINT(("---FUNCTRL1: 0x%08X", Miniport
->CMIAdapter
->readUInt32(REG_FUNCTRL1
)));
1541 DBGPRINT(("---CHFORMAT: 0x%08X", Miniport
->CMIAdapter
->readUInt32(REG_CHFORMAT
)));
1542 DBGPRINT(("---LEGACYCTRL: 0x%08X", Miniport
->CMIAdapter
->readUInt32(REG_LEGACY
)));
1543 DBGPRINT(("---MISCCTRL: 0x%08X", Miniport
->CMIAdapter
->readUInt32(REG_MISCCTRL
)));
1544 DBGPRINT(("---MIX1: 0x%02X", Miniport
->CMIAdapter
->readUInt8(REG_MIXER1
)));
1545 DBGPRINT(("---MIX2: 0x%02X", Miniport
->CMIAdapter
->readUInt8(REG_MIXER2
)));
1546 DBGPRINT(("---MIX3: 0x%02X", Miniport
->CMIAdapter
->readUInt8(REG_MIXER3
)));
1548 KeReleaseMutex(&Miniport
->mutex
, false);
1551 case KSSTATE_STOP_AC3
:
1553 DBGPRINT(("---KSSTATE_STOP: previous state: %d", state
));
1554 KeWaitForSingleObject(&Miniport
->mutex
, Executive
, KernelMode
, FALSE
, NULL
);
1556 Miniport
->CMIAdapter
->clearUInt32Bit(REG_INTHLDCLR
, inthld
);
1557 Miniport
->cm
->regFUNCTRL0
&= ~chen
;
1559 Miniport
->CMIAdapter
->writeUInt32(REG_FUNCTRL0
, Miniport
->cm
->regFUNCTRL0
| reset
);
1560 Miniport
->CMIAdapter
->writeUInt32(REG_FUNCTRL0
, Miniport
->cm
->regFUNCTRL0
& ~reset
);
1561 if (isCaptureStream
&& (Miniport
->cm
->enableSPDIFIn
)) {
1563 Miniport
->CMIAdapter
->clearUInt32Bit(REG_FUNCTRL1
, SPDF_1
);
1565 Miniport
->CMIAdapter
->clearUInt32Bit(REG_FUNCTRL1
, SPDF_0
);
1568 KeReleaseMutex(&Miniport
->mutex
, FALSE
);
1571 if (NewState
!= KSSTATE_STOP_AC3
) {
1579 STDMETHODIMP
CMiniportWaveStreamCMI::GetPosition(PKSAUDIO_POSITION Position
)
1585 if ((state
== KSSTATE_RUN
) && (dmaAddress
)) {
1586 reg
= (channelNumber
) ? REG_CH1_FRAME1
: REG_CH0_FRAME1
;
1587 Position
->PlayOffset
= Miniport
->CMIAdapter
->readUInt32(reg
) - dmaAddress
;
1588 Position
->WriteOffset
= Position
->PlayOffset
+ currentChannelCount
* 2 * 8;
1590 Position
->PlayOffset
= 0;
1591 Position
->WriteOffset
= 0;
1594 return STATUS_SUCCESS
;
1598 STDMETHODIMP
CMiniportWaveStreamCMI::GetPosition(PULONG Position
)
1604 if ((DMAChannel
) && (state
== KSSTATE_RUN
)) {
1606 // this implementation messes with SPDIF-in recording
1607 reg
= (channelNumber
) ? REG_CH1_FRAME2
: REG_CH0_FRAME2
;
1608 *Position
= dmaSize
- (Miniport
->CMIAdapter
->readUInt16(reg
)-1);
1609 *Position
*= 2 * (currentResolution
>> 3);
1611 reg
= (channelNumber
) ? REG_CH1_FRAME1
: REG_CH0_FRAME1
;
1612 *Position
= Miniport
->CMIAdapter
->readUInt32(reg
);
1613 if (*Position
> DMAChannel
->PhysicalAddress().u
.LowPart
) {
1614 *Position
-= DMAChannel
->PhysicalAddress().u
.LowPart
;
1623 return STATUS_SUCCESS
;
1626 STDMETHODIMP_(ULONG
) CMiniportWaveStreamCMI::SetNotificationFreq(ULONG Interval
, PULONG FramingSize
)
1628 Miniport
->notificationInterval
= Interval
;
1630 if (state
== KSSTATE_RUN
) {
1633 periodSize
= Interval
* currentSampleRate
/1000;
1634 *FramingSize
= periodSize
*currentChannelCount
*(currentResolution
>> 3);
1636 KeWaitForSingleObject(&Miniport
->mutex
, Executive
, KernelMode
, FALSE
, NULL
);
1637 Miniport
->CMIAdapter
->writeUInt16((channelNumber
? REG_CH1_FRAME2
: REG_CH0_FRAME2
) + 2, periodSize
-1);
1638 KeReleaseMutex(&Miniport
->mutex
, FALSE
);
1640 DBGPRINT(("periodSize: %x, FramingSize: %x", periodSize
, *FramingSize
));
1644 STDMETHODIMP
CMiniportWaveStreamCMI::NormalizePhysicalPosition(OUT PLONGLONG PhysicalPosition
)
1646 *PhysicalPosition
= (_100NS_UNITS_PER_SECOND
/ currentChannelCount
* (currentResolution
>> 3) * *PhysicalPosition
) / currentSampleRate
;
1647 return STATUS_SUCCESS
;
1651 STDMETHODIMP_(void) CMiniportWaveStreamCMI::Silence(PVOID Buffer
, ULONG ByteCount
)
1653 RtlFillMemory(Buffer
, ByteCount
, 0x00);
1658 STDMETHODIMP_(void) CMiniportWaveCMI::ServiceWaveISR(UInt32 streamIndex
)
1661 if ((streamIndex
== PCM_OUT_STREAM
) && isStreamRunning
[AC3_OUT_STREAM
]) {
1662 streamIndex
= AC3_OUT_STREAM
;
1664 if (Port
&& stream
[streamIndex
]->ServiceGroup
) {
1665 Port
->Notify(stream
[streamIndex
]->ServiceGroup
);