diff options
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/efifb.c | 5 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 31 | ||||
-rw-r--r-- | drivers/video/vesafb.c | 15 |
3 files changed, 49 insertions, 2 deletions
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index 8dea2bc92705..eb12182b2059 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c | |||
@@ -280,6 +280,9 @@ static int __init efifb_probe(struct platform_device *dev) | |||
280 | info->pseudo_palette = info->par; | 280 | info->pseudo_palette = info->par; |
281 | info->par = NULL; | 281 | info->par = NULL; |
282 | 282 | ||
283 | info->aperture_base = efifb_fix.smem_start; | ||
284 | info->aperture_size = size_total; | ||
285 | |||
283 | info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len); | 286 | info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len); |
284 | if (!info->screen_base) { | 287 | if (!info->screen_base) { |
285 | printk(KERN_ERR "efifb: abort, cannot ioremap video memory " | 288 | printk(KERN_ERR "efifb: abort, cannot ioremap video memory " |
@@ -337,7 +340,7 @@ static int __init efifb_probe(struct platform_device *dev) | |||
337 | info->fbops = &efifb_ops; | 340 | info->fbops = &efifb_ops; |
338 | info->var = efifb_defined; | 341 | info->var = efifb_defined; |
339 | info->fix = efifb_fix; | 342 | info->fix = efifb_fix; |
340 | info->flags = FBINFO_FLAG_DEFAULT; | 343 | info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE; |
341 | 344 | ||
342 | if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) { | 345 | if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) { |
343 | printk(KERN_ERR "efifb: cannot allocate colormap\n"); | 346 | printk(KERN_ERR "efifb: cannot allocate colormap\n"); |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index d412a1ddc12f..f8a09bf8d0cd 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -1462,6 +1462,16 @@ static int fb_check_foreignness(struct fb_info *fi) | |||
1462 | return 0; | 1462 | return 0; |
1463 | } | 1463 | } |
1464 | 1464 | ||
1465 | static bool fb_do_apertures_overlap(struct fb_info *gen, struct fb_info *hw) | ||
1466 | { | ||
1467 | /* is the generic aperture base the same as the HW one */ | ||
1468 | if (gen->aperture_base == hw->aperture_base) | ||
1469 | return true; | ||
1470 | /* is the generic aperture base inside the hw base->hw base+size */ | ||
1471 | if (gen->aperture_base > hw->aperture_base && gen->aperture_base <= hw->aperture_base + hw->aperture_size) | ||
1472 | return true; | ||
1473 | return false; | ||
1474 | } | ||
1465 | /** | 1475 | /** |
1466 | * register_framebuffer - registers a frame buffer device | 1476 | * register_framebuffer - registers a frame buffer device |
1467 | * @fb_info: frame buffer info structure | 1477 | * @fb_info: frame buffer info structure |
@@ -1485,6 +1495,23 @@ register_framebuffer(struct fb_info *fb_info) | |||
1485 | if (fb_check_foreignness(fb_info)) | 1495 | if (fb_check_foreignness(fb_info)) |
1486 | return -ENOSYS; | 1496 | return -ENOSYS; |
1487 | 1497 | ||
1498 | /* check all firmware fbs and kick off if the base addr overlaps */ | ||
1499 | for (i = 0 ; i < FB_MAX; i++) { | ||
1500 | if (!registered_fb[i]) | ||
1501 | continue; | ||
1502 | |||
1503 | if (registered_fb[i]->flags & FBINFO_MISC_FIRMWARE) { | ||
1504 | if (fb_do_apertures_overlap(registered_fb[i], fb_info)) { | ||
1505 | printk(KERN_ERR "fb: conflicting fb hw usage " | ||
1506 | "%s vs %s - removing generic driver\n", | ||
1507 | fb_info->fix.id, | ||
1508 | registered_fb[i]->fix.id); | ||
1509 | unregister_framebuffer(registered_fb[i]); | ||
1510 | break; | ||
1511 | } | ||
1512 | } | ||
1513 | } | ||
1514 | |||
1488 | num_registered_fb++; | 1515 | num_registered_fb++; |
1489 | for (i = 0 ; i < FB_MAX; i++) | 1516 | for (i = 0 ; i < FB_MAX; i++) |
1490 | if (!registered_fb[i]) | 1517 | if (!registered_fb[i]) |
@@ -1586,6 +1613,10 @@ unregister_framebuffer(struct fb_info *fb_info) | |||
1586 | device_destroy(fb_class, MKDEV(FB_MAJOR, i)); | 1613 | device_destroy(fb_class, MKDEV(FB_MAJOR, i)); |
1587 | event.info = fb_info; | 1614 | event.info = fb_info; |
1588 | fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); | 1615 | fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); |
1616 | |||
1617 | /* this may free fb info */ | ||
1618 | if (fb_info->fbops->fb_destroy) | ||
1619 | fb_info->fbops->fb_destroy(fb_info); | ||
1589 | done: | 1620 | done: |
1590 | return ret; | 1621 | return ret; |
1591 | } | 1622 | } |
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index d6856f43d241..bd37ee1f6a25 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c | |||
@@ -174,8 +174,17 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green, | |||
174 | return err; | 174 | return err; |
175 | } | 175 | } |
176 | 176 | ||
177 | static void vesafb_destroy(struct fb_info *info) | ||
178 | { | ||
179 | if (info->screen_base) | ||
180 | iounmap(info->screen_base); | ||
181 | release_mem_region(info->aperture_base, info->aperture_size); | ||
182 | framebuffer_release(info); | ||
183 | } | ||
184 | |||
177 | static struct fb_ops vesafb_ops = { | 185 | static struct fb_ops vesafb_ops = { |
178 | .owner = THIS_MODULE, | 186 | .owner = THIS_MODULE, |
187 | .fb_destroy = vesafb_destroy, | ||
179 | .fb_setcolreg = vesafb_setcolreg, | 188 | .fb_setcolreg = vesafb_setcolreg, |
180 | .fb_pan_display = vesafb_pan_display, | 189 | .fb_pan_display = vesafb_pan_display, |
181 | .fb_fillrect = cfb_fillrect, | 190 | .fb_fillrect = cfb_fillrect, |
@@ -286,6 +295,10 @@ static int __init vesafb_probe(struct platform_device *dev) | |||
286 | info->pseudo_palette = info->par; | 295 | info->pseudo_palette = info->par; |
287 | info->par = NULL; | 296 | info->par = NULL; |
288 | 297 | ||
298 | /* set vesafb aperture size for generic probing */ | ||
299 | info->aperture_base = screen_info.lfb_base; | ||
300 | info->aperture_size = size_total; | ||
301 | |||
289 | info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len); | 302 | info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len); |
290 | if (!info->screen_base) { | 303 | if (!info->screen_base) { |
291 | printk(KERN_ERR | 304 | printk(KERN_ERR |
@@ -437,7 +450,7 @@ static int __init vesafb_probe(struct platform_device *dev) | |||
437 | info->fbops = &vesafb_ops; | 450 | info->fbops = &vesafb_ops; |
438 | info->var = vesafb_defined; | 451 | info->var = vesafb_defined; |
439 | info->fix = vesafb_fix; | 452 | info->fix = vesafb_fix; |
440 | info->flags = FBINFO_FLAG_DEFAULT | | 453 | info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE | |
441 | (ypan ? FBINFO_HWACCEL_YPAN : 0); | 454 | (ypan ? FBINFO_HWACCEL_YPAN : 0); |
442 | 455 | ||
443 | if (!ypan) | 456 | if (!ypan) |