diff options
-rw-r--r-- | linux-core/nv50_crtc.c | 10 | ||||
-rw-r--r-- | linux-core/nv50_crtc.h | 1 | ||||
-rw-r--r-- | linux-core/nv50_cursor.c | 18 | ||||
-rw-r--r-- | linux-core/nv50_cursor.h | 1 | ||||
-rw-r--r-- | shared-core/nouveau_mem.c | 29 |
5 files changed, 54 insertions, 5 deletions
diff --git a/linux-core/nv50_crtc.c b/linux-core/nv50_crtc.c index 0bcf3058..af2f03d8 100644 --- a/linux-core/nv50_crtc.c +++ b/linux-core/nv50_crtc.c @@ -192,10 +192,9 @@ static int nv50_crtc_blank(struct nv50_crtc *crtc, bool blanked) } else { OUT_MODE(NV50_CRTC0_FB_OFFSET + offset, crtc->fb->block->start >> 8); OUT_MODE(0x864 + offset, 0); - if (crtc->cursor->block) - OUT_MODE(NV50_CRTC0_CURSOR_OFFSET + offset, crtc->cursor->block->start >> 8); - else - OUT_MODE(NV50_CRTC0_CURSOR_OFFSET + offset, 0); + + crtc->cursor->set_offset(crtc); + if (dev_priv->chipset != 0x50) OUT_MODE(NV84_CRTC0_BLANK_UNK2 + offset, NV84_CRTC0_BLANK_UNK2_UNBLANK); @@ -212,6 +211,9 @@ static int nv50_crtc_blank(struct nv50_crtc *crtc, bool blanked) OUT_MODE(NV50_CRTC0_BLANK_CTRL + offset, NV50_CRTC0_BLANK_CTRL_UNBLANK); } + /* sometimes you need to know if a screen is already blanked. */ + crtc->blanked = blanked; + return 0; } diff --git a/linux-core/nv50_crtc.h b/linux-core/nv50_crtc.h index 0eadc3d4..b63c5a22 100644 --- a/linux-core/nv50_crtc.h +++ b/linux-core/nv50_crtc.h @@ -39,6 +39,7 @@ struct nv50_crtc { struct drm_device *dev; int index; bool active; + bool blanked; struct nouveau_hw_mode *mode; struct nouveau_hw_mode *native_mode; diff --git a/linux-core/nv50_cursor.c b/linux-core/nv50_cursor.c index 47ae11bb..091c94fe 100644 --- a/linux-core/nv50_cursor.c +++ b/linux-core/nv50_cursor.c @@ -103,6 +103,21 @@ static int nv50_cursor_set_pos(struct nv50_crtc *crtc, int x, int y) return 0; } +static int nv50_cursor_set_offset(struct nv50_crtc *crtc) +{ + struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; + + NV50_DEBUG("\n"); + + if (crtc->cursor->block) { + OUT_MODE(NV50_CRTC0_CURSOR_OFFSET + crtc->index * 0x400, crtc->cursor->block->start >> 8); + } else { + OUT_MODE(NV50_CRTC0_CURSOR_OFFSET + crtc->index * 0x400, 0); + } + + return 0; +} + static int nv50_cursor_set_bo(struct nv50_crtc *crtc, drm_handle_t handle) { struct mem_block *block = NULL; @@ -121,7 +136,7 @@ static int nv50_cursor_set_bo(struct nv50_crtc *crtc, drm_handle_t handle) /* set the cursor offset cursor */ if (first_time) { - OUT_MODE(NV50_CRTC0_CURSOR_OFFSET + crtc->index * 0x400, crtc->cursor->block->start >> 8); + crtc->cursor->set_offset(crtc); if (crtc->cursor->visible) crtc->cursor->show(crtc); } @@ -148,6 +163,7 @@ int nv50_cursor_create(struct nv50_crtc *crtc) crtc->cursor->show = nv50_cursor_show; crtc->cursor->hide = nv50_cursor_hide; crtc->cursor->set_pos = nv50_cursor_set_pos; + crtc->cursor->set_offset = nv50_cursor_set_offset; crtc->cursor->set_bo = nv50_cursor_set_bo; crtc->cursor->enable = nv50_cursor_enable; crtc->cursor->disable = nv50_cursor_disable; diff --git a/linux-core/nv50_cursor.h b/linux-core/nv50_cursor.h index a2e4632c..4fd0d39a 100644 --- a/linux-core/nv50_cursor.h +++ b/linux-core/nv50_cursor.h @@ -40,6 +40,7 @@ struct nv50_cursor { int (*show) (struct nv50_crtc *crtc); int (*hide) (struct nv50_crtc *crtc); int (*set_pos) (struct nv50_crtc *crtc, int x, int y); + int (*set_offset) (struct nv50_crtc *crtc); int (*set_bo) (struct nv50_crtc *crtc, drm_handle_t handle); int (*enable) (struct nv50_crtc *crtc); int (*disable) (struct nv50_crtc *crtc); diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c index 51ac48dd..4acd6bd6 100644 --- a/shared-core/nouveau_mem.c +++ b/shared-core/nouveau_mem.c @@ -34,6 +34,8 @@ #include "drm.h" #include "drm_sarea.h" #include "nouveau_drv.h" +#include "nv50_kms_wrapper.h" + static struct mem_block * split_block(struct mem_block *p, uint64_t start, uint64_t size, @@ -730,6 +732,33 @@ void nouveau_mem_free(struct drm_device* dev, struct mem_block* block) DRM_DEBUG("freeing 0x%llx type=0x%08x\n", block->start, block->flags); + /* Check if the deallocations cause problems for our modesetting system. */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + if (dev_priv->card_type >= NV_50) { + struct nv50_crtc *crtc = NULL; + struct nv50_display *display = nv50_get_display(dev); + + list_for_each_entry(crtc, &display->crtcs, head) { + if (crtc->fb->block == block) { + crtc->fb->block = NULL; + + /* this will force a lut change next time a fb is loaded */ + crtc->lut->depth = 0; + + if (!crtc->blanked) + crtc->blank(crtc, TRUE); + } + + if (crtc->cursor->block == block) { + crtc->cursor->block = NULL; + + if (crtc->cursor->visible) + crtc->cursor->hide(crtc); + } + } + } + } + if (block->flags&NOUVEAU_MEM_MAPPED) drm_rmmap(dev, block->map); |