cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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");