1926deccbSFrançois Tigeot /* 2926deccbSFrançois Tigeot * Copyright 2007-8 Advanced Micro Devices, Inc. 3926deccbSFrançois Tigeot * Copyright 2008 Red Hat Inc. 4926deccbSFrançois Tigeot * 5926deccbSFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a 6926deccbSFrançois Tigeot * copy of this software and associated documentation files (the "Software"), 7926deccbSFrançois Tigeot * to deal in the Software without restriction, including without limitation 8926deccbSFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9926deccbSFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the 10926deccbSFrançois Tigeot * Software is furnished to do so, subject to the following conditions: 11926deccbSFrançois Tigeot * 12926deccbSFrançois Tigeot * The above copyright notice and this permission notice shall be included in 13926deccbSFrançois Tigeot * all copies or substantial portions of the Software. 14926deccbSFrançois Tigeot * 15926deccbSFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16926deccbSFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17926deccbSFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18926deccbSFrançois Tigeot * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19926deccbSFrançois Tigeot * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20926deccbSFrançois Tigeot * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21926deccbSFrançois Tigeot * OTHER DEALINGS IN THE SOFTWARE. 22926deccbSFrançois Tigeot * 23926deccbSFrançois Tigeot * Authors: Dave Airlie 24926deccbSFrançois Tigeot * Alex Deucher 25926deccbSFrançois Tigeot */ 26926deccbSFrançois Tigeot #include <drm/drmP.h> 2783b4b9b9SFrançois Tigeot #include <drm/radeon_drm.h> 28926deccbSFrançois Tigeot #include "radeon.h" 29926deccbSFrançois Tigeot 30926deccbSFrançois Tigeot static void radeon_lock_cursor(struct drm_crtc *crtc, bool lock) 31926deccbSFrançois Tigeot { 32926deccbSFrançois Tigeot struct radeon_device *rdev = crtc->dev->dev_private; 33926deccbSFrançois Tigeot struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 34926deccbSFrançois Tigeot uint32_t cur_lock; 35926deccbSFrançois Tigeot 36926deccbSFrançois Tigeot if (ASIC_IS_DCE4(rdev)) { 37926deccbSFrançois Tigeot cur_lock = RREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset); 38926deccbSFrançois Tigeot if (lock) 39926deccbSFrançois Tigeot cur_lock |= EVERGREEN_CURSOR_UPDATE_LOCK; 40926deccbSFrançois Tigeot else 41926deccbSFrançois Tigeot cur_lock &= ~EVERGREEN_CURSOR_UPDATE_LOCK; 42926deccbSFrançois Tigeot WREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock); 43926deccbSFrançois Tigeot } else if (ASIC_IS_AVIVO(rdev)) { 44926deccbSFrançois Tigeot cur_lock = RREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset); 45926deccbSFrançois Tigeot if (lock) 46926deccbSFrançois Tigeot cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK; 47926deccbSFrançois Tigeot else 48926deccbSFrançois Tigeot cur_lock &= ~AVIVO_D1CURSOR_UPDATE_LOCK; 49926deccbSFrançois Tigeot WREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock); 50926deccbSFrançois Tigeot } else { 51926deccbSFrançois Tigeot cur_lock = RREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset); 52926deccbSFrançois Tigeot if (lock) 53926deccbSFrançois Tigeot cur_lock |= RADEON_CUR_LOCK; 54926deccbSFrançois Tigeot else 55926deccbSFrançois Tigeot cur_lock &= ~RADEON_CUR_LOCK; 56926deccbSFrançois Tigeot WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, cur_lock); 57926deccbSFrançois Tigeot } 58926deccbSFrançois Tigeot } 59926deccbSFrançois Tigeot 60926deccbSFrançois Tigeot static void radeon_hide_cursor(struct drm_crtc *crtc) 61926deccbSFrançois Tigeot { 62926deccbSFrançois Tigeot struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 63926deccbSFrançois Tigeot struct radeon_device *rdev = crtc->dev->dev_private; 64926deccbSFrançois Tigeot 65926deccbSFrançois Tigeot if (ASIC_IS_DCE4(rdev)) { 66926deccbSFrançois Tigeot WREG32_IDX(EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset, 67926deccbSFrançois Tigeot EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | 68926deccbSFrançois Tigeot EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2)); 69926deccbSFrançois Tigeot } else if (ASIC_IS_AVIVO(rdev)) { 70926deccbSFrançois Tigeot WREG32_IDX(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, 71926deccbSFrançois Tigeot (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); 72926deccbSFrançois Tigeot } else { 73926deccbSFrançois Tigeot u32 reg; 74926deccbSFrançois Tigeot switch (radeon_crtc->crtc_id) { 75926deccbSFrançois Tigeot case 0: 76926deccbSFrançois Tigeot reg = RADEON_CRTC_GEN_CNTL; 77926deccbSFrançois Tigeot break; 78926deccbSFrançois Tigeot case 1: 79926deccbSFrançois Tigeot reg = RADEON_CRTC2_GEN_CNTL; 80926deccbSFrançois Tigeot break; 81926deccbSFrançois Tigeot default: 82926deccbSFrançois Tigeot return; 83926deccbSFrançois Tigeot } 84926deccbSFrançois Tigeot WREG32_IDX(reg, RREG32_IDX(reg) & ~RADEON_CRTC_CUR_EN); 85926deccbSFrançois Tigeot } 86926deccbSFrançois Tigeot } 87926deccbSFrançois Tigeot 88926deccbSFrançois Tigeot static void radeon_show_cursor(struct drm_crtc *crtc) 89926deccbSFrançois Tigeot { 90926deccbSFrançois Tigeot struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 91926deccbSFrançois Tigeot struct radeon_device *rdev = crtc->dev->dev_private; 92926deccbSFrançois Tigeot 93926deccbSFrançois Tigeot if (ASIC_IS_DCE4(rdev)) { 94926deccbSFrançois Tigeot WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset); 95926deccbSFrançois Tigeot WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN | 96926deccbSFrançois Tigeot EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | 97926deccbSFrançois Tigeot EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2)); 98926deccbSFrançois Tigeot } else if (ASIC_IS_AVIVO(rdev)) { 99926deccbSFrançois Tigeot WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset); 100926deccbSFrançois Tigeot WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN | 101926deccbSFrançois Tigeot (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); 102926deccbSFrançois Tigeot } else { 103926deccbSFrançois Tigeot switch (radeon_crtc->crtc_id) { 104926deccbSFrançois Tigeot case 0: 105926deccbSFrançois Tigeot WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); 106926deccbSFrançois Tigeot break; 107926deccbSFrançois Tigeot case 1: 108926deccbSFrançois Tigeot WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL); 109926deccbSFrançois Tigeot break; 110926deccbSFrançois Tigeot default: 111926deccbSFrançois Tigeot return; 112926deccbSFrançois Tigeot } 113926deccbSFrançois Tigeot 114926deccbSFrançois Tigeot WREG32_P(RADEON_MM_DATA, (RADEON_CRTC_CUR_EN | 115926deccbSFrançois Tigeot (RADEON_CRTC_CUR_MODE_24BPP << RADEON_CRTC_CUR_MODE_SHIFT)), 116926deccbSFrançois Tigeot ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK)); 117926deccbSFrançois Tigeot } 118926deccbSFrançois Tigeot } 119926deccbSFrançois Tigeot 120*7dcf36dcSFrançois Tigeot static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y) 121926deccbSFrançois Tigeot { 122926deccbSFrançois Tigeot struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 123926deccbSFrançois Tigeot struct radeon_device *rdev = crtc->dev->dev_private; 124926deccbSFrançois Tigeot int xorigin = 0, yorigin = 0; 125926deccbSFrançois Tigeot int w = radeon_crtc->cursor_width; 126926deccbSFrançois Tigeot 127926deccbSFrançois Tigeot if (ASIC_IS_AVIVO(rdev)) { 128926deccbSFrançois Tigeot /* avivo cursor are offset into the total surface */ 129926deccbSFrançois Tigeot x += crtc->x; 130926deccbSFrançois Tigeot y += crtc->y; 131926deccbSFrançois Tigeot } 132926deccbSFrançois Tigeot DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y); 133926deccbSFrançois Tigeot 134926deccbSFrançois Tigeot if (x < 0) { 13557e252bfSMichael Neumann xorigin = min(-x, radeon_crtc->max_cursor_width - 1); 136926deccbSFrançois Tigeot x = 0; 137926deccbSFrançois Tigeot } 138926deccbSFrançois Tigeot if (y < 0) { 13957e252bfSMichael Neumann yorigin = min(-y, radeon_crtc->max_cursor_height - 1); 140926deccbSFrançois Tigeot y = 0; 141926deccbSFrançois Tigeot } 142926deccbSFrançois Tigeot 143926deccbSFrançois Tigeot /* fixed on DCE6 and newer */ 144926deccbSFrançois Tigeot if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) { 145926deccbSFrançois Tigeot int i = 0; 146926deccbSFrançois Tigeot struct drm_crtc *crtc_p; 147926deccbSFrançois Tigeot 148b403bed8SMichael Neumann /* 149b403bed8SMichael Neumann * avivo cursor image can't end on 128 pixel boundary or 150926deccbSFrançois Tigeot * go past the end of the frame if both crtcs are enabled 151b403bed8SMichael Neumann * 152b403bed8SMichael Neumann * NOTE: It is safe to access crtc->enabled of other crtcs 153b403bed8SMichael Neumann * without holding either the mode_config lock or the other 154b403bed8SMichael Neumann * crtc's lock as long as write access to this flag _always_ 155b403bed8SMichael Neumann * grabs all locks. 156926deccbSFrançois Tigeot */ 157926deccbSFrançois Tigeot list_for_each_entry(crtc_p, &crtc->dev->mode_config.crtc_list, head) { 158926deccbSFrançois Tigeot if (crtc_p->enabled) 159926deccbSFrançois Tigeot i++; 160926deccbSFrançois Tigeot } 161926deccbSFrançois Tigeot if (i > 1) { 162926deccbSFrançois Tigeot int cursor_end, frame_end; 163926deccbSFrançois Tigeot 164926deccbSFrançois Tigeot cursor_end = x - xorigin + w; 165926deccbSFrançois Tigeot frame_end = crtc->x + crtc->mode.crtc_hdisplay; 166926deccbSFrançois Tigeot if (cursor_end >= frame_end) { 167926deccbSFrançois Tigeot w = w - (cursor_end - frame_end); 168926deccbSFrançois Tigeot if (!(frame_end & 0x7f)) 169926deccbSFrançois Tigeot w--; 170926deccbSFrançois Tigeot } else { 171926deccbSFrançois Tigeot if (!(cursor_end & 0x7f)) 172926deccbSFrançois Tigeot w--; 173926deccbSFrançois Tigeot } 174926deccbSFrançois Tigeot if (w <= 0) { 175926deccbSFrançois Tigeot w = 1; 176926deccbSFrançois Tigeot cursor_end = x - xorigin + w; 177926deccbSFrançois Tigeot if (!(cursor_end & 0x7f)) { 178926deccbSFrançois Tigeot x--; 179c4ef309bSzrj WARN_ON_ONCE(x < 0); 180926deccbSFrançois Tigeot } 181926deccbSFrançois Tigeot } 182926deccbSFrançois Tigeot } 183926deccbSFrançois Tigeot } 184926deccbSFrançois Tigeot 185926deccbSFrançois Tigeot if (ASIC_IS_DCE4(rdev)) { 186926deccbSFrançois Tigeot WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, (x << 16) | y); 187926deccbSFrançois Tigeot WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); 188926deccbSFrançois Tigeot WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset, 189926deccbSFrançois Tigeot ((w - 1) << 16) | (radeon_crtc->cursor_height - 1)); 190926deccbSFrançois Tigeot } else if (ASIC_IS_AVIVO(rdev)) { 191926deccbSFrançois Tigeot WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, (x << 16) | y); 192926deccbSFrançois Tigeot WREG32(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); 193926deccbSFrançois Tigeot WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset, 194926deccbSFrançois Tigeot ((w - 1) << 16) | (radeon_crtc->cursor_height - 1)); 195926deccbSFrançois Tigeot } else { 196926deccbSFrançois Tigeot if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN) 197926deccbSFrançois Tigeot y *= 2; 198926deccbSFrançois Tigeot 199926deccbSFrançois Tigeot WREG32(RADEON_CUR_HORZ_VERT_OFF + radeon_crtc->crtc_offset, 200926deccbSFrançois Tigeot (RADEON_CUR_LOCK 201926deccbSFrançois Tigeot | (xorigin << 16) 202926deccbSFrançois Tigeot | yorigin)); 203926deccbSFrançois Tigeot WREG32(RADEON_CUR_HORZ_VERT_POSN + radeon_crtc->crtc_offset, 204926deccbSFrançois Tigeot (RADEON_CUR_LOCK 205926deccbSFrançois Tigeot | (x << 16) 206926deccbSFrançois Tigeot | y)); 207926deccbSFrançois Tigeot /* offset is from DISP(2)_BASE_ADDRESS */ 208ee479021SImre Vadász WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (radeon_crtc->legacy_cursor_offset + 209ee479021SImre Vadász (yorigin * 256))); 210926deccbSFrançois Tigeot } 211*7dcf36dcSFrançois Tigeot 212*7dcf36dcSFrançois Tigeot radeon_crtc->cursor_x = x; 213*7dcf36dcSFrançois Tigeot radeon_crtc->cursor_y = y; 214926deccbSFrançois Tigeot 215926deccbSFrançois Tigeot return 0; 216926deccbSFrançois Tigeot } 217*7dcf36dcSFrançois Tigeot 218*7dcf36dcSFrançois Tigeot int radeon_crtc_cursor_move(struct drm_crtc *crtc, 219*7dcf36dcSFrançois Tigeot int x, int y) 220*7dcf36dcSFrançois Tigeot { 221*7dcf36dcSFrançois Tigeot int ret; 222*7dcf36dcSFrançois Tigeot 223*7dcf36dcSFrançois Tigeot radeon_lock_cursor(crtc, true); 224*7dcf36dcSFrançois Tigeot ret = radeon_cursor_move_locked(crtc, x, y); 225*7dcf36dcSFrançois Tigeot radeon_lock_cursor(crtc, false); 226*7dcf36dcSFrançois Tigeot 227*7dcf36dcSFrançois Tigeot return ret; 228*7dcf36dcSFrançois Tigeot } 229*7dcf36dcSFrançois Tigeot 230*7dcf36dcSFrançois Tigeot static int radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj) 231*7dcf36dcSFrançois Tigeot { 232*7dcf36dcSFrançois Tigeot struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 233*7dcf36dcSFrançois Tigeot struct radeon_device *rdev = crtc->dev->dev_private; 234*7dcf36dcSFrançois Tigeot struct radeon_bo *robj = gem_to_radeon_bo(obj); 235*7dcf36dcSFrançois Tigeot u64 gpu_addr; 236*7dcf36dcSFrançois Tigeot int ret; 237*7dcf36dcSFrançois Tigeot 238*7dcf36dcSFrançois Tigeot ret = radeon_bo_reserve(robj, false); 239*7dcf36dcSFrançois Tigeot if (unlikely(ret != 0)) 240*7dcf36dcSFrançois Tigeot goto fail; 241*7dcf36dcSFrançois Tigeot /* Only 27 bit offset for legacy cursor */ 242*7dcf36dcSFrançois Tigeot ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM, 243*7dcf36dcSFrançois Tigeot ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, 244*7dcf36dcSFrançois Tigeot &gpu_addr); 245*7dcf36dcSFrançois Tigeot radeon_bo_unreserve(robj); 246*7dcf36dcSFrançois Tigeot if (ret) 247*7dcf36dcSFrançois Tigeot goto fail; 248*7dcf36dcSFrançois Tigeot 249*7dcf36dcSFrançois Tigeot if (ASIC_IS_DCE4(rdev)) { 250*7dcf36dcSFrançois Tigeot WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, 251*7dcf36dcSFrançois Tigeot upper_32_bits(gpu_addr)); 252*7dcf36dcSFrançois Tigeot WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, 253*7dcf36dcSFrançois Tigeot gpu_addr & 0xffffffff); 254*7dcf36dcSFrançois Tigeot } else if (ASIC_IS_AVIVO(rdev)) { 255*7dcf36dcSFrançois Tigeot if (rdev->family >= CHIP_RV770) { 256*7dcf36dcSFrançois Tigeot if (radeon_crtc->crtc_id) 257*7dcf36dcSFrançois Tigeot WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH, upper_32_bits(gpu_addr)); 258*7dcf36dcSFrançois Tigeot else 259*7dcf36dcSFrançois Tigeot WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, upper_32_bits(gpu_addr)); 260*7dcf36dcSFrançois Tigeot } 261*7dcf36dcSFrançois Tigeot WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, 262*7dcf36dcSFrançois Tigeot gpu_addr & 0xffffffff); 263*7dcf36dcSFrançois Tigeot } else { 264*7dcf36dcSFrançois Tigeot radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr; 265*7dcf36dcSFrançois Tigeot /* offset is from DISP(2)_BASE_ADDRESS */ 266*7dcf36dcSFrançois Tigeot WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset); 267*7dcf36dcSFrançois Tigeot } 268*7dcf36dcSFrançois Tigeot 269*7dcf36dcSFrançois Tigeot return 0; 270*7dcf36dcSFrançois Tigeot 271*7dcf36dcSFrançois Tigeot fail: 272*7dcf36dcSFrançois Tigeot drm_gem_object_unreference_unlocked(obj); 273*7dcf36dcSFrançois Tigeot 274*7dcf36dcSFrançois Tigeot return ret; 275*7dcf36dcSFrançois Tigeot } 276*7dcf36dcSFrançois Tigeot 277*7dcf36dcSFrançois Tigeot int radeon_crtc_cursor_set2(struct drm_crtc *crtc, 278*7dcf36dcSFrançois Tigeot struct drm_file *file_priv, 279*7dcf36dcSFrançois Tigeot uint32_t handle, 280*7dcf36dcSFrançois Tigeot uint32_t width, 281*7dcf36dcSFrançois Tigeot uint32_t height, 282*7dcf36dcSFrançois Tigeot int32_t hot_x, 283*7dcf36dcSFrançois Tigeot int32_t hot_y) 284*7dcf36dcSFrançois Tigeot { 285*7dcf36dcSFrançois Tigeot struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 286*7dcf36dcSFrançois Tigeot struct drm_gem_object *obj; 287*7dcf36dcSFrançois Tigeot int ret; 288*7dcf36dcSFrançois Tigeot 289*7dcf36dcSFrançois Tigeot if (!handle) { 290*7dcf36dcSFrançois Tigeot /* turn off cursor */ 291*7dcf36dcSFrançois Tigeot radeon_hide_cursor(crtc); 292*7dcf36dcSFrançois Tigeot obj = NULL; 293*7dcf36dcSFrançois Tigeot goto unpin; 294*7dcf36dcSFrançois Tigeot } 295*7dcf36dcSFrançois Tigeot 296*7dcf36dcSFrançois Tigeot if ((width > radeon_crtc->max_cursor_width) || 297*7dcf36dcSFrançois Tigeot (height > radeon_crtc->max_cursor_height)) { 298*7dcf36dcSFrançois Tigeot DRM_ERROR("bad cursor width or height %d x %d\n", width, height); 299*7dcf36dcSFrançois Tigeot return -EINVAL; 300*7dcf36dcSFrançois Tigeot } 301*7dcf36dcSFrançois Tigeot 302*7dcf36dcSFrançois Tigeot obj = drm_gem_object_lookup(file_priv, handle); 303*7dcf36dcSFrançois Tigeot if (!obj) { 304*7dcf36dcSFrançois Tigeot DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id); 305*7dcf36dcSFrançois Tigeot return -ENOENT; 306*7dcf36dcSFrançois Tigeot } 307*7dcf36dcSFrançois Tigeot 308*7dcf36dcSFrançois Tigeot radeon_crtc->cursor_width = width; 309*7dcf36dcSFrançois Tigeot radeon_crtc->cursor_height = height; 310*7dcf36dcSFrançois Tigeot 311*7dcf36dcSFrançois Tigeot radeon_lock_cursor(crtc, true); 312*7dcf36dcSFrançois Tigeot 313*7dcf36dcSFrançois Tigeot if (hot_x != radeon_crtc->cursor_hot_x || 314*7dcf36dcSFrançois Tigeot hot_y != radeon_crtc->cursor_hot_y) { 315*7dcf36dcSFrançois Tigeot int x, y; 316*7dcf36dcSFrançois Tigeot 317*7dcf36dcSFrançois Tigeot x = radeon_crtc->cursor_x + radeon_crtc->cursor_hot_x - hot_x; 318*7dcf36dcSFrançois Tigeot y = radeon_crtc->cursor_y + radeon_crtc->cursor_hot_y - hot_y; 319*7dcf36dcSFrançois Tigeot 320*7dcf36dcSFrançois Tigeot radeon_cursor_move_locked(crtc, x, y); 321*7dcf36dcSFrançois Tigeot 322*7dcf36dcSFrançois Tigeot radeon_crtc->cursor_hot_x = hot_x; 323*7dcf36dcSFrançois Tigeot radeon_crtc->cursor_hot_y = hot_y; 324*7dcf36dcSFrançois Tigeot } 325*7dcf36dcSFrançois Tigeot 326*7dcf36dcSFrançois Tigeot ret = radeon_set_cursor(crtc, obj); 327*7dcf36dcSFrançois Tigeot 328*7dcf36dcSFrançois Tigeot if (ret) 329*7dcf36dcSFrançois Tigeot DRM_ERROR("radeon_set_cursor returned %d, not changing cursor\n", 330*7dcf36dcSFrançois Tigeot ret); 331*7dcf36dcSFrançois Tigeot else 332*7dcf36dcSFrançois Tigeot radeon_show_cursor(crtc); 333*7dcf36dcSFrançois Tigeot 334*7dcf36dcSFrançois Tigeot radeon_lock_cursor(crtc, false); 335*7dcf36dcSFrançois Tigeot 336*7dcf36dcSFrançois Tigeot unpin: 337*7dcf36dcSFrançois Tigeot if (radeon_crtc->cursor_bo) { 338*7dcf36dcSFrançois Tigeot struct radeon_bo *robj = gem_to_radeon_bo(radeon_crtc->cursor_bo); 339*7dcf36dcSFrançois Tigeot ret = radeon_bo_reserve(robj, false); 340*7dcf36dcSFrançois Tigeot if (likely(ret == 0)) { 341*7dcf36dcSFrançois Tigeot radeon_bo_unpin(robj); 342*7dcf36dcSFrançois Tigeot radeon_bo_unreserve(robj); 343*7dcf36dcSFrançois Tigeot } 344*7dcf36dcSFrançois Tigeot if (radeon_crtc->cursor_bo != obj) 345*7dcf36dcSFrançois Tigeot drm_gem_object_unreference_unlocked(radeon_crtc->cursor_bo); 346*7dcf36dcSFrançois Tigeot } 347*7dcf36dcSFrançois Tigeot 348*7dcf36dcSFrançois Tigeot radeon_crtc->cursor_bo = obj; 349*7dcf36dcSFrançois Tigeot return 0; 350*7dcf36dcSFrançois Tigeot } 351*7dcf36dcSFrançois Tigeot 352*7dcf36dcSFrançois Tigeot /** 353*7dcf36dcSFrançois Tigeot * radeon_cursor_reset - Re-set the current cursor, if any. 354*7dcf36dcSFrançois Tigeot * 355*7dcf36dcSFrançois Tigeot * @crtc: drm crtc 356*7dcf36dcSFrançois Tigeot * 357*7dcf36dcSFrançois Tigeot * If the CRTC passed in currently has a cursor assigned, this function 358*7dcf36dcSFrançois Tigeot * makes sure it's visible. 359*7dcf36dcSFrançois Tigeot */ 360*7dcf36dcSFrançois Tigeot void radeon_cursor_reset(struct drm_crtc *crtc) 361*7dcf36dcSFrançois Tigeot { 362*7dcf36dcSFrançois Tigeot struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 363*7dcf36dcSFrançois Tigeot int ret; 364*7dcf36dcSFrançois Tigeot 365*7dcf36dcSFrançois Tigeot if (radeon_crtc->cursor_bo) { 366*7dcf36dcSFrançois Tigeot radeon_lock_cursor(crtc, true); 367*7dcf36dcSFrançois Tigeot 368*7dcf36dcSFrançois Tigeot radeon_cursor_move_locked(crtc, radeon_crtc->cursor_x, 369*7dcf36dcSFrançois Tigeot radeon_crtc->cursor_y); 370*7dcf36dcSFrançois Tigeot 371*7dcf36dcSFrançois Tigeot ret = radeon_set_cursor(crtc, radeon_crtc->cursor_bo); 372*7dcf36dcSFrançois Tigeot if (ret) 373*7dcf36dcSFrançois Tigeot DRM_ERROR("radeon_set_cursor returned %d, not showing " 374*7dcf36dcSFrançois Tigeot "cursor\n", ret); 375*7dcf36dcSFrançois Tigeot else 376*7dcf36dcSFrançois Tigeot radeon_show_cursor(crtc); 377*7dcf36dcSFrançois Tigeot 378*7dcf36dcSFrançois Tigeot radeon_lock_cursor(crtc, false); 379*7dcf36dcSFrançois Tigeot } 380*7dcf36dcSFrançois Tigeot } 381