Unverified Commit 0c48a653 authored by derek.fang's avatar derek.fang Committed by Mark Brown
Browse files

ASoC: rt5682: Enable PLL2 function



Enable RT5682 PLL2 function to implement the more complex
frequency conversion.

Signed-off-by: default avatarderek.fang <derek.fang@realtek.com>
Link: https://lore.kernel.org/r/1581577510-1807-1-git-send-email-derek.fang@realtek.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent ff0035e4
Loading
Loading
Loading
Loading
+166 −45
Original line number Diff line number Diff line
@@ -64,9 +64,9 @@ struct rt5682_priv {
	int bclk[RT5682_AIFS];
	int master[RT5682_AIFS];

	int pll_src;
	int pll_in;
	int pll_out;
	int pll_src[RT5682_PLLS];
	int pll_in[RT5682_PLLS];
	int pll_out[RT5682_PLLS];

	int jack_type;
};
@@ -75,6 +75,7 @@ static const struct reg_sequence patch_list[] = {
	{RT5682_HP_IMP_SENS_CTRL_19, 0x1000},
	{RT5682_DAC_ADC_DIG_VOL1, 0xa020},
	{RT5682_I2C_CTRL, 0x000f},
	{RT5682_PLL2_INTERNAL, 0x8266},
};

static const struct reg_default rt5682_reg[] = {
@@ -222,7 +223,7 @@ static const struct reg_default rt5682_reg[] = {
	{0x0148, 0x0000},
	{0x0149, 0x0000},
	{0x0150, 0x79a1},
	{0x0151, 0x0000},
	{0x0156, 0xaaaa},
	{0x0160, 0x4ec0},
	{0x0161, 0x0080},
	{0x0162, 0x0200},
@@ -1298,6 +1299,21 @@ static int is_sys_clk_from_pll1(struct snd_soc_dapm_widget *w,
		return 0;
}

static int is_sys_clk_from_pll2(struct snd_soc_dapm_widget *w,
			 struct snd_soc_dapm_widget *sink)
{
	unsigned int val;
	struct snd_soc_component *component =
		snd_soc_dapm_to_component(w->dapm);

	val = snd_soc_component_read32(component, RT5682_GLB_CLK);
	val &= RT5682_SCLK_SRC_MASK;
	if (val == RT5682_SCLK_SRC_PLL2)
		return 1;
	else
		return 0;
}

static int is_using_asrc(struct snd_soc_dapm_widget *w,
			 struct snd_soc_dapm_widget *sink)
{
@@ -1612,9 +1628,11 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = {
	SND_SOC_DAPM_SUPPLY("PLL2B", RT5682_PWR_ANLG_3, RT5682_PWR_PLL2B_BIT,
		0, NULL, 0),
	SND_SOC_DAPM_SUPPLY("PLL2F", RT5682_PWR_ANLG_3, RT5682_PWR_PLL2F_BIT,
		0, NULL, 0),
		0, set_filter_clk, SND_SOC_DAPM_PRE_PMU),
	SND_SOC_DAPM_SUPPLY("Vref1", RT5682_PWR_ANLG_1, RT5682_PWR_VREF1_BIT, 0,
		rt5655_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
	SND_SOC_DAPM_SUPPLY("Vref2", RT5682_PWR_ANLG_1, RT5682_PWR_VREF2_BIT, 0,
		NULL, 0),

	/* ASRC */
	SND_SOC_DAPM_SUPPLY_S("DAC STO1 ASRC", 1, RT5682_PLL_TRACK_1,
@@ -1796,7 +1814,11 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = {
static const struct snd_soc_dapm_route rt5682_dapm_routes[] = {
	/*PLL*/
	{"ADC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll1},
	{"ADC Stereo1 Filter", NULL, "PLL2B", is_sys_clk_from_pll2},
	{"ADC Stereo1 Filter", NULL, "PLL2F", is_sys_clk_from_pll2},
	{"DAC Stereo1 Filter", NULL, "PLL1", is_sys_clk_from_pll1},
	{"DAC Stereo1 Filter", NULL, "PLL2B", is_sys_clk_from_pll2},
	{"DAC Stereo1 Filter", NULL, "PLL2F", is_sys_clk_from_pll2},

	/*ASRC*/
	{"ADC Stereo1 Filter", NULL, "ADC STO1 ASRC", is_using_asrc},
@@ -2053,8 +2075,10 @@ static int rt5682_hw_params(struct snd_pcm_substream *substream,
			RT5682_I2S1_DL_MASK, len_1);
		if (rt5682->master[RT5682_AIF1]) {
			snd_soc_component_update_bits(component,
				RT5682_ADDA_CLK_1, RT5682_I2S_M_DIV_MASK,
				pre_div << RT5682_I2S_M_DIV_SFT);
				RT5682_ADDA_CLK_1, RT5682_I2S_M_DIV_MASK |
				RT5682_I2S_CLK_SRC_MASK,
				pre_div << RT5682_I2S_M_DIV_SFT |
				(rt5682->sysclk_src) << RT5682_I2S_CLK_SRC_SFT);
		}
		if (params_channels(params) == 1) /* mono mode */
			snd_soc_component_update_bits(component,
@@ -2227,40 +2251,103 @@ static int rt5682_set_component_pll(struct snd_soc_component *component,
		unsigned int freq_out)
{
	struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
	struct rl6231_pll_code pll_code;
	struct rl6231_pll_code pll_code, pll2f_code, pll2b_code;
	unsigned int pll2_fout1;
	int ret;

	if (source == rt5682->pll_src && freq_in == rt5682->pll_in &&
	    freq_out == rt5682->pll_out)
	if (source == rt5682->pll_src[pll_id] &&
	    freq_in == rt5682->pll_in[pll_id] &&
	    freq_out == rt5682->pll_out[pll_id])
		return 0;

	if (!freq_in || !freq_out) {
		dev_dbg(component->dev, "PLL disabled\n");

		rt5682->pll_in = 0;
		rt5682->pll_out = 0;
		rt5682->pll_in[pll_id] = 0;
		rt5682->pll_out[pll_id] = 0;
		snd_soc_component_update_bits(component, RT5682_GLB_CLK,
			RT5682_SCLK_SRC_MASK, RT5682_SCLK_SRC_MCLK);
		return 0;
	}

	if (pll_id == RT5682_PLL2) {
		switch (source) {
		case RT5682_PLL2_S_MCLK:
			snd_soc_component_update_bits(component,
				RT5682_GLB_CLK, RT5682_PLL2_SRC_MASK,
				RT5682_PLL2_SRC_MCLK);
			break;
		default:
			dev_err(component->dev, "Unknown PLL2 Source %d\n",
				source);
			return -EINVAL;
		}

		/**
		 * PLL2 concatenates 2 PLL units.
		 * We suggest the Fout of the front PLL is 3.84MHz.
		 */
		pll2_fout1 = 3840000;
		ret = rl6231_pll_calc(freq_in, pll2_fout1, &pll2f_code);
		if (ret < 0) {
			dev_err(component->dev, "Unsupport input clock %d\n",
				freq_in);
			return ret;
		}
		dev_dbg(component->dev, "PLL2F: fin=%d fout=%d bypass=%d m=%d n=%d k=%d\n",
			freq_in, pll2_fout1,
			pll2f_code.m_bp,
			(pll2f_code.m_bp ? 0 : pll2f_code.m_code),
			pll2f_code.n_code, pll2f_code.k_code);

		ret = rl6231_pll_calc(pll2_fout1, freq_out, &pll2b_code);
		if (ret < 0) {
			dev_err(component->dev, "Unsupport input clock %d\n",
				pll2_fout1);
			return ret;
		}
		dev_dbg(component->dev, "PLL2B: fin=%d fout=%d bypass=%d m=%d n=%d k=%d\n",
			pll2_fout1, freq_out,
			pll2b_code.m_bp,
			(pll2b_code.m_bp ? 0 : pll2b_code.m_code),
			pll2b_code.n_code, pll2b_code.k_code);

		snd_soc_component_write(component, RT5682_PLL2_CTRL_1,
			pll2f_code.k_code << RT5682_PLL2F_K_SFT |
			pll2b_code.k_code << RT5682_PLL2B_K_SFT |
			pll2b_code.m_code);
		snd_soc_component_write(component, RT5682_PLL2_CTRL_2,
			pll2f_code.m_code << RT5682_PLL2F_M_SFT |
			pll2b_code.n_code);
		snd_soc_component_write(component, RT5682_PLL2_CTRL_3,
			pll2f_code.n_code << RT5682_PLL2F_N_SFT);
		snd_soc_component_update_bits(component, RT5682_PLL2_CTRL_4,
			RT5682_PLL2B_M_BP_MASK | RT5682_PLL2F_M_BP_MASK | 0xf,
			(pll2b_code.m_bp ? 1 : 0) << RT5682_PLL2B_M_BP_SFT |
			(pll2f_code.m_bp ? 1 : 0) << RT5682_PLL2F_M_BP_SFT |
			0xf);
	} else {
		switch (source) {
		case RT5682_PLL1_S_MCLK:
		snd_soc_component_update_bits(component, RT5682_GLB_CLK,
			RT5682_PLL1_SRC_MASK, RT5682_PLL1_SRC_MCLK);
			snd_soc_component_update_bits(component,
				RT5682_GLB_CLK, RT5682_PLL1_SRC_MASK,
				RT5682_PLL1_SRC_MCLK);
			break;
		case RT5682_PLL1_S_BCLK1:
		snd_soc_component_update_bits(component, RT5682_GLB_CLK,
				RT5682_PLL1_SRC_MASK, RT5682_PLL1_SRC_BCLK1);
			snd_soc_component_update_bits(component,
				RT5682_GLB_CLK, RT5682_PLL1_SRC_MASK,
				RT5682_PLL1_SRC_BCLK1);
			break;
		default:
		dev_err(component->dev, "Unknown PLL Source %d\n", source);
			dev_err(component->dev, "Unknown PLL1 Source %d\n",
				source);
			return -EINVAL;
		}

		ret = rl6231_pll_calc(freq_in, freq_out, &pll_code);
		if (ret < 0) {
		dev_err(component->dev, "Unsupport input clock %d\n", freq_in);
			dev_err(component->dev, "Unsupport input clock %d\n",
				freq_in);
			return ret;
		}

@@ -2273,15 +2360,48 @@ static int rt5682_set_component_pll(struct snd_soc_component *component,
		snd_soc_component_write(component, RT5682_PLL_CTRL_2,
		    (pll_code.m_bp ? 0 : pll_code.m_code) << RT5682_PLL_M_SFT |
		    pll_code.m_bp << RT5682_PLL_M_BP_SFT | RT5682_PLL_RST);
	}

	rt5682->pll_in[pll_id] = freq_in;
	rt5682->pll_out[pll_id] = freq_out;
	rt5682->pll_src[pll_id] = source;

	return 0;
}

static int rt5682_set_bclk1_ratio(struct snd_soc_dai *dai, unsigned int ratio)
{
	struct snd_soc_component *component = dai->component;
	struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);

	rt5682->bclk[dai->id] = ratio;

	rt5682->pll_in = freq_in;
	rt5682->pll_out = freq_out;
	rt5682->pll_src = source;
	switch (ratio) {
	case 256:
		snd_soc_component_update_bits(component, RT5682_TDM_TCON_CTRL,
			RT5682_TDM_BCLK_MS1_MASK, RT5682_TDM_BCLK_MS1_256);
		break;
	case 128:
		snd_soc_component_update_bits(component, RT5682_TDM_TCON_CTRL,
			RT5682_TDM_BCLK_MS1_MASK, RT5682_TDM_BCLK_MS1_128);
		break;
	case 64:
		snd_soc_component_update_bits(component, RT5682_TDM_TCON_CTRL,
			RT5682_TDM_BCLK_MS1_MASK, RT5682_TDM_BCLK_MS1_64);
		break;
	case 32:
		snd_soc_component_update_bits(component, RT5682_TDM_TCON_CTRL,
			RT5682_TDM_BCLK_MS1_MASK, RT5682_TDM_BCLK_MS1_32);
		break;
	default:
		dev_err(dai->dev, "Invalid bclk1 ratio %d\n", ratio);
		return -EINVAL;
	}

	return 0;
}

static int rt5682_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
static int rt5682_set_bclk2_ratio(struct snd_soc_dai *dai, unsigned int ratio)
{
	struct snd_soc_component *component = dai->component;
	struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
@@ -2300,7 +2420,7 @@ static int rt5682_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
			RT5682_I2S2_BCLK_MS2_32);
		break;
	default:
		dev_err(dai->dev, "Invalid bclk ratio %d\n", ratio);
		dev_err(dai->dev, "Invalid bclk2 ratio %d\n", ratio);
		return -EINVAL;
	}

@@ -2389,12 +2509,13 @@ static const struct snd_soc_dai_ops rt5682_aif1_dai_ops = {
	.hw_params = rt5682_hw_params,
	.set_fmt = rt5682_set_dai_fmt,
	.set_tdm_slot = rt5682_set_tdm_slot,
	.set_bclk_ratio = rt5682_set_bclk1_ratio,
};

static const struct snd_soc_dai_ops rt5682_aif2_dai_ops = {
	.hw_params = rt5682_hw_params,
	.set_fmt = rt5682_set_dai_fmt,
	.set_bclk_ratio = rt5682_set_bclk_ratio,
	.set_bclk_ratio = rt5682_set_bclk2_ratio,
};

static struct snd_soc_dai_driver rt5682_dai[] = {
+37 −2
Original line number Diff line number Diff line
@@ -177,7 +177,7 @@
#define RT5682_TEST_MODE_CTRL_4			0x0148
#define RT5682_TEST_MODE_CTRL_5			0x0149
#define RT5682_PLL1_INTERNAL			0x0150
#define RT5682_PLL2_INTERNAL			0x0151
#define RT5682_PLL2_INTERNAL			0x0156
#define RT5682_STO_NG2_CTRL_1			0x0160
#define RT5682_STO_NG2_CTRL_2			0x0161
#define RT5682_STO_NG2_CTRL_3			0x0162
@@ -738,7 +738,7 @@
#define RT5682_ADC_OSR_D_24			(0x7 << 12)
#define RT5682_ADC_OSR_D_32			(0x8 << 12)
#define RT5682_ADC_OSR_D_48			(0x9 << 12)
#define RT5682_I2S_M_DIV_MASK			(0xf << 12)
#define RT5682_I2S_M_DIV_MASK			(0xf << 8)
#define RT5682_I2S_M_DIV_SFT			8
#define RT5682_I2S_M_D_1			(0x0 << 8)
#define RT5682_I2S_M_D_2			(0x1 << 8)
@@ -820,6 +820,12 @@
#define RT5682_TDM_DF_PCM_B			(0x3 << 11)
#define RT5682_TDM_DF_PCM_A_N			(0x6 << 11)
#define RT5682_TDM_DF_PCM_B_N			(0x7 << 11)
#define RT5682_TDM_BCLK_MS1_MASK		(0x3 << 9)
#define RT5682_TDM_BCLK_MS1_SFT			9
#define RT5682_TDM_BCLK_MS1_32			(0x0 << 9)
#define RT5682_TDM_BCLK_MS1_64			(0x1 << 9)
#define RT5682_TDM_BCLK_MS1_128			(0x2 << 9)
#define RT5682_TDM_BCLK_MS1_256			(0x3 << 9)
#define RT5682_TDM_CL_MASK			(0x3 << 4)
#define RT5682_TDM_CL_16			(0x0 << 4)
#define RT5682_TDM_CL_20			(0x1 << 4)
@@ -1049,6 +1055,28 @@
#define RT5682_PWR_CLK1M_PD			(0x0 << 8)
#define RT5682_PWR_CLK1M_PU			(0x1 << 8)

/* PLL2 M/N/K Code Control 1 (0x009b) */
#define RT5682_PLL2F_K_MASK			(0x1f << 8)
#define RT5682_PLL2F_K_SFT			8
#define RT5682_PLL2B_K_MASK			(0xf << 4)
#define RT5682_PLL2B_K_SFT			4
#define RT5682_PLL2B_M_MASK			(0xf << 0)

/* PLL2 M/N/K Code Control 2 (0x009c) */
#define RT5682_PLL2F_M_MASK			(0x3f << 8)
#define RT5682_PLL2F_M_SFT			8
#define RT5682_PLL2B_N_MASK			(0x3f << 0)

/* PLL2 M/N/K Code Control 2 (0x009d) */
#define RT5682_PLL2F_N_MASK			(0x7f << 8)
#define RT5682_PLL2F_N_SFT			8

/* PLL2 M/N/K Code Control 2 (0x009e) */
#define RT5682_PLL2B_M_BP_MASK			(0x1 << 11)
#define RT5682_PLL2B_M_BP_SFT			11
#define RT5682_PLL2F_M_BP_MASK			(0x1 << 7)
#define RT5682_PLL2F_M_BP_SFT			7

/* RC Clock Control (0x009f) */
#define RT5682_POW_IRQ				(0x1 << 15)
#define RT5682_POW_JDH				(0x1 << 14)
@@ -1315,6 +1343,13 @@ enum {
	RT5682_PLL1_S_MCLK,
	RT5682_PLL1_S_BCLK1,
	RT5682_PLL1_S_RCCLK,
	RT5682_PLL2_S_MCLK,
};

enum {
	RT5682_PLL1,
	RT5682_PLL2,
	RT5682_PLLS,
};

enum {