summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/atombios_output.c402
1 files changed, 208 insertions, 194 deletions
diff --git a/src/atombios_output.c b/src/atombios_output.c
index cad506e9..af0e59a9 100644
--- a/src/atombios_output.c
+++ b/src/atombios_output.c
@@ -65,7 +65,114 @@ const char *device_name[12] = {
"DFP5",
};
+#define AUX_NATIVE_WRITE 0x8
+#define AUX_NATIVE_READ 0x9
+
+#define AUX_I2C_WRITE 0x0
+#define AUX_I2C_READ 0x1
+#define AUX_I2C_STATUS 0x2
+#define AUX_I2C_MOT 0x4
+
+#define DP_DPCD_REV 0x0
+#define DP_MAX_LINK_RATE 0x1
+#define DP_MAX_LANE_COUNT 0x2
+#define DP_MAX_DOWNSPREAD 0x3
+#define DP_NORP 0x4
+#define DP_DOWNSTREAMPORT_PRESENT 0x5
+#define DP_MAIN_LINK_CHANNEL_CONFIG 0x6
+#define DP_DP11_DOWNSTREAM_PORT_COUNT 0x7
+
+/* from intel i830_dp.h */
+#define DP_LINK_BW_SET 0x100
+//# define DP_LINK_BW_1_62 0x06
+//# define DP_LINK_BW_2_7 0x0a
+#define DP_LANE_COUNT_SET 0x101
+# define DP_LANE_COUNT_MASK 0x0f
+# define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7)
+
+#define DP_TRAINING_PATTERN_SET 0x102
+
+# define DP_TRAINING_PATTERN_DISABLE 0
+# define DP_TRAINING_PATTERN_1 1
+# define DP_TRAINING_PATTERN_2 2
+# define DP_TRAINING_PATTERN_MASK 0x3
+
+# define DP_LINK_QUAL_PATTERN_DISABLE (0 << 2)
+# define DP_LINK_QUAL_PATTERN_D10_2 (1 << 2)
+# define DP_LINK_QUAL_PATTERN_ERROR_RATE (2 << 2)
+# define DP_LINK_QUAL_PATTERN_PRBS7 (3 << 2)
+# define DP_LINK_QUAL_PATTERN_MASK (3 << 2)
+# define DP_RECOVERED_CLOCK_OUT_EN (1 << 4)
+# define DP_LINK_SCRAMBLING_DISABLE (1 << 5)
+
+# define DP_SYMBOL_ERROR_COUNT_BOTH (0 << 6)
+# define DP_SYMBOL_ERROR_COUNT_DISPARITY (1 << 6)
+# define DP_SYMBOL_ERROR_COUNT_SYMBOL (2 << 6)
+# define DP_SYMBOL_ERROR_COUNT_MASK (3 << 6)
+
+#define DP_TRAINING_LANE0_SET 0x103
+#define DP_TRAINING_LANE1_SET 0x104
+#define DP_TRAINING_LANE2_SET 0x105
+#define DP_TRAINING_LANE3_SET 0x106
+# define DP_TRAIN_VOLTAGE_SWING_MASK 0x3
+# define DP_TRAIN_VOLTAGE_SWING_SHIFT 0
+# define DP_TRAIN_MAX_SWING_REACHED (1 << 2)
+# define DP_TRAIN_VOLTAGE_SWING_400 (0 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_600 (1 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_800 (2 << 0)
+# define DP_TRAIN_VOLTAGE_SWING_1200 (3 << 0)
+
+# define DP_TRAIN_PRE_EMPHASIS_MASK (3 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_0 (0 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_3_5 (1 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_6 (2 << 3)
+# define DP_TRAIN_PRE_EMPHASIS_9_5 (3 << 3)
+
+# define DP_TRAIN_PRE_EMPHASIS_SHIFT 3
+# define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED (1 << 5)
+#define DP_DOWNSPREAD_CTRL 0x107
+# define DP_SPREAD_AMP_0_5 (1 << 4)
+
+#define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108
+# define DP_SET_ANSI_8B10B (1 << 0)
+
+#define DP_LANE0_1_STATUS 0x202
+#define DP_LANE2_3_STATUS 0x203
+
+# define DP_LANE_CR_DONE (1 << 0)
+# define DP_LANE_CHANNEL_EQ_DONE (1 << 1)
+# define DP_LANE_SYMBOL_LOCKED (1 << 2)
+
+#define DP_LANE_ALIGN_STATUS_UPDATED 0x204
+#define DP_INTERLANE_ALIGN_DONE (1 << 0)
+#define DP_DOWNSTREAM_PORT_STATUS_CHANGED (1 << 6)
+#define DP_LINK_STATUS_UPDATED (1 << 7)
+
+#define DP_SINK_STATUS 0x205
+
+#define DP_RECEIVE_PORT_0_STATUS (1 << 0)
+#define DP_RECEIVE_PORT_1_STATUS (1 << 1)
+
+#define DP_ADJUST_REQUEST_LANE0_1 0x206
+#define DP_ADJUST_REQUEST_LANE2_3 0x207
+
+#define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03
+#define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0
+#define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c
+#define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2
+#define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30
+#define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4
+#define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0
+#define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6
+
+#define DP_LINK_STATUS_SIZE 6
+#define DP_LINK_CONFIGURATION_SIZE 9
+
+#define DP_SET_POWER_D0 0x1
+#define DP_SET_POWER_D3 0x2
+
static void do_displayport_link_train(xf86OutputPtr output);
+static void atombios_pick_dig_encoder(xf86OutputPtr output);
static int
atombios_output_dac_setup(xf86OutputPtr output, int action)
@@ -487,40 +594,68 @@ static const int num_dp_clocks = sizeof(dp_clocks) / sizeof(int);
# define DP_LINK_BW_1_62 0x06
# define DP_LINK_BW_2_7 0x0a
+static int radeon_dp_max_lane_count(xf86OutputPtr output);
static int
-dp_lanes_for_mode_clock(RADEONOutputPrivatePtr radeon_output,
- int mode_clock)
+dp_lanes_for_mode_clock(xf86OutputPtr output, int mode_clock)
{
+ RADEONOutputPrivatePtr radeon_output = output->driver_private;
int i;
int max_link_bw = radeon_output->dpcd[1];
+ int max_lane_count = radeon_dp_max_lane_count(output);
switch (max_link_bw) {
case DP_LINK_BW_1_62:
default:
for (i = 0; i < num_dp_clocks; i++) {
- if (i % 2)
- continue;
- if (dp_clocks[i] > (mode_clock / 10)) {
- if (i < 2)
- return 1;
- else if (i < 4)
- return 2;
- else
- return 4;
- }
+ if (i % 2)
+ continue;
+ switch (max_lane_count) {
+ case 1:
+ if (i > 1)
+ return 0;
+ break;
+ case 2:
+ if (i > 3)
+ return 0;
+ break;
+ case 4:
+ default:
+ break;
+ }
+ if (dp_clocks[i] > (mode_clock/10)) {
+ if (i < 2)
+ return 1;
+ else if (i < 4)
+ return 2;
+ else
+ return 4;
+ }
}
break;
case DP_LINK_BW_2_7:
for (i = 0; i < num_dp_clocks; i++) {
- if (dp_clocks[i] > (mode_clock / 10)) {
- if (i < 2)
- return 1;
- else if (i < 4)
- return 2;
- else
- return 4;
- }
+ switch (max_lane_count) {
+ case 1:
+ if (i > 1)
+ return 0;
+ break;
+ case 2:
+ if (i > 3)
+ return 0;
+ break;
+ case 4:
+ default:
+ break;
+ }
+ if (dp_clocks[i] > (mode_clock/10)) {
+ if (i < 2)
+ return 1;
+ else if (i < 4)
+ return 2;
+ else
+ return 4;
+ }
}
break;
}
@@ -529,21 +664,54 @@ dp_lanes_for_mode_clock(RADEONOutputPrivatePtr radeon_output,
}
static int
-dp_link_clock_for_mode_clock(RADEONOutputPrivatePtr radeon_output,
- int mode_clock)
+dp_link_clock_for_mode_clock(xf86OutputPtr output, int mode_clock)
{
+ RADEONOutputPrivatePtr radeon_output = output->driver_private;
int i;
int max_link_bw = radeon_output->dpcd[1];
+ int max_lane_count = radeon_dp_max_lane_count(output);
switch (max_link_bw) {
case DP_LINK_BW_1_62:
default:
- return 16200;
+ for (i = 0; i < num_dp_clocks; i++) {
+ if (i % 2)
+ continue;
+ switch (max_lane_count) {
+ case 1:
+ if (i > 1)
+ return 0;
+ break;
+ case 2:
+ if (i > 3)
+ return 0;
+ break;
+ case 4:
+ default:
+ break;
+ }
+ if (dp_clocks[i] > (mode_clock/10))
+ return 16200;
+ }
break;
case DP_LINK_BW_2_7:
- for (i = 0; i < num_dp_clocks; i++)
- if (dp_clocks[i] > (mode_clock / 10))
- return (i % 2) ? 27000 : 16200;
+ for (i = 0; i < num_dp_clocks; i++) {
+ switch (max_lane_count) {
+ case 1:
+ if (i > 1)
+ return 0;
+ break;
+ case 2:
+ if (i > 3)
+ return 0;
+ break;
+ case 4:
+ default:
+ break;
+ }
+ if (dp_clocks[i] > (mode_clock/10))
+ return (i % 2) ? 27000 : 16200;
+ }
break;
}
@@ -624,9 +792,9 @@ atombios_output_dig_encoder_setup(xf86OutputPtr output, int action)
disp_data.v1.ucEncoderMode = atombios_get_encoder_mode(output);
if (disp_data.v1.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
- if (dp_link_clock_for_mode_clock(radeon_output, clock) == 27000)
+ if (dp_link_clock_for_mode_clock(output, clock) == 27000)
disp_data.v1.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
- disp_data.v1.ucLaneNum = dp_lanes_for_mode_clock(radeon_output, clock);
+ disp_data.v1.ucLaneNum = dp_lanes_for_mode_clock(output, clock);
} else if (clock > 165000)
disp_data.v1.ucLaneNum = 8;
else
@@ -716,7 +884,7 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action, uint8_t
} else {
if (radeon_output->MonType == MT_DP)
disp_data.v1.usPixelClock =
- cpu_to_le16(dp_link_clock_for_mode_clock(radeon_output, clock));
+ cpu_to_le16(dp_link_clock_for_mode_clock(output, clock));
else if (clock > 165000)
disp_data.v1.usPixelClock = cpu_to_le16((clock / 2) / 10);
else
@@ -725,7 +893,7 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action, uint8_t
if (IS_DCE4_VARIANT) {
if (radeon_output->MonType == MT_DP)
- disp_data.v3.ucLaneNum = dp_lanes_for_mode_clock(radeon_output, clock);
+ disp_data.v3.ucLaneNum = dp_lanes_for_mode_clock(output, clock);
else if (clock > 165000)
disp_data.v3.ucLaneNum = 8;
else
@@ -1301,6 +1469,7 @@ atombios_output_dpms(xf86OutputPtr output, int mode)
if (radeon_encoder == NULL)
return;
+ atombios_pick_dig_encoder(output);
switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
@@ -1887,111 +2056,6 @@ atombios_dac_detect(xf86OutputPtr output)
return MonType;
}
-#define AUX_NATIVE_WRITE 0x8
-#define AUX_NATIVE_READ 0x9
-
-#define AUX_I2C_WRITE 0x0
-#define AUX_I2C_READ 0x1
-#define AUX_I2C_STATUS 0x2
-#define AUX_I2C_MOT 0x4
-
-#define DP_DPCD_REV 0x0
-#define DP_MAX_LINK_RATE 0x1
-#define DP_MAX_LANE_COUNT 0x2
-#define DP_MAX_DOWNSPREAD 0x3
-#define DP_NORP 0x4
-#define DP_DOWNSTREAMPORT_PRESENT 0x5
-#define DP_MAIN_LINK_CHANNEL_CONFIG 0x6
-#define DP_DP11_DOWNSTREAM_PORT_COUNT 0x7
-
-/* from intel i830_dp.h */
-#define DP_LINK_BW_SET 0x100
-//# define DP_LINK_BW_1_62 0x06
-//# define DP_LINK_BW_2_7 0x0a
-#define DP_LANE_COUNT_SET 0x101
-# define DP_LANE_COUNT_MASK 0x0f
-# define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7)
-
-#define DP_TRAINING_PATTERN_SET 0x102
-
-# define DP_TRAINING_PATTERN_DISABLE 0
-# define DP_TRAINING_PATTERN_1 1
-# define DP_TRAINING_PATTERN_2 2
-# define DP_TRAINING_PATTERN_MASK 0x3
-
-# define DP_LINK_QUAL_PATTERN_DISABLE (0 << 2)
-# define DP_LINK_QUAL_PATTERN_D10_2 (1 << 2)
-# define DP_LINK_QUAL_PATTERN_ERROR_RATE (2 << 2)
-# define DP_LINK_QUAL_PATTERN_PRBS7 (3 << 2)
-# define DP_LINK_QUAL_PATTERN_MASK (3 << 2)
-# define DP_RECOVERED_CLOCK_OUT_EN (1 << 4)
-# define DP_LINK_SCRAMBLING_DISABLE (1 << 5)
-
-# define DP_SYMBOL_ERROR_COUNT_BOTH (0 << 6)
-# define DP_SYMBOL_ERROR_COUNT_DISPARITY (1 << 6)
-# define DP_SYMBOL_ERROR_COUNT_SYMBOL (2 << 6)
-# define DP_SYMBOL_ERROR_COUNT_MASK (3 << 6)
-
-#define DP_TRAINING_LANE0_SET 0x103
-#define DP_TRAINING_LANE1_SET 0x104
-#define DP_TRAINING_LANE2_SET 0x105
-#define DP_TRAINING_LANE3_SET 0x106
-# define DP_TRAIN_VOLTAGE_SWING_MASK 0x3
-# define DP_TRAIN_VOLTAGE_SWING_SHIFT 0
-# define DP_TRAIN_MAX_SWING_REACHED (1 << 2)
-# define DP_TRAIN_VOLTAGE_SWING_400 (0 << 0)
-# define DP_TRAIN_VOLTAGE_SWING_600 (1 << 0)
-# define DP_TRAIN_VOLTAGE_SWING_800 (2 << 0)
-# define DP_TRAIN_VOLTAGE_SWING_1200 (3 << 0)
-
-# define DP_TRAIN_PRE_EMPHASIS_MASK (3 << 3)
-# define DP_TRAIN_PRE_EMPHASIS_0 (0 << 3)
-# define DP_TRAIN_PRE_EMPHASIS_3_5 (1 << 3)
-# define DP_TRAIN_PRE_EMPHASIS_6 (2 << 3)
-# define DP_TRAIN_PRE_EMPHASIS_9_5 (3 << 3)
-
-# define DP_TRAIN_PRE_EMPHASIS_SHIFT 3
-# define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED (1 << 5)
-#define DP_DOWNSPREAD_CTRL 0x107
-# define DP_SPREAD_AMP_0_5 (1 << 4)
-
-#define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108
-# define DP_SET_ANSI_8B10B (1 << 0)
-
-#define DP_LANE0_1_STATUS 0x202
-#define DP_LANE2_3_STATUS 0x203
-
-# define DP_LANE_CR_DONE (1 << 0)
-# define DP_LANE_CHANNEL_EQ_DONE (1 << 1)
-# define DP_LANE_SYMBOL_LOCKED (1 << 2)
-
-#define DP_LANE_ALIGN_STATUS_UPDATED 0x204
-#define DP_INTERLANE_ALIGN_DONE (1 << 0)
-#define DP_DOWNSTREAM_PORT_STATUS_CHANGED (1 << 6)
-#define DP_LINK_STATUS_UPDATED (1 << 7)
-
-#define DP_SINK_STATUS 0x205
-
-#define DP_RECEIVE_PORT_0_STATUS (1 << 0)
-#define DP_RECEIVE_PORT_1_STATUS (1 << 1)
-
-#define DP_ADJUST_REQUEST_LANE0_1 0x206
-#define DP_ADJUST_REQUEST_LANE2_3 0x207
-
-#define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03
-#define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0
-#define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c
-#define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2
-#define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30
-#define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4
-#define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0
-#define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6
-
-#define DP_LINK_STATUS_SIZE 6
-#define DP_LINK_CONFIGURATION_SIZE 9
-
-#define DP_SET_POWER_D0 0x1
-#define DP_SET_POWER_D3 0x2
static inline int atom_dp_get_encoder_id(xf86OutputPtr output)
{
@@ -2534,66 +2598,16 @@ static int radeon_dp_max_lane_count(xf86OutputPtr output)
return max_lane_count;
}
-static int radeon_dp_max_link_bw(xf86OutputPtr output)
-{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- int max_link_bw = radeon_output->dpcd[1];
- switch(max_link_bw) {
- case DP_LINK_BW_1_62:
- case DP_LINK_BW_2_7:
- break;
- default:
- max_link_bw = DP_LINK_BW_1_62;
- break;
- }
- return max_link_bw;
-}
-
-static int radeon_dp_link_clock(uint8_t link_bw)
-{
- if (link_bw == DP_LINK_BW_2_7)
- return 270000;
- else
- return 162000;
-}
-
-
-/* I think this is a fiction */
-static int radeon_dp_link_required(int pixel_clock)
-{
- return pixel_clock * 3;
-}
-
-static int link_bw_avail(int max_link_clock, int max_lanes)
-{
- return (max_link_clock * max_lanes * 8) / 10;
-}
-
Bool radeon_dp_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode)
{
- RADEONOutputPrivatePtr radeon_output = output->driver_private;
- int lane_count, clock;
- int max_lane_count = radeon_dp_max_lane_count(output);
- int max_clock = radeon_dp_max_link_bw(output) == DP_LINK_BW_2_7 ? 1 : 0;
- static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
-
- for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
- for (clock = 0; clock <= max_clock; clock++) {
- int link_avail = link_bw_avail(radeon_dp_link_clock(bws[clock]), lane_count);
-
- if (radeon_dp_link_required(mode->Clock) <= link_avail) {
- radeon_output->dp_lane_count = lane_count;
- radeon_output->dp_clock = radeon_dp_link_clock(bws[clock]);
- if (0)
- xf86DrvMsg(0, X_INFO,
- "lane_count %d clock %d\n",
- radeon_output->dp_lane_count,
- radeon_output->dp_clock);
- return TRUE;
- }
- }
- }
- return FALSE;
+ RADEONOutputPrivatePtr radeon_output = output->driver_private;
+ int clock = adjusted_mode->Clock;
+
+ radeon_output->dp_lane_count = dp_lanes_for_mode_clock(output, clock);
+ radeon_output->dp_clock = dp_link_clock_for_mode_clock(output, clock);
+ if (!radeon_output->dp_lane_count || !radeon_output->dp_clock)
+ return FALSE;
+ return TRUE;
}
static void dp_update_dpvs_emph(xf86OutputPtr output, uint8_t train_set[4])
@@ -2625,7 +2639,7 @@ static void do_displayport_link_train(xf86OutputPtr output)
/* set up link configuration */
memset(dp_link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
- if (radeon_output->dp_clock == 270000)
+ if (radeon_output->dp_clock == 27000)
dp_link_configuration[0] = DP_LINK_BW_2_7;
else
dp_link_configuration[0] = DP_LINK_BW_1_62;