drm: Propagate error from drm_fb_helper_init().
[safe/jmp/linux-2.6] / drivers / gpu / drm / nouveau / nouveau_fbcon.c
index 90843b6..c9a4a0d 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/slab.h>
 #include <linux/sysrq.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
@@ -98,7 +97,6 @@ static struct fb_ops nouveau_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 = cfb_fillrect,
        .fb_copyarea = cfb_copyarea,
        .fb_imageblit = cfb_imageblit,
@@ -112,7 +110,6 @@ 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,
@@ -126,7 +123,6 @@ 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,
@@ -156,49 +152,6 @@ static void nouveau_fbcon_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
        *blue = nv_crtc->lut.b[regno];
 }
 
-static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
-       .gamma_set = nouveau_fbcon_gamma_set,
-       .gamma_get = nouveau_fbcon_gamma_get
-};
-
-#if defined(__i386__) || defined(__x86_64__)
-static bool
-nouveau_fbcon_has_vesafb_or_efifb(struct drm_device *dev)
-{
-       struct pci_dev *pdev = dev->pdev;
-       int ramin;
-
-       if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB &&
-           screen_info.orig_video_isVGA != VIDEO_TYPE_EFI)
-               return false;
-
-       if (screen_info.lfb_base < pci_resource_start(pdev, 1))
-               goto not_fb;
-
-       if (screen_info.lfb_base + screen_info.lfb_size >=
-           pci_resource_start(pdev, 1) + pci_resource_len(pdev, 1))
-               goto not_fb;
-
-       return true;
-not_fb:
-       ramin = 2;
-       if (pci_resource_len(pdev, ramin) == 0) {
-               ramin = 3;
-               if (pci_resource_len(pdev, ramin) == 0)
-                       return false;
-       }
-
-       if (screen_info.lfb_base < pci_resource_start(pdev, ramin))
-               return false;
-
-       if (screen_info.lfb_base + screen_info.lfb_size >=
-           pci_resource_start(pdev, ramin) + pci_resource_len(pdev, ramin))
-               return false;
-
-       return true;
-}
-#endif
-
 static void
 nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbdev *nfbdev)
 {
@@ -228,7 +181,8 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
        struct nouveau_framebuffer *nouveau_fb;
        struct nouveau_bo *nvbo;
        struct drm_mode_fb_cmd mode_cmd;
-       struct device *device = &dev->pdev->dev;
+       struct pci_dev *pdev = dev->pdev;
+       struct device *device = &pdev->dev;
        int size, ret;
 
        mode_cmd.width = sizes->surface_width;
@@ -272,6 +226,12 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
                goto out_unref;
        }
 
+       ret = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (ret) {
+               ret = -ENOMEM;
+               goto out_unref;
+       }
+
        info->par = nfbdev;
 
        nouveau_framebuffer_init(dev, &nfbdev->nouveau_fb, &mode_cmd, nvbo);
@@ -282,7 +242,6 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
        /* setup helper */
        nfbdev->helper.fb = fb;
        nfbdev->helper.fbdev = info;
-       nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs;
 
        strcpy(info->fix.id, "nouveaufb");
        if (nouveau_nofbaccel)
@@ -303,28 +262,14 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
        drm_fb_helper_fill_var(info, &nfbdev->helper, sizes->fb_width, sizes->fb_height);
 
        /* FIXME: we really shouldn't expose mmio space at all */
-       info->fix.mmio_start = pci_resource_start(dev->pdev, 1);
-       info->fix.mmio_len = pci_resource_len(dev->pdev, 1);
+       info->fix.mmio_start = pci_resource_start(pdev, 1);
+       info->fix.mmio_len = pci_resource_len(pdev, 1);
 
        /* Set aperture base/size for vesafb takeover */
-#if defined(__i386__) || defined(__x86_64__)
-       if (nouveau_fbcon_has_vesafb_or_efifb(dev)) {
-               /* Some NVIDIA VBIOS' are stupid and decide to put the
-                * framebuffer in the middle of the PRAMIN BAR for
-                * whatever reason.  We need to know the exact lfb_base
-                * to get vesafb kicked off, and the only reliable way
-                * we have left is to find out lfb_base the same way
-                * vesafb did.
-                */
-               info->aperture_base = screen_info.lfb_base;
-               info->aperture_size = screen_info.lfb_size;
-               if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB)
-                       info->aperture_size *= 65536;
-       } else
-#endif
-       {
-               info->aperture_base = info->fix.mmio_start;
-               info->aperture_size = info->fix.mmio_len;
+       info->apertures = dev_priv->apertures;
+       if (!info->apertures) {
+               ret = -ENOMEM;
+               goto out_unref;
        }
 
        info->pixmap.size = 64*1024;
@@ -381,12 +326,11 @@ nouveau_fbcon_find_or_create_single(struct drm_fb_helper *helper,
        return new_fb;
 }
 
-static int
-nouveau_fbcon_probe(struct nouveau_fbdev *nfbdev)
+void
+nouveau_fbcon_output_poll_changed(struct drm_device *dev)
 {
-       NV_DEBUG_KMS(nfbdev->dev, "\n");
-
-       return drm_fb_helper_single_fb_probe(&nfbdev->helper, 32);
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
+       drm_fb_helper_hotplug_event(&dev_priv->nfbdev->helper);
 }
 
 int
@@ -398,6 +342,8 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev)
        if (nfbdev->helper.fbdev) {
                info = nfbdev->helper.fbdev;
                unregister_framebuffer(info);
+               if (info->cmap.len)
+                       fb_dealloc_cmap(&info->cmap);
                framebuffer_release(info);
        }
 
@@ -406,7 +352,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev)
                drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem);
                nouveau_fb->nvbo = NULL;
        }
-       drm_fb_helper_free(&nfbdev->helper);
+       drm_fb_helper_fini(&nfbdev->helper);
        drm_framebuffer_cleanup(&nouveau_fb->base);
        return 0;
 }
@@ -420,10 +366,18 @@ void nouveau_fbcon_gpu_lockup(struct fb_info *info)
        info->flags |= FBINFO_HWACCEL_DISABLED;
 }
 
+static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = {
+       .gamma_set = nouveau_fbcon_gamma_set,
+       .gamma_get = nouveau_fbcon_gamma_get,
+       .fb_probe = nouveau_fbcon_find_or_create_single,
+};
+
+
 int nouveau_fbcon_init(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_fbdev *nfbdev;
+       int ret;
 
        nfbdev = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL);
        if (!nfbdev)
@@ -431,12 +385,16 @@ int nouveau_fbcon_init(struct drm_device *dev)
 
        nfbdev->dev = dev;
        dev_priv->nfbdev = nfbdev;
+       nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs;
+
+       ret = drm_fb_helper_init(dev, &nfbdev->helper, 2, 4);
+       if (ret) {
+               kfree(nfbdev);
+               return ret;
+       }
 
-       drm_fb_helper_init_crtc_count(dev, &nfbdev->helper,
-                                     2, 4);
-       nfbdev->helper.fb_probe = nouveau_fbcon_find_or_create_single;
-       drm_fb_helper_initial_config(&nfbdev->helper);
-       nouveau_fbcon_probe(nfbdev);
+       drm_fb_helper_single_add_all_connectors(&nfbdev->helper);
+       drm_fb_helper_initial_config(&nfbdev->helper, 32);
        return 0;
 }