1746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie/* 2746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * Copyright 2007-8 Advanced Micro Devices, Inc. 3746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * Copyright 2008 Red Hat Inc. 4746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * 5746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * Permission is hereby granted, free of charge, to any person obtaining a 6746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * copy of this software and associated documentation files (the "Software"), 7746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * to deal in the Software without restriction, including without limitation 8746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * and/or sell copies of the Software, and to permit persons to whom the 10746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * Software is furnished to do so, subject to the following conditions: 11746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * 12746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * The above copyright notice and this permission notice shall be included in 13746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * all copies or substantial portions of the Software. 14746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * 15746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * OTHER DEALINGS IN THE SOFTWARE. 22746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * 23746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * Authors: Dave Airlie 24746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie * Alex Deucher 25746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie */ 26746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie#include "drmP.h" 27746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie#include "radeon_drm.h" 28746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie#include "radeon.h" 29746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 30746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie#include "atom.h" 31746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie#include "atom-bits.h" 32746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie#include "drm_dp_helper.h" 33746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 34f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher/* move these to drm_dp_helper.c/h */ 355801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher#define DP_LINK_CONFIGURATION_SIZE 9 365801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher#define DP_LINK_STATUS_SIZE 6 375801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher#define DP_DPCD_SIZE 8 385801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 395801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucherstatic char *voltage_names[] = { 405801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher "0.4V", "0.6V", "0.8V", "1.2V" 415801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher}; 425801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucherstatic char *pre_emph_names[] = { 435801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher "0dB", "3.5dB", "6dB", "9.5dB" 445801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher}; 45f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher 46224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher/***** radeon AUX functions *****/ 47224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherunion aux_channel_transaction { 48224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1; 49224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2; 50f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher}; 51f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher 52224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic int radeon_process_aux_ch(struct radeon_i2c_chan *chan, 53224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 *send, int send_bytes, 54224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 *recv, int recv_size, 55224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 delay, u8 *ack) 56224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher{ 57224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct drm_device *dev = chan->dev; 58224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct radeon_device *rdev = dev->dev_private; 59224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher union aux_channel_transaction args; 60224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); 61224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher unsigned char *base; 62224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int recv_bytes; 63224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 64224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher memset(&args, 0, sizeof(args)); 65f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher 66224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher base = (unsigned char *)rdev->mode_info.atom_context->scratch; 67224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 68224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher memcpy(base, send, send_bytes); 69224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 70224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher args.v1.lpAuxRequest = 0; 71224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher args.v1.lpDataOut = 16; 72224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher args.v1.ucDataOutLen = 0; 73224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher args.v1.ucChannelID = chan->rec.i2c_id; 74224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher args.v1.ucDelay = delay / 10; 75224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (ASIC_IS_DCE4(rdev)) 76224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher args.v2.ucHPD_ID = chan->rec.hpd; 77224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 78224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 79224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 80224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher *ack = args.v1.ucReplyStatus; 81224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 82224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher /* timeout */ 83224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (args.v1.ucReplyStatus == 1) { 84224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DRM_DEBUG_KMS("dp_aux_ch timeout\n"); 85224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return -ETIMEDOUT; 86224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } 87224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 88224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher /* flags not zero */ 89224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (args.v1.ucReplyStatus == 2) { 90224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DRM_DEBUG_KMS("dp_aux_ch flags not zero\n"); 91224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return -EBUSY; 92224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } 93224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 94224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher /* error */ 95224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (args.v1.ucReplyStatus == 3) { 96224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DRM_DEBUG_KMS("dp_aux_ch error\n"); 97224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return -EIO; 98224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } 99224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 100224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher recv_bytes = args.v1.ucDataOutLen; 101224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (recv_bytes > recv_size) 102224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher recv_bytes = recv_size; 103224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 104224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (recv && recv_size) 105224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher memcpy(recv, base + 16, recv_bytes); 106224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 107224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return recv_bytes; 108224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher} 109224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 110224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic int radeon_dp_aux_native_write(struct radeon_connector *radeon_connector, 111224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u16 address, u8 *send, u8 send_bytes, u8 delay) 112f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher{ 113224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; 114224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int ret; 115224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 msg[20]; 116224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int msg_bytes = send_bytes + 4; 117224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 ack; 1186375bda073724ead7df08746866b724b1799a295Alex Deucher unsigned retry; 1195801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 120224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (send_bytes > 16) 121224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return -1; 1225801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 123224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg[0] = address; 124224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg[1] = address >> 8; 125224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg[2] = AUX_NATIVE_WRITE << 4; 126224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg[3] = (msg_bytes << 4) | (send_bytes - 1); 127224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher memcpy(&msg[4], send, send_bytes); 128f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher 1296375bda073724ead7df08746866b724b1799a295Alex Deucher for (retry = 0; retry < 4; retry++) { 130224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, 131224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg, msg_bytes, NULL, 0, delay, &ack); 1324f332844cc87c5f99c5300f788abbe8a8c731390Alex Deucher if (ret == -EBUSY) 1334f332844cc87c5f99c5300f788abbe8a8c731390Alex Deucher continue; 1344f332844cc87c5f99c5300f788abbe8a8c731390Alex Deucher else if (ret < 0) 135224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return ret; 136224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) 1376375bda073724ead7df08746866b724b1799a295Alex Deucher return send_bytes; 138224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) 139224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher udelay(400); 140224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher else 141224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return -EIO; 142f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher } 143f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher 1446375bda073724ead7df08746866b724b1799a295Alex Deucher return -EIO; 145f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher} 146f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher 147224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector, 148224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u16 address, u8 *recv, int recv_bytes, u8 delay) 149f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher{ 150224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; 151224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 msg[4]; 152224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int msg_bytes = 4; 153224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 ack; 154224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int ret; 1556375bda073724ead7df08746866b724b1799a295Alex Deucher unsigned retry; 1565801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 157224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg[0] = address; 158224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg[1] = address >> 8; 159224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg[2] = AUX_NATIVE_READ << 4; 160224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg[3] = (msg_bytes << 4) | (recv_bytes - 1); 1615801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 1626375bda073724ead7df08746866b724b1799a295Alex Deucher for (retry = 0; retry < 4; retry++) { 163224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, 164224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg, msg_bytes, recv, recv_bytes, delay, &ack); 1654f332844cc87c5f99c5300f788abbe8a8c731390Alex Deucher if (ret == -EBUSY) 1664f332844cc87c5f99c5300f788abbe8a8c731390Alex Deucher continue; 1674f332844cc87c5f99c5300f788abbe8a8c731390Alex Deucher else if (ret < 0) 168224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return ret; 169224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) 170224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return ret; 171224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) 172224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher udelay(400); 173109bc10d30f33e84f1d7289f0039e0c858ade82fAlex Deucher else if (ret == 0) 174109bc10d30f33e84f1d7289f0039e0c858ade82fAlex Deucher return -EPROTO; 175224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher else 176224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return -EIO; 177224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } 1786375bda073724ead7df08746866b724b1799a295Alex Deucher 1796375bda073724ead7df08746866b724b1799a295Alex Deucher return -EIO; 180224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher} 181f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher 182224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic void radeon_write_dpcd_reg(struct radeon_connector *radeon_connector, 183224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u16 reg, u8 val) 184224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher{ 185224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_dp_aux_native_write(radeon_connector, reg, &val, 1, 0); 186224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher} 187224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 188224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic u8 radeon_read_dpcd_reg(struct radeon_connector *radeon_connector, 189224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u16 reg) 190224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher{ 191224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 val = 0; 192224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 193224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_dp_aux_native_read(radeon_connector, reg, &val, 1, 0); 194224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 195224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return val; 196224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher} 197224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 198224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherint radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, 199224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 write_byte, u8 *read_byte) 200224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher{ 201224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; 202224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct radeon_i2c_chan *auxch = (struct radeon_i2c_chan *)adapter; 203224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u16 address = algo_data->address; 204224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 msg[5]; 205224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 reply[2]; 206224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher unsigned retry; 207224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int msg_bytes; 208224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int reply_bytes = 1; 209224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int ret; 210224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 ack; 211224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 212224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher /* Set up the command byte */ 213224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (mode & MODE_I2C_READ) 214224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg[2] = AUX_I2C_READ << 4; 215224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher else 216224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg[2] = AUX_I2C_WRITE << 4; 217224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 218224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (!(mode & MODE_I2C_STOP)) 219224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg[2] |= AUX_I2C_MOT << 4; 220224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 221224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg[0] = address; 222224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg[1] = address >> 8; 223224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 224224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher switch (mode) { 225224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case MODE_I2C_WRITE: 226224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg_bytes = 5; 227224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg[3] = msg_bytes << 4; 228224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg[4] = write_byte; 229224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher break; 230224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case MODE_I2C_READ: 231224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg_bytes = 4; 232224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg[3] = msg_bytes << 4; 233224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher break; 234f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher default: 235224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg_bytes = 4; 236224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg[3] = 3 << 4; 237f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher break; 238f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher } 239f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher 240224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher for (retry = 0; retry < 4; retry++) { 241224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher ret = radeon_process_aux_ch(auxch, 242224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher msg, msg_bytes, reply, reply_bytes, 0, &ack); 2434f332844cc87c5f99c5300f788abbe8a8c731390Alex Deucher if (ret == -EBUSY) 2444f332844cc87c5f99c5300f788abbe8a8c731390Alex Deucher continue; 2454f332844cc87c5f99c5300f788abbe8a8c731390Alex Deucher else if (ret < 0) { 246224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DRM_DEBUG_KMS("aux_ch failed %d\n", ret); 247224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return ret; 248224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } 249f92a8b6758bdc0f277c4f42aa7d736a205ac9dedAlex Deucher 250224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher switch (ack & AUX_NATIVE_REPLY_MASK) { 251224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case AUX_NATIVE_REPLY_ACK: 252224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher /* I2C-over-AUX Reply field is only valid 253224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher * when paired with AUX ACK. 254224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher */ 255224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher break; 256224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case AUX_NATIVE_REPLY_NACK: 257224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DRM_DEBUG_KMS("aux_ch native nack\n"); 258224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return -EREMOTEIO; 259224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case AUX_NATIVE_REPLY_DEFER: 260224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DRM_DEBUG_KMS("aux_ch native defer\n"); 261224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher udelay(400); 262224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher continue; 263224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher default: 264224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DRM_ERROR("aux_ch invalid native reply 0x%02x\n", ack); 265224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return -EREMOTEIO; 266224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } 2675801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 268224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher switch (ack & AUX_I2C_REPLY_MASK) { 269224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case AUX_I2C_REPLY_ACK: 270224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (mode == MODE_I2C_READ) 271224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher *read_byte = reply[0]; 272224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return ret; 273224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case AUX_I2C_REPLY_NACK: 274224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DRM_DEBUG_KMS("aux_i2c nack\n"); 275224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return -EREMOTEIO; 276224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case AUX_I2C_REPLY_DEFER: 277224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DRM_DEBUG_KMS("aux_i2c defer\n"); 278224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher udelay(400); 279224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher break; 280224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher default: 281224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DRM_ERROR("aux_i2c invalid reply 0x%02x\n", ack); 282224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return -EREMOTEIO; 283224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } 284224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } 2855801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 286091264f0bc12419560ac64fcef4567809d611658Alex Deucher DRM_DEBUG_KMS("aux i2c too many retries, giving up\n"); 287224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return -EREMOTEIO; 2885801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher} 2895801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 290224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher/***** general DP utility functions *****/ 291224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 2925801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucherstatic u8 dp_link_status(u8 link_status[DP_LINK_STATUS_SIZE], int r) 2935801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher{ 2945801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher return link_status[r - DP_LANE0_1_STATUS]; 2955801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher} 2965801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 2975801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucherstatic u8 dp_get_lane_status(u8 link_status[DP_LINK_STATUS_SIZE], 2985801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher int lane) 2995801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher{ 3005801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher int i = DP_LANE0_1_STATUS + (lane >> 1); 3015801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher int s = (lane & 1) * 4; 3025801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher u8 l = dp_link_status(link_status, i); 3035801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher return (l >> s) & 0xf; 3045801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher} 3055801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 3065801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucherstatic bool dp_clock_recovery_ok(u8 link_status[DP_LINK_STATUS_SIZE], 3075801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher int lane_count) 3085801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher{ 3095801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher int lane; 3105801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher u8 lane_status; 3115801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 3125801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher for (lane = 0; lane < lane_count; lane++) { 3135801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher lane_status = dp_get_lane_status(link_status, lane); 3145801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher if ((lane_status & DP_LANE_CR_DONE) == 0) 3155801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher return false; 3165801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher } 3175801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher return true; 3185801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher} 3195801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 3205801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucherstatic bool dp_channel_eq_ok(u8 link_status[DP_LINK_STATUS_SIZE], 3215801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher int lane_count) 3225801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher{ 3235801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher u8 lane_align; 3245801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher u8 lane_status; 3255801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher int lane; 3265801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 3275801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher lane_align = dp_link_status(link_status, 3285801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher DP_LANE_ALIGN_STATUS_UPDATED); 3295801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) 3305801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher return false; 3315801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher for (lane = 0; lane < lane_count; lane++) { 3325801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher lane_status = dp_get_lane_status(link_status, lane); 3335801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher if ((lane_status & DP_CHANNEL_EQ_BITS) != DP_CHANNEL_EQ_BITS) 3345801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher return false; 3355801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher } 3365801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher return true; 3375801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher} 3385801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 339224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic u8 dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE], 3405801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher int lane) 3415801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 3425801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher{ 3435801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); 3445801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher int s = ((lane & 1) ? 3455801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : 3465801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT); 3475801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher u8 l = dp_link_status(link_status, i); 3485801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 3495801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; 3505801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher} 3515801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 352224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic u8 dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE], 3535801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher int lane) 3545801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher{ 3555801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); 3565801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher int s = ((lane & 1) ? 3575801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT : 3585801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT); 3595801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher u8 l = dp_link_status(link_status, i); 3605801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 3615801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; 3625801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher} 3635801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 3645801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher#define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200 365224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher#define DP_PRE_EMPHASIS_MAX DP_TRAIN_PRE_EMPHASIS_9_5 3665801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 3675801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucherstatic void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE], 3685801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher int lane_count, 3695801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher u8 train_set[4]) 3705801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher{ 3715801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher u8 v = 0; 3725801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher u8 p = 0; 3735801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher int lane; 3745801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 3755801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher for (lane = 0; lane < lane_count; lane++) { 3765801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher u8 this_v = dp_get_adjust_request_voltage(link_status, lane); 3775801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher u8 this_p = dp_get_adjust_request_pre_emphasis(link_status, lane); 3785801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 379d9fdaafbe912a34ef06ed569c6606fe2811f325bDave Airlie DRM_DEBUG_KMS("requested signal parameters: lane %d voltage %s pre_emph %s\n", 38053c1e09fea4cf3fc0ec1f735a5fcab78c43cb55dAlex Deucher lane, 38153c1e09fea4cf3fc0ec1f735a5fcab78c43cb55dAlex Deucher voltage_names[this_v >> DP_TRAIN_VOLTAGE_SWING_SHIFT], 38253c1e09fea4cf3fc0ec1f735a5fcab78c43cb55dAlex Deucher pre_emph_names[this_p >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); 3835801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 3845801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher if (this_v > v) 3855801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher v = this_v; 3865801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher if (this_p > p) 3875801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher p = this_p; 3885801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher } 3895801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 3905801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher if (v >= DP_VOLTAGE_MAX) 391224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher v |= DP_TRAIN_MAX_SWING_REACHED; 3925801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 393224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (p >= DP_PRE_EMPHASIS_MAX) 394224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher p |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; 3955801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 396d9fdaafbe912a34ef06ed569c6606fe2811f325bDave Airlie DRM_DEBUG_KMS("using signal parameters: voltage %s pre_emph %s\n", 39753c1e09fea4cf3fc0ec1f735a5fcab78c43cb55dAlex Deucher voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK) >> DP_TRAIN_VOLTAGE_SWING_SHIFT], 39853c1e09fea4cf3fc0ec1f735a5fcab78c43cb55dAlex Deucher pre_emph_names[(p & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); 3995801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 4005801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher for (lane = 0; lane < 4; lane++) 4015801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher train_set[lane] = v | p; 4025801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher} 4035801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 404224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher/* convert bits per color to bits per pixel */ 405224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher/* get bpc from the EDID */ 406224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic int convert_bpc_to_bpp(int bpc) 407746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie{ 408224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (bpc == 0) 409224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return 24; 410224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher else 411224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return bpc * 3; 412224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher} 413746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 414224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher/* get the max pix clock supported by the link rate and lane num */ 415224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic int dp_get_max_dp_pix_clock(int link_rate, 416224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int lane_num, 417224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int bpp) 418224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher{ 419224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return (link_rate * lane_num * 8) / bpp; 420224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher} 421834b2904bbfde3d85b5e984688777d56e9c7bf80Alex Deucher 422224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic int dp_get_max_link_rate(u8 dpcd[DP_DPCD_SIZE]) 423224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher{ 424224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher switch (dpcd[DP_MAX_LINK_RATE]) { 425224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case DP_LINK_BW_1_62: 426224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher default: 427224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return 162000; 428224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case DP_LINK_BW_2_7: 429224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return 270000; 430224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case DP_LINK_BW_5_4: 431224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return 540000; 432834b2904bbfde3d85b5e984688777d56e9c7bf80Alex Deucher } 433746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie} 434746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 435224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic u8 dp_get_max_lane_number(u8 dpcd[DP_DPCD_SIZE]) 436746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie{ 437224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; 438224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher} 439834b2904bbfde3d85b5e984688777d56e9c7bf80Alex Deucher 440224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic u8 dp_get_dp_link_rate_coded(int link_rate) 441224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher{ 442224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher switch (link_rate) { 443224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case 162000: 444224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher default: 445224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return DP_LINK_BW_1_62; 446224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case 270000: 447224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return DP_LINK_BW_2_7; 448224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case 540000: 449224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return DP_LINK_BW_5_4; 450224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } 451224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher} 452746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 453224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher/***** radeon specific DP functions *****/ 454746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 455224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher/* First get the min lane# when low rate is used according to pixel clock 456224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher * (prefer low rate), second check max lane# supported by DP panel, 457224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher * if the max lane# < low rate lane# then use max lane# instead. 458224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher */ 459224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic int radeon_dp_get_dp_lane_number(struct drm_connector *connector, 460224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 dpcd[DP_DPCD_SIZE], 461224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int pix_clock) 462224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher{ 463224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int bpp = convert_bpc_to_bpp(connector->display_info.bpc); 464224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int max_link_rate = dp_get_max_link_rate(dpcd); 465224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int max_lane_num = dp_get_max_lane_number(dpcd); 466224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int lane_num; 467224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int max_dp_pix_clock; 468224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 469224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) { 470224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher max_dp_pix_clock = dp_get_max_dp_pix_clock(max_link_rate, lane_num, bpp); 471224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (pix_clock <= max_dp_pix_clock) 472224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher break; 473834b2904bbfde3d85b5e984688777d56e9c7bf80Alex Deucher } 474746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 475224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return lane_num; 476746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie} 477746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 478224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic int radeon_dp_get_dp_link_clock(struct drm_connector *connector, 479224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 dpcd[DP_DPCD_SIZE], 480224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int pix_clock) 481746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie{ 482224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int bpp = convert_bpc_to_bpp(connector->display_info.bpc); 483224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int lane_num, max_pix_clock; 484224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 485fdca78c3b8876e47f1c92b3b28693b261bfd913aAlex Deucher if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == 486fdca78c3b8876e47f1c92b3b28693b261bfd913aAlex Deucher ENCODER_OBJECT_ID_NUTMEG) 487224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return 270000; 488224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 489224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher lane_num = radeon_dp_get_dp_lane_number(connector, dpcd, pix_clock); 490224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher max_pix_clock = dp_get_max_dp_pix_clock(162000, lane_num, bpp); 491224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (pix_clock <= max_pix_clock) 492224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return 162000; 493224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher max_pix_clock = dp_get_max_dp_pix_clock(270000, lane_num, bpp); 494224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (pix_clock <= max_pix_clock) 495224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return 270000; 496224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (radeon_connector_is_dp12_capable(connector)) { 497224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher max_pix_clock = dp_get_max_dp_pix_clock(540000, lane_num, bpp); 498224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (pix_clock <= max_pix_clock) 499224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return 540000; 500834b2904bbfde3d85b5e984688777d56e9c7bf80Alex Deucher } 501224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 502224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return dp_get_max_link_rate(dpcd); 503746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie} 504746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 505834b2904bbfde3d85b5e984688777d56e9c7bf80Alex Deucherstatic u8 radeon_dp_encoder_service(struct radeon_device *rdev, 506834b2904bbfde3d85b5e984688777d56e9c7bf80Alex Deucher int action, int dp_clock, 507224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 ucconfig, u8 lane_num) 5085801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher{ 5095801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher DP_ENCODER_SERVICE_PARAMETERS args; 5105801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher int index = GetIndexIntoMasterTable(COMMAND, DPEncoderService); 5115801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 5125801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher memset(&args, 0, sizeof(args)); 5135801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher args.ucLinkClock = dp_clock / 10; 5145801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher args.ucConfig = ucconfig; 5155801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher args.ucAction = action; 5165801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher args.ucLaneNum = lane_num; 5175801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher args.ucStatus = 0; 5185801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 5195801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); 5205801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher return args.ucStatus; 5215801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher} 5225801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 5235801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucheru8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector) 5245801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher{ 5255801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; 5265801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher struct drm_device *dev = radeon_connector->base.dev; 5275801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher struct radeon_device *rdev = dev->dev_private; 5285801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 5295801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher return radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_GET_SINK_TYPE, 0, 5305801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher dig_connector->dp_i2c_bus->rec.i2c_id, 0); 5315801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher} 5325801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 5339fa05c98d69eb77c82e59b5e434ca63bba230ba0Alex Deucherbool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) 534746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie{ 5355801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; 536746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie u8 msg[25]; 537224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int ret, i; 538746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 539834b2904bbfde3d85b5e984688777d56e9c7bf80Alex Deucher ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, msg, 8, 0); 540834b2904bbfde3d85b5e984688777d56e9c7bf80Alex Deucher if (ret > 0) { 5415801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher memcpy(dig_connector->dpcd, msg, 8); 542224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DRM_DEBUG_KMS("DPCD: "); 543224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher for (i = 0; i < 8; i++) 544224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DRM_DEBUG_KMS("%02x ", msg[i]); 545224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DRM_DEBUG_KMS("\n"); 5469fa05c98d69eb77c82e59b5e434ca63bba230ba0Alex Deucher return true; 547746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie } 5485801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher dig_connector->dpcd[0] = 0; 5499fa05c98d69eb77c82e59b5e434ca63bba230ba0Alex Deucher return false; 550746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie} 551746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 552386d4d751e8e0b4b693bb724f09aae064ee5297dAlex Deucherint radeon_dp_get_panel_mode(struct drm_encoder *encoder, 553386d4d751e8e0b4b693bb724f09aae064ee5297dAlex Deucher struct drm_connector *connector) 554224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher{ 555224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct drm_device *dev = encoder->dev; 556224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct radeon_device *rdev = dev->dev_private; 55700dfb8df5bf8c3afe4c0bb8361133156b06b7a2cAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 558224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; 559224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 560224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (!ASIC_IS_DCE4(rdev)) 561386d4d751e8e0b4b693bb724f09aae064ee5297dAlex Deucher return panel_mode; 562224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 563cf2aff6eff251b6fbdaf8c253e65ff7c693de8cdAlex Deucher if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == 564cf2aff6eff251b6fbdaf8c253e65ff7c693de8cdAlex Deucher ENCODER_OBJECT_ID_NUTMEG) 565224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; 566cf2aff6eff251b6fbdaf8c253e65ff7c693de8cdAlex Deucher else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == 567304a48400d9718f74ec35ae46f30868a5f4c4516Alex Deucher ENCODER_OBJECT_ID_TRAVIS) { 568304a48400d9718f74ec35ae46f30868a5f4c4516Alex Deucher u8 id[6]; 569304a48400d9718f74ec35ae46f30868a5f4c4516Alex Deucher int i; 570304a48400d9718f74ec35ae46f30868a5f4c4516Alex Deucher for (i = 0; i < 6; i++) 571304a48400d9718f74ec35ae46f30868a5f4c4516Alex Deucher id[i] = radeon_read_dpcd_reg(radeon_connector, 0x503 + i); 572304a48400d9718f74ec35ae46f30868a5f4c4516Alex Deucher if (id[0] == 0x73 && 573304a48400d9718f74ec35ae46f30868a5f4c4516Alex Deucher id[1] == 0x69 && 574304a48400d9718f74ec35ae46f30868a5f4c4516Alex Deucher id[2] == 0x76 && 575304a48400d9718f74ec35ae46f30868a5f4c4516Alex Deucher id[3] == 0x61 && 576304a48400d9718f74ec35ae46f30868a5f4c4516Alex Deucher id[4] == 0x72 && 577304a48400d9718f74ec35ae46f30868a5f4c4516Alex Deucher id[5] == 0x54) 578304a48400d9718f74ec35ae46f30868a5f4c4516Alex Deucher panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; 579304a48400d9718f74ec35ae46f30868a5f4c4516Alex Deucher else 580304a48400d9718f74ec35ae46f30868a5f4c4516Alex Deucher panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; 581304a48400d9718f74ec35ae46f30868a5f4c4516Alex Deucher } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { 58200dfb8df5bf8c3afe4c0bb8361133156b06b7a2cAlex Deucher u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); 58300dfb8df5bf8c3afe4c0bb8361133156b06b7a2cAlex Deucher if (tmp & 1) 58400dfb8df5bf8c3afe4c0bb8361133156b06b7a2cAlex Deucher panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; 58500dfb8df5bf8c3afe4c0bb8361133156b06b7a2cAlex Deucher } 586224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 587386d4d751e8e0b4b693bb724f09aae064ee5297dAlex Deucher return panel_mode; 588224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher} 589224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 5905801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deuchervoid radeon_dp_set_link_config(struct drm_connector *connector, 5915801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher struct drm_display_mode *mode) 5925801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher{ 593224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 5945801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher struct radeon_connector_atom_dig *dig_connector; 5955801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 5965801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher if (!radeon_connector->con_priv) 5975801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher return; 5985801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher dig_connector = radeon_connector->con_priv; 5995801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 600224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || 601224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { 602224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dig_connector->dp_clock = 603224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); 604224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dig_connector->dp_lane_count = 605224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock); 606224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } 6075801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher} 6085801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 609224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherint radeon_dp_mode_valid_helper(struct drm_connector *connector, 6105801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher struct drm_display_mode *mode) 6115801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher{ 612224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct radeon_connector *radeon_connector = to_radeon_connector(connector); 613224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct radeon_connector_atom_dig *dig_connector; 614224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int dp_clock; 6155801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 616224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (!radeon_connector->con_priv) 617224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return MODE_CLOCK_HIGH; 618224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dig_connector = radeon_connector->con_priv; 619224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 620224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_clock = 621224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); 622224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 623224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if ((dp_clock == 540000) && 624224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher (!radeon_connector_is_dp12_capable(connector))) 625224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return MODE_CLOCK_HIGH; 626224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 627224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return MODE_OK; 6285801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher} 6295801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 630224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector, 631224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 link_status[DP_LINK_STATUS_SIZE]) 632746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie{ 633746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie int ret; 634834b2904bbfde3d85b5e984688777d56e9c7bf80Alex Deucher ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, 635834b2904bbfde3d85b5e984688777d56e9c7bf80Alex Deucher link_status, DP_LINK_STATUS_SIZE, 100); 636834b2904bbfde3d85b5e984688777d56e9c7bf80Alex Deucher if (ret <= 0) { 637746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie DRM_ERROR("displayport link status failed\n"); 638746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie return false; 639746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie } 640746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 641d9fdaafbe912a34ef06ed569c6606fe2811f325bDave Airlie DRM_DEBUG_KMS("link status %02x %02x %02x %02x %02x %02x\n", 64253c1e09fea4cf3fc0ec1f735a5fcab78c43cb55dAlex Deucher link_status[0], link_status[1], link_status[2], 64353c1e09fea4cf3fc0ec1f735a5fcab78c43cb55dAlex Deucher link_status[3], link_status[4], link_status[5]); 644746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie return true; 645746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie} 646746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 647d5811e8731213f80c80d89e980505052f16aca1cAlex Deucherbool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector) 648d5811e8731213f80c80d89e980505052f16aca1cAlex Deucher{ 649d5811e8731213f80c80d89e980505052f16aca1cAlex Deucher u8 link_status[DP_LINK_STATUS_SIZE]; 650d5811e8731213f80c80d89e980505052f16aca1cAlex Deucher struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; 651d5811e8731213f80c80d89e980505052f16aca1cAlex Deucher 652d5811e8731213f80c80d89e980505052f16aca1cAlex Deucher if (!radeon_dp_get_link_status(radeon_connector, link_status)) 653d5811e8731213f80c80d89e980505052f16aca1cAlex Deucher return false; 654d5811e8731213f80c80d89e980505052f16aca1cAlex Deucher if (dp_channel_eq_ok(link_status, dig->dp_lane_count)) 655d5811e8731213f80c80d89e980505052f16aca1cAlex Deucher return false; 656d5811e8731213f80c80d89e980505052f16aca1cAlex Deucher return true; 657d5811e8731213f80c80d89e980505052f16aca1cAlex Deucher} 658d5811e8731213f80c80d89e980505052f16aca1cAlex Deucher 659224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstruct radeon_dp_link_train_info { 660224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct radeon_device *rdev; 661224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct drm_encoder *encoder; 662224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct drm_connector *connector; 663224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct radeon_connector *radeon_connector; 664224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int enc_id; 665224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int dp_clock; 666224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int dp_lane_count; 667224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int rd_interval; 668224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher bool tp3_supported; 669224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 dpcd[8]; 670224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 train_set[4]; 671224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 link_status[DP_LINK_STATUS_SIZE]; 672224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 tries; 6735a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse bool use_dpencoder; 674224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher}; 6755801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 676224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic void radeon_dp_update_vs_emph(struct radeon_dp_link_train_info *dp_info) 6775801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher{ 678224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher /* set the initial vs/emph on the source */ 679224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher atombios_dig_transmitter_setup(dp_info->encoder, 680224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH, 681224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 0, dp_info->train_set[0]); /* sets all lanes at once */ 682224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 683224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher /* set the vs/emph on the sink */ 684224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_dp_aux_native_write(dp_info->radeon_connector, DP_TRAINING_LANE0_SET, 685224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info->train_set, dp_info->dp_lane_count, 0); 6865801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher} 6875801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 688224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp) 689746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie{ 690224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int rtp = 0; 691746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 692224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher /* set training pattern on the source */ 6935a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) { 694224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher switch (tp) { 695224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case DP_TRAINING_PATTERN_1: 696224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1; 697224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher break; 698224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case DP_TRAINING_PATTERN_2: 699224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2; 700224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher break; 701224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case DP_TRAINING_PATTERN_3: 702224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3; 703224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher break; 704224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } 705224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher atombios_dig_encoder_setup(dp_info->encoder, rtp, 0); 706224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } else { 707224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher switch (tp) { 708224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case DP_TRAINING_PATTERN_1: 709224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher rtp = 0; 710224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher break; 711224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher case DP_TRAINING_PATTERN_2: 712224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher rtp = 1; 713224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher break; 714224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } 715224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, 716224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info->dp_clock, dp_info->enc_id, rtp); 717224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } 718746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 719224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher /* enable training pattern on the sink */ 720224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_write_dpcd_reg(dp_info->radeon_connector, DP_TRAINING_PATTERN_SET, tp); 721746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie} 722746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 723224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info) 7245801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher{ 725386d4d751e8e0b4b693bb724f09aae064ee5297dAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(dp_info->encoder); 726386d4d751e8e0b4b693bb724f09aae064ee5297dAlex Deucher struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 727224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 tmp; 7285801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 729224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher /* power up the sink */ 730224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (dp_info->dpcd[0] >= 0x11) 731224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_write_dpcd_reg(dp_info->radeon_connector, 732224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DP_SET_POWER, DP_SET_POWER_D0); 733224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 734224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher /* possibly enable downspread on the sink */ 735224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (dp_info->dpcd[3] & 0x1) 736224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_write_dpcd_reg(dp_info->radeon_connector, 737224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DP_DOWNSPREAD_CTRL, DP_SPREAD_AMP_0_5); 738224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher else 739224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_write_dpcd_reg(dp_info->radeon_connector, 740224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DP_DOWNSPREAD_CTRL, 0); 7415801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 742386d4d751e8e0b4b693bb724f09aae064ee5297dAlex Deucher if ((dp_info->connector->connector_type == DRM_MODE_CONNECTOR_eDP) && 743386d4d751e8e0b4b693bb724f09aae064ee5297dAlex Deucher (dig->panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) { 744386d4d751e8e0b4b693bb724f09aae064ee5297dAlex Deucher radeon_write_dpcd_reg(dp_info->radeon_connector, DP_EDP_CONFIGURATION_SET, 1); 745386d4d751e8e0b4b693bb724f09aae064ee5297dAlex Deucher } 7465801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 747224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher /* set the lane count on the sink */ 748224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher tmp = dp_info->dp_lane_count; 749224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (dp_info->dpcd[0] >= 0x11) 750224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher tmp |= DP_LANE_COUNT_ENHANCED_FRAME_EN; 751224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LANE_COUNT_SET, tmp); 7525801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 753224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher /* set the link rate on the sink */ 754224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher tmp = dp_get_dp_link_rate_coded(dp_info->dp_clock); 755224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp); 7565801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 757224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher /* start training on the source */ 7585a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) 759224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher atombios_dig_encoder_setup(dp_info->encoder, 760224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher ATOM_ENCODER_CMD_DP_LINK_TRAINING_START, 0); 7615801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher else 762224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_START, 763224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info->dp_clock, dp_info->enc_id, 0); 7645801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 7655801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher /* disable the training pattern on the sink */ 766224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_write_dpcd_reg(dp_info->radeon_connector, 767224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DP_TRAINING_PATTERN_SET, 768224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DP_TRAINING_PATTERN_DISABLE); 769224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 770224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return 0; 771224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher} 7725801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 773224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic int radeon_dp_link_train_finish(struct radeon_dp_link_train_info *dp_info) 774224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher{ 7755801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher udelay(400); 7765801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 777224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher /* disable the training pattern on the sink */ 778224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_write_dpcd_reg(dp_info->radeon_connector, 779224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DP_TRAINING_PATTERN_SET, 780224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher DP_TRAINING_PATTERN_DISABLE); 781224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 782224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher /* disable the training pattern on the source */ 7835a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) 784224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher atombios_dig_encoder_setup(dp_info->encoder, 785224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE, 0); 786224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher else 787224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_COMPLETE, 788224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info->dp_clock, dp_info->enc_id, 0); 789224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 790224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return 0; 791224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher} 792224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 793224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info) 794224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher{ 795224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher bool clock_recovery; 796224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher u8 voltage; 797224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher int i; 798224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 799224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_1); 800224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher memset(dp_info->train_set, 0, 4); 801224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_dp_update_vs_emph(dp_info); 802224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 803224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher udelay(400); 8045fbfce7fc906c4a9e3d5e0872e5d6affaca54761Dave Airlie 8055801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher /* clock recovery loop */ 8065801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher clock_recovery = false; 807224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info->tries = 0; 8085801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher voltage = 0xff; 809224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher while (1) { 810224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (dp_info->rd_interval == 0) 811224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher udelay(100); 812224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher else 813224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher mdelay(dp_info->rd_interval * 4); 814224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 815224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) 8165801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher break; 8175801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 818224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { 8195801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher clock_recovery = true; 8205801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher break; 8215801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher } 8225801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 823224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher for (i = 0; i < dp_info->dp_lane_count; i++) { 824224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if ((dp_info->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) 8255801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher break; 8265801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher } 827224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (i == dp_info->dp_lane_count) { 8285801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher DRM_ERROR("clock recovery reached max voltage\n"); 8295801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher break; 8305801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher } 8315801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 832224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if ((dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { 833224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher ++dp_info->tries; 834224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (dp_info->tries == 5) { 8355801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher DRM_ERROR("clock recovery tried 5 times\n"); 8365801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher break; 8375801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher } 8385801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher } else 839224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info->tries = 0; 8405801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 841224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher voltage = dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; 8425801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 8435801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher /* Compute new train_set as requested by sink */ 844224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_get_adjust_train(dp_info->link_status, dp_info->dp_lane_count, dp_info->train_set); 845224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 846224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_dp_update_vs_emph(dp_info); 8475801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher } 848224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (!clock_recovery) { 8495801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher DRM_ERROR("clock recovery failed\n"); 850224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return -1; 851224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } else { 852d9fdaafbe912a34ef06ed569c6606fe2811f325bDave Airlie DRM_DEBUG_KMS("clock recovery at voltage %d pre-emphasis %d\n", 853224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, 854224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher (dp_info->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >> 85553c1e09fea4cf3fc0ec1f735a5fcab78c43cb55dAlex Deucher DP_TRAIN_PRE_EMPHASIS_SHIFT); 856224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return 0; 857224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } 858224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher} 8595801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 860224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherstatic int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info) 861224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher{ 862224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher bool channel_eq; 8635801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 864224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (dp_info->tp3_supported) 865224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_3); 866bcc1c2a1d22974215e39dc87ce746ba9a39223e5Alex Deucher else 867224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_2); 8685801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 8695801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher /* channel equalization loop */ 870224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info->tries = 0; 8715801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher channel_eq = false; 872224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher while (1) { 873224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (dp_info->rd_interval == 0) 874224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher udelay(400); 875224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher else 876224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher mdelay(dp_info->rd_interval * 4); 877224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 878224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) 8795801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher break; 8805801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 881224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { 8825801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher channel_eq = true; 8835801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher break; 8845801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher } 8855801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 8865801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher /* Try 5 times */ 887224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (dp_info->tries > 5) { 8885801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher DRM_ERROR("channel eq failed: 5 tries\n"); 8895801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher break; 8905801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher } 8915801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 8925801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher /* Compute new train_set as requested by sink */ 893224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_get_adjust_train(dp_info->link_status, dp_info->dp_lane_count, dp_info->train_set); 8945801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 895224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_dp_update_vs_emph(dp_info); 896224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info->tries++; 8975801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher } 8985801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 899224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (!channel_eq) { 9005801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher DRM_ERROR("channel eq failed\n"); 901224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return -1; 902224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } else { 903d9fdaafbe912a34ef06ed569c6606fe2811f325bDave Airlie DRM_DEBUG_KMS("channel eq at voltage %d pre-emphasis %d\n", 904224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, 905224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher (dp_info->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) 90653c1e09fea4cf3fc0ec1f735a5fcab78c43cb55dAlex Deucher >> DP_TRAIN_PRE_EMPHASIS_SHIFT); 907224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return 0; 908224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher } 9095801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher} 9105801ead6bd6bddf5505d6eab55f84d8ee8106cd8Alex Deucher 911224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deuchervoid radeon_dp_link_train(struct drm_encoder *encoder, 912224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct drm_connector *connector) 913746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie{ 914224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct drm_device *dev = encoder->dev; 915224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct radeon_device *rdev = dev->dev_private; 916224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 917224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct radeon_encoder_atom_dig *dig; 918224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct radeon_connector *radeon_connector; 919224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct radeon_connector_atom_dig *dig_connector; 920224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher struct radeon_dp_link_train_info dp_info; 9215a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse int index; 9225a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse u8 tmp, frev, crev; 923746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 924224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (!radeon_encoder->enc_priv) 925224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return; 926224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dig = radeon_encoder->enc_priv; 927746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 928224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher radeon_connector = to_radeon_connector(connector); 929224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (!radeon_connector->con_priv) 930224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return; 931224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dig_connector = radeon_connector->con_priv; 932834b2904bbfde3d85b5e984688777d56e9c7bf80Alex Deucher 933224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if ((dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_DISPLAYPORT) && 934224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_eDP)) 935224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return; 936746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie 9375a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse /* DPEncoderService newer than 1.1 can't program properly the 9385a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse * training pattern. When facing such version use the 9395a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse * DIGXEncoderControl (X== 1 | 2) 9405a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse */ 9415a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse dp_info.use_dpencoder = true; 9425a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse index = GetIndexIntoMasterTable(COMMAND, DPEncoderService); 9435a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse if (atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) { 9445a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse if (crev > 1) { 9455a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse dp_info.use_dpencoder = false; 9465a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse } 9475a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse } 9485a96a899bbdee86024ab9ea6d02b9e242faacbedJerome Glisse 949224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info.enc_id = 0; 950224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (dig->dig_encoder) 951224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info.enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER; 952224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher else 953224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info.enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER; 954224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (dig->linkb) 955224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info.enc_id |= ATOM_DP_CONFIG_LINK_B; 956224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher else 957224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; 958834b2904bbfde3d85b5e984688777d56e9c7bf80Alex Deucher 959224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info.rd_interval = radeon_read_dpcd_reg(radeon_connector, DP_TRAINING_AUX_RD_INTERVAL); 960224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher tmp = radeon_read_dpcd_reg(radeon_connector, DP_MAX_LANE_COUNT); 961224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) 962224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info.tp3_supported = true; 963224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher else 964224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info.tp3_supported = false; 965224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 966224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher memcpy(dp_info.dpcd, dig_connector->dpcd, 8); 967224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info.rdev = rdev; 968224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info.encoder = encoder; 969224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info.connector = connector; 970224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info.radeon_connector = radeon_connector; 971224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info.dp_lane_count = dig_connector->dp_lane_count; 972224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher dp_info.dp_clock = dig_connector->dp_clock; 973224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher 974224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (radeon_dp_link_train_init(&dp_info)) 975224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher goto done; 976224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (radeon_dp_link_train_cr(&dp_info)) 977224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher goto done; 978224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (radeon_dp_link_train_ce(&dp_info)) 979224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher goto done; 980224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucherdone: 981224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher if (radeon_dp_link_train_finish(&dp_info)) 982224d94b1445e2a836cd3790ff29f1866c052de4dAlex Deucher return; 983746c1aa4d100f7441423050f34be79f401fbf7d4Dave Airlie} 984