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

Commit f72854bb authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ARM: dts: msm: enable DSI SSC feature for SDM439/SDM429"

parents da97a47e 9677d34a
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -341,10 +341,10 @@
	reg = <0x001a94400 0x400>,
		<0x0184d074 0x8>;
	reg-names = "pll_base", "gdsc_base";
	/delete-property/ qcom,dsi-pll-ssc-en;
	/delete-property/ qcom,dsi-pll-ssc-mode;
	/delete-property/ qcom,ssc-frequency-hz;
	/delete-property/ qcom,ssc-ppm;
	qcom,dsi-pll-ssc-en;
	qcom,dsi-pll-ssc-mode = "down-spread";
	qcom,ssc-frequency-hz = <31500>;
	qcom,ssc-ppm = <5000>;
};

&mdss_dsi1_pll {
@@ -352,10 +352,10 @@
	reg = <0x001a96400 0x400>,
		<0x0184d074 0x8>;
	reg-names = "pll_base", "gdsc_base";
	/delete-property/ qcom,dsi-pll-ssc-en;
	/delete-property/ qcom,dsi-pll-ssc-mode;
	/delete-property/ qcom,ssc-frequency-hz;
	/delete-property/ qcom,ssc-ppm;
	qcom,dsi-pll-ssc-en;
	qcom,dsi-pll-ssc-mode = "down-spread";
	qcom,ssc-frequency-hz = <31500>;
	qcom,ssc-ppm = <5000>;
};

&mdss_dsi {
+168 −15
Original line number Diff line number Diff line
@@ -165,7 +165,8 @@ int get_gp_mux_sel(struct mux_clk *clk)
	return sel;
}

static bool pll_is_pll_locked_12nm(struct mdss_pll_resources *pll)
static bool pll_is_pll_locked_12nm(struct mdss_pll_resources *pll,
	bool is_handoff)
{
	u32 status;
	bool pll_locked;
@@ -177,6 +178,7 @@ static bool pll_is_pll_locked_12nm(struct mdss_pll_resources *pll)
			((status & BIT(1)) > 0),
			DSI_PLL_POLL_MAX_READS,
			DSI_PLL_POLL_TIMEOUT_US)) {
		if (!is_handoff)
			pr_err("DSI PLL ndx=%d status=%x failed to Lock\n",
				pll->index, status);
		pll_locked = false;
@@ -213,7 +215,7 @@ int dsi_pll_enable_seq_12nm(struct mdss_pll_resources *pll)
	wmb(); /* make sure register committed before enabling branch clocks */
	udelay(50); /* h/w recommended delay */

	if (!pll_is_pll_locked_12nm(pll)) {
	if (!pll_is_pll_locked_12nm(pll, false)) {
		pr_err("DSI PLL ndx=%d lock failed!\n",
			pll->index);
		rc = -EINVAL;
@@ -261,7 +263,7 @@ static int dsi_pll_relock(struct mdss_pll_resources *pll)
	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_POWERUP_CTRL, data);
	ndelay(500); /* h/w recommended delay */

	if (!pll_is_pll_locked_12nm(pll)) {
	if (!pll_is_pll_locked_12nm(pll, false)) {
		pr_err("DSI PLL ndx=%d lock failed!\n",
			pll->index);
		rc = -EINVAL;
@@ -556,6 +558,142 @@ static void mdss_dsi_pll_12nm_calc_reg(struct mdss_pll_resources *pll,
	param->gmp_cntrl = 0x1;
}

static u32 __mdss_dsi_get_multi_intX100(u64 vco_rate, u32 *rem)
{
	u32 reminder = 0;
	u64 temp = 0;
	const u32 ref_clk_rate = 19200000, quarterX100 = 25;

	temp = div_u64_rem(vco_rate, ref_clk_rate, &reminder);
	temp *= 100;

	/*
	 * Multiplication integer needs to be floored in steps of 0.25
	 * Hence multi_intX100 needs to be rounded off in steps of 25
	 */
	if (reminder < (ref_clk_rate / 4)) {
		*rem = reminder;
		return temp;
	} else if ((reminder >= (ref_clk_rate / 4)) &&
		reminder < (ref_clk_rate / 2)) {
		*rem = (reminder - (ref_clk_rate / 4));
		return (temp + quarterX100);
	} else if ((reminder >= (ref_clk_rate / 2)) &&
		(reminder < ((3 * ref_clk_rate) / 4))) {
		*rem = (reminder - (ref_clk_rate / 2));
		return (temp + (quarterX100 * 2));
	}

	*rem = (reminder - ((3 * ref_clk_rate) / 4));
	return (temp + (quarterX100 * 3));
}

static u32 __calc_gcd(u32 num1, u32 num2)
{
	if (num2 != 0)
		return __calc_gcd(num2, (num1 % num2));
	else
		return num1;
}

static void mdss_dsi_pll_12nm_calc_ssc(struct mdss_pll_resources *pll,
					struct dsi_pll_db *pdb)
{
	struct dsi_pll_param *param = &pdb->param;
	u64 multi_intX100 = 0, temp = 0;
	u32 temp_rem1 = 0, temp_rem2 = 0;
	const u64 power_2_17 = 131072, power_2_10 = 1024;
	const u32 ref_clk_rate = 19200000;

	multi_intX100 = __mdss_dsi_get_multi_intX100(pll->vco_current_rate,
		&temp_rem1);

	/* Calculation for mpll_ssc_peak_i */
	temp = (multi_intX100 * pll->ssc_ppm * power_2_17);
	temp = div_u64(temp, 100); /* 100 div for multi_intX100 */
	param->mpll_ssc_peak_i =
		(u32) div_u64(temp, 1000000); /*10^6 for SSC PPM */

	/* Calculation for mpll_stepsize_i */
	param->mpll_stepsize_i = (u32) div_u64((param->mpll_ssc_peak_i *
		pll->ssc_freq * power_2_10), ref_clk_rate);

	/* Calculation for mpll_mint_i */
	param->mpll_mint_i = (u32) (div_u64((multi_intX100 * 4), 100) - 32);

	/* Calculation for mpll_frac_den */
	param->mpll_frac_den = (u32) div_u64(ref_clk_rate,
		__calc_gcd((u32)pll->vco_current_rate, ref_clk_rate));

	/* Calculation for mpll_frac_quot_i */
	temp = (temp_rem1 * power_2_17);
	param->mpll_frac_quot_i =
		(u32) div_u64_rem(temp, ref_clk_rate, &temp_rem2);

	/* Calculation for mpll_frac_rem */
	param->mpll_frac_rem = (u32) div_u64(((u64)temp_rem2 *
		param->mpll_frac_den), ref_clk_rate);

	pr_debug("mpll_ssc_peak_i=%d mpll_stepsize_i=%d mpll_mint_i=%d\n",
		param->mpll_ssc_peak_i, param->mpll_stepsize_i,
		param->mpll_mint_i);
	pr_debug("mpll_frac_den=%d mpll_frac_quot_i=%d mpll_frac_rem=%d",
		param->mpll_frac_den, param->mpll_frac_quot_i,
		param->mpll_frac_rem);
}

static void pll_db_commit_12nm_ssc(struct mdss_pll_resources *pll,
					struct dsi_pll_db *pdb)
{
	void __iomem *pll_base = pll->pll_base;
	struct dsi_pll_param *param = &pdb->param;
	char data = 0;

	MDSS_PLL_REG_W(pll_base, DSIPHY_SSC0, 0x27);

	data = (param->mpll_mint_i & 0xff);
	MDSS_PLL_REG_W(pll_base, DSIPHY_SSC7, data);

	data = ((param->mpll_mint_i & 0xff00) >> 8);
	MDSS_PLL_REG_W(pll_base, DSIPHY_SSC8, data);

	data = (param->mpll_ssc_peak_i & 0xff);
	MDSS_PLL_REG_W(pll_base, DSIPHY_SSC1, data);

	data = ((param->mpll_ssc_peak_i & 0xff00) >> 8);
	MDSS_PLL_REG_W(pll_base, DSIPHY_SSC2, data);

	data = ((param->mpll_ssc_peak_i & 0xf0000) >> 16);
	MDSS_PLL_REG_W(pll_base, DSIPHY_SSC3, data);

	data = (param->mpll_stepsize_i & 0xff);
	MDSS_PLL_REG_W(pll_base, DSIPHY_SSC4, data);

	data = ((param->mpll_stepsize_i & 0xff00) >> 8);
	MDSS_PLL_REG_W(pll_base, DSIPHY_SSC5, data);

	data = ((param->mpll_stepsize_i & 0x1f0000) >> 16);
	MDSS_PLL_REG_W(pll_base, DSIPHY_SSC6, data);

	data = (param->mpll_frac_quot_i & 0xff);
	MDSS_PLL_REG_W(pll_base, DSIPHY_SSC10, data);

	data = ((param->mpll_frac_quot_i & 0xff00) >> 8);
	MDSS_PLL_REG_W(pll_base, DSIPHY_SSC11, data);

	data = (param->mpll_frac_rem & 0xff);
	MDSS_PLL_REG_W(pll_base, DSIPHY_SSC12, data);

	data = ((param->mpll_frac_rem & 0xff00) >> 8);
	MDSS_PLL_REG_W(pll_base, DSIPHY_SSC13, data);

	data = (param->mpll_frac_den & 0xff);
	MDSS_PLL_REG_W(pll_base, DSIPHY_SSC14, data);

	data = ((param->mpll_frac_den & 0xff00) >> 8);
	MDSS_PLL_REG_W(pll_base, DSIPHY_SSC15, data);
}

static void pll_db_commit_12nm(struct mdss_pll_resources *pll,
					struct dsi_pll_db *pdb)
{
@@ -616,6 +754,9 @@ static void pll_db_commit_12nm(struct mdss_pll_resources *pll,
	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PRO_DLY_RELOCK, 0x0c);
	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_LOCK_DET_MODE_SEL, 0x02);

	if (pll->ssc_en)
		pll_db_commit_12nm_ssc(pll, pdb);

	pr_debug("pll:%d\n", pll->index);
	wmb(); /* make sure register committed before preparing the clocks */
}
@@ -710,7 +851,7 @@ enum handoff pll_vco_handoff_12nm(struct clk *c)
		return ret;
	}

	if (pll_is_pll_locked_12nm(pll)) {
	if (pll_is_pll_locked_12nm(pll, true)) {
		pll->handoff_resources = true;
		pll->pll_on = true;
		c->rate = pll_vco_get_rate_12nm(c);
@@ -756,18 +897,27 @@ int pll_vco_prepare_12nm(struct clk *c)
					rc, pll->index);
			goto error;
		}
	}

	/*
	 * For cases where  DSI PHY is already enabled like:
	 * 1.) LP-11 during static screen
	 * 2.) ULPS during static screen
	 * 3.) Boot up with cont splash enabled where PHY is programmed in LK
	 * Execute the Re-lock sequence to enable the DSI PLL.
	 */
	data = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_SYS_CTRL);
		if (data & BIT(7)) { /* DSI PHY in LP-11 or ULPS */
	if (data & BIT(7)) {
		rc = dsi_pll_relock(pll);
		if (rc)
			goto error;
		else
			goto end;
	}
	}

	mdss_dsi_pll_12nm_calc_reg(pll, pdb);
	if (pll->ssc_en)
		mdss_dsi_pll_12nm_calc_ssc(pll, pdb);

	/* commit DSI vco  */
	pll_db_commit_12nm(pll, pdb);
@@ -802,6 +952,7 @@ int pll_vco_enable_12nm(struct clk *c)
{
	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
	struct mdss_pll_resources *pll = vco->priv;
	u32 data = 0;

	if (!pll) {
		pr_err("Dsi pll resources are not available\n");
@@ -813,7 +964,9 @@ int pll_vco_enable_12nm(struct clk *c)
		return -EINVAL;
	}

	MDSS_PLL_REG_W(pll->pll_base, DSIPHY_SSC0, 0x40);
	data = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_SSC0);
	data |= BIT(6); /* enable GP_CLK_EN */
	MDSS_PLL_REG_W(pll->pll_base, DSIPHY_SSC0, data);
	wmb(); /* make sure register committed before enabling branch clocks */

	return 0;
+20 −0
Original line number Diff line number Diff line
@@ -636,11 +636,13 @@ static struct div_clk dsi1pll_byte_clk_src = {
};

static struct clk_lookup mdss_dsi_pllcc_12nm[] = {
	CLK_LIST(dsi0pll_vco_clk),
	CLK_LIST(dsi0pll_byte_clk_src),
	CLK_LIST(dsi0pll_pixel_clk_src),
};

static struct clk_lookup mdss_dsi_pllcc_12nm_1[] = {
	CLK_LIST(dsi1pll_vco_clk),
	CLK_LIST(dsi1pll_byte_clk_src),
	CLK_LIST(dsi1pll_pixel_clk_src),
};
@@ -650,6 +652,9 @@ int dsi_pll_clock_register_12nm(struct platform_device *pdev,
{
	int rc = 0, ndx;
	struct dsi_pll_db *pdb;
	int const ssc_freq_min = 30000; /* min. recommended freq. value */
	int const ssc_freq_max = 33000; /* max. recommended freq. value */
	int const ssc_ppm_max = 5000; /* max. recommended ppm */

	if (!pdev || !pdev->dev.of_node) {
		pr_err("Invalid input parameters\n");
@@ -680,6 +685,21 @@ int dsi_pll_clock_register_12nm(struct platform_device *pdev,
	pixel_div_clk_src_ops = clk_ops_div;
	pixel_div_clk_src_ops.prepare = dsi_pll_div_prepare;

	if (pll_res->ssc_en) {
		if (!pll_res->ssc_freq || (pll_res->ssc_freq < ssc_freq_min) ||
			(pll_res->ssc_freq > ssc_freq_max)) {
			pll_res->ssc_freq = ssc_freq_min;
			pr_debug("SSC frequency out of recommended range. Set to default=%d\n",
				pll_res->ssc_freq);
		}

		if (!pll_res->ssc_ppm || (pll_res->ssc_ppm > ssc_ppm_max)) {
			pll_res->ssc_ppm = ssc_ppm_max;
			pr_debug("SSC PPM out of recommended range. Set to default=%d\n",
				pll_res->ssc_ppm);
		}
	}

	/* Set client data to mux, div and vco clocks.  */
	if (pll_res->index == DSI_PLL_1) {
		dsi1pll_byte_clk_src.priv = pll_res;
+24 −0
Original line number Diff line number Diff line
@@ -37,6 +37,22 @@
#define DSIPHY_PLL_LOOP_DIV_RATIO_1			0x2e8
#define DSIPHY_SLEWRATE_DDL_CYC_FRQ_ADJ_1		0x328
#define DSIPHY_SSC0					0x394
#define DSIPHY_SSC7					0x3b0
#define DSIPHY_SSC8					0x3b4
#define DSIPHY_SSC1					0x398
#define DSIPHY_SSC2					0x39c
#define DSIPHY_SSC3					0x3a0
#define DSIPHY_SSC4					0x3a4
#define DSIPHY_SSC5					0x3a8
#define DSIPHY_SSC6					0x3ac
#define DSIPHY_SSC10					0x360
#define DSIPHY_SSC11					0x364
#define DSIPHY_SSC12					0x368
#define DSIPHY_SSC13					0x36c
#define DSIPHY_SSC14					0x370
#define DSIPHY_SSC15					0x374
#define DSIPHY_SSC7					0x3b0
#define DSIPHY_SSC8					0x3b4
#define DSIPHY_SSC9					0x3b8
#define DSIPHY_STAT0					0x3e0
#define DSIPHY_CTRL0					0x3e8
@@ -58,6 +74,14 @@ struct dsi_pll_param {
	u32 post_div_mux;
	u32 pixel_divhf;
	u32 fsm_ovr_ctrl;

	/* ssc_params */
	u32 mpll_ssc_peak_i;
	u32 mpll_stepsize_i;
	u32 mpll_mint_i;
	u32 mpll_frac_den;
	u32 mpll_frac_quot_i;
	u32 mpll_frac_rem;
};

enum {
+2 −0
Original line number Diff line number Diff line
@@ -237,8 +237,10 @@

#define clk_dsi0pll_byte_clk_src		0xbbaa30be
#define clk_dsi0pll_pixel_clk_src		0x45b3260f
#define clk_dsi0pll_vco_clk			0x15940d40
#define clk_dsi1pll_byte_clk_src		0x63930a8f
#define clk_dsi1pll_pixel_clk_src		0x0e4c9b56
#define clk_dsi1pll_vco_clk			0x99797b50

#define clk_dsi_pll0_byte_clk_src		0x44539836
#define clk_dsi_pll0_pixel_clk_src		0x5767c287