drm/radeon/kms: Implement KDB debug hooks for radeon KMS.
[pandora-kernel.git] / drivers / gpu / drm / radeon / atombios_crtc.c
index 464a81a..2ab9b36 100644 (file)
@@ -539,14 +539,15 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                                        pll->algo = PLL_ALGO_LEGACY;
                                        pll->flags |= RADEON_PLL_PREFER_CLOSEST_LOWER;
                                }
-                               /* There is some evidence (often anecdotal) that RV515 LVDS
+                               /* There is some evidence (often anecdotal) that RV515/RV620 LVDS
                                 * (on some boards at least) prefers the legacy algo.  I'm not
                                 * sure whether this should handled generically or on a
                                 * case-by-case quirk basis.  Both algos should work fine in the
                                 * majority of cases.
                                 */
                                if ((radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) &&
-                                   (rdev->family == CHIP_RV515)) {
+                                   ((rdev->family == CHIP_RV515) ||
+                                    (rdev->family == CHIP_RV620))) {
                                        /* allow the user to overrride just in case */
                                        if (radeon_new_pll == 1)
                                                pll->algo = PLL_ALGO_NEW;
@@ -853,13 +854,15 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
 
 }
 
-static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y,
-                                  struct drm_framebuffer *old_fb)
+static int evergreen_crtc_do_set_base(struct drm_crtc *crtc,
+                                     struct drm_framebuffer *fb,
+                                     int x, int y, int atomic)
 {
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_framebuffer *radeon_fb;
+       struct drm_framebuffer *target_fb;
        struct drm_gem_object *obj;
        struct radeon_bo *rbo;
        uint64_t fb_location;
@@ -867,28 +870,43 @@ static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y,
        int r;
 
        /* no fb bound */
-       if (!crtc->fb) {
+       if (!atomic && !crtc->fb) {
                DRM_DEBUG_KMS("No FB bound\n");
                return 0;
        }
 
-       radeon_fb = to_radeon_framebuffer(crtc->fb);
+       if (atomic) {
+               radeon_fb = to_radeon_framebuffer(fb);
+               target_fb = fb;
+       }
+       else {
+               radeon_fb = to_radeon_framebuffer(crtc->fb);
+               target_fb = crtc->fb;
+       }
 
-       /* Pin framebuffer & get tilling informations */
+       /* If atomic, assume fb object is pinned & idle & fenced and
+        * just update base pointers
+        */
        obj = radeon_fb->obj;
        rbo = obj->driver_private;
        r = radeon_bo_reserve(rbo, false);
        if (unlikely(r != 0))
                return r;
-       r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location);
-       if (unlikely(r != 0)) {
-               radeon_bo_unreserve(rbo);
-               return -EINVAL;
+
+       if (atomic)
+               fb_location = radeon_bo_gpu_offset(rbo);
+       else {
+               r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location);
+               if (unlikely(r != 0)) {
+                       radeon_bo_unreserve(rbo);
+                       return -EINVAL;
+               }
        }
+
        radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
        radeon_bo_unreserve(rbo);
 
-       switch (crtc->fb->bits_per_pixel) {
+       switch (target_fb->bits_per_pixel) {
        case 8:
                fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_8BPP) |
                             EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_INDEXED));
@@ -908,7 +926,7 @@ static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y,
                break;
        default:
                DRM_ERROR("Unsupported screen depth %d\n",
-                         crtc->fb->bits_per_pixel);
+                         target_fb->bits_per_pixel);
                return -EINVAL;
        }
 
@@ -954,10 +972,10 @@ static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y,
        WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
        WREG32(EVERGREEN_GRPH_X_START + radeon_crtc->crtc_offset, 0);
        WREG32(EVERGREEN_GRPH_Y_START + radeon_crtc->crtc_offset, 0);
-       WREG32(EVERGREEN_GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width);
-       WREG32(EVERGREEN_GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height);
+       WREG32(EVERGREEN_GRPH_X_END + radeon_crtc->crtc_offset, target_fb->width);
+       WREG32(EVERGREEN_GRPH_Y_END + radeon_crtc->crtc_offset, target_fb->height);
 
-       fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8);
+       fb_pitch_pixels = target_fb->pitch / (target_fb->bits_per_pixel / 8);
        WREG32(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);
        WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
 
@@ -976,8 +994,8 @@ static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y,
        else
                WREG32(EVERGREEN_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
 
-       if (old_fb && old_fb != crtc->fb) {
-               radeon_fb = to_radeon_framebuffer(old_fb);
+       if (!atomic && fb && fb != crtc->fb) {
+               radeon_fb = to_radeon_framebuffer(fb);
                rbo = radeon_fb->obj->driver_private;
                r = radeon_bo_reserve(rbo, false);
                if (unlikely(r != 0))
@@ -992,8 +1010,9 @@ static int evergreen_crtc_set_base(struct drm_crtc *crtc, int x, int y,
        return 0;
 }
 
-static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y,
-                              struct drm_framebuffer *old_fb)
+static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
+                                 struct drm_framebuffer *fb,
+                                 int x, int y, int atomic)
 {
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
@@ -1001,33 +1020,48 @@ static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y,
        struct radeon_framebuffer *radeon_fb;
        struct drm_gem_object *obj;
        struct radeon_bo *rbo;
+       struct drm_framebuffer *target_fb;
        uint64_t fb_location;
        uint32_t fb_format, fb_pitch_pixels, tiling_flags;
        int r;
 
        /* no fb bound */
-       if (!crtc->fb) {
+       if (!atomic && !crtc->fb) {
                DRM_DEBUG_KMS("No FB bound\n");
                return 0;
        }
 
-       radeon_fb = to_radeon_framebuffer(crtc->fb);
+       if (atomic) {
+               radeon_fb = to_radeon_framebuffer(fb);
+               target_fb = fb;
+       }
+       else {
+               radeon_fb = to_radeon_framebuffer(crtc->fb);
+               target_fb = crtc->fb;
+       }
 
-       /* Pin framebuffer & get tilling informations */
        obj = radeon_fb->obj;
        rbo = obj->driver_private;
        r = radeon_bo_reserve(rbo, false);
        if (unlikely(r != 0))
                return r;
-       r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location);
-       if (unlikely(r != 0)) {
-               radeon_bo_unreserve(rbo);
-               return -EINVAL;
+
+       /* If atomic, assume fb object is pinned & idle & fenced and
+        * just update base pointers
+        */
+       if (atomic)
+               fb_location = radeon_bo_gpu_offset(rbo);
+       else {
+               r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location);
+               if (unlikely(r != 0)) {
+                       radeon_bo_unreserve(rbo);
+                       return -EINVAL;
+               }
        }
        radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
        radeon_bo_unreserve(rbo);
 
-       switch (crtc->fb->bits_per_pixel) {
+       switch (target_fb->bits_per_pixel) {
        case 8:
                fb_format =
                    AVIVO_D1GRPH_CONTROL_DEPTH_8BPP |
@@ -1051,7 +1085,7 @@ static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y,
                break;
        default:
                DRM_ERROR("Unsupported screen depth %d\n",
-                         crtc->fb->bits_per_pixel);
+                         target_fb->bits_per_pixel);
                return -EINVAL;
        }
 
@@ -1092,10 +1126,10 @@ static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y,
        WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
        WREG32(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0);
        WREG32(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0);
-       WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width);
-       WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height);
+       WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, target_fb->width);
+       WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, target_fb->height);
 
-       fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8);
+       fb_pitch_pixels = target_fb->pitch / (target_fb->bits_per_pixel / 8);
        WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);
        WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
 
@@ -1114,8 +1148,8 @@ static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y,
        else
                WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
 
-       if (old_fb && old_fb != crtc->fb) {
-               radeon_fb = to_radeon_framebuffer(old_fb);
+       if (!atomic && fb && fb != crtc->fb) {
+               radeon_fb = to_radeon_framebuffer(fb);
                rbo = radeon_fb->obj->driver_private;
                r = radeon_bo_reserve(rbo, false);
                if (unlikely(r != 0))
@@ -1137,11 +1171,26 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
        struct radeon_device *rdev = dev->dev_private;
 
        if (ASIC_IS_DCE4(rdev))
-               return evergreen_crtc_set_base(crtc, x, y, old_fb);
+               return evergreen_crtc_do_set_base(crtc, old_fb, x, y, 0);
+       else if (ASIC_IS_AVIVO(rdev))
+               return avivo_crtc_do_set_base(crtc, old_fb, x, y, 0);
+       else
+               return radeon_crtc_do_set_base(crtc, old_fb, x, y, 0);
+}
+
+int atombios_crtc_set_base_atomic(struct drm_crtc *crtc,
+                                  struct drm_framebuffer *fb,
+                                  int x, int y)
+{
+       struct drm_device *dev = crtc->dev;
+       struct radeon_device *rdev = dev->dev_private;
+
+       if (ASIC_IS_DCE4(rdev))
+               return evergreen_crtc_do_set_base(crtc, fb, x, y, 1);
        else if (ASIC_IS_AVIVO(rdev))
-               return avivo_crtc_set_base(crtc, x, y, old_fb);
+               return avivo_crtc_do_set_base(crtc, fb, x, y, 1);
        else
-               return radeon_crtc_set_base(crtc, x, y, old_fb);
+               return radeon_crtc_do_set_base(crtc, fb, x, y, 1);
 }
 
 /* properly set additional regs when using atombios */
@@ -1310,6 +1359,7 @@ static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
        .mode_fixup = atombios_crtc_mode_fixup,
        .mode_set = atombios_crtc_mode_set,
        .mode_set_base = atombios_crtc_set_base,
+       .mode_set_base_atomic = atombios_crtc_set_base_atomic,
        .prepare = atombios_crtc_prepare,
        .commit = atombios_crtc_commit,
        .load_lut = radeon_crtc_load_lut,