radeon_hd: Improve tracing; implement older DCE3 DP training.
* Implement older DCE 3 DisplayPort Training Service.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016, Haiku, Inc. All Rights Reserved.
|
* Copyright 2016-2017, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -21,4 +21,22 @@
|
|||||||
#define ATOM_S2_DFP5_DPMS_STATE 0x08000000L
|
#define ATOM_S2_DFP5_DPMS_STATE 0x08000000L
|
||||||
|
|
||||||
|
|
||||||
|
// ucAction
|
||||||
|
#define ATOM_DP_ACTION_TRAINING_START 0x02
|
||||||
|
#define ATOM_DP_ACTION_TRAINING_COMPLETE 0x03
|
||||||
|
#define ATOM_DP_ACTION_TRAINING_PATTERN_SEL 0x04
|
||||||
|
#define ATOM_DP_ACTION_SET_VSWING_PREEMP 0x05
|
||||||
|
#define ATOM_DP_ACTION_GET_VSWING_PREEMP 0x06
|
||||||
|
#define ATOM_DP_ACTION_BLANKING 0x07
|
||||||
|
|
||||||
|
// ucConfig
|
||||||
|
#define ATOM_DP_CONFIG_ENCODER_SEL_MASK 0x03
|
||||||
|
#define ATOM_DP_CONFIG_DIG1_ENCODER 0x00
|
||||||
|
#define ATOM_DP_CONFIG_DIG2_ENCODER 0x01
|
||||||
|
#define ATOM_DP_CONFIG_EXTERNAL_ENCODER 0x02
|
||||||
|
#define ATOM_DP_CONFIG_LINK_SEL_MASK 0x04
|
||||||
|
#define ATOM_DP_CONFIG_LINK_A 0x00
|
||||||
|
#define ATOM_DP_CONFIG_LINK_B 0x04
|
||||||
|
|
||||||
|
|
||||||
#endif /* _ATOMBIOS_OBSOLETE_H */
|
#endif /* _ATOMBIOS_OBSOLETE_H */
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <Debug.h>
|
#include <Debug.h>
|
||||||
|
|
||||||
#include "accelerant_protos.h"
|
#include "accelerant_protos.h"
|
||||||
|
#include "atombios-obsolete.h"
|
||||||
#include "connector.h"
|
#include "connector.h"
|
||||||
#include "mode.h"
|
#include "mode.h"
|
||||||
#include "edid.h"
|
#include "edid.h"
|
||||||
@@ -327,6 +328,28 @@ dp_aux_set_i2c_byte(uint32 connectorIndex, uint16 address, uint8* data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
dp_get_encoder_config(uint32 connectorIndex)
|
||||||
|
{
|
||||||
|
uint32 result = 0;
|
||||||
|
|
||||||
|
uint32 digEncoderID = encoder_pick_dig(connectorIndex);
|
||||||
|
if (digEncoderID)
|
||||||
|
result |= ATOM_DP_CONFIG_DIG2_ENCODER;
|
||||||
|
else
|
||||||
|
result |= ATOM_DP_CONFIG_DIG1_ENCODER;
|
||||||
|
|
||||||
|
bool linkB = gConnector[connectorIndex]->encoder.linkEnumeration
|
||||||
|
== GRAPH_OBJECT_ENUM_ID2 ? true : false;
|
||||||
|
if (linkB)
|
||||||
|
result |= ATOM_DP_CONFIG_LINK_B;
|
||||||
|
else
|
||||||
|
result |= ATOM_DP_CONFIG_LINK_A;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32
|
uint32
|
||||||
dp_get_lane_count(uint32 connectorIndex, display_mode* mode)
|
dp_get_lane_count(uint32 connectorIndex, display_mode* mode)
|
||||||
{
|
{
|
||||||
@@ -541,17 +564,21 @@ dp_clock_equalization_ok(dp_info* dp)
|
|||||||
uint8 laneAlignment
|
uint8 laneAlignment
|
||||||
= dp->linkStatus[DP_LANE_ALIGN - DP_LANE_STATUS_0_1];
|
= dp->linkStatus[DP_LANE_ALIGN - DP_LANE_STATUS_0_1];
|
||||||
|
|
||||||
if ((laneAlignment & DP_LANE_ALIGN_DONE) == 0)
|
if ((laneAlignment & DP_LANE_ALIGN_DONE) == 0) {
|
||||||
|
TRACE("%s: false. Lane alignment incomplete.\n", __func__);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int lane;
|
int lane;
|
||||||
for (lane = 0; lane < dp->laneCount; lane++) {
|
for (lane = 0; lane < dp->laneCount; lane++) {
|
||||||
uint8 laneStatus = dp_get_lane_status(dp, lane);
|
uint8 laneStatus = dp_get_lane_status(dp, lane);
|
||||||
if ((laneStatus & DP_LANE_STATUS_EQUALIZED_A)
|
if ((laneStatus & DP_LANE_STATUS_EQUALIZED_A)
|
||||||
!= DP_LANE_STATUS_EQUALIZED_A) {
|
!= DP_LANE_STATUS_EQUALIZED_A) {
|
||||||
|
TRACE("%s: false. Lanes not yet equalized.\n", __func__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
TRACE("%s: true. Lanes equalized.\n", __func__);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -649,24 +676,39 @@ static void
|
|||||||
dp_set_tp(uint32 connectorIndex, int trainingPattern)
|
dp_set_tp(uint32 connectorIndex, int trainingPattern)
|
||||||
{
|
{
|
||||||
TRACE("%s\n", __func__);
|
TRACE("%s\n", __func__);
|
||||||
|
radeon_shared_info &info = *gInfo->shared_info;
|
||||||
|
|
||||||
pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
|
pll_info* pll = &gConnector[connectorIndex]->encoder.pll;
|
||||||
|
|
||||||
int rawTrainingPattern = 0;
|
int rawTrainingPattern = 0;
|
||||||
|
|
||||||
/* set training pattern on the source */
|
if (info.dceMajor >= 4) {
|
||||||
TRACE("%s: Training with encoder...\n", __func__);
|
TRACE("%s: Training with encoder...\n", __func__);
|
||||||
switch (trainingPattern) {
|
switch (trainingPattern) {
|
||||||
case DP_TRAIN_PATTERN_1:
|
case DP_TRAIN_PATTERN_1:
|
||||||
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1;
|
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1;
|
||||||
break;
|
break;
|
||||||
case DP_TRAIN_PATTERN_2:
|
case DP_TRAIN_PATTERN_2:
|
||||||
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2;
|
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2;
|
||||||
break;
|
break;
|
||||||
case DP_TRAIN_PATTERN_3:
|
case DP_TRAIN_PATTERN_3:
|
||||||
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3;
|
rawTrainingPattern = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
encoder_dig_setup(connectorIndex, pll->pixelClock, rawTrainingPattern);
|
||||||
|
} else {
|
||||||
|
switch (trainingPattern) {
|
||||||
|
case DP_TRAIN_PATTERN_1:
|
||||||
|
rawTrainingPattern = 0;
|
||||||
|
break;
|
||||||
|
case DP_TRAIN_PATTERN_2:
|
||||||
|
rawTrainingPattern = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
uint32 encoderConfig = dp_get_encoder_config(connectorIndex);
|
||||||
|
dp_encoder_service(ATOM_DP_ACTION_TRAINING_PATTERN_SEL, pll->pixelClock,
|
||||||
|
rawTrainingPattern, encoderConfig);
|
||||||
}
|
}
|
||||||
encoder_dig_setup(connectorIndex, pll->pixelClock, rawTrainingPattern);
|
|
||||||
|
|
||||||
// Enable training pattern on the sink
|
// Enable training pattern on the sink
|
||||||
dpcd_reg_write(connectorIndex, DP_TRAIN, trainingPattern);
|
dpcd_reg_write(connectorIndex, DP_TRAIN, trainingPattern);
|
||||||
@@ -676,7 +718,7 @@ dp_set_tp(uint32 connectorIndex, int trainingPattern)
|
|||||||
status_t
|
status_t
|
||||||
dp_link_train_cr(uint32 connectorIndex)
|
dp_link_train_cr(uint32 connectorIndex)
|
||||||
{
|
{
|
||||||
TRACE("%s\n", __func__);
|
TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex);
|
||||||
|
|
||||||
dp_info* dp = &gConnector[connectorIndex]->dpInfo;
|
dp_info* dp = &gConnector[connectorIndex]->dpInfo;
|
||||||
|
|
||||||
@@ -748,7 +790,7 @@ dp_link_train_cr(uint32 connectorIndex)
|
|||||||
status_t
|
status_t
|
||||||
dp_link_train_ce(uint32 connectorIndex, bool tp3Support)
|
dp_link_train_ce(uint32 connectorIndex, bool tp3Support)
|
||||||
{
|
{
|
||||||
TRACE("%s\n", __func__);
|
TRACE("%s: connector %" B_PRIu32 "\n", __func__, connectorIndex);
|
||||||
|
|
||||||
dp_info* dp = &gConnector[connectorIndex]->dpInfo;
|
dp_info* dp = &gConnector[connectorIndex]->dpInfo;
|
||||||
|
|
||||||
@@ -853,9 +895,16 @@ dp_link_train(uint8 crtcID)
|
|||||||
sandbox = dp_encode_link_rate(dp->linkRate);
|
sandbox = dp_encode_link_rate(dp->linkRate);
|
||||||
dpcd_reg_write(connectorIndex, DP_LINK_RATE, sandbox);
|
dpcd_reg_write(connectorIndex, DP_LINK_RATE, sandbox);
|
||||||
|
|
||||||
|
uint32 encoderConfig = dp_get_encoder_config(connectorIndex);
|
||||||
|
|
||||||
// Start link training on source
|
// Start link training on source
|
||||||
encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
|
if (info.dceMajor >= 4) {
|
||||||
ATOM_ENCODER_CMD_DP_LINK_TRAINING_START);
|
encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
|
||||||
|
ATOM_ENCODER_CMD_DP_LINK_TRAINING_START);
|
||||||
|
} else {
|
||||||
|
dp_encoder_service(ATOM_DP_ACTION_TRAINING_START,
|
||||||
|
mode->timing.pixel_clock, 0, encoderConfig);
|
||||||
|
}
|
||||||
|
|
||||||
// Disable the training pattern on the sink
|
// Disable the training pattern on the sink
|
||||||
dpcd_reg_write(connectorIndex, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED);
|
dpcd_reg_write(connectorIndex, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED);
|
||||||
@@ -870,8 +919,13 @@ dp_link_train(uint8 crtcID)
|
|||||||
dpcd_reg_write(connectorIndex, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED);
|
dpcd_reg_write(connectorIndex, DP_TRAIN, DP_TRAIN_PATTERN_DISABLED);
|
||||||
|
|
||||||
// Disable the training pattern on the source
|
// Disable the training pattern on the source
|
||||||
encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
|
if (info.dceMajor >= 4) {
|
||||||
ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE);
|
encoder_dig_setup(connectorIndex, mode->timing.pixel_clock,
|
||||||
|
ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE);
|
||||||
|
} else {
|
||||||
|
dp_encoder_service(ATOM_DP_ACTION_TRAINING_COMPLETE,
|
||||||
|
mode->timing.pixel_clock, 0, encoderConfig);
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ status_t dp_aux_get_i2c_byte(uint32 connectorIndex, uint16 address,
|
|||||||
|
|
||||||
uint32 dp_get_link_rate(uint32 connectorIndex, display_mode* mode);
|
uint32 dp_get_link_rate(uint32 connectorIndex, display_mode* mode);
|
||||||
uint32 dp_get_lane_count(uint32 connectorIndex, display_mode* mode);
|
uint32 dp_get_lane_count(uint32 connectorIndex, display_mode* mode);
|
||||||
|
uint32 dp_get_encoder_config(uint32 connectorIndex);
|
||||||
uint8 dp_get_sink_type(uint32 connectorIndex);
|
uint8 dp_get_sink_type(uint32 connectorIndex);
|
||||||
|
|
||||||
void dp_setup_connectors();
|
void dp_setup_connectors();
|
||||||
|
|||||||
Reference in New Issue
Block a user