diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_display.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 77 |
1 files changed, 63 insertions, 14 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 8154cdf796e4..74dac9635d70 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -42,7 +42,7 @@ static void avivo_crtc_load_lut(struct drm_crtc *crtc) | |||
42 | struct radeon_device *rdev = dev->dev_private; | 42 | struct radeon_device *rdev = dev->dev_private; |
43 | int i; | 43 | int i; |
44 | 44 | ||
45 | DRM_DEBUG("%d\n", radeon_crtc->crtc_id); | 45 | DRM_DEBUG_KMS("%d\n", radeon_crtc->crtc_id); |
46 | WREG32(AVIVO_DC_LUTA_CONTROL + radeon_crtc->crtc_offset, 0); | 46 | WREG32(AVIVO_DC_LUTA_CONTROL + radeon_crtc->crtc_offset, 0); |
47 | 47 | ||
48 | WREG32(AVIVO_DC_LUTA_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0); | 48 | WREG32(AVIVO_DC_LUTA_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0); |
@@ -75,7 +75,7 @@ static void evergreen_crtc_load_lut(struct drm_crtc *crtc) | |||
75 | struct radeon_device *rdev = dev->dev_private; | 75 | struct radeon_device *rdev = dev->dev_private; |
76 | int i; | 76 | int i; |
77 | 77 | ||
78 | DRM_DEBUG("%d\n", radeon_crtc->crtc_id); | 78 | DRM_DEBUG_KMS("%d\n", radeon_crtc->crtc_id); |
79 | WREG32(EVERGREEN_DC_LUT_CONTROL + radeon_crtc->crtc_offset, 0); | 79 | WREG32(EVERGREEN_DC_LUT_CONTROL + radeon_crtc->crtc_offset, 0); |
80 | 80 | ||
81 | WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0); | 81 | WREG32(EVERGREEN_DC_LUT_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0); |
@@ -469,7 +469,7 @@ static void radeon_compute_pll_legacy(struct radeon_pll *pll, | |||
469 | uint32_t post_div; | 469 | uint32_t post_div; |
470 | u32 pll_out_min, pll_out_max; | 470 | u32 pll_out_min, pll_out_max; |
471 | 471 | ||
472 | DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div); | 472 | DRM_DEBUG_KMS("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div); |
473 | freq = freq * 1000; | 473 | freq = freq * 1000; |
474 | 474 | ||
475 | if (pll->flags & RADEON_PLL_IS_LCD) { | 475 | if (pll->flags & RADEON_PLL_IS_LCD) { |
@@ -558,15 +558,17 @@ static void radeon_compute_pll_legacy(struct radeon_pll *pll, | |||
558 | current_freq = radeon_div(tmp, ref_div * post_div); | 558 | current_freq = radeon_div(tmp, ref_div * post_div); |
559 | 559 | ||
560 | if (pll->flags & RADEON_PLL_PREFER_CLOSEST_LOWER) { | 560 | if (pll->flags & RADEON_PLL_PREFER_CLOSEST_LOWER) { |
561 | error = freq - current_freq; | 561 | if (freq < current_freq) |
562 | error = error < 0 ? 0xffffffff : error; | 562 | error = 0xffffffff; |
563 | else | ||
564 | error = freq - current_freq; | ||
563 | } else | 565 | } else |
564 | error = abs(current_freq - freq); | 566 | error = abs(current_freq - freq); |
565 | vco_diff = abs(vco - best_vco); | 567 | vco_diff = abs(vco - best_vco); |
566 | 568 | ||
567 | if ((best_vco == 0 && error < best_error) || | 569 | if ((best_vco == 0 && error < best_error) || |
568 | (best_vco != 0 && | 570 | (best_vco != 0 && |
569 | (error < best_error - 100 || | 571 | ((best_error > 100 && error < best_error - 100) || |
570 | (abs(error - best_error) < 100 && vco_diff < best_vco_diff)))) { | 572 | (abs(error - best_error) < 100 && vco_diff < best_vco_diff)))) { |
571 | best_post_div = post_div; | 573 | best_post_div = post_div; |
572 | best_ref_div = ref_div; | 574 | best_ref_div = ref_div; |
@@ -803,7 +805,7 @@ done: | |||
803 | *ref_div_p = ref_div; | 805 | *ref_div_p = ref_div; |
804 | *post_div_p = post_div; | 806 | *post_div_p = post_div; |
805 | 807 | ||
806 | DRM_DEBUG("%u %d.%d, %d, %d\n", *dot_clock_p, *fb_div_p, *frac_fb_div_p, *ref_div_p, *post_div_p); | 808 | DRM_DEBUG_KMS("%u %d.%d, %d, %d\n", *dot_clock_p, *fb_div_p, *frac_fb_div_p, *ref_div_p, *post_div_p); |
807 | } | 809 | } |
808 | 810 | ||
809 | void radeon_compute_pll(struct radeon_pll *pll, | 811 | void radeon_compute_pll(struct radeon_pll *pll, |
@@ -919,6 +921,12 @@ static struct drm_prop_enum_list radeon_tv_std_enum_list[] = | |||
919 | { TV_STD_SECAM, "secam" }, | 921 | { TV_STD_SECAM, "secam" }, |
920 | }; | 922 | }; |
921 | 923 | ||
924 | static struct drm_prop_enum_list radeon_underscan_enum_list[] = | ||
925 | { { UNDERSCAN_OFF, "off" }, | ||
926 | { UNDERSCAN_ON, "on" }, | ||
927 | { UNDERSCAN_AUTO, "auto" }, | ||
928 | }; | ||
929 | |||
922 | static int radeon_modeset_create_props(struct radeon_device *rdev) | 930 | static int radeon_modeset_create_props(struct radeon_device *rdev) |
923 | { | 931 | { |
924 | int i, sz; | 932 | int i, sz; |
@@ -972,6 +980,18 @@ static int radeon_modeset_create_props(struct radeon_device *rdev) | |||
972 | radeon_tv_std_enum_list[i].name); | 980 | radeon_tv_std_enum_list[i].name); |
973 | } | 981 | } |
974 | 982 | ||
983 | sz = ARRAY_SIZE(radeon_underscan_enum_list); | ||
984 | rdev->mode_info.underscan_property = | ||
985 | drm_property_create(rdev->ddev, | ||
986 | DRM_MODE_PROP_ENUM, | ||
987 | "underscan", sz); | ||
988 | for (i = 0; i < sz; i++) { | ||
989 | drm_property_add_enum(rdev->mode_info.underscan_property, | ||
990 | i, | ||
991 | radeon_underscan_enum_list[i].type, | ||
992 | radeon_underscan_enum_list[i].name); | ||
993 | } | ||
994 | |||
975 | return 0; | 995 | return 0; |
976 | } | 996 | } |
977 | 997 | ||
@@ -1067,15 +1087,26 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | |||
1067 | struct drm_display_mode *adjusted_mode) | 1087 | struct drm_display_mode *adjusted_mode) |
1068 | { | 1088 | { |
1069 | struct drm_device *dev = crtc->dev; | 1089 | struct drm_device *dev = crtc->dev; |
1090 | struct radeon_device *rdev = dev->dev_private; | ||
1070 | struct drm_encoder *encoder; | 1091 | struct drm_encoder *encoder; |
1071 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 1092 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
1072 | struct radeon_encoder *radeon_encoder; | 1093 | struct radeon_encoder *radeon_encoder; |
1094 | struct drm_connector *connector; | ||
1095 | struct radeon_connector *radeon_connector; | ||
1073 | bool first = true; | 1096 | bool first = true; |
1097 | u32 src_v = 1, dst_v = 1; | ||
1098 | u32 src_h = 1, dst_h = 1; | ||
1099 | |||
1100 | radeon_crtc->h_border = 0; | ||
1101 | radeon_crtc->v_border = 0; | ||
1074 | 1102 | ||
1075 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 1103 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
1076 | radeon_encoder = to_radeon_encoder(encoder); | ||
1077 | if (encoder->crtc != crtc) | 1104 | if (encoder->crtc != crtc) |
1078 | continue; | 1105 | continue; |
1106 | radeon_encoder = to_radeon_encoder(encoder); | ||
1107 | connector = radeon_get_connector_for_encoder(encoder); | ||
1108 | radeon_connector = to_radeon_connector(connector); | ||
1109 | |||
1079 | if (first) { | 1110 | if (first) { |
1080 | /* set scaling */ | 1111 | /* set scaling */ |
1081 | if (radeon_encoder->rmx_type == RMX_OFF) | 1112 | if (radeon_encoder->rmx_type == RMX_OFF) |
@@ -1085,31 +1116,49 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc, | |||
1085 | radeon_crtc->rmx_type = radeon_encoder->rmx_type; | 1116 | radeon_crtc->rmx_type = radeon_encoder->rmx_type; |
1086 | else | 1117 | else |
1087 | radeon_crtc->rmx_type = RMX_OFF; | 1118 | radeon_crtc->rmx_type = RMX_OFF; |
1119 | src_v = crtc->mode.vdisplay; | ||
1120 | dst_v = radeon_crtc->native_mode.vdisplay; | ||
1121 | src_h = crtc->mode.hdisplay; | ||
1122 | dst_h = radeon_crtc->native_mode.vdisplay; | ||
1088 | /* copy native mode */ | 1123 | /* copy native mode */ |
1089 | memcpy(&radeon_crtc->native_mode, | 1124 | memcpy(&radeon_crtc->native_mode, |
1090 | &radeon_encoder->native_mode, | 1125 | &radeon_encoder->native_mode, |
1091 | sizeof(struct drm_display_mode)); | 1126 | sizeof(struct drm_display_mode)); |
1127 | |||
1128 | /* fix up for overscan on hdmi */ | ||
1129 | if (ASIC_IS_AVIVO(rdev) && | ||
1130 | ((radeon_encoder->underscan_type == UNDERSCAN_ON) || | ||
1131 | ((radeon_encoder->underscan_type == UNDERSCAN_AUTO) && | ||
1132 | drm_detect_hdmi_monitor(radeon_connector->edid)))) { | ||
1133 | radeon_crtc->h_border = (mode->hdisplay >> 5) + 16; | ||
1134 | radeon_crtc->v_border = (mode->vdisplay >> 5) + 16; | ||
1135 | radeon_crtc->rmx_type = RMX_FULL; | ||
1136 | src_v = crtc->mode.vdisplay; | ||
1137 | dst_v = crtc->mode.vdisplay - (radeon_crtc->v_border * 2); | ||
1138 | src_h = crtc->mode.hdisplay; | ||
1139 | dst_h = crtc->mode.hdisplay - (radeon_crtc->h_border * 2); | ||
1140 | } | ||
1092 | first = false; | 1141 | first = false; |
1093 | } else { | 1142 | } else { |
1094 | if (radeon_crtc->rmx_type != radeon_encoder->rmx_type) { | 1143 | if (radeon_crtc->rmx_type != radeon_encoder->rmx_type) { |
1095 | /* WARNING: Right now this can't happen but | 1144 | /* WARNING: Right now this can't happen but |
1096 | * in the future we need to check that scaling | 1145 | * in the future we need to check that scaling |
1097 | * are consistent accross different encoder | 1146 | * are consistent across different encoder |
1098 | * (ie all encoder can work with the same | 1147 | * (ie all encoder can work with the same |
1099 | * scaling). | 1148 | * scaling). |
1100 | */ | 1149 | */ |
1101 | DRM_ERROR("Scaling not consistent accross encoder.\n"); | 1150 | DRM_ERROR("Scaling not consistent across encoder.\n"); |
1102 | return false; | 1151 | return false; |
1103 | } | 1152 | } |
1104 | } | 1153 | } |
1105 | } | 1154 | } |
1106 | if (radeon_crtc->rmx_type != RMX_OFF) { | 1155 | if (radeon_crtc->rmx_type != RMX_OFF) { |
1107 | fixed20_12 a, b; | 1156 | fixed20_12 a, b; |
1108 | a.full = dfixed_const(crtc->mode.vdisplay); | 1157 | a.full = dfixed_const(src_v); |
1109 | b.full = dfixed_const(radeon_crtc->native_mode.hdisplay); | 1158 | b.full = dfixed_const(dst_v); |
1110 | radeon_crtc->vsc.full = dfixed_div(a, b); | 1159 | radeon_crtc->vsc.full = dfixed_div(a, b); |
1111 | a.full = dfixed_const(crtc->mode.hdisplay); | 1160 | a.full = dfixed_const(src_h); |
1112 | b.full = dfixed_const(radeon_crtc->native_mode.vdisplay); | 1161 | b.full = dfixed_const(dst_h); |
1113 | radeon_crtc->hsc.full = dfixed_div(a, b); | 1162 | radeon_crtc->hsc.full = dfixed_div(a, b); |
1114 | } else { | 1163 | } else { |
1115 | radeon_crtc->vsc.full = dfixed_const(1); | 1164 | radeon_crtc->vsc.full = dfixed_const(1); |