summaryrefslogtreecommitdiffstats
path: root/sound/soc/ep93xx/ep93xx-i2s.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/ep93xx/ep93xx-i2s.c')
-rw-r--r--sound/soc/ep93xx/ep93xx-i2s.c47
1 files changed, 25 insertions, 22 deletions
diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c
index 4f4873359613..042f4e93746f 100644
--- a/sound/soc/ep93xx/ep93xx-i2s.c
+++ b/sound/soc/ep93xx/ep93xx-i2s.c
@@ -242,7 +242,7 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream,
{
struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
unsigned word_len, div, sdiv, lrdiv;
- int found = 0, err;
+ int err;
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
@@ -267,21 +267,22 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream,
ep93xx_i2s_write_reg(info, EP93XX_I2S_RXWRDLEN, word_len);
/*
- * Calculate the sdiv (bit clock) and lrdiv (left/right clock) values.
- * If the lrclk is pulse length is larger than the word size, then the
- * bit clock will be gated for the unused bits.
+ * EP93xx I2S module can be setup so SCLK / LRCLK value can be
+ * 32, 64, 128. MCLK / SCLK value can be 2 and 4.
+ * We set LRCLK equal to `rate' and minimum SCLK / LRCLK
+ * value is 64, because our sample size is 32 bit * 2 channels.
+ * I2S standard permits us to transmit more bits than
+ * the codec uses.
*/
- div = (clk_get_rate(info->mclk) / params_rate(params)) *
- params_channels(params);
- for (sdiv = 2; sdiv <= 4; sdiv += 2)
- for (lrdiv = 32; lrdiv <= 128; lrdiv <<= 1)
- if (sdiv * lrdiv == div) {
- found = 1;
- goto out;
- }
-out:
- if (!found)
- return -EINVAL;
+ div = clk_get_rate(info->mclk) / params_rate(params);
+ sdiv = 4;
+ if (div > (256 + 512) / 2) {
+ lrdiv = 128;
+ } else {
+ lrdiv = 64;
+ if (div < (128 + 256) / 2)
+ sdiv = 2;
+ }
err = clk_set_rate(info->sclk, clk_get_rate(info->mclk) / sdiv);
if (err)
@@ -312,10 +313,12 @@ static int ep93xx_i2s_suspend(struct snd_soc_dai *dai)
struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
if (!dai->active)
- return;
+ return 0;
ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_PLAYBACK);
ep93xx_i2s_disable(info, SNDRV_PCM_STREAM_CAPTURE);
+
+ return 0;
}
static int ep93xx_i2s_resume(struct snd_soc_dai *dai)
@@ -323,10 +326,12 @@ static int ep93xx_i2s_resume(struct snd_soc_dai *dai)
struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
if (!dai->active)
- return;
+ return 0;
ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_PLAYBACK);
ep93xx_i2s_enable(info, SNDRV_PCM_STREAM_CAPTURE);
+
+ return 0;
}
#else
#define ep93xx_i2s_suspend NULL
@@ -341,9 +346,7 @@ static struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
.set_fmt = ep93xx_i2s_set_dai_fmt,
};
-#define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
- SNDRV_PCM_FMTBIT_S24_LE | \
- SNDRV_PCM_FMTBIT_S32_LE)
+#define EP93XX_I2S_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
static struct snd_soc_dai_driver ep93xx_i2s_dai = {
.symmetric_rates= 1,
@@ -352,13 +355,13 @@ static struct snd_soc_dai_driver ep93xx_i2s_dai = {
.playback = {
.channels_min = 2,
.channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_48000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.formats = EP93XX_I2S_FORMATS,
},
.capture = {
.channels_min = 2,
.channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_48000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.formats = EP93XX_I2S_FORMATS,
},
.ops = &ep93xx_i2s_dai_ops,
OpenPOWER on IntegriCloud