Subversion Repositories Kolibri OS

Rev

Rev 5078 | Blame | Compare with Previous | 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 <drm/drmP.h>
  27. #include <drm/radeon_drm.h>
  28. #include "radeon.h"
  29.  
  30. static void radeon_lock_cursor(struct drm_crtc *crtc, bool lock)
  31. {
  32.         struct radeon_device *rdev = crtc->dev->dev_private;
  33.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  34.         uint32_t cur_lock;
  35.  
  36.         if (ASIC_IS_DCE4(rdev)) {
  37.                 cur_lock = RREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset);
  38.                 if (lock)
  39.                         cur_lock |= EVERGREEN_CURSOR_UPDATE_LOCK;
  40.                 else
  41.                         cur_lock &= ~EVERGREEN_CURSOR_UPDATE_LOCK;
  42.                 WREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock);
  43.         } else if (ASIC_IS_AVIVO(rdev)) {
  44.                 cur_lock = RREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset);
  45.                 if (lock)
  46.                         cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK;
  47.                 else
  48.                         cur_lock &= ~AVIVO_D1CURSOR_UPDATE_LOCK;
  49.                 WREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock);
  50.         } else {
  51.                 cur_lock = RREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset);
  52.                 if (lock)
  53.                         cur_lock |= RADEON_CUR_LOCK;
  54.                 else
  55.                         cur_lock &= ~RADEON_CUR_LOCK;
  56.                 WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, cur_lock);
  57.         }
  58. }
  59.  
  60. static void radeon_hide_cursor(struct drm_crtc *crtc)
  61. {
  62.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  63.         struct radeon_device *rdev = crtc->dev->dev_private;
  64.  
  65.         if (ASIC_IS_DCE4(rdev)) {
  66.                 WREG32_IDX(EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset,
  67.                            EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) |
  68.                            EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2));
  69.         } else if (ASIC_IS_AVIVO(rdev)) {
  70.                 WREG32_IDX(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset,
  71.                            (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
  72.         } else {
  73.                 u32 reg;
  74.                 switch (radeon_crtc->crtc_id) {
  75.                 case 0:
  76.                         reg = RADEON_CRTC_GEN_CNTL;
  77.                         break;
  78.                 case 1:
  79.                         reg = RADEON_CRTC2_GEN_CNTL;
  80.                         break;
  81.                 default:
  82.                         return;
  83.                 }
  84.                 WREG32_IDX(reg, RREG32_IDX(reg) & ~RADEON_CRTC_CUR_EN);
  85.         }
  86. }
  87.  
  88. static void radeon_show_cursor(struct drm_crtc *crtc)
  89. {
  90.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  91.         struct radeon_device *rdev = crtc->dev->dev_private;
  92.  
  93.         if (ASIC_IS_DCE4(rdev)) {
  94.                 WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
  95.                        upper_32_bits(radeon_crtc->cursor_addr));
  96.                 WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
  97.                        lower_32_bits(radeon_crtc->cursor_addr));
  98.                 WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset);
  99.                 WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN |
  100.                        EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) |
  101.                        EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2));
  102.         } else if (ASIC_IS_AVIVO(rdev)) {
  103.                 if (rdev->family >= CHIP_RV770) {
  104.                         if (radeon_crtc->crtc_id)
  105.                                 WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH,
  106.                                        upper_32_bits(radeon_crtc->cursor_addr));
  107.                         else
  108.                                 WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH,
  109.                                        upper_32_bits(radeon_crtc->cursor_addr));
  110.                 }
  111.  
  112.                 WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
  113.                        lower_32_bits(radeon_crtc->cursor_addr));
  114.                 WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
  115.                 WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN |
  116.                        (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
  117.         } else {
  118.                 /* offset is from DISP(2)_BASE_ADDRESS */
  119.                 WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset,
  120.                        radeon_crtc->cursor_addr - radeon_crtc->legacy_display_base_addr);
  121.  
  122.                 switch (radeon_crtc->crtc_id) {
  123.                 case 0:
  124.                         WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
  125.                         break;
  126.                 case 1:
  127.                         WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
  128.                         break;
  129.                 default:
  130.                         return;
  131.                 }
  132.  
  133.                 WREG32_P(RADEON_MM_DATA, (RADEON_CRTC_CUR_EN |
  134.                                           (RADEON_CRTC_CUR_MODE_24BPP << RADEON_CRTC_CUR_MODE_SHIFT)),
  135.                          ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK));
  136.         }
  137. }
  138.  
  139. static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y)
  140. {
  141.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  142.         struct radeon_device *rdev = crtc->dev->dev_private;
  143.         int xorigin = 0, yorigin = 0;
  144.         int w = radeon_crtc->cursor_width;
  145.  
  146.         if (ASIC_IS_AVIVO(rdev)) {
  147.                 /* avivo cursor are offset into the total surface */
  148.                 x += crtc->x;
  149.                 y += crtc->y;
  150.         }
  151.         DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
  152.  
  153.         if (x < 0) {
  154.                 xorigin = min(-x, radeon_crtc->max_cursor_width - 1);
  155.                 x = 0;
  156.         }
  157.         if (y < 0) {
  158.                 yorigin = min(-y, radeon_crtc->max_cursor_height - 1);
  159.                 y = 0;
  160.         }
  161.  
  162.         /* fixed on DCE6 and newer */
  163.         if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) {
  164.                 int i = 0;
  165.                 struct drm_crtc *crtc_p;
  166.  
  167.                 /*
  168.                  * avivo cursor image can't end on 128 pixel boundary or
  169.                  * go past the end of the frame if both crtcs are enabled
  170.                  *
  171.                  * NOTE: It is safe to access crtc->enabled of other crtcs
  172.                  * without holding either the mode_config lock or the other
  173.                  * crtc's lock as long as write access to this flag _always_
  174.                  * grabs all locks.
  175.                  */
  176.                 list_for_each_entry(crtc_p, &crtc->dev->mode_config.crtc_list, head) {
  177.                         if (crtc_p->enabled)
  178.                                 i++;
  179.                 }
  180.                 if (i > 1) {
  181.                         int cursor_end, frame_end;
  182.  
  183.                         cursor_end = x - xorigin + w;
  184.                         frame_end = crtc->x + crtc->mode.crtc_hdisplay;
  185.                         if (cursor_end >= frame_end) {
  186.                                 w = w - (cursor_end - frame_end);
  187.                                 if (!(frame_end & 0x7f))
  188.                                         w--;
  189.                         } else {
  190.                                 if (!(cursor_end & 0x7f))
  191.                                         w--;
  192.                         }
  193.                         if (w <= 0) {
  194.                                 w = 1;
  195.                                 cursor_end = x - xorigin + w;
  196.                                 if (!(cursor_end & 0x7f)) {
  197.                                         x--;
  198.                                         WARN_ON_ONCE(x < 0);
  199.                                 }
  200.                         }
  201.                 }
  202.         }
  203.  
  204.         if (ASIC_IS_DCE4(rdev)) {
  205.                 WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset, (x << 16) | y);
  206.                 WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
  207.                 WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset,
  208.                        ((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
  209.         } else if (ASIC_IS_AVIVO(rdev)) {
  210.                 WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, (x << 16) | y);
  211.                 WREG32(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
  212.                 WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
  213.                        ((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
  214.         } else {
  215.                 if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
  216.                         y *= 2;
  217.  
  218.                 WREG32(RADEON_CUR_HORZ_VERT_OFF + radeon_crtc->crtc_offset,
  219.                        (RADEON_CUR_LOCK
  220.                         | (xorigin << 16)
  221.                         | yorigin));
  222.                 WREG32(RADEON_CUR_HORZ_VERT_POSN + radeon_crtc->crtc_offset,
  223.                        (RADEON_CUR_LOCK
  224.                         | (x << 16)
  225.                         | y));
  226.                 /* offset is from DISP(2)_BASE_ADDRESS */
  227.                 WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset,
  228.                        radeon_crtc->cursor_addr - radeon_crtc->legacy_display_base_addr +
  229.                        yorigin * 256);
  230.         }
  231.  
  232.         radeon_crtc->cursor_x = x;
  233.         radeon_crtc->cursor_y = y;
  234.  
  235.         return 0;
  236. }
  237.  
  238. int radeon_crtc_cursor_move(struct drm_crtc *crtc,
  239.                             int x, int y)
  240. {
  241.         int ret;
  242.  
  243.         radeon_lock_cursor(crtc, true);
  244.         ret = radeon_cursor_move_locked(crtc, x, y);
  245.         radeon_lock_cursor(crtc, false);
  246.  
  247.         return ret;
  248. }
  249.  
  250. int radeon_crtc_cursor_set2(struct drm_crtc *crtc,
  251.                             struct drm_file *file_priv,
  252.                             uint32_t handle,
  253.                             uint32_t width,
  254.                             uint32_t height,
  255.                             int32_t hot_x,
  256.                             int32_t hot_y)
  257. {
  258.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  259.         struct radeon_device *rdev = crtc->dev->dev_private;
  260.         struct drm_gem_object *obj;
  261.         struct radeon_bo *robj;
  262.         int ret;
  263.  
  264.         if (!handle) {
  265.                 /* turn off cursor */
  266.                 radeon_hide_cursor(crtc);
  267.                 obj = NULL;
  268.                 goto unpin;
  269.         }
  270.  
  271.         if ((width > radeon_crtc->max_cursor_width) ||
  272.             (height > radeon_crtc->max_cursor_height)) {
  273.                 DRM_ERROR("bad cursor width or height %d x %d\n", width, height);
  274.                 return -EINVAL;
  275.         }
  276.  
  277.         obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
  278.         if (!obj) {
  279.                 DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id);
  280.                 return -ENOENT;
  281.         }
  282.  
  283.         robj = gem_to_radeon_bo(obj);
  284.         ret = radeon_bo_reserve(robj, false);
  285.         if (ret != 0) {
  286.                 drm_gem_object_unreference_unlocked(obj);
  287.                 return ret;
  288.         }
  289.         /* Only 27 bit offset for legacy cursor */
  290.         ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM,
  291.                                        ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27,
  292.                                        &radeon_crtc->cursor_addr);
  293.         radeon_bo_unreserve(robj);
  294.         if (ret) {
  295.                 DRM_ERROR("Failed to pin new cursor BO (%d)\n", ret);
  296.                 drm_gem_object_unreference_unlocked(obj);
  297.                 return ret;
  298.         }
  299.  
  300.         radeon_crtc->cursor_width = width;
  301.         radeon_crtc->cursor_height = height;
  302.  
  303.         radeon_lock_cursor(crtc, true);
  304.  
  305.         if (hot_x != radeon_crtc->cursor_hot_x ||
  306.             hot_y != radeon_crtc->cursor_hot_y) {
  307.                 int x, y;
  308.  
  309.                 x = radeon_crtc->cursor_x + radeon_crtc->cursor_hot_x - hot_x;
  310.                 y = radeon_crtc->cursor_y + radeon_crtc->cursor_hot_y - hot_y;
  311.  
  312.                 radeon_cursor_move_locked(crtc, x, y);
  313.  
  314.                 radeon_crtc->cursor_hot_x = hot_x;
  315.                 radeon_crtc->cursor_hot_y = hot_y;
  316.         }
  317.  
  318.         radeon_show_cursor(crtc);
  319.  
  320.         radeon_lock_cursor(crtc, false);
  321.  
  322. unpin:
  323.         if (radeon_crtc->cursor_bo) {
  324.                 struct radeon_bo *robj = gem_to_radeon_bo(radeon_crtc->cursor_bo);
  325.                 ret = radeon_bo_reserve(robj, false);
  326.                 if (likely(ret == 0)) {
  327.                         radeon_bo_unpin(robj);
  328.                         radeon_bo_unreserve(robj);
  329.                 }
  330.                 drm_gem_object_unreference_unlocked(radeon_crtc->cursor_bo);
  331.         }
  332.  
  333.         radeon_crtc->cursor_bo = obj;
  334.         return 0;
  335. }
  336.  
  337. /**
  338.  * radeon_cursor_reset - Re-set the current cursor, if any.
  339.  *
  340.  * @crtc: drm crtc
  341.  *
  342.  * If the CRTC passed in currently has a cursor assigned, this function
  343.  * makes sure it's visible.
  344.  */
  345. void radeon_cursor_reset(struct drm_crtc *crtc)
  346. {
  347.         struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
  348.  
  349.         if (radeon_crtc->cursor_bo) {
  350.                 radeon_lock_cursor(crtc, true);
  351.  
  352.                 radeon_cursor_move_locked(crtc, radeon_crtc->cursor_x,
  353.                                           radeon_crtc->cursor_y);
  354.  
  355.                 radeon_show_cursor(crtc);
  356.  
  357.                 radeon_lock_cursor(crtc, false);
  358.         }
  359. }
  360.