Skip to content

Commit

Permalink
drm/msm/dp: Add DP compliance tests on Snapdragon Chipsets
Browse files Browse the repository at this point in the history
add event thread to execute events serially from event queue. Also
timeout mode is supported  which allow an event be deferred to be
executed at later time. Both link and phy compliant tests had been
done successfully.

Changes in v2:
-- Fix potential deadlock by removing redundant connect_mutex
-- Check and enable link clock during modeset
-- Drop unused code and fix function prototypes.
-- set sink power to normal operation state (D0) before DPCD read

Changes in v3:
-- push idle pattern at main link before timing generator off
-- add timeout handles for both connect and disconnect

Changes in v4:
-- add ST_SUSPEND_PENDING to handles suspend/modeset test operations
-- clear dp phy aux interrupt status when ERR_DPPHY_AUX error
-- send segment addr during edid read
-- clear bpp depth before MISC register write

Changes in v5:
-- add ST_SUSPENDED to fix crash at resume

Changes in v6:
-- at msm_dp_display_enable() do not return until resume_done to avoid
   kms commit timeout

Signed-off-by: Kuogee Hsieh <khsieh@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@chromium.org>
  • Loading branch information
Kuogee Hsieh authored and Rob Clark committed Sep 15, 2020
1 parent 220b856 commit 8ede2ec
Show file tree
Hide file tree
Showing 19 changed files with 1,050 additions and 457 deletions.
6 changes: 6 additions & 0 deletions drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -1225,6 +1225,11 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
/* wait for idle */
dpu_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE);

if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS && priv->dp) {
if (msm_dp_display_pre_disable(priv->dp, drm_enc))
DPU_ERROR_ENC(dpu_enc, "dp display push idle failed\n");
}

dpu_encoder_resource_control(drm_enc, DPU_ENC_RC_EVENT_PRE_STOP);

for (i = 0; i < dpu_enc->num_phys_encs; i++) {
Expand All @@ -1234,6 +1239,7 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
phys->ops.disable(phys);
}


/* after phys waits for frame-done, should be no more frames pending */
if (atomic_xchg(&dpu_enc->frame_done_timeout_ms, 0)) {
DPU_ERROR("enc%d timeout pending\n", drm_enc->base.id);
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/msm/dp/dp_aux.c
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
PHY_AUX_CFG1);
dp_catalog_aux_reset(aux->catalog);
}
usleep_range(400, 500); /* at least 400us to next try */
goto unlock_exit;
}

Expand Down
77 changes: 52 additions & 25 deletions drivers/gpu/drm/msm/dp/dp_catalog.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,16 +536,21 @@ void dp_catalog_ctrl_mainlink_ctrl(struct dp_catalog *dp_catalog,
* To make sure link reg writes happens before other operation,
* dp_write_link() function uses writel()
*/
dp_write_link(catalog, REG_DP_MAINLINK_CTRL,
DP_MAINLINK_FB_BOUNDARY_SEL);
dp_write_link(catalog, REG_DP_MAINLINK_CTRL,
DP_MAINLINK_FB_BOUNDARY_SEL |
DP_MAINLINK_CTRL_RESET);
dp_write_link(catalog, REG_DP_MAINLINK_CTRL,
mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);

mainlink_ctrl &= ~(DP_MAINLINK_CTRL_RESET |
DP_MAINLINK_CTRL_ENABLE);
dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);

mainlink_ctrl |= DP_MAINLINK_CTRL_RESET;
dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);

mainlink_ctrl &= ~DP_MAINLINK_CTRL_RESET;
dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);

mainlink_ctrl |= (DP_MAINLINK_CTRL_ENABLE |
DP_MAINLINK_FB_BOUNDARY_SEL);
dp_write_link(catalog, REG_DP_MAINLINK_CTRL,
DP_MAINLINK_FB_BOUNDARY_SEL |
DP_MAINLINK_CTRL_ENABLE);
dp_write_link(catalog, REG_DP_MAINLINK_CTRL, mainlink_ctrl);
} else {
mainlink_ctrl = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
mainlink_ctrl &= ~DP_MAINLINK_CTRL_ENABLE;
Expand Down Expand Up @@ -644,7 +649,7 @@ int dp_catalog_ctrl_set_pattern(struct dp_catalog *dp_catalog,

bit = BIT(pattern - 1);
DRM_DEBUG_DP("hw: bit=%d train=%d\n", bit, pattern);
dp_write_link(catalog, REG_DP_STATE_CTRL, bit);
dp_catalog_ctrl_state_ctrl(dp_catalog, bit);

bit = BIT(pattern - 1) << DP_MAINLINK_READY_LINK_TRAINING_SHIFT;

Expand Down Expand Up @@ -769,7 +774,7 @@ void dp_catalog_ctrl_hpd_config(struct dp_catalog *dp_catalog)
/* enable HPD interrupts */
dp_catalog_hpd_config_intr(dp_catalog,
DP_DP_HPD_PLUG_INT_MASK | DP_DP_IRQ_HPD_INT_MASK
| DP_DP_HPD_UNPLUG_INT_MASK, true);
| DP_DP_HPD_UNPLUG_INT_MASK | DP_DP_HPD_REPLUG_INT_MASK, true);

/* Configure REFTIMER and enable it */
reftimer |= DP_DP_HPD_REFTIMER_ENABLE;
Expand Down Expand Up @@ -881,15 +886,27 @@ void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog,
dp_write_link(catalog, REG_DP_STATE_CTRL, 0x0);

switch (pattern) {
case DP_LINK_QUAL_PATTERN_D10_2:
case DP_PHY_TEST_PATTERN_D10_2:
dp_write_link(catalog, REG_DP_STATE_CTRL,
DP_STATE_CTRL_LINK_TRAINING_PATTERN1);
return;
case DP_LINK_QUAL_PATTERN_PRBS7:
break;
case DP_PHY_TEST_PATTERN_ERROR_COUNT:
value &= ~(1 << 16);
dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
value);
value |= SCRAMBLER_RESET_COUNT_VALUE;
dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
value);
dp_write_link(catalog, REG_DP_MAINLINK_LEVELS,
DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2);
dp_write_link(catalog, REG_DP_STATE_CTRL,
DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE);
break;
case DP_PHY_TEST_PATTERN_PRBS7:
dp_write_link(catalog, REG_DP_STATE_CTRL,
DP_STATE_CTRL_LINK_PRBS7);
return;
case DP_LINK_QUAL_PATTERN_80BIT_CUSTOM:
break;
case DP_PHY_TEST_PATTERN_80BIT_CUSTOM:
dp_write_link(catalog, REG_DP_STATE_CTRL,
DP_STATE_CTRL_LINK_TEST_CUSTOM_PATTERN);
/* 00111110000011111000001111100000 */
Expand All @@ -901,25 +918,35 @@ void dp_catalog_ctrl_send_phy_pattern(struct dp_catalog *dp_catalog,
/* 1111100000111110 */
dp_write_link(catalog, REG_DP_TEST_80BIT_CUSTOM_PATTERN_REG2,
0x0000F83E);
return;
case DP_LINK_QUAL_PATTERN_HBR2_EYE:
case DP_LINK_QUAL_PATTERN_ERROR_RATE:
value &= ~DP_HBR2_ERM_PATTERN;
if (pattern == DP_LINK_QUAL_PATTERN_HBR2_EYE)
value = DP_HBR2_ERM_PATTERN;
break;
case DP_PHY_TEST_PATTERN_CP2520:
value = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
value &= ~DP_MAINLINK_CTRL_SW_BYPASS_SCRAMBLER;
dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value);

value = DP_HBR2_ERM_PATTERN;
dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
value);
value);
value |= SCRAMBLER_RESET_COUNT_VALUE;
dp_write_link(catalog, REG_DP_HBR2_COMPLIANCE_SCRAMBLER_RESET,
value);
dp_write_link(catalog, REG_DP_MAINLINK_LEVELS,
DP_MAINLINK_SAFE_TO_EXIT_LEVEL_2);
dp_write_link(catalog, REG_DP_STATE_CTRL,
DP_STATE_CTRL_LINK_SYMBOL_ERR_MEASURE);
return;
value = dp_read_link(catalog, REG_DP_MAINLINK_CTRL);
value |= DP_MAINLINK_CTRL_ENABLE;
dp_write_link(catalog, REG_DP_MAINLINK_CTRL, value);
break;
case DP_PHY_TEST_PATTERN_SEL_MASK:
dp_write_link(catalog, REG_DP_MAINLINK_CTRL,
DP_MAINLINK_CTRL_ENABLE);
dp_write_link(catalog, REG_DP_STATE_CTRL,
DP_STATE_CTRL_LINK_TRAINING_PATTERN4);
break;
default:
DRM_DEBUG_DP("No valid test pattern requested:0x%x\n", pattern);
return;
break;
}
}

Expand Down
Loading

0 comments on commit 8ede2ec

Please sign in to comment.