Some of the watermark registers need to be programmed prior to enabling the display. Doing this in the set base callback means the watermark registers can be updated at arbitray times when the display offset is changed which can lead to display problems.
Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_crtc.c | 13 +++++++------ drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 6 +++--- 2 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index b9d3b43..dd11e00 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1278,9 +1278,6 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, radeon_bo_unreserve(rbo); }
- /* Bytes per pixel may have changed */ - radeon_bandwidth_update(rdev); - return 0; }
@@ -1447,9 +1444,6 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, radeon_bo_unreserve(rbo); }
- /* Bytes per pixel may have changed */ - radeon_bandwidth_update(rdev); - return 0; }
@@ -1897,6 +1891,11 @@ static void atombios_crtc_prepare(struct drm_crtc *crtc)
static void atombios_crtc_commit(struct drm_crtc *crtc) { + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + + /* set up watermarks before enabling the display */ + radeon_bandwidth_update(rdev); atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON); atombios_lock_crtc(crtc, ATOM_DISABLE); } @@ -1910,6 +1909,8 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) int i;
atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + /* set up watermarks when the display is off */ + radeon_bandwidth_update(rdev); if (ASIC_IS_DCE6(rdev)) atombios_powergate_crtc(crtc, ATOM_ENABLE);
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 7cb178a..dbc5b773 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -537,9 +537,6 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc, radeon_bo_unreserve(rbo); }
- /* Bytes per pixel may have changed */ - radeon_bandwidth_update(rdev); - return 0; }
@@ -1045,8 +1042,11 @@ static void radeon_crtc_prepare(struct drm_crtc *crtc) static void radeon_crtc_commit(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; struct drm_crtc *crtci;
+ /* set up watermarks before enabling the display */ + radeon_bandwidth_update(rdev); /* * Reenable the CRTCs that should be running. */
We need to allocate line buffer to each display when setting up the watermarks. Failure to do so can lead to a blank screen. This fixes blank screen problems on dce4.1/5 asics.
Based on an initial fix from: Jay Cornwall jay.cornwall@amd.com
Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/evergreen.c | 25 +++++++++++++++++++++---- drivers/gpu/drm/radeon/evergreend.h | 4 ++++ 2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 2ca9f13..1832136 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1812,7 +1812,8 @@ static u32 evergreen_line_buffer_adjust(struct radeon_device *rdev, struct drm_display_mode *mode, struct drm_display_mode *other_mode) { - u32 tmp; + u32 tmp, buffer_alloc, i; + u32 pipe_offset = radeon_crtc->crtc_id * 0x20; /* * Line Buffer Setup * There are 3 line buffers, each one shared by 2 display controllers. @@ -1835,18 +1836,34 @@ static u32 evergreen_line_buffer_adjust(struct radeon_device *rdev, * non-linked crtcs for maximum line buffer allocation. */ if (radeon_crtc->base.enabled && mode) { - if (other_mode) + if (other_mode) { tmp = 0; /* 1/2 */ - else + buffer_alloc = 1; + } else { tmp = 2; /* whole */ - } else + buffer_alloc = 2; + } + } else { tmp = 0; + buffer_alloc = 0; + }
/* second controller of the pair uses second half of the lb */ if (radeon_crtc->crtc_id % 2) tmp += 4; WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset, tmp);
+ if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + WREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset, + DMIF_BUFFERS_ALLOCATED(buffer_alloc)); + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset) & + DMIF_BUFFERS_ALLOCATED_COMPLETED) + break; + udelay(1); + } + } + if (radeon_crtc->base.enabled && mode) { switch (tmp) { case 0: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 430997a..8768fd6 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -1160,6 +1160,10 @@ # define LATENCY_LOW_WATERMARK(x) ((x) << 0) # define LATENCY_HIGH_WATERMARK(x) ((x) << 16)
+#define PIPE0_DMIF_BUFFER_CONTROL 0x0ca0 +# define DMIF_BUFFERS_ALLOCATED(x) ((x) << 0) +# define DMIF_BUFFERS_ALLOCATED_COMPLETED (1 << 4) + #define IH_RB_CNTL 0x3e00 # define IH_RB_ENABLE (1 << 0) # define IH_IB_SIZE(x) ((x) << 1) /* log2 */
We need to allocate line buffer to each display when setting up the watermarks. Failure to do so can lead to a blank screen. This fixes blank screen problems on dce6 asics.
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=64850
Based on an initial fix from: Jay Cornwall jay.cornwall@amd.com
Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/si.c | 23 +++++++++++++++++++---- drivers/gpu/drm/radeon/sid.h | 4 ++++ 2 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 0b4e979..89393ed 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -1711,7 +1711,8 @@ static u32 dce6_line_buffer_adjust(struct radeon_device *rdev, struct drm_display_mode *mode, struct drm_display_mode *other_mode) { - u32 tmp; + u32 tmp, buffer_alloc, i; + u32 pipe_offset = radeon_crtc->crtc_id * 0x20; /* * Line Buffer Setup * There are 3 line buffers, each one shared by 2 display controllers. @@ -1726,16 +1727,30 @@ static u32 dce6_line_buffer_adjust(struct radeon_device *rdev, * non-linked crtcs for maximum line buffer allocation. */ if (radeon_crtc->base.enabled && mode) { - if (other_mode) + if (other_mode) { tmp = 0; /* 1/2 */ - else + buffer_alloc = 1; + } else { tmp = 2; /* whole */ - } else + buffer_alloc = 2; + } + } else { tmp = 0; + buffer_alloc = 0; + }
WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset, DC_LB_MEMORY_CONFIG(tmp));
+ WREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset, + DMIF_BUFFERS_ALLOCATED(buffer_alloc)); + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset) & + DMIF_BUFFERS_ALLOCATED_COMPLETED) + break; + udelay(1); + } + if (radeon_crtc->base.enabled && mode) { switch (tmp) { case 0: diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 91dae16..52d2ab6 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -282,6 +282,10 @@
#define DMIF_ADDR_CALC 0xC00
+#define PIPE0_DMIF_BUFFER_CONTROL 0x0ca0 +# define DMIF_BUFFERS_ALLOCATED(x) ((x) << 0) +# define DMIF_BUFFERS_ALLOCATED_COMPLETED (1 << 4) + #define SRBM_STATUS 0xE50 #define GRBM_RQ_PENDING (1 << 5) #define VMC_BUSY (1 << 8)
We need to allocate line buffer to each display when setting up the watermarks. Failure to do so can lead to a blank screen. This fixes blank screen problems on dce8 asics.
Based on an initial fix from: Jay Cornwall jay.cornwall@amd.com
Signed-off-by: Alex Deucher alexander.deucher@amd.com Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/cik.c | 29 ++++++++++++++++++++++------- drivers/gpu/drm/radeon/cikd.h | 4 ++++ 2 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 582f8e4..1942571 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -7367,8 +7367,8 @@ static u32 dce8_line_buffer_adjust(struct radeon_device *rdev, struct radeon_crtc *radeon_crtc, struct drm_display_mode *mode) { - u32 tmp; - + u32 tmp, buffer_alloc, i; + u32 pipe_offset = radeon_crtc->crtc_id * 0x20; /* * Line Buffer Setup * There are 6 line buffers, one for each display controllers. @@ -7378,22 +7378,37 @@ static u32 dce8_line_buffer_adjust(struct radeon_device *rdev, * them using the stereo blender. */ if (radeon_crtc->base.enabled && mode) { - if (mode->crtc_hdisplay < 1920) + if (mode->crtc_hdisplay < 1920) { tmp = 1; - else if (mode->crtc_hdisplay < 2560) + buffer_alloc = 2; + } else if (mode->crtc_hdisplay < 2560) { tmp = 2; - else if (mode->crtc_hdisplay < 4096) + buffer_alloc = 2; + } else if (mode->crtc_hdisplay < 4096) { tmp = 0; - else { + buffer_alloc = (rdev->flags & RADEON_IS_IGP) ? 2 : 4; + } else { DRM_DEBUG_KMS("Mode too big for LB!\n"); tmp = 0; + buffer_alloc = (rdev->flags & RADEON_IS_IGP) ? 2 : 4; } - } else + } else { tmp = 1; + buffer_alloc = 0; + }
WREG32(LB_MEMORY_CTRL + radeon_crtc->crtc_offset, LB_MEMORY_CONFIG(tmp) | LB_MEMORY_SIZE(0x6B0));
+ WREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset, + DMIF_BUFFERS_ALLOCATED(buffer_alloc)); + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset) & + DMIF_BUFFERS_ALLOCATED_COMPLETED) + break; + udelay(1); + } + if (radeon_crtc->base.enabled && mode) { switch (tmp) { case 0: diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index 6a92f49..203d2a0 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h @@ -393,6 +393,10 @@
#define DMIF_ADDR_CALC 0xC00
+#define PIPE0_DMIF_BUFFER_CONTROL 0x0ca0 +# define DMIF_BUFFERS_ALLOCATED(x) ((x) << 0) +# define DMIF_BUFFERS_ALLOCATED_COMPLETED (1 << 4) + #define SRBM_GFX_CNTL 0xE44 #define PIPEID(x) ((x) << 0) #define MEID(x) ((x) << 2)
dri-devel@lists.freedesktop.org