aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrancisco Jerez <currojerez@riseup.net>2010-10-21 12:19:29 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-12-03 00:11:11 -0500
commit042206c0cd4924879c4292c5ffa2bf1e8023ae5a (patch)
treec775b823b4e3d598e4fc41023a96e2e4b3126c20
parent63f7fcfebd2ff1995b649101d6120b60fa0e5b06 (diff)
drm/nouveau: Implement the vblank DRM hooks.
Signed-off-by: Francisco Jerez <currojerez@riseup.net> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c27
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_hw.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_irq.c8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_state.c12
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c16
-rw-r--r--drivers/gpu/drm/nouveau/nv50_graph.c9
8 files changed, 59 insertions, 26 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 2e11fd65b4dd..f8987bcb7f51 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -29,6 +29,7 @@
29#include "nouveau_drv.h" 29#include "nouveau_drv.h"
30#include "nouveau_fb.h" 30#include "nouveau_fb.h"
31#include "nouveau_fbcon.h" 31#include "nouveau_fbcon.h"
32#include "nouveau_hw.h"
32 33
33static void 34static void
34nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) 35nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
@@ -104,3 +105,29 @@ const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
104 .output_poll_changed = nouveau_fbcon_output_poll_changed, 105 .output_poll_changed = nouveau_fbcon_output_poll_changed,
105}; 106};
106 107
108int
109nouveau_vblank_enable(struct drm_device *dev, int crtc)
110{
111 struct drm_nouveau_private *dev_priv = dev->dev_private;
112
113 if (dev_priv->card_type >= NV_50)
114 nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, 0,
115 NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc));
116 else
117 NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0,
118 NV_PCRTC_INTR_0_VBLANK);
119
120 return 0;
121}
122
123void
124nouveau_vblank_disable(struct drm_device *dev, int crtc)
125{
126 struct drm_nouveau_private *dev_priv = dev->dev_private;
127
128 if (dev_priv->card_type >= NV_50)
129 nv_mask(dev, NV50_PDISPLAY_INTR_EN_1,
130 NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc), 0);
131 else
132 NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0);
133}
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index 15f48493d0d8..52f9307d7396 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -397,6 +397,9 @@ static struct drm_driver driver = {
397 .irq_postinstall = nouveau_irq_postinstall, 397 .irq_postinstall = nouveau_irq_postinstall,
398 .irq_uninstall = nouveau_irq_uninstall, 398 .irq_uninstall = nouveau_irq_uninstall,
399 .irq_handler = nouveau_irq_handler, 399 .irq_handler = nouveau_irq_handler,
400 .get_vblank_counter = drm_vblank_count,
401 .enable_vblank = nouveau_vblank_enable,
402 .disable_vblank = nouveau_vblank_disable,
400 .reclaim_buffers = drm_core_reclaim_buffers, 403 .reclaim_buffers = drm_core_reclaim_buffers,
401 .ioctls = nouveau_ioctls, 404 .ioctls = nouveau_ioctls,
402 .fops = { 405 .fops = {
@@ -407,6 +410,7 @@ static struct drm_driver driver = {
407 .mmap = nouveau_ttm_mmap, 410 .mmap = nouveau_ttm_mmap,
408 .poll = drm_poll, 411 .poll = drm_poll,
409 .fasync = drm_fasync, 412 .fasync = drm_fasync,
413 .read = drm_read,
410#if defined(CONFIG_COMPAT) 414#if defined(CONFIG_COMPAT)
411 .compat_ioctl = nouveau_compat_ioctl, 415 .compat_ioctl = nouveau_compat_ioctl,
412#endif 416#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index a356d894a2ee..7cf034fd5cd0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -1312,6 +1312,10 @@ extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *,
1312extern int nouveau_gem_ioctl_info(struct drm_device *, void *, 1312extern int nouveau_gem_ioctl_info(struct drm_device *, void *,
1313 struct drm_file *); 1313 struct drm_file *);
1314 1314
1315/* nouveau_display.c */
1316int nouveau_vblank_enable(struct drm_device *dev, int crtc);
1317void nouveau_vblank_disable(struct drm_device *dev, int crtc);
1318
1315/* nv10_gpio.c */ 1319/* nv10_gpio.c */
1316int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); 1320int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
1317int nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); 1321int nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.c b/drivers/gpu/drm/nouveau/nouveau_hw.c
index 979275836985..6ba640e7a7e9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_hw.c
+++ b/drivers/gpu/drm/nouveau/nouveau_hw.c
@@ -1017,8 +1017,9 @@ nv_load_state_ext(struct drm_device *dev, int head,
1017 1017
1018 NVWriteCRTC(dev, head, NV_PCRTC_START, regp->fb_start); 1018 NVWriteCRTC(dev, head, NV_PCRTC_START, regp->fb_start);
1019 1019
1020 /* Setting 1 on this value gives you interrupts for every vblank period. */ 1020 /* Enable vblank interrupts. */
1021 NVWriteCRTC(dev, head, NV_PCRTC_INTR_EN_0, 0); 1021 NVWriteCRTC(dev, head, NV_PCRTC_INTR_EN_0,
1022 (dev->vblank_enabled[head] ? 1 : 0));
1022 NVWriteCRTC(dev, head, NV_PCRTC_INTR_0, NV_PCRTC_INTR_0_VBLANK); 1023 NVWriteCRTC(dev, head, NV_PCRTC_INTR_0, NV_PCRTC_INTR_0_VBLANK);
1023} 1024}
1024 1025
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c
index 17e2fa86cde7..f3ae74ef3318 100644
--- a/drivers/gpu/drm/nouveau/nouveau_irq.c
+++ b/drivers/gpu/drm/nouveau/nouveau_irq.c
@@ -1200,11 +1200,15 @@ nv50_pgraph_irq_handler(struct drm_device *dev)
1200static void 1200static void
1201nouveau_crtc_irq_handler(struct drm_device *dev, int crtc) 1201nouveau_crtc_irq_handler(struct drm_device *dev, int crtc)
1202{ 1202{
1203 if (crtc & 1) 1203 if (crtc & 1) {
1204 nv_wr32(dev, NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK); 1204 nv_wr32(dev, NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK);
1205 drm_handle_vblank(dev, 0);
1206 }
1205 1207
1206 if (crtc & 2) 1208 if (crtc & 2) {
1207 nv_wr32(dev, NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK); 1209 nv_wr32(dev, NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK);
1210 drm_handle_vblank(dev, 1);
1211 }
1208} 1212}
1209 1213
1210irqreturn_t 1214irqreturn_t
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index c5f29f0d18da..d72aa8d19a19 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -669,13 +669,13 @@ nouveau_card_init(struct drm_device *dev)
669 if (ret) 669 if (ret)
670 goto out_fifo; 670 goto out_fifo;
671 671
672 ret = nouveau_irq_init(dev); 672 ret = drm_vblank_init(dev, nv_two_heads(dev) ? 2 : 1);
673 if (ret) 673 if (ret)
674 goto out_display; 674 goto out_vblank;
675 675
676 ret = drm_vblank_init(dev, 0); 676 ret = nouveau_irq_init(dev);
677 if (ret) 677 if (ret)
678 goto out_irq; 678 goto out_vblank;
679 679
680 /* what about PVIDEO/PCRTC/PRAMDAC etc? */ 680 /* what about PVIDEO/PCRTC/PRAMDAC etc? */
681 681
@@ -701,7 +701,8 @@ out_fence:
701 nouveau_fence_fini(dev); 701 nouveau_fence_fini(dev);
702out_irq: 702out_irq:
703 nouveau_irq_fini(dev); 703 nouveau_irq_fini(dev);
704out_display: 704out_vblank:
705 drm_vblank_cleanup(dev);
705 engine->display.destroy(dev); 706 engine->display.destroy(dev);
706out_fifo: 707out_fifo:
707 if (!nouveau_noaccel) 708 if (!nouveau_noaccel)
@@ -772,6 +773,7 @@ static void nouveau_card_takedown(struct drm_device *dev)
772 nouveau_mem_vram_fini(dev); 773 nouveau_mem_vram_fini(dev);
773 774
774 nouveau_irq_fini(dev); 775 nouveau_irq_fini(dev);
776 drm_vblank_cleanup(dev);
775 777
776 nouveau_pm_fini(dev); 778 nouveau_pm_fini(dev);
777 nouveau_bios_takedown(dev); 779 nouveau_bios_takedown(dev);
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 99871e304d10..17b950abf200 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -428,31 +428,29 @@ static void
428nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc) 428nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc)
429{ 429{
430 struct drm_nouveau_private *dev_priv = dev->dev_private; 430 struct drm_nouveau_private *dev_priv = dev->dev_private;
431 struct nouveau_channel *chan; 431 struct nouveau_channel *chan, *tmp;
432 struct list_head *entry, *tmp;
433
434 list_for_each_safe(entry, tmp, &dev_priv->vbl_waiting) {
435 chan = list_entry(entry, struct nouveau_channel, nvsw.vbl_wait);
436 432
433 list_for_each_entry_safe(chan, tmp, &dev_priv->vbl_waiting,
434 nvsw.vbl_wait) {
437 nouveau_bo_wr32(chan->notifier_bo, chan->nvsw.vblsem_offset, 435 nouveau_bo_wr32(chan->notifier_bo, chan->nvsw.vblsem_offset,
438 chan->nvsw.vblsem_rval); 436 chan->nvsw.vblsem_rval);
439 list_del(&chan->nvsw.vbl_wait); 437 list_del(&chan->nvsw.vbl_wait);
438 drm_vblank_put(dev, crtc);
440 } 439 }
440
441 drm_handle_vblank(dev, crtc);
441} 442}
442 443
443static void 444static void
444nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr) 445nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr)
445{ 446{
446 intr &= NV50_PDISPLAY_INTR_1_VBLANK_CRTC;
447
448 if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_0) 447 if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_0)
449 nv50_display_vblank_crtc_handler(dev, 0); 448 nv50_display_vblank_crtc_handler(dev, 0);
450 449
451 if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_1) 450 if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_1)
452 nv50_display_vblank_crtc_handler(dev, 1); 451 nv50_display_vblank_crtc_handler(dev, 1);
453 452
454 nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, intr, 0x00000000); 453 nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_VBLANK_CRTC);
455 nv_wr32(dev, NV50_PDISPLAY_INTR_1, intr);
456} 454}
457 455
458static void 456static void
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c
index d441308a09cf..ac7f62d524bb 100644
--- a/drivers/gpu/drm/nouveau/nv50_graph.c
+++ b/drivers/gpu/drm/nouveau/nv50_graph.c
@@ -384,14 +384,7 @@ nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan,
384 if (!chan->nvsw.vblsem || chan->nvsw.vblsem_offset == ~0 || data > 1) 384 if (!chan->nvsw.vblsem || chan->nvsw.vblsem_offset == ~0 || data > 1)
385 return -EINVAL; 385 return -EINVAL;
386 386
387 if (!(nv_rd32(dev, NV50_PDISPLAY_INTR_EN_1) & 387 drm_vblank_get(dev, data);
388 NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(data))) {
389 nv_wr32(dev, NV50_PDISPLAY_INTR_1,
390 NV50_PDISPLAY_INTR_1_VBLANK_CRTC_(data));
391 nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, 0,
392 NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(data));
393 }
394
395 list_add(&chan->nvsw.vbl_wait, &dev_priv->vbl_waiting); 388 list_add(&chan->nvsw.vbl_wait, &dev_priv->vbl_waiting);
396 return 0; 389 return 0;
397} 390}