summaryrefslogtreecommitdiff
path: root/sound/soc/tegra/tegra30_i2s.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/tegra/tegra30_i2s.c')
-rw-r--r--sound/soc/tegra/tegra30_i2s.c238
1 files changed, 4 insertions, 234 deletions
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index c2750bfbef64..02d1038ea36e 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -36,7 +36,6 @@
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/io.h>
-#include <linux/delay.h>
#include <mach/iomap.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -281,194 +280,6 @@ static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai,
return 0;
}
-static void tegra30_i2s_set_channel_bit_count(struct tegra30_i2s *i2s,
- int i2sclock, int srate)
-{
- int sym_bitclk, bitcnt;
- u32 val;
-
- bitcnt = (i2sclock / (2 * srate)) - 1;
- sym_bitclk = !(i2sclock % (2 * srate));
-
- val = bitcnt << TEGRA30_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT;
-
- if (!sym_bitclk)
- val |= TEGRA30_I2S_TIMING_NON_SYM_ENABLE;
-
- tegra30_i2s_write(i2s, TEGRA30_I2S_TIMING, val);
-}
-
-static void tegra30_i2s_set_data_offset(struct tegra30_i2s *i2s)
-{
- u32 val;
- int rx_data_offset = i2s->dsp_config.rx_data_offset;
- int tx_data_offset = i2s->dsp_config.tx_data_offset;
-
- val = (rx_data_offset <<
- TEGRA30_I2S_OFFSET_RX_DATA_OFFSET_SHIFT) |
- (tx_data_offset <<
- TEGRA30_I2S_OFFSET_TX_DATA_OFFSET_SHIFT);
-
- tegra30_i2s_write(i2s, TEGRA30_I2S_OFFSET, val);
-}
-
-static void tegra30_i2s_set_slot_control(struct tegra30_i2s *i2s, int stream)
-{
- u32 val;
- int tx_mask = i2s->dsp_config.tx_mask;
- int rx_mask = i2s->dsp_config.rx_mask;
-
- val = tegra30_i2s_read(i2s, TEGRA30_I2S_SLOT_CTRL);
- if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- val &= ~TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_MASK;
- val |= (tx_mask << TEGRA30_I2S_SLOT_CTRL_TX_SLOT_ENABLES_SHIFT);
- } else {
- val &= ~TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_MASK;
- val |= (rx_mask << TEGRA30_I2S_SLOT_CTRL_RX_SLOT_ENABLES_SHIFT);
- }
-
- val &= ~TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_MASK;
- val |= (i2s->dsp_config.num_slots - 1)
- << TEGRA30_I2S_SLOT_CTRL_TOTAL_SLOTS_SHIFT;
-
- tegra30_i2s_write(i2s, TEGRA30_I2S_SLOT_CTRL, val);
-}
-
-static int tegra30_i2s_tdm_setup_clocks(struct device *dev,
- struct tegra30_i2s *i2s, int *i2sclock)
-{
- int ret;
-
- if (i2s->reg_ctrl & TEGRA30_I2S_CTRL_MASTER_ENABLE) {
-
- ret = clk_set_parent(i2s->clk_i2s, i2s->clk_pll_a_out0);
- if (ret) {
- dev_err(dev, "Can't set parent of I2S clock\n");
- return ret;
- }
- ret = clk_set_rate(i2s->clk_i2s, *i2sclock);
- if (ret) {
- dev_err(dev, "Can't set I2S clock rate: %d\n", ret);
- return ret;
- }
- } else {
-
- ret = clk_set_rate(i2s->clk_i2s_sync, *i2sclock);
- if (ret) {
- dev_err(dev, "Can't set I2S sync clock rate\n");
- return ret;
- }
-
- ret = clk_set_rate(i2s->clk_audio_2x, *i2sclock);
- if (ret) {
- dev_err(dev, "Can't set audio2x clock rate\n");
- return ret;
- }
-
- ret = clk_set_parent(i2s->clk_i2s, i2s->clk_audio_2x);
- if (ret) {
- dev_err(dev, "Can't set parent of audio2x clock\n");
- return ret;
- }
- }
- return ret;
-}
-
-
-static int tegra30_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct device *dev = substream->pcm->card->dev;
- struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(dai);
- u32 val;
- int i2s_client_ch, i2s_audio_ch, i2s_audio_bits, i2s_client_bits;
- int i2sclock, srate;
- int ret;
-
- srate = params_rate(params);
-
- i2sclock = srate *
- i2s->dsp_config.num_slots *
- i2s->dsp_config.slot_width;
-
- ret = tegra30_i2s_tdm_setup_clocks(dev, i2s, &i2sclock);
- if (ret)
- return -EINVAL;
-
- /* Run ahub clock greater than i2sclock */
- tegra30_ahub_clock_set_rate(i2sclock*2);
-
- tegra30_i2s_enable_clocks(i2s);
-
- tegra30_i2s_set_channel_bit_count(i2s, i2sclock*2, srate);
-
- i2s_client_ch = i2s->dsp_config.num_slots;
- i2s_audio_ch = i2s->dsp_config.num_slots;
-
- i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_BIT_SIZE_MASK;
- switch (i2s->dsp_config.slot_width) {
- case 16:
- i2s_audio_bits = TEGRA30_AUDIOCIF_BITS_16;
- i2s_client_bits = TEGRA30_AUDIOCIF_BITS_16;
- i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_16;
- break;
- case 32:
- i2s_audio_bits = TEGRA30_AUDIOCIF_BITS_32;
- i2s_client_bits = TEGRA30_AUDIOCIF_BITS_32;
- i2s->reg_ctrl |= TEGRA30_I2S_CTRL_BIT_SIZE_32;
- break;
- }
-
- val = (0 << TEGRA30_AUDIOCIF_CTRL_FIFO_THRESHOLD_SHIFT) |
- ((i2s_audio_ch - 1) <<
- TEGRA30_AUDIOCIF_CTRL_AUDIO_CHANNELS_SHIFT) |
- ((i2s_client_ch - 1) <<
- TEGRA30_AUDIOCIF_CTRL_CLIENT_CHANNELS_SHIFT) |
- (i2s_audio_bits <<
- TEGRA30_AUDIOCIF_CTRL_AUDIO_BITS_SHIFT) |
- (i2s_client_bits <<
- TEGRA30_AUDIOCIF_CTRL_CLIENT_BITS_SHIFT);
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_RX;
- tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_RX_CTRL, val);
-
- tegra30_ahub_set_tx_cif_channels(i2s->txcif,
- i2s_audio_ch,
- i2s_client_ch);
- tegra30_ahub_set_tx_cif_bits(i2s->txcif,
- i2s_audio_bits,
- i2s_client_bits);
- tegra30_ahub_set_tx_fifo_pack_mode(i2s->txcif, 0);
-
- } else {
- val |= TEGRA30_AUDIOCIF_CTRL_DIRECTION_TX;
- tegra30_i2s_write(i2s, TEGRA30_I2S_CIF_TX_CTRL, val);
-
- tegra30_ahub_set_rx_cif_channels(i2s->rxcif,
- i2s_audio_ch,
- i2s_client_ch);
- tegra30_ahub_set_rx_cif_bits(i2s->rxcif,
- i2s_audio_bits,
- i2s_client_bits);
- tegra30_ahub_set_rx_fifo_pack_mode(i2s->rxcif, 0);
- }
-
- tegra30_i2s_set_slot_control(i2s, substream->stream);
-
- tegra30_i2s_set_data_offset(i2s);
-
- i2s->reg_ch_ctrl &= ~TEGRA30_I2S_CH_CTRL_FSYNC_WIDTH_MASK;
- i2s->reg_ch_ctrl |= (i2s->dsp_config.slot_width - 1) <<
- TEGRA30_I2S_CH_CTRL_FSYNC_WIDTH_SHIFT;
- tegra30_i2s_write(i2s, TEGRA30_I2S_CH_CTRL, i2s->reg_ch_ctrl);
-
- tegra30_i2s_disable_clocks(i2s);
-
- return 0;
-}
-
static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -489,12 +300,6 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- /* TDM mode */
- if ((i2s->reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC) &&
- (i2s->dsp_config.slot_width > 2))
- return tegra30_i2s_tdm_hw_params(substream, params, dai);
-
-
srate = params_rate(params);
if (i2s->reg_ctrl & TEGRA30_I2S_CTRL_MASTER_ENABLE) {
@@ -618,16 +423,12 @@ static void tegra30_i2s_start_playback(struct tegra30_i2s *i2s)
static void tegra30_i2s_stop_playback(struct tegra30_i2s *i2s)
{
- int dcnt = 10;
- /* if this is the only user of i2s tx then disable it*/
tegra30_ahub_disable_tx_fifo(i2s->txcif);
+ /* if this is the only user of i2s tx then disable it*/
if (i2s->playback_ref_count == 1) {
i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_TX;
tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
}
- while (tegra30_ahub_tx_fifo_is_busy(i2s->txcif) && dcnt--)
- udelay(100);
- tegra30_ahub_tx_fifo_clear(i2s->txcif);
}
static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s)
@@ -641,15 +442,11 @@ static void tegra30_i2s_start_capture(struct tegra30_i2s *i2s)
static void tegra30_i2s_stop_capture(struct tegra30_i2s *i2s)
{
- int dcnt = 10;
tegra30_ahub_disable_rx_fifo(i2s->rxcif);
if (!i2s->is_call_mode_rec) {
i2s->reg_ctrl &= ~TEGRA30_I2S_CTRL_XFER_EN_RX;
tegra30_i2s_write(i2s, TEGRA30_I2S_CTRL, i2s->reg_ctrl);
}
- while (tegra30_ahub_rx_fifo_is_busy(i2s->rxcif) && dcnt--)
- udelay(100);
- tegra30_ahub_rx_fifo_clear(i2s->rxcif);
}
static int tegra30_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
@@ -703,33 +500,6 @@ static int tegra30_i2s_probe(struct snd_soc_dai *dai)
tegra30_i2s_disable_clocks(i2s);
#endif
- /* Default values for DSP mode */
- i2s->dsp_config.num_slots = 1;
- i2s->dsp_config.slot_width = 2;
- i2s->dsp_config.tx_mask = 1;
- i2s->dsp_config.rx_mask = 1;
- i2s->dsp_config.rx_data_offset = 1;
- i2s->dsp_config.tx_data_offset = 1;
-
-
- return 0;
-}
-
-int tegra30_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai,
- unsigned int tx_mask,
- unsigned int rx_mask,
- int slots,
- int slot_width)
-{
- struct tegra30_i2s *i2s = snd_soc_dai_get_drvdata(cpu_dai);
-
- i2s->dsp_config.num_slots = slots;
- i2s->dsp_config.slot_width = slot_width;
- i2s->dsp_config.tx_mask = tx_mask;
- i2s->dsp_config.rx_mask = rx_mask;
- i2s->dsp_config.rx_data_offset = 0;
- i2s->dsp_config.tx_data_offset = 0;
-
return 0;
}
@@ -764,7 +534,6 @@ static struct snd_soc_dai_ops tegra30_i2s_dai_ops = {
.set_fmt = tegra30_i2s_set_fmt,
.hw_params = tegra30_i2s_hw_params,
.trigger = tegra30_i2s_trigger,
- .set_tdm_slot = tegra30_i2s_set_tdm_slot,
};
#define TEGRA30_I2S_DAI(id) \
@@ -774,13 +543,13 @@ static struct snd_soc_dai_ops tegra30_i2s_dai_ops = {
.resume = tegra30_i2s_resume, \
.playback = { \
.channels_min = 1, \
- .channels_max = 16, \
+ .channels_max = 2, \
.rates = SNDRV_PCM_RATE_8000_96000, \
.formats = SNDRV_PCM_FMTBIT_S16_LE, \
}, \
.capture = { \
.channels_min = 1, \
- .channels_max = 16, \
+ .channels_max = 2, \
.rates = SNDRV_PCM_RATE_8000_96000, \
.formats = SNDRV_PCM_FMTBIT_S16_LE, \
}, \
@@ -1058,6 +827,7 @@ static __devinit int tegra30_i2s_platform_probe(struct platform_device *pdev)
ret = PTR_ERR(i2s->clk_i2s);
goto exit;
}
+
i2s->clk_i2s_sync = clk_get(&pdev->dev, "ext_audio_sync");
if (IS_ERR(i2s->clk_i2s_sync)) {
dev_err(&pdev->dev, "Can't retrieve i2s_sync clock\n");