mirror of
https://github.com/NVIDIA/open-gpu-kernel-modules.git
synced 2026-02-27 18:34:00 +00:00
525.47.07
This commit is contained in:
@@ -31,6 +31,9 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
void nvDpyProbeMaxPixelClock(NVDpyEvoPtr pDpyEvo);
|
||||
NVEvoPassiveDpDongleType nvDpyGetPassiveDpDongleType(
|
||||
const NVDpyEvoRec *pDpyEvo,
|
||||
NvU32 *passiveDpDongleMaxPclkKHz);
|
||||
void nvDpySetValidSyncsEvo(const NVDpyEvoRec *pDpyEvo,
|
||||
struct NvKmsModeValidationValidSyncs *pValidSyncs);
|
||||
NVDpyEvoPtr nvAllocDpyEvo(NVDispEvoPtr pDispEvo,
|
||||
|
||||
@@ -59,6 +59,7 @@ NvBool nvInitHdmiLibrary(NVDevEvoRec *pDevEvo);
|
||||
void nvTeardownHdmiLibrary(NVDevEvoRec *pDevEvo);
|
||||
|
||||
NvBool nvHdmiFrlAssessLink(NVDpyEvoPtr pDpyEvo);
|
||||
NvBool nvHdmiDpySupportsFrl(const NVDpyEvoRec *pDpyEvo);
|
||||
NvBool nvHdmiFrlQueryConfig(const NVDpyEvoRec *pDpyEvo,
|
||||
const NvModeTimings *pModeTimings,
|
||||
NVHwModeTimingsEvo *pTimings,
|
||||
|
||||
@@ -54,9 +54,6 @@ static void DpyGetDynamicDfpProperties(
|
||||
NVDpyEvoPtr pDpyEvo,
|
||||
const NvBool disableACPIBrightnessHotkeys);
|
||||
|
||||
static NVEvoPassiveDpDongleType
|
||||
DpyGetPassiveDpDongleType(const NVDpyEvoRec *pDpyEvo,
|
||||
NvU32 *passiveDpDongleMaxPclkKHz);
|
||||
static void
|
||||
CreateParsedEdidFromNVT_TIMING(NVT_TIMING *pTimings,
|
||||
NvU8 bpc,
|
||||
@@ -676,53 +673,37 @@ void nvDpyProbeMaxPixelClock(NVDpyEvoPtr pDpyEvo)
|
||||
nvkms_memset(&pDpyEvo->hdmi.srcCaps, 0, sizeof(pDpyEvo->hdmi.srcCaps));
|
||||
nvkms_memset(&pDpyEvo->hdmi.sinkCaps, 0, sizeof(pDpyEvo->hdmi.sinkCaps));
|
||||
|
||||
if (pDevEvo->hal->caps.supportsHDMIFRL) {
|
||||
if (nvHdmiDpySupportsFrl(pDpyEvo)) {
|
||||
/*
|
||||
* This function is called multiple times for each pDpyEvo:
|
||||
* - Once when the dpy is created
|
||||
* - Once when the dpy is connected
|
||||
* - Once when the dpy is disconnected
|
||||
* In the first and third cases, we don't yet have an EDID so
|
||||
* we don't know if the sink supports HDMI FRL. Assume it
|
||||
* doesn't, since if we try to set a mode anyway there won't be
|
||||
* a sink to do link training with.
|
||||
* An SOR needs to be assigned temporarily to do FRL training.
|
||||
*
|
||||
* Since the only other SORs in use at the moment (if any) are
|
||||
* those driving heads, we don't need to exclude RM from
|
||||
* selecting any SOR, so an sorExcludeMask of 0 is appropriate.
|
||||
*/
|
||||
if (pDpyEvo->parsedEdid.valid &&
|
||||
pDpyEvo->parsedEdid.info.hdmiForumInfo.max_FRL_Rate) {
|
||||
if (nvAssignSOREvo(pConnectorEvo, 0) &&
|
||||
nvHdmiFrlAssessLink(pDpyEvo)) {
|
||||
/*
|
||||
* An SOR needs to be assigned temporarily to do FRL
|
||||
* training.
|
||||
* Since the only other SORs in use at the moment (if any)
|
||||
* are those driving heads, we don't need to exclude RM
|
||||
* from selecting any SOR, so an sorExcludeMask of 0 is
|
||||
* appropriate.
|
||||
* Note that although we "assessed" the link above, the
|
||||
* maximum pixel clock set here doesn't take that into
|
||||
* account -- it's the maximum the GPU hardware is capable
|
||||
* of on the most capable link, mostly for reporting
|
||||
* purposes.
|
||||
*
|
||||
* The calculation for if a given mode can fit in the
|
||||
* assessed FRL configuration is complex and depends on
|
||||
* things like the amount of blanking, rather than a simple
|
||||
* pclk cutoff. So, we query the hdmi library when
|
||||
* validating each individual mode, when we know actual
|
||||
* timings.
|
||||
*/
|
||||
if (nvAssignSOREvo(pConnectorEvo, 0)) {
|
||||
if (nvHdmiFrlAssessLink(pDpyEvo)) {
|
||||
|
||||
/*
|
||||
* Note that although we "assessed" the link above,
|
||||
* the maximum pixel clock set here doesn't take
|
||||
* that into account -- it's the maximum the GPU
|
||||
* hardware is capable of on the most capable link,
|
||||
* mostly for reporting purposes.
|
||||
*
|
||||
* The calculation for if a given mode can fit in
|
||||
* the assessed FRL configuration is complex and
|
||||
* depends on things like the amount of blanking,
|
||||
* rather than a simple pclk cutoff. So, we query
|
||||
* the hdmi library when validating each individual
|
||||
* mode, when we know actual timings.
|
||||
*/
|
||||
pDpyEvo->maxPixelClockKHz =
|
||||
/*
|
||||
* This comes from the Windows display driver:
|
||||
* (4 lanes * 12Gb per lane *
|
||||
* FRL encoding i.e 16/18) / 1K
|
||||
*/
|
||||
((4 * 12 * 1000 * 1000 * 16) / 18);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This comes from the Windows display driver: (4 lanes *
|
||||
* 12Gb per lane * FRL encoding i.e 16/18) / 1K
|
||||
*/
|
||||
pDpyEvo->maxPixelClockKHz =
|
||||
((4 * 12 * 1000 * 1000 * 16) / 18);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -754,8 +735,8 @@ void nvDpyProbeMaxPixelClock(NVDpyEvoPtr pDpyEvo)
|
||||
* restrictive than the one described above. Check whether one of
|
||||
* these dongles is in use, and override the limit accordingly.
|
||||
*/
|
||||
passiveDpDongleType = DpyGetPassiveDpDongleType(pDpyEvo,
|
||||
&passiveDpDongleMaxPclkKHz);
|
||||
passiveDpDongleType =
|
||||
nvDpyGetPassiveDpDongleType(pDpyEvo, &passiveDpDongleMaxPclkKHz);
|
||||
|
||||
if (passiveDpDongleType != NV_EVO_PASSIVE_DP_DONGLE_UNUSED) {
|
||||
pDpyEvo->maxPixelClockKHz = NV_MIN(passiveDpDongleMaxPclkKHz,
|
||||
@@ -832,9 +813,9 @@ static NvBool IsConnectorTMDS(NVConnectorEvoPtr pConnectorEvo)
|
||||
* Query RM for the passive Displayport dongle type; this can influence
|
||||
* the maximum pixel clock allowed on that display.
|
||||
*/
|
||||
static NVEvoPassiveDpDongleType
|
||||
DpyGetPassiveDpDongleType(const NVDpyEvoRec *pDpyEvo,
|
||||
NvU32 *passiveDpDongleMaxPclkKHz)
|
||||
NVEvoPassiveDpDongleType
|
||||
nvDpyGetPassiveDpDongleType(const NVDpyEvoRec *pDpyEvo,
|
||||
NvU32 *passiveDpDongleMaxPclkKHz)
|
||||
{
|
||||
NV0073_CTRL_DFP_GET_DISPLAYPORT_DONGLE_INFO_PARAMS params = { 0 };
|
||||
NvU32 ret;
|
||||
|
||||
@@ -1866,6 +1866,8 @@ NvBool nvHdmiFrlAssessLink(NVDpyEvoPtr pDpyEvo)
|
||||
NVHDMIPKT_RESULT ret;
|
||||
const NvU32 displayId = nvDpyIdToNvU32(pDpyEvo->pConnectorEvo->displayId);
|
||||
|
||||
nvAssert(nvDpyIsHdmiEvo(pDpyEvo));
|
||||
|
||||
/* HDMI dpys not dynamic dpy so its connector should have a dpyId. */
|
||||
nvAssert(displayId != 0);
|
||||
nvAssert(pDpyEvo->parsedEdid.valid);
|
||||
@@ -1884,33 +1886,54 @@ NvBool nvHdmiFrlAssessLink(NVDpyEvoPtr pDpyEvo)
|
||||
return pDpyEvo->hdmi.sinkCaps.linkMaxFRLRate != HDMI_FRL_DATA_RATE_NONE;
|
||||
}
|
||||
|
||||
/* Determine if HDMI FRL is needed to drive the given timings on the given dpy. */
|
||||
static NvBool TimingsNeedFRL(const NVDpyEvoRec *pDpyEvo,
|
||||
const NVHwModeTimingsEvo *pTimings)
|
||||
/*
|
||||
* Determine if the given HDMI dpy supports FRL.
|
||||
*
|
||||
* Returns TRUE if the dpy supports FRL, or FALSE otherwise.
|
||||
*/
|
||||
NvBool nvHdmiDpySupportsFrl(const NVDpyEvoRec *pDpyEvo)
|
||||
{
|
||||
NvU32 passiveDpDongleMaxPclkKHz;
|
||||
const NVDevEvoRec *pDevEvo = pDpyEvo->pDispEvo->pDevEvo;
|
||||
|
||||
/* Can't use FRL if the display hardware doesn't support it */
|
||||
nvAssert(nvDpyIsHdmiEvo(pDpyEvo));
|
||||
|
||||
/* Can't use FRL if the display hardware doesn't support it. */
|
||||
if (!pDevEvo->hal->caps.supportsHDMIFRL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Can only use FRL for HDMI devices. */
|
||||
if (!nvDpyIsHdmiEvo(pDpyEvo)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Can only use FRL if the HDMI sink supports it. */
|
||||
/* Can't use FRL if the HDMI sink doesn't support it. */
|
||||
if (!pDpyEvo->parsedEdid.valid ||
|
||||
!pDpyEvo->parsedEdid.info.hdmiForumInfo.max_FRL_Rate) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Can't use FRL if we are using a passive DP to HDMI dongle. */
|
||||
if (nvDpyGetPassiveDpDongleType(pDpyEvo, &passiveDpDongleMaxPclkKHz) !=
|
||||
NV_EVO_PASSIVE_DP_DONGLE_UNUSED) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if HDMI FRL is needed to drive timings with the given pixel clock
|
||||
* on the given dpy.
|
||||
*
|
||||
* Returns TRUE if FRL is needed, or FALSE otherwise.
|
||||
* */
|
||||
static NvBool HdmiTimingsNeedFrl(const NVDpyEvoRec *pDpyEvo,
|
||||
const NvU32 pixelClock)
|
||||
{
|
||||
nvAssert(nvDpyIsHdmiEvo(pDpyEvo));
|
||||
|
||||
/*
|
||||
* For HDMI, maxSingleLinkPixelClockKHz is the maximum non-FRL rate.
|
||||
* If the rate is higher than that, try to use FRL for the mode.
|
||||
*/
|
||||
return pTimings->pixelClock > pDpyEvo->maxSingleLinkPixelClockKHz;
|
||||
return pixelClock > pDpyEvo->maxSingleLinkPixelClockKHz;
|
||||
}
|
||||
|
||||
NvBool nvHdmiFrlQueryConfig(
|
||||
@@ -1927,10 +1950,15 @@ NvBool nvHdmiFrlQueryConfig(
|
||||
NVT_TIMING nvtTiming = { };
|
||||
NVHDMIPKT_RESULT ret;
|
||||
|
||||
if (!TimingsNeedFRL(pDpyEvo, pHwTimings)) {
|
||||
if (!nvDpyIsHdmiEvo(pDpyEvo) ||
|
||||
!HdmiTimingsNeedFrl(pDpyEvo, pHwTimings->pixelClock)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!nvHdmiDpySupportsFrl(pDpyEvo)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* See if we can find an NVT_TIMING for this mode from the EDID. */
|
||||
pNvtTiming = nvFindEdidNVT_TIMING(pDpyEvo, pModeTimings, pValidationParams);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user