drm/radeon/kms: add initial Evergreen support (Radeon HD 5xxx)
[safe/jmp/linux-2.6] / drivers / gpu / drm / radeon / radeon_cursor.c
index 5f8ce37..9514f32 100644 (file)
@@ -36,7 +36,14 @@ static void radeon_lock_cursor(struct drm_crtc *crtc, bool lock)
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        uint32_t cur_lock;
 
-       if (ASIC_IS_AVIVO(rdev)) {
+       if (ASIC_IS_DCE4(rdev)) {
+               cur_lock = RREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset);
+               if (lock)
+                       cur_lock |= EVERGREEN_CURSOR_UPDATE_LOCK;
+               else
+                       cur_lock &= ~EVERGREEN_CURSOR_UPDATE_LOCK;
+               WREG32(EVERGREEN_CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock);
+       } else if (ASIC_IS_AVIVO(rdev)) {
                cur_lock = RREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset);
                if (lock)
                        cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK;
@@ -58,7 +65,10 @@ static void radeon_hide_cursor(struct drm_crtc *crtc)
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct radeon_device *rdev = crtc->dev->dev_private;
 
-       if (ASIC_IS_AVIVO(rdev)) {
+       if (ASIC_IS_DCE4(rdev)) {
+               WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset);
+               WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT));
+       } else if (ASIC_IS_AVIVO(rdev)) {
                WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
                WREG32(RADEON_MM_DATA, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
        } else {
@@ -81,10 +91,14 @@ static void radeon_show_cursor(struct drm_crtc *crtc)
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct radeon_device *rdev = crtc->dev->dev_private;
 
-       if (ASIC_IS_AVIVO(rdev)) {
+       if (ASIC_IS_DCE4(rdev)) {
+               WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset);
+               WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN |
+                      EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT));
+       } else if (ASIC_IS_AVIVO(rdev)) {
                WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
                WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN |
-                            (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
+                      (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
        } else {
                switch (radeon_crtc->crtc_id) {
                case 0:
@@ -109,11 +123,22 @@ static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj,
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct radeon_device *rdev = crtc->dev->dev_private;
 
-       if (ASIC_IS_AVIVO(rdev))
+       if (ASIC_IS_DCE4(rdev)) {
+               WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, 0);
+               WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr);
+       } else if (ASIC_IS_AVIVO(rdev)) {
+               if (rdev->family >= CHIP_RV770) {
+                       if (radeon_crtc->crtc_id)
+                               WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH, 0);
+                       else
+                               WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, 0);
+               }
                WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr);
-       else
+       } else {
+               radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr;
                /* offset is from DISP(2)_BASE_ADDRESS */
-               WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (gpu_addr-radeon_crtc->legacy_display_base_addr));
+               WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset);
+       }
 }
 
 int radeon_crtc_cursor_set(struct drm_crtc *crtc,
@@ -193,7 +218,15 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
                yorigin = CURSOR_HEIGHT - 1;
 
        radeon_lock_cursor(crtc, true);
-       if (ASIC_IS_AVIVO(rdev)) {
+       if (ASIC_IS_DCE4(rdev)) {
+               /* XXX: check if evergreen has the same issues as avivo chips */
+               WREG32(EVERGREEN_CUR_POSITION + radeon_crtc->crtc_offset,
+                      ((xorigin ? 0 : x) << 16) |
+                      (yorigin ? 0 : y));
+               WREG32(EVERGREEN_CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
+               WREG32(EVERGREEN_CUR_SIZE + radeon_crtc->crtc_offset,
+                      ((radeon_crtc->cursor_width - 1) << 16) | (radeon_crtc->cursor_height - 1));
+       } else if (ASIC_IS_AVIVO(rdev)) {
                int w = radeon_crtc->cursor_width;
                int i = 0;
                struct drm_crtc *crtc_p;
@@ -245,6 +278,9 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
                       (RADEON_CUR_LOCK
                        | ((xorigin ? 0 : x) << 16)
                        | (yorigin ? 0 : y)));
+               /* offset is from DISP(2)_BASE_ADDRESS */
+               WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (radeon_crtc->legacy_cursor_offset +
+                                                                     (yorigin * 256)));
        }
        radeon_lock_cursor(crtc, false);