X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fgpu%2Fdrm%2Fradeon%2Fradeon_fb.c;h=c32f44096feccbccf474c3e2ca0619696950f15e;hb=068143d38804825d59d951a192cfadd2e22f457d;hp=09987089193e2576613e6e2ce2a7627d1098954d;hpb=f92e93eb5f4d56d73215f089580d53597bacd468;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 0998708..c32f440 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -28,15 +28,7 @@ */ #include -#include -#include -#include -#include -#include -#include -#include #include -#include #include "drmP.h" #include "drm.h" @@ -45,351 +37,25 @@ #include "radeon_drm.h" #include "radeon.h" +#include "drm_fb_helper.h" + struct radeon_fb_device { - struct radeon_device *rdev; - struct drm_display_mode *mode; + struct drm_fb_helper helper; struct radeon_framebuffer *rfb; - int crtc_count; - /* crtc currently bound to this */ - uint32_t crtc_ids[2]; + struct radeon_device *rdev; }; -static int radeonfb_setcolreg(unsigned regno, - unsigned red, - unsigned green, - unsigned blue, - unsigned transp, - struct fb_info *info) -{ - struct radeon_fb_device *rfbdev = info->par; - struct drm_device *dev = rfbdev->rdev->ddev; - struct drm_crtc *crtc; - int i; - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - struct drm_mode_set *modeset = &radeon_crtc->mode_set; - struct drm_framebuffer *fb = modeset->fb; - - for (i = 0; i < rfbdev->crtc_count; i++) { - if (crtc->base.id == rfbdev->crtc_ids[i]) { - break; - } - } - if (i == rfbdev->crtc_count) { - continue; - } - if (regno > 255) { - return 1; - } - if (fb->depth == 8) { - radeon_crtc_fb_gamma_set(crtc, red, green, blue, regno); - return 0; - } - - 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: - case 32: - fb->pseudo_palette[regno] = ((red & 0xff00) << 8) | - (green & 0xff00) | - ((blue & 0xff00) >> 8); - break; - } - } - } - return 0; -} - -static int radeonfb_check_var(struct fb_var_screeninfo *var, - struct fb_info *info) -{ - struct radeon_fb_device *rfbdev = info->par; - struct radeon_framebuffer *rfb = rfbdev->rfb; - struct drm_framebuffer *fb = &rfb->base; - int depth; - - if (var->pixclock == -1 || !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 = 5; - 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; - } - return 0; -} - -/* this will let fbcon do the mode init */ -static int radeonfb_set_par(struct fb_info *info) -{ - struct radeon_fb_device *rfbdev = info->par; - struct drm_device *dev = rfbdev->rdev->ddev; - struct fb_var_screeninfo *var = &info->var; - struct drm_crtc *crtc; - int ret; - int i; - - if (var->pixclock != -1) { - DRM_ERROR("PIXEL CLCOK SET\n"); - return -EINVAL; - } - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - - for (i = 0; i < rfbdev->crtc_count; i++) { - if (crtc->base.id == rfbdev->crtc_ids[i]) { - break; - } - } - if (i == rfbdev->crtc_count) { - continue; - } - if (crtc->fb == radeon_crtc->mode_set.fb) { - mutex_lock(&dev->mode_config.mutex); - ret = crtc->funcs->set_config(&radeon_crtc->mode_set); - mutex_unlock(&dev->mode_config.mutex); - if (ret) { - return ret; - } - } - } - return 0; -} - -static int radeonfb_pan_display(struct fb_var_screeninfo *var, - struct fb_info *info) -{ - struct radeon_fb_device *rfbdev = info->par; - struct drm_device *dev = rfbdev->rdev->ddev; - struct drm_mode_set *modeset; - struct drm_crtc *crtc; - struct radeon_crtc *radeon_crtc; - int ret = 0; - int i; - - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - for (i = 0; i < rfbdev->crtc_count; i++) { - if (crtc->base.id == rfbdev->crtc_ids[i]) { - break; - } - } - - if (i == rfbdev->crtc_count) { - continue; - } - - radeon_crtc = to_radeon_crtc(crtc); - modeset = &radeon_crtc->mode_set; - - modeset->x = var->xoffset; - modeset->y = var->yoffset; - - if (modeset->num_connectors) { - mutex_lock(&dev->mode_config.mutex); - ret = crtc->funcs->set_config(modeset); - mutex_unlock(&dev->mode_config.mutex); - if (!ret) { - info->var.xoffset = var->xoffset; - info->var.yoffset = var->yoffset; - } - } - } - return ret; -} - -static void radeonfb_on(struct fb_info *info) -{ - struct radeon_fb_device *rfbdev = info->par; - struct drm_device *dev = rfbdev->rdev->ddev; - struct drm_crtc *crtc; - struct drm_encoder *encoder; - int i; - - /* - * For each CRTC in this fb, find all associated encoders - * and turn them off, then turn off the CRTC. - */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; - - for (i = 0; i < rfbdev->crtc_count; i++) { - if (crtc->base.id == rfbdev->crtc_ids[i]) { - break; - } - } - - mutex_lock(&dev->mode_config.mutex); - crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); - mutex_unlock(&dev->mode_config.mutex); - - /* Found a CRTC on this fb, now find encoders */ - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - if (encoder->crtc == crtc) { - struct drm_encoder_helper_funcs *encoder_funcs; - - encoder_funcs = encoder->helper_private; - mutex_lock(&dev->mode_config.mutex); - encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); - mutex_unlock(&dev->mode_config.mutex); - } - } - } -} - -static void radeonfb_off(struct fb_info *info, int dpms_mode) -{ - struct radeon_fb_device *rfbdev = info->par; - struct drm_device *dev = rfbdev->rdev->ddev; - struct drm_crtc *crtc; - struct drm_encoder *encoder; - int i; - - /* - * For each CRTC in this fb, find all associated encoders - * and turn them off, then turn off the CRTC. - */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; - - for (i = 0; i < rfbdev->crtc_count; i++) { - if (crtc->base.id == rfbdev->crtc_ids[i]) { - break; - } - } - - /* Found a CRTC on this fb, now find encoders */ - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - if (encoder->crtc == crtc) { - struct drm_encoder_helper_funcs *encoder_funcs; - - encoder_funcs = encoder->helper_private; - mutex_lock(&dev->mode_config.mutex); - encoder_funcs->dpms(encoder, dpms_mode); - mutex_unlock(&dev->mode_config.mutex); - } - } - if (dpms_mode == DRM_MODE_DPMS_OFF) { - mutex_lock(&dev->mode_config.mutex); - crtc_funcs->dpms(crtc, dpms_mode); - mutex_unlock(&dev->mode_config.mutex); - } - } -} - -int radeonfb_blank(int blank, struct fb_info *info) -{ - switch (blank) { - case FB_BLANK_UNBLANK: - radeonfb_on(info); - break; - case FB_BLANK_NORMAL: - radeonfb_off(info, DRM_MODE_DPMS_STANDBY); - break; - case FB_BLANK_HSYNC_SUSPEND: - radeonfb_off(info, DRM_MODE_DPMS_STANDBY); - break; - case FB_BLANK_VSYNC_SUSPEND: - radeonfb_off(info, DRM_MODE_DPMS_SUSPEND); - break; - case FB_BLANK_POWERDOWN: - radeonfb_off(info, DRM_MODE_DPMS_OFF); - break; - } - return 0; -} - static struct fb_ops radeonfb_ops = { .owner = THIS_MODULE, - .fb_check_var = radeonfb_check_var, - .fb_set_par = radeonfb_set_par, - .fb_setcolreg = radeonfb_setcolreg, + .fb_check_var = drm_fb_helper_check_var, + .fb_set_par = drm_fb_helper_set_par, + .fb_setcolreg = drm_fb_helper_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_pan_display = radeonfb_pan_display, - .fb_blank = radeonfb_blank, + .fb_pan_display = drm_fb_helper_pan_display, + .fb_blank = drm_fb_helper_blank, + .fb_setcmap = drm_fb_helper_setcmap, }; /** @@ -432,25 +98,10 @@ int radeonfb_resize(struct drm_device *dev, struct drm_crtc *crtc) } EXPORT_SYMBOL(radeonfb_resize); -static struct drm_mode_set panic_mode; - -int radeonfb_panic(struct notifier_block *n, unsigned long ununsed, - void *panic_str) -{ - DRM_ERROR("panic occurred, switching back to text console\n"); - drm_crtc_helper_set_config(&panic_mode); - return 0; -} -EXPORT_SYMBOL(radeonfb_panic); - -static struct notifier_block paniced = { - .notifier_call = radeonfb_panic, -}; - -static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp) +static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled) { int aligned = width; - int align_large = (ASIC_IS_AVIVO(rdev)); + int align_large = (ASIC_IS_AVIVO(rdev)) || tiled; int pitch_mask = 0; switch (bpp / 8) { @@ -471,11 +122,17 @@ static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp) return aligned; } -int radeonfb_create(struct radeon_device *rdev, +static struct drm_fb_helper_funcs radeon_fb_helper_funcs = { + .gamma_set = radeon_crtc_fb_gamma_set, +}; + +int radeonfb_create(struct drm_device *dev, uint32_t fb_width, uint32_t fb_height, uint32_t surface_width, uint32_t surface_height, - struct radeon_framebuffer **rfb_p) + uint32_t surface_depth, uint32_t surface_bpp, + struct drm_framebuffer **fb_p) { + struct radeon_device *rdev = dev->dev_private; struct fb_info *info; struct radeon_fb_device *rfbdev; struct drm_framebuffer *fb = NULL; @@ -488,13 +145,16 @@ int radeonfb_create(struct radeon_device *rdev, u64 fb_gpuaddr; void *fbptr = NULL; unsigned long tmp; + bool fb_tiled = false; /* useful for testing */ + u32 tiling_flags = 0; + int crtc_count; mode_cmd.width = surface_width; mode_cmd.height = surface_height; - mode_cmd.bpp = 32; + mode_cmd.bpp = surface_bpp; /* need to align pitch with crtc limits */ - mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp) * ((mode_cmd.bpp + 1) / 8); - mode_cmd.depth = 24; + mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8); + mode_cmd.depth = surface_depth; size = mode_cmd.pitch * mode_cmd.height; aligned_size = ALIGN(size, PAGE_SIZE); @@ -511,6 +171,23 @@ int radeonfb_create(struct radeon_device *rdev, } robj = gobj->driver_private; + if (fb_tiled) + tiling_flags = RADEON_TILING_MACRO; + +#ifdef __BIG_ENDIAN + switch (mode_cmd.bpp) { + case 32: + tiling_flags |= RADEON_TILING_SWAP_32BIT; + break; + case 16: + tiling_flags |= RADEON_TILING_SWAP_16BIT; + default: + break; + } +#endif + + if (tiling_flags) + radeon_object_set_tiling_flags(robj, tiling_flags | RADEON_TILING_SURFACE, mode_cmd.pitch); mutex_lock(&rdev->ddev->struct_mutex); fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj); if (fb == NULL) { @@ -527,8 +204,8 @@ int radeonfb_create(struct radeon_device *rdev, list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list); + *fb_p = fb; rfb = to_radeon_framebuffer(fb); - *rfb_p = rfb; rdev->fbdev_rfb = rfb; rdev->fbdev_robj = robj; @@ -537,43 +214,51 @@ int radeonfb_create(struct radeon_device *rdev, ret = -ENOMEM; goto out_unref; } + + rdev->fbdev_info = info; rfbdev = info->par; + rfbdev->helper.funcs = &radeon_fb_helper_funcs; + rfbdev->helper.dev = dev; + if (rdev->flags & RADEON_SINGLE_CRTC) + crtc_count = 1; + else + crtc_count = 2; + ret = drm_fb_helper_init_crtc_count(&rfbdev->helper, crtc_count, + RADEONFB_CONN_LIMIT); + if (ret) + goto out_unref; + + if (fb_tiled) + radeon_object_check_tiling(robj, 0, 0); ret = radeon_object_kmap(robj, &fbptr); if (ret) { goto out_unref; } + memset_io(fbptr, 0, aligned_size); + strcpy(info->fix.id, "radeondrmfb"); - info->fix.type = FB_TYPE_PACKED_PIXELS; - info->fix.visual = FB_VISUAL_TRUECOLOR; - info->fix.type_aux = 0; - info->fix.xpanstep = 1; /* doing it in hw */ - info->fix.ypanstep = 1; /* doing it in hw */ - info->fix.ywrapstep = 0; - info->fix.accel = FB_ACCEL_I830; - info->fix.type_aux = 0; + + drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); + info->flags = FBINFO_DEFAULT; info->fbops = &radeonfb_ops; - info->fix.line_length = fb->pitch; + tmp = fb_gpuaddr - rdev->mc.vram_location; info->fix.smem_start = rdev->mc.aper_base + tmp; info->fix.smem_len = size; info->screen_base = fbptr; info->screen_size = size; - info->pseudo_palette = fb->pseudo_palette; - info->var.xres_virtual = fb->width; - info->var.yres_virtual = fb->height; - 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.xres = fb_width; - info->var.yres = fb_height; - info->fix.mmio_start = pci_resource_start(rdev->pdev, 2); - info->fix.mmio_len = pci_resource_len(rdev->pdev, 2); + + drm_fb_helper_fill_var(info, fb, fb_width, fb_height); + + /* setup aperture base/size for vesafb takeover */ + info->aperture_base = rdev->ddev->mode_config.fb_base; + info->aperture_size = rdev->mc.real_vram_size; + + info->fix.mmio_start = 0; + info->fix.mmio_len = 0; info->pixmap.size = 64*1024; info->pixmap.buf_align = 8; info->pixmap.access_align = 32; @@ -589,60 +274,6 @@ int radeonfb_create(struct radeon_device *rdev, DRM_INFO("fb depth is %d\n", fb->depth); DRM_INFO(" pitch is %d\n", fb->pitch); - 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 = 5; - info->var.green.length = 5; - 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; - break; - case 24: - info->var.red.offset = 16; - info->var.green.offset = 8; - info->var.blue.offset = 0; - info->var.red.length = 8; - info->var.green.length = 8; - 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 = 8; - info->var.green.length = 8; - info->var.blue.length = 8; - info->var.transp.offset = 24; - info->var.transp.length = 8; - break; - default: - break; - } - fb->fbdev = info; rfbdev->rfb = rfb; rfbdev->rdev = rdev; @@ -666,148 +297,26 @@ out: return ret; } -static int radeonfb_single_fb_probe(struct radeon_device *rdev) +static char *mode_option; +int radeon_parse_options(char *options) { - struct drm_crtc *crtc; - struct drm_connector *connector; - unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1; - unsigned int surface_width = 0, surface_height = 0; - int new_fb = 0; - int crtc_count = 0; - int ret, i, conn_count = 0; - struct radeon_framebuffer *rfb; - struct fb_info *info; - struct radeon_fb_device *rfbdev; - struct drm_mode_set *modeset = NULL; - - /* first up get a count of crtcs now in use and new min/maxes width/heights */ - list_for_each_entry(crtc, &rdev->ddev->mode_config.crtc_list, head) { - if (drm_helper_crtc_in_use(crtc)) { - if (crtc->desired_mode) { - if (crtc->desired_mode->hdisplay < fb_width) - fb_width = crtc->desired_mode->hdisplay; - - if (crtc->desired_mode->vdisplay < fb_height) - fb_height = crtc->desired_mode->vdisplay; - - if (crtc->desired_mode->hdisplay > surface_width) - surface_width = crtc->desired_mode->hdisplay; - - if (crtc->desired_mode->vdisplay > surface_height) - surface_height = crtc->desired_mode->vdisplay; - } - crtc_count++; - } - } + char *this_opt; - if (crtc_count == 0 || fb_width == -1 || fb_height == -1) { - /* hmm everyone went away - assume VGA cable just fell out - and will come back later. */ + if (!options || !*options) return 0; - } - /* do we have an fb already? */ - if (list_empty(&rdev->ddev->mode_config.fb_kernel_list)) { - /* create an fb if we don't have one */ - ret = radeonfb_create(rdev, fb_width, fb_height, surface_width, surface_height, &rfb); - if (ret) { - return -EINVAL; - } - new_fb = 1; - } else { - struct drm_framebuffer *fb; - fb = list_first_entry(&rdev->ddev->mode_config.fb_kernel_list, struct drm_framebuffer, filp_head); - rfb = to_radeon_framebuffer(fb); - - /* if someone hotplugs something bigger than we have already allocated, we are pwned. - As really we can't resize an fbdev that is in the wild currently due to fbdev - not really being designed for the lower layers moving stuff around under it. - - so in the grand style of things - punt. */ - if ((fb->width < surface_width) || (fb->height < surface_height)) { - DRM_ERROR("Framebuffer not large enough to scale console onto.\n"); - return -EINVAL; - } - } - - info = rfb->base.fbdev; - rdev->fbdev_info = info; - rfbdev = info->par; - - crtc_count = 0; - /* okay we need to setup new connector sets in the crtcs */ - list_for_each_entry(crtc, &rdev->ddev->mode_config.crtc_list, head) { - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - modeset = &radeon_crtc->mode_set; - modeset->fb = &rfb->base; - conn_count = 0; - list_for_each_entry(connector, &rdev->ddev->mode_config.connector_list, head) { - if (connector->encoder) - if (connector->encoder->crtc == modeset->crtc) { - modeset->connectors[conn_count] = connector; - conn_count++; - if (conn_count > RADEONFB_CONN_LIMIT) - BUG(); - } - } - - for (i = conn_count; i < RADEONFB_CONN_LIMIT; i++) - modeset->connectors[i] = NULL; - - - rfbdev->crtc_ids[crtc_count++] = crtc->base.id; - - modeset->num_connectors = conn_count; - if (modeset->crtc->desired_mode) { - if (modeset->mode) { - drm_mode_destroy(rdev->ddev, modeset->mode); - } - modeset->mode = drm_mode_duplicate(rdev->ddev, - modeset->crtc->desired_mode); - } - } - rfbdev->crtc_count = crtc_count; - - if (new_fb) { - info->var.pixclock = -1; - if (register_framebuffer(info) < 0) - return -EINVAL; - } else { - radeonfb_set_par(info); + while ((this_opt = strsep(&options, ",")) != NULL) { + if (!*this_opt) + continue; + mode_option = this_opt; } - printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, - info->fix.id); - - /* Switch back to kernel console on panic */ - panic_mode = *modeset; - atomic_notifier_chain_register(&panic_notifier_list, &paniced); - printk(KERN_INFO "registered panic notifier\n"); - return 0; } int radeonfb_probe(struct drm_device *dev) { - int ret; - - /* something has changed in the lower levels of hell - deal with it - here */ - - /* two modes : a) 1 fb to rule all crtcs. - b) one fb per crtc. - two actions 1) new connected device - 2) device removed. - case a/1 : if the fb surface isn't big enough - resize the surface fb. - if the fb size isn't big enough - resize fb into surface. - if everything big enough configure the new crtc/etc. - case a/2 : undo the configuration - possibly resize down the fb to fit the new configuration. - case b/1 : see if it is on a new crtc - setup a new fb and add it. - case b/2 : teardown the new fb. - */ - ret = radeonfb_single_fb_probe(dev->dev_private); - return ret; + return drm_fb_helper_single_fb_probe(dev, &radeonfb_create); } -EXPORT_SYMBOL(radeonfb_probe); int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) { @@ -820,16 +329,17 @@ int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) } info = fb->fbdev; if (info) { + struct radeon_fb_device *rfbdev = info->par; robj = rfb->obj->driver_private; unregister_framebuffer(info); radeon_object_kunmap(robj); radeon_object_unpin(robj); + drm_fb_helper_free(&rfbdev->helper); framebuffer_release(info); } printk(KERN_INFO "unregistered panic notifier\n"); - atomic_notifier_chain_unregister(&panic_notifier_list, &paniced); - memset(&panic_mode, 0, sizeof(struct drm_mode_set)); + return 0; } EXPORT_SYMBOL(radeonfb_remove);