aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_display.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c77
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
809void radeon_compute_pll(struct radeon_pll *pll, 811void 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
924static struct drm_prop_enum_list radeon_underscan_enum_list[] =
925{ { UNDERSCAN_OFF, "off" },
926 { UNDERSCAN_ON, "on" },
927 { UNDERSCAN_AUTO, "auto" },
928};
929
922static int radeon_modeset_create_props(struct radeon_device *rdev) 930static 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);