diff options
-rw-r--r-- | drivers/gpu/drm/i915/intel_fb.c | 8 | ||||
-rw-r--r-- | drivers/video/efifb.c | 5 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 31 | ||||
-rw-r--r-- | drivers/video/vesafb.c | 15 | ||||
-rw-r--r-- | include/linux/fb.h | 12 |
5 files changed, 68 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 0ecf6b76a401..8e28e5993df5 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c | |||
@@ -504,6 +504,14 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
504 | info->fbops = &intelfb_ops; | 504 | info->fbops = &intelfb_ops; |
505 | 505 | ||
506 | info->fix.line_length = fb->pitch; | 506 | info->fix.line_length = fb->pitch; |
507 | |||
508 | /* setup aperture base/size for vesafb takeover */ | ||
509 | info->aperture_base = dev->mode_config.fb_base; | ||
510 | if (IS_I9XX(dev)) | ||
511 | info->aperture_size = pci_resource_len(dev->pdev, 2); | ||
512 | else | ||
513 | info->aperture_size = pci_resource_len(dev->pdev, 0); | ||
514 | |||
507 | info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset; | 515 | info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset; |
508 | info->fix.smem_len = size; | 516 | info->fix.smem_len = size; |
509 | 517 | ||
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) |
diff --git a/include/linux/fb.h b/include/linux/fb.h index 330c4b1bfcaa..3c5562a52167 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
@@ -677,6 +677,9 @@ struct fb_ops { | |||
677 | /* get capability given var */ | 677 | /* get capability given var */ |
678 | void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps, | 678 | void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps, |
679 | struct fb_var_screeninfo *var); | 679 | struct fb_var_screeninfo *var); |
680 | |||
681 | /* teardown any resources to do with this framebuffer */ | ||
682 | void (*fb_destroy)(struct fb_info *info); | ||
680 | }; | 683 | }; |
681 | 684 | ||
682 | #ifdef CONFIG_FB_TILEBLITTING | 685 | #ifdef CONFIG_FB_TILEBLITTING |
@@ -786,6 +789,8 @@ struct fb_tile_ops { | |||
786 | #define FBINFO_MISC_USEREVENT 0x10000 /* event request | 789 | #define FBINFO_MISC_USEREVENT 0x10000 /* event request |
787 | from userspace */ | 790 | from userspace */ |
788 | #define FBINFO_MISC_TILEBLITTING 0x20000 /* use tile blitting */ | 791 | #define FBINFO_MISC_TILEBLITTING 0x20000 /* use tile blitting */ |
792 | #define FBINFO_MISC_FIRMWARE 0x40000 /* a replaceable firmware | ||
793 | inited framebuffer */ | ||
789 | 794 | ||
790 | /* A driver may set this flag to indicate that it does want a set_par to be | 795 | /* A driver may set this flag to indicate that it does want a set_par to be |
791 | * called every time when fbcon_switch is executed. The advantage is that with | 796 | * called every time when fbcon_switch is executed. The advantage is that with |
@@ -854,7 +859,12 @@ struct fb_info { | |||
854 | u32 state; /* Hardware state i.e suspend */ | 859 | u32 state; /* Hardware state i.e suspend */ |
855 | void *fbcon_par; /* fbcon use-only private area */ | 860 | void *fbcon_par; /* fbcon use-only private area */ |
856 | /* From here on everything is device dependent */ | 861 | /* From here on everything is device dependent */ |
857 | void *par; | 862 | void *par; |
863 | /* we need the PCI or similiar aperture base/size not | ||
864 | smem_start/size as smem_start may just be an object | ||
865 | allocated inside the aperture so may not actually overlap */ | ||
866 | resource_size_t aperture_base; | ||
867 | resource_size_t aperture_size; | ||
858 | }; | 868 | }; |
859 | 869 | ||
860 | #ifdef MODULE | 870 | #ifdef MODULE |