Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Au1000/Au1500/Au1100 I2S controller driver for ASoC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Note: clock supplied to the I2S controller must be 256x samplerate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/suspend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <asm/mach-au1x00/au1000.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include "psc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #define I2S_RXTX	0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define I2S_CFG		0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define I2S_ENABLE	0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #define CFG_XU		(1 << 25)	/* tx underflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #define CFG_XO		(1 << 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #define CFG_RU		(1 << 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #define CFG_RO		(1 << 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #define CFG_TR		(1 << 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #define CFG_TE		(1 << 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define CFG_TF		(1 << 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #define CFG_RR		(1 << 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #define CFG_RF		(1 << 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #define CFG_ICK		(1 << 12)	/* clock invert */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #define CFG_PD		(1 << 11)	/* set to make I2SDIO INPUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define CFG_LB		(1 << 10)	/* loopback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define CFG_IC		(1 << 9)	/* word select invert */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) #define CFG_FM_I2S	(0 << 7)	/* I2S format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #define CFG_FM_LJ	(1 << 7)	/* left-justified */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define CFG_FM_RJ	(2 << 7)	/* right-justified */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) #define CFG_FM_MASK	(3 << 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #define CFG_TN		(1 << 6)	/* tx fifo en */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define CFG_RN		(1 << 5)	/* rx fifo en */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) #define CFG_SZ_8	(0x08)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) #define CFG_SZ_16	(0x10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #define CFG_SZ_18	(0x12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #define CFG_SZ_20	(0x14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) #define CFG_SZ_24	(0x18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) #define CFG_SZ_MASK	(0x1f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) #define EN_D		(1 << 1)	/* DISable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) #define EN_CE		(1 << 0)	/* clock enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) /* only limited by clock generator and board design */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) #define AU1XI2SC_RATES \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	SNDRV_PCM_RATE_CONTINUOUS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) #define AU1XI2SC_FMTS \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	(SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 |		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE |	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_U18_3LE |	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	SNDRV_PCM_FMTBIT_S18_3BE | SNDRV_PCM_FMTBIT_U18_3BE |	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE |	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	SNDRV_PCM_FMTBIT_S20_3BE | SNDRV_PCM_FMTBIT_U20_3BE |	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE |	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_U24_BE |	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) static inline unsigned long RD(struct au1xpsc_audio_data *ctx, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	return __raw_readl(ctx->mmio + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) static inline void WR(struct au1xpsc_audio_data *ctx, int reg, unsigned long v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	__raw_writel(v, ctx->mmio + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) static int au1xi2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	unsigned long c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	c = ctx->cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	c &= ~CFG_FM_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	case SND_SOC_DAIFMT_I2S:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 		c |= CFG_FM_I2S;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	case SND_SOC_DAIFMT_MSB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		c |= CFG_FM_RJ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	case SND_SOC_DAIFMT_LSB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		c |= CFG_FM_LJ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	c &= ~(CFG_IC | CFG_ICK);		/* IB-IF */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	case SND_SOC_DAIFMT_NB_NF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		c |= CFG_IC | CFG_ICK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	case SND_SOC_DAIFMT_NB_IF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 		c |= CFG_IC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	case SND_SOC_DAIFMT_IB_NF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 		c |= CFG_ICK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	case SND_SOC_DAIFMT_IB_IF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	/* I2S controller only supports master */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	case SND_SOC_DAIFMT_CBS_CFS:	/* CODEC slave */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	ctx->cfg = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static int au1xi2s_trigger(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 			   int cmd, struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	int stype = SUBSTREAM_TYPE(substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	case SNDRV_PCM_TRIGGER_RESUME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		/* power up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		WR(ctx, I2S_ENABLE, EN_D | EN_CE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		WR(ctx, I2S_ENABLE, EN_CE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		ctx->cfg |= (stype == PCM_TX) ? CFG_TN : CFG_RN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		WR(ctx, I2S_CFG, ctx->cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	case SNDRV_PCM_TRIGGER_SUSPEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		ctx->cfg &= ~((stype == PCM_TX) ? CFG_TN : CFG_RN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		WR(ctx, I2S_CFG, ctx->cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		WR(ctx, I2S_ENABLE, EN_D);		/* power off */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static unsigned long msbits_to_reg(int msbits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	switch (msbits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		return CFG_SZ_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		return CFG_SZ_16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	case 18:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		return CFG_SZ_18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	case 20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		return CFG_SZ_20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	case 24:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		return CFG_SZ_24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static int au1xi2s_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 			     struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 			     struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	unsigned long v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	v = msbits_to_reg(params->msbits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	if (!v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	ctx->cfg &= ~CFG_SZ_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	ctx->cfg |= v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static int au1xi2s_startup(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 			   struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	snd_soc_dai_set_dma_data(dai, substream, &ctx->dmaids[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static const struct snd_soc_dai_ops au1xi2s_dai_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	.startup	= au1xi2s_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	.trigger	= au1xi2s_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	.hw_params	= au1xi2s_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	.set_fmt	= au1xi2s_set_fmt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static struct snd_soc_dai_driver au1xi2s_dai_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	.symmetric_rates	= 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	.playback = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		.rates		= AU1XI2SC_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		.formats	= AU1XI2SC_FMTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		.channels_min	= 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		.channels_max	= 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	.capture = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 		.rates		= AU1XI2SC_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 		.formats	= AU1XI2SC_FMTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		.channels_min	= 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		.channels_max	= 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	.ops = &au1xi2s_dai_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) static const struct snd_soc_component_driver au1xi2s_component = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	.name		= "au1xi2s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static int au1xi2s_drvprobe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	struct resource *iores, *dmares;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	struct au1xpsc_audio_data *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	if (!ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	if (!iores)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 	if (!devm_request_mem_region(&pdev->dev, iores->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 				     resource_size(iores),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 				     pdev->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	ctx->mmio = devm_ioremap(&pdev->dev, iores->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 					 resource_size(iores));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	if (!ctx->mmio)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	if (!dmares)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	if (!dmares)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	platform_set_drvdata(pdev, ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	return snd_soc_register_component(&pdev->dev, &au1xi2s_component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 					  &au1xi2s_dai_driver, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static int au1xi2s_drvremove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 	struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	snd_soc_unregister_component(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	WR(ctx, I2S_ENABLE, EN_D);	/* clock off, disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static int au1xi2s_drvsuspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	struct au1xpsc_audio_data *ctx = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	WR(ctx, I2S_ENABLE, EN_D);	/* clock off, disable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static int au1xi2s_drvresume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) static const struct dev_pm_ops au1xi2sc_pmops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	.suspend	= au1xi2s_drvsuspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	.resume		= au1xi2s_drvresume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) #define AU1XI2SC_PMOPS (&au1xi2sc_pmops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) #define AU1XI2SC_PMOPS NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) static struct platform_driver au1xi2s_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	.driver	= {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 		.name	= "alchemy-i2sc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		.pm	= AU1XI2SC_PMOPS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	.probe		= au1xi2s_drvprobe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	.remove		= au1xi2s_drvremove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) module_platform_driver(au1xi2s_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) MODULE_DESCRIPTION("Au1000/1500/1100 I2S ASoC driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) MODULE_AUTHOR("Manuel Lauss");