diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2010-11-21 10:59:01 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-11-21 20:51:08 -0500 |
commit | 6f34be50bd1bdd2ff3c955940e033a80d05f248a (patch) | |
tree | 7e9635a2e589cd3a49490a4656611c112e485059 /drivers/gpu/drm/radeon/r100.c | |
parent | f5a8020903932624cf020dc72455a10a3e005087 (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.c | 74 |
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 | ||
71 | void 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 | |||
92 | void 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 | |||
98 | u32 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 | |||
71 | void r100_pm_get_dynpm_state(struct radeon_device *rdev) | 119 | void 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; |