diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-09-23 18:22:11 +0200 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-11-01 17:43:12 +0100 |
commit | 134b480f4b92654b9590fad6c9374c7dc6722375 (patch) | |
tree | b5d423cad7200e8efd2e23d08d76c5df6a348bd7 /drivers/gpu/drm/radeon/evergreen.c | |
parent | drm/sysfs: Do not drop device reference twice (diff) | |
download | linux-134b480f4b92654b9590fad6c9374c7dc6722375.tar.xz linux-134b480f4b92654b9590fad6c9374c7dc6722375.zip |
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/evergreen.c')
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen.c | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 555164e270a7..feedfcc6554b 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1193,6 +1193,59 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev) } } +void dce4_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/eDP 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_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE | + FMT_SPATIAL_DITHER_EN); + else + tmp |= FMT_TRUNCATE_EN; + break; + case 8: + if (dither) + /* XXX sort out optimal dither settings */ + tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE | + FMT_RGB_RANDOM_ENABLE | + 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); +} + static bool dce4_is_in_vblank(struct radeon_device *rdev, int crtc) { if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK) |