Example #1
0
static int max98925_set_clock(struct max98925_priv *max98925, unsigned int rate)
{
	unsigned int clock;
	unsigned int mdll;
	unsigned int n;
	unsigned int m;
	u8 dai_sr = 0;

	switch (max98925->sysclk) {
	case 6000000:
		clock = 0;
		mdll  = MAX98925_MDLL_MULT_MCLKx16;
		break;
	case 11289600:
		clock = 1;
		mdll  = MAX98925_MDLL_MULT_MCLKx8;
		break;
	case 12000000:
		clock = 0;
		mdll  = MAX98925_MDLL_MULT_MCLKx8;
		break;
	case 12288000:
		clock = 2;
		mdll  = MAX98925_MDLL_MULT_MCLKx8;
		break;
	default:
		dev_info(max98925->codec->dev, "unsupported sysclk %d\n",
					max98925->sysclk);
		return -EINVAL;
	}

	if (max98925_rate_value(rate, clock, &dai_sr, &n, &m))
		return -EINVAL;

	/*
	 * 1. set DAI_SR to correct LRCLK frequency
	 */
	regmap_update_bits(max98925->regmap, MAX98925_R01B_DAI_CLK_MODE2,
			MAX98925_DAI_SR_MASK, dai_sr << MAX98925_DAI_SR_SHIFT);
	/*
	 * 2. set DAI m divider
	 */
	regmap_write(max98925->regmap, MAX98925_R01C_DAI_CLK_DIV_M_MSBS,
			m >> 8);
	regmap_write(max98925->regmap, MAX98925_R01D_DAI_CLK_DIV_M_LSBS,
			m & 0xFF);
	/*
	 * 3. set DAI n divider
	 */
	regmap_write(max98925->regmap, MAX98925_R01E_DAI_CLK_DIV_N_MSBS,
			n >> 8);
	regmap_write(max98925->regmap, MAX98925_R01F_DAI_CLK_DIV_N_LSBS,
			n & 0xFF);
	/*
	 * 4. set MDLL
	 */
	regmap_update_bits(max98925->regmap, MAX98925_R01A_DAI_CLK_MODE1,
			MAX98925_MDLL_MULT_MASK, mdll << MAX98925_MDLL_MULT_SHIFT);

	return 0;
}
Example #2
0
static int max98925_set_clock(struct max98925_priv *max98925,
		struct snd_pcm_hw_params *params)
{
	unsigned int dai_sr = 0, clock, mdll, n, m;
	struct snd_soc_codec *codec = max98925->codec;
	int rate = params_rate(params);
	/* BCLK/LRCLK ratio calculation */
	int blr_clk_ratio = params_channels(params) * max98925->ch_size;

	switch (blr_clk_ratio) {
	case 32:
		regmap_update_bits(max98925->regmap,
			MAX98925_DAI_CLK_MODE2,
			M98925_DAI_BSEL_MASK, M98925_DAI_BSEL_32);
		break;
	case 48:
		regmap_update_bits(max98925->regmap,
			MAX98925_DAI_CLK_MODE2,
			M98925_DAI_BSEL_MASK, M98925_DAI_BSEL_48);
		break;
	case 64:
		regmap_update_bits(max98925->regmap,
			MAX98925_DAI_CLK_MODE2,
			M98925_DAI_BSEL_MASK, M98925_DAI_BSEL_64);
		break;
	default:
		return -EINVAL;
	}

	switch (max98925->sysclk) {
	case 6000000:
		clock = 0;
		mdll  = M98925_MDLL_MULT_MCLKx16;
		break;
	case 11289600:
		clock = 1;
		mdll  = M98925_MDLL_MULT_MCLKx8;
		break;
	case 12000000:
		clock = 0;
		mdll  = M98925_MDLL_MULT_MCLKx8;
		break;
	case 12288000:
		clock = 2;
		mdll  = M98925_MDLL_MULT_MCLKx8;
		break;
	default:
		dev_info(max98925->codec->dev, "unsupported sysclk %d\n",
					max98925->sysclk);
		return -EINVAL;
	}

	if (max98925_rate_value(codec, rate, clock, &dai_sr, &n, &m))
		return -EINVAL;

	/* set DAI_SR to correct LRCLK frequency */
	regmap_update_bits(max98925->regmap,
			MAX98925_DAI_CLK_MODE2,
			M98925_DAI_SR_MASK, dai_sr << M98925_DAI_SR_SHIFT);
	/* set DAI m divider */
	regmap_write(max98925->regmap,
		MAX98925_DAI_CLK_DIV_M_MSBS, m >> 8);
	regmap_write(max98925->regmap,
		MAX98925_DAI_CLK_DIV_M_LSBS, m & 0xFF);
	/* set DAI n divider */
	regmap_write(max98925->regmap,
		MAX98925_DAI_CLK_DIV_N_MSBS, n >> 8);
	regmap_write(max98925->regmap,
		MAX98925_DAI_CLK_DIV_N_LSBS, n & 0xFF);
	/* set MDLL */
	regmap_update_bits(max98925->regmap, MAX98925_DAI_CLK_MODE1,
			M98925_MDLL_MULT_MASK, mdll << M98925_MDLL_MULT_SHIFT);
	return 0;
}