drm/radeon: implement output csc property for DCE5+

Implement the property for DCE5+ asics.  Older asics
require a slightly more complex process.

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

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Alex Deucher 2015-02-23 10:59:36 -05:00
parent 67ba31d352
commit 643b1f5629
4 changed files with 61 additions and 1 deletions

View File

@ -2069,6 +2069,12 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
radeon_crtc->connector = NULL; radeon_crtc->connector = NULL;
return false; return false;
} }
if (radeon_crtc->encoder) {
struct radeon_encoder *radeon_encoder =
to_radeon_encoder(radeon_crtc->encoder);
radeon_crtc->output_csc = radeon_encoder->output_csc;
}
if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode)) if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
return false; return false;
if (!atombios_crtc_prepare_pll(crtc, adjusted_mode)) if (!atombios_crtc_prepare_pll(crtc, adjusted_mode))

View File

@ -725,6 +725,30 @@ 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 == rdev->mode_info.output_csc_property) {
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));
}
if (radeon_encoder->output_csc == val)
return 0;
radeon_encoder->output_csc = val;
if (connector->encoder->crtc) {
struct drm_crtc *crtc = connector->encoder->crtc;
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
radeon_crtc->output_csc = radeon_encoder->output_csc;
(*crtc_funcs->load_lut)(crtc);
}
}
return 0; return 0;
} }
@ -1872,6 +1896,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,
dev->mode_config.scaling_mode_property, dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_NONE); DRM_MODE_SCALE_NONE);
if (ASIC_IS_DCE5(rdev))
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.output_csc_property,
RADEON_OUTPUT_CSC_BYPASS);
break; break;
case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_DVID: case DRM_MODE_CONNECTOR_DVID:
@ -1904,6 +1932,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.audio_property, rdev->mode_info.audio_property,
RADEON_AUDIO_AUTO); RADEON_AUDIO_AUTO);
if (ASIC_IS_DCE5(rdev))
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.output_csc_property,
RADEON_OUTPUT_CSC_BYPASS);
subpixel_order = SubPixelHorizontalRGB; subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = true; connector->interlace_allowed = true;
@ -1950,6 +1982,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,
dev->mode_config.scaling_mode_property, dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_NONE); DRM_MODE_SCALE_NONE);
if (ASIC_IS_DCE5(rdev))
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.output_csc_property,
RADEON_OUTPUT_CSC_BYPASS);
/* 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;
@ -1972,6 +2008,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,
dev->mode_config.scaling_mode_property, dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_NONE); DRM_MODE_SCALE_NONE);
if (ASIC_IS_DCE5(rdev))
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.output_csc_property,
RADEON_OUTPUT_CSC_BYPASS);
/* 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;
@ -2023,6 +2063,10 @@ radeon_add_atom_connector(struct drm_device *dev,
rdev->mode_info.load_detect_property, rdev->mode_info.load_detect_property,
1); 1);
} }
if (ASIC_IS_DCE5(rdev))
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.output_csc_property,
RADEON_OUTPUT_CSC_BYPASS);
connector->interlace_allowed = true; connector->interlace_allowed = true;
if (connector_type == DRM_MODE_CONNECTOR_DVII) if (connector_type == DRM_MODE_CONNECTOR_DVII)
connector->doublescan_allowed = true; connector->doublescan_allowed = true;
@ -2068,6 +2112,10 @@ radeon_add_atom_connector(struct drm_device *dev,
rdev->mode_info.audio_property, rdev->mode_info.audio_property,
RADEON_AUDIO_AUTO); RADEON_AUDIO_AUTO);
} }
if (ASIC_IS_DCE5(rdev))
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.output_csc_property,
RADEON_OUTPUT_CSC_BYPASS);
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)
@ -2116,6 +2164,10 @@ radeon_add_atom_connector(struct drm_device *dev,
rdev->mode_info.audio_property, rdev->mode_info.audio_property,
RADEON_AUDIO_AUTO); RADEON_AUDIO_AUTO);
} }
if (ASIC_IS_DCE5(rdev))
drm_object_attach_property(&radeon_connector->base.base,
rdev->mode_info.output_csc_property,
RADEON_OUTPUT_CSC_BYPASS);
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;

View File

@ -154,7 +154,7 @@ static void dce5_crtc_load_lut(struct drm_crtc *crtc)
(NI_GRPH_REGAMMA_MODE(NI_REGAMMA_BYPASS) | (NI_GRPH_REGAMMA_MODE(NI_REGAMMA_BYPASS) |
NI_OVL_REGAMMA_MODE(NI_REGAMMA_BYPASS))); NI_OVL_REGAMMA_MODE(NI_REGAMMA_BYPASS)));
WREG32(NI_OUTPUT_CSC_CONTROL + radeon_crtc->crtc_offset, WREG32(NI_OUTPUT_CSC_CONTROL + radeon_crtc->crtc_offset,
(NI_OUTPUT_CSC_GRPH_MODE(NI_OUTPUT_CSC_BYPASS) | (NI_OUTPUT_CSC_GRPH_MODE(radeon_crtc->output_csc) |
NI_OUTPUT_CSC_OVL_MODE(NI_OUTPUT_CSC_BYPASS))); NI_OUTPUT_CSC_OVL_MODE(NI_OUTPUT_CSC_BYPASS)));
/* XXX match this to the depth of the crtc fmt block, move to modeset? */ /* XXX match this to the depth of the crtc fmt block, move to modeset? */
WREG32(0x6940 + radeon_crtc->crtc_offset, 0); WREG32(0x6940 + radeon_crtc->crtc_offset, 0);

View File

@ -366,6 +366,7 @@ struct radeon_crtc {
u32 wm_low; u32 wm_low;
u32 wm_high; u32 wm_high;
struct drm_display_mode hw_mode; struct drm_display_mode hw_mode;
enum radeon_output_csc output_csc;
}; };
struct radeon_encoder_primary_dac { struct radeon_encoder_primary_dac {
@ -459,6 +460,7 @@ struct radeon_encoder {
bool is_ext_encoder; bool is_ext_encoder;
u16 caps; u16 caps;
struct radeon_audio_funcs *audio; struct radeon_audio_funcs *audio;
enum radeon_output_csc output_csc;
}; };
struct radeon_connector_atom_dig { struct radeon_connector_atom_dig {