diff --git a/src/common/modeset/timing/nvt_dsc_pps.c b/src/common/modeset/timing/nvt_dsc_pps.c index 4ed6c25a4..2ee862738 100644 --- a/src/common/modeset/timing/nvt_dsc_pps.c +++ b/src/common/modeset/timing/nvt_dsc_pps.c @@ -1010,7 +1010,7 @@ DSC_PpsCalcBase } else { - RANGE_CHECK("pic_width", in->pic_width, 32, 5120); + RANGE_CHECK("pic_width", in->pic_width, 32, DSC_MAX_SINGLE_HEAD_WIDTH); } } diff --git a/src/common/modeset/timing/nvt_dsc_pps.h b/src/common/modeset/timing/nvt_dsc_pps.h index bd49c1464..a13911ef8 100644 --- a/src/common/modeset/timing/nvt_dsc_pps.h +++ b/src/common/modeset/timing/nvt_dsc_pps.h @@ -34,6 +34,7 @@ /* ------------------------ Macros ----------------------------------------- */ #define DSC_MAX_PPS_SIZE_DWORD 32 +#define DSC_MAX_SINGLE_HEAD_WIDTH 5120 /* ------------------------ Datatypes -------------------------------------- */ typedef struct diff --git a/src/nvidia-modeset/include/nvkms-evo.h b/src/nvidia-modeset/include/nvkms-evo.h index 63cc8b953..bb790ae4e 100644 --- a/src/nvidia-modeset/include/nvkms-evo.h +++ b/src/nvidia-modeset/include/nvkms-evo.h @@ -196,8 +196,8 @@ NvBool nvDowngradeColorFormatAndBpc( const NvBool colorBpcSpecified, NVDpyAttributeColor *pDpyColor); -NvBool nvDPValidateModeEvo(NVDpyEvoPtr pDpyEvo, - NVHwModeTimingsEvoPtr pTimings, +NvBool nvDPValidateModeEvo(const NVDpyEvoRec *pDpyEvo, + const NVHwModeTimingsEvo *pTimings, const NvBool colorFormatSpecified, const NvBool colorBpcSpecified, NVDpyAttributeColor *pDpyColor, @@ -435,6 +435,9 @@ NvBool nvEvoGetSingleMergeHeadSectionHwModeTimings( NvBool nvEvoUse2Heads1OR(const NVDpyEvoRec *pDpyEvo, const NVHwModeTimingsEvo *pTimings, + const NVDpyAttributeColor *pDpyColor, + const NvBool colorFormatSpecified, + const NvBool colorBpcSpecified, const struct NvKmsModeValidationParams *pParams); NvU32 nvGetRefreshRate10kHz(const NVHwModeTimingsEvo *pTimings); diff --git a/src/nvidia-modeset/src/nvkms-evo.c b/src/nvidia-modeset/src/nvkms-evo.c index 600003f0a..3b1cf25b8 100644 --- a/src/nvidia-modeset/src/nvkms-evo.c +++ b/src/nvidia-modeset/src/nvkms-evo.c @@ -7032,8 +7032,8 @@ NvBool nvDowngradeColorFormatAndBpc( * the given mode timings. */ -NvBool nvDPValidateModeEvo(NVDpyEvoPtr pDpyEvo, - NVHwModeTimingsEvoPtr pTimings, +NvBool nvDPValidateModeEvo(const NVDpyEvoRec *pDpyEvo, + const NVHwModeTimingsEvo *pTimings, const NvBool colorFormatSpecified, const NvBool colorBpcSpecified, NVDpyAttributeColor *pDpyColor, @@ -9813,6 +9813,9 @@ NvBool nvEvoGetSingleMergeHeadSectionHwModeTimings( NvBool nvEvoUse2Heads1OR(const NVDpyEvoRec *pDpyEvo, const NVHwModeTimingsEvo *pTimings, + const NVDpyAttributeColor *pDpyColor, + const NvBool colorFormatSpecified, + const NvBool colorBpcSpecified, const struct NvKmsModeValidationParams *pParams) { const NVDispEvoRec *pDispEvo = pDpyEvo->pDispEvo; @@ -9846,9 +9849,29 @@ NvBool nvEvoUse2Heads1OR(const NVDpyEvoRec *pDpyEvo, return FALSE; } - /* Use 2Heads1OR mode only if the required pixel clock is greater than the - * maximum pixel clock support by a head. */ - return (pTimings->pixelClock > pHeadCaps->maxPClkKHz); + if (pTimings->pixelClock > pHeadCaps->maxPClkKHz) { + return TRUE; + } + + if (!nvDpyUsesDPLib(pDpyEvo) || + (pParams->dscMode == NVKMS_DSC_MODE_FORCE_DISABLE) || + (pTimings->yuv420Mode == NV_YUV420_MODE_HW) || + (nvEvoVisibleWidth(pTimings) <= DSC_MAX_SINGLE_HEAD_WIDTH)) { + return FALSE; + } + + /* + * A wide DSC picture needs two heads even when its pixel clock fits one. + * Preserve single-head modes that can already pass DP validation, + * including its existing uncompressed color-depth fallbacks. + */ + NVDpyAttributeColor dpyColor = *pDpyColor; + + return !nvDPValidateModeEvo(pDpyEvo, pTimings, + colorFormatSpecified, + colorBpcSpecified, + &dpyColor, FALSE /* b2Heads1Or */, + NULL /* pDscInfo */, pParams); } NvBool nvIsLockGroupFlipLocked(const NVLockGroup *pLockGroup) diff --git a/src/nvidia-modeset/src/nvkms-modepool.c b/src/nvidia-modeset/src/nvkms-modepool.c index 59dfd370d..6b42ee542 100644 --- a/src/nvidia-modeset/src/nvkms-modepool.c +++ b/src/nvidia-modeset/src/nvkms-modepool.c @@ -1721,7 +1721,10 @@ static NvBool ValidateMode(NVDpyEvoPtr pDpyEvo, goto done; } - b2Heads1Or = nvEvoUse2Heads1OR(pDpyEvo, pTimingsEvo, pParams); + b2Heads1Or = nvEvoUse2Heads1OR(pDpyEvo, pTimingsEvo, &dpyColor, + pDpyOutputColorParams->formatSpecified, + pDpyOutputColorParams->bpcSpecified, + pParams); if (nvDpyIsHdmiEvo(pDpyEvo)) { NvBool foundFrlConfig = FALSE; diff --git a/src/nvidia-modeset/src/nvkms-modeset.c b/src/nvidia-modeset/src/nvkms-modeset.c index f51f97bcf..d3809ca16 100644 --- a/src/nvidia-modeset/src/nvkms-modeset.c +++ b/src/nvidia-modeset/src/nvkms-modeset.c @@ -831,6 +831,9 @@ static NvBool AssignProposedHwHeadsGeneric( if (!nvEvoUse2Heads1OR( pDpyEvo, &pProposedApiHead->timings, + &pProposedApiHead->attributes.color, + pProposedApiHead->colorFormatSpecified, + pProposedApiHead->colorBpcSpecified, &pProposedApiHead->modeValidationParams)) { continue; } @@ -840,6 +843,9 @@ static NvBool AssignProposedHwHeadsGeneric( nvAssert(!nvEvoUse2Heads1OR( pDpyEvo, &pProposedApiHead->timings, + &pProposedApiHead->attributes.color, + pProposedApiHead->colorFormatSpecified, + pProposedApiHead->colorBpcSpecified, &pProposedApiHead->modeValidationParams)); NvU32 foundHead = GetFreeHeads(pDevEvo, apiHead, pDpyEvo, @@ -908,6 +914,9 @@ void ClearIncompatibleHwHeadsMaskOneDisp(const NVDispEvoRec *pDispEvo, const NvBool new2Heads1OrState = nvEvoUse2Heads1OR(pDpyEvo, &pProposedApiHead->timings, + &pProposedApiHead->attributes.color, + pProposedApiHead->colorFormatSpecified, + pProposedApiHead->colorBpcSpecified, &pProposedApiHead->modeValidationParams); if (new2Heads1OrState != current2Heads1OrState) {