aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r100.c
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2010-11-21 10:59:01 -0500
committerDave Airlie <airlied@redhat.com>2010-11-21 20:51:08 -0500
commit6f34be50bd1bdd2ff3c955940e033a80d05f248a (patch)
tree7e9635a2e589cd3a49490a4656611c112e485059 /drivers/gpu/drm/radeon/r100.c
parentf5a8020903932624cf020dc72455a10a3e005087 (diff)
drm/radeon/kms: add pageflip ioctl support (v3)
This adds support for dri2 pageflipping. v2: precision updates from Mario Kleiner. v3: Multihead fixes from Mario Kleiner; missing crtc offset add note about update pending bit on pre-avivo chips Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/r100.c')
-rw-r--r--drivers/gpu/drm/radeon/r100.c74
1 files changed, 66 insertions, 8 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 8e10aa9f74b0..b2e29798a99d 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -68,6 +68,54 @@ MODULE_FIRMWARE(FIRMWARE_R520);
68 * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 68 * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
69 */ 69 */
70 70
71void r100_pre_page_flip(struct radeon_device *rdev, int crtc)
72{
73 struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc];
74 u32 tmp;
75
76 /* make sure flip is at vb rather than hb */
77 tmp = RREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset);
78 tmp &= ~RADEON_CRTC_OFFSET_FLIP_CNTL;
79 WREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset, tmp);
80
81 /* set pageflip to happen as late as possible in the vblank interval.
82 * same field for crtc1/2
83 */
84 tmp = RREG32(RADEON_CRTC_GEN_CNTL);
85 tmp &= ~RADEON_CRTC_VSTAT_MODE_MASK;
86 WREG32(RADEON_CRTC_GEN_CNTL, tmp);
87
88 /* enable the pflip int */
89 radeon_irq_kms_pflip_irq_get(rdev, crtc);
90}
91
92void r100_post_page_flip(struct radeon_device *rdev, int crtc)
93{
94 /* disable the pflip int */
95 radeon_irq_kms_pflip_irq_put(rdev, crtc);
96}
97
98u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
99{
100 struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
101 u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK;
102
103 /* Lock the graphics update lock */
104 /* update the scanout addresses */
105 WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
106
107 /* Note: We don't wait for update_pending to assert, as this never
108 * happens for some reason on R1xx - R4xx. Adds a bit of imprecision.
109 */
110
111 /* Unlock the lock, so double-buffering can take place inside vblank */
112 tmp &= ~RADEON_CRTC_OFFSET__OFFSET_LOCK;
113 WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
114
115 /* Return current update_pending status: */
116 return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET;
117}
118
71void r100_pm_get_dynpm_state(struct radeon_device *rdev) 119void r100_pm_get_dynpm_state(struct radeon_device *rdev)
72{ 120{
73 int i; 121 int i;
@@ -526,10 +574,12 @@ int r100_irq_set(struct radeon_device *rdev)
526 if (rdev->irq.gui_idle) { 574 if (rdev->irq.gui_idle) {
527 tmp |= RADEON_GUI_IDLE_MASK; 575 tmp |= RADEON_GUI_IDLE_MASK;
528 } 576 }
529 if (rdev->irq.crtc_vblank_int[0]) { 577 if (rdev->irq.crtc_vblank_int[0] ||
578 rdev->irq.pflip[0]) {
530 tmp |= RADEON_CRTC_VBLANK_MASK; 579 tmp |= RADEON_CRTC_VBLANK_MASK;
531 } 580 }
532 if (rdev->irq.crtc_vblank_int[1]) { 581 if (rdev->irq.crtc_vblank_int[1] ||
582 rdev->irq.pflip[1]) {
533 tmp |= RADEON_CRTC2_VBLANK_MASK; 583 tmp |= RADEON_CRTC2_VBLANK_MASK;
534 } 584 }
535 if (rdev->irq.hpd[0]) { 585 if (rdev->irq.hpd[0]) {
@@ -600,14 +650,22 @@ int r100_irq_process(struct radeon_device *rdev)
600 } 650 }
601 /* Vertical blank interrupts */ 651 /* Vertical blank interrupts */
602 if (status & RADEON_CRTC_VBLANK_STAT) { 652 if (status & RADEON_CRTC_VBLANK_STAT) {
603 drm_handle_vblank(rdev->ddev, 0); 653 if (rdev->irq.pflip[0])
604 rdev->pm.vblank_sync = true; 654 radeon_crtc_handle_flip(rdev, 0);
605 wake_up(&rdev->irq.vblank_queue); 655 if (rdev->irq.crtc_vblank_int[0]) {
656 drm_handle_vblank(rdev->ddev, 0);
657 rdev->pm.vblank_sync = true;
658 wake_up(&rdev->irq.vblank_queue);
659 }
606 } 660 }
607 if (status & RADEON_CRTC2_VBLANK_STAT) { 661 if (status & RADEON_CRTC2_VBLANK_STAT) {
608 drm_handle_vblank(rdev->ddev, 1); 662 if (rdev->irq.pflip[1])
609 rdev->pm.vblank_sync = true; 663 radeon_crtc_handle_flip(rdev, 1);
610 wake_up(&rdev->irq.vblank_queue); 664 if (rdev->irq.crtc_vblank_int[1]) {
665 drm_handle_vblank(rdev->ddev, 1);
666 rdev->pm.vblank_sync = true;
667 wake_up(&rdev->irq.vblank_queue);
668 }
611 } 669 }
612 if (status & RADEON_FP_DETECT_STAT) { 670 if (status & RADEON_FP_DETECT_STAT) {
613 queue_hotplug = true; 671 queue_hotplug = true;