drm/kms/fb: use slow work mechanism for normal hotplug also.

a) slow work is always used now for any fbcon hotplug, as its not
   a fast task and is more suited to being ran under slow work.

b) attempt to not do any fbdev changes when X is running as we'll
   just mess it up. This hooks set_par to hopefully do the changes
   once X hands control to fbdev.

This also adds the nouveau/intel hotplug support.

Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Dave Airlie
2010-03-30 05:34:18 +00:00
parent 5c4426a782
commit 4abe35204a
9 changed files with 242 additions and 183 deletions

View File

@@ -86,11 +86,6 @@ static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bo
return aligned;
}
static struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
.gamma_set = radeon_crtc_fb_gamma_set,
.gamma_get = radeon_crtc_fb_gamma_get,
};
static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj)
{
struct radeon_bo *rbo = gobj->driver_private;
@@ -222,7 +217,6 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
/* setup helper */
rfbdev->helper.fb = fb;
rfbdev->helper.fbdev = info;
rfbdev->helper.funcs = &radeon_fb_helper_funcs;
memset_io(rbo->kptr, 0x0, radeon_bo_size(rbo));
@@ -252,10 +246,18 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
info->pixmap.access_align = 32;
info->pixmap.flags = FB_PIXMAP_SYSTEM;
info->pixmap.scan_align = 1;
if (info->screen_base == NULL) {
ret = -ENOSPC;
goto out_unref;
}
ret = fb_alloc_cmap(&info->cmap, 256, 0);
if (ret) {
ret = -ENOMEM;
goto out_unref;
}
DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start);
DRM_INFO("vram apper at 0x%lX\n", (unsigned long)rdev->mc.aper_base);
DRM_INFO("size %lu\n", (unsigned long)radeon_bo_size(rbo));
@@ -309,33 +311,16 @@ int radeon_parse_options(char *options)
return 0;
}
static int radeonfb_probe(struct radeon_fbdev *rfbdev)
{
struct radeon_device *rdev = rfbdev->rdev;
int bpp_sel = 32;
/* select 8 bpp console on RN50 or 16MB cards */
if (ASIC_IS_RN50(rdev) || rdev->mc.real_vram_size <= (32*1024*1024))
bpp_sel = 8;
return drm_fb_helper_single_fb_probe(&rfbdev->helper, bpp_sel);
}
void radeonfb_hotplug(struct drm_device *dev, bool polled)
{
struct radeon_device *rdev = dev->dev_private;
int max_width, max_height;
max_width = rdev->mode_info.rfbdev->rfb.base.width;
max_height = rdev->mode_info.rfbdev->rfb.base.height;
drm_helper_fb_hotplug_event(&rdev->mode_info.rfbdev->helper, max_width, max_height, polled);
radeonfb_probe(rdev->mode_info.rfbdev);
drm_helper_fb_hpd_irq_event(&rdev->mode_info.rfbdev->helper);
}
static void radeon_fb_poll_changed(struct drm_fb_helper *fb_helper)
static void radeon_fb_output_status_changed(struct drm_fb_helper *fb_helper)
{
radeonfb_hotplug(fb_helper->dev, true);
drm_helper_fb_hotplug_event(fb_helper, true);
}
static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfbdev)
@@ -347,7 +332,10 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb
if (rfbdev->helper.fbdev) {
info = rfbdev->helper.fbdev;
unregister_framebuffer(info);
if (info->cmap.len)
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
}
@@ -361,16 +349,27 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb
}
drm_gem_object_unreference_unlocked(rfb->obj);
}
drm_fb_helper_free(&rfbdev->helper);
drm_fb_helper_fini(&rfbdev->helper);
drm_framebuffer_cleanup(&rfb->base);
return 0;
}
MODULE_LICENSE("GPL");
static struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
.gamma_set = radeon_crtc_fb_gamma_set,
.gamma_get = radeon_crtc_fb_gamma_get,
.fb_probe = radeon_fb_find_or_create_single,
.fb_output_status_changed = radeon_fb_output_status_changed,
};
int radeon_fbdev_init(struct radeon_device *rdev)
{
struct radeon_fbdev *rfbdev;
int bpp_sel = 32;
/* select 8 bpp console on RN50 or 16MB cards */
if (ASIC_IS_RN50(rdev) || rdev->mc.real_vram_size <= (32*1024*1024))
bpp_sel = 8;
rfbdev = kzalloc(sizeof(struct radeon_fbdev), GFP_KERNEL);
if (!rfbdev)
@@ -378,20 +377,13 @@ int radeon_fbdev_init(struct radeon_device *rdev)
rfbdev->rdev = rdev;
rdev->mode_info.rfbdev = rfbdev;
rfbdev->helper.funcs = &radeon_fb_helper_funcs;
drm_fb_helper_init_crtc_count(rdev->ddev, &rfbdev->helper,
rdev->num_crtc,
RADEONFB_CONN_LIMIT);
rfbdev->helper.fb_probe = radeon_fb_find_or_create_single;
drm_fb_helper_init(rdev->ddev, &rfbdev->helper,
rdev->num_crtc,
RADEONFB_CONN_LIMIT, true);
drm_fb_helper_single_add_all_connectors(&rfbdev->helper);
rfbdev->helper.fb_poll_changed = radeon_fb_poll_changed;
drm_fb_helper_poll_init(&rfbdev->helper);
drm_fb_helper_initial_config(&rfbdev->helper);
radeonfb_probe(rfbdev);
drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel);
return 0;
}
@@ -401,7 +393,6 @@ void radeon_fbdev_fini(struct radeon_device *rdev)
if (!rdev->mode_info.rfbdev)
return;
drm_fb_helper_poll_fini(&rdev->mode_info.rfbdev->helper);
radeon_fbdev_destroy(rdev->ddev, rdev->mode_info.rfbdev);
kfree(rdev->mode_info.rfbdev);
rdev->mode_info.rfbdev = NULL;
@@ -428,4 +419,3 @@ bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
return true;
return false;
}