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

Commit b0f2e222 authored by Yujun Zhang's avatar Yujun Zhang
Browse files

disp: msm: dsi: add support for dsi dynamic clock switch



This change adds support for dynamic switching of dsi clocks
to avoid RF interference issues. Also with dynamic dsi clock
switch feature coming into picture, now populate the supported
refresh rate as list instead of providing a range. Modify the
logic to enumerate all the modes in dsi driver, taking dynamic
bit clocks, resolutions and refresh rates into account.

Change-Id: I5b6e62bc935cf2234bdd96fcb3c7537b4e735fff
Signed-off-by: default avatarSandeep Panda <spanda@codeaurora.org>
Signed-off-by: default avatarRitesh Kumar <riteshk@codeaurora.org>
Signed-off-by: default avatarYujun Zhang <yujunzhang@codeaurora.org>
parent 6ec69969
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -62,6 +62,8 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl,
		dsi_ctrl_hw_cmn_wait_for_cmd_mode_mdp_idle;
	ctrl->ops.setup_avr = dsi_ctrl_hw_cmn_setup_avr;
	ctrl->ops.set_continuous_clk = dsi_ctrl_hw_cmn_set_continuous_clk;
	ctrl->ops.wait4dynamic_refresh_done =
		dsi_ctrl_hw_cmn_wait4dynamic_refresh_done;

	switch (version) {
	case DSI_CTRL_VERSION_1_4:
@@ -219,6 +221,14 @@ static void dsi_catalog_phy_3_0_init(struct dsi_phy_hw *phy)
	phy->ops.clamp_ctrl = dsi_phy_hw_v3_0_clamp_ctrl;
	phy->ops.phy_lane_reset = dsi_phy_hw_v3_0_lane_reset;
	phy->ops.toggle_resync_fifo = dsi_phy_hw_v3_0_toggle_resync_fifo;
	phy->ops.dyn_refresh_ops.dyn_refresh_config =
		dsi_phy_hw_v3_0_dyn_refresh_config;
	phy->ops.dyn_refresh_ops.dyn_refresh_pipe_delay =
		dsi_phy_hw_v3_0_dyn_refresh_pipe_delay;
	phy->ops.dyn_refresh_ops.dyn_refresh_helper =
		dsi_phy_hw_v3_0_dyn_refresh_helper;
	phy->ops.dyn_refresh_ops.cache_phy_timings =
		dsi_phy_hw_v3_0_cache_phy_timings;
}

/**
+15 −3
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ int dsi_phy_timing_calc_init(struct dsi_phy_hw *phy,
 * @mode:       DSI mode information.
 * @host:       DSI host configuration.
 * @timing:     DSI phy lane configurations.
 * @use_mode_bit_clk: Boolean to indicate whether to recalculate bit clk.
 *
 * This function setups the catalog information in the dsi_phy_hw object.
 *
@@ -65,7 +66,8 @@ int dsi_phy_timing_calc_init(struct dsi_phy_hw *phy,
int dsi_phy_hw_calculate_timing_params(struct dsi_phy_hw *phy,
				       struct dsi_mode_info *mode,
				       struct dsi_host_common_cfg *host,
	struct dsi_phy_per_lane_cfgs *timing);
				       struct dsi_phy_per_lane_cfgs *timing,
				       bool use_mode_bit_clk);

/* Definitions for 14nm PHY hardware driver */
void dsi_phy_hw_v2_0_regulator_enable(struct dsi_phy_hw *phy,
@@ -239,4 +241,14 @@ void dsi_ctrl_hw_22_config_clk_gating(struct dsi_ctrl_hw *ctrl, bool enable,

void dsi_ctrl_hw_cmn_set_continuous_clk(struct dsi_ctrl_hw *ctrl, bool enable);

/* dynamic refresh specific functions */
void dsi_phy_hw_v3_0_dyn_refresh_helper(struct dsi_phy_hw *phy, u32 offset);
void dsi_phy_hw_v3_0_dyn_refresh_config(struct dsi_phy_hw *phy,
				struct dsi_phy_cfg *cfg, bool is_master);
void dsi_phy_hw_v3_0_dyn_refresh_pipe_delay(struct dsi_phy_hw *phy,
					    struct dsi_dyn_clk_delay *delay);

int dsi_ctrl_hw_cmn_wait4dynamic_refresh_done(struct dsi_ctrl_hw *ctrl);
int dsi_phy_hw_v3_0_cache_phy_timings(struct dsi_phy_per_lane_cfgs *timings,
				      u32 *dst, u32 size);
#endif /* _DSI_CATALOG_H_ */
+14 −0
Original line number Diff line number Diff line
@@ -307,4 +307,18 @@ int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index);
 */
int dsi_clk_update_parent(struct dsi_clk_link_set *parent,
			  struct dsi_clk_link_set *child);

/**
 * dsi_clk_prepare_enable() - prepare and enable dsi src clocks
 * @clk:       list of src clocks.
 *
 * @return:	Zero on success and err no on failure
 */
int dsi_clk_prepare_enable(struct dsi_clk_link_set *clk);

/**
 * dsi_clk_disable_unprepare() - disable and unprepare dsi src clocks
 * @clk:       list of src clocks.
 */
void dsi_clk_disable_unprepare(struct dsi_clk_link_set *clk);
#endif /* _DSI_CLK_H_ */
+51 −6
Original line number Diff line number Diff line
@@ -107,6 +107,7 @@ int dsi_clk_set_link_frequencies(void *client, struct link_clk_freq freq,
 * dsi_clk_set_pixel_clk_rate() - set frequency for pixel clock
 * @clks:	DSI link clock information.
 * @pixel_clk:	Pixel clock rate in KHz.
 * @index:	Index of the DSI controller.
 *
 * return: error code in case of failure or 0 for success.
 */
@@ -129,7 +130,7 @@ int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index)
/**
 * dsi_clk_set_byte_clk_rate() - set frequency for byte clock
 * @client:	DSI clock client pointer.
 * @byte_clk: Pixel clock rate in Hz.
 * @byte_clk:	Byte clock rate in Hz.
 * @index:	Index of the DSI controller.
 * return: error code in case of failure or 0 for success.
 */
@@ -138,6 +139,7 @@ int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index)
	int rc = 0;
	struct dsi_clk_client_info *c = client;
	struct dsi_clk_mngr *mngr;
	u64 byte_intf_rate;

	mngr = c->mngr;
	rc = clk_set_rate(mngr->link_clks[index].hs_clks.byte_clk, byte_clk);
@@ -146,8 +148,16 @@ int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index)
	else
		mngr->link_clks[index].freq.byte_clk_rate = byte_clk;

	return rc;
	if (mngr->link_clks[index].hs_clks.byte_intf_clk) {
		byte_intf_rate = mngr->link_clks[index].freq.byte_clk_rate / 2;
		rc = clk_set_rate(mngr->link_clks[index].hs_clks.byte_intf_clk,
				  byte_intf_rate);
		if (rc)
			pr_err("failed to set clk rate for byte intf clk=%d\n",
			       rc);
	}

	return rc;
}

/**
@@ -175,6 +185,41 @@ int dsi_clk_update_parent(struct dsi_clk_link_set *parent,
	return rc;
}

/**
 * dsi_clk_prepare_enable() - prepare and enable dsi src clocks
 * @clk:       list of src clocks.
 *
 * @return:	Zero on success and err no on failure.
 */
int dsi_clk_prepare_enable(struct dsi_clk_link_set *clk)
{
	int rc;

	rc = clk_prepare_enable(clk->byte_clk);
	if (rc) {
		pr_err("failed to enable byte src clk %d\n", rc);
		return rc;
	}

	rc = clk_prepare_enable(clk->pixel_clk);
	if (rc) {
		pr_err("failed to enable pixel src clk %d\n", rc);
		return rc;
	}

	return 0;
}

/**
 * dsi_clk_disable_unprepare() - disable and unprepare dsi src clocks
 * @clk:       list of src clocks.
 */
void dsi_clk_disable_unprepare(struct dsi_clk_link_set *clk)
{
	clk_disable_unprepare(clk->pixel_clk);
	clk_disable_unprepare(clk->byte_clk);
}

int dsi_core_clk_start(struct dsi_core_clks *c_clks)
{
	int rc = 0;
+27 −1
Original line number Diff line number Diff line
@@ -2887,7 +2887,12 @@ int dsi_ctrl_update_host_config(struct dsi_ctrl *ctrl,
		goto error;
	}

	if (!(flags & (DSI_MODE_FLAG_SEAMLESS | DSI_MODE_FLAG_VRR))) {
	if (!(flags & (DSI_MODE_FLAG_SEAMLESS | DSI_MODE_FLAG_VRR |
		       DSI_MODE_FLAG_DYN_CLK))) {
		/*
		 * for dynamic clk switch case link frequence would
		 * be updated dsi_display_dynamic_clk_switch().
		 */
		rc = dsi_ctrl_update_link_freqs(ctrl, config, clk_handle,
				mode);
		if (rc) {
@@ -3603,6 +3608,27 @@ void dsi_ctrl_irq_update(struct dsi_ctrl *dsi_ctrl, bool enable)
	mutex_unlock(&dsi_ctrl->ctrl_lock);
}

/**
 * dsi_ctrl_wait4dynamic_refresh_done() - Poll for dynamci refresh
 *				done interrupt.
 * @dsi_ctrl:              DSI controller handle.
 */
int dsi_ctrl_wait4dynamic_refresh_done(struct dsi_ctrl *ctrl)
{
	int rc = 0;

	if (!ctrl)
		return 0;

	mutex_lock(&ctrl->ctrl_lock);

	if (ctrl->hw.ops.wait4dynamic_refresh_done)
		rc = ctrl->hw.ops.wait4dynamic_refresh_done(&ctrl->hw);

	mutex_unlock(&ctrl->ctrl_lock);
	return rc;
}

/**
 * dsi_ctrl_drv_register() - register platform driver for dsi controller
 */
Loading