diff options
author | Dave Airlie <airlied@redhat.com> | 2010-03-30 01:34:18 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-04-06 20:30:38 -0400 |
commit | 4abe35204af82a018ca3ce6db4102aa09719698e (patch) | |
tree | fcc91e2e109fe311a673d5b99dc758aba3bb4a79 /drivers/gpu/drm/nouveau/nouveau_fbcon.c | |
parent | 5c4426a782bc9509573fc7958a786ebd14fafdf3 (diff) |
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>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_fbcon.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fbcon.c | 45 |
1 files changed, 28 insertions, 17 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index fd5d3cde0a07..bc81ec7dc131 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c | |||
@@ -156,11 +156,6 @@ static void nouveau_fbcon_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
156 | *blue = nv_crtc->lut.b[regno]; | 156 | *blue = nv_crtc->lut.b[regno]; |
157 | } | 157 | } |
158 | 158 | ||
159 | static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = { | ||
160 | .gamma_set = nouveau_fbcon_gamma_set, | ||
161 | .gamma_get = nouveau_fbcon_gamma_get | ||
162 | }; | ||
163 | |||
164 | #if defined(__i386__) || defined(__x86_64__) | 159 | #if defined(__i386__) || defined(__x86_64__) |
165 | static bool | 160 | static bool |
166 | nouveau_fbcon_has_vesafb_or_efifb(struct drm_device *dev) | 161 | nouveau_fbcon_has_vesafb_or_efifb(struct drm_device *dev) |
@@ -272,6 +267,12 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, | |||
272 | goto out_unref; | 267 | goto out_unref; |
273 | } | 268 | } |
274 | 269 | ||
270 | ret = fb_alloc_cmap(&info->cmap, 256, 0); | ||
271 | if (ret) { | ||
272 | ret = -ENOMEM; | ||
273 | goto out_unref; | ||
274 | } | ||
275 | |||
275 | info->par = nfbdev; | 276 | info->par = nfbdev; |
276 | 277 | ||
277 | nouveau_framebuffer_init(dev, &nfbdev->nouveau_fb, &mode_cmd, nvbo); | 278 | nouveau_framebuffer_init(dev, &nfbdev->nouveau_fb, &mode_cmd, nvbo); |
@@ -282,7 +283,6 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, | |||
282 | /* setup helper */ | 283 | /* setup helper */ |
283 | nfbdev->helper.fb = fb; | 284 | nfbdev->helper.fb = fb; |
284 | nfbdev->helper.fbdev = info; | 285 | nfbdev->helper.fbdev = info; |
285 | nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs; | ||
286 | 286 | ||
287 | strcpy(info->fix.id, "nouveaufb"); | 287 | strcpy(info->fix.id, "nouveaufb"); |
288 | if (nouveau_nofbaccel) | 288 | if (nouveau_nofbaccel) |
@@ -381,12 +381,15 @@ nouveau_fbcon_find_or_create_single(struct drm_fb_helper *helper, | |||
381 | return new_fb; | 381 | return new_fb; |
382 | } | 382 | } |
383 | 383 | ||
384 | static int | 384 | void nouveau_fbcon_hotplug(struct drm_device *dev) |
385 | nouveau_fbcon_probe(struct nouveau_fbdev *nfbdev) | ||
386 | { | 385 | { |
387 | NV_DEBUG_KMS(nfbdev->dev, "\n"); | 386 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
387 | drm_helper_fb_hpd_irq_event(&dev_priv->nfbdev->helper); | ||
388 | } | ||
388 | 389 | ||
389 | return drm_fb_helper_single_fb_probe(&nfbdev->helper, 32); | 390 | static void nouveau_fbcon_output_status_changed(struct drm_fb_helper *fb_helper) |
391 | { | ||
392 | drm_helper_fb_hotplug_event(fb_helper, true); | ||
390 | } | 393 | } |
391 | 394 | ||
392 | int | 395 | int |
@@ -398,6 +401,8 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev) | |||
398 | if (nfbdev->helper.fbdev) { | 401 | if (nfbdev->helper.fbdev) { |
399 | info = nfbdev->helper.fbdev; | 402 | info = nfbdev->helper.fbdev; |
400 | unregister_framebuffer(info); | 403 | unregister_framebuffer(info); |
404 | if (info->cmap.len) | ||
405 | fb_dealloc_cmap(&info->cmap); | ||
401 | framebuffer_release(info); | 406 | framebuffer_release(info); |
402 | } | 407 | } |
403 | 408 | ||
@@ -406,7 +411,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev) | |||
406 | drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem); | 411 | drm_gem_object_unreference_unlocked(nouveau_fb->nvbo->gem); |
407 | nouveau_fb->nvbo = NULL; | 412 | nouveau_fb->nvbo = NULL; |
408 | } | 413 | } |
409 | drm_fb_helper_free(&nfbdev->helper); | 414 | drm_fb_helper_fini(&nfbdev->helper); |
410 | drm_framebuffer_cleanup(&nouveau_fb->base); | 415 | drm_framebuffer_cleanup(&nouveau_fb->base); |
411 | return 0; | 416 | return 0; |
412 | } | 417 | } |
@@ -420,6 +425,14 @@ void nouveau_fbcon_gpu_lockup(struct fb_info *info) | |||
420 | info->flags |= FBINFO_HWACCEL_DISABLED; | 425 | info->flags |= FBINFO_HWACCEL_DISABLED; |
421 | } | 426 | } |
422 | 427 | ||
428 | static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = { | ||
429 | .gamma_set = nouveau_fbcon_gamma_set, | ||
430 | .gamma_get = nouveau_fbcon_gamma_get, | ||
431 | .fb_probe = nouveau_fbcon_find_or_create_single, | ||
432 | .fb_output_status_changed = nouveau_fbcon_output_status_changed, | ||
433 | }; | ||
434 | |||
435 | |||
423 | int nouveau_fbcon_init(struct drm_device *dev) | 436 | int nouveau_fbcon_init(struct drm_device *dev) |
424 | { | 437 | { |
425 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 438 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
@@ -431,14 +444,12 @@ int nouveau_fbcon_init(struct drm_device *dev) | |||
431 | 444 | ||
432 | nfbdev->dev = dev; | 445 | nfbdev->dev = dev; |
433 | dev_priv->nfbdev = nfbdev; | 446 | dev_priv->nfbdev = nfbdev; |
447 | nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs; | ||
434 | 448 | ||
435 | drm_fb_helper_init_crtc_count(dev, &nfbdev->helper, | 449 | drm_fb_helper_init(dev, &nfbdev->helper, |
436 | 2, 4); | 450 | 2, 4, true); |
437 | nfbdev->helper.fb_probe = nouveau_fbcon_find_or_create_single; | ||
438 | drm_fb_helper_single_add_all_connectors(&nfbdev->helper); | 451 | drm_fb_helper_single_add_all_connectors(&nfbdev->helper); |
439 | 452 | drm_fb_helper_initial_config(&nfbdev->helper, 32); | |
440 | drm_fb_helper_initial_config(&nfbdev->helper); | ||
441 | nouveau_fbcon_probe(nfbdev); | ||
442 | return 0; | 453 | return 0; |
443 | } | 454 | } |
444 | 455 | ||