1771fe6b9SJerome Glisse /*
2771fe6b9SJerome Glisse * Copyright 2007-8 Advanced Micro Devices, Inc.
3771fe6b9SJerome Glisse * Copyright 2008 Red Hat Inc.
4771fe6b9SJerome Glisse *
5771fe6b9SJerome Glisse * Permission is hereby granted, free of charge, to any person obtaining a
6771fe6b9SJerome Glisse * copy of this software and associated documentation files (the "Software"),
7771fe6b9SJerome Glisse * to deal in the Software without restriction, including without limitation
8771fe6b9SJerome Glisse * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9771fe6b9SJerome Glisse * and/or sell copies of the Software, and to permit persons to whom the
10771fe6b9SJerome Glisse * Software is furnished to do so, subject to the following conditions:
11771fe6b9SJerome Glisse *
12771fe6b9SJerome Glisse * The above copyright notice and this permission notice shall be included in
13771fe6b9SJerome Glisse * all copies or substantial portions of the Software.
14771fe6b9SJerome Glisse *
15771fe6b9SJerome Glisse * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16771fe6b9SJerome Glisse * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17771fe6b9SJerome Glisse * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18771fe6b9SJerome Glisse * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19771fe6b9SJerome Glisse * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20771fe6b9SJerome Glisse * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21771fe6b9SJerome Glisse * OTHER DEALINGS IN THE SOFTWARE.
22771fe6b9SJerome Glisse *
23771fe6b9SJerome Glisse * Authors: Dave Airlie
24771fe6b9SJerome Glisse * Alex Deucher
25771fe6b9SJerome Glisse */
26f9183127SSam Ravnborg
27f9183127SSam Ravnborg #include <drm/drm_device.h>
28760285e7SDavid Howells #include <drm/radeon_drm.h>
29f9183127SSam Ravnborg
30771fe6b9SJerome Glisse #include "radeon.h"
31771fe6b9SJerome Glisse
radeon_lock_cursor(struct drm_crtc * crtc,bool lock)32771fe6b9SJerome Glisse static void radeon_lock_cursor(struct drm_crtc *crtc, bool lock)
33771fe6b9SJerome Glisse {
34771fe6b9SJerome Glisse struct radeon_device *rdev = crtc->dev->dev_private;
35771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
36771fe6b9SJerome Glisse uint32_t cur_lock;
37771fe6b9SJerome Glisse
38bcc1c2a1SAlex Deucher if (ASIC_IS_DCE4(rdev)) {
39bcc1c2a1SAlex Deucher cur_lock = RREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset);
40bcc1c2a1SAlex Deucher if (lock)
41bcc1c2a1SAlex Deucher cur_lock |= EVERGREEN_CURSOR_UPDATE_LOCK;
42bcc1c2a1SAlex Deucher else
43bcc1c2a1SAlex Deucher cur_lock &= ~EVERGREEN_CURSOR_UPDATE_LOCK;
44bcc1c2a1SAlex Deucher WREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock);
45bcc1c2a1SAlex Deucher } else if (ASIC_IS_AVIVO(rdev)) {
46771fe6b9SJerome Glisse cur_lock = RREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset);
47771fe6b9SJerome Glisse if (lock)
48771fe6b9SJerome Glisse cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK;
49771fe6b9SJerome Glisse else
50771fe6b9SJerome Glisse cur_lock &= ~AVIVO_D1CURSOR_UPDATE_LOCK;
51771fe6b9SJerome Glisse WREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock);
52771fe6b9SJerome Glisse } else {
53771fe6b9SJerome Glisse cur_lock = RREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset);
54771fe6b9SJerome Glisse if (lock)
55771fe6b9SJerome Glisse cur_lock |= RADEON_CUR_LOCK;
56771fe6b9SJerome Glisse else
57771fe6b9SJerome Glisse cur_lock &= ~RADEON_CUR_LOCK;
58771fe6b9SJerome Glisse WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, cur_lock);
59771fe6b9SJerome Glisse }
60771fe6b9SJerome Glisse }
61771fe6b9SJerome Glisse
radeon_hide_cursor(struct drm_crtc * crtc)62771fe6b9SJerome Glisse static void radeon_hide_cursor(struct drm_crtc *crtc)
63771fe6b9SJerome Glisse {
64771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
65771fe6b9SJerome Glisse struct radeon_device *rdev = crtc->dev->dev_private;
66771fe6b9SJerome Glisse
67bcc1c2a1SAlex Deucher if (ASIC_IS_DCE4(rdev)) {
682ef9bdfeSDaniel Vetter WREG32_IDX(EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset,
692ef9bdfeSDaniel Vetter EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) |
70f4254a2bSAlex Deucher EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2));
71bcc1c2a1SAlex Deucher } else if (ASIC_IS_AVIVO(rdev)) {
722ef9bdfeSDaniel Vetter WREG32_IDX(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset,
732ef9bdfeSDaniel Vetter (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
74771fe6b9SJerome Glisse } else {
752ef9bdfeSDaniel Vetter u32 reg;
76771fe6b9SJerome Glisse switch (radeon_crtc->crtc_id) {
77771fe6b9SJerome Glisse case 0:
782ef9bdfeSDaniel Vetter reg = RADEON_CRTC_GEN_CNTL;
79771fe6b9SJerome Glisse break;
80771fe6b9SJerome Glisse case 1:
812ef9bdfeSDaniel Vetter reg = RADEON_CRTC2_GEN_CNTL;
82771fe6b9SJerome Glisse break;
83771fe6b9SJerome Glisse default:
84771fe6b9SJerome Glisse return;
85771fe6b9SJerome Glisse }
862ef9bdfeSDaniel Vetter WREG32_IDX(reg, RREG32_IDX(reg) & ~RADEON_CRTC_CUR_EN);
87771fe6b9SJerome Glisse }
88771fe6b9SJerome Glisse }
89771fe6b9SJerome Glisse
radeon_show_cursor(struct drm_crtc * crtc)90771fe6b9SJerome Glisse static void radeon_show_cursor(struct drm_crtc *crtc)
91771fe6b9SJerome Glisse {
92771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
93771fe6b9SJerome Glisse struct radeon_device *rdev = crtc->dev->dev_private;
94771fe6b9SJerome Glisse
956b16cf77SMichel Dänzer if (radeon_crtc->cursor_out_of_bounds)
966b16cf77SMichel Dänzer return;
976b16cf77SMichel Dänzer
98bcc1c2a1SAlex Deucher if (ASIC_IS_DCE4(rdev)) {
998991668aSMichel Dänzer WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
1008991668aSMichel Dänzer upper_32_bits(radeon_crtc->cursor_addr));
1018991668aSMichel Dänzer WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
1028991668aSMichel Dänzer lower_32_bits(radeon_crtc->cursor_addr));
103bcc1c2a1SAlex Deucher WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset);
104bcc1c2a1SAlex Deucher WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN |
105f4254a2bSAlex Deucher EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) |
106f4254a2bSAlex Deucher EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2));
107bcc1c2a1SAlex Deucher } else if (ASIC_IS_AVIVO(rdev)) {
1088991668aSMichel Dänzer if (rdev->family >= CHIP_RV770) {
1098991668aSMichel Dänzer if (radeon_crtc->crtc_id)
1108991668aSMichel Dänzer WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH,
1118991668aSMichel Dänzer upper_32_bits(radeon_crtc->cursor_addr));
1128991668aSMichel Dänzer else
1138991668aSMichel Dänzer WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH,
1148991668aSMichel Dänzer upper_32_bits(radeon_crtc->cursor_addr));
1158991668aSMichel Dänzer }
1168991668aSMichel Dänzer
1178991668aSMichel Dänzer WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
1188991668aSMichel Dänzer lower_32_bits(radeon_crtc->cursor_addr));
119771fe6b9SJerome Glisse WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
120771fe6b9SJerome Glisse WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN |
121771fe6b9SJerome Glisse (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
122771fe6b9SJerome Glisse } else {
1238991668aSMichel Dänzer /* offset is from DISP(2)_BASE_ADDRESS */
1248991668aSMichel Dänzer WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset,
1258991668aSMichel Dänzer radeon_crtc->cursor_addr - radeon_crtc->legacy_display_base_addr);
1268991668aSMichel Dänzer
127771fe6b9SJerome Glisse switch (radeon_crtc->crtc_id) {
128771fe6b9SJerome Glisse case 0:
129771fe6b9SJerome Glisse WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
130771fe6b9SJerome Glisse break;
131771fe6b9SJerome Glisse case 1:
132771fe6b9SJerome Glisse WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
133771fe6b9SJerome Glisse break;
134771fe6b9SJerome Glisse default:
135771fe6b9SJerome Glisse return;
136771fe6b9SJerome Glisse }
137771fe6b9SJerome Glisse
138771fe6b9SJerome Glisse WREG32_P(RADEON_MM_DATA, (RADEON_CRTC_CUR_EN |
139771fe6b9SJerome Glisse (RADEON_CRTC_CUR_MODE_24BPP << RADEON_CRTC_CUR_MODE_SHIFT)),
140771fe6b9SJerome Glisse ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK));
141771fe6b9SJerome Glisse }
142771fe6b9SJerome Glisse }
143771fe6b9SJerome Glisse
radeon_cursor_move_locked(struct drm_crtc * crtc,int x,int y)1443feba08dSMichel Dänzer static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y)
1453feba08dSMichel Dänzer {
1463feba08dSMichel Dänzer struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
1473feba08dSMichel Dänzer struct radeon_device *rdev = crtc->dev->dev_private;
1483feba08dSMichel Dänzer int xorigin = 0, yorigin = 0;
1493feba08dSMichel Dänzer int w = radeon_crtc->cursor_width;
1503feba08dSMichel Dänzer
1514349bd77SMichel Dänzer radeon_crtc->cursor_x = x;
1524349bd77SMichel Dänzer radeon_crtc->cursor_y = y;
1534349bd77SMichel Dänzer
1543feba08dSMichel Dänzer if (ASIC_IS_AVIVO(rdev)) {
1553feba08dSMichel Dänzer /* avivo cursor are offset into the total surface */
1563feba08dSMichel Dänzer x += crtc->x;
1573feba08dSMichel Dänzer y += crtc->y;
1583feba08dSMichel Dänzer }
1593feba08dSMichel Dänzer
1606b16cf77SMichel Dänzer if (x < 0)
1613feba08dSMichel Dänzer xorigin = min(-x, radeon_crtc->max_cursor_width - 1);
1626b16cf77SMichel Dänzer if (y < 0)
1633feba08dSMichel Dänzer yorigin = min(-y, radeon_crtc->max_cursor_height - 1);
1646b16cf77SMichel Dänzer
1656b16cf77SMichel Dänzer if (!ASIC_IS_AVIVO(rdev)) {
1666b16cf77SMichel Dänzer x += crtc->x;
1676b16cf77SMichel Dänzer y += crtc->y;
1683feba08dSMichel Dänzer }
1696b16cf77SMichel Dänzer DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
1703feba08dSMichel Dänzer
1713feba08dSMichel Dänzer /* fixed on DCE6 and newer */
1723feba08dSMichel Dänzer if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) {
1733feba08dSMichel Dänzer int i = 0;
1743feba08dSMichel Dänzer struct drm_crtc *crtc_p;
1753feba08dSMichel Dänzer
1763feba08dSMichel Dänzer /*
1773feba08dSMichel Dänzer * avivo cursor image can't end on 128 pixel boundary or
1783feba08dSMichel Dänzer * go past the end of the frame if both crtcs are enabled
1793feba08dSMichel Dänzer *
1803feba08dSMichel Dänzer * NOTE: It is safe to access crtc->enabled of other crtcs
1813feba08dSMichel Dänzer * without holding either the mode_config lock or the other
1823feba08dSMichel Dänzer * crtc's lock as long as write access to this flag _always_
1833feba08dSMichel Dänzer * grabs all locks.
1843feba08dSMichel Dänzer */
1853feba08dSMichel Dänzer list_for_each_entry(crtc_p, &crtc->dev->mode_config.crtc_list, head) {
1863feba08dSMichel Dänzer if (crtc_p->enabled)
1873feba08dSMichel Dänzer i++;
1883feba08dSMichel Dänzer }
1893feba08dSMichel Dänzer if (i > 1) {
1903feba08dSMichel Dänzer int cursor_end, frame_end;
1913feba08dSMichel Dänzer
1926b16cf77SMichel Dänzer cursor_end = x + w;
1933feba08dSMichel Dänzer frame_end = crtc->x + crtc->mode.crtc_hdisplay;
1943feba08dSMichel Dänzer if (cursor_end >= frame_end) {
1953feba08dSMichel Dänzer w = w - (cursor_end - frame_end);
1963feba08dSMichel Dänzer if (!(frame_end & 0x7f))
1973feba08dSMichel Dänzer w--;
1986b16cf77SMichel Dänzer } else if (cursor_end <= 0) {
1996b16cf77SMichel Dänzer goto out_of_bounds;
2006b16cf77SMichel Dänzer } else if (!(cursor_end & 0x7f)) {
2013feba08dSMichel Dänzer w--;
2023feba08dSMichel Dänzer }
2033feba08dSMichel Dänzer if (w <= 0) {
2046b16cf77SMichel Dänzer goto out_of_bounds;
2053feba08dSMichel Dänzer }
2063feba08dSMichel Dänzer }
2073feba08dSMichel Dänzer }
2086b16cf77SMichel Dänzer
2096b16cf77SMichel Dänzer if (x <= (crtc->x - w) || y <= (crtc->y - radeon_crtc->cursor_height) ||
210d74c67ddSMichel Dänzer x >= (crtc->x + crtc->mode.hdisplay) ||
211d74c67ddSMichel Dänzer y >= (crtc->y + crtc->mode.vdisplay))
2126b16cf77SMichel Dänzer goto out_of_bounds;
2136b16cf77SMichel Dänzer
2146b16cf77SMichel Dänzer x += xorigin;
2156b16cf77SMichel Dänzer y += yorigin;
2163feba08dSMichel Dänzer
2173feba08dSMichel Dänzer if (ASIC_IS_DCE4(rdev)) {
2183feba08dSMichel Dänzer WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, (x << 16) | y);
2193feba08dSMichel Dänzer WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
2203feba08dSMichel Dänzer WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset,
2213feba08dSMichel Dänzer ((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
2223feba08dSMichel Dänzer } else if (ASIC_IS_AVIVO(rdev)) {
2233feba08dSMichel Dänzer WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, (x << 16) | y);
2243feba08dSMichel Dänzer WREG32(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
2253feba08dSMichel Dänzer WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
2263feba08dSMichel Dänzer ((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
2273feba08dSMichel Dänzer } else {
2286b16cf77SMichel Dänzer x -= crtc->x;
2296b16cf77SMichel Dänzer y -= crtc->y;
2306b16cf77SMichel Dänzer
2313feba08dSMichel Dänzer if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
2323feba08dSMichel Dänzer y *= 2;
2333feba08dSMichel Dänzer
2343feba08dSMichel Dänzer WREG32(RADEON_CUR_HORZ_VERT_OFF + radeon_crtc->crtc_offset,
2353feba08dSMichel Dänzer (RADEON_CUR_LOCK
2363feba08dSMichel Dänzer | (xorigin << 16)
2373feba08dSMichel Dänzer | yorigin));
2383feba08dSMichel Dänzer WREG32(RADEON_CUR_HORZ_VERT_POSN + radeon_crtc->crtc_offset,
2393feba08dSMichel Dänzer (RADEON_CUR_LOCK
2403feba08dSMichel Dänzer | (x << 16)
2413feba08dSMichel Dänzer | y));
2423feba08dSMichel Dänzer /* offset is from DISP(2)_BASE_ADDRESS */
243cd404af0SMichel Dänzer WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset,
244cd404af0SMichel Dänzer radeon_crtc->cursor_addr - radeon_crtc->legacy_display_base_addr +
245cd404af0SMichel Dänzer yorigin * 256);
2463feba08dSMichel Dänzer }
2473feba08dSMichel Dänzer
2486b16cf77SMichel Dänzer if (radeon_crtc->cursor_out_of_bounds) {
2496b16cf77SMichel Dänzer radeon_crtc->cursor_out_of_bounds = false;
2506b16cf77SMichel Dänzer if (radeon_crtc->cursor_bo)
2516b16cf77SMichel Dänzer radeon_show_cursor(crtc);
2526b16cf77SMichel Dänzer }
2536b16cf77SMichel Dänzer
2546b16cf77SMichel Dänzer return 0;
2556b16cf77SMichel Dänzer
2566b16cf77SMichel Dänzer out_of_bounds:
2576b16cf77SMichel Dänzer if (!radeon_crtc->cursor_out_of_bounds) {
2586b16cf77SMichel Dänzer radeon_hide_cursor(crtc);
2596b16cf77SMichel Dänzer radeon_crtc->cursor_out_of_bounds = true;
2606b16cf77SMichel Dänzer }
2613feba08dSMichel Dänzer return 0;
2623feba08dSMichel Dänzer }
2633feba08dSMichel Dänzer
radeon_crtc_cursor_move(struct drm_crtc * crtc,int x,int y)2643feba08dSMichel Dänzer int radeon_crtc_cursor_move(struct drm_crtc *crtc,
2653feba08dSMichel Dänzer int x, int y)
2663feba08dSMichel Dänzer {
2673feba08dSMichel Dänzer int ret;
2683feba08dSMichel Dänzer
2693feba08dSMichel Dänzer radeon_lock_cursor(crtc, true);
2703feba08dSMichel Dänzer ret = radeon_cursor_move_locked(crtc, x, y);
2713feba08dSMichel Dänzer radeon_lock_cursor(crtc, false);
2723feba08dSMichel Dänzer
2733feba08dSMichel Dänzer return ret;
2743feba08dSMichel Dänzer }
27578b1a601SMichel Dänzer
radeon_crtc_cursor_set2(struct drm_crtc * crtc,struct drm_file * file_priv,uint32_t handle,uint32_t width,uint32_t height,int32_t hot_x,int32_t hot_y)27678b1a601SMichel Dänzer int radeon_crtc_cursor_set2(struct drm_crtc *crtc,
277771fe6b9SJerome Glisse struct drm_file *file_priv,
278771fe6b9SJerome Glisse uint32_t handle,
279771fe6b9SJerome Glisse uint32_t width,
28078b1a601SMichel Dänzer uint32_t height,
28178b1a601SMichel Dänzer int32_t hot_x,
28278b1a601SMichel Dänzer int32_t hot_y)
283771fe6b9SJerome Glisse {
284771fe6b9SJerome Glisse struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
285cd404af0SMichel Dänzer struct radeon_device *rdev = crtc->dev->dev_private;
286771fe6b9SJerome Glisse struct drm_gem_object *obj;
287cd404af0SMichel Dänzer struct radeon_bo *robj;
288771fe6b9SJerome Glisse int ret;
289771fe6b9SJerome Glisse
290771fe6b9SJerome Glisse if (!handle) {
291771fe6b9SJerome Glisse /* turn off cursor */
292771fe6b9SJerome Glisse radeon_hide_cursor(crtc);
293771fe6b9SJerome Glisse obj = NULL;
294771fe6b9SJerome Glisse goto unpin;
295771fe6b9SJerome Glisse }
296771fe6b9SJerome Glisse
2979e05fa1dSAlex Deucher if ((width > radeon_crtc->max_cursor_width) ||
2989e05fa1dSAlex Deucher (height > radeon_crtc->max_cursor_height)) {
299771fe6b9SJerome Glisse DRM_ERROR("bad cursor width or height %d x %d\n", width, height);
300771fe6b9SJerome Glisse return -EINVAL;
301771fe6b9SJerome Glisse }
302771fe6b9SJerome Glisse
303a8ad0bd8SChris Wilson obj = drm_gem_object_lookup(file_priv, handle);
304771fe6b9SJerome Glisse if (!obj) {
305771fe6b9SJerome Glisse DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id);
306bf79cb91SChris Wilson return -ENOENT;
307771fe6b9SJerome Glisse }
308771fe6b9SJerome Glisse
309cd404af0SMichel Dänzer robj = gem_to_radeon_bo(obj);
310cd404af0SMichel Dänzer ret = radeon_bo_reserve(robj, false);
311cd404af0SMichel Dänzer if (ret != 0) {
312*f11fb66aSEmil Velikov drm_gem_object_put(obj);
313cd404af0SMichel Dänzer return ret;
314cd404af0SMichel Dänzer }
315cd404af0SMichel Dänzer /* Only 27 bit offset for legacy cursor */
316cd404af0SMichel Dänzer ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM,
317cd404af0SMichel Dänzer ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27,
318cd404af0SMichel Dänzer &radeon_crtc->cursor_addr);
319cd404af0SMichel Dänzer radeon_bo_unreserve(robj);
320cd404af0SMichel Dänzer if (ret) {
321cd404af0SMichel Dänzer DRM_ERROR("Failed to pin new cursor BO (%d)\n", ret);
322*f11fb66aSEmil Velikov drm_gem_object_put(obj);
323cd404af0SMichel Dänzer return ret;
324cd404af0SMichel Dänzer }
325cd404af0SMichel Dänzer
326771fe6b9SJerome Glisse radeon_lock_cursor(crtc, true);
3272e007e61SMichel Dänzer
328dcab0fa6SMichel Dänzer if (width != radeon_crtc->cursor_width ||
329dcab0fa6SMichel Dänzer height != radeon_crtc->cursor_height ||
330dcab0fa6SMichel Dänzer hot_x != radeon_crtc->cursor_hot_x ||
3312e007e61SMichel Dänzer hot_y != radeon_crtc->cursor_hot_y) {
3322e007e61SMichel Dänzer int x, y;
3332e007e61SMichel Dänzer
3342e007e61SMichel Dänzer x = radeon_crtc->cursor_x + radeon_crtc->cursor_hot_x - hot_x;
3352e007e61SMichel Dänzer y = radeon_crtc->cursor_y + radeon_crtc->cursor_hot_y - hot_y;
3362e007e61SMichel Dänzer
337dcab0fa6SMichel Dänzer radeon_crtc->cursor_width = width;
338dcab0fa6SMichel Dänzer radeon_crtc->cursor_height = height;
3392e007e61SMichel Dänzer radeon_crtc->cursor_hot_x = hot_x;
3402e007e61SMichel Dänzer radeon_crtc->cursor_hot_y = hot_y;
3416b16cf77SMichel Dänzer
3426b16cf77SMichel Dänzer radeon_cursor_move_locked(crtc, x, y);
3432e007e61SMichel Dänzer }
3442e007e61SMichel Dänzer
345771fe6b9SJerome Glisse radeon_show_cursor(crtc);
3466d3759faSMichel Dänzer
347771fe6b9SJerome Glisse radeon_lock_cursor(crtc, false);
348771fe6b9SJerome Glisse
349771fe6b9SJerome Glisse unpin:
350771fe6b9SJerome Glisse if (radeon_crtc->cursor_bo) {
3516d3759faSMichel Dänzer struct radeon_bo *robj = gem_to_radeon_bo(radeon_crtc->cursor_bo);
352654c59cfSMichel Dänzer ret = radeon_bo_reserve(robj, false);
353654c59cfSMichel Dänzer if (likely(ret == 0)) {
354654c59cfSMichel Dänzer radeon_bo_unpin(robj);
355654c59cfSMichel Dänzer radeon_bo_unreserve(robj);
356654c59cfSMichel Dänzer }
357*f11fb66aSEmil Velikov drm_gem_object_put(radeon_crtc->cursor_bo);
358771fe6b9SJerome Glisse }
359771fe6b9SJerome Glisse
360771fe6b9SJerome Glisse radeon_crtc->cursor_bo = obj;
361771fe6b9SJerome Glisse return 0;
3626d3759faSMichel Dänzer }
363771fe6b9SJerome Glisse
3646d3759faSMichel Dänzer /**
3656d3759faSMichel Dänzer * radeon_cursor_reset - Re-set the current cursor, if any.
3666d3759faSMichel Dänzer *
3676d3759faSMichel Dänzer * @crtc: drm crtc
3686d3759faSMichel Dänzer *
3696d3759faSMichel Dänzer * If the CRTC passed in currently has a cursor assigned, this function
3706d3759faSMichel Dänzer * makes sure it's visible.
3716d3759faSMichel Dänzer */
radeon_cursor_reset(struct drm_crtc * crtc)3726d3759faSMichel Dänzer void radeon_cursor_reset(struct drm_crtc *crtc)
3736d3759faSMichel Dänzer {
3746d3759faSMichel Dänzer struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
3756d3759faSMichel Dänzer
3766d3759faSMichel Dänzer if (radeon_crtc->cursor_bo) {
3776d3759faSMichel Dänzer radeon_lock_cursor(crtc, true);
3786d3759faSMichel Dänzer
3796d3759faSMichel Dänzer radeon_cursor_move_locked(crtc, radeon_crtc->cursor_x,
3806d3759faSMichel Dänzer radeon_crtc->cursor_y);
3816d3759faSMichel Dänzer
3826d3759faSMichel Dänzer radeon_show_cursor(crtc);
3836d3759faSMichel Dänzer
3846d3759faSMichel Dänzer radeon_lock_cursor(crtc, false);
3856d3759faSMichel Dänzer }
386771fe6b9SJerome Glisse }
387