Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright 2007-8 Advanced Micro Devices, Inc.
  3.  * Copyright 2008 Red Hat Inc.
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining a
  6.  * copy of this software and associated documentation files (the "Software"),
  7.  * to deal in the Software without restriction, including without limitation
  8.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9.  * and/or sell copies of the Software, and to permit persons to whom the
  10.  * Software is furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice shall be included in
  13.  * all copies or substantial portions of the Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  19.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  20.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  21.  * OTHER DEALINGS IN THE SOFTWARE.
  22.  *
  23.  * Authors: Dave Airlie
  24.  *          Alex Deucher
  25.  */
  26. #include "drmP.h"
  27. #include "radeon_drm.h"
  28. #include "radeon.h"
  29.  
  30. #define CURSOR_WIDTH 64
  31. #define CURSOR_HEIGHT 64
  32.  
  33. static void radeon_lock_cursor(struct drm_crtc *crtc, bool lock)
  34. {
  35.         struct radeon_device *rdev = crtc->dev->dev_private;
  36.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  37.         uint32_t cur_lock;
  38.  
  39.         if (ASIC_IS_AVIVO(rdev)) {
  40.                 cur_lock = RREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset);
  41.                 if (lock)
  42.                         cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK;
  43.                 else
  44.                         cur_lock &= ~AVIVO_D1CURSOR_UPDATE_LOCK;
  45.                 WREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock);
  46.         } else {
  47.                 cur_lock = RREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset);
  48.                 if (lock)
  49.                         cur_lock |= RADEON_CUR_LOCK;
  50.                 else
  51.                         cur_lock &= ~RADEON_CUR_LOCK;
  52.                 WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, cur_lock);
  53.         }
  54. }
  55.  
  56. static void radeon_hide_cursor(struct drm_crtc *crtc)
  57. {
  58.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  59.         struct radeon_device *rdev = crtc->dev->dev_private;
  60.  
  61.         if (ASIC_IS_AVIVO(rdev)) {
  62.                 WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
  63.                 WREG32(RADEON_MM_DATA, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
  64.         } else {
  65.                 switch (radeon_crtc->crtc_id) {
  66.                 case 0:
  67.                         WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
  68.                         break;
  69.                 case 1:
  70.                         WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
  71.                         break;
  72.                 default:
  73.                         return;
  74.                 }
  75.                 WREG32_P(RADEON_MM_DATA, 0, ~RADEON_CRTC_CUR_EN);
  76.         }
  77. }
  78.  
  79. static void radeon_show_cursor(struct drm_crtc *crtc)
  80. {
  81.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  82.         struct radeon_device *rdev = crtc->dev->dev_private;
  83.  
  84.         if (ASIC_IS_AVIVO(rdev)) {
  85.                 WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
  86.                 WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN |
  87.                              (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
  88.         } else {
  89.                 switch (radeon_crtc->crtc_id) {
  90.                 case 0:
  91.                         WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
  92.                         break;
  93.                 case 1:
  94.                         WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
  95.                         break;
  96.                 default:
  97.                         return;
  98.                 }
  99.  
  100.                 WREG32_P(RADEON_MM_DATA, (RADEON_CRTC_CUR_EN |
  101.                                           (RADEON_CRTC_CUR_MODE_24BPP << RADEON_CRTC_CUR_MODE_SHIFT)),
  102.                          ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK));
  103.         }
  104. }
  105.  
  106. static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj,
  107.                               uint32_t gpu_addr)
  108. {
  109.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  110.         struct radeon_device *rdev = crtc->dev->dev_private;
  111.  
  112.         if (ASIC_IS_AVIVO(rdev))
  113.                 WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr);
  114.         else {
  115.                 radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr;
  116.                 /* offset is from DISP(2)_BASE_ADDRESS */
  117.                 WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset);
  118.         }
  119. }
  120.  
  121. #if 0
  122.  
  123. int radeon_crtc_cursor_set(struct drm_crtc *crtc,
  124.                            struct drm_file *file_priv,
  125.                            uint32_t handle,
  126.                            uint32_t width,
  127.                            uint32_t height)
  128. {
  129.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  130.         struct drm_gem_object *obj;
  131.         uint64_t gpu_addr;
  132.         int ret;
  133.  
  134.         if (!handle) {
  135.                 /* turn off cursor */
  136.                 radeon_hide_cursor(crtc);
  137.                 obj = NULL;
  138.                 goto unpin;
  139.         }
  140.  
  141.         if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) {
  142.                 DRM_ERROR("bad cursor width or height %d x %d\n", width, height);
  143.                 return -EINVAL;
  144.         }
  145.  
  146.         radeon_crtc->cursor_width = width;
  147.         radeon_crtc->cursor_height = height;
  148.  
  149.         obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
  150.         if (!obj) {
  151.                 DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id);
  152.                 return -EINVAL;
  153.         }
  154.  
  155.         ret = radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
  156.         if (ret)
  157.                 goto fail;
  158.  
  159.         radeon_lock_cursor(crtc, true);
  160.         /* XXX only 27 bit offset for legacy cursor */
  161.         radeon_set_cursor(crtc, obj, gpu_addr);
  162.         radeon_show_cursor(crtc);
  163.         radeon_lock_cursor(crtc, false);
  164.  
  165. unpin:
  166.         if (radeon_crtc->cursor_bo) {
  167.                 radeon_gem_object_unpin(radeon_crtc->cursor_bo);
  168.                 mutex_lock(&crtc->dev->struct_mutex);
  169.                 drm_gem_object_unreference(radeon_crtc->cursor_bo);
  170.                 mutex_unlock(&crtc->dev->struct_mutex);
  171.         }
  172.  
  173.         radeon_crtc->cursor_bo = obj;
  174.         return 0;
  175. fail:
  176.         mutex_lock(&crtc->dev->struct_mutex);
  177.         drm_gem_object_unreference(obj);
  178.         mutex_unlock(&crtc->dev->struct_mutex);
  179.  
  180.         return 0;
  181. }
  182. #endif
  183.  
  184. int radeon_crtc_cursor_move(struct drm_crtc *crtc,
  185.                             int x, int y)
  186. {
  187.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  188.         struct radeon_device *rdev = crtc->dev->dev_private;
  189.         int xorigin = 0, yorigin = 0;
  190.  
  191.         if (x < 0)
  192.                 xorigin = -x + 1;
  193.         if (y < 0)
  194.                 yorigin = -y + 1;
  195.         if (xorigin >= CURSOR_WIDTH)
  196.                 xorigin = CURSOR_WIDTH - 1;
  197.         if (yorigin >= CURSOR_HEIGHT)
  198.                 yorigin = CURSOR_HEIGHT - 1;
  199.  
  200.         radeon_lock_cursor(crtc, true);
  201.         if (ASIC_IS_AVIVO(rdev)) {
  202.                 int w = radeon_crtc->cursor_width;
  203.                 int i = 0;
  204.                 struct drm_crtc *crtc_p;
  205.  
  206.                 /* avivo cursor are offset into the total surface */
  207.                 x += crtc->x;
  208.                 y += crtc->y;
  209.                 DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
  210.  
  211.                 /* avivo cursor image can't end on 128 pixel boundry or
  212.                  * go past the end of the frame if both crtcs are enabled
  213.                  */
  214.                 list_for_each_entry(crtc_p, &crtc->dev->mode_config.crtc_list, head) {
  215.                         if (crtc_p->enabled)
  216.                                 i++;
  217.                 }
  218.                 if (i > 1) {
  219.                         int cursor_end, frame_end;
  220.  
  221.                         cursor_end = x - xorigin + w;
  222.                         frame_end = crtc->x + crtc->mode.crtc_hdisplay;
  223.                         if (cursor_end >= frame_end) {
  224.                                 w = w - (cursor_end - frame_end);
  225.                                 if (!(frame_end & 0x7f))
  226.                                         w--;
  227.                         } else {
  228.                                 if (!(cursor_end & 0x7f))
  229.                                         w--;
  230.                         }
  231.                         if (w <= 0)
  232.                                 w = 1;
  233.                 }
  234.  
  235.                 WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset,
  236.                              ((xorigin ? 0 : x) << 16) |
  237.                              (yorigin ? 0 : y));
  238.                 WREG32(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
  239.                 WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
  240.                        ((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
  241.         } else {
  242.                 if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
  243.                         y *= 2;
  244.  
  245.                 WREG32(RADEON_CUR_HORZ_VERT_OFF + radeon_crtc->crtc_offset,
  246.                        (RADEON_CUR_LOCK
  247.                         | (xorigin << 16)
  248.                         | yorigin));
  249.                 WREG32(RADEON_CUR_HORZ_VERT_POSN + radeon_crtc->crtc_offset,
  250.                        (RADEON_CUR_LOCK
  251.                         | ((xorigin ? 0 : x) << 16)
  252.                         | (yorigin ? 0 : y)));
  253.                 /* offset is from DISP(2)_BASE_ADDRESS */
  254.                 WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (radeon_crtc->legacy_cursor_offset +
  255.                                                                       (yorigin * 256)));
  256.         }
  257.         radeon_lock_cursor(crtc, false);
  258.  
  259.         return 0;
  260. }
  261.