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

Commit 18288cc3 authored by Jeevan Shriram's avatar Jeevan Shriram Committed by Ingrid Gallardo
Browse files

msm: mdss: add support for dynamic refresh in clock update method



It is possible to change the refresh rate of the panel by
changing the byte clock and pixel clock to the required panel supported
frequency. This change adds support to program dynamic refresh
registers and trigger the dynamic refresh interrupt. Once the current
frame is done, hardware ensures that the change in clock frequency is
taken effect within the vertical blanking period.

Change-Id: I3a1e0eb478c34111e94f977088c20e9a50c4ef25
Signed-off-by: default avatarJeevan Shriram <jshriram@codeaurora.org>
Signed-off-by: default avatarIngrid Gallardo <ingridg@codeaurora.org>
parent 3df28711
Loading
Loading
Loading
Loading
+18 −5
Original line number Diff line number Diff line
@@ -385,11 +385,17 @@
				 <&mdss_dsi0_pll clk_dsi0pll_byte_clk_mux>,
				 <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_mux>,
				 <&mdss_dsi0_pll clk_dsi0pll_byte_clk_src>,
				 <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_src>;
				 <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_src>,
				 <&mdss_dsi0_pll
					clk_dsi0pll_shadow_byte_clk_src>,
				 <&mdss_dsi0_pll
					clk_dsi0pll_shadow_pixel_clk_src>;
			clock-names = "byte_clk", "pixel_clk", "core_clk",
				"byte_clk_rcg", "pixel_clk_rcg",
				"pll_byte_clk_mux", "pll_pixel_clk_mux",
				"pll_byte_clk_src", "pll_pixel_clk_src";
				"pll_byte_clk_src", "pll_pixel_clk_src",
				"pll_shadow_byte_clk_src",
				"pll_shadow_pixel_clk_src";

			qcom,null-insertion-enabled;
			qcom,platform-strength-ctrl = [ff 06
@@ -429,12 +435,19 @@
				 <&clock_mmss clk_pclk1_clk_src>,
				 <&mdss_dsi0_pll clk_dsi0pll_byte_clk_mux>,
				 <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_mux>,
				 <&mdss_dsi0_pll clk_dsi0pll_byte_clk_src>,
				 <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_src>;
				 <&mdss_dsi1_pll clk_dsi1pll_byte_clk_src>,
				 <&mdss_dsi1_pll clk_dsi1pll_pixel_clk_src>,
				 <&mdss_dsi1_pll
					clk_dsi1pll_shadow_byte_clk_src>,
				 <&mdss_dsi1_pll
					clk_dsi1pll_shadow_pixel_clk_src>;
			clock-names = "byte_clk", "pixel_clk", "core_clk",
				"byte_clk_rcg", "pixel_clk_rcg",
				"pll_byte_clk_mux", "pll_pixel_clk_mux",
				"pll_byte_clk_src", "pll_pixel_clk_src";
				"pll_byte_clk_src", "pll_pixel_clk_src",
				"pll_byte_clk_src", "pll_pixel_clk_src",
				"pll_shadow_byte_clk_src",
				"pll_shadow_pixel_clk_src";

			qcom,null-insertion-enabled;
			qcom,platform-strength-ctrl = [ff 06
+291 −127
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include "mdss_panel.h"
#include "mdss_dsi.h"
#include "mdss_debug.h"
#include "mdss_dsi_phy.h"

#define XO_CLK_RATE	19200000
#define CMDLINE_DSI_CTL_NUM_STRING_LEN 2
@@ -1247,6 +1248,7 @@ int mdss_dsi_on(struct mdss_panel_data *pdata)
		 * sent to panel
		 */
		mdss_dsi_read_hw_revision(ctrl_pdata);
		mdss_dsi_read_phy_revision(ctrl_pdata);
		mdss_dsi_restore_intr_mask(ctrl_pdata);
		pr_debug("%s: panel already on\n", __func__);
		goto end;
@@ -1295,6 +1297,7 @@ int mdss_dsi_on(struct mdss_panel_data *pdata)
			  MDSS_DSI_LINK_CLK, MDSS_DSI_CLK_ON);
	mdss_dsi_sw_reset(ctrl_pdata, true);
	mdss_dsi_read_hw_revision(ctrl_pdata);
	mdss_dsi_read_phy_revision(ctrl_pdata);

	/*
	 * Issue hardware reset line after enabling the DSI clocks and data
@@ -1642,13 +1645,33 @@ static void __mdss_dsi_update_video_mode_total(struct mdss_panel_data *pdata,
static void __mdss_dsi_dyn_refresh_config(
		struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
	int reg_data;
	int reg_data = 0;
	u32 phy_rev = mdss_dsi_get_phy_revision(ctrl_pdata);

	reg_data = MIPI_INP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL);
	/* configure only for master control in split display */
	if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) &&
			mdss_dsi_is_ctrl_clk_slave(ctrl_pdata))
		return;

	switch (phy_rev) {
	case DSI_PHY_REV_10:
		reg_data = MIPI_INP((ctrl_pdata->ctrl_base) +
				DSI_DYNAMIC_REFRESH_CTRL);
		reg_data &= ~BIT(12);
		MIPI_OUTP((ctrl_pdata->ctrl_base)
				+ DSI_DYNAMIC_REFRESH_CTRL, reg_data);
		break;
	case DSI_PHY_REV_20:
		reg_data = BIT(13);
		MIPI_OUTP((ctrl_pdata->ctrl_base)
				+ DSI_DYNAMIC_REFRESH_CTRL, reg_data);
		break;
	default:
		pr_err("Phy rev %d unsupported\n", phy_rev);
		break;
	}

	pr_debug("Dynamic fps ctrl = 0x%x\n", reg_data);
	MIPI_OUTP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, reg_data);
}

static void __mdss_dsi_calc_dfps_delay(struct mdss_panel_data *pdata)
@@ -1668,6 +1691,14 @@ static void __mdss_dsi_calc_dfps_delay(struct mdss_panel_data *pdata)

	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
			panel_data);
	if (ctrl_pdata == NULL) {
		pr_err("%s Invalid ctrl_pdata\n", __func__);
		return;
	}

	if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) &&
		mdss_dsi_is_ctrl_clk_slave(ctrl_pdata))
		return;

	pinfo = &pdata->panel_info;
	pd = &(pinfo->mipi.dsi_phy_db);
@@ -1706,13 +1737,14 @@ static void __mdss_dsi_calc_dfps_delay(struct mdss_panel_data *pdata)
						pll_delay);
}

static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata,
static int __mdss_dsi_dfps_calc_clks(struct mdss_panel_data *pdata,
		int new_fps)
{
	int rc = 0;
	u32 data;
	u64 clk_rate;
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
	struct mdss_panel_info *pinfo;
	u32 phy_rev;

	if (pdata == NULL) {
		pr_err("%s Invalid pdata\n", __func__);
@@ -1726,6 +1758,9 @@ static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata,
		return -EINVAL;
	}

	pinfo = &pdata->panel_info;
	phy_rev = mdss_dsi_get_phy_revision(ctrl_pdata);

	rc = mdss_dsi_clk_div_config
		(&ctrl_pdata->panel_data.panel_info, new_fps);
	if (rc) {
@@ -1734,42 +1769,116 @@ static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata,
		return rc;
	}

	if (pdata->panel_info.dfps_update
			== DFPS_IMMEDIATE_CLK_UPDATE_MODE) {
	__mdss_dsi_dyn_refresh_config(ctrl_pdata);

	if (phy_rev == DSI_PHY_REV_20)
		mdss_dsi_dfps_config_8996(ctrl_pdata);

	__mdss_dsi_calc_dfps_delay(pdata);
		ctrl_pdata->pclk_rate =
			pdata->panel_info.mipi.dsi_pclk_rate;
		clk_rate = pdata->panel_info.clk_rate;

	/* take a backup of current clk rates */
	ctrl_pdata->pclk_rate_bkp = ctrl_pdata->pclk_rate;
	ctrl_pdata->byte_clk_rate_bkp = ctrl_pdata->byte_clk_rate;

	ctrl_pdata->pclk_rate = pinfo->mipi.dsi_pclk_rate;
	clk_rate = pinfo->clk_rate;
	do_div(clk_rate, 8U);
	ctrl_pdata->byte_clk_rate = (u32) clk_rate;

	pr_debug("byte_rate=%i\n", ctrl_pdata->byte_clk_rate);
	pr_debug("pclk_rate=%i\n", ctrl_pdata->pclk_rate);

		if (mdss_dsi_is_ctrl_clk_slave(ctrl_pdata)) {
			pr_debug("%s DFPS already updated.\n", __func__);
			ctrl_pdata->panel_data.panel_info.mipi.frame_rate =
				new_fps;
	return rc;
}

		/* add an extra reference to main clks */
		clk_prepare_enable(ctrl_pdata->pll_byte_clk);
		clk_prepare_enable(ctrl_pdata->pll_pixel_clk);
static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata,
		int new_fps)
{
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
	struct mdss_dsi_ctrl_pdata *sctrl_pdata = NULL;
	struct mdss_panel_info *pinfo, *spinfo;
	int rc = 0;
	u32 data;

	if (pdata == NULL) {
		pr_err("%s Invalid pdata\n", __func__);
		return -EINVAL;
	}

	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
			panel_data);
	if (IS_ERR_OR_NULL(ctrl_pdata)) {
		pr_err("Invalid sctrl_pdata = %lu\n", PTR_ERR(ctrl_pdata));
		return PTR_ERR(ctrl_pdata);
	}

	pinfo = &ctrl_pdata->panel_data.panel_info;

	/*
	 * In split display case, configure and enable dynamic refresh
	 * register only after both the ctrl data is programmed. So,
	 * ignore enabling dynamic refresh for the master control and
	 * configure only when it is slave control.
	 */
	if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) &&
			mdss_dsi_is_ctrl_clk_master(ctrl_pdata))
		return 0;

	if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) &&
			mdss_dsi_is_ctrl_clk_slave(ctrl_pdata)) {
		sctrl_pdata = ctrl_pdata;
		spinfo = pinfo;
		ctrl_pdata = mdss_dsi_get_ctrl_clk_master();
		if (IS_ERR_OR_NULL(ctrl_pdata)) {
			pr_err("Invalid ctrl_pdata = %lu\n",
					PTR_ERR(ctrl_pdata));
			return PTR_ERR(ctrl_pdata);
		}

		pinfo = &ctrl_pdata->panel_data.panel_info;
	}

	/*
	 * For programming dynamic refresh registers, we need to change
	 * the parent to shadow clocks for the software byte and pixel mux.
	 * After switching to shadow clocks, if there is no ref count on
	 * main byte and pixel clocks, clock driver may shutdown those
	 * unreferenced  byte and pixel clocks. Hence add an extra reference
	 * count to avoid shutting down the main byte and pixel clocks.
	 */
	rc = clk_prepare_enable(ctrl_pdata->pll_byte_clk);
	if (rc) {
		pr_err("Unable to add extra refcnt for byte clock\n");
		goto error_byte;
	}

	rc = clk_prepare_enable(ctrl_pdata->pll_pixel_clk);
	if (rc) {
		pr_err("Unable to add extra refcnt for pixel clock\n");
		goto error_pixel;
	}

	/* change the parent to shadow clocks*/
		clk_set_parent(ctrl_pdata->mux_byte_clk,
	rc = clk_set_parent(ctrl_pdata->mux_byte_clk,
			ctrl_pdata->shadow_byte_clk);
		clk_set_parent(ctrl_pdata->mux_pixel_clk,
	if (rc) {
		pr_err("Unable to set parent to shadow byte clock\n");
		goto error_shadow_byte;
	}

	rc = clk_set_parent(ctrl_pdata->mux_pixel_clk,
			ctrl_pdata->shadow_pixel_clk);
	if (rc) {
		pr_err("Unable to set parent to shadow pixel clock\n");
		goto error_shadow_pixel;
	}

	rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle,
			MDSS_DSI_LINK_BYTE_CLK, ctrl_pdata->byte_clk_rate, 0);
	if (rc) {
		pr_err("%s: dsi_byte_clk - clk_set_rate failed\n",
				__func__);
			return rc;
		goto error_byte_link;
	}

	rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle,
@@ -1777,55 +1886,94 @@ static int __mdss_dsi_dfps_update_clks(struct mdss_panel_data *pdata,
	if (rc) {
		pr_err("%s: dsi_pixel_clk - clk_set_rate failed\n",
				__func__);
			return rc;
		goto error_pixel_link;
	}

	if (sctrl_pdata) {
		rc = mdss_dsi_clk_set_link_rate(sctrl_pdata->dsi_clk_handle,
			MDSS_DSI_LINK_BYTE_CLK, sctrl_pdata->byte_clk_rate, 0);
		if (rc) {
			pr_err("%s: slv dsi_byte_clk - clk_set_rate failed\n",
					__func__);
			goto error_sbyte_link;
		}

		rc = mdss_dsi_clk_set_link_rate(sctrl_pdata->dsi_clk_handle,
			MDSS_DSI_LINK_PIX_CLK, sctrl_pdata->pclk_rate, 0);
		if (rc) {
			pr_err("%s: slv dsi_pixel_clk - clk_set_rate failed\n",
					__func__);
			goto error_spixel_link;
		}
	}

	rc = mdss_dsi_en_wait4dynamic_done(ctrl_pdata);
		MIPI_OUTP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL,
	if (rc) {
		pr_err("Unsuccessful dynamic fps change");
		goto dfps_timeout;
	}

	MIPI_OUTP((ctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL, 0x00);
	if (sctrl_pdata)
		MIPI_OUTP((sctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL,
				0x00);

	data = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0120);
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x120, data);
		pr_debug("pll unlock: 0x%x\n", data);
		clk_set_parent(ctrl_pdata->mux_byte_clk,
	if (data & BIT(16)) {
		pr_debug("pll unlocked: 0x%x\n", data);
		/* clear PLL unlock bit */
		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x120, BIT(16));
	}

	/* Move the mux clocks to main byte and pixel clocks */
	rc = clk_set_parent(ctrl_pdata->mux_byte_clk,
			ctrl_pdata->pll_byte_clk);
		clk_set_parent(ctrl_pdata->mux_pixel_clk,
	if (rc)
		pr_err("Unable to set parent back to main byte clock\n");

	rc = clk_set_parent(ctrl_pdata->mux_pixel_clk,
			ctrl_pdata->pll_pixel_clk);
	if (rc)
		pr_err("Unable to set parent back to main pixel clock\n");

	/* Remove extra ref count on parent clocks */
	clk_disable_unprepare(ctrl_pdata->pll_byte_clk);
	clk_disable_unprepare(ctrl_pdata->pll_pixel_clk);

		if (!rc) {
			ctrl_pdata->panel_data.panel_info.mipi.frame_rate =
				new_fps;
			/* we are using current_fps to compare if dfps needed */
			ctrl_pdata->panel_data.panel_info.current_fps =
				new_fps;
		}
	} else {
		ctrl_pdata->pclk_rate =
			pdata->panel_info.mipi.dsi_pclk_rate;
		clk_rate = pdata->panel_info.clk_rate;
		do_div(clk_rate, 8U);
		ctrl_pdata->byte_clk_rate = (u32) clk_rate;
		rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle,
			MDSS_DSI_LINK_BYTE_CLK, ctrl_pdata->byte_clk_rate,
			MDSS_DSI_CLK_UPDATE_CLK_RATE_AT_ON);
		if (rc) {
			pr_err("%s: dsi_byte_clk - clk_set_rate failed\n",
					__func__);
			return rc;
	pinfo->mipi.frame_rate = new_fps;
	pinfo->current_fps = new_fps;
	if (sctrl_pdata) {
		spinfo->mipi.frame_rate = new_fps;
		spinfo->current_fps = new_fps;
	}

		rc = mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle,
			MDSS_DSI_LINK_PIX_CLK, ctrl_pdata->pclk_rate,
			MDSS_DSI_CLK_UPDATE_CLK_RATE_AT_ON);
		if (rc) {
			pr_err("%s: dsi_pixel_clk - clk_set_rate failed\n",
				__func__);
	return rc;
		}
	}

dfps_timeout:
	if (sctrl_pdata)
		mdss_dsi_clk_set_link_rate(sctrl_pdata->dsi_clk_handle,
				MDSS_DSI_LINK_PIX_CLK,
				sctrl_pdata->pclk_rate_bkp, 0);
error_spixel_link:
	if (sctrl_pdata)
		mdss_dsi_clk_set_link_rate(sctrl_pdata->dsi_clk_handle,
				MDSS_DSI_LINK_BYTE_CLK,
				sctrl_pdata->byte_clk_rate_bkp, 0);
error_sbyte_link:
	mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle,
		MDSS_DSI_LINK_PIX_CLK, ctrl_pdata->pclk_rate_bkp, 0);
error_pixel_link:
	mdss_dsi_clk_set_link_rate(ctrl_pdata->dsi_clk_handle,
		MDSS_DSI_LINK_BYTE_CLK, ctrl_pdata->byte_clk_rate_bkp, 0);
error_byte_link:
	clk_set_parent(ctrl_pdata->mux_pixel_clk, ctrl_pdata->pll_pixel_clk);
error_shadow_pixel:
	clk_set_parent(ctrl_pdata->mux_byte_clk, ctrl_pdata->pll_byte_clk);
error_shadow_byte:
	clk_disable_unprepare(ctrl_pdata->pll_pixel_clk);
error_pixel:
	clk_disable_unprepare(ctrl_pdata->pll_byte_clk);
error_byte:
	return rc;
}

@@ -1833,8 +1981,9 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps)
{
	int rc = 0;
	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
	struct mdss_dsi_ctrl_pdata *sctrl_pdata = NULL;
	struct mdss_panel_info *pinfo;
	u32 phy_rev;
	u32 frame_rate_bkp;

	pr_debug("%s+:\n", __func__);

@@ -1847,56 +1996,60 @@ static int mdss_dsi_dfps_config(struct mdss_panel_data *pdata, int new_fps)
			panel_data);

	if (!ctrl_pdata->panel_data.panel_info.dynamic_fps) {
		pr_err("%s: Dynamic fps not enabled for this panel\n",
					__func__);
		pr_err("Dynamic fps not enabled for this panel\n");
		return -EINVAL;
	}

	phy_rev = mdss_dsi_get_phy_revision(ctrl_pdata);
	pinfo = &pdata->panel_info;

	frame_rate_bkp = mdss_panel_get_framerate(pinfo);
	if (new_fps == pinfo->mipi.frame_rate) {
		/*
	 * at split display case, DFPS registers were already programmed
	 * while programming the left ctrl(DSI0). Ignore right ctrl (DSI1)
	 * reguest.
		 * This is unlikely as mdss driver checks for previously
		 * configured frame rate.
		 */
	pinfo = &pdata->panel_info;
	if (mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data)) {
		if (mdss_dsi_is_right_ctrl(ctrl_pdata)) {
			pr_debug("%s DFPS already updated.\n", __func__);
			return rc;
		pr_debug("Panel is already at this FPS\n");
		goto end_update;
	}
		/* left ctrl to get right ctrl */
		sctrl_pdata = mdss_dsi_get_other_ctrl(ctrl_pdata);
	}

	if (new_fps !=
		ctrl_pdata->panel_data.panel_info.current_fps) {
		if (pdata->panel_info.dfps_update
			== DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP ||
			pdata->panel_info.dfps_update
			== DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP) {

	if (pinfo->dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_HFP ||
		pinfo->dfps_update == DFPS_IMMEDIATE_PORCH_UPDATE_MODE_VFP) {
		/* Porch method */
		__mdss_dsi_update_video_mode_total(pdata, new_fps);
			if (sctrl_pdata) {
				pr_debug("%s Updating slave ctrl DFPS\n",
						__func__);
				__mdss_dsi_update_video_mode_total(
						&sctrl_pdata->panel_data,
	} else if (pinfo->dfps_update == DFPS_IMMEDIATE_CLK_UPDATE_MODE) {
		/* Clock update method */
		if (phy_rev == DSI_PHY_REV_20) {
			rc = mdss_dsi_phy_calc_timing_param(pinfo, phy_rev,
					new_fps);
			if (rc) {
				pr_err("PHY calculations failed-%d\n", new_fps);
				goto end_update;
			}
		}

		} else {
			rc = __mdss_dsi_dfps_update_clks(pdata, new_fps);
			if (!rc && sctrl_pdata) {
				pr_debug("%s Updating slave ctrl DFPS\n",
						__func__);
				rc = __mdss_dsi_dfps_update_clks(
						&sctrl_pdata->panel_data,
						new_fps);
		rc = __mdss_dsi_dfps_calc_clks(pdata, new_fps);
		if (rc) {
			pr_err("error calculating clocks for %d\n", new_fps);
			goto error_clks;
		}

		rc = __mdss_dsi_dfps_update_clks(pdata,	new_fps);
		if (rc) {
			pr_err("Dynamic refresh failed-%d\n", new_fps);
			goto error_dfps;
		}
	} else {
		pr_debug("%s: Panel is already at this FPS\n", __func__);
	}

	return rc;
error_dfps:
	if (__mdss_dsi_dfps_calc_clks(pdata, frame_rate_bkp))
		pr_err("error reverting clock calculations for %d\n",
				frame_rate_bkp);
error_clks:
	if (mdss_dsi_phy_calc_timing_param(pinfo, phy_rev, frame_rate_bkp))
		pr_err("Unable to revert phy timing-%d\n", frame_rate_bkp);
end_update:
	return rc;
}

@@ -2135,8 +2288,12 @@ static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
		if (arg != NULL) {
			rc = mdss_dsi_dfps_config(pdata,
					 (int) (unsigned long) arg);
			pr_debug("%s:update fps to = %d\n",
				 __func__, (int) (unsigned long) arg);
			if (rc)
				pr_err("unable to change fps-%d, error-%d\n",
						(int) (unsigned long) arg, rc);
			else
				pr_debug("panel frame rate changed to %d\n",
						(int) (unsigned long) arg);
		}
		break;
	case MDSS_EVENT_CONT_SPLASH_BEGIN:
@@ -2651,10 +2808,17 @@ static int mdss_dsi_ctrl_probe(struct platform_device *pdev)
	}

	pinfo = &(ctrl_pdata->panel_data.panel_info);
	if (pinfo->dynamic_fps)
		if (mdss_dsi_shadow_clk_init(pdev, ctrl_pdata))
	if (!(mdss_dsi_is_hw_config_split(ctrl_pdata->shared_data) &&
		mdss_dsi_is_ctrl_clk_slave(ctrl_pdata)) &&
		pinfo->dynamic_fps) {
		rc = mdss_dsi_shadow_clk_init(pdev, ctrl_pdata);

		if (rc) {
			pr_err("%s: unable to initialize shadow ctrl clks\n",
					__func__);
			rc = -EPERM;
		}
	}

	rc = mdss_dsi_set_clk_rates(ctrl_pdata);
	if (rc) {
+10 −0
Original line number Diff line number Diff line
@@ -230,6 +230,7 @@ struct dsi_shared_data {
	u32 hw_config; /* DSI setup configuration i.e. single/dual/split */
	u32 pll_src_config; /* PLL source selection for DSI link clocks */
	u32 hw_rev; /* DSI h/w revision */
	u32 phy_rev; /* DSI PHY revision*/

	/* DSI ULPS clamp register offsets */
	u32 ulps_clamp_ctrl_off;
@@ -439,6 +440,8 @@ struct mdss_dsi_ctrl_pdata {
	struct pwm_device *pwm_bl;
	u32 pclk_rate;
	u32 byte_clk_rate;
	u32 pclk_rate_bkp;
	u32 byte_clk_rate_bkp;
	bool refresh_clk_rate; /* flag to recalculate clk_rate */
	struct dss_module_power panel_power_data;
	struct dss_module_power power_data[DSI_MAX_PM]; /* for 8x10 */
@@ -619,6 +622,7 @@ void mdss_dsi_ctrl_setup(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_dln0_phy_err(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_lp_cd_rx(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_get_hw_revision(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_read_phy_revision(struct mdss_dsi_ctrl_pdata *ctrl);
u32 mdss_dsi_panel_cmd_read(struct mdss_dsi_ctrl_pdata *ctrl, char cmd0,
		char cmd1, void (*fxn)(int), char *rbuf, int len);
int mdss_dsi_panel_init(struct device_node *node,
@@ -639,6 +643,7 @@ void mdss_dsi_panel_dsc_pps_send(struct mdss_dsi_ctrl_pdata *ctrl,
				struct mdss_panel_info *pinfo);
void mdss_dsi_dsc_config(struct mdss_dsi_ctrl_pdata *ctrl,
	struct dsc_desc *dsc);
void mdss_dsi_dfps_config_8996(struct mdss_dsi_ctrl_pdata *ctrl);

static inline const char *__mdss_dsi_pm_name(enum dsi_pm_type module)
{
@@ -735,6 +740,11 @@ static inline bool mdss_dsi_is_dsi1_active(struct dsi_shared_data *sdata)
	return sdata->dsi1_active;
}

static inline u32 mdss_dsi_get_phy_revision(struct mdss_dsi_ctrl_pdata *ctrl)
{
	return ctrl->shared_data->phy_rev;
}

static inline bool mdss_dsi_sync_wait_enable(struct mdss_dsi_ctrl_pdata *ctrl)
{
	return ctrl->cmd_sync_wait_broadcast;
+40 −1
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include "mdss_panel.h"
#include "mdss_debug.h"
#include "mdss_smmu.h"
#include "mdss_dsi_phy.h"

#define VSYNC_PERIOD 17
#define DMA_TX_TIMEOUT 200
@@ -290,6 +291,23 @@ void mdss_dsi_get_hw_revision(struct mdss_dsi_ctrl_pdata *ctrl)
				ctrl->ndx, ctrl->shared_data->hw_rev);
}

void mdss_dsi_read_phy_revision(struct mdss_dsi_ctrl_pdata *ctrl)
{
	u32 reg_val;

	if (ctrl->shared_data->phy_rev > DSI_PHY_REV_UNKNOWN)
		return;

	reg_val = MIPI_INP(ctrl->phy_io.base);

	if (reg_val == DSI_PHY_REV_20)
		ctrl->shared_data->phy_rev = DSI_PHY_REV_20;
	else if (reg_val == DSI_PHY_REV_10)
		ctrl->shared_data->phy_rev = DSI_PHY_REV_10;
	else
		ctrl->shared_data->phy_rev = DSI_PHY_REV_UNKNOWN;
}

void mdss_dsi_host_init(struct mdss_panel_data *pdata)
{
	u32 dsi_ctrl, intr_ctrl;
@@ -2119,6 +2137,7 @@ int mdss_dsi_en_wait4dynamic_done(struct mdss_dsi_ctrl_pdata *ctrl)
	unsigned long flag;
	u32 data;
	int rc = 0;
	struct mdss_dsi_ctrl_pdata *sctrl_pdata;

	/* DSI_INTL_CTRL */
	data = MIPI_INP((ctrl->ctrl_base) + 0x0110);
@@ -2130,8 +2149,21 @@ int mdss_dsi_en_wait4dynamic_done(struct mdss_dsi_ctrl_pdata *ctrl)
	reinit_completion(&ctrl->dynamic_comp);
	mdss_dsi_enable_irq(ctrl, DSI_DYNAMIC_TERM);
	spin_unlock_irqrestore(&ctrl->mdp_lock, flag);

	/*
	 * Ensure that registers are updated before triggering
	 * dynamic refresh
	 */
	wmb();

	MIPI_OUTP((ctrl->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL,
			(BIT(8) | BIT(0)));
		(BIT(13) | BIT(8) | BIT(0)));

	sctrl_pdata = mdss_dsi_get_ctrl_clk_slave();

	if (sctrl_pdata)
		MIPI_OUTP((sctrl_pdata->ctrl_base) + DSI_DYNAMIC_REFRESH_CTRL,
				(BIT(13) | BIT(8) | BIT(0)));

	if (!wait_for_completion_timeout(&ctrl->dynamic_comp,
			msecs_to_jiffies(VSYNC_PERIOD * 4))) {
@@ -2813,6 +2845,7 @@ void mdss_dsi_error(struct mdss_dsi_ctrl_pdata *ctrl)
irqreturn_t mdss_dsi_isr(int irq, void *ptr)
{
	u32 isr;
	u32 intr;
	struct mdss_dsi_ctrl_pdata *ctrl =
			(struct mdss_dsi_ctrl_pdata *)ptr;

@@ -2889,6 +2922,12 @@ irqreturn_t mdss_dsi_isr(int irq, void *ptr)
	if (isr & DSI_INTR_DYNAMIC_REFRESH_DONE) {
		spin_lock(&ctrl->mdp_lock);
		mdss_dsi_disable_irq_nosync(ctrl, DSI_DYNAMIC_TERM);

		/* clear dfps interrupt */
		intr = MIPI_INP(ctrl->ctrl_base + 0x0110);
		intr |= DSI_INTR_DYNAMIC_REFRESH_DONE;
		MIPI_OUTP(ctrl->ctrl_base + 0x0110, intr);

		complete(&ctrl->dynamic_comp);
		spin_unlock(&ctrl->mdp_lock);
	}
+360 −0

File changed.

Preview size limit exceeded, changes collapsed.