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@xxxxxxxxx>
---
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))
_______________________________________________
Intel-gfx mailing list
Intel-gfx@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/intel-gfx