drm/i915: Add support for DP Video pattern compliance tests
authorManasi Navare <manasi.d.navare@intel.com>
Tue, 24 Jan 2017 16:21:49 +0000 (08:21 -0800)
committerJani Nikula <jani.nikula@intel.com>
Thu, 26 Jan 2017 11:16:06 +0000 (13:16 +0200)
The intel_dp_autotest_video_pattern() function gets invoked through the
compliance test handler on a HPD short pulse if the test type is
set to DP_TEST_VIDEO_PATTERN. This performs the DPCD registers
reads to read the requested test pattern, video pattern resolution,
frame rate and bits per color value. The results of this analysis
are handed off to userspace so that the userspace app can set the
video pattern mode appropriately for the test result/response.
When the  test is requested with specific BPC value, we read the BPC
value from the DPCD register. If this BPC value in intel_dp structure
has a non-zero value and we're on a display port connector, then we use
the value to calculate the bpp for the pipe. Also in this case if its
a 18bpp video pattern request, then we force the dithering on pipe to be
disabled since it causes CRC mismatches.

The compliance_test_active flag is set at the end of the individual
test handling functions. This is so that the kernel-side operations
can be completed without the risk of interruption from the userspace
app that is polling on that flag.

v5:
* Remove test_result variable
* Populate the compliance test data at the end of the function (Jani Nikula)
v4:
*Return TEST_NAK on read failures and invalid values (Jani Nikula)
* Address CRC mismatch errors
v3:
* Use the updated properly shifted bit definitions (Jani Nikula)
* Force dithering to be disabled on 18bpp compliance
test request (Manasi Navare)
v2:
* Updated the DPCD Register reads based on proper defines in header (Jani Nikula)
* Squahsed the patch that forced the pipe bpp to compliance test bpp (Jani Nikula)
Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@intel.com>
Cc: Ville Syrjala <ville.syrjala@linux.intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1485274909-17470-1-git-send-email-manasi.d.navare@intel.com
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_dp_mst.c
drivers/gpu/drm/i915/intel_drv.h

index 726256fa35cea489f5124c28c6dc1855a339cf06..0a39487386ad12caa8b12527ff6ae516603f67e9 100644 (file)
@@ -3779,6 +3779,15 @@ static int i915_displayport_test_data_show(struct seq_file *m, void *data)
                            DP_TEST_LINK_EDID_READ)
                                seq_printf(m, "%lx",
                                           intel_dp->compliance.test_data.edid);
+                       else if (intel_dp->compliance.test_type ==
+                                DP_TEST_LINK_VIDEO_PATTERN) {
+                               seq_printf(m, "hdisplay: %d\n",
+                                          intel_dp->compliance.test_data.hdisplay);
+                               seq_printf(m, "vdisplay: %d\n",
+                                          intel_dp->compliance.test_data.vdisplay);
+                               seq_printf(m, "bpc: %u\n",
+                                          intel_dp->compliance.test_data.bpc);
+                       }
                } else
                        seq_puts(m, "0");
        }
index 5a9da484bb232e3759b5a1cd4a3aaa3d1f8b95fd..ef65b4be5e56067bdb34414e3bfcbb8c1e8523e3 100644 (file)
@@ -13060,8 +13060,11 @@ encoder_retry:
        }
 
        /* Dithering seems to not pass-through bits correctly when it should, so
-        * only enable it on 6bpc panels. */
-       pipe_config->dither = pipe_config->pipe_bpp == 6*3;
+        * only enable it on 6bpc panels and when its not a compliance
+        * test requesting 6bpc video pattern.
+        */
+       pipe_config->dither = (pipe_config->pipe_bpp == 6*3) &&
+               !pipe_config->dither_force_disable;
        DRM_DEBUG_KMS("hw max bpp: %i, pipe bpp: %i, dithering: %i\n",
                      base_bpp, pipe_config->pipe_bpp, pipe_config->dither);
 
index e245802c572729a4c18cd1175b607efc5da807be..0fafbec6dacfc430cc1a1d6a2ffb6fc4ccc21303 100644 (file)
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <linux/types.h>
 #include <linux/notifier.h>
 #include <linux/reboot.h>
+#include <asm/byteorder.h>
 #include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
@@ -1593,6 +1595,13 @@ static int intel_dp_compute_bpp(struct intel_dp *intel_dp,
        if (bpc > 0)
                bpp = min(bpp, 3*bpc);
 
+       /* For DP Compliance we override the computed bpp for the pipe */
+       if (intel_dp->compliance.test_data.bpc != 0) {
+               pipe_config->pipe_bpp = 3*intel_dp->compliance.test_data.bpc;
+               pipe_config->dither_force_disable = pipe_config->pipe_bpp == 6*3;
+               DRM_DEBUG_KMS("Setting pipe_bpp to %d\n",
+                             pipe_config->pipe_bpp);
+       }
        return bpp;
 }
 
@@ -3973,8 +3982,63 @@ static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)
 
 static uint8_t intel_dp_autotest_video_pattern(struct intel_dp *intel_dp)
 {
-       uint8_t test_result = DP_TEST_NAK;
-       return test_result;
+       uint8_t test_pattern;
+       uint16_t test_misc;
+       __be16 h_width, v_height;
+       int status = 0;
+
+       /* Read the TEST_PATTERN (DP CTS 3.1.5) */
+       status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_PATTERN,
+                                 &test_pattern, 1);
+       if (status <= 0) {
+               DRM_DEBUG_KMS("Test pattern read failed\n");
+               return DP_TEST_NAK;
+       }
+       if (test_pattern != DP_COLOR_RAMP)
+               return DP_TEST_NAK;
+
+       status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_H_WIDTH_HI,
+                                 &h_width, 2);
+       if (status <= 0) {
+               DRM_DEBUG_KMS("H Width read failed\n");
+               return DP_TEST_NAK;
+       }
+
+       status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_V_HEIGHT_HI,
+                                 &v_height, 2);
+       if (status <= 0) {
+               DRM_DEBUG_KMS("V Height read failed\n");
+               return DP_TEST_NAK;
+       }
+
+       status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_MISC0,
+                                 &test_misc, 1);
+       if (status <= 0) {
+               DRM_DEBUG_KMS("TEST MISC read failed\n");
+               return DP_TEST_NAK;
+       }
+       if ((test_misc & DP_TEST_COLOR_FORMAT_MASK) != DP_COLOR_FORMAT_RGB)
+               return DP_TEST_NAK;
+       if (test_misc & DP_TEST_DYNAMIC_RANGE_CEA)
+               return DP_TEST_NAK;
+       switch (test_misc & DP_TEST_BIT_DEPTH_MASK) {
+       case DP_TEST_BIT_DEPTH_6:
+               intel_dp->compliance.test_data.bpc = 6;
+               break;
+       case DP_TEST_BIT_DEPTH_8:
+               intel_dp->compliance.test_data.bpc = 8;
+               break;
+       default:
+               return DP_TEST_NAK;
+       }
+
+       intel_dp->compliance.test_data.video_pattern = test_pattern;
+       intel_dp->compliance.test_data.hdisplay = be16_to_cpu(h_width);
+       intel_dp->compliance.test_data.vdisplay = be16_to_cpu(v_height);
+       /* Set test active flag here so userspace doesn't interrupt things */
+       intel_dp->compliance.test_active = 1;
+
+       return DP_TEST_ACK;
 }
 
 static uint8_t intel_dp_autotest_edid(struct intel_dp *intel_dp)
index 205fe4748ec5acf424bed24ebd1fa7fc3740dae4..29a9af177734d220520c045d7796af6e61cf1c89 100644 (file)
@@ -47,6 +47,11 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
 
        pipe_config->has_pch_encoder = false;
        bpp = 24;
+       if (intel_dp->compliance.test_data.bpc) {
+               bpp = intel_dp->compliance.test_data.bpc * 3;
+               DRM_DEBUG_KMS("Setting pipe bpp to %d\n",
+                             bpp);
+       }
        /*
         * for MST we always configure max link bw - the spec doesn't
         * seem to suggest we should do otherwise.
@@ -55,7 +60,7 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
 
        pipe_config->lane_count = lane_count;
 
-       pipe_config->pipe_bpp = 24;
+       pipe_config->pipe_bpp = bpp;
        pipe_config->port_clock = intel_dp_max_link_rate(intel_dp);
 
        state = pipe_config->base.state;
index fbd20dab5b457d059a88b8c333fd730d7d2a8f2d..1fb593ecc60c23f09b37cb9ee27b149a04d554fd 100644 (file)
@@ -580,6 +580,14 @@ struct intel_crtc_state {
         */
        bool dither;
 
+       /*
+        * Dither gets enabled for 18bpp which causes CRC mismatch errors for
+        * compliance video pattern tests.
+        * Disable dither only if it is a compliance test request for
+        * 18bpp.
+        */
+       bool dither_force_disable;
+
        /* Controls for the clock computation, to override various stages. */
        bool clock_set;
 
@@ -890,6 +898,9 @@ struct intel_dp_desc {
 
 struct intel_dp_compliance_data {
        unsigned long edid;
+       uint8_t video_pattern;
+       uint16_t hdisplay, vdisplay;
+       uint8_t bpc;
 };
 
 struct intel_dp_compliance {