mirror of
https://github.com/NVIDIA/open-gpu-kernel-modules.git
synced 2026-01-30 13:09:47 +00:00
763 lines
32 KiB
C++
763 lines
32 KiB
C++
/*
|
|
* SPDX-FileCopyrightText: Copyright (c) 1993-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
/******************************* DisplayPort *******************************\
|
|
* *
|
|
* Module: dp_wardatabase.cpp *
|
|
* EDID and OUI based workarounds for panel/TCON issues *
|
|
* *
|
|
\***************************************************************************/
|
|
#include "dp_wardatabase.h"
|
|
#include "dp_edid.h"
|
|
#include "dp_connectorimpl.h"
|
|
#include "dp_connectorimpl2x.h"
|
|
#include "dp_printf.h"
|
|
|
|
using namespace DisplayPort;
|
|
|
|
void ConnectorImpl::applyOuiWARs()
|
|
{
|
|
switch (ouiId)
|
|
{
|
|
// Megachips Mystique
|
|
case 0xE18000:
|
|
if (((modelName[0] == 'D') && (modelName[1] == 'p') && (modelName[2] == '1') &&
|
|
(modelName[3] == '.') && (modelName[4] == '1')))
|
|
{
|
|
//
|
|
// Mystique based link box for HTC Vive has a peculiar behaviour
|
|
// of sending a link retraining pulse if the link is powered down in the absence
|
|
// of an active stream. Bug# 1793084. Set the flag so that link is not powered down.
|
|
//
|
|
bKeepOptLinkAlive = true;
|
|
}
|
|
|
|
if (((modelName[0] == 'D') && (modelName[1] == 'p') && (modelName[2] == '1') &&
|
|
(modelName[3] == '.') && (modelName[4] == '2')))
|
|
{
|
|
//
|
|
// ASUS monitor loses link sometimes during assessing link or link training.
|
|
// So if we retrain link by lowering config from HBR2 to HBR we see black screen
|
|
// Set the flag so that we first retry link training with same link config
|
|
// before following link training fallback. Bug #1846925
|
|
//
|
|
bNoFallbackInPostLQA = true;
|
|
}
|
|
break;
|
|
|
|
// Synaptics
|
|
case 0x24CC90:
|
|
if ((modelName[0] == 'S') && (modelName[1] == 'Y') && (modelName[2] == 'N') &&
|
|
(modelName[3] == 'A') && (((modelName[4] == 'S') &&
|
|
((modelName[5] == '1') || (modelName[5] == '2') ||
|
|
(modelName[5] == '3') || (modelName[5] == '#') ||
|
|
(modelName[5] == '\"')))||((modelName[4] == 0x84) &&
|
|
(modelName[5] == '0'))))
|
|
{
|
|
//
|
|
// Extended latency from link-train end to FEC enable pattern
|
|
// to avoid link lost or blank screen with Synaptics branch.
|
|
//
|
|
LT2FecLatencyMs = 57;
|
|
|
|
if (bDscMstCapBug3143315)
|
|
{
|
|
//
|
|
// Synaptics branch device doesn't support Virtual Peer Devices so DSC
|
|
// capability of downstream device should be decided based on device's own
|
|
// and its parent's DSC capability
|
|
//
|
|
bDscCapBasedOnParent = true;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ConnectorImpl2x::applyOuiWARs()
|
|
{
|
|
switch (ouiId)
|
|
{
|
|
// Novatek Microelectronics Corp.
|
|
case 0x11EC38:
|
|
if((modelName[0] == 'N') && (modelName[1] == 'T') && (modelName[2] == '6'))
|
|
{
|
|
NvU8 portType;
|
|
if (hal->getSupportsMultistream() &&
|
|
hal->isDp2xChannelCodingCapable() &&
|
|
!hal->getDownstreamPort(&portType))
|
|
{
|
|
bMstTimeslotBug4968411 = true;
|
|
hal->setMainLinkChannelCoding(ChannelCoding128B132B);
|
|
}
|
|
}
|
|
break;
|
|
case 0xAD6000:
|
|
if ((modelName[0] == 'M') &&
|
|
(modelName[1] == 'C') &&
|
|
(modelName[2] == '2') &&
|
|
(modelName[3] == '9') &&
|
|
(modelName[4] == '0'))
|
|
{
|
|
bForceHeadShutdownPerMonitor = true;
|
|
bApplyStuffDummySymbolsWAR = true;
|
|
bStuffDummySymbolsFor128b132b = false;
|
|
bStuffDummySymbolsFor8b10b = true;
|
|
}
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
void Edid::applyEdidWorkArounds(NvU32 warFlag, const DpMonitorDenylistData *pDenylistData)
|
|
{
|
|
unsigned ManufacturerID = this->getManufId();
|
|
unsigned ProductID = this->getProductId();
|
|
unsigned YearWeek = this->getYearWeek();
|
|
|
|
//
|
|
// Work around EDID problems, using manufacturer, product ID, and date of manufacture,
|
|
// to identify each case.
|
|
//
|
|
switch (ManufacturerID)
|
|
{
|
|
// Apple
|
|
case 0x1006:
|
|
if (0x9227 == ProductID)
|
|
{
|
|
this->WARFlags.powerOnBeforeLt = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> WAR for Apple thunderbolt J29 panel");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> - Monitor needs to be powered up before LT. Bug 933051");
|
|
}
|
|
break;
|
|
|
|
// Acer
|
|
case 0x7204:
|
|
// Bug 451868: Acer AL1512 monitor has a wrong extension count:
|
|
if(0xad15 == ProductID && YearWeek <= 0x0d01)
|
|
{
|
|
// clear the extension count
|
|
buffer.data[0x7E] = 0;
|
|
this->WARFlags.extensionCountDisabled = true;
|
|
this->WARFlags.dataForced = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Edid override on Acer AL1512");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> - Disabling extension count.Bug 451868");
|
|
}
|
|
break;
|
|
|
|
// Westinghouse
|
|
case 0x855C:
|
|
|
|
// Westinghouse 37" 1080p TV. LVM-37w3 (Port DVI1 EDID).
|
|
// Westinghouse 42" 1080p TV. LVM-42w2 (Port DVI1 EDID).
|
|
if (ProductID == 0x3703 || ProductID == 0x4202)
|
|
{
|
|
// Claims HDMI support, but audio causes picture corruption.
|
|
// Removing HDMI extension block
|
|
|
|
if (buffer.getLength() > 0x80 &&
|
|
buffer.data[0x7E] == 1 && // extension block present
|
|
buffer.data[0x80] == 0x02 && // CEA block
|
|
buffer.data[0x81] == 0x03 && // revision 3
|
|
!(buffer.data[0x83] & 0x40)) // No basic audio, must not be the HDMI port
|
|
{
|
|
// clear the extension count
|
|
buffer.data[0x7E] = 0;
|
|
this->WARFlags.extensionCountDisabled = true;
|
|
this->WARFlags.dataForced = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Edid overrid on Westinghouse AL1512 LVM- <37/42> w <2/3>");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> - Disabling extension count.");
|
|
}
|
|
}
|
|
break;
|
|
|
|
// IBM
|
|
case 0x4D24:
|
|
if(ProductID == 0x1A03)
|
|
{
|
|
// 2001 Week 50
|
|
if (YearWeek == 0x0B32)
|
|
{
|
|
// Override IBM T210. IBM T210 reports 2048x1536x60Hz in the edid but it's
|
|
// actually 2048x1536x40Hz. See bug 76347. This hack was, earlier, in disp driver
|
|
// Now it's being moved down to keep all overrides in same place.
|
|
// This hack was also preventing disp driver from comparing entire edid when
|
|
// trying to figure out whether or not the edid for some device has changed.
|
|
buffer.data[0x36] = 0x32;
|
|
buffer.data[0x37] = 0x3E;
|
|
this->WARFlags.dataForced = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Edid overrid on IBM T210");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> 2048x1536x60Hz(misreported) -> 2048x1536x40Hz. Bug 76347");
|
|
}
|
|
}
|
|
break;
|
|
// GWY (Gateway) or EMA (eMachines)
|
|
case 0xF91E: // GWY
|
|
case 0xA115: // EMA
|
|
// Some Gateway monitors present the eMachines mfg code, so these two cases are combined.
|
|
// Future fixes may require the two cases to be separated.
|
|
// Fix for Bug 343870. NOTE: Problem found on G80; fix applied to all GPUs.
|
|
if ((ProductID >= 0x0776 ) && (ProductID <= 0x0779)) // Product id's range from decimal 1910 to 1913
|
|
{
|
|
// if detailed pixel clock frequency = 106.50MHz
|
|
if ((buffer.data[0x36] == 0x9A) &&
|
|
(buffer.data[0x37] == 0x29) )
|
|
{
|
|
// then change detailed pixel clock frequency to 106.54MHz to fix bug 343870
|
|
buffer.data[0x36] = 0x9E;
|
|
buffer.data[0x37] = 0x29;
|
|
this->WARFlags.dataForced = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Edid overrid on GWY/EMA");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> 106.50MHz(misreported) -> 106.50MHz.Bug 343870");
|
|
}
|
|
}
|
|
break;
|
|
|
|
// INX
|
|
case 0x2C0C:
|
|
// INX L15CX monitor has an invalid detailed timing 10x311 @ 78Hz.
|
|
if( ProductID == 0x1502)
|
|
{
|
|
// remove detailed timing #4: zero out the first 3 bytes of DTD#4 block
|
|
buffer.data[0x6c] = 0x0;
|
|
buffer.data[0x6d] = 0x0;
|
|
buffer.data[0x6e] = 0x0;
|
|
this->WARFlags.dataForced = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Edid overrid on INX L15CX");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Removing invalid detailed timing 10x311 @ 78Hz");
|
|
}
|
|
break;
|
|
|
|
// AUO
|
|
case 0xAF06:
|
|
if ((ProductID == 0x103C) || (ProductID == 0x113C))
|
|
{
|
|
//
|
|
// Acer have faulty AUO eDP panels which have
|
|
// wrong HBlank in the EDID. Correcting it here.
|
|
//
|
|
buffer.data[0x39] = 0x4B; // new hblank width: 75
|
|
buffer.data[0x3F] = 0x1B; // new hsync pulse width: 27
|
|
this->WARFlags.dataForced = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Edid overrid on AUO eDP panel");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Modifying HBlank and HSync pulse width.");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Bugs 907998, 1001160");
|
|
}
|
|
else if (ProductID == 0x109B || ProductID == 0x119B)
|
|
{
|
|
this->WARFlags.useLegacyAddress = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> AUO eDP");
|
|
DP_PRINTF(DP_NOTICE, "implements only Legacy interrupt address range");
|
|
|
|
// Bug 1792962 - Panel got glitch on D3 write, apply this WAR.
|
|
this->WARFlags.disableDpcdPowerOff = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Disable DPCD Power Off");
|
|
}
|
|
break;
|
|
|
|
// LPL
|
|
case 0x0C32:
|
|
if (ProductID == 0x0000)
|
|
{
|
|
//
|
|
// Patch EDID for Quanta - Toshiba LG 1440x900 panel. See Bug 201428
|
|
// Must 1st verify that we have that panel. It has MFG id 32, 0C
|
|
// BUT product ID for this (and other different LG panels) are 0000.
|
|
// So verify that the last "Custom Timing" area of the EDID has
|
|
// a "Monitor Description" of type FE = "ASCII Data String" which
|
|
// has this panel's name = "LP171WX2-A4K5".
|
|
//
|
|
if ((buffer.data[0x71] == 0x4C) &&
|
|
(buffer.data[0x72] == 0x50) &&
|
|
(buffer.data[0x73] == 0x31) &&
|
|
(buffer.data[0x74] == 0x37) &&
|
|
(buffer.data[0x75] == 0x31) &&
|
|
(buffer.data[0x76] == 0x57) &&
|
|
(buffer.data[0x77] == 0x58) &&
|
|
(buffer.data[0x78] == 0x32) &&
|
|
(buffer.data[0x79] == 0x2D) &&
|
|
(buffer.data[0x7A] == 0x41) &&
|
|
(buffer.data[0x7B] == 0x34) &&
|
|
(buffer.data[0x7C] == 0x4B) &&
|
|
(buffer.data[0x7D] == 0x35) )
|
|
{
|
|
//
|
|
// Was 0x95, 0x25 = -> 0x2595 = 9621 or 96.21 Mhz.
|
|
// 96,210,000 / 1760 / 912 = 59.939 Hz
|
|
// Want 60 * 1760 * 912 ~= 9631 or 96.31 MHz
|
|
// 9631 = 0x259F -> 0x9F 0x25.
|
|
// So, change byte 36 from 0x95 to 0x9F.
|
|
//
|
|
buffer.data[0x36] = 0x9F;
|
|
this->WARFlags.dataForced = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Edid overrid on Quanta - Toshiba LG 1440x900");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Correcting pclk. Bug 201428");
|
|
}
|
|
}
|
|
else
|
|
if (ProductID == 0xE300)
|
|
{
|
|
//
|
|
// Patch EDID for MSI - LG LPL 1280x800 panel. See Bug 359313
|
|
// Must 1st verify that we have that panel. It has MFG id 32, 0C
|
|
// BUT product ID for this (and other different LG panels) are E300.
|
|
// So verify that the last "Custom Timing" area of the EDID has
|
|
// a "Monitor Description" of type FE = "ASCII Data String" which
|
|
// has this panel's name = "LP154WX4-TLC3".
|
|
//
|
|
if ((buffer.data[0x71] == 0x4C) &&
|
|
(buffer.data[0x72] == 0x50) &&
|
|
(buffer.data[0x73] == 0x31) &&
|
|
(buffer.data[0x74] == 0x35) &&
|
|
(buffer.data[0x75] == 0x34) &&
|
|
(buffer.data[0x76] == 0x57) &&
|
|
(buffer.data[0x77] == 0x58) &&
|
|
(buffer.data[0x78] == 0x34) &&
|
|
(buffer.data[0x79] == 0x2D) &&
|
|
(buffer.data[0x7A] == 0x54) &&
|
|
(buffer.data[0x7B] == 0x4C) &&
|
|
(buffer.data[0x7C] == 0x43) &&
|
|
(buffer.data[0x7D] == 0x33) )
|
|
{
|
|
//
|
|
// Was 0xBC, 0x1B = -> 0x1BBC = 7100 or 71.00 Mhz.
|
|
// 71,000,000 / 1488 / 826 = 59.939 Hz
|
|
// Want 60 * 1488 * 826 ~= 7111 or 71.11 MHz
|
|
// 7111 = 0x1BC7 -> 0xC7 0x1B.
|
|
// So, change byte 36 from 0xBC to 0xC7.
|
|
//
|
|
buffer.data[0x36] = 0xC7;
|
|
this->WARFlags.dataForced = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Edid overrid on MSI - LG LPL 1280x800");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Correcting pclk. Bug 359313");
|
|
}
|
|
}
|
|
break;
|
|
|
|
// SKY
|
|
case 0x794D:
|
|
if (ProductID == 0x9880)
|
|
{
|
|
//
|
|
// Override for Haier TV to remove resolution
|
|
// 1366x768 from EDID data. Refer bug 351680 & 327891
|
|
// Overriding 18 bytes from offset 0x36.
|
|
//
|
|
buffer.data[0x36] = 0x01;
|
|
buffer.data[0x37] = 0x1D;
|
|
buffer.data[0x38] = 0x00;
|
|
buffer.data[0x39] = 0x72;
|
|
buffer.data[0x3A] = 0x51;
|
|
buffer.data[0x3B] = 0xD0;
|
|
buffer.data[0x3C] = 0x1E;
|
|
buffer.data[0x3D] = 0x20;
|
|
buffer.data[0x3E] = 0x6E;
|
|
buffer.data[0x3F] = 0x28;
|
|
buffer.data[0x40] = 0x55;
|
|
buffer.data[0x41] = 0x00;
|
|
buffer.data[0x42] = 0xC4;
|
|
buffer.data[0x43] = 0x8E;
|
|
buffer.data[0x44] = 0x21;
|
|
buffer.data[0x45] = 0x00;
|
|
buffer.data[0x46] = 0x00;
|
|
buffer.data[0x47] = 0x1E;
|
|
|
|
this->WARFlags.dataForced = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Edid overrid on Haier TV.");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Removing 1366x768. bug 351680 & 327891");
|
|
|
|
}
|
|
break;
|
|
// HP
|
|
case 0xF022:
|
|
switch (ProductID)
|
|
{
|
|
case 0x192F:
|
|
//
|
|
// WAR for bug 1643712 - Issue specific to HP Z1 G2 (Zeus) All-In-One
|
|
// Putting the Rx in power save mode before BL_EN is deasserted, makes this specific sink unhappy
|
|
// Bug 1559465 will address the right power down sequence. We need to revisit this WAR once Bug 1559465 is fixed.
|
|
//
|
|
this->WARFlags.disableDpcdPowerOff = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Disable DPCD Power Off");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> HP Z1 G2 (Zeus) AIO Bug 1643712");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
// Sharp
|
|
case 0x104d:
|
|
switch (ProductID)
|
|
{
|
|
case 0x141c: // HP Valor QHD+ N15P-Q3 Sharp EDP
|
|
//
|
|
// HP Valor QHD+ N15P-Q3 EDP needs 50 ms delay
|
|
// after D3 to avoid black screen issues.
|
|
//
|
|
this->WARFlags.delayAfterD3 = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> HP Valor QHD+ N15P-Q3 Sharp EDP needs 50 ms after D3");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> bug 1520011");
|
|
break;
|
|
|
|
//Sharp EDPs that declares DP1.2 but doesn't implement ESI address space
|
|
case 0x1414:
|
|
case 0x1430:
|
|
case 0x1445:
|
|
case 0x1446:
|
|
case 0x144C:
|
|
case 0x1450:
|
|
case 0x1467:
|
|
case 0x145e:
|
|
//
|
|
// Use Legacy address space for DP1.2 panel
|
|
//
|
|
this->WARFlags.useLegacyAddress = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Sharp EDP implements only Legacy interrupt address range");
|
|
break;
|
|
|
|
case 0x143B:
|
|
//
|
|
// Bug 200113041
|
|
// Need to be unique to identify this Sharp panel. Besides
|
|
// manufacturer ID and ProductID, we have to add the mode
|
|
// name to make this happen as LQ156D1JW05 in ASCII.
|
|
//
|
|
if ((buffer.data[0x71] == 0x4C) &&
|
|
(buffer.data[0x72] == 0x51) &&
|
|
(buffer.data[0x73] == 0x31) &&
|
|
(buffer.data[0x74] == 0x35) &&
|
|
(buffer.data[0x75] == 0x36) &&
|
|
(buffer.data[0x76] == 0x44) &&
|
|
(buffer.data[0x77] == 0x31) &&
|
|
(buffer.data[0x78] == 0x4A) &&
|
|
(buffer.data[0x79] == 0x57) &&
|
|
(buffer.data[0x7A] == 0x30) &&
|
|
(buffer.data[0x7B] == 0x35) &&
|
|
(buffer.data[0x7C] == 0x0A) &&
|
|
(buffer.data[0x7D] == 0x20))
|
|
{
|
|
this->WARFlags.useLegacyAddress = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Sharp EDP implements only Legacy interrupt address range");
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
|
|
// EIZO
|
|
case 0xc315:
|
|
if (ProductID == 0x2227)
|
|
{
|
|
//
|
|
// The EIZO FlexScan SX2762W generates a redundant long HPD
|
|
// pulse after a modeset, which triggers another modeset on GPUs
|
|
// without flush mode, triggering an infinite link training
|
|
// loop.
|
|
//
|
|
this->WARFlags.ignoreRedundantHotplug = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> EIZO FlexScan SX2762W generates redundant");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> hotplugs (bug 1048796)");
|
|
break;
|
|
}
|
|
break;
|
|
|
|
// MEI-Panasonic
|
|
case 0xa934:
|
|
if (ProductID == 0x96a2)
|
|
{
|
|
//
|
|
// Bug 200113041
|
|
// Need to be unique to identify this MEI-Panasonic panel.
|
|
// Besides manufacturer ID and ProductID, we have to add the
|
|
// model name to make this happen as VVX17P051J00^ in ASCII.
|
|
//
|
|
if ((buffer.data[0x71] == 0x56) &&
|
|
(buffer.data[0x72] == 0x56) &&
|
|
(buffer.data[0x73] == 0x58) &&
|
|
(buffer.data[0x74] == 0x31) &&
|
|
(buffer.data[0x75] == 0x37) &&
|
|
(buffer.data[0x76] == 0x50) &&
|
|
(buffer.data[0x77] == 0x30) &&
|
|
(buffer.data[0x78] == 0x35) &&
|
|
(buffer.data[0x79] == 0x31) &&
|
|
(buffer.data[0x7A] == 0x4A) &&
|
|
(buffer.data[0x7B] == 0x30) &&
|
|
(buffer.data[0x7C] == 0x30) &&
|
|
(buffer.data[0x7D] == 0x0A))
|
|
{
|
|
this->WARFlags.useLegacyAddress = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> MEI-Panasonic EDP");
|
|
DP_PRINTF(DP_NOTICE, "implements only Legacy interrupt address range");
|
|
}
|
|
}
|
|
break;
|
|
|
|
// LG
|
|
case 0xE430:
|
|
switch (ProductID)
|
|
{
|
|
case 0x0469:
|
|
{
|
|
//
|
|
// The LG display can't be driven at FHD with 2*RBR.
|
|
// Force max link config
|
|
//
|
|
this->WARFlags.forceMaxLinkConfig = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Force maximum link config WAR required on LG panel.");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> bug 1649626");
|
|
break;
|
|
}
|
|
case 0x06DB:
|
|
{
|
|
this->WARFlags.useLegacyAddress = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> LG eDP implements only Legacy interrupt address range");
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case 0x8F34:
|
|
if (ProductID == 0xAA55)
|
|
{
|
|
this->WARFlags.forceMaxLinkConfig = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Force maximum link config WAR required on Sharp-CerebrEx panel.");
|
|
}
|
|
break;
|
|
|
|
// CMN
|
|
case 0xAE0D:
|
|
if (ProductID == 0x1747)
|
|
{
|
|
this->WARFlags.useLegacyAddress = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> CMN eDP");
|
|
DP_PRINTF(DP_NOTICE, "implements only Legacy interrupt address range");
|
|
}
|
|
break;
|
|
|
|
// BenQ
|
|
case 0xD109:
|
|
if ((ProductID == 0x7F2B) || (ProductID == 0x7F2F))
|
|
{
|
|
this->WARFlags.ignoreRedundantHotplug = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> BenQ GSync power on/off redundant hotplug");
|
|
}
|
|
break;
|
|
|
|
// MSI
|
|
case 0x834C:
|
|
if (ProductID == 0x4C48)
|
|
{
|
|
this->WARFlags.useLegacyAddress = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> MSI eDP\n");
|
|
DP_PRINTF(DP_NOTICE, "implements only Legacy interrupt address range\n");
|
|
}
|
|
break;
|
|
|
|
// Unigraf
|
|
case 0xC754:
|
|
case 0x1863:
|
|
{
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Unigraf device, keep link alive during detection\n");
|
|
this->WARFlags.keepLinkAlive = true;
|
|
}
|
|
break;
|
|
|
|
// BOE
|
|
case 0xE509:
|
|
if ((ProductID == 0x977) || (ProductID == 0x974) || (ProductID == 0x9D9))
|
|
{
|
|
this->WARFlags.bIgnoreDscCap = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> BOE panels incorrectly exposing DSC capability. Ignoring it.");
|
|
}
|
|
break;
|
|
|
|
// NCP
|
|
case 0x7038:
|
|
if (ProductID == 0x005F)
|
|
{
|
|
this->WARFlags.bIgnoreDscCap = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> NCP panels incorrectly exposing DSC capability. Ignoring it.");
|
|
}
|
|
break;
|
|
|
|
//
|
|
// This panel advertise DSC capabilities, but panel doesn't support DSC
|
|
// So ignoring DSC capability on this panel
|
|
//
|
|
case 0x6F0E:
|
|
if (ProductID == 0x1609)
|
|
{
|
|
this->WARFlags.bIgnoreDscCap = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Ignoring DSC capability on Lenovo CSOT 1609 Panel.");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Bug 3444252");
|
|
}
|
|
break;
|
|
|
|
// Asus
|
|
case 0x6D1E:
|
|
if (ProductID == 0x7707)
|
|
{
|
|
this->WARFlags.bIgnoreDscCap = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Panel incorrectly exposing DSC capability. Ignoring it.");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Bug 3543158");
|
|
}
|
|
else if (ProductID == 0x5B9A)
|
|
{
|
|
this->WARFlags.bDisableDscMaxBppLimit = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Disable DSC max BPP limit of 16 for DSC.");
|
|
}
|
|
else if (ProductID == 0x5CA7 || ProductID == 0x9E9D || ProductID == 0x9EA0 || ProductID == 0x9EA5 || ProductID == 0x5CB7 ||
|
|
ProductID == 0x9EA8 || ProductID == 0x9EAF || ProductID == 0x7846 || ProductID == 0x7849 || ProductID == 0x5CB5 ||
|
|
ProductID == 0x77E0 || ProductID == 0x9EB9)
|
|
{
|
|
this->WARFlags.bForceHeadShutdownOnModeTransition = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Force head shutdown on Mode transition.");
|
|
}
|
|
break;
|
|
case 0xB306:
|
|
if (ProductID == 0x3228)
|
|
{
|
|
// ASUS PG32UQXR does not set DPCD 0x2217 to reflect correct CableID.
|
|
this->WARFlags.bSkipCableIdCheck = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Panel does not expose cable capability. Ignoring it. Bug 4968411");
|
|
}
|
|
else if(ProductID == 0x24b5 || ProductID == 0x32f2 || ProductID == 0x27BC)
|
|
{
|
|
//
|
|
// Asus ROG PG248QP (0x24b5) Bug 5100062
|
|
// Asus ROG PG32UCDM (0x32f2) Bug 5088957
|
|
// Asus ROG PG27AQN (0x27BC) Bug 5300665
|
|
|
|
this->WARFlags.bForceHeadShutdown = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Force head shutdown.");
|
|
}
|
|
break;
|
|
|
|
// Samsung
|
|
case 0x2D4C:
|
|
if (ProductID == 0x7474)
|
|
{
|
|
//
|
|
// Samsung Odyssey Neo 57 G9 needs manual allocation of timeslots when directly connected to upstream source
|
|
// Do not allocate manual timeslot when under a separate branch. This is checked with branch OUI.
|
|
//
|
|
this->WARFlags.bAllocateManualTimeslots = true;
|
|
this->WARFlags.bDP2XPreferNonDSCForLowPClk = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Panel needs allocation of manual timeslot. Bug 4958974");
|
|
}
|
|
if (ProductID == 0x7256)
|
|
{
|
|
this->WARFlags.bDisableDownspread = true;
|
|
}
|
|
break;
|
|
case 0x545A: // VRT Varjo XR3
|
|
if (ProductID == 0x5841 || ProductID == 0x5842 || ProductID == 0x5843)
|
|
{
|
|
this->WARFlags.bDisableDownspread = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> VRT monitor does not work with GB20x when downspread is enabled. Disabling downspread.");
|
|
}
|
|
break;
|
|
|
|
case 0xD94D: // Sony
|
|
if (ProductID == 0x07EE) // Sony SDM27Q10S
|
|
{
|
|
this->WARFlags.bSkipResetMSTMBeforeLt = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Sony SDM27Q10S needs to skip reset MST_EN before LT");
|
|
}
|
|
break;
|
|
case 0xAC10:
|
|
switch (ProductID)
|
|
{
|
|
case 0x42AD:
|
|
case 0x42AC:
|
|
this->WARFlags.bApplyStuffDummySymbolsWAR = true;
|
|
this->WARData.bStuffDummySymbolsFor128b132b = true;
|
|
this->WARData.bStuffDummySymbolsFor8b10b = false;
|
|
break;
|
|
case 0xA21F:
|
|
this->WARFlags.bForceHeadShutdown = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Force head shutdown for Dell AW2524H.");
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// Find out if the monitor needs a WAR to applied.
|
|
if (warFlag)
|
|
{
|
|
if (warFlag & DP_MONITOR_CAPABILITY_DP_SKIP_REDUNDANT_LT)
|
|
{
|
|
this->WARFlags.skipRedundantLt = true;
|
|
}
|
|
|
|
if (warFlag & DP_MONITOR_CAPABILITY_DP_SKIP_CABLE_BW_CHECK)
|
|
{
|
|
this->WARFlags.skipCableBWCheck = true;
|
|
this->WARData.maxLaneAtHighRate = pDenylistData->dpSkipCheckLink.maxLaneAtHighRate;
|
|
this->WARData.maxLaneAtLowRate = pDenylistData->dpSkipCheckLink.maxLaneAtLowRate;
|
|
}
|
|
|
|
if (warFlag & DP_MONITOR_CAPABILITY_DP_WRITE_0x600_BEFORE_LT)
|
|
{
|
|
// all HP monitors need to be powered up before link training
|
|
this->WARFlags.powerOnBeforeLt = true;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> HP monitors need to be powered up before LT");
|
|
}
|
|
|
|
if (warFlag & DP_MONITOR_CAPABILITY_DP_OVERRIDE_OPTIMAL_LINK_CONFIG)
|
|
{
|
|
//
|
|
// Instead of calculating the optimum link config
|
|
// based on timing, bpc etc. just used a default
|
|
// fixed link config for the monitor for all modes
|
|
//
|
|
this->WARFlags.overrideOptimalLinkCfg = true;
|
|
// Force the fix max LT
|
|
this->WARFlags.forceMaxLinkConfig = true;
|
|
this->WARData.optimalLinkRate = pDenylistData->dpOverrideOptimalLinkConfig.linkRate;
|
|
this->WARData.optimalLaneCount = pDenylistData->dpOverrideOptimalLinkConfig.laneCount;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Overriding optimal link config on Dell U2410.");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> bug 632801");
|
|
}
|
|
|
|
if (warFlag & DP_MONITOR_CAPABILITY_DP_OVERRIDE_MAX_LANE_COUNT)
|
|
{
|
|
//
|
|
// Some monitors claim more lanes than they actually support.
|
|
// This particular Lenovo monitos has just 2 lanes, but its DPCD says 4.
|
|
// This WAR is to override the max lane count read from DPCD.
|
|
//
|
|
this->WARFlags.overrideMaxLaneCount = true;
|
|
this->WARData.maxLaneCount = pDenylistData->dpMaxLaneCountOverride;
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> Overriding max lane count on Lenovo L2440x.");
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> bug 687952");
|
|
}
|
|
}
|
|
|
|
if (this->WARFlags.dataForced)
|
|
{
|
|
DP_PRINTF(DP_NOTICE, "DP-WAR> EDID was overridden for some data. Patching CRC.");
|
|
this->patchCrc();
|
|
}
|
|
}
|