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

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

Merge changes Ic7ce1af6,I05efde2b into dev/msm-4.14-display

* changes:
  drm/msm/dsi-staging: fix idle power collapse exit sequence for PHY v3
  drm/msm/dsi-staging: separate link HS and LP clocks
parents 97d3131d 6417228b
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -216,6 +216,7 @@ static void dsi_catalog_phy_3_0_init(struct dsi_phy_hw *phy)
	phy->ops.ulps_ops.is_lanes_in_ulps =
	phy->ops.ulps_ops.is_lanes_in_ulps =
		dsi_phy_hw_v3_0_is_lanes_in_ulps;
		dsi_phy_hw_v3_0_is_lanes_in_ulps;
	phy->ops.phy_timing_val = dsi_phy_hw_timing_val_v3_0;
	phy->ops.phy_timing_val = dsi_phy_hw_timing_val_v3_0;
	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.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.toggle_resync_fifo = dsi_phy_hw_v3_0_toggle_resync_fifo;
}
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -102,6 +102,7 @@ u32 dsi_phy_hw_v3_0_get_lanes_in_ulps(struct dsi_phy_hw *phy);
bool dsi_phy_hw_v3_0_is_lanes_in_ulps(u32 lanes, u32 ulps_lanes);
bool dsi_phy_hw_v3_0_is_lanes_in_ulps(u32 lanes, u32 ulps_lanes);
int dsi_phy_hw_timing_val_v3_0(struct dsi_phy_per_lane_cfgs *timing_cfg,
int dsi_phy_hw_timing_val_v3_0(struct dsi_phy_per_lane_cfgs *timing_cfg,
		u32 *timing_val, u32 size);
		u32 *timing_val, u32 size);
void dsi_phy_hw_v3_0_clamp_ctrl(struct dsi_phy_hw *phy, bool enable);
int dsi_phy_hw_v3_0_lane_reset(struct dsi_phy_hw *phy);
int dsi_phy_hw_v3_0_lane_reset(struct dsi_phy_hw *phy);
void dsi_phy_hw_v3_0_toggle_resync_fifo(struct dsi_phy_hw *phy);
void dsi_phy_hw_v3_0_toggle_resync_fifo(struct dsi_phy_hw *phy);


+44 −15
Original line number Original line Diff line number Diff line
@@ -43,6 +43,13 @@ enum dsi_link_clk_type {
	DSI_LINK_CLK_MAX,
	DSI_LINK_CLK_MAX,
};
};


enum dsi_link_clk_op_type {
	DSI_LINK_CLK_SET_RATE = BIT(0),
	DSI_LINK_CLK_PREPARE = BIT(1),
	DSI_LINK_CLK_ENABLE = BIT(2),
	DSI_LINK_CLK_START = BIT(0) | BIT(1) | BIT(2),
};

enum dsi_clk_type {
enum dsi_clk_type {
	DSI_CORE_CLK = BIT(0),
	DSI_CORE_CLK = BIT(0),
	DSI_LINK_CLK = BIT(1),
	DSI_LINK_CLK = BIT(1),
@@ -50,6 +57,12 @@ enum dsi_clk_type {
	DSI_CLKS_MAX = BIT(2),
	DSI_CLKS_MAX = BIT(2),
};
};


enum dsi_lclk_type {
	DSI_LINK_NONE = 0,
	DSI_LINK_LP_CLK = BIT(0),
	DSI_LINK_HS_CLK = BIT(1),
};

struct dsi_clk_ctrl_info {
struct dsi_clk_ctrl_info {
	enum dsi_clk_type clk_type;
	enum dsi_clk_type clk_type;
	enum dsi_clk_state clk_state;
	enum dsi_clk_state clk_state;
@@ -82,23 +95,29 @@ struct dsi_core_clk_info {
};
};


/**
/**
 * struct dsi_link_clk_info - Link clock information for DSI hardware.
 * struct dsi_link_hs_clk_info - Set of high speed link clocks for DSI HW
 * @byte_clk:        Handle to DSI byte clock.
 * @byte_clk:        Handle to DSI byte_clk.
 * @pixel_clk:       Handle to DSI pixel clock.
 * @pixel_clk:       Handle to DSI pixel_clk.
 * @esc_clk:         Handle to DSI escape clock.
 * @byte_intf_clk:   Handle to DSI byte intf. clock.
 * @byte_intf_clk:   Handle to DSI byte intf. clock.
 */
 */
struct dsi_link_clk_info {
struct dsi_link_hs_clk_info {
	struct clk *byte_clk;
	struct clk *byte_clk;
	struct clk *pixel_clk;
	struct clk *pixel_clk;
	struct clk *esc_clk;
	struct clk *byte_intf_clk;
	struct clk *byte_intf_clk;
};
};


/**
 * struct dsi_link_lp_clk_info - Set of low power link clocks for DSI HW.
 * @esc_clk:         Handle to DSI escape clock.
 */
struct dsi_link_lp_clk_info {
	struct clk *esc_clk;
};

/**
/**
 * struct link_clk_freq - Clock frequency information for Link clocks
 * struct link_clk_freq - Clock frequency information for Link clocks
 * @byte_clk_rate:   Frequency of DSI byte clock in KHz.
 * @byte_clk_rate:   Frequency of DSI byte_clk in KHz.
 * @pixel_clk_rate:  Frequency of DSI pixel clock in KHz.
 * @pixel_clk_rate:  Frequency of DSI pixel_clk in KHz.
 * @esc_clk_rate:    Frequency of DSI escape clock in KHz.
 * @esc_clk_rate:    Frequency of DSI escape clock in KHz.
 */
 */
struct link_clk_freq {
struct link_clk_freq {
@@ -111,48 +130,56 @@ struct link_clk_freq {
 * typedef *pre_clockoff_cb() - Callback before clock is turned off
 * typedef *pre_clockoff_cb() - Callback before clock is turned off
 * @priv: private data pointer.
 * @priv: private data pointer.
 * @clk_type: clock which is being turned off.
 * @clk_type: clock which is being turned off.
 * @l_type: specifies if the clock is HS or LP type. Valid only for link clocks.
 * @new_state: next state for the clock.
 * @new_state: next state for the clock.
 *
 *
 * @return: error code.
 * @return: error code.
 */
 */
typedef int (*pre_clockoff_cb)(void *priv,
typedef int (*pre_clockoff_cb)(void *priv,
			       enum dsi_clk_type clk_type,
			       enum dsi_clk_type clk_type,
			       enum dsi_lclk_type l_type,
			       enum dsi_clk_state new_state);
			       enum dsi_clk_state new_state);


/**
/**
 * typedef *post_clockoff_cb() - Callback after clock is turned off
 * typedef *post_clockoff_cb() - Callback after clock is turned off
 * @priv: private data pointer.
 * @priv: private data pointer.
 * @clk_type: clock which was turned off.
 * @clk_type: clock which was turned off.
 * @l_type: specifies if the clock is HS or LP type. Valid only for link clocks.
 * @curr_state: current state for the clock.
 * @curr_state: current state for the clock.
 *
 *
 * @return: error code.
 * @return: error code.
 */
 */
typedef int (*post_clockoff_cb)(void *priv,
typedef int (*post_clockoff_cb)(void *priv,
				enum dsi_clk_type clk_type,
				enum dsi_clk_type clk_type,
				enum dsi_lclk_type l_type,
				enum dsi_clk_state curr_state);
				enum dsi_clk_state curr_state);


/**
/**
 * typedef *post_clockon_cb() - Callback after clock is turned on
 * typedef *post_clockon_cb() - Callback after clock is turned on
 * @priv: private data pointer.
 * @priv: private data pointer.
 * @clk_type: clock which was turned on.
 * @clk_type: clock which was turned on.
 * @l_type: specifies if the clock is HS or LP type. Valid only for link clocks.
 * @curr_state: current state for the clock.
 * @curr_state: current state for the clock.
 *
 *
 * @return: error code.
 * @return: error code.
 */
 */
typedef int (*post_clockon_cb)(void *priv,
typedef int (*post_clockon_cb)(void *priv,
			       enum dsi_clk_type clk_type,
			       enum dsi_clk_type clk_type,
			       enum dsi_lclk_type l_type,
			       enum dsi_clk_state curr_state);
			       enum dsi_clk_state curr_state);


/**
/**
 * typedef *pre_clockon_cb() - Callback before clock is turned on
 * typedef *pre_clockon_cb() - Callback before clock is turned on
 * @priv: private data pointer.
 * @priv: private data pointer.
 * @clk_type: clock which is being turned on.
 * @clk_type: clock which is being turned on.
 * @l_type: specifies if the clock is HS or LP type.Valid only for link clocks.
 * @new_state: next state for the clock.
 * @new_state: next state for the clock.
 *
 *
 * @return: error code.
 * @return: error code.
 */
 */
typedef int (*pre_clockon_cb)(void *priv,
typedef int (*pre_clockon_cb)(void *priv,
			      enum dsi_clk_type clk_type,
			      enum dsi_clk_type clk_type,
			      enum dsi_lclk_type l_type,
			      enum dsi_clk_state new_state);
			      enum dsi_clk_state new_state);




@@ -160,7 +187,8 @@ typedef int (*pre_clockon_cb)(void *priv,
 * struct dsi_clk_info - clock information for DSI hardware.
 * struct dsi_clk_info - clock information for DSI hardware.
 * @name:                    client name.
 * @name:                    client name.
 * @c_clks[MAX_DSI_CTRL]     array of core clock configurations
 * @c_clks[MAX_DSI_CTRL]     array of core clock configurations
 * @l_clks[MAX_DSI_CTRL]     array of link clock configurations
 * @l_lp_clks[MAX_DSI_CTRL]  array of low power(esc) clock configurations
 * @l_hs_clks[MAX_DSI_CTRL]  array of high speed clock configurations
 * @bus_handle[MAX_DSI_CTRL] array of bus handles
 * @bus_handle[MAX_DSI_CTRL] array of bus handles
 * @ctrl_index[MAX_DSI_CTRL] array of DSI controller indexes mapped
 * @ctrl_index[MAX_DSI_CTRL] array of DSI controller indexes mapped
 *                           to core and link clock configurations
 *                           to core and link clock configurations
@@ -175,7 +203,8 @@ typedef int (*pre_clockon_cb)(void *priv,
struct dsi_clk_info {
struct dsi_clk_info {
	char name[MAX_STRING_LEN];
	char name[MAX_STRING_LEN];
	struct dsi_core_clk_info c_clks[MAX_DSI_CTRL];
	struct dsi_core_clk_info c_clks[MAX_DSI_CTRL];
	struct dsi_link_clk_info l_clks[MAX_DSI_CTRL];
	struct dsi_link_lp_clk_info l_lp_clks[MAX_DSI_CTRL];
	struct dsi_link_hs_clk_info l_hs_clks[MAX_DSI_CTRL];
	u32 bus_handle[MAX_DSI_CTRL];
	u32 bus_handle[MAX_DSI_CTRL];
	u32 ctrl_index[MAX_DSI_CTRL];
	u32 ctrl_index[MAX_DSI_CTRL];
	pre_clockoff_cb pre_clkoff_cb;
	pre_clockoff_cb pre_clkoff_cb;
@@ -189,8 +218,8 @@ struct dsi_clk_info {


/**
/**
 * struct dsi_clk_link_set - Pair of clock handles to describe link clocks
 * struct dsi_clk_link_set - Pair of clock handles to describe link clocks
 * @byte_clk:     Handle to DSi byte clock.
 * @byte_clk:     Handle to DSi byte_clk.
 * @pixel_clk:    Handle to DSI pixel clock.
 * @pixel_clk:    Handle to DSI pixel_clk.
 */
 */
struct dsi_clk_link_set {
struct dsi_clk_link_set {
	struct clk *byte_clk;
	struct clk *byte_clk;
@@ -264,9 +293,9 @@ int dsi_clk_set_link_frequencies(void *client, struct link_clk_freq freq,




/**
/**
 * dsi_clk_set_pixel_clk_rate() - set frequency for pixel clock
 * dsi_clk_set_pixel_clk_rate() - set frequency for pixel_clk
 * @client:       DSI clock client pointer.
 * @client:       DSI clock client pointer.
 * @pixel_clk: Pixel clock rate in Hz.
 * @pixel_clk:    Pixel_clk rate in Hz.
 * @index:        Index of the DSI controller.
 * @index:        Index of the DSI controller.
 * return: error code in case of failure or 0 for success.
 * return: error code in case of failure or 0 for success.
 */
 */
+283 −134
Original line number Original line Diff line number Diff line
@@ -24,7 +24,8 @@ struct dsi_core_clks {
};
};


struct dsi_link_clks {
struct dsi_link_clks {
	struct dsi_link_clk_info clks;
	struct dsi_link_hs_clk_info hs_clks;
	struct dsi_link_lp_clk_info lp_clks;
	struct link_clk_freq freq;
	struct link_clk_freq freq;
};
};


@@ -124,7 +125,7 @@ int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index)
	struct dsi_clk_mngr *mngr;
	struct dsi_clk_mngr *mngr;


	mngr = c->mngr;
	mngr = c->mngr;
	rc = clk_set_rate(mngr->link_clks[index].clks.pixel_clk, pixel_clk);
	rc = clk_set_rate(mngr->link_clks[index].hs_clks.pixel_clk, pixel_clk);
	if (rc)
	if (rc)
		pr_err("failed to set clk rate for pixel clk, rc=%d\n", rc);
		pr_err("failed to set clk rate for pixel clk, rc=%d\n", rc);
	else
	else
@@ -147,7 +148,7 @@ int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index)
	struct dsi_clk_mngr *mngr;
	struct dsi_clk_mngr *mngr;


	mngr = c->mngr;
	mngr = c->mngr;
	rc = clk_set_rate(mngr->link_clks[index].clks.byte_clk, byte_clk);
	rc = clk_set_rate(mngr->link_clks[index].hs_clks.byte_clk, byte_clk);
	if (rc)
	if (rc)
		pr_err("failed to set clk rate for byte clk, rc=%d\n", rc);
		pr_err("failed to set clk rate for byte clk, rc=%d\n", rc);
	else
	else
@@ -285,38 +286,39 @@ int dsi_core_clk_stop(struct dsi_core_clks *c_clks)
	return rc;
	return rc;
}
}


static int dsi_link_clk_set_rate(struct dsi_link_clks *l_clks, int index)
static int dsi_link_hs_clk_set_rate(struct dsi_link_hs_clk_info *link_hs_clks,
		int index)
{
{
	int rc = 0;
	int rc = 0;
	struct dsi_clk_mngr *mngr;
	struct dsi_clk_mngr *mngr;
	struct dsi_link_clks *l_clks;


	if (index >= MAX_DSI_CTRL) {
	if (index >= MAX_DSI_CTRL) {
		pr_err("Invalid DSI ctrl index\n");
		pr_err("Invalid DSI ctrl index\n");
		return -EINVAL;
		return -EINVAL;
	}
	}


	l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks);
	mngr = container_of(l_clks, struct dsi_clk_mngr, link_clks[index]);
	mngr = container_of(l_clks, struct dsi_clk_mngr, link_clks[index]);
	if (mngr->is_cont_splash_enabled)

		return 0;
	/*
	/*
	 * In an ideal world, cont_splash_enabled should not be required inside
	 * In an ideal world, cont_splash_enabled should not be required inside
	 * the clock manager. But, in the current driver cont_splash_enabled
	 * the clock manager. But, in the current driver cont_splash_enabled
	 * flag is set inside mdp driver and there is no interface event
	 * flag is set inside mdp driver and there is no interface event
	 * associated with this flag setting.
	 * associated with this flag setting.
	 */
	 */
	rc = clk_set_rate(l_clks->clks.esc_clk, l_clks->freq.esc_clk_rate);
	if (mngr->is_cont_splash_enabled)
	if (rc) {
		return 0;
		pr_err("clk_set_rate failed for esc_clk rc = %d\n", rc);
		goto error;
	}


	rc = clk_set_rate(l_clks->clks.byte_clk, l_clks->freq.byte_clk_rate);
	rc = clk_set_rate(link_hs_clks->byte_clk,
		l_clks->freq.byte_clk_rate);
	if (rc) {
	if (rc) {
		pr_err("clk_set_rate failed for byte_clk rc = %d\n", rc);
		pr_err("clk_set_rate failed for byte_clk rc = %d\n", rc);
		goto error;
		goto error;
	}
	}


	rc = clk_set_rate(l_clks->clks.pixel_clk, l_clks->freq.pix_clk_rate);
	rc = clk_set_rate(link_hs_clks->pixel_clk,
		l_clks->freq.pix_clk_rate);
	if (rc) {
	if (rc) {
		pr_err("clk_set_rate failed for pixel_clk rc = %d\n", rc);
		pr_err("clk_set_rate failed for pixel_clk rc = %d\n", rc);
		goto error;
		goto error;
@@ -327,8 +329,8 @@ static int dsi_link_clk_set_rate(struct dsi_link_clks *l_clks, int index)
	 * For DPHY: byte_intf_clk_rate = byte_clk_rate / 2
	 * For DPHY: byte_intf_clk_rate = byte_clk_rate / 2
	 * todo: this needs to be revisited when support for CPHY is added
	 * todo: this needs to be revisited when support for CPHY is added
	 */
	 */
	if (l_clks->clks.byte_intf_clk) {
	if (link_hs_clks->byte_intf_clk) {
		rc = clk_set_rate(l_clks->clks.byte_intf_clk,
		rc = clk_set_rate(link_hs_clks->byte_intf_clk,
			(l_clks->freq.byte_clk_rate / 2));
			(l_clks->freq.byte_clk_rate / 2));
		if (rc) {
		if (rc) {
			pr_err("set_rate failed for byte_intf_clk rc = %d\n",
			pr_err("set_rate failed for byte_intf_clk rc = %d\n",
@@ -340,30 +342,24 @@ static int dsi_link_clk_set_rate(struct dsi_link_clks *l_clks, int index)
	return rc;
	return rc;
}
}


static int dsi_link_clk_prepare(struct dsi_link_clks *l_clks)
static int dsi_link_hs_clk_prepare(struct dsi_link_hs_clk_info *link_hs_clks)
{
{
	int rc = 0;
	int rc = 0;


	rc = clk_prepare(l_clks->clks.esc_clk);
	rc = clk_prepare(link_hs_clks->byte_clk);
	if (rc) {
		pr_err("Failed to prepare dsi esc clk, rc=%d\n", rc);
		goto esc_clk_err;
	}

	rc = clk_prepare(l_clks->clks.byte_clk);
	if (rc) {
	if (rc) {
		pr_err("Failed to prepare dsi byte clk, rc=%d\n", rc);
		pr_err("Failed to prepare dsi byte clk, rc=%d\n", rc);
		goto byte_clk_err;
		goto byte_clk_err;
	}
	}


	rc = clk_prepare(l_clks->clks.pixel_clk);
	rc = clk_prepare(link_hs_clks->pixel_clk);
	if (rc) {
	if (rc) {
		pr_err("Failed to prepare dsi pixel clk, rc=%d\n", rc);
		pr_err("Failed to prepare dsi pixel clk, rc=%d\n", rc);
		goto pixel_clk_err;
		goto pixel_clk_err;
	}
	}


	if (l_clks->clks.byte_intf_clk) {
	if (link_hs_clks->byte_intf_clk) {
		rc = clk_prepare(l_clks->clks.byte_intf_clk);
		rc = clk_prepare(link_hs_clks->byte_intf_clk);
		if (rc) {
		if (rc) {
			pr_err("Failed to prepare dsi byte intf clk, rc=%d\n",
			pr_err("Failed to prepare dsi byte intf clk, rc=%d\n",
				rc);
				rc);
@@ -374,48 +370,39 @@ static int dsi_link_clk_prepare(struct dsi_link_clks *l_clks)
	return rc;
	return rc;


byte_intf_clk_err:
byte_intf_clk_err:
	clk_unprepare(l_clks->clks.pixel_clk);
	clk_unprepare(link_hs_clks->pixel_clk);
pixel_clk_err:
pixel_clk_err:
	clk_unprepare(l_clks->clks.byte_clk);
	clk_unprepare(link_hs_clks->byte_clk);
byte_clk_err:
byte_clk_err:
	clk_unprepare(l_clks->clks.esc_clk);
esc_clk_err:
	return rc;
	return rc;
}
}


static void dsi_link_clk_unprepare(struct dsi_link_clks *l_clks)
static void dsi_link_hs_clk_unprepare(struct dsi_link_hs_clk_info *link_hs_clks)
{
{
	if (l_clks->clks.byte_intf_clk)
	if (link_hs_clks->byte_intf_clk)
		clk_unprepare(l_clks->clks.byte_intf_clk);
		clk_unprepare(link_hs_clks->byte_intf_clk);
	clk_unprepare(l_clks->clks.pixel_clk);
	clk_unprepare(link_hs_clks->pixel_clk);
	clk_unprepare(l_clks->clks.byte_clk);
	clk_unprepare(link_hs_clks->byte_clk);
	clk_unprepare(l_clks->clks.esc_clk);
}
}


static int dsi_link_clk_enable(struct dsi_link_clks *l_clks)
static int dsi_link_hs_clk_enable(struct dsi_link_hs_clk_info *link_hs_clks)
{
{
	int rc = 0;
	int rc = 0;


	rc = clk_enable(l_clks->clks.esc_clk);
	rc = clk_enable(link_hs_clks->byte_clk);
	if (rc) {
		pr_err("Failed to enable dsi esc clk, rc=%d\n", rc);
		goto esc_clk_err;
	}

	rc = clk_enable(l_clks->clks.byte_clk);
	if (rc) {
	if (rc) {
		pr_err("Failed to enable dsi byte clk, rc=%d\n", rc);
		pr_err("Failed to enable dsi byte clk, rc=%d\n", rc);
		goto byte_clk_err;
		goto byte_clk_err;
	}
	}


	rc = clk_enable(l_clks->clks.pixel_clk);
	rc = clk_enable(link_hs_clks->pixel_clk);
	if (rc) {
	if (rc) {
		pr_err("Failed to enable dsi pixel clk, rc=%d\n", rc);
		pr_err("Failed to enable dsi pixel clk, rc=%d\n", rc);
		goto pixel_clk_err;
		goto pixel_clk_err;
	}
	}


	if (l_clks->clks.byte_intf_clk) {
	if (link_hs_clks->byte_intf_clk) {
		rc = clk_enable(l_clks->clks.byte_intf_clk);
		rc = clk_enable(link_hs_clks->byte_intf_clk);
		if (rc) {
		if (rc) {
			pr_err("Failed to enable dsi byte intf clk, rc=%d\n",
			pr_err("Failed to enable dsi byte intf clk, rc=%d\n",
				rc);
				rc);
@@ -426,28 +413,26 @@ static int dsi_link_clk_enable(struct dsi_link_clks *l_clks)
	return rc;
	return rc;


byte_intf_clk_err:
byte_intf_clk_err:
	clk_disable(l_clks->clks.pixel_clk);
	clk_disable(link_hs_clks->pixel_clk);
pixel_clk_err:
pixel_clk_err:
	clk_disable(l_clks->clks.byte_clk);
	clk_disable(link_hs_clks->byte_clk);
byte_clk_err:
byte_clk_err:
	clk_disable(l_clks->clks.esc_clk);
esc_clk_err:
	return rc;
	return rc;
}
}


static void dsi_link_clk_disable(struct dsi_link_clks *l_clks)
static void dsi_link_hs_clk_disable(struct dsi_link_hs_clk_info *link_hs_clks)
{
{
	if (l_clks->clks.byte_intf_clk)
	if (link_hs_clks->byte_intf_clk)
		clk_disable(l_clks->clks.byte_intf_clk);
		clk_disable(link_hs_clks->byte_intf_clk);
	clk_disable(l_clks->clks.esc_clk);
	clk_disable(link_hs_clks->pixel_clk);
	clk_disable(l_clks->clks.pixel_clk);
	clk_disable(link_hs_clks->byte_clk);
	clk_disable(l_clks->clks.byte_clk);
}
}


/**
/**
 * dsi_link_clk_start() - enable dsi link clocks
 * dsi_link_clk_start() - enable dsi link clocks
 */
 */
static int dsi_link_clk_start(struct dsi_link_clks *clks, int index)
static int dsi_link_hs_clk_start(struct dsi_link_hs_clk_info *link_hs_clks,
	enum dsi_link_clk_op_type op_type, int index)
{
{
	int rc = 0;
	int rc = 0;


@@ -456,28 +441,34 @@ static int dsi_link_clk_start(struct dsi_link_clks *clks, int index)
		return -EINVAL;
		return -EINVAL;
	}
	}


	rc = dsi_link_clk_set_rate(clks, index);
	if (op_type & DSI_LINK_CLK_SET_RATE) {
		rc = dsi_link_hs_clk_set_rate(link_hs_clks, index);
		if (rc) {
		if (rc) {
		pr_err("failed to set clk rates, rc = %d\n", rc);
			pr_err("failed to set HS clk rates, rc = %d\n", rc);
			goto error;
			goto error;
		}
		}
	}


	rc = dsi_link_clk_prepare(clks);
	if (op_type & DSI_LINK_CLK_PREPARE) {
		rc = dsi_link_hs_clk_prepare(link_hs_clks);
		if (rc) {
		if (rc) {
		pr_err("failed to prepare link clks, rc = %d\n", rc);
			pr_err("failed to prepare link HS clks, rc = %d\n", rc);
			goto error;
			goto error;
		}
		}
	}


	rc = dsi_link_clk_enable(clks);
	if (op_type & DSI_LINK_CLK_ENABLE) {
		rc = dsi_link_hs_clk_enable(link_hs_clks);
		if (rc) {
		if (rc) {
		pr_err("failed to enable link clks, rc = %d\n", rc);
			pr_err("failed to enable link HS clks, rc = %d\n", rc);
			goto error_unprepare;
			goto error_unprepare;
		}
		}
	}


	pr_debug("Link clocks are enabled\n");
	pr_debug("HS Link clocks are enabled\n");
	return rc;
	return rc;
error_unprepare:
error_unprepare:
	dsi_link_clk_unprepare(clks);
	dsi_link_hs_clk_unprepare(link_hs_clks);
error:
error:
	return rc;
	return rc;
}
}
@@ -485,13 +476,69 @@ static int dsi_link_clk_start(struct dsi_link_clks *clks, int index)
/**
/**
 * dsi_link_clk_stop() - Stop DSI link clocks.
 * dsi_link_clk_stop() - Stop DSI link clocks.
 */
 */
int dsi_link_clk_stop(struct dsi_link_clks *clks)
static int dsi_link_hs_clk_stop(struct dsi_link_hs_clk_info *link_hs_clks)
{
	struct dsi_link_clks *l_clks;

	l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks);

	dsi_link_hs_clk_disable(link_hs_clks);
	dsi_link_hs_clk_unprepare(link_hs_clks);

	pr_debug("HS Link clocks disabled\n");

	return 0;
}

static int dsi_link_lp_clk_start(struct dsi_link_lp_clk_info *link_lp_clks)
{
	int rc = 0;
	struct dsi_clk_mngr *mngr;
	struct dsi_link_clks *l_clks;

	l_clks = container_of(link_lp_clks, struct dsi_link_clks, lp_clks);

	mngr = container_of(l_clks, struct dsi_clk_mngr, link_clks[0]);
	if (!mngr)
		return -EINVAL;
	/*
	 * In an ideal world, cont_splash_enabled should not be required inside
	 * the clock manager. But, in the current driver cont_splash_enabled
	 * flag is set inside mdp driver and there is no interface event
	 * associated with this flag setting. Also, set rate for clock need not
	 * be called for every enable call. It should be done only once when
	 * coming out of suspend.
	 */
	if (mngr->is_cont_splash_enabled)
		goto prepare;

	rc = clk_set_rate(link_lp_clks->esc_clk, l_clks->freq.esc_clk_rate);
	if (rc) {
		pr_err("clk_set_rate failed for esc_clk rc = %d\n", rc);
		goto error;
	}

prepare:
	rc = clk_prepare_enable(link_lp_clks->esc_clk);
	if (rc) {
		pr_err("Failed to enable dsi esc clk\n");
		clk_unprepare(l_clks->lp_clks.esc_clk);
	}
error:
	pr_debug("LP Link clocks are enabled\n");
	return rc;
}

static int dsi_link_lp_clk_stop(
	struct dsi_link_lp_clk_info *link_lp_clks)
{
{
	dsi_link_clk_disable(clks);
	struct dsi_link_clks *l_clks;
	dsi_link_clk_unprepare(clks);


	pr_debug("Link clocks disabled\n");
	l_clks = container_of(link_lp_clks, struct dsi_link_clks, lp_clks);


	clk_disable_unprepare(l_clks->lp_clks.esc_clk);

	pr_debug("LP Link clocks are disabled\n");
	return 0;
	return 0;
}
}


@@ -556,7 +603,7 @@ static int dsi_display_core_clk_enable(struct dsi_core_clks *clks,
}
}


static int dsi_display_link_clk_enable(struct dsi_link_clks *clks,
static int dsi_display_link_clk_enable(struct dsi_link_clks *clks,
	u32 ctrl_count, u32 master_ndx)
	enum dsi_lclk_type l_type, u32 ctrl_count, u32 master_ndx)
{
{
	int rc = 0;
	int rc = 0;
	int i;
	int i;
@@ -570,27 +617,56 @@ static int dsi_display_link_clk_enable(struct dsi_link_clks *clks,


	m_clks = &clks[master_ndx];
	m_clks = &clks[master_ndx];


	rc = dsi_link_clk_start(m_clks, master_ndx);
	if (l_type & DSI_LINK_LP_CLK) {
		rc = dsi_link_lp_clk_start(&m_clks->lp_clks);
		if (rc) {
		if (rc) {
		pr_err("failed to turn on master clocks, rc=%d\n", rc);
			pr_err("failed to turn on master lp link clocks, rc=%d\n",
				rc);
			goto error;
			goto error;
		}
		}
	}

	if (l_type & DSI_LINK_HS_CLK) {
		rc = dsi_link_hs_clk_start(&m_clks->hs_clks,
			DSI_LINK_CLK_START, master_ndx);
		if (rc) {
			pr_err("failed to turn on master hs link clocks, rc=%d\n",
				rc);
			goto error;
		}
	}


	/* Turn on rest of the core clocks */
	for (i = 0; i < ctrl_count; i++) {
	for (i = 0; i < ctrl_count; i++) {
		clk = &clks[i];
		clk = &clks[i];
		if (!clk || (clk == m_clks))
		if (!clk || (clk == m_clks))
			continue;
			continue;


		rc = dsi_link_clk_start(clk, i);
		if (l_type & DSI_LINK_LP_CLK) {
			rc = dsi_link_lp_clk_start(&clk->lp_clks);
			if (rc) {
			if (rc) {
			pr_err("failed to turn on clocks, rc=%d\n", rc);
				pr_err("failed to turn on lp link clocks, rc=%d\n",
					rc);
				goto error_disable_master;
			}
		}

		if (l_type & DSI_LINK_HS_CLK) {
			rc = dsi_link_hs_clk_start(&clk->hs_clks,
				DSI_LINK_CLK_START, i);
			if (rc) {
				pr_err("failed to turn on hs link clocks, rc=%d\n",
					rc);
				goto error_disable_master;
				goto error_disable_master;
			}
			}
		}
		}
	}
	return rc;
	return rc;

error_disable_master:
error_disable_master:
	(void)dsi_link_clk_stop(m_clks);
	if (l_type == DSI_LINK_LP_CLK)
		(void)dsi_link_lp_clk_stop(&m_clks->lp_clks);
	else if (l_type == DSI_LINK_HS_CLK)
		(void)dsi_link_hs_clk_stop(&m_clks->hs_clks);
error:
error:
	return rc;
	return rc;
}
}
@@ -646,7 +722,7 @@ static int dsi_display_core_clk_disable(struct dsi_core_clks *clks,
}
}


static int dsi_display_link_clk_disable(struct dsi_link_clks *clks,
static int dsi_display_link_clk_disable(struct dsi_link_clks *clks,
	u32 ctrl_count, u32 master_ndx)
	enum dsi_lclk_type l_type, u32 ctrl_count, u32 master_ndx)
{
{
	int rc = 0;
	int rc = 0;
	int i;
	int i;
@@ -667,15 +743,100 @@ static int dsi_display_link_clk_disable(struct dsi_link_clks *clks,
		if (!clk || (clk == m_clks))
		if (!clk || (clk == m_clks))
			continue;
			continue;


		rc = dsi_link_clk_stop(clk);
		if (l_type & DSI_LINK_LP_CLK) {
			rc = dsi_link_lp_clk_stop(&clk->lp_clks);
			if (rc)
			if (rc)
			pr_err("failed to turn off clocks, rc=%d\n", rc);
				pr_err("failed to turn off lp link clocks, rc=%d\n",
					rc);
		}
		}


	rc = dsi_link_clk_stop(m_clks);
		if (l_type & DSI_LINK_HS_CLK) {
			rc = dsi_link_hs_clk_stop(&clk->hs_clks);
			if (rc)
			if (rc)
		pr_err("failed to turn off master clocks, rc=%d\n", rc);
				pr_err("failed to turn off hs link clocks, rc=%d\n",
					rc);
		}
	}

	if (l_type & DSI_LINK_LP_CLK) {
		rc = dsi_link_lp_clk_stop(&m_clks->lp_clks);
		if (rc)
			pr_err("failed to turn off master lp link clocks, rc=%d\n",
				rc);
	}

	if (l_type & DSI_LINK_HS_CLK) {
		rc = dsi_link_hs_clk_stop(&m_clks->hs_clks);
		if (rc)
			pr_err("failed to turn off master hs link clocks, rc=%d\n",
				rc);
	}

	return rc;
}

static int dsi_clk_update_link_clk_state(struct dsi_link_clks *l_clks,
	enum dsi_lclk_type l_type, u32 l_state, bool enable)
{
	int rc = 0;
	struct dsi_clk_mngr *mngr;

	mngr = container_of(l_clks, struct dsi_clk_mngr, link_clks[0]);
	if (!mngr)
		return -EINVAL;

	if (enable) {
		if (mngr->pre_clkon_cb) {
			rc = mngr->pre_clkon_cb(mngr->priv_data, DSI_LINK_CLK,
				l_type, l_state);
			if (rc) {
				pr_err("pre link clk on cb failed for type %d\n",
					l_type);
				goto error;
			}
		}
		rc = dsi_display_link_clk_enable(l_clks, l_type,
				mngr->dsi_ctrl_count, mngr->master_ndx);
		if (rc) {
			pr_err("failed to start link clk type %d rc=%d\n",
				l_type, rc);
			goto error;
		}

		if (mngr->post_clkon_cb) {
			rc = mngr->post_clkon_cb(mngr->priv_data, DSI_LINK_CLK,
				l_type, l_state);
			if (rc) {
				pr_err("post link clk on cb failed for type %d\n",
					l_type);
				goto error;
			}
		}
	} else {
		if (mngr->pre_clkoff_cb) {
			rc = mngr->pre_clkoff_cb(mngr->priv_data,
				DSI_LINK_CLK, l_type, l_state);
			if (rc)
				pr_err("pre link clk off cb failed\n");
		}


		rc = dsi_display_link_clk_disable(l_clks, l_type,
			mngr->dsi_ctrl_count, mngr->master_ndx);
		if (rc) {
			pr_err("failed to stop link clk type %d, rc = %d\n",
			       l_type, rc);
			goto error;
		}

		if (mngr->post_clkoff_cb) {
			rc = mngr->post_clkoff_cb(mngr->priv_data,
				DSI_LINK_CLK, l_type, l_state);
			if (rc)
				pr_err("post link clk off cb failed\n");
		}
	}

error:
	return rc;
	return rc;
}
}


@@ -710,6 +871,7 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state,
		if (mngr->core_clk_state == DSI_CLK_OFF) {
		if (mngr->core_clk_state == DSI_CLK_OFF) {
			rc = mngr->pre_clkon_cb(mngr->priv_data,
			rc = mngr->pre_clkon_cb(mngr->priv_data,
						DSI_CORE_CLK,
						DSI_CORE_CLK,
						DSI_LINK_NONE,
						DSI_CLK_ON);
						DSI_CLK_ON);
			if (rc) {
			if (rc) {
				pr_err("failed to turn on MDP FS rc= %d\n", rc);
				pr_err("failed to turn on MDP FS rc= %d\n", rc);
@@ -726,6 +888,7 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state,
		if (mngr->post_clkon_cb) {
		if (mngr->post_clkon_cb) {
			rc = mngr->post_clkon_cb(mngr->priv_data,
			rc = mngr->post_clkon_cb(mngr->priv_data,
						 DSI_CORE_CLK,
						 DSI_CORE_CLK,
						 DSI_LINK_NONE,
						 DSI_CLK_ON);
						 DSI_CLK_ON);
			if (rc)
			if (rc)
				pr_err("post clk on cb failed, rc = %d\n", rc);
				pr_err("post clk on cb failed, rc = %d\n", rc);
@@ -735,25 +898,15 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state,


	if (l_clks) {
	if (l_clks) {
		if (l_state == DSI_CLK_ON) {
		if (l_state == DSI_CLK_ON) {
			if (mngr->pre_clkon_cb) {
			rc = dsi_clk_update_link_clk_state(l_clks,
				rc = mngr->pre_clkon_cb(mngr->priv_data,
				DSI_LINK_LP_CLK, l_state, true);
					DSI_LINK_CLK, l_state);
			if (rc)
			if (rc)
					pr_err("pre link clk on cb failed\n");
			}
			rc = dsi_display_link_clk_enable(l_clks,
					mngr->dsi_ctrl_count, mngr->master_ndx);
			if (rc) {
				pr_err("failed to start link clk rc= %d\n", rc);
				goto error;
				goto error;
			}

			if (mngr->post_clkon_cb) {
			rc = dsi_clk_update_link_clk_state(l_clks,
				rc = mngr->post_clkon_cb(mngr->priv_data,
				DSI_LINK_HS_CLK, l_state, true);
							DSI_LINK_CLK,
							l_state);
			if (rc)
			if (rc)
					pr_err("post link clk on cb failed\n");
				goto error;
			}
		} else {
		} else {
			/*
			/*
			 * Two conditions that need to be checked for Link
			 * Two conditions that need to be checked for Link
@@ -784,36 +937,26 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state,
				}
				}


				rc = dsi_display_link_clk_enable(l_clks,
				rc = dsi_display_link_clk_enable(l_clks,
					(DSI_LINK_LP_CLK & DSI_LINK_HS_CLK),
					mngr->dsi_ctrl_count, mngr->master_ndx);
					mngr->dsi_ctrl_count, mngr->master_ndx);
				if (rc) {
				if (rc) {
					pr_err("Link clks did not start\n");
					pr_err("LP Link clks did not start\n");
					goto error;
					goto error;
				}
				}
				l_c_on = true;
				l_c_on = true;
				pr_debug("ECG: core and Link_on\n");
				pr_debug("ECG: core and Link_on\n");
			}
			}


			if (mngr->pre_clkoff_cb) {
			rc = dsi_clk_update_link_clk_state(l_clks,
				rc = mngr->pre_clkoff_cb(mngr->priv_data,
				DSI_LINK_HS_CLK, l_state, false);
					DSI_LINK_CLK, l_state);
			if (rc)
			if (rc)
					pr_err("pre link clk off cb failed\n");
			}

			rc = dsi_display_link_clk_disable(l_clks,
				mngr->dsi_ctrl_count, mngr->master_ndx);
			if (rc) {
				pr_err("failed to stop link clk, rc = %d\n",
				       rc);
				goto error;
				goto error;
			}


			if (mngr->post_clkoff_cb) {
			rc = dsi_clk_update_link_clk_state(l_clks,
				rc = mngr->post_clkoff_cb(mngr->priv_data,
				DSI_LINK_LP_CLK, l_state, false);
					DSI_LINK_CLK, l_state);
			if (rc)
			if (rc)
					pr_err("post link clk off cb failed\n");
				goto error;
			}

			/*
			/*
			 * This check is to save unnecessary clock state
			 * This check is to save unnecessary clock state
			 * change when going from EARLY_GATE to OFF. In the
			 * change when going from EARLY_GATE to OFF. In the
@@ -872,6 +1015,7 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state,
		if (mngr->pre_clkoff_cb) {
		if (mngr->pre_clkoff_cb) {
			rc = mngr->pre_clkoff_cb(mngr->priv_data,
			rc = mngr->pre_clkoff_cb(mngr->priv_data,
						 DSI_CORE_CLK,
						 DSI_CORE_CLK,
						 DSI_LINK_NONE,
						 c_state);
						 c_state);
			if (rc)
			if (rc)
				pr_err("pre core clk off cb failed\n");
				pr_err("pre core clk off cb failed\n");
@@ -888,6 +1032,7 @@ static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state,
			if (mngr->post_clkoff_cb) {
			if (mngr->post_clkoff_cb) {
				rc = mngr->post_clkoff_cb(mngr->priv_data,
				rc = mngr->post_clkoff_cb(mngr->priv_data,
						DSI_CORE_CLK,
						DSI_CORE_CLK,
						DSI_LINK_NONE,
						DSI_CLK_OFF);
						DSI_CLK_OFF);
				if (rc)
				if (rc)
					pr_err("post clkoff cb fail, rc = %d\n",
					pr_err("post clkoff cb fail, rc = %d\n",
@@ -1095,6 +1240,7 @@ static int dsi_display_link_clk_force_update(void *client)
	}
	}


	rc = dsi_display_link_clk_disable(l_clks,
	rc = dsi_display_link_clk_disable(l_clks,
			(DSI_LINK_LP_CLK | DSI_LINK_HS_CLK),
			mngr->dsi_ctrl_count, mngr->master_ndx);
			mngr->dsi_ctrl_count, mngr->master_ndx);
	if (rc) {
	if (rc) {
		pr_err("%s, failed to stop link clk, rc = %d\n",
		pr_err("%s, failed to stop link clk, rc = %d\n",
@@ -1103,6 +1249,7 @@ static int dsi_display_link_clk_force_update(void *client)
	}
	}


	rc = dsi_display_link_clk_enable(l_clks,
	rc = dsi_display_link_clk_enable(l_clks,
			(DSI_LINK_LP_CLK | DSI_LINK_HS_CLK),
			mngr->dsi_ctrl_count, mngr->master_ndx);
			mngr->dsi_ctrl_count, mngr->master_ndx);
	if (rc) {
	if (rc) {
		pr_err("%s, failed to start link clk rc= %d\n",
		pr_err("%s, failed to start link clk rc= %d\n",
@@ -1268,8 +1415,10 @@ void *dsi_display_clk_mngr_register(struct dsi_clk_info *info)
	for (i = 0; i < mngr->dsi_ctrl_count; i++) {
	for (i = 0; i < mngr->dsi_ctrl_count; i++) {
		memcpy(&mngr->core_clks[i].clks, &info->c_clks[i],
		memcpy(&mngr->core_clks[i].clks, &info->c_clks[i],
			sizeof(struct dsi_core_clk_info));
			sizeof(struct dsi_core_clk_info));
		memcpy(&mngr->link_clks[i].clks, &info->l_clks[i],
		memcpy(&mngr->link_clks[i].hs_clks, &info->l_hs_clks[i],
			sizeof(struct dsi_link_clk_info));
			sizeof(struct dsi_link_hs_clk_info));
		memcpy(&mngr->link_clks[i].lp_clks, &info->l_lp_clks[i],
			sizeof(struct dsi_link_lp_clk_info));
		mngr->core_clks[i].bus_handle = info->bus_handle[i];
		mngr->core_clks[i].bus_handle = info->bus_handle[i];
		mngr->ctrl_index[i] = info->ctrl_index[i];
		mngr->ctrl_index[i] = info->ctrl_index[i];
	}
	}
+26 −23

File changed.

Preview size limit exceeded, changes collapsed.

Loading