aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_edid.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2021-10-11 16:53:56 +1000
committerDave Airlie <airlied@redhat.com>2021-10-11 16:53:57 +1000
commitc7c774fe09389fc806bbe4b487c18e45f576c1ae (patch)
tree7e64c57b93dc88ca9a9c1817fed787e7e5664a1b /drivers/gpu/drm/drm_edid.c
parentMerge tag 'drm-misc-next-2021-10-06' of git://anongit.freedesktop.org/drm/drm-misc into drm-next (diff)
parentdrm/i915: Allow per-lane drive settings with LTTPRs (diff)
downloadlinux-dev-c7c774fe09389fc806bbe4b487c18e45f576c1ae.tar.xz
linux-dev-c7c774fe09389fc806bbe4b487c18e45f576c1ae.zip
Merge tag 'drm-intel-next-2021-10-04' of git://anongit.freedesktop.org/drm/drm-intel into drm-next
Cross-subsystem Changes: - fbdev/efifb: Release PCI device's runtime PM ref during FB destr\ oy (Imre) i915 Core Driver Changes: - Only access SFC_DONE in media when not fused off for graphics 12 and newer. - Double Memory latency values from pcode for DG2 (Matt Roper) - ADL-S PCI ID update (Tejas) - New DG1 PCI ID (Jose) - Fix regression with uncore refactoring (Dave) i915 Display Changes: - ADL-P display (XE_LPD) fixes and updates (Ankit, Jani, Matt Roper, Anusham, Jose, Imre, Vandita) - DG2 display fixes (Ankit, Jani) - Expand PCH_CNP tweaked display workaround to all newer displays (Anshuman) - General display simplifications and clean-ups (Jani, Swati, Jose, Ville) - PSR Clean-ups, dropping support for BDW/HSD and enable PSR2 selective fetch by default (Jose, Gwan-gyeong) - Nuke ORIGIN_GTT (Jose) - Return proper DPRX link training result (Lee) - FBC related refactor and fixes (Ville) - Yet another attempt to solve the fast+narrow vs slow+wide eDP link training (Kai-Heng) - DP 2.0 preparation work (Jani) - Silence __iomem sparse warn (Ville) - Clean up DPLL stuff (Ville) - Fix various dp/edp max rates (Matt Atwood, Animesh, Jani) - Remove VBT ddi_port_info caching (Jani) - DSI driver improvements (Lee) - HDCP fixes (Juston) - Associate ACPI connector nodes with connector entries (Heikki) - Add support for out-of-bound hotplug events (Hans) - VESA vendor block and drm/i915 MSO use of it (Jani) - Fixes for bigjoiner (Ville) - Update memory bandwidth parameters (RK) - DMC related fixes (Chris, Jose) - HDR related fixes and improvements (Tejas) - g4x/vlv/chv CxSR/wm fixes/cleanups (Ville) - Use BIOS provided value for RKL Audio's HDA link (Kai-Heng) - Fix the dsc check while selecting min_cdclk (Vandita) - Split and constify vtable (Dave) - Add ww context to intel_dpt_pin (Maarten) - Fix bdb version check (Lukasz) - DP per-lane drive settings prep work and other DP fixes (Ville) Signed-off-by: Dave Airlie <airlied@redhat.com> # gpg: Signature made Tue 05 Oct 2021 04:58:16 AEST # gpg: using RSA key 6D207068EEDD65091C2CE2A3FA625F640EEB13CA # gpg: Good signature from "Rodrigo Vivi <rodrigo.vivi@intel.com>" [unknown] # gpg: aka "Rodrigo Vivi <rodrigo.vivi@gmail.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 6D20 7068 EEDD 6509 1C2C E2A3 FA62 5F64 0EEB 13CA From: Rodrigo Vivi <rodrigo.vivi@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/YVtPk6llsxBFiw7W@intel.com
Diffstat (limited to 'drivers/gpu/drm/drm_edid.c')
-rw-r--r--drivers/gpu/drm/drm_edid.c89
1 files changed, 79 insertions, 10 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 9c9463ec5465..7aa2a56a71c8 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -28,6 +28,7 @@
* DEALINGS IN THE SOFTWARE.
*/
+#include <linux/bitfield.h>
#include <linux/hdmi.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
@@ -49,6 +50,11 @@
(((edid)->version > (maj)) || \
((edid)->version == (maj) && (edid)->revision > (min)))
+static int oui(u8 first, u8 second, u8 third)
+{
+ return (first << 16) | (second << 8) | third;
+}
+
#define EDID_EST_TIMINGS 16
#define EDID_STD_TIMINGS 8
#define EDID_DETAILED_TIMINGS 4
@@ -4187,32 +4193,24 @@ cea_db_offsets(const u8 *cea, int *start, int *end)
static bool cea_db_is_hdmi_vsdb(const u8 *db)
{
- int hdmi_id;
-
if (cea_db_tag(db) != VENDOR_BLOCK)
return false;
if (cea_db_payload_len(db) < 5)
return false;
- hdmi_id = db[1] | (db[2] << 8) | (db[3] << 16);
-
- return hdmi_id == HDMI_IEEE_OUI;
+ return oui(db[3], db[2], db[1]) == HDMI_IEEE_OUI;
}
static bool cea_db_is_hdmi_forum_vsdb(const u8 *db)
{
- unsigned int oui;
-
if (cea_db_tag(db) != VENDOR_BLOCK)
return false;
if (cea_db_payload_len(db) < 7)
return false;
- oui = db[3] << 16 | db[2] << 8 | db[1];
-
- return oui == HDMI_FORUM_IEEE_OUI;
+ return oui(db[3], db[2], db[1]) == HDMI_FORUM_IEEE_OUI;
}
static bool cea_db_is_vcdb(const u8 *db)
@@ -5222,6 +5220,71 @@ void drm_get_monitor_range(struct drm_connector *connector,
info->monitor_range.max_vfreq);
}
+static void drm_parse_vesa_mso_data(struct drm_connector *connector,
+ const struct displayid_block *block)
+{
+ struct displayid_vesa_vendor_specific_block *vesa =
+ (struct displayid_vesa_vendor_specific_block *)block;
+ struct drm_display_info *info = &connector->display_info;
+
+ if (block->num_bytes < 3) {
+ drm_dbg_kms(connector->dev, "Unexpected vendor block size %u\n",
+ block->num_bytes);
+ return;
+ }
+
+ if (oui(vesa->oui[0], vesa->oui[1], vesa->oui[2]) != VESA_IEEE_OUI)
+ return;
+
+ if (sizeof(*vesa) != sizeof(*block) + block->num_bytes) {
+ drm_dbg_kms(connector->dev, "Unexpected VESA vendor block size\n");
+ return;
+ }
+
+ switch (FIELD_GET(DISPLAYID_VESA_MSO_MODE, vesa->mso)) {
+ default:
+ drm_dbg_kms(connector->dev, "Reserved MSO mode value\n");
+ fallthrough;
+ case 0:
+ info->mso_stream_count = 0;
+ break;
+ case 1:
+ info->mso_stream_count = 2; /* 2 or 4 links */
+ break;
+ case 2:
+ info->mso_stream_count = 4; /* 4 links */
+ break;
+ }
+
+ if (!info->mso_stream_count) {
+ info->mso_pixel_overlap = 0;
+ return;
+ }
+
+ info->mso_pixel_overlap = FIELD_GET(DISPLAYID_VESA_MSO_OVERLAP, vesa->mso);
+ if (info->mso_pixel_overlap > 8) {
+ drm_dbg_kms(connector->dev, "Reserved MSO pixel overlap value %u\n",
+ info->mso_pixel_overlap);
+ info->mso_pixel_overlap = 8;
+ }
+
+ drm_dbg_kms(connector->dev, "MSO stream count %u, pixel overlap %u\n",
+ info->mso_stream_count, info->mso_pixel_overlap);
+}
+
+static void drm_update_mso(struct drm_connector *connector, const struct edid *edid)
+{
+ const struct displayid_block *block;
+ struct displayid_iter iter;
+
+ displayid_iter_edid_begin(edid, &iter);
+ displayid_iter_for_each(block, &iter) {
+ if (block->tag == DATA_BLOCK_2_VENDOR_SPECIFIC)
+ drm_parse_vesa_mso_data(connector, block);
+ }
+ displayid_iter_end(&iter);
+}
+
/* A connector has no EDID information, so we've got no EDID to compute quirks from. Reset
* all of the values which would have been set from EDID
*/
@@ -5245,6 +5308,9 @@ drm_reset_display_info(struct drm_connector *connector)
info->non_desktop = 0;
memset(&info->monitor_range, 0, sizeof(info->monitor_range));
+
+ info->mso_stream_count = 0;
+ info->mso_pixel_overlap = 0;
}
u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edid)
@@ -5323,6 +5389,9 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi
info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422)
info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;
+
+ drm_update_mso(connector, edid);
+
return quirks;
}