diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r100.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 77 |
1 files changed, 53 insertions, 24 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 9db58530be37..4973bff37fec 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
@@ -69,6 +69,38 @@ MODULE_FIRMWARE(FIRMWARE_R520); | |||
69 | * and others in some cases. | 69 | * and others in some cases. |
70 | */ | 70 | */ |
71 | 71 | ||
72 | static bool r100_is_in_vblank(struct radeon_device *rdev, int crtc) | ||
73 | { | ||
74 | if (crtc == 0) { | ||
75 | if (RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR) | ||
76 | return true; | ||
77 | else | ||
78 | return false; | ||
79 | } else { | ||
80 | if (RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR) | ||
81 | return true; | ||
82 | else | ||
83 | return false; | ||
84 | } | ||
85 | } | ||
86 | |||
87 | static bool r100_is_counter_moving(struct radeon_device *rdev, int crtc) | ||
88 | { | ||
89 | u32 vline1, vline2; | ||
90 | |||
91 | if (crtc == 0) { | ||
92 | vline1 = (RREG32(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL; | ||
93 | vline2 = (RREG32(RADEON_CRTC_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL; | ||
94 | } else { | ||
95 | vline1 = (RREG32(RADEON_CRTC2_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL; | ||
96 | vline2 = (RREG32(RADEON_CRTC2_VLINE_CRNT_VLINE) >> 16) & RADEON_CRTC_V_TOTAL; | ||
97 | } | ||
98 | if (vline1 != vline2) | ||
99 | return true; | ||
100 | else | ||
101 | return false; | ||
102 | } | ||
103 | |||
72 | /** | 104 | /** |
73 | * r100_wait_for_vblank - vblank wait asic callback. | 105 | * r100_wait_for_vblank - vblank wait asic callback. |
74 | * | 106 | * |
@@ -79,36 +111,33 @@ MODULE_FIRMWARE(FIRMWARE_R520); | |||
79 | */ | 111 | */ |
80 | void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) | 112 | void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) |
81 | { | 113 | { |
82 | int i; | 114 | unsigned i = 0; |
83 | 115 | ||
84 | if (crtc >= rdev->num_crtc) | 116 | if (crtc >= rdev->num_crtc) |
85 | return; | 117 | return; |
86 | 118 | ||
87 | if (crtc == 0) { | 119 | if (crtc == 0) { |
88 | if (RREG32(RADEON_CRTC_GEN_CNTL) & RADEON_CRTC_EN) { | 120 | if (!(RREG32(RADEON_CRTC_GEN_CNTL) & RADEON_CRTC_EN)) |
89 | for (i = 0; i < rdev->usec_timeout; i++) { | 121 | return; |
90 | if (!(RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR)) | ||
91 | break; | ||
92 | udelay(1); | ||
93 | } | ||
94 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
95 | if (RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR) | ||
96 | break; | ||
97 | udelay(1); | ||
98 | } | ||
99 | } | ||
100 | } else { | 122 | } else { |
101 | if (RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_EN) { | 123 | if (!(RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_EN)) |
102 | for (i = 0; i < rdev->usec_timeout; i++) { | 124 | return; |
103 | if (!(RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR)) | 125 | } |
104 | break; | 126 | |
105 | udelay(1); | 127 | /* depending on when we hit vblank, we may be close to active; if so, |
106 | } | 128 | * wait for another frame. |
107 | for (i = 0; i < rdev->usec_timeout; i++) { | 129 | */ |
108 | if (RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR) | 130 | while (r100_is_in_vblank(rdev, crtc)) { |
109 | break; | 131 | if (i++ % 100 == 0) { |
110 | udelay(1); | 132 | if (!r100_is_counter_moving(rdev, crtc)) |
111 | } | 133 | break; |
134 | } | ||
135 | } | ||
136 | |||
137 | while (!r100_is_in_vblank(rdev, crtc)) { | ||
138 | if (i++ % 100 == 0) { | ||
139 | if (!r100_is_counter_moving(rdev, crtc)) | ||
140 | break; | ||
112 | } | 141 | } |
113 | } | 142 | } |
114 | } | 143 | } |