├── max98390 ├── stdint.h ├── dsm_param_Google_Nightfury.bin ├── firmware.h ├── resource.h ├── max98390.rc ├── spb.h ├── trace.h ├── max98390.inf ├── firmware.c ├── max98390.h ├── max98390.vcxproj ├── spb.c ├── registers.h └── max98390.c ├── README.md ├── max98390.sln ├── LICENSE.txt ├── .gitignore └── max98390 Package └── max98390 Package.vcxproj /max98390/stdint.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define BIT(nr) (1UL << (nr)) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # max98390 2 | MAX98390 Amplifier Driver 3 | 4 | Tested on Samsung Galaxy Chromebook 2. Requires CoolStar SOF Audio -------------------------------------------------------------------------------- /max98390/dsm_param_Google_Nightfury.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chrultrabook/max98390/master/max98390/dsm_param_Google_Nightfury.bin -------------------------------------------------------------------------------- /max98390/firmware.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | struct firmware { 5 | UINT8* data; 6 | size_t size; 7 | }; 8 | 9 | NTSTATUS request_firmware(struct firmware** img, PCWSTR path); 10 | void free_firmware(struct firmware* fw); -------------------------------------------------------------------------------- /max98390/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by max98390.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 | -------------------------------------------------------------------------------- /max98390/max98390.rc: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | max98390.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 98390 I2S Amplifier" 18 | #define VER_INTERNALNAME_STR "max98390.sys" 19 | #define VER_ORIGINALFILENAME_STR "max98390.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,0,0 25 | #define VER_PRODUCTVERSION_STR "1.0.0.0" 26 | #define VER_PRODUCTVERSION 1,0,0,0 27 | #define LVER_PRODUCTVERSION_STR L"1.0.0.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 98390 I2S Amplifier" 40 | 41 | #include "common.ver" -------------------------------------------------------------------------------- /max98390/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 | ); -------------------------------------------------------------------------------- /max98390/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 | -------------------------------------------------------------------------------- /max98390/max98390.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 Maxim 98390 Amplifier 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 = max98390.cat 21 | PnpLockdown=1 22 | 23 | [DestinationDirs] 24 | DefaultDestDir = 12 25 | 26 | ; ================= Class section ===================== 27 | 28 | [SourceDisksNames] 29 | 1 = %DiskId1%,,,"" 30 | 31 | [SourceDisksFiles] 32 | max98390.sys = 1 33 | dsm_param_Google_Nightfury.bin = 1 34 | 35 | ;***************************************** 36 | ; max98390 Install Section 37 | ;***************************************** 38 | 39 | [Manufacturer] 40 | %StdMfg%=Standard,NTAMD64 41 | 42 | ; Decorated model section take precedence over undecorated 43 | ; ones on XP and later. 44 | [Standard.NTAMD64] 45 | %max98390.DeviceDesc%=Max98390_Device, ACPI\MX98390 46 | 47 | [Max98390_Device.NT] 48 | CopyFiles=Drivers_Dir 49 | 50 | [Drivers_Dir] 51 | max98390.sys 52 | dsm_param_Google_Nightfury.bin 53 | 54 | ;-------------- Service installation 55 | [Max98390_Device.NT.Services] 56 | AddService = max98390,%SPSVCINST_ASSOCSERVICE%, Max98390_Service_Inst 57 | 58 | ; -------------- max98390 driver install sections 59 | [Max98390_Service_Inst] 60 | DisplayName = %max98390.SVCDESC% 61 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 62 | StartType = 3 ; SERVICE_DEMAND_START 63 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 64 | ServiceBinary = %12%\max98390.sys 65 | LoadOrderGroup = Base 66 | 67 | [Strings] 68 | SPSVCINST_ASSOCSERVICE= 0x00000002 69 | StdMfg = "CoolStar" 70 | DiskId1 = "Maxim 98390 Installation Disk #1" 71 | max98390.DeviceDesc = "Maxim 98390 I2S Amplifier" 72 | max98390.SVCDESC = "Maxim 98390 Service" 73 | -------------------------------------------------------------------------------- /max98390/firmware.c: -------------------------------------------------------------------------------- 1 | #include "max98390.h" 2 | #include "firmware.h" 3 | 4 | NTSTATUS request_firmware(struct firmware** img, PCWSTR path) { 5 | *img = NULL; 6 | 7 | struct firmware* fw = (struct firmware*)ExAllocatePoolZero(NonPagedPool, sizeof(struct firmware), MAX98390_POOL_TAG); 8 | if (!fw) { 9 | return STATUS_NO_MEMORY; 10 | } 11 | RtlZeroMemory(fw, sizeof(struct firmware)); 12 | 13 | NTSTATUS status; 14 | 15 | UNICODE_STRING uniName; 16 | OBJECT_ATTRIBUTES objAttr; 17 | 18 | RtlInitUnicodeString(&uniName, path); 19 | InitializeObjectAttributes(&objAttr, &uniName, 20 | OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 21 | NULL, NULL); 22 | 23 | // Do not try to perform any file operations at higher IRQL levels. 24 | // Instead, you may use a work item or a system worker thread to perform file operations. 25 | 26 | if (KeGetCurrentIrql() != PASSIVE_LEVEL) { 27 | status = STATUS_INVALID_DEVICE_STATE; 28 | free_firmware(fw); 29 | return status; 30 | } 31 | 32 | HANDLE handle; 33 | IO_STATUS_BLOCK ioStatusBlock; 34 | 35 | status = ZwCreateFile(&handle, 36 | GENERIC_READ, 37 | &objAttr, &ioStatusBlock, NULL, 38 | FILE_ATTRIBUTE_NORMAL, 39 | 0, 40 | FILE_OPEN, 41 | FILE_SYNCHRONOUS_IO_NONALERT, 42 | NULL, 0); 43 | if (!NT_SUCCESS(status)) { 44 | free_firmware(fw); 45 | return status; 46 | } 47 | 48 | FILE_STANDARD_INFORMATION fileInfo; 49 | status = ZwQueryInformationFile( 50 | handle, 51 | &ioStatusBlock, 52 | &fileInfo, 53 | sizeof(fileInfo), 54 | FileStandardInformation 55 | ); 56 | if (!NT_SUCCESS(status)) { 57 | ZwClose(handle); 58 | free_firmware(fw); 59 | return status; 60 | } 61 | 62 | fw->size = fileInfo.EndOfFile.QuadPart; 63 | fw->data = (UINT8*)ExAllocatePoolWithTag(NonPagedPool, fw->size, MAX98390_POOL_TAG); 64 | if (!fw->data) { 65 | status = STATUS_NO_MEMORY; 66 | ZwClose(handle); 67 | free_firmware(fw); 68 | return status; 69 | } 70 | 71 | LARGE_INTEGER byteOffset; 72 | byteOffset.LowPart = byteOffset.HighPart = 0; 73 | status = ZwReadFile(handle, NULL, NULL, NULL, &ioStatusBlock, fw->data, (ULONG)fw->size, &byteOffset, NULL); 74 | if (!NT_SUCCESS(status)) { 75 | ZwClose(handle); 76 | free_firmware(fw); 77 | return status; 78 | } 79 | *img = fw; 80 | 81 | ZwClose(handle); 82 | return status; 83 | } 84 | 85 | void free_firmware(struct firmware* fw) { 86 | if (fw->data) { 87 | ExFreePoolWithTag(fw->data, MAX98390_POOL_TAG); 88 | } 89 | ExFreePoolWithTag((PVOID)fw, MAX98390_POOL_TAG); 90 | } -------------------------------------------------------------------------------- /max98390.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}") = "max98390", "max98390\max98390.vcxproj", "{36580C07-EDC3-4C2B-B45F-6AB017E01A5D}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "max98390 Package", "max98390 Package\max98390 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 2023 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. -------------------------------------------------------------------------------- /max98390/max98390.h: -------------------------------------------------------------------------------- 1 | #if !defined(_MAX98390_H_) 2 | #define _MAX98390_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 | // 25 | // String definitions 26 | // 27 | 28 | #define DRIVERNAME "max98390.sys: " 29 | 30 | #define MAX98390_POOL_TAG (ULONG) '3XAM' 31 | 32 | #define true 1 33 | #define false 0 34 | 35 | typedef enum { 36 | CSAudioEndpointTypeDSP, 37 | CSAudioEndpointTypeSpeaker, 38 | CSAudioEndpointTypeHeadphone, 39 | CSAudioEndpointTypeMicArray, 40 | CSAudioEndpointTypeMicJack 41 | } CSAudioEndpointType; 42 | 43 | typedef enum { 44 | CSAudioEndpointRegister, 45 | CSAudioEndpointStart, 46 | CSAudioEndpointStop, 47 | CSAudioEndpointOverrideFormat 48 | } CSAudioEndpointRequest; 49 | 50 | typedef struct CSAUDIOFORMATOVERRIDE { 51 | UINT16 channels; 52 | UINT16 frequency; 53 | UINT16 bitsPerSample; 54 | UINT16 validBitsPerSample; 55 | BOOL force32BitOutputContainer; 56 | } CsAudioFormatOverride; 57 | 58 | typedef struct CSAUDIOARG { 59 | UINT32 argSz; 60 | CSAudioEndpointType endpointType; 61 | CSAudioEndpointRequest endpointRequest; 62 | union { 63 | CsAudioFormatOverride formatOverride; 64 | }; 65 | } CsAudioArg, * PCsAudioArg; 66 | 67 | typedef struct _MAX98390_CONTEXT 68 | { 69 | 70 | WDFDEVICE FxDevice; 71 | 72 | WDFQUEUE ReportQueue; 73 | 74 | SPB_CONTEXT I2CContext; 75 | 76 | BOOLEAN SetUID; 77 | INT32 UID; 78 | 79 | BOOLEAN DevicePoweredOn; 80 | 81 | PCALLBACK_OBJECT CSAudioAPICallback; 82 | PVOID CSAudioAPICallbackObj; 83 | 84 | BOOL CSAudioManaged; 85 | 86 | } MAX98390_CONTEXT, *PMAX98390_CONTEXT; 87 | 88 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(MAX98390_CONTEXT, GetDeviceContext) 89 | 90 | // 91 | // Function definitions 92 | // 93 | 94 | DRIVER_INITIALIZE DriverEntry; 95 | 96 | EVT_WDF_DRIVER_UNLOAD Max98390DriverUnload; 97 | 98 | EVT_WDF_DRIVER_DEVICE_ADD Max98390EvtDeviceAdd; 99 | 100 | EVT_WDFDEVICE_WDM_IRP_PREPROCESS Max98390EvtWdmPreprocessMnQueryId; 101 | 102 | EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL Max98390EvtInternalDeviceControl; 103 | 104 | // 105 | // Helper macros 106 | // 107 | 108 | #define DEBUG_LEVEL_ERROR 1 109 | #define DEBUG_LEVEL_INFO 2 110 | #define DEBUG_LEVEL_VERBOSE 3 111 | 112 | #define DBG_INIT 1 113 | #define DBG_PNP 2 114 | #define DBG_IOCTL 4 115 | 116 | #if 0 117 | #define Max98390Print(dbglevel, dbgcatagory, fmt, ...) { \ 118 | if (Max98390DebugLevel >= dbglevel && \ 119 | (Max98390DebugCatagories && dbgcatagory)) \ 120 | { \ 121 | DbgPrint(DRIVERNAME); \ 122 | DbgPrint(fmt, __VA_ARGS__); \ 123 | } \ 124 | } 125 | #else 126 | #define Max98390Print(dbglevel, fmt, ...) { \ 127 | } 128 | #endif 129 | 130 | #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 | -------------------------------------------------------------------------------- /max98390 Package/max98390 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 | max98390_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 | cmd /k mkdir "$(Inf2CatSource)" && copy "$(SolutionDir)max98390\dsm_param_Google_Nightfury.bin" "$(Inf2CatSource)" 130 | 131 | 132 | 133 | 134 | SHA256 135 | 136 | 137 | cmd /k mkdir "$(Inf2CatSource)" && copy "$(SolutionDir)max98390\dsm_param_Google_Nightfury.bin" "$(Inf2CatSource)" 138 | 139 | 140 | 141 | 142 | SHA256 143 | 144 | 145 | cmd /k mkdir "$(Inf2CatSource)" && copy "$(SolutionDir)max98390\dsm_param_Google_Nightfury.bin" "$(Inf2CatSource)" 146 | 147 | 148 | 149 | 150 | SHA256 151 | 152 | 153 | cmd /k mkdir "$(Inf2CatSource)" && copy "$(SolutionDir)max98390\dsm_param_Google_Nightfury.bin" "$(Inf2CatSource)" 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | {36580c07-edc3-4c2b-b45f-6ab017e01a5d} 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /max98390/max98390.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 | max98390 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 | true 70 | 71 | 72 | DbgengKernelDebugger 73 | true 74 | 75 | 76 | DbgengKernelDebugger 77 | true 78 | 79 | 80 | DbgengKernelDebugger 81 | true 82 | 83 | 84 | 85 | true 86 | trace.h 87 | true 88 | false 89 | 90 | 91 | 1.0.0 92 | 93 | 94 | cmd /k mkdir "$(Inf2CatSource)" && copy "$(SolutionDir)max98390\dsm_param_Google_Nightfury.bin" "$(Inf2CatSource)" 95 | 96 | 97 | 98 | 99 | true 100 | trace.h 101 | true 102 | false 103 | 104 | 105 | 1.0.0 106 | 107 | 108 | cmd /k mkdir "$(Inf2CatSource)" && copy "$(SolutionDir)max98390\dsm_param_Google_Nightfury.bin" "$(Inf2CatSource)" 109 | 110 | 111 | 112 | 113 | true 114 | trace.h 115 | true 116 | false 117 | 118 | 119 | 1.0.0 120 | 121 | 122 | cmd /k mkdir "$(Inf2CatSource)" && copy "$(SolutionDir)max98390\dsm_param_Google_Nightfury.bin" "$(Inf2CatSource)" 123 | 124 | 125 | 126 | 127 | true 128 | trace.h 129 | true 130 | false 131 | 132 | 133 | 1.0.0 134 | 135 | 136 | cmd /k mkdir "$(Inf2CatSource)" && copy "$(SolutionDir)max98390\dsm_param_Google_Nightfury.bin" "$(Inf2CatSource)" 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 | 162 | true 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /max98390/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 "max98390.h" 22 | #include "spb.h" 23 | #include 24 | #include 25 | 26 | static ULONG Max98390DebugLevel = 100; 27 | static ULONG Max98390DebugCatagories = 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 | MAX98390_POOL_TAG, 70 | length, 71 | &memory, 72 | (PVOID*)&buffer); 73 | 74 | if (!NT_SUCCESS(status)) 75 | { 76 | Max98390Print( 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 | Max98390Print( 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 | Max98390Print( 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 | Max98390Print( 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 | Max98390Print( 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 | MAX98390_POOL_TAG, 326 | Length, 327 | &memory, 328 | (PVOID*)&buffer); 329 | 330 | if (!NT_SUCCESS(status)) 331 | { 332 | Max98390Print( 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 | Max98390Print( 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 | Max98390Print( 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 | Max98390Print( 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 | Max98390Print( 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 | MAX98390_POOL_TAG, 537 | DEFAULT_SPB_BUFFER_SIZE, 538 | &SpbContext->WriteMemory, 539 | NULL); 540 | 541 | if (!NT_SUCCESS(status)) 542 | { 543 | Max98390Print( 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 | MAX98390_POOL_TAG, 555 | DEFAULT_SPB_BUFFER_SIZE, 556 | &SpbContext->ReadMemory, 557 | NULL); 558 | 559 | if (!NT_SUCCESS(status)) 560 | { 561 | Max98390Print( 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 | Max98390Print( 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 | } -------------------------------------------------------------------------------- /max98390/registers.h: -------------------------------------------------------------------------------- 1 | 2 | /* MAX98390 Register Address */ 3 | #define MAX98390_SOFTWARE_RESET 0x2000 4 | #define MAX98390_INT_RAW1 0x2002 5 | #define MAX98390_INT_RAW2 0x2003 6 | #define MAX98390_INT_RAW3 0x2004 7 | #define MAX98390_INT_STATE1 0x2005 8 | #define MAX98390_INT_STATE2 0x2006 9 | #define MAX98390_INT_STATE3 0x2007 10 | #define MAX98390_INT_FLAG1 0x2008 11 | #define MAX98390_INT_FLAG2 0x2009 12 | #define MAX98390_INT_FLAG3 0x200a 13 | #define MAX98390_INT_EN1 0x200b 14 | #define MAX98390_INT_EN2 0x200c 15 | #define MAX98390_INT_EN3 0x200d 16 | #define MAX98390_INT_FLAG_CLR1 0x200e 17 | #define MAX98390_INT_FLAG_CLR2 0x200f 18 | #define MAX98390_INT_FLAG_CLR3 0x2010 19 | #define MAX98390_IRQ_CTRL 0x2011 20 | #define MAX98390_CLK_MON 0x2012 21 | #define MAX98390_DAT_MON 0x2014 22 | #define MAX98390_WDOG_CTRL 0x2015 23 | #define MAX98390_WDOG_RST 0x2016 24 | #define MAX98390_MEAS_ADC_THERM_WARN_THRESH 0x2017 25 | #define MAX98390_MEAS_ADC_THERM_SHDN_THRESH 0x2018 26 | #define MAX98390_MEAS_ADC_THERM_HYSTERESIS 0x2019 27 | #define MAX98390_PIN_CFG 0x201a 28 | #define MAX98390_PCM_RX_EN_A 0x201b 29 | #define MAX98390_PCM_RX_EN_B 0x201c 30 | #define MAX98390_PCM_TX_EN_A 0x201d 31 | #define MAX98390_PCM_TX_EN_B 0x201e 32 | #define MAX98390_PCM_TX_HIZ_CTRL_A 0x201f 33 | #define MAX98390_PCM_TX_HIZ_CTRL_B 0x2020 34 | #define MAX98390_PCM_CH_SRC_1 0x2021 35 | #define MAX98390_PCM_CH_SRC_2 0x2022 36 | #define MAX98390_PCM_CH_SRC_3 0x2023 37 | #define MAX98390_PCM_MODE_CFG 0x2024 38 | #define MAX98390_PCM_MASTER_MODE 0x2025 39 | #define MAX98390_PCM_CLK_SETUP 0x2026 40 | #define MAX98390_PCM_SR_SETUP 0x2027 41 | #define MAX98390_ICC_RX_EN_A 0x202c 42 | #define MAX98390_ICC_RX_EN_B 0x202d 43 | #define MAX98390_ICC_TX_EN_A 0x202e 44 | #define MAX98390_ICC_TX_EN_B 0x202f 45 | #define MAX98390_ICC_HIZ_MANUAL_MODE 0x2030 46 | #define MAX98390_ICC_TX_HIZ_EN_A 0x2031 47 | #define MAX98390_ICC_TX_HIZ_EN_B 0x2032 48 | #define MAX98390_ICC_LNK_EN 0x2033 49 | #define MAX98390_R2039_AMP_DSP_CFG 0x2039 50 | #define MAX98390_R203A_AMP_EN 0x203a 51 | #define MAX98390_TONE_GEN_DC_CFG 0x203b 52 | #define MAX98390_SPK_SRC_SEL 0x203c 53 | #define MAX98390_R203D_SPK_GAIN 0x203d 54 | #define MAX98390_SSM_CFG 0x203e 55 | #define MAX98390_MEAS_EN 0x203f 56 | #define MAX98390_MEAS_DSP_CFG 0x2040 57 | #define MAX98390_BOOST_CTRL0 0x2041 58 | #define MAX98390_BOOST_CTRL3 0x2042 59 | #define MAX98390_BOOST_CTRL1 0x2043 60 | #define MAX98390_MEAS_ADC_CFG 0x2044 61 | #define MAX98390_MEAS_ADC_BASE_MSB 0x2045 62 | #define MAX98390_MEAS_ADC_BASE_LSB 0x2046 63 | #define MAX98390_ADC_CH0_DIVIDE 0x2047 64 | #define MAX98390_ADC_CH1_DIVIDE 0x2048 65 | #define MAX98390_ADC_CH2_DIVIDE 0x2049 66 | #define MAX98390_ADC_CH0_FILT_CFG 0x204a 67 | #define MAX98390_ADC_CH1_FILT_CFG 0x204b 68 | #define MAX98390_ADC_CH2_FILT_CFG 0x204c 69 | #define MAX98390_MEAS_ADC_CH0_READ 0x204d 70 | #define MAX98390_MEAS_ADC_CH1_READ 0x204e 71 | #define MAX98390_MEAS_ADC_CH2_READ 0x204f 72 | #define MAX98390_PWR_GATE_CTL 0x2050 73 | #define MAX98390_PWR_GATE_STATUS 0x2051 74 | #define MAX98390_VBAT_LOW_STATUS 0x2052 75 | #define MAX98390_PVDD_LOW_STATUS 0x2053 76 | #define MAX98390_BROWNOUT_STATUS 0x2054 77 | #define MAX98390_BROWNOUT_EN 0x2055 78 | #define MAX98390_BROWNOUT_INFINITE_HOLD 0x2056 79 | #define MAX98390_BROWNOUT_INFINITE_HOLD_CLR 0x2057 80 | #define MAX98390_BROWNOUT_LVL_HOLD 0x2058 81 | #define MAX98390_BROWNOUT_LVL1_THRESH 0x2059 82 | #define MAX98390_BROWNOUT_LVL2_THRESH 0x205a 83 | #define MAX98390_BROWNOUT_LVL3_THRESH 0x205b 84 | #define MAX98390_BROWNOUT_LVL4_THRESH 0x205c 85 | #define MAX98390_BROWNOUT_THRESH_HYSTERYSIS 0x205d 86 | #define MAX98390_BROWNOUT_AMP_LIMITER_ATK_REL 0x205e 87 | #define MAX98390_BROWNOUT_AMP_GAIN_ATK_REL 0x205f 88 | #define MAX98390_BROWNOUT_AMP1_CLIP_MODE 0x2060 89 | #define MAX98390_BROWNOUT_LVL1_CUR_LIMIT 0x2061 90 | #define MAX98390_BROWNOUT_LVL1_AMP1_CTRL1 0x2062 91 | #define MAX98390_BROWNOUT_LVL1_AMP1_CTRL2 0x2063 92 | #define MAX98390_BROWNOUT_LVL1_AMP1_CTRL3 0x2064 93 | #define MAX98390_BROWNOUT_LVL2_CUR_LIMIT 0x2065 94 | #define MAX98390_BROWNOUT_LVL2_AMP1_CTRL1 0x2066 95 | #define MAX98390_BROWNOUT_LVL2_AMP1_CTRL2 0x2067 96 | #define MAX98390_BROWNOUT_LVL2_AMP1_CTRL3 0x2068 97 | #define MAX98390_BROWNOUT_LVL3_CUR_LIMIT 0x2069 98 | #define MAX98390_BROWNOUT_LVL3_AMP1_CTRL1 0x206a 99 | #define MAX98390_BROWNOUT_LVL3_AMP1_CTRL2 0x206b 100 | #define MAX98390_BROWNOUT_LVL3_AMP1_CTRL3 0x206c 101 | #define MAX98390_BROWNOUT_LVL4_CUR_LIMIT 0x206d 102 | #define MAX98390_BROWNOUT_LVL4_AMP1_CTRL1 0x206e 103 | #define MAX98390_BROWNOUT_LVL4_AMP1_CTRL2 0x206f 104 | #define MAX98390_BROWNOUT_LVL4_AMP1_CTRL3 0x2070 105 | #define MAX98390_BROWNOUT_LOWEST_STATUS 0x2071 106 | #define MAX98390_BROWNOUT_ILIM_HLD 0x2072 107 | #define MAX98390_BROWNOUT_LIM_HLD 0x2073 108 | #define MAX98390_BROWNOUT_CLIP_HLD 0x2074 109 | #define MAX98390_BROWNOUT_GAIN_HLD 0x2075 110 | #define MAX98390_ENV_TRACK_VOUT_HEADROOM 0x2076 111 | #define MAX98390_ENV_TRACK_BOOST_VOUT_DELAY 0x2077 112 | #define MAX98390_ENV_TRACK_REL_RATE 0x2078 113 | #define MAX98390_ENV_TRACK_HOLD_RATE 0x2079 114 | #define MAX98390_ENV_TRACK_CTRL 0x207a 115 | #define MAX98390_ENV_TRACK_BOOST_VOUT_READ 0x207b 116 | #define MAX98390_BOOST_BYPASS1 0x207c 117 | #define MAX98390_BOOST_BYPASS2 0x207d 118 | #define MAX98390_BOOST_BYPASS3 0x207e 119 | #define MAX98390_FET_SCALING1 0x207f 120 | #define MAX98390_FET_SCALING2 0x2080 121 | #define MAX98390_FET_SCALING3 0x2081 122 | #define MAX98390_FET_SCALING4 0x2082 123 | #define MAX98390_SPK_SPEEDUP 0x2084 124 | 125 | #define DSM_STBASS_HPF_B0_BYTE0 0x2101 126 | #define DSM_STBASS_HPF_B0_BYTE1 0x2102 127 | #define DSM_STBASS_HPF_B0_BYTE2 0x2103 128 | #define DSM_STBASS_HPF_B1_BYTE0 0x2105 129 | #define DSM_STBASS_HPF_B1_BYTE1 0x2106 130 | #define DSM_STBASS_HPF_B1_BYTE2 0x2107 131 | #define DSM_STBASS_HPF_B2_BYTE0 0x2109 132 | #define DSM_STBASS_HPF_B2_BYTE1 0x210a 133 | #define DSM_STBASS_HPF_B2_BYTE2 0x210b 134 | #define DSM_STBASS_HPF_A1_BYTE0 0x210d 135 | #define DSM_STBASS_HPF_A1_BYTE1 0x210e 136 | #define DSM_STBASS_HPF_A1_BYTE2 0x210f 137 | #define DSM_STBASS_HPF_A2_BYTE0 0x2111 138 | #define DSM_STBASS_HPF_A2_BYTE1 0x2112 139 | #define DSM_STBASS_HPF_A2_BYTE2 0x2113 140 | #define DSM_STBASS_LPF_B0_BYTE0 0x2115 141 | #define DSM_STBASS_LPF_B0_BYTE1 0x2116 142 | #define DSM_STBASS_LPF_B0_BYTE2 0x2117 143 | #define DSM_STBASS_LPF_B1_BYTE0 0x2119 144 | #define DSM_STBASS_LPF_B1_BYTE1 0x211a 145 | #define DSM_STBASS_LPF_B1_BYTE2 0x211b 146 | #define DSM_STBASS_LPF_B2_BYTE0 0x211d 147 | #define DSM_STBASS_LPF_B2_BYTE1 0x211e 148 | #define DSM_STBASS_LPF_B2_BYTE2 0x211f 149 | #define DSM_STBASS_LPF_A1_BYTE0 0x2121 150 | #define DSM_STBASS_LPF_A1_BYTE1 0x2122 151 | #define DSM_STBASS_LPF_A1_BYTE2 0x2123 152 | #define DSM_STBASS_LPF_A2_BYTE0 0x2125 153 | #define DSM_STBASS_LPF_A2_BYTE1 0x2126 154 | #define DSM_STBASS_LPF_A2_BYTE2 0x2127 155 | #define DSM_EQ_BQ1_B0_BYTE0 0x2129 156 | #define DSM_EQ_BQ1_B0_BYTE1 0x212a 157 | #define DSM_EQ_BQ1_B0_BYTE2 0x212b 158 | #define DSM_EQ_BQ1_B1_BYTE0 0x212d 159 | #define DSM_EQ_BQ1_B1_BYTE1 0x212e 160 | #define DSM_EQ_BQ1_B1_BYTE2 0x212f 161 | #define DSM_EQ_BQ1_B2_BYTE0 0x2131 162 | #define DSM_EQ_BQ1_B2_BYTE1 0x2132 163 | #define DSM_EQ_BQ1_B2_BYTE2 0x2133 164 | #define DSM_EQ_BQ1_A1_BYTE0 0x2135 165 | #define DSM_EQ_BQ1_A1_BYTE1 0x2136 166 | #define DSM_EQ_BQ1_A1_BYTE2 0x2137 167 | #define DSM_EQ_BQ1_A2_BYTE0 0x2139 168 | #define DSM_EQ_BQ1_A2_BYTE1 0x213a 169 | #define DSM_EQ_BQ1_A2_BYTE2 0x213b 170 | #define DSM_EQ_BQ2_B0_BYTE0 0x213d 171 | #define DSM_EQ_BQ2_B0_BYTE1 0x213e 172 | #define DSM_EQ_BQ2_B0_BYTE2 0x213f 173 | #define DSM_EQ_BQ2_B1_BYTE0 0x2141 174 | #define DSM_EQ_BQ2_B1_BYTE1 0x2142 175 | #define DSM_EQ_BQ2_B1_BYTE2 0x2143 176 | #define DSM_EQ_BQ2_B2_BYTE0 0x2145 177 | #define DSM_EQ_BQ2_B2_BYTE1 0x2146 178 | #define DSM_EQ_BQ2_B2_BYTE2 0x2147 179 | #define DSM_EQ_BQ2_A1_BYTE0 0x2149 180 | #define DSM_EQ_BQ2_A1_BYTE1 0x214a 181 | #define DSM_EQ_BQ2_A1_BYTE2 0x214b 182 | #define DSM_EQ_BQ2_A2_BYTE0 0x214d 183 | #define DSM_EQ_BQ2_A2_BYTE1 0x214e 184 | #define DSM_EQ_BQ2_A2_BYTE2 0x214f 185 | #define DSM_EQ_BQ3_B0_BYTE0 0x2151 186 | #define DSM_EQ_BQ3_B0_BYTE1 0x2152 187 | #define DSM_EQ_BQ3_B0_BYTE2 0x2153 188 | #define DSM_EQ_BQ3_B1_BYTE0 0x2155 189 | #define DSM_EQ_BQ3_B1_BYTE1 0x2156 190 | #define DSM_EQ_BQ3_B1_BYTE2 0x2157 191 | #define DSM_EQ_BQ3_B2_BYTE0 0x2159 192 | #define DSM_EQ_BQ3_B2_BYTE1 0x215a 193 | #define DSM_EQ_BQ3_B2_BYTE2 0x215b 194 | #define DSM_EQ_BQ3_A1_BYTE0 0x215d 195 | #define DSM_EQ_BQ3_A1_BYTE1 0x215e 196 | #define DSM_EQ_BQ3_A1_BYTE2 0x215f 197 | #define DSM_EQ_BQ3_A2_BYTE0 0x2161 198 | #define DSM_EQ_BQ3_A2_BYTE1 0x2162 199 | #define DSM_EQ_BQ3_A2_BYTE2 0x2163 200 | #define DSM_EQ_BQ4_B0_BYTE0 0x2165 201 | #define DSM_EQ_BQ4_B0_BYTE1 0x2166 202 | #define DSM_EQ_BQ4_B0_BYTE2 0x2167 203 | #define DSM_EQ_BQ4_B1_BYTE0 0x2169 204 | #define DSM_EQ_BQ4_B1_BYTE1 0x216a 205 | #define DSM_EQ_BQ4_B1_BYTE2 0x216b 206 | #define DSM_EQ_BQ4_B2_BYTE0 0x216d 207 | #define DSM_EQ_BQ4_B2_BYTE1 0x216e 208 | #define DSM_EQ_BQ4_B2_BYTE2 0x216f 209 | #define DSM_EQ_BQ4_A1_BYTE0 0x2171 210 | #define DSM_EQ_BQ4_A1_BYTE1 0x2172 211 | #define DSM_EQ_BQ4_A1_BYTE2 0x2173 212 | #define DSM_EQ_BQ4_A2_BYTE0 0x2175 213 | #define DSM_EQ_BQ4_A2_BYTE1 0x2176 214 | #define DSM_EQ_BQ4_A2_BYTE2 0x2177 215 | #define DSM_EQ_BQ5_B0_BYTE0 0x2179 216 | #define DSM_EQ_BQ5_B0_BYTE1 0x217a 217 | #define DSM_EQ_BQ5_B0_BYTE2 0x217b 218 | #define DSM_EQ_BQ5_B1_BYTE0 0x217d 219 | #define DSM_EQ_BQ5_B1_BYTE1 0x217e 220 | #define DSM_EQ_BQ5_B1_BYTE2 0x217f 221 | #define DSM_EQ_BQ5_B2_BYTE0 0x2181 222 | #define DSM_EQ_BQ5_B2_BYTE1 0x2182 223 | #define DSM_EQ_BQ5_B2_BYTE2 0x2183 224 | #define DSM_EQ_BQ5_A1_BYTE0 0x2185 225 | #define DSM_EQ_BQ5_A1_BYTE1 0x2186 226 | #define DSM_EQ_BQ5_A1_BYTE2 0x2187 227 | #define DSM_EQ_BQ5_A2_BYTE0 0x2189 228 | #define DSM_EQ_BQ5_A2_BYTE1 0x218a 229 | #define DSM_EQ_BQ5_A2_BYTE2 0x218b 230 | #define DSM_EQ_BQ6_B0_BYTE0 0x218d 231 | #define DSM_EQ_BQ6_B0_BYTE1 0x218e 232 | #define DSM_EQ_BQ6_B0_BYTE2 0x218f 233 | #define DSM_EQ_BQ6_B1_BYTE0 0x2191 234 | #define DSM_EQ_BQ6_B1_BYTE1 0x2192 235 | #define DSM_EQ_BQ6_B1_BYTE2 0x2193 236 | #define DSM_EQ_BQ6_B2_BYTE0 0x2195 237 | #define DSM_EQ_BQ6_B2_BYTE1 0x2196 238 | #define DSM_EQ_BQ6_B2_BYTE2 0x2197 239 | #define DSM_EQ_BQ6_A1_BYTE0 0x2199 240 | #define DSM_EQ_BQ6_A1_BYTE1 0x219a 241 | #define DSM_EQ_BQ6_A1_BYTE2 0x219b 242 | #define DSM_EQ_BQ6_A2_BYTE0 0x219d 243 | #define DSM_EQ_BQ6_A2_BYTE1 0x219e 244 | #define DSM_EQ_BQ6_A2_BYTE2 0x219f 245 | #define DSM_EQ_BQ7_B0_BYTE0 0x21a1 246 | #define DSM_EQ_BQ7_B0_BYTE1 0x21a2 247 | #define DSM_EQ_BQ7_B0_BYTE2 0x21a3 248 | #define DSM_EQ_BQ7_B1_BYTE0 0x21a5 249 | #define DSM_EQ_BQ7_B1_BYTE1 0x21a6 250 | #define DSM_EQ_BQ7_B1_BYTE2 0x21a7 251 | #define DSM_EQ_BQ7_B2_BYTE0 0x21a9 252 | #define DSM_EQ_BQ7_B2_BYTE1 0x21aa 253 | #define DSM_EQ_BQ7_B2_BYTE2 0x21ab 254 | #define DSM_EQ_BQ7_A1_BYTE0 0x21ad 255 | #define DSM_EQ_BQ7_A1_BYTE1 0x21ae 256 | #define DSM_EQ_BQ7_A1_BYTE2 0x21af 257 | #define DSM_EQ_BQ7_A2_BYTE0 0x21b1 258 | #define DSM_EQ_BQ7_A2_BYTE1 0x21b2 259 | #define DSM_EQ_BQ7_A2_BYTE2 0x21b3 260 | #define DSM_EQ_BQ8_B0_BYTE0 0x21b5 261 | #define DSM_EQ_BQ8_B0_BYTE1 0x21b6 262 | #define DSM_EQ_BQ8_B0_BYTE2 0x21b7 263 | #define DSM_EQ_BQ8_B1_BYTE0 0x21b9 264 | #define DSM_EQ_BQ8_B1_BYTE1 0x21ba 265 | #define DSM_EQ_BQ8_B1_BYTE2 0x21bb 266 | #define DSM_EQ_BQ8_B2_BYTE0 0x21bd 267 | #define DSM_EQ_BQ8_B2_BYTE1 0x21be 268 | #define DSM_EQ_BQ8_B2_BYTE2 0x21bf 269 | #define DSM_EQ_BQ8_A1_BYTE0 0x21c1 270 | #define DSM_EQ_BQ8_A1_BYTE1 0x21c2 271 | #define DSM_EQ_BQ8_A1_BYTE2 0x21c3 272 | #define DSM_EQ_BQ8_A2_BYTE0 0x21c5 273 | #define DSM_EQ_BQ8_A2_BYTE1 0x21c6 274 | #define DSM_EQ_BQ8_A2_BYTE2 0x21c7 275 | #define DSM_LFX_BQ_B0_BYTE0 0x21c9 276 | #define DSM_LFX_BQ_B0_BYTE1 0x21ca 277 | #define DSM_LFX_BQ_B0_BYTE2 0x21cb 278 | #define DSM_LFX_BQ_B1_BYTE0 0x21cd 279 | #define DSM_LFX_BQ_B1_BYTE1 0x21ce 280 | #define DSM_LFX_BQ_B1_BYTE2 0x21cf 281 | #define DSM_LFX_BQ_B2_BYTE0 0x21d1 282 | #define DSM_LFX_BQ_B2_BYTE1 0x21d2 283 | #define DSM_LFX_BQ_B2_BYTE2 0x21d3 284 | #define DSM_LFX_BQ_A1_BYTE0 0x21d5 285 | #define DSM_LFX_BQ_A1_BYTE1 0x21d6 286 | #define DSM_LFX_BQ_A1_BYTE2 0x21d7 287 | #define DSM_LFX_BQ_A2_BYTE0 0x21d9 288 | #define DSM_LFX_BQ_A2_BYTE1 0x21da 289 | #define DSM_LFX_BQ_A2_BYTE2 0x21db 290 | #define DSM_PPR_HPF_B0_BYTE0 0x21dd 291 | #define DSM_PPR_HPF_B0_BYTE1 0x21de 292 | #define DSM_PPR_HPF_B0_BYTE2 0x21df 293 | #define DSM_PPR_HPF_B1_BYTE0 0x21e1 294 | #define DSM_PPR_HPF_B1_BYTE1 0x21e2 295 | #define DSM_PPR_HPF_B1_BYTE2 0x21e3 296 | #define DSM_PPR_HPF_B2_BYTE0 0x21e5 297 | #define DSM_PPR_HPF_B2_BYTE1 0x21e6 298 | #define DSM_PPR_HPF_B2_BYTE2 0x21e7 299 | #define DSM_PPR_HPF_A1_BYTE0 0x21e9 300 | #define DSM_PPR_HPF_A1_BYTE1 0x21ea 301 | #define DSM_PPR_HPF_A1_BYTE2 0x21eb 302 | #define DSM_PPR_HPF_A2_BYTE0 0x21ed 303 | #define DSM_PPR_HPF_A2_BYTE1 0x21ee 304 | #define DSM_PPR_HPF_A2_BYTE2 0x21ef 305 | #define DSM_PPR_LPF_B0_BYTE0 0x21f1 306 | #define DSM_PPR_LPF_B0_BYTE1 0x21f2 307 | #define DSM_PPR_LPF_B0_BYTE2 0x21f3 308 | #define DSM_PPR_LPF_B1_BYTE0 0x21f5 309 | #define DSM_PPR_LPF_B1_BYTE1 0x21f6 310 | #define DSM_PPR_LPF_B1_BYTE2 0x21f7 311 | #define DSM_PPR_LPF_B2_BYTE0 0x21f9 312 | #define DSM_PPR_LPF_B2_BYTE1 0x21fa 313 | #define DSM_PPR_LPF_B2_BYTE2 0x21fb 314 | #define DSM_PPR_LPF_A1_BYTE0 0x21fd 315 | #define DSM_PPR_LPF_A1_BYTE1 0x21fe 316 | #define DSM_PPR_LPF_A1_BYTE2 0x21ff 317 | #define DSM_PPR_LPF_A2_BYTE0 0x2201 318 | #define DSM_PPR_LPF_A2_BYTE1 0x2202 319 | #define DSM_PPR_LPF_A2_BYTE2 0x2203 320 | #define DSM_SPL_BQ_B0_BYTE0 0x2205 321 | #define DSM_SPL_BQ_B0_BYTE1 0x2206 322 | #define DSM_SPL_BQ_B0_BYTE2 0x2207 323 | #define DSM_SPL_BQ_B1_BYTE0 0x2209 324 | #define DSM_SPL_BQ_B1_BYTE1 0x220a 325 | #define DSM_SPL_BQ_B1_BYTE2 0x220b 326 | #define DSM_SPL_BQ_B2_BYTE0 0x220d 327 | #define DSM_SPL_BQ_B2_BYTE1 0x220e 328 | #define DSM_SPL_BQ_B2_BYTE2 0x220f 329 | #define DSM_SPL_BQ_A1_BYTE0 0x2211 330 | #define DSM_SPL_BQ_A1_BYTE1 0x2212 331 | #define DSM_SPL_BQ_A1_BYTE2 0x2213 332 | #define DSM_SPL_BQ_A2_BYTE0 0x2215 333 | #define DSM_SPL_BQ_A2_BYTE1 0x2216 334 | #define DSM_SPL_BQ_A2_BYTE2 0x2217 335 | #define DSM_EXCUR_BQ_B0_BYTE0 0x2219 336 | #define DSM_EXCUR_BQ_B0_BYTE1 0x221a 337 | #define DSM_EXCUR_BQ_B0_BYTE2 0x221b 338 | #define DSM_EXCUR_BQ_B1_BYTE0 0x221d 339 | #define DSM_EXCUR_BQ_B1_BYTE1 0x221e 340 | #define DSM_EXCUR_BQ_B1_BYTE2 0x221f 341 | #define DSM_EXCUR_BQ_B2_BYTE0 0x2221 342 | #define DSM_EXCUR_BQ_B2_BYTE1 0x2222 343 | #define DSM_EXCUR_BQ_B2_BYTE2 0x2223 344 | #define DSM_EXCUR_BQ_A1_BYTE0 0x2225 345 | #define DSM_EXCUR_BQ_A1_BYTE1 0x2226 346 | #define DSM_EXCUR_BQ_A1_BYTE2 0x2227 347 | #define DSM_EXCUR_BQ_A2_BYTE0 0x2229 348 | #define DSM_EXCUR_BQ_A2_BYTE1 0x222a 349 | #define DSM_EXCUR_BQ_A2_BYTE2 0x222b 350 | #define DSM_EXCPROT_HPF1_B0_BYTE0 0x222d 351 | #define DSM_EXCPROT_HPF1_B0_BYTE1 0x222e 352 | #define DSM_EXCPROT_HPF1_B0_BYTE2 0x222f 353 | #define DSM_EXCPROT_HPF1_B1_BYTE0 0x2231 354 | #define DSM_EXCPROT_HPF1_B1_BYTE1 0x2232 355 | #define DSM_EXCPROT_HPF1_B1_BYTE2 0x2233 356 | #define DSM_EXCPROT_HPF1_B2_BYTE0 0x2235 357 | #define DSM_EXCPROT_HPF1_B2_BYTE1 0x2236 358 | #define DSM_EXCPROT_HPF1_B2_BYTE2 0x2237 359 | #define DSM_EXCPROT_HPF1_A1_BYTE0 0x2239 360 | #define DSM_EXCPROT_HPF1_A1_BYTE1 0x223a 361 | #define DSM_EXCPROT_HPF1_A1_BYTE2 0x223b 362 | #define DSM_EXCPROT_HPF1_A2_BYTE0 0x223d 363 | #define DSM_EXCPROT_HPF1_A2_BYTE1 0x223e 364 | #define DSM_EXCPROT_HPF1_A2_BYTE2 0x223f 365 | #define DSM_EXCPROT_HPF2_B0_BYTE0 0x2241 366 | #define DSM_EXCPROT_HPF2_B0_BYTE1 0x2242 367 | #define DSM_EXCPROT_HPF2_B0_BYTE2 0x2243 368 | #define DSM_EXCPROT_HPF2_B1_BYTE0 0x2245 369 | #define DSM_EXCPROT_HPF2_B1_BYTE1 0x2246 370 | #define DSM_EXCPROT_HPF2_B1_BYTE2 0x2247 371 | #define DSM_EXCPROT_HPF2_B2_BYTE0 0x2249 372 | #define DSM_EXCPROT_HPF2_B2_BYTE1 0x224a 373 | #define DSM_EXCPROT_HPF2_B2_BYTE2 0x224b 374 | #define DSM_EXCPROT_HPF2_A1_BYTE0 0x224d 375 | #define DSM_EXCPROT_HPF2_A1_BYTE1 0x224e 376 | #define DSM_EXCPROT_HPF2_A1_BYTE2 0x224f 377 | #define DSM_EXCPROT_HPF2_A2_BYTE0 0x2251 378 | #define DSM_EXCPROT_HPF2_A2_BYTE1 0x2252 379 | #define DSM_EXCPROT_HPF2_A2_BYTE2 0x2253 380 | #define DSM_EXCPROT_HPF3_B0_BYTE0 0x2255 381 | #define DSM_EXCPROT_HPF3_B0_BYTE1 0x2256 382 | #define DSM_EXCPROT_HPF3_B0_BYTE2 0x2257 383 | #define DSM_EXCPROT_HPF3_B1_BYTE0 0x2259 384 | #define DSM_EXCPROT_HPF3_B1_BYTE1 0x225a 385 | #define DSM_EXCPROT_HPF3_B1_BYTE2 0x225b 386 | #define DSM_EXCPROT_HPF3_B2_BYTE0 0x225d 387 | #define DSM_EXCPROT_HPF3_B2_BYTE1 0x225e 388 | #define DSM_EXCPROT_HPF3_B2_BYTE2 0x225f 389 | #define DSM_EXCPROT_HPF3_A1_BYTE0 0x2261 390 | #define DSM_EXCPROT_HPF3_A1_BYTE1 0x2262 391 | #define DSM_EXCPROT_HPF3_A1_BYTE2 0x2263 392 | #define DSM_EXCPROT_HPF3_A2_BYTE0 0x2265 393 | #define DSM_EXCPROT_HPF3_A2_BYTE1 0x2266 394 | #define DSM_EXCPROT_HPF3_A2_BYTE2 0x2267 395 | #define DSM_EXCPROT_HPF4_B0_BYTE0 0x2269 396 | #define DSM_EXCPROT_HPF4_B0_BYTE1 0x226a 397 | #define DSM_EXCPROT_HPF4_B0_BYTE2 0x226b 398 | #define DSM_EXCPROT_HPF4_B1_BYTE0 0x226d 399 | #define DSM_EXCPROT_HPF4_B1_BYTE1 0x226e 400 | #define DSM_EXCPROT_HPF4_B1_BYTE2 0x226f 401 | #define DSM_EXCPROT_HPF4_B2_BYTE0 0x2271 402 | #define DSM_EXCPROT_HPF4_B2_BYTE1 0x2272 403 | #define DSM_EXCPROT_HPF4_B2_BYTE2 0x2273 404 | #define DSM_EXCPROT_HPF4_A1_BYTE0 0x2275 405 | #define DSM_EXCPROT_HPF4_A1_BYTE1 0x2276 406 | #define DSM_EXCPROT_HPF4_A1_BYTE2 0x2277 407 | #define DSM_EXCPROT_HPF4_A2_BYTE0 0x2279 408 | #define DSM_EXCPROT_HPF4_A2_BYTE1 0x227a 409 | #define DSM_EXCPROT_HPF4_A2_BYTE2 0x227b 410 | #define DSM_EXCPROT_HPF5_B0_BYTE0 0x227d 411 | #define DSM_EXCPROT_HPF5_B0_BYTE1 0x227e 412 | #define DSM_EXCPROT_HPF5_B0_BYTE2 0x227f 413 | #define DSM_EXCPROT_HPF5_B1_BYTE0 0x2281 414 | #define DSM_EXCPROT_HPF5_B1_BYTE1 0x2282 415 | #define DSM_EXCPROT_HPF5_B1_BYTE2 0x2283 416 | #define DSM_EXCPROT_HPF5_B2_BYTE0 0x2285 417 | #define DSM_EXCPROT_HPF5_B2_BYTE1 0x2286 418 | #define DSM_EXCPROT_HPF5_B2_BYTE2 0x2287 419 | #define DSM_EXCPROT_HPF5_A1_BYTE0 0x2289 420 | #define DSM_EXCPROT_HPF5_A1_BYTE1 0x228a 421 | #define DSM_EXCPROT_HPF5_A1_BYTE2 0x228b 422 | #define DSM_EXCPROT_HPF5_A2_BYTE0 0x228d 423 | #define DSM_EXCPROT_HPF5_A2_BYTE1 0x228e 424 | #define DSM_EXCPROT_HPF5_A2_BYTE2 0x228f 425 | #define DSM_DEBUZZ_BPF_B0_BYTE0 0x2291 426 | #define DSM_DEBUZZ_BPF_B0_BYTE1 0x2292 427 | #define DSM_DEBUZZ_BPF_B0_BYTE2 0x2293 428 | #define DSM_DEBUZZ_BPF_B1_BYTE0 0x2295 429 | #define DSM_DEBUZZ_BPF_B1_BYTE1 0x2296 430 | #define DSM_DEBUZZ_BPF_B1_BYTE2 0x2297 431 | #define DSM_DEBUZZ_BPF_B2_BYTE0 0x2299 432 | #define DSM_DEBUZZ_BPF_B2_BYTE1 0x229a 433 | #define DSM_DEBUZZ_BPF_B2_BYTE2 0x229b 434 | #define DSM_DEBUZZ_BPF_A1_BYTE0 0x229d 435 | #define DSM_DEBUZZ_BPF_A1_BYTE1 0x229e 436 | #define DSM_DEBUZZ_BPF_A1_BYTE2 0x229f 437 | #define DSM_DEBUZZ_BPF_A2_BYTE0 0x22a1 438 | #define DSM_DEBUZZ_BPF_A2_BYTE1 0x22a2 439 | #define DSM_DEBUZZ_BPF_A2_BYTE2 0x22a3 440 | #define DSM_DEBUZZ_PORT_B0_BYTE0 0x22a5 441 | #define DSM_DEBUZZ_PORT_B0_BYTE1 0x22a6 442 | #define DSM_DEBUZZ_PORT_B0_BYTE2 0x22a7 443 | #define DSM_DEBUZZ_PORT_B1_BYTE0 0x22a9 444 | #define DSM_DEBUZZ_PORT_B1_BYTE1 0x22aa 445 | #define DSM_DEBUZZ_PORT_B1_BYTE2 0x22ab 446 | #define DSM_DEBUZZ_PORT_B2_BYTE0 0x22ad 447 | #define DSM_DEBUZZ_PORT_B2_BYTE1 0x22ae 448 | #define DSM_DEBUZZ_PORT_B2_BYTE2 0x22af 449 | #define DSM_DEBUZZ_PORT_A1_BYTE0 0x22b1 450 | #define DSM_DEBUZZ_PORT_A1_BYTE1 0x22b2 451 | #define DSM_DEBUZZ_PORT_A1_BYTE2 0x22b3 452 | #define DSM_DEBUZZ_PORT_A2_BYTE0 0x22b5 453 | #define DSM_DEBUZZ_PORT_A2_BYTE1 0x22b6 454 | #define DSM_DEBUZZ_PORT_A2_BYTE2 0x22b7 455 | #define DSM_DEBUZZ_NOTCH_B0_BYTE0 0x22b9 456 | #define DSM_DEBUZZ_NOTCH_B0_BYTE1 0x22ba 457 | #define DSM_DEBUZZ_NOTCH_B0_BYTE2 0x22bb 458 | #define DSM_DEBUZZ_NOTCH_B1_BYTE0 0x22bd 459 | #define DSM_DEBUZZ_NOTCH_B1_BYTE1 0x22be 460 | #define DSM_DEBUZZ_NOTCH_B1_BYTE2 0x22bf 461 | #define DSM_DEBUZZ_NOTCH_B2_BYTE0 0x22c1 462 | #define DSM_DEBUZZ_NOTCH_B2_BYTE1 0x22c2 463 | #define DSM_DEBUZZ_NOTCH_B2_BYTE2 0x22c3 464 | #define DSM_DEBUZZ_NOTCH_A1_BYTE0 0x22c5 465 | #define DSM_DEBUZZ_NOTCH_A1_BYTE1 0x22c6 466 | #define DSM_DEBUZZ_NOTCH_A1_BYTE2 0x22c7 467 | #define DSM_DEBUZZ_NOTCH_A2_BYTE0 0x22c9 468 | #define DSM_DEBUZZ_NOTCH_A2_BYTE1 0x22ca 469 | #define DSM_DEBUZZ_NOTCH_A2_BYTE2 0x22cb 470 | #define DSM_THERMAL_BQ_B0_BYTE0 0x22cd 471 | #define DSM_THERMAL_BQ_B0_BYTE1 0x22ce 472 | #define DSM_THERMAL_BQ_B0_BYTE2 0x22cf 473 | #define DSM_THERMAL_BQ_B1_BYTE0 0x22d1 474 | #define DSM_THERMAL_BQ_B1_BYTE1 0x22d2 475 | #define DSM_THERMAL_BQ_B1_BYTE2 0x22d3 476 | #define DSM_THERMAL_BQ_B2_BYTE0 0x22d5 477 | #define DSM_THERMAL_BQ_B2_BYTE1 0x22d6 478 | #define DSM_THERMAL_BQ_B2_BYTE2 0x22d7 479 | #define DSM_THERMAL_BQ_A1_BYTE0 0x22d9 480 | #define DSM_THERMAL_BQ_A1_BYTE1 0x22da 481 | #define DSM_THERMAL_BQ_A1_BYTE2 0x22db 482 | #define DSM_THERMAL_BQ_A2_BYTE0 0x22dd 483 | #define DSM_THERMAL_BQ_A2_BYTE1 0x22de 484 | #define DSM_THERMAL_BQ_A2_BYTE2 0x22df 485 | #define DSM_WBDRC_FILT1_B0_BYTE0 0x22e1 486 | #define DSM_WBDRC_FILT1_B0_BYTE1 0x22e2 487 | #define DSM_WBDRC_FILT1_B0_BYTE2 0x22e3 488 | #define DSM_WBDRC_FILT1_B1_BYTE0 0x22e5 489 | #define DSM_WBDRC_FILT1_B1_BYTE1 0x22e6 490 | #define DSM_WBDRC_FILT1_B1_BYTE2 0x22e7 491 | #define DSM_WBDRC_FILT1_B2_BYTE0 0x22e9 492 | #define DSM_WBDRC_FILT1_B2_BYTE1 0x22ea 493 | #define DSM_WBDRC_FILT1_B2_BYTE2 0x22eb 494 | #define DSM_WBDRC_FILT1_A1_BYTE0 0x22ed 495 | #define DSM_WBDRC_FILT1_A1_BYTE1 0x22ee 496 | #define DSM_WBDRC_FILT1_A1_BYTE2 0x22ef 497 | #define DSM_WBDRC_FILT1_A2_BYTE0 0x22f1 498 | #define DSM_WBDRC_FILT1_A2_BYTE1 0x22f2 499 | #define DSM_WBDRC_FILT1_A2_BYTE2 0x22f3 500 | #define DSM_WBDRC_FILT2_B0_BYTE0 0x22f5 501 | #define DSM_WBDRC_FILT2_B0_BYTE1 0x22f6 502 | #define DSM_WBDRC_FILT2_B0_BYTE2 0x22f7 503 | #define DSM_WBDRC_FILT2_B1_BYTE0 0x22f9 504 | #define DSM_WBDRC_FILT2_B1_BYTE1 0x22fa 505 | #define DSM_WBDRC_FILT2_B1_BYTE2 0x22fb 506 | #define DSM_WBDRC_FILT2_B2_BYTE0 0x22fd 507 | #define DSM_WBDRC_FILT2_B2_BYTE1 0x22fe 508 | #define DSM_WBDRC_FILT2_B2_BYTE2 0x22ff 509 | #define DSM_WBDRC_FILT2_A1_BYTE0 0x2301 510 | #define DSM_WBDRC_FILT2_A1_BYTE1 0x2302 511 | #define DSM_WBDRC_FILT2_A1_BYTE2 0x2303 512 | #define DSM_WBDRC_FILT2_A2_BYTE0 0x2305 513 | #define DSM_WBDRC_FILT2_A2_BYTE1 0x2306 514 | #define DSM_WBDRC_FILT2_A2_BYTE2 0x2307 515 | #define DSM_PPR_RELEASE_TIME_BYTE0 0x2309 516 | #define DSM_PPR_RELEASE_TIME_BYTE1 0x230a 517 | #define DSM_PPR_RELEASE_TIME_BYTE2 0x230b 518 | #define DSM_PPR_ATTACK_TIME_BYTE0 0x230d 519 | #define DSM_PPR_ATTACK_TIME_BYTE1 0x230e 520 | #define DSM_PPR_ATTACK_TIME_BYTE2 0x230f 521 | #define DSM_DEBUZZER_RELEASE_TIME_BYTE0 0x2311 522 | #define DSM_DEBUZZER_RELEASE_TIME_BYTE1 0x2312 523 | #define DSM_DEBUZZER_RELEASE_TIME_BYTE2 0x2313 524 | #define DSM_DEBUZZER_ATTACK_TIME_BYTE0 0x2315 525 | #define DSM_DEBUZZER_ATTACK_TIME_BYTE1 0x2316 526 | #define DSM_DEBUZZER_ATTACK_TIME_BYTE2 0x2317 527 | 528 | #define DSMIG_WB_DRC_RELEASE_TIME_1 0x2380 529 | #define DSMIG_WB_DRC_RELEASE_TIME_2 0x2381 530 | #define DSMIG_WB_DRC_ATTACK_TIME_1 0x2382 531 | #define DSMIG_WB_DRC_ATTACK_TIME_2 0x2383 532 | #define DSMIG_WB_DRC_COMPRESSION_RATIO 0x2384 533 | #define DSMIG_WB_DRC_COMPRESSION_THRESHOLD 0x2385 534 | #define DSMIG_WB_DRC_MAKEUPGAIN 0x2386 535 | #define DSMIG_WB_DRC_NOISE_GATE_THRESHOLD 0x2387 536 | #define DSMIG_WBDRC_HPF_ENABLE 0x2388 537 | #define DSMIG_WB_DRC_TEST_SMOOTHER_OUT_EN 0x2389 538 | #define DSMIG_PPR_THRESHOLD 0x238b 539 | #define DSM_STEREO_BASS_CHANNEL_SELECT 0x238d 540 | #define DSM_TPROT_THRESHOLD_BYTE0 0x238e 541 | #define DSM_TPROT_THRESHOLD_BYTE1 0x238f 542 | #define DSM_TPROT_ROOM_TEMPERATURE_BYTE0 0x2390 543 | #define DSM_TPROT_ROOM_TEMPERATURE_BYTE1 0x2391 544 | #define DSM_TPROT_RECIP_RDC_ROOM_BYTE0 0x2392 545 | #define DSM_TPROT_RECIP_RDC_ROOM_BYTE1 0x2393 546 | #define DSM_TPROT_RECIP_RDC_ROOM_BYTE2 0x2394 547 | #define DSM_TPROT_RECIP_TCONST_BYTE0 0x2395 548 | #define DSM_TPROT_RECIP_TCONST_BYTE1 0x2396 549 | #define DSM_TPROT_RECIP_TCONST_BYTE2 0x2397 550 | #define DSM_THERMAL_ATTENUATION_SETTINGS 0x2398 551 | #define DSM_THERMAL_PILOT_TONE_ATTENUATION 0x2399 552 | #define DSM_TPROT_PG_TEMP_THRESH_BYTE0 0x239a 553 | #define DSM_TPROT_PG_TEMP_THRESH_BYTE1 0x239b 554 | 555 | #define THERMAL_RDC_RD_BACK_BYTE1 0x239c 556 | #define THERMAL_RDC_RD_BACK_BYTE0 0x239d 557 | #define THERMAL_COILTEMP_RD_BACK_BYTE1 0x239e 558 | #define THERMAL_COILTEMP_RD_BACK_BYTE0 0x239f 559 | 560 | #define DSMIG_DEBUZZER_THRESHOLD 0x23b5 561 | #define DSMIG_DEBUZZER_ALPHA_COEF_TEST_ONLY 0x23b6 562 | #define DSM_VOL_ENA 0x23b9 563 | #define DSM_VOL_CTRL 0x23ba 564 | 565 | #define DSMIG_EN 0x23e0 566 | #define MAX98390_R23E1_DSP_GLOBAL_EN 0x23e1 567 | 568 | #define DSM_THERMAL_GAIN 0x23f0 569 | #define DSM_PPR_GAIN 0x23f1 570 | #define DSM_DBZ_GAIN 0x23f2 571 | #define DSM_WBDRC_GAIN 0x23f3 572 | 573 | #define MAX98390_R23FF_GLOBAL_EN 0x23FF 574 | #define MAX98390_R24FF_REV_ID 0x24FF 575 | 576 | /* MAX98390_R2021_PCM_RX_SRC_1 */ 577 | #define MAX98390_PCM_RX_CH_SRC_SHIFT (0) 578 | #define MAX98390_PCM_RX_CH_SRC_BASS_SHIFT (4) 579 | 580 | /* MAX98390_R2022_PCM_TX_SRC_1 */ 581 | #define MAX98390_PCM_TX_CH_SRC_A_V_SHIFT (0) 582 | #define MAX98390_PCM_TX_CH_SRC_A_I_SHIFT (4) 583 | 584 | /* MAX98390_R2024_PCM_DATA_FMT_CFG */ 585 | #define MAX98390_PCM_MODE_CFG_FORMAT_MASK (0x7 << 3) 586 | #define MAX98390_PCM_MODE_CFG_FORMAT_SHIFT (3) 587 | #define MAX98390_PCM_TX_CH_INTERLEAVE_MASK (0x1 << 2) 588 | #define MAX98390_PCM_FORMAT_I2S (0x0 << 0) 589 | #define MAX98390_PCM_FORMAT_LJ (0x1 << 0) 590 | #define MAX98390_PCM_FORMAT_TDM_MODE0 (0x3 << 0) 591 | #define MAX98390_PCM_FORMAT_TDM_MODE1 (0x4 << 0) 592 | #define MAX98390_PCM_FORMAT_TDM_MODE2 (0x5 << 0) 593 | #define MAX98390_PCM_MODE_CFG_CHANSZ_MASK (0x3 << 6) 594 | #define MAX98390_PCM_MODE_CFG_CHANSZ_16 (0x1 << 6) 595 | #define MAX98390_PCM_MODE_CFG_CHANSZ_24 (0x2 << 6) 596 | #define MAX98390_PCM_MODE_CFG_CHANSZ_32 (0x3 << 6) 597 | 598 | /* MAX98390_R2039_AMP_DSP_CFG */ 599 | #define MAX98390_AMP_DSP_CFG_RMP_UP_SHIFT (4) 600 | #define MAX98390_AMP_DSP_CFG_RMP_DN_SHIFT (5) 601 | 602 | /* MAX98390_R203A_AMP_EN */ 603 | #define MAX98390_R203A_AMP_EN_SHIFT (0) 604 | 605 | /* MAX98390_PCM_MASTER_MODE */ 606 | #define MAX98390_PCM_MASTER_MODE_MASK (0x3 << 0) 607 | #define MAX98390_PCM_MASTER_MODE_SLAVE (0x0 << 0) 608 | #define MAX98390_PCM_MASTER_MODE_MASTER (0x3 << 0) 609 | 610 | #define MAX98390_PCM_MASTER_MODE_MCLK_MASK (0xF << 2) 611 | #define MAX98390_PCM_MASTER_MODE_MCLK_RATE_SHIFT (2) 612 | 613 | /* PCM_CLK_SETUP */ 614 | #define MAX98390_PCM_MODE_CFG_PCM_BCLKEDGE (0x1 << 2) 615 | #define MAX98390_PCM_CLK_SETUP_BSEL_MASK (0xF << 0) 616 | 617 | /* PCM_SR_SETUP */ 618 | #define MAX98390_PCM_SR_SET1_SR_MASK (0xF << 0) 619 | #define MAX98390_PCM_SR_SET1_SR_8000 (0x0 << 0) 620 | #define MAX98390_PCM_SR_SET1_SR_11025 (0x1 << 0) 621 | #define MAX98390_PCM_SR_SET1_SR_12000 (0x2 << 0) 622 | #define MAX98390_PCM_SR_SET1_SR_16000 (0x3 << 0) 623 | #define MAX98390_PCM_SR_SET1_SR_22050 (0x4 << 0) 624 | #define MAX98390_PCM_SR_SET1_SR_24000 (0x5 << 0) 625 | #define MAX98390_PCM_SR_SET1_SR_32000 (0x6 << 0) 626 | #define MAX98390_PCM_SR_SET1_SR_44100 (0x7 << 0) 627 | #define MAX98390_PCM_SR_SET1_SR_48000 (0x8 << 0) 628 | 629 | /* PCM_TO_SPK_MONO_MIX_1 */ 630 | #define MAX98390_PCM_TO_SPK_MONOMIX_CFG_MASK (0x3 << 6) 631 | #define MAX98390_PCM_TO_SPK_MONOMIX_CFG_SHIFT (6) 632 | #define MAX98390_PCM_TO_SPK_CH0_SRC_MASK (0xF << 0) 633 | #define MAX98390_PCM_TO_SPK_CH1_SRC_MASK (0xF << 4) 634 | 635 | /* MAX98390_BOOST_CTRL3 */ 636 | #define MAX98390_BOOST_CLK_PHASE_CFG_SHIFT (2) 637 | 638 | /* SOFT_RESET */ 639 | #define MAX98390_SOFT_RESET_MASK (0x1 << 0) 640 | 641 | #define MAX98390_GLOBAL_EN_MASK (0x1 << 0) 642 | #define MAX98390_AMP_EN_MASK (0x1 << 0) 643 | 644 | /* DSM register offset */ 645 | #define MAX98390_DSM_PAYLOAD_OFFSET 16 646 | #define MAX98390_DSM_PARAM_MAX_SIZE 1024 647 | #define MAX98390_DSM_PARAM_MIN_SIZE 670 -------------------------------------------------------------------------------- /max98390/max98390.c: -------------------------------------------------------------------------------- 1 | #include "max98390.h" 2 | #include "registers.h" 3 | #include "firmware.h" 4 | 5 | #define bool int 6 | 7 | static ULONG Max98390DebugLevel = 100; 8 | static ULONG Max98390DebugCatagories = 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 | Max98390Print(DEBUG_LEVEL_INFO, DBG_INIT, 21 | "Driver Entry\n"); 22 | 23 | WDF_DRIVER_CONFIG_INIT(&config, Max98390EvtDeviceAdd); 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 | Max98390Print(DEBUG_LEVEL_ERROR, DBG_INIT, 41 | "WdfDriverCreate failed with status 0x%x\n", status); 42 | } 43 | 44 | return status; 45 | } 46 | 47 | NTSTATUS max98390_reg_read( 48 | _In_ PMAX98390_CONTEXT pDevice, 49 | uint16_t reg, 50 | uint8_t* data 51 | ) { 52 | uint8_t buf[2]; 53 | buf[0] = (reg >> 8) & 0xff; 54 | buf[1] = reg & 0xff; 55 | 56 | uint8_t raw_data = 0; 57 | NTSTATUS status = SpbXferDataSynchronously(&pDevice->I2CContext, buf, sizeof(buf), &raw_data, sizeof(uint8_t)); 58 | *data = raw_data; 59 | return status; 60 | } 61 | 62 | NTSTATUS max98390_reg_write( 63 | _In_ PMAX98390_CONTEXT pDevice, 64 | uint16_t reg, 65 | uint8_t data 66 | ) { 67 | uint8_t buf[3]; 68 | buf[0] = (reg >> 8) & 0xff; 69 | buf[1] = reg & 0xff; 70 | buf[2] = data; 71 | return SpbWriteDataSynchronously(&pDevice->I2CContext, buf, sizeof(buf)); 72 | } 73 | 74 | NTSTATUS max98390_reg_update( 75 | _In_ PMAX98390_CONTEXT pDevice, 76 | uint16_t reg, 77 | uint8_t mask, 78 | uint8_t val 79 | ) { 80 | uint8_t tmp = 0, orig = 0; 81 | 82 | NTSTATUS status = max98390_reg_read(pDevice, reg, &orig); 83 | if (!NT_SUCCESS(status)) { 84 | return status; 85 | } 86 | 87 | tmp = orig & ~mask; 88 | tmp |= val & mask; 89 | 90 | if (tmp != orig) { 91 | status = max98390_reg_write(pDevice, reg, tmp); 92 | } 93 | return status; 94 | } 95 | 96 | NTSTATUS 97 | GetDeviceUID( 98 | _In_ WDFDEVICE FxDevice, 99 | _In_ PINT32 PUID 100 | ) 101 | { 102 | NTSTATUS status = STATUS_ACPI_NOT_INITIALIZED; 103 | ACPI_EVAL_INPUT_BUFFER_EX inputBuffer; 104 | RtlZeroMemory(&inputBuffer, sizeof(inputBuffer)); 105 | 106 | inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE_EX; 107 | status = RtlStringCchPrintfA( 108 | inputBuffer.MethodName, 109 | sizeof(inputBuffer.MethodName), 110 | "_UID" 111 | ); 112 | if (!NT_SUCCESS(status)) { 113 | return status; 114 | } 115 | 116 | WDFMEMORY outputMemory; 117 | PACPI_EVAL_OUTPUT_BUFFER outputBuffer; 118 | size_t outputArgumentBufferSize = 32; 119 | size_t outputBufferSize = FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) + outputArgumentBufferSize; 120 | 121 | WDF_OBJECT_ATTRIBUTES attributes; 122 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 123 | attributes.ParentObject = FxDevice; 124 | 125 | status = WdfMemoryCreate(&attributes, 126 | NonPagedPoolNx, 127 | 0, 128 | outputBufferSize, 129 | &outputMemory, 130 | (PVOID*)&outputBuffer); 131 | if (!NT_SUCCESS(status)) { 132 | return status; 133 | } 134 | 135 | RtlZeroMemory(outputBuffer, outputBufferSize); 136 | 137 | WDF_MEMORY_DESCRIPTOR inputMemDesc; 138 | WDF_MEMORY_DESCRIPTOR outputMemDesc; 139 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&inputMemDesc, &inputBuffer, (ULONG)sizeof(inputBuffer)); 140 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&outputMemDesc, outputMemory, NULL); 141 | 142 | status = WdfIoTargetSendInternalIoctlSynchronously( 143 | WdfDeviceGetIoTarget(FxDevice), 144 | NULL, 145 | IOCTL_ACPI_EVAL_METHOD_EX, 146 | &inputMemDesc, 147 | &outputMemDesc, 148 | NULL, 149 | NULL 150 | ); 151 | if (!NT_SUCCESS(status)) { 152 | goto Exit; 153 | } 154 | 155 | if (outputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) { 156 | goto Exit; 157 | } 158 | 159 | if (outputBuffer->Count < 1) { 160 | goto Exit; 161 | } 162 | 163 | uint32_t uid; 164 | if (outputBuffer->Argument[0].DataLength >= 4) { 165 | uid = *(uint32_t*)outputBuffer->Argument->Data; 166 | } 167 | else if (outputBuffer->Argument[0].DataLength >= 2) { 168 | uid = *(uint16_t*)outputBuffer->Argument->Data; 169 | } 170 | else { 171 | uid = *(uint8_t*)outputBuffer->Argument->Data; 172 | } 173 | if (PUID) { 174 | *PUID = uid; 175 | } 176 | else { 177 | status = STATUS_ACPI_INVALID_ARGUMENT; 178 | } 179 | Exit: 180 | if (outputMemory != WDF_NO_HANDLE) { 181 | WdfObjectDelete(outputMemory); 182 | } 183 | return status; 184 | } 185 | 186 | int CsAudioArg2 = 1; 187 | 188 | static NTSTATUS GetIntegerProperty( 189 | _In_ WDFDEVICE FxDevice, 190 | char* propertyStr, 191 | UINT16* property 192 | ) { 193 | PMAX98390_CONTEXT pDevice = GetDeviceContext(FxDevice); 194 | WDFMEMORY outputMemory = WDF_NO_HANDLE; 195 | 196 | NTSTATUS status = STATUS_ACPI_NOT_INITIALIZED; 197 | 198 | size_t inputBufferLen = sizeof(ACPI_GET_DEVICE_SPECIFIC_DATA) + strlen(propertyStr) + 1; 199 | ACPI_GET_DEVICE_SPECIFIC_DATA* inputBuffer = ExAllocatePoolWithTag(NonPagedPool, inputBufferLen, MAX98390_POOL_TAG); 200 | if (!inputBuffer) { 201 | goto Exit; 202 | } 203 | RtlZeroMemory(inputBuffer, inputBufferLen); 204 | 205 | inputBuffer->Signature = IOCTL_ACPI_GET_DEVICE_SPECIFIC_DATA_SIGNATURE; 206 | 207 | unsigned char uuidend[] = { 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01 }; 208 | 209 | inputBuffer->Section.Data1 = 0xdaffd814; 210 | inputBuffer->Section.Data2 = 0x6eba; 211 | inputBuffer->Section.Data3 = 0x4d8c; 212 | memcpy(inputBuffer->Section.Data4, uuidend, sizeof(uuidend)); //Avoid Windows defender false positive 213 | 214 | strcpy(inputBuffer->PropertyName, propertyStr); 215 | inputBuffer->PropertyNameLength = strlen(propertyStr) + 1; 216 | 217 | PACPI_EVAL_OUTPUT_BUFFER outputBuffer; 218 | size_t outputArgumentBufferSize = 8; 219 | size_t outputBufferSize = FIELD_OFFSET(ACPI_EVAL_OUTPUT_BUFFER, Argument) + sizeof(ACPI_METHOD_ARGUMENT_V1) + outputArgumentBufferSize; 220 | 221 | WDF_OBJECT_ATTRIBUTES attributes; 222 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 223 | attributes.ParentObject = FxDevice; 224 | status = WdfMemoryCreate(&attributes, 225 | NonPagedPoolNx, 226 | 0, 227 | outputBufferSize, 228 | &outputMemory, 229 | &outputBuffer); 230 | if (!NT_SUCCESS(status)) { 231 | goto Exit; 232 | } 233 | 234 | WDF_MEMORY_DESCRIPTOR inputMemDesc; 235 | WDF_MEMORY_DESCRIPTOR outputMemDesc; 236 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&inputMemDesc, inputBuffer, (ULONG)inputBufferLen); 237 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE(&outputMemDesc, outputMemory, NULL); 238 | 239 | status = WdfIoTargetSendInternalIoctlSynchronously( 240 | WdfDeviceGetIoTarget(FxDevice), 241 | NULL, 242 | IOCTL_ACPI_GET_DEVICE_SPECIFIC_DATA, 243 | &inputMemDesc, 244 | &outputMemDesc, 245 | NULL, 246 | NULL 247 | ); 248 | if (!NT_SUCCESS(status)) { 249 | Max98390Print( 250 | DEBUG_LEVEL_ERROR, 251 | DBG_IOCTL, 252 | "Error getting device data - 0x%x\n", 253 | status); 254 | goto Exit; 255 | } 256 | 257 | if (outputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE_V1 && 258 | outputBuffer->Count < 1 && 259 | outputBuffer->Argument->Type != ACPI_METHOD_ARGUMENT_INTEGER && 260 | outputBuffer->Argument->DataLength < 1) { 261 | status = STATUS_ACPI_INVALID_ARGUMENT; 262 | goto Exit; 263 | } 264 | 265 | if (property) { 266 | *property = outputBuffer->Argument->Data[0] & 0xF; 267 | } 268 | 269 | Exit: 270 | if (inputBuffer) { 271 | ExFreePoolWithTag(inputBuffer, MAX98390_POOL_TAG); 272 | } 273 | if (outputMemory != WDF_NO_HANDLE) { 274 | WdfObjectDelete(outputMemory); 275 | } 276 | return status; 277 | } 278 | 279 | #define MAX_DEVICE_REG_VAL_LENGTH 0x100 280 | NTSTATUS GetSmbiosName(WCHAR systemProductName[MAX_DEVICE_REG_VAL_LENGTH]) { 281 | NTSTATUS status = STATUS_UNSUCCESSFUL; 282 | HANDLE parentKey = NULL; 283 | UNICODE_STRING ParentKeyName; 284 | OBJECT_ATTRIBUTES ObjectAttributes; 285 | RtlInitUnicodeString(&ParentKeyName, L"\\Registry\\Machine\\Hardware\\DESCRIPTION\\System\\BIOS"); 286 | 287 | InitializeObjectAttributes(&ObjectAttributes, 288 | &ParentKeyName, 289 | OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 290 | NULL, // handle 291 | NULL); 292 | 293 | status = ZwOpenKey(&parentKey, KEY_READ, &ObjectAttributes); 294 | if (!NT_SUCCESS(status)) { 295 | return status; 296 | } 297 | 298 | ULONG ResultLength; 299 | PKEY_VALUE_PARTIAL_INFORMATION KeyValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolZero(NonPagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + MAX_DEVICE_REG_VAL_LENGTH, MAX98390_POOL_TAG); 300 | if (!KeyValueInfo) { 301 | status = STATUS_NO_MEMORY; 302 | goto exit; 303 | } 304 | 305 | UNICODE_STRING SystemProductNameValue; 306 | RtlInitUnicodeString(&SystemProductNameValue, L"SystemProductName"); 307 | status = ZwQueryValueKey(parentKey, &SystemProductNameValue, KeyValuePartialInformation, KeyValueInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + MAX_DEVICE_REG_VAL_LENGTH, &ResultLength); 308 | if (!NT_SUCCESS(status)) { 309 | goto exit; 310 | } 311 | 312 | if (KeyValueInfo->DataLength > MAX_DEVICE_REG_VAL_LENGTH) { 313 | status = STATUS_BUFFER_OVERFLOW; 314 | goto exit; 315 | } 316 | 317 | RtlZeroMemory(systemProductName, sizeof(systemProductName)); 318 | RtlCopyMemory(systemProductName, &KeyValueInfo->Data, KeyValueInfo->DataLength); 319 | 320 | exit: 321 | if (KeyValueInfo) { 322 | ExFreePoolWithTag(KeyValueInfo, MAX98390_POOL_TAG); 323 | } 324 | return status; 325 | } 326 | 327 | void max98390_init_regs(PMAX98390_CONTEXT pDevice, UINT8 vmon_slot_no, UINT8 imon_slot_no) { 328 | max98390_reg_write(pDevice, MAX98390_CLK_MON, 0x6f); 329 | max98390_reg_write(pDevice, MAX98390_DAT_MON, 0x00); 330 | max98390_reg_write(pDevice, MAX98390_PWR_GATE_CTL, 0x00); 331 | max98390_reg_write(pDevice, MAX98390_PCM_RX_EN_A, 0x03); 332 | max98390_reg_write(pDevice, MAX98390_ENV_TRACK_VOUT_HEADROOM, 0x0e); 333 | max98390_reg_write(pDevice, MAX98390_BOOST_BYPASS1, 0x46); 334 | max98390_reg_write(pDevice, MAX98390_FET_SCALING3, 0x03); 335 | 336 | /* voltage, current slot configuration */ 337 | max98390_reg_write(pDevice, MAX98390_PCM_CH_SRC_2, 338 | (imon_slot_no << 4 | 339 | vmon_slot_no) & 0xFF); 340 | 341 | if (vmon_slot_no < 8) { 342 | max98390_reg_update(pDevice, 343 | MAX98390_PCM_TX_HIZ_CTRL_A, 344 | 1 << vmon_slot_no, 0); 345 | max98390_reg_update(pDevice, 346 | MAX98390_PCM_TX_EN_A, 347 | 1 << vmon_slot_no, 348 | 1 << vmon_slot_no); 349 | } 350 | else { 351 | max98390_reg_update(pDevice, 352 | MAX98390_PCM_TX_HIZ_CTRL_B, 353 | 1 << (vmon_slot_no - 8), 0); 354 | max98390_reg_update(pDevice, 355 | MAX98390_PCM_TX_EN_B, 356 | 1 << (vmon_slot_no - 8), 357 | 1 << (vmon_slot_no - 8)); 358 | } 359 | 360 | if (imon_slot_no < 8) { 361 | max98390_reg_update(pDevice, 362 | MAX98390_PCM_TX_HIZ_CTRL_A, 363 | 1 << imon_slot_no, 0); 364 | max98390_reg_update(pDevice, 365 | MAX98390_PCM_TX_EN_A, 366 | 1 << imon_slot_no, 367 | 1 << imon_slot_no); 368 | } 369 | else { 370 | max98390_reg_update(pDevice, 371 | MAX98390_PCM_TX_HIZ_CTRL_B, 372 | 1 << (imon_slot_no - 8), 0); 373 | max98390_reg_update(pDevice, 374 | MAX98390_PCM_TX_EN_B, 375 | 1 << (imon_slot_no - 8), 376 | 1 << (imon_slot_no - 8)); 377 | } 378 | } 379 | 380 | void uploadDSMBin(PMAX98390_CONTEXT pDevice, WCHAR SystemProductName[MAX_DEVICE_REG_VAL_LENGTH]) { 381 | NTSTATUS status; 382 | 383 | struct firmware *fw = NULL; 384 | status = STATUS_NOT_FOUND; 385 | if (wcscmp(SystemProductName, L"Nightfury") == 0) { 386 | status = request_firmware(&fw, L"\\SystemRoot\\system32\\DRIVERS\\dsm_param_Google_Nightfury.bin"); 387 | } 388 | if (!NT_SUCCESS(status) || !fw) { 389 | DbgPrint("Warning: No DSM found for MAX98390!!!\n"); 390 | return; 391 | } 392 | 393 | char* dsm_param = (char*)fw->data; 394 | UINT16 param_size; 395 | UINT16 param_start_addr; 396 | param_start_addr = (dsm_param[0] & 0xff) | (dsm_param[1] & 0xff) << 8; 397 | param_size = (dsm_param[2] & 0xff) | (dsm_param[3] & 0xff) << 8; 398 | 399 | if (param_size > MAX98390_DSM_PARAM_MAX_SIZE || 400 | param_start_addr < MAX98390_IRQ_CTRL || 401 | fw->size < param_size + MAX98390_DSM_PAYLOAD_OFFSET) { 402 | DbgPrint("DSM param fw is invalid.\n"); 403 | goto dealloc; 404 | } 405 | 406 | 407 | max98390_reg_write(pDevice, MAX98390_R203A_AMP_EN, 0x80); 408 | dsm_param += MAX98390_DSM_PAYLOAD_OFFSET; 409 | 410 | for (UINT16 i = 0; i < param_size; i++) { 411 | max98390_reg_write(pDevice, param_start_addr + i, dsm_param[i]); 412 | } 413 | 414 | max98390_reg_write(pDevice, MAX98390_R23E1_DSP_GLOBAL_EN, 0x01); 415 | 416 | dealloc: 417 | free_firmware(fw); 418 | } 419 | 420 | NTSTATUS 421 | StartCodec( 422 | PMAX98390_CONTEXT pDevice 423 | ) { 424 | NTSTATUS status = STATUS_SUCCESS; 425 | if (!pDevice->SetUID) { 426 | status = STATUS_INVALID_DEVICE_STATE; 427 | return status; 428 | } 429 | 430 | UINT8 reg; 431 | status = max98390_reg_read(pDevice, MAX98390_R24FF_REV_ID, ®); 432 | if (!NT_SUCCESS(status)) { 433 | return status; 434 | } 435 | 436 | UINT16 vmon_slot_no, imon_slot_no; 437 | status = GetIntegerProperty(pDevice->FxDevice, "maxim,vmon-slot-no", &vmon_slot_no); 438 | if (!NT_SUCCESS(status)) { 439 | return status; 440 | } 441 | 442 | status = GetIntegerProperty(pDevice->FxDevice, "maxim,imon-slot-no", &imon_slot_no); 443 | if (!NT_SUCCESS(status)) { 444 | return status; 445 | } 446 | 447 | vmon_slot_no = vmon_slot_no & 0xF; 448 | imon_slot_no = imon_slot_no & 0xF; 449 | 450 | UINT16 ref_rdc_value = 0, ambient_temp_value = 0; 451 | GetIntegerProperty(pDevice->FxDevice, "maxim,r0_calib", &ref_rdc_value); 452 | GetIntegerProperty(pDevice->FxDevice, "maxim,temperature_calib", &ambient_temp_value); 453 | 454 | status = max98390_reg_write(pDevice, MAX98390_SOFTWARE_RESET, 0x01); 455 | if (!NT_SUCCESS(status)) { 456 | return status; 457 | } 458 | 459 | LARGE_INTEGER Interval; 460 | Interval.QuadPart = -10 * 1000 * 20; 461 | KeDelayExecutionThread(KernelMode, false, &Interval); 462 | 463 | /* Amp init setting */ 464 | max98390_init_regs(pDevice, vmon_slot_no, imon_slot_no); 465 | 466 | WCHAR SystemProductName[MAX_DEVICE_REG_VAL_LENGTH]; 467 | status = GetSmbiosName(SystemProductName); 468 | if (!NT_SUCCESS(status)) { 469 | return status; 470 | } 471 | /* Update dsm bin param */ 472 | uploadDSMBin(pDevice, SystemProductName); 473 | 474 | /* Dsm Setting */ 475 | if (ref_rdc_value) { 476 | max98390_reg_write(pDevice, DSM_TPROT_RECIP_RDC_ROOM_BYTE0, 477 | ref_rdc_value & 0x000000ff); 478 | max98390_reg_write(pDevice, DSM_TPROT_RECIP_RDC_ROOM_BYTE1, 479 | (ref_rdc_value >> 8) & 0x000000ff); 480 | max98390_reg_write(pDevice, DSM_TPROT_RECIP_RDC_ROOM_BYTE2, 481 | (ref_rdc_value >> 16) & 0x000000ff); 482 | } 483 | if (ambient_temp_value) { 484 | max98390_reg_write(pDevice, DSM_TPROT_ROOM_TEMPERATURE_BYTE1, 485 | (ambient_temp_value >> 8) & 0x000000ff); 486 | max98390_reg_write(pDevice, DSM_TPROT_ROOM_TEMPERATURE_BYTE0, 487 | (ambient_temp_value) & 0x000000ff); 488 | } 489 | 490 | max98390_reg_write(pDevice, DSM_VOL_CTRL, 0x8a); 491 | 492 | max98390_reg_write(pDevice, MAX98390_PCM_CH_SRC_1, pDevice->UID % 2); //Set Left or Right according to UID 493 | 494 | if (wcscmp(SystemProductName, L"Nightfury") == 0) { //10th gen 495 | max98390_reg_update(pDevice, 496 | MAX98390_BOOST_CTRL3, 497 | 3 << MAX98390_BOOST_CLK_PHASE_CFG_SHIFT, 498 | (pDevice->UID ? 3 : 0) << MAX98390_BOOST_CLK_PHASE_CFG_SHIFT 499 | ); 500 | } 501 | else { //12th gen 502 | 503 | } 504 | 505 | 506 | max98390_reg_update(pDevice, 507 | MAX98390_R203A_AMP_EN, 508 | MAX98390_AMP_EN_MASK, 1); 509 | max98390_reg_write(pDevice, MAX98390_R23FF_GLOBAL_EN, 0x01); 510 | 511 | pDevice->DevicePoweredOn = TRUE; 512 | return status; 513 | } 514 | 515 | NTSTATUS 516 | StopCodec( 517 | PMAX98390_CONTEXT pDevice 518 | ) { 519 | NTSTATUS status; 520 | 521 | status = max98390_reg_write(pDevice, MAX98390_SOFTWARE_RESET, 0x01); 522 | if (!NT_SUCCESS(status)) { 523 | return status; 524 | } 525 | 526 | pDevice->DevicePoweredOn = FALSE; 527 | return status; 528 | } 529 | 530 | VOID 531 | CSAudioRegisterEndpoint( 532 | PMAX98390_CONTEXT pDevice 533 | ) { 534 | CsAudioArg arg; 535 | RtlZeroMemory(&arg, sizeof(CsAudioArg)); 536 | arg.argSz = sizeof(CsAudioArg); 537 | arg.endpointType = CSAudioEndpointTypeSpeaker; 538 | arg.endpointRequest = CSAudioEndpointRegister; 539 | ExNotifyCallback(pDevice->CSAudioAPICallback, &arg, &CsAudioArg2); 540 | } 541 | 542 | VOID 543 | CsAudioCallbackFunction( 544 | IN PMAX98390_CONTEXT pDevice, 545 | CsAudioArg* arg, 546 | PVOID Argument2 547 | ) { 548 | if (!pDevice) { 549 | return; 550 | } 551 | 552 | if (Argument2 == &CsAudioArg2) { 553 | return; 554 | } 555 | 556 | pDevice->CSAudioManaged = TRUE; 557 | 558 | CsAudioArg localArg; 559 | RtlZeroMemory(&localArg, sizeof(CsAudioArg)); 560 | RtlCopyMemory(&localArg, arg, min(arg->argSz, sizeof(CsAudioArg))); 561 | 562 | if (localArg.endpointType == CSAudioEndpointTypeDSP && localArg.endpointRequest == CSAudioEndpointRegister) { 563 | CSAudioRegisterEndpoint(pDevice); 564 | } 565 | else if (localArg.endpointType != CSAudioEndpointTypeSpeaker) { 566 | return; 567 | } 568 | 569 | if (localArg.endpointRequest == CSAudioEndpointStop) { 570 | StopCodec(pDevice); 571 | } 572 | if (localArg.endpointRequest == CSAudioEndpointStart) { 573 | StartCodec(pDevice); 574 | } 575 | } 576 | 577 | NTSTATUS 578 | OnPrepareHardware( 579 | _In_ WDFDEVICE FxDevice, 580 | _In_ WDFCMRESLIST FxResourcesRaw, 581 | _In_ WDFCMRESLIST FxResourcesTranslated 582 | ) 583 | /*++ 584 | 585 | Routine Description: 586 | 587 | This routine caches the SPB resource connection ID. 588 | 589 | Arguments: 590 | 591 | FxDevice - a handle to the framework device object 592 | FxResourcesRaw - list of translated hardware resources that 593 | the PnP manager has assigned to the device 594 | FxResourcesTranslated - list of raw hardware resources that 595 | the PnP manager has assigned to the device 596 | 597 | Return Value: 598 | 599 | Status 600 | 601 | --*/ 602 | { 603 | PMAX98390_CONTEXT pDevice = GetDeviceContext(FxDevice); 604 | BOOLEAN fSpbResourceFound = FALSE; 605 | NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES; 606 | 607 | UNREFERENCED_PARAMETER(FxResourcesRaw); 608 | 609 | // 610 | // Parse the peripheral's resources. 611 | // 612 | 613 | ULONG resourceCount = WdfCmResourceListGetCount(FxResourcesTranslated); 614 | 615 | for (ULONG i = 0; i < resourceCount; i++) 616 | { 617 | PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor; 618 | UCHAR Class; 619 | UCHAR Type; 620 | 621 | pDescriptor = WdfCmResourceListGetDescriptor( 622 | FxResourcesTranslated, i); 623 | 624 | switch (pDescriptor->Type) 625 | { 626 | case CmResourceTypeConnection: 627 | // 628 | // Look for I2C or SPI resource and save connection ID. 629 | // 630 | Class = pDescriptor->u.Connection.Class; 631 | Type = pDescriptor->u.Connection.Type; 632 | if (Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL && 633 | Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C) 634 | { 635 | if (fSpbResourceFound == FALSE) 636 | { 637 | status = STATUS_SUCCESS; 638 | pDevice->I2CContext.I2cResHubId.LowPart = pDescriptor->u.Connection.IdLowPart; 639 | pDevice->I2CContext.I2cResHubId.HighPart = pDescriptor->u.Connection.IdHighPart; 640 | fSpbResourceFound = TRUE; 641 | } 642 | else 643 | { 644 | } 645 | } 646 | break; 647 | default: 648 | // 649 | // Ignoring all other resource types. 650 | // 651 | break; 652 | } 653 | } 654 | 655 | // 656 | // An SPB resource is required. 657 | // 658 | 659 | if (fSpbResourceFound == FALSE) 660 | { 661 | status = STATUS_NOT_FOUND; 662 | } 663 | 664 | status = SpbTargetInitialize(FxDevice, &pDevice->I2CContext); 665 | 666 | if (!NT_SUCCESS(status)) 667 | { 668 | return status; 669 | } 670 | 671 | status = GetDeviceUID(FxDevice, &pDevice->UID); 672 | if (!NT_SUCCESS(status)) { 673 | return status; 674 | } 675 | pDevice->SetUID = TRUE; 676 | 677 | return status; 678 | } 679 | 680 | NTSTATUS 681 | OnReleaseHardware( 682 | _In_ WDFDEVICE FxDevice, 683 | _In_ WDFCMRESLIST FxResourcesTranslated 684 | ) 685 | /*++ 686 | 687 | Routine Description: 688 | 689 | Arguments: 690 | 691 | FxDevice - a handle to the framework device object 692 | FxResourcesTranslated - list of raw hardware resources that 693 | the PnP manager has assigned to the device 694 | 695 | Return Value: 696 | 697 | Status 698 | 699 | --*/ 700 | { 701 | PMAX98390_CONTEXT pDevice = GetDeviceContext(FxDevice); 702 | NTSTATUS status = STATUS_SUCCESS; 703 | 704 | UNREFERENCED_PARAMETER(FxResourcesTranslated); 705 | 706 | SpbTargetDeinitialize(FxDevice, &pDevice->I2CContext); 707 | 708 | if (pDevice->CSAudioAPICallbackObj) { 709 | ExUnregisterCallback(pDevice->CSAudioAPICallbackObj); 710 | pDevice->CSAudioAPICallbackObj = NULL; 711 | } 712 | 713 | if (pDevice->CSAudioAPICallback) { 714 | ObfDereferenceObject(pDevice->CSAudioAPICallback); 715 | pDevice->CSAudioAPICallback = NULL; 716 | } 717 | 718 | return status; 719 | } 720 | 721 | NTSTATUS 722 | OnSelfManagedIoInit( 723 | _In_ 724 | WDFDEVICE FxDevice 725 | ) { 726 | PMAX98390_CONTEXT pDevice = GetDeviceContext(FxDevice); 727 | NTSTATUS status = STATUS_SUCCESS; 728 | 729 | if (!pDevice->SetUID) { 730 | status = STATUS_INVALID_DEVICE_STATE; 731 | return status; 732 | } 733 | 734 | // CS Audio Callback 735 | 736 | UNICODE_STRING CSAudioCallbackAPI; 737 | RtlInitUnicodeString(&CSAudioCallbackAPI, L"\\CallBack\\CsAudioCallbackAPI"); 738 | 739 | 740 | OBJECT_ATTRIBUTES attributes; 741 | InitializeObjectAttributes(&attributes, 742 | &CSAudioCallbackAPI, 743 | OBJ_KERNEL_HANDLE | OBJ_OPENIF | OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, 744 | NULL, 745 | NULL 746 | ); 747 | status = ExCreateCallback(&pDevice->CSAudioAPICallback, &attributes, TRUE, TRUE); 748 | if (!NT_SUCCESS(status)) { 749 | return status; 750 | } 751 | 752 | pDevice->CSAudioAPICallbackObj = ExRegisterCallback(pDevice->CSAudioAPICallback, 753 | CsAudioCallbackFunction, 754 | pDevice 755 | ); 756 | if (!pDevice->CSAudioAPICallbackObj) { 757 | 758 | return STATUS_NO_CALLBACK_ACTIVE; 759 | } 760 | 761 | CSAudioRegisterEndpoint(pDevice); 762 | 763 | return status; 764 | } 765 | 766 | NTSTATUS 767 | OnD0Entry( 768 | _In_ WDFDEVICE FxDevice, 769 | _In_ WDF_POWER_DEVICE_STATE FxPreviousState 770 | ) 771 | /*++ 772 | 773 | Routine Description: 774 | 775 | This routine allocates objects needed by the driver. 776 | 777 | Arguments: 778 | 779 | FxDevice - a handle to the framework device object 780 | FxPreviousState - previous power state 781 | 782 | Return Value: 783 | 784 | Status 785 | 786 | --*/ 787 | { 788 | UNREFERENCED_PARAMETER(FxPreviousState); 789 | 790 | PMAX98390_CONTEXT pDevice = GetDeviceContext(FxDevice); 791 | NTSTATUS status = STATUS_SUCCESS; 792 | 793 | if (!pDevice->CSAudioManaged) { 794 | status = StartCodec(pDevice); 795 | } 796 | 797 | return status; 798 | } 799 | 800 | NTSTATUS 801 | OnD0Exit( 802 | _In_ WDFDEVICE FxDevice, 803 | _In_ WDF_POWER_DEVICE_STATE FxPreviousState 804 | ) 805 | /*++ 806 | 807 | Routine Description: 808 | 809 | This routine destroys objects needed by the driver. 810 | 811 | Arguments: 812 | 813 | FxDevice - a handle to the framework device object 814 | FxPreviousState - previous power state 815 | 816 | Return Value: 817 | 818 | Status 819 | 820 | --*/ 821 | { 822 | UNREFERENCED_PARAMETER(FxPreviousState); 823 | 824 | PMAX98390_CONTEXT pDevice = GetDeviceContext(FxDevice); 825 | NTSTATUS status = STATUS_SUCCESS; 826 | 827 | status = StopCodec(pDevice); 828 | 829 | return STATUS_SUCCESS; 830 | } 831 | 832 | NTSTATUS 833 | Max98390EvtDeviceAdd( 834 | IN WDFDRIVER Driver, 835 | IN PWDFDEVICE_INIT DeviceInit 836 | ) 837 | { 838 | NTSTATUS status = STATUS_SUCCESS; 839 | WDF_IO_QUEUE_CONFIG queueConfig; 840 | WDF_OBJECT_ATTRIBUTES attributes; 841 | WDFDEVICE device; 842 | WDFQUEUE queue; 843 | PMAX98390_CONTEXT devContext; 844 | 845 | UNREFERENCED_PARAMETER(Driver); 846 | 847 | PAGED_CODE(); 848 | 849 | Max98390Print(DEBUG_LEVEL_INFO, DBG_PNP, 850 | "Max98390EvtDeviceAdd called\n"); 851 | 852 | { 853 | WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks; 854 | WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks); 855 | 856 | pnpCallbacks.EvtDevicePrepareHardware = OnPrepareHardware; 857 | pnpCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware; 858 | pnpCallbacks.EvtDeviceSelfManagedIoInit = OnSelfManagedIoInit; 859 | pnpCallbacks.EvtDeviceD0Entry = OnD0Entry; 860 | pnpCallbacks.EvtDeviceD0Exit = OnD0Exit; 861 | 862 | WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks); 863 | } 864 | 865 | // 866 | // Setup the device context 867 | // 868 | 869 | WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, MAX98390_CONTEXT); 870 | 871 | // 872 | // Create a framework device object.This call will in turn create 873 | // a WDM device object, attach to the lower stack, and set the 874 | // appropriate flags and attributes. 875 | // 876 | 877 | status = WdfDeviceCreate(&DeviceInit, &attributes, &device); 878 | 879 | if (!NT_SUCCESS(status)) 880 | { 881 | Max98390Print(DEBUG_LEVEL_ERROR, DBG_PNP, 882 | "WdfDeviceCreate failed with status code 0x%x\n", status); 883 | 884 | return status; 885 | } 886 | 887 | { 888 | WDF_DEVICE_STATE deviceState; 889 | WDF_DEVICE_STATE_INIT(&deviceState); 890 | 891 | deviceState.NotDisableable = WdfFalse; 892 | WdfDeviceSetDeviceState(device, &deviceState); 893 | } 894 | 895 | WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); 896 | 897 | queueConfig.EvtIoInternalDeviceControl = Max98390EvtInternalDeviceControl; 898 | 899 | status = WdfIoQueueCreate(device, 900 | &queueConfig, 901 | WDF_NO_OBJECT_ATTRIBUTES, 902 | &queue 903 | ); 904 | 905 | if (!NT_SUCCESS(status)) 906 | { 907 | Max98390Print(DEBUG_LEVEL_ERROR, DBG_PNP, 908 | "WdfIoQueueCreate failed 0x%x\n", status); 909 | 910 | return status; 911 | } 912 | 913 | // 914 | // Create manual I/O queue to take care of hid report read requests 915 | // 916 | 917 | devContext = GetDeviceContext(device); 918 | 919 | devContext->FxDevice = device; 920 | devContext->CSAudioManaged = FALSE; 921 | 922 | WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); 923 | 924 | queueConfig.PowerManaged = WdfFalse; 925 | 926 | status = WdfIoQueueCreate(device, 927 | &queueConfig, 928 | WDF_NO_OBJECT_ATTRIBUTES, 929 | &devContext->ReportQueue 930 | ); 931 | 932 | if (!NT_SUCCESS(status)) 933 | { 934 | Max98390Print(DEBUG_LEVEL_ERROR, DBG_PNP, 935 | "WdfIoQueueCreate failed 0x%x\n", status); 936 | 937 | return status; 938 | } 939 | 940 | return status; 941 | } 942 | 943 | VOID 944 | Max98390EvtInternalDeviceControl( 945 | IN WDFQUEUE Queue, 946 | IN WDFREQUEST Request, 947 | IN size_t OutputBufferLength, 948 | IN size_t InputBufferLength, 949 | IN ULONG IoControlCode 950 | ) 951 | { 952 | NTSTATUS status = STATUS_SUCCESS; 953 | WDFDEVICE device; 954 | PMAX98390_CONTEXT devContext; 955 | 956 | UNREFERENCED_PARAMETER(OutputBufferLength); 957 | UNREFERENCED_PARAMETER(InputBufferLength); 958 | 959 | device = WdfIoQueueGetDevice(Queue); 960 | devContext = GetDeviceContext(device); 961 | 962 | switch (IoControlCode) 963 | { 964 | default: 965 | status = STATUS_NOT_SUPPORTED; 966 | break; 967 | } 968 | 969 | WdfRequestComplete(Request, status); 970 | 971 | return; 972 | } --------------------------------------------------------------------------------