├── Source ├── Main │ ├── IntcSST2.bin │ ├── csaudiosstcatpt.inx │ ├── Main.vcxproj.filters │ ├── csaudiosstcatpt.rc │ ├── minwavertstream.h │ ├── NewDelete.cpp │ └── minwavert.h ├── Utilities │ ├── firmware.h │ ├── resource.h │ ├── bitops.h │ ├── bitops.c │ ├── firmware.cpp │ ├── resource.cpp │ ├── Utilities.vcxproj.Filters │ ├── registers.h │ ├── loader.cpp │ ├── ipc.cpp │ ├── messages.cpp │ ├── pcm.cpp │ ├── dsp.cpp │ ├── messages.h │ ├── pa2xxssp.h │ ├── hw.h │ ├── dw_dma.cpp │ └── dw_dma.h ├── Filters │ ├── speakertopo.h │ ├── micjacktopo.h │ ├── micjacktopo.cpp │ ├── speakertopo.cpp │ ├── Filters.vcxproj.Filters │ ├── speakertoptable.h │ ├── micjacktoptable.h │ ├── minipairs.h │ ├── speakerwavtable.h │ └── micarraywavtable.h └── Inc │ ├── Inc.vcxproj.Filters │ ├── mintopo.h │ ├── NewDelete.h │ ├── basetopo.h │ ├── endpoints.h │ ├── kshelper.h │ └── definitions.h ├── README.md ├── Package ├── package.VcxProj.Filters └── package.VcxProj ├── .gitignore └── csaudiosstcatpt.sln /Source/Main/IntcSST2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrultrabook/csaudiosstcatpt/main/Source/Main/IntcSST2.bin -------------------------------------------------------------------------------- /Source/Main/csaudiosstcatpt.inx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrultrabook/csaudiosstcatpt/main/Source/Main/csaudiosstcatpt.inx -------------------------------------------------------------------------------- /Source/Utilities/firmware.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | struct firmware { 5 | void* data; 6 | size_t size; 7 | }; 8 | 9 | NTSTATUS request_firmware(const struct firmware** img, PCWSTR path); 10 | void free_firmware(struct firmware* fw); -------------------------------------------------------------------------------- /Source/Utilities/resource.h: -------------------------------------------------------------------------------- 1 | #include "hw.h" 2 | #pragma once 3 | 4 | PRESOURCE __request_region(PRESOURCE parent, 5 | size_t start, size_t n, int flags); 6 | void __release_region(PRESOURCE parent, size_t start, 7 | size_t n); 8 | NTSTATUS release_resource(PRESOURCE old); 9 | static inline size_t resource_size(PRESOURCE res) 10 | { 11 | return res->end - res->start + 1; 12 | } -------------------------------------------------------------------------------- /Source/Utilities/bitops.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define BITS_PER_LONG sizeof(LONG) * 8 4 | 5 | #define GENMASK(h, l) (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) 6 | #define BIT(nr) (1UL << (nr)) 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | int fls(unsigned int x); 13 | unsigned long __ffs(unsigned long word); 14 | unsigned int __sw_hweight32(unsigned int w); 15 | 16 | #define hweight_long __sw_hweight32 17 | 18 | #ifdef __cplusplus 19 | } 20 | #endif -------------------------------------------------------------------------------- /Source/Filters/speakertopo.h: -------------------------------------------------------------------------------- 1 | 2 | /*++ 3 | 4 | Copyright (c) Microsoft Corporation All Rights Reserved 5 | 6 | Module Name: 7 | 8 | speakertopo.h 9 | 10 | Abstract: 11 | 12 | Declaration of topology miniport for the speaker (internal). 13 | --*/ 14 | 15 | #ifndef _CSAUDIOSSTCATPT_SPEAKERTOPO_H_ 16 | #define _CSAUDIOSSTCATPT_SPEAKERTOPO_H_ 17 | 18 | NTSTATUS PropertyHandler_SpeakerTopoFilter(_In_ PPCPROPERTY_REQUEST PropertyRequest); 19 | 20 | NTSTATUS PropertyHandler_SpeakerTopology(_In_ PPCPROPERTY_REQUEST PropertyRequest); 21 | 22 | #endif // _CSAUDIOSSTCATPT_SPEAKERTOPO_H_ 23 | -------------------------------------------------------------------------------- /Source/Filters/micjacktopo.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | micjack.h 8 | 9 | Abstract: 10 | 11 | Declaration of topology miniport for the mic (external: headphone). 12 | 13 | --*/ 14 | 15 | #ifndef _CSAUDIOSSTCATPT_MICJACKTOPO_H_ 16 | #define _CSAUDIOSSTCATPT_MICJACKTOPO_H_ 17 | 18 | // Function declarations. 19 | NTSTATUS 20 | PropertyHandler_MicJackTopoFilter(_In_ PPCPROPERTY_REQUEST PropertyRequest); 21 | 22 | NTSTATUS PropertyHandler_MicJackTopology(_In_ PPCPROPERTY_REQUEST PropertyRequest); 23 | 24 | #endif // _CSAUDIOSSTCATPT_MICJACKTOPO_H_ 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CoolStar Audio for Intel Haswell / Broadwell SST 2 | 3 | Open Source alternative for the Intel Haswell / Broadwell SST driver (untested on Haswell) 4 | 5 | Tested on Google Pixel 2 LS (Core i7-5500U) 6 | 7 | Based off csaudioacp3x 8 | 9 | catpt commit: b695f5c0a86ea685500a72b6a9959da041f26da6 10 | dma/dw commit: d5a8fe0fee54d830c47959f625ffc41d080ee526 11 | 12 | # Binary Blob 13 | 14 | This driver requires a binary blob you can get here: https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/intel/IntcSST2.bin 15 | 16 | Drop this binary into Source/Main and you can build 17 | 18 | Known working SHA256: 78DC1771E6AE22A392CC9E249AE2817B01EC0D3CABCF631719624CDD3CF5AB81 -------------------------------------------------------------------------------- /Source/Main/Main.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {26f27f11-65d5-4096-9986-11ab95e6ca55} 21 | .bin 22 | 23 | 24 | 25 | 26 | Firmware 27 | 28 | 29 | -------------------------------------------------------------------------------- /Package/package.VcxProj.Filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;* 6 | {0924612D-FBA7-477E-BBB9-B3B6EA7C6B03} 7 | 8 | 9 | h;hpp;hxx;hm;inl;inc;xsd 10 | {97311738-0AD8-4F7E-AC88-9C9BEAF53AEE} 11 | 12 | 13 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml 14 | {8DC1C4F0-C285-400E-A983-77A339891354} 15 | 16 | 17 | inf;inv;inx;mof;mc; 18 | {9F086F34-79D2-4FAA-87FD-C2DBEFCED0BA} 19 | 20 | 21 | -------------------------------------------------------------------------------- /Source/Inc/Inc.vcxproj.Filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;* 6 | {54BE0AAC-642F-4D50-80D1-CA3C4BB4BB4C} 7 | 8 | 9 | h;hpp;hxx;hm;inl;inc;xsd 10 | {6A00B9EC-DB03-4D51-B351-60DE9C0C51A1} 11 | 12 | 13 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml 14 | {887357BD-50C0-40E6-85E8-87E0F45862DB} 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Source/Main/csaudiosstcatpt.rc: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | CsAudioSSTCatPt.rc 8 | 9 | Abstract: 10 | 11 | --*/ 12 | 13 | #include 14 | 15 | #define VER_FILETYPE VFT_DRV 16 | #define VER_FILESUBTYPE VFT2_DRV_SOUND 17 | #define VER_FILEDESCRIPTION_STR "CoolStar SST Audio (Broadwell)" 18 | #define VER_INTERNALNAME_STR "CsAudioSSTCatPt.sys" 19 | #define VER_ORIGINALFILENAME_STR "CsAudioSSTCatPt.sys" 20 | 21 | #define VER_LEGALCOPYRIGHT_YEARS "2023" 22 | #define VER_LEGALCOPYRIGHT_STR "Copyright (C) " VER_LEGALCOPYRIGHT_YEARS " CoolStar." 23 | 24 | #define VER_FILEVERSION 1,0,1,0 25 | #define VER_PRODUCTVERSION_STR "1.0.1.0" 26 | #define VER_PRODUCTVERSION 1,0,1,0 27 | #define LVER_PRODUCTVERSION_STR L"1.0.1.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 SST Audio (Broadwell)" 40 | 41 | #include "common.ver" -------------------------------------------------------------------------------- /Source/Utilities/bitops.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "bitops.h" 3 | 4 | #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) 5 | 6 | unsigned int __sw_hweight32(unsigned int w) 7 | { 8 | w -= (w >> 1) & 0x55555555; 9 | w = (w & 0x33333333) + ((w >> 2) & 0x33333333); 10 | w = (w + (w >> 4)) & 0x0f0f0f0f; 11 | return (w * 0x01010101) >> 24; 12 | } 13 | 14 | int fls(unsigned int x) 15 | { 16 | int r = 32; 17 | 18 | if (!x) 19 | return 0; 20 | if (!(x & 0xffff0000u)) { 21 | x <<= 16; 22 | r -= 16; 23 | } 24 | if (!(x & 0xff000000u)) { 25 | x <<= 8; 26 | r -= 8; 27 | } 28 | if (!(x & 0xf0000000u)) { 29 | x <<= 4; 30 | r -= 4; 31 | } 32 | if (!(x & 0xc0000000u)) { 33 | x <<= 2; 34 | r -= 2; 35 | } 36 | if (!(x & 0x80000000u)) { 37 | x <<= 1; 38 | r -= 1; 39 | } 40 | return r; 41 | } 42 | 43 | unsigned long __ffs(unsigned long word) 44 | { 45 | int num = 0; 46 | 47 | if ((word & 0xffff) == 0) { 48 | num += 16; 49 | word >>= 16; 50 | } 51 | if ((word & 0xff) == 0) { 52 | num += 8; 53 | word >>= 8; 54 | } 55 | if ((word & 0xf) == 0) { 56 | num += 4; 57 | word >>= 4; 58 | } 59 | if ((word & 0x3) == 0) { 60 | num += 2; 61 | word >>= 2; 62 | } 63 | if ((word & 0x1) == 0) 64 | num += 1; 65 | return num; 66 | } -------------------------------------------------------------------------------- /Source/Utilities/firmware.cpp: -------------------------------------------------------------------------------- 1 | #include "firmware.h" 2 | 3 | #define INTCSST_TAG (ULONG) '$SST' 4 | 5 | NTSTATUS request_firmware(const struct firmware** img, PCWSTR path) { 6 | *img = NULL; 7 | 8 | struct firmware* fw = (struct firmware*)ExAllocatePoolZero(NonPagedPool, sizeof(struct firmware), INTCSST_TAG); 9 | if (!fw) { 10 | return STATUS_NO_MEMORY; 11 | } 12 | RtlZeroMemory(fw, sizeof(struct firmware)); 13 | 14 | NTSTATUS status; 15 | 16 | UNICODE_STRING uniName; 17 | OBJECT_ATTRIBUTES objAttr; 18 | 19 | RtlInitUnicodeString(&uniName, path); 20 | InitializeObjectAttributes(&objAttr, &uniName, 21 | OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 22 | NULL, NULL); 23 | 24 | // Do not try to perform any file operations at higher IRQL levels. 25 | // Instead, you may use a work item or a system worker thread to perform file operations. 26 | 27 | if (KeGetCurrentIrql() != PASSIVE_LEVEL) { 28 | status = STATUS_INVALID_DEVICE_STATE; 29 | free_firmware(fw); 30 | return status; 31 | } 32 | 33 | HANDLE handle; 34 | IO_STATUS_BLOCK ioStatusBlock; 35 | 36 | status = ZwCreateFile(&handle, 37 | GENERIC_READ, 38 | &objAttr, &ioStatusBlock, NULL, 39 | FILE_ATTRIBUTE_NORMAL, 40 | 0, 41 | FILE_OPEN, 42 | FILE_SYNCHRONOUS_IO_NONALERT, 43 | NULL, 0); 44 | if (!NT_SUCCESS(status)) { 45 | free_firmware(fw); 46 | return status; 47 | } 48 | 49 | FILE_STANDARD_INFORMATION fileInfo; 50 | status = ZwQueryInformationFile( 51 | handle, 52 | &ioStatusBlock, 53 | &fileInfo, 54 | sizeof(fileInfo), 55 | FileStandardInformation 56 | ); 57 | if (!NT_SUCCESS(status)) { 58 | ZwClose(handle); 59 | free_firmware(fw); 60 | return status; 61 | } 62 | 63 | fw->size = fileInfo.EndOfFile.QuadPart; 64 | fw->data = ExAllocatePoolZero(NonPagedPool, fw->size, INTCSST_TAG); 65 | if (!fw->data) { 66 | status = STATUS_NO_MEMORY; 67 | ZwClose(handle); 68 | free_firmware(fw); 69 | return status; 70 | } 71 | 72 | LARGE_INTEGER byteOffset; 73 | byteOffset.LowPart = byteOffset.HighPart = 0; 74 | status = ZwReadFile(handle, NULL, NULL, NULL, &ioStatusBlock, fw->data, (ULONG)fw->size, &byteOffset, NULL); 75 | if (!NT_SUCCESS(status)) { 76 | ZwClose(handle); 77 | free_firmware(fw); 78 | return status; 79 | } 80 | *img = fw; 81 | 82 | ZwClose(handle); 83 | return status; 84 | } 85 | 86 | void free_firmware(struct firmware* fw) { 87 | if (fw->data) { 88 | ExFreePoolWithTag(fw->data, INTCSST_TAG); 89 | } 90 | ExFreePoolWithTag(fw, INTCSST_TAG); 91 | } -------------------------------------------------------------------------------- /Source/Inc/mintopo.h: -------------------------------------------------------------------------------- 1 | 2 | /*++ 3 | 4 | Copyright (c) Microsoft Corporation All Rights Reserved 5 | 6 | Module Name: 7 | 8 | minitopo.h 9 | 10 | Abstract: 11 | 12 | Declaration of topology miniport. 13 | --*/ 14 | 15 | #ifndef _CSAUDIOSSTCATPT_MINTOPO_H_ 16 | #define _CSAUDIOSSTCATPT_MINTOPO_H_ 17 | 18 | #include "basetopo.h" 19 | 20 | //============================================================================= 21 | // Classes 22 | //============================================================================= 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | // CMiniportTopology 26 | // 27 | 28 | class CMiniportTopology : 29 | public CMiniportTopologyCsAudioSstCatPt, 30 | public IMiniportTopology, 31 | public CUnknown 32 | { 33 | private: 34 | eDeviceType m_DeviceType; 35 | 36 | union { 37 | PVOID m_DeviceContext; 38 | }; 39 | 40 | public: 41 | DECLARE_STD_UNKNOWN(); 42 | CMiniportTopology 43 | ( 44 | _In_opt_ PUNKNOWN UnknownOuter, 45 | _In_ PCFILTER_DESCRIPTOR *FilterDesc, 46 | _In_ USHORT DeviceMaxChannels, 47 | _In_ eDeviceType DeviceType, 48 | _In_opt_ PVOID DeviceContext 49 | ) 50 | : CUnknown(UnknownOuter), 51 | CMiniportTopologyCsAudioSstCatPt(FilterDesc, DeviceMaxChannels), 52 | m_DeviceType(DeviceType), 53 | m_DeviceContext(DeviceContext) 54 | { 55 | } 56 | 57 | ~CMiniportTopology(); 58 | 59 | IMP_IMiniportTopology; 60 | 61 | NTSTATUS PropertyHandlerJackDescription 62 | ( 63 | _In_ PPCPROPERTY_REQUEST PropertyRequest, 64 | _In_ ULONG cJackDescriptions, 65 | _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION *JackDescriptions 66 | ); 67 | 68 | NTSTATUS PropertyHandlerJackDescription2 69 | ( 70 | _In_ PPCPROPERTY_REQUEST PropertyRequest, 71 | _In_ ULONG cJackDescriptions, 72 | _In_reads_(cJackDescriptions) PKSJACK_DESCRIPTION *JackDescriptions, 73 | _In_ DWORD JackCapabilities 74 | ); 75 | 76 | PVOID GetDeviceContext() { return m_DeviceContext; } 77 | }; 78 | 79 | typedef CMiniportTopology *PCMiniportTopology; 80 | 81 | #endif // _CSAUDIOSSTCATPT_MINTOPO_H_ 82 | -------------------------------------------------------------------------------- /Source/Main/minwavertstream.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | minwavertstream.h 8 | 9 | Abstract: 10 | 11 | Definition of wavert miniport class. 12 | --*/ 13 | 14 | #ifndef _CSAUDIOACP3X_MINWAVERTSTREAM_H_ 15 | #define _CSAUDIOACP3X_MINWAVERTSTREAM_H_ 16 | 17 | // 18 | // Structure to store notifications events in a protected list 19 | // 20 | typedef struct _NotificationListEntry 21 | { 22 | LIST_ENTRY ListEntry; 23 | PKEVENT NotificationEvent; 24 | } NotificationListEntry; 25 | 26 | EXT_CALLBACK TimerNotifyRT; 27 | 28 | //============================================================================= 29 | // Referenced Forward 30 | //============================================================================= 31 | class CMiniportWaveRT; 32 | typedef CMiniportWaveRT *PCMiniportWaveRT; 33 | 34 | //============================================================================= 35 | // Classes 36 | //============================================================================= 37 | /////////////////////////////////////////////////////////////////////////////// 38 | // CMiniportWaveRTStream 39 | // 40 | class CMiniportWaveRTStream : 41 | public IMiniportWaveRTStream, 42 | public IDrmAudioStream, 43 | public CUnknown 44 | { 45 | public: 46 | PPORTWAVERTSTREAM m_pPortStream; 47 | PMDL m_pMDL; 48 | 49 | DECLARE_STD_UNKNOWN(); 50 | DEFINE_STD_CONSTRUCTOR(CMiniportWaveRTStream); 51 | ~CMiniportWaveRTStream(); 52 | 53 | IMP_IMiniportWaveRTStream; 54 | IMP_IMiniportWaveRT; 55 | IMP_IDrmAudioStream; 56 | 57 | NTSTATUS Init 58 | ( 59 | _In_ PCMiniportWaveRT Miniport, 60 | _In_ PPORTWAVERTSTREAM Stream, 61 | _In_ ULONG Channel, 62 | _In_ BOOLEAN Capture, 63 | _In_ PKSDATAFORMAT DataFormat, 64 | _In_ GUID SignalProcessingMode 65 | ); 66 | 67 | // Friends 68 | friend class CMiniportWaveRT; 69 | protected: 70 | CMiniportWaveRT* m_pMiniport; 71 | ULONG m_ulPin; 72 | BOOLEAN m_bCapture; 73 | BOOLEAN m_bUnregisterStream; 74 | ULONG m_ulDmaBufferSize; 75 | KSSTATE m_KsState; 76 | ULONG m_ulDmaMovementRate; 77 | PWAVEFORMATEXTENSIBLE m_pWfExt; 78 | ULONG m_ulContentId; 79 | KSPIN_LOCK m_PositionSpinLock; 80 | UINT32 m_lastLinkPos; 81 | UINT64 m_lastLinearPos; 82 | 83 | }; 84 | typedef CMiniportWaveRTStream *PCMiniportWaveRTStream; 85 | #endif // _CSAUDIOACP3X_MINWAVERTSTREAM_H_ 86 | 87 | -------------------------------------------------------------------------------- /Source/Inc/NewDelete.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | NewDelete.h 8 | 9 | Abstract: 10 | 11 | Declaration of placement new and delete operators. 12 | --*/ 13 | #pragma once 14 | 15 | #ifdef _NEW_DELETE_OPERATORS_ 16 | 17 | /***************************************************************************** 18 | * Functions 19 | */ 20 | 21 | /***************************************************************************** 22 | * ::new() 23 | ***************************************************************************** 24 | * New function for creating objects with a specified allocation tag and 25 | * pool type 26 | */ 27 | PVOID operator new 28 | ( 29 | size_t iSize, 30 | POOL_TYPE poolType, 31 | ULONG tag 32 | ); 33 | 34 | 35 | /***************************************************************************** 36 | * ::new() 37 | ***************************************************************************** 38 | * New function for creating objects with a specified pool type. 39 | */ 40 | PVOID operator new 41 | ( 42 | size_t iSize, 43 | POOL_TYPE poolType 44 | ); 45 | 46 | 47 | /***************************************************************************** 48 | * ::delete() 49 | ***************************************************************************** 50 | * Delete with tag function. 51 | */ 52 | void __cdecl operator delete 53 | ( 54 | PVOID pVoid, 55 | ULONG tag 56 | ); 57 | 58 | 59 | /***************************************************************************** 60 | * ::delete() 61 | ***************************************************************************** 62 | * Sized Delete function. 63 | */ 64 | void __cdecl operator delete 65 | ( 66 | _Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid, 67 | _In_ size_t cbSize 68 | ); 69 | 70 | 71 | /***************************************************************************** 72 | * ::delete() 73 | ***************************************************************************** 74 | * Basic Delete function. 75 | */ 76 | void __cdecl operator delete 77 | ( 78 | PVOID pVoid 79 | ); 80 | 81 | 82 | /***************************************************************************** 83 | * ::delete() 84 | ***************************************************************************** 85 | * Sized Array Delete function. 86 | */ 87 | void __cdecl operator delete[] 88 | ( 89 | _Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid, 90 | _In_ size_t cbSize 91 | ); 92 | 93 | 94 | /***************************************************************************** 95 | * ::delete() 96 | ***************************************************************************** 97 | * Array Delete function. 98 | */ 99 | void __cdecl operator delete[] 100 | ( 101 | _Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid 102 | ); 103 | 104 | #endif//_NEW_DELETE_OPERATORS_ 105 | -------------------------------------------------------------------------------- /Source/Inc/basetopo.h: -------------------------------------------------------------------------------- 1 | 2 | /*++ 3 | 4 | Copyright (c) Microsoft Corporation All Rights Reserved 5 | 6 | Module Name: 7 | 8 | basetopo.h 9 | 10 | Abstract: 11 | 12 | Declaration of topology miniport. 13 | --*/ 14 | 15 | #ifndef _CSAUDIOSSTCATPT_BASETOPO_H_ 16 | #define _CSAUDIOSSTCATPT_BASETOPO_H_ 17 | 18 | //============================================================================= 19 | // Classes 20 | //============================================================================= 21 | 22 | /////////////////////////////////////////////////////////////////////////////// 23 | // CMiniportTopologyCsAudioSstCatPt 24 | // 25 | 26 | class CMiniportTopologyCsAudioSstCatPt 27 | { 28 | protected: 29 | PADAPTERCOMMON m_AdapterCommon; // Adapter common object. 30 | PPCFILTER_DESCRIPTOR m_FilterDescriptor; // Filter descriptor. 31 | PPORTEVENTS m_PortEvents; // Event interface. 32 | USHORT m_DeviceMaxChannels; // Max device channels. 33 | 34 | public: 35 | CMiniportTopologyCsAudioSstCatPt( 36 | _In_ PCFILTER_DESCRIPTOR *FilterDesc, 37 | _In_ USHORT DeviceMaxChannels 38 | ); 39 | 40 | ~CMiniportTopologyCsAudioSstCatPt(); 41 | 42 | NTSTATUS GetDescription 43 | ( 44 | _Out_ PPCFILTER_DESCRIPTOR * Description 45 | ); 46 | 47 | NTSTATUS DataRangeIntersection 48 | ( 49 | _In_ ULONG PinId, 50 | _In_ PKSDATARANGE ClientDataRange, 51 | _In_ PKSDATARANGE MyDataRange, 52 | _In_ ULONG OutputBufferLength, 53 | _Out_writes_bytes_to_opt_(OutputBufferLength, *ResultantFormatLength) 54 | PVOID ResultantFormat OPTIONAL, 55 | _Out_ PULONG ResultantFormatLength 56 | ); 57 | 58 | NTSTATUS Init 59 | ( 60 | _In_ PUNKNOWN UnknownAdapter, 61 | _In_ PPORTTOPOLOGY Port_ 62 | ); 63 | 64 | // PropertyHandlers. 65 | NTSTATUS PropertyHandlerGeneric 66 | ( 67 | _In_ PPCPROPERTY_REQUEST PropertyRequest 68 | ); 69 | 70 | NTSTATUS PropertyHandlerMuxSource 71 | ( 72 | _In_ PPCPROPERTY_REQUEST PropertyRequest 73 | ); 74 | 75 | NTSTATUS PropertyHandlerDevSpecific 76 | ( 77 | _In_ PPCPROPERTY_REQUEST PropertyRequest 78 | ); 79 | 80 | VOID AddEventToEventList 81 | ( 82 | _In_ PKSEVENT_ENTRY EventEntry 83 | ); 84 | 85 | VOID GenerateEventList 86 | ( 87 | _In_opt_ GUID *Set, 88 | _In_ ULONG EventId, 89 | _In_ BOOL PinEvent, 90 | _In_ ULONG PinId, 91 | _In_ BOOL NodeEvent, 92 | _In_ ULONG NodeId 93 | ); 94 | }; 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /Source/Utilities/resource.cpp: -------------------------------------------------------------------------------- 1 | #include "definitions.h" 2 | #include "hw.h" 3 | #include "resource.h" 4 | 5 | #define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */ 6 | 7 | /* Return the conflict entry if you can't request it */ 8 | static PRESOURCE __request_resource(PRESOURCE root, PRESOURCE newRes) 9 | { 10 | size_t start = newRes->start; 11 | size_t end = newRes->end; 12 | PRESOURCE tmp, * p; 13 | 14 | if (end < start) 15 | return root; 16 | if (start < root->start) 17 | return root; 18 | if (end > root->end) 19 | return root; 20 | p = &root->child; 21 | for (;;) { 22 | tmp = *p; 23 | if (!tmp || tmp->start > end) { 24 | newRes->sibling = tmp; 25 | *p = newRes; 26 | newRes->parent = root; 27 | return NULL; 28 | } 29 | p = &tmp->sibling; 30 | if (tmp->end < start) 31 | continue; 32 | return tmp; 33 | } 34 | } 35 | 36 | /** 37 | * __request_region - create a new busy resource region 38 | * @parent: parent resource descriptor 39 | * @start: resource start address 40 | * @n: resource region size 41 | * @name: reserving caller's ID string 42 | * @flags: IO resource flags 43 | */ 44 | PRESOURCE __request_region(PRESOURCE parent, 45 | size_t start, size_t n, int flags) 46 | { 47 | PRESOURCE res = (PRESOURCE)ExAllocatePoolZero(NonPagedPool, sizeof(_RESOURCE), CSAUDIOCATPTSST_POOLTAG); 48 | if (!res) 49 | return NULL; 50 | 51 | res->start = start; 52 | res->end = start + n - 1; 53 | res->flags = IORESOURCE_BUSY; 54 | res->flags |= flags; 55 | 56 | for (;;) { 57 | PRESOURCE conflict; 58 | 59 | conflict = __request_resource(parent, res); 60 | if (!conflict) 61 | break; 62 | if (conflict != parent) { 63 | parent = conflict; 64 | if (!(conflict->flags & IORESOURCE_BUSY)) 65 | continue; 66 | } 67 | /* Uhhuh, that didn't work out.. */ 68 | ExFreePoolWithTag(res, CSAUDIOCATPTSST_POOLTAG); 69 | res = NULL; 70 | break; 71 | } 72 | return res; 73 | } 74 | 75 | void __release_region(PRESOURCE parent, size_t start, 76 | size_t n) 77 | { 78 | PRESOURCE* p; 79 | size_t end; 80 | 81 | p = &parent->child; 82 | end = start + n - 1; 83 | 84 | for (;;) { 85 | PRESOURCE res = *p; 86 | 87 | if (!res) 88 | break; 89 | if (res->start <= start && res->end >= end) { 90 | if (!(res->flags & IORESOURCE_BUSY)) { 91 | p = &res->child; 92 | continue; 93 | } 94 | if (res->start != start || res->end != end) 95 | break; 96 | *p = res->sibling; 97 | ExFreePoolWithTag(res, CSAUDIOCATPTSST_POOLTAG); 98 | return; 99 | } 100 | p = &res->sibling; 101 | } 102 | 103 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "Trying to free nonexistent resource " 104 | "<%016llx-%016llx>\n", (unsigned long long)start, 105 | (unsigned long long)end); 106 | } 107 | 108 | NTSTATUS release_resource(PRESOURCE old) 109 | { 110 | PRESOURCE tmp, * p; 111 | 112 | p = &old->parent->child; 113 | for (;;) { 114 | tmp = *p; 115 | if (!tmp) 116 | break; 117 | if (tmp == old) { 118 | *p = tmp->sibling; 119 | old->parent = NULL; 120 | return STATUS_SUCCESS; 121 | } 122 | p = &tmp->sibling; 123 | } 124 | return STATUS_INVALID_PARAMETER; 125 | } -------------------------------------------------------------------------------- /Source/Filters/micjacktopo.cpp: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | usbhsmictopo.cpp 8 | 9 | Abstract: 10 | 11 | Implementation of topology miniport for the mic (external: headphone). 12 | 13 | --*/ 14 | #pragma warning (disable : 4127) 15 | 16 | #include "definitions.h" 17 | #include "endpoints.h" 18 | #include "mintopo.h" 19 | #include "micjacktopo.h" 20 | #include "micjacktoptable.h" 21 | 22 | //============================================================================= 23 | #pragma code_seg("PAGE") 24 | NTSTATUS 25 | PropertyHandler_MicJackTopoFilter 26 | ( 27 | _In_ PPCPROPERTY_REQUEST PropertyRequest 28 | ) 29 | /*++ 30 | 31 | Routine Description: 32 | 33 | Redirects property request to miniport object 34 | 35 | Arguments: 36 | 37 | PropertyRequest - 38 | 39 | Return Value: 40 | 41 | NT status code. 42 | 43 | --*/ 44 | { 45 | PAGED_CODE(); 46 | 47 | ASSERT(PropertyRequest); 48 | 49 | DPF_ENTER(("[PropertyHandler_MicJackTopoFilter]")); 50 | 51 | // PropertryRequest structure is filled by portcls. 52 | // MajorTarget is a pointer to miniport object for miniports. 53 | // 54 | NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; 55 | PCMiniportTopology pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget; 56 | 57 | if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Jack)) 58 | { 59 | switch (PropertyRequest->PropertyItem->Id) 60 | { 61 | case KSPROPERTY_JACK_DESCRIPTION: 62 | ntStatus = pMiniport->PropertyHandlerJackDescription( 63 | PropertyRequest, 64 | ARRAYSIZE(MicJackDescriptions), 65 | MicJackDescriptions); 66 | break; 67 | 68 | case KSPROPERTY_JACK_DESCRIPTION2: 69 | ntStatus = pMiniport->PropertyHandlerJackDescription2( 70 | PropertyRequest, 71 | ARRAYSIZE(MicJackDescriptions), 72 | MicJackDescriptions, 73 | 0 // jack capabilities 74 | ); 75 | break; 76 | } 77 | } 78 | 79 | return ntStatus; 80 | } // PropertyHandler_MicJackTopoFilter 81 | 82 | //============================================================================= 83 | NTSTATUS 84 | PropertyHandler_MicJackTopology 85 | ( 86 | _In_ PPCPROPERTY_REQUEST PropertyRequest 87 | ) 88 | /*++ 89 | 90 | Routine Description: 91 | 92 | Redirects property request to miniport object 93 | 94 | Arguments: 95 | 96 | PropertyRequest - 97 | 98 | Return Value: 99 | 100 | NT status code. 101 | 102 | --*/ 103 | { 104 | PAGED_CODE(); 105 | 106 | ASSERT(PropertyRequest); 107 | 108 | DPF_ENTER(("[PropertyHandler_MicJackTopology]")); 109 | 110 | // PropertryRequest structure is filled by portcls. 111 | // MajorTarget is a pointer to miniport object for miniports. 112 | // 113 | PCMiniportTopology pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget; 114 | 115 | return pMiniport->PropertyHandlerGeneric(PropertyRequest); 116 | } // PropertyHandler_HeadphoneTopology 117 | 118 | #pragma code_seg() 119 | -------------------------------------------------------------------------------- /Source/Filters/speakertopo.cpp: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | speakertopo.cpp 8 | 9 | Abstract: 10 | 11 | Implementation of topology miniport for the speaker (internal). 12 | --*/ 13 | 14 | #pragma warning (disable : 4127) 15 | 16 | #include "definitions.h" 17 | #include "endpoints.h" 18 | #include "mintopo.h" 19 | #include "speakertopo.h" 20 | #include "speakertoptable.h" 21 | 22 | 23 | #pragma code_seg("PAGE") 24 | //============================================================================= 25 | NTSTATUS 26 | PropertyHandler_SpeakerTopoFilter 27 | ( 28 | _In_ PPCPROPERTY_REQUEST PropertyRequest 29 | ) 30 | /*++ 31 | 32 | Routine Description: 33 | 34 | Redirects property request to miniport object 35 | 36 | Arguments: 37 | 38 | PropertyRequest - 39 | 40 | Return Value: 41 | 42 | NT status code. 43 | 44 | --*/ 45 | { 46 | PAGED_CODE(); 47 | 48 | ASSERT(PropertyRequest); 49 | 50 | DPF_ENTER(("[PropertyHandler_SpeakerTopoFilter]")); 51 | 52 | // PropertryRequest structure is filled by portcls. 53 | // MajorTarget is a pointer to miniport object for miniports. 54 | // 55 | NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST; 56 | PCMiniportTopology pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget; 57 | 58 | if (IsEqualGUIDAligned(*PropertyRequest->PropertyItem->Set, KSPROPSETID_Jack)) 59 | { 60 | if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION) 61 | { 62 | ntStatus = pMiniport->PropertyHandlerJackDescription( 63 | PropertyRequest, 64 | ARRAYSIZE(SpeakerJackDescriptions), 65 | SpeakerJackDescriptions 66 | ); 67 | } 68 | else if (PropertyRequest->PropertyItem->Id == KSPROPERTY_JACK_DESCRIPTION2) 69 | { 70 | ntStatus = pMiniport->PropertyHandlerJackDescription2( 71 | PropertyRequest, 72 | ARRAYSIZE(SpeakerJackDescriptions), 73 | SpeakerJackDescriptions, 74 | 0 // jack capabilities 75 | ); 76 | } 77 | } 78 | 79 | return ntStatus; 80 | } // PropertyHandler_SpeakerTopoFilter 81 | 82 | //============================================================================= 83 | NTSTATUS 84 | PropertyHandler_SpeakerTopology 85 | ( 86 | _In_ PPCPROPERTY_REQUEST PropertyRequest 87 | ) 88 | /*++ 89 | 90 | Routine Description: 91 | 92 | Redirects property request to miniport object 93 | 94 | Arguments: 95 | 96 | PropertyRequest - 97 | 98 | Return Value: 99 | 100 | NT status code. 101 | 102 | --*/ 103 | { 104 | PAGED_CODE(); 105 | 106 | ASSERT(PropertyRequest); 107 | 108 | DPF_ENTER(("[PropertyHandler_SpeakerTopology]")); 109 | 110 | // PropertryRequest structure is filled by portcls. 111 | // MajorTarget is a pointer to miniport object for miniports. 112 | // 113 | PCMiniportTopology pMiniport = (PCMiniportTopology)PropertyRequest->MajorTarget; 114 | 115 | return pMiniport->PropertyHandlerGeneric(PropertyRequest); 116 | } // PropertyHandler_SpeakerTopology 117 | 118 | #pragma code_seg() 119 | -------------------------------------------------------------------------------- /Source/Utilities/Utilities.vcxproj.Filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;* 6 | {CDBBEDA3-98E9-4C7A-BDB1-25EC47D0B087} 7 | 8 | 9 | h;hpp;hxx;hm;inl;inc;xsd 10 | {FA3DF57E-BA19-4783-831B-CF9D4D594F70} 11 | 12 | 13 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml 14 | {CB830E4F-01DA-4D35-9789-E7DB0D02A79C} 15 | 16 | 17 | inf;inv;inx;mof;mc; 18 | {49F92783-3B39-4D0C-A153-8C346F754749} 19 | 20 | 21 | 22 | 23 | Source Files 24 | 25 | 26 | Source Files 27 | 28 | 29 | Source Files 30 | 31 | 32 | Source Files 33 | 34 | 35 | Source Files 36 | 37 | 38 | Source Files 39 | 40 | 41 | Source Files 42 | 43 | 44 | Source Files 45 | 46 | 47 | Source Files 48 | 49 | 50 | Source Files 51 | 52 | 53 | Source Files 54 | 55 | 56 | Source Files 57 | 58 | 59 | 60 | 61 | Header Files 62 | 63 | 64 | Header Files 65 | 66 | 67 | Header Files 68 | 69 | 70 | Header Files 71 | 72 | 73 | Header Files 74 | 75 | 76 | Header Files 77 | 78 | 79 | Header Files 80 | 81 | 82 | Header Files 83 | 84 | 85 | Header Files 86 | 87 | 88 | -------------------------------------------------------------------------------- /Source/Inc/endpoints.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | endpoints.h 8 | 9 | Abstract: 10 | 11 | Node and Pin numbers and other common definitions for simple audio sample. 12 | --*/ 13 | 14 | #ifndef _CSAUDIOSSTCATPT_ENDPOINTS_H_ 15 | #define _CSAUDIOSSTCATPT_ENDPOINTS_H_ 16 | 17 | // Name Guid 18 | // {0104947F-82AE-4291-A6F3-5E2DE1AD7DC2} 19 | #define STATIC_NAME_SIMPLE_AUDIO_SAMPLE\ 20 | 0x104947f, 0x82ae, 0x4291, 0xa6, 0xf3, 0x5e, 0x2d, 0xe1, 0xad, 0x7d, 0xc2 21 | DEFINE_GUIDSTRUCT("0104947F-82AE-4291-A6F3-5E2DE1AD7DC2", NAME_SIMPLE_AUDIO_SAMPLE); 22 | #define NAME_SIMPLE_AUDIO_SAMPLE DEFINE_GUIDNAMED(NAME_SIMPLE_AUDIO_SAMPLE) 23 | 24 | //---------------------------------------------------- 25 | // New defines for the render endpoints. 26 | //---------------------------------------------------- 27 | 28 | // Default pin instances. 29 | #define MAX_INPUT_SYSTEM_STREAMS 1 30 | 31 | // Wave pins - no mix, no offload 32 | enum 33 | { 34 | KSPIN_WAVE_RENDER3_SINK_SYSTEM = 0, 35 | KSPIN_WAVE_RENDER3_SOURCE 36 | }; 37 | 38 | // Wave pins - offloading is NOT supported. 39 | enum 40 | { 41 | KSPIN_WAVE_RENDER2_SINK_SYSTEM = 0, 42 | KSPIN_WAVE_RENDER2_SINK_LOOPBACK, 43 | KSPIN_WAVE_RENDER2_SOURCE 44 | }; 45 | 46 | // Wave Topology nodes - offloading is NOT supported. 47 | enum 48 | { 49 | KSNODE_WAVE_SUM = 0, 50 | KSNODE_WAVE_VOLUME, 51 | KSNODE_WAVE_MUTE, 52 | KSNODE_WAVE_PEAKMETER 53 | }; 54 | 55 | // Topology pins. 56 | enum 57 | { 58 | KSPIN_TOPO_WAVEOUT_SOURCE = 0, 59 | KSPIN_TOPO_LINEOUT_DEST, 60 | }; 61 | 62 | // Topology nodes. 63 | enum 64 | { 65 | KSNODE_TOPO_WAVEOUT_VOLUME = 0, 66 | KSNODE_TOPO_WAVEOUT_MUTE, 67 | KSNODE_TOPO_WAVEOUT_PEAKMETER 68 | }; 69 | 70 | //---------------------------------------------------- 71 | // New defines for the capture endpoints. 72 | //---------------------------------------------------- 73 | 74 | // Default pin instances. 75 | #define MAX_INPUT_STREAMS 1 // Number of capture streams. 76 | 77 | // Wave pins 78 | enum 79 | { 80 | KSPIN_WAVE_BRIDGE = 0, 81 | KSPIN_WAVEIN_HOST, 82 | }; 83 | 84 | // Wave Topology nodes. 85 | enum 86 | { 87 | KSNODE_WAVE_ADC = 0 88 | }; 89 | 90 | // Wave Topology nodes. 91 | enum 92 | { 93 | KSNODE_WAVE_DAC = 0 94 | }; 95 | 96 | // topology pins. 97 | enum 98 | { 99 | KSPIN_TOPO_MIC_ELEMENTS, 100 | KSPIN_TOPO_BRIDGE 101 | }; 102 | 103 | // topology nodes. 104 | enum 105 | { 106 | KSNODE_TOPO_VOLUME, 107 | KSNODE_TOPO_MUTE, 108 | KSNODE_TOPO_PEAKMETER 109 | }; 110 | 111 | // data format attribute range definitions. 112 | static 113 | KSATTRIBUTE PinDataRangeSignalProcessingModeAttribute = 114 | { 115 | sizeof(KSATTRIBUTE), 116 | 0, 117 | STATICGUIDOF(KSATTRIBUTEID_AUDIOSIGNALPROCESSING_MODE), 118 | }; 119 | 120 | static 121 | PKSATTRIBUTE PinDataRangeAttributes[] = 122 | { 123 | &PinDataRangeSignalProcessingModeAttribute, 124 | }; 125 | 126 | static 127 | KSATTRIBUTE_LIST PinDataRangeAttributeList = 128 | { 129 | ARRAYSIZE(PinDataRangeAttributes), 130 | PinDataRangeAttributes, 131 | }; 132 | 133 | #endif // _CSAUDIOSSTCATPT_ENDPOINTS_H_ 134 | -------------------------------------------------------------------------------- /Source/Filters/Filters.vcxproj.Filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;* 6 | {75C3E63D-04EA-4EB3-B9F1-505497C51F71} 7 | 8 | 9 | h;hpp;hxx;hm;inl;inc;xsd 10 | {5E8F8D4C-2886-4109-9E78-CE5EA6DB4AC4} 11 | 12 | 13 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml 14 | {75D3016A-4ED8-4FAF-9817-394BE1112534} 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | 29 | 30 | Header Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | Header Files 43 | 44 | 45 | Header Files 46 | 47 | 48 | Header Files 49 | 50 | 51 | Header Files 52 | 53 | 54 | Header Files 55 | 56 | 57 | Header Files 58 | 59 | 60 | Header Files 61 | 62 | 63 | Header Files 64 | 65 | 66 | Header Files 67 | 68 | 69 | Header Files 70 | 71 | 72 | Header Files 73 | 74 | 75 | Header Files 76 | 77 | 78 | Header Files 79 | 80 | 81 | Header Files 82 | 83 | 84 | Header Files 85 | 86 | 87 | Header Files 88 | 89 | 90 | Header Files 91 | 92 | 93 | Header Files 94 | 95 | 96 | Header Files 97 | 98 | 99 | -------------------------------------------------------------------------------- /Source/Main/NewDelete.cpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * NewDelete.cpp - CPP placement new and delete operators implementation 3 | ***************************************************************************** 4 | * Copyright (c) Microsoft Corporation All Rights Reserved 5 | * 6 | * Module Name: 7 | * 8 | * NewDelete.cpp 9 | * 10 | * Abstract: 11 | * 12 | * Definition of placement new and delete operators. 13 | * 14 | */ 15 | 16 | #ifdef _NEW_DELETE_OPERATORS_ 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #include 20 | } 21 | #else 22 | #include 23 | #endif 24 | 25 | #include "newDelete.h" 26 | #include "definitions.h" 27 | 28 | #pragma code_seg() 29 | /***************************************************************************** 30 | * Functions 31 | */ 32 | 33 | /***************************************************************************** 34 | * ::new() 35 | ***************************************************************************** 36 | * New function for creating objects with a specified allocation tag. 37 | */ 38 | PVOID operator new 39 | ( 40 | size_t iSize, 41 | POOL_TYPE poolType, 42 | ULONG tag 43 | ) 44 | { 45 | PVOID result = ExAllocatePoolZero(poolType, iSize, tag); 46 | 47 | return result; 48 | } 49 | 50 | 51 | /***************************************************************************** 52 | * ::new() 53 | ***************************************************************************** 54 | * New function for creating objects with a specified allocation tag. 55 | */ 56 | PVOID operator new 57 | ( 58 | size_t iSize, 59 | POOL_TYPE poolType 60 | ) 61 | { 62 | PVOID result = ExAllocatePoolZero(poolType, iSize, CSAUDIOCATPTSST_POOLTAG); 63 | 64 | return result; 65 | } 66 | 67 | 68 | /***************************************************************************** 69 | * ::delete() 70 | ***************************************************************************** 71 | * Delete with tag function. 72 | */ 73 | void __cdecl operator delete 74 | ( 75 | PVOID pVoid, 76 | ULONG tag 77 | ) 78 | { 79 | if (pVoid) 80 | { 81 | ExFreePoolWithTag(pVoid, tag); 82 | } 83 | } 84 | 85 | 86 | /***************************************************************************** 87 | * ::delete() 88 | ***************************************************************************** 89 | * Sized Delete function. 90 | */ 91 | void __cdecl operator delete 92 | ( 93 | _Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid, 94 | _In_ size_t cbSize 95 | ) 96 | { 97 | UNREFERENCED_PARAMETER(cbSize); 98 | 99 | if (pVoid) 100 | { 101 | ExFreePoolWithTag(pVoid, CSAUDIOCATPTSST_POOLTAG); 102 | } 103 | } 104 | 105 | 106 | /***************************************************************************** 107 | * ::delete() 108 | ***************************************************************************** 109 | * Sized Array Delete function. 110 | */ 111 | void __cdecl operator delete[] 112 | ( 113 | _Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid, 114 | _In_ size_t cbSize 115 | ) 116 | { 117 | UNREFERENCED_PARAMETER(cbSize); 118 | 119 | if (pVoid) 120 | { 121 | ExFreePoolWithTag(pVoid, CSAUDIOCATPTSST_POOLTAG); 122 | } 123 | } 124 | 125 | 126 | /***************************************************************************** 127 | * ::delete() 128 | ***************************************************************************** 129 | * Array Delete function. 130 | */ 131 | void __cdecl operator delete[] 132 | ( 133 | _Pre_maybenull_ __drv_freesMem(Mem) PVOID pVoid 134 | ) 135 | { 136 | if (pVoid) 137 | { 138 | ExFreePoolWithTag(pVoid, CSAUDIOCATPTSST_POOLTAG); 139 | } 140 | } 141 | #endif//_NEW_DELETE_OPERATORS_ 142 | -------------------------------------------------------------------------------- /Source/Inc/kshelper.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | kshelper.h 8 | 9 | Abstract: 10 | 11 | Helper functions for simple audio sample 12 | --*/ 13 | #ifndef _CSAUDIOSSTCATPT_KSHELPER_H_ 14 | #define _CSAUDIOSSTCATPT_KSHELPER_H_ 15 | 16 | #include 17 | #include 18 | 19 | PWAVEFORMATEX 20 | GetWaveFormatEx 21 | ( 22 | _In_ PKSDATAFORMAT pDataFormat 23 | ); 24 | 25 | NTSTATUS 26 | ValidatePropertyParams 27 | ( 28 | _In_ PPCPROPERTY_REQUEST PropertyRequest, 29 | _In_ ULONG cbValueSize, 30 | _In_ ULONG cbInstanceSize = 0 31 | ); 32 | 33 | NTSTATUS 34 | PropertyHandler_BasicSupport 35 | ( 36 | _In_ PPCPROPERTY_REQUEST PropertyRequest, 37 | _In_ ULONG Flags, 38 | _In_ DWORD PropTypeSetId 39 | ); 40 | 41 | NTSTATUS 42 | PropertyHandler_BasicSupportPeakMeter2 43 | ( 44 | _In_ PPCPROPERTY_REQUEST PropertyRequest, 45 | _In_ ULONG MaxChannels 46 | ); 47 | 48 | NTSTATUS 49 | PropertyHandler_CpuResources 50 | ( 51 | _In_ PPCPROPERTY_REQUEST PropertyRequest 52 | ); 53 | 54 | NTSTATUS 55 | PropertyHandler_PeakMeter2 56 | ( 57 | _In_ PADAPTERCOMMON AdapterCommon, 58 | _In_ PPCPROPERTY_REQUEST PropertyRequest, 59 | _In_ ULONG MaxChannels 60 | ); 61 | 62 | //============================================================================= 63 | // Property helpers 64 | //============================================================================= 65 | 66 | NTSTATUS 67 | CsAudioSstCatPtPropertyDispatch 68 | ( 69 | _In_ PPCPROPERTY_REQUEST PropertyRequest 70 | ); 71 | 72 | // Use this structure to define property items with extra data allowing easier 73 | // definition of separate get, set, and support handlers dispatched through 74 | // CsAudioSstCatPtPropertyDispatch. 75 | typedef struct 76 | { 77 | PCPROPERTY_ITEM PropertyItem; // Standard PCPROPERTY_ITEM 78 | ULONG MinProperty; // Minimum size of the property instance data 79 | ULONG MinData; // Minimum size of the property value 80 | PCPFNPROPERTY_HANDLER GetHandler; // Property get handler (NULL if GET not supported) 81 | PCPFNPROPERTY_HANDLER SetHandler; // Property set handler (NULL if SET not supported) 82 | PCPFNPROPERTY_HANDLER SupportHandler; // Property support handler (NULL for common handler) 83 | VOID *ContextData; // Optional context information for the handler, NULL for unused 84 | ULONG ContextDataSize; // Size of the data held at ContextData, 0 for unused 85 | } CSAUDIOSSTCATPT_PROPERTY_ITEM; 86 | 87 | // The following macros facilitate adding property handlers to a class, allowing 88 | // easier declaration and definition of a "thunk" routine that directly handles 89 | // the property request and calls into a class instance method. Note that as 90 | // written, the thunk routine assumes PAGED_CODE. 91 | #define DECLARE_CLASSPROPERTYHANDLER(theClass, theMethod) \ 92 | NTSTATUS theClass##_##theMethod \ 93 | ( \ 94 | _In_ PPCPROPERTY_REQUEST PropertyRequest \ 95 | ); 96 | 97 | #define DECLARE_PROPERTYHANDLER(theMethod) \ 98 | NTSTATUS theMethod \ 99 | ( \ 100 | _In_ PPCPROPERTY_REQUEST PropertyRequest \ 101 | ); 102 | 103 | #define DEFINE_CLASSPROPERTYHANDLER(theClass, theMethod) \ 104 | NTSTATUS theClass##_##theMethod \ 105 | ( \ 106 | _In_ PPCPROPERTY_REQUEST PropertyRequest \ 107 | ) \ 108 | { \ 109 | NTSTATUS status; \ 110 | \ 111 | PAGED_CODE(); \ 112 | \ 113 | theClass* p = reinterpret_cast(PropertyRequest->MajorTarget); \ 114 | \ 115 | p->AddRef(); \ 116 | status = p->theMethod(PropertyRequest); \ 117 | p->Release(); \ 118 | \ 119 | return status; \ 120 | } \ 121 | NTSTATUS theClass::theMethod \ 122 | ( \ 123 | _In_ PPCPROPERTY_REQUEST PropertyRequest \ 124 | ) 125 | 126 | 127 | 128 | 129 | #endif // _CSAUDIOSSTCATPT_KSHELPER_H_ 130 | -------------------------------------------------------------------------------- /Source/Filters/speakertoptable.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | speakertoptable.h 8 | 9 | Abstract: 10 | 11 | Declaration of topology tables. 12 | --*/ 13 | 14 | #ifndef _CSAUDIOSSTCATPT_SPEAKERTOPTABLE_H_ 15 | #define _CSAUDIOSSTCATPT_SPEAKERTOPTABLE_H_ 16 | 17 | //============================================================================= 18 | static 19 | KSDATARANGE SpeakerTopoPinDataRangesBridge[] = 20 | { 21 | { 22 | sizeof(KSDATARANGE), 23 | 0, 24 | 0, 25 | 0, 26 | STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), 27 | STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG), 28 | STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE) 29 | } 30 | }; 31 | 32 | //============================================================================= 33 | static 34 | PKSDATARANGE SpeakerTopoPinDataRangePointersBridge[] = 35 | { 36 | &SpeakerTopoPinDataRangesBridge[0] 37 | }; 38 | 39 | //============================================================================= 40 | static 41 | PCPIN_DESCRIPTOR SpeakerTopoMiniportPins[] = 42 | { 43 | // KSPIN_TOPO_WAVEOUT_SOURCE 44 | { 45 | 0, 46 | 0, 47 | 0, // InstanceCount 48 | NULL, // AutomationTable 49 | { // KsPinDescriptor 50 | 0, // InterfacesCount 51 | NULL, // Interfaces 52 | 0, // MediumsCount 53 | NULL, // Mediums 54 | SIZEOF_ARRAY(SpeakerTopoPinDataRangePointersBridge),// DataRangesCount 55 | SpeakerTopoPinDataRangePointersBridge, // DataRanges 56 | KSPIN_DATAFLOW_IN, // DataFlow 57 | KSPIN_COMMUNICATION_NONE, // Communication 58 | &KSCATEGORY_AUDIO, // Category 59 | NULL, // Name 60 | 0 // Reserved 61 | } 62 | }, 63 | // KSPIN_TOPO_LINEOUT_DEST 64 | { 65 | 0, 66 | 0, 67 | 0, // InstanceCount 68 | NULL, // AutomationTable 69 | { // KsPinDescriptor 70 | 0, // InterfacesCount 71 | NULL, // Interfaces 72 | 0, // MediumsCount 73 | NULL, // Mediums 74 | SIZEOF_ARRAY(SpeakerTopoPinDataRangePointersBridge),// DataRangesCount 75 | SpeakerTopoPinDataRangePointersBridge, // DataRanges 76 | KSPIN_DATAFLOW_OUT, // DataFlow 77 | KSPIN_COMMUNICATION_NONE, // Communication 78 | &KSNODETYPE_SPEAKER, // Category 79 | NULL, // Name 80 | 0 // Reserved 81 | } 82 | } 83 | }; 84 | 85 | //============================================================================= 86 | static 87 | KSJACK_DESCRIPTION SpeakerJackDescBridge = 88 | { 89 | KSAUDIO_SPEAKER_STEREO, 90 | 0xB3C98C, // Color spec for green 91 | eConnTypeAtapiInternal, 92 | eGeoLocFront, 93 | eGenLocInternal, 94 | ePortConnIntegratedDevice, 95 | TRUE 96 | }; 97 | 98 | // Only return a KSJACK_DESCRIPTION for the physical bridge pin. 99 | static 100 | PKSJACK_DESCRIPTION SpeakerJackDescriptions[] = 101 | { 102 | NULL, 103 | &SpeakerJackDescBridge 104 | }; 105 | 106 | static 107 | PCCONNECTION_DESCRIPTOR SpeakerTopoMiniportConnections[] = 108 | { 109 | {PCFILTER_NODE, KSPIN_TOPO_WAVEOUT_SOURCE, PCFILTER_NODE, KSPIN_TOPO_LINEOUT_DEST} //no volume controls 110 | }; 111 | 112 | //============================================================================= 113 | static 114 | PCPROPERTY_ITEM PropertiesSpeakerTopoFilter[] = 115 | { 116 | { 117 | &KSPROPSETID_Jack, 118 | KSPROPERTY_JACK_DESCRIPTION, 119 | KSPROPERTY_TYPE_GET | 120 | KSPROPERTY_TYPE_BASICSUPPORT, 121 | PropertyHandler_SpeakerTopoFilter 122 | }, 123 | { 124 | &KSPROPSETID_Jack, 125 | KSPROPERTY_JACK_DESCRIPTION2, 126 | KSPROPERTY_TYPE_GET | 127 | KSPROPERTY_TYPE_BASICSUPPORT, 128 | PropertyHandler_SpeakerTopoFilter 129 | } 130 | }; 131 | 132 | DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerTopoFilter, PropertiesSpeakerTopoFilter); 133 | 134 | //============================================================================= 135 | static 136 | PCFILTER_DESCRIPTOR SpeakerTopoMiniportFilterDescriptor = 137 | { 138 | 0, // Version 139 | &AutomationSpeakerTopoFilter, // AutomationTable 140 | sizeof(PCPIN_DESCRIPTOR), // PinSize 141 | SIZEOF_ARRAY(SpeakerTopoMiniportPins), // PinCount 142 | SpeakerTopoMiniportPins, // Pins 143 | sizeof(PCNODE_DESCRIPTOR), // NodeSize 144 | 0, // NodeCount 145 | NULL, // Nodes 146 | SIZEOF_ARRAY(SpeakerTopoMiniportConnections), // ConnectionCount 147 | SpeakerTopoMiniportConnections, // Connections 148 | 0, // CategoryCount 149 | NULL // Categories 150 | }; 151 | 152 | #endif // _CSAUDIOSSTCATPT_SPEAKERTOPTABLE_H_ 153 | -------------------------------------------------------------------------------- /Source/Filters/micjacktoptable.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | usbhsmictopotable.h 8 | 9 | Abstract: 10 | 11 | Declaration of topology table for the USB Headset mic (external) 12 | 13 | --*/ 14 | 15 | #ifndef _CSAUDIOSSTCATPT_MICJACKTOPTABLE_H_ 16 | #define _CSAUDIOSSTCATPT_MICJACKTOPTABLE_H_ 17 | 18 | //============================================================================= 19 | static 20 | KSDATARANGE MicJackTopoPinDataRangesBridge[] = 21 | { 22 | { 23 | sizeof(KSDATARANGE), 24 | 0, 25 | 0, 26 | 0, 27 | STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), 28 | STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG), 29 | STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE) 30 | } 31 | }; 32 | 33 | //============================================================================= 34 | static 35 | PKSDATARANGE MicJackTopoPinDataRangePointersBridge[] = 36 | { 37 | &MicJackTopoPinDataRangesBridge[0] 38 | }; 39 | 40 | //============================================================================= 41 | static 42 | PCPIN_DESCRIPTOR MicJackTopoMiniportPins[] = 43 | { 44 | // KSPIN_TOPO_MIC_ELEMENTS 45 | { 46 | 0, 47 | 0, 48 | 0, // InstanceCount 49 | NULL, // AutomationTable 50 | { // KsPinDescriptor 51 | 0, // InterfacesCount 52 | NULL, // Interfaces 53 | 0, // MediumsCount 54 | NULL, // Mediums 55 | SIZEOF_ARRAY(MicJackTopoPinDataRangePointersBridge),// DataRangesCount 56 | MicJackTopoPinDataRangePointersBridge, // DataRanges 57 | KSPIN_DATAFLOW_IN, // DataFlow 58 | KSPIN_COMMUNICATION_NONE, // Communication 59 | &KSNODETYPE_MICROPHONE, // Category 60 | NULL, // Name 61 | 0 // Reserved 62 | } 63 | }, 64 | 65 | // KSPIN_TOPO_BRIDGE 66 | { 67 | 0, 68 | 0, 69 | 0, // InstanceCount 70 | NULL, // AutomationTable 71 | { // KsPinDescriptor 72 | 0, // InterfacesCount 73 | NULL, // Interfaces 74 | 0, // MediumsCount 75 | NULL, // Mediums 76 | SIZEOF_ARRAY(MicJackTopoPinDataRangePointersBridge),// DataRangesCount 77 | MicJackTopoPinDataRangePointersBridge, // DataRanges 78 | KSPIN_DATAFLOW_OUT, // DataFlow 79 | KSPIN_COMMUNICATION_NONE, // Communication 80 | &KSCATEGORY_AUDIO, // Category 81 | NULL, // Name 82 | 0 // Reserved 83 | } 84 | } 85 | }; 86 | 87 | //============================================================================= 88 | static 89 | KSJACK_DESCRIPTION MicJackDesc = 90 | { 91 | KSAUDIO_SPEAKER_MONO, 92 | JACKDESC_RGB(0, 0, 0), 93 | eConnType3Point5mm, 94 | eGeoLocRight, 95 | eGenLocPrimaryBox, 96 | ePortConnJack, 97 | TRUE // NOTE: For convenience, wired headset jacks will be "unplugged" at boot. 98 | }; 99 | 100 | //============================================================================= 101 | // Only return a KSJACK_DESCRIPTION for the physical bridge pin. 102 | static 103 | PKSJACK_DESCRIPTION MicJackDescriptions[] = 104 | { 105 | &MicJackDesc, 106 | NULL 107 | }; 108 | 109 | //============================================================================= 110 | static 111 | PCCONNECTION_DESCRIPTOR MicJackMiniportConnections[] = 112 | { 113 | // FromNode, FromPin, ToNode, ToPin 114 | { PCFILTER_NODE, KSPIN_TOPO_MIC_ELEMENTS, PCFILTER_NODE, KSPIN_TOPO_BRIDGE } 115 | }; 116 | 117 | 118 | //============================================================================= 119 | static 120 | PCPROPERTY_ITEM MicJackPropertiesTopoFilter[] = 121 | { 122 | { 123 | &KSPROPSETID_Jack, 124 | KSPROPERTY_JACK_DESCRIPTION, 125 | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, 126 | PropertyHandler_MicJackTopoFilter 127 | }, 128 | { 129 | &KSPROPSETID_Jack, 130 | KSPROPERTY_JACK_DESCRIPTION2, 131 | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, 132 | PropertyHandler_MicJackTopoFilter 133 | } 134 | }; 135 | 136 | 137 | DEFINE_PCAUTOMATION_TABLE_PROP(AutomationMicJackTopoFilter, 138 | MicJackPropertiesTopoFilter); 139 | 140 | 141 | //============================================================================= 142 | static 143 | PCFILTER_DESCRIPTOR MicJackTopoMiniportFilterDescriptor = 144 | { 145 | 0, // Version 146 | &AutomationMicJackTopoFilter, // AutomationTable 147 | sizeof(PCPIN_DESCRIPTOR), // PinSize 148 | SIZEOF_ARRAY(MicJackTopoMiniportPins), // PinCount 149 | MicJackTopoMiniportPins, // Pins 150 | sizeof(PCNODE_DESCRIPTOR), // NodeSize 151 | 0, // NodeCount 152 | NULL, // Nodes 153 | SIZEOF_ARRAY(MicJackMiniportConnections),// ConnectionCount 154 | MicJackMiniportConnections, // Connections 155 | 0, // CategoryCount 156 | NULL // Categories 157 | }; 158 | 159 | #endif // _CSAUDIOSSTCATPT_MICJACKTOPTABLE_H_ 160 | -------------------------------------------------------------------------------- /Source/Filters/minipairs.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | minipairs.h 8 | 9 | Abstract: 10 | 11 | Local audio endpoint filter definitions. 12 | --*/ 13 | 14 | #ifndef _CSAUDIOSSTCATPT_MINIPAIRS_H_ 15 | #define _CSAUDIOSSTCATPT_MINIPAIRS_H_ 16 | 17 | #include "speakertopo.h" 18 | #include "speakertoptable.h" 19 | #include "speakerwavtable.h" 20 | 21 | #include "micjacktopo.h" 22 | #include "micjacktoptable.h" 23 | #include "micarraywavtable.h" 24 | 25 | 26 | NTSTATUS 27 | CreateMiniportWaveRTCsAudioSstCatPt 28 | ( 29 | _Out_ PUNKNOWN *, 30 | _In_ REFCLSID, 31 | _In_opt_ PUNKNOWN, 32 | _In_ POOL_TYPE, 33 | _In_ PUNKNOWN, 34 | _In_opt_ PVOID, 35 | _In_ PENDPOINT_MINIPAIR 36 | ); 37 | 38 | NTSTATUS 39 | CreateMiniportTopologyCsAudioSstCatPt 40 | ( 41 | _Out_ PUNKNOWN *, 42 | _In_ REFCLSID, 43 | _In_opt_ PUNKNOWN, 44 | _In_ POOL_TYPE, 45 | _In_ PUNKNOWN, 46 | _In_opt_ PVOID, 47 | _In_ PENDPOINT_MINIPAIR 48 | ); 49 | 50 | // 51 | // Render miniports. 52 | // 53 | 54 | /********************************************************************* 55 | * Topology/Wave bridge connection for speaker (internal) * 56 | * * 57 | * +------+ +------+ * 58 | * | Wave | | Topo | * 59 | * | | | | * 60 | * System --->|0 1|--------------->|0 1|---> Line Out * 61 | * | | | | * 62 | * +------+ +------+ * 63 | *********************************************************************/ 64 | static 65 | PHYSICALCONNECTIONTABLE SpeakerTopologyPhysicalConnections[] = 66 | { 67 | { 68 | KSPIN_TOPO_WAVEOUT_SOURCE, // TopologyIn 69 | KSPIN_WAVE_RENDER3_SOURCE, // WaveOut 70 | CONNECTIONTYPE_WAVE_OUTPUT 71 | } 72 | }; 73 | 74 | static 75 | ENDPOINT_MINIPAIR SpeakerMiniports = 76 | { 77 | eSpeakerDevice, 78 | L"TopologySpeaker", // make sure this or the template name matches with KSNAME_TopologySpeaker in the inf's [Strings] section 79 | NULL, // optional template name 80 | CreateMiniportTopologyCsAudioSstCatPt, 81 | &SpeakerTopoMiniportFilterDescriptor, 82 | 0, NULL, // Interface properties 83 | L"WaveSpeaker", // make sure this or the template name matches with KSNAME_WaveSpeaker in the inf's [Strings] section 84 | NULL, // optional template name 85 | CreateMiniportWaveRTCsAudioSstCatPt, 86 | &SpeakerWaveMiniportFilterDescriptor, 87 | 0, // Interface properties 88 | NULL, 89 | SPEAKER_DEVICE_MAX_CHANNELS, 90 | SpeakerPinDeviceFormatsAndModes, 91 | SIZEOF_ARRAY(SpeakerPinDeviceFormatsAndModes), 92 | SpeakerTopologyPhysicalConnections, 93 | SIZEOF_ARRAY(SpeakerTopologyPhysicalConnections), 94 | ENDPOINT_NO_FLAGS, 95 | }; 96 | 97 | // 98 | // Capture miniports. 99 | // 100 | 101 | /********************************************************************* 102 | * Topology/Wave bridge connection for mic array 1 (front) * 103 | * * 104 | * +------+ +------+ * 105 | * | Topo | | Wave | * 106 | * | | | | * 107 | * Mic in --->|0 1|===>|0 1|---> Capture Host Pin * 108 | * | | | | * 109 | * +------+ +------+ * 110 | *********************************************************************/ 111 | static 112 | PHYSICALCONNECTIONTABLE MicArray1TopologyPhysicalConnections[] = 113 | { 114 | { 115 | KSPIN_TOPO_BRIDGE, // TopologyOut 116 | KSPIN_WAVE_BRIDGE, // WaveIn 117 | CONNECTIONTYPE_TOPOLOGY_OUTPUT 118 | } 119 | }; 120 | 121 | static 122 | ENDPOINT_MINIPAIR MicJackMiniports = 123 | { 124 | eMicJackDevice, 125 | L"TopologyMicJack", // make sure this or the template name matches with KSNAME_TopologyMicArray1 in the inf's [Strings] section 126 | NULL, // optional template name 127 | CreateMiniportTopologyCsAudioSstCatPt, 128 | &MicJackTopoMiniportFilterDescriptor, 129 | 0, NULL, // Interface properties 130 | L"WaveMicJack", // make sure this or the tempalte name matches with KSNAME_WaveMicArray1 in the inf's [Strings] section 131 | NULL, // optional template name 132 | CreateMiniportWaveRTCsAudioSstCatPt, 133 | &MicArrayWaveMiniportFilterDescriptor, 134 | 0, // Interface properties 135 | NULL, 136 | MICARRAY_DEVICE_MAX_CHANNELS, 137 | MicArrayPinDeviceFormatsAndModes, 138 | SIZEOF_ARRAY(MicArrayPinDeviceFormatsAndModes), 139 | MicArray1TopologyPhysicalConnections, 140 | SIZEOF_ARRAY(MicArray1TopologyPhysicalConnections), 141 | ENDPOINT_NO_FLAGS, 142 | }; 143 | 144 | 145 | //============================================================================= 146 | // 147 | // Render miniport pairs. NOTE: the split of render and capture is arbitrary and 148 | // unnessary, this array could contain capture endpoints. 149 | // 150 | static 151 | PENDPOINT_MINIPAIR g_RenderEndpoints[] = 152 | { 153 | &SpeakerMiniports, 154 | }; 155 | 156 | #define g_cRenderEndpoints (SIZEOF_ARRAY(g_RenderEndpoints)) 157 | 158 | //============================================================================= 159 | // 160 | // Capture miniport pairs. NOTE: the split of render and capture is arbitrary and 161 | // unnessary, this array could contain render endpoints. 162 | // 163 | static 164 | PENDPOINT_MINIPAIR g_CaptureEndpoints[] = 165 | { 166 | &MicJackMiniports 167 | }; 168 | 169 | #define g_cCaptureEndpoints (SIZEOF_ARRAY(g_CaptureEndpoints)) 170 | 171 | //============================================================================= 172 | // 173 | // Total miniports = # endpoints * 2 (topology + wave). 174 | // 175 | #define g_MaxMiniports ((g_cRenderEndpoints + g_cCaptureEndpoints) * 2) 176 | 177 | #endif // _CSAUDIOSSTCATPT_MINIPAIRS_H_ 178 | -------------------------------------------------------------------------------- /Source/Utilities/registers.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-only */ 2 | /* 3 | * Copyright(c) 2020 Intel Corporation. All rights reserved. 4 | * 5 | * Author: Cezary Rojewski 6 | */ 7 | 8 | #ifndef __SND_SOC_INTEL_CATPT_REGS_H 9 | #define __SND_SOC_INTEL_CATPT_REGS_H 10 | 11 | #define CATPT_SHIM_REGS_SIZE 4096 12 | #define CATPT_DMA_REGS_SIZE 1024 13 | #define CATPT_DMA_COUNT 2 14 | #define CATPT_SSP_REGS_SIZE 512 15 | 16 | /* DSP Shim registers */ 17 | 18 | #define CATPT_SHIM_CS1 0x00 19 | #define CATPT_SHIM_ISC 0x18 20 | #define CATPT_SHIM_ISD 0x20 21 | #define CATPT_SHIM_IMC 0x28 22 | #define CATPT_SHIM_IMD 0x30 23 | #define CATPT_SHIM_IPCC 0x38 24 | #define CATPT_SHIM_IPCD 0x40 25 | #define CATPT_SHIM_CLKCTL 0x78 26 | #define CATPT_SHIM_CS2 0x80 27 | #define CATPT_SHIM_LTRC 0xE0 28 | #define CATPT_SHIM_HMDC 0xE8 29 | 30 | #define CATPT_CS_LPCS BIT(31) 31 | #define CATPT_CS_SFCR(ssp) BIT(27 + (ssp)) 32 | #define CATPT_CS_S1IOCS BIT(23) 33 | #define CATPT_CS_S0IOCS BIT(21) 34 | #define CATPT_CS_PCE BIT(15) 35 | #define CATPT_CS_SDPM(ssp) BIT(11 + (ssp)) 36 | #define CATPT_CS_STALL BIT(10) 37 | #define CATPT_CS_DCS GENMASK(6, 4) 38 | /* b100 DSP core & audio fabric high clock */ 39 | #define CATPT_CS_DCS_HIGH (0x4 << 4) 40 | #define CATPT_CS_SBCS(ssp) BIT(2 + (ssp)) 41 | #define CATPT_CS_RST BIT(1) 42 | 43 | #define CATPT_ISC_IPCDB BIT(1) 44 | #define CATPT_ISC_IPCCD BIT(0) 45 | #define CATPT_ISD_DCPWM BIT(31) 46 | #define CATPT_ISD_IPCCB BIT(1) 47 | #define CATPT_ISD_IPCDD BIT(0) 48 | 49 | #define CATPT_IMC_IPCDB BIT(1) 50 | #define CATPT_IMC_IPCCD BIT(0) 51 | #define CATPT_IMD_IPCCB BIT(1) 52 | #define CATPT_IMD_IPCDD BIT(0) 53 | 54 | #define CATPT_IPCC_BUSY BIT(31) 55 | #define CATPT_IPCC_DONE BIT(30) 56 | #define CATPT_IPCD_BUSY BIT(31) 57 | #define CATPT_IPCD_DONE BIT(30) 58 | 59 | #define CATPT_CLKCTL_CFCIP BIT(31) 60 | #define CATPT_CLKCTL_SMOS GENMASK(25, 24) 61 | 62 | #define CATPT_HMDC_HDDA(e, ch) BIT(8 * (e) + (ch)) 63 | 64 | /* defaults to reset SHIM registers to after each power cycle */ 65 | #define CATPT_CS_DEFAULT 0x8480040E 66 | #define CATPT_ISC_DEFAULT 0x0 67 | #define CATPT_ISD_DEFAULT 0x0 68 | #define CATPT_IMC_DEFAULT 0x7FFF0003 69 | #define CATPT_IMD_DEFAULT 0x7FFF0003 70 | #define CATPT_IPCC_DEFAULT 0x0 71 | #define CATPT_IPCD_DEFAULT 0x0 72 | #define CATPT_CLKCTL_DEFAULT 0x7FF 73 | #define CATPT_CS2_DEFAULT 0x0 74 | #define CATPT_LTRC_DEFAULT 0x0 75 | #define CATPT_HMDC_DEFAULT 0x0 76 | 77 | /* PCI Configuration registers */ 78 | 79 | #define CATPT_PCI_PMCAPID 0x80 80 | #define CATPT_PCI_PMCS (CATPT_PCI_PMCAPID + PCI_PM_CTRL) 81 | #define CATPT_PCI_VDRTCTL0 0xA0 82 | #define CATPT_PCI_VDRTCTL2 0xA8 83 | 84 | #define CATPT_VDRTCTL2_DTCGE BIT(10) 85 | #define CATPT_VDRTCTL2_DCLCGE BIT(1) 86 | #define CATPT_VDRTCTL2_CGEALL 0xF7F 87 | 88 | /* LPT PCI Configuration bits */ 89 | 90 | #define LPT_VDRTCTL0_DSRAMPGE(b) BIT(16 + (b)) 91 | #define LPT_VDRTCTL0_DSRAMPGE_MASK GENMASK(31, 16) 92 | #define LPT_VDRTCTL0_ISRAMPGE(b) BIT(6 + (b)) 93 | #define LPT_VDRTCTL0_ISRAMPGE_MASK GENMASK(15, 6) 94 | #define LPT_VDRTCTL0_D3SRAMPGD BIT(2) 95 | #define LPT_VDRTCTL0_D3PGD BIT(1) 96 | #define LPT_VDRTCTL0_APLLSE BIT(0) 97 | 98 | /* WPT PCI Configuration bits */ 99 | 100 | #define WPT_VDRTCTL0_DSRAMPGE(b) BIT(12 + (b)) 101 | #define WPT_VDRTCTL0_DSRAMPGE_MASK GENMASK(31, 12) 102 | #define WPT_VDRTCTL0_ISRAMPGE(b) BIT(2 + (b)) 103 | #define WPT_VDRTCTL0_ISRAMPGE_MASK GENMASK(11, 2) 104 | #define WPT_VDRTCTL0_D3SRAMPGD BIT(1) 105 | #define WPT_VDRTCTL0_D3PGD BIT(0) 106 | 107 | #define WPT_VDRTCTL2_APLLSE BIT(31) 108 | 109 | /* defaults to reset SSP registers to after each power cycle */ 110 | #define CATPT_SSC0_DEFAULT 0x0 111 | #define CATPT_SSC1_DEFAULT 0x0 112 | #define CATPT_SSS_DEFAULT 0xF004 113 | #define CATPT_SSIT_DEFAULT 0x0 114 | #define CATPT_SSD_DEFAULT 0xC43893A3 115 | #define CATPT_SSTO_DEFAULT 0x0 116 | #define CATPT_SSPSP_DEFAULT 0x0 117 | #define CATPT_SSTSA_DEFAULT 0x0 118 | #define CATPT_SSRSA_DEFAULT 0x0 119 | #define CATPT_SSTSS_DEFAULT 0x0 120 | #define CATPT_SSCR2_DEFAULT 0x0 121 | #define CATPT_SSPSP2_DEFAULT 0x0 122 | 123 | /* Physically the same block, access address differs between host and dsp */ 124 | #define CATPT_DSP_DRAM_OFFSET 0x400000 125 | #define catpt_to_host_offset(offset) ((offset) & ~(CATPT_DSP_DRAM_OFFSET)) 126 | #define catpt_to_dsp_offset(offset) ((offset) | CATPT_DSP_DRAM_OFFSET) 127 | 128 | #define CATPT_MEMBLOCK_SIZE 0x8000 129 | #define catpt_num_dram(cdev) (hweight_long((cdev)->spec->dram_mask)) 130 | #define catpt_num_iram(cdev) (hweight_long((cdev)->spec->iram_mask)) 131 | #define catpt_dram_size(cdev) (catpt_num_dram(cdev) * CATPT_MEMBLOCK_SIZE) 132 | #define catpt_iram_size(cdev) (catpt_num_iram(cdev) * CATPT_MEMBLOCK_SIZE) 133 | 134 | /* registry I/O helpers */ 135 | 136 | #define lpe_ba m_BAR0.Base.baseptr 137 | #define pci_ba m_BAR1.Base.baseptr 138 | 139 | #define catpt_shim_addr(cdev) \ 140 | ((cdev)->lpe_ba + (cdev)->spec->host_shim_offset) 141 | #define catpt_dma_addr(cdev, dma) \ 142 | ((cdev)->lpe_ba + (cdev)->spec->host_dma_offset[dma]) 143 | #define catpt_ssp_addr(cdev, ssp) \ 144 | ((cdev)->lpe_ba + (cdev)->spec->host_ssp_offset[ssp]) 145 | #define catpt_inbox_addr(cdev) \ 146 | ((cdev)->lpe_ba + (cdev)->ipc_config.inbox_offset) 147 | #define catpt_outbox_addr(cdev) \ 148 | ((cdev)->lpe_ba + (cdev)->ipc_config.outbox_offset) 149 | 150 | #define catpt_writel_ssp(cdev, ssp, reg, val) \ 151 | writel(val, catpt_ssp_addr(cdev, ssp) + (reg)) 152 | 153 | #define catpt_readl_shim(cdev, reg) \ 154 | readl(catpt_shim_addr(cdev) + CATPT_SHIM_##reg) 155 | #define catpt_writel_shim(cdev, reg, val) \ 156 | writel(val, catpt_shim_addr(cdev) + CATPT_SHIM_##reg) 157 | #define catpt_updatel_shim(cdev, reg, mask, val) \ 158 | catpt_writel_shim(cdev, reg, \ 159 | (catpt_readl_shim(cdev, reg) & ~(mask)) | (val)) 160 | 161 | #define catpt_readl_poll_shim(cdev, reg, val, mask, delay_us, timeout_us) \ 162 | readl_poll_timeout(catpt_shim_addr(cdev) + CATPT_SHIM_##reg, \ 163 | val, mask, delay_us, timeout_us) 164 | 165 | #define catpt_readl_pci(cdev, reg) \ 166 | readl(cdev->pci_ba + CATPT_PCI_##reg) 167 | #define catpt_writel_pci(cdev, reg, val) \ 168 | writel(val, cdev->pci_ba + CATPT_PCI_##reg) 169 | 170 | #define catpt_readl_pci_raw(cdev, reg) \ 171 | readl(cdev->pci_ba + reg) 172 | #define catpt_writel_pci_raw(cdev, reg, val) \ 173 | writel(val, cdev->pci_ba + reg) 174 | 175 | #define catpt_updatel_pci(cdev, reg, mask, val) \ 176 | catpt_writel_pci(cdev, reg, \ 177 | (catpt_readl_pci(cdev, reg) & ~(mask)) | (val)) 178 | 179 | #define catpt_updatel_pci_raw(cdev, reg, mask, val) \ 180 | catpt_writel_pci_raw(cdev, reg, \ 181 | (catpt_readl_pci_raw(cdev, reg) & ~(mask)) | (val)) 182 | 183 | #define catpt_readl_poll_pci(cdev, reg, mask, cond, delay_us, timeout_us) \ 184 | readl_poll_timeout((cdev)->pci_ba + CATPT_PCI_##reg, \ 185 | mask, cond, delay_us, timeout_us) 186 | 187 | #endif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Dd]ebugPublic/ 19 | [Rr]elease/ 20 | [Rr]eleases/ 21 | x64/ 22 | x86/ 23 | bld/ 24 | [Bb]in/ 25 | [Oo]bj/ 26 | [Ll]og/ 27 | 28 | # Visual Studio 2015/2017 cache/options directory 29 | .vs/ 30 | # Uncomment if you have tasks that create the project's static files in wwwroot 31 | #wwwroot/ 32 | 33 | # Visual Studio 2017 auto generated files 34 | Generated\ Files/ 35 | 36 | # MSTest test Results 37 | [Tt]est[Rr]esult*/ 38 | [Bb]uild[Ll]og.* 39 | 40 | # NUNIT 41 | *.VisualState.xml 42 | TestResult.xml 43 | 44 | # Build Results of an ATL Project 45 | [Dd]ebugPS/ 46 | [Rr]eleasePS/ 47 | dlldata.c 48 | 49 | # Benchmark Results 50 | BenchmarkDotNet.Artifacts/ 51 | 52 | # .NET Core 53 | project.lock.json 54 | project.fragment.lock.json 55 | artifacts/ 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_h.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *_wpftmp.csproj 81 | *.log 82 | *.vspscc 83 | *.vssscc 84 | .builds 85 | *.pidb 86 | *.svclog 87 | *.scc 88 | 89 | # Chutzpah Test files 90 | _Chutzpah* 91 | 92 | # Visual C++ cache files 93 | ipch/ 94 | *.aps 95 | *.ncb 96 | *.opendb 97 | *.opensdf 98 | *.sdf 99 | *.cachefile 100 | *.VC.db 101 | *.VC.VC.opendb 102 | 103 | # Visual Studio profiler 104 | *.psess 105 | *.vsp 106 | *.vspx 107 | *.sap 108 | 109 | # Visual Studio Trace Files 110 | *.e2e 111 | 112 | # TFS 2012 Local Workspace 113 | $tf/ 114 | 115 | # Guidance Automation Toolkit 116 | *.gpState 117 | 118 | # ReSharper is a .NET coding add-in 119 | _ReSharper*/ 120 | *.[Rr]e[Ss]harper 121 | *.DotSettings.user 122 | 123 | # JustCode is a .NET coding add-in 124 | .JustCode 125 | 126 | # TeamCity is a build add-in 127 | _TeamCity* 128 | 129 | # DotCover is a Code Coverage Tool 130 | *.dotCover 131 | 132 | # AxoCover is a Code Coverage Tool 133 | .axoCover/* 134 | !.axoCover/settings.json 135 | 136 | # Visual Studio code coverage results 137 | *.coverage 138 | *.coveragexml 139 | 140 | # NCrunch 141 | _NCrunch_* 142 | .*crunch*.local.xml 143 | nCrunchTemp_* 144 | 145 | # MightyMoose 146 | *.mm.* 147 | AutoTest.Net/ 148 | 149 | # Web workbench (sass) 150 | .sass-cache/ 151 | 152 | # Installshield output folder 153 | [Ee]xpress/ 154 | 155 | # DocProject is a documentation generator add-in 156 | DocProject/buildhelp/ 157 | DocProject/Help/*.HxT 158 | DocProject/Help/*.HxC 159 | DocProject/Help/*.hhc 160 | DocProject/Help/*.hhk 161 | DocProject/Help/*.hhp 162 | DocProject/Help/Html2 163 | DocProject/Help/html 164 | 165 | # Click-Once directory 166 | publish/ 167 | 168 | # Publish Web Output 169 | *.[Pp]ublish.xml 170 | *.azurePubxml 171 | # Note: Comment the next line if you want to checkin your web deploy settings, 172 | # but database connection strings (with potential passwords) will be unencrypted 173 | *.pubxml 174 | *.publishproj 175 | 176 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 177 | # checkin your Azure Web App publish settings, but sensitive information contained 178 | # in these scripts will be unencrypted 179 | PublishScripts/ 180 | 181 | # NuGet Packages 182 | *.nupkg 183 | # The packages folder can be ignored because of Package Restore 184 | **/[Pp]ackages/* 185 | # except build/, which is used as an MSBuild target. 186 | !**/[Pp]ackages/build/ 187 | # Uncomment if necessary however generally it will be regenerated when needed 188 | #!**/[Pp]ackages/repositories.config 189 | # NuGet v3's project.json files produces more ignorable files 190 | *.nuget.props 191 | *.nuget.targets 192 | 193 | # Microsoft Azure Build Output 194 | csx/ 195 | *.build.csdef 196 | 197 | # Microsoft Azure Emulator 198 | ecf/ 199 | rcf/ 200 | 201 | # Windows Store app package directories and files 202 | AppPackages/ 203 | BundleArtifacts/ 204 | Package.StoreAssociation.xml 205 | _pkginfo.txt 206 | *.appx 207 | 208 | # Visual Studio cache files 209 | # files ending in .cache can be ignored 210 | *.[Cc]ache 211 | # but keep track of directories ending in .cache 212 | !*.[Cc]ache/ 213 | 214 | # Others 215 | ClientBin/ 216 | ~$* 217 | *~ 218 | *.dbmdl 219 | *.dbproj.schemaview 220 | *.jfm 221 | *.pfx 222 | *.publishsettings 223 | orleans.codegen.cs 224 | 225 | # Including strong name files can present a security risk 226 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 227 | #*.snk 228 | 229 | # Since there are multiple workflows, uncomment next line to ignore bower_components 230 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 231 | #bower_components/ 232 | 233 | # RIA/Silverlight projects 234 | Generated_Code/ 235 | 236 | # Backup & report files from converting an old project file 237 | # to a newer Visual Studio version. Backup files are not needed, 238 | # because we have git ;-) 239 | _UpgradeReport_Files/ 240 | Backup*/ 241 | UpgradeLog*.XML 242 | UpgradeLog*.htm 243 | ServiceFabricBackup/ 244 | *.rptproj.bak 245 | 246 | # SQL Server files 247 | *.mdf 248 | *.ldf 249 | *.ndf 250 | 251 | # Business Intelligence projects 252 | *.rdl.data 253 | *.bim.layout 254 | *.bim_*.settings 255 | *.rptproj.rsuser 256 | 257 | # Microsoft Fakes 258 | FakesAssemblies/ 259 | 260 | # GhostDoc plugin setting file 261 | *.GhostDoc.xml 262 | 263 | # Node.js Tools for Visual Studio 264 | .ntvs_analysis.dat 265 | node_modules/ 266 | 267 | # Visual Studio 6 build log 268 | *.plg 269 | 270 | # Visual Studio 6 workspace options file 271 | *.opt 272 | 273 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 274 | *.vbw 275 | 276 | # Visual Studio LightSwitch build output 277 | **/*.HTMLClient/GeneratedArtifacts 278 | **/*.DesktopClient/GeneratedArtifacts 279 | **/*.DesktopClient/ModelManifest.xml 280 | **/*.Server/GeneratedArtifacts 281 | **/*.Server/ModelManifest.xml 282 | _Pvt_Extensions 283 | 284 | # Paket dependency manager 285 | .paket/paket.exe 286 | paket-files/ 287 | 288 | # FAKE - F# Make 289 | .fake/ 290 | 291 | # JetBrains Rider 292 | .idea/ 293 | *.sln.iml 294 | 295 | # CodeRush personal settings 296 | .cr/personal 297 | 298 | # Python Tools for Visual Studio (PTVS) 299 | __pycache__/ 300 | *.pyc 301 | 302 | # Cake - Uncomment if you are using it 303 | # tools/** 304 | # !tools/packages.config 305 | 306 | # Tabs Studio 307 | *.tss 308 | 309 | # Telerik's JustMock configuration file 310 | *.jmconfig 311 | 312 | # BizTalk build output 313 | *.btp.cs 314 | *.btm.cs 315 | *.odx.cs 316 | *.xsd.cs 317 | 318 | # OpenCover UI analysis results 319 | OpenCover/ 320 | 321 | # Azure Stream Analytics local run output 322 | ASALocalRun/ 323 | 324 | # MSBuild Binary and Structured Log 325 | *.binlog 326 | 327 | # NVidia Nsight GPU debugger configuration file 328 | *.nvuser 329 | 330 | # MFractors (Xamarin productivity tool) working folder 331 | .mfractor/ 332 | 333 | # Local History for Visual Studio 334 | .localhistory/ 335 | -------------------------------------------------------------------------------- /Source/Utilities/loader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "definitions.h" 3 | #include "hw.h" 4 | #include "resource.h" 5 | 6 | /* FW load (200ms) plus operational delays */ 7 | #define FW_READY_TIMEOUT_MS 250 8 | 9 | #define FW_SIGNATURE "$SST" 10 | #define FW_SIGNATURE_SIZE 4 11 | 12 | #include 13 | struct catpt_fw_hdr { 14 | char signature[FW_SIGNATURE_SIZE]; 15 | UINT32 file_size; 16 | UINT32 modules; 17 | UINT32 file_format; 18 | UINT32 reserved[4]; 19 | }; 20 | 21 | struct catpt_fw_mod_hdr { 22 | char signature[FW_SIGNATURE_SIZE]; 23 | UINT32 mod_size; 24 | UINT32 blocks; 25 | UINT16 slot; 26 | UINT16 module_id; 27 | UINT32 entry_point; 28 | UINT32 persistent_size; 29 | UINT32 scratch_size; 30 | }; 31 | 32 | enum catpt_ram_type { 33 | CATPT_RAM_TYPE_IRAM = 1, 34 | CATPT_RAM_TYPE_DRAM = 2, 35 | /* DRAM with module's initial state */ 36 | CATPT_RAM_TYPE_INSTANCE = 3, 37 | }; 38 | 39 | struct catpt_fw_block_hdr { 40 | UINT32 ram_type; 41 | UINT32 size; 42 | UINT32 ram_offset; 43 | UINT32 rsvd; 44 | }; 45 | #include 46 | 47 | void CCsAudioCatptSSTHW::sram_init(PRESOURCE sram, UINT32 start, UINT32 size) { 48 | sram->start = start; 49 | sram->end = start + size - 1; 50 | } 51 | 52 | void CCsAudioCatptSSTHW::sram_free(PRESOURCE sram) { 53 | PRESOURCE res, save; 54 | 55 | for (res = sram->child; res;) { 56 | save = res->sibling; 57 | release_resource(res); 58 | ExFreePoolWithTag(res, CSAUDIOCATPTSST_POOLTAG); 59 | res = save; 60 | } 61 | } 62 | 63 | PRESOURCE CCsAudioCatptSSTHW::catpt_request_region(PRESOURCE root, size_t size) 64 | { 65 | PRESOURCE res = root->child; 66 | size_t addr = root->start; 67 | 68 | for (;;) { 69 | if (res->start - addr >= size) 70 | break; 71 | addr = res->end + 1; 72 | res = res->sibling; 73 | if (!res) 74 | return NULL; 75 | } 76 | 77 | return __request_region(root, addr, size, 0); 78 | } 79 | 80 | NTSTATUS CCsAudioCatptSSTHW::catpt_load_block(PHYSICAL_ADDRESS pAddr, struct catpt_fw_block_hdr* blk, bool alloc) 81 | { 82 | NTSTATUS status; 83 | PRESOURCE sram; 84 | 85 | switch (blk->ram_type) { 86 | case CATPT_RAM_TYPE_IRAM: 87 | sram = &this->iram; 88 | break; 89 | default: 90 | sram = &this->dram; 91 | break; 92 | } 93 | 94 | UINT32 dst_addr = (UINT32)(sram->start + blk->ram_offset); 95 | //TODO: mark region as busy 96 | 97 | if (alloc) { 98 | PRESOURCE res = __request_region(sram, dst_addr, blk->size, 0); 99 | if (!res) { 100 | return STATUS_DEVICE_BUSY; 101 | } 102 | } 103 | 104 | dst_addr |= CATPT_DMA_DSP_ADDR_MASK; 105 | 106 | /* advance to data area */ 107 | pAddr.QuadPart += sizeof(*blk); 108 | 109 | //TODO: dma_memcpy_todsp 110 | status = this->dmac->transfer_dma(dst_addr, pAddr.LowPart, blk->size); 111 | 112 | if (!NT_SUCCESS(status)) { 113 | __release_region(sram, dst_addr, blk->size); 114 | } 115 | 116 | return status; 117 | } 118 | 119 | NTSTATUS CCsAudioCatptSSTHW::catpt_load_module(PHYSICAL_ADDRESS paddr, struct catpt_fw_mod_hdr* mod) 120 | { 121 | struct catpt_module_type* type; 122 | UINT32 offset = sizeof(*mod); 123 | 124 | type = &this->modules[mod->module_id]; 125 | 126 | for (UINT32 i = 0; i < mod->blocks; i++) { 127 | struct catpt_fw_block_hdr* blk; 128 | NTSTATUS status; 129 | 130 | blk = (struct catpt_fw_block_hdr*)((UINT8*)mod + offset); 131 | 132 | PHYSICAL_ADDRESS blockPaddr; 133 | blockPaddr.QuadPart = paddr.QuadPart + offset; 134 | status = catpt_load_block(blockPaddr, blk, true); 135 | if (!NT_SUCCESS(status)) { 136 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "load block failed: 0x%x\n", status); 137 | return status; 138 | } 139 | /* 140 | * Save state window coordinates - these will be 141 | * used to capture module state on D0 exit. 142 | */ 143 | if (blk->ram_type == CATPT_RAM_TYPE_INSTANCE) { 144 | type->state_offset = blk->ram_offset; 145 | type->state_size = blk->size; 146 | } 147 | 148 | offset += sizeof(*blk) + blk->size; 149 | } 150 | 151 | /* init module type static info */ 152 | type->loaded = true; 153 | /* DSP expects address from module header substracted by 4 */ 154 | type->entry_point = mod->entry_point - 4; 155 | type->persistent_size = mod->persistent_size; 156 | type->scratch_size = mod->scratch_size; 157 | 158 | return STATUS_SUCCESS; 159 | } 160 | 161 | NTSTATUS CCsAudioCatptSSTHW::catpt_load_firmware(PHYSICAL_ADDRESS paddr, struct catpt_fw_hdr* fw) { 162 | UINT32 offset = sizeof(*fw); 163 | 164 | for (UINT32 i = 0; i < fw->modules; i++) { 165 | struct catpt_fw_mod_hdr* mod; 166 | NTSTATUS status; 167 | 168 | mod = (struct catpt_fw_mod_hdr*)((UINT8*)fw + offset); 169 | if (strncmp(fw->signature, mod->signature, 170 | FW_SIGNATURE_SIZE)) { 171 | DPF(D_ERROR, "module signature mismatch\n"); 172 | return STATUS_INVALID_PARAMETER; 173 | } 174 | 175 | if (mod->module_id > CATPT_MODID_LAST) 176 | return STATUS_INVALID_PARAMETER; 177 | 178 | PHYSICAL_ADDRESS modulePaddr; 179 | modulePaddr.QuadPart = paddr.QuadPart + offset; 180 | status = catpt_load_module(modulePaddr, mod); 181 | if (!NT_SUCCESS(status)) { 182 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "load module failed: 0x%x\n", status); 183 | return status; 184 | } 185 | 186 | offset += sizeof(*mod) + mod->mod_size; 187 | } 188 | return STATUS_SUCCESS; 189 | } 190 | 191 | NTSTATUS CCsAudioCatptSSTHW::catpt_load_image(PCWSTR path, BOOL restore) { 192 | NTSTATUS status; 193 | struct firmware* img; 194 | struct catpt_fw_hdr* fw; 195 | 196 | const char* signature = FW_SIGNATURE; 197 | 198 | status = request_firmware((const struct firmware**)&img, path); 199 | if (!NT_SUCCESS(status)) { 200 | return status; 201 | } 202 | 203 | fw = (struct catpt_fw_hdr*)img->data; 204 | if (strncmp(fw->signature, signature, FW_SIGNATURE_SIZE)) { 205 | status = STATUS_INVALID_PARAMETER; 206 | goto release_fw; 207 | } 208 | 209 | PHYSICAL_ADDRESS maxAddr; 210 | maxAddr.QuadPart = MAXULONG32; 211 | void* vaddr; 212 | vaddr = MmAllocateContiguousMemory(img->size, maxAddr); 213 | if (!vaddr) { 214 | status = STATUS_NO_MEMORY; 215 | goto release_fw; 216 | } 217 | memcpy(vaddr, img->data, img->size); 218 | 219 | PHYSICAL_ADDRESS paddr; 220 | paddr = MmGetPhysicalAddress(vaddr); 221 | 222 | fw = (struct catpt_fw_hdr*)vaddr; 223 | if (restore) { 224 | //TODO: restore 225 | } 226 | else { 227 | status = catpt_load_firmware(paddr, fw); 228 | } 229 | 230 | MmFreeContiguousMemory(vaddr); 231 | release_fw: 232 | free_firmware(img); 233 | return status; 234 | } 235 | 236 | NTSTATUS CCsAudioCatptSSTHW::catpt_boot_firmware(BOOL restore) { 237 | NTSTATUS status; 238 | 239 | dsp_stall(true); 240 | 241 | status = catpt_load_image(L"\\SystemRoot\\system32\\DRIVERS\\IntcSST2.bin", restore); 242 | if (status) { 243 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "Load binaries failed: 0x%x\n", status); 244 | return status; 245 | } 246 | 247 | this->fw_ready = FALSE; 248 | dsp_stall(false); 249 | 250 | LARGE_INTEGER StartTime; 251 | KeQuerySystemTimePrecise(&StartTime); 252 | while (this->fw_ready == FALSE) { 253 | LARGE_INTEGER CurrentTime; 254 | KeQuerySystemTimePrecise(&CurrentTime); 255 | 256 | if (((CurrentTime.QuadPart - StartTime.QuadPart) / (10 * 1000)) >= FW_READY_TIMEOUT_MS) { 257 | DPF(D_ERROR, "Firmware ready timeout\n"); 258 | return STATUS_TIMEOUT; 259 | } 260 | } 261 | DPF(D_ERROR, "Firmware ready!!!\n"); 262 | 263 | /* update sram pg & clock once done booting */ 264 | dsp_update_srampge(&this->dram, this->spec->dram_mask); 265 | dsp_update_srampge(&this->iram, this->spec->iram_mask); 266 | 267 | return dsp_update_lpclock(); 268 | } -------------------------------------------------------------------------------- /Source/Utilities/ipc.cpp: -------------------------------------------------------------------------------- 1 | #include "definitions.h" 2 | #include "hw.h" 3 | 4 | static void memcpy_io(PVOID dst, PVOID src, size_t sz) { 5 | for (size_t i = 0; i < sz; i++) { 6 | ((PUINT8)dst)[i] = ((PUINT8)src)[i]; 7 | } 8 | } 9 | 10 | void CCsAudioCatptSSTHW::ipc_init() { 11 | this->ipc_ready = false; 12 | this->ipc_done = false; 13 | this->ipc_busy = false; 14 | } 15 | 16 | NTSTATUS CCsAudioCatptSSTHW::ipc_arm(struct catpt_fw_ready* config) 17 | { 18 | /* 19 | * Both tx and rx are put into and received from outbox. Inbox is 20 | * only used for notifications where payload size is known upfront, 21 | * thus no separate buffer is allocated for it. 22 | */ 23 | this->ipc_rx.data = ExAllocatePoolZero(NonPagedPool, config->outbox_size, CSAUDIOCATPTSST_POOLTAG); 24 | if (!this->ipc_rx.data) 25 | return STATUS_NO_MEMORY; 26 | 27 | memcpy_io(&ipc_config, config, sizeof(*config)); 28 | this->ipc_ready = true; 29 | 30 | return STATUS_SUCCESS; 31 | } 32 | 33 | NTSTATUS CCsAudioCatptSSTHW::ipc_send_msg(struct catpt_ipc_msg request, 34 | struct catpt_ipc_msg* reply, int timeout) { 35 | if (!this->ipc_ready) { 36 | return STATUS_NO_SUCH_DEVICE; 37 | } 38 | 39 | if (request.size > ipc_config.outbox_size || (reply && reply->size > ipc_config.outbox_size)) { 40 | return STATUS_BUFFER_OVERFLOW; 41 | } 42 | 43 | //msg init 44 | { 45 | ipc_rx.header = 0; 46 | ipc_rx.size = reply ? reply->size : 0; 47 | 48 | this->ipc_done = false; 49 | this->ipc_busy = true; 50 | } 51 | 52 | dsp_send_tx(&request); 53 | 54 | NTSTATUS status; 55 | status = ipc_wait_completion(timeout); 56 | if (!NT_SUCCESS(status)) { 57 | DPF(D_ERROR, "IPC Failed!!!\n"); 58 | this->ipc_ready = false; 59 | return status; 60 | } 61 | 62 | int ret = ipc_rx.rsp.status; 63 | if (reply) { 64 | reply->header = ipc_rx.header; 65 | if (!ret && reply->data) { 66 | memcpy_io(reply->data, ipc_rx.data, reply->size); 67 | } 68 | } 69 | 70 | if (ret) { 71 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "SST returned %d\n", ret); 72 | return STATUS_INVALID_DEVICE_STATE; 73 | } 74 | return status; 75 | } 76 | 77 | NTSTATUS CCsAudioCatptSSTHW::ipc_wait_completion(int timeout) { 78 | LARGE_INTEGER StartTime; 79 | KeQuerySystemTimePrecise(&StartTime); 80 | while (!this->ipc_done) { 81 | LARGE_INTEGER CurrentTime; 82 | KeQuerySystemTimePrecise(&CurrentTime); 83 | 84 | if (((CurrentTime.QuadPart - StartTime.QuadPart) / (10 * 1000)) >= timeout) { 85 | DPF(D_ERROR, "Timed out waiting for transmit IPC\n"); 86 | return STATUS_IO_TIMEOUT; 87 | } 88 | 89 | LARGE_INTEGER Interval; 90 | Interval.QuadPart = -10 * 1000; 91 | KeDelayExecutionThread(KernelMode, false, &Interval); 92 | } 93 | 94 | if (ipc_rx.rsp.status != CATPT_REPLY_PENDING) 95 | return STATUS_SUCCESS; 96 | 97 | KeQuerySystemTimePrecise(&StartTime); 98 | while (this->ipc_busy) { 99 | LARGE_INTEGER CurrentTime; 100 | KeQuerySystemTimePrecise(&CurrentTime); 101 | 102 | if (((CurrentTime.QuadPart - StartTime.QuadPart) / (10 * 1000)) >= timeout) { 103 | DPF(D_ERROR, "Timed out waiting for receive IPC\n"); 104 | return STATUS_IO_TIMEOUT; 105 | } 106 | 107 | LARGE_INTEGER Interval; 108 | Interval.QuadPart = -10 * 1000; 109 | KeDelayExecutionThread(KernelMode, false, &Interval); 110 | } 111 | return STATUS_SUCCESS; 112 | } 113 | 114 | void CCsAudioCatptSSTHW::dsp_send_tx(const struct catpt_ipc_msg* tx) { 115 | UINT32 header = tx->header | CATPT_IPCC_BUSY; 116 | 117 | memcpy_io(catpt_outbox_addr(this), tx->data, tx->size); 118 | 119 | catpt_writel_shim(this, IPCC, header); 120 | } 121 | 122 | void CCsAudioCatptSSTHW::dsp_copy_rx(UINT32 header) 123 | { 124 | this->ipc_rx.header = header; 125 | if (this->ipc_rx.rsp.status != CATPT_REPLY_SUCCESS) 126 | return; 127 | 128 | memcpy_io(this->ipc_rx.data, catpt_outbox_addr(this), this->ipc_rx.size); 129 | } 130 | 131 | void CCsAudioCatptSSTHW::dsp_notify_stream(union catpt_notify_msg msg) { 132 | catpt_stream *stream = catpt_stream_find(msg.stream_hw_id); 133 | if (!stream) { 134 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "notify %d for non-existent stream %d\n", msg.notify_reason, msg.stream_hw_id); 135 | return; 136 | } 137 | 138 | struct catpt_notify_position pos; 139 | struct catpt_notify_glitch glitch; 140 | 141 | switch (msg.notify_reason) { 142 | case CATPT_NOTIFY_POSITION_CHANGED: 143 | memcpy_io(&pos, catpt_inbox_addr(this), sizeof(pos)); 144 | break; 145 | 146 | case CATPT_NOTIFY_GLITCH_OCCURRED: 147 | memcpy_io(&glitch, catpt_inbox_addr(this), sizeof(glitch)); 148 | 149 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "glitch %d at pos: 0x%08llx, wp: 0x%08x\n", 150 | glitch.type, glitch.presentation_pos, 151 | glitch.write_pos); 152 | break; 153 | 154 | default: 155 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "unknown notification: %d received\n", 156 | msg.notify_reason); 157 | break; 158 | } 159 | } 160 | 161 | void CCsAudioCatptSSTHW::dsp_process_response(UINT32 header) 162 | { 163 | union catpt_notify_msg msg = CATPT_MSG(header); 164 | 165 | if (msg.fw_ready) { 166 | struct catpt_fw_ready config; 167 | /* to fit 32b header original address is shifted right by 3 */ 168 | UINT32 off = msg.mailbox_address << 3; 169 | 170 | memcpy_io(&config, this->lpe_ba + off, sizeof(config)); 171 | 172 | ipc_arm(&config); 173 | this->fw_ready = true; 174 | return; 175 | } 176 | 177 | switch (msg.global_msg_type) { 178 | case CATPT_GLB_REQUEST_CORE_DUMP: 179 | DPF(D_ERROR, "ADSP device coredump received\n"); 180 | this->ipc_ready = false; 181 | //catpt_coredump(); 182 | /* TODO: attempt recovery */ 183 | break; 184 | 185 | case CATPT_GLB_STREAM_MESSAGE: 186 | switch (msg.stream_msg_type) { 187 | case CATPT_STRM_NOTIFICATION: 188 | dsp_notify_stream(msg); 189 | break; 190 | default: 191 | dsp_copy_rx(header); 192 | /* signal completion of delayed reply */ 193 | this->ipc_busy = FALSE; 194 | break; 195 | } 196 | break; 197 | 198 | default: 199 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "unknown response: %d received\n", 200 | msg.global_msg_type); 201 | break; 202 | } 203 | } 204 | 205 | NTSTATUS CCsAudioCatptSSTHW::dsp_irq_handler() { 206 | NTSTATUS status = STATUS_INVALID_PARAMETER; 207 | UINT32 isc, ipcc; 208 | isc = catpt_readl_shim(this, ISC); 209 | 210 | /* immediate reply */ 211 | if (isc & CATPT_ISC_IPCCD) { 212 | /* mask host DONE interrupt */ 213 | catpt_updatel_shim(this, IMC, CATPT_IMC_IPCCD, CATPT_IMC_IPCCD); 214 | 215 | ipcc = catpt_readl_shim(this, IPCC); 216 | dsp_copy_rx(ipcc); 217 | 218 | this->ipc_done = true; 219 | 220 | /* tell DSP processing is completed */ 221 | catpt_updatel_shim(this, IPCC, CATPT_IPCC_DONE, 0); 222 | /* unmask host DONE interrupt */ 223 | catpt_updatel_shim(this, IMC, CATPT_IMC_IPCCD, 0); 224 | status = STATUS_SUCCESS; 225 | } 226 | 227 | /* delayed reply or notification */ 228 | if (isc & CATPT_ISC_IPCDB) { 229 | /* mask dsp BUSY interrupt */ 230 | catpt_updatel_shim(this, IMC, CATPT_IMC_IPCDB, CATPT_IMC_IPCDB); 231 | 232 | { //from thread in linux 233 | UINT32 ipcd; 234 | 235 | ipcd = catpt_readl_shim(this, IPCD); 236 | 237 | /* ensure there is delayed reply or notification to process */ 238 | if ((ipcd & CATPT_IPCD_BUSY)) { 239 | dsp_process_response(ipcd); 240 | 241 | 242 | /* tell DSP processing is completed */ 243 | catpt_updatel_shim(this, IPCD, CATPT_IPCD_BUSY | CATPT_IPCD_DONE, 244 | CATPT_IPCD_DONE); 245 | } 246 | 247 | /* unmask dsp BUSY interrupt */ 248 | catpt_updatel_shim(this, IMC, CATPT_IMC_IPCDB, 0); 249 | } 250 | 251 | status = STATUS_SUCCESS; 252 | } 253 | 254 | return status; 255 | } -------------------------------------------------------------------------------- /Source/Inc/definitions.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | Definitions.h 8 | 9 | Abstract: 10 | 11 | Header file for common stuff. 12 | --*/ 13 | 14 | #ifndef _CSAUDIOSSTCATPT_DEFINITIONS_H_ 15 | #define _CSAUDIOSSTCATPT_DEFINITIONS_H_ 16 | 17 | #pragma warning(disable:4471) // suppress enum forward declaration 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #pragma warning(default:4471) 26 | #include "NewDelete.h" 27 | 28 | //============================================================================= 29 | // Defines 30 | //============================================================================= 31 | 32 | // Product Id 33 | // {836BA6D1-3FF7-4411-8BCD-469553452DCE} 34 | #define STATIC_PID_CSAUDIOSSTCATPT\ 35 | 0x836ba6d1, 0x3ff7, 0x4411, 0x8b, 0xcd, 0x46, 0x95, 0x53, 0x45, 0x2d, 0xce 36 | DEFINE_GUIDSTRUCT("836BA6D1-3FF7-4411-8BCD-469553452DCE", PID_CSAUDIOSSTCATPT); 37 | #define PID_CSAUDIOSSTCATPT DEFINE_GUIDNAMED(PID_CSAUDIOSSTCATPT) 38 | 39 | // Pool tag used for CSAUDIOSSTCATPT allocations 40 | #define CSAUDIOCATPTSST_POOLTAG 'UASC' 41 | 42 | // Debug module name 43 | #define STR_MODULENAME "CSAUDIOSSTCATPT: " 44 | 45 | // Debug utility macros 46 | #define D_FUNC 4 47 | #define D_BLAB DEBUGLVL_BLAB 48 | #define D_VERBOSE DEBUGLVL_VERBOSE 49 | #define D_TERSE DEBUGLVL_TERSE 50 | #define D_ERROR DEBUGLVL_ERROR 51 | #define DPF _DbgPrintF 52 | #define DPF_ENTER(x) DPF(D_FUNC, x) 53 | 54 | // Channel orientation 55 | #define CHAN_LEFT 0 56 | #define CHAN_RIGHT 1 57 | #define CHAN_MASTER (-1) 58 | 59 | // Dma Settings. 60 | #define DMA_BUFFER_SIZE 0x16000 61 | 62 | #define KSPROPERTY_TYPE_ALL KSPROPERTY_TYPE_BASICSUPPORT | \ 63 | KSPROPERTY_TYPE_GET | \ 64 | KSPROPERTY_TYPE_SET 65 | 66 | // Specific node numbers 67 | #define DEV_SPECIFIC_VT_BOOL 9 68 | #define DEV_SPECIFIC_VT_I4 10 69 | #define DEV_SPECIFIC_VT_UI4 11 70 | 71 | #define _100NS_PER_MILLISECOND 10000 // number of 100ns units per millisecond 72 | 73 | // Default volume settings. 74 | #define VOLUME_STEPPING_DELTA 0x8000 75 | #define VOLUME_SIGNED_MAXIMUM 0x00000000 76 | #define VOLUME_SIGNED_MINIMUM (-96 * 0x10000) 77 | 78 | // Default peak meter settings 79 | #define PEAKMETER_STEPPING_DELTA 0x1000 80 | #define PEAKMETER_SIGNED_MAXIMUM LONG_MAX 81 | #define PEAKMETER_SIGNED_MINIMUM LONG_MIN 82 | 83 | #define VALUE_NORMALIZE_P(v, step) \ 84 | ((((v) + (step)/2) / (step)) * (step)) 85 | 86 | #define VALUE_NORMALIZE(v, step) \ 87 | ((v) > 0 ? VALUE_NORMALIZE_P((v), (step)) : -(VALUE_NORMALIZE_P(-(v), (step)))) 88 | 89 | #define VALUE_NORMALIZE_IN_RANGE_EX(v, min, max, step) \ 90 | ((v) > (max) ? (max) : \ 91 | (v) < (min) ? (min) : \ 92 | VALUE_NORMALIZE((v), (step))) 93 | 94 | // to normalize volume values. 95 | #define VOLUME_NORMALIZE_IN_RANGE(v) \ 96 | VALUE_NORMALIZE_IN_RANGE_EX((v), VOLUME_SIGNED_MINIMUM, VOLUME_SIGNED_MAXIMUM, VOLUME_STEPPING_DELTA) 97 | 98 | // to normalize sample peak meter. 99 | #define PEAKMETER_NORMALIZE_IN_RANGE(v) \ 100 | VALUE_NORMALIZE_IN_RANGE_EX((v), PEAKMETER_SIGNED_MINIMUM, PEAKMETER_SIGNED_MAXIMUM, PEAKMETER_STEPPING_DELTA) 101 | 102 | #define ALL_CHANNELS_ID UINT32_MAX 103 | 104 | // Macros to assist with pin instance counting 105 | #define VERIFY_PIN_INSTANCE_RESOURCES_AVAILABLE(status, allocated, max) \ 106 | status = (allocated < max) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES 107 | 108 | #define ALLOCATE_PIN_INSTANCE_RESOURCES(allocated) \ 109 | allocated++ 110 | 111 | #define FREE_PIN_INSTANCE_RESOURCES(allocated) \ 112 | allocated-- 113 | 114 | // Define the value data type for supported sound detector patterns. Only 115 | // one pattern type is supported in this sample. 116 | typedef struct { 117 | KSMULTIPLE_ITEM MultipleItem; 118 | GUID PatternType[1]; 119 | } CONTOSO_SUPPORTEDPATTERNSVALUE; 120 | 121 | //============================================================================= 122 | // Typedefs 123 | //============================================================================= 124 | 125 | // Flags to identify stream processing mode 126 | typedef enum { 127 | CONNECTIONTYPE_TOPOLOGY_OUTPUT = 0, 128 | CONNECTIONTYPE_WAVE_OUTPUT = 1 129 | } CONNECTIONTYPE; 130 | 131 | // Connection table for registering topology/wave bridge connection 132 | typedef struct _PHYSICALCONNECTIONTABLE 133 | { 134 | ULONG ulTopology; 135 | ULONG ulWave; 136 | CONNECTIONTYPE eType; 137 | } PHYSICALCONNECTIONTABLE, *PPHYSICALCONNECTIONTABLE; 138 | 139 | // 140 | // This is the structure of the portclass FDO device extension Nt has created 141 | // for us. We keep the adapter common object here. 142 | // 143 | struct IAdapterCommon; 144 | typedef struct _PortClassDeviceContext // 32 64 Byte offsets for 32 and 64 bit architectures 145 | { 146 | ULONG_PTR m_pulReserved1[2]; // 0-7 0-15 First two pointers are reserved. 147 | PDEVICE_OBJECT m_DoNotUsePhysicalDeviceObject; // 8-11 16-23 Reserved pointer to our Physical Device Object (PDO). 148 | PVOID m_pvReserved2; // 12-15 24-31 Reserved pointer to our Start Device function. 149 | PVOID m_pvReserved3; // 16-19 32-39 "Out Memory" according to DDK. 150 | IAdapterCommon* m_pCommon; // 20-23 40-47 Pointer to our adapter common object. 151 | PVOID m_pvUnused1; // 24-27 48-55 Unused space. 152 | PVOID m_pvUnused2; // 28-31 56-63 Unused space. 153 | 154 | // Anything after above line should not be used. 155 | // This actually goes on for (64*sizeof(ULONG_PTR)) but it is all opaque. 156 | } PortClassDeviceContext; 157 | 158 | // 159 | // Major/MinorTarget to object casting. 160 | // 161 | #define MajorTarget_to_Obj(ptr) \ 162 | reinterpret_cast(ptr) 163 | 164 | #define MinorTarget_to_Obj(ptr) \ 165 | static_cast(reinterpret_cast(ptr)) 166 | 167 | // 168 | // Global settings. 169 | // 170 | extern DWORD g_DoNotCreateDataFiles; 171 | extern DWORD g_DisableBthScoBypass; 172 | extern UNICODE_STRING g_RegistryPath; 173 | 174 | //============================================================================= 175 | // Function prototypes 176 | //============================================================================= 177 | 178 | // Generic topology handler 179 | NTSTATUS PropertyHandler_Topology 180 | ( 181 | _In_ PPCPROPERTY_REQUEST PropertyRequest 182 | ); 183 | 184 | // Default WaveFilter automation table. 185 | // Handles the GeneralComponentId request. 186 | NTSTATUS PropertyHandler_WaveFilter 187 | ( 188 | _In_ PPCPROPERTY_REQUEST PropertyRequest 189 | ); 190 | 191 | NTSTATUS PropertyHandler_GenericPin 192 | ( 193 | _In_ PPCPROPERTY_REQUEST PropertyRequest 194 | ); 195 | 196 | // common.h uses some of the above definitions. 197 | #include "common.h" 198 | #include "kshelper.h" 199 | 200 | #endif // _CSAUDIOSSTCATPT_DEFINITIONS_H_ 201 | -------------------------------------------------------------------------------- /csaudiosstcatpt.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 16 3 | VisualStudioVersion = 16.0.30503.244 4 | MinimumVisualStudioVersion = 12.0 5 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Package", "Package", "{FA56D96B-290B-4C73-A5E1-02C1861D3224}" 6 | EndProject 7 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Filters", "Filters", "{952A7CB1-E516-44AA-AC38-4AEED9874C41}" 8 | EndProject 9 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Utilities", "Utilities", "{0B4B8E51-20A8-43A4-A8DA-42FF90D628AC}" 10 | EndProject 11 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Inc", "Inc", "{C65091AE-E5B7-4359-8984-55852792406E}" 12 | EndProject 13 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Main", "Main", "{C06F6070-75EE-4F57-8D35-4AC2AB08D029}" 14 | EndProject 15 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "package", "Package\package.VcxProj", "{830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}" 16 | EndProject 17 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Filters", "Source\Filters\Filters.vcxproj", "{771312CF-E5A2-4676-8142-86CEBDF99E2B}" 18 | EndProject 19 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Utilities", "Source\Utilities\Utilities.vcxproj", "{33E61864-6F2C-4F9F-BE70-8F8985A4F283}" 20 | EndProject 21 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Inc", "Source\Inc\Inc.vcxproj", "{4B664BA5-057A-41B8-B365-2C99065C4DFA}" 22 | EndProject 23 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Main", "Source\Main\Main.vcxproj", "{E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}" 24 | ProjectSection(ProjectDependencies) = postProject 25 | {33E61864-6F2C-4F9F-BE70-8F8985A4F283} = {33E61864-6F2C-4F9F-BE70-8F8985A4F283} 26 | {771312CF-E5A2-4676-8142-86CEBDF99E2B} = {771312CF-E5A2-4676-8142-86CEBDF99E2B} 27 | EndProjectSection 28 | EndProject 29 | Global 30 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 31 | Debug|ARM64 = Debug|ARM64 32 | Debug|Win32 = Debug|Win32 33 | Debug|x64 = Debug|x64 34 | Release|ARM64 = Release|ARM64 35 | Release|Win32 = Release|Win32 36 | Release|x64 = Release|x64 37 | EndGlobalSection 38 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 39 | {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|ARM64.ActiveCfg = Debug|ARM64 40 | {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|ARM64.Build.0 = Debug|ARM64 41 | {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|Win32.ActiveCfg = Debug|Win32 42 | {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|Win32.Build.0 = Debug|Win32 43 | {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|x64.ActiveCfg = Debug|x64 44 | {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Debug|x64.Build.0 = Debug|x64 45 | {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|ARM64.ActiveCfg = Release|ARM64 46 | {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|ARM64.Build.0 = Release|ARM64 47 | {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|Win32.ActiveCfg = Release|Win32 48 | {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|Win32.Build.0 = Release|Win32 49 | {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|x64.ActiveCfg = Release|x64 50 | {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A}.Release|x64.Build.0 = Release|x64 51 | {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|ARM64.ActiveCfg = Debug|ARM64 52 | {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|ARM64.Build.0 = Debug|ARM64 53 | {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|Win32.ActiveCfg = Debug|Win32 54 | {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|Win32.Build.0 = Debug|Win32 55 | {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|x64.ActiveCfg = Debug|x64 56 | {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Debug|x64.Build.0 = Debug|x64 57 | {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|ARM64.ActiveCfg = Release|ARM64 58 | {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|ARM64.Build.0 = Release|ARM64 59 | {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|Win32.ActiveCfg = Release|Win32 60 | {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|Win32.Build.0 = Release|Win32 61 | {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|x64.ActiveCfg = Release|x64 62 | {771312CF-E5A2-4676-8142-86CEBDF99E2B}.Release|x64.Build.0 = Release|x64 63 | {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|ARM64.ActiveCfg = Debug|ARM64 64 | {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|ARM64.Build.0 = Debug|ARM64 65 | {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|Win32.ActiveCfg = Debug|Win32 66 | {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|Win32.Build.0 = Debug|Win32 67 | {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|x64.ActiveCfg = Debug|x64 68 | {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Debug|x64.Build.0 = Debug|x64 69 | {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|ARM64.ActiveCfg = Release|ARM64 70 | {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|ARM64.Build.0 = Release|ARM64 71 | {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|Win32.ActiveCfg = Release|Win32 72 | {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|Win32.Build.0 = Release|Win32 73 | {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|x64.ActiveCfg = Release|x64 74 | {33E61864-6F2C-4F9F-BE70-8F8985A4F283}.Release|x64.Build.0 = Release|x64 75 | {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|ARM64.ActiveCfg = Debug|ARM64 76 | {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|ARM64.Build.0 = Debug|ARM64 77 | {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|Win32.ActiveCfg = Debug|Win32 78 | {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|Win32.Build.0 = Debug|Win32 79 | {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|x64.ActiveCfg = Debug|x64 80 | {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Debug|x64.Build.0 = Debug|x64 81 | {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|ARM64.ActiveCfg = Release|ARM64 82 | {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|ARM64.Build.0 = Release|ARM64 83 | {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|Win32.ActiveCfg = Release|Win32 84 | {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|Win32.Build.0 = Release|Win32 85 | {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|x64.ActiveCfg = Release|x64 86 | {4B664BA5-057A-41B8-B365-2C99065C4DFA}.Release|x64.Build.0 = Release|x64 87 | {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|ARM64.ActiveCfg = Debug|ARM64 88 | {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|ARM64.Build.0 = Debug|ARM64 89 | {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|Win32.ActiveCfg = Debug|Win32 90 | {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|Win32.Build.0 = Debug|Win32 91 | {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|x64.ActiveCfg = Debug|x64 92 | {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Debug|x64.Build.0 = Debug|x64 93 | {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|ARM64.ActiveCfg = Release|ARM64 94 | {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|ARM64.Build.0 = Release|ARM64 95 | {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|Win32.ActiveCfg = Release|Win32 96 | {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|Win32.Build.0 = Release|Win32 97 | {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|x64.ActiveCfg = Release|x64 98 | {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF}.Release|x64.Build.0 = Release|x64 99 | EndGlobalSection 100 | GlobalSection(SolutionProperties) = preSolution 101 | HideSolutionNode = FALSE 102 | EndGlobalSection 103 | GlobalSection(NestedProjects) = preSolution 104 | {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A} = {FA56D96B-290B-4C73-A5E1-02C1861D3224} 105 | {771312CF-E5A2-4676-8142-86CEBDF99E2B} = {952A7CB1-E516-44AA-AC38-4AEED9874C41} 106 | {33E61864-6F2C-4F9F-BE70-8F8985A4F283} = {0B4B8E51-20A8-43A4-A8DA-42FF90D628AC} 107 | {4B664BA5-057A-41B8-B365-2C99065C4DFA} = {C65091AE-E5B7-4359-8984-55852792406E} 108 | {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF} = {C06F6070-75EE-4F57-8D35-4AC2AB08D029} 109 | EndGlobalSection 110 | GlobalSection(ExtensibilityGlobals) = postSolution 111 | SolutionGuid = {6DB4FE19-4FE0-4DC4-B898-C46E01E6BDF4} 112 | EndGlobalSection 113 | EndGlobal 114 | -------------------------------------------------------------------------------- /Package/package.VcxProj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | ARM64 7 | 8 | 9 | Debug 10 | Win32 11 | 12 | 13 | Release 14 | ARM64 15 | 16 | 17 | Release 18 | Win32 19 | 20 | 21 | Debug 22 | x64 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | 30 | 31 | {E4DF0EEE-D35B-47F2-A9B1-41EA97C465FF} 32 | true 33 | false 34 | 35 | 36 | 37 | WindowsKernelModeDriver10.0 38 | Utility 39 | Package 40 | true 41 | Debug 42 | 43 | 44 | 45 | {830B14D5-0E32-4F9E-AEFA-4C9F6FC13C2A} 46 | {E9D167E6-E633-4284-8F02-FF86DF3B6D7F} 47 | $(MSBuildProjectName) 48 | 49 | 50 | Windows10 51 | true 52 | 53 | 54 | Windows10 55 | false 56 | 57 | 58 | Windows10 59 | true 60 | 61 | 62 | Windows10 63 | true 64 | 65 | 66 | Windows10 67 | false 68 | 69 | 70 | Windows10 71 | false 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | DbgengKernelDebugger 83 | False 84 | None 85 | 86 | 87 | 88 | 89 | 90 | %PathToInf% 91 | False 92 | False 93 | True 94 | 95 | 133563 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | sha256 105 | 106 | 107 | cmd /k mkdir "$(Inf2CatSource)" && copy "$(SolutionDir)Source\Main\$(IntDir)IntcSST2.bin" "$(Inf2CatSource)" 108 | 109 | 110 | 111 | 112 | sha256 113 | 114 | 115 | cmd /k mkdir "$(Inf2CatSource)" && copy "$(SolutionDir)Source\Main\$(IntDir)IntcSST2.bin" "$(Inf2CatSource)" 116 | 117 | 118 | 119 | 120 | sha256 121 | 122 | 123 | cmd /k mkdir "$(Inf2CatSource)" && copy "$(SolutionDir)Source\Main\$(IntDir)IntcSST2.bin" "$(Inf2CatSource)" 124 | 125 | 126 | 127 | 128 | sha256 129 | 130 | 131 | cmd /k mkdir "$(Inf2CatSource)" && copy "$(SolutionDir)Source\Main\$(IntDir)IntcSST2.bin" "$(Inf2CatSource)" 132 | 133 | 134 | 135 | 136 | sha256 137 | 138 | 139 | cmd /k mkdir "$(Inf2CatSource)" && copy "$(SolutionDir)Source\Main\$(IntDir)IntcSST2.bin" "$(Inf2CatSource)" 140 | 141 | 142 | 143 | 144 | sha256 145 | 146 | 147 | cmd /k mkdir "$(Inf2CatSource)" && copy "$(SolutionDir)Source\Main\$(IntDir)IntcSST2.bin" "$(Inf2CatSource)" 148 | 149 | 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /Source/Utilities/messages.cpp: -------------------------------------------------------------------------------- 1 | #include "definitions.h" 2 | #include "hw.h" 3 | #include "messages.h" 4 | #include "resource.h" 5 | #include 6 | 7 | #include 8 | struct catpt_alloc_stream_input { 9 | enum catpt_path_id path_id :8; 10 | enum catpt_stream_type stream_type :8; 11 | enum catpt_format_id format_id :8; 12 | //UINT8 reserved; (for GCC/clang only) 13 | struct catpt_audio_format input_format; 14 | struct catpt_ring_info ring_info; 15 | UINT8 num_entries; 16 | /* flex array with entries here */ 17 | struct catpt_memory_info persistent_mem; 18 | struct catpt_memory_info scratch_mem; 19 | UINT32 num_notifications; /* obsolete */ 20 | }; 21 | #include 22 | 23 | NTSTATUS CCsAudioCatptSSTHW::ipc_alloc_stream( 24 | enum catpt_path_id path_id, 25 | enum catpt_stream_type type, 26 | struct catpt_audio_format* afmt, 27 | struct catpt_ring_info* rinfo, 28 | UINT8 num_modules, 29 | struct catpt_module_entry* mods, 30 | PRESOURCE persistent, 31 | struct catpt_stream_info* sinfo 32 | ) { 33 | union catpt_global_msg msg = CATPT_GLOBAL_MSG(ALLOCATE_STREAM); 34 | struct catpt_alloc_stream_input input; 35 | struct catpt_ipc_msg request, reply; 36 | size_t size, arrsz; 37 | UINT8* payload; 38 | UINT32 off; 39 | NTSTATUS status; 40 | 41 | off = offsetof(struct catpt_alloc_stream_input, persistent_mem); 42 | arrsz = sizeof(*mods) * num_modules; 43 | size = sizeof(input) + arrsz; 44 | 45 | payload = (UINT8 *)ExAllocatePoolZero(NonPagedPool, size, CSAUDIOCATPTSST_POOLTAG); 46 | if (!payload) { 47 | return STATUS_NO_MEMORY; 48 | } 49 | 50 | RtlZeroMemory(&input, sizeof(input)); 51 | input.path_id = path_id; 52 | input.stream_type = type; 53 | input.format_id = CATPT_FORMAT_PCM; 54 | input.input_format = *afmt; 55 | input.ring_info = *rinfo; 56 | input.num_entries = num_modules; 57 | input.persistent_mem.offset = (UINT32)catpt_to_dsp_offset(persistent->start); 58 | input.persistent_mem.size = (UINT32)resource_size(persistent); 59 | if (scratch) { 60 | input.scratch_mem.offset = (UINT32)catpt_to_dsp_offset(scratch->start); 61 | input.scratch_mem.size = (UINT32)resource_size(scratch); 62 | } 63 | 64 | /* re-arrange the input: account for flex array 'entries' */ 65 | memcpy(payload, &input, sizeof(input)); 66 | memmove(payload + off + arrsz, payload + off, sizeof(input) - off); 67 | memcpy(payload + off, mods, arrsz); 68 | 69 | request.header = msg.val; 70 | request.size = size; 71 | request.data = payload; 72 | reply.size = sizeof(*sinfo); 73 | reply.data = sinfo; 74 | 75 | status = ipc_send_msg(request, &reply, CATPT_IPC_TIMEOUT_MS); 76 | if (!NT_SUCCESS(status)) { 77 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "alloc stream type %d failed 0x%x\n", type, status); 78 | } 79 | ExFreePoolWithTag(payload, CSAUDIOCATPTSST_POOLTAG); 80 | return status; 81 | } 82 | 83 | NTSTATUS CCsAudioCatptSSTHW::ipc_free_stream(UINT8 stream_hw_id) 84 | { 85 | union catpt_global_msg msg = CATPT_GLOBAL_MSG(FREE_STREAM); 86 | struct catpt_ipc_msg request; 87 | NTSTATUS status; 88 | 89 | request.header = msg.val; 90 | request.size = sizeof(stream_hw_id); 91 | request.data = &stream_hw_id; 92 | 93 | status = ipc_send_msg(request, NULL, CATPT_IPC_TIMEOUT_MS); 94 | if (!NT_SUCCESS(status)) { 95 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "free stream %d failed: %d\n", 96 | stream_hw_id, status); 97 | } 98 | 99 | return status; 100 | } 101 | 102 | NTSTATUS CCsAudioCatptSSTHW::ipc_set_device_format(struct catpt_ssp_device_format* devfmt) 103 | { 104 | union catpt_global_msg msg = CATPT_GLOBAL_MSG(SET_DEVICE_FORMATS); 105 | struct catpt_ipc_msg request; 106 | NTSTATUS status; 107 | 108 | request.header = msg.val; 109 | request.size = sizeof(*devfmt); 110 | request.data = devfmt; 111 | 112 | status = ipc_send_msg(request, NULL, CATPT_IPC_TIMEOUT_MS); 113 | if (!NT_SUCCESS(status)) { 114 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "set device format failed: %d\n", status); 115 | } 116 | 117 | return status; 118 | } 119 | 120 | #include 121 | struct catpt_set_volume_input { 122 | UINT32 channel; 123 | UINT32 target_volume; 124 | UINT64 curve_duration; 125 | UINT32 curve_type; 126 | }; 127 | #include 128 | 129 | NTSTATUS CCsAudioCatptSSTHW::ipc_set_volume(UINT8 stream_hw_id, 130 | UINT32 channel, UINT32 volume, 131 | UINT32 curve_duration, 132 | enum catpt_audio_curve_type curve_type) 133 | { 134 | union catpt_stream_msg msg = CATPT_STAGE_MSG(SET_VOLUME); 135 | struct catpt_ipc_msg request; 136 | struct catpt_set_volume_input input; 137 | NTSTATUS status; 138 | 139 | msg.stream_hw_id = stream_hw_id; 140 | input.channel = channel; 141 | input.target_volume = volume; 142 | input.curve_duration = curve_duration; 143 | input.curve_type = curve_type; 144 | 145 | request.header = msg.val; 146 | request.size = sizeof(input); 147 | request.data = &input; 148 | 149 | status = ipc_send_msg(request, NULL, CATPT_IPC_TIMEOUT_MS); 150 | if (!NT_SUCCESS(status)) { 151 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "set stream %d volume failed: 0x%x\n", 152 | stream_hw_id, status); 153 | } 154 | 155 | return status; 156 | } 157 | 158 | #include 159 | struct catpt_set_write_pos_input { 160 | UINT32 new_write_pos; 161 | bool end_of_buffer; 162 | bool low_latency; 163 | }; 164 | #include 165 | 166 | NTSTATUS CCsAudioCatptSSTHW::ipc_set_write_pos(UINT8 stream_hw_id, 167 | UINT32 pos, bool eob, bool ll) 168 | { 169 | union catpt_stream_msg msg = CATPT_STAGE_MSG(SET_WRITE_POSITION); 170 | struct catpt_ipc_msg request; 171 | struct catpt_set_write_pos_input input; 172 | NTSTATUS status; 173 | 174 | msg.stream_hw_id = stream_hw_id; 175 | input.new_write_pos = pos; 176 | input.end_of_buffer = eob; 177 | input.low_latency = ll; 178 | 179 | request.header = msg.val; 180 | request.size = sizeof(input); 181 | request.data = &input; 182 | 183 | status = ipc_send_msg(request, NULL, CATPT_IPC_TIMEOUT_MS); 184 | if (!NT_SUCCESS(status)) { 185 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "set stream %d write pos failed: 0x%x\n", 186 | stream_hw_id, status); 187 | } 188 | 189 | return status; 190 | } 191 | 192 | NTSTATUS CCsAudioCatptSSTHW::ipc_reset_stream(UINT8 stream_hw_id) 193 | { 194 | union catpt_stream_msg msg = CATPT_STREAM_MSG(RESET_STREAM); 195 | struct catpt_ipc_msg request = { {0} }; 196 | NTSTATUS status; 197 | 198 | msg.stream_hw_id = stream_hw_id; 199 | request.header = msg.val; 200 | 201 | status = ipc_send_msg(request, NULL, CATPT_IPC_TIMEOUT_MS); 202 | if (!NT_SUCCESS(status)) { 203 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "reset stream %d failed : 0x%x\n", 204 | stream_hw_id, status); 205 | } 206 | 207 | return status; 208 | } 209 | 210 | NTSTATUS CCsAudioCatptSSTHW::ipc_pause_stream(UINT8 stream_hw_id) 211 | { 212 | union catpt_stream_msg msg = CATPT_STREAM_MSG(PAUSE_STREAM); 213 | struct catpt_ipc_msg request = { {0} }; 214 | NTSTATUS status; 215 | 216 | msg.stream_hw_id = stream_hw_id; 217 | request.header = msg.val; 218 | 219 | status = ipc_send_msg(request, NULL, CATPT_IPC_TIMEOUT_MS); 220 | if (!NT_SUCCESS(status)) { 221 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "pause stream %d failed : 0x%x\n", 222 | stream_hw_id, status); 223 | } 224 | 225 | return status; 226 | } 227 | 228 | NTSTATUS CCsAudioCatptSSTHW::ipc_resume_stream(UINT8 stream_hw_id) 229 | { 230 | union catpt_stream_msg msg = CATPT_STREAM_MSG(RESUME_STREAM); 231 | struct catpt_ipc_msg request = { {0} }; 232 | NTSTATUS status; 233 | 234 | msg.stream_hw_id = stream_hw_id; 235 | request.header = msg.val; 236 | 237 | status = ipc_send_msg(request, NULL, CATPT_IPC_TIMEOUT_MS); 238 | if (!NT_SUCCESS(status)) { 239 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "resume stream %d failed : 0x%x\n", 240 | stream_hw_id, status); 241 | } 242 | 243 | return status; 244 | } -------------------------------------------------------------------------------- /Source/Filters/speakerwavtable.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | speakerwavtable.h 8 | 9 | Abstract: 10 | 11 | Declaration of wave miniport tables for the render endpoints. 12 | --*/ 13 | 14 | #ifndef _CSAUDIOSSTCATPT_SPEAKERWAVTABLE_H_ 15 | #define _CSAUDIOSSTCATPT_SPEAKERWAVTABLE_H_ 16 | 17 | // To keep the code simple assume device supports only 48KHz, 16-bit, stereo (PCM and NON-PCM) 18 | 19 | #define SPEAKER_DEVICE_MAX_CHANNELS 2 // Max Channels. 20 | 21 | #define SPEAKER_HOST_MAX_CHANNELS 2 // Max Channels. 22 | #define SPEAKER_HOST_MIN_BITS_PER_SAMPLE 16 // Min Bits Per Sample 23 | #define SPEAKER_HOST_MAX_BITS_PER_SAMPLE 16 // Max Bits Per Sample 24 | #define SPEAKER_HOST_MIN_SAMPLE_RATE 48000 // Min Sample Rate 25 | #define SPEAKER_HOST_MAX_SAMPLE_RATE 48000 // Max Sample Rate 26 | 27 | // 28 | // Max # of pin instances. 29 | // 30 | #define SPEAKER_MAX_INPUT_SYSTEM_STREAMS 1 31 | 32 | //============================================================================= 33 | 34 | static 35 | KSDATAFORMAT_WAVEFORMATEXTENSIBLE SpeakerHostPinSupportedDeviceFormats[] = 36 | { 37 | { // 0 38 | { 39 | sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), 40 | 0, 41 | 0, 42 | 0, 43 | STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), 44 | STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), 45 | STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) 46 | }, 47 | { 48 | { 49 | WAVE_FORMAT_EXTENSIBLE, 50 | 2, 51 | 48000, 52 | 192000, 53 | 4, 54 | 16, 55 | sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) 56 | }, 57 | 16, 58 | KSAUDIO_SPEAKER_STEREO, 59 | STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) 60 | } 61 | } 62 | }; 63 | 64 | // 65 | // Supported modes (only on streaming pins). 66 | // 67 | static 68 | MODE_AND_DEFAULT_FORMAT SpeakerHostPinSupportedDeviceModes[] = 69 | { 70 | { 71 | STATIC_AUDIO_SIGNALPROCESSINGMODE_DEFAULT, 72 | &SpeakerHostPinSupportedDeviceFormats[0].DataFormat // 48KHz 73 | } 74 | }; 75 | 76 | // 77 | // The entries here must follow the same order as the filter's pin 78 | // descriptor array. 79 | // 80 | static 81 | PIN_DEVICE_FORMATS_AND_MODES SpeakerPinDeviceFormatsAndModes[] = 82 | { 83 | { 84 | SystemRenderPin, 85 | SpeakerHostPinSupportedDeviceFormats, 86 | SIZEOF_ARRAY(SpeakerHostPinSupportedDeviceFormats), 87 | SpeakerHostPinSupportedDeviceModes, 88 | SIZEOF_ARRAY(SpeakerHostPinSupportedDeviceModes) 89 | }, 90 | { 91 | BridgePin, 92 | NULL, 93 | 0, 94 | NULL, 95 | 0 96 | } 97 | }; 98 | 99 | //============================================================================= 100 | static 101 | KSDATARANGE_AUDIO SpeakerPinDataRangesStream[] = 102 | { 103 | { // 0 104 | { 105 | sizeof(KSDATARANGE_AUDIO), 106 | KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range 107 | 0, 108 | 0, 109 | STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), 110 | STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), 111 | STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) 112 | }, 113 | SPEAKER_HOST_MAX_CHANNELS, 114 | SPEAKER_HOST_MIN_BITS_PER_SAMPLE, 115 | SPEAKER_HOST_MAX_BITS_PER_SAMPLE, 116 | SPEAKER_HOST_MIN_SAMPLE_RATE, 117 | SPEAKER_HOST_MAX_SAMPLE_RATE 118 | } 119 | }; 120 | 121 | static 122 | PKSDATARANGE SpeakerPinDataRangePointersStream[] = 123 | { 124 | PKSDATARANGE(&SpeakerPinDataRangesStream[0]), 125 | PKSDATARANGE(&PinDataRangeAttributeList), 126 | }; 127 | 128 | //============================================================================= 129 | static 130 | KSDATARANGE SpeakerPinDataRangesBridge[] = 131 | { 132 | { 133 | sizeof(KSDATARANGE), 134 | 0, 135 | 0, 136 | 0, 137 | STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), 138 | STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG), 139 | STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE) 140 | } 141 | }; 142 | 143 | static 144 | PKSDATARANGE SpeakerPinDataRangePointersBridge[] = 145 | { 146 | &SpeakerPinDataRangesBridge[0] 147 | }; 148 | 149 | //============================================================================= 150 | static 151 | PCPIN_DESCRIPTOR SpeakerWaveMiniportPins[] = 152 | { 153 | // Wave Out Streaming Pin (Renderer) KSPIN_WAVE_RENDER3_SINK_SYSTEM 154 | { 155 | SPEAKER_MAX_INPUT_SYSTEM_STREAMS, 156 | SPEAKER_MAX_INPUT_SYSTEM_STREAMS, 157 | 0, 158 | NULL, // AutomationTable 159 | { 160 | 0, 161 | NULL, 162 | 0, 163 | NULL, 164 | SIZEOF_ARRAY(SpeakerPinDataRangePointersStream), 165 | SpeakerPinDataRangePointersStream, 166 | KSPIN_DATAFLOW_IN, 167 | KSPIN_COMMUNICATION_SINK, 168 | &KSCATEGORY_AUDIO, 169 | NULL, 170 | 0 171 | } 172 | }, 173 | // Wave Out Bridge Pin (Renderer) KSPIN_WAVE_RENDER3_SOURCE 174 | { 175 | 0, 176 | 0, 177 | 0, 178 | NULL, 179 | { 180 | 0, 181 | NULL, 182 | 0, 183 | NULL, 184 | SIZEOF_ARRAY(SpeakerPinDataRangePointersBridge), 185 | SpeakerPinDataRangePointersBridge, 186 | KSPIN_DATAFLOW_OUT, 187 | KSPIN_COMMUNICATION_NONE, 188 | &KSCATEGORY_AUDIO, 189 | NULL, 190 | 0 191 | } 192 | }, 193 | }; 194 | 195 | //============================================================================= 196 | // 197 | // ---------------------------- 198 | // | | 199 | // Host Pin 0-->| |--> 1 KSPIN_WAVE_RENDER3_SOURCE 200 | // | | 201 | // ---------------------------- 202 | static 203 | PCCONNECTION_DESCRIPTOR SpeakerWaveMiniportConnections[] = 204 | { 205 | { PCFILTER_NODE, KSPIN_WAVE_RENDER3_SINK_SYSTEM, PCFILTER_NODE, KSPIN_WAVE_RENDER3_SOURCE } 206 | }; 207 | 208 | //============================================================================= 209 | static 210 | PCPROPERTY_ITEM PropertiesSpeakerWaveFilter[] = 211 | { 212 | { 213 | &KSPROPSETID_Pin, 214 | KSPROPERTY_PIN_PROPOSEDATAFORMAT, 215 | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, 216 | PropertyHandler_WaveFilter 217 | }, 218 | { 219 | &KSPROPSETID_Pin, 220 | KSPROPERTY_PIN_PROPOSEDATAFORMAT2, 221 | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, 222 | PropertyHandler_WaveFilter 223 | } 224 | }; 225 | 226 | DEFINE_PCAUTOMATION_TABLE_PROP(AutomationSpeakerWaveFilter, PropertiesSpeakerWaveFilter); 227 | 228 | //============================================================================= 229 | static 230 | PCFILTER_DESCRIPTOR SpeakerWaveMiniportFilterDescriptor = 231 | { 232 | 0, // Version 233 | &AutomationSpeakerWaveFilter, // AutomationTable 234 | sizeof(PCPIN_DESCRIPTOR), // PinSize 235 | SIZEOF_ARRAY(SpeakerWaveMiniportPins), // PinCount 236 | SpeakerWaveMiniportPins, // Pins 237 | sizeof(PCNODE_DESCRIPTOR), // NodeSize 238 | 0, // NodeCount 239 | NULL, // Nodes 240 | SIZEOF_ARRAY(SpeakerWaveMiniportConnections), // ConnectionCount 241 | SpeakerWaveMiniportConnections, // Connections 242 | 0, // CategoryCount 243 | NULL // Categories - use defaults (audio, render, capture) 244 | }; 245 | 246 | #endif // _CSAUDIOSSTCATPT_SPEAKERWAVTABLE_H_ 247 | -------------------------------------------------------------------------------- /Source/Utilities/pcm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "definitions.h" 3 | #include "hw.h" 4 | #include "messages.h" 5 | #include "resource.h" 6 | 7 | struct catpt_stream_template { 8 | enum catpt_path_id path_id; 9 | enum catpt_stream_type type; 10 | UINT32 persistent_size; 11 | UINT8 num_entries; 12 | struct catpt_module_entry entries[1]; 13 | }; 14 | 15 | static struct catpt_stream_template system_pb = { 16 | .path_id = CATPT_PATH_SSP0_OUT, 17 | .type = CATPT_STRM_TYPE_SYSTEM, 18 | .num_entries = 1, 19 | .entries = {{ CATPT_MODID_PCM_SYSTEM, 0 }}, 20 | }; 21 | 22 | static struct catpt_stream_template system_cp = { 23 | .path_id = CATPT_PATH_SSP0_IN, 24 | .type = CATPT_STRM_TYPE_CAPTURE, 25 | .num_entries = 1, 26 | .entries = {{ CATPT_MODID_PCM_CAPTURE, 0 }}, 27 | }; 28 | 29 | static struct catpt_stream_template offload_pb = { 30 | .path_id = CATPT_PATH_SSP0_OUT, 31 | .type = CATPT_STRM_TYPE_RENDER, 32 | .num_entries = 1, 33 | .entries = {{ CATPT_MODID_PCM, 0 }}, 34 | }; 35 | 36 | static struct catpt_stream_template loopback_cp = { 37 | .path_id = CATPT_PATH_SSP0_OUT, 38 | .type = CATPT_STRM_TYPE_LOOPBACK, 39 | .num_entries = 1, 40 | .entries = {{ CATPT_MODID_PCM_REFERENCE, 0 }}, 41 | }; 42 | 43 | static struct catpt_stream_template bluetooth_pb = { 44 | .path_id = CATPT_PATH_SSP1_OUT, 45 | .type = CATPT_STRM_TYPE_BLUETOOTH_RENDER, 46 | .num_entries = 1, 47 | .entries = {{ CATPT_MODID_BLUETOOTH_RENDER, 0 }}, 48 | }; 49 | 50 | static struct catpt_stream_template bluetooth_cp = { 51 | .path_id = CATPT_PATH_SSP1_IN, 52 | .type = CATPT_STRM_TYPE_BLUETOOTH_CAPTURE, 53 | .num_entries = 1, 54 | .entries = {{ CATPT_MODID_BLUETOOTH_CAPTURE, 0 }}, 55 | }; 56 | 57 | static struct catpt_stream_template* catpt_topology[] = { 58 | /*[CATPT_STRM_TYPE_RENDER] =*/ &offload_pb, 59 | /*[CATPT_STRM_TYPE_SYSTEM] =*/ &system_pb, 60 | /*[CATPT_STRM_TYPE_CAPTURE] =*/ &system_cp, 61 | /*[CATPT_STRM_TYPE_LOOPBACK] =*/ &loopback_cp, 62 | /*[CATPT_STRM_TYPE_BLUETOOTH_RENDER] =*/ &bluetooth_pb, 63 | /*[CATPT_STRM_TYPE_BLUETOOTH_CAPTURE] =*/ &bluetooth_cp, 64 | }; 65 | 66 | NTSTATUS CCsAudioCatptSSTHW::catpt_arm_stream_templates() 67 | { 68 | PRESOURCE res; 69 | UINT32 scratch_size = 0; 70 | int i, j; 71 | 72 | for (i = 0; i < sizeof(catpt_topology) / sizeof(struct catpt_stream_template *); i++) { 73 | struct catpt_stream_template* templ; 74 | struct catpt_module_entry* entry; 75 | struct catpt_module_type* type; 76 | 77 | templ = catpt_topology[i]; 78 | templ->persistent_size = 0; 79 | 80 | for (j = 0; j < templ->num_entries; j++) { 81 | entry = &templ->entries[j]; 82 | type = &this->modules[entry->module_id]; 83 | 84 | if (!type->loaded) 85 | return STATUS_NOT_FOUND; 86 | 87 | entry->entry_point = type->entry_point; 88 | templ->persistent_size += type->persistent_size; 89 | if (type->scratch_size > scratch_size) 90 | scratch_size = type->scratch_size; 91 | } 92 | } 93 | 94 | if (scratch_size) { 95 | /* allocate single scratch area for all modules */ 96 | res = catpt_request_region(&this->dram, scratch_size); 97 | if (!res) 98 | return STATUS_DEVICE_BUSY; 99 | this->scratch = res; 100 | } 101 | 102 | return 0; 103 | } 104 | 105 | struct catpt_stream* CCsAudioCatptSSTHW::catpt_stream_find(UINT8 stream_hw_id) 106 | { 107 | if (this->outStream.info.stream_hw_id == stream_hw_id) { 108 | return &this->outStream; 109 | } 110 | if (this->inStream.info.stream_hw_id == stream_hw_id) { 111 | return &this->inStream; 112 | } 113 | return NULL; 114 | } 115 | 116 | NTSTATUS CCsAudioCatptSSTHW::sst_program_dma(eDeviceType deviceType, UINT32 byteCount, PMDL mdl, IPortWaveRTStream* waveStream) { 117 | #if USESSTHW 118 | NTSTATUS status; 119 | 120 | catpt_stream* stream; 121 | 122 | CatPtPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "Programming stream %d\n", deviceType); 123 | 124 | switch (deviceType) { 125 | case eSpeakerDevice: 126 | stream = &this->outStream; 127 | stream->templ = &system_pb; 128 | break; 129 | case eMicJackDevice: 130 | stream = &this->inStream; 131 | stream->templ = &system_cp; 132 | break; 133 | default: 134 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "Unknown device type"); 135 | return STATUS_INVALID_PARAMETER; 136 | } 137 | 138 | if (stream->allocated) { 139 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "%s: Already have stream for %d\n", __func__, deviceType); 140 | return STATUS_INVALID_PARAMETER; 141 | } 142 | 143 | LONG volMax[CATPT_CHANNELS_MAX] = { 0, 0, 0, 0 }; 144 | 145 | int pageCount = waveStream->GetPhysicalPagesCount(mdl); 146 | if (pageCount < 1) { 147 | return STATUS_NO_MEMORY; 148 | } 149 | 150 | PHYSICAL_ADDRESS highAddr; 151 | highAddr.QuadPart = MAXULONG; 152 | 153 | UINT8* pageTable = (UINT8*)stream->pageTable; 154 | if (!pageTable) { 155 | stream->pageTable = MmAllocateContiguousMemory(PAGE_SIZE, highAddr); 156 | pageTable = (UINT8*)stream->pageTable; 157 | } 158 | if (!pageTable) { 159 | return STATUS_NO_MEMORY; 160 | } 161 | 162 | RtlZeroMemory(pageTable, PAGE_SIZE); 163 | for (int i = 0; i < pageCount; i++) { 164 | PHYSICAL_ADDRESS address = waveStream->GetPhysicalPageAddress(mdl, i); 165 | LONGLONG addrVal = address.QuadPart; 166 | 167 | UINT32 pfn = (UINT32)(addrVal >> 12); 168 | UINT32 offset = ((i << 2) + i) >> 1; 169 | 170 | UINT32* page_table = (UINT32*)(pageTable + offset); 171 | if (i & 1) 172 | *page_table |= (pfn << 4); 173 | else 174 | *page_table |= pfn; 175 | } 176 | 177 | PHYSICAL_ADDRESS pageTableAddr = MmGetPhysicalAddress(pageTable); 178 | 179 | if (!stream->persistent) { 180 | stream->persistent = catpt_request_region(&this->dram, stream->templ->persistent_size); 181 | dsp_update_srampge(&this->dram, this->spec->dram_mask); 182 | } 183 | 184 | struct catpt_audio_format afmt; 185 | RtlZeroMemory(&afmt, sizeof(afmt)); 186 | afmt.sample_rate = 48000; 187 | afmt.bit_depth = 16; 188 | afmt.valid_bit_depth = 16; 189 | afmt.num_channels = 2; 190 | afmt.channel_config = CATPT_CHANNEL_CONFIG_STEREO; 191 | afmt.channel_map = GENMASK(31, 8) | CATPT_CHANNEL_LEFT 192 | | (CATPT_CHANNEL_RIGHT << 4); 193 | afmt.interleaving = CATPT_INTERLEAVING_PER_CHANNEL; 194 | 195 | PHYSICAL_ADDRESS firstPage = waveStream->GetPhysicalPageAddress(mdl, 0); 196 | 197 | struct catpt_ring_info rinfo; 198 | RtlZeroMemory(&rinfo, sizeof(rinfo)); 199 | rinfo.page_table_addr = pageTableAddr.LowPart; //TODO: figure out page table addr 200 | rinfo.num_pages = pageCount; 201 | rinfo.size = byteCount; 202 | rinfo.offset = 0; 203 | rinfo.ring_first_page_pfn = (firstPage.LowPart >> 12); 204 | 205 | CatPtPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "Buffer Size: %d, Pages: %d\n", rinfo.size, rinfo.num_pages); 206 | 207 | status = ipc_alloc_stream( 208 | stream->templ->path_id, 209 | stream->templ->type, 210 | &afmt, &rinfo, 211 | stream->templ->num_entries, 212 | stream->templ->entries, 213 | stream->persistent, 214 | &stream->info 215 | ); 216 | 217 | if (!NT_SUCCESS(status)) { 218 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "Failed to alloc stream: 0x%x\n", status); 219 | 220 | force_stop(stream); 221 | return status; 222 | } 223 | 224 | stream->byteCount = byteCount; 225 | stream->pMDL = mdl; 226 | stream->waveRtStream = waveStream; 227 | stream->allocated = true; 228 | 229 | NTSTATUS volStatus; 230 | volStatus = set_dsp_vol((UINT8)this->outStream.info.stream_hw_id, volMax); 231 | if (!NT_SUCCESS(volStatus)) { 232 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "Failed to set stream volume 0x%x\n", volStatus); 233 | //Don't fail here 234 | } 235 | #else 236 | UNREFERENCED_PARAMETER(deviceType); 237 | UNREFERENCED_PARAMETER(stream); 238 | UNREFERENCED_PARAMETER(mdl); 239 | #endif 240 | return STATUS_SUCCESS; 241 | } 242 | 243 | #define DSP_VOLUME_MAX INT32_MAX /* 0db */ 244 | #define DSP_VOLUME_STEP_MAX 30 245 | static UINT32 ctlvol_to_dspvol(UINT32 value) 246 | { 247 | if (value > DSP_VOLUME_STEP_MAX) 248 | value = 0; 249 | return DSP_VOLUME_MAX >> (DSP_VOLUME_STEP_MAX - value); 250 | } 251 | 252 | NTSTATUS CCsAudioCatptSSTHW::set_dsp_vol(UINT8 stream_id, LONG* ctlvol) { 253 | UINT32 dspvol; 254 | int i; 255 | NTSTATUS status; 256 | 257 | for (i = 1; i < CATPT_CHANNELS_MAX; i++) 258 | if (ctlvol[i] != ctlvol[0]) 259 | break; 260 | 261 | if (i == CATPT_CHANNELS_MAX) { 262 | dspvol = ctlvol_to_dspvol(ctlvol[0]); 263 | 264 | status = ipc_set_volume(stream_id, 265 | CATPT_ALL_CHANNELS_MASK, dspvol, 266 | 0, CATPT_AUDIO_CURVE_NONE); 267 | } 268 | else { 269 | for (i = 0; i < CATPT_CHANNELS_MAX; i++) { 270 | dspvol = ctlvol_to_dspvol(ctlvol[i]); 271 | 272 | status = ipc_set_volume(stream_id, 273 | i, dspvol, 274 | 0, CATPT_AUDIO_CURVE_NONE); 275 | if (!NT_SUCCESS(status)) 276 | break; 277 | } 278 | } 279 | 280 | return status; 281 | } -------------------------------------------------------------------------------- /Source/Main/minwavert.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | minwavert.h 8 | 9 | Abstract: 10 | 11 | Definition of wavert miniport class. 12 | --*/ 13 | 14 | #ifndef _CSAUDIOACP3X_MINWAVERT_H_ 15 | #define _CSAUDIOACP3X_MINWAVERT_H_ 16 | 17 | //============================================================================= 18 | // Referenced Forward 19 | //============================================================================= 20 | class CMiniportWaveRTStream; 21 | class CAdapterCommon; 22 | typedef CMiniportWaveRTStream *PCMiniportWaveRTStream; 23 | 24 | //============================================================================= 25 | // Classes 26 | //============================================================================= 27 | /////////////////////////////////////////////////////////////////////////////// 28 | // CMiniportWaveRT 29 | // 30 | class CMiniportWaveRT : 31 | public IMiniportWaveRT, 32 | public IMiniportAudioSignalProcessing, 33 | public CUnknown 34 | { 35 | private: 36 | ULONG m_ulSystemAllocated; 37 | 38 | ULONG m_ulMaxSystemStreams; 39 | ULONG m_ulMaxOffloadStreams; 40 | ULONG m_ulMaxLoopbackStreams; 41 | 42 | // weak ref of running streams. 43 | PCMiniportWaveRTStream * m_SystemStreams; 44 | 45 | PKSDATAFORMAT_WAVEFORMATEXTENSIBLE m_pMixFormat; 46 | PKSDATAFORMAT_WAVEFORMATEXTENSIBLE m_pDeviceFormat; 47 | PCFILTER_DESCRIPTOR m_FilterDesc; 48 | PIN_DEVICE_FORMATS_AND_MODES * m_DeviceFormatsAndModes; 49 | KSPIN_LOCK m_DeviceFormatsAndModesLock; // To serialize access. 50 | KIRQL m_DeviceFormatsAndModesIrql; 51 | ULONG m_DeviceFormatsAndModesCount; 52 | USHORT m_DeviceMaxChannels; 53 | PDRMPORT m_pDrmPort; 54 | DRMRIGHTS m_MixDrmRights; 55 | ULONG m_ulMixDrmContentId; 56 | 57 | union { 58 | PVOID m_DeviceContext; 59 | }; 60 | 61 | protected: 62 | PADAPTERCOMMON m_pAdapterCommon; 63 | ULONG m_DeviceFlags; 64 | eDeviceType m_DeviceType; 65 | PPORTEVENTS m_pPortEvents; 66 | PENDPOINT_MINIPAIR m_pMiniportPair; 67 | 68 | public: 69 | NTSTATUS EventHandler_PinCapsChange 70 | ( 71 | _In_ PPCEVENT_REQUEST EventRequest 72 | ); 73 | 74 | NTSTATUS ValidateStreamCreate 75 | ( 76 | _In_ ULONG _Pin, 77 | _In_ BOOLEAN _Capture 78 | ); 79 | 80 | NTSTATUS StreamCreated 81 | ( 82 | _In_ ULONG _Pin, 83 | _In_ PCMiniportWaveRTStream _Stream 84 | ); 85 | 86 | NTSTATUS StreamClosed 87 | ( 88 | _In_ ULONG _Pin, 89 | _In_ PCMiniportWaveRTStream _Stream 90 | ); 91 | 92 | NTSTATUS AcquireDMA( 93 | _In_ PCMiniportWaveRTStream _Stream, 94 | UINT32 byteCount 95 | ); 96 | 97 | NTSTATUS StartDMA(); 98 | 99 | NTSTATUS StopDMA(); 100 | 101 | NTSTATUS CurrentPosition(UINT32* linkPos, UINT64* linearPos); 102 | 103 | NTSTATUS IsFormatSupported 104 | ( 105 | _In_ ULONG _ulPin, 106 | _In_ BOOLEAN _bCapture, 107 | _In_ PKSDATAFORMAT _pDataFormat 108 | ); 109 | 110 | static NTSTATUS GetAttributesFromAttributeList 111 | ( 112 | _In_ const KSMULTIPLE_ITEM *_pAttributes, 113 | _In_ size_t _Size, 114 | _Out_ GUID* _pSignalProcessingMode 115 | ); 116 | 117 | protected: 118 | NTSTATUS UpdateDrmRights 119 | ( 120 | void 121 | ); 122 | 123 | public: 124 | DECLARE_STD_UNKNOWN(); 125 | 126 | #pragma code_seg("PAGE") 127 | CMiniportWaveRT( 128 | _In_ PUNKNOWN UnknownAdapter, 129 | _In_ PENDPOINT_MINIPAIR MiniportPair, 130 | _In_opt_ PVOID DeviceContext 131 | ) 132 | :CUnknown(0), 133 | m_ulMaxSystemStreams(0), 134 | m_DeviceType(MiniportPair->DeviceType), 135 | m_DeviceContext(DeviceContext), 136 | m_DeviceMaxChannels(MiniportPair->DeviceMaxChannels), 137 | m_DeviceFormatsAndModes(MiniportPair->PinDeviceFormatsAndModes), 138 | m_DeviceFormatsAndModesCount(MiniportPair->PinDeviceFormatsAndModesCount), 139 | m_DeviceFlags(MiniportPair->DeviceFlags), 140 | m_pMiniportPair(MiniportPair) 141 | { 142 | PAGED_CODE(); 143 | 144 | m_pAdapterCommon = (PADAPTERCOMMON)UnknownAdapter; 145 | if (m_pAdapterCommon) 146 | m_pAdapterCommon->AddRef(); 147 | 148 | if (MiniportPair->WaveDescriptor) 149 | { 150 | RtlCopyMemory(&m_FilterDesc, MiniportPair->WaveDescriptor, sizeof(m_FilterDesc)); 151 | 152 | // 153 | // Get the max # of pin instances. 154 | // 155 | if (IsRenderDevice()) 156 | { 157 | if (m_FilterDesc.PinCount > KSPIN_WAVE_RENDER2_SOURCE) 158 | { 159 | m_ulMaxSystemStreams = m_FilterDesc.Pins[KSPIN_WAVE_RENDER2_SINK_SYSTEM].MaxFilterInstanceCount; 160 | m_ulMaxLoopbackStreams = m_FilterDesc.Pins[KSPIN_WAVE_RENDER2_SINK_LOOPBACK].MaxFilterInstanceCount; 161 | } 162 | else if(m_FilterDesc.PinCount > KSPIN_WAVE_RENDER3_SOURCE) 163 | { 164 | m_ulMaxSystemStreams = m_FilterDesc.Pins[KSPIN_WAVE_RENDER3_SINK_SYSTEM].MaxFilterInstanceCount; 165 | } 166 | } 167 | else 168 | { 169 | // 170 | // capture bridge pin comes first in the enumeration 171 | // 172 | if (m_FilterDesc.PinCount > KSPIN_WAVEIN_HOST) 173 | { 174 | m_ulMaxSystemStreams = m_FilterDesc.Pins[KSPIN_WAVEIN_HOST].MaxFilterInstanceCount; 175 | } 176 | } 177 | } 178 | 179 | KeInitializeSpinLock(&m_DeviceFormatsAndModesLock); 180 | m_DeviceFormatsAndModesIrql = PASSIVE_LEVEL; 181 | } 182 | 183 | #pragma code_seg() 184 | 185 | ~CMiniportWaveRT(); 186 | 187 | IMP_IMiniportWaveRT; 188 | IMP_IMiniportAudioSignalProcessing; 189 | 190 | // Friends 191 | friend class CMiniportWaveRTStream; 192 | friend class CMiniportTopologyCsAudioAcp3x; 193 | 194 | friend NTSTATUS PropertyHandler_WaveFilter 195 | ( 196 | _In_ PPCPROPERTY_REQUEST PropertyRequest 197 | ); 198 | 199 | public: 200 | public: 201 | NTSTATUS PropertyHandlerProposedFormat 202 | ( 203 | _In_ PPCPROPERTY_REQUEST PropertyRequest 204 | ); 205 | 206 | NTSTATUS PropertyHandlerProposedFormat2 207 | 208 | ( 209 | _In_ PPCPROPERTY_REQUEST PropertyRequest 210 | ); 211 | 212 | PADAPTERCOMMON GetAdapterCommObj() 213 | { 214 | return (PADAPTERCOMMON)m_pAdapterCommon; 215 | }; 216 | #pragma code_seg() 217 | 218 | private: 219 | _IRQL_raises_(DISPATCH_LEVEL) 220 | _Acquires_lock_(m_DeviceFormatsAndModesLock) 221 | _Requires_lock_not_held_(m_DeviceFormatsAndModesLock) 222 | _IRQL_saves_global_(SpinLock, m_DeviceFormatsAndModesIrql) 223 | VOID AcquireFormatsAndModesLock(); 224 | 225 | _Releases_lock_(m_DeviceFormatsAndModesLock) 226 | _Requires_lock_held_(m_DeviceFormatsAndModesLock) 227 | _IRQL_restores_global_(SpinLock, m_DeviceFormatsAndModesIrql) 228 | VOID ReleaseFormatsAndModesLock(); 229 | 230 | _Post_satisfies_(return > 0) 231 | ULONG GetPinSupportedDeviceFormats(_In_ ULONG PinId, _Outptr_opt_result_buffer_(return) KSDATAFORMAT_WAVEFORMATEXTENSIBLE **ppFormats); 232 | 233 | _Success_(return != 0) 234 | ULONG GetPinSupportedDeviceModes(_In_ ULONG PinId, _Outptr_opt_result_buffer_(return) _On_failure_(_Deref_post_null_) MODE_AND_DEFAULT_FORMAT **ppModes); 235 | 236 | #pragma code_seg() 237 | 238 | protected: 239 | #pragma code_seg() 240 | BOOL IsRenderDevice() 241 | { 242 | return (m_DeviceType == eSpeakerDevice) ? TRUE : FALSE; 243 | } 244 | 245 | BOOL IsSystemRenderPin(ULONG nPinId); 246 | 247 | BOOL IsSystemCapturePin(ULONG nPinId); 248 | 249 | BOOL IsBridgePin(ULONG nPinId); 250 | 251 | // These three pins are the pins used by the audio engine for host, loopback, and offload. 252 | ULONG GetSystemPinId() 253 | { 254 | ASSERT(IsRenderDevice()); 255 | return KSPIN_WAVE_RENDER2_SINK_SYSTEM; 256 | } 257 | }; 258 | 259 | typedef CMiniportWaveRT *PCMiniportWaveRT; 260 | 261 | #endif // _CSAUDIOACP3X_MINWAVERT_H_ 262 | -------------------------------------------------------------------------------- /Source/Filters/micarraywavtable.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | micarraywavtable.h 8 | 9 | Abstract:- 10 | 11 | Declaration of wave miniport tables for the mic array. 12 | 13 | --*/ 14 | 15 | #ifndef _CSAUDIOSSTCATPT_MICARRAYWAVTABLE_H_ 16 | #define _CSAUDIOSSTCATPT_MICARRAYWAVTABLE_H_ 17 | 18 | // 19 | // Mic array range. 20 | // 21 | #define MICARRAY_RAW_CHANNELS 2 // Channels for raw mode 22 | #define MICARRAY_DEVICE_MAX_CHANNELS 2 // Max channels overall 23 | #define MICARRAY_32_BITS_PER_SAMPLE_PCM 32 // 32 Bits Per Sample 24 | #define MICARRAY_RAW_SAMPLE_RATE 48000 // Raw sample rate 25 | 26 | // 27 | // Max # of pin instances. 28 | // 29 | #define MICARRAY_MAX_INPUT_STREAMS 1 30 | 31 | //============================================================================= 32 | static 33 | KSDATAFORMAT_WAVEFORMATEXTENSIBLE MicArrayPinSupportedDeviceFormats[] = 34 | { 35 | // 48 KHz 16-bit 2 channels 36 | { 37 | { 38 | sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE), 39 | 0, 40 | 0, 41 | 0, 42 | STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), 43 | STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), 44 | STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) 45 | }, 46 | { 47 | { 48 | WAVE_FORMAT_EXTENSIBLE, 49 | 2, 50 | 48000, 51 | 192000, 52 | 4, 53 | 16, 54 | sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) 55 | }, 56 | 16, 57 | KSAUDIO_SPEAKER_STEREO, 58 | STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM) 59 | } 60 | } 61 | }; 62 | 63 | // 64 | // Supported modes (only on streaming pins). 65 | // 66 | static 67 | MODE_AND_DEFAULT_FORMAT MicArrayPinSupportedDeviceModes[] = 68 | { 69 | { 70 | STATIC_AUDIO_SIGNALPROCESSINGMODE_RAW, 71 | &MicArrayPinSupportedDeviceFormats[0].DataFormat 72 | } 73 | }; 74 | 75 | // 76 | // The entries here must follow the same order as the filter's pin 77 | // descriptor array. 78 | // 79 | static 80 | PIN_DEVICE_FORMATS_AND_MODES MicArrayPinDeviceFormatsAndModes[] = 81 | { 82 | { 83 | BridgePin, 84 | NULL, 85 | 0, 86 | NULL, 87 | 0 88 | }, 89 | { 90 | SystemCapturePin, 91 | MicArrayPinSupportedDeviceFormats, 92 | SIZEOF_ARRAY(MicArrayPinSupportedDeviceFormats), 93 | MicArrayPinSupportedDeviceModes, 94 | SIZEOF_ARRAY(MicArrayPinSupportedDeviceModes) 95 | } 96 | }; 97 | 98 | //============================================================================= 99 | // Data ranges 100 | // 101 | // See CMiniportWaveRT::DataRangeIntersection. 102 | // 103 | static 104 | KSDATARANGE_AUDIO MicArrayPinDataRangesRawStream[] = 105 | { 106 | { 107 | { 108 | sizeof(KSDATARANGE_AUDIO), 109 | KSDATARANGE_ATTRIBUTES, // An attributes list follows this data range 110 | 0, 111 | 0, 112 | STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), 113 | STATICGUIDOF(KSDATAFORMAT_SUBTYPE_PCM), 114 | STATICGUIDOF(KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) 115 | }, 116 | MICARRAY_RAW_CHANNELS, 117 | MICARRAY_32_BITS_PER_SAMPLE_PCM, 118 | MICARRAY_32_BITS_PER_SAMPLE_PCM, 119 | MICARRAY_RAW_SAMPLE_RATE, 120 | MICARRAY_RAW_SAMPLE_RATE 121 | }, 122 | }; 123 | 124 | static 125 | PKSDATARANGE MicArrayPinDataRangePointersStream[] = 126 | { 127 | // All supported device formats should be listed in the DataRange. 128 | PKSDATARANGE(&MicArrayPinDataRangesRawStream[0]), 129 | PKSDATARANGE(&PinDataRangeAttributeList), 130 | }; 131 | 132 | //============================================================================= 133 | static 134 | KSDATARANGE MicArrayPinDataRangesBridge[] = 135 | { 136 | { 137 | sizeof(KSDATARANGE), 138 | 0, 139 | 0, 140 | 0, 141 | STATICGUIDOF(KSDATAFORMAT_TYPE_AUDIO), 142 | STATICGUIDOF(KSDATAFORMAT_SUBTYPE_ANALOG), 143 | STATICGUIDOF(KSDATAFORMAT_SPECIFIER_NONE) 144 | } 145 | }; 146 | 147 | static 148 | PKSDATARANGE MicArrayPinDataRangePointersBridge[] = 149 | { 150 | &MicArrayPinDataRangesBridge[0] 151 | }; 152 | 153 | //============================================================================= 154 | static 155 | PCPIN_DESCRIPTOR MicArrayWaveMiniportPins[] = 156 | { 157 | // Wave In Bridge Pin (Capture - From Topology) KSPIN_WAVE_BRIDGE 158 | { 159 | 0, 160 | 0, 161 | 0, 162 | NULL, 163 | { 164 | 0, 165 | NULL, 166 | 0, 167 | NULL, 168 | SIZEOF_ARRAY(MicArrayPinDataRangePointersBridge), 169 | MicArrayPinDataRangePointersBridge, 170 | KSPIN_DATAFLOW_IN, 171 | KSPIN_COMMUNICATION_NONE, 172 | &KSCATEGORY_AUDIO, 173 | NULL, 174 | 0 175 | } 176 | }, 177 | // Wave In Streaming Pin (Capture) KSPIN_WAVE_HOST 178 | { 179 | MICARRAY_MAX_INPUT_STREAMS, 180 | MICARRAY_MAX_INPUT_STREAMS, 181 | 0, 182 | NULL, 183 | { 184 | 0, 185 | NULL, 186 | 0, 187 | NULL, 188 | SIZEOF_ARRAY(MicArrayPinDataRangePointersStream), 189 | MicArrayPinDataRangePointersStream, 190 | KSPIN_DATAFLOW_OUT, 191 | KSPIN_COMMUNICATION_SINK, 192 | &KSCATEGORY_AUDIO, 193 | &KSAUDFNAME_RECORDING_CONTROL, 194 | 0 195 | } 196 | } 197 | }; 198 | 199 | //============================================================================= 200 | static 201 | PCNODE_DESCRIPTOR MicArrayWaveMiniportNodes[] = 202 | { 203 | // KSNODE_WAVE_ADC 204 | { 205 | 0, // Flags 206 | NULL, // AutomationTable 207 | &KSNODETYPE_ADC, // Type 208 | NULL // Name 209 | } 210 | }; 211 | 212 | //============================================================================= 213 | static 214 | PCCONNECTION_DESCRIPTOR MicArrayWaveMiniportConnections[] = 215 | { 216 | { PCFILTER_NODE, KSPIN_WAVE_BRIDGE, KSNODE_WAVE_ADC, 1 }, 217 | { KSNODE_WAVE_ADC, 0, PCFILTER_NODE, KSPIN_WAVEIN_HOST }, 218 | }; 219 | 220 | //============================================================================= 221 | 222 | static 223 | CSAUDIOSSTCATPT_PROPERTY_ITEM PropertiesMicArrayWaveFilter[] = 224 | { 225 | { 226 | { 227 | &KSPROPSETID_General, 228 | KSPROPERTY_GENERAL_COMPONENTID, 229 | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, 230 | PropertyHandler_WaveFilter, 231 | }, 232 | 0, 233 | 0, 234 | NULL, 235 | NULL, 236 | NULL, 237 | NULL, 238 | 0 239 | }, 240 | { 241 | { 242 | &KSPROPSETID_Pin, 243 | KSPROPERTY_PIN_PROPOSEDATAFORMAT, 244 | KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_BASICSUPPORT, 245 | PropertyHandler_WaveFilter, 246 | }, 247 | 0, 248 | 0, 249 | NULL, 250 | NULL, 251 | NULL, 252 | NULL, 253 | 0 254 | }, 255 | { 256 | { 257 | &KSPROPSETID_Pin, 258 | KSPROPERTY_PIN_PROPOSEDATAFORMAT2, 259 | KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_BASICSUPPORT, 260 | PropertyHandler_WaveFilter, 261 | }, 262 | 0, 263 | 0, 264 | NULL, 265 | NULL, 266 | NULL, 267 | NULL, 268 | 0 269 | }, 270 | }; 271 | 272 | DEFINE_PCAUTOMATION_TABLE_PROP(AutomationMicArrayWaveFilter, PropertiesMicArrayWaveFilter); 273 | 274 | //============================================================================= 275 | static 276 | PCFILTER_DESCRIPTOR MicArrayWaveMiniportFilterDescriptor = 277 | { 278 | 0, // Version 279 | &AutomationMicArrayWaveFilter, // AutomationTable 280 | sizeof(PCPIN_DESCRIPTOR), // PinSize 281 | SIZEOF_ARRAY(MicArrayWaveMiniportPins), // PinCount 282 | MicArrayWaveMiniportPins, // Pins 283 | sizeof(PCNODE_DESCRIPTOR), // NodeSize 284 | SIZEOF_ARRAY(MicArrayWaveMiniportNodes), // NodeCount 285 | MicArrayWaveMiniportNodes, // Nodes 286 | SIZEOF_ARRAY(MicArrayWaveMiniportConnections), // ConnectionCount 287 | MicArrayWaveMiniportConnections, // Connections 288 | 0, // CategoryCount 289 | NULL // Categories - use defaults (audio, render, capture) 290 | }; 291 | 292 | #endif // _CSAUDIOSSTCATPT_MICARRAYWAVTABLE_H_ 293 | -------------------------------------------------------------------------------- /Source/Utilities/dsp.cpp: -------------------------------------------------------------------------------- 1 | #include "definitions.h" 2 | #include "hw.h" 3 | #include "pa2xxssp.h" 4 | 5 | #if USESSTHW 6 | NTSTATUS CCsAudioCatptSSTHW::dsp_select_lpclock(BOOL lp, BOOL waiti) 7 | { 8 | UINT32 mask, reg, val; 9 | int ret; 10 | 11 | ExAcquireFastMutex(&clk_mutex); 12 | 13 | val = lp ? CATPT_CS_LPCS : 0; 14 | reg = catpt_readl_shim(this, CS1) & CATPT_CS_LPCS; 15 | CatPtPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "LPCS [0x%08lx] 0x%08x -> 0x%08x", 16 | CATPT_CS_LPCS, reg, val); 17 | 18 | if (reg == val) { 19 | ExReleaseFastMutex(&clk_mutex); 20 | return STATUS_SUCCESS; 21 | } 22 | 23 | if (waiti) { 24 | /* wait for DSP to signal WAIT state */ 25 | ret = catpt_readl_poll_shim(this, ISD, 26 | CATPT_ISD_DCPWM, CATPT_ISD_DCPWM, 27 | 500, 10000); 28 | if (ret) { 29 | DPF(D_ERROR, "await WAITI timeout\n"); 30 | /* no signal - only high clock selection allowed */ 31 | if (lp) { 32 | ExReleaseFastMutex(&clk_mutex); 33 | return STATUS_SUCCESS; 34 | } 35 | } 36 | } 37 | 38 | ret = catpt_readl_poll_shim(this, CLKCTL, 39 | 0, CATPT_CLKCTL_CFCIP, 40 | 500, 10000); 41 | if (ret) 42 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "clock change still in progress\n"); 43 | 44 | /* default to DSP core & audio fabric high clock */ 45 | val |= CATPT_CS_DCS_HIGH; 46 | mask = CATPT_CS_LPCS | CATPT_CS_DCS; 47 | catpt_updatel_shim(this, CS1, mask, val); 48 | 49 | ret = catpt_readl_poll_shim(this, CLKCTL, 50 | 0, CATPT_CLKCTL_CFCIP, 51 | 500, 10000); 52 | if (ret) 53 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "clock change still in progress\n"); 54 | 55 | /* update PLL accordingly */ 56 | catpt_updatel_pci_raw(this, this->spec->pll_shutdown_reg, this->spec->pll_shutdown_val, lp ? this->spec->pll_shutdown_val : 0); 57 | 58 | ExReleaseFastMutex(&clk_mutex); 59 | return STATUS_SUCCESS; 60 | } 61 | 62 | NTSTATUS CCsAudioCatptSSTHW::dsp_update_lpclock() 63 | { 64 | if (this->outStream.prepared || this->inStream.prepared) 65 | return dsp_select_lpclock(false, true); 66 | 67 | return dsp_select_lpclock(true, true); 68 | } 69 | 70 | /* bring registers to their defaults as HW won't reset itself */ 71 | void CCsAudioCatptSSTHW::dsp_set_regs_defaults() 72 | { 73 | int i; 74 | 75 | catpt_writel_shim(this, CS1, CATPT_CS_DEFAULT); 76 | catpt_writel_shim(this, ISC, CATPT_ISC_DEFAULT); 77 | catpt_writel_shim(this, ISD, CATPT_ISD_DEFAULT); 78 | catpt_writel_shim(this, IMC, CATPT_IMC_DEFAULT); 79 | catpt_writel_shim(this, IMD, CATPT_IMD_DEFAULT); 80 | catpt_writel_shim(this, IPCC, CATPT_IPCC_DEFAULT); 81 | catpt_writel_shim(this, IPCD, CATPT_IPCD_DEFAULT); 82 | catpt_writel_shim(this, CLKCTL, CATPT_CLKCTL_DEFAULT); 83 | catpt_writel_shim(this, CS2, CATPT_CS2_DEFAULT); 84 | catpt_writel_shim(this, LTRC, CATPT_LTRC_DEFAULT); 85 | catpt_writel_shim(this, HMDC, CATPT_HMDC_DEFAULT); 86 | 87 | for (i = 0; i < CATPT_SSP_COUNT; i++) { 88 | catpt_writel_ssp(this, i, SSCR0, CATPT_SSC0_DEFAULT); 89 | catpt_writel_ssp(this, i, SSCR1, CATPT_SSC1_DEFAULT); 90 | catpt_writel_ssp(this, i, SSSR, CATPT_SSS_DEFAULT); 91 | catpt_writel_ssp(this, i, SSITR, CATPT_SSIT_DEFAULT); 92 | catpt_writel_ssp(this, i, SSDR, CATPT_SSD_DEFAULT); 93 | catpt_writel_ssp(this, i, SSTO, CATPT_SSTO_DEFAULT); 94 | catpt_writel_ssp(this, i, SSPSP, CATPT_SSPSP_DEFAULT); 95 | catpt_writel_ssp(this, i, SSTSA, CATPT_SSTSA_DEFAULT); 96 | catpt_writel_ssp(this, i, SSRSA, CATPT_SSRSA_DEFAULT); 97 | catpt_writel_ssp(this, i, SSTSS, CATPT_SSTSS_DEFAULT); 98 | catpt_writel_ssp(this, i, SSCR2, CATPT_SSCR2_DEFAULT); 99 | catpt_writel_ssp(this, i, SSPSP2, CATPT_SSPSP2_DEFAULT); 100 | } 101 | } 102 | 103 | void CCsAudioCatptSSTHW::dsp_set_srampge(PRESOURCE sram, 104 | unsigned long mask, unsigned long newVal) 105 | { 106 | unsigned long oldVal; 107 | UINT32 off = (UINT32)sram->start; 108 | 109 | oldVal = catpt_readl_pci(this, VDRTCTL0) & mask; 110 | CatPtPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "SRAMPGE [0x%08lx] 0x%08lx -> 0x%08lx", 111 | mask, oldVal, newVal); 112 | 113 | if (oldVal == newVal) 114 | return; 115 | 116 | catpt_updatel_pci(this, VDRTCTL0, mask, newVal); 117 | /* wait for SRAM power gating to propagate */ 118 | udelay(60); 119 | 120 | /* 121 | * Dummy read as the very first access after block enable 122 | * to prevent byte loss in future operations. 123 | */ 124 | for (int bit = __ffs(mask); bit <= fls(mask); bit++) { 125 | if ((newVal >> bit) & 1) { 126 | continue; 127 | } 128 | 129 | UINT8 buf[4]; 130 | 131 | /* newly enabled: new bit=0 while old bit=1 */ 132 | if ((oldVal >> bit) & 1) { 133 | CatPtPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "sanitize block %ld: off 0x%08x\n", 134 | bit - __ffs(mask), off); 135 | memcpy(buf, this->lpe_ba + off, sizeof(buf)); 136 | } 137 | off += CATPT_MEMBLOCK_SIZE; 138 | } 139 | } 140 | 141 | void CCsAudioCatptSSTHW::dsp_update_srampge(PRESOURCE sram, 142 | unsigned long mask) 143 | { 144 | PRESOURCE resVal; 145 | unsigned long newVal = 0; 146 | 147 | /* flag all busy blocks */ 148 | for (resVal = sram->child; resVal; resVal = resVal->sibling) { 149 | UINT32 h, l; 150 | 151 | h = (UINT32)((resVal->end - sram->start) / CATPT_MEMBLOCK_SIZE); 152 | l = (UINT32)((resVal->start - sram->start) / CATPT_MEMBLOCK_SIZE); 153 | newVal |= GENMASK(h, l); 154 | } 155 | 156 | /* offset value given mask's start and invert it as ON=b0 */ 157 | newVal = ~(newVal << __ffs(mask)) & mask; 158 | 159 | /* disable core clock gating */ 160 | catpt_updatel_pci(this, VDRTCTL2, CATPT_VDRTCTL2_DCLCGE, 0); 161 | 162 | dsp_set_srampge(sram, mask, newVal); 163 | 164 | /* enable core clock gating */ 165 | catpt_updatel_pci(this, VDRTCTL2, CATPT_VDRTCTL2_DCLCGE, 166 | CATPT_VDRTCTL2_DCLCGE); 167 | } 168 | 169 | NTSTATUS CCsAudioCatptSSTHW::dsp_stall(BOOL stall) 170 | { 171 | UINT32 val; 172 | 173 | val = stall ? CATPT_CS_STALL : 0; 174 | catpt_updatel_shim(this, CS1, CATPT_CS_STALL, val); 175 | 176 | return catpt_readl_poll_shim(this, CS1, 177 | val, CATPT_CS_STALL, 178 | 500, 10000); 179 | } 180 | 181 | NTSTATUS CCsAudioCatptSSTHW::dsp_reset(BOOL reset) 182 | { 183 | UINT32 val; 184 | 185 | val = reset ? CATPT_CS_RST : 0; 186 | catpt_updatel_shim(this, CS1, CATPT_CS_RST, val); 187 | 188 | return catpt_readl_poll_shim(this, CS1, 189 | val, CATPT_CS_RST, 190 | 500, 10000); 191 | } 192 | 193 | NTSTATUS CCsAudioCatptSSTHW::dsp_power_down() 194 | { 195 | UINT32 mask, val; 196 | 197 | /* disable core clock gating */ 198 | catpt_updatel_pci(this, VDRTCTL2, CATPT_VDRTCTL2_DCLCGE, 0); 199 | 200 | dsp_reset(true); 201 | /* set 24Mhz clock for both SSPs */ 202 | catpt_updatel_shim(this, CS1, CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1), 203 | CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1)); 204 | dsp_select_lpclock(true, false); 205 | /* disable MCLK */ 206 | catpt_updatel_shim(this, CLKCTL, CATPT_CLKCTL_SMOS, 0); 207 | 208 | dsp_set_regs_defaults(); 209 | 210 | /* switch clock gating */ 211 | mask = CATPT_VDRTCTL2_CGEALL & (~CATPT_VDRTCTL2_DCLCGE); 212 | val = mask & (~CATPT_VDRTCTL2_DTCGE); 213 | catpt_updatel_pci(this, VDRTCTL2, mask, val); 214 | /* enable DTCGE separatelly */ 215 | catpt_updatel_pci(this, VDRTCTL2, CATPT_VDRTCTL2_DTCGE, 216 | CATPT_VDRTCTL2_DTCGE); 217 | 218 | /* SRAM power gating all */ 219 | dsp_set_srampge(&this->dram, this->spec->dram_mask, 220 | this->spec->dram_mask); 221 | dsp_set_srampge(&this->iram, this->spec->iram_mask, 222 | this->spec->iram_mask); 223 | mask = this->spec->d3srampgd_bit | this->spec->d3pgd_bit; 224 | catpt_updatel_pci(this, VDRTCTL0, mask, this->spec->d3pgd_bit); 225 | 226 | catpt_updatel_pci(this, PMCS, PCI_PM_CTRL_STATE_MASK, PCI_D3hot); 227 | /* give hw time to drop off */ 228 | udelay(50); 229 | 230 | /* enable core clock gating */ 231 | catpt_updatel_pci(this, VDRTCTL2, CATPT_VDRTCTL2_DCLCGE, 232 | CATPT_VDRTCTL2_DCLCGE); 233 | 234 | udelay(50); 235 | 236 | return STATUS_SUCCESS; 237 | } 238 | 239 | NTSTATUS CCsAudioCatptSSTHW::dsp_power_up() { 240 | UINT32 mask, val; 241 | 242 | /* disable core clock gating */ 243 | catpt_updatel_pci(this, VDRTCTL2, CATPT_VDRTCTL2_DCLCGE, 0); 244 | 245 | /* switch clock gating */ 246 | mask = CATPT_VDRTCTL2_CGEALL & (~CATPT_VDRTCTL2_DCLCGE); 247 | val = mask & (~CATPT_VDRTCTL2_DTCGE); 248 | catpt_updatel_pci(this, VDRTCTL2, mask, val); 249 | 250 | catpt_updatel_pci(this, PMCS, PCI_PM_CTRL_STATE_MASK, PCI_D0); 251 | 252 | /* SRAM power gating none */ 253 | mask = this->spec->d3srampgd_bit | this->spec->d3pgd_bit; 254 | catpt_updatel_pci(this, VDRTCTL0, mask, mask); 255 | dsp_set_srampge(&this->dram, this->spec->dram_mask, 0); 256 | dsp_set_srampge(&this->iram, this->spec->iram_mask, 0); 257 | 258 | dsp_set_regs_defaults(); 259 | 260 | /* restore MCLK */ 261 | catpt_updatel_shim(this, CLKCTL, CATPT_CLKCTL_SMOS, CATPT_CLKCTL_SMOS); 262 | dsp_select_lpclock(false, false); 263 | /* set 24Mhz clock for both SSPs */ 264 | catpt_updatel_shim(this, CS1, CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1), 265 | CATPT_CS_SBCS(0) | CATPT_CS_SBCS(1)); 266 | dsp_reset(false); 267 | 268 | /* enable core clock gating */ 269 | catpt_updatel_pci(this, VDRTCTL2, CATPT_VDRTCTL2_DCLCGE, 270 | CATPT_VDRTCTL2_DCLCGE); 271 | 272 | /* generate int deassert msg to fix inversed int logic */ 273 | catpt_updatel_shim(this, IMC, CATPT_IMC_IPCDB | CATPT_IMC_IPCCD, 0); 274 | 275 | return STATUS_SUCCESS; 276 | } 277 | #endif -------------------------------------------------------------------------------- /Source/Utilities/messages.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright(c) 2020 Intel Corporation. All rights reserved. 3 | * 4 | * Author: Cezary Rojewski 5 | */ 6 | 7 | #ifndef __INTEL_CATPT_MSG_H 8 | #define __INTEL_CATPT_MSG_H 9 | 10 | #include "definitions.h" 11 | #include 12 | 13 | /* IPC messages base types */ 14 | 15 | enum catpt_reply_status { 16 | CATPT_REPLY_SUCCESS = 0, 17 | CATPT_REPLY_ERROR_INVALID_PARAM = 1, 18 | CATPT_REPLY_UNKNOWN_MESSAGE_TYPE = 2, 19 | CATPT_REPLY_OUT_OF_RESOURCES = 3, 20 | CATPT_REPLY_BUSY = 4, 21 | CATPT_REPLY_PENDING = 5, 22 | CATPT_REPLY_FAILURE = 6, 23 | CATPT_REPLY_INVALID_REQUEST = 7, 24 | CATPT_REPLY_UNINITIALIZED = 8, 25 | CATPT_REPLY_NOT_FOUND = 9, 26 | CATPT_REPLY_SOURCE_NOT_STARTED = 10, 27 | }; 28 | 29 | /* GLOBAL messages */ 30 | 31 | enum catpt_global_msg_type { 32 | CATPT_GLB_GET_FW_VERSION = 0, 33 | CATPT_GLB_ALLOCATE_STREAM = 3, 34 | CATPT_GLB_FREE_STREAM = 4, 35 | CATPT_GLB_STREAM_MESSAGE = 6, 36 | CATPT_GLB_REQUEST_CORE_DUMP = 7, 37 | CATPT_GLB_SET_DEVICE_FORMATS = 10, 38 | CATPT_GLB_ENTER_DX_STATE = 12, 39 | CATPT_GLB_GET_MIXER_STREAM_INFO = 13, 40 | }; 41 | 42 | union catpt_global_msg { 43 | UINT32 val; 44 | struct { 45 | UINT32 status : 5; 46 | UINT32 context : 19; /* stream or module specific */ 47 | UINT32 global_msg_type : 5; 48 | UINT32 fw_ready : 1; 49 | UINT32 done : 1; 50 | UINT32 busy : 1; 51 | }; 52 | }; 53 | 54 | #define CATPT_MSG(hdr) { .val = hdr } 55 | #define CATPT_GLOBAL_MSG(msg_type) \ 56 | { .global_msg_type = CATPT_GLB_##msg_type } 57 | 58 | #define BUILD_HASH_SIZE 40 59 | 60 | struct catpt_fw_version { 61 | UINT8 build; 62 | UINT8 minor; 63 | UINT8 major; 64 | UINT8 type; 65 | UINT8 build_hash[BUILD_HASH_SIZE]; 66 | UINT32 log_providers_hash; 67 | }; 68 | 69 | enum catpt_pin_id { 70 | CATPT_PIN_ID_SYSTEM = 0, 71 | CATPT_PIN_ID_REFERENCE = 1, 72 | CATPT_PIN_ID_CAPTURE1 = 2, 73 | CATPT_PIN_ID_CAPTURE2 = 3, 74 | CATPT_PIN_ID_OFFLOAD1 = 4, 75 | CATPT_PIN_ID_OFFLOAD2 = 5, 76 | CATPT_PIN_ID_MIXER = 7, 77 | CATPT_PIN_ID_BLUETOOTH_CAPTURE = 8, 78 | CATPT_PIN_ID_BLUETOOTH_RENDER = 9, 79 | }; 80 | 81 | enum catpt_path_id { 82 | CATPT_PATH_SSP0_OUT = 0, 83 | CATPT_PATH_SSP0_IN = 1, 84 | CATPT_PATH_SSP1_OUT = 2, 85 | CATPT_PATH_SSP1_IN = 3, 86 | /* duplicated audio in capture path */ 87 | CATPT_PATH_SSP0_IN_DUP = 4, 88 | }; 89 | 90 | enum catpt_stream_type { 91 | CATPT_STRM_TYPE_RENDER = 0, /* offload */ 92 | CATPT_STRM_TYPE_SYSTEM = 1, 93 | CATPT_STRM_TYPE_CAPTURE = 2, 94 | CATPT_STRM_TYPE_LOOPBACK = 3, 95 | CATPT_STRM_TYPE_BLUETOOTH_RENDER = 4, 96 | CATPT_STRM_TYPE_BLUETOOTH_CAPTURE = 5, 97 | }; 98 | 99 | enum catpt_format_id { 100 | CATPT_FORMAT_PCM = 0, 101 | CATPT_FORMAT_MP3 = 1, 102 | CATPT_FORMAT_AAC = 2, 103 | CATPT_FORMAT_WMA = 3, 104 | }; 105 | 106 | enum catpt_channel_index { 107 | CATPT_CHANNEL_LEFT = 0x0, 108 | CATPT_CHANNEL_CENTER = 0x1, 109 | CATPT_CHANNEL_RIGHT = 0x2, 110 | CATPT_CHANNEL_LEFT_SURROUND = 0x3, 111 | CATPT_CHANNEL_CENTER_SURROUND = 0x3, 112 | CATPT_CHANNEL_RIGHT_SURROUND = 0x4, 113 | CATPT_CHANNEL_LFE = 0x7, 114 | CATPT_CHANNEL_INVALID = 0xF, 115 | }; 116 | 117 | enum catpt_channel_config { 118 | CATPT_CHANNEL_CONFIG_MONO = 0, /* One channel only */ 119 | CATPT_CHANNEL_CONFIG_STEREO = 1, /* L & R */ 120 | CATPT_CHANNEL_CONFIG_2_POINT_1 = 2, /* L, R & LFE; PCM only */ 121 | CATPT_CHANNEL_CONFIG_3_POINT_0 = 3, /* L, C & R; MP3 & AAC only */ 122 | CATPT_CHANNEL_CONFIG_3_POINT_1 = 4, /* L, C, R & LFE; PCM only */ 123 | CATPT_CHANNEL_CONFIG_QUATRO = 5, /* L, R, Ls & Rs; PCM only */ 124 | CATPT_CHANNEL_CONFIG_4_POINT_0 = 6, /* L, C, R & Cs; MP3 & AAC only */ 125 | CATPT_CHANNEL_CONFIG_5_POINT_0 = 7, /* L, C, R, Ls & Rs */ 126 | CATPT_CHANNEL_CONFIG_5_POINT_1 = 8, /* L, C, R, Ls, Rs & LFE */ 127 | CATPT_CHANNEL_CONFIG_DUAL_MONO = 9, /* One channel replicated in two */ 128 | CATPT_CHANNEL_CONFIG_INVALID = 10, 129 | }; 130 | 131 | enum catpt_interleaving_style { 132 | CATPT_INTERLEAVING_PER_CHANNEL = 0, 133 | CATPT_INTERLEAVING_PER_SAMPLE = 1, 134 | }; 135 | 136 | struct catpt_audio_format { 137 | UINT32 sample_rate; 138 | UINT32 bit_depth; 139 | UINT32 channel_map; 140 | UINT32 channel_config; 141 | UINT32 interleaving; 142 | UINT8 num_channels; 143 | UINT8 valid_bit_depth; 144 | UINT8 reserved[2]; 145 | }; 146 | 147 | struct catpt_ring_info { 148 | UINT32 page_table_addr; 149 | UINT32 num_pages; 150 | UINT32 size; 151 | UINT32 offset; 152 | UINT32 ring_first_page_pfn; 153 | }; 154 | 155 | #define CATPT_MODULE_COUNT (CATPT_MODID_LAST + 1) 156 | 157 | enum catpt_module_id { 158 | CATPT_MODID_BASE_FW = 0x0, 159 | CATPT_MODID_MP3 = 0x1, 160 | CATPT_MODID_AAC_5_1 = 0x2, 161 | CATPT_MODID_AAC_2_0 = 0x3, 162 | CATPT_MODID_SRC = 0x4, 163 | CATPT_MODID_WAVES = 0x5, 164 | CATPT_MODID_DOLBY = 0x6, 165 | CATPT_MODID_BOOST = 0x7, 166 | CATPT_MODID_LPAL = 0x8, 167 | CATPT_MODID_DTS = 0x9, 168 | CATPT_MODID_PCM_CAPTURE = 0xA, 169 | CATPT_MODID_PCM_SYSTEM = 0xB, 170 | CATPT_MODID_PCM_REFERENCE = 0xC, 171 | CATPT_MODID_PCM = 0xD, /* offload */ 172 | CATPT_MODID_BLUETOOTH_RENDER = 0xE, 173 | CATPT_MODID_BLUETOOTH_CAPTURE = 0xF, 174 | CATPT_MODID_LAST = CATPT_MODID_BLUETOOTH_CAPTURE, 175 | }; 176 | 177 | struct catpt_module_entry { 178 | UINT32 module_id; 179 | UINT32 entry_point; 180 | }; 181 | 182 | /*struct catpt_module_map { 183 | UINT8 num_entries; 184 | struct catpt_module_entry entries[]; 185 | };*/ 186 | 187 | struct catpt_memory_info { 188 | UINT32 offset; 189 | UINT32 size; 190 | }; 191 | 192 | #define CATPT_CHANNELS_MAX 4 193 | #define CATPT_ALL_CHANNELS_MASK UINT_MAX 194 | 195 | struct catpt_stream_info { 196 | UINT32 stream_hw_id; 197 | UINT32 reserved; 198 | UINT32 read_pos_regaddr; 199 | UINT32 pres_pos_regaddr; 200 | UINT32 peak_meter_regaddr[CATPT_CHANNELS_MAX]; 201 | UINT32 volume_regaddr[CATPT_CHANNELS_MAX]; 202 | }; 203 | 204 | enum catpt_ssp_iface { 205 | CATPT_SSP_IFACE_0 = 0, 206 | CATPT_SSP_IFACE_1 = 1, 207 | CATPT_SSP_COUNT, 208 | }; 209 | 210 | enum catpt_mclk_frequency { 211 | CATPT_MCLK_OFF = 0, 212 | CATPT_MCLK_FREQ_6_MHZ = 1, 213 | CATPT_MCLK_FREQ_21_MHZ = 2, 214 | CATPT_MCLK_FREQ_24_MHZ = 3, 215 | }; 216 | 217 | enum catpt_ssp_mode { 218 | CATPT_SSP_MODE_I2S_CONSUMER = 0, 219 | CATPT_SSP_MODE_I2S_PROVIDER = 1, 220 | CATPT_SSP_MODE_TDM_PROVIDER = 2, 221 | }; 222 | 223 | struct catpt_ssp_device_format { 224 | UINT32 iface; 225 | UINT32 mclk; 226 | UINT32 mode; 227 | UINT16 clock_divider; 228 | UINT8 channels; 229 | }; 230 | 231 | enum catpt_dx_state { 232 | CATPT_DX_STATE_D3 = 3, 233 | }; 234 | 235 | enum catpt_dx_type { 236 | CATPT_DX_TYPE_FW_IMAGE = 0, 237 | CATPT_DX_TYPE_MEMORY_DUMP = 1, 238 | }; 239 | 240 | struct catpt_save_meminfo { 241 | UINT32 offset; 242 | UINT32 size; 243 | UINT32 source; 244 | }; 245 | 246 | #define SAVE_MEMINFO_MAX 14 247 | 248 | struct catpt_dx_context { 249 | UINT32 num_meminfo; 250 | struct catpt_save_meminfo meminfo[SAVE_MEMINFO_MAX]; 251 | }; 252 | 253 | struct catpt_mixer_stream_info { 254 | UINT32 mixer_hw_id; 255 | UINT32 peak_meter_regaddr[CATPT_CHANNELS_MAX]; 256 | UINT32 volume_regaddr[CATPT_CHANNELS_MAX]; 257 | }; 258 | 259 | /* STREAM messages */ 260 | 261 | enum catpt_stream_msg_type { 262 | CATPT_STRM_RESET_STREAM = 0, 263 | CATPT_STRM_PAUSE_STREAM = 1, 264 | CATPT_STRM_RESUME_STREAM = 2, 265 | CATPT_STRM_STAGE_MESSAGE = 3, 266 | CATPT_STRM_NOTIFICATION = 4, 267 | }; 268 | 269 | enum catpt_stage_action { 270 | CATPT_STG_SET_VOLUME = 1, 271 | CATPT_STG_SET_WRITE_POSITION = 2, 272 | CATPT_STG_MUTE_LOOPBACK = 3, 273 | }; 274 | 275 | union catpt_stream_msg { 276 | UINT32 val; 277 | struct { 278 | UINT32 status : 5; 279 | UINT32 reserved : 7; 280 | UINT32 stage_action : 4; 281 | UINT32 stream_hw_id : 4; 282 | UINT32 stream_msg_type : 4; 283 | UINT32 global_msg_type : 5; 284 | UINT32 fw_ready : 1; 285 | UINT32 done : 1; 286 | UINT32 busy : 1; 287 | }; 288 | }; 289 | 290 | #define CATPT_STREAM_MSG(msg_type) \ 291 | { \ 292 | .stream_msg_type = CATPT_STRM_##msg_type, \ 293 | .global_msg_type = CATPT_GLB_STREAM_MESSAGE } 294 | #define CATPT_STAGE_MSG(msg_type) \ 295 | { \ 296 | .stage_action = CATPT_STG_##msg_type, \ 297 | .stream_msg_type = CATPT_STRM_STAGE_MESSAGE, \ 298 | .global_msg_type = CATPT_GLB_STREAM_MESSAGE } 299 | 300 | /* STREAM messages - STAGE subtype */ 301 | 302 | enum catpt_audio_curve_type { 303 | CATPT_AUDIO_CURVE_NONE = 0, 304 | CATPT_AUDIO_CURVE_WINDOWS_FADE = 1, 305 | }; 306 | 307 | /* NOTIFICATION messages */ 308 | 309 | enum catpt_notify_reason { 310 | CATPT_NOTIFY_POSITION_CHANGED = 0, 311 | CATPT_NOTIFY_GLITCH_OCCURRED = 1, 312 | }; 313 | 314 | union catpt_notify_msg { 315 | UINT32 val; 316 | struct { 317 | UINT32 mailbox_address : 29; 318 | UINT32 fw_ready : 1; 319 | UINT32 done : 1; 320 | UINT32 busy : 1; 321 | }; 322 | struct { 323 | UINT32 status : 5; 324 | UINT32 reserved : 7; 325 | UINT32 notify_reason : 4; 326 | UINT32 stream_hw_id : 4; 327 | UINT32 stream_msg_type : 4; 328 | UINT32 global_msg_type : 5; 329 | UINT32 hdr : 3; /* fw_ready, done, busy */ 330 | }; 331 | }; 332 | 333 | #define FW_INFO_SIZE_MAX 100 334 | 335 | struct catpt_fw_ready { 336 | UINT32 inbox_offset; 337 | UINT32 outbox_offset; 338 | UINT32 inbox_size; 339 | UINT32 outbox_size; 340 | UINT32 fw_info_size; 341 | char fw_info[FW_INFO_SIZE_MAX]; 342 | }; 343 | 344 | struct catpt_notify_position { 345 | UINT32 stream_position; 346 | UINT32 fw_cycle_count; 347 | }; 348 | 349 | enum catpt_glitch_type { 350 | CATPT_GLITCH_UNDERRUN = 1, 351 | CATPT_GLITCH_DECODER_ERROR = 2, 352 | CATPT_GLITCH_DOUBLED_WRITE_POS = 3, 353 | }; 354 | 355 | struct catpt_notify_glitch { 356 | UINT32 type; 357 | UINT64 presentation_pos; 358 | UINT32 write_pos; 359 | }; 360 | 361 | #include 362 | #endif 363 | -------------------------------------------------------------------------------- /Source/Utilities/pa2xxssp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /* 4 | * SSP Serial Port Registers 5 | * PXA250, PXA255, PXA26x and PXA27x SSP controllers are all slightly different. 6 | * PXA255, PXA26x and PXA27x have extra ports, registers and bits. 7 | */ 8 | 9 | #define SSCR0 (0x00) /* SSP Control Register 0 */ 10 | #define SSCR1 (0x04) /* SSP Control Register 1 */ 11 | #define SSSR (0x08) /* SSP Status Register */ 12 | #define SSITR (0x0C) /* SSP Interrupt Test Register */ 13 | #define SSDR (0x10) /* SSP Data Write/Data Read Register */ 14 | 15 | #define SSTO (0x28) /* SSP Time Out Register */ 16 | #define SSPSP (0x2C) /* SSP Programmable Serial Protocol */ 17 | #define SSTSA (0x30) /* SSP Tx Timeslot Active */ 18 | #define SSRSA (0x34) /* SSP Rx Timeslot Active */ 19 | #define SSTSS (0x38) /* SSP Timeslot Status */ 20 | #define SSACD (0x3C) /* SSP Audio Clock Divider */ 21 | #define SSACDD (0x40) /* SSP Audio Clock Dither Divider */ 22 | 23 | /* Common PXA2xx bits first */ 24 | #define SSCR0_DSS GENMASK(3, 0) /* Data Size Select (mask) */ 25 | #define SSCR0_DataSize(x) ((x) - 1) /* Data Size Select [4..16] */ 26 | #define SSCR0_FRF GENMASK(5, 4) /* FRame Format (mask) */ 27 | #define SSCR0_Motorola (0x0 << 4) /* Motorola's Serial Peripheral Interface (SPI) */ 28 | #define SSCR0_TI (0x1 << 4) /* Texas Instruments' Synchronous Serial Protocol (SSP) */ 29 | #define SSCR0_National (0x2 << 4) /* National Microwire */ 30 | #define SSCR0_ECS BIT(6) /* External clock select */ 31 | #define SSCR0_SSE BIT(7) /* Synchronous Serial Port Enable */ 32 | #define SSCR0_SCR(x) ((x) << 8) /* Serial Clock Rate (mask) */ 33 | 34 | /* PXA27x, PXA3xx */ 35 | #define SSCR0_EDSS BIT(20) /* Extended data size select */ 36 | #define SSCR0_NCS BIT(21) /* Network clock select */ 37 | #define SSCR0_RIM BIT(22) /* Receive FIFO overrun interrupt mask */ 38 | #define SSCR0_TUM BIT(23) /* Transmit FIFO underrun interrupt mask */ 39 | #define SSCR0_FRDC GENMASK(26, 24) /* Frame rate divider control (mask) */ 40 | #define SSCR0_SlotsPerFrm(x) (((x) - 1) << 24) /* Time slots per frame [1..8] */ 41 | #define SSCR0_FPCKE BIT(29) /* FIFO packing enable */ 42 | #define SSCR0_ACS BIT(30) /* Audio clock select */ 43 | #define SSCR0_MOD BIT(31) /* Mode (normal or network) */ 44 | 45 | #define SSCR1_RIE BIT(0) /* Receive FIFO Interrupt Enable */ 46 | #define SSCR1_TIE BIT(1) /* Transmit FIFO Interrupt Enable */ 47 | #define SSCR1_LBM BIT(2) /* Loop-Back Mode */ 48 | #define SSCR1_SPO BIT(3) /* Motorola SPI SSPSCLK polarity setting */ 49 | #define SSCR1_SPH BIT(4) /* Motorola SPI SSPSCLK phase setting */ 50 | #define SSCR1_MWDS BIT(5) /* Microwire Transmit Data Size */ 51 | 52 | #define SSSR_ALT_FRM_MASK GENMASK(1, 0) /* Masks the SFRM signal number */ 53 | #define SSSR_TNF BIT(2) /* Transmit FIFO Not Full */ 54 | #define SSSR_RNE BIT(3) /* Receive FIFO Not Empty */ 55 | #define SSSR_BSY BIT(4) /* SSP Busy */ 56 | #define SSSR_TFS BIT(5) /* Transmit FIFO Service Request */ 57 | #define SSSR_RFS BIT(6) /* Receive FIFO Service Request */ 58 | #define SSSR_ROR BIT(7) /* Receive FIFO Overrun */ 59 | 60 | #define RX_THRESH_DFLT 8 61 | #define TX_THRESH_DFLT 8 62 | 63 | #define SSSR_TFL_MASK GENMASK(11, 8) /* Transmit FIFO Level mask */ 64 | #define SSSR_RFL_MASK GENMASK(15, 12) /* Receive FIFO Level mask */ 65 | 66 | #define SSCR1_TFT GENMASK(9, 6) /* Transmit FIFO Threshold (mask) */ 67 | #define SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..16] */ 68 | #define SSCR1_RFT GENMASK(13, 10) /* Receive FIFO Threshold (mask) */ 69 | #define SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..16] */ 70 | 71 | #define RX_THRESH_CE4100_DFLT 2 72 | #define TX_THRESH_CE4100_DFLT 2 73 | 74 | #define CE4100_SSSR_TFL_MASK GENMASK(9, 8) /* Transmit FIFO Level mask */ 75 | #define CE4100_SSSR_RFL_MASK GENMASK(13, 12) /* Receive FIFO Level mask */ 76 | 77 | #define CE4100_SSCR1_TFT GENMASK(7, 6) /* Transmit FIFO Threshold (mask) */ 78 | #define CE4100_SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..4] */ 79 | #define CE4100_SSCR1_RFT GENMASK(11, 10) /* Receive FIFO Threshold (mask) */ 80 | #define CE4100_SSCR1_RxTresh(x) (((x) - 1) << 10) /* level [1..4] */ 81 | 82 | /* Intel Quark X1000 */ 83 | #define DDS_RATE 0x28 /* SSP DDS Clock Rate Register */ 84 | 85 | /* QUARK_X1000 SSCR0 bit definition */ 86 | #define QUARK_X1000_SSCR0_DSS GENMASK(4, 0) /* Data Size Select (mask) */ 87 | #define QUARK_X1000_SSCR0_DataSize(x) ((x) - 1) /* Data Size Select [4..32] */ 88 | #define QUARK_X1000_SSCR0_FRF GENMASK(6, 5) /* FRame Format (mask) */ 89 | #define QUARK_X1000_SSCR0_Motorola (0x0 << 5) /* Motorola's Serial Peripheral Interface (SPI) */ 90 | 91 | #define RX_THRESH_QUARK_X1000_DFLT 1 92 | #define TX_THRESH_QUARK_X1000_DFLT 16 93 | 94 | #define QUARK_X1000_SSSR_TFL_MASK GENMASK(12, 8) /* Transmit FIFO Level mask */ 95 | #define QUARK_X1000_SSSR_RFL_MASK GENMASK(17, 13) /* Receive FIFO Level mask */ 96 | 97 | #define QUARK_X1000_SSCR1_TFT GENMASK(10, 6) /* Transmit FIFO Threshold (mask) */ 98 | #define QUARK_X1000_SSCR1_TxTresh(x) (((x) - 1) << 6) /* level [1..32] */ 99 | #define QUARK_X1000_SSCR1_RFT GENMASK(15, 11) /* Receive FIFO Threshold (mask) */ 100 | #define QUARK_X1000_SSCR1_RxTresh(x) (((x) - 1) << 11) /* level [1..32] */ 101 | #define QUARK_X1000_SSCR1_EFWR BIT(16) /* Enable FIFO Write/Read */ 102 | #define QUARK_X1000_SSCR1_STRF BIT(17) /* Select FIFO or EFWR */ 103 | 104 | /* Extra bits in PXA255, PXA26x and PXA27x SSP ports */ 105 | #define SSCR0_TISSP (1 << 4) /* TI Sync Serial Protocol */ 106 | #define SSCR0_PSP (3 << 4) /* PSP - Programmable Serial Protocol */ 107 | 108 | #define SSCR1_EFWR BIT(14) /* Enable FIFO Write/Read */ 109 | #define SSCR1_STRF BIT(15) /* Select FIFO or EFWR */ 110 | #define SSCR1_IFS BIT(16) /* Invert Frame Signal */ 111 | #define SSCR1_PINTE BIT(18) /* Peripheral Trailing Byte Interrupt Enable */ 112 | #define SSCR1_TINTE BIT(19) /* Receiver Time-out Interrupt enable */ 113 | #define SSCR1_RSRE BIT(20) /* Receive Service Request Enable */ 114 | #define SSCR1_TSRE BIT(21) /* Transmit Service Request Enable */ 115 | #define SSCR1_TRAIL BIT(22) /* Trailing Byte */ 116 | #define SSCR1_RWOT BIT(23) /* Receive Without Transmit */ 117 | #define SSCR1_SFRMDIR BIT(24) /* Frame Direction */ 118 | #define SSCR1_SCLKDIR BIT(25) /* Serial Bit Rate Clock Direction */ 119 | #define SSCR1_ECRB BIT(26) /* Enable Clock request B */ 120 | #define SSCR1_ECRA BIT(27) /* Enable Clock Request A */ 121 | #define SSCR1_SCFR BIT(28) /* Slave Clock free Running */ 122 | #define SSCR1_EBCEI BIT(29) /* Enable Bit Count Error interrupt */ 123 | #define SSCR1_TTE BIT(30) /* TXD Tristate Enable */ 124 | #define SSCR1_TTELP BIT(31) /* TXD Tristate Enable Last Phase */ 125 | 126 | #define SSSR_PINT BIT(18) /* Peripheral Trailing Byte Interrupt */ 127 | #define SSSR_TINT BIT(19) /* Receiver Time-out Interrupt */ 128 | #define SSSR_EOC BIT(20) /* End Of Chain */ 129 | #define SSSR_TUR BIT(21) /* Transmit FIFO Under Run */ 130 | #define SSSR_CSS BIT(22) /* Clock Synchronisation Status */ 131 | #define SSSR_BCE BIT(23) /* Bit Count Error */ 132 | 133 | #define SSPSP_SCMODE(x) ((x) << 0) /* Serial Bit Rate Clock Mode */ 134 | #define SSPSP_SFRMP BIT(2) /* Serial Frame Polarity */ 135 | #define SSPSP_ETDS BIT(3) /* End of Transfer data State */ 136 | #define SSPSP_STRTDLY(x) ((x) << 4) /* Start Delay */ 137 | #define SSPSP_DMYSTRT(x) ((x) << 7) /* Dummy Start */ 138 | #define SSPSP_SFRMDLY(x) ((x) << 9) /* Serial Frame Delay */ 139 | #define SSPSP_SFRMWDTH(x) ((x) << 16) /* Serial Frame Width */ 140 | #define SSPSP_DMYSTOP(x) ((x) << 23) /* Dummy Stop */ 141 | #define SSPSP_FSRT BIT(25) /* Frame Sync Relative Timing */ 142 | 143 | /* PXA3xx */ 144 | #define SSPSP_EDMYSTRT(x) ((x) << 26) /* Extended Dummy Start */ 145 | #define SSPSP_EDMYSTOP(x) ((x) << 28) /* Extended Dummy Stop */ 146 | #define SSPSP_TIMING_MASK (0x7f8001f0) 147 | 148 | #define SSACD_ACDS(x) ((x) << 0) /* Audio clock divider select */ 149 | #define SSACD_ACDS_1 (0) 150 | #define SSACD_ACDS_2 (1) 151 | #define SSACD_ACDS_4 (2) 152 | #define SSACD_ACDS_8 (3) 153 | #define SSACD_ACDS_16 (4) 154 | #define SSACD_ACDS_32 (5) 155 | #define SSACD_SCDB BIT(3) /* SSPSYSCLK Divider Bypass */ 156 | #define SSACD_SCDB_4X (0) 157 | #define SSACD_SCDB_1X (1) 158 | #define SSACD_ACPS(x) ((x) << 4) /* Audio clock PLL select */ 159 | #define SSACD_SCDX8 BIT(7) /* SYSCLK division ratio select */ 160 | 161 | /* Intel Merrifield SSP */ 162 | #define SFIFOL 0x68 /* FIFO level */ 163 | #define SFIFOTT 0x6c /* FIFO trigger threshold */ 164 | 165 | #define RX_THRESH_MRFLD_DFLT 16 166 | #define TX_THRESH_MRFLD_DFLT 16 167 | 168 | #define SFIFOL_TFL_MASK GENMASK(15, 0) /* Transmit FIFO Level mask */ 169 | #define SFIFOL_RFL_MASK GENMASK(31, 16) /* Receive FIFO Level mask */ 170 | 171 | #define SFIFOTT_TFT GENMASK(15, 0) /* Transmit FIFO Threshold (mask) */ 172 | #define SFIFOTT_TxThresh(x) (((x) - 1) << 0) /* TX FIFO trigger threshold / level */ 173 | #define SFIFOTT_RFT GENMASK(31, 16) /* Receive FIFO Threshold (mask) */ 174 | #define SFIFOTT_RxThresh(x) (((x) - 1) << 16) /* RX FIFO trigger threshold / level */ 175 | 176 | /* LPSS SSP */ 177 | #define SSITF 0x44 /* TX FIFO trigger level */ 178 | #define SSITF_TxHiThresh(x) (((x) - 1) << 0) 179 | #define SSITF_TxLoThresh(x) (((x) - 1) << 8) 180 | 181 | #define SSIRF 0x48 /* RX FIFO trigger level */ 182 | #define SSIRF_RxThresh(x) ((x) - 1) 183 | 184 | /* LPT/WPT SSP */ 185 | #define SSCR2 (0x40) /* SSP Command / Status 2 */ 186 | #define SSPSP2 (0x44) /* SSP Programmable Serial Protocol 2 */ 187 | 188 | enum pxa_ssp_type { 189 | SSP_UNDEFINED = 0, 190 | PXA25x_SSP, /* pxa 210, 250, 255, 26x */ 191 | PXA25x_NSSP, /* pxa 255, 26x (including ASSP) */ 192 | PXA27x_SSP, 193 | PXA3xx_SSP, 194 | PXA168_SSP, 195 | MMP2_SSP, 196 | PXA910_SSP, 197 | CE4100_SSP, 198 | MRFLD_SSP, 199 | QUARK_X1000_SSP, 200 | /* Keep LPSS types sorted with lpss_platforms[] */ 201 | LPSS_LPT_SSP, 202 | LPSS_BYT_SSP, 203 | LPSS_BSW_SSP, 204 | LPSS_SPT_SSP, 205 | LPSS_BXT_SSP, 206 | LPSS_CNL_SSP, 207 | }; -------------------------------------------------------------------------------- /Source/Utilities/hw.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | hw.h 8 | 9 | Abstract: 10 | 11 | Declaration of Simple Audio Sample HW class. 12 | Simple Audio Sample HW has an array for storing mixer and volume settings 13 | for the topology. 14 | --*/ 15 | 16 | #ifndef _CSAUDIOSSTCATPT_HW_H_ 17 | #define _CSAUDIOSSTCATPT_HW_H_ 18 | #define USESSTHW 1 19 | 20 | // 21 | // Helper macros 22 | // 23 | 24 | #define DEBUG_LEVEL_ERROR 1 25 | #define DEBUG_LEVEL_INFO 2 26 | #define DEBUG_LEVEL_VERBOSE 3 27 | 28 | #define CatptDebugLevel 100; 29 | #define CatptDebugCatagories (DBG_INIT || DBG_PNP || DBG_IOCTL) 30 | 31 | #define DBG_INIT 1 32 | #define DBG_PNP 2 33 | #define DBG_IOCTL 4 34 | 35 | #if 0 36 | #define CatPtPrint(dbglevel, dbgcatagory, fmt, ...) { \ 37 | if (CatptDebugLevel >= dbglevel && \ 38 | (CatptDebugCatagories && dbgcatagory)) \ 39 | { \ 40 | DbgPrint(DRIVERNAME); \ 41 | DbgPrint(fmt, __VA_ARGS__); \ 42 | } \ 43 | } 44 | #else 45 | #define CatPtPrint(dbglevel, fmt, ...) { \ 46 | } 47 | #endif 48 | 49 | #if USESSTHW 50 | #include "bitops.h" 51 | 52 | union baseaddr { 53 | PVOID Base; 54 | UINT8* baseptr; 55 | }; 56 | 57 | typedef struct _PCI_BAR { 58 | union baseaddr Base; 59 | ULONG Len; 60 | } PCI_BAR, * PPCI_BAR; 61 | 62 | typedef struct _RESOURCE { 63 | UINT64 start; 64 | UINT64 end; 65 | int flags; 66 | struct _RESOURCE* parent, * sibling, * child; 67 | } RESOURCE, *PRESOURCE; 68 | 69 | enum PCI_POWER { 70 | PCI_D0, 71 | PCI_D1, 72 | PCI_D3, 73 | PCI_D3hot, 74 | PCI_D3cold 75 | }; 76 | #define PCI_PM_CTRL 4 /* PM control and status register */ 77 | #define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */ 78 | 79 | #include "messages.h" 80 | #include "firmware.h" 81 | #include "registers.h" 82 | #include "dw_dma.h" 83 | 84 | /* 85 | * Either engine 0 or 1 can be used for image loading. 86 | * Align with Intel Windows driver equivalent and stick to engine 1. 87 | */ 88 | #define CATPT_DMA_DEVID 1 89 | #define CATPT_DMA_DSP_ADDR_MASK GENMASK(31, 20) 90 | 91 | #define CATPT_IPC_TIMEOUT_MS 300 92 | 93 | struct catpt_ipc_msg { 94 | union { 95 | UINT32 header; 96 | union catpt_global_msg rsp; 97 | }; 98 | void* data; 99 | size_t size; 100 | }; 101 | 102 | struct catpt_module_type { 103 | bool loaded; 104 | UINT32 entry_point; 105 | UINT32 persistent_size; 106 | UINT32 scratch_size; 107 | /* DRAM, initial module state */ 108 | UINT32 state_offset; 109 | UINT32 state_size; 110 | }; 111 | 112 | struct catpt_spec { 113 | UINT8 core_id; 114 | UINT32 host_dram_offset; 115 | UINT32 host_iram_offset; 116 | UINT32 host_shim_offset; 117 | UINT32 host_dma_offset[CATPT_DMA_COUNT]; 118 | UINT32 host_ssp_offset[CATPT_SSP_COUNT]; 119 | UINT32 dram_mask; 120 | UINT32 iram_mask; 121 | UINT32 d3srampgd_bit; 122 | UINT32 d3pgd_bit; 123 | UINT32 pll_shutdown_reg; 124 | UINT32 pll_shutdown_val; 125 | }; 126 | 127 | struct catpt_stream { 128 | struct catpt_stream_template* templ; 129 | struct catpt_stream_info info; 130 | PRESOURCE persistent; 131 | 132 | PVOID pageTable; 133 | 134 | UINT32 byteCount; 135 | PMDL pMDL; 136 | IPortWaveRTStream* waveRtStream; 137 | 138 | BOOL allocated; 139 | BOOL prepared; 140 | }; 141 | #endif 142 | 143 | //============================================================================= 144 | // Defines 145 | //============================================================================= 146 | // BUGBUG we should dynamically allocate this... 147 | #define MAX_TOPOLOGY_NODES 20 148 | 149 | //============================================================================= 150 | // Classes 151 | //============================================================================= 152 | /////////////////////////////////////////////////////////////////////////////// 153 | // CCsAudioSstCatPtHW 154 | // This class represents virtual Simple Audio Sample HW. An array representing volume 155 | // registers and mute registers. 156 | 157 | class CCsAudioCatptSSTHW 158 | { 159 | public: 160 | protected: 161 | LONG m_PeakMeterControls[MAX_TOPOLOGY_NODES]; 162 | ULONG m_ulMux; // Mux selection 163 | BOOL m_bDevSpecific; 164 | INT m_iDevSpecific; 165 | UINT m_uiDevSpecific; 166 | #if USESSTHW 167 | PCI_BAR m_BAR0; 168 | PCI_BAR m_BAR1; 169 | 170 | PINTERRUPTSYNC m_InterruptSync; 171 | 172 | RESOURCE dram; 173 | RESOURCE iram; 174 | PRESOURCE scratch; 175 | 176 | DwDMA* dmac; 177 | #endif 178 | 179 | #if USEACPHW 180 | UINT32 m_pme_en; 181 | 182 | INT bt_running_streams; 183 | INT sp_running_streams; 184 | #endif 185 | 186 | private: 187 | #if USESSTHW 188 | const struct catpt_spec* spec; 189 | 190 | struct catpt_mixer_stream_info mixer; 191 | 192 | catpt_stream outStream; 193 | catpt_stream inStream; 194 | FAST_MUTEX clk_mutex; 195 | 196 | void udelay(ULONG usec); 197 | UINT32 readl(PVOID reg); 198 | void writel(UINT32 val, PVOID reg); 199 | NTSTATUS readl_poll_timeout(PVOID reg, UINT32 val, UINT32 mask, ULONG sleep_us, ULONG timeout_us); 200 | 201 | //DSP Private methods 202 | NTSTATUS dsp_select_lpclock(BOOL lp, BOOL waiti); 203 | NTSTATUS dsp_update_lpclock(); 204 | void dsp_set_regs_defaults(); 205 | void dsp_set_srampge(PRESOURCE sram, unsigned long mask, unsigned long newVal); 206 | void dsp_update_srampge(PRESOURCE sram, unsigned long mask); 207 | NTSTATUS dsp_stall(BOOL stall); 208 | NTSTATUS dsp_reset(BOOL reset); 209 | 210 | //DSP methods 211 | NTSTATUS dsp_power_down(); 212 | NTSTATUS dsp_power_up(); 213 | 214 | //loader vars 215 | struct catpt_module_type modules[CATPT_MODULE_COUNT]; 216 | BOOL fw_ready; 217 | 218 | //loader private methods 219 | void sram_init(PRESOURCE sram, UINT32 start, UINT32 size); 220 | void sram_free(PRESOURCE sram); 221 | PRESOURCE catpt_request_region(PRESOURCE root, size_t size); 222 | 223 | NTSTATUS catpt_load_block(PHYSICAL_ADDRESS pAddr, struct catpt_fw_block_hdr* blk, bool alloc); 224 | NTSTATUS catpt_load_module(PHYSICAL_ADDRESS paddr, struct catpt_fw_mod_hdr* mod); 225 | NTSTATUS catpt_load_firmware(PHYSICAL_ADDRESS paddr, struct catpt_fw_hdr* fw); 226 | NTSTATUS catpt_load_image(PCWSTR path, BOOL restore); 227 | 228 | //loader methods 229 | NTSTATUS catpt_boot_firmware(BOOL restore); 230 | 231 | //IPC vars 232 | struct catpt_ipc_msg ipc_rx; 233 | struct catpt_fw_ready ipc_config; 234 | BOOL ipc_ready; 235 | 236 | BOOL ipc_done; 237 | BOOL ipc_busy; 238 | 239 | //IPC private methods 240 | void ipc_init(); 241 | NTSTATUS ipc_arm(struct catpt_fw_ready* config); 242 | NTSTATUS ipc_send_msg(struct catpt_ipc_msg request, 243 | struct catpt_ipc_msg* reply, int timeout); 244 | NTSTATUS ipc_wait_completion(int timeout); 245 | void dsp_send_tx(const struct catpt_ipc_msg* tx); 246 | void dsp_copy_rx(UINT32 header); 247 | void dsp_notify_stream(union catpt_notify_msg msg); 248 | void dsp_process_response(UINT32 header); 249 | //IPC methods 250 | 251 | //PCM private methods 252 | NTSTATUS catpt_arm_stream_templates(); 253 | struct catpt_stream* catpt_stream_find(UINT8 stream_hw_id); 254 | NTSTATUS set_dsp_vol(UINT8 stream_id, LONG* ctlvol); 255 | void stream_update_position(struct catpt_stream* stream, struct catpt_notify_position* pos); 256 | 257 | //messages private methods 258 | NTSTATUS ipc_alloc_stream(enum catpt_path_id path_id, enum catpt_stream_type type, 259 | struct catpt_audio_format* afmt, struct catpt_ring_info* rinfo, UINT8 num_modules, 260 | struct catpt_module_entry* modules, PRESOURCE persistent, struct catpt_stream_info* sinfo); 261 | NTSTATUS ipc_free_stream(UINT8 stream_hw_id); 262 | NTSTATUS ipc_set_device_format(struct catpt_ssp_device_format* devfmt); 263 | NTSTATUS ipc_set_volume(UINT8 stream_hw_id, 264 | UINT32 channel, UINT32 volume, 265 | UINT32 curve_duration, 266 | enum catpt_audio_curve_type curve_type); 267 | NTSTATUS ipc_set_write_pos(UINT8 stream_hw_id, 268 | UINT32 pos, bool eob, bool ll); 269 | NTSTATUS ipc_reset_stream(UINT8 stream_hw_id); 270 | NTSTATUS ipc_pause_stream(UINT8 stream_hw_id); 271 | NTSTATUS ipc_resume_stream(UINT8 stream_hw_id); 272 | public: 273 | NTSTATUS dsp_irq_handler(); 274 | #endif 275 | 276 | public: 277 | CCsAudioCatptSSTHW(_In_ PRESOURCELIST ResourceList); 278 | ~CCsAudioCatptSSTHW(); 279 | 280 | bool ResourcesValidated(); 281 | NTSTATUS sst_init(); 282 | NTSTATUS sst_deinit(); 283 | 284 | NTSTATUS sst_program_dma(eDeviceType deviceType, UINT32 byteCount, PMDL mdl, IPortWaveRTStream* stream); 285 | NTSTATUS sst_play(eDeviceType deviceType); 286 | NTSTATUS sst_stop(eDeviceType deviceType); 287 | void force_stop(catpt_stream* stream); 288 | NTSTATUS sst_current_position(eDeviceType deviceType, UINT32* linkPos, UINT64* linearPos); 289 | 290 | void MixerReset(); 291 | BOOL bGetDevSpecific(); 292 | void bSetDevSpecific 293 | ( 294 | _In_ BOOL bDevSpecific 295 | ); 296 | INT iGetDevSpecific(); 297 | void iSetDevSpecific 298 | ( 299 | _In_ INT iDevSpecific 300 | ); 301 | UINT uiGetDevSpecific(); 302 | void uiSetDevSpecific 303 | ( 304 | _In_ UINT uiDevSpecific 305 | ); 306 | ULONG GetMixerMux(); 307 | void SetMixerMux 308 | ( 309 | _In_ ULONG ulNode 310 | ); 311 | 312 | LONG GetMixerPeakMeter 313 | ( 314 | _In_ ULONG ulNode, 315 | _In_ ULONG ulChannel 316 | ); 317 | 318 | protected: 319 | private: 320 | }; 321 | typedef CCsAudioCatptSSTHW *PCCsAudioCatptSSTHW; 322 | 323 | #endif // _CSAUDIOSSTCATPT_HW_H_ 324 | -------------------------------------------------------------------------------- /Source/Utilities/dw_dma.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dw_dma.h" 3 | #include "bitops.h" 4 | #include "hw.h" 5 | 6 | // Pool tag used for DMA allocations 7 | #define DWDMA_POOLTAG 'MDWD' 8 | 9 | DwDMA::DwDMA(void* regs) { 10 | this->regs = regs; 11 | 12 | this->pdata = NULL; 13 | this->chan = NULL; 14 | this->all_chan_mask = 0; 15 | } 16 | 17 | NTSTATUS DwDMA::init() { 18 | NTSTATUS status; 19 | 20 | this->pdata = (struct dw_dma_platform_data*)ExAllocatePoolZero(NonPagedPool, sizeof(*this->pdata), DWDMA_POOLTAG); 21 | if (!this->pdata) { 22 | return STATUS_NO_MEMORY; 23 | } 24 | 25 | UINT32 dw_params = dma_readl(this, DW_PARAMS); 26 | CatPtPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "DW_PARMS: 0x%08x\n", dw_params); 27 | 28 | BOOL autocfg = FALSE; 29 | autocfg = dw_params >> DW_PARAMS_EN & 1; 30 | if (!autocfg){ 31 | status = STATUS_INVALID_PARAMETER; 32 | goto err_pdata; 33 | } 34 | 35 | /* Get hardware configuration parameters */ 36 | pdata->nr_channels = (dw_params >> DW_PARAMS_NR_CHAN & 7) + 1; 37 | pdata->nr_masters = (dw_params >> DW_PARAMS_NR_MASTER & 3) + 1; 38 | for (unsigned int i = 0; i < pdata->nr_masters; i++) { 39 | pdata->data_width[i] = 40 | 4 << (dw_params >> DW_PARAMS_DATA_WIDTH(i) & 3); 41 | } 42 | pdata->block_size = dma_readl(this, MAX_BLK_SIZE); 43 | 44 | /* Fill platform data with the default values */ 45 | pdata->chan_allocation_order = CHAN_ALLOCATION_ASCENDING; 46 | pdata->chan_priority = CHAN_PRIORITY_ASCENDING; 47 | 48 | //pdata done 49 | 50 | this->chan = (struct dw_dma_chan*)ExAllocatePoolZero(NonPagedPool, pdata->nr_channels * sizeof(*this->chan), DWDMA_POOLTAG); 51 | 52 | if (!this->chan) { 53 | status = STATUS_NO_MEMORY; 54 | goto err_pdata; 55 | } 56 | 57 | /* Calculate all channel mask before DMA setup */ 58 | this->all_chan_mask = (1 << pdata->nr_channels) - 1; 59 | 60 | /* Force dma off, just in case */ 61 | this->disable(); 62 | 63 | for (UINT32 i = 0; i < pdata->nr_channels; i++) { 64 | struct dw_dma_chan* dwc = &this->chan[i]; 65 | 66 | /* 7 is highest priority & 0 is lowest. */ 67 | if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING) 68 | dwc->priority = (UINT8)(pdata->nr_channels - i - 1); 69 | else 70 | dwc->priority = (UINT8)i; 71 | 72 | dwc->ch_regs = &__dw_regs(this)->CHAN[i]; 73 | 74 | ExInitializeFastMutex(&dwc->lock); 75 | 76 | dwc->mask = 1 << i; 77 | 78 | channel_clear_bit(this, CH_EN, dwc->mask); 79 | 80 | dwc->direction = DMA_TRANS_NONE; 81 | 82 | /* Hardware configuration */ 83 | if (autocfg) { 84 | unsigned int r = DW_DMA_MAX_NR_CHANNELS - i - 1; 85 | void* addr = &__dw_regs(this)->DWC_PARAMS[r]; 86 | unsigned int dwc_params = readl(addr); 87 | 88 | CatPtPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, "DWC_PARAMS[%d]: 0x%08x\n", i, 89 | dwc_params); 90 | 91 | /* 92 | * Decode maximum block size for given channel. The 93 | * stored 4 bit value represents blocks from 0x00 for 3 94 | * up to 0x0a for 4095. 95 | */ 96 | dwc->block_size = 97 | (4 << ((pdata->block_size >> 4 * i) & 0xf)) - 1; 98 | 99 | /* 100 | * According to the DW DMA databook the true scatter- 101 | * gether LLPs aren't available if either multi-block 102 | * config is disabled (CHx_MULTI_BLK_EN == 0) or the 103 | * LLP register is hard-coded to zeros 104 | * (CHx_HC_LLP == 1). 105 | */ 106 | dwc->nollp = 107 | (dwc_params >> DWC_PARAMS_MBLK_EN & 0x1) == 0 || 108 | (dwc_params >> DWC_PARAMS_HC_LLP & 0x1) == 1; 109 | dwc->max_burst = 110 | (0x4 << (dwc_params >> DWC_PARAMS_MSIZE & 0x7)); 111 | } 112 | else { 113 | dwc->block_size = pdata->block_size; 114 | dwc->nollp = !pdata->multi_block[i]; 115 | dwc->max_burst = pdata->max_burst[i] ? 0 : DW_DMA_MAX_BURST; 116 | } 117 | } 118 | 119 | /* Clear all interrupts on all channels. */ 120 | dma_writel(this, CLEAR.XFER, this->all_chan_mask); 121 | dma_writel(this, CLEAR.BLOCK, this->all_chan_mask); 122 | dma_writel(this, CLEAR.SRC_TRAN, this->all_chan_mask); 123 | dma_writel(this, CLEAR.DST_TRAN, this->all_chan_mask); 124 | dma_writel(this, CLEAR.ERROR, this->all_chan_mask); 125 | 126 | status = STATUS_SUCCESS; 127 | 128 | err_pdata: 129 | return status; 130 | } 131 | 132 | DwDMA::~DwDMA() { 133 | this->disable(); 134 | 135 | for (UINT32 i = 0; i < pdata->nr_channels; i++) { 136 | struct dw_dma_chan* dwc = &this->chan[i]; 137 | channel_clear_bit(this, CH_EN, dwc->mask); 138 | } 139 | 140 | if (this->chan) 141 | ExFreePoolWithTag(this->chan, DWDMA_POOLTAG); 142 | if (this->pdata) 143 | ExFreePoolWithTag(this->pdata, DWDMA_POOLTAG); 144 | } 145 | 146 | void DwDMA::disable() { 147 | dma_writel(this, CFG, 0); 148 | 149 | channel_clear_bit(this, MASK.XFER, this->all_chan_mask); 150 | channel_clear_bit(this, MASK.BLOCK, this->all_chan_mask); 151 | channel_clear_bit(this, MASK.SRC_TRAN, this->all_chan_mask); 152 | channel_clear_bit(this, MASK.DST_TRAN, this->all_chan_mask); 153 | channel_clear_bit(this, MASK.ERROR, this->all_chan_mask); 154 | 155 | while (dma_readl(this, CFG) & DW_CFG_DMA_EN) { 156 | LARGE_INTEGER Interval; 157 | Interval.QuadPart = -10 * 1000; 158 | KeDelayExecutionThread(KernelMode, false, &Interval); 159 | } 160 | } 161 | 162 | void DwDMA::enable() { 163 | dma_writel(this, CFG, DW_CFG_DMA_EN); 164 | } 165 | 166 | UINT32 DwDMA::readl(PVOID addr) { 167 | UINT32 ret = *(UINT32*)addr; 168 | //DbgPrint("Read from %p: 0x%x\n", addr, ret); 169 | return ret; 170 | } 171 | 172 | void DwDMA::writel(UINT32 data, PVOID addr) { 173 | *(UINT32*)addr = data; 174 | //DbgPrint("Write to %p: 0x%x\n", addr, data); 175 | } 176 | 177 | UINT32 DwDMA::bytes2block(struct dw_dma_chan* dwc, UINT32 bytes, unsigned int width, UINT32* len) { 178 | UINT32 block; 179 | 180 | if ((bytes >> width) > dwc->block_size) { 181 | block = dwc->block_size; 182 | *len = (UINT32)dwc->block_size << width; 183 | } 184 | else { 185 | block = bytes >> width; 186 | *len = bytes; 187 | } 188 | 189 | return block; 190 | } 191 | 192 | NTSTATUS DwDMA::transfer_dma(UINT32 dest, UINT32 src, UINT32 len) { 193 | this->enable(); 194 | struct dw_dma_chan* dwc = NULL; 195 | for (UINT32 i = 0; i < this->pdata->nr_channels; i++) { 196 | if (dma_readl(this, CH_EN) & this->chan[i].mask) { 197 | DPF(D_ERROR, "Channel not idle!\n"); 198 | } 199 | else { 200 | dwc = &this->chan[i]; 201 | break; 202 | } 203 | } 204 | 205 | if (!dwc) { 206 | return STATUS_RESOURCE_IN_USE; 207 | } 208 | 209 | UINT8 m_master = 0; 210 | 211 | UINT8 lms = DWC_LLP_LMS(m_master); 212 | 213 | UINT32 data_width = this->pdata->data_width[m_master]; 214 | 215 | UINT32 src_width, dst_width; 216 | src_width = dst_width = __ffs(data_width | src | dest | len); 217 | 218 | dwc->direction = DMA_MEM_TO_MEM; 219 | 220 | UINT32 ctllo; 221 | UINT32 ctlhi; 222 | 223 | { 224 | //prepare ctllo 225 | UINT8 smsize = (dwc->direction == DMA_DEV_TO_MEM) ? 3 : 0; //src_maxburst (DMA_DEV_MEM_TO_MEM) [16 -> 3] 226 | UINT8 dmsize = (dwc->direction == DMA_MEM_TO_DEV) ? 3 : 0; //dst_maxburst (DMA_DEV_MEM_TO_DEV) [16 -> 3] 227 | UINT8 p_master = 0; 228 | UINT8 dms = (dwc->direction == DMA_MEM_TO_DEV) ? p_master : m_master; 229 | UINT8 sms = (dwc->direction == DMA_DEV_TO_MEM) ? p_master : m_master; 230 | 231 | ctllo = DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN | 232 | DWC_CTLL_DST_MSIZE(dmsize) | DWC_CTLL_SRC_MSIZE(smsize) | 233 | DWC_CTLL_DMS(dms) | DWC_CTLL_SMS(sms); 234 | } 235 | ctllo = ctllo | DWC_CTLL_DST_WIDTH(dst_width) 236 | | DWC_CTLL_SRC_WIDTH(src_width) 237 | | DWC_CTLL_DST_INC 238 | | DWC_CTLL_SRC_INC 239 | | DWC_CTLL_FC_M2M; 240 | 241 | NTSTATUS status; 242 | 243 | PHYSICAL_ADDRESS maxAddr; 244 | maxAddr.QuadPart = MAXULONG32; 245 | UINT8* vaddr; 246 | vaddr = (UINT8 *)MmAllocateContiguousMemory(0x1000, maxAddr); 247 | if (!vaddr) { 248 | status = STATUS_NO_MEMORY; 249 | goto err; 250 | } 251 | 252 | RtlZeroMemory(vaddr, 0x1000); 253 | 254 | UINT8* curVaddr; 255 | curVaddr = vaddr; 256 | 257 | struct dw_lli* prev; 258 | prev = NULL; 259 | 260 | UINT32 xfer_count, offset; 261 | for (offset = 0; offset < len; offset += xfer_count) { 262 | ctlhi = this->bytes2block(dwc, len - offset, src_width, &xfer_count); 263 | 264 | //write sar, dar, ctllo, ctlhi 265 | struct dw_lli* cur = (struct dw_lli*)curVaddr; 266 | if (curVaddr + sizeof(struct dw_lli) > vaddr + 0x1000) { 267 | status = STATUS_NO_MEMORY; 268 | DPF(D_ERROR, "Unable to get lli entry\n"); 269 | goto err; 270 | } 271 | 272 | cur->sar = (UINT32)(src + offset); 273 | cur->dar = (UINT32)(dest + offset); 274 | cur->ctllo = ctllo; 275 | cur->ctlhi = ctlhi; 276 | cur->llp = 0; 277 | 278 | if (prev) { 279 | PHYSICAL_ADDRESS paddr; 280 | paddr = MmGetPhysicalAddress(cur); 281 | 282 | prev->llp = paddr.LowPart | lms; 283 | } 284 | prev = cur; 285 | 286 | curVaddr += sizeof(struct dw_lli); 287 | } 288 | 289 | if (prev) { 290 | prev->ctllo &= ~(DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN); 291 | } 292 | 293 | PHYSICAL_ADDRESS paddr; 294 | paddr = MmGetPhysicalAddress(vaddr); 295 | 296 | //Begin start transfer 297 | { 298 | //Initialize channel 299 | 300 | UINT32 cfghi = is_slave_direction(dwc->direction) ? 0 : DWC_CFGH_FIFO_MODE; 301 | UINT32 cfglo = DWC_CFGL_CH_PRIOR(dwc->priority); 302 | BOOL hs_polarity = FALSE; 303 | 304 | cfghi |= DWC_CFGH_DST_PER(0); //dwc->dws.dst_id 305 | cfghi |= DWC_CFGH_SRC_PER(0); //dwc->dws.src_id 306 | cfghi |= DWC_CFGH_PROTCTL(this->pdata->protctl); 307 | 308 | /* Set polarity of handshake interface */ 309 | cfglo |= hs_polarity ? DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL : 0; 310 | 311 | channel_writel(dwc, CFG_LO, cfglo); 312 | channel_writel(dwc, CFG_HI, cfghi); 313 | } 314 | 315 | /* Enable interrupts */ 316 | channel_set_bit(this, MASK.XFER, dwc->mask); 317 | channel_set_bit(this, MASK.ERROR, dwc->mask); 318 | 319 | channel_writel(dwc, LLP, paddr.LowPart | lms); 320 | channel_writel(dwc, CTL_LO, DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN); 321 | channel_writel(dwc, CTL_HI, 0); 322 | channel_set_bit(this, CH_EN, dwc->mask); 323 | 324 | LARGE_INTEGER Start; 325 | KeQuerySystemTimePrecise(&Start); 326 | 327 | //Check status 328 | while (true) { 329 | LARGE_INTEGER Cur; 330 | KeQuerySystemTimePrecise(&Cur); 331 | 332 | if (Cur.QuadPart - Start.QuadPart > 10 * 1000 * 1000 * 1) { 333 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "Timed out!\n"); 334 | CatPtPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, "Regs; SAR: 0x%x DAR: 0x%x LLP: 0x%x CTL: 0x%x:%08x\n", 335 | channel_readl(dwc, SAR), 336 | channel_readl(dwc, DAR), 337 | channel_readl(dwc, LLP), 338 | channel_readl(dwc, CTL_HI), 339 | channel_readl(dwc, CTL_LO)); 340 | status = STATUS_TIMEOUT; 341 | break; 342 | } 343 | 344 | UINT32 status_xfer = dma_readl(this, RAW.XFER); 345 | if (status_xfer & dwc->mask) { 346 | dma_writel(this, CLEAR.XFER, dwc->mask); 347 | if (dma_readl(this, CH_EN) & dwc->mask) { 348 | DPF(D_ERROR, "Channel not idle???\n"); 349 | status = STATUS_INTERNAL_ERROR; 350 | } 351 | else { 352 | status = STATUS_SUCCESS; 353 | } 354 | break; 355 | } 356 | 357 | LARGE_INTEGER Interval; 358 | Interval.QuadPart = -10 * 10; 359 | KeDelayExecutionThread(KernelMode, false, &Interval); 360 | } 361 | 362 | err: 363 | if (vaddr) { 364 | MmFreeContiguousMemory(vaddr); 365 | } 366 | this->disable(); 367 | return status; 368 | } -------------------------------------------------------------------------------- /Source/Utilities/dw_dma.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "definitions.h" 3 | 4 | #define DW_DMA_MAX_NR_MASTERS 4 5 | #define DW_DMA_MAX_NR_CHANNELS 8 6 | #define DW_DMA_MIN_BURST 1 7 | #define DW_DMA_MAX_BURST 256 8 | 9 | /* 10 | * Redefine this macro to handle differences between 32- and 64-bit 11 | * addressing, big vs. little endian, etc. 12 | */ 13 | #define DW_REG(name) UINT32 name; UINT32 __pad_##name 14 | 15 | /* Hardware register definitions. */ 16 | struct dw_dma_chan_regs { 17 | DW_REG(SAR); /* Source Address Register */ 18 | DW_REG(DAR); /* Destination Address Register */ 19 | DW_REG(LLP); /* Linked List Pointer */ 20 | UINT32 CTL_LO; /* Control Register Low */ 21 | UINT32 CTL_HI; /* Control Register High */ 22 | DW_REG(SSTAT); 23 | DW_REG(DSTAT); 24 | DW_REG(SSTATAR); 25 | DW_REG(DSTATAR); 26 | UINT32 CFG_LO; /* Configuration Register Low */ 27 | UINT32 CFG_HI; /* Configuration Register High */ 28 | DW_REG(SGR); 29 | DW_REG(DSR); 30 | }; 31 | 32 | struct dw_dma_irq_regs { 33 | DW_REG(XFER); 34 | DW_REG(BLOCK); 35 | DW_REG(SRC_TRAN); 36 | DW_REG(DST_TRAN); 37 | DW_REG(ERROR); 38 | }; 39 | 40 | struct dw_dma_regs { 41 | /* per-channel registers */ 42 | struct dw_dma_chan_regs CHAN[DW_DMA_MAX_NR_CHANNELS]; 43 | 44 | /* irq handling */ 45 | struct dw_dma_irq_regs RAW; /* r */ 46 | struct dw_dma_irq_regs STATUS; /* r (raw & mask) */ 47 | struct dw_dma_irq_regs MASK; /* rw (set = irq enabled) */ 48 | struct dw_dma_irq_regs CLEAR; /* w (ack, affects "raw") */ 49 | 50 | DW_REG(STATUS_INT); /* r */ 51 | 52 | /* software handshaking */ 53 | DW_REG(REQ_SRC); 54 | DW_REG(REQ_DST); 55 | DW_REG(SGL_REQ_SRC); 56 | DW_REG(SGL_REQ_DST); 57 | DW_REG(LAST_SRC); 58 | DW_REG(LAST_DST); 59 | 60 | /* miscellaneous */ 61 | DW_REG(CFG); 62 | DW_REG(CH_EN); 63 | DW_REG(ID); 64 | DW_REG(TEST); 65 | 66 | /* iDMA 32-bit support */ 67 | DW_REG(CLASS_PRIORITY0); 68 | DW_REG(CLASS_PRIORITY1); 69 | 70 | /* optional encoded params, 0x3c8..0x3f7 */ 71 | UINT32 dw___reserved; 72 | 73 | /* per-channel configuration registers */ 74 | UINT32 DWC_PARAMS[DW_DMA_MAX_NR_CHANNELS]; 75 | UINT32 MULTI_BLK_TYPE; 76 | UINT32 MAX_BLK_SIZE; 77 | 78 | /* top-level parameters */ 79 | UINT32 DW_PARAMS; 80 | 81 | /* component ID */ 82 | UINT32 COMP_TYPE; 83 | UINT32 COMP_VERSION; 84 | 85 | /* iDMA 32-bit support */ 86 | DW_REG(FIFO_PARTITION0); 87 | DW_REG(FIFO_PARTITION1); 88 | 89 | DW_REG(SAI_ERR); 90 | DW_REG(GLOBAL_CFG); 91 | }; 92 | 93 | /* Bitfields in DW_PARAMS */ 94 | #define DW_PARAMS_NR_CHAN 8 /* number of channels */ 95 | #define DW_PARAMS_NR_MASTER 11 /* number of AHB masters */ 96 | #define DW_PARAMS_DATA_WIDTH(n) (15 + 2 * (n)) 97 | #define DW_PARAMS_DATA_WIDTH1 15 /* master 1 data width */ 98 | #define DW_PARAMS_DATA_WIDTH2 17 /* master 2 data width */ 99 | #define DW_PARAMS_DATA_WIDTH3 19 /* master 3 data width */ 100 | #define DW_PARAMS_DATA_WIDTH4 21 /* master 4 data width */ 101 | #define DW_PARAMS_EN 28 /* encoded parameters */ 102 | 103 | /* Bitfields in DWC_PARAMS */ 104 | #define DWC_PARAMS_MBLK_EN 11 /* multi block transfer */ 105 | #define DWC_PARAMS_HC_LLP 13 /* set LLP register to zero */ 106 | #define DWC_PARAMS_MSIZE 16 /* max group transaction size */ 107 | 108 | /* bursts size */ 109 | enum dw_dma_msize { 110 | DW_DMA_MSIZE_1, 111 | DW_DMA_MSIZE_4, 112 | DW_DMA_MSIZE_8, 113 | DW_DMA_MSIZE_16, 114 | DW_DMA_MSIZE_32, 115 | DW_DMA_MSIZE_64, 116 | DW_DMA_MSIZE_128, 117 | DW_DMA_MSIZE_256, 118 | }; 119 | 120 | /* Bitfields in LLP */ 121 | #define DWC_LLP_LMS(x) ((x) & 3) /* list master select */ 122 | #define DWC_LLP_LOC(x) ((x) & ~3) /* next lli */ 123 | 124 | /* Bitfields in CTL_LO */ 125 | #define DWC_CTLL_INT_EN (1 << 0) /* irqs enabled? */ 126 | #define DWC_CTLL_DST_WIDTH(n) ((n)<<1) /* bytes per element */ 127 | #define DWC_CTLL_SRC_WIDTH(n) ((n)<<4) 128 | #define DWC_CTLL_DST_INC (0<<7) /* DAR update/not */ 129 | #define DWC_CTLL_DST_DEC (1<<7) 130 | #define DWC_CTLL_DST_FIX (2<<7) 131 | #define DWC_CTLL_SRC_INC (0<<9) /* SAR update/not */ 132 | #define DWC_CTLL_SRC_DEC (1<<9) 133 | #define DWC_CTLL_SRC_FIX (2<<9) 134 | #define DWC_CTLL_DST_MSIZE(n) ((n)<<11) /* burst, #elements */ 135 | #define DWC_CTLL_SRC_MSIZE(n) ((n)<<14) 136 | #define DWC_CTLL_S_GATH_EN (1 << 17) /* src gather, !FIX */ 137 | #define DWC_CTLL_D_SCAT_EN (1 << 18) /* dst scatter, !FIX */ 138 | #define DWC_CTLL_FC(n) ((n) << 20) 139 | #define DWC_CTLL_FC_M2M (0 << 20) /* mem-to-mem */ 140 | #define DWC_CTLL_FC_M2P (1 << 20) /* mem-to-periph */ 141 | #define DWC_CTLL_FC_P2M (2 << 20) /* periph-to-mem */ 142 | #define DWC_CTLL_FC_P2P (3 << 20) /* periph-to-periph */ 143 | /* plus 4 transfer types for peripheral-as-flow-controller */ 144 | #define DWC_CTLL_DMS(n) ((n)<<23) /* dst master select */ 145 | #define DWC_CTLL_SMS(n) ((n)<<25) /* src master select */ 146 | #define DWC_CTLL_LLP_D_EN (1 << 27) /* dest block chain */ 147 | #define DWC_CTLL_LLP_S_EN (1 << 28) /* src block chain */ 148 | 149 | /* Bitfields in CTL_HI */ 150 | #define DWC_CTLH_BLOCK_TS_MASK GENMASK(11, 0) 151 | #define DWC_CTLH_BLOCK_TS(x) ((x) & DWC_CTLH_BLOCK_TS_MASK) 152 | #define DWC_CTLH_DONE (1 << 12) 153 | 154 | /* Bitfields in CFG_LO */ 155 | #define DWC_CFGL_CH_PRIOR_MASK (0x7 << 5) /* priority mask */ 156 | #define DWC_CFGL_CH_PRIOR(x) ((x) << 5) /* priority */ 157 | #define DWC_CFGL_CH_SUSP (1 << 8) /* pause xfer */ 158 | #define DWC_CFGL_FIFO_EMPTY (1 << 9) /* pause xfer */ 159 | #define DWC_CFGL_HS_DST (1 << 10) /* handshake w/dst */ 160 | #define DWC_CFGL_HS_SRC (1 << 11) /* handshake w/src */ 161 | #define DWC_CFGL_LOCK_CH_XFER (0 << 12) /* scope of LOCK_CH */ 162 | #define DWC_CFGL_LOCK_CH_BLOCK (1 << 12) 163 | #define DWC_CFGL_LOCK_CH_XACT (2 << 12) 164 | #define DWC_CFGL_LOCK_BUS_XFER (0 << 14) /* scope of LOCK_BUS */ 165 | #define DWC_CFGL_LOCK_BUS_BLOCK (1 << 14) 166 | #define DWC_CFGL_LOCK_BUS_XACT (2 << 14) 167 | #define DWC_CFGL_LOCK_CH (1 << 15) /* channel lockout */ 168 | #define DWC_CFGL_LOCK_BUS (1 << 16) /* busmaster lockout */ 169 | #define DWC_CFGL_HS_DST_POL (1 << 18) /* dst handshake active low */ 170 | #define DWC_CFGL_HS_SRC_POL (1 << 19) /* src handshake active low */ 171 | #define DWC_CFGL_MAX_BURST(x) ((x) << 20) 172 | #define DWC_CFGL_RELOAD_SAR (1 << 30) 173 | #define DWC_CFGL_RELOAD_DAR (1 << 31) 174 | 175 | /* Bitfields in CFG_HI */ 176 | #define DWC_CFGH_FCMODE (1 << 0) 177 | #define DWC_CFGH_FIFO_MODE (1 << 1) 178 | #define DWC_CFGH_PROTCTL(x) ((x) << 2) 179 | #define DWC_CFGH_PROTCTL_DATA (0 << 2) /* data access - always set */ 180 | #define DWC_CFGH_PROTCTL_PRIV (1 << 2) /* privileged -> AHB HPROT[1] */ 181 | #define DWC_CFGH_PROTCTL_BUFFER (2 << 2) /* bufferable -> AHB HPROT[2] */ 182 | #define DWC_CFGH_PROTCTL_CACHE (4 << 2) /* cacheable -> AHB HPROT[3] */ 183 | #define DWC_CFGH_DS_UPD_EN (1 << 5) 184 | #define DWC_CFGH_SS_UPD_EN (1 << 6) 185 | #define DWC_CFGH_SRC_PER(x) ((x) << 7) 186 | #define DWC_CFGH_DST_PER(x) ((x) << 11) 187 | 188 | /* Bitfields in SGR */ 189 | #define DWC_SGR_SGI(x) ((x) << 0) 190 | #define DWC_SGR_SGC(x) ((x) << 20) 191 | 192 | /* Bitfields in DSR */ 193 | #define DWC_DSR_DSI(x) ((x) << 0) 194 | #define DWC_DSR_DSC(x) ((x) << 20) 195 | 196 | /* Bitfields in CFG */ 197 | #define DW_CFG_DMA_EN (1 << 0) 198 | 199 | /* iDMA 32-bit support */ 200 | 201 | /* bursts size */ 202 | enum idma32_msize { 203 | IDMA32_MSIZE_1, 204 | IDMA32_MSIZE_2, 205 | IDMA32_MSIZE_4, 206 | IDMA32_MSIZE_8, 207 | IDMA32_MSIZE_16, 208 | IDMA32_MSIZE_32, 209 | }; 210 | 211 | /* Bitfields in CTL_HI */ 212 | #define IDMA32C_CTLH_BLOCK_TS_MASK GENMASK(16, 0) 213 | #define IDMA32C_CTLH_BLOCK_TS(x) ((x) & IDMA32C_CTLH_BLOCK_TS_MASK) 214 | #define IDMA32C_CTLH_DONE (1 << 17) 215 | 216 | /* Bitfields in CFG_LO */ 217 | #define IDMA32C_CFGL_DST_BURST_ALIGN (1 << 0) /* dst burst align */ 218 | #define IDMA32C_CFGL_SRC_BURST_ALIGN (1 << 1) /* src burst align */ 219 | #define IDMA32C_CFGL_CH_DRAIN (1 << 10) /* drain FIFO */ 220 | #define IDMA32C_CFGL_DST_OPT_BL (1 << 20) /* optimize dst burst length */ 221 | #define IDMA32C_CFGL_SRC_OPT_BL (1 << 21) /* optimize src burst length */ 222 | 223 | /* Bitfields in CFG_HI */ 224 | #define IDMA32C_CFGH_SRC_PER(x) ((x) << 0) 225 | #define IDMA32C_CFGH_DST_PER(x) ((x) << 4) 226 | #define IDMA32C_CFGH_RD_ISSUE_THD(x) ((x) << 8) 227 | #define IDMA32C_CFGH_RW_ISSUE_THD(x) ((x) << 18) 228 | #define IDMA32C_CFGH_SRC_PER_EXT(x) ((x) << 28) /* src peripheral extension */ 229 | #define IDMA32C_CFGH_DST_PER_EXT(x) ((x) << 30) /* dst peripheral extension */ 230 | 231 | /* Bitfields in FIFO_PARTITION */ 232 | #define IDMA32C_FP_PSIZE_CH0(x) ((x) << 0) 233 | #define IDMA32C_FP_PSIZE_CH1(x) ((x) << 13) 234 | #define IDMA32C_FP_UPDATE (1 << 26) 235 | 236 | enum dw_dmac_flags { 237 | DW_DMA_IS_CYCLIC = 0, 238 | DW_DMA_IS_SOFT_LLP = 1, 239 | DW_DMA_IS_PAUSED = 2, 240 | DW_DMA_IS_INITIALIZED = 3, 241 | }; 242 | 243 | /** 244 | * enum dma_transfer_direction - dma transfer mode and direction indicator 245 | * @DMA_MEM_TO_MEM: Async/Memcpy mode 246 | * @DMA_MEM_TO_DEV: Slave mode & From Memory to Device 247 | * @DMA_DEV_TO_MEM: Slave mode & From Device to Memory 248 | * @DMA_DEV_TO_DEV: Slave mode & From Device to Device 249 | */ 250 | enum dma_transfer_direction { 251 | DMA_MEM_TO_MEM, 252 | DMA_MEM_TO_DEV, 253 | DMA_DEV_TO_MEM, 254 | DMA_DEV_TO_DEV, 255 | DMA_TRANS_NONE, 256 | }; 257 | 258 | static inline bool is_slave_direction(enum dma_transfer_direction direction) 259 | { 260 | return (direction == DMA_MEM_TO_DEV) || (direction == DMA_DEV_TO_MEM); 261 | } 262 | 263 | struct dw_dma_chan { 264 | struct dw_dma_chan_regs* ch_regs; 265 | UINT8 mask; 266 | UINT8 priority; 267 | enum dma_transfer_direction direction; 268 | 269 | #if 0 270 | /* software emulation of the LLP transfers */ 271 | struct list_head* tx_node_active; 272 | #endif 273 | 274 | FAST_MUTEX lock; 275 | 276 | /* these other elements are all protected by lock */ 277 | unsigned long flags; 278 | #if 0 279 | struct list_head active_list; 280 | struct list_head queue; 281 | #endif 282 | 283 | unsigned int descs_allocated; 284 | 285 | /* hardware configuration */ 286 | unsigned int block_size; 287 | bool nollp; 288 | UINT32 max_burst; 289 | 290 | #if 0 291 | /* custom slave configuration */ 292 | struct dw_dma_slave dws; 293 | 294 | /* configuration passed via .device_config */ 295 | struct dma_slave_config dma_sconfig; 296 | #endif 297 | }; 298 | 299 | /** 300 | * struct dw_dma_platform_data - Controller configuration parameters 301 | * @nr_masters: Number of AHB masters supported by the controller 302 | * @nr_channels: Number of channels supported by hardware (max 8) 303 | * @chan_allocation_order: Allocate channels starting from 0 or 7 304 | * @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0. 305 | * @block_size: Maximum block size supported by the controller 306 | * @data_width: Maximum data width supported by hardware per AHB master 307 | * (in bytes, power of 2) 308 | * @multi_block: Multi block transfers supported by hardware per channel. 309 | * @max_burst: Maximum value of burst transaction size supported by hardware 310 | * per channel (in units of CTL.SRC_TR_WIDTH/CTL.DST_TR_WIDTH). 311 | * @protctl: Protection control signals setting per channel. 312 | * @quirks: Optional platform quirks. 313 | */ 314 | struct dw_dma_platform_data { 315 | UINT32 nr_masters; 316 | UINT32 nr_channels; 317 | #define CHAN_ALLOCATION_ASCENDING 0 /* zero to seven */ 318 | #define CHAN_ALLOCATION_DESCENDING 1 /* seven to zero */ 319 | UINT32 chan_allocation_order; 320 | #define CHAN_PRIORITY_ASCENDING 0 /* chan0 highest */ 321 | #define CHAN_PRIORITY_DESCENDING 1 /* chan7 highest */ 322 | UINT32 chan_priority; 323 | UINT32 block_size; 324 | UINT32 data_width[DW_DMA_MAX_NR_MASTERS]; 325 | UINT32 multi_block[DW_DMA_MAX_NR_CHANNELS]; 326 | UINT32 max_burst[DW_DMA_MAX_NR_CHANNELS]; 327 | #define CHAN_PROTCTL_PRIVILEGED BIT(0) 328 | #define CHAN_PROTCTL_BUFFERABLE BIT(1) 329 | #define CHAN_PROTCTL_CACHEABLE BIT(2) 330 | #define CHAN_PROTCTL_MASK GENMASK(2, 0) 331 | UINT32 protctl; 332 | #define DW_DMA_QUIRK_XBAR_PRESENT BIT(0) 333 | UINT32 quirks; 334 | }; 335 | 336 | /* LLI == Linked List Item; a.k.a. DMA block descriptor */ 337 | struct dw_lli { 338 | /* values that are not changed by hardware */ 339 | UINT32 sar; 340 | UINT32 dar; 341 | UINT32 llp; //chain to next lli 342 | UINT32 ctllo; 343 | /* values that may get written back: */ 344 | UINT32 ctlhi; 345 | /* sstat and dstat can snapshot peripheral register state. 346 | * silicon config may discard either or both... 347 | */ 348 | UINT32 sstat; 349 | UINT32 dstat; 350 | }; 351 | 352 | class DwDMA { 353 | public: 354 | void* regs; 355 | 356 | DwDMA(void* regs); 357 | ~DwDMA(); 358 | 359 | NTSTATUS init(); 360 | private: 361 | struct dw_dma_chan* chan; 362 | 363 | /* channels */ 364 | UINT8 all_chan_mask; 365 | 366 | struct dw_dma_platform_data* pdata; 367 | 368 | void disable(); 369 | void enable(); 370 | 371 | UINT32 bytes2block(struct dw_dma_chan* dwc, UINT32 bytes, unsigned int width, UINT32* len); 372 | 373 | UINT32 readl(PVOID reg); 374 | void writel(UINT32 val, PVOID reg); 375 | 376 | public: 377 | NTSTATUS transfer_dma(UINT32 dest, UINT32 src, UINT32 len); 378 | }; 379 | typedef DwDMA* PDwDMA; 380 | 381 | static inline struct dw_dma_regs* __dw_regs(DwDMA* dw) 382 | { 383 | return (struct dw_dma_regs *)dw->regs; 384 | } 385 | 386 | static inline struct dw_dma_chan_regs* __dwc_regs(struct dw_dma_chan* dwc) 387 | { 388 | return dwc->ch_regs; 389 | } 390 | 391 | #define dma_readl(dw, name) \ 392 | readl(&(__dw_regs(dw)->name)) 393 | #define dma_writel(dw, name, val) \ 394 | writel((val), &(__dw_regs(dw)->name)) 395 | 396 | #define channel_set_bit(dw, reg, mask) \ 397 | dma_writel(dw, reg, ((mask) << 8) | (mask)) 398 | #define channel_clear_bit(dw, reg, mask) \ 399 | dma_writel(dw, reg, ((mask) << 8) | 0) 400 | 401 | #define channel_readl(dwc, name) \ 402 | readl(&(__dwc_regs(dwc)->name)) 403 | #define channel_writel(dwc, name, val) \ 404 | writel((val), &(__dwc_regs(dwc)->name)) --------------------------------------------------------------------------------