├── rt5663 ├── stdint.h ├── resource.h ├── rl6231.h ├── hidcommon.h ├── rt5663.rc ├── trace.h ├── spb.h ├── rt5663.inf ├── rt5663.h ├── rl6231.c ├── rt5663.vcxproj ├── spb.c ├── registers.h └── rt5663.c ├── README.md ├── rt5663.sln ├── LICENSE.txt ├── .gitignore └── rt5663 Package └── rt5663 Package.vcxproj /rt5663/stdint.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define BIT(nr) (1UL << (nr)) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rt5663 2 | Realtek ALC 5663 I2C Codec driver 3 | 4 | Supports: 5 | * Jack Detection 6 | * Headphone output 7 | * Sleep/Wake 8 | 9 | Note: 10 | * Intel SST proprietary drivers do NOT have documented interfaces, so this driver will not work with them. 11 | * Using this driver on chromebooks with this audio chip will require using CoolStar SST Audio or CoolStar SOF Audio 12 | 13 | Tested on Asus Chromebox 3 (Core i7-8650U) -------------------------------------------------------------------------------- /rt5663/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by opengmaxcodec.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /rt5663/rl6231.h: -------------------------------------------------------------------------------- 1 | #ifndef __RL6231_H__ 2 | #define __RL6231_H__ 3 | 4 | #include 5 | 6 | #define RL6231_PLL_INP_MAX 50000000 7 | #define RL6231_PLL_INP_MIN 256000 8 | #define RL6231_PLL_N_MAX 0x1ff 9 | #define RL6231_PLL_K_MAX 0x1f 10 | #define RL6231_PLL_M_MAX 0xf 11 | 12 | struct rl6231_pll_code { 13 | BOOLEAN m_bp; /* Indicates bypass m code or not. */ 14 | BOOLEAN k_bp; /* Indicates bypass k code or not. */ 15 | INT m_code; 16 | INT n_code; 17 | INT k_code; 18 | }; 19 | 20 | NTSTATUS rl6231_calc_dmic_clk(int rate, int* clk); 21 | NTSTATUS rl6231_pll_calc(const unsigned int freq_in, 22 | const unsigned int freq_out, struct rl6231_pll_code* pll_code); 23 | NTSTATUS rl6231_get_clk_info(int sclk, int rate); 24 | NTSTATUS rl6231_get_pre_div(unsigned int regval, int sft); 25 | 26 | #endif /* __RL6231_H__ */ -------------------------------------------------------------------------------- /rt5663/hidcommon.h: -------------------------------------------------------------------------------- 1 | #if !defined(_RT5663_COMMON_H_) 2 | #define _RT5663_COMMON_H_ 3 | 4 | // 5 | //These are the device attributes returned by vmulti in response 6 | // to IOCTL_HID_GET_DEVICE_ATTRIBUTES. 7 | // 8 | 9 | #define RT5663_PID 0x5663 10 | #define RT5663_VID 0x10EC 11 | #define RT5663_VERSION 0x0001 12 | 13 | // 14 | // These are the report ids 15 | // 16 | 17 | #define REPORTID_MEDIA 0x01 18 | #define REPORTID_SPECKEYS 0x02 19 | 20 | #pragma pack(1) 21 | typedef struct _RT5663_MEDIA_REPORT 22 | { 23 | 24 | BYTE ReportID; 25 | 26 | BYTE ControlCode; 27 | 28 | } Rt5663MediaReport; 29 | #pragma pack() 30 | 31 | #define CONTROL_CODE_JACK_TYPE 0x1 32 | 33 | #pragma pack(1) 34 | typedef struct _CSAUDIO_SPECKEY_REPORT 35 | { 36 | 37 | BYTE ReportID; 38 | 39 | BYTE ControlCode; 40 | 41 | BYTE ControlValue; 42 | 43 | } CsAudioSpecialKeyReport; 44 | 45 | #pragma pack() 46 | 47 | #pragma pack(1) 48 | typedef struct _CSAUDIO_SPECKEYREQ_REPORT 49 | { 50 | 51 | BYTE ReportID; 52 | 53 | BYTE AnyCode; 54 | 55 | } CsAudioSpecialKeyRequestReport; 56 | #pragma pack() 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /rt5663/rt5663.rc: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (c) Microsoft Corporation All Rights Reserved 4 | 5 | Module Name: 6 | 7 | rt5663.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 "Realtek ALC5663 I2S Audio" 18 | #define VER_INTERNALNAME_STR "rt5663.sys" 19 | #define VER_ORIGINALFILENAME_STR "rt5663.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 "Realtek ALC5663 I2S Audio" 40 | 41 | #include "common.ver" -------------------------------------------------------------------------------- /rt5663/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 | -------------------------------------------------------------------------------- /rt5663/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 | ); 69 | 70 | typedef struct _SPB_BURST_INFO { 71 | PVOID Data; 72 | ULONG Length; 73 | } SPB_BURST_INFO; 74 | 75 | NTSTATUS 76 | SpbBurstWriteDataSynchronously( 77 | IN SPB_CONTEXT* SpbContext, 78 | IN SPB_BURST_INFO* Data, 79 | IN ULONG Count 80 | ); -------------------------------------------------------------------------------- /rt5663/rt5663.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 RT5663 Jack Detect 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 = 12/16/2021,1.0.0 20 | CatalogFile = rt5663.cat 21 | PnpLockdown=1 22 | 23 | [DestinationDirs] 24 | DefaultDestDir = 12 25 | 26 | ; ================= Class section ===================== 27 | 28 | [SourceDisksNames] 29 | 1 = %DiskId1%,,,"" 30 | 31 | [SourceDisksFiles] 32 | rt5663.sys = 1,, 33 | 34 | ;***************************************** 35 | ; rt5663 Install Section 36 | ;***************************************** 37 | 38 | [Manufacturer] 39 | %StdMfg%=Standard,NTAMD64 40 | 41 | ; Decorated model section take precedence over undecorated 42 | ; ones on XP and later. 43 | [Standard.NTAMD64] 44 | %rt5663.DeviceDesc%=Rt5663_Device, ACPI\10EC5663 45 | 46 | [Rt5663_Device.NT] 47 | CopyFiles=Drivers_Dir 48 | 49 | [Rt5663_Device.NT.HW] 50 | AddReg=Rt5663_AddReg 51 | 52 | [Drivers_Dir] 53 | rt5663.sys 54 | 55 | [Rt5663_AddReg] 56 | ; Set to 1 to connect the first interrupt resource found, 0 to leave disconnected 57 | HKR,Settings,"ConnectInterrupt",0x00010001,0 58 | HKR,,"UpperFilters",0x00010000,"mshidkmdf" 59 | 60 | ;-------------- Service installation 61 | [Rt5663_Device.NT.Services] 62 | AddService = rt5663,%SPSVCINST_ASSOCSERVICE%, Rt5663_Service_Inst 63 | 64 | ; -------------- rt5663 driver install sections 65 | [Rt5663_Service_Inst] 66 | DisplayName = %rt5663.SVCDESC% 67 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 68 | StartType = 3 ; SERVICE_DEMAND_START 69 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 70 | ServiceBinary = %12%\rt5663.sys 71 | LoadOrderGroup = Base 72 | 73 | [Strings] 74 | SPSVCINST_ASSOCSERVICE= 0x00000002 75 | StdMfg = "CoolStar" 76 | DiskId1 = "ALC5663 Installation Disk #1" 77 | rt5663.DeviceDesc = "Realtek ALC5663 I2S Audio" 78 | rt5663.SVCDESC = "ALC5663 Service" 79 | -------------------------------------------------------------------------------- /rt5663.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31829.152 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rt5663", "rt5663\rt5663.vcxproj", "{36580C07-EDC3-4C2B-B45F-6AB017E01A5D}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rt5663 Package", "rt5663 Package\rt5663 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 = {1EBAC2E3-504A-4D97-960C-BBD6F6AFBEC6} 51 | EndGlobalSection 52 | EndGlobal 53 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2022 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. -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /rt5663 Package/rt5663 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 | rt5663_Package 29 | $(LatestTargetPlatformVersion) 30 | 31 | 32 | 33 | WindowsV6.3 34 | true 35 | WindowsKernelModeDriver10.0 36 | Utility 37 | Package 38 | true 39 | 40 | 41 | WindowsV6.3 42 | false 43 | WindowsKernelModeDriver10.0 44 | Utility 45 | Package 46 | true 47 | 48 | 49 | WindowsV6.3 50 | true 51 | WindowsKernelModeDriver10.0 52 | Utility 53 | Package 54 | true 55 | 56 | 57 | WindowsV6.3 58 | false 59 | WindowsKernelModeDriver10.0 60 | Utility 61 | Package 62 | true 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | DbgengKernelDebugger 74 | False 75 | True 76 | 77 | 78 | 79 | False 80 | False 81 | True 82 | 83 | 133563 84 | 85 | 86 | DbgengKernelDebugger 87 | False 88 | True 89 | 90 | 91 | 92 | False 93 | False 94 | True 95 | 96 | 133563 97 | 98 | 99 | DbgengKernelDebugger 100 | False 101 | True 102 | 103 | 104 | 105 | False 106 | False 107 | True 108 | 109 | 133563 110 | 111 | 112 | DbgengKernelDebugger 113 | False 114 | True 115 | 116 | 117 | 118 | False 119 | False 120 | True 121 | 122 | 133563 123 | 124 | 125 | 126 | SHA256 127 | 128 | 129 | 130 | 131 | SHA256 132 | 133 | 134 | 135 | 136 | SHA256 137 | 138 | 139 | 140 | 141 | SHA256 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | {36580c07-edc3-4c2b-b45f-6ab017e01a5d} 150 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /rt5663/rt5663.h: -------------------------------------------------------------------------------- 1 | #if !defined(_RT5663_H_) 2 | #define _RT5663_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 | #pragma warning(disable:4201) // suppress nameless struct/union warning 16 | #pragma warning(disable:4214) // suppress bit field types other than int warning 17 | #include 18 | 19 | #include "hidcommon.h" 20 | #include "spb.h" 21 | #include 22 | 23 | #define true 1 24 | #define false 0 25 | 26 | enum snd_jack_types { 27 | SND_JACK_HEADPHONE = 0x0001, 28 | SND_JACK_MICROPHONE = 0x0002, 29 | SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE, 30 | }; 31 | 32 | enum snd_bias_level { 33 | SND_BIAS_OFF = 0, 34 | SND_BIAS_STANDBY = 1, 35 | SND_BIAS_PREPARE = 2, 36 | SND_BIAS_ON = 3, 37 | }; 38 | 39 | #define SND_DAPM_PRE_PMU 0x1 /* before widget power up */ 40 | #define SND_DAPM_POST_PMU 0x2 /* after widget power up */ 41 | #define SND_DAPM_PRE_PMD 0x4 /* before widget power down */ 42 | #define SND_DAPM_POST_PMD 0x8 /* after widget power down */ 43 | #define SND_DAPM_PRE_REG 0x10 /* before audio path setup */ 44 | #define SND_DAPM_POST_REG 0x20 /* after audio path setup */ 45 | #define SND_DAPM_WILL_PMU 0x40 /* called at start of sequence */ 46 | #define SND_DAPM_WILL_PMD 0x80 /* called at start of sequence */ 47 | 48 | 49 | struct reg { 50 | UINT16 reg; 51 | UINT16 val; 52 | }; 53 | 54 | // 55 | // String definitions 56 | // 57 | 58 | #define DRIVERNAME "rt5663.sys: " 59 | 60 | #define RT5663_POOL_TAG (ULONG) '856R' 61 | 62 | typedef UCHAR HID_REPORT_DESCRIPTOR, *PHID_REPORT_DESCRIPTOR; 63 | 64 | #ifdef DESCRIPTOR_DEF 65 | HID_REPORT_DESCRIPTOR DefaultReportDescriptor[] = { 66 | // 67 | // Consumer Control starts here 68 | // 69 | 0x05, 0x0C, /* Usage Page (Consumer Devices) */ 70 | 0x09, 0x01, /* Usage (Consumer Control) */ 71 | 0xA1, 0x01, /* Collection (Application) */ 72 | 0x85, REPORTID_MEDIA, /* Report ID=1 */ 73 | 0x05, 0x0C, /* Usage Page (Consumer Devices) */ 74 | 0x15, 0x00, /* Logical Minimum (0) */ 75 | 0x25, 0x01, /* Logical Maximum (1) */ 76 | 0x75, 0x01, /* Report Size (1) */ 77 | 0x95, 0x04, /* Report Count (4) */ 78 | 0x09, 0xCD, /* Usage (Play / Pause) */ 79 | 0x09, 0xCF, /* Usage (Voice Command) */ 80 | 0x09, 0xE9, /* Usage (Volume Up) */ 81 | 0x09, 0xEA, /* Usage (Volume Down) */ 82 | 0x81, 0x02, /* Input (Data, Variable, Absolute) */ 83 | 0x95, 0x04, /* Report Count (4) */ 84 | 0x81, 0x01, /* Input (Constant) */ 85 | 0xC0, /* End Collection */ 86 | 87 | 0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined Page 1) 88 | 0x09, 0x04, // USAGE (Vendor Usage 4) 89 | 0xa1, 0x01, // COLLECTION (Application) 90 | 0x85, REPORTID_SPECKEYS, // REPORT_ID (Special Keys) 91 | 0x15, 0x00, // LOGICAL_MINIMUM (0) 92 | 0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (256) 93 | 0x75, 0x08, // REPORT_SIZE (8) - bits 94 | 0x95, 0x01, // REPORT_COUNT (1) - Bytes 95 | 0x09, 0x02, // USAGE (Vendor Usage 1) 96 | 0x81, 0x02, // INPUT (Data,Var,Abs) 97 | 0x09, 0x03, // USAGE (Vendor Usage 2) 98 | 0x81, 0x02, // INPUT (Data,Var,Abs) 99 | 0x09, 0x02, // USAGE (Vendor Usage 1) 100 | 0x91, 0x02, // OUTPUT (Data,Var,Abs) 101 | 0xc0, // END_COLLECTION 102 | }; 103 | 104 | 105 | // 106 | // This is the default HID descriptor returned by the mini driver 107 | // in response to IOCTL_HID_GET_DEVICE_DESCRIPTOR. The size 108 | // of report descriptor is currently the size of DefaultReportDescriptor. 109 | // 110 | 111 | CONST HID_DESCRIPTOR DefaultHidDescriptor = { 112 | 0x09, // length of HID descriptor 113 | 0x21, // descriptor type == HID 0x21 114 | 0x0100, // hid spec release 115 | 0x00, // country code == Not Specified 116 | 0x01, // number of HID class descriptors 117 | { 0x22, // descriptor type 118 | sizeof(DefaultReportDescriptor) } // total length of report descriptor 119 | }; 120 | #endif 121 | 122 | typedef struct _RTEK_CONTEXT 123 | { 124 | 125 | WDFDEVICE FxDevice; 126 | 127 | WDFQUEUE ReportQueue; 128 | 129 | SPB_CONTEXT I2CContext; 130 | 131 | WDFINTERRUPT Interrupt; 132 | 133 | BOOLEAN ConnectInterrupt; 134 | 135 | INT JackType; 136 | 137 | UINT8 CodecVer; 138 | 139 | } RTEK_CONTEXT, *PRTEK_CONTEXT; 140 | 141 | WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(RTEK_CONTEXT, GetDeviceContext) 142 | 143 | // 144 | // Function definitions 145 | // 146 | 147 | DRIVER_INITIALIZE DriverEntry; 148 | 149 | EVT_WDF_DRIVER_UNLOAD Rt5663DriverUnload; 150 | 151 | EVT_WDF_DRIVER_DEVICE_ADD Rt5663EvtDeviceAdd; 152 | 153 | EVT_WDFDEVICE_WDM_IRP_PREPROCESS Rt5663EvtWdmPreprocessMnQueryId; 154 | 155 | EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL Rt5663EvtInternalDeviceControl; 156 | 157 | NTSTATUS 158 | Rt5663GetHidDescriptor( 159 | IN WDFDEVICE Device, 160 | IN WDFREQUEST Request 161 | ); 162 | 163 | NTSTATUS 164 | Rt5663GetReportDescriptor( 165 | IN WDFDEVICE Device, 166 | IN WDFREQUEST Request 167 | ); 168 | 169 | NTSTATUS 170 | Rt5663GetDeviceAttributes( 171 | IN WDFREQUEST Request 172 | ); 173 | 174 | NTSTATUS 175 | Rt5663GetString( 176 | IN WDFREQUEST Request 177 | ); 178 | 179 | NTSTATUS 180 | Rt5663WriteReport( 181 | IN PRTEK_CONTEXT DevContext, 182 | IN WDFREQUEST Request 183 | ); 184 | 185 | NTSTATUS 186 | Rt5663ProcessVendorReport( 187 | IN PRTEK_CONTEXT DevContext, 188 | IN PVOID ReportBuffer, 189 | IN ULONG ReportBufferLen, 190 | OUT size_t* BytesWritten 191 | ); 192 | 193 | NTSTATUS 194 | Rt5663ReadReport( 195 | IN PRTEK_CONTEXT DevContext, 196 | IN WDFREQUEST Request, 197 | OUT BOOLEAN* CompleteRequest 198 | ); 199 | 200 | NTSTATUS 201 | Rt5663SetFeature( 202 | IN PRTEK_CONTEXT DevContext, 203 | IN WDFREQUEST Request, 204 | OUT BOOLEAN* CompleteRequest 205 | ); 206 | 207 | NTSTATUS 208 | Rt5663GetFeature( 209 | IN PRTEK_CONTEXT DevContext, 210 | IN WDFREQUEST Request, 211 | OUT BOOLEAN* CompleteRequest 212 | ); 213 | 214 | PCHAR 215 | DbgHidInternalIoctlString( 216 | IN ULONG IoControlCode 217 | ); 218 | 219 | // 220 | // Helper macros 221 | // 222 | 223 | #define DEBUG_LEVEL_ERROR 1 224 | #define DEBUG_LEVEL_INFO 2 225 | #define DEBUG_LEVEL_VERBOSE 3 226 | 227 | #define DBG_INIT 1 228 | #define DBG_PNP 2 229 | #define DBG_IOCTL 4 230 | 231 | #if 0 232 | #define RtekPrint(dbglevel, dbgcatagory, fmt, ...) { \ 233 | if (Rt5663DebugLevel >= dbglevel && \ 234 | (Rt5663DebugCatagories && dbgcatagory)) \ 235 | { \ 236 | DbgPrint(DRIVERNAME); \ 237 | DbgPrint(fmt, __VA_ARGS__); \ 238 | } \ 239 | } 240 | #else 241 | #define RtekPrint(dbglevel, fmt, ...) { \ 242 | } 243 | #endif 244 | 245 | #endif -------------------------------------------------------------------------------- /rt5663/rl6231.c: -------------------------------------------------------------------------------- 1 | #include "rl6231.h" 2 | 3 | /** 4 | * __ffs - find first bit in word. 5 | * @word: The word to search 6 | * 7 | * Undefined if no bit exists, so code should check against 0 first. 8 | */ 9 | static unsigned long __ffs(unsigned long word) 10 | { 11 | int num = 0; 12 | 13 | #if BITS_PER_LONG == 64 14 | if ((word & 0xffffffff) == 0) { 15 | num += 32; 16 | word >>= 32; 17 | } 18 | #endif 19 | if ((word & 0xffff) == 0) { 20 | num += 16; 21 | word >>= 16; 22 | } 23 | if ((word & 0xff) == 0) { 24 | num += 8; 25 | word >>= 8; 26 | } 27 | if ((word & 0xf) == 0) { 28 | num += 4; 29 | word >>= 4; 30 | } 31 | if ((word & 0x3) == 0) { 32 | num += 2; 33 | word >>= 2; 34 | } 35 | if ((word & 0x1) == 0) 36 | num += 1; 37 | return num; 38 | } 39 | 40 | /** 41 | * gcd - calculate and return the greatest common divisor of 2 unsigned longs 42 | * @a: first value 43 | * @b: second value 44 | */ 45 | unsigned long gcd(unsigned long a, unsigned long b) 46 | { 47 | unsigned long r = a | b; 48 | 49 | if (!a || !b) 50 | return r; 51 | 52 | b >>= __ffs(b); 53 | if (b == 1) 54 | return r & -r; 55 | 56 | for (;;) { 57 | a >>= __ffs(a); 58 | if (a == 1) 59 | return r & -r; 60 | if (a == b) 61 | return a << __ffs(r); 62 | 63 | if (a < b) { 64 | unsigned long temp = a; 65 | a = b; 66 | b = temp; 67 | } 68 | a -= b; 69 | } 70 | } 71 | 72 | /** 73 | * rl6231_get_pre_div - Return the value of pre divider. 74 | * 75 | * @map: map for setting. 76 | * @reg: register. 77 | * @sft: shift. 78 | * 79 | * Return the value of pre divider from given register value. 80 | * Return negative error code for unexpected register value. 81 | */ 82 | NTSTATUS rl6231_get_pre_div(unsigned int regval, int sft) 83 | { 84 | int pd, val; 85 | 86 | val = (regval >> sft) & 0x7; 87 | 88 | switch (val) { 89 | case 0: 90 | case 1: 91 | case 2: 92 | case 3: 93 | pd = val + 1; 94 | break; 95 | case 4: 96 | pd = 6; 97 | break; 98 | case 5: 99 | pd = 8; 100 | break; 101 | case 6: 102 | pd = 12; 103 | break; 104 | case 7: 105 | pd = 16; 106 | break; 107 | default: 108 | pd = -1; 109 | break; 110 | } 111 | 112 | return pd; 113 | } 114 | 115 | /** 116 | * rl6231_calc_dmic_clk - Calculate the frequency divider parameter of dmic. 117 | * 118 | * @rate: base clock rate. 119 | * 120 | * Choose divider parameter that gives the highest possible DMIC frequency in 121 | * 1MHz - 3MHz range. 122 | */ 123 | NTSTATUS rl6231_calc_dmic_clk(int rate, int *clk) 124 | { 125 | static const int div[] = { 2, 3, 4, 6, 8, 12 }; 126 | int i; 127 | 128 | if (rate < 1000000 * div[0]) { 129 | DbgPrint("Base clock rate %d is too low\n", rate); 130 | return STATUS_INVALID_PARAMETER; 131 | } 132 | 133 | for (i = 0; i < sizeof(div) / sizeof(const int); i++) { 134 | if ((div[i] % 3) == 0) 135 | continue; 136 | /* find divider that gives DMIC frequency below 1.536MHz */ 137 | if (1536000 * div[i] >= rate) { 138 | *clk = i; 139 | return STATUS_SUCCESS; 140 | } 141 | } 142 | 143 | DbgPrint("Base clock rate %d is too high\n", rate); 144 | return STATUS_INVALID_PARAMETER; 145 | } 146 | 147 | struct pll_calc_map { 148 | UINT32 pll_in; 149 | UINT32 pll_out; 150 | INT k; 151 | INT n; 152 | INT m; 153 | BOOLEAN m_bp; 154 | BOOLEAN k_bp; 155 | }; 156 | 157 | static const struct pll_calc_map pll_preset_table[] = { 158 | {19200000, 4096000, 23, 14, 1, FALSE, FALSE}, 159 | {19200000, 24576000, 3, 30, 3, FALSE, FALSE}, 160 | {48000000, 3840000, 23, 2, 0, FALSE, FALSE}, 161 | {3840000, 24576000, 3, 30, 0, TRUE, FALSE}, 162 | {3840000, 22579200, 3, 5, 0, TRUE, FALSE}, 163 | }; 164 | 165 | static unsigned int find_best_div(unsigned int in, 166 | unsigned int max, unsigned int div) 167 | { 168 | unsigned int d; 169 | 170 | if (in <= max) 171 | return 1; 172 | 173 | d = in / max; 174 | if (in % max) 175 | d++; 176 | 177 | while (div % d != 0) 178 | d++; 179 | 180 | 181 | return d; 182 | } 183 | 184 | /** 185 | * rl6231_pll_calc - Calcualte PLL M/N/K code. 186 | * @freq_in: external clock provided to codec. 187 | * @freq_out: target clock which codec works on. 188 | * @pll_code: Pointer to structure with M, N, K, m_bypass and k_bypass flag. 189 | * 190 | * Calcualte M/N/K code to configure PLL for codec. 191 | * 192 | * Returns 0 for success or negative error code. 193 | */ 194 | NTSTATUS rl6231_pll_calc(const unsigned int freq_in, 195 | const unsigned int freq_out, struct rl6231_pll_code* pll_code) 196 | { 197 | int max_n = RL6231_PLL_N_MAX, max_m = RL6231_PLL_M_MAX; 198 | int i, k, n_t; 199 | int k_t, min_k, max_k, n = 0, m = 0, m_t = 0; 200 | unsigned int red, pll_out, in_t, out_t, div, div_t; 201 | unsigned int red_t = abs(freq_out - freq_in); 202 | unsigned int f_in, f_out, f_max; 203 | BOOLEAN m_bypass = FALSE, k_bypass = FALSE; 204 | 205 | if (RL6231_PLL_INP_MAX < freq_in || RL6231_PLL_INP_MIN > freq_in) 206 | return STATUS_INVALID_PARAMETER; 207 | 208 | for (i = 0; i < sizeof(pll_preset_table) / sizeof(const struct pll_calc_map); i++) { 209 | if (freq_in == pll_preset_table[i].pll_in && 210 | freq_out == pll_preset_table[i].pll_out) { 211 | k = pll_preset_table[i].k; 212 | m = pll_preset_table[i].m; 213 | n = pll_preset_table[i].n; 214 | m_bypass = pll_preset_table[i].m_bp; 215 | k_bypass = pll_preset_table[i].k_bp; 216 | DbgPrint("Use preset PLL parameter table\n"); 217 | goto code_find; 218 | } 219 | } 220 | 221 | min_k = 80000000 / freq_out - 2; 222 | max_k = 150000000 / freq_out - 2; 223 | if (max_k > RL6231_PLL_K_MAX) 224 | max_k = RL6231_PLL_K_MAX; 225 | if (min_k > RL6231_PLL_K_MAX) 226 | min_k = max_k = RL6231_PLL_K_MAX; 227 | div_t = gcd(freq_in, freq_out); 228 | f_max = 0xffffffff / RL6231_PLL_N_MAX; 229 | div = find_best_div(freq_in, f_max, div_t); 230 | f_in = freq_in / div; 231 | f_out = freq_out / div; 232 | k = min_k; 233 | if (min_k < -1) 234 | min_k = -1; 235 | for (k_t = min_k; k_t <= max_k; k_t++) { 236 | for (n_t = 0; n_t <= max_n; n_t++) { 237 | in_t = f_in * (n_t + 2); 238 | pll_out = f_out * (k_t + 2); 239 | if (in_t == pll_out) { 240 | m_bypass = TRUE; 241 | n = n_t; 242 | k = k_t; 243 | goto code_find; 244 | } 245 | out_t = in_t / (k_t + 2); 246 | red = abs(f_out - out_t); 247 | if (red < red_t) { 248 | m_bypass = TRUE; 249 | n = n_t; 250 | m = 0; 251 | k = k_t; 252 | if (red == 0) 253 | goto code_find; 254 | red_t = red; 255 | } 256 | for (m_t = 0; m_t <= max_m; m_t++) { 257 | out_t = in_t / ((m_t + 2) * (k_t + 2)); 258 | red = abs(f_out - out_t); 259 | if (red < red_t) { 260 | m_bypass = FALSE; 261 | n = n_t; 262 | m = m_t; 263 | k = k_t; 264 | if (red == 0) 265 | goto code_find; 266 | red_t = red; 267 | } 268 | } 269 | } 270 | } 271 | DbgPrint("Only get approximation about PLL\n"); 272 | 273 | code_find: 274 | if (k == -1) { 275 | k_bypass = TRUE; 276 | k = 0; 277 | } 278 | 279 | pll_code->m_bp = m_bypass; 280 | pll_code->k_bp = k_bypass; 281 | pll_code->m_code = m; 282 | pll_code->n_code = n; 283 | pll_code->k_code = k; 284 | return STATUS_SUCCESS; 285 | } 286 | 287 | NTSTATUS rl6231_get_clk_info(int sclk, int rate) 288 | { 289 | int i; 290 | static const int pd[] = { 1, 2, 3, 4, 6, 8, 12, 16 }; 291 | 292 | if (sclk <= 0 || rate <= 0) 293 | return STATUS_INVALID_PARAMETER; 294 | 295 | rate = rate << 8; 296 | for (i = 0; i < sizeof(pd) / sizeof(const int); i++) 297 | if (sclk == rate * pd[i]) 298 | return i; 299 | 300 | return STATUS_INVALID_PARAMETER; 301 | } -------------------------------------------------------------------------------- /rt5663/rt5663.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 | rt5663 29 | 10.0.22000.0 30 | 31 | 32 | 33 | 34 | 35 | true 36 | WindowsKernelModeDriver10.0 37 | Driver 38 | KMDF 39 | 40 | 41 | 42 | 43 | false 44 | WindowsKernelModeDriver10.0 45 | Driver 46 | KMDF 47 | 48 | 49 | 50 | 51 | true 52 | WindowsKernelModeDriver10.0 53 | Driver 54 | KMDF 55 | 56 | 57 | 58 | 59 | false 60 | WindowsKernelModeDriver10.0 61 | Driver 62 | KMDF 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | DbgengKernelDebugger 74 | 75 | 76 | DbgengKernelDebugger 77 | 78 | 79 | DbgengKernelDebugger 80 | 81 | 82 | DbgengKernelDebugger 83 | 84 | 85 | 86 | true 87 | trace.h 88 | true 89 | false 90 | 91 | 92 | 1.0.0 93 | 94 | 95 | SHA256 96 | 97 | 98 | 99 | 100 | true 101 | trace.h 102 | true 103 | false 104 | 105 | 106 | 1.0.0 107 | 108 | 109 | SHA256 110 | 111 | 112 | 113 | 114 | true 115 | trace.h 116 | true 117 | false 118 | 119 | 120 | 1.0.0 121 | 122 | 123 | SHA256 124 | 125 | 126 | 127 | 128 | true 129 | trace.h 130 | true 131 | false 132 | 133 | 134 | 1.0.0 135 | 136 | 137 | SHA256 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 | 163 | 164 | 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /rt5663/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 "rt5663.h" 22 | #include "spb.h" 23 | #include 24 | #include 25 | 26 | static ULONG Rt5663DebugLevel = 100; 27 | static ULONG Rt5663DebugCatagories = 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 | RT5663_POOL_TAG, 70 | length, 71 | &memory, 72 | (PVOID*)&buffer); 73 | 74 | if (!NT_SUCCESS(status)) 75 | { 76 | RtekPrint( 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 | RtekPrint( 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 | SpbWriteDataSynchronously( 131 | IN SPB_CONTEXT* SpbContext, 132 | IN PVOID Data, 133 | IN ULONG Length 134 | ) 135 | /*++ 136 | 137 | Routine Description: 138 | 139 | This routine abstracts creating and sending an I/O 140 | request (I2C Write) to the Spb I/O target and utilizes 141 | a helper routine to do work inside of locked code. 142 | 143 | Arguments: 144 | 145 | SpbContext - Pointer to the current device context 146 | Address - The I2C register address to write to 147 | Data - A buffer to receive the data at at the above address 148 | Length - The amount of data to be read from the above address 149 | 150 | Return Value: 151 | 152 | NTSTATUS Status indicating success or failure 153 | 154 | --*/ 155 | { 156 | NTSTATUS status; 157 | 158 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 159 | 160 | status = SpbDoWriteDataSynchronously( 161 | SpbContext, 162 | Data, 163 | Length); 164 | 165 | WdfWaitLockRelease(SpbContext->SpbLock); 166 | 167 | return status; 168 | } 169 | 170 | NTSTATUS 171 | SpbBurstWriteDataSynchronously( 172 | IN SPB_CONTEXT* SpbContext, 173 | IN SPB_BURST_INFO* BurstInfo, 174 | IN ULONG Count 175 | ) 176 | { 177 | NTSTATUS status; 178 | 179 | typedef struct _SPB_TRANSFER { 180 | SPB_TRANSFER_LIST List; 181 | SPB_TRANSFER_LIST_ENTRY ExtraTransfers[]; 182 | } SPB_TRANSFER; 183 | 184 | size_t seq_size = sizeof(SPB_TRANSFER) + (sizeof(SPB_TRANSFER_LIST_ENTRY) * (Count - 1)); 185 | SPB_TRANSFER* seq = ExAllocatePoolWithTag(NonPagedPool, seq_size, RT5663_POOL_TAG); 186 | if (!seq) 187 | return STATUS_NO_MEMORY; 188 | 189 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 190 | 191 | SPB_TRANSFER_LIST_INIT(&(seq->List), Count); 192 | 193 | for (int i = 0; i < Count; i++) { 194 | SPB_BURST_INFO Info = BurstInfo[i]; 195 | 196 | seq->List.Transfers[i] = SPB_TRANSFER_LIST_ENTRY_INIT_SIMPLE( 197 | SpbTransferDirectionToDevice, 198 | 0, 199 | Info.Data, 200 | Info.Length); 201 | } 202 | 203 | WDF_MEMORY_DESCRIPTOR MemoryDescriptor; 204 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 205 | &MemoryDescriptor, 206 | seq, 207 | seq_size); 208 | ULONG_PTR BytesTransferred = 0; 209 | status = WdfIoTargetSendIoctlSynchronously( 210 | SpbContext->SpbIoTarget, 211 | NULL, 212 | IOCTL_SPB_EXECUTE_SEQUENCE, 213 | &MemoryDescriptor, 214 | NULL, 215 | NULL, 216 | &BytesTransferred 217 | ); 218 | 219 | WdfWaitLockRelease(SpbContext->SpbLock); 220 | 221 | exit: 222 | if (seq) 223 | ExFreePoolWithTag(seq, RT5663_POOL_TAG); 224 | return status; 225 | } 226 | 227 | NTSTATUS 228 | SpbXferDataSynchronously( 229 | _In_ SPB_CONTEXT* SpbContext, 230 | _In_ PVOID SendData, 231 | _In_ ULONG SendLength, 232 | _In_reads_bytes_(Length) PVOID Data, 233 | _In_ ULONG Length 234 | ) 235 | /*++ 236 | Routine Description: 237 | This helper routine abstracts creating and sending an I/O 238 | request (I2C Read) to the Spb I/O target. 239 | Arguments: 240 | SpbContext - Pointer to the current device context 241 | Address - The I2C register address to read from 242 | Data - A buffer to receive the data at at the above address 243 | Length - The amount of data to be read from the above address 244 | Return Value: 245 | NTSTATUS Status indicating success or failure 246 | --*/ 247 | { 248 | PUCHAR buffer; 249 | WDFMEMORY memory; 250 | WDF_MEMORY_DESCRIPTOR memoryDescriptor; 251 | NTSTATUS status; 252 | ULONG_PTR bytesRead; 253 | 254 | WdfWaitLockAcquire(SpbContext->SpbLock, NULL); 255 | 256 | memory = NULL; 257 | status = STATUS_INVALID_PARAMETER; 258 | bytesRead = 0; 259 | 260 | // 261 | // Xfer transactions start by writing an address pointer 262 | // 263 | status = SpbDoWriteDataSynchronously( 264 | SpbContext, 265 | SendData, 266 | SendLength); 267 | 268 | if (!NT_SUCCESS(status)) 269 | { 270 | RtekPrint( 271 | DEBUG_LEVEL_ERROR, 272 | DBG_IOCTL, 273 | "Error setting address pointer for Spb read - %!STATUS!", 274 | status); 275 | goto exit; 276 | } 277 | 278 | if (Length > DEFAULT_SPB_BUFFER_SIZE) 279 | { 280 | status = WdfMemoryCreate( 281 | WDF_NO_OBJECT_ATTRIBUTES, 282 | NonPagedPool, 283 | RT5663_POOL_TAG, 284 | Length, 285 | &memory, 286 | (PVOID*)&buffer); 287 | 288 | if (!NT_SUCCESS(status)) 289 | { 290 | RtekPrint( 291 | DEBUG_LEVEL_ERROR, 292 | DBG_IOCTL, 293 | "Error allocating memory for Spb read - %!STATUS!", 294 | status); 295 | goto exit; 296 | } 297 | 298 | WDF_MEMORY_DESCRIPTOR_INIT_HANDLE( 299 | &memoryDescriptor, 300 | memory, 301 | NULL); 302 | } 303 | else 304 | { 305 | buffer = (PUCHAR)WdfMemoryGetBuffer(SpbContext->ReadMemory, NULL); 306 | 307 | WDF_MEMORY_DESCRIPTOR_INIT_BUFFER( 308 | &memoryDescriptor, 309 | (PVOID)buffer, 310 | Length); 311 | } 312 | 313 | 314 | status = WdfIoTargetSendReadSynchronously( 315 | SpbContext->SpbIoTarget, 316 | NULL, 317 | &memoryDescriptor, 318 | NULL, 319 | NULL, 320 | &bytesRead); 321 | 322 | if (!NT_SUCCESS(status) || 323 | bytesRead != Length) 324 | { 325 | RtekPrint( 326 | DEBUG_LEVEL_ERROR, 327 | DBG_IOCTL, 328 | "Error reading from Spb - %!STATUS!", 329 | status); 330 | goto exit; 331 | } 332 | 333 | // 334 | // Copy back to the caller's buffer 335 | // 336 | RtlCopyMemory(Data, buffer, Length); 337 | 338 | exit: 339 | if (NULL != memory) 340 | { 341 | WdfObjectDelete(memory); 342 | } 343 | 344 | WdfWaitLockRelease(SpbContext->SpbLock); 345 | 346 | return status; 347 | } 348 | 349 | VOID 350 | SpbTargetDeinitialize( 351 | IN WDFDEVICE FxDevice, 352 | IN SPB_CONTEXT* SpbContext 353 | ) 354 | /*++ 355 | 356 | Routine Description: 357 | 358 | This helper routine is used to free any members added to the SPB_CONTEXT, 359 | note the SPB I/O target is parented to the device and will be 360 | closed and free'd when the device is removed. 361 | 362 | Arguments: 363 | 364 | FxDevice - Handle to the framework device object 365 | SpbContext - Pointer to the current device context 366 | 367 | Return Value: 368 | 369 | NTSTATUS Status indicating success or failure 370 | 371 | --*/ 372 | { 373 | UNREFERENCED_PARAMETER(FxDevice); 374 | UNREFERENCED_PARAMETER(SpbContext); 375 | 376 | // 377 | // Free any SPB_CONTEXT allocations here 378 | // 379 | if (SpbContext->SpbLock != NULL) 380 | { 381 | WdfObjectDelete(SpbContext->SpbLock); 382 | } 383 | 384 | if (SpbContext->ReadMemory != NULL) 385 | { 386 | WdfObjectDelete(SpbContext->ReadMemory); 387 | } 388 | 389 | if (SpbContext->WriteMemory != NULL) 390 | { 391 | WdfObjectDelete(SpbContext->WriteMemory); 392 | } 393 | } 394 | 395 | NTSTATUS 396 | SpbTargetInitialize( 397 | IN WDFDEVICE FxDevice, 398 | IN SPB_CONTEXT* SpbContext 399 | ) 400 | /*++ 401 | 402 | Routine Description: 403 | 404 | This helper routine opens the Spb I/O target and 405 | initializes a request object used for the lifetime 406 | of communication between this driver and Spb. 407 | 408 | Arguments: 409 | 410 | FxDevice - Handle to the framework device object 411 | SpbContext - Pointer to the current device context 412 | 413 | Return Value: 414 | 415 | NTSTATUS Status indicating success or failure 416 | 417 | --*/ 418 | { 419 | WDF_OBJECT_ATTRIBUTES objectAttributes; 420 | WDF_IO_TARGET_OPEN_PARAMS openParams; 421 | UNICODE_STRING spbDeviceName; 422 | WCHAR spbDeviceNameBuffer[RESOURCE_HUB_PATH_SIZE]; 423 | NTSTATUS status; 424 | 425 | WDF_OBJECT_ATTRIBUTES_INIT(&objectAttributes); 426 | objectAttributes.ParentObject = FxDevice; 427 | 428 | status = WdfIoTargetCreate( 429 | FxDevice, 430 | &objectAttributes, 431 | &SpbContext->SpbIoTarget); 432 | 433 | if (!NT_SUCCESS(status)) 434 | { 435 | RtekPrint( 436 | DEBUG_LEVEL_ERROR, 437 | DBG_IOCTL, 438 | "Error creating IoTarget object - %!STATUS!", 439 | status); 440 | 441 | WdfObjectDelete(SpbContext->SpbIoTarget); 442 | goto exit; 443 | } 444 | 445 | RtlInitEmptyUnicodeString( 446 | &spbDeviceName, 447 | spbDeviceNameBuffer, 448 | sizeof(spbDeviceNameBuffer)); 449 | 450 | status = RESOURCE_HUB_CREATE_PATH_FROM_ID( 451 | &spbDeviceName, 452 | SpbContext->I2cResHubId.LowPart, 453 | SpbContext->I2cResHubId.HighPart); 454 | 455 | if (!NT_SUCCESS(status)) 456 | { 457 | RtekPrint( 458 | DEBUG_LEVEL_ERROR, 459 | DBG_IOCTL, 460 | "Error creating Spb resource hub path string - %!STATUS!", 461 | status); 462 | goto exit; 463 | } 464 | 465 | WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME( 466 | &openParams, 467 | &spbDeviceName, 468 | (GENERIC_READ | GENERIC_WRITE)); 469 | 470 | openParams.ShareAccess = 0; 471 | openParams.CreateDisposition = FILE_OPEN; 472 | openParams.FileAttributes = FILE_ATTRIBUTE_NORMAL; 473 | 474 | status = WdfIoTargetOpen(SpbContext->SpbIoTarget, &openParams); 475 | 476 | if (!NT_SUCCESS(status)) 477 | { 478 | RtekPrint( 479 | DEBUG_LEVEL_ERROR, 480 | DBG_IOCTL, 481 | "Error opening Spb target for communication - %!STATUS!", 482 | status); 483 | goto exit; 484 | } 485 | 486 | // 487 | // Allocate some fixed-size buffers from NonPagedPool for typical 488 | // Spb transaction sizes to avoid pool fragmentation in most cases 489 | // 490 | status = WdfMemoryCreate( 491 | WDF_NO_OBJECT_ATTRIBUTES, 492 | NonPagedPool, 493 | RT5663_POOL_TAG, 494 | DEFAULT_SPB_BUFFER_SIZE, 495 | &SpbContext->WriteMemory, 496 | NULL); 497 | 498 | if (!NT_SUCCESS(status)) 499 | { 500 | RtekPrint( 501 | DEBUG_LEVEL_ERROR, 502 | DBG_IOCTL, 503 | "Error allocating default memory for Spb write - %!STATUS!", 504 | status); 505 | goto exit; 506 | } 507 | 508 | status = WdfMemoryCreate( 509 | WDF_NO_OBJECT_ATTRIBUTES, 510 | NonPagedPool, 511 | RT5663_POOL_TAG, 512 | DEFAULT_SPB_BUFFER_SIZE, 513 | &SpbContext->ReadMemory, 514 | NULL); 515 | 516 | if (!NT_SUCCESS(status)) 517 | { 518 | RtekPrint( 519 | DEBUG_LEVEL_ERROR, 520 | DBG_IOCTL, 521 | "Error allocating default memory for Spb read - %!STATUS!", 522 | status); 523 | goto exit; 524 | } 525 | 526 | // 527 | // Allocate a waitlock to guard access to the default buffers 528 | // 529 | status = WdfWaitLockCreate( 530 | WDF_NO_OBJECT_ATTRIBUTES, 531 | &SpbContext->SpbLock); 532 | 533 | if (!NT_SUCCESS(status)) 534 | { 535 | RtekPrint( 536 | DEBUG_LEVEL_ERROR, 537 | DBG_IOCTL, 538 | "Error creating Spb Waitlock - %!STATUS!", 539 | status); 540 | goto exit; 541 | } 542 | 543 | exit: 544 | 545 | if (!NT_SUCCESS(status)) 546 | { 547 | SpbTargetDeinitialize(FxDevice, SpbContext); 548 | } 549 | 550 | return status; 551 | } -------------------------------------------------------------------------------- /rt5663/registers.h: -------------------------------------------------------------------------------- 1 | #ifndef __RT5663_H__ 2 | #define __RT5663_H__ 3 | 4 | /* Info */ 5 | #define RT5663_RESET 0x0000 6 | #define RT5663_VENDOR_ID 0x00fd 7 | #define RT5663_VENDOR_ID_1 0x00fe 8 | #define RT5663_VENDOR_ID_2 0x00ff 9 | 10 | #define RT5663_LOUT_CTRL 0x0001 11 | #define RT5663_HP_AMP_2 0x0003 12 | #define RT5663_MONO_OUT 0x0004 13 | #define RT5663_MONO_GAIN 0x0007 14 | 15 | #define RT5663_AEC_BST 0x000b 16 | #define RT5663_IN1_IN2 0x000c 17 | #define RT5663_IN3_IN4 0x000d 18 | #define RT5663_INL1_INR1 0x000f 19 | #define RT5663_CBJ_TYPE_2 0x0011 20 | #define RT5663_CBJ_TYPE_3 0x0012 21 | #define RT5663_CBJ_TYPE_4 0x0013 22 | #define RT5663_CBJ_TYPE_5 0x0014 23 | #define RT5663_CBJ_TYPE_8 0x0017 24 | 25 | /* I/O - ADC/DAC/DMIC */ 26 | #define RT5663_DAC3_DIG_VOL 0x001a 27 | #define RT5663_DAC3_CTRL 0x001b 28 | #define RT5663_MONO_ADC_DIG_VOL 0x001d 29 | #define RT5663_STO2_ADC_DIG_VOL 0x001e 30 | #define RT5663_MONO_ADC_BST_GAIN 0x0020 31 | #define RT5663_STO2_ADC_BST_GAIN 0x0021 32 | #define RT5663_SIDETONE_CTRL 0x0024 33 | /* Mixer - D-D */ 34 | #define RT5663_MONO1_ADC_MIXER 0x0027 35 | #define RT5663_STO2_ADC_MIXER 0x0028 36 | #define RT5663_MONO_DAC_MIXER 0x002b 37 | #define RT5663_DAC2_SRC_CTRL 0x002e 38 | #define RT5663_IF_3_4_DATA_CTL 0x002f 39 | #define RT5663_IF_5_DATA_CTL 0x0030 40 | #define RT5663_PDM_OUT_CTL 0x0031 41 | #define RT5663_PDM_I2C_DATA_CTL1 0x0032 42 | #define RT5663_PDM_I2C_DATA_CTL2 0x0033 43 | #define RT5663_PDM_I2C_DATA_CTL3 0x0034 44 | #define RT5663_PDM_I2C_DATA_CTL4 0x0035 45 | 46 | /*Mixer - Analog*/ 47 | #define RT5663_RECMIX1_NEW 0x003a 48 | #define RT5663_RECMIX1L_0 0x003b 49 | #define RT5663_RECMIX1L 0x003c 50 | #define RT5663_RECMIX1R_0 0x003d 51 | #define RT5663_RECMIX1R 0x003e 52 | #define RT5663_RECMIX2_NEW 0x003f 53 | #define RT5663_RECMIX2_L_2 0x0041 54 | #define RT5663_RECMIX2_R 0x0042 55 | #define RT5663_RECMIX2_R_2 0x0043 56 | #define RT5663_CALIB_REC_LR 0x0044 57 | #define RT5663_ALC_BK_GAIN 0x0049 58 | #define RT5663_MONOMIX_GAIN 0x004a 59 | #define RT5663_MONOMIX_IN_GAIN 0x004b 60 | #define RT5663_OUT_MIXL_GAIN 0x004d 61 | #define RT5663_OUT_LMIX_IN_GAIN 0x004e 62 | #define RT5663_OUT_RMIX_IN_GAIN 0x004f 63 | #define RT5663_OUT_RMIX_IN_GAIN1 0x0050 64 | #define RT5663_LOUT_MIXER_CTRL 0x0052 65 | /* Power */ 66 | #define RT5663_PWR_VOL 0x0067 67 | 68 | #define RT5663_ADCDAC_RST 0x006d 69 | /* Format - ADC/DAC */ 70 | #define RT5663_I2S34_SDP 0x0071 71 | #define RT5663_I2S5_SDP 0x0072 72 | 73 | /* Function - Analog */ 74 | #define RT5663_ASRC_3 0x0085 75 | #define RT5663_ASRC_6 0x0088 76 | #define RT5663_ASRC_7 0x0089 77 | #define RT5663_PLL_TRK_13 0x0099 78 | #define RT5663_I2S_M_CLK_CTL 0x00a0 79 | #define RT5663_FDIV_I2S34_M_CLK 0x00a1 80 | #define RT5663_FDIV_I2S34_M_CLK2 0x00a2 81 | #define RT5663_FDIV_I2S5_M_CLK 0x00a3 82 | #define RT5663_FDIV_I2S5_M_CLK2 0x00a4 83 | 84 | /* Function - Digital */ 85 | #define RT5663_V2_IRQ_4 0x00b9 86 | #define RT5663_GPIO_3 0x00c2 87 | #define RT5663_GPIO_4 0x00c3 88 | #define RT5663_GPIO_STA2 0x00c4 89 | #define RT5663_HP_AMP_DET1 0x00d0 90 | #define RT5663_HP_AMP_DET2 0x00d1 91 | #define RT5663_HP_AMP_DET3 0x00d2 92 | #define RT5663_MID_BD_HP_AMP 0x00d3 93 | #define RT5663_LOW_BD_HP_AMP 0x00d4 94 | #define RT5663_SOF_VOL_ZC2 0x00da 95 | #define RT5663_ADC_STO2_ADJ1 0x00ee 96 | #define RT5663_ADC_STO2_ADJ2 0x00ef 97 | /* General Control */ 98 | #define RT5663_A_JD_CTRL 0x00f0 99 | #define RT5663_JD1_TRES_CTRL 0x00f1 100 | #define RT5663_JD2_TRES_CTRL 0x00f2 101 | #define RT5663_V2_JD_CTRL2 0x00f7 102 | #define RT5663_DUM_REG_2 0x00fb 103 | #define RT5663_DUM_REG_3 0x00fc 104 | 105 | 106 | #define RT5663_DACADC_DIG_VOL2 0x0101 107 | #define RT5663_DIG_IN_PIN2 0x0133 108 | #define RT5663_PAD_DRV_CTL1 0x0136 109 | #define RT5663_SOF_RAM_DEPOP 0x0138 110 | #define RT5663_VOL_TEST 0x013f 111 | #define RT5663_MONO_DYNA_1 0x0170 112 | #define RT5663_MONO_DYNA_2 0x0171 113 | #define RT5663_MONO_DYNA_3 0x0172 114 | #define RT5663_MONO_DYNA_4 0x0173 115 | #define RT5663_MONO_DYNA_5 0x0174 116 | #define RT5663_MONO_DYNA_6 0x0175 117 | #define RT5663_STO1_SIL_DET 0x0190 118 | #define RT5663_MONOL_SIL_DET 0x0191 119 | #define RT5663_MONOR_SIL_DET 0x0192 120 | #define RT5663_STO2_DAC_SIL 0x0193 121 | #define RT5663_PWR_SAV_CTL1 0x0194 122 | #define RT5663_PWR_SAV_CTL2 0x0195 123 | #define RT5663_PWR_SAV_CTL3 0x0196 124 | #define RT5663_PWR_SAV_CTL4 0x0197 125 | #define RT5663_PWR_SAV_CTL5 0x0198 126 | #define RT5663_PWR_SAV_CTL6 0x0199 127 | #define RT5663_MONO_AMP_CAL1 0x01a0 128 | #define RT5663_MONO_AMP_CAL2 0x01a1 129 | #define RT5663_MONO_AMP_CAL3 0x01a2 130 | #define RT5663_MONO_AMP_CAL4 0x01a3 131 | #define RT5663_MONO_AMP_CAL5 0x01a4 132 | #define RT5663_MONO_AMP_CAL6 0x01a5 133 | #define RT5663_MONO_AMP_CAL7 0x01a6 134 | #define RT5663_MONO_AMP_CAL_ST1 0x01a7 135 | #define RT5663_MONO_AMP_CAL_ST2 0x01a8 136 | #define RT5663_MONO_AMP_CAL_ST3 0x01a9 137 | #define RT5663_MONO_AMP_CAL_ST4 0x01aa 138 | #define RT5663_MONO_AMP_CAL_ST5 0x01ab 139 | #define RT5663_V2_HP_IMP_SEN_13 0x01b9 140 | #define RT5663_V2_HP_IMP_SEN_14 0x01ba 141 | #define RT5663_V2_HP_IMP_SEN_6 0x01bb 142 | #define RT5663_V2_HP_IMP_SEN_7 0x01bc 143 | #define RT5663_V2_HP_IMP_SEN_8 0x01bd 144 | #define RT5663_V2_HP_IMP_SEN_9 0x01be 145 | #define RT5663_V2_HP_IMP_SEN_10 0x01bf 146 | #define RT5663_HP_LOGIC_3 0x01dc 147 | #define RT5663_HP_CALIB_ST10 0x01f3 148 | #define RT5663_HP_CALIB_ST11 0x01f4 149 | #define RT5663_PRO_REG_TBL_4 0x0203 150 | #define RT5663_PRO_REG_TBL_5 0x0204 151 | #define RT5663_PRO_REG_TBL_6 0x0205 152 | #define RT5663_PRO_REG_TBL_7 0x0206 153 | #define RT5663_PRO_REG_TBL_8 0x0207 154 | #define RT5663_PRO_REG_TBL_9 0x0208 155 | #define RT5663_SAR_ADC_INL_1 0x0210 156 | #define RT5663_SAR_ADC_INL_2 0x0211 157 | #define RT5663_SAR_ADC_INL_3 0x0212 158 | #define RT5663_SAR_ADC_INL_4 0x0213 159 | #define RT5663_SAR_ADC_INL_5 0x0214 160 | #define RT5663_SAR_ADC_INL_6 0x0215 161 | #define RT5663_SAR_ADC_INL_7 0x0216 162 | #define RT5663_SAR_ADC_INL_8 0x0217 163 | #define RT5663_SAR_ADC_INL_9 0x0218 164 | #define RT5663_SAR_ADC_INL_10 0x0219 165 | #define RT5663_SAR_ADC_INL_11 0x021a 166 | #define RT5663_SAR_ADC_INL_12 0x021b 167 | #define RT5663_DRC_CTRL_1 0x02ff 168 | #define RT5663_DRC1_CTRL_2 0x0301 169 | #define RT5663_DRC1_CTRL_3 0x0302 170 | #define RT5663_DRC1_CTRL_4 0x0303 171 | #define RT5663_DRC1_CTRL_5 0x0304 172 | #define RT5663_DRC1_CTRL_6 0x0305 173 | #define RT5663_DRC1_HD_CTRL_1 0x0306 174 | #define RT5663_DRC1_HD_CTRL_2 0x0307 175 | #define RT5663_DRC1_PRI_REG_1 0x0310 176 | #define RT5663_DRC1_PRI_REG_2 0x0311 177 | #define RT5663_DRC1_PRI_REG_3 0x0312 178 | #define RT5663_DRC1_PRI_REG_4 0x0313 179 | #define RT5663_DRC1_PRI_REG_5 0x0314 180 | #define RT5663_DRC1_PRI_REG_6 0x0315 181 | #define RT5663_DRC1_PRI_REG_7 0x0316 182 | #define RT5663_DRC1_PRI_REG_8 0x0317 183 | #define RT5663_ALC_PGA_CTL_1 0x0330 184 | #define RT5663_ALC_PGA_CTL_2 0x0331 185 | #define RT5663_ALC_PGA_CTL_3 0x0332 186 | #define RT5663_ALC_PGA_CTL_4 0x0333 187 | #define RT5663_ALC_PGA_CTL_5 0x0334 188 | #define RT5663_ALC_PGA_CTL_6 0x0335 189 | #define RT5663_ALC_PGA_CTL_7 0x0336 190 | #define RT5663_ALC_PGA_CTL_8 0x0337 191 | #define RT5663_ALC_PGA_REG_1 0x0338 192 | #define RT5663_ALC_PGA_REG_2 0x0339 193 | #define RT5663_ALC_PGA_REG_3 0x033a 194 | #define RT5663_ADC_EQ_RECOV_1 0x03c0 195 | #define RT5663_ADC_EQ_RECOV_2 0x03c1 196 | #define RT5663_ADC_EQ_RECOV_3 0x03c2 197 | #define RT5663_ADC_EQ_RECOV_4 0x03c3 198 | #define RT5663_ADC_EQ_RECOV_5 0x03c4 199 | #define RT5663_ADC_EQ_RECOV_6 0x03c5 200 | #define RT5663_ADC_EQ_RECOV_7 0x03c6 201 | #define RT5663_ADC_EQ_RECOV_8 0x03c7 202 | #define RT5663_ADC_EQ_RECOV_9 0x03c8 203 | #define RT5663_ADC_EQ_RECOV_10 0x03c9 204 | #define RT5663_ADC_EQ_RECOV_11 0x03ca 205 | #define RT5663_ADC_EQ_RECOV_12 0x03cb 206 | #define RT5663_ADC_EQ_RECOV_13 0x03cc 207 | #define RT5663_VID_HIDDEN 0x03fe 208 | #define RT5663_VID_CUSTOMER 0x03ff 209 | #define RT5663_SCAN_MODE 0x07f0 210 | #define RT5663_I2C_BYPA 0x07fa 211 | 212 | /* Headphone Amp Control 2 (0x0003) */ 213 | #define RT5663_EN_DAC_HPO_MASK (0x1 << 14) 214 | #define RT5663_EN_DAC_HPO_SHIFT 14 215 | #define RT5663_EN_DAC_HPO_DIS (0x0 << 14) 216 | #define RT5663_EN_DAC_HPO_EN (0x1 << 14) 217 | 218 | /*Headphone Amp L/R Analog Gain and Digital NG2 Gain Control (0x0005 0x0006)*/ 219 | #define RT5663_GAIN_HP (0x1f << 8) 220 | #define RT5663_GAIN_HP_SHIFT 8 221 | 222 | /* AEC BST Control (0x000b) */ 223 | #define RT5663_GAIN_CBJ_MASK (0xf << 8) 224 | #define RT5663_GAIN_CBJ_SHIFT 8 225 | 226 | /* IN1 Control / MIC GND REF (0x000c) */ 227 | #define RT5663_IN1_DF_MASK (0x1 << 15) 228 | #define RT5663_IN1_DF_SHIFT 15 229 | 230 | /* Combo Jack and Type Detection Control 1 (0x0010) */ 231 | #define RT5663_CBJ_DET_MASK (0x1 << 15) 232 | #define RT5663_CBJ_DET_SHIFT 15 233 | #define RT5663_CBJ_DET_DIS (0x0 << 15) 234 | #define RT5663_CBJ_DET_EN (0x1 << 15) 235 | #define RT5663_DET_TYPE_MASK (0x1 << 12) 236 | #define RT5663_DET_TYPE_SHIFT 12 237 | #define RT5663_DET_TYPE_WLCSP (0x0 << 12) 238 | #define RT5663_DET_TYPE_QFN (0x1 << 12) 239 | #define RT5663_VREF_BIAS_MASK (0x1 << 6) 240 | #define RT5663_VREF_BIAS_SHIFT 6 241 | #define RT5663_VREF_BIAS_FSM (0x0 << 6) 242 | #define RT5663_VREF_BIAS_REG (0x1 << 6) 243 | 244 | /* REC Left Mixer Control 2 (0x003c) */ 245 | #define RT5663_RECMIX1L_BST1_CBJ (0x1 << 7) 246 | #define RT5663_RECMIX1L_BST1_CBJ_SHIFT 7 247 | #define RT5663_RECMIX1L_BST2 (0x1 << 4) 248 | #define RT5663_RECMIX1L_BST2_SHIFT 4 249 | 250 | /* REC Right Mixer Control 2 (0x003e) */ 251 | #define RT5663_RECMIX1R_BST2 (0x1 << 4) 252 | #define RT5663_RECMIX1R_BST2_SHIFT 4 253 | 254 | /* DAC1 Digital Volume (0x0019) */ 255 | #define RT5663_DAC_L1_VOL_MASK (0xff << 8) 256 | #define RT5663_DAC_L1_VOL_SHIFT 8 257 | #define RT5663_DAC_R1_VOL_MASK (0xff) 258 | #define RT5663_DAC_R1_VOL_SHIFT 0 259 | 260 | /* ADC Digital Volume Control (0x001c) */ 261 | #define RT5663_ADC_L_MUTE_MASK (0x1 << 15) 262 | #define RT5663_ADC_L_MUTE_SHIFT 15 263 | #define RT5663_ADC_L_VOL_MASK (0x7f << 8) 264 | #define RT5663_ADC_L_VOL_SHIFT 8 265 | #define RT5663_ADC_R_MUTE_MASK (0x1 << 7) 266 | #define RT5663_ADC_R_MUTE_SHIFT 7 267 | #define RT5663_ADC_R_VOL_MASK (0x7f) 268 | #define RT5663_ADC_R_VOL_SHIFT 0 269 | 270 | /* Stereo ADC Mixer Control (0x0026) */ 271 | #define RT5663_M_STO1_ADC_L1 (0x1 << 15) 272 | #define RT5663_M_STO1_ADC_L1_SHIFT 15 273 | #define RT5663_M_STO1_ADC_L2 (0x1 << 14) 274 | #define RT5663_M_STO1_ADC_L2_SHIFT 14 275 | #define RT5663_STO1_ADC_L1_SRC (0x1 << 13) 276 | #define RT5663_STO1_ADC_L1_SRC_SHIFT 13 277 | #define RT5663_STO1_ADC_L2_SRC (0x1 << 12) 278 | #define RT5663_STO1_ADC_L2_SRC_SHIFT 12 279 | #define RT5663_STO1_ADC_L_SRC (0x3 << 10) 280 | #define RT5663_STO1_ADC_L_SRC_SHIFT 10 281 | #define RT5663_M_STO1_ADC_R1 (0x1 << 7) 282 | #define RT5663_M_STO1_ADC_R1_SHIFT 7 283 | #define RT5663_M_STO1_ADC_R2 (0x1 << 6) 284 | #define RT5663_M_STO1_ADC_R2_SHIFT 6 285 | #define RT5663_STO1_ADC_R1_SRC (0x1 << 5) 286 | #define RT5663_STO1_ADC_R1_SRC_SHIFT 5 287 | #define RT5663_STO1_ADC_R2_SRC (0x1 << 4) 288 | #define RT5663_STO1_ADC_R2_SRC_SHIFT 4 289 | #define RT5663_STO1_ADC_R_SRC (0x3 << 2) 290 | #define RT5663_STO1_ADC_R_SRC_SHIFT 2 291 | 292 | /* ADC Mixer to DAC Mixer Control (0x0029) */ 293 | #define RT5663_M_ADCMIX_L (0x1 << 15) 294 | #define RT5663_M_ADCMIX_L_SHIFT 15 295 | #define RT5663_M_DAC1_L (0x1 << 14) 296 | #define RT5663_M_DAC1_L_SHIFT 14 297 | #define RT5663_M_ADCMIX_R (0x1 << 7) 298 | #define RT5663_M_ADCMIX_R_SHIFT 7 299 | #define RT5663_M_DAC1_R (0x1 << 6) 300 | #define RT5663_M_DAC1_R_SHIFT 6 301 | 302 | /* Stereo DAC Mixer Control (0x002a) */ 303 | #define RT5663_M_DAC_L1_STO_L (0x1 << 15) 304 | #define RT5663_M_DAC_L1_STO_L_SHIFT 15 305 | #define RT5663_M_DAC_R1_STO_L (0x1 << 13) 306 | #define RT5663_M_DAC_R1_STO_L_SHIFT 13 307 | #define RT5663_M_DAC_L1_STO_R (0x1 << 7) 308 | #define RT5663_M_DAC_L1_STO_R_SHIFT 7 309 | #define RT5663_M_DAC_R1_STO_R (0x1 << 5) 310 | #define RT5663_M_DAC_R1_STO_R_SHIFT 5 311 | 312 | /* Power Management for Digital 1 (0x0061) */ 313 | #define RT5663_PWR_I2S1 (0x1 << 15) 314 | #define RT5663_PWR_I2S1_SHIFT 15 315 | #define RT5663_PWR_DAC_L1 (0x1 << 11) 316 | #define RT5663_PWR_DAC_L1_SHIFT 11 317 | #define RT5663_PWR_DAC_R1 (0x1 << 10) 318 | #define RT5663_PWR_DAC_R1_SHIFT 10 319 | #define RT5663_PWR_LDO_DACREF_MASK (0x1 << 8) 320 | #define RT5663_PWR_LDO_DACREF_SHIFT 8 321 | #define RT5663_PWR_LDO_DACREF_ON (0x1 << 8) 322 | #define RT5663_PWR_LDO_DACREF_DOWN (0x0 << 8) 323 | #define RT5663_PWR_LDO_SHIFT 8 324 | #define RT5663_PWR_ADC_L1 (0x1 << 4) 325 | #define RT5663_PWR_ADC_L1_SHIFT 4 326 | #define RT5663_PWR_ADC_R1 (0x1 << 3) 327 | #define RT5663_PWR_ADC_R1_SHIFT 3 328 | 329 | /* Power Management for Digital 2 (0x0062) */ 330 | #define RT5663_PWR_ADC_S1F (0x1 << 15) 331 | #define RT5663_PWR_ADC_S1F_SHIFT 15 332 | #define RT5663_PWR_DAC_S1F (0x1 << 10) 333 | #define RT5663_PWR_DAC_S1F_SHIFT 10 334 | 335 | /* Power Management for Analog 1 (0x0063) */ 336 | #define RT5663_PWR_VREF1 (0x1 << 15) 337 | #define RT5663_PWR_VREF1_MASK (0x1 << 15) 338 | #define RT5663_PWR_VREF1_SHIFT 15 339 | #define RT5663_PWR_FV1 (0x1 << 14) 340 | #define RT5663_PWR_FV1_MASK (0x1 << 14) 341 | #define RT5663_PWR_FV1_SHIFT 14 342 | #define RT5663_PWR_VREF2 (0x1 << 13) 343 | #define RT5663_PWR_VREF2_MASK (0x1 << 13) 344 | #define RT5663_PWR_VREF2_SHIFT 13 345 | #define RT5663_PWR_FV2 (0x1 << 12) 346 | #define RT5663_PWR_FV2_MASK (0x1 << 12) 347 | #define RT5663_PWR_FV2_SHIFT 12 348 | #define RT5663_PWR_MB (0x1 << 9) 349 | #define RT5663_PWR_MB_MASK (0x1 << 9) 350 | #define RT5663_PWR_MB_SHIFT 9 351 | #define RT5663_AMP_HP_MASK (0x3 << 2) 352 | #define RT5663_AMP_HP_SHIFT 2 353 | #define RT5663_AMP_HP_1X (0x0 << 2) 354 | #define RT5663_AMP_HP_3X (0x1 << 2) 355 | #define RT5663_AMP_HP_5X (0x3 << 2) 356 | #define RT5663_LDO1_DVO_MASK (0x3) 357 | #define RT5663_LDO1_DVO_SHIFT 0 358 | #define RT5663_LDO1_DVO_0_9V (0x0) 359 | #define RT5663_LDO1_DVO_1_0V (0x1) 360 | #define RT5663_LDO1_DVO_1_2V (0x2) 361 | #define RT5663_LDO1_DVO_1_4V (0x3) 362 | 363 | /* Power Management for Analog 2 (0x0064) */ 364 | #define RT5663_PWR_BST1 (0x1 << 15) 365 | #define RT5663_PWR_BST1_MASK (0x1 << 15) 366 | #define RT5663_PWR_BST1_SHIFT 15 367 | #define RT5663_PWR_BST1_OFF (0x0 << 15) 368 | #define RT5663_PWR_BST1_ON (0x1 << 15) 369 | #define RT5663_PWR_BST2 (0x1 << 14) 370 | #define RT5663_PWR_BST2_MASK (0x1 << 14) 371 | #define RT5663_PWR_BST2_SHIFT 14 372 | #define RT5663_PWR_MB1 (0x1 << 11) 373 | #define RT5663_PWR_MB1_SHIFT 11 374 | #define RT5663_PWR_MB2 (0x1 << 10) 375 | #define RT5663_PWR_MB2_SHIFT 10 376 | #define RT5663_PWR_BST2_OP (0x1 << 6) 377 | #define RT5663_PWR_BST2_OP_MASK (0x1 << 6) 378 | #define RT5663_PWR_BST2_OP_SHIFT 6 379 | #define RT5663_PWR_JD1 (0x1 << 3) 380 | #define RT5663_PWR_JD1_MASK (0x1 << 3) 381 | #define RT5663_PWR_JD1_SHIFT 3 382 | #define RT5663_PWR_JD2 (0x1 << 2) 383 | #define RT5663_PWR_JD2_MASK (0x1 << 2) 384 | #define RT5663_PWR_JD2_SHIFT 2 385 | #define RT5663_PWR_RECMIX1 (0x1 << 1) 386 | #define RT5663_PWR_RECMIX1_SHIFT 1 387 | #define RT5663_PWR_RECMIX2 (0x1) 388 | #define RT5663_PWR_RECMIX2_SHIFT 0 389 | 390 | /* Power Management for Analog 3 (0x0065) */ 391 | #define RT5663_PWR_CBJ_MASK (0x1 << 9) 392 | #define RT5663_PWR_CBJ_SHIFT 9 393 | #define RT5663_PWR_CBJ_OFF (0x0 << 9) 394 | #define RT5663_PWR_CBJ_ON (0x1 << 9) 395 | #define RT5663_PWR_PLL (0x1 << 6) 396 | #define RT5663_PWR_PLL_SHIFT 6 397 | #define RT5663_PWR_LDO2 (0x1 << 2) 398 | #define RT5663_PWR_LDO2_SHIFT 2 399 | 400 | /* Power Management for Volume (0x0067) */ 401 | #define RT5663_V2_PWR_MIC_DET (0x1 << 5) 402 | #define RT5663_V2_PWR_MIC_DET_SHIFT 5 403 | 404 | /* MCLK and System Clock Detection Control (0x006b) */ 405 | #define RT5663_EN_ANA_CLK_DET_MASK (0x1 << 15) 406 | #define RT5663_EN_ANA_CLK_DET_SHIFT 15 407 | #define RT5663_EN_ANA_CLK_DET_DIS (0x0 << 15) 408 | #define RT5663_EN_ANA_CLK_DET_AUTO (0x1 << 15) 409 | #define RT5663_PWR_CLK_DET_MASK (0x1) 410 | #define RT5663_PWR_CLK_DET_SHIFT 0 411 | #define RT5663_PWR_CLK_DET_DIS (0x0) 412 | #define RT5663_PWR_CLK_DET_EN (0x1) 413 | 414 | /* I2S1 Audio Serial Data Port Control (0x0070) */ 415 | #define RT5663_I2S_MS_MASK (0x1 << 15) 416 | #define RT5663_I2S_MS_SHIFT 15 417 | #define RT5663_I2S_MS_M (0x0 << 15) 418 | #define RT5663_I2S_MS_S (0x1 << 15) 419 | #define RT5663_I2S_BP_MASK (0x1 << 8) 420 | #define RT5663_I2S_BP_SHIFT 8 421 | #define RT5663_I2S_BP_NOR (0x0 << 8) 422 | #define RT5663_I2S_BP_INV (0x1 << 8) 423 | #define RT5663_I2S_DL_MASK (0x3 << 4) 424 | #define RT5663_I2S_DL_SHIFT 4 425 | #define RT5663_I2S_DL_16 (0x0 << 4) 426 | #define RT5663_I2S_DL_20 (0x1 << 4) 427 | #define RT5663_I2S_DL_24 (0x2 << 4) 428 | #define RT5663_I2S_DL_8 (0x3 << 4) 429 | #define RT5663_I2S_DF_MASK (0x7) 430 | #define RT5663_I2S_DF_SHIFT 0 431 | #define RT5663_I2S_DF_I2S (0x0) 432 | #define RT5663_I2S_DF_LEFT (0x1) 433 | #define RT5663_I2S_DF_PCM_A (0x2) 434 | #define RT5663_I2S_DF_PCM_B (0x3) 435 | #define RT5663_I2S_DF_PCM_A_N (0x6) 436 | #define RT5663_I2S_DF_PCM_B_N (0x7) 437 | 438 | /* ADC/DAC Clock Control 1 (0x0073) */ 439 | #define RT5663_I2S_PD1_MASK (0x7 << 12) 440 | #define RT5663_I2S_PD1_SHIFT 12 441 | #define RT5663_M_I2S_DIV_MASK (0x7 << 8) 442 | #define RT5663_M_I2S_DIV_SHIFT 8 443 | #define RT5663_CLK_SRC_MASK (0x3 << 4) 444 | #define RT5663_CLK_SRC_MCLK (0x0 << 4) 445 | #define RT5663_CLK_SRC_PLL_OUT (0x1 << 4) 446 | #define RT5663_CLK_SRC_DIV (0x2 << 4) 447 | #define RT5663_CLK_SRC_RC (0x3 << 4) 448 | #define RT5663_DAC_OSR_MASK (0x3 << 2) 449 | #define RT5663_DAC_OSR_SHIFT 2 450 | #define RT5663_DAC_OSR_128 (0x0 << 2) 451 | #define RT5663_DAC_OSR_64 (0x1 << 2) 452 | #define RT5663_DAC_OSR_32 (0x2 << 2) 453 | #define RT5663_ADC_OSR_MASK (0x3) 454 | #define RT5663_ADC_OSR_SHIFT 0 455 | #define RT5663_ADC_OSR_128 (0x0) 456 | #define RT5663_ADC_OSR_64 (0x1) 457 | #define RT5663_ADC_OSR_32 (0x2) 458 | 459 | /* TDM1 control 1 (0x0078) */ 460 | #define RT5663_TDM_MODE_MASK (0x1 << 15) 461 | #define RT5663_TDM_MODE_SHIFT 15 462 | #define RT5663_TDM_MODE_I2S (0x0 << 15) 463 | #define RT5663_TDM_MODE_TDM (0x1 << 15) 464 | #define RT5663_TDM_IN_CH_MASK (0x3 << 10) 465 | #define RT5663_TDM_IN_CH_SHIFT 10 466 | #define RT5663_TDM_IN_CH_2 (0x0 << 10) 467 | #define RT5663_TDM_IN_CH_4 (0x1 << 10) 468 | #define RT5663_TDM_IN_CH_6 (0x2 << 10) 469 | #define RT5663_TDM_IN_CH_8 (0x3 << 10) 470 | #define RT5663_TDM_OUT_CH_MASK (0x3 << 8) 471 | #define RT5663_TDM_OUT_CH_SHIFT 8 472 | #define RT5663_TDM_OUT_CH_2 (0x0 << 8) 473 | #define RT5663_TDM_OUT_CH_4 (0x1 << 8) 474 | #define RT5663_TDM_OUT_CH_6 (0x2 << 8) 475 | #define RT5663_TDM_OUT_CH_8 (0x3 << 8) 476 | #define RT5663_TDM_IN_LEN_MASK (0x3 << 6) 477 | #define RT5663_TDM_IN_LEN_SHIFT 6 478 | #define RT5663_TDM_IN_LEN_16 (0x0 << 6) 479 | #define RT5663_TDM_IN_LEN_20 (0x1 << 6) 480 | #define RT5663_TDM_IN_LEN_24 (0x2 << 6) 481 | #define RT5663_TDM_IN_LEN_32 (0x3 << 6) 482 | #define RT5663_TDM_OUT_LEN_MASK (0x3 << 4) 483 | #define RT5663_TDM_OUT_LEN_SHIFT 4 484 | #define RT5663_TDM_OUT_LEN_16 (0x0 << 4) 485 | #define RT5663_TDM_OUT_LEN_20 (0x1 << 4) 486 | #define RT5663_TDM_OUT_LEN_24 (0x2 << 4) 487 | #define RT5663_TDM_OUT_LEN_32 (0x3 << 4) 488 | 489 | /* Global Clock Control (0x0080) */ 490 | #define RT5663_SCLK_SRC_MASK (0x3 << 14) 491 | #define RT5663_SCLK_SRC_SHIFT 14 492 | #define RT5663_SCLK_SRC_MCLK (0x0 << 14) 493 | #define RT5663_SCLK_SRC_PLL1 (0x1 << 14) 494 | #define RT5663_SCLK_SRC_RCCLK (0x2 << 14) 495 | #define RT5663_PLL1_SRC_MASK (0x7 << 11) 496 | #define RT5663_PLL1_SRC_SHIFT 11 497 | #define RT5663_PLL1_SRC_MCLK (0x0 << 11) 498 | #define RT5663_PLL1_SRC_BCLK1 (0x1 << 11) 499 | #define RT5663_V2_PLL1_SRC_MASK (0x7 << 8) 500 | #define RT5663_V2_PLL1_SRC_SHIFT 8 501 | #define RT5663_V2_PLL1_SRC_MCLK (0x0 << 8) 502 | #define RT5663_V2_PLL1_SRC_BCLK1 (0x1 << 8) 503 | #define RT5663_PLL1_PD_MASK (0x1 << 4) 504 | #define RT5663_PLL1_PD_SHIFT 4 505 | 506 | #define RT5663_PLL_INP_MAX 40000000 507 | #define RT5663_PLL_INP_MIN 256000 508 | /* PLL M/N/K Code Control 1 (0x0081) */ 509 | #define RT5663_PLL_N_MAX 0x001ff 510 | #define RT5663_PLL_N_MASK (RT5663_PLL_N_MAX << 7) 511 | #define RT5663_PLL_N_SHIFT 7 512 | #define RT5663_PLL_K_MAX 0x001f 513 | #define RT5663_PLL_K_MASK (RT5663_PLL_K_MAX) 514 | #define RT5663_PLL_K_SHIFT 0 515 | 516 | /* PLL M/N/K Code Control 2 (0x0082) */ 517 | #define RT5663_PLL_M_MAX 0x00f 518 | #define RT5663_PLL_M_MASK (RT5663_PLL_M_MAX << 12) 519 | #define RT5663_PLL_M_SHIFT 12 520 | #define RT5663_PLL_M_BP (0x1 << 11) 521 | #define RT5663_PLL_M_BP_SHIFT 11 522 | 523 | /* PLL tracking mode 1 (0x0083) */ 524 | #define RT5663_V2_I2S1_ASRC_MASK (0x1 << 13) 525 | #define RT5663_V2_I2S1_ASRC_SHIFT 13 526 | #define RT5663_V2_DAC_STO1_ASRC_MASK (0x1 << 12) 527 | #define RT5663_V2_DAC_STO1_ASRC_SHIFT 12 528 | #define RT5663_V2_ADC_STO1_ASRC_MASK (0x1 << 4) 529 | #define RT5663_V2_ADC_STO1_ASRC_SHIFT 4 530 | 531 | /* PLL tracking mode 2 (0x0084)*/ 532 | #define RT5663_DA_STO1_TRACK_MASK (0x7 << 12) 533 | #define RT5663_DA_STO1_TRACK_SHIFT 12 534 | #define RT5663_DA_STO1_TRACK_SYSCLK (0x0 << 12) 535 | #define RT5663_DA_STO1_TRACK_I2S1 (0x1 << 12) 536 | 537 | /* PLL tracking mode 3 (0x0085)*/ 538 | #define RT5663_V2_AD_STO1_TRACK_MASK (0x7 << 12) 539 | #define RT5663_V2_AD_STO1_TRACK_SHIFT 12 540 | #define RT5663_V2_AD_STO1_TRACK_SYSCLK (0x0 << 12) 541 | #define RT5663_V2_AD_STO1_TRACK_I2S1 (0x1 << 12) 542 | 543 | /* HPOUT Charge pump control 1 (0x0091) */ 544 | #define RT5663_OSW_HP_L_MASK (0x1 << 11) 545 | #define RT5663_OSW_HP_L_SHIFT 11 546 | #define RT5663_OSW_HP_L_EN (0x1 << 11) 547 | #define RT5663_OSW_HP_L_DIS (0x0 << 11) 548 | #define RT5663_OSW_HP_R_MASK (0x1 << 10) 549 | #define RT5663_OSW_HP_R_SHIFT 10 550 | #define RT5663_OSW_HP_R_EN (0x1 << 10) 551 | #define RT5663_OSW_HP_R_DIS (0x0 << 10) 552 | #define RT5663_SEL_PM_HP_MASK (0x3 << 8) 553 | #define RT5663_SEL_PM_HP_SHIFT 8 554 | #define RT5663_SEL_PM_HP_0_6 (0x0 << 8) 555 | #define RT5663_SEL_PM_HP_0_9 (0x1 << 8) 556 | #define RT5663_SEL_PM_HP_1_8 (0x2 << 8) 557 | #define RT5663_SEL_PM_HP_HIGH (0x3 << 8) 558 | #define RT5663_OVCD_HP_MASK (0x1 << 2) 559 | #define RT5663_OVCD_HP_SHIFT 2 560 | #define RT5663_OVCD_HP_EN (0x1 << 2) 561 | #define RT5663_OVCD_HP_DIS (0x0 << 2) 562 | 563 | /* RC Clock Control (0x0094) */ 564 | #define RT5663_DIG_25M_CLK_MASK (0x1 << 9) 565 | #define RT5663_DIG_25M_CLK_SHIFT 9 566 | #define RT5663_DIG_25M_CLK_DIS (0x0 << 9) 567 | #define RT5663_DIG_25M_CLK_EN (0x1 << 9) 568 | #define RT5663_DIG_1M_CLK_MASK (0x1 << 8) 569 | #define RT5663_DIG_1M_CLK_SHIFT 8 570 | #define RT5663_DIG_1M_CLK_DIS (0x0 << 8) 571 | #define RT5663_DIG_1M_CLK_EN (0x1 << 8) 572 | 573 | /* Auto Turn On 1M RC CLK (0x009f) */ 574 | #define RT5663_IRQ_POW_SAV_MASK (0x1 << 15) 575 | #define RT5663_IRQ_POW_SAV_SHIFT 15 576 | #define RT5663_IRQ_POW_SAV_DIS (0x0 << 15) 577 | #define RT5663_IRQ_POW_SAV_EN (0x1 << 15) 578 | #define RT5663_IRQ_POW_SAV_JD1_MASK (0x1 << 14) 579 | #define RT5663_IRQ_POW_SAV_JD1_SHIFT 14 580 | #define RT5663_IRQ_POW_SAV_JD1_DIS (0x0 << 14) 581 | #define RT5663_IRQ_POW_SAV_JD1_EN (0x1 << 14) 582 | #define RT5663_IRQ_MANUAL_MASK (0x1 << 8) 583 | #define RT5663_IRQ_MANUAL_SHIFT 8 584 | #define RT5663_IRQ_MANUAL_DIS (0x0 << 8) 585 | #define RT5663_IRQ_MANUAL_EN (0x1 << 8) 586 | 587 | /* IRQ Control 1 (0x00b6) */ 588 | #define RT5663_EN_CB_JD_MASK (0x1 << 3) 589 | #define RT5663_EN_CB_JD_SHIFT 3 590 | #define RT5663_EN_CB_JD_EN (0x1 << 3) 591 | #define RT5663_EN_CB_JD_DIS (0x0 << 3) 592 | 593 | /* IRQ Control 3 (0x00b8) */ 594 | #define RT5663_V2_EN_IRQ_INLINE_MASK (0x1 << 6) 595 | #define RT5663_V2_EN_IRQ_INLINE_SHIFT 6 596 | #define RT5663_V2_EN_IRQ_INLINE_BYP (0x0 << 6) 597 | #define RT5663_V2_EN_IRQ_INLINE_NOR (0x1 << 6) 598 | 599 | /* GPIO Control 1 (0x00c0) */ 600 | #define RT5663_GP1_PIN_MASK (0x1 << 15) 601 | #define RT5663_GP1_PIN_SHIFT 15 602 | #define RT5663_GP1_PIN_GPIO1 (0x0 << 15) 603 | #define RT5663_GP1_PIN_IRQ (0x1 << 15) 604 | 605 | /* GPIO Control 2 (0x00c1) */ 606 | #define RT5663_GP4_PIN_CONF_MASK (0x1 << 5) 607 | #define RT5663_GP4_PIN_CONF_SHIFT 5 608 | #define RT5663_GP4_PIN_CONF_INPUT (0x0 << 5) 609 | #define RT5663_GP4_PIN_CONF_OUTPUT (0x1 << 5) 610 | 611 | /* GPIO Control 2 (0x00c2) */ 612 | #define RT5663_GP8_PIN_CONF_MASK (0x1 << 13) 613 | #define RT5663_GP8_PIN_CONF_SHIFT 13 614 | #define RT5663_GP8_PIN_CONF_INPUT (0x0 << 13) 615 | #define RT5663_GP8_PIN_CONF_OUTPUT (0x1 << 13) 616 | 617 | /* 4 Buttons Inline Command Function 1 (0x00df) */ 618 | #define RT5663_4BTN_CLK_DEB_MASK (0x3 << 2) 619 | #define RT5663_4BTN_CLK_DEB_SHIFT 2 620 | #define RT5663_4BTN_CLK_DEB_8MS (0x0 << 2) 621 | #define RT5663_4BTN_CLK_DEB_16MS (0x1 << 2) 622 | #define RT5663_4BTN_CLK_DEB_32MS (0x2 << 2) 623 | #define RT5663_4BTN_CLK_DEB_65MS (0x3 << 2) 624 | 625 | /* Inline Command Function 6 (0x00e0) */ 626 | #define RT5663_EN_4BTN_INL_MASK (0x1 << 15) 627 | #define RT5663_EN_4BTN_INL_SHIFT 15 628 | #define RT5663_EN_4BTN_INL_DIS (0x0 << 15) 629 | #define RT5663_EN_4BTN_INL_EN (0x1 << 15) 630 | #define RT5663_RESET_4BTN_INL_MASK (0x1 << 14) 631 | #define RT5663_RESET_4BTN_INL_SHIFT 14 632 | #define RT5663_RESET_4BTN_INL_RESET (0x0 << 14) 633 | #define RT5663_RESET_4BTN_INL_NOR (0x1 << 14) 634 | 635 | /* Digital Misc Control (0x00fa) */ 636 | #define RT5663_DIG_GATE_CTRL_MASK 0x1 637 | #define RT5663_DIG_GATE_CTRL_SHIFT (0) 638 | #define RT5663_DIG_GATE_CTRL_DIS 0x0 639 | #define RT5663_DIG_GATE_CTRL_EN 0x1 640 | 641 | /* Chopper and Clock control for DAC L (0x013a)*/ 642 | #define RT5663_CKXEN_DAC1_MASK (0x1 << 13) 643 | #define RT5663_CKXEN_DAC1_SHIFT 13 644 | #define RT5663_CKGEN_DAC1_MASK (0x1 << 12) 645 | #define RT5663_CKGEN_DAC1_SHIFT 12 646 | 647 | /* Chopper and Clock control for ADC (0x013b)*/ 648 | #define RT5663_CKXEN_ADCC_MASK (0x1 << 13) 649 | #define RT5663_CKXEN_ADCC_SHIFT 13 650 | #define RT5663_CKGEN_ADCC_MASK (0x1 << 12) 651 | #define RT5663_CKGEN_ADCC_SHIFT 12 652 | 653 | /* HP Behavior Logic Control 2 (0x01db) */ 654 | #define RT5663_HP_SIG_SRC1_MASK (0x3) 655 | #define RT5663_HP_SIG_SRC1_SHIFT 0 656 | #define RT5663_HP_SIG_SRC1_HP_DC (0x0) 657 | #define RT5663_HP_SIG_SRC1_HP_CALIB (0x1) 658 | #define RT5663_HP_SIG_SRC1_REG (0x2) 659 | #define RT5663_HP_SIG_SRC1_SILENCE (0x3) 660 | 661 | /* RT5663 specific register */ 662 | #define RT5663_HP_OUT_EN 0x0002 663 | #define RT5663_HP_LCH_DRE 0x0005 664 | #define RT5663_HP_RCH_DRE 0x0006 665 | #define RT5663_CALIB_BST 0x000a 666 | #define RT5663_RECMIX 0x0010 667 | #define RT5663_SIL_DET_CTL 0x0015 668 | #define RT5663_PWR_SAV_SILDET 0x0016 669 | #define RT5663_SIDETONE_CTL 0x0018 670 | #define RT5663_STO1_DAC_DIG_VOL 0x0019 671 | #define RT5663_STO1_ADC_DIG_VOL 0x001c 672 | #define RT5663_STO1_BOOST 0x001f 673 | #define RT5663_HP_IMP_GAIN_1 0x0022 674 | #define RT5663_HP_IMP_GAIN_2 0x0023 675 | #define RT5663_STO1_ADC_MIXER 0x0026 676 | #define RT5663_AD_DA_MIXER 0x0029 677 | #define RT5663_STO_DAC_MIXER 0x002a 678 | #define RT5663_DIG_SIDE_MIXER 0x002c 679 | #define RT5663_BYPASS_STO_DAC 0x002d 680 | #define RT5663_CALIB_REC_MIX 0x0040 681 | #define RT5663_PWR_DIG_1 0x0061 682 | #define RT5663_PWR_DIG_2 0x0062 683 | #define RT5663_PWR_ANLG_1 0x0063 684 | #define RT5663_PWR_ANLG_2 0x0064 685 | #define RT5663_PWR_ANLG_3 0x0065 686 | #define RT5663_PWR_MIXER 0x0066 687 | #define RT5663_SIG_CLK_DET 0x006b 688 | #define RT5663_PRE_DIV_GATING_1 0x006e 689 | #define RT5663_PRE_DIV_GATING_2 0x006f 690 | #define RT5663_I2S1_SDP 0x0070 691 | #define RT5663_ADDA_CLK_1 0x0073 692 | #define RT5663_ADDA_RST 0x0074 693 | #define RT5663_FRAC_DIV_1 0x0075 694 | #define RT5663_FRAC_DIV_2 0x0076 695 | #define RT5663_TDM_1 0x0077 696 | #define RT5663_TDM_2 0x0078 697 | #define RT5663_TDM_3 0x0079 698 | #define RT5663_TDM_4 0x007a 699 | #define RT5663_TDM_5 0x007b 700 | #define RT5663_TDM_6 0x007c 701 | #define RT5663_TDM_7 0x007d 702 | #define RT5663_TDM_8 0x007e 703 | #define RT5663_TDM_9 0x007f 704 | #define RT5663_GLB_CLK 0x0080 705 | #define RT5663_PLL_1 0x0081 706 | #define RT5663_PLL_2 0x0082 707 | #define RT5663_ASRC_1 0x0083 708 | #define RT5663_ASRC_2 0x0084 709 | #define RT5663_ASRC_4 0x0086 710 | #define RT5663_DUMMY_REG 0x0087 711 | #define RT5663_ASRC_8 0x008a 712 | #define RT5663_ASRC_9 0x008b 713 | #define RT5663_ASRC_11 0x008c 714 | #define RT5663_DEPOP_1 0x008e 715 | #define RT5663_DEPOP_2 0x008f 716 | #define RT5663_DEPOP_3 0x0090 717 | #define RT5663_HP_CHARGE_PUMP_1 0x0091 718 | #define RT5663_HP_CHARGE_PUMP_2 0x0092 719 | #define RT5663_MICBIAS_1 0x0093 720 | #define RT5663_RC_CLK 0x0094 721 | #define RT5663_ASRC_11_2 0x0097 722 | #define RT5663_DUMMY_REG_2 0x0098 723 | #define RT5663_REC_PATH_GAIN 0x009a 724 | #define RT5663_AUTO_1MRC_CLK 0x009f 725 | #define RT5663_ADC_EQ_1 0x00ae 726 | #define RT5663_ADC_EQ_2 0x00af 727 | #define RT5663_IRQ_1 0x00b6 728 | #define RT5663_IRQ_2 0x00b7 729 | #define RT5663_IRQ_3 0x00b8 730 | #define RT5663_IRQ_4 0x00ba 731 | #define RT5663_IRQ_5 0x00bb 732 | #define RT5663_INT_ST_1 0x00be 733 | #define RT5663_INT_ST_2 0x00bf 734 | #define RT5663_GPIO_1 0x00c0 735 | #define RT5663_GPIO_2 0x00c1 736 | #define RT5663_GPIO_STA1 0x00c5 737 | #define RT5663_SIN_GEN_1 0x00cb 738 | #define RT5663_SIN_GEN_2 0x00cc 739 | #define RT5663_SIN_GEN_3 0x00cd 740 | #define RT5663_SOF_VOL_ZC1 0x00d9 741 | #define RT5663_IL_CMD_1 0x00db 742 | #define RT5663_IL_CMD_2 0x00dc 743 | #define RT5663_IL_CMD_3 0x00dd 744 | #define RT5663_IL_CMD_4 0x00de 745 | #define RT5663_IL_CMD_5 0x00df 746 | #define RT5663_IL_CMD_6 0x00e0 747 | #define RT5663_IL_CMD_7 0x00e1 748 | #define RT5663_IL_CMD_8 0x00e2 749 | #define RT5663_IL_CMD_PWRSAV1 0x00e4 750 | #define RT5663_IL_CMD_PWRSAV2 0x00e5 751 | #define RT5663_EM_JACK_TYPE_1 0x00e6 752 | #define RT5663_EM_JACK_TYPE_2 0x00e7 753 | #define RT5663_EM_JACK_TYPE_3 0x00e8 754 | #define RT5663_EM_JACK_TYPE_4 0x00e9 755 | #define RT5663_EM_JACK_TYPE_5 0x00ea 756 | #define RT5663_EM_JACK_TYPE_6 0x00eb 757 | #define RT5663_STO1_HPF_ADJ1 0x00ec 758 | #define RT5663_STO1_HPF_ADJ2 0x00ed 759 | #define RT5663_FAST_OFF_MICBIAS 0x00f4 760 | #define RT5663_JD_CTRL1 0x00f6 761 | #define RT5663_JD_CTRL2 0x00f8 762 | #define RT5663_DIG_MISC 0x00fa 763 | #define RT5663_DIG_VOL_ZCD 0x0100 764 | #define RT5663_ANA_BIAS_CUR_1 0x0108 765 | #define RT5663_ANA_BIAS_CUR_2 0x0109 766 | #define RT5663_ANA_BIAS_CUR_3 0x010a 767 | #define RT5663_ANA_BIAS_CUR_4 0x010b 768 | #define RT5663_ANA_BIAS_CUR_5 0x010c 769 | #define RT5663_ANA_BIAS_CUR_6 0x010d 770 | #define RT5663_BIAS_CUR_5 0x010e 771 | #define RT5663_BIAS_CUR_6 0x010f 772 | #define RT5663_BIAS_CUR_7 0x0110 773 | #define RT5663_BIAS_CUR_8 0x0111 774 | #define RT5663_DACREF_LDO 0x0112 775 | #define RT5663_DUMMY_REG_3 0x0113 776 | #define RT5663_BIAS_CUR_9 0x0114 777 | #define RT5663_DUMMY_REG_4 0x0116 778 | #define RT5663_VREFADJ_OP 0x0117 779 | #define RT5663_VREF_RECMIX 0x0118 780 | #define RT5663_CHARGE_PUMP_1 0x0125 781 | #define RT5663_CHARGE_PUMP_1_2 0x0126 782 | #define RT5663_CHARGE_PUMP_1_3 0x0127 783 | #define RT5663_CHARGE_PUMP_2 0x0128 784 | #define RT5663_DIG_IN_PIN1 0x0132 785 | #define RT5663_PAD_DRV_CTL 0x0137 786 | #define RT5663_PLL_INT_REG 0x0139 787 | #define RT5663_CHOP_DAC_L 0x013a 788 | #define RT5663_CHOP_ADC 0x013b 789 | #define RT5663_CALIB_ADC 0x013c 790 | #define RT5663_CHOP_DAC_R 0x013d 791 | #define RT5663_DUMMY_CTL_DACLR 0x013e 792 | #define RT5663_DUMMY_REG_5 0x0140 793 | #define RT5663_SOFT_RAMP 0x0141 794 | #define RT5663_TEST_MODE_1 0x0144 795 | #define RT5663_TEST_MODE_2 0x0145 796 | #define RT5663_TEST_MODE_3 0x0146 797 | #define RT5663_TEST_MODE_4 0x0147 798 | #define RT5663_TEST_MODE_5 0x0148 799 | #define RT5663_STO_DRE_1 0x0160 800 | #define RT5663_STO_DRE_2 0x0161 801 | #define RT5663_STO_DRE_3 0x0162 802 | #define RT5663_STO_DRE_4 0x0163 803 | #define RT5663_STO_DRE_5 0x0164 804 | #define RT5663_STO_DRE_6 0x0165 805 | #define RT5663_STO_DRE_7 0x0166 806 | #define RT5663_STO_DRE_8 0x0167 807 | #define RT5663_STO_DRE_9 0x0168 808 | #define RT5663_STO_DRE_10 0x0169 809 | #define RT5663_MIC_DECRO_1 0x0180 810 | #define RT5663_MIC_DECRO_2 0x0181 811 | #define RT5663_MIC_DECRO_3 0x0182 812 | #define RT5663_MIC_DECRO_4 0x0183 813 | #define RT5663_MIC_DECRO_5 0x0184 814 | #define RT5663_MIC_DECRO_6 0x0185 815 | #define RT5663_HP_DECRO_1 0x01b0 816 | #define RT5663_HP_DECRO_2 0x01b1 817 | #define RT5663_HP_DECRO_3 0x01b2 818 | #define RT5663_HP_DECRO_4 0x01b3 819 | #define RT5663_HP_DECOUP 0x01b4 820 | #define RT5663_HP_IMP_SEN_MAP8 0x01b5 821 | #define RT5663_HP_IMP_SEN_MAP9 0x01b6 822 | #define RT5663_HP_IMP_SEN_MAP10 0x01b7 823 | #define RT5663_HP_IMP_SEN_MAP11 0x01b8 824 | #define RT5663_HP_IMP_SEN_1 0x01c0 825 | #define RT5663_HP_IMP_SEN_2 0x01c1 826 | #define RT5663_HP_IMP_SEN_3 0x01c2 827 | #define RT5663_HP_IMP_SEN_4 0x01c3 828 | #define RT5663_HP_IMP_SEN_5 0x01c4 829 | #define RT5663_HP_IMP_SEN_6 0x01c5 830 | #define RT5663_HP_IMP_SEN_7 0x01c6 831 | #define RT5663_HP_IMP_SEN_8 0x01c7 832 | #define RT5663_HP_IMP_SEN_9 0x01c8 833 | #define RT5663_HP_IMP_SEN_10 0x01c9 834 | #define RT5663_HP_IMP_SEN_11 0x01ca 835 | #define RT5663_HP_IMP_SEN_12 0x01cb 836 | #define RT5663_HP_IMP_SEN_13 0x01cc 837 | #define RT5663_HP_IMP_SEN_14 0x01cd 838 | #define RT5663_HP_IMP_SEN_15 0x01ce 839 | #define RT5663_HP_IMP_SEN_16 0x01cf 840 | #define RT5663_HP_IMP_SEN_17 0x01d0 841 | #define RT5663_HP_IMP_SEN_18 0x01d1 842 | #define RT5663_HP_IMP_SEN_19 0x01d2 843 | #define RT5663_HP_IMPSEN_DIG5 0x01d3 844 | #define RT5663_HP_IMPSEN_MAP1 0x01d4 845 | #define RT5663_HP_IMPSEN_MAP2 0x01d5 846 | #define RT5663_HP_IMPSEN_MAP3 0x01d6 847 | #define RT5663_HP_IMPSEN_MAP4 0x01d7 848 | #define RT5663_HP_IMPSEN_MAP5 0x01d8 849 | #define RT5663_HP_IMPSEN_MAP7 0x01d9 850 | #define RT5663_HP_LOGIC_1 0x01da 851 | #define RT5663_HP_LOGIC_2 0x01db 852 | #define RT5663_HP_CALIB_1 0x01dd 853 | #define RT5663_HP_CALIB_1_1 0x01de 854 | #define RT5663_HP_CALIB_2 0x01df 855 | #define RT5663_HP_CALIB_3 0x01e0 856 | #define RT5663_HP_CALIB_4 0x01e1 857 | #define RT5663_HP_CALIB_5 0x01e2 858 | #define RT5663_HP_CALIB_5_1 0x01e3 859 | #define RT5663_HP_CALIB_6 0x01e4 860 | #define RT5663_HP_CALIB_7 0x01e5 861 | #define RT5663_HP_CALIB_9 0x01e6 862 | #define RT5663_HP_CALIB_10 0x01e7 863 | #define RT5663_HP_CALIB_11 0x01e8 864 | #define RT5663_HP_CALIB_ST1 0x01ea 865 | #define RT5663_HP_CALIB_ST2 0x01eb 866 | #define RT5663_HP_CALIB_ST3 0x01ec 867 | #define RT5663_HP_CALIB_ST4 0x01ed 868 | #define RT5663_HP_CALIB_ST5 0x01ee 869 | #define RT5663_HP_CALIB_ST6 0x01ef 870 | #define RT5663_HP_CALIB_ST7 0x01f0 871 | #define RT5663_HP_CALIB_ST8 0x01f1 872 | #define RT5663_HP_CALIB_ST9 0x01f2 873 | #define RT5663_HP_AMP_DET 0x0200 874 | #define RT5663_DUMMY_REG_6 0x0201 875 | #define RT5663_HP_BIAS 0x0202 876 | #define RT5663_CBJ_1 0x0250 877 | #define RT5663_CBJ_2 0x0251 878 | #define RT5663_CBJ_3 0x0252 879 | #define RT5663_DUMMY_1 0x02fa 880 | #define RT5663_DUMMY_2 0x02fb 881 | #define RT5663_DUMMY_3 0x02fc 882 | #define RT5663_ANA_JD 0x0300 883 | #define RT5663_ADC_LCH_LPF1_A1 0x03d0 884 | #define RT5663_ADC_RCH_LPF1_A1 0x03d1 885 | #define RT5663_ADC_LCH_LPF1_H0 0x03d2 886 | #define RT5663_ADC_RCH_LPF1_H0 0x03d3 887 | #define RT5663_ADC_LCH_BPF1_A1 0x03d4 888 | #define RT5663_ADC_RCH_BPF1_A1 0x03d5 889 | #define RT5663_ADC_LCH_BPF1_A2 0x03d6 890 | #define RT5663_ADC_RCH_BPF1_A2 0x03d7 891 | #define RT5663_ADC_LCH_BPF1_H0 0x03d8 892 | #define RT5663_ADC_RCH_BPF1_H0 0x03d9 893 | #define RT5663_ADC_LCH_BPF2_A1 0x03da 894 | #define RT5663_ADC_RCH_BPF2_A1 0x03db 895 | #define RT5663_ADC_LCH_BPF2_A2 0x03dc 896 | #define RT5663_ADC_RCH_BPF2_A2 0x03dd 897 | #define RT5663_ADC_LCH_BPF2_H0 0x03de 898 | #define RT5663_ADC_RCH_BPF2_H0 0x03df 899 | #define RT5663_ADC_LCH_BPF3_A1 0x03e0 900 | #define RT5663_ADC_RCH_BPF3_A1 0x03e1 901 | #define RT5663_ADC_LCH_BPF3_A2 0x03e2 902 | #define RT5663_ADC_RCH_BPF3_A2 0x03e3 903 | #define RT5663_ADC_LCH_BPF3_H0 0x03e4 904 | #define RT5663_ADC_RCH_BPF3_H0 0x03e5 905 | #define RT5663_ADC_LCH_BPF4_A1 0x03e6 906 | #define RT5663_ADC_RCH_BPF4_A1 0x03e7 907 | #define RT5663_ADC_LCH_BPF4_A2 0x03e8 908 | #define RT5663_ADC_RCH_BPF4_A2 0x03e9 909 | #define RT5663_ADC_LCH_BPF4_H0 0x03ea 910 | #define RT5663_ADC_RCH_BPF4_H0 0x03eb 911 | #define RT5663_ADC_LCH_HPF1_A1 0x03ec 912 | #define RT5663_ADC_RCH_HPF1_A1 0x03ed 913 | #define RT5663_ADC_LCH_HPF1_H0 0x03ee 914 | #define RT5663_ADC_RCH_HPF1_H0 0x03ef 915 | #define RT5663_ADC_EQ_PRE_VOL_L 0x03f0 916 | #define RT5663_ADC_EQ_PRE_VOL_R 0x03f1 917 | #define RT5663_ADC_EQ_POST_VOL_L 0x03f2 918 | #define RT5663_ADC_EQ_POST_VOL_R 0x03f3 919 | 920 | /* RECMIX Control (0x0010) */ 921 | #define RT5663_RECMIX1_BST1_MASK (0x1) 922 | #define RT5663_RECMIX1_BST1_SHIFT 0 923 | #define RT5663_RECMIX1_BST1_ON (0x0) 924 | #define RT5663_RECMIX1_BST1_OFF (0x1) 925 | 926 | /* Bypass Stereo1 DAC Mixer Control (0x002d) */ 927 | #define RT5663_DACL1_SRC_MASK (0x1 << 3) 928 | #define RT5663_DACL1_SRC_SHIFT 3 929 | #define RT5663_DACR1_SRC_MASK (0x1 << 2) 930 | #define RT5663_DACR1_SRC_SHIFT 2 931 | 932 | /* TDM control 2 (0x0078) */ 933 | #define RT5663_DATA_SWAP_ADCDAT1_MASK (0x3 << 14) 934 | #define RT5663_DATA_SWAP_ADCDAT1_SHIFT 14 935 | #define RT5663_DATA_SWAP_ADCDAT1_LR (0x0 << 14) 936 | #define RT5663_DATA_SWAP_ADCDAT1_RL (0x1 << 14) 937 | #define RT5663_DATA_SWAP_ADCDAT1_LL (0x2 << 14) 938 | #define RT5663_DATA_SWAP_ADCDAT1_RR (0x3 << 14) 939 | 940 | /* TDM control 5 (0x007b) */ 941 | #define RT5663_TDM_LENGTN_MASK (0x3) 942 | #define RT5663_TDM_LENGTN_SHIFT 0 943 | #define RT5663_TDM_LENGTN_16 (0x0) 944 | #define RT5663_TDM_LENGTN_20 (0x1) 945 | #define RT5663_TDM_LENGTN_24 (0x2) 946 | #define RT5663_TDM_LENGTN_32 (0x3) 947 | 948 | /* PLL tracking mode 1 (0x0083) */ 949 | #define RT5663_I2S1_ASRC_MASK (0x1 << 11) 950 | #define RT5663_I2S1_ASRC_SHIFT 11 951 | #define RT5663_DAC_STO1_ASRC_MASK (0x1 << 10) 952 | #define RT5663_DAC_STO1_ASRC_SHIFT 10 953 | #define RT5663_ADC_STO1_ASRC_MASK (0x1 << 3) 954 | #define RT5663_ADC_STO1_ASRC_SHIFT 3 955 | 956 | /* PLL tracking mode 2 (0x0084)*/ 957 | #define RT5663_DA_STO1_TRACK_MASK (0x7 << 12) 958 | #define RT5663_DA_STO1_TRACK_SHIFT 12 959 | #define RT5663_DA_STO1_TRACK_SYSCLK (0x0 << 12) 960 | #define RT5663_DA_STO1_TRACK_I2S1 (0x1 << 12) 961 | #define RT5663_AD_STO1_TRACK_MASK (0x7) 962 | #define RT5663_AD_STO1_TRACK_SHIFT 0 963 | #define RT5663_AD_STO1_TRACK_SYSCLK (0x0) 964 | #define RT5663_AD_STO1_TRACK_I2S1 (0x1) 965 | 966 | /* HPOUT Charge pump control 1 (0x0091) */ 967 | #define RT5663_SI_HP_MASK (0x1 << 12) 968 | #define RT5663_SI_HP_SHIFT 12 969 | #define RT5663_SI_HP_EN (0x1 << 12) 970 | #define RT5663_SI_HP_DIS (0x0 << 12) 971 | 972 | /* GPIO Control 2 (0x00b6) */ 973 | #define RT5663_GP1_PIN_CONF_MASK (0x1 << 2) 974 | #define RT5663_GP1_PIN_CONF_SHIFT 2 975 | #define RT5663_GP1_PIN_CONF_OUTPUT (0x1 << 2) 976 | #define RT5663_GP1_PIN_CONF_INPUT (0x0 << 2) 977 | 978 | /* GPIO Control 2 (0x00b7) */ 979 | #define RT5663_EN_IRQ_INLINE_MASK (0x1 << 3) 980 | #define RT5663_EN_IRQ_INLINE_SHIFT 3 981 | #define RT5663_EN_IRQ_INLINE_NOR (0x1 << 3) 982 | #define RT5663_EN_IRQ_INLINE_BYP (0x0 << 3) 983 | 984 | /* GPIO Control 1 (0x00c0) */ 985 | #define RT5663_GPIO1_TYPE_MASK (0x1 << 15) 986 | #define RT5663_GPIO1_TYPE_SHIFT 15 987 | #define RT5663_GPIO1_TYPE_EN (0x1 << 15) 988 | #define RT5663_GPIO1_TYPE_DIS (0x0 << 15) 989 | 990 | /* IRQ Control 1 (0x00c1) */ 991 | #define RT5663_EN_IRQ_JD1_MASK (0x1 << 6) 992 | #define RT5663_EN_IRQ_JD1_SHIFT 6 993 | #define RT5663_EN_IRQ_JD1_EN (0x1 << 6) 994 | #define RT5663_EN_IRQ_JD1_DIS (0x0 << 6) 995 | #define RT5663_SEL_GPIO1_MASK (0x1 << 2) 996 | #define RT5663_SEL_GPIO1_SHIFT 6 997 | #define RT5663_SEL_GPIO1_EN (0x1 << 2) 998 | #define RT5663_SEL_GPIO1_DIS (0x0 << 2) 999 | 1000 | /* Inline Command Function 2 (0x00dc) */ 1001 | #define RT5663_PWR_MIC_DET_MASK (0x1) 1002 | #define RT5663_PWR_MIC_DET_SHIFT 0 1003 | #define RT5663_PWR_MIC_DET_ON (0x1) 1004 | #define RT5663_PWR_MIC_DET_OFF (0x0) 1005 | 1006 | /* Embeeded Jack and Type Detection Control 1 (0x00e6)*/ 1007 | #define RT5663_CBJ_DET_MASK (0x1 << 15) 1008 | #define RT5663_CBJ_DET_SHIFT 15 1009 | #define RT5663_CBJ_DET_DIS (0x0 << 15) 1010 | #define RT5663_CBJ_DET_EN (0x1 << 15) 1011 | #define RT5663_EXT_JD_MASK (0x1 << 11) 1012 | #define RT5663_EXT_JD_SHIFT 11 1013 | #define RT5663_EXT_JD_EN (0x1 << 11) 1014 | #define RT5663_EXT_JD_DIS (0x0 << 11) 1015 | #define RT5663_POL_EXT_JD_MASK (0x1 << 10) 1016 | #define RT5663_POL_EXT_JD_SHIFT 10 1017 | #define RT5663_POL_EXT_JD_EN (0x1 << 10) 1018 | #define RT5663_POL_EXT_JD_DIS (0x0 << 10) 1019 | #define RT5663_EM_JD_MASK (0x1 << 7) 1020 | #define RT5663_EM_JD_SHIFT 7 1021 | #define RT5663_EM_JD_NOR (0x1 << 7) 1022 | #define RT5663_EM_JD_RST (0x0 << 7) 1023 | 1024 | /* DACREF LDO Control (0x0112)*/ 1025 | #define RT5663_PWR_LDO_DACREFL_MASK (0x1 << 9) 1026 | #define RT5663_PWR_LDO_DACREFL_SHIFT 9 1027 | #define RT5663_PWR_LDO_DACREFR_MASK (0x1 << 1) 1028 | #define RT5663_PWR_LDO_DACREFR_SHIFT 1 1029 | 1030 | /* Stereo Dynamic Range Enhancement Control 9 (0x0168, 0x0169)*/ 1031 | #define RT5663_DRE_GAIN_HP_MASK (0x1f) 1032 | #define RT5663_DRE_GAIN_HP_SHIFT 0 1033 | 1034 | /* Combo Jack Control (0x0250) */ 1035 | #define RT5663_INBUF_CBJ_BST1_MASK (0x1 << 11) 1036 | #define RT5663_INBUF_CBJ_BST1_SHIFT 11 1037 | #define RT5663_INBUF_CBJ_BST1_ON (0x1 << 11) 1038 | #define RT5663_INBUF_CBJ_BST1_OFF (0x0 << 11) 1039 | #define RT5663_CBJ_SENSE_BST1_MASK (0x1 << 10) 1040 | #define RT5663_CBJ_SENSE_BST1_SHIFT 10 1041 | #define RT5663_CBJ_SENSE_BST1_L (0x1 << 10) 1042 | #define RT5663_CBJ_SENSE_BST1_R (0x0 << 10) 1043 | 1044 | /* Combo Jack Control (0x0251) */ 1045 | #define RT5663_GAIN_BST1_MASK (0xf) 1046 | #define RT5663_GAIN_BST1_SHIFT 0 1047 | 1048 | /* Dummy register 1 (0x02fa) */ 1049 | #define RT5663_EMB_CLK_MASK (0x1 << 9) 1050 | #define RT5663_EMB_CLK_SHIFT 9 1051 | #define RT5663_EMB_CLK_EN (0x1 << 9) 1052 | #define RT5663_EMB_CLK_DIS (0x0 << 9) 1053 | #define RT5663_HPA_CPL_BIAS_MASK (0x7 << 6) 1054 | #define RT5663_HPA_CPL_BIAS_SHIFT 6 1055 | #define RT5663_HPA_CPL_BIAS_0_5 (0x0 << 6) 1056 | #define RT5663_HPA_CPL_BIAS_1 (0x1 << 6) 1057 | #define RT5663_HPA_CPL_BIAS_2 (0x2 << 6) 1058 | #define RT5663_HPA_CPL_BIAS_3 (0x3 << 6) 1059 | #define RT5663_HPA_CPL_BIAS_4_1 (0x4 << 6) 1060 | #define RT5663_HPA_CPL_BIAS_4_2 (0x5 << 6) 1061 | #define RT5663_HPA_CPL_BIAS_6 (0x6 << 6) 1062 | #define RT5663_HPA_CPL_BIAS_8 (0x7 << 6) 1063 | #define RT5663_HPA_CPR_BIAS_MASK (0x7 << 3) 1064 | #define RT5663_HPA_CPR_BIAS_SHIFT 3 1065 | #define RT5663_HPA_CPR_BIAS_0_5 (0x0 << 3) 1066 | #define RT5663_HPA_CPR_BIAS_1 (0x1 << 3) 1067 | #define RT5663_HPA_CPR_BIAS_2 (0x2 << 3) 1068 | #define RT5663_HPA_CPR_BIAS_3 (0x3 << 3) 1069 | #define RT5663_HPA_CPR_BIAS_4_1 (0x4 << 3) 1070 | #define RT5663_HPA_CPR_BIAS_4_2 (0x5 << 3) 1071 | #define RT5663_HPA_CPR_BIAS_6 (0x6 << 3) 1072 | #define RT5663_HPA_CPR_BIAS_8 (0x7 << 3) 1073 | #define RT5663_DUMMY_BIAS_MASK (0x7) 1074 | #define RT5663_DUMMY_BIAS_SHIFT 0 1075 | #define RT5663_DUMMY_BIAS_0_5 (0x0) 1076 | #define RT5663_DUMMY_BIAS_1 (0x1) 1077 | #define RT5663_DUMMY_BIAS_2 (0x2) 1078 | #define RT5663_DUMMY_BIAS_3 (0x3) 1079 | #define RT5663_DUMMY_BIAS_4_1 (0x4) 1080 | #define RT5663_DUMMY_BIAS_4_2 (0x5) 1081 | #define RT5663_DUMMY_BIAS_6 (0x6) 1082 | #define RT5663_DUMMY_BIAS_8 (0x7) 1083 | 1084 | 1085 | /* System Clock Source */ 1086 | enum { 1087 | RT5663_SCLK_S_MCLK, 1088 | RT5663_SCLK_S_PLL1, 1089 | RT5663_SCLK_S_RCCLK, 1090 | }; 1091 | 1092 | /* PLL1 Source */ 1093 | enum { 1094 | RT5663_PLL1_S_MCLK, 1095 | RT5663_PLL1_S_BCLK1, 1096 | }; 1097 | 1098 | enum { 1099 | RT5663_AIF, 1100 | RT5663_AIFS, 1101 | }; 1102 | 1103 | /* asrc clock source */ 1104 | enum { 1105 | RT5663_CLK_SEL_SYS = 0x0, 1106 | RT5663_CLK_SEL_I2S1_ASRC = 0x1, 1107 | }; 1108 | 1109 | /* filter mask */ 1110 | enum { 1111 | RT5663_DA_STEREO_FILTER = 0x1, 1112 | RT5663_AD_STEREO_FILTER = 0x2, 1113 | }; 1114 | 1115 | #endif -------------------------------------------------------------------------------- /rt5663/rt5663.c: -------------------------------------------------------------------------------- 1 | #define DESCRIPTOR_DEF 2 | #include "rt5663.h" 3 | #include "registers.h" 4 | #include "rl6231.h" 5 | 6 | #define RT5663_DEVICE_ID_2 0x6451 7 | #define RT5663_DEVICE_ID_1 0x6406 8 | 9 | #define RT5663_POWER_ON_DELAY_MS 300 10 | 11 | enum { 12 | CODEC_VER_1, 13 | CODEC_VER_0, 14 | }; 15 | 16 | #define bool int 17 | #define MHz 1000000 18 | 19 | static ULONG Rt5663DebugLevel = 100; 20 | static ULONG Rt5663DebugCatagories = DBG_INIT || DBG_PNP || DBG_IOCTL; 21 | 22 | void rt5663_jackdetect(PRTEK_CONTEXT pDevice); 23 | 24 | NTSTATUS 25 | DriverEntry( 26 | __in PDRIVER_OBJECT DriverObject, 27 | __in PUNICODE_STRING RegistryPath 28 | ) 29 | { 30 | NTSTATUS status = STATUS_SUCCESS; 31 | WDF_DRIVER_CONFIG config; 32 | WDF_OBJECT_ATTRIBUTES attributes; 33 | 34 | RtekPrint(DEBUG_LEVEL_INFO, DBG_INIT, 35 | "Driver Entry\n"); 36 | 37 | WDF_DRIVER_CONFIG_INIT(&config, Rt5663EvtDeviceAdd); 38 | 39 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 40 | 41 | // 42 | // Create a framework driver object to represent our driver. 43 | // 44 | 45 | status = WdfDriverCreate(DriverObject, 46 | RegistryPath, 47 | &attributes, 48 | &config, 49 | WDF_NO_HANDLE 50 | ); 51 | 52 | if (!NT_SUCCESS(status)) 53 | { 54 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_INIT, 55 | "WdfDriverCreate failed with status 0x%x\n", status); 56 | } 57 | 58 | return status; 59 | } 60 | 61 | 62 | static NTSTATUS rt5663_reg_write(PRTEK_CONTEXT pDevice, uint16_t reg, uint16_t data) 63 | { 64 | uint16_t rawdata[2]; 65 | rawdata[0] = RtlUshortByteSwap(reg); 66 | rawdata[1] = RtlUshortByteSwap(data); 67 | return SpbWriteDataSynchronously(&pDevice->I2CContext, rawdata, sizeof(rawdata)); 68 | } 69 | 70 | static NTSTATUS rt5663_reg_read(PRTEK_CONTEXT pDevice, uint16_t reg, uint16_t* data) 71 | { 72 | uint16_t reg_swap = RtlUshortByteSwap(reg); 73 | uint16_t data_swap = 0; 74 | NTSTATUS ret = SpbXferDataSynchronously(&pDevice->I2CContext, ®_swap, sizeof(uint16_t), &data_swap, sizeof(uint16_t)); 75 | *data = RtlUshortByteSwap(data_swap); 76 | return ret; 77 | } 78 | 79 | static NTSTATUS rt5663_reg_update( 80 | _In_ PRTEK_CONTEXT pDevice, 81 | uint16_t reg, 82 | uint16_t mask, 83 | uint16_t val 84 | ) { 85 | uint16_t tmp = 0, orig = 0; 86 | 87 | NTSTATUS status = rt5663_reg_read(pDevice, reg, &orig); 88 | if (!NT_SUCCESS(status)) { 89 | return status; 90 | } 91 | 92 | tmp = orig & ~mask; 93 | tmp |= val & mask; 94 | 95 | if (tmp != orig) { 96 | status = rt5663_reg_write(pDevice, reg, tmp); 97 | } 98 | return status; 99 | } 100 | 101 | #define rt5663_widget_update rt5663_reg_update 102 | 103 | static NTSTATUS rt5663_reg_burstWrite(PRTEK_CONTEXT pDevice, struct reg* regs, int regCount) { 104 | NTSTATUS status = STATUS_NO_MEMORY; 105 | for (int i = 0; i < regCount; i++) { 106 | struct reg* regToSet = ®s[i]; 107 | status = rt5663_reg_write(pDevice, regToSet->reg, regToSet->val); 108 | if (!NT_SUCCESS(status)) { 109 | return status; 110 | } 111 | } 112 | return status; 113 | } 114 | 115 | static void msleep(unsigned int msec) { 116 | LARGE_INTEGER delay; 117 | delay.QuadPart = -10 * 1000 * msec; 118 | KeDelayExecutionThread(KernelMode, FALSE, &delay); 119 | } 120 | 121 | static void rt5663_set_bias_level(PRTEK_CONTEXT pDevice, 122 | enum snd_bias_level level){ 123 | switch (level) { 124 | case SND_BIAS_ON: 125 | rt5663_reg_update(pDevice, RT5663_PWR_ANLG_1, 126 | RT5663_PWR_FV1_MASK | RT5663_PWR_FV2_MASK, 127 | RT5663_PWR_FV1 | RT5663_PWR_FV2); 128 | break; 129 | 130 | case SND_BIAS_PREPARE: 131 | break; 132 | 133 | case SND_BIAS_STANDBY: 134 | rt5663_reg_update(pDevice, RT5663_PWR_ANLG_1, 135 | RT5663_PWR_VREF1_MASK | RT5663_PWR_VREF2_MASK | 136 | RT5663_PWR_FV1_MASK | RT5663_PWR_FV2_MASK | 137 | RT5663_PWR_MB_MASK, RT5663_PWR_VREF1 | 138 | RT5663_PWR_VREF2 | RT5663_PWR_MB); 139 | msleep(10); 140 | break; 141 | 142 | case SND_BIAS_OFF: 143 | if (pDevice->CodecVer != SND_JACK_HEADSET) 144 | rt5663_reg_update(pDevice, 145 | RT5663_PWR_ANLG_1, 146 | RT5663_PWR_VREF1_MASK | RT5663_PWR_VREF2_MASK | 147 | RT5663_PWR_FV1 | RT5663_PWR_FV2 | 148 | RT5663_PWR_MB_MASK, 0); 149 | else 150 | rt5663_reg_update(pDevice, 151 | RT5663_PWR_ANLG_1, 152 | RT5663_PWR_FV1_MASK | RT5663_PWR_FV2_MASK, 153 | RT5663_PWR_FV1 | RT5663_PWR_FV2); 154 | break; 155 | 156 | default: 157 | break; 158 | } 159 | } 160 | 161 | static void rt5663_hp_event(PRTEK_CONTEXT pDevice, int event) 162 | { 163 | switch (event) { 164 | case SND_DAPM_POST_PMU: 165 | if (pDevice->CodecVer == CODEC_VER_0) { 166 | rt5663_reg_update(pDevice, 167 | RT5663_DACREF_LDO, 0x3e0e, 0x3a0a); 168 | rt5663_reg_write(pDevice, RT5663_DEPOP_2, 0x3003); 169 | rt5663_reg_update(pDevice, RT5663_HP_CHARGE_PUMP_1, 170 | RT5663_OVCD_HP_MASK, RT5663_OVCD_HP_DIS); 171 | rt5663_reg_write(pDevice, RT5663_HP_CHARGE_PUMP_2, 0x1371); 172 | rt5663_reg_write(pDevice, RT5663_HP_BIAS, 0xabba); 173 | rt5663_reg_write(pDevice, RT5663_CHARGE_PUMP_1, 0x2224); 174 | rt5663_reg_write(pDevice, RT5663_ANA_BIAS_CUR_1, 0x7766); 175 | rt5663_reg_write(pDevice, RT5663_HP_BIAS, 0xafaa); 176 | rt5663_reg_write(pDevice, RT5663_CHARGE_PUMP_2, 0x7777); 177 | rt5663_reg_update(pDevice, RT5663_STO_DRE_1, 0x8000, 178 | 0x8000); 179 | rt5663_reg_update(pDevice, RT5663_DEPOP_1, 0x3000, 180 | 0x3000); 181 | rt5663_reg_update(pDevice, 182 | RT5663_DIG_VOL_ZCD, 0x00c0, 0x0080); 183 | } 184 | break; 185 | 186 | case SND_DAPM_PRE_PMD: 187 | if (pDevice->CodecVer == CODEC_VER_0) { 188 | rt5663_reg_update(pDevice, RT5663_DEPOP_1, 0x3000, 0x0); 189 | rt5663_reg_update(pDevice, RT5663_HP_CHARGE_PUMP_1, 190 | RT5663_OVCD_HP_MASK, RT5663_OVCD_HP_EN); 191 | rt5663_reg_update(pDevice, 192 | RT5663_DACREF_LDO, 0x3e0e, 0); 193 | rt5663_reg_update(pDevice, 194 | RT5663_DIG_VOL_ZCD, 0x00c0, 0); 195 | } 196 | break; 197 | 198 | default: 199 | break; 200 | } 201 | } 202 | 203 | static void rt5663_charge_pump_event(PRTEK_CONTEXT pDevice, int event) { 204 | switch (event){ 205 | case SND_DAPM_PRE_PMU: 206 | if (pDevice->CodecVer == CODEC_VER_0) { 207 | rt5663_reg_update(pDevice, RT5663_DEPOP_1, 0x0030, 208 | 0x0030); 209 | rt5663_reg_update(pDevice, RT5663_DEPOP_1, 0x0003, 210 | 0x0003); 211 | } 212 | break; 213 | case SND_DAPM_POST_PMD: 214 | if (pDevice->CodecVer == CODEC_VER_0) { 215 | rt5663_reg_update(pDevice, RT5663_DEPOP_1, 0x0003, 0); 216 | rt5663_reg_update(pDevice, RT5663_DEPOP_1, 0x0030, 0); 217 | } 218 | break; 219 | default: 220 | break; 221 | } 222 | } 223 | 224 | static void rt5663_pre_div_power(PRTEK_CONTEXT pDevice, int event) 225 | { 226 | switch (event) { 227 | case SND_DAPM_POST_PMU: 228 | rt5663_reg_write(pDevice, RT5663_PRE_DIV_GATING_1, 0xff00); 229 | rt5663_reg_write(pDevice, RT5663_PRE_DIV_GATING_2, 0xfffc); 230 | break; 231 | 232 | case SND_DAPM_PRE_PMD: 233 | rt5663_reg_write(pDevice, RT5663_PRE_DIV_GATING_1, 0x0000); 234 | rt5663_reg_write(pDevice, RT5663_PRE_DIV_GATING_2, 0x0000); 235 | break; 236 | default: 237 | break; 238 | } 239 | } 240 | 241 | void rt5663_enable(PRTEK_CONTEXT pDevice) { 242 | { //hw params 243 | int pre_div = rl6231_get_clk_info(24576000, 48000); 244 | 245 | unsigned int val_len = RT5663_I2S_DL_16; 246 | rt5663_widget_update(pDevice, RT5663_I2S1_SDP, RT5663_I2S_DL_MASK, val_len); 247 | 248 | rt5663_widget_update(pDevice, RT5663_ADDA_CLK_1, 249 | RT5663_I2S_PD1_MASK, pre_div << RT5663_I2S_PD1_SHIFT); 250 | } 251 | 252 | rt5663_set_bias_level(pDevice, SND_BIAS_STANDBY); 253 | rt5663_set_bias_level(pDevice, SND_BIAS_PREPARE); 254 | 255 | rt5663_charge_pump_event(pDevice, SND_DAPM_PRE_PMU); 256 | 257 | rt5663_pre_div_power(pDevice, SND_DAPM_POST_PMU); 258 | 259 | { 260 | //set round 3 261 | 262 | //DAC Mixer 263 | rt5663_widget_update(pDevice, RT5663_PWR_DIG_1, 264 | RT5663_PWR_DAC_L1 | RT5663_PWR_DAC_R1 | RT5663_PWR_I2S1, 265 | RT5663_PWR_DAC_L1 | RT5663_PWR_DAC_R1 | RT5663_PWR_I2S1); 266 | rt5663_widget_update(pDevice, RT5663_PWR_DIG_2, 267 | RT5663_PWR_DAC_S1F, 268 | RT5663_PWR_DAC_S1F); 269 | 270 | //ASRC 271 | rt5663_widget_update(pDevice, RT5663_ASRC_1, 272 | RT5663_I2S1_ASRC_MASK | RT5663_DAC_STO1_ASRC_MASK, 273 | RT5663_I2S1_ASRC_MASK | RT5663_DAC_STO1_ASRC_MASK); 274 | } 275 | 276 | rt5663_hp_event(pDevice, SND_DAPM_POST_PMU); 277 | 278 | rt5663_set_bias_level(pDevice, SND_BIAS_ON); 279 | 280 | { //defaults (v1) 281 | //set round 4 282 | 283 | //DAC Mixer 284 | rt5663_widget_update(pDevice, RT5663_PWR_DIG_1, 285 | RT5663_PWR_ADC_L1, 286 | RT5663_PWR_ADC_L1); 287 | rt5663_widget_update(pDevice, RT5663_PWR_DIG_2, 288 | RT5663_PWR_ADC_S1F, 289 | RT5663_PWR_ADC_S1F); 290 | 291 | rt5663_widget_update(pDevice, RT5663_PWR_ANLG_2, 292 | RT5663_PWR_RECMIX1, 293 | RT5663_PWR_RECMIX1); 294 | 295 | //ASRC 296 | rt5663_widget_update(pDevice, RT5663_ASRC_1, 297 | RT5663_ADC_STO1_ASRC_MASK, 298 | RT5663_ADC_STO1_ASRC_MASK); 299 | 300 | //ADC Mixer 301 | rt5663_widget_update(pDevice, 302 | RT5663_CHOP_ADC, 303 | RT5663_CKGEN_ADCC_MASK, 304 | RT5663_CKGEN_ADCC_MASK); 305 | 306 | //Headphone Volume 307 | rt5663_widget_update(pDevice, 308 | RT5663_STO_DRE_9, 309 | RT5663_DRE_GAIN_HP_MASK, 310 | 0x07); 311 | rt5663_widget_update(pDevice, 312 | RT5663_STO_DRE_10, 313 | RT5663_DRE_GAIN_HP_MASK, 314 | 0x07); 315 | 316 | rt5663_widget_update(pDevice, RT5663_PWR_ANLG_1, 317 | RT5663_PWR_VREF1 | RT5663_PWR_VREF2 | RT5663_PWR_MB, 318 | RT5663_PWR_VREF1 | RT5663_PWR_VREF2 | RT5663_PWR_MB); 319 | } 320 | } 321 | 322 | void rt5663_disable(PRTEK_CONTEXT pDevice) { 323 | { //Unset defaults 324 | //DAC Mixer 325 | rt5663_widget_update(pDevice, RT5663_PWR_DIG_1, 326 | RT5663_PWR_ADC_L1, 327 | 0); 328 | rt5663_widget_update(pDevice, RT5663_PWR_DIG_2, 329 | RT5663_PWR_ADC_S1F, 330 | 0); 331 | 332 | rt5663_widget_update(pDevice, RT5663_PWR_ANLG_2, 333 | RT5663_PWR_RECMIX1, 334 | 0); 335 | 336 | //ASRC 337 | rt5663_widget_update(pDevice, RT5663_ASRC_1, 338 | RT5663_ADC_STO1_ASRC_MASK, 339 | 0); 340 | 341 | //ADC Mixer 342 | rt5663_widget_update(pDevice, 343 | RT5663_CHOP_ADC, 344 | RT5663_CKGEN_ADCC_MASK, 345 | 0); 346 | } 347 | 348 | rt5663_set_bias_level(pDevice, SND_BIAS_PREPARE); 349 | 350 | rt5663_hp_event(pDevice, SND_DAPM_PRE_PMD); 351 | 352 | rt5663_pre_div_power(pDevice, SND_DAPM_PRE_PMD); 353 | 354 | rt5663_charge_pump_event(pDevice, SND_DAPM_POST_PMD); 355 | 356 | { //unset last defaults 357 | rt5663_widget_update(pDevice, RT5663_PWR_DIG_1, 358 | RT5663_PWR_I2S1 | RT5663_PWR_DAC_L1 | RT5663_PWR_DAC_R1, 359 | 0); 360 | rt5663_widget_update(pDevice, RT5663_PWR_DIG_2, 361 | RT5663_PWR_DAC_S1F, 362 | 0); 363 | 364 | //ASRC 365 | rt5663_widget_update(pDevice, RT5663_ASRC_1, 366 | RT5663_I2S1_ASRC_MASK | RT5663_DAC_STO1_ASRC_MASK, 367 | 0); 368 | } 369 | 370 | rt5663_set_bias_level(pDevice, SND_BIAS_STANDBY); 371 | 372 | rt5663_set_bias_level(pDevice, SND_BIAS_OFF); 373 | } 374 | 375 | NTSTATUS BOOTCODEC( 376 | _In_ PRTEK_CONTEXT devContext 377 | ) 378 | { 379 | NTSTATUS status = STATUS_SUCCESS; 380 | 381 | UINT16 val; 382 | status = rt5663_reg_read(devContext, RT5663_VENDOR_ID_2, &val); 383 | if (!NT_SUCCESS(status) || (val != RT5663_DEVICE_ID_2 && val != RT5663_DEVICE_ID_1)) { 384 | msleep(100); 385 | rt5663_reg_read(devContext, RT5663_VENDOR_ID_2, &val); 386 | } 387 | 388 | switch (val) { 389 | case RT5663_DEVICE_ID_2: 390 | DbgPrint("Codec version 1 is not supported\n"); 391 | return STATUS_INVALID_DEVICE_STATE; 392 | case RT5663_DEVICE_ID_1: 393 | devContext->CodecVer = CODEC_VER_0; 394 | break; 395 | default: 396 | DbgPrint("Device with ID register %#x is not rt5663\n", 397 | val); 398 | return STATUS_INVALID_DEVICE_STATE; 399 | } 400 | 401 | /* reset */ 402 | 403 | rt5663_reg_write(devContext, RT5663_RESET, 0); 404 | 405 | static const struct reg rt5663_patch_list[] = { 406 | { 0x002a, 0x8020 }, 407 | { 0x0086, 0x0028 }, 408 | { 0x0100, 0xa020 }, 409 | { 0x0117, 0x0f28 }, 410 | { 0x02fb, 0x8089 }, 411 | }; 412 | if (devContext->CodecVer == CODEC_VER_0) { 413 | status = rt5663_reg_burstWrite(devContext, rt5663_patch_list, ARRAYSIZE(rt5663_patch_list)); 414 | if (!NT_SUCCESS(status)) { 415 | return status; 416 | } 417 | } 418 | 419 | /* GPIO1 as IRQ */ 420 | rt5663_reg_update(devContext, RT5663_GPIO_1, RT5663_GP1_PIN_MASK, 421 | RT5663_GP1_PIN_IRQ); 422 | /* 4btn inline command debounce */ 423 | rt5663_reg_update(devContext, RT5663_IL_CMD_5, 424 | RT5663_4BTN_CLK_DEB_MASK, RT5663_4BTN_CLK_DEB_65MS); 425 | 426 | switch (devContext->CodecVer) { 427 | case CODEC_VER_0: 428 | rt5663_reg_update(devContext, RT5663_DIG_MISC, 429 | RT5663_DIG_GATE_CTRL_MASK, RT5663_DIG_GATE_CTRL_EN); 430 | rt5663_reg_update(devContext, RT5663_AUTO_1MRC_CLK, 431 | RT5663_IRQ_MANUAL_MASK, RT5663_IRQ_MANUAL_EN); 432 | rt5663_reg_update(devContext, RT5663_IRQ_1, 433 | RT5663_EN_IRQ_JD1_MASK, RT5663_EN_IRQ_JD1_EN); 434 | rt5663_reg_update(devContext, RT5663_GPIO_1, 435 | RT5663_GPIO1_TYPE_MASK, RT5663_GPIO1_TYPE_EN); 436 | rt5663_reg_write(devContext, RT5663_VREF_RECMIX, 0x0032); 437 | rt5663_reg_update(devContext, RT5663_GPIO_2, 438 | RT5663_GP1_PIN_CONF_MASK | RT5663_SEL_GPIO1_MASK, 439 | RT5663_GP1_PIN_CONF_OUTPUT | RT5663_SEL_GPIO1_EN); 440 | rt5663_reg_update(devContext, RT5663_RECMIX, 441 | RT5663_RECMIX1_BST1_MASK, RT5663_RECMIX1_BST1_ON); 442 | rt5663_reg_update(devContext, RT5663_TDM_2, 443 | RT5663_DATA_SWAP_ADCDAT1_MASK, 444 | RT5663_DATA_SWAP_ADCDAT1_LL); 445 | break; 446 | } 447 | 448 | { //i2s use asrc 449 | unsigned int asrc2_mask = 0; 450 | unsigned int asrc2_value = 0; 451 | unsigned int clk_src = RT5663_CLK_SEL_I2S1_ASRC; 452 | unsigned int filter_mask = RT5663_DA_STEREO_FILTER | RT5663_AD_STEREO_FILTER; 453 | 454 | if (filter_mask & RT5663_DA_STEREO_FILTER) { 455 | asrc2_mask |= RT5663_DA_STO1_TRACK_MASK; 456 | asrc2_value |= clk_src << RT5663_DA_STO1_TRACK_SHIFT; 457 | } 458 | 459 | if (filter_mask & RT5663_AD_STEREO_FILTER) { 460 | switch (devContext->CodecVer) { 461 | case CODEC_VER_0: 462 | asrc2_mask |= RT5663_AD_STO1_TRACK_MASK; 463 | asrc2_value |= clk_src << RT5663_AD_STO1_TRACK_SHIFT; 464 | break; 465 | } 466 | } 467 | 468 | if (asrc2_mask) 469 | rt5663_reg_update(devContext, RT5663_ASRC_2, asrc2_mask, 470 | asrc2_value); 471 | } 472 | 473 | { //set sysclk 474 | int clk_id = RT5663_SCLK_S_MCLK; 475 | unsigned int freq = 24576000; 476 | 477 | unsigned int reg_val = 0; 478 | switch (clk_id) { 479 | case RT5663_SCLK_S_MCLK: 480 | reg_val |= RT5663_SCLK_SRC_MCLK; 481 | break; 482 | case RT5663_SCLK_S_PLL1: 483 | reg_val |= RT5663_SCLK_SRC_PLL1; 484 | break; 485 | case RT5663_SCLK_S_RCCLK: 486 | reg_val |= RT5663_SCLK_SRC_RCCLK; 487 | break; 488 | default: 489 | return STATUS_INVALID_DEVICE_REQUEST; 490 | } 491 | rt5663_reg_update(devContext, RT5663_GLB_CLK, RT5663_SCLK_SRC_MASK, 492 | reg_val); 493 | } 494 | 495 | { //dai fmt 496 | unsigned int reg_val = RT5663_I2S_MS_S; 497 | 498 | UINT16 val; 499 | rt5663_reg_read(devContext, RT5663_I2S1_SDP, &val); 500 | 501 | rt5663_reg_update(devContext, RT5663_I2S1_SDP, RT5663_I2S_MS_MASK | 502 | RT5663_I2S_BP_MASK | RT5663_I2S_DF_MASK, reg_val); 503 | 504 | rt5663_reg_read(devContext, RT5663_I2S1_SDP, &val); 505 | } 506 | 507 | { 508 | //set round 1 509 | //Headphone Volume 510 | rt5663_widget_update(devContext, 511 | RT5663_STO_DRE_9, 512 | RT5663_DRE_GAIN_HP_MASK, 513 | 0x00); 514 | rt5663_widget_update(devContext, 515 | RT5663_STO_DRE_10, 516 | RT5663_DRE_GAIN_HP_MASK, 517 | 0x00); 518 | 519 | //Mic Volume 520 | rt5663_widget_update(devContext, 521 | RT5663_STO1_ADC_DIG_VOL, 522 | RT5663_ADC_L_MUTE_MASK | RT5663_ADC_L_VOL_MASK | RT5663_ADC_R_MUTE_MASK | RT5663_ADC_R_VOL_MASK, 523 | (0x53 << RT5663_ADC_L_VOL_SHIFT) | (0x53 << RT5663_ADC_R_VOL_SHIFT)); 524 | 525 | //ADC Mixer 526 | rt5663_widget_update(devContext, 527 | RT5663_STO1_ADC_MIXER, 528 | RT5663_M_STO1_ADC_L1, 529 | 0); 530 | 531 | //Headphone Volume 532 | rt5663_widget_update(devContext, 533 | RT5663_STO_DRE_9, 534 | RT5663_DRE_GAIN_HP_MASK, 535 | 0x07); 536 | rt5663_widget_update(devContext, 537 | RT5663_STO_DRE_10, 538 | RT5663_DRE_GAIN_HP_MASK, 539 | 0x07); 540 | } 541 | 542 | rt5663_enable(devContext); //must power cycle once before enabling it or output doesn't work 543 | 544 | rt5663_disable(devContext); 545 | 546 | rt5663_enable(devContext); 547 | 548 | rt5663_jackdetect(devContext); //attempt to check if microphone present 549 | 550 | return STATUS_SUCCESS; 551 | } 552 | 553 | NTSTATUS 554 | OnPrepareHardware( 555 | _In_ WDFDEVICE FxDevice, 556 | _In_ WDFCMRESLIST FxResourcesRaw, 557 | _In_ WDFCMRESLIST FxResourcesTranslated 558 | ) 559 | /*++ 560 | 561 | Routine Description: 562 | 563 | This routine caches the SPB resource connection ID. 564 | 565 | Arguments: 566 | 567 | FxDevice - a handle to the framework device object 568 | FxResourcesRaw - list of translated hardware resources that 569 | the PnP manager has assigned to the device 570 | FxResourcesTranslated - list of raw hardware resources that 571 | the PnP manager has assigned to the device 572 | 573 | Return Value: 574 | 575 | Status 576 | 577 | --*/ 578 | { 579 | PRTEK_CONTEXT pDevice = GetDeviceContext(FxDevice); 580 | BOOLEAN fSpbResourceFound = FALSE; 581 | NTSTATUS status = STATUS_INSUFFICIENT_RESOURCES; 582 | 583 | UNREFERENCED_PARAMETER(FxResourcesRaw); 584 | 585 | // 586 | // Parse the peripheral's resources. 587 | // 588 | 589 | ULONG resourceCount = WdfCmResourceListGetCount(FxResourcesTranslated); 590 | 591 | for (ULONG i = 0; i < resourceCount; i++) 592 | { 593 | PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor; 594 | UCHAR Class; 595 | UCHAR Type; 596 | 597 | pDescriptor = WdfCmResourceListGetDescriptor( 598 | FxResourcesTranslated, i); 599 | 600 | switch (pDescriptor->Type) 601 | { 602 | case CmResourceTypeConnection: 603 | // 604 | // Look for I2C or SPI resource and save connection ID. 605 | // 606 | Class = pDescriptor->u.Connection.Class; 607 | Type = pDescriptor->u.Connection.Type; 608 | if (Class == CM_RESOURCE_CONNECTION_CLASS_SERIAL && 609 | Type == CM_RESOURCE_CONNECTION_TYPE_SERIAL_I2C) 610 | { 611 | if (fSpbResourceFound == FALSE) 612 | { 613 | status = STATUS_SUCCESS; 614 | pDevice->I2CContext.I2cResHubId.LowPart = pDescriptor->u.Connection.IdLowPart; 615 | pDevice->I2CContext.I2cResHubId.HighPart = pDescriptor->u.Connection.IdHighPart; 616 | fSpbResourceFound = TRUE; 617 | } 618 | else 619 | { 620 | } 621 | } 622 | break; 623 | default: 624 | // 625 | // Ignoring all other resource types. 626 | // 627 | break; 628 | } 629 | } 630 | 631 | // 632 | // An SPB resource is required. 633 | // 634 | 635 | if (fSpbResourceFound == FALSE) 636 | { 637 | status = STATUS_NOT_FOUND; 638 | } 639 | 640 | status = SpbTargetInitialize(FxDevice, &pDevice->I2CContext); 641 | 642 | if (!NT_SUCCESS(status)) 643 | { 644 | return status; 645 | } 646 | 647 | return status; 648 | } 649 | 650 | NTSTATUS 651 | OnReleaseHardware( 652 | _In_ WDFDEVICE FxDevice, 653 | _In_ WDFCMRESLIST FxResourcesTranslated 654 | ) 655 | /*++ 656 | 657 | Routine Description: 658 | 659 | Arguments: 660 | 661 | FxDevice - a handle to the framework device object 662 | FxResourcesTranslated - list of raw hardware resources that 663 | the PnP manager has assigned to the device 664 | 665 | Return Value: 666 | 667 | Status 668 | 669 | --*/ 670 | { 671 | PRTEK_CONTEXT pDevice = GetDeviceContext(FxDevice); 672 | NTSTATUS status = STATUS_SUCCESS; 673 | 674 | UNREFERENCED_PARAMETER(FxResourcesTranslated); 675 | 676 | SpbTargetDeinitialize(FxDevice, &pDevice->I2CContext); 677 | 678 | return status; 679 | } 680 | 681 | NTSTATUS 682 | OnD0Entry( 683 | _In_ WDFDEVICE FxDevice, 684 | _In_ WDF_POWER_DEVICE_STATE FxPreviousState 685 | ) 686 | /*++ 687 | 688 | Routine Description: 689 | 690 | This routine allocates objects needed by the driver. 691 | 692 | Arguments: 693 | 694 | FxDevice - a handle to the framework device object 695 | FxPreviousState - previous power state 696 | 697 | Return Value: 698 | 699 | Status 700 | 701 | --*/ 702 | { 703 | UNREFERENCED_PARAMETER(FxPreviousState); 704 | 705 | PRTEK_CONTEXT pDevice = GetDeviceContext(FxDevice); 706 | NTSTATUS status = STATUS_SUCCESS; 707 | 708 | pDevice->JackType = 0; 709 | 710 | status = BOOTCODEC(pDevice); 711 | if (!NT_SUCCESS(status)) { 712 | return status; 713 | } 714 | 715 | pDevice->ConnectInterrupt = true; 716 | 717 | return status; 718 | } 719 | 720 | NTSTATUS 721 | OnD0Exit( 722 | _In_ WDFDEVICE FxDevice, 723 | _In_ WDF_POWER_DEVICE_STATE FxPreviousState 724 | ) 725 | /*++ 726 | 727 | Routine Description: 728 | 729 | This routine destroys objects needed by the driver. 730 | 731 | Arguments: 732 | 733 | FxDevice - a handle to the framework device object 734 | FxPreviousState - previous power state 735 | 736 | Return Value: 737 | 738 | Status 739 | 740 | --*/ 741 | { 742 | UNREFERENCED_PARAMETER(FxPreviousState); 743 | 744 | PRTEK_CONTEXT pDevice = GetDeviceContext(FxDevice); 745 | 746 | rt5663_disable(pDevice); 747 | rt5663_reg_write(pDevice, RT5663_RESET, 0); 748 | 749 | pDevice->ConnectInterrupt = false; 750 | 751 | return STATUS_SUCCESS; 752 | } 753 | 754 | static void rt5663_enable_push_button_irq(PRTEK_CONTEXT pDevice, 755 | bool enable) 756 | { 757 | 758 | if (enable) { 759 | rt5663_reg_update(pDevice, RT5663_IL_CMD_6, 760 | RT5663_EN_4BTN_INL_MASK, RT5663_EN_4BTN_INL_EN); 761 | /* reset in-line command */ 762 | rt5663_reg_update(pDevice, RT5663_IL_CMD_6, 763 | RT5663_RESET_4BTN_INL_MASK, 764 | RT5663_RESET_4BTN_INL_RESET); 765 | rt5663_reg_update(pDevice, RT5663_IL_CMD_6, 766 | RT5663_RESET_4BTN_INL_MASK, 767 | RT5663_RESET_4BTN_INL_NOR); 768 | switch (pDevice->CodecVer) { 769 | case CODEC_VER_0: 770 | rt5663_reg_update(pDevice, RT5663_IRQ_2, 771 | RT5663_EN_IRQ_INLINE_MASK, 772 | RT5663_EN_IRQ_INLINE_NOR); 773 | break; 774 | } 775 | } 776 | else { 777 | switch (pDevice->CodecVer) { 778 | case CODEC_VER_0: 779 | rt5663_reg_update(pDevice, RT5663_IRQ_2, 780 | RT5663_EN_IRQ_INLINE_MASK, 781 | RT5663_EN_IRQ_INLINE_BYP); 782 | break; 783 | } 784 | rt5663_reg_update(pDevice, RT5663_IL_CMD_6, 785 | RT5663_EN_4BTN_INL_MASK, RT5663_EN_4BTN_INL_DIS); 786 | /* reset in-line command */ 787 | rt5663_reg_update(pDevice, RT5663_IL_CMD_6, 788 | RT5663_RESET_4BTN_INL_MASK, 789 | RT5663_RESET_4BTN_INL_RESET); 790 | rt5663_reg_update(pDevice, RT5663_IL_CMD_6, 791 | RT5663_RESET_4BTN_INL_MASK, 792 | RT5663_RESET_4BTN_INL_NOR); 793 | } 794 | } 795 | 796 | int rt5663_jack_detect(PRTEK_CONTEXT pDevice, int jack_insert) { 797 | UINT16 val, i = 0; 798 | if (jack_insert) { 799 | rt5663_reg_update(pDevice, RT5663_DIG_MISC, 800 | RT5663_DIG_GATE_CTRL_MASK, RT5663_DIG_GATE_CTRL_EN); 801 | rt5663_reg_update(pDevice, RT5663_HP_CHARGE_PUMP_1, 802 | RT5663_SI_HP_MASK | RT5663_OSW_HP_L_MASK | 803 | RT5663_OSW_HP_R_MASK, RT5663_SI_HP_EN | 804 | RT5663_OSW_HP_L_DIS | RT5663_OSW_HP_R_DIS); 805 | rt5663_reg_update(pDevice, RT5663_DUMMY_1, 806 | RT5663_EMB_CLK_MASK | RT5663_HPA_CPL_BIAS_MASK | 807 | RT5663_HPA_CPR_BIAS_MASK, RT5663_EMB_CLK_EN | 808 | RT5663_HPA_CPL_BIAS_1 | RT5663_HPA_CPR_BIAS_1); 809 | rt5663_reg_update(pDevice, RT5663_CBJ_1, 810 | RT5663_INBUF_CBJ_BST1_MASK | RT5663_CBJ_SENSE_BST1_MASK, 811 | RT5663_INBUF_CBJ_BST1_ON | RT5663_CBJ_SENSE_BST1_L); 812 | rt5663_reg_update(pDevice, RT5663_IL_CMD_2, 813 | RT5663_PWR_MIC_DET_MASK, RT5663_PWR_MIC_DET_ON); 814 | /* BST1 power on for JD */ 815 | rt5663_reg_update(pDevice, RT5663_PWR_ANLG_2, 816 | RT5663_PWR_BST1_MASK, RT5663_PWR_BST1_ON); 817 | rt5663_reg_update(pDevice, RT5663_EM_JACK_TYPE_1, 818 | RT5663_CBJ_DET_MASK | RT5663_EXT_JD_MASK | 819 | RT5663_POL_EXT_JD_MASK, RT5663_CBJ_DET_EN | 820 | RT5663_EXT_JD_EN | RT5663_POL_EXT_JD_EN); 821 | rt5663_reg_update(pDevice, RT5663_PWR_ANLG_1, 822 | RT5663_PWR_MB_MASK | RT5663_LDO1_DVO_MASK | 823 | RT5663_AMP_HP_MASK, RT5663_PWR_MB | 824 | RT5663_LDO1_DVO_0_9V | RT5663_AMP_HP_3X); 825 | rt5663_reg_update(pDevice, RT5663_PWR_ANLG_1, 826 | RT5663_PWR_VREF1_MASK | RT5663_PWR_VREF2_MASK | 827 | RT5663_PWR_FV1_MASK | RT5663_PWR_FV2_MASK, 828 | RT5663_PWR_VREF1 | RT5663_PWR_VREF2); 829 | msleep(20); 830 | rt5663_reg_update(pDevice, RT5663_PWR_ANLG_1, 831 | RT5663_PWR_FV1_MASK | RT5663_PWR_FV2_MASK, 832 | RT5663_PWR_FV1 | RT5663_PWR_FV2); 833 | rt5663_reg_update(pDevice, RT5663_AUTO_1MRC_CLK, 834 | RT5663_IRQ_POW_SAV_MASK, RT5663_IRQ_POW_SAV_EN); 835 | rt5663_reg_update(pDevice, RT5663_IRQ_1, 836 | RT5663_EN_IRQ_JD1_MASK, RT5663_EN_IRQ_JD1_EN); 837 | rt5663_reg_update(pDevice, RT5663_EM_JACK_TYPE_1, 838 | RT5663_EM_JD_MASK, RT5663_EM_JD_RST); 839 | rt5663_reg_update(pDevice, RT5663_EM_JACK_TYPE_1, 840 | RT5663_EM_JD_MASK, RT5663_EM_JD_NOR); 841 | 842 | while (true) { 843 | rt5663_reg_read(pDevice, RT5663_INT_ST_2, &val); 844 | if (!(val & 0x80)) 845 | msleep(10); 846 | else 847 | break; 848 | 849 | if (i > 200) 850 | break; 851 | i++; 852 | } 853 | 854 | rt5663_reg_read(pDevice, RT5663_EM_JACK_TYPE_2, &val); 855 | val &= 0x0003; 856 | 857 | rt5663_reg_update(pDevice, RT5663_HP_CHARGE_PUMP_1, 858 | RT5663_OSW_HP_L_MASK | RT5663_OSW_HP_R_MASK, 859 | RT5663_OSW_HP_L_EN | RT5663_OSW_HP_R_EN); 860 | 861 | val = 2; 862 | 863 | switch (val) { 864 | case 0x1: 865 | case 0x2: 866 | pDevice->JackType = SND_JACK_HEADSET; 867 | rt5663_enable_push_button_irq(pDevice, true); 868 | 869 | break; 870 | default: 871 | pDevice->JackType = SND_JACK_HEADPHONE; 872 | 873 | rt5663_reg_update(pDevice, 874 | RT5663_PWR_ANLG_1, 875 | RT5663_PWR_MB_MASK | RT5663_PWR_VREF1_MASK | 876 | RT5663_PWR_VREF2_MASK, 0); 877 | } 878 | } 879 | else { 880 | if (pDevice->JackType == SND_JACK_HEADSET) 881 | rt5663_enable_push_button_irq(pDevice, false); 882 | 883 | pDevice->JackType = 0; 884 | 885 | rt5663_reg_update(pDevice, RT5663_PWR_ANLG_1, 886 | RT5663_PWR_MB_MASK | RT5663_PWR_VREF1_MASK | 887 | RT5663_PWR_VREF2_MASK, 0); 888 | } 889 | 890 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 891 | "Jack Type: %d\n", pDevice->JackType); 892 | return pDevice->JackType; 893 | } 894 | 895 | static UINT16 rt5663_button_detect(PRTEK_CONTEXT pDevice) 896 | { 897 | UINT16 btn_type, val; 898 | 899 | rt5663_reg_read(pDevice, RT5663_IL_CMD_5, &val); 900 | btn_type = val & 0xfff0; 901 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 902 | "btn_type=%x\n", btn_type); 903 | rt5663_reg_write(pDevice, 904 | RT5663_IL_CMD_5, val); 905 | 906 | return btn_type; 907 | } 908 | 909 | static bool rt5663_check_jd_status(PRTEK_CONTEXT pDevice) 910 | { 911 | UINT16 val; 912 | rt5663_reg_read(pDevice, RT5663_INT_ST_1, &val); 913 | 914 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 915 | "%s val=%x\n", __func__, val); 916 | 917 | /* JD1 */ 918 | switch (pDevice->CodecVer) { 919 | case CODEC_VER_0: 920 | return !(val & 0x1000); 921 | } 922 | 923 | return false; 924 | } 925 | 926 | void rt5663_jackdetect(PRTEK_CONTEXT pDevice) { 927 | NTSTATUS status = STATUS_SUCCESS; 928 | 929 | msleep(250); 930 | 931 | if (rt5663_check_jd_status(pDevice)) { 932 | /* jack in */ 933 | if (pDevice->JackType == 0) { 934 | /* jack was out, report jack type */ 935 | switch (pDevice->CodecVer) { 936 | case CODEC_VER_0: 937 | pDevice->JackType = rt5663_jack_detect(pDevice, 1); 938 | break; 939 | } 940 | 941 | /* Delay the jack insert report to avoid pop noise */ 942 | msleep(30); 943 | } 944 | else { 945 | /* jack is already in, report button event */ 946 | UINT16 btn_type = rt5663_button_detect(pDevice); 947 | /** 948 | * rt5663 can report three kinds of button behavior, 949 | * one click, double click and hold. However, 950 | * currently we will report button pressed/released 951 | * event. So all the three button behaviors are 952 | * treated as button pressed. 953 | */ 954 | int rawButton = 0; 955 | 956 | switch (btn_type) { 957 | case 0x8000: 958 | case 0x4000: 959 | case 0x2000: 960 | rawButton = 1; 961 | break; 962 | case 0x1000: 963 | case 0x0800: 964 | case 0x0400: 965 | rawButton = 2; 966 | break; 967 | case 0x0200: 968 | case 0x0100: 969 | case 0x0080: 970 | rawButton = 3; 971 | break; 972 | case 0x0040: 973 | case 0x0020: 974 | case 0x0010: 975 | rawButton = 4; 976 | break; 977 | case 0x0000: /* unpressed */ 978 | break; 979 | default: 980 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 981 | "Unexpected button code 0x%04x\n", 982 | btn_type); 983 | break; 984 | } 985 | 986 | ///XXX: Spurious Button Reports. Ignore 987 | 988 | /*Rt5663MediaReport report; 989 | report.ReportID = REPORTID_MEDIA; 990 | report.ControlCode = rawButton; 991 | 992 | size_t bytesWritten; 993 | Rt5663ProcessVendorReport(pDevice, &report, sizeof(report), &bytesWritten);*/ 994 | } 995 | } 996 | else { 997 | /* jack out */ 998 | switch (pDevice->CodecVer) { 999 | case CODEC_VER_0: 1000 | pDevice->JackType = rt5663_jack_detect(pDevice, 0); 1001 | break; 1002 | } 1003 | } 1004 | 1005 | CsAudioSpecialKeyReport report; 1006 | report.ReportID = REPORTID_SPECKEYS; 1007 | report.ControlCode = CONTROL_CODE_JACK_TYPE; 1008 | report.ControlValue = pDevice->JackType; 1009 | 1010 | size_t bytesWritten; 1011 | Rt5663ProcessVendorReport(pDevice, &report, sizeof(report), &bytesWritten); 1012 | } 1013 | 1014 | VOID 1015 | RtekJdetWorkItem( 1016 | IN WDFWORKITEM WorkItem 1017 | ) 1018 | { 1019 | WDFDEVICE Device = (WDFDEVICE)WdfWorkItemGetParentObject(WorkItem); 1020 | PRTEK_CONTEXT pDevice = GetDeviceContext(Device); 1021 | 1022 | rt5663_jackdetect(pDevice); 1023 | } 1024 | 1025 | BOOLEAN OnInterruptIsr( 1026 | WDFINTERRUPT Interrupt, 1027 | ULONG MessageID) { 1028 | UNREFERENCED_PARAMETER(MessageID); 1029 | 1030 | WDFDEVICE Device = WdfInterruptGetDevice(Interrupt); 1031 | PRTEK_CONTEXT pDevice = GetDeviceContext(Device); 1032 | 1033 | if (!pDevice->ConnectInterrupt) 1034 | return true; 1035 | 1036 | NTSTATUS status = STATUS_SUCCESS; 1037 | 1038 | WDF_OBJECT_ATTRIBUTES attributes; 1039 | WDF_WORKITEM_CONFIG workitemConfig; 1040 | WDFWORKITEM hWorkItem; 1041 | 1042 | WDF_OBJECT_ATTRIBUTES_INIT(&attributes); 1043 | WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attributes, RTEK_CONTEXT); 1044 | attributes.ParentObject = Device; 1045 | WDF_WORKITEM_CONFIG_INIT(&workitemConfig, RtekJdetWorkItem); 1046 | 1047 | WdfWorkItemCreate(&workitemConfig, 1048 | &attributes, 1049 | &hWorkItem); 1050 | 1051 | WdfWorkItemEnqueue(hWorkItem); 1052 | 1053 | return true; 1054 | } 1055 | 1056 | NTSTATUS 1057 | Rt5663EvtDeviceAdd( 1058 | IN WDFDRIVER Driver, 1059 | IN PWDFDEVICE_INIT DeviceInit 1060 | ) 1061 | { 1062 | NTSTATUS status = STATUS_SUCCESS; 1063 | WDF_IO_QUEUE_CONFIG queueConfig; 1064 | WDF_OBJECT_ATTRIBUTES attributes; 1065 | WDFDEVICE device; 1066 | WDF_INTERRUPT_CONFIG interruptConfig; 1067 | WDFQUEUE queue; 1068 | UCHAR minorFunction; 1069 | PRTEK_CONTEXT devContext; 1070 | 1071 | UNREFERENCED_PARAMETER(Driver); 1072 | 1073 | PAGED_CODE(); 1074 | 1075 | RtekPrint(DEBUG_LEVEL_INFO, DBG_PNP, 1076 | "Rt5663EvtDeviceAdd called\n"); 1077 | 1078 | // 1079 | // Tell framework this is a filter driver. Filter drivers by default are 1080 | // not power policy owners. This works well for this driver because 1081 | // HIDclass driver is the power policy owner for HID minidrivers. 1082 | // 1083 | 1084 | WdfFdoInitSetFilter(DeviceInit); 1085 | 1086 | { 1087 | WDF_PNPPOWER_EVENT_CALLBACKS pnpCallbacks; 1088 | WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpCallbacks); 1089 | 1090 | pnpCallbacks.EvtDevicePrepareHardware = OnPrepareHardware; 1091 | pnpCallbacks.EvtDeviceReleaseHardware = OnReleaseHardware; 1092 | pnpCallbacks.EvtDeviceD0Entry = OnD0Entry; 1093 | pnpCallbacks.EvtDeviceD0Exit = OnD0Exit; 1094 | 1095 | WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpCallbacks); 1096 | } 1097 | 1098 | // 1099 | // Setup the device context 1100 | // 1101 | 1102 | WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, RTEK_CONTEXT); 1103 | 1104 | // 1105 | // Create a framework device object.This call will in turn create 1106 | // a WDM device object, attach to the lower stack, and set the 1107 | // appropriate flags and attributes. 1108 | // 1109 | 1110 | status = WdfDeviceCreate(&DeviceInit, &attributes, &device); 1111 | 1112 | if (!NT_SUCCESS(status)) 1113 | { 1114 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 1115 | "WdfDeviceCreate failed with status code 0x%x\n", status); 1116 | 1117 | return status; 1118 | } 1119 | 1120 | { 1121 | WDF_DEVICE_STATE deviceState; 1122 | WDF_DEVICE_STATE_INIT(&deviceState); 1123 | 1124 | deviceState.NotDisableable = WdfFalse; 1125 | WdfDeviceSetDeviceState(device, &deviceState); 1126 | } 1127 | 1128 | WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); 1129 | 1130 | queueConfig.EvtIoInternalDeviceControl = Rt5663EvtInternalDeviceControl; 1131 | 1132 | status = WdfIoQueueCreate(device, 1133 | &queueConfig, 1134 | WDF_NO_OBJECT_ATTRIBUTES, 1135 | &queue 1136 | ); 1137 | 1138 | if (!NT_SUCCESS(status)) 1139 | { 1140 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 1141 | "WdfIoQueueCreate failed 0x%x\n", status); 1142 | 1143 | return status; 1144 | } 1145 | 1146 | // 1147 | // Create manual I/O queue to take care of hid report read requests 1148 | // 1149 | 1150 | devContext = GetDeviceContext(device); 1151 | 1152 | devContext->FxDevice = device; 1153 | 1154 | WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchManual); 1155 | 1156 | queueConfig.PowerManaged = WdfFalse; 1157 | 1158 | status = WdfIoQueueCreate(device, 1159 | &queueConfig, 1160 | WDF_NO_OBJECT_ATTRIBUTES, 1161 | &devContext->ReportQueue 1162 | ); 1163 | 1164 | if (!NT_SUCCESS(status)) 1165 | { 1166 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 1167 | "WdfIoQueueCreate failed 0x%x\n", status); 1168 | 1169 | return status; 1170 | } 1171 | 1172 | // 1173 | // Create an interrupt object for hardware notifications 1174 | // 1175 | WDF_INTERRUPT_CONFIG_INIT( 1176 | &interruptConfig, 1177 | OnInterruptIsr, 1178 | NULL); 1179 | interruptConfig.PassiveHandling = TRUE; 1180 | 1181 | status = WdfInterruptCreate( 1182 | device, 1183 | &interruptConfig, 1184 | WDF_NO_OBJECT_ATTRIBUTES, 1185 | &devContext->Interrupt); 1186 | 1187 | if (!NT_SUCCESS(status)) 1188 | { 1189 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_PNP, 1190 | "Error creating WDF interrupt object - %!STATUS!", 1191 | status); 1192 | 1193 | return status; 1194 | } 1195 | 1196 | return status; 1197 | } 1198 | 1199 | VOID 1200 | Rt5663EvtInternalDeviceControl( 1201 | IN WDFQUEUE Queue, 1202 | IN WDFREQUEST Request, 1203 | IN size_t OutputBufferLength, 1204 | IN size_t InputBufferLength, 1205 | IN ULONG IoControlCode 1206 | ) 1207 | { 1208 | NTSTATUS status = STATUS_SUCCESS; 1209 | WDFDEVICE device; 1210 | PRTEK_CONTEXT devContext; 1211 | BOOLEAN completeRequest = TRUE; 1212 | 1213 | UNREFERENCED_PARAMETER(OutputBufferLength); 1214 | UNREFERENCED_PARAMETER(InputBufferLength); 1215 | 1216 | device = WdfIoQueueGetDevice(Queue); 1217 | devContext = GetDeviceContext(device); 1218 | 1219 | RtekPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1220 | "%s, Queue:0x%p, Request:0x%p\n", 1221 | DbgHidInternalIoctlString(IoControlCode), 1222 | Queue, 1223 | Request 1224 | ); 1225 | 1226 | // 1227 | // Please note that HIDCLASS provides the buffer in the Irp->UserBuffer 1228 | // field irrespective of the ioctl buffer type. However, framework is very 1229 | // strict about type checking. You cannot get Irp->UserBuffer by using 1230 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 1231 | // internal ioctl. So depending on the ioctl code, we will either 1232 | // use retreive function or escape to WDM to get the UserBuffer. 1233 | // 1234 | 1235 | switch (IoControlCode) 1236 | { 1237 | 1238 | case IOCTL_HID_GET_DEVICE_DESCRIPTOR: 1239 | // 1240 | // Retrieves the device's HID descriptor. 1241 | // 1242 | status = Rt5663GetHidDescriptor(device, Request); 1243 | break; 1244 | 1245 | case IOCTL_HID_GET_DEVICE_ATTRIBUTES: 1246 | // 1247 | //Retrieves a device's attributes in a HID_DEVICE_ATTRIBUTES structure. 1248 | // 1249 | status = Rt5663GetDeviceAttributes(Request); 1250 | break; 1251 | 1252 | case IOCTL_HID_GET_REPORT_DESCRIPTOR: 1253 | // 1254 | //Obtains the report descriptor for the HID device. 1255 | // 1256 | status = Rt5663GetReportDescriptor(device, Request); 1257 | break; 1258 | 1259 | case IOCTL_HID_GET_STRING: 1260 | // 1261 | // Requests that the HID minidriver retrieve a human-readable string 1262 | // for either the manufacturer ID, the product ID, or the serial number 1263 | // from the string descriptor of the device. The minidriver must send 1264 | // a Get String Descriptor request to the device, in order to retrieve 1265 | // the string descriptor, then it must extract the string at the 1266 | // appropriate index from the string descriptor and return it in the 1267 | // output buffer indicated by the IRP. Before sending the Get String 1268 | // Descriptor request, the minidriver must retrieve the appropriate 1269 | // index for the manufacturer ID, the product ID or the serial number 1270 | // from the device extension of a top level collection associated with 1271 | // the device. 1272 | // 1273 | status = Rt5663GetString(Request); 1274 | break; 1275 | 1276 | case IOCTL_HID_WRITE_REPORT: 1277 | case IOCTL_HID_SET_OUTPUT_REPORT: 1278 | // 1279 | //Transmits a class driver-supplied report to the device. 1280 | // 1281 | status = Rt5663WriteReport(devContext, Request); 1282 | break; 1283 | 1284 | case IOCTL_HID_READ_REPORT: 1285 | case IOCTL_HID_GET_INPUT_REPORT: 1286 | // 1287 | // Returns a report from the device into a class driver-supplied buffer. 1288 | // 1289 | status = Rt5663ReadReport(devContext, Request, &completeRequest); 1290 | break; 1291 | 1292 | case IOCTL_HID_SET_FEATURE: 1293 | // 1294 | // This sends a HID class feature report to a top-level collection of 1295 | // a HID class device. 1296 | // 1297 | status = Rt5663SetFeature(devContext, Request, &completeRequest); 1298 | break; 1299 | 1300 | case IOCTL_HID_GET_FEATURE: 1301 | // 1302 | // returns a feature report associated with a top-level collection 1303 | status = Rt5663GetFeature(devContext, Request, &completeRequest); 1304 | break; 1305 | 1306 | case IOCTL_HID_ACTIVATE_DEVICE: 1307 | // 1308 | // Makes the device ready for I/O operations. 1309 | // 1310 | case IOCTL_HID_DEACTIVATE_DEVICE: 1311 | // 1312 | // Causes the device to cease operations and terminate all outstanding 1313 | // I/O requests. 1314 | // 1315 | default: 1316 | status = STATUS_NOT_SUPPORTED; 1317 | break; 1318 | } 1319 | 1320 | if (completeRequest) 1321 | { 1322 | WdfRequestComplete(Request, status); 1323 | 1324 | RtekPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1325 | "%s completed, Queue:0x%p, Request:0x%p\n", 1326 | DbgHidInternalIoctlString(IoControlCode), 1327 | Queue, 1328 | Request 1329 | ); 1330 | } 1331 | else 1332 | { 1333 | RtekPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1334 | "%s deferred, Queue:0x%p, Request:0x%p\n", 1335 | DbgHidInternalIoctlString(IoControlCode), 1336 | Queue, 1337 | Request 1338 | ); 1339 | } 1340 | 1341 | return; 1342 | } 1343 | 1344 | NTSTATUS 1345 | Rt5663GetHidDescriptor( 1346 | IN WDFDEVICE Device, 1347 | IN WDFREQUEST Request 1348 | ) 1349 | { 1350 | NTSTATUS status = STATUS_SUCCESS; 1351 | size_t bytesToCopy = 0; 1352 | WDFMEMORY memory; 1353 | 1354 | UNREFERENCED_PARAMETER(Device); 1355 | 1356 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1357 | "Rt5663GetHidDescriptor Entry\n"); 1358 | 1359 | // 1360 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 1361 | // will correctly retrieve buffer from Irp->UserBuffer. 1362 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 1363 | // field irrespective of the ioctl buffer type. However, framework is very 1364 | // strict about type checking. You cannot get Irp->UserBuffer by using 1365 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 1366 | // internal ioctl. 1367 | // 1368 | status = WdfRequestRetrieveOutputMemory(Request, &memory); 1369 | 1370 | if (!NT_SUCCESS(status)) 1371 | { 1372 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1373 | "WdfRequestRetrieveOutputMemory failed 0x%x\n", status); 1374 | 1375 | return status; 1376 | } 1377 | 1378 | // 1379 | // Use hardcoded "HID Descriptor" 1380 | // 1381 | bytesToCopy = DefaultHidDescriptor.bLength; 1382 | 1383 | if (bytesToCopy == 0) 1384 | { 1385 | status = STATUS_INVALID_DEVICE_STATE; 1386 | 1387 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1388 | "DefaultHidDescriptor is zero, 0x%x\n", status); 1389 | 1390 | return status; 1391 | } 1392 | 1393 | status = WdfMemoryCopyFromBuffer(memory, 1394 | 0, // Offset 1395 | (PVOID)&DefaultHidDescriptor, 1396 | bytesToCopy); 1397 | 1398 | if (!NT_SUCCESS(status)) 1399 | { 1400 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1401 | "WdfMemoryCopyFromBuffer failed 0x%x\n", status); 1402 | 1403 | return status; 1404 | } 1405 | 1406 | // 1407 | // Report how many bytes were copied 1408 | // 1409 | WdfRequestSetInformation(Request, bytesToCopy); 1410 | 1411 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1412 | "Rt5663GetHidDescriptor Exit = 0x%x\n", status); 1413 | 1414 | return status; 1415 | } 1416 | 1417 | NTSTATUS 1418 | Rt5663GetReportDescriptor( 1419 | IN WDFDEVICE Device, 1420 | IN WDFREQUEST Request 1421 | ) 1422 | { 1423 | NTSTATUS status = STATUS_SUCCESS; 1424 | ULONG_PTR bytesToCopy; 1425 | WDFMEMORY memory; 1426 | 1427 | PRTEK_CONTEXT devContext = GetDeviceContext(Device); 1428 | 1429 | UNREFERENCED_PARAMETER(Device); 1430 | 1431 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1432 | "Rt5663GetReportDescriptor Entry\n"); 1433 | 1434 | // 1435 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 1436 | // will correctly retrieve buffer from Irp->UserBuffer. 1437 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 1438 | // field irrespective of the ioctl buffer type. However, framework is very 1439 | // strict about type checking. You cannot get Irp->UserBuffer by using 1440 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 1441 | // internal ioctl. 1442 | // 1443 | status = WdfRequestRetrieveOutputMemory(Request, &memory); 1444 | if (!NT_SUCCESS(status)) 1445 | { 1446 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1447 | "WdfRequestRetrieveOutputMemory failed 0x%x\n", status); 1448 | 1449 | return status; 1450 | } 1451 | 1452 | // 1453 | // Use hardcoded Report descriptor 1454 | // 1455 | bytesToCopy = DefaultHidDescriptor.DescriptorList[0].wReportLength; 1456 | 1457 | if (bytesToCopy == 0) 1458 | { 1459 | status = STATUS_INVALID_DEVICE_STATE; 1460 | 1461 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1462 | "DefaultHidDescriptor's reportLength is zero, 0x%x\n", status); 1463 | 1464 | return status; 1465 | } 1466 | 1467 | status = WdfMemoryCopyFromBuffer(memory, 1468 | 0, 1469 | (PVOID)DefaultReportDescriptor, 1470 | bytesToCopy); 1471 | if (!NT_SUCCESS(status)) 1472 | { 1473 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1474 | "WdfMemoryCopyFromBuffer failed 0x%x\n", status); 1475 | 1476 | return status; 1477 | } 1478 | 1479 | // 1480 | // Report how many bytes were copied 1481 | // 1482 | WdfRequestSetInformation(Request, bytesToCopy); 1483 | 1484 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1485 | "Rt5663GetReportDescriptor Exit = 0x%x\n", status); 1486 | 1487 | return status; 1488 | } 1489 | 1490 | 1491 | NTSTATUS 1492 | Rt5663GetDeviceAttributes( 1493 | IN WDFREQUEST Request 1494 | ) 1495 | { 1496 | NTSTATUS status = STATUS_SUCCESS; 1497 | PHID_DEVICE_ATTRIBUTES deviceAttributes = NULL; 1498 | 1499 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1500 | "Rt5663GetDeviceAttributes Entry\n"); 1501 | 1502 | // 1503 | // This IOCTL is METHOD_NEITHER so WdfRequestRetrieveOutputMemory 1504 | // will correctly retrieve buffer from Irp->UserBuffer. 1505 | // Remember that HIDCLASS provides the buffer in the Irp->UserBuffer 1506 | // field irrespective of the ioctl buffer type. However, framework is very 1507 | // strict about type checking. You cannot get Irp->UserBuffer by using 1508 | // WdfRequestRetrieveOutputMemory if the ioctl is not a METHOD_NEITHER 1509 | // internal ioctl. 1510 | // 1511 | status = WdfRequestRetrieveOutputBuffer(Request, 1512 | sizeof(HID_DEVICE_ATTRIBUTES), 1513 | (PVOID *)&deviceAttributes, 1514 | NULL); 1515 | if (!NT_SUCCESS(status)) 1516 | { 1517 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1518 | "WdfRequestRetrieveOutputBuffer failed 0x%x\n", status); 1519 | 1520 | return status; 1521 | } 1522 | 1523 | // 1524 | // Set USB device descriptor 1525 | // 1526 | 1527 | deviceAttributes->Size = sizeof(HID_DEVICE_ATTRIBUTES); 1528 | deviceAttributes->VendorID = RT5663_VID; 1529 | deviceAttributes->ProductID = RT5663_PID; 1530 | deviceAttributes->VersionNumber = RT5663_VERSION; 1531 | 1532 | // 1533 | // Report how many bytes were copied 1534 | // 1535 | WdfRequestSetInformation(Request, sizeof(HID_DEVICE_ATTRIBUTES)); 1536 | 1537 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1538 | "Rt5663GetDeviceAttributes Exit = 0x%x\n", status); 1539 | 1540 | return status; 1541 | } 1542 | 1543 | NTSTATUS 1544 | Rt5663GetString( 1545 | IN WDFREQUEST Request 1546 | ) 1547 | { 1548 | 1549 | NTSTATUS status = STATUS_SUCCESS; 1550 | PWSTR pwstrID; 1551 | size_t lenID; 1552 | WDF_REQUEST_PARAMETERS params; 1553 | void *pStringBuffer = NULL; 1554 | 1555 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1556 | "Rt5663GetString Entry\n"); 1557 | 1558 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1559 | WdfRequestGetParameters(Request, ¶ms); 1560 | 1561 | switch ((ULONG_PTR)params.Parameters.DeviceIoControl.Type3InputBuffer & 0xFFFF) 1562 | { 1563 | case HID_STRING_ID_IMANUFACTURER: 1564 | pwstrID = L"Rt5663.\0"; 1565 | break; 1566 | 1567 | case HID_STRING_ID_IPRODUCT: 1568 | pwstrID = L"MaxTouch Touch Screen\0"; 1569 | break; 1570 | 1571 | case HID_STRING_ID_ISERIALNUMBER: 1572 | pwstrID = L"123123123\0"; 1573 | break; 1574 | 1575 | default: 1576 | pwstrID = NULL; 1577 | break; 1578 | } 1579 | 1580 | lenID = pwstrID ? wcslen(pwstrID) * sizeof(WCHAR) + sizeof(UNICODE_NULL) : 0; 1581 | 1582 | if (pwstrID == NULL) 1583 | { 1584 | 1585 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1586 | "Rt5663GetString Invalid request type\n"); 1587 | 1588 | status = STATUS_INVALID_PARAMETER; 1589 | 1590 | return status; 1591 | } 1592 | 1593 | status = WdfRequestRetrieveOutputBuffer(Request, 1594 | lenID, 1595 | &pStringBuffer, 1596 | &lenID); 1597 | 1598 | if (!NT_SUCCESS(status)) 1599 | { 1600 | 1601 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1602 | "Rt5663GetString WdfRequestRetrieveOutputBuffer failed Status 0x%x\n", status); 1603 | 1604 | return status; 1605 | } 1606 | 1607 | RtlCopyMemory(pStringBuffer, pwstrID, lenID); 1608 | 1609 | WdfRequestSetInformation(Request, lenID); 1610 | 1611 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1612 | "Rt5663GetString Exit = 0x%x\n", status); 1613 | 1614 | return status; 1615 | } 1616 | 1617 | NTSTATUS 1618 | Rt5663WriteReport( 1619 | IN PRTEK_CONTEXT DevContext, 1620 | IN WDFREQUEST Request 1621 | ) 1622 | { 1623 | NTSTATUS status = STATUS_SUCCESS; 1624 | WDF_REQUEST_PARAMETERS params; 1625 | PHID_XFER_PACKET transferPacket = NULL; 1626 | size_t bytesWritten = 0; 1627 | 1628 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1629 | "Rt5663WriteReport Entry\n"); 1630 | 1631 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1632 | WdfRequestGetParameters(Request, ¶ms); 1633 | 1634 | if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET)) 1635 | { 1636 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1637 | "Rt5663WriteReport Xfer packet too small\n"); 1638 | 1639 | status = STATUS_BUFFER_TOO_SMALL; 1640 | } 1641 | else 1642 | { 1643 | 1644 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1645 | 1646 | if (transferPacket == NULL) 1647 | { 1648 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1649 | "Rt5663WriteReport No xfer packet\n"); 1650 | 1651 | status = STATUS_INVALID_DEVICE_REQUEST; 1652 | } 1653 | else 1654 | { 1655 | // 1656 | // switch on the report id 1657 | // 1658 | 1659 | switch (transferPacket->reportId) 1660 | { 1661 | case REPORTID_SPECKEYS: 1662 | status = STATUS_SUCCESS; 1663 | 1664 | CsAudioSpecialKeyReport report; 1665 | report.ReportID = REPORTID_SPECKEYS; 1666 | report.ControlCode = CONTROL_CODE_JACK_TYPE; 1667 | report.ControlValue = DevContext->JackType; 1668 | 1669 | size_t bytesWritten; 1670 | Rt5663ProcessVendorReport(DevContext, &report, sizeof(report), &bytesWritten); 1671 | break; 1672 | default: 1673 | 1674 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1675 | "Rt5663WriteReport Unhandled report type %d\n", transferPacket->reportId); 1676 | 1677 | status = STATUS_INVALID_PARAMETER; 1678 | 1679 | break; 1680 | } 1681 | } 1682 | } 1683 | 1684 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1685 | "Rt5663WriteReport Exit = 0x%x\n", status); 1686 | 1687 | return status; 1688 | 1689 | } 1690 | 1691 | NTSTATUS 1692 | Rt5663ProcessVendorReport( 1693 | IN PRTEK_CONTEXT DevContext, 1694 | IN PVOID ReportBuffer, 1695 | IN ULONG ReportBufferLen, 1696 | OUT size_t* BytesWritten 1697 | ) 1698 | { 1699 | NTSTATUS status = STATUS_SUCCESS; 1700 | WDFREQUEST reqRead; 1701 | PVOID pReadReport = NULL; 1702 | size_t bytesReturned = 0; 1703 | 1704 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1705 | "Rt5663ProcessVendorReport Entry\n"); 1706 | 1707 | status = WdfIoQueueRetrieveNextRequest(DevContext->ReportQueue, 1708 | &reqRead); 1709 | 1710 | if (NT_SUCCESS(status)) 1711 | { 1712 | status = WdfRequestRetrieveOutputBuffer(reqRead, 1713 | ReportBufferLen, 1714 | &pReadReport, 1715 | &bytesReturned); 1716 | 1717 | if (NT_SUCCESS(status)) 1718 | { 1719 | // 1720 | // Copy ReportBuffer into read request 1721 | // 1722 | 1723 | if (bytesReturned > ReportBufferLen) 1724 | { 1725 | bytesReturned = ReportBufferLen; 1726 | } 1727 | 1728 | RtlCopyMemory(pReadReport, 1729 | ReportBuffer, 1730 | bytesReturned); 1731 | 1732 | // 1733 | // Complete read with the number of bytes returned as info 1734 | // 1735 | 1736 | WdfRequestCompleteWithInformation(reqRead, 1737 | status, 1738 | bytesReturned); 1739 | 1740 | RtekPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1741 | "Rt5663ProcessVendorReport %d bytes returned\n", bytesReturned); 1742 | 1743 | // 1744 | // Return the number of bytes written for the write request completion 1745 | // 1746 | 1747 | *BytesWritten = bytesReturned; 1748 | 1749 | RtekPrint(DEBUG_LEVEL_INFO, DBG_IOCTL, 1750 | "%s completed, Queue:0x%p, Request:0x%p\n", 1751 | DbgHidInternalIoctlString(IOCTL_HID_READ_REPORT), 1752 | DevContext->ReportQueue, 1753 | reqRead); 1754 | } 1755 | else 1756 | { 1757 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1758 | "WdfRequestRetrieveOutputBuffer failed Status 0x%x\n", status); 1759 | } 1760 | } 1761 | else 1762 | { 1763 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1764 | "WdfIoQueueRetrieveNextRequest failed Status 0x%x\n", status); 1765 | } 1766 | 1767 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1768 | "Rt5663ProcessVendorReport Exit = 0x%x\n", status); 1769 | 1770 | return status; 1771 | } 1772 | 1773 | NTSTATUS 1774 | Rt5663ReadReport( 1775 | IN PRTEK_CONTEXT DevContext, 1776 | IN WDFREQUEST Request, 1777 | OUT BOOLEAN* CompleteRequest 1778 | ) 1779 | { 1780 | NTSTATUS status = STATUS_SUCCESS; 1781 | 1782 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1783 | "Rt5663ReadReport Entry\n"); 1784 | 1785 | // 1786 | // Forward this read request to our manual queue 1787 | // (in other words, we are going to defer this request 1788 | // until we have a corresponding write request to 1789 | // match it with) 1790 | // 1791 | 1792 | status = WdfRequestForwardToIoQueue(Request, DevContext->ReportQueue); 1793 | 1794 | if (!NT_SUCCESS(status)) 1795 | { 1796 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1797 | "WdfRequestForwardToIoQueue failed Status 0x%x\n", status); 1798 | } 1799 | else 1800 | { 1801 | *CompleteRequest = FALSE; 1802 | } 1803 | 1804 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1805 | "Rt5663ReadReport Exit = 0x%x\n", status); 1806 | 1807 | return status; 1808 | } 1809 | 1810 | NTSTATUS 1811 | Rt5663SetFeature( 1812 | IN PRTEK_CONTEXT DevContext, 1813 | IN WDFREQUEST Request, 1814 | OUT BOOLEAN* CompleteRequest 1815 | ) 1816 | { 1817 | NTSTATUS status = STATUS_SUCCESS; 1818 | WDF_REQUEST_PARAMETERS params; 1819 | PHID_XFER_PACKET transferPacket = NULL; 1820 | 1821 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1822 | "Rt5663SetFeature Entry\n"); 1823 | 1824 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1825 | WdfRequestGetParameters(Request, ¶ms); 1826 | 1827 | if (params.Parameters.DeviceIoControl.InputBufferLength < sizeof(HID_XFER_PACKET)) 1828 | { 1829 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1830 | "Rt5663SetFeature Xfer packet too small\n"); 1831 | 1832 | status = STATUS_BUFFER_TOO_SMALL; 1833 | } 1834 | else 1835 | { 1836 | 1837 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1838 | 1839 | if (transferPacket == NULL) 1840 | { 1841 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1842 | "Rt5663WriteReport No xfer packet\n"); 1843 | 1844 | status = STATUS_INVALID_DEVICE_REQUEST; 1845 | } 1846 | else 1847 | { 1848 | // 1849 | // switch on the report id 1850 | // 1851 | 1852 | switch (transferPacket->reportId) 1853 | { 1854 | default: 1855 | 1856 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1857 | "Rt5663SetFeature Unhandled report type %d\n", transferPacket->reportId); 1858 | 1859 | status = STATUS_INVALID_PARAMETER; 1860 | 1861 | break; 1862 | } 1863 | } 1864 | } 1865 | 1866 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1867 | "Rt5663SetFeature Exit = 0x%x\n", status); 1868 | 1869 | return status; 1870 | } 1871 | 1872 | NTSTATUS 1873 | Rt5663GetFeature( 1874 | IN PRTEK_CONTEXT DevContext, 1875 | IN WDFREQUEST Request, 1876 | OUT BOOLEAN* CompleteRequest 1877 | ) 1878 | { 1879 | NTSTATUS status = STATUS_SUCCESS; 1880 | WDF_REQUEST_PARAMETERS params; 1881 | PHID_XFER_PACKET transferPacket = NULL; 1882 | 1883 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1884 | "Rt5663GetFeature Entry\n"); 1885 | 1886 | WDF_REQUEST_PARAMETERS_INIT(¶ms); 1887 | WdfRequestGetParameters(Request, ¶ms); 1888 | 1889 | if (params.Parameters.DeviceIoControl.OutputBufferLength < sizeof(HID_XFER_PACKET)) 1890 | { 1891 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1892 | "Rt5663GetFeature Xfer packet too small\n"); 1893 | 1894 | status = STATUS_BUFFER_TOO_SMALL; 1895 | } 1896 | else 1897 | { 1898 | 1899 | transferPacket = (PHID_XFER_PACKET)WdfRequestWdmGetIrp(Request)->UserBuffer; 1900 | 1901 | if (transferPacket == NULL) 1902 | { 1903 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1904 | "Rt5663GetFeature No xfer packet\n"); 1905 | 1906 | status = STATUS_INVALID_DEVICE_REQUEST; 1907 | } 1908 | else 1909 | { 1910 | // 1911 | // switch on the report id 1912 | // 1913 | 1914 | switch (transferPacket->reportId) 1915 | { 1916 | default: 1917 | 1918 | RtekPrint(DEBUG_LEVEL_ERROR, DBG_IOCTL, 1919 | "Rt5663GetFeature Unhandled report type %d\n", transferPacket->reportId); 1920 | 1921 | status = STATUS_INVALID_PARAMETER; 1922 | 1923 | break; 1924 | } 1925 | } 1926 | } 1927 | 1928 | RtekPrint(DEBUG_LEVEL_VERBOSE, DBG_IOCTL, 1929 | "Rt5663GetFeature Exit = 0x%x\n", status); 1930 | 1931 | return status; 1932 | } 1933 | 1934 | PCHAR 1935 | DbgHidInternalIoctlString( 1936 | IN ULONG IoControlCode 1937 | ) 1938 | { 1939 | switch (IoControlCode) 1940 | { 1941 | case IOCTL_HID_GET_DEVICE_DESCRIPTOR: 1942 | return "IOCTL_HID_GET_DEVICE_DESCRIPTOR"; 1943 | case IOCTL_HID_GET_REPORT_DESCRIPTOR: 1944 | return "IOCTL_HID_GET_REPORT_DESCRIPTOR"; 1945 | case IOCTL_HID_READ_REPORT: 1946 | return "IOCTL_HID_READ_REPORT"; 1947 | case IOCTL_HID_GET_DEVICE_ATTRIBUTES: 1948 | return "IOCTL_HID_GET_DEVICE_ATTRIBUTES"; 1949 | case IOCTL_HID_WRITE_REPORT: 1950 | return "IOCTL_HID_WRITE_REPORT"; 1951 | case IOCTL_HID_SET_FEATURE: 1952 | return "IOCTL_HID_SET_FEATURE"; 1953 | case IOCTL_HID_GET_FEATURE: 1954 | return "IOCTL_HID_GET_FEATURE"; 1955 | case IOCTL_HID_GET_STRING: 1956 | return "IOCTL_HID_GET_STRING"; 1957 | case IOCTL_HID_ACTIVATE_DEVICE: 1958 | return "IOCTL_HID_ACTIVATE_DEVICE"; 1959 | case IOCTL_HID_DEACTIVATE_DEVICE: 1960 | return "IOCTL_HID_DEACTIVATE_DEVICE"; 1961 | case IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST: 1962 | return "IOCTL_HID_SEND_IDLE_NOTIFICATION_REQUEST"; 1963 | case IOCTL_HID_SET_OUTPUT_REPORT: 1964 | return "IOCTL_HID_SET_OUTPUT_REPORT"; 1965 | case IOCTL_HID_GET_INPUT_REPORT: 1966 | return "IOCTL_HID_GET_INPUT_REPORT"; 1967 | default: 1968 | return "Unknown IOCTL"; 1969 | } 1970 | } --------------------------------------------------------------------------------