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

Reply via email to