embeddedsw/XilinxProcessorIPLib/drivers/dp/src/xdptx_spm.c

863 lines
32 KiB
C
Raw Normal View History

/*******************************************************************************
*
* Copyright (C) 2014 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 THE
* XILINX CONSORTIUM 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 xdptx_spm.c
*
* This file contains the stream policy maker functions for the XDptx driver.
* These functions set up the DisplayPort TX core's main stream attributes that
* determine how a video stream will be displayed.
*
* @note None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.0 als 05/17/14 Initial release.
* als 08/03/14 Initial MST addition.
* 3.0 als 12/16/14 Updated to use common video library.
* Stream naming now starts at 1 to follow IP.
* </pre>
*
*******************************************************************************/
/******************************* Include Files ********************************/
#include "xdptx.h"
#include "xdptx_hw.h"
#include "xstatus.h"
/**************************** Function Prototypes *****************************/
static void XDptx_CalculateTs(XDptx *InstancePtr, u8 Stream, u8 BitsPerPixel);
/**************************** Function Definitions ****************************/
/******************************************************************************/
/**
* This function calculates the following Main Stream Attributes (MSA):
* - Transfer unit size
* - User pixel width
* - Horizontal start
* - Vertical start
* - Horizontal total clock
* - Vertical total clock
* - Misc0
* - Misc1
* - Data per lane
* - Average number of bytes per transfer unit
* - Number of initial wait cycles
* These values are derived from:
* - Bits per color
* - Horizontal resolution
* - Vertical resolution
* - Pixel clock (in KHz)
* - Horizontal sync polarity
* - Vertical sync polarity
* - Horizontal front porch
* - Horizontal sync pulse width
* - Horizontal back porch
* - Vertical front porch
* - Vertical sync pulse width
* - Vertical back porch
*
* @param InstancePtr is a pointer to the XDptx instance.
* @param Stream is the stream number for which to calculate the MSA
* values.
*
* @return None.
*
* @note The MsaConfig structure is modified with the new, calculated
* values. The main stream attributes that were used to derive the
* calculated values are untouched in the MsaConfig structure.
*
*******************************************************************************/
void XDptx_CfgMsaRecalculate(XDptx *InstancePtr, u8 Stream)
{
u32 VideoBw;
u32 LinkBw;
u32 WordsPerLine;
u8 BitsPerPixel;
XDptx_MainStreamAttributes *MsaConfig;
XDptx_LinkConfig *LinkConfig;
/* Verify arguments. */
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid((Stream == XDPTX_STREAM_ID1) ||
(Stream == XDPTX_STREAM_ID2) || (Stream == XDPTX_STREAM_ID3) ||
(Stream == XDPTX_STREAM_ID4));
MsaConfig = &InstancePtr->MsaConfig[Stream - 1];
LinkConfig = &InstancePtr->LinkConfig;
/* Verify the rest of the values used. */
Xil_AssertVoid((LinkConfig->LinkRate == XDPTX_LINK_BW_SET_162GBPS) ||
(LinkConfig->LinkRate == XDPTX_LINK_BW_SET_270GBPS) ||
(LinkConfig->LinkRate == XDPTX_LINK_BW_SET_540GBPS));
Xil_AssertVoid((LinkConfig->LaneCount == XDPTX_LANE_COUNT_SET_1) ||
(LinkConfig->LaneCount == XDPTX_LANE_COUNT_SET_2) ||
(LinkConfig->LaneCount == XDPTX_LANE_COUNT_SET_4));
Xil_AssertVoid((MsaConfig->SynchronousClockMode == 0) ||
(MsaConfig->SynchronousClockMode == 1));
Xil_AssertVoid((MsaConfig->DynamicRange == 0) ||
(MsaConfig->DynamicRange == 1));
Xil_AssertVoid((MsaConfig->YCbCrColorimetry == 0) ||
(MsaConfig->YCbCrColorimetry == 1));
Xil_AssertVoid((MsaConfig->BitsPerColor == 6) ||
(MsaConfig->BitsPerColor == 8) ||
(MsaConfig->BitsPerColor == 10) ||
(MsaConfig->BitsPerColor == 12) ||
(MsaConfig->BitsPerColor == 16));
/* Set the user pixel width to handle clocks that exceed the
* capabilities of the DisplayPort TX core. */
if (MsaConfig->OverrideUserPixelWidth == 0) {
if ((MsaConfig->Vtm.PixelClkKhz > 300000) &&
(LinkConfig->LaneCount == XDPTX_LANE_COUNT_SET_4)) {
MsaConfig->UserPixelWidth = 4;
}
else if ((MsaConfig->Vtm.PixelClkKhz > 75000) &&
(LinkConfig->LaneCount != XDPTX_LANE_COUNT_SET_1)) {
MsaConfig->UserPixelWidth = 2;
}
else {
MsaConfig->UserPixelWidth = 1;
}
}
/* Compute the rest of the MSA values. */
MsaConfig->NVid = 27 * 1000 * LinkConfig->LinkRate;
MsaConfig->HStart = MsaConfig->Vtm.Timing.HSyncWidth +
MsaConfig->Vtm.Timing.HBackPorch;
MsaConfig->VStart = MsaConfig->Vtm.Timing.F0PVSyncWidth +
MsaConfig->Vtm.Timing.F0PVBackPorch;
MsaConfig->HClkTotal = (MsaConfig->Vtm.Timing.HSyncWidth +
MsaConfig->Vtm.Timing.HBackPorch +
MsaConfig->Vtm.Timing.HFrontPorch +
MsaConfig->Vtm.Timing.HActive);
MsaConfig->VClkTotal = (MsaConfig->Vtm.Timing.F0PVSyncWidth +
MsaConfig->Vtm.Timing.F0PVBackPorch +
MsaConfig->Vtm.Timing.F0PVFrontPorch +
MsaConfig->Vtm.Timing.VActive);
/* Miscellaneous attributes. */
if (MsaConfig->BitsPerColor == 6) {
MsaConfig->Misc0 = XDPTX_MAIN_STREAMX_MISC0_BDC_6BPC;
}
else if (MsaConfig->BitsPerColor == 8) {
MsaConfig->Misc0 = XDPTX_MAIN_STREAMX_MISC0_BDC_8BPC;
}
else if (MsaConfig->BitsPerColor == 10) {
MsaConfig->Misc0 = XDPTX_MAIN_STREAMX_MISC0_BDC_10BPC;
}
else if (MsaConfig->BitsPerColor == 12) {
MsaConfig->Misc0 = XDPTX_MAIN_STREAMX_MISC0_BDC_12BPC;
}
else if (MsaConfig->BitsPerColor == 16) {
MsaConfig->Misc0 = XDPTX_MAIN_STREAMX_MISC0_BDC_16BPC;
}
MsaConfig->Misc0 = (MsaConfig->Misc0 <<
XDPTX_MAIN_STREAMX_MISC0_BDC_SHIFT) |
(MsaConfig->YCbCrColorimetry <<
XDPTX_MAIN_STREAMX_MISC0_YCBCR_COLORIMETRY_SHIFT) |
(MsaConfig->DynamicRange <<
XDPTX_MAIN_STREAMX_MISC0_DYNAMIC_RANGE_SHIFT) |
(MsaConfig->ComponentFormat <<
XDPTX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_SHIFT) |
(MsaConfig->SynchronousClockMode);
MsaConfig->Misc1 = 0;
/* Determine the number of bits per pixel for the specified color
* component format. */
if (MsaConfig->ComponentFormat ==
XDPTX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_YCBCR422) {
/* YCbCr422 color component format. */
BitsPerPixel = MsaConfig->BitsPerColor * 2;
}
else {
/* RGB or YCbCr 4:4:4 color component format. */
BitsPerPixel = MsaConfig->BitsPerColor * 3;
}
/* Calculate the data per lane. */
WordsPerLine = (MsaConfig->Vtm.Timing.HActive * BitsPerPixel);
if ((WordsPerLine % 16) != 0) {
WordsPerLine += 16;
}
WordsPerLine /= 16;
MsaConfig->DataPerLane = WordsPerLine - LinkConfig->LaneCount;
if ((WordsPerLine % LinkConfig->LaneCount) != 0) {
MsaConfig->DataPerLane += (WordsPerLine % LinkConfig->LaneCount);
}
if (InstancePtr->MstEnable == 1) {
/* Do time slot (and payload bandwidth number) calculations for
* MST. */
XDptx_CalculateTs(InstancePtr, Stream, BitsPerPixel);
MsaConfig->InitWait = 0;
}
else {
/* Allocate a fixed size for single-stream transport (SST)
* operation. */
MsaConfig->TransferUnitSize = 64;
/* Calculate the average number of bytes per transfer unit.
* Note: Both the integer and the fractional part is stored in
* AvgBytesPerTU. */
VideoBw = (MsaConfig->Vtm.PixelClkKhz * BitsPerPixel) / 8;
LinkBw = (LinkConfig->LaneCount * LinkConfig->LinkRate * 27);
MsaConfig->AvgBytesPerTU = (VideoBw *
MsaConfig->TransferUnitSize) / LinkBw;
/* The number of initial wait cycles at the start of a new line
* by the framing logic. This allows enough data to be buffered
* in the input FIFO before video is sent. */
if ((MsaConfig->AvgBytesPerTU / 1000) <= 4) {
MsaConfig->InitWait = 64;
}
else {
MsaConfig->InitWait = MsaConfig->TransferUnitSize -
(MsaConfig->AvgBytesPerTU / 1000);
}
}
}
/******************************************************************************/
/**
* This function sets the Main Stream Attribute (MSA) values in the
* configuration structure to match one of the standard display mode timings
* from the XDptx_DmtModes[] standard Display Monitor Timing (DMT) table. The
* XDptx_VideoMode enumeration in xdptx.h lists the available video modes.
*
* @param InstancePtr is a pointer to the XDptx instance.
* @param Stream is the stream number for which the MSA values will be
* used for.
* @param VideoMode is one of the enumerated standard video modes that is
* used to determine the MSA values to be used.
*
* @return None.
*
* @note The InstancePtr->MsaConfig structure is modified to reflect the
* MSA values associated to the specified video mode.
*
*******************************************************************************/
void XDptx_CfgMsaUseStandardVideoMode(XDptx *InstancePtr, u8 Stream,
XVid_VideoMode VideoMode)
{
XDptx_MainStreamAttributes *MsaConfig;
/* Verify arguments. */
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(VideoMode < XVID_VM_NUM_SUPPORT);
Xil_AssertVoid((Stream == XDPTX_STREAM_ID1) ||
(Stream == XDPTX_STREAM_ID2) || (Stream == XDPTX_STREAM_ID3) ||
(Stream == XDPTX_STREAM_ID4));
MsaConfig = &InstancePtr->MsaConfig[Stream - 1];
/* Configure the MSA values from the display monitor DMT table. */
MsaConfig->Vtm.PixelClkKhz =
XVid_VideoTimingModes[VideoMode].PixelClkKhz;
MsaConfig->Vtm.Timing.HActive =
XVid_VideoTimingModes[VideoMode].Timing.HActive;
MsaConfig->Vtm.Timing.VActive =
XVid_VideoTimingModes[VideoMode].Timing.VActive;
MsaConfig->Vtm.Timing.HSyncPolarity =
XVid_VideoTimingModes[VideoMode].Timing.HSyncPolarity;
MsaConfig->Vtm.Timing.VSyncPolarity =
XVid_VideoTimingModes[VideoMode].Timing.VSyncPolarity;
MsaConfig->Vtm.Timing.HFrontPorch =
XVid_VideoTimingModes[VideoMode].Timing.HFrontPorch;
MsaConfig->Vtm.Timing.HSyncWidth =
XVid_VideoTimingModes[VideoMode].Timing.HSyncWidth;
MsaConfig->Vtm.Timing.HBackPorch =
XVid_VideoTimingModes[VideoMode].Timing.HBackPorch;
MsaConfig->Vtm.Timing.F0PVFrontPorch =
XVid_VideoTimingModes[VideoMode].Timing.F0PVFrontPorch;
MsaConfig->Vtm.Timing.F0PVSyncWidth =
XVid_VideoTimingModes[VideoMode].Timing.F0PVSyncWidth;
MsaConfig->Vtm.Timing.F0PVBackPorch =
XVid_VideoTimingModes[VideoMode].Timing.F0PVBackPorch;
/* Calculate the rest of the MSA values. */
XDptx_CfgMsaRecalculate(InstancePtr, Stream);
}
/******************************************************************************/
/**
* This function sets the main stream attribute values in the configuration
* structure to match the preferred timing of the sink monitor. This Preferred
* Timing Mode (PTM) information is stored in the sink's Extended Display
* Identification Data (EDID).
*
* @param InstancePtr is a pointer to the XDptx instance
* @param Stream is the stream number for which the MSA values will be
* used for.
* @param Edid is a pointer to the Edid to use for the specified stream.
*
* @return None.
*
* @note The InstancePtr->MsaConfig structure is modified to reflect the
* main stream attribute values associated to the preferred timing
* of the sink monitor.
*
*******************************************************************************/
void XDptx_CfgMsaUseEdidPreferredTiming(XDptx *InstancePtr, u8 Stream, u8 *Edid)
{
XDptx_MainStreamAttributes *MsaConfig;
u8 *Ptm;
/* Verify arguments. */
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid((Stream == XDPTX_STREAM_ID1) ||
(Stream == XDPTX_STREAM_ID2) || (Stream == XDPTX_STREAM_ID3) ||
(Stream == XDPTX_STREAM_ID4));
Xil_AssertVoid(Edid != NULL);
MsaConfig = &InstancePtr->MsaConfig[Stream - 1];
Ptm = &Edid[XDPTX_EDID_PTM];
/* Configure the MSA values with the PTM information as
* specified by the preferred Detailed Timing Descriptor (DTD) of the
* monitor's EDID.
* Note, the PTM is only required for EDID versions 1.3 a newer. Earlier
* versions may not contain this information. */
u16 HBlank = ((Ptm[XDPTX_EDID_DTD_HRES_HBLANK_U4] &
XDPTX_EDID_DTD_XRES_XBLANK_U4_XBLANK_MASK) << 8) |
Ptm[XDPTX_EDID_DTD_HBLANK_LSB];
u16 VBlank = ((Ptm[XDPTX_EDID_DTD_VRES_VBLANK_U4] &
XDPTX_EDID_DTD_XRES_XBLANK_U4_XBLANK_MASK) << 8) |
Ptm[XDPTX_EDID_DTD_VBLANK_LSB];
MsaConfig->Vtm.Timing.HActive =
(((Ptm[XDPTX_EDID_DTD_HRES_HBLANK_U4] &
XDPTX_EDID_DTD_XRES_XBLANK_U4_XRES_MASK) >>
XDPTX_EDID_DTD_XRES_XBLANK_U4_XRES_SHIFT) << 8) |
Ptm[XDPTX_EDID_DTD_HRES_LSB];
MsaConfig->Vtm.Timing.VActive =
(((Ptm[XDPTX_EDID_DTD_VRES_VBLANK_U4] &
XDPTX_EDID_DTD_XRES_XBLANK_U4_XRES_MASK) >>
XDPTX_EDID_DTD_XRES_XBLANK_U4_XRES_SHIFT) << 8) |
Ptm[XDPTX_EDID_DTD_VRES_LSB];
MsaConfig->Vtm.PixelClkKhz = ((Ptm[XDPTX_EDID_DTD_PIXEL_CLK_KHZ_MSB] <<
8) | Ptm[XDPTX_EDID_DTD_PIXEL_CLK_KHZ_LSB]) * 10;
MsaConfig->Vtm.Timing.HFrontPorch =
(((Ptm[XDPTX_EDID_DTD_XFPORCH_XSPW_U2] &
XDPTX_EDID_DTD_XFPORCH_XSPW_U2_HFPORCH_MASK) >>
XDPTX_EDID_DTD_XFPORCH_XSPW_U2_HFPORCH_SHIFT) << 8) |
Ptm[XDPTX_EDID_DTD_HFPORCH_LSB];
MsaConfig->Vtm.Timing.HSyncWidth =
(((Ptm[XDPTX_EDID_DTD_XFPORCH_XSPW_U2] &
XDPTX_EDID_DTD_XFPORCH_XSPW_U2_HSPW_MASK) >>
XDPTX_EDID_DTD_XFPORCH_XSPW_U2_HSPW_SHIFT) << 8) |
Ptm[XDPTX_EDID_DTD_HSPW_LSB];
MsaConfig->Vtm.Timing.F0PVFrontPorch =
(((Ptm[XDPTX_EDID_DTD_XFPORCH_XSPW_U2] &
XDPTX_EDID_DTD_XFPORCH_XSPW_U2_VFPORCH_MASK) >>
XDPTX_EDID_DTD_XFPORCH_XSPW_U2_VFPORCH_SHIFT) << 8) |
((Ptm[XDPTX_EDID_DTD_VFPORCH_VSPW_L4] &
XDPTX_EDID_DTD_VFPORCH_VSPW_L4_VFPORCH_MASK) >>
XDPTX_EDID_DTD_VFPORCH_VSPW_L4_VFPORCH_SHIFT);
MsaConfig->Vtm.Timing.F0PVSyncWidth =
((Ptm[XDPTX_EDID_DTD_XFPORCH_XSPW_U2] &
XDPTX_EDID_DTD_XFPORCH_XSPW_U2_VSPW_MASK) << 8) |
(Ptm[XDPTX_EDID_DTD_VFPORCH_VSPW_L4] &
XDPTX_EDID_DTD_VFPORCH_VSPW_L4_VSPW_MASK);
MsaConfig->Vtm.Timing.HBackPorch = HBlank -
(MsaConfig->Vtm.Timing.HFrontPorch +
MsaConfig->Vtm.Timing.HSyncWidth);
MsaConfig->Vtm.Timing.F0PVBackPorch = VBlank -
(MsaConfig->Vtm.Timing.F0PVFrontPorch +
MsaConfig->Vtm.Timing.F0PVSyncWidth);
/* Calculate the rest of the MSA values. */
XDptx_CfgMsaRecalculate(InstancePtr, Stream);
}
/******************************************************************************/
/**
* This function takes a the main stream attributes from MsaConfigCustom and
* copies them into InstancePtr->MsaConfig. If desired, given a base set of
* attributes, the rest of the attributes may be derived. The minimal required
* main stream attributes (MSA) that must be contained in the MsaConfigCustom
* structure are:
* - Pixel clock (in KHz)
* - Horizontal sync polarity
* - Vertical sync polarity
* - Horizontal sync pulse width
* - Vertical sync pulse width
* - Horizontal resolution
* - Vertical resolution
* - Vertical back porch
* - Vertical front porch
* - Horizontal back porch
* - Horizontal front porch
*
* @param InstancePtr is a pointer to the XDptx instance.
* @param Stream is the stream number for which the MSA values will be
* used for.
* @param MsaConfigCustom is the structure that will be used to copy the
* main stream attributes from (into InstancePtr->MsaConfig).
* @param Recalculate is a boolean enable that determines whether or not
* the main stream attributes should be recalculated.
*
* @return None.
*
* @note The InstancePtr->MsaConfig structure is modified with the new
* values.
*
*******************************************************************************/
void XDptx_CfgMsaUseCustom(XDptx *InstancePtr, u8 Stream,
XDptx_MainStreamAttributes *MsaConfigCustom, u8 Recalculate)
{
XDptx_MainStreamAttributes *MsaConfig;
/* Verify arguments. */
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid((Stream == XDPTX_STREAM_ID1) ||
(Stream == XDPTX_STREAM_ID2) || (Stream == XDPTX_STREAM_ID3) ||
(Stream == XDPTX_STREAM_ID4));
Xil_AssertVoid(MsaConfigCustom != NULL);
MsaConfig = &InstancePtr->MsaConfig[Stream - 1];
/* Copy the MSA values from the user configuration structure. */
MsaConfig->Vtm.Timing.HActive =
MsaConfigCustom->Vtm.Timing.HActive;
MsaConfig->Vtm.Timing.VActive =
MsaConfigCustom->Vtm.Timing.VActive;
MsaConfig->Vtm.PixelClkKhz = MsaConfigCustom->Vtm.PixelClkKhz;
MsaConfig->Vtm.Timing.HSyncPolarity =
MsaConfigCustom->Vtm.Timing.HSyncPolarity;
MsaConfig->Vtm.Timing.VSyncPolarity =
MsaConfigCustom->Vtm.Timing.VSyncPolarity;
MsaConfig->Vtm.Timing.HFrontPorch =
MsaConfigCustom->Vtm.Timing.HFrontPorch;
MsaConfig->Vtm.Timing.HSyncWidth =
MsaConfigCustom->Vtm.Timing.HSyncWidth;
MsaConfig->Vtm.Timing.HBackPorch =
MsaConfigCustom->Vtm.Timing.HBackPorch;
MsaConfig->Vtm.Timing.F0PVFrontPorch =
MsaConfigCustom->Vtm.Timing.F0PVFrontPorch;
MsaConfig->Vtm.Timing.F0PVSyncWidth =
MsaConfigCustom->Vtm.Timing.F0PVSyncWidth;
MsaConfig->Vtm.Timing.F0PVBackPorch =
MsaConfigCustom->Vtm.Timing.F0PVBackPorch;
if (Recalculate) {
/* Calculate the rest of the MSA values. */
XDptx_CfgMsaRecalculate(InstancePtr, Stream);
}
else {
/* Use the custom values for the rest. */
MsaConfig->TransferUnitSize = MsaConfigCustom->TransferUnitSize;
MsaConfig->UserPixelWidth = MsaConfigCustom->UserPixelWidth;
MsaConfig->NVid = MsaConfigCustom->NVid;
MsaConfig->HStart = MsaConfigCustom->HStart;
MsaConfig->VStart = MsaConfigCustom->VStart;
MsaConfig->HClkTotal = MsaConfigCustom->HClkTotal;
MsaConfig->VClkTotal = MsaConfigCustom->VClkTotal;
MsaConfig->Misc0 = MsaConfigCustom->Misc0;
MsaConfig->Misc1 = MsaConfigCustom->Misc1;
MsaConfig->DataPerLane = MsaConfigCustom->DataPerLane;
MsaConfig->AvgBytesPerTU = MsaConfigCustom->AvgBytesPerTU;
MsaConfig->InitWait = MsaConfigCustom->InitWait;
}
}
/******************************************************************************/
/**
* This function sets the bits per color value of the video stream.
*
* @param InstancePtr is a pointer to the XDptx instance
* @param Stream is the stream number for which to set the color depth.
* @param BitsPerColor is the new number of bits per color to use.
*
* @return None.
*
* @note The InstancePtr->MsaConfig structure is modified to reflect the
* new main stream attributes associated with a new bits per color
* value.
*
*******************************************************************************/
void XDptx_CfgMsaSetBpc(XDptx *InstancePtr, u8 Stream, u8 BitsPerColor)
{
/* Verify arguments. */
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid((Stream == XDPTX_STREAM_ID1) ||
(Stream == XDPTX_STREAM_ID2) || (Stream == XDPTX_STREAM_ID3) ||
(Stream == XDPTX_STREAM_ID4));
Xil_AssertVoid((BitsPerColor == 6) || (BitsPerColor == 8) ||
(BitsPerColor == 10) || (BitsPerColor == 12) ||
(BitsPerColor == 16));
InstancePtr->MsaConfig[Stream - 1].BitsPerColor = BitsPerColor;
/* Calculate the rest of the MSA values. */
XDptx_CfgMsaRecalculate(InstancePtr, Stream);
}
/******************************************************************************/
/**
* This function enables or disables synchronous clock mode for a video stream.
*
* @param InstancePtr is a pointer to the XDptx instance
* @param Stream is the stream number for which to enable or disable
* synchronous clock mode.
* @param Enable if set to 1, will enable synchronous clock mode.
* Otherwise, if set to 0, synchronous clock mode will be disabled.
*
* @return None.
*
* @note None.
*
*******************************************************************************/
void XDptx_CfgMsaEnSynchClkMode(XDptx *InstancePtr, u8 Stream, u8 Enable)
{
XDptx_MainStreamAttributes *MsaConfig;
/* Verify arguments. */
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid((Stream == XDPTX_STREAM_ID1) ||
(Stream == XDPTX_STREAM_ID2) || (Stream == XDPTX_STREAM_ID3) ||
(Stream == XDPTX_STREAM_ID4));
Xil_AssertVoid((Enable == 0) || (Enable == 1));
MsaConfig = &InstancePtr->MsaConfig[Stream - 1];
MsaConfig->SynchronousClockMode = Enable;
if (Enable == 1) {
MsaConfig->Misc0 |= (1 <<
XDPTX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_SHIFT);
}
else {
MsaConfig->Misc0 &= ~(1 <<
XDPTX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_SHIFT);
}
}
/******************************************************************************/
/**
* This function clears the main stream attributes registers of the DisplayPort
* TX core and sets them to the values specified in the main stream attributes
* configuration structure.
*
* @param InstancePtr is a pointer to the XDptx instance
* @param Stream is the stream number for which to set the MSA values for.
*
* @return None.
*
* @note None.
*
*******************************************************************************/
void XDptx_SetVideoMode(XDptx *InstancePtr, u8 Stream)
{
/* Verify arguments. */
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid((Stream == XDPTX_STREAM_ID1) ||
(Stream == XDPTX_STREAM_ID2) || (Stream == XDPTX_STREAM_ID3) ||
(Stream == XDPTX_STREAM_ID4));
XDptx_ClearMsaValues(InstancePtr, Stream);
XDptx_SetMsaValues(InstancePtr, Stream);
}
/******************************************************************************/
/**
* This function clears the main stream attributes registers of the DisplayPort
* TX core.
*
* @param InstancePtr is a pointer to the XDptx instance.
* @param Stream is the stream number for which to clear the MSA values.
*
* @return None.
*
* @note None.
*
*******************************************************************************/
void XDptx_ClearMsaValues(XDptx *InstancePtr, u8 Stream)
{
XDptx_Config *Config;
u32 StreamOffset[4] = {0, XDPTX_STREAM2_MSA_START_OFFSET,
XDPTX_STREAM3_MSA_START_OFFSET, XDPTX_STREAM4_MSA_START_OFFSET};
/* Verify arguments. */
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid((Stream == XDPTX_STREAM_ID1) ||
(Stream == XDPTX_STREAM_ID2) || (Stream == XDPTX_STREAM_ID3) ||
(Stream == XDPTX_STREAM_ID4));
Config = &InstancePtr->Config;
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_HTOTAL +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_VTOTAL +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_POLARITY +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_HSWIDTH +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_VSWIDTH +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_HRES +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_VRES +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_HSTART +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_VSTART +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_MISC0 +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_MISC1 +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_USER_PIXEL_WIDTH +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_USER_DATA_COUNT_PER_LANE +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_M_VID +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_N_VID +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_STREAM1 + (Stream - 1) * 4, 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_TU_SIZE +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MIN_BYTES_PER_TU +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_FRAC_BYTES_PER_TU +
StreamOffset[Stream - 1], 0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_INIT_WAIT +
StreamOffset[Stream - 1], 0);
}
/******************************************************************************/
/**
* This function sets the main stream attributes registers of the DisplayPort TX
* core with the values specified in the main stream attributes configuration
* structure.
*
* @param InstancePtr is a pointer to the XDptx instance.
* @param Stream is the stream number for which to set the MSA values for.
*
* @return None.
*
* @note None.
*
*******************************************************************************/
void XDptx_SetMsaValues(XDptx *InstancePtr, u8 Stream)
{
XDptx_Config *Config;
XDptx_MainStreamAttributes *MsaConfig;
u32 StreamOffset[4] = {0, XDPTX_STREAM2_MSA_START_OFFSET,
XDPTX_STREAM3_MSA_START_OFFSET, XDPTX_STREAM4_MSA_START_OFFSET};
/* Verify arguments. */
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertVoid((Stream == XDPTX_STREAM_ID1) ||
(Stream == XDPTX_STREAM_ID2) || (Stream == XDPTX_STREAM_ID3) ||
(Stream == XDPTX_STREAM_ID4));
Config = &InstancePtr->Config;
MsaConfig = &InstancePtr->MsaConfig[Stream - 1];
/* Set the main stream attributes to the associated DisplayPort TX core
* registers. */
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_HTOTAL +
StreamOffset[Stream - 1], MsaConfig->HClkTotal);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_VTOTAL +
StreamOffset[Stream - 1], MsaConfig->VClkTotal);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_POLARITY +
StreamOffset[Stream - 1],
MsaConfig->Vtm.Timing.HSyncPolarity |
(MsaConfig->Vtm.Timing.VSyncPolarity <<
XDPTX_MAIN_STREAMX_POLARITY_VSYNC_POL_SHIFT));
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_HSWIDTH +
StreamOffset[Stream - 1], MsaConfig->Vtm.Timing.HSyncWidth);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_VSWIDTH +
StreamOffset[Stream - 1], MsaConfig->Vtm.Timing.F0PVSyncWidth);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_HRES +
StreamOffset[Stream - 1],
MsaConfig->Vtm.Timing.HActive);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_VRES +
StreamOffset[Stream - 1],
MsaConfig->Vtm.Timing.VActive);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_HSTART +
StreamOffset[Stream - 1], MsaConfig->HStart);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_VSTART +
StreamOffset[Stream - 1], MsaConfig->VStart);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_MISC0 +
StreamOffset[Stream - 1], MsaConfig->Misc0);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_MISC1 +
StreamOffset[Stream - 1], MsaConfig->Misc1);
XDptx_WriteReg(Config->BaseAddr, XDPTX_M_VID +
StreamOffset[Stream - 1], MsaConfig->Vtm.PixelClkKhz);
XDptx_WriteReg(Config->BaseAddr, XDPTX_N_VID +
StreamOffset[Stream - 1], MsaConfig->NVid);
XDptx_WriteReg(Config->BaseAddr, XDPTX_USER_PIXEL_WIDTH +
StreamOffset[Stream - 1], MsaConfig->UserPixelWidth);
XDptx_WriteReg(Config->BaseAddr, XDPTX_USER_DATA_COUNT_PER_LANE +
StreamOffset[Stream - 1], MsaConfig->DataPerLane);
/* Set the transfer unit values to the associated DisplayPort TX core
* registers. */
if (InstancePtr->MstEnable == 1) {
XDptx_WriteReg(Config->BaseAddr,
XDPTX_STREAM1 + (Stream - 1) * 4,
((MsaConfig->AvgBytesPerTU / 1000) << 16) |
(MsaConfig->AvgBytesPerTU % 1000));
}
XDptx_WriteReg(Config->BaseAddr, XDPTX_TU_SIZE +
StreamOffset[Stream - 1], MsaConfig->TransferUnitSize);
XDptx_WriteReg(Config->BaseAddr, XDPTX_MIN_BYTES_PER_TU +
StreamOffset[Stream - 1], MsaConfig->AvgBytesPerTU / 1000);
XDptx_WriteReg(Config->BaseAddr, XDPTX_FRAC_BYTES_PER_TU +
StreamOffset[Stream - 1], MsaConfig->AvgBytesPerTU % 1000);
XDptx_WriteReg(Config->BaseAddr, XDPTX_INIT_WAIT +
StreamOffset[Stream - 1], MsaConfig->InitWait);
}
/******************************************************************************/
/**
* When the driver is in multi-stream transport (MST) mode, this function will
* make the necessary calculations to describe a stream in MST mode. The key
* values are the payload bandwidth number (PBN), the number of timeslots
* required for allocating the bandwidth, and the average bytes per transfer
* unit (both the integer and the fractional part).
*
* @param InstancePtr is a pointer to the XDptx instance.
* @param Stream is the stream number to make the calculations for.
* @param BitsPerPixel is the number of bits that is used to store one
* pixel.
*
* @return None.
*
* @note None.
*
*******************************************************************************/
static void XDptx_CalculateTs(XDptx *InstancePtr, u8 Stream, u8 BitsPerPixel)
{
XDptx_MainStreamAttributes *MsaConfig =
&InstancePtr->MsaConfig[Stream - 1];
XDptx_LinkConfig *LinkConfig = &InstancePtr->LinkConfig;
double PeakPixelBw;
u32 LinkBw;
double Average_StreamSymbolTimeSlotsPerMTP;
double Target_Average_StreamSymbolTimeSlotsPerMTP;
double MaximumTarget_Average_StreamSymbolTimeSlotsPerMTP;
u32 TsInt;
u32 TsFrac;
PeakPixelBw = ((double)MsaConfig->Vtm.PixelClkKhz / 1000) *
((double)BitsPerPixel / 8);
LinkBw = (LinkConfig->LaneCount * LinkConfig->LinkRate * 27);
/* Calculate the payload bandiwdth number (PBN). */
InstancePtr->MstStreamConfig[Stream - 1].MstPbn =
1.006 * PeakPixelBw * ((double)64 / 54);
/* Ceil - round up if required, avoiding overhead of math.h. */
if ((double)(1.006 * PeakPixelBw * ((double)64 / 54)) >
((double)InstancePtr->MstStreamConfig[Stream - 1].MstPbn)) {
InstancePtr->MstStreamConfig[Stream - 1].MstPbn++;
}
/* Calculate the average stream symbol time slots per MTP. */
Average_StreamSymbolTimeSlotsPerMTP = (64.0 * PeakPixelBw / LinkBw);
MaximumTarget_Average_StreamSymbolTimeSlotsPerMTP = (54.0 *
((double)InstancePtr->MstStreamConfig[Stream - 1].MstPbn /
LinkBw));
/* The target value to be found needs to follow the condition:
* Average_StreamSymbolTimeSlotsPerMTP <=
* Target_Average_StreamSymbolTimeSlotsPerMTP
* >= MaximumTarget_Average_StreamSymbolTimeSlotsPerMTP
* Obtain the greatest target value that satisfies the above condition
* and still a multiple of 1/TsFrac_Denominator.
* Note: TsFrac_Denominator = 8. */
/* Round down. */
Target_Average_StreamSymbolTimeSlotsPerMTP =
(u32)Average_StreamSymbolTimeSlotsPerMTP;
/* Find the greatest multiple that is less than the maximum. */
Target_Average_StreamSymbolTimeSlotsPerMTP += ((1.0 / 8.0) * (u32)(8.0 *
(MaximumTarget_Average_StreamSymbolTimeSlotsPerMTP -
Target_Average_StreamSymbolTimeSlotsPerMTP)));
/* Determine the integer and the fractional part of the number of time
* slots that will be allocated for the stream. */
TsInt = Target_Average_StreamSymbolTimeSlotsPerMTP;
TsFrac = (((double)Target_Average_StreamSymbolTimeSlotsPerMTP * 1000) -
(TsInt * 1000));
/* Store TsInt and TsFrac in AvgBytesPerTU. */
MsaConfig->AvgBytesPerTU = TsInt * 1000 + TsFrac;
/* Set the number of time slots to allocate for this stream. */
MsaConfig->TransferUnitSize = TsInt;
if (TsFrac != 0) {
/* Round up. */
MsaConfig->TransferUnitSize++;
}
if ((InstancePtr->Config.PayloadDataWidth == 4) &&
(MsaConfig->TransferUnitSize % 4) != 0) {
/* Set to a multiple of 4 boundary. */
MsaConfig->TransferUnitSize += (4 -
(MsaConfig->TransferUnitSize % 4));
}
else if ((MsaConfig->TransferUnitSize % 2) != 0) {
/* Set to an even boundary. */
MsaConfig->TransferUnitSize++;
}
/* Determine the PBN for the stream. */
InstancePtr->MstStreamConfig[Stream - 1].MstPbn =
MsaConfig->TransferUnitSize *
(LinkConfig->LaneCount * LinkConfig->LinkRate / 2);
}