aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorMarcin Slusarz <marcin.slusarz@gmail.com>2010-05-16 11:29:56 -0400
committerDave Airlie <airlied@redhat.com>2010-05-18 02:19:28 -0400
commit06415c564fb98562a4d6b6215615deb2d1cc0dae (patch)
tree93982221251bc68eb292a07da72220a0c90d94f0 /drivers/video
parent1471ca9aa71cd37b6a7476bb6f06a3a8622ea1bd (diff)
fbmem, drm/nouveau: kick firmware framebuffers as soon as possible
Currently vesafb/efifb/... is kicked when hardware driver is registering framebuffer. To do it hardware must be fully functional, so there's a short window between start of initialisation and framebuffer registration when two drivers touch the hardware. Unfortunately sometimes it breaks nouveau initialisation. Fix it by kicking firmware driver(s) before we start touching the hardware. Reported-by: Didier Spaier <didier.spaier@epsm.fr> Tested-by: Didier Spaier <didier.spaier@epsm.fr> Signed-off-by: Marcin Slusarz <marcin.slusarz@gmail.com> Cc: Ben Skeggs <bskeggs@redhat.com> Cc: Peter Jones <pjones@redhat.com> Cc: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/fbmem.c43
1 files changed, 25 insertions, 18 deletions
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++)