Merge branch 'gpu-switcher' of /ssd/git//linux-2.6 into drm-next-stage
[safe/jmp/linux-2.6] / drivers / gpu / drm / nouveau / nouveau_fbcon.c
index eddadac..68cedd9 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/screen_info.h>
+#include <linux/vga_switcheroo.h>
 
 #include "drmP.h"
 #include "drm.h"
@@ -107,6 +108,34 @@ static struct fb_ops nouveau_fbcon_ops = {
        .fb_setcmap = drm_fb_helper_setcmap,
 };
 
+static struct fb_ops nv04_fbcon_ops = {
+       .owner = THIS_MODULE,
+       .fb_check_var = drm_fb_helper_check_var,
+       .fb_set_par = drm_fb_helper_set_par,
+       .fb_setcolreg = drm_fb_helper_setcolreg,
+       .fb_fillrect = nv04_fbcon_fillrect,
+       .fb_copyarea = nv04_fbcon_copyarea,
+       .fb_imageblit = nv04_fbcon_imageblit,
+       .fb_sync = nouveau_fbcon_sync,
+       .fb_pan_display = drm_fb_helper_pan_display,
+       .fb_blank = drm_fb_helper_blank,
+       .fb_setcmap = drm_fb_helper_setcmap,
+};
+
+static struct fb_ops nv50_fbcon_ops = {
+       .owner = THIS_MODULE,
+       .fb_check_var = drm_fb_helper_check_var,
+       .fb_set_par = drm_fb_helper_set_par,
+       .fb_setcolreg = drm_fb_helper_setcolreg,
+       .fb_fillrect = nv50_fbcon_fillrect,
+       .fb_copyarea = nv50_fbcon_copyarea,
+       .fb_imageblit = nv50_fbcon_imageblit,
+       .fb_sync = nouveau_fbcon_sync,
+       .fb_pan_display = drm_fb_helper_pan_display,
+       .fb_blank = drm_fb_helper_blank,
+       .fb_setcmap = drm_fb_helper_setcmap,
+};
+
 static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
                                    u16 blue, int regno)
 {
@@ -324,9 +353,11 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width,
                switch (dev_priv->card_type) {
                case NV_50:
                        nv50_fbcon_accel_init(info);
+                       info->fbops = &nv50_fbcon_ops;
                        break;
                default:
                        nv04_fbcon_accel_init(info);
+                       info->fbops = &nv04_fbcon_ops;
                        break;
                };
        }
@@ -340,6 +371,7 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width,
                                                nvbo->bo.offset, nvbo);
 
        mutex_unlock(&dev->struct_mutex);
+       vga_switcheroo_client_fb_set(dev->pdev, info);
        return 0;
 
 out_unref:
@@ -371,10 +403,8 @@ nouveau_fbcon_remove(struct drm_device *dev, struct drm_framebuffer *fb)
 
                unregister_framebuffer(info);
                nouveau_bo_unmap(nouveau_fb->nvbo);
-               mutex_lock(&dev->struct_mutex);
-               drm_gem_object_unreference(nouveau_fb->nvbo->gem);
+               drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem);
                nouveau_fb->nvbo = NULL;
-               mutex_unlock(&dev->struct_mutex);
                if (par)
                        drm_fb_helper_free(&par->helper);
                framebuffer_release(info);