1 // SPDX-License-Identifier: MIT
3 * Copyright © 2023 Intel Corporation
6 #include <linux/debugfs.h>
10 #include "intel_display_types.h"
12 #include "skl_watermark.h"
15 * intel_update_watermarks - update FIFO watermark values based on current modes
18 * Calculate watermark values for the various WM regs based on current mode
19 * and plane configuration.
21 * There are several cases to deal with here:
22 * - normal (i.e. non-self-refresh)
23 * - self-refresh (SR) mode
24 * - lines are large relative to FIFO size (buffer can hold up to 2)
25 * - lines are small relative to FIFO size (buffer can hold more than 2
26 * lines), so need to account for TLB latency
28 * The normal calculation is:
29 * watermark = dotclock * bytes per pixel * latency
30 * where latency is platform & configuration dependent (we assume pessimal
33 * The SR calculation is:
34 * watermark = (trunc(latency/line time)+1) * surface width *
37 * line time = htotal / dotclock
38 * surface width = hdisplay for normal plane and 64 for cursor
39 * and latency is assumed to be high, as above.
41 * The final value programmed to the register should always be rounded up,
42 * and include an extra 2 entries to account for clock crossings.
44 * We don't use the sprite, so we can ignore that. And on Crestline we have
45 * to set the non-SR watermarks to 8.
47 void intel_update_watermarks(struct drm_i915_private *i915)
49 if (i915->display.funcs.wm->update_wm)
50 i915->display.funcs.wm->update_wm(i915);
53 int intel_wm_compute(struct intel_atomic_state *state,
54 struct intel_crtc *crtc)
56 struct intel_display *display = to_intel_display(state);
58 if (!display->funcs.wm->compute_watermarks)
61 return display->funcs.wm->compute_watermarks(state, crtc);
64 bool intel_initial_watermarks(struct intel_atomic_state *state,
65 struct intel_crtc *crtc)
67 struct drm_i915_private *i915 = to_i915(state->base.dev);
69 if (i915->display.funcs.wm->initial_watermarks) {
70 i915->display.funcs.wm->initial_watermarks(state, crtc);
77 void intel_atomic_update_watermarks(struct intel_atomic_state *state,
78 struct intel_crtc *crtc)
80 struct drm_i915_private *i915 = to_i915(state->base.dev);
82 if (i915->display.funcs.wm->atomic_update_watermarks)
83 i915->display.funcs.wm->atomic_update_watermarks(state, crtc);
86 void intel_optimize_watermarks(struct intel_atomic_state *state,
87 struct intel_crtc *crtc)
89 struct drm_i915_private *i915 = to_i915(state->base.dev);
91 if (i915->display.funcs.wm->optimize_watermarks)
92 i915->display.funcs.wm->optimize_watermarks(state, crtc);
95 int intel_compute_global_watermarks(struct intel_atomic_state *state)
97 struct drm_i915_private *i915 = to_i915(state->base.dev);
99 if (i915->display.funcs.wm->compute_global_watermarks)
100 return i915->display.funcs.wm->compute_global_watermarks(state);
105 void intel_wm_get_hw_state(struct drm_i915_private *i915)
107 if (i915->display.funcs.wm->get_hw_state)
108 return i915->display.funcs.wm->get_hw_state(i915);
111 bool intel_wm_plane_visible(const struct intel_crtc_state *crtc_state,
112 const struct intel_plane_state *plane_state)
114 struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
116 /* FIXME check the 'enable' instead */
117 if (!crtc_state->hw.active)
121 * Treat cursor with fb as always visible since cursor updates
122 * can happen faster than the vrefresh rate, and the current
123 * watermark code doesn't handle that correctly. Cursor updates
124 * which set/clear the fb or change the cursor size are going
125 * to get throttled by intel_legacy_cursor_update() to work
126 * around this problem with the watermark code.
128 if (plane->id == PLANE_CURSOR)
129 return plane_state->hw.fb != NULL;
131 return plane_state->uapi.visible;
134 void intel_print_wm_latency(struct drm_i915_private *dev_priv,
135 const char *name, const u16 wm[])
139 for (level = 0; level < dev_priv->display.wm.num_levels; level++) {
140 unsigned int latency = wm[level];
143 drm_dbg_kms(&dev_priv->drm,
144 "%s WM%d latency not provided\n",
150 * - latencies are in us on gen9.
151 * - before then, WM1+ latency values are in 0.5us units
153 if (DISPLAY_VER(dev_priv) >= 9)
158 drm_dbg_kms(&dev_priv->drm,
159 "%s WM%d latency %u (%u.%u usec)\n", name, level,
160 wm[level], latency / 10, latency % 10);
164 void intel_wm_init(struct drm_i915_private *i915)
166 if (DISPLAY_VER(i915) >= 9)
172 static void wm_latency_show(struct seq_file *m, const u16 wm[8])
174 struct drm_i915_private *dev_priv = m->private;
177 drm_modeset_lock_all(&dev_priv->drm);
179 for (level = 0; level < dev_priv->display.wm.num_levels; level++) {
180 unsigned int latency = wm[level];
183 * - WM1+ latency values in 0.5us units
184 * - latencies are in us on gen9/vlv/chv
186 if (DISPLAY_VER(dev_priv) >= 9 ||
187 IS_VALLEYVIEW(dev_priv) ||
188 IS_CHERRYVIEW(dev_priv) ||
194 seq_printf(m, "WM%d %u (%u.%u usec)\n",
195 level, wm[level], latency / 10, latency % 10);
198 drm_modeset_unlock_all(&dev_priv->drm);
201 static int pri_wm_latency_show(struct seq_file *m, void *data)
203 struct drm_i915_private *dev_priv = m->private;
204 const u16 *latencies;
206 if (DISPLAY_VER(dev_priv) >= 9)
207 latencies = dev_priv->display.wm.skl_latency;
209 latencies = dev_priv->display.wm.pri_latency;
211 wm_latency_show(m, latencies);
216 static int spr_wm_latency_show(struct seq_file *m, void *data)
218 struct drm_i915_private *dev_priv = m->private;
219 const u16 *latencies;
221 if (DISPLAY_VER(dev_priv) >= 9)
222 latencies = dev_priv->display.wm.skl_latency;
224 latencies = dev_priv->display.wm.spr_latency;
226 wm_latency_show(m, latencies);
231 static int cur_wm_latency_show(struct seq_file *m, void *data)
233 struct drm_i915_private *dev_priv = m->private;
234 const u16 *latencies;
236 if (DISPLAY_VER(dev_priv) >= 9)
237 latencies = dev_priv->display.wm.skl_latency;
239 latencies = dev_priv->display.wm.cur_latency;
241 wm_latency_show(m, latencies);
246 static int pri_wm_latency_open(struct inode *inode, struct file *file)
248 struct drm_i915_private *dev_priv = inode->i_private;
250 if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv))
253 return single_open(file, pri_wm_latency_show, dev_priv);
256 static int spr_wm_latency_open(struct inode *inode, struct file *file)
258 struct drm_i915_private *dev_priv = inode->i_private;
260 if (HAS_GMCH(dev_priv))
263 return single_open(file, spr_wm_latency_show, dev_priv);
266 static int cur_wm_latency_open(struct inode *inode, struct file *file)
268 struct drm_i915_private *dev_priv = inode->i_private;
270 if (HAS_GMCH(dev_priv))
273 return single_open(file, cur_wm_latency_show, dev_priv);
276 static ssize_t wm_latency_write(struct file *file, const char __user *ubuf,
277 size_t len, loff_t *offp, u16 wm[8])
279 struct seq_file *m = file->private_data;
280 struct drm_i915_private *dev_priv = m->private;
286 if (len >= sizeof(tmp))
289 if (copy_from_user(tmp, ubuf, len))
294 ret = sscanf(tmp, "%hu %hu %hu %hu %hu %hu %hu %hu",
295 &new[0], &new[1], &new[2], &new[3],
296 &new[4], &new[5], &new[6], &new[7]);
297 if (ret != dev_priv->display.wm.num_levels)
300 drm_modeset_lock_all(&dev_priv->drm);
302 for (level = 0; level < dev_priv->display.wm.num_levels; level++)
303 wm[level] = new[level];
305 drm_modeset_unlock_all(&dev_priv->drm);
310 static ssize_t pri_wm_latency_write(struct file *file, const char __user *ubuf,
311 size_t len, loff_t *offp)
313 struct seq_file *m = file->private_data;
314 struct drm_i915_private *dev_priv = m->private;
317 if (DISPLAY_VER(dev_priv) >= 9)
318 latencies = dev_priv->display.wm.skl_latency;
320 latencies = dev_priv->display.wm.pri_latency;
322 return wm_latency_write(file, ubuf, len, offp, latencies);
325 static ssize_t spr_wm_latency_write(struct file *file, const char __user *ubuf,
326 size_t len, loff_t *offp)
328 struct seq_file *m = file->private_data;
329 struct drm_i915_private *dev_priv = m->private;
332 if (DISPLAY_VER(dev_priv) >= 9)
333 latencies = dev_priv->display.wm.skl_latency;
335 latencies = dev_priv->display.wm.spr_latency;
337 return wm_latency_write(file, ubuf, len, offp, latencies);
340 static ssize_t cur_wm_latency_write(struct file *file, const char __user *ubuf,
341 size_t len, loff_t *offp)
343 struct seq_file *m = file->private_data;
344 struct drm_i915_private *dev_priv = m->private;
347 if (DISPLAY_VER(dev_priv) >= 9)
348 latencies = dev_priv->display.wm.skl_latency;
350 latencies = dev_priv->display.wm.cur_latency;
352 return wm_latency_write(file, ubuf, len, offp, latencies);
355 static const struct file_operations i915_pri_wm_latency_fops = {
356 .owner = THIS_MODULE,
357 .open = pri_wm_latency_open,
360 .release = single_release,
361 .write = pri_wm_latency_write
364 static const struct file_operations i915_spr_wm_latency_fops = {
365 .owner = THIS_MODULE,
366 .open = spr_wm_latency_open,
369 .release = single_release,
370 .write = spr_wm_latency_write
373 static const struct file_operations i915_cur_wm_latency_fops = {
374 .owner = THIS_MODULE,
375 .open = cur_wm_latency_open,
378 .release = single_release,
379 .write = cur_wm_latency_write
382 void intel_wm_debugfs_register(struct drm_i915_private *i915)
384 struct drm_minor *minor = i915->drm.primary;
386 debugfs_create_file("i915_pri_wm_latency", 0644, minor->debugfs_root,
387 i915, &i915_pri_wm_latency_fops);
389 debugfs_create_file("i915_spr_wm_latency", 0644, minor->debugfs_root,
390 i915, &i915_spr_wm_latency_fops);
392 debugfs_create_file("i915_cur_wm_latency", 0644, minor->debugfs_root,
393 i915, &i915_cur_wm_latency_fops);
395 skl_watermark_debugfs_register(i915);