sun8i-codec.c (45037B)
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#include <sound/tlv.h> 25 26#define SUN8I_SYSCLK_CTL 0x00c 27#define SUN8I_SYSCLK_CTL_AIF1CLK_ENA 11 28#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL (0x2 << 8) 29#define SUN8I_SYSCLK_CTL_AIF2CLK_ENA 7 30#define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL (0x2 << 4) 31#define SUN8I_SYSCLK_CTL_SYSCLK_ENA 3 32#define SUN8I_SYSCLK_CTL_SYSCLK_SRC 0 33#define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK (0x0 << 0) 34#define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF2CLK (0x1 << 0) 35#define SUN8I_MOD_CLK_ENA 0x010 36#define SUN8I_MOD_CLK_ENA_AIF1 15 37#define SUN8I_MOD_CLK_ENA_AIF2 14 38#define SUN8I_MOD_CLK_ENA_AIF3 13 39#define SUN8I_MOD_CLK_ENA_ADC 3 40#define SUN8I_MOD_CLK_ENA_DAC 2 41#define SUN8I_MOD_RST_CTL 0x014 42#define SUN8I_MOD_RST_CTL_AIF1 15 43#define SUN8I_MOD_RST_CTL_AIF2 14 44#define SUN8I_MOD_RST_CTL_AIF3 13 45#define SUN8I_MOD_RST_CTL_ADC 3 46#define SUN8I_MOD_RST_CTL_DAC 2 47#define SUN8I_SYS_SR_CTRL 0x018 48#define SUN8I_SYS_SR_CTRL_AIF1_FS 12 49#define SUN8I_SYS_SR_CTRL_AIF2_FS 8 50#define SUN8I_AIF_CLK_CTRL(n) (0x040 * (1 + (n))) 51#define SUN8I_AIF_CLK_CTRL_MSTR_MOD 15 52#define SUN8I_AIF_CLK_CTRL_CLK_INV 13 53#define SUN8I_AIF_CLK_CTRL_BCLK_DIV 9 54#define SUN8I_AIF_CLK_CTRL_LRCK_DIV 6 55#define SUN8I_AIF_CLK_CTRL_WORD_SIZ 4 56#define SUN8I_AIF_CLK_CTRL_DATA_FMT 2 57#define SUN8I_AIF1_ADCDAT_CTRL 0x044 58#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA 15 59#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA 14 60#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC 10 61#define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC 8 62#define SUN8I_AIF1_DACDAT_CTRL 0x048 63#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA 15 64#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA 14 65#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC 10 66#define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC 8 67#define SUN8I_AIF1_MXR_SRC 0x04c 68#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L 15 69#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL 14 70#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL 13 71#define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR 12 72#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R 11 73#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR 10 74#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR 9 75#define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL 8 76#define SUN8I_AIF1_VOL_CTRL1 0x050 77#define SUN8I_AIF1_VOL_CTRL1_AD0L_VOL 8 78#define SUN8I_AIF1_VOL_CTRL1_AD0R_VOL 0 79#define SUN8I_AIF1_VOL_CTRL3 0x058 80#define SUN8I_AIF1_VOL_CTRL3_DA0L_VOL 8 81#define SUN8I_AIF1_VOL_CTRL3_DA0R_VOL 0 82#define SUN8I_AIF2_ADCDAT_CTRL 0x084 83#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_ENA 15 84#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_ENA 14 85#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_SRC 10 86#define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_SRC 8 87#define SUN8I_AIF2_DACDAT_CTRL 0x088 88#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_ENA 15 89#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_ENA 14 90#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_SRC 10 91#define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_SRC 8 92#define SUN8I_AIF2_MXR_SRC 0x08c 93#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA0L 15 94#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA1L 14 95#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF2DACR 13 96#define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_ADCL 12 97#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA0R 11 98#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA1R 10 99#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF2DACL 9 100#define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_ADCR 8 101#define SUN8I_AIF2_VOL_CTRL1 0x090 102#define SUN8I_AIF2_VOL_CTRL1_ADCL_VOL 8 103#define SUN8I_AIF2_VOL_CTRL1_ADCR_VOL 0 104#define SUN8I_AIF2_VOL_CTRL2 0x098 105#define SUN8I_AIF2_VOL_CTRL2_DACL_VOL 8 106#define SUN8I_AIF2_VOL_CTRL2_DACR_VOL 0 107#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1 (0x0 << 0) 108#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF2 (0x1 << 0) 109#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1CLK (0x2 << 0) 110#define SUN8I_AIF3_PATH_CTRL 0x0cc 111#define SUN8I_AIF3_PATH_CTRL_AIF3_ADC_SRC 10 112#define SUN8I_AIF3_PATH_CTRL_AIF2_DAC_SRC 8 113#define SUN8I_AIF3_PATH_CTRL_AIF3_PINS_TRI 7 114#define SUN8I_ADC_DIG_CTRL 0x100 115#define SUN8I_ADC_DIG_CTRL_ENAD 15 116#define SUN8I_ADC_DIG_CTRL_ADOUT_DTS 2 117#define SUN8I_ADC_DIG_CTRL_ADOUT_DLY 1 118#define SUN8I_ADC_VOL_CTRL 0x104 119#define SUN8I_ADC_VOL_CTRL_ADCL_VOL 8 120#define SUN8I_ADC_VOL_CTRL_ADCR_VOL 0 121#define SUN8I_DAC_DIG_CTRL 0x120 122#define SUN8I_DAC_DIG_CTRL_ENDA 15 123#define SUN8I_DAC_VOL_CTRL 0x124 124#define SUN8I_DAC_VOL_CTRL_DACL_VOL 8 125#define SUN8I_DAC_VOL_CTRL_DACR_VOL 0 126#define SUN8I_DAC_MXR_SRC 0x130 127#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L 15 128#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L 14 129#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL 13 130#define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL 12 131#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R 11 132#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R 10 133#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR 9 134#define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR 8 135 136#define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK GENMASK(9, 8) 137#define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK GENMASK(5, 4) 138#define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK GENMASK(15, 12) 139#define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK GENMASK(11, 8) 140#define SUN8I_AIF_CLK_CTRL_CLK_INV_MASK GENMASK(14, 13) 141#define SUN8I_AIF_CLK_CTRL_BCLK_DIV_MASK GENMASK(12, 9) 142#define SUN8I_AIF_CLK_CTRL_LRCK_DIV_MASK GENMASK(8, 6) 143#define SUN8I_AIF_CLK_CTRL_WORD_SIZ_MASK GENMASK(5, 4) 144#define SUN8I_AIF_CLK_CTRL_DATA_FMT_MASK GENMASK(3, 2) 145#define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_MASK GENMASK(1, 0) 146 147#define SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE 48000 148 149#define SUN8I_CODEC_PCM_FORMATS (SNDRV_PCM_FMTBIT_S8 |\ 150 SNDRV_PCM_FMTBIT_S16_LE |\ 151 SNDRV_PCM_FMTBIT_S20_LE |\ 152 SNDRV_PCM_FMTBIT_S24_LE |\ 153 SNDRV_PCM_FMTBIT_S20_3LE|\ 154 SNDRV_PCM_FMTBIT_S24_3LE) 155 156#define SUN8I_CODEC_PCM_RATES (SNDRV_PCM_RATE_8000_48000|\ 157 SNDRV_PCM_RATE_88200 |\ 158 SNDRV_PCM_RATE_96000 |\ 159 SNDRV_PCM_RATE_176400 |\ 160 SNDRV_PCM_RATE_192000 |\ 161 SNDRV_PCM_RATE_KNOT) 162 163enum { 164 SUN8I_CODEC_AIF1, 165 SUN8I_CODEC_AIF2, 166 SUN8I_CODEC_AIF3, 167 SUN8I_CODEC_NAIFS 168}; 169 170struct sun8i_codec_aif { 171 unsigned int lrck_div_order; 172 unsigned int sample_rate; 173 unsigned int slots; 174 unsigned int slot_width; 175 unsigned int active_streams : 2; 176 unsigned int open_streams : 2; 177}; 178 179struct sun8i_codec_quirks { 180 bool legacy_widgets : 1; 181 bool lrck_inversion : 1; 182}; 183 184struct sun8i_codec { 185 struct regmap *regmap; 186 struct clk *clk_module; 187 const struct sun8i_codec_quirks *quirks; 188 struct sun8i_codec_aif aifs[SUN8I_CODEC_NAIFS]; 189 unsigned int sysclk_rate; 190 int sysclk_refcnt; 191}; 192 193static struct snd_soc_dai_driver sun8i_codec_dais[]; 194 195static int sun8i_codec_runtime_resume(struct device *dev) 196{ 197 struct sun8i_codec *scodec = dev_get_drvdata(dev); 198 int ret; 199 200 regcache_cache_only(scodec->regmap, false); 201 202 ret = regcache_sync(scodec->regmap); 203 if (ret) { 204 dev_err(dev, "Failed to sync regmap cache\n"); 205 return ret; 206 } 207 208 return 0; 209} 210 211static int sun8i_codec_runtime_suspend(struct device *dev) 212{ 213 struct sun8i_codec *scodec = dev_get_drvdata(dev); 214 215 regcache_cache_only(scodec->regmap, true); 216 regcache_mark_dirty(scodec->regmap); 217 218 return 0; 219} 220 221static int sun8i_codec_get_hw_rate(unsigned int sample_rate) 222{ 223 switch (sample_rate) { 224 case 7350: 225 case 8000: 226 return 0x0; 227 case 11025: 228 return 0x1; 229 case 12000: 230 return 0x2; 231 case 14700: 232 case 16000: 233 return 0x3; 234 case 22050: 235 return 0x4; 236 case 24000: 237 return 0x5; 238 case 29400: 239 case 32000: 240 return 0x6; 241 case 44100: 242 return 0x7; 243 case 48000: 244 return 0x8; 245 case 88200: 246 case 96000: 247 return 0x9; 248 case 176400: 249 case 192000: 250 return 0xa; 251 default: 252 return -EINVAL; 253 } 254} 255 256static int sun8i_codec_update_sample_rate(struct sun8i_codec *scodec) 257{ 258 unsigned int max_rate = 0; 259 int hw_rate, i; 260 261 for (i = SUN8I_CODEC_AIF1; i < SUN8I_CODEC_NAIFS; ++i) { 262 struct sun8i_codec_aif *aif = &scodec->aifs[i]; 263 264 if (aif->active_streams) 265 max_rate = max(max_rate, aif->sample_rate); 266 } 267 268 /* Set the sample rate for ADC->DAC passthrough when no AIF is active. */ 269 if (!max_rate) 270 max_rate = SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE; 271 272 hw_rate = sun8i_codec_get_hw_rate(max_rate); 273 if (hw_rate < 0) 274 return hw_rate; 275 276 regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL, 277 SUN8I_SYS_SR_CTRL_AIF1_FS_MASK, 278 hw_rate << SUN8I_SYS_SR_CTRL_AIF1_FS); 279 280 return 0; 281} 282 283static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 284{ 285 struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); 286 u32 dsp_format, format, invert, value; 287 288 /* clock masters */ 289 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 290 case SND_SOC_DAIFMT_CBS_CFS: /* Codec slave, DAI master */ 291 value = 0x1; 292 break; 293 case SND_SOC_DAIFMT_CBM_CFM: /* Codec Master, DAI slave */ 294 value = 0x0; 295 break; 296 default: 297 return -EINVAL; 298 } 299 300 if (dai->id == SUN8I_CODEC_AIF3) { 301 /* AIF3 only supports master mode. */ 302 if (value) 303 return -EINVAL; 304 305 /* Use the AIF2 BCLK and LRCK for AIF3. */ 306 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id), 307 SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_MASK, 308 SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF2); 309 } else { 310 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id), 311 BIT(SUN8I_AIF_CLK_CTRL_MSTR_MOD), 312 value << SUN8I_AIF_CLK_CTRL_MSTR_MOD); 313 } 314 315 /* DAI format */ 316 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 317 case SND_SOC_DAIFMT_I2S: 318 format = 0x0; 319 break; 320 case SND_SOC_DAIFMT_LEFT_J: 321 format = 0x1; 322 break; 323 case SND_SOC_DAIFMT_RIGHT_J: 324 format = 0x2; 325 break; 326 case SND_SOC_DAIFMT_DSP_A: 327 format = 0x3; 328 dsp_format = 0x0; /* Set LRCK_INV to 0 */ 329 break; 330 case SND_SOC_DAIFMT_DSP_B: 331 format = 0x3; 332 dsp_format = 0x1; /* Set LRCK_INV to 1 */ 333 break; 334 default: 335 return -EINVAL; 336 } 337 338 if (dai->id == SUN8I_CODEC_AIF3) { 339 /* AIF3 only supports DSP mode. */ 340 if (format != 3) 341 return -EINVAL; 342 } else { 343 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id), 344 SUN8I_AIF_CLK_CTRL_DATA_FMT_MASK, 345 format << SUN8I_AIF_CLK_CTRL_DATA_FMT); 346 } 347 348 /* clock inversion */ 349 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 350 case SND_SOC_DAIFMT_NB_NF: /* Normal */ 351 invert = 0x0; 352 break; 353 case SND_SOC_DAIFMT_NB_IF: /* Inverted LRCK */ 354 invert = 0x1; 355 break; 356 case SND_SOC_DAIFMT_IB_NF: /* Inverted BCLK */ 357 invert = 0x2; 358 break; 359 case SND_SOC_DAIFMT_IB_IF: /* Both inverted */ 360 invert = 0x3; 361 break; 362 default: 363 return -EINVAL; 364 } 365 366 if (format == 0x3) { 367 /* Inverted LRCK is not available in DSP mode. */ 368 if (invert & BIT(0)) 369 return -EINVAL; 370 371 /* Instead, the bit selects between DSP A/B formats. */ 372 invert |= dsp_format; 373 } else { 374 /* 375 * It appears that the DAI and the codec in the A33 SoC don't 376 * share the same polarity for the LRCK signal when they mean 377 * 'normal' and 'inverted' in the datasheet. 378 * 379 * Since the DAI here is our regular i2s driver that have been 380 * tested with way more codecs than just this one, it means 381 * that the codec probably gets it backward, and we have to 382 * invert the value here. 383 */ 384 invert ^= scodec->quirks->lrck_inversion; 385 } 386 387 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id), 388 SUN8I_AIF_CLK_CTRL_CLK_INV_MASK, 389 invert << SUN8I_AIF_CLK_CTRL_CLK_INV); 390 391 return 0; 392} 393 394static int sun8i_codec_set_tdm_slot(struct snd_soc_dai *dai, 395 unsigned int tx_mask, unsigned int rx_mask, 396 int slots, int slot_width) 397{ 398 struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); 399 struct sun8i_codec_aif *aif = &scodec->aifs[dai->id]; 400 401 if (slot_width && !is_power_of_2(slot_width)) 402 return -EINVAL; 403 404 aif->slots = slots; 405 aif->slot_width = slot_width; 406 407 return 0; 408} 409 410static const unsigned int sun8i_codec_rates[] = { 411 7350, 8000, 11025, 12000, 14700, 16000, 22050, 24000, 412 29400, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 413}; 414 415static const struct snd_pcm_hw_constraint_list sun8i_codec_all_rates = { 416 .list = sun8i_codec_rates, 417 .count = ARRAY_SIZE(sun8i_codec_rates), 418}; 419 420static const struct snd_pcm_hw_constraint_list sun8i_codec_22M_rates = { 421 .list = sun8i_codec_rates, 422 .count = ARRAY_SIZE(sun8i_codec_rates), 423 .mask = 0x5555, 424}; 425 426static const struct snd_pcm_hw_constraint_list sun8i_codec_24M_rates = { 427 .list = sun8i_codec_rates, 428 .count = ARRAY_SIZE(sun8i_codec_rates), 429 .mask = 0xaaaa, 430}; 431 432static int sun8i_codec_startup(struct snd_pcm_substream *substream, 433 struct snd_soc_dai *dai) 434{ 435 struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); 436 const struct snd_pcm_hw_constraint_list *list; 437 438 /* hw_constraints is not relevant for codec2codec DAIs. */ 439 if (dai->id != SUN8I_CODEC_AIF1) 440 return 0; 441 442 if (!scodec->sysclk_refcnt) 443 list = &sun8i_codec_all_rates; 444 else if (scodec->sysclk_rate == 22579200) 445 list = &sun8i_codec_22M_rates; 446 else if (scodec->sysclk_rate == 24576000) 447 list = &sun8i_codec_24M_rates; 448 else 449 return -EINVAL; 450 451 return snd_pcm_hw_constraint_list(substream->runtime, 0, 452 SNDRV_PCM_HW_PARAM_RATE, list); 453} 454 455struct sun8i_codec_clk_div { 456 u8 div; 457 u8 val; 458}; 459 460static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = { 461 { .div = 1, .val = 0 }, 462 { .div = 2, .val = 1 }, 463 { .div = 4, .val = 2 }, 464 { .div = 6, .val = 3 }, 465 { .div = 8, .val = 4 }, 466 { .div = 12, .val = 5 }, 467 { .div = 16, .val = 6 }, 468 { .div = 24, .val = 7 }, 469 { .div = 32, .val = 8 }, 470 { .div = 48, .val = 9 }, 471 { .div = 64, .val = 10 }, 472 { .div = 96, .val = 11 }, 473 { .div = 128, .val = 12 }, 474 { .div = 192, .val = 13 }, 475}; 476 477static int sun8i_codec_get_bclk_div(unsigned int sysclk_rate, 478 unsigned int lrck_div_order, 479 unsigned int sample_rate) 480{ 481 unsigned int div = sysclk_rate / sample_rate >> lrck_div_order; 482 int i; 483 484 for (i = 0; i < ARRAY_SIZE(sun8i_codec_bclk_div); i++) { 485 const struct sun8i_codec_clk_div *bdiv = &sun8i_codec_bclk_div[i]; 486 487 if (bdiv->div == div) 488 return bdiv->val; 489 } 490 491 return -EINVAL; 492} 493 494static int sun8i_codec_get_lrck_div_order(unsigned int slots, 495 unsigned int slot_width) 496{ 497 unsigned int div = slots * slot_width; 498 499 if (div < 16 || div > 256) 500 return -EINVAL; 501 502 return order_base_2(div); 503} 504 505static unsigned int sun8i_codec_get_sysclk_rate(unsigned int sample_rate) 506{ 507 return (sample_rate % 4000) ? 22579200 : 24576000; 508} 509 510static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, 511 struct snd_pcm_hw_params *params, 512 struct snd_soc_dai *dai) 513{ 514 struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); 515 struct sun8i_codec_aif *aif = &scodec->aifs[dai->id]; 516 unsigned int sample_rate = params_rate(params); 517 unsigned int slots = aif->slots ?: params_channels(params); 518 unsigned int slot_width = aif->slot_width ?: params_width(params); 519 unsigned int sysclk_rate = sun8i_codec_get_sysclk_rate(sample_rate); 520 int bclk_div, lrck_div_order, ret, word_size; 521 u32 clk_reg; 522 523 /* word size */ 524 switch (params_width(params)) { 525 case 8: 526 word_size = 0x0; 527 break; 528 case 16: 529 word_size = 0x1; 530 break; 531 case 20: 532 word_size = 0x2; 533 break; 534 case 24: 535 word_size = 0x3; 536 break; 537 default: 538 return -EINVAL; 539 } 540 541 regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id), 542 SUN8I_AIF_CLK_CTRL_WORD_SIZ_MASK, 543 word_size << SUN8I_AIF_CLK_CTRL_WORD_SIZ); 544 545 /* LRCK divider (BCLK/LRCK ratio) */ 546 lrck_div_order = sun8i_codec_get_lrck_div_order(slots, slot_width); 547 if (lrck_div_order < 0) 548 return lrck_div_order; 549 550 if (dai->id == SUN8I_CODEC_AIF2 || dai->id == SUN8I_CODEC_AIF3) { 551 /* AIF2 and AIF3 share AIF2's BCLK and LRCK generation circuitry. */ 552 int partner = (SUN8I_CODEC_AIF2 + SUN8I_CODEC_AIF3) - dai->id; 553 const struct sun8i_codec_aif *partner_aif = &scodec->aifs[partner]; 554 const char *partner_name = sun8i_codec_dais[partner].name; 555 556 if (partner_aif->open_streams && 557 (lrck_div_order != partner_aif->lrck_div_order || 558 sample_rate != partner_aif->sample_rate)) { 559 dev_err(dai->dev, 560 "%s sample and bit rates must match %s when both are used\n", 561 dai->name, partner_name); 562 return -EBUSY; 563 } 564 565 clk_reg = SUN8I_AIF_CLK_CTRL(SUN8I_CODEC_AIF2); 566 } else { 567 clk_reg = SUN8I_AIF_CLK_CTRL(dai->id); 568 } 569 570 regmap_update_bits(scodec->regmap, clk_reg, 571 SUN8I_AIF_CLK_CTRL_LRCK_DIV_MASK, 572 (lrck_div_order - 4) << SUN8I_AIF_CLK_CTRL_LRCK_DIV); 573 574 /* BCLK divider (SYSCLK/BCLK ratio) */ 575 bclk_div = sun8i_codec_get_bclk_div(sysclk_rate, lrck_div_order, sample_rate); 576 if (bclk_div < 0) 577 return bclk_div; 578 579 regmap_update_bits(scodec->regmap, clk_reg, 580 SUN8I_AIF_CLK_CTRL_BCLK_DIV_MASK, 581 bclk_div << SUN8I_AIF_CLK_CTRL_BCLK_DIV); 582 583 /* 584 * SYSCLK rate 585 * 586 * Clock rate protection is reference counted; but hw_params may be 587 * called many times per substream, without matching calls to hw_free. 588 * Protect the clock rate once per AIF, on the first hw_params call 589 * for the first substream. clk_set_rate() will allow clock rate 590 * changes on subsequent calls if only one AIF has open streams. 591 */ 592 ret = (aif->open_streams ? clk_set_rate : clk_set_rate_exclusive)(scodec->clk_module, 593 sysclk_rate); 594 if (ret == -EBUSY) 595 dev_err(dai->dev, 596 "%s sample rate (%u Hz) conflicts with other audio streams\n", 597 dai->name, sample_rate); 598 if (ret < 0) 599 return ret; 600 601 if (!aif->open_streams) 602 scodec->sysclk_refcnt++; 603 scodec->sysclk_rate = sysclk_rate; 604 605 aif->lrck_div_order = lrck_div_order; 606 aif->sample_rate = sample_rate; 607 aif->open_streams |= BIT(substream->stream); 608 609 return sun8i_codec_update_sample_rate(scodec); 610} 611 612static int sun8i_codec_hw_free(struct snd_pcm_substream *substream, 613 struct snd_soc_dai *dai) 614{ 615 struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai); 616 struct sun8i_codec_aif *aif = &scodec->aifs[dai->id]; 617 618 /* Drop references when the last substream for the AIF is freed. */ 619 if (aif->open_streams != BIT(substream->stream)) 620 goto done; 621 622 clk_rate_exclusive_put(scodec->clk_module); 623 scodec->sysclk_refcnt--; 624 aif->lrck_div_order = 0; 625 aif->sample_rate = 0; 626 627done: 628 aif->open_streams &= ~BIT(substream->stream); 629 return 0; 630} 631 632static const struct snd_soc_dai_ops sun8i_codec_dai_ops = { 633 .set_fmt = sun8i_codec_set_fmt, 634 .set_tdm_slot = sun8i_codec_set_tdm_slot, 635 .startup = sun8i_codec_startup, 636 .hw_params = sun8i_codec_hw_params, 637 .hw_free = sun8i_codec_hw_free, 638}; 639 640static struct snd_soc_dai_driver sun8i_codec_dais[] = { 641 { 642 .name = "sun8i-codec-aif1", 643 .id = SUN8I_CODEC_AIF1, 644 .ops = &sun8i_codec_dai_ops, 645 /* capture capabilities */ 646 .capture = { 647 .stream_name = "AIF1 Capture", 648 .channels_min = 1, 649 .channels_max = 2, 650 .rates = SUN8I_CODEC_PCM_RATES, 651 .formats = SUN8I_CODEC_PCM_FORMATS, 652 .sig_bits = 24, 653 }, 654 /* playback capabilities */ 655 .playback = { 656 .stream_name = "AIF1 Playback", 657 .channels_min = 1, 658 .channels_max = 2, 659 .rates = SUN8I_CODEC_PCM_RATES, 660 .formats = SUN8I_CODEC_PCM_FORMATS, 661 }, 662 .symmetric_rate = true, 663 .symmetric_channels = true, 664 .symmetric_sample_bits = true, 665 }, 666 { 667 .name = "sun8i-codec-aif2", 668 .id = SUN8I_CODEC_AIF2, 669 .ops = &sun8i_codec_dai_ops, 670 /* capture capabilities */ 671 .capture = { 672 .stream_name = "AIF2 Capture", 673 .channels_min = 1, 674 .channels_max = 2, 675 .rates = SUN8I_CODEC_PCM_RATES, 676 .formats = SUN8I_CODEC_PCM_FORMATS, 677 .sig_bits = 24, 678 }, 679 /* playback capabilities */ 680 .playback = { 681 .stream_name = "AIF2 Playback", 682 .channels_min = 1, 683 .channels_max = 2, 684 .rates = SUN8I_CODEC_PCM_RATES, 685 .formats = SUN8I_CODEC_PCM_FORMATS, 686 }, 687 .symmetric_rate = true, 688 .symmetric_channels = true, 689 .symmetric_sample_bits = true, 690 }, 691 { 692 .name = "sun8i-codec-aif3", 693 .id = SUN8I_CODEC_AIF3, 694 .ops = &sun8i_codec_dai_ops, 695 /* capture capabilities */ 696 .capture = { 697 .stream_name = "AIF3 Capture", 698 .channels_min = 1, 699 .channels_max = 1, 700 .rates = SUN8I_CODEC_PCM_RATES, 701 .formats = SUN8I_CODEC_PCM_FORMATS, 702 .sig_bits = 24, 703 }, 704 /* playback capabilities */ 705 .playback = { 706 .stream_name = "AIF3 Playback", 707 .channels_min = 1, 708 .channels_max = 1, 709 .rates = SUN8I_CODEC_PCM_RATES, 710 .formats = SUN8I_CODEC_PCM_FORMATS, 711 }, 712 .symmetric_rate = true, 713 .symmetric_channels = true, 714 .symmetric_sample_bits = true, 715 }, 716}; 717 718static const DECLARE_TLV_DB_SCALE(sun8i_codec_vol_scale, -12000, 75, 1); 719 720static const struct snd_kcontrol_new sun8i_codec_controls[] = { 721 SOC_DOUBLE_TLV("AIF1 AD0 Capture Volume", 722 SUN8I_AIF1_VOL_CTRL1, 723 SUN8I_AIF1_VOL_CTRL1_AD0L_VOL, 724 SUN8I_AIF1_VOL_CTRL1_AD0R_VOL, 725 0xc0, 0, sun8i_codec_vol_scale), 726 SOC_DOUBLE_TLV("AIF1 DA0 Playback Volume", 727 SUN8I_AIF1_VOL_CTRL3, 728 SUN8I_AIF1_VOL_CTRL3_DA0L_VOL, 729 SUN8I_AIF1_VOL_CTRL3_DA0R_VOL, 730 0xc0, 0, sun8i_codec_vol_scale), 731 SOC_DOUBLE_TLV("AIF2 ADC Capture Volume", 732 SUN8I_AIF2_VOL_CTRL1, 733 SUN8I_AIF2_VOL_CTRL1_ADCL_VOL, 734 SUN8I_AIF2_VOL_CTRL1_ADCR_VOL, 735 0xc0, 0, sun8i_codec_vol_scale), 736 SOC_DOUBLE_TLV("AIF2 DAC Playback Volume", 737 SUN8I_AIF2_VOL_CTRL2, 738 SUN8I_AIF2_VOL_CTRL2_DACL_VOL, 739 SUN8I_AIF2_VOL_CTRL2_DACR_VOL, 740 0xc0, 0, sun8i_codec_vol_scale), 741 SOC_DOUBLE_TLV("ADC Capture Volume", 742 SUN8I_ADC_VOL_CTRL, 743 SUN8I_ADC_VOL_CTRL_ADCL_VOL, 744 SUN8I_ADC_VOL_CTRL_ADCR_VOL, 745 0xc0, 0, sun8i_codec_vol_scale), 746 SOC_DOUBLE_TLV("DAC Playback Volume", 747 SUN8I_DAC_VOL_CTRL, 748 SUN8I_DAC_VOL_CTRL_DACL_VOL, 749 SUN8I_DAC_VOL_CTRL_DACR_VOL, 750 0xc0, 0, sun8i_codec_vol_scale), 751}; 752 753static int sun8i_codec_aif_event(struct snd_soc_dapm_widget *w, 754 struct snd_kcontrol *kcontrol, int event) 755{ 756 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); 757 struct sun8i_codec *scodec = snd_soc_component_get_drvdata(component); 758 struct sun8i_codec_aif *aif = &scodec->aifs[w->sname[3] - '1']; 759 int stream = w->id == snd_soc_dapm_aif_out; 760 761 if (SND_SOC_DAPM_EVENT_ON(event)) 762 aif->active_streams |= BIT(stream); 763 else 764 aif->active_streams &= ~BIT(stream); 765 766 return sun8i_codec_update_sample_rate(scodec); 767} 768 769static const char *const sun8i_aif_stereo_mux_enum_values[] = { 770 "Stereo", "Reverse Stereo", "Sum Mono", "Mix Mono" 771}; 772 773static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_ad0_stereo_mux_enum, 774 SUN8I_AIF1_ADCDAT_CTRL, 775 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC, 776 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC, 777 sun8i_aif_stereo_mux_enum_values); 778 779static const struct snd_kcontrol_new sun8i_aif1_ad0_stereo_mux_control = 780 SOC_DAPM_ENUM("AIF1 AD0 Stereo Capture Route", 781 sun8i_aif1_ad0_stereo_mux_enum); 782 783static SOC_ENUM_DOUBLE_DECL(sun8i_aif2_adc_stereo_mux_enum, 784 SUN8I_AIF2_ADCDAT_CTRL, 785 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_SRC, 786 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_SRC, 787 sun8i_aif_stereo_mux_enum_values); 788 789static const struct snd_kcontrol_new sun8i_aif2_adc_stereo_mux_control = 790 SOC_DAPM_ENUM("AIF2 ADC Stereo Capture Route", 791 sun8i_aif2_adc_stereo_mux_enum); 792 793static const char *const sun8i_aif3_adc_mux_enum_values[] = { 794 "None", "AIF2 ADCL", "AIF2 ADCR" 795}; 796 797static SOC_ENUM_SINGLE_DECL(sun8i_aif3_adc_mux_enum, 798 SUN8I_AIF3_PATH_CTRL, 799 SUN8I_AIF3_PATH_CTRL_AIF3_ADC_SRC, 800 sun8i_aif3_adc_mux_enum_values); 801 802static const struct snd_kcontrol_new sun8i_aif3_adc_mux_control = 803 SOC_DAPM_ENUM("AIF3 ADC Source Capture Route", 804 sun8i_aif3_adc_mux_enum); 805 806static const struct snd_kcontrol_new sun8i_aif1_ad0_mixer_controls[] = { 807 SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital ADC Capture Switch", 808 SUN8I_AIF1_MXR_SRC, 809 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L, 810 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R, 1, 0), 811 SOC_DAPM_DOUBLE("AIF2 Digital ADC Capture Switch", 812 SUN8I_AIF1_MXR_SRC, 813 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL, 814 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR, 1, 0), 815 SOC_DAPM_DOUBLE("AIF1 Data Digital ADC Capture Switch", 816 SUN8I_AIF1_MXR_SRC, 817 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL, 818 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR, 1, 0), 819 SOC_DAPM_DOUBLE("AIF2 Inv Digital ADC Capture Switch", 820 SUN8I_AIF1_MXR_SRC, 821 SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR, 822 SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL, 1, 0), 823}; 824 825static const struct snd_kcontrol_new sun8i_aif2_adc_mixer_controls[] = { 826 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF1 DA0 Capture Switch", 827 SUN8I_AIF2_MXR_SRC, 828 SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA0L, 829 SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA0R, 1, 0), 830 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF1 DA1 Capture Switch", 831 SUN8I_AIF2_MXR_SRC, 832 SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA1L, 833 SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA1R, 1, 0), 834 SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF2 DAC Rev Capture Switch", 835 SUN8I_AIF2_MXR_SRC, 836 SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF2DACR, 837 SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF2DACL, 1, 0), 838 SOC_DAPM_DOUBLE("AIF2 ADC Mixer ADC Capture Switch", 839 SUN8I_AIF2_MXR_SRC, 840 SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_ADCL, 841 SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_ADCR, 1, 0), 842}; 843 844static const char *const sun8i_aif2_dac_mux_enum_values[] = { 845 "AIF2", "AIF3+2", "AIF2+3" 846}; 847 848static SOC_ENUM_SINGLE_DECL(sun8i_aif2_dac_mux_enum, 849 SUN8I_AIF3_PATH_CTRL, 850 SUN8I_AIF3_PATH_CTRL_AIF2_DAC_SRC, 851 sun8i_aif2_dac_mux_enum_values); 852 853static const struct snd_kcontrol_new sun8i_aif2_dac_mux_control = 854 SOC_DAPM_ENUM("AIF2 DAC Source Playback Route", 855 sun8i_aif2_dac_mux_enum); 856 857static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_da0_stereo_mux_enum, 858 SUN8I_AIF1_DACDAT_CTRL, 859 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC, 860 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC, 861 sun8i_aif_stereo_mux_enum_values); 862 863static const struct snd_kcontrol_new sun8i_aif1_da0_stereo_mux_control = 864 SOC_DAPM_ENUM("AIF1 DA0 Stereo Playback Route", 865 sun8i_aif1_da0_stereo_mux_enum); 866 867static SOC_ENUM_DOUBLE_DECL(sun8i_aif2_dac_stereo_mux_enum, 868 SUN8I_AIF2_DACDAT_CTRL, 869 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_SRC, 870 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_SRC, 871 sun8i_aif_stereo_mux_enum_values); 872 873static const struct snd_kcontrol_new sun8i_aif2_dac_stereo_mux_control = 874 SOC_DAPM_ENUM("AIF2 DAC Stereo Playback Route", 875 sun8i_aif2_dac_stereo_mux_enum); 876 877static const struct snd_kcontrol_new sun8i_dac_mixer_controls[] = { 878 SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital DAC Playback Switch", 879 SUN8I_DAC_MXR_SRC, 880 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L, 881 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R, 1, 0), 882 SOC_DAPM_DOUBLE("AIF1 Slot 1 Digital DAC Playback Switch", 883 SUN8I_DAC_MXR_SRC, 884 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L, 885 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R, 1, 0), 886 SOC_DAPM_DOUBLE("AIF2 Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC, 887 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL, 888 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR, 1, 0), 889 SOC_DAPM_DOUBLE("ADC Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC, 890 SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL, 891 SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR, 1, 0), 892}; 893 894static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets[] = { 895 /* System Clocks */ 896 SND_SOC_DAPM_CLOCK_SUPPLY("mod"), 897 898 SND_SOC_DAPM_SUPPLY("AIF1CLK", 899 SUN8I_SYSCLK_CTL, 900 SUN8I_SYSCLK_CTL_AIF1CLK_ENA, 0, NULL, 0), 901 SND_SOC_DAPM_SUPPLY("AIF2CLK", 902 SUN8I_SYSCLK_CTL, 903 SUN8I_SYSCLK_CTL_AIF2CLK_ENA, 0, NULL, 0), 904 SND_SOC_DAPM_SUPPLY("SYSCLK", 905 SUN8I_SYSCLK_CTL, 906 SUN8I_SYSCLK_CTL_SYSCLK_ENA, 0, NULL, 0), 907 908 /* Module Clocks */ 909 SND_SOC_DAPM_SUPPLY("CLK AIF1", 910 SUN8I_MOD_CLK_ENA, 911 SUN8I_MOD_CLK_ENA_AIF1, 0, NULL, 0), 912 SND_SOC_DAPM_SUPPLY("CLK AIF2", 913 SUN8I_MOD_CLK_ENA, 914 SUN8I_MOD_CLK_ENA_AIF2, 0, NULL, 0), 915 SND_SOC_DAPM_SUPPLY("CLK AIF3", 916 SUN8I_MOD_CLK_ENA, 917 SUN8I_MOD_CLK_ENA_AIF3, 0, NULL, 0), 918 SND_SOC_DAPM_SUPPLY("CLK ADC", 919 SUN8I_MOD_CLK_ENA, 920 SUN8I_MOD_CLK_ENA_ADC, 0, NULL, 0), 921 SND_SOC_DAPM_SUPPLY("CLK DAC", 922 SUN8I_MOD_CLK_ENA, 923 SUN8I_MOD_CLK_ENA_DAC, 0, NULL, 0), 924 925 /* Module Resets */ 926 SND_SOC_DAPM_SUPPLY("RST AIF1", 927 SUN8I_MOD_RST_CTL, 928 SUN8I_MOD_RST_CTL_AIF1, 0, NULL, 0), 929 SND_SOC_DAPM_SUPPLY("RST AIF2", 930 SUN8I_MOD_RST_CTL, 931 SUN8I_MOD_RST_CTL_AIF2, 0, NULL, 0), 932 SND_SOC_DAPM_SUPPLY("RST AIF3", 933 SUN8I_MOD_RST_CTL, 934 SUN8I_MOD_RST_CTL_AIF3, 0, NULL, 0), 935 SND_SOC_DAPM_SUPPLY("RST ADC", 936 SUN8I_MOD_RST_CTL, 937 SUN8I_MOD_RST_CTL_ADC, 0, NULL, 0), 938 SND_SOC_DAPM_SUPPLY("RST DAC", 939 SUN8I_MOD_RST_CTL, 940 SUN8I_MOD_RST_CTL_DAC, 0, NULL, 0), 941 942 /* Module Supplies */ 943 SND_SOC_DAPM_SUPPLY("ADC", 944 SUN8I_ADC_DIG_CTRL, 945 SUN8I_ADC_DIG_CTRL_ENAD, 0, NULL, 0), 946 SND_SOC_DAPM_SUPPLY("DAC", 947 SUN8I_DAC_DIG_CTRL, 948 SUN8I_DAC_DIG_CTRL_ENDA, 0, NULL, 0), 949 950 /* AIF "ADC" Outputs */ 951 SND_SOC_DAPM_AIF_OUT_E("AIF1 AD0L", "AIF1 Capture", 0, 952 SUN8I_AIF1_ADCDAT_CTRL, 953 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA, 0, 954 sun8i_codec_aif_event, 955 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 956 SND_SOC_DAPM_AIF_OUT("AIF1 AD0R", "AIF1 Capture", 1, 957 SUN8I_AIF1_ADCDAT_CTRL, 958 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA, 0), 959 960 SND_SOC_DAPM_AIF_OUT_E("AIF2 ADCL", "AIF2 Capture", 0, 961 SUN8I_AIF2_ADCDAT_CTRL, 962 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_ENA, 0, 963 sun8i_codec_aif_event, 964 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 965 SND_SOC_DAPM_AIF_OUT("AIF2 ADCR", "AIF2 Capture", 1, 966 SUN8I_AIF2_ADCDAT_CTRL, 967 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_ENA, 0), 968 969 SND_SOC_DAPM_AIF_OUT_E("AIF3 ADC", "AIF3 Capture", 0, 970 SND_SOC_NOPM, 0, 0, 971 sun8i_codec_aif_event, 972 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 973 974 /* AIF "ADC" Mono/Stereo Muxes */ 975 SND_SOC_DAPM_MUX("AIF1 AD0L Stereo Mux", SND_SOC_NOPM, 0, 0, 976 &sun8i_aif1_ad0_stereo_mux_control), 977 SND_SOC_DAPM_MUX("AIF1 AD0R Stereo Mux", SND_SOC_NOPM, 0, 0, 978 &sun8i_aif1_ad0_stereo_mux_control), 979 980 SND_SOC_DAPM_MUX("AIF2 ADCL Stereo Mux", SND_SOC_NOPM, 0, 0, 981 &sun8i_aif2_adc_stereo_mux_control), 982 SND_SOC_DAPM_MUX("AIF2 ADCR Stereo Mux", SND_SOC_NOPM, 0, 0, 983 &sun8i_aif2_adc_stereo_mux_control), 984 985 /* AIF "ADC" Output Muxes */ 986 SND_SOC_DAPM_MUX("AIF3 ADC Source Capture Route", SND_SOC_NOPM, 0, 0, 987 &sun8i_aif3_adc_mux_control), 988 989 /* AIF "ADC" Mixers */ 990 SOC_MIXER_ARRAY("AIF1 AD0L Mixer", SND_SOC_NOPM, 0, 0, 991 sun8i_aif1_ad0_mixer_controls), 992 SOC_MIXER_ARRAY("AIF1 AD0R Mixer", SND_SOC_NOPM, 0, 0, 993 sun8i_aif1_ad0_mixer_controls), 994 995 SOC_MIXER_ARRAY("AIF2 ADCL Mixer", SND_SOC_NOPM, 0, 0, 996 sun8i_aif2_adc_mixer_controls), 997 SOC_MIXER_ARRAY("AIF2 ADCR Mixer", SND_SOC_NOPM, 0, 0, 998 sun8i_aif2_adc_mixer_controls), 999 1000 /* AIF "DAC" Input Muxes */ 1001 SND_SOC_DAPM_MUX("AIF2 DACL Source", SND_SOC_NOPM, 0, 0, 1002 &sun8i_aif2_dac_mux_control), 1003 SND_SOC_DAPM_MUX("AIF2 DACR Source", SND_SOC_NOPM, 0, 0, 1004 &sun8i_aif2_dac_mux_control), 1005 1006 /* AIF "DAC" Mono/Stereo Muxes */ 1007 SND_SOC_DAPM_MUX("AIF1 DA0L Stereo Mux", SND_SOC_NOPM, 0, 0, 1008 &sun8i_aif1_da0_stereo_mux_control), 1009 SND_SOC_DAPM_MUX("AIF1 DA0R Stereo Mux", SND_SOC_NOPM, 0, 0, 1010 &sun8i_aif1_da0_stereo_mux_control), 1011 1012 SND_SOC_DAPM_MUX("AIF2 DACL Stereo Mux", SND_SOC_NOPM, 0, 0, 1013 &sun8i_aif2_dac_stereo_mux_control), 1014 SND_SOC_DAPM_MUX("AIF2 DACR Stereo Mux", SND_SOC_NOPM, 0, 0, 1015 &sun8i_aif2_dac_stereo_mux_control), 1016 1017 /* AIF "DAC" Inputs */ 1018 SND_SOC_DAPM_AIF_IN_E("AIF1 DA0L", "AIF1 Playback", 0, 1019 SUN8I_AIF1_DACDAT_CTRL, 1020 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA, 0, 1021 sun8i_codec_aif_event, 1022 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 1023 SND_SOC_DAPM_AIF_IN("AIF1 DA0R", "AIF1 Playback", 1, 1024 SUN8I_AIF1_DACDAT_CTRL, 1025 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA, 0), 1026 1027 SND_SOC_DAPM_AIF_IN_E("AIF2 DACL", "AIF2 Playback", 0, 1028 SUN8I_AIF2_DACDAT_CTRL, 1029 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_ENA, 0, 1030 sun8i_codec_aif_event, 1031 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 1032 SND_SOC_DAPM_AIF_IN("AIF2 DACR", "AIF2 Playback", 1, 1033 SUN8I_AIF2_DACDAT_CTRL, 1034 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_ENA, 0), 1035 1036 SND_SOC_DAPM_AIF_IN_E("AIF3 DAC", "AIF3 Playback", 0, 1037 SND_SOC_NOPM, 0, 0, 1038 sun8i_codec_aif_event, 1039 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), 1040 1041 /* ADC Inputs (connected to analog codec DAPM context) */ 1042 SND_SOC_DAPM_ADC("ADCL", NULL, SND_SOC_NOPM, 0, 0), 1043 SND_SOC_DAPM_ADC("ADCR", NULL, SND_SOC_NOPM, 0, 0), 1044 1045 /* DAC Outputs (connected to analog codec DAPM context) */ 1046 SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0), 1047 SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0), 1048 1049 /* DAC Mixers */ 1050 SOC_MIXER_ARRAY("DACL Mixer", SND_SOC_NOPM, 0, 0, 1051 sun8i_dac_mixer_controls), 1052 SOC_MIXER_ARRAY("DACR Mixer", SND_SOC_NOPM, 0, 0, 1053 sun8i_dac_mixer_controls), 1054}; 1055 1056static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = { 1057 /* Clock Routes */ 1058 { "AIF1CLK", NULL, "mod" }, 1059 1060 { "SYSCLK", NULL, "AIF1CLK" }, 1061 1062 { "CLK AIF1", NULL, "AIF1CLK" }, 1063 { "CLK AIF1", NULL, "SYSCLK" }, 1064 { "RST AIF1", NULL, "CLK AIF1" }, 1065 { "AIF1 AD0L", NULL, "RST AIF1" }, 1066 { "AIF1 AD0R", NULL, "RST AIF1" }, 1067 { "AIF1 DA0L", NULL, "RST AIF1" }, 1068 { "AIF1 DA0R", NULL, "RST AIF1" }, 1069 1070 { "CLK AIF2", NULL, "AIF2CLK" }, 1071 { "CLK AIF2", NULL, "SYSCLK" }, 1072 { "RST AIF2", NULL, "CLK AIF2" }, 1073 { "AIF2 ADCL", NULL, "RST AIF2" }, 1074 { "AIF2 ADCR", NULL, "RST AIF2" }, 1075 { "AIF2 DACL", NULL, "RST AIF2" }, 1076 { "AIF2 DACR", NULL, "RST AIF2" }, 1077 1078 { "CLK AIF3", NULL, "AIF1CLK" }, 1079 { "CLK AIF3", NULL, "SYSCLK" }, 1080 { "RST AIF3", NULL, "CLK AIF3" }, 1081 { "AIF3 ADC", NULL, "RST AIF3" }, 1082 { "AIF3 DAC", NULL, "RST AIF3" }, 1083 1084 { "CLK ADC", NULL, "SYSCLK" }, 1085 { "RST ADC", NULL, "CLK ADC" }, 1086 { "ADC", NULL, "RST ADC" }, 1087 { "ADCL", NULL, "ADC" }, 1088 { "ADCR", NULL, "ADC" }, 1089 1090 { "CLK DAC", NULL, "SYSCLK" }, 1091 { "RST DAC", NULL, "CLK DAC" }, 1092 { "DAC", NULL, "RST DAC" }, 1093 { "DACL", NULL, "DAC" }, 1094 { "DACR", NULL, "DAC" }, 1095 1096 /* AIF "ADC" Output Routes */ 1097 { "AIF1 AD0L", NULL, "AIF1 AD0L Stereo Mux" }, 1098 { "AIF1 AD0R", NULL, "AIF1 AD0R Stereo Mux" }, 1099 1100 { "AIF2 ADCL", NULL, "AIF2 ADCL Stereo Mux" }, 1101 { "AIF2 ADCR", NULL, "AIF2 ADCR Stereo Mux" }, 1102 1103 { "AIF3 ADC", NULL, "AIF3 ADC Source Capture Route" }, 1104 1105 /* AIF "ADC" Mono/Stereo Mux Routes */ 1106 { "AIF1 AD0L Stereo Mux", "Stereo", "AIF1 AD0L Mixer" }, 1107 { "AIF1 AD0L Stereo Mux", "Reverse Stereo", "AIF1 AD0R Mixer" }, 1108 { "AIF1 AD0L Stereo Mux", "Sum Mono", "AIF1 AD0L Mixer" }, 1109 { "AIF1 AD0L Stereo Mux", "Sum Mono", "AIF1 AD0R Mixer" }, 1110 { "AIF1 AD0L Stereo Mux", "Mix Mono", "AIF1 AD0L Mixer" }, 1111 { "AIF1 AD0L Stereo Mux", "Mix Mono", "AIF1 AD0R Mixer" }, 1112 1113 { "AIF1 AD0R Stereo Mux", "Stereo", "AIF1 AD0R Mixer" }, 1114 { "AIF1 AD0R Stereo Mux", "Reverse Stereo", "AIF1 AD0L Mixer" }, 1115 { "AIF1 AD0R Stereo Mux", "Sum Mono", "AIF1 AD0L Mixer" }, 1116 { "AIF1 AD0R Stereo Mux", "Sum Mono", "AIF1 AD0R Mixer" }, 1117 { "AIF1 AD0R Stereo Mux", "Mix Mono", "AIF1 AD0L Mixer" }, 1118 { "AIF1 AD0R Stereo Mux", "Mix Mono", "AIF1 AD0R Mixer" }, 1119 1120 { "AIF2 ADCL Stereo Mux", "Stereo", "AIF2 ADCL Mixer" }, 1121 { "AIF2 ADCL Stereo Mux", "Reverse Stereo", "AIF2 ADCR Mixer" }, 1122 { "AIF2 ADCL Stereo Mux", "Sum Mono", "AIF2 ADCL Mixer" }, 1123 { "AIF2 ADCL Stereo Mux", "Sum Mono", "AIF2 ADCR Mixer" }, 1124 { "AIF2 ADCL Stereo Mux", "Mix Mono", "AIF2 ADCL Mixer" }, 1125 { "AIF2 ADCL Stereo Mux", "Mix Mono", "AIF2 ADCR Mixer" }, 1126 1127 { "AIF2 ADCR Stereo Mux", "Stereo", "AIF2 ADCR Mixer" }, 1128 { "AIF2 ADCR Stereo Mux", "Reverse Stereo", "AIF2 ADCL Mixer" }, 1129 { "AIF2 ADCR Stereo Mux", "Sum Mono", "AIF2 ADCL Mixer" }, 1130 { "AIF2 ADCR Stereo Mux", "Sum Mono", "AIF2 ADCR Mixer" }, 1131 { "AIF2 ADCR Stereo Mux", "Mix Mono", "AIF2 ADCL Mixer" }, 1132 { "AIF2 ADCR Stereo Mux", "Mix Mono", "AIF2 ADCR Mixer" }, 1133 1134 /* AIF "ADC" Output Mux Routes */ 1135 { "AIF3 ADC Source Capture Route", "AIF2 ADCL", "AIF2 ADCL Mixer" }, 1136 { "AIF3 ADC Source Capture Route", "AIF2 ADCR", "AIF2 ADCR Mixer" }, 1137 1138 /* AIF "ADC" Mixer Routes */ 1139 { "AIF1 AD0L Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0L Stereo Mux" }, 1140 { "AIF1 AD0L Mixer", "AIF2 Digital ADC Capture Switch", "AIF2 DACL Source" }, 1141 { "AIF1 AD0L Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCL" }, 1142 { "AIF1 AD0L Mixer", "AIF2 Inv Digital ADC Capture Switch", "AIF2 DACR Source" }, 1143 1144 { "AIF1 AD0R Mixer", "AIF1 Slot 0 Digital ADC Capture Switch", "AIF1 DA0R Stereo Mux" }, 1145 { "AIF1 AD0R Mixer", "AIF2 Digital ADC Capture Switch", "AIF2 DACR Source" }, 1146 { "AIF1 AD0R Mixer", "AIF1 Data Digital ADC Capture Switch", "ADCR" }, 1147 { "AIF1 AD0R Mixer", "AIF2 Inv Digital ADC Capture Switch", "AIF2 DACL Source" }, 1148 1149 { "AIF2 ADCL Mixer", "AIF2 ADC Mixer AIF1 DA0 Capture Switch", "AIF1 DA0L Stereo Mux" }, 1150 { "AIF2 ADCL Mixer", "AIF2 ADC Mixer AIF2 DAC Rev Capture Switch", "AIF2 DACR Source" }, 1151 { "AIF2 ADCL Mixer", "AIF2 ADC Mixer ADC Capture Switch", "ADCL" }, 1152 1153 { "AIF2 ADCR Mixer", "AIF2 ADC Mixer AIF1 DA0 Capture Switch", "AIF1 DA0R Stereo Mux" }, 1154 { "AIF2 ADCR Mixer", "AIF2 ADC Mixer AIF2 DAC Rev Capture Switch", "AIF2 DACL Source" }, 1155 { "AIF2 ADCR Mixer", "AIF2 ADC Mixer ADC Capture Switch", "ADCR" }, 1156 1157 /* AIF "DAC" Input Mux Routes */ 1158 { "AIF2 DACL Source", "AIF2", "AIF2 DACL Stereo Mux" }, 1159 { "AIF2 DACL Source", "AIF3+2", "AIF3 DAC" }, 1160 { "AIF2 DACL Source", "AIF2+3", "AIF2 DACL Stereo Mux" }, 1161 1162 { "AIF2 DACR Source", "AIF2", "AIF2 DACR Stereo Mux" }, 1163 { "AIF2 DACR Source", "AIF3+2", "AIF2 DACR Stereo Mux" }, 1164 { "AIF2 DACR Source", "AIF2+3", "AIF3 DAC" }, 1165 1166 /* AIF "DAC" Mono/Stereo Mux Routes */ 1167 { "AIF1 DA0L Stereo Mux", "Stereo", "AIF1 DA0L" }, 1168 { "AIF1 DA0L Stereo Mux", "Reverse Stereo", "AIF1 DA0R" }, 1169 { "AIF1 DA0L Stereo Mux", "Sum Mono", "AIF1 DA0L" }, 1170 { "AIF1 DA0L Stereo Mux", "Sum Mono", "AIF1 DA0R" }, 1171 { "AIF1 DA0L Stereo Mux", "Mix Mono", "AIF1 DA0L" }, 1172 { "AIF1 DA0L Stereo Mux", "Mix Mono", "AIF1 DA0R" }, 1173 1174 { "AIF1 DA0R Stereo Mux", "Stereo", "AIF1 DA0R" }, 1175 { "AIF1 DA0R Stereo Mux", "Reverse Stereo", "AIF1 DA0L" }, 1176 { "AIF1 DA0R Stereo Mux", "Sum Mono", "AIF1 DA0L" }, 1177 { "AIF1 DA0R Stereo Mux", "Sum Mono", "AIF1 DA0R" }, 1178 { "AIF1 DA0R Stereo Mux", "Mix Mono", "AIF1 DA0L" }, 1179 { "AIF1 DA0R Stereo Mux", "Mix Mono", "AIF1 DA0R" }, 1180 1181 { "AIF2 DACL Stereo Mux", "Stereo", "AIF2 DACL" }, 1182 { "AIF2 DACL Stereo Mux", "Reverse Stereo", "AIF2 DACR" }, 1183 { "AIF2 DACL Stereo Mux", "Sum Mono", "AIF2 DACL" }, 1184 { "AIF2 DACL Stereo Mux", "Sum Mono", "AIF2 DACR" }, 1185 { "AIF2 DACL Stereo Mux", "Mix Mono", "AIF2 DACL" }, 1186 { "AIF2 DACL Stereo Mux", "Mix Mono", "AIF2 DACR" }, 1187 1188 { "AIF2 DACR Stereo Mux", "Stereo", "AIF2 DACR" }, 1189 { "AIF2 DACR Stereo Mux", "Reverse Stereo", "AIF2 DACL" }, 1190 { "AIF2 DACR Stereo Mux", "Sum Mono", "AIF2 DACL" }, 1191 { "AIF2 DACR Stereo Mux", "Sum Mono", "AIF2 DACR" }, 1192 { "AIF2 DACR Stereo Mux", "Mix Mono", "AIF2 DACL" }, 1193 { "AIF2 DACR Stereo Mux", "Mix Mono", "AIF2 DACR" }, 1194 1195 /* DAC Output Routes */ 1196 { "DACL", NULL, "DACL Mixer" }, 1197 { "DACR", NULL, "DACR Mixer" }, 1198 1199 /* DAC Mixer Routes */ 1200 { "DACL Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0L Stereo Mux" }, 1201 { "DACL Mixer", "AIF2 Digital DAC Playback Switch", "AIF2 DACL Source" }, 1202 { "DACL Mixer", "ADC Digital DAC Playback Switch", "ADCL" }, 1203 1204 { "DACR Mixer", "AIF1 Slot 0 Digital DAC Playback Switch", "AIF1 DA0R Stereo Mux" }, 1205 { "DACR Mixer", "AIF2 Digital DAC Playback Switch", "AIF2 DACR Source" }, 1206 { "DACR Mixer", "ADC Digital DAC Playback Switch", "ADCR" }, 1207}; 1208 1209static const struct snd_soc_dapm_widget sun8i_codec_legacy_widgets[] = { 1210 /* Legacy ADC Inputs (connected to analog codec DAPM context) */ 1211 SND_SOC_DAPM_ADC("AIF1 Slot 0 Left ADC", NULL, SND_SOC_NOPM, 0, 0), 1212 SND_SOC_DAPM_ADC("AIF1 Slot 0 Right ADC", NULL, SND_SOC_NOPM, 0, 0), 1213 1214 /* Legacy DAC Outputs (connected to analog codec DAPM context) */ 1215 SND_SOC_DAPM_DAC("AIF1 Slot 0 Left", NULL, SND_SOC_NOPM, 0, 0), 1216 SND_SOC_DAPM_DAC("AIF1 Slot 0 Right", NULL, SND_SOC_NOPM, 0, 0), 1217}; 1218 1219static const struct snd_soc_dapm_route sun8i_codec_legacy_routes[] = { 1220 /* Legacy ADC Routes */ 1221 { "ADCL", NULL, "AIF1 Slot 0 Left ADC" }, 1222 { "ADCR", NULL, "AIF1 Slot 0 Right ADC" }, 1223 1224 /* Legacy DAC Routes */ 1225 { "AIF1 Slot 0 Left", NULL, "DACL" }, 1226 { "AIF1 Slot 0 Right", NULL, "DACR" }, 1227}; 1228 1229static int sun8i_codec_component_probe(struct snd_soc_component *component) 1230{ 1231 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); 1232 struct sun8i_codec *scodec = snd_soc_component_get_drvdata(component); 1233 int ret; 1234 1235 /* Add widgets for backward compatibility with old device trees. */ 1236 if (scodec->quirks->legacy_widgets) { 1237 ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_legacy_widgets, 1238 ARRAY_SIZE(sun8i_codec_legacy_widgets)); 1239 if (ret) 1240 return ret; 1241 1242 ret = snd_soc_dapm_add_routes(dapm, sun8i_codec_legacy_routes, 1243 ARRAY_SIZE(sun8i_codec_legacy_routes)); 1244 if (ret) 1245 return ret; 1246 } 1247 1248 /* 1249 * AIF1CLK and AIF2CLK share a pair of clock parents: PLL_AUDIO ("mod") 1250 * and MCLK (from the CPU DAI connected to AIF1). MCLK's parent is also 1251 * PLL_AUDIO, so using it adds no additional flexibility. Use PLL_AUDIO 1252 * directly to simplify the clock tree. 1253 */ 1254 regmap_update_bits(scodec->regmap, SUN8I_SYSCLK_CTL, 1255 SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK | 1256 SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK, 1257 SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL | 1258 SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL); 1259 1260 /* Use AIF1CLK as the SYSCLK parent since AIF1 is used most often. */ 1261 regmap_update_bits(scodec->regmap, SUN8I_SYSCLK_CTL, 1262 BIT(SUN8I_SYSCLK_CTL_SYSCLK_SRC), 1263 SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK); 1264 1265 /* Program the default sample rate. */ 1266 sun8i_codec_update_sample_rate(scodec); 1267 1268 return 0; 1269} 1270 1271static const struct snd_soc_component_driver sun8i_soc_component = { 1272 .controls = sun8i_codec_controls, 1273 .num_controls = ARRAY_SIZE(sun8i_codec_controls), 1274 .dapm_widgets = sun8i_codec_dapm_widgets, 1275 .num_dapm_widgets = ARRAY_SIZE(sun8i_codec_dapm_widgets), 1276 .dapm_routes = sun8i_codec_dapm_routes, 1277 .num_dapm_routes = ARRAY_SIZE(sun8i_codec_dapm_routes), 1278 .probe = sun8i_codec_component_probe, 1279 .idle_bias_on = 1, 1280 .endianness = 1, 1281 .non_legacy_dai_naming = 1, 1282}; 1283 1284static const struct regmap_config sun8i_codec_regmap_config = { 1285 .reg_bits = 32, 1286 .reg_stride = 4, 1287 .val_bits = 32, 1288 .max_register = SUN8I_DAC_MXR_SRC, 1289 1290 .cache_type = REGCACHE_FLAT, 1291}; 1292 1293static int sun8i_codec_probe(struct platform_device *pdev) 1294{ 1295 struct sun8i_codec *scodec; 1296 void __iomem *base; 1297 int ret; 1298 1299 scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL); 1300 if (!scodec) 1301 return -ENOMEM; 1302 1303 scodec->clk_module = devm_clk_get(&pdev->dev, "mod"); 1304 if (IS_ERR(scodec->clk_module)) { 1305 dev_err(&pdev->dev, "Failed to get the module clock\n"); 1306 return PTR_ERR(scodec->clk_module); 1307 } 1308 1309 base = devm_platform_ioremap_resource(pdev, 0); 1310 if (IS_ERR(base)) { 1311 dev_err(&pdev->dev, "Failed to map the registers\n"); 1312 return PTR_ERR(base); 1313 } 1314 1315 scodec->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "bus", base, 1316 &sun8i_codec_regmap_config); 1317 if (IS_ERR(scodec->regmap)) { 1318 dev_err(&pdev->dev, "Failed to create our regmap\n"); 1319 return PTR_ERR(scodec->regmap); 1320 } 1321 1322 scodec->quirks = of_device_get_match_data(&pdev->dev); 1323 1324 platform_set_drvdata(pdev, scodec); 1325 1326 pm_runtime_enable(&pdev->dev); 1327 if (!pm_runtime_enabled(&pdev->dev)) { 1328 ret = sun8i_codec_runtime_resume(&pdev->dev); 1329 if (ret) 1330 goto err_pm_disable; 1331 } 1332 1333 ret = devm_snd_soc_register_component(&pdev->dev, &sun8i_soc_component, 1334 sun8i_codec_dais, 1335 ARRAY_SIZE(sun8i_codec_dais)); 1336 if (ret) { 1337 dev_err(&pdev->dev, "Failed to register codec\n"); 1338 goto err_suspend; 1339 } 1340 1341 return ret; 1342 1343err_suspend: 1344 if (!pm_runtime_status_suspended(&pdev->dev)) 1345 sun8i_codec_runtime_suspend(&pdev->dev); 1346 1347err_pm_disable: 1348 pm_runtime_disable(&pdev->dev); 1349 1350 return ret; 1351} 1352 1353static int sun8i_codec_remove(struct platform_device *pdev) 1354{ 1355 pm_runtime_disable(&pdev->dev); 1356 if (!pm_runtime_status_suspended(&pdev->dev)) 1357 sun8i_codec_runtime_suspend(&pdev->dev); 1358 1359 return 0; 1360} 1361 1362static const struct sun8i_codec_quirks sun8i_a33_quirks = { 1363 .legacy_widgets = true, 1364 .lrck_inversion = true, 1365}; 1366 1367static const struct sun8i_codec_quirks sun50i_a64_quirks = { 1368}; 1369 1370static const struct of_device_id sun8i_codec_of_match[] = { 1371 { .compatible = "allwinner,sun8i-a33-codec", .data = &sun8i_a33_quirks }, 1372 { .compatible = "allwinner,sun50i-a64-codec", .data = &sun50i_a64_quirks }, 1373 {} 1374}; 1375MODULE_DEVICE_TABLE(of, sun8i_codec_of_match); 1376 1377static const struct dev_pm_ops sun8i_codec_pm_ops = { 1378 SET_RUNTIME_PM_OPS(sun8i_codec_runtime_suspend, 1379 sun8i_codec_runtime_resume, NULL) 1380}; 1381 1382static struct platform_driver sun8i_codec_driver = { 1383 .driver = { 1384 .name = "sun8i-codec", 1385 .of_match_table = sun8i_codec_of_match, 1386 .pm = &sun8i_codec_pm_ops, 1387 }, 1388 .probe = sun8i_codec_probe, 1389 .remove = sun8i_codec_remove, 1390}; 1391module_platform_driver(sun8i_codec_driver); 1392 1393MODULE_DESCRIPTION("Allwinner A33 (sun8i) codec driver"); 1394MODULE_AUTHOR("Mylène Josserand <mylene.josserand@free-electrons.com>"); 1395MODULE_LICENSE("GPL"); 1396MODULE_ALIAS("platform:sun8i-codec");