aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nouveau_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_display.c')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c40
1 files changed, 26 insertions, 14 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index a85e112863d1..69688ef5cf46 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -33,7 +33,9 @@
33#include "nouveau_crtc.h" 33#include "nouveau_crtc.h"
34#include "nouveau_dma.h" 34#include "nouveau_dma.h"
35#include "nouveau_connector.h" 35#include "nouveau_connector.h"
36#include "nouveau_software.h"
36#include "nouveau_gpio.h" 37#include "nouveau_gpio.h"
38#include "nouveau_fence.h"
37#include "nv50_display.h" 39#include "nv50_display.h"
38 40
39static void 41static void
@@ -300,7 +302,7 @@ nouveau_display_create(struct drm_device *dev)
300 disp->color_vibrance_property->values[1] = 200; /* -100..+100 */ 302 disp->color_vibrance_property->values[1] = 200; /* -100..+100 */
301 } 303 }
302 304
303 dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; 305 dev->mode_config.funcs = &nouveau_mode_config_funcs;
304 dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1); 306 dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1);
305 307
306 dev->mode_config.min_width = 0; 308 dev->mode_config.min_width = 0;
@@ -325,14 +327,21 @@ nouveau_display_create(struct drm_device *dev)
325 327
326 ret = disp->create(dev); 328 ret = disp->create(dev);
327 if (ret) 329 if (ret)
328 return ret; 330 goto disp_create_err;
329 331
330 if (dev->mode_config.num_crtc) { 332 if (dev->mode_config.num_crtc) {
331 ret = drm_vblank_init(dev, dev->mode_config.num_crtc); 333 ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
332 if (ret) 334 if (ret)
333 return ret; 335 goto vblank_err;
334 } 336 }
335 337
338 return 0;
339
340vblank_err:
341 disp->destroy(dev);
342disp_create_err:
343 drm_kms_helper_poll_fini(dev);
344 drm_mode_config_cleanup(dev);
336 return ret; 345 return ret;
337} 346}
338 347
@@ -425,6 +434,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
425 struct nouveau_page_flip_state *s, 434 struct nouveau_page_flip_state *s,
426 struct nouveau_fence **pfence) 435 struct nouveau_fence **pfence)
427{ 436{
437 struct nouveau_software_chan *swch = chan->engctx[NVOBJ_ENGINE_SW];
428 struct drm_nouveau_private *dev_priv = chan->dev->dev_private; 438 struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
429 struct drm_device *dev = chan->dev; 439 struct drm_device *dev = chan->dev;
430 unsigned long flags; 440 unsigned long flags;
@@ -432,7 +442,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
432 442
433 /* Queue it to the pending list */ 443 /* Queue it to the pending list */
434 spin_lock_irqsave(&dev->event_lock, flags); 444 spin_lock_irqsave(&dev->event_lock, flags);
435 list_add_tail(&s->head, &chan->nvsw.flip); 445 list_add_tail(&s->head, &swch->flip);
436 spin_unlock_irqrestore(&dev->event_lock, flags); 446 spin_unlock_irqrestore(&dev->event_lock, flags);
437 447
438 /* Synchronize with the old framebuffer */ 448 /* Synchronize with the old framebuffer */
@@ -446,17 +456,17 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
446 goto fail; 456 goto fail;
447 457
448 if (dev_priv->card_type < NV_C0) { 458 if (dev_priv->card_type < NV_C0) {
449 BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); 459 BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
450 OUT_RING (chan, 0x00000000); 460 OUT_RING (chan, 0x00000000);
451 OUT_RING (chan, 0x00000000); 461 OUT_RING (chan, 0x00000000);
452 } else { 462 } else {
453 BEGIN_NVC0(chan, 2, 0, NV10_SUBCHAN_REF_CNT, 1); 463 BEGIN_NVC0(chan, 0, NV10_SUBCHAN_REF_CNT, 1);
454 OUT_RING (chan, ++chan->fence.sequence); 464 OUT_RING (chan, 0);
455 BEGIN_NVC0(chan, 8, 0, NVSW_SUBCHAN_PAGE_FLIP, 0x0000); 465 BEGIN_IMC0(chan, 0, NVSW_SUBCHAN_PAGE_FLIP, 0x0000);
456 } 466 }
457 FIRE_RING (chan); 467 FIRE_RING (chan);
458 468
459 ret = nouveau_fence_new(chan, pfence, true); 469 ret = nouveau_fence_new(chan, pfence);
460 if (ret) 470 if (ret)
461 goto fail; 471 goto fail;
462 472
@@ -477,7 +487,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
477 struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo; 487 struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo;
478 struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo; 488 struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo;
479 struct nouveau_page_flip_state *s; 489 struct nouveau_page_flip_state *s;
480 struct nouveau_channel *chan; 490 struct nouveau_channel *chan = NULL;
481 struct nouveau_fence *fence; 491 struct nouveau_fence *fence;
482 int ret; 492 int ret;
483 493
@@ -500,7 +510,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
500 new_bo->bo.offset }; 510 new_bo->bo.offset };
501 511
502 /* Choose the channel the flip will be handled in */ 512 /* Choose the channel the flip will be handled in */
503 chan = nouveau_fence_channel(new_bo->bo.sync_obj); 513 fence = new_bo->bo.sync_obj;
514 if (fence)
515 chan = nouveau_channel_get_unlocked(fence->channel);
504 if (!chan) 516 if (!chan)
505 chan = nouveau_channel_get_unlocked(dev_priv->channel); 517 chan = nouveau_channel_get_unlocked(dev_priv->channel);
506 mutex_lock(&chan->mutex); 518 mutex_lock(&chan->mutex);
@@ -540,20 +552,20 @@ int
540nouveau_finish_page_flip(struct nouveau_channel *chan, 552nouveau_finish_page_flip(struct nouveau_channel *chan,
541 struct nouveau_page_flip_state *ps) 553 struct nouveau_page_flip_state *ps)
542{ 554{
555 struct nouveau_software_chan *swch = chan->engctx[NVOBJ_ENGINE_SW];
543 struct drm_device *dev = chan->dev; 556 struct drm_device *dev = chan->dev;
544 struct nouveau_page_flip_state *s; 557 struct nouveau_page_flip_state *s;
545 unsigned long flags; 558 unsigned long flags;
546 559
547 spin_lock_irqsave(&dev->event_lock, flags); 560 spin_lock_irqsave(&dev->event_lock, flags);
548 561
549 if (list_empty(&chan->nvsw.flip)) { 562 if (list_empty(&swch->flip)) {
550 NV_ERROR(dev, "Unexpected pageflip in channel %d.\n", chan->id); 563 NV_ERROR(dev, "Unexpected pageflip in channel %d.\n", chan->id);
551 spin_unlock_irqrestore(&dev->event_lock, flags); 564 spin_unlock_irqrestore(&dev->event_lock, flags);
552 return -EINVAL; 565 return -EINVAL;
553 } 566 }
554 567
555 s = list_first_entry(&chan->nvsw.flip, 568 s = list_first_entry(&swch->flip, struct nouveau_page_flip_state, head);
556 struct nouveau_page_flip_state, head);
557 if (s->event) { 569 if (s->event) {
558 struct drm_pending_vblank_event *e = s->event; 570 struct drm_pending_vblank_event *e = s->event;
559 struct timeval now; 571 struct timeval now;