Rev 5354 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5354 | Rev 6084 | ||
---|---|---|---|
Line 63... | Line 63... | ||
63 | #include |
63 | #include |
Line 64... | Line 64... | ||
64 | 64 | ||
65 | #include "intel_drv.h" |
65 | #include "intel_drv.h" |
Line 66... | Line -... | ||
66 | #include "i915_drv.h" |
- | |
67 | - | ||
68 | static void intel_increase_pllclock(struct drm_device *dev, |
- | |
69 | enum pipe pipe) |
- | |
70 | { |
- | |
71 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | |
72 | int dpll_reg = DPLL(pipe); |
- | |
73 | int dpll; |
- | |
74 | - | ||
75 | if (!HAS_GMCH_DISPLAY(dev)) |
- | |
76 | return; |
- | |
77 | - | ||
78 | if (!dev_priv->lvds_downclock_avail) |
- | |
79 | return; |
- | |
80 | - | ||
81 | dpll = I915_READ(dpll_reg); |
- | |
82 | if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) { |
- | |
83 | DRM_DEBUG_DRIVER("upclocking LVDS\n"); |
- | |
84 | - | ||
85 | assert_panel_unlocked(dev_priv, pipe); |
- | |
86 | - | ||
87 | dpll &= ~DISPLAY_RATE_SELECT_FPA1; |
- | |
88 | I915_WRITE(dpll_reg, dpll); |
- | |
89 | intel_wait_for_vblank(dev, pipe); |
- | |
90 | - | ||
91 | dpll = I915_READ(dpll_reg); |
- | |
92 | if (dpll & DISPLAY_RATE_SELECT_FPA1) |
- | |
93 | DRM_DEBUG_DRIVER("failed to upclock LVDS!\n"); |
- | |
94 | } |
- | |
95 | } |
- | |
96 | - | ||
97 | /** |
- | |
98 | * intel_mark_fb_busy - mark given planes as busy |
- | |
99 | * @dev: DRM device |
- | |
100 | * @frontbuffer_bits: bits for the affected planes |
- | |
101 | * @ring: optional ring for asynchronous commands |
- | |
102 | * |
- | |
103 | * This function gets called every time the screen contents change. It can be |
- | |
104 | * used to keep e.g. the update rate at the nominal refresh rate with DRRS. |
- | |
105 | */ |
- | |
106 | static void intel_mark_fb_busy(struct drm_device *dev, |
- | |
107 | unsigned frontbuffer_bits, |
- | |
108 | struct intel_engine_cs *ring) |
- | |
109 | { |
- | |
110 | struct drm_i915_private *dev_priv = dev->dev_private; |
- | |
111 | enum pipe pipe; |
- | |
112 | - | ||
113 | if (!i915.powersave) |
- | |
114 | return; |
- | |
115 | - | ||
116 | for_each_pipe(dev_priv, pipe) { |
- | |
117 | if (!(frontbuffer_bits & INTEL_FRONTBUFFER_ALL_MASK(pipe))) |
- | |
118 | continue; |
- | |
119 | - | ||
120 | intel_increase_pllclock(dev, pipe); |
- | |
121 | if (ring && intel_fbc_enabled(dev)) |
- | |
122 | ring->fbc_dirty = true; |
- | |
123 | } |
- | |
124 | } |
66 | #include "i915_drv.h" |
125 | 67 | ||
126 | /** |
68 | /** |
127 | * intel_fb_obj_invalidate - invalidate frontbuffer object |
69 | * intel_fb_obj_invalidate - invalidate frontbuffer object |
128 | * @obj: GEM object to invalidate |
70 | * @obj: GEM object to invalidate |
129 | * @ring: set for asynchronous rendering |
71 | * @origin: which operation caused the invalidation |
130 | * |
72 | * |
131 | * This function gets called every time rendering on the given object starts and |
73 | * This function gets called every time rendering on the given object starts and |
132 | * frontbuffer caching (fbc, low refresh rate for DRRS, panel self refresh) must |
74 | * frontbuffer caching (fbc, low refresh rate for DRRS, panel self refresh) must |
133 | * be invalidated. If @ring is non-NULL any subsequent invalidation will be delayed |
75 | * be invalidated. For ORIGIN_CS any subsequent invalidation will be delayed |
134 | * until the rendering completes or a flip on this frontbuffer plane is |
76 | * until the rendering completes or a flip on this frontbuffer plane is |
135 | * scheduled. |
77 | * scheduled. |
136 | */ |
78 | */ |
137 | void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj, |
79 | void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj, |
138 | struct intel_engine_cs *ring) |
80 | enum fb_op_origin origin) |
139 | { |
81 | { |
Line 140... | Line 82... | ||
140 | struct drm_device *dev = obj->base.dev; |
82 | struct drm_device *dev = obj->base.dev; |
Line 141... | Line 83... | ||
141 | struct drm_i915_private *dev_priv = dev->dev_private; |
83 | struct drm_i915_private *dev_priv = to_i915(dev); |
142 | 84 | ||
Line 143... | Line 85... | ||
143 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); |
85 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); |
144 | 86 | ||
145 | if (!obj->frontbuffer_bits) |
87 | if (!obj->frontbuffer_bits) |
146 | return; |
88 | return; |
147 | 89 | ||
148 | if (ring) { |
90 | if (origin == ORIGIN_CS) { |
149 | mutex_lock(&dev_priv->fb_tracking.lock); |
91 | mutex_lock(&dev_priv->fb_tracking.lock); |
150 | dev_priv->fb_tracking.busy_bits |
92 | dev_priv->fb_tracking.busy_bits |
Line 151... | Line -... | ||
151 | |= obj->frontbuffer_bits; |
- | |
152 | dev_priv->fb_tracking.flip_bits |
- | |
153 | &= ~obj->frontbuffer_bits; |
93 | |= obj->frontbuffer_bits; |
- | 94 | dev_priv->fb_tracking.flip_bits |
|
- | 95 | &= ~obj->frontbuffer_bits; |
|
154 | mutex_unlock(&dev_priv->fb_tracking.lock); |
96 | mutex_unlock(&dev_priv->fb_tracking.lock); |
Line 155... | Line 97... | ||
155 | } |
97 | } |
156 | 98 | ||
157 | intel_mark_fb_busy(dev, obj->frontbuffer_bits, ring); |
99 | intel_psr_invalidate(dev, obj->frontbuffer_bits); |
158 | 100 | intel_edp_drrs_invalidate(dev, obj->frontbuffer_bits); |
|
- | 101 | intel_fbc_invalidate(dev_priv, obj->frontbuffer_bits, origin); |
|
159 | intel_psr_invalidate(dev, obj->frontbuffer_bits); |
102 | } |
160 | } |
103 | |
161 | 104 | /** |
|
162 | /** |
105 | * intel_frontbuffer_flush - flush frontbuffer |
163 | * intel_frontbuffer_flush - flush frontbuffer |
106 | * @dev: DRM device |
164 | * @dev: DRM device |
107 | * @frontbuffer_bits: frontbuffer plane tracking bits |
165 | * @frontbuffer_bits: frontbuffer plane tracking bits |
108 | * @origin: which operation caused the flush |
166 | * |
109 | * |
167 | * This function gets called every time rendering on the given planes has |
110 | * This function gets called every time rendering on the given planes has |
- | 111 | * completed and frontbuffer caching can be started again. Flushes will get |
|
168 | * completed and frontbuffer caching can be started again. Flushes will get |
112 | * delayed if they're blocked by some outstanding asynchronous rendering. |
169 | * delayed if they're blocked by some outstanding asynchronous rendering. |
113 | * |
Line 170... | Line 114... | ||
170 | * |
114 | * Can be called without any locks held. |
171 | * Can be called without any locks held. |
115 | */ |
172 | */ |
116 | static void intel_frontbuffer_flush(struct drm_device *dev, |
173 | void intel_frontbuffer_flush(struct drm_device *dev, |
117 | unsigned frontbuffer_bits, |
Line 174... | Line 118... | ||
174 | unsigned frontbuffer_bits) |
118 | enum fb_op_origin origin) |
175 | { |
- | |
176 | struct drm_i915_private *dev_priv = dev->dev_private; |
119 | { |
Line 177... | Line -... | ||
177 | - | ||
178 | /* Delay flushing when rings are still busy.*/ |
- | |
179 | mutex_lock(&dev_priv->fb_tracking.lock); |
- | |
180 | frontbuffer_bits &= ~dev_priv->fb_tracking.busy_bits; |
- | |
181 | mutex_unlock(&dev_priv->fb_tracking.lock); |
- | |
182 | 120 | struct drm_i915_private *dev_priv = to_i915(dev); |
|
183 | intel_mark_fb_busy(dev, frontbuffer_bits, NULL); |
121 | |
184 | 122 | /* Delay flushing when rings are still busy.*/ |
|
185 | intel_psr_flush(dev, frontbuffer_bits); |
- | |
186 | 123 | mutex_lock(&dev_priv->fb_tracking.lock); |
|
Line 187... | Line 124... | ||
187 | /* |
124 | frontbuffer_bits &= ~dev_priv->fb_tracking.busy_bits; |
188 | * FIXME: Unconditional fbc flushing here is a rather gross hack and |
125 | mutex_unlock(&dev_priv->fb_tracking.lock); |
189 | * needs to be reworked into a proper frontbuffer tracking scheme like |
126 | |
190 | * psr employs. |
127 | if (!frontbuffer_bits) |
- | 128 | return; |
|
191 | */ |
129 | |
192 | if (dev_priv->fbc.need_sw_cache_clean) { |
130 | intel_edp_drrs_flush(dev, frontbuffer_bits); |
193 | dev_priv->fbc.need_sw_cache_clean = false; |
131 | intel_psr_flush(dev, frontbuffer_bits, origin); |
194 | bdw_fbc_sw_flush(dev, FBC_REND_CACHE_CLEAN); |
132 | intel_fbc_flush(dev_priv, frontbuffer_bits, origin); |
195 | } |
133 | } |
196 | } |
134 | |
197 | 135 | /** |
|
198 | /** |
136 | * intel_fb_obj_flush - flush frontbuffer object |
199 | * intel_fb_obj_flush - flush frontbuffer object |
137 | * @obj: GEM object to flush |
200 | * @obj: GEM object to flush |
138 | * @retire: set when retiring asynchronous rendering |
201 | * @retire: set when retiring asynchronous rendering |
139 | * @origin: which operation caused the flush |
Line 202... | Line 140... | ||
202 | * |
140 | * |
Line 203... | Line 141... | ||
203 | * This function gets called every time rendering on the given object has |
141 | * This function gets called every time rendering on the given object has |
Line 225... | Line 163... | ||
225 | 163 | ||
226 | dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits; |
164 | dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits; |
227 | mutex_unlock(&dev_priv->fb_tracking.lock); |
165 | mutex_unlock(&dev_priv->fb_tracking.lock); |
Line 228... | Line 166... | ||
228 | } |
166 | } |
229 | 167 | ||
Line 230... | Line 168... | ||
230 | intel_frontbuffer_flush(dev, frontbuffer_bits); |
168 | intel_frontbuffer_flush(dev, frontbuffer_bits, origin); |
231 | } |
169 | } |
232 | 170 | ||
Line 243... | Line 181... | ||
243 | * Can be called without any locks held. |
181 | * Can be called without any locks held. |
244 | */ |
182 | */ |
245 | void intel_frontbuffer_flip_prepare(struct drm_device *dev, |
183 | void intel_frontbuffer_flip_prepare(struct drm_device *dev, |
246 | unsigned frontbuffer_bits) |
184 | unsigned frontbuffer_bits) |
247 | { |
185 | { |
248 | struct drm_i915_private *dev_priv = dev->dev_private; |
186 | struct drm_i915_private *dev_priv = to_i915(dev); |
Line 249... | Line 187... | ||
249 | 187 | ||
250 | mutex_lock(&dev_priv->fb_tracking.lock); |
188 | mutex_lock(&dev_priv->fb_tracking.lock); |
251 | dev_priv->fb_tracking.flip_bits |= frontbuffer_bits; |
189 | dev_priv->fb_tracking.flip_bits |= frontbuffer_bits; |
252 | /* Remove stale busy bits due to the old buffer. */ |
190 | /* Remove stale busy bits due to the old buffer. */ |
253 | dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits; |
191 | dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits; |
- | 192 | mutex_unlock(&dev_priv->fb_tracking.lock); |
|
- | 193 | ||
254 | mutex_unlock(&dev_priv->fb_tracking.lock); |
194 | intel_psr_single_frame_update(dev, frontbuffer_bits); |
Line 255... | Line 195... | ||
255 | } |
195 | } |
256 | 196 | ||
257 | /** |
197 | /** |
Line 265... | Line 205... | ||
265 | * Can be called without any locks held. |
205 | * Can be called without any locks held. |
266 | */ |
206 | */ |
267 | void intel_frontbuffer_flip_complete(struct drm_device *dev, |
207 | void intel_frontbuffer_flip_complete(struct drm_device *dev, |
268 | unsigned frontbuffer_bits) |
208 | unsigned frontbuffer_bits) |
269 | { |
209 | { |
270 | struct drm_i915_private *dev_priv = dev->dev_private; |
210 | struct drm_i915_private *dev_priv = to_i915(dev); |
Line 271... | Line 211... | ||
271 | 211 | ||
272 | mutex_lock(&dev_priv->fb_tracking.lock); |
212 | mutex_lock(&dev_priv->fb_tracking.lock); |
273 | /* Mask any cancelled flips. */ |
213 | /* Mask any cancelled flips. */ |
274 | frontbuffer_bits &= dev_priv->fb_tracking.flip_bits; |
214 | frontbuffer_bits &= dev_priv->fb_tracking.flip_bits; |
275 | dev_priv->fb_tracking.flip_bits &= ~frontbuffer_bits; |
215 | dev_priv->fb_tracking.flip_bits &= ~frontbuffer_bits; |
Line 276... | Line 216... | ||
276 | mutex_unlock(&dev_priv->fb_tracking.lock); |
216 | mutex_unlock(&dev_priv->fb_tracking.lock); |
- | 217 | ||
- | 218 | intel_frontbuffer_flush(dev, frontbuffer_bits, ORIGIN_FLIP); |
|
- | 219 | } |
|
- | 220 | ||
- | 221 | /** |
|
- | 222 | * intel_frontbuffer_flip - synchronous frontbuffer flip |
|
- | 223 | * @dev: DRM device |
|
- | 224 | * @frontbuffer_bits: frontbuffer plane tracking bits |
|
- | 225 | * |
|
- | 226 | * This function gets called after scheduling a flip on @obj. This is for |
|
- | 227 | * synchronous plane updates which will happen on the next vblank and which will |
|
- | 228 | * not get delayed by pending gpu rendering. |
|
- | 229 | * |
|
- | 230 | * Can be called without any locks held. |
|
- | 231 | */ |
|
- | 232 | void intel_frontbuffer_flip(struct drm_device *dev, |
|
- | 233 | unsigned frontbuffer_bits) |
|
- | 234 | { |
|
- | 235 | struct drm_i915_private *dev_priv = to_i915(dev); |
|
- | 236 | ||
- | 237 | mutex_lock(&dev_priv->fb_tracking.lock); |
|
- | 238 | /* Remove stale busy bits due to the old buffer. */ |
|
- | 239 | dev_priv->fb_tracking.busy_bits &= ~frontbuffer_bits; |
|
- | 240 | mutex_unlock(&dev_priv->fb_tracking.lock); |
|
277 | 241 |