diff options
author | Sean Paul <seanpaul@chromium.org> | 2012-10-31 19:21:00 -0400 |
---|---|---|
committer | Jingoo Han <jg1.han@samsung.com> | 2012-11-28 20:33:27 -0500 |
commit | ace2d7f2b537a072e39ddb4f51467d32b4900f8c (patch) | |
tree | 9a11b68cefb2768790c820a06f2ad96ed77e1c62 /drivers/video | |
parent | 825e90d0a138738657509d7460d77edb28fcfdc0 (diff) |
video: exynos_dp: Check DPCD return codes
Add return code checks to the DPCD transactions in the SW link training
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/exynos/exynos_dp_core.c | 86 |
1 files changed, 56 insertions, 30 deletions
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c index 9a9ecc16269a..e007906694fa 100644 --- a/drivers/video/exynos/exynos_dp_core.c +++ b/drivers/video/exynos/exynos_dp_core.c | |||
@@ -262,11 +262,10 @@ static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp, | |||
262 | } | 262 | } |
263 | } | 263 | } |
264 | 264 | ||
265 | static void exynos_dp_link_start(struct exynos_dp_device *dp) | 265 | static int exynos_dp_link_start(struct exynos_dp_device *dp) |
266 | { | 266 | { |
267 | u8 buf[4]; | 267 | u8 buf[4]; |
268 | int lane; | 268 | int lane, lane_count, retval; |
269 | int lane_count; | ||
270 | 269 | ||
271 | lane_count = dp->link_train.lane_count; | 270 | lane_count = dp->link_train.lane_count; |
272 | 271 | ||
@@ -277,8 +276,10 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp) | |||
277 | dp->link_train.cr_loop[lane] = 0; | 276 | dp->link_train.cr_loop[lane] = 0; |
278 | 277 | ||
279 | /* Set sink to D0 (Sink Not Ready) mode. */ | 278 | /* Set sink to D0 (Sink Not Ready) mode. */ |
280 | exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE, | 279 | retval = exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE, |
281 | DPCD_SET_POWER_STATE_D0); | 280 | DPCD_SET_POWER_STATE_D0); |
281 | if (retval) | ||
282 | return retval; | ||
282 | 283 | ||
283 | /* Set link rate and count as you want to establish*/ | 284 | /* Set link rate and count as you want to establish*/ |
284 | exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate); | 285 | exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate); |
@@ -287,8 +288,10 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp) | |||
287 | /* Setup RX configuration */ | 288 | /* Setup RX configuration */ |
288 | buf[0] = dp->link_train.link_rate; | 289 | buf[0] = dp->link_train.link_rate; |
289 | buf[1] = dp->link_train.lane_count; | 290 | buf[1] = dp->link_train.lane_count; |
290 | exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET, | 291 | retval = exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET, |
291 | 2, buf); | 292 | 2, buf); |
293 | if (retval) | ||
294 | return retval; | ||
292 | 295 | ||
293 | /* Set TX pre-emphasis to minimum */ | 296 | /* Set TX pre-emphasis to minimum */ |
294 | for (lane = 0; lane < lane_count; lane++) | 297 | for (lane = 0; lane < lane_count; lane++) |
@@ -307,9 +310,11 @@ static void exynos_dp_link_start(struct exynos_dp_device *dp) | |||
307 | for (lane = 0; lane < lane_count; lane++) | 310 | for (lane = 0; lane < lane_count; lane++) |
308 | buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 | | 311 | buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 | |
309 | DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0; | 312 | DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0; |
310 | exynos_dp_write_bytes_to_dpcd(dp, | 313 | retval = exynos_dp_write_bytes_to_dpcd(dp, |
311 | DPCD_ADDR_TRAINING_LANE0_SET, | 314 | DPCD_ADDR_TRAINING_LANE0_SET, |
312 | lane_count, buf); | 315 | lane_count, buf); |
316 | |||
317 | return retval; | ||
313 | } | 318 | } |
314 | 319 | ||
315 | static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane) | 320 | static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane) |
@@ -431,8 +436,7 @@ static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp) | |||
431 | static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) | 436 | static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) |
432 | { | 437 | { |
433 | u8 link_status[2]; | 438 | u8 link_status[2]; |
434 | int lane; | 439 | int lane, lane_count, retval; |
435 | int lane_count; | ||
436 | 440 | ||
437 | u8 adjust_request[2]; | 441 | u8 adjust_request[2]; |
438 | u8 voltage_swing; | 442 | u8 voltage_swing; |
@@ -443,17 +447,22 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) | |||
443 | 447 | ||
444 | lane_count = dp->link_train.lane_count; | 448 | lane_count = dp->link_train.lane_count; |
445 | 449 | ||
446 | exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS, | 450 | retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS, |
447 | 2, link_status); | 451 | 2, link_status); |
452 | if (retval) | ||
453 | return retval; | ||
448 | 454 | ||
449 | if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) { | 455 | if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) { |
450 | /* set training pattern 2 for EQ */ | 456 | /* set training pattern 2 for EQ */ |
451 | exynos_dp_set_training_pattern(dp, TRAINING_PTN2); | 457 | exynos_dp_set_training_pattern(dp, TRAINING_PTN2); |
452 | 458 | ||
453 | for (lane = 0; lane < lane_count; lane++) { | 459 | for (lane = 0; lane < lane_count; lane++) { |
454 | exynos_dp_read_bytes_from_dpcd(dp, | 460 | retval = exynos_dp_read_bytes_from_dpcd(dp, |
455 | DPCD_ADDR_ADJUST_REQUEST_LANE0_1, | 461 | DPCD_ADDR_ADJUST_REQUEST_LANE0_1, |
456 | 2, adjust_request); | 462 | 2, adjust_request); |
463 | if (retval) | ||
464 | return retval; | ||
465 | |||
457 | voltage_swing = exynos_dp_get_adjust_request_voltage( | 466 | voltage_swing = exynos_dp_get_adjust_request_voltage( |
458 | adjust_request, lane); | 467 | adjust_request, lane); |
459 | pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( | 468 | pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( |
@@ -473,15 +482,19 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) | |||
473 | lane); | 482 | lane); |
474 | } | 483 | } |
475 | 484 | ||
476 | exynos_dp_write_byte_to_dpcd(dp, | 485 | retval = exynos_dp_write_byte_to_dpcd(dp, |
477 | DPCD_ADDR_TRAINING_PATTERN_SET, | 486 | DPCD_ADDR_TRAINING_PATTERN_SET, |
478 | DPCD_SCRAMBLING_DISABLED | | 487 | DPCD_SCRAMBLING_DISABLED | |
479 | DPCD_TRAINING_PATTERN_2); | 488 | DPCD_TRAINING_PATTERN_2); |
489 | if (retval) | ||
490 | return retval; | ||
480 | 491 | ||
481 | exynos_dp_write_bytes_to_dpcd(dp, | 492 | retval = exynos_dp_write_bytes_to_dpcd(dp, |
482 | DPCD_ADDR_TRAINING_LANE0_SET, | 493 | DPCD_ADDR_TRAINING_LANE0_SET, |
483 | lane_count, | 494 | lane_count, |
484 | dp->link_train.training_lane); | 495 | dp->link_train.training_lane); |
496 | if (retval) | ||
497 | return retval; | ||
485 | 498 | ||
486 | dev_info(dp->dev, "Link Training Clock Recovery success\n"); | 499 | dev_info(dp->dev, "Link Training Clock Recovery success\n"); |
487 | dp->link_train.lt_state = EQUALIZER_TRAINING; | 500 | dp->link_train.lt_state = EQUALIZER_TRAINING; |
@@ -489,9 +502,12 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) | |||
489 | for (lane = 0; lane < lane_count; lane++) { | 502 | for (lane = 0; lane < lane_count; lane++) { |
490 | training_lane = exynos_dp_get_lane_link_training( | 503 | training_lane = exynos_dp_get_lane_link_training( |
491 | dp, lane); | 504 | dp, lane); |
492 | exynos_dp_read_bytes_from_dpcd(dp, | 505 | retval = exynos_dp_read_bytes_from_dpcd(dp, |
493 | DPCD_ADDR_ADJUST_REQUEST_LANE0_1, | 506 | DPCD_ADDR_ADJUST_REQUEST_LANE0_1, |
494 | 2, adjust_request); | 507 | 2, adjust_request); |
508 | if (retval) | ||
509 | return retval; | ||
510 | |||
495 | voltage_swing = exynos_dp_get_adjust_request_voltage( | 511 | voltage_swing = exynos_dp_get_adjust_request_voltage( |
496 | adjust_request, lane); | 512 | adjust_request, lane); |
497 | pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( | 513 | pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( |
@@ -528,13 +544,14 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) | |||
528 | dp->link_train.training_lane[lane], lane); | 544 | dp->link_train.training_lane[lane], lane); |
529 | } | 545 | } |
530 | 546 | ||
531 | exynos_dp_write_bytes_to_dpcd(dp, | 547 | retval = exynos_dp_write_bytes_to_dpcd(dp, |
532 | DPCD_ADDR_TRAINING_LANE0_SET, | 548 | DPCD_ADDR_TRAINING_LANE0_SET, lane_count, |
533 | lane_count, | 549 | dp->link_train.training_lane); |
534 | dp->link_train.training_lane); | 550 | if (retval) |
551 | return retval; | ||
535 | } | 552 | } |
536 | 553 | ||
537 | return 0; | 554 | return retval; |
538 | 555 | ||
539 | reduce_link_rate: | 556 | reduce_link_rate: |
540 | exynos_dp_reduce_link_rate(dp); | 557 | exynos_dp_reduce_link_rate(dp); |
@@ -545,8 +562,7 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) | |||
545 | { | 562 | { |
546 | u8 link_status[2]; | 563 | u8 link_status[2]; |
547 | u8 link_align[3]; | 564 | u8 link_align[3]; |
548 | int lane; | 565 | int lane, lane_count, retval; |
549 | int lane_count; | ||
550 | u32 reg; | 566 | u32 reg; |
551 | 567 | ||
552 | u8 adjust_request[2]; | 568 | u8 adjust_request[2]; |
@@ -558,8 +574,10 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) | |||
558 | 574 | ||
559 | lane_count = dp->link_train.lane_count; | 575 | lane_count = dp->link_train.lane_count; |
560 | 576 | ||
561 | exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS, | 577 | retval = exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS, |
562 | 2, link_status); | 578 | 2, link_status); |
579 | if (retval) | ||
580 | return retval; | ||
563 | 581 | ||
564 | if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) { | 582 | if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) { |
565 | link_align[0] = link_status[0]; | 583 | link_align[0] = link_status[0]; |
@@ -570,9 +588,12 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) | |||
570 | &link_align[2]); | 588 | &link_align[2]); |
571 | 589 | ||
572 | for (lane = 0; lane < lane_count; lane++) { | 590 | for (lane = 0; lane < lane_count; lane++) { |
573 | exynos_dp_read_bytes_from_dpcd(dp, | 591 | retval = exynos_dp_read_bytes_from_dpcd(dp, |
574 | DPCD_ADDR_ADJUST_REQUEST_LANE0_1, | 592 | DPCD_ADDR_ADJUST_REQUEST_LANE0_1, |
575 | 2, adjust_request); | 593 | 2, adjust_request); |
594 | if (retval) | ||
595 | return retval; | ||
596 | |||
576 | voltage_swing = exynos_dp_get_adjust_request_voltage( | 597 | voltage_swing = exynos_dp_get_adjust_request_voltage( |
577 | adjust_request, lane); | 598 | adjust_request, lane); |
578 | pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( | 599 | pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( |
@@ -621,10 +642,12 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) | |||
621 | dp->link_train.training_lane[lane], | 642 | dp->link_train.training_lane[lane], |
622 | lane); | 643 | lane); |
623 | 644 | ||
624 | exynos_dp_write_bytes_to_dpcd(dp, | 645 | retval = exynos_dp_write_bytes_to_dpcd(dp, |
625 | DPCD_ADDR_TRAINING_LANE0_SET, | 646 | DPCD_ADDR_TRAINING_LANE0_SET, |
626 | lane_count, | 647 | lane_count, |
627 | dp->link_train.training_lane); | 648 | dp->link_train.training_lane); |
649 | if (retval) | ||
650 | return retval; | ||
628 | } | 651 | } |
629 | } else { | 652 | } else { |
630 | goto reduce_link_rate; | 653 | goto reduce_link_rate; |
@@ -702,16 +725,17 @@ static void exynos_dp_init_training(struct exynos_dp_device *dp, | |||
702 | 725 | ||
703 | static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) | 726 | static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) |
704 | { | 727 | { |
705 | int retval = 0; | 728 | int retval = 0, training_finished = 0; |
706 | int training_finished = 0; | ||
707 | 729 | ||
708 | dp->link_train.lt_state = START; | 730 | dp->link_train.lt_state = START; |
709 | 731 | ||
710 | /* Process here */ | 732 | /* Process here */ |
711 | while (!training_finished) { | 733 | while (!retval && !training_finished) { |
712 | switch (dp->link_train.lt_state) { | 734 | switch (dp->link_train.lt_state) { |
713 | case START: | 735 | case START: |
714 | exynos_dp_link_start(dp); | 736 | retval = exynos_dp_link_start(dp); |
737 | if (retval) | ||
738 | dev_err(dp->dev, "LT link start failed!\n"); | ||
715 | break; | 739 | break; |
716 | case CLOCK_RECOVERY: | 740 | case CLOCK_RECOVERY: |
717 | retval = exynos_dp_process_clock_recovery(dp); | 741 | retval = exynos_dp_process_clock_recovery(dp); |
@@ -730,6 +754,8 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) | |||
730 | return -EREMOTEIO; | 754 | return -EREMOTEIO; |
731 | } | 755 | } |
732 | } | 756 | } |
757 | if (retval) | ||
758 | dev_err(dp->dev, "eDP link training failed (%d)\n", retval); | ||
733 | 759 | ||
734 | return retval; | 760 | return retval; |
735 | } | 761 | } |