Commit 3b9676e7 authored by Marcin Slusarz's avatar Marcin Slusarz Committed by Dave Airlie

vga16fb, drm: vga16fb->drm handoff

let vga16fb claim 0xA0000+0x10000 region as its aperture;
drm drivers don't use it, so we have to detect it and kick
vga16fb manually - but only if drm is driving the primary card
Signed-off-by: default avatarMarcin Slusarz <marcin.slusarz@gmail.com>
Cc: James Simmons <jsimmons@infradead.org>
Cc: Dave Airlie <airlied@redhat.com>
Cc: Ben Skeggs <bskeggs@redhat.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 06415c56
...@@ -668,11 +668,16 @@ static struct apertures_struct *nouveau_get_apertures(struct drm_device *dev) ...@@ -668,11 +668,16 @@ static struct apertures_struct *nouveau_get_apertures(struct drm_device *dev)
static int nouveau_remove_conflicting_drivers(struct drm_device *dev) static int nouveau_remove_conflicting_drivers(struct drm_device *dev)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
bool primary = false;
dev_priv->apertures = nouveau_get_apertures(dev); dev_priv->apertures = nouveau_get_apertures(dev);
if (!dev_priv->apertures) if (!dev_priv->apertures)
return -ENOMEM; return -ENOMEM;
remove_conflicting_framebuffers(dev_priv->apertures, "nouveaufb"); #ifdef CONFIG_X86
primary = dev->pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
#endif
remove_conflicting_framebuffers(dev_priv->apertures, "nouveaufb", primary);
return 0; return 0;
} }
......
...@@ -1500,19 +1500,26 @@ static bool fb_do_apertures_overlap(struct apertures_struct *gena, ...@@ -1500,19 +1500,26 @@ static bool fb_do_apertures_overlap(struct apertures_struct *gena,
return false; return false;
} }
void remove_conflicting_framebuffers(struct apertures_struct *a, const char *name) #define VGA_FB_PHYS 0xA0000
void remove_conflicting_framebuffers(struct apertures_struct *a,
const char *name, bool primary)
{ {
int i; int i;
/* check all firmware fbs and kick off if the base addr overlaps */ /* check all firmware fbs and kick off if the base addr overlaps */
for (i = 0 ; i < FB_MAX; i++) { for (i = 0 ; i < FB_MAX; i++) {
struct apertures_struct *gen_aper;
if (!registered_fb[i]) if (!registered_fb[i])
continue; continue;
if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE)) if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
continue; continue;
if (fb_do_apertures_overlap(registered_fb[i]->apertures, a)) { gen_aper = registered_fb[i]->apertures;
if (fb_do_apertures_overlap(gen_aper, a) ||
(primary && gen_aper && gen_aper->count &&
gen_aper->ranges[0].base == VGA_FB_PHYS)) {
printk(KERN_ERR "fb: conflicting fb hw usage " printk(KERN_ERR "fb: conflicting fb hw usage "
"%s vs %s - removing generic driver\n", "%s vs %s - removing generic driver\n",
name, registered_fb[i]->fix.id); name, registered_fb[i]->fix.id);
...@@ -1545,7 +1552,8 @@ register_framebuffer(struct fb_info *fb_info) ...@@ -1545,7 +1552,8 @@ register_framebuffer(struct fb_info *fb_info)
if (fb_check_foreignness(fb_info)) if (fb_check_foreignness(fb_info))
return -ENOSYS; return -ENOSYS;
remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id); remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id,
fb_is_primary_device(fb_info));
num_registered_fb++; num_registered_fb++;
for (i = 0 ; i < FB_MAX; i++) for (i = 0 ; i < FB_MAX; i++)
......
...@@ -1263,10 +1263,19 @@ static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image ...@@ -1263,10 +1263,19 @@ static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image
vga_imageblit_color(info, image); vga_imageblit_color(info, image);
} }
static void vga16fb_destroy(struct fb_info *info)
{
iounmap(info->screen_base);
fb_dealloc_cmap(&info->cmap);
/* XXX unshare VGA regions */
framebuffer_release(info);
}
static struct fb_ops vga16fb_ops = { static struct fb_ops vga16fb_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.fb_open = vga16fb_open, .fb_open = vga16fb_open,
.fb_release = vga16fb_release, .fb_release = vga16fb_release,
.fb_destroy = vga16fb_destroy,
.fb_check_var = vga16fb_check_var, .fb_check_var = vga16fb_check_var,
.fb_set_par = vga16fb_set_par, .fb_set_par = vga16fb_set_par,
.fb_setcolreg = vga16fb_setcolreg, .fb_setcolreg = vga16fb_setcolreg,
...@@ -1306,6 +1315,11 @@ static int __devinit vga16fb_probe(struct platform_device *dev) ...@@ -1306,6 +1315,11 @@ static int __devinit vga16fb_probe(struct platform_device *dev)
ret = -ENOMEM; ret = -ENOMEM;
goto err_fb_alloc; goto err_fb_alloc;
} }
info->apertures = alloc_apertures(1);
if (!info->apertures) {
ret = -ENOMEM;
goto err_ioremap;
}
/* XXX share VGA_FB_PHYS and I/O region with vgacon and others */ /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */
info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0); info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0);
...@@ -1335,7 +1349,7 @@ static int __devinit vga16fb_probe(struct platform_device *dev) ...@@ -1335,7 +1349,7 @@ static int __devinit vga16fb_probe(struct platform_device *dev)
info->fix = vga16fb_fix; info->fix = vga16fb_fix;
/* supports rectangles with widths of multiples of 8 */ /* supports rectangles with widths of multiples of 8 */
info->pixmap.blit_x = 1 << 7 | 1 << 15 | 1 << 23 | 1 << 31; info->pixmap.blit_x = 1 << 7 | 1 << 15 | 1 << 23 | 1 << 31;
info->flags = FBINFO_FLAG_DEFAULT | info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE |
FBINFO_HWACCEL_YPAN; FBINFO_HWACCEL_YPAN;
i = (info->var.bits_per_pixel == 8) ? 256 : 16; i = (info->var.bits_per_pixel == 8) ? 256 : 16;
...@@ -1354,6 +1368,9 @@ static int __devinit vga16fb_probe(struct platform_device *dev) ...@@ -1354,6 +1368,9 @@ static int __devinit vga16fb_probe(struct platform_device *dev)
vga16fb_update_fix(info); vga16fb_update_fix(info);
info->apertures->ranges[0].base = VGA_FB_PHYS;
info->apertures->ranges[0].size = VGA_FB_PHYS_LEN;
if (register_framebuffer(info) < 0) { if (register_framebuffer(info) < 0) {
printk(KERN_ERR "vga16fb: unable to register framebuffer\n"); printk(KERN_ERR "vga16fb: unable to register framebuffer\n");
ret = -EINVAL; ret = -EINVAL;
...@@ -1380,13 +1397,8 @@ static int vga16fb_remove(struct platform_device *dev) ...@@ -1380,13 +1397,8 @@ static int vga16fb_remove(struct platform_device *dev)
{ {
struct fb_info *info = platform_get_drvdata(dev); struct fb_info *info = platform_get_drvdata(dev);
if (info) { if (info)
unregister_framebuffer(info); unregister_framebuffer(info);
iounmap(info->screen_base);
fb_dealloc_cmap(&info->cmap);
/* XXX unshare VGA regions */
framebuffer_release(info);
}
return 0; return 0;
} }
......
...@@ -971,7 +971,8 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, ...@@ -971,7 +971,8 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
/* drivers/video/fbmem.c */ /* drivers/video/fbmem.c */
extern int register_framebuffer(struct fb_info *fb_info); extern int register_framebuffer(struct fb_info *fb_info);
extern int unregister_framebuffer(struct fb_info *fb_info); extern int unregister_framebuffer(struct fb_info *fb_info);
extern void remove_conflicting_framebuffers(struct apertures_struct *a, const char *name); extern void remove_conflicting_framebuffers(struct apertures_struct *a,
const char *name, bool primary);
extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
extern int fb_show_logo(struct fb_info *fb_info, int rotate); extern int fb_show_logo(struct fb_info *fb_info, int rotate);
extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment