aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2014-06-28 06:44:07 -0400
committerBen Skeggs <bskeggs@redhat.com>2014-08-09 15:11:08 -0400
commit4b5098f3597195e9faf17e5a0cfca905d9a04d9f (patch)
tree8d5cf3a6e87ee3be4608424439c1a12df943c198 /drivers
parent7238eca4cf18a5bba8679afc8c71a274e264f82e (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.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c92
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.h4
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
215void
216nouveau_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
225void
226nouveau_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
234void
235nouveau_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
247void
248nouveau_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
215static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, 267static 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
507void 548void
508nouveau_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
517void
518nouveau_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
526void
527nouveau_fbcon_set_suspend(struct drm_device *dev, int state) 549nouveau_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);
61int nouveau_fbcon_init(struct drm_device *dev); 61int nouveau_fbcon_init(struct drm_device *dev);
62void nouveau_fbcon_fini(struct drm_device *dev); 62void nouveau_fbcon_fini(struct drm_device *dev);
63void nouveau_fbcon_set_suspend(struct drm_device *dev, int state); 63void nouveau_fbcon_set_suspend(struct drm_device *dev, int state);
64void nouveau_fbcon_save_disable_accel(struct drm_device *dev); 64void nouveau_fbcon_accel_save_disable(struct drm_device *dev);
65void nouveau_fbcon_restore_accel(struct drm_device *dev); 65void nouveau_fbcon_accel_restore(struct drm_device *dev);
66 66
67void nouveau_fbcon_output_poll_changed(struct drm_device *dev); 67void nouveau_fbcon_output_poll_changed(struct drm_device *dev);
68#endif /* __NV50_FBCON_H__ */ 68#endif /* __NV50_FBCON_H__ */