Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 2996 → Rev 2997

/drivers/video/drm/radeon/atombios_dp.c
22,14 → 22,15
*
* Authors: Dave Airlie
* Alex Deucher
* Jerome Glisse
*/
#include "drmP.h"
#include "radeon_drm.h"
#include <drm/drmP.h>
#include <drm/radeon_drm.h>
#include "radeon.h"
 
#include "atom.h"
#include "atom-bits.h"
#include "drm_dp_helper.h"
#include <drm/drm_dp_helper.h>
 
/* move these to drm_dp_helper.c/h */
#define DP_LINK_CONFIGURATION_SIZE 9
63,12 → 64,12
 
memset(&args, 0, sizeof(args));
 
base = (unsigned char *)rdev->mode_info.atom_context->scratch;
base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1);
 
memcpy(base, send, send_bytes);
 
args.v1.lpAuxRequest = 0;
args.v1.lpDataOut = 16;
args.v1.lpAuxRequest = 0 + 4;
args.v1.lpDataOut = 16 + 4;
args.v1.ucDataOutLen = 0;
args.v1.ucChannelID = chan->rec.i2c_id;
args.v1.ucDelay = delay / 10;
115,6 → 116,7
u8 msg[20];
int msg_bytes = send_bytes + 4;
u8 ack;
unsigned retry;
 
if (send_bytes > 16)
return -1;
125,13 → 127,15
msg[3] = (msg_bytes << 4) | (send_bytes - 1);
memcpy(&msg[4], send, send_bytes);
 
while (1) {
for (retry = 0; retry < 4; retry++) {
ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus,
msg, msg_bytes, NULL, 0, delay, &ack);
if (ret < 0)
if (ret == -EBUSY)
continue;
else if (ret < 0)
return ret;
if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
break;
return send_bytes;
else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
udelay(400);
else
138,7 → 142,7
return -EIO;
}
 
return send_bytes;
return -EIO;
}
 
static int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector,
149,6 → 153,7
int msg_bytes = 4;
u8 ack;
int ret;
unsigned retry;
 
msg[0] = address;
msg[1] = address >> 8;
155,20 → 160,24
msg[2] = AUX_NATIVE_READ << 4;
msg[3] = (msg_bytes << 4) | (recv_bytes - 1);
 
while (1) {
for (retry = 0; retry < 4; retry++) {
ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus,
msg, msg_bytes, recv, recv_bytes, delay, &ack);
if (ret == 0)
return -EPROTO;
if (ret < 0)
if (ret == -EBUSY)
continue;
else if (ret < 0)
return ret;
if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK)
return ret;
else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER)
udelay(400);
else if (ret == 0)
return -EPROTO;
else
return -EIO;
}
 
return -EIO;
}
 
static void radeon_write_dpcd_reg(struct radeon_connector *radeon_connector,
232,7 → 241,9
for (retry = 0; retry < 4; retry++) {
ret = radeon_process_aux_ch(auxch,
msg, msg_bytes, reply, reply_bytes, 0, &ack);
if (ret < 0) {
if (ret == -EBUSY)
continue;
else if (ret < 0) {
DRM_DEBUG_KMS("aux_ch failed %d\n", ret);
return ret;
}
273,7 → 284,7
}
}
 
DRM_ERROR("aux i2c too many retries, giving up\n");
DRM_DEBUG_KMS("aux i2c too many retries, giving up\n");
return -EREMOTEIO;
}
 
450,7 → 461,7
u8 dpcd[DP_DPCD_SIZE],
int pix_clock)
{
int bpp = convert_bpc_to_bpp(connector->display_info.bpc);
int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector));
int max_link_rate = dp_get_max_link_rate(dpcd);
int max_lane_num = dp_get_max_lane_number(dpcd);
int lane_num;
469,10 → 480,11
u8 dpcd[DP_DPCD_SIZE],
int pix_clock)
{
int bpp = convert_bpc_to_bpp(connector->display_info.bpc);
int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector));
int lane_num, max_pix_clock;
 
if (radeon_connector_encoder_is_dp_bridge(connector))
if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
ENCODER_OBJECT_ID_NUTMEG)
return 270000;
 
lane_num = radeon_dp_get_dp_lane_number(connector, dpcd, pix_clock);
519,6 → 531,23
dig_connector->dp_i2c_bus->rec.i2c_id, 0);
}
 
static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector)
{
struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
u8 buf[3];
 
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))
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))
DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n",
buf[0], buf[1], buf[2]);
}
 
bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector)
{
struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv;
532,6 → 561,9
for (i = 0; i < 8; i++)
DRM_DEBUG_KMS("%02x ", msg[i]);
DRM_DEBUG_KMS("\n");
 
radeon_dp_probe_oui(radeon_connector);
 
return true;
}
dig_connector->dpcd[0] = 0;
538,26 → 570,41
return false;
}
 
static void radeon_dp_set_panel_mode(struct drm_encoder *encoder,
int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
struct drm_connector *connector)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
u16 dp_bridge = radeon_connector_encoder_get_dp_bridge_encoder_id(connector);
u8 tmp;
 
if (!ASIC_IS_DCE4(rdev))
return;
return panel_mode;
 
if (radeon_connector_encoder_is_dp_bridge(connector))
if (dp_bridge != ENCODER_OBJECT_ID_NONE) {
/* DP bridge chips */
tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
if (tmp & 1)
panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) ||
(dp_bridge == ENCODER_OBJECT_ID_TRAVIS))
panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
else
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);
if (tmp & 1)
panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
}
 
atombios_dig_encoder_setup(encoder,
ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
panel_mode);
return panel_mode;
}
 
void radeon_dp_set_link_config(struct drm_connector *connector,
struct drm_display_mode *mode)
const struct drm_display_mode *mode)
{
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct radeon_connector_atom_dig *dig_connector;
603,16 → 650,25
ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS,
link_status, DP_LINK_STATUS_SIZE, 100);
if (ret <= 0) {
DRM_ERROR("displayport link status failed\n");
return false;
}
 
DRM_DEBUG_KMS("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]);
DRM_DEBUG_KMS("link status %*ph\n", 6, 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))
return false;
if (dp_channel_eq_ok(link_status, dig->dp_lane_count))
return false;
return true;
}
 
struct radeon_dp_link_train_info {
struct radeon_device *rdev;
struct drm_encoder *encoder;
679,6 → 735,8
 
static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(dp_info->encoder);
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
u8 tmp;
 
/* power up the sink */
694,11 → 752,15
radeon_write_dpcd_reg(dp_info->radeon_connector,
DP_DOWNSPREAD_CTRL, 0);
 
radeon_dp_set_panel_mode(dp_info->encoder, dp_info->connector);
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);
}
 
/* set the lane count on the sink */
tmp = dp_info->dp_lane_count;
if (dp_info->dpcd[0] >= 0x11)
if (dp_info->dpcd[DP_DPCD_REV] >= 0x11 &&
dp_info->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)
tmp |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LANE_COUNT_SET, tmp);
 
764,8 → 826,10
else
mdelay(dp_info->rd_interval * 4);
 
if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status))
if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) {
DRM_ERROR("displayport link status failed\n");
break;
}
 
if (dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) {
clock_recovery = true;
827,8 → 891,10
else
mdelay(dp_info->rd_interval * 4);
 
if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status))
if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) {
DRM_ERROR("displayport link status failed\n");
break;
}
 
if (dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) {
channel_eq = true;