From 32f6a58db216f23a7c71ca9c7eda56aaa8293078 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 11 Apr 2007 16:33:03 +1000 Subject: 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. --- linux-core/drm_fb.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 linux-core/drm_fb.c (limited to 'linux-core/drm_fb.c') 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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"); -- cgit v1.2.3 From c582eaac194411f52a2c0527ffa093b5a422d7b9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 11 Apr 2007 16:34:40 +1000 Subject: add copyright statement --- linux-core/drm_fb.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'linux-core/drm_fb.c') diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index 9bf2187c..1fe3e54b 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -1,3 +1,28 @@ +/* + * Copyright © 2007 David Airlie + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * David Airlie + */ /* * Modularization */ -- cgit v1.2.3 From 1147fefed8d1154482c9cc9a9785e6871cd6e6a1 Mon Sep 17 00:00:00 2001 From: David Airlie Date: Wed, 11 Apr 2007 17:13:57 +1000 Subject: fixup framebuffer depth --- linux-core/drm_fb.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'linux-core/drm_fb.c') diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index 1fe3e54b..e404642f 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -53,8 +53,6 @@ static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green, 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: @@ -118,6 +116,7 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb) info->fix.smem_len = (8*1024*1024); info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = FB_VISUAL_DIRECTCOLOR; + info->fix.accel = FB_ACCEL_NONE; info->fix.type_aux = 0; info->fix.mmio_start = 0; info->fix.mmio_len = 0; @@ -141,12 +140,18 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb) info->var.bits_per_pixel = fb->bits_per_pixel; info->var.xoffset = 0; info->var.yoffset = 0; + info->var.activate = FB_ACTIVATE_NOW; + info->var.height = -1; + info->var.width = -1; + info->var.vmode = FB_VMODE_NONINTERLACED; + DRM_DEBUG("fb depth is %d\n", fb->depth); switch(fb->depth) { case 8: case 15: case 16: break; + default: case 24: case 32: info->var.red.offset = 16; -- cgit v1.2.3 From 0392badd84ec833ddd9e2b187844d246d860bbf7 Mon Sep 17 00:00:00 2001 From: David Airlie Date: Wed, 11 Apr 2007 17:25:37 +1000 Subject: oops for 32 pitch.. hey I can see stuff on fbcon now.. it looks like text.. just a bit garbled --- linux-core/drm_fb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux-core/drm_fb.c') diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index e404642f..30b14188 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -66,6 +66,7 @@ static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green, ((blue & 0xf800) >> 11); break; case 24: + case 32: fb->pseudo_palette[regno] = ((red & 0xff00) << 8) | (green & 0xff00) | ((blue & 0xff00) >> 8); -- cgit v1.2.3 From 7e48d47fb51cc0f1a38a99acfe591821a45d7081 Mon Sep 17 00:00:00 2001 From: David Airlie Date: Wed, 11 Apr 2007 17:35:00 +1000 Subject: line_length calculation was incorrect.. I now can get fbcon to run --- linux-core/drm_fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/drm_fb.c') diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index 30b14188..1a0fb79c 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -121,7 +121,7 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb) info->fix.type_aux = 0; info->fix.mmio_start = 0; info->fix.mmio_len = 0; - info->fix.line_length = fb->pitch; + info->fix.line_length = fb->pitch * ((fb->bits_per_pixel + 1) / 8); info->flags = FBINFO_DEFAULT; -- cgit v1.2.3 From fb6c5aacb9955248300e0c62f68a5a65b40e15e1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 12 Apr 2007 11:54:49 +1000 Subject: only initialise modes when fbcon or fbset asks for it --- linux-core/drm_fb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'linux-core/drm_fb.c') diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index 1a0fb79c..a70e4d52 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -77,6 +77,15 @@ static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green, return 0; } +/* this will let fbcon do the mode init */ +static int drmfb_set_par(struct fb_info *info) +{ + struct drmfb_par *par = info->par; + struct drm_device *dev = par->dev; + + drm_set_desired_modes(dev); +} + static struct fb_ops drmfb_ops = { .owner = THIS_MODULE, // .fb_open = drmfb_open, @@ -84,6 +93,7 @@ static struct fb_ops drmfb_ops = { // .fb_write = drmfb_write, // .fb_release = drmfb_release, // .fb_ioctl = drmfb_ioctl, + .fb_set_par = drmfb_set_par, .fb_setcolreg = drmfb_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, -- cgit v1.2.3 From 2aa183db1ff0fb6044d24eae51854ff128da9a0f Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Sat, 14 Apr 2007 15:35:38 -0700 Subject: Use drm_mem_reg_ioremap to map buffer object. --- linux-core/drm_fb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'linux-core/drm_fb.c') diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index a70e4d52..df979cd1 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -107,6 +107,7 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb) struct device *device = &dev->pdev->dev; struct fb_var_screeninfo *var_info; unsigned long base, size; + int ret; info = framebuffer_alloc(sizeof(struct drmfb_par), device); if (!info){ @@ -139,7 +140,9 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb) size = (fb->bo->mem.num_pages * PAGE_SIZE); DRM_DEBUG("remapping %08X %d\n", base, size); - fb->virtual_base = ioremap_nocache(base, size); + ret = drm_mem_reg_ioremap(dev, &fb->bo->mem, &fb->virtual_base); + if (ret) + DRM_ERROR("error mapping fb: %d\n", ret); info->screen_base = fb->virtual_base; info->screen_size = size; -- cgit v1.2.3 From 79aa1d54746f33c33ffbf98fb96ccbf88c3cb390 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 17 Apr 2007 18:16:38 +1000 Subject: another large overhaul of interactions with userspace... We need to keep a list of user created fbs to nuke on master exit. We also need to use the bo properly. --- linux-core/drm_fb.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'linux-core/drm_fb.c') diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index df979cd1..ef05341a 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -84,6 +84,7 @@ static int drmfb_set_par(struct fb_info *info) struct drm_device *dev = par->dev; drm_set_desired_modes(dev); + return 0; } static struct fb_ops drmfb_ops = { @@ -136,10 +137,6 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb) 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); ret = drm_mem_reg_ioremap(dev, &fb->bo->mem, &fb->virtual_base); if (ret) DRM_ERROR("error mapping fb: %d\n", ret); @@ -194,7 +191,7 @@ int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) struct fb_info *info = fb->fbdev; if (info) { - iounmap(fb->virtual_base); + drm_mem_reg_iounmap(dev, &fb->bo->mem, fb->virtual_base); unregister_framebuffer(info); framebuffer_release(info); } -- cgit v1.2.3 From eba00df1203040905d38bf0ef449d25d6dbdb72c Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Thu, 10 May 2007 13:16:05 +0100 Subject: Just some minor cleanups. --- linux-core/drm_fb.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'linux-core/drm_fb.c') diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index ef05341a..c0453258 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -106,8 +106,7 @@ 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; + unsigned long size = (8*1024*1024); /* FIXME */ int ret; info = framebuffer_alloc(sizeof(struct drmfb_par), device); @@ -126,7 +125,7 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb) 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.smem_len = size; info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = FB_VISUAL_DIRECTCOLOR; info->fix.accel = FB_ACCEL_NONE; -- cgit v1.2.3 From 5ce8aaae7251e60c078eda0a21894aae0e1d7a45 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 17 May 2007 12:46:36 +0100 Subject: Large changes for fbdev support. Change from DIRECTCOLOR to TRUECOLOR, and enable support for PSEUDOCOLOR. DIRECTCOLOR support needs more work. Add the ability to change the mode on the fbdev device. Support depth 8, 15, 16 and 24 (and 32). Add a /dev/fbX device per CRTC, but there's some code which doesn't allocate the fbX device unless the output is actually enabled. Read the code on this as it impacts the fbcon map flags. Pick CRTC's based on the available outputs. More work could be done here to match modes, so cloning could be achieved on outputs. This fits more inline with what the X code does. --- linux-core/drm_fb.c | 267 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 248 insertions(+), 19 deletions(-) (limited to 'linux-core/drm_fb.c') diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index c0453258..8fd0f620 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -39,9 +39,11 @@ #include #include "drmP.h" +#include "drm_crtc.h" + struct drmfb_par { struct drm_device *dev; - struct drm_framebuffer *fb; + struct drm_crtc *crtc; }; static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green, @@ -49,11 +51,20 @@ static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green, struct fb_info *info) { struct drmfb_par *par = info->par; - struct drm_framebuffer *fb = par->fb; - if (regno > 17) + struct drm_framebuffer *fb = par->crtc->fb; + struct drm_crtc *crtc = par->crtc; + + if (regno > 255) return 1; - if (regno < 16) { + if (fb->depth == 8) { + if (crtc->funcs->gamma_set) { + crtc->funcs->gamma_set(crtc, red, green, blue, regno); + } + return 0; + } + + if (regno < 16) { switch (fb->depth) { case 15: fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) | @@ -72,8 +83,118 @@ static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green, ((blue & 0xff00) >> 8); break; } + } + + return 0; +} + +static int drmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + struct drmfb_par *par = info->par; + struct drm_device *dev = par->dev; + struct drm_display_mode *drm_mode; + struct drm_output *output; + int depth; + + if (!var->pixclock) + return -EINVAL; + + /* Need to resize the fb object !!! */ + if (var->xres > fb->width || var->yres > fb->height) { + DRM_ERROR("Requested width/height is greater than current fb object %dx%d > %dx%d\n",var->xres,var->yres,fb->width,fb->height); + DRM_ERROR("Need resizing code.\n"); + return -EINVAL; + } + + switch (var->bits_per_pixel) { + case 16: + depth = (var->green.length == 6) ? 16 : 15; + break; + case 32: + depth = (var->transp.length > 0) ? 32 : 24; + break; + default: + depth = var->bits_per_pixel; + break; + } + + switch (depth) { + case 8: + var->red.offset = 0; + var->green.offset = 0; + var->blue.offset = 0; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + var->transp.length = 0; + var->transp.offset = 0; + break; + case 15: + var->red.offset = 10; + var->green.offset = 5; + var->blue.offset = 0; + var->red.length = 5; + var->green.length = 5; + var->blue.length = 5; + var->transp.length = 1; + var->transp.offset = 15; + break; + case 16: + var->red.offset = 11; + var->green.offset = 6; + var->blue.offset = 0; + var->red.length = 5; + var->green.length = 6; + var->blue.length = 5; + var->transp.length = 0; + var->transp.offset = 0; + break; + case 24: + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + var->transp.length = 0; + var->transp.offset = 0; + break; + case 32: + var->red.offset = 16; + var->green.offset = 8; + var->blue.offset = 0; + var->red.length = 8; + var->green.length = 8; + var->blue.length = 8; + var->transp.length = 8; + var->transp.offset = 24; + break; + default: + return -EINVAL; + } + +#if 0 + /* Here we walk the output mode list and look for modes. If we haven't + * got it, then bail. Not very nice, so this is disabled. + * In the set_par code, we create our mode based on the incoming + * parameters. Nicer, but may not be desired by some. + */ + list_for_each_entry(output, &dev->mode_config.output_list, head) { + if (output->crtc == par->crtc) + break; + } + + list_for_each_entry(drm_mode, &output->modes, head) { + if (drm_mode->hdisplay == var->xres && + drm_mode->vdisplay == var->yres && + drm_mode->clock != 0) + break; } + if (!drm_mode) + return -EINVAL; +#endif + return 0; } @@ -81,9 +202,74 @@ static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green, static int drmfb_set_par(struct fb_info *info) { struct drmfb_par *par = info->par; + struct drm_framebuffer *fb = par->crtc->fb; struct drm_device *dev = par->dev; + struct drm_display_mode *drm_mode; + struct fb_var_screeninfo *var = &info->var; + struct drm_output *output; + + switch (var->bits_per_pixel) { + case 16: + fb->depth = (var->green.length == 6) ? 16 : 15; + break; + case 32: + fb->depth = (var->transp.length > 0) ? 32 : 24; + break; + default: + fb->depth = var->bits_per_pixel; + break; + } + + fb->bits_per_pixel = var->bits_per_pixel; + + info->fix.line_length = fb->pitch * ((fb->bits_per_pixel + 1) / 8); + info->fix.smem_len = info->fix.line_length * fb->height; + info->fix.visual = (fb->depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; + + info->screen_size = info->fix.smem_len; /* ??? */ + + /* Should we walk the output's modelist or just create our own ??? + * For now, we create and destroy a mode based on the incoming + * parameters. But there's commented out code below which scans + * the output list too. + */ +#if 0 + list_for_each_entry(output, &dev->mode_config.output_list, head) { + if (output->crtc == par->crtc) + break; + } + + list_for_each_entry(drm_mode, &output->modes, head) { + if (drm_mode->hdisplay == var->xres && + drm_mode->vdisplay == var->yres && + drm_mode->clock != 0) + break; + } +#else + drm_mode = drm_mode_create(dev); + drm_mode->hdisplay = var->xres; + drm_mode->hsync_start = drm_mode->hdisplay + var->right_margin; + drm_mode->hsync_end = drm_mode->hsync_start + var->hsync_len; + drm_mode->htotal = drm_mode->hsync_end + var->left_margin; + drm_mode->vdisplay = var->yres; + drm_mode->vsync_start = drm_mode->vdisplay + var->lower_margin; + drm_mode->vsync_end = drm_mode->vsync_start + var->vsync_len; + drm_mode->vtotal = drm_mode->vsync_end + var->upper_margin; + drm_mode->clock = PICOS2KHZ(var->pixclock); + drm_mode->vrefresh = drm_mode_vrefresh(drm_mode); + drm_mode_set_name(drm_mode); +#endif + + if (!drm_crtc_set_mode(par->crtc, drm_mode, 0, 0)) + return -EINVAL; + + /* Have to destroy our created mode if we're not searching the mode + * list for it. + */ +#if 1 + drm_mode_destroy(dev, drm_mode); +#endif - drm_set_desired_modes(dev); return 0; } @@ -94,6 +280,7 @@ static struct fb_ops drmfb_ops = { // .fb_write = drmfb_write, // .fb_release = drmfb_release, // .fb_ioctl = drmfb_ioctl, + .fb_check_var = drmfb_check_var, .fb_set_par = drmfb_set_par, .fb_setcolreg = drmfb_setcolreg, .fb_fillrect = cfb_fillrect, @@ -101,12 +288,13 @@ static struct fb_ops drmfb_ops = { .fb_imageblit = cfb_imageblit, }; -int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb) +int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc) { struct fb_info *info; + struct drm_framebuffer *fb = crtc->fb; struct drmfb_par *par; struct device *device = &dev->pdev->dev; - unsigned long size = (8*1024*1024); /* FIXME */ + struct drm_display_mode *mode = crtc->desired_mode; int ret; info = framebuffer_alloc(sizeof(struct drmfb_par), device); @@ -119,20 +307,20 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb) par = info->par; par->dev = dev; - par->fb = fb; + par->crtc = crtc; info->fbops = &drmfb_ops; strcpy(info->fix.id, "drmfb"); - info->fix.smem_start = fb->offset + dev->mode_config.fb_base; - info->fix.smem_len = size; info->fix.type = FB_TYPE_PACKED_PIXELS; - info->fix.visual = FB_VISUAL_DIRECTCOLOR; + info->fix.visual = FB_VISUAL_TRUECOLOR; info->fix.accel = FB_ACCEL_NONE; info->fix.type_aux = 0; info->fix.mmio_start = 0; info->fix.mmio_len = 0; info->fix.line_length = fb->pitch * ((fb->bits_per_pixel + 1) / 8); + info->fix.smem_start = fb->offset + dev->mode_config.fb_base; + info->fix.smem_len = info->fix.line_length * fb->height; info->flags = FBINFO_DEFAULT; @@ -141,11 +329,9 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb) DRM_ERROR("error mapping fb: %d\n", ret); info->screen_base = fb->virtual_base; - info->screen_size = size; + info->screen_size = info->fix.smem_len; /* ??? */ 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; @@ -155,24 +341,67 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb) info->var.width = -1; info->var.vmode = FB_VMODE_NONINTERLACED; + info->var.xres = mode->hdisplay; + info->var.right_margin = mode->hsync_start - mode->hdisplay; + info->var.hsync_len = mode->hsync_end - mode->hsync_start; + info->var.left_margin = mode->htotal - mode->hsync_end; + info->var.yres = mode->vdisplay; + info->var.lower_margin = mode->vsync_start - mode->vdisplay; + info->var.vsync_len = mode->vsync_end - mode->vsync_start; + info->var.upper_margin = mode->vtotal - mode->vsync_end; + info->var.pixclock = 10000000 / mode->htotal * 1000 / + mode->vtotal * 100000 / mode->vrefresh; + DRM_DEBUG("fb depth is %d\n", fb->depth); switch(fb->depth) { case 8: + info->var.red.offset = 0; + info->var.green.offset = 0; + info->var.blue.offset = 0; + info->var.red.length = 8; /* 8bit DAC */ + info->var.green.length = 8; + info->var.blue.length = 8; + info->var.transp.offset = 0; + info->var.transp.length = 0; + break; case 15: + info->var.red.offset = 10; + info->var.green.offset = 5; + info->var.blue.offset = 0; + info->var.red.length = info->var.green.length = + info->var.blue.length = 5; + info->var.transp.offset = 15; + info->var.transp.length = 1; + break; case 16: + info->var.red.offset = 11; + info->var.green.offset = 5; + info->var.blue.offset = 0; + info->var.red.length = 5; + info->var.green.length = 6; + info->var.blue.length = 5; + info->var.transp.offset = 0; + info->var.transp.length = 0; break; - default: case 24: + 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; + info->var.transp.offset = 0; + info->var.transp.length = 0; + break; 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; - } + info->var.transp.offset = 24; + info->var.transp.length = 8; + break; + default: break; } -- cgit v1.2.3 From 2222bd767f9fc02d05ebd0f35a8ceeff2f032c94 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Thu, 17 May 2007 13:19:56 +0100 Subject: Fix build problem --- linux-core/drm_fb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux-core/drm_fb.c') diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index 8fd0f620..27d80d7a 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -92,6 +92,7 @@ static int drmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct drmfb_par *par = info->par; struct drm_device *dev = par->dev; + struct drm_framebuffer *fb = par->crtc->fb; struct drm_display_mode *drm_mode; struct drm_output *output; int depth; -- cgit v1.2.3 From a18b4befb9b76c4b2662ff6caa0e4f0975eb8e9c Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 17 May 2007 09:00:06 -0700 Subject: Fix FB pitch value (we had it wrong and were working around it in a few places). Add new FB hooks to the drm driver structure and make i915 use them for an Intel specific FB driver. This will allow acceleration and better handling of the command stream. --- linux-core/drm_fb.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'linux-core/drm_fb.c') diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index ef05341a..1eb31952 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -106,8 +106,6 @@ 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; int ret; info = framebuffer_alloc(sizeof(struct drmfb_par), device); @@ -126,7 +124,7 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb) 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.smem_len = fb->bo->mem.size; info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = FB_VISUAL_DIRECTCOLOR; info->fix.accel = FB_ACCEL_NONE; @@ -142,7 +140,7 @@ int drmfb_probe(struct drm_device *dev, struct drm_framebuffer *fb) DRM_ERROR("error mapping fb: %d\n", ret); info->screen_base = fb->virtual_base; - info->screen_size = size; + info->screen_size = fb->bo->mem.size; info->pseudo_palette = fb->pseudo_palette; info->var.xres = fb->width; info->var.xres_virtual = fb->pitch; -- cgit v1.2.3 From fd63ea971322246734fca5977a800c3ef51cc3fe Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Thu, 17 May 2007 17:00:11 +0100 Subject: Grab the default mode if the preferred mode isn't available. Fix an overflow problem. --- linux-core/drm_fb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'linux-core/drm_fb.c') diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index 27d80d7a..118967bf 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -351,7 +351,9 @@ int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc) info->var.vsync_len = mode->vsync_end - mode->vsync_start; info->var.upper_margin = mode->vtotal - mode->vsync_end; info->var.pixclock = 10000000 / mode->htotal * 1000 / - mode->vtotal * 100000 / mode->vrefresh; + mode->vtotal * 100; + /* avoid overflow */ + info->var.pixclock = info->var.pixclock * 1000 / mode->vrefresh; DRM_DEBUG("fb depth is %d\n", fb->depth); switch(fb->depth) { -- cgit v1.2.3 From 95945bbf226610ba4f41381fd0436722082397ec Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Thu, 17 May 2007 23:33:48 +0100 Subject: Set crtcinfo on temporary mode --- linux-core/drm_fb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'linux-core/drm_fb.c') diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index 5f2b1cea..173864d0 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -259,6 +259,7 @@ static int drmfb_set_par(struct fb_info *info) drm_mode->clock = PICOS2KHZ(var->pixclock); drm_mode->vrefresh = drm_mode_vrefresh(drm_mode); drm_mode_set_name(drm_mode); + drm_mode_set_crtcinfo(drm_mode, CRTC_INTERLACE_HALVE_V); #endif if (!drm_crtc_set_mode(par->crtc, drm_mode, 0, 0)) -- cgit v1.2.3 From 0c33a2cd2ec81478403d39b1b92aaa4431e7cf0a Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Fri, 18 May 2007 14:16:10 +0100 Subject: Move fbo creation to the specified fb driver which gives it a chance to allocate the memory from whichever buffer it wants to. --- linux-core/drm_fb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'linux-core/drm_fb.c') diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index 173864d0..1531e96c 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -418,9 +418,10 @@ int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc) } EXPORT_SYMBOL(drmfb_probe); -int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) +int drmfb_remove(struct drm_device *dev, struct drm_crtc *crtc) { struct fb_info *info = fb->fbdev; + struct drm_framebuffer *fb = crtc->fb; if (info) { drm_mem_reg_iounmap(dev, &fb->bo->mem, fb->virtual_base); -- cgit v1.2.3 From f89458722173b364b8c3c27788b6c61889da554c Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Fri, 18 May 2007 09:40:01 -0700 Subject: Add locking. The main lock is dev->mode_config.config_lock. It should be held across any operations that modify mode lists, crtc config, output config, etc. It should be taken at high level entry points (currently just initial config and user IOCTL). Seems to work ok on my system, but needs more testing (with lockdep) and review from some fresh eyes. --- linux-core/drm_fb.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'linux-core/drm_fb.c') diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index 5f2b1cea..7a105d59 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -299,9 +299,8 @@ int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc) int ret; info = framebuffer_alloc(sizeof(struct drmfb_par), device); - if (!info){ - return -EINVAL; - } + if (!info) + return -ENOMEM; fb->fbdev = info; @@ -408,8 +407,10 @@ int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc) break; } - if (register_framebuffer(info) < 0) + if (register_framebuffer(info) < 0) { + unregister_framebuffer(info); return -EINVAL; + } printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id); -- cgit v1.2.3 From 4e7b24639808e5e1e2c05143028db1a3bc2812e9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 2 Jun 2008 14:04:41 +1000 Subject: drm: add functions to get/set gamma ramps --- linux-core/drm_fb.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'linux-core/drm_fb.c') diff --git a/linux-core/drm_fb.c b/linux-core/drm_fb.c index 775fd180..74a4394a 100644 --- a/linux-core/drm_fb.c +++ b/linux-core/drm_fb.c @@ -58,9 +58,6 @@ static int drmfb_setcolreg(unsigned regno, unsigned red, unsigned green, return 1; if (fb->depth == 8) { - if (crtc->funcs->gamma_set) { - crtc->funcs->gamma_set(crtc, red, green, blue, regno); - } return 0; } -- cgit v1.2.3