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

Madhav Chauhan madhav.chauhan at intel.com
Wed Sep 12 06:34:51 UTC 2018


On 9/11/2018 11:46 PM, Jani Nikula wrote:
> On Mon, 10 Sep 2018, Madhav Chauhan <madhav.chauhan at 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 at 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))



More information about the Intel-gfx mailing list