summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_fb.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c694
1 files changed, 75 insertions, 619 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index ec383edf5f3..b38c4c8e2c6 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -28,15 +28,7 @@
*/
#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"
#include "drm.h"
@@ -45,375 +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 >> 8) & 0xff) << info->var.red.offset) |
- (((green >> 8) & 0xff) << info->var.green.offset) |
- (((blue >> 8) & 0xff) << info->var.blue.offset);
- 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;
-#ifdef __LITTLE_ENDIAN
- 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;
-#else
- case 24:
- var->red.offset = 8;
- var->green.offset = 16;
- var->blue.offset = 24;
- 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 = 8;
- var->green.offset = 16;
- var->blue.offset = 24;
- var->red.length = 8;
- var->green.length = 8;
- var->blue.length = 8;
- var->transp.length = 8;
- var->transp.offset = 0;
- break;
-#endif
- 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,
};
/**
@@ -456,21 +98,6 @@ 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, bool tiled)
{
int aligned = width;
@@ -495,11 +122,18 @@ static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bo
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,
+ .gamma_get = radeon_crtc_fb_gamma_get,
+};
+
+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;
@@ -513,13 +147,20 @@ int radeonfb_create(struct radeon_device *rdev,
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;
+
+ /* avivo can't scanout real 24bpp */
+ if ((surface_bpp == 24) && ASIC_IS_AVIVO(rdev))
+ surface_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, fb_tiled) * ((mode_cmd.bpp + 1) / 8);
- mode_cmd.depth = 24;
+ mode_cmd.depth = surface_depth;
size = mode_cmd.pitch * mode_cmd.height;
aligned_size = ALIGN(size, PAGE_SIZE);
@@ -537,7 +178,22 @@ int radeonfb_create(struct radeon_device *rdev,
robj = gobj->driver_private;
if (fb_tiled)
- radeon_object_set_tiling_flags(robj, RADEON_TILING_MACRO|RADEON_TILING_SURFACE, mode_cmd.pitch);
+ 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) {
@@ -554,8 +210,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;
@@ -564,7 +220,19 @@ 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);
@@ -577,33 +245,19 @@ int radeonfb_create(struct radeon_device *rdev,
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_NONE;
- 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;
+
+ 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;
@@ -626,83 +280,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;
-#ifdef __LITTLE_ENDIAN
- 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;
-#else
- case 24:
- info->var.red.offset = 8;
- info->var.green.offset = 16;
- info->var.blue.offset = 24;
- 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 = 8;
- info->var.green.offset = 16;
- info->var.blue.offset = 24;
- info->var.red.length = 8;
- info->var.green.length = 8;
- info->var.blue.length = 8;
- info->var.transp.offset = 0;
- info->var.transp.length = 8;
- break;
- default:
-#endif
- break;
- }
-
fb->fbdev = info;
rfbdev->rfb = rfb;
rfbdev->rdev = rdev;
@@ -726,148 +303,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, 32, &radeonfb_create);
}
-EXPORT_SYMBOL(radeonfb_probe);
int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
{
@@ -880,16 +335,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);