1 // Copyright 2018 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use crate::pci::ac97_regs::*; 6 use crate::pci::PCI_VENDOR_ID_INTEL; 7 8 // Extented Audio ID 9 const AC97_EXTENDED_ID: u16 = MIXER_EI_VRA | MIXER_EI_CDAC | MIXER_EI_SDAC | MIXER_EI_LDAC; 10 11 // Master volume register is specified in 1.5dB steps. 12 const MASTER_VOLUME_STEP_DB: f64 = 1.5; 13 14 /// `Ac97Mixer` holds the mixer state for the AC97 bus. 15 /// The mixer is used by calling the `readb`/`readw`/`readl` functions to read register values and 16 /// the `writeb`/`writew`/`writel` functions to set register values. 17 pub struct Ac97Mixer { 18 // Mixer Registers 19 master_volume_l: u8, 20 master_volume_r: u8, 21 master_mute: bool, 22 mic_muted: bool, 23 mic_20db: bool, 24 mic_volume: u8, 25 record_gain_l: u8, 26 record_gain_r: u8, 27 record_gain_mute: bool, 28 pcm_out_vol_l: u16, 29 pcm_out_vol_r: u16, 30 pcm_out_mute: bool, 31 power_down_control: u16, 32 ext_audio_status_ctl: u16, 33 pcm_front_dac_rate: u16, 34 pcm_surr_dac_rate: u16, 35 pcm_lfe_dac_rate: u16, 36 } 37 38 impl Ac97Mixer { 39 /// Creates an 'Ac97Mixer' with the standard default register values. new() -> Self40 pub fn new() -> Self { 41 Ac97Mixer { 42 master_volume_l: 0, 43 master_volume_r: 0, 44 master_mute: true, 45 mic_muted: true, 46 mic_20db: false, 47 mic_volume: 0x8, 48 record_gain_l: 0, 49 record_gain_r: 0, 50 record_gain_mute: true, 51 pcm_out_vol_l: 0x8, 52 pcm_out_vol_r: 0x8, 53 pcm_out_mute: true, 54 power_down_control: PD_REG_STATUS_MASK, // Report everything is ready. 55 ext_audio_status_ctl: 0, 56 // Default to 48 kHz. 57 pcm_front_dac_rate: 0xBB80, 58 pcm_surr_dac_rate: 0xBB80, 59 pcm_lfe_dac_rate: 0xBB80, 60 } 61 } 62 reset(&mut self)63 pub fn reset(&mut self) { 64 // Upon reset, the audio sample rate registers default to 48 kHz, and VRA=0. 65 self.ext_audio_status_ctl &= !MIXER_EI_VRA; 66 self.pcm_front_dac_rate = 0xBB80; 67 self.pcm_surr_dac_rate = 0xBB80; 68 self.pcm_lfe_dac_rate = 0xBB80; 69 } 70 71 /// Reads a word from the register at `offset`. readw(&self, offset: u64) -> u1672 pub fn readw(&self, offset: u64) -> u16 { 73 match offset { 74 MIXER_RESET_00 => BC_DEDICATED_MIC, 75 MIXER_MASTER_VOL_MUTE_02 => self.get_master_reg(), 76 MIXER_MIC_VOL_MUTE_0E => self.get_mic_volume(), 77 MIXER_PCM_OUT_VOL_MUTE_18 => self.get_pcm_out_volume(), 78 MIXER_REC_VOL_MUTE_1C => self.get_record_gain_reg(), 79 MIXER_POWER_DOWN_CONTROL_26 => self.power_down_control, 80 MIXER_EXTENDED_AUDIO_ID_28 => AC97_EXTENDED_ID, 81 MIXER_VENDOR_ID1_7C => PCI_VENDOR_ID_INTEL, 82 MIXER_VENDOR_ID2_7E => PCI_VENDOR_ID_INTEL, 83 MIXER_EXTENDED_AUDIO_STATUS_CONTROL_28 => self.ext_audio_status_ctl, 84 MIXER_PCM_FRONT_DAC_RATE_2C => self.pcm_front_dac_rate, 85 MIXER_PCM_SURR_DAC_RATE_2E => self.pcm_surr_dac_rate, 86 MIXER_PCM_LFE_DAC_RATE_30 => self.pcm_lfe_dac_rate, 87 _ => 0, 88 } 89 } 90 91 /// Writes a word `val` to the register `offset`. writew(&mut self, offset: u64, val: u16)92 pub fn writew(&mut self, offset: u64, val: u16) { 93 match offset { 94 MIXER_RESET_00 => self.reset(), 95 MIXER_MASTER_VOL_MUTE_02 => self.set_master_reg(val), 96 MIXER_MIC_VOL_MUTE_0E => self.set_mic_volume(val), 97 MIXER_PCM_OUT_VOL_MUTE_18 => self.set_pcm_out_volume(val), 98 MIXER_REC_VOL_MUTE_1C => self.set_record_gain_reg(val), 99 MIXER_POWER_DOWN_CONTROL_26 => self.set_power_down_reg(val), 100 MIXER_EXTENDED_AUDIO_STATUS_CONTROL_28 => self.ext_audio_status_ctl = val, 101 MIXER_PCM_FRONT_DAC_RATE_2C => self.pcm_front_dac_rate = val, 102 MIXER_PCM_SURR_DAC_RATE_2E => self.pcm_surr_dac_rate = val, 103 MIXER_PCM_LFE_DAC_RATE_30 => self.pcm_lfe_dac_rate = val, 104 _ => (), 105 } 106 } 107 108 /// Returns the mute status and left and right attenuation from the master volume register. get_master_volume(&self) -> (bool, f64, f64)109 pub fn get_master_volume(&self) -> (bool, f64, f64) { 110 ( 111 self.master_mute, 112 f64::from(self.master_volume_l) * MASTER_VOLUME_STEP_DB, 113 f64::from(self.master_volume_r) * MASTER_VOLUME_STEP_DB, 114 ) 115 } 116 117 /// Returns the front sample rate (reg 0x2c). get_sample_rate(&self) -> u16118 pub fn get_sample_rate(&self) -> u16 { 119 // MIXER_PCM_FRONT_DAC_RATE_2C, MIXER_PCM_SURR_DAC_RATE_2E, and MIXER_PCM_LFE_DAC_RATE_30 120 // are updated to the same rate when playback with 2,4 and 6 tubes. 121 self.pcm_front_dac_rate 122 } 123 124 // Returns the master mute and l/r volumes (reg 0x02). get_master_reg(&self) -> u16125 fn get_master_reg(&self) -> u16 { 126 let reg = (u16::from(self.master_volume_l)) << 8 | u16::from(self.master_volume_r); 127 if self.master_mute { 128 reg | MUTE_REG_BIT 129 } else { 130 reg 131 } 132 } 133 134 // Handles writes to the master register (0x02). set_master_reg(&mut self, val: u16)135 fn set_master_reg(&mut self, val: u16) { 136 self.master_mute = val & MUTE_REG_BIT != 0; 137 self.master_volume_r = (val & VOL_REG_MASK) as u8; 138 self.master_volume_l = (val >> 8 & VOL_REG_MASK) as u8; 139 } 140 141 // Returns the value read in the Mic volume register (0x0e). get_mic_volume(&self) -> u16142 fn get_mic_volume(&self) -> u16 { 143 let mut reg = u16::from(self.mic_volume); 144 if self.mic_muted { 145 reg |= MUTE_REG_BIT; 146 } 147 if self.mic_20db { 148 reg |= MIXER_MIC_20DB; 149 } 150 reg 151 } 152 153 // Sets the mic input mute, boost, and volume settings (0x0e). set_mic_volume(&mut self, val: u16)154 fn set_mic_volume(&mut self, val: u16) { 155 self.mic_volume = (val & MIXER_VOL_MASK) as u8; 156 self.mic_muted = val & MUTE_REG_BIT != 0; 157 self.mic_20db = val & MIXER_MIC_20DB != 0; 158 } 159 160 // Returns the value read in the Mic volume register (0x18). get_pcm_out_volume(&self) -> u16161 fn get_pcm_out_volume(&self) -> u16 { 162 let reg = (self.pcm_out_vol_l as u16) << 8 | self.pcm_out_vol_r as u16; 163 if self.pcm_out_mute { 164 reg | MUTE_REG_BIT 165 } else { 166 reg 167 } 168 } 169 170 // Sets the pcm output mute and volume states (0x18). set_pcm_out_volume(&mut self, val: u16)171 fn set_pcm_out_volume(&mut self, val: u16) { 172 self.pcm_out_vol_r = val & MIXER_VOL_MASK; 173 self.pcm_out_vol_l = (val >> MIXER_VOL_LEFT_SHIFT) & MIXER_VOL_MASK; 174 self.pcm_out_mute = val & MUTE_REG_BIT != 0; 175 } 176 177 // Returns the record gain register (0x01c). get_record_gain_reg(&self) -> u16178 fn get_record_gain_reg(&self) -> u16 { 179 let reg = u16::from(self.record_gain_l) << 8 | u16::from(self.record_gain_r); 180 if self.record_gain_mute { 181 reg | MUTE_REG_BIT 182 } else { 183 reg 184 } 185 } 186 187 // Handles writes to the record_gain register (0x1c). set_record_gain_reg(&mut self, val: u16)188 fn set_record_gain_reg(&mut self, val: u16) { 189 self.record_gain_mute = val & MUTE_REG_BIT != 0; 190 self.record_gain_r = (val & VOL_REG_MASK) as u8; 191 self.record_gain_l = (val >> 8 & VOL_REG_MASK) as u8; 192 } 193 194 // Handles writes to the powerdown ctrl/status register (0x26). set_power_down_reg(&mut self, val: u16)195 fn set_power_down_reg(&mut self, val: u16) { 196 self.power_down_control = 197 (val & !PD_REG_STATUS_MASK) | (self.power_down_control & PD_REG_STATUS_MASK); 198 } 199 } 200