1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2023 Intel Corporation 4 */ 5 6 #include <linux/debugfs.h> 7 8 #include <drm/drm_print.h> 9 10 #include "i9xx_wm.h" 11 #include "intel_display_core.h" 12 #include "intel_display_types.h" 13 #include "intel_wm.h" 14 #include "skl_watermark.h" 15 16 /** 17 * intel_update_watermarks - update FIFO watermark values based on current modes 18 * @display: display device 19 * 20 * Calculate watermark values for the various WM regs based on current mode 21 * and plane configuration. 22 * 23 * There are several cases to deal with here: 24 * - normal (i.e. non-self-refresh) 25 * - self-refresh (SR) mode 26 * - lines are large relative to FIFO size (buffer can hold up to 2) 27 * - lines are small relative to FIFO size (buffer can hold more than 2 28 * lines), so need to account for TLB latency 29 * 30 * The normal calculation is: 31 * watermark = dotclock * bytes per pixel * latency 32 * where latency is platform & configuration dependent (we assume pessimal 33 * values here). 34 * 35 * The SR calculation is: 36 * watermark = (trunc(latency/line time)+1) * surface width * 37 * bytes per pixel 38 * where 39 * line time = htotal / dotclock 40 * surface width = hdisplay for normal plane and 64 for cursor 41 * and latency is assumed to be high, as above. 42 * 43 * The final value programmed to the register should always be rounded up, 44 * and include an extra 2 entries to account for clock crossings. 45 * 46 * We don't use the sprite, so we can ignore that. And on Crestline we have 47 * to set the non-SR watermarks to 8. 48 */ 49 void intel_update_watermarks(struct intel_display *display) 50 { 51 if (display->funcs.wm->update_wm) 52 display->funcs.wm->update_wm(display); 53 } 54 55 int intel_wm_compute(struct intel_atomic_state *state, 56 struct intel_crtc *crtc) 57 { 58 struct intel_display *display = to_intel_display(state); 59 60 if (!display->funcs.wm->compute_watermarks) 61 return 0; 62 63 return display->funcs.wm->compute_watermarks(state, crtc); 64 } 65 66 bool intel_initial_watermarks(struct intel_atomic_state *state, 67 struct intel_crtc *crtc) 68 { 69 struct intel_display *display = to_intel_display(state); 70 71 if (display->funcs.wm->initial_watermarks) { 72 display->funcs.wm->initial_watermarks(state, crtc); 73 return true; 74 } 75 76 return false; 77 } 78 79 void intel_atomic_update_watermarks(struct intel_atomic_state *state, 80 struct intel_crtc *crtc) 81 { 82 struct intel_display *display = to_intel_display(state); 83 84 if (display->funcs.wm->atomic_update_watermarks) 85 display->funcs.wm->atomic_update_watermarks(state, crtc); 86 } 87 88 void intel_optimize_watermarks(struct intel_atomic_state *state, 89 struct intel_crtc *crtc) 90 { 91 struct intel_display *display = to_intel_display(state); 92 93 if (display->funcs.wm->optimize_watermarks) 94 display->funcs.wm->optimize_watermarks(state, crtc); 95 } 96 97 int intel_compute_global_watermarks(struct intel_atomic_state *state) 98 { 99 struct intel_display *display = to_intel_display(state); 100 101 if (display->funcs.wm->compute_global_watermarks) 102 return display->funcs.wm->compute_global_watermarks(state); 103 104 return 0; 105 } 106 107 void intel_wm_get_hw_state(struct intel_display *display) 108 { 109 if (display->funcs.wm->get_hw_state) 110 return display->funcs.wm->get_hw_state(display); 111 } 112 113 void intel_wm_sanitize(struct intel_display *display) 114 { 115 if (display->funcs.wm->sanitize) 116 return display->funcs.wm->sanitize(display); 117 } 118 119 bool intel_wm_plane_visible(const struct intel_crtc_state *crtc_state, 120 const struct intel_plane_state *plane_state) 121 { 122 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); 123 124 /* FIXME check the 'enable' instead */ 125 if (!crtc_state->hw.active) 126 return false; 127 128 /* 129 * Treat cursor with fb as always visible since cursor updates 130 * can happen faster than the vrefresh rate, and the current 131 * watermark code doesn't handle that correctly. Cursor updates 132 * which set/clear the fb or change the cursor size are going 133 * to get throttled by intel_legacy_cursor_update() to work 134 * around this problem with the watermark code. 135 */ 136 if (plane->id == PLANE_CURSOR) 137 return plane_state->hw.fb != NULL; 138 else 139 return plane_state->uapi.visible; 140 } 141 142 void intel_print_wm_latency(struct intel_display *display, 143 const char *name, const u16 wm[]) 144 { 145 int level; 146 147 for (level = 0; level < display->wm.num_levels; level++) { 148 unsigned int latency = wm[level]; 149 150 if (latency == 0) { 151 drm_dbg_kms(display->drm, 152 "%s WM%d latency not provided\n", 153 name, level); 154 continue; 155 } 156 157 /* 158 * - latencies are in us on gen9. 159 * - before then, WM1+ latency values are in 0.5us units 160 */ 161 if (DISPLAY_VER(display) >= 9) 162 latency *= 10; 163 else if (level > 0) 164 latency *= 5; 165 166 drm_dbg_kms(display->drm, 167 "%s WM%d latency %u (%u.%u usec)\n", name, level, 168 wm[level], latency / 10, latency % 10); 169 } 170 } 171 172 void intel_wm_init(struct intel_display *display) 173 { 174 if (DISPLAY_VER(display) >= 9) 175 skl_wm_init(display); 176 else 177 i9xx_wm_init(display); 178 } 179 180 static void wm_latency_show(struct seq_file *m, const u16 wm[8]) 181 { 182 struct intel_display *display = m->private; 183 int level; 184 185 drm_modeset_lock_all(display->drm); 186 187 for (level = 0; level < display->wm.num_levels; level++) { 188 unsigned int latency = wm[level]; 189 190 /* 191 * - WM1+ latency values in 0.5us units 192 * - latencies are in us on gen9/vlv/chv 193 */ 194 if (DISPLAY_VER(display) >= 9 || 195 display->platform.valleyview || 196 display->platform.cherryview || 197 display->platform.g4x) 198 latency *= 10; 199 else if (level > 0) 200 latency *= 5; 201 202 seq_printf(m, "WM%d %u (%u.%u usec)\n", 203 level, wm[level], latency / 10, latency % 10); 204 } 205 206 drm_modeset_unlock_all(display->drm); 207 } 208 209 static int pri_wm_latency_show(struct seq_file *m, void *data) 210 { 211 struct intel_display *display = m->private; 212 const u16 *latencies; 213 214 if (DISPLAY_VER(display) >= 9) 215 latencies = display->wm.skl_latency; 216 else 217 latencies = display->wm.pri_latency; 218 219 wm_latency_show(m, latencies); 220 221 return 0; 222 } 223 224 static int spr_wm_latency_show(struct seq_file *m, void *data) 225 { 226 struct intel_display *display = m->private; 227 const u16 *latencies; 228 229 if (DISPLAY_VER(display) >= 9) 230 latencies = display->wm.skl_latency; 231 else 232 latencies = display->wm.spr_latency; 233 234 wm_latency_show(m, latencies); 235 236 return 0; 237 } 238 239 static int cur_wm_latency_show(struct seq_file *m, void *data) 240 { 241 struct intel_display *display = m->private; 242 const u16 *latencies; 243 244 if (DISPLAY_VER(display) >= 9) 245 latencies = display->wm.skl_latency; 246 else 247 latencies = display->wm.cur_latency; 248 249 wm_latency_show(m, latencies); 250 251 return 0; 252 } 253 254 static int pri_wm_latency_open(struct inode *inode, struct file *file) 255 { 256 struct intel_display *display = inode->i_private; 257 258 if (DISPLAY_VER(display) < 5 && !display->platform.g4x) 259 return -ENODEV; 260 261 return single_open(file, pri_wm_latency_show, display); 262 } 263 264 static int spr_wm_latency_open(struct inode *inode, struct file *file) 265 { 266 struct intel_display *display = inode->i_private; 267 268 if (HAS_GMCH(display)) 269 return -ENODEV; 270 271 return single_open(file, spr_wm_latency_show, display); 272 } 273 274 static int cur_wm_latency_open(struct inode *inode, struct file *file) 275 { 276 struct intel_display *display = inode->i_private; 277 278 if (HAS_GMCH(display)) 279 return -ENODEV; 280 281 return single_open(file, cur_wm_latency_show, display); 282 } 283 284 static ssize_t wm_latency_write(struct file *file, const char __user *ubuf, 285 size_t len, loff_t *offp, u16 wm[8]) 286 { 287 struct seq_file *m = file->private_data; 288 struct intel_display *display = m->private; 289 u16 new[8] = {}; 290 int level; 291 int ret; 292 char tmp[32]; 293 294 if (len >= sizeof(tmp)) 295 return -EINVAL; 296 297 if (copy_from_user(tmp, ubuf, len)) 298 return -EFAULT; 299 300 tmp[len] = '\0'; 301 302 ret = sscanf(tmp, "%hu %hu %hu %hu %hu %hu %hu %hu", 303 &new[0], &new[1], &new[2], &new[3], 304 &new[4], &new[5], &new[6], &new[7]); 305 if (ret != display->wm.num_levels) 306 return -EINVAL; 307 308 drm_modeset_lock_all(display->drm); 309 310 for (level = 0; level < display->wm.num_levels; level++) 311 wm[level] = new[level]; 312 313 drm_modeset_unlock_all(display->drm); 314 315 return len; 316 } 317 318 static ssize_t pri_wm_latency_write(struct file *file, const char __user *ubuf, 319 size_t len, loff_t *offp) 320 { 321 struct seq_file *m = file->private_data; 322 struct intel_display *display = m->private; 323 u16 *latencies; 324 325 if (DISPLAY_VER(display) >= 9) 326 latencies = display->wm.skl_latency; 327 else 328 latencies = display->wm.pri_latency; 329 330 return wm_latency_write(file, ubuf, len, offp, latencies); 331 } 332 333 static ssize_t spr_wm_latency_write(struct file *file, const char __user *ubuf, 334 size_t len, loff_t *offp) 335 { 336 struct seq_file *m = file->private_data; 337 struct intel_display *display = m->private; 338 u16 *latencies; 339 340 if (DISPLAY_VER(display) >= 9) 341 latencies = display->wm.skl_latency; 342 else 343 latencies = display->wm.spr_latency; 344 345 return wm_latency_write(file, ubuf, len, offp, latencies); 346 } 347 348 static ssize_t cur_wm_latency_write(struct file *file, const char __user *ubuf, 349 size_t len, loff_t *offp) 350 { 351 struct seq_file *m = file->private_data; 352 struct intel_display *display = m->private; 353 u16 *latencies; 354 355 if (DISPLAY_VER(display) >= 9) 356 latencies = display->wm.skl_latency; 357 else 358 latencies = display->wm.cur_latency; 359 360 return wm_latency_write(file, ubuf, len, offp, latencies); 361 } 362 363 static const struct file_operations i915_pri_wm_latency_fops = { 364 .owner = THIS_MODULE, 365 .open = pri_wm_latency_open, 366 .read = seq_read, 367 .llseek = seq_lseek, 368 .release = single_release, 369 .write = pri_wm_latency_write 370 }; 371 372 static const struct file_operations i915_spr_wm_latency_fops = { 373 .owner = THIS_MODULE, 374 .open = spr_wm_latency_open, 375 .read = seq_read, 376 .llseek = seq_lseek, 377 .release = single_release, 378 .write = spr_wm_latency_write 379 }; 380 381 static const struct file_operations i915_cur_wm_latency_fops = { 382 .owner = THIS_MODULE, 383 .open = cur_wm_latency_open, 384 .read = seq_read, 385 .llseek = seq_lseek, 386 .release = single_release, 387 .write = cur_wm_latency_write 388 }; 389 390 void intel_wm_debugfs_register(struct intel_display *display) 391 { 392 struct dentry *debugfs_root = display->drm->debugfs_root; 393 394 debugfs_create_file("i915_pri_wm_latency", 0644, debugfs_root, 395 display, &i915_pri_wm_latency_fops); 396 397 debugfs_create_file("i915_spr_wm_latency", 0644, debugfs_root, 398 display, &i915_spr_wm_latency_fops); 399 400 debugfs_create_file("i915_cur_wm_latency", 0644, debugfs_root, 401 display, &i915_cur_wm_latency_fops); 402 403 skl_watermark_debugfs_register(display); 404 } 405