diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2009-03-10 18:21:31 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2009-03-10 18:22:42 +1000 |
commit | cce3eb4e26bb765303d177526d70517e56301d98 (patch) | |
tree | 53e7ee103d75c366b4ef18cdc3f3dfc5c4694bea | |
parent | 16122cb1d9e4ec8eb21de69b3b66a83b8777a6f0 (diff) |
drm/nv50: assorted kms fixes/cleanups
-rw-r--r-- | linux-core/nouveau_crtc.h | 5 | ||||
-rw-r--r-- | linux-core/nv50_connector.c | 1 | ||||
-rw-r--r-- | linux-core/nv50_crtc.c | 155 | ||||
-rw-r--r-- | linux-core/nv50_cursor.c | 24 | ||||
-rw-r--r-- | linux-core/nv50_cursor.h | 4 | ||||
-rw-r--r-- | linux-core/nv50_display_commands.h | 13 | ||||
-rw-r--r-- | linux-core/nv50_sor.c | 1 |
7 files changed, 108 insertions, 95 deletions
diff --git a/linux-core/nouveau_crtc.h b/linux-core/nouveau_crtc.h index 0ba94756..c65994f0 100644 --- a/linux-core/nouveau_crtc.h +++ b/linux-core/nouveau_crtc.h @@ -37,7 +37,12 @@ struct nouveau_crtc { struct drm_display_mode *mode; bool use_dithering; + struct { + uint32_t offset; + } fb; + struct nv50_cursor *cursor; + struct { struct mem_block *mem; uint16_t r[256]; diff --git a/linux-core/nv50_connector.c b/linux-core/nv50_connector.c index dd404734..2c6952b8 100644 --- a/linux-core/nv50_connector.c +++ b/linux-core/nv50_connector.c @@ -385,7 +385,6 @@ nv50_connector_native_mode(struct nouveau_connector *connector) return NULL; list_for_each_entry(mode, &connector->base.probed_modes, head) { - DRM_INFO("%d %d 0x%08x\n", mode->hdisplay, mode->vdisplay, mode->type); if (mode->type & DRM_MODE_TYPE_PREFERRED) return drm_mode_duplicate(dev, mode); } diff --git a/linux-core/nv50_crtc.c b/linux-core/nv50_crtc.c index efd3b9cf..8d410b00 100644 --- a/linux-core/nv50_crtc.c +++ b/linux-core/nv50_crtc.c @@ -95,33 +95,34 @@ nv50_crtc_blank(struct nouveau_crtc *crtc, bool blanked) DRM_DEBUG("%s\n", blanked ? "blanked" : "unblanked"); if (blanked) { - crtc->cursor->hide(crtc); + crtc->cursor->hide(crtc, false); OUT_MODE(NV50_CRTC0_CLUT_MODE + offset, NV50_CRTC0_CLUT_MODE_BLANK); + OUT_MODE(NV50_CRTC0_CLUT_OFFSET + offset, 0); if (dev_priv->chipset != 0x50) - OUT_MODE(NV84_CRTC0_BLANK_UNK1 + offset, - NV84_CRTC0_BLANK_UNK1_BLANK); + OUT_MODE(NV84_CRTC0_CLUT_DMA + offset, + NV84_CRTC0_CLUT_DMA_DISABLE); + OUT_MODE(NV50_CRTC0_BLANK_CTRL + offset, NV50_CRTC0_BLANK_CTRL_BLANK); - if (dev_priv->chipset != 0x50) - OUT_MODE(NV84_CRTC0_BLANK_UNK2 + offset, - NV84_CRTC0_BLANK_UNK2_BLANK); } else { crtc->cursor->set_offset(crtc); - - if (dev_priv->chipset != 0x50) - OUT_MODE(NV84_CRTC0_BLANK_UNK2 + offset, - NV84_CRTC0_BLANK_UNK2_UNBLANK); - if (crtc->cursor->visible) - crtc->cursor->show(crtc); + crtc->cursor->show(crtc, false); else - crtc->cursor->hide(crtc); + crtc->cursor->hide(crtc, false); + OUT_MODE(NV50_CRTC0_CLUT_MODE + offset, crtc->lut.depth == 8 ? + NV50_CRTC0_CLUT_MODE_OFF : NV50_CRTC0_CLUT_MODE_ON); + OUT_MODE(NV50_CRTC0_CLUT_OFFSET + offset, + crtc->lut.mem->start >> 8); if (dev_priv->chipset != 0x50) - OUT_MODE(NV84_CRTC0_BLANK_UNK1 + offset, - NV84_CRTC0_BLANK_UNK1_UNBLANK); + OUT_MODE(NV84_CRTC0_CLUT_DMA + offset, + NV84_CRTC0_CLUT_DMA_LOCAL); + + OUT_MODE(NV50_CRTC0_FB_OFFSET + offset, crtc->fb.offset >> 8); + OUT_MODE(0x864 + offset, 0); OUT_MODE(NV50_CRTC0_BLANK_CTRL + offset, NV50_CRTC0_BLANK_CTRL_UNBLANK); } @@ -444,13 +445,12 @@ static int nv50_crtc_cursor_set(struct drm_crtc *drm_crtc, crtc->cursor->set_bo(crtc, gem); crtc->cursor->set_offset(crtc); - ret = crtc->cursor->show(crtc); + ret = crtc->cursor->show(crtc, true); } else { crtc->cursor->set_bo(crtc, NULL); - crtc->cursor->hide(crtc); + crtc->cursor->hide(crtc, true); } - OUT_MODE(NV50_UPDATE_DISPLAY, 0); return ret; } @@ -525,6 +525,9 @@ static void nv50_crtc_prepare(struct drm_crtc *drm_crtc) static void nv50_crtc_commit(struct drm_crtc *drm_crtc) { + struct nouveau_crtc *crtc = to_nouveau_crtc(drm_crtc); + + nv50_crtc_blank(crtc, false); } static bool nv50_crtc_mode_fixup(struct drm_crtc *drm_crtc, @@ -534,35 +537,67 @@ static bool nv50_crtc_mode_fixup(struct drm_crtc *drm_crtc, return true; } -static int -nv50_crtc_execute_mode(struct nouveau_crtc *crtc, struct drm_display_mode *mode) +static void +nv50_crtc_mode_set(struct drm_crtc *drm_crtc, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, int x, int y) { - struct drm_device *dev = crtc->base.dev; + struct drm_device *dev = drm_crtc->dev; + struct nouveau_crtc *crtc = to_nouveau_crtc(drm_crtc); + struct drm_encoder *drm_encoder; + struct nouveau_encoder *encoder; + struct drm_crtc_helper_funcs *crtc_helper = drm_crtc->helper_private; + struct nouveau_connector *connector = NULL; uint32_t hsync_dur, vsync_dur, hsync_start_to_end, vsync_start_to_end; uint32_t hunk1, vunk1, vunk2a, vunk2b; uint32_t offset = crtc->index * 0x400; + /* Find the connector attached to this CRTC */ + list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) { + struct drm_connector *drm_connector; + + encoder = to_nouveau_encoder(drm_encoder); + if (drm_encoder->crtc != &crtc->base) + continue; + + list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) { + connector = to_nouveau_connector(drm_connector); + if (drm_connector->encoder != drm_encoder) + continue; + + break; + } + + break; /* no use in finding more than one mode */ + } + + *crtc->mode = *adjusted_mode; + crtc->use_dithering = connector->use_dithering; + DRM_DEBUG("index %d\n", crtc->index); - hsync_dur = mode->hsync_end - mode->hsync_start; - vsync_dur = mode->vsync_end - mode->vsync_start; - hsync_start_to_end = mode->htotal - mode->hsync_start; - vsync_start_to_end = mode->vtotal - mode->vsync_start; + hsync_dur = adjusted_mode->hsync_end - adjusted_mode->hsync_start; + vsync_dur = adjusted_mode->vsync_end - adjusted_mode->vsync_start; + hsync_start_to_end = adjusted_mode->htotal - adjusted_mode->hsync_start; + vsync_start_to_end = adjusted_mode->vtotal - adjusted_mode->vsync_start; /* I can't give this a proper name, anyone else can? */ - hunk1 = mode->htotal - mode->hsync_start + mode->hdisplay; - vunk1 = mode->vtotal - mode->vsync_start + mode->vdisplay; - /* Another strange value, this time only for interlaced modes. */ - vunk2a = 2*mode->vtotal - mode->vsync_start + mode->vdisplay; - vunk2b = mode->vtotal - mode->vsync_start + mode->vtotal; - - if (mode->flags & DRM_MODE_FLAG_INTERLACE) { + hunk1 = adjusted_mode->htotal - + adjusted_mode->hsync_start + adjusted_mode->hdisplay; + vunk1 = adjusted_mode->vtotal - + adjusted_mode->vsync_start + adjusted_mode->vdisplay; + /* Another strange value, this time only for interlaced adjusted_modes. */ + vunk2a = 2 * adjusted_mode->vtotal - + adjusted_mode->vsync_start + adjusted_mode->vdisplay; + vunk2b = adjusted_mode->vtotal - + adjusted_mode->vsync_start + adjusted_mode->vtotal; + + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { vsync_dur /= 2; vsync_start_to_end /= 2; vunk1 /= 2; vunk2a /= 2; vunk2b /= 2; /* magic */ - if (mode->flags & DRM_MODE_FLAG_DBLSCAN) { + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) { vsync_start_to_end -= 1; vunk1 -= 1; vunk2a -= 1; @@ -570,20 +605,20 @@ nv50_crtc_execute_mode(struct nouveau_crtc *crtc, struct drm_display_mode *mode) } } - OUT_MODE(NV50_CRTC0_CLOCK + offset, mode->clock | 0x800000); + OUT_MODE(NV50_CRTC0_CLOCK + offset, adjusted_mode->clock | 0x800000); OUT_MODE(NV50_CRTC0_INTERLACE + offset, - (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 0); + (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 0); OUT_MODE(NV50_CRTC0_DISPLAY_START + offset, 0); OUT_MODE(NV50_CRTC0_UNK82C + offset, 0); OUT_MODE(NV50_CRTC0_DISPLAY_TOTAL + offset, - mode->vtotal << 16 | mode->htotal); + adjusted_mode->vtotal << 16 | adjusted_mode->htotal); OUT_MODE(NV50_CRTC0_SYNC_DURATION + offset, (vsync_dur - 1) << 16 | (hsync_dur - 1)); OUT_MODE(NV50_CRTC0_SYNC_START_TO_BLANK_END + offset, (vsync_start_to_end - 1) << 16 | (hsync_start_to_end - 1)); OUT_MODE(NV50_CRTC0_MODE_UNK1 + offset, (vunk1 - 1) << 16 | (hunk1 - 1)); - if (mode->flags & DRM_MODE_FLAG_INTERLACE) { + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { OUT_MODE(NV50_CRTC0_MODE_UNK2 + offset, (vunk2b - 1) << 16 | (vunk2a - 1)); } @@ -597,44 +632,7 @@ nv50_crtc_execute_mode(struct nouveau_crtc *crtc, struct drm_display_mode *mode) NV50_CRTC_SCALE_CENTER_OFFSET_VAL(0,0)); nv50_crtc_blank(crtc, false); - return 0; -} - - -static void -nv50_crtc_mode_set(struct drm_crtc *drm_crtc, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, int x, int y) -{ - struct drm_device *dev = drm_crtc->dev; - struct nouveau_crtc *crtc = to_nouveau_crtc(drm_crtc); - struct drm_encoder *drm_encoder; - struct nouveau_encoder *encoder; - struct drm_crtc_helper_funcs *crtc_helper = drm_crtc->helper_private; - struct nouveau_connector *connector = NULL; - - /* Find the connector attached to this CRTC */ - list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) { - struct drm_connector *drm_connector; - encoder = to_nouveau_encoder(drm_encoder); - if (drm_encoder->crtc != &crtc->base) - continue; - - list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) { - connector = to_nouveau_connector(drm_connector); - if (drm_connector->encoder != drm_encoder) - continue; - - break; - } - - break; /* no use in finding more than one mode */ - } - - *crtc->mode = *adjusted_mode; - crtc->use_dithering = connector->use_dithering; - - nv50_crtc_execute_mode(crtc, adjusted_mode); crtc->set_scale(crtc, connector->scaling_mode, false); crtc_helper->mode_set_base(drm_crtc, x, y); } @@ -648,10 +646,11 @@ nv50_crtc_mode_set_base(struct drm_crtc *drm_crtc, int x, int y) struct drm_framebuffer *drm_fb = crtc->base.fb; struct nouveau_framebuffer *fb = to_nouveau_framebuffer(drm_fb); struct nouveau_gem_object *ngem = nouveau_gem_object(fb->gem); - uint32_t v_vram = ngem->bo->offset - dev_priv->vm_vram_base; uint32_t offset = crtc->index * 0x400; - OUT_MODE(NV50_CRTC0_FB_OFFSET + offset, v_vram >> 8); + crtc->fb.offset = ngem->bo->offset - dev_priv->vm_vram_base; + + OUT_MODE(NV50_CRTC0_FB_OFFSET + offset, crtc->fb.offset >> 8); OUT_MODE(0x864 + offset, 0); OUT_MODE(NV50_CRTC0_FB_SIZE + offset, @@ -684,10 +683,6 @@ nv50_crtc_mode_set_base(struct drm_crtc *drm_crtc, int x, int y) nv50_crtc_lut_load(crtc); } - OUT_MODE(NV50_CRTC0_CLUT_MODE + offset, fb->base.depth == 8 ? - NV50_CRTC0_CLUT_MODE_OFF : NV50_CRTC0_CLUT_MODE_ON); - OUT_MODE(NV50_CRTC0_CLUT_OFFSET + offset, crtc->lut.mem->start >> 8); - OUT_MODE(NV50_UPDATE_DISPLAY, 0); } diff --git a/linux-core/nv50_cursor.c b/linux-core/nv50_cursor.c index fca5b4a4..10736de6 100644 --- a/linux-core/nv50_cursor.c +++ b/linux-core/nv50_cursor.c @@ -84,8 +84,9 @@ static int nv50_cursor_disable(struct nouveau_crtc *crtc) } /* Calling update or changing the stored cursor state is left to the higher level ioctl's. */ -static int nv50_cursor_show(struct nouveau_crtc *crtc) +static int nv50_cursor_show(struct nouveau_crtc *crtc, bool update) { + struct drm_nouveau_private *dev_priv = crtc->base.dev->dev_private; struct drm_device *dev = crtc->base.dev; uint32_t offset = crtc->index * 0x400; @@ -98,22 +99,37 @@ static int nv50_cursor_show(struct nouveau_crtc *crtc) return -EINVAL; } + if (dev_priv->chipset != 0x50) + OUT_MODE(NV84_CRTC0_CURSOR_DMA + offset, + NV84_CRTC0_CURSOR_DMA_LOCAL); OUT_MODE(NV50_CRTC0_CURSOR_CTRL + offset, NV50_CRTC0_CURSOR_CTRL_SHOW); + + if (update) { + OUT_MODE(NV50_UPDATE_DISPLAY, 0); + crtc->cursor->visible = true; + } - crtc->cursor->visible = true; return 0; } -static int nv50_cursor_hide(struct nouveau_crtc *crtc) +static int nv50_cursor_hide(struct nouveau_crtc *crtc, bool update) { + struct drm_nouveau_private *dev_priv = crtc->base.dev->dev_private; struct drm_device *dev = crtc->base.dev; uint32_t offset = crtc->index * 0x400; DRM_DEBUG("\n"); OUT_MODE(NV50_CRTC0_CURSOR_CTRL + offset, NV50_CRTC0_CURSOR_CTRL_HIDE); + if (dev_priv->chipset != 0x50) + OUT_MODE(NV84_CRTC0_CURSOR_DMA + offset, + NV84_CRTC0_CURSOR_DMA_DISABLE); + + if (update) { + OUT_MODE(NV50_UPDATE_DISPLAY, 0); + crtc->cursor->visible = false; + } - crtc->cursor->visible = false; return 0; } diff --git a/linux-core/nv50_cursor.h b/linux-core/nv50_cursor.h index 9be1591a..089a69c9 100644 --- a/linux-core/nv50_cursor.h +++ b/linux-core/nv50_cursor.h @@ -32,8 +32,8 @@ struct nv50_cursor { int x, y; bool visible; - int (*show) (struct nouveau_crtc *crtc); - int (*hide) (struct nouveau_crtc *crtc); + int (*show) (struct nouveau_crtc *crtc, bool update); + int (*hide) (struct nouveau_crtc *crtc, bool update); int (*set_pos) (struct nouveau_crtc *crtc, int x, int y); int (*set_offset) (struct nouveau_crtc *crtc); int (*set_bo) (struct nouveau_crtc *crtc, struct drm_gem_object *gem); diff --git a/linux-core/nv50_display_commands.h b/linux-core/nv50_display_commands.h index 97b3d3c1..4fd10c96 100644 --- a/linux-core/nv50_display_commands.h +++ b/linux-core/nv50_display_commands.h @@ -75,10 +75,9 @@ #define NV50_CRTC0_CLUT_MODE_ON 0xC0000000 #define NV50_CRTC0_CLUT_OFFSET 0x844 -/* Anyone know what part of the chip is triggered here precisely? */ -#define NV84_CRTC0_BLANK_UNK1 0x85C - #define NV84_CRTC0_BLANK_UNK1_BLANK 0x0 - #define NV84_CRTC0_BLANK_UNK1_UNBLANK 0x1 +#define NV84_CRTC0_CLUT_DMA 0x85C + #define NV84_CRTC0_CLUT_DMA_DISABLE 0x0 + #define NV84_CRTC0_CLUT_DMA_LOCAL 0x1 #define NV50_CRTC0_FB_OFFSET 0x860 @@ -105,9 +104,9 @@ #define NV50_CRTC0_CURSOR_OFFSET 0x884 /* Anyone know what part of the chip is triggered here precisely? */ -#define NV84_CRTC0_BLANK_UNK2 0x89C - #define NV84_CRTC0_BLANK_UNK2_BLANK 0x0 - #define NV84_CRTC0_BLANK_UNK2_UNBLANK 0x1 +#define NV84_CRTC0_CURSOR_DMA 0x89C + #define NV84_CRTC0_CURSOR_DMA_DISABLE 0x0 + #define NV84_CRTC0_CURSOR_DMA_LOCAL 0x1 #define NV50_CRTC0_DITHERING_CTRL 0x8A0 #define NV50_CRTC0_DITHERING_CTRL_ON 0x11 diff --git a/linux-core/nv50_sor.c b/linux-core/nv50_sor.c index fd29ffc9..a147fb66 100644 --- a/linux-core/nv50_sor.c +++ b/linux-core/nv50_sor.c @@ -44,7 +44,6 @@ nv50_sor_disconnect(struct nouveau_encoder *encoder) DRM_DEBUG("Disconnecting SOR %d\n", encoder->or); OUT_MODE(NV50_SOR0_MODE_CTRL + offset, NV50_SOR_MODE_CTRL_OFF); - OUT_MODE(NV50_UPDATE_DISPLAY, 0); } static int |