summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/radeon
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2010-10-06 12:57:50 +1000
committerDave Airlie <airlied@redhat.com>2010-10-06 12:57:50 +1000
commit96a03fce54af40b4f0820cd729608bc32c9b8949 (patch)
tree91fbbaaacba4fe8562c5544460e99f3b09122e85 /drivers/gpu/drm/radeon
parent0c8eb0dc65f5a78b252eeff6c729ba4741390e23 (diff)
parenta424d761a00c0233cb7734a8cd572ecd6d0362aa (diff)
Merge branch 'drm-kdb-next' into drm-core-next
* drm-kdb-next: drm/nouveau/kms: Avoid a hang entering KDB with VT accel on. radeon, kdb, kms: Save and restore the LUT on atomic KMS enter/exit drm, kdb, kms: Add an enter argument to mode_set_base_atomic() API drm/nouveau/kms: Implement KDB debug hooks for nouveau KMS. drm/radeon/kms: Implement KDB debug hooks for radeon KMS.
Diffstat (limited to 'drivers/gpu/drm/radeon')
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c119
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c32
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_legacy_crtc.c50
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h13
5 files changed, 169 insertions, 47 deletions
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index cd0290f946cf..501e5286ec3f 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, int enter)
+{
+ 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_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_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..42954785247f 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
@@ -348,10 +348,30 @@ 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, 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);
+}
+
+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 +384,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 +442,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 +470,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 +523,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 +1067,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..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,8 +513,13 @@ 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,
+ struct drm_framebuffer *fb,
+ 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,
@@ -523,7 +529,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, int enter);
+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,