Rev 5271 | Rev 6661 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5271 | Rev 6104 | ||
---|---|---|---|
Line 121... | Line 121... | ||
121 | /* timeout */ |
121 | /* timeout */ |
122 | if (args.v1.ucReplyStatus == 1) { |
122 | if (args.v1.ucReplyStatus == 1) { |
123 | DRM_DEBUG_KMS("dp_aux_ch timeout\n"); |
123 | DRM_DEBUG_KMS("dp_aux_ch timeout\n"); |
124 | r = -ETIMEDOUT; |
124 | r = -ETIMEDOUT; |
125 | goto done; |
125 | goto done; |
126 | } |
126 | } |
Line 127... | Line 127... | ||
127 | 127 | ||
128 | /* flags not zero */ |
128 | /* flags not zero */ |
129 | if (args.v1.ucReplyStatus == 2) { |
129 | if (args.v1.ucReplyStatus == 2) { |
130 | DRM_DEBUG_KMS("dp_aux_ch flags not zero\n"); |
130 | DRM_DEBUG_KMS("dp_aux_ch flags not zero\n"); |
131 | r = -EIO; |
131 | r = -EIO; |
132 | goto done; |
132 | goto done; |
Line 133... | Line 133... | ||
133 | } |
133 | } |
134 | 134 | ||
135 | /* error */ |
135 | /* error */ |
136 | if (args.v1.ucReplyStatus == 3) { |
136 | if (args.v1.ucReplyStatus == 3) { |
137 | DRM_DEBUG_KMS("dp_aux_ch error\n"); |
137 | DRM_DEBUG_KMS("dp_aux_ch error\n"); |
138 | r = -EIO; |
138 | r = -EIO; |
Line 139... | Line 139... | ||
139 | goto done; |
139 | goto done; |
140 | } |
140 | } |
141 | 141 | ||
Line 156... | Line 156... | ||
156 | 156 | ||
157 | #define BARE_ADDRESS_SIZE 3 |
157 | #define BARE_ADDRESS_SIZE 3 |
Line 158... | Line 158... | ||
158 | #define HEADER_SIZE (BARE_ADDRESS_SIZE + 1) |
158 | #define HEADER_SIZE (BARE_ADDRESS_SIZE + 1) |
159 | 159 | ||
160 | static ssize_t |
160 | static ssize_t |
161 | radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) |
161 | radeon_dp_aux_transfer_atom(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) |
162 | { |
162 | { |
163 | struct radeon_i2c_chan *chan = |
163 | struct radeon_i2c_chan *chan = |
164 | container_of(aux, struct radeon_i2c_chan, aux); |
164 | container_of(aux, struct radeon_i2c_chan, aux); |
Line 169... | Line 169... | ||
169 | 169 | ||
170 | if (WARN_ON(msg->size > 16)) |
170 | if (WARN_ON(msg->size > 16)) |
Line 171... | Line 171... | ||
171 | return -E2BIG; |
171 | return -E2BIG; |
172 | 172 | ||
173 | tx_buf[0] = msg->address & 0xff; |
173 | tx_buf[0] = msg->address & 0xff; |
- | 174 | tx_buf[1] = (msg->address >> 8) & 0xff; |
|
174 | tx_buf[1] = msg->address >> 8; |
175 | tx_buf[2] = (msg->request << 4) | |
Line 175... | Line 176... | ||
175 | tx_buf[2] = msg->request << 4; |
176 | ((msg->address >> 16) & 0xf); |
176 | tx_buf[3] = msg->size ? (msg->size - 1) : 0; |
177 | tx_buf[3] = msg->size ? (msg->size - 1) : 0; |
177 | 178 | ||
- | 179 | switch (msg->request & ~DP_AUX_I2C_MOT) { |
|
- | 180 | case DP_AUX_NATIVE_WRITE: |
|
- | 181 | case DP_AUX_I2C_WRITE: |
|
- | 182 | case DP_AUX_I2C_WRITE_STATUS_UPDATE: |
|
- | 183 | /* The atom implementation only supports writes with a max payload of |
|
- | 184 | * 12 bytes since it uses 4 bits for the total count (header + payload) |
|
- | 185 | * in the parameter space. The atom interface supports 16 byte |
|
- | 186 | * payloads for reads. The hw itself supports up to 16 bytes of payload. |
|
178 | switch (msg->request & ~DP_AUX_I2C_MOT) { |
187 | */ |
179 | case DP_AUX_NATIVE_WRITE: |
188 | if (WARN_ON_ONCE(msg->size > 12)) |
180 | case DP_AUX_I2C_WRITE: |
189 | return -E2BIG; |
181 | /* tx_size needs to be 4 even for bare address packets since the atom |
190 | /* tx_size needs to be 4 even for bare address packets since the atom |
182 | * table needs the info in tx_buf[3]. |
191 | * table needs the info in tx_buf[3]. |
Line 207... | Line 216... | ||
207 | tx_buf, tx_size, msg->buffer, msg->size, delay, &ack); |
216 | tx_buf, tx_size, msg->buffer, msg->size, delay, &ack); |
208 | break; |
217 | break; |
209 | default: |
218 | default: |
210 | ret = -EINVAL; |
219 | ret = -EINVAL; |
211 | break; |
220 | break; |
212 | } |
221 | } |
Line 213... | Line 222... | ||
213 | 222 | ||
214 | if (ret >= 0) |
223 | if (ret >= 0) |
Line 215... | Line 224... | ||
215 | msg->reply = ack >> 4; |
224 | msg->reply = ack >> 4; |
216 | 225 | ||
Line 217... | Line 226... | ||
217 | return ret; |
226 | return ret; |
218 | } |
227 | } |
- | 228 | ||
- | 229 | void radeon_dp_aux_init(struct radeon_connector *radeon_connector) |
|
219 | 230 | { |
|
Line 220... | Line 231... | ||
220 | void radeon_dp_aux_init(struct radeon_connector *radeon_connector) |
231 | struct drm_device *dev = radeon_connector->base.dev; |
221 | { |
232 | struct radeon_device *rdev = dev->dev_private; |
- | 233 | int ret; |
|
- | 234 | ||
- | 235 | radeon_connector->ddc_bus->rec.hpd = radeon_connector->hpd.hpd; |
|
- | 236 | radeon_connector->ddc_bus->aux.dev = radeon_connector->base.kdev; |
|
- | 237 | if (ASIC_IS_DCE5(rdev)) { |
|
- | 238 | if (radeon_auxch) |
|
222 | int ret; |
239 | radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer_native; |
- | 240 | else |
|
Line 223... | Line 241... | ||
223 | 241 | radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer_atom; |
|
224 | radeon_connector->ddc_bus->rec.hpd = radeon_connector->hpd.hpd; |
242 | } else { |
225 | radeon_connector->ddc_bus->aux.dev = radeon_connector->base.kdev; |
243 | radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer_atom; |
Line 235... | Line 253... | ||
235 | /***** general DP utility functions *****/ |
253 | /***** general DP utility functions *****/ |
Line 236... | Line 254... | ||
236 | 254 | ||
237 | #define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_LEVEL_3 |
255 | #define DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_LEVEL_3 |
Line 238... | Line 256... | ||
238 | #define DP_PRE_EMPHASIS_MAX DP_TRAIN_PRE_EMPH_LEVEL_3 |
256 | #define DP_PRE_EMPHASIS_MAX DP_TRAIN_PRE_EMPH_LEVEL_3 |
239 | 257 | ||
240 | static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE], |
258 | static void dp_get_adjust_train(const u8 link_status[DP_LINK_STATUS_SIZE], |
241 | int lane_count, |
259 | int lane_count, |
242 | u8 train_set[4]) |
260 | u8 train_set[4]) |
243 | { |
261 | { |
Line 292... | Line 310... | ||
292 | return (link_rate * lane_num * 8) / bpp; |
310 | return (link_rate * lane_num * 8) / bpp; |
293 | } |
311 | } |
Line 294... | Line 312... | ||
294 | 312 | ||
Line 295... | Line 313... | ||
295 | /***** radeon specific DP functions *****/ |
313 | /***** radeon specific DP functions *****/ |
296 | 314 | ||
297 | static int radeon_dp_get_max_link_rate(struct drm_connector *connector, |
315 | int radeon_dp_get_max_link_rate(struct drm_connector *connector, |
298 | u8 dpcd[DP_DPCD_SIZE]) |
316 | const u8 dpcd[DP_DPCD_SIZE]) |
Line 299... | Line 317... | ||
299 | { |
317 | { |
300 | int max_link_rate; |
318 | int max_link_rate; |
Line 310... | Line 328... | ||
310 | /* First get the min lane# when low rate is used according to pixel clock |
328 | /* First get the min lane# when low rate is used according to pixel clock |
311 | * (prefer low rate), second check max lane# supported by DP panel, |
329 | * (prefer low rate), second check max lane# supported by DP panel, |
312 | * if the max lane# < low rate lane# then use max lane# instead. |
330 | * if the max lane# < low rate lane# then use max lane# instead. |
313 | */ |
331 | */ |
314 | static int radeon_dp_get_dp_lane_number(struct drm_connector *connector, |
332 | static int radeon_dp_get_dp_lane_number(struct drm_connector *connector, |
315 | u8 dpcd[DP_DPCD_SIZE], |
333 | const u8 dpcd[DP_DPCD_SIZE], |
316 | int pix_clock) |
334 | int pix_clock) |
317 | { |
335 | { |
318 | int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); |
336 | int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); |
319 | int max_link_rate = radeon_dp_get_max_link_rate(connector, dpcd); |
337 | int max_link_rate = radeon_dp_get_max_link_rate(connector, dpcd); |
320 | int max_lane_num = drm_dp_max_lane_count(dpcd); |
338 | int max_lane_num = drm_dp_max_lane_count(dpcd); |
Line 329... | Line 347... | ||
329 | 347 | ||
330 | return lane_num; |
348 | return lane_num; |
Line 331... | Line 349... | ||
331 | } |
349 | } |
332 | 350 | ||
333 | static int radeon_dp_get_dp_link_clock(struct drm_connector *connector, |
351 | static int radeon_dp_get_dp_link_clock(struct drm_connector *connector, |
334 | u8 dpcd[DP_DPCD_SIZE], |
352 | const u8 dpcd[DP_DPCD_SIZE], |
335 | int pix_clock) |
353 | int pix_clock) |
336 | { |
354 | { |
Line 403... | Line 421... | ||
403 | 421 | ||
404 | bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) |
422 | bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) |
405 | { |
423 | { |
406 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
424 | struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; |
407 | u8 msg[DP_DPCD_SIZE]; |
425 | u8 msg[DP_DPCD_SIZE]; |
Line -... | Line 426... | ||
- | 426 | int ret, i; |
|
408 | int ret; |
427 | |
409 | 428 | for (i = 0; i < 7; i++) { |
|
410 | ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_DPCD_REV, msg, |
429 | ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_DPCD_REV, msg, |
411 | DP_DPCD_SIZE); |
430 | DP_DPCD_SIZE); |
Line 412... | Line 431... | ||
412 | if (ret > 0) { |
431 | if (ret == DP_DPCD_SIZE) { |
413 | memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); |
432 | memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); |
Line 414... | Line 433... | ||
414 | 433 | ||
Line 415... | Line 434... | ||
415 | DRM_DEBUG_KMS("DPCD: %*ph\n", (int)sizeof(dig_connector->dpcd), |
434 | DRM_DEBUG_KMS("DPCD: %*ph\n", (int)sizeof(dig_connector->dpcd), |
- | 435 | dig_connector->dpcd); |
|
416 | dig_connector->dpcd); |
436 | |
417 | 437 | radeon_dp_probe_oui(radeon_connector); |
|
418 | radeon_dp_probe_oui(radeon_connector); |
438 | |
419 | 439 | return true; |
|
Line 420... | Line 440... | ||
420 | return true; |
440 | } |
421 | } |
441 | } |
422 | dig_connector->dpcd[0] = 0; |
442 | dig_connector->dpcd[0] = 0; |
423 | return false; |
443 | return false; |
424 | } |
444 | } |
425 | 445 | ||
426 | int radeon_dp_get_panel_mode(struct drm_encoder *encoder, |
446 | int radeon_dp_get_panel_mode(struct drm_encoder *encoder, |
Line 444... | Line 464... | ||
444 | 464 | ||
445 | if (dp_bridge != ENCODER_OBJECT_ID_NONE) { |
465 | if (dp_bridge != ENCODER_OBJECT_ID_NONE) { |
446 | /* DP bridge chips */ |
466 | /* DP bridge chips */ |
447 | if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, |
467 | if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, |
448 | DP_EDP_CONFIGURATION_CAP, &tmp) == 1) { |
468 | DP_EDP_CONFIGURATION_CAP, &tmp) == 1) { |
449 | if (tmp & 1) |
469 | if (tmp & 1) |
450 | panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; |
470 | panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; |
451 | else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) || |
471 | else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) || |
452 | (dp_bridge == ENCODER_OBJECT_ID_TRAVIS)) |
472 | (dp_bridge == ENCODER_OBJECT_ID_TRAVIS)) |
453 | panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; |
473 | panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE; |
454 | else |
474 | else |
455 | panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; |
475 | panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; |
456 | } |
476 | } |
457 | } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { |
477 | } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { |
458 | /* eDP */ |
478 | /* eDP */ |
459 | if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, |
479 | if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, |
460 | DP_EDP_CONFIGURATION_CAP, &tmp) == 1) { |
480 | DP_EDP_CONFIGURATION_CAP, &tmp) == 1) { |
461 | if (tmp & 1) |
481 | if (tmp & 1) |
462 | panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; |
482 | panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; |
463 | } |
483 | } |
Line 464... | Line 484... | ||
464 | } |
484 | } |
465 | 485 | ||
Line 476... | Line 496... | ||
476 | return; |
496 | return; |
477 | dig_connector = radeon_connector->con_priv; |
497 | dig_connector = radeon_connector->con_priv; |
Line 478... | Line 498... | ||
478 | 498 | ||
479 | if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || |
499 | if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || |
480 | (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { |
500 | (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { |
481 | dig_connector->dp_clock = |
501 | dig_connector->dp_clock = |
482 | radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); |
502 | radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); |
483 | dig_connector->dp_lane_count = |
503 | dig_connector->dp_lane_count = |
484 | radeon_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock); |
504 | radeon_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock); |
485 | } |
505 | } |
Line 486... | Line 506... | ||
486 | } |
506 | } |
Line 490... | Line 510... | ||
490 | { |
510 | { |
491 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
511 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
492 | struct radeon_connector_atom_dig *dig_connector; |
512 | struct radeon_connector_atom_dig *dig_connector; |
493 | int dp_clock; |
513 | int dp_clock; |
Line -... | Line 514... | ||
- | 514 | ||
- | 515 | if ((mode->clock > 340000) && |
|
- | 516 | (!radeon_connector_is_dp12_capable(connector))) |
|
- | 517 | return MODE_CLOCK_HIGH; |
|
494 | 518 | ||
495 | if (!radeon_connector->con_priv) |
519 | if (!radeon_connector->con_priv) |
496 | return MODE_CLOCK_HIGH; |
520 | return MODE_CLOCK_HIGH; |
Line 497... | Line 521... | ||
497 | dig_connector = radeon_connector->con_priv; |
521 | dig_connector = radeon_connector->con_priv; |
Line 612... | Line 636... | ||
612 | radeon_dp_set_rx_power_state(dp_info->connector, DP_SET_POWER_D0); |
636 | radeon_dp_set_rx_power_state(dp_info->connector, DP_SET_POWER_D0); |
Line 613... | Line 637... | ||
613 | 637 | ||
614 | /* possibly enable downspread on the sink */ |
638 | /* possibly enable downspread on the sink */ |
615 | if (dp_info->dpcd[3] & 0x1) |
639 | if (dp_info->dpcd[3] & 0x1) |
616 | drm_dp_dpcd_writeb(dp_info->aux, |
640 | drm_dp_dpcd_writeb(dp_info->aux, |
617 | DP_DOWNSPREAD_CTRL, DP_SPREAD_AMP_0_5); |
641 | DP_DOWNSPREAD_CTRL, DP_SPREAD_AMP_0_5); |
618 | else |
642 | else |
619 | drm_dp_dpcd_writeb(dp_info->aux, |
643 | drm_dp_dpcd_writeb(dp_info->aux, |
Line 620... | Line -... | ||
620 | DP_DOWNSPREAD_CTRL, 0); |
- | |
621 | 644 | DP_DOWNSPREAD_CTRL, 0); |
|
622 | if ((dp_info->connector->connector_type == DRM_MODE_CONNECTOR_eDP) && |
645 | |
623 | (dig->panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE)) { |
- | |
Line 624... | Line 646... | ||
624 | drm_dp_dpcd_writeb(dp_info->aux, DP_EDP_CONFIGURATION_SET, 1); |
646 | if (dig->panel_mode == DP_PANEL_MODE_INTERNAL_DP2_MODE) |
625 | } |
647 | drm_dp_dpcd_writeb(dp_info->aux, DP_EDP_CONFIGURATION_SET, 1); |
626 | 648 | ||
627 | /* set the lane count on the sink */ |
649 | /* set the lane count on the sink */ |
Line 642... | Line 664... | ||
642 | radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_START, |
664 | radeon_dp_encoder_service(dp_info->rdev, ATOM_DP_ACTION_TRAINING_START, |
643 | dp_info->dp_clock, dp_info->enc_id, 0); |
665 | dp_info->dp_clock, dp_info->enc_id, 0); |
Line 644... | Line 666... | ||
644 | 666 | ||
645 | /* disable the training pattern on the sink */ |
667 | /* disable the training pattern on the sink */ |
646 | drm_dp_dpcd_writeb(dp_info->aux, |
668 | drm_dp_dpcd_writeb(dp_info->aux, |
647 | DP_TRAINING_PATTERN_SET, |
669 | DP_TRAINING_PATTERN_SET, |
Line 648... | Line 670... | ||
648 | DP_TRAINING_PATTERN_DISABLE); |
670 | DP_TRAINING_PATTERN_DISABLE); |
649 | 671 | ||
Line 650... | Line 672... | ||
650 | return 0; |
672 | return 0; |
651 | } |
673 | } |
652 | 674 | ||
Line 653... | Line 675... | ||
653 | static int radeon_dp_link_train_finish(struct radeon_dp_link_train_info *dp_info) |
675 | static int radeon_dp_link_train_finish(struct radeon_dp_link_train_info *dp_info) |
654 | { |
676 | { |
655 | udelay(400); |
677 | udelay(400); |
656 | 678 | ||
Line 657... | Line 679... | ||
657 | /* disable the training pattern on the sink */ |
679 | /* disable the training pattern on the sink */ |
658 | drm_dp_dpcd_writeb(dp_info->aux, |
680 | drm_dp_dpcd_writeb(dp_info->aux, |
659 | DP_TRAINING_PATTERN_SET, |
681 | DP_TRAINING_PATTERN_SET, |
660 | DP_TRAINING_PATTERN_DISABLE); |
682 | DP_TRAINING_PATTERN_DISABLE); |
Line 836... | Line 858... | ||
836 | else |
858 | else |
837 | dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; |
859 | dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; |
Line 838... | Line 860... | ||
838 | 860 | ||
839 | if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_MAX_LANE_COUNT, &tmp) |
861 | if (drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_MAX_LANE_COUNT, &tmp) |
840 | == 1) { |
862 | == 1) { |
841 | if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) |
863 | if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) |
842 | dp_info.tp3_supported = true; |
864 | dp_info.tp3_supported = true; |
843 | else |
865 | else |
844 | dp_info.tp3_supported = false; |
866 | dp_info.tp3_supported = false; |
845 | } else { |
867 | } else { |
846 | dp_info.tp3_supported = false; |
868 | dp_info.tp3_supported = false; |
Line 847... | Line 869... | ||
847 | } |
869 | } |