Merge remote-tracking branch 'asoc/topic/kirkwood' into asoc-next
This commit is contained in:
commit
686378497f
|
@ -22,12 +22,16 @@
|
||||||
#include "kirkwood.h"
|
#include "kirkwood.h"
|
||||||
|
|
||||||
#define KIRKWOOD_RATES \
|
#define KIRKWOOD_RATES \
|
||||||
(SNDRV_PCM_RATE_44100 | \
|
(SNDRV_PCM_RATE_8000_192000 | \
|
||||||
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
|
SNDRV_PCM_RATE_CONTINUOUS | \
|
||||||
|
SNDRV_PCM_RATE_KNOT)
|
||||||
|
|
||||||
#define KIRKWOOD_FORMATS \
|
#define KIRKWOOD_FORMATS \
|
||||||
(SNDRV_PCM_FMTBIT_S16_LE | \
|
(SNDRV_PCM_FMTBIT_S16_LE | \
|
||||||
SNDRV_PCM_FMTBIT_S24_LE | \
|
SNDRV_PCM_FMTBIT_S24_LE | \
|
||||||
SNDRV_PCM_FMTBIT_S32_LE)
|
SNDRV_PCM_FMTBIT_S32_LE | \
|
||||||
|
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | \
|
||||||
|
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE)
|
||||||
|
|
||||||
struct kirkwood_dma_priv {
|
struct kirkwood_dma_priv {
|
||||||
struct snd_pcm_substream *play_stream;
|
struct snd_pcm_substream *play_stream;
|
||||||
|
@ -43,10 +47,10 @@ static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
|
||||||
SNDRV_PCM_INFO_PAUSE),
|
SNDRV_PCM_INFO_PAUSE),
|
||||||
.formats = KIRKWOOD_FORMATS,
|
.formats = KIRKWOOD_FORMATS,
|
||||||
.rates = KIRKWOOD_RATES,
|
.rates = KIRKWOOD_RATES,
|
||||||
.rate_min = 44100,
|
.rate_min = 8000,
|
||||||
.rate_max = 96000,
|
.rate_max = 384000,
|
||||||
.channels_min = 1,
|
.channels_min = 1,
|
||||||
.channels_max = 2,
|
.channels_max = 8,
|
||||||
.buffer_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES * KIRKWOOD_SND_MAX_PERIODS,
|
.buffer_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES * KIRKWOOD_SND_MAX_PERIODS,
|
||||||
.period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES,
|
.period_bytes_min = KIRKWOOD_SND_MIN_PERIOD_BYTES,
|
||||||
.period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES,
|
.period_bytes_max = KIRKWOOD_SND_MAX_PERIOD_BYTES,
|
||||||
|
|
|
@ -99,6 +99,29 @@ static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
|
||||||
} while (value == 0);
|
} while (value == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void kirkwood_set_rate(struct snd_soc_dai *dai,
|
||||||
|
struct kirkwood_dma_data *priv, unsigned long rate)
|
||||||
|
{
|
||||||
|
uint32_t clks_ctrl;
|
||||||
|
|
||||||
|
if (rate == 44100 || rate == 48000 || rate == 96000) {
|
||||||
|
/* use internal dco for supported rates */
|
||||||
|
dev_dbg(dai->dev, "%s: dco set rate = %lu\n",
|
||||||
|
__func__, rate);
|
||||||
|
kirkwood_set_dco(priv->io, rate);
|
||||||
|
|
||||||
|
clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO;
|
||||||
|
} else if (!IS_ERR(priv->extclk)) {
|
||||||
|
/* use optional external clk for other rates */
|
||||||
|
dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n",
|
||||||
|
__func__, rate, 256 * rate);
|
||||||
|
clk_set_rate(priv->extclk, 256 * rate);
|
||||||
|
|
||||||
|
clks_ctrl = KIRKWOOD_MCLK_SOURCE_EXTCLK;
|
||||||
|
}
|
||||||
|
writel(clks_ctrl, priv->io + KIRKWOOD_CLOCKS_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
static int kirkwood_i2s_startup(struct snd_pcm_substream *substream,
|
static int kirkwood_i2s_startup(struct snd_pcm_substream *substream,
|
||||||
struct snd_soc_dai *dai)
|
struct snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
|
@ -113,26 +136,21 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||||
struct snd_soc_dai *dai)
|
struct snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
|
struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||||
unsigned int i2s_reg, reg;
|
uint32_t ctl_play, ctl_rec;
|
||||||
unsigned long i2s_value, value;
|
unsigned int i2s_reg;
|
||||||
|
unsigned long i2s_value;
|
||||||
|
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
i2s_reg = KIRKWOOD_I2S_PLAYCTL;
|
i2s_reg = KIRKWOOD_I2S_PLAYCTL;
|
||||||
reg = KIRKWOOD_PLAYCTL;
|
|
||||||
} else {
|
} else {
|
||||||
i2s_reg = KIRKWOOD_I2S_RECCTL;
|
i2s_reg = KIRKWOOD_I2S_RECCTL;
|
||||||
reg = KIRKWOOD_RECCTL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set dco conf */
|
kirkwood_set_rate(dai, priv, params_rate(params));
|
||||||
kirkwood_set_dco(priv->io, params_rate(params));
|
|
||||||
|
|
||||||
i2s_value = readl(priv->io+i2s_reg);
|
i2s_value = readl(priv->io+i2s_reg);
|
||||||
i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK;
|
i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK;
|
||||||
|
|
||||||
value = readl(priv->io+reg);
|
|
||||||
value &= ~KIRKWOOD_PLAYCTL_SIZE_MASK;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Size settings in play/rec i2s control regs and play/rec control
|
* Size settings in play/rec i2s control regs and play/rec control
|
||||||
* regs must be the same.
|
* regs must be the same.
|
||||||
|
@ -140,38 +158,57 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
|
||||||
switch (params_format(params)) {
|
switch (params_format(params)) {
|
||||||
case SNDRV_PCM_FORMAT_S16_LE:
|
case SNDRV_PCM_FORMAT_S16_LE:
|
||||||
i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16;
|
i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16;
|
||||||
value |= KIRKWOOD_PLAYCTL_SIZE_16_C;
|
ctl_play = KIRKWOOD_PLAYCTL_SIZE_16_C |
|
||||||
|
KIRKWOOD_PLAYCTL_I2S_EN;
|
||||||
|
ctl_rec = KIRKWOOD_RECCTL_SIZE_16_C |
|
||||||
|
KIRKWOOD_RECCTL_I2S_EN;
|
||||||
break;
|
break;
|
||||||
/*
|
/*
|
||||||
* doesn't work... S20_3LE != kirkwood 20bit format ?
|
* doesn't work... S20_3LE != kirkwood 20bit format ?
|
||||||
*
|
*
|
||||||
case SNDRV_PCM_FORMAT_S20_3LE:
|
case SNDRV_PCM_FORMAT_S20_3LE:
|
||||||
i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20;
|
i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20;
|
||||||
value |= KIRKWOOD_PLAYCTL_SIZE_20;
|
ctl_play = KIRKWOOD_PLAYCTL_SIZE_20 |
|
||||||
|
KIRKWOOD_PLAYCTL_I2S_EN;
|
||||||
|
ctl_rec = KIRKWOOD_RECCTL_SIZE_20 |
|
||||||
|
KIRKWOOD_RECCTL_I2S_EN;
|
||||||
break;
|
break;
|
||||||
*/
|
*/
|
||||||
case SNDRV_PCM_FORMAT_S24_LE:
|
case SNDRV_PCM_FORMAT_S24_LE:
|
||||||
i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24;
|
i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24;
|
||||||
value |= KIRKWOOD_PLAYCTL_SIZE_24;
|
ctl_play = KIRKWOOD_PLAYCTL_SIZE_24 |
|
||||||
|
KIRKWOOD_PLAYCTL_I2S_EN;
|
||||||
|
ctl_rec = KIRKWOOD_RECCTL_SIZE_24 |
|
||||||
|
KIRKWOOD_RECCTL_I2S_EN;
|
||||||
break;
|
break;
|
||||||
case SNDRV_PCM_FORMAT_S32_LE:
|
case SNDRV_PCM_FORMAT_S32_LE:
|
||||||
i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32;
|
i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32;
|
||||||
value |= KIRKWOOD_PLAYCTL_SIZE_32;
|
ctl_play = KIRKWOOD_PLAYCTL_SIZE_32 |
|
||||||
|
KIRKWOOD_PLAYCTL_I2S_EN;
|
||||||
|
ctl_rec = KIRKWOOD_RECCTL_SIZE_32 |
|
||||||
|
KIRKWOOD_RECCTL_I2S_EN;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||||
value &= ~KIRKWOOD_PLAYCTL_MONO_MASK;
|
|
||||||
if (params_channels(params) == 1)
|
if (params_channels(params) == 1)
|
||||||
value |= KIRKWOOD_PLAYCTL_MONO_BOTH;
|
ctl_play |= KIRKWOOD_PLAYCTL_MONO_BOTH;
|
||||||
else
|
else
|
||||||
value |= KIRKWOOD_PLAYCTL_MONO_OFF;
|
ctl_play |= KIRKWOOD_PLAYCTL_MONO_OFF;
|
||||||
|
|
||||||
|
priv->ctl_play &= ~(KIRKWOOD_PLAYCTL_MONO_MASK |
|
||||||
|
KIRKWOOD_PLAYCTL_I2S_EN |
|
||||||
|
KIRKWOOD_PLAYCTL_SPDIF_EN |
|
||||||
|
KIRKWOOD_PLAYCTL_SIZE_MASK);
|
||||||
|
priv->ctl_play |= ctl_play;
|
||||||
|
} else {
|
||||||
|
priv->ctl_rec &= ~KIRKWOOD_RECCTL_SIZE_MASK;
|
||||||
|
priv->ctl_rec |= ctl_rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
writel(i2s_value, priv->io+i2s_reg);
|
writel(i2s_value, priv->io+i2s_reg);
|
||||||
writel(value, priv->io+reg);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -205,20 +242,18 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case SNDRV_PCM_TRIGGER_START:
|
case SNDRV_PCM_TRIGGER_START:
|
||||||
|
/* configure */
|
||||||
|
ctl = priv->ctl_play;
|
||||||
|
value = ctl & ~(KIRKWOOD_PLAYCTL_I2S_EN |
|
||||||
|
KIRKWOOD_PLAYCTL_SPDIF_EN);
|
||||||
|
writel(value, priv->io + KIRKWOOD_PLAYCTL);
|
||||||
|
|
||||||
|
/* enable interrupts */
|
||||||
value = readl(priv->io + KIRKWOOD_INT_MASK);
|
value = readl(priv->io + KIRKWOOD_INT_MASK);
|
||||||
value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
|
value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
|
||||||
writel(value, priv->io + KIRKWOOD_INT_MASK);
|
writel(value, priv->io + KIRKWOOD_INT_MASK);
|
||||||
|
|
||||||
/* configure audio & enable i2s playback */
|
/* enable playback */
|
||||||
ctl &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
|
|
||||||
ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
|
|
||||||
| KIRKWOOD_PLAYCTL_SPDIF_EN);
|
|
||||||
|
|
||||||
if (priv->burst == 32)
|
|
||||||
ctl |= KIRKWOOD_PLAYCTL_BURST_32;
|
|
||||||
else
|
|
||||||
ctl |= KIRKWOOD_PLAYCTL_BURST_128;
|
|
||||||
ctl |= KIRKWOOD_PLAYCTL_I2S_EN;
|
|
||||||
writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
|
writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -259,30 +294,24 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
|
||||||
int cmd, struct snd_soc_dai *dai)
|
int cmd, struct snd_soc_dai *dai)
|
||||||
{
|
{
|
||||||
struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
|
struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||||
unsigned long value;
|
uint32_t ctl, value;
|
||||||
|
|
||||||
value = readl(priv->io + KIRKWOOD_RECCTL);
|
value = readl(priv->io + KIRKWOOD_RECCTL);
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case SNDRV_PCM_TRIGGER_START:
|
case SNDRV_PCM_TRIGGER_START:
|
||||||
|
/* configure */
|
||||||
|
ctl = priv->ctl_rec;
|
||||||
|
value = ctl & ~KIRKWOOD_RECCTL_I2S_EN;
|
||||||
|
writel(value, priv->io + KIRKWOOD_RECCTL);
|
||||||
|
|
||||||
|
/* enable interrupts */
|
||||||
value = readl(priv->io + KIRKWOOD_INT_MASK);
|
value = readl(priv->io + KIRKWOOD_INT_MASK);
|
||||||
value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
|
value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
|
||||||
writel(value, priv->io + KIRKWOOD_INT_MASK);
|
writel(value, priv->io + KIRKWOOD_INT_MASK);
|
||||||
|
|
||||||
/* configure audio & enable i2s record */
|
/* enable record */
|
||||||
value = readl(priv->io + KIRKWOOD_RECCTL);
|
writel(ctl, priv->io + KIRKWOOD_RECCTL);
|
||||||
value &= ~KIRKWOOD_RECCTL_BURST_MASK;
|
|
||||||
value &= ~KIRKWOOD_RECCTL_MONO;
|
|
||||||
value &= ~(KIRKWOOD_RECCTL_PAUSE | KIRKWOOD_RECCTL_MUTE
|
|
||||||
| KIRKWOOD_RECCTL_SPDIF_EN);
|
|
||||||
|
|
||||||
if (priv->burst == 32)
|
|
||||||
value |= KIRKWOOD_RECCTL_BURST_32;
|
|
||||||
else
|
|
||||||
value |= KIRKWOOD_RECCTL_BURST_128;
|
|
||||||
value |= KIRKWOOD_RECCTL_I2S_EN;
|
|
||||||
|
|
||||||
writel(value, priv->io + KIRKWOOD_RECCTL);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SNDRV_PCM_TRIGGER_STOP:
|
case SNDRV_PCM_TRIGGER_STOP:
|
||||||
|
@ -389,90 +418,125 @@ static struct snd_soc_dai_driver kirkwood_i2s_dai = {
|
||||||
.channels_min = 1,
|
.channels_min = 1,
|
||||||
.channels_max = 2,
|
.channels_max = 2,
|
||||||
.rates = KIRKWOOD_I2S_RATES,
|
.rates = KIRKWOOD_I2S_RATES,
|
||||||
.formats = KIRKWOOD_I2S_FORMATS,},
|
.formats = KIRKWOOD_I2S_FORMATS,
|
||||||
|
},
|
||||||
.capture = {
|
.capture = {
|
||||||
.channels_min = 1,
|
.channels_min = 1,
|
||||||
.channels_max = 2,
|
.channels_max = 2,
|
||||||
.rates = KIRKWOOD_I2S_RATES,
|
.rates = KIRKWOOD_I2S_RATES,
|
||||||
.formats = KIRKWOOD_I2S_FORMATS,},
|
.formats = KIRKWOOD_I2S_FORMATS,
|
||||||
|
},
|
||||||
|
.ops = &kirkwood_i2s_dai_ops,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct snd_soc_dai_driver kirkwood_i2s_dai_extclk = {
|
||||||
|
.probe = kirkwood_i2s_probe,
|
||||||
|
.remove = kirkwood_i2s_remove,
|
||||||
|
.playback = {
|
||||||
|
.channels_min = 1,
|
||||||
|
.channels_max = 2,
|
||||||
|
.rates = SNDRV_PCM_RATE_8000_192000 |
|
||||||
|
SNDRV_PCM_RATE_CONTINUOUS |
|
||||||
|
SNDRV_PCM_RATE_KNOT,
|
||||||
|
.formats = KIRKWOOD_I2S_FORMATS,
|
||||||
|
},
|
||||||
|
.capture = {
|
||||||
|
.channels_min = 1,
|
||||||
|
.channels_max = 2,
|
||||||
|
.rates = SNDRV_PCM_RATE_8000_192000 |
|
||||||
|
SNDRV_PCM_RATE_CONTINUOUS |
|
||||||
|
SNDRV_PCM_RATE_KNOT,
|
||||||
|
.formats = KIRKWOOD_I2S_FORMATS,
|
||||||
|
},
|
||||||
.ops = &kirkwood_i2s_dai_ops,
|
.ops = &kirkwood_i2s_dai_ops,
|
||||||
};
|
};
|
||||||
|
|
||||||
static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)
|
static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct resource *mem;
|
struct kirkwood_asoc_platform_data *data = pdev->dev.platform_data;
|
||||||
struct kirkwood_asoc_platform_data *data =
|
struct snd_soc_dai_driver *soc_dai = &kirkwood_i2s_dai;
|
||||||
pdev->dev.platform_data;
|
|
||||||
struct kirkwood_dma_data *priv;
|
struct kirkwood_dma_data *priv;
|
||||||
|
struct resource *mem;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
priv = kzalloc(sizeof(struct kirkwood_dma_data), GFP_KERNEL);
|
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||||
if (!priv) {
|
if (!priv) {
|
||||||
dev_err(&pdev->dev, "allocation failed\n");
|
dev_err(&pdev->dev, "allocation failed\n");
|
||||||
err = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
dev_set_drvdata(&pdev->dev, priv);
|
dev_set_drvdata(&pdev->dev, priv);
|
||||||
|
|
||||||
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
if (!mem) {
|
if (!mem) {
|
||||||
dev_err(&pdev->dev, "platform_get_resource failed\n");
|
dev_err(&pdev->dev, "platform_get_resource failed\n");
|
||||||
err = -ENXIO;
|
return -ENXIO;
|
||||||
goto err_alloc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->mem = request_mem_region(mem->start, SZ_16K, DRV_NAME);
|
priv->io = devm_request_and_ioremap(&pdev->dev, mem);
|
||||||
if (!priv->mem) {
|
|
||||||
dev_err(&pdev->dev, "request_mem_region failed\n");
|
|
||||||
err = -EBUSY;
|
|
||||||
goto err_alloc;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->io = ioremap(priv->mem->start, SZ_16K);
|
|
||||||
if (!priv->io) {
|
if (!priv->io) {
|
||||||
dev_err(&pdev->dev, "ioremap failed\n");
|
dev_err(&pdev->dev, "devm_request_and_ioremap failed\n");
|
||||||
err = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto err_iomem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->irq = platform_get_irq(pdev, 0);
|
priv->irq = platform_get_irq(pdev, 0);
|
||||||
if (priv->irq <= 0) {
|
if (priv->irq <= 0) {
|
||||||
dev_err(&pdev->dev, "platform_get_irq failed\n");
|
dev_err(&pdev->dev, "platform_get_irq failed\n");
|
||||||
err = -ENXIO;
|
return -ENXIO;
|
||||||
goto err_ioremap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
dev_err(&pdev->dev, "no platform data ?!\n");
|
dev_err(&pdev->dev, "no platform data ?!\n");
|
||||||
err = -EINVAL;
|
return -EINVAL;
|
||||||
goto err_ioremap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->burst = data->burst;
|
priv->burst = data->burst;
|
||||||
|
|
||||||
priv->clk = clk_get(&pdev->dev, NULL);
|
priv->clk = devm_clk_get(&pdev->dev, NULL);
|
||||||
if (IS_ERR(priv->clk)) {
|
if (IS_ERR(priv->clk)) {
|
||||||
dev_err(&pdev->dev, "no clock\n");
|
dev_err(&pdev->dev, "no clock\n");
|
||||||
err = PTR_ERR(priv->clk);
|
return PTR_ERR(priv->clk);
|
||||||
goto err_ioremap;
|
|
||||||
}
|
}
|
||||||
clk_prepare_enable(priv->clk);
|
|
||||||
|
|
||||||
err = snd_soc_register_dai(&pdev->dev, &kirkwood_i2s_dai);
|
err = clk_prepare_enable(priv->clk);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
priv->extclk = clk_get(&pdev->dev, "extclk");
|
||||||
|
if (!IS_ERR(priv->extclk)) {
|
||||||
|
if (priv->extclk == priv->clk) {
|
||||||
|
clk_put(priv->extclk);
|
||||||
|
priv->extclk = ERR_PTR(-EINVAL);
|
||||||
|
} else {
|
||||||
|
dev_info(&pdev->dev, "found external clock\n");
|
||||||
|
clk_prepare_enable(priv->extclk);
|
||||||
|
soc_dai = &kirkwood_i2s_dai_extclk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Some sensible defaults - this reflects the powerup values */
|
||||||
|
priv->ctl_play = KIRKWOOD_PLAYCTL_SIZE_24;
|
||||||
|
priv->ctl_rec = KIRKWOOD_RECCTL_SIZE_24;
|
||||||
|
|
||||||
|
/* Select the burst size */
|
||||||
|
if (data->burst == 32) {
|
||||||
|
priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_32;
|
||||||
|
priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_32;
|
||||||
|
} else {
|
||||||
|
priv->ctl_play |= KIRKWOOD_PLAYCTL_BURST_128;
|
||||||
|
priv->ctl_rec |= KIRKWOOD_RECCTL_BURST_128;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = snd_soc_register_dai(&pdev->dev, soc_dai);
|
||||||
if (!err)
|
if (!err)
|
||||||
return 0;
|
return 0;
|
||||||
dev_err(&pdev->dev, "snd_soc_register_dai failed\n");
|
dev_err(&pdev->dev, "snd_soc_register_dai failed\n");
|
||||||
|
|
||||||
|
if (!IS_ERR(priv->extclk)) {
|
||||||
|
clk_disable_unprepare(priv->extclk);
|
||||||
|
clk_put(priv->extclk);
|
||||||
|
}
|
||||||
clk_disable_unprepare(priv->clk);
|
clk_disable_unprepare(priv->clk);
|
||||||
clk_put(priv->clk);
|
|
||||||
|
|
||||||
err_ioremap:
|
|
||||||
iounmap(priv->io);
|
|
||||||
err_iomem:
|
|
||||||
release_mem_region(priv->mem->start, SZ_16K);
|
|
||||||
err_alloc:
|
|
||||||
kfree(priv);
|
|
||||||
error:
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,12 +546,11 @@ static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev)
|
||||||
|
|
||||||
snd_soc_unregister_dai(&pdev->dev);
|
snd_soc_unregister_dai(&pdev->dev);
|
||||||
|
|
||||||
|
if (!IS_ERR(priv->extclk)) {
|
||||||
|
clk_disable_unprepare(priv->extclk);
|
||||||
|
clk_put(priv->extclk);
|
||||||
|
}
|
||||||
clk_disable_unprepare(priv->clk);
|
clk_disable_unprepare(priv->clk);
|
||||||
clk_put(priv->clk);
|
|
||||||
|
|
||||||
iounmap(priv->io);
|
|
||||||
release_mem_region(priv->mem->start, SZ_16K);
|
|
||||||
kfree(priv);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,11 @@
|
||||||
#define KIRKWOOD_DCO_SPCR_STATUS 0x120c
|
#define KIRKWOOD_DCO_SPCR_STATUS 0x120c
|
||||||
#define KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK (1<<16)
|
#define KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK (1<<16)
|
||||||
|
|
||||||
|
#define KIRKWOOD_CLOCKS_CTRL 0x1230
|
||||||
|
#define KIRKWOOD_MCLK_SOURCE_MASK (3<<0)
|
||||||
|
#define KIRKWOOD_MCLK_SOURCE_DCO (0<<0)
|
||||||
|
#define KIRKWOOD_MCLK_SOURCE_EXTCLK (3<<0)
|
||||||
|
|
||||||
#define KIRKWOOD_ERR_CAUSE 0x1300
|
#define KIRKWOOD_ERR_CAUSE 0x1300
|
||||||
#define KIRKWOOD_ERR_MASK 0x1304
|
#define KIRKWOOD_ERR_MASK 0x1304
|
||||||
|
|
||||||
|
@ -119,11 +124,13 @@
|
||||||
#define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x4000
|
#define KIRKWOOD_SND_MAX_PERIOD_BYTES 0x4000
|
||||||
|
|
||||||
struct kirkwood_dma_data {
|
struct kirkwood_dma_data {
|
||||||
struct resource *mem;
|
|
||||||
void __iomem *io;
|
void __iomem *io;
|
||||||
|
struct clk *clk;
|
||||||
|
struct clk *extclk;
|
||||||
|
uint32_t ctl_play;
|
||||||
|
uint32_t ctl_rec;
|
||||||
int irq;
|
int irq;
|
||||||
int burst;
|
int burst;
|
||||||
struct clk *clk;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue