Commit da997620 authored by Alex Deucher's avatar Alex Deucher

drm/radeon: enable display scaling on all connectors (v2)

This enables the display scaler on all connectors for r5xx
and newer asics.  Previously we only enabled the scaler for
fixed mode displays (eDP or LVDS) since they have to use the
scaler to support non-native modes.  Most other displays
are multi-sync or have a built in scaler to support non-native
modes.  The default scaling mode for non-fixed displays is
none which will use the scaler in the monitor.  Note that
we do not populate any fake modes like we do for fixed
displays so it will only use the modes in the edid.  For
other modes, you'll need to populate them manually.

bug:
https://bugs.freedesktop.org/show_bug.cgi?id=80868

v2: properly handle scaling with no modes defined
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 9c244878
...@@ -331,12 +331,10 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, ...@@ -331,12 +331,10 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
&& (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2))) && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2; adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
/* get the native mode for LVDS */ /* get the native mode for scaling */
if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
radeon_panel_mode_fixup(encoder, adjusted_mode); radeon_panel_mode_fixup(encoder, adjusted_mode);
} else if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
/* get the native mode for TV */
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv; struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
if (tv_dac) { if (tv_dac) {
if (tv_dac->tv_std == TV_STD_NTSC || if (tv_dac->tv_std == TV_STD_NTSC ||
...@@ -346,6 +344,8 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, ...@@ -346,6 +344,8 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
else else
radeon_atom_get_tv_timings(rdev, 1, adjusted_mode); radeon_atom_get_tv_timings(rdev, 1, adjusted_mode);
} }
} else if (radeon_encoder->rmx_type != RMX_OFF) {
radeon_panel_mode_fixup(encoder, adjusted_mode);
} }
if (ASIC_IS_DCE3(rdev) && if (ASIC_IS_DCE3(rdev) &&
......
...@@ -271,6 +271,27 @@ static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *conn ...@@ -271,6 +271,27 @@ static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *conn
return NULL; return NULL;
} }
static void radeon_get_native_mode(struct drm_connector *connector)
{
struct drm_encoder *encoder = radeon_best_single_encoder(connector);
struct radeon_encoder *radeon_encoder;
if (encoder == NULL)
return;
radeon_encoder = to_radeon_encoder(encoder);
if (!list_empty(&connector->probed_modes)) {
struct drm_display_mode *preferred_mode =
list_first_entry(&connector->probed_modes,
struct drm_display_mode, head);
radeon_encoder->native_mode = *preferred_mode;
} else {
radeon_encoder->native_mode.clock = 0;
}
}
/* /*
* radeon_connector_analog_encoder_conflict_solve * radeon_connector_analog_encoder_conflict_solve
* - search for other connectors sharing this encoder * - search for other connectors sharing this encoder
...@@ -571,6 +592,35 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct ...@@ -571,6 +592,35 @@ static int radeon_connector_set_property(struct drm_connector *connector, struct
radeon_property_change_mode(&radeon_encoder->base); radeon_property_change_mode(&radeon_encoder->base);
} }
if (property == dev->mode_config.scaling_mode_property) {
enum radeon_rmx_type rmx_type;
if (connector->encoder)
radeon_encoder = to_radeon_encoder(connector->encoder);
else {
struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
}
switch (val) {
default:
case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break;
case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break;
case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break;
case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break;
}
if (radeon_encoder->rmx_type == rmx_type)
return 0;
if ((rmx_type != DRM_MODE_SCALE_NONE) &&
(radeon_encoder->native_mode.clock == 0))
return 0;
radeon_encoder->rmx_type = rmx_type;
radeon_property_change_mode(&radeon_encoder->base);
}
return 0; return 0;
} }
...@@ -788,6 +838,8 @@ static int radeon_vga_get_modes(struct drm_connector *connector) ...@@ -788,6 +838,8 @@ static int radeon_vga_get_modes(struct drm_connector *connector)
ret = radeon_ddc_get_modes(radeon_connector); ret = radeon_ddc_get_modes(radeon_connector);
radeon_get_native_mode(connector);
return ret; return ret;
} }
...@@ -991,6 +1043,9 @@ static int radeon_dvi_get_modes(struct drm_connector *connector) ...@@ -991,6 +1043,9 @@ static int radeon_dvi_get_modes(struct drm_connector *connector)
int ret; int ret;
ret = radeon_ddc_get_modes(radeon_connector); ret = radeon_ddc_get_modes(radeon_connector);
radeon_get_native_mode(connector);
return ret; return ret;
} }
...@@ -1358,6 +1413,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector) ...@@ -1358,6 +1413,8 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
radeon_atom_ext_encoder_setup_ddc(encoder); radeon_atom_ext_encoder_setup_ddc(encoder);
} }
ret = radeon_ddc_get_modes(radeon_connector); ret = radeon_ddc_get_modes(radeon_connector);
radeon_get_native_mode(connector);
} }
return ret; return ret;
...@@ -1717,6 +1774,9 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1717,6 +1774,9 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_object_attach_property(&radeon_connector->base.base, drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property, rdev->mode_info.load_detect_property,
1); 1);
drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_NONE);
break; break;
case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_DVID: case DRM_MODE_CONNECTOR_DVID:
...@@ -1737,6 +1797,10 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1737,6 +1797,10 @@ radeon_add_atom_connector(struct drm_device *dev,
rdev->mode_info.underscan_vborder_property, rdev->mode_info.underscan_vborder_property,
0); 0);
drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_NONE);
drm_object_attach_property(&radeon_connector->base.base, drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.dither_property, rdev->mode_info.dither_property,
RADEON_FMT_DITHER_DISABLE); RADEON_FMT_DITHER_DISABLE);
...@@ -1787,6 +1851,10 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1787,6 +1851,10 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_object_attach_property(&radeon_connector->base.base, drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property, rdev->mode_info.load_detect_property,
1); 1);
if (ASIC_IS_AVIVO(rdev))
drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_NONE);
/* no HPD on analog connectors */ /* no HPD on analog connectors */
radeon_connector->hpd.hpd = RADEON_HPD_NONE; radeon_connector->hpd.hpd = RADEON_HPD_NONE;
connector->polled = DRM_CONNECTOR_POLL_CONNECT; connector->polled = DRM_CONNECTOR_POLL_CONNECT;
...@@ -1805,6 +1873,10 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1805,6 +1873,10 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_object_attach_property(&radeon_connector->base.base, drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.load_detect_property, rdev->mode_info.load_detect_property,
1); 1);
if (ASIC_IS_AVIVO(rdev))
drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_NONE);
/* no HPD on analog connectors */ /* no HPD on analog connectors */
radeon_connector->hpd.hpd = RADEON_HPD_NONE; radeon_connector->hpd.hpd = RADEON_HPD_NONE;
connector->interlace_allowed = true; connector->interlace_allowed = true;
...@@ -1838,17 +1910,18 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1838,17 +1910,18 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_object_attach_property(&radeon_connector->base.base, drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_vborder_property, rdev->mode_info.underscan_vborder_property,
0); 0);
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.dither_property,
RADEON_FMT_DITHER_DISABLE);
drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_NONE);
} }
if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) { if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
drm_object_attach_property(&radeon_connector->base.base, drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.audio_property, rdev->mode_info.audio_property,
RADEON_AUDIO_AUTO); RADEON_AUDIO_AUTO);
} }
if (ASIC_IS_AVIVO(rdev)) {
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.dither_property,
RADEON_FMT_DITHER_DISABLE);
}
if (connector_type == DRM_MODE_CONNECTOR_DVII) { if (connector_type == DRM_MODE_CONNECTOR_DVII) {
radeon_connector->dac_load_detect = true; radeon_connector->dac_load_detect = true;
drm_object_attach_property(&radeon_connector->base.base, drm_object_attach_property(&radeon_connector->base.base,
...@@ -1888,17 +1961,18 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1888,17 +1961,18 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_object_attach_property(&radeon_connector->base.base, drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_vborder_property, rdev->mode_info.underscan_vborder_property,
0); 0);
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.dither_property,
RADEON_FMT_DITHER_DISABLE);
drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_NONE);
} }
if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) { if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
drm_object_attach_property(&radeon_connector->base.base, drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.audio_property, rdev->mode_info.audio_property,
RADEON_AUDIO_AUTO); RADEON_AUDIO_AUTO);
} }
if (ASIC_IS_AVIVO(rdev)) {
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.dither_property,
RADEON_FMT_DITHER_DISABLE);
}
subpixel_order = SubPixelHorizontalRGB; subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = true; connector->interlace_allowed = true;
if (connector_type == DRM_MODE_CONNECTOR_HDMIB) if (connector_type == DRM_MODE_CONNECTOR_HDMIB)
...@@ -1935,18 +2009,18 @@ radeon_add_atom_connector(struct drm_device *dev, ...@@ -1935,18 +2009,18 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_object_attach_property(&radeon_connector->base.base, drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.underscan_vborder_property, rdev->mode_info.underscan_vborder_property,
0); 0);
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.dither_property,
RADEON_FMT_DITHER_DISABLE);
drm_object_attach_property(&radeon_connector->base.base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_NONE);
} }
if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) { if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) {
drm_object_attach_property(&radeon_connector->base.base, drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.audio_property, rdev->mode_info.audio_property,
RADEON_AUDIO_AUTO); RADEON_AUDIO_AUTO);
} }
if (ASIC_IS_AVIVO(rdev)) {
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.dither_property,
RADEON_FMT_DITHER_DISABLE);
}
connector->interlace_allowed = true; connector->interlace_allowed = true;
/* in theory with a DP to VGA converter... */ /* in theory with a DP to VGA converter... */
connector->doublescan_allowed = false; connector->doublescan_allowed = false;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment