Пример #1
0
static inline int kirkwood_set_rate(struct kirkwood_dma_data* priv,
				     unsigned long rate)
{
	int ret = -EINVAL;
	/* First check if ext clk is available */
	if (!IS_ERR(priv->extclk)) {
		/* use optional external clk for other rates */
		printk (">>> %s :: extclk set rate = %lu -> %lu\n",
			__FUNCTION__, rate, 256*rate);
		ret = clk_set_rate(priv->extclk, 256*rate);
		if (!ret) writel(KIRKWOOD_MCLK_SOURCE_EXTCLK,
				priv->io+KIRKWOOD_CLOCKS_CTRL);
	}
	if (ret && (rate == 44100 || rate == 48000 || rate == 96000)) {
		/* use internal dco for supported rates */
		printk (">>> %s :: dco set rate = %lu\n", 
			__FUNCTION__, rate);
		ret = kirkwood_set_dco(priv->io, rate);
		if (!ret) writel(KIRKWOOD_MCLK_SOURCE_DCO, 
			priv->io+KIRKWOOD_CLOCKS_CTRL);
	}
	return ret;
}
Пример #2
0
static void kirkwood_set_rate(struct snd_soc_dai *dai,
	struct kirkwood_dma_data *priv, unsigned long rate)
{
	uint32_t clks_ctrl;

	if (IS_ERR(priv->extclk)) {
		/* use internal dco for the supported rates
		 * defined in kirkwood_i2s_dai */
		dev_dbg(dai->dev, "%s: dco set rate = %lu\n",
			__func__, rate);
		kirkwood_set_dco(priv->io, rate);

		clks_ctrl = KIRKWOOD_MCLK_SOURCE_DCO;
	} else {
		/* use the external clock for the other rates
		 * defined in kirkwood_i2s_dai_extclk */
		dev_dbg(dai->dev, "%s: extclk set rate = %lu -> %lu\n",
			__func__, rate, 256 * rate);
		clk_set_rate(priv->extclk, 256 * rate);

		clks_ctrl = KIRKWOOD_MCLK_SOURCE_EXTCLK;
	}
	writel(clks_ctrl, priv->io + KIRKWOOD_CLOCKS_CTRL);
}
Пример #3
0
static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
                                  struct snd_pcm_hw_params *params,
                                  struct snd_soc_dai *dai)
{
    struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
    unsigned int i2s_reg, reg;
    unsigned long i2s_value, value;

    if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
        i2s_reg = KIRKWOOD_I2S_PLAYCTL;
        reg = KIRKWOOD_PLAYCTL;
    } else {
        i2s_reg = KIRKWOOD_I2S_RECCTL;
        reg = KIRKWOOD_RECCTL;
    }

    /* set dco conf */
    kirkwood_set_dco(priv->io, params_rate(params));

    i2s_value = readl(priv->io+i2s_reg);
    i2s_value &= ~KIRKWOOD_I2S_CTL_SIZE_MASK;

    value = readl(priv->io+reg);
    value &= ~KIRKWOOD_PLAYCTL_SIZE_MASK;

    /*
     * Size settings in play/rec i2s control regs and play/rec control
     * regs must be the same.
     */
    switch (params_format(params)) {
    case SNDRV_PCM_FORMAT_S16_LE:
        i2s_value |= KIRKWOOD_I2S_CTL_SIZE_16;
        value |= KIRKWOOD_PLAYCTL_SIZE_16_C;
        break;
    /*
     * doesn't work... S20_3LE != kirkwood 20bit format ?
     *
    case SNDRV_PCM_FORMAT_S20_3LE:
    	i2s_value |= KIRKWOOD_I2S_CTL_SIZE_20;
    	value |= KIRKWOOD_PLAYCTL_SIZE_20;
    	break;
    */
    case SNDRV_PCM_FORMAT_S24_LE:
        i2s_value |= KIRKWOOD_I2S_CTL_SIZE_24;
        value |= KIRKWOOD_PLAYCTL_SIZE_24;
        break;
    case SNDRV_PCM_FORMAT_S32_LE:
        i2s_value |= KIRKWOOD_I2S_CTL_SIZE_32;
        value |= KIRKWOOD_PLAYCTL_SIZE_32;
        break;
    default:
        return -EINVAL;
    }

    if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
        value &= ~KIRKWOOD_PLAYCTL_MONO_MASK;
        if (params_channels(params) == 1)
            value |= KIRKWOOD_PLAYCTL_MONO_BOTH;
        else
            value |= KIRKWOOD_PLAYCTL_MONO_OFF;
    }

    writel(i2s_value, priv->io+i2s_reg);
    writel(value, priv->io+reg);

    return 0;
}