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

Commit 6115c76b authored by Kyle Yan's avatar Kyle Yan Committed by Gerrit - the friendly Code Review server
Browse files

Merge "clk: mdss: add software mux for byte and pixel source clocks" into msm-4.8

parents 7d01cb69 3287bab4
Loading
Loading
Loading
Loading
+337 −52
Original line number Diff line number Diff line
@@ -98,10 +98,118 @@
#define MMSS_DSI_PHY_PLL_HR_OCLK3_DIVIDER		0x0148
#define MMSS_DSI_PHY_PLL_PLL_VCO_HIGH			0x014C
#define MMSS_DSI_PHY_PLL_RESET_SM			0x0150
#define MMSS_DSI_PHY_PLL_MUXVAL			0x0154
#define MMSS_DSI_PHY_PLL_CORE_RES_CODE_DN		0x0158
#define MMSS_DSI_PHY_PLL_CORE_RES_CODE_UP		0x015C
#define MMSS_DSI_PHY_PLL_CORE_VCO_TUNE			0x0160
#define MMSS_DSI_PHY_PLL_CORE_VCO_TAIL			0x0164
#define MMSS_DSI_PHY_PLL_CORE_KVCO_CODE		0x0168

#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL0		0x014
#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL1		0x018
#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL2		0x01C
#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL3		0x020
#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL4		0x024
#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL5		0x028
#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL6		0x02C
#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL7		0x030
#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL8		0x034
#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL9		0x038
#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL10		0x03C
#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL11		0x040
#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL12		0x044
#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL13		0x048
#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL14		0x04C
#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL15		0x050
#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL16		0x054
#define MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL17		0x058

#define DSI_PLL_POLL_MAX_READS			15
#define DSI_PLL_POLL_TIMEOUT_US			1000

int set_mdss_byte_mux_sel(struct mux_clk *clk, int sel)
{
	return 0;
}

int get_mdss_byte_mux_sel(struct mux_clk *clk)
{
	return 0;
}

int set_mdss_pixel_mux_sel(struct mux_clk *clk, int sel)
{
	return 0;
}

int get_mdss_pixel_mux_sel(struct mux_clk *clk)
{
	return 0;
}

void dsi_cache_trim_codes(struct mdss_pll_resources *dsi_pll_res)
{
	int rc;

	if (dsi_pll_res->reg_upd)
		return;

	rc = mdss_pll_resource_enable(dsi_pll_res, true);
	if (rc) {
		pr_err("Failed to enable mdss dsi pll resources\n");
		return;
	}

	dsi_pll_res->cache_pll_trim_codes[0] =
		(MDSS_PLL_REG_R(dsi_pll_res->pll_base,
		MMSS_DSI_PHY_PLL_CORE_KVCO_CODE) & ~0xF);
	dsi_pll_res->cache_pll_trim_codes[1] =
		(MDSS_PLL_REG_R(dsi_pll_res->pll_base,
		MMSS_DSI_PHY_PLL_CORE_VCO_TAIL) & ~0xF);
	dsi_pll_res->cache_pll_trim_codes[2] =
		(MDSS_PLL_REG_R(dsi_pll_res->pll_base,
		MMSS_DSI_PHY_PLL_CORE_VCO_TUNE) & ~0x7F);
	dsi_pll_res->cache_pll_trim_codes[3] =
		(MDSS_PLL_REG_R(dsi_pll_res->pll_base,
		MMSS_DSI_PHY_PLL_CORE_RES_CODE_UP) & ~0xF);
	dsi_pll_res->cache_pll_trim_codes[4] =
		(MDSS_PLL_REG_R(dsi_pll_res->pll_base,
		MMSS_DSI_PHY_PLL_CORE_RES_CODE_DN) & ~0xF);

	mdss_pll_resource_enable(dsi_pll_res, false);

	dsi_pll_res->reg_upd = true;
}

static void dsi_dfps_override_trim_codes(struct mdss_pll_resources *dsi_pll_res)
{
	int reg_data;

	/*
	 * Override mux config for all cached trim codes from
	 * saved config except for VCO Tune
	 */
	reg_data = dsi_pll_res->cache_pll_trim_codes[0];
	reg_data |= BIT(5);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
		MMSS_DSI_PHY_PLL_KVCO_CODE, reg_data);

	reg_data = dsi_pll_res->cache_pll_trim_codes[1] << 2;
	reg_data |= BIT(7);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
		MMSS_DSI_PHY_PLL_PLL_VCOTAIL_EN, reg_data);

	reg_data = dsi_pll_res->cache_pll_trim_codes[3];
	reg_data |= BIT(5);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
		MMSS_DSI_PHY_PLL_RES_CODE_UP, reg_data);

	reg_data = dsi_pll_res->cache_pll_trim_codes[4];
	reg_data |= BIT(5);
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
		MMSS_DSI_PHY_PLL_RES_CODE_DN, reg_data);

}

int set_bypass_lp_div_mux_sel(struct mux_clk *clk, int sel)
{
@@ -121,6 +229,33 @@ int set_bypass_lp_div_mux_sel(struct mux_clk *clk, int sel)
	return 0;
}

int set_shadow_bypass_lp_div_mux_sel(struct mux_clk *clk, int sel)
{
	struct mdss_pll_resources *dsi_pll_res = clk->priv;
	int reg_data, rem;

	if (!dsi_pll_res->resource_enable) {
		pr_err("PLL resources disabled. Dynamic fps invalid\n");
		return -EINVAL;
	}

	reg_data = MDSS_PLL_REG_R(dsi_pll_res->pll_base,
			MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL);
	reg_data |= BIT(7);

	pr_debug("%d: reg_data = %x\n", __LINE__, reg_data);

	/* Repeat POST DIVIDER 2 times (4 writes)*/
	for (rem = 0; rem < 2; rem++)
		MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base,
			MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL16 + (4 * rem),
			MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL,
			MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL,
			(reg_data | (sel << 5)), (reg_data | (sel << 5)));

	return 0;
}

int get_bypass_lp_div_mux_sel(struct mux_clk *clk)
{
	int mux_mode, rc;
@@ -147,6 +282,8 @@ int ndiv_set_div(struct div_clk *clk, int div)
	int rc, reg_data;
	struct mdss_pll_resources *dsi_pll_res = clk->priv;

	pr_debug("%d div=%i\n", __LINE__, div);

	rc = mdss_pll_resource_enable(dsi_pll_res, true);
	if (rc) {
		pr_err("Failed to enable mdss dsi pll resources\n");
@@ -163,6 +300,26 @@ int ndiv_set_div(struct div_clk *clk, int div)
	return rc;
}

int shadow_ndiv_set_div(struct div_clk *clk, int div)
{
	struct mdss_pll_resources *dsi_pll_res = clk->priv;

	if (!dsi_pll_res->resource_enable) {
		pr_err("PLL resources disabled. Dynamic fps invalid\n");
		return -EINVAL;
	}

	pr_debug("%d div=%i\n", __LINE__, div);

	MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base,
		MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL14,
		MMSS_DSI_PHY_PLL_RESETSM_CNTRL3,
		MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL,
		0x07, (0xB | div));

	return 0;
}

int ndiv_get_div(struct div_clk *clk)
{
	int div = 0, rc;
@@ -201,6 +358,25 @@ int fixed_hr_oclk2_set_div(struct div_clk *clk, int div)
	return rc;
}

int shadow_fixed_hr_oclk2_set_div(struct div_clk *clk, int div)
{
	struct mdss_pll_resources *dsi_pll_res = clk->priv;

	if (!dsi_pll_res->resource_enable) {
		pr_err("PLL resources disabled. Dynamic fps invalid\n");
		return -EINVAL;
	}
	pr_debug("%d div = %d\n", __LINE__, div);

	MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base,
		MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL5,
		MMSS_DSI_PHY_PLL_HR_OCLK2_DIVIDER,
		MMSS_DSI_PHY_PLL_HR_OCLK2_DIVIDER,
		(div - 1), (div - 1));

	return 0;
}

int fixed_hr_oclk2_get_div(struct div_clk *clk)
{
	int div = 0, rc;
@@ -238,6 +414,26 @@ int hr_oclk3_set_div(struct div_clk *clk, int div)
	return rc;
}

int shadow_hr_oclk3_set_div(struct div_clk *clk, int div)
{
	struct mdss_pll_resources *dsi_pll_res = clk->priv;

	if (!dsi_pll_res->resource_enable) {
		pr_err("PLL resources disabled. Dynamic fps invalid\n");
		return -EINVAL;
	}

	pr_debug("%d div = %d\n", __LINE__, div);

	MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base,
		MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL6,
		MMSS_DSI_PHY_PLL_HR_OCLK3_DIVIDER,
		MMSS_DSI_PHY_PLL_HR_OCLK3_DIVIDER,
		(div - 1), (div - 1));

	return 0;
}

int hr_oclk3_get_div(struct div_clk *clk)
{
	int div = 0, rc;
@@ -478,93 +674,103 @@ static void pll_20nm_phy_config(struct dsi_pll_vco_clk *vco)
	pll_20nm_phy_loop_bw_config(dsi_pll_res);
}

int pll_20nm_vco_set_rate(struct dsi_pll_vco_clk *vco, unsigned long rate)
static void pll_20nm_vco_rate_calc(struct dsi_pll_vco_clk *vco,
		struct mdss_pll_vco_calc *vco_calc, s64 vco_clk_rate)
{
	s64 vco_clk_rate = rate;
	s64 multiplier = (1 << 20);
	s64 duration = 128, pll_comp_val;
	s64 dec_start_multiple, dec_start;
	s32 div_frac_start;
	s32 div_frac_start1, div_frac_start2, div_frac_start3;
	s64 dec_start_multiple, dec_start, multiplier = (1 << 20);
	s64 dec_start1, dec_start2;
	s64 duration = 128, pll_comp_val;
	s32 div_frac_start1, div_frac_start2, div_frac_start3;
	s64 pll_plllock_cmp1, pll_plllock_cmp2, pll_plllock_cmp3;

	struct mdss_pll_resources *dsi_pll_res = vco->priv;

	pr_debug("%s: vco set rate: %lld\n", __func__, vco_clk_rate);
	pll_20nm_phy_config(vco);

	memset(vco_calc, 0, sizeof(*vco_calc));
	dec_start_multiple = div_s64(vco_clk_rate * multiplier,
					2 * vco->ref_clk_rate);
	div_s64_rem(dec_start_multiple,
			multiplier, &div_frac_start);

	dec_start = div_s64(dec_start_multiple, multiplier);
	pr_debug("%s: dec_start_multiple = 0x%llx\n",
				__func__, dec_start_multiple);
	pr_debug("%s: dec_start = 0x%llx, div_frac_start = 0x%x\n",
			__func__, dec_start, div_frac_start);

	dec_start1 = (dec_start & 0x7f) | BIT(7);
	dec_start2 = ((dec_start & 0x80) >> 7) | BIT(1);
	pr_debug("%s: dec_start1 = 0x%llx, dec_start2 = 0x%llx\n",
				__func__, dec_start1, dec_start2);

	div_frac_start1 = (div_frac_start & 0x7f) | BIT(7);
	div_frac_start2 = ((div_frac_start >> 7) & 0x7f) | BIT(7);
	div_frac_start3 = ((div_frac_start >> 14) & 0x3f) | BIT(6);
	pr_debug("%s: div_frac_start1 = 0x%x\n",
				__func__, div_frac_start1);
	pr_debug("%s: div_frac_start2 = 0x%x\n",
				__func__, div_frac_start2);
	pr_debug("%s: div_frac_start3 = 0x%x\n",
				__func__, div_frac_start3);
	pll_comp_val = div_s64(dec_start_multiple * 2 * (duration - 1),
				10 * multiplier);
	pll_plllock_cmp1 = pll_comp_val & 0xff;
	pll_plllock_cmp2 = (pll_comp_val >> 8) & 0xff;
	pll_plllock_cmp3 = (pll_comp_val >> 16) & 0xff;

	pr_debug("dec_start_multiple = 0x%llx\n", dec_start_multiple);
	pr_debug("dec_start = 0x%llx, div_frac_start = 0x%x\n",
			dec_start, div_frac_start);
	pr_debug("dec_start1 = 0x%llx, dec_start2 = 0x%llx\n",
			dec_start1, dec_start2);
	pr_debug("div_frac_start1 = 0x%x, div_frac_start2 = 0x%x\n",
			div_frac_start1, div_frac_start2);
	pr_debug("div_frac_start3 = 0x%x\n", div_frac_start3);
	pr_debug("pll_comp_val = 0x%llx\n", pll_comp_val);
	pr_debug("pll_plllock_cmp1 = 0x%llx, pll_plllock_cmp2 =%llx\n",
			pll_plllock_cmp1, pll_plllock_cmp2);
	pr_debug("pll_plllock_cmp3 = 0x%llx\n",	pll_plllock_cmp3);

	/* Assign to vco struct */
	vco_calc->div_frac_start1 = div_frac_start1;
	vco_calc->div_frac_start2 = div_frac_start2;
	vco_calc->div_frac_start3 = div_frac_start3;
	vco_calc->dec_start1 = dec_start1;
	vco_calc->dec_start2 = dec_start2;
	vco_calc->pll_plllock_cmp1 = pll_plllock_cmp1;
	vco_calc->pll_plllock_cmp2 = pll_plllock_cmp2;
	vco_calc->pll_plllock_cmp3 = pll_plllock_cmp3;
}

int pll_20nm_vco_set_rate(struct dsi_pll_vco_clk *vco, unsigned long rate)
{
	s64 vco_clk_rate = rate;
	struct mdss_pll_resources *dsi_pll_res = vco->priv;
	struct mdss_pll_vco_calc vco_calc;

	pr_debug("vco set rate: %lld\n", vco_clk_rate);
	pll_20nm_phy_config(vco);

	/* div fraction, start and comp calculations */
	pll_20nm_vco_rate_calc(vco, &vco_calc, vco_clk_rate);

	/* register programming*/
	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			MMSS_DSI_PHY_PLL_DIV_FRAC_START1,
			div_frac_start1);
			vco_calc.div_frac_start1);

	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			MMSS_DSI_PHY_PLL_DIV_FRAC_START2,
			div_frac_start2);
			vco_calc.div_frac_start2);

	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			MMSS_DSI_PHY_PLL_DIV_FRAC_START3,
			div_frac_start3);
			vco_calc.div_frac_start3);

	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			MMSS_DSI_PHY_PLL_DEC_START1,
			dec_start1);
			vco_calc.dec_start1);

	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			MMSS_DSI_PHY_PLL_DEC_START2,
			dec_start2);

	pll_comp_val = div_s64(dec_start_multiple * 2 * (duration - 1),
				10 * multiplier);

	pr_debug("%s: pll_comp_val = 0x%llx\n", __func__, pll_comp_val);

	pll_plllock_cmp1 = pll_comp_val & 0xff;
	pll_plllock_cmp2 = (pll_comp_val >> 8) & 0xff;
	pll_plllock_cmp3 = (pll_comp_val >> 16) & 0xff;
	pr_debug("%s: pll_plllock_cmp1 = 0x%llx\n",
				__func__, pll_plllock_cmp1);
	pr_debug("%s: pll_plllock_cmp2 = 0x%llx\n",
				__func__, pll_plllock_cmp2);
	pr_debug("%s: pll_plllock_cmp3 = 0x%llx\n",
				__func__, pll_plllock_cmp3);
			vco_calc.dec_start2);

	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			MMSS_DSI_PHY_PLL_PLLLOCK_CMP1,
			pll_plllock_cmp1);
			vco_calc.pll_plllock_cmp1);

	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			MMSS_DSI_PHY_PLL_PLLLOCK_CMP2,
			pll_plllock_cmp2);
			vco_calc.pll_plllock_cmp2);

	MDSS_PLL_REG_W(dsi_pll_res->pll_base,
			MMSS_DSI_PHY_PLL_PLLLOCK_CMP3,
			pll_plllock_cmp3);
			vco_calc.pll_plllock_cmp3);

	/*
	 * Make sure that PLL vco configuration is complete
@@ -576,6 +782,87 @@ int pll_20nm_vco_set_rate(struct dsi_pll_vco_clk *vco, unsigned long rate)
	return 0;
}

int shadow_pll_20nm_vco_set_rate(struct dsi_pll_vco_clk *vco,
		unsigned long rate)
{
	struct mdss_pll_resources *dsi_pll_res = vco->priv;
	struct mdss_pll_vco_calc vco_calc;
	s64 vco_clk_rate = rate;
	u32 rem;

	if (!dsi_pll_res->resource_enable) {
		pr_err("PLL resources disabled. Dynamic fps invalid\n");
		return -EINVAL;
	}

	pr_debug("req vco set rate: %lld\n", vco_clk_rate);

	dsi_dfps_override_trim_codes(dsi_pll_res);
	/* div fraction, start and comp calculations */
	pll_20nm_vco_rate_calc(vco, &vco_calc, vco_clk_rate);

	MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base,
		MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL0,
		MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL,
		MMSS_DSI_PHY_PLL_PLLLOCK_CMP_EN,
		0xB1, 0);
	MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base,
		MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL1,
		MMSS_DSI_PHY_PLL_PLLLOCK_CMP1,
		MMSS_DSI_PHY_PLL_PLLLOCK_CMP2,
		vco_calc.pll_plllock_cmp1, vco_calc.pll_plllock_cmp2);
	MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base,
		MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL2,
		MMSS_DSI_PHY_PLL_PLLLOCK_CMP3,
		MMSS_DSI_PHY_PLL_DEC_START1,
		vco_calc.pll_plllock_cmp3, vco_calc.dec_start1);
	MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base,
		MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL3,
		MMSS_DSI_PHY_PLL_DEC_START2,
		MMSS_DSI_PHY_PLL_DIV_FRAC_START1,
		vco_calc.dec_start2, vco_calc.div_frac_start1);
	MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base,
		MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL4,
		MMSS_DSI_PHY_PLL_DIV_FRAC_START2,
		MMSS_DSI_PHY_PLL_DIV_FRAC_START3,
		vco_calc.div_frac_start2, vco_calc.div_frac_start3);
	/* Method 2 - Auto PLL calibration */
	MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base,
		MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL7,
		MMSS_DSI_PHY_PLL_PLL_VCO_TUNE,
		MMSS_DSI_PHY_PLL_PLLLOCK_CMP_EN,
		0, 0x0D);
	MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base,
		MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL8,
		MMSS_DSI_PHY_PLL_POST_DIVIDER_CONTROL,
		MMSS_DSI_PHY_PLL_RESETSM_CNTRL3,
		0xF0, 0x07);

	/*
	 * RESETSM_CTRL3 has to be set for 12 times (6 reg writes),
	 * Each register setting write 2 times, running in loop for 5
	 * times (5 reg writes) and other two iterations are taken
	 * care (one above and other in shadow_bypass
	 */
	for (rem = 0; rem < 5; rem++) {
		MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base,
				MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL9 + (4 * rem),
				MMSS_DSI_PHY_PLL_RESETSM_CNTRL3,
				MMSS_DSI_PHY_PLL_RESETSM_CNTRL3,
				0x07, 0x07);
	}

	MDSS_DYN_PLL_REG_W(dsi_pll_res->dyn_pll_base,
		MMSS_DSI_DYNAMIC_REFRESH_PLL_CTRL15,
		MMSS_DSI_PHY_PLL_RESETSM_CNTRL3,
		MMSS_DSI_PHY_PLL_RESETSM_CNTRL3,
		0x03, 0x03);

	/* memory barrier */
	wmb();
	return 0;
}

unsigned long pll_20nm_vco_get_rate(struct clk *c)
{
	u64 vco_rate, multiplier = (1 << 20);
@@ -596,7 +883,7 @@ unsigned long pll_20nm_vco_get_rate(struct clk *c)
			MMSS_DSI_PHY_PLL_DEC_START2) & BIT(0)) << 7;
	dec_start |= (MDSS_PLL_REG_R(dsi_pll_res->pll_base,
			MMSS_DSI_PHY_PLL_DEC_START1) & 0x7f);
	pr_debug("%s: dec_start = 0x%x\n", __func__, dec_start);
	pr_debug("dec_start = 0x%x\n", dec_start);

	div_frac_start = (MDSS_PLL_REG_R(dsi_pll_res->pll_base,
			MMSS_DSI_PHY_PLL_DIV_FRAC_START3) & 0x3f) << 14;
@@ -604,13 +891,11 @@ unsigned long pll_20nm_vco_get_rate(struct clk *c)
			MMSS_DSI_PHY_PLL_DIV_FRAC_START2) & 0x7f) << 7;
	div_frac_start |= MDSS_PLL_REG_R(dsi_pll_res->pll_base,
			MMSS_DSI_PHY_PLL_DIV_FRAC_START1) & 0x7f;
	pr_debug("%s: div_frac_start = 0x%x\n",
			__func__, div_frac_start);
	pr_debug("div_frac_start = 0x%x\n", div_frac_start);

	vco_rate = ref_clk * 2 * dec_start;
	vco_rate += ((ref_clk * 2 * div_frac_start) / multiplier);
	pr_debug("%s: returning vco rate = %lu\n",
			__func__, (unsigned long)vco_rate);
	pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate);

	mdss_pll_resource_enable(dsi_pll_res, false);

+235 −2
Original line number Diff line number Diff line
@@ -31,6 +31,10 @@ static const struct clk_ops pixel_clk_src_ops;
static const struct clk_ops byte_clk_src_ops;
static const struct clk_ops ndiv_clk_ops;

static const struct clk_ops shadow_pixel_clk_src_ops;
static const struct clk_ops shadow_byte_clk_src_ops;
static const struct clk_ops clk_ops_gen_mux_dsi;

static int vco_set_rate_20nm(struct clk *c, unsigned long rate)
{
	int rc;
@@ -49,6 +53,22 @@ static int vco_set_rate_20nm(struct clk *c, unsigned long rate)
	return rc;
}

static int shadow_vco_set_rate_20nm(struct clk *c, unsigned long rate)
{
	int rc;
	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
	struct mdss_pll_resources *dsi_pll_res = vco->priv;

	if (!dsi_pll_res->resource_enable) {
		pr_err("PLL resources disabled. Dynamic fps invalid\n");
		return -EINVAL;
	}

	rc = shadow_pll_20nm_vco_set_rate(vco, rate);

	return rc;
}

static int dsi_pll_enable_seq_8994(struct mdss_pll_resources *dsi_pll_res)
{
	int rc = 0;
@@ -77,13 +97,17 @@ static int dsi_pll_enable_seq_8994(struct mdss_pll_resources *dsi_pll_res)
		rc = -EINVAL;
	} else {
		pr_debug("DSI PLL Lock success\n");
		/*
		 *  Following cached registers are useful when
		 *  dynamic refresh feature is enabled.
		 */
		dsi_cache_trim_codes(dsi_pll_res);
	}

	return rc;
}

/* Op structures */

static const struct clk_ops clk_ops_dsi_vco = {
	.set_rate = vco_set_rate_20nm,
	.round_rate = pll_20nm_vco_round_rate,
@@ -92,7 +116,6 @@ static const struct clk_ops clk_ops_dsi_vco = {
	.unprepare = pll_20nm_vco_unprepare,
};


static struct clk_div_ops fixed_hr_oclk2_div_ops = {
	.set_div = fixed_hr_oclk2_set_div,
	.get_div = fixed_hr_oclk2_get_div,
@@ -113,6 +136,42 @@ static struct clk_mux_ops bypass_lp_div_mux_ops = {
	.get_mux_sel = get_bypass_lp_div_mux_sel,
};

static const struct clk_ops shadow_clk_ops_dsi_vco = {
	.set_rate = shadow_vco_set_rate_20nm,
	.round_rate = pll_20nm_vco_round_rate,
	.handoff = pll_20nm_vco_handoff,
};

static struct clk_div_ops shadow_fixed_hr_oclk2_div_ops = {
	.set_div = shadow_fixed_hr_oclk2_set_div,
	.get_div = fixed_hr_oclk2_get_div,
};

static struct clk_div_ops shadow_ndiv_ops = {
	.set_div = shadow_ndiv_set_div,
	.get_div = ndiv_get_div,
};

static struct clk_div_ops shadow_hr_oclk3_div_ops = {
	.set_div = shadow_hr_oclk3_set_div,
	.get_div = hr_oclk3_get_div,
};

static struct clk_mux_ops shadow_bypass_lp_div_mux_ops = {
	.set_mux_sel = set_shadow_bypass_lp_div_mux_sel,
	.get_mux_sel = get_bypass_lp_div_mux_sel,
};

static struct clk_mux_ops mdss_byte_mux_ops = {
	.set_mux_sel = set_mdss_byte_mux_sel,
	.get_mux_sel = get_mdss_byte_mux_sel,
};

static struct clk_mux_ops mdss_pixel_mux_ops = {
	.set_mux_sel = set_mdss_pixel_mux_sel,
	.get_mux_sel = get_mdss_pixel_mux_sel,
};

static struct dsi_pll_vco_clk dsi_vco_clk_8994 = {
	.ref_clk_rate = 19200000,
	.min_rate = 1000000000,
@@ -126,6 +185,17 @@ static struct dsi_pll_vco_clk dsi_vco_clk_8994 = {
	},
};

static struct dsi_pll_vco_clk shadow_dsi_vco_clk_8994 = {
	.ref_clk_rate = 19200000,
	.min_rate = 1000000000,
	.max_rate = 2000000000,
	.c = {
		.dbg_name = "shadow_dsi_vco_clk_8994",
		.ops = &shadow_clk_ops_dsi_vco,
		CLK_INIT(shadow_dsi_vco_clk_8994.c),
	},
};

static struct div_clk ndiv_clk_8994 = {
	.data = {
		.max_div = 15,
@@ -141,6 +211,21 @@ static struct div_clk ndiv_clk_8994 = {
	},
};

static struct div_clk shadow_ndiv_clk_8994 = {
	.data = {
		.max_div = 15,
		.min_div = 1,
	},
	.ops = &shadow_ndiv_ops,
	.c = {
		.parent = &shadow_dsi_vco_clk_8994.c,
		.dbg_name = "shadow_ndiv_clk_8994",
		.ops = &clk_ops_div,
		.flags = CLKFLAG_NO_RATE_CACHE,
		CLK_INIT(shadow_ndiv_clk_8994.c),
	},
};

static struct div_clk indirect_path_div2_clk_8994 = {
	.data = {
		.div = 2,
@@ -156,6 +241,21 @@ static struct div_clk indirect_path_div2_clk_8994 = {
	},
};

static struct div_clk shadow_indirect_path_div2_clk_8994 = {
	.data = {
		.div = 2,
		.min_div = 2,
		.max_div = 2,
	},
	.c = {
		.parent = &shadow_ndiv_clk_8994.c,
		.dbg_name = "shadow_indirect_path_div2_clk_8994",
		.ops = &clk_ops_div,
		.flags = CLKFLAG_NO_RATE_CACHE,
		CLK_INIT(shadow_indirect_path_div2_clk_8994.c),
	},
};

static struct div_clk hr_oclk3_div_clk_8994 = {
	.data = {
		.max_div = 255,
@@ -171,6 +271,21 @@ static struct div_clk hr_oclk3_div_clk_8994 = {
	},
};

static struct div_clk shadow_hr_oclk3_div_clk_8994 = {
	.data = {
		.max_div = 255,
		.min_div = 1,
	},
	.ops = &shadow_hr_oclk3_div_ops,
	.c = {
		.parent = &shadow_dsi_vco_clk_8994.c,
		.dbg_name = "shadow_hr_oclk3_div_clk_8994",
		.ops = &shadow_pixel_clk_src_ops,
		.flags = CLKFLAG_NO_RATE_CACHE,
		CLK_INIT(shadow_hr_oclk3_div_clk_8994.c),
	},
};

static struct div_clk pixel_clk_src = {
	.data = {
		.div = 2,
@@ -186,6 +301,21 @@ static struct div_clk pixel_clk_src = {
	},
};

static struct div_clk shadow_pixel_clk_src = {
	.data = {
		.div = 2,
		.min_div = 2,
		.max_div = 2,
	},
	.c = {
		.parent = &shadow_hr_oclk3_div_clk_8994.c,
		.dbg_name = "shadow_pixel_clk_src",
		.ops = &clk_ops_div,
		.flags = CLKFLAG_NO_RATE_CACHE,
		CLK_INIT(shadow_pixel_clk_src.c),
	},
};

static struct mux_clk bypass_lp_div_mux_8994 = {
	.num_parents = 2,
	.parents = (struct clk_src[]){
@@ -201,6 +331,21 @@ static struct mux_clk bypass_lp_div_mux_8994 = {
	},
};

static struct mux_clk shadow_bypass_lp_div_mux_8994 = {
	.num_parents = 2,
	.parents = (struct clk_src[]){
		{&shadow_dsi_vco_clk_8994.c, 0},
		{&shadow_indirect_path_div2_clk_8994.c, 1},
	},
	.ops = &shadow_bypass_lp_div_mux_ops,
	.c = {
		.parent = &shadow_dsi_vco_clk_8994.c,
		.dbg_name = "shadow_bypass_lp_div_mux_8994",
		.ops = &clk_ops_gen_mux,
		CLK_INIT(shadow_bypass_lp_div_mux_8994.c),
	},
};

static struct div_clk fixed_hr_oclk2_div_clk_8994 = {
	.ops = &fixed_hr_oclk2_div_ops,
	.data = {
@@ -215,6 +360,20 @@ static struct div_clk fixed_hr_oclk2_div_clk_8994 = {
	},
};

static struct div_clk shadow_fixed_hr_oclk2_div_clk_8994 = {
	.ops = &shadow_fixed_hr_oclk2_div_ops,
	.data = {
		.min_div = 4,
		.max_div = 4,
	},
	.c = {
		.parent = &shadow_bypass_lp_div_mux_8994.c,
		.dbg_name = "shadow_fixed_hr_oclk2_div_clk_8994",
		.ops = &shadow_byte_clk_src_ops,
		CLK_INIT(shadow_fixed_hr_oclk2_div_clk_8994.c),
	},
};

static struct div_clk byte_clk_src = {
	.data = {
		.div = 2,
@@ -229,7 +388,53 @@ static struct div_clk byte_clk_src = {
	},
};

static struct div_clk shadow_byte_clk_src = {
	.data = {
		.div = 2,
		.min_div = 2,
		.max_div = 2,
	},
	.c = {
		.parent = &shadow_fixed_hr_oclk2_div_clk_8994.c,
		.dbg_name = "shadow_byte_clk_src",
		.ops = &clk_ops_div,
		CLK_INIT(shadow_byte_clk_src.c),
	},
};

static struct mux_clk mdss_pixel_clk_mux = {
	.num_parents = 2,
	.parents = (struct clk_src[]) {
		{&pixel_clk_src.c, 0},
		{&shadow_pixel_clk_src.c, 1},
	},
	.ops = &mdss_pixel_mux_ops,
	.c = {
		.parent = &pixel_clk_src.c,
		.dbg_name = "mdss_pixel_clk_mux",
		.ops = &clk_ops_gen_mux,
		CLK_INIT(mdss_pixel_clk_mux.c),
	}
};

static struct mux_clk mdss_byte_clk_mux = {
	.num_parents = 2,
	.parents = (struct clk_src[]) {
		{&byte_clk_src.c, 0},
		{&shadow_byte_clk_src.c, 1},
	},
	.ops = &mdss_byte_mux_ops,
	.c = {
		.parent = &byte_clk_src.c,
		.dbg_name = "mdss_byte_clk_mux",
		.ops = &clk_ops_gen_mux_dsi,
		CLK_INIT(mdss_byte_clk_mux.c),
	}
};

static struct clk_lookup mdss_dsi_pllcc_8994[] = {
	CLK_LIST(mdss_pixel_clk_mux),
	CLK_LIST(mdss_byte_clk_mux),
	CLK_LIST(pixel_clk_src),
	CLK_LIST(byte_clk_src),
	CLK_LIST(fixed_hr_oclk2_div_clk_8994),
@@ -238,6 +443,14 @@ static struct clk_lookup mdss_dsi_pllcc_8994[] = {
	CLK_LIST(indirect_path_div2_clk_8994),
	CLK_LIST(ndiv_clk_8994),
	CLK_LIST(dsi_vco_clk_8994),
	CLK_LIST(shadow_pixel_clk_src),
	CLK_LIST(shadow_byte_clk_src),
	CLK_LIST(shadow_fixed_hr_oclk2_div_clk_8994),
	CLK_LIST(shadow_bypass_lp_div_mux_8994),
	CLK_LIST(shadow_hr_oclk3_div_clk_8994),
	CLK_LIST(shadow_indirect_path_div2_clk_8994),
	CLK_LIST(shadow_ndiv_clk_8994),
	CLK_LIST(shadow_dsi_vco_clk_8994),
};

int dsi_pll_clock_register_20nm(struct platform_device *pdev,
@@ -264,6 +477,16 @@ int dsi_pll_clock_register_20nm(struct platform_device *pdev,
	fixed_hr_oclk2_div_clk_8994.priv = pll_res;
	hr_oclk3_div_clk_8994.priv = pll_res;
	dsi_vco_clk_8994.priv = pll_res;

	shadow_byte_clk_src.priv = pll_res;
	shadow_pixel_clk_src.priv = pll_res;
	shadow_bypass_lp_div_mux_8994.priv = pll_res;
	shadow_indirect_path_div2_clk_8994.priv = pll_res;
	shadow_ndiv_clk_8994.priv = pll_res;
	shadow_fixed_hr_oclk2_div_clk_8994.priv = pll_res;
	shadow_hr_oclk3_div_clk_8994.priv = pll_res;
	shadow_dsi_vco_clk_8994.priv = pll_res;

	pll_res->vco_delay = VCO_DELAY_USEC;

	/* Set clock source operations */
@@ -279,6 +502,16 @@ int dsi_pll_clock_register_20nm(struct platform_device *pdev,
	bypass_lp_div_mux_clk_ops = clk_ops_gen_mux;
	bypass_lp_div_mux_clk_ops.prepare = dsi_pll_mux_prepare;

	clk_ops_gen_mux_dsi = clk_ops_gen_mux;
	clk_ops_gen_mux_dsi.round_rate = parent_round_rate;
	clk_ops_gen_mux_dsi.set_rate = parent_set_rate;

	shadow_pixel_clk_src_ops = clk_ops_slave_div;
	shadow_pixel_clk_src_ops.prepare = dsi_pll_div_prepare;

	shadow_byte_clk_src_ops = clk_ops_div;
	shadow_byte_clk_src_ops.prepare = dsi_pll_div_prepare;

	if (pll_res->target_id == MDSS_PLL_TARGET_8994) {
		rc = of_msm_clock_register(pdev->dev.of_node,
			mdss_dsi_pllcc_8994, ARRAY_SIZE(mdss_dsi_pllcc_8994));
+12 −0
Original line number Diff line number Diff line
@@ -79,6 +79,8 @@ void vco_unprepare(struct clk *c);

/* APIs for 20nm PHY PLL */
int pll_20nm_vco_set_rate(struct dsi_pll_vco_clk *vco, unsigned long rate);
int shadow_pll_20nm_vco_set_rate(struct dsi_pll_vco_clk *vco,
				unsigned long rate);
long pll_20nm_vco_round_rate(struct clk *c, unsigned long rate);
enum handoff pll_20nm_vco_handoff(struct clk *c);
int pll_20nm_vco_prepare(struct clk *c);
@@ -86,12 +88,22 @@ void pll_20nm_vco_unprepare(struct clk *c);
int dsi_20nm_pll_lock_status(struct mdss_pll_resources *dsi_pll_res);

int set_bypass_lp_div_mux_sel(struct mux_clk *clk, int sel);
int set_shadow_bypass_lp_div_mux_sel(struct mux_clk *clk, int sel);
int get_bypass_lp_div_mux_sel(struct mux_clk *clk);
int fixed_hr_oclk2_set_div(struct div_clk *clk, int div);
int shadow_fixed_hr_oclk2_set_div(struct div_clk *clk, int div);
int fixed_hr_oclk2_get_div(struct div_clk *clk);
int hr_oclk3_set_div(struct div_clk *clk, int div);
int shadow_hr_oclk3_set_div(struct div_clk *clk, int div);
int hr_oclk3_get_div(struct div_clk *clk);
int ndiv_set_div(struct div_clk *clk, int div);
int shadow_ndiv_set_div(struct div_clk *clk, int div);
int ndiv_get_div(struct div_clk *clk);

int set_mdss_pixel_mux_sel(struct mux_clk *clk, int sel);
int get_mdss_pixel_mux_sel(struct mux_clk *clk);
int set_mdss_byte_mux_sel(struct mux_clk *clk, int sel);
int get_mdss_byte_mux_sel(struct mux_clk *clk);
void dsi_cache_trim_codes(struct mdss_pll_resources *dsi_pll_res);

#endif
+29 −1

File changed.

Preview size limit exceeded, changes collapsed.