Rev 3764 | Rev 5128 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3764 | Rev 5078 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Copyright 2007-8 Advanced Micro Devices, Inc. |
2 | * Copyright 2007-8 Advanced Micro Devices, Inc. |
3 | * Copyright 2008 Red Hat Inc. |
3 | * Copyright 2008 Red Hat Inc. |
4 | * |
4 | * |
5 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * Permission is hereby granted, free of charge, to any person obtaining a |
6 | * copy of this software and associated documentation files (the "Software"), |
6 | * copy of this software and associated documentation files (the "Software"), |
7 | * to deal in the Software without restriction, including without limitation |
7 | * to deal in the Software without restriction, including without limitation |
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
9 | * and/or sell copies of the Software, and to permit persons to whom the |
9 | * and/or sell copies of the Software, and to permit persons to whom the |
10 | * Software is furnished to do so, subject to the following conditions: |
10 | * Software is furnished to do so, subject to the following conditions: |
11 | * |
11 | * |
12 | * The above copyright notice and this permission notice shall be included in |
12 | * The above copyright notice and this permission notice shall be included in |
13 | * all copies or substantial portions of the Software. |
13 | * all copies or substantial portions of the Software. |
14 | * |
14 | * |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR |
19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
21 | * OTHER DEALINGS IN THE SOFTWARE. |
21 | * OTHER DEALINGS IN THE SOFTWARE. |
22 | * |
22 | * |
23 | * Authors: Dave Airlie |
23 | * Authors: Dave Airlie |
24 | * Alex Deucher |
24 | * Alex Deucher |
25 | * Jerome Glisse |
25 | * Jerome Glisse |
26 | */ |
26 | */ |
27 | #include |
27 | #include |
28 | #include |
28 | #include |
29 | #include "radeon.h" |
29 | #include "radeon.h" |
30 | 30 | ||
31 | #include "atom.h" |
31 | #include "atom.h" |
32 | #include "atom-bits.h" |
32 | #include "atom-bits.h" |
33 | #include |
33 | #include |
34 | 34 | ||
35 | /* move these to drm_dp_helper.c/h */ |
35 | /* move these to drm_dp_helper.c/h */ |
36 | #define DP_LINK_CONFIGURATION_SIZE 9 |
36 | #define DP_LINK_CONFIGURATION_SIZE 9 |
37 | #define DP_DPCD_SIZE DP_RECEIVER_CAP_SIZE |
37 | #define DP_DPCD_SIZE DP_RECEIVER_CAP_SIZE |
38 | 38 | ||
39 | static char *voltage_names[] = { |
39 | static char *voltage_names[] = { |
40 | "0.4V", "0.6V", "0.8V", "1.2V" |
40 | "0.4V", "0.6V", "0.8V", "1.2V" |
41 | }; |
41 | }; |
42 | static char *pre_emph_names[] = { |
42 | static char *pre_emph_names[] = { |
43 | "0dB", "3.5dB", "6dB", "9.5dB" |
43 | "0dB", "3.5dB", "6dB", "9.5dB" |
44 | }; |
44 | }; |
45 | 45 | ||
46 | /***** radeon AUX functions *****/ |
46 | /***** radeon AUX functions *****/ |
- | 47 | ||
- | 48 | /* Atom needs data in little endian format |
|
- | 49 | * so swap as appropriate when copying data to |
|
- | 50 | * or from atom. Note that atom operates on |
|
- | 51 | * dw units. |
|
- | 52 | */ |
|
- | 53 | void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le) |
|
- | 54 | { |
|
- | 55 | #ifdef __BIG_ENDIAN |
|
- | 56 | u8 src_tmp[20], dst_tmp[20]; /* used for byteswapping */ |
|
- | 57 | u32 *dst32, *src32; |
|
- | 58 | int i; |
|
- | 59 | ||
- | 60 | memcpy(src_tmp, src, num_bytes); |
|
- | 61 | src32 = (u32 *)src_tmp; |
|
- | 62 | dst32 = (u32 *)dst_tmp; |
|
- | 63 | if (to_le) { |
|
- | 64 | for (i = 0; i < ((num_bytes + 3) / 4); i++) |
|
- | 65 | dst32[i] = cpu_to_le32(src32[i]); |
|
- | 66 | memcpy(dst, dst_tmp, num_bytes); |
|
- | 67 | } else { |
|
- | 68 | u8 dws = num_bytes & ~3; |
|
- | 69 | for (i = 0; i < ((num_bytes + 3) / 4); i++) |
|
- | 70 | dst32[i] = le32_to_cpu(src32[i]); |
|
- | 71 | memcpy(dst, dst_tmp, dws); |
|
- | 72 | if (num_bytes % 4) { |
|
- | 73 | for (i = 0; i < (num_bytes % 4); i++) |
|
- | 74 | dst[dws+i] = dst_tmp[dws+i]; |
|
- | 75 | } |
|
- | 76 | } |
|
- | 77 | #else |
|
- | 78 | memcpy(dst, src, num_bytes); |
|
- | 79 | #endif |
|
- | 80 | } |
|
- | 81 | ||
47 | union aux_channel_transaction { |
82 | union aux_channel_transaction { |
48 | PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1; |
83 | PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1; |
49 | PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2; |
84 | PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2; |
50 | }; |
85 | }; |
51 | 86 | ||
52 | static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, |
87 | static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, |
53 | u8 *send, int send_bytes, |
88 | u8 *send, int send_bytes, |
54 | u8 *recv, int recv_size, |
89 | u8 *recv, int recv_size, |
55 | u8 delay, u8 *ack) |
90 | u8 delay, u8 *ack) |
56 | { |
91 | { |
57 | struct drm_device *dev = chan->dev; |
92 | struct drm_device *dev = chan->dev; |
58 | struct radeon_device *rdev = dev->dev_private; |
93 | struct radeon_device *rdev = dev->dev_private; |
59 | union aux_channel_transaction args; |
94 | union aux_channel_transaction args; |
60 | int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); |
95 | int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); |
61 | unsigned char *base; |
96 | unsigned char *base; |
62 | int recv_bytes; |
97 | int recv_bytes; |
- | 98 | int r = 0; |
|
63 | 99 | ||
64 | memset(&args, 0, sizeof(args)); |
100 | memset(&args, 0, sizeof(args)); |
- | 101 | ||
- | 102 | mutex_lock(&chan->mutex); |
|
65 | 103 | ||
66 | base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1); |
104 | base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1); |
67 | 105 | ||
68 | memcpy(base, send, send_bytes); |
106 | radeon_atom_copy_swap(base, send, send_bytes, true); |
69 | 107 | ||
70 | args.v1.lpAuxRequest = 0 + 4; |
108 | args.v1.lpAuxRequest = cpu_to_le16((u16)(0 + 4)); |
71 | args.v1.lpDataOut = 16 + 4; |
109 | args.v1.lpDataOut = cpu_to_le16((u16)(16 + 4)); |
72 | args.v1.ucDataOutLen = 0; |
110 | args.v1.ucDataOutLen = 0; |
73 | args.v1.ucChannelID = chan->rec.i2c_id; |
111 | args.v1.ucChannelID = chan->rec.i2c_id; |
74 | args.v1.ucDelay = delay / 10; |
112 | args.v1.ucDelay = delay / 10; |
75 | if (ASIC_IS_DCE4(rdev)) |
113 | if (ASIC_IS_DCE4(rdev)) |
76 | args.v2.ucHPD_ID = chan->rec.hpd; |
114 | args.v2.ucHPD_ID = chan->rec.hpd; |
77 | 115 | ||
78 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
116 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
79 | 117 | ||
80 | *ack = args.v1.ucReplyStatus; |
118 | *ack = args.v1.ucReplyStatus; |
81 | 119 | ||
82 | /* timeout */ |
120 | /* timeout */ |
83 | if (args.v1.ucReplyStatus == 1) { |
121 | if (args.v1.ucReplyStatus == 1) { |
84 | DRM_DEBUG_KMS("dp_aux_ch timeout\n"); |
122 | DRM_DEBUG_KMS("dp_aux_ch timeout\n"); |
85 | return -ETIMEDOUT; |
123 | r = -ETIMEDOUT; |
- | 124 | goto done; |
|
86 | } |
125 | } |
87 | 126 | ||
88 | /* flags not zero */ |
127 | /* flags not zero */ |
89 | if (args.v1.ucReplyStatus == 2) { |
128 | if (args.v1.ucReplyStatus == 2) { |
90 | DRM_DEBUG_KMS("dp_aux_ch flags not zero\n"); |
129 | DRM_DEBUG_KMS("dp_aux_ch flags not zero\n"); |
91 | return -EBUSY; |
130 | r = -EIO; |
- | 131 | goto done; |
|
92 | } |
132 | } |
93 | 133 | ||
94 | /* error */ |
134 | /* error */ |
95 | if (args.v1.ucReplyStatus == 3) { |
135 | if (args.v1.ucReplyStatus == 3) { |
96 | DRM_DEBUG_KMS("dp_aux_ch error\n"); |
136 | DRM_DEBUG_KMS("dp_aux_ch error\n"); |
97 | return -EIO; |
137 | r = -EIO; |
- | 138 | goto done; |
|
98 | } |
139 | } |
99 | 140 | ||
100 | recv_bytes = args.v1.ucDataOutLen; |
141 | recv_bytes = args.v1.ucDataOutLen; |
101 | if (recv_bytes > recv_size) |
142 | if (recv_bytes > recv_size) |
102 | recv_bytes = recv_size; |
143 | recv_bytes = recv_size; |
103 | 144 | ||
104 | if (recv && recv_size) |
145 | if (recv && recv_size) |
105 | memcpy(recv, base + 16, recv_bytes); |
146 | radeon_atom_copy_swap(recv, base + 16, recv_bytes, false); |
106 | - | ||
107 | return recv_bytes; |
- | |
108 | } |
- | |
109 | - | ||
110 | static int radeon_dp_aux_native_write(struct radeon_connector *radeon_connector, |
- | |
111 | u16 address, u8 *send, u8 send_bytes, u8 delay) |
- | |
112 | { |
- | |
113 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
- | |
114 | int ret; |
- | |
115 | u8 msg[20]; |
- | |
116 | int msg_bytes = send_bytes + 4; |
- | |
117 | u8 ack; |
- | |
118 | unsigned retry; |
- | |
119 | - | ||
120 | if (send_bytes > 16) |
- | |
121 | return -1; |
- | |
122 | - | ||
123 | msg[0] = address; |
- | |
124 | msg[1] = address >> 8; |
- | |
125 | msg[2] = AUX_NATIVE_WRITE << 4; |
- | |
126 | msg[3] = (msg_bytes << 4) | (send_bytes - 1); |
- | |
127 | memcpy(&msg[4], send, send_bytes); |
- | |
128 | - | ||
129 | for (retry = 0; retry < 4; retry++) { |
- | |
130 | ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, |
- | |
131 | msg, msg_bytes, NULL, 0, delay, &ack); |
- | |
132 | if (ret == -EBUSY) |
- | |
133 | continue; |
- | |
134 | else if (ret < 0) |
- | |
135 | return ret; |
- | |
136 | if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) |
- | |
137 | return send_bytes; |
- | |
138 | else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) |
- | |
139 | udelay(400); |
- | |
140 | else |
- | |
141 | return -EIO; |
- | |
142 | } |
- | |
143 | - | ||
144 | return -EIO; |
- | |
145 | } |
- | |
146 | - | ||
147 | static int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector, |
- | |
148 | u16 address, u8 *recv, int recv_bytes, u8 delay) |
- | |
149 | { |
- | |
150 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
- | |
151 | u8 msg[4]; |
- | |
152 | int msg_bytes = 4; |
- | |
153 | u8 ack; |
- | |
154 | int ret; |
- | |
155 | unsigned retry; |
- | |
156 | - | ||
157 | msg[0] = address; |
- | |
158 | msg[1] = address >> 8; |
- | |
159 | msg[2] = AUX_NATIVE_READ << 4; |
- | |
160 | msg[3] = (msg_bytes << 4) | (recv_bytes - 1); |
- | |
161 | - | ||
162 | for (retry = 0; retry < 4; retry++) { |
- | |
163 | ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, |
- | |
164 | msg, msg_bytes, recv, recv_bytes, delay, &ack); |
- | |
165 | if (ret == -EBUSY) |
- | |
166 | continue; |
- | |
167 | else if (ret < 0) |
147 | |
168 | return ret; |
- | |
169 | if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) |
- | |
170 | return ret; |
- | |
171 | else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) |
- | |
172 | udelay(400); |
- | |
173 | else if (ret == 0) |
- | |
174 | return -EPROTO; |
148 | r = recv_bytes; |
175 | else |
149 | done: |
176 | return -EIO; |
- | |
177 | } |
150 | mutex_unlock(&chan->mutex); |
178 | 151 | ||
179 | return -EIO; |
- | |
180 | } |
152 | return r; |
181 | - | ||
182 | static void radeon_write_dpcd_reg(struct radeon_connector *radeon_connector, |
153 | } |
183 | u16 reg, u8 val) |
- | |
- | 154 | ||
184 | { |
155 | #define BARE_ADDRESS_SIZE 3 |
185 | radeon_dp_aux_native_write(radeon_connector, reg, &val, 1, 0); |
- | |
186 | } |
156 | #define HEADER_SIZE (BARE_ADDRESS_SIZE + 1) |
187 | - | ||
188 | static u8 radeon_read_dpcd_reg(struct radeon_connector *radeon_connector, |
- | |
189 | u16 reg) |
- | |
190 | { |
- | |
191 | u8 val = 0; |
- | |
192 | - | ||
193 | radeon_dp_aux_native_read(radeon_connector, reg, &val, 1, 0); |
- | |
194 | - | ||
195 | return val; |
157 | |
196 | } |
- | |
197 | - | ||
198 | int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, |
158 | static ssize_t |
199 | u8 write_byte, u8 *read_byte) |
- | |
200 | { |
- | |
201 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; |
- | |
202 | struct radeon_i2c_chan *auxch = (struct radeon_i2c_chan *)adapter; |
- | |
203 | u16 address = algo_data->address; |
- | |
204 | u8 msg[5]; |
- | |
205 | u8 reply[2]; |
159 | radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) |
206 | unsigned retry; |
160 | { |
207 | int msg_bytes; |
- | |
208 | int reply_bytes = 1; |
- | |
209 | int ret; |
161 | struct radeon_i2c_chan *chan = |
210 | u8 ack; |
162 | container_of(aux, struct radeon_i2c_chan, aux); |
211 | - | ||
212 | /* Set up the command byte */ |
- | |
213 | if (mode & MODE_I2C_READ) |
163 | int ret; |
214 | msg[2] = AUX_I2C_READ << 4; |
164 | u8 tx_buf[20]; |
215 | else |
165 | size_t tx_size; |
216 | msg[2] = AUX_I2C_WRITE << 4; |
166 | u8 ack, delay = 0; |
217 | 167 | ||
218 | if (!(mode & MODE_I2C_STOP)) |
168 | if (WARN_ON(msg->size > 16)) |
- | 169 | return -E2BIG; |
|
- | 170 | ||
219 | msg[2] |= AUX_I2C_MOT << 4; |
171 | tx_buf[0] = msg->address & 0xff; |
220 | 172 | tx_buf[1] = msg->address >> 8; |
|
- | 173 | tx_buf[2] = msg->request << 4; |
|
221 | msg[0] = address; |
174 | tx_buf[3] = msg->size ? (msg->size - 1) : 0; |
- | 175 | ||
- | 176 | switch (msg->request & ~DP_AUX_I2C_MOT) { |
|
- | 177 | case DP_AUX_NATIVE_WRITE: |
|
- | 178 | case DP_AUX_I2C_WRITE: |
|
222 | msg[1] = address >> 8; |
179 | /* tx_size needs to be 4 even for bare address packets since the atom |
- | 180 | * table needs the info in tx_buf[3]. |
|
- | 181 | */ |
|
223 | 182 | tx_size = HEADER_SIZE + msg->size; |
|
- | 183 | if (msg->size == 0) |
|
- | 184 | tx_buf[3] |= BARE_ADDRESS_SIZE << 4; |
|
- | 185 | else |
|
- | 186 | tx_buf[3] |= tx_size << 4; |
|
- | 187 | memcpy(tx_buf + HEADER_SIZE, msg->buffer, msg->size); |
|
224 | switch (mode) { |
188 | ret = radeon_process_aux_ch(chan, |
225 | case MODE_I2C_WRITE: |
189 | tx_buf, tx_size, NULL, 0, delay, &ack); |
- | 190 | if (ret >= 0) |
|
226 | msg_bytes = 5; |
191 | /* Return payload size. */ |
- | 192 | ret = msg->size; |
|
- | 193 | break; |
|
- | 194 | case DP_AUX_NATIVE_READ: |
|
- | 195 | case DP_AUX_I2C_READ: |
|
227 | msg[3] = msg_bytes << 4; |
196 | /* tx_size needs to be 4 even for bare address packets since the atom |
- | 197 | * table needs the info in tx_buf[3]. |
|
- | 198 | */ |
|
228 | msg[4] = write_byte; |
199 | tx_size = HEADER_SIZE; |
- | 200 | if (msg->size == 0) |
|
- | 201 | tx_buf[3] |= BARE_ADDRESS_SIZE << 4; |
|
229 | break; |
202 | else |
230 | case MODE_I2C_READ: |
203 | tx_buf[3] |= tx_size << 4; |
231 | msg_bytes = 4; |
- | |
232 | msg[3] = msg_bytes << 4; |
204 | ret = radeon_process_aux_ch(chan, |
233 | break; |
205 | tx_buf, tx_size, msg->buffer, msg->size, delay, &ack); |
234 | default: |
206 | break; |
235 | msg_bytes = 4; |
207 | default: |
236 | msg[3] = 3 << 4; |
208 | ret = -EINVAL; |
237 | break; |
209 | break; |
238 | } |
210 | } |
239 | - | ||
240 | for (retry = 0; retry < 4; retry++) { |
- | |
241 | ret = radeon_process_aux_ch(auxch, |
- | |
242 | msg, msg_bytes, reply, reply_bytes, 0, &ack); |
211 | |
243 | if (ret == -EBUSY) |
- | |
244 | continue; |
212 | if (ret >= 0) |
245 | else if (ret < 0) { |
- | |
- | 213 | msg->reply = ack >> 4; |
|
246 | DRM_DEBUG_KMS("aux_ch failed %d\n", ret); |
214 | |
247 | return ret; |
215 | return ret; |
248 | } |
216 | } |
249 | - | ||
250 | switch (ack & AUX_NATIVE_REPLY_MASK) { |
- | |
251 | case AUX_NATIVE_REPLY_ACK: |
217 | |
252 | /* I2C-over-AUX Reply field is only valid |
- | |
253 | * when paired with AUX ACK. |
218 | void radeon_dp_aux_init(struct radeon_connector *radeon_connector) |
254 | */ |
219 | { |
255 | break; |
- | |
256 | case AUX_NATIVE_REPLY_NACK: |
- | |
257 | DRM_DEBUG_KMS("aux_ch native nack\n"); |
- | |
258 | return -EREMOTEIO; |
- | |
259 | case AUX_NATIVE_REPLY_DEFER: |
- | |
260 | DRM_DEBUG_KMS("aux_ch native defer\n"); |
- | |
261 | udelay(400); |
- | |
262 | continue; |
- | |
263 | default: |
- | |
264 | DRM_ERROR("aux_ch invalid native reply 0x%02x\n", ack); |
- | |
265 | return -EREMOTEIO; |
- | |
266 | } |
220 | int ret; |
267 | - | ||
268 | switch (ack & AUX_I2C_REPLY_MASK) { |
- | |
269 | case AUX_I2C_REPLY_ACK: |
221 | |
270 | if (mode == MODE_I2C_READ) |
- | |
271 | *read_byte = reply[0]; |
- | |
272 | return ret; |
222 | radeon_connector->ddc_bus->rec.hpd = radeon_connector->hpd.hpd; |
273 | case AUX_I2C_REPLY_NACK: |
- | |
274 | DRM_DEBUG_KMS("aux_i2c nack\n"); |
- | |
- | 223 | radeon_connector->ddc_bus->aux.dev = radeon_connector->base.kdev; |
|
275 | return -EREMOTEIO; |
224 | radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer; |
276 | case AUX_I2C_REPLY_DEFER: |
- | |
277 | DRM_DEBUG_KMS("aux_i2c defer\n"); |
225 | |
278 | udelay(400); |
- | |
279 | break; |
226 | ret = drm_dp_aux_register(&radeon_connector->ddc_bus->aux); |
280 | default: |
- | |
281 | DRM_ERROR("aux_i2c invalid reply 0x%02x\n", ack); |
- | |
282 | return -EREMOTEIO; |
- | |
283 | } |
227 | if (!ret) |
284 | } |
- | |
285 | 228 | radeon_connector->ddc_bus->has_aux = true; |
|
286 | DRM_DEBUG_KMS("aux i2c too many retries, giving up\n"); |
229 | |
287 | return -EREMOTEIO; |
230 | WARN(ret, "drm_dp_aux_register() failed with error %d\n", ret); |
288 | } |
231 | } |
289 | 232 | ||
290 | /***** general DP utility functions *****/ |
233 | /***** general DP utility functions *****/ |
291 | 234 | ||
292 | #define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200 |
235 | #define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200 |
293 | #define DP_PRE_EMPHASIS_MAX DP_TRAIN_PRE_EMPHASIS_9_5 |
236 | #define DP_PRE_EMPHASIS_MAX DP_TRAIN_PRE_EMPHASIS_9_5 |
294 | 237 | ||
295 | static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE], |
238 | static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE], |
296 | int lane_count, |
239 | int lane_count, |
297 | u8 train_set[4]) |
240 | u8 train_set[4]) |
298 | { |
241 | { |
299 | u8 v = 0; |
242 | u8 v = 0; |
300 | u8 p = 0; |
243 | u8 p = 0; |
301 | int lane; |
244 | int lane; |
302 | 245 | ||
303 | for (lane = 0; lane < lane_count; lane++) { |
246 | for (lane = 0; lane < lane_count; lane++) { |
304 | u8 this_v = drm_dp_get_adjust_request_voltage(link_status, lane); |
247 | u8 this_v = drm_dp_get_adjust_request_voltage(link_status, lane); |
305 | u8 this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane); |
248 | u8 this_p = drm_dp_get_adjust_request_pre_emphasis(link_status, lane); |
306 | 249 | ||
307 | DRM_DEBUG_KMS("requested signal parameters: lane %d voltage %s pre_emph %s\n", |
250 | DRM_DEBUG_KMS("requested signal parameters: lane %d voltage %s pre_emph %s\n", |
308 | lane, |
251 | lane, |
309 | voltage_names[this_v >> DP_TRAIN_VOLTAGE_SWING_SHIFT], |
252 | voltage_names[this_v >> DP_TRAIN_VOLTAGE_SWING_SHIFT], |
310 | pre_emph_names[this_p >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); |
253 | pre_emph_names[this_p >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); |
311 | 254 | ||
312 | if (this_v > v) |
255 | if (this_v > v) |
313 | v = this_v; |
256 | v = this_v; |
314 | if (this_p > p) |
257 | if (this_p > p) |
315 | p = this_p; |
258 | p = this_p; |
316 | } |
259 | } |
317 | 260 | ||
318 | if (v >= DP_VOLTAGE_MAX) |
261 | if (v >= DP_VOLTAGE_MAX) |
319 | v |= DP_TRAIN_MAX_SWING_REACHED; |
262 | v |= DP_TRAIN_MAX_SWING_REACHED; |
320 | 263 | ||
321 | if (p >= DP_PRE_EMPHASIS_MAX) |
264 | if (p >= DP_PRE_EMPHASIS_MAX) |
322 | p |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; |
265 | p |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; |
323 | 266 | ||
324 | DRM_DEBUG_KMS("using signal parameters: voltage %s pre_emph %s\n", |
267 | DRM_DEBUG_KMS("using signal parameters: voltage %s pre_emph %s\n", |
325 | voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK) >> DP_TRAIN_VOLTAGE_SWING_SHIFT], |
268 | voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK) >> DP_TRAIN_VOLTAGE_SWING_SHIFT], |
326 | pre_emph_names[(p & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); |
269 | pre_emph_names[(p & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); |
327 | 270 | ||
328 | for (lane = 0; lane < 4; lane++) |
271 | for (lane = 0; lane < 4; lane++) |
329 | train_set[lane] = v | p; |
272 | train_set[lane] = v | p; |
330 | } |
273 | } |
331 | 274 | ||
332 | /* convert bits per color to bits per pixel */ |
275 | /* convert bits per color to bits per pixel */ |
333 | /* get bpc from the EDID */ |
276 | /* get bpc from the EDID */ |
334 | static int convert_bpc_to_bpp(int bpc) |
277 | static int convert_bpc_to_bpp(int bpc) |
335 | { |
278 | { |
336 | if (bpc == 0) |
279 | if (bpc == 0) |
337 | return 24; |
280 | return 24; |
338 | else |
281 | else |
339 | return bpc * 3; |
282 | return bpc * 3; |
340 | } |
283 | } |
341 | 284 | ||
342 | /* get the max pix clock supported by the link rate and lane num */ |
285 | /* get the max pix clock supported by the link rate and lane num */ |
343 | static int dp_get_max_dp_pix_clock(int link_rate, |
286 | static int dp_get_max_dp_pix_clock(int link_rate, |
344 | int lane_num, |
287 | int lane_num, |
345 | int bpp) |
288 | int bpp) |
346 | { |
289 | { |
347 | return (link_rate * lane_num * 8) / bpp; |
290 | return (link_rate * lane_num * 8) / bpp; |
348 | } |
291 | } |
349 | 292 | ||
350 | /***** radeon specific DP functions *****/ |
293 | /***** radeon specific DP functions *****/ |
- | 294 | ||
- | 295 | static int radeon_dp_get_max_link_rate(struct drm_connector *connector, |
|
- | 296 | u8 dpcd[DP_DPCD_SIZE]) |
|
- | 297 | { |
|
- | 298 | int max_link_rate; |
|
- | 299 | ||
- | 300 | if (radeon_connector_is_dp12_capable(connector)) |
|
- | 301 | max_link_rate = min(drm_dp_max_link_rate(dpcd), 540000); |
|
- | 302 | else |
|
- | 303 | max_link_rate = min(drm_dp_max_link_rate(dpcd), 270000); |
|
- | 304 | ||
- | 305 | return max_link_rate; |
|
- | 306 | } |
|
351 | 307 | ||
352 | /* First get the min lane# when low rate is used according to pixel clock |
308 | /* First get the min lane# when low rate is used according to pixel clock |
353 | * (prefer low rate), second check max lane# supported by DP panel, |
309 | * (prefer low rate), second check max lane# supported by DP panel, |
354 | * if the max lane# < low rate lane# then use max lane# instead. |
310 | * if the max lane# < low rate lane# then use max lane# instead. |
355 | */ |
311 | */ |
356 | static int radeon_dp_get_dp_lane_number(struct drm_connector *connector, |
312 | static int radeon_dp_get_dp_lane_number(struct drm_connector *connector, |
357 | u8 dpcd[DP_DPCD_SIZE], |
313 | u8 dpcd[DP_DPCD_SIZE], |
358 | int pix_clock) |
314 | int pix_clock) |
359 | { |
315 | { |
360 | int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); |
316 | int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); |
361 | int max_link_rate = drm_dp_max_link_rate(dpcd); |
317 | int max_link_rate = radeon_dp_get_max_link_rate(connector, dpcd); |
362 | int max_lane_num = drm_dp_max_lane_count(dpcd); |
318 | int max_lane_num = drm_dp_max_lane_count(dpcd); |
363 | int lane_num; |
319 | int lane_num; |
364 | int max_dp_pix_clock; |
320 | int max_dp_pix_clock; |
365 | 321 | ||
366 | for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) { |
322 | for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) { |
367 | max_dp_pix_clock = dp_get_max_dp_pix_clock(max_link_rate, lane_num, bpp); |
323 | max_dp_pix_clock = dp_get_max_dp_pix_clock(max_link_rate, lane_num, bpp); |
368 | if (pix_clock <= max_dp_pix_clock) |
324 | if (pix_clock <= max_dp_pix_clock) |
369 | break; |
325 | break; |
370 | } |
326 | } |
371 | 327 | ||
372 | return lane_num; |
328 | return lane_num; |
373 | } |
329 | } |
374 | 330 | ||
375 | static int radeon_dp_get_dp_link_clock(struct drm_connector *connector, |
331 | static int radeon_dp_get_dp_link_clock(struct drm_connector *connector, |
376 | u8 dpcd[DP_DPCD_SIZE], |
332 | u8 dpcd[DP_DPCD_SIZE], |
377 | int pix_clock) |
333 | int pix_clock) |
378 | { |
334 | { |
379 | int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); |
335 | int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); |
380 | int lane_num, max_pix_clock; |
336 | int lane_num, max_pix_clock; |
381 | 337 | ||
382 | if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == |
338 | if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == |
383 | ENCODER_OBJECT_ID_NUTMEG) |
339 | ENCODER_OBJECT_ID_NUTMEG) |
384 | return 270000; |
340 | return 270000; |
385 | 341 | ||
386 | lane_num = radeon_dp_get_dp_lane_number(connector, dpcd, pix_clock); |
342 | lane_num = radeon_dp_get_dp_lane_number(connector, dpcd, pix_clock); |
387 | max_pix_clock = dp_get_max_dp_pix_clock(162000, lane_num, bpp); |
343 | max_pix_clock = dp_get_max_dp_pix_clock(162000, lane_num, bpp); |
388 | if (pix_clock <= max_pix_clock) |
344 | if (pix_clock <= max_pix_clock) |
389 | return 162000; |
345 | return 162000; |
390 | max_pix_clock = dp_get_max_dp_pix_clock(270000, lane_num, bpp); |
346 | max_pix_clock = dp_get_max_dp_pix_clock(270000, lane_num, bpp); |
391 | if (pix_clock <= max_pix_clock) |
347 | if (pix_clock <= max_pix_clock) |
392 | return 270000; |
348 | return 270000; |
393 | if (radeon_connector_is_dp12_capable(connector)) { |
349 | if (radeon_connector_is_dp12_capable(connector)) { |
394 | max_pix_clock = dp_get_max_dp_pix_clock(540000, lane_num, bpp); |
350 | max_pix_clock = dp_get_max_dp_pix_clock(540000, lane_num, bpp); |
395 | if (pix_clock <= max_pix_clock) |
351 | if (pix_clock <= max_pix_clock) |
396 | return 540000; |
352 | return 540000; |
397 | } |
353 | } |
398 | 354 | ||
399 | return drm_dp_max_link_rate(dpcd); |
355 | return radeon_dp_get_max_link_rate(connector, dpcd); |
400 | } |
356 | } |
401 | 357 | ||
402 | static u8 radeon_dp_encoder_service(struct radeon_device *rdev, |
358 | static u8 radeon_dp_encoder_service(struct radeon_device *rdev, |
403 | int action, int dp_clock, |
359 | int action, int dp_clock, |
404 | u8 ucconfig, u8 lane_num) |
360 | u8 ucconfig, u8 lane_num) |
405 | { |
361 | { |
406 | DP_ENCODER_SERVICE_PARAMETERS args; |
362 | DP_ENCODER_SERVICE_PARAMETERS args; |
407 | int index = GetIndexIntoMasterTable(COMMAND, DPEncoderService); |
363 | int index = GetIndexIntoMasterTable(COMMAND, DPEncoderService); |
408 | 364 | ||
409 | memset(&args, 0, sizeof(args)); |
365 | memset(&args, 0, sizeof(args)); |
410 | args.ucLinkClock = dp_clock / 10; |
366 | args.ucLinkClock = dp_clock / 10; |
411 | args.ucConfig = ucconfig; |
367 | args.ucConfig = ucconfig; |
412 | args.ucAction = action; |
368 | args.ucAction = action; |
413 | args.ucLaneNum = lane_num; |
369 | args.ucLaneNum = lane_num; |
414 | args.ucStatus = 0; |
370 | args.ucStatus = 0; |
415 | 371 | ||
416 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
372 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
417 | return args.ucStatus; |
373 | return args.ucStatus; |
418 | } |
374 | } |
419 | 375 | ||
420 | u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector) |
376 | u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector) |
421 | { |
377 | { |
422 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
- | |
423 | struct drm_device *dev = radeon_connector->base.dev; |
378 | struct drm_device *dev = radeon_connector->base.dev; |
424 | struct radeon_device *rdev = dev->dev_private; |
379 | struct radeon_device *rdev = dev->dev_private; |
425 | 380 | ||
426 | return radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_GET_SINK_TYPE, 0, |
381 | return radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_GET_SINK_TYPE, 0, |
427 | dig_connector->dp_i2c_bus->rec.i2c_id, 0); |
382 | radeon_connector->ddc_bus->rec.i2c_id, 0); |
428 | } |
383 | } |
429 | 384 | ||
430 | static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector) |
385 | static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector) |
431 | { |
386 | { |
432 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
387 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
433 | u8 buf[3]; |
388 | u8 buf[3]; |
434 | 389 | ||
435 | if (!(dig_connector->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) |
390 | if (!(dig_connector->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) |
436 | return; |
391 | return; |
437 | 392 | ||
438 | if (radeon_dp_aux_native_read(radeon_connector, DP_SINK_OUI, buf, 3, 0)) |
393 | if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_SINK_OUI, buf, 3) == 3) |
439 | DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n", |
394 | DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n", |
440 | buf[0], buf[1], buf[2]); |
395 | buf[0], buf[1], buf[2]); |
441 | 396 | ||
442 | if (radeon_dp_aux_native_read(radeon_connector, DP_BRANCH_OUI, buf, 3, 0)) |
397 | if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_BRANCH_OUI, buf, 3) == 3) |
443 | DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n", |
398 | DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n", |
444 | buf[0], buf[1], buf[2]); |
399 | buf[0], buf[1], buf[2]); |
445 | } |
400 | } |
446 | 401 | ||
447 | bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) |
402 | bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) |
448 | { |
403 | { |
449 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
404 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
450 | u8 msg[DP_DPCD_SIZE]; |
405 | u8 msg[DP_DPCD_SIZE]; |
451 | int ret, i; |
406 | int ret; |
- | 407 | ||
- | 408 | char dpcd_hex_dump[DP_DPCD_SIZE * 3]; |
|
452 | 409 | ||
453 | ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, msg, |
410 | ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_DPCD_REV, msg, |
454 | DP_DPCD_SIZE, 0); |
411 | DP_DPCD_SIZE); |
455 | if (ret > 0) { |
412 | if (ret > 0) { |
456 | memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); |
- | |
- | 413 | memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); |
|
457 | DRM_DEBUG_KMS("DPCD: "); |
414 | |
458 | for (i = 0; i < DP_DPCD_SIZE; i++) |
415 | hex_dump_to_buffer(dig_connector->dpcd, sizeof(dig_connector->dpcd), |
459 | DRM_DEBUG_KMS("%02x ", msg[i]); |
416 | 32, 1, dpcd_hex_dump, sizeof(dpcd_hex_dump), false); |
460 | DRM_DEBUG_KMS("\n"); |
417 | DRM_DEBUG_KMS("DPCD: %s\n", dpcd_hex_dump); |
461 | 418 | ||
462 | radeon_dp_probe_oui(radeon_connector); |
419 | radeon_dp_probe_oui(radeon_connector); |
463 | 420 | ||
464 | return true; |
421 | return true; |
465 | } |
422 | } |
466 | dig_connector->dpcd[0] = 0; |
423 | dig_connector->dpcd[0] = 0; |
467 | return false; |
424 | return false; |
468 | } |
425 | } |
469 | 426 | ||
470 | int radeon_dp_get_panel_mode(struct drm_encoder *encoder, |
427 | int radeon_dp_get_panel_mode(struct drm_encoder *encoder, |
471 | struct drm_connector *connector) |
428 | struct drm_connector *connector) |
472 | { |
429 | { |
473 | struct drm_device *dev = encoder->dev; |
430 | struct drm_device *dev = encoder->dev; |
474 | struct radeon_device *rdev = dev->dev_private; |
431 | struct radeon_device *rdev = dev->dev_private; |
475 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
432 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
- | 433 | struct radeon_connector_atom_dig *dig_connector; |
|
476 | int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; |
434 | int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; |
477 | u16 dp_bridge = radeon_connector_encoder_get_dp_bridge_encoder_id(connector); |
435 | u16 dp_bridge = radeon_connector_encoder_get_dp_bridge_encoder_id(connector); |
478 | u8 tmp; |
436 | u8 tmp; |
479 | 437 | ||
480 | if (!ASIC_IS_DCE4(rdev)) |
438 | if (!ASIC_IS_DCE4(rdev)) |
481 | return panel_mode; |
439 | return panel_mode; |
- | 440 | ||
- | 441 | if (!radeon_connector->con_priv) |
|
- | 442 | return panel_mode; |
|
- | 443 | ||
- | 444 | dig_connector = radeon_connector->con_priv; |
|
482 | 445 | ||
483 | if (dp_bridge != ENCODER_OBJECT_ID_NONE) { |
446 | if (dp_bridge != ENCODER_OBJECT_ID_NONE) { |
484 | /* DP bridge chips */ |
447 | /* DP bridge chips */ |
- | 448 | if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, |
|
485 | tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); |
449 | DP_EDP_CONFIGURATION_CAP, &tmp) == 1) { |
486 | if (tmp & 1) |
450 | if (tmp & 1) |
487 | panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; |
451 | panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; |
488 | else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) || |
452 | else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) || |
489 | (dp_bridge == ENCODER_OBJECT_ID_TRAVIS)) |
453 | (dp_bridge == ENCODER_OBJECT_ID_TRAVIS)) |
490 | panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; |
454 | panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; |
491 | else |
455 | else |
492 | panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; |
456 | panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; |
- | 457 | } |
|
493 | } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { |
458 | } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { |
494 | /* eDP */ |
459 | /* eDP */ |
495 | tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP); |
460 | if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, |
- | 461 | DP_EDP_CONFIGURATION_CAP, &tmp) == 1) { |
|
496 | if (tmp & 1) |
462 | if (tmp & 1) |
497 | panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; |
463 | panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; |
498 | } |
464 | } |
- | 465 | } |
|
499 | 466 | ||
500 | return panel_mode; |
467 | return panel_mode; |
501 | } |
468 | } |
502 | 469 | ||
503 | void radeon_dp_set_link_config(struct drm_connector *connector, |
470 | void radeon_dp_set_link_config(struct drm_connector *connector, |
504 | const struct drm_display_mode *mode) |
471 | const struct drm_display_mode *mode) |
505 | { |
472 | { |
506 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
473 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
507 | struct radeon_connector_atom_dig *dig_connector; |
474 | struct radeon_connector_atom_dig *dig_connector; |
508 | 475 | ||
509 | if (!radeon_connector->con_priv) |
476 | if (!radeon_connector->con_priv) |
510 | return; |
477 | return; |
511 | dig_connector = radeon_connector->con_priv; |
478 | dig_connector = radeon_connector->con_priv; |
512 | 479 | ||
513 | if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || |
480 | if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || |
514 | (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { |
481 | (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { |
515 | dig_connector->dp_clock = |
482 | dig_connector->dp_clock = |
516 | radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); |
483 | radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); |
517 | dig_connector->dp_lane_count = |
484 | dig_connector->dp_lane_count = |
518 | radeon_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock); |
485 | radeon_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock); |
519 | } |
486 | } |
520 | } |
487 | } |
521 | 488 | ||
522 | int radeon_dp_mode_valid_helper(struct drm_connector *connector, |
489 | int radeon_dp_mode_valid_helper(struct drm_connector *connector, |
523 | struct drm_display_mode *mode) |
490 | struct drm_display_mode *mode) |
524 | { |
491 | { |
525 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
492 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
526 | struct radeon_connector_atom_dig *dig_connector; |
493 | struct radeon_connector_atom_dig *dig_connector; |
527 | int dp_clock; |
494 | int dp_clock; |
528 | 495 | ||
529 | if (!radeon_connector->con_priv) |
496 | if (!radeon_connector->con_priv) |
530 | return MODE_CLOCK_HIGH; |
497 | return MODE_CLOCK_HIGH; |
531 | dig_connector = radeon_connector->con_priv; |
498 | dig_connector = radeon_connector->con_priv; |
532 | 499 | ||
533 | dp_clock = |
500 | dp_clock = |
534 | radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); |
501 | radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); |
535 | 502 | ||
536 | if ((dp_clock == 540000) && |
503 | if ((dp_clock == 540000) && |
537 | (!radeon_connector_is_dp12_capable(connector))) |
504 | (!radeon_connector_is_dp12_capable(connector))) |
538 | return MODE_CLOCK_HIGH; |
505 | return MODE_CLOCK_HIGH; |
539 | 506 | ||
540 | return MODE_OK; |
507 | return MODE_OK; |
541 | } |
508 | } |
542 | - | ||
543 | static bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector, |
- | |
544 | u8 link_status[DP_LINK_STATUS_SIZE]) |
- | |
545 | { |
- | |
546 | int ret; |
- | |
547 | ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, |
- | |
548 | link_status, DP_LINK_STATUS_SIZE, 100); |
- | |
549 | if (ret <= 0) { |
- | |
550 | return false; |
- | |
551 | } |
- | |
552 | - | ||
553 | DRM_DEBUG_KMS("link status %*ph\n", 6, link_status); |
- | |
554 | return true; |
- | |
555 | } |
- | |
556 | 509 | ||
557 | bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector) |
510 | bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector) |
558 | { |
511 | { |
559 | u8 link_status[DP_LINK_STATUS_SIZE]; |
512 | u8 link_status[DP_LINK_STATUS_SIZE]; |
560 | struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; |
513 | struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; |
561 | 514 | ||
- | 515 | if (drm_dp_dpcd_read_link_status(&radeon_connector->ddc_bus->aux, link_status) |
|
562 | if (!radeon_dp_get_link_status(radeon_connector, link_status)) |
516 | <= 0) |
563 | return false; |
517 | return false; |
564 | if (drm_dp_channel_eq_ok(link_status, dig->dp_lane_count)) |
518 | if (drm_dp_channel_eq_ok(link_status, dig->dp_lane_count)) |
565 | return false; |
519 | return false; |
566 | return true; |
520 | return true; |
567 | } |
521 | } |
- | 522 | ||
- | 523 | void radeon_dp_set_rx_power_state(struct drm_connector *connector, |
|
- | 524 | u8 power_state) |
|
- | 525 | { |
|
- | 526 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
|
- | 527 | struct radeon_connector_atom_dig *dig_connector; |
|
- | 528 | ||
- | 529 | if (!radeon_connector->con_priv) |
|
- | 530 | return; |
|
- | 531 | ||
- | 532 | dig_connector = radeon_connector->con_priv; |
|
- | 533 | ||
- | 534 | /* power up/down the sink */ |
|
- | 535 | if (dig_connector->dpcd[0] >= 0x11) { |
|
- | 536 | drm_dp_dpcd_writeb(&radeon_connector->ddc_bus->aux, |
|
- | 537 | DP_SET_POWER, power_state); |
|
- | 538 | usleep_range(1000, 2000); |
|
- | 539 | } |
|
- | 540 | } |
|
- | 541 | ||
568 | 542 | ||
569 | struct radeon_dp_link_train_info { |
543 | struct radeon_dp_link_train_info { |
570 | struct radeon_device *rdev; |
544 | struct radeon_device *rdev; |
571 | struct drm_encoder *encoder; |
545 | struct drm_encoder *encoder; |
572 | struct drm_connector *connector; |
546 | struct drm_connector *connector; |
573 | struct radeon_connector *radeon_connector; |
- | |
574 | int enc_id; |
547 | int enc_id; |
575 | int dp_clock; |
548 | int dp_clock; |
576 | int dp_lane_count; |
549 | int dp_lane_count; |
577 | bool tp3_supported; |
550 | bool tp3_supported; |
578 | u8 dpcd[DP_RECEIVER_CAP_SIZE]; |
551 | u8 dpcd[DP_RECEIVER_CAP_SIZE]; |
579 | u8 train_set[4]; |
552 | u8 train_set[4]; |
580 | u8 link_status[DP_LINK_STATUS_SIZE]; |
553 | u8 link_status[DP_LINK_STATUS_SIZE]; |
581 | u8 tries; |
554 | u8 tries; |
582 | bool use_dpencoder; |
555 | bool use_dpencoder; |
- | 556 | struct drm_dp_aux *aux; |
|
583 | }; |
557 | }; |
584 | 558 | ||
585 | static void radeon_dp_update_vs_emph(struct radeon_dp_link_train_info *dp_info) |
559 | static void radeon_dp_update_vs_emph(struct radeon_dp_link_train_info *dp_info) |
586 | { |
560 | { |
587 | /* set the initial vs/emph on the source */ |
561 | /* set the initial vs/emph on the source */ |
588 | atombios_dig_transmitter_setup(dp_info->encoder, |
562 | atombios_dig_transmitter_setup(dp_info->encoder, |
589 | ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH, |
563 | ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH, |
590 | 0, dp_info->train_set[0]); /* sets all lanes at once */ |
564 | 0, dp_info->train_set[0]); /* sets all lanes at once */ |
591 | 565 | ||
592 | /* set the vs/emph on the sink */ |
566 | /* set the vs/emph on the sink */ |
593 | radeon_dp_aux_native_write(dp_info->radeon_connector, DP_TRAINING_LANE0_SET, |
567 | drm_dp_dpcd_write(dp_info->aux, DP_TRAINING_LANE0_SET, |
594 | dp_info->train_set, dp_info->dp_lane_count, 0); |
568 | dp_info->train_set, dp_info->dp_lane_count); |
595 | } |
569 | } |
596 | 570 | ||
597 | static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp) |
571 | static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp) |
598 | { |
572 | { |
599 | int rtp = 0; |
573 | int rtp = 0; |
600 | 574 | ||
601 | /* set training pattern on the source */ |
575 | /* set training pattern on the source */ |
602 | if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) { |
576 | if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) { |
603 | switch (tp) { |
577 | switch (tp) { |
604 | case DP_TRAINING_PATTERN_1: |
578 | case DP_TRAINING_PATTERN_1: |
605 | rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1; |
579 | rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1; |
606 | break; |
580 | break; |
607 | case DP_TRAINING_PATTERN_2: |
581 | case DP_TRAINING_PATTERN_2: |
608 | rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2; |
582 | rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2; |
609 | break; |
583 | break; |
610 | case DP_TRAINING_PATTERN_3: |
584 | case DP_TRAINING_PATTERN_3: |
611 | rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3; |
585 | rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3; |
612 | break; |
586 | break; |
613 | } |
587 | } |
614 | atombios_dig_encoder_setup(dp_info->encoder, rtp, 0); |
588 | atombios_dig_encoder_setup(dp_info->encoder, rtp, 0); |
615 | } else { |
589 | } else { |
616 | switch (tp) { |
590 | switch (tp) { |
617 | case DP_TRAINING_PATTERN_1: |
591 | case DP_TRAINING_PATTERN_1: |
618 | rtp = 0; |
592 | rtp = 0; |
619 | break; |
593 | break; |
620 | case DP_TRAINING_PATTERN_2: |
594 | case DP_TRAINING_PATTERN_2: |
621 | rtp = 1; |
595 | rtp = 1; |
622 | break; |
596 | break; |
623 | } |
597 | } |
624 | radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, |
598 | radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, |
625 | dp_info->dp_clock, dp_info->enc_id, rtp); |
599 | dp_info->dp_clock, dp_info->enc_id, rtp); |
626 | } |
600 | } |
627 | 601 | ||
628 | /* enable training pattern on the sink */ |
602 | /* enable training pattern on the sink */ |
629 | radeon_write_dpcd_reg(dp_info->radeon_connector, DP_TRAINING_PATTERN_SET, tp); |
603 | drm_dp_dpcd_writeb(dp_info->aux, DP_TRAINING_PATTERN_SET, tp); |
630 | } |
604 | } |
631 | 605 | ||
632 | static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info) |
606 | static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info) |
633 | { |
607 | { |
634 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(dp_info->encoder); |
608 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(dp_info->encoder); |
635 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
609 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
636 | u8 tmp; |
610 | u8 tmp; |
637 | 611 | ||
638 | /* power up the sink */ |
612 | /* power up the sink */ |
639 | if (dp_info->dpcd[0] >= 0x11) |
- | |
640 | radeon_write_dpcd_reg(dp_info->radeon_connector, |
613 | radeon_dp_set_rx_power_state(dp_info->connector, DP_SET_POWER_D0); |
641 | DP_SET_POWER, DP_SET_POWER_D0); |
- | |
642 | 614 | ||
643 | /* possibly enable downspread on the sink */ |
615 | /* possibly enable downspread on the sink */ |
644 | if (dp_info->dpcd[3] & 0x1) |
616 | if (dp_info->dpcd[3] & 0x1) |
645 | radeon_write_dpcd_reg(dp_info->radeon_connector, |
617 | drm_dp_dpcd_writeb(dp_info->aux, |
646 | DP_DOWNSPREAD_CTRL, DP_SPREAD_AMP_0_5); |
618 | DP_DOWNSPREAD_CTRL, DP_SPREAD_AMP_0_5); |
647 | else |
619 | else |
648 | radeon_write_dpcd_reg(dp_info->radeon_connector, |
620 | drm_dp_dpcd_writeb(dp_info->aux, |
649 | DP_DOWNSPREAD_CTRL, 0); |
621 | DP_DOWNSPREAD_CTRL, 0); |
650 | 622 | ||
651 | if ((dp_info->connector->connector_type == DRM_MODE_CONNECTOR_eDP) && |
623 | if ((dp_info->connector->connector_type == DRM_MODE_CONNECTOR_eDP) && |
652 | (dig->panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) { |
624 | (dig->panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) { |
653 | radeon_write_dpcd_reg(dp_info->radeon_connector, DP_EDP_CONFIGURATION_SET, 1); |
625 | drm_dp_dpcd_writeb(dp_info->aux, DP_EDP_CONFIGURATION_SET, 1); |
654 | } |
626 | } |
655 | 627 | ||
656 | /* set the lane count on the sink */ |
628 | /* set the lane count on the sink */ |
657 | tmp = dp_info->dp_lane_count; |
629 | tmp = dp_info->dp_lane_count; |
658 | if (dp_info->dpcd[DP_DPCD_REV] >= 0x11 && |
630 | if (drm_dp_enhanced_frame_cap(dp_info->dpcd)) |
659 | dp_info->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP) |
- | |
660 | tmp |= DP_LANE_COUNT_ENHANCED_FRAME_EN; |
631 | tmp |= DP_LANE_COUNT_ENHANCED_FRAME_EN; |
661 | radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LANE_COUNT_SET, tmp); |
632 | drm_dp_dpcd_writeb(dp_info->aux, DP_LANE_COUNT_SET, tmp); |
662 | 633 | ||
663 | /* set the link rate on the sink */ |
634 | /* set the link rate on the sink */ |
664 | tmp = drm_dp_link_rate_to_bw_code(dp_info->dp_clock); |
635 | tmp = drm_dp_link_rate_to_bw_code(dp_info->dp_clock); |
665 | radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp); |
636 | drm_dp_dpcd_writeb(dp_info->aux, DP_LINK_BW_SET, tmp); |
666 | 637 | ||
667 | /* start training on the source */ |
638 | /* start training on the source */ |
668 | if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) |
639 | if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) |
669 | atombios_dig_encoder_setup(dp_info->encoder, |
640 | atombios_dig_encoder_setup(dp_info->encoder, |
670 | ATOM_ENCODER_CMD_DP_LINK_TRAINING_START, 0); |
641 | ATOM_ENCODER_CMD_DP_LINK_TRAINING_START, 0); |
671 | else |
642 | else |
672 | radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_START, |
643 | radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_START, |
673 | dp_info->dp_clock, dp_info->enc_id, 0); |
644 | dp_info->dp_clock, dp_info->enc_id, 0); |
674 | 645 | ||
675 | /* disable the training pattern on the sink */ |
646 | /* disable the training pattern on the sink */ |
676 | radeon_write_dpcd_reg(dp_info->radeon_connector, |
647 | drm_dp_dpcd_writeb(dp_info->aux, |
677 | DP_TRAINING_PATTERN_SET, |
648 | DP_TRAINING_PATTERN_SET, |
678 | DP_TRAINING_PATTERN_DISABLE); |
649 | DP_TRAINING_PATTERN_DISABLE); |
679 | 650 | ||
680 | return 0; |
651 | return 0; |
681 | } |
652 | } |
682 | 653 | ||
683 | static int radeon_dp_link_train_finish(struct radeon_dp_link_train_info *dp_info) |
654 | static int radeon_dp_link_train_finish(struct radeon_dp_link_train_info *dp_info) |
684 | { |
655 | { |
685 | udelay(400); |
656 | udelay(400); |
686 | 657 | ||
687 | /* disable the training pattern on the sink */ |
658 | /* disable the training pattern on the sink */ |
688 | radeon_write_dpcd_reg(dp_info->radeon_connector, |
659 | drm_dp_dpcd_writeb(dp_info->aux, |
689 | DP_TRAINING_PATTERN_SET, |
660 | DP_TRAINING_PATTERN_SET, |
690 | DP_TRAINING_PATTERN_DISABLE); |
661 | DP_TRAINING_PATTERN_DISABLE); |
691 | 662 | ||
692 | /* disable the training pattern on the source */ |
663 | /* disable the training pattern on the source */ |
693 | if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) |
664 | if (ASIC_IS_DCE4(dp_info->rdev) || !dp_info->use_dpencoder) |
694 | atombios_dig_encoder_setup(dp_info->encoder, |
665 | atombios_dig_encoder_setup(dp_info->encoder, |
695 | ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE, 0); |
666 | ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE, 0); |
696 | else |
667 | else |
697 | radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_COMPLETE, |
668 | radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_COMPLETE, |
698 | dp_info->dp_clock, dp_info->enc_id, 0); |
669 | dp_info->dp_clock, dp_info->enc_id, 0); |
699 | 670 | ||
700 | return 0; |
671 | return 0; |
701 | } |
672 | } |
702 | 673 | ||
703 | static int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info) |
674 | static int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info) |
704 | { |
675 | { |
705 | bool clock_recovery; |
676 | bool clock_recovery; |
706 | u8 voltage; |
677 | u8 voltage; |
707 | int i; |
678 | int i; |
708 | 679 | ||
709 | radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_1); |
680 | radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_1); |
710 | memset(dp_info->train_set, 0, 4); |
681 | memset(dp_info->train_set, 0, 4); |
711 | radeon_dp_update_vs_emph(dp_info); |
682 | radeon_dp_update_vs_emph(dp_info); |
712 | 683 | ||
713 | udelay(400); |
684 | udelay(400); |
714 | 685 | ||
715 | /* clock recovery loop */ |
686 | /* clock recovery loop */ |
716 | clock_recovery = false; |
687 | clock_recovery = false; |
717 | dp_info->tries = 0; |
688 | dp_info->tries = 0; |
718 | voltage = 0xff; |
689 | voltage = 0xff; |
719 | while (1) { |
690 | while (1) { |
720 | drm_dp_link_train_clock_recovery_delay(dp_info->dpcd); |
691 | drm_dp_link_train_clock_recovery_delay(dp_info->dpcd); |
721 | 692 | ||
- | 693 | if (drm_dp_dpcd_read_link_status(dp_info->aux, |
|
722 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { |
694 | dp_info->link_status) <= 0) { |
723 | DRM_ERROR("displayport link status failed\n"); |
695 | DRM_ERROR("displayport link status failed\n"); |
724 | break; |
696 | break; |
725 | } |
697 | } |
726 | 698 | ||
727 | if (drm_dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { |
699 | if (drm_dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { |
728 | clock_recovery = true; |
700 | clock_recovery = true; |
729 | break; |
701 | break; |
730 | } |
702 | } |
731 | 703 | ||
732 | for (i = 0; i < dp_info->dp_lane_count; i++) { |
704 | for (i = 0; i < dp_info->dp_lane_count; i++) { |
733 | if ((dp_info->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) |
705 | if ((dp_info->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) |
734 | break; |
706 | break; |
735 | } |
707 | } |
736 | if (i == dp_info->dp_lane_count) { |
708 | if (i == dp_info->dp_lane_count) { |
737 | DRM_ERROR("clock recovery reached max voltage\n"); |
709 | DRM_ERROR("clock recovery reached max voltage\n"); |
738 | break; |
710 | break; |
739 | } |
711 | } |
740 | 712 | ||
741 | if ((dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { |
713 | if ((dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { |
742 | ++dp_info->tries; |
714 | ++dp_info->tries; |
743 | if (dp_info->tries == 5) { |
715 | if (dp_info->tries == 5) { |
744 | DRM_ERROR("clock recovery tried 5 times\n"); |
716 | DRM_ERROR("clock recovery tried 5 times\n"); |
745 | break; |
717 | break; |
746 | } |
718 | } |
747 | } else |
719 | } else |
748 | dp_info->tries = 0; |
720 | dp_info->tries = 0; |
749 | 721 | ||
750 | voltage = dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; |
722 | voltage = dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; |
751 | 723 | ||
752 | /* Compute new train_set as requested by sink */ |
724 | /* Compute new train_set as requested by sink */ |
753 | dp_get_adjust_train(dp_info->link_status, dp_info->dp_lane_count, dp_info->train_set); |
725 | dp_get_adjust_train(dp_info->link_status, dp_info->dp_lane_count, dp_info->train_set); |
754 | 726 | ||
755 | radeon_dp_update_vs_emph(dp_info); |
727 | radeon_dp_update_vs_emph(dp_info); |
756 | } |
728 | } |
757 | if (!clock_recovery) { |
729 | if (!clock_recovery) { |
758 | DRM_ERROR("clock recovery failed\n"); |
730 | DRM_ERROR("clock recovery failed\n"); |
759 | return -1; |
731 | return -1; |
760 | } else { |
732 | } else { |
761 | DRM_DEBUG_KMS("clock recovery at voltage %d pre-emphasis %d\n", |
733 | DRM_DEBUG_KMS("clock recovery at voltage %d pre-emphasis %d\n", |
762 | dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, |
734 | dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, |
763 | (dp_info->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >> |
735 | (dp_info->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >> |
764 | DP_TRAIN_PRE_EMPHASIS_SHIFT); |
736 | DP_TRAIN_PRE_EMPHASIS_SHIFT); |
765 | return 0; |
737 | return 0; |
766 | } |
738 | } |
767 | } |
739 | } |
768 | 740 | ||
769 | static int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info) |
741 | static int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info) |
770 | { |
742 | { |
771 | bool channel_eq; |
743 | bool channel_eq; |
772 | 744 | ||
773 | if (dp_info->tp3_supported) |
745 | if (dp_info->tp3_supported) |
774 | radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_3); |
746 | radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_3); |
775 | else |
747 | else |
776 | radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_2); |
748 | radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_2); |
777 | 749 | ||
778 | /* channel equalization loop */ |
750 | /* channel equalization loop */ |
779 | dp_info->tries = 0; |
751 | dp_info->tries = 0; |
780 | channel_eq = false; |
752 | channel_eq = false; |
781 | while (1) { |
753 | while (1) { |
782 | drm_dp_link_train_channel_eq_delay(dp_info->dpcd); |
754 | drm_dp_link_train_channel_eq_delay(dp_info->dpcd); |
783 | 755 | ||
- | 756 | if (drm_dp_dpcd_read_link_status(dp_info->aux, |
|
784 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { |
757 | dp_info->link_status) <= 0) { |
785 | DRM_ERROR("displayport link status failed\n"); |
758 | DRM_ERROR("displayport link status failed\n"); |
786 | break; |
759 | break; |
787 | } |
760 | } |
788 | 761 | ||
789 | if (drm_dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { |
762 | if (drm_dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { |
790 | channel_eq = true; |
763 | channel_eq = true; |
791 | break; |
764 | break; |
792 | } |
765 | } |
793 | 766 | ||
794 | /* Try 5 times */ |
767 | /* Try 5 times */ |
795 | if (dp_info->tries > 5) { |
768 | if (dp_info->tries > 5) { |
796 | DRM_ERROR("channel eq failed: 5 tries\n"); |
769 | DRM_ERROR("channel eq failed: 5 tries\n"); |
797 | break; |
770 | break; |
798 | } |
771 | } |
799 | 772 | ||
800 | /* Compute new train_set as requested by sink */ |
773 | /* Compute new train_set as requested by sink */ |
801 | dp_get_adjust_train(dp_info->link_status, dp_info->dp_lane_count, dp_info->train_set); |
774 | dp_get_adjust_train(dp_info->link_status, dp_info->dp_lane_count, dp_info->train_set); |
802 | 775 | ||
803 | radeon_dp_update_vs_emph(dp_info); |
776 | radeon_dp_update_vs_emph(dp_info); |
804 | dp_info->tries++; |
777 | dp_info->tries++; |
805 | } |
778 | } |
806 | 779 | ||
807 | if (!channel_eq) { |
780 | if (!channel_eq) { |
808 | DRM_ERROR("channel eq failed\n"); |
781 | DRM_ERROR("channel eq failed\n"); |
809 | return -1; |
782 | return -1; |
810 | } else { |
783 | } else { |
811 | DRM_DEBUG_KMS("channel eq at voltage %d pre-emphasis %d\n", |
784 | DRM_DEBUG_KMS("channel eq at voltage %d pre-emphasis %d\n", |
812 | dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, |
785 | dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, |
813 | (dp_info->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) |
786 | (dp_info->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) |
814 | >> DP_TRAIN_PRE_EMPHASIS_SHIFT); |
787 | >> DP_TRAIN_PRE_EMPHASIS_SHIFT); |
815 | return 0; |
788 | return 0; |
816 | } |
789 | } |
817 | } |
790 | } |
818 | 791 | ||
819 | void radeon_dp_link_train(struct drm_encoder *encoder, |
792 | void radeon_dp_link_train(struct drm_encoder *encoder, |
820 | struct drm_connector *connector) |
793 | struct drm_connector *connector) |
821 | { |
794 | { |
822 | struct drm_device *dev = encoder->dev; |
795 | struct drm_device *dev = encoder->dev; |
823 | struct radeon_device *rdev = dev->dev_private; |
796 | struct radeon_device *rdev = dev->dev_private; |
824 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
797 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
825 | struct radeon_encoder_atom_dig *dig; |
798 | struct radeon_encoder_atom_dig *dig; |
826 | struct radeon_connector *radeon_connector; |
799 | struct radeon_connector *radeon_connector; |
827 | struct radeon_connector_atom_dig *dig_connector; |
800 | struct radeon_connector_atom_dig *dig_connector; |
828 | struct radeon_dp_link_train_info dp_info; |
801 | struct radeon_dp_link_train_info dp_info; |
829 | int index; |
802 | int index; |
830 | u8 tmp, frev, crev; |
803 | u8 tmp, frev, crev; |
831 | 804 | ||
832 | if (!radeon_encoder->enc_priv) |
805 | if (!radeon_encoder->enc_priv) |
833 | return; |
806 | return; |
834 | dig = radeon_encoder->enc_priv; |
807 | dig = radeon_encoder->enc_priv; |
835 | 808 | ||
836 | radeon_connector = to_radeon_connector(connector); |
809 | radeon_connector = to_radeon_connector(connector); |
837 | if (!radeon_connector->con_priv) |
810 | if (!radeon_connector->con_priv) |
838 | return; |
811 | return; |
839 | dig_connector = radeon_connector->con_priv; |
812 | dig_connector = radeon_connector->con_priv; |
840 | 813 | ||
841 | if ((dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_DISPLAYPORT) && |
814 | if ((dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_DISPLAYPORT) && |
842 | (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_eDP)) |
815 | (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_eDP)) |
843 | return; |
816 | return; |
844 | 817 | ||
845 | /* DPEncoderService newer than 1.1 can't program properly the |
818 | /* DPEncoderService newer than 1.1 can't program properly the |
846 | * training pattern. When facing such version use the |
819 | * training pattern. When facing such version use the |
847 | * DIGXEncoderControl (X== 1 | 2) |
820 | * DIGXEncoderControl (X== 1 | 2) |
848 | */ |
821 | */ |
849 | dp_info.use_dpencoder = true; |
822 | dp_info.use_dpencoder = true; |
850 | index = GetIndexIntoMasterTable(COMMAND, DPEncoderService); |
823 | index = GetIndexIntoMasterTable(COMMAND, DPEncoderService); |
851 | if (atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) { |
824 | if (atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) { |
852 | if (crev > 1) { |
825 | if (crev > 1) { |
853 | dp_info.use_dpencoder = false; |
826 | dp_info.use_dpencoder = false; |
854 | } |
827 | } |
855 | } |
828 | } |
856 | 829 | ||
857 | dp_info.enc_id = 0; |
830 | dp_info.enc_id = 0; |
858 | if (dig->dig_encoder) |
831 | if (dig->dig_encoder) |
859 | dp_info.enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER; |
832 | dp_info.enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER; |
860 | else |
833 | else |
861 | dp_info.enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER; |
834 | dp_info.enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER; |
862 | if (dig->linkb) |
835 | if (dig->linkb) |
863 | dp_info.enc_id |= ATOM_DP_CONFIG_LINK_B; |
836 | dp_info.enc_id |= ATOM_DP_CONFIG_LINK_B; |
864 | else |
837 | else |
865 | dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; |
838 | dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; |
866 | 839 | ||
- | 840 | if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_MAX_LANE_COUNT, &tmp) |
|
867 | tmp = radeon_read_dpcd_reg(radeon_connector, DP_MAX_LANE_COUNT); |
841 | == 1) { |
868 | if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) |
842 | if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) |
869 | dp_info.tp3_supported = true; |
843 | dp_info.tp3_supported = true; |
870 | else |
844 | else |
871 | dp_info.tp3_supported = false; |
845 | dp_info.tp3_supported = false; |
- | 846 | } else { |
|
- | 847 | dp_info.tp3_supported = false; |
|
- | 848 | } |
|
872 | 849 | ||
873 | memcpy(dp_info.dpcd, dig_connector->dpcd, DP_RECEIVER_CAP_SIZE); |
850 | memcpy(dp_info.dpcd, dig_connector->dpcd, DP_RECEIVER_CAP_SIZE); |
874 | dp_info.rdev = rdev; |
851 | dp_info.rdev = rdev; |
875 | dp_info.encoder = encoder; |
852 | dp_info.encoder = encoder; |
876 | dp_info.connector = connector; |
853 | dp_info.connector = connector; |
877 | dp_info.radeon_connector = radeon_connector; |
- | |
878 | dp_info.dp_lane_count = dig_connector->dp_lane_count; |
854 | dp_info.dp_lane_count = dig_connector->dp_lane_count; |
879 | dp_info.dp_clock = dig_connector->dp_clock; |
855 | dp_info.dp_clock = dig_connector->dp_clock; |
- | 856 | dp_info.aux = &radeon_connector->ddc_bus->aux; |
|
880 | 857 | ||
881 | if (radeon_dp_link_train_init(&dp_info)) |
858 | if (radeon_dp_link_train_init(&dp_info)) |
882 | goto done; |
859 | goto done; |
883 | if (radeon_dp_link_train_cr(&dp_info)) |
860 | if (radeon_dp_link_train_cr(&dp_info)) |
884 | goto done; |
861 | goto done; |
885 | if (radeon_dp_link_train_ce(&dp_info)) |
862 | if (radeon_dp_link_train_ce(&dp_info)) |
886 | goto done; |
863 | goto done; |
887 | done: |
864 | done: |
888 | if (radeon_dp_link_train_finish(&dp_info)) |
865 | if (radeon_dp_link_train_finish(&dp_info)) |
889 | return; |
866 | return; |
890 | }>=>>=>=>=>=>=><=>>>>>>>><>><>><>><>><>><>>>><>><>>>><>><> |
867 | }=>>=>=>=>=>=>=>=><=>>>>>><>><>><>><>><>>>> |