1 /* 2 * Copyright © 2014 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 * 23 * Authors: 24 * Daniel Vetter <daniel.vetter@ffwll.ch> 25 */ 26 27 /** 28 * DOC: frontbuffer tracking 29 * 30 * Many features require us to track changes to the currently active 31 * frontbuffer, especially rendering targeted at the frontbuffer. 32 * 33 * To be able to do so we track frontbuffers using a bitmask for all possible 34 * frontbuffer slots through intel_frontbuffer_track(). The functions in this 35 * file are then called when the contents of the frontbuffer are invalidated, 36 * when frontbuffer rendering has stopped again to flush out all the changes 37 * and when the frontbuffer is exchanged with a flip. Subsystems interested in 38 * frontbuffer changes (e.g. PSR, FBC, DRRS) should directly put their callbacks 39 * into the relevant places and filter for the frontbuffer slots that they are 40 * interested int. 41 * 42 * On a high level there are two types of powersaving features. The first one 43 * work like a special cache (FBC and PSR) and are interested when they should 44 * stop caching and when to restart caching. This is done by placing callbacks 45 * into the invalidate and the flush functions: At invalidate the caching must 46 * be stopped and at flush time it can be restarted. And maybe they need to know 47 * when the frontbuffer changes (e.g. when the hw doesn't initiate an invalidate 48 * and flush on its own) which can be achieved with placing callbacks into the 49 * flip functions. 50 * 51 * The other type of display power saving feature only cares about busyness 52 * (e.g. DRRS). In that case all three (invalidate, flush and flip) indicate 53 * busyness. There is no direct way to detect idleness. Instead an idle timer 54 * work delayed work should be started from the flush and flip functions and 55 * cancelled as soon as busyness is detected. 56 */ 57 58 #include <drm/drm_gem.h> 59 #include <drm/drm_print.h> 60 61 #include "intel_bo.h" 62 #include "intel_display_trace.h" 63 #include "intel_display_types.h" 64 #include "intel_dp.h" 65 #include "intel_drrs.h" 66 #include "intel_fbc.h" 67 #include "intel_frontbuffer.h" 68 #include "intel_psr.h" 69 #include "intel_tdf.h" 70 71 /** 72 * frontbuffer_flush - flush frontbuffer 73 * @display: display device 74 * @frontbuffer_bits: frontbuffer plane tracking bits 75 * @origin: which operation caused the flush 76 * 77 * This function gets called every time rendering on the given planes has 78 * completed and frontbuffer caching can be started again. Flushes will get 79 * delayed if they're blocked by some outstanding asynchronous rendering. 80 * 81 * Can be called without any locks held. 82 */ 83 static void frontbuffer_flush(struct intel_display *display, 84 unsigned int frontbuffer_bits, 85 enum fb_op_origin origin) 86 { 87 /* Delay flushing when rings are still busy.*/ 88 spin_lock(&display->fb_tracking.lock); 89 frontbuffer_bits &= ~display->fb_tracking.busy_bits; 90 spin_unlock(&display->fb_tracking.lock); 91 92 if (!frontbuffer_bits) 93 return; 94 95 trace_intel_frontbuffer_flush(display, frontbuffer_bits, origin); 96 97 might_sleep(); 98 intel_td_flush(display); 99 intel_drrs_flush(display, frontbuffer_bits); 100 intel_psr_flush(display, frontbuffer_bits, origin); 101 intel_fbc_flush(display, frontbuffer_bits, origin); 102 } 103 104 /** 105 * intel_frontbuffer_flip - synchronous frontbuffer flip 106 * @display: display device 107 * @frontbuffer_bits: frontbuffer plane tracking bits 108 * 109 * This function gets called after scheduling a flip on @obj. This is for 110 * synchronous plane updates which will happen on the next vblank and which will 111 * not get delayed by pending gpu rendering. 112 * 113 * Can be called without any locks held. 114 */ 115 void intel_frontbuffer_flip(struct intel_display *display, 116 unsigned frontbuffer_bits) 117 { 118 spin_lock(&display->fb_tracking.lock); 119 /* Remove stale busy bits due to the old buffer. */ 120 display->fb_tracking.busy_bits &= ~frontbuffer_bits; 121 spin_unlock(&display->fb_tracking.lock); 122 123 frontbuffer_flush(display, frontbuffer_bits, ORIGIN_FLIP); 124 } 125 126 void __intel_fb_invalidate(struct intel_frontbuffer *front, 127 enum fb_op_origin origin, 128 unsigned int frontbuffer_bits) 129 { 130 struct intel_display *display = front->display; 131 132 if (origin == ORIGIN_CS) { 133 spin_lock(&display->fb_tracking.lock); 134 display->fb_tracking.busy_bits |= frontbuffer_bits; 135 spin_unlock(&display->fb_tracking.lock); 136 } 137 138 trace_intel_frontbuffer_invalidate(display, frontbuffer_bits, origin); 139 140 might_sleep(); 141 intel_psr_invalidate(display, frontbuffer_bits, origin); 142 intel_drrs_invalidate(display, frontbuffer_bits); 143 intel_fbc_invalidate(display, frontbuffer_bits, origin); 144 } 145 146 void __intel_fb_flush(struct intel_frontbuffer *front, 147 enum fb_op_origin origin, 148 unsigned int frontbuffer_bits) 149 { 150 struct intel_display *display = front->display; 151 152 if (origin == ORIGIN_DIRTYFB) 153 intel_bo_frontbuffer_flush_for_display(front); 154 155 if (origin == ORIGIN_CS) { 156 spin_lock(&display->fb_tracking.lock); 157 /* Filter out new bits since rendering started. */ 158 frontbuffer_bits &= display->fb_tracking.busy_bits; 159 display->fb_tracking.busy_bits &= ~frontbuffer_bits; 160 spin_unlock(&display->fb_tracking.lock); 161 } 162 163 if (frontbuffer_bits) 164 frontbuffer_flush(display, frontbuffer_bits, origin); 165 } 166 167 static void intel_frontbuffer_ref(struct intel_frontbuffer *front) 168 { 169 intel_bo_frontbuffer_ref(front); 170 } 171 172 static void intel_frontbuffer_flush_work(struct work_struct *work) 173 { 174 struct intel_frontbuffer *front = 175 container_of(work, struct intel_frontbuffer, flush_work); 176 177 intel_frontbuffer_flush(front, ORIGIN_DIRTYFB); 178 intel_frontbuffer_put(front); 179 } 180 181 /** 182 * intel_frontbuffer_queue_flush - queue flushing frontbuffer object 183 * @front: GEM object to flush 184 * 185 * This function is targeted for our dirty callback for queueing flush when 186 * dma fence is signals 187 */ 188 void intel_frontbuffer_queue_flush(struct intel_frontbuffer *front) 189 { 190 if (!front) 191 return; 192 193 intel_frontbuffer_ref(front); 194 if (!schedule_work(&front->flush_work)) 195 intel_frontbuffer_put(front); 196 } 197 198 void intel_frontbuffer_init(struct intel_frontbuffer *front, struct drm_device *drm) 199 { 200 front->display = to_intel_display(drm); 201 atomic_set(&front->bits, 0); 202 INIT_WORK(&front->flush_work, intel_frontbuffer_flush_work); 203 } 204 205 void intel_frontbuffer_fini(struct intel_frontbuffer *front) 206 { 207 drm_WARN_ON(front->display->drm, atomic_read(&front->bits)); 208 } 209 210 struct intel_frontbuffer *intel_frontbuffer_get(struct drm_gem_object *obj) 211 { 212 return intel_bo_frontbuffer_get(obj); 213 } 214 215 void intel_frontbuffer_put(struct intel_frontbuffer *front) 216 { 217 intel_bo_frontbuffer_put(front); 218 } 219 220 /** 221 * intel_frontbuffer_track - update frontbuffer tracking 222 * @old: current buffer for the frontbuffer slots 223 * @new: new buffer for the frontbuffer slots 224 * @frontbuffer_bits: bitmask of frontbuffer slots 225 * 226 * This updates the frontbuffer tracking bits @frontbuffer_bits by clearing them 227 * from @old and setting them in @new. Both @old and @new can be NULL. 228 */ 229 void intel_frontbuffer_track(struct intel_frontbuffer *old, 230 struct intel_frontbuffer *new, 231 unsigned int frontbuffer_bits) 232 { 233 /* 234 * Control of individual bits within the mask are guarded by 235 * the owning plane->mutex, i.e. we can never see concurrent 236 * manipulation of individual bits. But since the bitfield as a whole 237 * is updated using RMW, we need to use atomics in order to update 238 * the bits. 239 */ 240 BUILD_BUG_ON(INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES > 241 BITS_PER_TYPE(atomic_t)); 242 BUILD_BUG_ON(INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES > 32); 243 BUILD_BUG_ON(I915_MAX_PLANES > INTEL_FRONTBUFFER_BITS_PER_PIPE); 244 245 if (old) { 246 drm_WARN_ON(old->display->drm, 247 !(atomic_read(&old->bits) & frontbuffer_bits)); 248 atomic_andnot(frontbuffer_bits, &old->bits); 249 } 250 251 if (new) { 252 drm_WARN_ON(new->display->drm, 253 atomic_read(&new->bits) & frontbuffer_bits); 254 atomic_or(frontbuffer_bits, &new->bits); 255 } 256 } 257