[PATCH v2 5/9] drm/i915/dsb: Send uevent to testapp.
Send uevent to testapp and set test_active flag. To align with link compliance design existing intel_dp_compliance tool will be used to get the phy request in userspace through uevent. Signed-off-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_dp.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index a871834b90d9..81eeb9bbb050 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5011,6 +5011,9 @@ static u8 intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp) if (test_result != DP_TEST_ACK) DRM_ERROR("Phy test preparation failed\n"); + /* Set test active flag here so userspace doesn't interrupt things */ + intel_dp->compliance.test_active = 1; + return test_result; } @@ -5336,8 +5339,11 @@ intel_dp_short_pulse(struct intel_dp *intel_dp) intel_psr_short_pulse(intel_dp); - if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) { - DRM_DEBUG_KMS("Link Training Compliance Test requested\n"); + if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING || + intel_dp->compliance.test_type == + DP_TEST_LINK_PHY_TEST_PATTERN) { + DRM_DEBUG_KMS("Compliance Test requested, test-type = 0x%lx\n", + intel_dp->compliance.test_type); /* Send a Hotplug Uevent to userspace to start modeset */ drm_kms_helper_hotplug_event(&dev_priv->drm); } -- 2.24.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 7/9] drm/i915/dp: Register definition for DP compliance register
DP_COMP_CTL and DP_COMP_PAT register used to program DP compliance pattern. Reviewed-by: Manasi Navare Signed-off-by: Animesh Manna --- drivers/gpu/drm/i915/i915_reg.h | 20 1 file changed, 20 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index cbb4689af432..fc54143bd4a4 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -9788,6 +9788,26 @@ enum skl_power_gate { #define DDI_BUF_BALANCE_LEG_ENABLE(1 << 31) #define DDI_BUF_TRANS_HI(port, i) _MMIO(_PORT(port, _DDI_BUF_TRANS_A, _DDI_BUF_TRANS_B) + (i) * 8 + 4) +/* DDI DP Compliance Control */ +#define DDI_DP_COMP_CTL_A 0x605F0 +#define DDI_DP_COMP_CTL_B 0x615F0 +#define DDI_DP_COMP_CTL(port) _MMIO_PORT(port, DDI_DP_COMP_CTL_A, \ +DDI_DP_COMP_CTL_B) +#define DDI_DP_COMP_CTL_ENABLE(1 << 31) +#define DDI_DP_COMP_CTL_D10_2 (0 << 28) +#define DDI_DP_COMP_CTL_SCRAMBLED_0 (1 << 28) +#define DDI_DP_COMP_CTL_PRBS7 (2 << 28) +#define DDI_DP_COMP_CTL_CUSTOM80 (3 << 28) +#define DDI_DP_COMP_CTL_HBR2 (4 << 28) +#define DDI_DP_COMP_CTL_SCRAMBLED_1 (5 << 28) +#define DDI_DP_COMP_CTL_HBR2_RESET(0xFC << 0) + +/* DDI DP Compliance Pattern */ +#define DDI_DP_COMP_PAT_A 0x605F4 +#define DDI_DP_COMP_PAT_B 0x615F4 +#define DDI_DP_COMP_PAT(port, i) _MMIO(_PORT(port, DDI_DP_COMP_PAT_A, \ +DDI_DP_COMP_PAT_B) + (i) * 4) + /* Sideband Interface (SBI) is programmed indirectly, via * SBI_ADDR, which contains the register offset; and SBI_DATA, * which contains the payload */ -- 2.24.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 8/9] drm/i915/dp: Update the pattern as per request
As per request from DP phy compliance test few special test pattern need to set by source. Added function to set pattern in DP_COMP_CTL register. It will be called along with other test parameters like vswing, pre-emphasis programming in atomic_commit_tail path. Signed-off-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_dp.c | 55 + 1 file changed, 55 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 81eeb9bbb050..f38929db1f2e 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5003,6 +5003,61 @@ static u8 intel_dp_prepare_phytest(struct intel_dp *intel_dp) return DP_TEST_ACK; } +static inline void intel_dp_phy_pattern_update(struct intel_dp *intel_dp) +{ + struct drm_i915_private *dev_priv = + to_i915(dp_to_dig_port(intel_dp)->base.base.dev); + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct drm_dp_phy_test_params *data = + &intel_dp->compliance.test_data.phytest; + u32 temp; + + switch (data->phy_pattern) { + case DP_PHY_TEST_PATTERN_NONE: + DRM_DEBUG_KMS("Disable Phy Test Pattern\n"); + I915_WRITE(DDI_DP_COMP_CTL(intel_dig_port->base.port), 0x0); + break; + case DP_PHY_TEST_PATTERN_D10_2: + DRM_DEBUG_KMS("Set D10.2 Phy Test Pattern\n"); + I915_WRITE(DDI_DP_COMP_CTL(intel_dig_port->base.port), + DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_D10_2); + break; + case DP_PHY_TEST_PATTERN_ERROR_COUNT: + DRM_DEBUG_KMS("Set Error Count Phy Test Pattern\n"); + I915_WRITE(DDI_DP_COMP_CTL(intel_dig_port->base.port), + DDI_DP_COMP_CTL_ENABLE | + DDI_DP_COMP_CTL_SCRAMBLED_0); + break; + case DP_PHY_TEST_PATTERN_PRBS7: + DRM_DEBUG_KMS("Set PRBS7 Phy Test Pattern\n"); + I915_WRITE(DDI_DP_COMP_CTL(intel_dig_port->base.port), + DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_PRBS7); + break; + case DP_PHY_TEST_PATTERN_80BIT_CUSTOM: + DRM_DEBUG_KMS("Set 80Bit Custom Phy Test Pattern\n"); + temp = ((data->custom80[0] << 24) | (data->custom80[1] << 16) | + (data->custom80[2] << 8) | (data->custom80[3])); + I915_WRITE(DDI_DP_COMP_PAT(intel_dig_port->base.port, 0), temp); + temp = ((data->custom80[4] << 24) | (data->custom80[5] << 16) | + (data->custom80[6] << 8) | (data->custom80[7])); + I915_WRITE(DDI_DP_COMP_PAT(intel_dig_port->base.port, 1), temp); + temp = ((data->custom80[8] << 8) | data->custom80[9]); + I915_WRITE(DDI_DP_COMP_PAT(intel_dig_port->base.port, 2), temp); + I915_WRITE(DDI_DP_COMP_CTL(intel_dig_port->base.port), + DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_CUSTOM80); + break; + case DP_PHY_TEST_PATTERN_CP2520: + DRM_DEBUG_KMS("Set HBR2 compliance Phy Test Pattern\n"); + temp = ((data->hbr2_reset[1] << 8) | data->hbr2_reset[0]); + I915_WRITE(DDI_DP_COMP_CTL(intel_dig_port->base.port), + DDI_DP_COMP_CTL_ENABLE | DDI_DP_COMP_CTL_HBR2 | + temp); + break; + default: + WARN(1, "Invalid Phy Test PAttern\n"); + } +} + static u8 intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp) { u8 test_result = DP_TEST_NAK; -- 2.24.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 9/9] drm/i915/dp: [FIXME] Program vswing, pre-emphasis, test-pattern
This patch process phy compliance request by programming requested vswing, pre-emphasis and test pattern. Note: FIXME tag added as design discusion is ongoing in previous patch series. Some temporary fix added and the patch is under-development, not for review. Signed-off-by: Animesh Manna --- drivers/gpu/drm/i915/display/intel_display.c | 24 ++- drivers/gpu/drm/i915/display/intel_dp.c | 74 drivers/gpu/drm/i915/display/intel_dp.h | 2 + drivers/gpu/drm/i915/i915_drv.h | 2 + 4 files changed, 101 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e18ee1f17d6e..2d58ed249452 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -14084,6 +14084,9 @@ static int intel_atomic_check(struct drm_device *dev, int ret, i; bool any_ms = false; + if (dev_priv->dp_phy_comp) + return 0; + /* Catch I915_MODE_FLAG_INHERITED */ for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { @@ -14692,10 +14695,23 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) struct drm_i915_private *dev_priv = to_i915(dev); struct intel_crtc_state *new_crtc_state, *old_crtc_state; struct intel_crtc *crtc; + const struct drm_connector_state *conn_state; + struct drm_connector *conn; u64 put_domains[I915_MAX_PIPES] = {}; intel_wakeref_t wakeref = 0; int i; + if(dev_priv->dp_phy_comp) { + for_each_new_connector_in_state(&state->base, conn, conn_state, i) { + struct intel_encoder *encoder = + to_intel_encoder(conn_state->best_encoder); + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + + intel_dp_process_phy_request(intel_dp); + } + goto dp_phy_comp1; + } + intel_atomic_commit_fence_wait(state); drm_atomic_helper_wait_for_dependencies(&state->base); @@ -14830,6 +14846,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) if (state->modeset && intel_can_enable_sagv(state)) intel_enable_sagv(dev_priv); +dp_phy_comp1: drm_atomic_helper_commit_hw_done(&state->base); if (state->modeset) { @@ -14921,6 +14938,7 @@ static int intel_atomic_commit(struct drm_device *dev, state->wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); drm_atomic_state_get(&state->base); + if (!dev_priv->dp_phy_comp) { i915_sw_fence_init(&state->commit_ready, intel_atomic_commit_ready); @@ -14959,11 +14977,13 @@ static int intel_atomic_commit(struct drm_device *dev, intel_runtime_pm_put(&dev_priv->runtime_pm, state->wakeref); return ret; } + } ret = drm_atomic_helper_setup_commit(&state->base, nonblock); if (!ret) ret = drm_atomic_helper_swap_state(&state->base, true); + if (!dev_priv->dp_phy_comp) { if (ret) { i915_sw_fence_commit(&state->commit_ready); @@ -14974,6 +14994,7 @@ static int intel_atomic_commit(struct drm_device *dev, dev_priv->wm.distrust_bios_wm = false; intel_shared_dpll_swap_state(state); intel_atomic_track_fbs(state); + } if (state->global_state_changed) { assert_global_state_locked(dev_priv); @@ -14990,8 +15011,9 @@ static int intel_atomic_commit(struct drm_device *dev, drm_atomic_state_get(&state->base); INIT_WORK(&state->base.commit_work, intel_atomic_commit_work); - + if (!dev_priv->dp_phy_comp) { i915_sw_fence_commit(&state->commit_ready); + } if (nonblock && state->modeset) { queue_work(dev_priv->modeset_wq, &state->base.commit_work); } else if (nonblock) { diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index f38929db1f2e..4b4fa9074d18 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5058,9 +5058,82 @@ static inline void intel_dp_phy_pattern_update(struct intel_dp *intel_dp) } } +static void +intel_dp_autotest_phy_ddi_disable(struct intel_dp *intel_dp) +{ + struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = intel_dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + enum port port = intel_dig_port->base.port; + u32 ddi_buf
[PATCH v2 4/9] drm/i915/dp: Preparation for DP phy compliance auto test
During DP phy compliance auto test mode, sink will request combination of different test pattern with differnt level of vswing, pre-emphasis. Function added to prepare for it. Reviewed-by: Manasi Navare Signed-off-by: Animesh Manna --- .../drm/i915/display/intel_display_types.h| 1 + drivers/gpu/drm/i915/display/intel_dp.c | 24 +++ 2 files changed, 25 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 83ea04149b77..c17866f126c9 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1205,6 +1205,7 @@ struct intel_dp_compliance_data { u8 video_pattern; u16 hdisplay, vdisplay; u8 bpc; + struct drm_dp_phy_test_params phytest; }; struct intel_dp_compliance { diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index ca82835b6dcf..a871834b90d9 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4984,9 +4984,33 @@ static u8 intel_dp_autotest_edid(struct intel_dp *intel_dp) return test_result; } +static u8 intel_dp_prepare_phytest(struct intel_dp *intel_dp) +{ + struct drm_dp_phy_test_params *data = + &intel_dp->compliance.test_data.phytest; + + if (drm_dp_get_phy_test_pattern(&intel_dp->aux, data)) { + DRM_DEBUG_KMS("DP Phy Test pattern AUX read failure\n"); + return DP_TEST_NAK; + } + + /* +* link_mst is set to false to avoid executing mst related code +* during compliance testing. +*/ + intel_dp->link_mst = false; + + return DP_TEST_ACK; +} + static u8 intel_dp_autotest_phy_pattern(struct intel_dp *intel_dp) { u8 test_result = DP_TEST_NAK; + + test_result = intel_dp_prepare_phytest(intel_dp); + if (test_result != DP_TEST_ACK) + DRM_ERROR("Phy test preparation failed\n"); + return test_result; } -- 2.24.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 2/9] drm/amd/display: Fix compilation issue.
[Why]: Aligh with DP spec wanted to follow same naming convention. [How]: Changed the macro name of the dpcd address used for getting requested test-pattern. Cc: Harry Wentland Cc: Alex Deucher Signed-off-by: Animesh Manna --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 42aa889fd0f5..1a6109be2fce 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2491,7 +2491,7 @@ static void dp_test_send_phy_test_pattern(struct dc_link *link) /* get phy test pattern and pattern parameters from DP receiver */ core_link_read_dpcd( link, - DP_TEST_PHY_PATTERN, + DP_PHY_TEST_PATTERN, &dpcd_test_pattern.raw, sizeof(dpcd_test_pattern)); core_link_read_dpcd( -- 2.24.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 1/9] drm/dp: get/set phy compliance pattern
During phy compliance auto test mode source need to read requested test pattern from sink through DPCD. After processing the request source need to set the pattern. So set/get method added in drm layer as it is DP protocol. v2: As per review feedback from Manasi on RFC version, - added dp revision as function argument in set_phy_pattern api. - used int for link_rate and u8 for lane_count to align with existing code. Signed-off-by: Animesh Manna --- drivers/gpu/drm/drm_dp_helper.c | 93 + include/drm/drm_dp_helper.h | 33 +++- 2 files changed, 125 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 2c7870aef469..91c80973aa83 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -1371,3 +1371,96 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S return num_bpc; } EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs); + +/** + * drm_dp_get_phy_test_pattern() - get the requested pattern from the sink. + * @aux: DisplayPort AUX channel + * @data: DP phy compliance test parameters. + * + * Returns 0 on success or a negative error code on failure. + */ +int drm_dp_get_phy_test_pattern(struct drm_dp_aux *aux, + struct drm_dp_phy_test_params *data) +{ + int err; + u8 rate, lanes; + + err = drm_dp_dpcd_readb(aux, DP_TEST_LINK_RATE, &rate); + if (err < 0) + return err; + data->link_rate = drm_dp_bw_code_to_link_rate(rate); + + err = drm_dp_dpcd_readb(aux, DP_TEST_LANE_COUNT, &lanes); + if (err < 0) + return err; + data->num_lanes = lanes & DP_MAX_LANE_COUNT_MASK; + + if (lanes & DP_ENHANCED_FRAME_CAP) + data->enahanced_frame_cap = true; + + err = drm_dp_dpcd_readb(aux, DP_PHY_TEST_PATTERN, &data->phy_pattern); + if (err < 0) + return err; + + switch (data->phy_pattern) { + case DP_PHY_TEST_PATTERN_80BIT_CUSTOM: + err = drm_dp_dpcd_read(aux, DP_TEST_80BIT_CUSTOM_PATTERN_7_0, + &data->custom80, 10); + if (err < 0) + return err; + + break; + case DP_PHY_TEST_PATTERN_CP2520: + err = drm_dp_dpcd_read(aux, DP_TEST_HBR2_SCRAMBLER_RESET, + &data->hbr2_reset, 2); + if (err < 0) + return err; + } + + return 0; +} +EXPORT_SYMBOL(drm_dp_get_phy_test_pattern); + +/** + * drm_dp_set_phy_test_pattern() - set the pattern to the sink. + * @aux: DisplayPort AUX channel + * @data: DP phy compliance test parameters. + * + * Returns 0 on success or a negative error code on failure. + */ +int drm_dp_set_phy_test_pattern(struct drm_dp_aux *aux, + struct drm_dp_phy_test_params *data, u8 dp_rev) +{ + int err, i; + u8 link_config[2]; + u8 test_pattern; + + link_config[0] = drm_dp_link_rate_to_bw_code(data->link_rate); + link_config[1] = data->num_lanes; + if (data->enahanced_frame_cap) + link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, link_config, 2); + if (err < 0) + return err; + + test_pattern = data->phy_pattern; + if (dp_rev < 0x12) { + test_pattern = (test_pattern << 2) & + DP_LINK_QUAL_PATTERN_11_MASK; + err = drm_dp_dpcd_writeb(aux, DP_TRAINING_PATTERN_SET, +test_pattern); + if (err < 0) + return err; + } else { + for (i = 0; i < data->num_lanes; i++) { + err = drm_dp_dpcd_writeb(aux, +DP_LINK_QUAL_LANE0_SET + i, +test_pattern); + if (err < 0) + return err; + } + } + + return 0; +} +EXPORT_SYMBOL(drm_dp_set_phy_test_pattern); diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 8f8f3632e697..42a364748308 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -699,7 +699,16 @@ # define DP_TEST_CRC_SUPPORTED (1 << 5) # define DP_TEST_COUNT_MASK0xf -#define DP_TEST_PHY_PATTERN 0x248 +#define DP_PHY_TEST_PATTERN 0x248 +# define DP_PHY_TEST_PATTERN_SEL_MASK 0x7 +# define DP_PHY_TEST_PATTERN_NONE 0x0 +# define DP_PHY_TEST_PATTERN_D10_2 0x1 +# define DP_PHY_TEST_PATTERN_ERROR_COUNT0x2 +# define DP_PHY_TEST_PATTERN_PRBS7 0x
[PATCH v2 0/9] DP Phy compliance auto test
Driver changes mainly to process the request coming from Test equipment as short pulse hpd interrupt to change link-pattern/v-swing/pre-emphasis Complete auto test suite takes much lesser time than manual run. Overall design: -- Automate test request will come to source device as HDP short pulse interrupt from test scope. Read DPCD 0x201, Check for bit 1 for automated test request. If set continue and read DPCD 0x218. Check for bit 3 for phy test pattern, If set continue. Get the requested test pattern through DPCD 0x248. Compute requested voltage swing level and pre-emphasis level from DPCD 0x206 and 0x207 Set signal level through vswing programming sequence. Write DDI_COMP_CTL and DDI_COMP_PATx as per requested pattern. Configure the link and write the new test pattern through DPCD. High level patch description. - patch 1: drm level api added to get/set test pattern as per vesa DP spec. This maybe useful for other driver so added in drm layer. patch 2: Fix for a compilation issue. patch 3: vswing/preemphasis adjustment calculation is needed during phy compliance request processing along with existing link training process, so moved the same function in intel_dp.c. patch 4: Parse the test scope request regarding rquested test pattern, vswing level, preemphasis level. patch 5: Notify testapp through uevent. patch 6: Added debugfs entry for phy compliance. patch 7: Register difnition of DP compliance register added. patch 8: Function added to update the pattern in source side. patch 9: This patch os mainly processing the request. Currently through prototyping patch able to run DP compliance where vswing, preemphasis and test pattern is changing fine but complete test is under process. As per feedback redesigned the code. Could not test due to unavailability of test scope, so sending as RFC again to get design feedback. v1: Redesigned the code as per review feedback from Manasi on RFC. v2: Addressed review comments from Manasi. Animesh Manna (9): drm/dp: get/set phy compliance pattern drm/amd/display: Fix compilation issue. drm/i915/dp: Move vswing/pre-emphasis adjustment calculation drm/i915/dp: Preparation for DP phy compliance auto test drm/i915/dsb: Send uevent to testapp. drm/i915/dp: Add debugfs entry for DP phy compliance. drm/i915/dp: Register definition for DP compliance register drm/i915/dp: Update the pattern as per request drm/i915/dp: [FIXME] Program vswing, pre-emphasis, test-pattern .../gpu/drm/amd/display/dc/core/dc_link_dp.c | 2 +- drivers/gpu/drm/drm_dp_helper.c | 93 + drivers/gpu/drm/i915/display/intel_display.c | 24 ++- .../drm/i915/display/intel_display_types.h| 1 + drivers/gpu/drm/i915/display/intel_dp.c | 195 +- drivers/gpu/drm/i915/display/intel_dp.h | 5 + .../drm/i915/display/intel_dp_link_training.c | 32 --- drivers/gpu/drm/i915/i915_debugfs.c | 12 +- drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_reg.h | 20 ++ include/drm/drm_dp_helper.h | 33 ++- 11 files changed, 381 insertions(+), 38 deletions(-) -- 2.24.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/1] drm/dp: get/set phy compliance pattern
During phy compliance auto test mode source need to read requested test pattern from sink through DPCD. After processing the request source need to set the pattern. So set/get method added in drm layer as it is DP protocol. v1: As per review feedback from Manasi on RFC version, - added dp revision as function argument in set_phy_pattern api. - used int for link_rate and u8 for lane_count to align with existing code. Signed-off-by: Animesh Manna --- drivers/gpu/drm/drm_dp_helper.c | 93 + include/drm/drm_dp_helper.h | 33 +++- 2 files changed, 125 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 2c7870aef469..91c80973aa83 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -1371,3 +1371,96 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S return num_bpc; } EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs); + +/** + * drm_dp_get_phy_test_pattern() - get the requested pattern from the sink. + * @aux: DisplayPort AUX channel + * @data: DP phy compliance test parameters. + * + * Returns 0 on success or a negative error code on failure. + */ +int drm_dp_get_phy_test_pattern(struct drm_dp_aux *aux, + struct drm_dp_phy_test_params *data) +{ + int err; + u8 rate, lanes; + + err = drm_dp_dpcd_readb(aux, DP_TEST_LINK_RATE, &rate); + if (err < 0) + return err; + data->link_rate = drm_dp_bw_code_to_link_rate(rate); + + err = drm_dp_dpcd_readb(aux, DP_TEST_LANE_COUNT, &lanes); + if (err < 0) + return err; + data->num_lanes = lanes & DP_MAX_LANE_COUNT_MASK; + + if (lanes & DP_ENHANCED_FRAME_CAP) + data->enahanced_frame_cap = true; + + err = drm_dp_dpcd_readb(aux, DP_PHY_TEST_PATTERN, &data->phy_pattern); + if (err < 0) + return err; + + switch (data->phy_pattern) { + case DP_PHY_TEST_PATTERN_80BIT_CUSTOM: + err = drm_dp_dpcd_read(aux, DP_TEST_80BIT_CUSTOM_PATTERN_7_0, + &data->custom80, 10); + if (err < 0) + return err; + + break; + case DP_PHY_TEST_PATTERN_CP2520: + err = drm_dp_dpcd_read(aux, DP_TEST_HBR2_SCRAMBLER_RESET, + &data->hbr2_reset, 2); + if (err < 0) + return err; + } + + return 0; +} +EXPORT_SYMBOL(drm_dp_get_phy_test_pattern); + +/** + * drm_dp_set_phy_test_pattern() - set the pattern to the sink. + * @aux: DisplayPort AUX channel + * @data: DP phy compliance test parameters. + * + * Returns 0 on success or a negative error code on failure. + */ +int drm_dp_set_phy_test_pattern(struct drm_dp_aux *aux, + struct drm_dp_phy_test_params *data, u8 dp_rev) +{ + int err, i; + u8 link_config[2]; + u8 test_pattern; + + link_config[0] = drm_dp_link_rate_to_bw_code(data->link_rate); + link_config[1] = data->num_lanes; + if (data->enahanced_frame_cap) + link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + err = drm_dp_dpcd_write(aux, DP_LINK_BW_SET, link_config, 2); + if (err < 0) + return err; + + test_pattern = data->phy_pattern; + if (dp_rev < 0x12) { + test_pattern = (test_pattern << 2) & + DP_LINK_QUAL_PATTERN_11_MASK; + err = drm_dp_dpcd_writeb(aux, DP_TRAINING_PATTERN_SET, +test_pattern); + if (err < 0) + return err; + } else { + for (i = 0; i < data->num_lanes; i++) { + err = drm_dp_dpcd_writeb(aux, +DP_LINK_QUAL_LANE0_SET + i, +test_pattern); + if (err < 0) + return err; + } + } + + return 0; +} +EXPORT_SYMBOL(drm_dp_set_phy_test_pattern); diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 51ecb5112ef8..a64267d197d0 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -699,7 +699,16 @@ # define DP_TEST_CRC_SUPPORTED (1 << 5) # define DP_TEST_COUNT_MASK0xf -#define DP_TEST_PHY_PATTERN 0x248 +#define DP_PHY_TEST_PATTERN 0x248 +# define DP_PHY_TEST_PATTERN_SEL_MASK 0x7 +# define DP_PHY_TEST_PATTERN_NONE 0x0 +# define DP_PHY_TEST_PATTERN_D10_2 0x1 +# define DP_PHY_TEST_PATTERN_ERROR_COUNT0x2 +# define DP_PHY_TEST_PATTERN_PRBS7 0x
Re: [RFC] drm/i915: adding state checker for gamma lut values
Hi, On 3/20/2019 6:11 PM, Jani Nikula wrote: On Wed, 20 Mar 2019, "Sharma, Swati2" wrote: On 15-Mar-19 3:17 PM, Nikula, Jani wrote: On Fri, 15 Mar 2019, swati2.sha...@intel.com wrote: From: Swati Sharma Added state checker to validate gamma_lut values. This reads hardware state, and compares the originally requested state to the state read from hardware. This implementation can be used for Gen9+ platforms, I haven't implemented it for legacy platforms. Just want to get feedback if this is the right approach to follow. Also, inverse function of drm_color_lut_extract is missing to convert hardware read values back to user values. Thinking for that. I have added all "TODOs" and "Placeholders". Another approach: Storing "word" to be written into hardware in dev_priv and instead of comparing blob, comparing "word"? In dev_priv, only pointer will be there (something like *gamma_word). You can't store it in dev_priv because it's crtc state specific data. Even if stored in crtc state, the approach doesn't help the initial hw state readout and takeover. Please use intel-gfx mailing list for i915 patches. For this too, I will send a patch to make it more clear. Signed-off-by: Swati Sharma --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_color.c | 127 +-- drivers/gpu/drm/i915/intel_display.c | 50 ++ drivers/gpu/drm/i915/intel_drv.h | 1 + 4 files changed, 173 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c4ffe19..b41bfaa 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -334,6 +334,7 @@ struct drm_i915_display_funcs { * involved with the same commit. */ void (*load_luts)(const struct intel_crtc_state *crtc_state); + void (*get_config)(struct intel_crtc_state *crtc_state); The name is too generic. }; #define CSR_VERSION(major, minor) ((major) << 16 | (minor)) diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c index da7a07d..a515e9f 100644 --- a/drivers/gpu/drm/i915/intel_color.c +++ b/drivers/gpu/drm/i915/intel_color.c @@ -74,6 +74,11 @@ #define ILK_CSC_COEFF_1_0\ ((7 << 12) | ILK_CSC_COEFF_FP(CTM_COEFF_1_0, 8)) +/* Mask to extract RGB values from registers */ +#define COLOR_BLUE_MASK 0x03FF /* 9:0 */ +#define COLOR_GREEN_MASK0x000FFC00 /* 19:10 */ +#define COLOR_RED_MASK 0x3FF0 /* 29:20 */ These belong in i915_reg.h, and you need platform specific shifts and masks. The code that writes the registers seems to use magic numbers... + static bool lut_is_legacy(const struct drm_property_blob *lut) { return drm_color_lut_size(lut) == LEGACY_LUT_LENGTH; @@ -672,6 +677,97 @@ static void cherryview_load_luts(const struct intel_crtc_state *crtc_state) i9xx_load_luts_internal(crtc_state, NULL); } +static void bdw_get_gamma_config(struct intel_crtc_state *crtc_state, u32 offset) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_device *dev = crtc->base.dev; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + u32 i, tmp, lut_size = INTEL_INFO(dev_priv)->color.gamma_lut_size; + enum pipe pipe = crtc->pipe; + struct drm_property_blob *blob = NULL; + struct drm_color_lut *blob_data; + + WARN_ON(offset & ~PAL_PREC_INDEX_VALUE_MASK); + + I915_WRITE(PREC_PAL_INDEX(pipe), + (offset ? PAL_PREC_SPLIT_MODE : 0) | + PAL_PREC_AUTO_INCREMENT | + offset); + + blob = drm_property_create_blob(dev, + sizeof(struct drm_color_lut) * lut_size, + NULL); + if (IS_ERR(blob)) + return; + + blob_data = blob->data; + + for (i = 0; i < lut_size; i++) { + tmp = I915_READ(PREC_PAL_DATA(pipe)); + /* +* TODO: convert RGB value read from register into corresponding user value using +* some wrapper like drm_color_lut_put() (or) intel_color_lut_put() so that it +* can be compared later. +*/ Yeah, you'll need this. Can you please help in this? Something like this: /* convert hw value with given bit_precision to lut property val */ u32 drm_color_lut_pack(u32 val, u32 bit_precision) { u32 max = 0x >> (16 - bit_precision); val = clamp_val(val, 0, max); if (bit_precision < 16) val <<= 16 - bit_precision; return val; } /* compare two lut property values with given bit_precision */ bool drm_color_lut_match(u32 a, u32 b, u32 bit_precision) { u32 err = 0x >> bit_precision; return abs((long)a - b) <= err; } I didn't double check th