1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Rockchip RK3308 internal audio codec driver 4 * 5 * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved. 6 * Copyright (c) 2024, Vivax-Metrotech Ltd 7 */ 8 9 #include <linux/clk.h> 10 #include <linux/device.h> 11 #include <linux/delay.h> 12 #include <linux/init.h> 13 #include <linux/io.h> 14 #include <linux/mfd/syscon.h> 15 #include <linux/module.h> 16 #include <linux/of.h> 17 #include <linux/platform_device.h> 18 #include <linux/regmap.h> 19 #include <linux/reset.h> 20 #include <linux/util_macros.h> 21 #include <sound/core.h> 22 #include <sound/pcm.h> 23 #include <sound/pcm_params.h> 24 #include <sound/soc.h> 25 #include <sound/tlv.h> 26 27 #include "rk3308_codec.h" 28 29 #define ADC_LR_GROUP_MAX 4 30 31 #define GRF_CHIP_ID 0x800 32 33 enum { 34 ACODEC_VERSION_A = 'A', 35 ACODEC_VERSION_B, 36 ACODEC_VERSION_C, 37 }; 38 39 struct rk3308_codec_priv { 40 const struct device *dev; 41 struct regmap *regmap; 42 struct regmap *grf; 43 struct reset_control *reset; 44 struct clk *hclk; 45 struct clk *mclk_rx; 46 struct clk *mclk_tx; 47 struct snd_soc_component *component; 48 unsigned char codec_ver; 49 }; 50 51 static struct clk_bulk_data rk3308_codec_clocks[] = { 52 { .id = "hclk" }, 53 { .id = "mclk_rx" }, 54 { .id = "mclk_tx" }, 55 }; 56 57 static const DECLARE_TLV_DB_SCALE(rk3308_codec_adc_alc_gain_tlv, -1800, 150, 0); 58 static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpout_gain_tlv, -3900, 150, 0); 59 static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpmix_gain_tlv, -600, 600, 0); 60 61 static const DECLARE_TLV_DB_RANGE(rk3308_codec_dac_lineout_gain_tlv, 62 0, 0, TLV_DB_SCALE_ITEM(-600, 0, 0), 63 1, 1, TLV_DB_SCALE_ITEM(-300, 0, 0), 64 2, 2, TLV_DB_SCALE_ITEM(-150, 0, 0), 65 3, 3, TLV_DB_SCALE_ITEM(0, 0, 0), 66 ); 67 68 static const char * const rk3308_codec_hpf_cutoff_text[] = { 69 "20 Hz", "245 Hz", "612 Hz" 70 }; 71 72 static SOC_ENUM_SINGLE_DECL(rk3308_codec_hpf_cutoff_enum12, RK3308_ADC_DIG_CON04(0), 0, 73 rk3308_codec_hpf_cutoff_text); 74 static SOC_ENUM_SINGLE_DECL(rk3308_codec_hpf_cutoff_enum34, RK3308_ADC_DIG_CON04(1), 0, 75 rk3308_codec_hpf_cutoff_text); 76 static SOC_ENUM_SINGLE_DECL(rk3308_codec_hpf_cutoff_enum56, RK3308_ADC_DIG_CON04(2), 0, 77 rk3308_codec_hpf_cutoff_text); 78 static SOC_ENUM_SINGLE_DECL(rk3308_codec_hpf_cutoff_enum78, RK3308_ADC_DIG_CON04(3), 0, 79 rk3308_codec_hpf_cutoff_text); 80 81 static const struct snd_kcontrol_new rk3308_codec_controls[] = { 82 /* Despite the register names, these set the gain when AGC is OFF */ 83 SOC_SINGLE_RANGE_TLV("MIC1 Capture Volume", 84 RK3308_ADC_ANA_CON03(0), 85 RK3308_ADC_CH1_ALC_GAIN_SFT, 86 RK3308_ADC_CH1_ALC_GAIN_MIN, 87 RK3308_ADC_CH1_ALC_GAIN_MAX, 88 0, rk3308_codec_adc_alc_gain_tlv), 89 SOC_SINGLE_RANGE_TLV("MIC2 Capture Volume", 90 RK3308_ADC_ANA_CON04(0), 91 RK3308_ADC_CH2_ALC_GAIN_SFT, 92 RK3308_ADC_CH2_ALC_GAIN_MIN, 93 RK3308_ADC_CH2_ALC_GAIN_MAX, 94 0, rk3308_codec_adc_alc_gain_tlv), 95 SOC_SINGLE_RANGE_TLV("MIC3 Capture Volume", 96 RK3308_ADC_ANA_CON03(1), 97 RK3308_ADC_CH1_ALC_GAIN_SFT, 98 RK3308_ADC_CH1_ALC_GAIN_MIN, 99 RK3308_ADC_CH1_ALC_GAIN_MAX, 100 0, rk3308_codec_adc_alc_gain_tlv), 101 SOC_SINGLE_RANGE_TLV("MIC4 Capture Volume", 102 RK3308_ADC_ANA_CON04(1), 103 RK3308_ADC_CH2_ALC_GAIN_SFT, 104 RK3308_ADC_CH2_ALC_GAIN_MIN, 105 RK3308_ADC_CH2_ALC_GAIN_MAX, 106 0, rk3308_codec_adc_alc_gain_tlv), 107 SOC_SINGLE_RANGE_TLV("MIC5 Capture Volume", 108 RK3308_ADC_ANA_CON03(2), 109 RK3308_ADC_CH1_ALC_GAIN_SFT, 110 RK3308_ADC_CH1_ALC_GAIN_MIN, 111 RK3308_ADC_CH1_ALC_GAIN_MAX, 112 0, rk3308_codec_adc_alc_gain_tlv), 113 SOC_SINGLE_RANGE_TLV("MIC6 Capture Volume", 114 RK3308_ADC_ANA_CON04(2), 115 RK3308_ADC_CH2_ALC_GAIN_SFT, 116 RK3308_ADC_CH2_ALC_GAIN_MIN, 117 RK3308_ADC_CH2_ALC_GAIN_MAX, 118 0, rk3308_codec_adc_alc_gain_tlv), 119 SOC_SINGLE_RANGE_TLV("MIC7 Capture Volume", 120 RK3308_ADC_ANA_CON03(3), 121 RK3308_ADC_CH1_ALC_GAIN_SFT, 122 RK3308_ADC_CH1_ALC_GAIN_MIN, 123 RK3308_ADC_CH1_ALC_GAIN_MAX, 124 0, rk3308_codec_adc_alc_gain_tlv), 125 SOC_SINGLE_RANGE_TLV("MIC8 Capture Volume", 126 RK3308_ADC_ANA_CON04(3), 127 RK3308_ADC_CH2_ALC_GAIN_SFT, 128 RK3308_ADC_CH2_ALC_GAIN_MIN, 129 RK3308_ADC_CH2_ALC_GAIN_MAX, 130 0, rk3308_codec_adc_alc_gain_tlv), 131 132 SOC_SINGLE("MIC1 Capture Switch", RK3308_ADC_ANA_CON00(0), 3, 1, 0), 133 SOC_SINGLE("MIC2 Capture Switch", RK3308_ADC_ANA_CON00(0), 7, 1, 0), 134 SOC_SINGLE("MIC3 Capture Switch", RK3308_ADC_ANA_CON00(1), 3, 1, 0), 135 SOC_SINGLE("MIC4 Capture Switch", RK3308_ADC_ANA_CON00(1), 7, 1, 0), 136 SOC_SINGLE("MIC5 Capture Switch", RK3308_ADC_ANA_CON00(2), 3, 1, 0), 137 SOC_SINGLE("MIC6 Capture Switch", RK3308_ADC_ANA_CON00(2), 7, 1, 0), 138 SOC_SINGLE("MIC7 Capture Switch", RK3308_ADC_ANA_CON00(3), 3, 1, 0), 139 SOC_SINGLE("MIC8 Capture Switch", RK3308_ADC_ANA_CON00(3), 7, 1, 0), 140 141 SOC_SINGLE("MIC12 HPF Capture Switch", RK3308_ADC_DIG_CON04(0), 2, 1, 1), 142 SOC_SINGLE("MIC34 HPF Capture Switch", RK3308_ADC_DIG_CON04(1), 2, 1, 1), 143 SOC_SINGLE("MIC56 HPF Capture Switch", RK3308_ADC_DIG_CON04(2), 2, 1, 1), 144 SOC_SINGLE("MIC78 HPF Capture Switch", RK3308_ADC_DIG_CON04(3), 2, 1, 1), 145 146 SOC_ENUM("MIC12 HPF Cutoff", rk3308_codec_hpf_cutoff_enum12), 147 SOC_ENUM("MIC34 HPF Cutoff", rk3308_codec_hpf_cutoff_enum34), 148 SOC_ENUM("MIC56 HPF Cutoff", rk3308_codec_hpf_cutoff_enum56), 149 SOC_ENUM("MIC78 HPF Cutoff", rk3308_codec_hpf_cutoff_enum78), 150 151 SOC_DOUBLE_TLV("Line Out Playback Volume", 152 RK3308_DAC_ANA_CON04, 153 RK3308_DAC_L_LINEOUT_GAIN_SFT, 154 RK3308_DAC_R_LINEOUT_GAIN_SFT, 155 RK3308_DAC_x_LINEOUT_GAIN_MAX, 156 0, rk3308_codec_dac_lineout_gain_tlv), 157 SOC_DOUBLE("Line Out Playback Switch", 158 RK3308_DAC_ANA_CON04, 159 RK3308_DAC_L_LINEOUT_MUTE_SFT, 160 RK3308_DAC_R_LINEOUT_MUTE_SFT, 1, 0), 161 SOC_DOUBLE_R_TLV("Headphone Playback Volume", 162 RK3308_DAC_ANA_CON05, 163 RK3308_DAC_ANA_CON06, 164 RK3308_DAC_x_HPOUT_GAIN_SFT, 165 RK3308_DAC_x_HPOUT_GAIN_MAX, 166 0, rk3308_codec_dac_hpout_gain_tlv), 167 SOC_DOUBLE("Headphone Playback Switch", 168 RK3308_DAC_ANA_CON03, 169 RK3308_DAC_L_HPOUT_MUTE_SFT, 170 RK3308_DAC_R_HPOUT_MUTE_SFT, 1, 0), 171 SOC_DOUBLE_RANGE_TLV("DAC HPMIX Playback Volume", 172 RK3308_DAC_ANA_CON12, 173 RK3308_DAC_L_HPMIX_GAIN_SFT, 174 RK3308_DAC_R_HPMIX_GAIN_SFT, 175 1, 2, 0, rk3308_codec_dac_hpmix_gain_tlv), 176 }; 177 178 static int rk3308_codec_pop_sound_set(struct snd_soc_dapm_widget *w, 179 struct snd_kcontrol *kcontrol, 180 int event) 181 { 182 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 183 struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); 184 unsigned int val = (event == SND_SOC_DAPM_POST_PMU) ? 185 RK3308_DAC_HPOUT_POP_SOUND_x_WORK : 186 RK3308_DAC_HPOUT_POP_SOUND_x_INIT; 187 unsigned int mask = RK3308_DAC_HPOUT_POP_SOUND_x_MSK; 188 189 regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, 190 mask << w->shift, val << w->shift); 191 192 return 0; 193 } 194 195 static int rk3308_codec_dac_output_vcm_event(struct snd_soc_dapm_widget *w, 196 struct snd_kcontrol *kcontrol, 197 int event) 198 { 199 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 200 struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); 201 unsigned int val; 202 203 if (rk3308->codec_ver != ACODEC_VERSION_B) 204 return 0; 205 206 switch (event) { 207 case SND_SOC_DAPM_PRE_PMU: 208 /* Keep the DAC outputs at VCM while their reference is charged. */ 209 regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, 210 RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | 211 RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, 212 RK3308_DAC_L_SEL_DC_FROM_VCM | 213 RK3308_DAC_R_SEL_DC_FROM_VCM); 214 regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, 215 RK3308_DAC_CURRENT_CHARGE_MSK, 1); 216 regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, 217 RK3308_DAC_VCM_LINEOUT_EN); 218 for (val = 1; val <= 0xf; val++) { 219 regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, 220 RK3308_DAC_CURRENT_CHARGE_MSK, val); 221 usleep_range(200, 400); 222 } 223 msleep(20); 224 break; 225 case SND_SOC_DAPM_POST_PMU: 226 regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, 227 RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | 228 RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, 229 RK3308_DAC_L_SEL_DC_FROM_INTERNAL | 230 RK3308_DAC_R_SEL_DC_FROM_INTERNAL); 231 break; 232 case SND_SOC_DAPM_POST_PMD: 233 regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, 234 RK3308_DAC_LINEOUT_POP_SOUND_L_MSK | 235 RK3308_DAC_LINEOUT_POP_SOUND_R_MSK, 236 RK3308_DAC_L_SEL_DC_FROM_VCM | 237 RK3308_DAC_R_SEL_DC_FROM_VCM); 238 regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, 239 RK3308_DAC_CURRENT_CHARGE_MSK, 1); 240 regmap_clear_bits(rk3308->regmap, RK3308_DAC_ANA_CON14, 241 RK3308_DAC_VCM_LINEOUT_EN); 242 break; 243 default: 244 break; 245 } 246 247 return 0; 248 } 249 250 static int rk3308_codec_lineout_event(struct snd_soc_dapm_widget *w, 251 struct snd_kcontrol *kcontrol, 252 int event) 253 { 254 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 255 struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); 256 unsigned int mask = RK3308_DAC_LINEOUT_POP_SOUND_L_MSK << w->shift; 257 unsigned int val; 258 259 if (rk3308->codec_ver != ACODEC_VERSION_B) 260 return 0; 261 262 switch (event) { 263 case SND_SOC_DAPM_POST_PMU: 264 val = RK3308_DAC_L_SEL_LINEOUT_FROM_INTERNAL << w->shift; 265 break; 266 case SND_SOC_DAPM_POST_PMD: 267 val = RK3308_DAC_L_SEL_DC_FROM_INTERNAL << w->shift; 268 break; 269 default: 270 return 0; 271 } 272 273 regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15, mask, val); 274 usleep_range(20, 40); 275 276 return 0; 277 } 278 279 static const struct snd_soc_dapm_widget rk3308_codec_dapm_widgets[] = { 280 SND_SOC_DAPM_INPUT("MIC1"), 281 SND_SOC_DAPM_INPUT("MIC2"), 282 SND_SOC_DAPM_INPUT("MIC3"), 283 SND_SOC_DAPM_INPUT("MIC4"), 284 SND_SOC_DAPM_INPUT("MIC5"), 285 SND_SOC_DAPM_INPUT("MIC6"), 286 SND_SOC_DAPM_INPUT("MIC7"), 287 SND_SOC_DAPM_INPUT("MIC8"), 288 289 SND_SOC_DAPM_SUPPLY("ADC_CURRENT_EN12", RK3308_ADC_ANA_CON06(0), 0, 0, NULL, 0), 290 SND_SOC_DAPM_SUPPLY("ADC_CURRENT_EN34", RK3308_ADC_ANA_CON06(1), 0, 0, NULL, 0), 291 SND_SOC_DAPM_SUPPLY("ADC_CURRENT_EN56", RK3308_ADC_ANA_CON06(2), 0, 0, NULL, 0), 292 SND_SOC_DAPM_SUPPLY("ADC_CURRENT_EN78", RK3308_ADC_ANA_CON06(3), 0, 0, NULL, 0), 293 294 SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC1_EN", RK3308_ADC_ANA_CON00(0), 1, 1, 1, 0), 295 SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC2_EN", RK3308_ADC_ANA_CON00(0), 5, 1, 1, 0), 296 SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC3_EN", RK3308_ADC_ANA_CON00(1), 1, 1, 1, 0), 297 SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC4_EN", RK3308_ADC_ANA_CON00(1), 5, 1, 1, 0), 298 SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC5_EN", RK3308_ADC_ANA_CON00(2), 1, 1, 1, 0), 299 SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC6_EN", RK3308_ADC_ANA_CON00(2), 5, 1, 1, 0), 300 SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC7_EN", RK3308_ADC_ANA_CON00(3), 1, 1, 1, 0), 301 SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC8_EN", RK3308_ADC_ANA_CON00(3), 5, 1, 1, 0), 302 303 SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC1_WORK", RK3308_ADC_ANA_CON00(0), 2, 1, 1, 0), 304 SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC2_WORK", RK3308_ADC_ANA_CON00(0), 6, 1, 1, 0), 305 SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC3_WORK", RK3308_ADC_ANA_CON00(1), 2, 1, 1, 0), 306 SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC4_WORK", RK3308_ADC_ANA_CON00(1), 6, 1, 1, 0), 307 SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC5_WORK", RK3308_ADC_ANA_CON00(2), 2, 1, 1, 0), 308 SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC6_WORK", RK3308_ADC_ANA_CON00(2), 6, 1, 1, 0), 309 SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC7_WORK", RK3308_ADC_ANA_CON00(3), 2, 1, 1, 0), 310 SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC8_WORK", RK3308_ADC_ANA_CON00(3), 6, 1, 1, 0), 311 312 /* 313 * In theory MIC1 and MIC2 can switch to LINE IN, but this is not 314 * supported so all we can do is enabling the MIC input. 315 */ 316 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "CH1_IN_SEL", RK3308_ADC_ANA_CON07(0), 4, 1, 1, 0), 317 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "CH2_IN_SEL", RK3308_ADC_ANA_CON07(0), 6, 1, 1, 0), 318 319 SND_SOC_DAPM_SUPPLY("ADC1_BUF_REF_EN", RK3308_ADC_ANA_CON00(0), 0, 0, NULL, 0), 320 SND_SOC_DAPM_SUPPLY("ADC2_BUF_REF_EN", RK3308_ADC_ANA_CON00(0), 4, 0, NULL, 0), 321 SND_SOC_DAPM_SUPPLY("ADC3_BUF_REF_EN", RK3308_ADC_ANA_CON00(1), 0, 0, NULL, 0), 322 SND_SOC_DAPM_SUPPLY("ADC4_BUF_REF_EN", RK3308_ADC_ANA_CON00(1), 4, 0, NULL, 0), 323 SND_SOC_DAPM_SUPPLY("ADC5_BUF_REF_EN", RK3308_ADC_ANA_CON00(2), 0, 0, NULL, 0), 324 SND_SOC_DAPM_SUPPLY("ADC6_BUF_REF_EN", RK3308_ADC_ANA_CON00(2), 4, 0, NULL, 0), 325 SND_SOC_DAPM_SUPPLY("ADC7_BUF_REF_EN", RK3308_ADC_ANA_CON00(3), 0, 0, NULL, 0), 326 SND_SOC_DAPM_SUPPLY("ADC8_BUF_REF_EN", RK3308_ADC_ANA_CON00(3), 4, 0, NULL, 0), 327 328 SND_SOC_DAPM_SUPPLY("ADC_MCLK_GATE", RK3308_GLB_CON, 5, 1, NULL, 0), 329 330 SND_SOC_DAPM_SUPPLY("ADC1_CLK_EN", RK3308_ADC_ANA_CON05(0), 0, 0, NULL, 0), 331 SND_SOC_DAPM_SUPPLY("ADC2_CLK_EN", RK3308_ADC_ANA_CON05(0), 4, 0, NULL, 0), 332 SND_SOC_DAPM_SUPPLY("ADC3_CLK_EN", RK3308_ADC_ANA_CON05(1), 0, 0, NULL, 0), 333 SND_SOC_DAPM_SUPPLY("ADC4_CLK_EN", RK3308_ADC_ANA_CON05(1), 4, 0, NULL, 0), 334 SND_SOC_DAPM_SUPPLY("ADC5_CLK_EN", RK3308_ADC_ANA_CON05(2), 0, 0, NULL, 0), 335 SND_SOC_DAPM_SUPPLY("ADC6_CLK_EN", RK3308_ADC_ANA_CON05(2), 4, 0, NULL, 0), 336 SND_SOC_DAPM_SUPPLY("ADC7_CLK_EN", RK3308_ADC_ANA_CON05(3), 0, 0, NULL, 0), 337 SND_SOC_DAPM_SUPPLY("ADC8_CLK_EN", RK3308_ADC_ANA_CON05(3), 4, 0, NULL, 0), 338 339 /* The "ALC" name from the TRM is misleading, these are needed even without ALC/AGC */ 340 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC1_EN", RK3308_ADC_ANA_CON02(0), 0, 1, 1, 0), 341 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC2_EN", RK3308_ADC_ANA_CON02(0), 4, 1, 1, 0), 342 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC3_EN", RK3308_ADC_ANA_CON02(1), 0, 1, 1, 0), 343 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC4_EN", RK3308_ADC_ANA_CON02(1), 4, 1, 1, 0), 344 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC5_EN", RK3308_ADC_ANA_CON02(2), 0, 1, 1, 0), 345 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC6_EN", RK3308_ADC_ANA_CON02(2), 4, 1, 1, 0), 346 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC7_EN", RK3308_ADC_ANA_CON02(3), 0, 1, 1, 0), 347 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC8_EN", RK3308_ADC_ANA_CON02(3), 4, 1, 1, 0), 348 349 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC1_EN", RK3308_ADC_ANA_CON05(0), 1, 1, 1, 0), 350 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC2_EN", RK3308_ADC_ANA_CON05(0), 5, 1, 1, 0), 351 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC3_EN", RK3308_ADC_ANA_CON05(1), 1, 1, 1, 0), 352 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC4_EN", RK3308_ADC_ANA_CON05(1), 5, 1, 1, 0), 353 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC5_EN", RK3308_ADC_ANA_CON05(2), 1, 1, 1, 0), 354 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC6_EN", RK3308_ADC_ANA_CON05(2), 5, 1, 1, 0), 355 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC7_EN", RK3308_ADC_ANA_CON05(3), 1, 1, 1, 0), 356 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC8_EN", RK3308_ADC_ANA_CON05(3), 5, 1, 1, 0), 357 358 SND_SOC_DAPM_ADC("ADC1_WORK", "Capture", RK3308_ADC_ANA_CON05(0), 2, 0), 359 SND_SOC_DAPM_ADC("ADC2_WORK", "Capture", RK3308_ADC_ANA_CON05(0), 6, 0), 360 SND_SOC_DAPM_ADC("ADC3_WORK", "Capture", RK3308_ADC_ANA_CON05(1), 2, 0), 361 SND_SOC_DAPM_ADC("ADC4_WORK", "Capture", RK3308_ADC_ANA_CON05(1), 6, 0), 362 SND_SOC_DAPM_ADC("ADC5_WORK", "Capture", RK3308_ADC_ANA_CON05(2), 2, 0), 363 SND_SOC_DAPM_ADC("ADC6_WORK", "Capture", RK3308_ADC_ANA_CON05(2), 6, 0), 364 SND_SOC_DAPM_ADC("ADC7_WORK", "Capture", RK3308_ADC_ANA_CON05(3), 2, 0), 365 SND_SOC_DAPM_ADC("ADC8_WORK", "Capture", RK3308_ADC_ANA_CON05(3), 6, 0), 366 367 /* The "ALC" name from the TRM is misleading, these are needed even without ALC/AGC */ 368 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC1_WORK", RK3308_ADC_ANA_CON02(0), 1, 1, 1, 0), 369 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC2_WORK", RK3308_ADC_ANA_CON02(0), 5, 1, 1, 0), 370 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC3_WORK", RK3308_ADC_ANA_CON02(1), 1, 1, 1, 0), 371 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC4_WORK", RK3308_ADC_ANA_CON02(1), 5, 1, 1, 0), 372 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC5_WORK", RK3308_ADC_ANA_CON02(2), 1, 1, 1, 0), 373 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC6_WORK", RK3308_ADC_ANA_CON02(2), 5, 1, 1, 0), 374 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC7_WORK", RK3308_ADC_ANA_CON02(3), 1, 1, 1, 0), 375 SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC8_WORK", RK3308_ADC_ANA_CON02(3), 5, 1, 1, 0), 376 377 SND_SOC_DAPM_SUPPLY("MICBIAS Current", RK3308_ADC_ANA_CON08(0), 4, 0, NULL, 0), 378 SND_SOC_DAPM_SUPPLY("MICBIAS1", RK3308_ADC_ANA_CON07(1), 3, 0, NULL, 0), 379 SND_SOC_DAPM_SUPPLY("MICBIAS2", RK3308_ADC_ANA_CON07(2), 3, 0, NULL, 0), 380 381 SND_SOC_DAPM_OUT_DRV("DAC_L_HPMIX_EN", RK3308_DAC_ANA_CON13, 0, 0, NULL, 0), 382 SND_SOC_DAPM_OUT_DRV("DAC_R_HPMIX_EN", RK3308_DAC_ANA_CON13, 4, 0, NULL, 0), 383 SND_SOC_DAPM_OUT_DRV("DAC_L_HPMIX_WORK", RK3308_DAC_ANA_CON13, 1, 0, NULL, 0), 384 SND_SOC_DAPM_OUT_DRV("DAC_R_HPMIX_WORK", RK3308_DAC_ANA_CON13, 5, 0, NULL, 0), 385 /* HPMIX is not actually acting as a mixer as the only supported input is I2S */ 386 SND_SOC_DAPM_OUT_DRV("DAC_L_HPMIX_SEL", RK3308_DAC_ANA_CON12, 2, 0, NULL, 0), 387 SND_SOC_DAPM_OUT_DRV("DAC_R_HPMIX_SEL", RK3308_DAC_ANA_CON12, 6, 0, NULL, 0), 388 SND_SOC_DAPM_MIXER("DAC HPMIX Left", RK3308_DAC_ANA_CON13, 2, 0, NULL, 0), 389 SND_SOC_DAPM_MIXER("DAC HPMIX Right", RK3308_DAC_ANA_CON13, 6, 0, NULL, 0), 390 391 SND_SOC_DAPM_SUPPLY("DAC_MCLK_GATE", RK3308_GLB_CON, 4, 1, NULL, 0), 392 393 SND_SOC_DAPM_SUPPLY("DAC_CURRENT_EN", RK3308_DAC_ANA_CON00, 0, 0, NULL, 0), 394 SND_SOC_DAPM_SUPPLY("DAC_L_REF_EN", RK3308_DAC_ANA_CON02, 0, 0, NULL, 0), 395 SND_SOC_DAPM_SUPPLY("DAC_R_REF_EN", RK3308_DAC_ANA_CON02, 4, 0, NULL, 0), 396 SND_SOC_DAPM_SUPPLY("DAC_L_CLK_EN", RK3308_DAC_ANA_CON02, 1, 0, NULL, 0), 397 SND_SOC_DAPM_SUPPLY("DAC_R_CLK_EN", RK3308_DAC_ANA_CON02, 5, 0, NULL, 0), 398 SND_SOC_DAPM_DAC("DAC_L_DAC_WORK", NULL, RK3308_DAC_ANA_CON02, 3, 0), 399 SND_SOC_DAPM_DAC("DAC_R_DAC_WORK", NULL, RK3308_DAC_ANA_CON02, 7, 0), 400 401 SND_SOC_DAPM_SUPPLY("DAC_BUF_REF_L", RK3308_DAC_ANA_CON01, 2, 0, NULL, 0), 402 SND_SOC_DAPM_SUPPLY("DAC_BUF_REF_R", RK3308_DAC_ANA_CON01, 6, 0, NULL, 0), 403 SND_SOC_DAPM_OUT_DRV_E("HPOUT_POP_SOUND_L", SND_SOC_NOPM, 0, 0, NULL, 0, 404 rk3308_codec_pop_sound_set, 405 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 406 SND_SOC_DAPM_OUT_DRV_E("HPOUT_POP_SOUND_R", SND_SOC_NOPM, 4, 0, NULL, 0, 407 rk3308_codec_pop_sound_set, 408 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 409 SND_SOC_DAPM_SUPPLY("DAC_OUTPUT_VCM", SND_SOC_NOPM, 0, 0, 410 rk3308_codec_dac_output_vcm_event, 411 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | 412 SND_SOC_DAPM_POST_PMD), 413 SND_SOC_DAPM_OUT_DRV("L_HPOUT_EN", RK3308_DAC_ANA_CON03, 1, 0, NULL, 0), 414 SND_SOC_DAPM_OUT_DRV("R_HPOUT_EN", RK3308_DAC_ANA_CON03, 5, 0, NULL, 0), 415 SND_SOC_DAPM_OUT_DRV("L_HPOUT_WORK", RK3308_DAC_ANA_CON03, 2, 0, NULL, 0), 416 SND_SOC_DAPM_OUT_DRV("R_HPOUT_WORK", RK3308_DAC_ANA_CON03, 6, 0, NULL, 0), 417 SND_SOC_DAPM_OUTPUT("HPOUT_L"), 418 SND_SOC_DAPM_OUTPUT("HPOUT_R"), 419 420 SND_SOC_DAPM_OUT_DRV_E("L_LINEOUT_EN", RK3308_DAC_ANA_CON04, 0, 0, 421 NULL, 0, rk3308_codec_lineout_event, 422 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 423 SND_SOC_DAPM_OUT_DRV_E("R_LINEOUT_EN", RK3308_DAC_ANA_CON04, 4, 0, 424 NULL, 0, rk3308_codec_lineout_event, 425 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 426 SND_SOC_DAPM_OUTPUT("LINEOUT_L"), 427 SND_SOC_DAPM_OUTPUT("LINEOUT_R"), 428 }; 429 430 static const struct snd_soc_dapm_route rk3308_codec_dapm_routes[] = { 431 { "MICBIAS1", NULL, "MICBIAS Current" }, 432 { "MICBIAS2", NULL, "MICBIAS Current" }, 433 434 { "MIC1_EN", NULL, "MIC1" }, 435 { "MIC2_EN", NULL, "MIC2" }, 436 { "MIC3_EN", NULL, "MIC3" }, 437 { "MIC4_EN", NULL, "MIC4" }, 438 { "MIC5_EN", NULL, "MIC5" }, 439 { "MIC6_EN", NULL, "MIC6" }, 440 { "MIC7_EN", NULL, "MIC7" }, 441 { "MIC8_EN", NULL, "MIC8" }, 442 443 { "MIC1_WORK", NULL, "MIC1_EN" }, 444 { "MIC2_WORK", NULL, "MIC2_EN" }, 445 { "MIC3_WORK", NULL, "MIC3_EN" }, 446 { "MIC4_WORK", NULL, "MIC4_EN" }, 447 { "MIC5_WORK", NULL, "MIC5_EN" }, 448 { "MIC6_WORK", NULL, "MIC6_EN" }, 449 { "MIC7_WORK", NULL, "MIC7_EN" }, 450 { "MIC8_WORK", NULL, "MIC8_EN" }, 451 452 { "CH1_IN_SEL", NULL, "MIC1_WORK" }, 453 { "CH2_IN_SEL", NULL, "MIC2_WORK" }, 454 455 { "ALC1_EN", NULL, "CH1_IN_SEL" }, 456 { "ALC2_EN", NULL, "CH2_IN_SEL" }, 457 { "ALC3_EN", NULL, "MIC3_WORK" }, 458 { "ALC4_EN", NULL, "MIC4_WORK" }, 459 { "ALC5_EN", NULL, "MIC5_WORK" }, 460 { "ALC6_EN", NULL, "MIC6_WORK" }, 461 { "ALC7_EN", NULL, "MIC7_WORK" }, 462 { "ALC8_EN", NULL, "MIC8_WORK" }, 463 464 { "ADC1_EN", NULL, "ALC1_EN" }, 465 { "ADC2_EN", NULL, "ALC2_EN" }, 466 { "ADC3_EN", NULL, "ALC3_EN" }, 467 { "ADC4_EN", NULL, "ALC4_EN" }, 468 { "ADC5_EN", NULL, "ALC5_EN" }, 469 { "ADC6_EN", NULL, "ALC6_EN" }, 470 { "ADC7_EN", NULL, "ALC7_EN" }, 471 { "ADC8_EN", NULL, "ALC8_EN" }, 472 473 { "ADC1_WORK", NULL, "ADC1_EN" }, 474 { "ADC2_WORK", NULL, "ADC2_EN" }, 475 { "ADC3_WORK", NULL, "ADC3_EN" }, 476 { "ADC4_WORK", NULL, "ADC4_EN" }, 477 { "ADC5_WORK", NULL, "ADC5_EN" }, 478 { "ADC6_WORK", NULL, "ADC6_EN" }, 479 { "ADC7_WORK", NULL, "ADC7_EN" }, 480 { "ADC8_WORK", NULL, "ADC8_EN" }, 481 482 { "ADC1_BUF_REF_EN", NULL, "ADC_CURRENT_EN12" }, 483 { "ADC2_BUF_REF_EN", NULL, "ADC_CURRENT_EN12" }, 484 { "ADC3_BUF_REF_EN", NULL, "ADC_CURRENT_EN34" }, 485 { "ADC4_BUF_REF_EN", NULL, "ADC_CURRENT_EN34" }, 486 { "ADC5_BUF_REF_EN", NULL, "ADC_CURRENT_EN56" }, 487 { "ADC6_BUF_REF_EN", NULL, "ADC_CURRENT_EN56" }, 488 { "ADC7_BUF_REF_EN", NULL, "ADC_CURRENT_EN78" }, 489 { "ADC8_BUF_REF_EN", NULL, "ADC_CURRENT_EN78" }, 490 491 { "ADC1_WORK", NULL, "ADC1_BUF_REF_EN" }, 492 { "ADC2_WORK", NULL, "ADC2_BUF_REF_EN" }, 493 { "ADC3_WORK", NULL, "ADC3_BUF_REF_EN" }, 494 { "ADC4_WORK", NULL, "ADC4_BUF_REF_EN" }, 495 { "ADC5_WORK", NULL, "ADC5_BUF_REF_EN" }, 496 { "ADC6_WORK", NULL, "ADC6_BUF_REF_EN" }, 497 { "ADC7_WORK", NULL, "ADC7_BUF_REF_EN" }, 498 { "ADC8_WORK", NULL, "ADC8_BUF_REF_EN" }, 499 500 { "ADC1_CLK_EN", NULL, "ADC_MCLK_GATE" }, 501 { "ADC2_CLK_EN", NULL, "ADC_MCLK_GATE" }, 502 { "ADC3_CLK_EN", NULL, "ADC_MCLK_GATE" }, 503 { "ADC4_CLK_EN", NULL, "ADC_MCLK_GATE" }, 504 { "ADC5_CLK_EN", NULL, "ADC_MCLK_GATE" }, 505 { "ADC6_CLK_EN", NULL, "ADC_MCLK_GATE" }, 506 { "ADC7_CLK_EN", NULL, "ADC_MCLK_GATE" }, 507 { "ADC8_CLK_EN", NULL, "ADC_MCLK_GATE" }, 508 509 { "ADC1_WORK", NULL, "ADC1_CLK_EN" }, 510 { "ADC2_WORK", NULL, "ADC2_CLK_EN" }, 511 { "ADC3_WORK", NULL, "ADC3_CLK_EN" }, 512 { "ADC4_WORK", NULL, "ADC4_CLK_EN" }, 513 { "ADC5_WORK", NULL, "ADC5_CLK_EN" }, 514 { "ADC6_WORK", NULL, "ADC6_CLK_EN" }, 515 { "ADC7_WORK", NULL, "ADC7_CLK_EN" }, 516 { "ADC8_WORK", NULL, "ADC8_CLK_EN" }, 517 518 { "ALC1_WORK", NULL, "ADC1_WORK" }, 519 { "ALC2_WORK", NULL, "ADC2_WORK" }, 520 { "ALC3_WORK", NULL, "ADC3_WORK" }, 521 { "ALC4_WORK", NULL, "ADC4_WORK" }, 522 { "ALC5_WORK", NULL, "ADC5_WORK" }, 523 { "ALC6_WORK", NULL, "ADC6_WORK" }, 524 { "ALC7_WORK", NULL, "ADC7_WORK" }, 525 { "ALC8_WORK", NULL, "ADC8_WORK" }, 526 527 { "HiFi Capture", NULL, "ALC1_WORK" }, 528 { "HiFi Capture", NULL, "ALC2_WORK" }, 529 { "HiFi Capture", NULL, "ALC3_WORK" }, 530 { "HiFi Capture", NULL, "ALC4_WORK" }, 531 { "HiFi Capture", NULL, "ALC5_WORK" }, 532 { "HiFi Capture", NULL, "ALC6_WORK" }, 533 { "HiFi Capture", NULL, "ALC7_WORK" }, 534 { "HiFi Capture", NULL, "ALC8_WORK" }, 535 536 { "DAC_L_HPMIX_EN", NULL, "HiFi Playback" }, 537 { "DAC_R_HPMIX_EN", NULL, "HiFi Playback" }, 538 { "DAC_L_HPMIX_WORK", NULL, "DAC_L_HPMIX_EN" }, 539 { "DAC_R_HPMIX_WORK", NULL, "DAC_R_HPMIX_EN" }, 540 { "DAC HPMIX Left", NULL, "DAC_L_HPMIX_WORK" }, 541 { "DAC HPMIX Right", NULL, "DAC_R_HPMIX_WORK" }, 542 543 { "DAC_L_DAC_WORK", NULL, "DAC HPMIX Left" }, 544 { "DAC_R_DAC_WORK", NULL, "DAC HPMIX Right" }, 545 546 { "DAC_L_REF_EN", NULL, "DAC_CURRENT_EN" }, 547 { "DAC_R_REF_EN", NULL, "DAC_CURRENT_EN" }, 548 { "DAC_L_CLK_EN", NULL, "DAC_L_REF_EN" }, 549 { "DAC_R_CLK_EN", NULL, "DAC_R_REF_EN" }, 550 { "DAC_L_CLK_EN", NULL, "DAC_MCLK_GATE" }, 551 { "DAC_R_CLK_EN", NULL, "DAC_MCLK_GATE" }, 552 { "DAC_L_DAC_WORK", NULL, "DAC_L_CLK_EN" }, 553 { "DAC_R_DAC_WORK", NULL, "DAC_R_CLK_EN" }, 554 { "DAC_L_HPMIX_SEL", NULL, "DAC_L_DAC_WORK" }, 555 { "DAC_R_HPMIX_SEL", NULL, "DAC_R_DAC_WORK" }, 556 557 { "HPOUT_L", NULL, "DAC_BUF_REF_L" }, 558 { "HPOUT_R", NULL, "DAC_BUF_REF_R" }, 559 { "L_HPOUT_EN", NULL, "DAC_L_HPMIX_SEL" }, 560 { "R_HPOUT_EN", NULL, "DAC_R_HPMIX_SEL" }, 561 { "L_HPOUT_EN", NULL, "DAC_OUTPUT_VCM" }, 562 { "R_HPOUT_EN", NULL, "DAC_OUTPUT_VCM" }, 563 { "L_HPOUT_WORK", NULL, "L_HPOUT_EN" }, 564 { "R_HPOUT_WORK", NULL, "R_HPOUT_EN" }, 565 { "HPOUT_POP_SOUND_L", NULL, "L_HPOUT_WORK" }, 566 { "HPOUT_POP_SOUND_R", NULL, "R_HPOUT_WORK" }, 567 { "HPOUT_L", NULL, "HPOUT_POP_SOUND_L" }, 568 { "HPOUT_R", NULL, "HPOUT_POP_SOUND_R" }, 569 570 { "L_LINEOUT_EN", NULL, "DAC_L_HPMIX_SEL" }, 571 { "R_LINEOUT_EN", NULL, "DAC_R_HPMIX_SEL" }, 572 { "L_LINEOUT_EN", NULL, "DAC_OUTPUT_VCM" }, 573 { "R_LINEOUT_EN", NULL, "DAC_OUTPUT_VCM" }, 574 { "LINEOUT_L", NULL, "L_LINEOUT_EN" }, 575 { "LINEOUT_R", NULL, "R_LINEOUT_EN" }, 576 }; 577 578 static int rk3308_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, 579 unsigned int fmt) 580 { 581 struct snd_soc_component *component = codec_dai->component; 582 struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); 583 const unsigned int inv_bits = fmt & SND_SOC_DAIFMT_INV_MASK; 584 const bool inv_bitclk = 585 (inv_bits & SND_SOC_DAIFMT_IB_IF) || 586 (inv_bits & SND_SOC_DAIFMT_IB_NF); 587 const bool inv_frmclk = 588 (inv_bits & SND_SOC_DAIFMT_IB_IF) || 589 (inv_bits & SND_SOC_DAIFMT_NB_IF); 590 const unsigned int dac_master_bits = rk3308->codec_ver < ACODEC_VERSION_C ? 591 RK3308_DAC_IO_MODE_MASTER | RK3308_DAC_MODE_MASTER : 592 RK3308BS_DAC_IO_MODE_MASTER | RK3308BS_DAC_MODE_MASTER; 593 unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; 594 bool is_master = false; 595 int grp; 596 597 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 598 case SND_SOC_DAIFMT_CBC_CFC: 599 break; 600 case SND_SOC_DAIFMT_CBP_CFP: 601 adc_aif2 |= RK3308_ADC_IO_MODE_MASTER; 602 adc_aif2 |= RK3308_ADC_MODE_MASTER; 603 dac_aif2 |= dac_master_bits; 604 is_master = true; 605 break; 606 default: 607 return -EINVAL; 608 } 609 610 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 611 case SND_SOC_DAIFMT_DSP_A: 612 adc_aif1 |= RK3308_ADC_I2S_MODE_PCM; 613 dac_aif1 |= RK3308_DAC_I2S_MODE_PCM; 614 break; 615 case SND_SOC_DAIFMT_I2S: 616 adc_aif1 |= RK3308_ADC_I2S_MODE_I2S; 617 dac_aif1 |= RK3308_DAC_I2S_MODE_I2S; 618 break; 619 case SND_SOC_DAIFMT_RIGHT_J: 620 adc_aif1 |= RK3308_ADC_I2S_MODE_RJ; 621 dac_aif1 |= RK3308_DAC_I2S_MODE_RJ; 622 break; 623 case SND_SOC_DAIFMT_LEFT_J: 624 adc_aif1 |= RK3308_ADC_I2S_MODE_LJ; 625 dac_aif1 |= RK3308_DAC_I2S_MODE_LJ; 626 break; 627 default: 628 return -EINVAL; 629 } 630 631 if (inv_bitclk) { 632 adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL; 633 dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL; 634 } 635 636 if (inv_frmclk) { 637 adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL; 638 dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL; 639 } 640 641 /* 642 * Hold ADC Digital registers start at master mode 643 * 644 * There are 8 ADCs which use the same internal SCLK and LRCK for 645 * master mode. We need to make sure that they are in effect at the 646 * same time, otherwise they will cause abnormal clocks. 647 */ 648 if (is_master) 649 regmap_clear_bits(rk3308->regmap, RK3308_GLB_CON, RK3308_ADC_DIG_WORK); 650 651 for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) { 652 regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(grp), 653 RK3308_ADC_I2S_LRC_POL_REVERSAL | 654 RK3308_ADC_I2S_MODE_MSK, 655 adc_aif1); 656 regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(grp), 657 RK3308_ADC_IO_MODE_MASTER | 658 RK3308_ADC_MODE_MASTER | 659 RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL, 660 adc_aif2); 661 } 662 663 /* Hold ADC Digital registers end at master mode */ 664 if (is_master) 665 regmap_set_bits(rk3308->regmap, RK3308_GLB_CON, RK3308_ADC_DIG_WORK); 666 667 regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, 668 RK3308_DAC_I2S_LRC_POL_REVERSAL | 669 RK3308_DAC_I2S_MODE_MSK, 670 dac_aif1); 671 regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, 672 dac_master_bits | RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL, 673 dac_aif2); 674 675 return 0; 676 } 677 678 static int rk3308_codec_dac_dig_config(struct rk3308_codec_priv *rk3308, 679 struct snd_pcm_hw_params *params) 680 { 681 unsigned int dac_aif1 = 0; 682 683 switch (params_format(params)) { 684 case SNDRV_PCM_FORMAT_S16_LE: 685 dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_16BITS; 686 break; 687 case SNDRV_PCM_FORMAT_S20_3LE: 688 dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_20BITS; 689 break; 690 case SNDRV_PCM_FORMAT_S24_LE: 691 dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_24BITS; 692 break; 693 case SNDRV_PCM_FORMAT_S32_LE: 694 dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_32BITS; 695 break; 696 default: 697 return -EINVAL; 698 } 699 700 regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, 701 RK3308_DAC_I2S_VALID_LEN_MSK, dac_aif1); 702 regmap_set_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, RK3308_DAC_I2S_WORK); 703 704 return 0; 705 } 706 707 static int rk3308_codec_adc_dig_config(struct rk3308_codec_priv *rk3308, 708 struct snd_pcm_hw_params *params) 709 { 710 unsigned int adc_aif1 = 0; 711 /* 712 * grp 0 = ADC1 and ADC2 713 * grp 1 = ADC3 and ADC4 714 * grp 2 = ADC5 and ADC6 715 * grp 3 = ADC7 and ADC8 716 */ 717 u32 used_adc_grps; 718 int grp; 719 720 switch (params_channels(params)) { 721 case 1: 722 adc_aif1 |= RK3308_ADC_I2S_MONO; 723 used_adc_grps = 1; 724 break; 725 case 2: 726 case 4: 727 case 6: 728 case 8: 729 used_adc_grps = params_channels(params) / 2; 730 break; 731 default: 732 dev_err(rk3308->dev, "Invalid channel number %d\n", params_channels(params)); 733 return -EINVAL; 734 } 735 736 switch (params_format(params)) { 737 case SNDRV_PCM_FORMAT_S16_LE: 738 adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_16BITS; 739 break; 740 case SNDRV_PCM_FORMAT_S20_3LE: 741 adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_20BITS; 742 break; 743 case SNDRV_PCM_FORMAT_S24_LE: 744 adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_24BITS; 745 break; 746 case SNDRV_PCM_FORMAT_S32_LE: 747 adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_32BITS; 748 break; 749 default: 750 return -EINVAL; 751 } 752 753 for (grp = 0; grp < used_adc_grps; grp++) { 754 regmap_update_bits(rk3308->regmap, 755 RK3308_ADC_DIG_CON03(grp), 756 RK3308_ADC_L_CH_BIST_MSK | RK3308_ADC_R_CH_BIST_MSK, 757 RK3308_ADC_L_CH_NORMAL_LEFT | RK3308_ADC_R_CH_NORMAL_RIGHT); 758 regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(grp), 759 RK3308_ADC_I2S_VALID_LEN_MSK | RK3308_ADC_I2S_MONO, adc_aif1); 760 regmap_set_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(grp), RK3308_ADC_I2S_WORK); 761 } 762 763 return 0; 764 } 765 766 static int rk3308_codec_hw_params(struct snd_pcm_substream *substream, 767 struct snd_pcm_hw_params *params, 768 struct snd_soc_dai *dai) 769 { 770 struct snd_soc_component *component = dai->component; 771 struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); 772 773 return (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 774 rk3308_codec_dac_dig_config(rk3308, params) : 775 rk3308_codec_adc_dig_config(rk3308, params); 776 } 777 778 static const u64 rk3308_selectable_formats = 779 SND_SOC_POSSIBLE_DAIFMT_I2S | 780 SND_SOC_POSSIBLE_DAIFMT_RIGHT_J | 781 SND_SOC_POSSIBLE_DAIFMT_LEFT_J | 782 SND_SOC_POSSIBLE_DAIFMT_DSP_A | 783 SND_SOC_POSSIBLE_DAIFMT_NB_IF | 784 SND_SOC_POSSIBLE_DAIFMT_IB_NF | 785 SND_SOC_POSSIBLE_DAIFMT_IB_IF; 786 787 static const struct snd_soc_dai_ops rk3308_codec_dai_ops = { 788 .hw_params = rk3308_codec_hw_params, 789 .set_fmt = rk3308_codec_set_dai_fmt, 790 .auto_selectable_formats = &rk3308_selectable_formats, 791 .num_auto_selectable_formats = 1, 792 }; 793 794 static struct snd_soc_dai_driver rk3308_codec_dai_driver = { 795 .name = "rk3308-hifi", 796 .playback = { 797 .stream_name = "HiFi Playback", 798 .channels_min = 2, 799 .channels_max = 2, 800 .rates = SNDRV_PCM_RATE_8000_192000, 801 .formats = (SNDRV_PCM_FMTBIT_S16_LE | 802 SNDRV_PCM_FMTBIT_S20_3LE | 803 SNDRV_PCM_FMTBIT_S24_LE | 804 SNDRV_PCM_FMTBIT_S32_LE), 805 }, 806 .capture = { 807 .stream_name = "HiFi Capture", 808 .channels_min = 1, 809 .channels_max = 8, 810 .rates = SNDRV_PCM_RATE_8000_192000, 811 .formats = (SNDRV_PCM_FMTBIT_S16_LE | 812 SNDRV_PCM_FMTBIT_S20_3LE | 813 SNDRV_PCM_FMTBIT_S24_LE | 814 SNDRV_PCM_FMTBIT_S32_LE), 815 }, 816 .ops = &rk3308_codec_dai_ops, 817 }; 818 819 static void rk3308_codec_reset(struct snd_soc_component *component) 820 { 821 struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); 822 823 reset_control_assert(rk3308->reset); 824 usleep_range(10000, 11000); /* estimated value */ 825 reset_control_deassert(rk3308->reset); 826 827 regmap_write(rk3308->regmap, RK3308_GLB_CON, 0x00); 828 usleep_range(10000, 11000); /* estimated value */ 829 regmap_write(rk3308->regmap, RK3308_GLB_CON, 830 RK3308_SYS_WORK | 831 RK3308_DAC_DIG_WORK | 832 RK3308_ADC_DIG_WORK); 833 } 834 835 /* 836 * Initialize register whose default after HW reset is problematic or which 837 * are never modified. 838 */ 839 static int rk3308_codec_initialize(struct rk3308_codec_priv *rk3308) 840 { 841 int grp; 842 843 /* 844 * Init ADC digital vol to 0 dB (reset value is 0xff, undocumented). 845 * Range: -97dB ~ +32dB. 846 */ 847 if (rk3308->codec_ver == ACODEC_VERSION_C) { 848 for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) { 849 regmap_write(rk3308->regmap, RK3308_ADC_DIG_CON05(grp), 850 RK3308_ADC_DIG_VOL_CON_x_0DB); 851 regmap_write(rk3308->regmap, RK3308_ADC_DIG_CON06(grp), 852 RK3308_ADC_DIG_VOL_CON_x_0DB); 853 } 854 } 855 856 /* set HPMIX default gains (reset value is 0, which is illegal) */ 857 regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, 858 RK3308_DAC_L_HPMIX_GAIN_MSK | 859 RK3308_DAC_R_HPMIX_GAIN_MSK, 860 RK3308_DAC_L_HPMIX_GAIN_NDB_6 | 861 RK3308_DAC_R_HPMIX_GAIN_NDB_6); 862 863 /* recover DAC digital gain to 0 dB (reset value is 0xff, undocumented) */ 864 if (rk3308->codec_ver == ACODEC_VERSION_C) 865 regmap_write(rk3308->regmap, RK3308_DAC_DIG_CON04, 866 RK3308BS_DAC_DIG_GAIN_0DB); 867 868 /* 869 * Unconditionally enable zero-cross detection (needed for AGC, 870 * harmless without AGC) 871 */ 872 for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) 873 regmap_set_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), 874 RK3308_ADC_CH1_ZEROCROSS_DET_EN | 875 RK3308_ADC_CH2_ZEROCROSS_DET_EN); 876 877 return 0; 878 } 879 880 static int rk3308_codec_probe(struct snd_soc_component *component) 881 { 882 struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); 883 884 rk3308->component = component; 885 886 rk3308_codec_reset(component); 887 rk3308_codec_initialize(rk3308); 888 889 return 0; 890 } 891 892 static int rk3308_codec_set_bias_level(struct snd_soc_component *component, 893 enum snd_soc_bias_level level) 894 { 895 struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); 896 struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component); 897 898 switch (level) { 899 case SND_SOC_BIAS_ON: 900 break; 901 case SND_SOC_BIAS_PREPARE: 902 break; 903 case SND_SOC_BIAS_STANDBY: 904 if (snd_soc_dapm_get_bias_level(dapm) != SND_SOC_BIAS_OFF) 905 break; 906 907 /* Sequence from TRM Section 8.6.3 "Power Up" */ 908 regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, 909 RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN); 910 regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), 911 RK3308_ADC_CURRENT_CHARGE_MSK, 1); 912 regmap_set_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), 913 RK3308_ADC_REF_EN); 914 regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), 915 RK3308_ADC_CURRENT_CHARGE_MSK, 0x7f); 916 msleep(20); /* estimated value */ 917 break; 918 case SND_SOC_BIAS_OFF: 919 /* Sequence from TRM Section 8.6.4 "Power Down" */ 920 regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), 921 RK3308_ADC_CURRENT_CHARGE_MSK, 1); 922 regmap_clear_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), 923 RK3308_ADC_REF_EN); 924 regmap_clear_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, 925 RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN); 926 msleep(20); /* estimated value */ 927 break; 928 } 929 return 0; 930 } 931 932 static const struct snd_soc_component_driver rk3308_codec_component_driver = { 933 .probe = rk3308_codec_probe, 934 .set_bias_level = rk3308_codec_set_bias_level, 935 .controls = rk3308_codec_controls, 936 .num_controls = ARRAY_SIZE(rk3308_codec_controls), 937 .dapm_widgets = rk3308_codec_dapm_widgets, 938 .num_dapm_widgets = ARRAY_SIZE(rk3308_codec_dapm_widgets), 939 .dapm_routes = rk3308_codec_dapm_routes, 940 .num_dapm_routes = ARRAY_SIZE(rk3308_codec_dapm_routes), 941 }; 942 943 static const struct regmap_config rk3308_codec_regmap_config = { 944 .reg_bits = 32, 945 .reg_stride = 4, 946 .val_bits = 32, 947 .max_register = RK3308_DAC_ANA_CON15, 948 }; 949 950 static int rk3308_codec_get_version(struct rk3308_codec_priv *rk3308) 951 { 952 unsigned int chip_id; 953 int err; 954 955 err = regmap_read(rk3308->grf, GRF_CHIP_ID, &chip_id); 956 if (err) 957 return err; 958 959 switch (chip_id) { 960 case 3306: 961 rk3308->codec_ver = ACODEC_VERSION_A; 962 break; 963 case 0x3308: 964 rk3308->codec_ver = ACODEC_VERSION_B; 965 break; 966 case 0x3308c: 967 rk3308->codec_ver = ACODEC_VERSION_C; 968 break; 969 default: 970 return dev_err_probe(rk3308->dev, -EINVAL, "Unknown chip_id: 0x%x\n", chip_id); 971 } 972 973 dev_info(rk3308->dev, "Found codec version %c\n", rk3308->codec_ver); 974 return 0; 975 } 976 977 static int rk3308_codec_set_micbias_level(struct rk3308_codec_priv *rk3308) 978 { 979 struct device_node *np = rk3308->dev->of_node; 980 u32 percent; 981 u32 mult; 982 int err; 983 984 err = of_property_read_u32(np, "rockchip,micbias-avdd-percent", &percent); 985 if (err == -EINVAL) 986 return 0; 987 if (err) 988 return dev_err_probe(rk3308->dev, err, 989 "Error reading 'rockchip,micbias-avdd-percent'\n"); 990 991 /* Convert percent to register value, linerarly (50% -> 0, 5% step = +1) */ 992 mult = (percent - 50) / 5; 993 994 /* Check range and that the percent was an exact value allowed */ 995 if (mult > RK3308_ADC_LEVEL_RANGE_MICBIAS_MAX || mult * 5 + 50 != percent) 996 return dev_err_probe(rk3308->dev, -EINVAL, 997 "Invalid value %u for 'rockchip,micbias-avdd-percent'\n", 998 percent); 999 1000 regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0), 1001 RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK, 1002 mult << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT); 1003 1004 return 0; 1005 } 1006 1007 static int rk3308_codec_platform_probe(struct platform_device *pdev) 1008 { 1009 struct device_node *np = pdev->dev.of_node; 1010 struct device *dev = &pdev->dev; 1011 struct rk3308_codec_priv *rk3308; 1012 void __iomem *base; 1013 int err; 1014 1015 rk3308 = devm_kzalloc(&pdev->dev, sizeof(*rk3308), GFP_KERNEL); 1016 if (!rk3308) 1017 return -ENOMEM; 1018 1019 rk3308->dev = dev; 1020 1021 rk3308->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); 1022 if (IS_ERR(rk3308->grf)) 1023 return dev_err_probe(dev, PTR_ERR(rk3308->grf), "Error getting GRF\n"); 1024 1025 rk3308->reset = devm_reset_control_get_optional_exclusive(dev, "codec"); 1026 if (IS_ERR(rk3308->reset)) 1027 return dev_err_probe(dev, PTR_ERR(rk3308->reset), "Failed to get reset control\n"); 1028 1029 err = devm_clk_bulk_get(dev, ARRAY_SIZE(rk3308_codec_clocks), rk3308_codec_clocks); 1030 if (err) 1031 return dev_err_probe(dev, err, "Failed to get clocks\n"); 1032 1033 err = clk_bulk_prepare_enable(ARRAY_SIZE(rk3308_codec_clocks), rk3308_codec_clocks); 1034 if (err) 1035 return dev_err_probe(dev, err, "Failed to enable clocks\n"); 1036 1037 err = rk3308_codec_get_version(rk3308); 1038 if (err) 1039 return err; 1040 1041 base = devm_platform_ioremap_resource(pdev, 0); 1042 if (IS_ERR(base)) 1043 return PTR_ERR(base); 1044 1045 rk3308->regmap = devm_regmap_init_mmio(dev, base, &rk3308_codec_regmap_config); 1046 if (IS_ERR(rk3308->regmap)) 1047 return dev_err_probe(dev, PTR_ERR(rk3308->regmap), 1048 "Failed to init regmap\n"); 1049 1050 platform_set_drvdata(pdev, rk3308); 1051 1052 err = rk3308_codec_set_micbias_level(rk3308); 1053 if (err) 1054 return err; 1055 1056 err = devm_snd_soc_register_component(dev, &rk3308_codec_component_driver, 1057 &rk3308_codec_dai_driver, 1); 1058 if (err) 1059 return dev_err_probe(dev, err, "Failed to register codec\n"); 1060 1061 return 0; 1062 } 1063 1064 static const struct of_device_id __maybe_unused rk3308_codec_of_match[] = { 1065 { .compatible = "rockchip,rk3308-codec", }, 1066 {}, 1067 }; 1068 MODULE_DEVICE_TABLE(of, rk3308_codec_of_match); 1069 1070 static struct platform_driver rk3308_codec_driver = { 1071 .driver = { 1072 .name = "rk3308-acodec", 1073 .of_match_table = rk3308_codec_of_match, 1074 }, 1075 .probe = rk3308_codec_platform_probe, 1076 }; 1077 module_platform_driver(rk3308_codec_driver); 1078 1079 MODULE_AUTHOR("Xing Zheng <zhengxing@rock-chips.com>"); 1080 MODULE_AUTHOR("Luca Ceresoli <luca.ceresoli@bootlin.com>"); 1081 MODULE_DESCRIPTION("ASoC RK3308 Codec Driver"); 1082 MODULE_LICENSE("GPL"); 1083