drm/i915/dsc: Add debugfs entry to validate DSC output formats
authorSwati Sharma <swati2.sharma@intel.com>
Thu, 9 Mar 2023 06:28:55 +0000 (11:58 +0530)
committerUma Shankar <uma.shankar@intel.com>
Mon, 3 Apr 2023 07:11:13 +0000 (12:41 +0530)
DSC_Output_Format_Sink_Support entry is added to i915_dsc_fec_support_show
to depict if sink supports DSC output formats (RGB/YCbCr420/YCbCr444).
Also, new debugfs entry is created to enforce output format. This is
required because of our driver policy. For ex. if a mode is supported
in both RGB and YCbCr420 output formats by the sink, our policy is to
try RGB first and fall back to YCbCr420, if mode cannot be shown
using RGB. So, to test other output formats like YCbCr420 or YCbCr444,
we need a debugfs entry (force_dsc_output_format) to force this
output format.

v2: -Func name changed to intel_output_format_name() (Jani N)
    -Return forced o/p format from intel_dp_output_format() (Jani N)
v3: -output_format_str[] to remain static (Jani N)

Signed-off-by: Swati Sharma <swati2.sharma@intel.com>
Reviewed-by: Uma Shankar <uma.shankar@intel.com>
Signed-off-by: Uma Shankar <uma.shankar@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230309062855.393087-8-suraj.kandpal@intel.com
drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
drivers/gpu/drm/i915/display/intel_crtc_state_dump.h
drivers/gpu/drm/i915/display/intel_display_debugfs.c
drivers/gpu/drm/i915/display/intel_display_types.h
drivers/gpu/drm/i915/display/intel_dp.c

index 766633566fd6d1cbfcd8d6583d6c84e0f91ccddc..54c8adc0702eeba1dd9ecc417c43ef8224bea8e7 100644 (file)
@@ -123,7 +123,7 @@ static const char * const output_format_str[] = {
        [INTEL_OUTPUT_FORMAT_YCBCR444] = "YCBCR4:4:4",
 };
 
-static const char *output_formats(enum intel_output_format format)
+const char *intel_output_format_name(enum intel_output_format format)
 {
        if (format >= ARRAY_SIZE(output_format_str))
                return "invalid";
@@ -181,7 +181,7 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config,
                    "active: %s, output_types: %s (0x%x), output format: %s\n",
                    str_yes_no(pipe_config->hw.active),
                    buf, pipe_config->output_types,
-                   output_formats(pipe_config->output_format));
+                   intel_output_format_name(pipe_config->output_format));
 
        drm_dbg_kms(&i915->drm,
                    "cpu_transcoder: %s, pipe bpp: %i, dithering: %i\n",
index 9399c35b7e5edae12b4e3d60170aac025c1f39c4..780f3f1190d762ed5377d1d90940678c03115ab8 100644 (file)
@@ -8,9 +8,11 @@
 
 struct intel_crtc_state;
 struct intel_atomic_state;
+enum intel_output_format;
 
 void intel_crtc_state_dump(const struct intel_crtc_state *crtc_state,
                           struct intel_atomic_state *state,
                           const char *context);
+const char *intel_output_format_name(enum intel_output_format format);
 
 #endif /* __INTEL_CRTC_STATE_H__ */
index d5715ccc37f0e67d837aed01b10e72e38bf6209d..bad29cdd139df89e12d0021bd58e96ed2c6583d9 100644 (file)
@@ -13,6 +13,7 @@
 #include "i915_irq.h"
 #include "i915_reg.h"
 #include "intel_de.h"
+#include "intel_crtc_state_dump.h"
 #include "intel_display_debugfs.h"
 #include "intel_display_power.h"
 #include "intel_display_power_well.h"
@@ -1234,6 +1235,13 @@ static int i915_dsc_fec_support_show(struct seq_file *m, void *data)
                           str_yes_no(crtc_state->dsc.compression_enable));
                seq_printf(m, "DSC_Sink_Support: %s\n",
                           str_yes_no(drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd)));
+               seq_printf(m, "DSC_Output_Format_Sink_Support: RGB: %s YCBCR420: %s YCBCR444: %s\n",
+                          str_yes_no(drm_dp_dsc_sink_supports_format(intel_dp->dsc_dpcd,
+                                                                     DP_DSC_RGB)),
+                          str_yes_no(drm_dp_dsc_sink_supports_format(intel_dp->dsc_dpcd,
+                                                                     DP_DSC_YCbCr420_Native)),
+                          str_yes_no(drm_dp_dsc_sink_supports_format(intel_dp->dsc_dpcd,
+                                                                     DP_DSC_YCbCr444)));
                seq_printf(m, "Force_DSC_Enable: %s\n",
                           str_yes_no(intel_dp->force_dsc_en));
                if (!intel_dp_is_edp(intel_dp))
@@ -1359,6 +1367,73 @@ static const struct file_operations i915_dsc_bpc_fops = {
        .write = i915_dsc_bpc_write
 };
 
+static int i915_dsc_output_format_show(struct seq_file *m, void *data)
+{
+       struct drm_connector *connector = m->private;
+       struct drm_device *dev = connector->dev;
+       struct drm_crtc *crtc;
+       struct intel_crtc_state *crtc_state;
+       struct intel_encoder *encoder = intel_attached_encoder(to_intel_connector(connector));
+       int ret;
+
+       if (!encoder)
+               return -ENODEV;
+
+       ret = drm_modeset_lock_single_interruptible(&dev->mode_config.connection_mutex);
+       if (ret)
+               return ret;
+
+       crtc = connector->state->crtc;
+       if (connector->status != connector_status_connected || !crtc) {
+               ret = -ENODEV;
+               goto out;
+       }
+
+       crtc_state = to_intel_crtc_state(crtc->state);
+       seq_printf(m, "DSC_Output_Format: %s\n",
+                  intel_output_format_name(crtc_state->output_format));
+
+out:   drm_modeset_unlock(&dev->mode_config.connection_mutex);
+
+       return ret;
+}
+
+static ssize_t i915_dsc_output_format_write(struct file *file,
+                                           const char __user *ubuf,
+                                           size_t len, loff_t *offp)
+{
+       struct drm_connector *connector =
+               ((struct seq_file *)file->private_data)->private;
+       struct intel_encoder *encoder = intel_attached_encoder(to_intel_connector(connector));
+       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+       int dsc_output_format = 0;
+       int ret;
+
+       ret = kstrtoint_from_user(ubuf, len, 0, &dsc_output_format);
+       if (ret < 0)
+               return ret;
+
+       intel_dp->force_dsc_output_format = dsc_output_format;
+       *offp += len;
+
+       return len;
+}
+
+static int i915_dsc_output_format_open(struct inode *inode,
+                                      struct file *file)
+{
+       return single_open(file, i915_dsc_output_format_show, inode->i_private);
+}
+
+static const struct file_operations i915_dsc_output_format_fops = {
+       .owner = THIS_MODULE,
+       .open = i915_dsc_output_format_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+       .write = i915_dsc_output_format_write
+};
+
 /*
  * Returns the Current CRTC's bpc.
  * Example usage: cat /sys/kernel/debug/dri/0/crtc-0/i915_current_bpc
@@ -1433,6 +1508,9 @@ void intel_connector_debugfs_add(struct intel_connector *intel_connector)
 
                debugfs_create_file("i915_dsc_bpc", 0644, root,
                                    connector, &i915_dsc_bpc_fops);
+
+               debugfs_create_file("i915_dsc_output_format", 0644, root,
+                                   connector, &i915_dsc_output_format_fops);
        }
 
        if (connector->connector_type == DRM_MODE_CONNECTOR_DSI ||
index 4236ad751c2ca7eea6a302480a1038ac32edf890..d84818fc94a4358627ccce0af87faa8cffe4ce68 100644 (file)
@@ -1741,6 +1741,7 @@ struct intel_dp {
 
        /* Display stream compression testing */
        bool force_dsc_en;
+       int force_dsc_output_format;
        int force_dsc_bpc;
 
        bool hobl_failed;
index 4a909087ea49ddf1a10b2676bab9dff44b8d5eec..f0bace9d98a18c16e5564f97506d540d786875d6 100644 (file)
@@ -76,6 +76,7 @@
 #include "intel_tc.h"
 #include "intel_vdsc.h"
 #include "intel_vrr.h"
+#include "intel_crtc_state_dump.h"
 
 /* DP DSC throughput values used for slice count calculations KPixels/s */
 #define DP_DSC_PEAK_PIXEL_RATE                 2720000
@@ -833,6 +834,9 @@ intel_dp_output_format(struct intel_connector *connector,
 {
        struct intel_dp *intel_dp = intel_attached_dp(connector);
 
+       if (intel_dp->force_dsc_output_format)
+               return intel_dp->force_dsc_output_format;
+
        if (!connector->base.ycbcr_420_allowed || !ycbcr_420_output)
                return INTEL_OUTPUT_FORMAT_RGB;