static int tegra_i2s_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 tegra_i2s *i2s = snd_soc_dai_get_drvdata(dai); u32 reg; int ret, sample_size, srate, i2sclock, bitcnt; i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_BIT_SIZE_MASK; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_16; sample_size = 16; break; case SNDRV_PCM_FORMAT_S24_LE: i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_24; sample_size = 24; break; case SNDRV_PCM_FORMAT_S32_LE: i2s->reg_ctrl |= TEGRA_I2S_CTRL_BIT_SIZE_32; sample_size = 32; break; default: return -EINVAL; } srate = params_rate(params); /* Final "* 2" required by Tegra hardware */ i2sclock = srate * params_channels(params) * sample_size * 2; ret = clk_set_rate(i2s->clk_i2s, i2sclock); if (ret) { dev_err(dev, "Can't set I2S clock rate: %d\n", ret); return ret; } bitcnt = (i2sclock / (2 * srate)) - 1; if (bitcnt < 0 || bitcnt > TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_MASK_US) return -EINVAL; reg = bitcnt << TEGRA_I2S_TIMING_CHANNEL_BIT_COUNT_SHIFT; if (i2sclock % (2 * srate)) reg |= TEGRA_I2S_TIMING_NON_SYM_ENABLE; if (!i2s->clk_refs) clk_enable(i2s->clk_i2s); tegra_i2s_write(i2s, TEGRA_I2S_TIMING, reg); tegra_i2s_write(i2s, TEGRA_I2S_FIFO_SCR, TEGRA_I2S_FIFO_SCR_FIFO2_ATN_LVL_FOUR_SLOTS | TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_FOUR_SLOTS); if (!i2s->clk_refs) clk_disable(i2s->clk_i2s); return 0; }
static void tegra_i2s_stop_capture(struct tegra_i2s *i2s) { i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_FIFO2_ENABLE; tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl); }
static void tegra_i2s_stop_playback(struct tegra_i2s *i2s) { i2s->reg_ctrl &= ~TEGRA_I2S_CTRL_FIFO1_ENABLE; tegra_i2s_write(i2s, TEGRA_I2S_CTRL, i2s->reg_ctrl); }