Reactos

[HDAUDBUS_NEW] Import new SkyLake/KabyLake/ApolloLake HD audio bus driver from https://github.com/coolstar/sklhdaudbus/tree/master (BSD-3-Clause License) [DOC] 3rd Party Files.txt: Add 'HD Audio Driver for Windows 10 / 11 with Skylake -> Raptor Lake DSP support' CORE-15350, CORE-18776

authored by

Oleg Dubinskiy and committed by
Oleg Dubinskiy
7c2d9230 4e72ec83

+6098
+11
drivers/wdm/audio/hdaudbus_new/LICENSE.txt
··· 1 + Copyright 2024 CoolStar 2 + 3 + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 + 5 + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 + 7 + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 + 9 + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 10 + 11 + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+14
drivers/wdm/audio/hdaudbus_new/README.md
··· 1 + HD Audio Bus Driver for Intel Skylake and newer 2 + 3 + * Exposes HD Audio devices 4 + * Compatible with VMWare, QEMU, and Intel Skylake / Kaby Lake / Apollo Lake / Gemini Lake / Comet Lake / Tiger Lake / Jasper Lake / Alder Lake(-N) / Raptor Lake 5 + * Compatible with Windows default codec driver (QEMU / VMWare) 6 + * Compatible with Intel Display Audio driver (Intel Lakes, and Intel Haswell / Broadwell) 7 + * Compatible with Realtek ALC283 driver (Intel Haswell / Broadwell) 8 + * Compatible with NVIDIA RTX 30-40 Series (HDMI Audio) 9 + * Compatible with Asus TUF Gaming X570 Plus (AMD Ryzen 5000) 10 + * Compatible with Asus ROG Strix B850-A Gaming Wifi (AMD Ryzen 9000) 11 + * Support accessing AudioDSP on Intel platforms 12 + * Compatible with csaudiosstavs and csaudiointcsof 13 + * Working Sleep / Wake 14 + * Compatible with Windows 10 / 11 64-bit
+398
drivers/wdm/audio/hdaudbus_new/adsp.cpp
··· 1 + #include "driver.h" 2 + #define ADSP_DECL 1 3 + #include "adsp.h" 4 + 5 + NTSTATUS ADSPGetResources(_In_ PVOID _context, _PCI_BAR* hdaBar, _PCI_BAR* adspBar, PVOID *ppcap, PNHLT_INFO nhltInfo, BUS_INTERFACE_STANDARD* pciConfig) { 6 + if (!_context) 7 + return STATUS_NO_SUCH_DEVICE; 8 + 9 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 10 + if (!devData->FdoContext) { 11 + return STATUS_NO_SUCH_DEVICE; 12 + } 13 + 14 + if (hdaBar) { 15 + *hdaBar = devData->FdoContext->m_BAR0; 16 + } 17 + 18 + if (adspBar) { 19 + *adspBar = devData->FdoContext->m_BAR4; 20 + } 21 + 22 + if (ppcap) { 23 + *ppcap = devData->FdoContext->ppcap; 24 + } 25 + 26 + if (nhltInfo) { 27 + if (devData->FdoContext->nhlt) { 28 + nhltInfo->nhlt = devData->FdoContext->nhlt; 29 + nhltInfo->nhltSz = devData->FdoContext->nhltSz; 30 + } 31 + else if (devData->FdoContext->sofTplg) { 32 + nhltInfo->nhlt = devData->FdoContext->sofTplg; 33 + nhltInfo->nhltSz = devData->FdoContext->sofTplgSz; 34 + } 35 + } 36 + 37 + if (pciConfig) { 38 + *pciConfig = devData->FdoContext->BusInterface; 39 + } 40 + 41 + return STATUS_SUCCESS; 42 + } 43 + 44 + NTSTATUS ADSPSetPowerState(_In_ PVOID _context, _In_ DEVICE_POWER_STATE powerState) { 45 + if (!_context) 46 + return STATUS_NO_SUCH_DEVICE; 47 + 48 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 49 + if (!devData->FdoContext) { 50 + return STATUS_NO_SUCH_DEVICE; 51 + } 52 + 53 + NTSTATUS status = STATUS_SUCCESS; 54 + if (powerState == PowerDeviceD3) { 55 + WdfDeviceResumeIdle(devData->FdoContext->WdfDevice); 56 + } else if (powerState == PowerDeviceD0) { 57 + status = WdfDeviceStopIdle(devData->FdoContext->WdfDevice, TRUE); 58 + } 59 + return status; 60 + } 61 + 62 + NTSTATUS ADSPRegisterInterrupt(_In_ PVOID _context, _In_ PADSP_INTERRUPT_CALLBACK callback, _In_ PVOID callbackContext) { 63 + if (!_context) 64 + return STATUS_NO_SUCH_DEVICE; 65 + 66 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 67 + if (!devData->FdoContext) { 68 + return STATUS_NO_SUCH_DEVICE; 69 + } 70 + 71 + devData->FdoContext->dspInterruptCallback = callback; 72 + devData->FdoContext->dspInterruptContext = callbackContext; 73 + return STATUS_SUCCESS; 74 + } 75 + 76 + NTSTATUS ADSPUnregisterInterrupt(_In_ PVOID _context) { 77 + if (!_context) 78 + return STATUS_NO_SUCH_DEVICE; 79 + 80 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 81 + if (!devData->FdoContext) { 82 + return STATUS_NO_SUCH_DEVICE; 83 + } 84 + 85 + devData->FdoContext->dspInterruptCallback = NULL; 86 + devData->FdoContext->dspInterruptContext = NULL; 87 + return STATUS_SUCCESS; 88 + } 89 + 90 + NTSTATUS ADSPGetRenderStream(_In_ PVOID _context, HDAUDIO_STREAM_FORMAT StreamFormat, PHANDLE Handle, _Out_ UINT8* streamTag) { 91 + if (!_context) 92 + return STATUS_NO_SUCH_DEVICE; 93 + 94 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 95 + if (!devData->FdoContext) { 96 + return STATUS_NO_SUCH_DEVICE; 97 + } 98 + 99 + PFDO_CONTEXT fdoContext = devData->FdoContext; 100 + 101 + NTSTATUS status = WdfDeviceStopIdle(devData->FdoContext->WdfDevice, TRUE); 102 + if (!NT_SUCCESS(status)) { 103 + return status; 104 + } 105 + 106 + WdfInterruptAcquireLock(devData->FdoContext->Interrupt); 107 + for (UINT32 i = 0; i < fdoContext->playbackStreams; i++) { 108 + int tag = fdoContext->playbackIndexOff + i; 109 + PHDAC_STREAM stream = &fdoContext->streams[tag]; 110 + if (stream->PdoContext != NULL) { 111 + continue; 112 + } 113 + 114 + stream->stripe = FALSE; 115 + stream->PdoContext = devData; 116 + stream->running = FALSE; 117 + stream->streamFormat = StreamFormat; 118 + 119 + int mask = HDA_PPCTL_PROCEN(stream->idx); 120 + UINT32 val = 0; 121 + val = read16(fdoContext->ppcap + HDA_REG_PP_PPCTL) & mask; 122 + 123 + if (!val) { 124 + hdac_update32(fdoContext->ppcap, HDA_REG_PP_PPCTL, mask, mask); 125 + } 126 + 127 + if (Handle) 128 + *Handle = (HANDLE)stream; 129 + if (streamTag) 130 + *streamTag = stream->streamTag; 131 + 132 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 133 + return STATUS_SUCCESS; 134 + } 135 + 136 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 137 + WdfDeviceResumeIdle(devData->FdoContext->WdfDevice); 138 + return STATUS_INSUFFICIENT_RESOURCES; 139 + } 140 + 141 + NTSTATUS ADSPGetCaptureStream(_In_ PVOID _context, HDAUDIO_STREAM_FORMAT StreamFormat, PHANDLE Handle, _Out_ UINT8* streamTag) { 142 + if (!_context) 143 + return STATUS_NO_SUCH_DEVICE; 144 + 145 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 146 + if (!devData->FdoContext) { 147 + return STATUS_NO_SUCH_DEVICE; 148 + } 149 + 150 + PFDO_CONTEXT fdoContext = devData->FdoContext; 151 + 152 + NTSTATUS status = WdfDeviceStopIdle(devData->FdoContext->WdfDevice, TRUE); 153 + if (!NT_SUCCESS(status)) { 154 + return status; 155 + } 156 + 157 + WdfInterruptAcquireLock(devData->FdoContext->Interrupt); 158 + for (UINT32 i = 0; i < fdoContext->captureStreams; i++) { 159 + int tag = fdoContext->captureIndexOff + i; 160 + PHDAC_STREAM stream = &fdoContext->streams[tag]; 161 + if (stream->PdoContext != NULL) { 162 + continue; 163 + } 164 + 165 + stream->stripe = FALSE; 166 + stream->PdoContext = devData; 167 + stream->running = FALSE; 168 + stream->streamFormat = StreamFormat; 169 + 170 + int mask = HDA_PPCTL_PROCEN(stream->idx); 171 + UINT32 val = 0; 172 + val = read16(fdoContext->ppcap + HDA_REG_PP_PPCTL) & mask; 173 + 174 + if (!val) { 175 + hdac_update32(fdoContext->ppcap, HDA_REG_PP_PPCTL, mask, mask); 176 + } 177 + 178 + if (Handle) 179 + *Handle = (HANDLE)stream; 180 + if (streamTag) 181 + *streamTag = stream->streamTag; 182 + 183 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 184 + return STATUS_SUCCESS; 185 + } 186 + 187 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 188 + WdfDeviceResumeIdle(devData->FdoContext->WdfDevice); 189 + return STATUS_INSUFFICIENT_RESOURCES; 190 + } 191 + 192 + NTSTATUS ADSPFreeStream( 193 + _In_ PVOID _context, 194 + _In_ HANDLE Handle 195 + ) { 196 + SklHdAudBusPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "%s called!\n", __func__); 197 + 198 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 199 + if (!devData->FdoContext) { 200 + return STATUS_NO_SUCH_DEVICE; 201 + } 202 + 203 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 204 + if (!stream || stream->PdoContext != devData) { 205 + return STATUS_INVALID_HANDLE; 206 + } 207 + 208 + WdfInterruptAcquireLock(devData->FdoContext->Interrupt); 209 + 210 + if (stream->running) { 211 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 212 + return STATUS_INVALID_DEVICE_REQUEST; 213 + } 214 + 215 + PFDO_CONTEXT fdoContext = devData->FdoContext; 216 + int mask = HDA_PPCTL_PROCEN(stream->idx); 217 + UINT32 val = 0; 218 + val = read16(fdoContext->ppcap + HDA_REG_PP_PPCTL) & mask; 219 + 220 + if (val) { 221 + hdac_update32(fdoContext->ppcap, HDA_REG_PP_PPCTL, mask, 0); 222 + } 223 + 224 + stream->PdoContext = NULL; 225 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 226 + WdfDeviceResumeIdle(devData->FdoContext->WdfDevice); 227 + 228 + return STATUS_SUCCESS; 229 + } 230 + 231 + NTSTATUS ADSPPrepareDSP( 232 + _In_ PVOID _context, 233 + _In_ HANDLE Handle, 234 + _In_ unsigned int ByteSize, 235 + _In_ int NumBlocks, 236 + _Out_ PVOID* bdlBuf 237 + ) { 238 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 239 + if (!devData->FdoContext) { 240 + return STATUS_NO_SUCH_DEVICE; 241 + } 242 + 243 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 244 + if (!stream || stream->PdoContext != devData) { 245 + return STATUS_INVALID_HANDLE; 246 + } 247 + 248 + WdfInterruptAcquireLock(devData->FdoContext->Interrupt); 249 + 250 + if (stream->running) { 251 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 252 + return STATUS_DEVICE_BUSY; 253 + } 254 + 255 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 256 + 257 + stream->mdlBuf = NULL; 258 + stream->bufSz = ByteSize; 259 + stream->numBlocks = (UINT16)NumBlocks; 260 + 261 + hdac_stream_reset(stream); 262 + 263 + /* reset BDL address */ 264 + stream_write32(stream, SD_BDLPL, 0); 265 + stream_write32(stream, SD_BDLPU, 0); 266 + 267 + hdac_stream_setup(stream); 268 + 269 + if (bdlBuf) 270 + *bdlBuf = stream->bdl; 271 + return STATUS_SUCCESS; 272 + } 273 + 274 + NTSTATUS ADSPCleanupDSP(_In_ PVOID _context, _In_ HANDLE Handle) { 275 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 276 + if (!devData->FdoContext) { 277 + return STATUS_NO_SUCH_DEVICE; 278 + } 279 + 280 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 281 + if (!stream || stream->PdoContext != devData) { 282 + return STATUS_INVALID_HANDLE; 283 + } 284 + 285 + WdfInterruptAcquireLock(devData->FdoContext->Interrupt); 286 + 287 + stream_write32(stream, SD_BDLPL, 0); 288 + stream_write32(stream, SD_BDLPU, 0); 289 + stream_write32(stream, SD_CTL, 0); 290 + 291 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 292 + 293 + return STATUS_SUCCESS; 294 + } 295 + 296 + void ADSPStartStopDSP(_In_ PVOID _context, _In_ HANDLE Handle, BOOL startStop) { 297 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 298 + if (!devData->FdoContext) { 299 + return; 300 + } 301 + 302 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 303 + if (!stream || stream->PdoContext != devData) { 304 + return; 305 + } 306 + 307 + if (startStop) 308 + hdac_stream_start(stream); 309 + else 310 + hdac_stream_stop(stream); 311 + } 312 + 313 + void ADSPEnableSPIB(_In_ PVOID _context, _In_ HANDLE Handle, UINT32 value) { 314 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 315 + if (!devData->FdoContext) { 316 + return; 317 + } 318 + 319 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 320 + if (!stream || stream->PdoContext != devData) { 321 + return; 322 + } 323 + 324 + if (!devData->FdoContext->spbcap) { 325 + return; 326 + } 327 + 328 + UINT32 mask = (1 << stream->idx); 329 + hdac_update32(devData->FdoContext->spbcap, HDA_REG_SPB_SPBFCCTL, mask, mask); 330 + 331 + write32(stream->spib_addr, value); 332 + } 333 + 334 + void ADSPDisableSPIB(_In_ PVOID _context, _In_ HANDLE Handle) { 335 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 336 + if (!devData->FdoContext) { 337 + return; 338 + } 339 + 340 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 341 + if (!stream || stream->PdoContext != devData) { 342 + return; 343 + } 344 + 345 + if (!devData->FdoContext->spbcap) { 346 + return; 347 + } 348 + 349 + UINT32 mask = (1 << stream->idx); 350 + hdac_update32(devData->FdoContext->spbcap, HDA_REG_SPB_SPBFCCTL, mask, 0); 351 + 352 + write32(stream->spib_addr, 0); 353 + } 354 + 355 + UINT32 ADSPStreamPosition(_In_ PVOID _context, _In_ HANDLE Handle) { 356 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 357 + if (!devData->FdoContext) { 358 + return 0; 359 + } 360 + 361 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 362 + if (!stream || stream->PdoContext != devData) { 363 + return 0; 364 + } 365 + 366 + return *stream->posbuf; 367 + } 368 + 369 + ADSP_BUS_INTERFACE ADSP_BusInterface(PVOID Context) { 370 + ADSP_BUS_INTERFACE busInterface; 371 + RtlZeroMemory(&busInterface, sizeof(ADSP_BUS_INTERFACE)); 372 + 373 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)Context; 374 + 375 + busInterface.Size = sizeof(ADSP_BUS_INTERFACE); 376 + busInterface.Version = 1; 377 + busInterface.Context = Context; 378 + busInterface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; 379 + busInterface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; 380 + busInterface.CtlrDevId = devData->CodecIds.CtlrDevId; 381 + busInterface.GetResources = ADSPGetResources; 382 + busInterface.SetDSPPowerState = ADSPSetPowerState; 383 + busInterface.RegisterInterrupt = ADSPRegisterInterrupt; 384 + busInterface.UnregisterInterrupt = ADSPUnregisterInterrupt; 385 + 386 + busInterface.GetRenderStream = ADSPGetRenderStream; 387 + busInterface.GetCaptureStream = ADSPGetCaptureStream; 388 + busInterface.FreeStream = ADSPFreeStream; 389 + busInterface.PrepareDSP = ADSPPrepareDSP; 390 + busInterface.CleanupDSP = ADSPCleanupDSP; 391 + busInterface.TriggerDSP = ADSPStartStopDSP; 392 + busInterface.StreamPosition = ADSPStreamPosition; 393 + 394 + busInterface.DSPEnableSPIB = ADSPEnableSPIB; 395 + busInterface.DSPDisableSPIB = ADSPDisableSPIB; 396 + 397 + return busInterface; 398 + }
+64
drivers/wdm/audio/hdaudbus_new/adsp.h
··· 1 + #ifndef __ADSP_INTERFACE 2 + #define __ADSP_INTERFACE 3 + 4 + // 5 + // The ADSP_BUS_INTERFACE interface GUID 6 + // 7 + // {752A2CAE-3455-4D18-A184-8B34B22632CE} 8 + DEFINE_GUID(GUID_ADSP_BUS_INTERFACE, 9 + 0x752a2cae, 0x3455, 0x4d18, 0xa1, 0x84, 0x8b, 0x34, 0xb2, 0x26, 0x32, 0xce); 10 + 11 + typedef struct _NHLT_INFO { 12 + PVOID nhlt; 13 + UINT64 nhltSz; 14 + } NHLT_INFO, * PNHLT_INFO; 15 + 16 + typedef _Must_inspect_result_ NTSTATUS(*PGET_ADSP_RESOURCES) (_In_ PVOID _context, _Out_ _PCI_BAR* hdaBar, _Out_ _PCI_BAR* adspBar, PVOID* ppcap, PNHLT_INFO nhltInfo, _Out_ BUS_INTERFACE_STANDARD* pciConfig); 17 + typedef _Must_inspect_result_ NTSTATUS(*PDSP_SET_POWER_STATE) (_In_ PVOID _context, _In_ DEVICE_POWER_STATE newPowerState); 18 + typedef _Must_inspect_result_ BOOL(*PADSP_INTERRUPT_CALLBACK)(PVOID context); 19 + typedef _Must_inspect_result_ NTSTATUS(*PREGISTER_ADSP_INTERRUPT) (_In_ PVOID _context, _In_ PADSP_INTERRUPT_CALLBACK callback, _In_ PVOID callbackContext); 20 + typedef _Must_inspect_result_ NTSTATUS(*PUNREGISTER_ADSP_INTERRUPT) (_In_ PVOID _context); 21 + typedef _Must_inspect_result_ NTSTATUS(*PGET_STREAM)(_In_ PVOID _context, HDAUDIO_STREAM_FORMAT StreamFormat, PHANDLE Handle, _Out_ UINT8* streamTag); 22 + typedef _Must_inspect_result_ NTSTATUS(*PFREE_STREAM)(_In_ PVOID _context, _In_ HANDLE Handle); 23 + typedef _Must_inspect_result_ NTSTATUS(*PDSP_PREPARE_STREAM)(_In_ PVOID _context, _In_ HANDLE Handle, _In_ unsigned int ByteSize, _In_ int frags, _Out_ PVOID* bdlBuf); 24 + typedef _Must_inspect_result_ NTSTATUS(*PDSP_CLEANUP_STREAM)(_In_ PVOID _context, _In_ HANDLE Handle); 25 + typedef _Must_inspect_result_ UINT32(*PDSP_STREAM_POSITION)(_In_ PVOID _context, _In_ HANDLE Handle); 26 + typedef void (*PDSP_START_STOP_STREAM)(_In_ PVOID _context, _In_ HANDLE Handle, BOOL startStop); 27 + typedef void (*PDSP_ENABLE_SPIB)(_In_ PVOID _context, _In_ HANDLE Handle, UINT32 value); 28 + typedef void (*PDSP_DISABLE_SPIB)(_In_ PVOID _context, _In_ HANDLE Handle); 29 + 30 + typedef struct _ADSP_BUS_INTERFACE 31 + { 32 + // 33 + // First we define the standard INTERFACE structure ... 34 + // 35 + USHORT Size; 36 + USHORT Version; 37 + PVOID Context; 38 + PINTERFACE_REFERENCE InterfaceReference; 39 + PINTERFACE_DEREFERENCE InterfaceDereference; 40 + 41 + // 42 + // Then we expand the structure with the ADSP_BUS_INTERFACE stuff. 43 + 44 + UINT16 CtlrDevId; 45 + PGET_ADSP_RESOURCES GetResources; 46 + PDSP_SET_POWER_STATE SetDSPPowerState; 47 + PREGISTER_ADSP_INTERRUPT RegisterInterrupt; 48 + PUNREGISTER_ADSP_INTERRUPT UnregisterInterrupt; 49 + PGET_STREAM GetRenderStream; 50 + PGET_STREAM GetCaptureStream; 51 + PFREE_STREAM FreeStream; 52 + PDSP_PREPARE_STREAM PrepareDSP; 53 + PDSP_CLEANUP_STREAM CleanupDSP; 54 + PDSP_START_STOP_STREAM TriggerDSP; 55 + PDSP_STREAM_POSITION StreamPosition; 56 + 57 + PDSP_ENABLE_SPIB DSPEnableSPIB; 58 + PDSP_DISABLE_SPIB DSPDisableSPIB; 59 + } ADSP_BUS_INTERFACE, * PADSP_BUS_INTERFACE; 60 + 61 + #ifndef ADSP_DECL 62 + ADSP_BUS_INTERFACE ADSP_BusInterface(PVOID Context); 63 + #endif 64 + #endif
+561
drivers/wdm/audio/hdaudbus_new/buspdo.cpp
··· 1 + #include "driver.h" 2 + #include "adsp.h" 3 + 4 + NTSTATUS 5 + Bus_CreatePdo( 6 + _In_ WDFDEVICE Device, 7 + _In_ PWDFDEVICE_INIT DeviceInit, 8 + _In_ PPDO_IDENTIFICATION_DESCRIPTION Desc 9 + ); 10 + 11 + NTSTATUS 12 + NTAPI 13 + Bus_EvtChildListIdentificationDescriptionDuplicate( 14 + WDFCHILDLIST DeviceList, 15 + PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER SourceIdentificationDescription, 16 + PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER DestinationIdentificationDescription 17 + ) 18 + /*++ 19 + Routine Description: 20 + It is called when the framework needs to make a copy of a description. 21 + This happens when a request is made to create a new child device by 22 + calling WdfChildListAddOrUpdateChildDescriptionAsPresent. 23 + If this function is left unspecified, RtlCopyMemory will be used to copy the 24 + source description to destination. Memory for the description is managed by the 25 + framework. 26 + NOTE: Callback is invoked with an internal lock held. So do not call out 27 + to any WDF function which will require this lock 28 + (basically any other WDFCHILDLIST api) 29 + Arguments: 30 + DeviceList - Handle to the default WDFCHILDLIST created by the framework. 31 + SourceIdentificationDescription - Description of the child being created -memory in 32 + the calling thread stack. 33 + DestinationIdentificationDescription - Created by the framework in nonpaged pool. 34 + Return Value: 35 + NT Status code. 36 + --*/ 37 + { 38 + PPDO_IDENTIFICATION_DESCRIPTION src, dst; 39 + 40 + UNREFERENCED_PARAMETER(DeviceList); 41 + 42 + src = CONTAINING_RECORD(SourceIdentificationDescription, 43 + PDO_IDENTIFICATION_DESCRIPTION, 44 + Header); 45 + dst = CONTAINING_RECORD(DestinationIdentificationDescription, 46 + PDO_IDENTIFICATION_DESCRIPTION, 47 + Header); 48 + 49 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 50 + "%s\n", __func__); 51 + 52 + dst->FdoContext = src->FdoContext; 53 + RtlCopyMemory(&dst->CodecIds, &src->CodecIds, sizeof(dst->CodecIds)); 54 + 55 + return STATUS_SUCCESS; 56 + } 57 + 58 + BOOLEAN 59 + NTAPI 60 + Bus_EvtChildListIdentificationDescriptionCompare( 61 + WDFCHILDLIST DeviceList, 62 + PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER FirstIdentificationDescription, 63 + PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER SecondIdentificationDescription 64 + ) 65 + /*++ 66 + Routine Description: 67 + It is called when the framework needs to compare one description with another. 68 + Typically this happens whenever a request is made to add a new child device. 69 + If this function is left unspecified, RtlCompareMemory will be used to compare the 70 + descriptions. 71 + NOTE: Callback is invoked with an internal lock held. So do not call out 72 + to any WDF function which will require this lock 73 + (basically any other WDFCHILDLIST api) 74 + Arguments: 75 + DeviceList - Handle to the default WDFCHILDLIST created by the framework. 76 + Return Value: 77 + TRUE or FALSE. 78 + --*/ 79 + { 80 + PPDO_IDENTIFICATION_DESCRIPTION lhs, rhs; 81 + 82 + UNREFERENCED_PARAMETER(DeviceList); 83 + 84 + lhs = CONTAINING_RECORD(FirstIdentificationDescription, 85 + PDO_IDENTIFICATION_DESCRIPTION, 86 + Header); 87 + rhs = CONTAINING_RECORD(SecondIdentificationDescription, 88 + PDO_IDENTIFICATION_DESCRIPTION, 89 + Header); 90 + 91 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 92 + "%s\n", __func__); 93 + 94 + return (lhs->FdoContext == rhs->FdoContext) && 95 + (RtlCompareMemory(&lhs->CodecIds, &rhs->CodecIds, sizeof(lhs->CodecIds)) == sizeof(lhs->CodecIds)); 96 + } 97 + 98 + VOID 99 + NTAPI 100 + Bus_EvtChildListIdentificationDescriptionCleanup( 101 + _In_ WDFCHILDLIST DeviceList, 102 + _Inout_ PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription 103 + ) 104 + /*++ 105 + Routine Description: 106 + It is called to free up any memory resources allocated as part of the description. 107 + This happens when a child device is unplugged or ejected from the bus. 108 + Memory for the description itself will be freed by the framework. 109 + Arguments: 110 + DeviceList - Handle to the default WDFCHILDLIST created by the framework. 111 + IdentificationDescription - Description of the child being deleted 112 + Return Value: 113 + --*/ 114 + { 115 + UNREFERENCED_PARAMETER(DeviceList); 116 + UNREFERENCED_PARAMETER(IdentificationDescription); 117 + } 118 + 119 + NTSTATUS 120 + NTAPI 121 + Bus_EvtDeviceListCreatePdo( 122 + WDFCHILDLIST DeviceList, 123 + PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, 124 + PWDFDEVICE_INIT ChildInit 125 + ) 126 + /*++ 127 + Routine Description: 128 + Called by the framework in response to Query-Device relation when 129 + a new PDO for a child device needs to be created. 130 + Arguments: 131 + DeviceList - Handle to the default WDFCHILDLIST created by the framework as part 132 + of FDO. 133 + IdentificationDescription - Decription of the new child device. 134 + ChildInit - It's a opaque structure used in collecting device settings 135 + and passed in as a parameter to CreateDevice. 136 + Return Value: 137 + NT Status code. 138 + --*/ 139 + { 140 + PPDO_IDENTIFICATION_DESCRIPTION pDesc; 141 + 142 + PAGED_CODE(); 143 + 144 + pDesc = CONTAINING_RECORD(IdentificationDescription, 145 + PDO_IDENTIFICATION_DESCRIPTION, 146 + Header); 147 + 148 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 149 + "%s\n", __func__); 150 + 151 + return Bus_CreatePdo(WdfChildListGetDevice(DeviceList), 152 + ChildInit, 153 + pDesc); 154 + } 155 + 156 + NTSTATUS 157 + Bus_CreatePdo( 158 + _In_ WDFDEVICE Device, 159 + _In_ PWDFDEVICE_INIT DeviceInit, 160 + _In_ PPDO_IDENTIFICATION_DESCRIPTION Desc 161 + ) 162 + { 163 + UNREFERENCED_PARAMETER(Device); 164 + 165 + NTSTATUS status; 166 + PPDO_DEVICE_DATA pdoData = NULL; 167 + WDFDEVICE hChild = NULL; 168 + WDF_QUERY_INTERFACE_CONFIG qiConfig; 169 + WDF_OBJECT_ATTRIBUTES pdoAttributes; 170 + WDF_DEVICE_PNP_CAPABILITIES pnpCaps; 171 + WDF_DEVICE_POWER_CAPABILITIES powerCaps; 172 + DECLARE_CONST_UNICODE_STRING(deviceLocation, L"High Definition Audio Bus"); 173 + DECLARE_UNICODE_STRING_SIZE(buffer, MAX_INSTANCE_ID_LEN); 174 + DECLARE_UNICODE_STRING_SIZE(deviceId, MAX_INSTANCE_ID_LEN); 175 + DECLARE_UNICODE_STRING_SIZE(compatId, MAX_INSTANCE_ID_LEN); 176 + 177 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 178 + "%s\n", __func__); 179 + 180 + if (Desc->CodecIds.IsDSP) { 181 + // 182 + // Set DeviceType 183 + // 184 + WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER); 185 + 186 + // 187 + // Provide DeviceID, HardwareIDs, CompatibleIDs and InstanceId 188 + // 189 + status = RtlUnicodeStringPrintf(&deviceId, L"CSAUDIO\\ADSP&CTLR_VEN_%04X&CTLR_DEV_%04X", 190 + Desc->CodecIds.CtlrVenId, Desc->CodecIds.CtlrDevId); 191 + if (!NT_SUCCESS(status)) { 192 + return status; 193 + } 194 + 195 + status = WdfPdoInitAssignInstanceID(DeviceInit, &deviceId); 196 + if (!NT_SUCCESS(status)) { 197 + return status; 198 + } 199 + 200 + status = WdfPdoInitAssignDeviceID(DeviceInit, &deviceId); 201 + if (!NT_SUCCESS(status)) { 202 + return status; 203 + } 204 + 205 + // 206 + // NOTE: same string is used to initialize hardware id too 207 + // 208 + status = WdfPdoInitAddHardwareID(DeviceInit, &deviceId); 209 + if (!NT_SUCCESS(status)) { 210 + return status; 211 + } 212 + 213 + status = RtlUnicodeStringPrintf(&compatId, L"CSAUDIO\\ADSP&CTLR_VEN_%04X&CTLR_DEV_%04X", 214 + Desc->CodecIds.CtlrVenId, Desc->CodecIds.CtlrDevId); 215 + if (!NT_SUCCESS(status)) { 216 + return status; 217 + } 218 + 219 + // 220 + // NOTE: same string is used to initialize compat id too 221 + // 222 + status = WdfPdoInitAddCompatibleID(DeviceInit, &compatId); 223 + if (!NT_SUCCESS(status)) { 224 + return status; 225 + } 226 + } 227 + else { 228 + // 229 + // Set DeviceType 230 + // 231 + WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_SOUND); 232 + 233 + PWCHAR prefix = L"HDAUDIO"; 234 + PWCHAR funcPrefix = L""; 235 + if (Desc->CodecIds.IsGraphicsCodec) { 236 + funcPrefix = L"SGPC_"; 237 + } 238 + 239 + // 240 + // Provide DeviceID, HardwareIDs, CompatibleIDs and InstanceId 241 + // 242 + status = RtlUnicodeStringPrintf(&deviceId, L"%s\\%sFUNC_%02X&VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%04X", 243 + prefix, funcPrefix, Desc->CodecIds.FuncId, Desc->CodecIds.VenId, Desc->CodecIds.DevId, Desc->CodecIds.SubsysId, Desc->CodecIds.RevId); 244 + if (!NT_SUCCESS(status)) { 245 + return status; 246 + } 247 + 248 + status = WdfPdoInitAssignDeviceID(DeviceInit, &deviceId); 249 + if (!NT_SUCCESS(status)) { 250 + return status; 251 + } 252 + 253 + // 254 + // NOTE: same string is used to initialize hardware id too 255 + // 256 + status = WdfPdoInitAddHardwareID(DeviceInit, &deviceId); 257 + if (!NT_SUCCESS(status)) { 258 + return status; 259 + } 260 + 261 + //Add second hardware ID without Rev 262 + status = RtlUnicodeStringPrintf(&deviceId, L"%s\\%sFUNC_%02X&VEN_%04X&DEV_%04X&SUBSYS_%08X", 263 + prefix, funcPrefix, Desc->CodecIds.FuncId, Desc->CodecIds.VenId, Desc->CodecIds.DevId, Desc->CodecIds.SubsysId); 264 + if (!NT_SUCCESS(status)) { 265 + return status; 266 + } 267 + 268 + status = WdfPdoInitAddHardwareID(DeviceInit, &deviceId); 269 + if (!NT_SUCCESS(status)) { 270 + return status; 271 + } 272 + 273 + //Add Compatible Ids 274 + { 275 + status = RtlUnicodeStringPrintf(&compatId, L"%s\\%sFUNC_%02X&CTLR_VEN_%02X&CTLR_DEV_%02X&VEN_%04X&DEV_%04X&REV_%04X", 276 + prefix, funcPrefix, Desc->CodecIds.FuncId, Desc->CodecIds.CtlrVenId, Desc->CodecIds.CtlrDevId, Desc->CodecIds.VenId, Desc->CodecIds.DevId, Desc->CodecIds.RevId); 277 + if (!NT_SUCCESS(status)) { 278 + return status; 279 + } 280 + 281 + status = WdfPdoInitAddCompatibleID(DeviceInit, &compatId); 282 + if (!NT_SUCCESS(status)) { 283 + return status; 284 + } 285 + 286 + status = RtlUnicodeStringPrintf(&compatId, L"%s\\%sFUNC_%02X&CTLR_VEN_%02X&VEN_%04X&DEV_%04X&REV_%04X", 287 + prefix, funcPrefix, Desc->CodecIds.FuncId, Desc->CodecIds.CtlrVenId, Desc->CodecIds.VenId, Desc->CodecIds.DevId, Desc->CodecIds.RevId); 288 + if (!NT_SUCCESS(status)) { 289 + return status; 290 + } 291 + 292 + status = WdfPdoInitAddCompatibleID(DeviceInit, &compatId); 293 + if (!NT_SUCCESS(status)) { 294 + return status; 295 + } 296 + 297 + status = RtlUnicodeStringPrintf(&compatId, L"%s\\%sFUNC_%02X&VEN_%04X&DEV_%04X&REV_%04X", 298 + prefix, funcPrefix, Desc->CodecIds.FuncId, Desc->CodecIds.VenId, Desc->CodecIds.DevId, Desc->CodecIds.RevId); 299 + if (!NT_SUCCESS(status)) { 300 + return status; 301 + } 302 + 303 + status = WdfPdoInitAddCompatibleID(DeviceInit, &compatId); 304 + if (!NT_SUCCESS(status)) { 305 + return status; 306 + } 307 + 308 + status = RtlUnicodeStringPrintf(&compatId, L"%s\\%sFUNC_%02X&CTLR_VEN_%02X&CTLR_DEV_%02X&VEN_%04X&DEV_%04X", 309 + prefix, funcPrefix, Desc->CodecIds.FuncId, Desc->CodecIds.CtlrVenId, Desc->CodecIds.CtlrDevId, Desc->CodecIds.VenId, Desc->CodecIds.DevId); 310 + if (!NT_SUCCESS(status)) { 311 + return status; 312 + } 313 + 314 + status = WdfPdoInitAddCompatibleID(DeviceInit, &compatId); 315 + if (!NT_SUCCESS(status)) { 316 + return status; 317 + } 318 + 319 + status = RtlUnicodeStringPrintf(&compatId, L"%s\\%sFUNC_%02X&CTLR_VEN_%02X&VEN_%04X&DEV_%04X", 320 + prefix, funcPrefix, Desc->CodecIds.FuncId, Desc->CodecIds.CtlrVenId, Desc->CodecIds.VenId, Desc->CodecIds.DevId); 321 + if (!NT_SUCCESS(status)) { 322 + return status; 323 + } 324 + 325 + status = WdfPdoInitAddCompatibleID(DeviceInit, &compatId); 326 + if (!NT_SUCCESS(status)) { 327 + return status; 328 + } 329 + 330 + status = RtlUnicodeStringPrintf(&compatId, L"%s\\%sFUNC_%02X&VEN_%04X&DEV_%04X", 331 + prefix, funcPrefix, Desc->CodecIds.FuncId, Desc->CodecIds.VenId, Desc->CodecIds.DevId); 332 + if (!NT_SUCCESS(status)) { 333 + return status; 334 + } 335 + 336 + status = WdfPdoInitAddCompatibleID(DeviceInit, &compatId); 337 + if (!NT_SUCCESS(status)) { 338 + return status; 339 + } 340 + 341 + status = RtlUnicodeStringPrintf(&compatId, L"%s\\%sFUNC_%02X&CTLR_VEN_%02X&CTLR_DEV_%02X&VEN_%04X", 342 + prefix, funcPrefix, Desc->CodecIds.FuncId, Desc->CodecIds.CtlrVenId, Desc->CodecIds.CtlrDevId, Desc->CodecIds.VenId); 343 + if (!NT_SUCCESS(status)) { 344 + return status; 345 + } 346 + 347 + status = WdfPdoInitAddCompatibleID(DeviceInit, &compatId); 348 + if (!NT_SUCCESS(status)) { 349 + return status; 350 + } 351 + 352 + status = RtlUnicodeStringPrintf(&compatId, L"%s\\%sFUNC_%02X&CTLR_VEN_%02X&VEN_%04X", 353 + prefix, funcPrefix, Desc->CodecIds.FuncId, Desc->CodecIds.CtlrVenId, Desc->CodecIds.VenId); 354 + if (!NT_SUCCESS(status)) { 355 + return status; 356 + } 357 + 358 + status = WdfPdoInitAddCompatibleID(DeviceInit, &compatId); 359 + if (!NT_SUCCESS(status)) { 360 + return status; 361 + } 362 + 363 + status = RtlUnicodeStringPrintf(&compatId, L"%s\\%sFUNC_%02X&VEN_%04X", 364 + prefix, funcPrefix, Desc->CodecIds.FuncId, Desc->CodecIds.VenId); 365 + if (!NT_SUCCESS(status)) { 366 + return status; 367 + } 368 + 369 + status = WdfPdoInitAddCompatibleID(DeviceInit, &compatId); 370 + if (!NT_SUCCESS(status)) { 371 + return status; 372 + } 373 + 374 + status = RtlUnicodeStringPrintf(&compatId, L"%s\\%sFUNC_%02X&CTLR_VEN_%02X&CTLR_DEV_%02X", 375 + prefix, funcPrefix, Desc->CodecIds.FuncId, Desc->CodecIds.CtlrVenId, Desc->CodecIds.CtlrDevId); 376 + if (!NT_SUCCESS(status)) { 377 + return status; 378 + } 379 + 380 + status = WdfPdoInitAddCompatibleID(DeviceInit, &compatId); 381 + if (!NT_SUCCESS(status)) { 382 + return status; 383 + } 384 + 385 + status = RtlUnicodeStringPrintf(&compatId, L"%s\\%sFUNC_%02X&CTLR_VEN_%02X", 386 + prefix, funcPrefix, Desc->CodecIds.FuncId, Desc->CodecIds.CtlrVenId); 387 + if (!NT_SUCCESS(status)) { 388 + return status; 389 + } 390 + 391 + status = WdfPdoInitAddCompatibleID(DeviceInit, &compatId); 392 + if (!NT_SUCCESS(status)) { 393 + return status; 394 + } 395 + 396 + status = RtlUnicodeStringPrintf(&compatId, L"%s\\%sFUNC_%02X", 397 + prefix, funcPrefix, Desc->CodecIds.FuncId); 398 + if (!NT_SUCCESS(status)) { 399 + return status; 400 + } 401 + 402 + status = WdfPdoInitAddCompatibleID(DeviceInit, &compatId); 403 + if (!NT_SUCCESS(status)) { 404 + return status; 405 + } 406 + } 407 + } 408 + 409 + status = RtlUnicodeStringPrintf(&buffer, L"%02d", Desc->CodecIds.CodecAddress); 410 + if (!NT_SUCCESS(status)) { 411 + return status; 412 + } 413 + 414 + status = WdfPdoInitAssignInstanceID(DeviceInit, &buffer); 415 + if (!NT_SUCCESS(status)) { 416 + return status; 417 + } 418 + 419 + // 420 + // Provide a description about the device. This text is usually read from 421 + // the device. In the case of USB device, this text comes from the string 422 + // descriptor. This text is displayed momentarily by the PnP manager while 423 + // it's looking for a matching INF. If it finds one, it uses the Device 424 + // Description from the INF file or the friendly name created by 425 + // coinstallers to display in the device manager. FriendlyName takes 426 + // precedence over the DeviceDesc from the INF file. 427 + // 428 + if (Desc->CodecIds.IsDSP) { 429 + status = RtlUnicodeStringPrintf(&buffer, 430 + L"Intel Audio DSP"); 431 + } 432 + else { 433 + status = RtlUnicodeStringPrintf(&buffer, 434 + L"High Definition Audio Device"); 435 + } 436 + if (!NT_SUCCESS(status)) { 437 + return status; 438 + } 439 + 440 + // 441 + // You can call WdfPdoInitAddDeviceText multiple times, adding device 442 + // text for multiple locales. When the system displays the text, it 443 + // chooses the text that matches the current locale, if available. 444 + // Otherwise it will use the string for the default locale. 445 + // The driver can specify the driver's default locale by calling 446 + // WdfPdoInitSetDefaultLocale. 447 + // 448 + status = WdfPdoInitAddDeviceText(DeviceInit, 449 + &buffer, 450 + &deviceLocation, 451 + MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); 452 + if (!NT_SUCCESS(status)) { 453 + return status; 454 + } 455 + 456 + WdfPdoInitSetDefaultLocale(DeviceInit, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)); 457 + 458 + // 459 + // Initialize the attributes to specify the size of PDO device extension. 460 + // All the state information private to the PDO will be tracked here. 461 + // 462 + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, PDO_DEVICE_DATA); 463 + 464 + status = WdfDeviceCreate(&DeviceInit, &pdoAttributes, &hChild); 465 + if (!NT_SUCCESS(status)) { 466 + return status; 467 + } 468 + 469 + // 470 + // Get the device context. 471 + // 472 + pdoData = PdoGetData(hChild); 473 + 474 + pdoData->FdoContext = Desc->FdoContext; 475 + RtlCopyMemory(&pdoData->CodecIds, &Desc->CodecIds, sizeof(Desc->CodecIds)); 476 + 477 + if (!Desc->CodecIds.IsDSP) 478 + Desc->FdoContext->codecs[Desc->CodecIds.CodecAddress] = pdoData; 479 + 480 + // 481 + // Set some properties for the child device. 482 + // 483 + WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); 484 + pnpCaps.Removable = WdfFalse; 485 + pnpCaps.EjectSupported = Desc->CodecIds.IsGraphicsCodec ? WdfTrue : WdfFalse; 486 + pnpCaps.SurpriseRemovalOK = Desc->CodecIds.IsGraphicsCodec ? WdfTrue : WdfFalse; 487 + 488 + pnpCaps.Address = Desc->CodecIds.CodecAddress; 489 + pnpCaps.UINumber = Desc->CodecIds.CodecAddress; 490 + 491 + WdfDeviceSetPnpCapabilities(hChild, &pnpCaps); 492 + 493 + WDF_DEVICE_POWER_CAPABILITIES_INIT(&powerCaps); 494 + 495 + powerCaps.DeviceD1 = WdfTrue; 496 + powerCaps.WakeFromD1 = WdfTrue; 497 + powerCaps.DeviceWake = PowerDeviceD1; 498 + 499 + powerCaps.DeviceState[PowerSystemWorking] = PowerDeviceD1; 500 + powerCaps.DeviceState[PowerSystemSleeping1] = PowerDeviceD1; 501 + powerCaps.DeviceState[PowerSystemSleeping2] = PowerDeviceD2; 502 + powerCaps.DeviceState[PowerSystemSleeping3] = PowerDeviceD2; 503 + powerCaps.DeviceState[PowerSystemHibernate] = PowerDeviceD3; 504 + powerCaps.DeviceState[PowerSystemShutdown] = PowerDeviceD3; 505 + 506 + WdfDeviceSetPowerCapabilities(hChild, &powerCaps); 507 + 508 + if (Desc->CodecIds.IsDSP) { 509 + ADSP_BUS_INTERFACE busInterface = ADSP_BusInterface(pdoData); 510 + WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig, 511 + (PINTERFACE)&busInterface, 512 + &GUID_ADSP_BUS_INTERFACE, 513 + NULL); 514 + status = WdfDeviceAddQueryInterface(hChild, &qiConfig); 515 + } 516 + else { 517 + HDAUDIO_BUS_INTERFACE busInterface = HDA_BusInterface(pdoData); 518 + 519 + WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig, 520 + (PINTERFACE)&busInterface, 521 + &GUID_HDAUDIO_BUS_INTERFACE, 522 + NULL); 523 + 524 + status = WdfDeviceAddQueryInterface(hChild, &qiConfig); 525 + if (!NT_SUCCESS(status)) { 526 + return status; 527 + } 528 + 529 + HDAUDIO_BUS_INTERFACE_BDL busInterfaceBDL = HDA_BusInterfaceBDL(pdoData); 530 + WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig, 531 + (PINTERFACE)&busInterfaceBDL, 532 + &GUID_HDAUDIO_BUS_INTERFACE_BDL, 533 + NULL); 534 + status = WdfDeviceAddQueryInterface(hChild, &qiConfig); 535 + if (!NT_SUCCESS(status)) { 536 + return status; 537 + } 538 + 539 + HDAUDIO_BUS_INTERFACE_V2 busInterface2 = HDA_BusInterfaceV2(pdoData); 540 + WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig, 541 + (PINTERFACE)&busInterface2, 542 + &GUID_HDAUDIO_BUS_INTERFACE_V2, 543 + NULL); 544 + status = WdfDeviceAddQueryInterface(hChild, &qiConfig); 545 + if (!NT_SUCCESS(status)) { 546 + return status; 547 + } 548 + 549 + HDAUDIO_BUS_INTERFACE_V3 busInterface3 = HDA_BusInterfaceV3(pdoData); 550 + WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig, 551 + (PINTERFACE)&busInterface3, 552 + &GUID_HDAUDIO_BUS_INTERFACE_V3, 553 + NULL); 554 + status = WdfDeviceAddQueryInterface(hChild, &qiConfig); 555 + if (!NT_SUCCESS(status)) { 556 + return status; 557 + } 558 + } 559 + 560 + return status; 561 + }
+90
drivers/wdm/audio/hdaudbus_new/buspdo.h
··· 1 + #if !defined(_SKLHDAUDBUS_BUSPDO_H_) 2 + #define _SKLHDAUDBUS_BUSPDO_H_ 3 + 4 + #define MAX_INSTANCE_ID_LEN 80 5 + 6 + typedef struct _CODEC_UNSOLICITED_CALLBACK { 7 + BOOLEAN inUse; 8 + PVOID Context; 9 + PHDAUDIO_UNSOLICITED_RESPONSE_CALLBACK Routine; 10 + } CODEC_UNSOLICITED_CALLBACK, *PCODEC_UNSOLICIT_CALLBACK; 11 + 12 + typedef struct _CODEC_IDS { 13 + UINT32 CodecAddress; 14 + BOOL IsGraphicsCodec; 15 + 16 + UINT8 FunctionGroupStartNode; 17 + 18 + UINT16 CtlrDevId; 19 + UINT16 CtlrVenId; 20 + 21 + BOOL IsDSP; 22 + 23 + UINT16 FuncId; 24 + UINT16 VenId; 25 + UINT16 DevId; 26 + UINT32 SubsysId; 27 + UINT16 RevId; 28 + } CODEC_IDS, * PCODEC_IDS; 29 + 30 + typedef struct _PDO_IDENTIFICATION_DESCRIPTION 31 + { 32 + WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER Header; // should contain this header 33 + 34 + PFDO_CONTEXT FdoContext; 35 + 36 + CODEC_IDS CodecIds; 37 + 38 + } PDO_IDENTIFICATION_DESCRIPTION, * PPDO_IDENTIFICATION_DESCRIPTION; 39 + 40 + #define MAX_UNSOLICIT_CALLBACKS 64 // limit is 64 for hdaudbus (See: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/hdaudio/nc-hdaudio-pregister_event_callback) 41 + #define SUBTAG_MASK 0x3F 42 + #define TAG_ADDR_SHIFT 6 43 + 44 + // 45 + // This is PDO device-extension. 46 + // 47 + typedef struct _PDO_DEVICE_DATA 48 + { 49 + PFDO_CONTEXT FdoContext; 50 + 51 + CODEC_IDS CodecIds; 52 + 53 + CODEC_UNSOLICITED_CALLBACK unsolitCallbacks[MAX_UNSOLICIT_CALLBACKS]; 54 + 55 + } PDO_DEVICE_DATA, * PPDO_DEVICE_DATA; 56 + 57 + WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(PDO_DEVICE_DATA, PdoGetData) 58 + 59 + extern "C" { 60 + 61 + NTSTATUS NTAPI 62 + Bus_EvtChildListIdentificationDescriptionDuplicate( 63 + WDFCHILDLIST DeviceList, 64 + PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER SourceIdentificationDescription, 65 + PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER DestinationIdentificationDescription 66 + ); 67 + 68 + BOOLEAN NTAPI 69 + Bus_EvtChildListIdentificationDescriptionCompare( 70 + WDFCHILDLIST DeviceList, 71 + PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER FirstIdentificationDescription, 72 + PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER SecondIdentificationDescription 73 + ); 74 + 75 + VOID NTAPI 76 + Bus_EvtChildListIdentificationDescriptionCleanup( 77 + _In_ WDFCHILDLIST DeviceList, 78 + _Inout_ PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription 79 + ); 80 + 81 + NTSTATUS NTAPI 82 + Bus_EvtDeviceListCreatePdo( 83 + WDFCHILDLIST DeviceList, 84 + PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, 85 + PWDFDEVICE_INIT ChildInit 86 + ); 87 + 88 + } 89 + 90 + #endif
+104
drivers/wdm/audio/hdaudbus_new/driver.h
··· 1 + #if !defined(_SKLHDAUDBUS_H_) 2 + #define _SKLHDAUDBUS_H_ 3 + 4 + #define POOL_ZERO_DOWN_LEVEL_SUPPORT 5 + 6 + #pragma warning(disable:4200) // suppress nameless struct/union warning 7 + #pragma warning(disable:4201) // suppress nameless struct/union warning 8 + #pragma warning(disable:4214) // suppress bit field types other than int warning 9 + #include <ntddk.h> 10 + #include <initguid.h> 11 + 12 + //SGPC (Win10 1809+ support) 13 + extern "C" { 14 + #define __CPLUSPLUS 15 + 16 + #include <windef.h> 17 + #include <winerror.h> 18 + 19 + #include <wingdi.h> 20 + #include <d3dkmddi.h> 21 + #include <d3dkmthk.h> 22 + } 23 + 24 + #include <wdm.h> 25 + #include <wdmguid.h> 26 + #include <wdf.h> 27 + #include <ntintsafe.h> 28 + #include <ntstrsafe.h> 29 + #include <hdaudio.h> 30 + #include <portcls.h> 31 + 32 + #include "hda_registers.h" 33 + #include "fdo.h" 34 + #include "buspdo.h" 35 + #include "hdac_controller.h" 36 + #include "hdac_stream.h" 37 + #include "hda_verbs.h" 38 + 39 + #define DRIVERNAME "sklhdaudbus.sys: " 40 + #define SKLHDAUDBUS_POOL_TAG 'SADH' 41 + 42 + #define VEN_INTEL 0x8086 43 + #define VEN_ATI 0x1002 44 + #define VEN_AMD 0x1022 45 + #define VEN_NVIDIA 0x10DE 46 + #define VEN_VMWARE 0x15AD 47 + 48 + #include "regfuncs.h" 49 + 50 + NTSTATUS HDA_WaitForTransfer( 51 + PFDO_CONTEXT fdoCtx, 52 + UINT16 codecAddr, 53 + _In_ ULONG Count, 54 + _Inout_updates_(Count) 55 + PHDAUDIO_CODEC_TRANSFER CodecTransfer 56 + ); 57 + HDAUDIO_BUS_INTERFACE HDA_BusInterface(PVOID Context); 58 + HDAUDIO_BUS_INTERFACE_V2 HDA_BusInterfaceV2(PVOID Context); 59 + HDAUDIO_BUS_INTERFACE_V3 HDA_BusInterfaceV3(PVOID Context); 60 + HDAUDIO_BUS_INTERFACE_BDL HDA_BusInterfaceBDL(PVOID Context); 61 + 62 + #define IS_BXT(ven, dev) (ven == VEN_INTEL && dev == 0x5a98) 63 + 64 + static inline void mdelay(LONG msec) { 65 + LARGE_INTEGER Interval; 66 + Interval.QuadPart = -10 * 1000 * (LONGLONG)msec; 67 + KeDelayExecutionThread(KernelMode, FALSE, &Interval); 68 + } 69 + 70 + static inline void udelay(LONG usec) { 71 + LARGE_INTEGER Interval; 72 + Interval.QuadPart = -10 * (LONGLONG)usec; 73 + KeDelayExecutionThread(KernelMode, FALSE, &Interval); 74 + } 75 + 76 + // 77 + // Helper macros 78 + // 79 + 80 + #if DBG 81 + #define DEBUG_LEVEL_ERROR 1 82 + #define DEBUG_LEVEL_INFO 2 83 + #define DEBUG_LEVEL_VERBOSE 3 84 + 85 + #define DBG_INIT 1 86 + #define DBG_PNP 2 87 + #define DBG_IOCTL 4 88 + 89 + #define SklHdAudBusDebugLevel 100 90 + #define SklHdAudBusDebugCategories (DBG_INIT | DBG_PNP | DBG_IOCTL) 91 + 92 + #define SklHdAudBusPrint(dbglevel, dbgcategory, fmt, ...) { \ 93 + if (SklHdAudBusDebugLevel >= dbglevel && \ 94 + (SklHdAudBusDebugCategories & dbgcategory)) \ 95 + { \ 96 + DbgPrint(DRIVERNAME); \ 97 + DbgPrint(fmt, ##__VA_ARGS__); \ 98 + } \ 99 + } 100 + #else 101 + #define SklHdAudBusPrint(dbglevel, fmt, ...) { \ 102 + } 103 + #endif 104 + #endif
+851
drivers/wdm/audio/hdaudbus_new/fdo.cpp
··· 1 + #include "driver.h" 2 + #include "nhlt.h" 3 + #include "sof-tplg.h" 4 + 5 + EVT_WDF_DEVICE_PREPARE_HARDWARE Fdo_EvtDevicePrepareHardware; 6 + EVT_WDF_DEVICE_RELEASE_HARDWARE Fdo_EvtDeviceReleaseHardware; 7 + EVT_WDF_DEVICE_D0_ENTRY Fdo_EvtDeviceD0Entry; 8 + EVT_WDF_DEVICE_D0_ENTRY_POST_INTERRUPTS_ENABLED Fdo_EvtDeviceD0EntryPostInterrupts; 9 + EVT_WDF_DEVICE_D0_EXIT Fdo_EvtDeviceD0Exit; 10 + EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT Fdo_EvtDeviceSelfManagedIoInit; 11 + 12 + void CheckHDAGraphicsRegistryKeys(PFDO_CONTEXT fdoCtx); 13 + 14 + NTSTATUS 15 + NTAPI 16 + HDAGraphicsPowerInterfaceCallback( 17 + PVOID NotificationStruct, 18 + PVOID Context 19 + ); 20 + 21 + NTSTATUS 22 + NTAPI 23 + Fdo_Initialize( 24 + _In_ PFDO_CONTEXT FdoCtx 25 + ); 26 + 27 + NTSTATUS 28 + NTAPI 29 + Fdo_Create( 30 + _Inout_ PWDFDEVICE_INIT DeviceInit 31 + ) 32 + { 33 + WDF_CHILD_LIST_CONFIG config; 34 + WDF_OBJECT_ATTRIBUTES attributes; 35 + WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks; 36 + PFDO_CONTEXT fdoCtx; 37 + WDFDEVICE wdfDevice; 38 + NTSTATUS status; 39 + 40 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 41 + "%s\n", __func__); 42 + 43 + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks); 44 + pnpPowerCallbacks.EvtDevicePrepareHardware = Fdo_EvtDevicePrepareHardware; 45 + pnpPowerCallbacks.EvtDeviceReleaseHardware = Fdo_EvtDeviceReleaseHardware; 46 + pnpPowerCallbacks.EvtDeviceD0Entry = Fdo_EvtDeviceD0Entry; 47 + pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = Fdo_EvtDeviceD0EntryPostInterrupts; 48 + pnpPowerCallbacks.EvtDeviceD0Exit = Fdo_EvtDeviceD0Exit; 49 + pnpPowerCallbacks.EvtDeviceSelfManagedIoInit = Fdo_EvtDeviceSelfManagedIoInit; 50 + WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks); 51 + 52 + // 53 + // WDF_ DEVICE_LIST_CONFIG describes how the framework should handle 54 + // dynamic child enumeration on behalf of the driver writer. 55 + // Since we are a bus driver, we need to specify identification description 56 + // for our child devices. This description will serve as the identity of our 57 + // child device. Since the description is opaque to the framework, we 58 + // have to provide bunch of callbacks to compare, copy, or free 59 + // any other resources associated with the description. 60 + // 61 + WDF_CHILD_LIST_CONFIG_INIT(&config, 62 + sizeof(PDO_IDENTIFICATION_DESCRIPTION), 63 + Bus_EvtDeviceListCreatePdo // callback to create a child device. 64 + ); 65 + 66 + // 67 + // This function pointer will be called when the framework needs to copy a 68 + // identification description from one location to another. An implementation 69 + // of this function is only necessary if the description contains description 70 + // relative pointer values (like LIST_ENTRY for instance) . 71 + // If set to NULL, the framework will use RtlCopyMemory to copy an identification . 72 + // description. In this sample, it's not required to provide these callbacks. 73 + // they are added just for illustration. 74 + // 75 + config.EvtChildListIdentificationDescriptionDuplicate = 76 + Bus_EvtChildListIdentificationDescriptionDuplicate; 77 + 78 + // 79 + // This function pointer will be called when the framework needs to compare 80 + // two identificaiton descriptions. If left NULL a call to RtlCompareMemory 81 + // will be used to compare two identificaiton descriptions. 82 + // 83 + config.EvtChildListIdentificationDescriptionCompare = 84 + Bus_EvtChildListIdentificationDescriptionCompare; 85 + // 86 + // This function pointer will be called when the framework needs to free a 87 + // identification description. An implementation of this function is only 88 + // necessary if the description contains dynamically allocated memory 89 + // (by the driver writer) that needs to be freed. The actual identification 90 + // description pointer itself will be freed by the framework. 91 + // 92 + config.EvtChildListIdentificationDescriptionCleanup = 93 + Bus_EvtChildListIdentificationDescriptionCleanup; 94 + 95 + // 96 + // Tell the framework to use the built-in childlist to track the state 97 + // of the device based on the configuration we just created. 98 + // 99 + WdfFdoInitSetDefaultChildListConfig(DeviceInit, 100 + &config, 101 + WDF_NO_OBJECT_ATTRIBUTES); 102 + 103 + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, FDO_CONTEXT); 104 + status = WdfDeviceCreate(&DeviceInit, &attributes, &wdfDevice); 105 + if (!NT_SUCCESS(status)) { 106 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_INIT, 107 + "WdfDriverCreate failed %x\n", status); 108 + goto Exit; 109 + } 110 + 111 + /*{ 112 + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS IdleSettings; 113 + 114 + WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&IdleSettings, IdleCannotWakeFromS0); 115 + IdleSettings.IdleTimeoutType = SystemManagedIdleTimeoutWithHint; 116 + IdleSettings.IdleTimeout = 1000; 117 + IdleSettings.UserControlOfIdleSettings = IdleDoNotAllowUserControl; 118 + 119 + WdfDeviceAssignS0IdleSettings(wdfDevice, &IdleSettings); 120 + }*/ 121 + 122 + { 123 + WDF_DEVICE_STATE deviceState; 124 + WDF_DEVICE_STATE_INIT(&deviceState); 125 + 126 + deviceState.NotDisableable = WdfFalse; 127 + WdfDeviceSetDeviceState(wdfDevice, &deviceState); 128 + } 129 + 130 + fdoCtx = Fdo_GetContext(wdfDevice); 131 + fdoCtx->WdfDevice = wdfDevice; 132 + 133 + status = Fdo_Initialize(fdoCtx); 134 + if (!NT_SUCCESS(status)) 135 + { 136 + goto Exit; 137 + } 138 + 139 + CheckHDAGraphicsRegistryKeys(fdoCtx); 140 + 141 + Exit: 142 + return status; 143 + } 144 + 145 + NTSTATUS 146 + NTAPI 147 + Fdo_Initialize( 148 + _In_ PFDO_CONTEXT FdoCtx 149 + ) 150 + { 151 + NTSTATUS status; 152 + WDFDEVICE device; 153 + WDF_INTERRUPT_CONFIG interruptConfig; 154 + 155 + device = FdoCtx->WdfDevice; 156 + 157 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 158 + "%s\n", __func__); 159 + 160 + // 161 + // Create an interrupt object for hardware notifications 162 + // 163 + WDF_INTERRUPT_CONFIG_INIT( 164 + &interruptConfig, 165 + hda_interrupt, 166 + hda_dpc); 167 + 168 + status = WdfInterruptCreate( 169 + device, 170 + &interruptConfig, 171 + WDF_NO_OBJECT_ATTRIBUTES, 172 + &FdoCtx->Interrupt); 173 + 174 + if (!NT_SUCCESS(status)) 175 + { 176 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 177 + "Error creating WDF interrupt object - %!STATUS!", 178 + status); 179 + 180 + return status; 181 + } 182 + 183 + 184 + status = WdfWaitLockCreate(WDF_NO_OBJECT_ATTRIBUTES, &FdoCtx->GraphicsDevicesCollectionWaitLock); 185 + if (!NT_SUCCESS(status)) 186 + { 187 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 188 + "Error creating WDF wait lock - %!STATUS!", 189 + status); 190 + 191 + return status; 192 + } 193 + 194 + status = WdfCollectionCreate(WDF_NO_OBJECT_ATTRIBUTES, &FdoCtx->GraphicsDevicesCollection); 195 + 196 + if (!NT_SUCCESS(status)) 197 + { 198 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 199 + "Error creating WDF collection - %!STATUS!", 200 + status); 201 + 202 + return status; 203 + } 204 + 205 + return STATUS_SUCCESS; 206 + } 207 + 208 + NTSTATUS 209 + NTAPI 210 + Fdo_EvtDevicePrepareHardware( 211 + _In_ WDFDEVICE Device, 212 + _In_ WDFCMRESLIST ResourcesRaw, 213 + _In_ WDFCMRESLIST ResourcesTranslated 214 + ) 215 + { 216 + UNREFERENCED_PARAMETER(ResourcesRaw); 217 + 218 + BOOLEAN fBar0Found = FALSE; 219 + BOOLEAN fBar4Found = FALSE; 220 + NTSTATUS status; 221 + PFDO_CONTEXT fdoCtx; 222 + ULONG resourceCount; 223 + 224 + fdoCtx = Fdo_GetContext(Device); 225 + resourceCount = WdfCmResourceListGetCount(ResourcesTranslated); 226 + 227 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 228 + "%s\n", __func__); 229 + 230 + status = WdfFdoQueryForInterface(Device, &GUID_BUS_INTERFACE_STANDARD, (PINTERFACE)&fdoCtx->BusInterface, sizeof(BUS_INTERFACE_STANDARD), PCI_BUS_INTERFACE_STANDARD_VERSION, NULL); 231 + if (!NT_SUCCESS(status)) { 232 + return status; 233 + } 234 + 235 + for (ULONG i = 0; i < resourceCount; i++) 236 + { 237 + PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor; 238 + 239 + pDescriptor = WdfCmResourceListGetDescriptor( 240 + ResourcesTranslated, i); 241 + 242 + switch (pDescriptor->Type) 243 + { 244 + case CmResourceTypeMemory: 245 + //Look for BAR0 and BAR4 246 + if (fBar0Found == FALSE) { 247 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 248 + "Found BAR0: 0x%llx (size 0x%lx)\n", pDescriptor->u.Memory.Start.QuadPart, pDescriptor->u.Memory.Length); 249 + 250 + fdoCtx->m_BAR0.Base.Base = MmMapIoSpace(pDescriptor->u.Memory.Start, pDescriptor->u.Memory.Length, MmNonCached); 251 + fdoCtx->m_BAR0.Len = pDescriptor->u.Memory.Length; 252 + 253 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 254 + "Mapped to %p\n", fdoCtx->m_BAR0.Base.baseptr); 255 + fBar0Found = TRUE; 256 + } 257 + else if (fBar4Found == FALSE) { 258 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 259 + "Found BAR4: 0x%llx (size 0x%lx)\n", pDescriptor->u.Memory.Start.QuadPart, pDescriptor->u.Memory.Length); 260 + 261 + //BAR4 is an optional ADSP memory mapping 262 + fdoCtx->m_BAR4.Base.Base = MmMapIoSpace(pDescriptor->u.Memory.Start, pDescriptor->u.Memory.Length, MmNonCached); 263 + fdoCtx->m_BAR4.Len = pDescriptor->u.Memory.Length; 264 + 265 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 266 + "Mapped to %p\n", fdoCtx->m_BAR4.Base.baseptr); 267 + fBar4Found = TRUE; 268 + } 269 + break; 270 + } 271 + } 272 + 273 + if (fdoCtx->m_BAR0.Base.Base == NULL) { 274 + status = STATUS_NOT_FOUND; //BAR0 is required 275 + return status; 276 + } 277 + 278 + fdoCtx->BusInterface.GetBusData(fdoCtx->BusInterface.Context, PCI_WHICHSPACE_CONFIG, &fdoCtx->venId, FIELD_OFFSET(PCI_COMMON_HEADER, VendorID), sizeof(UINT16)); 279 + fdoCtx->BusInterface.GetBusData(fdoCtx->BusInterface.Context, PCI_WHICHSPACE_CONFIG, &fdoCtx->devId, FIELD_OFFSET(PCI_COMMON_HEADER, DeviceID), sizeof(UINT16)); 280 + fdoCtx->BusInterface.GetBusData(fdoCtx->BusInterface.Context, PCI_WHICHSPACE_CONFIG, &fdoCtx->revId, FIELD_OFFSET(PCI_COMMON_HEADER, RevisionID), sizeof(UINT8)); 281 + 282 + //mlcap & lctl (hda_intel_init_chip) 283 + if (fdoCtx->venId == VEN_INTEL) { 284 + //read bus capabilities 285 + 286 + unsigned int cur_cap; 287 + unsigned int offset; 288 + unsigned int counter = 0; 289 + 290 + offset = hda_read16(fdoCtx, LLCH); 291 + 292 + #define HDAC_MAX_CAPS 10 293 + 294 + /* Lets walk the linked capabilities list */ 295 + do { 296 + cur_cap = read32(fdoCtx->m_BAR0.Base.baseptr + offset); 297 + 298 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 299 + "Capability version: 0x%x\n", 300 + (cur_cap & HDA_CAP_HDR_VER_MASK) >> HDA_CAP_HDR_VER_OFF); 301 + 302 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 303 + "HDA capability ID: 0x%x\n", 304 + (cur_cap & HDA_CAP_HDR_ID_MASK) >> HDA_CAP_HDR_ID_OFF); 305 + 306 + if (cur_cap == (unsigned int)-1) { 307 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 308 + "Invalid capability reg read\n"); 309 + break; 310 + } 311 + 312 + switch ((cur_cap & HDA_CAP_HDR_ID_MASK) >> HDA_CAP_HDR_ID_OFF) { 313 + case HDA_ML_CAP_ID: 314 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 315 + "Found ML capability\n"); 316 + fdoCtx->mlcap = fdoCtx->m_BAR0.Base.baseptr + offset; 317 + break; 318 + 319 + case HDA_GTS_CAP_ID: 320 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 321 + "Found GTS capability offset=%x\n", offset); 322 + break; 323 + 324 + case HDA_PP_CAP_ID: 325 + /* PP capability found, the Audio DSP is present */ 326 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 327 + "Found PP capability offset=%x\n", offset); 328 + fdoCtx->ppcap = fdoCtx->m_BAR0.Base.baseptr + offset; 329 + break; 330 + 331 + case HDA_SPB_CAP_ID: 332 + /* SPIB capability found, handler function */ 333 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 334 + "Found SPB capability\n"); 335 + fdoCtx->spbcap = fdoCtx->m_BAR0.Base.baseptr + offset; 336 + break; 337 + 338 + case HDA_DRSM_CAP_ID: 339 + /* DMA resume capability found, handler function */ 340 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 341 + "Found DRSM capability\n"); 342 + break; 343 + 344 + default: 345 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Unknown capability %d\n", cur_cap); 346 + cur_cap = 0; 347 + break; 348 + } 349 + 350 + counter++; 351 + 352 + if (counter > HDAC_MAX_CAPS) { 353 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "We exceeded HDAC capabilities!!!\n"); 354 + break; 355 + } 356 + 357 + /* read the offset of next capability */ 358 + offset = cur_cap & HDA_CAP_HDR_NXT_PTR_MASK; 359 + 360 + } while (offset); 361 + } 362 + 363 + status = GetHDACapabilities(fdoCtx); 364 + if (!NT_SUCCESS(status)) { 365 + return status; 366 + } 367 + 368 + fdoCtx->streams = (PHDAC_STREAM)ExAllocatePoolZero(NonPagedPool, sizeof(HDAC_STREAM) * fdoCtx->numStreams, SKLHDAUDBUS_POOL_TAG); 369 + if (!fdoCtx->streams) { 370 + return STATUS_NO_MEMORY; 371 + } 372 + 373 + PHYSICAL_ADDRESS maxAddr; 374 + maxAddr.QuadPart = fdoCtx->is64BitOK ? MAXULONG64 : MAXULONG32; 375 + 376 + fdoCtx->posbuf = MmAllocateContiguousMemory(PAGE_SIZE, maxAddr); 377 + if (!fdoCtx->posbuf) { 378 + return STATUS_NO_MEMORY; 379 + } 380 + 381 + RtlZeroMemory(fdoCtx->posbuf, PAGE_SIZE); 382 + 383 + fdoCtx->rb = (UINT8 *)MmAllocateContiguousMemory(PAGE_SIZE, maxAddr); 384 + if (!fdoCtx->rb) { 385 + return STATUS_NO_MEMORY; 386 + } 387 + 388 + RtlZeroMemory(fdoCtx->rb, PAGE_SIZE); 389 + 390 + //Init Streams 391 + { 392 + UINT8 i; 393 + UINT8 streamTags[2] = { 0, 0 }; 394 + 395 + for (i = 0; i < fdoCtx->numStreams; i++) { 396 + int isCapture = (i >= fdoCtx->captureIndexOff && 397 + i < fdoCtx->captureIndexOff + fdoCtx->captureStreams); 398 + /* stream tag must be unique throughout 399 + * the stream direction group, 400 + * valid values 1...15 401 + * use separate stream tag 402 + */ 403 + UINT8 tag = ++streamTags[isCapture]; 404 + 405 + { 406 + UINT64 idx = i; 407 + 408 + PHDAC_STREAM stream = &fdoCtx->streams[i]; 409 + stream->FdoContext = fdoCtx; 410 + /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ 411 + stream->sdAddr = fdoCtx->m_BAR0.Base.baseptr + (0x20 * idx + 0x80); 412 + /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */ 413 + stream->int_sta_mask = 1 << i; 414 + stream->idx = i; 415 + if (fdoCtx->venId == VEN_INTEL) 416 + stream->streamTag = tag; 417 + else 418 + stream->streamTag = i + 1; 419 + 420 + stream->posbuf = (UINT32 *)(((UINT8 *)fdoCtx->posbuf) + (idx * 8)); 421 + 422 + stream->spib_addr = NULL; 423 + if (fdoCtx->spbcap) { 424 + stream->spib_addr = fdoCtx->spbcap + HDA_SPB_BASE + (HDA_SPB_INTERVAL * idx) + HDA_SPB_SPIB; 425 + } 426 + 427 + stream->bdl = (PHDAC_BDLENTRY)MmAllocateContiguousMemory(BDL_SIZE, maxAddr); 428 + if (stream->bdl) { 429 + RtlZeroMemory(stream->bdl, BDL_SIZE); 430 + } 431 + } 432 + 433 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 434 + "Stream tag (idx %d): %d\n", i, tag); 435 + } 436 + } 437 + 438 + fdoCtx->nhlt = NULL; 439 + fdoCtx->nhltSz = 0; 440 + 441 + { //Check NHLT for Intel SST 442 + NTSTATUS status2 = NHLTCheckSupported(Device); 443 + if (NT_SUCCESS(status2)) { 444 + UINT64 nhltAddr; 445 + UINT64 nhltSz; 446 + 447 + status2 = NHLTQueryTableAddress(Device, &nhltAddr, &nhltSz); 448 + 449 + if (NT_SUCCESS(status2)) { 450 + PHYSICAL_ADDRESS nhltBaseAddr; 451 + nhltBaseAddr.QuadPart = nhltAddr; 452 + 453 + if (nhltAddr != 0 && nhltSz != 0) { 454 + fdoCtx->nhlt = MmMapIoSpace(nhltBaseAddr, nhltSz, MmCached); 455 + if (!fdoCtx->nhlt) { 456 + return STATUS_NO_MEMORY; 457 + } 458 + fdoCtx->nhltSz = nhltSz; 459 + } 460 + } 461 + } 462 + } 463 + 464 + fdoCtx->sofTplg = NULL; 465 + fdoCtx->sofTplgSz = 0; 466 + 467 + { //Check topology for Intel SOF 468 + SOF_TPLG sofTplg = { 0 }; 469 + NTSTATUS status2 = GetSOFTplg(Device, &sofTplg); 470 + if (NT_SUCCESS(status2) && sofTplg.magic == SOFTPLG_MAGIC) { 471 + fdoCtx->sofTplg = ExAllocatePoolUninitialized(NonPagedPool, sofTplg.length, SKLHDAUDBUS_POOL_TAG); 472 + RtlCopyMemory(fdoCtx->sofTplg, &sofTplg, sofTplg.length); 473 + fdoCtx->sofTplgSz = sofTplg.length; 474 + } 475 + } 476 + 477 + status = STATUS_SUCCESS; 478 + 479 + return status; 480 + } 481 + 482 + NTSTATUS 483 + NTAPI 484 + Fdo_EvtDeviceReleaseHardware( 485 + _In_ WDFDEVICE Device, 486 + _In_ WDFCMRESLIST ResourcesTranslated 487 + ) 488 + { 489 + PFDO_CONTEXT fdoCtx; 490 + 491 + UNREFERENCED_PARAMETER(ResourcesTranslated); 492 + 493 + fdoCtx = Fdo_GetContext(Device); 494 + 495 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 496 + "%s\n", __func__); 497 + 498 + if (fdoCtx->GraphicsDevicesCollection) { 499 + for (ULONG i = 0; i < WdfCollectionGetCount(fdoCtx->GraphicsDevicesCollection); i++) { 500 + WDFIOTARGET ioTarget = (WDFIOTARGET)WdfCollectionGetItem(fdoCtx->GraphicsDevicesCollection, i); 501 + PGRAPHICSIOTARGET_CONTEXT ioTargetContext = GraphicsIoTarget_GetContext(ioTarget); 502 + 503 + if (ioTargetContext->graphicsPowerRegisterOutput.DeviceHandle && ioTargetContext->graphicsPowerRegisterOutput.UnregisterCb) { 504 + NTSTATUS status = ioTargetContext->graphicsPowerRegisterOutput.UnregisterCb(ioTargetContext->graphicsPowerRegisterOutput.DeviceHandle, fdoCtx); 505 + if (!NT_SUCCESS(status)) { 506 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Warning: unregister failed with status 0x%x\n", status); 507 + } 508 + } 509 + } 510 + } 511 + 512 + if (fdoCtx->GraphicsNotificationHandle) { 513 + IoUnregisterPlugPlayNotification(fdoCtx->GraphicsNotificationHandle); 514 + } 515 + 516 + if (fdoCtx->nhlt) { 517 + MmUnmapIoSpace(fdoCtx->nhlt, fdoCtx->nhltSz); 518 + fdoCtx->nhlt = NULL; 519 + } 520 + 521 + if (fdoCtx->sofTplg) 522 + ExFreePoolWithTag(fdoCtx->sofTplg, SKLHDAUDBUS_POOL_TAG); 523 + 524 + if (fdoCtx->posbuf) 525 + MmFreeContiguousMemory(fdoCtx->posbuf); 526 + if (fdoCtx->rb) 527 + MmFreeContiguousMemory(fdoCtx->rb); 528 + 529 + if (fdoCtx->streams) { 530 + for (UINT32 i = 0; i < fdoCtx->numStreams; i++) { 531 + PHDAC_STREAM stream = &fdoCtx->streams[i]; 532 + if (stream->bdl) { 533 + MmFreeContiguousMemory(stream->bdl); 534 + stream->bdl = NULL; 535 + } 536 + } 537 + 538 + ExFreePoolWithTag(fdoCtx->streams, SKLHDAUDBUS_POOL_TAG); 539 + } 540 + 541 + if (fdoCtx->m_BAR0.Base.Base) { 542 + MmUnmapIoSpace(fdoCtx->m_BAR0.Base.Base, fdoCtx->m_BAR0.Len); 543 + fdoCtx->m_BAR0.Base.Base = NULL; 544 + } 545 + if (fdoCtx->m_BAR4.Base.Base) { 546 + MmUnmapIoSpace(fdoCtx->m_BAR4.Base.Base, fdoCtx->m_BAR4.Len); 547 + fdoCtx->m_BAR4.Base.Base = NULL; 548 + } 549 + 550 + return STATUS_SUCCESS; 551 + } 552 + 553 + #define ENABLE_HDA 1 554 + 555 + NTSTATUS 556 + NTAPI 557 + Fdo_EvtDeviceD0Entry( 558 + _In_ WDFDEVICE Device, 559 + _In_ WDF_POWER_DEVICE_STATE PreviousState 560 + ) 561 + { 562 + UNREFERENCED_PARAMETER(PreviousState); 563 + 564 + NTSTATUS status; 565 + PFDO_CONTEXT fdoCtx; 566 + 567 + fdoCtx = Fdo_GetContext(Device); 568 + 569 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 570 + "%s\n", __func__); 571 + 572 + status = STATUS_SUCCESS; 573 + 574 + if (fdoCtx->venId == VEN_INTEL) { 575 + UINT32 val; 576 + pci_read_cfg_dword(&fdoCtx->BusInterface, INTEL_HDA_CGCTL, &val); 577 + val = val & ~INTEL_HDA_CGCTL_MISCBDCGE; 578 + pci_write_cfg_dword(&fdoCtx->BusInterface, INTEL_HDA_CGCTL, val); 579 + } 580 + else if (fdoCtx->venId == VEN_AMD || fdoCtx->venId == VEN_ATI) { 581 + update_pci_byte(&fdoCtx->BusInterface, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, 0x07, ATI_SB450_HDAUDIO_ENABLE_SNOOP); 582 + } 583 + else if (fdoCtx->venId == VEN_NVIDIA) { 584 + update_pci_byte(&fdoCtx->BusInterface, NVIDIA_HDA_TRANSREG_ADDR, 0x0f, NVIDIA_HDA_ENABLE_COHBIT); 585 + update_pci_byte(&fdoCtx->BusInterface, NVIDIA_HDA_ISTRM_COH, 0x01, NVIDIA_HDA_ENABLE_COHBIT); 586 + update_pci_byte(&fdoCtx->BusInterface, NVIDIA_HDA_OSTRM_COH, 0x01, NVIDIA_HDA_ENABLE_COHBIT); 587 + } 588 + 589 + //Reset CORB / RIRB 590 + RtlZeroMemory(&fdoCtx->corb, sizeof(fdoCtx->corb)); 591 + RtlZeroMemory(&fdoCtx->rirb, sizeof(fdoCtx->rirb)); 592 + fdoCtx->processRirb = FALSE; 593 + 594 + status = StartHDAController(fdoCtx); 595 + 596 + if (fdoCtx->venId == VEN_INTEL) { 597 + UINT32 val; 598 + pci_read_cfg_dword(&fdoCtx->BusInterface, INTEL_HDA_CGCTL, &val); 599 + val = val | INTEL_HDA_CGCTL_MISCBDCGE; 600 + pci_write_cfg_dword(&fdoCtx->BusInterface, INTEL_HDA_CGCTL, val); 601 + 602 + hda_update32(fdoCtx, VS_EM2, HDA_VS_EM2_DUM, HDA_VS_EM2_DUM); 603 + } 604 + 605 + if (!NT_SUCCESS(status)) { 606 + return status; 607 + } 608 + 609 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 610 + "hda bus initialized\n"); 611 + 612 + return status; 613 + } 614 + 615 + NTSTATUS 616 + NTAPI 617 + Fdo_EvtDeviceD0EntryPostInterrupts( 618 + _In_ WDFDEVICE Device, 619 + _In_ WDF_POWER_DEVICE_STATE PreviousState 620 + ) 621 + { 622 + UNREFERENCED_PARAMETER(PreviousState); 623 + 624 + NTSTATUS status; 625 + PFDO_CONTEXT fdoCtx; 626 + 627 + status = STATUS_SUCCESS; 628 + fdoCtx = Fdo_GetContext(Device); 629 + 630 + #if ENABLE_HDA 631 + for (UINT8 addr = 0; addr < HDA_MAX_CODECS; addr++) { 632 + KeInitializeEvent(&fdoCtx->rirb.xferEvent[addr], NotificationEvent, FALSE); 633 + if (((fdoCtx->codecMask >> addr) & 0x1) == 0) 634 + continue; 635 + 636 + if (fdoCtx->UseSGPCCodec && fdoCtx->GraphicsCodecAddress == addr) 637 + continue; 638 + 639 + UINT32 cmdTmpl = (addr << 28) | (AC_NODE_ROOT << 20) | 640 + (AC_VERB_PARAMETERS << 8); 641 + 642 + ULONG vendorDevice; 643 + if (!NT_SUCCESS(RunSingleHDACmd(fdoCtx, cmdTmpl | AC_PAR_VENDOR_ID, &vendorDevice))) { //Some codecs might need a kickstart 644 + //First attempt failed. Retry 645 + NTSTATUS status2 = RunSingleHDACmd(fdoCtx, cmdTmpl | AC_PAR_VENDOR_ID, &vendorDevice); //If this fails, something is wrong. 646 + if (!NT_SUCCESS(status2)) { 647 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Warning: Failed to wake up codec %d: 0x%x", addr, status2); 648 + } 649 + } 650 + } 651 + #endif 652 + 653 + return status; 654 + } 655 + 656 + NTSTATUS 657 + NTAPI 658 + Fdo_EvtDeviceD0Exit( 659 + _In_ WDFDEVICE Device, 660 + _In_ WDF_POWER_DEVICE_STATE TargetState 661 + ) 662 + { 663 + UNREFERENCED_PARAMETER(TargetState); 664 + 665 + NTSTATUS status; 666 + PFDO_CONTEXT fdoCtx; 667 + 668 + fdoCtx = Fdo_GetContext(Device); 669 + 670 + status = StopHDAController(fdoCtx); 671 + 672 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 673 + "%s\n", __func__); 674 + 675 + return status; 676 + } 677 + 678 + void 679 + NTAPI 680 + Fdo_EnumerateCodec( 681 + PFDO_CONTEXT fdoCtx, 682 + UINT8 addr 683 + ) 684 + { 685 + UINT32 cmdTmpl = (addr << 28) | (AC_NODE_ROOT << 20) | 686 + (AC_VERB_PARAMETERS << 8); 687 + ULONG funcType = 0, vendorDevice, subsysId, revId, nodeCount; 688 + if (!NT_SUCCESS(RunSingleHDACmd(fdoCtx, cmdTmpl | AC_PAR_VENDOR_ID, &vendorDevice))) { 689 + return; 690 + } 691 + if (!NT_SUCCESS(RunSingleHDACmd(fdoCtx, cmdTmpl | AC_PAR_REV_ID, &revId))) { 692 + return; 693 + } 694 + if (!NT_SUCCESS(RunSingleHDACmd(fdoCtx, cmdTmpl | AC_PAR_NODE_COUNT, &nodeCount))) { 695 + return; 696 + } 697 + 698 + fdoCtx->numCodecs += 1; 699 + 700 + UINT8 startID = (nodeCount >> 16) & 0xFF; 701 + nodeCount = (nodeCount & 0x7FFF); 702 + 703 + UINT16 mainFuncGrp = 0; 704 + { 705 + UINT16 nid = startID; 706 + for (UINT32 i = 0; i < nodeCount; i++, nid++) { 707 + UINT32 cmd = (addr << 28) | (nid << 20) | 708 + (AC_VERB_PARAMETERS << 8) | AC_PAR_FUNCTION_TYPE; 709 + if (!NT_SUCCESS(RunSingleHDACmd(fdoCtx, cmd, &funcType))) { 710 + continue; 711 + } 712 + switch (funcType & 0xFF) { 713 + case AC_GRP_AUDIO_FUNCTION: 714 + case AC_GRP_MODEM_FUNCTION: 715 + mainFuncGrp = nid; 716 + break; 717 + } 718 + } 719 + } 720 + 721 + UINT32 cmd = (addr << 28) | (mainFuncGrp << 20) | 722 + (AC_VERB_GET_SUBSYSTEM_ID << 8); 723 + RunSingleHDACmd(fdoCtx, cmd, &subsysId); 724 + 725 + PDO_IDENTIFICATION_DESCRIPTION description; 726 + // 727 + // Initialize the description with the information about the detected codec. 728 + // 729 + WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT( 730 + &description.Header, 731 + sizeof(description) 732 + ); 733 + 734 + description.FdoContext = fdoCtx; 735 + 736 + description.CodecIds.CtlrDevId = fdoCtx->devId; 737 + description.CodecIds.CtlrVenId = fdoCtx->venId; 738 + 739 + description.CodecIds.CodecAddress = addr; 740 + if (fdoCtx->UseSGPCCodec && addr == fdoCtx->GraphicsCodecAddress) 741 + description.CodecIds.IsGraphicsCodec = TRUE; 742 + else 743 + description.CodecIds.IsGraphicsCodec = FALSE; 744 + 745 + description.CodecIds.FunctionGroupStartNode = startID; 746 + 747 + description.CodecIds.IsDSP = FALSE; 748 + 749 + description.CodecIds.FuncId = funcType & 0xFF; 750 + description.CodecIds.VenId = (vendorDevice >> 16) & 0xFFFF; 751 + description.CodecIds.DevId = vendorDevice & 0xFFFF; 752 + description.CodecIds.SubsysId = subsysId; 753 + description.CodecIds.RevId = (revId >> 8) & 0xFFFF; 754 + 755 + // 756 + // Call the framework to add this child to the childlist. This call 757 + // will internaly call our DescriptionCompare callback to check 758 + // whether this device is a new device or existing device. If 759 + // it's a new device, the framework will call DescriptionDuplicate to create 760 + // a copy of this description in nonpaged pool. 761 + // The actual creation of the child device will happen when the framework 762 + // receives QUERY_DEVICE_RELATION request from the PNP manager in 763 + // response to InvalidateDeviceRelations call made as part of adding 764 + // a new child. 765 + // 766 + WdfChildListAddOrUpdateChildDescriptionAsPresent( 767 + WdfFdoGetDefaultChildList(fdoCtx->WdfDevice), &description.Header, 768 + NULL); // AddressDescription 769 + } 770 + 771 + NTSTATUS 772 + NTAPI 773 + Fdo_EvtDeviceSelfManagedIoInit( 774 + _In_ WDFDEVICE Device 775 + ) 776 + { 777 + NTSTATUS status = STATUS_SUCCESS; 778 + PFDO_CONTEXT fdoCtx; 779 + 780 + fdoCtx = Fdo_GetContext(Device); 781 + 782 + WdfChildListBeginScan(WdfFdoGetDefaultChildList(Device)); 783 + 784 + fdoCtx->numCodecs = 0; 785 + #if ENABLE_HDA 786 + for (UINT8 addr = 0; addr < HDA_MAX_CODECS; addr++) { 787 + fdoCtx->codecs[addr] = NULL; 788 + if (((fdoCtx->codecMask >> addr) & 0x1) == 0) 789 + continue; 790 + 791 + if (fdoCtx->UseSGPCCodec && fdoCtx->GraphicsCodecAddress == addr) 792 + continue; 793 + 794 + Fdo_EnumerateCodec(fdoCtx, addr); 795 + } 796 + 797 + if (fdoCtx->mlcap) { 798 + IoRegisterPlugPlayNotification( 799 + EventCategoryDeviceInterfaceChange, 800 + PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, 801 + (PVOID)&GUID_DEVINTERFACE_GRAPHICSPOWER, 802 + WdfDriverWdmGetDriverObject(WdfDeviceGetDriver(fdoCtx->WdfDevice)), 803 + HDAGraphicsPowerInterfaceCallback, 804 + (PVOID)fdoCtx, 805 + &fdoCtx->GraphicsNotificationHandle 806 + ); 807 + 808 + } 809 + #endif 810 + 811 + fdoCtx->dspInterruptCallback = NULL; 812 + if (fdoCtx->m_BAR4.Base.Base) { //Populate ADSP if present 813 + PDO_IDENTIFICATION_DESCRIPTION description; 814 + // 815 + // Initialize the description with the information about the detected codec. 816 + // 817 + WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT( 818 + &description.Header, 819 + sizeof(description) 820 + ); 821 + 822 + description.FdoContext = fdoCtx; 823 + 824 + description.CodecIds.CtlrDevId = fdoCtx->devId; 825 + description.CodecIds.CtlrVenId = fdoCtx->venId; 826 + 827 + description.CodecIds.CodecAddress = 0x10000000; 828 + description.CodecIds.IsDSP = TRUE; 829 + 830 + // 831 + // Call the framework to add this child to the childlist. This call 832 + // will internaly call our DescriptionCompare callback to check 833 + // whether this device is a new device or existing device. If 834 + // it's a new device, the framework will call DescriptionDuplicate to create 835 + // a copy of this description in nonpaged pool. 836 + // The actual creation of the child device will happen when the framework 837 + // receives QUERY_DEVICE_RELATION request from the PNP manager in 838 + // response to InvalidateDeviceRelations call made as part of adding 839 + // a new child. 840 + // 841 + status = WdfChildListAddOrUpdateChildDescriptionAsPresent( 842 + WdfFdoGetDefaultChildList(Device), &description.Header, 843 + NULL); // AddressDescription 844 + } 845 + 846 + WdfChildListEndScan(WdfFdoGetDefaultChildList(Device)); 847 + 848 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 849 + "hda scan complete\n"); 850 + return status; 851 + }
+179
drivers/wdm/audio/hdaudbus_new/fdo.h
··· 1 + #if !defined(_SKLHDAUDBUS_FDO_H_) 2 + #define _SKLHDAUDBUS_FDO_H_ 3 + 4 + union baseaddr { 5 + PVOID Base; 6 + UINT8* baseptr; 7 + }; 8 + 9 + typedef struct _PCI_BAR { 10 + union baseaddr Base; 11 + ULONG Len; 12 + } PCI_BAR, * PPCI_BAR; 13 + 14 + #include "adsp.h" 15 + 16 + #define HDA_UNSOL_QUEUE_SIZE 64 17 + #define MAX_NOTIF_EVENTS 16 18 + #define HDA_MAX_CODECS 16 /* limit by controller side */ 19 + 20 + struct _FDO_CONTEXT; 21 + struct _PDO_DEVICE_DATA; 22 + 23 + typedef struct _HDAC_STREAM_CALLBACK { 24 + BOOLEAN InUse; 25 + PDEVICE_OBJECT Fdo; 26 + PHDAUDIO_DMA_NOTIFICATION_CALLBACK NotificationCallback; 27 + PVOID CallbackContext; 28 + } HDAC_STREAM_CALLBACK, *PHDAC_STREAM_CALLBACK; 29 + 30 + typedef struct _HDAC_ISR_CALLBACK { 31 + BOOLEAN IOC; 32 + PHDAUDIO_BDL_ISR IsrCallback; 33 + PVOID CallbackContext; 34 + } HDAC_ISR_CALLBACK, *PHDAC_ISR_CALLBACK; 35 + 36 + typedef struct _HDAC_BDLENTRY { 37 + UINT32 lowAddr; 38 + UINT32 highAddr; 39 + UINT32 len; 40 + UINT32 ioc; 41 + } HDAC_BDLENTRY, *PHDAC_BDLENTRY; 42 + 43 + typedef struct _HDAC_STREAM { 44 + struct _FDO_CONTEXT* FdoContext; 45 + struct _PDO_DEVICE_DATA* PdoContext; 46 + 47 + PMDL mdlBuf; 48 + UINT32* posbuf; 49 + 50 + PVOID dmaBuf; 51 + HDAC_BDLENTRY* bdl; 52 + 53 + BOOLEAN stripe; 54 + 55 + UINT32 bufSz; 56 + UINT32 periodBytes; 57 + UINT32 fifoSize; 58 + UINT16 numBlocks; 59 + 60 + UINT8* sdAddr; 61 + UINT32 int_sta_mask; 62 + 63 + UINT8* spib_addr; //spbcap 64 + 65 + UINT8 streamTag; 66 + UINT8 idx; 67 + 68 + HDAUDIO_STREAM_FORMAT streamFormat; 69 + 70 + PKEVENT registeredEvents[MAX_NOTIF_EVENTS]; 71 + HDAC_STREAM_CALLBACK registeredCallbacks[MAX_NOTIF_EVENTS]; 72 + 73 + HDAC_ISR_CALLBACK isr; 74 + 75 + BOOLEAN running; 76 + BOOLEAN irqReceived; 77 + } HDAC_STREAM, *PHDAC_STREAM; 78 + 79 + typedef struct _HDAC_RIRB { 80 + UINT32 response; 81 + UINT32 response_ex; 82 + } HDAC_RIRB, *PHDAC_RIRB; 83 + 84 + typedef struct _HDAC_CODEC_XFER { 85 + PHDAUDIO_CODEC_TRANSFER xfer[HDA_MAX_CORB_ENTRIES]; 86 + } HDAC_CODEC_XFER, *PHDAC_CODEC_XFER; 87 + 88 + typedef struct _HDAC_RB { 89 + union { 90 + UINT32* buf; 91 + PHDAC_RIRB rirbbuf; 92 + }; 93 + PHYSICAL_ADDRESS addr; 94 + UINT16 rp, wp; 95 + LONG cmds[HDA_MAX_CODECS]; 96 + KEVENT xferEvent[HDA_MAX_CODECS]; 97 + HDAC_CODEC_XFER xfer[HDA_MAX_CODECS]; 98 + } HDAC_RB, *PHDAC_RB; 99 + 100 + typedef struct _GRAPHICSWORKITEM_CONTEXT { 101 + struct _FDO_CONTEXT* FdoContext; 102 + UNICODE_STRING GPUDeviceSymlink; 103 + } GRAPHICSWORKITEM_CONTEXT, *PGRAPHICSWORKITEM_CONTEXT; 104 + 105 + WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(GRAPHICSWORKITEM_CONTEXT, GraphicsWorkitem_GetContext) 106 + 107 + typedef struct _GRAPHICSIOTARGET_CONTEXT { 108 + struct _FDO_CONTEXT* FdoContext; 109 + DXGK_GRAPHICSPOWER_REGISTER_OUTPUT graphicsPowerRegisterOutput; 110 + } GRAPHICSIOTARGET_CONTEXT, *PGRAPHICSIOTARGET_CONTEXT; 111 + WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(GRAPHICSIOTARGET_CONTEXT, GraphicsIoTarget_GetContext) 112 + 113 + typedef struct _FDO_CONTEXT 114 + { 115 + WDFDEVICE WdfDevice; 116 + 117 + UINT16 venId; 118 + UINT16 devId; 119 + UINT8 revId; 120 + 121 + PCI_BAR m_BAR0; //required 122 + PCI_BAR m_BAR4; //Intel AudioDSP 123 + BUS_INTERFACE_STANDARD BusInterface; //PCI Bus Interface 124 + WDFINTERRUPT Interrupt; 125 + 126 + //Graphics Notifications 127 + PVOID GraphicsNotificationHandle; 128 + WDFWAITLOCK GraphicsDevicesCollectionWaitLock; 129 + WDFCOLLECTION GraphicsDevicesCollection; 130 + ULONG GraphicsCodecAddress; 131 + BOOLEAN UseSGPCCodec; 132 + BOOLEAN GraphicsCodecConnected; 133 + 134 + UINT8 *mlcap; 135 + UINT8 *ppcap; 136 + UINT8 *spbcap; 137 + 138 + BOOLEAN ControllerEnabled; 139 + 140 + BOOLEAN is64BitOK; 141 + UINT16 hwVersion; 142 + 143 + UINT32 captureIndexOff; 144 + UINT32 playbackIndexOff; 145 + UINT32 captureStreams; 146 + UINT32 playbackStreams; 147 + UINT32 numStreams; 148 + 149 + PHDAC_STREAM streams; 150 + struct _PDO_DEVICE_DATA* codecs[HDA_MAX_CODECS]; 151 + 152 + PADSP_INTERRUPT_CALLBACK dspInterruptCallback; 153 + PVOID dspInterruptContext; 154 + PVOID nhlt; 155 + UINT64 nhltSz; 156 + PVOID sofTplg; 157 + UINT64 sofTplgSz; 158 + 159 + //bit flags of detected codecs 160 + UINT16 codecMask; 161 + USHORT numCodecs; 162 + 163 + HDAC_RB corb; 164 + HDAC_RB rirb; 165 + BOOL processRirb; 166 + 167 + UINT8 *rb; //CORB and RIRB buffers 168 + PVOID posbuf; 169 + } FDO_CONTEXT, * PFDO_CONTEXT; 170 + 171 + WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FDO_CONTEXT, Fdo_GetContext) 172 + 173 + NTSTATUS 174 + NTAPI 175 + Fdo_Create( 176 + _Inout_ PWDFDEVICE_INIT DeviceInit 177 + ); 178 + 179 + #endif
+321
drivers/wdm/audio/hdaudbus_new/hda_registers.h
··· 1 + #define HDA_REG_GCAP 0x00 2 + #define HDA_GCAP_64OK (1 << 0) /* 64bit address support */ 3 + #define HDA_GCAP_NSDO (3 << 1) /* # of serial data out signals */ 4 + #define HDA_GCAP_BSS (31 << 3) /* # of bidirectional streams */ 5 + #define HDA_GCAP_ISS (15 << 8) /* # of input streams */ 6 + #define HDA_GCAP_OSS (15 << 12) /* # of output streams */ 7 + #define HDA_REG_VMIN 0x02 8 + #define HDA_REG_VMAJ 0x03 9 + #define HDA_REG_OUTPAY 0x04 10 + #define HDA_REG_INPAY 0x06 11 + #define HDA_REG_GCTL 0x08 12 + #define HDA_GCTL_RESET (1 << 0) /* controller reset */ 13 + #define HDA_GCTL_FCNTRL (1 << 1) /* flush control */ 14 + #define HDA_GCTL_UNSOL (1 << 8) /* accept unsol. response enable */ 15 + #define HDA_REG_WAKEEN 0x0c 16 + #define HDA_REG_STATESTS 0x0e 17 + #define HDA_REG_GSTS 0x10 18 + #define HDA_GSTS_FSTS (1 << 1) /* flush status */ 19 + #define HDA_REG_GCAP2 0x12 20 + #define HDA_REG_LLCH 0x14 21 + #define HDA_REG_OUTSTRMPAY 0x18 22 + #define HDA_REG_INSTRMPAY 0x1A 23 + #define HDA_REG_INTCTL 0x20 24 + #define HDA_REG_INTSTS 0x24 25 + #define HDA_REG_WALLCLK 0x30 /* 24Mhz source */ 26 + #define HDA_REG_WALLCLKA 0x2030 /* 24Mhz source */ 27 + #define HDA_REG_OLD_SSYNC 0x34 /* SSYNC for old ICH */ 28 + #define HDA_REG_SSYNC 0x38 29 + #define HDA_REG_CORBLBASE 0x40 30 + #define HDA_REG_CORBUBASE 0x44 31 + #define HDA_REG_CORBWP 0x48 32 + #define HDA_REG_CORBRP 0x4a 33 + #define HDA_CORBRP_RST (1 << 15) /* read pointer reset */ 34 + #define HDA_REG_CORBCTL 0x4c 35 + #define HDA_CORBCTL_RUN (1 << 1) /* enable DMA */ 36 + #define HDA_CORBCTL_CMEIE (1 << 0) /* enable memory error irq */ 37 + #define HDA_REG_CORBSTS 0x4d 38 + #define HDA_CORBSTS_CMEI (1 << 0) /* memory error indication */ 39 + #define HDA_REG_CORBSIZE 0x4e 40 + 41 + #define HDA_REG_RIRBLBASE 0x50 42 + #define HDA_REG_RIRBUBASE 0x54 43 + #define HDA_REG_RIRBWP 0x58 44 + #define HDA_RIRBWP_RST (1 << 15) /* write pointer reset */ 45 + #define HDA_REG_RINTCNT 0x5a 46 + #define HDA_REG_RIRBCTL 0x5c 47 + #define HDA_RBCTL_IRQ_EN (1 << 0) /* enable IRQ */ 48 + #define HDA_RBCTL_DMA_EN (1 << 1) /* enable DMA */ 49 + #define HDA_RBCTL_OVERRUN_EN (1 << 2) /* enable overrun irq */ 50 + #define HDA_REG_RIRBSTS 0x5d 51 + #define HDA_RBSTS_IRQ (1 << 0) /* response irq */ 52 + #define HDA_RBSTS_OVERRUN (1 << 2) /* overrun irq */ 53 + #define HDA_REG_RIRBSIZE 0x5e 54 + 55 + #define HDA_REG_IC 0x60 56 + #define HDA_REG_IR 0x64 57 + #define HDA_REG_IRS 0x68 58 + #define HDA_IRS_VALID (1<<1) 59 + #define HDA_IRS_BUSY (1<<0) 60 + 61 + #define HDA_REG_DPLBASE 0x70 62 + #define HDA_REG_DPUBASE 0x74 63 + #define HDA_DPLBASE_ENABLE 0x1 /* Enable position buffer */ 64 + 65 + /* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */ 66 + enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; 67 + 68 + /* stream register offsets from stream base */ 69 + #define HDA_REG_SD_CTL 0x00 70 + #define HDA_REG_SD_CTL_3B 0x02 /* 3rd byte of SD_CTL register */ 71 + #define HDA_REG_SD_STS 0x03 72 + #define HDA_REG_SD_LPIB 0x04 73 + #define HDA_REG_SD_CBL 0x08 74 + #define HDA_REG_SD_LVI 0x0c 75 + #define HDA_REG_SD_FIFOW 0x0e 76 + #define HDA_REG_SD_FIFOSIZE 0x10 77 + #define HDA_REG_SD_FORMAT 0x12 78 + #define HDA_REG_SD_FIFOL 0x14 79 + #define HDA_REG_SD_BDLPL 0x18 80 + #define HDA_REG_SD_BDLPU 0x1c 81 + #define HDA_REG_SD_LPIBA 0x2004 82 + 83 + /* GTS registers */ 84 + #define HDA_REG_LLCH 0x14 85 + 86 + #define HDA_REG_GTS_BASE 0x520 87 + 88 + #define HDA_REG_GTSCC (HDA_REG_GTS_BASE + 0x00) 89 + #define HDA_REG_WALFCC (HDA_REG_GTS_BASE + 0x04) 90 + #define HDA_REG_TSCCL (HDA_REG_GTS_BASE + 0x08) 91 + #define HDA_REG_TSCCU (HDA_REG_GTS_BASE + 0x0C) 92 + #define HDA_REG_LLPFOC (HDA_REG_GTS_BASE + 0x14) 93 + #define HDA_REG_LLPCL (HDA_REG_GTS_BASE + 0x18) 94 + #define HDA_REG_LLPCU (HDA_REG_GTS_BASE + 0x1C) 95 + 96 + /* Haswell/Broadwell display HD-A controller Extended Mode registers */ 97 + #define HDA_REG_HSW_EM4 0x100c 98 + #define HDA_REG_HSW_EM5 0x1010 99 + 100 + /* Skylake/Broxton vendor-specific registers */ 101 + #define HDA_REG_VS_EM1 0x1000 102 + #define HDA_REG_VS_INRC 0x1004 103 + #define HDA_REG_VS_OUTRC 0x1008 104 + #define HDA_REG_VS_FIFOTRK 0x100C 105 + #define HDA_REG_VS_FIFOTRK2 0x1010 106 + #define HDA_REG_VS_EM2 0x1030 107 + #define HDA_REG_VS_EM3L 0x1038 108 + #define HDA_REG_VS_EM3U 0x103C 109 + #define HDA_REG_VS_EM4L 0x1040 110 + #define HDA_REG_VS_EM4U 0x1044 111 + #define HDA_REG_VS_LTRP 0x1048 112 + #define HDA_REG_VS_D0I3C 0x104A 113 + #define HDA_REG_VS_PCE 0x104B 114 + #define HDA_REG_VS_L2MAGC 0x1050 115 + #define HDA_REG_VS_L2LAHPT 0x1054 116 + #define HDA_REG_VS_SDXDPIB_XBASE 0x1084 117 + #define HDA_REG_VS_SDXDPIB_XINTERVAL 0x20 118 + #define HDA_REG_VS_SDXEFIFOS_XBASE 0x1094 119 + #define HDA_REG_VS_SDXEFIFOS_XINTERVAL 0x20 120 + 121 + /* PCI space */ 122 + #define HDA_PCIREG_TCSEL 0x44 123 + 124 + /* 125 + * other constants 126 + */ 127 + 128 + /* max number of fragments - we may use more if allocating more pages for BDL */ 129 + #define BDL_SIZE 4096 130 + #define HDA_MAX_BDL_ENTRIES (BDL_SIZE / 16) 131 + /* 132 + * max buffer size - artificial 4MB limit per stream to avoid big allocations 133 + * In theory it can be really big, but as it is per stream on systems with many streams memory could 134 + * be quickly saturated if userspace requests maximum buffer size for each of them. 135 + */ 136 + #define HDA_MAX_BUF_SIZE (4*1024*1024) 137 + 138 + /* RIRB int mask: overrun[2], response[0] */ 139 + #define RIRB_INT_RESPONSE 0x01 140 + #define RIRB_INT_OVERRUN 0x04 141 + #define RIRB_INT_MASK 0x05 142 + 143 + /* STATESTS int mask: S3,SD2,SD1,SD0 */ 144 + #define STATESTS_INT_MASK ((1 << HDA_MAX_CODECS) - 1) 145 + 146 + /* SD_CTL bits */ 147 + #define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ 148 + #define SD_CTL_DMA_START 0x02 /* stream DMA start bit */ 149 + #define SD_CTL_STRIPE (3 << 16) /* stripe control */ 150 + #define SD_CTL_TRAFFIC_PRIO (1 << 18) /* traffic priority */ 151 + #define SD_CTL_DIR (1 << 19) /* bi-directional stream */ 152 + #define SD_CTL_STREAM_TAG_MASK (0xf << 20) 153 + #define SD_CTL_STREAM_TAG_SHIFT 20 154 + 155 + /* SD_CTL and SD_STS */ 156 + #define SD_INT_DESC_ERR 0x10 /* descriptor error interrupt */ 157 + #define SD_INT_FIFO_ERR 0x08 /* FIFO error interrupt */ 158 + #define SD_INT_COMPLETE 0x04 /* completion interrupt */ 159 + #define SD_INT_MASK (SD_INT_DESC_ERR|SD_INT_FIFO_ERR|\ 160 + SD_INT_COMPLETE) 161 + #define SD_CTL_STRIPE_MASK 0x3 /* stripe control mask */ 162 + 163 + /* SD_STS */ 164 + #define SD_STS_FIFO_READY 0x20 /* FIFO ready */ 165 + 166 + /* INTCTL and INTSTS */ 167 + #define HDA_INT_ALL_STREAM 0xff /* all stream interrupts */ 168 + #define HDA_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ 169 + #define HDA_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ 170 + 171 + /* below are so far hardcoded - should read registers in future */ 172 + #define HDA_MAX_CORB_ENTRIES 256 173 + #define HDA_MAX_RIRB_ENTRIES 256 174 + 175 + /* Capability header Structure */ 176 + #define HDA_REG_CAP_HDR 0x0 177 + #define HDA_CAP_HDR_VER_OFF 28 178 + #define HDA_CAP_HDR_VER_MASK (0xF << HDA_CAP_HDR_VER_OFF) 179 + #define HDA_CAP_HDR_ID_OFF 16 180 + #define HDA_CAP_HDR_ID_MASK (0xFFF << HDA_CAP_HDR_ID_OFF) 181 + #define HDA_CAP_HDR_NXT_PTR_MASK 0xFFFF 182 + 183 + /* registers of Software Position Based FIFO Capability Structure */ 184 + #define HDA_SPB_CAP_ID 0x4 185 + #define HDA_REG_SPB_BASE_ADDR 0x700 186 + #define HDA_REG_SPB_SPBFCH 0x00 187 + #define HDA_REG_SPB_SPBFCCTL 0x04 188 + /* Base used to calculate the iterating register offset */ 189 + #define HDA_SPB_BASE 0x08 190 + /* Interval used to calculate the iterating register offset */ 191 + #define HDA_SPB_INTERVAL 0x08 192 + /* SPIB base */ 193 + #define HDA_SPB_SPIB 0x00 194 + /* SPIB MAXFIFO base*/ 195 + #define HDA_SPB_MAXFIFO 0x04 196 + 197 + /* registers of Global Time Synchronization Capability Structure */ 198 + #define HDA_GTS_CAP_ID 0x1 199 + #define HDA_REG_GTS_GTSCH 0x00 200 + #define HDA_REG_GTS_GTSCD 0x04 201 + #define HDA_REG_GTS_GTSCTLAC 0x0C 202 + #define HDA_GTS_BASE 0x20 203 + #define HDA_GTS_INTERVAL 0x20 204 + 205 + /* registers for Processing Pipe Capability Structure */ 206 + #define HDA_PP_CAP_ID 0x3 207 + #define HDA_REG_PP_PPCH 0x10 208 + #define HDA_REG_PP_PPCTL 0x04 209 + #define HDA_PPCTL_PIE (1<<31) 210 + #define HDA_PPCTL_GPROCEN (1<<30) 211 + /* _X_ = dma engine # and cannot * exceed 29 (per spec max 30 dma engines) */ 212 + #define HDA_PPCTL_PROCEN(_X_) (1<<(_X_)) 213 + 214 + #define HDA_REG_PP_PPSTS 0x08 215 + 216 + #define HDA_PPHC_BASE 0x10 217 + #define HDA_PPHC_INTERVAL 0x10 218 + 219 + #define HDA_REG_PPHCLLPL 0x0 220 + #define HDA_REG_PPHCLLPU 0x4 221 + #define HDA_REG_PPHCLDPL 0x8 222 + #define HDA_REG_PPHCLDPU 0xC 223 + 224 + #define HDA_PPLC_BASE 0x10 225 + #define HDA_PPLC_MULTI 0x10 226 + #define HDA_PPLC_INTERVAL 0x10 227 + 228 + #define HDA_REG_PPLCCTL 0x0 229 + #define HDA_PPLCCTL_STRM_BITS 4 230 + #define HDA_PPLCCTL_STRM_SHIFT 20 231 + #define HDA_REG_MASK(bit_num, offset) \ 232 + (((1 << (bit_num)) - 1) << (offset)) 233 + #define HDA_PPLCCTL_STRM_MASK \ 234 + HDA_REG_MASK(HDA_PPLCCTL_STRM_BITS, HDA_PPLCCTL_STRM_SHIFT) 235 + #define HDA_PPLCCTL_RUN (1<<1) 236 + #define HDA_PPLCCTL_STRST (1<<0) 237 + 238 + #define HDA_REG_PPLCFMT 0x4 239 + #define HDA_REG_PPLCLLPL 0x8 240 + #define HDA_REG_PPLCLLPU 0xC 241 + 242 + /* registers for Multiple Links Capability Structure */ 243 + #define HDA_ML_CAP_ID 0x2 244 + #define HDA_REG_ML_MLCH 0x00 245 + #define HDA_REG_ML_MLCD 0x04 246 + #define HDA_ML_BASE 0x40 247 + #define HDA_ML_INTERVAL 0x40 248 + 249 + #define HDA_REG_ML_LCAP 0x00 250 + #define HDA_REG_ML_LCTL 0x04 251 + #define HDA_REG_ML_LOSIDV 0x08 252 + #define HDA_REG_ML_LSDIID 0x0C 253 + #define HDA_REG_ML_LPSOO 0x10 254 + #define HDA_REG_ML_LPSIO 0x12 255 + #define HDA_REG_ML_LWALFC 0x18 256 + #define HDA_REG_ML_LOUTPAY 0x20 257 + #define HDA_REG_ML_LINPAY 0x30 258 + 259 + /* bit0 is reserved, with BIT(1) mapping to stream1 */ 260 + #define ML_LOSIDV_STREAM_MASK 0xFFFE 261 + 262 + #define ML_LCTL_SCF_MASK 0xF 263 + #define HDA_MLCTL_SPA (0x1 << 16) 264 + #define HDA_MLCTL_CPA (0x1 << 23) 265 + #define HDA_MLCTL_SPA_SHIFT 16 266 + #define HDA_MLCTL_CPA_SHIFT 23 267 + 268 + /* registers for DMA Resume Capability Structure */ 269 + #define HDA_DRSM_CAP_ID 0x5 270 + #define HDA_REG_DRSM_CTL 0x4 271 + /* Base used to calculate the iterating register offset */ 272 + #define HDA_DRSM_BASE 0x08 273 + /* Interval used to calculate the iterating register offset */ 274 + #define HDA_DRSM_INTERVAL 0x08 275 + 276 + /* Global time synchronization registers */ 277 + #define GTSCC_TSCCD_MASK 0x80000000 278 + #define GTSCC_TSCCD_SHIFT BIT(31) 279 + #define GTSCC_TSCCI_MASK 0x20 280 + #define GTSCC_CDMAS_DMA_DIR_SHIFT 4 281 + 282 + #define WALFCC_CIF_MASK 0x1FF 283 + #define WALFCC_FN_SHIFT 9 284 + #define HDA_CLK_CYCLES_PER_FRAME 512 285 + 286 + /* 287 + * An error occurs near frame "rollover". The clocks in frame value indicates 288 + * whether this error may have occurred. Here we use the value of 10. Please 289 + * see the errata for the right number [<10] 290 + */ 291 + #define HDA_MAX_CYCLE_VALUE 499 292 + #define HDA_MAX_CYCLE_OFFSET 10 293 + #define HDA_MAX_CYCLE_READ_RETRY 10 294 + 295 + #define TSCCU_CCU_SHIFT 32 296 + #define LLPC_CCU_SHIFT 32 297 + 298 + /* Defines for Intel SCH HDA snoop control */ 299 + #define INTEL_HDA_CGCTL 0x48 300 + #define INTEL_HDA_CGCTL_MISCBDCGE (0x1 << 6) 301 + #define INTEL_SCH_HDA_DEVC 0x78 302 + #define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11) 303 + 304 + #define HDA_VS_EM2_DUM (1 << 23) 305 + 306 + /* Defines for ATI HD Audio support in SB450 south bridge */ 307 + #define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42 308 + #define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02 309 + 310 + /* Defines for Nvidia HDA support */ 311 + #define NVIDIA_HDA_TRANSREG_ADDR 0x4e 312 + #define NVIDIA_HDA_ENABLE_COHBITS 0x0f 313 + #define NVIDIA_HDA_ISTRM_COH 0x4d 314 + #define NVIDIA_HDA_OSTRM_COH 0x4c 315 + #define NVIDIA_HDA_ENABLE_COHBIT 0x01 316 + 317 + /* Defines for Intel SCH HDA snoop control */ 318 + #define INTEL_HDA_CGCTL 0x48 319 + #define INTEL_HDA_CGCTL_MISCBDCGE (0x1 << 6) 320 + #define INTEL_SCH_HDA_DEVC 0x78 321 + #define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11)
+535
drivers/wdm/audio/hdaudbus_new/hda_verbs.h
··· 1 + #if !defined(_HDA_VERBS_H_) 2 + #define _HDA_VERBS_H_ 3 + 4 + #define AC_NODE_ROOT 0x00 5 + 6 + /* 7 + * function group types 8 + */ 9 + enum { 10 + AC_GRP_AUDIO_FUNCTION = 0x01, 11 + AC_GRP_MODEM_FUNCTION = 0x02, 12 + }; 13 + 14 + /* 15 + * GET verbs 16 + */ 17 + #define AC_VERB_GET_STREAM_FORMAT 0x0a00 18 + #define AC_VERB_GET_AMP_GAIN_MUTE 0x0b00 19 + #define AC_VERB_GET_PROC_COEF 0x0c00 20 + #define AC_VERB_GET_COEF_INDEX 0x0d00 21 + #define AC_VERB_PARAMETERS 0x0f00 22 + #define AC_VERB_GET_CONNECT_SEL 0x0f01 23 + #define AC_VERB_GET_CONNECT_LIST 0x0f02 24 + #define AC_VERB_GET_PROC_STATE 0x0f03 25 + #define AC_VERB_GET_SDI_SELECT 0x0f04 26 + #define AC_VERB_GET_POWER_STATE 0x0f05 27 + #define AC_VERB_GET_CONV 0x0f06 28 + #define AC_VERB_GET_PIN_WIDGET_CONTROL 0x0f07 29 + #define AC_VERB_GET_UNSOLICITED_RESPONSE 0x0f08 30 + #define AC_VERB_GET_PIN_SENSE 0x0f09 31 + #define AC_VERB_GET_BEEP_CONTROL 0x0f0a 32 + #define AC_VERB_GET_EAPD_BTLENABLE 0x0f0c 33 + #define AC_VERB_GET_DIGI_CONVERT_1 0x0f0d 34 + #define AC_VERB_GET_DIGI_CONVERT_2 0x0f0e /* unused */ 35 + #define AC_VERB_GET_VOLUME_KNOB_CONTROL 0x0f0f 36 + /* f10-f1a: GPIO */ 37 + #define AC_VERB_GET_GPIO_DATA 0x0f15 38 + #define AC_VERB_GET_GPIO_MASK 0x0f16 39 + #define AC_VERB_GET_GPIO_DIRECTION 0x0f17 40 + #define AC_VERB_GET_GPIO_WAKE_MASK 0x0f18 41 + #define AC_VERB_GET_GPIO_UNSOLICITED_RSP_MASK 0x0f19 42 + #define AC_VERB_GET_GPIO_STICKY_MASK 0x0f1a 43 + #define AC_VERB_GET_CONFIG_DEFAULT 0x0f1c 44 + /* f20: AFG/MFG */ 45 + #define AC_VERB_GET_SUBSYSTEM_ID 0x0f20 46 + #define AC_VERB_GET_STRIPE_CONTROL 0x0f24 47 + #define AC_VERB_GET_CVT_CHAN_COUNT 0x0f2d 48 + #define AC_VERB_GET_HDMI_DIP_SIZE 0x0f2e 49 + #define AC_VERB_GET_HDMI_ELDD 0x0f2f 50 + #define AC_VERB_GET_HDMI_DIP_INDEX 0x0f30 51 + #define AC_VERB_GET_HDMI_DIP_DATA 0x0f31 52 + #define AC_VERB_GET_HDMI_DIP_XMIT 0x0f32 53 + #define AC_VERB_GET_HDMI_CP_CTRL 0x0f33 54 + #define AC_VERB_GET_HDMI_CHAN_SLOT 0x0f34 55 + #define AC_VERB_GET_DEVICE_SEL 0xf35 56 + #define AC_VERB_GET_DEVICE_LIST 0xf36 57 + 58 + /* 59 + * SET verbs 60 + */ 61 + #define AC_VERB_SET_STREAM_FORMAT 0x200 62 + #define AC_VERB_SET_AMP_GAIN_MUTE 0x300 63 + #define AC_VERB_SET_PROC_COEF 0x400 64 + #define AC_VERB_SET_COEF_INDEX 0x500 65 + #define AC_VERB_SET_CONNECT_SEL 0x701 66 + #define AC_VERB_SET_PROC_STATE 0x703 67 + #define AC_VERB_SET_SDI_SELECT 0x704 68 + #define AC_VERB_SET_POWER_STATE 0x705 69 + #define AC_VERB_SET_CHANNEL_STREAMID 0x706 70 + #define AC_VERB_SET_PIN_WIDGET_CONTROL 0x707 71 + #define AC_VERB_SET_UNSOLICITED_ENABLE 0x708 72 + #define AC_VERB_SET_PIN_SENSE 0x709 73 + #define AC_VERB_SET_BEEP_CONTROL 0x70a 74 + #define AC_VERB_SET_EAPD_BTLENABLE 0x70c 75 + #define AC_VERB_SET_DIGI_CONVERT_1 0x70d 76 + #define AC_VERB_SET_DIGI_CONVERT_2 0x70e 77 + #define AC_VERB_SET_DIGI_CONVERT_3 0x73e 78 + #define AC_VERB_SET_VOLUME_KNOB_CONTROL 0x70f 79 + #define AC_VERB_SET_GPIO_DATA 0x715 80 + #define AC_VERB_SET_GPIO_MASK 0x716 81 + #define AC_VERB_SET_GPIO_DIRECTION 0x717 82 + #define AC_VERB_SET_GPIO_WAKE_MASK 0x718 83 + #define AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK 0x719 84 + #define AC_VERB_SET_GPIO_STICKY_MASK 0x71a 85 + #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 0x71c 86 + #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1 0x71d 87 + #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2 0x71e 88 + #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_3 0x71f 89 + #define AC_VERB_SET_EAPD 0x788 90 + #define AC_VERB_SET_CODEC_RESET 0x7ff 91 + #define AC_VERB_SET_STRIPE_CONTROL 0x724 92 + #define AC_VERB_SET_CVT_CHAN_COUNT 0x72d 93 + #define AC_VERB_SET_HDMI_DIP_INDEX 0x730 94 + #define AC_VERB_SET_HDMI_DIP_DATA 0x731 95 + #define AC_VERB_SET_HDMI_DIP_XMIT 0x732 96 + #define AC_VERB_SET_HDMI_CP_CTRL 0x733 97 + #define AC_VERB_SET_HDMI_CHAN_SLOT 0x734 98 + #define AC_VERB_SET_DEVICE_SEL 0x735 99 + 100 + /* 101 + * Parameter IDs 102 + */ 103 + #define AC_PAR_VENDOR_ID 0x00 104 + #define AC_PAR_SUBSYSTEM_ID 0x01 105 + #define AC_PAR_REV_ID 0x02 106 + #define AC_PAR_NODE_COUNT 0x04 107 + #define AC_PAR_FUNCTION_TYPE 0x05 108 + #define AC_PAR_AUDIO_FG_CAP 0x08 109 + #define AC_PAR_AUDIO_WIDGET_CAP 0x09 110 + #define AC_PAR_PCM 0x0a 111 + #define AC_PAR_STREAM 0x0b 112 + #define AC_PAR_PIN_CAP 0x0c 113 + #define AC_PAR_AMP_IN_CAP 0x0d 114 + #define AC_PAR_CONNLIST_LEN 0x0e 115 + #define AC_PAR_POWER_STATE 0x0f 116 + #define AC_PAR_PROC_CAP 0x10 117 + #define AC_PAR_GPIO_CAP 0x11 118 + #define AC_PAR_AMP_OUT_CAP 0x12 119 + #define AC_PAR_VOL_KNB_CAP 0x13 120 + #define AC_PAR_DEVLIST_LEN 0x15 121 + #define AC_PAR_HDMI_LPCM_CAP 0x20 122 + 123 + /* 124 + * AC_VERB_PARAMETERS results (32bit) 125 + */ 126 + 127 + /* Function Group Type */ 128 + #define AC_FGT_TYPE (0xff<<0) 129 + #define AC_FGT_TYPE_SHIFT 0 130 + #define AC_FGT_UNSOL_CAP (1<<8) 131 + 132 + /* Audio Function Group Capabilities */ 133 + #define AC_AFG_OUT_DELAY (0xf<<0) 134 + #define AC_AFG_IN_DELAY (0xf<<8) 135 + #define AC_AFG_BEEP_GEN (1<<16) 136 + 137 + /* Audio Widget Capabilities */ 138 + #define AC_WCAP_STEREO (1<<0) /* stereo I/O */ 139 + #define AC_WCAP_IN_AMP (1<<1) /* AMP-in present */ 140 + #define AC_WCAP_OUT_AMP (1<<2) /* AMP-out present */ 141 + #define AC_WCAP_AMP_OVRD (1<<3) /* AMP-parameter override */ 142 + #define AC_WCAP_FORMAT_OVRD (1<<4) /* format override */ 143 + #define AC_WCAP_STRIPE (1<<5) /* stripe */ 144 + #define AC_WCAP_PROC_WID (1<<6) /* Proc Widget */ 145 + #define AC_WCAP_UNSOL_CAP (1<<7) /* Unsol capable */ 146 + #define AC_WCAP_CONN_LIST (1<<8) /* connection list */ 147 + #define AC_WCAP_DIGITAL (1<<9) /* digital I/O */ 148 + #define AC_WCAP_POWER (1<<10) /* power control */ 149 + #define AC_WCAP_LR_SWAP (1<<11) /* L/R swap */ 150 + #define AC_WCAP_CP_CAPS (1<<12) /* content protection */ 151 + #define AC_WCAP_CHAN_CNT_EXT (7<<13) /* channel count ext */ 152 + #define AC_WCAP_DELAY (0xf<<16) 153 + #define AC_WCAP_DELAY_SHIFT 16 154 + #define AC_WCAP_TYPE (0xf<<20) 155 + #define AC_WCAP_TYPE_SHIFT 20 156 + 157 + /* supported PCM rates and bits */ 158 + #define AC_SUPPCM_RATES (0xfff << 0) 159 + #define AC_SUPPCM_BITS_8 (1<<16) 160 + #define AC_SUPPCM_BITS_16 (1<<17) 161 + #define AC_SUPPCM_BITS_20 (1<<18) 162 + #define AC_SUPPCM_BITS_24 (1<<19) 163 + #define AC_SUPPCM_BITS_32 (1<<20) 164 + 165 + /* supported PCM stream format */ 166 + #define AC_SUPFMT_PCM (1<<0) 167 + #define AC_SUPFMT_FLOAT32 (1<<1) 168 + #define AC_SUPFMT_AC3 (1<<2) 169 + 170 + /* GP I/O count */ 171 + #define AC_GPIO_IO_COUNT (0xff<<0) 172 + #define AC_GPIO_O_COUNT (0xff<<8) 173 + #define AC_GPIO_O_COUNT_SHIFT 8 174 + #define AC_GPIO_I_COUNT (0xff<<16) 175 + #define AC_GPIO_I_COUNT_SHIFT 16 176 + #define AC_GPIO_UNSOLICITED (1<<30) 177 + #define AC_GPIO_WAKE (1<<31) 178 + 179 + /* Converter stream, channel */ 180 + #define AC_CONV_CHANNEL (0xf<<0) 181 + #define AC_CONV_STREAM (0xf<<4) 182 + #define AC_CONV_STREAM_SHIFT 4 183 + 184 + /* Input converter SDI select */ 185 + #define AC_SDI_SELECT (0xf<<0) 186 + 187 + /* stream format id */ 188 + #define AC_FMT_CHAN_SHIFT 0 189 + #define AC_FMT_CHAN_MASK (0x0f << 0) 190 + #define AC_FMT_BITS_SHIFT 4 191 + #define AC_FMT_BITS_MASK (7 << 4) 192 + #define AC_FMT_BITS_8 (0 << 4) 193 + #define AC_FMT_BITS_16 (1 << 4) 194 + #define AC_FMT_BITS_20 (2 << 4) 195 + #define AC_FMT_BITS_24 (3 << 4) 196 + #define AC_FMT_BITS_32 (4 << 4) 197 + #define AC_FMT_DIV_SHIFT 8 198 + #define AC_FMT_DIV_MASK (7 << 8) 199 + #define AC_FMT_MULT_SHIFT 11 200 + #define AC_FMT_MULT_MASK (7 << 11) 201 + #define AC_FMT_BASE_SHIFT 14 202 + #define AC_FMT_BASE_48K (0 << 14) 203 + #define AC_FMT_BASE_44K (1 << 14) 204 + #define AC_FMT_TYPE_SHIFT 15 205 + #define AC_FMT_TYPE_PCM (0 << 15) 206 + #define AC_FMT_TYPE_NON_PCM (1 << 15) 207 + 208 + /* Unsolicited response control */ 209 + #define AC_UNSOL_TAG (0x3f<<0) 210 + #define AC_UNSOL_ENABLED (1<<7) 211 + #define AC_USRSP_EN AC_UNSOL_ENABLED 212 + 213 + /* Unsolicited responses */ 214 + #define AC_UNSOL_RES_TAG (0x3f<<26) 215 + #define AC_UNSOL_RES_TAG_SHIFT 26 216 + #define AC_UNSOL_RES_SUBTAG (0x1f<<21) 217 + #define AC_UNSOL_RES_SUBTAG_SHIFT 21 218 + #define AC_UNSOL_RES_DE (0x3f<<15) /* Device Entry 219 + * (for DP1.2 MST) 220 + */ 221 + #define AC_UNSOL_RES_DE_SHIFT 15 222 + #define AC_UNSOL_RES_IA (1<<2) /* Inactive (for DP1.2 MST) */ 223 + #define AC_UNSOL_RES_ELDV (1<<1) /* ELD Data valid (for HDMI) */ 224 + #define AC_UNSOL_RES_PD (1<<0) /* pinsense detect */ 225 + #define AC_UNSOL_RES_CP_STATE (1<<1) /* content protection */ 226 + #define AC_UNSOL_RES_CP_READY (1<<0) /* content protection */ 227 + 228 + /* Pin widget capabilies */ 229 + #define AC_PINCAP_IMP_SENSE (1<<0) /* impedance sense capable */ 230 + #define AC_PINCAP_TRIG_REQ (1<<1) /* trigger required */ 231 + #define AC_PINCAP_PRES_DETECT (1<<2) /* presence detect capable */ 232 + #define AC_PINCAP_HP_DRV (1<<3) /* headphone drive capable */ 233 + #define AC_PINCAP_OUT (1<<4) /* output capable */ 234 + #define AC_PINCAP_IN (1<<5) /* input capable */ 235 + #define AC_PINCAP_BALANCE (1<<6) /* balanced I/O capable */ 236 + /* Note: This LR_SWAP pincap is defined in the Realtek ALC883 specification, 237 + * but is marked reserved in the Intel HDA specification. 238 + */ 239 + #define AC_PINCAP_LR_SWAP (1<<7) /* L/R swap */ 240 + /* Note: The same bit as LR_SWAP is newly defined as HDMI capability 241 + * in HD-audio specification 242 + */ 243 + #define AC_PINCAP_HDMI (1<<7) /* HDMI pin */ 244 + #define AC_PINCAP_DP (1<<24) /* DisplayPort pin, can 245 + * coexist with AC_PINCAP_HDMI 246 + */ 247 + #define AC_PINCAP_VREF (0x37<<8) 248 + #define AC_PINCAP_VREF_SHIFT 8 249 + #define AC_PINCAP_EAPD (1<<16) /* EAPD capable */ 250 + #define AC_PINCAP_HBR (1<<27) /* High Bit Rate */ 251 + /* Vref status (used in pin cap) */ 252 + #define AC_PINCAP_VREF_HIZ (1<<0) /* Hi-Z */ 253 + #define AC_PINCAP_VREF_50 (1<<1) /* 50% */ 254 + #define AC_PINCAP_VREF_GRD (1<<2) /* ground */ 255 + #define AC_PINCAP_VREF_80 (1<<4) /* 80% */ 256 + #define AC_PINCAP_VREF_100 (1<<5) /* 100% */ 257 + 258 + /* Amplifier capabilities */ 259 + #define AC_AMPCAP_OFFSET (0x7f<<0) /* 0dB offset */ 260 + #define AC_AMPCAP_OFFSET_SHIFT 0 261 + #define AC_AMPCAP_NUM_STEPS (0x7f<<8) /* number of steps */ 262 + #define AC_AMPCAP_NUM_STEPS_SHIFT 8 263 + #define AC_AMPCAP_STEP_SIZE (0x7f<<16) /* step size 0-32dB 264 + * in 0.25dB 265 + */ 266 + #define AC_AMPCAP_STEP_SIZE_SHIFT 16 267 + #define AC_AMPCAP_MUTE (1<<31) /* mute capable */ 268 + #define AC_AMPCAP_MUTE_SHIFT 31 269 + 270 + /* driver-specific amp-caps: using bits 24-30 */ 271 + #define AC_AMPCAP_MIN_MUTE (1 << 30) /* min-volume = mute */ 272 + 273 + /* Connection list */ 274 + #define AC_CLIST_LENGTH (0x7f<<0) 275 + #define AC_CLIST_LONG (1<<7) 276 + 277 + /* Supported power status */ 278 + #define AC_PWRST_D0SUP (1<<0) 279 + #define AC_PWRST_D1SUP (1<<1) 280 + #define AC_PWRST_D2SUP (1<<2) 281 + #define AC_PWRST_D3SUP (1<<3) 282 + #define AC_PWRST_D3COLDSUP (1<<4) 283 + #define AC_PWRST_S3D3COLDSUP (1<<29) 284 + #define AC_PWRST_CLKSTOP (1<<30) 285 + #define AC_PWRST_EPSS (1U<<31) 286 + 287 + /* Power state values */ 288 + #define AC_PWRST_SETTING (0xf<<0) 289 + #define AC_PWRST_ACTUAL (0xf<<4) 290 + #define AC_PWRST_ACTUAL_SHIFT 4 291 + #define AC_PWRST_D0 0x00 292 + #define AC_PWRST_D1 0x01 293 + #define AC_PWRST_D2 0x02 294 + #define AC_PWRST_D3 0x03 295 + #define AC_PWRST_ERROR (1<<8) 296 + #define AC_PWRST_CLK_STOP_OK (1<<9) 297 + #define AC_PWRST_SETTING_RESET (1<<10) 298 + 299 + /* Processing capabilies */ 300 + #define AC_PCAP_BENIGN (1<<0) 301 + #define AC_PCAP_NUM_COEF (0xff<<8) 302 + #define AC_PCAP_NUM_COEF_SHIFT 8 303 + 304 + /* Volume knobs capabilities */ 305 + #define AC_KNBCAP_NUM_STEPS (0x7f<<0) 306 + #define AC_KNBCAP_DELTA (1<<7) 307 + 308 + /* HDMI LPCM capabilities */ 309 + #define AC_LPCMCAP_48K_CP_CHNS (0x0f<<0) /* max channels w/ CP-on */ 310 + #define AC_LPCMCAP_48K_NO_CHNS (0x0f<<4) /* max channels w/o CP-on */ 311 + #define AC_LPCMCAP_48K_20BIT (1<<8) /* 20b bitrate supported */ 312 + #define AC_LPCMCAP_48K_24BIT (1<<9) /* 24b bitrate supported */ 313 + #define AC_LPCMCAP_96K_CP_CHNS (0x0f<<10) /* max channels w/ CP-on */ 314 + #define AC_LPCMCAP_96K_NO_CHNS (0x0f<<14) /* max channels w/o CP-on */ 315 + #define AC_LPCMCAP_96K_20BIT (1<<18) /* 20b bitrate supported */ 316 + #define AC_LPCMCAP_96K_24BIT (1<<19) /* 24b bitrate supported */ 317 + #define AC_LPCMCAP_192K_CP_CHNS (0x0f<<20) /* max channels w/ CP-on */ 318 + #define AC_LPCMCAP_192K_NO_CHNS (0x0f<<24) /* max channels w/o CP-on */ 319 + #define AC_LPCMCAP_192K_20BIT (1<<28) /* 20b bitrate supported */ 320 + #define AC_LPCMCAP_192K_24BIT (1<<29) /* 24b bitrate supported */ 321 + #define AC_LPCMCAP_44K (1<<30) /* 44.1kHz support */ 322 + #define AC_LPCMCAP_44K_MS (1<<31) /* 44.1kHz-multiplies support */ 323 + 324 + /* Display pin's device list length */ 325 + #define AC_DEV_LIST_LEN_MASK 0x3f 326 + #define AC_MAX_DEV_LIST_LEN 64 327 + 328 + /* 329 + * Control Parameters 330 + */ 331 + 332 + /* Amp gain/mute */ 333 + #define AC_AMP_MUTE (1<<7) 334 + #define AC_AMP_GAIN (0x7f) 335 + #define AC_AMP_GET_INDEX (0xf<<0) 336 + 337 + #define AC_AMP_GET_LEFT (1<<13) 338 + #define AC_AMP_GET_RIGHT (0<<13) 339 + #define AC_AMP_GET_OUTPUT (1<<15) 340 + #define AC_AMP_GET_INPUT (0<<15) 341 + 342 + #define AC_AMP_SET_INDEX (0xf<<8) 343 + #define AC_AMP_SET_INDEX_SHIFT 8 344 + #define AC_AMP_SET_RIGHT (1<<12) 345 + #define AC_AMP_SET_LEFT (1<<13) 346 + #define AC_AMP_SET_INPUT (1<<14) 347 + #define AC_AMP_SET_OUTPUT (1<<15) 348 + 349 + /* DIGITAL1 bits */ 350 + #define AC_DIG1_ENABLE (1<<0) 351 + #define AC_DIG1_V (1<<1) 352 + #define AC_DIG1_VCFG (1<<2) 353 + #define AC_DIG1_EMPHASIS (1<<3) 354 + #define AC_DIG1_COPYRIGHT (1<<4) 355 + #define AC_DIG1_NONAUDIO (1<<5) 356 + #define AC_DIG1_PROFESSIONAL (1<<6) 357 + #define AC_DIG1_LEVEL (1<<7) 358 + 359 + /* DIGITAL2 bits */ 360 + #define AC_DIG2_CC (0x7f<<0) 361 + 362 + /* DIGITAL3 bits */ 363 + #define AC_DIG3_ICT (0xf<<0) 364 + #define AC_DIG3_KAE (1<<7) 365 + 366 + /* Pin widget control - 8bit */ 367 + #define AC_PINCTL_EPT (0x3<<0) 368 + #define AC_PINCTL_EPT_NATIVE 0 369 + #define AC_PINCTL_EPT_HBR 3 370 + #define AC_PINCTL_VREFEN (0x7<<0) 371 + #define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */ 372 + #define AC_PINCTL_VREF_50 1 /* 50% */ 373 + #define AC_PINCTL_VREF_GRD 2 /* ground */ 374 + #define AC_PINCTL_VREF_80 4 /* 80% */ 375 + #define AC_PINCTL_VREF_100 5 /* 100% */ 376 + #define AC_PINCTL_IN_EN (1<<5) 377 + #define AC_PINCTL_OUT_EN (1<<6) 378 + #define AC_PINCTL_HP_EN (1<<7) 379 + 380 + /* Pin sense - 32bit */ 381 + #define AC_PINSENSE_IMPEDANCE_MASK (0x7fffffff) 382 + #define AC_PINSENSE_PRESENCE (1<<31) 383 + #define AC_PINSENSE_ELDV (1<<30) /* ELD valid (HDMI) */ 384 + 385 + /* EAPD/BTL enable - 32bit */ 386 + #define AC_EAPDBTL_BALANCED (1<<0) 387 + #define AC_EAPDBTL_EAPD (1<<1) 388 + #define AC_EAPDBTL_LR_SWAP (1<<2) 389 + 390 + /* HDMI ELD data */ 391 + #define AC_ELDD_ELD_VALID (1<<31) 392 + #define AC_ELDD_ELD_DATA 0xff 393 + 394 + /* HDMI DIP size */ 395 + #define AC_DIPSIZE_ELD_BUF (1<<3) /* ELD buf size of packet size */ 396 + #define AC_DIPSIZE_PACK_IDX (0x07<<0) /* packet index */ 397 + 398 + /* HDMI DIP index */ 399 + #define AC_DIPIDX_PACK_IDX (0x07<<5) /* packet idnex */ 400 + #define AC_DIPIDX_BYTE_IDX (0x1f<<0) /* byte index */ 401 + 402 + /* HDMI DIP xmit (transmit) control */ 403 + #define AC_DIPXMIT_MASK (0x3<<6) 404 + #define AC_DIPXMIT_DISABLE (0x0<<6) /* disable xmit */ 405 + #define AC_DIPXMIT_ONCE (0x2<<6) /* xmit once then disable */ 406 + #define AC_DIPXMIT_BEST (0x3<<6) /* best effort */ 407 + 408 + /* HDMI content protection (CP) control */ 409 + #define AC_CPCTRL_CES (1<<9) /* current encryption state */ 410 + #define AC_CPCTRL_READY (1<<8) /* ready bit */ 411 + #define AC_CPCTRL_SUBTAG (0x1f<<3) /* subtag for unsol-resp */ 412 + #define AC_CPCTRL_STATE (3<<0) /* current CP request state */ 413 + 414 + /* Converter channel <-> HDMI slot mapping */ 415 + #define AC_CVTMAP_HDMI_SLOT (0xf<<0) /* HDMI slot number */ 416 + #define AC_CVTMAP_CHAN (0xf<<4) /* converter channel number */ 417 + 418 + /* configuration default - 32bit */ 419 + #define AC_DEFCFG_SEQUENCE (0xf<<0) 420 + #define AC_DEFCFG_DEF_ASSOC (0xf<<4) 421 + #define AC_DEFCFG_ASSOC_SHIFT 4 422 + #define AC_DEFCFG_MISC (0xf<<8) 423 + #define AC_DEFCFG_MISC_SHIFT 8 424 + #define AC_DEFCFG_MISC_NO_PRESENCE (1<<0) 425 + #define AC_DEFCFG_COLOR (0xf<<12) 426 + #define AC_DEFCFG_COLOR_SHIFT 12 427 + #define AC_DEFCFG_CONN_TYPE (0xf<<16) 428 + #define AC_DEFCFG_CONN_TYPE_SHIFT 16 429 + #define AC_DEFCFG_DEVICE (0xf<<20) 430 + #define AC_DEFCFG_DEVICE_SHIFT 20 431 + #define AC_DEFCFG_LOCATION (0x3f<<24) 432 + #define AC_DEFCFG_LOCATION_SHIFT 24 433 + #define AC_DEFCFG_PORT_CONN (0x3<<30) 434 + #define AC_DEFCFG_PORT_CONN_SHIFT 30 435 + 436 + /* Display pin's device list entry */ 437 + #define AC_DE_PD (1<<0) 438 + #define AC_DE_ELDV (1<<1) 439 + #define AC_DE_IA (1<<2) 440 + 441 + /* device types (0x0-0xf) */ 442 + enum { 443 + AC_JACK_LINE_OUT, 444 + AC_JACK_SPEAKER, 445 + AC_JACK_HP_OUT, 446 + AC_JACK_CD, 447 + AC_JACK_SPDIF_OUT, 448 + AC_JACK_DIG_OTHER_OUT, 449 + AC_JACK_MODEM_LINE_SIDE, 450 + AC_JACK_MODEM_HAND_SIDE, 451 + AC_JACK_LINE_IN, 452 + AC_JACK_AUX, 453 + AC_JACK_MIC_IN, 454 + AC_JACK_TELEPHONY, 455 + AC_JACK_SPDIF_IN, 456 + AC_JACK_DIG_OTHER_IN, 457 + AC_JACK_OTHER = 0xf, 458 + }; 459 + 460 + /* jack connection types (0x0-0xf) */ 461 + enum { 462 + AC_JACK_CONN_UNKNOWN, 463 + AC_JACK_CONN_1_8, 464 + AC_JACK_CONN_1_4, 465 + AC_JACK_CONN_ATAPI, 466 + AC_JACK_CONN_RCA, 467 + AC_JACK_CONN_OPTICAL, 468 + AC_JACK_CONN_OTHER_DIGITAL, 469 + AC_JACK_CONN_OTHER_ANALOG, 470 + AC_JACK_CONN_DIN, 471 + AC_JACK_CONN_XLR, 472 + AC_JACK_CONN_RJ11, 473 + AC_JACK_CONN_COMB, 474 + AC_JACK_CONN_OTHER = 0xf, 475 + }; 476 + 477 + /* jack colors (0x0-0xf) */ 478 + enum { 479 + AC_JACK_COLOR_UNKNOWN, 480 + AC_JACK_COLOR_BLACK, 481 + AC_JACK_COLOR_GREY, 482 + AC_JACK_COLOR_BLUE, 483 + AC_JACK_COLOR_GREEN, 484 + AC_JACK_COLOR_RED, 485 + AC_JACK_COLOR_ORANGE, 486 + AC_JACK_COLOR_YELLOW, 487 + AC_JACK_COLOR_PURPLE, 488 + AC_JACK_COLOR_PINK, 489 + AC_JACK_COLOR_WHITE = 0xe, 490 + AC_JACK_COLOR_OTHER, 491 + }; 492 + 493 + /* Jack location (0x0-0x3f) */ 494 + /* common case */ 495 + enum { 496 + AC_JACK_LOC_NONE, 497 + AC_JACK_LOC_REAR, 498 + AC_JACK_LOC_FRONT, 499 + AC_JACK_LOC_LEFT, 500 + AC_JACK_LOC_RIGHT, 501 + AC_JACK_LOC_TOP, 502 + AC_JACK_LOC_BOTTOM, 503 + }; 504 + /* bits 4-5 */ 505 + enum { 506 + AC_JACK_LOC_EXTERNAL = 0x00, 507 + AC_JACK_LOC_INTERNAL = 0x10, 508 + AC_JACK_LOC_SEPARATE = 0x20, 509 + AC_JACK_LOC_OTHER = 0x30, 510 + }; 511 + enum { 512 + /* external on primary chasis */ 513 + AC_JACK_LOC_REAR_PANEL = 0x07, 514 + AC_JACK_LOC_DRIVE_BAY, 515 + /* internal */ 516 + AC_JACK_LOC_RISER = 0x17, 517 + AC_JACK_LOC_HDMI, 518 + AC_JACK_LOC_ATAPI, 519 + /* others */ 520 + AC_JACK_LOC_MOBILE_IN = 0x37, 521 + AC_JACK_LOC_MOBILE_OUT, 522 + }; 523 + 524 + /* Port connectivity (0-3) */ 525 + enum { 526 + AC_JACK_PORT_COMPLEX, 527 + AC_JACK_PORT_NONE, 528 + AC_JACK_PORT_FIXED, 529 + AC_JACK_PORT_BOTH, 530 + }; 531 + 532 + /* max. codec address */ 533 + #define HDA_MAX_CODEC_ADDRESS 0x0f 534 + 535 + #endif
+449
drivers/wdm/audio/hdaudbus_new/hdac_controller.cpp
··· 1 + #include "driver.h" 2 + 3 + //New 4 + NTSTATUS ResetHDAController(PFDO_CONTEXT fdoCtx, BOOLEAN wakeup) { 5 + UINT32 gctl; 6 + 7 + //Clear STATESTS 8 + hda_write16(fdoCtx, STATESTS, STATESTS_INT_MASK); 9 + 10 + //Stop all Streams DMA Engine 11 + for (UINT32 i = 0; i < fdoCtx->numStreams; i++) { 12 + hdac_stream_stop(&fdoCtx->streams[i]); 13 + } 14 + 15 + //Stop CORB and RIRB 16 + hda_write8(fdoCtx, CORBCTL, 0); 17 + hda_write8(fdoCtx, RIRBCTL, 0); 18 + 19 + //Reset DMA position buffer 20 + hda_write32(fdoCtx, DPLBASE, 0); 21 + hda_write32(fdoCtx, DPUBASE, 0); 22 + 23 + //Reset the controller for at least 100 us 24 + gctl = hda_read32(fdoCtx, GCTL); 25 + hda_write32(fdoCtx, GCTL, gctl & ~HDA_GCTL_RESET); 26 + 27 + for (int count = 0; count < 1000; count++) { 28 + gctl = hda_read32(fdoCtx, GCTL); 29 + if (!(gctl & HDA_GCTL_RESET)) { 30 + break; 31 + } 32 + udelay(10); 33 + } 34 + 35 + if (gctl & HDA_GCTL_RESET) { 36 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "%s Error: unable to put controller in reset\n", __func__); 37 + return STATUS_DEVICE_POWER_FAILURE; 38 + } 39 + 40 + //If wakeup not requested, leave in reset state 41 + if (!wakeup) 42 + return STATUS_SUCCESS; 43 + 44 + udelay(100); 45 + gctl = hda_read32(fdoCtx, GCTL); 46 + hda_write32(fdoCtx, GCTL, gctl | HDA_GCTL_RESET); 47 + 48 + for (int count = 0; count < 1000; count++) { 49 + gctl = hda_read32(fdoCtx, GCTL); 50 + if (gctl & HDA_GCTL_RESET) { 51 + break; 52 + } 53 + udelay(10); 54 + } 55 + if (!(gctl & HDA_GCTL_RESET)) { 56 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "%s Error: controller stuck in reset\n", __func__); 57 + return STATUS_DEVICE_POWER_FAILURE; 58 + } 59 + 60 + //Wait for codecs to finish their own reset sequence. Delay from VoodooHDA so it resets properly 61 + udelay(1000); 62 + 63 + if (!fdoCtx->codecMask) { 64 + fdoCtx->codecMask = hda_read16(fdoCtx, STATESTS); 65 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 66 + "codec mask = 0x%lx\n", fdoCtx->codecMask); 67 + } 68 + 69 + return STATUS_SUCCESS; 70 + } 71 + 72 + NTSTATUS GetHDACapabilities(PFDO_CONTEXT fdoCtx) { 73 + UINT16 gcap = hda_read16(fdoCtx, GCAP); 74 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 75 + "chipset global capabilities = 0x%x\n", gcap); 76 + 77 + fdoCtx->is64BitOK = !!(gcap & 0x1); 78 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 79 + "64 bit OK? %d\n", fdoCtx->is64BitOK); 80 + 81 + fdoCtx->hwVersion = (hda_read8(fdoCtx, VMAJ) << 8) | hda_read8(fdoCtx, VMIN); 82 + 83 + fdoCtx->captureStreams = (gcap >> 8) & 0x0f; 84 + fdoCtx->playbackStreams = (gcap >> 12) & 0x0f; 85 + 86 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 87 + "streams (cap %d, playback %d)\n", fdoCtx->captureStreams, fdoCtx->playbackStreams); 88 + 89 + fdoCtx->captureIndexOff = 0; 90 + fdoCtx->playbackIndexOff = fdoCtx->captureStreams; 91 + fdoCtx->numStreams = fdoCtx->captureStreams + fdoCtx->playbackStreams; 92 + 93 + UINT8 corbSize = hda_read8(fdoCtx, CORBSIZE); 94 + if (!(corbSize & 0x40)) { 95 + return STATUS_DEVICE_FEATURE_NOT_SUPPORTED; //CORB must support 256 96 + } 97 + 98 + UINT8 rirbSize = hda_read8(fdoCtx, RIRBSIZE); 99 + if (!(rirbSize & 0x40)) { 100 + return STATUS_DEVICE_FEATURE_NOT_SUPPORTED; //RIRB must support 256 101 + } 102 + 103 + return STATUS_SUCCESS; 104 + } 105 + 106 + void HDAInitCorb(PFDO_CONTEXT fdoCtx) { 107 + //Set the corb size to 256 entries 108 + hda_write8(fdoCtx, CORBSIZE, 0x02); 109 + 110 + //Setup CORB address 111 + fdoCtx->corb.buf = (UINT32*)fdoCtx->rb; 112 + fdoCtx->corb.addr = MmGetPhysicalAddress(fdoCtx->corb.buf); 113 + hda_write32(fdoCtx, CORBLBASE, fdoCtx->corb.addr.LowPart); 114 + hda_write32(fdoCtx, CORBUBASE, fdoCtx->corb.addr.HighPart); 115 + 116 + //Set WP and RP 117 + fdoCtx->corb.wp = 0; 118 + hda_write16(fdoCtx, CORBWP, fdoCtx->corb.wp); 119 + hda_write16(fdoCtx, CORBRP, HDA_CORBRP_RST); 120 + 121 + udelay(10); //Delay for 10 us to reset 122 + 123 + hda_write16(fdoCtx, CORBRP, 0); 124 + } 125 + 126 + void HDAInitRirb(PFDO_CONTEXT fdoCtx) { 127 + //Set the rirb size to 256 entries 128 + hda_write8(fdoCtx, RIRBSIZE, 0x02); 129 + 130 + //Setup RIRB address 131 + fdoCtx->rirb.buf = (UINT32*)(fdoCtx->rb + 0x800); 132 + fdoCtx->rirb.addr = MmGetPhysicalAddress(fdoCtx->rirb.buf); 133 + RtlZeroMemory(fdoCtx->rirb.cmds, sizeof(fdoCtx->rirb.cmds)); 134 + hda_write32(fdoCtx, RIRBLBASE, fdoCtx->rirb.addr.LowPart); 135 + hda_write32(fdoCtx, RIRBUBASE, fdoCtx->rirb.addr.HighPart); 136 + 137 + //Set WP and RP 138 + fdoCtx->rirb.rp = 0; 139 + hda_write16(fdoCtx, RIRBWP, HDA_RIRBWP_RST); 140 + 141 + //Set interrupt threshold 142 + hda_write16(fdoCtx, RINTCNT, 1); 143 + 144 + //Enable Received response reporting 145 + hda_write8(fdoCtx, RIRBCTL, HDA_RBCTL_IRQ_EN); 146 + } 147 + 148 + void HDAStartCorb(PFDO_CONTEXT fdoCtx) { 149 + UINT8 corbCTL; 150 + corbCTL = hda_read8(fdoCtx, CORBCTL); 151 + corbCTL |= HDA_CORBCTL_RUN; 152 + hda_write8(fdoCtx, CORBCTL, corbCTL); 153 + } 154 + 155 + void HDAStartRirb(PFDO_CONTEXT fdoCtx) { 156 + UINT8 rirbCTL; 157 + rirbCTL = hda_read8(fdoCtx, RIRBCTL); 158 + rirbCTL |= HDA_RBCTL_DMA_EN; 159 + hda_write8(fdoCtx, RIRBCTL, rirbCTL); 160 + } 161 + 162 + NTSTATUS StartHDAController(PFDO_CONTEXT fdoCtx) { 163 + NTSTATUS status; 164 + status = ResetHDAController(fdoCtx, TRUE); 165 + if (!NT_SUCCESS(status)) { 166 + goto exit; 167 + } 168 + 169 + //Clear STATESTS 170 + hda_write16(fdoCtx, STATESTS, STATESTS_INT_MASK); 171 + 172 + HDAInitCorb(fdoCtx); 173 + HDAInitRirb(fdoCtx); 174 + 175 + HDAStartCorb(fdoCtx); 176 + HDAStartRirb(fdoCtx); 177 + 178 + //Enabling Controller Interrupt 179 + hda_write32(fdoCtx, GCTL, hda_read32(fdoCtx, GCTL) | HDA_GCTL_UNSOL); 180 + hda_write32(fdoCtx, INTCTL, hda_read32(fdoCtx, INTCTL) | HDA_INT_CTRL_EN | HDA_INT_GLOBAL_EN); 181 + 182 + { 183 + //Program position buffer 184 + PHYSICAL_ADDRESS posbufAddr = MmGetPhysicalAddress(fdoCtx->posbuf); 185 + hda_write32(fdoCtx, DPLBASE, posbufAddr.LowPart); 186 + hda_write32(fdoCtx, DPUBASE, posbufAddr.HighPart); 187 + } 188 + 189 + udelay(1000); 190 + 191 + fdoCtx->ControllerEnabled = TRUE; 192 + 193 + exit: 194 + return status; 195 + } 196 + 197 + NTSTATUS StopHDAController(PFDO_CONTEXT fdoCtx) { 198 + NTSTATUS status = ResetHDAController(fdoCtx, FALSE); 199 + fdoCtx->ControllerEnabled = FALSE; 200 + return status; 201 + } 202 + 203 + static UINT16 HDACommandAddr(UINT32 cmd) { 204 + return (cmd >> 28) & 0xF; 205 + } 206 + 207 + NTSTATUS SendHDACmds(PFDO_CONTEXT fdoCtx, ULONG count, PHDAUDIO_CODEC_TRANSFER CodecTransfer) { 208 + WdfInterruptAcquireLock(fdoCtx->Interrupt); 209 + for (ULONG i = 0; i < count; i++) { 210 + PHDAUDIO_CODEC_TRANSFER transfer = &CodecTransfer[i]; 211 + RtlZeroMemory(&transfer->Input, sizeof(transfer->Input)); 212 + 213 + UINT16 addr = HDACommandAddr(transfer->Output.Command); 214 + 215 + //Add command to corb 216 + UINT16 wp = hda_read16(fdoCtx, CORBWP); 217 + if (wp == 0xffff) { 218 + //Something wrong, controller likely went to sleep 219 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 220 + "%s: device not found\n", __func__); 221 + WdfInterruptReleaseLock(fdoCtx->Interrupt); 222 + return STATUS_DEVICE_DOES_NOT_EXIST; 223 + } 224 + 225 + wp++; 226 + wp %= HDA_MAX_CORB_ENTRIES; 227 + 228 + UINT16 rp = hda_read16(fdoCtx, CORBRP); 229 + if (wp == rp) { 230 + //Oops it's full 231 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 232 + "%s: device busy\n", __func__); 233 + WdfInterruptReleaseLock(fdoCtx->Interrupt); 234 + return STATUS_RETRY; 235 + } 236 + 237 + LONG oldVal = InterlockedIncrement(&fdoCtx->rirb.cmds[addr]); 238 + fdoCtx->rirb.xfer[addr].xfer[oldVal - 1] = transfer; 239 + 240 + fdoCtx->corb.buf[wp] = transfer->Output.Command; 241 + 242 + hda_write16(fdoCtx, CORBWP, wp); 243 + } 244 + 245 + WdfInterruptReleaseLock(fdoCtx->Interrupt); 246 + return STATUS_SUCCESS; 247 + } 248 + 249 + NTSTATUS RunSingleHDACmd(PFDO_CONTEXT fdoCtx, ULONG val, ULONG* res) { 250 + HDAUDIO_CODEC_TRANSFER transfer = { 0 }; 251 + transfer.Output.Command = val; 252 + 253 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 254 + "%s: Called. Command: 0x%x\n", __func__, val); 255 + 256 + NTSTATUS status = SendHDACmds(fdoCtx, 1, &transfer); 257 + if (!NT_SUCCESS(status)) { 258 + return status; 259 + } 260 + 261 + UINT16 addr = HDACommandAddr(transfer.Output.Command); 262 + status = HDA_WaitForTransfer(fdoCtx, addr, 1, &transfer); 263 + if (transfer.Input.IsValid && res) { 264 + *res = transfer.Input.Response; 265 + } 266 + return status; 267 + } 268 + 269 + #define HDA_RIRB_EX_UNSOL_EV (1<<4) 270 + 271 + static void HDAFlushRIRB(PFDO_CONTEXT fdoCtx) { 272 + UINT16 wp, addr; 273 + 274 + wp = hda_read16(fdoCtx, RIRBWP); 275 + if (wp == 0xffff) { 276 + //Invalid WP 277 + return; 278 + } 279 + 280 + if (wp == fdoCtx->rirb.wp) 281 + return; 282 + fdoCtx->rirb.wp = wp; 283 + 284 + while (fdoCtx->rirb.rp != wp) { 285 + fdoCtx->rirb.rp++; 286 + fdoCtx->rirb.rp %= HDA_MAX_RIRB_ENTRIES; 287 + 288 + HDAC_RIRB rirb = fdoCtx->rirb.rirbbuf[fdoCtx->rirb.rp]; 289 + 290 + addr = rirb.response_ex & 0xf; 291 + if (addr >= HDA_MAX_CODECS) { 292 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 293 + "Unexpected unsolicited response %x: %x\n", 294 + rirb.response, rirb.response_ex); 295 + } 296 + else if (rirb.response_ex & HDA_RIRB_EX_UNSOL_EV) { 297 + HDAUDIO_CODEC_RESPONSE response; 298 + RtlZeroMemory(&response, sizeof(HDAUDIO_CODEC_RESPONSE)); 299 + 300 + response.SDataIn = addr; 301 + response.Response = rirb.response; 302 + response.IsUnsolicitedResponse = 1; 303 + response.IsValid = 1; 304 + 305 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 306 + "Unsol response on 0x%x: 0x%x\n", addr, response.Response); 307 + 308 + PPDO_DEVICE_DATA codec = fdoCtx->codecs[addr]; 309 + if (!codec || codec->FdoContext != fdoCtx) 310 + continue; 311 + 312 + UINT Tag = response.Unsolicited.Tag; 313 + CODEC_UNSOLICITED_CALLBACK callback = codec->unsolitCallbacks[Tag]; 314 + if (callback.inUse && callback.Routine) { 315 + callback.Routine(response, callback.Context); 316 + } 317 + } 318 + else if (InterlockedAdd(&fdoCtx->rirb.cmds[addr], 0)) { 319 + PHDAC_CODEC_XFER codecXfer = &fdoCtx->rirb.xfer[addr]; 320 + if (codecXfer->xfer[0]) { 321 + codecXfer->xfer[0]->Input.SDataIn = addr; 322 + codecXfer->xfer[0]->Input.Response = rirb.response; 323 + codecXfer->xfer[0]->Input.IsValid = 1; 324 + 325 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 326 + "Got response on 0x%x for 0x%x: 0x%x\n", addr, codecXfer->xfer[0]->Output.Command, rirb.response); 327 + } 328 + else { 329 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 330 + "Got response 0x%x but no xfer!\n", rirb.response); 331 + } 332 + 333 + RtlMoveMemory(&codecXfer->xfer[0], &codecXfer->xfer[1], sizeof(PHDAUDIO_CODEC_TRANSFER) * (HDA_MAX_CORB_ENTRIES - 1)); 334 + codecXfer->xfer[HDA_MAX_CORB_ENTRIES - 1] = NULL; 335 + if (!InterlockedDecrement(&fdoCtx->rirb.cmds[addr])) { 336 + SklHdAudBusPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "Empty queue for 0x%x\n", addr); 337 + KeSetEvent(&fdoCtx->rirb.xferEvent[addr], IO_NO_INCREMENT, FALSE); 338 + } 339 + } 340 + else { 341 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 342 + "Unexpected unsolicited response from address %d %x\n", addr, 343 + rirb.response); 344 + } 345 + } 346 + } 347 + 348 + int hda_stream_interrupt(PFDO_CONTEXT fdoCtx, unsigned int status) { 349 + int handled = 0; 350 + UINT8 sd_status; 351 + 352 + for (UINT32 i = 0; i < fdoCtx->numStreams; i++) { 353 + PHDAC_STREAM stream = &fdoCtx->streams[i]; 354 + if (status & stream->int_sta_mask) { 355 + sd_status = stream_read8(stream, SD_STS); 356 + stream_write8(stream, SD_STS, SD_INT_MASK); 357 + handled |= 1 << stream->idx; 358 + 359 + if (sd_status & SD_INT_COMPLETE) { 360 + if (stream->isr.IOC && stream->isr.IsrCallback) { 361 + stream->isr.IsrCallback( 362 + stream->isr.CallbackContext, 363 + sd_status); 364 + } 365 + stream->irqReceived = TRUE; 366 + } 367 + } 368 + } 369 + return handled; 370 + } 371 + 372 + BOOLEAN 373 + NTAPI 374 + hda_interrupt( 375 + WDFINTERRUPT Interrupt, 376 + ULONG MessageID) { 377 + UNREFERENCED_PARAMETER(MessageID); 378 + 379 + WDFDEVICE Device = WdfInterruptGetDevice(Interrupt); 380 + PFDO_CONTEXT fdoCtx = Fdo_GetContext(Device); 381 + 382 + BOOLEAN handled = FALSE; 383 + 384 + if (fdoCtx->dspInterruptCallback) { 385 + handled = (BOOLEAN)fdoCtx->dspInterruptCallback(fdoCtx->dspInterruptContext); 386 + } 387 + 388 + if (!fdoCtx->ControllerEnabled) 389 + return handled; 390 + 391 + UINT32 status = hda_read32(fdoCtx, INTSTS); 392 + if (status == 0 || status == 0xffffffff) 393 + return handled; 394 + 395 + handled = TRUE; 396 + 397 + if (hda_stream_interrupt(fdoCtx, status)) { 398 + WdfInterruptQueueDpcForIsr(Interrupt); 399 + } 400 + 401 + status = hda_read8(fdoCtx, RIRBSTS); 402 + if (status & RIRB_INT_MASK) { 403 + hda_write8(fdoCtx, RIRBSTS, RIRB_INT_MASK); 404 + if (status & RIRB_INT_RESPONSE) { 405 + fdoCtx->processRirb = TRUE; 406 + WdfInterruptQueueDpcForIsr(Interrupt); 407 + } 408 + } 409 + 410 + return handled; 411 + } 412 + 413 + void 414 + NTAPI 415 + hda_dpc( 416 + WDFINTERRUPT Interrupt, 417 + WDFOBJECT AssociatedObject 418 + ) { 419 + UNREFERENCED_PARAMETER(AssociatedObject); 420 + 421 + WDFDEVICE Device = WdfInterruptGetDevice(Interrupt); 422 + PFDO_CONTEXT fdoCtx = Fdo_GetContext(Device); 423 + 424 + for (UINT32 i = 0; i < fdoCtx->numStreams; i++) { 425 + PHDAC_STREAM stream = &fdoCtx->streams[i]; 426 + if (stream->irqReceived) { 427 + stream->irqReceived = FALSE; 428 + 429 + for (int j = 0; j < MAX_NOTIF_EVENTS; j++) { 430 + if (stream->registeredCallbacks[j].InUse) { 431 + LARGE_INTEGER unknownVal = { 0 }; 432 + KeQuerySystemTime(&unknownVal); 433 + stream->registeredCallbacks[j].NotificationCallback(stream->registeredCallbacks[j].CallbackContext, unknownVal); 434 + } 435 + } 436 + 437 + for (int j = 0; j < MAX_NOTIF_EVENTS; j++) { 438 + if (stream->registeredEvents[j]) { 439 + KeSetEvent(stream->registeredEvents[j], IO_NO_INCREMENT, FALSE); 440 + } 441 + } 442 + } 443 + } 444 + 445 + if (fdoCtx->processRirb) { 446 + fdoCtx->processRirb = FALSE; 447 + HDAFlushRIRB(fdoCtx); 448 + } 449 + }
+25
drivers/wdm/audio/hdaudbus_new/hdac_controller.h
··· 1 + #if !defined(_HDA_CONTROLLER_H_) 2 + #define _HDA_CONTROLLER_H_ 3 + 4 + typedef struct _HDA_ASYNC_CONTEXT { 5 + PPDO_DEVICE_DATA devData; 6 + ULONG Count; 7 + PHDAUDIO_CODEC_TRANSFER CodecTransfer; 8 + PHDAUDIO_TRANSFER_COMPLETE_CALLBACK Callback; 9 + PVOID CallbackContext; 10 + } HDA_ASYNC_CONTEXT, * PHDA_ASYNC_CONTEXT; 11 + 12 + WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(HDA_ASYNC_CONTEXT, HDAAsyncWorkItem_GetContext); 13 + 14 + //New 15 + NTSTATUS GetHDACapabilities(PFDO_CONTEXT fdoCtx); 16 + NTSTATUS StartHDAController(PFDO_CONTEXT fdoCtx); 17 + NTSTATUS StopHDAController(PFDO_CONTEXT fdoCtx); 18 + NTSTATUS SendHDACmds(PFDO_CONTEXT fdoCtx, ULONG count, PHDAUDIO_CODEC_TRANSFER CodecTransfer); 19 + NTSTATUS RunSingleHDACmd(PFDO_CONTEXT fdoCtx, ULONG val, ULONG* res); 20 + 21 + //Old 22 + BOOLEAN NTAPI hda_interrupt(WDFINTERRUPT Interrupt, ULONG MessageID); 23 + void NTAPI hda_dpc(WDFINTERRUPT Interrupt, WDFOBJECT AssociatedObject); 24 + 25 + #endif
+176
drivers/wdm/audio/hdaudbus_new/hdac_stream.cpp
··· 1 + #include "driver.h" 2 + 3 + void hdac_stream_start(PHDAC_STREAM stream) { 4 + hda_read32(stream->FdoContext, WALLCLK); 5 + 6 + /* enable SIE */ 7 + hda_update32(stream->FdoContext, INTCTL, 1 << stream->idx, 1 << stream->idx); 8 + 9 + /* set stripe control */ 10 + if (stream->stripe) { 11 + UINT8 stripe_ctl = 1; 12 + stream_update8(stream, SD_CTL_3B, SD_CTL_STRIPE_MASK, 13 + stripe_ctl); 14 + } 15 + 16 + /* set DMA start and interrupt mask */ 17 + stream_update8(stream, SD_CTL, 0, SD_CTL_DMA_START | SD_INT_MASK); 18 + stream->running = TRUE; 19 + } 20 + 21 + void hdac_stream_clear(PHDAC_STREAM stream) { 22 + stream_update8(stream, SD_CTL, SD_CTL_DMA_START | SD_INT_MASK, 0); 23 + stream_write8(stream, SD_STS, SD_INT_MASK); /* to be sure */ 24 + if (stream->stripe) 25 + stream_update8(stream, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0); 26 + 27 + stream->running = FALSE; 28 + } 29 + 30 + void hdac_stream_stop(PHDAC_STREAM stream) { 31 + hdac_stream_clear(stream); 32 + 33 + /* disable SIE */ 34 + hda_update32(stream->FdoContext, INTCTL, 1 << stream->idx, 0); 35 + } 36 + 37 + void hdac_stream_reset(PHDAC_STREAM stream) { 38 + hdac_stream_clear(stream); 39 + 40 + stream_update8(stream, SD_CTL, 0, SD_CTL_STREAM_RESET); 41 + KeStallExecutionProcessor(3); 42 + int timeout = 300; 43 + 44 + UCHAR val; 45 + do { 46 + val = stream_read8(stream, SD_CTL) & SD_CTL_STREAM_RESET; 47 + if (val) 48 + break; 49 + } while (--timeout); 50 + 51 + val &= ~SD_CTL_STREAM_RESET; 52 + stream_write8(stream, SD_CTL, val); 53 + KeStallExecutionProcessor(3); 54 + 55 + timeout = 300; 56 + /* waiting for hardware to report that the stream is out of reset */ 57 + do { 58 + val = stream_read8(stream, SD_CTL) & SD_CTL_STREAM_RESET; 59 + if (!val) 60 + break; 61 + } while (--timeout); 62 + 63 + if (stream->posbuf) 64 + *stream->posbuf = 0; 65 + } 66 + 67 + UINT16 hdac_format(PHDAC_STREAM stream) { 68 + UINT16 format = 0; 69 + 70 + switch (stream->streamFormat.SampleRate) { 71 + case 8000: 72 + format = HDA_RATE(48, 1, 6); 73 + break; 74 + case 9600: 75 + format = HDA_RATE(48, 1, 5); 76 + break; 77 + case 11025: 78 + format = HDA_RATE(44, 1, 4); 79 + break; 80 + case 16000: 81 + format = HDA_RATE(48, 1, 3); 82 + break; 83 + case 22050: 84 + format = HDA_RATE(44, 1, 2); 85 + break; 86 + case 32000: 87 + format = HDA_RATE(48, 2, 3); 88 + break; 89 + case 44100: 90 + format = HDA_RATE(44, 1, 1); 91 + break; 92 + case 48000: 93 + format = HDA_RATE(48, 1, 1); 94 + break; 95 + case 88200: 96 + format = HDA_RATE(44, 2, 1); 97 + break; 98 + case 96000: 99 + format = HDA_RATE(48, 2, 1); 100 + break; 101 + case 176400: 102 + format = HDA_RATE(44, 4, 1); 103 + break; 104 + case 192000: 105 + format = HDA_RATE(48, 4, 1); 106 + break; 107 + } 108 + 109 + { 110 + UINT16 channels = stream->streamFormat.NumberOfChannels; 111 + if (channels == 0 || channels > 8) 112 + return 0; 113 + format |= channels - 1; 114 + 115 + switch (stream->streamFormat.ContainerSize) { 116 + case 8: 117 + format |= AC_FMT_BITS_8; 118 + break; 119 + case 16: 120 + format |= AC_FMT_BITS_16; 121 + break; 122 + case 20: 123 + format |= AC_FMT_BITS_20; 124 + break; 125 + case 24: 126 + format |= AC_FMT_BITS_24; 127 + break; 128 + case 32: 129 + format |= AC_FMT_BITS_32; 130 + break; 131 + } 132 + } 133 + return format; 134 + } 135 + 136 + void hdac_stream_setup(PHDAC_STREAM stream) { 137 + /* make sure the run bit is zero for SD */ 138 + hdac_stream_clear(stream); 139 + 140 + UINT val; 141 + /* program the stream_tag */ 142 + val = stream_read32(stream, SD_CTL); 143 + val = (val & ~SD_CTL_STREAM_TAG_MASK) | 144 + (stream->streamTag << SD_CTL_STREAM_TAG_SHIFT); 145 + stream_write32(stream, SD_CTL, val); 146 + 147 + /* program the length of samples in cyclic buffer */ 148 + stream_write32(stream, SD_CBL, stream->bufSz); 149 + 150 + /* program the stream format */ 151 + /* this value needs to be the same as the one programmed */ 152 + UINT16 format = hdac_format(stream); 153 + stream_write16(stream, SD_FORMAT, format); 154 + 155 + /* program the stream LVI (last valid index) of the BDL */ 156 + stream_write16(stream, SD_LVI, stream->numBlocks - 1); 157 + 158 + /* program the BDL address */ 159 + /* lower BDL address */ 160 + PHYSICAL_ADDRESS bdlAddr = MmGetPhysicalAddress(stream->bdl); 161 + stream_write32(stream, SD_BDLPL, bdlAddr.LowPart); 162 + /* upper BDL address */ 163 + stream_write32(stream, SD_BDLPU, bdlAddr.HighPart); 164 + 165 + //Enable position buffer 166 + if (!(hda_read32(stream->FdoContext, DPLBASE) & HDA_DPLBASE_ENABLE)){ 167 + PHYSICAL_ADDRESS posbufAddr = MmGetPhysicalAddress(stream->FdoContext->posbuf); 168 + hda_write32(stream->FdoContext, DPLBASE, posbufAddr.LowPart | HDA_DPLBASE_ENABLE); 169 + } 170 + 171 + /* set the interrupt enable bits in the descriptor control register */ 172 + stream_update32(stream, SD_CTL, 0, SD_INT_MASK); 173 + 174 + stream->fifoSize = 0; 175 + stream->fifoSize = stream_read16(stream, SD_FIFOSIZE) + 1; 176 + }
+6
drivers/wdm/audio/hdaudbus_new/hdac_stream.h
··· 1 + UINT16 hdac_format(PHDAC_STREAM stream); 2 + 3 + void hdac_stream_start(PHDAC_STREAM stream); 4 + void hdac_stream_stop(PHDAC_STREAM stream); 5 + void hdac_stream_reset(PHDAC_STREAM stream); 6 + void hdac_stream_setup(PHDAC_STREAM stream);
+1173
drivers/wdm/audio/hdaudbus_new/hdaudio.cpp
··· 1 + #include "driver.h" 2 + 3 + NTSTATUS HDA_WaitForTransfer( 4 + PFDO_CONTEXT fdoCtx, 5 + UINT16 codecAddr, 6 + _In_ ULONG Count, 7 + _Inout_updates_(Count) 8 + PHDAUDIO_CODEC_TRANSFER CodecTransfer 9 + ) { 10 + NTSTATUS status = STATUS_SUCCESS; 11 + 12 + SklHdAudBusPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "%s called (Count: %d)!\n", __func__, Count); 13 + 14 + LARGE_INTEGER Timeout; 15 + Timeout.QuadPart = -10LL * 1000LL * 1000LL * (LONGLONG)Count; 16 + status = KeWaitForSingleObject(&fdoCtx->rirb.xferEvent[codecAddr], Executive, KernelMode, FALSE, &Timeout); 17 + KeClearEvent(&fdoCtx->rirb.xferEvent[codecAddr]); 18 + 19 + SklHdAudBusPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "%s wait status: 0x%x!\n", __func__, status); 20 + 21 + ULONG TransferredCount = 0; 22 + for (ULONG i = 0; i < Count; i++) { 23 + if (CodecTransfer[i].Input.IsValid) { 24 + TransferredCount++; 25 + } 26 + } 27 + 28 + if (TransferredCount < Count) { 29 + InterlockedAdd(&fdoCtx->rirb.cmds[codecAddr], TransferredCount - Count); 30 + 31 + SklHdAudBusPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "%s timeout (Count: %d, transferred %d)!\n", __func__, Count, TransferredCount); 32 + status = STATUS_IO_TIMEOUT; 33 + goto out; 34 + } 35 + 36 + out: 37 + SklHdAudBusPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "%s exit (Count: %d)!\n", __func__, Count); 38 + return status; 39 + } 40 + 41 + void 42 + NTAPI 43 + HDA_AsyncWait(WDFWORKITEM WorkItem) { 44 + PHDA_ASYNC_CONTEXT workItemContext = HDAAsyncWorkItem_GetContext(WorkItem); 45 + 46 + SklHdAudBusPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "%s called (Count: %d)!\n", __func__, workItemContext->Count); 47 + 48 + NTSTATUS status = HDA_WaitForTransfer( 49 + workItemContext->devData->FdoContext, 50 + (UINT16)workItemContext->devData->CodecIds.CodecAddress, 51 + workItemContext->Count, 52 + workItemContext->CodecTransfer 53 + ); 54 + UNREFERENCED_PARAMETER(status); 55 + 56 + workItemContext->Callback( 57 + workItemContext->CodecTransfer, 58 + workItemContext->CallbackContext 59 + ); 60 + 61 + PFDO_CONTEXT fdoCtx = workItemContext->devData->FdoContext; 62 + WdfDeviceResumeIdle(fdoCtx->WdfDevice); 63 + WdfObjectDelete(WorkItem); 64 + 65 + SklHdAudBusPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "%s exit (Count: %d)!\n", __func__); 66 + } 67 + 68 + NTSTATUS 69 + NTAPI 70 + HDA_TransferCodecVerbs( 71 + _In_ PVOID _context, 72 + _In_ ULONG Count, 73 + _Inout_updates_(Count) 74 + PHDAUDIO_CODEC_TRANSFER CodecTransfer, 75 + _In_opt_ PHDAUDIO_TRANSFER_COMPLETE_CALLBACK Callback, 76 + _In_opt_ PVOID Context 77 + ) { 78 + SklHdAudBusPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "%s called (Count: %d, Callback? %d)!\n", __func__, Count, Callback != NULL); 79 + 80 + if (!_context) 81 + return STATUS_NO_SUCH_DEVICE; 82 + 83 + NTSTATUS status = STATUS_SUCCESS; 84 + 85 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 86 + if (!devData->FdoContext) { 87 + return STATUS_NO_SUCH_DEVICE; 88 + } 89 + 90 + PFDO_CONTEXT fdoCtx = devData->FdoContext; 91 + if (devData->CodecIds.IsGraphicsCodec) { 92 + if (!fdoCtx->GraphicsCodecConnected) { 93 + SklHdAudBusPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "Gfx codec 0x%x disconnected! Not transferring.\n", devData->CodecIds.CodecAddress); 94 + return STATUS_DEVICE_NOT_CONNECTED; 95 + } 96 + } 97 + 98 + status = WdfDeviceStopIdle(devData->FdoContext->WdfDevice, TRUE); 99 + if (!NT_SUCCESS(status)) { 100 + return status; 101 + } 102 + 103 + status = SendHDACmds(fdoCtx, Count, CodecTransfer); 104 + if (!NT_SUCCESS(status)) { 105 + goto out; 106 + } 107 + 108 + if (Callback) { //TODO: Do this async 109 + WDF_WORKITEM_CONFIG workItemConfig; 110 + WDF_WORKITEM_CONFIG_INIT(&workItemConfig, HDA_AsyncWait); 111 + 112 + WDF_OBJECT_ATTRIBUTES attributes; 113 + WDFWORKITEM workItem; 114 + 115 + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 116 + WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE( 117 + &attributes, 118 + HDA_ASYNC_CONTEXT 119 + ); 120 + attributes.ParentObject = fdoCtx->WdfDevice; 121 + 122 + WdfWorkItemCreate(&workItemConfig, &attributes, &workItem); 123 + 124 + PHDA_ASYNC_CONTEXT workItemContext = HDAAsyncWorkItem_GetContext(workItem); 125 + workItemContext->devData = devData; 126 + workItemContext->Count = Count; 127 + workItemContext->CodecTransfer = CodecTransfer; 128 + workItemContext->Callback = Callback; 129 + workItemContext->CallbackContext = Context; 130 + WdfWorkItemEnqueue(workItem); 131 + } 132 + else { 133 + status = HDA_WaitForTransfer(fdoCtx, (UINT16)devData->CodecIds.CodecAddress, Count, CodecTransfer); 134 + if (!NT_SUCCESS(status)) { 135 + goto out; 136 + } 137 + } 138 + 139 + status = STATUS_SUCCESS; 140 + 141 + out: 142 + if (!Callback) 143 + WdfDeviceResumeIdle(fdoCtx->WdfDevice); 144 + SklHdAudBusPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "%s exit (Count: %d)!\n", __func__, Count); 145 + return status; 146 + } 147 + 148 + NTSTATUS 149 + NTAPI 150 + HDA_AllocateCaptureDmaEngine( 151 + _In_ PVOID _context, 152 + _In_ UCHAR CodecAddress, 153 + _In_ PHDAUDIO_STREAM_FORMAT StreamFormat, 154 + _Out_ PHANDLE Handle, 155 + _Out_ PHDAUDIO_CONVERTER_FORMAT ConverterFormat 156 + ) { 157 + UNREFERENCED_PARAMETER(CodecAddress); 158 + 159 + if (KeGetCurrentIrql() > PASSIVE_LEVEL) { 160 + return STATUS_UNSUCCESSFUL; 161 + } 162 + 163 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 164 + if (!devData->FdoContext) { 165 + return STATUS_NO_SUCH_DEVICE; 166 + } 167 + 168 + PFDO_CONTEXT fdoContext = devData->FdoContext; 169 + 170 + NTSTATUS status = WdfDeviceStopIdle(devData->FdoContext->WdfDevice, TRUE); 171 + if (!NT_SUCCESS(status)) { 172 + return status; 173 + } 174 + 175 + WdfInterruptAcquireLock(devData->FdoContext->Interrupt); 176 + for (UINT32 i = 0; i < fdoContext->captureStreams; i++) { 177 + int tag = fdoContext->captureIndexOff + i; 178 + PHDAC_STREAM stream = &fdoContext->streams[tag]; 179 + if (stream->PdoContext != NULL) { 180 + continue; 181 + } 182 + 183 + stream->PdoContext = devData; 184 + stream->running = FALSE; 185 + stream->streamFormat = *StreamFormat; 186 + 187 + ConverterFormat->ConverterFormat = hdac_format(stream); 188 + 189 + if (Handle) 190 + *Handle = (HANDLE)stream; 191 + 192 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 193 + return STATUS_SUCCESS; 194 + } 195 + 196 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 197 + WdfDeviceResumeIdle(devData->FdoContext->WdfDevice); 198 + return STATUS_INSUFFICIENT_RESOURCES; 199 + } 200 + 201 + NTSTATUS 202 + NTAPI 203 + HDA_AllocateRenderDmaEngine( 204 + _In_ PVOID _context, 205 + _In_ PHDAUDIO_STREAM_FORMAT StreamFormat, 206 + _In_ BOOLEAN Stripe, 207 + _Out_ PHANDLE Handle, 208 + _Out_ PHDAUDIO_CONVERTER_FORMAT ConverterFormat 209 + ) { 210 + if (KeGetCurrentIrql() > PASSIVE_LEVEL) { 211 + return STATUS_UNSUCCESSFUL; 212 + } 213 + 214 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 215 + if (!devData->FdoContext) { 216 + return STATUS_NO_SUCH_DEVICE; 217 + } 218 + 219 + PFDO_CONTEXT fdoContext = devData->FdoContext; 220 + 221 + NTSTATUS status = WdfDeviceStopIdle(devData->FdoContext->WdfDevice, TRUE); 222 + if (!NT_SUCCESS(status)) { 223 + return status; 224 + } 225 + 226 + WdfInterruptAcquireLock(devData->FdoContext->Interrupt); 227 + for (UINT32 i = 0; i < fdoContext->playbackStreams; i++) { 228 + int tag = fdoContext->playbackIndexOff + i; 229 + PHDAC_STREAM stream = &fdoContext->streams[tag]; 230 + if (stream->PdoContext != NULL) { 231 + continue; 232 + } 233 + 234 + stream->stripe = Stripe; 235 + stream->PdoContext = devData; 236 + stream->running = FALSE; 237 + stream->streamFormat = *StreamFormat; 238 + 239 + ConverterFormat->ConverterFormat = hdac_format(stream); 240 + 241 + if (Handle) 242 + *Handle = (HANDLE)stream; 243 + 244 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 245 + return STATUS_SUCCESS; 246 + } 247 + 248 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 249 + WdfDeviceResumeIdle(devData->FdoContext->WdfDevice); 250 + return STATUS_INSUFFICIENT_RESOURCES; 251 + } 252 + 253 + NTSTATUS 254 + NTAPI 255 + HDA_ChangeBandwidthAllocation( 256 + _In_ PVOID _context, 257 + _In_ HANDLE Handle, 258 + _In_ PHDAUDIO_STREAM_FORMAT StreamFormat, 259 + _Out_ PHDAUDIO_CONVERTER_FORMAT ConverterFormat 260 + ) { 261 + if (KeGetCurrentIrql() > PASSIVE_LEVEL) { 262 + return STATUS_UNSUCCESSFUL; 263 + } 264 + 265 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 266 + if (!devData->FdoContext) { 267 + return STATUS_NO_SUCH_DEVICE; 268 + } 269 + 270 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 271 + if (stream->PdoContext != devData) { 272 + return STATUS_INVALID_HANDLE; 273 + } 274 + 275 + WdfInterruptAcquireLock(devData->FdoContext->Interrupt); 276 + 277 + if (stream->running) { 278 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 279 + return STATUS_INVALID_DEVICE_REQUEST; 280 + } 281 + 282 + stream->streamFormat = *StreamFormat; 283 + ConverterFormat->ConverterFormat = hdac_format(stream); 284 + 285 + hdac_stream_setup(stream); 286 + 287 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 288 + 289 + SklHdAudBusPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "%s called!\n", __func__); 290 + 291 + return STATUS_SUCCESS; 292 + } 293 + 294 + NTSTATUS 295 + NTAPI 296 + HDA_FreeDmaEngine( 297 + _In_ PVOID _context, 298 + _In_ HANDLE Handle 299 + ) { 300 + if (KeGetCurrentIrql() > PASSIVE_LEVEL) { 301 + return STATUS_UNSUCCESSFUL; 302 + } 303 + 304 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 305 + if (!devData->FdoContext) { 306 + return STATUS_NO_SUCH_DEVICE; 307 + } 308 + 309 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 310 + if (stream->PdoContext != devData) { 311 + return STATUS_INVALID_HANDLE; 312 + } 313 + 314 + WdfInterruptAcquireLock(devData->FdoContext->Interrupt); 315 + 316 + if (stream->running) { 317 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 318 + return STATUS_INVALID_DEVICE_REQUEST; 319 + } 320 + 321 + stream->PdoContext = NULL; 322 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 323 + 324 + WdfDeviceResumeIdle(devData->FdoContext->WdfDevice); 325 + 326 + return STATUS_SUCCESS; 327 + } 328 + 329 + NTSTATUS 330 + NTAPI 331 + HDA_SetDmaEngineState( 332 + _In_ PVOID _context, 333 + _In_ HDAUDIO_STREAM_STATE StreamState, 334 + _In_ ULONG NumberOfHandles, 335 + _In_reads_(NumberOfHandles) PHANDLE Handles 336 + ) { 337 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 338 + if (!devData->FdoContext) { 339 + return STATUS_NO_SUCH_DEVICE; 340 + } 341 + 342 + for (ULONG i = 0; i < NumberOfHandles; i++) { 343 + PHDAC_STREAM stream = (PHDAC_STREAM)Handles[i]; 344 + if (stream->PdoContext != devData) { 345 + return STATUS_INVALID_HANDLE; 346 + } 347 + 348 + WdfInterruptAcquireLock(devData->FdoContext->Interrupt); 349 + 350 + if (StreamState == RunState && !stream->running) { 351 + hdac_stream_setup(stream); 352 + hdac_stream_start(stream); 353 + stream->running = TRUE; 354 + } 355 + else if ((StreamState == PauseState || StreamState == StopState) && stream->running) { 356 + hdac_stream_stop(stream); 357 + stream->running = FALSE; 358 + } 359 + else if (StreamState == ResetState) { 360 + if (!stream->running) { 361 + hdac_stream_reset(stream); 362 + hdac_stream_setup(stream); 363 + } 364 + } 365 + 366 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 367 + } 368 + 369 + return STATUS_SUCCESS; 370 + } 371 + 372 + VOID 373 + NTAPI 374 + HDA_GetWallClockRegister( 375 + _In_ PVOID _context, 376 + _Out_ PULONG* Wallclock 377 + ) { 378 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 379 + if (!devData->FdoContext) { 380 + *Wallclock = NULL; 381 + return; 382 + } 383 + *Wallclock = (ULONG *)((devData->FdoContext)->m_BAR0.Base.baseptr + HDA_REG_WALLCLKA); 384 + } 385 + 386 + NTSTATUS 387 + NTAPI 388 + HDA_GetLinkPositionRegister( 389 + _In_ PVOID _context, 390 + _In_ HANDLE Handle, 391 + _Out_ PULONG* Position 392 + ) { 393 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 394 + if (!devData->FdoContext) { 395 + return STATUS_NO_SUCH_DEVICE; 396 + } 397 + 398 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 399 + if (stream->PdoContext != devData) { 400 + return STATUS_INVALID_HANDLE; 401 + } 402 + 403 + if (devData->CodecIds.CtlrVenId != VEN_INTEL) //Experimental Non-Intel support 404 + *Position = (ULONG*)(stream->sdAddr + HDA_REG_SD_LPIBA); 405 + else 406 + *Position = (ULONG *)stream->posbuf; //Use Posbuf for all Intel 407 + 408 + return STATUS_SUCCESS; 409 + } 410 + 411 + NTSTATUS 412 + NTAPI 413 + HDA_RegisterEventCallback( 414 + _In_ PVOID _context, 415 + _In_ PHDAUDIO_UNSOLICITED_RESPONSE_CALLBACK Routine, 416 + _In_opt_ PVOID Context, 417 + _Out_ PUCHAR Tag 418 + ) { 419 + if (!_context) 420 + return STATUS_NO_SUCH_DEVICE; 421 + 422 + 423 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 424 + if (devData->FdoContext) { 425 + WdfInterruptAcquireLock(devData->FdoContext->Interrupt); 426 + } 427 + 428 + for (UINT8 i = 0; i < MAX_UNSOLICIT_CALLBACKS; i++) { 429 + if (devData->unsolitCallbacks[i].inUse) 430 + continue; 431 + 432 + if (Tag) 433 + *Tag = i; 434 + 435 + devData->unsolitCallbacks[i].inUse = TRUE; 436 + devData->unsolitCallbacks[i].Context = Context; 437 + devData->unsolitCallbacks[i].Routine = Routine; 438 + 439 + if (devData->FdoContext) { 440 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 441 + } 442 + return STATUS_SUCCESS; 443 + } 444 + 445 + if (devData->FdoContext) { 446 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 447 + } 448 + return STATUS_INSUFFICIENT_RESOURCES; 449 + } 450 + 451 + NTSTATUS 452 + NTAPI 453 + HDA_UnregisterEventCallback( 454 + _In_ PVOID _context, 455 + _In_ UCHAR Tag 456 + ) { 457 + if (!_context) 458 + return STATUS_NO_SUCH_DEVICE; 459 + 460 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 461 + if (!devData->unsolitCallbacks[Tag].inUse) { 462 + return STATUS_NOT_FOUND; 463 + } 464 + 465 + if (devData->FdoContext) { 466 + WdfInterruptAcquireLock(devData->FdoContext->Interrupt); 467 + } 468 + 469 + devData->unsolitCallbacks[Tag].Routine = NULL; 470 + devData->unsolitCallbacks[Tag].Context = NULL; 471 + devData->unsolitCallbacks[Tag].inUse = FALSE; 472 + 473 + if (devData->FdoContext) { 474 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 475 + } 476 + 477 + return STATUS_SUCCESS; 478 + } 479 + 480 + NTSTATUS 481 + NTAPI 482 + HDA_GetDeviceInformation( 483 + _In_ PVOID _context, 484 + _Inout_ PHDAUDIO_DEVICE_INFORMATION DeviceInformation 485 + ) { 486 + if (!_context) 487 + return STATUS_NO_SUCH_DEVICE; 488 + 489 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 490 + if (!devData->FdoContext) { 491 + return STATUS_NO_SUCH_DEVICE; 492 + } 493 + 494 + if (DeviceInformation->Size >= sizeof(HDAUDIO_DEVICE_INFORMATION)) { 495 + DeviceInformation->CodecsDetected = devData->FdoContext->numCodecs; 496 + DeviceInformation->DeviceVersion = devData->FdoContext->hwVersion; 497 + DeviceInformation->DriverVersion = 0x100; 498 + DeviceInformation->IsStripingSupported = TRUE; 499 + } 500 + if (DeviceInformation->Size >= sizeof(HDAUDIO_DEVICE_INFORMATION_V2)) { 501 + PHDAUDIO_DEVICE_INFORMATION_V2 DeviceInformationV2 = (PHDAUDIO_DEVICE_INFORMATION_V2)DeviceInformation; 502 + DeviceInformationV2->CtrlRevision = devData->FdoContext->revId; 503 + DeviceInformationV2->CtrlVendorId = devData->FdoContext->venId; 504 + DeviceInformationV2->CtrlDeviceId = devData->FdoContext->devId; 505 + } 506 + 507 + return STATUS_SUCCESS; 508 + } 509 + 510 + void 511 + NTAPI 512 + HDA_GetResourceInformation( 513 + _In_ PVOID _context, 514 + _Out_ PUCHAR CodecAddress, 515 + _Out_ PUCHAR FunctionGroupStartNode 516 + ) { 517 + if (!_context) 518 + return; 519 + 520 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 521 + if (CodecAddress) 522 + *CodecAddress = (UINT8)devData->CodecIds.CodecAddress; 523 + if (FunctionGroupStartNode) 524 + *FunctionGroupStartNode = devData->CodecIds.FunctionGroupStartNode; 525 + } 526 + 527 + NTSTATUS 528 + NTAPI 529 + HDA_AllocateDmaBufferWithNotification( 530 + _In_ PVOID _context, 531 + _In_ HANDLE Handle, 532 + _In_ ULONG NotificationCount, 533 + _In_ SIZE_T RequestedBufferSize, 534 + _Out_ PMDL* BufferMdl, 535 + _Out_ PSIZE_T AllocatedBufferSize, 536 + _Out_ PSIZE_T OffsetFromFirstPage, 537 + _Out_ PUCHAR StreamId, 538 + _Out_ PULONG FifoSize 539 + ) { 540 + if (KeGetCurrentIrql() > PASSIVE_LEVEL) { 541 + return STATUS_UNSUCCESSFUL; 542 + } 543 + 544 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 545 + if (!devData->FdoContext) { 546 + return STATUS_NO_SUCH_DEVICE; 547 + } 548 + 549 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 550 + if (stream->PdoContext != devData) { 551 + return STATUS_INVALID_HANDLE; 552 + } 553 + 554 + if (stream->running) { 555 + return STATUS_INVALID_DEVICE_REQUEST; 556 + } 557 + 558 + if (stream->mdlBuf) { 559 + return STATUS_INVALID_DEVICE_REQUEST; 560 + } 561 + 562 + PHYSICAL_ADDRESS zeroAddr; 563 + zeroAddr.QuadPart = 0; 564 + PHYSICAL_ADDRESS maxAddr; 565 + maxAddr.QuadPart = devData->FdoContext->is64BitOK ? MAXULONG64 : MAXULONG32; 566 + 567 + UINT32 allocSize = (UINT32)RequestedBufferSize; 568 + UINT32 allocOffset = 0; 569 + UINT32 halfSize = 0; 570 + if (NotificationCount == 2) { 571 + halfSize = (UINT32)RequestedBufferSize / 2; 572 + allocOffset = PAGE_SIZE - (halfSize % PAGE_SIZE); 573 + allocSize = (UINT32)RequestedBufferSize + allocOffset; 574 + } 575 + 576 + PMDL mdl = MmAllocatePagesForMdl(zeroAddr, maxAddr, zeroAddr, allocSize); 577 + if (!mdl) { 578 + return STATUS_NO_MEMORY; 579 + } 580 + 581 + WdfInterruptAcquireLock(devData->FdoContext->Interrupt); 582 + stream->mdlBuf = mdl; 583 + stream->bufSz = (UINT32)RequestedBufferSize; 584 + 585 + *BufferMdl = mdl; 586 + *AllocatedBufferSize = RequestedBufferSize; 587 + *OffsetFromFirstPage = allocOffset; 588 + *StreamId = stream->streamTag; 589 + 590 + { 591 + UINT16 numBlocks = 0; 592 + UINT16 pageNum = 0; 593 + 594 + //Set up the BDL 595 + PHDAC_BDLENTRY bdl = stream->bdl; 596 + UINT32 size = (UINT32)RequestedBufferSize; 597 + 598 + PPFN_NUMBER pfnArray = MmGetMdlPfnArray(mdl); 599 + UINT32 offset = allocOffset; 600 + while (halfSize > 0) { 601 + if (numBlocks > HDA_MAX_BDL_ENTRIES) { 602 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "%s Too many BDL entries!\n", __func__); 603 + numBlocks = HDA_MAX_BDL_ENTRIES; 604 + break; 605 + } 606 + 607 + UINT32 pageOff = offset % PAGE_SIZE; 608 + UINT32 chunk = (pageOff == 0) ? PAGE_SIZE : (PAGE_SIZE - pageOff); 609 + if (halfSize < chunk) 610 + chunk = halfSize; 611 + 612 + PFN_NUMBER pfn = pfnArray[pageNum]; 613 + PHYSICAL_ADDRESS addr = { 0 }; 614 + addr.QuadPart = pfn << PAGE_SHIFT; 615 + 616 + bdl->lowAddr = addr.LowPart + pageOff; 617 + bdl->highAddr = addr.HighPart; 618 + bdl->len = chunk; 619 + 620 + halfSize -= chunk; 621 + size -= chunk; 622 + 623 + //Program interrupt for when buffer is halfway 624 + bdl->ioc = (halfSize > 0) ? 0 : 1; 625 + bdl++; 626 + numBlocks++; 627 + offset += chunk; 628 + if ((offset % PAGE_SIZE) == 0) 629 + pageNum++; //Only increment page num if we go past page boundary 630 + } 631 + 632 + while (size > 0) { 633 + if (numBlocks > HDA_MAX_BDL_ENTRIES) { 634 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "%s Too many BDL entries!\n", __func__); 635 + numBlocks = HDA_MAX_BDL_ENTRIES; 636 + break; 637 + } 638 + 639 + UINT32 pageOff = offset % PAGE_SIZE; 640 + UINT32 chunk = (pageOff == 0) ? PAGE_SIZE : (PAGE_SIZE - pageOff); 641 + if (size < chunk) 642 + chunk = size; 643 + 644 + PFN_NUMBER pfn = pfnArray[pageNum]; 645 + PHYSICAL_ADDRESS addr = { 0 }; 646 + addr.QuadPart = pfn << PAGE_SHIFT; 647 + bdl->lowAddr = addr.LowPart + pageOff; 648 + bdl->highAddr = addr.HighPart; 649 + bdl->len = chunk; 650 + 651 + size -= chunk; 652 + //Program interrupt for when buffer ends 653 + bdl->ioc = (size > 0) ? 0 : 1; 654 + bdl++; 655 + numBlocks++; 656 + offset += chunk; 657 + if ((offset % PAGE_SIZE) == 0) 658 + pageNum++; //Only increment page num if we go past page boundary 659 + } 660 + stream->numBlocks = numBlocks; 661 + } 662 + 663 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 664 + 665 + hdac_stream_reset(stream); 666 + hdac_stream_setup(stream); 667 + 668 + *FifoSize = stream->fifoSize; 669 + return STATUS_SUCCESS; 670 + } 671 + 672 + NTSTATUS 673 + NTAPI 674 + HDA_FreeDmaBufferWithNotification( 675 + _In_ PVOID _context, 676 + _In_ HANDLE Handle, 677 + _In_ PMDL BufferMdl, 678 + _In_ SIZE_T BufferSize 679 + ) { 680 + UNREFERENCED_PARAMETER(BufferMdl); 681 + UNREFERENCED_PARAMETER(BufferSize); 682 + 683 + if (KeGetCurrentIrql() > PASSIVE_LEVEL) { 684 + return STATUS_UNSUCCESSFUL; 685 + } 686 + 687 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 688 + if (!devData->FdoContext) { 689 + return STATUS_NO_SUCH_DEVICE; 690 + } 691 + 692 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 693 + if (stream->PdoContext != devData) { 694 + return STATUS_INVALID_HANDLE; 695 + } 696 + 697 + if (stream->running) { 698 + return STATUS_INVALID_DEVICE_REQUEST; 699 + } 700 + 701 + if (!stream->mdlBuf) { 702 + return STATUS_INVALID_DEVICE_REQUEST; 703 + } 704 + 705 + WdfInterruptAcquireLock(devData->FdoContext->Interrupt); 706 + 707 + stream_write32(stream, SD_BDLPL, 0); 708 + stream_write32(stream, SD_BDLPU, 0); 709 + stream_write32(stream, SD_CTL, 0); 710 + 711 + PMDL mdl = stream->mdlBuf; 712 + stream->mdlBuf = NULL; 713 + 714 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 715 + 716 + MmFreePagesFromMdl(mdl); 717 + ExFreePool(mdl); 718 + 719 + return STATUS_SUCCESS; 720 + } 721 + 722 + NTSTATUS 723 + NTAPI 724 + HDA_AllocateDmaBuffer( 725 + _In_ PVOID _context, 726 + _In_ HANDLE Handle, 727 + _In_ SIZE_T RequestedBufferSize, 728 + _Out_ PMDL* BufferMdl, 729 + _Out_ PSIZE_T AllocatedBufferSize, 730 + _Out_ PUCHAR StreamId, 731 + _Out_ PULONG FifoSize 732 + ) { 733 + SIZE_T OffsetFromFirstPage; 734 + return HDA_AllocateDmaBufferWithNotification(_context, Handle, 1, RequestedBufferSize, BufferMdl, AllocatedBufferSize, &OffsetFromFirstPage, StreamId, FifoSize); 735 + } 736 + 737 + NTSTATUS 738 + NTAPI 739 + HDA_FreeDmaBuffer( 740 + _In_ PVOID _context, 741 + _In_ HANDLE Handle 742 + ) { 743 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 744 + if (!devData->FdoContext) { 745 + return STATUS_NO_SUCH_DEVICE; 746 + } 747 + 748 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 749 + if (stream->PdoContext != devData) { 750 + return STATUS_INVALID_HANDLE; 751 + } 752 + 753 + return HDA_FreeDmaBufferWithNotification(_context, Handle, stream->mdlBuf, stream->bufSz); 754 + } 755 + 756 + NTSTATUS 757 + NTAPI 758 + HDA_RegisterNotificationEvent( 759 + _In_ PVOID _context, 760 + _In_ HANDLE Handle, 761 + _In_ PKEVENT NotificationEvent 762 + ) { 763 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 764 + if (!devData->FdoContext) { 765 + return STATUS_NO_SUCH_DEVICE; 766 + } 767 + 768 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 769 + if (stream->PdoContext != devData) { 770 + return STATUS_INVALID_HANDLE; 771 + } 772 + 773 + BOOL registered = FALSE; 774 + 775 + for (int i = 0; i < MAX_NOTIF_EVENTS; i++) { 776 + if (stream->registeredEvents[i]) 777 + continue; 778 + stream->registeredEvents[i] = NotificationEvent; 779 + registered = true; 780 + break; 781 + } 782 + 783 + return registered ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; 784 + } 785 + 786 + NTSTATUS 787 + NTAPI 788 + HDA_UnregisterNotificationEvent( 789 + _In_ PVOID _context, 790 + _In_ HANDLE Handle, 791 + _In_ PKEVENT NotificationEvent 792 + ) { 793 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 794 + if (!devData->FdoContext) { 795 + return STATUS_NO_SUCH_DEVICE; 796 + } 797 + 798 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 799 + if (stream->PdoContext != devData) { 800 + return STATUS_INVALID_HANDLE; 801 + } 802 + 803 + BOOL registered = FALSE; 804 + 805 + for (int i = 0; i < MAX_NOTIF_EVENTS; i++) { 806 + if (stream->registeredEvents[i] != NotificationEvent) 807 + continue; 808 + stream->registeredEvents[i] = NULL; 809 + registered = true; 810 + break; 811 + } 812 + 813 + return registered ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER; 814 + } 815 + 816 + NTSTATUS 817 + NTAPI 818 + HDA_RegisterNotificationCallback( 819 + _In_ PVOID _context, 820 + _In_ HANDLE Handle, 821 + PDEVICE_OBJECT Fdo, 822 + PHDAUDIO_DMA_NOTIFICATION_CALLBACK NotificationCallback, 823 + PVOID CallbackContext 824 + ) { 825 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 826 + if (!devData->FdoContext) { 827 + return STATUS_NO_SUCH_DEVICE; 828 + } 829 + 830 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 831 + if (stream->PdoContext != devData) { 832 + return STATUS_INVALID_HANDLE; 833 + } 834 + 835 + BOOL registered = FALSE; 836 + 837 + for (int i = 0; i < MAX_NOTIF_EVENTS; i++) { 838 + if (stream->registeredCallbacks[i].InUse) 839 + continue; 840 + stream->registeredCallbacks[i].InUse = TRUE; 841 + stream->registeredCallbacks[i].Fdo = Fdo; 842 + stream->registeredCallbacks[i].NotificationCallback = NotificationCallback; 843 + stream->registeredCallbacks[i].CallbackContext = CallbackContext; 844 + 845 + InterlockedIncrement(&Fdo->ReferenceCount); 846 + 847 + registered = true; 848 + break; 849 + } 850 + 851 + return registered ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; 852 + } 853 + 854 + NTSTATUS 855 + NTAPI 856 + HDA_UnregisterNotificationCallback( 857 + _In_ PVOID _context, 858 + _In_ HANDLE Handle, 859 + PHDAUDIO_DMA_NOTIFICATION_CALLBACK NotificationCallback, 860 + PVOID CallbackContext 861 + ) { 862 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 863 + if (!devData->FdoContext) { 864 + return STATUS_NO_SUCH_DEVICE; 865 + } 866 + 867 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 868 + if (stream->PdoContext != devData) { 869 + return STATUS_INVALID_HANDLE; 870 + } 871 + 872 + BOOL registered = FALSE; 873 + 874 + for (int i = 0; i < MAX_NOTIF_EVENTS; i++) { 875 + if (stream->registeredCallbacks[i].InUse && 876 + stream->registeredCallbacks[i].NotificationCallback != NotificationCallback && 877 + stream->registeredCallbacks[i].CallbackContext != CallbackContext) 878 + continue; 879 + 880 + InterlockedDecrement(&stream->registeredCallbacks[i].Fdo->ReferenceCount); 881 + 882 + RtlZeroMemory(&stream->registeredCallbacks[i], sizeof(stream->registeredCallbacks[i])); 883 + registered = true; 884 + break; 885 + } 886 + 887 + return registered ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER; 888 + } 889 + 890 + NTSTATUS 891 + NTAPI 892 + HDA_SetupDmaEngineWithBdl( 893 + _In_ PVOID _context, 894 + _In_ HANDLE Handle, 895 + _In_ ULONG BufferLength, 896 + _In_ ULONG Lvi, 897 + _In_ PHDAUDIO_BDL_ISR Isr, 898 + _In_ PVOID Context, 899 + _Out_ PUCHAR StreamId, 900 + _Out_ PULONG FifoSize) 901 + { 902 + if (KeGetCurrentIrql() > PASSIVE_LEVEL) { 903 + return STATUS_UNSUCCESSFUL; 904 + } 905 + 906 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 907 + if (!devData->FdoContext) { 908 + return STATUS_NO_SUCH_DEVICE; 909 + } 910 + 911 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 912 + if (stream->PdoContext != devData) { 913 + return STATUS_INVALID_HANDLE; 914 + } 915 + 916 + if (stream->running) { 917 + return STATUS_INVALID_DEVICE_REQUEST; 918 + } 919 + 920 + if (!stream->bdl) { 921 + return STATUS_INVALID_DEVICE_REQUEST; 922 + } 923 + 924 + if (!stream->dmaBuf) { 925 + return STATUS_INVALID_DEVICE_REQUEST; 926 + } 927 + 928 + WdfInterruptAcquireLock(devData->FdoContext->Interrupt); 929 + 930 + stream->bufSz = BufferLength; 931 + stream->numBlocks = (UINT16)Lvi; 932 + 933 + RtlZeroMemory(&stream->isr, sizeof(HDAC_ISR_CALLBACK)); 934 + stream->isr.IOC = TRUE; 935 + stream->isr.IsrCallback = Isr; 936 + stream->isr.CallbackContext = Context; 937 + 938 + hdac_stream_reset(stream); 939 + hdac_stream_setup(stream); 940 + 941 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 942 + 943 + *StreamId = stream->streamTag; 944 + *FifoSize = stream->fifoSize; 945 + 946 + return STATUS_SUCCESS; 947 + } 948 + 949 + NTSTATUS 950 + NTAPI 951 + HDA_FreeContiguousDmaBuffer( 952 + _In_ PVOID _context, 953 + _In_ HANDLE Handle) 954 + { 955 + if (KeGetCurrentIrql() > PASSIVE_LEVEL) { 956 + return STATUS_UNSUCCESSFUL; 957 + } 958 + 959 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 960 + if (!devData->FdoContext) { 961 + return STATUS_NO_SUCH_DEVICE; 962 + } 963 + 964 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 965 + if (stream->PdoContext != devData) { 966 + return STATUS_INVALID_HANDLE; 967 + } 968 + 969 + if (stream->running) { 970 + return STATUS_INVALID_DEVICE_REQUEST; 971 + } 972 + 973 + if (!stream->bdl) { 974 + return STATUS_INVALID_DEVICE_REQUEST; 975 + } 976 + 977 + if (!stream->dmaBuf) { 978 + return STATUS_INVALID_DEVICE_REQUEST; 979 + } 980 + 981 + WdfInterruptAcquireLock(devData->FdoContext->Interrupt); 982 + 983 + stream_write32(stream, SD_BDLPL, 0); 984 + stream_write32(stream, SD_BDLPU, 0); 985 + stream_write32(stream, SD_CTL, 0); 986 + 987 + RtlZeroMemory(&stream->isr, sizeof(HDAC_ISR_CALLBACK)); 988 + 989 + PVOID dmaBuf = stream->dmaBuf; 990 + stream->dmaBuf = NULL; 991 + 992 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 993 + 994 + MmFreeContiguousMemory(dmaBuf); 995 + 996 + return STATUS_SUCCESS; 997 + } 998 + 999 + NTSTATUS 1000 + NTAPI 1001 + HDA_AllocateContiguousDmaBuffer( 1002 + _In_ PVOID _context, 1003 + _In_ HANDLE Handle, 1004 + _In_ ULONG RequestedBufferSize, 1005 + _Out_ PVOID* DataBuffer, 1006 + _Out_ PHDAUDIO_BUFFER_DESCRIPTOR* BdlBuffer) 1007 + { 1008 + if (KeGetCurrentIrql() > PASSIVE_LEVEL) { 1009 + return STATUS_UNSUCCESSFUL; 1010 + } 1011 + 1012 + PPDO_DEVICE_DATA devData = (PPDO_DEVICE_DATA)_context; 1013 + if (!devData->FdoContext) { 1014 + return STATUS_NO_SUCH_DEVICE; 1015 + } 1016 + 1017 + PHDAC_STREAM stream = (PHDAC_STREAM)Handle; 1018 + if (stream->PdoContext != devData) { 1019 + return STATUS_INVALID_HANDLE; 1020 + } 1021 + 1022 + if (stream->running) { 1023 + return STATUS_INVALID_DEVICE_REQUEST; 1024 + } 1025 + 1026 + if (stream->dmaBuf) { 1027 + return STATUS_INVALID_DEVICE_REQUEST; 1028 + } 1029 + 1030 + if (!stream->bdl) { 1031 + return STATUS_INVALID_DEVICE_REQUEST; 1032 + } 1033 + 1034 + PHYSICAL_ADDRESS maxAddr; 1035 + maxAddr.QuadPart = devData->FdoContext->is64BitOK ? MAXULONG64 : MAXULONG32; 1036 + 1037 + PVOID dmaBuf = MmAllocateContiguousMemory(RequestedBufferSize, maxAddr); 1038 + if (!dmaBuf) { 1039 + return STATUS_INSUFFICIENT_RESOURCES; 1040 + } 1041 + RtlZeroMemory(dmaBuf, RequestedBufferSize); 1042 + 1043 + WdfInterruptAcquireLock(devData->FdoContext->Interrupt); 1044 + 1045 + stream->dmaBuf = dmaBuf; 1046 + 1047 + WdfInterruptReleaseLock(devData->FdoContext->Interrupt); 1048 + 1049 + *DataBuffer = stream->dmaBuf; 1050 + *BdlBuffer = (PHDAUDIO_BUFFER_DESCRIPTOR)stream->bdl; 1051 + 1052 + return STATUS_SUCCESS; 1053 + } 1054 + 1055 + HDAUDIO_BUS_INTERFACE_V2 HDA_BusInterfaceV2(PVOID Context) { 1056 + HDAUDIO_BUS_INTERFACE_V2 busInterface; 1057 + RtlZeroMemory(&busInterface, sizeof(HDAUDIO_BUS_INTERFACE_V2)); 1058 + 1059 + busInterface.Size = sizeof(HDAUDIO_BUS_INTERFACE_V2); 1060 + busInterface.Version = 0x0100; 1061 + busInterface.Context = Context; 1062 + busInterface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; 1063 + busInterface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; 1064 + busInterface.TransferCodecVerbs = HDA_TransferCodecVerbs; 1065 + busInterface.AllocateCaptureDmaEngine = HDA_AllocateCaptureDmaEngine; 1066 + busInterface.AllocateRenderDmaEngine = HDA_AllocateRenderDmaEngine; 1067 + busInterface.ChangeBandwidthAllocation = HDA_ChangeBandwidthAllocation; 1068 + busInterface.AllocateDmaBuffer = HDA_AllocateDmaBuffer; 1069 + busInterface.FreeDmaBuffer = HDA_FreeDmaBuffer; 1070 + busInterface.FreeDmaEngine = HDA_FreeDmaEngine; 1071 + busInterface.SetDmaEngineState = HDA_SetDmaEngineState; 1072 + busInterface.GetWallClockRegister = HDA_GetWallClockRegister; 1073 + busInterface.GetLinkPositionRegister = HDA_GetLinkPositionRegister; 1074 + busInterface.RegisterEventCallback = HDA_RegisterEventCallback; 1075 + busInterface.UnregisterEventCallback = HDA_UnregisterEventCallback; 1076 + busInterface.GetDeviceInformation = HDA_GetDeviceInformation; 1077 + busInterface.GetResourceInformation = HDA_GetResourceInformation; 1078 + busInterface.AllocateDmaBufferWithNotification = HDA_AllocateDmaBufferWithNotification; 1079 + busInterface.FreeDmaBufferWithNotification = HDA_FreeDmaBufferWithNotification; 1080 + busInterface.RegisterNotificationEvent = HDA_RegisterNotificationEvent; 1081 + busInterface.UnregisterNotificationEvent = HDA_UnregisterNotificationEvent; 1082 + 1083 + return busInterface; 1084 + } 1085 + 1086 + HDAUDIO_BUS_INTERFACE_V3 HDA_BusInterfaceV3(PVOID Context) { 1087 + HDAUDIO_BUS_INTERFACE_V3 busInterface; 1088 + RtlZeroMemory(&busInterface, sizeof(HDAUDIO_BUS_INTERFACE_V3)); 1089 + 1090 + busInterface.Size = sizeof(HDAUDIO_BUS_INTERFACE_V3); 1091 + busInterface.Version = 0x0100; 1092 + busInterface.Context = Context; 1093 + busInterface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; 1094 + busInterface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; 1095 + busInterface.TransferCodecVerbs = HDA_TransferCodecVerbs; 1096 + busInterface.AllocateCaptureDmaEngine = HDA_AllocateCaptureDmaEngine; 1097 + busInterface.AllocateRenderDmaEngine = HDA_AllocateRenderDmaEngine; 1098 + busInterface.ChangeBandwidthAllocation = HDA_ChangeBandwidthAllocation; 1099 + busInterface.AllocateDmaBuffer = HDA_AllocateDmaBuffer; 1100 + busInterface.FreeDmaBuffer = HDA_FreeDmaBuffer; 1101 + busInterface.FreeDmaEngine = HDA_FreeDmaEngine; 1102 + busInterface.SetDmaEngineState = HDA_SetDmaEngineState; 1103 + busInterface.GetWallClockRegister = HDA_GetWallClockRegister; 1104 + busInterface.GetLinkPositionRegister = HDA_GetLinkPositionRegister; 1105 + busInterface.RegisterEventCallback = HDA_RegisterEventCallback; 1106 + busInterface.UnregisterEventCallback = HDA_UnregisterEventCallback; 1107 + busInterface.GetDeviceInformation = HDA_GetDeviceInformation; 1108 + busInterface.GetResourceInformation = HDA_GetResourceInformation; 1109 + busInterface.AllocateDmaBufferWithNotification = HDA_AllocateDmaBufferWithNotification; 1110 + busInterface.FreeDmaBufferWithNotification = HDA_FreeDmaBufferWithNotification; 1111 + busInterface.RegisterNotificationEvent = HDA_RegisterNotificationEvent; 1112 + busInterface.UnregisterNotificationEvent = HDA_UnregisterNotificationEvent; 1113 + busInterface.RegisterNotificationCallback = HDA_RegisterNotificationCallback; 1114 + busInterface.UnregisterNotificationCallback = HDA_UnregisterNotificationCallback; 1115 + 1116 + return busInterface; 1117 + } 1118 + 1119 + HDAUDIO_BUS_INTERFACE HDA_BusInterface(PVOID Context) { 1120 + HDAUDIO_BUS_INTERFACE busInterface; 1121 + RtlZeroMemory(&busInterface, sizeof(HDAUDIO_BUS_INTERFACE)); 1122 + 1123 + busInterface.Size = sizeof(HDAUDIO_BUS_INTERFACE); 1124 + busInterface.Version = 0x0100; 1125 + busInterface.Context = Context; 1126 + busInterface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; 1127 + busInterface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; 1128 + busInterface.TransferCodecVerbs = HDA_TransferCodecVerbs; 1129 + busInterface.AllocateCaptureDmaEngine = HDA_AllocateCaptureDmaEngine; 1130 + busInterface.AllocateRenderDmaEngine = HDA_AllocateRenderDmaEngine; 1131 + busInterface.ChangeBandwidthAllocation = HDA_ChangeBandwidthAllocation; 1132 + busInterface.AllocateDmaBuffer = HDA_AllocateDmaBuffer; 1133 + busInterface.FreeDmaBuffer = HDA_FreeDmaBuffer; 1134 + busInterface.FreeDmaEngine = HDA_FreeDmaEngine; 1135 + busInterface.SetDmaEngineState = HDA_SetDmaEngineState; 1136 + busInterface.GetWallClockRegister = HDA_GetWallClockRegister; 1137 + busInterface.GetLinkPositionRegister = HDA_GetLinkPositionRegister; 1138 + busInterface.RegisterEventCallback = HDA_RegisterEventCallback; 1139 + busInterface.UnregisterEventCallback = HDA_UnregisterEventCallback; 1140 + busInterface.GetDeviceInformation = HDA_GetDeviceInformation; 1141 + busInterface.GetResourceInformation = HDA_GetResourceInformation; 1142 + 1143 + return busInterface; 1144 + } 1145 + 1146 + HDAUDIO_BUS_INTERFACE_BDL HDA_BusInterfaceBDL(PVOID Context) 1147 + { 1148 + HDAUDIO_BUS_INTERFACE_BDL busInterface; 1149 + RtlZeroMemory(&busInterface, sizeof(HDAUDIO_BUS_INTERFACE_BDL)); 1150 + 1151 + busInterface.Size = sizeof(HDAUDIO_BUS_INTERFACE_BDL); 1152 + busInterface.Version = 0x0100; 1153 + busInterface.Context = Context; 1154 + busInterface.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; 1155 + busInterface.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; 1156 + busInterface.TransferCodecVerbs = HDA_TransferCodecVerbs; 1157 + busInterface.AllocateCaptureDmaEngine = HDA_AllocateCaptureDmaEngine; 1158 + busInterface.AllocateRenderDmaEngine = HDA_AllocateRenderDmaEngine; 1159 + busInterface.ChangeBandwidthAllocation = HDA_ChangeBandwidthAllocation; 1160 + busInterface.AllocateContiguousDmaBuffer = HDA_AllocateContiguousDmaBuffer; 1161 + busInterface.SetupDmaEngineWithBdl = HDA_SetupDmaEngineWithBdl; 1162 + busInterface.FreeContiguousDmaBuffer = HDA_FreeContiguousDmaBuffer; 1163 + busInterface.FreeDmaEngine = HDA_FreeDmaEngine; 1164 + busInterface.SetDmaEngineState = HDA_SetDmaEngineState; 1165 + busInterface.GetWallClockRegister = HDA_GetWallClockRegister; 1166 + busInterface.GetLinkPositionRegister = HDA_GetLinkPositionRegister; 1167 + busInterface.RegisterEventCallback = HDA_RegisterEventCallback; 1168 + busInterface.UnregisterEventCallback = HDA_UnregisterEventCallback; 1169 + busInterface.GetDeviceInformation = HDA_GetDeviceInformation; 1170 + busInterface.GetResourceInformation = HDA_GetResourceInformation; 1171 + 1172 + return busInterface; 1173 + }
+278
drivers/wdm/audio/hdaudbus_new/nhlt.cpp
··· 1 + #include "driver.h" 2 + #include "nhlt.h" 3 + #include <acpiioct.h> 4 + 5 + DEFINE_GUID(GUID_SST_NHLT, 6 + 0xA69F886E, 0x6CEB, 0x4594, 0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53); 7 + 8 + NTSTATUS 9 + NHLTQuery( 10 + _In_ WDFDEVICE FxDevice, 11 + _In_ ULONG Arg1, 12 + _In_ ULONG Arg2, 13 + _Out_ WDFMEMORY* outputBufferMemoryArg 14 + ) { 15 + ULONG_PTR bytesReturned; 16 + NTSTATUS status = STATUS_ACPI_NOT_INITIALIZED; 17 + WDFMEMORY inputBufferMemory = NULL; 18 + PACPI_EVAL_INPUT_BUFFER_COMPLEX_EX inputBuffer = NULL; 19 + PACPI_METHOD_ARGUMENT inputArgument = NULL; 20 + ACPI_EVAL_OUTPUT_BUFFER outputHeader; 21 + WDFMEMORY outputBufferMemory = NULL; 22 + WDF_MEMORY_DESCRIPTOR inputBufferMemoryDescriptor; 23 + WDF_MEMORY_DESCRIPTOR outputBufferMemoryDescriptor; 24 + 25 + ULONG inputBufferSize = 26 + (ULONG)( 27 + FIELD_OFFSET(ACPI_EVAL_INPUT_BUFFER_COMPLEX_EX, Argument) + 28 + ACPI_METHOD_ARGUMENT_LENGTH(sizeof(GUID)) + 29 + ACPI_METHOD_ARGUMENT_LENGTH(sizeof(ULONG)) + 30 + ACPI_METHOD_ARGUMENT_LENGTH(sizeof(ULONG)) + 31 + ACPI_METHOD_ARGUMENT_LENGTH(0) 32 + ); 33 + 34 + status = WdfMemoryCreate(WDF_NO_OBJECT_ATTRIBUTES, 35 + PagedPool, 36 + SKLHDAUDBUS_POOL_TAG, 37 + inputBufferSize, 38 + &inputBufferMemory, 39 + (PVOID*)&inputBuffer); 40 + if (!NT_SUCCESS(status)) { 41 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Failed to create input buffer\n"); 42 + goto end; 43 + } 44 + RtlZeroMemory(inputBuffer, inputBufferSize); 45 + 46 + inputBuffer->Signature = ACPI_EVAL_INPUT_BUFFER_COMPLEX_SIGNATURE_V1_EX; 47 + status = RtlStringCchPrintfA( 48 + inputBuffer->MethodName, 49 + sizeof(inputBuffer->MethodName), 50 + "_DSM" 51 + ); 52 + if (!NT_SUCCESS(status)) { 53 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Failed to write method name\n"); 54 + goto end; 55 + } 56 + 57 + inputBuffer->Size = inputBufferSize; 58 + inputBuffer->ArgumentCount = 4; 59 + inputArgument = inputBuffer->Argument; 60 + 61 + //arg 0 62 + ACPI_METHOD_SET_ARGUMENT_BUFFER(inputArgument, 63 + &GUID_SST_NHLT, 64 + sizeof(GUID_SST_NHLT)); 65 + 66 + inputArgument = ACPI_METHOD_NEXT_ARGUMENT(inputArgument); 67 + ACPI_METHOD_SET_ARGUMENT_INTEGER(inputArgument, Arg1); 68 + 69 + inputArgument = ACPI_METHOD_NEXT_ARGUMENT(inputArgument); 70 + ACPI_METHOD_SET_ARGUMENT_INTEGER(inputArgument, Arg2); 71 + 72 + inputArgument = ACPI_METHOD_NEXT_ARGUMENT(inputArgument); 73 + RtlZeroMemory(inputArgument, sizeof(*inputArgument)); 74 + inputArgument->Type = ACPI_METHOD_ARGUMENT_PACKAGE_EX; 75 + inputArgument->DataLength = 0; 76 + 77 + WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&inputBufferMemoryDescriptor, 78 + inputBufferMemory, 79 + 0); 80 + RtlZeroMemory(&outputHeader, sizeof(outputHeader)); 81 + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputBufferMemoryDescriptor, 82 + &outputHeader, 83 + sizeof(outputHeader)); 84 + 85 + status = WdfIoTargetSendIoctlSynchronously(WdfDeviceGetIoTarget(FxDevice), 86 + NULL, 87 + IOCTL_ACPI_EVAL_METHOD_EX, 88 + &inputBufferMemoryDescriptor, 89 + &outputBufferMemoryDescriptor, 90 + NULL, 91 + &bytesReturned); 92 + 93 + if (status == STATUS_BUFFER_OVERFLOW) { 94 + status = STATUS_SUCCESS; 95 + } 96 + else if (!NT_SUCCESS(status)) { 97 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Failed first ioctl\n"); 98 + goto end; 99 + } 100 + 101 + status = WdfMemoryCreate(WDF_NO_OBJECT_ATTRIBUTES, 102 + PagedPool, 103 + SKLHDAUDBUS_POOL_TAG, 104 + outputHeader.Length, 105 + &outputBufferMemory, 106 + (PVOID*)NULL); 107 + if (!NT_SUCCESS(status)) { 108 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Failed to create output buffer\n"); 109 + goto end; 110 + } 111 + 112 + WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&outputBufferMemoryDescriptor, 113 + outputBufferMemory, 114 + 0); 115 + status = WdfIoTargetSendIoctlSynchronously(WdfDeviceGetIoTarget(FxDevice), 116 + NULL, 117 + IOCTL_ACPI_EVAL_METHOD_EX, 118 + &inputBufferMemoryDescriptor, 119 + &outputBufferMemoryDescriptor, 120 + NULL, 121 + &bytesReturned); 122 + 123 + if (!NT_SUCCESS(status)) { 124 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_INIT, "Failed to do 2nd ioctl\n"); 125 + goto end; 126 + } 127 + 128 + end: 129 + if (inputBufferMemory != NULL) { 130 + WdfObjectDelete(inputBufferMemory); 131 + inputBufferMemory = NULL; 132 + } 133 + 134 + if (!NT_SUCCESS(status)) { 135 + if (outputBufferMemory != NULL) { 136 + WdfObjectDelete(outputBufferMemory); 137 + outputBufferMemory = NULL; 138 + } 139 + } 140 + else { 141 + *outputBufferMemoryArg = outputBufferMemory; 142 + } 143 + return status; 144 + } 145 + 146 + NTSTATUS NHLTCheckSupported(_In_ WDFDEVICE FxDevice) { 147 + WDFMEMORY outputBufferMemory; 148 + NTSTATUS status = NHLTQuery(FxDevice, NHLTRev1, NHLTSupportQuery, &outputBufferMemory); 149 + if (!NT_SUCCESS(status)) { 150 + return status; 151 + } 152 + if (!outputBufferMemory) { 153 + return STATUS_NO_MEMORY; 154 + } 155 + 156 + PACPI_EVAL_OUTPUT_BUFFER outputBuffer = (PACPI_EVAL_OUTPUT_BUFFER)WdfMemoryGetBuffer(outputBufferMemory, NULL); 157 + if (outputBuffer->Count < 1) { 158 + status = STATUS_INVALID_DEVICE_OBJECT_PARAMETER; 159 + goto end; 160 + } 161 + 162 + { 163 + PACPI_METHOD_ARGUMENT argument = outputBuffer->Argument; 164 + 165 + UCHAR supportedQueries = argument->Data[0]; 166 + 167 + if ((supportedQueries & 0x3) == 0) { 168 + status = STATUS_NOT_SUPPORTED; 169 + } 170 + } 171 + 172 + end: 173 + if (outputBufferMemory != NULL) { 174 + WdfObjectDelete(outputBufferMemory); 175 + outputBufferMemory = NULL; 176 + } 177 + return status; 178 + } 179 + 180 + void parseACPI(UINT8* res, UINT32 offset, UINT32 sz, UINT64* nhltAddr, UINT64* nhltSz); 181 + 182 + NTSTATUS NHLTQueryTableAddress(_In_ WDFDEVICE FxDevice, UINT64 *nhltAddr, UINT64 *nhltSz) { 183 + WDFMEMORY outputBufferMemory; 184 + NTSTATUS status = NHLTQuery(FxDevice, NHLTRev1, NHLTMemoryAddress, &outputBufferMemory); 185 + if (!NT_SUCCESS(status)) { 186 + return status; 187 + } 188 + if (!outputBufferMemory) { 189 + return STATUS_NO_MEMORY; 190 + } 191 + 192 + PACPI_EVAL_OUTPUT_BUFFER outputBuffer = (PACPI_EVAL_OUTPUT_BUFFER)WdfMemoryGetBuffer(outputBufferMemory, NULL); 193 + if (outputBuffer->Count < 1) { 194 + status = STATUS_INVALID_DEVICE_OBJECT_PARAMETER; 195 + goto end; 196 + } 197 + 198 + { 199 + PACPI_METHOD_ARGUMENT argument = outputBuffer->Argument; 200 + 201 + UINT8* res = argument->Data; 202 + UINT32 sz = argument->DataLength; 203 + 204 + *nhltAddr = 0; 205 + *nhltSz = 0; 206 + parseACPI(res, 0, sz, nhltAddr, nhltSz); 207 + } 208 + 209 + if (nhltAddr == 0 || nhltSz == 0) { 210 + status = STATUS_UNSUCCESSFUL; 211 + } 212 + 213 + end: 214 + if (outputBufferMemory != NULL) { 215 + WdfObjectDelete(outputBufferMemory); 216 + outputBufferMemory = NULL; 217 + } 218 + return status; 219 + } 220 + 221 + //Begin ACPI parser 222 + 223 + #define ACPI_RESOURCE_NAME_ADDRESS64 0x8A 224 + 225 + /* 226 + * LARGE descriptors 227 + */ 228 + #define AML_RESOURCE_LARGE_HEADER_COMMON \ 229 + UINT8 DescriptorType;\ 230 + UINT16 ResourceLength; 231 + 232 + #define AML_RESOURCE_ADDRESS_COMMON \ 233 + UINT8 ResourceType; \ 234 + UINT8 Flags; \ 235 + UINT8 SpecificFlags; 236 + 237 + #include <pshpack1.h> 238 + typedef struct aml_resource_address64 239 + { 240 + AML_RESOURCE_LARGE_HEADER_COMMON 241 + AML_RESOURCE_ADDRESS_COMMON 242 + UINT64 Granularity; 243 + UINT64 Minimum; 244 + UINT64 Maximum; 245 + UINT64 TranslationOffset; 246 + UINT64 AddressLength; 247 + } AML_RESOURCE_ADDRESS64; 248 + #include <poppack.h> 249 + 250 + void parseACPIMemory64(UINT8* res, UINT32 offset, UINT32 sz, UINT64 *nhltAddr, UINT64 *nhltSz) { 251 + if (offset + 3 > sz) 252 + return; 253 + 254 + UINT8 opcode = res[offset]; 255 + if (opcode != ACPI_RESOURCE_NAME_ADDRESS64) 256 + return; 257 + 258 + AML_RESOURCE_ADDRESS64* address64 = (AML_RESOURCE_ADDRESS64*)(res + offset); 259 + 260 + *nhltAddr = address64->Minimum; 261 + *nhltSz = address64->AddressLength; 262 + } 263 + 264 + void parseACPI(UINT8* res, UINT32 offset, UINT32 sz, UINT64* nhltAddr, UINT64* nhltSz) { 265 + if (offset + 3 > sz) 266 + return; 267 + 268 + UINT8 opcode = res[offset]; 269 + 270 + UINT16 len; 271 + memcpy(&len, res + offset + 1, sizeof(UINT16)); 272 + 273 + if (opcode == ACPI_RESOURCE_NAME_ADDRESS64) 274 + parseACPIMemory64(res, offset, sz, nhltAddr, nhltSz); 275 + 276 + offset += (len + 3); 277 + parseACPI(res, offset, sz, nhltAddr, nhltSz); 278 + }
+11
drivers/wdm/audio/hdaudbus_new/nhlt.h
··· 1 + enum NHLTQueryRevision { 2 + NHLTRev1 = 1 3 + }; 4 + 5 + enum NHLTQuery { 6 + NHLTSupportQuery = 0, 7 + NHLTMemoryAddress 8 + }; 9 + 10 + NTSTATUS NHLTCheckSupported(_In_ WDFDEVICE FxDevice); 11 + NTSTATUS NHLTQueryTableAddress(_In_ WDFDEVICE FxDevice, UINT64* nhltAddr, UINT64* nhltSz);
+78
drivers/wdm/audio/hdaudbus_new/regfuncs.h
··· 1 + static inline UINT8 read8(PVOID addr) { 2 + return READ_REGISTER_UCHAR((PUCHAR)addr); 3 + } 4 + 5 + static inline void write8(PVOID addr, UINT8 data) { 6 + WRITE_REGISTER_UCHAR((PUCHAR)addr, (UCHAR)data); 7 + } 8 + 9 + static inline UINT16 read16(PVOID addr) { 10 + return READ_REGISTER_USHORT((PUSHORT)addr); 11 + } 12 + 13 + static inline void write16(PVOID addr, UINT16 data) { 14 + WRITE_REGISTER_USHORT((PUSHORT)addr, (USHORT)data); 15 + } 16 + 17 + static inline UINT32 read32(PVOID addr) { 18 + return READ_REGISTER_ULONG((PULONG)addr); 19 + } 20 + 21 + static inline void write32(PVOID addr, UINT32 data) { 22 + WRITE_REGISTER_ULONG((PULONG)addr, (ULONG)data); 23 + } 24 + 25 + static inline void pci_read_cfg_byte(PBUS_INTERFACE_STANDARD pciInterface, UINT reg, BYTE* data) { 26 + pciInterface->GetBusData(pciInterface->Context, PCI_WHICHSPACE_CONFIG, data, reg, sizeof(BYTE)); 27 + } 28 + 29 + static inline void pci_read_cfg_dword(PBUS_INTERFACE_STANDARD pciInterface, UINT reg, UINT32* data) { 30 + pciInterface->GetBusData(pciInterface->Context, PCI_WHICHSPACE_CONFIG, data, reg, sizeof(UINT32)); 31 + } 32 + 33 + static inline void pci_write_cfg_byte(PBUS_INTERFACE_STANDARD pciInterface, UINT reg, BYTE data) { 34 + pciInterface->SetBusData(pciInterface->Context, PCI_WHICHSPACE_CONFIG, &data, reg, sizeof(BYTE)); 35 + } 36 + 37 + static inline void pci_write_cfg_dword(PBUS_INTERFACE_STANDARD pciInterface, UINT reg, UINT32 data) { 38 + pciInterface->GetBusData(pciInterface->Context, PCI_WHICHSPACE_CONFIG, &data, reg, sizeof(UINT32)); 39 + } 40 + 41 + static inline void update_pci_byte(PBUS_INTERFACE_STANDARD pciInterface, UINT reg, BYTE mask, BYTE val) { 42 + BYTE data; 43 + pci_read_cfg_byte(pciInterface, reg, &data); 44 + data &= ~mask; 45 + data |= (val & mask); 46 + pci_write_cfg_byte(pciInterface, reg, data); 47 + } 48 + 49 + #define HDA_RATE(base, mult, div) \ 50 + (AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \ 51 + (((div) - 1) << AC_FMT_DIV_SHIFT)) 52 + 53 + #define hda_read8(ctx, reg) read8((ctx)->m_BAR0.Base.baseptr + HDA_REG_##reg) 54 + #define hda_write8(ctx, reg, data) write8((ctx)->m_BAR0.Base.baseptr + HDA_REG_##reg, data) 55 + #define hda_update8(ctx, reg, mask, val) hda_write8(ctx, reg, (hda_read8(ctx, reg) & ~(mask)) | (val)) 56 + #define hda_read16(ctx, reg) read16((ctx)->m_BAR0.Base.baseptr + HDA_REG_##reg) 57 + #define hda_write16(ctx, reg, data) write16((ctx)->m_BAR0.Base.baseptr + HDA_REG_##reg, data) 58 + #define hda_update16(ctx, reg, mask, val) hda_write16(ctx, reg, (hda_read16(ctx, reg) & ~(mask)) | (val)) 59 + #define hda_read32(ctx, reg) read32((ctx)->m_BAR0.Base.baseptr + HDA_REG_##reg) 60 + #define hda_write32(ctx, reg, data) write32((ctx)->m_BAR0.Base.baseptr + HDA_REG_##reg, data) 61 + #define hda_update32(ctx, reg, mask, val) hda_write32(ctx, reg, (hda_read32(ctx, reg) & ~(mask)) | (val)) 62 + 63 + #define stream_read8(ctx, reg) read8((ctx)->sdAddr + HDA_REG_##reg) 64 + #define stream_write8(ctx, reg, data) write8((ctx)->sdAddr + HDA_REG_##reg, data) 65 + #define stream_update8(ctx, reg, mask, val) stream_write8(ctx, reg, (stream_read8(ctx, reg) & ~(mask)) | (val)) 66 + #define stream_read16(ctx, reg) read16((ctx)->sdAddr + HDA_REG_##reg) 67 + #define stream_write16(ctx, reg, data) write16((ctx)->sdAddr + HDA_REG_##reg, data) 68 + #define stream_update16(ctx, reg, mask, val) stream_write16(ctx, reg, (stream_read16(ctx, reg) & ~(mask)) | (val)) 69 + #define stream_read32(ctx, reg) read32((ctx)->sdAddr + HDA_REG_##reg) 70 + #define stream_write32(ctx, reg, data) write32((ctx)->sdAddr + HDA_REG_##reg, data) 71 + #define stream_update32(ctx, reg, mask, val) stream_write32(ctx, reg, (stream_read32(ctx, reg) & ~(mask)) | (val)) 72 + 73 + /* update register macro */ 74 + #define hdac_update32(addr, reg, mask, val) \ 75 + write32(addr + reg, ((read32(addr + reg) & ~(mask)) | (val))) 76 + 77 + #define hdac_update16(addr, reg, mask, val) \ 78 + write16(addr + reg,((read16(addr + reg) & ~(mask)) | (val)))
+14
drivers/wdm/audio/hdaudbus_new/resource.h
··· 1 + //{{NO_DEPENDENCIES}} 2 + // Microsoft Visual C++ generated include file. 3 + // Used by sklhdaudbus.rc 4 + 5 + // Next default values for new objects 6 + // 7 + #ifdef APSTUDIO_INVOKED 8 + #ifndef APSTUDIO_READONLY_SYMBOLS 9 + #define _APS_NEXT_RESOURCE_VALUE 101 10 + #define _APS_NEXT_COMMAND_VALUE 40001 11 + #define _APS_NEXT_CONTROL_VALUE 1001 12 + #define _APS_NEXT_SYMED_VALUE 101 13 + #endif 14 + #endif
+340
drivers/wdm/audio/hdaudbus_new/sgpc.cpp
··· 1 + #include "driver.h" 2 + 3 + NTSTATUS 4 + NTAPI 5 + HDAGraphics_EvtIoTargetQueryRemove( 6 + WDFIOTARGET ioTarget 7 + ) { 8 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 9 + "Device Removal Notification\n"); 10 + 11 + WdfIoTargetCloseForQueryRemove(ioTarget); 12 + return STATUS_SUCCESS; 13 + } 14 + 15 + void 16 + NTAPI 17 + HDAGraphics_EvtIoTargetRemoveCanceled( 18 + WDFIOTARGET ioTarget 19 + ) { 20 + WDF_IO_TARGET_OPEN_PARAMS openParams; 21 + NTSTATUS status; 22 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 23 + "Device Removal Cancel\n"); 24 + 25 + WDF_IO_TARGET_OPEN_PARAMS_INIT_REOPEN(&openParams); 26 + 27 + status = WdfIoTargetOpen(ioTarget, &openParams); 28 + 29 + if (!NT_SUCCESS(status)) { 30 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 31 + "WdfIoTargetOpen failed 0x%x\n", status); 32 + WdfObjectDelete(ioTarget); 33 + return; 34 + } 35 + } 36 + 37 + void 38 + NTAPI 39 + HDAGraphics_EvtIoTargetRemoveComplete( 40 + WDFIOTARGET ioTarget 41 + ) { 42 + PFDO_CONTEXT fdoCtx; 43 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 44 + "Device Removal Complete\n"); 45 + 46 + PGRAPHICSIOTARGET_CONTEXT ioTargetContext; 47 + ioTargetContext = GraphicsIoTarget_GetContext(ioTarget); 48 + 49 + fdoCtx = ioTargetContext->FdoContext; 50 + 51 + WdfWaitLockAcquire(fdoCtx->GraphicsDevicesCollectionWaitLock, NULL); 52 + WdfCollectionRemove(fdoCtx->GraphicsDevicesCollection, ioTarget); 53 + WdfWaitLockRelease(fdoCtx->GraphicsDevicesCollectionWaitLock); 54 + 55 + WdfObjectDelete(ioTarget); 56 + } 57 + 58 + void 59 + HDAGraphicsPowerNotificationCallback( 60 + PVOID GraphicsDeviceHandle, 61 + DEVICE_POWER_STATE NewGrfxPowerState, 62 + BOOLEAN PreNotification, 63 + PVOID PrivateHandle 64 + ) { 65 + PFDO_CONTEXT fdoCtx = (PFDO_CONTEXT)PrivateHandle; 66 + UNREFERENCED_PARAMETER(GraphicsDeviceHandle); 67 + UNREFERENCED_PARAMETER(NewGrfxPowerState); 68 + UNREFERENCED_PARAMETER(PreNotification); 69 + UNREFERENCED_PARAMETER(fdoCtx); 70 + //No-Op 71 + } 72 + 73 + void 74 + HDAGraphicsPowerRemovalNotificationCallback( 75 + PVOID GraphicsDeviceHandle, 76 + PVOID PrivateHandle 77 + ) { 78 + PFDO_CONTEXT fdoCtx = (PFDO_CONTEXT)PrivateHandle; 79 + UNREFERENCED_PARAMETER(GraphicsDeviceHandle); 80 + UNREFERENCED_PARAMETER(fdoCtx); 81 + //No-Op 82 + } 83 + 84 + void 85 + NTAPI 86 + Fdo_EnumerateCodec( 87 + PFDO_CONTEXT fdoCtx, 88 + UINT8 addr 89 + ); 90 + 91 + void 92 + NTAPI 93 + EjectGraphicsCodec(PFDO_CONTEXT fdoCtx) { 94 + if (!fdoCtx->UseSGPCCodec) { 95 + return; 96 + } 97 + 98 + if (!fdoCtx->codecs[fdoCtx->GraphicsCodecAddress]) 99 + return; 100 + 101 + fdoCtx->GraphicsCodecConnected = FALSE; 102 + 103 + PDO_IDENTIFICATION_DESCRIPTION description;// 104 + // Initialize the description with the information about the detected codec. 105 + // 106 + WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT( 107 + &description.Header, 108 + sizeof(description) 109 + ); 110 + 111 + description.FdoContext = fdoCtx; 112 + RtlCopyMemory(&description.CodecIds, &fdoCtx->codecs[fdoCtx->GraphicsCodecAddress]->CodecIds, sizeof(description.CodecIds)); 113 + 114 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 115 + "Ejecting Gfx Codec\n"); 116 + 117 + WdfInterruptAcquireLock(fdoCtx->Interrupt); 118 + 119 + WdfChildListUpdateChildDescriptionAsMissing(WdfFdoGetDefaultChildList(fdoCtx->WdfDevice), &description.Header); 120 + //Don't null FdoContext to allow SGPC Audio driver to unregister callbacks / events and cleanup 121 + 122 + WdfInterruptReleaseLock(fdoCtx->Interrupt); 123 + 124 + } 125 + 126 + void 127 + NTAPI 128 + EnumerateGraphicsCodec(PFDO_CONTEXT fdoCtx) { 129 + if (!fdoCtx->UseSGPCCodec) { 130 + return; 131 + } 132 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 133 + "Enumerating Gfx Codec\n"); 134 + fdoCtx->GraphicsCodecConnected = TRUE; 135 + Fdo_EnumerateCodec(fdoCtx, (UINT8)fdoCtx->GraphicsCodecAddress); 136 + } 137 + 138 + void HDAGraphicsPowerFStateNotificationCallback( 139 + PVOID GraphicsDeviceHandle, 140 + ULONG ComponentIndex, 141 + UINT NewFState, 142 + BOOLEAN PreNotification, 143 + PVOID PrivateHandle 144 + ) { 145 + PFDO_CONTEXT fdoCtx = (PFDO_CONTEXT)PrivateHandle; 146 + UNREFERENCED_PARAMETER(GraphicsDeviceHandle); 147 + UNREFERENCED_PARAMETER(ComponentIndex); 148 + if (NewFState) { 149 + if (PreNotification) { 150 + EjectGraphicsCodec(fdoCtx); 151 + } 152 + else { 153 + 154 + } 155 + } 156 + else { 157 + if (PreNotification) { 158 + 159 + } 160 + else { 161 + EnumerateGraphicsCodec(fdoCtx); 162 + } 163 + } 164 + } 165 + 166 + void HDAGraphicsPowerInitialComponentStateCallback( //https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/d3dkmthk/nc-d3dkmthk-pdxgk_initial_component_state 167 + PVOID GraphicsDeviceHandle, 168 + PVOID PrivateHandle, 169 + ULONG ComponentIndex, 170 + BOOLEAN IsBlockingType, 171 + UINT InitialFState, 172 + GUID ComponentGuid, 173 + UINT PowerComponentMappingFlag 174 + ) { 175 + UNREFERENCED_PARAMETER(GraphicsDeviceHandle); 176 + UNREFERENCED_PARAMETER(ComponentIndex); 177 + UNREFERENCED_PARAMETER(IsBlockingType); 178 + UNREFERENCED_PARAMETER(ComponentGuid); 179 + PFDO_CONTEXT fdoCtx = (PFDO_CONTEXT)PrivateHandle; 180 + if (PowerComponentMappingFlag) { 181 + } 182 + else { 183 + if (InitialFState) { 184 + } else { 185 + EnumerateGraphicsCodec(fdoCtx); 186 + } 187 + } 188 + } 189 + 190 + void 191 + NTAPI 192 + HDAGraphicsPowerInterfaceAdd(WDFWORKITEM WorkItem) { 193 + PGRAPHICSWORKITEM_CONTEXT workItemContext = GraphicsWorkitem_GetContext(WorkItem); 194 + PFDO_CONTEXT fdoCtx = workItemContext->FdoContext; 195 + PUNICODE_STRING graphicsDeviceSymlink = &workItemContext->GPUDeviceSymlink; 196 + 197 + WDF_OBJECT_ATTRIBUTES attributes; 198 + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, GRAPHICSIOTARGET_CONTEXT); 199 + 200 + WDFIOTARGET ioTarget; 201 + WDF_IO_TARGET_OPEN_PARAMS openParams; 202 + PGRAPHICSIOTARGET_CONTEXT ioTargetContext; 203 + 204 + NTSTATUS status = WdfIoTargetCreate(fdoCtx->WdfDevice, &attributes, &ioTarget); 205 + if (!NT_SUCCESS(status)) { 206 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 207 + "WdfIoTargetCreate failed 0x%x\n", status); 208 + goto exit; 209 + } 210 + 211 + ioTargetContext = GraphicsIoTarget_GetContext(ioTarget); 212 + ioTargetContext->FdoContext = fdoCtx; 213 + 214 + WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME( 215 + &openParams, 216 + graphicsDeviceSymlink, 217 + STANDARD_RIGHTS_ALL); 218 + openParams.ShareAccess = FILE_SHARE_WRITE | FILE_SHARE_READ; 219 + openParams.EvtIoTargetQueryRemove = HDAGraphics_EvtIoTargetQueryRemove; 220 + openParams.EvtIoTargetRemoveCanceled = HDAGraphics_EvtIoTargetRemoveCanceled; 221 + openParams.EvtIoTargetRemoveComplete = HDAGraphics_EvtIoTargetRemoveComplete; 222 + 223 + status = WdfIoTargetOpen(ioTarget, &openParams); 224 + 225 + if (!NT_SUCCESS(status)) { 226 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 227 + "WdfIoTargetOpen failed with status 0x%x\n", status); 228 + WdfObjectDelete(ioTarget); 229 + goto exit; 230 + } 231 + 232 + WdfWaitLockAcquire(fdoCtx->GraphicsDevicesCollectionWaitLock, NULL); 233 + WdfCollectionAdd(fdoCtx->GraphicsDevicesCollection, ioTarget); 234 + WdfWaitLockRelease(fdoCtx->GraphicsDevicesCollectionWaitLock); 235 + 236 + DXGK_GRAPHICSPOWER_REGISTER_INPUT graphicsPowerRegisterInput; 237 + graphicsPowerRegisterInput = { 0 }; 238 + graphicsPowerRegisterInput.Version = DXGK_GRAPHICSPOWER_VERSION; 239 + graphicsPowerRegisterInput.PrivateHandle = fdoCtx; 240 + graphicsPowerRegisterInput.PowerNotificationCb = HDAGraphicsPowerNotificationCallback; 241 + graphicsPowerRegisterInput.RemovalNotificationCb = HDAGraphicsPowerRemovalNotificationCallback; 242 + graphicsPowerRegisterInput.FStateNotificationCb = HDAGraphicsPowerFStateNotificationCallback; 243 + graphicsPowerRegisterInput.InitialComponentStateCb = HDAGraphicsPowerInitialComponentStateCallback; 244 + 245 + WDF_MEMORY_DESCRIPTOR inputDescriptor; 246 + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&inputDescriptor, &graphicsPowerRegisterInput, sizeof(graphicsPowerRegisterInput)); 247 + 248 + WDF_MEMORY_DESCRIPTOR outputDescriptor; 249 + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputDescriptor, &ioTargetContext->graphicsPowerRegisterOutput, sizeof(ioTargetContext->graphicsPowerRegisterOutput)); 250 + 251 + status = WdfIoTargetSendInternalIoctlSynchronously(ioTarget, 252 + WDF_NO_HANDLE, 253 + IOCTL_INTERNAL_GRAPHICSPOWER_REGISTER, 254 + &inputDescriptor, &outputDescriptor, NULL, NULL); 255 + if (!NT_SUCCESS(status)) { 256 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 257 + "IOCTL_INTERNAL_GRAPHICSPOWER_REGISTER failed with status 0x%x\n", status); 258 + goto exit; 259 + } 260 + 261 + exit: 262 + WdfObjectDelete(WorkItem); 263 + } 264 + 265 + NTSTATUS 266 + NTAPI 267 + HDAGraphicsPowerInterfaceCallback( 268 + PVOID NotificationStruct, 269 + PVOID Context 270 + ) { 271 + NTSTATUS status = STATUS_SUCCESS; 272 + PFDO_CONTEXT fdoCtx = (PFDO_CONTEXT)Context; 273 + PDEVICE_INTERFACE_CHANGE_NOTIFICATION devNotificationStruct = (PDEVICE_INTERFACE_CHANGE_NOTIFICATION)NotificationStruct; 274 + 275 + if (!IsEqualGUID(devNotificationStruct->InterfaceClassGuid, GUID_DEVINTERFACE_GRAPHICSPOWER)) { 276 + return STATUS_NOT_SUPPORTED; 277 + } 278 + 279 + if (IsEqualGUID(devNotificationStruct->Event, GUID_DEVICE_INTERFACE_ARRIVAL)) { 280 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 281 + "Graphics Arrival Notification!\n"); 282 + 283 + status = RtlUnicodeStringValidate(devNotificationStruct->SymbolicLinkName); 284 + if (!NT_SUCCESS(status)) { 285 + return status; 286 + } 287 + 288 + WDF_WORKITEM_CONFIG workItemConfig; 289 + WDF_WORKITEM_CONFIG_INIT(&workItemConfig, HDAGraphicsPowerInterfaceAdd); 290 + 291 + WDF_OBJECT_ATTRIBUTES attributes; 292 + WDFWORKITEM workItem; 293 + 294 + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 295 + WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE( 296 + &attributes, 297 + GRAPHICSWORKITEM_CONTEXT 298 + ); 299 + attributes.ParentObject = fdoCtx->WdfDevice; 300 + 301 + WdfWorkItemCreate(&workItemConfig, &attributes, &workItem); 302 + 303 + PGRAPHICSWORKITEM_CONTEXT workItemContext = GraphicsWorkitem_GetContext(workItem); 304 + workItemContext->FdoContext = fdoCtx; 305 + workItemContext->GPUDeviceSymlink = *devNotificationStruct->SymbolicLinkName; 306 + 307 + WdfWorkItemEnqueue(workItem); 308 + } 309 + 310 + return status; 311 + } 312 + 313 + void CheckHDAGraphicsRegistryKeys(PFDO_CONTEXT fdoCtx) { 314 + NTSTATUS status; 315 + WDFKEY driverKey; 316 + status = WdfDeviceOpenRegistryKey(fdoCtx->WdfDevice, PLUGPLAY_REGKEY_DRIVER, READ_CONTROL, NULL, &driverKey); 317 + if (!NT_SUCCESS(status)) { 318 + return; 319 + } 320 + 321 + WDFKEY settingsKey; 322 + DECLARE_CONST_UNICODE_STRING(DriverSettings, L"Settings"); 323 + DECLARE_CONST_UNICODE_STRING(GfxSharedCodecAddress, L"GfxSharedCodecAddress"); 324 + status = WdfRegistryOpenKey(driverKey, &DriverSettings, READ_CONTROL, NULL, &settingsKey); 325 + if (!NT_SUCCESS(status)) { 326 + goto closeDriverKey; 327 + } 328 + 329 + ULONG GfxCodecAddr; 330 + status = WdfRegistryQueryULong(settingsKey, &GfxSharedCodecAddress, &GfxCodecAddr); 331 + if (NT_SUCCESS(status)) { 332 + fdoCtx->UseSGPCCodec = TRUE; 333 + fdoCtx->GraphicsCodecAddress = GfxCodecAddr; 334 + } 335 + 336 + WdfRegistryClose(settingsKey); 337 + 338 + closeDriverKey: 339 + WdfRegistryClose(driverKey); 340 + }
+60
drivers/wdm/audio/hdaudbus_new/sklhdaudbus.cpp
··· 1 + #include "driver.h" 2 + 3 + NTSTATUS 4 + NTAPI 5 + SklHdAudBusEvtDeviceAdd( 6 + _In_ WDFDRIVER Driver, 7 + _Inout_ PWDFDEVICE_INIT DeviceInit 8 + ) 9 + { 10 + UNREFERENCED_PARAMETER(Driver); 11 + NTSTATUS status; 12 + 13 + // 14 + // Initialize all the properties specific to the device. 15 + // Framework has default values for the one that are not 16 + // set explicitly here. So please read the doc and make sure 17 + // you are okay with the defaults. 18 + // 19 + WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER); 20 + 21 + status = Fdo_Create(DeviceInit); 22 + return status; 23 + } 24 + 25 + extern "C" NTSTATUS 26 + NTAPI 27 + DriverEntry( 28 + __in PDRIVER_OBJECT DriverObject, 29 + __in PUNICODE_STRING RegistryPath 30 + ) 31 + { 32 + WDF_DRIVER_CONFIG config; 33 + NTSTATUS status; 34 + WDFDRIVER wdfDriver; 35 + 36 + SklHdAudBusPrint(DEBUG_LEVEL_INFO, DBG_INIT, 37 + "Driver Entry\n"); 38 + 39 + // 40 + // Default to NonPagedPoolNx for non paged pool allocations where supported. 41 + // 42 + 43 + ExInitializeDriverRuntime(DrvRtPoolNxOptIn); 44 + 45 + WDF_DRIVER_CONFIG_INIT(&config, SklHdAudBusEvtDeviceAdd); 46 + 47 + status = WdfDriverCreate(DriverObject, 48 + RegistryPath, 49 + WDF_NO_OBJECT_ATTRIBUTES, 50 + &config, 51 + &wdfDriver 52 + ); 53 + if (!NT_SUCCESS(status)) 54 + { 55 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_INIT, 56 + "WdfDriverCreate failed %x\n", status); 57 + } 58 + 59 + return status; 60 + }
+101
drivers/wdm/audio/hdaudbus_new/sklhdaudbus.inf
··· 1 + ;/*++ 2 + ; 3 + ;Copyright (c) CoolStar. All rights reserved. 4 + ; 5 + ;Module Name: 6 + ; sklhdaudbus.inf 7 + ; 8 + ;Abstract: 9 + ; INF file for installing the SKL HD Aud Bus Driver 10 + ; 11 + ; 12 + ;--*/ 13 + 14 + [Version] 15 + Signature = "$WINDOWS NT$" 16 + Class = System 17 + ClassGuid = {4d36e97d-e325-11ce-bfc1-08002be10318} 18 + Provider = CoolStar 19 + DriverVer = 8/15/2022,1.0.0 20 + CatalogFile = sklhdaudbus.cat 21 + PnpLockdown = 1 22 + 23 + [DestinationDirs] 24 + DefaultDestDir = 12 25 + 26 + ; ================= Class section ===================== 27 + 28 + [SourceDisksNames] 29 + 1 = %DiskId1%,,,"" 30 + 31 + [SourceDisksFiles] 32 + sklhdaudbus.sys = 1,, 33 + 34 + [SignatureAttributes] 35 + sklhdaudbus.sys=SignatureAttributes.DRM 36 + 37 + [SignatureAttributes.DRM] 38 + DRMLevel=1300 39 + 40 + [SignatureAttributes.PETrust] 41 + PETrust=true 42 + 43 + ;***************************************** 44 + ; SklHDAudBus Install Section 45 + ;***************************************** 46 + 47 + [Manufacturer] 48 + %StdMfg%=Standard,NT$ARCH$ 49 + 50 + ; Decorated model section take precedence over undecorated 51 + ; ones on XP and later. 52 + [Standard.NT$ARCH$] 53 + %SklHDAudBus.DeviceDesc%=SklHDAudBus_Device, PCI\VEN_8086&DEV_9D70&CC_0401 ;Intel Skylake 54 + %SklHDAudBus.DeviceDesc%=SklHDAudBus_Device, PCI\VEN_8086&DEV_9D71&CC_0401 ;Intel Kaby Lake 55 + %SklHDAudBus.DeviceDesc%=SklHDAudBus_Device, PCI\VEN_8086&DEV_5A98&CC_0401 ;Intel Apollo Lake 56 + %SklHDAudBus.DeviceDesc%=SklHDAudBus_Device, PCI\VEN_8086&DEV_3198&CC_0401 ;Intel Gemini Lake 57 + %SklHDAudBus.DeviceDesc%=SklHDAudBus_Device, PCI\VEN_8086&DEV_02C8&CC_0401 ;Intel Comet Lake 58 + %SklHDAudBus.DeviceDesc%=SklHDAudBus_Device, PCI\VEN_8086&DEV_4DC8&CC_0401 ;Intel Jasper Lake 59 + %SklHDAudBus.DeviceDesc%=SklHDAudBus_Device, PCI\VEN_8086&DEV_A0C8&CC_0401 ;Intel Tiger Lake 60 + %SklHDAudBus.DeviceDesc%=SklHDAudBus_Device, PCI\VEN_8086&DEV_51C8&CC_0401 ;Intel Alder Lake-P 61 + %SklHDAudBus.DeviceDesc%=SklHDAudBus_Device, PCI\VEN_8086&DEV_51CC&CC_0401 ;Intel Alder Lake-M 62 + %SklHDAudBus.DeviceDesc%=SklHDAudBus_Device, PCI\VEN_8086&DEV_54C8&CC_0401 ;Intel Alder Lake-N 63 + %SklHDAudBus.DeviceDesc%=SklHDAudBus_Device, PCI\VEN_8086&DEV_51CA&CC_0401 ;Intel Raptor Lake-P 64 + %SklHDAudBus.DeviceDesc%=SklHDAudBus_Device, PCI\VEN_8086&DEV_7E28&CC_0401 ;Intel Meteor Lake-P 65 + %SklHDAudBus.DeviceDesc%=SklHDAudBus_Device, PCI\VEN_8086&DEV_7728&CC_0401 ;Intel Arrow Lake-P 66 + %SklHDAudBus.DeviceDesc%=SklHDAudBus_Device, PCI\VEN_8086&DEV_A828&CC_0401 ;Intel Lunar Lake-P 67 + 68 + [SklHDAudBus_Device.NT] 69 + CopyFiles=Drivers_Dir 70 + 71 + [SklHDAudBus_Device.NT.HW] 72 + AddReg=SklHDAudBus_AddReg 73 + Include=pci.inf 74 + Needs=PciD3ColdSupported.HW 75 + 76 + [Drivers_Dir] 77 + sklhdaudbus.sys 78 + 79 + [SklHDAudBus_AddReg] 80 + ; Set to 1 to connect the first interrupt resource found, 0 to leave disconnected 81 + HKR,Settings,"ConnectInterrupt",0x00010001,0 82 + 83 + ;-------------- Service installation 84 + [SklHDAudBus_Device.NT.Services] 85 + AddService = SklHDAudBus,%SPSVCINST_ASSOCSERVICE%, SklHDAudBus_Service_Inst 86 + 87 + ; -------------- SklHDAudBus driver install sections 88 + [SklHDAudBus_Service_Inst] 89 + DisplayName = %SklHDAudBus.SVCDESC% 90 + ServiceType = 1 ; SERVICE_KERNEL_DRIVER 91 + StartType = 3 ; SERVICE_DEMAND_START 92 + ErrorControl = 1 ; SERVICE_ERROR_NORMAL 93 + ServiceBinary = %12%\sklhdaudbus.sys 94 + LoadOrderGroup = Base 95 + 96 + [Strings] 97 + SPSVCINST_ASSOCSERVICE= 0x00000002 98 + StdMfg = "CoolStar" 99 + DiskId1 = "CoolStar HD Audio Installation Disk #1" 100 + SklHDAudBus.DeviceDesc = "CoolStar HD Audio" 101 + SklHDAudBus.SVCDESC = "CoolStar HD Audio Service"
+41
drivers/wdm/audio/hdaudbus_new/sklhdaudbus.rc
··· 1 + /*++ 2 + 3 + Copyright (c) Microsoft Corporation All Rights Reserved 4 + 5 + Module Name: 6 + 7 + sklhdaudbus.rc 8 + 9 + Abstract: 10 + 11 + --*/ 12 + 13 + #include <windows.h> 14 + 15 + #define VER_FILETYPE VFT_DRV 16 + #define VER_FILESUBTYPE VFT2_DRV_SYSTEM 17 + #define VER_FILEDESCRIPTION_STR "CoolStar HD Audio" 18 + #define VER_INTERNALNAME_STR "sklhdaudbus.sys" 19 + #define VER_ORIGINALFILENAME_STR "sklhdaudbus.sys" 20 + 21 + #define VER_LEGALCOPYRIGHT_YEARS "2024" 22 + #define VER_LEGALCOPYRIGHT_STR "Copyright (C) " VER_LEGALCOPYRIGHT_YEARS " CoolStar." 23 + 24 + #define VER_FILEVERSION 1,0,5,0 25 + #define VER_PRODUCTVERSION_STR "1.0.5.0" 26 + #define VER_PRODUCTVERSION 1,0,5,0 27 + #define LVER_PRODUCTVERSION_STR L"1.0.5.0" 28 + 29 + #define VER_FILEFLAGSMASK (VS_FF_DEBUG | VS_FF_PRERELEASE) 30 + #ifdef DEBUG 31 + #define VER_FILEFLAGS (VS_FF_DEBUG) 32 + #else 33 + #define VER_FILEFLAGS (0) 34 + #endif 35 + 36 + #define VER_FILEOS VOS_NT_WINDOWS32 37 + 38 + #define VER_COMPANYNAME_STR "CoolStar" 39 + #define VER_PRODUCTNAME_STR "CoolStar HD Audio" 40 + 41 + #include "common.ver"
+158
drivers/wdm/audio/hdaudbus_new/sof-tplg.cpp
··· 1 + #include "driver.h" 2 + #include <acpiioct.h> 3 + #include "sof-tplg.h" 4 + 5 + DEFINE_GUID(GUID_ACPI_DSD, 6 + 0xdaffd814, 0x6eba, 0x4d8c, 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01); 7 + 8 + void copyDSDParam(PACPI_METHOD_ARGUMENT dsdParameterData, char** buf) { 9 + RtlZeroMemory(buf, 32); 10 + RtlCopyMemory(buf, dsdParameterData->Data, min(dsdParameterData->DataLength, 32)); 11 + } 12 + 13 + NTSTATUS 14 + GetSOFTplg( 15 + _In_ WDFDEVICE FxDevice, 16 + SOF_TPLG* sofTplg 17 + ) 18 + { 19 + if (!sofTplg) { 20 + return STATUS_INVALID_PARAMETER; 21 + } 22 + 23 + NTSTATUS status = STATUS_ACPI_NOT_INITIALIZED; 24 + ACPI_EVAL_INPUT_BUFFER_EX inputBuffer; 25 + RtlZeroMemory(&inputBuffer, sizeof(inputBuffer)); 26 + 27 + inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE_EX; 28 + status = RtlStringCchPrintfA( 29 + inputBuffer.MethodName, 30 + sizeof(inputBuffer.MethodName), 31 + "_DSD" 32 + ); 33 + if (!NT_SUCCESS(status)) { 34 + return status; 35 + } 36 + 37 + ACPI_EVAL_OUTPUT_BUFFER outputSizeBuffer = { 0 }; 38 + 39 + WDF_MEMORY_DESCRIPTOR outputSizeMemDesc; 40 + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&outputSizeMemDesc, &outputSizeBuffer, (ULONG)sizeof(outputSizeBuffer)); 41 + 42 + WDF_MEMORY_DESCRIPTOR inputMemDesc; 43 + WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&inputMemDesc, &inputBuffer, (ULONG)sizeof(inputBuffer)); 44 + 45 + // Send the request along 46 + status = WdfIoTargetSendInternalIoctlSynchronously( 47 + WdfDeviceGetIoTarget(FxDevice), 48 + NULL, 49 + IOCTL_ACPI_EVAL_METHOD_EX, 50 + &inputMemDesc, 51 + &outputSizeMemDesc, 52 + NULL, 53 + NULL 54 + ); 55 + 56 + if (status != STATUS_BUFFER_OVERFLOW) { 57 + // Method might not exist? 58 + return status; 59 + } 60 + 61 + WDFMEMORY outputMemory; 62 + PACPI_EVAL_OUTPUT_BUFFER outputBuffer; 63 + size_t outputArgumentBufferSize = outputSizeBuffer.Length; 64 + size_t outputBufferSize = FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) + outputArgumentBufferSize; 65 + 66 + WDF_OBJECT_ATTRIBUTES attributes; 67 + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 68 + attributes.ParentObject = FxDevice; 69 + 70 + status = WdfMemoryCreate(&attributes, 71 + NonPagedPoolNx, 72 + 0, 73 + outputBufferSize, 74 + &outputMemory, 75 + (PVOID*)&outputBuffer); 76 + if (!NT_SUCCESS(status)) { 77 + return status; 78 + } 79 + 80 + RtlZeroMemory(outputBuffer, outputBufferSize); 81 + 82 + WDF_MEMORY_DESCRIPTOR outputMemDesc; 83 + WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&outputMemDesc, outputMemory, NULL); 84 + 85 + status = WdfIoTargetSendInternalIoctlSynchronously( 86 + WdfDeviceGetIoTarget(FxDevice), 87 + NULL, 88 + IOCTL_ACPI_EVAL_METHOD_EX, 89 + &inputMemDesc, 90 + &outputMemDesc, 91 + NULL, 92 + NULL 93 + ); 94 + if (!NT_SUCCESS(status)) { 95 + goto Exit; 96 + } 97 + 98 + if (outputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) { 99 + goto Exit; 100 + } 101 + 102 + SklHdAudBusPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 103 + "Evaluted %s successfully\n", inputBuffer.MethodName); 104 + 105 + if (outputBuffer->Count % 2) { 106 + status = STATUS_ACPI_INVALID_DATA; 107 + goto Exit; 108 + } 109 + 110 + status = STATUS_NOT_FOUND; 111 + 112 + RtlZeroMemory(sofTplg, sizeof(*sofTplg)); 113 + sofTplg->magic = SOFTPLG_MAGIC; 114 + sofTplg->length = sizeof(*sofTplg); 115 + 116 + { 117 + PACPI_METHOD_ARGUMENT currArgument = &outputBuffer->Argument[0]; 118 + for (ULONG i = 0; i < outputBuffer->Count; i += 2) { 119 + PACPI_METHOD_ARGUMENT guidArg = currArgument; 120 + currArgument = ACPI_METHOD_NEXT_ARGUMENT(currArgument); 121 + PACPI_METHOD_ARGUMENT packageArg = currArgument; 122 + currArgument = ACPI_METHOD_NEXT_ARGUMENT(currArgument); 123 + 124 + if (guidArg->Type != ACPI_METHOD_ARGUMENT_BUFFER || 125 + guidArg->DataLength != 16 || 126 + packageArg->Type != ACPI_METHOD_ARGUMENT_PACKAGE) { 127 + break; 128 + } 129 + 130 + if (memcmp(guidArg->Data, &GUID_ACPI_DSD, guidArg->DataLength) != 0) { 131 + continue; 132 + } 133 + 134 + status = STATUS_SUCCESS; 135 + 136 + FOR_EACH_ACPI_METHOD_ARGUMENT(dsdParameter, (PACPI_METHOD_ARGUMENT)packageArg->Data, (PACPI_METHOD_ARGUMENT)(packageArg->Data + packageArg->DataLength)) { 137 + PACPI_METHOD_ARGUMENT dsdParameterName = (PACPI_METHOD_ARGUMENT)dsdParameter->Data; 138 + PACPI_METHOD_ARGUMENT dsdParameterData = ACPI_METHOD_NEXT_ARGUMENT(dsdParameterName); 139 + 140 + if (strncmp((const char*)&dsdParameterName->Data[0], "speaker-tplg", dsdParameterName->DataLength) == 0) { 141 + copyDSDParam(dsdParameterData, (char **)&sofTplg->speaker_tplg); 142 + } 143 + else if (strncmp((const char*)&dsdParameterName->Data[0], "hp-tplg", dsdParameterName->DataLength) == 0) { 144 + copyDSDParam(dsdParameterData, (char**)&sofTplg->hp_tplg); 145 + } 146 + else if (strncmp((const char*)&dsdParameterName->Data[0], "mic-tplg", dsdParameterName->DataLength) == 0) { 147 + copyDSDParam(dsdParameterData, (char**)&sofTplg->dmic_tplg); 148 + } 149 + } 150 + } 151 + } 152 + 153 + Exit: 154 + if (outputMemory != WDF_NO_HANDLE) { 155 + WdfObjectDelete(outputMemory); 156 + } 157 + return status; 158 + }
+11
drivers/wdm/audio/hdaudbus_new/sof-tplg.h
··· 1 + #define SOFTPLG_MAGIC '$SOF' 2 + 3 + typedef struct _SOF_TPLG { 4 + UINT32 magic; 5 + UINT32 length; 6 + char speaker_tplg[32]; 7 + char hp_tplg[32]; 8 + char dmic_tplg[32]; 9 + } SOF_TPLG, *PSOF_TPLG; 10 + 11 + NTSTATUS GetSOFTplg(WDFDEVICE FxDevice, SOF_TPLG *sofTplg);
+43
drivers/wdm/audio/hdaudbus_new/trace.h
··· 1 + #include <evntrace.h> 2 + 3 + #ifndef _TRACE_H_ 4 + #define _TRACE_H_ 5 + 6 + extern "C" 7 + { 8 + // 9 + // Tracing Definitions: 10 + // 11 + // Control GUID: 12 + // {73e3b785-f5fb-423e-94a9-56627fea9053} 13 + // 14 + 15 + #define WPP_CONTROL_GUIDS \ 16 + WPP_DEFINE_CONTROL_GUID( \ 17 + SpbTestToolTraceGuid, \ 18 + (73e3b785,f5fb,423e,94a9,56627fea9053), \ 19 + WPP_DEFINE_BIT(TRACE_FLAG_WDFLOADING) \ 20 + WPP_DEFINE_BIT(TRACE_FLAG_SPBAPI) \ 21 + WPP_DEFINE_BIT(TRACE_FLAG_OTHER) \ 22 + ) 23 + } 24 + 25 + #define WPP_LEVEL_FLAGS_LOGGER(level,flags) WPP_LEVEL_LOGGER(flags) 26 + #define WPP_LEVEL_FLAGS_ENABLED(level, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= level) 27 + 28 + #define Trace CyapaPrint 29 + #define FuncEntry 30 + #define FuncExit 31 + #define WPP_INIT_TRACING 32 + #define WPP_CLEANUP 33 + #define TRACE_FLAG_SPBAPI 0 34 + #define TRACE_FLAG_WDFLOADING 0 35 + 36 + // begin_wpp config 37 + // FUNC FuncEntry{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS); 38 + // FUNC FuncExit{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS); 39 + // USEPREFIX(FuncEntry, "%!STDPREFIX! [%!FUNC!] --> entry"); 40 + // USEPREFIX(FuncExit, "%!STDPREFIX! [%!FUNC!] <--"); 41 + // end_wpp 42 + 43 + #endif _TRACE_H_
+6
media/doc/3rd Party Files.txt
··· 174 174 License: BSD-3-Clause (https://opensource.org/licenses/BSD-3-Clause) 175 175 URL: https://code.google.com/archive/p/cmediadrivers/ 176 176 177 + Title: HD Audio Driver for Windows 10 / 11 with Skylake -> Raptor Lake DSP support 178 + Path: drivers/wdm/audio/hdaudbus_new 179 + Used Version: git commit ad50bcc 180 + License: BSD-3-Clause (https://opensource.org/licenses/BSD-3-Clause) 181 + URL: https://github.com/coolstar/sklhdaudbus/tree/master 182 + 177 183 Title: PCI hardware IDs database 178 184 Path: hal/halx86/legacy/bus/pci_classes.ids 179 185 Path: hal/halx86/legacy/bus/pci_vendors.ids