diff options
author | Francisco Jerez <currojerez@riseup.net> | 2010-10-21 12:19:29 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-12-03 00:11:11 -0500 |
commit | 042206c0cd4924879c4292c5ffa2bf1e8023ae5a (patch) | |
tree | c775b823b4e3d598e4fc41023a96e2e4b3126c20 | |
parent | 63f7fcfebd2ff1995b649101d6120b60fa0e5b06 (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.c | 27 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_hw.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_irq.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_state.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_display.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_graph.c | 9 |
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 | ||
33 | static void | 34 | static void |
34 | nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) | 35 | nouveau_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 | ||
108 | int | ||
109 | nouveau_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 | |||
123 | void | ||
124 | nouveau_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 *, | |||
1312 | extern int nouveau_gem_ioctl_info(struct drm_device *, void *, | 1312 | extern int nouveau_gem_ioctl_info(struct drm_device *, void *, |
1313 | struct drm_file *); | 1313 | struct drm_file *); |
1314 | 1314 | ||
1315 | /* nouveau_display.c */ | ||
1316 | int nouveau_vblank_enable(struct drm_device *dev, int crtc); | ||
1317 | void nouveau_vblank_disable(struct drm_device *dev, int crtc); | ||
1318 | |||
1315 | /* nv10_gpio.c */ | 1319 | /* nv10_gpio.c */ |
1316 | int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); | 1320 | int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); |
1317 | int nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); | 1321 | int 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) | |||
1200 | static void | 1200 | static void |
1201 | nouveau_crtc_irq_handler(struct drm_device *dev, int crtc) | 1201 | nouveau_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 | ||
1210 | irqreturn_t | 1214 | irqreturn_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); |
702 | out_irq: | 702 | out_irq: |
703 | nouveau_irq_fini(dev); | 703 | nouveau_irq_fini(dev); |
704 | out_display: | 704 | out_vblank: |
705 | drm_vblank_cleanup(dev); | ||
705 | engine->display.destroy(dev); | 706 | engine->display.destroy(dev); |
706 | out_fifo: | 707 | out_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 | |||
428 | nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc) | 428 | nv50_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 | ||
443 | static void | 444 | static void |
444 | nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr) | 445 | nv50_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 | ||
458 | static void | 456 | static 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 | } |