Rev 1430 | Rev 2160 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1430 | Rev 1963 | ||
---|---|---|---|
Line 41... | Line 41... | ||
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 | }; |
Line 45... | Line 45... | ||
45 | 45 | ||
46 | static const int dp_clocks[] = { |
46 | /***** radeon AUX functions *****/ |
47 | 54000, /* 1 lane, 1.62 Ghz */ |
- | |
48 | 90000, /* 1 lane, 2.70 Ghz */ |
- | |
49 | 108000, /* 2 lane, 1.62 Ghz */ |
- | |
50 | 180000, /* 2 lane, 2.70 Ghz */ |
47 | union aux_channel_transaction { |
51 | 216000, /* 4 lane, 1.62 Ghz */ |
48 | PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1; |
52 | 360000, /* 4 lane, 2.70 Ghz */ |
49 | PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2; |
Line 53... | Line 50... | ||
53 | }; |
50 | }; |
54 | - | ||
55 | static const int num_dp_clocks = sizeof(dp_clocks) / sizeof(int); |
51 | |
56 | 52 | static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, |
|
- | 53 | u8 *send, int send_bytes, |
|
57 | /* common helper functions */ |
54 | u8 *recv, int recv_size, |
- | 55 | u8 delay, u8 *ack) |
|
- | 56 | { |
|
58 | static int dp_lanes_for_mode_clock(u8 dpcd[DP_DPCD_SIZE], int mode_clock) |
57 | struct drm_device *dev = chan->dev; |
- | 58 | struct radeon_device *rdev = dev->dev_private; |
|
59 | { |
59 | union aux_channel_transaction args; |
60 | int i; |
60 | int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); |
Line 61... | Line -... | ||
61 | u8 max_link_bw; |
- | |
62 | u8 max_lane_count; |
61 | unsigned char *base; |
Line 63... | Line -... | ||
63 | - | ||
64 | if (!dpcd) |
62 | int recv_bytes; |
Line 65... | Line -... | ||
65 | return 0; |
- | |
66 | 63 | ||
67 | max_link_bw = dpcd[DP_MAX_LINK_RATE]; |
64 | memset(&args, 0, sizeof(args)); |
68 | max_lane_count = dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; |
65 | |
69 | 66 | base = (unsigned char *)rdev->mode_info.atom_context->scratch; |
|
70 | switch (max_link_bw) { |
67 | |
71 | case DP_LINK_BW_1_62: |
68 | memcpy(base, send, send_bytes); |
72 | default: |
69 | |
73 | for (i = 0; i < num_dp_clocks; i++) { |
70 | args.v1.lpAuxRequest = 0; |
74 | if (i % 2) |
71 | args.v1.lpDataOut = 16; |
75 | continue; |
72 | args.v1.ucDataOutLen = 0; |
- | 73 | args.v1.ucChannelID = chan->rec.i2c_id; |
|
76 | switch (max_lane_count) { |
74 | args.v1.ucDelay = delay / 10; |
77 | case 1: |
75 | if (ASIC_IS_DCE4(rdev)) |
- | 76 | args.v2.ucHPD_ID = chan->rec.hpd; |
|
78 | if (i > 1) |
77 | |
79 | return 0; |
- | |
80 | break; |
78 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
81 | case 2: |
79 | |
82 | if (i > 3) |
80 | *ack = args.v1.ucReplyStatus; |
83 | return 0; |
81 | |
84 | break; |
- | |
85 | case 4: |
82 | /* timeout */ |
86 | default: |
83 | if (args.v1.ucReplyStatus == 1) { |
87 | break; |
84 | DRM_DEBUG_KMS("dp_aux_ch timeout\n"); |
88 | } |
85 | return -ETIMEDOUT; |
89 | if (dp_clocks[i] > mode_clock) { |
- | |
90 | if (i < 2) |
86 | } |
91 | return 1; |
87 | |
- | 88 | /* flags not zero */ |
|
- | 89 | if (args.v1.ucReplyStatus == 2) { |
|
- | 90 | DRM_DEBUG_KMS("dp_aux_ch flags not zero\n"); |
|
- | 91 | return -EBUSY; |
|
- | 92 | } |
|
92 | else if (i < 4) |
93 | |
- | 94 | /* error */ |
|
- | 95 | if (args.v1.ucReplyStatus == 3) { |
|
- | 96 | DRM_DEBUG_KMS("dp_aux_ch error\n"); |
|
- | 97 | return -EIO; |
|
- | 98 | } |
|
- | 99 | ||
- | 100 | recv_bytes = args.v1.ucDataOutLen; |
|
- | 101 | if (recv_bytes > recv_size) |
|
- | 102 | recv_bytes = recv_size; |
|
- | 103 | ||
- | 104 | if (recv && recv_size) |
|
- | 105 | memcpy(recv, base + 16, recv_bytes); |
|
- | 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 | ||
- | 119 | if (send_bytes > 16) |
|
- | 120 | return -1; |
|
- | 121 | ||
- | 122 | msg[0] = address; |
|
- | 123 | msg[1] = address >> 8; |
|
- | 124 | msg[2] = AUX_NATIVE_WRITE << 4; |
|
- | 125 | msg[3] = (msg_bytes << 4) | (send_bytes - 1); |
|
- | 126 | memcpy(&msg[4], send, send_bytes); |
|
- | 127 | ||
- | 128 | while (1) { |
|
93 | return 2; |
129 | ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, |
94 | else |
- | |
95 | return 4; |
130 | msg, msg_bytes, NULL, 0, delay, &ack); |
96 | } |
- | |
97 | } |
- | |
98 | break; |
- | |
99 | case DP_LINK_BW_2_7: |
131 | if (ret < 0) |
100 | for (i = 0; i < num_dp_clocks; i++) { |
- | |
101 | switch (max_lane_count) { |
132 | return ret; |
102 | case 1: |
- | |
103 | if (i > 1) |
133 | if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) |
104 | return 0; |
134 | break; |
105 | break; |
135 | else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) |
106 | case 2: |
- | |
107 | if (i > 3) |
136 | udelay(400); |
108 | return 0; |
137 | else |
- | 138 | return -EIO; |
|
- | 139 | } |
|
- | 140 | ||
- | 141 | return send_bytes; |
|
- | 142 | } |
|
- | 143 | ||
- | 144 | static int radeon_dp_aux_native_read(struct radeon_connector *radeon_connector, |
|
- | 145 | u16 address, u8 *recv, int recv_bytes, u8 delay) |
|
- | 146 | { |
|
- | 147 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
|
- | 148 | u8 msg[4]; |
|
- | 149 | int msg_bytes = 4; |
|
- | 150 | u8 ack; |
|
109 | break; |
151 | int ret; |
- | 152 | ||
- | 153 | msg[0] = address; |
|
- | 154 | msg[1] = address >> 8; |
|
- | 155 | msg[2] = AUX_NATIVE_READ << 4; |
|
110 | case 4: |
156 | msg[3] = (msg_bytes << 4) | (recv_bytes - 1); |
111 | default: |
157 | |
112 | break; |
158 | while (1) { |
- | 159 | ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, |
|
- | 160 | msg, msg_bytes, recv, recv_bytes, delay, &ack); |
|
113 | } |
161 | if (ret == 0) |
- | 162 | return -EPROTO; |
|
- | 163 | if (ret < 0) |
|
114 | if (dp_clocks[i] > mode_clock) { |
164 | return ret; |
115 | if (i < 2) |
165 | if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) |
116 | return 1; |
166 | return ret; |
117 | else if (i < 4) |
167 | else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) |
- | 168 | udelay(400); |
|
- | 169 | else |
|
118 | return 2; |
170 | return -EIO; |
- | 171 | } |
|
- | 172 | } |
|
119 | else |
173 | |
Line -... | Line 174... | ||
- | 174 | static void radeon_write_dpcd_reg(struct radeon_connector *radeon_connector, |
|
- | 175 | u16 reg, u8 val) |
|
- | 176 | { |
|
- | 177 | radeon_dp_aux_native_write(radeon_connector, reg, &val, 1, 0); |
|
- | 178 | } |
|
- | 179 | ||
- | 180 | static u8 radeon_read_dpcd_reg(struct radeon_connector *radeon_connector, |
|
120 | return 4; |
181 | u16 reg) |
121 | } |
182 | { |
Line 122... | Line 183... | ||
122 | } |
183 | u8 val = 0; |
- | 184 | ||
123 | break; |
185 | radeon_dp_aux_native_read(radeon_connector, reg, &val, 1, 0); |
- | 186 | ||
- | 187 | return val; |
|
- | 188 | } |
|
124 | } |
189 | |
125 | 190 | int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, |
|
- | 191 | u8 write_byte, u8 *read_byte) |
|
126 | return 0; |
192 | { |
- | 193 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; |
|
- | 194 | struct radeon_i2c_chan *auxch = (struct radeon_i2c_chan *)adapter; |
|
- | 195 | u16 address = algo_data->address; |
|
Line -... | Line 196... | ||
- | 196 | u8 msg[5]; |
|
127 | } |
197 | u8 reply[2]; |
- | 198 | unsigned retry; |
|
128 | 199 | int msg_bytes; |
|
- | 200 | int reply_bytes = 1; |
|
Line 129... | Line 201... | ||
129 | static int dp_link_clock_for_mode_clock(u8 dpcd[DP_DPCD_SIZE], int mode_clock) |
201 | int ret; |
130 | { |
202 | u8 ack; |
Line 131... | Line 203... | ||
131 | int i; |
203 | |
132 | u8 max_link_bw; |
204 | /* Set up the command byte */ |
133 | u8 max_lane_count; |
205 | if (mode & MODE_I2C_READ) |
134 | - | ||
135 | if (!dpcd) |
206 | msg[2] = AUX_I2C_READ << 4; |
136 | return 0; |
- | |
137 | 207 | else |
|
138 | max_link_bw = dpcd[DP_MAX_LINK_RATE]; |
208 | msg[2] = AUX_I2C_WRITE << 4; |
139 | max_lane_count = dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; |
209 | |
140 | 210 | if (!(mode & MODE_I2C_STOP)) |
|
141 | switch (max_link_bw) { |
211 | msg[2] |= AUX_I2C_MOT << 4; |
142 | case DP_LINK_BW_1_62: |
212 | |
143 | default: |
213 | msg[0] = address; |
144 | for (i = 0; i < num_dp_clocks; i++) { |
214 | msg[1] = address >> 8; |
145 | if (i % 2) |
215 | |
146 | continue; |
- | |
147 | switch (max_lane_count) { |
216 | switch (mode) { |
- | 217 | case MODE_I2C_WRITE: |
|
- | 218 | msg_bytes = 5; |
|
148 | case 1: |
219 | msg[3] = msg_bytes << 4; |
149 | if (i > 1) |
220 | msg[4] = write_byte; |
- | 221 | break; |
|
- | 222 | case MODE_I2C_READ: |
|
150 | return 0; |
223 | msg_bytes = 4; |
- | 224 | msg[3] = msg_bytes << 4; |
|
- | 225 | break; |
|
- | 226 | default: |
|
151 | break; |
227 | msg_bytes = 4; |
152 | case 2: |
228 | msg[3] = 3 << 4; |
- | 229 | break; |
|
- | 230 | } |
|
- | 231 | ||
- | 232 | for (retry = 0; retry < 4; retry++) { |
|
- | 233 | ret = radeon_process_aux_ch(auxch, |
|
- | 234 | msg, msg_bytes, reply, reply_bytes, 0, &ack); |
|
153 | if (i > 3) |
235 | if (ret < 0) { |
154 | return 0; |
236 | DRM_DEBUG_KMS("aux_ch failed %d\n", ret); |
155 | break; |
- | |
156 | case 4: |
237 | return ret; |
157 | default: |
- | |
158 | break; |
- | |
159 | } |
238 | } |
160 | if (dp_clocks[i] > mode_clock) |
- | |
161 | return 162000; |
239 | |
162 | } |
240 | switch (ack & AUX_NATIVE_REPLY_MASK) { |
163 | break; |
241 | case AUX_NATIVE_REPLY_ACK: |
164 | case DP_LINK_BW_2_7: |
- | |
165 | for (i = 0; i < num_dp_clocks; i++) { |
242 | /* I2C-over-AUX Reply field is only valid |
166 | switch (max_lane_count) { |
243 | * when paired with AUX ACK. |
- | 244 | */ |
|
167 | case 1: |
245 | break; |
168 | if (i > 1) |
246 | case AUX_NATIVE_REPLY_NACK: |
- | 247 | DRM_DEBUG_KMS("aux_ch native nack\n"); |
|
- | 248 | return -EREMOTEIO; |
|
- | 249 | case AUX_NATIVE_REPLY_DEFER: |
|
169 | return 0; |
250 | DRM_DEBUG_KMS("aux_ch native defer\n"); |
170 | break; |
251 | udelay(400); |
- | 252 | continue; |
|
- | 253 | default: |
|
- | 254 | DRM_ERROR("aux_ch invalid native reply 0x%02x\n", ack); |
|
- | 255 | return -EREMOTEIO; |
|
- | 256 | } |
|
- | 257 | ||
- | 258 | switch (ack & AUX_I2C_REPLY_MASK) { |
|
- | 259 | case AUX_I2C_REPLY_ACK: |
|
- | 260 | if (mode == MODE_I2C_READ) |
|
- | 261 | *read_byte = reply[0]; |
|
- | 262 | return ret; |
|
171 | case 2: |
263 | case AUX_I2C_REPLY_NACK: |
172 | if (i > 3) |
264 | DRM_DEBUG_KMS("aux_i2c nack\n"); |
Line -... | Line 265... | ||
- | 265 | return -EREMOTEIO; |
|
173 | return 0; |
266 | case AUX_I2C_REPLY_DEFER: |
174 | break; |
267 | DRM_DEBUG_KMS("aux_i2c defer\n"); |
Line 175... | Line -... | ||
175 | case 4: |
- | |
176 | default: |
- | |
177 | break; |
- | |
178 | } |
- | |
179 | if (dp_clocks[i] > mode_clock) |
- | |
180 | return (i % 2) ? 270000 : 162000; |
268 | udelay(400); |
181 | } |
- | |
182 | } |
- | |
183 | - | ||
184 | return 0; |
- | |
Line 185... | Line 269... | ||
185 | } |
269 | break; |
186 | 270 | default: |
|
187 | int dp_mode_valid(u8 dpcd[DP_DPCD_SIZE], int mode_clock) |
271 | DRM_ERROR("aux_i2c invalid reply 0x%02x\n", ack); |
188 | { |
272 | return -EREMOTEIO; |
Line 240... | Line 324... | ||
240 | return false; |
324 | return false; |
241 | } |
325 | } |
242 | return true; |
326 | return true; |
243 | } |
327 | } |
Line 244... | Line 328... | ||
244 | 328 | ||
245 | static u8 dp_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE], |
329 | static u8 dp_get_adjust_request_voltage(u8 link_status[DP_LINK_STATUS_SIZE], |
Line 246... | Line 330... | ||
246 | int lane) |
330 | int lane) |
247 | 331 | ||
248 | { |
332 | { |
Line 253... | Line 337... | ||
253 | u8 l = dp_link_status(link_status, i); |
337 | u8 l = dp_link_status(link_status, i); |
Line 254... | Line 338... | ||
254 | 338 | ||
255 | return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; |
339 | return ((l >> s) & 0x3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; |
Line 256... | Line 340... | ||
256 | } |
340 | } |
257 | 341 | ||
258 | static u8 dp_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE], |
342 | static u8 dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE], |
259 | int lane) |
343 | int lane) |
260 | { |
344 | { |
261 | int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); |
345 | int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); |
Line 265... | Line 349... | ||
265 | u8 l = dp_link_status(link_status, i); |
349 | u8 l = dp_link_status(link_status, i); |
Line 266... | Line 350... | ||
266 | 350 | ||
267 | return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; |
351 | return ((l >> s) & 0x3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; |
Line 268... | Line -... | ||
268 | } |
- | |
269 | 352 | } |
|
270 | /* XXX fix me -- chip specific */ |
- | |
271 | #define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200 |
- | |
272 | static u8 dp_pre_emphasis_max(u8 voltage_swing) |
- | |
273 | { |
- | |
274 | switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { |
- | |
275 | case DP_TRAIN_VOLTAGE_SWING_400: |
- | |
276 | return DP_TRAIN_PRE_EMPHASIS_6; |
- | |
277 | case DP_TRAIN_VOLTAGE_SWING_600: |
- | |
278 | return DP_TRAIN_PRE_EMPHASIS_6; |
353 | |
279 | case DP_TRAIN_VOLTAGE_SWING_800: |
- | |
280 | return DP_TRAIN_PRE_EMPHASIS_3_5; |
- | |
281 | case DP_TRAIN_VOLTAGE_SWING_1200: |
- | |
282 | default: |
- | |
283 | return DP_TRAIN_PRE_EMPHASIS_0; |
- | |
Line 284... | Line 354... | ||
284 | } |
354 | #define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200 |
285 | } |
355 | #define DP_PRE_EMPHASIS_MAX DP_TRAIN_PRE_EMPHASIS_9_5 |
286 | 356 | ||
287 | static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE], |
357 | static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE], |
Line 294... | Line 364... | ||
294 | 364 | ||
295 | for (lane = 0; lane < lane_count; lane++) { |
365 | for (lane = 0; lane < lane_count; lane++) { |
296 | u8 this_v = dp_get_adjust_request_voltage(link_status, lane); |
366 | u8 this_v = dp_get_adjust_request_voltage(link_status, lane); |
Line 297... | Line 367... | ||
297 | u8 this_p = dp_get_adjust_request_pre_emphasis(link_status, lane); |
367 | u8 this_p = dp_get_adjust_request_pre_emphasis(link_status, lane); |
298 | 368 | ||
299 | DRM_DEBUG("requested signal parameters: lane %d voltage %s pre_emph %s\n", |
369 | DRM_DEBUG_KMS("requested signal parameters: lane %d voltage %s pre_emph %s\n", |
300 | lane, |
370 | lane, |
Line 301... | Line 371... | ||
301 | voltage_names[this_v >> DP_TRAIN_VOLTAGE_SWING_SHIFT], |
371 | voltage_names[this_v >> DP_TRAIN_VOLTAGE_SWING_SHIFT], |
Line 306... | Line 376... | ||
306 | if (this_p > p) |
376 | if (this_p > p) |
307 | p = this_p; |
377 | p = this_p; |
308 | } |
378 | } |
Line 309... | Line 379... | ||
309 | 379 | ||
310 | if (v >= DP_VOLTAGE_MAX) |
380 | if (v >= DP_VOLTAGE_MAX) |
Line 311... | Line 381... | ||
311 | v = DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED; |
381 | v |= DP_TRAIN_MAX_SWING_REACHED; |
312 | 382 | ||
Line 313... | Line 383... | ||
313 | if (p >= dp_pre_emphasis_max(v)) |
383 | if (p >= DP_PRE_EMPHASIS_MAX) |
314 | p = dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; |
384 | p |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; |
315 | 385 | ||
Line 316... | Line 386... | ||
316 | DRM_DEBUG("using signal parameters: voltage %s pre_emph %s\n", |
386 | DRM_DEBUG_KMS("using signal parameters: voltage %s pre_emph %s\n", |
317 | voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK) >> DP_TRAIN_VOLTAGE_SWING_SHIFT], |
387 | voltage_names[(v & DP_TRAIN_VOLTAGE_SWING_MASK) >> DP_TRAIN_VOLTAGE_SWING_SHIFT], |
318 | pre_emph_names[(p & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); |
388 | pre_emph_names[(p & DP_TRAIN_PRE_EMPHASIS_MASK) >> DP_TRAIN_PRE_EMPHASIS_SHIFT]); |
Line 319... | Line 389... | ||
319 | 389 | ||
320 | for (lane = 0; lane < 4; lane++) |
- | |
321 | train_set[lane] = v | p; |
- | |
322 | } |
- | |
323 | - | ||
324 | union aux_channel_transaction { |
390 | for (lane = 0; lane < 4; lane++) |
325 | PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1; |
- | |
326 | PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2; |
391 | train_set[lane] = v | p; |
327 | }; |
- | |
328 | 392 | } |
|
329 | /* radeon aux chan functions */ |
- | |
330 | bool radeon_process_aux_ch(struct radeon_i2c_chan *chan, u8 *req_bytes, |
- | |
331 | int num_bytes, u8 *read_byte, |
- | |
332 | u8 read_buf_len, u8 delay) |
- | |
333 | { |
393 | |
334 | struct drm_device *dev = chan->dev; |
394 | /* convert bits per color to bits per pixel */ |
335 | struct radeon_device *rdev = dev->dev_private; |
- | |
336 | union aux_channel_transaction args; |
- | |
337 | int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); |
- | |
338 | unsigned char *base; |
- | |
339 | int retry_count = 0; |
- | |
340 | 395 | /* get bpc from the EDID */ |
|
341 | memset(&args, 0, sizeof(args)); |
- | |
342 | - | ||
343 | base = (unsigned char *)rdev->mode_info.atom_context->scratch; |
- | |
344 | - | ||
345 | retry: |
- | |
346 | memcpy(base, req_bytes, num_bytes); |
- | |
347 | - | ||
348 | args.v1.lpAuxRequest = 0; |
- | |
349 | args.v1.lpDataOut = 16; |
- | |
350 | args.v1.ucDataOutLen = 0; |
- | |
351 | args.v1.ucChannelID = chan->rec.i2c_id; |
- | |
352 | args.v1.ucDelay = delay / 10; |
- | |
353 | if (ASIC_IS_DCE4(rdev)) |
- | |
354 | args.v2.ucHPD_ID = chan->rec.hpd_id; |
- | |
355 | - | ||
356 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
- | |
357 | - | ||
358 | if (args.v1.ucReplyStatus && !args.v1.ucDataOutLen) { |
- | |
359 | if (args.v1.ucReplyStatus == 0x20 && retry_count++ < 10) |
396 | static int convert_bpc_to_bpp(int bpc) |
360 | goto retry; |
397 | { |
Line 361... | Line 398... | ||
361 | DRM_DEBUG("failed to get auxch %02x%02x %02x %02x 0x%02x %02x after %d retries\n", |
398 | if (bpc == 0) |
362 | req_bytes[1], req_bytes[0], req_bytes[2], req_bytes[3], |
399 | return 24; |
363 | chan->rec.i2c_id, args.v1.ucReplyStatus, retry_count); |
400 | else |
364 | return false; |
401 | return bpc * 3; |
- | 402 | } |
|
365 | } |
403 | |
366 | 404 | /* get the max pix clock supported by the link rate and lane num */ |
|
- | 405 | static int dp_get_max_dp_pix_clock(int link_rate, |
|
- | 406 | int lane_num, |
|
367 | if (args.v1.ucDataOutLen && read_byte && read_buf_len) { |
407 | int bpp) |
368 | if (read_buf_len < args.v1.ucDataOutLen) { |
408 | { |
- | 409 | return (link_rate * lane_num * 8) / bpp; |
|
- | 410 | } |
|
369 | DRM_ERROR("Buffer to small for return answer %d %d\n", |
411 | |
- | 412 | static int dp_get_max_link_rate(u8 dpcd[DP_DPCD_SIZE]) |
|
- | 413 | { |
|
- | 414 | switch (dpcd[DP_MAX_LINK_RATE]) { |
|
- | 415 | case DP_LINK_BW_1_62: |
|
370 | read_buf_len, args.v1.ucDataOutLen); |
416 | default: |
371 | return false; |
417 | return 162000; |
- | 418 | case DP_LINK_BW_2_7: |
|
- | 419 | return 270000; |
|
- | 420 | case DP_LINK_BW_5_4: |
|
372 | } |
421 | return 540000; |
373 | { |
422 | } |
Line 374... | Line -... | ||
374 | int len = min(read_buf_len, args.v1.ucDataOutLen); |
- | |
375 | memcpy(read_byte, base + 16, len); |
423 | } |
376 | } |
424 | |
377 | } |
425 | static u8 dp_get_max_lane_number(u8 dpcd[DP_DPCD_SIZE]) |
378 | return true; |
426 | { |
- | 427 | return dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; |
|
- | 428 | } |
|
- | 429 | ||
379 | } |
430 | static u8 dp_get_dp_link_rate_coded(int link_rate) |
380 | 431 | { |
|
- | 432 | switch (link_rate) { |
|
- | 433 | case 162000: |
|
- | 434 | default: |
|
Line 381... | Line -... | ||
381 | bool radeon_dp_aux_native_write(struct radeon_connector *radeon_connector, uint16_t address, |
- | |
382 | uint8_t send_bytes, uint8_t *send) |
- | |
383 | { |
- | |
384 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
- | |
385 | u8 msg[20]; |
- | |
386 | u8 msg_len, dp_msg_len; |
435 | return DP_LINK_BW_1_62; |
Line -... | Line 436... | ||
- | 436 | case 270000: |
|
- | 437 | return DP_LINK_BW_2_7; |
|
- | 438 | case 540000: |
|
- | 439 | return DP_LINK_BW_5_4; |
|
- | 440 | } |
|
- | 441 | } |
|
387 | bool ret; |
442 | |
- | 443 | /***** radeon specific DP functions *****/ |
|
- | 444 | ||
- | 445 | /* First get the min lane# when low rate is used according to pixel clock |
|
- | 446 | * (prefer low rate), second check max lane# supported by DP panel, |
|
388 | 447 | * if the max lane# < low rate lane# then use max lane# instead. |
|
- | 448 | */ |
|
Line 389... | Line 449... | ||
389 | dp_msg_len = 4; |
449 | static int radeon_dp_get_dp_lane_number(struct drm_connector *connector, |
390 | msg[0] = address; |
450 | u8 dpcd[DP_DPCD_SIZE], |
391 | msg[1] = address >> 8; |
451 | int pix_clock) |
- | 452 | { |
|
- | 453 | int bpp = convert_bpc_to_bpp(connector->display_info.bpc); |
|
- | 454 | int max_link_rate = dp_get_max_link_rate(dpcd); |
|
392 | msg[2] = AUX_NATIVE_WRITE << 4; |
455 | int max_lane_num = dp_get_max_lane_number(dpcd); |
393 | dp_msg_len += send_bytes; |
456 | int lane_num; |
Line 394... | Line 457... | ||
394 | msg[3] = (dp_msg_len << 4) | (send_bytes - 1); |
457 | int max_dp_pix_clock; |
395 | 458 | ||
396 | if (send_bytes > 16) |
459 | for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) { |
397 | return false; |
460 | max_dp_pix_clock = dp_get_max_dp_pix_clock(max_link_rate, lane_num, bpp); |
398 | 461 | if (pix_clock <= max_dp_pix_clock) |
|
399 | memcpy(&msg[4], send, send_bytes); |
- | |
400 | msg_len = 4 + send_bytes; |
462 | break; |
401 | ret = radeon_process_aux_ch(dig_connector->dp_i2c_bus, msg, msg_len, NULL, 0, 0); |
- | |
402 | return ret; |
- | |
403 | } |
- | |
404 | - | ||
405 | bool radeon_dp_aux_native_read(struct radeon_connector *radeon_connector, uint16_t address, |
- | |
406 | uint8_t delay, uint8_t expected_bytes, |
- | |
407 | uint8_t *read_p) |
- | |
408 | { |
- | |
Line -... | Line 463... | ||
- | 463 | } |
|
- | 464 | ||
- | 465 | return lane_num; |
|
409 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
466 | } |
- | 467 | ||
- | 468 | static int radeon_dp_get_dp_link_clock(struct drm_connector *connector, |
|
- | 469 | u8 dpcd[DP_DPCD_SIZE], |
|
- | 470 | int pix_clock) |
|
- | 471 | { |
|
410 | u8 msg[20]; |
472 | int bpp = convert_bpc_to_bpp(connector->display_info.bpc); |
- | 473 | int lane_num, max_pix_clock; |
|
- | 474 | ||
- | 475 | if (radeon_connector_encoder_is_dp_bridge(connector)) |
|
- | 476 | return 270000; |
|
411 | u8 msg_len, dp_msg_len; |
477 | |
Line 412... | Line 478... | ||
412 | bool ret = false; |
478 | lane_num = radeon_dp_get_dp_lane_number(connector, dpcd, pix_clock); |
- | 479 | max_pix_clock = dp_get_max_dp_pix_clock(162000, lane_num, bpp); |
|
- | 480 | if (pix_clock <= max_pix_clock) |
|
413 | msg_len = 4; |
481 | return 162000; |
- | 482 | max_pix_clock = dp_get_max_dp_pix_clock(270000, lane_num, bpp); |
|
414 | dp_msg_len = 4; |
483 | if (pix_clock <= max_pix_clock) |
415 | msg[0] = address; |
484 | return 270000; |
416 | msg[1] = address >> 8; |
485 | if (radeon_connector_is_dp12_capable(connector)) { |
417 | msg[2] = AUX_NATIVE_READ << 4; |
486 | max_pix_clock = dp_get_max_dp_pix_clock(540000, lane_num, bpp); |
Line 418... | Line 487... | ||
418 | msg[3] = (dp_msg_len) << 4; |
487 | if (pix_clock <= max_pix_clock) |
Line 452... | Line 521... | ||
452 | 521 | ||
453 | bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) |
522 | bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) |
454 | { |
523 | { |
455 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
524 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
456 | u8 msg[25]; |
525 | u8 msg[25]; |
Line 457... | Line 526... | ||
457 | int ret; |
526 | int ret, i; |
458 | 527 | ||
459 | ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, 0, 8, msg); |
528 | ret = radeon_dp_aux_native_read(radeon_connector, DP_DPCD_REV, msg, 8, 0); |
460 | if (ret) { |
- | |
461 | memcpy(dig_connector->dpcd, msg, 8); |
- | |
462 | { |
529 | if (ret > 0) { |
463 | int i; |
530 | memcpy(dig_connector->dpcd, msg, 8); |
464 | DRM_DEBUG("DPCD: "); |
531 | DRM_DEBUG_KMS("DPCD: "); |
465 | for (i = 0; i < 8; i++) |
532 | for (i = 0; i < 8; i++) |
466 | DRM_DEBUG("%02x ", msg[i]); |
- | |
467 | DRM_DEBUG("\n"); |
533 | DRM_DEBUG_KMS("%02x ", msg[i]); |
468 | } |
534 | DRM_DEBUG_KMS("\n"); |
469 | return true; |
535 | return true; |
470 | } |
536 | } |
471 | dig_connector->dpcd[0] = 0; |
537 | dig_connector->dpcd[0] = 0; |
Line -... | Line 538... | ||
- | 538 | return false; |
|
- | 539 | } |
|
- | 540 | ||
- | 541 | static void radeon_dp_set_panel_mode(struct drm_encoder *encoder, |
|
- | 542 | struct drm_connector *connector) |
|
- | 543 | { |
|
- | 544 | struct drm_device *dev = encoder->dev; |
|
- | 545 | struct radeon_device *rdev = dev->dev_private; |
|
- | 546 | int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; |
|
- | 547 | ||
- | 548 | if (!ASIC_IS_DCE4(rdev)) |
|
- | 549 | return; |
|
- | 550 | ||
- | 551 | if (radeon_connector_encoder_is_dp_bridge(connector)) |
|
- | 552 | panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; |
|
- | 553 | ||
- | 554 | atombios_dig_encoder_setup(encoder, |
|
- | 555 | ATOM_ENCODER_CMD_SETUP_PANEL_MODE, |
|
472 | return false; |
556 | panel_mode); |
473 | } |
557 | } |
474 | 558 | ||
475 | void radeon_dp_set_link_config(struct drm_connector *connector, |
559 | void radeon_dp_set_link_config(struct drm_connector *connector, |
476 | struct drm_display_mode *mode) |
560 | struct drm_display_mode *mode) |
Line 477... | Line -... | ||
477 | { |
- | |
478 | struct radeon_connector *radeon_connector; |
- | |
479 | struct radeon_connector_atom_dig *dig_connector; |
- | |
480 | - | ||
481 | if ((connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) && |
- | |
482 | (connector->connector_type != DRM_MODE_CONNECTOR_eDP)) |
561 | { |
483 | return; |
562 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
484 | 563 | struct radeon_connector_atom_dig *dig_connector; |
|
Line -... | Line 564... | ||
- | 564 | ||
- | 565 | if (!radeon_connector->con_priv) |
|
485 | radeon_connector = to_radeon_connector(connector); |
566 | return; |
486 | if (!radeon_connector->con_priv) |
567 | dig_connector = radeon_connector->con_priv; |
487 | return; |
568 | |
488 | dig_connector = radeon_connector->con_priv; |
569 | if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || |
- | 570 | (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { |
|
489 | 571 | dig_connector->dp_clock = |
|
Line 490... | Line 572... | ||
490 | dig_connector->dp_clock = |
572 | radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); |
491 | dp_link_clock_for_mode_clock(dig_connector->dpcd, mode->clock); |
573 | dig_connector->dp_lane_count = |
492 | dig_connector->dp_lane_count = |
574 | radeon_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock); |
493 | dp_lanes_for_mode_clock(dig_connector->dpcd, mode->clock); |
575 | } |
- | 576 | } |
|
- | 577 | ||
Line -... | Line 578... | ||
- | 578 | int radeon_dp_mode_valid_helper(struct drm_connector *connector, |
|
- | 579 | struct drm_display_mode *mode) |
|
- | 580 | { |
|
- | 581 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
|
- | 582 | struct radeon_connector_atom_dig *dig_connector; |
|
494 | } |
583 | int dp_clock; |
- | 584 | ||
- | 585 | if (!radeon_connector->con_priv) |
|
- | 586 | return MODE_CLOCK_HIGH; |
|
- | 587 | dig_connector = radeon_connector->con_priv; |
|
- | 588 | ||
- | 589 | dp_clock = |
|
495 | 590 | radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); |
|
Line 496... | Line 591... | ||
496 | int radeon_dp_mode_valid_helper(struct radeon_connector *radeon_connector, |
591 | |
497 | struct drm_display_mode *mode) |
592 | if ((dp_clock == 540000) && |
498 | { |
593 | (!radeon_connector_is_dp12_capable(connector))) |
499 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
594 | return MODE_CLOCK_HIGH; |
500 | 595 | ||
501 | return dp_mode_valid(dig_connector->dpcd, mode->clock); |
596 | return MODE_OK; |
502 | } |
597 | } |
503 | 598 | ||
504 | static bool atom_dp_get_link_status(struct radeon_connector *radeon_connector, |
599 | static bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector, |
505 | u8 link_status[DP_LINK_STATUS_SIZE]) |
600 | u8 link_status[DP_LINK_STATUS_SIZE]) |
Line 506... | Line 601... | ||
506 | { |
601 | { |
507 | int ret; |
602 | int ret; |
508 | ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, 100, |
603 | ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, |
509 | DP_LINK_STATUS_SIZE, link_status); |
604 | link_status, DP_LINK_STATUS_SIZE, 100); |
510 | if (!ret) { |
605 | if (ret <= 0) { |
Line -... | Line 606... | ||
- | 606 | DRM_ERROR("displayport link status failed\n"); |
|
- | 607 | return false; |
|
- | 608 | } |
|
511 | DRM_ERROR("displayport link status failed\n"); |
609 | |
512 | return false; |
- | |
513 | } |
610 | DRM_DEBUG_KMS("link status %02x %02x %02x %02x %02x %02x\n", |
- | 611 | link_status[0], link_status[1], link_status[2], |
|
- | 612 | link_status[3], link_status[4], link_status[5]); |
|
- | 613 | return true; |
|
- | 614 | } |
|
- | 615 | ||
- | 616 | struct radeon_dp_link_train_info { |
|
- | 617 | struct radeon_device *rdev; |
|
514 | 618 | struct drm_encoder *encoder; |
|
- | 619 | struct drm_connector *connector; |
|
- | 620 | struct radeon_connector *radeon_connector; |
|
Line 515... | Line 621... | ||
515 | DRM_DEBUG("link status %02x %02x %02x %02x %02x %02x\n", |
621 | int enc_id; |
- | 622 | int dp_clock; |
|
516 | link_status[0], link_status[1], link_status[2], |
623 | int dp_lane_count; |
- | 624 | int rd_interval; |
|
- | 625 | bool tp3_supported; |
|
517 | link_status[3], link_status[4], link_status[5]); |
626 | u8 dpcd[8]; |
- | 627 | u8 train_set[4]; |
|
518 | return true; |
628 | u8 link_status[DP_LINK_STATUS_SIZE]; |
- | 629 | u8 tries; |
|
519 | } |
630 | }; |
520 | 631 | ||
Line 521... | Line 632... | ||
521 | bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector) |
632 | static void radeon_dp_update_vs_emph(struct radeon_dp_link_train_info *dp_info) |
522 | { |
633 | { |
523 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
634 | /* set the initial vs/emph on the source */ |
Line -... | Line 635... | ||
- | 635 | atombios_dig_transmitter_setup(dp_info->encoder, |
|
524 | u8 link_status[DP_LINK_STATUS_SIZE]; |
636 | ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH, |
- | 637 | 0, dp_info->train_set[0]); /* sets all lanes at once */ |
|
- | 638 | ||
525 | 639 | /* set the vs/emph on the sink */ |
|
- | 640 | radeon_dp_aux_native_write(dp_info->radeon_connector, DP_TRAINING_LANE0_SET, |
|
- | 641 | dp_info->train_set, dp_info->dp_lane_count, 0); |
|
- | 642 | } |
|
- | 643 | ||
526 | if (!atom_dp_get_link_status(radeon_connector, link_status)) |
644 | static void radeon_dp_set_tp(struct radeon_dp_link_train_info *dp_info, int tp) |
- | 645 | { |
|
- | 646 | int rtp = 0; |
|
527 | return false; |
647 | |
- | 648 | /* set training pattern on the source */ |
|
- | 649 | if (ASIC_IS_DCE4(dp_info->rdev)) { |
|
- | 650 | switch (tp) { |
|
- | 651 | case DP_TRAINING_PATTERN_1: |
|
- | 652 | rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1; |
|
- | 653 | break; |
|
- | 654 | case DP_TRAINING_PATTERN_2: |
|
- | 655 | rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2; |
|
- | 656 | break; |
|
528 | if (dp_channel_eq_ok(link_status, dig_connector->dp_lane_count)) |
657 | case DP_TRAINING_PATTERN_3: |
529 | return false; |
- | |
530 | return true; |
- | |
531 | } |
- | |
532 | 658 | rtp = ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3; |
|
533 | static void dp_set_power(struct radeon_connector *radeon_connector, u8 power_state) |
659 | break; |
534 | { |
660 | } |
Line 535... | Line -... | ||
535 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
- | |
536 | 661 | atombios_dig_encoder_setup(dp_info->encoder, rtp, 0); |
|
537 | if (dig_connector->dpcd[0] >= 0x11) { |
- | |
538 | radeon_dp_aux_native_write(radeon_connector, DP_SET_POWER, 1, |
662 | } else { |
539 | &power_state); |
- | |
540 | } |
663 | switch (tp) { |
Line 541... | Line 664... | ||
541 | } |
664 | case DP_TRAINING_PATTERN_1: |
542 | - | ||
543 | static void dp_set_downspread(struct radeon_connector *radeon_connector, u8 downspread) |
- | |
544 | { |
665 | rtp = 0; |
545 | radeon_dp_aux_native_write(radeon_connector, DP_DOWNSPREAD_CTRL, 1, |
- | |
546 | &downspread); |
666 | break; |
Line -... | Line 667... | ||
- | 667 | case DP_TRAINING_PATTERN_2: |
|
- | 668 | rtp = 1; |
|
547 | } |
669 | break; |
- | 670 | } |
|
- | 671 | radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, |
|
- | 672 | dp_info->dp_clock, dp_info->enc_id, rtp); |
|
- | 673 | } |
|
548 | 674 | ||
549 | static void dp_set_link_bw_lanes(struct radeon_connector *radeon_connector, |
675 | /* enable training pattern on the sink */ |
- | 676 | radeon_write_dpcd_reg(dp_info->radeon_connector, DP_TRAINING_PATTERN_SET, tp); |
|
- | 677 | } |
|
550 | u8 link_configuration[DP_LINK_CONFIGURATION_SIZE]) |
678 | |
Line 551... | Line 679... | ||
551 | { |
679 | static int radeon_dp_link_train_init(struct radeon_dp_link_train_info *dp_info) |
552 | radeon_dp_aux_native_write(radeon_connector, DP_LINK_BW_SET, 2, |
- | |
553 | link_configuration); |
- | |
Line 554... | Line 680... | ||
554 | } |
680 | { |
555 | 681 | u8 tmp; |
|
- | 682 | ||
- | 683 | /* power up the sink */ |
|
- | 684 | if (dp_info->dpcd[0] >= 0x11) |
|
556 | static void dp_update_dpvs_emph(struct radeon_connector *radeon_connector, |
685 | radeon_write_dpcd_reg(dp_info->radeon_connector, |
- | 686 | DP_SET_POWER, DP_SET_POWER_D0); |
|
- | 687 | ||
557 | struct drm_encoder *encoder, |
688 | /* possibly enable downspread on the sink */ |
558 | u8 train_set[4]) |
- | |
559 | { |
- | |
Line 560... | Line -... | ||
560 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
- | |
561 | int i; |
689 | if (dp_info->dpcd[3] & 0x1) |
562 | - | ||
563 | for (i = 0; i < dig_connector->dp_lane_count; i++) |
690 | radeon_write_dpcd_reg(dp_info->radeon_connector, |
564 | atombios_dig_transmitter_setup(encoder, |
- | |
565 | ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH, |
- | |
566 | i, train_set[i]); |
691 | DP_DOWNSPREAD_CTRL, DP_SPREAD_AMP_0_5); |
567 | - | ||
568 | radeon_dp_aux_native_write(radeon_connector, DP_TRAINING_LANE0_SET, |
692 | else |
569 | dig_connector->dp_lane_count, train_set); |
693 | radeon_write_dpcd_reg(dp_info->radeon_connector, |
570 | } |
- | |
571 | 694 | DP_DOWNSPREAD_CTRL, 0); |
|
572 | static void dp_set_training(struct radeon_connector *radeon_connector, |
695 | |
573 | u8 training) |
- | |
574 | { |
- | |
575 | radeon_dp_aux_native_write(radeon_connector, DP_TRAINING_PATTERN_SET, |
- | |
Line 576... | Line 696... | ||
576 | 1, &training); |
696 | radeon_dp_set_panel_mode(dp_info->encoder, dp_info->connector); |
577 | } |
697 | |
578 | 698 | /* set the lane count on the sink */ |
|
- | 699 | tmp = dp_info->dp_lane_count; |
|
Line 579... | Line -... | ||
579 | void dp_link_train(struct drm_encoder *encoder, |
- | |
580 | struct drm_connector *connector) |
700 | if (dp_info->dpcd[0] >= 0x11) |
581 | { |
- | |
- | 701 | tmp |= DP_LANE_COUNT_ENHANCED_FRAME_EN; |
|
Line 582... | Line 702... | ||
582 | struct drm_device *dev = encoder->dev; |
702 | radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LANE_COUNT_SET, tmp); |
583 | struct radeon_device *rdev = dev->dev_private; |
- | |
- | 703 | ||
584 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
704 | /* set the link rate on the sink */ |
585 | struct radeon_encoder_atom_dig *dig; |
- | |
Line -... | Line 705... | ||
- | 705 | tmp = dp_get_dp_link_rate_coded(dp_info->dp_clock); |
|
- | 706 | radeon_write_dpcd_reg(dp_info->radeon_connector, DP_LINK_BW_SET, tmp); |
|
- | 707 | ||
- | 708 | /* start training on the source */ |
|
- | 709 | if (ASIC_IS_DCE4(dp_info->rdev)) |
|
- | 710 | atombios_dig_encoder_setup(dp_info->encoder, |
|
586 | struct radeon_connector *radeon_connector; |
711 | ATOM_ENCODER_CMD_DP_LINK_TRAINING_START, 0); |
- | 712 | else |
|
587 | struct radeon_connector_atom_dig *dig_connector; |
713 | radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_START, |
588 | int enc_id = 0; |
714 | dp_info->dp_clock, dp_info->enc_id, 0); |
589 | bool clock_recovery, channel_eq; |
- | |
590 | u8 link_status[DP_LINK_STATUS_SIZE]; |
- | |
591 | u8 link_configuration[DP_LINK_CONFIGURATION_SIZE]; |
- | |
592 | u8 tries, voltage; |
- | |
593 | u8 train_set[4]; |
- | |
594 | int i; |
- | |
595 | 715 | ||
596 | if ((connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort) && |
716 | /* disable the training pattern on the sink */ |
597 | (connector->connector_type != DRM_MODE_CONNECTOR_eDP)) |
- | |
598 | return; |
- | |
599 | - | ||
600 | if (!radeon_encoder->enc_priv) |
- | |
601 | return; |
- | |
602 | dig = radeon_encoder->enc_priv; |
- | |
Line 603... | Line -... | ||
603 | - | ||
604 | radeon_connector = to_radeon_connector(connector); |
- | |
605 | if (!radeon_connector->con_priv) |
- | |
606 | return; |
- | |
607 | dig_connector = radeon_connector->con_priv; |
- | |
608 | - | ||
609 | if (dig->dig_encoder) |
- | |
610 | enc_id |= ATOM_DP_CONFIG_DIG2_ENCODER; |
- | |
611 | else |
- | |
612 | enc_id |= ATOM_DP_CONFIG_DIG1_ENCODER; |
- | |
613 | if (dig_connector->linkb) |
- | |
614 | enc_id |= ATOM_DP_CONFIG_LINK_B; |
- | |
615 | else |
- | |
616 | enc_id |= ATOM_DP_CONFIG_LINK_A; |
717 | radeon_write_dpcd_reg(dp_info->radeon_connector, |
617 | - | ||
618 | memset(link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); |
- | |
619 | if (dig_connector->dp_clock == 270000) |
- | |
620 | link_configuration[0] = DP_LINK_BW_2_7; |
- | |
621 | else |
- | |
622 | link_configuration[0] = DP_LINK_BW_1_62; |
- | |
623 | link_configuration[1] = dig_connector->dp_lane_count; |
718 | DP_TRAINING_PATTERN_SET, |
Line 624... | Line 719... | ||
624 | if (dig_connector->dpcd[0] >= 0x11) |
719 | DP_TRAINING_PATTERN_DISABLE); |
- | 720 | ||
625 | link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; |
721 | return 0; |
626 | 722 | } |
|
627 | /* power up the sink */ |
723 | |
628 | dp_set_power(radeon_connector, DP_SET_POWER_D0); |
- | |
Line 629... | Line 724... | ||
629 | /* disable the training pattern on the sink */ |
724 | static int radeon_dp_link_train_finish(struct radeon_dp_link_train_info *dp_info) |
- | 725 | { |
|
- | 726 | udelay(400); |
|
- | 727 | ||
- | 728 | /* disable the training pattern on the sink */ |
|
Line 630... | Line 729... | ||
630 | dp_set_training(radeon_connector, DP_TRAINING_PATTERN_DISABLE); |
729 | radeon_write_dpcd_reg(dp_info->radeon_connector, |
631 | /* set link bw and lanes on the sink */ |
730 | DP_TRAINING_PATTERN_SET, |
632 | dp_set_link_bw_lanes(radeon_connector, link_configuration); |
731 | DP_TRAINING_PATTERN_DISABLE); |
633 | /* disable downspread on the sink */ |
732 | |
634 | dp_set_downspread(radeon_connector, 0); |
733 | /* disable the training pattern on the source */ |
- | 734 | if (ASIC_IS_DCE4(dp_info->rdev)) |
|
635 | if (ASIC_IS_DCE4(rdev)) { |
735 | atombios_dig_encoder_setup(dp_info->encoder, |
- | 736 | ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE, 0); |
|
- | 737 | else |
|
- | 738 | radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_COMPLETE, |
|
636 | /* start training on the source */ |
739 | dp_info->dp_clock, dp_info->enc_id, 0); |
637 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_START); |
740 | |
Line 638... | Line 741... | ||
638 | /* set training pattern 1 on the source */ |
741 | return 0; |
639 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1); |
742 | } |
640 | } else { |
743 | |
641 | /* start training on the source */ |
744 | static int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info) |
Line 642... | Line 745... | ||
642 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_START, |
745 | { |
643 | dig_connector->dp_clock, enc_id, 0); |
746 | bool clock_recovery; |
644 | /* set training pattern 1 on the source */ |
747 | u8 voltage; |
645 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, |
748 | int i; |
646 | dig_connector->dp_clock, enc_id, 0); |
749 | |
647 | } |
750 | radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_1); |
648 | 751 | memset(dp_info->train_set, 0, 4); |
|
649 | /* set initial vs/emph */ |
752 | radeon_dp_update_vs_emph(dp_info); |
Line 650... | Line 753... | ||
650 | memset(train_set, 0, 4); |
753 | |
651 | udelay(400); |
754 | udelay(400); |
652 | /* set training pattern 1 on the sink */ |
755 | |
653 | dp_set_training(radeon_connector, DP_TRAINING_PATTERN_1); |
756 | /* clock recovery loop */ |
654 | 757 | clock_recovery = false; |
|
655 | dp_update_dpvs_emph(radeon_connector, encoder, train_set); |
758 | dp_info->tries = 0; |
656 | 759 | voltage = 0xff; |
|
657 | /* clock recovery loop */ |
760 | while (1) { |
Line 658... | Line 761... | ||
658 | clock_recovery = false; |
761 | if (dp_info->rd_interval == 0) |
Line 659... | Line 762... | ||
659 | tries = 0; |
762 | udelay(100); |
660 | voltage = 0xff; |
763 | else |
- | 764 | mdelay(dp_info->rd_interval * 4); |
|
661 | for (;;) { |
765 | |
662 | udelay(100); |
766 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) |
663 | if (!atom_dp_get_link_status(radeon_connector, link_status)) |
767 | break; |
664 | break; |
768 | |
- | 769 | if (dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { |
|
665 | 770 | clock_recovery = true; |
|
666 | if (dp_clock_recovery_ok(link_status, dig_connector->dp_lane_count)) { |
771 | break; |
667 | clock_recovery = true; |
772 | } |
668 | break; |
773 | |
669 | } |
774 | for (i = 0; i < dp_info->dp_lane_count; i++) { |
- | 775 | if ((dp_info->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) |
|
- | 776 | break; |
|
- | 777 | } |
|
Line -... | Line 778... | ||
- | 778 | if (i == dp_info->dp_lane_count) { |
|
- | 779 | DRM_ERROR("clock recovery reached max voltage\n"); |
|
- | 780 | break; |
|
Line 670... | Line 781... | ||
670 | 781 | } |
|
671 | for (i = 0; i < dig_connector->dp_lane_count; i++) { |
782 | |
672 | if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) |
- | |
673 | break; |
- | |
674 | } |
- | |
675 | if (i == dig_connector->dp_lane_count) { |
783 | if ((dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { |
676 | DRM_ERROR("clock recovery reached max voltage\n"); |
784 | ++dp_info->tries; |
677 | break; |
- | |
Line 678... | Line 785... | ||
678 | } |
785 | if (dp_info->tries == 5) { |
679 | 786 | DRM_ERROR("clock recovery tried 5 times\n"); |
|
680 | if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { |
787 | break; |
681 | ++tries; |
788 | } |
- | 789 | } else |
|
682 | if (tries == 5) { |
790 | dp_info->tries = 0; |
- | 791 | ||
- | 792 | voltage = dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; |
|
- | 793 | ||
683 | DRM_ERROR("clock recovery tried 5 times\n"); |
794 | /* Compute new train_set as requested by sink */ |
684 | break; |
795 | dp_get_adjust_train(dp_info->link_status, dp_info->dp_lane_count, dp_info->train_set); |
Line 685... | Line 796... | ||
685 | } |
796 | |
686 | } else |
797 | radeon_dp_update_vs_emph(dp_info); |
687 | tries = 0; |
798 | } |
688 | 799 | if (!clock_recovery) { |
|
Line 689... | Line 800... | ||
689 | voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; |
800 | DRM_ERROR("clock recovery failed\n"); |
690 | 801 | return -1; |
|
691 | /* Compute new train_set as requested by sink */ |
802 | } else { |
692 | dp_get_adjust_train(link_status, dig_connector->dp_lane_count, train_set); |
803 | DRM_DEBUG_KMS("clock recovery at voltage %d pre-emphasis %d\n", |
693 | dp_update_dpvs_emph(radeon_connector, encoder, train_set); |
804 | dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, |
Line 694... | Line 805... | ||
694 | } |
805 | (dp_info->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >> |
695 | if (!clock_recovery) |
806 | DP_TRAIN_PRE_EMPHASIS_SHIFT); |
696 | DRM_ERROR("clock recovery failed\n"); |
- | |
Line -... | Line 807... | ||
- | 807 | return 0; |
|
697 | else |
808 | } |
698 | DRM_DEBUG("clock recovery at voltage %d pre-emphasis %d\n", |
809 | } |
Line 699... | Line 810... | ||
699 | train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, |
810 | |
700 | (train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) >> |
811 | static int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info) |
- | 812 | { |
|
701 | DP_TRAIN_PRE_EMPHASIS_SHIFT); |
813 | bool channel_eq; |
702 | 814 | ||
703 | 815 | if (dp_info->tp3_supported) |
|
704 | /* set training pattern 2 on the sink */ |
816 | radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_3); |
705 | dp_set_training(radeon_connector, DP_TRAINING_PATTERN_2); |
817 | else |
706 | /* set training pattern 2 on the source */ |
- | |
707 | if (ASIC_IS_DCE4(rdev)) |
- | |
708 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2); |
- | |
709 | else |
- | |
710 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_PATTERN_SEL, |
818 | radeon_dp_set_tp(dp_info, DP_TRAINING_PATTERN_2); |
711 | dig_connector->dp_clock, enc_id, 1); |
- | |
712 | - | ||
713 | /* channel equalization loop */ |
819 | |
714 | tries = 0; |
- | |
715 | channel_eq = false; |
- | |
716 | for (;;) { |
820 | /* channel equalization loop */ |
Line 717... | Line 821... | ||
717 | udelay(400); |
821 | dp_info->tries = 0; |
718 | if (!atom_dp_get_link_status(radeon_connector, link_status)) |
822 | channel_eq = false; |
719 | break; |
823 | while (1) { |
720 | 824 | if (dp_info->rd_interval == 0) |
|
721 | if (dp_channel_eq_ok(link_status, dig_connector->dp_lane_count)) { |
825 | udelay(400); |
722 | channel_eq = true; |
- | |
723 | break; |
826 | else |
724 | } |
- | |
725 | - | ||
726 | /* Try 5 times */ |
827 | mdelay(dp_info->rd_interval * 4); |
727 | if (tries > 5) { |
- | |
728 | DRM_ERROR("channel eq failed: 5 tries\n"); |
- | |
729 | break; |
828 | |
730 | } |
829 | if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) |
731 | 830 | break; |
|
732 | /* Compute new train_set as requested by sink */ |
831 | |
733 | dp_get_adjust_train(link_status, dig_connector->dp_lane_count, train_set); |
- | |
Line 734... | Line 832... | ||
734 | dp_update_dpvs_emph(radeon_connector, encoder, train_set); |
832 | if (dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { |
- | 833 | channel_eq = true; |
|
735 | 834 | break; |
|
Line -... | Line 835... | ||
- | 835 | } |
|
- | 836 | ||
736 | tries++; |
837 | /* Try 5 times */ |
737 | } |
838 | if (dp_info->tries > 5) { |
Line -... | Line 839... | ||
- | 839 | DRM_ERROR("channel eq failed: 5 tries\n"); |
|
- | 840 | break; |
|
738 | 841 | } |
|
Line 739... | Line -... | ||
739 | if (!channel_eq) |
- | |
740 | DRM_ERROR("channel eq failed\n"); |
842 | |
741 | else |
843 | /* Compute new train_set as requested by sink */ |
742 | DRM_DEBUG("channel eq at voltage %d pre-emphasis %d\n", |
844 | dp_get_adjust_train(dp_info->link_status, dp_info->dp_lane_count, dp_info->train_set); |
743 | train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, |
- | |
744 | (train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) |
845 | |
745 | >> DP_TRAIN_PRE_EMPHASIS_SHIFT); |
846 | radeon_dp_update_vs_emph(dp_info); |
746 | - | ||
747 | /* disable the training pattern on the sink */ |
847 | dp_info->tries++; |
748 | if (ASIC_IS_DCE4(rdev)) |
848 | } |
749 | atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE); |
- | |
750 | else |
849 | |
751 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE, |
850 | if (!channel_eq) { |
752 | dig_connector->dp_clock, enc_id, 0); |
- | |
Line -... | Line 851... | ||
- | 851 | DRM_ERROR("channel eq failed\n"); |
|
- | 852 | return -1; |
|
- | 853 | } else { |
|
753 | 854 | DRM_DEBUG_KMS("channel eq at voltage %d pre-emphasis %d\n", |
|
- | 855 | dp_info->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK, |
|
754 | radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_TRAINING_COMPLETE, |
856 | (dp_info->train_set[0] & DP_TRAIN_PRE_EMPHASIS_MASK) |
Line -... | Line 857... | ||
- | 857 | >> DP_TRAIN_PRE_EMPHASIS_SHIFT); |
|
- | 858 | return 0; |
|
- | 859 | } |
|
- | 860 | } |
|
- | 861 | ||
- | 862 | void radeon_dp_link_train(struct drm_encoder *encoder, |
|
- | 863 | struct drm_connector *connector) |
|
- | 864 | { |
|
- | 865 | struct drm_device *dev = encoder->dev; |
|
755 | dig_connector->dp_clock, enc_id, 0); |
866 | struct radeon_device *rdev = dev->dev_private; |
- | 867 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
|
756 | } |
868 | struct radeon_encoder_atom_dig *dig; |
757 | 869 | struct radeon_connector *radeon_connector; |
|
758 | int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, |
870 | struct radeon_connector_atom_dig *dig_connector; |
759 | uint8_t write_byte, uint8_t *read_byte) |
871 | struct radeon_dp_link_train_info dp_info; |
- | 872 | u8 tmp; |
|
760 | { |
873 | |
761 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; |
874 | if (!radeon_encoder->enc_priv) |
762 | struct radeon_i2c_chan *auxch = (struct radeon_i2c_chan *)adapter; |
- |