Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * This driver supports the digital controls for the internal codec
0004  * found in Allwinner's A33 SoCs.
0005  *
0006  * (C) Copyright 2010-2016
0007  * Reuuimlla Technology Co., Ltd. <www.reuuimllatech.com>
0008  * huangxin <huangxin@Reuuimllatech.com>
0009  * Mylène Josserand <mylene.josserand@free-electrons.com>
0010  */
0011 
0012 #include <linux/module.h>
0013 #include <linux/delay.h>
0014 #include <linux/clk.h>
0015 #include <linux/io.h>
0016 #include <linux/of_device.h>
0017 #include <linux/pm_runtime.h>
0018 #include <linux/regmap.h>
0019 #include <linux/log2.h>
0020 
0021 #include <sound/pcm_params.h>
0022 #include <sound/soc.h>
0023 #include <sound/soc-dapm.h>
0024 #include <sound/tlv.h>
0025 
0026 #define SUN8I_SYSCLK_CTL                0x00c
0027 #define SUN8I_SYSCLK_CTL_AIF1CLK_ENA            11
0028 #define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_PLL        (0x2 << 8)
0029 #define SUN8I_SYSCLK_CTL_AIF2CLK_ENA            7
0030 #define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_PLL        (0x2 << 4)
0031 #define SUN8I_SYSCLK_CTL_SYSCLK_ENA         3
0032 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC         0
0033 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF1CLK     (0x0 << 0)
0034 #define SUN8I_SYSCLK_CTL_SYSCLK_SRC_AIF2CLK     (0x1 << 0)
0035 #define SUN8I_MOD_CLK_ENA               0x010
0036 #define SUN8I_MOD_CLK_ENA_AIF1              15
0037 #define SUN8I_MOD_CLK_ENA_AIF2              14
0038 #define SUN8I_MOD_CLK_ENA_AIF3              13
0039 #define SUN8I_MOD_CLK_ENA_ADC               3
0040 #define SUN8I_MOD_CLK_ENA_DAC               2
0041 #define SUN8I_MOD_RST_CTL               0x014
0042 #define SUN8I_MOD_RST_CTL_AIF1              15
0043 #define SUN8I_MOD_RST_CTL_AIF2              14
0044 #define SUN8I_MOD_RST_CTL_AIF3              13
0045 #define SUN8I_MOD_RST_CTL_ADC               3
0046 #define SUN8I_MOD_RST_CTL_DAC               2
0047 #define SUN8I_SYS_SR_CTRL               0x018
0048 #define SUN8I_SYS_SR_CTRL_AIF1_FS           12
0049 #define SUN8I_SYS_SR_CTRL_AIF2_FS           8
0050 #define SUN8I_AIF_CLK_CTRL(n)               (0x040 * (1 + (n)))
0051 #define SUN8I_AIF_CLK_CTRL_MSTR_MOD         15
0052 #define SUN8I_AIF_CLK_CTRL_CLK_INV          13
0053 #define SUN8I_AIF_CLK_CTRL_BCLK_DIV         9
0054 #define SUN8I_AIF_CLK_CTRL_LRCK_DIV         6
0055 #define SUN8I_AIF_CLK_CTRL_WORD_SIZ         4
0056 #define SUN8I_AIF_CLK_CTRL_DATA_FMT         2
0057 #define SUN8I_AIF1_ADCDAT_CTRL              0x044
0058 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA        15
0059 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA        14
0060 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC        10
0061 #define SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC        8
0062 #define SUN8I_AIF1_DACDAT_CTRL              0x048
0063 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_ENA        15
0064 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_ENA        14
0065 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC        10
0066 #define SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC        8
0067 #define SUN8I_AIF1_MXR_SRC              0x04c
0068 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L    15
0069 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL    14
0070 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL        13
0071 #define SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR    12
0072 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R    11
0073 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR    10
0074 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR        9
0075 #define SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL    8
0076 #define SUN8I_AIF1_VOL_CTRL1                0x050
0077 #define SUN8I_AIF1_VOL_CTRL1_AD0L_VOL           8
0078 #define SUN8I_AIF1_VOL_CTRL1_AD0R_VOL           0
0079 #define SUN8I_AIF1_VOL_CTRL3                0x058
0080 #define SUN8I_AIF1_VOL_CTRL3_DA0L_VOL           8
0081 #define SUN8I_AIF1_VOL_CTRL3_DA0R_VOL           0
0082 #define SUN8I_AIF2_ADCDAT_CTRL              0x084
0083 #define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_ENA        15
0084 #define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_ENA        14
0085 #define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_SRC        10
0086 #define SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_SRC        8
0087 #define SUN8I_AIF2_DACDAT_CTRL              0x088
0088 #define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_ENA        15
0089 #define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_ENA        14
0090 #define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_SRC        10
0091 #define SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_SRC        8
0092 #define SUN8I_AIF2_MXR_SRC              0x08c
0093 #define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA0L    15
0094 #define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA1L    14
0095 #define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF2DACR    13
0096 #define SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_ADCL        12
0097 #define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA0R    11
0098 #define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA1R    10
0099 #define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF2DACL    9
0100 #define SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_ADCR        8
0101 #define SUN8I_AIF2_VOL_CTRL1                0x090
0102 #define SUN8I_AIF2_VOL_CTRL1_ADCL_VOL           8
0103 #define SUN8I_AIF2_VOL_CTRL1_ADCR_VOL           0
0104 #define SUN8I_AIF2_VOL_CTRL2                0x098
0105 #define SUN8I_AIF2_VOL_CTRL2_DACL_VOL           8
0106 #define SUN8I_AIF2_VOL_CTRL2_DACR_VOL           0
0107 #define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1       (0x0 << 0)
0108 #define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF2       (0x1 << 0)
0109 #define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF1CLK    (0x2 << 0)
0110 #define SUN8I_AIF3_PATH_CTRL                0x0cc
0111 #define SUN8I_AIF3_PATH_CTRL_AIF3_ADC_SRC       10
0112 #define SUN8I_AIF3_PATH_CTRL_AIF2_DAC_SRC       8
0113 #define SUN8I_AIF3_PATH_CTRL_AIF3_PINS_TRI      7
0114 #define SUN8I_ADC_DIG_CTRL              0x100
0115 #define SUN8I_ADC_DIG_CTRL_ENAD             15
0116 #define SUN8I_ADC_DIG_CTRL_ADOUT_DTS            2
0117 #define SUN8I_ADC_DIG_CTRL_ADOUT_DLY            1
0118 #define SUN8I_ADC_VOL_CTRL              0x104
0119 #define SUN8I_ADC_VOL_CTRL_ADCL_VOL         8
0120 #define SUN8I_ADC_VOL_CTRL_ADCR_VOL         0
0121 #define SUN8I_DAC_DIG_CTRL              0x120
0122 #define SUN8I_DAC_DIG_CTRL_ENDA             15
0123 #define SUN8I_DAC_VOL_CTRL              0x124
0124 #define SUN8I_DAC_VOL_CTRL_DACL_VOL         8
0125 #define SUN8I_DAC_VOL_CTRL_DACR_VOL         0
0126 #define SUN8I_DAC_MXR_SRC               0x130
0127 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L     15
0128 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L     14
0129 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL     13
0130 #define SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL     12
0131 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R     11
0132 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R     10
0133 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR     9
0134 #define SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR     8
0135 
0136 #define SUN8I_SYSCLK_CTL_AIF1CLK_SRC_MASK   GENMASK(9, 8)
0137 #define SUN8I_SYSCLK_CTL_AIF2CLK_SRC_MASK   GENMASK(5, 4)
0138 #define SUN8I_SYS_SR_CTRL_AIF1_FS_MASK      GENMASK(15, 12)
0139 #define SUN8I_SYS_SR_CTRL_AIF2_FS_MASK      GENMASK(11, 8)
0140 #define SUN8I_AIF_CLK_CTRL_CLK_INV_MASK     GENMASK(14, 13)
0141 #define SUN8I_AIF_CLK_CTRL_BCLK_DIV_MASK    GENMASK(12, 9)
0142 #define SUN8I_AIF_CLK_CTRL_LRCK_DIV_MASK    GENMASK(8, 6)
0143 #define SUN8I_AIF_CLK_CTRL_WORD_SIZ_MASK    GENMASK(5, 4)
0144 #define SUN8I_AIF_CLK_CTRL_DATA_FMT_MASK    GENMASK(3, 2)
0145 #define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_MASK   GENMASK(1, 0)
0146 
0147 #define SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE 48000
0148 
0149 #define SUN8I_CODEC_PCM_FORMATS (SNDRV_PCM_FMTBIT_S8     |\
0150                  SNDRV_PCM_FMTBIT_S16_LE |\
0151                  SNDRV_PCM_FMTBIT_S20_LE |\
0152                  SNDRV_PCM_FMTBIT_S24_LE |\
0153                  SNDRV_PCM_FMTBIT_S20_3LE|\
0154                  SNDRV_PCM_FMTBIT_S24_3LE)
0155 
0156 #define SUN8I_CODEC_PCM_RATES   (SNDRV_PCM_RATE_8000_48000|\
0157                  SNDRV_PCM_RATE_88200     |\
0158                  SNDRV_PCM_RATE_96000     |\
0159                  SNDRV_PCM_RATE_176400    |\
0160                  SNDRV_PCM_RATE_192000    |\
0161                  SNDRV_PCM_RATE_KNOT)
0162 
0163 enum {
0164     SUN8I_CODEC_AIF1,
0165     SUN8I_CODEC_AIF2,
0166     SUN8I_CODEC_AIF3,
0167     SUN8I_CODEC_NAIFS
0168 };
0169 
0170 struct sun8i_codec_aif {
0171     unsigned int    lrck_div_order;
0172     unsigned int    sample_rate;
0173     unsigned int    slots;
0174     unsigned int    slot_width;
0175     unsigned int    active_streams  : 2;
0176     unsigned int    open_streams    : 2;
0177 };
0178 
0179 struct sun8i_codec_quirks {
0180     bool legacy_widgets : 1;
0181     bool lrck_inversion : 1;
0182 };
0183 
0184 struct sun8i_codec {
0185     struct regmap           *regmap;
0186     struct clk          *clk_module;
0187     const struct sun8i_codec_quirks *quirks;
0188     struct sun8i_codec_aif      aifs[SUN8I_CODEC_NAIFS];
0189     unsigned int            sysclk_rate;
0190     int             sysclk_refcnt;
0191 };
0192 
0193 static struct snd_soc_dai_driver sun8i_codec_dais[];
0194 
0195 static int sun8i_codec_runtime_resume(struct device *dev)
0196 {
0197     struct sun8i_codec *scodec = dev_get_drvdata(dev);
0198     int ret;
0199 
0200     regcache_cache_only(scodec->regmap, false);
0201 
0202     ret = regcache_sync(scodec->regmap);
0203     if (ret) {
0204         dev_err(dev, "Failed to sync regmap cache\n");
0205         return ret;
0206     }
0207 
0208     return 0;
0209 }
0210 
0211 static int sun8i_codec_runtime_suspend(struct device *dev)
0212 {
0213     struct sun8i_codec *scodec = dev_get_drvdata(dev);
0214 
0215     regcache_cache_only(scodec->regmap, true);
0216     regcache_mark_dirty(scodec->regmap);
0217 
0218     return 0;
0219 }
0220 
0221 static int sun8i_codec_get_hw_rate(unsigned int sample_rate)
0222 {
0223     switch (sample_rate) {
0224     case 7350:
0225     case 8000:
0226         return 0x0;
0227     case 11025:
0228         return 0x1;
0229     case 12000:
0230         return 0x2;
0231     case 14700:
0232     case 16000:
0233         return 0x3;
0234     case 22050:
0235         return 0x4;
0236     case 24000:
0237         return 0x5;
0238     case 29400:
0239     case 32000:
0240         return 0x6;
0241     case 44100:
0242         return 0x7;
0243     case 48000:
0244         return 0x8;
0245     case 88200:
0246     case 96000:
0247         return 0x9;
0248     case 176400:
0249     case 192000:
0250         return 0xa;
0251     default:
0252         return -EINVAL;
0253     }
0254 }
0255 
0256 static int sun8i_codec_update_sample_rate(struct sun8i_codec *scodec)
0257 {
0258     unsigned int max_rate = 0;
0259     int hw_rate, i;
0260 
0261     for (i = SUN8I_CODEC_AIF1; i < SUN8I_CODEC_NAIFS; ++i) {
0262         struct sun8i_codec_aif *aif = &scodec->aifs[i];
0263 
0264         if (aif->active_streams)
0265             max_rate = max(max_rate, aif->sample_rate);
0266     }
0267 
0268     /* Set the sample rate for ADC->DAC passthrough when no AIF is active. */
0269     if (!max_rate)
0270         max_rate = SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE;
0271 
0272     hw_rate = sun8i_codec_get_hw_rate(max_rate);
0273     if (hw_rate < 0)
0274         return hw_rate;
0275 
0276     regmap_update_bits(scodec->regmap, SUN8I_SYS_SR_CTRL,
0277                SUN8I_SYS_SR_CTRL_AIF1_FS_MASK,
0278                hw_rate << SUN8I_SYS_SR_CTRL_AIF1_FS);
0279 
0280     return 0;
0281 }
0282 
0283 static int sun8i_codec_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
0284 {
0285     struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
0286     u32 dsp_format, format, invert, value;
0287 
0288     /* clock masters */
0289     switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
0290     case SND_SOC_DAIFMT_CBC_CFC: /* Codec slave, DAI master */
0291         value = 0x1;
0292         break;
0293     case SND_SOC_DAIFMT_CBP_CFP: /* Codec Master, DAI slave */
0294         value = 0x0;
0295         break;
0296     default:
0297         return -EINVAL;
0298     }
0299 
0300     if (dai->id == SUN8I_CODEC_AIF3) {
0301         /* AIF3 only supports master mode. */
0302         if (value)
0303             return -EINVAL;
0304 
0305         /* Use the AIF2 BCLK and LRCK for AIF3. */
0306         regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),
0307                    SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_MASK,
0308                    SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_AIF2);
0309     } else {
0310         regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),
0311                    BIT(SUN8I_AIF_CLK_CTRL_MSTR_MOD),
0312                    value << SUN8I_AIF_CLK_CTRL_MSTR_MOD);
0313     }
0314 
0315     /* DAI format */
0316     switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
0317     case SND_SOC_DAIFMT_I2S:
0318         format = 0x0;
0319         break;
0320     case SND_SOC_DAIFMT_LEFT_J:
0321         format = 0x1;
0322         break;
0323     case SND_SOC_DAIFMT_RIGHT_J:
0324         format = 0x2;
0325         break;
0326     case SND_SOC_DAIFMT_DSP_A:
0327         format = 0x3;
0328         dsp_format = 0x0; /* Set LRCK_INV to 0 */
0329         break;
0330     case SND_SOC_DAIFMT_DSP_B:
0331         format = 0x3;
0332         dsp_format = 0x1; /* Set LRCK_INV to 1 */
0333         break;
0334     default:
0335         return -EINVAL;
0336     }
0337 
0338     if (dai->id == SUN8I_CODEC_AIF3) {
0339         /* AIF3 only supports DSP mode. */
0340         if (format != 3)
0341             return -EINVAL;
0342     } else {
0343         regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),
0344                    SUN8I_AIF_CLK_CTRL_DATA_FMT_MASK,
0345                    format << SUN8I_AIF_CLK_CTRL_DATA_FMT);
0346     }
0347 
0348     /* clock inversion */
0349     switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
0350     case SND_SOC_DAIFMT_NB_NF: /* Normal */
0351         invert = 0x0;
0352         break;
0353     case SND_SOC_DAIFMT_NB_IF: /* Inverted LRCK */
0354         invert = 0x1;
0355         break;
0356     case SND_SOC_DAIFMT_IB_NF: /* Inverted BCLK */
0357         invert = 0x2;
0358         break;
0359     case SND_SOC_DAIFMT_IB_IF: /* Both inverted */
0360         invert = 0x3;
0361         break;
0362     default:
0363         return -EINVAL;
0364     }
0365 
0366     if (format == 0x3) {
0367         /* Inverted LRCK is not available in DSP mode. */
0368         if (invert & BIT(0))
0369             return -EINVAL;
0370 
0371         /* Instead, the bit selects between DSP A/B formats. */
0372         invert |= dsp_format;
0373     } else {
0374         /*
0375          * It appears that the DAI and the codec in the A33 SoC don't
0376          * share the same polarity for the LRCK signal when they mean
0377          * 'normal' and 'inverted' in the datasheet.
0378          *
0379          * Since the DAI here is our regular i2s driver that have been
0380          * tested with way more codecs than just this one, it means
0381          * that the codec probably gets it backward, and we have to
0382          * invert the value here.
0383          */
0384         invert ^= scodec->quirks->lrck_inversion;
0385     }
0386 
0387     regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),
0388                SUN8I_AIF_CLK_CTRL_CLK_INV_MASK,
0389                invert << SUN8I_AIF_CLK_CTRL_CLK_INV);
0390 
0391     return 0;
0392 }
0393 
0394 static int sun8i_codec_set_tdm_slot(struct snd_soc_dai *dai,
0395                     unsigned int tx_mask, unsigned int rx_mask,
0396                     int slots, int slot_width)
0397 {
0398     struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
0399     struct sun8i_codec_aif *aif = &scodec->aifs[dai->id];
0400 
0401     if (slot_width && !is_power_of_2(slot_width))
0402         return -EINVAL;
0403 
0404     aif->slots = slots;
0405     aif->slot_width = slot_width;
0406 
0407     return 0;
0408 }
0409 
0410 static const unsigned int sun8i_codec_rates[] = {
0411       7350,   8000,  11025,  12000,  14700,  16000,  22050,  24000,
0412      29400,  32000,  44100,  48000,  88200,  96000, 176400, 192000,
0413 };
0414 
0415 static const struct snd_pcm_hw_constraint_list sun8i_codec_all_rates = {
0416     .list   = sun8i_codec_rates,
0417     .count  = ARRAY_SIZE(sun8i_codec_rates),
0418 };
0419 
0420 static const struct snd_pcm_hw_constraint_list sun8i_codec_22M_rates = {
0421     .list   = sun8i_codec_rates,
0422     .count  = ARRAY_SIZE(sun8i_codec_rates),
0423     .mask   = 0x5555,
0424 };
0425 
0426 static const struct snd_pcm_hw_constraint_list sun8i_codec_24M_rates = {
0427     .list   = sun8i_codec_rates,
0428     .count  = ARRAY_SIZE(sun8i_codec_rates),
0429     .mask   = 0xaaaa,
0430 };
0431 
0432 static int sun8i_codec_startup(struct snd_pcm_substream *substream,
0433                    struct snd_soc_dai *dai)
0434 {
0435     struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
0436     const struct snd_pcm_hw_constraint_list *list;
0437 
0438     /* hw_constraints is not relevant for codec2codec DAIs. */
0439     if (dai->id != SUN8I_CODEC_AIF1)
0440         return 0;
0441 
0442     if (!scodec->sysclk_refcnt)
0443         list = &sun8i_codec_all_rates;
0444     else if (scodec->sysclk_rate == 22579200)
0445         list = &sun8i_codec_22M_rates;
0446     else if (scodec->sysclk_rate == 24576000)
0447         list = &sun8i_codec_24M_rates;
0448     else
0449         return -EINVAL;
0450 
0451     return snd_pcm_hw_constraint_list(substream->runtime, 0,
0452                       SNDRV_PCM_HW_PARAM_RATE, list);
0453 }
0454 
0455 struct sun8i_codec_clk_div {
0456     u8  div;
0457     u8  val;
0458 };
0459 
0460 static const struct sun8i_codec_clk_div sun8i_codec_bclk_div[] = {
0461     { .div = 1, .val = 0 },
0462     { .div = 2, .val = 1 },
0463     { .div = 4, .val = 2 },
0464     { .div = 6, .val = 3 },
0465     { .div = 8, .val = 4 },
0466     { .div = 12,    .val = 5 },
0467     { .div = 16,    .val = 6 },
0468     { .div = 24,    .val = 7 },
0469     { .div = 32,    .val = 8 },
0470     { .div = 48,    .val = 9 },
0471     { .div = 64,    .val = 10 },
0472     { .div = 96,    .val = 11 },
0473     { .div = 128,   .val = 12 },
0474     { .div = 192,   .val = 13 },
0475 };
0476 
0477 static int sun8i_codec_get_bclk_div(unsigned int sysclk_rate,
0478                     unsigned int lrck_div_order,
0479                     unsigned int sample_rate)
0480 {
0481     unsigned int div = sysclk_rate / sample_rate >> lrck_div_order;
0482     int i;
0483 
0484     for (i = 0; i < ARRAY_SIZE(sun8i_codec_bclk_div); i++) {
0485         const struct sun8i_codec_clk_div *bdiv = &sun8i_codec_bclk_div[i];
0486 
0487         if (bdiv->div == div)
0488             return bdiv->val;
0489     }
0490 
0491     return -EINVAL;
0492 }
0493 
0494 static int sun8i_codec_get_lrck_div_order(unsigned int slots,
0495                       unsigned int slot_width)
0496 {
0497     unsigned int div = slots * slot_width;
0498 
0499     if (div < 16 || div > 256)
0500         return -EINVAL;
0501 
0502     return order_base_2(div);
0503 }
0504 
0505 static unsigned int sun8i_codec_get_sysclk_rate(unsigned int sample_rate)
0506 {
0507     return (sample_rate % 4000) ? 22579200 : 24576000;
0508 }
0509 
0510 static int sun8i_codec_hw_params(struct snd_pcm_substream *substream,
0511                  struct snd_pcm_hw_params *params,
0512                  struct snd_soc_dai *dai)
0513 {
0514     struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
0515     struct sun8i_codec_aif *aif = &scodec->aifs[dai->id];
0516     unsigned int sample_rate = params_rate(params);
0517     unsigned int slots = aif->slots ?: params_channels(params);
0518     unsigned int slot_width = aif->slot_width ?: params_width(params);
0519     unsigned int sysclk_rate = sun8i_codec_get_sysclk_rate(sample_rate);
0520     int bclk_div, lrck_div_order, ret, word_size;
0521     u32 clk_reg;
0522 
0523     /* word size */
0524     switch (params_width(params)) {
0525     case 8:
0526         word_size = 0x0;
0527         break;
0528     case 16:
0529         word_size = 0x1;
0530         break;
0531     case 20:
0532         word_size = 0x2;
0533         break;
0534     case 24:
0535         word_size = 0x3;
0536         break;
0537     default:
0538         return -EINVAL;
0539     }
0540 
0541     regmap_update_bits(scodec->regmap, SUN8I_AIF_CLK_CTRL(dai->id),
0542                SUN8I_AIF_CLK_CTRL_WORD_SIZ_MASK,
0543                word_size << SUN8I_AIF_CLK_CTRL_WORD_SIZ);
0544 
0545     /* LRCK divider (BCLK/LRCK ratio) */
0546     lrck_div_order = sun8i_codec_get_lrck_div_order(slots, slot_width);
0547     if (lrck_div_order < 0)
0548         return lrck_div_order;
0549 
0550     if (dai->id == SUN8I_CODEC_AIF2 || dai->id == SUN8I_CODEC_AIF3) {
0551         /* AIF2 and AIF3 share AIF2's BCLK and LRCK generation circuitry. */
0552         int partner = (SUN8I_CODEC_AIF2 + SUN8I_CODEC_AIF3) - dai->id;
0553         const struct sun8i_codec_aif *partner_aif = &scodec->aifs[partner];
0554         const char *partner_name = sun8i_codec_dais[partner].name;
0555 
0556         if (partner_aif->open_streams &&
0557             (lrck_div_order != partner_aif->lrck_div_order ||
0558              sample_rate != partner_aif->sample_rate)) {
0559             dev_err(dai->dev,
0560                 "%s sample and bit rates must match %s when both are used\n",
0561                 dai->name, partner_name);
0562             return -EBUSY;
0563         }
0564 
0565         clk_reg = SUN8I_AIF_CLK_CTRL(SUN8I_CODEC_AIF2);
0566     } else {
0567         clk_reg = SUN8I_AIF_CLK_CTRL(dai->id);
0568     }
0569 
0570     regmap_update_bits(scodec->regmap, clk_reg,
0571                SUN8I_AIF_CLK_CTRL_LRCK_DIV_MASK,
0572                (lrck_div_order - 4) << SUN8I_AIF_CLK_CTRL_LRCK_DIV);
0573 
0574     /* BCLK divider (SYSCLK/BCLK ratio) */
0575     bclk_div = sun8i_codec_get_bclk_div(sysclk_rate, lrck_div_order, sample_rate);
0576     if (bclk_div < 0)
0577         return bclk_div;
0578 
0579     regmap_update_bits(scodec->regmap, clk_reg,
0580                SUN8I_AIF_CLK_CTRL_BCLK_DIV_MASK,
0581                bclk_div << SUN8I_AIF_CLK_CTRL_BCLK_DIV);
0582 
0583     /*
0584      * SYSCLK rate
0585      *
0586      * Clock rate protection is reference counted; but hw_params may be
0587      * called many times per substream, without matching calls to hw_free.
0588      * Protect the clock rate once per AIF, on the first hw_params call
0589      * for the first substream. clk_set_rate() will allow clock rate
0590      * changes on subsequent calls if only one AIF has open streams.
0591      */
0592     ret = (aif->open_streams ? clk_set_rate : clk_set_rate_exclusive)(scodec->clk_module,
0593                                       sysclk_rate);
0594     if (ret == -EBUSY)
0595         dev_err(dai->dev,
0596             "%s sample rate (%u Hz) conflicts with other audio streams\n",
0597             dai->name, sample_rate);
0598     if (ret < 0)
0599         return ret;
0600 
0601     if (!aif->open_streams)
0602         scodec->sysclk_refcnt++;
0603     scodec->sysclk_rate = sysclk_rate;
0604 
0605     aif->lrck_div_order = lrck_div_order;
0606     aif->sample_rate = sample_rate;
0607     aif->open_streams |= BIT(substream->stream);
0608 
0609     return sun8i_codec_update_sample_rate(scodec);
0610 }
0611 
0612 static int sun8i_codec_hw_free(struct snd_pcm_substream *substream,
0613                    struct snd_soc_dai *dai)
0614 {
0615     struct sun8i_codec *scodec = snd_soc_dai_get_drvdata(dai);
0616     struct sun8i_codec_aif *aif = &scodec->aifs[dai->id];
0617 
0618     /* Drop references when the last substream for the AIF is freed. */
0619     if (aif->open_streams != BIT(substream->stream))
0620         goto done;
0621 
0622     clk_rate_exclusive_put(scodec->clk_module);
0623     scodec->sysclk_refcnt--;
0624     aif->lrck_div_order = 0;
0625     aif->sample_rate = 0;
0626 
0627 done:
0628     aif->open_streams &= ~BIT(substream->stream);
0629     return 0;
0630 }
0631 
0632 static const struct snd_soc_dai_ops sun8i_codec_dai_ops = {
0633     .set_fmt    = sun8i_codec_set_fmt,
0634     .set_tdm_slot   = sun8i_codec_set_tdm_slot,
0635     .startup    = sun8i_codec_startup,
0636     .hw_params  = sun8i_codec_hw_params,
0637     .hw_free    = sun8i_codec_hw_free,
0638 };
0639 
0640 static struct snd_soc_dai_driver sun8i_codec_dais[] = {
0641     {
0642         .name   = "sun8i-codec-aif1",
0643         .id = SUN8I_CODEC_AIF1,
0644         .ops    = &sun8i_codec_dai_ops,
0645         /* capture capabilities */
0646         .capture = {
0647             .stream_name    = "AIF1 Capture",
0648             .channels_min   = 1,
0649             .channels_max   = 2,
0650             .rates      = SUN8I_CODEC_PCM_RATES,
0651             .formats    = SUN8I_CODEC_PCM_FORMATS,
0652             .sig_bits   = 24,
0653         },
0654         /* playback capabilities */
0655         .playback = {
0656             .stream_name    = "AIF1 Playback",
0657             .channels_min   = 1,
0658             .channels_max   = 2,
0659             .rates      = SUN8I_CODEC_PCM_RATES,
0660             .formats    = SUN8I_CODEC_PCM_FORMATS,
0661         },
0662         .symmetric_rate     = true,
0663         .symmetric_channels = true,
0664         .symmetric_sample_bits  = true,
0665     },
0666     {
0667         .name   = "sun8i-codec-aif2",
0668         .id = SUN8I_CODEC_AIF2,
0669         .ops    = &sun8i_codec_dai_ops,
0670         /* capture capabilities */
0671         .capture = {
0672             .stream_name    = "AIF2 Capture",
0673             .channels_min   = 1,
0674             .channels_max   = 2,
0675             .rates      = SUN8I_CODEC_PCM_RATES,
0676             .formats    = SUN8I_CODEC_PCM_FORMATS,
0677             .sig_bits   = 24,
0678         },
0679         /* playback capabilities */
0680         .playback = {
0681             .stream_name    = "AIF2 Playback",
0682             .channels_min   = 1,
0683             .channels_max   = 2,
0684             .rates      = SUN8I_CODEC_PCM_RATES,
0685             .formats    = SUN8I_CODEC_PCM_FORMATS,
0686         },
0687         .symmetric_rate     = true,
0688         .symmetric_channels = true,
0689         .symmetric_sample_bits  = true,
0690     },
0691     {
0692         .name   = "sun8i-codec-aif3",
0693         .id = SUN8I_CODEC_AIF3,
0694         .ops    = &sun8i_codec_dai_ops,
0695         /* capture capabilities */
0696         .capture = {
0697             .stream_name    = "AIF3 Capture",
0698             .channels_min   = 1,
0699             .channels_max   = 1,
0700             .rates      = SUN8I_CODEC_PCM_RATES,
0701             .formats    = SUN8I_CODEC_PCM_FORMATS,
0702             .sig_bits   = 24,
0703         },
0704         /* playback capabilities */
0705         .playback = {
0706             .stream_name    = "AIF3 Playback",
0707             .channels_min   = 1,
0708             .channels_max   = 1,
0709             .rates      = SUN8I_CODEC_PCM_RATES,
0710             .formats    = SUN8I_CODEC_PCM_FORMATS,
0711         },
0712         .symmetric_rate     = true,
0713         .symmetric_channels = true,
0714         .symmetric_sample_bits  = true,
0715     },
0716 };
0717 
0718 static const DECLARE_TLV_DB_SCALE(sun8i_codec_vol_scale, -12000, 75, 1);
0719 
0720 static const struct snd_kcontrol_new sun8i_codec_controls[] = {
0721     SOC_DOUBLE_TLV("AIF1 AD0 Capture Volume",
0722                SUN8I_AIF1_VOL_CTRL1,
0723                SUN8I_AIF1_VOL_CTRL1_AD0L_VOL,
0724                SUN8I_AIF1_VOL_CTRL1_AD0R_VOL,
0725                0xc0, 0, sun8i_codec_vol_scale),
0726     SOC_DOUBLE_TLV("AIF1 DA0 Playback Volume",
0727                SUN8I_AIF1_VOL_CTRL3,
0728                SUN8I_AIF1_VOL_CTRL3_DA0L_VOL,
0729                SUN8I_AIF1_VOL_CTRL3_DA0R_VOL,
0730                0xc0, 0, sun8i_codec_vol_scale),
0731     SOC_DOUBLE_TLV("AIF2 ADC Capture Volume",
0732                SUN8I_AIF2_VOL_CTRL1,
0733                SUN8I_AIF2_VOL_CTRL1_ADCL_VOL,
0734                SUN8I_AIF2_VOL_CTRL1_ADCR_VOL,
0735                0xc0, 0, sun8i_codec_vol_scale),
0736     SOC_DOUBLE_TLV("AIF2 DAC Playback Volume",
0737                SUN8I_AIF2_VOL_CTRL2,
0738                SUN8I_AIF2_VOL_CTRL2_DACL_VOL,
0739                SUN8I_AIF2_VOL_CTRL2_DACR_VOL,
0740                0xc0, 0, sun8i_codec_vol_scale),
0741     SOC_DOUBLE_TLV("ADC Capture Volume",
0742                SUN8I_ADC_VOL_CTRL,
0743                SUN8I_ADC_VOL_CTRL_ADCL_VOL,
0744                SUN8I_ADC_VOL_CTRL_ADCR_VOL,
0745                0xc0, 0, sun8i_codec_vol_scale),
0746     SOC_DOUBLE_TLV("DAC Playback Volume",
0747                SUN8I_DAC_VOL_CTRL,
0748                SUN8I_DAC_VOL_CTRL_DACL_VOL,
0749                SUN8I_DAC_VOL_CTRL_DACR_VOL,
0750                0xc0, 0, sun8i_codec_vol_scale),
0751 };
0752 
0753 static int sun8i_codec_aif_event(struct snd_soc_dapm_widget *w,
0754                  struct snd_kcontrol *kcontrol, int event)
0755 {
0756     struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
0757     struct sun8i_codec *scodec = snd_soc_component_get_drvdata(component);
0758     struct sun8i_codec_aif *aif = &scodec->aifs[w->sname[3] - '1'];
0759     int stream = w->id == snd_soc_dapm_aif_out;
0760 
0761     if (SND_SOC_DAPM_EVENT_ON(event))
0762         aif->active_streams |= BIT(stream);
0763     else
0764         aif->active_streams &= ~BIT(stream);
0765 
0766     return sun8i_codec_update_sample_rate(scodec);
0767 }
0768 
0769 static const char *const sun8i_aif_stereo_mux_enum_values[] = {
0770     "Stereo", "Reverse Stereo", "Sum Mono", "Mix Mono"
0771 };
0772 
0773 static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_ad0_stereo_mux_enum,
0774                 SUN8I_AIF1_ADCDAT_CTRL,
0775                 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_SRC,
0776                 SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_SRC,
0777                 sun8i_aif_stereo_mux_enum_values);
0778 
0779 static const struct snd_kcontrol_new sun8i_aif1_ad0_stereo_mux_control =
0780     SOC_DAPM_ENUM("AIF1 AD0 Stereo Capture Route",
0781               sun8i_aif1_ad0_stereo_mux_enum);
0782 
0783 static SOC_ENUM_DOUBLE_DECL(sun8i_aif2_adc_stereo_mux_enum,
0784                 SUN8I_AIF2_ADCDAT_CTRL,
0785                 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_SRC,
0786                 SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_SRC,
0787                 sun8i_aif_stereo_mux_enum_values);
0788 
0789 static const struct snd_kcontrol_new sun8i_aif2_adc_stereo_mux_control =
0790     SOC_DAPM_ENUM("AIF2 ADC Stereo Capture Route",
0791               sun8i_aif2_adc_stereo_mux_enum);
0792 
0793 static const char *const sun8i_aif3_adc_mux_enum_values[] = {
0794     "None", "AIF2 ADCL", "AIF2 ADCR"
0795 };
0796 
0797 static SOC_ENUM_SINGLE_DECL(sun8i_aif3_adc_mux_enum,
0798                 SUN8I_AIF3_PATH_CTRL,
0799                 SUN8I_AIF3_PATH_CTRL_AIF3_ADC_SRC,
0800                 sun8i_aif3_adc_mux_enum_values);
0801 
0802 static const struct snd_kcontrol_new sun8i_aif3_adc_mux_control =
0803     SOC_DAPM_ENUM("AIF3 ADC Source Capture Route",
0804               sun8i_aif3_adc_mux_enum);
0805 
0806 static const struct snd_kcontrol_new sun8i_aif1_ad0_mixer_controls[] = {
0807     SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital ADC Capture Switch",
0808             SUN8I_AIF1_MXR_SRC,
0809             SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF1DA0L,
0810             SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF1DA0R, 1, 0),
0811     SOC_DAPM_DOUBLE("AIF2 Digital ADC Capture Switch",
0812             SUN8I_AIF1_MXR_SRC,
0813             SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACL,
0814             SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACR, 1, 0),
0815     SOC_DAPM_DOUBLE("AIF1 Data Digital ADC Capture Switch",
0816             SUN8I_AIF1_MXR_SRC,
0817             SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_ADCL,
0818             SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_ADCR, 1, 0),
0819     SOC_DAPM_DOUBLE("AIF2 Inv Digital ADC Capture Switch",
0820             SUN8I_AIF1_MXR_SRC,
0821             SUN8I_AIF1_MXR_SRC_AD0L_MXR_SRC_AIF2DACR,
0822             SUN8I_AIF1_MXR_SRC_AD0R_MXR_SRC_AIF2DACL, 1, 0),
0823 };
0824 
0825 static const struct snd_kcontrol_new sun8i_aif2_adc_mixer_controls[] = {
0826     SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF1 DA0 Capture Switch",
0827             SUN8I_AIF2_MXR_SRC,
0828             SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA0L,
0829             SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA0R, 1, 0),
0830     SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF1 DA1 Capture Switch",
0831             SUN8I_AIF2_MXR_SRC,
0832             SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF1DA1L,
0833             SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF1DA1R, 1, 0),
0834     SOC_DAPM_DOUBLE("AIF2 ADC Mixer AIF2 DAC Rev Capture Switch",
0835             SUN8I_AIF2_MXR_SRC,
0836             SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_AIF2DACR,
0837             SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_AIF2DACL, 1, 0),
0838     SOC_DAPM_DOUBLE("AIF2 ADC Mixer ADC Capture Switch",
0839             SUN8I_AIF2_MXR_SRC,
0840             SUN8I_AIF2_MXR_SRC_ADCL_MXR_SRC_ADCL,
0841             SUN8I_AIF2_MXR_SRC_ADCR_MXR_SRC_ADCR, 1, 0),
0842 };
0843 
0844 static const char *const sun8i_aif2_dac_mux_enum_values[] = {
0845     "AIF2", "AIF3+2", "AIF2+3"
0846 };
0847 
0848 static SOC_ENUM_SINGLE_DECL(sun8i_aif2_dac_mux_enum,
0849                 SUN8I_AIF3_PATH_CTRL,
0850                 SUN8I_AIF3_PATH_CTRL_AIF2_DAC_SRC,
0851                 sun8i_aif2_dac_mux_enum_values);
0852 
0853 static const struct snd_kcontrol_new sun8i_aif2_dac_mux_control =
0854     SOC_DAPM_ENUM("AIF2 DAC Source Playback Route",
0855               sun8i_aif2_dac_mux_enum);
0856 
0857 static SOC_ENUM_DOUBLE_DECL(sun8i_aif1_da0_stereo_mux_enum,
0858                 SUN8I_AIF1_DACDAT_CTRL,
0859                 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0L_SRC,
0860                 SUN8I_AIF1_DACDAT_CTRL_AIF1_DA0R_SRC,
0861                 sun8i_aif_stereo_mux_enum_values);
0862 
0863 static const struct snd_kcontrol_new sun8i_aif1_da0_stereo_mux_control =
0864     SOC_DAPM_ENUM("AIF1 DA0 Stereo Playback Route",
0865               sun8i_aif1_da0_stereo_mux_enum);
0866 
0867 static SOC_ENUM_DOUBLE_DECL(sun8i_aif2_dac_stereo_mux_enum,
0868                 SUN8I_AIF2_DACDAT_CTRL,
0869                 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACL_SRC,
0870                 SUN8I_AIF2_DACDAT_CTRL_AIF2_DACR_SRC,
0871                 sun8i_aif_stereo_mux_enum_values);
0872 
0873 static const struct snd_kcontrol_new sun8i_aif2_dac_stereo_mux_control =
0874     SOC_DAPM_ENUM("AIF2 DAC Stereo Playback Route",
0875               sun8i_aif2_dac_stereo_mux_enum);
0876 
0877 static const struct snd_kcontrol_new sun8i_dac_mixer_controls[] = {
0878     SOC_DAPM_DOUBLE("AIF1 Slot 0 Digital DAC Playback Switch",
0879             SUN8I_DAC_MXR_SRC,
0880             SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA0L,
0881             SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA0R, 1, 0),
0882     SOC_DAPM_DOUBLE("AIF1 Slot 1 Digital DAC Playback Switch",
0883             SUN8I_DAC_MXR_SRC,
0884             SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF1DA1L,
0885             SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF1DA1R, 1, 0),
0886     SOC_DAPM_DOUBLE("AIF2 Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC,
0887             SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_AIF2DACL,
0888             SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_AIF2DACR, 1, 0),
0889     SOC_DAPM_DOUBLE("ADC Digital DAC Playback Switch", SUN8I_DAC_MXR_SRC,
0890             SUN8I_DAC_MXR_SRC_DACL_MXR_SRC_ADCL,
0891             SUN8I_DAC_MXR_SRC_DACR_MXR_SRC_ADCR, 1, 0),
0892 };
0893 
0894 static const struct snd_soc_dapm_widget sun8i_codec_dapm_widgets[] = {
0895     /* System Clocks */
0896     SND_SOC_DAPM_CLOCK_SUPPLY("mod"),
0897 
0898     SND_SOC_DAPM_SUPPLY("AIF1CLK",
0899                 SUN8I_SYSCLK_CTL,
0900                 SUN8I_SYSCLK_CTL_AIF1CLK_ENA, 0, NULL, 0),
0901     SND_SOC_DAPM_SUPPLY("AIF2CLK",
0902                 SUN8I_SYSCLK_CTL,
0903                 SUN8I_SYSCLK_CTL_AIF2CLK_ENA, 0, NULL, 0),
0904     SND_SOC_DAPM_SUPPLY("SYSCLK",
0905                 SUN8I_SYSCLK_CTL,
0906                 SUN8I_SYSCLK_CTL_SYSCLK_ENA, 0, NULL, 0),
0907 
0908     /* Module Clocks */
0909     SND_SOC_DAPM_SUPPLY("CLK AIF1",
0910                 SUN8I_MOD_CLK_ENA,
0911                 SUN8I_MOD_CLK_ENA_AIF1, 0, NULL, 0),
0912     SND_SOC_DAPM_SUPPLY("CLK AIF2",
0913                 SUN8I_MOD_CLK_ENA,
0914                 SUN8I_MOD_CLK_ENA_AIF2, 0, NULL, 0),
0915     SND_SOC_DAPM_SUPPLY("CLK AIF3",
0916                 SUN8I_MOD_CLK_ENA,
0917                 SUN8I_MOD_CLK_ENA_AIF3, 0, NULL, 0),
0918     SND_SOC_DAPM_SUPPLY("CLK ADC",
0919                 SUN8I_MOD_CLK_ENA,
0920                 SUN8I_MOD_CLK_ENA_ADC, 0, NULL, 0),
0921     SND_SOC_DAPM_SUPPLY("CLK DAC",
0922                 SUN8I_MOD_CLK_ENA,
0923                 SUN8I_MOD_CLK_ENA_DAC, 0, NULL, 0),
0924 
0925     /* Module Resets */
0926     SND_SOC_DAPM_SUPPLY("RST AIF1",
0927                 SUN8I_MOD_RST_CTL,
0928                 SUN8I_MOD_RST_CTL_AIF1, 0, NULL, 0),
0929     SND_SOC_DAPM_SUPPLY("RST AIF2",
0930                 SUN8I_MOD_RST_CTL,
0931                 SUN8I_MOD_RST_CTL_AIF2, 0, NULL, 0),
0932     SND_SOC_DAPM_SUPPLY("RST AIF3",
0933                 SUN8I_MOD_RST_CTL,
0934                 SUN8I_MOD_RST_CTL_AIF3, 0, NULL, 0),
0935     SND_SOC_DAPM_SUPPLY("RST ADC",
0936                 SUN8I_MOD_RST_CTL,
0937                 SUN8I_MOD_RST_CTL_ADC, 0, NULL, 0),
0938     SND_SOC_DAPM_SUPPLY("RST DAC",
0939                 SUN8I_MOD_RST_CTL,
0940                 SUN8I_MOD_RST_CTL_DAC, 0, NULL, 0),
0941 
0942     /* Module Supplies */
0943     SND_SOC_DAPM_SUPPLY("ADC",
0944                 SUN8I_ADC_DIG_CTRL,
0945                 SUN8I_ADC_DIG_CTRL_ENAD, 0, NULL, 0),
0946     SND_SOC_DAPM_SUPPLY("DAC",
0947                 SUN8I_DAC_DIG_CTRL,
0948                 SUN8I_DAC_DIG_CTRL_ENDA, 0, NULL, 0),
0949 
0950     /* AIF "ADC" Outputs */
0951     SND_SOC_DAPM_AIF_OUT_E("AIF1 AD0L", "AIF1 Capture", 0,
0952                    SUN8I_AIF1_ADCDAT_CTRL,
0953                    SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0L_ENA, 0,
0954                    sun8i_codec_aif_event,
0955                    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
0956     SND_SOC_DAPM_AIF_OUT("AIF1 AD0R", "AIF1 Capture", 1,
0957                  SUN8I_AIF1_ADCDAT_CTRL,
0958                  SUN8I_AIF1_ADCDAT_CTRL_AIF1_AD0R_ENA, 0),
0959 
0960     SND_SOC_DAPM_AIF_OUT_E("AIF2 ADCL", "AIF2 Capture", 0,
0961                    SUN8I_AIF2_ADCDAT_CTRL,
0962                    SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCL_ENA, 0,
0963                    sun8i_codec_aif_event,
0964                    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
0965     SND_SOC_DAPM_AIF_OUT("AIF2 ADCR", "AIF2 Capture", 1,
0966                  SUN8I_AIF2_ADCDAT_CTRL,
0967                  SUN8I_AIF2_ADCDAT_CTRL_AIF2_ADCR_ENA, 0),
0968 
0969     SND_SOC_DAPM_AIF_OUT_E("AIF3 ADC", "AIF3 Capture", 0,
0970                    SND_SOC_NOPM, 0, 0,
0971                    sun8i_codec_aif_event,
0972                    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
0973 
0974     /* AIF "ADC" Mono/Stereo Muxes */
0975     SND_SOC_DAPM_MUX("AIF1 AD0L Stereo Mux", SND_SOC_NOPM, 0, 0,
0976              &sun8i_aif1_ad0_stereo_mux_control),
0977     SND_SOC_DAPM_MUX("AIF1 AD0R Stereo Mux", SND_SOC_NOPM, 0, 0,
0978              &sun8i_aif1_ad0_stereo_mux_control),
0979 
0980     SND_SOC_DAPM_MUX("AIF2 ADCL Stereo Mux", SND_SOC_NOPM, 0, 0,
0981              &sun8i_aif2_adc_stereo_mux_control),
0982     SND_SOC_DAPM_MUX("AIF2 ADCR Stereo Mux", SND_SOC_NOPM, 0, 0,
0983              &sun8i_aif2_adc_stereo_mux_control),
0984 
0985     /* AIF "ADC" Output Muxes */
0986     SND_SOC_DAPM_MUX("AIF3 ADC Source Capture Route", SND_SOC_NOPM, 0, 0,
0987              &sun8i_aif3_adc_mux_control),
0988 
0989     /* AIF "ADC" Mixers */
0990     SOC_MIXER_ARRAY("AIF1 AD0L Mixer", SND_SOC_NOPM, 0, 0,
0991             sun8i_aif1_ad0_mixer_controls),
0992     SOC_MIXER_ARRAY("AIF1 AD0R Mixer", SND_SOC_NOPM, 0, 0,
0993             sun8i_aif1_ad0_mixer_controls),
0994 
0995     SOC_MIXER_ARRAY("AIF2 ADCL Mixer", SND_SOC_NOPM, 0, 0,
0996             sun8i_aif2_adc_mixer_controls),
0997     SOC_MIXER_ARRAY("AIF2 ADCR Mixer", SND_SOC_NOPM, 0, 0,
0998             sun8i_aif2_adc_mixer_controls),
0999 
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 
1056 static 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 
1209 static 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 
1219 static 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 
1229 static 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 
1271 static 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 };
1282 
1283 static const struct regmap_config sun8i_codec_regmap_config = {
1284     .reg_bits   = 32,
1285     .reg_stride = 4,
1286     .val_bits   = 32,
1287     .max_register   = SUN8I_DAC_MXR_SRC,
1288 
1289     .cache_type = REGCACHE_FLAT,
1290 };
1291 
1292 static int sun8i_codec_probe(struct platform_device *pdev)
1293 {
1294     struct sun8i_codec *scodec;
1295     void __iomem *base;
1296     int ret;
1297 
1298     scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL);
1299     if (!scodec)
1300         return -ENOMEM;
1301 
1302     scodec->clk_module = devm_clk_get(&pdev->dev, "mod");
1303     if (IS_ERR(scodec->clk_module)) {
1304         dev_err(&pdev->dev, "Failed to get the module clock\n");
1305         return PTR_ERR(scodec->clk_module);
1306     }
1307 
1308     base = devm_platform_ioremap_resource(pdev, 0);
1309     if (IS_ERR(base)) {
1310         dev_err(&pdev->dev, "Failed to map the registers\n");
1311         return PTR_ERR(base);
1312     }
1313 
1314     scodec->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "bus", base,
1315                            &sun8i_codec_regmap_config);
1316     if (IS_ERR(scodec->regmap)) {
1317         dev_err(&pdev->dev, "Failed to create our regmap\n");
1318         return PTR_ERR(scodec->regmap);
1319     }
1320 
1321     scodec->quirks = of_device_get_match_data(&pdev->dev);
1322 
1323     platform_set_drvdata(pdev, scodec);
1324 
1325     pm_runtime_enable(&pdev->dev);
1326     if (!pm_runtime_enabled(&pdev->dev)) {
1327         ret = sun8i_codec_runtime_resume(&pdev->dev);
1328         if (ret)
1329             goto err_pm_disable;
1330     }
1331 
1332     ret = devm_snd_soc_register_component(&pdev->dev, &sun8i_soc_component,
1333                           sun8i_codec_dais,
1334                           ARRAY_SIZE(sun8i_codec_dais));
1335     if (ret) {
1336         dev_err(&pdev->dev, "Failed to register codec\n");
1337         goto err_suspend;
1338     }
1339 
1340     return ret;
1341 
1342 err_suspend:
1343     if (!pm_runtime_status_suspended(&pdev->dev))
1344         sun8i_codec_runtime_suspend(&pdev->dev);
1345 
1346 err_pm_disable:
1347     pm_runtime_disable(&pdev->dev);
1348 
1349     return ret;
1350 }
1351 
1352 static int sun8i_codec_remove(struct platform_device *pdev)
1353 {
1354     pm_runtime_disable(&pdev->dev);
1355     if (!pm_runtime_status_suspended(&pdev->dev))
1356         sun8i_codec_runtime_suspend(&pdev->dev);
1357 
1358     return 0;
1359 }
1360 
1361 static const struct sun8i_codec_quirks sun8i_a33_quirks = {
1362     .legacy_widgets = true,
1363     .lrck_inversion = true,
1364 };
1365 
1366 static const struct sun8i_codec_quirks sun50i_a64_quirks = {
1367 };
1368 
1369 static const struct of_device_id sun8i_codec_of_match[] = {
1370     { .compatible = "allwinner,sun8i-a33-codec", .data = &sun8i_a33_quirks },
1371     { .compatible = "allwinner,sun50i-a64-codec", .data = &sun50i_a64_quirks },
1372     {}
1373 };
1374 MODULE_DEVICE_TABLE(of, sun8i_codec_of_match);
1375 
1376 static const struct dev_pm_ops sun8i_codec_pm_ops = {
1377     SET_RUNTIME_PM_OPS(sun8i_codec_runtime_suspend,
1378                sun8i_codec_runtime_resume, NULL)
1379 };
1380 
1381 static struct platform_driver sun8i_codec_driver = {
1382     .driver = {
1383         .name = "sun8i-codec",
1384         .of_match_table = sun8i_codec_of_match,
1385         .pm = &sun8i_codec_pm_ops,
1386     },
1387     .probe = sun8i_codec_probe,
1388     .remove = sun8i_codec_remove,
1389 };
1390 module_platform_driver(sun8i_codec_driver);
1391 
1392 MODULE_DESCRIPTION("Allwinner A33 (sun8i) codec driver");
1393 MODULE_AUTHOR("Mylène Josserand <mylene.josserand@free-electrons.com>");
1394 MODULE_LICENSE("GPL");
1395 MODULE_ALIAS("platform:sun8i-codec");