diff mbox series

[v6,06/20] drm/i915/icl: Program DSI clock and data lane timing params

Message ID 1537095223-5184-7-git-send-email-madhav.chauhan@intel.com (mailing list archive)
State New, archived
Headers show
Series ICELAKE DSI DRIVER | expand

Commit Message

Chauhan, Madhav Sept. 16, 2018, 10:53 a.m. UTC
This patch programs D-PHY timing parameters for the
clock and data lane (in escape clocks) of DSI
controller (DSI port 0 and 1).
These programmed timings would be used by DSI Controller
to calculate link transition latencies of the data and
clock lanes.

v2: Use newly defined bitfields for data and clock lane

Signed-off-by: Madhav Chauhan <madhav.chauhan@intel.com>
---
 drivers/gpu/drm/i915/icl_dsi.c       |  18 ++++
 drivers/gpu/drm/i915/intel_dsi.h     |   3 +
 drivers/gpu/drm/i915/intel_dsi_vbt.c | 200 +++++++++++++++++++++++++----------
 3 files changed, 165 insertions(+), 56 deletions(-)

Comments

Jani Nikula Sept. 26, 2018, 12:59 p.m. UTC | #1
On Sun, 16 Sep 2018, Madhav Chauhan <madhav.chauhan@intel.com> wrote:
> This patch programs D-PHY timing parameters for the
> clock and data lane (in escape clocks) of DSI
> controller (DSI port 0 and 1).
> These programmed timings would be used by DSI Controller
> to calculate link transition latencies of the data and
> clock lanes.
>
> v2: Use newly defined bitfields for data and clock lane

Ville's review [1] hasn't been addressed.

BR,
Jani.

[1] http://mid.mail-archive.com/20180719161739.GC5565@intel.com

>
> Signed-off-by: Madhav Chauhan <madhav.chauhan@intel.com>
> ---
>  drivers/gpu/drm/i915/icl_dsi.c       |  18 ++++
>  drivers/gpu/drm/i915/intel_dsi.h     |   3 +
>  drivers/gpu/drm/i915/intel_dsi_vbt.c | 200 +++++++++++++++++++++++++----------
>  3 files changed, 165 insertions(+), 56 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c
> index ff5b285..9602b65 100644
> --- a/drivers/gpu/drm/i915/icl_dsi.c
> +++ b/drivers/gpu/drm/i915/icl_dsi.c
> @@ -291,6 +291,24 @@ static void gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder)
>  		tmp |= intel_dsi->init_count;
>  		I915_WRITE(ICL_DSI_T_INIT_MASTER(port), tmp);
>  	}
> +
> +	/* Program DPHY clock lanes timings */
> +	for_each_dsi_port(port, intel_dsi->ports) {
> +		I915_WRITE(DPHY_CLK_TIMING_PARAM(port), intel_dsi->dphy_reg);
> +
> +		/* shadow register inside display core */
> +		I915_WRITE(DSI_CLK_TIMING_PARAM(port), intel_dsi->dphy_reg);
> +	}
> +
> +	/* Program DPHY data lanes timings */
> +	for_each_dsi_port(port, intel_dsi->ports) {
> +		I915_WRITE(DPHY_DATA_TIMING_PARAM(port),
> +			   intel_dsi->dphy_data_lane_reg);
> +
> +		/* shadow register inside display core */
> +		I915_WRITE(DSI_DATA_TIMING_PARAM(port),
> +			   intel_dsi->dphy_data_lane_reg);
> +	}
>  }
>  
>  static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
> diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
> index ad7c1cb..9fd8526 100644
> --- a/drivers/gpu/drm/i915/intel_dsi.h
> +++ b/drivers/gpu/drm/i915/intel_dsi.h
> @@ -85,6 +85,9 @@ struct intel_dsi {
>  	u32 port_bits;
>  	u32 bw_timer;
>  	u32 dphy_reg;
> +
> +	/* data lanes dphy timing */
> +	u32 dphy_data_lane_reg;
>  	u32 video_frmt_cfg_bits;
>  	u16 lp_byte_clk;
>  
> diff --git a/drivers/gpu/drm/i915/intel_dsi_vbt.c b/drivers/gpu/drm/i915/intel_dsi_vbt.c
> index ac83d6b..fbb159b 100644
> --- a/drivers/gpu/drm/i915/intel_dsi_vbt.c
> +++ b/drivers/gpu/drm/i915/intel_dsi_vbt.c
> @@ -509,7 +509,9 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
>  	u32 bpp;
>  	u32 tlpx_ns, extra_byte_count, bitrate, tlpx_ui;
>  	u32 ui_num, ui_den;
> -	u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt;
> +	u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt, hs_zero_cnt;
> +	u32 tclk_pre_cnt, tclk_post_cnt;
> +	u32 tclk_pre_ns, tclk_post_ns;
>  	u32 ths_prepare_ns, tclk_trail_ns;
>  	u32 tclk_prepare_clkzero, ths_prepare_hszero;
>  	u32 lp_to_hs_switch, hs_to_lp_switch;
> @@ -624,76 +626,157 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
>  
>  	tclk_prepare_clkzero = mipi_config->tclk_prepare_clkzero;
>  	ths_prepare_hszero = mipi_config->ths_prepare_hszero;
> -
> +	tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail);
> +	ths_prepare_ns = max(mipi_config->ths_prepare,
> +				mipi_config->tclk_prepare);
>  	/*
>  	 * B060
>  	 * LP byte clock = TLPX/ (8UI)
>  	 */
>  	intel_dsi->lp_byte_clk = DIV_ROUND_UP(tlpx_ns * ui_den, 8 * ui_num);
>  
> -	/* DDR clock period = 2 * UI
> -	 * UI(sec) = 1/(bitrate * 10^3) (bitrate is in KHZ)
> -	 * UI(nsec) = 10^6 / bitrate
> -	 * DDR clock period (nsec) = 2 * UI = (2 * 10^6)/ bitrate
> -	 * DDR clock count  = ns_value / DDR clock period
> -	 *
> +	/*
>  	 * For GEMINILAKE dphy_param_reg will be programmed in terms of
>  	 * HS byte clock count for other platform in HS ddr clock count
>  	 */
>  	mul = IS_GEMINILAKE(dev_priv) ? 8 : 2;
> -	ths_prepare_ns = max(mipi_config->ths_prepare,
> -			     mipi_config->tclk_prepare);
>  
> -	/* prepare count */
> -	prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * ui_den, ui_num * mul);
> +	if (IS_ICELAKE(dev_priv)) {
> +		/*
> +		 * prepare cnt in escape clocks
> +		 * this field represents a hexadecimal value with a precision
> +		 * of 1.2 – i.e. the most significant bit is the integer
> +		 * and the least significant 2 bits are fraction bits.
> +		 * so, the field can represent a range of 0.25 to 1.75
> +		 */
> +		prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * 4, tlpx_ns);
> +
> +		/* clk zero count in escape clocks */
> +		clk_zero_cnt = DIV_ROUND_UP(
> +					(tclk_prepare_clkzero - ths_prepare_ns),
> +					tlpx_ns);
> +
> +		/* trail cnt in escape clocks*/
> +		trail_cnt = DIV_ROUND_UP(tclk_trail_ns, tlpx_ns);
> +
> +		/* tclk pre/post count in escape clocks */
> +		tclk_post_ns = mipi_config->tclk_post;
> +		tclk_pre_ns = mipi_config->tclk_pre;
> +		tclk_pre_cnt = DIV_ROUND_UP(tclk_pre_ns, tlpx_ns);
> +		tclk_post_cnt = DIV_ROUND_UP(tclk_post_ns, tlpx_ns);
> +
> +		/* hs zero cnt in escape clocks */
> +		hs_zero_cnt = DIV_ROUND_UP(
> +					(ths_prepare_hszero - ths_prepare_ns),
> +					tlpx_ns);
> +
> +		/* hs exit zero cnt in escape clocks */
> +		exit_zero_cnt = DIV_ROUND_UP(mipi_config->ths_exit, tlpx_ns);
> +
> +		if (prepare_cnt > 0x7 ||
> +		    clk_zero_cnt > 0xF ||
> +		    tclk_pre_cnt > 0x3 ||
> +		    tclk_post_cnt > 0x7 ||
> +		    trail_cnt > 0x7 ||
> +		    hs_zero_cnt > 0xF ||
> +		    exit_zero_cnt > 0x7) {
> +			DRM_DEBUG_DRIVER("DPHY values crossing max limits,");
> +			DRM_DEBUG_DRIVER("restricting to max values\n");
> +		}
> +
> +		prepare_cnt = (prepare_cnt > 0x7) ? 0x7 : prepare_cnt;
> +		clk_zero_cnt = (clk_zero_cnt > 0xF) ? 0xF : clk_zero_cnt;
> +		tclk_pre_cnt = (tclk_pre_cnt > 0x3) ? 0x3 : tclk_pre_cnt;
> +		tclk_post_cnt = (tclk_post_cnt > 0x7) ? 0x7 : tclk_post_cnt;
> +		trail_cnt = (trail_cnt > 0x7) ? 0x7 : trail_cnt;
> +		hs_zero_cnt = (hs_zero_cnt > 0xF) ? 0xF : hs_zero_cnt;
> +		exit_zero_cnt = (exit_zero_cnt > 0x7) ? 0x7 : exit_zero_cnt;
> +
> +		/* clock lane dphy timings */
> +		intel_dsi->dphy_reg |= (CLK_PREPARE_OVERRIDE |
> +					CLK_PREPARE(prepare_cnt) |
> +					CLK_ZERO_OVERRIDE |
> +					CLK_ZERO(clk_zero_cnt) |
> +					CLK_PRE_OVERRIDE |
> +					CLK_PRE(tclk_pre_cnt) |
> +					CLK_POST_OVERRIDE |
> +					CLK_POST(tclk_post_cnt) |
> +					CLK_TRAIL_OVERRIDE |
> +					CLK_TRAIL(trail_cnt));
> +
> +		/* data lanes dphy timings */
> +		intel_dsi->dphy_data_lane_reg = HS_PREPARE_OVERRIDE |
> +						HS_PREPARE(prepare_cnt) |
> +						HS_ZERO_OVERRIDE |
> +						HS_ZERO(hs_zero_cnt) |
> +						HS_TRAIL_OVERRIDE |
> +						HS_TRAIL(trail_cnt) |
> +						HS_EXIT_OVERRIDE |
> +						HS_EXIT(exit_zero_cnt);
> +	} else {
> +		/*
> +		 * DDR clock period = 2 * UI
> +		 * UI(sec) = 1/(bitrate * 10^3) (bitrate is in KHZ)
> +		 * UI(nsec) = 10^6 / bitrate
> +		 * DDR clock period (nsec) = 2 * UI = (2 * 10^6)/ bitrate
> +		 * DDR clock count  = ns_value / DDR clock period
> +		 */
>  
> -	if (prepare_cnt > PREPARE_CNT_MAX) {
> -		DRM_DEBUG_KMS("prepare count too high %u\n", prepare_cnt);
> -		prepare_cnt = PREPARE_CNT_MAX;
> -	}
> +		/* prepare count */
> +		prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * ui_den,
> +							ui_num * mul);
>  
> -	/* exit zero count */
> -	exit_zero_cnt = DIV_ROUND_UP(
> +		if (prepare_cnt > PREPARE_CNT_MAX) {
> +			DRM_DEBUG_KMS("prepare count too high %u\n",
> +								prepare_cnt);
> +			prepare_cnt = PREPARE_CNT_MAX;
> +		}
> +
> +		/* exit zero count */
> +		exit_zero_cnt = DIV_ROUND_UP(
>  				(ths_prepare_hszero - ths_prepare_ns) * ui_den,
>  				ui_num * mul
>  				);
>  
> -	/*
> -	 * Exit zero is unified val ths_zero and ths_exit
> -	 * minimum value for ths_exit = 110ns
> -	 * min (exit_zero_cnt * 2) = 110/UI
> -	 * exit_zero_cnt = 55/UI
> -	 */
> -	if (exit_zero_cnt < (55 * ui_den / ui_num) && (55 * ui_den) % ui_num)
> -		exit_zero_cnt += 1;
> -
> -	if (exit_zero_cnt > EXIT_ZERO_CNT_MAX) {
> -		DRM_DEBUG_KMS("exit zero count too high %u\n", exit_zero_cnt);
> -		exit_zero_cnt = EXIT_ZERO_CNT_MAX;
> -	}
> +		/*
> +		 * Exit zero is unified val ths_zero and ths_exit
> +		 * minimum value for ths_exit = 110ns
> +		 * min (exit_zero_cnt * 2) = 110/UI
> +		 * exit_zero_cnt = 55/UI
> +		 */
> +		if (exit_zero_cnt < (55 * ui_den / ui_num) &&
> +					(55 * ui_den) % ui_num)
> +			exit_zero_cnt += 1;
> +
> +		if (exit_zero_cnt > EXIT_ZERO_CNT_MAX) {
> +			DRM_DEBUG_KMS("exit zero count too high %u\n",
> +								exit_zero_cnt);
> +			exit_zero_cnt = EXIT_ZERO_CNT_MAX;
> +		}
>  
> -	/* clk zero count */
> -	clk_zero_cnt = DIV_ROUND_UP(
> -				(tclk_prepare_clkzero -	ths_prepare_ns)
> -				* ui_den, ui_num * mul);
> +		/* clk zero count */
> +		clk_zero_cnt = DIV_ROUND_UP((tclk_prepare_clkzero -
> +						ths_prepare_ns)
> +						* ui_den, ui_num * mul);
>  
> -	if (clk_zero_cnt > CLK_ZERO_CNT_MAX) {
> -		DRM_DEBUG_KMS("clock zero count too high %u\n", clk_zero_cnt);
> -		clk_zero_cnt = CLK_ZERO_CNT_MAX;
> -	}
> +		if (clk_zero_cnt > CLK_ZERO_CNT_MAX) {
> +			DRM_DEBUG_KMS("clock zero count too high %u\n",
> +								clk_zero_cnt);
> +			clk_zero_cnt = CLK_ZERO_CNT_MAX;
> +		}
>  
> -	/* trail count */
> -	tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail);
> -	trail_cnt = DIV_ROUND_UP(tclk_trail_ns * ui_den, ui_num * mul);
> +		/* trail cnt */
> +		trail_cnt = DIV_ROUND_UP(tclk_trail_ns * ui_den, ui_num * mul);
>  
> -	if (trail_cnt > TRAIL_CNT_MAX) {
> -		DRM_DEBUG_KMS("trail count too high %u\n", trail_cnt);
> -		trail_cnt = TRAIL_CNT_MAX;
> -	}
> +		if (trail_cnt > TRAIL_CNT_MAX) {
> +			DRM_DEBUG_KMS("trail count too high %u\n", trail_cnt);
> +			trail_cnt = TRAIL_CNT_MAX;
> +		}
>  
> -	/* B080 */
> -	intel_dsi->dphy_reg = exit_zero_cnt << 24 | trail_cnt << 16 |
> +		/* B080 */
> +		intel_dsi->dphy_reg = exit_zero_cnt << 24 | trail_cnt << 16 |
>  						clk_zero_cnt << 8 | prepare_cnt;
> +	}
>  
>  	/*
>  	 * LP to HS switch count = 4TLPX + PREP_COUNT * mul + EXIT_ZERO_COUNT *
> @@ -707,9 +790,10 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
>  	 */
>  	tlpx_ui = DIV_ROUND_UP(tlpx_ns * ui_den, ui_num);
>  
> -	/* B044 */
> -	/* FIXME:
> -	 * The comment above does not match with the code */
> +	/*
> +	 * B044
> +	 * FIXME: comment above does not match with the code
> +	 */
>  	lp_to_hs_switch = DIV_ROUND_UP(4 * tlpx_ui + prepare_cnt * mul +
>  						exit_zero_cnt * mul + 10, 8);
>  
> @@ -718,8 +802,9 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
>  	intel_dsi->hs_to_lp_count = max(lp_to_hs_switch, hs_to_lp_switch);
>  	intel_dsi->hs_to_lp_count += extra_byte_count;
>  
> -	/* B088 */
> -	/* LP -> HS for clock lanes
> +	/*
> +	 * B088
> +	 * LP -> HS for clock lanes
>  	 * LP clk sync + LP11 + LP01 + tclk_prepare + tclk_zero +
>  	 *						extra byte count
>  	 * 2TPLX + 1TLPX + 1 TPLX(in ns) + prepare_cnt * 2 + clk_zero_cnt *
> @@ -735,7 +820,8 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
>  
>  	intel_dsi->clk_lp_to_hs_count += extra_byte_count;
>  
> -	/* HS->LP for Clock Lanes
> +	/*
> +	 * HS->LP for Clock Lanes
>  	 * Low Power clock synchronisations + 1Tx byteclk + tclk_trail +
>  	 *						Extra byte count
>  	 * 2TLPX + 8UI + (trail_count*2)(in UI) + Extra byte count
> @@ -782,9 +868,11 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
>  	DRM_DEBUG_KMS("BTA %s\n",
>  			enableddisabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA)));
>  
> -	/* delays in VBT are in unit of 100us, so need to convert
> +	/*
> +	 * delays in VBT are in unit of 100us, so need to convert
>  	 * here in ms
> -	 * Delay (100us) * 100 /1000 = Delay / 10 (ms) */
> +	 * Delay (100us) * 100 /1000 = Delay / 10 (ms)
> +	 */
>  	intel_dsi->backlight_off_delay = pps->bl_disable_delay / 10;
>  	intel_dsi->backlight_on_delay = pps->bl_enable_delay / 10;
>  	intel_dsi->panel_on_delay = pps->panel_on_delay / 10;
Chauhan, Madhav Sept. 26, 2018, 1:08 p.m. UTC | #2
> -----Original Message-----
> From: Nikula, Jani
> Sent: Wednesday, September 26, 2018 6:29 PM
> To: Chauhan, Madhav <madhav.chauhan@intel.com>; intel-
> gfx@lists.freedesktop.org
> Cc: Kulkarni, Vandita <vandita.kulkarni@intel.com>; Vivi, Rodrigo
> <rodrigo.vivi@intel.com>; Rangappa, Komala B
> <komala.b.rangappa@intel.com>; Chauhan, Madhav
> <madhav.chauhan@intel.com>
> Subject: Re: [PATCH v6 06/20] drm/i915/icl: Program DSI clock and data lane
> timing params
> 
> On Sun, 16 Sep 2018, Madhav Chauhan <madhav.chauhan@intel.com>
> wrote:
> > This patch programs D-PHY timing parameters for the clock and data
> > lane (in escape clocks) of DSI controller (DSI port 0 and 1).
> > These programmed timings would be used by DSI Controller to calculate
> > link transition latencies of the data and clock lanes.
> >
> > v2: Use newly defined bitfields for data and clock lane
> 
> Ville's review [1] hasn't been addressed.

Oh..Overlooked the comments. My bad.
Will address them while publishing v7.

Regards,
Madhav

> 
> BR,
> Jani.
> 
> [1] http://mid.mail-archive.com/20180719161739.GC5565@intel.com
> 
> >
> > Signed-off-by: Madhav Chauhan <madhav.chauhan@intel.com>
> > ---
> >  drivers/gpu/drm/i915/icl_dsi.c       |  18 ++++
> >  drivers/gpu/drm/i915/intel_dsi.h     |   3 +
> >  drivers/gpu/drm/i915/intel_dsi_vbt.c | 200
> > +++++++++++++++++++++++++----------
> >  3 files changed, 165 insertions(+), 56 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/icl_dsi.c
> > b/drivers/gpu/drm/i915/icl_dsi.c index ff5b285..9602b65 100644
> > --- a/drivers/gpu/drm/i915/icl_dsi.c
> > +++ b/drivers/gpu/drm/i915/icl_dsi.c
> > @@ -291,6 +291,24 @@ static void gen11_dsi_setup_dphy_timings(struct
> intel_encoder *encoder)
> >  		tmp |= intel_dsi->init_count;
> >  		I915_WRITE(ICL_DSI_T_INIT_MASTER(port), tmp);
> >  	}
> > +
> > +	/* Program DPHY clock lanes timings */
> > +	for_each_dsi_port(port, intel_dsi->ports) {
> > +		I915_WRITE(DPHY_CLK_TIMING_PARAM(port), intel_dsi-
> >dphy_reg);
> > +
> > +		/* shadow register inside display core */
> > +		I915_WRITE(DSI_CLK_TIMING_PARAM(port), intel_dsi-
> >dphy_reg);
> > +	}
> > +
> > +	/* Program DPHY data lanes timings */
> > +	for_each_dsi_port(port, intel_dsi->ports) {
> > +		I915_WRITE(DPHY_DATA_TIMING_PARAM(port),
> > +			   intel_dsi->dphy_data_lane_reg);
> > +
> > +		/* shadow register inside display core */
> > +		I915_WRITE(DSI_DATA_TIMING_PARAM(port),
> > +			   intel_dsi->dphy_data_lane_reg);
> > +	}
> >  }
> >
> >  static void gen11_dsi_enable_port_and_phy(struct intel_encoder
> > *encoder) diff --git a/drivers/gpu/drm/i915/intel_dsi.h
> > b/drivers/gpu/drm/i915/intel_dsi.h
> > index ad7c1cb..9fd8526 100644
> > --- a/drivers/gpu/drm/i915/intel_dsi.h
> > +++ b/drivers/gpu/drm/i915/intel_dsi.h
> > @@ -85,6 +85,9 @@ struct intel_dsi {
> >  	u32 port_bits;
> >  	u32 bw_timer;
> >  	u32 dphy_reg;
> > +
> > +	/* data lanes dphy timing */
> > +	u32 dphy_data_lane_reg;
> >  	u32 video_frmt_cfg_bits;
> >  	u16 lp_byte_clk;
> >
> > diff --git a/drivers/gpu/drm/i915/intel_dsi_vbt.c
> > b/drivers/gpu/drm/i915/intel_dsi_vbt.c
> > index ac83d6b..fbb159b 100644
> > --- a/drivers/gpu/drm/i915/intel_dsi_vbt.c
> > +++ b/drivers/gpu/drm/i915/intel_dsi_vbt.c
> > @@ -509,7 +509,9 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi,
> u16 panel_id)
> >  	u32 bpp;
> >  	u32 tlpx_ns, extra_byte_count, bitrate, tlpx_ui;
> >  	u32 ui_num, ui_den;
> > -	u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt;
> > +	u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt, hs_zero_cnt;
> > +	u32 tclk_pre_cnt, tclk_post_cnt;
> > +	u32 tclk_pre_ns, tclk_post_ns;
> >  	u32 ths_prepare_ns, tclk_trail_ns;
> >  	u32 tclk_prepare_clkzero, ths_prepare_hszero;
> >  	u32 lp_to_hs_switch, hs_to_lp_switch; @@ -624,76 +626,157 @@
> bool
> > intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
> >
> >  	tclk_prepare_clkzero = mipi_config->tclk_prepare_clkzero;
> >  	ths_prepare_hszero = mipi_config->ths_prepare_hszero;
> > -
> > +	tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail);
> > +	ths_prepare_ns = max(mipi_config->ths_prepare,
> > +				mipi_config->tclk_prepare);
> >  	/*
> >  	 * B060
> >  	 * LP byte clock = TLPX/ (8UI)
> >  	 */
> >  	intel_dsi->lp_byte_clk = DIV_ROUND_UP(tlpx_ns * ui_den, 8 *
> ui_num);
> >
> > -	/* DDR clock period = 2 * UI
> > -	 * UI(sec) = 1/(bitrate * 10^3) (bitrate is in KHZ)
> > -	 * UI(nsec) = 10^6 / bitrate
> > -	 * DDR clock period (nsec) = 2 * UI = (2 * 10^6)/ bitrate
> > -	 * DDR clock count  = ns_value / DDR clock period
> > -	 *
> > +	/*
> >  	 * For GEMINILAKE dphy_param_reg will be programmed in terms of
> >  	 * HS byte clock count for other platform in HS ddr clock count
> >  	 */
> >  	mul = IS_GEMINILAKE(dev_priv) ? 8 : 2;
> > -	ths_prepare_ns = max(mipi_config->ths_prepare,
> > -			     mipi_config->tclk_prepare);
> >
> > -	/* prepare count */
> > -	prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * ui_den, ui_num *
> mul);
> > +	if (IS_ICELAKE(dev_priv)) {
> > +		/*
> > +		 * prepare cnt in escape clocks
> > +		 * this field represents a hexadecimal value with a precision
> > +		 * of 1.2 – i.e. the most significant bit is the integer
> > +		 * and the least significant 2 bits are fraction bits.
> > +		 * so, the field can represent a range of 0.25 to 1.75
> > +		 */
> > +		prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * 4, tlpx_ns);
> > +
> > +		/* clk zero count in escape clocks */
> > +		clk_zero_cnt = DIV_ROUND_UP(
> > +					(tclk_prepare_clkzero -
> ths_prepare_ns),
> > +					tlpx_ns);
> > +
> > +		/* trail cnt in escape clocks*/
> > +		trail_cnt = DIV_ROUND_UP(tclk_trail_ns, tlpx_ns);
> > +
> > +		/* tclk pre/post count in escape clocks */
> > +		tclk_post_ns = mipi_config->tclk_post;
> > +		tclk_pre_ns = mipi_config->tclk_pre;
> > +		tclk_pre_cnt = DIV_ROUND_UP(tclk_pre_ns, tlpx_ns);
> > +		tclk_post_cnt = DIV_ROUND_UP(tclk_post_ns, tlpx_ns);
> > +
> > +		/* hs zero cnt in escape clocks */
> > +		hs_zero_cnt = DIV_ROUND_UP(
> > +					(ths_prepare_hszero -
> ths_prepare_ns),
> > +					tlpx_ns);
> > +
> > +		/* hs exit zero cnt in escape clocks */
> > +		exit_zero_cnt = DIV_ROUND_UP(mipi_config->ths_exit,
> tlpx_ns);
> > +
> > +		if (prepare_cnt > 0x7 ||
> > +		    clk_zero_cnt > 0xF ||
> > +		    tclk_pre_cnt > 0x3 ||
> > +		    tclk_post_cnt > 0x7 ||
> > +		    trail_cnt > 0x7 ||
> > +		    hs_zero_cnt > 0xF ||
> > +		    exit_zero_cnt > 0x7) {
> > +			DRM_DEBUG_DRIVER("DPHY values crossing max
> limits,");
> > +			DRM_DEBUG_DRIVER("restricting to max values\n");
> > +		}
> > +
> > +		prepare_cnt = (prepare_cnt > 0x7) ? 0x7 : prepare_cnt;
> > +		clk_zero_cnt = (clk_zero_cnt > 0xF) ? 0xF : clk_zero_cnt;
> > +		tclk_pre_cnt = (tclk_pre_cnt > 0x3) ? 0x3 : tclk_pre_cnt;
> > +		tclk_post_cnt = (tclk_post_cnt > 0x7) ? 0x7 : tclk_post_cnt;
> > +		trail_cnt = (trail_cnt > 0x7) ? 0x7 : trail_cnt;
> > +		hs_zero_cnt = (hs_zero_cnt > 0xF) ? 0xF : hs_zero_cnt;
> > +		exit_zero_cnt = (exit_zero_cnt > 0x7) ? 0x7 : exit_zero_cnt;
> > +
> > +		/* clock lane dphy timings */
> > +		intel_dsi->dphy_reg |= (CLK_PREPARE_OVERRIDE |
> > +					CLK_PREPARE(prepare_cnt) |
> > +					CLK_ZERO_OVERRIDE |
> > +					CLK_ZERO(clk_zero_cnt) |
> > +					CLK_PRE_OVERRIDE |
> > +					CLK_PRE(tclk_pre_cnt) |
> > +					CLK_POST_OVERRIDE |
> > +					CLK_POST(tclk_post_cnt) |
> > +					CLK_TRAIL_OVERRIDE |
> > +					CLK_TRAIL(trail_cnt));
> > +
> > +		/* data lanes dphy timings */
> > +		intel_dsi->dphy_data_lane_reg = HS_PREPARE_OVERRIDE |
> > +						HS_PREPARE(prepare_cnt) |
> > +						HS_ZERO_OVERRIDE |
> > +						HS_ZERO(hs_zero_cnt) |
> > +						HS_TRAIL_OVERRIDE |
> > +						HS_TRAIL(trail_cnt) |
> > +						HS_EXIT_OVERRIDE |
> > +						HS_EXIT(exit_zero_cnt);
> > +	} else {
> > +		/*
> > +		 * DDR clock period = 2 * UI
> > +		 * UI(sec) = 1/(bitrate * 10^3) (bitrate is in KHZ)
> > +		 * UI(nsec) = 10^6 / bitrate
> > +		 * DDR clock period (nsec) = 2 * UI = (2 * 10^6)/ bitrate
> > +		 * DDR clock count  = ns_value / DDR clock period
> > +		 */
> >
> > -	if (prepare_cnt > PREPARE_CNT_MAX) {
> > -		DRM_DEBUG_KMS("prepare count too high %u\n",
> prepare_cnt);
> > -		prepare_cnt = PREPARE_CNT_MAX;
> > -	}
> > +		/* prepare count */
> > +		prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * ui_den,
> > +							ui_num * mul);
> >
> > -	/* exit zero count */
> > -	exit_zero_cnt = DIV_ROUND_UP(
> > +		if (prepare_cnt > PREPARE_CNT_MAX) {
> > +			DRM_DEBUG_KMS("prepare count too high %u\n",
> > +								prepare_cnt);
> > +			prepare_cnt = PREPARE_CNT_MAX;
> > +		}
> > +
> > +		/* exit zero count */
> > +		exit_zero_cnt = DIV_ROUND_UP(
> >  				(ths_prepare_hszero - ths_prepare_ns) *
> ui_den,
> >  				ui_num * mul
> >  				);
> >
> > -	/*
> > -	 * Exit zero is unified val ths_zero and ths_exit
> > -	 * minimum value for ths_exit = 110ns
> > -	 * min (exit_zero_cnt * 2) = 110/UI
> > -	 * exit_zero_cnt = 55/UI
> > -	 */
> > -	if (exit_zero_cnt < (55 * ui_den / ui_num) && (55 * ui_den) %
> ui_num)
> > -		exit_zero_cnt += 1;
> > -
> > -	if (exit_zero_cnt > EXIT_ZERO_CNT_MAX) {
> > -		DRM_DEBUG_KMS("exit zero count too high %u\n",
> exit_zero_cnt);
> > -		exit_zero_cnt = EXIT_ZERO_CNT_MAX;
> > -	}
> > +		/*
> > +		 * Exit zero is unified val ths_zero and ths_exit
> > +		 * minimum value for ths_exit = 110ns
> > +		 * min (exit_zero_cnt * 2) = 110/UI
> > +		 * exit_zero_cnt = 55/UI
> > +		 */
> > +		if (exit_zero_cnt < (55 * ui_den / ui_num) &&
> > +					(55 * ui_den) % ui_num)
> > +			exit_zero_cnt += 1;
> > +
> > +		if (exit_zero_cnt > EXIT_ZERO_CNT_MAX) {
> > +			DRM_DEBUG_KMS("exit zero count too high %u\n",
> > +
> 	exit_zero_cnt);
> > +			exit_zero_cnt = EXIT_ZERO_CNT_MAX;
> > +		}
> >
> > -	/* clk zero count */
> > -	clk_zero_cnt = DIV_ROUND_UP(
> > -				(tclk_prepare_clkzero -	ths_prepare_ns)
> > -				* ui_den, ui_num * mul);
> > +		/* clk zero count */
> > +		clk_zero_cnt = DIV_ROUND_UP((tclk_prepare_clkzero -
> > +						ths_prepare_ns)
> > +						* ui_den, ui_num * mul);
> >
> > -	if (clk_zero_cnt > CLK_ZERO_CNT_MAX) {
> > -		DRM_DEBUG_KMS("clock zero count too high %u\n",
> clk_zero_cnt);
> > -		clk_zero_cnt = CLK_ZERO_CNT_MAX;
> > -	}
> > +		if (clk_zero_cnt > CLK_ZERO_CNT_MAX) {
> > +			DRM_DEBUG_KMS("clock zero count too high %u\n",
> > +								clk_zero_cnt);
> > +			clk_zero_cnt = CLK_ZERO_CNT_MAX;
> > +		}
> >
> > -	/* trail count */
> > -	tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail);
> > -	trail_cnt = DIV_ROUND_UP(tclk_trail_ns * ui_den, ui_num * mul);
> > +		/* trail cnt */
> > +		trail_cnt = DIV_ROUND_UP(tclk_trail_ns * ui_den, ui_num *
> mul);
> >
> > -	if (trail_cnt > TRAIL_CNT_MAX) {
> > -		DRM_DEBUG_KMS("trail count too high %u\n", trail_cnt);
> > -		trail_cnt = TRAIL_CNT_MAX;
> > -	}
> > +		if (trail_cnt > TRAIL_CNT_MAX) {
> > +			DRM_DEBUG_KMS("trail count too high %u\n",
> trail_cnt);
> > +			trail_cnt = TRAIL_CNT_MAX;
> > +		}
> >
> > -	/* B080 */
> > -	intel_dsi->dphy_reg = exit_zero_cnt << 24 | trail_cnt << 16 |
> > +		/* B080 */
> > +		intel_dsi->dphy_reg = exit_zero_cnt << 24 | trail_cnt << 16 |
> >  						clk_zero_cnt << 8 |
> prepare_cnt;
> > +	}
> >
> >  	/*
> >  	 * LP to HS switch count = 4TLPX + PREP_COUNT * mul +
> > EXIT_ZERO_COUNT * @@ -707,9 +790,10 @@ bool intel_dsi_vbt_init(struct
> intel_dsi *intel_dsi, u16 panel_id)
> >  	 */
> >  	tlpx_ui = DIV_ROUND_UP(tlpx_ns * ui_den, ui_num);
> >
> > -	/* B044 */
> > -	/* FIXME:
> > -	 * The comment above does not match with the code */
> > +	/*
> > +	 * B044
> > +	 * FIXME: comment above does not match with the code
> > +	 */
> >  	lp_to_hs_switch = DIV_ROUND_UP(4 * tlpx_ui + prepare_cnt * mul +
> >  						exit_zero_cnt * mul + 10, 8);
> >
> > @@ -718,8 +802,9 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi,
> u16 panel_id)
> >  	intel_dsi->hs_to_lp_count = max(lp_to_hs_switch, hs_to_lp_switch);
> >  	intel_dsi->hs_to_lp_count += extra_byte_count;
> >
> > -	/* B088 */
> > -	/* LP -> HS for clock lanes
> > +	/*
> > +	 * B088
> > +	 * LP -> HS for clock lanes
> >  	 * LP clk sync + LP11 + LP01 + tclk_prepare + tclk_zero +
> >  	 *						extra byte count
> >  	 * 2TPLX + 1TLPX + 1 TPLX(in ns) + prepare_cnt * 2 + clk_zero_cnt *
> > @@ -735,7 +820,8 @@ bool intel_dsi_vbt_init(struct intel_dsi
> > *intel_dsi, u16 panel_id)
> >
> >  	intel_dsi->clk_lp_to_hs_count += extra_byte_count;
> >
> > -	/* HS->LP for Clock Lanes
> > +	/*
> > +	 * HS->LP for Clock Lanes
> >  	 * Low Power clock synchronisations + 1Tx byteclk + tclk_trail +
> >  	 *						Extra byte count
> >  	 * 2TLPX + 8UI + (trail_count*2)(in UI) + Extra byte count @@ -782,9
> > +868,11 @@ bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16
> panel_id)
> >  	DRM_DEBUG_KMS("BTA %s\n",
> >  			enableddisabled(!(intel_dsi->video_frmt_cfg_bits &
> > DISABLE_VIDEO_BTA)));
> >
> > -	/* delays in VBT are in unit of 100us, so need to convert
> > +	/*
> > +	 * delays in VBT are in unit of 100us, so need to convert
> >  	 * here in ms
> > -	 * Delay (100us) * 100 /1000 = Delay / 10 (ms) */
> > +	 * Delay (100us) * 100 /1000 = Delay / 10 (ms)
> > +	 */
> >  	intel_dsi->backlight_off_delay = pps->bl_disable_delay / 10;
> >  	intel_dsi->backlight_on_delay = pps->bl_enable_delay / 10;
> >  	intel_dsi->panel_on_delay = pps->panel_on_delay / 10;
> 
> --
> Jani Nikula, Intel Open Source Graphics Center
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c
index ff5b285..9602b65 100644
--- a/drivers/gpu/drm/i915/icl_dsi.c
+++ b/drivers/gpu/drm/i915/icl_dsi.c
@@ -291,6 +291,24 @@  static void gen11_dsi_setup_dphy_timings(struct intel_encoder *encoder)
 		tmp |= intel_dsi->init_count;
 		I915_WRITE(ICL_DSI_T_INIT_MASTER(port), tmp);
 	}
+
+	/* Program DPHY clock lanes timings */
+	for_each_dsi_port(port, intel_dsi->ports) {
+		I915_WRITE(DPHY_CLK_TIMING_PARAM(port), intel_dsi->dphy_reg);
+
+		/* shadow register inside display core */
+		I915_WRITE(DSI_CLK_TIMING_PARAM(port), intel_dsi->dphy_reg);
+	}
+
+	/* Program DPHY data lanes timings */
+	for_each_dsi_port(port, intel_dsi->ports) {
+		I915_WRITE(DPHY_DATA_TIMING_PARAM(port),
+			   intel_dsi->dphy_data_lane_reg);
+
+		/* shadow register inside display core */
+		I915_WRITE(DSI_DATA_TIMING_PARAM(port),
+			   intel_dsi->dphy_data_lane_reg);
+	}
 }
 
 static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h
index ad7c1cb..9fd8526 100644
--- a/drivers/gpu/drm/i915/intel_dsi.h
+++ b/drivers/gpu/drm/i915/intel_dsi.h
@@ -85,6 +85,9 @@  struct intel_dsi {
 	u32 port_bits;
 	u32 bw_timer;
 	u32 dphy_reg;
+
+	/* data lanes dphy timing */
+	u32 dphy_data_lane_reg;
 	u32 video_frmt_cfg_bits;
 	u16 lp_byte_clk;
 
diff --git a/drivers/gpu/drm/i915/intel_dsi_vbt.c b/drivers/gpu/drm/i915/intel_dsi_vbt.c
index ac83d6b..fbb159b 100644
--- a/drivers/gpu/drm/i915/intel_dsi_vbt.c
+++ b/drivers/gpu/drm/i915/intel_dsi_vbt.c
@@ -509,7 +509,9 @@  bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
 	u32 bpp;
 	u32 tlpx_ns, extra_byte_count, bitrate, tlpx_ui;
 	u32 ui_num, ui_den;
-	u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt;
+	u32 prepare_cnt, exit_zero_cnt, clk_zero_cnt, trail_cnt, hs_zero_cnt;
+	u32 tclk_pre_cnt, tclk_post_cnt;
+	u32 tclk_pre_ns, tclk_post_ns;
 	u32 ths_prepare_ns, tclk_trail_ns;
 	u32 tclk_prepare_clkzero, ths_prepare_hszero;
 	u32 lp_to_hs_switch, hs_to_lp_switch;
@@ -624,76 +626,157 @@  bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
 
 	tclk_prepare_clkzero = mipi_config->tclk_prepare_clkzero;
 	ths_prepare_hszero = mipi_config->ths_prepare_hszero;
-
+	tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail);
+	ths_prepare_ns = max(mipi_config->ths_prepare,
+				mipi_config->tclk_prepare);
 	/*
 	 * B060
 	 * LP byte clock = TLPX/ (8UI)
 	 */
 	intel_dsi->lp_byte_clk = DIV_ROUND_UP(tlpx_ns * ui_den, 8 * ui_num);
 
-	/* DDR clock period = 2 * UI
-	 * UI(sec) = 1/(bitrate * 10^3) (bitrate is in KHZ)
-	 * UI(nsec) = 10^6 / bitrate
-	 * DDR clock period (nsec) = 2 * UI = (2 * 10^6)/ bitrate
-	 * DDR clock count  = ns_value / DDR clock period
-	 *
+	/*
 	 * For GEMINILAKE dphy_param_reg will be programmed in terms of
 	 * HS byte clock count for other platform in HS ddr clock count
 	 */
 	mul = IS_GEMINILAKE(dev_priv) ? 8 : 2;
-	ths_prepare_ns = max(mipi_config->ths_prepare,
-			     mipi_config->tclk_prepare);
 
-	/* prepare count */
-	prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * ui_den, ui_num * mul);
+	if (IS_ICELAKE(dev_priv)) {
+		/*
+		 * prepare cnt in escape clocks
+		 * this field represents a hexadecimal value with a precision
+		 * of 1.2 – i.e. the most significant bit is the integer
+		 * and the least significant 2 bits are fraction bits.
+		 * so, the field can represent a range of 0.25 to 1.75
+		 */
+		prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * 4, tlpx_ns);
+
+		/* clk zero count in escape clocks */
+		clk_zero_cnt = DIV_ROUND_UP(
+					(tclk_prepare_clkzero - ths_prepare_ns),
+					tlpx_ns);
+
+		/* trail cnt in escape clocks*/
+		trail_cnt = DIV_ROUND_UP(tclk_trail_ns, tlpx_ns);
+
+		/* tclk pre/post count in escape clocks */
+		tclk_post_ns = mipi_config->tclk_post;
+		tclk_pre_ns = mipi_config->tclk_pre;
+		tclk_pre_cnt = DIV_ROUND_UP(tclk_pre_ns, tlpx_ns);
+		tclk_post_cnt = DIV_ROUND_UP(tclk_post_ns, tlpx_ns);
+
+		/* hs zero cnt in escape clocks */
+		hs_zero_cnt = DIV_ROUND_UP(
+					(ths_prepare_hszero - ths_prepare_ns),
+					tlpx_ns);
+
+		/* hs exit zero cnt in escape clocks */
+		exit_zero_cnt = DIV_ROUND_UP(mipi_config->ths_exit, tlpx_ns);
+
+		if (prepare_cnt > 0x7 ||
+		    clk_zero_cnt > 0xF ||
+		    tclk_pre_cnt > 0x3 ||
+		    tclk_post_cnt > 0x7 ||
+		    trail_cnt > 0x7 ||
+		    hs_zero_cnt > 0xF ||
+		    exit_zero_cnt > 0x7) {
+			DRM_DEBUG_DRIVER("DPHY values crossing max limits,");
+			DRM_DEBUG_DRIVER("restricting to max values\n");
+		}
+
+		prepare_cnt = (prepare_cnt > 0x7) ? 0x7 : prepare_cnt;
+		clk_zero_cnt = (clk_zero_cnt > 0xF) ? 0xF : clk_zero_cnt;
+		tclk_pre_cnt = (tclk_pre_cnt > 0x3) ? 0x3 : tclk_pre_cnt;
+		tclk_post_cnt = (tclk_post_cnt > 0x7) ? 0x7 : tclk_post_cnt;
+		trail_cnt = (trail_cnt > 0x7) ? 0x7 : trail_cnt;
+		hs_zero_cnt = (hs_zero_cnt > 0xF) ? 0xF : hs_zero_cnt;
+		exit_zero_cnt = (exit_zero_cnt > 0x7) ? 0x7 : exit_zero_cnt;
+
+		/* clock lane dphy timings */
+		intel_dsi->dphy_reg |= (CLK_PREPARE_OVERRIDE |
+					CLK_PREPARE(prepare_cnt) |
+					CLK_ZERO_OVERRIDE |
+					CLK_ZERO(clk_zero_cnt) |
+					CLK_PRE_OVERRIDE |
+					CLK_PRE(tclk_pre_cnt) |
+					CLK_POST_OVERRIDE |
+					CLK_POST(tclk_post_cnt) |
+					CLK_TRAIL_OVERRIDE |
+					CLK_TRAIL(trail_cnt));
+
+		/* data lanes dphy timings */
+		intel_dsi->dphy_data_lane_reg = HS_PREPARE_OVERRIDE |
+						HS_PREPARE(prepare_cnt) |
+						HS_ZERO_OVERRIDE |
+						HS_ZERO(hs_zero_cnt) |
+						HS_TRAIL_OVERRIDE |
+						HS_TRAIL(trail_cnt) |
+						HS_EXIT_OVERRIDE |
+						HS_EXIT(exit_zero_cnt);
+	} else {
+		/*
+		 * DDR clock period = 2 * UI
+		 * UI(sec) = 1/(bitrate * 10^3) (bitrate is in KHZ)
+		 * UI(nsec) = 10^6 / bitrate
+		 * DDR clock period (nsec) = 2 * UI = (2 * 10^6)/ bitrate
+		 * DDR clock count  = ns_value / DDR clock period
+		 */
 
-	if (prepare_cnt > PREPARE_CNT_MAX) {
-		DRM_DEBUG_KMS("prepare count too high %u\n", prepare_cnt);
-		prepare_cnt = PREPARE_CNT_MAX;
-	}
+		/* prepare count */
+		prepare_cnt = DIV_ROUND_UP(ths_prepare_ns * ui_den,
+							ui_num * mul);
 
-	/* exit zero count */
-	exit_zero_cnt = DIV_ROUND_UP(
+		if (prepare_cnt > PREPARE_CNT_MAX) {
+			DRM_DEBUG_KMS("prepare count too high %u\n",
+								prepare_cnt);
+			prepare_cnt = PREPARE_CNT_MAX;
+		}
+
+		/* exit zero count */
+		exit_zero_cnt = DIV_ROUND_UP(
 				(ths_prepare_hszero - ths_prepare_ns) * ui_den,
 				ui_num * mul
 				);
 
-	/*
-	 * Exit zero is unified val ths_zero and ths_exit
-	 * minimum value for ths_exit = 110ns
-	 * min (exit_zero_cnt * 2) = 110/UI
-	 * exit_zero_cnt = 55/UI
-	 */
-	if (exit_zero_cnt < (55 * ui_den / ui_num) && (55 * ui_den) % ui_num)
-		exit_zero_cnt += 1;
-
-	if (exit_zero_cnt > EXIT_ZERO_CNT_MAX) {
-		DRM_DEBUG_KMS("exit zero count too high %u\n", exit_zero_cnt);
-		exit_zero_cnt = EXIT_ZERO_CNT_MAX;
-	}
+		/*
+		 * Exit zero is unified val ths_zero and ths_exit
+		 * minimum value for ths_exit = 110ns
+		 * min (exit_zero_cnt * 2) = 110/UI
+		 * exit_zero_cnt = 55/UI
+		 */
+		if (exit_zero_cnt < (55 * ui_den / ui_num) &&
+					(55 * ui_den) % ui_num)
+			exit_zero_cnt += 1;
+
+		if (exit_zero_cnt > EXIT_ZERO_CNT_MAX) {
+			DRM_DEBUG_KMS("exit zero count too high %u\n",
+								exit_zero_cnt);
+			exit_zero_cnt = EXIT_ZERO_CNT_MAX;
+		}
 
-	/* clk zero count */
-	clk_zero_cnt = DIV_ROUND_UP(
-				(tclk_prepare_clkzero -	ths_prepare_ns)
-				* ui_den, ui_num * mul);
+		/* clk zero count */
+		clk_zero_cnt = DIV_ROUND_UP((tclk_prepare_clkzero -
+						ths_prepare_ns)
+						* ui_den, ui_num * mul);
 
-	if (clk_zero_cnt > CLK_ZERO_CNT_MAX) {
-		DRM_DEBUG_KMS("clock zero count too high %u\n", clk_zero_cnt);
-		clk_zero_cnt = CLK_ZERO_CNT_MAX;
-	}
+		if (clk_zero_cnt > CLK_ZERO_CNT_MAX) {
+			DRM_DEBUG_KMS("clock zero count too high %u\n",
+								clk_zero_cnt);
+			clk_zero_cnt = CLK_ZERO_CNT_MAX;
+		}
 
-	/* trail count */
-	tclk_trail_ns = max(mipi_config->tclk_trail, mipi_config->ths_trail);
-	trail_cnt = DIV_ROUND_UP(tclk_trail_ns * ui_den, ui_num * mul);
+		/* trail cnt */
+		trail_cnt = DIV_ROUND_UP(tclk_trail_ns * ui_den, ui_num * mul);
 
-	if (trail_cnt > TRAIL_CNT_MAX) {
-		DRM_DEBUG_KMS("trail count too high %u\n", trail_cnt);
-		trail_cnt = TRAIL_CNT_MAX;
-	}
+		if (trail_cnt > TRAIL_CNT_MAX) {
+			DRM_DEBUG_KMS("trail count too high %u\n", trail_cnt);
+			trail_cnt = TRAIL_CNT_MAX;
+		}
 
-	/* B080 */
-	intel_dsi->dphy_reg = exit_zero_cnt << 24 | trail_cnt << 16 |
+		/* B080 */
+		intel_dsi->dphy_reg = exit_zero_cnt << 24 | trail_cnt << 16 |
 						clk_zero_cnt << 8 | prepare_cnt;
+	}
 
 	/*
 	 * LP to HS switch count = 4TLPX + PREP_COUNT * mul + EXIT_ZERO_COUNT *
@@ -707,9 +790,10 @@  bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
 	 */
 	tlpx_ui = DIV_ROUND_UP(tlpx_ns * ui_den, ui_num);
 
-	/* B044 */
-	/* FIXME:
-	 * The comment above does not match with the code */
+	/*
+	 * B044
+	 * FIXME: comment above does not match with the code
+	 */
 	lp_to_hs_switch = DIV_ROUND_UP(4 * tlpx_ui + prepare_cnt * mul +
 						exit_zero_cnt * mul + 10, 8);
 
@@ -718,8 +802,9 @@  bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
 	intel_dsi->hs_to_lp_count = max(lp_to_hs_switch, hs_to_lp_switch);
 	intel_dsi->hs_to_lp_count += extra_byte_count;
 
-	/* B088 */
-	/* LP -> HS for clock lanes
+	/*
+	 * B088
+	 * LP -> HS for clock lanes
 	 * LP clk sync + LP11 + LP01 + tclk_prepare + tclk_zero +
 	 *						extra byte count
 	 * 2TPLX + 1TLPX + 1 TPLX(in ns) + prepare_cnt * 2 + clk_zero_cnt *
@@ -735,7 +820,8 @@  bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
 
 	intel_dsi->clk_lp_to_hs_count += extra_byte_count;
 
-	/* HS->LP for Clock Lanes
+	/*
+	 * HS->LP for Clock Lanes
 	 * Low Power clock synchronisations + 1Tx byteclk + tclk_trail +
 	 *						Extra byte count
 	 * 2TLPX + 8UI + (trail_count*2)(in UI) + Extra byte count
@@ -782,9 +868,11 @@  bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id)
 	DRM_DEBUG_KMS("BTA %s\n",
 			enableddisabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA)));
 
-	/* delays in VBT are in unit of 100us, so need to convert
+	/*
+	 * delays in VBT are in unit of 100us, so need to convert
 	 * here in ms
-	 * Delay (100us) * 100 /1000 = Delay / 10 (ms) */
+	 * Delay (100us) * 100 /1000 = Delay / 10 (ms)
+	 */
 	intel_dsi->backlight_off_delay = pps->bl_disable_delay / 10;
 	intel_dsi->backlight_on_delay = pps->bl_enable_delay / 10;
 	intel_dsi->panel_on_delay = pps->panel_on_delay / 10;