From 4dd19b0dd79c2bfe04a7a19bea0caf9284695cb4 Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Sun, 26 Sep 2010 06:47:23 -0500 Subject: drm/radeon/kms: Implement KDB debug hooks for radeon KMS. Signed-off-by: Chris Ball Signed-off-by: Jason Wessel CC: Jesse Barnes CC: dri-devel@lists.freedesktop.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios_crtc.c | 119 ++++++++++++++++++++-------- drivers/gpu/drm/radeon/radeon_fb.c | 2 + drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 45 ++++++++--- drivers/gpu/drm/radeon/radeon_mode.h | 10 ++- 4 files changed, 129 insertions(+), 47 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index cd0290f946cf..2ab9b360d3c9 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -854,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; @@ -868,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)); @@ -909,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; } @@ -955,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); @@ -977,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)) @@ -993,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; @@ -1002,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 | @@ -1052,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; } @@ -1093,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); @@ -1115,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)) @@ -1138,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 */ @@ -1311,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, diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 9cdf6a35bc2c..bc61c5adb56d 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -59,6 +59,8 @@ static struct fb_ops radeonfb_ops = { .fb_pan_display = drm_fb_helper_pan_display, .fb_blank = drm_fb_helper_blank, .fb_setcmap = drm_fb_helper_setcmap, + .fb_debug_enter = drm_fb_helper_debug_enter, + .fb_debug_leave = drm_fb_helper_debug_leave, }; diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 305049afde15..bfa090e1f512 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -347,11 +347,26 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) +{ + return radeon_crtc_do_set_base(crtc, old_fb, x, y, 0); +} + +int radeon_crtc_set_base_atomic(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y) +{ + return radeon_crtc_do_set_base(crtc, fb, x, y, 1); +} + +int radeon_crtc_do_set_base(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y, int atomic) { struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct radeon_framebuffer *radeon_fb; + struct drm_framebuffer *target_fb; struct drm_gem_object *obj; struct radeon_bo *rbo; uint64_t base; @@ -364,14 +379,21 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, DRM_DEBUG_KMS("\n"); /* 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; + } - switch (crtc->fb->bits_per_pixel) { + switch (target_fb->bits_per_pixel) { case 8: format = 2; break; @@ -415,10 +437,10 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, crtc_offset_cntl = 0; - pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8); - crtc_pitch = (((pitch_pixels * crtc->fb->bits_per_pixel) + - ((crtc->fb->bits_per_pixel * 8) - 1)) / - (crtc->fb->bits_per_pixel * 8)); + pitch_pixels = target_fb->pitch / (target_fb->bits_per_pixel / 8); + crtc_pitch = (((pitch_pixels * target_fb->bits_per_pixel) + + ((target_fb->bits_per_pixel * 8) - 1)) / + (target_fb->bits_per_pixel * 8)); crtc_pitch |= crtc_pitch << 16; @@ -443,14 +465,14 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, crtc_tile_x0_y0 = x | (y << 16); base &= ~0x7ff; } else { - int byteshift = crtc->fb->bits_per_pixel >> 4; + int byteshift = target_fb->bits_per_pixel >> 4; int tile_addr = (((y >> 3) * pitch_pixels + x) >> (8 - byteshift)) << 11; base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); crtc_offset_cntl |= (y % 16); } } else { int offset = y * pitch_pixels + x; - switch (crtc->fb->bits_per_pixel) { + switch (target_fb->bits_per_pixel) { case 8: offset *= 1; break; @@ -496,8 +518,8 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset); WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch); - 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)) @@ -1040,6 +1062,7 @@ static const struct drm_crtc_helper_funcs legacy_helper_funcs = { .mode_fixup = radeon_crtc_mode_fixup, .mode_set = radeon_crtc_mode_set, .mode_set_base = radeon_crtc_set_base, + .mode_set_base_atomic = radeon_crtc_set_base_atomic, .prepare = radeon_crtc_prepare, .commit = radeon_crtc_commit, .load_lut = radeon_crtc_load_lut, diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 17a6602b5885..9dd27c23a798 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -514,6 +514,9 @@ extern void radeon_encoder_set_active_device(struct drm_encoder *encoder); extern void radeon_crtc_load_lut(struct drm_crtc *crtc); extern int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb); +extern int atombios_crtc_set_base_atomic(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y); extern int atombios_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -523,7 +526,12 @@ extern void atombios_crtc_dpms(struct drm_crtc *crtc, int mode); extern int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb); - +extern int radeon_crtc_set_base_atomic(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y); +extern int radeon_crtc_do_set_base(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y, int atomic); extern int radeon_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, uint32_t handle, -- cgit v1.2.3 From be64c2bb4731b0e6223a496eed615b816ac879ec Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Sun, 26 Sep 2010 06:47:24 -0500 Subject: drm/nouveau/kms: Implement KDB debug hooks for nouveau KMS. Tested on nv50 and nv04 HW. Signed-off-by: Chris Ball Signed-off-by: Jason Wessel CC: Jesse Barnes CC: dri-devel@lists.freedesktop.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 6 ++++ drivers/gpu/drm/nouveau/nv04_crtc.c | 46 +++++++++++++++++++++++++------ drivers/gpu/drm/nouveau/nv50_crtc.c | 49 ++++++++++++++++++++++++--------- 3 files changed, 80 insertions(+), 21 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index d2047713dc59..c5afd146aeb2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -104,6 +104,8 @@ static struct fb_ops nouveau_fbcon_ops = { .fb_pan_display = drm_fb_helper_pan_display, .fb_blank = drm_fb_helper_blank, .fb_setcmap = drm_fb_helper_setcmap, + .fb_debug_enter = drm_fb_helper_debug_enter, + .fb_debug_leave = drm_fb_helper_debug_leave, }; static struct fb_ops nv04_fbcon_ops = { @@ -117,6 +119,8 @@ static struct fb_ops nv04_fbcon_ops = { .fb_pan_display = drm_fb_helper_pan_display, .fb_blank = drm_fb_helper_blank, .fb_setcmap = drm_fb_helper_setcmap, + .fb_debug_enter = drm_fb_helper_debug_enter, + .fb_debug_leave = drm_fb_helper_debug_leave, }; static struct fb_ops nv50_fbcon_ops = { @@ -130,6 +134,8 @@ static struct fb_ops nv50_fbcon_ops = { .fb_pan_display = drm_fb_helper_pan_display, .fb_blank = drm_fb_helper_blank, .fb_setcmap = drm_fb_helper_setcmap, + .fb_debug_enter = drm_fb_helper_debug_enter, + .fb_debug_leave = drm_fb_helper_debug_leave, }; static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index 497df8765f28..f5bbd46f76bc 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c @@ -768,8 +768,9 @@ nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start, } static int -nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb) +nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, + struct drm_framebuffer *passed_fb, + int x, int y, bool atomic) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct drm_device *dev = crtc->dev; @@ -780,13 +781,26 @@ nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, int arb_burst, arb_lwm; int ret; - ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM); - if (ret) - return ret; + /* If atomic, we want to switch to the fb we were passed, so + * now we update pointers to do that. (We don't pin; just + * assume we're already pinned and update the base address.) + */ + if (atomic) { + drm_fb = passed_fb; + fb = nouveau_framebuffer(passed_fb); + } + else { + /* If not atomic, we can go ahead and pin, and unpin the + * old fb we were passed. + */ + ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM); + if (ret) + return ret; - if (old_fb) { - struct nouveau_framebuffer *ofb = nouveau_framebuffer(old_fb); - nouveau_bo_unpin(ofb->nvbo); + if (passed_fb) { + struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb); + nouveau_bo_unpin(ofb->nvbo); + } } nv_crtc->fb.offset = fb->nvbo->bo.offset; @@ -834,6 +848,21 @@ nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, return 0; } +static int +nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb) +{ + return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false); +} + +static int +nv04_crtc_mode_set_base_atomic(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y) +{ + return nv04_crtc_do_mode_set_base(crtc, fb, x, y, true); +} + static void nv04_cursor_upload(struct drm_device *dev, struct nouveau_bo *src, struct nouveau_bo *dst) { @@ -962,6 +991,7 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = { .mode_fixup = nv_crtc_mode_fixup, .mode_set = nv_crtc_mode_set, .mode_set_base = nv04_crtc_mode_set_base, + .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic, .load_lut = nv_crtc_gamma_load, }; diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index bfd4ca2fe7ef..f41b44864e80 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c @@ -491,8 +491,9 @@ nv50_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *mode, } static int -nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb, bool update) +nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, + struct drm_framebuffer *passed_fb, + int x, int y, bool update, bool atomic) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct drm_device *dev = nv_crtc->base.dev; @@ -504,6 +505,28 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, int x, int y, NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); + /* If atomic, we want to switch to the fb we were passed, so + * now we update pointers to do that. (We don't pin; just + * assume we're already pinned and update the base address.) + */ + if (atomic) { + drm_fb = passed_fb; + fb = nouveau_framebuffer(passed_fb); + } + else { + /* If not atomic, we can go ahead and pin, and unpin the + * old fb we were passed. + */ + ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM); + if (ret) + return ret; + + if (passed_fb) { + struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb); + nouveau_bo_unpin(ofb->nvbo); + } + } + switch (drm_fb->depth) { case 8: format = NV50_EVO_CRTC_FB_DEPTH_8; @@ -526,15 +549,6 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, int x, int y, return -EINVAL; } - ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM); - if (ret) - return ret; - - if (old_fb) { - struct nouveau_framebuffer *ofb = nouveau_framebuffer(old_fb); - nouveau_bo_unpin(ofb->nvbo); - } - nv_crtc->fb.offset = fb->nvbo->bo.offset - dev_priv->vm_vram_base; nv_crtc->fb.tile_flags = fb->nvbo->tile_flags; nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; @@ -685,14 +699,22 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false); nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false); - return nv50_crtc_do_mode_set_base(crtc, x, y, old_fb, false); + return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false, false); } static int nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) { - return nv50_crtc_do_mode_set_base(crtc, x, y, old_fb, true); + return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, true, false); +} + +static int +nv50_crtc_mode_set_base_atomic(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + int x, int y) +{ + return nv50_crtc_do_mode_set_base(crtc, fb, x, y, true, true); } static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { @@ -702,6 +724,7 @@ static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { .mode_fixup = nv50_crtc_mode_fixup, .mode_set = nv50_crtc_mode_set, .mode_set_base = nv50_crtc_mode_set_base, + .mode_set_base_atomic = nv50_crtc_mode_set_base_atomic, .load_lut = nv50_crtc_lut_load, }; -- cgit v1.2.3 From 413d45d3627be4748058dea697718ed6fb88bd01 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Sun, 26 Sep 2010 06:47:25 -0500 Subject: drm, kdb, kms: Add an enter argument to mode_set_base_atomic() API Some devices such as the radeon chips receive information from user space which needs to be saved when executing an atomic mode set operation, else the user space would have to be queried again for the information. This patch extends the mode_set_base_atomic() call to pass an argument to indicate if this is an entry or an exit from an atomic kernel mode set change. Individual drm drivers can properly save and restore state accordingly. Signed-off-by: Jason Wessel CC: Jesse Barnes CC: David Airlie CC: dri-devel@lists.freedesktop.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fb_helper.c | 5 +++-- drivers/gpu/drm/i915/intel_display.c | 4 ++-- drivers/gpu/drm/nouveau/nv04_crtc.c | 2 +- drivers/gpu/drm/nouveau/nv50_crtc.c | 2 +- drivers/gpu/drm/radeon/atombios_crtc.c | 2 +- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 2 +- drivers/gpu/drm/radeon/radeon_mode.h | 4 ++-- 7 files changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 6a5e403f9aa1..625a2d551d6a 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -263,7 +263,8 @@ int drm_fb_helper_debug_enter(struct fb_info *info) funcs->mode_set_base_atomic(mode_set->crtc, mode_set->fb, mode_set->x, - mode_set->y); + mode_set->y, + 1); } } @@ -309,7 +310,7 @@ int drm_fb_helper_debug_leave(struct fb_info *info) } funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x, - crtc->y); + crtc->y, 0); } return 0; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 69c54c5a4254..9109c00f3ead 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1492,7 +1492,7 @@ err_unpin: /* Assume fb object is pinned & idle & fenced and just update base pointers */ static int intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, - int x, int y) + int x, int y, int enter) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -1614,7 +1614,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, atomic_read(&obj_priv->pending_flip) == 0); } - ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y); + ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y, 0); if (ret) { i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index f5bbd46f76bc..fb669dd39c3c 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c @@ -858,7 +858,7 @@ nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, static int nv04_crtc_mode_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, - int x, int y) + int x, int y, int enter) { return nv04_crtc_do_mode_set_base(crtc, fb, x, y, true); } diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index f41b44864e80..727a7a12fed9 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c @@ -712,7 +712,7 @@ nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, static int nv50_crtc_mode_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, - int x, int y) + int x, int y, int enter) { return nv50_crtc_do_mode_set_base(crtc, fb, x, y, true, true); } diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 2ab9b360d3c9..501e5286ec3f 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1180,7 +1180,7 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, int atombios_crtc_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, - int x, int y) + int x, int y, int enter) { struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index bfa090e1f512..8752d3447b72 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -353,7 +353,7 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, int radeon_crtc_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, - int x, int y) + int x, int y, int enter) { return radeon_crtc_do_set_base(crtc, fb, x, y, 1); } diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 9dd27c23a798..c4116d3d8d06 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -516,7 +516,7 @@ extern int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb); extern int atombios_crtc_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, - int x, int y); + int x, int y, int enter); extern int atombios_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -528,7 +528,7 @@ extern int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb); extern int radeon_crtc_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, - int x, int y); + int x, int y, int enter); extern int radeon_crtc_do_set_base(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y, int atomic); -- cgit v1.2.3 From ff773714dd30b802c336064109c535d8b2774e2f Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Sun, 26 Sep 2010 06:47:26 -0500 Subject: radeon, kdb, kms: Save and restore the LUT on atomic KMS enter/exit When changing VTs non-atomically the kernel works in conjunction with the Xserver in user space and receives the LUT information from the Xserver via a system call. When changing modes atomically for kdb, this information must be saved and restored without disturbing user space as if nothing ever happened. Signed-off-by: Jason Wessel CC: Jesse Barnes CC: David Airlie CC: dri-devel@lists.freedesktop.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_display.c | 32 +++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 5 +++++ drivers/gpu/drm/radeon/radeon_mode.h | 3 +++ 3 files changed, 40 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index b92d2f2fcbed..26935cf2c3b3 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -138,6 +138,38 @@ void radeon_crtc_load_lut(struct drm_crtc *crtc) legacy_crtc_load_lut(crtc); } +void radeon_crtc_save_lut(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + int i; + + if (!crtc->enabled) + return; + + for (i = 0; i < 256; i++) { + radeon_crtc->lut_r_copy[i] = radeon_crtc->lut_r[i]; + radeon_crtc->lut_g_copy[i] = radeon_crtc->lut_g[i]; + radeon_crtc->lut_b_copy[i] = radeon_crtc->lut_b[i]; + } +} + +void radeon_crtc_restore_lut(struct drm_crtc *crtc) +{ + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + int i; + + if (!crtc->enabled) + return; + + for (i = 0; i < 256; i++) { + radeon_crtc->lut_r[i] = radeon_crtc->lut_r_copy[i]; + radeon_crtc->lut_g[i] = radeon_crtc->lut_g_copy[i]; + radeon_crtc->lut_b[i] = radeon_crtc->lut_b_copy[i]; + } + + radeon_crtc_load_lut(crtc); +} + /** Sets the color ramps on behalf of fbcon */ void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, int regno) diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 8752d3447b72..42954785247f 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -355,6 +355,11 @@ int radeon_crtc_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y, int enter) { + if (enter) + radeon_crtc_save_lut(crtc); + else + radeon_crtc_restore_lut(crtc); + return radeon_crtc_do_set_base(crtc, fb, x, y, 1); } diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index c4116d3d8d06..2f78615f02aa 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -267,6 +267,7 @@ struct radeon_crtc { struct drm_crtc base; int crtc_id; u16 lut_r[256], lut_g[256], lut_b[256]; + u16 lut_r_copy[256], lut_g_copy[256], lut_b_copy[256]; bool enabled; bool can_tile; uint32_t crtc_offset; @@ -512,6 +513,8 @@ extern int atombios_get_encoder_mode(struct drm_encoder *encoder); extern void radeon_encoder_set_active_device(struct drm_encoder *encoder); extern void radeon_crtc_load_lut(struct drm_crtc *crtc); +extern void radeon_crtc_save_lut(struct drm_crtc *crtc); +extern void radeon_crtc_restore_lut(struct drm_crtc *crtc); extern int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb); extern int atombios_crtc_set_base_atomic(struct drm_crtc *crtc, -- cgit v1.2.3 From a424d761a00c0233cb7734a8cd572ecd6d0362aa Mon Sep 17 00:00:00 2001 From: Chris Ball Date: Sun, 26 Sep 2010 06:47:27 -0500 Subject: drm/nouveau/kms: Avoid a hang entering KDB with VT accel on. Francisco Jerez advises that pre-nv20 cards would hang if we entered kdb with accel on and IRQs disabled, so we now disable accel before entering kdb and re-enable it on the way back out. Reported-by: Francisco Jerez Signed-off-by: Chris Ball Signed-off-by: Jason Wessel Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nv04_crtc.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/gpu/drm') diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index fb669dd39c3c..427f90e17b9d 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c @@ -33,6 +33,7 @@ #include "nouveau_fb.h" #include "nouveau_hw.h" #include "nvreg.h" +#include "nouveau_fbcon.h" static int nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, @@ -860,6 +861,14 @@ nv04_crtc_mode_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y, int enter) { + struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; + struct drm_device *dev = dev_priv->dev; + + if (enter) + nouveau_fbcon_save_disable_accel(dev); + else + nouveau_fbcon_restore_accel(dev); + return nv04_crtc_do_mode_set_base(crtc, fb, x, y, true); } -- cgit v1.2.3