drm/msm/dsi-staging: update phy timings when clock is overridden

Currently in dsi driver when dsi bit clock is overridden via
device tree property, then driver is not updating the phy timings
accordingly. This change fixes the same.

Change-Id: I64ebfb4c3ff5b621449c9e5fcbc9212fadca272c
Signed-off-by: Sandeep Panda <spanda@codeaurora.org>
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index 79e3b75..68b0171 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -4264,6 +4264,7 @@
 	int i;
 	struct dsi_display_ctrl *ctrl;
 	struct dsi_display_mode_priv_info *priv_info;
+	struct dsi_host_config *config;
 
 	priv_info = mode->priv_info;
 	if (!dsi_display_has_ext_bridge(display) && !priv_info) {
@@ -4272,9 +4273,9 @@
 		return -EINVAL;
 	}
 
-	rc = dsi_panel_get_host_cfg_for_mode(display->panel,
-					     mode,
-					     &display->config);
+	config = &display->config;
+
+	rc = dsi_panel_get_host_cfg_for_mode(display->panel, mode, config);
 	if (rc) {
 		pr_err("[%s] failed to get host config for mode, rc=%d\n",
 		       display->name, rc);
@@ -4306,8 +4307,16 @@
 
 	for (i = 0; i < display->ctrl_count; i++) {
 		ctrl = &display->ctrl[i];
-		rc = dsi_ctrl_update_host_config(ctrl->ctrl, &display->config,
-				mode->dsi_mode_flags, display->dsi_clk_handle);
+		/*
+		 * if bit clock is overridden then update the phy timings
+		 * and clock out control values first.
+		 */
+		if (config->bit_clk_rate_hz)
+			dsi_phy_update_phy_timings(ctrl->phy, config);
+
+		rc = dsi_ctrl_update_host_config(ctrl->ctrl, config,
+						 mode->dsi_mode_flags,
+						 display->dsi_clk_handle);
 		if (rc) {
 			pr_err("[%s] failed to update ctrl config, rc=%d\n",
 			       display->name, rc);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
index ebc699a..32497ff 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -883,6 +883,8 @@
 						 &phy->cfg.timing, true);
 	if (rc)
 		pr_err("failed to calculate phy timings %d\n", rc);
+	else
+		phy->cfg.is_phy_timing_present = true;
 
 	return rc;
 }
@@ -1045,6 +1047,9 @@
 		return -EINVAL;
 	}
 
+	if (phy->cfg.is_phy_timing_present)
+		return rc;
+
 	mutex_lock(&phy->phy_lock);
 
 	if (phy->hw.ops.phy_timing_val)
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c
index 44d0928..5d9759d 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -434,6 +434,44 @@
 	return rc;
 }
 
+static int calc_clk_post(struct dsi_phy_hw *phy,
+			 struct phy_clk_params *clk_params,
+			 struct phy_timing_desc *desc)
+{
+	struct timing_entry *t = &desc->clk_post;
+	int temp = 0, rc;
+
+	temp = DIV_ROUND_UP(((60 * clk_params->bitclk_mbps) + 9000), 8000) - 1;
+	t->rec = DIV_ROUND_UP((t->rec_max + (9 * temp)), 10);
+
+	rc = dsi_phy_cmn_validate_and_set(t, "clk_post");
+
+	pr_debug("clk_post val 0x%x\n", t->reg_value);
+	return rc;
+}
+
+static int calc_clk_pre(struct dsi_phy_hw *phy,
+			struct phy_clk_params *clk_params,
+			struct phy_timing_desc *desc)
+{
+	struct timing_entry *t = &desc->clk_pre;
+	int temp = 0, rc;
+
+	temp = desc->clk_prepare.reg_value + desc->clk_zero.reg_value +
+		desc->hs_rqst_clk.reg_value + 2;
+
+	if (temp > t->rec_max) {
+		t->rec = DIV_ROUND_UP(((2 * t->rec_max) + (9 * temp)), 10);
+		t->rec = t->rec / 2;
+	} else
+		t->rec = DIV_ROUND_UP((t->rec_max + (9 * temp)), 10);
+
+	rc = dsi_phy_cmn_validate_and_set(t, "clk_pre");
+
+	pr_debug("clk_pre val 0x%x\n", t->reg_value);
+	return rc;
+}
+
 /**
  * dsi_phy_calc_timing_params - calculates timing paramets for a given bit clock
  */
@@ -501,6 +539,19 @@
 		pr_err("hs_rqst_clk calculations failed, rc=%d\n", rc);
 		goto error;
 	}
+
+	rc = calc_clk_post(phy, clk_params, desc);
+	if (rc) {
+		pr_err("clk_post calculation failed, rc= %d\n", rc);
+		goto error;
+	}
+
+	rc = calc_clk_pre(phy, clk_params, desc);
+	if (rc) {
+		pr_err("clk_pre calculation failed, rc= %d\n", rc);
+		goto error;
+	}
+
 error:
 	return rc;
 }
@@ -582,6 +633,8 @@
 	desc.hs_exit.rec_max = hs_exit_reco_max;
 	desc.hs_rqst.mipi_min = hs_rqst_spec_min;
 	desc.hs_rqst_clk.mipi_min = hs_rqst_spec_min;
+	desc.clk_post.rec_max = 63;
+	desc.clk_pre.rec_max = 63;
 
 	if (ops->get_default_phy_params) {
 		ops->get_default_phy_params(&clk_params);
@@ -611,6 +664,9 @@
 
 	if (ops->update_timing_params) {
 		ops->update_timing_params(timing, &desc);
+		/* update clock out timing control values */
+		host->t_clk_pre = desc.clk_pre.reg_value;
+		host->t_clk_post = desc.clk_post.reg_value;
 	} else {
 		rc = -EINVAL;
 		goto error;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c
index c0e9d44..c169a43 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,14 +17,14 @@
 void dsi_phy_hw_v3_0_get_default_phy_params(
 		struct phy_clk_params *params)
 {
-	params->clk_prep_buf = 0;
-	params->clk_zero_buf = 0;
-	params->clk_trail_buf = 0;
-	params->hs_prep_buf = 0;
-	params->hs_zero_buf = 0;
-	params->hs_trail_buf = 0;
+	params->clk_prep_buf = 50;
+	params->clk_zero_buf = 2;
+	params->clk_trail_buf = 30;
+	params->hs_prep_buf = 50;
+	params->hs_zero_buf = 10;
+	params->hs_trail_buf = 30;
 	params->hs_rqst_buf = 0;
-	params->hs_exit_buf = 0;
+	params->hs_exit_buf = 10;
 }
 
 int32_t dsi_phy_hw_v3_0_calc_clk_zero(s64 rec_temp1, s64 mult)