NV50: Improve set_config and fix some minor bugs.
authorMaarten Maathuis <madman2003@gmail.com>
Mon, 23 Jun 2008 18:33:32 +0000 (20:33 +0200)
committerMaarten Maathuis <madman2003@gmail.com>
Mon, 23 Jun 2008 18:33:32 +0000 (20:33 +0200)
linux-core/nv50_crtc.c
linux-core/nv50_crtc.h
linux-core/nv50_display.c
linux-core/nv50_fb.c
linux-core/nv50_fb.h
linux-core/nv50_kms_wrapper.c
linux-core/nv50_sor.c

index 887d6ec..0bcf305 100644 (file)
@@ -72,7 +72,6 @@ static int nv50_crtc_execute_mode(struct nv50_crtc *crtc)
        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;
-       uint32_t pitch;
 
        NV50_DEBUG("index %d\n", crtc->index);
        NV50_DEBUG("%s native mode\n", crtc->use_native_mode ? "using" : "not using");
@@ -119,12 +118,31 @@ static int nv50_crtc_execute_mode(struct nv50_crtc *crtc)
        if (hw_mode->flags & V_INTERLACE) {
                OUT_MODE(NV50_CRTC0_MODE_UNK2 + offset, (vunk2b - 1) << 16 | (vunk2a - 1));
        }
+
+       crtc->set_fb(crtc);
+       crtc->set_dither(crtc);
+
+       /* This is the actual resolution of the mode. */
+       OUT_MODE(NV50_CRTC0_REAL_RES + offset, (crtc->mode->vdisplay << 16) | crtc->mode->hdisplay);
+       OUT_MODE(NV50_CRTC0_SCALE_CENTER_OFFSET + offset, NV50_CRTC_SCALE_CENTER_OFFSET_VAL(0,0));
+
+       /* Maybe move this as well? */
+       crtc->blank(crtc, FALSE);
+
+       return 0;
+}
+
+static int nv50_crtc_set_fb(struct nv50_crtc *crtc)
+{
+       struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
+       uint32_t offset = crtc->index * 0x400;
+
+       NV50_DEBUG("\n");
+
        OUT_MODE(NV50_CRTC0_FB_SIZE + offset, crtc->fb->height << 16 | crtc->fb->width);
 
        /* I suspect this flag indicates a linear fb. */
-       pitch = ((crtc->fb->width + 63) & ~63) * (crtc->fb->bpp)/8;
-       NV50_DEBUG("fb_pitch %d\n", pitch);
-       OUT_MODE(NV50_CRTC0_FB_PITCH + offset, pitch | 0x100000);
+       OUT_MODE(NV50_CRTC0_FB_PITCH + offset, crtc->fb->pitch | 0x100000);
 
        switch (crtc->fb->depth) {
                case 8:
@@ -140,15 +158,9 @@ static int nv50_crtc_execute_mode(struct nv50_crtc *crtc)
                        OUT_MODE(NV50_CRTC0_DEPTH + offset, NV50_CRTC0_DEPTH_24BPP); 
                        break;
        }
-       crtc->set_dither(crtc);
+
        OUT_MODE(NV50_CRTC0_COLOR_CTRL + offset, NV50_CRTC_COLOR_CTRL_MODE_COLOR);
        OUT_MODE(NV50_CRTC0_FB_POS + offset, (crtc->fb->y << 16) | (crtc->fb->x));
-       /* This is the actual resolution of the mode. */
-       OUT_MODE(NV50_CRTC0_REAL_RES + offset, (crtc->mode->vdisplay << 16) | crtc->mode->hdisplay);
-       OUT_MODE(NV50_CRTC0_SCALE_CENTER_OFFSET + offset, NV50_CRTC_SCALE_CENTER_OFFSET_VAL(0,0));
-
-       /* Maybe move this as well? */
-       crtc->blank(crtc, FALSE);
 
        return 0;
 }
@@ -178,20 +190,8 @@ static int nv50_crtc_blank(struct nv50_crtc *crtc, bool blanked)
                if (dev_priv->chipset != 0x50)
                        OUT_MODE(NV84_CRTC0_BLANK_UNK2 + offset, NV84_CRTC0_BLANK_UNK2_BLANK);
        } else {
-               uint32_t ram_amount;
-
                OUT_MODE(NV50_CRTC0_FB_OFFSET + offset, crtc->fb->block->start >> 8);
                OUT_MODE(0x864 + offset, 0);
-               /* maybe this needs to be moved. */
-               NV_WRITE(NV50_PDISPLAY_UNK_380, 0);
-               /* RAM is clamped to 256 MiB. */
-               ram_amount = nouveau_mem_fb_amount(crtc->dev);
-               NV50_DEBUG("ram_amount %d\n", ram_amount);
-               if (ram_amount > 256*1024*1024)
-                       ram_amount = 256*1024*1024;
-               NV_WRITE(NV50_PDISPLAY_RAM_AMOUNT, ram_amount - 1);
-               NV_WRITE(NV50_PDISPLAY_UNK_388, 0x150000);
-               NV_WRITE(NV50_PDISPLAY_UNK_38C, 0);
                if (crtc->cursor->block)
                        OUT_MODE(NV50_CRTC0_CURSOR_OFFSET + offset, crtc->cursor->block->start >> 8);
                else
@@ -502,6 +502,7 @@ int nv50_crtc_create(struct drm_device *dev, int index)
        crtc->validate_mode = nv50_crtc_validate_mode;
        crtc->set_mode = nv50_crtc_set_mode;
        crtc->execute_mode = nv50_crtc_execute_mode;
+       crtc->set_fb = nv50_crtc_set_fb;
        crtc->blank = nv50_crtc_blank;
        crtc->set_dither = nv50_crtc_set_dither;
        crtc->set_scale = nv50_crtc_set_scale;
index 5eb815a..0eadc3d 100644 (file)
@@ -54,6 +54,7 @@ struct nv50_crtc {
        int (*validate_mode) (struct nv50_crtc *crtc, struct nouveau_hw_mode *mode);
        int (*set_mode) (struct nv50_crtc *crtc, struct nouveau_hw_mode *mode);
        int (*execute_mode) (struct nv50_crtc *crtc);
+       int (*set_fb) (struct nv50_crtc *crtc);
        int (*blank) (struct nv50_crtc *crtc, bool blanked);
        int (*set_dither) (struct nv50_crtc *crtc);
        int (*set_scale) (struct nv50_crtc *crtc);
index 05ff72f..0c82ff8 100644 (file)
@@ -34,6 +34,7 @@ static int nv50_display_pre_init(struct nv50_display *display)
        struct drm_device *dev = display->dev;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        int i;
+       uint32_t ram_amount;
 
        NV50_DEBUG("\n");
 
@@ -67,6 +68,17 @@ static int nv50_display_pre_init(struct nv50_display *display)
                NV_WRITE(NV50_PDISPLAY_DAC_REGS_CLK_CTRL1(i), 0x00000001);
        }
 
+       /* This used to be in crtc unblank, but seems out of place there. */
+       NV_WRITE(NV50_PDISPLAY_UNK_380, 0);
+       /* RAM is clamped to 256 MiB. */
+       ram_amount = nouveau_mem_fb_amount(display->dev);
+       NV50_DEBUG("ram_amount %d\n", ram_amount);
+       if (ram_amount > 256*1024*1024)
+               ram_amount = 256*1024*1024;
+       NV_WRITE(NV50_PDISPLAY_RAM_AMOUNT, ram_amount - 1);
+       NV_WRITE(NV50_PDISPLAY_UNK_388, 0x150000);
+       NV_WRITE(NV50_PDISPLAY_UNK_38C, 0);
+
        display->preinit_done = TRUE;
 
        return 0;
index f57a9fa..153899d 100644 (file)
@@ -40,8 +40,9 @@ static int nv50_fb_bind(struct nv50_crtc *crtc, struct nv50_fb_info *info)
                return -EINVAL;
        }
 
-       if (!info->block || !info->width || !info->height || !info->depth || !info->bpp) {
-               DRM_ERROR("block %p width %d height %d depth %d bpp %d\n", info->block, info->width, info->height, info->depth, info->bpp);
+       if (!info->block || !info->width || !info->height || !info->depth || !info->bpp || !info->pitch) {
+               DRM_ERROR("block %p width %d height %d depth %d bpp %d pitch %d\n", info->block, info->width, 
+                       info->height, info->depth, info->bpp, info->pitch);
                return -EINVAL;
        }
 
@@ -55,6 +56,8 @@ static int nv50_fb_bind(struct nv50_crtc *crtc, struct nv50_fb_info *info)
        crtc->fb->depth = info->depth;
        crtc->fb->bpp = info->bpp;
 
+       crtc->fb->pitch = info->pitch;
+
        /* update lut if needed */
        if (crtc->fb->depth != crtc->lut->depth) {
                int r_size = 0, g_size = 0, b_size = 0;
index 6b28631..3051dc5 100644 (file)
@@ -35,6 +35,7 @@ struct nv50_fb_info {
        struct mem_block *block;
        int width, height;
        int bpp, depth;
+       int pitch;
        int x,y;
 };
 
@@ -42,6 +43,7 @@ struct nv50_fb {
        struct mem_block *block;
        int width, height;
        int bpp, depth;
+       int pitch;
 
        int x,y;
 
index a63cb7d..e93a266 100644 (file)
@@ -284,12 +284,17 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set)
        struct nouveau_hw_mode *hw_mode = NULL;
        struct nv50_fb_info fb_info;
 
+       bool blank = false;
+       bool switch_fb = false;
+       bool modeset = false;
+
        NV50_DEBUG("\n");
 
        /*
-        * Initial approach is very simple, always set a mode.
-        * Always bail out completely if something is wrong.
-        * Later this could be extended to be more smart.
+        * Supported operations:
+        * - Switch mode.
+        * - Switch framebuffer.
+        * - Blank screen.
         */
 
        /* Sanity checking */
@@ -298,138 +303,200 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set)
                goto out;
        }
 
-       if (!set->crtc || !set->fb || !set->mode || !set->connectors) {
+       if (!set->crtc || !set->connectors) {
                NV50_DEBUG("Sanity check failed\n");
                goto out;
        }
 
+       if (set->mode) {
+               if (set->fb) {
+                       if (!drm_mode_equal(set->mode, &set->crtc->mode))
+                               modeset = true;
+
+                       if (set->fb != set->crtc->fb)
+                               switch_fb = true;
+
+                       if (set->x != set->crtc->x || set->y != set->crtc->y)
+                               switch_fb = true;
+               }
+       } else {
+               blank = true;
+       }
+
+       if (!modeset && !switch_fb && !blank) {
+               DRM_ERROR("There is nothing to do, bad input.\n");
+               goto out;
+       }
+
        /* Basic variable setting */
        dev = set->crtc->dev;
        dev_priv = dev->dev_private;
        display = nv50_get_display(dev);
        crtc = to_nv50_crtc(set->crtc);
 
-       /* Mode validation */
-       hw_mode = nv50_kms_to_hw_mode(set->mode);
-
-       rval = crtc->validate_mode(crtc, hw_mode);
-
-       if (rval != MODE_OK) {
-               NV50_DEBUG("Mode not ok\n");
-               goto out;
-       }
+       /**
+        * Wiring up the encoders and connectors.
+        */
 
-       for (i = 0; i < set->num_connectors; i++) {
-               drm_connector = set->connectors[i];
-               if (!drm_connector) {
-                       NV50_DEBUG("No connector\n");
-                       goto out;
-               }
-               connector = to_nv50_connector(drm_connector);
+       if (modeset) {
+               /* Mode validation */
+               hw_mode = nv50_kms_to_hw_mode(set->mode);
 
-               output = connector->to_output(connector, connector->digital);
-               if (!output) {
-                       NV50_DEBUG("No output\n");
-                       goto out;
-               }
+               rval = crtc->validate_mode(crtc, hw_mode);
 
-               rval = output->validate_mode(output, hw_mode);
                if (rval != MODE_OK) {
                        NV50_DEBUG("Mode not ok\n");
                        goto out;
                }
-       }
 
-       /* Validation done, move on to cleaning of existing structures. */
+               for (i = 0; i < set->num_connectors; i++) {
+                       drm_connector = set->connectors[i];
+                       if (!drm_connector) {
+                               NV50_DEBUG("No connector\n");
+                               goto out;
+                       }
+                       connector = to_nv50_connector(drm_connector);
 
-       /* find encoders that use this crtc. */
-       list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) {
-               if (drm_encoder->crtc == set->crtc) {
-                       /* find the connector that goes with it */
-                       list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) {
-                               if (drm_connector->encoder == drm_encoder) {
-                                       drm_connector->encoder =  NULL;
-                                       break;
-                               }
+                       output = connector->to_output(connector, connector->digital);
+                       if (!output) {
+                               NV50_DEBUG("No output\n");
+                               goto out;
                        }
-                       drm_encoder->crtc = NULL;
-               }
-       }
 
-       /* now find if our desired encoders or connectors are in use already. */
-       for (i = 0; i < set->num_connectors; i++) {
-               drm_connector = set->connectors[i];
-               if (!drm_connector) {
-                       NV50_DEBUG("No connector\n");
-                       goto out;
+                       rval = output->validate_mode(output, hw_mode);
+                       if (rval != MODE_OK) {
+                               NV50_DEBUG("Mode not ok\n");
+                               goto out;
+                       }
                }
 
-               if (!drm_connector->encoder)
-                       continue;
+               /* Validation done, move on to cleaning of existing structures. */
+
+               /* find encoders that use this crtc. */
+               list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) {
+                       if (drm_encoder->crtc == set->crtc) {
+                               /* find the connector that goes with it */
+                               list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) {
+                                       if (drm_connector->encoder == drm_encoder) {
+                                               drm_connector->encoder =  NULL;
+                                               break;
+                                       }
+                               }
+                               drm_encoder->crtc = NULL;
+                       }
+               }
 
-               drm_encoder = drm_connector->encoder;
-               drm_connector->encoder = NULL;
+               /* now find if our desired encoders or connectors are in use already. */
+               for (i = 0; i < set->num_connectors; i++) {
+                       drm_connector = set->connectors[i];
+                       if (!drm_connector) {
+                               NV50_DEBUG("No connector\n");
+                               goto out;
+                       }
 
-               if (!drm_encoder->crtc)
-                       continue;
+                       if (!drm_connector->encoder)
+                               continue;
 
-               drm_crtc = drm_encoder->crtc;
-               drm_encoder->crtc = NULL;
+                       drm_encoder = drm_connector->encoder;
+                       drm_connector->encoder = NULL;
 
-               crtc = to_nv50_crtc(drm_crtc);
-               crtc->active = false;
-               drm_crtc->enabled = false;
-       }
+                       if (!drm_encoder->crtc)
+                               continue;
 
-       /* set framebuffer */
-       set->crtc->fb = set->fb;
+                       drm_crtc = drm_encoder->crtc;
+                       drm_encoder->crtc = NULL;
 
-       /* Time to wire up the public encoder, the private one will be handled later. */
-       for (i = 0; i < set->num_connectors; i++) {
-               drm_connector = set->connectors[i];
-               if (!drm_connector) {
-                       NV50_DEBUG("No connector\n");
-                       goto out;
+                       crtc = to_nv50_crtc(drm_crtc);
+                       crtc->active = false;
+                       drm_crtc->enabled = false;
                }
 
-               output = connector->to_output(connector, connector->digital);
-               if (!output) {
-                       NV50_DEBUG("No output\n");
-                       goto out;
-               }
+               /* Time to wire up the public encoder, the private one will be handled later. */
+               for (i = 0; i < set->num_connectors; i++) {
+                       drm_connector = set->connectors[i];
+                       if (!drm_connector) {
+                               NV50_DEBUG("No connector\n");
+                               goto out;
+                       }
 
-               /* find the encoder public structure that matches out output structure. */
-               drm_encoder = to_nv50_kms_encoder(output);
+                       output = connector->to_output(connector, connector->digital);
+                       if (!output) {
+                               NV50_DEBUG("No output\n");
+                               goto out;
+                       }
 
-               if (!drm_encoder) {
-                       NV50_DEBUG("No encoder\n");
-                       goto out;
+                       /* find the encoder public structure that matches out output structure. */
+                       drm_encoder = to_nv50_kms_encoder(output);
+
+                       if (!drm_encoder) {
+                               NV50_DEBUG("No encoder\n");
+                               goto out;
+                       }
+
+                       drm_encoder->crtc = set->crtc;
+                       drm_connector->encoder = drm_encoder;
                }
+       }
+
+       /**
+        * Unwire encoders and connectors, etc.
+        */
 
+       if (blank) {
+               crtc = to_nv50_crtc(drm_crtc);
 
-               drm_encoder->crtc = set->crtc;
-               drm_connector->encoder = drm_encoder;
+               crtc->active = false;
+               set->crtc->enabled = false;
+
+               /* find encoders that use this crtc. */
+               list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) {
+                       if (drm_encoder->crtc == set->crtc) {
+                               /* find the connector that goes with it */
+                               list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) {
+                                       if (drm_connector->encoder == drm_encoder) {
+                                               drm_connector->encoder =  NULL;
+                                               break;
+                                       }
+                               }
+                               drm_encoder->crtc = NULL;
+                       }
+               }
        }
 
+       /**
+        * All state should now be updated, now onto the real work.
+        */
+
        /* mirror everything to the private structs */
        nv50_kms_mirror_routing(dev);
 
-       /* set private framebuffer */
-       crtc = to_nv50_crtc(set->crtc);
-       fb_info.block = find_block_by_handle(dev_priv->fb_heap, set->fb->mm_handle);
-       fb_info.width = set->fb->width;
-       fb_info.height = set->fb->height;
-       fb_info.depth = set->fb->depth;
-       fb_info.bpp = set->fb->bits_per_pixel;
-       fb_info.x = set->x;
-       fb_info.y = set->y;
-
-       rval = crtc->fb->bind(crtc, &fb_info);
-       if (rval != 0) {
-               NV50_DEBUG("fb_bind failed\n");
-               goto out;
+       /**
+        * Bind framebuffer.
+        */
+
+       if (switch_fb) {
+               /* set framebuffer */
+               set->crtc->fb = set->fb;
+
+               /* set private framebuffer */
+               crtc = to_nv50_crtc(set->crtc);
+               fb_info.block = find_block_by_handle(dev_priv->fb_heap, set->fb->mm_handle);
+               fb_info.width = set->fb->width;
+               fb_info.height = set->fb->height;
+               fb_info.depth = set->fb->depth;
+               fb_info.bpp = set->fb->bits_per_pixel;
+               fb_info.pitch = set->fb->pitch;
+               fb_info.x = set->x;
+               fb_info.y = set->y;
+
+               rval = crtc->fb->bind(crtc, &fb_info);
+               if (rval != 0) {
+                       NV50_DEBUG("fb_bind failed\n");
+                       goto out;
+               }
        }
 
+       /* this is !cursor_show */
        if (!crtc->cursor->enabled) {
                rval = crtc->cursor->enable(crtc);
                if (rval != 0) {
@@ -438,74 +505,119 @@ int nv50_kms_crtc_set_config(struct drm_mode_set *set)
                }
        }
 
-       /* modeset time, finally */
+       /**
+        * Blanking.
+        */
 
-       /* disconnect unused outputs */
-       list_for_each_entry(output, &display->outputs, head) {
-               if (output->crtc)
-                       crtc_mask |= 1 << output->crtc->index;
-               else
-                       output->execute_mode(output, TRUE);
-       }
+       if (blank) {
+               crtc = to_nv50_crtc(set->crtc);
 
-       rval = crtc->set_mode(crtc, hw_mode);
-       if (rval != 0) {
-               NV50_DEBUG("crtc mode set failed\n");
-               goto out;
+               rval = crtc->blank(crtc, TRUE);
+               if (rval != 0) {
+                       DRM_ERROR("blanking failed\n");
+                       goto out;
+               }
        }
 
-       /* find native mode. */
-       list_for_each_entry(output, &display->outputs, head) {
-               if (output->crtc != crtc)
-                       continue;
+       /**
+        * Change framebuffer, without changing mode.
+        */
 
-               *crtc->native_mode = *output->native_mode;
-               list_for_each_entry(connector, &display->connectors, head) {
-                       if (connector->output != output)
-                               continue;
+       if (switch_fb && !modeset) {
+               crtc = to_nv50_crtc(set->crtc);
 
-                       crtc->scaling_mode = connector->scaling_mode;
-                       break;
+               rval = crtc->blank(crtc, TRUE);
+               if (rval != 0) {
+                       DRM_ERROR("blanking failed\n");
+                       goto out;
                }
 
-               if (crtc->scaling_mode == SCALE_PANEL)
-                       crtc->use_native_mode = false;
-               else
-                       crtc->use_native_mode = true;
+               rval = crtc->set_fb(crtc);
+               if (rval != 0) {
+                       DRM_ERROR("set_fb failed\n");
+                       goto out;
+               }
 
-               break; /* no use in finding more than one mode */
+               /* this also sets the fb offset */
+               rval = crtc->blank(crtc, FALSE);
+               if (rval != 0) {
+                       DRM_ERROR("unblanking failed\n");
+                       goto out;
+               }
        }
 
-       rval = crtc->execute_mode(crtc);
-       if (rval != 0) {
-               NV50_DEBUG("crtc execute mode failed\n");
-               goto out;
-       }
+       /**
+        * Normal modesetting.
+        */
 
-       list_for_each_entry(output, &display->outputs, head) {
-               if (output->crtc != crtc)
-                       continue;
+       if (modeset) {
+               /* disconnect unused outputs */
+               list_for_each_entry(output, &display->outputs, head) {
+                       if (output->crtc)
+                               crtc_mask |= 1 << output->crtc->index;
+                       else
+                               output->execute_mode(output, TRUE);
+               }
 
-               rval = output->execute_mode(output, FALSE);
+               rval = crtc->set_mode(crtc, hw_mode);
                if (rval != 0) {
-                       NV50_DEBUG("output execute mode failed\n");
+                       NV50_DEBUG("crtc mode set failed\n");
                        goto out;
                }
-       }
 
-       rval = crtc->set_scale(crtc);
-       if (rval != 0) {
-               NV50_DEBUG("crtc set scale failed\n");
-               goto out;
-       }
+               /* find native mode. */
+               list_for_each_entry(output, &display->outputs, head) {
+                       if (output->crtc != crtc)
+                               continue;
 
-       /* next line changes crtc, so putting it here is important */
-       display->last_crtc = crtc->index;
+                       *crtc->native_mode = *output->native_mode;
+                       list_for_each_entry(connector, &display->connectors, head) {
+                               if (connector->output != output)
+                                       continue;
 
-       /* blank any unused crtcs */
-       list_for_each_entry(crtc, &display->crtcs, head) {
-               if (!(crtc_mask & (1 << crtc->index)))
-                       crtc->blank(crtc, TRUE);
+                               crtc->scaling_mode = connector->scaling_mode;
+                               break;
+                       }
+
+                       if (crtc->scaling_mode == SCALE_PANEL)
+                               crtc->use_native_mode = false;
+                       else
+                               crtc->use_native_mode = true;
+
+                       break; /* no use in finding more than one mode */
+               }
+
+               rval = crtc->execute_mode(crtc);
+               if (rval != 0) {
+                       NV50_DEBUG("crtc execute mode failed\n");
+                       goto out;
+               }
+
+               list_for_each_entry(output, &display->outputs, head) {
+                       if (output->crtc != crtc)
+                               continue;
+
+                       rval = output->execute_mode(output, FALSE);
+                       if (rval != 0) {
+                               NV50_DEBUG("output execute mode failed\n");
+                               goto out;
+                       }
+               }
+
+               rval = crtc->set_scale(crtc);
+               if (rval != 0) {
+                       NV50_DEBUG("crtc set scale failed\n");
+                       goto out;
+               }
+
+               /* next line changes crtc, so putting it here is important */
+               display->last_crtc = crtc->index;
+
+               /* blank any unused crtcs */
+               list_for_each_entry(crtc, &display->crtcs, head) {
+                       if (!(crtc_mask & (1 << crtc->index)))
+                               crtc->blank(crtc, TRUE);
+               }
        }
 
        display->update(display);
@@ -631,36 +743,35 @@ static int nv50_kms_encoders_init(struct drm_device *dev)
 void nv50_kms_connector_detect_all(struct drm_device *dev)
 {
        struct drm_connector *drm_connector = NULL;
-       enum drm_connector_status old, new;
-       bool notify = false;
 
        list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) {
-               old = drm_connector->status;
-               new = drm_connector->funcs->detect(drm_connector);
-
-               if (new != old) {
-                       notify = true;
-                       drm_connector->funcs->fill_modes(drm_connector, 0, 0);
-               }
+               drm_connector->funcs->detect(drm_connector);
        }
-
-       /* I think this is the hook that notifies of changes. */
-       if (notify)
-               dev->mode_config.funcs->fb_changed(dev);
 }
 
 static enum drm_connector_status nv50_kms_connector_detect(struct drm_connector *drm_connector)
 {
        struct nv50_connector *connector = to_nv50_connector(drm_connector);
+       struct drm_device *dev = drm_connector->dev;
        bool connected;
+       int old_status;
 
        connected = connector->detect(connector);
 
+       old_status = drm_connector->status;
+
        if (connected)
                drm_connector->status = connector_status_connected;
        else
                drm_connector->status = connector_status_disconnected;
 
+       /* update our modes whenever there is reason to */
+       if (old_status != drm_connector->status) {
+               drm_connector->funcs->fill_modes(drm_connector, 0, 0);
+               /* notify fb of changes */
+               dev->mode_config.funcs->fb_changed(dev);
+       }
+
        return drm_connector->status;
 }
 
@@ -695,7 +806,7 @@ static void nv50_kms_connector_fill_modes(struct drm_connector *drm_connector, u
        struct drm_display_mode *mode, *t;
        struct edid *edid = NULL;
 
-       DRM_DEBUG("%s\n", drm_get_connector_name(drm_connector));
+       NV50_DEBUG("%s\n", drm_get_connector_name(drm_connector));
        /* set all modes to the unverified state */
        list_for_each_entry_safe(mode, t, &drm_connector->modes, head)
                mode->status = MODE_UNVERIFIED;
@@ -708,7 +819,7 @@ static void nv50_kms_connector_fill_modes(struct drm_connector *drm_connector, u
                drm_connector->status = connector_status_disconnected;
 
        if (!connected) {
-               DRM_DEBUG("%s is disconnected\n", drm_get_connector_name(drm_connector));
+               NV50_DEBUG("%s is disconnected\n", drm_get_connector_name(drm_connector));
                /* TODO set EDID to NULL */
                return;
        }
@@ -762,7 +873,7 @@ static void nv50_kms_connector_fill_modes(struct drm_connector *drm_connector, u
                struct nouveau_hw_mode *hw_mode;
                struct nv50_output *output;
 
-               DRM_DEBUG("No valid modes on %s\n", drm_get_connector_name(drm_connector));
+               NV50_DEBUG("No valid modes on %s\n", drm_get_connector_name(drm_connector));
 
                /* Should we do this here ???
                 * When no valid EDID modes are available we end up
@@ -787,7 +898,7 @@ static void nv50_kms_connector_fill_modes(struct drm_connector *drm_connector, u
 
        drm_mode_sort(&drm_connector->modes);
 
-       DRM_DEBUG("Probed modes for %s\n", drm_get_connector_name(drm_connector));
+       NV50_DEBUG("Probed modes for %s\n", drm_get_connector_name(drm_connector));
 
        list_for_each_entry_safe(mode, t, &drm_connector->modes, head) {
                mode->vrefresh = drm_mode_vrefresh(mode);
index 49f29fd..75909c8 100644 (file)
@@ -100,6 +100,10 @@ static int nv50_sor_set_clock_mode(struct nv50_output *output)
 
        NV50_DEBUG("or %d\n", nv50_output_or_offset(output));
 
+       /* We don't yet know what to do, if anything at all. */
+       if (output->type == OUTPUT_LVDS)
+               return 0;
+
        if (crtc->use_native_mode)
                hw_mode = crtc->native_mode;
        else