aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c19
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_state.c43
-rw-r--r--drivers/video/fbmem.c43
-rw-r--r--include/linux/fb.h1
5 files changed, 71 insertions, 36 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 5b47b79f45e8..94d8dd27bde8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -624,6 +624,7 @@ struct drm_nouveau_private {
624 } debugfs; 624 } debugfs;
625 625
626 struct nouveau_fbdev *nfbdev; 626 struct nouveau_fbdev *nfbdev;
627 struct apertures_struct *apertures;
627}; 628};
628 629
629static inline struct drm_nouveau_private * 630static inline struct drm_nouveau_private *
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 292c7ff95105..2c2199329cc1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -183,7 +183,6 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
183 struct drm_mode_fb_cmd mode_cmd; 183 struct drm_mode_fb_cmd mode_cmd;
184 struct pci_dev *pdev = dev->pdev; 184 struct pci_dev *pdev = dev->pdev;
185 struct device *device = &pdev->dev; 185 struct device *device = &pdev->dev;
186 struct apertures_struct *aper;
187 int size, ret; 186 int size, ret;
188 187
189 mode_cmd.width = sizes->surface_width; 188 mode_cmd.width = sizes->surface_width;
@@ -267,28 +266,12 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev,
267 info->fix.mmio_len = pci_resource_len(pdev, 1); 266 info->fix.mmio_len = pci_resource_len(pdev, 1);
268 267
269 /* Set aperture base/size for vesafb takeover */ 268 /* Set aperture base/size for vesafb takeover */
270 aper = info->apertures = alloc_apertures(3); 269 info->apertures = dev_priv->apertures;
271 if (!info->apertures) { 270 if (!info->apertures) {
272 ret = -ENOMEM; 271 ret = -ENOMEM;
273 goto out_unref; 272 goto out_unref;
274 } 273 }
275 274
276 aper->ranges[0].base = pci_resource_start(pdev, 1);
277 aper->ranges[0].size = pci_resource_len(pdev, 1);
278 aper->count = 1;
279
280 if (pci_resource_len(pdev, 2)) {
281 aper->ranges[aper->count].base = pci_resource_start(pdev, 2);
282 aper->ranges[aper->count].size = pci_resource_len(pdev, 2);
283 aper->count++;
284 }
285
286 if (pci_resource_len(pdev, 3)) {
287 aper->ranges[aper->count].base = pci_resource_start(pdev, 3);
288 aper->ranges[aper->count].size = pci_resource_len(pdev, 3);
289 aper->count++;
290 }
291
292 info->pixmap.size = 64*1024; 275 info->pixmap.size = 64*1024;
293 info->pixmap.buf_align = 8; 276 info->pixmap.buf_align = 8;
294 info->pixmap.access_align = 32; 277 info->pixmap.access_align = 32;
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index 92100a9678ba..75c5c465e08e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -639,6 +639,43 @@ static void nouveau_OF_copy_vbios_to_ramin(struct drm_device *dev)
639#endif 639#endif
640} 640}
641 641
642static struct apertures_struct *nouveau_get_apertures(struct drm_device *dev)
643{
644 struct pci_dev *pdev = dev->pdev;
645 struct apertures_struct *aper = alloc_apertures(3);
646 if (!aper)
647 return NULL;
648
649 aper->ranges[0].base = pci_resource_start(pdev, 1);
650 aper->ranges[0].size = pci_resource_len(pdev, 1);
651 aper->count = 1;
652
653 if (pci_resource_len(pdev, 2)) {
654 aper->ranges[aper->count].base = pci_resource_start(pdev, 2);
655 aper->ranges[aper->count].size = pci_resource_len(pdev, 2);
656 aper->count++;
657 }
658
659 if (pci_resource_len(pdev, 3)) {
660 aper->ranges[aper->count].base = pci_resource_start(pdev, 3);
661 aper->ranges[aper->count].size = pci_resource_len(pdev, 3);
662 aper->count++;
663 }
664
665 return aper;
666}
667
668static int nouveau_remove_conflicting_drivers(struct drm_device *dev)
669{
670 struct drm_nouveau_private *dev_priv = dev->dev_private;
671 dev_priv->apertures = nouveau_get_apertures(dev);
672 if (!dev_priv->apertures)
673 return -ENOMEM;
674
675 remove_conflicting_framebuffers(dev_priv->apertures, "nouveaufb");
676 return 0;
677}
678
642int nouveau_load(struct drm_device *dev, unsigned long flags) 679int nouveau_load(struct drm_device *dev, unsigned long flags)
643{ 680{
644 struct drm_nouveau_private *dev_priv; 681 struct drm_nouveau_private *dev_priv;
@@ -726,6 +763,12 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
726 NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", 763 NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n",
727 dev_priv->card_type, reg0); 764 dev_priv->card_type, reg0);
728 765
766 if (drm_core_check_feature(dev, DRIVER_MODESET)) {
767 int ret = nouveau_remove_conflicting_drivers(dev);
768 if (ret)
769 return ret;
770 }
771
729 /* map larger RAMIN aperture on NV40 cards */ 772 /* map larger RAMIN aperture on NV40 cards */
730 dev_priv->ramin = NULL; 773 dev_priv->ramin = NULL;
731 if (dev_priv->card_type >= NV_40) { 774 if (dev_priv->card_type >= NV_40) {
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 03f2dc2470b5..7cfcd716fd5f 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1479,11 +1479,10 @@ static bool apertures_overlap(struct aperture *gen, struct aperture *hw)
1479 return false; 1479 return false;
1480} 1480}
1481 1481
1482static bool fb_do_apertures_overlap(struct fb_info *gen, struct fb_info *hw) 1482static bool fb_do_apertures_overlap(struct apertures_struct *gena,
1483 struct apertures_struct *hwa)
1483{ 1484{
1484 int i, j; 1485 int i, j;
1485 struct apertures_struct *hwa = hw->apertures;
1486 struct apertures_struct *gena = gen->apertures;
1487 if (!hwa || !gena) 1486 if (!hwa || !gena)
1488 return false; 1487 return false;
1489 1488
@@ -1501,6 +1500,28 @@ static bool fb_do_apertures_overlap(struct fb_info *gen, struct fb_info *hw)
1501 return false; 1500 return false;
1502} 1501}
1503 1502
1503void remove_conflicting_framebuffers(struct apertures_struct *a, const char *name)
1504{
1505 int i;
1506
1507 /* check all firmware fbs and kick off if the base addr overlaps */
1508 for (i = 0 ; i < FB_MAX; i++) {
1509 if (!registered_fb[i])
1510 continue;
1511
1512 if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
1513 continue;
1514
1515 if (fb_do_apertures_overlap(registered_fb[i]->apertures, a)) {
1516 printk(KERN_ERR "fb: conflicting fb hw usage "
1517 "%s vs %s - removing generic driver\n",
1518 name, registered_fb[i]->fix.id);
1519 unregister_framebuffer(registered_fb[i]);
1520 }
1521 }
1522}
1523EXPORT_SYMBOL(remove_conflicting_framebuffers);
1524
1504/** 1525/**
1505 * register_framebuffer - registers a frame buffer device 1526 * register_framebuffer - registers a frame buffer device
1506 * @fb_info: frame buffer info structure 1527 * @fb_info: frame buffer info structure
@@ -1524,21 +1545,7 @@ register_framebuffer(struct fb_info *fb_info)
1524 if (fb_check_foreignness(fb_info)) 1545 if (fb_check_foreignness(fb_info))
1525 return -ENOSYS; 1546 return -ENOSYS;
1526 1547
1527 /* check all firmware fbs and kick off if the base addr overlaps */ 1548 remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id);
1528 for (i = 0 ; i < FB_MAX; i++) {
1529 if (!registered_fb[i])
1530 continue;
1531
1532 if (registered_fb[i]->flags & FBINFO_MISC_FIRMWARE) {
1533 if (fb_do_apertures_overlap(registered_fb[i], fb_info)) {
1534 printk(KERN_ERR "fb: conflicting fb hw usage "
1535 "%s vs %s - removing generic driver\n",
1536 fb_info->fix.id,
1537 registered_fb[i]->fix.id);
1538 unregister_framebuffer(registered_fb[i]);
1539 }
1540 }
1541 }
1542 1549
1543 num_registered_fb++; 1550 num_registered_fb++;
1544 for (i = 0 ; i < FB_MAX; i++) 1551 for (i = 0 ; i < FB_MAX; i++)
diff --git a/include/linux/fb.h b/include/linux/fb.h
index de5ff5fa8380..f88e2549123d 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -971,6 +971,7 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
971/* drivers/video/fbmem.c */ 971/* drivers/video/fbmem.c */
972extern int register_framebuffer(struct fb_info *fb_info); 972extern int register_framebuffer(struct fb_info *fb_info);
973extern int unregister_framebuffer(struct fb_info *fb_info); 973extern int unregister_framebuffer(struct fb_info *fb_info);
974extern void remove_conflicting_framebuffers(struct apertures_struct *a, const char *name);
974extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); 975extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
975extern int fb_show_logo(struct fb_info *fb_info, int rotate); 976extern int fb_show_logo(struct fb_info *fb_info, int rotate);
976extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); 977extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);