diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2014-06-28 06:44:07 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2014-08-09 15:11:08 -0400 |
commit | 4b5098f3597195e9faf17e5a0cfca905d9a04d9f (patch) | |
tree | 8d5cf3a6e87ee3be4608424439c1a12df943c198 /drivers | |
parent | 7238eca4cf18a5bba8679afc8c71a274e264f82e (diff) |
drm/nouveau/kms: take more care when pulling down accelerated fbcon
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/nouveau/dispnv04/crtc.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fbcon.c | 92 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fbcon.h | 4 |
3 files changed, 61 insertions, 39 deletions
diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 41be3424c906..8b17d7d49e26 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c | |||
@@ -915,9 +915,9 @@ nv04_crtc_mode_set_base_atomic(struct drm_crtc *crtc, | |||
915 | struct drm_device *dev = drm->dev; | 915 | struct drm_device *dev = drm->dev; |
916 | 916 | ||
917 | if (state == ENTER_ATOMIC_MODE_SET) | 917 | if (state == ENTER_ATOMIC_MODE_SET) |
918 | nouveau_fbcon_save_disable_accel(dev); | 918 | nouveau_fbcon_accel_save_disable(dev); |
919 | else | 919 | else |
920 | nouveau_fbcon_restore_accel(dev); | 920 | nouveau_fbcon_accel_restore(dev); |
921 | 921 | ||
922 | return nv04_crtc_do_mode_set_base(crtc, fb, x, y, true); | 922 | return nv04_crtc_do_mode_set_base(crtc, fb, x, y, true); |
923 | } | 923 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 758c11cb9a9a..ba004932435a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c | |||
@@ -212,6 +212,58 @@ static struct fb_ops nouveau_fbcon_sw_ops = { | |||
212 | .fb_debug_leave = drm_fb_helper_debug_leave, | 212 | .fb_debug_leave = drm_fb_helper_debug_leave, |
213 | }; | 213 | }; |
214 | 214 | ||
215 | void | ||
216 | nouveau_fbcon_accel_save_disable(struct drm_device *dev) | ||
217 | { | ||
218 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
219 | if (drm->fbcon) { | ||
220 | drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags; | ||
221 | drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | void | ||
226 | nouveau_fbcon_accel_restore(struct drm_device *dev) | ||
227 | { | ||
228 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
229 | if (drm->fbcon) { | ||
230 | drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags; | ||
231 | } | ||
232 | } | ||
233 | |||
234 | void | ||
235 | nouveau_fbcon_accel_fini(struct drm_device *dev) | ||
236 | { | ||
237 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
238 | struct nouveau_fbdev *fbcon = drm->fbcon; | ||
239 | if (fbcon && drm->channel) { | ||
240 | console_lock(); | ||
241 | fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED; | ||
242 | console_unlock(); | ||
243 | nouveau_channel_idle(drm->channel); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | void | ||
248 | nouveau_fbcon_accel_init(struct drm_device *dev) | ||
249 | { | ||
250 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
251 | struct nouveau_fbdev *fbcon = drm->fbcon; | ||
252 | struct fb_info *info = fbcon->helper.fbdev; | ||
253 | int ret; | ||
254 | |||
255 | if (nv_device(drm->device)->card_type < NV_50) | ||
256 | ret = nv04_fbcon_accel_init(info); | ||
257 | else | ||
258 | if (nv_device(drm->device)->card_type < NV_C0) | ||
259 | ret = nv50_fbcon_accel_init(info); | ||
260 | else | ||
261 | ret = nvc0_fbcon_accel_init(info); | ||
262 | |||
263 | if (ret == 0) | ||
264 | info->fbops = &nouveau_fbcon_ops; | ||
265 | } | ||
266 | |||
215 | static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, | 267 | static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, |
216 | u16 blue, int regno) | 268 | u16 blue, int regno) |
217 | { | 269 | { |
@@ -357,20 +409,8 @@ nouveau_fbcon_create(struct drm_fb_helper *helper, | |||
357 | 409 | ||
358 | mutex_unlock(&dev->struct_mutex); | 410 | mutex_unlock(&dev->struct_mutex); |
359 | 411 | ||
360 | if (chan) { | 412 | if (chan) |
361 | ret = -ENODEV; | 413 | nouveau_fbcon_accel_init(dev); |
362 | if (device->card_type < NV_50) | ||
363 | ret = nv04_fbcon_accel_init(info); | ||
364 | else | ||
365 | if (device->card_type < NV_C0) | ||
366 | ret = nv50_fbcon_accel_init(info); | ||
367 | else | ||
368 | ret = nvc0_fbcon_accel_init(info); | ||
369 | |||
370 | if (ret == 0) | ||
371 | info->fbops = &nouveau_fbcon_ops; | ||
372 | } | ||
373 | |||
374 | nouveau_fbcon_zfill(dev, fbcon); | 414 | nouveau_fbcon_zfill(dev, fbcon); |
375 | 415 | ||
376 | /* To allow resizeing without swapping buffers */ | 416 | /* To allow resizeing without swapping buffers */ |
@@ -499,41 +539,23 @@ nouveau_fbcon_fini(struct drm_device *dev) | |||
499 | if (!drm->fbcon) | 539 | if (!drm->fbcon) |
500 | return; | 540 | return; |
501 | 541 | ||
542 | nouveau_fbcon_accel_fini(dev); | ||
502 | nouveau_fbcon_destroy(dev, drm->fbcon); | 543 | nouveau_fbcon_destroy(dev, drm->fbcon); |
503 | kfree(drm->fbcon); | 544 | kfree(drm->fbcon); |
504 | drm->fbcon = NULL; | 545 | drm->fbcon = NULL; |
505 | } | 546 | } |
506 | 547 | ||
507 | void | 548 | void |
508 | nouveau_fbcon_save_disable_accel(struct drm_device *dev) | ||
509 | { | ||
510 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
511 | if (drm->fbcon) { | ||
512 | drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags; | ||
513 | drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED; | ||
514 | } | ||
515 | } | ||
516 | |||
517 | void | ||
518 | nouveau_fbcon_restore_accel(struct drm_device *dev) | ||
519 | { | ||
520 | struct nouveau_drm *drm = nouveau_drm(dev); | ||
521 | if (drm->fbcon) { | ||
522 | drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags; | ||
523 | } | ||
524 | } | ||
525 | |||
526 | void | ||
527 | nouveau_fbcon_set_suspend(struct drm_device *dev, int state) | 549 | nouveau_fbcon_set_suspend(struct drm_device *dev, int state) |
528 | { | 550 | { |
529 | struct nouveau_drm *drm = nouveau_drm(dev); | 551 | struct nouveau_drm *drm = nouveau_drm(dev); |
530 | if (drm->fbcon) { | 552 | if (drm->fbcon) { |
531 | console_lock(); | 553 | console_lock(); |
532 | if (state == 1) | 554 | if (state == 1) |
533 | nouveau_fbcon_save_disable_accel(dev); | 555 | nouveau_fbcon_accel_save_disable(dev); |
534 | fb_set_suspend(drm->fbcon->helper.fbdev, state); | 556 | fb_set_suspend(drm->fbcon->helper.fbdev, state); |
535 | if (state == 0) { | 557 | if (state == 0) { |
536 | nouveau_fbcon_restore_accel(dev); | 558 | nouveau_fbcon_accel_restore(dev); |
537 | nouveau_fbcon_zfill(dev, drm->fbcon); | 559 | nouveau_fbcon_zfill(dev, drm->fbcon); |
538 | } | 560 | } |
539 | console_unlock(); | 561 | console_unlock(); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h index fcff797d2084..6d857e2869c9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h | |||
@@ -61,8 +61,8 @@ void nouveau_fbcon_gpu_lockup(struct fb_info *info); | |||
61 | int nouveau_fbcon_init(struct drm_device *dev); | 61 | int nouveau_fbcon_init(struct drm_device *dev); |
62 | void nouveau_fbcon_fini(struct drm_device *dev); | 62 | void nouveau_fbcon_fini(struct drm_device *dev); |
63 | void nouveau_fbcon_set_suspend(struct drm_device *dev, int state); | 63 | void nouveau_fbcon_set_suspend(struct drm_device *dev, int state); |
64 | void nouveau_fbcon_save_disable_accel(struct drm_device *dev); | 64 | void nouveau_fbcon_accel_save_disable(struct drm_device *dev); |
65 | void nouveau_fbcon_restore_accel(struct drm_device *dev); | 65 | void nouveau_fbcon_accel_restore(struct drm_device *dev); |
66 | 66 | ||
67 | void nouveau_fbcon_output_poll_changed(struct drm_device *dev); | 67 | void nouveau_fbcon_output_poll_changed(struct drm_device *dev); |
68 | #endif /* __NV50_FBCON_H__ */ | 68 | #endif /* __NV50_FBCON_H__ */ |