mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-05-12 02:06:00 +00:00
drm/radeon: Hide the HW cursor while it's out of bounds
Fixes hangs in that case under some circumstances. v2: * Only use non-0 x/yorigin if the cursor is (partially) outside of the top/left edge of the total surface with AVIVO/DCE Bugzilla: https://bugzilla.suse.com/show_bug.cgi?id=1000433 Cc: stable@vger.kernel.org Signed-off-by: Michel Dänzer <michel.daenzer@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> (v1) Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
4349bd775c
commit
6b16cf7785
2 changed files with 43 additions and 18 deletions
|
@ -90,6 +90,9 @@ static void radeon_show_cursor(struct drm_crtc *crtc)
|
||||||
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
|
||||||
struct radeon_device *rdev = crtc->dev->dev_private;
|
struct radeon_device *rdev = crtc->dev->dev_private;
|
||||||
|
|
||||||
|
if (radeon_crtc->cursor_out_of_bounds)
|
||||||
|
return;
|
||||||
|
|
||||||
if (ASIC_IS_DCE4(rdev)) {
|
if (ASIC_IS_DCE4(rdev)) {
|
||||||
WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
|
WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
|
||||||
upper_32_bits(radeon_crtc->cursor_addr));
|
upper_32_bits(radeon_crtc->cursor_addr));
|
||||||
|
@ -151,16 +154,17 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y)
|
||||||
x += crtc->x;
|
x += crtc->x;
|
||||||
y += crtc->y;
|
y += crtc->y;
|
||||||
}
|
}
|
||||||
DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
|
|
||||||
|
|
||||||
if (x < 0) {
|
if (x < 0)
|
||||||
xorigin = min(-x, radeon_crtc->max_cursor_width - 1);
|
xorigin = min(-x, radeon_crtc->max_cursor_width - 1);
|
||||||
x = 0;
|
if (y < 0)
|
||||||
}
|
|
||||||
if (y < 0) {
|
|
||||||
yorigin = min(-y, radeon_crtc->max_cursor_height - 1);
|
yorigin = min(-y, radeon_crtc->max_cursor_height - 1);
|
||||||
y = 0;
|
|
||||||
|
if (!ASIC_IS_AVIVO(rdev)) {
|
||||||
|
x += crtc->x;
|
||||||
|
y += crtc->y;
|
||||||
}
|
}
|
||||||
|
DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
|
||||||
|
|
||||||
/* fixed on DCE6 and newer */
|
/* fixed on DCE6 and newer */
|
||||||
if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) {
|
if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) {
|
||||||
|
@ -183,27 +187,31 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y)
|
||||||
if (i > 1) {
|
if (i > 1) {
|
||||||
int cursor_end, frame_end;
|
int cursor_end, frame_end;
|
||||||
|
|
||||||
cursor_end = x - xorigin + w;
|
cursor_end = x + w;
|
||||||
frame_end = crtc->x + crtc->mode.crtc_hdisplay;
|
frame_end = crtc->x + crtc->mode.crtc_hdisplay;
|
||||||
if (cursor_end >= frame_end) {
|
if (cursor_end >= frame_end) {
|
||||||
w = w - (cursor_end - frame_end);
|
w = w - (cursor_end - frame_end);
|
||||||
if (!(frame_end & 0x7f))
|
if (!(frame_end & 0x7f))
|
||||||
w--;
|
w--;
|
||||||
} else {
|
} else if (cursor_end <= 0) {
|
||||||
if (!(cursor_end & 0x7f))
|
goto out_of_bounds;
|
||||||
w--;
|
} else if (!(cursor_end & 0x7f)) {
|
||||||
|
w--;
|
||||||
}
|
}
|
||||||
if (w <= 0) {
|
if (w <= 0) {
|
||||||
w = 1;
|
goto out_of_bounds;
|
||||||
cursor_end = x - xorigin + w;
|
|
||||||
if (!(cursor_end & 0x7f)) {
|
|
||||||
x--;
|
|
||||||
WARN_ON_ONCE(x < 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (x <= (crtc->x - w) || y <= (crtc->y - radeon_crtc->cursor_height) ||
|
||||||
|
x >= (crtc->x + crtc->mode.crtc_hdisplay) ||
|
||||||
|
y >= (crtc->y + crtc->mode.crtc_vdisplay))
|
||||||
|
goto out_of_bounds;
|
||||||
|
|
||||||
|
x += xorigin;
|
||||||
|
y += yorigin;
|
||||||
|
|
||||||
if (ASIC_IS_DCE4(rdev)) {
|
if (ASIC_IS_DCE4(rdev)) {
|
||||||
WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, (x << 16) | y);
|
WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, (x << 16) | y);
|
||||||
WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
|
WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
|
||||||
|
@ -215,6 +223,9 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y)
|
||||||
WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
|
WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
|
||||||
((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
|
((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
|
||||||
} else {
|
} else {
|
||||||
|
x -= crtc->x;
|
||||||
|
y -= crtc->y;
|
||||||
|
|
||||||
if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
|
if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
|
||||||
y *= 2;
|
y *= 2;
|
||||||
|
|
||||||
|
@ -232,6 +243,19 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y)
|
||||||
yorigin * 256);
|
yorigin * 256);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (radeon_crtc->cursor_out_of_bounds) {
|
||||||
|
radeon_crtc->cursor_out_of_bounds = false;
|
||||||
|
if (radeon_crtc->cursor_bo)
|
||||||
|
radeon_show_cursor(crtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out_of_bounds:
|
||||||
|
if (!radeon_crtc->cursor_out_of_bounds) {
|
||||||
|
radeon_hide_cursor(crtc);
|
||||||
|
radeon_crtc->cursor_out_of_bounds = true;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,12 +332,12 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc,
|
||||||
x = radeon_crtc->cursor_x + radeon_crtc->cursor_hot_x - hot_x;
|
x = radeon_crtc->cursor_x + radeon_crtc->cursor_hot_x - hot_x;
|
||||||
y = radeon_crtc->cursor_y + radeon_crtc->cursor_hot_y - hot_y;
|
y = radeon_crtc->cursor_y + radeon_crtc->cursor_hot_y - hot_y;
|
||||||
|
|
||||||
radeon_cursor_move_locked(crtc, x, y);
|
|
||||||
|
|
||||||
radeon_crtc->cursor_width = width;
|
radeon_crtc->cursor_width = width;
|
||||||
radeon_crtc->cursor_height = height;
|
radeon_crtc->cursor_height = height;
|
||||||
radeon_crtc->cursor_hot_x = hot_x;
|
radeon_crtc->cursor_hot_x = hot_x;
|
||||||
radeon_crtc->cursor_hot_y = hot_y;
|
radeon_crtc->cursor_hot_y = hot_y;
|
||||||
|
|
||||||
|
radeon_cursor_move_locked(crtc, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
radeon_show_cursor(crtc);
|
radeon_show_cursor(crtc);
|
||||||
|
|
|
@ -330,6 +330,7 @@ struct radeon_crtc {
|
||||||
u16 lut_r[256], lut_g[256], lut_b[256];
|
u16 lut_r[256], lut_g[256], lut_b[256];
|
||||||
bool enabled;
|
bool enabled;
|
||||||
bool can_tile;
|
bool can_tile;
|
||||||
|
bool cursor_out_of_bounds;
|
||||||
uint32_t crtc_offset;
|
uint32_t crtc_offset;
|
||||||
struct drm_gem_object *cursor_bo;
|
struct drm_gem_object *cursor_bo;
|
||||||
uint64_t cursor_addr;
|
uint64_t cursor_addr;
|
||||||
|
|
Loading…
Add table
Reference in a new issue