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

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.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent ff0035e4
......@@ -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[] = {
......
......@@ -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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment