summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@airlied2.(none)>2007-04-11 16:33:03 +1000
committerDave Airlie <airlied@airlied2.(none)>2007-04-11 16:33:03 +1000
commit32f6a58db216f23a7c71ca9c7eda56aaa8293078 (patch)
treeb5c1899ce99797552cb6f01391b38a75ae6377f4
parentadd7a928ad1819df17d5764d06fb81985b285d08 (diff)
add initial drm_fb framebuffer
So far I can load fbcon, once I use my miniglx to add a framebuffer. fbcon doesn't show anything on screen but baby steps and all that.
-rw-r--r--linux-core/Makefile.kernel2
-rw-r--r--linux-core/drm_crtc.c2
-rw-r--r--linux-core/drm_crtc.h6
-rw-r--r--linux-core/drm_fb.c160
-rw-r--r--shared-core/i915_init.c4
5 files changed, 171 insertions, 3 deletions
diff --git a/linux-core/Makefile.kernel b/linux-core/Makefile.kernel
index c767116a..b9684d68 100644
--- a/linux-core/Makefile.kernel
+++ b/linux-core/Makefile.kernel
@@ -14,7 +14,7 @@ drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
drm_memory_debug.o ati_pcigart.o drm_sman.o \
drm_hashtab.o drm_mm.o drm_object.o drm_compat.o \
drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o drm_crtc.o \
- drm_edid.o drm_modes.o
+ drm_edid.o drm_modes.o drm_fb.o
tdfx-objs := tdfx_drv.o
r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o
mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
diff --git a/linux-core/drm_crtc.c b/linux-core/drm_crtc.c
index 12705272..83f8e167 100644
--- a/linux-core/drm_crtc.c
+++ b/linux-core/drm_crtc.c
@@ -1022,6 +1022,7 @@ int drm_mode_addfb(struct inode *inode, struct file *filp,
if (copy_to_user(argp, &r, sizeof(r)))
return -EFAULT;
+ drmfb_probe(dev, fb);
return 0;
}
@@ -1040,6 +1041,7 @@ int drm_mode_rmfb(struct inode *inode, struct file *filp,
return -EINVAL;
}
+ drmfb_remove(dev, fb);
/* TODO check if we own the buffer */
/* TODO release all crtc connected to the framebuffer */
/* bind the fb to the crtc for now */
diff --git a/linux-core/drm_crtc.h b/linux-core/drm_crtc.h
index 57bfb10b..d5d256d4 100644
--- a/linux-core/drm_crtc.h
+++ b/linux-core/drm_crtc.h
@@ -11,6 +11,8 @@
#include <linux/types.h>
#include <linux/idr.h>
+#include <linux/fb.h>
+
struct drm_device;
/*
@@ -179,6 +181,9 @@ struct drm_framebuffer {
int bits_per_pixel;
int flags;
struct drm_buffer_object *bo;
+ void *fbdev;
+ u32 pseudo_palette[17];
+ void *virtual_base;
};
struct drm_crtc;
struct drm_output;
@@ -412,6 +417,7 @@ struct drm_mode_config {
/* DamagePtr rotationDamage? */
/* DGA stuff? */
struct drm_mode_config_funcs *funcs;
+ int fb_base;
};
struct drm_output *drm_output_create(struct drm_device *dev,
diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c
new file mode 100644
index 00000000..9bf2187c
--- /dev/null
+++ b/linux-core/drm_fb.c
@@ -0,0 +1,160 @@
+ /*
+ * Modularization
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+
+#include "drmP.h"
+struct drmfb_par {
+ struct drm_device *dev;
+ struct drm_framebuffer *fb;
+};
+
+static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+ unsigned blue, unsigned transp,
+ struct fb_info *info)
+{
+ struct drmfb_par *par = info->par;
+ struct drm_framebuffer *fb = par->fb;
+ if (regno > 17)
+ return 1;
+
+ printk(KERN_INFO "Got set col reg %d %d %d %d\n", red, green, blue, regno);
+
+ if (regno < 16) {
+ switch (fb->depth) {
+ case 15:
+ fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
+ ((green & 0xf800) >> 6) |
+ ((blue & 0xf800) >> 11);
+ break;
+ case 16:
+ fb->pseudo_palette[regno] = (red & 0xf800) |
+ ((green & 0xfc00) >> 5) |
+ ((blue & 0xf800) >> 11);
+ break;
+ case 24:
+ fb->pseudo_palette[regno] = ((red & 0xff00) << 8) |
+ (green & 0xff00) |
+ ((blue & 0xff00) >> 8);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static struct fb_ops drmfb_ops = {
+ .owner = THIS_MODULE,
+ // .fb_open = drmfb_open,
+ // .fb_read = drmfb_read,
+ // .fb_write = drmfb_write,
+ // .fb_release = drmfb_release,
+ // .fb_ioctl = drmfb_ioctl,
+ .fb_setcolreg = drmfb_setcolreg,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb)
+{
+ struct fb_info *info;
+ struct drmfb_par *par;
+ struct device *device = &dev->pdev->dev;
+ struct fb_var_screeninfo *var_info;
+ unsigned long base, size;
+
+ info = framebuffer_alloc(sizeof(struct drmfb_par), device);
+ if (!info){
+ return -EINVAL;
+ }
+
+ fb->fbdev = info;
+
+ par = info->par;
+
+ par->dev = dev;
+ par->fb = fb;
+
+ info->fbops = &drmfb_ops;
+
+ strcpy(info->fix.id, "drmfb");
+ info->fix.smem_start = fb->offset + dev->mode_config.fb_base;
+ info->fix.smem_len = (8*1024*1024);
+ info->fix.type = FB_TYPE_PACKED_PIXELS;
+ info->fix.visual = FB_VISUAL_DIRECTCOLOR;
+ info->fix.type_aux = 0;
+ info->fix.mmio_start = 0;
+ info->fix.mmio_len = 0;
+ info->fix.line_length = fb->pitch;
+
+ info->flags = FBINFO_DEFAULT;
+
+ base = fb->bo->offset + dev->mode_config.fb_base;
+ size = (fb->bo->mem.num_pages * PAGE_SIZE);
+
+ DRM_DEBUG("remapping %08X %d\n", base, size);
+ fb->virtual_base = ioremap_nocache(base, size);
+
+ info->screen_base = fb->virtual_base;
+ info->screen_size = size;
+ info->pseudo_palette = fb->pseudo_palette;
+ info->var.xres = fb->width;
+ info->var.xres_virtual = fb->pitch;
+ info->var.yres = fb->height;
+ info->var.yres_virtual = fb->height;
+ info->var.bits_per_pixel = fb->bits_per_pixel;
+ info->var.xoffset = 0;
+ info->var.yoffset = 0;
+
+ switch(fb->depth) {
+ case 8:
+ case 15:
+ case 16:
+ break;
+ case 24:
+ case 32:
+ info->var.red.offset = 16;
+ info->var.green.offset = 8;
+ info->var.blue.offset = 0;
+ info->var.red.length = info->var.green.length =
+ info->var.blue.length = 8;
+ if (fb->depth == 32) {
+ info->var.transp.offset = 24;
+ info->var.transp.length = 8;
+ }
+ break;
+ }
+
+ if (register_framebuffer(info) < 0)
+ return -EINVAL;
+
+ printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+ info->fix.id);
+ return 0;
+}
+EXPORT_SYMBOL(drmfb_probe);
+
+int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
+{
+ struct fb_info *info = fb->fbdev;
+
+ if (info) {
+ iounmap(fb->virtual_base);
+ unregister_framebuffer(info);
+ framebuffer_release(info);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(drmfb_remove);
+MODULE_LICENSE("GPL");
diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c
index 61c128cb..5af86f82 100644
--- a/shared-core/i915_init.c
+++ b/shared-core/i915_init.c
@@ -28,11 +28,11 @@ int i915_driver_load(drm_device_t *dev, unsigned long flags)
if (IS_I9XX(dev)) {
dev_priv->mmiobase = drm_get_resource_start(dev, 0);
dev_priv->mmiolen = drm_get_resource_len(dev, 0);
- dev_priv->baseaddr = drm_get_resource_start(dev, 2) & 0xff000000;
+ dev->mode_config.fb_base = dev_priv->baseaddr = drm_get_resource_start(dev, 2) & 0xff000000;
} else if (drm_get_resource_start(dev, 1)) {
dev_priv->mmiobase = drm_get_resource_start(dev, 1);
dev_priv->mmiolen = drm_get_resource_len(dev, 1);
- dev_priv->baseaddr = drm_get_resource_start(dev, 0) & 0xff000000;
+ dev->mode_config.fb_base = dev_priv->baseaddr = drm_get_resource_start(dev, 0) & 0xff000000;
} else {
DRM_ERROR("Unable to find MMIO registers\n");
return -ENODEV;