diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/atombios_crtc.c')
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_crtc.c | 100 |
1 files changed, 86 insertions, 14 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 12ad512bd3d3..cd0290f946cf 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -332,6 +332,11 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc, | |||
332 | args.usV_SyncWidth = | 332 | args.usV_SyncWidth = |
333 | cpu_to_le16(mode->crtc_vsync_end - mode->crtc_vsync_start); | 333 | cpu_to_le16(mode->crtc_vsync_end - mode->crtc_vsync_start); |
334 | 334 | ||
335 | args.ucOverscanRight = radeon_crtc->h_border; | ||
336 | args.ucOverscanLeft = radeon_crtc->h_border; | ||
337 | args.ucOverscanBottom = radeon_crtc->v_border; | ||
338 | args.ucOverscanTop = radeon_crtc->v_border; | ||
339 | |||
335 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) | 340 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) |
336 | misc |= ATOM_VSYNC_POLARITY; | 341 | misc |= ATOM_VSYNC_POLARITY; |
337 | if (mode->flags & DRM_MODE_FLAG_NHSYNC) | 342 | if (mode->flags & DRM_MODE_FLAG_NHSYNC) |
@@ -471,6 +476,8 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
471 | struct radeon_encoder *radeon_encoder = NULL; | 476 | struct radeon_encoder *radeon_encoder = NULL; |
472 | u32 adjusted_clock = mode->clock; | 477 | u32 adjusted_clock = mode->clock; |
473 | int encoder_mode = 0; | 478 | int encoder_mode = 0; |
479 | u32 dp_clock = mode->clock; | ||
480 | int bpc = 8; | ||
474 | 481 | ||
475 | /* reset the pll flags */ | 482 | /* reset the pll flags */ |
476 | pll->flags = 0; | 483 | pll->flags = 0; |
@@ -513,6 +520,17 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
513 | if (encoder->crtc == crtc) { | 520 | if (encoder->crtc == crtc) { |
514 | radeon_encoder = to_radeon_encoder(encoder); | 521 | radeon_encoder = to_radeon_encoder(encoder); |
515 | encoder_mode = atombios_get_encoder_mode(encoder); | 522 | encoder_mode = atombios_get_encoder_mode(encoder); |
523 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) { | ||
524 | struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); | ||
525 | if (connector) { | ||
526 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
527 | struct radeon_connector_atom_dig *dig_connector = | ||
528 | radeon_connector->con_priv; | ||
529 | |||
530 | dp_clock = dig_connector->dp_clock; | ||
531 | } | ||
532 | } | ||
533 | |||
516 | if (ASIC_IS_AVIVO(rdev)) { | 534 | if (ASIC_IS_AVIVO(rdev)) { |
517 | /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ | 535 | /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ |
518 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) | 536 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) |
@@ -521,6 +539,21 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
521 | pll->algo = PLL_ALGO_LEGACY; | 539 | pll->algo = PLL_ALGO_LEGACY; |
522 | pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; | 540 | pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER; |
523 | } | 541 | } |
542 | /* There is some evidence (often anecdotal) that RV515/RV620 LVDS | ||
543 | * (on some boards at least) prefers the legacy algo. I'm not | ||
544 | * sure whether this should handled generically or on a | ||
545 | * case-by-case quirk basis. Both algos should work fine in the | ||
546 | * majority of cases. | ||
547 | */ | ||
548 | if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) && | ||
549 | ((rdev->family == CHIP_RV515) || | ||
550 | (rdev->family == CHIP_RV620))) { | ||
551 | /* allow the user to overrride just in case */ | ||
552 | if (radeon_new_pll == 1) | ||
553 | pll->algo = PLL_ALGO_NEW; | ||
554 | else | ||
555 | pll->algo = PLL_ALGO_LEGACY; | ||
556 | } | ||
524 | } else { | 557 | } else { |
525 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) | 558 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) |
526 | pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; | 559 | pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; |
@@ -555,6 +588,14 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
555 | args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); | 588 | args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); |
556 | args.v1.ucTransmitterID = radeon_encoder->encoder_id; | 589 | args.v1.ucTransmitterID = radeon_encoder->encoder_id; |
557 | args.v1.ucEncodeMode = encoder_mode; | 590 | args.v1.ucEncodeMode = encoder_mode; |
591 | if (encoder_mode == ATOM_ENCODER_MODE_DP) { | ||
592 | /* may want to enable SS on DP eventually */ | ||
593 | /* args.v1.ucConfig |= | ||
594 | ADJUST_DISPLAY_CONFIG_SS_ENABLE;*/ | ||
595 | } else if (encoder_mode == ATOM_ENCODER_MODE_LVDS) { | ||
596 | args.v1.ucConfig |= | ||
597 | ADJUST_DISPLAY_CONFIG_SS_ENABLE; | ||
598 | } | ||
558 | 599 | ||
559 | atom_execute_table(rdev->mode_info.atom_context, | 600 | atom_execute_table(rdev->mode_info.atom_context, |
560 | index, (uint32_t *)&args); | 601 | index, (uint32_t *)&args); |
@@ -568,10 +609,20 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
568 | if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { | 609 | if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { |
569 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 610 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
570 | 611 | ||
571 | if (encoder_mode == ATOM_ENCODER_MODE_DP) | 612 | if (encoder_mode == ATOM_ENCODER_MODE_DP) { |
613 | /* may want to enable SS on DP/eDP eventually */ | ||
614 | /*args.v3.sInput.ucDispPllConfig |= | ||
615 | DISPPLL_CONFIG_SS_ENABLE;*/ | ||
572 | args.v3.sInput.ucDispPllConfig |= | 616 | args.v3.sInput.ucDispPllConfig |= |
573 | DISPPLL_CONFIG_COHERENT_MODE; | 617 | DISPPLL_CONFIG_COHERENT_MODE; |
574 | else { | 618 | /* 16200 or 27000 */ |
619 | args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10); | ||
620 | } else { | ||
621 | if (encoder_mode == ATOM_ENCODER_MODE_HDMI) { | ||
622 | /* deep color support */ | ||
623 | args.v3.sInput.usPixelClock = | ||
624 | cpu_to_le16((mode->clock * bpc / 8) / 10); | ||
625 | } | ||
575 | if (dig->coherent_mode) | 626 | if (dig->coherent_mode) |
576 | args.v3.sInput.ucDispPllConfig |= | 627 | args.v3.sInput.ucDispPllConfig |= |
577 | DISPPLL_CONFIG_COHERENT_MODE; | 628 | DISPPLL_CONFIG_COHERENT_MODE; |
@@ -580,13 +631,19 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, | |||
580 | DISPPLL_CONFIG_DUAL_LINK; | 631 | DISPPLL_CONFIG_DUAL_LINK; |
581 | } | 632 | } |
582 | } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | 633 | } else if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { |
583 | /* may want to enable SS on DP/eDP eventually */ | 634 | if (encoder_mode == ATOM_ENCODER_MODE_DP) { |
584 | /*args.v3.sInput.ucDispPllConfig |= | 635 | /* may want to enable SS on DP/eDP eventually */ |
585 | DISPPLL_CONFIG_SS_ENABLE;*/ | 636 | /*args.v3.sInput.ucDispPllConfig |= |
586 | if (encoder_mode == ATOM_ENCODER_MODE_DP) | 637 | DISPPLL_CONFIG_SS_ENABLE;*/ |
587 | args.v3.sInput.ucDispPllConfig |= | 638 | args.v3.sInput.ucDispPllConfig |= |
588 | DISPPLL_CONFIG_COHERENT_MODE; | 639 | DISPPLL_CONFIG_COHERENT_MODE; |
589 | else { | 640 | /* 16200 or 27000 */ |
641 | args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10); | ||
642 | } else if (encoder_mode == ATOM_ENCODER_MODE_LVDS) { | ||
643 | /* want to enable SS on LVDS eventually */ | ||
644 | /*args.v3.sInput.ucDispPllConfig |= | ||
645 | DISPPLL_CONFIG_SS_ENABLE;*/ | ||
646 | } else { | ||
590 | if (mode->clock > 165000) | 647 | if (mode->clock > 165000) |
591 | args.v3.sInput.ucDispPllConfig |= | 648 | args.v3.sInput.ucDispPllConfig |= |
592 | DISPPLL_CONFIG_DUAL_LINK; | 649 | DISPPLL_CONFIG_DUAL_LINK; |
@@ -1019,11 +1076,11 @@ static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
1019 | 1076 | ||
1020 | if (rdev->family >= CHIP_RV770) { | 1077 | if (rdev->family >= CHIP_RV770) { |
1021 | if (radeon_crtc->crtc_id) { | 1078 | if (radeon_crtc->crtc_id) { |
1022 | WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0); | 1079 | WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); |
1023 | WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0); | 1080 | WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); |
1024 | } else { | 1081 | } else { |
1025 | WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, 0); | 1082 | WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); |
1026 | WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, 0); | 1083 | WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location)); |
1027 | } | 1084 | } |
1028 | } | 1085 | } |
1029 | WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, | 1086 | WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, |
@@ -1160,8 +1217,18 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, | |||
1160 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 1217 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
1161 | struct drm_device *dev = crtc->dev; | 1218 | struct drm_device *dev = crtc->dev; |
1162 | struct radeon_device *rdev = dev->dev_private; | 1219 | struct radeon_device *rdev = dev->dev_private; |
1220 | struct drm_encoder *encoder; | ||
1221 | bool is_tvcv = false; | ||
1163 | 1222 | ||
1164 | /* TODO color tiling */ | 1223 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
1224 | /* find tv std */ | ||
1225 | if (encoder->crtc == crtc) { | ||
1226 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
1227 | if (radeon_encoder->active_device & | ||
1228 | (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) | ||
1229 | is_tvcv = true; | ||
1230 | } | ||
1231 | } | ||
1165 | 1232 | ||
1166 | atombios_disable_ss(crtc); | 1233 | atombios_disable_ss(crtc); |
1167 | /* always set DCPLL */ | 1234 | /* always set DCPLL */ |
@@ -1170,9 +1237,14 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, | |||
1170 | atombios_crtc_set_pll(crtc, adjusted_mode); | 1237 | atombios_crtc_set_pll(crtc, adjusted_mode); |
1171 | atombios_enable_ss(crtc); | 1238 | atombios_enable_ss(crtc); |
1172 | 1239 | ||
1173 | if (ASIC_IS_AVIVO(rdev)) | 1240 | if (ASIC_IS_DCE4(rdev)) |
1174 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); | 1241 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); |
1175 | else { | 1242 | else if (ASIC_IS_AVIVO(rdev)) { |
1243 | if (is_tvcv) | ||
1244 | atombios_crtc_set_timing(crtc, adjusted_mode); | ||
1245 | else | ||
1246 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); | ||
1247 | } else { | ||
1176 | atombios_crtc_set_timing(crtc, adjusted_mode); | 1248 | atombios_crtc_set_timing(crtc, adjusted_mode); |
1177 | if (radeon_crtc->crtc_id == 0) | 1249 | if (radeon_crtc->crtc_id == 0) |
1178 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); | 1250 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); |