summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon')
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c20
-rw-r--r--drivers/gpu/drm/radeon/atombios_dp.c268
-rw-r--r--drivers/gpu/drm/radeon/atombios_encoders.c82
-rw-r--r--drivers/gpu/drm/radeon/cik.c33
-rw-r--r--drivers/gpu/drm/radeon/r100.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c19
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c12
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c248
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_crtc.c16
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h4
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.c13
-rw-r--r--drivers/gpu/drm/radeon/radeon_ring.c1
14 files changed, 400 insertions, 327 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index daa4dd375ab1..fb187c78978f 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1106,7 +1106,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
int r;
/* no fb bound */
- if (!atomic && !crtc->fb) {
+ if (!atomic && !crtc->primary->fb) {
DRM_DEBUG_KMS("No FB bound\n");
return 0;
}
@@ -1116,8 +1116,8 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
target_fb = fb;
}
else {
- radeon_fb = to_radeon_framebuffer(crtc->fb);
- target_fb = crtc->fb;
+ radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
+ target_fb = crtc->primary->fb;
}
/* If atomic, assume fb object is pinned & idle & fenced and
@@ -1316,7 +1316,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
/* set pageflip to happen anywhere in vblank interval */
WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
- if (!atomic && fb && fb != crtc->fb) {
+ if (!atomic && fb && fb != crtc->primary->fb) {
radeon_fb = to_radeon_framebuffer(fb);
rbo = gem_to_radeon_bo(radeon_fb->obj);
r = radeon_bo_reserve(rbo, false);
@@ -1350,7 +1350,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
int r;
/* no fb bound */
- if (!atomic && !crtc->fb) {
+ if (!atomic && !crtc->primary->fb) {
DRM_DEBUG_KMS("No FB bound\n");
return 0;
}
@@ -1360,8 +1360,8 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
target_fb = fb;
}
else {
- radeon_fb = to_radeon_framebuffer(crtc->fb);
- target_fb = crtc->fb;
+ radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
+ target_fb = crtc->primary->fb;
}
obj = radeon_fb->obj;
@@ -1485,7 +1485,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
/* set pageflip to happen anywhere in vblank interval */
WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
- if (!atomic && fb && fb != crtc->fb) {
+ if (!atomic && fb && fb != crtc->primary->fb) {
radeon_fb = to_radeon_framebuffer(fb);
rbo = gem_to_radeon_bo(radeon_fb->obj);
r = radeon_bo_reserve(rbo, false);
@@ -1972,12 +1972,12 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
int i;
atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
- if (crtc->fb) {
+ if (crtc->primary->fb) {
int r;
struct radeon_framebuffer *radeon_fb;
struct radeon_bo *rbo;
- radeon_fb = to_radeon_framebuffer(crtc->fb);
+ radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
rbo = gem_to_radeon_bo(radeon_fb->obj);
r = radeon_bo_reserve(rbo, false);
if (unlikely(r))
diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c
index 4ad7643fce5f..8b0ab170cef9 100644
--- a/drivers/gpu/drm/radeon/atombios_dp.c
+++ b/drivers/gpu/drm/radeon/atombios_dp.c
@@ -142,101 +142,69 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan,
return recv_bytes;
}
-static int radeon_dp_aux_native_write(struct radeon_connector *radeon_connector,
- u16 address, u8 *send, u8 send_bytes, u8 delay)
-{
- struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
- int ret;
- u8 msg[20];
- int msg_bytes = send_bytes + 4;
- u8 ack;
- unsigned retry;
-
- if (send_bytes > 16)
- return -1;
+#define HEADER_SIZE 4
- msg[0] = address;
- msg[1] = address >> 8;
- msg[2] = DP_AUX_NATIVE_WRITE << 4;
- msg[3] = (msg_bytes << 4) | (send_bytes - 1);
- memcpy(&msg[4], send, send_bytes);
-
- for (retry = 0; retry < 7; retry++) {
- ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus,
- msg, msg_bytes, NULL, 0, delay, &ack);
- if (ret == -EBUSY)
- continue;
- else if (ret < 0)
- return ret;
- ack >>= 4;
- if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
- return send_bytes;
- else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
- usleep_range(400, 500);
- else
- return -EIO;
- }
-
- return -EIO;
-}
-
-static int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector,
- u16 address, u8 *recv, int recv_bytes, u8 delay)
+static ssize_t
+radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
{
- struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
- u8 msg[4];
- int msg_bytes = 4;
- u8 ack;
+ struct radeon_i2c_chan *chan =
+ container_of(aux, struct radeon_i2c_chan, aux);
int ret;
- unsigned retry;
-
- msg[0] = address;
- msg[1] = address >> 8;
- msg[2] = DP_AUX_NATIVE_READ << 4;
- msg[3] = (msg_bytes << 4) | (recv_bytes - 1);
-
- for (retry = 0; retry < 7; retry++) {
- ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus,
- msg, msg_bytes, recv, recv_bytes, delay, &ack);
- if (ret == -EBUSY)
- continue;
- else if (ret < 0)
- return ret;
- ack >>= 4;
- if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_ACK)
- return ret;
- else if ((ack & DP_AUX_NATIVE_REPLY_MASK) == DP_AUX_NATIVE_REPLY_DEFER)
- usleep_range(400, 500);
- else if (ret == 0)
- return -EPROTO;
- else
- return -EIO;
+ u8 tx_buf[20];
+ size_t tx_size;
+ u8 ack, delay = 0;
+
+ if (WARN_ON(msg->size > 16))
+ return -E2BIG;
+
+ tx_buf[0] = msg->address & 0xff;
+ tx_buf[1] = msg->address >> 8;
+ tx_buf[2] = msg->request << 4;
+ tx_buf[3] = msg->size - 1;
+
+ switch (msg->request & ~DP_AUX_I2C_MOT) {
+ case DP_AUX_NATIVE_WRITE:
+ case DP_AUX_I2C_WRITE:
+ tx_size = HEADER_SIZE + msg->size;
+ tx_buf[3] |= tx_size << 4;
+ memcpy(tx_buf + HEADER_SIZE, msg->buffer, msg->size);
+ ret = radeon_process_aux_ch(chan,
+ tx_buf, tx_size, NULL, 0, delay, &ack);
+ if (ret >= 0)
+ /* Return payload size. */
+ ret = msg->size;
+ break;
+ case DP_AUX_NATIVE_READ:
+ case DP_AUX_I2C_READ:
+ tx_size = HEADER_SIZE;
+ tx_buf[3] |= tx_size << 4;
+ ret = radeon_process_aux_ch(chan,
+ tx_buf, tx_size, msg->buffer, msg->size, delay, &ack);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
}
- return -EIO;
-}
+ if (ret > 0)
+ msg->reply = ack >> 4;
-static void radeon_write_dpcd_reg(struct radeon_connector *radeon_connector,
- u16 reg, u8 val)
-{
- radeon_dp_aux_native_write(radeon_connector, reg, &val, 1, 0);
+ return ret;
}
-static u8 radeon_read_dpcd_reg(struct radeon_connector *radeon_connector,
- u16 reg)
+void radeon_dp_aux_init(struct radeon_connector *radeon_connector)
{
- u8 val = 0;
-
- radeon_dp_aux_native_read(radeon_connector, reg, &val, 1, 0);
+ struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
- return val;
+ dig_connector->dp_i2c_bus->aux.dev = radeon_connector->base.kdev;
+ dig_connector->dp_i2c_bus->aux.transfer = radeon_dp_aux_transfer;
}
int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
u8 write_byte, u8 *read_byte)
{
struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data;
- struct radeon_i2c_chan *auxch = (struct radeon_i2c_chan *)adapter;
+ struct radeon_i2c_chan *auxch = i2c_get_adapdata(adapter);
u16 address = algo_data->address;
u8 msg[5];
u8 reply[2];
@@ -246,34 +214,30 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
int ret;
u8 ack;
- /* Set up the command byte */
- if (mode & MODE_I2C_READ)
- msg[2] = DP_AUX_I2C_READ << 4;
- else
- msg[2] = DP_AUX_I2C_WRITE << 4;
-
- if (!(mode & MODE_I2C_STOP))
- msg[2] |= DP_AUX_I2C_MOT << 4;
-
+ /* Set up the address */
msg[0] = address;
msg[1] = address >> 8;
- switch (mode) {
- case MODE_I2C_WRITE:
+ /* Set up the command byte */
+ if (mode & MODE_I2C_READ) {
+ msg[2] = DP_AUX_I2C_READ << 4;
+ msg_bytes = 4;
+ msg[3] = msg_bytes << 4;
+ } else {
+ msg[2] = DP_AUX_I2C_WRITE << 4;
msg_bytes = 5;
msg[3] = msg_bytes << 4;
msg[4] = write_byte;
- break;
- case MODE_I2C_READ:
- msg_bytes = 4;
- msg[3] = msg_bytes << 4;
- break;
- default:
- msg_bytes = 4;
- msg[3] = 3 << 4;
- break;
}
+ /* special handling for start/stop */
+ if (mode & (MODE_I2C_START | MODE_I2C_STOP))
+ msg[3] = 3 << 4;
+
+ /* Set MOT bit for all but stop */
+ if ((mode & MODE_I2C_STOP) == 0)
+ msg[2] |= DP_AUX_I2C_MOT << 4;
+
for (retry = 0; retry < 7; retry++) {
ret = radeon_process_aux_ch(auxch,
msg, msg_bytes, reply, reply_bytes, 0, &ack);
@@ -472,11 +436,11 @@ static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector)
if (!(dig_connector->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT))
return;
- if (radeon_dp_aux_native_read(radeon_connector, DP_SINK_OUI, buf, 3, 0))
+ if (drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_SINK_OUI, buf, 3))
DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n",
buf[0], buf[1], buf[2]);
- if (radeon_dp_aux_native_read(radeon_connector, DP_BRANCH_OUI, buf, 3, 0))
+ if (drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_BRANCH_OUI, buf, 3))
DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
buf[0], buf[1], buf[2]);
}
@@ -487,8 +451,8 @@ bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector)
u8 msg[DP_DPCD_SIZE];
int ret, i;
- ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, msg,
- DP_DPCD_SIZE, 0);
+ ret = drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_DPCD_REV, msg,
+ DP_DPCD_SIZE);
if (ret > 0) {
memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE);
DRM_DEBUG_KMS("DPCD: ");
@@ -510,6 +474,7 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+ struct radeon_connector_atom_dig *dig_connector;
int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
u16 dp_bridge = radeon_connector_encoder_get_dp_bridge_encoder_id(connector);
u8 tmp;
@@ -517,9 +482,15 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
if (!ASIC_IS_DCE4(rdev))
return panel_mode;
+ if (!radeon_connector->con_priv)
+ return panel_mode;
+
+ dig_connector = radeon_connector->con_priv;
+
if (dp_bridge != ENCODER_OBJECT_ID_NONE) {
/* DP bridge chips */
- tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
+ drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux,
+ DP_EDP_CONFIGURATION_CAP, &tmp);
if (tmp & 1)
panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) ||
@@ -529,7 +500,8 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
} else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
/* eDP */
- tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
+ drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux,
+ DP_EDP_CONFIGURATION_CAP, &tmp);
if (tmp & 1)
panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
}
@@ -577,37 +549,42 @@ int radeon_dp_mode_valid_helper(struct drm_connector *connector,
return MODE_OK;
}
-static bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector,
- u8 link_status[DP_LINK_STATUS_SIZE])
-{
- int ret;
- ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS,
- link_status, DP_LINK_STATUS_SIZE, 100);
- if (ret <= 0) {
- return false;
- }
-
- DRM_DEBUG_KMS("link status %6ph\n", link_status);
- return true;
-}
-
bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector)
{
u8 link_status[DP_LINK_STATUS_SIZE];
struct radeon_connector_atom_dig *dig = radeon_connector->con_priv;
- if (!radeon_dp_get_link_status(radeon_connector, link_status))
+ if (drm_dp_dpcd_read_link_status(&dig->dp_i2c_bus->aux, link_status) <= 0)
return false;
if (drm_dp_channel_eq_ok(link_status, dig->dp_lane_count))
return false;
return true;
}
+void radeon_dp_set_rx_power_state(struct drm_connector *connector,
+ u8 power_state)
+{
+ struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+ struct radeon_connector_atom_dig *dig_connector;
+
+ if (!radeon_connector->con_priv)
+ return;
+
+ dig_connector = radeon_connector->con_priv;
+
+ /* power up/down the sink */
+ if (dig_connector->dpcd[0] >= 0x11) {
+ drm_dp_dpcd_writeb(&dig_connector->dp_i2c_bus->aux,
+ DP_SET_POWER, power_state);
+ usleep_range(1000, 2000);
+ }
+}
+
+
struct radeon_dp_link_train_info {
struct radeon_device *rdev;
struct drm_encoder *encoder;
struct drm_connector *connector;
- struct radeon_connector *radeon_connector;
int enc_id;
int dp_clock;
int dp_lane_count;
@@ -617,6 +594,7 @@ struct radeon_dp_link_train_info {
u8 link_status[DP_LINK_STATUS_SIZE];
u8 tries;
bool use_dpencoder;
+ struct drm_dp_aux *aux;
};
static void radeon_dp_update_vs_emph(struct radeon_dp_link_train_info *dp_info)
@@ -627,8 +605,8 @@ static void radeon_dp_update_vs_emph(struct radeon_dp_link_train_info *dp_info)
0, dp_info->train_set[0]); /* sets all lanes at once */
/* set the vs/emph on the sink */
- radeon_dp_aux_native_write(dp_info->radeon_connector, DP_TRAINING_LANE0_SET,
- dp_info->train_set, dp_info->dp_lane_count, 0);
+ drm_dp_dpcd_write(dp_info->aux, DP_TRAINING_LANE0_SET,
+ dp_info->train_set, dp_info->dp_lane_count);
}
static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp)
@@ -663,7 +641,7 @@ static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp)
}
/* enable training pattern on the sink */
- radeon_write_dpcd_reg(dp_info->radeon_connector, DP_TRAINING_PATTERN_SET, tp);
+ drm_dp_dpcd_writeb(dp_info->aux, DP_TRAINING_PATTERN_SET, tp);
}
static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
@@ -673,34 +651,30 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
u8 tmp;
/* power up the sink */
- if (dp_info->dpcd[0] >= 0x11) {
- radeon_write_dpcd_reg(dp_info->radeon_connector,
- DP_SET_POWER, DP_SET_POWER_D0);
- usleep_range(1000, 2000);
- }
+ radeon_dp_set_rx_power_state(dp_info->connector, DP_SET_POWER_D0);
/* possibly enable downspread on the sink */
if (dp_info->dpcd[3] & 0x1)
- radeon_write_dpcd_reg(dp_info->radeon_connector,
- DP_DOWNSPREAD_CTRL, DP_SPREAD_AMP_0_5);
+ drm_dp_dpcd_writeb(dp_info->aux,
+ DP_DOWNSPREAD_CTRL, DP_SPREAD_AMP_0_5);
else
- radeon_write_dpcd_reg(dp_info->radeon_connector,
- DP_DOWNSPREAD_CTRL, 0);
+ drm_dp_dpcd_writeb(dp_info->aux,
+ DP_DOWNSPREAD_CTRL, 0);
if ((dp_info->connector->connector_type == DRM_MODE_CONNECTOR_eDP) &&
(dig->panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) {
- radeon_write_dpcd_reg(dp_info->radeon_connector, DP_EDP_CONFIGURATION_SET, 1);
+ drm_dp_dpcd_writeb(dp_info->aux, DP_EDP_CONFIGURATION_SET, 1);
}
/* set the lane count on the sink */
tmp = dp_info->dp_lane_count;
if (drm_dp_enhanced_frame_cap(dp_info->dpcd))
tmp |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
- radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LANE_COUNT_SET, tmp);
+ drm_dp_dpcd_writeb(dp_info->aux, DP_LANE_COUNT_SET, tmp);
/* set the link rate on the sink */
tmp = drm_dp_link_rate_to_bw_code(dp_info->dp_clock);
- radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp);
+ drm_dp_dpcd_writeb(dp_info->aux, DP_LINK_BW_SET, tmp);
/* start training on the source */
if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder)
@@ -711,9 +685,9 @@ static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
dp_info->dp_clock, dp_info->enc_id, 0);
/* disable the training pattern on the sink */
- radeon_write_dpcd_reg(dp_info->radeon_connector,
- DP_TRAINING_PATTERN_SET,
- DP_TRAINING_PATTERN_DISABLE);
+ drm_dp_dpcd_writeb(dp_info->aux,
+ DP_TRAINING_PATTERN_SET,
+ DP_TRAINING_PATTERN_DISABLE);
return 0;
}
@@ -723,9 +697,9 @@ static int radeon_dp_link_train_finish(struct radeon_dp_link_train_info *dp_info
udelay(400);
/* disable the training pattern on the sink */
- radeon_write_dpcd_reg(dp_info->radeon_connector,
- DP_TRAINING_PATTERN_SET,
- DP_TRAINING_PATTERN_DISABLE);
+ drm_dp_dpcd_writeb(dp_info->aux,
+ DP_TRAINING_PATTERN_SET,
+ DP_TRAINING_PATTERN_DISABLE);
/* disable the training pattern on the source */
if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder)
@@ -757,7 +731,8 @@ static int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info)
while (1) {
drm_dp_link_train_clock_recovery_delay(dp_info->dpcd);
- if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) {
+ if (drm_dp_dpcd_read_link_status(dp_info->aux,
+ dp_info->link_status) <= 0) {
DRM_ERROR("displayport link status failed\n");
break;
}
@@ -819,7 +794,8 @@ static int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info)
while (1) {
drm_dp_link_train_channel_eq_delay(dp_info->dpcd);
- if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) {
+ if (drm_dp_dpcd_read_link_status(dp_info->aux,
+ dp_info->link_status) <= 0) {
DRM_ERROR("displayport link status failed\n");
break;
}
@@ -902,7 +878,7 @@ void radeon_dp_link_train(struct drm_encoder *encoder,
else
dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A;
- tmp = radeon_read_dpcd_reg(radeon_connector, DP_MAX_LANE_COUNT);
+ drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux, DP_MAX_LANE_COUNT, &tmp);
if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED))
dp_info.tp3_supported = true;
else
@@ -912,9 +888,9 @@ void radeon_dp_link_train(struct drm_encoder *encoder,
dp_info.rdev = rdev;
dp_info.encoder = encoder;
dp_info.connector = connector;
- dp_info.radeon_connector = radeon_connector;
dp_info.dp_lane_count = dig_connector->dp_lane_count;
dp_info.dp_clock = dig_connector->dp_clock;
+ dp_info.aux = &dig_connector->dp_i2c_bus->aux;
if (radeon_dp_link_train_init(&dp_info))
goto done;
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index 607dc14d195e..e6eb5097597f 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -1633,10 +1633,16 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
struct radeon_connector *radeon_connector = NULL;
struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
+ bool travis_quirk = false;
if (connector) {
radeon_connector = to_radeon_connector(connector);
radeon_dig_connector = radeon_connector->con_priv;
+ if ((radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
+ ENCODER_OBJECT_ID_TRAVIS) &&
+ (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) &&
+ !ASIC_IS_DCE5(rdev))
+ travis_quirk = true;
}
switch (mode) {
@@ -1657,17 +1663,13 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
atombios_external_encoder_setup(encoder, ext_encoder,
EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
}
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
} else if (ASIC_IS_DCE4(rdev)) {
/* setup and enable the encoder */
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
- /* enable the transmitter */
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
} else {
/* setup and enable the encoder and transmitter */
atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
}
if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
@@ -1675,68 +1677,56 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
ATOM_TRANSMITTER_ACTION_POWER_ON);
radeon_dig_connector->edp_on = true;
}
+ }
+ /* enable the transmitter */
+ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+ if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
+ /* DP_SET_POWER_D0 is set in radeon_dp_link_train */
radeon_dp_link_train(encoder, connector);
if (ASIC_IS_DCE4(rdev))
atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_ON, 0);
}
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+ atombios_dig_transmitter_setup(encoder,
+ ATOM_TRANSMITTER_ACTION_LCD_BLON, 0, 0);
+ if (ext_encoder)
+ atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
break;
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
if (ASIC_IS_DCE4(rdev)) {
+ if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector)
+ atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
+ }
+ if (ext_encoder)
+ atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
+ if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
+ atombios_dig_transmitter_setup(encoder,
+ ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
+
+ if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) &&
+ connector && !travis_quirk)
+ radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
+ if (ASIC_IS_DCE4(rdev)) {
/* disable the transmitter */
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+ atombios_dig_transmitter_setup(encoder,
+ ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
} else {
/* disable the encoder and transmitter */
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+ atombios_dig_transmitter_setup(encoder,
+ ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
}
if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
- if (ASIC_IS_DCE4(rdev))
- atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
+ if (travis_quirk)
+ radeon_dp_set_rx_power_state(connector, DP_SET_POWER_D3);
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
atombios_set_edp_panel_power(connector,
ATOM_TRANSMITTER_ACTION_POWER_OFF);
radeon_dig_connector->edp_on = false;
}
}
- if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT))
- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_LCD_BLOFF, 0, 0);
- break;
- }
-}
-
-static void
-radeon_atom_encoder_dpms_ext(struct drm_encoder *encoder,
- struct drm_encoder *ext_encoder,
- int mode)
-{
- struct drm_device *dev = encoder->dev;
- struct radeon_device *rdev = dev->dev_private;
-
- switch (mode) {
- case DRM_MODE_DPMS_ON:
- default:
- if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) {
- atombios_external_encoder_setup(encoder, ext_encoder,
- EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
- atombios_external_encoder_setup(encoder, ext_encoder,
- EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
- } else
- atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
- break;
- case DRM_MODE_DPMS_STANDBY:
- case DRM_MODE_DPMS_SUSPEND:
- case DRM_MODE_DPMS_OFF:
- if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) {
- atombios_external_encoder_setup(encoder, ext_encoder,
- EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
- atombios_external_encoder_setup(encoder, ext_encoder,
- EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
- } else
- atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
break;
}
}
@@ -1747,7 +1737,6 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
- struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
DRM_DEBUG_KMS("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
radeon_encoder->encoder_id, mode, radeon_encoder->devices,
@@ -1807,9 +1796,6 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
return;
}
- if (ext_encoder)
- radeon_atom_encoder_dpms_ext(encoder, ext_encoder, mode);
-
radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
}
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c
index 0ae991d3289a..745143c2358f 100644
--- a/drivers/gpu/drm/radeon/cik.c
+++ b/drivers/gpu/drm/radeon/cik.c
@@ -1096,7 +1096,7 @@ static const u32 spectre_golden_registers[] =
0x8a14, 0xf000003f, 0x00000007,
0x8b24, 0xffffffff, 0x00ffffff,
0x28350, 0x3f3f3fff, 0x00000082,
- 0x28355, 0x0000003f, 0x00000000,
+ 0x28354, 0x0000003f, 0x00000000,
0x3e78, 0x00000001, 0x00000002,
0x913c, 0xffff03df, 0x00000004,
0xc768, 0x00000008, 0x00000008,
@@ -2029,6 +2029,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 5:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
break;
case 6:
@@ -2049,6 +2050,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 9:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
break;
case 10:
@@ -2071,6 +2073,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 13:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
break;
case 14:
@@ -2093,6 +2096,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 27:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) |
MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
break;
case 28:
@@ -2247,6 +2251,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 5:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
break;
case 6:
@@ -2267,6 +2272,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 9:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
break;
case 10:
@@ -2289,6 +2295,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 13:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
break;
case 14:
@@ -2311,6 +2318,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 27:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) |
MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
break;
case 28:
@@ -2467,6 +2475,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 5:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P4_16x16) |
MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
break;
case 6:
@@ -2487,6 +2496,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 9:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P4_16x16) |
MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
break;
case 10:
@@ -2509,6 +2519,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 13:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P4_16x16) |
MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
break;
case 14:
@@ -2531,6 +2542,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 27:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P4_16x16) |
MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
break;
case 28:
@@ -2593,6 +2605,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 5:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P4_8x16) |
MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
break;
case 6:
@@ -2613,6 +2626,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 9:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P4_8x16) |
MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
break;
case 10:
@@ -2635,6 +2649,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 13:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P4_8x16) |
MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
break;
case 14:
@@ -2657,6 +2672,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 27:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P4_8x16) |
MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
break;
case 28:
@@ -2813,6 +2829,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 5:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING));
break;
case 6:
@@ -2828,11 +2845,13 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
TILE_SPLIT(split_equal_to_row_size));
break;
case 8:
- gb_tile_moden = ARRAY_MODE(ARRAY_LINEAR_ALIGNED);
+ gb_tile_moden = ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
+ PIPE_CONFIG(ADDR_SURF_P2);
break;
case 9:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
- MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING));
+ MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) |
+ PIPE_CONFIG(ADDR_SURF_P2));
break;
case 10:
gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
@@ -2854,6 +2873,7 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 13:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
+ PIPE_CONFIG(ADDR_SURF_P2) |
MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING));
break;
case 14:
@@ -2876,7 +2896,8 @@ static void cik_tiling_mode_table_init(struct radeon_device *rdev)
break;
case 27:
gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
- MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING));
+ MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) |
+ PIPE_CONFIG(ADDR_SURF_P2));
break;
case 28:
gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_2D_TILED_THIN1) |
@@ -6521,8 +6542,8 @@ void cik_get_csb_buffer(struct radeon_device *rdev, volatile u32 *buffer)
buffer[count++] = cpu_to_le32(0x00000000);
break;
case CHIP_HAWAII:
- buffer[count++] = 0x3a00161a;
- buffer[count++] = 0x0000002e;
+ buffer[count++] = cpu_to_le32(0x3a00161a);
+ buffer[count++] = cpu_to_le32(0x0000002e);
break;
default:
buffer[count++] = cpu_to_le32(0x00000000);
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 030f8e49c5ee..b6c32640df20 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -3220,12 +3220,12 @@ void r100_bandwidth_update(struct radeon_device *rdev)
if (rdev->mode_info.crtcs[0]->base.enabled) {
mode1 = &rdev->mode_info.crtcs[0]->base.mode;
- pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8;
+ pixel_bytes1 = rdev->mode_info.crtcs[0]->base.primary->fb->bits_per_pixel / 8;
}
if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
if (rdev->mode_info.crtcs[1]->base.enabled) {
mode2 = &rdev->mode_info.crtcs[1]->base.mode;
- pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8;
+ pixel_bytes2 = rdev->mode_info.crtcs[1]->base.primary->fb->bits_per_pixel / 8;
}
}
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 82d4f865546e..c566b486ca08 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -89,7 +89,7 @@ static void radeon_property_change_mode(struct drm_encoder *encoder)
if (crtc && crtc->enabled) {
drm_crtc_helper_set_mode(crtc, &crtc->mode,
- crtc->x, crtc->y, crtc->fb);
+ crtc->x, crtc->y, crtc->primary->fb);
}
}
@@ -1595,6 +1595,7 @@ radeon_add_atom_connector(struct drm_device *dev,
uint32_t subpixel_order = SubPixelNone;
bool shared_ddc = false;
bool is_dp_bridge = false;
+ bool has_aux = false;
if (connector_type == DRM_MODE_CONNECTOR_Unknown)
return;
@@ -1672,7 +1673,9 @@ radeon_add_atom_connector(struct drm_device *dev,
radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch");
else
radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch");
- if (!radeon_dig_connector->dp_i2c_bus)
+ if (radeon_dig_connector->dp_i2c_bus)
+ has_aux = true;
+ else
DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n");
radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
if (!radeon_connector->ddc_bus)
@@ -1895,7 +1898,9 @@ radeon_add_atom_connector(struct drm_device *dev,
if (!radeon_dig_connector->dp_i2c_bus)
DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n");
radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
- if (!radeon_connector->ddc_bus)
+ if (radeon_connector->ddc_bus)
+ has_aux = true;
+ else
DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
}
subpixel_order = SubPixelHorizontalRGB;
@@ -1939,7 +1944,9 @@ radeon_add_atom_connector(struct drm_device *dev,
if (i2c_bus->valid) {
/* add DP i2c bus */
radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch");
- if (!radeon_dig_connector->dp_i2c_bus)
+ if (radeon_dig_connector->dp_i2c_bus)
+ has_aux = true;
+ else
DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n");
radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
if (!radeon_connector->ddc_bus)
@@ -2000,6 +2007,10 @@ radeon_add_atom_connector(struct drm_device *dev,
connector->display_info.subpixel_order = subpixel_order;
drm_sysfs_connector_add(connector);
+
+ if (has_aux)
+ radeon_dp_aux_init(radeon_connector);
+
return;
failed:
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 2e72dcd94b13..835516d2d257 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1424,7 +1424,7 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon)
/* unpin the front buffers */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
- struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
+ struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->primary->fb);
struct radeon_bo *robj;
if (rfb == NULL || rfb->obj == NULL) {
@@ -1551,10 +1551,12 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon)
/* reset hpd state */
radeon_hpd_init(rdev);
/* blat the mode back in */
- drm_helper_resume_force_mode(dev);
- /* turn on display hw */
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+ if (fbcon) {
+ drm_helper_resume_force_mode(dev);
+ /* turn on display hw */
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+ }
}
drm_kms_helper_poll_enable(dev);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index fbd8b930f2be..386cfa4c194d 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -34,6 +34,8 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_edid.h>
+#include <linux/gcd.h>
+
static void avivo_crtc_load_lut(struct drm_crtc *crtc)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
@@ -369,7 +371,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
work->event = event;
work->rdev = rdev;
work->crtc_id = radeon_crtc->crtc_id;
- old_radeon_fb = to_radeon_framebuffer(crtc->fb);
+ old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
new_radeon_fb = to_radeon_framebuffer(fb);
/* schedule unpin of the old buffer */
obj = old_radeon_fb->obj;
@@ -460,7 +462,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
spin_unlock_irqrestore(&dev->event_lock, flags);
/* update crtc fb */
- crtc->fb = fb;
+ crtc->primary->fb = fb;
r = drm_vblank_get(dev, radeon_crtc->crtc_id);
if (r) {
@@ -792,6 +794,7 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
if (radeon_connector->edid) {
drm_mode_connector_update_edid_property(&radeon_connector->base, radeon_connector->edid);
ret = drm_add_edid_modes(&radeon_connector->base, radeon_connector->edid);
+ drm_edid_to_eld(&radeon_connector->base, radeon_connector->edid);
return ret;
}
drm_mode_connector_update_edid_property(&radeon_connector->base, NULL);
@@ -799,66 +802,57 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
}
/* avivo */
-static void avivo_get_fb_div(struct radeon_pll *pll,
- u32 target_clock,
- u32 post_div,
- u32 ref_div,
- u32 *fb_div,
- u32 *frac_fb_div)
-{
- u32 tmp = post_div * ref_div;
- tmp *= target_clock;
- *fb_div = tmp / pll->reference_freq;
- *frac_fb_div = tmp % pll->reference_freq;
-
- if (*fb_div > pll->max_feedback_div)
- *fb_div = pll->max_feedback_div;
- else if (*fb_div < pll->min_feedback_div)
- *fb_div = pll->min_feedback_div;
-}
-
-static u32 avivo_get_post_div(struct radeon_pll *pll,
- u32 target_clock)
+/**
+ * avivo_reduce_ratio - fractional number reduction
+ *
+ * @nom: nominator
+ * @den: denominator
+ * @nom_min: minimum value for nominator
+ * @den_min: minimum value for denominator
+ *
+ * Find the greatest common divisor and apply it on both nominator and
+ * denominator, but make nominator and denominator are at least as large
+ * as their minimum values.
+ */
+static void avivo_reduce_ratio(unsigned *nom, unsigned *den,
+ unsigned nom_min, unsigned den_min)
{
- u32 vco, post_div, tmp;
-
- if (pll->flags & RADEON_PLL_USE_POST_DIV)
- return pll->post_div;
-
- if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) {
- if (pll->flags & RADEON_PLL_IS_LCD)
- vco = pll->lcd_pll_out_min;
- else
- vco = pll->pll_out_min;
- } else {
- if (pll->flags & RADEON_PLL_IS_LCD)
- vco = pll->lcd_pll_out_max;
- else
- vco = pll->pll_out_max;
+ unsigned tmp;
+
+ /* reduce the numbers to a simpler ratio */
+ tmp = gcd(*nom, *den);
+ *nom /= tmp;
+ *den /= tmp;
+
+ /* make sure nominator is large enough */
+ if (*nom < nom_min) {
+ tmp = (nom_min + *nom - 1) / *nom;
+ *nom *= tmp;
+ *den *= tmp;
}
- post_div = vco / target_clock;
- tmp = vco % target_clock;
-
- if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP) {
- if (tmp)
- post_div++;
- } else {
- if (!tmp)
- post_div--;
+ /* make sure the denominator is large enough */
+ if (*den < den_min) {
+ tmp = (den_min + *den - 1) / *den;
+ *nom *= tmp;
+ *den *= tmp;
}
-
- if (post_div > pll->max_post_div)
- post_div = pll->max_post_div;
- else if (post_div < pll->min_post_div)
- post_div = pll->min_post_div;
-
- return post_div;
}
-#define MAX_TOLERANCE 10
-
+/**
+ * radeon_compute_pll_avivo - compute PLL paramaters
+ *
+ * @pll: information about the PLL
+ * @dot_clock_p: resulting pixel clock
+ * fb_div_p: resulting feedback divider
+ * frac_fb_div_p: fractional part of the feedback divider
+ * ref_div_p: resulting reference divider
+ * post_div_p: resulting reference divider
+ *
+ * Try to calculate the PLL parameters to generate the given frequency:
+ * dot_clock = (ref_freq * feedback_div) / (ref_div * post_div)
+ */
void radeon_compute_pll_avivo(struct radeon_pll *pll,
u32 freq,
u32 *dot_clock_p,
@@ -867,53 +861,123 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll,
u32 *ref_div_p,
u32 *post_div_p)
{
- u32 target_clock = freq / 10;
- u32 post_div = avivo_get_post_div(pll, target_clock);
- u32 ref_div = pll->min_ref_div;
- u32 fb_div = 0, frac_fb_div = 0, tmp;
+ unsigned fb_div_min, fb_div_max, fb_div;
+ unsigned post_div_min, post_div_max, post_div;
+ unsigned ref_div_min, ref_div_max, ref_div;
+ unsigned post_div_best, diff_best;
+ unsigned nom, den, tmp;
- if (pll->flags & RADEON_PLL_USE_REF_DIV)
- ref_div = pll->reference_div;
+ /* determine allowed feedback divider range */
+ fb_div_min = pll->min_feedback_div;
+ fb_div_max = pll->max_feedback_div;
if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
- avivo_get_fb_div(pll, target_clock, post_div, ref_div, &fb_div, &frac_fb_div);
- frac_fb_div = (100 * frac_fb_div) / pll->reference_freq;
- if (frac_fb_div >= 5) {
- frac_fb_div -= 5;
- frac_fb_div = frac_fb_div / 10;
- frac_fb_div++;
+ fb_div_min *= 10;
+ fb_div_max *= 10;
+ }
+
+ /* determine allowed ref divider range */
+ if (pll->flags & RADEON_PLL_USE_REF_DIV)
+ ref_div_min = pll->reference_div;
+ else
+ ref_div_min = pll->min_ref_div;
+ ref_div_max = pll->max_ref_div;
+
+ /* determine allowed post divider range */
+ if (pll->flags & RADEON_PLL_USE_POST_DIV) {
+ post_div_min = pll->post_div;
+ post_div_max = pll->post_div;
+ } else {
+ unsigned target_clock = freq / 10;
+ unsigned vco_min, vco_max;
+
+ if (pll->flags & RADEON_PLL_IS_LCD) {
+ vco_min = pll->lcd_pll_out_min;
+ vco_max = pll->lcd_pll_out_max;
+ } else {
+ vco_min = pll->pll_out_min;
+ vco_max = pll->pll_out_max;
}
- if (frac_fb_div >= 10) {
- fb_div++;
- frac_fb_div = 0;
+
+ post_div_min = vco_min / target_clock;
+ if ((target_clock * post_div_min) < vco_min)
+ ++post_div_min;
+ if (post_div_min < pll->min_post_div)
+ post_div_min = pll->min_post_div;
+
+ post_div_max = vco_max / target_clock;
+ if ((target_clock * post_div_max) > vco_max)
+ --post_div_max;
+ if (post_div_max > pll->max_post_div)
+ post_div_max = pll->max_post_div;
+ }
+
+ /* represent the searched ratio as fractional number */
+ nom = pll->flags & RADEON_PLL_USE_FRAC_FB_DIV ? freq : freq / 10;
+ den = pll->reference_freq;
+
+ /* reduce the numbers to a simpler ratio */
+ avivo_reduce_ratio(&nom, &den, fb_div_min, post_div_min);
+
+ /* now search for a post divider */
+ if (pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP)
+ post_div_best = post_div_min;
+ else
+ post_div_best = post_div_max;
+ diff_best = ~0;
+
+ for (post_div = post_div_min; post_div <= post_div_max; ++post_div) {
+ unsigned diff = abs(den - den / post_div * post_div);
+ if (diff < diff_best || (diff == diff_best &&
+ !(pll->flags & RADEON_PLL_PREFER_MINM_OVER_MAXP))) {
+
+ post_div_best = post_div;
+ diff_best = diff;
}
+ }
+ post_div = post_div_best;
+
+ /* get matching reference and feedback divider */
+ ref_div = max(den / post_div, 1u);
+ fb_div = nom;
+
+ /* we're almost done, but reference and feedback
+ divider might be to large now */
+
+ tmp = ref_div;
+
+ if (fb_div > fb_div_max) {
+ ref_div = ref_div * fb_div_max / fb_div;
+ fb_div = fb_div_max;
+ }
+
+ if (ref_div > ref_div_max) {
+ ref_div = ref_div_max;
+ fb_div = nom * ref_div_max / tmp;
+ }
+
+ /* reduce the numbers to a simpler ratio once more */
+ /* this also makes sure that the reference divider is large enough */
+ avivo_reduce_ratio(&fb_div, &ref_div, fb_div_min, ref_div_min);
+
+ /* and finally save the result */
+ if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) {
+ *fb_div_p = fb_div / 10;
+ *frac_fb_div_p = fb_div % 10;
} else {
- while (ref_div <= pll->max_ref_div) {
- avivo_get_fb_div(pll, target_clock, post_div, ref_div,
- &fb_div, &frac_fb_div);
- if (frac_fb_div >= (pll->reference_freq / 2))
- fb_div++;
- frac_fb_div = 0;
- tmp = (pll->reference_freq * fb_div) / (post_div * ref_div);
- tmp = (tmp * 10000) / target_clock;
-
- if (tmp > (10000 + MAX_TOLERANCE))
- ref_div++;
- else if (tmp >= (10000 - MAX_TOLERANCE))
- break;
- else
- ref_div++;
- }
+ *fb_div_p = fb_div;
+ *frac_fb_div_p = 0;
}
- *dot_clock_p = ((pll->reference_freq * fb_div * 10) + (pll->reference_freq * frac_fb_div)) /
- (ref_div * post_div * 10);
- *fb_div_p = fb_div;
- *frac_fb_div_p = frac_fb_div;
+ *dot_clock_p = ((pll->reference_freq * *fb_div_p * 10) +
+ (pll->reference_freq * *frac_fb_div_p)) /
+ (ref_div * post_div * 10);
*ref_div_p = ref_div;
*post_div_p = post_div;
- DRM_DEBUG_KMS("%d, pll dividers - fb: %d.%d ref: %d, post %d\n",
- *dot_clock_p, fb_div, frac_fb_div, ref_div, post_div);
+
+ DRM_DEBUG_KMS("%d - %d, pll dividers - fb: %d.%d ref: %d, post %d\n",
+ freq, *dot_clock_p, *fb_div_p, *frac_fb_div_p,
+ ref_div, post_div);
}
/* pre-avivo */
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 2dc2cc48f92b..d0eba48dd74e 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -79,7 +79,8 @@
* 2.35.0 - Add CIK macrotile mode array query
* 2.36.0 - Fix CIK DCE tiling setup
* 2.37.0 - allow GS ring setup on r6xx/r7xx
- * 2.38.0 - RADEON_GEM_OP (GET_INITIAL_DOMAIN, SET_INITIAL_DOMAIN)
+ * 2.38.0 - RADEON_GEM_OP (GET_INITIAL_DOMAIN, SET_INITIAL_DOMAIN),
+ * CIK: 1D and linear tiling modes contain valid PIPE_CONFIG
*/
#define KMS_DRIVER_MAJOR 2
#define KMS_DRIVER_MINOR 38
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 6f1dfac17507..3e49342a20e6 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -575,10 +575,6 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
if (r)
return r;
- r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
- if (r)
- return r;
-
/* map the ib pool buffer read only into
* virtual address space */
bo_va = radeon_vm_bo_add(rdev, &fpriv->vm,
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
index 0b158f98d287..cafb1ccf2ec3 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
@@ -385,7 +385,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
DRM_DEBUG_KMS("\n");
/* no fb bound */
- if (!atomic && !crtc->fb) {
+ if (!atomic && !crtc->primary->fb) {
DRM_DEBUG_KMS("No FB bound\n");
return 0;
}
@@ -395,8 +395,8 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc,
target_fb = fb;
}
else {
- radeon_fb = to_radeon_framebuffer(crtc->fb);
- target_fb = crtc->fb;
+ radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
+ target_fb = crtc->primary->fb;
}
switch (target_fb->bits_per_pixel) {
@@ -444,7 +444,7 @@ retry:
* We don't shutdown the display controller because new buffer
* will end up in same spot.
*/
- if (!atomic && fb && fb != crtc->fb) {
+ if (!atomic && fb && fb != crtc->primary->fb) {
struct radeon_bo *old_rbo;
unsigned long nsize, osize;
@@ -555,7 +555,7 @@ retry:
WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset);
WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
- if (!atomic && fb && fb != crtc->fb) {
+ if (!atomic && fb && fb != crtc->primary->fb) {
radeon_fb = to_radeon_framebuffer(fb);
rbo = gem_to_radeon_bo(radeon_fb->obj);
r = radeon_bo_reserve(rbo, false);
@@ -599,7 +599,7 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
}
}
- switch (crtc->fb->bits_per_pixel) {
+ switch (crtc->primary->fb->bits_per_pixel) {
case 8:
format = 2;
break;
@@ -1087,12 +1087,12 @@ static void radeon_crtc_commit(struct drm_crtc *crtc)
static void radeon_crtc_disable(struct drm_crtc *crtc)
{
radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
- if (crtc->fb) {
+ if (crtc->primary->fb) {
int r;
struct radeon_framebuffer *radeon_fb;
struct radeon_bo *rbo;
- radeon_fb = to_radeon_framebuffer(crtc->fb);
+ radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
rbo = gem_to_radeon_bo(radeon_fb->obj);
r = radeon_bo_reserve(rbo, false);
if (unlikely(r))
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 402dbe32c234..832d9fa1a4c4 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -192,6 +192,7 @@ struct radeon_i2c_chan {
struct i2c_algo_dp_aux_data dp;
} algo;
struct radeon_i2c_bus_rec rec;
+ struct drm_dp_aux aux;
};
/* mostly for macs, but really any system without connector tables */
@@ -690,6 +691,9 @@ extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector);
extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector);
extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
struct drm_connector *connector);
+extern void radeon_dp_set_rx_power_state(struct drm_connector *connector,
+ u8 power_state);
+extern void radeon_dp_aux_init(struct radeon_connector *radeon_connector);
extern void atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mode);
extern void radeon_atom_encoder_init(struct radeon_device *rdev);
extern void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 1375ff85b08a..19bec0dbfa38 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -104,7 +104,7 @@ bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo)
void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
{
- u32 c = 0;
+ u32 c = 0, i;
rbo->placement.fpfn = 0;
rbo->placement.lpfn = 0;
@@ -131,6 +131,17 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
rbo->placement.num_placement = c;
rbo->placement.num_busy_placement = c;
+
+ /*
+ * Use two-ended allocation depending on the buffer size to
+ * improve fragmentation quality.
+ * 512kb was measured as the most optimal number.
+ */
+ if (rbo->tbo.mem.size > 512 * 1024) {
+ for (i = 0; i < c; i++) {
+ rbo->placements[i] |= TTM_PL_FLAG_TOPDOWN;
+ }
+ }
}
int radeon_bo_create(struct radeon_device *rdev,
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 8b0dfdd23793..f8050f5429e2 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -262,6 +262,7 @@ int radeon_ib_ring_tests(struct radeon_device *rdev)
r = radeon_ib_test(rdev, i, ring);
if (r) {
ring->ready = false;
+ rdev->needs_reset = false;
if (i == RADEON_RING_TYPE_GFX_INDEX) {
/* oh, oh, that's really bad */