|
@@ -209,16 +209,9 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
|
|
|
|
|
|
switch (config->chan_nr) {
|
|
|
case EIGHT_CHANNEL_SUPPORT:
|
|
|
- ch_reg = 3;
|
|
|
- break;
|
|
|
case SIX_CHANNEL_SUPPORT:
|
|
|
- ch_reg = 2;
|
|
|
- break;
|
|
|
case FOUR_CHANNEL_SUPPORT:
|
|
|
- ch_reg = 1;
|
|
|
- break;
|
|
|
case TWO_CHANNEL_SUPPORT:
|
|
|
- ch_reg = 0;
|
|
|
break;
|
|
|
default:
|
|
|
dev_err(dev->dev, "channel not supported\n");
|
|
@@ -227,18 +220,22 @@ static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
|
|
|
|
|
|
i2s_disable_channels(dev, substream->stream);
|
|
|
|
|
|
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
|
- i2s_write_reg(dev->i2s_base, TCR(ch_reg), xfer_resolution);
|
|
|
- i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02);
|
|
|
- irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
|
|
|
- i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30);
|
|
|
- i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
|
|
|
- } else {
|
|
|
- i2s_write_reg(dev->i2s_base, RCR(ch_reg), xfer_resolution);
|
|
|
- i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07);
|
|
|
- irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
|
|
|
- i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03);
|
|
|
- i2s_write_reg(dev->i2s_base, RER(ch_reg), 1);
|
|
|
+ for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) {
|
|
|
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
|
|
+ i2s_write_reg(dev->i2s_base, TCR(ch_reg),
|
|
|
+ xfer_resolution);
|
|
|
+ i2s_write_reg(dev->i2s_base, TFCR(ch_reg), 0x02);
|
|
|
+ irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
|
|
|
+ i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30);
|
|
|
+ i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
|
|
|
+ } else {
|
|
|
+ i2s_write_reg(dev->i2s_base, RCR(ch_reg),
|
|
|
+ xfer_resolution);
|
|
|
+ i2s_write_reg(dev->i2s_base, RFCR(ch_reg), 0x07);
|
|
|
+ irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
|
|
|
+ i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03);
|
|
|
+ i2s_write_reg(dev->i2s_base, RER(ch_reg), 1);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
i2s_write_reg(dev->i2s_base, CCR, ccr);
|
|
@@ -263,6 +260,19 @@ static void dw_i2s_shutdown(struct snd_pcm_substream *substream,
|
|
|
snd_soc_dai_set_dma_data(dai, substream, NULL);
|
|
|
}
|
|
|
|
|
|
+static int dw_i2s_prepare(struct snd_pcm_substream *substream,
|
|
|
+ struct snd_soc_dai *dai)
|
|
|
+{
|
|
|
+ struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
|
|
|
+
|
|
|
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
|
|
+ i2s_write_reg(dev->i2s_base, TXFFR, 1);
|
|
|
+ else
|
|
|
+ i2s_write_reg(dev->i2s_base, RXFFR, 1);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static int dw_i2s_trigger(struct snd_pcm_substream *substream,
|
|
|
int cmd, struct snd_soc_dai *dai)
|
|
|
{
|
|
@@ -294,6 +304,7 @@ static struct snd_soc_dai_ops dw_i2s_dai_ops = {
|
|
|
.startup = dw_i2s_startup,
|
|
|
.shutdown = dw_i2s_shutdown,
|
|
|
.hw_params = dw_i2s_hw_params,
|
|
|
+ .prepare = dw_i2s_prepare,
|
|
|
.trigger = dw_i2s_trigger,
|
|
|
};
|
|
|
|