Re: [PATCH v6 3/9] drm/i915/vrr: Add per-CRTC vrr/cmrr debugfs control
"Borah, Chaitanya Kumar" <[email protected]> Thu, 23 Jul 2026 21:46:48 +0530
| Newsgroups | org.freedesktop.lists.intel-gfx,org.freedesktop.lists.intel-xe |
|---|---|
| Message-ID | <[email protected]> |
On 7/22/2026 10:09 AM, Mitul Golani wrote: > Add a per-CRTC debugfs file 'intel_vrr_cmrr' that lets the user force a > CMRR target refresh rate and video-mode requirement. > > The file uses a "numerator/denominator" format: > - numerator: requested refresh rate in milli-Hz > (refresh rate in Hz * 1000, e.g. 60000 for 60 Hz) > - denominator: 1000 for a 1:1 ratio (no video timing) or > 1001 for the 1000/1001 video timing > > Reading the file reports the currently stored values; writing updates > them. The file is created only on platforms with VRR and CMRR support. > The commit message is not updated with the new debugfs name. > --v2: > - Drop the "vrr" debugfs subdirectory and expose a single flat, > intel_-prefixed "intel_vrr_cmrr" file (Jani, Nikula) > - Rename struct intel_crtc.cmrr to force_cmrr to make its purpose > explicit (Chaitanya) > - Fix parse comment: numerator unit is milli-Hz, not KHz (Chaitanya) > - Add debugfs/intel_ prefixes to the debugfs handler functions (Chaitanya) > - Expand commit message with debugfs entry semantics (Chaitanya) > > --v3: > - Rename debugfs function and file name (Chaitanya) > - Remove railing new line at EOF (Chaitanya) > - Update CMRR guard conditions (Chaitanya) > - Add 0/0 default case. (Ramanaidu) > > --v4: > - Correct CMRR guard check while creating debugfs > > Signed-off-by: Mitul Golani <[email protected]> > Reviewed-by: Chaitanya Kumar Borah <[email protected]> > --- > .../drm/i915/display/intel_display_debugfs.c | 2 + > .../drm/i915/display/intel_display_types.h | 5 + > drivers/gpu/drm/i915/display/intel_vrr.c | 108 ++++++++++++++++++ > drivers/gpu/drm/i915/display/intel_vrr.h | 2 + > 4 files changed, 117 insertions(+) > > diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c > index 3f02868ef105..2bbf4760dc30 100644 > --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c > +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c > @@ -49,6 +49,7 @@ > #include "intel_psr.h" > #include "intel_psr_regs.h" > #include "intel_vdsc.h" > +#include "intel_vrr.h" > #include "intel_wm.h" > #include "intel_tc.h" > > @@ -1395,6 +1396,7 @@ void intel_crtc_debugfs_add(struct intel_crtc *crtc) > intel_drrs_crtc_debugfs_add(crtc); > intel_fbc_crtc_debugfs_add(crtc); > hsw_ips_crtc_debugfs_add(crtc); > + intel_vrr_crtc_debugfs_add(crtc); > > debugfs_create_file("i915_current_bpc", 0444, root, crtc, > &i915_current_bpc_fops); > diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h > index b7cc361fd955..46dd980b315a 100644 > --- a/drivers/gpu/drm/i915/display/intel_display_types.h > +++ b/drivers/gpu/drm/i915/display/intel_display_types.h > @@ -1553,6 +1553,11 @@ struct intel_crtc { > u64 flip_count; > } dc_balance; > > + struct { > + u32 numerator; > + u32 denominator; > + } force_cmrr; > + > int scanline_offset; > > struct { > diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c > index 14f8ac07c911..267c65d9245f 100644 > --- a/drivers/gpu/drm/i915/display/intel_vrr.c > +++ b/drivers/gpu/drm/i915/display/intel_vrr.c > @@ -4,6 +4,10 @@ > * > */ > > +#include <linux/debugfs.h> > +#include <linux/seq_file.h> > +#include <linux/string.h> > + > #include <drm/drm_print.h> > #include <drm/intel/step.h> > > @@ -1237,3 +1241,107 @@ int intel_vrr_dcb_vmax_vblank_start_final(const struct intel_crtc_state *crtc_st > > return intel_vrr_vblank_start(crtc_state, VRR_DCB_VMAX(tmp) + 1); > } > + > +static > +int intel_vrr_cmrr_parse_ratio(char *str, u32 *numerator, u32 *denominator) > +{ > + char *sep; > + int ret; > + > + /* > + * Parse a "numerator/denominator" CMRR ratio string. The numerator > + * is the requested refresh rate in milli-Hz (refresh rate in Hz * 1000) > + * and the denominator selects the timing: 1000 for a 1:1 ratio > + * (no video timing) or 1001 for the 1000/1001 video timing. > + */ > + > + sep = strchr(str, '/'); > + if (!sep) > + return -EINVAL; > + > + *sep = '\0'; > + > + ret = kstrtou32(strim(str), 10, numerator); > + if (ret) > + return ret; > + > + ret = kstrtou32(strim(sep + 1), 10, denominator); > + if (ret) > + return ret; > + /* > + * "0/0" clears any previously configured CMRR override. > + * A zero numerator already means "CMRR not requested" in > + * intel_vrr_cmrr_compute_config(), so just let it through. > + */ > + if (*numerator == 0 && *denominator == 0) > + return 0; > + > + if (*numerator == 0) > + return -EINVAL; > + > + if (*denominator != 1000 && *denominator != 1001) > + return -EINVAL; > + > + return 0; > +} > + > +static int intel_vrr_debugfs_target_rr_show(struct seq_file *m, void *data) > +{ > + struct intel_crtc *crtc = m->private; > + > + seq_printf(m, "%u/%u\n", crtc->force_cmrr.numerator, crtc->force_cmrr.denominator); > + > + return 0; > +} > + > +static int intel_vrr_debugfs_target_rr_open(struct inode *inode, struct file *file) > +{ > + return single_open(file, intel_vrr_debugfs_target_rr_show, inode->i_private); > +} > + > +static ssize_t intel_vrr_debugfs_target_rr_write(struct file *file, const char __user *ubuf, > + size_t len, loff_t *offp) > +{ > + struct seq_file *m = file->private_data; > + struct intel_crtc *crtc = m->private; > + u32 numerator, denominator; > + char kbuf[32]; > + int ret; > + > + if (len >= sizeof(kbuf)) > + return -EINVAL; > + > + if (copy_from_user(kbuf, ubuf, len)) > + return -EFAULT; > + > + kbuf[len] = '\0'; > + > + ret = intel_vrr_cmrr_parse_ratio(kbuf, &numerator, &denominator); > + if (ret) > + return ret; > + > + crtc->force_cmrr.numerator = numerator; > + crtc->force_cmrr.denominator = denominator; > + > + return len; > +} > + > +static const struct file_operations intel_vrr_debugfs_target_rr_fops = { > + .owner = THIS_MODULE, > + .open = intel_vrr_debugfs_target_rr_open, > + .read = seq_read, > + .llseek = seq_lseek, > + .release = single_release, > + .write = intel_vrr_debugfs_target_rr_write, > +}; > + > +void intel_vrr_crtc_debugfs_add(struct intel_crtc *crtc) > +{ > + struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); > + > + if (!intel_vrr_cmrr_possible(crtc_state)) > + return; > + > + debugfs_create_file("intel_vrr_target_refresh_rate", 0600, crtc->base.debugfs_entry, > + crtc, &intel_vrr_debugfs_target_rr_fops); > +} > diff --git a/drivers/gpu/drm/i915/display/intel_vrr.h b/drivers/gpu/drm/i915/display/intel_vrr.h > index 55e9c429f579..19c7990be1b2 100644 > --- a/drivers/gpu/drm/i915/display/intel_vrr.h > +++ b/drivers/gpu/drm/i915/display/intel_vrr.h > @@ -56,4 +56,6 @@ int intel_vrr_dcb_vmax_vblank_start_next(const struct intel_crtc_state *crtc_sta > int intel_vrr_dcb_vmin_vblank_start_final(const struct intel_crtc_state *crtc_state); > int intel_vrr_dcb_vmax_vblank_start_final(const struct intel_crtc_state *crtc_state); > > +void intel_vrr_crtc_debugfs_add(struct intel_crtc *crtc); > + > #endif /* __INTEL_VRR_H__ */