Add a per-CRTC debugfs entry 'vrr/cmrr' and a debugfs file (numerator/denominator) that indicates user intended target refresh rate and video mode requirement.
Signed-off-by: Mitul Golani <[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 | 105 ++++++++++++++++++ drivers/gpu/drm/i915/display/intel_vrr.h | 2 + 4 files changed, 114 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 08004c1ba03f..1ce6e73ec83c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -48,6 +48,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" @@ -1393,6 +1394,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 6cd102a3b610..897a1ffd7b79 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1545,6 +1545,11 @@ struct intel_crtc { u64 flip_count; } dc_balance; + struct { + u32 numerator; + u32 denominator; + } 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 cd380fe8fd01..41118883b845 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 "intel_alpm.h" @@ -1231,3 +1235,104 @@ 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 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 KHz (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; + + if (*numerator == 0) + return -EINVAL; + + if (*denominator != 1000 && *denominator != 1001) + return -EINVAL; + + return 0; +} + +static int intel_vrr_cmrr_show(struct seq_file *m, void *data) +{ + struct intel_crtc *crtc = m->private; + + seq_printf(m, "%u/%u\n", crtc->cmrr.numerator, crtc->cmrr.denominator); + + return 0; +} + +static int intel_vrr_cmrr_open(struct inode *inode, struct file *file) +{ + return single_open(file, intel_vrr_cmrr_show, inode->i_private); +} + +static ssize_t intel_vrr_cmrr_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 = cmrr_parse_ratio(kbuf, &numerator, &denominator); + if (ret) + return ret; + + crtc->cmrr.numerator = numerator; + crtc->cmrr.denominator = denominator; + + return len; +} + +static const struct file_operations intel_vrr_cmrr_fops = { + .owner = THIS_MODULE, + .open = intel_vrr_cmrr_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = intel_vrr_cmrr_write, +}; + +void intel_vrr_crtc_debugfs_add(struct intel_crtc *crtc) +{ + struct intel_display *display = to_intel_display(crtc); + struct dentry *vrr_dir; + + if (!HAS_VRR(display)) + return; + + vrr_dir = debugfs_create_dir("vrr", crtc->base.debugfs_entry); + + if (HAS_CMRR(display)) + debugfs_create_file("cmrr", 0600, vrr_dir, crtc, + &intel_vrr_cmrr_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__ */ -- 2.48.1
