aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2009-11-23 18:40:40 -0500
committerDave Airlie <airlied@redhat.com>2009-12-08 10:22:43 +1000
commitf92a8b6758bdc0f277c4f42aa7d736a205ac9ded (patch)
tree3feb11b2cb76229767c42a4a3d34d6e525b73364
parent4143e919ea999c9356ae4f71b5a3a80e075290d5 (diff)
drm/radeon/kms: handle dp sinks in atom encoder/transmitter tables
Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/radeon/atombios_dp.c69
-rw-r--r--drivers/gpu/drm/radeon/radeon_encoders.c41
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h2
3 files changed, 100 insertions, 12 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index e761fefaacb..76eb5c8a701 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -33,6 +33,75 @@
#define DP_LINK_STATUS_SIZE 6
+/* move these to drm_dp_helper.c/h */
+
+static const int dp_clocks[] = {
+ 54000, // 1 lane, 1.62 Ghz
+ 90000, // 1 lane, 2.70 Ghz
+ 108000, // 2 lane, 1.62 Ghz
+ 180000, // 2 lane, 2.70 Ghz
+ 216000, // 4 lane, 1.62 Ghz
+ 360000, // 4 lane, 2.70 Ghz
+};
+
+static const int num_dp_clocks = sizeof(dp_clocks) / sizeof(int);
+
+int dp_lanes_for_mode_clock(int max_link_bw, int mode_clock)
+{
+ int i;
+
+ 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) {
+ 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) {
+ if (i < 2)
+ return 1;
+ else if (i < 4)
+ return 2;
+ else
+ return 4;
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
+
+int dp_link_clock_for_mode_clock(int max_link_bw, int mode_clock)
+{
+ int i;
+
+ switch (max_link_bw) {
+ case DP_LINK_BW_1_62:
+ default:
+ return 162000;
+ break;
+ case DP_LINK_BW_2_7:
+ for (i = 0; i < num_dp_clocks; i++) {
+ if (dp_clocks[i] > mode_clock)
+ return (i % 2) ? 270000 : 162000;
+ }
+ }
+
+ return 0;
+}
+
bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes,
int num_bytes, u8 *read_byte,
u8 read_buf_len, u8 delay)
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
index b4e7abadbfb..8f3d67b6032 100644
--- a/drivers/gpu/drm/radeon/radeon_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_encoders.c
@@ -554,6 +554,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
{
struct drm_connector *connector;
struct radeon_connector *radeon_connector;
+ struct radeon_connector_atom_dig *radeon_dig_connector;
connector = radeon_get_connector_for_encoder(encoder);
if (!connector)
@@ -583,10 +584,10 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
return ATOM_ENCODER_MODE_LVDS;
break;
case DRM_MODE_CONNECTOR_DisplayPort:
- /*if (radeon_output->MonType == MT_DP)
- return ATOM_ENCODER_MODE_DP;
- else*/
- if (drm_detect_hdmi_monitor(radeon_connector->edid))
+ radeon_dig_connector = radeon_connector->con_priv;
+ if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT)
+ return ATOM_ENCODER_MODE_DP;
+ else if (drm_detect_hdmi_monitor(radeon_connector->edid))
return ATOM_ENCODER_MODE_HDMI;
else
return ATOM_ENCODER_MODE_DVI;
@@ -715,7 +716,15 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
}
}
- if (radeon_encoder->pixel_clock > 165000)
+ args.ucEncoderMode = atombios_get_encoder_mode(encoder);
+
+ if (args.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
+ if (dp_link_clock_for_mode_clock(dig_connector->dpcd[1],
+ radeon_encoder->pixel_clock) == 270000)
+ args.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
+ args.ucLaneNum = dp_lanes_for_mode_clock(dig_connector->dpcd[1],
+ radeon_encoder->pixel_clock);
+ } else if (radeon_encoder->pixel_clock > 165000)
args.ucLaneNum = 8;
else
args.ucLaneNum = 4;
@@ -725,8 +734,6 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
else
args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
- args.ucEncoderMode = atombios_get_encoder_mode(encoder);
-
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
}
@@ -749,6 +756,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
struct drm_connector *connector;
struct radeon_connector *radeon_connector;
struct radeon_connector_atom_dig *dig_connector;
+ bool is_dp = false;
connector = radeon_get_connector_for_encoder(encoder);
if (!connector)
@@ -766,6 +774,9 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
dig_connector = radeon_connector->con_priv;
+ if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP)
+ is_dp = true;
+
memset(&args, 0, sizeof(args));
if (ASIC_IS_DCE32(rdev))
@@ -790,14 +801,16 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
args.v1.asMode.ucLaneSel = lane_num;
args.v1.asMode.ucLaneSet = lane_set;
} else {
- if (radeon_encoder->pixel_clock > 165000)
+ if (is_dp)
+ args.v1.usPixelClock =
+ cpu_to_le16(dp_link_clock_for_mode_clock(dig_connector->dpcd[1],
+ radeon_encoder->pixel_clock) / 10);
+ else if (radeon_encoder->pixel_clock > 165000)
args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
else
args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
}
if (ASIC_IS_DCE32(rdev)) {
- if (radeon_encoder->pixel_clock > 165000)
- args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
if (dig->dig_block)
args.v2.acConfig.ucEncoderSel = 1;
if (dig_connector->linkb)
@@ -818,7 +831,9 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
break;
}
- if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+ if (is_dp)
+ args.v2.acConfig.fCoherentMode = 1;
+ else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
if (dig->coherent_mode)
args.v2.acConfig.fCoherentMode = 1;
}
@@ -866,7 +881,9 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
else
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA;
- if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+ if (is_dp)
+ args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
+ else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
if (dig->coherent_mode)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
}
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 338d0af1851..b516401c151 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -366,6 +366,8 @@ struct radeon_framebuffer {
struct drm_gem_object *obj;
};
+extern int dp_lanes_for_mode_clock(int max_link_bw, int mode_clock);
+extern int dp_link_clock_for_mode_clock(int max_link_bw, int mode_clock);
extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
extern void radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,