Linux Audio

Check our new training course

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