Commit 5801ead6 authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie

drm/radeon/kms: add support for DP modesetting

Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent f92a8b67
...@@ -1214,3 +1214,28 @@ void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t * frev, ...@@ -1214,3 +1214,28 @@ void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t * frev,
*crev = CU8(idx + 3); *crev = CU8(idx + 3);
return; return;
} }
int atom_allocate_fb_scratch(struct atom_context *ctx)
{
int index = GetIndexIntoMasterTable(DATA, VRAM_UsageByFirmware);
uint16_t data_offset;
int usage_bytes;
struct _ATOM_VRAM_USAGE_BY_FIRMWARE *firmware_usage;
atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset);
firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset);
DRM_DEBUG("atom firmware requested %08x %dkb\n",
firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware,
firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb);
usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024;
if (usage_bytes == 0)
usage_bytes = 20 * 1024;
/* allocate some scratch memory */
ctx->scratch = kzalloc(usage_bytes, GFP_KERNEL);
if (!ctx->scratch)
return -ENOMEM;
return 0;
}
This diff is collapsed.
...@@ -934,9 +934,23 @@ static enum drm_connector_status radeon_dp_detect(struct drm_connector *connecto ...@@ -934,9 +934,23 @@ static enum drm_connector_status radeon_dp_detect(struct drm_connector *connecto
return ret; return ret;
} }
static int radeon_dp_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
/* XXX check mode bandwidth */
if (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT)
return radeon_dp_mode_valid_helper(radeon_connector, mode);
else
return MODE_OK;
}
struct drm_connector_helper_funcs radeon_dp_connector_helper_funcs = { struct drm_connector_helper_funcs radeon_dp_connector_helper_funcs = {
.get_modes = radeon_dp_get_modes, .get_modes = radeon_dp_get_modes,
.mode_valid = radeon_dvi_mode_valid, .mode_valid = radeon_dp_mode_valid,
.best_encoder = radeon_dvi_encoder, .best_encoder = radeon_dvi_encoder,
}; };
......
...@@ -250,6 +250,12 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, ...@@ -250,6 +250,12 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
} }
} }
if (ASIC_IS_DCE3(rdev) &&
(radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT))) {
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
radeon_dp_set_link_config(connector, mode);
}
return true; return true;
} }
...@@ -719,11 +725,9 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) ...@@ -719,11 +725,9 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action)
args.ucEncoderMode = atombios_get_encoder_mode(encoder); args.ucEncoderMode = atombios_get_encoder_mode(encoder);
if (args.ucEncoderMode == ATOM_ENCODER_MODE_DP) { if (args.ucEncoderMode == ATOM_ENCODER_MODE_DP) {
if (dp_link_clock_for_mode_clock(dig_connector->dpcd[1], if (dig_connector->dp_clock == 270000)
radeon_encoder->pixel_clock) == 270000)
args.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ; args.ucConfig |= ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ;
args.ucLaneNum = dp_lanes_for_mode_clock(dig_connector->dpcd[1], args.ucLaneNum = dig_connector->dp_lane_count;
radeon_encoder->pixel_clock);
} else if (radeon_encoder->pixel_clock > 165000) } else if (radeon_encoder->pixel_clock > 165000)
args.ucLaneNum = 8; args.ucLaneNum = 8;
else else
...@@ -743,7 +747,7 @@ union dig_transmitter_control { ...@@ -743,7 +747,7 @@ union dig_transmitter_control {
DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2;
}; };
static void void
atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set) atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t lane_num, uint8_t lane_set)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
...@@ -803,8 +807,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t ...@@ -803,8 +807,7 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
} else { } else {
if (is_dp) if (is_dp)
args.v1.usPixelClock = args.v1.usPixelClock =
cpu_to_le16(dp_link_clock_for_mode_clock(dig_connector->dpcd[1], cpu_to_le16(dig_connector->dp_clock / 10);
radeon_encoder->pixel_clock) / 10);
else if (radeon_encoder->pixel_clock > 165000) 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
...@@ -1198,13 +1201,17 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, ...@@ -1198,13 +1201,17 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
if (radeon_encoder->active_device &
(ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) {
if (radeon_encoder->enc_priv) { if (radeon_encoder->enc_priv) {
struct radeon_encoder_atom_dig *dig; struct radeon_encoder_atom_dig *dig;
dig = radeon_encoder->enc_priv; dig = radeon_encoder->enc_priv;
dig->dig_block = radeon_crtc->crtc_id; dig->dig_block = radeon_crtc->crtc_id;
} }
}
radeon_encoder->pixel_clock = adjusted_mode->clock; radeon_encoder->pixel_clock = adjusted_mode->clock;
radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
...@@ -1237,6 +1244,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, ...@@ -1237,6 +1244,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_INIT, 0, 0);
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
dp_link_train(encoder, connector);
break; break;
case ENCODER_OBJECT_ID_INTERNAL_DDI: case ENCODER_OBJECT_ID_INTERNAL_DDI:
atombios_ddia_setup(encoder, ATOM_ENABLE); atombios_ddia_setup(encoder, ATOM_ENABLE);
......
...@@ -343,6 +343,8 @@ struct radeon_connector_atom_dig { ...@@ -343,6 +343,8 @@ struct radeon_connector_atom_dig {
struct radeon_i2c_chan *dp_i2c_bus; struct radeon_i2c_chan *dp_i2c_bus;
u8 dpcd[8]; u8 dpcd[8];
u8 dp_sink_type; u8 dp_sink_type;
int dp_clock;
int dp_lane_count;
}; };
struct radeon_connector { struct radeon_connector {
...@@ -366,10 +368,17 @@ struct radeon_framebuffer { ...@@ -366,10 +368,17 @@ 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 radeon_dp_mode_valid_helper(struct radeon_connector *radeon_connector,
extern int dp_link_clock_for_mode_clock(int max_link_bw, int mode_clock); struct drm_display_mode *mode);
extern void radeon_dp_set_link_config(struct drm_connector *connector,
struct drm_display_mode *mode);
extern void dp_link_train(struct drm_encoder *encoder,
struct drm_connector *connector);
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 void atombios_dig_transmitter_setup(struct drm_encoder *encoder,
int action, uint8_t lane_num,
uint8_t lane_set);
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,
uint8_t write_byte, uint8_t *read_byte); uint8_t write_byte, uint8_t *read_byte);
......
...@@ -43,8 +43,32 @@ ...@@ -43,8 +43,32 @@
#define AUX_I2C_REPLY_MASK (0x3 << 6) #define AUX_I2C_REPLY_MASK (0x3 << 6)
/* AUX CH addresses */ /* AUX CH addresses */
#define DP_DPCD_REV 0x0 /* DPCD */
#define DP_DPCD_REV 0x000
#define DP_MAX_LINK_RATE 0x001
#define DP_MAX_LANE_COUNT 0x002
# define DP_MAX_LANE_COUNT_MASK 0x1f
# define DP_ENHANCED_FRAME_CAP (1 << 7)
#define DP_MAX_DOWNSPREAD 0x003
# define DP_NO_AUX_HANDSHAKE_LINK_TRAINING (1 << 6)
#define DP_NORP 0x004
#define DP_DOWNSTREAMPORT_PRESENT 0x005
# define DP_DWN_STRM_PORT_PRESENT (1 << 0)
# define DP_DWN_STRM_PORT_TYPE_MASK 0x06
/* 00b = DisplayPort */
/* 01b = Analog */
/* 10b = TMDS or HDMI */
/* 11b = Other */
# define DP_FORMAT_CONVERSION (1 << 3)
#define DP_MAIN_LINK_CHANNEL_CODING 0x006
/* link configuration */
#define DP_LINK_BW_SET 0x100 #define DP_LINK_BW_SET 0x100
# define DP_LINK_BW_1_62 0x06 # define DP_LINK_BW_1_62 0x06
# define DP_LINK_BW_2_7 0x0a # define DP_LINK_BW_2_7 0x0a
...@@ -54,7 +78,6 @@ ...@@ -54,7 +78,6 @@
# define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7) # define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7)
#define DP_TRAINING_PATTERN_SET 0x102 #define DP_TRAINING_PATTERN_SET 0x102
# define DP_TRAINING_PATTERN_DISABLE 0 # define DP_TRAINING_PATTERN_DISABLE 0
# define DP_TRAINING_PATTERN_1 1 # define DP_TRAINING_PATTERN_1 1
# define DP_TRAINING_PATTERN_2 2 # define DP_TRAINING_PATTERN_2 2
...@@ -104,11 +127,14 @@ ...@@ -104,11 +127,14 @@
#define DP_LANE0_1_STATUS 0x202 #define DP_LANE0_1_STATUS 0x202
#define DP_LANE2_3_STATUS 0x203 #define DP_LANE2_3_STATUS 0x203
# define DP_LANE_CR_DONE (1 << 0) # define DP_LANE_CR_DONE (1 << 0)
# define DP_LANE_CHANNEL_EQ_DONE (1 << 1) # define DP_LANE_CHANNEL_EQ_DONE (1 << 1)
# define DP_LANE_SYMBOL_LOCKED (1 << 2) # define DP_LANE_SYMBOL_LOCKED (1 << 2)
#define DP_CHANNEL_EQ_BITS (DP_LANE_CR_DONE | \
DP_LANE_CHANNEL_EQ_DONE | \
DP_LANE_SYMBOL_LOCKED)
#define DP_LANE_ALIGN_STATUS_UPDATED 0x204 #define DP_LANE_ALIGN_STATUS_UPDATED 0x204
#define DP_INTERLANE_ALIGN_DONE (1 << 0) #define DP_INTERLANE_ALIGN_DONE (1 << 0)
...@@ -122,17 +148,18 @@ ...@@ -122,17 +148,18 @@
#define DP_ADJUST_REQUEST_LANE0_1 0x206 #define DP_ADJUST_REQUEST_LANE0_1 0x206
#define DP_ADJUST_REQUEST_LANE2_3 0x207 #define DP_ADJUST_REQUEST_LANE2_3 0x207
# define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03
#define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03 # define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0
#define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0 # define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c
#define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c # define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2
#define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2 # define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30
#define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30 # define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4
#define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4 # define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0
#define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0 # define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6
#define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6
#define DP_SET_POWER 0x600 #define DP_SET_POWER 0x600
# define DP_SET_POWER_D0 0x1
# define DP_SET_POWER_D3 0x2
#define MODE_I2C_START 1 #define MODE_I2C_START 1
#define MODE_I2C_WRITE 2 #define MODE_I2C_WRITE 2
......
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