162143Sarchie/* 262143Sarchie * Copyright 2007-8 Advanced Micro Devices, Inc. 362143Sarchie * Copyright 2008 Red Hat Inc. 4139823Simp * 5139823Simp * Permission is hereby granted, free of charge, to any person obtaining a 6139823Simp * copy of this software and associated documentation files (the "Software"), 762143Sarchie * to deal in the Software without restriction, including without limitation 862143Sarchie * the rights to use, copy, modify, merge, publish, distribute, sublicense, 962143Sarchie * and/or sell copies of the Software, and to permit persons to whom the 1062143Sarchie * Software is furnished to do so, subject to the following conditions: 1162143Sarchie * 1262143Sarchie * The above copyright notice and this permission notice shall be included in 1362143Sarchie * all copies or substantial portions of the Software. 1462143Sarchie * 1562143Sarchie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1662143Sarchie * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1762143Sarchie * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1862143Sarchie * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 1962143Sarchie * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2062143Sarchie * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2162143Sarchie * OTHER DEALINGS IN THE SOFTWARE. 2262143Sarchie * 2362143Sarchie * Authors: Dave Airlie 2462143Sarchie * Alex Deucher 2562143Sarchie * Jerome Glisse 2662143Sarchie */ 2762143Sarchie 2862143Sarchie#include <sys/cdefs.h> 2962143Sarchie__FBSDID("$FreeBSD: releng/10.3/sys/dev/drm2/radeon/atombios_dp.c 282199 2015-04-28 19:35:05Z dumbbell $"); 3062143Sarchie 3162143Sarchie#include <dev/drm2/drmP.h> 3262143Sarchie#include <dev/drm2/radeon/radeon_drm.h> 3362143Sarchie#include "radeon.h" 3462143Sarchie 3562143Sarchie#include "atom.h" 3662143Sarchie#include "atom-bits.h" 3762143Sarchie#include <dev/drm2/drm_dp_helper.h> 3862143Sarchie 3962143Sarchie/* move these to drm_dp_helper.c/h */ 4062143Sarchie#define DP_LINK_CONFIGURATION_SIZE 9 4162143Sarchie#define DP_DPCD_SIZE DP_RECEIVER_CAP_SIZE 4262143Sarchie 4362143Sarchiestatic char *voltage_names[] = { 4462143Sarchie "0.4V", "0.6V", "0.8V", "1.2V" 4562143Sarchie}; 4662143Sarchiestatic char *pre_emph_names[] = { 4762143Sarchie "0dB", "3.5dB", "6dB", "9.5dB" 4862143Sarchie}; 4962143Sarchie 5062143Sarchie/***** radeon AUX functions *****/ 5162143Sarchieunion aux_channel_transaction { 5262143Sarchie PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1; 5362143Sarchie PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2; 5462143Sarchie}; 5562143Sarchie 5662143Sarchiestatic int radeon_process_aux_ch(struct radeon_i2c_chan *chan, 5762143Sarchie u8 *send, int send_bytes, 58136428Sglebius u8 *recv, int recv_size, 5962143Sarchie u8 delay, u8 *ack) 60141721Sglebius{ 6162143Sarchie struct drm_device *dev = chan->dev; 6262143Sarchie struct radeon_device *rdev = dev->dev_private; 6362143Sarchie union aux_channel_transaction args; 6462143Sarchie int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); 6562143Sarchie unsigned char *base; 6662143Sarchie int recv_bytes; 6762143Sarchie 6862143Sarchie memset(&args, 0, sizeof(args)); 6962143Sarchie 7062143Sarchie base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1); 71147256Sbrooks 72147256Sbrooks memcpy(base, send, send_bytes); 7362143Sarchie 74126035Spjd args.v1.lpAuxRequest = 0 + 4; 75126035Spjd args.v1.lpDataOut = 16 + 4; 76126035Spjd args.v1.ucDataOutLen = 0; 77126035Spjd args.v1.ucChannelID = chan->rec.i2c_id; 78129281Sarchie args.v1.ucDelay = delay / 10; 79129281Sarchie if (ASIC_IS_DCE4(rdev)) 80126035Spjd args.v2.ucHPD_ID = chan->rec.hpd; 81126035Spjd 82126035Spjd atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 83126035Spjd 84126035Spjd *ack = args.v1.ucReplyStatus; 85126035Spjd 8662143Sarchie /* timeout */ 87106933Ssam if (args.v1.ucReplyStatus == 1) { 88106933Ssam DRM_DEBUG_KMS("dp_aux_ch timeout\n"); 89106933Ssam return -ETIMEDOUT; 90106933Ssam } 91106933Ssam 92106933Ssam /* flags not zero */ 93139903Sglebius if (args.v1.ucReplyStatus == 2) { 94106933Ssam DRM_DEBUG_KMS("dp_aux_ch flags not zero\n"); 9562143Sarchie return -EBUSY; 96106933Ssam } 97106933Ssam 9862143Sarchie /* error */ 9962143Sarchie if (args.v1.ucReplyStatus == 3) { 10062143Sarchie DRM_DEBUG_KMS("dp_aux_ch error\n"); 101139903Sglebius return -EIO; 10262143Sarchie } 10362143Sarchie 104131155Sjulian recv_bytes = args.v1.ucDataOutLen; 105131155Sjulian if (recv_bytes > recv_size) 10662143Sarchie recv_bytes = recv_size; 10762143Sarchie 10862143Sarchie if (recv && recv_size) 10962143Sarchie memcpy(recv, base + 16, recv_bytes); 11070700Sjulian 11162143Sarchie return recv_bytes; 11269922Sjulian} 11362143Sarchie 11462143Sarchiestatic int radeon_dp_aux_native_write(struct radeon_connector *radeon_connector, 11562143Sarchie u16 address, u8 *send, u8 send_bytes, u8 delay) 11662143Sarchie{ 11762143Sarchie struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; 11862143Sarchie int ret; 11962143Sarchie u8 msg[20]; 12062143Sarchie int msg_bytes = send_bytes + 4; 12162143Sarchie u8 ack; 12262143Sarchie unsigned retry; 12362143Sarchie 12462143Sarchie if (send_bytes > 16) 12562143Sarchie return -1; 12662143Sarchie 12762143Sarchie msg[0] = address; 12862143Sarchie msg[1] = address >> 8; 12962143Sarchie msg[2] = AUX_NATIVE_WRITE << 4; 13062143Sarchie msg[3] = (msg_bytes << 4) | (send_bytes - 1); 13162143Sarchie memcpy(&msg[4], send, send_bytes); 13262143Sarchie 13364358Sarchie for (retry = 0; retry < 4; retry++) { 13464358Sarchie ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, 13564358Sarchie msg, msg_bytes, NULL, 0, delay, &ack); 13664358Sarchie if (ret == -EBUSY) 13764358Sarchie continue; 138123600Sru else if (ret < 0) 13964358Sarchie return ret; 14064358Sarchie if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) 14164358Sarchie return send_bytes; 14264653Sarchie else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) 14364653Sarchie udelay(400); 144123600Sru else 14564653Sarchie return -EIO; 14664653Sarchie } 14764653Sarchie 14864653Sarchie return -EIO; 14964653Sarchie} 15064653Sarchie 15164653Sarchiestatic int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector, 15264653Sarchie u16 address, u8 *recv, int recv_bytes, u8 delay) 15364653Sarchie{ 15464653Sarchie struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; 15564653Sarchie u8 msg[4]; 15664358Sarchie int msg_bytes = 4; 15764358Sarchie u8 ack; 15864358Sarchie int ret; 15964358Sarchie unsigned retry; 16064358Sarchie 16164358Sarchie msg[0] = address; 16264358Sarchie msg[1] = address >> 8; 16364653Sarchie msg[2] = AUX_NATIVE_READ << 4; 16464653Sarchie msg[3] = (msg_bytes << 4) | (recv_bytes - 1); 16564653Sarchie 16664653Sarchie for (retry = 0; retry < 4; retry++) { 16764653Sarchie ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, 16864653Sarchie msg, msg_bytes, recv, recv_bytes, delay, &ack); 16964653Sarchie if (ret == -EBUSY) 17064358Sarchie continue; 17164358Sarchie else if (ret < 0) 17264358Sarchie return ret; 17364358Sarchie if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) 17464358Sarchie return ret; 175141721Sglebius else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) 176141721Sglebius udelay(400); 177141721Sglebius else if (ret == 0) 178141721Sglebius return -EPROTO; 179141721Sglebius else 180141721Sglebius return -EIO; 181141721Sglebius } 182141721Sglebius 183141721Sglebius return -EIO; 184141721Sglebius} 185141721Sglebius 186141721Sglebiusstatic void radeon_write_dpcd_reg(struct radeon_connector *radeon_connector, 187141721Sglebius u16 reg, u8 val) 188141721Sglebius{ 189141910Sglebius radeon_dp_aux_native_write(radeon_connector, reg, &val, 1, 0); 190141910Sglebius} 191141910Sglebius 192141910Sglebiusstatic u8 radeon_read_dpcd_reg(struct radeon_connector *radeon_connector, 193141910Sglebius u16 reg) 194141910Sglebius{ 195141910Sglebius u8 val = 0; 19662143Sarchie 19762143Sarchie radeon_dp_aux_native_read(radeon_connector, reg, &val, 1, 0); 19862143Sarchie 19962143Sarchie return val; 200129823Sjulian} 201129823Sjulian 202129823Sjulianint radeon_dp_i2c_aux_ch(device_t dev, int mode, u8 write_byte, u8 *read_byte) 203129823Sjulian{ 204129823Sjulian struct iic_dp_aux_data *algo_data = device_get_softc(dev); 205129823Sjulian struct radeon_i2c_chan *auxch = algo_data->priv; 206129823Sjulian u16 address = algo_data->address; 207129823Sjulian u8 msg[5]; 208129823Sjulian u8 reply[2]; 209129823Sjulian unsigned retry; 210129823Sjulian int msg_bytes; 21162143Sarchie int reply_bytes = 1; 21262143Sarchie int ret; 21362143Sarchie u8 ack; 21462143Sarchie 21562143Sarchie /* Set up the command byte */ 21662143Sarchie if (mode & MODE_I2C_READ) 21762143Sarchie msg[2] = AUX_I2C_READ << 4; 21862143Sarchie else 21962143Sarchie msg[2] = AUX_I2C_WRITE << 4; 22062143Sarchie 22162143Sarchie if (!(mode & MODE_I2C_STOP)) 22262143Sarchie msg[2] |= AUX_I2C_MOT << 4; 22362143Sarchie 22462143Sarchie msg[0] = address; 225106933Ssam msg[1] = address >> 8; 22662143Sarchie 22762143Sarchie switch (mode) { 22870784Sjulian case MODE_I2C_WRITE: 229129281Sarchie msg_bytes = 5; 23062143Sarchie msg[3] = msg_bytes << 4; 23162143Sarchie msg[4] = write_byte; 232129281Sarchie break; 23362143Sarchie case MODE_I2C_READ: 234129281Sarchie msg_bytes = 4; 23562143Sarchie msg[3] = msg_bytes << 4; 23662143Sarchie break; 23762143Sarchie default: 23862143Sarchie msg_bytes = 4; 23962143Sarchie msg[3] = 3 << 4; 24062143Sarchie break; 24162143Sarchie } 24262143Sarchie 24362143Sarchie for (retry = 0; retry < 4; retry++) { 244106933Ssam ret = radeon_process_aux_ch(auxch, 24562143Sarchie msg, msg_bytes, reply, reply_bytes, 0, &ack); 24662143Sarchie if (ret == -EBUSY) 24770784Sjulian continue; 248129281Sarchie else if (ret < 0) { 24962143Sarchie DRM_DEBUG_KMS("aux_ch failed %d\n", ret); 250129281Sarchie return ret; 251129281Sarchie } 25262143Sarchie 25362143Sarchie switch (ack & AUX_NATIVE_REPLY_MASK) { 25462143Sarchie case AUX_NATIVE_REPLY_ACK: 255129281Sarchie /* I2C-over-AUX Reply field is only valid 25662143Sarchie * when paired with AUX ACK. 25762143Sarchie */ 25862143Sarchie break; 25962143Sarchie case AUX_NATIVE_REPLY_NACK: 26062143Sarchie DRM_DEBUG_KMS("aux_ch native nack\n"); 26162143Sarchie return -EREMOTEIO; 26262143Sarchie case AUX_NATIVE_REPLY_DEFER: 26362143Sarchie DRM_DEBUG_KMS("aux_ch native defer\n"); 26462143Sarchie udelay(400); 26562143Sarchie continue; 26670784Sjulian default: 26762143Sarchie DRM_ERROR("aux_ch invalid native reply 0x%02x\n", ack); 26862143Sarchie return -EREMOTEIO; 26962143Sarchie } 27062143Sarchie 27162143Sarchie switch (ack & AUX_I2C_REPLY_MASK) { 27262143Sarchie case AUX_I2C_REPLY_ACK: 27362143Sarchie if (mode == MODE_I2C_READ) 27470700Sjulian *read_byte = reply[0]; 27562143Sarchie return ret; 27662143Sarchie case AUX_I2C_REPLY_NACK: 27762143Sarchie DRM_DEBUG_KMS("aux_i2c nack\n"); 27862143Sarchie return -EREMOTEIO; 27962143Sarchie case AUX_I2C_REPLY_DEFER: 28062143Sarchie DRM_DEBUG_KMS("aux_i2c defer\n"); 28162143Sarchie udelay(400); 28262143Sarchie break; 28362143Sarchie default: 28462143Sarchie DRM_ERROR("aux_i2c invalid reply 0x%02x\n", ack); 28562143Sarchie return -EREMOTEIO; 28662143Sarchie } 28762143Sarchie } 28862143Sarchie 28987599Sobrien DRM_DEBUG_KMS("aux i2c too many retries, giving up\n"); 29062143Sarchie return -EREMOTEIO; 29162143Sarchie} 292121816Sbrooks 29362143Sarchie/***** general DP utility functions *****/ 29462143Sarchie 29562143Sarchie#define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200 29662143Sarchie#define DP_PRE_EMPHASIS_MAX DP_TRAIN_PRE_EMPHASIS_9_5 29768876Sdwmalone 29862143Sarchiestatic void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE], 29962143Sarchie int lane_count, 300121816Sbrooks u8 train_set[4]) 30170784Sjulian{ 30262143Sarchie u8 v = 0; 30362143Sarchie u8 p = 0; 30470784Sjulian int lane; 30562143Sarchie 306132780Skan for (lane = 0; lane < lane_count; lane++) { 30764358Sarchie u8 this_v = drm_dp_get_adjust_request_voltage(link_status, lane); 30890249Sarchie u8 this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane); 30962143Sarchie 31062143Sarchie DRM_DEBUG_KMS("requested signal parameters: lane %d voltage %s pre_emph %s\n", 311121816Sbrooks lane, 31262143Sarchie voltage_names[this_v >> DP_TRAIN_VOLTAGE_SWING_SHIFT], 313121816Sbrooks pre_emph_names[this_p >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); 31462143Sarchie 31562143Sarchie if (this_v > v) 31662143Sarchie v = this_v; 31762143Sarchie if (this_p > p) 31862143Sarchie p = this_p; 31971849Sjulian } 32062143Sarchie 32162143Sarchie if (v >= DP_VOLTAGE_MAX) 32262143Sarchie v |= DP_TRAIN_MAX_SWING_REACHED; 32362143Sarchie 32462143Sarchie if (p >= DP_PRE_EMPHASIS_MAX) 32571849Sjulian p |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; 32662143Sarchie 32771849Sjulian DRM_DEBUG_KMS("using signal parameters: voltage %s pre_emph %s\n", 32871849Sjulian voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK) >> DP_TRAIN_VOLTAGE_SWING_SHIFT], 32971849Sjulian pre_emph_names[(p & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); 33071849Sjulian 33171849Sjulian for (lane = 0; lane < 4; lane++) 33271849Sjulian train_set[lane] = v | p; 333132780Skan} 33471849Sjulian 33571849Sjulian/* convert bits per color to bits per pixel */ 33662143Sarchie/* get bpc from the EDID */ 33762143Sarchiestatic int convert_bpc_to_bpp(int bpc) 338139903Sglebius{ 339139903Sglebius if (bpc == 0) 340139903Sglebius return 24; 341139903Sglebius else 342139903Sglebius return bpc * 3; 343139903Sglebius} 344139903Sglebius 345139903Sglebius/* get the max pix clock supported by the link rate and lane num */ 346139903Sglebiusstatic int dp_get_max_dp_pix_clock(int link_rate, 347139903Sglebius int lane_num, 348139903Sglebius int bpp) 349139903Sglebius{ 350139903Sglebius return (link_rate * lane_num * 8) / bpp; 351139903Sglebius} 352139903Sglebius 353139903Sglebius/***** radeon specific DP functions *****/ 354139903Sglebius 355139903Sglebius/* First get the min lane# when low rate is used according to pixel clock 356139903Sglebius * (prefer low rate), second check max lane# supported by DP panel, 357139903Sglebius * if the max lane# < low rate lane# then use max lane# instead. 358139903Sglebius */ 359139903Sglebiusstatic int radeon_dp_get_dp_lane_number(struct drm_connector *connector, 360139903Sglebius u8 dpcd[DP_DPCD_SIZE], 361139903Sglebius int pix_clock) 362139903Sglebius{ 363139903Sglebius int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); 364139903Sglebius int max_link_rate = drm_dp_max_link_rate(dpcd); 36562143Sarchie int max_lane_num = drm_dp_max_lane_count(dpcd); 36662143Sarchie int lane_num; 36762143Sarchie int max_dp_pix_clock; 36862143Sarchie 36962143Sarchie for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) { 37062143Sarchie max_dp_pix_clock = dp_get_max_dp_pix_clock(max_link_rate, lane_num, bpp); 37162143Sarchie if (pix_clock <= max_dp_pix_clock) 37262143Sarchie break; 37362143Sarchie } 37462143Sarchie 37570700Sjulian return lane_num; 37662143Sarchie} 37762143Sarchie 37862143Sarchiestatic int radeon_dp_get_dp_link_clock(struct drm_connector *connector, 37962143Sarchie u8 dpcd[DP_DPCD_SIZE], 38062143Sarchie int pix_clock) 38162143Sarchie{ 38262143Sarchie int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); 38362143Sarchie int lane_num, max_pix_clock; 38462143Sarchie 38562143Sarchie if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == 38670784Sjulian ENCODER_OBJECT_ID_NUTMEG) 38762143Sarchie return 270000; 38862143Sarchie 38962143Sarchie lane_num = radeon_dp_get_dp_lane_number(connector, dpcd, pix_clock); 39062143Sarchie max_pix_clock = dp_get_max_dp_pix_clock(162000, lane_num, bpp); 39162143Sarchie if (pix_clock <= max_pix_clock) 39262143Sarchie return 162000; 39362143Sarchie max_pix_clock = dp_get_max_dp_pix_clock(270000, lane_num, bpp); 39462143Sarchie if (pix_clock <= max_pix_clock) 39562143Sarchie return 270000; 396129281Sarchie if (radeon_connector_is_dp12_capable(connector)) { 39762143Sarchie max_pix_clock = dp_get_max_dp_pix_clock(540000, lane_num, bpp); 398129281Sarchie if (pix_clock <= max_pix_clock) 399129281Sarchie return 540000; 400129281Sarchie } 40162143Sarchie 40262143Sarchie return drm_dp_max_link_rate(dpcd); 40362143Sarchie} 40462143Sarchie 40562143Sarchiestatic u8 radeon_dp_encoder_service(struct radeon_device *rdev, 40662143Sarchie int action, int dp_clock, 40790249Sarchie u8 ucconfig, u8 lane_num) 40890249Sarchie{ 40990249Sarchie DP_ENCODER_SERVICE_PARAMETERS args; 41090249Sarchie int index = GetIndexIntoMasterTable(COMMAND, DPEncoderService); 41162143Sarchie 41262143Sarchie memset(&args, 0, sizeof(args)); 41362143Sarchie args.ucLinkClock = dp_clock / 10; 41462143Sarchie args.ucConfig = ucconfig; 41562143Sarchie args.ucAction = action; 41662143Sarchie args.ucLaneNum = lane_num; 41769922Sjulian args.ucStatus = 0; 41869922Sjulian 41969922Sjulian atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 42069922Sjulian return args.ucStatus; 42169922Sjulian} 42269922Sjulian 42369922Sjulianu8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector) 42470784Sjulian{ 42569922Sjulian struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; 42669922Sjulian struct drm_device *dev = radeon_connector->base.dev; 42769922Sjulian struct radeon_device *rdev = dev->dev_private; 42869922Sjulian 42962143Sarchie return radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_GET_SINK_TYPE, 0, 43062143Sarchie dig_connector->dp_i2c_bus->rec.i2c_id, 0); 43162143Sarchie} 43270700Sjulian 43362143Sarchiestatic void radeon_dp_probe_oui(struct radeon_connector *radeon_connector) 43470784Sjulian{ 43562143Sarchie struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; 43662143Sarchie u8 buf[3]; 43770700Sjulian 43862143Sarchie if (!(dig_connector->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) 43970700Sjulian return; 44062143Sarchie 44162143Sarchie if (radeon_dp_aux_native_read(radeon_connector, DP_SINK_OUI, buf, 3, 0)) 44262143Sarchie DRM_DEBUG_KMS("Sink OUI: %02hhx%02hhx%02hhx\n", 44362143Sarchie buf[0], buf[1], buf[2]); 444141195Sru 44562143Sarchie if (radeon_dp_aux_native_read(radeon_connector, DP_BRANCH_OUI, buf, 3, 0)) 44662143Sarchie DRM_DEBUG_KMS("Branch OUI: %02hhx%02hhx%02hhx\n", 44762143Sarchie buf[0], buf[1], buf[2]); 44862143Sarchie} 449141195Sru 45062143Sarchiebool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) 45162143Sarchie{ 45262143Sarchie struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; 45362143Sarchie u8 msg[DP_DPCD_SIZE]; 45462143Sarchie int ret, i; 45562143Sarchie 45662143Sarchie ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, msg, 45762143Sarchie DP_DPCD_SIZE, 0); 45862143Sarchie if (ret > 0) { 45964358Sarchie memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); 46064358Sarchie DRM_DEBUG_KMS("DPCD: "); 46164358Sarchie for (i = 0; i < DP_DPCD_SIZE; i++) 46264358Sarchie DRM_DEBUG_KMS("%02x ", msg[i]); 46364358Sarchie DRM_DEBUG_KMS("\n"); 46464358Sarchie 465147256Sbrooks radeon_dp_probe_oui(radeon_connector); 46664358Sarchie 46764358Sarchie return true; 46864653Sarchie } 46964653Sarchie dig_connector->dpcd[0] = 0; 47064653Sarchie return false; 47164653Sarchie} 47264653Sarchie 47364653Sarchieint radeon_dp_get_panel_mode(struct drm_encoder *encoder, 47464653Sarchie struct drm_connector *connector) 47564653Sarchie{ 47664653Sarchie struct drm_device *dev = encoder->dev; 47764653Sarchie struct radeon_device *rdev = dev->dev_private; 47864653Sarchie struct radeon_connector *radeon_connector = to_radeon_connector(connector); 47964653Sarchie int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; 48064653Sarchie u16 dp_bridge = radeon_connector_encoder_get_dp_bridge_encoder_id(connector); 48164653Sarchie u8 tmp; 48264653Sarchie 48364653Sarchie if (!ASIC_IS_DCE4(rdev)) 48464653Sarchie return panel_mode; 48564653Sarchie 48664358Sarchie if (dp_bridge != ENCODER_OBJECT_ID_NONE) { 48764358Sarchie /* DP bridge chips */ 48864358Sarchie tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); 48964358Sarchie if (tmp & 1) 49064358Sarchie panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; 49164358Sarchie else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) || 49264358Sarchie (dp_bridge == ENCODER_OBJECT_ID_TRAVIS)) 49364358Sarchie panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; 49464358Sarchie else 49564358Sarchie panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; 49664358Sarchie } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { 49764358Sarchie /* eDP */ 49864358Sarchie tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); 49964358Sarchie if (tmp & 1) 50064358Sarchie panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; 50164358Sarchie } 50264653Sarchie 50364653Sarchie return panel_mode; 50464653Sarchie} 50564653Sarchie 50664653Sarchievoid radeon_dp_set_link_config(struct drm_connector *connector, 50764653Sarchie const struct drm_display_mode *mode) 50864653Sarchie{ 50964653Sarchie struct radeon_connector *radeon_connector = to_radeon_connector(connector); 51064358Sarchie struct radeon_connector_atom_dig *dig_connector; 51164358Sarchie 51264358Sarchie if (!radeon_connector->con_priv) 51364358Sarchie return; 51464358Sarchie dig_connector = radeon_connector->con_priv; 51564358Sarchie 51664358Sarchie if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || 517141721Sglebius (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { 518141721Sglebius dig_connector->dp_clock = 519141721Sglebius radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); 520141721Sglebius dig_connector->dp_lane_count = 521141721Sglebius radeon_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock); 522141721Sglebius } 523141721Sglebius} 524141721Sglebius 525141721Sglebiusint radeon_dp_mode_valid_helper(struct drm_connector *connector, 526141755Sglebius struct drm_display_mode *mode) 527141721Sglebius{ 528141721Sglebius struct radeon_connector *radeon_connector = to_radeon_connector(connector); 529141755Sglebius struct radeon_connector_atom_dig *dig_connector; 530141721Sglebius int dp_clock; 531141721Sglebius 532141721Sglebius if (!radeon_connector->con_priv) 533141721Sglebius return MODE_CLOCK_HIGH; 534141721Sglebius dig_connector = radeon_connector->con_priv; 535141721Sglebius 536141721Sglebius dp_clock = 537141721Sglebius radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); 538141721Sglebius 539141721Sglebius if ((dp_clock == 540000) && 540141721Sglebius (!radeon_connector_is_dp12_capable(connector))) 541141721Sglebius return MODE_CLOCK_HIGH; 542141721Sglebius 543141721Sglebius return MODE_OK; 544141755Sglebius} 545141721Sglebius 546141721Sglebiusstatic bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector, 547141755Sglebius u8 link_status[DP_LINK_STATUS_SIZE]) 548141721Sglebius{ 549141721Sglebius int ret; 550141721Sglebius ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, 551141721Sglebius link_status, DP_LINK_STATUS_SIZE, 100); 552141721Sglebius if (ret <= 0) { 553141721Sglebius return false; 554141910Sglebius } 555141910Sglebius 556141910Sglebius DRM_DEBUG_KMS("link status %*ph\n", 6, link_status); 55762143Sarchie return true; 55862143Sarchie} 55962143Sarchie 56062143Sarchiebool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector) 56162143Sarchie{ 56262143Sarchie u8 link_status[DP_LINK_STATUS_SIZE]; 56362143Sarchie struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; 56462143Sarchie 56562143Sarchie if (!radeon_dp_get_link_status(radeon_connector, link_status)) 56670700Sjulian return false; 56770700Sjulian if (drm_dp_channel_eq_ok(link_status, dig->dp_lane_count)) 56862143Sarchie return false; 56962143Sarchie return true; 57062143Sarchie} 57162143Sarchie 57262143Sarchiestruct radeon_dp_link_train_info { 57362143Sarchie struct radeon_device *rdev; 57462143Sarchie struct drm_encoder *encoder; 57570700Sjulian struct drm_connector *connector; 57662143Sarchie struct radeon_connector *radeon_connector; 57770784Sjulian int enc_id; 57870784Sjulian int dp_clock; 57970700Sjulian int dp_lane_count; 58062143Sarchie bool tp3_supported; 58170700Sjulian u8 dpcd[DP_RECEIVER_CAP_SIZE]; 58270700Sjulian u8 train_set[4]; 583131155Sjulian u8 link_status[DP_LINK_STATUS_SIZE]; 584129281Sarchie u8 tries; 585131155Sjulian bool use_dpencoder; 58662143Sarchie}; 587131155Sjulian 58887599Sobrienstatic void radeon_dp_update_vs_emph(struct radeon_dp_link_train_info *dp_info) 589129281Sarchie{ 590136312Sdes /* set the initial vs/emph on the source */ 59183366Sjulian atombios_dig_transmitter_setup(dp_info->encoder, 59262143Sarchie ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH, 59362143Sarchie 0, dp_info->train_set[0]); /* sets all lanes at once */ 59462143Sarchie 595129281Sarchie /* set the vs/emph on the sink */ 59662143Sarchie radeon_dp_aux_native_write(dp_info->radeon_connector, DP_TRAINING_LANE0_SET, 59762143Sarchie dp_info->train_set, dp_info->dp_lane_count, 0); 598131155Sjulian} 59962143Sarchie 60070784Sjulianstatic void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp) 60196265Sarchie{ 60262143Sarchie int rtp = 0; 60396265Sarchie 604148887Srwatson /* set training pattern on the source */ 605148887Srwatson if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) { 60696265Sarchie switch (tp) { 60796265Sarchie case DP_TRAINING_PATTERN_1: 60896265Sarchie rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1; 60996265Sarchie break; 61062143Sarchie case DP_TRAINING_PATTERN_2: 61162143Sarchie rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2; 61270700Sjulian break; 61362143Sarchie case DP_TRAINING_PATTERN_3: 61462143Sarchie rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3; 61562143Sarchie break; 61697896Sarchie } 61762143Sarchie atombios_dig_encoder_setup(dp_info->encoder, rtp, 0); 61862143Sarchie } else { 61964358Sarchie switch (tp) { 62064358Sarchie case DP_TRAINING_PATTERN_1: 62197896Sarchie rtp = 0; 62297896Sarchie break; 62397896Sarchie case DP_TRAINING_PATTERN_2: 62497896Sarchie rtp = 1; 62597896Sarchie break; 62697896Sarchie } 62797896Sarchie radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, 628147256Sbrooks dp_info->dp_clock, dp_info->enc_id, rtp); 62964358Sarchie } 63064358Sarchie 63164358Sarchie /* enable training pattern on the sink */ 63262678Sjulian radeon_write_dpcd_reg(dp_info->radeon_connector, DP_TRAINING_PATTERN_SET, tp); 63362143Sarchie} 63496265Sarchie 63562143Sarchiestatic int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info) 63662143Sarchie{ 63762143Sarchie struct radeon_encoder *radeon_encoder = to_radeon_encoder(dp_info->encoder); 63862143Sarchie struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 63962143Sarchie u8 tmp; 64062143Sarchie 641131155Sjulian /* power up the sink */ 64262143Sarchie if (dp_info->dpcd[0] >= 0x11) 64370784Sjulian radeon_write_dpcd_reg(dp_info->radeon_connector, 64462143Sarchie DP_SET_POWER, DP_SET_POWER_D0); 64566061Sjulian 64662143Sarchie /* possibly enable downspread on the sink */ 647136428Sglebius if (dp_info->dpcd[3] & 0x1) 648136428Sglebius radeon_write_dpcd_reg(dp_info->radeon_connector, 649136428Sglebius DP_DOWNSPREAD_CTRL, DP_SPREAD_AMP_0_5); 650136428Sglebius else 65162143Sarchie radeon_write_dpcd_reg(dp_info->radeon_connector, 652106933Ssam DP_DOWNSPREAD_CTRL, 0); 65362143Sarchie 65462143Sarchie if ((dp_info->connector->connector_type == DRM_MODE_CONNECTOR_eDP) && 65562143Sarchie (dig->panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) { 65662143Sarchie radeon_write_dpcd_reg(dp_info->radeon_connector, DP_EDP_CONFIGURATION_SET, 1); 65771849Sjulian } 65871849Sjulian 65962143Sarchie /* set the lane count on the sink */ 66062143Sarchie tmp = dp_info->dp_lane_count; 66170700Sjulian if (dp_info->dpcd[DP_DPCD_REV] >= 0x11 && 66262143Sarchie dp_info->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP) 66370784Sjulian tmp |= DP_LANE_COUNT_ENHANCED_FRAME_EN; 66464358Sarchie radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LANE_COUNT_SET, tmp); 665132464Sjulian 66671849Sjulian /* set the link rate on the sink */ 66771849Sjulian tmp = drm_dp_link_rate_to_bw_code(dp_info->dp_clock); 66871849Sjulian radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp); 66971849Sjulian 67071849Sjulian /* start training on the source */ 67171849Sjulian if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) 67271849Sjulian atombios_dig_encoder_setup(dp_info->encoder, 67371849Sjulian ATOM_ENCODER_CMD_DP_LINK_TRAINING_START, 0); 67471849Sjulian else 67571849Sjulian radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_START, 67670700Sjulian dp_info->dp_clock, dp_info->enc_id, 0); 677124269Sgreen 678124269Sgreen /* disable the training pattern on the sink */ 679124269Sgreen radeon_write_dpcd_reg(dp_info->radeon_connector, 680124269Sgreen DP_TRAINING_PATTERN_SET, 68164358Sarchie DP_TRAINING_PATTERN_DISABLE); 682132464Sjulian 683132464Sjulian return 0; 68462143Sarchie} 68562143Sarchie 68662143Sarchiestatic int radeon_dp_link_train_finish(struct radeon_dp_link_train_info *dp_info) 68762143Sarchie{ 68862143Sarchie udelay(400); 68962143Sarchie 69062143Sarchie /* disable the training pattern on the sink */ 69162143Sarchie radeon_write_dpcd_reg(dp_info->radeon_connector, 69262143Sarchie DP_TRAINING_PATTERN_SET, 69370784Sjulian DP_TRAINING_PATTERN_DISABLE); 69462143Sarchie 69590249Sarchie /* disable the training pattern on the source */ 69662143Sarchie if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) 697124270Sgreen atombios_dig_encoder_setup(dp_info->encoder, 698124270Sgreen ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE, 0); 699129281Sarchie else 70062143Sarchie radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_COMPLETE, 701129281Sarchie dp_info->dp_clock, dp_info->enc_id, 0); 702129281Sarchie 703129281Sarchie return 0; 70487599Sobrien} 70570784Sjulian 70670784Sjulianstatic int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info) 70770784Sjulian{ 70862143Sarchie bool clock_recovery; 70962143Sarchie u8 voltage; 71062143Sarchie int i; 71162143Sarchie 71262143Sarchie radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_1); 71362143Sarchie memset(dp_info->train_set, 0, 4); 71462143Sarchie radeon_dp_update_vs_emph(dp_info); 71562143Sarchie 71662143Sarchie udelay(400); 71762143Sarchie 71862143Sarchie /* clock recovery loop */ 71962143Sarchie clock_recovery = false; 72062143Sarchie dp_info->tries = 0; 72162143Sarchie voltage = 0xff; 72262143Sarchie while (1) { 72362143Sarchie drm_dp_link_train_clock_recovery_delay(dp_info->dpcd); 72462143Sarchie 72562143Sarchie if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { 72662143Sarchie DRM_ERROR("displayport link status failed\n"); 72762143Sarchie break; 72862143Sarchie } 72962143Sarchie 73062143Sarchie if (drm_dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { 73162143Sarchie clock_recovery = true; 73262143Sarchie break; 73362143Sarchie } 73462143Sarchie 73562143Sarchie for (i = 0; i < dp_info->dp_lane_count; i++) { 73662143Sarchie if ((dp_info->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) 73762143Sarchie break; 73862143Sarchie } 739139903Sglebius if (i == dp_info->dp_lane_count) { 74062143Sarchie DRM_ERROR("clock recovery reached max voltage\n"); 74162143Sarchie break; 742108172Shsu } 74362143Sarchie 74482586Sarchie if ((dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { 74582586Sarchie ++dp_info->tries; 74662143Sarchie if (dp_info->tries == 5) { 74762143Sarchie DRM_ERROR("clock recovery tried 5 times\n"); 748108172Shsu break; 74962143Sarchie } 75062143Sarchie } else 75162143Sarchie dp_info->tries = 0; 75262143Sarchie 75362143Sarchie voltage = dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; 75462143Sarchie 75562143Sarchie /* Compute new train_set as requested by sink */ 75662143Sarchie dp_get_adjust_train(dp_info->link_status, dp_info->dp_lane_count, dp_info->train_set); 75762143Sarchie 75862143Sarchie radeon_dp_update_vs_emph(dp_info); 75962143Sarchie } 76062143Sarchie if (!clock_recovery) { 76162143Sarchie DRM_ERROR("clock recovery failed\n"); 76262143Sarchie return -1; 76362143Sarchie } else { 76462143Sarchie DRM_DEBUG_KMS("clock recovery at voltage %d pre-emphasis %d\n", 76562143Sarchie dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, 76662143Sarchie (dp_info->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >> 767139903Sglebius DP_TRAIN_PRE_EMPHASIS_SHIFT); 76862143Sarchie return 0; 76962143Sarchie } 77062143Sarchie} 77162143Sarchie 77262143Sarchiestatic int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info) 77362143Sarchie{ 77462143Sarchie bool channel_eq; 77562143Sarchie 77662143Sarchie if (dp_info->tp3_supported) 77762143Sarchie radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_3); 778 else 779 radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_2); 780 781 /* channel equalization loop */ 782 dp_info->tries = 0; 783 channel_eq = false; 784 while (1) { 785 drm_dp_link_train_channel_eq_delay(dp_info->dpcd); 786 787 if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { 788 DRM_ERROR("displayport link status failed\n"); 789 break; 790 } 791 792 if (drm_dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { 793 channel_eq = true; 794 break; 795 } 796 797 /* Try 5 times */ 798 if (dp_info->tries > 5) { 799 DRM_ERROR("channel eq failed: 5 tries\n"); 800 break; 801 } 802 803 /* Compute new train_set as requested by sink */ 804 dp_get_adjust_train(dp_info->link_status, dp_info->dp_lane_count, dp_info->train_set); 805 806 radeon_dp_update_vs_emph(dp_info); 807 dp_info->tries++; 808 } 809 810 if (!channel_eq) { 811 DRM_ERROR("channel eq failed\n"); 812 return -1; 813 } else { 814 DRM_DEBUG_KMS("channel eq at voltage %d pre-emphasis %d\n", 815 dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, 816 (dp_info->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) 817 >> DP_TRAIN_PRE_EMPHASIS_SHIFT); 818 return 0; 819 } 820} 821 822void radeon_dp_link_train(struct drm_encoder *encoder, 823 struct drm_connector *connector) 824{ 825 struct drm_device *dev = encoder->dev; 826 struct radeon_device *rdev = dev->dev_private; 827 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 828 struct radeon_encoder_atom_dig *dig; 829 struct radeon_connector *radeon_connector; 830 struct radeon_connector_atom_dig *dig_connector; 831 struct radeon_dp_link_train_info dp_info; 832 int index; 833 u8 tmp, frev, crev; 834 835 if (!radeon_encoder->enc_priv) 836 return; 837 dig = radeon_encoder->enc_priv; 838 839 radeon_connector = to_radeon_connector(connector); 840 if (!radeon_connector->con_priv) 841 return; 842 dig_connector = radeon_connector->con_priv; 843 844 if ((dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_DISPLAYPORT) && 845 (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_eDP)) 846 return; 847 848 /* DPEncoderService newer than 1.1 can't program properly the 849 * training pattern. When facing such version use the 850 * DIGXEncoderControl (X== 1 | 2) 851 */ 852 dp_info.use_dpencoder = true; 853 index = GetIndexIntoMasterTable(COMMAND, DPEncoderService); 854 if (atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) { 855 if (crev > 1) { 856 dp_info.use_dpencoder = false; 857 } 858 } 859 860 dp_info.enc_id = 0; 861 if (dig->dig_encoder) 862 dp_info.enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER; 863 else 864 dp_info.enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER; 865 if (dig->linkb) 866 dp_info.enc_id |= ATOM_DP_CONFIG_LINK_B; 867 else 868 dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; 869 870 tmp = radeon_read_dpcd_reg(radeon_connector, DP_MAX_LANE_COUNT); 871 if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) 872 dp_info.tp3_supported = true; 873 else 874 dp_info.tp3_supported = false; 875 876 memcpy(dp_info.dpcd, dig_connector->dpcd, DP_RECEIVER_CAP_SIZE); 877 dp_info.rdev = rdev; 878 dp_info.encoder = encoder; 879 dp_info.connector = connector; 880 dp_info.radeon_connector = radeon_connector; 881 dp_info.dp_lane_count = dig_connector->dp_lane_count; 882 dp_info.dp_clock = dig_connector->dp_clock; 883 884 if (radeon_dp_link_train_init(&dp_info)) 885 goto done; 886 if (radeon_dp_link_train_cr(&dp_info)) 887 goto done; 888 if (radeon_dp_link_train_ce(&dp_info)) 889 goto done; 890done: 891 if (radeon_dp_link_train_finish(&dp_info)) 892 return; 893} 894