├── opengmaxcodec ├── stdint.h ├── resource.h ├── opengmaxcodec.rc ├── spb.h ├── trace.h ├── opengmaxcodec.inf ├── opengmaxcodec.h ├── opengmaxcodec.vcxproj ├── max98373.h ├── max98927.h ├── spb.c └── opengmaxcodec.c ├── README.md ├── opengmaxcodec.sln ├── LICENSE.txt ├── .gitignore └── opengmaxcodec Package └── opengmaxcodec Package.vcxproj /opengmaxcodec/stdint.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define BIT(nr) (1UL << (nr)) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # opengmaxcodec 2 | MAX98927/MAX98373 Amplifier Driver 3 | 4 | Drop-in replacement for closed source Google-provided gmaxcodec, with the goal of fully supporting csaudiosstavs and csaudiointcsof. 5 | 6 | MAX98927: Tested on Asus Chromebook Flip C433 w/ CoolStar SST Audio (AVS). 7 | 8 | MAX98973: Tested on Google Pixel Slate w/ CoolStar SST Audio (AVS). 9 | MAX98973: Tested on Asus CX9400 w/ CoolStar SOF Audio (Intel/I2S). -------------------------------------------------------------------------------- /opengmaxcodec/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by opengmaxcodec.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /opengmaxcodec/opengmaxcodec.rc: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | opengmaxcodec.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 "Maxim 98927/98373 Audio Codec" 18 | #define VER_INTERNALNAME_STR "opengmaxcodec.sys" 19 | #define VER_ORIGINALFILENAME_STR "opengmaxcodec.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 "Maxim 98927/98373 Audio Codec" 40 | 41 | #include "common.ver" -------------------------------------------------------------------------------- /opengmaxcodec/spb.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | Copyright (c) Microsoft Corporation. All Rights Reserved. 3 | Sample code. Dealpoint ID #843729. 4 | 5 | Module Name: 6 | 7 | spb.h 8 | 9 | Abstract: 10 | 11 | This module contains the touch driver I2C helper definitions. 12 | 13 | Environment: 14 | 15 | Kernel Mode 16 | 17 | Revision History: 18 | 19 | --*/ 20 | 21 | #pragma once 22 | 23 | #include 24 | #include 25 | 26 | #define DEFAULT_SPB_BUFFER_SIZE 64 27 | #define RESHUB_USE_HELPER_ROUTINES 28 | 29 | // 30 | // SPB (I2C) context 31 | // 32 | 33 | typedef struct _SPB_CONTEXT 34 | { 35 | WDFIOTARGET SpbIoTarget; 36 | LARGE_INTEGER I2cResHubId; 37 | WDFMEMORY WriteMemory; 38 | WDFMEMORY ReadMemory; 39 | WDFWAITLOCK SpbLock; 40 | } SPB_CONTEXT; 41 | 42 | NTSTATUS 43 | SpbXferDataSynchronously( 44 | _In_ SPB_CONTEXT* SpbContext, 45 | _In_ PVOID SendData, 46 | _In_ ULONG SendLength, 47 | _In_reads_bytes_(Length) PVOID Data, 48 | _In_ ULONG Length 49 | ); 50 | 51 | VOID 52 | SpbTargetDeinitialize( 53 | IN WDFDEVICE FxDevice, 54 | IN SPB_CONTEXT* SpbContext 55 | ); 56 | 57 | NTSTATUS 58 | SpbTargetInitialize( 59 | IN WDFDEVICE FxDevice, 60 | IN SPB_CONTEXT* SpbContext 61 | ); 62 | 63 | NTSTATUS 64 | SpbWriteDataSynchronously( 65 | IN SPB_CONTEXT* SpbContext, 66 | IN PVOID Data, 67 | IN ULONG Length 68 | ); -------------------------------------------------------------------------------- /opengmaxcodec/trace.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef _TRACE_H_ 4 | #define _TRACE_H_ 5 | 6 | extern "C" 7 | { 8 | // 9 | // Tracing Definitions: 10 | // 11 | // Control GUID: 12 | // {73e3b785-f5fb-423e-94a9-56627fea9053} 13 | // 14 | 15 | #define WPP_CONTROL_GUIDS \ 16 | WPP_DEFINE_CONTROL_GUID( \ 17 | SpbTestToolTraceGuid, \ 18 | (73e3b785,f5fb,423e,94a9,56627fea9053), \ 19 | WPP_DEFINE_BIT(TRACE_FLAG_WDFLOADING) \ 20 | WPP_DEFINE_BIT(TRACE_FLAG_SPBAPI) \ 21 | WPP_DEFINE_BIT(TRACE_FLAG_OTHER) \ 22 | ) 23 | } 24 | 25 | #define WPP_LEVEL_FLAGS_LOGGER(level,flags) WPP_LEVEL_LOGGER(flags) 26 | #define WPP_LEVEL_FLAGS_ENABLED(level, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= level) 27 | 28 | #define Trace CyapaPrint 29 | #define FuncEntry 30 | #define FuncExit 31 | #define WPP_INIT_TRACING 32 | #define WPP_CLEANUP 33 | #define TRACE_FLAG_SPBAPI 0 34 | #define TRACE_FLAG_WDFLOADING 0 35 | 36 | // begin_wpp config 37 | // FUNC FuncEntry{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS); 38 | // FUNC FuncExit{LEVEL=TRACE_LEVEL_VERBOSE}(FLAGS); 39 | // USEPREFIX(FuncEntry, "%!STDPREFIX! [%!FUNC!] --> entry"); 40 | // USEPREFIX(FuncExit, "%!STDPREFIX! [%!FUNC!] <--"); 41 | // end_wpp 42 | 43 | #endif _TRACE_H_ 44 | -------------------------------------------------------------------------------- /opengmaxcodec/opengmaxcodec.inf: -------------------------------------------------------------------------------- 1 | ;/*++ 2 | ; 3 | ;Copyright (c) CoolStar. All rights reserved. 4 | ; 5 | ;Module Name: 6 | ; coolstar.inf 7 | ; 8 | ;Abstract: 9 | ; INF file for installing the Open Gmax Codec Driver 10 | ; 11 | ; 12 | ;--*/ 13 | 14 | [Version] 15 | Signature = "$WINDOWS NT$" 16 | Class = Media 17 | ClassGuid = {4d36e96c-e325-11ce-bfc1-08002be10318} 18 | Provider = CoolStar 19 | DriverVer = 2/23/2022,1.0.0 20 | CatalogFile = opengmaxcodec.cat 21 | PnpLockdown=1 22 | 23 | [DestinationDirs] 24 | DefaultDestDir = 12 25 | 26 | ; ================= Class section ===================== 27 | 28 | [SourceDisksNames] 29 | 1 = %DiskId1%,,,"" 30 | 31 | [SourceDisksFiles] 32 | opengmaxcodec.sys = 1,, 33 | 34 | ;***************************************** 35 | ; opengmaxcodec Install Section 36 | ;***************************************** 37 | 38 | [Manufacturer] 39 | %StdMfg%=Standard,NTAMD64 40 | 41 | ; Decorated model section take precedence over undecorated 42 | ; ones on XP and later. 43 | [Standard.NTAMD64] 44 | %Max98927.DeviceDesc%=OpenGmaxCodec_Device, ACPI\MX98927 45 | %Max98373.DeviceDesc%=OpenGmaxCodec_Device, ACPI\MX98373 46 | 47 | [OpenGmaxCodec_Device.NT] 48 | CopyFiles=Drivers_Dir 49 | 50 | [OpenGmaxCodec_Device.NT.HW] 51 | Include=pci.inf 52 | Needs=PciD3ColdSupported.HW 53 | 54 | [Drivers_Dir] 55 | opengmaxcodec.sys 56 | 57 | ;-------------- Service installation 58 | [OpenGmaxCodec_Device.NT.Services] 59 | AddService = opengmaxcodec,%SPSVCINST_ASSOCSERVICE%, OpenGmaxCodec_Service_Inst 60 | 61 | ; -------------- opengmaxcodec driver install sections 62 | [OpenGmaxCodec_Service_Inst] 63 | DisplayName = %opengmaxcodec.SVCDESC% 64 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 65 | StartType = 3 ; SERVICE_DEMAND_START 66 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 67 | ServiceBinary = %12%\opengmaxcodec.sys 68 | LoadOrderGroup = Base 69 | 70 | [Strings] 71 | SPSVCINST_ASSOCSERVICE= 0x00000002 72 | StdMfg = "CoolStar" 73 | DiskId1 = "OpenGMaxCodec Installation Disk #1" 74 | Max98927.DeviceDesc = "Maxim 98927 Audio Codec" 75 | Max98373.DeviceDesc = "Maxim 98373 Audio Codec" 76 | opengmaxcodec.SVCDESC = "OpenGMaxCodec Service" 77 | -------------------------------------------------------------------------------- /opengmaxcodec.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32922.545 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opengmaxcodec", "opengmaxcodec\opengmaxcodec.vcxproj", "{36580C07-EDC3-4C2B-B45F-6AB017E01A5D}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opengmaxcodec Package", "opengmaxcodec Package\opengmaxcodec Package.vcxproj", "{3DAE7ED3-003A-4495-8352-3D7B5B5D846F}" 9 | ProjectSection(ProjectDependencies) = postProject 10 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D} = {36580C07-EDC3-4C2B-B45F-6AB017E01A5D} 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|Win32 = Debug|Win32 16 | Debug|x64 = Debug|x64 17 | Release|Win32 = Release|Win32 18 | Release|x64 = Release|x64 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Debug|Win32.ActiveCfg = Debug|Win32 22 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Debug|Win32.Build.0 = Debug|Win32 23 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Debug|Win32.Deploy.0 = Debug|Win32 24 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Debug|x64.ActiveCfg = Debug|x64 25 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Debug|x64.Build.0 = Debug|x64 26 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Debug|x64.Deploy.0 = Debug|x64 27 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Release|Win32.ActiveCfg = Release|Win32 28 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Release|Win32.Build.0 = Release|Win32 29 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Release|Win32.Deploy.0 = Release|Win32 30 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Release|x64.ActiveCfg = Release|x64 31 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Release|x64.Build.0 = Release|x64 32 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D}.Release|x64.Deploy.0 = Release|x64 33 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Debug|Win32.ActiveCfg = Debug|Win32 34 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Debug|Win32.Build.0 = Debug|Win32 35 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Debug|Win32.Deploy.0 = Debug|Win32 36 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Debug|x64.ActiveCfg = Debug|x64 37 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Debug|x64.Build.0 = Debug|x64 38 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Debug|x64.Deploy.0 = Debug|x64 39 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Release|Win32.ActiveCfg = Release|Win32 40 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Release|Win32.Build.0 = Release|Win32 41 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Release|Win32.Deploy.0 = Release|Win32 42 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Release|x64.ActiveCfg = Release|x64 43 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Release|x64.Build.0 = Release|x64 44 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F}.Release|x64.Deploy.0 = Release|x64 45 | EndGlobalSection 46 | GlobalSection(SolutionProperties) = preSolution 47 | HideSolutionNode = FALSE 48 | EndGlobalSection 49 | GlobalSection(ExtensibilityGlobals) = postSolution 50 | SolutionGuid = {9A2670CD-596B-41B9-958C-215F7069D30B} 51 | EndGlobalSection 52 | EndGlobal 53 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2021 CoolStar 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | 16 | ====================== Windows Driver Samples License ====================== 17 | 18 | The Microsoft Public License (MS-PL) 19 | Copyright (c) 2015 Microsoft 20 | 21 | This license governs use of the accompanying software. If you use the software, you 22 | accept this license. If you do not accept the license, do not use the software. 23 | 24 | 1. Definitions 25 | The terms "reproduce," "reproduction," "derivative works," and "distribution" have the 26 | same meaning here as under U.S. copyright law. 27 | A "contribution" is the original software, or any additions or changes to the software. 28 | A "contributor" is any person that distributes its contribution under this license. 29 | "Licensed patents" are a contributor's patent claims that read directly on its contribution. 30 | 31 | 2. Grant of Rights 32 | (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. 33 | (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 34 | 35 | 3. Conditions and Limitations 36 | (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. 37 | (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. 38 | (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. 39 | (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. 40 | (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. -------------------------------------------------------------------------------- /opengmaxcodec/opengmaxcodec.h: -------------------------------------------------------------------------------- 1 | #if !defined(_GMAX_H_) 2 | #define _GMAX_H_ 3 | 4 | #pragma warning(disable:4200) // suppress nameless struct/union warning 5 | #pragma warning(disable:4201) // suppress nameless struct/union warning 6 | #pragma warning(disable:4214) // suppress bit field types other than int warning 7 | #include 8 | #include 9 | 10 | #pragma warning(default:4200) 11 | #pragma warning(default:4201) 12 | #pragma warning(default:4214) 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | 22 | #include "spb.h" 23 | 24 | #define JACKDESC_RGB(r, g, b) \ 25 | ((COLORREF)((r << 16) | (g << 8) | (b))) 26 | 27 | // 28 | // String definitions 29 | // 30 | 31 | #define DRIVERNAME "opengmaxcodec.sys: " 32 | 33 | #define GMAX_POOL_TAG (ULONG) 'B343' 34 | 35 | #define true 1 36 | #define false 0 37 | 38 | typedef enum { 39 | CSAudioEndpointTypeDSP, 40 | CSAudioEndpointTypeSpeaker, 41 | CSAudioEndpointTypeHeadphone, 42 | CSAudioEndpointTypeMicArray, 43 | CSAudioEndpointTypeMicJack 44 | } CSAudioEndpointType; 45 | 46 | typedef enum { 47 | CSAudioEndpointRegister, 48 | CSAudioEndpointStart, 49 | CSAudioEndpointStop, 50 | CSAudioEndpointOverrideFormat 51 | } CSAudioEndpointRequest; 52 | 53 | typedef struct CSAUDIOFORMATOVERRIDE { 54 | UINT16 channels; 55 | UINT16 frequency; 56 | UINT16 bitsPerSample; 57 | UINT16 validBitsPerSample; 58 | BOOL force32BitOutputContainer; 59 | } CsAudioFormatOverride; 60 | 61 | typedef struct CSAUDIOARG { 62 | UINT32 argSz; 63 | CSAudioEndpointType endpointType; 64 | CSAudioEndpointRequest endpointRequest; 65 | union { 66 | CsAudioFormatOverride formatOverride; 67 | }; 68 | } CsAudioArg, * PCsAudioArg; 69 | 70 | typedef struct _GMAX_CONTEXT 71 | { 72 | 73 | WDFDEVICE FxDevice; 74 | 75 | WDFQUEUE ReportQueue; 76 | 77 | SPB_CONTEXT I2CContext; 78 | 79 | BOOLEAN SetUID; 80 | INT32 UID; 81 | 82 | UINT32 chipModel; 83 | 84 | BOOLEAN DevicePoweredOn; 85 | 86 | PCALLBACK_OBJECT CSAudioAPICallback; 87 | PVOID CSAudioAPICallbackObj; 88 | 89 | BOOLEAN CSAudioRequestsOn; 90 | 91 | } GMAX_CONTEXT, *PGMAX_CONTEXT; 92 | 93 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(GMAX_CONTEXT, GetDeviceContext) 94 | 95 | // 96 | // Function definitions 97 | // 98 | 99 | DRIVER_INITIALIZE DriverEntry; 100 | 101 | EVT_WDF_DRIVER_UNLOAD GmaxDriverUnload; 102 | 103 | EVT_WDF_DRIVER_DEVICE_ADD GmaxEvtDeviceAdd; 104 | 105 | EVT_WDFDEVICE_WDM_IRP_PREPROCESS GmaxEvtWdmPreprocessMnQueryId; 106 | 107 | EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL GmaxEvtInternalDeviceControl; 108 | 109 | // 110 | // Helper macros 111 | // 112 | 113 | #define DEBUG_LEVEL_ERROR 1 114 | #define DEBUG_LEVEL_INFO 2 115 | #define DEBUG_LEVEL_VERBOSE 3 116 | 117 | #define DBG_INIT 1 118 | #define DBG_PNP 2 119 | #define DBG_IOCTL 4 120 | 121 | #if 0 122 | #define GmaxPrint(dbglevel, dbgcatagory, fmt, ...) { \ 123 | if (GmaxDebugLevel >= dbglevel && \ 124 | (GmaxDebugCatagories && dbgcatagory)) \ 125 | { \ 126 | DbgPrint(DRIVERNAME); \ 127 | DbgPrint(fmt, __VA_ARGS__); \ 128 | } \ 129 | } 130 | #else 131 | #define GmaxPrint(dbglevel, fmt, ...) { \ 132 | } 133 | #endif 134 | 135 | #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 | -------------------------------------------------------------------------------- /opengmaxcodec Package/opengmaxcodec Package.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {3DAE7ED3-003A-4495-8352-3D7B5B5D846F} 23 | {4605da2c-74a5-4865-98e1-152ef136825f} 24 | v4.5 25 | 11.0 26 | Win8.1 Debug 27 | Win32 28 | opengmaxcodec_Package 29 | $(LatestTargetPlatformVersion) 30 | 31 | 32 | 33 | Windows10 34 | true 35 | WindowsKernelModeDriver10.0 36 | Utility 37 | Package 38 | true 39 | 40 | 41 | Windows10 42 | false 43 | WindowsKernelModeDriver10.0 44 | Utility 45 | Package 46 | true 47 | 48 | 49 | Windows10 50 | true 51 | WindowsKernelModeDriver10.0 52 | Utility 53 | Package 54 | true 55 | 56 | 57 | Windows10 58 | false 59 | WindowsKernelModeDriver10.0 60 | Utility 61 | Package 62 | true 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | DbgengKernelDebugger 74 | False 75 | True 76 | 77 | 78 | 79 | False 80 | False 81 | True 82 | 83 | 133563 84 | 85 | 86 | DbgengKernelDebugger 87 | False 88 | True 89 | 90 | 91 | 92 | False 93 | False 94 | True 95 | 96 | 133563 97 | 98 | 99 | DbgengKernelDebugger 100 | False 101 | True 102 | 103 | 104 | 105 | False 106 | False 107 | True 108 | 109 | 133563 110 | 111 | 112 | DbgengKernelDebugger 113 | False 114 | True 115 | 116 | 117 | 118 | False 119 | False 120 | True 121 | 122 | 133563 123 | 124 | 125 | 126 | SHA256 127 | 128 | 129 | 130 | 131 | SHA256 132 | 133 | 134 | 135 | 136 | SHA256 137 | 138 | 139 | 140 | 141 | SHA256 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | {36580c07-edc3-4c2b-b45f-6ab017e01a5d} 150 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /opengmaxcodec/opengmaxcodec.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {36580C07-EDC3-4C2B-B45F-6AB017E01A5D} 23 | {1bc93793-694f-48fe-9372-81e2b05556fd} 24 | v4.5 25 | 11.0 26 | Win8.1 Debug 27 | Win32 28 | opengmaxcodec 29 | 30 | 31 | 32 | Windows10 33 | true 34 | WindowsKernelModeDriver10.0 35 | Driver 36 | KMDF 37 | 38 | 39 | Windows10 40 | false 41 | WindowsKernelModeDriver10.0 42 | Driver 43 | KMDF 44 | 45 | 46 | Windows10 47 | true 48 | WindowsKernelModeDriver10.0 49 | Driver 50 | KMDF 51 | 52 | 53 | Windows10 54 | false 55 | WindowsKernelModeDriver10.0 56 | Driver 57 | KMDF 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | DbgengKernelDebugger 69 | 70 | 71 | DbgengKernelDebugger 72 | 73 | 74 | DbgengKernelDebugger 75 | 76 | 77 | DbgengKernelDebugger 78 | 79 | 80 | 81 | true 82 | trace.h 83 | true 84 | false 85 | 86 | 87 | 1.0.1 88 | 89 | 90 | SHA256 91 | 92 | 93 | 94 | 95 | true 96 | trace.h 97 | true 98 | false 99 | 100 | 101 | 1.0.1 102 | 103 | 104 | SHA256 105 | 106 | 107 | 108 | 109 | true 110 | trace.h 111 | true 112 | false 113 | 114 | 115 | 1.0.1 116 | 117 | 118 | SHA256 119 | 120 | 121 | 122 | 123 | true 124 | trace.h 125 | true 126 | false 127 | 128 | 129 | 1.0.1 130 | 131 | 132 | SHA256 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /opengmaxcodec/max98373.h: -------------------------------------------------------------------------------- 1 | #include "stdint.h" 2 | 3 | #ifndef _MAX98373_H 4 | #define _MAX98373_H 5 | 6 | #define MAX98373_R2000_SW_RESET 0x2000 7 | #define MAX98373_R2001_INT_RAW1 0x2001 8 | #define MAX98373_R2002_INT_RAW2 0x2002 9 | #define MAX98373_R2003_INT_RAW3 0x2003 10 | #define MAX98373_R2004_INT_STATE1 0x2004 11 | #define MAX98373_R2005_INT_STATE2 0x2005 12 | #define MAX98373_R2006_INT_STATE3 0x2006 13 | #define MAX98373_R2007_INT_FLAG1 0x2007 14 | #define MAX98373_R2008_INT_FLAG2 0x2008 15 | #define MAX98373_R2009_INT_FLAG3 0x2009 16 | #define MAX98373_R200A_INT_EN1 0x200A 17 | #define MAX98373_R200B_INT_EN2 0x200B 18 | #define MAX98373_R200C_INT_EN3 0x200C 19 | #define MAX98373_R200D_INT_FLAG_CLR1 0x200D 20 | #define MAX98373_R200E_INT_FLAG_CLR2 0x200E 21 | #define MAX98373_R200F_INT_FLAG_CLR3 0x200F 22 | #define MAX98373_R2010_IRQ_CTRL 0x2010 23 | #define MAX98373_R2014_THERM_WARN_THRESH 0x2014 24 | #define MAX98373_R2015_THERM_SHDN_THRESH 0x2015 25 | #define MAX98373_R2016_THERM_HYSTERESIS 0x2016 26 | #define MAX98373_R2017_THERM_FOLDBACK_SET 0x2017 27 | #define MAX98373_R2018_THERM_FOLDBACK_EN 0x2018 28 | #define MAX98373_R201E_PIN_DRIVE_STRENGTH 0x201E 29 | #define MAX98373_R2020_PCM_TX_HIZ_EN_1 0x2020 30 | #define MAX98373_R2021_PCM_TX_HIZ_EN_2 0x2021 31 | #define MAX98373_R2022_PCM_TX_SRC_1 0x2022 32 | #define MAX98373_R2023_PCM_TX_SRC_2 0x2023 33 | #define MAX98373_R2024_PCM_DATA_FMT_CFG 0x2024 34 | #define MAX98373_R2025_AUDIO_IF_MODE 0x2025 35 | #define MAX98373_R2026_PCM_CLOCK_RATIO 0x2026 36 | #define MAX98373_R2027_PCM_SR_SETUP_1 0x2027 37 | #define MAX98373_R2028_PCM_SR_SETUP_2 0x2028 38 | #define MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1 0x2029 39 | #define MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2 0x202A 40 | #define MAX98373_R202B_PCM_RX_EN 0x202B 41 | #define MAX98373_R202C_PCM_TX_EN 0x202C 42 | #define MAX98373_R202E_ICC_RX_CH_EN_1 0x202E 43 | #define MAX98373_R202F_ICC_RX_CH_EN_2 0x202F 44 | #define MAX98373_R2030_ICC_TX_HIZ_EN_1 0x2030 45 | #define MAX98373_R2031_ICC_TX_HIZ_EN_2 0x2031 46 | #define MAX98373_R2032_ICC_LINK_EN_CFG 0x2032 47 | #define MAX98373_R2034_ICC_TX_CNTL 0x2034 48 | #define MAX98373_R2035_ICC_TX_EN 0x2035 49 | #define MAX98373_R2036_SOUNDWIRE_CTRL 0x2036 50 | #define MAX98373_R203D_AMP_DIG_VOL_CTRL 0x203D 51 | #define MAX98373_R203E_AMP_PATH_GAIN 0x203E 52 | #define MAX98373_R203F_AMP_DSP_CFG 0x203F 53 | #define MAX98373_R2040_TONE_GEN_CFG 0x2040 54 | #define MAX98373_R2041_AMP_CFG 0x2041 55 | #define MAX98373_R2042_AMP_EDGE_RATE_CFG 0x2042 56 | #define MAX98373_R2043_AMP_EN 0x2043 57 | #define MAX98373_R2046_IV_SENSE_ADC_DSP_CFG 0x2046 58 | #define MAX98373_R2047_IV_SENSE_ADC_EN 0x2047 59 | #define MAX98373_R2051_MEAS_ADC_SAMPLING_RATE 0x2051 60 | #define MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG 0x2052 61 | #define MAX98373_R2053_MEAS_ADC_THERM_FLT_CFG 0x2053 62 | #define MAX98373_R2054_MEAS_ADC_PVDD_CH_READBACK 0x2054 63 | #define MAX98373_R2055_MEAS_ADC_THERM_CH_READBACK 0x2055 64 | #define MAX98373_R2056_MEAS_ADC_PVDD_CH_EN 0x2056 65 | #define MAX98373_R2090_BDE_LVL_HOLD 0x2090 66 | #define MAX98373_R2091_BDE_GAIN_ATK_REL_RATE 0x2091 67 | #define MAX98373_R2092_BDE_CLIPPER_MODE 0x2092 68 | #define MAX98373_R2097_BDE_L1_THRESH 0x2097 69 | #define MAX98373_R2098_BDE_L2_THRESH 0x2098 70 | #define MAX98373_R2099_BDE_L3_THRESH 0x2099 71 | #define MAX98373_R209A_BDE_L4_THRESH 0x209A 72 | #define MAX98373_R209B_BDE_THRESH_HYST 0x209B 73 | #define MAX98373_R20A8_BDE_L1_CFG_1 0x20A8 74 | #define MAX98373_R20A9_BDE_L1_CFG_2 0x20A9 75 | #define MAX98373_R20AA_BDE_L1_CFG_3 0x20AA 76 | #define MAX98373_R20AB_BDE_L2_CFG_1 0x20AB 77 | #define MAX98373_R20AC_BDE_L2_CFG_2 0x20AC 78 | #define MAX98373_R20AD_BDE_L2_CFG_3 0x20AD 79 | #define MAX98373_R20AE_BDE_L3_CFG_1 0x20AE 80 | #define MAX98373_R20AF_BDE_L3_CFG_2 0x20AF 81 | #define MAX98373_R20B0_BDE_L3_CFG_3 0x20B0 82 | #define MAX98373_R20B1_BDE_L4_CFG_1 0x20B1 83 | #define MAX98373_R20B2_BDE_L4_CFG_2 0x20B2 84 | #define MAX98373_R20B3_BDE_L4_CFG_3 0x20B3 85 | #define MAX98373_R20B4_BDE_INFINITE_HOLD_RELEASE 0x20B4 86 | #define MAX98373_R20B5_BDE_EN 0x20B5 87 | #define MAX98373_R20B6_BDE_CUR_STATE_READBACK 0x20B6 88 | #define MAX98373_R20D1_DHT_CFG 0x20D1 89 | #define MAX98373_R20D2_DHT_ATTACK_CFG 0x20D2 90 | #define MAX98373_R20D3_DHT_RELEASE_CFG 0x20D3 91 | #define MAX98373_R20D4_DHT_EN 0x20D4 92 | #define MAX98373_R20E0_LIMITER_THRESH_CFG 0x20E0 93 | #define MAX98373_R20E1_LIMITER_ATK_REL_RATES 0x20E1 94 | #define MAX98373_R20E2_LIMITER_EN 0x20E2 95 | #define MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG 0x20FE 96 | #define MAX98373_R20FF_GLOBAL_SHDN 0x20FF 97 | #define MAX98373_R21FF_REV_ID 0x21FF 98 | 99 | /* MAX98373_R2022_PCM_TX_SRC_1 */ 100 | #define MAX98373_PCM_TX_CH_SRC_A_V_SHIFT (0) 101 | #define MAX98373_PCM_TX_CH_SRC_A_I_SHIFT (4) 102 | 103 | /* MAX98373_R2024_PCM_DATA_FMT_CFG */ 104 | #define MAX98373_PCM_MODE_CFG_FORMAT_MASK (0x7 << 3) 105 | #define MAX98373_PCM_MODE_CFG_FORMAT_SHIFT (3) 106 | #define MAX98373_PCM_TX_CH_INTERLEAVE_MASK (0x1 << 2) 107 | #define MAX98373_PCM_FORMAT_I2S (0x0 << 0) 108 | #define MAX98373_PCM_FORMAT_LJ (0x1 << 0) 109 | #define MAX98373_PCM_FORMAT_TDM_MODE0 (0x3 << 0) 110 | #define MAX98373_PCM_FORMAT_TDM_MODE1 (0x4 << 0) 111 | #define MAX98373_PCM_FORMAT_TDM_MODE2 (0x5 << 0) 112 | #define MAX98373_PCM_MODE_CFG_CHANSZ_MASK (0x3 << 6) 113 | #define MAX98373_PCM_MODE_CFG_CHANSZ_16 (0x1 << 6) 114 | #define MAX98373_PCM_MODE_CFG_CHANSZ_24 (0x2 << 6) 115 | #define MAX98373_PCM_MODE_CFG_CHANSZ_32 (0x3 << 6) 116 | 117 | /* MAX98373_R2026_PCM_CLOCK_RATIO */ 118 | #define MAX98373_PCM_MODE_CFG_PCM_BCLKEDGE (0x1 << 4) 119 | #define MAX98373_PCM_CLK_SETUP_BSEL_MASK (0xF << 0) 120 | 121 | /* MAX98373_R2027_PCM_SR_SETUP_1 */ 122 | #define MAX98373_PCM_SR_SET1_SR_MASK (0xF << 0) 123 | #define MAX98373_PCM_SR_SET1_SR_8000 (0x0 << 0) 124 | #define MAX98373_PCM_SR_SET1_SR_11025 (0x1 << 0) 125 | #define MAX98373_PCM_SR_SET1_SR_12000 (0x2 << 0) 126 | #define MAX98373_PCM_SR_SET1_SR_16000 (0x3 << 0) 127 | #define MAX98373_PCM_SR_SET1_SR_22050 (0x4 << 0) 128 | #define MAX98373_PCM_SR_SET1_SR_24000 (0x5 << 0) 129 | #define MAX98373_PCM_SR_SET1_SR_32000 (0x6 << 0) 130 | #define MAX98373_PCM_SR_SET1_SR_44100 (0x7 << 0) 131 | #define MAX98373_PCM_SR_SET1_SR_48000 (0x8 << 0) 132 | #define MAX98373_PCM_SR_SET1_SR_88200 (0x9 << 0) 133 | #define MAX98373_PCM_SR_SET1_SR_96000 (0xA << 0) 134 | 135 | /* MAX98373_R2028_PCM_SR_SETUP_2 */ 136 | #define MAX98373_PCM_SR_SET2_SR_MASK (0xF << 4) 137 | #define MAX98373_PCM_SR_SET2_SR_SHIFT (4) 138 | #define MAX98373_PCM_SR_SET2_IVADC_SR_MASK (0xF << 0) 139 | 140 | /* MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1 */ 141 | #define MAX98373_PCM_TO_SPK_MONOMIX_CFG_MASK (0x3 << 6) 142 | #define MAX98373_PCM_TO_SPK_MONOMIX_CFG_SHIFT (6) 143 | #define MAX98373_PCM_TO_SPK_CH0_SRC_MASK (0xF << 0) 144 | 145 | /* MAX98373_R203E_AMP_PATH_GAIN */ 146 | #define MAX98373_SPK_DIGI_GAIN_MASK (0xF << 4) 147 | #define MAX98373_SPK_DIGI_GAIN_SHIFT (4) 148 | #define MAX98373_FS_GAIN_MAX_MASK (0xF << 0) 149 | #define MAX98373_FS_GAIN_MAX_SHIFT (0) 150 | 151 | /* MAX98373_R203F_AMP_DSP_CFG */ 152 | #define MAX98373_AMP_DSP_CFG_DCBLK_SHIFT (0) 153 | #define MAX98373_AMP_DSP_CFG_DITH_SHIFT (1) 154 | #define MAX98373_AMP_DSP_CFG_RMP_UP_SHIFT (2) 155 | #define MAX98373_AMP_DSP_CFG_RMP_DN_SHIFT (3) 156 | #define MAX98373_AMP_DSP_CFG_DAC_INV_SHIFT (5) 157 | #define MAX98373_AMP_VOL_SEL_SHIFT (7) 158 | 159 | /* MAX98373_R2043_AMP_EN */ 160 | #define MAX98373_SPKFB_EN_MASK (0x1 << 1) 161 | #define MAX98373_SPK_EN_MASK (0x1 << 0) 162 | #define MAX98373_SPKFB_EN_SHIFT (1) 163 | 164 | /*MAX98373_R2052_MEAS_ADC_PVDD_FLT_CFG */ 165 | #define MAX98373_FLT_EN_SHIFT (4) 166 | 167 | /* MAX98373_R20B2_BDE_L4_CFG_2 */ 168 | #define MAX98373_LVL4_MUTE_EN_SHIFT (7) 169 | #define MAX98373_LVL4_HOLD_EN_SHIFT (6) 170 | 171 | /* MAX98373_R20B5_BDE_EN */ 172 | #define MAX98373_BDE_EN_SHIFT (0) 173 | 174 | /* MAX98373_R20D1_DHT_CFG */ 175 | #define MAX98373_DHT_SPK_GAIN_MIN_SHIFT (4) 176 | #define MAX98373_DHT_ROT_PNT_SHIFT (0) 177 | 178 | /* MAX98373_R20D2_DHT_ATTACK_CFG */ 179 | #define MAX98373_DHT_ATTACK_STEP_SHIFT (3) 180 | #define MAX98373_DHT_ATTACK_RATE_SHIFT (0) 181 | 182 | /* MAX98373_R20D3_DHT_RELEASE_CFG */ 183 | #define MAX98373_DHT_RELEASE_STEP_SHIFT (3) 184 | #define MAX98373_DHT_RELEASE_RATE_SHIFT (0) 185 | 186 | /* MAX98373_R20D4_DHT_EN */ 187 | #define MAX98373_DHT_EN_SHIFT (0) 188 | 189 | /* MAX98373_R20E0_LIMITER_THRESH_CFG */ 190 | #define MAX98373_LIMITER_THRESH_SHIFT (2) 191 | #define MAX98373_LIMITER_THRESH_SRC_SHIFT (0) 192 | 193 | /* MAX98373_R20E2_LIMITER_EN */ 194 | #define MAX98373_LIMITER_EN_SHIFT (0) 195 | 196 | /* MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG */ 197 | #define MAX98373_OVC_AUTORESTART_SHIFT (3) 198 | #define MAX98373_THERM_AUTORESTART_SHIFT (2) 199 | #define MAX98373_CMON_AUTORESTART_SHIFT (1) 200 | #define MAX98373_CLOCK_MON_SHIFT (0) 201 | 202 | /* MAX98373_R20FF_GLOBAL_SHDN */ 203 | #define MAX98373_GLOBAL_EN_MASK (0x1 << 0) 204 | 205 | /* MAX98373_R2000_SW_RESET */ 206 | #define MAX98373_SOFT_RESET (0x1 << 0) 207 | 208 | #endif -------------------------------------------------------------------------------- /opengmaxcodec/max98927.h: -------------------------------------------------------------------------------- 1 | #include "stdint.h" 2 | 3 | #ifndef _MAX98927_H 4 | #define _MAX98927_H 5 | 6 | /* Register Values */ 7 | #define MAX98927_R0001_INT_RAW1 0x0001 8 | #define MAX98927_R0002_INT_RAW2 0x0002 9 | #define MAX98927_R0003_INT_RAW3 0x0003 10 | #define MAX98927_R0004_INT_STATE1 0x0004 11 | #define MAX98927_R0005_INT_STATE2 0x0005 12 | #define MAX98927_R0006_INT_STATE3 0x0006 13 | #define MAX98927_R0007_INT_FLAG1 0x0007 14 | #define MAX98927_R0008_INT_FLAG2 0x0008 15 | #define MAX98927_R0009_INT_FLAG3 0x0009 16 | #define MAX98927_R000A_INT_EN1 0x000A 17 | #define MAX98927_R000B_INT_EN2 0x000B 18 | #define MAX98927_R000C_INT_EN3 0x000C 19 | #define MAX98927_R000D_INT_FLAG_CLR1 0x000D 20 | #define MAX98927_R000E_INT_FLAG_CLR2 0x000E 21 | #define MAX98927_R000F_INT_FLAG_CLR3 0x000F 22 | #define MAX98927_R0010_IRQ_CTRL 0x0010 23 | #define MAX98927_R0011_CLK_MON 0x0011 24 | #define MAX98927_R0012_WDOG_CTRL 0x0012 25 | #define MAX98927_R0013_WDOG_RST 0x0013 26 | #define MAX98927_R0014_MEAS_ADC_THERM_WARN_THRESH 0x0014 27 | #define MAX98927_R0015_MEAS_ADC_THERM_SHDN_THRESH 0x0015 28 | #define MAX98927_R0016_MEAS_ADC_THERM_HYSTERESIS 0x0016 29 | #define MAX98927_R0017_PIN_CFG 0x0017 30 | #define MAX98927_R0018_PCM_RX_EN_A 0x0018 31 | #define MAX98927_R0019_PCM_RX_EN_B 0x0019 32 | #define MAX98927_R001A_PCM_TX_EN_A 0x001A 33 | #define MAX98927_R001B_PCM_TX_EN_B 0x001B 34 | #define MAX98927_R001C_PCM_TX_HIZ_CTRL_A 0x001C 35 | #define MAX98927_R001D_PCM_TX_HIZ_CTRL_B 0x001D 36 | #define MAX98927_R001E_PCM_TX_CH_SRC_A 0x001E 37 | #define MAX98927_R001F_PCM_TX_CH_SRC_B 0x001F 38 | #define MAX98927_R0020_PCM_MODE_CFG 0x0020 39 | #define MAX98927_R0021_PCM_MASTER_MODE 0x0021 40 | #define MAX98927_R0022_PCM_CLK_SETUP 0x0022 41 | #define MAX98927_R0023_PCM_SR_SETUP1 0x0023 42 | #define MAX98927_R0024_PCM_SR_SETUP2 0x0024 43 | #define MAX98927_R0025_PCM_TO_SPK_MONOMIX_A 0x0025 44 | #define MAX98927_R0026_PCM_TO_SPK_MONOMIX_B 0x0026 45 | #define MAX98927_R0027_ICC_RX_EN_A 0x0027 46 | #define MAX98927_R0028_ICC_RX_EN_B 0x0028 47 | #define MAX98927_R002B_ICC_TX_EN_A 0x002B 48 | #define MAX98927_R002C_ICC_TX_EN_B 0x002C 49 | #define MAX98927_R002E_ICC_HIZ_MANUAL_MODE 0x002E 50 | #define MAX98927_R002F_ICC_TX_HIZ_EN_A 0x002F 51 | #define MAX98927_R0030_ICC_TX_HIZ_EN_B 0x0030 52 | #define MAX98927_R0031_ICC_LNK_EN 0x0031 53 | #define MAX98927_R0032_PDM_TX_EN 0x0032 54 | #define MAX98927_R0033_PDM_TX_HIZ_CTRL 0x0033 55 | #define MAX98927_R0034_PDM_TX_CTRL 0x0034 56 | #define MAX98927_R0035_PDM_RX_CTRL 0x0035 57 | #define MAX98927_R0036_AMP_VOL_CTRL 0x0036 58 | #define MAX98927_R0037_AMP_DSP_CFG 0x0037 59 | #define MAX98927_R0038_TONE_GEN_DC_CFG 0x0038 60 | #define MAX98927_R0039_DRE_CTRL 0x0039 61 | #define MAX98927_R003A_AMP_EN 0x003A 62 | #define MAX98927_R003B_SPK_SRC_SEL 0x003B 63 | #define MAX98927_R003C_SPK_GAIN 0x003C 64 | #define MAX98927_R003D_SSM_CFG 0x003D 65 | #define MAX98927_R003E_MEAS_EN 0x003E 66 | #define MAX98927_R003F_MEAS_DSP_CFG 0x003F 67 | #define MAX98927_R0040_BOOST_CTRL0 0x0040 68 | #define MAX98927_R0041_BOOST_CTRL3 0x0041 69 | #define MAX98927_R0042_BOOST_CTRL1 0x0042 70 | #define MAX98927_R0043_MEAS_ADC_CFG 0x0043 71 | #define MAX98927_R0044_MEAS_ADC_BASE_MSB 0x0044 72 | #define MAX98927_R0045_MEAS_ADC_BASE_LSB 0x0045 73 | #define MAX98927_R0046_ADC_CH0_DIVIDE 0x0046 74 | #define MAX98927_R0047_ADC_CH1_DIVIDE 0x0047 75 | #define MAX98927_R0048_ADC_CH2_DIVIDE 0x0048 76 | #define MAX98927_R0049_ADC_CH0_FILT_CFG 0x0049 77 | #define MAX98927_R004A_ADC_CH1_FILT_CFG 0x004A 78 | #define MAX98927_R004B_ADC_CH2_FILT_CFG 0x004B 79 | #define MAX98927_R004C_MEAS_ADC_CH0_READ 0x004C 80 | #define MAX98927_R004D_MEAS_ADC_CH1_READ 0x004D 81 | #define MAX98927_R004E_MEAS_ADC_CH2_READ 0x004E 82 | #define MAX98927_R0051_BROWNOUT_STATUS 0x0051 83 | #define MAX98927_R0052_BROWNOUT_EN 0x0052 84 | #define MAX98927_R0053_BROWNOUT_INFINITE_HOLD 0x0053 85 | #define MAX98927_R0054_BROWNOUT_INFINITE_HOLD_CLR 0x0054 86 | #define MAX98927_R0055_BROWNOUT_LVL_HOLD 0x0055 87 | #define MAX98927_R005A_BROWNOUT_LVL1_THRESH 0x005A 88 | #define MAX98927_R005B_BROWNOUT_LVL2_THRESH 0x005B 89 | #define MAX98927_R005C_BROWNOUT_LVL3_THRESH 0x005C 90 | #define MAX98927_R005D_BROWNOUT_LVL4_THRESH 0x005D 91 | #define MAX98927_R005E_BROWNOUT_THRESH_HYSTERYSIS 0x005E 92 | #define MAX98927_R005F_BROWNOUT_AMP_LIMITER_ATK_REL 0x005F 93 | #define MAX98927_R0060_BROWNOUT_AMP_GAIN_ATK_REL 0x0060 94 | #define MAX98927_R0061_BROWNOUT_AMP1_CLIP_MODE 0x0061 95 | #define MAX98927_R0072_BROWNOUT_LVL1_CUR_LIMIT 0x0072 96 | #define MAX98927_R0073_BROWNOUT_LVL1_AMP1_CTRL1 0x0073 97 | #define MAX98927_R0074_BROWNOUT_LVL1_AMP1_CTRL2 0x0074 98 | #define MAX98927_R0075_BROWNOUT_LVL1_AMP1_CTRL3 0x0075 99 | #define MAX98927_R0076_BROWNOUT_LVL2_CUR_LIMIT 0x0076 100 | #define MAX98927_R0077_BROWNOUT_LVL2_AMP1_CTRL1 0x0077 101 | #define MAX98927_R0078_BROWNOUT_LVL2_AMP1_CTRL2 0x0078 102 | #define MAX98927_R0079_BROWNOUT_LVL2_AMP1_CTRL3 0x0079 103 | #define MAX98927_R007A_BROWNOUT_LVL3_CUR_LIMIT 0x007A 104 | #define MAX98927_R007B_BROWNOUT_LVL3_AMP1_CTRL1 0x007B 105 | #define MAX98927_R007C_BROWNOUT_LVL3_AMP1_CTRL2 0x007C 106 | #define MAX98927_R007D_BROWNOUT_LVL3_AMP1_CTRL3 0x007D 107 | #define MAX98927_R007E_BROWNOUT_LVL4_CUR_LIMIT 0x007E 108 | #define MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1 0x007F 109 | #define MAX98927_R0080_BROWNOUT_LVL4_AMP1_CTRL2 0x0080 110 | #define MAX98927_R0081_BROWNOUT_LVL4_AMP1_CTRL3 0x0081 111 | #define MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM 0x0082 112 | #define MAX98927_R0083_ENV_TRACK_BOOST_VOUT_DELAY 0x0083 113 | #define MAX98927_R0084_ENV_TRACK_REL_RATE 0x0084 114 | #define MAX98927_R0085_ENV_TRACK_HOLD_RATE 0x0085 115 | #define MAX98927_R0086_ENV_TRACK_CTRL 0x0086 116 | #define MAX98927_R0087_ENV_TRACK_BOOST_VOUT_READ 0x0087 117 | #define MAX98927_R00FF_GLOBAL_SHDN 0x00FF 118 | #define MAX98927_R0100_SOFT_RESET 0x0100 119 | #define MAX98927_R01FF_REV_ID 0x01FF 120 | 121 | /* MAX98927_R0018_PCM_RX_EN_A */ 122 | #define MAX98927_PCM_RX_CH0_EN (0x1 << 0) 123 | #define MAX98927_PCM_RX_CH1_EN (0x1 << 1) 124 | #define MAX98927_PCM_RX_CH2_EN (0x1 << 2) 125 | #define MAX98927_PCM_RX_CH3_EN (0x1 << 3) 126 | #define MAX98927_PCM_RX_CH4_EN (0x1 << 4) 127 | #define MAX98927_PCM_RX_CH5_EN (0x1 << 5) 128 | #define MAX98927_PCM_RX_CH6_EN (0x1 << 6) 129 | #define MAX98927_PCM_RX_CH7_EN (0x1 << 7) 130 | 131 | /* MAX98927_R001A_PCM_TX_EN_A */ 132 | #define MAX98927_PCM_TX_CH0_EN (0x1 << 0) 133 | #define MAX98927_PCM_TX_CH1_EN (0x1 << 1) 134 | #define MAX98927_PCM_TX_CH2_EN (0x1 << 2) 135 | #define MAX98927_PCM_TX_CH3_EN (0x1 << 3) 136 | #define MAX98927_PCM_TX_CH4_EN (0x1 << 4) 137 | #define MAX98927_PCM_TX_CH5_EN (0x1 << 5) 138 | #define MAX98927_PCM_TX_CH6_EN (0x1 << 6) 139 | #define MAX98927_PCM_TX_CH7_EN (0x1 << 7) 140 | 141 | /* MAX98927_R001E_PCM_TX_CH_SRC_A */ 142 | #define MAX98927_PCM_TX_CH_SRC_A_V_SHIFT (0) 143 | #define MAX98927_PCM_TX_CH_SRC_A_I_SHIFT (4) 144 | 145 | /* MAX98927_R001F_PCM_TX_CH_SRC_B */ 146 | #define MAX98927_PCM_TX_CH_INTERLEAVE_MASK (0x1 << 5) 147 | 148 | /* MAX98927_R0020_PCM_MODE_CFG */ 149 | #define MAX98927_PCM_MODE_CFG_PCM_BCLKEDGE (0x1 << 2) 150 | #define MAX98927_PCM_MODE_CFG_FORMAT_MASK (0x7 << 3) 151 | #define MAX98927_PCM_MODE_CFG_FORMAT_SHIFT (3) 152 | #define MAX98927_PCM_FORMAT_I2S (0x0 << 0) 153 | #define MAX98927_PCM_FORMAT_LJ (0x1 << 0) 154 | #define MAX98927_PCM_FORMAT_TDM_MODE0 (0x3 << 0) 155 | #define MAX98927_PCM_FORMAT_TDM_MODE1 (0x4 << 0) 156 | #define MAX98927_PCM_FORMAT_TDM_MODE2 (0x5 << 0) 157 | #define MAX98927_PCM_MODE_CFG_CHANSZ_MASK (0x3 << 6) 158 | #define MAX98927_PCM_MODE_CFG_CHANSZ_16 (0x1 << 6) 159 | #define MAX98927_PCM_MODE_CFG_CHANSZ_24 (0x2 << 6) 160 | #define MAX98927_PCM_MODE_CFG_CHANSZ_32 (0x3 << 6) 161 | 162 | /* MAX98927_R0021_PCM_MASTER_MODE */ 163 | #define MAX98927_PCM_MASTER_MODE_MASK (0x3 << 0) 164 | #define MAX98927_PCM_MASTER_MODE_SLAVE (0x0 << 0) 165 | #define MAX98927_PCM_MASTER_MODE_MASTER (0x3 << 0) 166 | 167 | #define MAX98927_PCM_MASTER_MODE_MCLK_MASK (0xF << 2) 168 | #define MAX98927_PCM_MASTER_MODE_MCLK_RATE_SHIFT (2) 169 | 170 | /* MAX98927_R0022_PCM_CLK_SETUP */ 171 | #define MAX98927_PCM_CLK_SETUP_BSEL_MASK (0xF << 0) 172 | 173 | /* MAX98927_R0023_PCM_SR_SETUP1 */ 174 | #define MAX98927_PCM_SR_SET1_SR_MASK (0xF << 0) 175 | 176 | #define MAX98927_PCM_SR_SET1_SR_8000 (0x0 << 0) 177 | #define MAX98927_PCM_SR_SET1_SR_11025 (0x1 << 0) 178 | #define MAX98927_PCM_SR_SET1_SR_12000 (0x2 << 0) 179 | #define MAX98927_PCM_SR_SET1_SR_16000 (0x3 << 0) 180 | #define MAX98927_PCM_SR_SET1_SR_22050 (0x4 << 0) 181 | #define MAX98927_PCM_SR_SET1_SR_24000 (0x5 << 0) 182 | #define MAX98927_PCM_SR_SET1_SR_32000 (0x6 << 0) 183 | #define MAX98927_PCM_SR_SET1_SR_44100 (0x7 << 0) 184 | #define MAX98927_PCM_SR_SET1_SR_48000 (0x8 << 0) 185 | 186 | /* MAX98927_R0024_PCM_SR_SETUP2 */ 187 | #define MAX98927_PCM_SR_SET2_SR_MASK (0xF << 4) 188 | #define MAX98927_PCM_SR_SET2_SR_SHIFT (4) 189 | #define MAX98927_PCM_SR_SET2_IVADC_SR_MASK (0xf << 0) 190 | 191 | /* MAX98927_R0025_PCM_TO_SPK_MONOMIX_A */ 192 | #define MAX98927_PCM_TO_SPK_MONOMIX_CFG_MASK (0x3 << 6) 193 | #define MAX98927_PCM_TO_SPK_MONOMIX_CFG_SHIFT (6) 194 | 195 | /* MAX98927_R0035_PDM_RX_CTRL */ 196 | #define MAX98927_PDM_RX_EN_MASK (0x1 << 0) 197 | 198 | /* MAX98927_R0036_AMP_VOL_CTRL */ 199 | #define MAX98927_AMP_VOL_SEL (0x1 << 7) 200 | #define MAX98927_AMP_VOL_SEL_WIDTH (1) 201 | #define MAX98927_AMP_VOL_SEL_SHIFT (7) 202 | #define MAX98927_AMP_VOL_MASK (0x7f << 0) 203 | #define MAX98927_AMP_VOL_WIDTH (7) 204 | #define MAX98927_AMP_VOL_SHIFT (0) 205 | 206 | /* MAX98927_R0037_AMP_DSP_CFG */ 207 | #define MAX98927_AMP_DSP_CFG_DCBLK_EN (0x1 << 0) 208 | #define MAX98927_AMP_DSP_CFG_DITH_EN (0x1 << 1) 209 | #define MAX98927_AMP_DSP_CFG_RMP_BYPASS (0x1 << 4) 210 | #define MAX98927_AMP_DSP_CFG_DAC_INV (0x1 << 5) 211 | #define MAX98927_AMP_DSP_CFG_RMP_SHIFT (4) 212 | 213 | /* MAX98927_R0039_DRE_CTRL */ 214 | #define MAX98927_DRE_CTRL_DRE_EN (0x1 << 0) 215 | #define MAX98927_DRE_EN_SHIFT 0x1 216 | 217 | /* MAX98927_R003A_AMP_EN */ 218 | #define MAX98927_AMP_EN_MASK (0x1 << 0) 219 | 220 | /* MAX98927_R003B_SPK_SRC_SEL */ 221 | #define MAX98927_SPK_SRC_MASK (0x3 << 0) 222 | 223 | /* MAX98927_R003C_SPK_GAIN */ 224 | #define MAX98927_SPK_PCM_GAIN_MASK (0x7 << 0) 225 | #define MAX98927_SPK_PDM_GAIN_MASK (0x7 << 4) 226 | #define MAX98927_SPK_GAIN_WIDTH (3) 227 | 228 | /* MAX98927_R003E_MEAS_EN */ 229 | #define MAX98927_MEAS_V_EN (0x1 << 0) 230 | #define MAX98927_MEAS_I_EN (0x1 << 1) 231 | 232 | /* MAX98927_R0040_BOOST_CTRL0 */ 233 | #define MAX98927_BOOST_CTRL0_VOUT_MASK (0x1f << 0) 234 | #define MAX98927_BOOST_CTRL0_PVDD_MASK (0x1 << 7) 235 | #define MAX98927_BOOST_CTRL0_PVDD_EN_SHIFT (7) 236 | 237 | /* MAX98927_R0052_BROWNOUT_EN */ 238 | #define MAX98927_BROWNOUT_BDE_EN (0x1 << 0) 239 | #define MAX98927_BROWNOUT_AMP_EN (0x1 << 1) 240 | #define MAX98927_BROWNOUT_DSP_EN (0x1 << 2) 241 | #define MAX98927_BROWNOUT_DSP_SHIFT (2) 242 | 243 | /* MAX98927_R0100_SOFT_RESET */ 244 | #define MAX98927_SOFT_RESET (0x1 << 0) 245 | 246 | /* MAX98927_R00FF_GLOBAL_SHDN */ 247 | #define MAX98927_GLOBAL_EN_MASK (0x1 << 0) 248 | 249 | #endif -------------------------------------------------------------------------------- /opengmaxcodec/spb.c: -------------------------------------------------------------------------------- 1 | /*++ 2 | Copyright (c) Microsoft Corporation. All Rights Reserved. 3 | Sample code. Dealpoint ID #843729. 4 | 5 | Module Name: 6 | 7 | spb.c 8 | 9 | Abstract: 10 | 11 | Contains all I2C-specific functionality 12 | 13 | Environment: 14 | 15 | Kernel mode 16 | 17 | Revision History: 18 | 19 | --*/ 20 | 21 | #include "opengmaxcodec.h" 22 | #include "spb.h" 23 | #include 24 | #include 25 | 26 | static ULONG GmaxDebugLevel = 100; 27 | static ULONG GmaxDebugCatagories = DBG_INIT || DBG_PNP || DBG_IOCTL; 28 | 29 | NTSTATUS 30 | SpbDoWriteDataSynchronously( 31 | IN SPB_CONTEXT* SpbContext, 32 | IN PVOID Data, 33 | IN ULONG Length 34 | ) 35 | /*++ 36 | 37 | Routine Description: 38 | 39 | This helper routine abstracts creating and sending an I/O 40 | request (I2C Write) to the Spb I/O target. 41 | 42 | Arguments: 43 | 44 | SpbContext - Pointer to the current device context 45 | Address - The I2C register address to write to 46 | Data - A buffer to receive the data at at the above address 47 | Length - The amount of data to be read from the above address 48 | 49 | Return Value: 50 | 51 | NTSTATUS Status indicating success or failure 52 | 53 | --*/ 54 | { 55 | PUCHAR buffer; 56 | ULONG length; 57 | WDFMEMORY memory; 58 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 59 | NTSTATUS status; 60 | 61 | length = Length; 62 | memory = NULL; 63 | 64 | if (length > DEFAULT_SPB_BUFFER_SIZE) 65 | { 66 | status = WdfMemoryCreate( 67 | WDF_NO_OBJECT_ATTRIBUTES, 68 | NonPagedPool, 69 | GMAX_POOL_TAG, 70 | length, 71 | &memory, 72 | (PVOID*)&buffer); 73 | 74 | if (!NT_SUCCESS(status)) 75 | { 76 | GmaxPrint( 77 | DEBUG_LEVEL_ERROR, 78 | DBG_IOCTL, 79 | "Error allocating memory for Spb write - %!STATUS!", 80 | status); 81 | goto exit; 82 | } 83 | 84 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( 85 | &memoryDescriptor, 86 | memory, 87 | NULL); 88 | } 89 | else 90 | { 91 | buffer = (PUCHAR)WdfMemoryGetBuffer(SpbContext->WriteMemory, NULL); 92 | 93 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 94 | &memoryDescriptor, 95 | (PVOID)buffer, 96 | length); 97 | } 98 | 99 | RtlCopyMemory(buffer, Data, length); 100 | 101 | status = WdfIoTargetSendWriteSynchronously( 102 | SpbContext->SpbIoTarget, 103 | NULL, 104 | &memoryDescriptor, 105 | NULL, 106 | NULL, 107 | NULL); 108 | 109 | if (!NT_SUCCESS(status)) 110 | { 111 | GmaxPrint( 112 | DEBUG_LEVEL_ERROR, 113 | DBG_IOCTL, 114 | "Error writing to Spb - %!STATUS!", 115 | status); 116 | goto exit; 117 | } 118 | 119 | exit: 120 | 121 | if (NULL != memory) 122 | { 123 | WdfObjectDelete(memory); 124 | } 125 | 126 | return status; 127 | } 128 | 129 | NTSTATUS 130 | SpbLockController( 131 | IN SPB_CONTEXT* SpbContext 132 | ) 133 | /*++ 134 | 135 | Routine Description: 136 | 137 | This routine sends a lock command to the SPB controller. 138 | 139 | Arguments: 140 | 141 | pDevice - a pointer to the device context 142 | FxRequest - the framework request object 143 | 144 | Return Value: 145 | 146 | None 147 | 148 | --*/ 149 | { 150 | NTSTATUS status; 151 | 152 | // 153 | // Initialize the SPB request for lock and send. 154 | // 155 | 156 | status = WdfIoTargetSendIoctlSynchronously( 157 | SpbContext->SpbIoTarget, 158 | NULL, 159 | IOCTL_SPB_LOCK_CONTROLLER, 160 | NULL, 161 | NULL, 162 | NULL, 163 | NULL); 164 | 165 | if (!NT_SUCCESS(status)) 166 | { 167 | GmaxPrint( 168 | DEBUG_LEVEL_ERROR, 169 | DBG_IOCTL, 170 | "Failed to send SPB request for " 171 | "IOCTL_SPB_LOCK_CONTROLLER - %!STATUS!", 172 | status); 173 | } 174 | return status; 175 | } 176 | 177 | NTSTATUS 178 | SpbUnlockController( 179 | IN SPB_CONTEXT* SpbContext 180 | ) 181 | /*++ 182 | 183 | Routine Description: 184 | 185 | This routine sends a lock command to the SPB controller. 186 | 187 | Arguments: 188 | 189 | pDevice - a pointer to the device context 190 | FxRequest - the framework request object 191 | 192 | Return Value: 193 | 194 | None 195 | 196 | --*/ 197 | { 198 | NTSTATUS status; 199 | 200 | // 201 | // Initialize the SPB request for lock and send. 202 | // 203 | 204 | status = WdfIoTargetSendIoctlSynchronously( 205 | SpbContext->SpbIoTarget, 206 | NULL, 207 | IOCTL_SPB_UNLOCK_CONTROLLER, 208 | NULL, 209 | NULL, 210 | NULL, 211 | NULL); 212 | 213 | if (!NT_SUCCESS(status)) 214 | { 215 | GmaxPrint( 216 | DEBUG_LEVEL_ERROR, 217 | DBG_IOCTL, 218 | "Failed to send SPB request for " 219 | "IOCTL_SPB_UNLOCK_CONTROLLER - %!STATUS!", 220 | status); 221 | } 222 | return status; 223 | } 224 | 225 | NTSTATUS 226 | SpbWriteDataSynchronously( 227 | IN SPB_CONTEXT* SpbContext, 228 | IN PVOID Data, 229 | IN ULONG Length 230 | ) 231 | /*++ 232 | 233 | Routine Description: 234 | 235 | This routine abstracts creating and sending an I/O 236 | request (I2C Write) to the Spb I/O target and utilizes 237 | a helper routine to do work inside of locked code. 238 | 239 | Arguments: 240 | 241 | SpbContext - Pointer to the current device context 242 | Address - The I2C register address to write to 243 | Data - A buffer to receive the data at at the above address 244 | Length - The amount of data to be read from the above address 245 | 246 | Return Value: 247 | 248 | NTSTATUS Status indicating success or failure 249 | 250 | --*/ 251 | { 252 | NTSTATUS status; 253 | 254 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 255 | SpbLockController(SpbContext); 256 | 257 | status = SpbDoWriteDataSynchronously( 258 | SpbContext, 259 | Data, 260 | Length); 261 | 262 | SpbUnlockController(SpbContext); 263 | WdfWaitLockRelease(SpbContext->SpbLock); 264 | 265 | return status; 266 | } 267 | 268 | NTSTATUS 269 | SpbXferDataSynchronously( 270 | _In_ SPB_CONTEXT* SpbContext, 271 | _In_ PVOID SendData, 272 | _In_ ULONG SendLength, 273 | _In_reads_bytes_(Length) PVOID Data, 274 | _In_ ULONG Length 275 | ) 276 | /*++ 277 | Routine Description: 278 | This helper routine abstracts creating and sending an I/O 279 | request (I2C Read) to the Spb I/O target. 280 | Arguments: 281 | SpbContext - Pointer to the current device context 282 | Address - The I2C register address to read from 283 | Data - A buffer to receive the data at at the above address 284 | Length - The amount of data to be read from the above address 285 | Return Value: 286 | NTSTATUS Status indicating success or failure 287 | --*/ 288 | { 289 | PUCHAR buffer; 290 | WDFMEMORY memory; 291 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 292 | NTSTATUS status; 293 | ULONG_PTR bytesRead; 294 | 295 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 296 | SpbLockController(SpbContext); 297 | 298 | memory = NULL; 299 | status = STATUS_INVALID_PARAMETER; 300 | bytesRead = 0; 301 | 302 | // 303 | // Xfer transactions start by writing an address pointer 304 | // 305 | status = SpbDoWriteDataSynchronously( 306 | SpbContext, 307 | SendData, 308 | SendLength); 309 | 310 | if (!NT_SUCCESS(status)) 311 | { 312 | GmaxPrint( 313 | DEBUG_LEVEL_ERROR, 314 | DBG_IOCTL, 315 | "Error setting address pointer for Spb read - %!STATUS!", 316 | status); 317 | goto exit; 318 | } 319 | 320 | if (Length > DEFAULT_SPB_BUFFER_SIZE) 321 | { 322 | status = WdfMemoryCreate( 323 | WDF_NO_OBJECT_ATTRIBUTES, 324 | NonPagedPool, 325 | GMAX_POOL_TAG, 326 | Length, 327 | &memory, 328 | (PVOID*)&buffer); 329 | 330 | if (!NT_SUCCESS(status)) 331 | { 332 | GmaxPrint( 333 | DEBUG_LEVEL_ERROR, 334 | DBG_IOCTL, 335 | "Error allocating memory for Spb read - %!STATUS!", 336 | status); 337 | goto exit; 338 | } 339 | 340 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( 341 | &memoryDescriptor, 342 | memory, 343 | NULL); 344 | } 345 | else 346 | { 347 | buffer = (PUCHAR)WdfMemoryGetBuffer(SpbContext->ReadMemory, NULL); 348 | 349 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 350 | &memoryDescriptor, 351 | (PVOID)buffer, 352 | Length); 353 | } 354 | 355 | 356 | status = WdfIoTargetSendReadSynchronously( 357 | SpbContext->SpbIoTarget, 358 | NULL, 359 | &memoryDescriptor, 360 | NULL, 361 | NULL, 362 | &bytesRead); 363 | 364 | if (!NT_SUCCESS(status) || 365 | bytesRead != Length) 366 | { 367 | GmaxPrint( 368 | DEBUG_LEVEL_ERROR, 369 | DBG_IOCTL, 370 | "Error reading from Spb - %!STATUS!", 371 | status); 372 | goto exit; 373 | } 374 | 375 | // 376 | // Copy back to the caller's buffer 377 | // 378 | RtlCopyMemory(Data, buffer, Length); 379 | 380 | exit: 381 | if (NULL != memory) 382 | { 383 | WdfObjectDelete(memory); 384 | } 385 | 386 | SpbUnlockController(SpbContext); 387 | WdfWaitLockRelease(SpbContext->SpbLock); 388 | 389 | return status; 390 | } 391 | 392 | VOID 393 | SpbTargetDeinitialize( 394 | IN WDFDEVICE FxDevice, 395 | IN SPB_CONTEXT* SpbContext 396 | ) 397 | /*++ 398 | 399 | Routine Description: 400 | 401 | This helper routine is used to free any members added to the SPB_CONTEXT, 402 | note the SPB I/O target is parented to the device and will be 403 | closed and free'd when the device is removed. 404 | 405 | Arguments: 406 | 407 | FxDevice - Handle to the framework device object 408 | SpbContext - Pointer to the current device context 409 | 410 | Return Value: 411 | 412 | NTSTATUS Status indicating success or failure 413 | 414 | --*/ 415 | { 416 | UNREFERENCED_PARAMETER(FxDevice); 417 | UNREFERENCED_PARAMETER(SpbContext); 418 | 419 | // 420 | // Free any SPB_CONTEXT allocations here 421 | // 422 | if (SpbContext->SpbLock != NULL) 423 | { 424 | WdfObjectDelete(SpbContext->SpbLock); 425 | } 426 | 427 | if (SpbContext->ReadMemory != NULL) 428 | { 429 | WdfObjectDelete(SpbContext->ReadMemory); 430 | } 431 | 432 | if (SpbContext->WriteMemory != NULL) 433 | { 434 | WdfObjectDelete(SpbContext->WriteMemory); 435 | } 436 | } 437 | 438 | NTSTATUS 439 | SpbTargetInitialize( 440 | IN WDFDEVICE FxDevice, 441 | IN SPB_CONTEXT* SpbContext 442 | ) 443 | /*++ 444 | 445 | Routine Description: 446 | 447 | This helper routine opens the Spb I/O target and 448 | initializes a request object used for the lifetime 449 | of communication between this driver and Spb. 450 | 451 | Arguments: 452 | 453 | FxDevice - Handle to the framework device object 454 | SpbContext - Pointer to the current device context 455 | 456 | Return Value: 457 | 458 | NTSTATUS Status indicating success or failure 459 | 460 | --*/ 461 | { 462 | WDF_OBJECT_ATTRIBUTES objectAttributes; 463 | WDF_IO_TARGET_OPEN_PARAMS openParams; 464 | UNICODE_STRING spbDeviceName; 465 | WCHAR spbDeviceNameBuffer[RESOURCE_HUB_PATH_SIZE]; 466 | NTSTATUS status; 467 | 468 | WDF_OBJECT_ATTRIBUTES_INIT(&objectAttributes); 469 | objectAttributes.ParentObject = FxDevice; 470 | 471 | status = WdfIoTargetCreate( 472 | FxDevice, 473 | &objectAttributes, 474 | &SpbContext->SpbIoTarget); 475 | 476 | if (!NT_SUCCESS(status)) 477 | { 478 | GmaxPrint( 479 | DEBUG_LEVEL_ERROR, 480 | DBG_IOCTL, 481 | "Error creating IoTarget object - %!STATUS!", 482 | status); 483 | 484 | WdfObjectDelete(SpbContext->SpbIoTarget); 485 | goto exit; 486 | } 487 | 488 | RtlInitEmptyUnicodeString( 489 | &spbDeviceName, 490 | spbDeviceNameBuffer, 491 | sizeof(spbDeviceNameBuffer)); 492 | 493 | status = RESOURCE_HUB_CREATE_PATH_FROM_ID( 494 | &spbDeviceName, 495 | SpbContext->I2cResHubId.LowPart, 496 | SpbContext->I2cResHubId.HighPart); 497 | 498 | if (!NT_SUCCESS(status)) 499 | { 500 | GmaxPrint( 501 | DEBUG_LEVEL_ERROR, 502 | DBG_IOCTL, 503 | "Error creating Spb resource hub path string - %!STATUS!", 504 | status); 505 | goto exit; 506 | } 507 | 508 | WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME( 509 | &openParams, 510 | &spbDeviceName, 511 | (GENERIC_READ | GENERIC_WRITE)); 512 | 513 | openParams.ShareAccess = 0; 514 | openParams.CreateDisposition = FILE_OPEN; 515 | openParams.FileAttributes = FILE_ATTRIBUTE_NORMAL; 516 | 517 | status = WdfIoTargetOpen(SpbContext->SpbIoTarget, &openParams); 518 | 519 | if (!NT_SUCCESS(status)) 520 | { 521 | GmaxPrint( 522 | DEBUG_LEVEL_ERROR, 523 | DBG_IOCTL, 524 | "Error opening Spb target for communication - %!STATUS!", 525 | status); 526 | goto exit; 527 | } 528 | 529 | // 530 | // Allocate some fixed-size buffers from NonPagedPool for typical 531 | // Spb transaction sizes to avoid pool fragmentation in most cases 532 | // 533 | status = WdfMemoryCreate( 534 | WDF_NO_OBJECT_ATTRIBUTES, 535 | NonPagedPool, 536 | GMAX_POOL_TAG, 537 | DEFAULT_SPB_BUFFER_SIZE, 538 | &SpbContext->WriteMemory, 539 | NULL); 540 | 541 | if (!NT_SUCCESS(status)) 542 | { 543 | GmaxPrint( 544 | DEBUG_LEVEL_ERROR, 545 | DBG_IOCTL, 546 | "Error allocating default memory for Spb write - %!STATUS!", 547 | status); 548 | goto exit; 549 | } 550 | 551 | status = WdfMemoryCreate( 552 | WDF_NO_OBJECT_ATTRIBUTES, 553 | NonPagedPool, 554 | GMAX_POOL_TAG, 555 | DEFAULT_SPB_BUFFER_SIZE, 556 | &SpbContext->ReadMemory, 557 | NULL); 558 | 559 | if (!NT_SUCCESS(status)) 560 | { 561 | GmaxPrint( 562 | DEBUG_LEVEL_ERROR, 563 | DBG_IOCTL, 564 | "Error allocating default memory for Spb read - %!STATUS!", 565 | status); 566 | goto exit; 567 | } 568 | 569 | // 570 | // Allocate a waitlock to guard access to the default buffers 571 | // 572 | status = WdfWaitLockCreate( 573 | WDF_NO_OBJECT_ATTRIBUTES, 574 | &SpbContext->SpbLock); 575 | 576 | if (!NT_SUCCESS(status)) 577 | { 578 | GmaxPrint( 579 | DEBUG_LEVEL_ERROR, 580 | DBG_IOCTL, 581 | "Error creating Spb Waitlock - %!STATUS!", 582 | status); 583 | goto exit; 584 | } 585 | 586 | exit: 587 | 588 | if (!NT_SUCCESS(status)) 589 | { 590 | SpbTargetDeinitialize(FxDevice, SpbContext); 591 | } 592 | 593 | return status; 594 | } -------------------------------------------------------------------------------- /opengmaxcodec/opengmaxcodec.c: -------------------------------------------------------------------------------- 1 | #include "opengmaxcodec.h" 2 | #include "max98927.h" 3 | #include "max98373.h" 4 | 5 | #define bool int 6 | 7 | static ULONG GmaxDebugLevel = 100; 8 | static ULONG GmaxDebugCatagories = DBG_INIT || DBG_PNP || DBG_IOCTL; 9 | 10 | NTSTATUS 11 | DriverEntry( 12 | __in PDRIVER_OBJECT DriverObject, 13 | __in PUNICODE_STRING RegistryPath 14 | ) 15 | { 16 | NTSTATUS status = STATUS_SUCCESS; 17 | WDF_DRIVER_CONFIG config; 18 | WDF_OBJECT_ATTRIBUTES attributes; 19 | 20 | GmaxPrint(DEBUG_LEVEL_INFO, DBG_INIT, 21 | "Driver Entry\n"); 22 | 23 | WDF_DRIVER_CONFIG_INIT(&config, GmaxEvtDeviceAdd); 24 | 25 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 26 | 27 | // 28 | // Create a framework driver object to represent our driver. 29 | // 30 | 31 | status = WdfDriverCreate(DriverObject, 32 | RegistryPath, 33 | &attributes, 34 | &config, 35 | WDF_NO_HANDLE 36 | ); 37 | 38 | if (!NT_SUCCESS(status)) 39 | { 40 | GmaxPrint(DEBUG_LEVEL_ERROR, DBG_INIT, 41 | "WdfDriverCreate failed with status 0x%x\n", status); 42 | } 43 | 44 | return status; 45 | } 46 | 47 | typedef enum platform { 48 | PlatformNone, 49 | PlatformRyzen, 50 | PlatformAmberLake, 51 | PlatformTigerLake 52 | } Platform; 53 | 54 | static Platform GetPlatform() { 55 | int cpuinfo[4]; 56 | __cpuidex(cpuinfo, 0, 0); 57 | 58 | int temp = cpuinfo[2]; 59 | cpuinfo[2] = cpuinfo[3]; 60 | cpuinfo[3] = temp; 61 | 62 | char vendorName[13]; 63 | RtlZeroMemory(vendorName, 13); 64 | memcpy(vendorName, &cpuinfo[1], 12); 65 | 66 | __cpuidex(cpuinfo, 1, 0); 67 | 68 | UINT16 family = (cpuinfo[0] >> 8) & 0xF; 69 | UINT8 model = (cpuinfo[0] >> 4) & 0xF; 70 | UINT8 stepping = cpuinfo[0] & 0xF; 71 | if (family == 0xF || family == 0x6) { 72 | model += (((cpuinfo[0] >> 16) & 0xF) << 4); 73 | } 74 | if (family == 0xF) { 75 | family += (cpuinfo[0] >> 20) & 0xFF; 76 | } 77 | 78 | if (strcmp(vendorName, "AuthenticAMD") == 0) { 79 | return PlatformRyzen; //family 23 for Picasso / Dali 80 | } 81 | else if (strcmp(vendorName, "GenuineIntel") == 0) { 82 | if (model == 142) 83 | return PlatformAmberLake; 84 | else 85 | return PlatformTigerLake; //should be 140 86 | } 87 | return PlatformNone; 88 | } 89 | 90 | NTSTATUS gmax_reg_read( 91 | _In_ PGMAX_CONTEXT pDevice, 92 | uint16_t reg, 93 | uint8_t* data 94 | ) { 95 | uint8_t buf[2]; 96 | buf[0] = (reg >> 8) & 0xff; 97 | buf[1] = reg & 0xff; 98 | 99 | uint8_t raw_data = 0; 100 | NTSTATUS status = SpbXferDataSynchronously(&pDevice->I2CContext, buf, sizeof(buf), &raw_data, sizeof(uint8_t)); 101 | *data = raw_data; 102 | return status; 103 | } 104 | 105 | NTSTATUS gmax_reg_write( 106 | _In_ PGMAX_CONTEXT pDevice, 107 | uint16_t reg, 108 | uint8_t data 109 | ) { 110 | uint8_t buf[3]; 111 | buf[0] = (reg >> 8) & 0xff; 112 | buf[1] = reg & 0xff; 113 | buf[2] = data; 114 | return SpbWriteDataSynchronously(&pDevice->I2CContext, buf, sizeof(buf)); 115 | } 116 | 117 | NTSTATUS gmax_reg_update( 118 | _In_ PGMAX_CONTEXT pDevice, 119 | uint16_t reg, 120 | uint8_t mask, 121 | uint8_t val 122 | ) { 123 | uint8_t tmp = 0, orig = 0; 124 | 125 | NTSTATUS status = gmax_reg_read(pDevice, reg, &orig); 126 | if (!NT_SUCCESS(status)) { 127 | return status; 128 | } 129 | 130 | tmp = orig & ~mask; 131 | tmp |= val & mask; 132 | 133 | if (tmp != orig) { 134 | status = gmax_reg_write(pDevice, reg, tmp); 135 | } 136 | return status; 137 | } 138 | 139 | struct initreg { 140 | UINT16 reg; 141 | UINT8 val; 142 | }; 143 | 144 | struct initreg max98927_initregs[] = { 145 | {MAX98927_R0014_MEAS_ADC_THERM_WARN_THRESH, 0x75}, 146 | {MAX98927_R0015_MEAS_ADC_THERM_SHDN_THRESH, 0x8C}, 147 | {MAX98927_R0016_MEAS_ADC_THERM_HYSTERESIS, 0x8}, 148 | {MAX98927_R0018_PCM_RX_EN_A, 0x3}, 149 | {MAX98927_R0020_PCM_MODE_CFG, 0x58}, 150 | {MAX98927_R0022_PCM_CLK_SETUP, 0x26}, 151 | {MAX98927_R0023_PCM_SR_SETUP1, 0x8}, 152 | {MAX98927_R0037_AMP_DSP_CFG, 0x3}, 153 | {MAX98927_R0039_DRE_CTRL, 0x1}, 154 | {MAX98927_R003E_MEAS_EN, 0x3}, 155 | {MAX98927_R003F_MEAS_DSP_CFG, 0xF7}, 156 | {MAX98927_R0040_BOOST_CTRL0, 0x1C}, 157 | {MAX98927_R0042_BOOST_CTRL1, 0x28}, //was 0x14 158 | {MAX98927_R0043_MEAS_ADC_CFG, 0x4}, 159 | {MAX98927_R0044_MEAS_ADC_BASE_MSB, 0x0}, 160 | {MAX98927_R0045_MEAS_ADC_BASE_LSB, 0x24}, 161 | {MAX98927_R007F_BROWNOUT_LVL4_AMP1_CTRL1, 0x6}, 162 | {MAX98927_R0082_ENV_TRACK_VOUT_HEADROOM, 0x0A}, 163 | {MAX98927_R0086_ENV_TRACK_CTRL, 0x1} 164 | }; 165 | 166 | struct initreg max98373_initregs[] = { 167 | {MAX98373_R2024_PCM_DATA_FMT_CFG, 0x58}, 168 | {MAX98373_R2026_PCM_CLOCK_RATIO, 0x6}, 169 | {MAX98373_R202B_PCM_RX_EN, 0x1}, 170 | {MAX98373_R202C_PCM_TX_EN, 0x1}, 171 | {MAX98373_R203F_AMP_DSP_CFG, 0x3}, 172 | {MAX98373_R2046_IV_SENSE_ADC_DSP_CFG, 0xF7}, 173 | {MAX98373_R2047_IV_SENSE_ADC_EN, 0x3}, 174 | {MAX98373_R20B1_BDE_L4_CFG_1, 0x6}, 175 | {MAX98373_R20D4_DHT_EN, 0x1} 176 | }; 177 | 178 | NTSTATUS toggleI2CAmp( 179 | _In_ PGMAX_CONTEXT pDevice, 180 | BOOLEAN enable 181 | ) { 182 | return gmax_reg_write(pDevice, pDevice->chipModel == 98927 ? MAX98927_R003A_AMP_EN : MAX98373_R2043_AMP_EN, enable & 0x1); 183 | } 184 | 185 | NTSTATUS enableOutput( 186 | _In_ PGMAX_CONTEXT pDevice, 187 | BOOLEAN enable 188 | ) { 189 | NTSTATUS status; 190 | status = gmax_reg_write(pDevice, pDevice->chipModel == 98927 ? MAX98927_R00FF_GLOBAL_SHDN : MAX98373_R20FF_GLOBAL_SHDN, 1); 191 | if (!NT_SUCCESS(status)) { 192 | return status; 193 | } 194 | 195 | LARGE_INTEGER Interval; 196 | Interval.QuadPart = -20; 197 | KeDelayExecutionThread(KernelMode, FALSE, &Interval); 198 | return toggleI2CAmp(pDevice, enable); 199 | } 200 | 201 | NTSTATUS 202 | GetDeviceHID( 203 | _In_ WDFDEVICE FxDevice 204 | ) 205 | { 206 | NTSTATUS status = STATUS_ACPI_NOT_INITIALIZED; 207 | ACPI_EVAL_INPUT_BUFFER_EX inputBuffer; 208 | RtlZeroMemory(&inputBuffer, sizeof(inputBuffer)); 209 | 210 | inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE_EX; 211 | status = RtlStringCchPrintfA( 212 | inputBuffer.MethodName, 213 | sizeof(inputBuffer.MethodName), 214 | "_HID" 215 | ); 216 | if (!NT_SUCCESS(status)) { 217 | return status; 218 | } 219 | 220 | WDFMEMORY outputMemory; 221 | PACPI_EVAL_OUTPUT_BUFFER outputBuffer; 222 | size_t outputArgumentBufferSize = 32; 223 | size_t outputBufferSize = FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) + outputArgumentBufferSize; 224 | 225 | WDF_OBJECT_ATTRIBUTES attributes; 226 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 227 | attributes.ParentObject = FxDevice; 228 | 229 | status = WdfMemoryCreate(&attributes, 230 | NonPagedPoolNx, 231 | 0, 232 | outputBufferSize, 233 | &outputMemory, 234 | (PVOID*)&outputBuffer); 235 | if (!NT_SUCCESS(status)) { 236 | return status; 237 | } 238 | 239 | RtlZeroMemory(outputBuffer, outputBufferSize); 240 | 241 | WDF_MEMORY_DESCRIPTOR inputMemDesc; 242 | WDF_MEMORY_DESCRIPTOR outputMemDesc; 243 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&inputMemDesc, &inputBuffer, (ULONG)sizeof(inputBuffer)); 244 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&outputMemDesc, outputMemory, NULL); 245 | 246 | status = WdfIoTargetSendInternalIoctlSynchronously( 247 | WdfDeviceGetIoTarget(FxDevice), 248 | NULL, 249 | IOCTL_ACPI_EVAL_METHOD_EX, 250 | &inputMemDesc, 251 | &outputMemDesc, 252 | NULL, 253 | NULL 254 | ); 255 | if (!NT_SUCCESS(status)) { 256 | goto Exit; 257 | } 258 | 259 | if (outputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) { 260 | goto Exit; 261 | } 262 | 263 | if (outputBuffer->Count < 1) { 264 | goto Exit; 265 | } 266 | 267 | PGMAX_CONTEXT pDevice = GetDeviceContext(FxDevice); 268 | if (strncmp(outputBuffer->Argument[0].Data, "MX98373", outputBuffer->Argument[0].DataLength) == 0) { 269 | pDevice->chipModel = 98373; 270 | } 271 | else if (strncmp(outputBuffer->Argument[0].Data, "MX98927", outputBuffer->Argument[0].DataLength) == 0) { 272 | pDevice->chipModel = 98927; 273 | } 274 | else { 275 | status = STATUS_ACPI_INVALID_ARGUMENT; 276 | } 277 | 278 | Exit: 279 | if (outputMemory != WDF_NO_HANDLE) { 280 | WdfObjectDelete(outputMemory); 281 | } 282 | return status; 283 | } 284 | 285 | NTSTATUS 286 | GetDeviceUID( 287 | _In_ WDFDEVICE FxDevice, 288 | _In_ PINT32 PUID 289 | ) 290 | { 291 | NTSTATUS status = STATUS_ACPI_NOT_INITIALIZED; 292 | ACPI_EVAL_INPUT_BUFFER_EX inputBuffer; 293 | RtlZeroMemory(&inputBuffer, sizeof(inputBuffer)); 294 | 295 | inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE_EX; 296 | status = RtlStringCchPrintfA( 297 | inputBuffer.MethodName, 298 | sizeof(inputBuffer.MethodName), 299 | "_UID" 300 | ); 301 | if (!NT_SUCCESS(status)) { 302 | return status; 303 | } 304 | 305 | WDFMEMORY outputMemory; 306 | PACPI_EVAL_OUTPUT_BUFFER outputBuffer; 307 | size_t outputArgumentBufferSize = 32; 308 | size_t outputBufferSize = FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) + outputArgumentBufferSize; 309 | 310 | WDF_OBJECT_ATTRIBUTES attributes; 311 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 312 | attributes.ParentObject = FxDevice; 313 | 314 | status = WdfMemoryCreate(&attributes, 315 | NonPagedPoolNx, 316 | 0, 317 | outputBufferSize, 318 | &outputMemory, 319 | (PVOID*)&outputBuffer); 320 | if (!NT_SUCCESS(status)) { 321 | return status; 322 | } 323 | 324 | RtlZeroMemory(outputBuffer, outputBufferSize); 325 | 326 | WDF_MEMORY_DESCRIPTOR inputMemDesc; 327 | WDF_MEMORY_DESCRIPTOR outputMemDesc; 328 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&inputMemDesc, &inputBuffer, (ULONG)sizeof(inputBuffer)); 329 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&outputMemDesc, outputMemory, NULL); 330 | 331 | status = WdfIoTargetSendInternalIoctlSynchronously( 332 | WdfDeviceGetIoTarget(FxDevice), 333 | NULL, 334 | IOCTL_ACPI_EVAL_METHOD_EX, 335 | &inputMemDesc, 336 | &outputMemDesc, 337 | NULL, 338 | NULL 339 | ); 340 | if (!NT_SUCCESS(status)) { 341 | goto Exit; 342 | } 343 | 344 | if (outputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) { 345 | goto Exit; 346 | } 347 | 348 | if (outputBuffer->Count < 1) { 349 | goto Exit; 350 | } 351 | 352 | uint32_t uid; 353 | if (outputBuffer->Argument[0].DataLength >= 4) { 354 | uid = *(uint32_t*)outputBuffer->Argument->Data; 355 | } 356 | else if (outputBuffer->Argument[0].DataLength >= 2) { 357 | uid = *(uint16_t*)outputBuffer->Argument->Data; 358 | } 359 | else { 360 | uid = *(uint8_t*)outputBuffer->Argument->Data; 361 | } 362 | if (PUID) { 363 | *PUID = uid; 364 | } 365 | else { 366 | status = STATUS_ACPI_INVALID_ARGUMENT; 367 | } 368 | Exit: 369 | if (outputMemory != WDF_NO_HANDLE) { 370 | WdfObjectDelete(outputMemory); 371 | } 372 | return status; 373 | } 374 | int CsAudioArg2 = 1; 375 | 376 | static NTSTATUS GetIntegerProperty( 377 | _In_ WDFDEVICE FxDevice, 378 | char *propertyStr, 379 | UINT16 *property 380 | ) { 381 | PGMAX_CONTEXT pDevice = GetDeviceContext(FxDevice); 382 | WDFMEMORY outputMemory = WDF_NO_HANDLE; 383 | 384 | NTSTATUS status = STATUS_ACPI_NOT_INITIALIZED; 385 | 386 | size_t inputBufferLen = sizeof(ACPI_GET_DEVICE_SPECIFIC_DATA) + strlen(propertyStr) + 1; 387 | ACPI_GET_DEVICE_SPECIFIC_DATA* inputBuffer = ExAllocatePoolWithTag(NonPagedPool, inputBufferLen, GMAX_POOL_TAG); 388 | if (!inputBuffer) { 389 | goto Exit; 390 | } 391 | RtlZeroMemory(inputBuffer, inputBufferLen); 392 | 393 | inputBuffer->Signature = IOCTL_ACPI_GET_DEVICE_SPECIFIC_DATA_SIGNATURE; 394 | 395 | unsigned char uuidend[] = { 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01 }; 396 | 397 | inputBuffer->Section.Data1 = 0xdaffd814; 398 | inputBuffer->Section.Data2 = 0x6eba; 399 | inputBuffer->Section.Data3 = 0x4d8c; 400 | memcpy(inputBuffer->Section.Data4, uuidend, sizeof(uuidend)); //Avoid Windows defender false positive 401 | 402 | strcpy(inputBuffer->PropertyName, propertyStr); 403 | inputBuffer->PropertyNameLength = strlen(propertyStr) + 1; 404 | 405 | PACPI_EVAL_OUTPUT_BUFFER outputBuffer; 406 | size_t outputArgumentBufferSize = 8; 407 | size_t outputBufferSize = FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) + sizeof(ACPI_METHOD_ARGUMENT_V1) + outputArgumentBufferSize; 408 | 409 | WDF_OBJECT_ATTRIBUTES attributes; 410 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 411 | attributes.ParentObject = FxDevice; 412 | status = WdfMemoryCreate(&attributes, 413 | NonPagedPoolNx, 414 | 0, 415 | outputBufferSize, 416 | &outputMemory, 417 | &outputBuffer); 418 | if (!NT_SUCCESS(status)) { 419 | goto Exit; 420 | } 421 | 422 | WDF_MEMORY_DESCRIPTOR inputMemDesc; 423 | WDF_MEMORY_DESCRIPTOR outputMemDesc; 424 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&inputMemDesc, inputBuffer, (ULONG)inputBufferLen); 425 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&outputMemDesc, outputMemory, NULL); 426 | 427 | status = WdfIoTargetSendInternalIoctlSynchronously( 428 | WdfDeviceGetIoTarget(FxDevice), 429 | NULL, 430 | IOCTL_ACPI_GET_DEVICE_SPECIFIC_DATA, 431 | &inputMemDesc, 432 | &outputMemDesc, 433 | NULL, 434 | NULL 435 | ); 436 | if (!NT_SUCCESS(status)) { 437 | GmaxPrint( 438 | DEBUG_LEVEL_ERROR, 439 | DBG_IOCTL, 440 | "Error getting device data - 0x%x\n", 441 | status); 442 | goto Exit; 443 | } 444 | 445 | if (outputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE_V1 && 446 | outputBuffer->Count < 1 && 447 | outputBuffer->Argument->Type != ACPI_METHOD_ARGUMENT_INTEGER && 448 | outputBuffer->Argument->DataLength < 1) { 449 | status = STATUS_ACPI_INVALID_ARGUMENT; 450 | goto Exit; 451 | } 452 | 453 | if (property) { 454 | *property = outputBuffer->Argument->Data[0] & 0xF; 455 | } 456 | 457 | Exit: 458 | if (inputBuffer) { 459 | ExFreePoolWithTag(inputBuffer, GMAX_POOL_TAG); 460 | } 461 | if (outputMemory != WDF_NO_HANDLE) { 462 | WdfObjectDelete(outputMemory); 463 | } 464 | return status; 465 | } 466 | 467 | NTSTATUS 468 | StartCodec( 469 | PGMAX_CONTEXT pDevice 470 | ) { 471 | NTSTATUS status = STATUS_SUCCESS; 472 | if (!pDevice->SetUID) { 473 | status = STATUS_INVALID_DEVICE_STATE; 474 | return status; 475 | } 476 | 477 | UINT8 data = 0; 478 | gmax_reg_read(pDevice, pDevice->chipModel == 98927 ? MAX98927_R01FF_REV_ID : MAX98373_R21FF_REV_ID, &data); 479 | 480 | BOOLEAN useDefaults = FALSE; 481 | 482 | INT32 rightSpeaker = 1; 483 | if (GetPlatform() == PlatformAmberLake) 484 | rightSpeaker = 0; 485 | 486 | if (pDevice->chipModel == 98927) { //max98927 487 | for (int i = 0; i < sizeof(max98927_initregs) / sizeof(struct initreg); i++) { 488 | struct initreg regval = max98927_initregs[i]; 489 | status = gmax_reg_write(pDevice, regval.reg, regval.val); 490 | if (!NT_SUCCESS(status)) { 491 | return status; 492 | } 493 | } 494 | 495 | UINT16 ampVolume = 60; 496 | UINT16 speakerGain = 1; 497 | 498 | status = gmax_reg_write(pDevice, MAX98927_R0036_AMP_VOL_CTRL, ampVolume & 0x7F); 499 | if (!NT_SUCCESS(status)) { 500 | return status; 501 | } 502 | 503 | status = gmax_reg_write(pDevice, MAX98927_R003C_SPK_GAIN, speakerGain & 0x7); 504 | if (!NT_SUCCESS(status)) { 505 | return status; 506 | } 507 | 508 | UINT16 interleave_mode = 0; 509 | UINT16 vmon_slot_no = 0; 510 | UINT16 imon_slot_no = 0; 511 | 512 | if (!NT_SUCCESS(GetIntegerProperty(pDevice->FxDevice, "interleave_mode", &interleave_mode))) { 513 | DbgPrint("Warning: unable to get vmon-slot-no. Using defaults.\n"); 514 | useDefaults = TRUE; 515 | } 516 | interleave_mode = interleave_mode & 1; 517 | 518 | if (!NT_SUCCESS(GetIntegerProperty(pDevice->FxDevice, "vmon-slot-no", &vmon_slot_no))) { 519 | DbgPrint("Warning: unable to get vmon-slot-no. Using defaults.\n"); 520 | useDefaults = TRUE; 521 | } 522 | if (!NT_SUCCESS(GetIntegerProperty(pDevice->FxDevice, "imon-slot-no", &vmon_slot_no))) { 523 | DbgPrint("Warning: unable to get vmon-slot-no. Using defaults.\n"); 524 | useDefaults = TRUE; 525 | } 526 | 527 | if (useDefaults) { 528 | interleave_mode = 0; 529 | if (pDevice->UID == 0) { 530 | vmon_slot_no = 4; 531 | imon_slot_no = 5; 532 | } 533 | else { 534 | vmon_slot_no = 6; 535 | imon_slot_no = 7; 536 | } 537 | } 538 | 539 | UINT16 temp = (1 << vmon_slot_no) | (1 << imon_slot_no); 540 | status = gmax_reg_write(pDevice, MAX98927_R001A_PCM_TX_EN_A, temp); 541 | if (!NT_SUCCESS(status)) { 542 | return status; 543 | } 544 | 545 | status = gmax_reg_write(pDevice, MAX98927_R001B_PCM_TX_EN_B, (temp >> 8) | 0xff00); 546 | if (!NT_SUCCESS(status)) { 547 | return status; 548 | } 549 | 550 | temp = ~temp; 551 | status = gmax_reg_write(pDevice, MAX98927_R001C_PCM_TX_HIZ_CTRL_A, temp); 552 | if (!NT_SUCCESS(status)) { 553 | return status; 554 | } 555 | 556 | status = gmax_reg_write(pDevice, MAX98927_R001D_PCM_TX_HIZ_CTRL_B, (temp >> 8) | 0xff00); 557 | if (!NT_SUCCESS(status)) { 558 | return status; 559 | } 560 | 561 | status = gmax_reg_write(pDevice, MAX98927_R001E_PCM_TX_CH_SRC_A, (imon_slot_no << MAX98927_PCM_TX_CH_SRC_A_I_SHIFT | 562 | vmon_slot_no) & 0xFF); 563 | if (!NT_SUCCESS(status)) { 564 | return status; 565 | } 566 | 567 | status = gmax_reg_write(pDevice, MAX98927_R001F_PCM_TX_CH_SRC_B, interleave_mode != 0 ? MAX98927_PCM_TX_CH_INTERLEAVE_MASK : 0); 568 | if (!NT_SUCCESS(status)) { 569 | return status; 570 | } 571 | 572 | status = gmax_reg_write(pDevice, MAX98927_R0024_PCM_SR_SETUP2, interleave_mode != 0 ? 0x85 : 0x88); 573 | if (!NT_SUCCESS(status)) { 574 | return status; 575 | } 576 | 577 | status = gmax_reg_write(pDevice, MAX98927_R0025_PCM_TO_SPK_MONOMIX_A, pDevice->UID == rightSpeaker ? 0x40 : 0); 578 | if (!NT_SUCCESS(status)) { 579 | return status; 580 | } 581 | 582 | status = gmax_reg_write(pDevice, MAX98927_R0026_PCM_TO_SPK_MONOMIX_B, 1); 583 | if (!NT_SUCCESS(status)) { 584 | return status; 585 | } 586 | } 587 | else { //98373 588 | for (int i = 0; i < sizeof(max98373_initregs) / sizeof(struct initreg); i++) { 589 | struct initreg regval = max98373_initregs[i]; 590 | status = gmax_reg_write(pDevice, regval.reg, regval.val); 591 | if (!NT_SUCCESS(status)) { 592 | return status; 593 | } 594 | } 595 | 596 | UINT16 digitalVolume = 12; 597 | UINT16 digitalGain = 0; 598 | UINT16 digitalMaxGain = 0; 599 | 600 | status = gmax_reg_write(pDevice, MAX98373_R203D_AMP_DIG_VOL_CTRL, digitalVolume & 0x7F); 601 | if (!NT_SUCCESS(status)) { 602 | return status; 603 | } 604 | 605 | status = gmax_reg_write(pDevice, MAX98373_R203E_AMP_PATH_GAIN, ((digitalGain & 0xF) << 4) | (digitalMaxGain & 0xF)); 606 | if (!NT_SUCCESS(status)) { 607 | return status; 608 | } 609 | 610 | UINT16 interleave_mode = 0; 611 | UINT16 vmon_slot_no = 0; 612 | UINT16 imon_slot_no = 0; 613 | 614 | UINT16 spkfb_slot_no = 0; 615 | if (!NT_SUCCESS(GetIntegerProperty(pDevice->FxDevice, "maxim,spkfb-slot-no", &spkfb_slot_no))) { 616 | spkfb_slot_no = 2; 617 | } 618 | 619 | if (!NT_SUCCESS(GetIntegerProperty(pDevice->FxDevice, "maxim,vmon-slot-no", &vmon_slot_no))) { 620 | DbgPrint("Warning: unable to get maxim,vmon-slot-no. Using defaults.\n"); 621 | useDefaults = TRUE; 622 | } 623 | if (!NT_SUCCESS(GetIntegerProperty(pDevice->FxDevice, "maxim,imon-slot-no", &imon_slot_no))) { 624 | DbgPrint("Warning: unable to get maxim,vmon-slot-no. Using defaults.\n"); 625 | useDefaults = TRUE; 626 | } 627 | 628 | if (useDefaults) { 629 | if (pDevice->UID == 0) { 630 | vmon_slot_no = 4; 631 | imon_slot_no = 5; 632 | } 633 | else { 634 | vmon_slot_no = 6; 635 | imon_slot_no = 7; 636 | } 637 | } else { 638 | if (NT_SUCCESS(GetIntegerProperty(pDevice->FxDevice, "maxim,interleave_mode", &interleave_mode))) { 639 | interleave_mode = 1; 640 | } 641 | else { 642 | interleave_mode = 0; 643 | } 644 | } 645 | 646 | UINT16 fmt = MAX98373_PCM_MODE_CFG_CHANSZ_16; 647 | UINT16 clkRatio = 0x6; 648 | 649 | if (vmon_slot_no < 4) { 650 | if ((vmon_slot_no % 2) == 0) { 651 | fmt = MAX98373_PCM_MODE_CFG_CHANSZ_32; 652 | clkRatio = 0x8; 653 | } 654 | else { 655 | fmt = MAX98373_PCM_MODE_CFG_CHANSZ_24; 656 | clkRatio = 0x7; 657 | } 658 | } 659 | 660 | status = gmax_reg_write(pDevice, MAX98373_R2026_PCM_CLOCK_RATIO, clkRatio); 661 | if (!NT_SUCCESS(status)) { 662 | return status; 663 | } 664 | 665 | UINT16 temp = ~((1 << vmon_slot_no) | (1 << imon_slot_no)); 666 | status = gmax_reg_write(pDevice, MAX98373_R2020_PCM_TX_HIZ_EN_1, temp); 667 | if (!NT_SUCCESS(status)) { 668 | return status; 669 | } 670 | 671 | status = gmax_reg_write(pDevice, MAX98373_R2021_PCM_TX_HIZ_EN_2, (temp >> 8) | 0xff00); 672 | if (!NT_SUCCESS(status)) { 673 | return status; 674 | } 675 | 676 | status = gmax_reg_write(pDevice, MAX98373_R2022_PCM_TX_SRC_1, ((imon_slot_no & 0xF) << 4) | (vmon_slot_no & 0xF)); 677 | if (!NT_SUCCESS(status)) { 678 | return status; 679 | } 680 | 681 | status = gmax_reg_write(pDevice, MAX98373_R2023_PCM_TX_SRC_2, spkfb_slot_no); 682 | if (!NT_SUCCESS(status)) { 683 | return status; 684 | } 685 | 686 | status = gmax_reg_write(pDevice, MAX98373_R2024_PCM_DATA_FMT_CFG, MAX98373_PCM_FORMAT_TDM_MODE0 << MAX98373_PCM_MODE_CFG_FORMAT_SHIFT); 687 | if (!NT_SUCCESS(status)) { 688 | return status; 689 | } 690 | 691 | status = gmax_reg_update(pDevice, MAX98373_R2024_PCM_DATA_FMT_CFG, MAX98373_PCM_MODE_CFG_CHANSZ_MASK, fmt); 692 | if (!NT_SUCCESS(status)) { 693 | return status; 694 | } 695 | 696 | status = gmax_reg_update(pDevice, MAX98373_R2024_PCM_DATA_FMT_CFG, MAX98373_PCM_TX_CH_INTERLEAVE_MASK, interleave_mode ? MAX98373_PCM_TX_CH_INTERLEAVE_MASK : 0); 697 | if (!NT_SUCCESS(status)) { 698 | return status; 699 | } 700 | 701 | status = gmax_reg_write(pDevice, MAX98373_R2028_PCM_SR_SETUP_2, interleave_mode != 0 ? 0x85 : 0x88); 702 | if (!NT_SUCCESS(status)) { 703 | return status; 704 | } 705 | 706 | status = gmax_reg_write(pDevice, MAX98373_R2029_PCM_TO_SPK_MONO_MIX_1, pDevice->UID == rightSpeaker ? 0x40 : 0); 707 | if (!NT_SUCCESS(status)) { 708 | return status; 709 | } 710 | 711 | status = gmax_reg_write(pDevice, MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, 1); 712 | if (!NT_SUCCESS(status)) { 713 | return status; 714 | } 715 | } 716 | 717 | status = enableOutput(pDevice, TRUE); 718 | 719 | /*uint16_t regs[] = {0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F,0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x002B,0x002C,0x002E,0x002F,0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F,0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x0051,0x0052,0x0053,0x0054,0x0055,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F,0x0060,0x0061,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F,0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,0x00FF,0x0100,0x01FF}; 720 | for (int i = 0; i < sizeof(regs) / sizeof(uint16_t); i++) { 721 | UINT16 reg = regs[i]; 722 | UINT8 data = 0; 723 | gmax_reg_read(pDevice, reg, &data); 724 | 725 | DbgPrint("Reg 0x%04x:\n\t0x%02x", reg, data); 726 | }*/ 727 | 728 | pDevice->DevicePoweredOn = TRUE; 729 | return status; 730 | } 731 | 732 | NTSTATUS 733 | StopCodec( 734 | PGMAX_CONTEXT pDevice 735 | ) { 736 | NTSTATUS status; 737 | 738 | status = gmax_reg_write(pDevice, pDevice->chipModel == 98927 ? MAX98927_R0100_SOFT_RESET : MAX98373_R2000_SW_RESET, 1); 739 | 740 | pDevice->DevicePoweredOn = FALSE; 741 | return status; 742 | } 743 | 744 | VOID 745 | CSAudioRegisterEndpoint( 746 | PGMAX_CONTEXT pDevice 747 | ) { 748 | return; 749 | 750 | CsAudioArg arg; 751 | RtlZeroMemory(&arg, sizeof(CsAudioArg)); 752 | arg.argSz = sizeof(CsAudioArg); 753 | arg.endpointType = CSAudioEndpointTypeSpeaker; 754 | arg.endpointRequest = CSAudioEndpointRegister; 755 | ExNotifyCallback(pDevice->CSAudioAPICallback, &arg, &CsAudioArg2); 756 | } 757 | 758 | VOID 759 | CsAudioCallbackFunction( 760 | IN PGMAX_CONTEXT pDevice, 761 | CsAudioArg* arg, 762 | PVOID Argument2 763 | ) { 764 | if (!pDevice) { 765 | return; 766 | } 767 | 768 | if (Argument2 == &CsAudioArg2) { 769 | return; 770 | } 771 | 772 | CsAudioArg localArg; 773 | RtlZeroMemory(&localArg, sizeof(CsAudioArg)); 774 | RtlCopyMemory(&localArg, arg, min(arg->argSz, sizeof(CsAudioArg))); 775 | 776 | if (localArg.endpointType == CSAudioEndpointTypeDSP && localArg.endpointRequest == CSAudioEndpointRegister) { 777 | CSAudioRegisterEndpoint(pDevice); 778 | } 779 | else if (localArg.endpointType != CSAudioEndpointTypeSpeaker) { 780 | return; 781 | } 782 | 783 | if (localArg.endpointRequest == CSAudioEndpointStop) { 784 | if (pDevice->CSAudioRequestsOn) { 785 | WdfDeviceResumeIdle(pDevice->FxDevice); 786 | pDevice->CSAudioRequestsOn = FALSE; 787 | } 788 | } 789 | if (localArg.endpointRequest == CSAudioEndpointStart) { 790 | if (!pDevice->CSAudioRequestsOn) { 791 | WdfDeviceStopIdle(pDevice->FxDevice, TRUE); 792 | pDevice->CSAudioRequestsOn = TRUE; 793 | } 794 | } 795 | } 796 | 797 | NTSTATUS 798 | OnPrepareHardware( 799 | _In_ WDFDEVICE FxDevice, 800 | _In_ WDFCMRESLIST FxResourcesRaw, 801 | _In_ WDFCMRESLIST FxResourcesTranslated 802 | ) 803 | /*++ 804 | 805 | Routine Description: 806 | 807 | This routine caches the SPB resource connection ID. 808 | 809 | Arguments: 810 | 811 | FxDevice - a handle to the framework device object 812 | FxResourcesRaw - list of translated hardware resources that 813 | the PnP manager has assigned to the device 814 | FxResourcesTranslated - list of raw hardware resources that 815 | the PnP manager has assigned to the device 816 | 817 | Return Value: 818 | 819 | Status 820 | 821 | --*/ 822 | { 823 | PGMAX_CONTEXT pDevice = GetDeviceContext(FxDevice); 824 | BOOLEAN fSpbResourceFound = FALSE; 825 | NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES; 826 | 827 | UNREFERENCED_PARAMETER(FxResourcesRaw); 828 | 829 | // 830 | // Parse the peripheral's resources. 831 | // 832 | 833 | ULONG resourceCount = WdfCmResourceListGetCount(FxResourcesTranslated); 834 | 835 | for (ULONG i = 0; i < resourceCount; i++) 836 | { 837 | PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor; 838 | UCHAR Class; 839 | UCHAR Type; 840 | 841 | pDescriptor = WdfCmResourceListGetDescriptor( 842 | FxResourcesTranslated, i); 843 | 844 | switch (pDescriptor->Type) 845 | { 846 | case CmResourceTypeConnection: 847 | // 848 | // Look for I2C or SPI resource and save connection ID. 849 | // 850 | Class = pDescriptor->u.Connection.Class; 851 | Type = pDescriptor->u.Connection.Type; 852 | if (Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL && 853 | Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C) 854 | { 855 | if (fSpbResourceFound == FALSE) 856 | { 857 | status = STATUS_SUCCESS; 858 | pDevice->I2CContext.I2cResHubId.LowPart = pDescriptor->u.Connection.IdLowPart; 859 | pDevice->I2CContext.I2cResHubId.HighPart = pDescriptor->u.Connection.IdHighPart; 860 | fSpbResourceFound = TRUE; 861 | } 862 | else 863 | { 864 | } 865 | } 866 | break; 867 | default: 868 | // 869 | // Ignoring all other resource types. 870 | // 871 | break; 872 | } 873 | } 874 | 875 | // 876 | // An SPB resource is required. 877 | // 878 | 879 | if (fSpbResourceFound == FALSE) 880 | { 881 | status = STATUS_NOT_FOUND; 882 | } 883 | 884 | status = SpbTargetInitialize(FxDevice, &pDevice->I2CContext); 885 | 886 | if (!NT_SUCCESS(status)) 887 | { 888 | return status; 889 | } 890 | 891 | status = GetDeviceUID(FxDevice, &pDevice->UID); 892 | if (!NT_SUCCESS(status)) { 893 | return status; 894 | } 895 | 896 | status = GetDeviceHID(FxDevice); 897 | if (!NT_SUCCESS(status)) { 898 | return status; 899 | } 900 | 901 | pDevice->SetUID = TRUE; 902 | 903 | return status; 904 | } 905 | 906 | NTSTATUS 907 | OnReleaseHardware( 908 | _In_ WDFDEVICE FxDevice, 909 | _In_ WDFCMRESLIST FxResourcesTranslated 910 | ) 911 | /*++ 912 | 913 | Routine Description: 914 | 915 | Arguments: 916 | 917 | FxDevice - a handle to the framework device object 918 | FxResourcesTranslated - list of raw hardware resources that 919 | the PnP manager has assigned to the device 920 | 921 | Return Value: 922 | 923 | Status 924 | 925 | --*/ 926 | { 927 | PGMAX_CONTEXT pDevice = GetDeviceContext(FxDevice); 928 | NTSTATUS status = STATUS_SUCCESS; 929 | 930 | UNREFERENCED_PARAMETER(FxResourcesTranslated); 931 | 932 | SpbTargetDeinitialize(FxDevice, &pDevice->I2CContext); 933 | 934 | if (pDevice->CSAudioAPICallbackObj) { 935 | ExUnregisterCallback(pDevice->CSAudioAPICallbackObj); 936 | pDevice->CSAudioAPICallbackObj = NULL; 937 | } 938 | 939 | if (pDevice->CSAudioAPICallback) { 940 | ObfDereferenceObject(pDevice->CSAudioAPICallback); 941 | pDevice->CSAudioAPICallback = NULL; 942 | } 943 | 944 | return status; 945 | } 946 | 947 | NTSTATUS 948 | OnSelfManagedIoInit( 949 | _In_ 950 | WDFDEVICE FxDevice 951 | ) { 952 | PGMAX_CONTEXT pDevice = GetDeviceContext(FxDevice); 953 | NTSTATUS status = STATUS_SUCCESS; 954 | 955 | if (!pDevice->SetUID) { 956 | status = STATUS_INVALID_DEVICE_STATE; 957 | return status; 958 | } 959 | 960 | // CS Audio Callback 961 | 962 | UNICODE_STRING CSAudioCallbackAPI; 963 | RtlInitUnicodeString(&CSAudioCallbackAPI, L"\\CallBack\\CsAudioCallbackAPI"); 964 | 965 | 966 | OBJECT_ATTRIBUTES attributes; 967 | InitializeObjectAttributes(&attributes, 968 | &CSAudioCallbackAPI, 969 | OBJ_KERNEL_HANDLE | OBJ_OPENIF | OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 970 | NULL, 971 | NULL 972 | ); 973 | status = ExCreateCallback(&pDevice->CSAudioAPICallback, &attributes, TRUE, TRUE); 974 | if (!NT_SUCCESS(status)) { 975 | return status; 976 | } 977 | 978 | pDevice->CSAudioAPICallbackObj = ExRegisterCallback(pDevice->CSAudioAPICallback, 979 | CsAudioCallbackFunction, 980 | pDevice 981 | ); 982 | if (!pDevice->CSAudioAPICallbackObj) { 983 | 984 | return STATUS_NO_CALLBACK_ACTIVE; 985 | } 986 | 987 | CSAudioRegisterEndpoint(pDevice); 988 | 989 | return status; 990 | } 991 | 992 | NTSTATUS 993 | OnD0Entry( 994 | _In_ WDFDEVICE FxDevice, 995 | _In_ WDF_POWER_DEVICE_STATE FxPreviousState 996 | ) 997 | /*++ 998 | 999 | Routine Description: 1000 | 1001 | This routine allocates objects needed by the driver. 1002 | 1003 | Arguments: 1004 | 1005 | FxDevice - a handle to the framework device object 1006 | FxPreviousState - previous power state 1007 | 1008 | Return Value: 1009 | 1010 | Status 1011 | 1012 | --*/ 1013 | { 1014 | UNREFERENCED_PARAMETER(FxPreviousState); 1015 | 1016 | PGMAX_CONTEXT pDevice = GetDeviceContext(FxDevice); 1017 | NTSTATUS status = StartCodec(pDevice); 1018 | return status; 1019 | } 1020 | 1021 | NTSTATUS 1022 | OnD0Exit( 1023 | _In_ WDFDEVICE FxDevice, 1024 | _In_ WDF_POWER_DEVICE_STATE FxPreviousState 1025 | ) 1026 | /*++ 1027 | 1028 | Routine Description: 1029 | 1030 | This routine destroys objects needed by the driver. 1031 | 1032 | Arguments: 1033 | 1034 | FxDevice - a handle to the framework device object 1035 | FxPreviousState - previous power state 1036 | 1037 | Return Value: 1038 | 1039 | Status 1040 | 1041 | --*/ 1042 | { 1043 | UNREFERENCED_PARAMETER(FxPreviousState); 1044 | 1045 | PGMAX_CONTEXT pDevice = GetDeviceContext(FxDevice); 1046 | NTSTATUS status = STATUS_SUCCESS; 1047 | 1048 | status = StopCodec(pDevice); 1049 | 1050 | return STATUS_SUCCESS; 1051 | } 1052 | 1053 | NTSTATUS 1054 | GmaxEvtDeviceAdd( 1055 | IN WDFDRIVER Driver, 1056 | IN PWDFDEVICE_INIT DeviceInit 1057 | ) 1058 | { 1059 | NTSTATUS status = STATUS_SUCCESS; 1060 | WDF_IO_QUEUE_CONFIG queueConfig; 1061 | WDF_OBJECT_ATTRIBUTES attributes; 1062 | WDFDEVICE device; 1063 | WDFQUEUE queue; 1064 | PGMAX_CONTEXT devContext; 1065 | 1066 | UNREFERENCED_PARAMETER(Driver); 1067 | 1068 | PAGED_CODE(); 1069 | 1070 | GmaxPrint(DEBUG_LEVEL_INFO, DBG_PNP, 1071 | "GmaxEvtDeviceAdd called\n"); 1072 | 1073 | { 1074 | WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks; 1075 | WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks); 1076 | 1077 | pnpCallbacks.EvtDevicePrepareHardware = OnPrepareHardware; 1078 | pnpCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware; 1079 | pnpCallbacks.EvtDeviceSelfManagedIoInit = OnSelfManagedIoInit; 1080 | pnpCallbacks.EvtDeviceD0Entry = OnD0Entry; 1081 | pnpCallbacks.EvtDeviceD0Exit = OnD0Exit; 1082 | 1083 | WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks); 1084 | } 1085 | 1086 | // 1087 | // Setup the device context 1088 | // 1089 | 1090 | WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, GMAX_CONTEXT); 1091 | 1092 | // 1093 | // Create a framework device object.This call will in turn create 1094 | // a WDM device object, attach to the lower stack, and set the 1095 | // appropriate flags and attributes. 1096 | // 1097 | 1098 | status = WdfDeviceCreate(&DeviceInit, &attributes, &device); 1099 | 1100 | if (!NT_SUCCESS(status)) 1101 | { 1102 | GmaxPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 1103 | "WdfDeviceCreate failed with status code 0x%x\n", status); 1104 | 1105 | return status; 1106 | } 1107 | 1108 | { 1109 | WDF_DEVICE_STATE deviceState; 1110 | WDF_DEVICE_STATE_INIT(&deviceState); 1111 | 1112 | deviceState.NotDisableable = WdfFalse; 1113 | WdfDeviceSetDeviceState(device, &deviceState); 1114 | } 1115 | 1116 | WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); 1117 | 1118 | queueConfig.EvtIoInternalDeviceControl = GmaxEvtInternalDeviceControl; 1119 | 1120 | status = WdfIoQueueCreate(device, 1121 | &queueConfig, 1122 | WDF_NO_OBJECT_ATTRIBUTES, 1123 | &queue 1124 | ); 1125 | 1126 | if (!NT_SUCCESS(status)) 1127 | { 1128 | GmaxPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 1129 | "WdfIoQueueCreate failed 0x%x\n", status); 1130 | 1131 | return status; 1132 | } 1133 | 1134 | // 1135 | // Create manual I/O queue to take care of hid report read requests 1136 | // 1137 | 1138 | devContext = GetDeviceContext(device); 1139 | 1140 | devContext->FxDevice = device; 1141 | 1142 | WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); 1143 | 1144 | queueConfig.PowerManaged = WdfTrue; 1145 | 1146 | status = WdfIoQueueCreate(device, 1147 | &queueConfig, 1148 | WDF_NO_OBJECT_ATTRIBUTES, 1149 | &devContext->ReportQueue 1150 | ); 1151 | 1152 | if (!NT_SUCCESS(status)) 1153 | { 1154 | GmaxPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 1155 | "WdfIoQueueCreate failed 0x%x\n", status); 1156 | 1157 | return status; 1158 | } 1159 | 1160 | WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS IdleSettings; 1161 | 1162 | WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&IdleSettings, IdleCannotWakeFromS0); 1163 | IdleSettings.IdleTimeoutType = SystemManagedIdleTimeoutWithHint; 1164 | IdleSettings.IdleTimeout = 1000; 1165 | IdleSettings.Enabled = WdfTrue; 1166 | 1167 | WdfDeviceAssignS0IdleSettings(devContext->FxDevice, &IdleSettings); 1168 | 1169 | return status; 1170 | } 1171 | 1172 | VOID 1173 | GmaxEvtInternalDeviceControl( 1174 | IN WDFQUEUE Queue, 1175 | IN WDFREQUEST Request, 1176 | IN size_t OutputBufferLength, 1177 | IN size_t InputBufferLength, 1178 | IN ULONG IoControlCode 1179 | ) 1180 | { 1181 | NTSTATUS status = STATUS_SUCCESS; 1182 | WDFDEVICE device; 1183 | PGMAX_CONTEXT devContext; 1184 | 1185 | UNREFERENCED_PARAMETER(OutputBufferLength); 1186 | UNREFERENCED_PARAMETER(InputBufferLength); 1187 | 1188 | device = WdfIoQueueGetDevice(Queue); 1189 | devContext = GetDeviceContext(device); 1190 | 1191 | switch (IoControlCode) 1192 | { 1193 | default: 1194 | status = STATUS_NOT_SUPPORTED; 1195 | break; 1196 | } 1197 | 1198 | WdfRequestComplete(Request, status); 1199 | 1200 | return; 1201 | } --------------------------------------------------------------------------------