• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #![allow(dead_code)]
6 
7 // Audio Mixer Registers
8 // 00h Reset
9 // 02h Master Volume Mute
10 // 04h Headphone Volume Mute
11 // 06h Master Volume Mono Mute
12 // 08h Master Tone (R & L)
13 // 0Ah PC_BEEP Volume Mute
14 // 0Ch Phone Volume Mute
15 // 0Eh Mic Volume Mute
16 // 10h Line In Volume Mute
17 // 12h CD Volume Mute
18 // 14h Video Volume Mute
19 // 16h Aux Volume Mute
20 // 18h PCM Out Volume Mute
21 // 1Ah Record Select
22 // 1Ch Record Gain Mute
23 // 1Eh Record Gain Mic Mute
24 // 20h General Purpose
25 // 22h 3D Control
26 // 24h AC’97 RESERVED
27 // 26h Powerdown Ctrl/Stat
28 // 28h Extended Audio ID
29 // 2Ah Extended Audio Status and Control
30 // 2CH PCM Front DAC Rate
31 // 2Eh PCM Surr DAC Rate
32 // 30h PCM LFE DAC Rate
33 // 32h PCM L/R ADC Rate
34 // 34h PCM MIC ADC Rate
35 
36 // Size of IO register regions
37 pub const MIXER_REGS_SIZE: u64 = 0x100;
38 pub const MASTER_REGS_SIZE: u64 = 0x400;
39 
40 pub const MIXER_RESET_00: u64 = 0x00;
41 pub const MIXER_MASTER_VOL_MUTE_02: u64 = 0x02;
42 pub const MIXER_MIC_VOL_MUTE_0E: u64 = 0x0e;
43 pub const MIXER_PCM_OUT_VOL_MUTE_18: u64 = 0x18;
44 pub const MIXER_REC_VOL_MUTE_1C: u64 = 0x1c;
45 pub const MIXER_POWER_DOWN_CONTROL_26: u64 = 0x26;
46 pub const MIXER_EXTENDED_AUDIO_ID_28: u64 = 0x28;
47 pub const MIXER_EXTENDED_AUDIO_STATUS_CONTROL_28: u64 = 0x2a;
48 pub const MIXER_PCM_FRONT_DAC_RATE_2C: u64 = 0x2c;
49 pub const MIXER_PCM_SURR_DAC_RATE_2E: u64 = 0x2e;
50 pub const MIXER_PCM_LFE_DAC_RATE_30: u64 = 0x30;
51 pub const MIXER_VENDOR_ID1_7C: u64 = 0x7c;
52 pub const MIXER_VENDOR_ID2_7E: u64 = 0x7e;
53 
54 // Extended Audio ID Bits.
55 pub const MIXER_EI_VRA: u16 = 0x0001; // Variable Rate Audio mode is available.
56 pub const MIXER_EI_CDAC: u16 = 0x0040; // PCM Center DAC is available.
57 pub const MIXER_EI_SDAC: u16 = 0x0080; // PCM Surround DAC is available.
58 pub const MIXER_EI_LDAC: u16 = 0x0100; // PCM LFE DAC is available.
59 
60 // Basic capabilities for MIXER_RESET_00
61 pub const BC_DEDICATED_MIC: u16 = 0x0001; /* Dedicated Mic PCM In Tube */
62 
63 // Bus Master regs from ICH spec:
64 // 00h PI_BDBAR PCM In Buffer Descriptor list Base Address Register
65 // 04h PI_CIV PCM In Current Index Value
66 // 05h PI_LVI PCM In Last Valid Index
67 // 06h PI_SR PCM In Status Register
68 // 08h PI_PICB PCM In Position In Current Buffer
69 // 0Ah PI_PIV PCM In Prefetched Index Value
70 // 0Bh PI_CR PCM In Control Register
71 // 10h PO_BDBAR PCM Out Buffer Descriptor list Base Address Register
72 // 14h PO_CIV PCM Out Current Index Value
73 // 15h PO_LVI PCM Out Last Valid Index
74 // 16h PO_SR PCM Out Status Register
75 // 18h PO_PICB PCM Out Position In Current Buffer
76 // 1Ah PO_PIV PCM Out Prefetched Index Value
77 // 1Bh PO_CR PCM Out Control Register
78 // 20h MC_BDBAR Mic. In Buffer Descriptor list Base Address Register
79 // 24h PM_CIV Mic. In Current Index Value
80 // 25h MC_LVI Mic. In Last Valid Index
81 // 26h MC_SR Mic. In Status Register
82 // 28h MC_PICB Mic In Position In Current Buffer
83 // 2Ah MC_PIV Mic. In Prefetched Index Value
84 // 2Bh MC_CR Mic. In Control Register
85 // 2Ch GLOB_CNT Global Control
86 // 30h GLOB_STA Global Status
87 // 34h ACC_SEMA Codec Write Semaphore Register
88 
89 // Global Control
90 pub const GLOB_CNT_2C: u64 = 0x2C;
91 pub const GLOB_CNT_COLD_RESET: u32 = 0x0000_0002;
92 pub const GLOB_CNT_WARM_RESET: u32 = 0x0000_0004;
93 pub const GLOB_CNT_STABLE_BITS: u32 = 0x0000_007f; // Bits not affected by reset.
94 
95 // PCM 4/6 Enable bits
96 pub const GLOB_CNT_PCM_2: u32 = 0x0000_0000; // 2 tubes
97 pub const GLOB_CNT_PCM_4: u32 = 0x0010_0000; // 4 tubes
98 pub const GLOB_CNT_PCM_6: u32 = 0x0020_0000; // 6 tubes
99 pub const GLOB_CNT_PCM_246_MASK: u32 = GLOB_CNT_PCM_4 | GLOB_CNT_PCM_6; // tube mask
100 
101 // Global status
102 pub const GLOB_STA_30: u64 = 0x30;
103 // Primary codec ready set and turn on D20:21 to support 4 and 6 tubes on PCM out.
104 pub const GLOB_STA_RESET_VAL: u32 = 0x0030_0100;
105 
106 // glob_sta bits
107 pub const GS_MD3: u32 = 1 << 17;
108 pub const GS_AD3: u32 = 1 << 16;
109 pub const GS_RCS: u32 = 1 << 15;
110 pub const GS_B3S12: u32 = 1 << 14;
111 pub const GS_B2S12: u32 = 1 << 13;
112 pub const GS_B1S12: u32 = 1 << 12;
113 pub const GS_S1R1: u32 = 1 << 11;
114 pub const GS_S0R1: u32 = 1 << 10;
115 pub const GS_S1CR: u32 = 1 << 9;
116 pub const GS_S0CR: u32 = 1 << 8;
117 pub const GS_MINT: u32 = 1 << 7;
118 pub const GS_POINT: u32 = 1 << 6;
119 pub const GS_PIINT: u32 = 1 << 5;
120 pub const GS_RSRVD: u32 = 1 << 4 | 1 << 3;
121 pub const GS_MOINT: u32 = 1 << 2;
122 pub const GS_MIINT: u32 = 1 << 1;
123 pub const GS_GSCI: u32 = 1;
124 pub const GS_RO_MASK: u32 = GS_B3S12
125     | GS_B2S12
126     | GS_B1S12
127     | GS_S1CR
128     | GS_S0CR
129     | GS_MINT
130     | GS_POINT
131     | GS_PIINT
132     | GS_RSRVD
133     | GS_MOINT
134     | GS_MIINT;
135 pub const GS_VALID_MASK: u32 = 0x0003_ffff;
136 pub const GS_WCLEAR_MASK: u32 = GS_RCS | GS_S1R1 | GS_S0R1 | GS_GSCI;
137 
138 pub const ACC_SEMA_34: u64 = 0x34;
139 
140 // Audio funciton registers.
141 pub const CIV_OFFSET: u64 = 0x04;
142 pub const LVI_OFFSET: u64 = 0x05;
143 pub const SR_OFFSET: u64 = 0x06;
144 pub const PICB_OFFSET: u64 = 0x08;
145 pub const PIV_OFFSET: u64 = 0x0a;
146 pub const CR_OFFSET: u64 = 0x0b;
147 
148 // Capture
149 pub const PI_BASE_00: u64 = 0x00;
150 pub const PI_BDBAR_00: u64 = PI_BASE_00;
151 pub const PI_CIV_04: u64 = PI_BASE_00 + CIV_OFFSET;
152 pub const PI_LVI_05: u64 = PI_BASE_00 + LVI_OFFSET;
153 pub const PI_SR_06: u64 = PI_BASE_00 + SR_OFFSET;
154 pub const PI_PICB_08: u64 = PI_BASE_00 + PICB_OFFSET;
155 pub const PI_PIV_0A: u64 = PI_BASE_00 + PIV_OFFSET;
156 pub const PI_CR_0B: u64 = PI_BASE_00 + CR_OFFSET;
157 
158 // Play Out
159 pub const PO_BASE_10: u64 = 0x10;
160 pub const PO_BDBAR_10: u64 = PO_BASE_10;
161 pub const PO_CIV_14: u64 = PO_BASE_10 + CIV_OFFSET;
162 pub const PO_LVI_15: u64 = PO_BASE_10 + LVI_OFFSET;
163 pub const PO_SR_16: u64 = PO_BASE_10 + SR_OFFSET;
164 pub const PO_PICB_18: u64 = PO_BASE_10 + PICB_OFFSET;
165 pub const PO_PIV_1A: u64 = PO_BASE_10 + PIV_OFFSET;
166 pub const PO_CR_1B: u64 = PO_BASE_10 + CR_OFFSET;
167 
168 // Microphone
169 pub const MC_BASE_20: u64 = 0x20;
170 pub const MC_BDBAR_20: u64 = MC_BASE_20;
171 pub const MC_CIV_24: u64 = MC_BASE_20 + CIV_OFFSET;
172 pub const MC_LVI_25: u64 = MC_BASE_20 + LVI_OFFSET;
173 pub const MC_SR_26: u64 = MC_BASE_20 + SR_OFFSET;
174 pub const MC_PICB_28: u64 = MC_BASE_20 + PICB_OFFSET;
175 pub const MC_PIV_2A: u64 = MC_BASE_20 + PIV_OFFSET;
176 pub const MC_CR_2B: u64 = MC_BASE_20 + CR_OFFSET;
177 
178 // Status Register Bits.
179 pub const SR_DCH: u16 = 0x01;
180 pub const SR_CELV: u16 = 0x02;
181 pub const SR_LVBCI: u16 = 0x04;
182 pub const SR_BCIS: u16 = 0x08;
183 pub const SR_FIFOE: u16 = 0x10;
184 pub const SR_VALID_MASK: u16 = 0x1f;
185 pub const SR_WCLEAR_MASK: u16 = SR_FIFOE | SR_BCIS | SR_LVBCI;
186 pub const SR_RO_MASK: u16 = SR_DCH | SR_CELV;
187 pub const SR_INT_MASK: u16 = SR_BCIS | SR_LVBCI;
188 
189 // Control Register Bits.
190 pub const CR_RPBM: u8 = 0x01;
191 pub const CR_RR: u8 = 0x02;
192 pub const CR_LVBIE: u8 = 0x04;
193 pub const CR_FEIE: u8 = 0x08;
194 pub const CR_IOCE: u8 = 0x10;
195 pub const CR_VALID_MASK: u8 = 0x1f;
196 pub const CR_DONT_CLEAR_MASK: u8 = CR_IOCE | CR_FEIE | CR_LVBIE;
197 
198 // Mixer register bits
199 pub const MUTE_REG_BIT: u16 = 0x8000;
200 pub const VOL_REG_MASK: u16 = 0x003f;
201 pub const MIXER_VOL_MASK: u16 = 0x001f;
202 pub const MIXER_VOL_LEFT_SHIFT: usize = 8;
203 pub const MIXER_MIC_20DB: u16 = 0x0040;
204 // Powerdown reg
205 pub const PD_REG_STATUS_MASK: u16 = 0x000f;
206 pub const PD_REG_OUTPUT_MUTE_MASK: u16 = 0xb200;
207 pub const PD_REG_INPUT_MUTE_MASK: u16 = 0x0d00;
208 
209 // Buffer descriptors are four bytes of pointer and 4 bytes of control/length.
210 pub const DESCRIPTOR_LENGTH: usize = 8;
211 pub const BD_IOC: u32 = 1 << 31;
212 
213 /// The functions that are supported by the Ac97 subsystem.
214 #[derive(Debug, Copy, Clone, PartialEq)]
215 pub enum Ac97Function {
216     Input,
217     Output,
218     Microphone,
219 }
220 
221 /// Registers for individual audio functions.
222 /// Each audio function in Ac97 gets a set of these registers.
223 #[derive(Clone, Default)]
224 pub struct Ac97FunctionRegs {
225     pub bdbar: u32,
226     pub civ: u8,
227     pub lvi: u8,
228     pub sr: u16,
229     pub picb: u16,
230     pub piv: u8,
231     pub cr: u8,
232 }
233 
234 impl Ac97FunctionRegs {
235     /// Creates a new set of function registers, these can be used for the capture, playback, or
236     /// microphone functions.
new() -> Self237     pub fn new() -> Self {
238         let mut regs = Ac97FunctionRegs {
239             sr: SR_DCH,
240             ..Default::default()
241         };
242         regs.do_reset();
243         regs
244     }
245 
246     /// Reset all the registers to the PoR defaults. `sr` should be updated by `update_sr`.
do_reset(&mut self)247     pub fn do_reset(&mut self) {
248         self.bdbar = 0;
249         self.civ = 0;
250         self.lvi = 0;
251         self.picb = 0;
252         self.piv = 0;
253         self.cr &= CR_DONT_CLEAR_MASK;
254     }
255 
256     /// Read register 4, 5, and 6 as one 32 bit word.
257     /// According to the ICH spec, reading these three with one 32 bit access is allowed.
atomic_status_regs(&self) -> u32258     pub fn atomic_status_regs(&self) -> u32 {
259         u32::from(self.civ) | u32::from(self.lvi) << 8 | u32::from(self.sr) << 16
260     }
261 
262     /// Returns the mask for enabled interrupts. The returned mask represents the bits in the status
263     /// register that should trigger and interrupt.
int_mask(&self) -> u16264     pub fn int_mask(&self) -> u16 {
265         let mut int_mask = 0;
266         if self.cr & CR_LVBIE != 0 {
267             int_mask |= SR_LVBCI;
268         }
269         if self.cr & CR_IOCE != 0 {
270             int_mask |= SR_BCIS;
271         }
272         int_mask
273     }
274 
275     /// Sets the current buffer to the next buffer by updating CIV to PIV, and
276     /// updates related fields.
move_to_next_buffer(&mut self)277     pub fn move_to_next_buffer(&mut self) {
278         self.civ = self.piv;
279         self.piv = (self.piv + 1) % 32; // move piv to the next buffer.
280     }
281 
282     /// Returns irq status.
has_irq(&self) -> bool283     pub fn has_irq(&self) -> bool {
284         self.sr & self.int_mask() != 0
285     }
286 }
287