
This patch adds new driver DisplayPort Transmitter Subsystem Signed-off-by: Shadul Shaikh <shaduls@xilinx.com>
1028 lines
32 KiB
C
1028 lines
32 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright (C) 2015 Xilinx, Inc. All rights reserved.
|
|
*
|
|
* 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.
|
|
*
|
|
* Use of the Software is limited solely to applications:
|
|
* (a) running on a Xilinx device, or
|
|
* (b) that interact with a Xilinx device through a bus or interconnect.
|
|
*
|
|
* 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
|
|
* XILINX 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.
|
|
*
|
|
* Except as contained in this notice, the name of the Xilinx shall not be used
|
|
* in advertising or otherwise to promote the sale, use or other dealings in
|
|
* this Software without prior written authorization from Xilinx.
|
|
*
|
|
******************************************************************************/
|
|
/*****************************************************************************/
|
|
/**
|
|
*
|
|
* @file xss_dptx.c
|
|
*
|
|
* This file contains a minimal set of functions for the DisplayPort core
|
|
* to configure in TX mode of operation.
|
|
*
|
|
* <pre>
|
|
* MODIFICATION HISTORY:
|
|
*
|
|
* Ver Who Date Changes
|
|
* ---- --- -------- --------------------------------------------------
|
|
* 1.00 sha 01/29/15 Initial release.
|
|
* </pre>
|
|
*
|
|
******************************************************************************/
|
|
|
|
/***************************** Include Files *********************************/
|
|
|
|
#include "xss_dptx.h"
|
|
#include "xvidc.h"
|
|
#include "xvidc_edid.h"
|
|
#include "xdebug.h"
|
|
#include "string.h"
|
|
|
|
/************************** Constant Definitions *****************************/
|
|
|
|
|
|
/***************** Macros (Inline Functions) Definitions *********************/
|
|
|
|
|
|
/**************************** Type Definitions *******************************/
|
|
|
|
|
|
/************************** Function Prototypes ******************************/
|
|
|
|
static u32 Dp_GetTopology(XDp *InstancePtr);
|
|
static u32 Dp_CheckBandwidth(XDp *InstancePtr, u8 Bpc,
|
|
XVidC_VideoMode VidMode);
|
|
static XVidC_VideoMode Dp_GetPreferredVm(u8 *EdidPtr);
|
|
|
|
/************************** Variable Definitions *****************************/
|
|
|
|
|
|
/************************** Function Definitions *****************************/
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
*
|
|
* This function configures DisplayPort sub-core with preferred resolution
|
|
* read from sink or user set resolution, bits per color in SST/MST mode.
|
|
* In MST mode, if sinks are more than two, it re-orders the sinks if belongs
|
|
* to same tiled display topology. It trains the link and allocates stream
|
|
* payloads for single stream (SST) or multi-stream transport mode (MST).
|
|
* In MST mode, discovers the topology and finds the actual number of sinks to
|
|
* which associates streams.
|
|
*
|
|
* @param InstancePtr is a pointer to the XDp instance.
|
|
* @param TransportMode specifies whether multiple/single steam to be
|
|
* sent over the main link.
|
|
* - TransportMode = 1 (for Multi-Stream Transport)
|
|
* - TransportMode = 0 (for Single Stream Transport)
|
|
* @param Bpc is the new number of bits per color to use.
|
|
* @param VidMode is one of the enumerated standard video modes
|
|
* defined in xvidc.h file.
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS DisplayPort configured successfully.
|
|
* - XST_FAILURE if DisplayPort configuration failed.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
u32 XSs_DpTxStart(XDp *InstancePtr, u8 TransportMode, u8 Bpc,
|
|
XVidC_VideoMode VidMode)
|
|
{
|
|
u32 Status;
|
|
u8 StreamIndex;
|
|
u8 NumOfStreams;
|
|
u8 Edid[128];
|
|
XDp_TxTopologyNode *Sink1;
|
|
|
|
/* Verify arguments. */
|
|
Xil_AssertNonvoid(InstancePtr != NULL);
|
|
Xil_AssertNonvoid((TransportMode == XSS_DPTX_MST) ||
|
|
(TransportMode == XSS_DPTX_SST));
|
|
Xil_AssertNonvoid((Bpc == XVIDC_BPC_8) || (Bpc == XVIDC_BPC_10) ||
|
|
(Bpc == XVIDC_BPC_12) || (Bpc == XVIDC_BPC_16));
|
|
Xil_AssertNonvoid((VidMode < XVIDC_VM_NUM_SUPPORTED) ||
|
|
(VidMode == XVIDC_VM_USE_EDID_PREFERRED));
|
|
|
|
/* Check for MST / SST mode */
|
|
if (TransportMode) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"\n\rSS INFO:Starting "
|
|
"MST config.\n\r");
|
|
/* Enable MST mode in both the RX and TX. */
|
|
Status = XDp_TxMstEnable(InstancePtr);
|
|
if (Status != XST_SUCCESS) {
|
|
/* If the immediate downstream RX device is an MST
|
|
* monitor and the DisplayPort Configuration Data
|
|
* (DPCD) does not indicate MST capability, it is
|
|
* likely that the MST or DisplayPort v1.2 option must
|
|
* be selected from the monitor's option menu.
|
|
* Likewise, the DisplayPort TX core must be configured
|
|
* to support MST mode. */
|
|
if (Status == XST_DEVICE_NOT_FOUND) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR:MST:"
|
|
"No connection exists. Verify cable "
|
|
"and/or monitor.\n\r");
|
|
}
|
|
else {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR:MST:"
|
|
"Verify DisplayPort MST capabilities "
|
|
"in the TX and/or RX device MST "
|
|
"status is %ld\n\r", Status);
|
|
}
|
|
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
/* Set AUX and sideband delays in microseconds */
|
|
InstancePtr->TxInstance.AuxDelayUs = 30000;
|
|
InstancePtr->TxInstance.SbMsgDelayUs = 30000;
|
|
|
|
/* Enable downshifting during link training */
|
|
XDp_TxEnableTrainAdaptive(InstancePtr, 1);
|
|
|
|
/* Enable redriver on DP output path */
|
|
XDp_TxSetHasRedriverInPath(InstancePtr, 1);
|
|
|
|
/* Disable main stream to force sending of IDLE patterns. */
|
|
XDp_TxDisableMainLink(InstancePtr);
|
|
|
|
/* Start link training with user set link rate and lane
|
|
* count. Training is required to discover topology so that
|
|
* prefer erred timing can be known.
|
|
*/
|
|
Status = XSs_DpTxStartLink(InstancePtr, FALSE);
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:Re- "
|
|
"training with maximum RX capabilities\n\r");
|
|
|
|
/* Train link with maximum RX capabilities */
|
|
Status = XSs_DpTxStartLink(InstancePtr, TRUE);
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR:MST:"
|
|
"Verify cable and/or monitor.\n\r");
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:Discovering "
|
|
"topology.\n\r");
|
|
|
|
/* Get list of sinks */
|
|
Status = Dp_GetTopology(InstancePtr);
|
|
if (Status != XST_SUCCESS) {
|
|
return Status;
|
|
}
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:Topology "
|
|
"discovery done, # of sinks found = %d.\n\r",
|
|
InstancePtr->TxInstance.Topology.SinkTotal);
|
|
|
|
/* Total number of streams equal to number of sinks found */
|
|
NumOfStreams = InstancePtr->TxInstance.Topology.SinkTotal;
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:Reading (MST) Sink "
|
|
"EDID...\n\r");
|
|
|
|
/* Read EDID of first sink */
|
|
Sink1 = InstancePtr->TxInstance.Topology.SinkList[0];
|
|
XDp_TxGetRemoteEdid(InstancePtr, Sink1->LinkCountTotal,
|
|
Sink1->RelativeAddress, Edid);
|
|
|
|
/* Check video mode for EDID preferred video mode */
|
|
if (VidMode == XVIDC_VM_USE_EDID_PREFERRED) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:Using "
|
|
"preferred EDID resolution.\n\r");
|
|
|
|
/* Get preferred video mode from EDID */
|
|
VidMode = Dp_GetPreferredVm(Edid);
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:VM "
|
|
"from EDID:%s\n\r",
|
|
XVidC_GetVideoModeStr(VidMode));
|
|
|
|
/* Check whether Video mode exist in VTM table */
|
|
if (XVIDC_VM_NOT_SUPPORTED == VidMode) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:"
|
|
"Preferred video mode not present in "
|
|
"VMT. Update video timing table.\n\r"
|
|
"Setting to 640x480 video mode\n\r");
|
|
VidMode = XVIDC_VM_640x480_60_P;
|
|
}
|
|
|
|
if ((InstancePtr->TxInstance.Topology.SinkTotal ==
|
|
4) && (VidMode == XVIDC_VM_UHD2_60_P)) {
|
|
VidMode = XVIDC_VM_1080_60_P;
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:"
|
|
"MST:Re-ordering sinks if belongs to "
|
|
"same TDT...\n\r");
|
|
|
|
/* Order the sink belong to same TDT */
|
|
XDp_TxTopologySortSinksByTiling(InstancePtr);
|
|
}
|
|
else if ((InstancePtr->TxInstance.Topology.SinkTotal ==
|
|
2) && (VidMode <= XVIDC_VM_UHD2_60_P)){
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:"
|
|
"MST:Re-ordering sinks if belongs to "
|
|
"same TDT...\n\r");
|
|
|
|
/* Order the sink belong to same TDT */
|
|
XDp_TxTopologySortSinksByTiling(InstancePtr);
|
|
}
|
|
}
|
|
else {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:Using "
|
|
"user set resolution.\n\r");
|
|
|
|
/* Check whether VidMode ID is supported */
|
|
Status = XVidC_EdidIsVideoTimingSupported(Edid,
|
|
(XVidC_VideoTimingMode *)XVidC_GetVideoModeData(
|
|
VidMode));
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:"
|
|
"MST:%s is not supported.\n\rSetting to "
|
|
"640x480 resolution."
|
|
"\n\r", XVidC_GetVideoModeStr(VidMode));
|
|
VidMode = XVIDC_VM_640x480_60_P;
|
|
}
|
|
|
|
if ((InstancePtr->TxInstance.Topology.SinkTotal ==
|
|
4) && (VidMode == XVIDC_VM_UHD2_60_P)){
|
|
VidMode = XVIDC_VM_1080_60_P;
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:"
|
|
"Re-ordering sinks if belongs to same "
|
|
"TDT...\n\r");
|
|
|
|
/* Order sinks belongs to the same TDT */
|
|
XDp_TxTopologySortSinksByTiling(InstancePtr);
|
|
}
|
|
else if ((InstancePtr->TxInstance.Topology.SinkTotal ==
|
|
2) && (VidMode <= XVIDC_VM_UHD2_60_P)){
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:"
|
|
"Re-ordering sinks if belongs to same "
|
|
"TDT...\n\r");
|
|
|
|
/* Order sinks belongs to the same TDT */
|
|
XDp_TxTopologySortSinksByTiling(InstancePtr);
|
|
}
|
|
}
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:calculating "
|
|
"payload...\n\r");
|
|
|
|
/* Check link and video bandwidth */
|
|
Status = Dp_CheckBandwidth(InstancePtr, Bpc, VidMode);
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:Link is "
|
|
"over-subscribed for selected resolution, "
|
|
"bpc, lane count and link rate value."
|
|
"\n\rRe-training with maximum RX capabilities."
|
|
"\n\r");
|
|
|
|
/* Check for link training need and run training
|
|
* sequence.
|
|
*/
|
|
Status = XSs_DpTxStartLink(InstancePtr, TRUE);
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:"
|
|
"Re-training with max after payload "
|
|
"failed.\n\r");
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
/* Enable each stream(s) */
|
|
for (StreamIndex = 0; StreamIndex < NumOfStreams;
|
|
StreamIndex++) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:"
|
|
"Enabling stream #%d\n", XDP_TX_STREAM_ID1 +
|
|
StreamIndex);
|
|
XDp_TxMstCfgStreamEnable(InstancePtr,
|
|
XDP_TX_STREAM_ID1 + StreamIndex);
|
|
XDp_TxSetStreamSelectFromSinkList(InstancePtr,
|
|
XDP_TX_STREAM_ID1 + StreamIndex, StreamIndex);
|
|
}
|
|
|
|
/* Disable stream(s) */
|
|
for (StreamIndex = NumOfStreams; StreamIndex < 4;
|
|
StreamIndex++) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:"
|
|
"Disabling stream #%d\n", XDP_TX_STREAM_ID1 +
|
|
StreamIndex);
|
|
XDp_TxMstCfgStreamDisable(InstancePtr,
|
|
XDP_TX_STREAM_ID1 + StreamIndex);
|
|
}
|
|
|
|
/* Stream setup */
|
|
for (StreamIndex = 0; StreamIndex < 4; StreamIndex++) {
|
|
if (XDp_TxMstStreamIsEnabled(InstancePtr,
|
|
XDP_TX_STREAM_ID1 + StreamIndex)) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:"
|
|
"Stream #%d... ",XDP_TX_STREAM_ID1 +
|
|
StreamIndex);
|
|
|
|
/* Set bits per color for each stream */
|
|
XDp_TxCfgMsaSetBpc(InstancePtr,
|
|
XDP_TX_STREAM_ID1 + StreamIndex, Bpc);
|
|
|
|
/* Enable sync clock mode for each stream */
|
|
XDp_TxCfgMsaEnSynchClkMode(InstancePtr,
|
|
XDP_TX_STREAM_ID1 + StreamIndex, 1);
|
|
|
|
/* Use standard video mode to calculate MSA */
|
|
XDp_TxCfgMsaUseStandardVideoMode(InstancePtr,
|
|
XDP_TX_STREAM_ID1 + StreamIndex,
|
|
VidMode);
|
|
|
|
/* Set user pixel width if video mode is
|
|
* UHD2
|
|
*/
|
|
if ((InstancePtr->TxInstance.MsaConfig[
|
|
StreamIndex].Vtm.VmId ==
|
|
XVIDC_VM_UHD2_60_P) &&
|
|
(InstancePtr->TxInstance.MsaConfig[
|
|
StreamIndex].OverrideUserPixelWidth ==
|
|
0)) {
|
|
InstancePtr->TxInstance.MsaConfig[
|
|
StreamIndex].UserPixelWidth =
|
|
4;
|
|
}
|
|
|
|
/* Apply to hardware */
|
|
XDp_TxSetVideoMode(InstancePtr,
|
|
XDP_TX_STREAM_ID1 + StreamIndex);
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"configured."
|
|
"\n\r");
|
|
}
|
|
}
|
|
|
|
Status = XDp_TxCheckLinkStatus(InstancePtr,
|
|
InstancePtr->TxInstance.LinkConfig.LaneCount);
|
|
if (Status == XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST: Link "
|
|
"is up after streams are configured!\n\r\n\r");
|
|
}
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:Allocating "
|
|
"payload...\n\r");
|
|
|
|
/* Clear virtual channel payload ID table in TX and all
|
|
* downstream RX devices
|
|
*/
|
|
Status = XDp_TxClearPayloadVcIdTable(InstancePtr);
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR:MST:"
|
|
"Clearing virtual channel payload "
|
|
"failed.\n\r");
|
|
return XST_DATA_LOST;
|
|
}
|
|
|
|
/* Allocate payloads. */
|
|
Status = XDp_TxAllocatePayloadStreams(InstancePtr);
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR:MST:"
|
|
"Allocation failed. Check link "
|
|
"over-subscription and bring down "
|
|
"resolution or BPC.\n\r");
|
|
return XST_DATA_LOST;
|
|
}
|
|
|
|
Status = XDp_TxCheckLinkStatus(InstancePtr,
|
|
InstancePtr->TxInstance.LinkConfig.LaneCount);
|
|
if (Status == XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:Link "
|
|
"is up after allocate payload!\n\r\n\r");
|
|
}
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:Config done!"
|
|
"\n\r\n\r");
|
|
}
|
|
/* SST */
|
|
else {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"\n\rSS INFO:Starting "
|
|
"SST config.\n\r");
|
|
|
|
/* Reset MST mode in both the RX and TX */
|
|
Status = XDp_TxMstDisable(InstancePtr);
|
|
if (Status != XST_SUCCESS) {
|
|
InstancePtr->TxInstance.MstEnable = 0;
|
|
}
|
|
|
|
/* set AUX and sideband delays in microseconds */
|
|
InstancePtr->TxInstance.AuxDelayUs = 0;
|
|
InstancePtr->TxInstance.SbMsgDelayUs = 0;
|
|
|
|
/* Enable downshifting during link training */
|
|
XDp_TxEnableTrainAdaptive(InstancePtr, 1);
|
|
|
|
/* Enable redriver on DP output path */
|
|
XDp_TxSetHasRedriverInPath(InstancePtr, 1);
|
|
|
|
/* Disable main stream to force sending of IDLE patterns. */
|
|
XDp_TxDisableMainLink(InstancePtr);
|
|
|
|
/* Start link training with user set link rate and lane
|
|
* count.
|
|
*/
|
|
Status = XSs_DpTxStartLink(InstancePtr, FALSE);
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:SST:"
|
|
"Re-training with maximum RX capabilities."
|
|
"\n\r");
|
|
|
|
/* Train link with maximum RX capabilities */
|
|
Status = XSs_DpTxStartLink(InstancePtr, TRUE);
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR:SST:"
|
|
"Verify cable and/or monitor.\n\r");
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"Reading (SST) Sink EDID..."
|
|
"\n\r");
|
|
|
|
/* Get EDID */
|
|
XDp_TxGetEdid(InstancePtr, Edid);
|
|
|
|
if (VidMode == XVIDC_VM_USE_EDID_PREFERRED) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:SST:Using "
|
|
"preferred EDID resolution.\n\r");
|
|
|
|
/* Get preferred video mode from EDID */
|
|
VidMode = Dp_GetPreferredVm(Edid);
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:SST: VM "
|
|
"from EDID:%s\n\r",
|
|
XVidC_GetVideoModeStr(VidMode));
|
|
|
|
/* Check whether Video mode exist in VTM table */
|
|
if (XVIDC_VM_NOT_SUPPORTED == VidMode) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"EDID "
|
|
"preferred video mode not present. "
|
|
"Update video timing table.\n\r"
|
|
"Setting to 640x480 video mode\n\r");
|
|
VidMode = XVIDC_VM_640x480_60_P;
|
|
}
|
|
}
|
|
else {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:SST:Using "
|
|
"user set resolution.\n\r");
|
|
|
|
/* Check whether VidMode ID is supported */
|
|
Status = XVidC_EdidIsVideoTimingSupported(Edid,
|
|
(XVidC_VideoTimingMode *)XVidC_GetVideoModeData(
|
|
VidMode));
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:SST:"
|
|
"%s is not supported.\n\rSetting to "
|
|
"640x480 resolution.\n\r",
|
|
XVidC_GetVideoModeStr(VidMode));
|
|
VidMode = XVIDC_VM_640x480_60_P;
|
|
}
|
|
}
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:SST:calculating "
|
|
"payload...\n\r");
|
|
|
|
/* Check link and video bandwidth */
|
|
Status = Dp_CheckBandwidth(InstancePtr, Bpc, VidMode);
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:SST:Link is "
|
|
"over-subscribed for selected resolution, "
|
|
"bpc, lane count and link rate value.\n\r"
|
|
"Re-training with maximum RX capabilities."
|
|
"\n\r");
|
|
|
|
/* Check for link training need and run training
|
|
* sequence.
|
|
*/
|
|
Status = XSs_DpTxStartLink(InstancePtr, TRUE);
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:SST:"
|
|
"Re-training failed with max "
|
|
"capabilities after payload "
|
|
"failure.\n\r");
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
/* Reset MSA values */
|
|
XDp_TxClearMsaValues(InstancePtr, XDP_TX_STREAM_ID1);
|
|
XDp_TxClearMsaValues(InstancePtr, XDP_TX_STREAM_ID2);
|
|
XDp_TxClearMsaValues(InstancePtr, XDP_TX_STREAM_ID3);
|
|
XDp_TxClearMsaValues(InstancePtr, XDP_TX_STREAM_ID4);
|
|
|
|
InstancePtr->TxInstance.MsaConfig[0].DynamicRange = 0;
|
|
InstancePtr->TxInstance.MsaConfig[0].YCbCrColorimetry = 0;
|
|
|
|
/* Enable sync clock mode */
|
|
XDp_TxCfgMsaEnSynchClkMode(InstancePtr,
|
|
XDP_TX_STREAM_ID1, 1);
|
|
|
|
/* Set user provided BPC to stream 1 */
|
|
XDp_TxCfgMsaSetBpc(InstancePtr, XDP_TX_STREAM_ID1, Bpc);
|
|
|
|
/* Set user standard video mode for stream 1 to populate
|
|
* MSA values
|
|
*/
|
|
XDp_TxCfgMsaUseStandardVideoMode(InstancePtr,
|
|
XDP_TX_STREAM_ID1, VidMode);
|
|
|
|
/* Set user pixel width if video mode is UHD2 */
|
|
if ((InstancePtr->TxInstance.MsaConfig[0].Vtm.VmId ==
|
|
XVIDC_VM_UHD2_60_P) &&
|
|
(InstancePtr->TxInstance.MsaConfig[
|
|
0].OverrideUserPixelWidth == 0)) {
|
|
InstancePtr->TxInstance.MsaConfig[
|
|
0].UserPixelWidth = 4;
|
|
}
|
|
|
|
/* Set video mode */
|
|
XDp_TxSetVideoMode(InstancePtr, XDP_TX_STREAM_ID1);
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:SST: Config done!"
|
|
"\n\r\n\r");
|
|
|
|
/* Reset the transmitter. */
|
|
XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_SOFT_RESET,
|
|
XDP_TX_SOFT_RESET_VIDEO_STREAM_ALL_MASK);
|
|
XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_SOFT_RESET,
|
|
0x0);
|
|
}
|
|
|
|
/* Enable the main link. */
|
|
XDp_TxEnableMainLink(InstancePtr);
|
|
|
|
Status = XDp_TxCheckLinkStatus(InstancePtr,
|
|
InstancePtr->TxInstance.LinkConfig.LaneCount);
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:Link "
|
|
"is DOWN after main link enabled!\n\r\n\r");
|
|
}
|
|
else if (Status == XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:Link "
|
|
"is UP after main link enabled!\n\r\n\r");
|
|
}
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:Enabled main link!"
|
|
"\n\r\n\r");
|
|
|
|
return XST_SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
*
|
|
* This function checks if the link needs training and runs the training
|
|
* sequence if training is required based on the flags, indicates to use maximum
|
|
* RX capabilities or user specified link rate, lane count during training.
|
|
*
|
|
* @param InstancePtr is a pointer to the XDp instance.
|
|
* @param TrainMaxCap is a flag indicates whether maximum capabilities
|
|
* to be used during link training.
|
|
* - TRUE - Use maximum RX capabilities.
|
|
* - FALSE - Use custom capabilities.
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS the if main link was successfully established.
|
|
* - XST_FAILURE otherwise.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
u32 XSs_DpTxStartLink(XDp *InstancePtr, u8 TrainMaxCap)
|
|
{
|
|
u32 Status;
|
|
u32 IntrMask;
|
|
u8 LinkRate;
|
|
u8 LaneCount;
|
|
|
|
/* Read interrupts */
|
|
IntrMask = XDp_ReadReg(InstancePtr->Config.BaseAddr,
|
|
XDP_TX_INTERRUPT_MASK);
|
|
|
|
/* Disable HPD pulse interrupts during link training. */
|
|
XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_INTERRUPT_MASK,
|
|
IntrMask | XDP_TX_INTERRUPT_MASK_HPD_PULSE_DETECTED_MASK);
|
|
|
|
/* Obtain the capabilities of the RX device by reading the monitor's
|
|
* DPCD.
|
|
*/
|
|
Status = XDp_TxGetRxCapabilities(InstancePtr);
|
|
if (Status != XST_SUCCESS) {
|
|
XDp_WriteReg(InstancePtr->Config.BaseAddr,
|
|
XDP_TX_INTERRUPT_MASK, IntrMask);
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
/* Enable clock spreading for both DP TX and RX device */
|
|
XDp_TxSetDownspread(InstancePtr, 1);
|
|
|
|
/* Enable enhanced framing symbol sequence */
|
|
XDp_TxSetEnhancedFrameMode(InstancePtr, 1);
|
|
|
|
/* Configure link with max values of link rate and lane count
|
|
* for the first time from next onwards configure it with the
|
|
* user set values.
|
|
*/
|
|
if (TrainMaxCap) {
|
|
/* Configure the main link based on the maximum common
|
|
* capabilities of the DisplayPort TX core and the
|
|
* receiver device.
|
|
*/
|
|
Status = XDp_TxCfgMainLinkMax(InstancePtr);
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR:RX device "
|
|
"not connected.\n\r");
|
|
XDp_WriteReg(InstancePtr->Config.BaseAddr,
|
|
XDP_TX_INTERRUPT_MASK, IntrMask);
|
|
return XST_FAILURE;
|
|
}
|
|
}
|
|
|
|
LinkRate = InstancePtr->TxInstance.LinkConfig.LinkRate;
|
|
LaneCount = InstancePtr->TxInstance.LinkConfig.LaneCount;
|
|
|
|
/* Establish link after training process */
|
|
Status = XDp_TxEstablishLink(InstancePtr);
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR:Training failed."
|
|
"\n\r");
|
|
XDp_WriteReg(InstancePtr->Config.BaseAddr,
|
|
XDP_TX_INTERRUPT_MASK, IntrMask);
|
|
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
/* Check whether link rate downshifted */
|
|
if (LinkRate != InstancePtr->TxInstance.LinkConfig.LinkRate) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS Warning! Link rate is "
|
|
"downshifted.\n\r");
|
|
}
|
|
|
|
/* Check whether lane count downshifted */
|
|
if (LaneCount != InstancePtr->TxInstance.LinkConfig.LaneCount) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS Warning! Lane count is "
|
|
"downshifted.\n\r");
|
|
}
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:Training passed at link rate:"
|
|
"0x%02x lane count:%d.\n\r",
|
|
InstancePtr->TxInstance.LinkConfig.LinkRate,
|
|
InstancePtr->TxInstance.LinkConfig.LaneCount);
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:VS:%d (TX:%ld) PE:%d (TX:%ld)"
|
|
"\n\r", InstancePtr->TxInstance.LinkConfig.VsLevel,
|
|
XDp_ReadReg(InstancePtr->Config.BaseAddr,
|
|
XDP_TX_PHY_VOLTAGE_DIFF_LANE_0),
|
|
InstancePtr->TxInstance.LinkConfig.PeLevel,
|
|
XDp_ReadReg(InstancePtr->Config.BaseAddr,
|
|
XDP_TX_PHY_POSTCURSOR_LANE_0));
|
|
|
|
/* Enable HPD interrupts after link training. */
|
|
XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_INTERRUPT_MASK,
|
|
IntrMask);
|
|
|
|
return XST_SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
*
|
|
* This function calculates the video bandwidth and link bandwidth in single
|
|
* stream and millstream mode. It checks whether the link bandwidth is not
|
|
* over-subscribed for video bandwidth.
|
|
*
|
|
* @param InstancePtr is a pointer to the XDp instance.
|
|
* @param Bpc is the new number of bits per color to use.
|
|
* @param VidMode is one of the enumerated standard video modes
|
|
* defined in xvidc.h file.
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if link bandwidth is not over-subscribed.
|
|
* - XST_FAILURE otherwise.
|
|
*
|
|
* @note Check that the stream allocation will succeed based on
|
|
* capabilities. Don't go through training and allocation sequence
|
|
* if the pre-calculations indicate that it will fail
|
|
*
|
|
******************************************************************************/
|
|
static u32 Dp_CheckBandwidth(XDp *InstancePtr, u8 Bpc, XVidC_VideoMode VidMode)
|
|
{
|
|
u32 MstCapable;
|
|
u32 LinkBw = (InstancePtr->TxInstance.LinkConfig.LaneCount *
|
|
InstancePtr->TxInstance.LinkConfig.LinkRate * 27);
|
|
u8 BitsPerPixel = 3 * Bpc;
|
|
|
|
/* Check for maximum link rate supported */
|
|
if (InstancePtr->TxInstance.LinkConfig.MaxLinkRate <
|
|
InstancePtr->TxInstance.LinkConfig.LinkRate) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS:INFO:Requested link rate "
|
|
"exceeds maximum capabilities.\n\rMaximum link "
|
|
"rate = ");
|
|
|
|
/* Report maximum link rate supported */
|
|
switch (InstancePtr->TxInstance.LinkConfig.MaxLinkRate) {
|
|
case XDP_TX_LINK_BW_SET_540GBPS:
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"5.40 Gbps."
|
|
"\n\r");
|
|
break;
|
|
|
|
case XDP_TX_LINK_BW_SET_270GBPS:
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"2.70 Gbps."
|
|
"\n\r");
|
|
break;
|
|
|
|
case XDP_TX_LINK_BW_SET_162GBPS:
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"1.62 Gbps."
|
|
"\n\r");
|
|
break;
|
|
}
|
|
|
|
return XST_FAILURE;
|
|
}
|
|
else if (InstancePtr->TxInstance.LinkConfig.MaxLaneCount <
|
|
InstancePtr->TxInstance.LinkConfig.LaneCount) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR:Requested lane count "
|
|
"exceeds maximum capabilities.\n\tMaximum lane count "
|
|
"= %d.\n\r",
|
|
InstancePtr->TxInstance.LinkConfig.MaxLaneCount);
|
|
return XST_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
/* Check MST mode */
|
|
MstCapable = XDp_TxMstCapable(InstancePtr);
|
|
|
|
/* This check is done so that this function check can be called from
|
|
* anywhere and it will precaculate the required total timeslots based
|
|
* on the number of sinks and MSA values.
|
|
* This works because if the example will always run in MST mode if
|
|
* the monitor is capable of it, otherwise in SST mode.
|
|
*/
|
|
if ((MstCapable != XST_SUCCESS) ||
|
|
(InstancePtr->TxInstance.MstEnable == 0)) {
|
|
u32 TransferUnitSize = 64;
|
|
u32 VideoBw = (XVidC_GetPixelClockHzByVmId(VidMode) / 1000) *
|
|
BitsPerPixel / 8;
|
|
u32 AvgBytesPerTU = (VideoBw * TransferUnitSize) / LinkBw;
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS:INFO:Checking link "
|
|
"bandwidth validity for SST.\n\r");
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO: Link bandwidth = "
|
|
"%ld Kbps and video bandwidth = %ld Kbps\n\r",
|
|
(LinkBw * 1000), VideoBw);
|
|
|
|
if (AvgBytesPerTU > (TransferUnitSize * 1000)) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:SST link is "
|
|
"over-subscribed.\n\r");
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:Link "
|
|
"bandwidth = %ld Kbps and video bandwidth = "
|
|
"%ld Kbps\n\r", (LinkBw * 1000), VideoBw);
|
|
|
|
return XST_BUFFER_TOO_SMALL;
|
|
}
|
|
}
|
|
else if ((MstCapable == XST_SUCCESS) &&
|
|
(InstancePtr->TxInstance.MstEnable == 1)) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:Checking link "
|
|
"bandwidth validity for MST\n\r");
|
|
|
|
u8 StreamIndex;
|
|
u32 TimeSlots;
|
|
u32 TotalTimeSlots = 0;
|
|
double PeakPixelBw;
|
|
double Average_StreamSymbolTimeSlotsPerMTP;
|
|
double Target_Average_StreamSymbolTimeSlotsPerMTP;
|
|
double MaximumTarget_Average_StreamSymbolTimeSlotsPerMTP;
|
|
u32 TsInt;
|
|
u32 TsFrac;
|
|
u16 Pbn;
|
|
|
|
PeakPixelBw = ((double)XVidC_GetPixelClockHzByVmId(VidMode) /
|
|
1000000) * ((double)BitsPerPixel / 8);
|
|
|
|
Pbn = 1.006 * PeakPixelBw * ((double)64 / 54);
|
|
|
|
if ((double)(1.006 * PeakPixelBw * ((double)64 / 54)) >
|
|
((double)Pbn)) {
|
|
Pbn++;
|
|
}
|
|
|
|
Average_StreamSymbolTimeSlotsPerMTP = (64.0 * PeakPixelBw /
|
|
LinkBw);
|
|
MaximumTarget_Average_StreamSymbolTimeSlotsPerMTP = (54.0 *
|
|
((double)Pbn / LinkBw));
|
|
|
|
Target_Average_StreamSymbolTimeSlotsPerMTP =
|
|
(u32)Average_StreamSymbolTimeSlotsPerMTP;
|
|
Target_Average_StreamSymbolTimeSlotsPerMTP += ((1.0 / 8.0) *
|
|
(u32)(8.0 *
|
|
(MaximumTarget_Average_StreamSymbolTimeSlotsPerMTP -
|
|
Target_Average_StreamSymbolTimeSlotsPerMTP)));
|
|
|
|
TsInt = Target_Average_StreamSymbolTimeSlotsPerMTP;
|
|
TsFrac = (((double)Target_Average_StreamSymbolTimeSlotsPerMTP *
|
|
1000) - (TsInt * 1000));
|
|
|
|
TimeSlots = TsInt;
|
|
if (TsFrac != 0) {
|
|
TimeSlots++;
|
|
}
|
|
if ((InstancePtr->Config.PayloadDataWidth == 4) &&
|
|
(TimeSlots % 4) != 0) {
|
|
TimeSlots += (4 - (TimeSlots % 4));
|
|
}
|
|
else if ((TimeSlots % 2) != 0) {
|
|
TimeSlots++;
|
|
}
|
|
|
|
/* Add up all the timeslots. */
|
|
for (StreamIndex = 0; StreamIndex < 4; StreamIndex++) {
|
|
if (XDp_TxMstStreamIsEnabled(InstancePtr,
|
|
StreamIndex + 1)) {
|
|
TotalTimeSlots += TimeSlots;
|
|
}
|
|
}
|
|
|
|
if (TotalTimeSlots > 63) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR: MST "
|
|
"link over-subscribed.\n\rTotal time slots "
|
|
"required: %ld for %ld streams.\n\rOnly 63 "
|
|
"time slots are available.\n\r",
|
|
TotalTimeSlots, TotalTimeSlots / TimeSlots);
|
|
|
|
return XST_FAILURE;
|
|
}
|
|
}
|
|
|
|
return XST_SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
*
|
|
* This function discovers the topology and finds the actual number of sinks.
|
|
* It enables streams corresponding to each sink found during topology
|
|
* discovery.
|
|
*
|
|
* @param InstancePtr is a pointer to the XDp instance.
|
|
*
|
|
* @return
|
|
* - XST_SUCCESS if topology discovered successfully.
|
|
* - XST_FAILURE if topology discovery failed.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
static u32 Dp_GetTopology(XDp *InstancePtr)
|
|
{
|
|
u32 Status;
|
|
u8 NumStreams;
|
|
|
|
/* Clear node and sink */
|
|
InstancePtr->TxInstance.Topology.NodeTotal = 0;
|
|
InstancePtr->TxInstance.Topology.SinkTotal = 0;
|
|
|
|
/* Discover topology and find total sinks */
|
|
Status = XDp_TxDiscoverTopology(InstancePtr);
|
|
if (Status != XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS ERR:MST:Topology failed:"
|
|
"%ld.\n\r", Status);
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
/* Total number of streams equivalent to number of sinks found */
|
|
NumStreams = InstancePtr->TxInstance.Topology.SinkTotal;
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:No of streams based on "
|
|
"topology discovery is = %d\n\r", NumStreams);
|
|
|
|
if (NumStreams > InstancePtr->Config.NumMstStreams) {
|
|
NumStreams = InstancePtr->Config.NumMstStreams;
|
|
}
|
|
|
|
Status = XDp_TxCheckLinkStatus(InstancePtr,
|
|
InstancePtr->TxInstance.LinkConfig.LaneCount);
|
|
if (Status == XST_SUCCESS) {
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:MST:Link "
|
|
"is up after topology discovery!\n\r\n\r");
|
|
}
|
|
|
|
return XST_SUCCESS;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
*
|
|
* This function retrieves preferred timing mode information from the EDID
|
|
* to identify video mode or resolution.
|
|
*
|
|
* @param EdidPtr is the supplied base EDID to retrieve timing values.
|
|
*
|
|
* @return Id of a supported video mode.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
static XVidC_VideoMode Dp_GetPreferredVm(u8 *EdidPtr)
|
|
{
|
|
u8 *Ptm;
|
|
u16 HBlank;
|
|
u16 VBlank;
|
|
u32 PixelClockHz;
|
|
XVidC_FrameRate FrameRate;
|
|
XVidC_VideoTiming Timing;
|
|
XVidC_VideoMode VmId;
|
|
|
|
(void)memset((void *)&Timing, 0, sizeof(XVidC_VideoTiming));
|
|
|
|
Ptm = &EdidPtr[XDP_EDID_PTM];
|
|
|
|
HBlank = ((Ptm[XDP_EDID_DTD_HRES_HBLANK_U4] &
|
|
XDP_EDID_DTD_XRES_XBLANK_U4_XBLANK_MASK) << 8) |
|
|
Ptm[XDP_EDID_DTD_HBLANK_LSB];
|
|
|
|
VBlank = ((Ptm[XDP_EDID_DTD_VRES_VBLANK_U4] &
|
|
XDP_EDID_DTD_XRES_XBLANK_U4_XBLANK_MASK) << 8) |
|
|
Ptm[XDP_EDID_DTD_VBLANK_LSB];
|
|
|
|
Timing.HActive = (((Ptm[XDP_EDID_DTD_HRES_HBLANK_U4] &
|
|
XDP_EDID_DTD_XRES_XBLANK_U4_XRES_MASK) >>
|
|
XDP_EDID_DTD_XRES_XBLANK_U4_XRES_SHIFT) << 8) |
|
|
Ptm[XDP_EDID_DTD_HRES_LSB];
|
|
|
|
Timing.VActive = (((Ptm[XDP_EDID_DTD_VRES_VBLANK_U4] &
|
|
XDP_EDID_DTD_XRES_XBLANK_U4_XRES_MASK) >>
|
|
XDP_EDID_DTD_XRES_XBLANK_U4_XRES_SHIFT) << 8) |
|
|
Ptm[XDP_EDID_DTD_VRES_LSB];
|
|
|
|
PixelClockHz = (((Ptm[XDP_EDID_DTD_PIXEL_CLK_KHZ_MSB] <<
|
|
8) | Ptm[XDP_EDID_DTD_PIXEL_CLK_KHZ_LSB]) * 10) * 1000;
|
|
|
|
Timing.HFrontPorch = (((Ptm[XDP_EDID_DTD_XFPORCH_XSPW_U2] &
|
|
XDP_EDID_DTD_XFPORCH_XSPW_U2_HFPORCH_MASK) >>
|
|
XDP_EDID_DTD_XFPORCH_XSPW_U2_HFPORCH_SHIFT) << 8) |
|
|
Ptm[XDP_EDID_DTD_HFPORCH_LSB];
|
|
|
|
Timing.HSyncWidth = (((Ptm[XDP_EDID_DTD_XFPORCH_XSPW_U2] &
|
|
XDP_EDID_DTD_XFPORCH_XSPW_U2_HSPW_MASK) >>
|
|
XDP_EDID_DTD_XFPORCH_XSPW_U2_HSPW_SHIFT) << 8) |
|
|
Ptm[XDP_EDID_DTD_HSPW_LSB];
|
|
|
|
Timing.F0PVFrontPorch = (((Ptm[XDP_EDID_DTD_XFPORCH_XSPW_U2] &
|
|
XDP_EDID_DTD_XFPORCH_XSPW_U2_VFPORCH_MASK) >>
|
|
XDP_EDID_DTD_XFPORCH_XSPW_U2_VFPORCH_SHIFT) << 8) |
|
|
((Ptm[XDP_EDID_DTD_VFPORCH_VSPW_L4] &
|
|
XDP_EDID_DTD_VFPORCH_VSPW_L4_VFPORCH_MASK) >>
|
|
XDP_EDID_DTD_VFPORCH_VSPW_L4_VFPORCH_SHIFT);
|
|
|
|
Timing.F0PVSyncWidth = ((Ptm[XDP_EDID_DTD_XFPORCH_XSPW_U2] &
|
|
XDP_EDID_DTD_XFPORCH_XSPW_U2_VSPW_MASK) << 8) |
|
|
(Ptm[XDP_EDID_DTD_VFPORCH_VSPW_L4] &
|
|
XDP_EDID_DTD_VFPORCH_VSPW_L4_VSPW_MASK);
|
|
|
|
/* Compute video mode timing values. */
|
|
Timing.HBackPorch = HBlank - (Timing.HFrontPorch + Timing.HSyncWidth);
|
|
Timing.F0PVBackPorch = VBlank - (Timing.F0PVFrontPorch +
|
|
Timing.F0PVSyncWidth);
|
|
Timing.HTotal = (Timing.HSyncWidth + Timing.HFrontPorch +
|
|
Timing.HActive + Timing.HBackPorch);
|
|
Timing.F0PVTotal = (Timing.F0PVSyncWidth + Timing.F0PVFrontPorch +
|
|
Timing.VActive + Timing.F0PVBackPorch);
|
|
FrameRate = PixelClockHz / (Timing.HTotal * Timing.F0PVTotal);
|
|
|
|
xdbg_printf(XDBG_DEBUG_GENERAL,"SS INFO:"
|
|
"HAct:%d, VAct:%d, FR:%d\n\r", Timing.HActive,
|
|
Timing.VActive, FrameRate);
|
|
|
|
/* Few monitors returns 59 HZ. Hence, setting to 60. */
|
|
if (FrameRate == 59) {
|
|
FrameRate = 60;
|
|
}
|
|
|
|
/* Get video mode ID */
|
|
VmId = XVidC_GetVideoModeId(Timing.HActive, Timing.VActive,
|
|
FrameRate, XVidC_EdidIsDtdPtmInterlaced(EdidPtr));
|
|
|
|
return VmId;
|
|
}
|