From c1e5925282725c3410d5d9646e71a8af304b56ab Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Jan 25 2010 04:03:17 +0000 Subject: - rebase to upstream - fix es1000 bug with 64MB VRAM --- diff --git a/.cvsignore b/.cvsignore index bbcbe99..85ec263 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,3 +1,4 @@ xf86-video-ati-20090929.tar.xz radeon-rlc-firmware-1.tar.bz2 xf86-video-ati-20091221.tar.xz +xf86-video-ati-20100125.tar.xz diff --git a/radeon-ums-displayport.patch b/radeon-ums-displayport.patch deleted file mode 100644 index 6e52960..0000000 --- a/radeon-ums-displayport.patch +++ /dev/null @@ -1,1372 +0,0 @@ -diff --git a/src/atombios_output.c b/src/atombios_output.c -index c9f1dfa..8047b53 100644 ---- a/src/atombios_output.c -+++ b/src/atombios_output.c -@@ -65,6 +65,8 @@ const char *device_name[12] = { - "DFP5", - }; - -+static void do_displayport_link_train(xf86OutputPtr output); -+ - static void atombios_set_output_crtc_source(xf86OutputPtr output); - - static int -@@ -466,41 +468,102 @@ atombios_get_encoder_mode(xf86OutputPtr output) - } - - static const int dp_clocks[] = { -- 16200, -- 27000, -- 32400, -- 54000, -- 0, -- 0, -- 64800, -- 108000, -+ 5400, // 1 lane, 1.62 Ghz -+ 9000, // 1 lane, 2.70 Ghz -+ 10800, // 2 lane, 1.62 Ghz -+ 18000, // 2 lane, 2.70 Ghz -+ 21600, // 4 lane, 1.62 Ghz -+ 36000, // 4 lane, 2.70 Ghz - }; - 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 --dp_lanes_for_mode_clock(int mode_clock) -+dp_lanes_for_mode_clock(RADEONOutputPrivatePtr radeon_output, -+ int mode_clock) - { - int i; -- -- for (i = 0; i < num_dp_clocks; i++) -- if (dp_clocks[i] > (mode_clock / 10)) -- return (i / 2) + 1; -+ int max_link_bw = radeon_output->dpcd[1]; -+ -+ 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; -+ } -+ } -+ 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; -+ } -+ } -+ break; -+ } - - return 0; - } - - static int --dp_link_clock_for_mode_clock(int mode_clock) -+dp_link_clock_for_mode_clock(RADEONOutputPrivatePtr radeon_output, -+ int mode_clock) - { - int i; -+ int max_link_bw = radeon_output->dpcd[1]; - -- for (i = 0; i < num_dp_clocks; i++) -- if (dp_clocks[i] > (mode_clock / 10)) -- return (dp_clocks[i % 2]); -+ switch (max_link_bw) { -+ case DP_LINK_BW_1_62: -+ default: -+ 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; -+ break; -+ } - - return 0; - } - -+/* -+ * DIG Encoder/Transmitter Setup -+ * -+ * DCE 3.0/3.1 -+ * - 2 DIG transmitter blocks. UNIPHY (links A and B) and LVTMA. -+ * Supports up to 3 digital outputs -+ * - 2 DIG encoder blocks. -+ * DIG1 can drive UNIPHY link A or link B -+ * DIG2 can drive UNIPHY link B or LVTMA -+ * -+ * DCE 3.2 -+ * - 3 DIG transmitter blocks. UNIPHY0/1/2 (links A and B). -+ * Supports up to 5 digital outputs -+ * - 2 DIG encoder blocks. -+ * DIG1/2 can drive UNIPHY0/1/2 link A or link B -+ * -+ * Routing -+ * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links) -+ * Examples: -+ * crtc0 -> dig2 -> LVTMA links A+B -+ * crtc1 -> dig1 -> UNIPHY0 link B -+ */ - static int - atombios_output_dig_encoder_setup(xf86OutputPtr output, int action) - { -@@ -528,10 +591,17 @@ atombios_output_dig_encoder_setup(xf86OutputPtr output, int action) - } else { - switch (radeon_encoder->encoder_id) { - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: -- index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); -+ /* doesn't really matter which dig encoder we pick as long as it's -+ * not already in use -+ */ -+ if (radeon_output->linkb) -+ index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); -+ else -+ index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); - num = 1; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: -+ /* Only dig2 encoder can drive LVTMA */ - index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); - num = 2; - break; -@@ -569,26 +639,18 @@ atombios_output_dig_encoder_setup(xf86OutputPtr output, int action) - disp_data.ucEncoderMode = atombios_get_encoder_mode(output); - - if (disp_data.ucEncoderMode == ATOM_ENCODER_MODE_DP) { -- if (radeon_output->linkb) -- disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; -- else -- disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; -- -- if (dp_link_clock_for_mode_clock(clock) == 27000) -+ if (dp_link_clock_for_mode_clock(radeon_output, clock) == 27000) - disp_data.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; -- -- disp_data.ucLaneNum = dp_lanes_for_mode_clock(clock); -- } else if (clock > 165000) { -- disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA_B; -+ disp_data.ucLaneNum = dp_lanes_for_mode_clock(radeon_output, clock); -+ } else if (clock > 165000) - disp_data.ucLaneNum = 8; -- } else { -- if (radeon_output->linkb) -- disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; -- else -- disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; -- -+ else - disp_data.ucLaneNum = 4; -- } -+ -+ if (radeon_output->linkb) -+ disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; -+ else -+ disp_data.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; - - data.exec.index = index; - data.exec.dataSpace = (void *)&space; -@@ -610,7 +672,7 @@ union dig_transmitter_control { - }; - - static int --atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action) -+atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action, uint8_t lane_num, uint8_t lane_set) - { - RADEONOutputPrivatePtr radeon_output = output->driver_private; - RADEONInfoPtr info = RADEONPTR(output->scrn); -@@ -648,10 +710,13 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action) - if (IS_DCE32_VARIANT) { - if (action == ATOM_TRANSMITTER_ACTION_INIT) { - disp_data.v2.usInitInfo = radeon_output->connector_object_id; -+ } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { -+ disp_data.v2.asMode.ucLaneSel = lane_num; -+ disp_data.v2.asMode.ucLaneSet = lane_set; - } else { - if (radeon_output->MonType == MT_DP) { - disp_data.v2.usPixelClock = -- cpu_to_le16(dp_link_clock_for_mode_clock(clock)); -+ cpu_to_le16(dp_link_clock_for_mode_clock(radeon_output, clock)); - disp_data.v2.acConfig.fDPConnector = 1; - } else if (clock > 165000) { - disp_data.v2.usPixelClock = cpu_to_le16((clock / 2) / 10); -@@ -663,6 +728,9 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action) - if (dig_block) - disp_data.v2.acConfig.ucEncoderSel = 1; - -+ if (radeon_output->linkb) -+ disp_data.v2.acConfig.ucLinkSel = 1; -+ - switch (radeon_encoder->encoder_id) { - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: - disp_data.v2.acConfig.ucTransmitterSel = 0; -@@ -678,7 +746,9 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action) - break; - } - -- if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) { -+ if (radeon_output->MonType == MT_DP) -+ disp_data.v2.acConfig.fCoherentMode = 1; /* DP requires coherent */ -+ else if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) { - if (radeon_output->coherent_mode) { - disp_data.v2.acConfig.fCoherentMode = 1; - xf86DrvMsg(output->scrn->scrnIndex, X_INFO, "UNIPHY%d transmitter: Coherent Mode enabled\n",disp_data.v2.acConfig.ucTransmitterSel); -@@ -690,10 +760,13 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action) - - if (action == ATOM_TRANSMITTER_ACTION_INIT) { - disp_data.v1.usInitInfo = radeon_output->connector_object_id; -+ } else if (action == ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH) { -+ disp_data.v2.asMode.ucLaneSel = lane_num; -+ disp_data.v2.asMode.ucLaneSet = lane_set; - } else { - if (radeon_output->MonType == MT_DP) - disp_data.v1.usPixelClock = -- cpu_to_le16(dp_link_clock_for_mode_clock(clock)); -+ cpu_to_le16(dp_link_clock_for_mode_clock(radeon_output, clock)); - else if (clock > 165000) - disp_data.v1.usPixelClock = cpu_to_le16((clock / 2) / 10); - else -@@ -702,18 +775,20 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action) - - switch (radeon_encoder->encoder_id) { - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: -- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; -+ /* doesn't really matter which dig encoder we pick as long as it's -+ * not already in use -+ */ -+ if (radeon_output->linkb) -+ disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; -+ else -+ disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; - if (info->IsIGP) { - if (clock > 165000) { -- disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | -- ATOM_TRANSMITTER_CONFIG_LINKA_B); -- - if (radeon_output->igp_lane_info & 0x3) - disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; - else if (radeon_output->igp_lane_info & 0xc) - disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; - } else { -- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; - if (radeon_output->igp_lane_info & 0x1) - disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; - else if (radeon_output->igp_lane_info & 0x2) -@@ -723,39 +798,24 @@ atombios_output_dig_transmitter_setup(xf86OutputPtr output, int action) - else if (radeon_output->igp_lane_info & 0x8) - disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; - } -- } else { -- if (clock > 165000) -- disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | -- ATOM_TRANSMITTER_CONFIG_LINKA_B | -- ATOM_TRANSMITTER_CONFIG_LANE_0_7); -- else { -- /* XXX */ -- if (radeon_output->linkb) -- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3; -- else -- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3; -- } - } - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: -+ /* Only dig2 encoder can drive LVTMA */ - disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; -- if (clock > 165000) -- disp_data.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | -- ATOM_TRANSMITTER_CONFIG_LINKA_B | -- ATOM_TRANSMITTER_CONFIG_LANE_0_7); -- else { -- /* XXX */ -- if (radeon_output->linkb) -- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3; -- else -- disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3; -- } - break; - } -+ if (clock > 165000) -+ disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_8LANE_LINK; -+ if (radeon_output->linkb) -+ disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB; -+ else -+ disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; - -- if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) { -- if (radeon_output->coherent_mode && -- radeon_output->MonType != MT_DP) { -+ if (radeon_output->MonType == MT_DP) -+ disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; /* DP requires coherent */ -+ else if (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT)) { -+ if (radeon_output->coherent_mode) { - disp_data.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; - xf86DrvMsg(output->scrn->scrnIndex, X_INFO, - "DIG%d transmitter: Coherent Mode enabled\n", num); -@@ -1285,8 +1345,12 @@ atombios_output_dpms(xf86OutputPtr output, int mode) - switch (mode) { - case DPMSModeOn: - radeon_encoder->devices |= radeon_output->active_device; -- if (is_dig) -- atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT); -+ if (is_dig) { -+ atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); -+ if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT && radeon_output->MonType == MT_DP) { -+ do_displayport_link_train(output); -+ } -+ } - else { - disp_data.ucAction = ATOM_ENABLE; - data.exec.index = index; -@@ -1310,7 +1374,7 @@ atombios_output_dpms(xf86OutputPtr output, int mode) - radeon_encoder->devices &= ~(radeon_output->active_device); - if (!radeon_encoder->devices) { - if (is_dig) -- atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT); -+ atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); - else { - disp_data.ucAction = ATOM_DISABLE; - data.exec.index = index; -@@ -1418,10 +1482,18 @@ atombios_set_output_crtc_source(xf86OutputPtr output) - crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; - else - crtc_src_param2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; -- } else -- crtc_src_param2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; -+ } else { -+ /* doesn't really matter which dig encoder we pick as long as it's -+ * not already in use -+ */ -+ if (radeon_output->linkb) -+ crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; -+ else -+ crtc_src_param2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; -+ } - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: -+ /* Only dig2 encoder can drive LVTMA */ - crtc_src_param2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; - break; - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: -@@ -1543,14 +1615,14 @@ atombios_output_mode_set(xf86OutputPtr output, - case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: - case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - /* disable encoder and transmitter */ -- atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE); -+ atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - atombios_output_dig_encoder_setup(output, ATOM_DISABLE); - - /* setup and enable the encoder and transmitter */ - atombios_output_dig_encoder_setup(output, ATOM_ENABLE); -- atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_INIT); -- atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP); -- atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE); -+ atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_INIT, 0, 0); -+ atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); -+ atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - break; - case ENCODER_OBJECT_ID_INTERNAL_DDI: - atombios_output_ddia_setup(output, ATOM_ENABLE); -@@ -1686,3 +1758,849 @@ 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) -+{ -+ RADEONInfoPtr info = RADEONPTR(output->scrn); -+ RADEONOutputPrivatePtr radeon_output = output->driver_private; -+ int ret = 0; -+ if (IS_DCE32_VARIANT) { -+ if (radeon_output->dig_block) -+ ret |= ATOM_DP_CONFIG_DIG2_ENCODER; -+ else -+ ret |= ATOM_DP_CONFIG_DIG1_ENCODER; -+ if (radeon_output->linkb) -+ ret |= ATOM_DP_CONFIG_LINK_B; -+ else -+ ret |= ATOM_DP_CONFIG_LINK_A; -+ } else { -+ if (radeon_output->linkb) -+ ret |= ATOM_DP_CONFIG_DIG2_ENCODER | ATOM_DP_CONFIG_LINK_B; -+ else -+ ret |= ATOM_DP_CONFIG_DIG1_ENCODER | ATOM_DP_CONFIG_LINK_A; -+ } -+ return ret; -+} -+ -+Bool -+RADEONProcessAuxCH(xf86OutputPtr output, uint8_t *req_bytes, uint8_t num_bytes, -+ uint8_t *read_byte, uint8_t read_buf_len, uint8_t delay) -+{ -+ RADEONOutputPrivatePtr radeon_output = output->driver_private; -+ RADEONInfoPtr info = RADEONPTR(output->scrn); -+ PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION args; -+ AtomBiosArgRec data; -+ unsigned char *space; -+ unsigned char *base; -+ -+ memset(&args, 0, sizeof(args)); -+ if (info->atomBIOS->fbBase) -+ base = info->FB + info->atomBIOS->fbBase; -+ else if (info->atomBIOS->scratchBase) -+ base = (unsigned char *)info->atomBIOS->scratchBase; -+ else -+ return FALSE; -+ -+ memcpy(base, req_bytes, num_bytes); -+ -+ args.lpAuxRequest = 0; -+ args.lpDataOut = 16; -+ args.ucDataOutLen = 0; -+ args.ucChannelID = radeon_output->ucI2cId; -+ args.ucDelay = delay / 10; /* 10 usec */ -+ -+ data.exec.index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); -+ data.exec.dataSpace = (void *)&space; -+ data.exec.pspace = &args; -+ -+ RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data); -+ if (args.ucReplyStatus) { -+ ErrorF("failed to get auxch %02x%02x %02x %02x %02x\n", -+ req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3],args.ucReplyStatus); -+ return FALSE; -+ } -+ if (args.ucDataOutLen && read_byte && read_buf_len) { -+ if (read_buf_len < args.ucDataOutLen) { -+ ErrorF("%s: Buffer too small for return answer %d %d\n", __func__, read_buf_len, args.ucDataOutLen); -+ return FALSE; -+ } -+ { -+ int len = read_buf_len < args.ucDataOutLen ? read_buf_len : args.ucDataOutLen; -+ memcpy(read_byte, base+16, len); -+ } -+ } -+ return TRUE; -+} -+ -+static int -+RADEONDPEncoderService(xf86OutputPtr output, int action, uint8_t ucconfig, uint8_t lane_num) -+{ -+ RADEONInfoPtr info = RADEONPTR(output->scrn); -+ DP_ENCODER_SERVICE_PARAMETERS args; -+ AtomBiosArgRec data; -+ unsigned char *space; -+ -+ memset(&args, 0, sizeof(args)); -+ -+ args.ucLinkClock = 0; -+ args.ucConfig = ucconfig; -+ args.ucAction = action; -+ args.ucLaneNum = lane_num; -+ args.ucStatus = 0; -+ -+ data.exec.index = GetIndexIntoMasterTable(COMMAND, DPEncoderService); -+ data.exec.dataSpace = (void *)&space; -+ data.exec.pspace = &args; -+ -+ RHDAtomBiosFunc(info->atomBIOS->scrnIndex, info->atomBIOS, ATOMBIOS_EXEC, &data); -+ -+ ErrorF("%s: %d\n", __func__, args.ucStatus); -+ return args.ucStatus; -+} -+ -+int RADEON_DP_GetSinkType(xf86OutputPtr output) -+{ -+ RADEONOutputPrivatePtr radeon_output = output->driver_private; -+ -+ return RADEONDPEncoderService(output, ATOM_DP_ACTION_GET_SINK_TYPE, radeon_output->ucI2cId, 0); -+} -+ -+static Bool atom_dp_aux_native_write(xf86OutputPtr output, uint16_t address, -+ uint8_t send_bytes, uint8_t *send) -+{ -+ uint8_t msg[20]; -+ uint8_t msg_len, dp_msg_len; -+ int ret; -+ -+ dp_msg_len = 4; -+ msg[0] = address; -+ msg[1] = address >> 8; -+ msg[2] = AUX_NATIVE_WRITE << 4; -+ dp_msg_len += send_bytes; -+ msg[3] = (dp_msg_len << 4)| (send_bytes - 1); -+ -+ if (0) -+ ErrorF("writing %02x %02x %02x, %d, %d\n", msg[0], msg[1], msg[3], send_bytes, dp_msg_len); -+ if (send_bytes > 16) -+ return FALSE; -+ -+ memcpy(&msg[4], send, send_bytes); -+ msg_len = 4 + send_bytes; -+ ret = RADEONProcessAuxCH(output, msg, msg_len, NULL, 0, 0); -+ return ret; -+} -+ -+static Bool atom_dp_aux_native_read(xf86OutputPtr output, uint16_t address, -+ uint8_t delay, -+ uint8_t expected_bytes, uint8_t *read_p) -+{ -+ uint8_t msg[20]; -+ uint8_t msg_len, dp_msg_len; -+ int ret; -+ -+ msg_len = 4; -+ dp_msg_len = 4; -+ msg[0] = address; -+ msg[1] = address >> 8; -+ msg[2] = AUX_NATIVE_READ << 4; -+ msg[3] = (dp_msg_len) << 4; -+ msg[3] |= expected_bytes - 1; -+ -+ if (0) -+ ErrorF("reading %02x %02x %02x, %d, %d\n", msg[0], msg[1], msg[3], expected_bytes, dp_msg_len); -+ ret = RADEONProcessAuxCH(output, msg, msg_len, read_p, expected_bytes, delay); -+ return ret; -+} -+ -+/* fill out the DPCD structure */ -+void RADEON_DP_GetDPCD(xf86OutputPtr output) -+{ -+ RADEONOutputPrivatePtr radeon_output = output->driver_private; -+ uint8_t msg[25]; -+ int ret; -+ -+ ret = atom_dp_aux_native_read(output, DP_DPCD_REV, 0, 8, msg); -+ if (ret) { -+ memcpy(radeon_output->dpcd, msg, 8); -+ if (0) { -+ int i; -+ ErrorF("DPCD: "); -+ for (i = 0; i < 8; i++) -+ ErrorF("%02x ", radeon_output->dpcd[i]); -+ ErrorF("\n"); -+ } -+ ret = atom_dp_aux_native_read(output, DP_LINK_BW_SET, 0, 2, msg); -+ if (0) { -+ ErrorF("0x200: %02x %02x\n", msg[0], msg[1]); -+ } -+ return; -+ } -+ radeon_output->dpcd[0] = 0; -+ return; -+} -+ -+ -+enum dp_aux_i2c_mode { -+ dp_aux_i2c_start, -+ dp_aux_i2c_write, -+ dp_aux_i2c_read, -+ dp_aux_i2c_stop, -+}; -+ -+ -+static Bool atom_dp_aux_i2c_transaction(xf86OutputPtr output, uint16_t address, -+ enum dp_aux_i2c_mode mode, -+ uint8_t write_byte, uint8_t *read_byte) -+{ -+ uint8_t msg[8], msg_len, dp_msg_len; -+ int ret; -+ int auxch_cmd = 0; -+ -+ memset(msg, 0, 8); -+ -+ if (mode != dp_aux_i2c_stop) -+ auxch_cmd = AUX_I2C_MOT; -+ -+ if (address & 1) -+ auxch_cmd |= AUX_I2C_READ; -+ else -+ auxch_cmd |= AUX_I2C_WRITE; -+ -+ msg[2] = auxch_cmd << 4; -+ -+ msg[4] = 0; -+ msg[0] = (address >> 1); -+ msg[1] = (address >> 9); -+ -+ msg_len = 4; -+ dp_msg_len = 3; -+ switch (mode) { -+ case dp_aux_i2c_read: -+ /* bottom bits is byte count - 1 so for 1 byte == 0 */ -+ dp_msg_len += 1; -+ break; -+ case dp_aux_i2c_write: -+ dp_msg_len += 2; -+ msg[4] = write_byte; -+ msg_len++; -+ break; -+ default: -+ break; -+ } -+ msg[3] = dp_msg_len << 4; -+ -+ ret = RADEONProcessAuxCH(output, msg, msg_len, read_byte, 1, 0); -+ return ret; -+} -+ -+static Bool -+atom_dp_i2c_address(I2CDevPtr dev, I2CSlaveAddr addr) -+{ -+ I2CBusPtr bus = dev->pI2CBus; -+ xf86OutputPtr output = bus->DriverPrivate.ptr; -+ RADEONOutputPrivatePtr radeon_output = output->driver_private; -+ int ret; -+ -+ radeon_output->dp_i2c_addr = addr; -+ radeon_output->dp_i2c_running = TRUE; -+ -+ /* call i2c start */ -+ ret = atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr, -+ dp_aux_i2c_start, 0, NULL); -+ -+ return ret; -+} -+static Bool -+atom_dp_i2c_start(I2CBusPtr bus, int timeout) -+{ -+ ErrorF("%s\n", __func__); -+ return TRUE; -+} -+ -+static void -+atom_dp_i2c_stop(I2CDevPtr dev) -+{ -+ I2CBusPtr bus = dev->pI2CBus; -+ xf86OutputPtr output = bus->DriverPrivate.ptr; -+ RADEONOutputPrivatePtr radeon_output = output->driver_private; -+ -+ if (radeon_output->dp_i2c_running) -+ atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr, -+ dp_aux_i2c_stop, 0, NULL); -+ radeon_output->dp_i2c_running = FALSE; -+} -+ -+ -+static Bool -+atom_dp_i2c_put_byte(I2CDevPtr dev, I2CByte byte) -+{ -+ I2CBusPtr bus = dev->pI2CBus; -+ xf86OutputPtr output = bus->DriverPrivate.ptr; -+ RADEONOutputPrivatePtr radeon_output = output->driver_private; -+ Bool ret; -+ -+ ret = (atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr, -+ dp_aux_i2c_write, byte, NULL)); -+ return ret; -+} -+ -+static Bool -+atom_dp_i2c_get_byte(I2CDevPtr dev, I2CByte *byte_ret, Bool last) -+{ -+ I2CBusPtr bus = dev->pI2CBus; -+ xf86OutputPtr output = bus->DriverPrivate.ptr; -+ RADEONOutputPrivatePtr radeon_output = output->driver_private; -+ Bool ret; -+ -+ ret = (atom_dp_aux_i2c_transaction(output, radeon_output->dp_i2c_addr, -+ dp_aux_i2c_read, 0, byte_ret)); -+ return ret; -+} -+ -+Bool -+RADEON_DP_I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, char *name, xf86OutputPtr output) -+{ -+ I2CBusPtr pI2CBus; -+ -+ pI2CBus = xf86CreateI2CBusRec(); -+ if (!pI2CBus) return FALSE; -+ -+ pI2CBus->BusName = name; -+ pI2CBus->scrnIndex = pScrn->scrnIndex; -+ pI2CBus->I2CGetByte = atom_dp_i2c_get_byte; -+ pI2CBus->I2CPutByte = atom_dp_i2c_put_byte; -+ pI2CBus->I2CAddress = atom_dp_i2c_address; -+ pI2CBus->I2CStart = atom_dp_i2c_start; -+ pI2CBus->I2CStop = atom_dp_i2c_stop; -+ pI2CBus->DriverPrivate.ptr = output; -+ -+ /* -+ * These were set incorrectly in the server pre-1.3, Having -+ * duplicate settings is sub-optimal, but this lets the driver -+ * work with older servers -+ */ -+ pI2CBus->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */ -+ pI2CBus->StartTimeout = 550; -+ pI2CBus->BitTimeout = 40; -+ pI2CBus->AcknTimeout = 40; -+ pI2CBus->RiseFallTime = 20; -+ -+ if (!xf86I2CBusInit(pI2CBus)) -+ return FALSE; -+ -+ *bus_ptr = pI2CBus; -+ return TRUE; -+} -+ -+ -+static uint8_t dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE], int r) -+{ -+ return link_status[r - DP_LANE0_1_STATUS]; -+} -+ -+static uint8_t dp_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane) -+{ -+ int i = DP_LANE0_1_STATUS + (lane >> 1); -+ int s = (lane & 1) * 4; -+ uint8_t l = dp_link_status(link_status, i); -+ return (l >> s) & 0xf; -+} -+ -+static Bool dp_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) -+{ -+ int lane; -+ -+ uint8_t lane_status; -+ -+ for (lane = 0; lane < lane_count; lane++) { -+ lane_status = dp_get_lane_status(link_status, lane); -+ if ((lane_status & DP_LANE_CR_DONE) == 0) -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+ -+/* Check to see if channel eq is done on all channels */ -+#define CHANNEL_EQ_BITS (DP_LANE_CR_DONE|\ -+ DP_LANE_CHANNEL_EQ_DONE|\ -+ DP_LANE_SYMBOL_LOCKED) -+static Bool -+dp_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) -+{ -+ uint8_t lane_align; -+ uint8_t lane_status; -+ int lane; -+ -+ lane_align = dp_link_status(link_status, -+ DP_LANE_ALIGN_STATUS_UPDATED); -+ if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) -+ return FALSE; -+ for (lane = 0; lane < lane_count; lane++) { -+ lane_status = dp_get_lane_status(link_status, lane); -+ if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS) -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+/* -+ * Fetch AUX CH registers 0x202 - 0x207 which contain -+ * link status information -+ */ -+static Bool -+atom_dp_get_link_status(xf86OutputPtr output, -+ uint8_t link_status[DP_LINK_STATUS_SIZE]) -+{ -+ ScrnInfoPtr pScrn = output->scrn; -+ int ret; -+ ret = atom_dp_aux_native_read(output, DP_LANE0_1_STATUS, 100, -+ DP_LINK_STATUS_SIZE, link_status); -+ if (!ret) { -+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "dp link status failed\n"); -+ return FALSE; -+ } -+ ErrorF("link status %02x %02x %02x %02x %02x %02x\n", link_status[0], link_status[1], -+ link_status[2], link_status[3], link_status[4], link_status[5]); -+ -+ return TRUE; -+} -+ -+static uint8_t -+dp_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE], -+ int lane) -+ -+{ -+ int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); -+ int s = ((lane & 1) ? -+ DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : -+ DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT); -+ uint8_t l = dp_link_status(link_status, i); -+ -+ return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; -+} -+ -+static uint8_t -+dp_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE], -+ int lane) -+{ -+ int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); -+ int s = ((lane & 1) ? -+ DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT : -+ DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT); -+ uint8_t l = dp_link_status(link_status, i); -+ -+ return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; -+} -+ -+static char *voltage_names[] = { -+ "0.4V", "0.6V", "0.8V", "1.2V" -+}; -+static char *pre_emph_names[] = { -+ "0dB", "3.5dB", "6dB", "9.5dB" -+}; -+ -+/* -+ * These are source-specific values; current Intel hardware supports -+ * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB -+ */ -+#define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200 -+ -+static uint8_t -+dp_pre_emphasis_max(uint8_t voltage_swing) -+{ -+ switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { -+ case DP_TRAIN_VOLTAGE_SWING_400: -+ return DP_TRAIN_PRE_EMPHASIS_6; -+ case DP_TRAIN_VOLTAGE_SWING_600: -+ return DP_TRAIN_PRE_EMPHASIS_6; -+ case DP_TRAIN_VOLTAGE_SWING_800: -+ return DP_TRAIN_PRE_EMPHASIS_3_5; -+ case DP_TRAIN_VOLTAGE_SWING_1200: -+ default: -+ return DP_TRAIN_PRE_EMPHASIS_0; -+ } -+} -+ -+static void dp_set_training(xf86OutputPtr output, uint8_t training) -+{ -+ atom_dp_aux_native_write(output, DP_TRAINING_PATTERN_SET, 1, &training); -+} -+ -+static void dp_set_power(xf86OutputPtr output, uint8_t power_state) -+{ -+ RADEONOutputPrivatePtr radeon_output = output->driver_private; -+ -+ if (radeon_output->dpcd[0] >= 0x11) { -+ atom_dp_aux_native_write(output, 0x600, 1, &power_state); -+ } -+} -+ -+static void -+dp_get_adjust_train(xf86OutputPtr output, -+ uint8_t link_status[DP_LINK_STATUS_SIZE], -+ int lane_count, -+ uint8_t train_set[4]) -+{ -+ ScrnInfoPtr pScrn = output->scrn; -+ uint8_t v = 0; -+ uint8_t p = 0; -+ int lane; -+ -+ for (lane = 0; lane < lane_count; lane++) { -+ uint8_t this_v = dp_get_adjust_request_voltage(link_status, lane); -+ uint8_t this_p = dp_get_adjust_request_pre_emphasis(link_status, lane); -+ -+ if (0) { -+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, -+ "requested signal parameters: lane %d voltage %s pre_emph %s\n", -+ lane, -+ voltage_names[this_v >> DP_TRAIN_VOLTAGE_SWING_SHIFT], -+ pre_emph_names[this_p >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); -+ } -+ if (this_v > v) -+ v = this_v; -+ if (this_p > p) -+ p = this_p; -+ } -+ -+ if (v >= DP_VOLTAGE_MAX) -+ v = DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED; -+ -+ if (p >= dp_pre_emphasis_max(v)) -+ p = dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; -+ -+ if (0) { -+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, -+ "using signal parameters: voltage %s pre_emph %s\n", -+ voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK) >> DP_TRAIN_VOLTAGE_SWING_SHIFT], -+ pre_emph_names[(p & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); -+ } -+ for (lane = 0; lane < 4; lane++) -+ train_set[lane] = v | p; -+} -+ -+static int radeon_dp_max_lane_count(xf86OutputPtr output) -+{ -+ RADEONOutputPrivatePtr radeon_output = output->driver_private; -+ int max_lane_count = 4; -+ -+ if (radeon_output->dpcd[0] >= 0x11) { -+ max_lane_count = radeon_output->dpcd[2] & 0x1f; -+ switch(max_lane_count) { -+ case 1: case 2: case 4: -+ break; -+ default: -+ max_lane_count = 4; -+ } -+ } -+ 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; -+} -+ -+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 = 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; -+} -+ -+static void dp_update_dpvs_emph(xf86OutputPtr output, uint8_t train_set[4]) -+{ -+ RADEONOutputPrivatePtr radeon_output = output->driver_private; -+ int i; -+ for (i = 0; i < radeon_output->dp_lane_count; i++) -+ atombios_output_dig_transmitter_setup(output, ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH, i, train_set[i]); -+ -+ atom_dp_aux_native_write(output, DP_TRAINING_LANE0_SET, radeon_output->dp_lane_count, train_set); -+} -+ -+static void do_displayport_link_train(xf86OutputPtr output) -+{ -+ ScrnInfoPtr pScrn = output->scrn; -+ RADEONOutputPrivatePtr radeon_output = output->driver_private; -+ int enc_id = atom_dp_get_encoder_id(output); -+ Bool clock_recovery; -+ uint8_t link_status[DP_LINK_STATUS_SIZE]; -+ uint8_t tries, voltage, ss_cntl; -+ uint8_t train_set[4]; -+ int i; -+ Bool channel_eq; -+ uint8_t dp_link_configuration[DP_LINK_CONFIGURATION_SIZE]; -+ -+ memset(train_set, 0, 4); -+ -+ /* set up link configuration */ -+ memset(dp_link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); -+ -+ if (radeon_output->dp_clock == 270000) -+ dp_link_configuration[0] = DP_LINK_BW_2_7; -+ else -+ dp_link_configuration[0] = DP_LINK_BW_1_62; -+ dp_link_configuration[1] = radeon_output->dp_lane_count; -+ -+ if (radeon_output->dpcd[0] >= 0x11) { -+ dp_link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; -+ } -+ -+ /* power up to D0 */ -+ dp_set_power(output, DP_SET_POWER_D0); -+ -+ /* disable training */ -+ dp_set_training(output, DP_TRAINING_PATTERN_DISABLE); -+ -+ /* write link rate / num / eh framing */ -+ atom_dp_aux_native_write(output, DP_LINK_BW_SET, 2, -+ dp_link_configuration); -+ -+ /* write ss cntl */ -+ ss_cntl = 0; -+ atom_dp_aux_native_write(output, DP_DOWNSPREAD_CTRL, 1, -+ &ss_cntl); -+ -+ /* start local training start */ -+ RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_START, enc_id, 0); -+ RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, enc_id, 0); -+ -+ usleep(400); -+ dp_set_training(output, DP_TRAINING_PATTERN_1); -+ dp_update_dpvs_emph(output, train_set); -+ -+ /* loop around doing configuration reads and DP encoder setups */ -+ clock_recovery = FALSE; -+ tries = 0; -+ voltage = 0xff; -+ for (;;) { -+ usleep(100); -+ if (!atom_dp_get_link_status(output, link_status)) -+ break; -+ -+ if (dp_clock_recovery_ok(link_status, radeon_output->dp_lane_count)) { -+ clock_recovery = TRUE; -+ break; -+ } -+ -+ for (i = 0; i < radeon_output->dp_lane_count; i++) -+ if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) -+ break; -+ if (i == radeon_output->dp_lane_count) { -+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, -+ "clock recovery reached max voltage\n"); -+ break; -+ } -+ -+ /* Check to see if we've tried the same voltage 5 times */ -+ if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { -+ ++tries; -+ if (tries == 5) { -+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, -+ "clock recovery tried 5 times\n"); -+ break; -+ } -+ } else -+ tries = 0; -+ -+ voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; -+ -+ dp_get_adjust_train(output, link_status, radeon_output->dp_lane_count, train_set); -+ dp_update_dpvs_emph(output, train_set); -+ -+ } -+ -+ if (!clock_recovery) -+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, -+ "clock recovery failed\n"); -+ -+ /* channel equalization */ -+ tries = 0; -+ channel_eq = FALSE; -+ dp_set_training(output, DP_TRAINING_PATTERN_2); -+ RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, enc_id, 1); -+ -+ for (;;) { -+ usleep(400); -+ if (!atom_dp_get_link_status(output, link_status)) -+ break; -+ -+ if (dp_channel_eq_ok(link_status, radeon_output->dp_lane_count)) { -+ channel_eq = TRUE; -+ break; -+ } -+ -+ /* Try 5 times */ -+ if (tries > 5) { -+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, -+ "channel eq failed: 5 tries\n"); -+ break; -+ } -+ -+ /* Compute new train_set as requested by target */ -+ dp_get_adjust_train(output, link_status, radeon_output->dp_lane_count, train_set); -+ dp_update_dpvs_emph(output, train_set); -+ -+ ++tries; -+ } -+ -+ if (!channel_eq) -+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, -+ "channel eq failed\n"); -+ -+ dp_set_training(output, DP_TRAINING_PATTERN_DISABLE); -+ RADEONDPEncoderService(output, ATOM_DP_ACTION_TRAINING_COMPLETE, enc_id, 0); -+ -+} -+ -diff --git a/src/radeon.h b/src/radeon.h -index 1b8ae3c..c9f388a 100644 ---- a/src/radeon.h -+++ b/src/radeon.h -@@ -1218,6 +1218,10 @@ void RADEONFreeRec(ScrnInfoPtr pScrn); - Bool RADEONPreInitVisual(ScrnInfoPtr pScrn); - Bool RADEONPreInitWeight(ScrnInfoPtr pScrn); - -+extern Bool RADEON_DP_I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, -+ char *name, xf86OutputPtr output); -+extern void RADEON_DP_GetDPCD(xf86OutputPtr output); -+extern int RADEON_DP_GetSinkType(xf86OutputPtr output); - - /* radeon_pm.c */ - extern void RADEONPMInit(ScrnInfoPtr pScrn); -@@ -1274,6 +1278,7 @@ extern void RADEONSetOutputType(ScrnInfoPtr pScrn, - extern Bool RADEONSetupConnectors(ScrnInfoPtr pScrn); - extern Bool RADEONI2CDoLock(xf86OutputPtr output, I2CBusPtr b, Bool lock_state); - -+extern Bool radeon_dp_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, DisplayModePtr adjusted_mode); - - /* radeon_tv.c */ - extern void RADEONSaveTVRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save); -diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c -index 462c5ef..72fbe21 100644 ---- a/src/radeon_atombios.c -+++ b/src/radeon_atombios.c -@@ -1581,8 +1581,10 @@ rhdAtomParseI2CRecord(ScrnInfoPtr pScrn, atomBiosHandlePtr handle, - ATOM_I2C_RECORD *Record, int i) - { - RADEONInfoPtr info = RADEONPTR (pScrn); -+ uint8_t *temp = &Record->sucI2cId; - - info->BiosConnector[i].i2c_line_mux = Record->sucI2cId.bfI2C_LineMux; -+ info->BiosConnector[i].ucI2cId = *temp; - return RADEONLookupGPIOLineForDDC(pScrn, Record->sucI2cId.bfI2C_LineMux); - } - -diff --git a/src/radeon_output.c b/src/radeon_output.c -index a2733a7..107955d 100644 ---- a/src/radeon_output.c -+++ b/src/radeon_output.c -@@ -301,10 +301,13 @@ radeon_ddc_connected(xf86OutputPtr output) - RADEONMonitorType MonType = MT_NONE; - xf86MonPtr MonInfo = NULL; - RADEONOutputPrivatePtr radeon_output = output->driver_private; -+ int ret; - - if (radeon_output->custom_edid) { - MonInfo = xnfcalloc(sizeof(xf86Monitor), 1); - *MonInfo = *radeon_output->custom_mon; -+ } else if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT) { -+ MonInfo = xf86OutputGetEDID(output, radeon_output->dp_pI2CBus); - } else if (radeon_output->pI2CBus) { - if (info->get_hardcoded_edid_from_bios) - MonInfo = RADEONGetHardCodedEDIDFromBIOS(output); -@@ -364,7 +367,13 @@ radeon_ddc_connected(xf86OutputPtr output) - * XXX wrong. need to infer based on whether we got DDC from I2C - * or AUXCH. - */ -- MonType = MT_DFP; -+ ret = RADEON_DP_GetSinkType(output); -+ -+ if (ret == CONNECTOR_OBJECT_ID_DISPLAYPORT) { -+ MonType = MT_DP; -+ RADEON_DP_GetDPCD(output); -+ } else -+ MonType = MT_DFP; - break; - case CONNECTOR_HDMI_TYPE_B: - case CONNECTOR_DVI_I: -@@ -660,6 +669,9 @@ radeon_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, - } - } - -+ if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT && radeon_output->MonType == MT_DP) { -+ radeon_dp_mode_fixup(output, mode, adjusted_mode); -+ } - return TRUE; - } - -@@ -2070,6 +2082,13 @@ void RADEONInitConnector(xf86OutputPtr output) - if (radeon_output->devices & (ATOM_DEVICE_DFP_SUPPORT)) - radeon_output->coherent_mode = TRUE; - -+ if (radeon_output->ConnectorType == CONNECTOR_DISPLAY_PORT) { -+ strcpy(radeon_output->dp_bus_name, output->name); -+ strcat(radeon_output->dp_bus_name, "-DP"); -+ RADEON_DP_I2CInit(pScrn, &radeon_output->dp_pI2CBus, radeon_output->dp_bus_name, output); -+ RADEON_DP_GetSinkType(output); -+ } -+ - if (radeon_output->ddc_i2c.valid) - RADEONI2CInit(pScrn, &radeon_output->pI2CBus, output->name, &radeon_output->ddc_i2c); - -@@ -2909,6 +2928,7 @@ Bool RADEONSetupConnectors(ScrnInfoPtr pScrn) - radeon_output->linkb = info->BiosConnector[i].linkb; - radeon_output->connector_id = info->BiosConnector[i].connector_object; - radeon_output->connector_object_id = info->BiosConnector[i].connector_object_id; -+ radeon_output->ucI2cId = info->BiosConnector[i].ucI2cId; - - /* Technically HDMI-B is a glorfied DL DVI so the bios is correct, - * but this can be confusing to users when it comes to output names, -diff --git a/src/radeon_probe.h b/src/radeon_probe.h -index 12e73ef..46bd1f5 100644 ---- a/src/radeon_probe.h -+++ b/src/radeon_probe.h -@@ -240,6 +240,7 @@ typedef struct { - Bool linkb; - uint16_t connector_object; - uint16_t connector_object_id; -+ uint8_t ucI2cId; - } RADEONBIOSConnector; - - typedef struct _RADEONOutputPrivateRec { -@@ -284,6 +285,17 @@ typedef struct _RADEONOutputPrivateRec { - int dig_block; - - int pixel_clock; -+ -+ /* DP - aux bus*/ -+ I2CBusPtr dp_pI2CBus; -+ uint8_t ucI2cId; -+ char dp_bus_name[20]; -+ uint32_t dp_i2c_addr; -+ Bool dp_i2c_running; -+ /* DP - general config */ -+ uint8_t dpcd[8]; -+ int dp_lane_count; -+ int dp_clock; - } RADEONOutputPrivateRec, *RADEONOutputPrivatePtr; - - struct avivo_pll_state { diff --git a/sources b/sources index e1ff017..94821dc 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 189be8ab60025bf81f8841ab53175665 radeon-rlc-firmware-1.tar.bz2 -84236a984ca7d78c7a33655e54c26e4c xf86-video-ati-20091221.tar.xz +8f52f5f8fa88f3e5b6db9fc744b82502 xf86-video-ati-20100125.tar.xz diff --git a/xorg-x11-drv-ati.spec b/xorg-x11-drv-ati.spec index de6ae46..9713a3d 100644 --- a/xorg-x11-drv-ati.spec +++ b/xorg-x11-drv-ati.spec @@ -1,13 +1,13 @@ %define tarball xf86-video-ati %define moduledir %(pkg-config xorg-server --variable=moduledir ) %define driverdir %{moduledir}/drivers -%define gitdate 20091221 -%define gitversion 4b05c47ac +%define gitdate 20100125 +%define gitversion ba99a82ce Summary: Xorg X11 ati video driver Name: xorg-x11-drv-ati Version: 6.13.0 -Release: 0.19.%{gitdate}git%{gitversion}%{?dist} +Release: 0.20.%{gitdate}git%{gitversion}%{?dist} URL: http://www.x.org License: MIT Group: User Interface/X Hardware Support @@ -95,6 +95,9 @@ rm -rf $RPM_BUILD_ROOT /lib/firmware/radeon/*.bin %changelog +* Mon Jan 25 2010 Dave Airlie 6.13.0-0.20.20100125gitba99a82ce +- rebase to upstream - fix es1000 bug with 64MB VRAM + * Thu Jan 21 2010 Peter Hutterer - 6.13.0-0.19.20091221git4b05c47ac - Rebuild for server 1.8