Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 934b5daa authored by Kuogee Hsieh's avatar Kuogee Hsieh
Browse files

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: default avatarKuogee Hsieh <khsieh@codeaurora.org>
parent ec5d3489
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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>;
+102 −13
Original line number Diff line number Diff line
@@ -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;
@@ -319,12 +321,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 */
@@ -335,8 +338,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 */

@@ -358,8 +361,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;
@@ -454,9 +498,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;
@@ -522,9 +604,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;
@@ -532,7 +615,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 */
@@ -606,6 +689,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 */
}

@@ -707,9 +793,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(pll, pdb);

	pll_8996_dec_frac_calc(pdb, pll);
	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);
@@ -717,10 +806,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);

+10 −3
Original line number Diff line number Diff line
@@ -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 */
+10 −0
Original line number Diff line number Diff line
@@ -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) {
+3 −0
Original line number Diff line number Diff line
@@ -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;

	/*