diff mbox

[v5,02/13] drm/i915/icl: DSI vswing programming sequence

Message ID 1531215614-6828-3-git-send-email-madhav.chauhan@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Chauhan, Madhav July 10, 2018, 9:40 a.m. UTC
This patch setup voltage swing before enabling
combo PHY DDI (shared with DSI).
Note that DSI voltage swing programming is for
high speed data buffers. HW automatically handles
the voltage swing for the low power data buffers.

v2: Rebase

Signed-off-by: Madhav Chauhan <madhav.chauhan@intel.com>
---
 drivers/gpu/drm/i915/icl_dsi.c | 114 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 114 insertions(+)

Comments

Kulkarni, Vandita Sept. 6, 2018, 2:01 p.m. UTC | #1
On 7/10/2018 3:10 PM, Madhav Chauhan wrote:
> This patch setup voltage swing before enabling
> combo PHY DDI (shared with DSI).
> Note that DSI voltage swing programming is for
> high speed data buffers. HW automatically handles
> the voltage swing for the low power data buffers.
>
> v2: Rebase
>
> Signed-off-by: Madhav Chauhan <madhav.chauhan@intel.com>
> ---
>   drivers/gpu/drm/i915/icl_dsi.c | 114 +++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 114 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c
> index a571339..dc16c1f 100644
> --- a/drivers/gpu/drm/i915/icl_dsi.c
> +++ b/drivers/gpu/drm/i915/icl_dsi.c
> @@ -27,6 +27,65 @@
>   
>   #include "intel_dsi.h"
>   
> +static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
> +	enum port port;
> +	u32 tmp;
> +	int lane;
> +
> +	for_each_dsi_port(port, intel_dsi->ports) {
> +
> +		/* Bspec: set scaling mode to 0x6 */
> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
> +		tmp |= SCALING_MODE_SEL(6);
> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
> +		tmp |= SCALING_MODE_SEL(6);
> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
> +		tmp |= TAP2_DISABLE | TAP3_DISABLE;
> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
> +		tmp |= TAP2_DISABLE | TAP3_DISABLE;
> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
> +
> +		/*
> +		 * swing and scaling values are taken from DSI
> +		 * table under vswing programming sequence for
> +		 * combo phy ddi in BSPEC.
> +		 * program swing values
> +		 */
> +		tmp = I915_READ(ICL_PORT_TX_DW2_LN0(port));
> +		tmp |= SWING_SEL_UPPER(0x2);
> +		tmp |= SWING_SEL_LOWER(0x2);
> +		tmp |= RCOMP_SCALAR(0x98);
> +		I915_WRITE(ICL_PORT_TX_DW2_GRP(port), tmp);
> +		tmp = I915_READ(ICL_PORT_TX_DW2_AUX(port));
> +		tmp |= SWING_SEL_UPPER(0x2);
> +		tmp |= SWING_SEL_LOWER(0x2);
> +		tmp |= RCOMP_SCALAR(0x98);
> +		I915_WRITE(ICL_PORT_TX_DW2_AUX(port), tmp);
> +
> +		/* program scaling values */
> +		tmp = I915_READ(ICL_PORT_TX_DW4_AUX(port));
> +		tmp |= POST_CURSOR_1(0x0);
> +		tmp |= POST_CURSOR_2(0x0);
> +		tmp |= CURSOR_COEFF(0x18);
> +		I915_WRITE(ICL_PORT_TX_DW4_AUX(port), tmp);
> +
> +		for (lane = 0; lane <= 3; lane++) {
> +			/* Bspec: must not use GRP register for write */
> +			tmp = I915_READ(ICL_PORT_TX_DW4_LN(port, lane));
> +			tmp |= POST_CURSOR_1(0x0);
> +			tmp |= POST_CURSOR_2(0x0);
> +			tmp |= CURSOR_COEFF(0x18);
> +			I915_WRITE(ICL_PORT_TX_DW4_LN(port, lane), tmp);
> +		}
> +	}
> +}
> +
>   static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder)
>   {
>   	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> @@ -140,6 +199,58 @@ static void gen11_dsi_config_phy_lanes_sequence(struct intel_encoder *encoder)
>   	}
>   }
>   

I see from the bspec that except for the Loadgen Select and Latency 
Optimization all other DDI buffer programming can be taken from the DDI 
Buffer section.

Can we use this function "icl_ddi_combo_vswing_program" function which 
is already there
patch for reference:
https://patchwork.freedesktop.org/patch/213515/

Thanks,
Vandita

> +static void gen11_dsi_voltage_swing_program_seq(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
> +	u32 tmp;
> +	enum port port;
> +
> +	/* Step C.1:clear common keeper enable bit */
> +	for_each_dsi_port(port, intel_dsi->ports) {
> +		tmp = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
> +		tmp &= ~COMMON_KEEPER_EN;
> +		I915_WRITE(ICL_PORT_PCS_DW1_GRP(port), tmp);
> +		tmp = I915_READ(ICL_PORT_PCS_DW1_AUX(port));
> +		tmp &= ~COMMON_KEEPER_EN;
> +		I915_WRITE(ICL_PORT_PCS_DW1_AUX(port), tmp);
> +	}
> +
> +	/*
> +	 * Step C.3: Set SUS Clock Config bitfield to 11b
> +	 * Note: Step C.2 (loadgen select program) is done
> +	 * as part of lane phy sequence configuration
> +	 */
> +	for_each_dsi_port(port, intel_dsi->ports) {
> +		tmp = I915_READ(ICL_PORT_CL_DW5(port));
> +		tmp |= SUS_CLOCK_CONFIG;
> +		I915_WRITE(ICL_PORT_CL_DW5(port), tmp);
> +	}
> +
> +	/* Step C.4: Clear training enable to change swing values */
> +	for_each_dsi_port(port, intel_dsi->ports) {
> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
> +		tmp &= ~TX_TRAINING_EN;
> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
> +		tmp &= ~TX_TRAINING_EN;
> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
> +	}
> +
> +	/* Step C.5: Program swing and de-emphasis */
> +	dsi_program_swing_and_deemphasis(encoder);
> +
> +	/* Step: C.6: Set training enable to trigger update */
> +	for_each_dsi_port(port, intel_dsi->ports) {
> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
> +		tmp |= TX_TRAINING_EN;
> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
> +		tmp |= TX_TRAINING_EN;
> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
> +	}
> +}
> +
>   static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
>   {
>   	/* step 4a: power up all lanes of the DDI used by DSI */
> @@ -147,6 +258,9 @@ static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
>   
>   	/* step 4b: configure lane sequencing of the Combo-PHY transmitters */
>   	gen11_dsi_config_phy_lanes_sequence(encoder);
> +
> +	/* step 4c: configure voltage swing and skew */
> +	gen11_dsi_voltage_swing_program_seq(encoder);
>   }
>   
>   static void __attribute__((unused))
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <p><br>
    </p>
    <br>
    <div class="moz-cite-prefix">On 7/10/2018 3:10 PM, Madhav Chauhan
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:%3C1531215614-6828-3-git-send-email-madhav.chauhan@intel.com%3E">
      <pre wrap="">This patch setup voltage swing before enabling
combo PHY DDI (shared with DSI).
Note that DSI voltage swing programming is for
high speed data buffers. HW automatically handles
the voltage swing for the low power data buffers.

v2: Rebase

Signed-off-by: Madhav Chauhan <a class="moz-txt-link-rfc2396E" href="mailto:madhav.chauhan@intel.com">&lt;madhav.chauhan@intel.com&gt;</a>
---
 drivers/gpu/drm/i915/icl_dsi.c | 114 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 114 insertions(+)

diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c
index a571339..dc16c1f 100644
--- a/drivers/gpu/drm/i915/icl_dsi.c
+++ b/drivers/gpu/drm/i915/icl_dsi.c
@@ -27,6 +27,65 @@
 
 #include "intel_dsi.h"
 
+static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder-&gt;base.dev);
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&amp;encoder-&gt;base);
+	enum port port;
+	u32 tmp;
+	int lane;
+
+	for_each_dsi_port(port, intel_dsi-&gt;ports) {
+
+		/* Bspec: set scaling mode to 0x6 */
+		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
+		tmp |= SCALING_MODE_SEL(6);
+		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
+		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
+		tmp |= SCALING_MODE_SEL(6);
+		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
+		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
+		tmp |= TAP2_DISABLE | TAP3_DISABLE;
+		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
+		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
+		tmp |= TAP2_DISABLE | TAP3_DISABLE;
+		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
+
+		/*
+		 * swing and scaling values are taken from DSI
+		 * table under vswing programming sequence for
+		 * combo phy ddi in BSPEC.
+		 * program swing values
+		 */
+		tmp = I915_READ(ICL_PORT_TX_DW2_LN0(port));
+		tmp |= SWING_SEL_UPPER(0x2);
+		tmp |= SWING_SEL_LOWER(0x2);
+		tmp |= RCOMP_SCALAR(0x98);
+		I915_WRITE(ICL_PORT_TX_DW2_GRP(port), tmp);
+		tmp = I915_READ(ICL_PORT_TX_DW2_AUX(port));
+		tmp |= SWING_SEL_UPPER(0x2);
+		tmp |= SWING_SEL_LOWER(0x2);
+		tmp |= RCOMP_SCALAR(0x98);
+		I915_WRITE(ICL_PORT_TX_DW2_AUX(port), tmp);
+
+		/* program scaling values */
+		tmp = I915_READ(ICL_PORT_TX_DW4_AUX(port));
+		tmp |= POST_CURSOR_1(0x0);
+		tmp |= POST_CURSOR_2(0x0);
+		tmp |= CURSOR_COEFF(0x18);
+		I915_WRITE(ICL_PORT_TX_DW4_AUX(port), tmp);
+
+		for (lane = 0; lane &lt;= 3; lane++) {
+			/* Bspec: must not use GRP register for write */
+			tmp = I915_READ(ICL_PORT_TX_DW4_LN(port, lane));
+			tmp |= POST_CURSOR_1(0x0);
+			tmp |= POST_CURSOR_2(0x0);
+			tmp |= CURSOR_COEFF(0x18);
+			I915_WRITE(ICL_PORT_TX_DW4_LN(port, lane), tmp);
+		}
+	}
+}
+
 static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder-&gt;base.dev);
@@ -140,6 +199,58 @@ static void gen11_dsi_config_phy_lanes_sequence(struct intel_encoder *encoder)
 	}
 }
 </pre>
    </blockquote>
    <!--[if gte mso 9]><xml>
 <o:OfficeDocumentSettings>
  <o:AllowPNG/>
 </o:OfficeDocumentSettings>
</xml><![endif]-->
    <p class="MsoNormal"><span
        style="mso-fareast-font-family:&quot;Times New Roman&quot;">I
        see from the bspec that except for the Loadgen Select and
        Latency Optimization
        all other DDI buffer programming can be taken from the DDI
        Buffer section.</span></p>
    <p class="MsoNormal"
      style="mso-margin-top-alt:auto;mso-margin-bottom-alt:auto">Can
      we use this function "icl_ddi_combo_vswing_program" function which
      is
      already there<br>
      patch for reference:<br>
      <a href="https://patchwork.freedesktop.org/patch/213515/">https://patchwork.freedesktop.org/patch/213515/</a><br>
      <br>
      Thanks,<br>
      Vandita</p>
    <!--[if gte mso 9]><xml>
 <w:WordDocument>
  <w:View>Normal</w:View>
  <w:Zoom>0</w:Zoom>
  <w:TrackMoves/>
  <w:TrackFormatting/>
  <w:PunctuationKerning/>
  <w:ValidateAgainstSchemas/>
  <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
  <w:IgnoreMixedContent>false</w:IgnoreMixedContent>
  <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
  <w:DoNotPromoteQF/>
  <w:LidThemeOther>EN-US</w:LidThemeOther>
  <w:LidThemeAsian>X-NONE</w:LidThemeAsian>
  <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
  <w:Compatibility>
   <w:BreakWrappedTables/>
   <w:SnapToGridInCell/>
   <w:WrapTextWithPunct/>
   <w:UseAsianBreakRules/>
   <w:DontGrowAutofit/>
   <w:SplitPgBreakAndParaMark/>
   <w:EnableOpenTypeKerning/>
   <w:DontFlipMirrorIndents/>
   <w:OverrideTableStyleHps/>
  </w:Compatibility>
  <m:mathPr>
   <m:mathFont m:val="Cambria Math"/>
   <m:brkBin m:val="before"/>
   <m:brkBinSub m:val="&#45;-"/>
   <m:smallFrac m:val="off"/>
   <m:dispDef/>
   <m:lMargin m:val="0"/>
   <m:rMargin m:val="0"/>
   <m:defJc m:val="centerGroup"/>
   <m:wrapIndent m:val="1440"/>
   <m:intLim m:val="subSup"/>
   <m:naryLim m:val="undOvr"/>
  </m:mathPr></w:WordDocument>
</xml><![endif]--><!--[if gte mso 9]><xml>
 <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="false"
  DefSemiHidden="false" DefQFormat="false" DefPriority="99"
  LatentStyleCount="375">
  <w:LsdException Locked="false" Priority="0" QFormat="true" Name="Normal"/>
  <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 1"/>
  <w:LsdException Locked="false" Priority="9" SemiHidden="true"
   UnhideWhenUsed="true" QFormat="true" Name="heading 2"/>
  <w:LsdException Locked="false" Priority="9" SemiHidden="true"
   UnhideWhenUsed="true" QFormat="true" Name="heading 3"/>
  <w:LsdException Locked="false" Priority="9" SemiHidden="true"
   UnhideWhenUsed="true" QFormat="true" Name="heading 4"/>
  <w:LsdException Locked="false" Priority="9" SemiHidden="true"
   UnhideWhenUsed="true" QFormat="true" Name="heading 5"/>
  <w:LsdException Locked="false" Priority="9" SemiHidden="true"
   UnhideWhenUsed="true" QFormat="true" Name="heading 6"/>
  <w:LsdException Locked="false" Priority="9" SemiHidden="true"
   UnhideWhenUsed="true" QFormat="true" Name="heading 7"/>
  <w:LsdException Locked="false" Priority="9" SemiHidden="true"
   UnhideWhenUsed="true" QFormat="true" Name="heading 8"/>
  <w:LsdException Locked="false" Priority="9" SemiHidden="true"
   UnhideWhenUsed="true" QFormat="true" Name="heading 9"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="index 1"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="index 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="index 3"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="index 4"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="index 5"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="index 6"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="index 7"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="index 8"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="index 9"/>
  <w:LsdException Locked="false" Priority="39" SemiHidden="true"
   UnhideWhenUsed="true" Name="toc 1"/>
  <w:LsdException Locked="false" Priority="39" SemiHidden="true"
   UnhideWhenUsed="true" Name="toc 2"/>
  <w:LsdException Locked="false" Priority="39" SemiHidden="true"
   UnhideWhenUsed="true" Name="toc 3"/>
  <w:LsdException Locked="false" Priority="39" SemiHidden="true"
   UnhideWhenUsed="true" Name="toc 4"/>
  <w:LsdException Locked="false" Priority="39" SemiHidden="true"
   UnhideWhenUsed="true" Name="toc 5"/>
  <w:LsdException Locked="false" Priority="39" SemiHidden="true"
   UnhideWhenUsed="true" Name="toc 6"/>
  <w:LsdException Locked="false" Priority="39" SemiHidden="true"
   UnhideWhenUsed="true" Name="toc 7"/>
  <w:LsdException Locked="false" Priority="39" SemiHidden="true"
   UnhideWhenUsed="true" Name="toc 8"/>
  <w:LsdException Locked="false" Priority="39" SemiHidden="true"
   UnhideWhenUsed="true" Name="toc 9"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Normal Indent"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="footnote text"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="annotation text"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="header"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="footer"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="index heading"/>
  <w:LsdException Locked="false" Priority="35" SemiHidden="true"
   UnhideWhenUsed="true" QFormat="true" Name="caption"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="table of figures"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="envelope address"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="envelope return"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="footnote reference"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="annotation reference"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="line number"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="page number"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="endnote reference"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="endnote text"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="table of authorities"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="macro"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="toa heading"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List Bullet"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List Number"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List 3"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List 4"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List 5"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List Bullet 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List Bullet 3"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List Bullet 4"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List Bullet 5"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List Number 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List Number 3"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List Number 4"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List Number 5"/>
  <w:LsdException Locked="false" Priority="10" QFormat="true" Name="Title"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Closing"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Signature"/>
  <w:LsdException Locked="false" Priority="1" SemiHidden="true"
   UnhideWhenUsed="true" Name="Default Paragraph Font"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Body Text"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Body Text Indent"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List Continue"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List Continue 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List Continue 3"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List Continue 4"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="List Continue 5"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Message Header"/>
  <w:LsdException Locked="false" Priority="11" QFormat="true" Name="Subtitle"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Salutation"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Date"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Body Text First Indent"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Body Text First Indent 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Note Heading"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Body Text 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Body Text 3"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Body Text Indent 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Body Text Indent 3"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Block Text"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Hyperlink"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="FollowedHyperlink"/>
  <w:LsdException Locked="false" Priority="22" QFormat="true" Name="Strong"/>
  <w:LsdException Locked="false" Priority="20" QFormat="true" Name="Emphasis"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Document Map"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Plain Text"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="E-mail Signature"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="HTML Top of Form"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="HTML Bottom of Form"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Normal (Web)"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="HTML Acronym"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="HTML Address"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="HTML Cite"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="HTML Code"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="HTML Definition"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="HTML Keyboard"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="HTML Preformatted"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="HTML Sample"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="HTML Typewriter"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="HTML Variable"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Normal Table"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="annotation subject"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="No List"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Outline List 1"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Outline List 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Outline List 3"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Simple 1"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Simple 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Simple 3"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Classic 1"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Classic 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Classic 3"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Classic 4"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Colorful 1"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Colorful 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Colorful 3"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Columns 1"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Columns 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Columns 3"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Columns 4"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Columns 5"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Grid 1"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Grid 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Grid 3"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Grid 4"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Grid 5"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Grid 6"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Grid 7"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Grid 8"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table List 1"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table List 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table List 3"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table List 4"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table List 5"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table List 6"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table List 7"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table List 8"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table 3D effects 1"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table 3D effects 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table 3D effects 3"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Contemporary"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Elegant"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Professional"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Subtle 1"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Subtle 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Web 1"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Web 2"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Web 3"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Balloon Text"/>
  <w:LsdException Locked="false" Priority="39" Name="Table Grid"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Table Theme"/>
  <w:LsdException Locked="false" SemiHidden="true" Name="Placeholder Text"/>
  <w:LsdException Locked="false" Priority="1" QFormat="true" Name="No Spacing"/>
  <w:LsdException Locked="false" Priority="60" Name="Light Shading"/>
  <w:LsdException Locked="false" Priority="61" Name="Light List"/>
  <w:LsdException Locked="false" Priority="62" Name="Light Grid"/>
  <w:LsdException Locked="false" Priority="63" Name="Medium Shading 1"/>
  <w:LsdException Locked="false" Priority="64" Name="Medium Shading 2"/>
  <w:LsdException Locked="false" Priority="65" Name="Medium List 1"/>
  <w:LsdException Locked="false" Priority="66" Name="Medium List 2"/>
  <w:LsdException Locked="false" Priority="67" Name="Medium Grid 1"/>
  <w:LsdException Locked="false" Priority="68" Name="Medium Grid 2"/>
  <w:LsdException Locked="false" Priority="69" Name="Medium Grid 3"/>
  <w:LsdException Locked="false" Priority="70" Name="Dark List"/>
  <w:LsdException Locked="false" Priority="71" Name="Colorful Shading"/>
  <w:LsdException Locked="false" Priority="72" Name="Colorful List"/>
  <w:LsdException Locked="false" Priority="73" Name="Colorful Grid"/>
  <w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 1"/>
  <w:LsdException Locked="false" Priority="61" Name="Light List Accent 1"/>
  <w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 1"/>
  <w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 1"/>
  <w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 1"/>
  <w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 1"/>
  <w:LsdException Locked="false" SemiHidden="true" Name="Revision"/>
  <w:LsdException Locked="false" Priority="34" QFormat="true"
   Name="List Paragraph"/>
  <w:LsdException Locked="false" Priority="29" QFormat="true" Name="Quote"/>
  <w:LsdException Locked="false" Priority="30" QFormat="true"
   Name="Intense Quote"/>
  <w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 1"/>
  <w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 1"/>
  <w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 1"/>
  <w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 1"/>
  <w:LsdException Locked="false" Priority="70" Name="Dark List Accent 1"/>
  <w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 1"/>
  <w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 1"/>
  <w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 1"/>
  <w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 2"/>
  <w:LsdException Locked="false" Priority="61" Name="Light List Accent 2"/>
  <w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 2"/>
  <w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 2"/>
  <w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 2"/>
  <w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 2"/>
  <w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 2"/>
  <w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 2"/>
  <w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 2"/>
  <w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 2"/>
  <w:LsdException Locked="false" Priority="70" Name="Dark List Accent 2"/>
  <w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 2"/>
  <w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 2"/>
  <w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 2"/>
  <w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 3"/>
  <w:LsdException Locked="false" Priority="61" Name="Light List Accent 3"/>
  <w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 3"/>
  <w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 3"/>
  <w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 3"/>
  <w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 3"/>
  <w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 3"/>
  <w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 3"/>
  <w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 3"/>
  <w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 3"/>
  <w:LsdException Locked="false" Priority="70" Name="Dark List Accent 3"/>
  <w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 3"/>
  <w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 3"/>
  <w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 3"/>
  <w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 4"/>
  <w:LsdException Locked="false" Priority="61" Name="Light List Accent 4"/>
  <w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 4"/>
  <w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 4"/>
  <w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 4"/>
  <w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 4"/>
  <w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 4"/>
  <w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 4"/>
  <w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 4"/>
  <w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 4"/>
  <w:LsdException Locked="false" Priority="70" Name="Dark List Accent 4"/>
  <w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 4"/>
  <w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 4"/>
  <w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 4"/>
  <w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 5"/>
  <w:LsdException Locked="false" Priority="61" Name="Light List Accent 5"/>
  <w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 5"/>
  <w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 5"/>
  <w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 5"/>
  <w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 5"/>
  <w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 5"/>
  <w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 5"/>
  <w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 5"/>
  <w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 5"/>
  <w:LsdException Locked="false" Priority="70" Name="Dark List Accent 5"/>
  <w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 5"/>
  <w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 5"/>
  <w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 5"/>
  <w:LsdException Locked="false" Priority="60" Name="Light Shading Accent 6"/>
  <w:LsdException Locked="false" Priority="61" Name="Light List Accent 6"/>
  <w:LsdException Locked="false" Priority="62" Name="Light Grid Accent 6"/>
  <w:LsdException Locked="false" Priority="63" Name="Medium Shading 1 Accent 6"/>
  <w:LsdException Locked="false" Priority="64" Name="Medium Shading 2 Accent 6"/>
  <w:LsdException Locked="false" Priority="65" Name="Medium List 1 Accent 6"/>
  <w:LsdException Locked="false" Priority="66" Name="Medium List 2 Accent 6"/>
  <w:LsdException Locked="false" Priority="67" Name="Medium Grid 1 Accent 6"/>
  <w:LsdException Locked="false" Priority="68" Name="Medium Grid 2 Accent 6"/>
  <w:LsdException Locked="false" Priority="69" Name="Medium Grid 3 Accent 6"/>
  <w:LsdException Locked="false" Priority="70" Name="Dark List Accent 6"/>
  <w:LsdException Locked="false" Priority="71" Name="Colorful Shading Accent 6"/>
  <w:LsdException Locked="false" Priority="72" Name="Colorful List Accent 6"/>
  <w:LsdException Locked="false" Priority="73" Name="Colorful Grid Accent 6"/>
  <w:LsdException Locked="false" Priority="19" QFormat="true"
   Name="Subtle Emphasis"/>
  <w:LsdException Locked="false" Priority="21" QFormat="true"
   Name="Intense Emphasis"/>
  <w:LsdException Locked="false" Priority="31" QFormat="true"
   Name="Subtle Reference"/>
  <w:LsdException Locked="false" Priority="32" QFormat="true"
   Name="Intense Reference"/>
  <w:LsdException Locked="false" Priority="33" QFormat="true" Name="Book Title"/>
  <w:LsdException Locked="false" Priority="37" SemiHidden="true"
   UnhideWhenUsed="true" Name="Bibliography"/>
  <w:LsdException Locked="false" Priority="39" SemiHidden="true"
   UnhideWhenUsed="true" QFormat="true" Name="TOC Heading"/>
  <w:LsdException Locked="false" Priority="41" Name="Plain Table 1"/>
  <w:LsdException Locked="false" Priority="42" Name="Plain Table 2"/>
  <w:LsdException Locked="false" Priority="43" Name="Plain Table 3"/>
  <w:LsdException Locked="false" Priority="44" Name="Plain Table 4"/>
  <w:LsdException Locked="false" Priority="45" Name="Plain Table 5"/>
  <w:LsdException Locked="false" Priority="40" Name="Grid Table Light"/>
  <w:LsdException Locked="false" Priority="46" Name="Grid Table 1 Light"/>
  <w:LsdException Locked="false" Priority="47" Name="Grid Table 2"/>
  <w:LsdException Locked="false" Priority="48" Name="Grid Table 3"/>
  <w:LsdException Locked="false" Priority="49" Name="Grid Table 4"/>
  <w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark"/>
  <w:LsdException Locked="false" Priority="51" Name="Grid Table 6 Colorful"/>
  <w:LsdException Locked="false" Priority="52" Name="Grid Table 7 Colorful"/>
  <w:LsdException Locked="false" Priority="46"
   Name="Grid Table 1 Light Accent 1"/>
  <w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 1"/>
  <w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 1"/>
  <w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 1"/>
  <w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 1"/>
  <w:LsdException Locked="false" Priority="51"
   Name="Grid Table 6 Colorful Accent 1"/>
  <w:LsdException Locked="false" Priority="52"
   Name="Grid Table 7 Colorful Accent 1"/>
  <w:LsdException Locked="false" Priority="46"
   Name="Grid Table 1 Light Accent 2"/>
  <w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 2"/>
  <w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 2"/>
  <w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 2"/>
  <w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 2"/>
  <w:LsdException Locked="false" Priority="51"
   Name="Grid Table 6 Colorful Accent 2"/>
  <w:LsdException Locked="false" Priority="52"
   Name="Grid Table 7 Colorful Accent 2"/>
  <w:LsdException Locked="false" Priority="46"
   Name="Grid Table 1 Light Accent 3"/>
  <w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 3"/>
  <w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 3"/>
  <w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 3"/>
  <w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 3"/>
  <w:LsdException Locked="false" Priority="51"
   Name="Grid Table 6 Colorful Accent 3"/>
  <w:LsdException Locked="false" Priority="52"
   Name="Grid Table 7 Colorful Accent 3"/>
  <w:LsdException Locked="false" Priority="46"
   Name="Grid Table 1 Light Accent 4"/>
  <w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 4"/>
  <w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 4"/>
  <w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 4"/>
  <w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 4"/>
  <w:LsdException Locked="false" Priority="51"
   Name="Grid Table 6 Colorful Accent 4"/>
  <w:LsdException Locked="false" Priority="52"
   Name="Grid Table 7 Colorful Accent 4"/>
  <w:LsdException Locked="false" Priority="46"
   Name="Grid Table 1 Light Accent 5"/>
  <w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 5"/>
  <w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 5"/>
  <w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 5"/>
  <w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 5"/>
  <w:LsdException Locked="false" Priority="51"
   Name="Grid Table 6 Colorful Accent 5"/>
  <w:LsdException Locked="false" Priority="52"
   Name="Grid Table 7 Colorful Accent 5"/>
  <w:LsdException Locked="false" Priority="46"
   Name="Grid Table 1 Light Accent 6"/>
  <w:LsdException Locked="false" Priority="47" Name="Grid Table 2 Accent 6"/>
  <w:LsdException Locked="false" Priority="48" Name="Grid Table 3 Accent 6"/>
  <w:LsdException Locked="false" Priority="49" Name="Grid Table 4 Accent 6"/>
  <w:LsdException Locked="false" Priority="50" Name="Grid Table 5 Dark Accent 6"/>
  <w:LsdException Locked="false" Priority="51"
   Name="Grid Table 6 Colorful Accent 6"/>
  <w:LsdException Locked="false" Priority="52"
   Name="Grid Table 7 Colorful Accent 6"/>
  <w:LsdException Locked="false" Priority="46" Name="List Table 1 Light"/>
  <w:LsdException Locked="false" Priority="47" Name="List Table 2"/>
  <w:LsdException Locked="false" Priority="48" Name="List Table 3"/>
  <w:LsdException Locked="false" Priority="49" Name="List Table 4"/>
  <w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark"/>
  <w:LsdException Locked="false" Priority="51" Name="List Table 6 Colorful"/>
  <w:LsdException Locked="false" Priority="52" Name="List Table 7 Colorful"/>
  <w:LsdException Locked="false" Priority="46"
   Name="List Table 1 Light Accent 1"/>
  <w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 1"/>
  <w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 1"/>
  <w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 1"/>
  <w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 1"/>
  <w:LsdException Locked="false" Priority="51"
   Name="List Table 6 Colorful Accent 1"/>
  <w:LsdException Locked="false" Priority="52"
   Name="List Table 7 Colorful Accent 1"/>
  <w:LsdException Locked="false" Priority="46"
   Name="List Table 1 Light Accent 2"/>
  <w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 2"/>
  <w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 2"/>
  <w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 2"/>
  <w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 2"/>
  <w:LsdException Locked="false" Priority="51"
   Name="List Table 6 Colorful Accent 2"/>
  <w:LsdException Locked="false" Priority="52"
   Name="List Table 7 Colorful Accent 2"/>
  <w:LsdException Locked="false" Priority="46"
   Name="List Table 1 Light Accent 3"/>
  <w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 3"/>
  <w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 3"/>
  <w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 3"/>
  <w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 3"/>
  <w:LsdException Locked="false" Priority="51"
   Name="List Table 6 Colorful Accent 3"/>
  <w:LsdException Locked="false" Priority="52"
   Name="List Table 7 Colorful Accent 3"/>
  <w:LsdException Locked="false" Priority="46"
   Name="List Table 1 Light Accent 4"/>
  <w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 4"/>
  <w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 4"/>
  <w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 4"/>
  <w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 4"/>
  <w:LsdException Locked="false" Priority="51"
   Name="List Table 6 Colorful Accent 4"/>
  <w:LsdException Locked="false" Priority="52"
   Name="List Table 7 Colorful Accent 4"/>
  <w:LsdException Locked="false" Priority="46"
   Name="List Table 1 Light Accent 5"/>
  <w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 5"/>
  <w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 5"/>
  <w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 5"/>
  <w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 5"/>
  <w:LsdException Locked="false" Priority="51"
   Name="List Table 6 Colorful Accent 5"/>
  <w:LsdException Locked="false" Priority="52"
   Name="List Table 7 Colorful Accent 5"/>
  <w:LsdException Locked="false" Priority="46"
   Name="List Table 1 Light Accent 6"/>
  <w:LsdException Locked="false" Priority="47" Name="List Table 2 Accent 6"/>
  <w:LsdException Locked="false" Priority="48" Name="List Table 3 Accent 6"/>
  <w:LsdException Locked="false" Priority="49" Name="List Table 4 Accent 6"/>
  <w:LsdException Locked="false" Priority="50" Name="List Table 5 Dark Accent 6"/>
  <w:LsdException Locked="false" Priority="51"
   Name="List Table 6 Colorful Accent 6"/>
  <w:LsdException Locked="false" Priority="52"
   Name="List Table 7 Colorful Accent 6"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Mention"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Smart Hyperlink"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Hashtag"/>
  <w:LsdException Locked="false" SemiHidden="true" UnhideWhenUsed="true"
   Name="Unresolved Mention"/>
 </w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
 /* Style Definitions */
 table.MsoNormalTable
	{mso-style-name:"Table Normal";
	mso-tstyle-rowband-size:0;
	mso-tstyle-colband-size:0;
	mso-style-noshow:yes;
	mso-style-priority:99;
	mso-style-parent:"";
	mso-padding-alt:0in 5.4pt 0in 5.4pt;
	mso-para-margin:0in;
	mso-para-margin-bottom:.0001pt;
	mso-pagination:widow-orphan;
	font-size:10.0pt;
	font-family:"Times New Roman",serif;}
</style>
<![endif]-->
    <blockquote type="cite"
cite="mid:%3C1531215614-6828-3-git-send-email-madhav.chauhan@intel.com%3E">
      <pre wrap="">
+static void gen11_dsi_voltage_swing_program_seq(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder-&gt;base.dev);
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&amp;encoder-&gt;base);
+	u32 tmp;
+	enum port port;
+
+	/* Step C.1:clear common keeper enable bit */
+	for_each_dsi_port(port, intel_dsi-&gt;ports) {
+		tmp = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
+		tmp &amp;= ~COMMON_KEEPER_EN;
+		I915_WRITE(ICL_PORT_PCS_DW1_GRP(port), tmp);
+		tmp = I915_READ(ICL_PORT_PCS_DW1_AUX(port));
+		tmp &amp;= ~COMMON_KEEPER_EN;
+		I915_WRITE(ICL_PORT_PCS_DW1_AUX(port), tmp);
+	}
+
+	/*
+	 * Step C.3: Set SUS Clock Config bitfield to 11b
+	 * Note: Step C.2 (loadgen select program) is done
+	 * as part of lane phy sequence configuration
+	 */
+	for_each_dsi_port(port, intel_dsi-&gt;ports) {
+		tmp = I915_READ(ICL_PORT_CL_DW5(port));
+		tmp |= SUS_CLOCK_CONFIG;
+		I915_WRITE(ICL_PORT_CL_DW5(port), tmp);
+	}
+
+	/* Step C.4: Clear training enable to change swing values */
+	for_each_dsi_port(port, intel_dsi-&gt;ports) {
+		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
+		tmp &amp;= ~TX_TRAINING_EN;
+		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
+		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
+		tmp &amp;= ~TX_TRAINING_EN;
+		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
+	}
+
+	/* Step C.5: Program swing and de-emphasis */
+	dsi_program_swing_and_deemphasis(encoder);
+
+	/* Step: C.6: Set training enable to trigger update */
+	for_each_dsi_port(port, intel_dsi-&gt;ports) {
+		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
+		tmp |= TX_TRAINING_EN;
+		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
+		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
+		tmp |= TX_TRAINING_EN;
+		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
+	}
+}
+
 static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
 {
 	/* step 4a: power up all lanes of the DDI used by DSI */
@@ -147,6 +258,9 @@ static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
 
 	/* step 4b: configure lane sequencing of the Combo-PHY transmitters */
 	gen11_dsi_config_phy_lanes_sequence(encoder);
+
+	/* step 4c: configure voltage swing and skew */
+	gen11_dsi_voltage_swing_program_seq(encoder);
 }
 
 static void __attribute__((unused))
</pre>
    </blockquote>
    <br>
  </body>
</html>
Chauhan, Madhav Sept. 10, 2018, 7:43 a.m. UTC | #2
On 9/6/2018 7:31 PM, Kulkarni, Vandita wrote:
>
>
>
> On 7/10/2018 3:10 PM, Madhav Chauhan wrote:
>> This patch setup voltage swing before enabling
>> combo PHY DDI (shared with DSI).
>> Note that DSI voltage swing programming is for
>> high speed data buffers. HW automatically handles
>> the voltage swing for the low power data buffers.
>>
>> v2: Rebase
>>
>> Signed-off-by: Madhav Chauhan<madhav.chauhan@intel.com>
>> ---
>>   drivers/gpu/drm/i915/icl_dsi.c | 114 +++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 114 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c
>> index a571339..dc16c1f 100644
>> --- a/drivers/gpu/drm/i915/icl_dsi.c
>> +++ b/drivers/gpu/drm/i915/icl_dsi.c
>> @@ -27,6 +27,65 @@
>>   
>>   #include "intel_dsi.h"
>>   
>> +static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>> +	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
>> +	enum port port;
>> +	u32 tmp;
>> +	int lane;
>> +
>> +	for_each_dsi_port(port, intel_dsi->ports) {
>> +
>> +		/* Bspec: set scaling mode to 0x6 */
>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>> +		tmp |= SCALING_MODE_SEL(6);
>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>> +		tmp |= SCALING_MODE_SEL(6);
>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>> +		tmp |= TAP2_DISABLE | TAP3_DISABLE;
>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>> +		tmp |= TAP2_DISABLE | TAP3_DISABLE;
>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>> +
>> +		/*
>> +		 * swing and scaling values are taken from DSI
>> +		 * table under vswing programming sequence for
>> +		 * combo phy ddi in BSPEC.
>> +		 * program swing values
>> +		 */
>> +		tmp = I915_READ(ICL_PORT_TX_DW2_LN0(port));
>> +		tmp |= SWING_SEL_UPPER(0x2);
>> +		tmp |= SWING_SEL_LOWER(0x2);
>> +		tmp |= RCOMP_SCALAR(0x98);
>> +		I915_WRITE(ICL_PORT_TX_DW2_GRP(port), tmp);
>> +		tmp = I915_READ(ICL_PORT_TX_DW2_AUX(port));
>> +		tmp |= SWING_SEL_UPPER(0x2);
>> +		tmp |= SWING_SEL_LOWER(0x2);
>> +		tmp |= RCOMP_SCALAR(0x98);
>> +		I915_WRITE(ICL_PORT_TX_DW2_AUX(port), tmp);
>> +
>> +		/* program scaling values */
>> +		tmp = I915_READ(ICL_PORT_TX_DW4_AUX(port));
>> +		tmp |= POST_CURSOR_1(0x0);
>> +		tmp |= POST_CURSOR_2(0x0);
>> +		tmp |= CURSOR_COEFF(0x18);
>> +		I915_WRITE(ICL_PORT_TX_DW4_AUX(port), tmp);
>> +
>> +		for (lane = 0; lane <= 3; lane++) {
>> +			/* Bspec: must not use GRP register for write */
>> +			tmp = I915_READ(ICL_PORT_TX_DW4_LN(port, lane));
>> +			tmp |= POST_CURSOR_1(0x0);
>> +			tmp |= POST_CURSOR_2(0x0);
>> +			tmp |= CURSOR_COEFF(0x18);
>> +			I915_WRITE(ICL_PORT_TX_DW4_LN(port, lane), tmp);
>> +		}
>> +	}
>> +}
>> +
>>   static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder)
>>   {
>>   	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>> @@ -140,6 +199,58 @@ static void gen11_dsi_config_phy_lanes_sequence(struct intel_encoder *encoder)
>>   	}
>>   }
>>   
>
> I see from the bspec that except for the Loadgen Select and Latency 
> Optimization all other DDI buffer programming can be taken from the 
> DDI Buffer section.
>
> Can we use this function "icl_ddi_combo_vswing_program" function which 
> is already there
> patch for reference:
> https://patchwork.freedesktop.org/patch/213515/
>

We can't directly use that implementation. Reasons:
1. For DSI we use AUX register as well to write which is not the case 
for DDI. We need to add multiple INTEL_OUTPUT_DSI
checks .
2. DSI specific icl_combo_phy_ddi_buf_trans not added in intel_ddi.c 
which will be used while doing vswing programming
3. intel_ddi_dp_level doesn't support "level" calculation for DSI.

Also in past we had similar discussion (with Jani N) to keep DSI 
specific entries/code in DSI encoder.

Jani N whats the suggestion here??

Regards,
Madhav

>
> Thanks,
> Vandita
>
>> +static void gen11_dsi_voltage_swing_program_seq(struct intel_encoder *encoder)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>> +	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
>> +	u32 tmp;
>> +	enum port port;
>> +
>> +	/* Step C.1:clear common keeper enable bit */
>> +	for_each_dsi_port(port, intel_dsi->ports) {
>> +		tmp = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
>> +		tmp &= ~COMMON_KEEPER_EN;
>> +		I915_WRITE(ICL_PORT_PCS_DW1_GRP(port), tmp);
>> +		tmp = I915_READ(ICL_PORT_PCS_DW1_AUX(port));
>> +		tmp &= ~COMMON_KEEPER_EN;
>> +		I915_WRITE(ICL_PORT_PCS_DW1_AUX(port), tmp);
>> +	}
>> +
>> +	/*
>> +	 * Step C.3: Set SUS Clock Config bitfield to 11b
>> +	 * Note: Step C.2 (loadgen select program) is done
>> +	 * as part of lane phy sequence configuration
>> +	 */
>> +	for_each_dsi_port(port, intel_dsi->ports) {
>> +		tmp = I915_READ(ICL_PORT_CL_DW5(port));
>> +		tmp |= SUS_CLOCK_CONFIG;
>> +		I915_WRITE(ICL_PORT_CL_DW5(port), tmp);
>> +	}
>> +
>> +	/* Step C.4: Clear training enable to change swing values */
>> +	for_each_dsi_port(port, intel_dsi->ports) {
>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>> +		tmp &= ~TX_TRAINING_EN;
>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>> +		tmp &= ~TX_TRAINING_EN;
>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>> +	}
>> +
>> +	/* Step C.5: Program swing and de-emphasis */
>> +	dsi_program_swing_and_deemphasis(encoder);
>> +
>> +	/* Step: C.6: Set training enable to trigger update */
>> +	for_each_dsi_port(port, intel_dsi->ports) {
>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>> +		tmp |= TX_TRAINING_EN;
>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>> +		tmp |= TX_TRAINING_EN;
>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>> +	}
>> +}
>> +
>>   static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
>>   {
>>   	/* step 4a: power up all lanes of the DDI used by DSI */
>> @@ -147,6 +258,9 @@ static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
>>   
>>   	/* step 4b: configure lane sequencing of the Combo-PHY transmitters */
>>   	gen11_dsi_config_phy_lanes_sequence(encoder);
>> +
>> +	/* step 4c: configure voltage swing and skew */
>> +	gen11_dsi_voltage_swing_program_seq(encoder);
>>   }
>>   
>>   static void __attribute__((unused))
>
Jani Nikula Sept. 11, 2018, 6:16 p.m. UTC | #3
On Mon, 10 Sep 2018, Madhav Chauhan <madhav.chauhan@intel.com> wrote:
> On 9/6/2018 7:31 PM, Kulkarni, Vandita wrote:
>>
>>
>>
>> On 7/10/2018 3:10 PM, Madhav Chauhan wrote:
>>> This patch setup voltage swing before enabling
>>> combo PHY DDI (shared with DSI).
>>> Note that DSI voltage swing programming is for
>>> high speed data buffers. HW automatically handles
>>> the voltage swing for the low power data buffers.
>>>
>>> v2: Rebase
>>>
>>> Signed-off-by: Madhav Chauhan<madhav.chauhan@intel.com>
>>> ---
>>>   drivers/gpu/drm/i915/icl_dsi.c | 114 +++++++++++++++++++++++++++++++++++++++++
>>>   1 file changed, 114 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c
>>> index a571339..dc16c1f 100644
>>> --- a/drivers/gpu/drm/i915/icl_dsi.c
>>> +++ b/drivers/gpu/drm/i915/icl_dsi.c
>>> @@ -27,6 +27,65 @@
>>>   
>>>   #include "intel_dsi.h"
>>>   
>>> +static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder)
>>> +{
>>> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>>> +	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
>>> +	enum port port;
>>> +	u32 tmp;
>>> +	int lane;
>>> +
>>> +	for_each_dsi_port(port, intel_dsi->ports) {
>>> +
>>> +		/* Bspec: set scaling mode to 0x6 */
>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>>> +		tmp |= SCALING_MODE_SEL(6);
>>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>>> +		tmp |= SCALING_MODE_SEL(6);
>>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>>> +		tmp |= TAP2_DISABLE | TAP3_DISABLE;
>>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>>> +		tmp |= TAP2_DISABLE | TAP3_DISABLE;
>>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>>> +
>>> +		/*
>>> +		 * swing and scaling values are taken from DSI
>>> +		 * table under vswing programming sequence for
>>> +		 * combo phy ddi in BSPEC.
>>> +		 * program swing values
>>> +		 */
>>> +		tmp = I915_READ(ICL_PORT_TX_DW2_LN0(port));
>>> +		tmp |= SWING_SEL_UPPER(0x2);
>>> +		tmp |= SWING_SEL_LOWER(0x2);
>>> +		tmp |= RCOMP_SCALAR(0x98);
>>> +		I915_WRITE(ICL_PORT_TX_DW2_GRP(port), tmp);
>>> +		tmp = I915_READ(ICL_PORT_TX_DW2_AUX(port));
>>> +		tmp |= SWING_SEL_UPPER(0x2);
>>> +		tmp |= SWING_SEL_LOWER(0x2);
>>> +		tmp |= RCOMP_SCALAR(0x98);
>>> +		I915_WRITE(ICL_PORT_TX_DW2_AUX(port), tmp);
>>> +
>>> +		/* program scaling values */
>>> +		tmp = I915_READ(ICL_PORT_TX_DW4_AUX(port));
>>> +		tmp |= POST_CURSOR_1(0x0);
>>> +		tmp |= POST_CURSOR_2(0x0);
>>> +		tmp |= CURSOR_COEFF(0x18);
>>> +		I915_WRITE(ICL_PORT_TX_DW4_AUX(port), tmp);
>>> +
>>> +		for (lane = 0; lane <= 3; lane++) {
>>> +			/* Bspec: must not use GRP register for write */
>>> +			tmp = I915_READ(ICL_PORT_TX_DW4_LN(port, lane));
>>> +			tmp |= POST_CURSOR_1(0x0);
>>> +			tmp |= POST_CURSOR_2(0x0);
>>> +			tmp |= CURSOR_COEFF(0x18);
>>> +			I915_WRITE(ICL_PORT_TX_DW4_LN(port, lane), tmp);
>>> +		}
>>> +	}
>>> +}
>>> +
>>>   static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder)
>>>   {
>>>   	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>>> @@ -140,6 +199,58 @@ static void gen11_dsi_config_phy_lanes_sequence(struct intel_encoder *encoder)
>>>   	}
>>>   }
>>>   
>>
>> I see from the bspec that except for the Loadgen Select and Latency 
>> Optimization all other DDI buffer programming can be taken from the 
>> DDI Buffer section.
>>
>> Can we use this function "icl_ddi_combo_vswing_program" function which 
>> is already there
>> patch for reference:
>> https://patchwork.freedesktop.org/patch/213515/

For code already merged upstream, please use commit id or file
references.

>
> We can't directly use that implementation. Reasons:
> 1. For DSI we use AUX register as well to write which is not the case 
> for DDI. We need to add multiple INTEL_OUTPUT_DSI
> checks .
> 2. DSI specific icl_combo_phy_ddi_buf_trans not added in intel_ddi.c 
> which will be used while doing vswing programming
> 3. intel_ddi_dp_level doesn't support "level" calculation for DSI.
>
> Also in past we had similar discussion (with Jani N) to keep DSI 
> specific entries/code in DSI encoder.
>
> Jani N whats the suggestion here??

Let's go with the slightly duplicated code, at least for now to get this
merged. This is tedious stuff to review, and combining that with merging
to DP/HDMI buf programming makes it unnecessarily hard. We can refactor
afterwards as needed.

BR,
Jani.


>
> Regards,
> Madhav
>
>>
>> Thanks,
>> Vandita
>>
>>> +static void gen11_dsi_voltage_swing_program_seq(struct intel_encoder *encoder)
>>> +{
>>> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>>> +	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
>>> +	u32 tmp;
>>> +	enum port port;
>>> +
>>> +	/* Step C.1:clear common keeper enable bit */
>>> +	for_each_dsi_port(port, intel_dsi->ports) {
>>> +		tmp = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
>>> +		tmp &= ~COMMON_KEEPER_EN;
>>> +		I915_WRITE(ICL_PORT_PCS_DW1_GRP(port), tmp);
>>> +		tmp = I915_READ(ICL_PORT_PCS_DW1_AUX(port));
>>> +		tmp &= ~COMMON_KEEPER_EN;
>>> +		I915_WRITE(ICL_PORT_PCS_DW1_AUX(port), tmp);
>>> +	}
>>> +
>>> +	/*
>>> +	 * Step C.3: Set SUS Clock Config bitfield to 11b
>>> +	 * Note: Step C.2 (loadgen select program) is done
>>> +	 * as part of lane phy sequence configuration
>>> +	 */
>>> +	for_each_dsi_port(port, intel_dsi->ports) {
>>> +		tmp = I915_READ(ICL_PORT_CL_DW5(port));
>>> +		tmp |= SUS_CLOCK_CONFIG;
>>> +		I915_WRITE(ICL_PORT_CL_DW5(port), tmp);
>>> +	}
>>> +
>>> +	/* Step C.4: Clear training enable to change swing values */
>>> +	for_each_dsi_port(port, intel_dsi->ports) {
>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>>> +		tmp &= ~TX_TRAINING_EN;
>>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>>> +		tmp &= ~TX_TRAINING_EN;
>>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>>> +	}
>>> +
>>> +	/* Step C.5: Program swing and de-emphasis */
>>> +	dsi_program_swing_and_deemphasis(encoder);
>>> +
>>> +	/* Step: C.6: Set training enable to trigger update */
>>> +	for_each_dsi_port(port, intel_dsi->ports) {
>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>>> +		tmp |= TX_TRAINING_EN;
>>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>>> +		tmp |= TX_TRAINING_EN;
>>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>>> +	}
>>> +}
>>> +
>>>   static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
>>>   {
>>>   	/* step 4a: power up all lanes of the DDI used by DSI */
>>> @@ -147,6 +258,9 @@ static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
>>>   
>>>   	/* step 4b: configure lane sequencing of the Combo-PHY transmitters */
>>>   	gen11_dsi_config_phy_lanes_sequence(encoder);
>>> +
>>> +	/* step 4c: configure voltage swing and skew */
>>> +	gen11_dsi_voltage_swing_program_seq(encoder);
>>>   }
>>>   
>>>   static void __attribute__((unused))
>>
>
Jani Nikula Sept. 11, 2018, 6:50 p.m. UTC | #4
On Tue, 10 Jul 2018, Madhav Chauhan <madhav.chauhan@intel.com> wrote:
> This patch setup voltage swing before enabling
> combo PHY DDI (shared with DSI).
> Note that DSI voltage swing programming is for
> high speed data buffers. HW automatically handles
> the voltage swing for the low power data buffers.
>
> v2: Rebase
>
> Signed-off-by: Madhav Chauhan <madhav.chauhan@intel.com>
> ---
>  drivers/gpu/drm/i915/icl_dsi.c | 114 +++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 114 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c
> index a571339..dc16c1f 100644
> --- a/drivers/gpu/drm/i915/icl_dsi.c
> +++ b/drivers/gpu/drm/i915/icl_dsi.c
> @@ -27,6 +27,65 @@
>  
>  #include "intel_dsi.h"
>  
> +static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
> +	enum port port;
> +	u32 tmp;
> +	int lane;
> +
> +	for_each_dsi_port(port, intel_dsi->ports) {
> +
> +		/* Bspec: set scaling mode to 0x6 */

Today bspec says 2. Also, please don't duplicate the value in the
comment.

> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
> +		tmp |= SCALING_MODE_SEL(6);
> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);

Like Ville said, adding a blank line between each read-modify-write
group helps readability. Perhaps add /* DW5 */ etc. comments to group
the, eh, groups.

> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
> +		tmp |= SCALING_MODE_SEL(6);
> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
> +		tmp |= TAP2_DISABLE | TAP3_DISABLE;
> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
> +		tmp |= TAP2_DISABLE | TAP3_DISABLE;
> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);

Are you missing RTERM_SELECT?

Why do you do two read-modify-writes (RMW) on both GRP and AUX, instead
of doing all the changes at once?

The RMW doesn't actually clear the fields before changing them, just ORs
more stuff on top of them, and cursor program or coeff polarity might
contain garbage (at least in theory). The same below.

> +
> +		/*
> +		 * swing and scaling values are taken from DSI
> +		 * table under vswing programming sequence for
> +		 * combo phy ddi in BSPEC.
> +		 * program swing values
> +		 */

Please reflow the comment.

> +		tmp = I915_READ(ICL_PORT_TX_DW2_LN0(port));
> +		tmp |= SWING_SEL_UPPER(0x2);
> +		tmp |= SWING_SEL_LOWER(0x2);

This would benefit from

+#define   SWING_SEL_MASK		(SWING_SEL_UPPER_MASK | SWING_SEL_LOWER_MASK)
+#define   SWING_SEL(x)			(SWING_SEL_UPPER(x) | SWING_SEL_LOWER(x))

in i915_reg.h. But I can look the other way and fix it myself later...

> +		tmp |= RCOMP_SCALAR(0x98);
> +		I915_WRITE(ICL_PORT_TX_DW2_GRP(port), tmp);
> +		tmp = I915_READ(ICL_PORT_TX_DW2_AUX(port));
> +		tmp |= SWING_SEL_UPPER(0x2);
> +		tmp |= SWING_SEL_LOWER(0x2);
> +		tmp |= RCOMP_SCALAR(0x98);
> +		I915_WRITE(ICL_PORT_TX_DW2_AUX(port), tmp);
> +
> +		/* program scaling values */
> +		tmp = I915_READ(ICL_PORT_TX_DW4_AUX(port));
> +		tmp |= POST_CURSOR_1(0x0);
> +		tmp |= POST_CURSOR_2(0x0);
> +		tmp |= CURSOR_COEFF(0x18);

0x3f?

Again, you need to zero the fields before ORin the new values into them.

> +		I915_WRITE(ICL_PORT_TX_DW4_AUX(port), tmp);
> +
> +		for (lane = 0; lane <= 3; lane++) {
> +			/* Bspec: must not use GRP register for write */

I'll take your word for it, although I've missed such a requirement.

> +			tmp = I915_READ(ICL_PORT_TX_DW4_LN(port, lane));
> +			tmp |= POST_CURSOR_1(0x0);
> +			tmp |= POST_CURSOR_2(0x0);
> +			tmp |= CURSOR_COEFF(0x18);

0x3f?

> +			I915_WRITE(ICL_PORT_TX_DW4_LN(port, lane), tmp);
> +		}
> +	}
> +}
> +
>  static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder)
>  {
>  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> @@ -140,6 +199,58 @@ static void gen11_dsi_config_phy_lanes_sequence(struct intel_encoder *encoder)
>  	}
>  }
>  
> +static void gen11_dsi_voltage_swing_program_seq(struct intel_encoder *encoder)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
> +	u32 tmp;
> +	enum port port;
> +

The step numbering below has changed in bspec. Please update. Maybe drop
the numbering, and use just the headings.

Otherwise, the bits here look ok.

BR,
Jani.

> +	/* Step C.1:clear common keeper enable bit */
> +	for_each_dsi_port(port, intel_dsi->ports) {
> +		tmp = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
> +		tmp &= ~COMMON_KEEPER_EN;
> +		I915_WRITE(ICL_PORT_PCS_DW1_GRP(port), tmp);
> +		tmp = I915_READ(ICL_PORT_PCS_DW1_AUX(port));
> +		tmp &= ~COMMON_KEEPER_EN;
> +		I915_WRITE(ICL_PORT_PCS_DW1_AUX(port), tmp);
> +	}
> +
> +	/*
> +	 * Step C.3: Set SUS Clock Config bitfield to 11b
> +	 * Note: Step C.2 (loadgen select program) is done
> +	 * as part of lane phy sequence configuration
> +	 */
> +	for_each_dsi_port(port, intel_dsi->ports) {
> +		tmp = I915_READ(ICL_PORT_CL_DW5(port));
> +		tmp |= SUS_CLOCK_CONFIG;
> +		I915_WRITE(ICL_PORT_CL_DW5(port), tmp);
> +	}
> +
> +	/* Step C.4: Clear training enable to change swing values */
> +	for_each_dsi_port(port, intel_dsi->ports) {
> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
> +		tmp &= ~TX_TRAINING_EN;
> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
> +		tmp &= ~TX_TRAINING_EN;
> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
> +	}
> +
> +	/* Step C.5: Program swing and de-emphasis */
> +	dsi_program_swing_and_deemphasis(encoder);
> +
> +	/* Step: C.6: Set training enable to trigger update */
> +	for_each_dsi_port(port, intel_dsi->ports) {
> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
> +		tmp |= TX_TRAINING_EN;
> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
> +		tmp |= TX_TRAINING_EN;
> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
> +	}
> +}
> +
>  static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
>  {
>  	/* step 4a: power up all lanes of the DDI used by DSI */
> @@ -147,6 +258,9 @@ static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
>  
>  	/* step 4b: configure lane sequencing of the Combo-PHY transmitters */
>  	gen11_dsi_config_phy_lanes_sequence(encoder);
> +
> +	/* step 4c: configure voltage swing and skew */
> +	gen11_dsi_voltage_swing_program_seq(encoder);
>  }
>  
>  static void __attribute__((unused))
Chauhan, Madhav Sept. 12, 2018, 6:34 a.m. UTC | #5
On 9/11/2018 11:46 PM, Jani Nikula wrote:
> On Mon, 10 Sep 2018, Madhav Chauhan <madhav.chauhan@intel.com> wrote:
>> On 9/6/2018 7:31 PM, Kulkarni, Vandita wrote:
>>>
>>>
>>> On 7/10/2018 3:10 PM, Madhav Chauhan wrote:
>>>> This patch setup voltage swing before enabling
>>>> combo PHY DDI (shared with DSI).
>>>> Note that DSI voltage swing programming is for
>>>> high speed data buffers. HW automatically handles
>>>> the voltage swing for the low power data buffers.
>>>>
>>>> v2: Rebase
>>>>
>>>> Signed-off-by: Madhav Chauhan<madhav.chauhan@intel.com>
>>>> ---
>>>>    drivers/gpu/drm/i915/icl_dsi.c | 114 +++++++++++++++++++++++++++++++++++++++++
>>>>    1 file changed, 114 insertions(+)
>>>>
>>>> diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c
>>>> index a571339..dc16c1f 100644
>>>> --- a/drivers/gpu/drm/i915/icl_dsi.c
>>>> +++ b/drivers/gpu/drm/i915/icl_dsi.c
>>>> @@ -27,6 +27,65 @@
>>>>    
>>>>    #include "intel_dsi.h"
>>>>    
>>>> +static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder)
>>>> +{
>>>> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>>>> +	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
>>>> +	enum port port;
>>>> +	u32 tmp;
>>>> +	int lane;
>>>> +
>>>> +	for_each_dsi_port(port, intel_dsi->ports) {
>>>> +
>>>> +		/* Bspec: set scaling mode to 0x6 */
>>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>>>> +		tmp |= SCALING_MODE_SEL(6);
>>>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>>>> +		tmp |= SCALING_MODE_SEL(6);
>>>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>>>> +		tmp |= TAP2_DISABLE | TAP3_DISABLE;
>>>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>>>> +		tmp |= TAP2_DISABLE | TAP3_DISABLE;
>>>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>>>> +
>>>> +		/*
>>>> +		 * swing and scaling values are taken from DSI
>>>> +		 * table under vswing programming sequence for
>>>> +		 * combo phy ddi in BSPEC.
>>>> +		 * program swing values
>>>> +		 */
>>>> +		tmp = I915_READ(ICL_PORT_TX_DW2_LN0(port));
>>>> +		tmp |= SWING_SEL_UPPER(0x2);
>>>> +		tmp |= SWING_SEL_LOWER(0x2);
>>>> +		tmp |= RCOMP_SCALAR(0x98);
>>>> +		I915_WRITE(ICL_PORT_TX_DW2_GRP(port), tmp);
>>>> +		tmp = I915_READ(ICL_PORT_TX_DW2_AUX(port));
>>>> +		tmp |= SWING_SEL_UPPER(0x2);
>>>> +		tmp |= SWING_SEL_LOWER(0x2);
>>>> +		tmp |= RCOMP_SCALAR(0x98);
>>>> +		I915_WRITE(ICL_PORT_TX_DW2_AUX(port), tmp);
>>>> +
>>>> +		/* program scaling values */
>>>> +		tmp = I915_READ(ICL_PORT_TX_DW4_AUX(port));
>>>> +		tmp |= POST_CURSOR_1(0x0);
>>>> +		tmp |= POST_CURSOR_2(0x0);
>>>> +		tmp |= CURSOR_COEFF(0x18);
>>>> +		I915_WRITE(ICL_PORT_TX_DW4_AUX(port), tmp);
>>>> +
>>>> +		for (lane = 0; lane <= 3; lane++) {
>>>> +			/* Bspec: must not use GRP register for write */
>>>> +			tmp = I915_READ(ICL_PORT_TX_DW4_LN(port, lane));
>>>> +			tmp |= POST_CURSOR_1(0x0);
>>>> +			tmp |= POST_CURSOR_2(0x0);
>>>> +			tmp |= CURSOR_COEFF(0x18);
>>>> +			I915_WRITE(ICL_PORT_TX_DW4_LN(port, lane), tmp);
>>>> +		}
>>>> +	}
>>>> +}
>>>> +
>>>>    static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder)
>>>>    {
>>>>    	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>>>> @@ -140,6 +199,58 @@ static void gen11_dsi_config_phy_lanes_sequence(struct intel_encoder *encoder)
>>>>    	}
>>>>    }
>>>>    
>>> I see from the bspec that except for the Loadgen Select and Latency
>>> Optimization all other DDI buffer programming can be taken from the
>>> DDI Buffer section.
>>>
>>> Can we use this function "icl_ddi_combo_vswing_program" function which
>>> is already there
>>> patch for reference:
>>> https://patchwork.freedesktop.org/patch/213515/
> For code already merged upstream, please use commit id or file
> references.
>
>> We can't directly use that implementation. Reasons:
>> 1. For DSI we use AUX register as well to write which is not the case
>> for DDI. We need to add multiple INTEL_OUTPUT_DSI
>> checks .
>> 2. DSI specific icl_combo_phy_ddi_buf_trans not added in intel_ddi.c
>> which will be used while doing vswing programming
>> 3. intel_ddi_dp_level doesn't support "level" calculation for DSI.
>>
>> Also in past we had similar discussion (with Jani N) to keep DSI
>> specific entries/code in DSI encoder.
>>
>> Jani N whats the suggestion here??
> Let's go with the slightly duplicated code, at least for now to get this
> merged. This is tedious stuff to review, and combining that with merging
> to DP/HDMI buf programming makes it unnecessarily hard. We can refactor
> afterwards as needed.
>
> BR,
> Jani.

Thanks for clarification Jani.

Regards,
Madhav

>
>
>> Regards,
>> Madhav
>>
>>> Thanks,
>>> Vandita
>>>
>>>> +static void gen11_dsi_voltage_swing_program_seq(struct intel_encoder *encoder)
>>>> +{
>>>> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>>>> +	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
>>>> +	u32 tmp;
>>>> +	enum port port;
>>>> +
>>>> +	/* Step C.1:clear common keeper enable bit */
>>>> +	for_each_dsi_port(port, intel_dsi->ports) {
>>>> +		tmp = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
>>>> +		tmp &= ~COMMON_KEEPER_EN;
>>>> +		I915_WRITE(ICL_PORT_PCS_DW1_GRP(port), tmp);
>>>> +		tmp = I915_READ(ICL_PORT_PCS_DW1_AUX(port));
>>>> +		tmp &= ~COMMON_KEEPER_EN;
>>>> +		I915_WRITE(ICL_PORT_PCS_DW1_AUX(port), tmp);
>>>> +	}
>>>> +
>>>> +	/*
>>>> +	 * Step C.3: Set SUS Clock Config bitfield to 11b
>>>> +	 * Note: Step C.2 (loadgen select program) is done
>>>> +	 * as part of lane phy sequence configuration
>>>> +	 */
>>>> +	for_each_dsi_port(port, intel_dsi->ports) {
>>>> +		tmp = I915_READ(ICL_PORT_CL_DW5(port));
>>>> +		tmp |= SUS_CLOCK_CONFIG;
>>>> +		I915_WRITE(ICL_PORT_CL_DW5(port), tmp);
>>>> +	}
>>>> +
>>>> +	/* Step C.4: Clear training enable to change swing values */
>>>> +	for_each_dsi_port(port, intel_dsi->ports) {
>>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>>>> +		tmp &= ~TX_TRAINING_EN;
>>>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>>>> +		tmp &= ~TX_TRAINING_EN;
>>>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>>>> +	}
>>>> +
>>>> +	/* Step C.5: Program swing and de-emphasis */
>>>> +	dsi_program_swing_and_deemphasis(encoder);
>>>> +
>>>> +	/* Step: C.6: Set training enable to trigger update */
>>>> +	for_each_dsi_port(port, intel_dsi->ports) {
>>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>>>> +		tmp |= TX_TRAINING_EN;
>>>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>>>> +		tmp |= TX_TRAINING_EN;
>>>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>>>> +	}
>>>> +}
>>>> +
>>>>    static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
>>>>    {
>>>>    	/* step 4a: power up all lanes of the DDI used by DSI */
>>>> @@ -147,6 +258,9 @@ static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
>>>>    
>>>>    	/* step 4b: configure lane sequencing of the Combo-PHY transmitters */
>>>>    	gen11_dsi_config_phy_lanes_sequence(encoder);
>>>> +
>>>> +	/* step 4c: configure voltage swing and skew */
>>>> +	gen11_dsi_voltage_swing_program_seq(encoder);
>>>>    }
>>>>    
>>>>    static void __attribute__((unused))
Chauhan, Madhav Sept. 12, 2018, 9:03 a.m. UTC | #6
On 9/12/2018 12:20 AM, Jani Nikula wrote:
> On Tue, 10 Jul 2018, Madhav Chauhan <madhav.chauhan@intel.com> wrote:
>> This patch setup voltage swing before enabling
>> combo PHY DDI (shared with DSI).
>> Note that DSI voltage swing programming is for
>> high speed data buffers. HW automatically handles
>> the voltage swing for the low power data buffers.
>>
>> v2: Rebase
>>
>> Signed-off-by: Madhav Chauhan <madhav.chauhan@intel.com>
>> ---
>>   drivers/gpu/drm/i915/icl_dsi.c | 114 +++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 114 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c
>> index a571339..dc16c1f 100644
>> --- a/drivers/gpu/drm/i915/icl_dsi.c
>> +++ b/drivers/gpu/drm/i915/icl_dsi.c
>> @@ -27,6 +27,65 @@
>>   
>>   #include "intel_dsi.h"
>>   
>> +static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>> +	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
>> +	enum port port;
>> +	u32 tmp;
>> +	int lane;
>> +
>> +	for_each_dsi_port(port, intel_dsi->ports) {
>> +
>> +		/* Bspec: set scaling mode to 0x6 */
> Today bspec says 2. Also, please don't duplicate the value in the
> comment.

Right..thanks for catching :)

>
>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>> +		tmp |= SCALING_MODE_SEL(6);
>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
> Like Ville said, adding a blank line between each read-modify-write
> group helps readability. Perhaps add /* DW5 */ etc. comments to group
> the, eh, groups.

Ok.

>
>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>> +		tmp |= SCALING_MODE_SEL(6);
>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>> +		tmp |= TAP2_DISABLE | TAP3_DISABLE;
>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>> +		tmp |= TAP2_DISABLE | TAP3_DISABLE;
>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
> Are you missing RTERM_SELECT?

Looks this was not earlier and added recently. Will program in next version.

>
> Why do you do two read-modify-writes (RMW) on both GRP and AUX, instead
> of doing all the changes at once?

Do you mean for  tmp |= TAP2_DISABLE | TAP3_DISABLE ??  If yes, because 
GRP and AUX
might contain different values and need to read them explicitly.

>
> The RMW doesn't actually clear the fields before changing them, just ORs
> more stuff on top of them, and cursor program or coeff polarity might
> contain garbage (at least in theory). The same below.

Yeah, we need to reset those bits using MASK and then do 'OR'.
Or are you suggesting something else??

>
>> +
>> +		/*
>> +		 * swing and scaling values are taken from DSI
>> +		 * table under vswing programming sequence for
>> +		 * combo phy ddi in BSPEC.
>> +		 * program swing values
>> +		 */
> Please reflow the comment.

Ok.

>
>> +		tmp = I915_READ(ICL_PORT_TX_DW2_LN0(port));
>> +		tmp |= SWING_SEL_UPPER(0x2);
>> +		tmp |= SWING_SEL_LOWER(0x2);
> This would benefit from
>
> +#define   SWING_SEL_MASK		(SWING_SEL_UPPER_MASK | SWING_SEL_LOWER_MASK)
> +#define   SWING_SEL(x)			(SWING_SEL_UPPER(x) | SWING_SEL_LOWER(x))
>
> in i915_reg.h. But I can look the other way and fix it myself later...
>
>> +		tmp |= RCOMP_SCALAR(0x98);
>> +		I915_WRITE(ICL_PORT_TX_DW2_GRP(port), tmp);
>> +		tmp = I915_READ(ICL_PORT_TX_DW2_AUX(port));
>> +		tmp |= SWING_SEL_UPPER(0x2);
>> +		tmp |= SWING_SEL_LOWER(0x2);
>> +		tmp |= RCOMP_SCALAR(0x98);
>> +		I915_WRITE(ICL_PORT_TX_DW2_AUX(port), tmp);
>> +
>> +		/* program scaling values */
>> +		tmp = I915_READ(ICL_PORT_TX_DW4_AUX(port));
>> +		tmp |= POST_CURSOR_1(0x0);
>> +		tmp |= POST_CURSOR_2(0x0);
>> +		tmp |= CURSOR_COEFF(0x18);
> 0x3f?

Yes, now its changed to 0x3f.

>
> Again, you need to zero the fields before ORin the new values into them.

Agree.

>
>> +		I915_WRITE(ICL_PORT_TX_DW4_AUX(port), tmp);
>> +
>> +		for (lane = 0; lane <= 3; lane++) {
>> +			/* Bspec: must not use GRP register for write */
> I'll take your word for it, although I've missed such a requirement.

:-)

>
>> +			tmp = I915_READ(ICL_PORT_TX_DW4_LN(port, lane));
>> +			tmp |= POST_CURSOR_1(0x0);
>> +			tmp |= POST_CURSOR_2(0x0);
>> +			tmp |= CURSOR_COEFF(0x18);
> 0x3f?

Yes.

>
>> +			I915_WRITE(ICL_PORT_TX_DW4_LN(port, lane), tmp);
>> +		}
>> +	}
>> +}
>> +
>>   static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder)
>>   {
>>   	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>> @@ -140,6 +199,58 @@ static void gen11_dsi_config_phy_lanes_sequence(struct intel_encoder *encoder)
>>   	}
>>   }
>>   
>> +static void gen11_dsi_voltage_swing_program_seq(struct intel_encoder *encoder)
>> +{
>> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>> +	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
>> +	u32 tmp;
>> +	enum port port;
>> +
> The step numbering below has changed in bspec. Please update. Maybe drop
> the numbering, and use just the headings.

Ok.

Regards,
Madhav

>
> Otherwise, the bits here look ok.
>
> BR,
> Jani.
>
>> +	/* Step C.1:clear common keeper enable bit */
>> +	for_each_dsi_port(port, intel_dsi->ports) {
>> +		tmp = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
>> +		tmp &= ~COMMON_KEEPER_EN;
>> +		I915_WRITE(ICL_PORT_PCS_DW1_GRP(port), tmp);
>> +		tmp = I915_READ(ICL_PORT_PCS_DW1_AUX(port));
>> +		tmp &= ~COMMON_KEEPER_EN;
>> +		I915_WRITE(ICL_PORT_PCS_DW1_AUX(port), tmp);
>> +	}
>> +
>> +	/*
>> +	 * Step C.3: Set SUS Clock Config bitfield to 11b
>> +	 * Note: Step C.2 (loadgen select program) is done
>> +	 * as part of lane phy sequence configuration
>> +	 */
>> +	for_each_dsi_port(port, intel_dsi->ports) {
>> +		tmp = I915_READ(ICL_PORT_CL_DW5(port));
>> +		tmp |= SUS_CLOCK_CONFIG;
>> +		I915_WRITE(ICL_PORT_CL_DW5(port), tmp);
>> +	}
>> +
>> +	/* Step C.4: Clear training enable to change swing values */
>> +	for_each_dsi_port(port, intel_dsi->ports) {
>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>> +		tmp &= ~TX_TRAINING_EN;
>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>> +		tmp &= ~TX_TRAINING_EN;
>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>> +	}
>> +
>> +	/* Step C.5: Program swing and de-emphasis */
>> +	dsi_program_swing_and_deemphasis(encoder);
>> +
>> +	/* Step: C.6: Set training enable to trigger update */
>> +	for_each_dsi_port(port, intel_dsi->ports) {
>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>> +		tmp |= TX_TRAINING_EN;
>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>> +		tmp |= TX_TRAINING_EN;
>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>> +	}
>> +}
>> +
>>   static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
>>   {
>>   	/* step 4a: power up all lanes of the DDI used by DSI */
>> @@ -147,6 +258,9 @@ static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
>>   
>>   	/* step 4b: configure lane sequencing of the Combo-PHY transmitters */
>>   	gen11_dsi_config_phy_lanes_sequence(encoder);
>> +
>> +	/* step 4c: configure voltage swing and skew */
>> +	gen11_dsi_voltage_swing_program_seq(encoder);
>>   }
>>   
>>   static void __attribute__((unused))
Jani Nikula Sept. 12, 2018, 9:10 a.m. UTC | #7
On Wed, 12 Sep 2018, Madhav Chauhan <madhav.chauhan@intel.com> wrote:
> On 9/12/2018 12:20 AM, Jani Nikula wrote:
>> On Tue, 10 Jul 2018, Madhav Chauhan <madhav.chauhan@intel.com> wrote:
>>> This patch setup voltage swing before enabling
>>> combo PHY DDI (shared with DSI).
>>> Note that DSI voltage swing programming is for
>>> high speed data buffers. HW automatically handles
>>> the voltage swing for the low power data buffers.
>>>
>>> v2: Rebase
>>>
>>> Signed-off-by: Madhav Chauhan <madhav.chauhan@intel.com>
>>> ---
>>>   drivers/gpu/drm/i915/icl_dsi.c | 114 +++++++++++++++++++++++++++++++++++++++++
>>>   1 file changed, 114 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c
>>> index a571339..dc16c1f 100644
>>> --- a/drivers/gpu/drm/i915/icl_dsi.c
>>> +++ b/drivers/gpu/drm/i915/icl_dsi.c
>>> @@ -27,6 +27,65 @@
>>>   
>>>   #include "intel_dsi.h"
>>>   
>>> +static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder)
>>> +{
>>> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>>> +	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
>>> +	enum port port;
>>> +	u32 tmp;
>>> +	int lane;
>>> +
>>> +	for_each_dsi_port(port, intel_dsi->ports) {
>>> +
>>> +		/* Bspec: set scaling mode to 0x6 */
>> Today bspec says 2. Also, please don't duplicate the value in the
>> comment.
>
> Right..thanks for catching :)
>
>>
>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>>> +		tmp |= SCALING_MODE_SEL(6);
>>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>> Like Ville said, adding a blank line between each read-modify-write
>> group helps readability. Perhaps add /* DW5 */ etc. comments to group
>> the, eh, groups.
>
> Ok.
>
>>
>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>>> +		tmp |= SCALING_MODE_SEL(6);
>>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>>> +		tmp |= TAP2_DISABLE | TAP3_DISABLE;
>>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>>> +		tmp |= TAP2_DISABLE | TAP3_DISABLE;
>>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>> Are you missing RTERM_SELECT?
>
> Looks this was not earlier and added recently. Will program in next version.
>
>>
>> Why do you do two read-modify-writes (RMW) on both GRP and AUX, instead
>> of doing all the changes at once?
>
> Do you mean for  tmp |= TAP2_DISABLE | TAP3_DISABLE ??  If yes, because 
> GRP and AUX
> might contain different values and need to read them explicitly.

No, I mean first you RMW scaling mode for GRP and AUX, then you do
TAP2/3 disable for GRP and AUX. Why not scaling mode *and* TAP2/3
disable in one go, for GRP and AUX separately of course.

>
>>
>> The RMW doesn't actually clear the fields before changing them, just ORs
>> more stuff on top of them, and cursor program or coeff polarity might
>> contain garbage (at least in theory). The same below.
>
> Yeah, we need to reset those bits using MASK and then do 'OR'.

Yes.

> Or are you suggesting something else??

No, that's just it.

BR,
Jani.

>
>>
>>> +
>>> +		/*
>>> +		 * swing and scaling values are taken from DSI
>>> +		 * table under vswing programming sequence for
>>> +		 * combo phy ddi in BSPEC.
>>> +		 * program swing values
>>> +		 */
>> Please reflow the comment.
>
> Ok.
>
>>
>>> +		tmp = I915_READ(ICL_PORT_TX_DW2_LN0(port));
>>> +		tmp |= SWING_SEL_UPPER(0x2);
>>> +		tmp |= SWING_SEL_LOWER(0x2);
>> This would benefit from
>>
>> +#define   SWING_SEL_MASK		(SWING_SEL_UPPER_MASK | SWING_SEL_LOWER_MASK)
>> +#define   SWING_SEL(x)			(SWING_SEL_UPPER(x) | SWING_SEL_LOWER(x))
>>
>> in i915_reg.h. But I can look the other way and fix it myself later...
>>
>>> +		tmp |= RCOMP_SCALAR(0x98);
>>> +		I915_WRITE(ICL_PORT_TX_DW2_GRP(port), tmp);
>>> +		tmp = I915_READ(ICL_PORT_TX_DW2_AUX(port));
>>> +		tmp |= SWING_SEL_UPPER(0x2);
>>> +		tmp |= SWING_SEL_LOWER(0x2);
>>> +		tmp |= RCOMP_SCALAR(0x98);
>>> +		I915_WRITE(ICL_PORT_TX_DW2_AUX(port), tmp);
>>> +
>>> +		/* program scaling values */
>>> +		tmp = I915_READ(ICL_PORT_TX_DW4_AUX(port));
>>> +		tmp |= POST_CURSOR_1(0x0);
>>> +		tmp |= POST_CURSOR_2(0x0);
>>> +		tmp |= CURSOR_COEFF(0x18);
>> 0x3f?
>
> Yes, now its changed to 0x3f.
>
>>
>> Again, you need to zero the fields before ORin the new values into them.
>
> Agree.
>
>>
>>> +		I915_WRITE(ICL_PORT_TX_DW4_AUX(port), tmp);
>>> +
>>> +		for (lane = 0; lane <= 3; lane++) {
>>> +			/* Bspec: must not use GRP register for write */
>> I'll take your word for it, although I've missed such a requirement.
>
> :-)
>
>>
>>> +			tmp = I915_READ(ICL_PORT_TX_DW4_LN(port, lane));
>>> +			tmp |= POST_CURSOR_1(0x0);
>>> +			tmp |= POST_CURSOR_2(0x0);
>>> +			tmp |= CURSOR_COEFF(0x18);
>> 0x3f?
>
> Yes.
>
>>
>>> +			I915_WRITE(ICL_PORT_TX_DW4_LN(port, lane), tmp);
>>> +		}
>>> +	}
>>> +}
>>> +
>>>   static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder)
>>>   {
>>>   	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>>> @@ -140,6 +199,58 @@ static void gen11_dsi_config_phy_lanes_sequence(struct intel_encoder *encoder)
>>>   	}
>>>   }
>>>   
>>> +static void gen11_dsi_voltage_swing_program_seq(struct intel_encoder *encoder)
>>> +{
>>> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
>>> +	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
>>> +	u32 tmp;
>>> +	enum port port;
>>> +
>> The step numbering below has changed in bspec. Please update. Maybe drop
>> the numbering, and use just the headings.
>
> Ok.
>
> Regards,
> Madhav
>
>>
>> Otherwise, the bits here look ok.
>>
>> BR,
>> Jani.
>>
>>> +	/* Step C.1:clear common keeper enable bit */
>>> +	for_each_dsi_port(port, intel_dsi->ports) {
>>> +		tmp = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
>>> +		tmp &= ~COMMON_KEEPER_EN;
>>> +		I915_WRITE(ICL_PORT_PCS_DW1_GRP(port), tmp);
>>> +		tmp = I915_READ(ICL_PORT_PCS_DW1_AUX(port));
>>> +		tmp &= ~COMMON_KEEPER_EN;
>>> +		I915_WRITE(ICL_PORT_PCS_DW1_AUX(port), tmp);
>>> +	}
>>> +
>>> +	/*
>>> +	 * Step C.3: Set SUS Clock Config bitfield to 11b
>>> +	 * Note: Step C.2 (loadgen select program) is done
>>> +	 * as part of lane phy sequence configuration
>>> +	 */
>>> +	for_each_dsi_port(port, intel_dsi->ports) {
>>> +		tmp = I915_READ(ICL_PORT_CL_DW5(port));
>>> +		tmp |= SUS_CLOCK_CONFIG;
>>> +		I915_WRITE(ICL_PORT_CL_DW5(port), tmp);
>>> +	}
>>> +
>>> +	/* Step C.4: Clear training enable to change swing values */
>>> +	for_each_dsi_port(port, intel_dsi->ports) {
>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>>> +		tmp &= ~TX_TRAINING_EN;
>>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>>> +		tmp &= ~TX_TRAINING_EN;
>>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>>> +	}
>>> +
>>> +	/* Step C.5: Program swing and de-emphasis */
>>> +	dsi_program_swing_and_deemphasis(encoder);
>>> +
>>> +	/* Step: C.6: Set training enable to trigger update */
>>> +	for_each_dsi_port(port, intel_dsi->ports) {
>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
>>> +		tmp |= TX_TRAINING_EN;
>>> +		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
>>> +		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
>>> +		tmp |= TX_TRAINING_EN;
>>> +		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
>>> +	}
>>> +}
>>> +
>>>   static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
>>>   {
>>>   	/* step 4a: power up all lanes of the DDI used by DSI */
>>> @@ -147,6 +258,9 @@ static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
>>>   
>>>   	/* step 4b: configure lane sequencing of the Combo-PHY transmitters */
>>>   	gen11_dsi_config_phy_lanes_sequence(encoder);
>>> +
>>> +	/* step 4c: configure voltage swing and skew */
>>> +	gen11_dsi_voltage_swing_program_seq(encoder);
>>>   }
>>>   
>>>   static void __attribute__((unused))
>
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/icl_dsi.c b/drivers/gpu/drm/i915/icl_dsi.c
index a571339..dc16c1f 100644
--- a/drivers/gpu/drm/i915/icl_dsi.c
+++ b/drivers/gpu/drm/i915/icl_dsi.c
@@ -27,6 +27,65 @@ 
 
 #include "intel_dsi.h"
 
+static void dsi_program_swing_and_deemphasis(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+	enum port port;
+	u32 tmp;
+	int lane;
+
+	for_each_dsi_port(port, intel_dsi->ports) {
+
+		/* Bspec: set scaling mode to 0x6 */
+		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
+		tmp |= SCALING_MODE_SEL(6);
+		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
+		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
+		tmp |= SCALING_MODE_SEL(6);
+		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
+		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
+		tmp |= TAP2_DISABLE | TAP3_DISABLE;
+		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
+		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
+		tmp |= TAP2_DISABLE | TAP3_DISABLE;
+		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
+
+		/*
+		 * swing and scaling values are taken from DSI
+		 * table under vswing programming sequence for
+		 * combo phy ddi in BSPEC.
+		 * program swing values
+		 */
+		tmp = I915_READ(ICL_PORT_TX_DW2_LN0(port));
+		tmp |= SWING_SEL_UPPER(0x2);
+		tmp |= SWING_SEL_LOWER(0x2);
+		tmp |= RCOMP_SCALAR(0x98);
+		I915_WRITE(ICL_PORT_TX_DW2_GRP(port), tmp);
+		tmp = I915_READ(ICL_PORT_TX_DW2_AUX(port));
+		tmp |= SWING_SEL_UPPER(0x2);
+		tmp |= SWING_SEL_LOWER(0x2);
+		tmp |= RCOMP_SCALAR(0x98);
+		I915_WRITE(ICL_PORT_TX_DW2_AUX(port), tmp);
+
+		/* program scaling values */
+		tmp = I915_READ(ICL_PORT_TX_DW4_AUX(port));
+		tmp |= POST_CURSOR_1(0x0);
+		tmp |= POST_CURSOR_2(0x0);
+		tmp |= CURSOR_COEFF(0x18);
+		I915_WRITE(ICL_PORT_TX_DW4_AUX(port), tmp);
+
+		for (lane = 0; lane <= 3; lane++) {
+			/* Bspec: must not use GRP register for write */
+			tmp = I915_READ(ICL_PORT_TX_DW4_LN(port, lane));
+			tmp |= POST_CURSOR_1(0x0);
+			tmp |= POST_CURSOR_2(0x0);
+			tmp |= CURSOR_COEFF(0x18);
+			I915_WRITE(ICL_PORT_TX_DW4_LN(port, lane), tmp);
+		}
+	}
+}
+
 static void gen11_dsi_program_esc_clk_div(struct intel_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
@@ -140,6 +199,58 @@  static void gen11_dsi_config_phy_lanes_sequence(struct intel_encoder *encoder)
 	}
 }
 
+static void gen11_dsi_voltage_swing_program_seq(struct intel_encoder *encoder)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+	u32 tmp;
+	enum port port;
+
+	/* Step C.1:clear common keeper enable bit */
+	for_each_dsi_port(port, intel_dsi->ports) {
+		tmp = I915_READ(ICL_PORT_PCS_DW1_LN0(port));
+		tmp &= ~COMMON_KEEPER_EN;
+		I915_WRITE(ICL_PORT_PCS_DW1_GRP(port), tmp);
+		tmp = I915_READ(ICL_PORT_PCS_DW1_AUX(port));
+		tmp &= ~COMMON_KEEPER_EN;
+		I915_WRITE(ICL_PORT_PCS_DW1_AUX(port), tmp);
+	}
+
+	/*
+	 * Step C.3: Set SUS Clock Config bitfield to 11b
+	 * Note: Step C.2 (loadgen select program) is done
+	 * as part of lane phy sequence configuration
+	 */
+	for_each_dsi_port(port, intel_dsi->ports) {
+		tmp = I915_READ(ICL_PORT_CL_DW5(port));
+		tmp |= SUS_CLOCK_CONFIG;
+		I915_WRITE(ICL_PORT_CL_DW5(port), tmp);
+	}
+
+	/* Step C.4: Clear training enable to change swing values */
+	for_each_dsi_port(port, intel_dsi->ports) {
+		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
+		tmp &= ~TX_TRAINING_EN;
+		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
+		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
+		tmp &= ~TX_TRAINING_EN;
+		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
+	}
+
+	/* Step C.5: Program swing and de-emphasis */
+	dsi_program_swing_and_deemphasis(encoder);
+
+	/* Step: C.6: Set training enable to trigger update */
+	for_each_dsi_port(port, intel_dsi->ports) {
+		tmp = I915_READ(ICL_PORT_TX_DW5_LN0(port));
+		tmp |= TX_TRAINING_EN;
+		I915_WRITE(ICL_PORT_TX_DW5_GRP(port), tmp);
+		tmp = I915_READ(ICL_PORT_TX_DW5_AUX(port));
+		tmp |= TX_TRAINING_EN;
+		I915_WRITE(ICL_PORT_TX_DW5_AUX(port), tmp);
+	}
+}
+
 static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
 {
 	/* step 4a: power up all lanes of the DDI used by DSI */
@@ -147,6 +258,9 @@  static void gen11_dsi_enable_port_and_phy(struct intel_encoder *encoder)
 
 	/* step 4b: configure lane sequencing of the Combo-PHY transmitters */
 	gen11_dsi_config_phy_lanes_sequence(encoder);
+
+	/* step 4c: configure voltage swing and skew */
+	gen11_dsi_voltage_swing_program_seq(encoder);
 }
 
 static void __attribute__((unused))