1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * This driver supports the digital controls for the internal codec 4 * found in Allwinner's A33 SoCs. 5 * 6 * (C) Copyright 2010-2016 7 * Reuuimlla Technology Co., Ltd. <www.reuuimllatech.com> 8 * huangxin <huangxin@Reuuimllatech.com> 9 * Mylène Josserand <mylene.josserand@free-electrons.com> 10 */ 11 12 #include <linux/module.h> 13 #include <linux/delay.h> 14 #include <linux/clk.h> 15 #include <linux/io.h> 16 #include <linux/of_device.h> 17 #include <linux/pm_runtime.h> 18 #include <linux/regmap.h> 19 #include <linux/log2.h> 20 21 #include <sound/pcm_params.h> 22 #include <sound/soc.h> 23 #include <sound/soc-dapm.h> 24 25 #define SUN8I_SYSCLK_CTL 0x00c 26 #define SUN8I_SYSCLK_CTL_AIF1CLK_ENA 11 27 #define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL (0x2 << 8) 28 #define SUN8I_SYSCLK_CTL_AIF2CLK_ENA 7 29 #define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL (0x2 << 4) 30 #define SUN8I_SYSCLK_CTL_SYSCLK_ENA 3 31 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC 0 32 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK (0x0 << 0) 33 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF2CLK (0x1 << 0) 34 #define SUN8I_MOD_CLK_ENA 0x010 35 #define SUN8I_MOD_CLK_ENA_AIF1 15 36 #define SUN8I_MOD_CLK_ENA_ADC 3 37 #define SUN8I_MOD_CLK_ENA_DAC 2 38 #define SUN8I_MOD_RST_CTL 0x014 39 #define SUN8I_MOD_RST_CTL_AIF1 15 40 #define SUN8I_MOD_RST_CTL_ADC 3 41 #define SUN8I_MOD_RST_CTL_DAC 2 42 #define SUN8I_SYS_SR_CTRL 0x018 43 #define SUN8I_SYS_SR_CTRL_AIF1_FS 12 44 #define SUN8I_SYS_SR_CTRL_AIF2_FS 8 45 #define SUN8I_AIF1CLK_CTRL 0x040 46 #define SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD 15 47 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV 14 48 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV 13 49 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV 9 50 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV 6 51 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ 4 52 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16 (1 << 4) 53 #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT 2 54 #define SUN8I_AIF1_ADCDAT_CTRL 0x044 55 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA 15 56 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA 14 57 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC 10 58 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC 8 59 #define SUN8I_AIF1_DACDAT_CTRL 0x048 60 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA 15 61 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA 14 62 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC 10 63 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC 8 64 #define SUN8I_AIF1_MXR_SRC 0x04c 65 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L 15 66 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL 14 67 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL 13 68 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR 12 69 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R 11 70 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR 10 71 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR 9 72 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL 8 73 #define SUN8I_ADC_DIG_CTRL 0x100 74 #define SUN8I_ADC_DIG_CTRL_ENAD 15 75 #define SUN8I_ADC_DIG_CTRL_ADOUT_DTS 2 76 #define SUN8I_ADC_DIG_CTRL_ADOUT_DLY 1 77 #define SUN8I_DAC_DIG_CTRL 0x120 78 #define SUN8I_DAC_DIG_CTRL_ENDA 15 79 #define SUN8I_DAC_MXR_SRC 0x130 80 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L 15 81 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L 14 82 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL 13 83 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL 12 84 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R 11 85 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R 10 86 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR 9 87 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR 8 88 89 #define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK GENMASK(9, 8) 90 #define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK GENMASK(5, 4) 91 #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12) 92 #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8) 93 #define SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK GENMASK(12, 9) 94 #define SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK GENMASK(8, 6) 95 #define SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK GENMASK(5, 4) 96 #define SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK GENMASK(3, 2) 97 98 struct sun8i_codec_quirks { 99 bool legacy_widgets : 1; 100 bool lrck_inversion : 1; 101 }; 102 103 struct sun8i_codec { 104 struct regmap *regmap; 105 struct clk *clk_module; 106 const struct sun8i_codec_quirks *quirks; 107 }; 108 109 static int sun8i_codec_runtime_resume(struct device *dev) 110 { 111 struct sun8i_codec *scodec = dev_get_drvdata(dev); 112 int ret; 113 114 regcache_cache_only(scodec->regmap, false); 115 116 ret = regcache_sync(scodec->regmap); 117 if (ret) { 118 dev_err(dev, "Failed to sync regmap cache\n"); 119 return ret; 120 } 121 122 return 0; 123 } 124 125 static int sun8i_codec_runtime_suspend(struct device *dev) 126 { 127 struct sun8i_codec *scodec = dev_get_drvdata(dev); 128 129 regcache_cache_only(scodec->regmap, true); 130 regcache_mark_dirty(scodec->regmap); 131 132 return 0; 133 } 134 135 static int sun8i_codec_get_hw_rate(struct snd_pcm_hw_params *params) 136 { 137 unsigned int rate = params_rate(params); 138 139 switch (rate) { 140 case 8000: 141 case 7350: 142 return 0x0; 143 case 11025: 144 return 0x1; 145 case 12000: 146 return 0x2; 147 case 16000: 148 return 0x3; 149 case 22050: 150 return 0x4; 151 case 24000: 152 return 0x5; 153 case 32000: 154 return 0x6; 155 case 44100: 156 return 0x7; 157 case 48000: 158 return 0x8; 159 case 96000: 160 return 0x9; 161 case 192000: 162 return 0xa; 163 default: 164 return -EINVAL; 165 } 166 } 167 168 static int sun8i_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 169 { 170 struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); 171 u32 value; 172 173 /* clock masters */ 174 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 175 case SND_SOC_DAIFMT_CBS_CFS: /* Codec slave, DAI master */ 176 value = 0x1; 177 break; 178 case SND_SOC_DAIFMT_CBM_CFM: /* Codec Master, DAI slave */ 179 value = 0x0; 180 break; 181 default: 182 return -EINVAL; 183 } 184 regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, 185 BIT(SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD), 186 value << SUN8I_AIF1CLK_CTRL_AIF1_MSTR_MOD); 187 188 /* clock inversion */ 189 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 190 case SND_SOC_DAIFMT_NB_NF: /* Normal */ 191 value = 0x0; 192 break; 193 case SND_SOC_DAIFMT_IB_IF: /* Inversion */ 194 value = 0x1; 195 break; 196 default: 197 return -EINVAL; 198 } 199 regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, 200 BIT(SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV), 201 value << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_INV); 202 203 /* 204 * It appears that the DAI and the codec in the A33 SoC don't 205 * share the same polarity for the LRCK signal when they mean 206 * 'normal' and 'inverted' in the datasheet. 207 * 208 * Since the DAI here is our regular i2s driver that have been 209 * tested with way more codecs than just this one, it means 210 * that the codec probably gets it backward, and we have to 211 * invert the value here. 212 */ 213 value ^= scodec->quirks->lrck_inversion; 214 regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, 215 BIT(SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV), 216 value << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_INV); 217 218 /* DAI format */ 219 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 220 case SND_SOC_DAIFMT_I2S: 221 value = 0x0; 222 break; 223 case SND_SOC_DAIFMT_LEFT_J: 224 value = 0x1; 225 break; 226 case SND_SOC_DAIFMT_RIGHT_J: 227 value = 0x2; 228 break; 229 case SND_SOC_DAIFMT_DSP_A: 230 case SND_SOC_DAIFMT_DSP_B: 231 value = 0x3; 232 break; 233 default: 234 return -EINVAL; 235 } 236 regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, 237 SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT_MASK, 238 value << SUN8I_AIF1CLK_CTRL_AIF1_DATA_FMT); 239 240 return 0; 241 } 242 243 struct sun8i_codec_clk_div { 244 u8 div; 245 u8 val; 246 }; 247 248 static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = { 249 { .div = 1, .val = 0 }, 250 { .div = 2, .val = 1 }, 251 { .div = 4, .val = 2 }, 252 { .div = 6, .val = 3 }, 253 { .div = 8, .val = 4 }, 254 { .div = 12, .val = 5 }, 255 { .div = 16, .val = 6 }, 256 { .div = 24, .val = 7 }, 257 { .div = 32, .val = 8 }, 258 { .div = 48, .val = 9 }, 259 { .div = 64, .val = 10 }, 260 { .div = 96, .val = 11 }, 261 { .div = 128, .val = 12 }, 262 { .div = 192, .val = 13 }, 263 }; 264 265 static u8 sun8i_codec_get_bclk_div(struct sun8i_codec *scodec, 266 unsigned int rate, 267 unsigned int word_size) 268 { 269 unsigned long clk_rate = clk_get_rate(scodec->clk_module); 270 unsigned int div = clk_rate / rate / word_size / 2; 271 unsigned int best_val = 0, best_diff = ~0; 272 int i; 273 274 for (i = 0; i < ARRAY_SIZE(sun8i_codec_bclk_div); i++) { 275 const struct sun8i_codec_clk_div *bdiv = &sun8i_codec_bclk_div[i]; 276 unsigned int diff = abs(bdiv->div - div); 277 278 if (diff < best_diff) { 279 best_diff = diff; 280 best_val = bdiv->val; 281 } 282 } 283 284 return best_val; 285 } 286 287 static int sun8i_codec_get_lrck_div(unsigned int channels, 288 unsigned int word_size) 289 { 290 unsigned int div = word_size * channels; 291 292 if (div < 16 || div > 256) 293 return -EINVAL; 294 295 return ilog2(div) - 4; 296 } 297 298 static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, 299 struct snd_pcm_hw_params *params, 300 struct snd_soc_dai *dai) 301 { 302 struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); 303 int sample_rate, lrck_div; 304 u8 bclk_div; 305 306 /* 307 * The CPU DAI handles only a sample of 16 bits. Configure the 308 * codec to handle this type of sample resolution. 309 */ 310 regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, 311 SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_MASK, 312 SUN8I_AIF1CLK_CTRL_AIF1_WORD_SIZ_16); 313 314 bclk_div = sun8i_codec_get_bclk_div(scodec, params_rate(params), 16); 315 regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, 316 SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV_MASK, 317 bclk_div << SUN8I_AIF1CLK_CTRL_AIF1_BCLK_DIV); 318 319 lrck_div = sun8i_codec_get_lrck_div(params_channels(params), 320 params_physical_width(params)); 321 if (lrck_div < 0) 322 return lrck_div; 323 324 regmap_update_bits(scodec->regmap, SUN8I_AIF1CLK_CTRL, 325 SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV_MASK, 326 lrck_div << SUN8I_AIF1CLK_CTRL_AIF1_LRCK_DIV); 327 328 sample_rate = sun8i_codec_get_hw_rate(params); 329 if (sample_rate < 0) 330 return sample_rate; 331 332 regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL, 333 SUN8I_SYS_SR_CTRL_AIF1_FS_MASK, 334 sample_rate << SUN8I_SYS_SR_CTRL_AIF1_FS); 335 336 return 0; 337 } 338 339 static const char *const sun8i_aif_stereo_mux_enum_values[] = { 340 "Stereo", "Reverse Stereo", "Sum Mono", "Mix Mono" 341 }; 342 343 static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_ad0_stereo_mux_enum, 344 SUN8I_AIF1_ADCDAT_CTRL, 345 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC, 346 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC, 347 sun8i_aif_stereo_mux_enum_values); 348 349 static const struct snd_kcontrol_new sun8i_aif1_ad0_stereo_mux_control = 350 SOC_DAPM_ENUM("AIF1 AD0 Stereo Capture Route", 351 sun8i_aif1_ad0_stereo_mux_enum); 352 353 static const struct snd_kcontrol_new sun8i_aif1_ad0_mixer_controls[] = { 354 SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital ADC Capture Switch", 355 SUN8I_AIF1_MXR_SRC, 356 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L, 357 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R, 1, 0), 358 SOC_DAPM_DOUBLE("AIF2 Digital ADC Capture Switch", 359 SUN8I_AIF1_MXR_SRC, 360 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL, 361 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR, 1, 0), 362 SOC_DAPM_DOUBLE("AIF1 Data Digital ADC Capture Switch", 363 SUN8I_AIF1_MXR_SRC, 364 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL, 365 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR, 1, 0), 366 SOC_DAPM_DOUBLE("AIF2 Inv Digital ADC Capture Switch", 367 SUN8I_AIF1_MXR_SRC, 368 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR, 369 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL, 1, 0), 370 }; 371 372 static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_da0_stereo_mux_enum, 373 SUN8I_AIF1_DACDAT_CTRL, 374 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC, 375 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC, 376 sun8i_aif_stereo_mux_enum_values); 377 378 static const struct snd_kcontrol_new sun8i_aif1_da0_stereo_mux_control = 379 SOC_DAPM_ENUM("AIF1 DA0 Stereo Playback Route", 380 sun8i_aif1_da0_stereo_mux_enum); 381 382 static const struct snd_kcontrol_new sun8i_dac_mixer_controls[] = { 383 SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital DAC Playback Switch", 384 SUN8I_DAC_MXR_SRC, 385 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L, 386 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R, 1, 0), 387 SOC_DAPM_DOUBLE("AIF1 Slot 1 Digital DAC Playback Switch", 388 SUN8I_DAC_MXR_SRC, 389 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L, 390 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R, 1, 0), 391 SOC_DAPM_DOUBLE("AIF2 Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC, 392 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL, 393 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR, 1, 0), 394 SOC_DAPM_DOUBLE("ADC Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC, 395 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL, 396 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR, 1, 0), 397 }; 398 399 static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets[] = { 400 /* System Clocks */ 401 SND_SOC_DAPM_CLOCK_SUPPLY("mod"), 402 403 SND_SOC_DAPM_SUPPLY("AIF1CLK", 404 SUN8I_SYSCLK_CTL, 405 SUN8I_SYSCLK_CTL_AIF1CLK_ENA, 0, NULL, 0), 406 SND_SOC_DAPM_SUPPLY("SYSCLK", 407 SUN8I_SYSCLK_CTL, 408 SUN8I_SYSCLK_CTL_SYSCLK_ENA, 0, NULL, 0), 409 410 /* Module Clocks */ 411 SND_SOC_DAPM_SUPPLY("CLK AIF1", 412 SUN8I_MOD_CLK_ENA, 413 SUN8I_MOD_CLK_ENA_AIF1, 0, NULL, 0), 414 SND_SOC_DAPM_SUPPLY("CLK ADC", 415 SUN8I_MOD_CLK_ENA, 416 SUN8I_MOD_CLK_ENA_ADC, 0, NULL, 0), 417 SND_SOC_DAPM_SUPPLY("CLK DAC", 418 SUN8I_MOD_CLK_ENA, 419 SUN8I_MOD_CLK_ENA_DAC, 0, NULL, 0), 420 421 /* Module Resets */ 422 SND_SOC_DAPM_SUPPLY("RST AIF1", 423 SUN8I_MOD_RST_CTL, 424 SUN8I_MOD_RST_CTL_AIF1, 0, NULL, 0), 425 SND_SOC_DAPM_SUPPLY("RST ADC", 426 SUN8I_MOD_RST_CTL, 427 SUN8I_MOD_RST_CTL_ADC, 0, NULL, 0), 428 SND_SOC_DAPM_SUPPLY("RST DAC", 429 SUN8I_MOD_RST_CTL, 430 SUN8I_MOD_RST_CTL_DAC, 0, NULL, 0), 431 432 /* Module Supplies */ 433 SND_SOC_DAPM_SUPPLY("ADC", 434 SUN8I_ADC_DIG_CTRL, 435 SUN8I_ADC_DIG_CTRL_ENAD, 0, NULL, 0), 436 SND_SOC_DAPM_SUPPLY("DAC", 437 SUN8I_DAC_DIG_CTRL, 438 SUN8I_DAC_DIG_CTRL_ENDA, 0, NULL, 0), 439 440 /* AIF "ADC" Outputs */ 441 SND_SOC_DAPM_AIF_OUT("AIF1 AD0L", "Capture", 0, 442 SUN8I_AIF1_ADCDAT_CTRL, 443 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA, 0), 444 SND_SOC_DAPM_AIF_OUT("AIF1 AD0R", "Capture", 1, 445 SUN8I_AIF1_ADCDAT_CTRL, 446 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA, 0), 447 448 /* AIF "ADC" Mono/Stereo Muxes */ 449 SND_SOC_DAPM_MUX("AIF1 AD0L Stereo Mux", SND_SOC_NOPM, 0, 0, 450 &sun8i_aif1_ad0_stereo_mux_control), 451 SND_SOC_DAPM_MUX("AIF1 AD0R Stereo Mux", SND_SOC_NOPM, 0, 0, 452 &sun8i_aif1_ad0_stereo_mux_control), 453 454 /* AIF "ADC" Mixers */ 455 SOC_MIXER_ARRAY("AIF1 AD0L Mixer", SND_SOC_NOPM, 0, 0, 456 sun8i_aif1_ad0_mixer_controls), 457 SOC_MIXER_ARRAY("AIF1 AD0R Mixer", SND_SOC_NOPM, 0, 0, 458 sun8i_aif1_ad0_mixer_controls), 459 460 /* AIF "DAC" Mono/Stereo Muxes */ 461 SND_SOC_DAPM_MUX("AIF1 DA0L Stereo Mux", SND_SOC_NOPM, 0, 0, 462 &sun8i_aif1_da0_stereo_mux_control), 463 SND_SOC_DAPM_MUX("AIF1 DA0R Stereo Mux", SND_SOC_NOPM, 0, 0, 464 &sun8i_aif1_da0_stereo_mux_control), 465 466 /* AIF "DAC" Inputs */ 467 SND_SOC_DAPM_AIF_IN("AIF1 DA0L", "Playback", 0, 468 SUN8I_AIF1_DACDAT_CTRL, 469 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA, 0), 470 SND_SOC_DAPM_AIF_IN("AIF1 DA0R", "Playback", 1, 471 SUN8I_AIF1_DACDAT_CTRL, 472 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA, 0), 473 474 /* ADC Inputs (connected to analog codec DAPM context) */ 475 SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 0, 0), 476 SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), 477 478 /* DAC Outputs (connected to analog codec DAPM context) */ 479 SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0), 480 SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0), 481 482 /* DAC Mixers */ 483 SOC_MIXER_ARRAY("DACL Mixer", SND_SOC_NOPM, 0, 0, 484 sun8i_dac_mixer_controls), 485 SOC_MIXER_ARRAY("DACR Mixer", SND_SOC_NOPM, 0, 0, 486 sun8i_dac_mixer_controls), 487 }; 488 489 static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = { 490 /* Clock Routes */ 491 { "AIF1CLK", NULL, "mod" }, 492 493 { "SYSCLK", NULL, "AIF1CLK" }, 494 495 { "CLK AIF1", NULL, "AIF1CLK" }, 496 { "CLK AIF1", NULL, "SYSCLK" }, 497 { "RST AIF1", NULL, "CLK AIF1" }, 498 { "AIF1 AD0L", NULL, "RST AIF1" }, 499 { "AIF1 AD0R", NULL, "RST AIF1" }, 500 { "AIF1 DA0L", NULL, "RST AIF1" }, 501 { "AIF1 DA0R", NULL, "RST AIF1" }, 502 503 { "CLK ADC", NULL, "SYSCLK" }, 504 { "RST ADC", NULL, "CLK ADC" }, 505 { "ADC", NULL, "RST ADC" }, 506 { "ADCL", NULL, "ADC" }, 507 { "ADCR", NULL, "ADC" }, 508 509 { "CLK DAC", NULL, "SYSCLK" }, 510 { "RST DAC", NULL, "CLK DAC" }, 511 { "DAC", NULL, "RST DAC" }, 512 { "DACL", NULL, "DAC" }, 513 { "DACR", NULL, "DAC" }, 514 515 /* AIF "ADC" Output Routes */ 516 { "AIF1 AD0L", NULL, "AIF1 AD0L Stereo Mux" }, 517 { "AIF1 AD0R", NULL, "AIF1 AD0R Stereo Mux" }, 518 519 /* AIF "ADC" Mono/Stereo Mux Routes */ 520 { "AIF1 AD0L Stereo Mux", "Stereo", "AIF1 AD0L Mixer" }, 521 { "AIF1 AD0L Stereo Mux", "Reverse Stereo", "AIF1 AD0R Mixer" }, 522 { "AIF1 AD0L Stereo Mux", "Sum Mono", "AIF1 AD0L Mixer" }, 523 { "AIF1 AD0L Stereo Mux", "Sum Mono", "AIF1 AD0R Mixer" }, 524 { "AIF1 AD0L Stereo Mux", "Mix Mono", "AIF1 AD0L Mixer" }, 525 { "AIF1 AD0L Stereo Mux", "Mix Mono", "AIF1 AD0R Mixer" }, 526 527 { "AIF1 AD0R Stereo Mux", "Stereo", "AIF1 AD0R Mixer" }, 528 { "AIF1 AD0R Stereo Mux", "Reverse Stereo", "AIF1 AD0L Mixer" }, 529 { "AIF1 AD0R Stereo Mux", "Sum Mono", "AIF1 AD0L Mixer" }, 530 { "AIF1 AD0R Stereo Mux", "Sum Mono", "AIF1 AD0R Mixer" }, 531 { "AIF1 AD0R Stereo Mux", "Mix Mono", "AIF1 AD0L Mixer" }, 532 { "AIF1 AD0R Stereo Mux", "Mix Mono", "AIF1 AD0R Mixer" }, 533 534 /* AIF "ADC" Mixer Routes */ 535 { "AIF1 AD0L Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0L Stereo Mux" }, 536 { "AIF1 AD0L Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCL" }, 537 538 { "AIF1 AD0R Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0R Stereo Mux" }, 539 { "AIF1 AD0R Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCR" }, 540 541 /* AIF "DAC" Mono/Stereo Mux Routes */ 542 { "AIF1 DA0L Stereo Mux", "Stereo", "AIF1 DA0L" }, 543 { "AIF1 DA0L Stereo Mux", "Reverse Stereo", "AIF1 DA0R" }, 544 { "AIF1 DA0L Stereo Mux", "Sum Mono", "AIF1 DA0L" }, 545 { "AIF1 DA0L Stereo Mux", "Sum Mono", "AIF1 DA0R" }, 546 { "AIF1 DA0L Stereo Mux", "Mix Mono", "AIF1 DA0L" }, 547 { "AIF1 DA0L Stereo Mux", "Mix Mono", "AIF1 DA0R" }, 548 549 { "AIF1 DA0R Stereo Mux", "Stereo", "AIF1 DA0R" }, 550 { "AIF1 DA0R Stereo Mux", "Reverse Stereo", "AIF1 DA0L" }, 551 { "AIF1 DA0R Stereo Mux", "Sum Mono", "AIF1 DA0L" }, 552 { "AIF1 DA0R Stereo Mux", "Sum Mono", "AIF1 DA0R" }, 553 { "AIF1 DA0R Stereo Mux", "Mix Mono", "AIF1 DA0L" }, 554 { "AIF1 DA0R Stereo Mux", "Mix Mono", "AIF1 DA0R" }, 555 556 /* DAC Output Routes */ 557 { "DACL", NULL, "DACL Mixer" }, 558 { "DACR", NULL, "DACR Mixer" }, 559 560 /* DAC Mixer Routes */ 561 { "DACL Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0L Stereo Mux" }, 562 { "DACL Mixer", "ADC Digital DAC Playback Switch", "ADCL" }, 563 564 { "DACR Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0R Stereo Mux" }, 565 { "DACR Mixer", "ADC Digital DAC Playback Switch", "ADCR" }, 566 }; 567 568 static const struct snd_soc_dapm_widget sun8i_codec_legacy_widgets[] = { 569 /* Legacy ADC Inputs (connected to analog codec DAPM context) */ 570 SND_SOC_DAPM_ADC("AIF1 Slot 0 Left ADC", NULL, SND_SOC_NOPM, 0, 0), 571 SND_SOC_DAPM_ADC("AIF1 Slot 0 Right ADC", NULL, SND_SOC_NOPM, 0, 0), 572 573 /* Legacy DAC Outputs (connected to analog codec DAPM context) */ 574 SND_SOC_DAPM_DAC("AIF1 Slot 0 Left", NULL, SND_SOC_NOPM, 0, 0), 575 SND_SOC_DAPM_DAC("AIF1 Slot 0 Right", NULL, SND_SOC_NOPM, 0, 0), 576 }; 577 578 static const struct snd_soc_dapm_route sun8i_codec_legacy_routes[] = { 579 /* Legacy ADC Routes */ 580 { "ADCL", NULL, "AIF1 Slot 0 Left ADC" }, 581 { "ADCR", NULL, "AIF1 Slot 0 Right ADC" }, 582 583 /* Legacy DAC Routes */ 584 { "AIF1 Slot 0 Left", NULL, "DACL" }, 585 { "AIF1 Slot 0 Right", NULL, "DACR" }, 586 }; 587 588 static int sun8i_codec_component_probe(struct snd_soc_component *component) 589 { 590 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 591 struct sun8i_codec *scodec = snd_soc_component_get_drvdata(component); 592 int ret; 593 594 /* Add widgets for backward compatibility with old device trees. */ 595 if (scodec->quirks->legacy_widgets) { 596 ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_legacy_widgets, 597 ARRAY_SIZE(sun8i_codec_legacy_widgets)); 598 if (ret) 599 return ret; 600 601 ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_legacy_routes, 602 ARRAY_SIZE(sun8i_codec_legacy_routes)); 603 if (ret) 604 return ret; 605 } 606 607 /* 608 * AIF1CLK and AIF2CLK share a pair of clock parents: PLL_AUDIO ("mod") 609 * and MCLK (from the CPU DAI connected to AIF1). MCLK's parent is also 610 * PLL_AUDIO, so using it adds no additional flexibility. Use PLL_AUDIO 611 * directly to simplify the clock tree. 612 */ 613 regmap_update_bits(scodec->regmap, SUN8I_SYSCLK_CTL, 614 SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK | 615 SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK, 616 SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL | 617 SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL); 618 619 /* Use AIF1CLK as the SYSCLK parent since AIF1 is used most often. */ 620 regmap_update_bits(scodec->regmap, SUN8I_SYSCLK_CTL, 621 BIT(SUN8I_SYSCLK_CTL_SYSCLK_SRC), 622 SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK); 623 624 return 0; 625 } 626 627 static const struct snd_soc_dai_ops sun8i_codec_dai_ops = { 628 .hw_params = sun8i_codec_hw_params, 629 .set_fmt = sun8i_set_fmt, 630 }; 631 632 static struct snd_soc_dai_driver sun8i_codec_dai = { 633 .name = "sun8i", 634 /* playback capabilities */ 635 .playback = { 636 .stream_name = "Playback", 637 .channels_min = 1, 638 .channels_max = 2, 639 .rates = SNDRV_PCM_RATE_8000_192000, 640 .formats = SNDRV_PCM_FMTBIT_S16_LE, 641 }, 642 /* capture capabilities */ 643 .capture = { 644 .stream_name = "Capture", 645 .channels_min = 1, 646 .channels_max = 2, 647 .rates = SNDRV_PCM_RATE_8000_192000, 648 .formats = SNDRV_PCM_FMTBIT_S16_LE, 649 .sig_bits = 24, 650 }, 651 /* pcm operations */ 652 .ops = &sun8i_codec_dai_ops, 653 }; 654 655 static const struct snd_soc_component_driver sun8i_soc_component = { 656 .dapm_widgets = sun8i_codec_dapm_widgets, 657 .num_dapm_widgets = ARRAY_SIZE(sun8i_codec_dapm_widgets), 658 .dapm_routes = sun8i_codec_dapm_routes, 659 .num_dapm_routes = ARRAY_SIZE(sun8i_codec_dapm_routes), 660 .probe = sun8i_codec_component_probe, 661 .idle_bias_on = 1, 662 .use_pmdown_time = 1, 663 .endianness = 1, 664 .non_legacy_dai_naming = 1, 665 }; 666 667 static const struct regmap_config sun8i_codec_regmap_config = { 668 .reg_bits = 32, 669 .reg_stride = 4, 670 .val_bits = 32, 671 .max_register = SUN8I_DAC_MXR_SRC, 672 673 .cache_type = REGCACHE_FLAT, 674 }; 675 676 static int sun8i_codec_probe(struct platform_device *pdev) 677 { 678 struct sun8i_codec *scodec; 679 void __iomem *base; 680 int ret; 681 682 scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL); 683 if (!scodec) 684 return -ENOMEM; 685 686 scodec->clk_module = devm_clk_get(&pdev->dev, "mod"); 687 if (IS_ERR(scodec->clk_module)) { 688 dev_err(&pdev->dev, "Failed to get the module clock\n"); 689 return PTR_ERR(scodec->clk_module); 690 } 691 692 base = devm_platform_ioremap_resource(pdev, 0); 693 if (IS_ERR(base)) { 694 dev_err(&pdev->dev, "Failed to map the registers\n"); 695 return PTR_ERR(base); 696 } 697 698 scodec->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "bus", base, 699 &sun8i_codec_regmap_config); 700 if (IS_ERR(scodec->regmap)) { 701 dev_err(&pdev->dev, "Failed to create our regmap\n"); 702 return PTR_ERR(scodec->regmap); 703 } 704 705 scodec->quirks = of_device_get_match_data(&pdev->dev); 706 707 platform_set_drvdata(pdev, scodec); 708 709 pm_runtime_enable(&pdev->dev); 710 if (!pm_runtime_enabled(&pdev->dev)) { 711 ret = sun8i_codec_runtime_resume(&pdev->dev); 712 if (ret) 713 goto err_pm_disable; 714 } 715 716 ret = devm_snd_soc_register_component(&pdev->dev, &sun8i_soc_component, 717 &sun8i_codec_dai, 1); 718 if (ret) { 719 dev_err(&pdev->dev, "Failed to register codec\n"); 720 goto err_suspend; 721 } 722 723 return ret; 724 725 err_suspend: 726 if (!pm_runtime_status_suspended(&pdev->dev)) 727 sun8i_codec_runtime_suspend(&pdev->dev); 728 729 err_pm_disable: 730 pm_runtime_disable(&pdev->dev); 731 732 return ret; 733 } 734 735 static int sun8i_codec_remove(struct platform_device *pdev) 736 { 737 pm_runtime_disable(&pdev->dev); 738 if (!pm_runtime_status_suspended(&pdev->dev)) 739 sun8i_codec_runtime_suspend(&pdev->dev); 740 741 return 0; 742 } 743 744 static const struct sun8i_codec_quirks sun8i_a33_quirks = { 745 .legacy_widgets = true, 746 .lrck_inversion = true, 747 }; 748 749 static const struct sun8i_codec_quirks sun50i_a64_quirks = { 750 }; 751 752 static const struct of_device_id sun8i_codec_of_match[] = { 753 { .compatible = "allwinner,sun8i-a33-codec", .data = &sun8i_a33_quirks }, 754 { .compatible = "allwinner,sun50i-a64-codec", .data = &sun50i_a64_quirks }, 755 {} 756 }; 757 MODULE_DEVICE_TABLE(of, sun8i_codec_of_match); 758 759 static const struct dev_pm_ops sun8i_codec_pm_ops = { 760 SET_RUNTIME_PM_OPS(sun8i_codec_runtime_suspend, 761 sun8i_codec_runtime_resume, NULL) 762 }; 763 764 static struct platform_driver sun8i_codec_driver = { 765 .driver = { 766 .name = "sun8i-codec", 767 .of_match_table = sun8i_codec_of_match, 768 .pm = &sun8i_codec_pm_ops, 769 }, 770 .probe = sun8i_codec_probe, 771 .remove = sun8i_codec_remove, 772 }; 773 module_platform_driver(sun8i_codec_driver); 774 775 MODULE_DESCRIPTION("Allwinner A33 (sun8i) codec driver"); 776 MODULE_AUTHOR("Mylène Josserand <mylene.josserand@free-electrons.com>"); 777 MODULE_LICENSE("GPL"); 778 MODULE_ALIAS("platform:sun8i-codec"); 779