This source file includes following definitions.
- radeon_lock_cursor
- radeon_hide_cursor
- radeon_show_cursor
- radeon_cursor_move_locked
- radeon_crtc_cursor_move
- radeon_crtc_cursor_set2
- radeon_cursor_reset
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 #include <drm/drm_device.h>
  28 #include <drm/radeon_drm.h>
  29 
  30 #include "radeon.h"
  31 
  32 static void radeon_lock_cursor(struct drm_crtc *crtc, bool lock)
  33 {
  34         struct radeon_device *rdev = crtc->dev->dev_private;
  35         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  36         uint32_t cur_lock;
  37 
  38         if (ASIC_IS_DCE4(rdev)) {
  39                 cur_lock = RREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset);
  40                 if (lock)
  41                         cur_lock |= EVERGREEN_CURSOR_UPDATE_LOCK;
  42                 else
  43                         cur_lock &= ~EVERGREEN_CURSOR_UPDATE_LOCK;
  44                 WREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock);
  45         } else if (ASIC_IS_AVIVO(rdev)) {
  46                 cur_lock = RREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset);
  47                 if (lock)
  48                         cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK;
  49                 else
  50                         cur_lock &= ~AVIVO_D1CURSOR_UPDATE_LOCK;
  51                 WREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock);
  52         } else {
  53                 cur_lock = RREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset);
  54                 if (lock)
  55                         cur_lock |= RADEON_CUR_LOCK;
  56                 else
  57                         cur_lock &= ~RADEON_CUR_LOCK;
  58                 WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, cur_lock);
  59         }
  60 }
  61 
  62 static void radeon_hide_cursor(struct drm_crtc *crtc)
  63 {
  64         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  65         struct radeon_device *rdev = crtc->dev->dev_private;
  66 
  67         if (ASIC_IS_DCE4(rdev)) {
  68                 WREG32_IDX(EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset,
  69                            EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) |
  70                            EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2));
  71         } else if (ASIC_IS_AVIVO(rdev)) {
  72                 WREG32_IDX(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset,
  73                            (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
  74         } else {
  75                 u32 reg;
  76                 switch (radeon_crtc->crtc_id) {
  77                 case 0:
  78                         reg = RADEON_CRTC_GEN_CNTL;
  79                         break;
  80                 case 1:
  81                         reg = RADEON_CRTC2_GEN_CNTL;
  82                         break;
  83                 default:
  84                         return;
  85                 }
  86                 WREG32_IDX(reg, RREG32_IDX(reg) & ~RADEON_CRTC_CUR_EN);
  87         }
  88 }
  89 
  90 static void radeon_show_cursor(struct drm_crtc *crtc)
  91 {
  92         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  93         struct radeon_device *rdev = crtc->dev->dev_private;
  94 
  95         if (radeon_crtc->cursor_out_of_bounds)
  96                 return;
  97 
  98         if (ASIC_IS_DCE4(rdev)) {
  99                 WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
 100                        upper_32_bits(radeon_crtc->cursor_addr));
 101                 WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
 102                        lower_32_bits(radeon_crtc->cursor_addr));
 103                 WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset);
 104                 WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN |
 105                        EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) |
 106                        EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2));
 107         } else if (ASIC_IS_AVIVO(rdev)) {
 108                 if (rdev->family >= CHIP_RV770) {
 109                         if (radeon_crtc->crtc_id)
 110                                 WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH,
 111                                        upper_32_bits(radeon_crtc->cursor_addr));
 112                         else
 113                                 WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH,
 114                                        upper_32_bits(radeon_crtc->cursor_addr));
 115                 }
 116 
 117                 WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
 118                        lower_32_bits(radeon_crtc->cursor_addr));
 119                 WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
 120                 WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN |
 121                        (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
 122         } else {
 123                 
 124                 WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset,
 125                        radeon_crtc->cursor_addr - radeon_crtc->legacy_display_base_addr);
 126 
 127                 switch (radeon_crtc->crtc_id) {
 128                 case 0:
 129                         WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
 130                         break;
 131                 case 1:
 132                         WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
 133                         break;
 134                 default:
 135                         return;
 136                 }
 137 
 138                 WREG32_P(RADEON_MM_DATA, (RADEON_CRTC_CUR_EN |
 139                                           (RADEON_CRTC_CUR_MODE_24BPP << RADEON_CRTC_CUR_MODE_SHIFT)),
 140                          ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK));
 141         }
 142 }
 143 
 144 static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y)
 145 {
 146         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 147         struct radeon_device *rdev = crtc->dev->dev_private;
 148         int xorigin = 0, yorigin = 0;
 149         int w = radeon_crtc->cursor_width;
 150 
 151         radeon_crtc->cursor_x = x;
 152         radeon_crtc->cursor_y = y;
 153 
 154         if (ASIC_IS_AVIVO(rdev)) {
 155                 
 156                 x += crtc->x;
 157                 y += crtc->y;
 158         }
 159 
 160         if (x < 0)
 161                 xorigin = min(-x, radeon_crtc->max_cursor_width - 1);
 162         if (y < 0)
 163                 yorigin = min(-y, radeon_crtc->max_cursor_height - 1);
 164 
 165         if (!ASIC_IS_AVIVO(rdev)) {
 166                 x += crtc->x;
 167                 y += crtc->y;
 168         }
 169         DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
 170 
 171         
 172         if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) {
 173                 int i = 0;
 174                 struct drm_crtc *crtc_p;
 175 
 176                 
 177 
 178 
 179 
 180 
 181 
 182 
 183 
 184 
 185                 list_for_each_entry(crtc_p, &crtc->dev->mode_config.crtc_list, head) {
 186                         if (crtc_p->enabled)
 187                                 i++;
 188                 }
 189                 if (i > 1) {
 190                         int cursor_end, frame_end;
 191 
 192                         cursor_end = x + w;
 193                         frame_end = crtc->x + crtc->mode.crtc_hdisplay;
 194                         if (cursor_end >= frame_end) {
 195                                 w = w - (cursor_end - frame_end);
 196                                 if (!(frame_end & 0x7f))
 197                                         w--;
 198                         } else if (cursor_end <= 0) {
 199                                 goto out_of_bounds;
 200                         } else if (!(cursor_end & 0x7f)) {
 201                                 w--;
 202                         }
 203                         if (w <= 0) {
 204                                 goto out_of_bounds;
 205                         }
 206                 }
 207         }
 208 
 209         if (x <= (crtc->x - w) || y <= (crtc->y - radeon_crtc->cursor_height) ||
 210             x >= (crtc->x + crtc->mode.hdisplay) ||
 211             y >= (crtc->y + crtc->mode.vdisplay))
 212                 goto out_of_bounds;
 213 
 214         x += xorigin;
 215         y += yorigin;
 216 
 217         if (ASIC_IS_DCE4(rdev)) {
 218                 WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, (x << 16) | y);
 219                 WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
 220                 WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset,
 221                        ((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
 222         } else if (ASIC_IS_AVIVO(rdev)) {
 223                 WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, (x << 16) | y);
 224                 WREG32(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
 225                 WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
 226                        ((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
 227         } else {
 228                 x -= crtc->x;
 229                 y -= crtc->y;
 230 
 231                 if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
 232                         y *= 2;
 233 
 234                 WREG32(RADEON_CUR_HORZ_VERT_OFF + radeon_crtc->crtc_offset,
 235                        (RADEON_CUR_LOCK
 236                         | (xorigin << 16)
 237                         | yorigin));
 238                 WREG32(RADEON_CUR_HORZ_VERT_POSN + radeon_crtc->crtc_offset,
 239                        (RADEON_CUR_LOCK
 240                         | (x << 16)
 241                         | y));
 242                 
 243                 WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset,
 244                        radeon_crtc->cursor_addr - radeon_crtc->legacy_display_base_addr +
 245                        yorigin * 256);
 246         }
 247 
 248         if (radeon_crtc->cursor_out_of_bounds) {
 249                 radeon_crtc->cursor_out_of_bounds = false;
 250                 if (radeon_crtc->cursor_bo)
 251                         radeon_show_cursor(crtc);
 252         }
 253 
 254         return 0;
 255 
 256  out_of_bounds:
 257         if (!radeon_crtc->cursor_out_of_bounds) {
 258                 radeon_hide_cursor(crtc);
 259                 radeon_crtc->cursor_out_of_bounds = true;
 260         }
 261         return 0;
 262 }
 263 
 264 int radeon_crtc_cursor_move(struct drm_crtc *crtc,
 265                             int x, int y)
 266 {
 267         int ret;
 268 
 269         radeon_lock_cursor(crtc, true);
 270         ret = radeon_cursor_move_locked(crtc, x, y);
 271         radeon_lock_cursor(crtc, false);
 272 
 273         return ret;
 274 }
 275 
 276 int radeon_crtc_cursor_set2(struct drm_crtc *crtc,
 277                             struct drm_file *file_priv,
 278                             uint32_t handle,
 279                             uint32_t width,
 280                             uint32_t height,
 281                             int32_t hot_x,
 282                             int32_t hot_y)
 283 {
 284         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 285         struct radeon_device *rdev = crtc->dev->dev_private;
 286         struct drm_gem_object *obj;
 287         struct radeon_bo *robj;
 288         int ret;
 289 
 290         if (!handle) {
 291                 
 292                 radeon_hide_cursor(crtc);
 293                 obj = NULL;
 294                 goto unpin;
 295         }
 296 
 297         if ((width > radeon_crtc->max_cursor_width) ||
 298             (height > radeon_crtc->max_cursor_height)) {
 299                 DRM_ERROR("bad cursor width or height %d x %d\n", width, height);
 300                 return -EINVAL;
 301         }
 302 
 303         obj = drm_gem_object_lookup(file_priv, handle);
 304         if (!obj) {
 305                 DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id);
 306                 return -ENOENT;
 307         }
 308 
 309         robj = gem_to_radeon_bo(obj);
 310         ret = radeon_bo_reserve(robj, false);
 311         if (ret != 0) {
 312                 drm_gem_object_put_unlocked(obj);
 313                 return ret;
 314         }
 315         
 316         ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM,
 317                                        ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27,
 318                                        &radeon_crtc->cursor_addr);
 319         radeon_bo_unreserve(robj);
 320         if (ret) {
 321                 DRM_ERROR("Failed to pin new cursor BO (%d)\n", ret);
 322                 drm_gem_object_put_unlocked(obj);
 323                 return ret;
 324         }
 325 
 326         radeon_lock_cursor(crtc, true);
 327 
 328         if (width != radeon_crtc->cursor_width ||
 329             height != radeon_crtc->cursor_height ||
 330             hot_x != radeon_crtc->cursor_hot_x ||
 331             hot_y != radeon_crtc->cursor_hot_y) {
 332                 int x, y;
 333 
 334                 x = radeon_crtc->cursor_x + radeon_crtc->cursor_hot_x - hot_x;
 335                 y = radeon_crtc->cursor_y + radeon_crtc->cursor_hot_y - hot_y;
 336 
 337                 radeon_crtc->cursor_width = width;
 338                 radeon_crtc->cursor_height = height;
 339                 radeon_crtc->cursor_hot_x = hot_x;
 340                 radeon_crtc->cursor_hot_y = hot_y;
 341 
 342                 radeon_cursor_move_locked(crtc, x, y);
 343         }
 344 
 345         radeon_show_cursor(crtc);
 346 
 347         radeon_lock_cursor(crtc, false);
 348 
 349 unpin:
 350         if (radeon_crtc->cursor_bo) {
 351                 struct radeon_bo *robj = gem_to_radeon_bo(radeon_crtc->cursor_bo);
 352                 ret = radeon_bo_reserve(robj, false);
 353                 if (likely(ret == 0)) {
 354                         radeon_bo_unpin(robj);
 355                         radeon_bo_unreserve(robj);
 356                 }
 357                 drm_gem_object_put_unlocked(radeon_crtc->cursor_bo);
 358         }
 359 
 360         radeon_crtc->cursor_bo = obj;
 361         return 0;
 362 }
 363 
 364 
 365 
 366 
 367 
 368 
 369 
 370 
 371 
 372 void radeon_cursor_reset(struct drm_crtc *crtc)
 373 {
 374         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 375 
 376         if (radeon_crtc->cursor_bo) {
 377                 radeon_lock_cursor(crtc, true);
 378 
 379                 radeon_cursor_move_locked(crtc, radeon_crtc->cursor_x,
 380                                           radeon_crtc->cursor_y);
 381 
 382                 radeon_show_cursor(crtc);
 383 
 384                 radeon_lock_cursor(crtc, false);
 385         }
 386 }