diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-09-23 20:22:11 +0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-11-01 20:43:12 +0400 |
commit | 134b480f4b92654b9590fad6c9374c7dc6722375 (patch) | |
tree | b5d423cad7200e8efd2e23d08d76c5df6a348bd7 /drivers/gpu/drm/radeon/r600.c | |
parent | 9d6104e0174b130ed864571b31811c3fd09fd611 (diff) | |
download | linux-134b480f4b92654b9590fad6c9374c7dc6722375.tar.xz |
drm/radeon: Add support for programming the FMT blocks
The FMT blocks control how data is sent from the backend
of the display pipe to to monitor. Proper set up of the
FMT blocks are required for 30bpp formats. Additionally,
dithering can be enabled on for better display with 18 and
24bpp displays. The exception is LVDS/eDP which atom
takes care of in the SelectCRTC_Source table. For now
just enable truncation until we test dithering more.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/r600.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 2a1b1876b431..bdf4b80202d5 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -124,6 +124,56 @@ int r600_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) return 0; } +void dce3_program_fmt(struct drm_encoder *encoder) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); + int bpc = 0; + u32 tmp = 0; + bool dither = false; + + if (connector) + bpc = radeon_get_monitor_bpc(connector); + + /* LVDS FMT is set up by atom */ + if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT) + return; + + /* not needed for analog */ + if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1) || + (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2)) + return; + + if (bpc == 0) + return; + + switch (bpc) { + case 6: + if (dither) + /* XXX sort out optimal dither settings */ + tmp |= FMT_SPATIAL_DITHER_EN; + else + tmp |= FMT_TRUNCATE_EN; + break; + case 8: + if (dither) + /* XXX sort out optimal dither settings */ + tmp |= (FMT_SPATIAL_DITHER_EN | FMT_SPATIAL_DITHER_DEPTH); + else + tmp |= (FMT_TRUNCATE_EN | FMT_TRUNCATE_DEPTH); + break; + case 10: + default: + /* not needed */ + break; + } + + WREG32(FMT_BIT_DEPTH_CONTROL + radeon_crtc->crtc_offset, tmp); +} + /* get temperature in millidegrees */ int rv6xx_get_temp(struct radeon_device *rdev) { |