cachepc-linux

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

kirkwood-i2s.c (16447B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * kirkwood-i2s.c
      4 *
      5 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
      6 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
      7 */
      8
      9#include <linux/init.h>
     10#include <linux/module.h>
     11#include <linux/platform_device.h>
     12#include <linux/io.h>
     13#include <linux/slab.h>
     14#include <linux/mbus.h>
     15#include <linux/delay.h>
     16#include <linux/clk.h>
     17#include <sound/pcm.h>
     18#include <sound/pcm_params.h>
     19#include <sound/soc.h>
     20#include <linux/platform_data/asoc-kirkwood.h>
     21#include <linux/of.h>
     22
     23#include "kirkwood.h"
     24
     25#define KIRKWOOD_I2S_FORMATS \
     26	(SNDRV_PCM_FMTBIT_S16_LE | \
     27	 SNDRV_PCM_FMTBIT_S24_LE | \
     28	 SNDRV_PCM_FMTBIT_S32_LE)
     29
     30#define KIRKWOOD_SPDIF_FORMATS \
     31	(SNDRV_PCM_FMTBIT_S16_LE | \
     32	 SNDRV_PCM_FMTBIT_S24_LE)
     33
     34static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
     35		unsigned int fmt)
     36{
     37	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(cpu_dai);
     38	unsigned long mask;
     39	unsigned long value;
     40
     41	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
     42	case SND_SOC_DAIFMT_RIGHT_J:
     43		mask = KIRKWOOD_I2S_CTL_RJ;
     44		break;
     45	case SND_SOC_DAIFMT_LEFT_J:
     46		mask = KIRKWOOD_I2S_CTL_LJ;
     47		break;
     48	case SND_SOC_DAIFMT_I2S:
     49		mask = KIRKWOOD_I2S_CTL_I2S;
     50		break;
     51	default:
     52		return -EINVAL;
     53	}
     54
     55	/*
     56	 * Set same format for playback and record
     57	 * This avoids some troubles.
     58	 */
     59	value = readl(priv->io+KIRKWOOD_I2S_PLAYCTL);
     60	value &= ~KIRKWOOD_I2S_CTL_JUST_MASK;
     61	value |= mask;
     62	writel(value, priv->io+KIRKWOOD_I2S_PLAYCTL);
     63
     64	value = readl(priv->io+KIRKWOOD_I2S_RECCTL);
     65	value &= ~KIRKWOOD_I2S_CTL_JUST_MASK;
     66	value |= mask;
     67	writel(value, priv->io+KIRKWOOD_I2S_RECCTL);
     68
     69	return 0;
     70}
     71
     72static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
     73{
     74	unsigned long value;
     75
     76	value = KIRKWOOD_DCO_CTL_OFFSET_0;
     77	switch (rate) {
     78	default:
     79	case 44100:
     80		value |= KIRKWOOD_DCO_CTL_FREQ_11;
     81		break;
     82	case 48000:
     83		value |= KIRKWOOD_DCO_CTL_FREQ_12;
     84		break;
     85	case 96000:
     86		value |= KIRKWOOD_DCO_CTL_FREQ_24;
     87		break;
     88	}
     89	writel(value, io + KIRKWOOD_DCO_CTL);
     90
     91	/* wait for dco locked */
     92	do {
     93		cpu_relax();
     94		value = readl(io + KIRKWOOD_DCO_SPCR_STATUS);
     95		value &= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK;
     96	} while (value == 0);
     97}
     98
     99static void kirkwood_set_rate(struct snd_soc_dai *dai,
    100	struct kirkwood_dma_data *priv, unsigned long rate)
    101{
    102	uint32_t clks_ctrl;
    103
    104	if (IS_ERR(priv->extclk)) {
    105		/* use internal dco for the supported rates
    106		 * defined in kirkwood_i2s_dai */
    107		dev_dbg(dai->dev, "%s: dco set rate = %lu\n",
    108			__func__, rate);
    109		kirkwood_set_dco(priv->io, rate);
    110
    111		clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO;
    112	} else {
    113		/* use the external clock for the other rates
    114		 * defined in kirkwood_i2s_dai_extclk */
    115		dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n",
    116			__func__, rate, 256 * rate);
    117		clk_set_rate(priv->extclk, 256 * rate);
    118
    119		clks_ctrl = KIRKWOOD_MCLK_SOURCE_EXTCLK;
    120	}
    121	writel(clks_ctrl, priv->io + KIRKWOOD_CLOCKS_CTRL);
    122}
    123
    124static int kirkwood_i2s_startup(struct snd_pcm_substream *substream,
    125		struct snd_soc_dai *dai)
    126{
    127	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
    128
    129	snd_soc_dai_set_dma_data(dai, substream, priv);
    130	return 0;
    131}
    132
    133static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
    134				 struct snd_pcm_hw_params *params,
    135				 struct snd_soc_dai *dai)
    136{
    137	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
    138	uint32_t ctl_play, ctl_rec;
    139	unsigned int i2s_reg;
    140	unsigned long i2s_value;
    141
    142	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    143		i2s_reg = KIRKWOOD_I2S_PLAYCTL;
    144	} else {
    145		i2s_reg = KIRKWOOD_I2S_RECCTL;
    146	}
    147
    148	kirkwood_set_rate(dai, priv, params_rate(params));
    149
    150	i2s_value = readl(priv->io+i2s_reg);
    151	i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK;
    152
    153	/*
    154	 * Size settings in play/rec i2s control regs and play/rec control
    155	 * regs must be the same.
    156	 */
    157	switch (params_format(params)) {
    158	case SNDRV_PCM_FORMAT_S16_LE:
    159		i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16;
    160		ctl_play = KIRKWOOD_PLAYCTL_SIZE_16_C |
    161			   KIRKWOOD_PLAYCTL_I2S_EN |
    162			   KIRKWOOD_PLAYCTL_SPDIF_EN;
    163		ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C |
    164			  KIRKWOOD_RECCTL_I2S_EN |
    165			  KIRKWOOD_RECCTL_SPDIF_EN;
    166		break;
    167	/*
    168	 * doesn't work... S20_3LE != kirkwood 20bit format ?
    169	 *
    170	case SNDRV_PCM_FORMAT_S20_3LE:
    171		i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20;
    172		ctl_play = KIRKWOOD_PLAYCTL_SIZE_20 |
    173			   KIRKWOOD_PLAYCTL_I2S_EN;
    174		ctl_rec = KIRKWOOD_RECCTL_SIZE_20 |
    175			  KIRKWOOD_RECCTL_I2S_EN;
    176		break;
    177	*/
    178	case SNDRV_PCM_FORMAT_S24_LE:
    179		i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24;
    180		ctl_play = KIRKWOOD_PLAYCTL_SIZE_24 |
    181			   KIRKWOOD_PLAYCTL_I2S_EN |
    182			   KIRKWOOD_PLAYCTL_SPDIF_EN;
    183		ctl_rec = KIRKWOOD_RECCTL_SIZE_24 |
    184			  KIRKWOOD_RECCTL_I2S_EN |
    185			  KIRKWOOD_RECCTL_SPDIF_EN;
    186		break;
    187	case SNDRV_PCM_FORMAT_S32_LE:
    188		i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32;
    189		ctl_play = KIRKWOOD_PLAYCTL_SIZE_32 |
    190			   KIRKWOOD_PLAYCTL_I2S_EN;
    191		ctl_rec = KIRKWOOD_RECCTL_SIZE_32 |
    192			  KIRKWOOD_RECCTL_I2S_EN;
    193		break;
    194	default:
    195		return -EINVAL;
    196	}
    197
    198	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    199		if (params_channels(params) == 1)
    200			ctl_play |= KIRKWOOD_PLAYCTL_MONO_BOTH;
    201		else
    202			ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF;
    203
    204		priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK |
    205				    KIRKWOOD_PLAYCTL_ENABLE_MASK |
    206				    KIRKWOOD_PLAYCTL_SIZE_MASK);
    207		priv->ctl_play |= ctl_play;
    208	} else {
    209		priv->ctl_rec &= ~(KIRKWOOD_RECCTL_ENABLE_MASK |
    210				   KIRKWOOD_RECCTL_SIZE_MASK);
    211		priv->ctl_rec |= ctl_rec;
    212	}
    213
    214	writel(i2s_value, priv->io+i2s_reg);
    215
    216	return 0;
    217}
    218
    219static unsigned kirkwood_i2s_play_mute(unsigned ctl)
    220{
    221	if (!(ctl & KIRKWOOD_PLAYCTL_I2S_EN))
    222		ctl |= KIRKWOOD_PLAYCTL_I2S_MUTE;
    223	if (!(ctl & KIRKWOOD_PLAYCTL_SPDIF_EN))
    224		ctl |= KIRKWOOD_PLAYCTL_SPDIF_MUTE;
    225	return ctl;
    226}
    227
    228static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
    229				int cmd, struct snd_soc_dai *dai)
    230{
    231	struct snd_pcm_runtime *runtime = substream->runtime;
    232	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
    233	uint32_t ctl, value;
    234
    235	ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
    236	if ((ctl & KIRKWOOD_PLAYCTL_ENABLE_MASK) == 0) {
    237		unsigned timeout = 5000;
    238		/*
    239		 * The Armada510 spec says that if we enter pause mode, the
    240		 * busy bit must be read back as clear _twice_.  Make sure
    241		 * we respect that otherwise we get DMA underruns.
    242		 */
    243		do {
    244			value = ctl;
    245			ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
    246			if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY))
    247				break;
    248			udelay(1);
    249		} while (timeout--);
    250
    251		if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)
    252			dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n",
    253				   ctl);
    254	}
    255
    256	switch (cmd) {
    257	case SNDRV_PCM_TRIGGER_START:
    258		/* configure */
    259		ctl = priv->ctl_play;
    260		if (dai->id == 0)
    261			ctl &= ~KIRKWOOD_PLAYCTL_SPDIF_EN;	/* i2s */
    262		else
    263			ctl &= ~KIRKWOOD_PLAYCTL_I2S_EN;	/* spdif */
    264		ctl = kirkwood_i2s_play_mute(ctl);
    265		value = ctl & ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
    266		writel(value, priv->io + KIRKWOOD_PLAYCTL);
    267
    268		/* enable interrupts */
    269		if (!runtime->no_period_wakeup) {
    270			value = readl(priv->io + KIRKWOOD_INT_MASK);
    271			value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
    272			writel(value, priv->io + KIRKWOOD_INT_MASK);
    273		}
    274
    275		/* enable playback */
    276		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
    277		break;
    278
    279	case SNDRV_PCM_TRIGGER_STOP:
    280		/* stop audio, disable interrupts */
    281		ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
    282				KIRKWOOD_PLAYCTL_SPDIF_MUTE;
    283		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
    284
    285		value = readl(priv->io + KIRKWOOD_INT_MASK);
    286		value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
    287		writel(value, priv->io + KIRKWOOD_INT_MASK);
    288
    289		/* disable all playbacks */
    290		ctl &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
    291		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
    292		break;
    293
    294	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
    295	case SNDRV_PCM_TRIGGER_SUSPEND:
    296		ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
    297				KIRKWOOD_PLAYCTL_SPDIF_MUTE;
    298		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
    299		break;
    300
    301	case SNDRV_PCM_TRIGGER_RESUME:
    302	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
    303		ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE |
    304				KIRKWOOD_PLAYCTL_SPDIF_MUTE);
    305		ctl = kirkwood_i2s_play_mute(ctl);
    306		writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
    307		break;
    308
    309	default:
    310		return -EINVAL;
    311	}
    312
    313	return 0;
    314}
    315
    316static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
    317				int cmd, struct snd_soc_dai *dai)
    318{
    319	struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
    320	uint32_t ctl, value;
    321
    322	value = readl(priv->io + KIRKWOOD_RECCTL);
    323
    324	switch (cmd) {
    325	case SNDRV_PCM_TRIGGER_START:
    326		/* configure */
    327		ctl = priv->ctl_rec;
    328		if (dai->id == 0)
    329			ctl &= ~KIRKWOOD_RECCTL_SPDIF_EN;	/* i2s */
    330		else
    331			ctl &= ~KIRKWOOD_RECCTL_I2S_EN;		/* spdif */
    332
    333		value = ctl & ~KIRKWOOD_RECCTL_ENABLE_MASK;
    334		writel(value, priv->io + KIRKWOOD_RECCTL);
    335
    336		/* enable interrupts */
    337		value = readl(priv->io + KIRKWOOD_INT_MASK);
    338		value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
    339		writel(value, priv->io + KIRKWOOD_INT_MASK);
    340
    341		/* enable record */
    342		writel(ctl, priv->io + KIRKWOOD_RECCTL);
    343		break;
    344
    345	case SNDRV_PCM_TRIGGER_STOP:
    346		/* stop audio, disable interrupts */
    347		value = readl(priv->io + KIRKWOOD_RECCTL);
    348		value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE;
    349		writel(value, priv->io + KIRKWOOD_RECCTL);
    350
    351		value = readl(priv->io + KIRKWOOD_INT_MASK);
    352		value &= ~KIRKWOOD_INT_CAUSE_REC_BYTES;
    353		writel(value, priv->io + KIRKWOOD_INT_MASK);
    354
    355		/* disable all records */
    356		value = readl(priv->io + KIRKWOOD_RECCTL);
    357		value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
    358		writel(value, priv->io + KIRKWOOD_RECCTL);
    359		break;
    360
    361	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
    362	case SNDRV_PCM_TRIGGER_SUSPEND:
    363		value = readl(priv->io + KIRKWOOD_RECCTL);
    364		value |= KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE;
    365		writel(value, priv->io + KIRKWOOD_RECCTL);
    366		break;
    367
    368	case SNDRV_PCM_TRIGGER_RESUME:
    369	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
    370		value = readl(priv->io + KIRKWOOD_RECCTL);
    371		value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE);
    372		writel(value, priv->io + KIRKWOOD_RECCTL);
    373		break;
    374
    375	default:
    376		return -EINVAL;
    377	}
    378
    379	return 0;
    380}
    381
    382static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
    383			       struct snd_soc_dai *dai)
    384{
    385	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    386		return kirkwood_i2s_play_trigger(substream, cmd, dai);
    387	else
    388		return kirkwood_i2s_rec_trigger(substream, cmd, dai);
    389
    390	return 0;
    391}
    392
    393static int kirkwood_i2s_init(struct kirkwood_dma_data *priv)
    394{
    395	unsigned long value;
    396	unsigned int reg_data;
    397
    398	/* put system in a "safe" state : */
    399	/* disable audio interrupts */
    400	writel(0xffffffff, priv->io + KIRKWOOD_INT_CAUSE);
    401	writel(0, priv->io + KIRKWOOD_INT_MASK);
    402
    403	reg_data = readl(priv->io + 0x1200);
    404	reg_data &= (~(0x333FF8));
    405	reg_data |= 0x111D18;
    406	writel(reg_data, priv->io + 0x1200);
    407
    408	msleep(500);
    409
    410	reg_data = readl(priv->io + 0x1200);
    411	reg_data &= (~(0x333FF8));
    412	reg_data |= 0x111D18;
    413	writel(reg_data, priv->io + 0x1200);
    414
    415	/* disable playback/record */
    416	value = readl(priv->io + KIRKWOOD_PLAYCTL);
    417	value &= ~KIRKWOOD_PLAYCTL_ENABLE_MASK;
    418	writel(value, priv->io + KIRKWOOD_PLAYCTL);
    419
    420	value = readl(priv->io + KIRKWOOD_RECCTL);
    421	value &= ~KIRKWOOD_RECCTL_ENABLE_MASK;
    422	writel(value, priv->io + KIRKWOOD_RECCTL);
    423
    424	return 0;
    425
    426}
    427
    428static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
    429	.startup	= kirkwood_i2s_startup,
    430	.trigger	= kirkwood_i2s_trigger,
    431	.hw_params      = kirkwood_i2s_hw_params,
    432	.set_fmt        = kirkwood_i2s_set_fmt,
    433};
    434
    435static struct snd_soc_dai_driver kirkwood_i2s_dai[2] = {
    436    {
    437	.name = "i2s",
    438	.id = 0,
    439	.playback = {
    440		.channels_min = 1,
    441		.channels_max = 2,
    442		.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
    443				SNDRV_PCM_RATE_96000,
    444		.formats = KIRKWOOD_I2S_FORMATS,
    445	},
    446	.capture = {
    447		.channels_min = 1,
    448		.channels_max = 2,
    449		.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
    450				SNDRV_PCM_RATE_96000,
    451		.formats = KIRKWOOD_I2S_FORMATS,
    452	},
    453	.ops = &kirkwood_i2s_dai_ops,
    454    },
    455    {
    456	.name = "spdif",
    457	.id = 1,
    458	.playback = {
    459		.channels_min = 1,
    460		.channels_max = 2,
    461		.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
    462				SNDRV_PCM_RATE_96000,
    463		.formats = KIRKWOOD_SPDIF_FORMATS,
    464	},
    465	.capture = {
    466		.channels_min = 1,
    467		.channels_max = 2,
    468		.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
    469				SNDRV_PCM_RATE_96000,
    470		.formats = KIRKWOOD_SPDIF_FORMATS,
    471	},
    472	.ops = &kirkwood_i2s_dai_ops,
    473    },
    474};
    475
    476static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk[2] = {
    477    {
    478	.name = "i2s",
    479	.id = 0,
    480	.playback = {
    481		.channels_min = 1,
    482		.channels_max = 2,
    483		.rates = SNDRV_PCM_RATE_CONTINUOUS,
    484		.rate_min = 5512,
    485		.rate_max = 192000,
    486		.formats = KIRKWOOD_I2S_FORMATS,
    487	},
    488	.capture = {
    489		.channels_min = 1,
    490		.channels_max = 2,
    491		.rates = SNDRV_PCM_RATE_CONTINUOUS,
    492		.rate_min = 5512,
    493		.rate_max = 192000,
    494		.formats = KIRKWOOD_I2S_FORMATS,
    495	},
    496	.ops = &kirkwood_i2s_dai_ops,
    497    },
    498    {
    499	.name = "spdif",
    500	.id = 1,
    501	.playback = {
    502		.channels_min = 1,
    503		.channels_max = 2,
    504		.rates = SNDRV_PCM_RATE_CONTINUOUS,
    505		.rate_min = 5512,
    506		.rate_max = 192000,
    507		.formats = KIRKWOOD_SPDIF_FORMATS,
    508	},
    509	.capture = {
    510		.channels_min = 1,
    511		.channels_max = 2,
    512		.rates = SNDRV_PCM_RATE_CONTINUOUS,
    513		.rate_min = 5512,
    514		.rate_max = 192000,
    515		.formats = KIRKWOOD_SPDIF_FORMATS,
    516	},
    517	.ops = &kirkwood_i2s_dai_ops,
    518    },
    519};
    520
    521static int kirkwood_i2s_dev_probe(struct platform_device *pdev)
    522{
    523	struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data;
    524	struct snd_soc_dai_driver *soc_dai = kirkwood_i2s_dai;
    525	struct kirkwood_dma_data *priv;
    526	struct device_node *np = pdev->dev.of_node;
    527	int err;
    528
    529	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
    530	if (!priv)
    531		return -ENOMEM;
    532
    533	dev_set_drvdata(&pdev->dev, priv);
    534
    535	priv->io = devm_platform_ioremap_resource(pdev, 0);
    536	if (IS_ERR(priv->io))
    537		return PTR_ERR(priv->io);
    538
    539	priv->irq = platform_get_irq(pdev, 0);
    540	if (priv->irq < 0)
    541		return priv->irq;
    542
    543	if (np) {
    544		priv->burst = 128;		/* might be 32 or 128 */
    545	} else if (data) {
    546		priv->burst = data->burst;
    547	} else {
    548		dev_err(&pdev->dev, "no DT nor platform data ?!\n");
    549		return -EINVAL;
    550	}
    551
    552	priv->clk = devm_clk_get(&pdev->dev, np ? "internal" : NULL);
    553	if (IS_ERR(priv->clk)) {
    554		dev_err(&pdev->dev, "no clock\n");
    555		return PTR_ERR(priv->clk);
    556	}
    557
    558	priv->extclk = devm_clk_get(&pdev->dev, "extclk");
    559	if (IS_ERR(priv->extclk)) {
    560		if (PTR_ERR(priv->extclk) == -EPROBE_DEFER)
    561			return -EPROBE_DEFER;
    562	} else {
    563		if (clk_is_match(priv->extclk, priv->clk)) {
    564			devm_clk_put(&pdev->dev, priv->extclk);
    565			priv->extclk = ERR_PTR(-EINVAL);
    566		} else {
    567			dev_info(&pdev->dev, "found external clock\n");
    568			clk_prepare_enable(priv->extclk);
    569			soc_dai = kirkwood_i2s_dai_extclk;
    570		}
    571	}
    572
    573	err = clk_prepare_enable(priv->clk);
    574	if (err < 0)
    575		return err;
    576
    577	/* Some sensible defaults - this reflects the powerup values */
    578	priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24;
    579	priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24;
    580
    581	/* Select the burst size */
    582	if (priv->burst == 32) {
    583		priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32;
    584		priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32;
    585	} else {
    586		priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128;
    587		priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128;
    588	}
    589
    590	err = snd_soc_register_component(&pdev->dev, &kirkwood_soc_component,
    591					 soc_dai, 2);
    592	if (err) {
    593		dev_err(&pdev->dev, "snd_soc_register_component failed\n");
    594		goto err_component;
    595	}
    596
    597	kirkwood_i2s_init(priv);
    598
    599	return 0;
    600
    601 err_component:
    602	if (!IS_ERR(priv->extclk))
    603		clk_disable_unprepare(priv->extclk);
    604	clk_disable_unprepare(priv->clk);
    605
    606	return err;
    607}
    608
    609static int kirkwood_i2s_dev_remove(struct platform_device *pdev)
    610{
    611	struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
    612
    613	snd_soc_unregister_component(&pdev->dev);
    614	if (!IS_ERR(priv->extclk))
    615		clk_disable_unprepare(priv->extclk);
    616	clk_disable_unprepare(priv->clk);
    617
    618	return 0;
    619}
    620
    621#ifdef CONFIG_OF
    622static const struct of_device_id mvebu_audio_of_match[] = {
    623	{ .compatible = "marvell,kirkwood-audio" },
    624	{ .compatible = "marvell,dove-audio" },
    625	{ .compatible = "marvell,armada370-audio" },
    626	{ }
    627};
    628MODULE_DEVICE_TABLE(of, mvebu_audio_of_match);
    629#endif
    630
    631static struct platform_driver kirkwood_i2s_driver = {
    632	.probe  = kirkwood_i2s_dev_probe,
    633	.remove = kirkwood_i2s_dev_remove,
    634	.driver = {
    635		.name = DRV_NAME,
    636		.of_match_table = of_match_ptr(mvebu_audio_of_match),
    637	},
    638};
    639
    640module_platform_driver(kirkwood_i2s_driver);
    641
    642/* Module information */
    643MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>");
    644MODULE_DESCRIPTION("Kirkwood I2S SoC Interface");
    645MODULE_LICENSE("GPL");
    646MODULE_ALIAS("platform:mvebu-audio");