msm: mdss: add support of dsi pll SSC for 8996
DSI SSC enabled through dtsi. Both down spread and center spread are supported. Default is down spread when SSC enabled. Change-Id: I4c5ef632e5442ef610444ea5439d4bb78541791b Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org>
This commit is contained in:
parent
fc534490e0
commit
f1f853212f
5 changed files with 132 additions and 16 deletions
|
@ -27,6 +27,11 @@ Optional properties:
|
|||
- label: A string used to describe the driver used.
|
||||
- vcca-supply: Phandle for vcca regulator device node.
|
||||
|
||||
|
||||
- qcom,dsi-pll-ssc-en: Boolean property to indicate that ssc is enabled.
|
||||
- qcom,dsi-pll-ssc-mode: Spread-spectrum clocking. It can be either "down-spread"
|
||||
or "center-spread". Default is "down-spread" if it is not specified.
|
||||
|
||||
- qcom,platform-supply-entries: A node that lists the elements of the supply. There
|
||||
can be more than one instance of this binding,
|
||||
in which case the entry would be appended with
|
||||
|
@ -64,6 +69,8 @@ Example:
|
|||
clock-rate = <0>, <0>, <0>;
|
||||
|
||||
qcom,dsi-pll-slave;
|
||||
qcom,dsi-pll-ssc-en:
|
||||
qcom,dsi-pll-ssc-mode = "down-spread";
|
||||
|
||||
qcom,platform-supply-entries {
|
||||
#address-cells = <1>;
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#define DSI_PLL_POLL_TIMEOUT_US 1000
|
||||
#define MSM8996_DSI_PLL_REVISION_2 2
|
||||
|
||||
#define CEIL(x, y) (((x) + ((y)-1)) / (y))
|
||||
|
||||
int set_mdss_byte_mux_sel_8996(struct mux_clk *clk, int sel)
|
||||
{
|
||||
return 0;
|
||||
|
@ -303,12 +305,13 @@ static void dsi_pll_disable(struct clk *c)
|
|||
return;
|
||||
}
|
||||
|
||||
static void mdss_dsi_pll_8996_input_init(struct dsi_pll_db *pdb)
|
||||
static void mdss_dsi_pll_8996_input_init(struct mdss_pll_resources *pll,
|
||||
struct dsi_pll_db *pdb)
|
||||
{
|
||||
pdb->in.fref = 19200000; /* 19.2 Mhz*/
|
||||
pdb->in.fdata = 0; /* bit clock rate */
|
||||
pdb->in.dsiclk_sel = 1; /* 1, reg: 0x0014 */
|
||||
pdb->in.ssc_en = 0; /* 1, reg: 0x0494, bit 0 */
|
||||
pdb->in.ssc_en = pll->ssc_en; /* 1, reg: 0x0494, bit 0 */
|
||||
pdb->in.ldo_en = 0; /* 0, reg: 0x004c, bit 0 */
|
||||
|
||||
/* fixed input */
|
||||
|
@ -319,8 +322,8 @@ static void mdss_dsi_pll_8996_input_init(struct dsi_pll_db *pdb)
|
|||
pdb->in.pll_wakeup_timer = 5; /* 5, reg: 0x043c, bit 0 - 2 */
|
||||
pdb->in.plllock_cnt = 1; /* 1, reg: 0x0488, bit 1 - 2 */
|
||||
pdb->in.plllock_rng = 0; /* 0, reg: 0x0488, bit 3 - 4 */
|
||||
pdb->in.ssc_center_spread = 0; /* 0, reg: 0x0494, bit 1 */
|
||||
pdb->in.ssc_adj_per = 37; /* 37, reg: 0x498, bit 0 - 9 */
|
||||
pdb->in.ssc_center = pll->ssc_center;/* 0, reg: 0x0494, bit 1 */
|
||||
pdb->in.ssc_adj_period = 37; /* 37, reg: 0x498, bit 0 - 9 */
|
||||
pdb->in.ssc_spread = 5; /* 0.005, 5kppm */
|
||||
pdb->in.ssc_freq = 31500; /* 31.5 khz */
|
||||
|
||||
|
@ -342,8 +345,49 @@ static void mdss_dsi_pll_8996_input_init(struct dsi_pll_db *pdb)
|
|||
pdb->in.pll_r3ctrl = 1; /* 1 */
|
||||
}
|
||||
|
||||
static void pll_8996_dec_frac_calc(struct dsi_pll_db *pdb,
|
||||
struct mdss_pll_resources *pll)
|
||||
static void pll_8996_ssc_calc(struct mdss_pll_resources *pll,
|
||||
struct dsi_pll_db *pdb)
|
||||
{
|
||||
u32 period, ssc_period;
|
||||
u32 ref, rem;
|
||||
s64 step_size;
|
||||
|
||||
pr_debug("%s: vco=%lld ref=%lld\n", __func__,
|
||||
pll->vco_current_rate, pll->vco_ref_clk_rate);
|
||||
|
||||
ssc_period = pdb->in.ssc_freq / 500;
|
||||
period = pll->vco_ref_clk_rate / 1000;
|
||||
ssc_period = CEIL(period, ssc_period);
|
||||
ssc_period -= 1;
|
||||
pdb->out.ssc_period = ssc_period;
|
||||
|
||||
pr_debug("%s: ssc, freq=%d spread=%d period=%d\n", __func__,
|
||||
pdb->in.ssc_freq, pdb->in.ssc_spread, pdb->out.ssc_period);
|
||||
|
||||
step_size = (u32)pll->vco_current_rate;
|
||||
ref = pll->vco_ref_clk_rate;
|
||||
ref /= 1000;
|
||||
step_size = div_s64(step_size, ref);
|
||||
step_size <<= 20;
|
||||
step_size = div_s64(step_size, 1000);
|
||||
step_size *= pdb->in.ssc_spread;
|
||||
step_size = div_s64(step_size, 1000);
|
||||
step_size *= (pdb->in.ssc_adj_period + 1);
|
||||
|
||||
rem = 0;
|
||||
step_size = div_s64_rem(step_size, ssc_period + 1, &rem);
|
||||
if (rem)
|
||||
step_size++;
|
||||
|
||||
pr_debug("%s: step_size=%lld\n", __func__, step_size);
|
||||
|
||||
step_size &= 0x0ffff; /* take lower 16 bits */
|
||||
|
||||
pdb->out.ssc_step_size = step_size;
|
||||
}
|
||||
|
||||
static void pll_8996_dec_frac_calc(struct mdss_pll_resources *pll,
|
||||
struct dsi_pll_db *pdb)
|
||||
{
|
||||
struct dsi_pll_input *pin = &pdb->in;
|
||||
struct dsi_pll_output *pout = &pdb->out;
|
||||
|
@ -438,9 +482,47 @@ static void pll_8996_calc_vco_count(struct dsi_pll_db *pdb,
|
|||
pout->pll_kvco_code = 0;
|
||||
}
|
||||
|
||||
static void pll_db_commit_common(void __iomem *pll_base,
|
||||
static void pll_db_commit_ssc(struct mdss_pll_resources *pll,
|
||||
struct dsi_pll_db *pdb)
|
||||
{
|
||||
void __iomem *pll_base = pll->pll_base;
|
||||
struct dsi_pll_input *pin = &pdb->in;
|
||||
struct dsi_pll_output *pout = &pdb->out;
|
||||
char data;
|
||||
|
||||
data = pin->ssc_adj_period;
|
||||
data &= 0x0ff;
|
||||
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_ADJ_PER1, data);
|
||||
data = (pin->ssc_adj_period >> 8);
|
||||
data &= 0x03;
|
||||
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_ADJ_PER2, data);
|
||||
|
||||
data = pout->ssc_period;
|
||||
data &= 0x0ff;
|
||||
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_PER1, data);
|
||||
data = (pout->ssc_period >> 8);
|
||||
data &= 0x0ff;
|
||||
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_PER2, data);
|
||||
|
||||
data = pout->ssc_step_size;
|
||||
data &= 0x0ff;
|
||||
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_STEP_SIZE1, data);
|
||||
data = (pout->ssc_step_size >> 8);
|
||||
data &= 0x0ff;
|
||||
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_STEP_SIZE2, data);
|
||||
|
||||
data = (pin->ssc_center & 0x01);
|
||||
data <<= 1;
|
||||
data |= 0x01; /* enable */
|
||||
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_SSC_EN_CENTER, data);
|
||||
|
||||
wmb(); /* make sure register committed */
|
||||
}
|
||||
|
||||
static void pll_db_commit_common(struct mdss_pll_resources *pll,
|
||||
struct dsi_pll_db *pdb)
|
||||
{
|
||||
void __iomem *pll_base = pll->pll_base;
|
||||
struct dsi_pll_input *pin = &pdb->in;
|
||||
struct dsi_pll_output *pout = &pdb->out;
|
||||
char data;
|
||||
|
@ -506,9 +588,10 @@ static void pll_db_commit_common(void __iomem *pll_base,
|
|||
MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PLL_CRCTRL, data);
|
||||
}
|
||||
|
||||
static void pll_db_commit_8996(void __iomem *pll_base,
|
||||
static void pll_db_commit_8996(struct mdss_pll_resources *pll,
|
||||
struct dsi_pll_db *pdb)
|
||||
{
|
||||
void __iomem *pll_base = pll->pll_base;
|
||||
struct dsi_pll_input *pin = &pdb->in;
|
||||
struct dsi_pll_output *pout = &pdb->out;
|
||||
char data;
|
||||
|
@ -516,7 +599,7 @@ static void pll_db_commit_8996(void __iomem *pll_base,
|
|||
data = pout->cmn_ldo_cntrl;
|
||||
MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_LDO_CNTRL, data);
|
||||
|
||||
pll_db_commit_common(pll_base, pdb);
|
||||
pll_db_commit_common(pll, pdb);
|
||||
|
||||
/* de assert pll start and apply pll sw reset */
|
||||
/* stop pll */
|
||||
|
@ -590,6 +673,9 @@ static void pll_db_commit_8996(void __iomem *pll_base,
|
|||
data = (pout->pll_n1div | (pout->pll_n2div << 4));
|
||||
MDSS_PLL_REG_W(pll_base, DSIPHY_CMN_CLK_CFG0, data);
|
||||
|
||||
if (pll->ssc_en)
|
||||
pll_db_commit_ssc(pll, pdb);
|
||||
|
||||
wmb(); /* make sure register committed */
|
||||
}
|
||||
|
||||
|
@ -691,9 +777,12 @@ int pll_vco_set_rate_8996(struct clk *c, unsigned long rate)
|
|||
pll->vco_current_rate = rate;
|
||||
pll->vco_ref_clk_rate = vco->ref_clk_rate;
|
||||
|
||||
mdss_dsi_pll_8996_input_init(pdb);
|
||||
mdss_dsi_pll_8996_input_init(pll, pdb);
|
||||
|
||||
pll_8996_dec_frac_calc(pdb, pll);
|
||||
pll_8996_dec_frac_calc(pll, pdb);
|
||||
|
||||
if (pll->ssc_en)
|
||||
pll_8996_ssc_calc(pll, pdb);
|
||||
|
||||
pll_8996_calc_vco_count(pdb, pll->vco_current_rate,
|
||||
pll->vco_ref_clk_rate);
|
||||
|
@ -701,10 +790,10 @@ int pll_vco_set_rate_8996(struct clk *c, unsigned long rate)
|
|||
/* commit slave if split display is enabled */
|
||||
slave = pll->slave;
|
||||
if (slave)
|
||||
pll_db_commit_8996(slave->pll_base, pdb);
|
||||
pll_db_commit_8996(slave, pdb);
|
||||
|
||||
/* commit master itself */
|
||||
pll_db_commit_8996(pll->pll_base, pdb);
|
||||
pll_db_commit_8996(pll, pdb);
|
||||
|
||||
mdss_pll_resource_enable(pll, false);
|
||||
|
||||
|
|
|
@ -52,6 +52,13 @@
|
|||
#define DSIPHY_PLL_PLLLOCK_CMP_EN 0x0488
|
||||
|
||||
#define DSIPHY_PLL_DEC_START 0x0490
|
||||
#define DSIPHY_PLL_SSC_EN_CENTER 0x0494
|
||||
#define DSIPHY_PLL_SSC_ADJ_PER1 0x0498
|
||||
#define DSIPHY_PLL_SSC_ADJ_PER2 0x049c
|
||||
#define DSIPHY_PLL_SSC_PER1 0x04a0
|
||||
#define DSIPHY_PLL_SSC_PER2 0x04a4
|
||||
#define DSIPHY_PLL_SSC_STEP_SIZE1 0x04a8
|
||||
#define DSIPHY_PLL_SSC_STEP_SIZE2 0x04ac
|
||||
#define DSIPHY_PLL_DIV_FRAC_START1 0x04b4
|
||||
#define DSIPHY_PLL_DIV_FRAC_START2 0x04b8
|
||||
#define DSIPHY_PLL_DIV_FRAC_START3 0x04bc
|
||||
|
@ -85,8 +92,8 @@ struct dsi_pll_input {
|
|||
u32 pll_wakeup_timer; /* 5, reg: 0x043c, bit 0 - 2 */
|
||||
u32 plllock_cnt; /* 1, reg: 0x0488, bit 1 - 2 */
|
||||
u32 plllock_rng; /* 1, reg: 0x0488, bit 3 - 4 */
|
||||
u32 ssc_center_spread; /* 0, reg: 0x0494, bit 1 */
|
||||
u32 ssc_adj_per; /* 37, reg: 0x498, bit 0 - 9 */
|
||||
u32 ssc_center; /* 0, reg: 0x0494, bit 1 */
|
||||
u32 ssc_adj_period; /* 37, reg: 0x498, bit 0 - 9 */
|
||||
u32 ssc_spread; /* 0.005 */
|
||||
u32 ssc_freq; /* unknown */
|
||||
u32 pll_ie_trim; /* 4, reg: 0x0400 */
|
||||
|
@ -115,7 +122,7 @@ struct dsi_pll_output {
|
|||
u32 pll_txclk_en; /* reg: 0x04c0 */
|
||||
u32 dec_start; /* reg: 0x0490 */
|
||||
u32 div_frac_start; /* reg: 0x04b4, 0x4b8, 0x04bc */
|
||||
u32 ssc_per; /* reg: 0x04a0, 0x04a4 */
|
||||
u32 ssc_period; /* reg: 0x04a0, 0x04a4 */
|
||||
u32 ssc_step_size; /* reg: 0x04a8, 0x04ac */
|
||||
u32 plllock_cmp; /* reg: 0x047c, 0x0480, 0x0484 */
|
||||
u32 pll_vco_div_ref; /* reg: 0x046c, 0x0470 */
|
||||
|
|
|
@ -222,6 +222,16 @@ static int mdss_pll_probe(struct platform_device *pdev)
|
|||
pll_res->index = 0;
|
||||
}
|
||||
|
||||
pll_res->ssc_en = of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,dsi-pll-ssc-en");
|
||||
|
||||
pll_res->ssc_center = false;
|
||||
|
||||
label = of_get_property(pdev->dev.of_node,
|
||||
"qcom,dsi-pll-ssc-mode", NULL);
|
||||
if (label && !strcmp(label, "center-spread"))
|
||||
pll_res->ssc_center = true;
|
||||
|
||||
pll_base_reg = platform_get_resource_byname(pdev,
|
||||
IORESOURCE_MEM, "pll_base");
|
||||
if (!pll_base_reg) {
|
||||
|
|
|
@ -124,6 +124,9 @@ struct mdss_pll_resources {
|
|||
*/
|
||||
uint32_t index;
|
||||
|
||||
bool ssc_en; /* share pll with master */
|
||||
bool ssc_center; /* default is down spread */
|
||||
|
||||
struct mdss_pll_resources *slave;
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Reference in a new issue