Beispiel #1
0
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;
}
Beispiel #2
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);
}
Beispiel #3
0
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);
}