Commit f92a8b67 authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie

drm/radeon/kms: handle dp sinks in atom encoder/transmitter tables

Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 4143e919
...@@ -33,6 +33,75 @@ ...@@ -33,6 +33,75 @@
#define DP_LINK_STATUS_SIZE 6 #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, bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes,
int num_bytes, u8 *read_byte, int num_bytes, u8 *read_byte,
u8 read_buf_len, u8 delay) u8 read_buf_len, u8 delay)
......
...@@ -554,6 +554,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) ...@@ -554,6 +554,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
{ {
struct drm_connector *connector; struct drm_connector *connector;
struct radeon_connector *radeon_connector; struct radeon_connector *radeon_connector;
struct radeon_connector_atom_dig *radeon_dig_connector;
connector = radeon_get_connector_for_encoder(encoder); connector = radeon_get_connector_for_encoder(encoder);
if (!connector) if (!connector)
...@@ -583,10 +584,10 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) ...@@ -583,10 +584,10 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
return ATOM_ENCODER_MODE_LVDS; return ATOM_ENCODER_MODE_LVDS;
break; break;
case DRM_MODE_CONNECTOR_DisplayPort: case DRM_MODE_CONNECTOR_DisplayPort:
/*if (radeon_output->MonType == MT_DP) radeon_dig_connector = radeon_connector->con_priv;
return ATOM_ENCODER_MODE_DP; if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT)
else*/ return ATOM_ENCODER_MODE_DP;
if (drm_detect_hdmi_monitor(radeon_connector->edid)) else if (drm_detect_hdmi_monitor(radeon_connector->edid))
return ATOM_ENCODER_MODE_HDMI; return ATOM_ENCODER_MODE_HDMI;
else else
return ATOM_ENCODER_MODE_DVI; return ATOM_ENCODER_MODE_DVI;
...@@ -715,7 +716,15 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) ...@@ -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; args.ucLaneNum = 8;
else else
args.ucLaneNum = 4; args.ucLaneNum = 4;
...@@ -725,8 +734,6 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) ...@@ -725,8 +734,6 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
else else
args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; 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); 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 ...@@ -749,6 +756,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
struct drm_connector *connector; struct drm_connector *connector;
struct radeon_connector *radeon_connector; struct radeon_connector *radeon_connector;
struct radeon_connector_atom_dig *dig_connector; struct radeon_connector_atom_dig *dig_connector;
bool is_dp = false;
connector = radeon_get_connector_for_encoder(encoder); connector = radeon_get_connector_for_encoder(encoder);
if (!connector) if (!connector)
...@@ -766,6 +774,9 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t ...@@ -766,6 +774,9 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
dig_connector = radeon_connector->con_priv; dig_connector = radeon_connector->con_priv;
if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP)
is_dp = true;
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
if (ASIC_IS_DCE32(rdev)) if (ASIC_IS_DCE32(rdev))
...@@ -790,14 +801,16 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t ...@@ -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.ucLaneSel = lane_num;
args.v1.asMode.ucLaneSet = lane_set; args.v1.asMode.ucLaneSet = lane_set;
} else { } 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); args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock / 2) / 10);
else else
args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10);
} }
if (ASIC_IS_DCE32(rdev)) { 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) if (dig->dig_block)
args.v2.acConfig.ucEncoderSel = 1; args.v2.acConfig.ucEncoderSel = 1;
if (dig_connector->linkb) if (dig_connector->linkb)
...@@ -818,7 +831,9 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t ...@@ -818,7 +831,9 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
break; 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) if (dig->coherent_mode)
args.v2.acConfig.fCoherentMode = 1; args.v2.acConfig.fCoherentMode = 1;
} }
...@@ -866,7 +881,9 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t ...@@ -866,7 +881,9 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
else else
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; 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) if (dig->coherent_mode)
args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
} }
......
...@@ -366,6 +366,8 @@ struct radeon_framebuffer { ...@@ -366,6 +366,8 @@ struct radeon_framebuffer {
struct drm_gem_object *obj; 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 u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
extern void radeon_dp_getdpcd(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, extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment