diff --git a/XilinxProcessorIPLib/drivers/dp/data/dependencies.props b/XilinxProcessorIPLib/drivers/dp/data/dependencies.props new file mode 100644 index 00000000..17983bbf --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/data/dependencies.props @@ -0,0 +1,7 @@ +xdp_selftest_example.c=xdp_selftest_example.c +xdp_rx_intr_timer_example.c=xdp_rx_intr_timer_example.c +xdp_tx_audio_example.c=xdp_tx_example_common.h,xdp_tx_example_common.c +xdp_tx_intr_example.c=xdp_tx_example_common.h,xdp_tx_example_common.c +xdp_tx_mst_example.c=xdp_tx_example_common.h,xdp_tx_example_common.c +xdp_tx_poll_example.c=xdp_tx_example_common.h,xdp_tx_example_common.c +xdp_tx_timer_example.c=xdp_tx_example_common.h,xdp_tx_example_common.c diff --git a/XilinxProcessorIPLib/drivers/dp/data/dp.mdd b/XilinxProcessorIPLib/drivers/dp/data/dp.mdd new file mode 100644 index 00000000..36973878 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/data/dp.mdd @@ -0,0 +1,42 @@ +##****************************************************************************** +## +## 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 +## 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. +## +##*****************************************************************************/ + +OPTION psf_version = 2.1; + +BEGIN driver dp + OPTION supported_peripherals = (displayport); + OPTION driver_state = ACTIVE; + OPTION depends = (video_common_v1_0); + OPTION copyfiles = all; + OPTION VERSION = 1.0; + OPTION NAME = dp; +END driver diff --git a/XilinxProcessorIPLib/drivers/dp/data/dp.tcl b/XilinxProcessorIPLib/drivers/dp/data/dp.tcl new file mode 100644 index 00000000..6ee4a780 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/data/dp.tcl @@ -0,0 +1,186 @@ +##****************************************************************************** +## +## 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 +## 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. +## +##*****************************************************************************/ +proc generate {drv_handle} { + xdefine_include_file $drv_handle "xparameters.h" "XDp" "NUM_INSTANCES" "DEVICE_ID" "C_BASEADDR" "C_LANE_COUNT" "C_LINK_RATE" "C_MAX_BITS_PER_COLOR" "C_QUAD_PIXEL_ENABLE" "C_DUAL_PIXEL_ENABLE" "C_YCRCB_ENABLE" "C_YONLY_ENABLE" "C_GT_DATAWIDTH" "C_SECONDARY_SUPPORT" "C_AUDIO_CHANNELS" "C_MST_ENABLE" "C_NUMBER_OF_MST_STREAMS" "C_PROTOCOL_SELECTION" "C_FLOW_DIRECTION" "S_AXI_ACLK" + ::hsi::utils::define_config_file $drv_handle "xdp_g.c" "XDp" "DEVICE_ID" "C_BASEADDR" "S_AXI_ACLK" "C_LANE_COUNT" "C_LINK_RATE" "C_MAX_BITS_PER_COLOR" "C_QUAD_PIXEL_ENABLE" "C_DUAL_PIXEL_ENABLE" "C_YCRCB_ENABLE" "C_YONLY_ENABLE" "C_GT_DATAWIDTH" "C_SECONDARY_SUPPORT" "C_AUDIO_CHANNELS" "C_MST_ENABLE" "C_NUMBER_OF_MST_STREAMS" "C_PROTOCOL_SELECTION" "C_FLOW_DIRECTION" + xdefine_canonical_xpars $drv_handle "xparameters.h" "XDp" "NUM_INSTANCES" "DEVICE_ID" "C_BASEADDR" "C_LANE_COUNT" "C_LINK_RATE" "C_MAX_BITS_PER_COLOR" "C_QUAD_PIXEL_ENABLE" "C_DUAL_PIXEL_ENABLE" "C_YCRCB_ENABLE" "C_YONLY_ENABLE" "C_GT_DATAWIDTH" "C_SECONDARY_SUPPORT" "C_AUDIO_CHANNELS" "C_MST_ENABLE" "C_NUMBER_OF_MST_STREAMS" "C_PROTOCOL_SELECTION" "C_FLOW_DIRECTION" "S_AXI_ACLK" +} + +# +# Given a list of arguments, define them all in an include file. +# Handles IP model/user parameters, as well as the special parameters NUM_INSTANCES, +# DEVICE_ID +# Will not work for a processor. +# +proc xdefine_include_file {drv_handle file_name drv_string args} { + set args [get_exact_arg_list $args] + # Open include file + set file_handle [xopen_include_file $file_name] + + # Get all peripherals connected to this driver + set periphs [xget_sw_iplist_for_driver $drv_handle] + + # Handle special cases + set arg "NUM_INSTANCES" + set posn [lsearch -exact $args $arg] + if {$posn > -1} { + puts $file_handle "/* Definitions for driver [string toupper [get_property name $drv_handle]] */" + # Define NUM_INSTANCES + puts $file_handle "#define [xget_dname $drv_string $arg] [llength $periphs]" + set args [lreplace $args $posn $posn] + } + + # Check if it is a driver parameter + lappend newargs + foreach arg $args { + set value [get_property CONFIG.$arg $drv_handle] + if {[llength $value] == 0} { + lappend newargs $arg + } else { + puts $file_handle "#define [xget_dname $drv_string $arg] [get_property $arg $drv_handle]" + } + } + set args $newargs + + # Print all parameters for all peripherals + set device_id 0 + foreach periph $periphs { + puts $file_handle "" + puts $file_handle "/* Definitions for peripheral [string toupper [get_property NAME $periph]] */" + + foreach arg $args { + if {[string compare -nocase "DEVICE_ID" $arg] == 0} { + set value $device_id + incr device_id + } elseif {[string compare -nocase "S_AXI_ACLK" $arg] == 0} { + set freq [xget_ip_clk_pin_freq $periph $arg] + if {[llength $freq] == 0} { + set freq 0 + puts "WARNING: Clock frequency information is not available in the design, \ + for peripheral $periph_name. This will not work." + } + set value $freq + } else { + set value [get_property CONFIG.$arg $periph] + } + if {[llength $value] == 0} { + set value 0 + } + set value [xformat_addr_string $value $arg] + if {[string compare -nocase "HW_VER" $arg] == 0} { + puts $file_handle "#define [xget_name $periph $arg] \"$value\"" + } else { + puts $file_handle "#define [xget_name $periph $arg] $value" + } + } + puts $file_handle "" + } + puts $file_handle "\n/******************************************************************/\n" + close $file_handle +} + +# +# xdefine_canonical_xpars - Used to print out canonical defines for a driver. +# Given a list of arguments, define each as a canonical constant name, using +# the driver name, in an include file. +# +proc xdefine_canonical_xpars {drv_handle file_name drv_string args} { + set args [get_exact_arg_list $args] + # Open include file + set file_handle [xopen_include_file $file_name] + + # Get all the peripherals connected to this driver + set periphs [xget_sw_iplist_for_driver $drv_handle] + + # Get the names of all the peripherals connected to this driver + foreach periph $periphs { + set peripheral_name [string toupper [get_property NAME $periph]] + lappend peripherals $peripheral_name + } + + # Get possible canonical names for all the peripherals connected to this + # driver + set device_id 0 + foreach periph $periphs { + set canonical_name [string toupper [format "%s_%s" $drv_string $device_id]] + lappend canonicals $canonical_name + + # Create a list of IDs of the peripherals whose hardware instance name + # doesn't match the canonical name. These IDs can be used later to + # generate canonical definitions + if { [lsearch $peripherals $canonical_name] < 0 } { + lappend indices $device_id + } + incr device_id + } + + set i 0 + foreach periph $periphs { + set periph_name [string toupper [get_property NAME $periph]] + + # Generate canonical definitions only for the peripherals whose + # canonical name is not the same as hardware instance name + if { [lsearch $canonicals $periph_name] < 0 } { + puts $file_handle "/* Canonical definitions for peripheral $periph_name */" + set canonical_name [format "%s_%s" $drv_string [lindex $indices $i]] + + foreach arg $args { + set lvalue [xget_dname $canonical_name $arg] + + # The commented out rvalue is the name of the instance-specific constant + # set rvalue [xget_name $periph $arg] + # The rvalue set below is the actual value of the parameter + if {[string compare -nocase "S_AXI_ACLK" $arg] == 0} { + set freq [xget_ip_clk_pin_freq $periph $arg] + if {[llength $freq] == 0} { + set freq 0 + puts "WARNING: Clock frequency information is not available in the design, \ + for peripheral $periph_name. This will not work." + } + set rvalue $freq + } else { + set rvalue [xget_param_value $periph $arg] + if {[llength $rvalue] == 0} { + set rvalue 0 + } + set rvalue [xformat_addr_string $rvalue $arg] + } + puts $file_handle "#define $lvalue $rvalue" + } + puts $file_handle "" + incr i + } + } + + puts $file_handle "\n/******************************************************************/\n" + close $file_handle +} diff --git a/XilinxProcessorIPLib/drivers/dp/examples/index.html b/XilinxProcessorIPLib/drivers/dp/examples/index.html new file mode 100755 index 00000000..dfb8defd --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/examples/index.html @@ -0,0 +1,23 @@ + + +
+ + +Copyright © 1995-2015 Xilinx, Inc. All rights reserved.
+ + diff --git a/XilinxProcessorIPLib/drivers/dp/examples/readme.txt b/XilinxProcessorIPLib/drivers/dp/examples/readme.txt new file mode 100644 index 00000000..98cfaec6 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/examples/readme.txt @@ -0,0 +1,76 @@ +There is 1 DisplayPort RX example included in this directory: +1) xdp_rx_intr_timer_example.c : This interrupt with timer example shows how to + set up both the interrupt system with interrupt handlers and how to override + the default sleep/delay functionality for MicroBlaze. A timer needs to exist + in the hardware system and will be used for sleep/delay functionality inside + of a callback function. The default behavior in MicroBlaze for sleep/delay is + to call MB_Sleep from microblaze_sleep.h, which has only millisecond + accuracy. For ARM/Zynq SoC systems, the supplied callback function will be + ignored - the usleep function will be called since the SoC has a timer + built-in. + +Note: All example functions start with Dprx_*, while all driver functions start +with XDp_*. + +There are 6 DisplayPort TX examples included in this directory: +1) xdp_tx_audio_example.c : This audio example, apart from training the main + link and outputting video, illustrates the sequence required for setting up + audio in the DisplayPort TX. This example requires that an audio source, such + as a S/PDIF instance be present and connected to the DisplayPort TX in the + hardware system, and for the audio enable configuration parameter to be set + for the instantiated DisplayPort TX. For audio to output, the user will need + to implement the following functions: + a) Dptx_ConfigureAudioSrc : This function needs to configure the audio source + to output to the DisplayPort TX. + b) Dptx_AudioSendInfoFrame : This function needs to set up and write an audio + info frame as per user requirements. + +2) xdp_tx_intr_example.c : This interrupt example shows how to set up the + interrupt system and specify the interrupt handlers for when a DisplayPort + interrupt event occurs. An interrupt controller with a connection to the + DisplayPort interrupt signal needs to exist in the hardware system. + +3) xdp_tx_mst_example.c : This multi-stream transport (MST) example shows how to + use the driver's MST capabilities. Streams can be directed at sinks using two + methods: + a) After topology discover has created a sink list, streams may be assigned + to sinks using the index in the sink list. + b) The streams may be assigned to sinks directly without using topology + discovery if their relative addresses (and total number of DisplayPort + links) from the DisplayPort source is known beforehand. + +4) xdp_tx_poll_example.c : This interrupt example shows how to poll the + DisplayPort TX instance's registers for DisplayPort interrupt events. + +5) xdp_tx_timer_example.c : This timer example shows how to override the default + sleep/delay functionality for MicroBlaze. A timer needs to exist in the + hardware system and will be used for sleep/delay functionality inside of a + callback function. The default behavior in MicroBlaze for sleep/delay is to + call MB_Sleep from microblaze_sleep.h, which has only millisecond accuracy. + For ARM/Zynq SoC systems, the supplied callback function will be ignored - + the usleep function will be called since the SoC has a timer built-in. + +6) xdp_tx_selftest_example.c : This self test example will perform a sanity + check on the state of the DisplayPort TX instance. It may be called prior to + usage of the core or after a reset to ensure that (a subset of) the registers + hold their default values. + +Each of these examples are meant to be used in conjunction with +xdp_tx_example_common.[ch] which holds common functionality for all examples. +After importing the examples, these files will need to be manually copied into +the example src/ directory. +This code shows how to train the main link and set up a video stream. + +Additionally, in order to be able to use the interrupt, polling, and timer +examples, the user will need to implement and link the following functions: +1) Dptx_InitPlatform : This function needs to do all hardware system + initialization. +2) Dptx_StreamSrc* : These function need to configure the source of the stream + (pattern generators, video input, etc.) such that a video stream, with + timings and video attributes that correspond to the main stream attributes + (MSA) configuration, is received by the DisplayPort Tx. The examples call + this function from the Dptx_Run->Dptx_StartVideoStream functions in + xdp_tx_example_common.c. + +Note: All example functions start with Dptx_*, while all driver functions start +with XDp_*. diff --git a/XilinxProcessorIPLib/drivers/dp/examples/xdp_rx_intr_timer_example.c b/XilinxProcessorIPLib/drivers/dp/examples/xdp_rx_intr_timer_example.c new file mode 100644 index 00000000..a27fe138 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/examples/xdp_rx_intr_timer_example.c @@ -0,0 +1,713 @@ +/******************************************************************************* + * + * 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 xdp_rx_intr_timer_example.c + * + * Contains a design example using the XDp driver with a user-defined hook + * for delay. The reasoning behind this is that MicroBlaze sleep is not very + * accurate without a hardware timer. For systems that have a hardware timer, + * the user may override the default MicroBlaze sleep with a function that will + * use the hardware timer. + * Also, this example sets up the interrupt controller and defines handlers for + * various interrupt types. In this way, the RX interrupt handler will arbitrate + * the different interrupts to their respective interrupt handlers defined in + * this example. + * This example will print out the detected resolution of the incoming + * DisplayPort video stream. + * This example is meant to take in the incoming DisplayPort video stream and + * pass it through using the Dprd_Vidpipe* functions which are left for the user + * to implement. + * + * @note This example requires an AXI timer in the system. + * @note For this example to work, the user will need to implement + * initialization of the system (Dprx_PlatformInit) as this is + * system-specific. + * @note For this example to display output, the user will need to + * implement the Dprx_Vidpipe* functions which configure and + * reset the video pipeline as required as this is system-specific. + * + *+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial creation. + *+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdp.h" +#include "xparameters.h" +#ifdef XPAR_INTC_0_DEVICE_ID +/* For MicroBlaze systems. */ +#include "xintc.h" +#else +/* For ARM/Zynq SoC systems. */ +#include "xscugic.h" +#endif /* XPAR_INTC_0_DEVICE_ID */ +#include "xtmrctr.h" + +/**************************** Constant Definitions ****************************/ + +/* The following constants map to the XPAR parameters created in the + * xparameters.h file. */ +#define DPRX_DEVICE_ID XPAR_DISPLAYPORT_0_DEVICE_ID +#ifdef XPAR_INTC_0_DEVICE_ID +#define DP_INTERRUPT_ID \ +XPAR_PROCESSOR_SUBSYSTEM_INTERCONNECT_AXI_INTC_1_DISPLAYPORT_0_AXI_INT_INTR +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID +#else +#define DP_INTERRUPT_ID XPAR_FABRIC_DISPLAYPORT_0_AXI_INT_INTR +#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID +#endif /* XPAR_INTC_0_DEVICE_ID */ + +/****************************** Type Definitions ******************************/ + +/* Depending on whether the system is a MicroBlaze or ARM/Zynq SoC system, + * different drivers and associated types will be used. */ +#ifdef XPAR_INTC_0_DEVICE_ID +#define INTC XIntc +#define INTC_HANDLER XIntc_InterruptHandler +#else +#define INTC XScuGic +#define INTC_HANDLER XScuGic_InterruptHandler +#endif /* XPAR_INTC_0_DEVICE_ID */ + +/**************************** Function Prototypes *****************************/ + +u32 Dprx_IntrTimerExample(XDp *InstancePtr, u16 DeviceId, INTC *IntcPtr, + u16 IntrId, u16 DpIntrId, XTmrCtr *TimerCounterPtr); +static u32 Dprx_SetupExample(XDp *InstancePtr, u16 DeviceId); +static u32 Dprx_SetupInterruptHandler(XDp *InstancePtr, INTC *IntcPtr, + u16 IntrId, u16 DpIntrId); +static void Dprx_CustomWaitUs(void *InstancePtr, u32 MicroSeconds); +static void Dprx_ResetVideoOutput(void *InstancePtr); +static void Dprx_DetectResolution(void *InstancePtr); +static void Dprx_InterruptHandlerVmChange(void *InstancePtr); +static void Dprx_InterruptHandlerPowerState(void *InstancePtr); +static void Dprx_InterruptHandlerNoVideo(void *InstancePtr); +static void Dprx_InterruptHandlerVBlank(void *InstancePtr); +static void Dprx_InterruptHandlerTrainingLost(void *InstancePtr); +static void Dprx_InterruptHandlerVideo(void *InstancePtr); +static void Dprx_InterruptHandlerTrainingDone(void *InstancePtr); +static void Dprx_InterruptHandlerBwChange(void *InstancePtr); +static void Dprx_InterruptHandlerTp1(void *InstancePtr); +static void Dprx_InterruptHandlerTp2(void *InstancePtr); +static void Dprx_InterruptHandlerTp3(void *InstancePtr); + +extern void Dprx_VidpipeConfig(XDp *InstancePtr); +extern void Dprx_VidpipeReset(void); + +/*************************** Variable Declarations ****************************/ + +XDp DpInstance; /* The Dp instance. */ +INTC IntcInstance; /* The interrupt controller instance. */ +XTmrCtr TimerCounterInst; /* The timer counter instance. */ + +/* Used by interrupt handlers. */ +u8 VBlankEnable; +u8 VBlankCount; + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function is the main function of the XDp (operating in RX mode) + * interrupt with timer example. If the Dprx_IntrTimerExample function, which + * sets up the system succeeds, this function will wait for interrupts. + * + * @param None. + * + * @return + * - XST_FAILURE if the interrupt example was unsuccessful - system + * setup failed. + * + * @note Unless setup failed, main will never return since + * Dprx_IntrTimerExample is blocking. + * +*******************************************************************************/ +int main(void) +{ + u32 Status; + + /* Run the XDp (in RX mode) interrupt with timer example. */ + Status = Dprx_IntrTimerExample(&DpInstance, DPRX_DEVICE_ID, + &IntcInstance, INTC_DEVICE_ID, DP_INTERRUPT_ID, + &TimerCounterInst); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * The main entry point for the interrupt with timer example using the XDp + * driver. This function will set up the system, interrupt controller and + * interrupt handlers, and the custom sleep handler. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param DeviceId is the unique device ID of the DisplayPort RX core + * instance. + * @param IntcPtr is a pointer to the interrupt instance. + * @param IntrId is the unique device ID of the interrupt controller. + * @param DpIntrId is the interrupt ID of the DisplayPort RX connection to + * the interrupt controller. + * @param TimerCounterPtr is a pointer to the timer instance. + * + * @return + * - XST_SUCCESS if the system was set up correctly and link + * training was successful. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 Dprx_IntrTimerExample(XDp *InstancePtr, u16 DeviceId, INTC *IntcPtr, + u16 IntrId, u16 DpIntrId, XTmrCtr *TimerCounterPtr) +{ + u32 Status; + + /* Do platform initialization here. This is hardware system specific - + * it is up to the user to implement this function. */ + Dprx_PlatformInit(InstancePtr); + /*******************/ + + Status = Dprx_SetupExample(InstancePtr, DeviceId); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* Set a custom timer handler for improved delay accuracy on MicroBlaze + * systems since the driver does not assume/have a dependency on the + * system having a timer in the FPGA. + * Note: This only has an affect for MicroBlaze systems since the Zynq + * ARM SoC contains a timer, which is used when the driver calls the + * delay function. */ + XDp_SetUserTimerHandler(InstancePtr, &Dprx_CustomWaitUs, + TimerCounterPtr); + + /* Setup interrupt handling in the system. */ + Status = Dprx_SetupInterruptHandler(InstancePtr, IntcPtr, IntrId, + DpIntrId); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* Do not return in order to allow interrupt handling to run. */ + while (1); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will setup and initialize the DisplayPort RX core. The core's + * configuration parameters will be retrieved based on the configuration + * to the DisplayPort RX core instance with the specified device ID. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param DeviceId is the unique device ID of the DisplayPort RX core + * instance. + * + * @return + * - XST_SUCCESS if the device configuration was found and obtained + * and if the main link was successfully established. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 Dprx_SetupExample(XDp *InstancePtr, u16 DeviceId) +{ + XDp_Config *ConfigPtr; + u32 Status; + + /* Obtain the device configuration for the DisplayPort RX core. */ + ConfigPtr = XDp_LookupConfig(DeviceId); + if (!ConfigPtr) { + return XST_FAILURE; + } + /* Copy the device configuration into the InstancePtr's Config + * structure. */ + XDp_CfgInitialize(InstancePtr, ConfigPtr, ConfigPtr->BaseAddr); + + XDp_RxSetLaneCount(InstancePtr, InstancePtr->Config.MaxLaneCount); + XDp_RxSetLinkRate(InstancePtr, InstancePtr->Config.MaxLinkRate); + + /* Initialize the DisplayPort RX core. */ + Status = XDp_Initialize(InstancePtr); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function sets up the interrupt system such that interrupts caused by + * Hot-Plug-Detect (HPD) events and pulses are handled. This function is + * application-specific for systems that have an interrupt controller connected + * to the processor. The user should modify this function to fit the + * application. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param IntcPtr is a pointer to the interrupt instance. + * @param IntrId is the unique device ID of the interrupt controller. + * @param DpIntrId is the interrupt ID of the DisplayPort RX connection to + * the interrupt controller. + * + * @return + * - XST_SUCCESS if the interrupt system was successfully set up. + * - XST_FAILURE otherwise. + * + * @note An interrupt controller must be present in the system, connected + * to the processor and the DisplayPort RX core. + * +*******************************************************************************/ +static u32 Dprx_SetupInterruptHandler(XDp *InstancePtr, INTC *IntcPtr, + u16 IntrId, u16 DpIntrId) +{ + u32 Status; + + /* Set the HPD interrupt handlers. */ + XDp_RxSetIntrVmChangeHandler(InstancePtr, + Dprx_InterruptHandlerVmChange, InstancePtr); + XDp_RxSetIntrPowerStateHandler(InstancePtr, + Dprx_InterruptHandlerPowerState, InstancePtr); + XDp_RxSetIntrNoVideoHandler(InstancePtr, + Dprx_InterruptHandlerNoVideo, InstancePtr); + XDp_RxSetIntrVBlankHandler(InstancePtr, + Dprx_InterruptHandlerVBlank, InstancePtr); + XDp_RxSetIntrTrainingLostHandler(InstancePtr, + Dprx_InterruptHandlerTrainingLost, InstancePtr); + XDp_RxSetIntrVideoHandler(InstancePtr, + Dprx_InterruptHandlerVideo, InstancePtr); + XDp_RxSetIntrTrainingDoneHandler(InstancePtr, + Dprx_InterruptHandlerTrainingDone, InstancePtr); + XDp_RxSetIntrBwChangeHandler(InstancePtr, + Dprx_InterruptHandlerBwChange, InstancePtr); + XDp_RxSetIntrTp1Handler(InstancePtr, + Dprx_InterruptHandlerTp1, InstancePtr); + XDp_RxSetIntrTp2Handler(InstancePtr, + Dprx_InterruptHandlerTp2, InstancePtr); + XDp_RxSetIntrTp3Handler(InstancePtr, + Dprx_InterruptHandlerTp3, InstancePtr); + + /* Initialize interrupt controller driver. */ +#ifdef XPAR_INTC_0_DEVICE_ID + Status = XIntc_Initialize(IntcPtr, IntrId); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } +#else + XScuGic_Config *IntcConfig; + + IntcConfig = XScuGic_LookupConfig(IntrId); + Status = XScuGic_CfgInitialize(IntcPtr, IntcConfig, + IntcConfig->CpuBaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + XScuGic_SetPriorityTriggerType(IntcPtr, DpIntrId, 0xA0, 0x1); +#endif /* XPAR_INTC_0_DEVICE_ID */ + + /* Connect the device driver handler that will be called when an + * interrupt for the device occurs, the handler defined above performs + * the specific interrupt processing for the device. */ +#ifdef XPAR_INTC_0_DEVICE_ID + Status = XIntc_Connect(IntcPtr, DpIntrId, + (XInterruptHandler)XDp_InterruptHandler, InstancePtr); +#else + Status = XScuGic_Connect(IntcPtr, DpIntrId, + (Xil_InterruptHandler)XDp_InterruptHandler, InstancePtr); +#endif /* XPAR_INTC_0_DEVICE_ID */ + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* Start the interrupt controller. */ +#ifdef XPAR_INTC_0_DEVICE_ID + Status = XIntc_Start(IntcPtr, XIN_REAL_MODE); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + XIntc_Enable(IntcPtr, DpIntrId); +#else + XScuGic_Enable(IntcPtr, DpIntrId); +#endif /* XPAR_INTC_0_DEVICE_ID */ + + /* Initialize the exception table. */ + Xil_ExceptionInit(); + + /* Register the interrupt controller handler with the exception + * table. */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)INTC_HANDLER, IntcPtr); + + /* Enable exceptions. */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function is used to override the driver's default sleep functionality. + * For MicroBlaze systems, the XDp_WaitUs driver function's default behavior + * is to use the MB_Sleep function from microblaze_sleep.h, which is implemented + * in software and only has millisecond accuracy. For this reason, using a + * hardware timer is preferrable. For ARM/Zynq SoC systems, the SoC's timer is + * used - XDp_WaitUs will ignore this custom timer handler. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note Use the XDp_SetUserTimerHandler driver function to set this + * function as the handler for when the XDp_WaitUs driver + * function is called. + * +*******************************************************************************/ +static void Dprx_CustomWaitUs(void *InstancePtr, u32 MicroSeconds) +{ + XDp *XDp_InstancePtr = (XDp *)InstancePtr; + u32 TimerVal; + + XTmrCtr_Start(XDp_InstancePtr->UserTimerPtr, 0); + + /* Wait specified number of useconds. */ + do { + TimerVal = XTmrCtr_GetValue(XDp_InstancePtr->UserTimerPtr, 0); + } + while (TimerVal < (MicroSeconds * + (XDp_InstancePtr->Config.SAxiClkHz / 1000000))); + + XTmrCtr_Stop(XDp_InstancePtr->UserTimerPtr, 0); +} + +/******************************************************************************/ +/** + * This function is used to reset video output for this example. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void Dprx_ResetVideoOutput(void *InstancePtr) +{ + xil_printf("\tDisabling the display timing generator.\n"); + XDp_RxDtgDis(InstancePtr); + + xil_printf("\tResetting the video output pipeline.\n"); + /* This is hardware system specific - it is up to the user to implement + * this function if needed. */ + Dprx_VidpipeReset(); + /*******************/ + + xil_printf("\tConfiguring the video output pipeline.\n"); + /* This is hardware system specific - it is up to the user to implement + * this function if needed. */ + Dprx_VidpipeConfig(InstancePtr); + /*******************/ + + xil_printf("\tRe-enabling the display timing generator.\n"); + XDp_RxDtgEn(InstancePtr); +} + +/******************************************************************************/ +/** + * This function will present the resolution of the incoming video stream. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note The resolution will be rounded up to the nearest resolution + * present in the XVidC_VideoTimingModes table. + * +*******************************************************************************/ +static void Dprx_DetectResolution(void *InstancePtr) +{ + u32 DpHres, DpVres; + u32 GetResCount = 0; + + do { + DpHres = (XDp_ReadReg(((XDp *)InstancePtr)->Config.BaseAddr, + XDP_RX_MSA_HRES)); + DpVres = (XDp_ReadReg(((XDp *)InstancePtr)->Config.BaseAddr, + XDP_RX_MSA_VHEIGHT)); + GetResCount++; + XDp_WaitUs(InstancePtr, 1000); + } while (((DpHres == 0) || (DpVres == 0)) && (GetResCount < 2000)); + + xil_printf("\n*** Detected resolution: %d x %d ***\n", DpHres, DpVres); +} + +/******************************************************************************/ +/** + * This function is the callback function for when a video mode chang interrupt + * occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void Dprx_InterruptHandlerVmChange(void *InstancePtr) +{ + u32 Status; + + xil_printf("> Interrupt: video mode change.\n"); + + Status = XDp_RxCheckLinkStatus(InstancePtr); + if ((Status == XST_SUCCESS) && (VBlankCount >= 20)) { + Dprx_ResetVideoOutput(InstancePtr); + Dprx_DetectResolution(InstancePtr); + } +} + +/******************************************************************************/ +/** + * This function is the callback function for when the power state interrupt + * occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void Dprx_InterruptHandlerPowerState(void *InstancePtr) +{ + xil_printf("> Interrupt: power state change request.\n"); +} + +/******************************************************************************/ +/** + * This function is the callback function for when a no video interrupt occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void Dprx_InterruptHandlerNoVideo(void *InstancePtr) +{ + xil_printf("> Interrupt: no-video flags in the VBID field after active " + "video has been received.\n"); +} + +/******************************************************************************/ +/** + * This function is the callback function for when a vertical blanking interrupt + * occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void Dprx_InterruptHandlerVBlank(void *InstancePtr) +{ + u32 Status; + + if (VBlankEnable) { + VBlankCount++; + + xil_printf("> Interrupt: vertical blanking (frame %d).\n", + VBlankCount); + + /* Wait until 20 frames have been received before forwarding or + * outputting any video stream. */ + if (VBlankCount >= 20) { + VBlankEnable = 0; + XDp_RxInterruptDisable(InstancePtr, + XDP_RX_INTERRUPT_MASK_VBLANK_MASK); + + Status = XDp_RxCheckLinkStatus(InstancePtr); + if (Status == XST_SUCCESS) { + Dprx_ResetVideoOutput(InstancePtr); + Dprx_DetectResolution(InstancePtr); + } + } + } +} + +/******************************************************************************/ +/** + * This function is the callback function for when a training lost interrupt + * occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void Dprx_InterruptHandlerTrainingLost(void *InstancePtr) +{ + xil_printf("> Interrupt: training lost.\n"); + + /* Re-enable vertical blanking interrupt and counter. */ + VBlankEnable = 1; + XDp_RxInterruptEnable(InstancePtr, XDP_RX_INTERRUPT_MASK_VBLANK_MASK); + VBlankCount = 0; + + xil_printf("\tDisabling the display timing generator.\n"); + XDp_RxDtgDis(InstancePtr); + xil_printf("\tResetting the video output pipeline.\n"); + /* This is hardware system specific - it is up to the user to implement + * this function if needed. */ + Dprx_VidpipeReset(); + /*******************/ +} + +/******************************************************************************/ +/** + * This function is the callback function for when a valid video interrupt + * occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void Dprx_InterruptHandlerVideo(void *InstancePtr) +{ + xil_printf("> Interrupt: a valid video frame is detected on main " + "link.\n"); +} + +/******************************************************************************/ +/** + * This function is the callback function for when a training done interrupt + * occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void Dprx_InterruptHandlerTrainingDone(void *InstancePtr) +{ + xil_printf("> Interrupt: training done.\n"); +} + +/******************************************************************************/ +/** + * This function is the callback function for when a bandwidth change interrupt + * occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void Dprx_InterruptHandlerBwChange(void *InstancePtr) +{ + xil_printf("> Interrupt: bandwidth change.\n"); +} + +/******************************************************************************/ +/** + * This function is the callback function for when a training pattern 1 + * interrupt occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void Dprx_InterruptHandlerTp1(void *InstancePtr) +{ + xil_printf("> Interrupt: training pattern 1.\n"); +} + +/******************************************************************************/ +/** + * This function is the callback function for when a training pattern 2 + * interrupt occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void Dprx_InterruptHandlerTp2(void *InstancePtr) +{ + xil_printf("> Interrupt: training pattern 2.\n"); +} + +/******************************************************************************/ +/** + * This function is the callback function for when a training pattern 3 + * interrupt occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void Dprx_InterruptHandlerTp3(void *InstancePtr) +{ + xil_printf("> Interrupt: training pattern 3.\n"); +} diff --git a/XilinxProcessorIPLib/drivers/dp/examples/xdp_selftest_example.c b/XilinxProcessorIPLib/drivers/dp/examples/xdp_selftest_example.c new file mode 100644 index 00000000..6ef01067 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/examples/xdp_selftest_example.c @@ -0,0 +1,137 @@ +/******************************************************************************* + * + * Copyright (C) 2014 - 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 xdp_selftest_example.c + * + * Contains a design example using the XDp driver. It performs a self test on + * the DisplayPort TX/RX core that will compare many of the DisplayPort core's + * registers against their default reset values. + * + * @note None. + * + *
+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial creation. + *+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdp.h" +#include "xparameters.h" + +/**************************** Constant Definitions ****************************/ + +#define DP_DEVICE_ID XPAR_DISPLAYPORT_0_DEVICE_ID + +/**************************** Function Prototypes *****************************/ + +u32 Dp_SelfTestExample(XDp *InstancePtr, u16 DeviceId); + +/*************************** Variable Declarations ****************************/ + +XDp DpInstance; + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function is the main function of the XDp selftest example. + * + * @param None. + * + * @return + * - XST_SUCCESS if the self test example passed. + * - XST_FAILURE if the self test example was unsuccessful - the + * DisplayPort TX's registers do not match their default values + * or no DisplayPort TX instance was found. + * + * @note None. + * +*******************************************************************************/ +int main(void) +{ + u32 Status; + + Status = Dp_SelfTestExample(&DpInstance, DP_DEVICE_ID); + if (Status != XST_SUCCESS) { + xil_printf("XDp_SelfTest failed, check register values.\n"); + return XST_FAILURE; + } + xil_printf("XDp_SelfTest passed.\n"); + return Status; +} + +/******************************************************************************/ +/** + * The main entry point for the selftest example using the XDp driver. This + * function will check whether or not the DisplayPort TX's registers are at + * their default reset values to ensure that the core is in a known and working + * state. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param DeviceId is the unique device ID of the DisplayPort TX core + * instance. + * + * @return + * - XST_SUCCESS if the DisplayPort TX's registers are at their + * default reset values. + * - XST_FAILURE if the DisplayPort TX's registers do not match + * their default values or no DisplayPort TX instance was found. + * + * @note None. + * +*******************************************************************************/ +u32 Dp_SelfTestExample(XDp *InstancePtr, u16 DeviceId) +{ + u32 Status; + XDp_Config *ConfigPtr; + + /* Obtain the device configuration for the DisplayPort TX core. */ + ConfigPtr = XDp_LookupConfig(DeviceId); + if (!ConfigPtr) { + return XST_FAILURE; + } + /* Copy the device configuration into the InstancePtr's Config + * structure. */ + XDp_CfgInitialize(InstancePtr, ConfigPtr, ConfigPtr->BaseAddr); + + /* Run the self test. */ + Status = XDp_SelfTest(InstancePtr); + return Status; +} diff --git a/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_audio_example.c b/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_audio_example.c new file mode 100644 index 00000000..67c7c3ed --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_audio_example.c @@ -0,0 +1,268 @@ +/******************************************************************************* + * + * Copyright (C) 2014 - 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 xdp_tx_audio_example.c + * + * Contains a design example using the XDp driver (operating in TX mode) to + * train the main link and to display video. In this example application, the + * sequence to enable audio is illustrated. + * + * @note This example requires an audio source such as an S/PDIF instance + * to be part of the hardware system. See XAPP1178 for reference. + * @note This example requires that the audio enable configuration + * parameter for DisplayPort be turned on when creating the + * hardware design. + * @note For this example to output audio, the user will need to + * implement initialization of the system (Dptx_PlatformInit), + * configuration of the audio source (Dptx_ConfigureAudioSrc) and, + * depending on the hardware system, will need to implement sending + * of an info frame (Dptx_AudioSendInfoFrame). See XAPP1178 and the + * IP documentation for reference. + * @note For this example to display output, after training is complete, + * the user will need to implement configuration of the video + * stream source in order to provide the DisplayPort core with + * input (Dptx_StreamSrc* - called in xdp_tx_example_common.c). See + * XAPP1178 for reference. + * @note The functions Dptx_PlatformInit and Dptx_StreamSrc* are declared + * extern in xdp_tx_example_common.h and are left up to the user to + * implement. The functions Dptx_ConfigureAudioSrc and + * Dptx_AudioSendInfoFrame are present in this file and are also + * left for the user to implement. + * + *
+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial creation. + *+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdp_tx_example_common.h" + +/**************************** Function Prototypes *****************************/ + +u32 Dptx_AudioExample(XDp *InstancePtr, u16 DeviceId); +static void Dptx_AudioInit(XDp *InstancePtr); +static void Dptx_ConfigureAudioSrc(XDp *InstancePtr); +static void Dptx_AudioSendInfoFrame(XDp *InstancePtr); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function is the main function of the XDp audio example. + * + * @param None. + * + * @return + * - XST_SUCCESS if the audio example finished successfully. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +int main(void) +{ + u32 Status; + + /* Run the XDp audio example. */ + Status = Dptx_AudioExample(&DpInstance, DPTX_DEVICE_ID); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * The main entry point for the audio example using the XDp driver. This + * function will set up audio, initiate link training, and a video stream will + * start being sent over the main link. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param DeviceId is the unique device ID of the DisplayPort TX core + * instance. + * + * @return + * - XST_SUCCESS if the system was set up correctly and link + * training was successful. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 Dptx_AudioExample(XDp *InstancePtr, u16 DeviceId) +{ + u32 Status; + + /* Use single-stream transport (SST) mode for this example. Audio is + * not supported in multi-stream transport (MST) mode. */ + XDp_TxMstCfgModeDisable(InstancePtr); + + /* Do platform initialization here. This is hardware system specific - + * it is up to the user to implement this function. */ + Dptx_PlatformInit(); + /*******************/ + + Status = Dptx_SetupExample(InstancePtr, DeviceId); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* Initialize DisplayPort audio. */ + Dptx_AudioInit(InstancePtr); + + XDp_TxEnableTrainAdaptive(InstancePtr, TRAIN_ADAPTIVE); + XDp_TxSetHasRedriverInPath(InstancePtr, TRAIN_HAS_REDRIVER); + + /* A sink monitor must be connected at this point. See the polling or + * interrupt examples for how to wait for a connection event. */ + Status = Dptx_Run(InstancePtr); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will set up audio in the DisplayPort TX. The user will need + * to implement configuration of the audio stream and, if needed, sending of + * the info frame. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note The user needs to implement the Dptx_ConfigureAudioSrc and + * the Dptx_AudioSendInfoFrame functions to fulfill audio + * initialization. + * +*******************************************************************************/ +static void Dptx_AudioInit(XDp *InstancePtr) +{ + u32 Fs; + u32 MAud; + u32 NAud; + u32 NumChs; + + /* Disable audio in the DisplayPort TX. This will also flush the buffers + * in the DisplayPort TX and set MUTE bit in VB-ID. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_AUDIO_CONTROL, 0x0); + + /* Configure the audio source (the S/PDIF controller). It is up to the + * user to implement this function. */ + Dptx_ConfigureAudioSrc(InstancePtr); + /*******************/ + + /* Write audio info frame as per user requirements. This may be optional + * for some systems. 8 writes are required to register + * XDP_TX_AUDIO_INFO_DATA. It is up to the user to implement this + * function. */ + Dptx_AudioSendInfoFrame(InstancePtr); + /*******************/ + + Fs = 48; /* KHz (32 | 44.1 | 48) */ + if (InstancePtr->TxInstance.LinkConfig.LinkRate == + XDP_TX_LINK_BW_SET_540GBPS) { + MAud = 512 * Fs; + } + else if (InstancePtr->TxInstance.LinkConfig.LinkRate == + XDP_TX_LINK_BW_SET_270GBPS) { + MAud = 512 * Fs; + } + else if (InstancePtr->TxInstance.LinkConfig.LinkRate == + XDP_TX_LINK_BW_SET_162GBPS) { + MAud = 512 * Fs; + } + + /* Write the channel count. The value is (actual count - 1). */ + NumChs = 2; + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_AUDIO_CHANNELS, + NumChs - 1); + + /* NAud = 540000 | 270000 | 162000 */ + NAud = 27 * InstancePtr->TxInstance.LinkConfig.LinkRate * 1000; + + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_AUDIO_MAUD, MAud); + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_AUDIO_NAUD, NAud); + + /* Enable audio in the DisplayPort TX. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_AUDIO_CONTROL, + 0x1); +} + +/******************************************************************************/ +/** + * This function needs to configure the audio source. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note The user needs to implement this. See XAPP1178 and the IP + * documentation for reference. + * +*******************************************************************************/ +static void Dptx_ConfigureAudioSrc(XDp *InstancePtr) +{ + xil_printf("Dptx_ConfigureAudioSrc: User defined function here.\n"); +} + +/******************************************************************************/ +/** + * This function needs to send an info frame as per user requirements. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note The user needs to implement this. See XAPP1178 and the IP + * documentation for reference. + * @note This may be optional for some systems. + * @note A sequence of 8 writes are required to register + * XDP_TX_AUDIO_INFO_DATA. See XAPP1178 and the IP documentation + * for reference. + * +*******************************************************************************/ +static void Dptx_AudioSendInfoFrame(XDp *InstancePtr) +{ + xil_printf("Dptx_AudioSendInfoFrame: User defined function here.\n"); +} diff --git a/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_example_common.c b/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_example_common.c new file mode 100644 index 00000000..d2fffe3c --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_example_common.c @@ -0,0 +1,349 @@ +/******************************************************************************* + * + * Copyright (C) 2014 - 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 xdp_tx_example_common.c + * + * Contains a design example using the XDp driver (operating in TX mode). It + * performs a self test on the DisplayPort TX core by training the main link at + * the maximum common capabilities between the TX and RX and checking the lane + * status. + * + * @note The DisplayPort TX core does not work alone - video/audio + * sources need to be set up in the system correctly, as well as + * setting up the output path (for example, configuring the + * hardware system with the DisplayPort TX core output to an FMC + * card with DisplayPort output capabilities. Some platform + * initialization will need to happen prior to calling XDp driver + * functions. See XAPP1178 as a reference. + * + *
+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial creation. + *+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdp_tx_example_common.h" + +/**************************** Function Prototypes *****************************/ + +static void Dptx_StartVideoStream(XDp *InstancePtr); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function will configure and establish a link with the receiver device, + * afterwards, a video stream will start to be sent over the main link. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LaneCount is the number of lanes to use over the main link. + * @param LinkRate is the link rate to use over the main link. + * + * @return + * - XST_SUCCESS if main link was successfully established. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 Dptx_Run(XDp *InstancePtr) +{ + u32 Status; + + /* Configure and establish a link. */ + Status = Dptx_StartLink(InstancePtr); + if (Status == XST_SUCCESS) { + /* Start the video stream. */ + Dptx_StartVideoStream(InstancePtr); + } else { + xil_printf("<-- Failed to establish/train the link.\n"); + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will setup and initialize the DisplayPort TX core. The core's + * configuration parameters will be retrieved based on the configuration + * to the DisplayPort TX core instance with the specified device ID. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param DeviceId is the unique device ID of the DisplayPort TX core + * instance. + * + * @return + * - XST_SUCCESS if the device configuration was found and obtained + * and if the main link was successfully established. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 Dptx_SetupExample(XDp *InstancePtr, u16 DeviceId) +{ + XDp_Config *ConfigPtr; + u32 Status; + + /* Obtain the device configuration for the DisplayPort TX core. */ + ConfigPtr = XDp_LookupConfig(DeviceId); + if (!ConfigPtr) { + return XST_FAILURE; + } + /* Copy the device configuration into the InstancePtr's Config + * structure. */ + XDp_CfgInitialize(InstancePtr, ConfigPtr, ConfigPtr->BaseAddr); + + /* Initialize the DisplayPort TX core. */ + Status = XDp_Initialize(InstancePtr); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will configure and establish a link with the receiver device. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS the if main link was successfully established. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 Dptx_StartLink(XDp *InstancePtr) +{ + u32 VsLevelTx; + u32 PeLevelTx; + u32 Status; + u8 LaneCount; + u8 LinkRate; + + /* Obtain the capabilities of the RX device by reading the monitor's + * DPCD. */ + Status = XDp_TxGetRxCapabilities(InstancePtr); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + +#if (TRAIN_USE_MAX_LINK == 1) + LaneCount = InstancePtr->TxInstance.LinkConfig.MaxLaneCount; + LinkRate = InstancePtr->TxInstance.LinkConfig.MaxLinkRate; +#else + LaneCount = TRAIN_USE_LANE_COUNT; + LinkRate = TRAIN_USE_LINK_RATE; +#endif + + /* Check if the link is already trained */ + Status = XDp_TxCheckLinkStatus(InstancePtr, LaneCount); + if (Status == XST_SUCCESS) { + xil_printf("-> Link is already trained on %d lanes.\n", + LaneCount); + if (XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_TX_LINK_BW_SET) == LinkRate) { + xil_printf("-> Link needs to be re-trained %d Mbps.\n", + (270 * LinkRate)); + } + else { + xil_printf("-> Link is already trained at %d Mbps.\n", + (270 * LinkRate)); + return XST_SUCCESS; + } + } + else if (Status == XST_FAILURE) { + xil_printf("-> Needs training.\n"); + } + else { + /* Either a connection does not exist or the supplied lane count + * is invalid. */ + xil_printf("-> Error checking link status.\n"); + return XST_FAILURE; + } + + XDp_TxSetEnhancedFrameMode(InstancePtr, 1); + XDp_TxSetDownspread(InstancePtr, 0); + +#if (TRAIN_USE_MAX_LINK == 1) + /* 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) { + return XST_FAILURE; + } +#else + XDp_TxSetLinkRate(InstancePtr, LinkRate); + XDp_TxSetLaneCount(InstancePtr, LaneCount); +#endif + + /* Train the link. */ + xil_printf("******************************************\n"); + Status = XDp_TxEstablishLink(InstancePtr); + if (Status != XST_SUCCESS) { + xil_printf("!!! Training failed !!!\n"); + xil_printf("******************************************\n"); + return XST_FAILURE; + } + + VsLevelTx = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_TX_PHY_VOLTAGE_DIFF_LANE_0); + PeLevelTx = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_TX_PHY_POSTCURSOR_LANE_0); + xil_printf("!!! Training passed at LR:0x%02lx LC:%d !!!\n", + InstancePtr->TxInstance.LinkConfig.LinkRate, + InstancePtr->TxInstance.LinkConfig.LaneCount); + xil_printf("VS:%d (TX:%d) PE:%d (TX:%d)\n", + InstancePtr->TxInstance.LinkConfig.VsLevel, VsLevelTx, + InstancePtr->TxInstance.LinkConfig.PeLevel, PeLevelTx); + xil_printf("******************************************\n"); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will start sending a video stream over the main link. The + * settings to be used are as follows: + * - 8 bits per color. + * - Video timing and screen resolution used: + * - The connected monitor's preferred timing is used to determine the + * video resolution (and associated timings) for the stream. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note The Dptx_StreamSrc* are intentionally left for the user to + * implement since configuration of the stream source is + * application-specific. + * @note The Extended Display Identification Data (EDID) is read in order + * to obtain the video resolution and timings. If this read fails, + * a resolution of 640x480 is used at a refresh rate of 60Hz. + * +*******************************************************************************/ +static void Dptx_StartVideoStream(XDp *InstancePtr) +{ + u32 Status; + u8 Edid[XDP_EDID_BLOCK_SIZE]; + + /* Set the bits per color. If not set, the default is 6. */ + XDp_TxCfgMsaSetBpc(InstancePtr, XDP_TX_STREAM_ID1, 8); + + /* Set synchronous clock mode. */ + XDp_TxCfgMsaEnSynchClkMode(InstancePtr, XDP_TX_STREAM_ID1, 1); + + 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); + +/* Choose a method for selecting the video mode. There are 3 ways to do this: + * 1) Use the preferred timing from the monitor's EDID: + * u8 Edid[XDP_EDID_BLOCK_SIZE]; + * XDp_TxGetEdid(InstancePtr, Edid); + * XDp_TxCfgMsaUseEdidPreferredTiming(InstancePtr, XDP_TX_STREAM_ID1, + * Edid); + * + * 2) Use a standard video timing mode (see mode_table.h): + * XDp_TxCfgMsaUseStandardVideoMode(InstancePtr, XDP_TX_STREAM_ID1, + XVIDC_VM_640x480_60_P); + * + * 3) Use a custom configuration for the main stream attributes (MSA): + * XDp_TxMainStreamAttributes MsaConfigCustom; + * MsaConfigCustom.Dmt.HResolution = 1280; + * MsaConfigCustom.Dmt.VResolution = 1024; + * MsaConfigCustom.Dmt.PixelClkKhz = 108000; + * MsaConfigCustom.Dmt.HSyncPolarity = 0; + * MsaConfigCustom.Dmt.VSyncPolarity = 0; + * MsaConfigCustom.Dmt.HFrontPorch = 48; + * MsaConfigCustom.Dmt.HSyncPulseWidth = 112; + * MsaConfigCustom.Dmt.HBackPorch = 248; + * MsaConfigCustom.Dmt.VFrontPorch = 1; + * MsaConfigCustom.Dmt.VSyncPulseWidth = 3; + * MsaConfigCustom.Dmt.VBackPorch = 38; + * XDp_TxCfgMsaUseCustom(InstancePtr, XDP_TX_STREAM_ID1, + * &MsaConfigCustom, 1); + * + * To override the user pixel width: + * InstancePtr->TxInstance.MsaConfig[_STREAM#_].OverrideUserPixelWidth = 1; + * InstancePtr->TxInstance.MsaConfig[_STREAM#_].UserPixelWidth = + * _DESIRED_VALUE_; + * Then, use one of the methods above to calculate the rest of the MSA. + */ + Status = XDp_TxGetEdid(InstancePtr, Edid); + if (Status == XST_SUCCESS) { + XDp_TxCfgMsaUseEdidPreferredTiming(InstancePtr, + XDP_TX_STREAM_ID1, Edid); + } + else { + XDp_TxCfgMsaUseStandardVideoMode(InstancePtr, XDP_TX_STREAM_ID1, + XVIDC_VM_640x480_60_P); + } + + /* Disable MST for this example. */ + XDp_TxMstDisable(InstancePtr); + + /* Disable main stream to force sending of IDLE patterns. */ + XDp_TxDisableMainLink(InstancePtr); + + /* 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); + + /* Set the DisplayPort TX video mode. */ + XDp_TxSetVideoMode(InstancePtr, XDP_TX_STREAM_ID1); + + /* Configure video stream source or generator here. These function need + * to be implemented in order for video to be displayed and is hardware + * system specific. It is up to the user to implement these + * functions. */ + Dptx_StreamSrcSetup(InstancePtr); + Dptx_StreamSrcConfigure(InstancePtr); + Dptx_StreamSrcSync(InstancePtr); + /*********************************/ + + XDp_TxEnableMainLink(InstancePtr); +} diff --git a/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_example_common.h b/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_example_common.h new file mode 100644 index 00000000..712f5557 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_example_common.h @@ -0,0 +1,135 @@ +/******************************************************************************* + * + * Copyright (C) 2014 - 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 xdp_tx_example_common.h + * + * Contains a design example using the XDp driver (operating in TX mode). It + * performs a self test on the DisplayPort TX core by training the main link at + * the maximum common capabilities between the TX and RX and checking the lane + * status. + * + * @note The DisplayPort TX core does not work alone - video/audio + * sources need to be set up in the system correctly, as well as + * setting up the output path (for example, configuring the + * hardware system with the DisplayPort TX core output to an FMC + * card with DisplayPort output capabilities. Some platform + * initialization will need to happen prior to calling XDp driver + * functions. See XAPP1178 as a reference. + * + *
+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial creation. + *+ * +*******************************************************************************/ + +#ifndef XDP_TX_EXAMPLE_COMMON_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XDP_TX_EXAMPLE_COMMON_H_ + +/******************************* Include Files ********************************/ + +#include "xdp.h" +#include "xil_printf.h" +#include "xparameters.h" + +/**************************** Constant Definitions ****************************/ + +/* The unique device ID of the DisplayPort TX core instance to be used with the + * examples. */ +#define DPTX_DEVICE_ID XPAR_DISPLAYPORT_0_DEVICE_ID + +/* If set to 1, the link training process will continue training despite failing + * by attempting training at a reduced link rate. It will also continue + * attempting to train the link at a reduced lane count if needed. With this + * option enabled, link training will return failure only when all link rate and + * lane count combinations have been exhausted - that is, training fails using + * 1-lane and a 1.62Gbps link rate. + * If set to 0, link training will return failure if the training failed using + * the current lane count and link rate settings. + * TRAIN_ADAPTIVE is used by the examples as input to the + * XDp_TxEnableTrainAdaptive driver function. */ +#define TRAIN_ADAPTIVE 1 + +/* A value of 1 is used to indicate that the DisplayPort output path has a + * redriver on the board that adjusts the voltage swing and pre-emphasis levels + * that are outputted from the FPGA. If this is the case, the voltage swing and + * pre-emphasis values supplied to the DisplayPort TX core will be evenly + * distributed among the available levels as specified in the IP documentation. + * Otherwise, a value of 0 is used to indicate that no redriver is present. In + * order to meet the necessary voltage swing and pre-emphasis levels required by + * a DisplayPort RX device, the level values specified to the DisplayPort TX + * core will require some compensation. + * TRAIN_HAS_REDRIVER is used by the examples as input to the + * XDp_TxSetHasRedriverInPath driver function. + * Note: There are 16 possible voltage swing levels and 32 possible pre-emphasis + * levels in the DisplayPort TX core that will be mapped to 4 possible + * voltage swing and 4 possible pre-emphasis levels in the RX device. */ +#define TRAIN_HAS_REDRIVER 1 + +/* The link rate setting to begin link training with. Valid values are: + * XDP_TX_LINK_BW_SET_540GBPS, XDP_TX_LINK_BW_SET_270GBPS, and + * XDP_TX_LINK_BW_SET_162GBPS. */ +#define TRAIN_USE_LINK_RATE XDP_TX_LINK_BW_SET_540GBPS +/* The lane count setting to begin link training with. Valid values are: + * XDP_TX_LANE_COUNT_SET_4, XDP_TX_LANE_COUNT_SET_2, and + * XDP_TX_LANE_COUNT_SET_1. */ +#define TRAIN_USE_LANE_COUNT XDP_TX_LANE_COUNT_SET_4 +/* If set to 1, TRAIN_USE_LINK_RATE and TRAIN_USE_LANE_COUNT will be ignored. + * Instead, the maximum common link capabilities between the DisplayPort TX core + * and the RX device will be used when establishing a link. + * If set to 0, TRAIN_USE_LINK_RATE and TRAIN_USE_LANE_COUNT will determine the + * link rate and lane count settings that the link training process will begin + * with. */ +#define TRAIN_USE_MAX_LINK 1 + +/**************************** Function Prototypes *****************************/ + +extern u32 Dptx_PlatformInit(void); +extern u32 Dptx_StreamSrcSync(XDp *InstancePtr); +extern u32 Dptx_StreamSrcSetup(XDp *InstancePtr); +extern u32 Dptx_StreamSrcConfigure(XDp *InstancePtr); + +u32 Dptx_SetupExample(XDp *InstancePtr, u16 DeviceId); +u32 Dptx_StartLink(XDp *InstancePtr); +u32 Dptx_Run(XDp *InstancePtr); + +/*************************** Variable Declarations ****************************/ + +XDp DpInstance; + +#endif /* XDP_TX_EXAMPLE_COMMON_H_ */ diff --git a/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_intr_example.c b/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_intr_example.c new file mode 100644 index 00000000..2ed33be6 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_intr_example.c @@ -0,0 +1,352 @@ +/******************************************************************************* + * + * Copyright (C) 2014 - 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 xdp_tx_intr_example.c + * + * Contains a design example using the XDp driver (operating in TX mode) with + * interrupts. Upon Hot-Plug-Detect (HPD - DisplayPort cable is + * plugged/unplugged or the monitor is turned on/off), the main link will be + * trained. + * + * @note This example requires an interrupt controller connected to the + * processor and the DisplayPort TX core in the system. + * @note For this example to display output, the user will need to + * implement initialization of the system (Dptx_PlatformInit) and, + * after training is complete, implement configuration of the video + * stream source in order to provide the DisplayPort core with + * input (Dptx_StreamSrc* - called in xdp_tx_example_common.c). See + * XAPP1178 for reference. + * @note The functions Dptx_PlatformInit and Dptx_StreamSrc* are declared + * extern in xdp_tx_example_common.h and are left up to the user to + * implement. + * + *
+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial creation. + *+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdp_tx_example_common.h" +#ifdef XPAR_INTC_0_DEVICE_ID +/* For MicroBlaze systems. */ +#include "xintc.h" +#else +/* For ARM/Zynq SoC systems. */ +#include "xscugic.h" +#endif /* XPAR_INTC_0_DEVICE_ID */ + +/**************************** Constant Definitions ****************************/ + +/* The following constants map to the XPAR parameters created in the + * xparameters.h file. */ +#ifdef XPAR_INTC_0_DEVICE_ID +#define DP_INTERRUPT_ID XPAR_AXI_INTC_1_DISPLAYPORT_0_AXI_INT_INTR +#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID +#else +#define DP_INTERRUPT_ID XPAR_FABRIC_DISPLAYPORT_0_AXI_INT_INTR +#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID +#endif /* XPAR_INTC_0_DEVICE_ID */ + +/****************************** Type Definitions ******************************/ + +/* Depending on whether the system is a MicroBlaze or ARM/Zynq SoC system, + * different drivers and associated types will be used. */ +#ifdef XPAR_INTC_0_DEVICE_ID +#define INTC XIntc +#define INTC_HANDLER XIntc_InterruptHandler +#else +#define INTC XScuGic +#define INTC_HANDLER XScuGic_InterruptHandler +#endif /* XPAR_INTC_0_DEVICE_ID */ + +/**************************** Function Prototypes *****************************/ + +u32 Dptx_IntrExample(XDp *InstancePtr, u16 DeviceId, INTC *IntcPtr, + u16 IntrId, u16 DpIntrId, XDp_IntrHandler HpdEventHandler, + XDp_IntrHandler HpdPulseHandler); +static u32 Dptx_SetupInterruptHandler(XDp *InstancePtr, INTC *IntcPtr, + u16 IntrId, u16 DpIntrId, XDp_IntrHandler HpdEventHandler, + XDp_IntrHandler HpdPulseHandler); +static void Dptx_HpdEventHandler(void *InstancePtr); +static void Dptx_HpdPulseHandler(void *InstancePtr); + +/**************************** Variable Definitions ****************************/ + +INTC IntcInstance; /* The interrupt controller instance. */ + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function is the main function of the XDptx interrupt example. If the + * DptxIntrExample function, which sets up the system succeeds, this function + * will wait for interrupts. Once a connection event or pulse is detected, link + * training will commence (if needed) and a video stream will start being sent + * over the main link. + * + * @param None. + * + * @return + * - XST_FAILURE if the interrupt example was unsuccessful - system + * setup failed. + * + * @note Unless setup failed, main will never return since + * DptxIntrExample is blocking (it is waiting on interrupts for + * Hot-Plug-Detect (HPD) events. + * +*******************************************************************************/ +int main(void) +{ + /* Run the XDptx interrupt example. */ + Dptx_IntrExample(&DpInstance, DPTX_DEVICE_ID, + &IntcInstance, INTC_DEVICE_ID, DP_INTERRUPT_ID, + &Dptx_HpdEventHandler, &Dptx_HpdPulseHandler); + + return XST_FAILURE; +} + +/******************************************************************************/ +/** + * The main entry point for the interrupt example using the XDp driver. This + * function will set up the system with interrupts and set up the Hot-Plug-Event + * (HPD) handlers. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param DeviceId is the unique device ID of the DisplayPort TX core + * instance. + * @param IntcPtr is a pointer to the interrupt instance. + * @param IntrId is the unique device ID of the interrupt controller. + * @param DpIntrId is the interrupt ID of the DisplayPort TX connection to + * the interrupt controller. + * @param HpdEventHandler is a pointer to the handler called when an HPD + * event occurs. + * @param HpdPulseHandler is a pointer to the handler called when an HPD + * pulse occurs. + * + * @return + * - XST_FAILURE if the system setup failed. + * - XST_SUCCESS should never return since this function, if setup + * was successful, is blocking. + * + * @note If system setup was successful, this function is blocking in + * order to illustrate interrupt handling taking place for HPD + * events. + * +*******************************************************************************/ +u32 Dptx_IntrExample(XDp *InstancePtr, u16 DeviceId, INTC *IntcPtr, + u16 IntrId, u16 DpIntrId, XDp_IntrHandler HpdEventHandler, + XDp_IntrHandler HpdPulseHandler) +{ + u32 Status; + + /* Use single-stream transport (SST) mode for this example. */ + XDp_TxMstCfgModeDisable(InstancePtr); + + /* Do platform initialization here. This is hardware system specific - + * it is up to the user to implement this function. */ + Dptx_PlatformInit(); + /******************/ + + Status = Dptx_SetupExample(InstancePtr, DeviceId); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + XDp_TxEnableTrainAdaptive(InstancePtr, TRAIN_ADAPTIVE); + XDp_TxSetHasRedriverInPath(InstancePtr, TRAIN_HAS_REDRIVER); + + /* Setup interrupt handling in the system. */ + Status = Dptx_SetupInterruptHandler(InstancePtr, IntcPtr, IntrId, + DpIntrId, HpdEventHandler, HpdPulseHandler); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* Do not return in order to allow interrupt handling to run. HPD events + * (connect, disconnect, and pulse) will be detected and handled. */ + while (1); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function sets up the interrupt system such that interrupts caused by + * Hot-Plug-Detect (HPD) events and pulses are handled. This function is + * application-specific for systems that have an interrupt controller connected + * to the processor. The user should modify this function to fit the + * application. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param IntcPtr is a pointer to the interrupt instance. + * @param IntrId is the unique device ID of the interrupt controller. + * @param DpIntrId is the interrupt ID of the DisplayPort TX connection to + * the interrupt controller. + * @param HpdEventHandler is a pointer to the handler called when an HPD + * event occurs. + * @param HpdPulseHandler is a pointer to the handler called when an HPD + * pulse occurs. + * + * @return + * - XST_SUCCESS if the interrupt system was successfully set up. + * - XST_FAILURE otherwise. + * + * @note An interrupt controller must be present in the system, connected + * to the processor and the DisplayPort TX core. + * +*******************************************************************************/ +static u32 Dptx_SetupInterruptHandler(XDp *InstancePtr, INTC *IntcPtr, + u16 IntrId, u16 DpIntrId, XDp_IntrHandler HpdEventHandler, + XDp_IntrHandler HpdPulseHandler) +{ + u32 Status; + + /* Set the HPD interrupt handlers. */ + XDp_TxSetHpdEventHandler(InstancePtr, HpdEventHandler, InstancePtr); + XDp_TxSetHpdPulseHandler(InstancePtr, HpdPulseHandler, InstancePtr); + + /* Initialize interrupt controller driver. */ +#ifdef XPAR_INTC_0_DEVICE_ID + Status = XIntc_Initialize(IntcPtr, IntrId); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } +#else + XScuGic_Config *IntcConfig; + + IntcConfig = XScuGic_LookupConfig(IntrId); + Status = XScuGic_CfgInitialize(IntcPtr, IntcConfig, + IntcConfig->CpuBaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + XScuGic_SetPriorityTriggerType(IntcPtr, DpIntrId, 0xA0, 0x1); +#endif /* XPAR_INTC_0_DEVICE_ID */ + + /* Connect the device driver handler that will be called when an + * interrupt for the device occurs, the handler defined above performs + * the specific interrupt processing for the device. */ +#ifdef XPAR_INTC_0_DEVICE_ID + Status = XIntc_Connect(IntcPtr, DpIntrId, + (XInterruptHandler)XDp_InterruptHandler, InstancePtr); +#else + Status = XScuGic_Connect(IntcPtr, DpIntrId, + (Xil_InterruptHandler)XDp_InterruptHandler, InstancePtr); +#endif /* XPAR_INTC_0_DEVICE_ID */ + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* Start the interrupt controller. */ +#ifdef XPAR_INTC_0_DEVICE_ID + Status = XIntc_Start(IntcPtr, XIN_REAL_MODE); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + XIntc_Enable(IntcPtr, DpIntrId); +#else + XScuGic_Enable(IntcPtr, DpIntrId); +#endif /* XPAR_INTC_0_DEVICE_ID */ + + /* Initialize the exception table. */ + Xil_ExceptionInit(); + + /* Register the interrupt controller handler with the exception table. */ + Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, + (Xil_ExceptionHandler)INTC_HANDLER, IntcPtr); + + /* Enable exceptions. */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function is called when a Hot-Plug-Detect (HPD) event is received by the + * DisplayPort TX core. The XDP_TX_INTERRUPT_STATUS_HPD_EVENT_MASK bit of the + * core's XDP_TX_INTERRUPT_STATUS register indicates that an HPD event has + * occurred. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note Use the XDp_TxSetHpdEventHandler driver function to set this + * function as the handler for HPD pulses. + * +*******************************************************************************/ +static void Dptx_HpdEventHandler(void *InstancePtr) +{ + XDp *XDp_InstancePtr = (XDp *)InstancePtr; + + if (XDp_TxIsConnected(XDp_InstancePtr)) { + xil_printf("+===> HPD connection event detected.\n"); + + Dptx_Run(XDp_InstancePtr); + } + else { + xil_printf("+===> HPD disconnection event detected.\n\n"); + } +} + +/******************************************************************************/ +/** + * This function is called when a Hot-Plug-Detect (HPD) pulse is received by the + * DisplayPort TX core. The XDP_TX_INTERRUPT_STATUS_HPD_PULSE_DETECTED_MASK bit + * of the core's XDP_TX_INTERRUPT_STATUS register indicates that an HPD event + * has occurred. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note Use the XDp_TxSetHpdPulseHandler driver function to set this + * function as the handler for HPD pulses. + * +*******************************************************************************/ +static void Dptx_HpdPulseHandler(void *InstancePtr) +{ + XDp *XDp_InstancePtr = (XDp *)InstancePtr; + + xil_printf("===> HPD pulse detected.\n"); + + Dptx_Run(XDp_InstancePtr); +} diff --git a/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_mst_example.c b/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_mst_example.c new file mode 100644 index 00000000..51e49f40 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_mst_example.c @@ -0,0 +1,387 @@ +/******************************************************************************* + * + * Copyright (C) 2014 - 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 xdp_tx_mst_example.c + * + * Contains a design example using the XDp driver (operating in TX mode) in + * multi-stream transport (MST) mode. + * + * @note For this example to display output, the user will need to + * implement initialization of the system (Dptx_PlatformInit) and, + * after training is complete, implement configuration of the video + * stream source in order to provide the DisplayPort core with + * input. See XAPP1178 for reference. + * @note The functions Dptx_PlatformInit and Dptx_StreamSrc* are declared + * extern in xdp_tx_example_common.h and are left up to the user to + * implement. + * @note Some setups may require introduction of delays when sending + * sideband messages. + * + *
+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial creation. + *+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdp_tx_example_common.h" + +/**************************** Constant Definitions ****************************/ + +/* The maximum number of streams to enable. */ +#define NUM_STREAMS 4 + +/* This enables topology discovery which will create a list of sinks in the + * topology. If ALLOCATE_FROM_SINKLIST is defined, the streams will sent to + * to the sinks with the corresponding index. See the function calls for + * the XDp_TxSetStreamSelectFromSinkList driver function below. */ +#define ALLOCATE_FROM_SINKLIST +#ifdef ALLOCATE_FROM_SINKLIST +/* Define the mapping between sinks and streams. The sink numbers are in the + * order that they are discovered by the XDp_TxFindAccessibleDpDevices driver + * function. */ +#define STREAM1_USE_SINKNUM 0 +#define STREAM2_USE_SINKNUM 1 +#define STREAM3_USE_SINKNUM 2 +#define STREAM4_USE_SINKNUM 3 +#endif + +/* The video resolution from the display mode timings (DMT) table to use for + * each stream. */ +#define USE_VIDEO_MODE XVIDC_VM_1920x1080_60_P + +/* The color depth (bits per color component) to use for each stream. */ +#define USE_BPC 8 + +/* Some MST configurations may require delays when sending sideband messages. By + * default, disable these delays.*/ +#undef USE_DELAYS_FOR_MST + +/**************************** Function Prototypes *****************************/ + +u32 Dptx_MstExample(XDp *InstancePtr, u16 DeviceId); +u32 Dptx_MstExampleRun(XDp *InstancePtr); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function is the main function of the XDptx multi-stream transport (MST) + * example. + * + * @param None. + * + * @return + * - XST_FAILURE if the MST example was unsuccessful - system + * setup failed. + * + * @note Unless setup failed, main will never return since + * Dptx_MstExample is blocking. + * +*******************************************************************************/ +int main(void) +{ + /* Run the XDptx MST example. */ + Dptx_MstExample(&DpInstance, DPTX_DEVICE_ID); + + return XST_FAILURE; +} + +/******************************************************************************/ +/** + * The main entry point for the multi-stream transport (MST) example using the + * XDp driver. This function will either discover the topology and map streams + * to the sinks in the sink list, or map streams to relative addresses. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param DeviceId is the unique device ID of the DisplayPort TX core + * instance. + * + * @return + * - XST_FAILURE if the system setup failed. + * - XST_SUCCESS should never return since this function, if setup + * was successful, is blocking. + * + * @note If system setup was successful, this function is blocking. + * +*******************************************************************************/ +u32 Dptx_MstExample(XDp *InstancePtr, u16 DeviceId) +{ + u32 Status; + + /* Do platform initialization here. This is hardware system specific - + * it is up to the user to implement this function. */ + Dptx_PlatformInit(); + /******************/ + + Status = Dptx_SetupExample(InstancePtr, DeviceId); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + Status = XDp_TxMstCapable(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. */ + xil_printf("!!! Verify DisplayPort MST capabilities in the TX " + "and/or RX device.\n"); + return XST_FAILURE; + } + + do { + Status = Dptx_MstExampleRun(InstancePtr); + if (Status == XST_DATA_LOST) { + xil_printf("!!! Link lost... Need to re-train.\n"); + } + } while (Status != XST_SUCCESS); + + /* Do not return. */ + xil_printf("MST example DONE.\n"); + while (1); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function trains the link and allocates stream payloads. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param DeviceId is the unique device ID of the DisplayPort TX core + * instance. + * + * @return + * - XST_SUCCESS if MST allocation was successful. + * - XST_ERROR_COUNT_MAX if the ACT trigger was lost. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 Dptx_MstExampleRun(XDp *InstancePtr) +{ + u32 Status; + u32 MaskVal; + u8 StreamIndex; + XVidC_VideoMode VideoMode = USE_VIDEO_MODE; + u8 Bpc = USE_BPC; + u8 NumStreams = NUM_STREAMS; + + /* Limit the number of streams to configure based on the configuration + * of the DisplayPort core. */ + if (NumStreams > InstancePtr->Config.NumMstStreams) { + NumStreams = InstancePtr->Config.NumMstStreams; + } + + XDp_TxEnableTrainAdaptive(InstancePtr, TRAIN_ADAPTIVE); + XDp_TxSetHasRedriverInPath(InstancePtr, TRAIN_HAS_REDRIVER); + + /* A DisplayPort connection must exist at this point. See the interrupt + * and polling examples for waiting for connection events. */ + Status = Dptx_StartLink(InstancePtr); + if (Status != XST_SUCCESS) { + xil_printf("Link Training failed.\n"); + return XST_FAILURE; + } + +#ifdef USE_DELAYS_FOR_MST + InstancePtr->TxInstance.AuxDelayUs = 30000; + InstancePtr->TxInstance.SbMsgDelayUs = 100000; +#else + InstancePtr->TxInstance.AuxDelayUs = 0; + InstancePtr->TxInstance.SbMsgDelayUs = 0; +#endif + + 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); + +#ifdef ALLOCATE_FROM_SINKLIST + /* Run topology discovery to determine what devices are accessible to + * the DisplayPort TX. */ + xil_printf("Find topology >>>\n"); + InstancePtr->TxInstance.Topology.NodeTotal = 0; + InstancePtr->TxInstance.Topology.SinkTotal = 0; + + Status = XDp_TxDiscoverTopology(InstancePtr); + if (Status != XST_SUCCESS) { + xil_printf("!!! A LINK_ADDRESS response from a branch device " + "in the MST topology was not successfully received.\n"); + return XST_FAILURE; + } + + xil_printf("<<< Find topology DONE; # of sinks found = %d.\n", + InstancePtr->TxInstance.Topology.SinkTotal); + + if (NumStreams > InstancePtr->TxInstance.Topology.SinkTotal) { + NumStreams = InstancePtr->TxInstance.Topology.SinkTotal; + } +#endif + + /* Enable multi-stream transport (MST) mode for this example. */ + XDp_TxMstCfgModeEnable(InstancePtr); + for (StreamIndex = 0; StreamIndex < NumStreams; StreamIndex++) { + XDp_TxMstCfgStreamEnable(InstancePtr, XDP_TX_STREAM_ID1 + + StreamIndex); + } + for (StreamIndex = NumStreams; StreamIndex < 4; StreamIndex++) { + XDp_TxMstCfgStreamDisable(InstancePtr, XDP_TX_STREAM_ID1 + + StreamIndex); + } + + /* Specify the DisplayPort sink devices that each enabled stream will be + * directed towards. */ +#ifndef ALLOCATE_FROM_SINKLIST + /* If topology discovery is not used, specify the relative addresses of + * the DisplayPort sink devices. */ + u8 Lct; + u8 Rad[15]; + + if (XDp_TxMstStreamIsEnabled(InstancePtr, XDP_TX_STREAM_ID1)) { + Lct = 2; Rad[0] = 8; + XDp_TxSetStreamSinkRad(InstancePtr, XDP_TX_STREAM_ID1, Lct, + Rad); + } + if (XDp_TxMstStreamIsEnabled(InstancePtr, XDP_TX_STREAM_ID2)) { + Lct = 3; Rad[0] = 1; Rad[1] = 8; + XDp_TxSetStreamSinkRad(InstancePtr, XDP_TX_STREAM_ID2, Lct, + Rad); + } + if (XDp_TxMstStreamIsEnabled(InstancePtr, XDP_TX_STREAM_ID3)) { + Lct = 4; Rad[0] = 1; Rad[1] = 1; Rad[2] = 8; + XDp_TxSetStreamSinkRad(InstancePtr, XDP_TX_STREAM_ID3, Lct, + Rad); + } + if (XDp_TxMstStreamIsEnabled(InstancePtr, XDP_TX_STREAM_ID4)) { + Lct = 4; Rad[0] = 1; Rad[1] = 1; Rad[2] = 9; + XDp_TxSetStreamSinkRad(InstancePtr, XDP_TX_STREAM_ID4, Lct, + Rad); + } +#else + /* If topology discovery is used, associate a stream number with a sink + * number from the sink list obtained during topology discovery. The + * sinks are numbered in the order that they were found during topology + * discovery. */ + if (XDp_TxMstStreamIsEnabled(InstancePtr, XDP_TX_STREAM_ID1)) { + XDp_TxSetStreamSelectFromSinkList(InstancePtr, + XDP_TX_STREAM_ID1, STREAM1_USE_SINKNUM); + } + if (XDp_TxMstStreamIsEnabled(InstancePtr, XDP_TX_STREAM_ID2)) { + XDp_TxSetStreamSelectFromSinkList(InstancePtr, + XDP_TX_STREAM_ID2, STREAM2_USE_SINKNUM); + } + if (XDp_TxMstStreamIsEnabled(InstancePtr, XDP_TX_STREAM_ID3)) { + XDp_TxSetStreamSelectFromSinkList(InstancePtr, + XDP_TX_STREAM_ID3, STREAM3_USE_SINKNUM); + } + if (XDp_TxMstStreamIsEnabled(InstancePtr, XDP_TX_STREAM_ID4)) { + XDp_TxSetStreamSelectFromSinkList(InstancePtr, + XDP_TX_STREAM_ID4, STREAM4_USE_SINKNUM); + } +#endif + + /* Reset MST mode in both the RX and TX. */ + XDp_TxMstDisable(InstancePtr); + XDp_TxMstEnable(InstancePtr); + + /* Set the main stream attributes (MSA) for each enabled stream (each + * stream has an identical configuration). Then, set the configuration + * for that stream in the corresponding DisplayPort TX registers. */ + for (StreamIndex = 0; StreamIndex < 4; StreamIndex++) { + if (XDp_TxMstStreamIsEnabled(InstancePtr, + XDP_TX_STREAM_ID1 + StreamIndex)) { + XDp_TxCfgMsaSetBpc(InstancePtr, XDP_TX_STREAM_ID1 + + StreamIndex, Bpc); + XDp_TxCfgMsaEnSynchClkMode(InstancePtr, + XDP_TX_STREAM_ID1 + StreamIndex, 1); + + XDp_TxCfgMsaUseStandardVideoMode(InstancePtr, + XDP_TX_STREAM_ID1 + StreamIndex, VideoMode); + XDp_TxSetVideoMode(InstancePtr, XDP_TX_STREAM_ID1 + + StreamIndex); + } + } + + /* Configure video stream source or generator here. This function needs + * to be implemented in order for video to be displayed and is hardware + * system specific. It is up to the user to implement this function. */ + Dptx_StreamSrcSetup(InstancePtr); + Dptx_StreamSrcConfigure(InstancePtr); + Dptx_StreamSrcSync(InstancePtr); + //////////////////////////////////// + + /* Mask interrupts while allocating payloads. */ + MaskVal = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_TX_INTERRUPT_MASK); + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_INTERRUPT_MASK, 0x3F); + + /* Clear the payload ID table first. */ + Status = XDp_TxClearPayloadVcIdTable(InstancePtr); + if (Status != XST_SUCCESS) { + return XST_DATA_LOST; + } + + /* Allocate payloads. */ + Status = XDp_TxAllocatePayloadStreams(InstancePtr); + if (Status != XST_SUCCESS) { + return XST_DATA_LOST; + } + + /* Enable the main link. */ + XDp_TxEnableMainLink(InstancePtr); + + /* Unmask interrupts. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_INTERRUPT_MASK, + MaskVal); + + /* Do a final check to verify that the link wasn't lost. */ + Status = XDp_TxCheckLinkStatus(InstancePtr, + InstancePtr->TxInstance.LinkConfig.LaneCount); + if (Status != XST_SUCCESS) { + XDp_WaitUs(InstancePtr, 10000); + return XST_DATA_LOST; + } + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_poll_example.c b/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_poll_example.c new file mode 100644 index 00000000..257997b3 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_poll_example.c @@ -0,0 +1,201 @@ +/******************************************************************************* + * + * Copyright (C) 2014 - 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 xdp_tx_poll_example.c + * + * Contains a design example using the XDp driver (operating in TX mode) with + * polling. Once the polling detects a Hot-Plug-Detect event (HPD - DisplayPort + * cable is plugged/unplugged or the monitor is turned on/off), the main link + * will be trained. + * + * @note For this example to display output, the user will need to + * implement initialization of the system (Dptx_PlatformInit) and, + * after training is complete, implement configuration of the video + * stream source in order to provide the DisplayPort core with + * input (Dptx_StreamSrc* - called in xdp_tx_example_common.c). See + * XAPP1178 for reference. + * @note The functions Dptx_PlatformInit and Dptx_StreamSrc* are declared + * extern in xdp_tx_example_common.h and are left up to the user to + * implement. + * + *
+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial creation. + *+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdp_tx_example_common.h" + +/**************************** Function Prototypes *****************************/ + +u32 Dptx_PollExample(XDp *InstancePtr, u16 DeviceId); +static void Dptx_HpdPoll(XDp *InstancePtr); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function is the main function of the XDp polling example. + * + * @param None. + * + * @return + * - XST_FAILURE if the polling example was unsuccessful - system + * setup failed. + * + * @note Unless setup failed, main will never return since + * Dptx_PollExample is blocking (it is continuously polling for + * Hot-Plug-Detect (HPD) events. + * +*******************************************************************************/ +int main(void) +{ + /* Run the XDp polling example. */ + Dptx_PollExample(&DpInstance, DPTX_DEVICE_ID); + + return XST_FAILURE; +} + +/******************************************************************************/ +/** + * The main entry point for the polling example using the XDp driver. This + * function will set up the system. If this is successful, this example will + * begin polling the Hot-Plug-Detect (HPD) status registers for HPD events. Once + * a connection event or a pulse is detected, link training will commence (if + * needed) and a video stream will start being sent over the main link. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param DeviceId is the unique device ID of the DisplayPort TX core + * instance. + * + * @return + * - XST_FAILURE if the system setup failed. + * - XST_SUCCESS should never return since this function, if setup + * was successful, is blocking. + * + * @note If system setup was successful, this function is blocking in + * order to illustrate polling taking place for HPD events. + * +*******************************************************************************/ +u32 Dptx_PollExample(XDp *InstancePtr, u16 DeviceId) +{ + u32 Status; + + /* Do platform initialization here. This is hardware system specific - + * it is up to the user to implement this function. */ + Dptx_PlatformInit(); + /******************/ + + Status = Dptx_SetupExample(InstancePtr, DeviceId); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + XDp_TxEnableTrainAdaptive(InstancePtr, TRAIN_ADAPTIVE); + XDp_TxSetHasRedriverInPath(InstancePtr, TRAIN_HAS_REDRIVER); + + /* Continuously poll for HPD events. */ + while (1) { + Dptx_HpdPoll(InstancePtr); + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function polls the XDP_TX_INTERRUPT_SIG_STATE and + * XDP_TX_INTERRUPT_STATUS registers for Hot-Plug-Detect (HPD) events and + * handles them accordingly. If a connection or pulse event is detected, link + * training will begin (if required) and a video stream will be initiated. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void Dptx_HpdPoll(XDp *InstancePtr) +{ + u32 InterruptSignalState; + u32 InterruptStatus; + u32 HpdState; + u32 HpdEvent; + u32 HpdPulseDetected; + u32 HpdDuration; + + /* Read interrupt registers. */ + InterruptSignalState = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_TX_INTERRUPT_SIG_STATE); + InterruptStatus = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_TX_INTERRUPT_STATUS); + + /* Check for HPD events. */ + HpdState = InterruptSignalState & + XDP_TX_INTERRUPT_SIG_STATE_HPD_STATE_MASK; + HpdEvent = InterruptStatus & XDP_TX_INTERRUPT_STATUS_HPD_EVENT_MASK; + HpdPulseDetected = InterruptStatus & + XDP_TX_INTERRUPT_STATUS_HPD_PULSE_DETECTED_MASK; + if (HpdPulseDetected) { + HpdDuration = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_TX_HPD_DURATION); + } + + /* HPD event handling. */ + if (HpdState && HpdEvent) { + xil_printf("+===> HPD connection event detected.\n"); + + /* Initiate link training. */ + Dptx_Run(InstancePtr); + } + else if (HpdState && HpdPulseDetected && (HpdDuration >= 250)) { + xil_printf("===> HPD pulse detected.\n"); + + /* Re-train if needed. */ + Dptx_Run(InstancePtr); + } + else if (!HpdState && HpdEvent) { + xil_printf("+===> HPD disconnection event detected.\n\n"); + + /* Disable main link. */ + XDp_TxDisableMainLink(InstancePtr); + } +} diff --git a/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_timer_example.c b/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_timer_example.c new file mode 100644 index 00000000..80c4c29d --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/examples/xdp_tx_timer_example.c @@ -0,0 +1,201 @@ +/******************************************************************************* + * + * Copyright (C) 2014 - 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 xdp_tx_timer_example.c + * + * Contains a design example using the XDp driver (operating in TX mode) with a + * user-defined hook for delay. The reasoning behind this is that MicroBlaze + * sleep is not very accurate without a hardware timer. For systems that have a + * hardware timer, the user may override the default MicroBlaze sleep with a + * function that will use the hardware timer. + * + * @note This example requires an AXI timer in the system. + * @note For this example to display output, the user will need to + * implement initialization of the system (Dptx_PlatformInit) and, + * after training is complete, implement configuration of the video + * stream source in order to provide the DisplayPort core with + * input (Dptx_StreamSrc* - called in xdp_tx_example_common.c). See + * XAPP1178 for reference. + * @note The functions Dptx_PlatformInit and Dptx_StreamSrc* are declared + * extern in xdp_tx_example_common.h and are left up to the user to + * implement. + * + *
+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial creation. + *+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdp_tx_example_common.h" +#include "xtmrctr.h" + +/**************************** Function Prototypes *****************************/ + +u32 Dptx_TimerExample(XDp *InstancePtr, u16 DeviceId, + XTmrCtr *TimerCounterPtr, XDp_TimerHandler UserSleepFunc); +static void Dptx_CustomWaitUs(void *InstancePtr, u32 MicroSeconds); + +/*************************** Variable Declarations ****************************/ + +XTmrCtr TimerCounterInst; /* The timer counter instance. */ + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function is the main function of the XDptx timer example. + * + * @param None. + * + * @return + * - XST_SUCCESS if the timer example finished successfully. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +int main(void) +{ + u32 Status; + + /* Run the XDptx timer example. */ + Status = Dptx_TimerExample(&DpInstance, DPTX_DEVICE_ID, + &TimerCounterInst, &Dptx_CustomWaitUs); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * The main entry point for the timer example using the XDp driver. This + * function will set up the system and the custom sleep handler. If this is + * successful, link training will commence and a video stream will start being + * sent over the main link. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param DeviceId is the unique device ID of the DisplayPort TX core + * instance. + * @param TimerCounterPtr is a pointer to the timer instance. + * @param UserSleepFunc is a pointer to the custom handler for sleep. + * + * @return + * - XST_SUCCESS if the system was set up correctly and link + * training was successful. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 Dptx_TimerExample(XDp *InstancePtr, u16 DeviceId, + XTmrCtr *TimerCounterPtr, XDp_TimerHandler UserSleepFunc) +{ + u32 Status; + + /* Use single-stream transport (SST) mode for this example. */ + XDp_TxMstCfgModeDisable(InstancePtr); + + /* Do platform initialization here. This is hardware system specific - + * it is up to the user to implement this function. */ + Dptx_PlatformInit(); + /*******************/ + + /* Set a custom timer handler for improved delay accuracy on MicroBlaze + * systems since the driver does not assume/have a dependency on the + * system having a timer in the FPGA. + * Note: This only has an affect for MicroBlaze systems since the Zynq + * ARM SoC contains a timer, which is used when the driver calls the + * delay function. */ + XDp_SetUserTimerHandler(InstancePtr, UserSleepFunc, TimerCounterPtr); + + Status = Dptx_SetupExample(InstancePtr, DeviceId); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + XDp_TxEnableTrainAdaptive(InstancePtr, TRAIN_ADAPTIVE); + XDp_TxSetHasRedriverInPath(InstancePtr, TRAIN_HAS_REDRIVER); + + /* A sink monitor must be connected at this point. See the polling or + * interrupt examples for how to wait for a connection event. */ + Status = Dptx_Run(InstancePtr); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function is used to override the driver's default sleep functionality. + * For MicroBlaze systems, the XDp_WaitUs driver function's default behavior + * is to use the MB_Sleep function from microblaze_sleep.h, which is implemented + * in software and only has millisecond accuracy. For this reason, using a + * hardware timer is preferrable. For ARM/Zynq SoC systems, the SoC's timer is + * used - XDp_WaitUs will ignore this custom timer handler. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note Use the XDp_SetUserTimerHandler driver function to set this + * function as the handler for when the XDp_WaitUs driver + * function is called. + * +*******************************************************************************/ +static void Dptx_CustomWaitUs(void *InstancePtr, u32 MicroSeconds) +{ + XDp *XDp_InstancePtr = (XDp *)InstancePtr; + u32 TimerVal; + + XTmrCtr_Start(XDp_InstancePtr->UserTimerPtr, 0); + + /* Wait specified number of useconds. */ + do { + TimerVal = XTmrCtr_GetValue(XDp_InstancePtr->UserTimerPtr, 0); + } + while (TimerVal < (MicroSeconds * + (XDp_InstancePtr->Config.SAxiClkHz / 1000000))); + + XTmrCtr_Stop(XDp_InstancePtr->UserTimerPtr, 0); +} diff --git a/XilinxProcessorIPLib/drivers/dp/src/Makefile b/XilinxProcessorIPLib/drivers/dp/src/Makefile new file mode 100644 index 00000000..d3030f60 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS= +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +LIBSOURCES:=*.c +INCLUDEFILES:=*.h + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xdp_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling dp" + +xdp_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xdp_includes + +xdp_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/XilinxProcessorIPLib/drivers/dp/src/xdp.c b/XilinxProcessorIPLib/drivers/dp/src/xdp.c new file mode 100644 index 00000000..4af90d04 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/src/xdp.c @@ -0,0 +1,3194 @@ +/******************************************************************************* + * + * 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 xdp.c + * + * Contains a minimal set of functions for the XDp driver that allow access to + * all of the DisplayPort core's functionality. See xdp.h for a detailed + * description of the driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial release. TX code merged from the dptx driver. + *+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdp.h" +#if defined(__arm__) +#include "sleep.h" +#elif defined(__MICROBLAZE__) +#include "microblaze_sleep.h" +#endif +#include "xenv.h" + +/**************************** Constant Definitions ****************************/ + +/* The maximum voltage swing level is 3. */ +#define XDP_TX_MAXIMUM_VS_LEVEL 3 +/* The maximum pre-emphasis level is 3. */ +#define XDP_TX_MAXIMUM_PE_LEVEL 3 + +/* Error out if an AUX request yields a defer reply more than 50 times. */ +#define XDP_AUX_MAX_DEFER_COUNT 50 +/* Error out if an AUX request times out more than 50 times awaiting a reply. */ +#define XDP_AUX_MAX_TIMEOUT_COUNT 50 +/* Error out if checking for a connected device times out more than 50 times. */ +#define XDP_IS_CONNECTED_MAX_TIMEOUT_COUNT 50 + +/****************************** Type Definitions ******************************/ + +/** + * This typedef enumerates the list of training states used in the state machine + * during the link training process. + */ +typedef enum { + XDP_TX_TS_CLOCK_RECOVERY, + XDP_TX_TS_CHANNEL_EQUALIZATION, + XDP_TX_TS_ADJUST_LINK_RATE, + XDP_TX_TS_ADJUST_LANE_COUNT, + XDP_TX_TS_FAILURE, + XDP_TX_TS_SUCCESS +} XDp_TxTrainingState; + +/** + * This typedef describes an AUX transaction. + */ +typedef struct { + u16 CmdCode; /**< The AUX command code that specifies what + type of AUX transaction is taking + place. */ + u8 NumBytes; /**< The number of bytes that the AUX + transaction will perform work on. */ + u32 Address; /**< The AUX or I2C start address that the AUX + transaction will perform work on. */ + u8 *Data; /**< The data buffer that will store the data + read from AUX read transactions or the + data to write for AUX write + transactions. */ +} XDp_AuxTransaction; + +/**************************** Function Prototypes *****************************/ + +/* Initialization functions. */ +static u32 XDp_TxInitialize(XDp *InstancePtr); +static u32 XDp_RxInitialize(XDp *InstancePtr); + +/* Training functions. */ +static u32 XDp_TxRunTraining(XDp *InstancePtr); +static XDp_TxTrainingState XDp_TxTrainingStateClockRecovery(XDp *InstancePtr); +static XDp_TxTrainingState XDp_TxTrainingStateChannelEqualization( + XDp *InstancePtr); +static XDp_TxTrainingState XDp_TxTrainingStateAdjustLinkRate( + XDp *InstancePtr); +static XDp_TxTrainingState XDp_TxTrainingStateAdjustLaneCount( + XDp *InstancePtr); +static u32 XDp_TxGetLaneStatusAdjReqs(XDp *InstancePtr); +static u32 XDp_TxCheckClockRecovery(XDp *InstancePtr, u8 LaneCount); +static u32 XDp_TxCheckChannelEqualization(XDp *InstancePtr, u8 LaneCount); +static void XDp_TxSetVswingPreemp(XDp *InstancePtr, u8 *AuxData); +static u32 XDp_TxAdjVswingPreemp(XDp *InstancePtr); +static u32 XDp_TxSetTrainingPattern(XDp *InstancePtr, u32 Pattern); +static u32 XDp_TxGetTrainingDelay(XDp *InstancePtr, + XDp_TxTrainingState TrainingState); +/* AUX transaction functions. */ +static u32 XDp_TxAuxCommon(XDp *InstancePtr, u32 CmdType, u32 Address, + u32 NumBytes, u8 *Data); +static u32 XDp_TxAuxRequest(XDp *InstancePtr, XDp_AuxTransaction *Request); +static u32 XDp_TxAuxRequestSend(XDp *InstancePtr, XDp_AuxTransaction *Request); +static u32 XDp_TxAuxWaitReply(XDp *InstancePtr); +static u32 XDp_TxAuxWaitReady(XDp *InstancePtr); +/* Miscellaneous functions. */ +static u32 XDp_TxSetClkSpeed(XDp *InstancePtr, u32 Speed); +static u32 XDp_WaitPhyReady(XDp *InstancePtr, u32 Mask); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function retrieves the configuration for this DisplayPort instance and + * fills in the InstancePtr->Config structure. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param ConfigPtr is a pointer to the configuration structure that will + * be used to copy the settings from. + * @param EffectiveAddr is the device base address in the virtual memory + * space. If the address translation is not used, then the physical + * address is passed. + * + * @return None. + * + * @note Unexpected errors may occur if the address mapping is changed + * after this function is invoked. + * +*******************************************************************************/ +void XDp_CfgInitialize(XDp *InstancePtr, XDp_Config *ConfigPtr, + u32 EffectiveAddr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(ConfigPtr != NULL); + Xil_AssertVoid(EffectiveAddr != 0x0); + + InstancePtr->IsReady = 0; + + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + InstancePtr->Config.BaseAddr = EffectiveAddr; + InstancePtr->Config.SAxiClkHz = ConfigPtr->SAxiClkHz; + + InstancePtr->Config.MaxLaneCount = ConfigPtr->MaxLaneCount; + InstancePtr->Config.MaxLinkRate = ConfigPtr->MaxLinkRate; + + InstancePtr->Config.MaxBitsPerColor = ConfigPtr->MaxBitsPerColor; + InstancePtr->Config.QuadPixelEn = ConfigPtr->QuadPixelEn; + InstancePtr->Config.DualPixelEn = ConfigPtr->DualPixelEn; + InstancePtr->Config.YCrCbEn = ConfigPtr->YCrCbEn; + InstancePtr->Config.YOnlyEn = ConfigPtr->YOnlyEn; + InstancePtr->Config.PayloadDataWidth = ConfigPtr->PayloadDataWidth; + + InstancePtr->Config.SecondaryChEn = ConfigPtr->SecondaryChEn; + InstancePtr->Config.NumAudioChs = ConfigPtr->NumAudioChs; + + InstancePtr->Config.MstSupport = ConfigPtr->MstSupport; + InstancePtr->Config.NumMstStreams = ConfigPtr->NumMstStreams; + + InstancePtr->Config.DpProtocol = ConfigPtr->DpProtocol; + + InstancePtr->Config.IsRx = ConfigPtr->IsRx; + + if (XDp_GetCoreType(InstancePtr) == XDP_TX) { + /* Set the DisplayPort TX's voltage swing and pre-emphasis + * levels to their defaults. */ + XDp_TxCfgTxVsOffset(InstancePtr, XDP_TX_VS_LEVEL_OFFSET); + XDp_TxCfgTxVsLevel(InstancePtr, 0, XDP_TX_VS_LEVEL_0); + XDp_TxCfgTxVsLevel(InstancePtr, 1, XDP_TX_VS_LEVEL_1); + XDp_TxCfgTxVsLevel(InstancePtr, 2, XDP_TX_VS_LEVEL_2); + XDp_TxCfgTxVsLevel(InstancePtr, 3, XDP_TX_VS_LEVEL_3); + XDp_TxCfgTxPeLevel(InstancePtr, 0, XDP_TX_PE_LEVEL_0); + XDp_TxCfgTxPeLevel(InstancePtr, 1, XDP_TX_PE_LEVEL_1); + XDp_TxCfgTxPeLevel(InstancePtr, 2, XDP_TX_PE_LEVEL_2); + XDp_TxCfgTxPeLevel(InstancePtr, 3, XDP_TX_PE_LEVEL_3); + } + + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; +} + +/******************************************************************************/ +/** + * This function prepares the DisplayPort core for use depending on whether the + * core is operating in TX or RX mode. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the DisplayPort core was successfully + * initialized. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_Initialize(XDp *InstancePtr) +{ + u32 Status; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (XDp_GetCoreType(InstancePtr) == XDP_TX) { + Status = XDp_TxInitialize(InstancePtr); + } + else { + Status = XDp_RxInitialize(InstancePtr); + } + + return Status; +} + +/******************************************************************************/ +/** + * This function retrieves the RX device's capabilities from the RX device's + * DisplayPort Configuration Data (DPCD). + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the DisplayPort Configuration Data was read + * successfully. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxGetRxCapabilities(XDp *InstancePtr) +{ + u32 Status; + u8 *Dpcd = InstancePtr->TxInstance.RxConfig.DpcdRxCapsField; + XDp_TxLinkConfig *LinkConfig = &InstancePtr->TxInstance.LinkConfig; + XDp_Config *ConfigPtr = &InstancePtr->Config; + u8 RxMaxLinkRate; + u8 RxMaxLaneCount; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(Dpcd != NULL); + Xil_AssertNonvoid(LinkConfig != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + if (!XDp_TxIsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + Status = XDp_TxAuxRead(InstancePtr, XDP_DPCD_RECEIVER_CAP_FIELD_START, + 16, Dpcd); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + RxMaxLinkRate = Dpcd[XDP_DPCD_MAX_LINK_RATE]; + RxMaxLaneCount = Dpcd[XDP_DPCD_MAX_LANE_COUNT] & + XDP_DPCD_MAX_LANE_COUNT_MASK; + LinkConfig->MaxLinkRate = (RxMaxLinkRate > ConfigPtr->MaxLinkRate) ? + ConfigPtr->MaxLinkRate : RxMaxLinkRate; + LinkConfig->MaxLaneCount = (RxMaxLaneCount > ConfigPtr->MaxLaneCount) ? + ConfigPtr->MaxLaneCount : RxMaxLaneCount; + + LinkConfig->SupportEnhancedFramingMode = + Dpcd[XDP_DPCD_MAX_LANE_COUNT] & + XDP_DPCD_ENHANCED_FRAME_SUPPORT_MASK; + LinkConfig->SupportDownspreadControl = + Dpcd[XDP_DPCD_MAX_DOWNSPREAD] & + XDP_DPCD_MAX_DOWNSPREAD_MASK; + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function determines the common capabilities between the DisplayPort TX + * core and the RX device. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if main link settings were successfully set. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxCfgMainLinkMax(XDp *InstancePtr) +{ + u32 Status; + XDp_TxLinkConfig *LinkConfig = &InstancePtr->TxInstance.LinkConfig; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + /* The link rate and lane count will be checked in XDp_TxSetLinkRate and + * XDp_TxSetLaneCount. */ + + if (!XDp_TxIsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + /* Configure the main link to the maximum common link rate between the + * DisplayPort TX core and the RX device. */ + Status = XDp_TxSetLinkRate(InstancePtr, LinkConfig->MaxLinkRate); + if (Status != XST_SUCCESS) { + return Status; + } + + /* Configure the main link to the maximum common lane count between the + * DisplayPort TX core and the RX device. */ + Status = XDp_TxSetLaneCount(InstancePtr, LinkConfig->MaxLaneCount); + if (Status != XST_SUCCESS) { + return Status; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function checks if the link needs training and runs the training + * sequence if training is required. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS was either already trained, or has been + * trained successfully. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxEstablishLink(XDp *InstancePtr) +{ + u32 Status; + u32 Status2; + u32 ReenableMainLink; + XDp_TxLinkConfig *LinkConfig = &InstancePtr->TxInstance.LinkConfig; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid((LinkConfig->LinkRate == + XDP_TX_LINK_BW_SET_162GBPS) || + (LinkConfig->LinkRate == XDP_TX_LINK_BW_SET_270GBPS) || + (LinkConfig->LinkRate == XDP_TX_LINK_BW_SET_540GBPS)); + Xil_AssertNonvoid((LinkConfig->LaneCount == XDP_TX_LANE_COUNT_SET_1) || + (LinkConfig->LaneCount == XDP_TX_LANE_COUNT_SET_2) || + (LinkConfig->LaneCount == XDP_TX_LANE_COUNT_SET_4)); + + XDp_TxResetPhy(InstancePtr, XDP_TX_PHY_CONFIG_PHY_RESET_MASK); + + /* Disable main link during training. */ + ReenableMainLink = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_TX_ENABLE_MAIN_STREAM); + if (ReenableMainLink) { + XDp_TxDisableMainLink(InstancePtr); + } + + /* Train main link. */ + Status = XDp_TxRunTraining(InstancePtr); + + /* Reenable main link after training if required. */ + if (ReenableMainLink != 0) { + XDp_TxEnableMainLink(InstancePtr); + } + + /* Turn off the training pattern and enable scrambler. */ + Status2 = XDp_TxSetTrainingPattern(InstancePtr, + XDP_TX_TRAINING_PATTERN_SET_OFF); + if ((Status != XST_SUCCESS) || (Status2 != XST_SUCCESS)) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function checks if the reciever's DisplayPort Configuration Data (DPCD) + * indicates the reciever has achieved and maintained clock recovery, channel + * equalization, symbol lock, and interlane alignment for all lanes currently in + * use. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LaneCount is the number of lanes to check. + * + * @return + * - XST_SUCCESS if the RX device has maintained clock recovery, + * channel equalization, symbol lock, and interlane alignment. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxCheckLinkStatus(XDp *InstancePtr, u8 LaneCount) +{ + u32 Status; + u8 RetryCount = 0; + XDp_TxLinkConfig *LinkConfig = &InstancePtr->TxInstance.LinkConfig; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid((LaneCount == XDP_TX_LANE_COUNT_SET_1) || + (LaneCount == XDP_TX_LANE_COUNT_SET_2) || + (LaneCount == XDP_TX_LANE_COUNT_SET_4)); + + if (!XDp_TxIsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + /* Retrieve AUX info. */ + do { + /* Get lane and adjustment requests. */ + Status = XDp_TxGetLaneStatusAdjReqs(InstancePtr); + if (Status != XST_SUCCESS) { + /* The AUX read failed. */ + return XST_FAILURE; + } + + /* Check if the link needs training. */ + if ((XDp_TxCheckClockRecovery( + InstancePtr, LaneCount) == XST_SUCCESS) && + (XDp_TxCheckChannelEqualization( + InstancePtr, LaneCount) == XST_SUCCESS)) { + return XST_SUCCESS; + } + + RetryCount++; + } + while (RetryCount < 5); /* Retry up to 5 times. */ + + return XST_FAILURE; +} + +/******************************************************************************/ +/** + * This function enables or disables downshifting during the training process. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Enable controls the downshift feature in the training process. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxEnableTrainAdaptive(XDp *InstancePtr, u8 Enable) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Enable == 1) || (Enable == 0)); + + InstancePtr->TxInstance.TrainAdaptive = Enable; +} + +/******************************************************************************/ +/** + * This function sets a software switch that signifies whether or not a redriver + * exists on the DisplayPort output path. XDp_TxSetVswingPreemp uses this switch + * to determine which set of voltage swing and pre-emphasis values to use in the + * TX core. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Set establishes that a redriver exists in the DisplayPort output + * path. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxSetHasRedriverInPath(XDp *InstancePtr, u8 Set) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Set == 1) || (Set == 0)); + + InstancePtr->TxInstance.BoardChar.HasRedriverInPath = Set; +} + +/******************************************************************************/ +/** + * This function sets the voltage swing offset to use during training when no + * redriver exists. The offset will be added to the DisplayPort TX's voltage + * swing level value when pre-emphasis is used (when the pre-emphasis level not + * equal to 0). + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Offset is the value to set for the voltage swing offset. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxCfgTxVsOffset(XDp *InstancePtr, u8 Offset) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Offset >= 0) && (Offset < 16)); + + InstancePtr->TxInstance.BoardChar.TxVsOffset = Offset; +} + +/******************************************************************************/ +/** + * This function sets the voltage swing level value in the DisplayPort TX that + * will be used during link training for a given voltage swing training level. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Level is the voltage swing training level to set the DisplayPort + * TX level for. + * @param TxLevel is the DisplayPort TX voltage swing level value to be + * used during link training. + * + * @return None. + * + * @note There are 16 possible voltage swing levels in the DisplayPort TX + * core that map to 4 possible voltage swing training levels in the + * RX device. + * +*******************************************************************************/ +void XDp_TxCfgTxVsLevel(XDp *InstancePtr, u8 Level, u8 TxLevel) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Level >= 0) && (Level < 4)); + Xil_AssertVoid((TxLevel >= 0) && (TxLevel < 16)); + + InstancePtr->TxInstance.BoardChar.TxVsLevels[Level] = TxLevel; +} + +/******************************************************************************/ +/** + * This function sets the pre-emphasis level value in the DisplayPort TX that + * will be used during link training for a given pre-emphasis training level. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Level is the pre-emphasis training level to set the DisplayPort + * TX level for. + * @param TxLevel is the DisplayPort TX pre-emphasis level value to be + * used during link training. + * + * @return None. + * + * @note There are 32 possible pre-emphasis levels in the DisplayPort TX + * core that map to 4 possible pre-emphasis training levels in the + * RX device. + * +*******************************************************************************/ +void XDp_TxCfgTxPeLevel(XDp *InstancePtr, u8 Level, u8 TxLevel) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Level >= 0) && (Level < 4)); + Xil_AssertVoid((TxLevel >= 0) && (TxLevel < 32)); + + InstancePtr->TxInstance.BoardChar.TxPeLevels[Level] = TxLevel; +} + +/******************************************************************************/ +/** + * This function checks if there is a connected RX device. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - TRUE if there is a connection. + * - FALSE if there is no connection. + * +*******************************************************************************/ +u32 XDp_TxIsConnected(XDp *InstancePtr) +{ + u32 Status; + u8 Retries = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + + do { + Status = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_TX_INTERRUPT_SIG_STATE) & + XDP_TX_INTERRUPT_SIG_STATE_HPD_STATE_MASK; + + if (Retries > XDP_IS_CONNECTED_MAX_TIMEOUT_COUNT) { + return 0; + } + + Retries++; + XDp_WaitUs(InstancePtr, 1000); + } while (Status == 0); + + return 1; +} + +/******************************************************************************/ +/** + * This function issues a read request over the AUX channel that will read from + * the RX device's DisplayPort Configuration Data (DPCD) address space. The read + * message will be divided into multiple transactions which read a maximum of 16 + * bytes each. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param DpcdAddress is the starting address to read from the RX device. + * @param BytesToRead is the number of bytes to read from the RX device. + * @param ReadData is a pointer to the data buffer that will be filled + * with read data. + * + * @return + * - XST_SUCCESS if the AUX read request was successfully + * acknowledged. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if the AUX request timed out. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxAuxRead(XDp *InstancePtr, u32 DpcdAddress, u32 BytesToRead, + void *ReadData) +{ + u32 Status; + XDp_AuxTransaction Request; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(DpcdAddress <= 0xFFFFF); + Xil_AssertNonvoid(BytesToRead <= 0xFFFFF); + Xil_AssertNonvoid(ReadData != NULL); + + if (!XDp_TxIsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + /* Send AUX read transaction. */ + Status = XDp_TxAuxCommon(InstancePtr, XDP_TX_AUX_CMD_READ, DpcdAddress, + BytesToRead, (u8 *)ReadData); + + return Status; +} + +/******************************************************************************/ +/** + * This function issues a write request over the AUX channel that will write to + * the RX device's DisplayPort Configuration Data (DPCD) address space. The + * write message will be divided into multiple transactions which write a + * maximum of 16 bytes each. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param DpcdAddress is the starting address to write to the RX device. + * @param BytesToWrite is the number of bytes to write to the RX device. + * @param WriteData is a pointer to the data buffer that contains the data + * to be written to the RX device. + * + * @return + * - XST_SUCCESS if the AUX write request was successfully + * acknowledged. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if the AUX request timed out. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxAuxWrite(XDp *InstancePtr, u32 DpcdAddress, u32 BytesToWrite, + void *WriteData) +{ + u32 Status; + XDp_AuxTransaction Request; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(DpcdAddress <= 0xFFFFF); + Xil_AssertNonvoid(BytesToWrite <= 0xFFFFF); + Xil_AssertNonvoid(WriteData != NULL); + + if (!XDp_TxIsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + /* Send AUX write transaction. */ + Status = XDp_TxAuxCommon(InstancePtr, XDP_TX_AUX_CMD_WRITE, DpcdAddress, + BytesToWrite, (u8 *)WriteData); + + return Status; +} + +/******************************************************************************/ +/** + * This function performs an I2C read over the AUX channel. The read message + * will be divided into multiple transactions if the requested data spans + * multiple segments. The segment pointer is automatically incremented and the + * offset is calibrated as needed. E.g. For an overall offset of: + * - 128, an I2C read is done on segptr=0; offset=128. + * - 256, an I2C read is done on segptr=1; offset=0. + * - 384, an I2C read is done on segptr=1; offset=128. + * - 512, an I2C read is done on segptr=2; offset=0. + * - etc. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param IicAddress is the address on the I2C bus of the target device. + * @param Offset is the offset at the specified address of the targeted + * I2C device that the read will start from. + * @param BytesToRead is the number of bytes to read. + * @param ReadData is a pointer to a buffer that will be filled with the + * I2C read data. + * + * @return + * - XST_SUCCESS if the I2C read has successfully completed with no + * errors. + * - XST_ERROR_COUNT_MAX if the AUX request timed out. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxIicRead(XDp *InstancePtr, u8 IicAddress, u16 Offset, + u16 BytesToRead, void *ReadData) +{ + u32 Status; + XDp_AuxTransaction Request; + u8 SegPtr; + u16 NumBytesLeftInSeg; + u16 BytesLeft; + u8 CurrBytesToRead; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(IicAddress <= 0xFF); + Xil_AssertNonvoid(Offset <= 0xFFFF); + Xil_AssertNonvoid(BytesToRead <= 0xFFFF); + Xil_AssertNonvoid(ReadData != NULL); + + if (!XDp_TxIsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + BytesLeft = BytesToRead; + + /* Reposition based on a segment length of 256 bytes. */ + SegPtr = 0; + if (Offset > 255) { + SegPtr += Offset / 256; + Offset %= 256; + } + NumBytesLeftInSeg = 256 - Offset; + + /* Set the segment pointer to 0. */ + if (SegPtr != 0) { + XDp_TxIicWrite(InstancePtr, XDP_SEGPTR_ADDR, 1, &SegPtr); + } + + /* Send I2C read message. Multiple transactions are required if the + * requested data spans multiple segments. */ + while (BytesLeft > 0) { + /* Read the remaining number of bytes as requested. */ + if (NumBytesLeftInSeg >= BytesLeft) { + CurrBytesToRead = BytesLeft; + } + /* Read the remaining data in the current segment boundary. */ + else { + CurrBytesToRead = NumBytesLeftInSeg; + } + + /* Setup the I2C-over-AUX read transaction with the offset. */ + Status = XDp_TxIicWrite(InstancePtr, IicAddress, 1, &Offset); + if (Status != XST_SUCCESS) { + return Status; + } + + /* Send I2C-over-AUX read transaction. */ + Status = XDp_TxAuxCommon(InstancePtr, XDP_TX_AUX_CMD_I2C_READ, + IicAddress, CurrBytesToRead, (u8 *)ReadData); + if (Status != XST_SUCCESS) { + return Status; + } + + /* Previous I2C read was done on the remaining data in the + * current segment; prepare for next read. */ + if (BytesLeft > CurrBytesToRead) { + BytesLeft -= CurrBytesToRead; + Offset += CurrBytesToRead; + ReadData += CurrBytesToRead; + + /* Increment the segment pointer to access more I2C + * address space, if required. */ + if (BytesLeft > 0) { + NumBytesLeftInSeg = 256; + Offset %= 256; + SegPtr++; + + XDp_TxIicWrite(InstancePtr, XDP_SEGPTR_ADDR, + 1, &SegPtr); + } + } + /* Last I2C read. */ + else { + BytesLeft = 0; + } + } + + /* Reset the segment pointer to 0. */ + if (SegPtr != 0) { + SegPtr = 0; + XDp_TxIicWrite(InstancePtr, XDP_SEGPTR_ADDR, 1, &SegPtr); + } + + return Status; +} + +/******************************************************************************/ +/** + * This function performs an I2C write over the AUX channel. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param IicAddress is the address on the I2C bus of the target device. + * @param BytesToWrite is the number of bytes to write. + * @param WriteData is a pointer to a buffer which will be used as the + * data source for the write. + * + * @return + * - XST_SUCCESS if the I2C write has successfully completed with + * no errors. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if the AUX request timed out. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxIicWrite(XDp *InstancePtr, u8 IicAddress, u8 BytesToWrite, + void *WriteData) +{ + u32 Status; + XDp_AuxTransaction Request; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(IicAddress <= 0xFF); + Xil_AssertNonvoid(BytesToWrite <= 0xFF); + Xil_AssertNonvoid(WriteData != NULL); + + if (!XDp_TxIsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + /* Send I2C-over-AUX read transaction. */ + Status = XDp_TxAuxCommon(InstancePtr, XDP_TX_AUX_CMD_I2C_WRITE, + IicAddress, BytesToWrite, (u8 *)WriteData); + + return Status; +} + +/******************************************************************************/ +/** + * This function enables or disables 0.5% spreading of the clock for both the + * DisplayPort and the RX device. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Enable will downspread the main link signal if set to 1 and + * disable downspreading if set to 0. + * + * @return + * - XST_SUCCESS if setting the downspread control enable was + * successful. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxSetDownspread(XDp *InstancePtr, u8 Enable) +{ + u32 Status; + u8 RegVal; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid((Enable == 1) || (Enable == 0)); + + if (!XDp_TxIsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + InstancePtr->TxInstance.LinkConfig.DownspreadControl = Enable; + + /* Write downspread enable to the DisplayPort TX core. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_DOWNSPREAD_CTRL, + InstancePtr->TxInstance.LinkConfig.DownspreadControl); + + /* Preserve the current RX device settings. */ + Status = XDp_TxAuxRead(InstancePtr, XDP_DPCD_DOWNSPREAD_CTRL, 0x1, + &RegVal); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + if (InstancePtr->TxInstance.LinkConfig.DownspreadControl) { + RegVal |= XDP_DPCD_SPREAD_AMP_MASK; + } + else { + RegVal &= ~XDP_DPCD_SPREAD_AMP_MASK; + } + + /* Write downspread enable to the RX device. */ + Status = XDp_TxAuxWrite(InstancePtr, XDP_DPCD_DOWNSPREAD_CTRL, 0x1, + &RegVal); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function enables or disables the enhanced framing symbol sequence for + * both the DisplayPort TX core and the RX device. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Enable will enable enhanced frame mode if set to 1 and disable + * it if set to 0. + * + * @return + * - XST_SUCCESS if setting the enhanced frame mode enable was + * successful. + * - XST_DEVICE_NOT_FOUND if no RX is connected. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxSetEnhancedFrameMode(XDp *InstancePtr, u8 Enable) +{ + u32 Status; + u8 RegVal; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid((Enable == 1) || (Enable == 0)); + + if (!XDp_TxIsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + InstancePtr->TxInstance.LinkConfig.EnhancedFramingMode = Enable; + + /* Write enhanced frame mode enable to the DisplayPort TX core. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_ENHANCED_FRAME_EN, + InstancePtr->TxInstance.LinkConfig.EnhancedFramingMode); + + /* Preserve the current RX device settings. */ + Status = XDp_TxAuxRead(InstancePtr, XDP_DPCD_LANE_COUNT_SET, 0x1, + &RegVal); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + if (InstancePtr->TxInstance.LinkConfig.EnhancedFramingMode) { + RegVal |= XDP_DPCD_ENHANCED_FRAME_EN_MASK; + } + else { + RegVal &= ~XDP_DPCD_ENHANCED_FRAME_EN_MASK; + } + + /* Write enhanced frame mode enable to the RX device. */ + Status = XDp_TxAuxWrite(InstancePtr, XDP_DPCD_LANE_COUNT_SET, 0x1, + &RegVal); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function sets the number of lanes to be used by the main link for both + * the DisplayPort TX core and the RX device. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LaneCount is the number of lanes to be used over the main link. + * + * @return + * - XST_SUCCESS if setting the new lane count was successful. + * - XST_DEVICE_NOT_FOUND if no RX is connected. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxSetLaneCount(XDp *InstancePtr, u8 LaneCount) +{ + u32 Status; + u8 RegVal; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid((LaneCount == XDP_TX_LANE_COUNT_SET_1) || + (LaneCount == XDP_TX_LANE_COUNT_SET_2) || + (LaneCount == XDP_TX_LANE_COUNT_SET_4)); + + if (!XDp_TxIsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + InstancePtr->TxInstance.LinkConfig.LaneCount = LaneCount; + + /* Write the new lane count to the DisplayPort TX core. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_LANE_COUNT_SET, + InstancePtr->TxInstance.LinkConfig.LaneCount); + + /* Preserve the current RX device settings. */ + Status = XDp_TxAuxRead(InstancePtr, XDP_DPCD_LANE_COUNT_SET, 0x1, + &RegVal); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + RegVal &= ~XDP_DPCD_LANE_COUNT_SET_MASK; + RegVal |= InstancePtr->TxInstance.LinkConfig.LaneCount; + + /* Write the new lane count to the RX device. */ + Status = XDp_TxAuxWrite(InstancePtr, XDP_DPCD_LANE_COUNT_SET, 0x1, + &RegVal); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function sets the data rate to be used by the main link for both the + * DisplayPort TX core and the RX device. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkRate is the link rate to be used over the main link based on + * one of the following selects: + * - XDP_TX_LINK_BW_SET_162GBPS = 0x06 (for a 1.62 Gbps data rate) + * - XDP_TX_LINK_BW_SET_270GBPS = 0x0A (for a 2.70 Gbps data rate) + * - XDP_TX_LINK_BW_SET_540GBPS = 0x14 (for a 5.40 Gbps data rate) + * + * @return + * - XST_SUCCESS if setting the new link rate was successful. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxSetLinkRate(XDp *InstancePtr, u8 LinkRate) +{ + u32 Status; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid((LinkRate == XDP_TX_LINK_BW_SET_162GBPS) || + (LinkRate == XDP_TX_LINK_BW_SET_270GBPS) || + (LinkRate == XDP_TX_LINK_BW_SET_540GBPS)); + + if (!XDp_TxIsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + /* Write a corresponding clock frequency to the DisplayPort TX core. */ + switch (LinkRate) { + case XDP_TX_LINK_BW_SET_162GBPS: + Status = XDp_TxSetClkSpeed(InstancePtr, + XDP_TX_PHY_CLOCK_SELECT_162GBPS); + break; + case XDP_TX_LINK_BW_SET_270GBPS: + Status = XDp_TxSetClkSpeed(InstancePtr, + XDP_TX_PHY_CLOCK_SELECT_270GBPS); + break; + case XDP_TX_LINK_BW_SET_540GBPS: + Status = XDp_TxSetClkSpeed(InstancePtr, + XDP_TX_PHY_CLOCK_SELECT_540GBPS); + break; + default: + break; + } + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + InstancePtr->TxInstance.LinkConfig.LinkRate = LinkRate; + + /* Write new link rate to the DisplayPort TX core. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_LINK_BW_SET, + InstancePtr->TxInstance.LinkConfig.LinkRate); + + /* Write new link rate to the RX device. */ + Status = XDp_TxAuxWrite(InstancePtr, XDP_DPCD_LINK_BW_SET, 1, + &InstancePtr->TxInstance.LinkConfig.LinkRate); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function enables or disables scrambling of symbols for both the + * DisplayPort and the RX device. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Enable will enable or disable scrambling. + * + * @return + * - XST_SUCCESS if setting the scrambling enable was successful. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxSetScrambler(XDp *InstancePtr, u8 Enable) +{ + u32 Status; + u8 RegVal; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid((Enable == 1) || (Enable == 0)); + + InstancePtr->TxInstance.LinkConfig.ScramblerEn = Enable; + + /* Write scrambler disable to the DisplayPort TX core. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_SCRAMBLING_DISABLE, + Enable ? 0x0 : 0x1); + + /* Preserve the current RX device settings. */ + Status = XDp_TxAuxRead(InstancePtr, XDP_DPCD_TP_SET, 1, &RegVal); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + if (Enable) { + RegVal &= ~XDP_DPCD_TP_SET_SCRAMB_DIS_MASK; + } + else { + RegVal |= XDP_DPCD_TP_SET_SCRAMB_DIS_MASK; + } + + /* Write scrambler disable to the RX device. */ + Status = XDp_TxAuxWrite(InstancePtr, XDP_DPCD_TP_SET, 1, &RegVal); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function enables the main link. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxEnableMainLink(XDp *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + + /* Reset the scrambler. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, + XDP_TX_FORCE_SCRAMBLER_RESET, 0x1); + + /* Enable the main stream. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, + XDP_TX_ENABLE_MAIN_STREAM, 0x1); +} + +/******************************************************************************/ +/** + * This function disables the main link. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxDisableMainLink(XDp *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + + /* Reset the scrambler. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, + XDP_TX_FORCE_SCRAMBLER_RESET, 0x1); + + /* Disable the main stream. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, + XDP_TX_ENABLE_MAIN_STREAM, 0x0); +} + +/******************************************************************************/ +/** + * This function does a PHY reset. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Reset is the type of reset to assert. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxResetPhy(XDp *InstancePtr, u32 Reset) +{ + u32 PhyVal; + u32 RegVal; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_ENABLE, 0x0); + + /* Preserve the current PHY settings. */ + PhyVal = XDp_ReadReg(InstancePtr->Config.BaseAddr, XDP_TX_PHY_CONFIG); + + /* Apply reset. */ + RegVal = PhyVal | Reset; + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_PHY_CONFIG, RegVal); + + /* Remove reset. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_PHY_CONFIG, PhyVal); + + /* Wait for the PHY to be ready. */ + if (InstancePtr->Config.MaxLaneCount > 2) { + XDp_WaitPhyReady(InstancePtr, + XDP_TX_PHY_STATUS_ALL_LANES_READY_MASK); + } + else { + XDp_WaitPhyReady(InstancePtr, + XDP_TX_PHY_STATUS_LANES_0_1_READY_MASK); + } + + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_ENABLE, 0x1); +} + +/******************************************************************************/ +/** + * This function sets the PHY polarity on all lanes. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Polarity is the value to set for the polarity (0 or 1). + * + * @return None. + * + * @note The individual PHY polarity option will be disabled if set. + * +*******************************************************************************/ +void XDp_TxSetPhyPolarityAll(XDp *InstancePtr, u8 Polarity) +{ + u32 RegVal; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Polarity == 0) || (Polarity == 1)); + + /* Preserve current settings. */ + RegVal = XDp_ReadReg(InstancePtr->Config.BaseAddr, XDP_TX_PHY_CONFIG); + + /* Set the polarity. */ + if (Polarity) { + RegVal |= XDP_TX_PHY_CONFIG_TX_PHY_POLARITY_MASK; + } + else { + RegVal &= ~XDP_TX_PHY_CONFIG_TX_PHY_POLARITY_MASK; + } + + /* Disable individual polarity setting. */ + RegVal &= ~XDP_TX_PHY_CONFIG_TX_PHY_POLARITY_IND_LANE_MASK; + + /* Write the new settings. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_PHY_CONFIG, RegVal); +} + +/******************************************************************************/ +/** + * This function sets the PHY polarity on a specified lane. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Lane is the lane number (0-3) to set the polarity for. + * @param Polarity is the value to set for the polarity (0 or 1). + * + * @return None. + * + * @note If individual lane polarity is used, it is recommended that this + * function is called for every lane in use. + * +*******************************************************************************/ +void XDp_TxSetPhyPolarityLane(XDp *InstancePtr, u8 Lane, u8 Polarity) +{ + u32 RegVal; + u32 MaskVal; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Lane >= 0) && (Lane <= 3)); + Xil_AssertVoid((Polarity == 0) || (Polarity == 1)); + + /* Preserve current settings. */ + RegVal = XDp_ReadReg(InstancePtr->Config.BaseAddr, XDP_TX_PHY_CONFIG); + + /* Determine bit mask to use. */ + switch (Lane) { + case 0: + MaskVal = XDP_TX_PHY_CONFIG_TX_PHY_POLARITY_LANE0_MASK; + break; + case 1: + MaskVal = XDP_TX_PHY_CONFIG_TX_PHY_POLARITY_LANE1_MASK; + break; + case 2: + MaskVal = XDP_TX_PHY_CONFIG_TX_PHY_POLARITY_LANE2_MASK; + break; + case 3: + MaskVal = XDP_TX_PHY_CONFIG_TX_PHY_POLARITY_LANE3_MASK; + break; + default: + break; + } + + /* Set the polarity. */ + if (Polarity) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + + /* Enable individual polarity setting. */ + RegVal |= XDP_TX_PHY_CONFIG_TX_PHY_POLARITY_IND_LANE_MASK; + + /* Write the new settings. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_PHY_CONFIG, RegVal); +} + +/******************************************************************************/ +/** + * This function checks if the reciever's internal registers indicate that link + * training has complete. That is, training has achieved channel equalization, + * symbol lock, and interlane alignment for all lanes currently in use. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the RX device has achieved clock recovery, + * channel equalization, symbol lock, and interlane alignment. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_RxCheckLinkStatus(XDp *InstancePtr) +{ + u8 LaneCount; + u8 LaneStatus[2]; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + + LaneCount = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_RX_DPCD_LANE_COUNT_SET); + + LaneStatus[0] = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_RX_DPCD_LANE01_STATUS); + LaneStatus[1] = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_RX_DPCD_LANE23_STATUS); + + switch (LaneCount) { + case 4: + if (LaneStatus[1] != 0x77) { + return XST_FAILURE; + } + case 2: + if ((LaneStatus[0] & 0x70) != 0x70) { + return XST_FAILURE; + } + case 1: + if ((LaneStatus[0] & 0x07) != 0x07) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function enables the display timing generator (DTG). + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxDtgEn(XDp *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_SOFT_RESET, + XDP_RX_SOFT_RESET_VIDEO_MASK); + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_SOFT_RESET, 0x0); + + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_DTG_ENABLE, 0x1); +} + +/******************************************************************************/ +/** + * This function disables the display timing generator (DTG). + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxDtgDis(XDp *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_DTG_ENABLE, 0x0); + + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_SOFT_RESET, + XDP_RX_SOFT_RESET_VIDEO_MASK); + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_SOFT_RESET, 0x0); +} + +/******************************************************************************/ +/** + * This function sets the maximum data rate to be exposed in the RX device's + * DisplayPort Configuration Data (DPCD) registers. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkRate is the link rate to be used over the main link based on + * one of the following selects: + * - XDP_RX_LINK_BW_SET_162GBPS = 0x06 (for a 1.62 Gbps data rate) + * - XDP_RX_LINK_BW_SET_270GBPS = 0x0A (for a 2.70 Gbps data rate) + * - XDP_RX_LINK_BW_SET_540GBPS = 0x14 (for a 5.40 Gbps data rate) + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxSetLinkRate(XDp *InstancePtr, u8 LinkRate) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + Xil_AssertVoid((LinkRate == XDP_RX_OVER_LINK_BW_SET_162GBPS) || + (LinkRate == XDP_RX_OVER_LINK_BW_SET_270GBPS) || + (LinkRate == XDP_RX_OVER_LINK_BW_SET_540GBPS)); + + InstancePtr->RxInstance.LinkConfig.LinkRate = LinkRate; + + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_OVER_CTRL_DPCD, 0x1); + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_OVER_LINK_BW_SET, + LinkRate); + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_OVER_CTRL_DPCD, 0x0); + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_LOCAL_EDID_VIDEO, + 0x1); +} + +/******************************************************************************/ +/** + * This function sets the maximum lane count to be exposed in the RX device's + * DisplayPort Configuration Data (DPCD) registers. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LaneCount is the number of lanes to be used over the main link. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxSetLaneCount(XDp *InstancePtr, u8 LaneCount) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + Xil_AssertVoid((LaneCount == XDP_RX_OVER_LANE_COUNT_SET_1) || + (LaneCount == XDP_RX_OVER_LANE_COUNT_SET_2) || + (LaneCount == XDP_RX_OVER_LANE_COUNT_SET_4)); + + InstancePtr->RxInstance.LinkConfig.LaneCount = LaneCount; + + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_OVER_CTRL_DPCD, 0x1); + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_OVER_LANE_COUNT_SET, + LaneCount); + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_OVER_CTRL_DPCD, 0x0); + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_LOCAL_EDID_VIDEO, + 0x1); +} + +/******************************************************************************/ +/** + * This function enables audio stream packets on the main link. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxAudioEn(XDp *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_AUDIO_CONTROL, 0x1); +} + +/******************************************************************************/ +/** + * This function disables audio stream packets on the main link. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxAudioDis(XDp *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_AUDIO_CONTROL, 0x0); +} + +/******************************************************************************/ +/** + * This function resets the RX core's reception of audio stream packets on the + * main link. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxAudioReset(XDp *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + + XDp_RxAudioDis(InstancePtr); + XDp_WaitUs(InstancePtr, 1000); + XDp_RxAudioEn(InstancePtr); +} + +/******************************************************************************/ +/** + * This function installs a custom delay/sleep function to be used by the XDp + * driver. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item (microseconds to delay) that + * will be passed to the custom sleep/delay function when it is + * invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_SetUserTimerHandler(XDp *InstancePtr, XDp_TimerHandler CallbackFunc, + void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->UserTimerWaitUs = CallbackFunc; + InstancePtr->UserTimerPtr = CallbackRef; +} + +/******************************************************************************/ +/** + * This function is the delay/sleep function for the XDp driver. For the Zynq + * family, there exists native sleep functionality. For MicroBlaze however, + * there does not exist such functionality. In the MicroBlaze case, the default + * method for delaying is to use a predetermined amount of loop iterations. This + * method is prone to inaccuracy and dependent on system configuration; for + * greater accuracy, the user may supply their own delay/sleep handler, pointed + * to by InstancePtr->UserTimerWaitUs, which may have better accuracy if a + * hardware timer is used. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param MicroSeconds is the number of microseconds to delay/sleep for. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_WaitUs(XDp *InstancePtr, u32 MicroSeconds) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (MicroSeconds == 0) { + return; + } + +#if defined(__arm__) + /* Wait the requested amount of time. */ + usleep(MicroSeconds); +#elif defined(__MICROBLAZE__) + if (InstancePtr->UserTimerWaitUs != NULL) { + /* Use the timer handler specified by the user for better + * accuracy. */ + InstancePtr->UserTimerWaitUs(InstancePtr, MicroSeconds); + } + else { + /* MicroBlaze sleep only has millisecond accuracy. Round up. */ + u32 MilliSeconds = (MicroSeconds + 999) / 1000; + MB_Sleep(MilliSeconds); + } +#endif +} + +/******************************************************************************/ +/** + * This function prepares the DisplayPort TX core for use. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the DisplayPort TX core was successfully + * initialized. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxInitialize(XDp *InstancePtr) +{ + u32 Status; + u32 PhyVal; + u32 RegVal; + XDp_Config *ConfigPtr = &InstancePtr->Config; + + /* Preserve the current PHY settings. */ + PhyVal = XDp_ReadReg(ConfigPtr->BaseAddr, XDP_TX_PHY_CONFIG); + + /* Place the PHY (and GTTXRESET) into reset. */ + RegVal = PhyVal | XDP_TX_PHY_CONFIG_GT_ALL_RESET_MASK; + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_PHY_CONFIG, RegVal); + + /* Reset the video streams and AUX logic. */ + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_SOFT_RESET, + XDP_TX_SOFT_RESET_VIDEO_STREAM_ALL_MASK | + XDP_TX_SOFT_RESET_AUX_MASK); + + /* Disable the DisplayPort TX core. */ + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_ENABLE, 0); + + /* Set the clock divider. */ + RegVal = (XDp_ReadReg(ConfigPtr->BaseAddr, XDP_TX_AUX_CLK_DIVIDER) & + ~XDP_TX_AUX_CLK_DIVIDER_VAL_MASK) | + (ConfigPtr->SAxiClkHz / 1000000); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_AUX_CLK_DIVIDER, RegVal); + + /* Set the DisplayPort TX core's clock speed. */ + switch (ConfigPtr->MaxLinkRate) { + case XDP_TX_LINK_BW_SET_540GBPS: + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_PHY_CLOCK_SELECT, + XDP_TX_PHY_CLOCK_SELECT_540GBPS); + break; + case XDP_TX_LINK_BW_SET_270GBPS: + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_PHY_CLOCK_SELECT, + XDP_TX_PHY_CLOCK_SELECT_270GBPS); + break; + case XDP_TX_LINK_BW_SET_162GBPS: + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_PHY_CLOCK_SELECT, + XDP_TX_PHY_CLOCK_SELECT_162GBPS); + break; + default: + break; + } + + /* Bring the PHY (and GTTXRESET) out of reset. */ + RegVal = PhyVal & ~XDP_TX_PHY_CONFIG_GT_ALL_RESET_MASK; + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_PHY_CONFIG, RegVal); + + /* Wait for the PHY to be ready. */ + if (ConfigPtr->MaxLaneCount > 2) { + Status = XDp_WaitPhyReady(InstancePtr, + XDP_TX_PHY_STATUS_ALL_LANES_READY_MASK); + } + else { + Status = XDp_WaitPhyReady(InstancePtr, + XDP_TX_PHY_STATUS_LANES_0_1_READY_MASK); + } + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* Enable the DisplayPort TX core. */ + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_ENABLE, 1); + + /* Unmask Hot-Plug-Detect (HPD) interrupts. */ + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_INTERRUPT_MASK, + ~XDP_TX_INTERRUPT_MASK_HPD_PULSE_DETECTED_MASK & + ~XDP_TX_INTERRUPT_MASK_HPD_EVENT_MASK & + ~XDP_TX_INTERRUPT_MASK_HPD_IRQ_MASK); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function prepares the DisplayPort RX core for use. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the DisplayPort RX core was successfully + * initialized. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_RxInitialize(XDp *InstancePtr) +{ + u32 Status; + + /* Disable the main link. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_LINK_ENABLE, 0x0); + + /* Set the AUX clock divider. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_AUX_CLK_DIVIDER, + (InstancePtr->Config.SAxiClkHz / 1000000)); + + /* Put both GT RX/TX and CPLL into reset. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_PHY_CONFIG, + XDP_RX_PHY_CONFIG_GTPLL_RESET_MASK | + XDP_RX_PHY_CONFIG_GTRX_RESET_MASK); + + /* Release CPLL reset. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_PHY_CONFIG, + XDP_RX_PHY_CONFIG_GTRX_RESET_MASK); + + /* Wait until all lane CPLLs have locked. */ + if (InstancePtr->Config.MaxLaneCount > 2) { + Status = XDp_WaitPhyReady(InstancePtr, + XDP_RX_PHY_STATUS_PLL_LANE0_1_LOCK_MASK | + XDP_RX_PHY_STATUS_PLL_LANE2_3_LOCK_MASK); + } + else { + Status = XDp_WaitPhyReady(InstancePtr, + XDP_RX_PHY_STATUS_PLL_LANE0_1_LOCK_MASK); + } + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* Remove the reset from the PHY. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_PHY_CONFIG, + XDP_RX_PHY_CONFIG_PHY_RESET_ENABLE_MASK); + + /* Wait until the PHY has completed the reset cycle. */ + if (InstancePtr->Config.MaxLaneCount > 2) { + Status = XDp_WaitPhyReady(InstancePtr, + XDP_RX_PHY_STATUS_ALL_LANES_READY_MASK | + XDP_RX_PHY_STATUS_PLL_FABRIC_LOCK_MASK | + XDP_RX_PHY_STATUS_RX_CLK_LOCK_MASK); + } + else { + Status = XDp_WaitPhyReady(InstancePtr, + XDP_RX_PHY_STATUS_LANES_0_1_READY_MASK | + XDP_RX_PHY_STATUS_PLL_FABRIC_LOCK_MASK | + XDP_RX_PHY_STATUS_RX_CLK_LOCK_MASK); + } + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* Enable the RX core. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_LINK_ENABLE, 0x1); + + /* Set other user parameters. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_MIN_VOLTAGE_SWING, + 0x01); + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_SINK_COUNT, 0x01); + /* Set the AUX training interval. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_OVER_CTRL_DPCD, 0x1); + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_OVER_TP_SET, + (2 << XDP_RX_OVER_TP_SET_TRAINING_AUX_RD_INTERVAL_SHIFT)); + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_OVER_CTRL_DPCD, 0x0); + /* Set the link configuration.*/ + XDp_RxSetLinkRate(InstancePtr, + InstancePtr->RxInstance.LinkConfig.LinkRate); + XDp_RxSetLaneCount(InstancePtr, + InstancePtr->RxInstance.LinkConfig.LaneCount); + /* Set the interrupt masks. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_INTERRUPT_MASK, + ~XDP_RX_INTERRUPT_MASK_ALL_MASK); + + /* Enable the display timing generator. */ + XDp_RxDtgEn(InstancePtr); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function runs the link training process. It is implemented as a state + * machine, with each state returning the next state. First, the clock recovery + * sequence will be run; if successful, the channel equalization sequence will + * run. If either the clock recovery or channel equalization sequence failed, + * the link rate or the number of lanes used will be reduced and training will + * be re-attempted. If training fails at the minimal data rate, 1.62 Gbps with + * a single lane, training will no longer re-attempt and fail. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the training process succeeded. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxRunTraining(XDp *InstancePtr) +{ + u32 Status; + XDp_TxTrainingState TrainingState = XDP_TX_TS_CLOCK_RECOVERY; + + while (1) { + switch (TrainingState) { + case XDP_TX_TS_CLOCK_RECOVERY: + TrainingState = XDp_TxTrainingStateClockRecovery( + InstancePtr); + break; + case XDP_TX_TS_CHANNEL_EQUALIZATION: + TrainingState = XDp_TxTrainingStateChannelEqualization( + InstancePtr); + break; + case XDP_TX_TS_ADJUST_LINK_RATE: + TrainingState = XDp_TxTrainingStateAdjustLinkRate( + InstancePtr); + break; + case XDP_TX_TS_ADJUST_LANE_COUNT: + TrainingState = XDp_TxTrainingStateAdjustLaneCount( + InstancePtr); + break; + default: + break; + } + + if (TrainingState == XDP_TX_TS_SUCCESS) { + break; + } + else if (TrainingState == XDP_TX_TS_FAILURE) { + return XST_FAILURE; + } + + if ((InstancePtr->TxInstance.TrainAdaptive == 0) && + ((TrainingState == XDP_TX_TS_ADJUST_LANE_COUNT) || + (TrainingState == XDP_TX_TS_ADJUST_LINK_RATE))) { + return XST_FAILURE; + } + if ((TrainingState == XDP_TX_TS_ADJUST_LINK_RATE) || + (TrainingState == XDP_TX_TS_ADJUST_LANE_COUNT)) { + Status = XDp_TxSetTrainingPattern(InstancePtr, + XDP_TX_TRAINING_PATTERN_SET_OFF); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + } + } + + /* Final status check. */ + Status = XDp_TxCheckLinkStatus(InstancePtr, + InstancePtr->TxInstance.LinkConfig.LaneCount); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function runs the clock recovery sequence as part of link training. The + * sequence is as follows: + * 0) Start signaling at the minimum voltage swing, pre-emphasis, and post- + * cursor levels. + * 1) Transmit training pattern 1 over the main link with symbol scrambling + * disabled. + * 2) The clock recovery loop. If clock recovery is unsuccessful after + * MaxIterations loop iterations, return. + * 2a) Wait for at least the period of time specified in the RX device's + * DisplayPort Configuration Data (DPCD) register, + * TRAINING_AUX_RD_INTERVAL. + * 2b) Check if all lanes have achieved clock recovery lock. If so, return. + * 2c) Check if the same voltage swing level has been used 5 consecutive + * times or if the maximum level has been reached. If so, return. + * 2d) Adjust the voltage swing, pre-emphasis, and post-cursor levels as + * requested by the RX device. + * 2e) Loop back to 2a. + * For a more detailed description of the clock recovery sequence, see section + * 3.5.1.2.1 of the DisplayPort 1.2a specification document. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return The next training state: + * - XDP_TX_TS_CHANNEL_EQUALIZATION if the clock recovery sequence + * completed successfully. + * - XDP_TX_TS_FAILURE if writing the drive settings to the RX + * device was unsuccesful. + * - XDP_TX_TS_ADJUST_LINK_RATE if the clock recovery sequence + * did not complete successfully. + * + * @note None. + * +*******************************************************************************/ +static XDp_TxTrainingState XDp_TxTrainingStateClockRecovery(XDp *InstancePtr) +{ + u32 Status; + u32 DelayUs; + u8 PrevVsLevel = 0; + u8 SameVsLevelCount = 0; + XDp_TxLinkConfig *LinkConfig = &InstancePtr->TxInstance.LinkConfig; + + /* Obtain the required delay for clock recovery as specified by the + * RX device. */ + DelayUs = XDp_TxGetTrainingDelay(InstancePtr, XDP_TX_TS_CLOCK_RECOVERY); + + /* Start CRLock. */ + + /* Transmit training pattern 1. */ + /* Disable the scrambler. */ + /* Start from minimal voltage swing and pre-emphasis levels. */ + InstancePtr->TxInstance.LinkConfig.VsLevel = 0; + InstancePtr->TxInstance.LinkConfig.PeLevel = 0; + Status = XDp_TxSetTrainingPattern(InstancePtr, + XDP_TX_TRAINING_PATTERN_SET_TP1); + if (Status != XST_SUCCESS) { + return XDP_TX_TS_FAILURE; + } + + while (1) { + /* Wait delay specified in TRAINING_AUX_RD_INTERVAL. */ + XDp_WaitUs(InstancePtr, DelayUs); + + /* Get lane and adjustment requests. */ + Status = XDp_TxGetLaneStatusAdjReqs(InstancePtr); + if (Status != XST_SUCCESS) { + /* The AUX read failed. */ + return XDP_TX_TS_FAILURE; + } + + /* Check if all lanes have realized and maintained the frequency + * lock and get adjustment requests. */ + Status = XDp_TxCheckClockRecovery(InstancePtr, + InstancePtr->TxInstance.LinkConfig.LaneCount); + if (Status == XST_SUCCESS) { + return XDP_TX_TS_CHANNEL_EQUALIZATION; + } + + /* Check if the same voltage swing for each lane has been used 5 + * consecutive times. */ + if (PrevVsLevel == LinkConfig->VsLevel) { + SameVsLevelCount++; + } + else { + SameVsLevelCount = 0; + PrevVsLevel = LinkConfig->VsLevel; + } + if (SameVsLevelCount >= 5) { + break; + } + if (LinkConfig->VsLevel == XDP_TX_MAXIMUM_VS_LEVEL) { + break; + } + + /* Adjust the drive settings as requested by the RX device. */ + Status = XDp_TxAdjVswingPreemp(InstancePtr); + if (Status != XST_SUCCESS) { + /* The AUX write failed. */ + return XDP_TX_TS_FAILURE; + } + } + + return XDP_TX_TS_ADJUST_LINK_RATE; +} + +/******************************************************************************/ +/** + * This function runs the channel equalization sequence as part of link + * training. The sequence is as follows: + * 0) Start signaling with the same drive settings used at the end of the + * clock recovery sequence. + * 1) Transmit training pattern 2 (or 3) over the main link with symbol + * scrambling disabled. + * 2) The channel equalization loop. If channel equalization is + * unsuccessful after 5 loop iterations, return. + * 2a) Wait for at least the period of time specified in the RX device's + * DisplayPort Configuration Data (DPCD) register, + * TRAINING_AUX_RD_INTERVAL. + * 2b) Check if all lanes have achieved channel equalization, symbol lock, + * and interlane alignment. If so, return. + * 2c) Check if the same voltage swing level has been used 5 consecutive + * times or if the maximum level has been reached. If so, return. + * 2d) Adjust the voltage swing, pre-emphasis, and post-cursor levels as + * requested by the RX device. + * 2e) Loop back to 2a. + * For a more detailed description of the channel equalization sequence, see + * section 3.5.1.2.2 of the DisplayPort 1.2a specification document. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return The next training state: + * - XDP_TX_TS_SUCCESS if training succeeded. + * - XDP_TX_TS_FAILURE if writing the drive settings to the RX + * device was unsuccesful. + * - XDP_TX_TS_ADJUST_LINK_RATE if, after 5 loop iterations, the + * channel equalization sequence did not complete successfully. + * + * @note None. + * +*******************************************************************************/ +static XDp_TxTrainingState XDp_TxTrainingStateChannelEqualization( + XDp *InstancePtr) +{ + u32 Status; + u32 DelayUs; + u32 IterationCount = 0; + XDp_TxLinkConfig *LinkConfig = &InstancePtr->TxInstance.LinkConfig; + + /* Obtain the required delay for channel equalization as specified by + * the RX device. */ + DelayUs = XDp_TxGetTrainingDelay(InstancePtr, + XDP_TX_TS_CHANNEL_EQUALIZATION); + + /* Start channel equalization. */ + + /* Write the current drive settings. */ + /* Transmit training pattern 2/3. */ + if (InstancePtr->TxInstance.RxConfig. + DpcdRxCapsField[XDP_DPCD_MAX_LANE_COUNT] & + XDP_DPCD_TPS3_SUPPORT_MASK) { + Status = XDp_TxSetTrainingPattern(InstancePtr, + XDP_TX_TRAINING_PATTERN_SET_TP3); + } + else { + Status = XDp_TxSetTrainingPattern(InstancePtr, + XDP_TX_TRAINING_PATTERN_SET_TP2); + } + if (Status != XST_SUCCESS) { + return XDP_TX_TS_FAILURE; + } + + while (IterationCount < 5) { + /* Wait delay specified in TRAINING_AUX_RD_INTERVAL. */ + XDp_WaitUs(InstancePtr, DelayUs); + + /* Get lane and adjustment requests. */ + Status = XDp_TxGetLaneStatusAdjReqs(InstancePtr); + if (Status != XST_SUCCESS) { + /* The AUX read failed. */ + return XDP_TX_TS_FAILURE; + } + + /* Check that all lanes still have their clocks locked. */ + Status = XDp_TxCheckClockRecovery(InstancePtr, + InstancePtr->TxInstance.LinkConfig.LaneCount); + if (Status != XST_SUCCESS) { + break; + } + + /* Check that all lanes stihave accomplished channel + * equalization, symbol lock, and interlane alignment. */ + Status = XDp_TxCheckChannelEqualization(InstancePtr, + InstancePtr->TxInstance.LinkConfig.LaneCount); + if (Status == XST_SUCCESS) { + return XDP_TX_TS_SUCCESS; + } + + /* Adjust the drive settings as requested by the RX device. */ + Status = XDp_TxAdjVswingPreemp(InstancePtr); + if (Status != XST_SUCCESS) { + /* The AUX write failed. */ + return XDP_TX_TS_FAILURE; + } + + IterationCount++; + } + + /* Tried MaxIteration times with no success. Try a reduced bitrate + * first, then reduce the number of lanes. */ + return XDP_TX_TS_ADJUST_LINK_RATE; +} + +/******************************************************************************/ +/** + * This function is reached if either the clock recovery or the channel + * equalization process failed during training. As a result, the data rate will + * be downshifted, and training will be re-attempted (starting with clock + * recovery) at the reduced data rate. If the data rate is already at 1.62 Gbps, + * a downshift in lane count will be attempted. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return The next training state: + * - XDP_TX_TS_ADJUST_LANE_COUNT if the minimal data rate is + * already in use. Re-attempt training at a reduced lane count. + * - XDP_TX_TS_CLOCK_RECOVERY otherwise. Re-attempt training. + * + * @note None. + * +*******************************************************************************/ +static XDp_TxTrainingState XDp_TxTrainingStateAdjustLinkRate(XDp *InstancePtr) +{ + u32 Status; + + switch (InstancePtr->TxInstance.LinkConfig.LinkRate) { + case XDP_TX_LINK_BW_SET_540GBPS: + Status = XDp_TxSetLinkRate(InstancePtr, + XDP_TX_LINK_BW_SET_270GBPS); + if (Status != XST_SUCCESS) { + Status = XDP_TX_TS_FAILURE; + break; + } + Status = XDP_TX_TS_CLOCK_RECOVERY; + break; + case XDP_TX_LINK_BW_SET_270GBPS: + Status = XDp_TxSetLinkRate(InstancePtr, + XDP_TX_LINK_BW_SET_162GBPS); + if (Status != XST_SUCCESS) { + Status = XDP_TX_TS_FAILURE; + break; + } + Status = XDP_TX_TS_CLOCK_RECOVERY; + break; + default: + /* Already at the lowest link rate. Try reducing the lane + * count next. */ + Status = XDP_TX_TS_ADJUST_LANE_COUNT; + break; + } + + return Status; +} + +/******************************************************************************/ +/** + * This function is reached if either the clock recovery or the channel + * equalization process failed during training, and a minimal data rate of 1.62 + * Gbps was being used. As a result, the number of lanes in use will be reduced, + * and training will be re-attempted (starting with clock recovery) at this + * lower lane count. + * + * @note Training will be re-attempted with the maximum data rate being + * used with the reduced lane count to train at the main link at + * the maximum bandwidth possible. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return The next training state: + * - XDP_TX_TS_FAILURE if only one lane is already in use. + * - XDP_TX_TS_CLOCK_RECOVERY otherwise. Re-attempt training. + * + * @note None. + * +*******************************************************************************/ +static XDp_TxTrainingState XDp_TxTrainingStateAdjustLaneCount(XDp *InstancePtr) +{ + u32 Status; + XDp_TxLinkConfig *LinkConfig = &InstancePtr->TxInstance.LinkConfig; + + switch (LinkConfig->LaneCount) { + case XDP_TX_LANE_COUNT_SET_4: + Status = XDp_TxSetLaneCount(InstancePtr, + XDP_TX_LANE_COUNT_SET_2); + if (Status != XST_SUCCESS) { + Status = XDP_TX_TS_FAILURE; + break; + } + + Status = XDp_TxSetLinkRate(InstancePtr, + LinkConfig->MaxLinkRate); + if (Status != XST_SUCCESS) { + Status = XDP_TX_TS_FAILURE; + break; + } + Status = XDP_TX_TS_CLOCK_RECOVERY; + break; + case XDP_TX_LANE_COUNT_SET_2: + Status = XDp_TxSetLaneCount(InstancePtr, + XDP_TX_LANE_COUNT_SET_1); + if (Status != XST_SUCCESS) { + Status = XDP_TX_TS_FAILURE; + break; + } + + Status = XDp_TxSetLinkRate(InstancePtr, + LinkConfig->MaxLinkRate); + if (Status != XST_SUCCESS) { + Status = XDP_TX_TS_FAILURE; + break; + } + Status = XDP_TX_TS_CLOCK_RECOVERY; + break; + default: + /* Already at the lowest lane count. Training has failed at the + * lowest lane count and link rate. */ + Status = XDP_TX_TS_FAILURE; + break; + } + + return Status; +} + +/******************************************************************************/ +/** + * This function will do a burst AUX read from the RX device over the AUX + * channel. The contents of the status registers will be stored for later use by + * XDp_TxCheckClockRecovery, XDp_TxCheckChannelEqualization, and + * XDp_TxAdjVswingPreemp. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the AUX read was successful. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxGetLaneStatusAdjReqs(XDp *InstancePtr) +{ + u32 Status; + + /* Read and store 4 bytes of lane status and 2 bytes of adjustment + * requests. */ + Status = XDp_TxAuxRead(InstancePtr, XDP_DPCD_STATUS_LANE_0_1, + 6, InstancePtr->TxInstance.RxConfig.LaneStatusAdjReqs); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function checks if the RX device's DisplayPort Configuration Data (DPCD) + * indicates that the clock recovery sequence during link training was + * successful - the RX device's link clock and data recovery unit has realized + * and maintained the frequency lock for all lanes currently in use. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LaneCount is the number of lanes to check. + * + * @return + * - XST_SUCCESS if the RX device's clock recovery PLL has + * achieved frequency lock for all lanes in use. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxCheckClockRecovery(XDp *InstancePtr, u8 LaneCount) +{ + u32 Status; + u8 AuxData[6]; + + u8 *LaneStatus = InstancePtr->TxInstance.RxConfig.LaneStatusAdjReqs; + + /* Check that all LANEx_CR_DONE bits are set. */ + switch (LaneCount) { + case XDP_TX_LANE_COUNT_SET_4: + if (!(LaneStatus[1] & + XDP_DPCD_STATUS_LANE_3_CR_DONE_MASK)) { + return XST_FAILURE; + } + if (!(LaneStatus[1] & + XDP_DPCD_STATUS_LANE_2_CR_DONE_MASK)) { + return XST_FAILURE; + } + /* Drop through and check lane 1. */ + case XDP_TX_LANE_COUNT_SET_2: + if (!(LaneStatus[0] & + XDP_DPCD_STATUS_LANE_1_CR_DONE_MASK)) { + return XST_FAILURE; + } + /* Drop through and check lane 0. */ + case XDP_TX_LANE_COUNT_SET_1: + if (!(LaneStatus[0] & + XDP_DPCD_STATUS_LANE_0_CR_DONE_MASK)) { + return XST_FAILURE; + } + default: + /* All (LaneCount) lanes have achieved clock recovery. */ + break; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function checks if the RX device's DisplayPort Configuration Data (DPCD) + * indicates that the channel equalization sequence during link training was + * successful - the RX device has achieved channel equalization, symbol lock, + * and interlane alignment for all lanes currently in use. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LaneCount is the number of lanes to check. + * + * @return + * - XST_SUCCESS if the RX device has achieved channel + * equalization symbol lock, and interlane alignment for all + * lanes in use. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxCheckChannelEqualization(XDp *InstancePtr, u8 LaneCount) +{ + u32 Status; + u8 AuxData[6]; + u8 *LaneStatus = InstancePtr->TxInstance.RxConfig.LaneStatusAdjReqs; + + /* Check that all LANEx_CHANNEL_EQ_DONE bits are set. */ + switch (LaneCount) { + case XDP_TX_LANE_COUNT_SET_4: + if (!(LaneStatus[1] & + XDP_DPCD_STATUS_LANE_3_CE_DONE_MASK)) { + return XST_FAILURE; + } + if (!(LaneStatus[1] & + XDP_DPCD_STATUS_LANE_2_CE_DONE_MASK)) { + return XST_FAILURE; + } + /* Drop through and check lane 1. */ + case XDP_TX_LANE_COUNT_SET_2: + if (!(LaneStatus[0] & + XDP_DPCD_STATUS_LANE_1_CE_DONE_MASK)) { + return XST_FAILURE; + } + /* Drop through and check lane 0. */ + case XDP_TX_LANE_COUNT_SET_1: + if (!(LaneStatus[0] & + XDP_DPCD_STATUS_LANE_0_CE_DONE_MASK)) { + return XST_FAILURE; + } + default: + /* All (LaneCount) lanes have achieved channel equalization. */ + break; + } + + /* Check that all LANEx_SYMBOL_LOCKED bits are set. */ + switch (LaneCount) { + case XDP_TX_LANE_COUNT_SET_4: + if (!(LaneStatus[1] & + XDP_DPCD_STATUS_LANE_3_SL_DONE_MASK)) { + return XST_FAILURE; + } + if (!(LaneStatus[1] & + XDP_DPCD_STATUS_LANE_2_SL_DONE_MASK)) { + return XST_FAILURE; + } + /* Drop through and check lane 1. */ + case XDP_TX_LANE_COUNT_SET_2: + if (!(LaneStatus[0] & + XDP_DPCD_STATUS_LANE_1_SL_DONE_MASK)) { + return XST_FAILURE; + } + /* Drop through and check lane 0. */ + case XDP_TX_LANE_COUNT_SET_1: + if (!(LaneStatus[0] & + XDP_DPCD_STATUS_LANE_0_SL_DONE_MASK)) { + return XST_FAILURE; + } + default: + /* All (LaneCount) lanes have achieved symbol lock. */ + break; + } + + /* Check that interlane alignment is done. */ + if (!(LaneStatus[2] & + XDP_DPCD_LANE_ALIGN_STATUS_UPDATED_IA_DONE_MASK)) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function sets current voltage swing and pre-emphasis level settings from + * the LinkConfig structure to hardware. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param AuxData is a pointer to the array used for preparing a burst + * write over the AUX channel. + * + * @return + * - XST_SUCCESS if writing the settings was successful. + * - XST_FAILURE otherwise. + * + * @note 7-series FPGAs registers use the terminology POSTCURSOR(1) to + * represent the DisplayPort pre-emphasis levels. + * +*******************************************************************************/ +static void XDp_TxSetVswingPreemp(XDp *InstancePtr, u8 *AuxData) +{ + u32 Status; + u8 Data; + u8 Index; + u8 VsLevelRx = InstancePtr->TxInstance.LinkConfig.VsLevel; + u8 PeLevelRx = InstancePtr->TxInstance.LinkConfig.PeLevel; + u32 VsLevel; + u32 PeLevel; + + if (InstancePtr->TxInstance.BoardChar.HasRedriverInPath == 0) { + PeLevel = + InstancePtr->TxInstance.BoardChar.TxPeLevels[PeLevelRx]; + VsLevel = + InstancePtr->TxInstance.BoardChar.TxVsLevels[VsLevelRx]; + + /* Need to compensate due to no redriver in the path. */ + if (PeLevelRx != 0) { + VsLevel += InstancePtr->TxInstance.BoardChar.TxVsOffset; + } + } + else { + /* No need to compensate since redriver does that. Can evenly + * disperse the voltage swing and pre-emphasis levels. */ + + /* Map 16 possible voltage swing levels in the DisplayPort TX + * core to 4 possible in the RX device. */ + VsLevel = VsLevelRx * 4 + 2; + /* Map 32 possible pre-emphasis levels in the DisplayPort TX + * core to 4 possible in the RX device. */ + PeLevel = PeLevelRx * 8 + 4; + } + + /* Set up the data buffer for writing to the RX device. */ + Data = (PeLevelRx << XDP_DPCD_TRAINING_LANEX_SET_PE_SHIFT) | + VsLevelRx; + /* The maximum voltage swing has been reached. */ + if (VsLevelRx == XDP_TX_MAXIMUM_VS_LEVEL) { + Data |= XDP_DPCD_TRAINING_LANEX_SET_MAX_VS_MASK; + } + /* The maximum pre-emphasis level has been reached. */ + if (PeLevelRx == XDP_TX_MAXIMUM_PE_LEVEL) { + Data |= XDP_DPCD_TRAINING_LANEX_SET_MAX_PE_MASK; + } + memset(AuxData, Data, 4); + + for (Index = 0; Index < InstancePtr->TxInstance.LinkConfig.LaneCount; + Index++) { + /* Disable pre-cursor levels. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, + XDP_TX_PHY_PRECURSOR_LANE_0 + 4 * Index, 0x0); + + /* Write new voltage swing levels to the TX registers. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, + XDP_TX_PHY_VOLTAGE_DIFF_LANE_0 + 4 * Index, VsLevel); + + /* Write new pre-emphasis levels to the TX registers. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, + XDP_TX_PHY_POSTCURSOR_LANE_0 + 4 * Index, PeLevel); + } +} + +/******************************************************************************/ +/** + * This function sets new voltage swing and pre-emphasis levels using the + * adjustment requests obtained from the RX device. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the new levels were written successfully. + * - XST_FAILURE otherwise (an AUX transaction failed). + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxAdjVswingPreemp(XDp *InstancePtr) +{ + u32 Status; + u8 Index; + u8 VsLevelAdjReq[4]; + u8 PeLevelAdjReq[4]; + u8 AuxData[4]; + u8 *AdjReqs = &InstancePtr->TxInstance.RxConfig.LaneStatusAdjReqs[4]; + + /* Analyze the adjustment requests for changes in voltage swing and + * pre-emphasis levels. */ + VsLevelAdjReq[0] = AdjReqs[0] & XDP_DPCD_ADJ_REQ_LANE_0_2_VS_MASK; + VsLevelAdjReq[1] = (AdjReqs[0] & XDP_DPCD_ADJ_REQ_LANE_1_3_VS_MASK) >> + XDP_DPCD_ADJ_REQ_LANE_1_3_VS_SHIFT; + VsLevelAdjReq[2] = AdjReqs[1] & XDP_DPCD_ADJ_REQ_LANE_0_2_VS_MASK; + VsLevelAdjReq[3] = (AdjReqs[1] & XDP_DPCD_ADJ_REQ_LANE_1_3_VS_MASK) >> + XDP_DPCD_ADJ_REQ_LANE_1_3_VS_SHIFT; + PeLevelAdjReq[0] = (AdjReqs[0] & XDP_DPCD_ADJ_REQ_LANE_0_2_PE_MASK) >> + XDP_DPCD_ADJ_REQ_LANE_0_2_PE_SHIFT; + PeLevelAdjReq[1] = (AdjReqs[0] & XDP_DPCD_ADJ_REQ_LANE_1_3_PE_MASK) >> + XDP_DPCD_ADJ_REQ_LANE_1_3_PE_SHIFT; + PeLevelAdjReq[2] = (AdjReqs[1] & XDP_DPCD_ADJ_REQ_LANE_0_2_PE_MASK) >> + XDP_DPCD_ADJ_REQ_LANE_0_2_PE_SHIFT; + PeLevelAdjReq[3] = (AdjReqs[1] & XDP_DPCD_ADJ_REQ_LANE_1_3_PE_MASK) >> + XDP_DPCD_ADJ_REQ_LANE_1_3_PE_SHIFT; + + /* Change the drive settings to match the adjustment requests. Use the + * greatest level requested. */ + InstancePtr->TxInstance.LinkConfig.VsLevel = 0; + InstancePtr->TxInstance.LinkConfig.PeLevel = 0; + for (Index = 0; Index < InstancePtr->TxInstance.LinkConfig.LaneCount; + Index++) { + if (VsLevelAdjReq[Index] > + InstancePtr->TxInstance.LinkConfig.VsLevel) { + InstancePtr->TxInstance.LinkConfig.VsLevel = + VsLevelAdjReq[Index]; + } + if (PeLevelAdjReq[Index] > + InstancePtr->TxInstance.LinkConfig.PeLevel) { + InstancePtr->TxInstance.LinkConfig.PeLevel = + PeLevelAdjReq[Index]; + } + } + + /* Verify that the voltage swing and pre-emphasis combination is + * allowed. Some combinations will result in a differential peak-to-peak + * voltage that is outside the permissable range. See the VESA + * DisplayPort v1.2 Specification, section 3.1.5.2. + * The valid combinations are: + * PE=0 PE=1 PE=2 PE=3 + * VS=0 Valid Valid Valid Valid + * VS=1 Valid Valid Valid + * VS=2 Valid Valid + * VS=3 Valid + */ + if (InstancePtr->TxInstance.LinkConfig.PeLevel > + (4 - InstancePtr->TxInstance.LinkConfig.VsLevel)) { + InstancePtr->TxInstance.LinkConfig.PeLevel = + 4 - InstancePtr->TxInstance.LinkConfig.VsLevel; + } + + /* Make the adjustments to both the DisplayPort TX core and the RX + * device. */ + XDp_TxSetVswingPreemp(InstancePtr, AuxData); + /* Write the voltage swing and pre-emphasis levels for each lane to the + * RX device. */ + Status = XDp_TxAuxWrite(InstancePtr, XDP_DPCD_TRAINING_LANE0_SET, + 4, AuxData); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function sets the training pattern to be used during link training for + * both the DisplayPort TX core and the RX device. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Pattern selects the pattern to be used. One of the following: + * - XDP_TX_TRAINING_PATTERN_SET_OFF + * - XDP_TX_TRAINING_PATTERN_SET_TP1 + * - XDP_TX_TRAINING_PATTERN_SET_TP2 + * - XDP_TX_TRAINING_PATTERN_SET_TP3 + * + * @return + * - XST_SUCCESS if setting the pattern was successful. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxSetTrainingPattern(XDp *InstancePtr, u32 Pattern) +{ + u32 Status; + u8 AuxData[5]; + + /* Write to the DisplayPort TX core. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, + XDP_TX_TRAINING_PATTERN_SET, Pattern); + + AuxData[0] = Pattern; + + /* Write scrambler disable to the DisplayPort TX core. */ + switch (Pattern) { + case XDP_TX_TRAINING_PATTERN_SET_OFF: + XDp_WriteReg(InstancePtr->Config.BaseAddr, + XDP_TX_SCRAMBLING_DISABLE, 0); + InstancePtr->TxInstance.LinkConfig.ScramblerEn = 1; + break; + case XDP_TX_TRAINING_PATTERN_SET_TP1: + case XDP_TX_TRAINING_PATTERN_SET_TP2: + case XDP_TX_TRAINING_PATTERN_SET_TP3: + AuxData[0] |= XDP_DPCD_TP_SET_SCRAMB_DIS_MASK; + XDp_WriteReg(InstancePtr->Config.BaseAddr, + XDP_TX_SCRAMBLING_DISABLE, 1); + InstancePtr->TxInstance.LinkConfig.ScramblerEn = 0; + break; + default: + break; + } + + /* Make the adjustments to both the DisplayPort TX core and the RX + * device. */ + XDp_TxSetVswingPreemp(InstancePtr, &AuxData[1]); + if (Pattern == XDP_TX_TRAINING_PATTERN_SET_OFF) { + Status = XDp_TxAuxWrite(InstancePtr, XDP_DPCD_TP_SET, 1, + AuxData); + } + else { + /* Write the voltage swing and pre-emphasis levels for each lane + * to the RX device. */ + Status = XDp_TxAuxWrite(InstancePtr, XDP_DPCD_TP_SET, 5, + AuxData); + } + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function determines what the RX device's required training delay is for + * link training. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param TrainingState is the current training state; either clock + * recovery or channel equalization. + * + * @return The training delay specified in the RX device's DisplayPort + * Configuration Data (DPCD) register, + * XDP_DPCD_TRAIN_AUX_RD_INTERVAL. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxGetTrainingDelay(XDp *InstancePtr, + XDp_TxTrainingState TrainingState) +{ + u8 *Dpcd = InstancePtr->TxInstance.RxConfig.DpcdRxCapsField; + u16 Delay; + + switch (Dpcd[XDP_DPCD_TRAIN_AUX_RD_INTERVAL]) { + case XDP_DPCD_TRAIN_AUX_RD_INT_100_400US: + if (TrainingState == XDP_TX_TS_CLOCK_RECOVERY) { + /* Delay for the clock recovery phase. */ + Delay = 100; + } + else { + /* Delay for the channel equalization phase. */ + Delay = 400; + } + break; + case XDP_DPCD_TRAIN_AUX_RD_INT_4MS: + Delay = 4000; + break; + case XDP_DPCD_TRAIN_AUX_RD_INT_8MS: + Delay = 8000; + break; + case XDP_DPCD_TRAIN_AUX_RD_INT_12MS: + Delay = 12000; + break; + case XDP_DPCD_TRAIN_AUX_RD_INT_16MS: + Delay = 16000; + break; + default: + /* Default to 20 ms. */ + Delay = 20000; + break; + } + + return Delay; +} + +/******************************************************************************/ +/** + * This function contains the common sequence of submitting an AUX command for + * AUX read, AUX write, I2C-over-AUX read, and I2C-over-AUX write transactions. + * If required, the reads and writes are split into multiple requests, each + * acting on a maximum of 16 bytes. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param CmdType is the type of AUX command (one of: XDP_TX_AUX_CMD_READ, + * XDP_TX_AUX_CMD_WRITE, XDP_TX_AUX_CMD_I2C_READ, or + * XDP_TX_AUX_CMD_I2C_WRITE. + * @param Address is the starting address that the AUX transaction will + * read/write from/to the RX device. + * @param NumBytes is the number of bytes to read/write from/to the RX + * device. + * @param Data is a pointer to the data buffer that contains the data + * to be read/written from/to the RX device. + * + * @return + * - XST_SUCCESS if the AUX transaction request was acknowledged. + * - XST_ERROR_COUNT_MAX if the AUX request timed out. + * - XST_FAILURE otherwise (if the DisplayPort TX core sees a NACK + * reply code or if the AUX transaction failed). + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxAuxCommon(XDp *InstancePtr, u32 CmdType, u32 Address, + u32 NumBytes, u8 *Data) +{ + u32 Status; + XDp_AuxTransaction Request; + u32 BytesLeft; + + /* Set the start address for AUX transactions. For I2C transactions, + * this is the address of the I2C bus. */ + Request.Address = Address; + + BytesLeft = NumBytes; + while (BytesLeft > 0) { + Request.CmdCode = CmdType; + + if ((CmdType == XDP_TX_AUX_CMD_READ) || + (CmdType == XDP_TX_AUX_CMD_WRITE)) { + /* Increment address for normal AUX transactions. */ + Request.Address = Address + (NumBytes - BytesLeft); + } + + /* Increment the pointer to the supplied data buffer. */ + Request.Data = &Data[NumBytes - BytesLeft]; + + if (BytesLeft > 16) { + Request.NumBytes = 16; + } + else { + Request.NumBytes = BytesLeft; + } + BytesLeft -= Request.NumBytes; + + if ((CmdType == XDP_TX_AUX_CMD_I2C_READ) && (BytesLeft > 0)) { + /* Middle of a transaction I2C read request. Override + * the command code that was set to CmdType. */ + Request.CmdCode = XDP_TX_AUX_CMD_I2C_READ_MOT; + } + else if ((CmdType == XDP_TX_AUX_CMD_I2C_WRITE) && + (BytesLeft > 0)) { + /* Middle of a transaction I2C write request. Override + * the command code that was set to CmdType. */ + Request.CmdCode = XDP_TX_AUX_CMD_I2C_WRITE_MOT; + } + + XDp_WaitUs(InstancePtr, InstancePtr->TxInstance.AuxDelayUs); + + Status = XDp_TxAuxRequest(InstancePtr, &Request); + if (Status != XST_SUCCESS) { + return Status; + } + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function submits the supplied AUX request to the RX device over the AUX + * channel. If waiting for a reply times out, or if the DisplayPort TX core + * indicates that the request was deferred, the request is sent again (up to a + * maximum specified by XDP_AUX_MAX_DEFER_COUNT|XDP_AUX_MAX_TIMEOUT_COUNT). + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Request is a pointer to an initialized XDp_AuxTransaction + * structure containing the required information for issuing an + * AUX command, as well as a write buffer used for write commands, + * and a read buffer for read commands. + * + * @return + * - XST_SUCCESS if the request was acknowledged. + * - XST_ERROR_COUNT_MAX if resending the request exceeded the + * maximum for deferral and timeout. + * - XST_FAILURE otherwise (if the DisplayPort TX core sees a NACK + * reply code or if the AUX transaction failed). + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxAuxRequest(XDp *InstancePtr, XDp_AuxTransaction *Request) +{ + u32 Status; + u32 DeferCount = 0; + u32 TimeoutCount = 0; + + while ((DeferCount < XDP_AUX_MAX_DEFER_COUNT) && + (TimeoutCount < XDP_AUX_MAX_TIMEOUT_COUNT)) { + Status = XDp_TxAuxWaitReady(InstancePtr); + if (Status != XST_SUCCESS) { + /* The RX device isn't ready yet. */ + TimeoutCount++; + continue; + } + + /* Send the request. */ + Status = XDp_TxAuxRequestSend(InstancePtr, Request); + if (Status == XST_SEND_ERROR) { + /* The request was deferred. */ + DeferCount++; + } + else if (Status == XST_ERROR_COUNT_MAX) { + /* Waiting for a reply timed out. */ + TimeoutCount++; + } + else { + /* XST_FAILURE indicates that the request was NACK'ed, + * XST_SUCCESS indicates that the request was ACK'ed. */ + return Status; + } + + XDp_WaitUs(InstancePtr, 100); + } + + /* The request was not successfully received by the RX device. */ + return XST_ERROR_COUNT_MAX; +} + +/******************************************************************************/ +/** + * This function submits the supplied AUX request to the RX device over the AUX + * channel by writing the command, the destination address, (the write buffer + * for write commands), and the data size to the DisplayPort TX core. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Request is a pointer to an initialized XDp_AuxTransaction + * structure containing the required information for issuing an AUX + * command. + * + * @return + * - XST_SUCCESS if the request was acknowledged. + * - XST_ERROR_COUNT_MAX if waiting for a reply timed out. + * - XST_SEND_ERROR if the request was deferred. + * - XST_FAILURE otherwise, if the request was NACK'ed. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxAuxRequestSend(XDp *InstancePtr, XDp_AuxTransaction *Request) +{ + u32 Status; + u8 Index; + + /* Set the address for the request. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_AUX_ADDRESS, + Request->Address); + + if ((Request->CmdCode == XDP_TX_AUX_CMD_WRITE) || + (Request->CmdCode == XDP_TX_AUX_CMD_I2C_WRITE) || + (Request->CmdCode == XDP_TX_AUX_CMD_I2C_WRITE_MOT)) { + /* Feed write data into the DisplayPort TX core's write FIFO. */ + for (Index = 0; Index < Request->NumBytes; Index++) { + XDp_WriteReg(InstancePtr->Config.BaseAddr, + XDP_TX_AUX_WRITE_FIFO, Request->Data[Index]); + } + } + + /* Submit the command and the data size. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_AUX_CMD, + ((Request->CmdCode << XDP_TX_AUX_CMD_SHIFT) | + ((Request->NumBytes - 1) & + XDP_TX_AUX_CMD_NBYTES_TRANSFER_MASK))); + + /* Check for a reply from the RX device to the submitted request. */ + Status = XDp_TxAuxWaitReply(InstancePtr); + if (Status != XST_SUCCESS) { + /* Waiting for a reply timed out. */ + return XST_ERROR_COUNT_MAX; + } + + /* Analyze the reply. */ + Status = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_TX_AUX_REPLY_CODE); + if ((Status == XDP_TX_AUX_REPLY_CODE_DEFER) || + (Status == XDP_TX_AUX_REPLY_CODE_I2C_DEFER)) { + /* The request was deferred. */ + return XST_SEND_ERROR; + } + else if ((Status == XDP_TX_AUX_REPLY_CODE_NACK) || + (Status == XDP_TX_AUX_REPLY_CODE_I2C_NACK)) { + /* The request was not acknowledged. */ + return XST_FAILURE; + } + + /* The request was acknowledged. */ + + if ((Request->CmdCode == XDP_TX_AUX_CMD_READ) || + (Request->CmdCode == XDP_TX_AUX_CMD_I2C_READ) || + (Request->CmdCode == XDP_TX_AUX_CMD_I2C_READ_MOT)) { + /* Obtain the read data from the reply FIFO. */ + for (Index = 0; Index < Request->NumBytes; Index++) { + Request->Data[Index] = XDp_ReadReg( + InstancePtr->Config.BaseAddr, + XDP_TX_AUX_REPLY_DATA); + } + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function waits for a reply indicating that the most recent AUX request + * has been received by the RX device. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if a reply was sent from the RX device. + * - XST_ERROR_COUNT_MAX otherwise, if a timeout has occurred. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxAuxWaitReply(XDp *InstancePtr) +{ + u32 Timeout = 100; + u32 Status; + + while (0 < Timeout) { + Status = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_TX_INTERRUPT_STATUS); + + /* Check for a timeout. */ + if (Status & XDP_TX_INTERRUPT_STATUS_REPLY_TIMEOUT_MASK) { + return XST_ERROR_COUNT_MAX; + } + + /* Check for a reply. */ + if (Status & XDP_TX_INTERRUPT_STATUS_REPLY_RECEIVED_MASK) { + return XST_SUCCESS; + } + + Timeout--; + XDp_WaitUs(InstancePtr, 20); + } + + return XST_ERROR_COUNT_MAX; +} + +/******************************************************************************/ +/** + * This function waits until another request is no longer in progress. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the the RX device is no longer busy. + * - XST_ERROR_COUNT_MAX otherwise, if a timeout has occurred. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxAuxWaitReady(XDp *InstancePtr) +{ + u32 Status; + u32 Timeout = 100; + + /* Wait until the DisplayPort TX core is ready. */ + do { + Status = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_TX_INTERRUPT_SIG_STATE); + + /* Protect against an infinite loop. */ + if (!Timeout--) { + return XST_ERROR_COUNT_MAX; + } + XDp_WaitUs(InstancePtr, 20); + } + while (Status & XDP_TX_REPLY_STATUS_REPLY_IN_PROGRESS_MASK); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function sets the clock frequency for the DisplayPort PHY corresponding + * to a desired data rate. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Speed determines what clock frequency will be used based on one + * of the following selects: + * - XDP_TX_PHY_CLOCK_SELECT_162GBPS = 0x01 + * - XDP_TX_PHY_CLOCK_SELECT_270GBPS = 0x03 + * - XDP_TX_PHY_CLOCK_SELECT_540GBPS = 0x05 + * + * @return + * - XST_SUCCESS if the reset for each lane is done after the clock + * frequency has been set. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxSetClkSpeed(XDp *InstancePtr, u32 Speed) +{ + u32 Status; + u32 RegVal; + + /* Disable the DisplayPort TX core first. */ + RegVal = XDp_ReadReg(InstancePtr->Config.BaseAddr, XDP_TX_ENABLE); + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_ENABLE, 0x0); + + /* Change speed of the feedback clock. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, + XDP_TX_PHY_CLOCK_SELECT, Speed); + + /* Re-enable the DisplayPort TX core if it was previously enabled. */ + if (RegVal != 0x0) { + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_ENABLE, 0x1); + } + + /* Wait until the PHY is ready. */ + if (InstancePtr->Config.MaxLaneCount > 2) { + Status = XDp_WaitPhyReady(InstancePtr, + XDP_TX_PHY_STATUS_ALL_LANES_READY_MASK); + } + else { + Status = XDp_WaitPhyReady(InstancePtr, + XDP_TX_PHY_STATUS_LANES_0_1_READY_MASK); + } + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function waits for the DisplayPort PHY to come out of reset. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_ERROR_COUNT_MAX if the PHY failed to be ready. + * - XST_SUCCESS otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_WaitPhyReady(XDp *InstancePtr, u32 Mask) +{ + u16 Timeout = 20000; + u32 PhyStatus; + u32 RegPhyStatus; + + if (XDp_GetCoreType(InstancePtr) == XDP_TX) { + RegPhyStatus = XDP_TX_PHY_STATUS; + } + else { + RegPhyStatus = XDP_RX_PHY_STATUS; + } + + /* Wait until the PHY is ready. */ + do { + PhyStatus = XDp_ReadReg(InstancePtr->Config.BaseAddr, + RegPhyStatus) & Mask; + + /* Protect against an infinite loop. */ + if (!Timeout--) { + return XST_ERROR_COUNT_MAX; + } + XDp_WaitUs(InstancePtr, 20); + } + while (PhyStatus != Mask); + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/dp/src/xdp.h b/XilinxProcessorIPLib/drivers/dp/src/xdp.h new file mode 100644 index 00000000..6d826f95 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/src/xdp.h @@ -0,0 +1,1038 @@ +/******************************************************************************* + * + * 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 xdp.h +* @addtogroup dp_v1_0 +* @{ +* @details + * + * The Xilinx DisplayPort transmitter (DP) driver. This driver supports the + * Xilinx DisplayPort soft IP core in both transmit/source (TX) and receive/sink + * (RX) modes of operation. + * + * The Xilinx DisplayPort soft IP supports the following features: + * - 1, 2, or 4 lanes. + * - A link rate of 1.62, 2.70, or 5.40Gbps per lane. + * - 1, 2, or 4 pixel-wide video interfaces. + * - RGB and YCbCr color space. + * - Up to 16 bits per component. + * - Up to 4Kx2K monitor resolution. + * - Auto lane rate and width negotiation. + * - I2C over a 1Mb/s AUX channel. + * - Secondary channel audio support (2 channels). + * - 4 independent video multi-streams. + * + * The Xilinx DisplayPort soft IP does not support the following features: + * - The automated test feature. + * - Audio (3-8 channel). + * - FAUX. + * - Bridging function. + * - MST audio. + * - eDP optional features. + * - iDP. + * - GTC. + * + * DisplayPort overview + * + * A DisplayPort link consists of: + * - A unidirectional main link which is used to transport isochronous data + * streams such as video and audio. The main link may use 1, 2, or 4 + * lanes at a link rate of 1.62, 2.70, or 5.40Gbps per lane. The link + * needs to be trained prior to sending streams. + * - An auxiliary (AUX) channel is a 1MBps bidirectional channel used for + * link training, link management, and device control. + * - A hot-plug-detect (HPD) signal line is used to determine whether a + * DisplayPort connection exists between the DisplayPort TX connector and + * an RX device. It is serves as an interrupt request by the RX device. + * + * Device configuration + * + * The device can be configured in various ways during the FPGA implementation + * process. Configuration parameters are stored in the xdp_g.c file which is + * generated when compiling the board support package (BSP). A table is defined + * where each entry contains configuration information for the DisplayPort + * instances present in the system. This information includes parameters that + * are defined in the driver's data/dp.tcl file such as the base address of the + * memory-mapped device and the maximum number of lanes, maximum link rate, and + * video interface that the DisplayPort instance supports, among others. + * + * The DisplayPort core may be configured in both transmitter (TX) or receiver + * (RX) modes of operation. Depending on which mode of operation the hardware is + * configured for, the set of registers associated with the core will be + * different. + * + * Driver description + * + * The DisplayPort (DP) driver consists of functions, structures, and + * definitions: + * 1) Specific to the DisplayPort TX mode of operation. + * - Prefix: XDp_Tx* and XDP_TX_* + * 2) Specific to the DisplayPort RX mode of operation. + * - Prefix: XDp_Rx* and XDP_RX_* + * 3) Common to both DisplayPort modes of operation. + * - Prefix: XDp_* and XDP_* + * + * Driver description: TX mode of operation + * + * The device driver enables higher-level software (e.g., an application) to + * configure and control a DisplayPort TX soft IP, communicate and control an + * RX device/sink monitor over the AUX channel, and to initialize and transmit + * data streams over the main link. This driver follows the DisplayPort 1.2a + * specification. + * + * This driver implements link layer functionality: a Link Policy Maker (LPM) + * and a Stream Policy Maker (SPM) as per the DisplayPort 1.2a specification. + * - The LPM manages the main link and is responsible for keeping the link + * synchronized. It will establish a link with a downstream RX device by + * undergoing a link training sequence which consists of: + * - Clock recovery: The clock needs to be recovered and PLLs need to be + * locked for all lanes. + * - Channel equalization: All lanes need to achieve channel equalization + * and and symbol lock, as well as for interlane alignment to take place. + * - The SPM manages transportation of an isochronous stream. That is, it will + * initialize and maintain a video stream, establish a virtual channel to a + * sink monitor, and transmit the stream. + * + * Using AUX transactions to read/write from/to the sink's DisplayPort + * Configuration Data (DPCD) address space, the LPM obtains the link + * capabilities, obtains link configuration and link and sink status, and + * configures and controls the link and sink. The main link is trained this way. + * + * I2C-over-AUX transactions are used to obtain the sink's Extended Display + * Identification Data (EDID) which give information on the display capabilities + * of the monitor. The SPM may use this information to determine what available + * screen resolutions and video timing are possible. + * + * Driver description: RX mode of operation + * + * The device driver enables higher-level software (e.g., an application) to + * configure and control a DisplayPort RX soft IP. + * + * This driver gives applications the ability to configure the RX using various + * settings, handle and issue interrupts, and modify a subset of its DisplayPort + * Configuration Data (DPCD) fields. + * + * Link training is done automatically by the hardware. + * + * Interrupt processing: TX mode of operation + * + * For the driver to process interrupts, the application must set up the + * system's interrupt controller and connect the XDp_InterruptHandler function + * to service interrupts. When an interrupt occurs, XDp_InterruptHandler will + * check which mode of operation the DisplayPort core is running in, and will + * call the appropriate interrupt handler for that core + * (XDp_TxInterruptHandler or XDp_RxInterruptHandler - local to xdp_intr.c). + * + * Interrupt processing: TX mode of operation + * + * DisplayPort interrupts occur on the HPD signal line when the DisplayPort + * cable is connected/disconnected or when the RX device sends a pulse. The user + * hardware design must contain an interrupt controller which the DisplayPort + * TX instance's interrupt signal is connected to. The user application must + * enable interrupts in the system and set up the interrupt controller such that + * the XDp_TxHpdInterruptHandler handler will service DisplayPort interrupts. + * When the XDp_TxHpdInterruptHandler function is invoked, the handler will + * identify what type of DisplayPort interrupt has occurred, and will call + * either the HPD event handler function or the HPD pulse handler function, + * depending on whether a an HPD event on an HPD pulse event occurred. + * + * The DisplayPort TX's XDP_TX_INTERRUPT_STATUS register indicates the type of + * interrupt that has occured, and the XDp_TxInterruptHandler will use this + * information to decide which handler to call. An HPD event is identified if + * bit XDP_TX_INTERRUPT_STATUS_HPD_EVENT_MASK is set, and an HPD pulse is + * identified from the XDP_TX_INTERRUPT_STATUS_HPD_PULSE_DETECTED_MASK bit. + * + * The HPD event handler may be set up by using the XDp_TxSetHpdEventHandler + * function and, for the HPD pulse handler, the XDp_TxSetHpdPulseHandler + * function. + * + * Interrupt processing: RX mode of operation + * + * The DisplayPort RX driver may generate a pulse on the hot-plug-detect (HPD) + * signal line using the XDp_RxGenerateHpdInterrupt function. This allows the RX + * to send an interrupt to the upstream TX device, useful for signaling the TX + * that it needs to do some checks for changes in downstream devices or a loss + * of link training. + * + * For RX interrupt handling of HPD events or events that happen internal to the + * RX, the user hardware design must contain an interrupt controller which the + * DisplayPort RX instance's interrupt signal is connected to. The user + * application must enable interrupts in the system and set up the interrupt + * controller such that the XDp_RxInterruptHandler handler will service + * interrupts. When the XDp_RxInterruptHandler function is invoked, the handler + * will identify what type of interrupt has occurred, and will call the + * appropriate interrupt handler. + * + * The DisplayPort RX's XDP_RX_INTERRUPT_CAUSE register indicates the type of + * interrupt that has occured, and the XDp_RxInterruptHandler will use this + * information to decide which handler to call. + * + * The handlers are set up using the XDp_RxSetIntr* functions. + * + * Specific interrupts may be enabled or disabled using the + * XDp_RxInterruptEnable and XDp_RxInterruptDisable functions. + * + * Multi-stream transport (MST) mode: TX mode of operation + * + * The current version of this driver doesn't support MST functionality when the + * core is configured do run in the RX mode of operation. + * + * The driver handles MST mode functionality in TX mode of operation, including + * sideband messaging, topology discovery, virtual channel payload ID table + * management, and directing streams to different sinks. + * + * MST testing has been done at all possible link rate/lane count/topology/ + * resolution/color depth combinations with each setting using following values: + * - Link rate: 1.62, 2.70, and 5.40Gbps per lane. + * - Lane count: 1, 2, and 4 lanes. + * - Number of sink displays: 1, 2, 3, and 4 sink displays in both a daisy-chain + * configuration and in a configuration using a combination of a 1-to-3 hub + * and daisy-chain. Each stream was using the same resolution. + * - Resolutions (60Hz): 640x480, 800x600, 1024x768, 1280x800, 1280x1024, + * 1360x768, 1400x1050, 1680x1050, 1920x1080, 1920x2160, and 3840x2160. + * - Color depths: 18, 24, 30, 36, and 48 bits per pixel. + * + * Audio + * + * The driver in RX mode of operation may received audio info and extension + * packets. When this happens, if interrupts are enabled, the appropriate + * handlers will be invoked. + * Control functions are available for enabling, disabling, and resetting audio + * in the DisplayPort RX core. + * + * The TX driver does not handle audio. For an example as to how to configure + * and transmit audio, examples/xdptx_audio_example.c illustrates the required + * sequence in the TX mode of operation. The user will need to configure the + * audio source connected to the Displayport TX instance and set up the audio + * info frame as per user requirements. + * + * Asserts + * + * Asserts are used within all Xilinx drivers to enforce constraints on argument + * values. Asserts can be turned off on a system-wide basis by defining, at + * compile time, the NDEBUG identifier. By default, asserts are turned on and + * it is recommended that application developers leave asserts on during + * development. + * + * Limitations: TX mode of operation + * + * - For MST mode to correctly display, the current version of the driver + * requires that each of the DisplayPort TX streams be allocated without + * skipping streams (i.e. assign stream 1, stream 2, and stream 3 - problems + * were experienced if skipping stream 2 and assigning stream 4 instead). + * skipping monitors in a daisy chain is OK as long as they are assigned to + * streams in order. + * - In MST mode, the current version of the driver does not support removal of + * an allocated stream from the virtual channel payload ID table without + * clearing the entire table. + * - Some sideband messages have not been implemented in the current version of + * the driver for MST mode. Notably, reception of a CONNECTION_STATUS_NOTIFY + * sideband message. + * - The driver does not handle audio. See the audio example in the driver + * examples directory for the required sequence for enabling audio. + * + * @note For a 5.4Gbps link rate, a high performance 7 series FPGA is + * required with a speed grade of -2 or -3. + * + *
+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial release. TX code merged from the dptx driver. + *+ * +*******************************************************************************/ + +#ifndef XDP_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XDP_H_ + +/******************************* Include Files ********************************/ + +#include "xil_assert.h" +#include "xil_types.h" +#include "xdp_hw.h" +#include "xstatus.h" +#include "xvidc.h" + +/****************************** Type Definitions ******************************/ + +/** + * This typedef enumerates the RX and TX modes of operation for the DisplayPort + * core. + */ +typedef enum { + XDP_TX = 0, + XDP_RX +} XDp_CoreType; + +/** + * This typedef contains configuration information for the DisplayPort core. + */ +typedef struct { + u16 DeviceId; /**< Device instance ID. */ + u32 BaseAddr; /**< The base address of the core instance. */ + u32 SAxiClkHz; /**< The clock frequency of the core instance's + S_AXI_ACLK port. */ + u8 MaxLaneCount; /**< The maximum lane count supported by this + core instance. */ + u8 MaxLinkRate; /**< The maximum link rate supported by this + core instance. */ + u8 MaxBitsPerColor; /**< The maximum bits/color supported by this + core instance*/ + u8 QuadPixelEn; /**< Quad pixel support by this core + instance. */ + u8 DualPixelEn; /**< Dual pixel support by this core + instance. */ + u8 YCrCbEn; /**< YCrCb format support by this core + instance. */ + u8 YOnlyEn; /**< YOnly format support by this core + instance. */ + u8 PayloadDataWidth; /**< The payload data width used by this core + instance. */ + u8 SecondaryChEn; /**< This core instance supports audio packets + being sent by the secondary channel. */ + u8 NumAudioChs; /**< The number of audio channels supported by + this core instance. */ + u8 MstSupport; /**< Multi-stream transport (MST) mode is + enabled by this core instance. */ + u8 NumMstStreams; /**< The total number of MST streams supported + by this core instance. */ + u8 DpProtocol; /**< The DisplayPort protocol version that this + core instance is configured for. + 0 = v1.1a, 1 = v1.2. */ + u8 IsRx; /**< The type of DisplayPort core. + 0 = TX, 1 = RX. */ +} XDp_Config; + +/** + * This typedef contains configuration information about the RX device. + */ +typedef struct { + u8 DpcdRxCapsField[16]; /**< The first 16 bytes of the raw capabilities + field of the RX device's DisplayPort + Configuration Data (DPCD). */ + u8 LaneStatusAdjReqs[6];/**< This is a raw read of the RX device's + status registers. The first 4 bytes + correspond to the lane status associated + with clock recovery, channel + equalization, symbol lock, and interlane + alignment. The remaining 2 bytes + represent the pre-emphasis and voltage + swing level adjustments requested by the + RX device. */ +} XDp_TxSinkConfig; + +/** + * This typedef contains configuration information about the main link settings. + */ +typedef struct { + u8 LaneCount; /**< The current lane count of the main + link. */ + u8 LinkRate; /**< The current link rate of the main + link. */ + u8 ScramblerEn; /**< Symbol scrambling is currently in + use over the main link. */ + u8 EnhancedFramingMode; /**< Enhanced frame mode is currently in + use over the main link. */ + u8 DownspreadControl; /**< Downspread control is currently in + use over the main link. */ + u8 MaxLaneCount; /**< The maximum lane count of the main + link. */ + u8 MaxLinkRate; /**< The maximum link rate of the main + link. */ + u8 SupportEnhancedFramingMode; /**< Enhanced frame mode is supported by + the RX device. */ + u8 SupportDownspreadControl; /**< Downspread control is supported by + the RX device. */ + u8 VsLevel; /**< The current voltage swing level for + each lane. */ + u8 PeLevel; /**< The current pre-emphasis/cursor + level for each lane. */ + u8 Pattern; /**< The current pattern currently in + use over the main link. */ +} XDp_TxLinkConfig; + +/** + * This typedef contains the main stream attributes which determine how the + * video will be displayed. + */ +typedef struct { + XVidC_VideoTimingMode Vtm; /**< The video timing. */ + u32 PixelClockHz; /**< The pixel clock of the stream (in + Hz). */ + u32 HStart; /**< Horizontal blank start (in + pixels). */ + u32 VStart; /**< Vertical blank start (in lines). */ + u32 Misc0; /**< Miscellaneous stream attributes 0 + as specified by the DisplayPort + 1.2 specification. */ + u32 Misc1; /**< Miscellaneous stream attributes 1 + as specified by the DisplayPort + 1.2 specification. */ + u32 NVid; /**< N value for the video stream. */ + u32 UserPixelWidth; /**< The width of the user data input + port. */ + u32 DataPerLane; /**< Used to translate the number of + pixels per line to the native + internal 16-bit datapath. */ + u32 AvgBytesPerTU; /**< Average number of bytes per + transfer unit, scaled up by a + factor of 1000. */ + u32 TransferUnitSize; /**< Size of the transfer unit in the + framing logic. In MST mode, this + is also the number of time slots + that are alloted in the payload + ID table. */ + u32 InitWait; /**< Number of initial wait cycles at + the start of a new line by + the framing logic. */ + u32 BitsPerColor; /**< Number of bits per color + component. */ + u8 ComponentFormat; /**< The component format currently in + use by the video stream. */ + u8 DynamicRange; /**< The dynamic range currently in use + by the video stream. */ + u8 YCbCrColorimetry; /**< The YCbCr colorimetry currently in + use by the video stream. */ + u8 SynchronousClockMode; /**< Synchronous clock mode is currently + in use by the video stream. */ + u8 OverrideUserPixelWidth; /**< If set to 1, the value stored for + UserPixelWidth will be used as + the pixel width. */ +} XDp_TxMainStreamAttributes; + +/** + * This typedef describes a stream when the driver is running in multi-stream + * transport (MST) mode. + */ +typedef struct { + u8 LinkCountTotal; /** The total number of DisplayPort + links from the DisplayPort TX to + the sink device that this MST + stream is targeting.*/ + u8 RelativeAddress[15]; /** The relative address from the + DisplayPort TX to the sink + device that this MST stream is + targeting.*/ + u16 MstPbn; /**< Payload bandwidth number used to + allocate bandwidth for the MST + stream. */ + u8 MstStreamEnable; /**< In MST mode, enables the + corresponding stream for this + MSA configuration. */ +} XDp_TxMstStream; + +/** + * This typedef describes some board characteristics information that affects + * link training. + */ +typedef struct { + u8 HasRedriverInPath; /**< Redriver in path requires different voltage + swing and pre-emphasis. */ + u8 TxVsLevels[4]; /**< The voltage swing levels to be used by the + DisplayPort TX. */ + u8 TxPeLevels[4]; /**< The pre-emphasis/cursor level to be used by + the DisplayPort TX. */ + u8 TxVsOffset; /**< Voltage swing compensation offset used when + pre-emphasis is used. */ +} XDp_TxBoardChar; + +/** + * This typedef describes a downstream DisplayPort device when the driver is + * running in multi-stream transport (MST) mode. + */ +typedef struct { + u32 Guid[4]; /**< The global unique identifier (GUID) + of the device. */ + u8 RelativeAddress[15]; /**< The relative address from the + DisplayPort TX to this + device. */ + u8 DeviceType; /**< The type of DisplayPort device. + Either a branch or sink. */ + u8 LinkCountTotal; /**< The total number of DisplayPort + links connecting this device to + the DisplayPort TX. */ + u8 DpcdRev; /**< The revision of the device's + DisplayPort Configuration Data + (DPCD). For this device to + support MST features, this value + must represent a protocl version + greater or equal to 1.2. */ + u8 MsgCapStatus; /**< This device is capable of sending + and receiving sideband + messages. */ +} XDp_TxTopologyNode; + +/** + * This typedef describes a the entire topology of connected downstream + * DisplayPort devices (from the DisplayPort TX) when the driver is operating + * in multi-stream transport (MST) mode. + */ +typedef struct { + u8 NodeTotal; /**< The total number of nodes that were + found in the MST topology. */ + XDp_TxTopologyNode NodeTable[63]; /**< A table listing all the nodes in + the MST topology. */ + u8 SinkTotal; /**< The total number of sinks in the + MST topology. */ + XDp_TxTopologyNode *SinkList[63]; /**< A pointer list of sinks in the + MST topology. The entries will + point to the sinks in the + NodeTable. */ +} XDp_TxTopology; + +/** + * This typedef describes a port that is connected to a DisplayPort branch + * device. This structure is used when the driver is operating in multi-stream + * transport (MST) mode. + */ +typedef struct { + u8 InputPort; /**< Specifies that this port is an + input port. */ + u8 PeerDeviceType; /**< Specifies the device type connected + to this port. */ + u8 PortNum; /**< The port number of this port. */ + u8 MsgCapStatus; /**< This port or the device at this + port can send and receive MST + messages. */ + u8 DpDevPlugStatus; /**< There is a device connected to this + port. */ + + u8 LegacyDevPlugStatus; /**< This port is connected to a legacy + device. */ + u8 DpcdRev; /**< The DisplayPort Configuration Data + (DPCD) revision of the device + connected to this port. */ + u32 Guid[4]; /**< The global unique identifier (GUID) + of the device connected to this + port. */ + u8 NumSdpStreams; /**< The total number of Secondary-Data + Packet (SDP) streams that this + port can handle. */ + u8 NumSdpStreamSinks; /**< The number of SDP streams + associated with this port. */ +} XDp_TxSbMsgLinkAddressReplyPortDetail; + +/** + * This typedef describes a DisplayPort branch device. This structure is used + * when the driver is operating in multi-stream transport (MST) mode. + */ +typedef struct { + u8 ReplyType; /**< The reply type of the sideband + message. A value of 1 indicates + that the request wasn't + successful and the return data + will give the reason for a + negative-acknowledge (NACK). */ + u8 RequestId; /**< The request identifier of the + reply. This should correspond to + the request identifier for the + LINK_ADDRESS sideband message + request. */ + u32 Guid[4]; /**< The global unique identifier (GUID) + of the branch device. */ + u8 NumPorts; /**< The number of ports associated with + this branch device. */ + XDp_TxSbMsgLinkAddressReplyPortDetail PortDetails[16]; /**< An array + describing all ports attached to + this branch device. */ +} XDp_TxSbMsgLinkAddressReplyDeviceInfo; + +/** + * This typedef contains configuration information about the main link settings. + */ +typedef struct { + u8 LaneCount; /**< The current lane count of the main + link. */ + u8 LinkRate; /**< The current link rate of the main + link. */ +} XDp_RxLinkConfig; + +/******************************************************************************/ +/** + * Callback type which represents a custom timer wait handler. This is only + * used for Microblaze since it doesn't have a native sleep function. To avoid + * dependency on a hardware timer, the default wait functionality is implemented + * using loop iterations; this isn't too accurate. If a custom timer handler is + * used, the user may implement their own wait implementation using a hardware + * timer (see example/) for better accuracy. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param MicroSeconds is the number of microseconds to be passed to the + * timer function. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XDp_TimerHandler)(void *InstancePtr, u32 MicroSeconds); + +/******************************************************************************/ +/** + * Callback type which represents the handler for interrupts. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XDp_IntrHandler)(void *InstancePtr); + +/** + * The XDp driver instance data representing the TX mode of operation. + */ +typedef struct { + u32 MstEnable; /**< Multi-stream transport + (MST) mode. Enables + functionality, allowing + multiple streams to be + sent over the main + link. */ + u8 TrainAdaptive; /**< Downshift lane count and + link rate if necessary + during training. */ + XDp_TxSinkConfig RxConfig; /**< Configuration structure for + the RX device. */ + XDp_TxLinkConfig LinkConfig; /**< Configuration structure for + the main link. */ + XDp_TxBoardChar BoardChar; /**< Some board characteristics + information that affects + link training. */ + XDp_TxMainStreamAttributes MsaConfig[4]; /**< Configuration structure + for the main stream + attributes (MSA). Each + stream has its own set + of attributes. When MST + mode is disabled, only + MsaConfig[0] is used. */ + XDp_TxMstStream MstStreamConfig[4]; /**< Configuration structure + for a multi-stream + transport (MST) + stream. */ + XDp_TxTopology Topology; /**< The topology of connected + downstream DisplayPort + devices when the driver + is running in MST + mode. */ + u32 AuxDelayUs; /**< Amount of latency in micro- + seconds to use between + AUX transactions. */ + u32 SbMsgDelayUs; /**< Amount of latency in micro- + seconds to use between + sideband messages for + multi-stream transport + (MST) mode. */ + XDp_IntrHandler HpdEventHandler; /**< Callback function for Hot- + Plug-Detect (HPD) event + interrupts. */ + void *HpdEventCallbackRef; /**< A pointer to the user data + passed to the HPD event + callback function. */ + XDp_IntrHandler HpdPulseHandler; /**< Callback function for Hot- + Plug-Detect (HPD) pulse + interrupts. */ + void *HpdPulseCallbackRef; /**< A pointer to the user data + passed to the HPD pulse + callback function. */ +} XDp_Tx; + +/** + * The XDp driver instance data representing the TX mode of operation. + */ +typedef struct { + XDp_RxLinkConfig LinkConfig; /**< Configuration structure for + the main link. */ + XDp_IntrHandler IntrVmChangeHandler; /**< Callback function for video + mode change + interrupts. */ + void *IntrVmChangeCallbackRef; /**< A pointer to the user data + passed to the video mode + change callback + function. */ + XDp_IntrHandler IntrPowerStateHandler; /**< Callback function for + power state change + interrupts. */ + void *IntrPowerStateCallbackRef; /**< A pointer to the user data + passed to the power + state change callback + function. */ + XDp_IntrHandler IntrNoVideoHandler; /**< Callback function for + no video interrupts. */ + void *IntrNoVideoCallbackRef; /**< A pointer to the user data + passed to the no video + callback function. */ + XDp_IntrHandler IntrVBlankHandler; /**< Callback function for + vertical blanking + interrupts. */ + void *IntrVBlankCallbackRef; /**< A pointer to the user data + passed to the vertical + blanking callback + function. */ + XDp_IntrHandler IntrTrainingLostHandler;/**< Callback function for + training lost + interrupts. */ + void *IntrTrainingLostCallbackRef; /**< A pointer to the user data + passed to the training + lost callback + function. */ + XDp_IntrHandler IntrVideoHandler; /**< Callback function for valid + video interrupts. */ + void *IntrVideoCallbackRef; /**< A pointer to the user data + passed to the valid + video callback + function. */ + XDp_IntrHandler IntrInfoPktHandler; /**< Callback function for audio + info packet received + interrupts. */ + void *IntrInfoPktCallbackRef; /**< A pointer to the user data + passed to the audio info + packet callback + function. */ + XDp_IntrHandler IntrExtPktHandler; /**< Callback function for audio + extension packet + received interrupts. */ + void *IntrExtPktCallbackRef; /**< A pointer to the user data + passed to the audio + extension packet + callback function. */ + XDp_IntrHandler IntrTrainingDoneHandler; /**< Callback function for + training done + interrupts. */ + void *IntrTrainingDoneCallbackRef; /**< A pointer to the user data + passed to the training + done callback + function. */ + XDp_IntrHandler IntrBwChangeHandler; /**< Callback function for + bandwidth change + interrupts. */ + void *IntrBwChangeCallbackRef; /**< A pointer to the user data + passed to the bandwidth + change callback + function. */ + XDp_IntrHandler IntrTp1Handler; /**< Callback function for + training pattern 1 + interrupts. */ + void *IntrTp1CallbackRef; /**< A pointer to the user data + passed to the training + pattern 1 callback + function. */ + XDp_IntrHandler IntrTp2Handler; /**< Callback function for + training pattern 2 + interrupts. */ + void *IntrTp2CallbackRef; /**< A pointer to the user data + passed to the training + pattern 2 callback + function. */ + XDp_IntrHandler IntrTp3Handler; /**< Callback function for + training pattern 3 + interrupts. */ + void *IntrTp3CallbackRef; /**< A pointer to the user data + passed to the training + pattern 3 callback + function. */ +} XDp_Rx; + +/** + * The XDp instance data. The user is required to allocate a variable of this + * type for every XDp device in the system. A pointer to a variable of this type + * is then passed to the driver API functions. + */ +typedef struct { + XDp_Config Config; /**< Configuration structure for + the DisplayPort TX + core. */ + u32 IsReady; /**< Device is initialized and + ready. */ + XDp_TimerHandler UserTimerWaitUs; /**< Custom user function for + delay/sleep. */ + void *UserTimerPtr; /**< Pointer to a timer instance + used by the custom user + delay/sleep function. */ + union { + XDp_Tx TxInstance; + XDp_Rx RxInstance; + }; +} XDp; + +/**************************** Function Prototypes *****************************/ + +/* xdp_sinit.c: Configuration extraction function. */ +XDp_Config *XDp_LookupConfig(u16 DeviceId); + +/* xdp.c: Setup and initialization functions. */ +void XDp_CfgInitialize(XDp *InstancePtr, XDp_Config *ConfigPtr, + u32 EffectiveAddr); +u32 XDp_Initialize(XDp *InstancePtr); +u32 XDp_TxGetRxCapabilities(XDp *InstancePtr); + +/* xdp.c: TX link policy maker functions. */ +u32 XDp_TxCfgMainLinkMax(XDp *InstancePtr); +u32 XDp_TxEstablishLink(XDp *InstancePtr); +u32 XDp_TxCheckLinkStatus(XDp *InstancePtr, u8 LaneCount); +void XDp_TxEnableTrainAdaptive(XDp *InstancePtr, u8 Enable); +void XDp_TxSetHasRedriverInPath(XDp *InstancePtr, u8 Set); +void XDp_TxCfgTxVsOffset(XDp *InstancePtr, u8 Offset); +void XDp_TxCfgTxVsLevel(XDp *InstancePtr, u8 Level, u8 TxLevel); +void XDp_TxCfgTxPeLevel(XDp *InstancePtr, u8 Level, u8 TxLevel); + +/* xdp.c: TX AUX transaction functions. */ +u32 XDp_TxAuxRead(XDp *InstancePtr, u32 DpcdAddress, u32 BytesToRead, + void *ReadData); +u32 XDp_TxAuxWrite(XDp *InstancePtr, u32 DpcdAddress, u32 BytesToWrite, + void *WriteData); +u32 XDp_TxIicRead(XDp *InstancePtr, u8 IicAddress, u16 Offset, + u16 BytesToRead, void *ReadData); +u32 XDp_TxIicWrite(XDp *InstancePtr, u8 IicAddress, u8 BytesToWrite, + void *WriteData); + +/* xdp.c: TX functions for controlling the link configuration. */ +u32 XDp_TxSetDownspread(XDp *InstancePtr, u8 Enable); +u32 XDp_TxSetEnhancedFrameMode(XDp *InstancePtr, u8 Enable); +u32 XDp_TxSetLaneCount(XDp *InstancePtr, u8 LaneCount); +u32 XDp_TxSetLinkRate(XDp *InstancePtr, u8 LinkRate); +u32 XDp_TxSetScrambler(XDp *InstancePtr, u8 Enable); + +/* xdp.c: General usage functions. */ +void XDp_SetUserTimerHandler(XDp *InstancePtr, + XDp_TimerHandler CallbackFunc, void *CallbackRef); +void XDp_WaitUs(XDp *InstancePtr, u32 MicroSeconds); +u32 XDp_TxIsConnected(XDp *InstancePtr); +void XDp_TxEnableMainLink(XDp *InstancePtr); +void XDp_TxDisableMainLink(XDp *InstancePtr); +void XDp_TxResetPhy(XDp *InstancePtr, u32 Reset); +void XDp_TxSetPhyPolarityAll(XDp *InstancePtr, u8 Polarity); +void XDp_TxSetPhyPolarityLane(XDp *InstancePtr, u8 Lane, u8 Polarity); +u32 XDp_RxCheckLinkStatus(XDp *InstancePtr); +void XDp_RxDtgEn(XDp *InstancePtr); +void XDp_RxDtgDis(XDp *InstancePtr); +void XDp_RxSetLinkRate(XDp *InstancePtr, u8 LinkRate); +void XDp_RxSetLaneCount(XDp *InstancePtr, u8 LaneCount); + +/* xdp.c: Audio functions. */ +void XDp_RxAudioEn(XDp *InstancePtr); +void XDp_RxAudioDis(XDp *InstancePtr); +void XDp_RxAudioReset(XDp *InstancePtr); + +/* xdp_edid.c: EDID utility functions. */ +u32 XDp_TxGetEdid(XDp *InstancePtr, u8 *Edid); +u32 XDp_TxGetRemoteEdid(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 *Edid); +u32 XDp_TxGetEdidBlock(XDp *InstancePtr, u8 *Data, u8 BlockNum); +u32 XDp_TxGetRemoteEdidBlock(XDp *InstancePtr, u8 *Data, u8 BlockNum, + u8 LinkCountTotal, u8 *RelativeAddress); +u32 XDp_TxGetRemoteEdidDispIdExt(XDp *InstancePtr, u8 *Data, + u8 LinkCountTotal, u8 *RelativeAddress); +u32 XDp_TxGetDispIdDataBlock(u8 *DisplayIdRaw, u8 SectionTag, + u8 **DataBlockPtr); +u32 XDp_TxGetRemoteTiledDisplayDb(XDp *InstancePtr, u8 *EdidExt, + u8 LinkCountTotal, u8 *RelativeAddress, u8 **DataBlockPtr); + +/* xdp_intr.c: Interrupt handling functions. */ +void XDp_InterruptHandler(XDp *InstancePtr); +void XDp_TxSetHpdEventHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef); +void XDp_TxSetHpdPulseHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef); +void XDp_RxGenerateHpdInterrupt(XDp *InstancePtr, u16 DurationUs); +void XDp_RxInterruptEnable(XDp *InstancePtr, u32 Mask); +void XDp_RxInterruptDisable(XDp *InstancePtr, u32 Mask); +void XDp_RxSetIntrVmChangeHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef); +void XDp_RxSetIntrPowerStateHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef); +void XDp_RxSetIntrNoVideoHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef); +void XDp_RxSetIntrVBlankHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef); +void XDp_RxSetIntrTrainingLostHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef); +void XDp_RxSetIntrVideoHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef); +void XDp_RxSetIntrInfoPktHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef); +void XDp_RxSetIntrExtPktHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef); +void XDp_RxSetIntrTrainingDoneHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef); +void XDp_RxSetIntrBwChangeHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef); +void XDp_RxSetIntrTp1Handler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef); +void XDp_RxSetIntrTp2Handler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef); +void XDp_RxSetIntrTp3Handler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef); + +/* xdp_mst.c: Multi-stream transport (MST) functions for enabling or disabling + * MST mode. */ +void XDp_TxMstCfgModeEnable(XDp *InstancePtr); +void XDp_TxMstCfgModeDisable(XDp *InstancePtr); +u32 XDp_TxMstCapable(XDp *InstancePtr); +u32 XDp_TxMstEnable(XDp *InstancePtr); +u32 XDp_TxMstDisable(XDp *InstancePtr); + +/* xdp_mst.c: Multi-stream transport (MST) functions for enabling or disabling + * MST streams and selecting their associated target sinks. */ +void XDp_TxMstCfgStreamEnable(XDp *InstancePtr, u8 Stream); +void XDp_TxMstCfgStreamDisable(XDp *InstancePtr, u8 Stream); +u8 XDp_TxMstStreamIsEnabled(XDp *InstancePtr, u8 Stream); +void XDp_TxSetStreamSelectFromSinkList(XDp *InstancePtr, u8 Stream, u8 SinkNum); +void XDp_TxSetStreamSinkRad(XDp *InstancePtr, u8 Stream, u8 LinkCountTotal, + u8 *RelativeAddress); + +/* xdp_mst.c: Multi-stream transport (MST) functions related to MST topology + * discovery and management. */ +u32 XDp_TxDiscoverTopology(XDp *InstancePtr); +u32 XDp_TxFindAccessibleDpDevices(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress); +void XDp_TxTopologySwapSinks(XDp *InstancePtr, u8 Index0, u8 Index1); +void XDp_TxTopologySortSinksByTiling(XDp *InstancePtr); + +/* xdp_mst.c: Multi-stream transport (MST) functions for communicating + * with downstream DisplayPort devices. */ +u32 XDp_TxRemoteDpcdRead(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u32 DpcdAddress, u32 BytesToRead, u8 *ReadData); +u32 XDp_TxRemoteDpcdWrite(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u32 DpcdAddress, u32 BytesToWrite, u8 *WriteData); +u32 XDp_TxRemoteIicRead(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 IicAddress, u16 Offset, u16 BytesToRead, + u8 *ReadData); +u32 XDp_TxRemoteIicWrite(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 IicAddress, u8 BytesToWrite, u8 *WriteData); + +/* xdp_mst.c: Multi-stream transport (MST) functions related to MST stream + * allocation. */ +u32 XDp_TxAllocatePayloadStreams(XDp *InstancePtr); +u32 XDp_TxAllocatePayloadVcIdTable(XDp *InstancePtr, u8 VcId, u8 Ts); +u32 XDp_TxClearPayloadVcIdTable(XDp *InstancePtr); + +/* xdp_mst.c: Multi-stream transport (MST) functions for issuing sideband + * messages. */ +u32 XDp_TxSendSbMsgRemoteDpcdWrite(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u32 DpcdAddress, u32 BytesToWrite, u8 *WriteData); +u32 XDp_TxSendSbMsgRemoteDpcdRead(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u32 DpcdAddress, u32 BytesToRead, u8 *ReadData); +u32 XDp_TxSendSbMsgRemoteIicWrite(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 IicDeviceId, u8 BytesToWrite, u8 *WriteData); +u32 XDp_TxSendSbMsgRemoteIicRead(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 IicDeviceId, u8 Offset, u8 BytesToRead, + u8 *ReadData); +u32 XDp_TxSendSbMsgLinkAddress(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, XDp_TxSbMsgLinkAddressReplyDeviceInfo *DeviceInfo); +u32 XDp_TxSendSbMsgEnumPathResources(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u16 *AvailPbn, u16 *FullPbn); +u32 XDp_TxSendSbMsgAllocatePayload(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 VcId, u16 Pbn); +u32 XDp_TxSendSbMsgClearPayloadIdTable(XDp *InstancePtr); + +/* xdp_mst.c: Multi-stream transport (MST) utility functions. */ +void XDp_TxWriteGuid(XDp *InstancePtr, u8 LinkCountTotal, u8 *RelativeAddress, + u32 Guid[4]); +void XDp_TxGetGuid(XDp *InstancePtr, u8 LinkCountTotal, u8 *RelativeAddress, + u32 *Guid); + +/* xdp_selftest.c: Self test function. */ +u32 XDp_SelfTest(XDp *InstancePtr); + +/* xdp_spm.c: Stream policy maker functions. */ +void XDp_TxCfgMsaRecalculate(XDp *InstancePtr, u8 Stream); +void XDp_TxCfgMsaUseStandardVideoMode(XDp *InstancePtr, u8 Stream, + XVidC_VideoMode VideoMode); +void XDp_TxCfgMsaUseEdidPreferredTiming(XDp *InstancePtr, u8 Stream, + u8 *Edid); +void XDp_TxCfgMsaUseCustom(XDp *InstancePtr, u8 Stream, + XDp_TxMainStreamAttributes *MsaConfigCustom, u8 Recalculate); +void XDp_TxCfgMsaSetBpc(XDp *InstancePtr, u8 Stream, u8 BitsPerColor); +void XDp_TxCfgMsaEnSynchClkMode(XDp *InstancePtr, u8 Stream, u8 Enable); +void XDp_TxSetVideoMode(XDp *InstancePtr, u8 Stream); +void XDp_TxClearMsaValues(XDp *InstancePtr, u8 Stream); +void XDp_TxSetMsaValues(XDp *InstancePtr, u8 Stream); +void XDp_RxSetUserPixelWidth(XDp *InstancePtr, u8 UserPixelWidth); + +/******************* Macros (Inline Functions) Definitions ********************/ + +/******************************************************************************/ +/** + * This is function determines whether the DisplayPort core, represented by the + * XDp structure pointed to, is a transmitter (TX) or a receiver (RX). + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return XDP_RX if the core is of type RX. + * XDP_TX if the core is of type TX. + * + * @note C-style signature: + * XDp_CoreType XDp_GetCoreType(XDp *InstancePtr) + * +*******************************************************************************/ +#define XDp_GetCoreType(InstancePtr) ((InstancePtr)->Config.IsRx \ + ? XDP_RX : XDP_TX) + +/******************************* Compatibility ********************************/ + +#define XDptx_ReadReg XDp_ReadReg +#define XDprx_ReadReg XDp_ReadReg +#define XDptx_WriteReg XDp_WriteReg +#define XDprx_WriteReg XDp_WriteReg +#define XDptx_Config XDp_Config +#define XDprx_Config XDp_Config +#define XDptx_TimerHandler XDp_TimerHandler +#define XDprx_TimerHandler XDp_TimerHandler +#define XDptx_HpdEventHandler XDp_IntrHandler +#define XDptx_HpdPulseHandler XDp_IntrHandler +#define XDprx_IntrHandler XDp_IntrHandler + +#define XDptx_LookupConfig XDp_LookupConfig +#define XDprx_LookupConfig XDp_LookupConfig +#define XDptx_CfgInitialize XDp_CfgInitialize +#define XDprx_CfgInitialize XDp_CfgInitialize +#define XDptx_InitializeTx XDp_Initialize +#define XDprx_InitializeRx XDp_Initialize +#define XDptx_WaitUs XDp_WaitUs +#define XDprx_WaitUs XDp_WaitUs +#define XDptx_SetUserTimerHandler XDp_SetUserTimerHandler +#define XDprx_SetUserTimerHandler XDp_SetUserTimerHandler +#define XDptx_SelfTest XDp_SelfTest +#define XDprx_SelfTest XDp_SelfTest +#define XDptx_HpdInterruptHandler XDp_InterruptHandler +#define XDprx_InterruptHandler XDp_InterruptHandler + +#define XDptx XDp +#define XDprx XDp + +#define XDPTX XDP_TX +#define XDPRX XDP_RX + +#endif /* XDP_H_ */ diff --git a/XilinxProcessorIPLib/drivers/dp/src/xdp_edid.c b/XilinxProcessorIPLib/drivers/dp/src/xdp_edid.c new file mode 100644 index 00000000..3313a0f3 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/src/xdp_edid.c @@ -0,0 +1,416 @@ +/******************************************************************************* + * + * 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 xdp_edid.c + * + * This file contains functions related to accessing the Extended Display + * Identification Data (EDID) of a specified sink using the XDp driver operating + * in TX mode. + * + * @note None. + * + *
+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial release. TX code merged from the dptx driver. + *+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdp.h" + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function retrieves an immediately connected RX device's Extended Display + * Identification Data (EDID) structure. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Edid is a pointer to the Edid buffer to save to. + * + * @return + * - XST_SUCCESS if the I2C transactions to read the EDID were + * successful. + * - XST_ERROR_COUNT_MAX if the EDID read request timed out. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxGetEdid(XDp *InstancePtr, u8 *Edid) +{ + u32 Status; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(Edid != NULL); + + /* Retrieve the base EDID block = EDID block #0. */ + Status = XDp_TxGetEdidBlock(InstancePtr, Edid, 0); + + return Status; +} + +/******************************************************************************/ +/** + * This function retrieves a remote RX device's Extended Display Identification + * Data (EDID) structure. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkCountTotal is the number of DisplayPort links from the + * DisplayPort source to the target DisplayPort device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the target DisplayPort device. + * @param Edid is a pointer to the Edid buffer to save to. + * + * @return + * - XST_SUCCESS if the I2C transactions to read the EDID were + * successful. + * - XST_ERROR_COUNT_MAX if the EDID read request timed out. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxGetRemoteEdid(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 *Edid) +{ + u32 Status; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertNonvoid(Edid != NULL); + + /* Retrieve the base EDID block = EDID block #0. */ + Status = XDp_TxGetRemoteEdidBlock(InstancePtr, Edid, 0, LinkCountTotal, + RelativeAddress); + + return Status; +} + +/******************************************************************************/ +/** + * Retrieve an immediately connected RX device's Extended Display Identification + * Data (EDID) block given the block number. A block number of 0 represents the + * base EDID and subsequent block numbers represent EDID extension blocks. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Data is a pointer to the data buffer to save the block data to. + * @param BlockNum is the EDID block number to retrieve. + * + * @return + * - XST_SUCCESS if the block read has successfully completed with + * no errors. + * - XST_ERROR_COUNT_MAX if a time out occurred while attempting to + * read the requested block. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxGetEdidBlock(XDp *InstancePtr, u8 *Data, u8 BlockNum) +{ + u32 Status; + u16 Offset; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(Data != NULL); + + /* Calculate the I2C offset for the specified EDID block. */ + Offset = BlockNum * XDP_EDID_BLOCK_SIZE; + + /* Issue the I2C read for the specified EDID block. */ + Status = XDp_TxIicRead(InstancePtr, XDP_EDID_ADDR, Offset, + XDP_EDID_BLOCK_SIZE, Data); + + return Status; +} + +/******************************************************************************/ +/** + * Retrieve a downstream DisplayPort device's Extended Display Identification + * Data (EDID) block given the block number. A block number of 0 represents the + * base EDID and subsequent block numbers represent EDID extension blocks. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Data is a pointer to the data buffer to save the block data to. + * @param BlockNum is the EDID block number to retrieve. + * @param LinkCountTotal is the total DisplayPort links connecting the + * DisplayPort TX to the targeted downstream device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the targeted DisplayPort device. + * + * @return + * - XST_SUCCESS if the block read has successfully completed with + * no errors. + * - XST_ERROR_COUNT_MAX if a time out occurred while attempting to + * read the requested block. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxGetRemoteEdidBlock(XDp *InstancePtr, u8 *Data, u8 BlockNum, + u8 LinkCountTotal, u8 *RelativeAddress) +{ + u32 Status; + u16 Offset; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertNonvoid(Data != NULL); + + /* Calculate the I2C offset for the specified EDID block. */ + Offset = BlockNum * XDP_EDID_BLOCK_SIZE; + + /* Issue the I2C read for the specified EDID block. */ + Status = XDp_TxRemoteIicRead(InstancePtr, LinkCountTotal, + RelativeAddress, XDP_EDID_ADDR, Offset, XDP_EDID_BLOCK_SIZE, + Data); + + return Status; +} + +/******************************************************************************/ +/** + * Search for and retrieve a downstream DisplayPort device's Extended Display + * Identification Data (EDID) extension block of type DisplayID. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Data is a pointer to the data buffer to save the DisplayID to. + * @param LinkCountTotal is the total DisplayPort links connecting the + * DisplayPort TX to the targeted downstream device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the targeted DisplayPort device. + * + * @return + * - XST_SUCCESS a DisplayID extension block was found. + * - XST_ERROR_COUNT_MAX if a time out occurred while attempting to + * read an extension block. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_FAILURE if no DisplayID extension block was found or some + * error occurred in the search. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxGetRemoteEdidDispIdExt(XDp *InstancePtr, u8 *Data, + u8 LinkCountTotal, u8 *RelativeAddress) +{ + u32 Status; + u8 NumExt; + u8 ExtIndex; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertNonvoid(Data != NULL); + + /* Get the base EDID block. */ + Status = XDp_TxGetRemoteEdid(InstancePtr, LinkCountTotal, + RelativeAddress, Data); + if (Status != XST_SUCCESS) { + return Status; + } + + NumExt = Data[XDP_EDID_EXT_BLOCK_COUNT]; + for (ExtIndex = 0; ExtIndex < NumExt; ExtIndex++) { + /* Get an EDID extension block. */ + Status = XDp_TxGetRemoteEdidBlock(InstancePtr, Data, + ExtIndex + 1, LinkCountTotal, RelativeAddress); + if (Status != XST_SUCCESS) { + return Status; + } + + if (XDp_TxIsEdidExtBlockDispId(Data)) { + /* The current extension block is of type DisplayID. */ + return XST_SUCCESS; + } + } + + /* All extension blocks have been searched; no DisplayID extension block + * exists in sink's EDID structure. */ + return XST_FAILURE; +} + +/******************************************************************************/ +/** + * Given a section tag, search for and retrieve the appropriate section data + * block that is part of the specified DisplayID structure. + * + * @param DisplayIdRaw is a pointer to the DisplayID data. + * @param SectionTag is the tag to search for that represents the desired + * section data block. + * @param DataBlockPtr will be set by this function to point to the + * appropriate section data block that is part of the DisplayIdRaw. + * + * @return + * - XST_SUCCESS if the section data block with the specified tag + * was found. + * - XST_FAILURE otherwise. + * + * @note The DataBlockPtr argument is modified to point to the entry + * in DisplayIdRaw that represents the beginning of the desired + * section data block. + * +*******************************************************************************/ +u32 XDp_TxGetDispIdDataBlock(u8 *DisplayIdRaw, u8 SectionTag, u8 **DataBlockPtr) +{ + u8 Index; + u8 DispIdSize = DisplayIdRaw[XDP_TX_DISPID_SIZE]; + u8 *DataBlock; + + /* Verify arguments. */ + Xil_AssertNonvoid(DisplayIdRaw != NULL); + + /* Search for a section data block matching the specified tag. */ + for (Index = XDP_TX_DISPID_PAYLOAD_START; Index < DispIdSize; Index++) { + DataBlock = &DisplayIdRaw[Index]; + + /* Check if the tag mataches the current section data block. */ + if (DataBlock[XDP_TX_DISPID_DB_SEC_TAG] == SectionTag) { + *DataBlockPtr = DataBlock; + return XST_SUCCESS; + } + + if (DataBlock[XDP_TX_DISPID_DB_SEC_SIZE] == 0) { + /* End of valid section data blocks. */ + break; + } + else { + /* Increment the search index to skip the remaining + * bytes of the current section data block. */ + Index += (XDP_TX_DISPID_DB_SEC_SIZE + + DataBlock[XDP_TX_DISPID_DB_SEC_SIZE]); + } + } + + /* The entire DisplayID was searched or the search ended due to data + * no longer containing a valid section data block. No section data + * block with the specified tag was found. */ + return XST_FAILURE; +} + +/******************************************************************************/ +/** + * Search for and retrieve a downstream DisplayPort device's Tiled Display + * Topology (TDT) section data block that is part of the downstream device's + * DisplayID structure. The DisplayID structure is part of the Extended Display + * Identification Data (EDID) in the form of an extension block. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param EdidExt is a pointer to the data area that will be filled by the + * retrieved DisplayID extension block. + * @param LinkCountTotal is the total DisplayPort links connecting the + * DisplayPort TX to the targeted downstream device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the targeted DisplayPort device. + * @param DataBlockPtr will be set by this function to point to the TDT + * data block that is part of the EdidExt extension block. + * + * @return + * - XST_SUCCESS a DisplayID extension block was found. + * - XST_ERROR_COUNT_MAX if a time out occurred while attempting to + * read an extension block. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_FAILURE if no DisplayID extension block was found or some + * error occurred in the search. + * + * @note The EdidExt will be filled with the DisplayID EDID extension + * block and the DataBlockPtr argument is modified to point to the + * EdidExt entry representing the TDT section data block. + * +*******************************************************************************/ +u32 XDp_TxGetRemoteTiledDisplayDb(XDp *InstancePtr, u8 *EdidExt, + u8 LinkCountTotal, u8 *RelativeAddress, u8 **DataBlockPtr) +{ + u32 Status; + u8 *EdidExtDispId; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertNonvoid(EdidExt != NULL); + + /* Obtain a DisplayID EDID extension block. */ + Status = XDp_TxGetRemoteEdidDispIdExt(InstancePtr, EdidExt, + LinkCountTotal, RelativeAddress); + if (Status != XST_SUCCESS) { + /* The sink does not have a DisplayID EDID extension block. */ + return Status; + } + + /* The first byte of the extension block is the tag. */ + EdidExtDispId = &EdidExt[0x01]; + + /* Obtain the tiled display topology block data from the DisplayId EDID + * extension block. */ + Status = XDp_TxGetDispIdDataBlock(EdidExtDispId, XDP_TX_DISPID_TDT_TAG, + DataBlockPtr); + if (Status != XST_SUCCESS) { + /* The sink does not possess a DisplayID EDID data block with + * the specified tag. */ + return Status; + } + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/dp/src/xdp_hw.h b/XilinxProcessorIPLib/drivers/dp/src/xdp_hw.h new file mode 100644 index 00000000..0669c4ae --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/src/xdp_hw.h @@ -0,0 +1,2467 @@ +/******************************************************************************* + * + * 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 xdp_hw.h + * + * This header file contains the identifiers and low-level driver functions (or + * macros) that can be used to access the device. High-level driver functions + * are defined in xdp.h. + * + * @note None. + * + *
+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial release. TX code merged from the dptx driver. + *+ * +*******************************************************************************/ + +#ifndef XDP_HW_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XDP_HW_H_ + +/***************************** Include Files **********************************/ + +#include "xil_io.h" + +/************************** Constant Definitions ******************************/ + +/******************************************************************************/ +/** + * Address mapping for the DisplayPort core in TX mode. + * +*******************************************************************************/ +/** @name DPTX core registers: Link configuration field. + * @{ + */ +#define XDP_TX_LINK_BW_SET 0x000 /**< Set main link bandwidth + setting. */ +#define XDP_TX_LANE_COUNT_SET 0x004 /**< Set lane count setting. */ +#define XDP_TX_ENHANCED_FRAME_EN 0x008 /**< Enable enhanced framing + symbol sequence. */ +#define XDP_TX_TRAINING_PATTERN_SET 0x00C /**< Set the link training + pattern. */ +#define XDP_TX_LINK_QUAL_PATTERN_SET 0x010 /**< Transmit the link quality + pattern. */ +#define XDP_TX_SCRAMBLING_DISABLE 0x014 /**< Disable scrambler and + transmit all symbols. */ +#define XDP_TX_DOWNSPREAD_CTRL 0x018 /**< Enable a 0.5% spreading of + the clock. */ +#define XDP_TX_SOFT_RESET 0x01C /**< Software reset. */ +/* @} */ + +/** @name DPTX core registers: Core enables. + * @{ + */ +#define XDP_TX_ENABLE 0x080 /**< Enable the basic operations + of the DisplayPort TX + core or output stuffing + symbols if disabled. */ +#define XDP_TX_ENABLE_MAIN_STREAM 0x084 /**< Enable transmission of main + link video info. */ +#define XDP_TX_ENABLE_SEC_STREAM 0x088 /**< Enable the transmission of + secondary link info. */ +#define XDP_TX_FORCE_SCRAMBLER_RESET 0x0C0 /**< Force a scrambler reset. */ +#define XDP_TX_MST_CONFIG 0x0D0 /**< Enable MST. */ +/* @} */ + +/** @name DPTX core registers: Core ID. + * @{ + */ +#define XDP_TX_VERSION 0x0F8 /**< Version and revision of the + DisplayPort core. */ +#define XDP_TX_CORE_ID 0x0FC /**< DisplayPort protocol + version and revision. */ +/* @} */ + +/** @name DPTX core registers: AUX channel interface. + * @{ + */ +#define XDP_TX_AUX_CMD 0x100 /**< Initiates AUX commands. */ +#define XDP_TX_AUX_WRITE_FIFO 0x104 /**< Write data for the current + AUX command. */ +#define XDP_TX_AUX_ADDRESS 0x108 /**< Specifies the address of + current AUX command. */ +#define XDP_TX_AUX_CLK_DIVIDER 0x10C /**< Clock divider value for + generating the internal + 1MHz clock. */ +#define XDP_TX_USER_FIFO_OVERFLOW 0x110 /**< Indicates an overflow in + user FIFO. */ +#define XDP_TX_INTERRUPT_SIG_STATE 0x130 /**< The raw signal values for + interupt events. */ +#define XDP_TX_AUX_REPLY_DATA 0x134 /**< Reply data received during + the AUX reply. */ +#define XDP_TX_AUX_REPLY_CODE 0x138 /**< Reply code received from + the most recent AUX + command. */ +#define XDP_TX_AUX_REPLY_COUNT 0x13C /**< Number of reply + transactions receieved + over AUX. */ +#define XDP_TX_INTERRUPT_STATUS 0x140 /**< Status for interrupt + events. */ +#define XDP_TX_INTERRUPT_MASK 0x144 /**< Masks the specified + interrupt sources. */ +#define XDP_TX_REPLY_DATA_COUNT 0x148 /**< Total number of data bytes + actually received during + a transaction. */ +#define XDP_TX_REPLY_STATUS 0x14C /**< Reply status of most recent + AUX transaction. */ +#define XDP_TX_HPD_DURATION 0x150 /**< Duration of the HPD pulse + in microseconds. */ +/* @} */ + +/** @name DPTX core registers: Main stream attributes for SST / MST STREAM1. + * @{ + */ +#define XDP_TX_STREAM1_MSA_START 0x180 /**< Start of the MSA registers + for stream 1. */ +#define XDP_TX_MAIN_STREAM_HTOTAL 0x180 /**< Total number of clocks in + the horizontal framing + period. */ +#define XDP_TX_MAIN_STREAM_VTOTAL 0x184 /**< Total number of lines in + the video frame. */ +#define XDP_TX_MAIN_STREAM_POLARITY 0x188 /**< Polarity for the video + sync signals. */ +#define XDP_TX_MAIN_STREAM_HSWIDTH 0x18C /**< Width of the horizontal + sync pulse. */ +#define XDP_TX_MAIN_STREAM_VSWIDTH 0x190 /**< Width of the vertical sync + pulse. */ +#define XDP_TX_MAIN_STREAM_HRES 0x194 /**< Number of active pixels per + line (the horizontal + resolution). */ +#define XDP_TX_MAIN_STREAM_VRES 0x198 /**< Number of active lines (the + vertical resolution). */ +#define XDP_TX_MAIN_STREAM_HSTART 0x19C /**< Number of clocks between + the leading edge of the + horizontal sync and the + start of active data. */ +#define XDP_TX_MAIN_STREAM_VSTART 0x1A0 /**< Number of lines between the + leading edge of the + vertical sync and the + first line of active + data. */ +#define XDP_TX_MAIN_STREAM_MISC0 0x1A4 /**< Miscellaneous stream + attributes. */ +#define XDP_TX_MAIN_STREAM_MISC1 0x1A8 /**< Miscellaneous stream + attributes. */ +#define XDP_TX_M_VID 0x1AC /**< M value for the video + stream as computed by + the source core in + asynchronous clock + mode. Must be written + in synchronous mode. */ +#define XDP_TX_TU_SIZE 0x1B0 /**< Size of a transfer unit in + the framing logic. */ +#define XDP_TX_N_VID 0x1B4 /**< N value for the video + stream as computed by + the source core in + asynchronous clock mode. + Must be written in + synchronous mode. */ +#define XDP_TX_USER_PIXEL_WIDTH 0x1B8 /**< Selects the width of the + user data input port. */ +#define XDP_TX_USER_DATA_COUNT_PER_LANE 0x1BC /**< Used to translate the + number of pixels per + line to the native + internal 16-bit + datapath. */ +#define XDP_TX_MAIN_STREAM_INTERLACED 0x1C0 /**< Video is interlaced. */ +#define XDP_TX_MIN_BYTES_PER_TU 0x1C4 /**< The minimum number of bytes + per transfer unit. */ +#define XDP_TX_FRAC_BYTES_PER_TU 0x1C8 /**< The fractional component + when calculated the + XDP_TX_MIN_BYTES_PER_TU + register value. */ +#define XDP_TX_INIT_WAIT 0x1CC /**< Number of initial wait + cycles at the start of a + new line by the framing + logic, allowing enough + data to be buffered in + the input FIFO. */ +#define XDP_TX_STREAM1 0x1D0 /**< Average stream symbol + timeslots per MTP + config. */ +#define XDP_TX_STREAM2 0x1D4 /**< Average stream symbol + timeslots per MTP + config. */ +#define XDP_TX_STREAM3 0x1D8 /**< Average stream symbol + timeslots per MTP + config. */ +#define XDP_TX_STREAM4 0x1DC /**< Average stream symbol + timeslots per MTP + config. */ +/* @} */ + +/** @name DPTX core registers: PHY configuration status. + * @{ + */ +#define XDP_TX_PHY_CONFIG 0x200 /**< Transceiver PHY reset and + configuration. */ +#define XDP_TX_PHY_VOLTAGE_DIFF_LANE_0 0x220 /**< Controls the differential + voltage swing. */ +#define XDP_TX_PHY_VOLTAGE_DIFF_LANE_1 0x224 /**< Controls the differential + voltage swing. */ +#define XDP_TX_PHY_VOLTAGE_DIFF_LANE_2 0x228 /**< Controls the differential + voltage swing. */ +#define XDP_TX_PHY_VOLTAGE_DIFF_LANE_3 0x22C /**< Controls the differential + voltage swing. */ +#define XDP_TX_PHY_TRANSMIT_PRBS7 0x230 /**< Enable pseudo random bit + sequence 7 pattern + transmission for link + quality assessment. */ +#define XDP_TX_PHY_CLOCK_SELECT 0x234 /**< Instructs the PHY PLL to + generate the proper + clock frequency for the + required link rate. */ +#define XDP_TX_PHY_POWER_DOWN 0x238 /**< Controls PHY power down. */ +#define XDP_TX_PHY_PRECURSOR_LANE_0 0x23C /**< Controls the pre-cursor + level. */ +#define XDP_TX_PHY_PRECURSOR_LANE_1 0x240 /**< Controls the pre-cursor + level. */ +#define XDP_TX_PHY_PRECURSOR_LANE_2 0x244 /**< Controls the pre-cursor + level. */ +#define XDP_TX_PHY_PRECURSOR_LANE_3 0x248 /**< Controls the pre-cursor + level. */ +#define XDP_TX_PHY_POSTCURSOR_LANE_0 0x24C /**< Controls the post-cursor + level. */ +#define XDP_TX_PHY_POSTCURSOR_LANE_1 0x250 /**< Controls the post-cursor + level. */ +#define XDP_TX_PHY_POSTCURSOR_LANE_2 0x254 /**< Controls the post-cursor + level. */ +#define XDP_TX_PHY_POSTCURSOR_LANE_3 0x258 /**< Controls the post-cursor + level. */ +#define XDP_TX_PHY_STATUS 0x280 /**< Current PHY status. */ +#define XDP_TX_GT_DRP_COMMAND 0x2A0 /**< Provides acces to the GT + DRP ports. */ +#define XDP_TX_GT_DRP_READ_DATA 0x2A4 /**< Provides access to GT DRP + read data. */ +#define XDP_TX_GT_DRP_CHANNEL_STATUS 0x2A8 /**< Provides access to GT DRP + channel status. */ +/* @} */ + +/** @name DPTX core registers: DisplayPort audio. + * @{ + */ +#define XDP_TX_AUDIO_CONTROL 0x300 /**< Enables audio stream + packets in main link and + buffer control. */ +#define XDP_TX_AUDIO_CHANNELS 0x304 /**< Used to input active + channel count. */ +#define XDP_TX_AUDIO_INFO_DATA(NUM) (0x308 + 4 * (NUM - 1)) /**< Word + formatted as per CEA + 861-C info frame. */ +#define XDP_TX_AUDIO_MAUD 0x328 /**< M value of audio stream + as computed by the + DisplayPort TX core when + audio and link clocks + are synchronous. */ +#define XDP_TX_AUDIO_NAUD 0x32C /**< N value of audio stream + as computed by the + DisplayPort TX core when + audio and link clocks + are synchronous. */ +#define XDP_TX_AUDIO_EXT_DATA(NUM) (0x330 + 4 * (NUM - 1)) /**< Word + formatted as per + extension packet. */ +/* @} */ + +/** @name DPTX core registers: Main stream attributes for MST STREAM2, 3, and 4. + * @{ + */ +#define XDP_TX_STREAM2_MSA_START 0x500 /**< Start of the MSA registers + for stream 2. */ +#define XDP_TX_STREAM2_MSA_START_OFFSET (XDP_TX_STREAM2_MSA_START - \ + XDP_TX_STREAM1_MSA_START) /**< The MSA registers for + stream 2 are at an + offset from the + corresponding registers + of stream 1. */ +#define XDP_TX_STREAM3_MSA_START 0x550 /**< Start of the MSA registers + for stream 3. */ +#define XDP_TX_STREAM3_MSA_START_OFFSET (XDP_TX_STREAM3_MSA_START - \ + XDP_TX_STREAM1_MSA_START) /**< The MSA registers for + stream 3 are at an + offset from the + corresponding registers + of stream 1. */ +#define XDP_TX_STREAM4_MSA_START 0x5A0 /**< Start of the MSA registers + for stream 4. */ +#define XDP_TX_STREAM4_MSA_START_OFFSET (XDP_TX_STREAM4_MSA_START - \ + XDP_TX_STREAM1_MSA_START) /**< The MSA registers for + stream 4 are at an + offset from the + corresponding registers + of stream 1. */ +/* @} */ + +#define XDP_TX_VC_PAYLOAD_BUFFER_ADDR 0x800 /**< Virtual channel payload + table (0xFF bytes). */ + +/******************************************************************************/ + +/** @name DPTX core masks, shifts, and register values. + * @{ + */ +/* 0x000: LINK_BW_SET */ +#define XDP_TX_LINK_BW_SET_162GBPS 0x06 /**< 1.62 Gbps link rate. */ +#define XDP_TX_LINK_BW_SET_270GBPS 0x0A /**< 2.70 Gbps link rate. */ +#define XDP_TX_LINK_BW_SET_540GBPS 0x14 /**< 5.40 Gbps link rate. */ +/* 0x001: LANE_COUNT_SET */ +#define XDP_TX_LANE_COUNT_SET_1 0x01 /**< Lane count of 1. */ +#define XDP_TX_LANE_COUNT_SET_2 0x02 /**< Lane count of 2. */ +#define XDP_TX_LANE_COUNT_SET_4 0x04 /**< Lane count of 4. */ +/* 0x00C: TRAINING_PATTERN_SET */ +#define XDP_TX_TRAINING_PATTERN_SET_OFF 0x0 /**< Training off. */ +#define XDP_TX_TRAINING_PATTERN_SET_TP1 0x1 /**< Training pattern 1 used for + clock recovery. */ +#define XDP_TX_TRAINING_PATTERN_SET_TP2 0x2 /**< Training pattern 2 used for + channel equalization. */ +#define XDP_TX_TRAINING_PATTERN_SET_TP3 0x3 /**< Training pattern 3 used for + channel equalization for + cores with DP v1.2. */ +/* 0x010: LINK_QUAL_PATTERN_SET */ +#define XDP_TX_LINK_QUAL_PATTERN_SET_OFF 0x0 /**< Link quality test pattern + not transmitted. */ +#define XDP_TX_LINK_QUAL_PATTERN_SET_D102_TEST \ + 0x1 /**< D10.2 unscrambled test + pattern transmitted. */ +#define XDP_TX_LINK_QUAL_PATTERN_SET_SER_MES \ + 0x2 /**< Symbol error rate + measurement pattern + transmitted. */ +#define XDP_TX_LINK_QUAL_PATTERN_SET_PRBS7 \ + 0x3 /**< Pseudo random bit sequence + 7 transmitted. */ +/* 0x01C: SOFTWARE_RESET */ +#define XDP_TX_SOFT_RESET_VIDEO_STREAM1_MASK \ + 0x00000001 /**< Reset video logic. */ +#define XDP_TX_SOFT_RESET_VIDEO_STREAM2_MASK \ + 0x00000002 /**< Reset video logic. */ +#define XDP_TX_SOFT_RESET_VIDEO_STREAM3_MASK \ + 0x00000004 /**< Reset video logic. */ +#define XDP_TX_SOFT_RESET_VIDEO_STREAM4_MASK \ + 0x00000008 /**< Reset video logic. */ +#define XDP_TX_SOFT_RESET_AUX_MASK \ + 0x00000080 /**< Reset AUX logic. */ +#define XDP_TX_SOFT_RESET_VIDEO_STREAM_ALL_MASK \ + 0x0000000F /**< Reset video logic for all + streams. */ +/* 0x0D0: TX_MST_CONFIG */ +#define XDP_TX_MST_CONFIG_MST_EN_MASK \ + 0x00000001 /**< Enable MST. */ +#define XDP_TX_MST_CONFIG_VCP_UPDATED_MASK \ + 0x00000002 /**< The VC payload has been + updated in the sink. */ +/* 0x0F8: VERSION */ +#define XDP_TX_VERSION_INTER_REV_MASK \ + 0x0000000F /**< Internal revision. */ +#define XDP_TX_VERSION_CORE_PATCH_MASK \ + 0x00000030 /**< Core patch details. */ +#define XDP_TX_VERSION_CORE_PATCH_SHIFT \ + 8 /**< Shift bits for core patch + details. */ +#define XDP_TX_VERSION_CORE_VER_REV_MASK \ + 0x000000C0 /**< Core version revision. */ +#define XDP_TX_VERSION_CORE_VER_REV_SHIFT \ + 12 /**< Shift bits for core version + revision. */ +#define XDP_TX_VERSION_CORE_VER_MNR_MASK \ + 0x00000F00 /**< Core minor version. */ +#define XDP_TX_VERSION_CORE_VER_MNR_SHIFT \ + 16 /**< Shift bits for core minor + version. */ +#define XDP_TX_VERSION_CORE_VER_MJR_MASK \ + 0x0000F000 /**< Core major version. */ +#define XDP_TX_VERSION_CORE_VER_MJR_SHIFT \ + 24 /**< Shift bits for core major + version. */ +/* 0x0FC: CORE_ID */ +#define XDP_TX_CORE_ID_TYPE_MASK 0x0000000F /**< Core type. */ +#define XDP_TX_CORE_ID_TYPE_TX 0x0 /**< Core is a transmitter. */ +#define XDP_TX_CORE_ID_TYPE_RX 0x1 /**< Core is a receiver. */ +#define XDP_TX_CORE_ID_DP_REV_MASK \ + 0x000000F0 /**< DisplayPort protocol + revision. */ +#define XDP_TX_CORE_ID_DP_REV_SHIFT \ + 8 /**< Shift bits for DisplayPort + protocol revision. */ +#define XDP_TX_CORE_ID_DP_MNR_VER_MASK \ + 0x00000F00 /**< DisplayPort protocol minor + version. */ +#define XDP_TX_CORE_ID_DP_MNR_VER_SHIFT \ + 16 /**< Shift bits for DisplayPort + protocol major + version. */ +#define XDP_TX_CORE_ID_DP_MJR_VER_MASK \ + 0x0000F000 /**< DisplayPort protocol major + version. */ +#define XDP_TX_CORE_ID_DP_MJR_VER_SHIFT \ + 24 /**< Shift bits for DisplayPort + protocol major + version. */ +/* 0x100: AUX_CMD */ +#define XDP_TX_AUX_CMD_NBYTES_TRANSFER_MASK \ + 0x0000000F /**< Number of bytes to transfer + with the current AUX + command. */ +#define XDP_TX_AUX_CMD_MASK 0x00000F00 /**< AUX command. */ +#define XDP_TX_AUX_CMD_SHIFT 8 /**< Shift bits for command. */ +#define XDP_TX_AUX_CMD_I2C_WRITE 0x0 /**< I2C-over-AUX write + command. */ +#define XDP_TX_AUX_CMD_I2C_READ 0x1 /**< I2C-over-AUX read + command. */ +#define XDP_TX_AUX_CMD_I2C_WRITE_STATUS 0x2 /**< I2C-over-AUX write status + command. */ +#define XDP_TX_AUX_CMD_I2C_WRITE_MOT 0x4 /**< I2C-over-AUX write MOT + (middle-of-transaction) + command. */ +#define XDP_TX_AUX_CMD_I2C_READ_MOT 0x5 /**< I2C-over-AUX read MOT + (middle-of-transaction) + command. */ +#define XDP_TX_AUX_CMD_I2C_WRITE_STATUS_MOT \ + 0x6 /**< I2C-over-AUX write status + MOT (middle-of- + transaction) command. */ +#define XDP_TX_AUX_CMD_WRITE 0x8 /**< AUX write command. */ +#define XDP_TX_AUX_CMD_READ 0x9 /**< AUX read command. */ +#define XDP_TX_AUX_CMD_ADDR_ONLY_TRANSFER_EN \ + 0x00001000 /**< Address only transfer + enable (STOP will be + sent after command). */ +/* 0x10C: AUX_CLK_DIVIDER */ +#define XDP_TX_AUX_CLK_DIVIDER_VAL_MASK 0x00FF /**< Clock divider value. */ +#define XDP_TX_AUX_CLK_DIVIDER_AUX_SIG_WIDTH_FILT_MASK \ + 0xFF00 /**< AUX (noise) signal width + filter. */ +#define XDP_TX_AUX_CLK_DIVIDER_AUX_SIG_WIDTH_FILT_SHIFT \ + 8 /**< Shift bits for AUX signal + width filter. */ +/* 0x130: INTERRUPT_SIG_STATE */ +#define XDP_TX_INTERRUPT_SIG_STATE_HPD_STATE_MASK \ + 0x00000001 /**< Raw state of the HPD pin on + the DP connector. */ +#define XDP_TX_INTERRUPT_SIG_STATE_REQUEST_STATE_MASK \ + 0x00000002 /**< A request is currently + being sent. */ +#define XDP_TX_INTERRUPT_SIG_STATE_REPLY_STATE_MASK \ + 0x00000004 /**< A reply is currently being + received. */ +#define XDP_TX_INTERRUPT_SIG_STATE_REPLY_TIMEOUT_MASK \ + 0x00000008 /**< A reply timeout has + occurred. */ +/* 0x138: AUX_REPLY_CODE */ +#define XDP_TX_AUX_REPLY_CODE_ACK 0x0 /**< AUX command ACKed. */ +#define XDP_TX_AUX_REPLY_CODE_I2C_ACK 0x0 /**< I2C-over-AUX command + not ACKed. */ +#define XDP_TX_AUX_REPLY_CODE_NACK 0x1 /**< AUX command not ACKed. */ +#define XDP_TX_AUX_REPLY_CODE_DEFER 0x2 /**< AUX command deferred. */ +#define XDP_TX_AUX_REPLY_CODE_I2C_NACK 0x4 /**< I2C-over-AUX command not + ACKed. */ +#define XDP_TX_AUX_REPLY_CODE_I2C_DEFER 0x8 /**< I2C-over-AUX command + deferred. */ +/* 0x140: INTERRUPT_STATUS */ +#define XDP_TX_INTERRUPT_STATUS_HPD_IRQ_MASK \ + 0x00000001 /**< Detected an IRQ framed with + the proper timing on the + HPD signal. */ +#define XDP_TX_INTERRUPT_STATUS_HPD_EVENT_MASK \ + 0x00000002 /**< Detected the presence of + the HPD signal. */ +#define XDP_TX_INTERRUPT_STATUS_REPLY_RECEIVED_MASK \ + 0x00000004 /**< An AUX reply transaction + has been detected. */ +#define XDP_TX_INTERRUPT_STATUS_REPLY_TIMEOUT_MASK \ + 0x00000008 /**< A reply timeout has + occurred. */ +#define XDP_TX_INTERRUPT_STATUS_HPD_PULSE_DETECTED_MASK \ + 0x00000010 /**< A pulse on the HPD line was + detected. */ +#define XDP_TX_INTERRUPT_STATUS_EXT_PKT_TXD_MASK \ + 0x00000020 /**< Extended packet has been + transmitted and the core + is ready to accept a new + packet. */ +/* 0x144: INTERRUPT_MASK */ +#define XDP_TX_INTERRUPT_MASK_HPD_IRQ_MASK \ + 0x00000001 /**< Mask HPD IRQ interrupt. */ +#define XDP_TX_INTERRUPT_MASK_HPD_EVENT_MASK \ + 0x00000002 /**< Mask HPD event + interrupt. */ +#define XDP_TX_INTERRUPT_MASK_REPLY_RECEIVED_MASK \ + 0x00000004 /**< Mask reply received + interrupt. */ +#define XDP_TX_INTERRUPT_MASK_REPLY_TIMEOUT_MASK \ + 0x00000008 /**< Mask reply received + interrupt. */ +#define XDP_TX_INTERRUPT_MASK_HPD_PULSE_DETECTED_MASK \ + 0x00000010 /**< Mask HPD pulse detected + interrupt. */ +#define XDP_TX_INTERRUPT_MASK_EXT_PKT_TXD_MASK \ + 0x00000020 /**< Mask extended packet + transmit interrupt. */ +/* 0x14C: REPLY_STATUS */ +#define XDP_TX_REPLY_STATUS_REPLY_RECEIVED_MASK \ + 0x00000001 /**< AUX transaction is complete + and a valid reply + transaction received. */ +#define XDP_TX_REPLY_STATUS_REPLY_IN_PROGRESS_MASK \ + 0x00000002 /**< AUX reply is currently + being received. */ +#define XDP_TX_REPLY_STATUS_REQUEST_IN_PROGRESS_MASK \ + 0x00000004 /**< AUX request is currently + being transmitted. */ +#define XDP_TX_REPLY_STATUS_REPLY_ERROR_MASK \ + 0x00000008 /**< Detected an error in the + AUX reply of the most + recent transaction. */ +#define XDP_TX_REPLY_STATUS_REPLY_STATUS_STATE_MASK \ + 0x00000FF0 /**< Internal AUX reply state + machine status bits. */ +#define XDP_TX_REPLY_STATUS_REPLY_STATUS_STATE_SHIFT \ + 4 /**< Shift bits for the internal + AUX reply state machine + status. */ +/* 0x188, 0x508, 0x558, 0x5A8: MAIN_STREAM[1-4]_POLARITY */ +#define XDP_TX_MAIN_STREAMX_POLARITY_HSYNC_POL_MASK \ + 0x00000001 /**< Polarity of the horizontal + sync pulse. */ +#define XDP_TX_MAIN_STREAMX_POLARITY_VSYNC_POL_MASK \ + 0x00000002 /**< Polarity of the vertical + sync pulse. */ +#define XDP_TX_MAIN_STREAMX_POLARITY_VSYNC_POL_SHIFT \ + 1 /**< Shift bits for polarity of + the vertical sync + pulse. */ +/* 0x1A4, 0x524, 0x574, 0x5C4: MAIN_STREAM[1-4]_MISC0 */ +#define XDP_TX_MAIN_STREAMX_MISC0_SYNC_CLK_MASK \ + 0x00000001 /**< Synchronous clock. */ +#define XDP_TX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_MASK \ + 0x00000006 /**< Component format. */ +#define XDP_TX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_SHIFT \ + 1 /**< Shift bits for component + format. */ +#define XDP_TX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_RGB \ + 0x0 /**< Stream's component format + is RGB. */ +#define XDP_TX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_YCBCR422 \ + 0x1 /**< Stream's component format + is YcbCr 4:2:2. */ +#define XDP_TX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_YCBCR444 \ + 0x2 /**< Stream's component format + is YcbCr 4:4:4. */ +#define XDP_TX_MAIN_STREAMX_MISC0_DYNAMIC_RANGE_MASK \ + 0x00000008 /**< Dynamic range. */ +#define XDP_TX_MAIN_STREAMX_MISC0_DYNAMIC_RANGE_SHIFT \ + 3 /**< Shift bits for dynamic + range. */ +#define XDP_TX_MAIN_STREAMX_MISC0_YCBCR_COLORIMETRY_MASK \ + 0x00000010 /**< YCbCr colorimetry. */ +#define XDP_TX_MAIN_STREAMX_MISC0_YCBCR_COLORIMETRY_SHIFT \ + 4 /**< Shift bits for YCbCr + colorimetry. */ +#define XDP_TX_MAIN_STREAMX_MISC0_BDC_MASK \ + 0x000000E0 /**< Bit depth per color + component (BDC). */ +#define XDP_TX_MAIN_STREAMX_MISC0_BDC_SHIFT \ + 5 /**< Shift bits for BDC.*/ +#define XDP_TX_MAIN_STREAMX_MISC0_BDC_6BPC \ + 0x0 /**< 6 bits per component.*/ +#define XDP_TX_MAIN_STREAMX_MISC0_BDC_8BPC \ + 0x1 /**< 8 bits per component.*/ +#define XDP_TX_MAIN_STREAMX_MISC0_BDC_10BPC \ + 0x2 /**< 10 bits per component.*/ +#define XDP_TX_MAIN_STREAMX_MISC0_BDC_12BPC \ + 0x3 /**< 12 bits per component.*/ +#define XDP_TX_MAIN_STREAMX_MISC0_BDC_16BPC \ + 0x4 /**< 16 bits per component.*/ +/* 0x1A8, 0x528, 0x578, 0x5C8: MAIN_STREAM[1-4]_MISC1 */ +#define XDP_TX_MAIN_STREAMX_MISC1_INTERLACED_VTOTAL_GIVEN_MASK \ + 0x00000001 /**< Interlaced vertical total + even. */ +#define XDP_TX_MAIN_STREAMX_MISC1_STEREO_VID_ATTR_MASK \ + 0x00000006 /**< Stereo video attribute. */ +#define XDP_TX_MAIN_STREAMX_MISC1_STEREO_VID_ATTR_SHIFT \ + 1 /**< Shift bits for stereo video + attribute. */ +/* 0x200: PHY_CONFIG */ +#define XDP_TX_PHY_CONFIG_PHY_RESET_ENABLE_MASK \ + 0x0000000 /**< Release reset. */ +#define XDP_TX_PHY_CONFIG_PHY_RESET_MASK \ + 0x0000001 /**< Hold the PHY in reset. */ +#define XDP_TX_PHY_CONFIG_GTTX_RESET_MASK \ + 0x0000002 /**< Hold GTTXRESET in reset. */ +#define XDP_TX_PHY_CONFIG_TX_PHY_PMA_RESET_MASK \ + 0x0000100 /**< Hold TX_PHY_PMA reset. */ +#define XDP_TX_PHY_CONFIG_TX_PHY_PCS_RESET_MASK \ + 0x0000200 /**< Hold TX_PHY_PCS reset. */ +#define XDP_TX_PHY_CONFIG_TX_PHY_POLARITY_MASK \ + 0x0000800 /**< Set TX_PHY_POLARITY. */ +#define XDP_TX_PHY_CONFIG_TX_PHY_PRBSFORCEERR_MASK \ + 0x0001000 /**< Set TX_PHY_PRBSFORCEERR. */ +#define XDP_TX_PHY_CONFIG_TX_PHY_LOOPBACK_MASK \ + 0x000E000 /**< Set TX_PHY_LOOPBACK. */ +#define XDP_TX_PHY_CONFIG_TX_PHY_LOOPBACK_SHIFT 13 /**< Shift bits for + TX_PHY_LOOPBACK. */ +#define XDP_TX_PHY_CONFIG_TX_PHY_POLARITY_IND_LANE_MASK \ + 0x0010000 /**< Set to enable individual + lane polarity. */ +#define XDP_TX_PHY_CONFIG_TX_PHY_POLARITY_LANE0_MASK \ + 0x0020000 /**< Set TX_PHY_POLARITY for + lane 0. */ +#define XDP_TX_PHY_CONFIG_TX_PHY_POLARITY_LANE1_MASK \ + 0x0040000 /**< Set TX_PHY_POLARITY for + lane 1. */ +#define XDP_TX_PHY_CONFIG_TX_PHY_POLARITY_LANE2_MASK \ + 0x0080000 /**< Set TX_PHY_POLARITY for + lane 2. */ +#define XDP_TX_PHY_CONFIG_TX_PHY_POLARITY_LANE3_MASK \ + 0x0100000 /**< Set TX_PHY_POLARITY for + lane 3. */ +#define XDP_TX_PHY_CONFIG_TX_PHY_8B10BEN_MASK \ + 0x0200000 /**< 8B10B encoding enable. */ +#define XDP_TX_PHY_CONFIG_GT_ALL_RESET_MASK \ + 0x0000003 /**< Reset GT and PHY. */ +/* 0x234: PHY_CLOCK_SELECT */ +#define XDP_TX_PHY_CLOCK_SELECT_162GBPS 0x1 /**< 1.62 Gbps link. */ +#define XDP_TX_PHY_CLOCK_SELECT_270GBPS 0x3 /**< 2.70 Gbps link. */ +#define XDP_TX_PHY_CLOCK_SELECT_540GBPS 0x5 /**< 5.40 Gbps link. */ +/* 0x0220, 0x0224, 0x0228, 0x022C: XDP_TX_PHY_VOLTAGE_DIFF_LANE_[0-3] */ +#define XDP_TX_VS_LEVEL_0 0x2 /**< Voltage swing level 0. */ +#define XDP_TX_VS_LEVEL_1 0x5 /**< Voltage swing level 1. */ +#define XDP_TX_VS_LEVEL_2 0x8 /**< Voltage swing level 2. */ +#define XDP_TX_VS_LEVEL_3 0xF /**< Voltage swing level 3. */ +#define XDP_TX_VS_LEVEL_OFFSET 0x4 /**< Voltage swing compensation + offset used when there's + no redriver in display + path. */ +/* 0x024C, 0x0250, 0x0254, 0x0258: XDP_TX_PHY_POSTCURSOR_LANE_[0-3] */ +#define XDP_TX_PE_LEVEL_0 0x00 /**< Pre-emphasis level 0. */ +#define XDP_TX_PE_LEVEL_1 0x0E /**< Pre-emphasis level 1. */ +#define XDP_TX_PE_LEVEL_2 0x14 /**< Pre-emphasis level 2. */ +#define XDP_TX_PE_LEVEL_3 0x1B /**< Pre-emphasis level 3. */ +/* 0x280: PHY_STATUS */ +#define XDP_TX_PHY_STATUS_RESET_LANE_0_1_DONE_MASK \ + 0x00000003 /**< Reset done for lanes + 0 and 1. */ +#define XDP_TX_PHY_STATUS_RESET_LANE_2_3_DONE_MASK \ + 0x0000000C /**< Reset done for lanes + 2 and 3. */ +#define XDP_TX_PHY_STATUS_RESET_LANE_2_3_DONE_SHIFT \ + 2 /**< Shift bits for reset done + for lanes 2 and 3. */ +#define XDP_TX_PHY_STATUS_PLL_LANE0_1_LOCK_MASK \ + 0x00000010 /**< PLL locked for lanes + 0 and 1. */ +#define XDP_TX_PHY_STATUS_PLL_LANE2_3_LOCK_MASK \ + 0x00000020 /**< PLL locked for lanes + 2 and 3. */ +#define XDP_TX_PHY_STATUS_PLL_FABRIC_LOCK_MASK \ + 0x00000040 /**< FPGA fabric clock PLL + locked. */ +#define XDP_TX_PHY_STATUS_TX_BUFFER_STATUS_LANE_0_MASK \ + 0x00030000 /**< TX buffer status lane 0. */ +#define XDP_TX_PHY_STATUS_TX_BUFFER_STATUS_LANE_0_SHIFT \ + 16 /**< Shift bits for TX buffer + status lane 0. */ +#define XDP_TX_PHY_STATUS_TX_ERROR_LANE_0_MASK \ + 0x000C0000 /**< TX error on lane 0. */ +#define XDP_TX_PHY_STATUS_TX_ERROR_LANE_0_SHIFT \ + 18 /**< Shift bits for TX error on + lane 0. */ +#define XDP_TX_PHY_STATUS_TX_BUFFER_STATUS_LANE_1_MASK \ + 0x00300000 /**< TX buffer status lane 1. */ +#define XDP_TX_PHY_STATUS_TX_BUFFER_STATUS_LANE_1_SHIFT \ + 20 /**< Shift bits for TX buffer + status lane 1. */ +#define XDP_TX_PHY_STATUS_TX_ERROR_LANE_1_MASK \ + 0x00C00000 /**< TX error on lane 1. */ +#define XDP_TX_PHY_STATUS_TX_ERROR_LANE_1_SHIFT \ + 22 /**< Shift bits for TX error on + lane 1. */ +#define XDP_TX_PHY_STATUS_TX_BUFFER_STATUS_LANE_2_MASK \ + 0x03000000 /**< TX buffer status lane 2. */ +#define XDP_TX_PHY_STATUS_TX_BUFFER_STATUS_LANE_2_SHIFT \ + 24 /**< Shift bits for TX buffer + status lane 2. */ +#define XDP_TX_PHY_STATUS_TX_ERROR_LANE_2_MASK \ + 0x0C000000 /**< TX error on lane 2. */ +#define XDP_TX_PHY_STATUS_TX_ERROR_LANE_2_SHIFT \ + 26 /**< Shift bits for TX error on + lane 2. */ +#define XDP_TX_PHY_STATUS_TX_BUFFER_STATUS_LANE_3_MASK \ + 0x30000000 /**< TX buffer status lane 3. */ +#define XDP_TX_PHY_STATUS_TX_BUFFER_STATUS_LANE_3_SHIFT \ + 28 /**< Shift bits for TX buffer + status lane 3. */ +#define XDP_TX_PHY_STATUS_TX_ERROR_LANE_3_MASK \ + 0xC0000000 /**< TX error on lane 3. */ +#define XDP_TX_PHY_STATUS_TX_ERROR_LANE_3_SHIFT \ + 30 /**< Shift bits for TX error on + lane 3. */ +#define XDP_TX_PHY_STATUS_LANES_0_1_READY_MASK \ + 0x00000013 /**< Lanes 0 and 1 are ready. */ +#define XDP_TX_PHY_STATUS_ALL_LANES_READY_MASK \ + 0x0000003F /**< All lanes are ready. */ +/* 0x2A0: XDP_TX_GT_DRP_COMMAND */ +#define XDP_TX_GT_DRP_COMMAND_DRP_ADDR_MASK \ + 0x000F /**< DRP address. */ +#define XDP_TX_GT_DRP_COMMAND_DRP_RW_CMD_MASK \ + 0x0080 /**< DRP read/write command + (Read=0, Write=1). */ +#define XDP_TX_GT_DRP_COMMAND_DRP_W_DATA_MASK \ + 0xFF00 /**< DRP write data. */ +#define XDP_TX_GT_DRP_COMMAND_DRP_W_DATA_SHIFT \ + 16 /**< Shift bits for DRP write + data. */ +/* @} */ + +/******************************************************************************/ + +/******************************************************************************/ +/** + * Address mapping for the DisplayPort core in RX mode. + * +*******************************************************************************/ + +/** @name DPRX core registers: Receiver core configuration. + * @{ + */ +#define XDP_RX_LINK_ENABLE 0x000 /**< Enable the receiver + core. */ +#define XDP_RX_AUX_CLK_DIVIDER 0x004 /**< Clock divider value for + generating the internal + 1MHz clock. */ +#define XDP_RX_DTG_ENABLE 0x00C /**< Enables the display timing + generator (DTG). */ +#define XDP_RX_USER_PIXEL_WIDTH 0x010 /**< Selects the width of the + user data input port. */ +#define XDP_RX_INTERRUPT_MASK 0x014 /**< Masks the specified + interrupt sources for + stream 1. */ +#define XDP_RX_MISC_CTRL 0x018 /**< Miscellaneous control of + RX behavior. */ +#define XDP_RX_SOFT_RESET 0x01C /**< Software reset. */ +/* @} */ + +/** @name DPRX core registers: AUX channel status. + * @{ + */ +#define XDP_RX_AUX_REQ_IN_PROGRESS 0x020 /**< Indicates the receipt of an + AUX channel request. */ +#define XDP_RX_REQ_ERROR_COUNT 0x024 /**< Provides a running total of + errors detected on + inbound AUX channel + requests. */ +#define XDP_RX_REQ_COUNT 0x028 /**< Provides a running total of + the number of AUX + requests received. */ +#define XDP_RX_HPD_INTERRUPT 0x02C /**< Instructs the DisplayPort + RX core to assert an + interrupt to the TX + using the HPD signal. */ +#define XDP_RX_REQ_CLK_WIDTH 0x030 /**< Holds the half period of + the recovered AUX + clock. */ +#define XDP_RX_REQ_CMD 0x034 /**< Provides the most recent + AUX command received. */ +#define XDP_RX_REQ_ADDRESS 0x038 /**< Contains the address field + of the most recent AUX + request. */ +#define XDP_RX_REQ_LENGTH 0x03C /**< Contains length of the most + recent AUX request. */ +/* @} */ + +/** @name DPRX core registers: Interrupt registers. + * @{ + */ +#define XDP_RX_INTERRUPT_CAUSE 0x040 /**< Indicates the cause of + pending host interrupts + for stream 1, training, + payload allocation, and + for the AUX channel. */ +#define XDP_RX_INTERRUPT_MASK_1 0x044 /**< Masks the specified + interrupt sources for + streams 2, 3, 4. */ +#define XDP_RX_INTERRUPT_CAUSE_1 0x048 /**< Indicates the cause of a + pending host interrupts + for streams 2, 3, 4. */ +#define XDP_RX_HSYNC_WIDTH 0x050 /**< Controls the timing of the + active-high horizontal + sync pulse generated + by the display timing + generator (DTG). */ +#define XDP_RX_FAST_I2C_DIVIDER 0x060 /**< Fast I2C mode clock divider + value. */ +/* @} */ + +/** @name DPRX core registers: DPCD fields. + * @{ + */ +#define XDP_RX_LOCAL_EDID_VIDEO 0x084 /**< Indicates the presence of + EDID information for the + video stream. */ +#define XDP_RX_LOCAL_EDID_AUDIO 0x088 /**< Indicates the presence of + EDID information for the + audio stream. */ +#define XDP_RX_REMOTE_CMD 0x08C /**< Used for passing remote + information to the + DisplayPort TX. */ +#define XDP_RX_DEVICE_SERVICE_IRQ 0x090 /**< Indicates the DPCD + DEVICE_SERVICE_IRQ_ + VECTOR state. */ +#define XDP_RX_VIDEO_UNSUPPORTED 0x094 /**< DPCD register bit to inform + the DisplayPort TX that + video data is not + supported. */ +#define XDP_RX_AUDIO_UNSUPPORTED 0x098 /**< DPCD register bit to inform + the DisplayPort TX that + audio data is not + supported. */ +#define XDP_RX_OVER_LINK_BW_SET 0x09C /**< Used to override the main + link bandwidth setting + in the DPCD. */ +#define XDP_RX_OVER_LANE_COUNT_SET 0x0A0 /**< Used to override the lane + count setting in the + DPCD. */ +#define XDP_RX_OVER_TP_SET 0x0A4 /**< Used to override the link + training pattern in the + DPCD. */ +#define XDP_RX_OVER_TRAINING_LANE0_SET 0x0A8 /**< Used to override the + TRAINING_LANE0_SET + register in the DPCD. */ +#define XDP_RX_OVER_TRAINING_LANE1_SET 0x0AC /**< Used to override the + TRAINING_LANE1_SET + register in the DPCD. */ +#define XDP_RX_OVER_TRAINING_LANE2_SET 0x0B0 /**< Used to override the + TRAINING_LANE2_SET + register in the DPCD. */ +#define XDP_RX_OVER_TRAINING_LANE3_SET 0x0B4 /**< Used to override the + TRAINING_LANE3_SET + register in the DPCD. */ +#define XDP_RX_OVER_CTRL_DPCD 0x0B8 /**< Used to enable AXI/APB + write access to the DPCD + capability structure. */ +#define XDP_RX_OVER_DOWNSPREAD_CTRL 0x0BC /**< Used to override downspread + control in the DPCD. */ +#define XDP_RX_OVER_LINK_QUAL_LANE0_SET 0x0C0 /**< Used to override the + LINK_QUAL_LANE0_SET + register in the DPCD. */ +#define XDP_RX_OVER_LINK_QUAL_LANE1_SET 0x0C4 /**< Used to override the + LINK_QUAL_LANE1_SET + register in the DPCD. */ +#define XDP_RX_OVER_LINK_QUAL_LANE2_SET 0x0C8 /**< Used to override the + LINK_QUAL_LANE2_SET + register in the DPCD. */ +#define XDP_RX_OVER_LINK_QUAL_LANE3_SET 0x0CC /**< Used to override the + LINK_QUAL_LANE3_SET + register in the DPCD. */ +#define XDP_RX_MST_CAP 0x0D0 /**< Used to enable or disable + MST capability. */ +#define XDP_RX_SINK_COUNT 0x0D4 /**< The sink device count. */ +#define XDP_RX_GUID0 0x0E0 /**< Lower 4 bytes of the DPCD's + GUID field. */ +#define XDP_RX_GUID1 0x0E4 /**< Bytes 4 to 7 of the DPCD's + GUID field. */ +#define XDP_RX_GUID2 0x0E8 /**< Bytes 8 to 11 of the DPCD's + GUID field. */ +#define XDP_RX_GUID3 0x0EC /**< Upper 4 bytes of the DPCD's + GUID field. */ +#define XDP_RX_OVER_GUID 0x0F0 /**< Used to override the GUID + field in the DPCD with + what is stored in + XDP_RX_GUID[0-3]. */ +/* @} */ + +/** @name DPRX core registers: Core ID. + * @{ + */ +#define XDP_RX_VERSION 0x0F8 /**< Version and revision of the + DisplayPort core. */ +#define XDP_RX_CORE_ID 0x0FC /**< DisplayPort protocol + version and revision. */ +/* @} */ + +/** @name DPRX core registers: User video status. + * @{ + */ +#define XDP_RX_USER_FIFO_OVERFLOW 0x110 /**< Indicates an overflow in + user FIFO. */ +#define XDP_RX_USER_VSYNC_STATE 0x114 /**< Provides a mechanism for + the host processor to + monitor the state of the + video data path. */ +/* @} */ + +/** @name DPRX core registers: PHY configuration and status. + * @{ + */ +#define XDP_RX_PHY_CONFIG 0x200 /**< Transceiver PHY reset and + configuration. */ +#define XDP_RX_PHY_STATUS 0x208 /**< Current PHY status. */ +#define XDP_RX_PHY_POWER_DOWN 0x210 /**< Control PHY power down. */ +#define XDP_RX_MIN_VOLTAGE_SWING 0x214 /**< Specifies the minimum + voltage swing required + during training before + a link can be reliably + established and advanced + configuration for link + training. */ +#define XDP_RX_CDR_CONTROL_CONFIG 0x21C /**< Control the configuration + for clock and data + recovery. */ +#define XDP_RX_GT_DRP_COMMAND 0x2A0 /**< Provides access to the GT + DRP ports. */ +#define XDP_RX_GT_DRP_READ_DATA 0x2A4 /**< Provides access to GT DRP + read data. */ +#define XDP_RX_GT_DRP_CH_STATUS 0x2A8 /**< Provides access to GT DRP + channel status. */ +/* @} */ + +/** @name DPRX core registers: Audio. + * @{ + */ +#define XDP_RX_AUDIO_CONTROL 0x300 /**< Enables audio stream + packets in main link. */ +#define XDP_RX_AUDIO_INFO_DATA(NUM) (0x304 + 4 * (NUM - 1)) /**< Word + formatted as per CEA + 861-C info frame. */ +#define XDP_RX_AUDIO_MAUD 0x324 /**< M value of audio stream + as decoded from audio + time stamp packet. */ +#define XDP_RX_AUDIO_NAUD 0x328 /**< N value of audio stream + as decoded from audio + time stamp packet. */ +#define XDP_RX_AUDIO_STATUS 0x32C /**< Status of audio stream. */ +#define XDP_RX_AUDIO_EXT_DATA(NUM) (0x330 + 4 * (NUM - 1)) /**< Word + formatted as per + extension packet. */ +/* @} */ + +/** @name DPRX core registers: DPCD configuration space. + * @{ + */ +#define XDP_RX_DPCD_LINK_BW_SET 0x400 /**< Current link bandwidth + setting as exposed in + the RX DPCD. */ +#define XDP_RX_DPCD_LANE_COUNT_SET 0x404 /**< Current lane count + setting as exposed in + the RX DPCD. */ +#define XDP_RX_DPCD_ENHANCED_FRAME_EN 0x408 /**< Current setting for + enhanced framing symbol + mode as exposed in the + RX DPCD. */ +#define XDP_RX_DPCD_TRAINING_PATTERN_SET 0x40C /**< Current training pattern + setting as exposed in + the RX DPCD. */ +#define XDP_RX_DPCD_LINK_QUALITY_PATTERN_SET 0x410 /**< Current value of the + link quality pattern + field as exposed in the + RX DPCD. */ +#define XDP_RX_DPCD_RECOVERED_CLOCK_OUT_EN 0x414 /**< Value of the output clock + enable field as exposed + in the RX DPCD. */ +#define XDP_RX_DPCD_SCRAMBLING_DISABLE 0x418 /**< Value of the scrambling + disable field as exposed + in the RX DPCD. */ +#define XDP_RX_DPCD_SYMBOL_ERROR_COUNT_SELECT 0x41C /**< Current value of the + symbol error count + select field as exposed + in the RX DPCD. */ +#define XDP_RX_DPCD_TRAINING_LANE_0_SET 0x420 /**< The RX DPCD value used by + the TX during link + training to configure + the RX PHY lane 0. */ +#define XDP_RX_DPCD_TRAINING_LANE_1_SET 0x424 /**< The RX DPCD value used by + the TX during link + training to configure + the RX PHY lane 1. */ +#define XDP_RX_DPCD_TRAINING_LANE_2_SET 0x428 /**< The RX DPCD value used by + the TX during link + training to configure + the RX PHY lane 2. */ +#define XDP_RX_DPCD_TRAINING_LANE_3_SET 0x42C /**< The RX DPCD value Used by + the TX during link + training to configure + the RX PHY lane 3. */ +#define XDP_RX_DPCD_DOWNSPREAD_CONTROL 0x430 /**< The RX DPCD value that + is used by the TX to + inform the RX that + downspreading has been + enabled. */ +#define XDP_RX_DPCD_MAIN_LINK_CHANNEL_CODING_SET 0x434 /**< 8B/10B encoding + setting as exposed in + the RX DPCD. */ +#define XDP_RX_DPCD_SET_POWER_STATE 0x438 /**< Power state requested by + the TX as exposed in the + RX DPCD. */ +#define XDP_RX_DPCD_LANE01_STATUS 0x43C /**< Link training status for + lanes 0 and 1 as exposed + in the RX DPCD. */ +#define XDP_RX_DPCD_LANE23_STATUS 0x440 /**< Link training status for + lanes 2 and 3 as exposed + in the RX DPCD. */ +#define XDP_RX_DPCD_SOURCE_OUI_VALUE 0x444 /** The RX DPCD value used by + the TX to set the + organizationally unique + identifier (OUI). */ +#define XDP_RX_DPCD_SYM_ERR_CNT01 0x448 /** The symbol error counter + values for lanes 0 and 1 + as exposed in the RX + DPCD. */ +#define XDP_RX_DPCD_SYM_ERR_CNT23 0x44C /** The symbol error counter + values for lanes 2 and 3 + as exposed in the RX + DPCD. */ +/* @} */ + +/** @name DPRX core registers: Main stream attributes for SST / MST STREAM1. + * @{ + */ +#define XDP_RX_STREAM1_MSA_START 0x500 /**< Start of the MSA registers + for stream 1. */ +#define XDP_RX_MSA_HRES 0x500 /**< Number of active pixels per + line (the horizontal + resolution). */ +#define XDP_RX_MSA_HSPOL 0x504 /**< The horizontal sync + polarity. */ +#define XDP_RX_MSA_HSWIDTH 0x508 /**< Width of the horizontal + sync pulse. */ +#define XDP_RX_MSA_HSTART 0x50C /**< Number of clocks between + the leading edge of the + horizontal sync and the + start of active data. */ +#define XDP_RX_MSA_HTOTAL 0x510 /**< Total number of clocks in + the horizontal framing + period. */ +#define XDP_RX_MSA_VHEIGHT 0x514 /**< Number of active lines (the + vertical resolution). */ +#define XDP_RX_MSA_VSPOL 0x518 /**< The vertical sync + polarity. */ +#define XDP_RX_MSA_VSWIDTH 0x51C /**< Width of the vertical + sync pulse. */ +#define XDP_RX_MSA_VSTART 0x520 /**< Number of lines between the + leading edge of the + vertical sync and the + first line of active + data. */ +#define XDP_RX_MSA_VTOTAL 0x524 /**< Total number of lines in + the video frame. */ +#define XDP_RX_MSA_MISC0 0x528 /**< Miscellaneous stream + attributes. */ +#define XDP_RX_MSA_MISC1 0x52C /**< Miscellaneous stream + attributes. */ +#define XDP_RX_MSA_MVID 0x530 /**< Used to recover the video + clock from the link + clock. */ +#define XDP_RX_MSA_NVID 0x534 /**< Used to recover the video + clock from the link + clock. */ +#define XDP_RX_MSA_VBID 0x538 /**< The most recently received + VB-ID value. */ +/* @} */ + +/** @name DPRX core registers: Main stream attributes for MST STREAM2, 3, and 4. + * @{ + */ +#define XDP_RX_STREAM2_MSA_START 0x540 /**< Start of the MSA registers + for stream 2. */ +#define XDP_RX_STREAM2_MSA_START_OFFSET (XDP_RX_STREAM2_MSA_START - \ + XDP_RX_STREAM1_MSA_START) /**< The MSA registers for + stream 2 are at an + offset from the + corresponding registers + of stream 1. */ +#define XDP_RX_STREAM3_MSA_START 0x580 /**< Start of the MSA registers + for stream 3. */ +#define XDP_RX_STREAM3_MSA_START_OFFSET (XDP_RX_STREAM3_MSA_START - \ + XDP_RX_STREAM1_MSA_START) /**< The MSA registers for + stream 3 are at an + offset from the + corresponding registers + of stream 1. */ +#define XDP_RX_STREAM4_MSA_START 0x5C0 /**< Start of the MSA registers + for stream 4. */ +#define XDP_RX_STREAM4_MSA_START_OFFSET (XDP_RX_STREAM4_MSA_START - \ + XDP_RX_STREAM1_MSA_START) /**< The MSA registers for + stream 4 are at an + offset from the + corresponding registers + of stream 1. */ +/* @} */ + +/** @name DPRX core registers: MST field for sideband message buffers and the + * virtual channel payload table. + * @{ + */ +#define XDP_RX_DOWN_REQ 0xA00 /**< Down request buffer address + space. */ +#define XDP_RX_DOWN_REP 0xB00 /**< Down reply buffer address + space. */ +#define XDP_RX_VC_PAYLOAD_TABLE 0x800 /**< Virtual channel payload + table (0xFF bytes). */ +#define XDP_RX_VC_PAYLOAD_TABLE_ID_SLOT(SlotNum) \ + (XDP_RX_VC_PAYLOAD_TABLE + SlotNum) +/* @} */ + +/** @name DPRX core registers: Vendor specific DPCD. + * @{ + */ +#define XDP_RX_SOURCE_DEVICE_SPECIFIC_FIELD 0xE00 /**< User access to the source + specific field as + exposed in the RX + DPCD (0xFF bytes). */ +#define XDP_RX_SOURCE_DEVICE_SPECIFIC_FIELD_REG(RegNum) \ + (XDP_RX_SOURCE_DEVICE_SPECIFIC_FIELD + (4 * RegNum)) +#define XDP_RX_SINK_DEVICE_SPECIFIC_FIELD 0xF00 /**< User access to the sink + specific field as + exposed in the RX + DPCD (0xFF bytes). */ +#define XDP_RX_SINK_DEVICE_SPECIFIC_FIELD_REG(RegNum) \ + (XDP_RX_SINK_DEVICE_SPECIFIC_FIELD + (4 * RegNum)) +/* @} */ + +/******************************************************************************/ + +/** @name DPRX core masks, shifts, and register values. + * @{ + */ +/* 0x004: AUX_CLK_DIVIDER */ +#define XDP_RX_AUX_CLK_DIVIDER_VAL_MASK 0x00FF /**< Clock divider value. */ +#define XDP_RX_AUX_CLK_DIVIDER_AUX_SIG_WIDTH_FILT_MASK \ + 0xFF00 /**< AUX (noise) signal width + filter. */ +#define XDP_RX_AUX_CLK_DIVIDER_AUX_SIG_WIDTH_FILT_SHIFT \ + 8 /**< Shift bits for AUX signal + width filter. */ +/* 0x010: USER_PIXEL_WIDTH */ +#define XDP_RX_USER_PIXEL_WIDTH_1 0x1 /**< Single pixel wide + interface. */ +#define XDP_RX_USER_PIXEL_WIDTH_2 0x2 /**< Dual pixel output mode. */ +#define XDP_RX_USER_PIXEL_WIDTH_4 0x4 /**< Quad pixel output mode. */ +/* 0x014: INTERRUPT_MASK */ +#define XDP_RX_INTERRUPT_MASK_VM_CHANGE_MASK \ + 0x00001 /**< Mask the interrupt + assertion for a + resolution change, as + detected from the MSA + fields. */ +#define XDP_RX_INTERRUPT_MASK_POWER_STATE_MASK \ + 0x00002 /**< Mask the interrupt + assertion for a power + state change. */ +#define XDP_RX_INTERRUPT_MASK_NO_VIDEO_MASK \ + 0x00004 /**< Mask the interrupt + assertion for the + no-video condition being + detected after active + video received. */ +#define XDP_RX_INTERRUPT_MASK_VBLANK_MASK \ + 0x00008 /**< Mask the interrupt + assertion for the start + of the blanking + interval. */ +#define XDP_RX_INTERRUPT_MASK_TRAINING_LOST_MASK \ + 0x00010 /**< Mask the interrupt + assertion for training + loss on active lanes. */ +#define XDP_RX_INTERRUPT_MASK_VIDEO_MASK 0x00040 /**< Mask the interrupt + assertion for a valid + video frame being + detected on the main + link. Video interrupt is + set after a delay of 8 + video frames following a + valid scrambler reset + character. */ +#define XDP_RX_INTERRUPT_MASK_INFO_PKT_MASK \ + 0x00100 /**< Mask the interrupt + assertion for an audio + info packet being + received. */ +#define XDP_RX_INTERRUPT_MASK_EXT_PKT_MASK \ + 0x00200 /**< Mask the interrupt + assertion for an audio + extension packet being + received. */ +#define XDP_RX_INTERRUPT_MASK_VCP_ALLOC_MASK \ + 0x00400 /**< Mask the interrupt + assertion for a virtual + channel payload being + allocated. */ +#define XDP_RX_INTERRUPT_MASK_VCP_DEALLOC_MASK \ + 0x00800 /**< Mask the interrupt + assertion for a virtual + channel payload being + allocated. */ +#define XDP_RX_INTERRUPT_MASK_DOWN_REPLY_MASK \ + 0x01000 /**< Mask the interrupt + assertion for a + downstream reply being + ready. */ +#define XDP_RX_INTERRUPT_MASK_DOWN_REQUEST_MASK \ + 0x02000 /**< Mask the interrupt + assertion for a + downstream request being + ready. */ +#define XDP_RX_INTERRUPT_MASK_TRAINING_DONE_MASK \ + 0x04000 /**< Mask the interrupt + assertion for link + training completion. */ +#define XDP_RX_INTERRUPT_MASK_BW_CHANGE_MASK \ + 0x08000 /**< Mask the interrupt + assertion for a change + in bandwidth. */ +#define XDP_RX_INTERRUPT_MASK_TP1_MASK 0x10000 /**< Mask the interrupt + assertion for start of + training pattern 1. */ +#define XDP_RX_INTERRUPT_MASK_TP2_MASK 0x20000 /**< Mask the interrupt + assertion for start of + training pattern 2. */ +#define XDP_RX_INTERRUPT_MASK_TP3_MASK 0x40000 /**< Mask the interrupt + assertion for start of + training pattern 3. */ +#define XDP_RX_INTERRUPT_MASK_ALL_MASK 0x7FFFF /**< Mask all interrupts. */ +/* 0x018: MISC_CTRL */ +#define XDP_RX_MISC_CTRL_USE_FILT_MSA_MASK \ + 0x1 /**< When set, two matching + values must be detected + for each field of the + MSA values before the + associated register is + updated internally. */ +#define XDP_RX_MISC_CTRL_LONG_I2C_USE_DEFER_MASK \ + 0x2 /**< When set, the long I2C + write data transfwers + are responded to using + DEFER instead of partial + ACKs. */ +#define XDP_RX_MISC_CTRL_I2C_USE_AUX_DEFER_MASK \ + 0x4 /**< When set, I2C DEFERs will + be sent as AUX DEFERs to + the source device. */ +/* 0x01C: SOFT_RESET */ +#define XDP_RX_SOFT_RESET_VIDEO_MASK 0x01 /**< Reset the video logic. */ +#define XDP_RX_SOFT_RESET_AUX_MASK 0x80 /**< Reset the AUX logic. */ +/* 0x02C: HPD_INTERRUPT */ +#define XDP_RX_HPD_INTERRUPT_ASSERT_MASK \ + 0x00000001 /**< Instructs the RX core to + assert an interrupt to + the TX using the HPD + signal. */ +#define XDP_RX_HPD_INTERRUPT_LENGTH_US_MASK \ + 0xFFFF0000 /**< The length of the HPD pulse + to generate (in + microseconds). */ +#define XDP_RX_HPD_INTERRUPT_LENGTH_US_SHIFT 16 /**< Shift bits for the HPD + pulse length. */ +/* 0x040: INTERRUPT_CAUSE */ +#define XDP_RX_INTERRUPT_CAUSE_VM_CHANGE_MASK \ + XDP_RX_INTERRUPT_MASK_VM_CHANGE_MASK /**< Interrupt caused by a + resolution change, as + detected from the MSA + fields. */ +#define XDP_RX_INTERRUPT_CAUSE_POWER_STATE_MASK \ + XDP_RX_INTERRUPT_MASK_POWER_STATE_MASK /**< Interrupt caused by a + power state change. */ +#define XDP_RX_INTERRUPT_CAUSE_NO_VIDEO_MASK \ + XDP_RX_INTERRUPT_MASK_NO_VIDEO_MASK /**< Interrupt caused by the + no-video condition being + detected after active + video received. */ +#define XDP_RX_INTERRUPT_CAUSE_VBLANK_MASK \ + XDP_RX_INTERRUPT_MASK_VBLANK_MASK /**< Interrupt caused by the + start of the blanking + interval. */ +#define XDP_RX_INTERRUPT_CAUSE_TRAINING_LOST_MASK \ + XDP_RX_INTERRUPT_MASK_TRAINING_LOST_MASK /**< Interrupt caused by + training loss on active + lanes. */ +#define XDP_RX_INTERRUPT_CAUSE_VIDEO_MASK \ + XDP_RX_INTERRUPT_MASK_VIDEO_MASK /**< Interrupt caused by a + valid video frame being + detected on the main + link. Video interrupt is + set after a delay of 8 + video frames following a + valid scrambler reset + character. */ +#define XDP_RX_INTERRUPT_CAUSE_INFO_PKT_MASK \ + XDP_RX_INTERRUPT_MASK_INFO_PKT_MASK /**< Interrupt caused by an + audio info packet being + received. */ +#define XDP_RX_INTERRUPT_CAUSE_EXT_PKT_MASK \ + XDP_RX_INTERRUPT_MASK_EXT_PKT_MASK /**< Interrupt caused by an + audio extension packet + being received. */ +#define XDP_RX_INTERRUPT_CAUSE_VCP_ALLOC_MASK \ + XDP_RX_INTERRUPT_MASK_VCP_ALLOC_MASK /**< Interrupt caused by a + virtual channel payload + being allocated. */ +#define XDP_RX_INTERRUPT_CAUSE_VCP_DEALLOC_MASK \ + XDP_RX_INTERRUPT_MASK_VCP_DEALLOC_MASK /**< Interrupt caused by a + virtual channel payload + being allocated. */ +#define XDP_RX_INTERRUPT_CAUSE_DOWN_REPLY_MASK \ + XDP_RX_INTERRUPT_MASK_DOWN_REPLY_MASK /**< Interrupt caused by a + downstream reply being + ready. */ +#define XDP_RX_INTERRUPT_CAUSE_DOWN_REQUEST_MASK \ + XDP_RX_INTERRUPT_MASK_DOWN_REQUEST_MASK /**< Interrupt caused by a + downstream request being + ready. */ +#define XDP_RX_INTERRUPT_CAUSE_TRAINING_DONE_MASK \ + XDP_RX_INTERRUPT_MASK_TRAINING_DONE_MASK /**< Interrupt caused by link + training completion. */ +#define XDP_RX_INTERRUPT_CAUSE_BW_CHANGE_MASK \ + XDP_RX_INTERRUPT_MASK_BW_CHANGE_MASK /**< Interrupt caused by a + change in bandwidth. */ +#define XDP_RX_INTERRUPT_CAUSE_TP1_MASK \ + XDP_RX_INTERRUPT_MASK_TP1_MASK /**< Interrupt caused by the + start of training + pattern 1. */ +#define XDP_RX_INTERRUPT_CAUSE_TP2_MASK \ + XDP_RX_INTERRUPT_MASK_TP2_MASK /**< Interrupt caused by the + start of training + pattern 2. */ +#define XDP_RX_INTERRUPT_CAUSE_TP3_MASK \ + XDP_RX_INTERRUPT_MASK_TP3_MASK /**< Interrupt caused by the + start of training + pattern 3. */ +/* 0x044: INTERRUPT_MASK_1 */ +#define XDP_RX_INTERRUPT_MASK_1_EXT_PKT_STREAM234_MASK(Stream) \ + (0x00001 << ((Stream - 2) * 6)) /**< Mask the interrupt + assertion for an audio + extension packet being + received for stream + 2, 3, or 4. */ +#define XDP_RX_INTERRUPT_MASK_1_INFO_PKT_STREAM234_MASK(Stream) \ + (0x00002 << ((Stream - 2) * 6)) /**< Mask the interrupt + assertion for an audio + info packet being + received for stream + 2, 3, or 4. */ +#define XDP_RX_INTERRUPT_MASK_1_VM_CHANGE_STREAM234_MASK(Stream) \ + (0x00004 << ((Stream - 2) * 6)) /**< Mask the interrupt + assertion for a + resolution change, as + detected from the MSA + fields for stream 2, 3, + or 4. */ +#define XDP_RX_INTERRUPT_MASK_1_NO_VIDEO_STREAM234_MASK(Stream) \ + (0x00008 << ((Stream - 2) * 6)) /**< Mask the interrupt + assertion for the + no-video condition being + detected after active + video received for + stream 2, 3, or 4. */ +#define XDP_RX_INTERRUPT_MASK_1_VBLANK_STREAM234_MASK(Stream) \ + (0x00010 << ((Stream - 2) * 6)) /**< Mask the interrupt + assertion for the start + of the blanking interval + for stream 2, 3, or + 4. */ +#define XDP_RX_INTERRUPT_MASK_1_VIDEO_STREAM234_MASK(Stream) \ + (0x00020 << ((Stream - 2) * 6)) /**< Mask the interrupt + assertion for a valid + video frame being + detected on the main + link for stream 2, 3, + or 4. */ +/* 0x048: INTERRUPT_CAUSE_1 */ +#define XDP_RX_INTERRUPT_CAUSE_1_EXT_PKT_STREAM234_MASK(Stream) \ + XDP_RX_INTERRUPT_CAUSE_1_EXT_PKT_STREAM234_MASK(Stream) /**< Interrupt + caused by an audio + extension packet being + received for stream 2, + 3, or 4. */ +#define XDP_RX_INTERRUPT_CAUSE_1_INFO_PKT_STREAM234_MASK(Stream) \ + XDP_RX_INTERRUPT_CAUSE_1_INFO_PKT_STREAM234_MASK(Stream) /**< Interrupt + caused by an audio info + packet being received + for stream 2, 3, or + 4. */ +#define XDP_RX_INTERRUPT_CAUSE_1_VM_CHANGE_STREAM234_MASK(Stream) \ + XDP_RX_INTERRUPT_CAUSE_1_VM_CHANGE_STREAM234_MASK(Stream) /**< Interrupt + caused by a resolution + change, as detected from + the MSA fields for + stream 2, 3, or 4. */ +#define XDP_RX_INTERRUPT_CAUSE_1_NO_VIDEO_STREAM234_MASK(Stream) \ + XDP_RX_INTERRUPT_CAUSE_1_NO_VIDEO_STREAM234_MASK(Stream) /**< Interrupt + caused by the no-video + condition being detected + after active video + received for stream 2, + 3, or 4. */ +#define XDP_RX_INTERRUPT_CAUSE_1_VBLANK_STREAM234_MASK(Stream) \ + XDP_RX_INTERRUPT_CAUSE_1_VBLANK_STREAM234_MASK(Stream) /**< Interrupt + caused by the start of + the blanking interval + for stream 2, 3, or + 4. */ +#define XDP_RX_INTERRUPT_CAUSE_1_VIDEO_STREAM234_MASK(Stream) \ + XDP_RX_INTERRUPT_CAUSE_1_VIDEO_STREAM234_MASK(Stream) /**< Interrupt + caused by a valid video + frame being detected on + the main link for + stream 2, 3, or 4. */ +/* 0x050: HSYNC_WIDTH */ +#define XDP_RX_HSYNC_WIDTH_PULSE_WIDTH_MASK \ + 0x00FF /**< Specifies the number of + clock cycles the + horizontal sync pulse is + asserted. */ +#define XDP_RX_HSYNC_WIDTH_FRONT_PORCH_MASK \ + 0xFF00 /**< Defines the number of video + clock cycles to place + between the last pixel + of active data and the + start of the horizontal + sync pulse (the front + porch). */ +#define XDP_RX_HSYNC_WIDTH_FRONT_PORCH_SHIFT 8 /**< Shift bits for the front + porch. */ +/* 0x090: DEVICE_SERVICE_IRQ */ +#define XDP_RX_DEVICE_SERVICE_IRQ_NEW_REMOTE_CMD_MASK \ + 0x01 /**< Indicates that a new + command is present in + the REMOTE_CMD + register. */ +#define XDP_RX_DEVICE_SERVICE_IRQ_SINK_SPECIFIC_IRQ_MASK \ + 0x02 /**< Reflects the + SINK_SPECIFIC_IRQ + state. */ +#define XDP_RX_DEVICE_SERVICE_IRQ_NEW_DOWN_REPLY_MASK \ + 0x10 /**< Indicates a new DOWN_REPLY + buffer message is + ready. */ +/* 0x09C: OVER_LINK_BW_SET */ +#define XDP_RX_OVER_LINK_BW_SET_162GBPS 0x06 /**< 1.62 Gbps link rate. */ +#define XDP_RX_OVER_LINK_BW_SET_270GBPS 0x0A /**< 2.70 Gbps link rate. */ +#define XDP_RX_OVER_LINK_BW_SET_540GBPS 0x14 /**< 5.40 Gbps link rate. */ + +/* 0x0A0: OVER_LANE_COUNT_SET */ +#define XDP_RX_OVER_LANE_COUNT_SET_MASK 0x1F /**< The lane count override + value. */ +#define XDP_RX_OVER_LANE_COUNT_SET_1 0x1 /**< Lane count of 1. */ +#define XDP_RX_OVER_LANE_COUNT_SET_2 0x2 /**< Lane count of 2. */ +#define XDP_RX_OVER_LANE_COUNT_SET_4 0x4 /**< Lane count of 4. */ +#define XDP_RX_OVER_LANE_COUNT_SET_TPS3_SUPPORTED_MASK \ + 0x20 /**< Capability override for + training pattern 3. */ +#define XDP_RX_OVER_LANE_COUNT_SET_ENHANCED_FRAME_CAP_MASK \ + 0x80 /**< Capability override for + enhanced framing. */ +/* 0x0A4: OVER_TP_SET */ +#define XDP_RX_OVER_TP_SET_TP_SELECT_MASK \ + 0x0003 /**< Training pattern select + override. */ +#define XDP_RX_OVER_TP_SET_LQP_SET_MASK \ + 0x000C /**< Link quality pattern set + override. */ +#define XDP_RX_OVER_TP_SET_LQP_SET_SHIFT 2 /**< Shift bits for link quality + pattern set override. */ +#define XDP_RX_OVER_TP_SET_REC_CLK_OUT_EN_MASK \ + 0x0010 /**< Recovered clock output + enable override. */ +#define XDP_RX_OVER_TP_SET_SCRAMBLER_DISABLE_MASK \ + 0x0020 /**< Scrambling disable + override. */ +#define XDP_RX_OVER_TP_SET_SYMBOL_ERROR_COUNT_SEL_MASK \ + 0x00C0 /**< Symbol error count + override. */ +#define XDP_RX_OVER_TP_SET_SYMBOL_ERROR_COUNT_SEL_SHIFT \ + 6 /**< Shift bits for symbol error + count override. */ +#define XDP_RX_OVER_TP_SET_TRAINING_AUX_RD_INTERVAL_MASK \ + 0xFF00 /**< Training AUX read interval + override. */ +#define XDP_RX_OVER_TP_SET_TRAINING_AUX_RD_INTERVAL_SHIFT \ + 8 /**< Shift bits for training AUX + read interval + override. */ +/* 0x0A8, 0x0AC, 0x0B0, 0x0B4: OVER_TRAINING_LANEX_SET */ +#define XDP_RX_OVER_TRAINING_LANEX_SET_VS_SET_MASK \ + 0x03 /**< Voltage swing set + override. */ +#define XDP_RX_OVER_TRAINING_LANEX_SET_MAX_VS_MASK \ + 0x04 /**< Maximum voltage swing + override. */ +#define XDP_RX_OVER_TRAINING_LANEX_SET_PE_SET_MASK \ + 0x18 /**< Pre-emphasis set + override. */ +#define XDP_RX_OVER_TRAINING_LANEX_SET_PE_SET_SHIFT \ + 3 /**< Shift bits for pre-emphasis + set override. */ +#define XDP_RX_OVER_TRAINING_LANEX_SET_MAX_PE_MASK \ + 0x20 /**< Maximum pre-emphasis + override. */ +/* 0x0F8 : VERSION_REGISTER */ +#define XDP_RX_VERSION_INTER_REV_MASK \ + 0x0000000F /**< Internal revision. */ +#define XDP_RX_VERSION_CORE_PATCH_MASK \ + 0x00000030 /**< Core patch details. */ +#define XDP_RX_VERSION_CORE_PATCH_SHIFT \ + 8 /**< Shift bits for core patch + details. */ +#define XDP_RX_VERSION_CORE_VER_REV_MASK \ + 0x000000C0 /**< Core version revision. */ +#define XDP_RX_VERSION_CORE_VER_REV_SHIFT \ + 12 /**< Shift bits for core version + revision. */ +#define XDP_RX_VERSION_CORE_VER_MNR_MASK \ + 0x00000F00 /**< Core minor version. */ +#define XDP_RX_VERSION_CORE_VER_MNR_SHIFT \ + 16 /**< Shift bits for core minor + version. */ +#define XDP_RX_VERSION_CORE_VER_MJR_MASK \ + 0x0000F000 /**< Core major version. */ +#define XDP_RX_VERSION_CORE_VER_MJR_SHIFT \ + 24 /**< Shift bits for core major + version. */ +/* 0x0FC : CORE_ID */ +#define XDP_RX_CORE_ID_TYPE_MASK 0x0000000F /**< Core type. */ +#define XDP_RX_CORE_ID_TYPE_TX 0x0 /**< Core is a transmitter. */ +#define XDP_RX_CORE_ID_TYPE_RX 0x1 /**< Core is a receiver. */ +#define XDP_RX_CORE_ID_DP_REV_MASK \ + 0x000000F0 /**< DisplayPort protocol + revision. */ +#define XDP_RX_CORE_ID_DP_REV_SHIFT \ + 8 /**< Shift bits for DisplayPort + protocol revision. */ +#define XDP_RX_CORE_ID_DP_MNR_VER_MASK \ + 0x00000F00 /**< DisplayPort protocol minor + version. */ +#define XDP_RX_CORE_ID_DP_MNR_VER_SHIFT \ + 16 /**< Shift bits for DisplayPort + protocol major + version. */ +#define XDP_RX_CORE_ID_DP_MJR_VER_MASK \ + 0x0000F000 /**< DisplayPort protocol major + version. */ +#define XDP_RX_CORE_ID_DP_MJR_VER_SHIFT \ + 24 /**< Shift bits for DisplayPort + protocol major + version. */ +/* 0x110: USER_FIFO_OVERFLOW */ +#define XDP_RX_USER_FIFO_OVERFLOW_FLAG_STREAMX_MASK(Stream) \ + (Stream) /**< Indicates that the internal + FIFO has detected on + overflow condition for + the specified stream. */ +#define XDP_RX_USER_FIFO_OVERFLOW_VID_UNPACK_STREAMX_MASK(Stream) \ + (Stream << 4) /**< Indicates that the video + unpack FIFO has + overflown for the + specified stream. */ +#define XDP_RX_USER_FIFO_OVERFLOW_VID_TIMING_STREAMX_MASK(Stream) \ + (Stream << 8) /**< Indicates that the video + timing FIFO has + overflown for the + specified stream. */ +/* 0x114: USER_VSYNC_STATE */ +#define XDP_RX_USER_VSYNC_STATE_STREAMX_MASK(Stream) \ + (Stream) /**< The state of the vertical + sync pulse for the + specified stream. */ +/* 0x200: PHY_CONFIG */ +#define XDP_RX_PHY_CONFIG_PHY_RESET_ENABLE_MASK \ + 0x00000000 /**< Release reset. */ +#define XDP_RX_PHY_CONFIG_GTPLL_RESET_MASK \ + 0x00000001 /**< Hold the GTPLL in reset. */ +#define XDP_RX_PHY_CONFIG_GTRX_RESET_MASK \ + 0x00000002 /**< Hold GTRXRESET in reset. */ +#define XDP_RX_PHY_CONFIG_RX_PHY_PMA_RESET_MASK \ + 0x00000100 /**< Hold RX_PHY_PMA reset. */ +#define XDP_RX_PHY_CONFIG_RX_PHY_PCS_RESET_MASK \ + 0x00000200 /**< Hold RX_PHY_PCS reset. */ +#define XDP_RX_PHY_CONFIG_RX_PHY_BUF_RESET_MASK \ + 0x00000400 /**< Hold RX_PHY_BUF reset. */ +#define XDP_RX_PHY_CONFIG_RX_PHY_DFE_LPM_RESET_MASK \ + 0x00000800 /**< Hold RX_PHY_DFE_LPM + reset. */ +#define XDP_RX_PHY_CONFIG_RX_PHY_POLARITY_MASK \ + 0x00001000 /**< Set RX_PHY_POLARITY. */ +#define XDP_RX_PHY_CONFIG_RX_PHY_LOOPBACK_MASK \ + 0x0000E000 /**< Set RX_PHY_LOOPBACK. */ +#define XDP_RX_PHY_CONFIG_RX_PHY_EYESCANRESET_MASK \ + 0x00010000 /**< Set RX_PHY_EYESCANRESET. */ +#define XDP_RX_PHY_CONFIG_RX_PHY_EYESCANTRIGGER_MASK \ + 0x00020000 /**< Set RX_PHY_ + EYESCANTRIGGER. */ +#define XDP_RX_PHY_CONFIG_RX_PHY_PRBSCNTRESET_MASK \ + 0x00040000 /**< Set RX_PHY_PRBSCNTRESET. */ +#define XDP_RX_PHY_CONFIG_RX_PHY_RXLPMHFHOLD_MASK \ + 0x00080000 /**< Set RX_PHY_RXLPMHFHOLD. */ +#define XDP_RX_PHY_CONFIG_RX_PHY_RXLPMLFHOLD_MASK \ + 0x00100000 /**< Set RX_PHY_RXLPMLFHOLD. */ +#define XDP_RX_PHY_CONFIG_RX_PHY_RXLPMHFOVERDEN_MASK \ + 0x00200000 /**< Set RX_PHY_ + RXLPMHFOVERDEN. */ +#define XDP_RX_PHY_CONFIG_RX_PHY_CDRHOLD_MASK \ + 0x00400000 /**< Set RX_PHY_CDRHOLD. */ +#define XDP_RX_PHY_CONFIG_RESET_AT_TRAIN_ITER_MASK \ + 0x00800000 /**< Issue reset at every + training iteration. */ +#define XDP_RX_PHY_CONFIG_RESET_AT_LINK_RATE_CHANGE_MASK \ + 0x01000000 /**< Issue reset at every link + rate change. */ +#define XDP_RX_PHY_CONFIG_RESET_AT_TP1_START_MASK \ + 0x02000000 /**< Issue reset at start of + training pattern 1. */ +#define XDP_RX_PHY_CONFIG_EN_CFG_RX_PHY_POLARITY_MASK \ + 0x04000000 /**< Enable the individual lane + polarity. */ +#define XDP_RX_PHY_CONFIG_RX_PHY_POLARITY_LANE0_MASK \ + 0x08000000 /**< Configure RX_PHY_POLARITY + for lane 0. */ +#define XDP_RX_PHY_CONFIG_RX_PHY_POLARITY_LANE1_MASK \ + 0x10000000 /**< Configure RX_PHY_POLARITY + for lane 1. */ +#define XDP_RX_PHY_CONFIG_RX_PHY_POLARITY_LANE2_MASK \ + 0x20000000 /**< Configure RX_PHY_POLARITY + for lane 2. */ +#define XDP_RX_PHY_CONFIG_RX_PHY_POLARITY_LANE3_MASK \ + 0x40000000 /**< Configure RX_PHY_POLARITY + for lane 3. */ +#define XDP_RX_PHY_CONFIG_GT_ALL_RESET_MASK \ + 0x00000003 /**< Rest GT and PHY. */ +/* 0x208: PHY_STATUS */ +#define XDP_RX_PHY_STATUS_RESET_LANE_0_1_DONE_MASK \ + 0x00000003 /**< Reset done for lanes + 0 and 1. */ +#define XDP_RX_PHY_STATUS_RESET_LANE_2_3_DONE_MASK \ + 0x0000000C /**< Reset done for lanes + 2 and 3. */ +#define XDP_RX_PHY_STATUS_RESET_LANE_2_3_DONE_SHIFT \ + 2 /**< Shift bits for reset done + for lanes 2 and 3. */ +#define XDP_RX_PHY_STATUS_PLL_LANE0_1_LOCK_MASK \ + 0x00000010 /**< PLL locked for lanes + 0 and 1. */ +#define XDP_RX_PHY_STATUS_PLL_LANE2_3_LOCK_MASK \ + 0x00000020 /**< PLL locked for lanes + 2 and 3. */ +#define XDP_RX_PHY_STATUS_PLL_FABRIC_LOCK_MASK \ + 0x00000040 /**< FPGA fabric clock PLL + locked. */ +#define XDP_RX_PHY_STATUS_RX_CLK_LOCK_MASK \ + 0x00000080 /**< Receiver clock locked. */ +#define XDP_RX_PHY_STATUS_PRBSERR_LANE_0_MASK \ + 0x00000100 /**< PRBS error on lane 0. */ +#define XDP_RX_PHY_STATUS_PRBSERR_LANE_1_MASK \ + 0x00000200 /**< PRBS error on lane 1. */ +#define XDP_RX_PHY_STATUS_PRBSERR_LANE_2_MASK \ + 0x00000400 /**< PRBS error on lane 2. */ +#define XDP_RX_PHY_STATUS_PRBSERR_LANE_3_MASK \ + 0x00000800 /**< PRBS error on lane 3. */ +#define XDP_RX_PHY_STATUS_RX_VLOW_LANE_0_MASK \ + 0x00001000 /**< RX voltage low on lane + 0. */ +#define XDP_RX_PHY_STATUS_RX_VLOW_LANE_1_MASK \ + 0x00002000 /**< RX voltage low on lane + 1. */ +#define XDP_RX_PHY_STATUS_RX_VLOW_LANE_2_MASK \ + 0x00004000 /**< RX voltage low on lane + 2. */ +#define XDP_RX_PHY_STATUS_RX_VLOW_LANE_3_MASK \ + 0x00008000 /**< RX voltage low on lane + 3. */ +#define XDP_RX_PHY_STATUS_LANE_ALIGN_LANE_0_MASK \ + 0x00010000 /**< Lane aligment status for + lane 0. */ +#define XDP_RX_PHY_STATUS_LANE_ALIGN_LANE_1_MASK \ + 0x00020000 /**< Lane aligment status for + lane 1. */ +#define XDP_RX_PHY_STATUS_LANE_ALIGN_LANE_2_MASK \ + 0x00040000 /**< Lane aligment status for + lane 2. */ +#define XDP_RX_PHY_STATUS_LANE_ALIGN_LANE_3_MASK \ + 0x00080000 /**< Lane aligment status for + lane 3. */ +#define XDP_RX_PHY_STATUS_SYM_LOCK_LANE_0_MASK \ + 0x00100000 /**< Symbol lock status for + lane 0. */ +#define XDP_RX_PHY_STATUS_SYM_LOCK_LANE_1_MASK \ + 0x00200000 /**< Symbol lock status for + lane 1. */ +#define XDP_RX_PHY_STATUS_SYM_LOCK_LANE_2_MASK \ + 0x00400000 /**< Symbol lock status for + lane 2. */ +#define XDP_RX_PHY_STATUS_SYM_LOCK_LANE_3_MASK \ + 0x00800000 /**< Symbol lock status for + lane 3. */ +#define XDP_RX_PHY_STATUS_RX_BUFFER_STATUS_LANE_0_MASK \ + 0x03000000 /**< RX buffer status lane 0. */ +#define XDP_RX_PHY_STATUS_RX_BUFFER_STATUS_LANE_0_SHIFT \ + 24 /**< Shift bits for RX buffer + status lane 0. */ +#define XDP_RX_PHY_STATUS_RX_BUFFER_STATUS_LANE_1_MASK \ + 0x0C000000 /**< RX buffer status lane 1. */ +#define XDP_RX_PHY_STATUS_RX_BUFFER_STATUE_LANE_1_SHIFT \ + 26 /**< Shift bits for RX buffer + status lane 1. */ +#define XDP_RX_PHY_STATUS_RX_BUFFER_STATUS_LANE_2_MASK \ + 0x30000000 /**< RX buffer status lane 2. */ +#define XDP_RX_PHY_STATUS_RX_BUFFER_STATUS_LANE_2_SHIFT \ + 28 /**< Shift bits for RX buffer + status lane 2. */ +#define XDP_RX_PHY_STATUS_RX_BUFFER_STATUS_LANE_3_MASK \ + 0xC0000000 /**< RX buffer status lane 3. */ +#define XDP_RX_PHY_STATUS_RX_BUFFER_STATUS_LANE_3_SHIFT \ + 30 /**< Shift bits for RX buffer + status lane 3. */ +#define XDP_RX_PHY_STATUS_LANES_0_1_READY_MASK \ + 0x00000013 /**< Lanes 0 and 1 are ready. */ +#define XDP_RX_PHY_STATUS_ALL_LANES_READY_MASK \ + 0x0000003F /**< All lanes are ready. */ +/* 0x210: PHY_POWER_DOWN */ +#define XDP_RX_PHY_POWER_DOWN_LANE_0_MASK 0x1 /**< Power down the PHY for lane + 0. */ +#define XDP_RX_PHY_POWER_DOWN_LANE_1_MASK 0x2 /**< Power down the PHY for lane + 1. */ +#define XDP_RX_PHY_POWER_DOWN_LANE_2_MASK 0x4 /**< Power down the PHY for lane + 2. */ +#define XDP_RX_PHY_POWER_DOWN_LANE_3_MASK 0x8 /**< Power down the PHY for lane + 3. */ +/* @} */ + +/******************************************************************************/ + +/******************************************************************************/ +/** + * Address mapping for the DisplayPort Configuration Data (DPCD) of the + * downstream device. + * +*******************************************************************************/ +/** @name DisplayPort Configuration Data: Receiver capability field. + * @{ + */ +#define XDP_DPCD_REV 0x00000 +#define XDP_DPCD_MAX_LINK_RATE 0x00001 +#define XDP_DPCD_MAX_LANE_COUNT 0x00002 +#define XDP_DPCD_MAX_DOWNSPREAD 0x00003 +#define XDP_DPCD_NORP_PWR_V_CAP 0x00004 +#define XDP_DPCD_DOWNSP_PRESENT 0x00005 +#define XDP_DPCD_ML_CH_CODING_CAP 0x00006 +#define XDP_DPCD_DOWNSP_COUNT_MSA_OUI 0x00007 +#define XDP_DPCD_RX_PORT0_CAP_0 0x00008 +#define XDP_DPCD_RX_PORT0_CAP_1 0x00009 +#define XDP_DPCD_RX_PORT1_CAP_0 0x0000A +#define XDP_DPCD_RX_PORT1_CAP_1 0x0000B +#define XDP_DPCD_I2C_SPEED_CTL_CAP 0x0000C +#define XDP_DPCD_EDP_CFG_CAP 0x0000D +#define XDP_DPCD_TRAIN_AUX_RD_INTERVAL 0x0000E +#define XDP_DPCD_ADAPTER_CAP 0x0000F +#define XDP_DPCD_FAUX_CAP 0x00020 +#define XDP_DPCD_MSTM_CAP 0x00021 +#define XDP_DPCD_NUM_AUDIO_EPS 0x00022 +#define XDP_DPCD_AV_GRANULARITY 0x00023 +#define XDP_DPCD_AUD_DEC_LAT_7_0 0x00024 +#define XDP_DPCD_AUD_DEC_LAT_15_8 0x00025 +#define XDP_DPCD_AUD_PP_LAT_7_0 0x00026 +#define XDP_DPCD_AUD_PP_LAT_15_8 0x00027 +#define XDP_DPCD_VID_INTER_LAT 0x00028 +#define XDP_DPCD_VID_PROG_LAT 0x00029 +#define XDP_DPCD_REP_LAT 0x0002A +#define XDP_DPCD_AUD_DEL_INS_7_0 0x0002B +#define XDP_DPCD_AUD_DEL_INS_15_8 0x0002C +#define XDP_DPCD_AUD_DEL_INS_23_16 0x0002D +#define XDP_DPCD_GUID 0x00030 +#define XDP_DPCD_RX_GTC_VALUE_7_0 0x00054 +#define XDP_DPCD_RX_GTC_VALUE_15_8 0x00055 +#define XDP_DPCD_RX_GTC_VALUE_23_16 0x00056 +#define XDP_DPCD_RX_GTC_VALUE_31_24 0x00057 +#define XDP_DPCD_RX_GTC_MSTR_REQ 0x00058 +#define XDP_DPCD_RX_GTC_FREQ_LOCK_DONE 0x00059 +#define XDP_DPCD_DOWNSP_0_CAP 0x00080 +#define XDP_DPCD_DOWNSP_1_CAP 0x00081 +#define XDP_DPCD_DOWNSP_2_CAP 0x00082 +#define XDP_DPCD_DOWNSP_3_CAP 0x00083 +#define XDP_DPCD_DOWNSP_0_DET_CAP 0x00080 +#define XDP_DPCD_DOWNSP_1_DET_CAP 0x00084 +#define XDP_DPCD_DOWNSP_2_DET_CAP 0x00088 +#define XDP_DPCD_DOWNSP_3_DET_CAP 0x0008C +/* @} */ + +/** @name DisplayPort Configuration Data: Link configuration field. + * @{ + */ +#define XDP_DPCD_LINK_BW_SET 0x00100 +#define XDP_DPCD_LANE_COUNT_SET 0x00101 +#define XDP_DPCD_TP_SET 0x00102 +#define XDP_DPCD_TRAINING_LANE0_SET 0x00103 +#define XDP_DPCD_TRAINING_LANE1_SET 0x00104 +#define XDP_DPCD_TRAINING_LANE2_SET 0x00105 +#define XDP_DPCD_TRAINING_LANE3_SET 0x00106 +#define XDP_DPCD_DOWNSPREAD_CTRL 0x00107 +#define XDP_DPCD_ML_CH_CODING_SET 0x00108 +#define XDP_DPCD_I2C_SPEED_CTL_SET 0x00109 +#define XDP_DPCD_EDP_CFG_SET 0x0010A +#define XDP_DPCD_LINK_QUAL_LANE0_SET 0x0010B +#define XDP_DPCD_LINK_QUAL_LANE1_SET 0x0010C +#define XDP_DPCD_LINK_QUAL_LANE2_SET 0x0010D +#define XDP_DPCD_LINK_QUAL_LANE3_SET 0x0010E +#define XDP_DPCD_TRAINING_LANE0_1_SET2 0x0010F +#define XDP_DPCD_TRAINING_LANE2_3_SET2 0x00110 +#define XDP_DPCD_MSTM_CTRL 0x00111 +#define XDP_DPCD_AUDIO_DELAY_7_0 0x00112 +#define XDP_DPCD_AUDIO_DELAY_15_8 0x00113 +#define XDP_DPCD_AUDIO_DELAY_23_6 0x00114 +#define XDP_DPCD_UPSTREAM_DEVICE_DP_PWR_NEED 0x00118 +#define XDP_DPCD_FAUX_MODE_CTRL 0x00120 +#define XDP_DPCD_FAUX_FORWARD_CH_DRIVE_SET 0x00121 +#define XDP_DPCD_BACK_CH_STATUS 0x00122 +#define XDP_DPCD_FAUX_BACK_CH_SYMBOL_ERROR_COUNT 0x00123 +#define XDP_DPCD_FAUX_BACK_CH_TRAINING_PATTERN_TIME 0x00125 +#define XDP_DPCD_TX_GTC_VALUE_7_0 0x00154 +#define XDP_DPCD_TX_GTC_VALUE_15_8 0x00155 +#define XDP_DPCD_TX_GTC_VALUE_23_16 0x00156 +#define XDP_DPCD_TX_GTC_VALUE_31_24 0x00157 +#define XDP_DPCD_RX_GTC_VALUE_PHASE_SKEW_EN 0x00158 +#define XDP_DPCD_TX_GTC_FREQ_LOCK_DONE 0x00159 +#define XDP_DPCD_ADAPTER_CTRL 0x001A0 +#define XDP_DPCD_BRANCH_DEVICE_CTRL 0x001A1 +#define XDP_DPCD_PAYLOAD_ALLOCATE_SET 0x001C0 +#define XDP_DPCD_PAYLOAD_ALLOCATE_START_TIME_SLOT 0x001C1 +#define XDP_DPCD_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT 0x001C2 +/* @} */ + +/** @name DisplayPort Configuration Data: Link/sink status field. + * @{ + */ +#define XDP_DPCD_SINK_COUNT 0x00200 +#define XDP_DPCD_DEVICE_SERVICE_IRQ 0x00201 +#define XDP_DPCD_STATUS_LANE_0_1 0x00202 +#define XDP_DPCD_STATUS_LANE_2_3 0x00203 +#define XDP_DPCD_LANE_ALIGN_STATUS_UPDATED 0x00204 +#define XDP_DPCD_SINK_STATUS 0x00205 +#define XDP_DPCD_ADJ_REQ_LANE_0_1 0x00206 +#define XDP_DPCD_ADJ_REQ_LANE_2_3 0x00207 +#define XDP_DPCD_TRAINING_SCORE_LANE_0 0x00208 +#define XDP_DPCD_TRAINING_SCORE_LANE_1 0x00209 +#define XDP_DPCD_TRAINING_SCORE_LANE_2 0x0020A +#define XDP_DPCD_TRAINING_SCORE_LANE_3 0x0020B +#define XDP_DPCD_ADJ_REQ_PC2 0x0020C +#define XDP_DPCD_FAUX_FORWARD_CH_SYMBOL_ERROR_COUNT 0x0020D +#define XDP_DPCD_SYMBOL_ERROR_COUNT_LANE_0 0x00210 +#define XDP_DPCD_SYMBOL_ERROR_COUNT_LANE_1 0x00212 +#define XDP_DPCD_SYMBOL_ERROR_COUNT_LANE_2 0x00214 +#define XDP_DPCD_SYMBOL_ERROR_COUNT_LANE_3 0x00216 +/* @} */ + +/** @name DisplayPort Configuration Data: Automated testing sub-field. + * @{ + */ +#define XDP_DPCD_FAUX_FORWARD_CH_STATUS 0x00280 +#define XDP_DPCD_FAUX_BACK_CH_DRIVE_SET 0x00281 +#define XDP_DPCD_FAUX_BACK_CH_SYM_ERR_COUNT_CTRL 0x00282 +#define XDP_DPCD_PAYLOAD_TABLE_UPDATE_STATUS 0x002C0 +#define XDP_DPCD_VC_PAYLOAD_ID_SLOT(SlotNum) \ + (XDP_DPCD_PAYLOAD_TABLE_UPDATE_STATUS + SlotNum) +/* @} */ + +/** @name DisplayPort Configuration Data: Sink control field. + * @{ + */ +#define XDP_DPCD_SET_POWER_DP_PWR_VOLTAGE 0x00600 +/* @} */ + +/** @name DisplayPort Configuration Data: Sideband message buffers. + * @{ + */ +#define XDP_DPCD_DOWN_REQ 0x01000 +#define XDP_DPCD_UP_REP 0x01200 +#define XDP_DPCD_DOWN_REP 0x01400 +#define XDP_DPCD_UP_REQ 0x01600 +/* @} */ + +/** @name DisplayPort Configuration Data: Event status indicator field. + * @{ + */ +#define XDP_DPCD_SINK_COUNT_ESI 0x02002 +#define XDP_DPCD_SINK_DEVICE_SERVICE_IRQ_VECTOR_ESI0 0x02003 +#define XDP_DPCD_SINK_DEVICE_SERVICE_IRQ_VECTOR_ESI1 0x02004 +#define XDP_DPCD_SINK_LINK_SERVICE_IRQ_VECTOR_ESI0 0x02005 +#define XDP_DPCD_SINK_LANE0_1_STATUS 0x0200C +#define XDP_DPCD_SINK_LANE2_3_STATUS 0x0200D +#define XDP_DPCD_SINK_ALIGN_STATUS_UPDATED_ESI 0x0200E +#define XDP_DPCD_SINK_STATUS_ESI 0x0200F +/* @} */ + +/** @name DisplayPort Configuration Data: Field addresses and sizes. + * @{ + */ +#define XDP_DPCD_RECEIVER_CAP_FIELD_START XDP_DPCD_REV +#define XDP_DPCD_RECEIVER_CAP_FIELD_SIZE 0x100 +#define XDP_DPCD_LINK_CFG_FIELD_START XDP_DPCD_LINK_BW_SET +#define XDP_DPCD_LINK_CFG_FIELD_SIZE 0x100 +#define XDP_DPCD_LINK_SINK_STATUS_FIELD_START XDP_DPCD_SINK_COUNT +#define XDP_DPCD_LINK_SINK_STATUS_FIELD_SIZE 0x17 +/* @} */ + +/******************************************************************************/ + +/** @name DisplayPort Configuration Data: Receiver capability field masks, + * shifts, and register values. + * @{ + */ +/* 0x00000: DPCD_REV */ +#define XDP_DPCD_REV_MNR_MASK 0x0F +#define XDP_DPCD_REV_MJR_MASK 0xF0 +#define XDP_DPCD_REV_MJR_SHIFT 4 +/* 0x00001: MAX_LINK_RATE */ +#define XDP_DPCD_MAX_LINK_RATE_162GBPS 0x06 +#define XDP_DPCD_MAX_LINK_RATE_270GBPS 0x0A +#define XDP_DPCD_MAX_LINK_RATE_540GBPS 0x14 +/* 0x00002: MAX_LANE_COUNT */ +#define XDP_DPCD_MAX_LANE_COUNT_MASK 0x1F +#define XDP_DPCD_MAX_LANE_COUNT_1 0x01 +#define XDP_DPCD_MAX_LANE_COUNT_2 0x02 +#define XDP_DPCD_MAX_LANE_COUNT_4 0x04 +#define XDP_DPCD_TPS3_SUPPORT_MASK 0x40 +#define XDP_DPCD_ENHANCED_FRAME_SUPPORT_MASK 0x80 +/* 0x00003: MAX_DOWNSPREAD */ +#define XDP_DPCD_MAX_DOWNSPREAD_MASK 0x01 +#define XDP_DPCD_NO_AUX_HANDSHAKE_LINK_TRAIN_MASK 0x40 +/* 0x00005: DOWNSP_PRESENT */ +#define XDP_DPCD_DOWNSP_PRESENT_MASK 0x01 +#define XDP_DPCD_DOWNSP_TYPE_MASK 0x06 +#define XDP_DPCD_DOWNSP_TYPE_SHIFT 1 +#define XDP_DPCD_DOWNSP_TYPE_DP 0x0 +#define XDP_DPCD_DOWNSP_TYPE_AVGA_ADVII 0x1 +#define XDP_DPCD_DOWNSP_TYPE_DVI_HDMI_DPPP 0x2 +#define XDP_DPCD_DOWNSP_TYPE_OTHERS 0x3 +#define XDP_DPCD_DOWNSP_FORMAT_CONV_MASK 0x08 +#define XDP_DPCD_DOWNSP_DCAP_INFO_AVAIL_MASK 0x10 +/* 0x00006, 0x00108: ML_CH_CODING_SUPPORT, ML_CH_CODING_SET */ +#define XDP_DPCD_ML_CH_CODING_MASK 0x01 +/* 0x00007: DOWNSP_COUNT_MSA_OUI */ +#define XDP_DPCD_DOWNSP_COUNT_MASK 0x0F +#define XDP_DPCD_MSA_TIMING_PAR_IGNORED_MASK 0x40 +#define XDP_DPCD_OUI_SUPPORT_MASK 0x80 +/* 0x00008, 0x0000A: RX_PORT[0-1]_CAP_0 */ +#define XDP_DPCD_RX_PORTX_CAP_0_LOCAL_EDID_PRESENT_MASK 0x02 +#define XDP_DPCD_RX_PORTX_CAP_0_ASSOC_TO_PRECEDING_PORT_MASK 0x04 +/* 0x0000C, 0x00109: I2C_SPEED_CTL_CAP, I2C_SPEED_CTL_SET */ +#define XDP_DPCD_I2C_SPEED_CTL_NONE 0x00 +#define XDP_DPCD_I2C_SPEED_CTL_1KBIPS 0x01 +#define XDP_DPCD_I2C_SPEED_CTL_5KBIPS 0x02 +#define XDP_DPCD_I2C_SPEED_CTL_10KBIPS 0x04 +#define XDP_DPCD_I2C_SPEED_CTL_100KBIPS 0x08 +#define XDP_DPCD_I2C_SPEED_CTL_400KBIPS 0x10 +#define XDP_DPCD_I2C_SPEED_CTL_1MBIPS 0x20 +/* 0x0000E: TRAIN_AUX_RD_INTERVAL */ +#define XDP_DPCD_TRAIN_AUX_RD_INT_100_400US 0x00 +#define XDP_DPCD_TRAIN_AUX_RD_INT_4MS 0x01 +#define XDP_DPCD_TRAIN_AUX_RD_INT_8MS 0x02 +#define XDP_DPCD_TRAIN_AUX_RD_INT_12MS 0x03 +#define XDP_DPCD_TRAIN_AUX_RD_INT_16MS 0x04 +/* 0x00020: DPCD_FAUX_CAP */ +#define XDP_DPCD_FAUX_CAP_MASK 0x01 +/* 0x00021: MSTM_CAP */ +#define XDP_DPCD_MST_CAP_MASK 0x01 +/* 0x00080, 0x00081|4, 0x00082|8, 0x00083|C: DOWNSP_X_(DET_)CAP */ +#define XDP_DPCD_DOWNSP_X_CAP_TYPE_MASK 0x07 +#define XDP_DPCD_DOWNSP_X_CAP_TYPE_DP 0x0 +#define XDP_DPCD_DOWNSP_X_CAP_TYPE_AVGA 0x1 +#define XDP_DPCD_DOWNSP_X_CAP_TYPE_DVI 0x2 +#define XDP_DPCD_DOWNSP_X_CAP_TYPE_HDMI 0x3 +#define XDP_DPCD_DOWNSP_X_CAP_TYPE_OTHERS 0x4 +#define XDP_DPCD_DOWNSP_X_CAP_TYPE_DPPP 0x5 +#define XDP_DPCD_DOWNSP_X_CAP_HPD_MASK 0x80 +#define XDP_DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_MASK 0xF0 +#define XDP_DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_SHIFT 4 +#define XDP_DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_720_480_I_60 0x1 +#define XDP_DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_720_480_I_50 0x2 +#define XDP_DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_1920_1080_I_60 0x3 +#define XDP_DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_1920_1080_I_50 0x4 +#define XDP_DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_1280_720_P_60 0x5 +#define XDP_DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_1280_720_P_50 0x7 +/* 0x00082, 0x00086, 0x0008A, 0x0008E: DOWNSP_X_(DET_)CAP2 */ +#define XDP_DPCD_DOWNSP_X_DCAP_MAX_BPC_MASK 0x03 +#define XDP_DPCD_DOWNSP_X_DCAP_MAX_BPC_8 0x0 +#define XDP_DPCD_DOWNSP_X_DCAP_MAX_BPC_10 0x1 +#define XDP_DPCD_DOWNSP_X_DCAP_MAX_BPC_12 0x2 +#define XDP_DPCD_DOWNSP_X_DCAP_MAX_BPC_16 0x3 +/* 0x00082, 0x00086, 0x0008A, 0x0008E: DOWNSP_X_(DET_)CAP2 */ +#define XDP_DPCD_DOWNSP_X_DCAP_HDMI_DPPP_FS2FP_MASK 0x01 +#define XDP_DPCD_DOWNSP_X_DCAP_DVI_DL_MASK 0x02 +#define XDP_DPCD_DOWNSP_X_DCAP_DVI_HCD_MASK 0x04 +/* @} */ + +/** @name DisplayPort Configuration Data: Link configuration field masks, + * shifts, and register values. + * @{ + */ +/* 0x00100: XDP_DPCD_LINK_BW_SET */ +#define XDP_DPCD_LINK_BW_SET_162GBPS 0x06 +#define XDP_DPCD_LINK_BW_SET_270GBPS 0x0A +#define XDP_DPCD_LINK_BW_SET_540GBPS 0x14 +/* 0x00101: LANE_COUNT_SET */ +#define XDP_DPCD_LANE_COUNT_SET_MASK 0x1F +#define XDP_DPCD_LANE_COUNT_SET_1 0x01 +#define XDP_DPCD_LANE_COUNT_SET_2 0x02 +#define XDP_DPCD_LANE_COUNT_SET_4 0x04 +#define XDP_DPCD_ENHANCED_FRAME_EN_MASK 0x80 +/* 0x00102: TP_SET */ +#define XDP_DPCD_TP_SEL_MASK 0x03 +#define XDP_DPCD_TP_SEL_OFF 0x0 +#define XDP_DPCD_TP_SEL_TP1 0x1 +#define XDP_DPCD_TP_SEL_TP2 0x2 +#define XDP_DPCD_TP_SEL_TP3 0x3 +#define XDP_DPCD_TP_SET_LQP_MASK 0x06 +#define XDP_DPCD_TP_SET_LQP_SHIFT 2 +#define XDP_DPCD_TP_SET_LQP_OFF 0x0 +#define XDP_DPCD_TP_SET_LQP_D102_TEST 0x1 +#define XDP_DPCD_TP_SET_LQP_SER_MES 0x2 +#define XDP_DPCD_TP_SET_LQP_PRBS7 0x3 +#define XDP_DPCD_TP_SET_REC_CLK_OUT_EN_MASK 0x10 +#define XDP_DPCD_TP_SET_SCRAMB_DIS_MASK 0x20 +#define XDP_DPCD_TP_SET_SE_COUNT_SEL_MASK 0xC0 +#define XDP_DPCD_TP_SET_SE_COUNT_SEL_SHIFT 6 +#define XDP_DPCD_TP_SET_SE_COUNT_SEL_DE_ISE 0x0 +#define XDP_DPCD_TP_SET_SE_COUNT_SEL_DE 0x1 +#define XDP_DPCD_TP_SET_SE_COUNT_SEL_ISE 0x2 +/* 0x00103-0x00106: TRAINING_LANE[0-3]_SET */ +#define XDP_DPCD_TRAINING_LANEX_SET_VS_MASK 0x03 +#define XDP_DPCD_TRAINING_LANEX_SET_MAX_VS_MASK 0x04 +#define XDP_DPCD_TRAINING_LANEX_SET_PE_MASK 0x18 +#define XDP_DPCD_TRAINING_LANEX_SET_PE_SHIFT 3 +#define XDP_DPCD_TRAINING_LANEX_SET_MAX_PE_MASK 0x20 +/* 0x00107: DOWNSPREAD_CTRL */ +#define XDP_DPCD_SPREAD_AMP_MASK 0x10 +#define XDP_DPCD_MSA_TIMING_PAR_IGNORED_EN_MASK 0x80 +/* 0x00108: ML_CH_CODING_SET - Same as 0x00006: ML_CH_CODING_SUPPORT */ +/* 0x00109: I2C_SPEED_CTL_SET - Same as 0x0000C: I2C_SPEED_CTL_CAP */ +/* 0x0010F-0x00110: TRAINING_LANE[0_1-2_3]_SET2 */ +#define XDP_DPCD_TRAINING_LANE_0_2_SET_PC2_MASK 0x03 +#define XDP_DPCD_TRAINING_LANE_0_2_SET_MAX_PC2_MASK 0x04 +#define XDP_DPCD_TRAINING_LANE_1_3_SET_PC2_MASK 0x30 +#define XDP_DPCD_TRAINING_LANE_1_3_SET_PC2_SHIFT 4 +#define XDP_DPCD_TRAINING_LANE_1_3_SET_MAX_PC2_MASK 0x40 +/* 0x00111: MSTM_CTRL */ +#define XDP_DPCD_MST_EN_MASK 0x01 +#define XDP_DPCD_UP_REQ_EN_MASK 0x02 +#define XDP_DPCD_UP_IS_SRC_MASK 0x03 +/* @} */ + +/** @name DisplayPort Configuration Data: Link/sink status field masks, shifts, + * and register values. + * @{ + */ +/* 0x00202: STATUS_LANE_0_1 */ +#define XDP_DPCD_STATUS_LANE_0_CR_DONE_MASK 0x01 +#define XDP_DPCD_STATUS_LANE_0_CE_DONE_MASK 0x02 +#define XDP_DPCD_STATUS_LANE_0_SL_DONE_MASK 0x04 +#define XDP_DPCD_STATUS_LANE_1_CR_DONE_MASK 0x10 +#define XDP_DPCD_STATUS_LANE_1_CE_DONE_MASK 0x20 +#define XDP_DPCD_STATUS_LANE_1_SL_DONE_MASK 0x40 +/* 0x00202: STATUS_LANE_2_3 */ +#define XDP_DPCD_STATUS_LANE_2_CR_DONE_MASK 0x01 +#define XDP_DPCD_STATUS_LANE_2_CE_DONE_MASK 0x02 +#define XDP_DPCD_STATUS_LANE_2_SL_DONE_MASK 0x04 +#define XDP_DPCD_STATUS_LANE_3_CR_DONE_MASK 0x10 +#define XDP_DPCD_STATUS_LANE_3_CE_DONE_MASK 0x20 +#define XDP_DPCD_STATUS_LANE_3_SL_DONE_MASK 0x40 +/* 0x00204: LANE_ALIGN_STATUS_UPDATED */ +#define XDP_DPCD_LANE_ALIGN_STATUS_UPDATED_IA_DONE_MASK \ + 0x01 +#define XDP_DPCD_LANE_ALIGN_STATUS_UPDATED_DOWNSP_STATUS_CHANGED_MASK \ + 0x40 +#define XDP_DPCD_LANE_ALIGN_STATUS_UPDATED_LINK_STATUS_UPDATED_MASK \ + 0x80 +/* 0x00205: SINK_STATUS */ +#define XDP_DPCD_SINK_STATUS_RX_PORT0_SYNC_STATUS_MASK 0x01 +#define XDP_DPCD_SINK_STATUS_RX_PORT1_SYNC_STATUS_MASK 0x02 + +/* 0x00206, 0x00207: ADJ_REQ_LANE_[0,2]_[1,3] */ +#define XDP_DPCD_ADJ_REQ_LANE_0_2_VS_MASK 0x03 +#define XDP_DPCD_ADJ_REQ_LANE_0_2_PE_MASK 0x0C +#define XDP_DPCD_ADJ_REQ_LANE_0_2_PE_SHIFT 2 +#define XDP_DPCD_ADJ_REQ_LANE_1_3_VS_MASK 0x30 +#define XDP_DPCD_ADJ_REQ_LANE_1_3_VS_SHIFT 4 +#define XDP_DPCD_ADJ_REQ_LANE_1_3_PE_MASK 0xC0 +#define XDP_DPCD_ADJ_REQ_LANE_1_3_PE_SHIFT 6 +/* 0x0020C: ADJ_REQ_PC2 */ +#define XDP_DPCD_ADJ_REQ_PC2_LANE_0_MASK 0x03 +#define XDP_DPCD_ADJ_REQ_PC2_LANE_1_MASK 0x0C +#define XDP_DPCD_ADJ_REQ_PC2_LANE_1_SHIFT 2 +#define XDP_DPCD_ADJ_REQ_PC2_LANE_2_MASK 0x30 +#define XDP_DPCD_ADJ_REQ_PC2_LANE_2_SHIFT 4 +#define XDP_DPCD_ADJ_REQ_PC2_LANE_3_MASK 0xC0 +#define XDP_DPCD_ADJ_REQ_PC2_LANE_3_SHIFT 6 +/* @} */ + +/******************************************************************************/ + +/******************************************************************************/ +/** + * Address mapping for the Extended Display Identification Data (EDID) of the + * downstream device. + * +*******************************************************************************/ +/** @name Extended Display Identification Data: Field addresses and sizes. + * @{ + */ +#define XDP_SEGPTR_ADDR 0x30 +#define XDP_EDID_ADDR 0x50 +#define XDP_EDID_BLOCK_SIZE 128 +#define XDP_EDID_DTD_DD(Num) (0x36 + (18 * Num)) +#define XDP_EDID_PTM XDP_EDID_DTD_DD(0) +#define XDP_EDID_EXT_BLOCK_COUNT 0x7E +/* @} */ + +/** @name Extended Display Identification Data: Register offsets for the + * Detailed Timing Descriptor (DTD). + * @{ + */ +#define XDP_EDID_DTD_PIXEL_CLK_KHZ_LSB 0x00 +#define XDP_EDID_DTD_PIXEL_CLK_KHZ_MSB 0x01 +#define XDP_EDID_DTD_HRES_LSB 0x02 +#define XDP_EDID_DTD_HBLANK_LSB 0x03 +#define XDP_EDID_DTD_HRES_HBLANK_U4 0x04 +#define XDP_EDID_DTD_VRES_LSB 0x05 +#define XDP_EDID_DTD_VBLANK_LSB 0x06 +#define XDP_EDID_DTD_VRES_VBLANK_U4 0x07 +#define XDP_EDID_DTD_HFPORCH_LSB 0x08 +#define XDP_EDID_DTD_HSPW_LSB 0x09 +#define XDP_EDID_DTD_VFPORCH_VSPW_L4 0x0A +#define XDP_EDID_DTD_XFPORCH_XSPW_U2 0x0B +#define XDP_EDID_DTD_HIMGSIZE_MM_LSB 0x0C +#define XDP_EDID_DTD_VIMGSIZE_MM_LSB 0x0D +#define XDP_EDID_DTD_XIMGSIZE_MM_U4 0x0E +#define XDP_EDID_DTD_HBORDER 0x0F +#define XDP_EDID_DTD_VBORDER 0x10 +#define XDP_EDID_DTD_SIGNAL 0x11 + +/** @name Extended Display Identification Data: Masks, shifts, and register + * values. + * @{ + */ +#define XDP_EDID_DTD_XRES_XBLANK_U4_XBLANK_MASK 0x0F +#define XDP_EDID_DTD_XRES_XBLANK_U4_XRES_MASK 0xF0 +#define XDP_EDID_DTD_XRES_XBLANK_U4_XRES_SHIFT 4 +#define XDP_EDID_DTD_VFPORCH_VSPW_L4_VSPW_MASK 0x0F +#define XDP_EDID_DTD_VFPORCH_VSPW_L4_VFPORCH_MASK 0xF0 +#define XDP_EDID_DTD_VFPORCH_VSPW_L4_VFPORCH_SHIFT 4 +#define XDP_EDID_DTD_XFPORCH_XSPW_U2_HFPORCH_MASK 0xC0 +#define XDP_EDID_DTD_XFPORCH_XSPW_U2_HSPW_MASK 0x30 +#define XDP_EDID_DTD_XFPORCH_XSPW_U2_VFPORCH_MASK 0x0C +#define XDP_EDID_DTD_XFPORCH_XSPW_U2_VSPW_MASK 0x03 +#define XDP_EDID_DTD_XFPORCH_XSPW_U2_HFPORCH_SHIFT 6 +#define XDP_EDID_DTD_XFPORCH_XSPW_U2_HSPW_SHIFT 4 +#define XDP_EDID_DTD_XFPORCH_XSPW_U2_VFPORCH_SHIFT 2 +#define XDP_EDID_DTD_XIMGSIZE_MM_U4_VIMGSIZE_MM_MASK 0x0F +#define XDP_EDID_DTD_XIMGSIZE_MM_U4_HIMGSIZE_MM_MASK 0xF0 +#define XDP_EDID_DTD_XIMGSIZE_MM_U4_HIMGSIZE_MM_SHIFT 4 +#define XDP_EDID_DTD_SIGNAL_HPOLARITY_MASK 0x02 +#define XDP_EDID_DTD_SIGNAL_VPOLARITY_MASK 0x04 +#define XDP_EDID_DTD_SIGNAL_HPOLARITY_SHIFT 1 +#define XDP_EDID_DTD_SIGNAL_VPOLARITY_SHIFT 2 +/* @} */ + +/** @name Extended Display Identification Data: Register offsets for the + * DisplayID extension block. + * @{ + */ +#define XDP_EDID_EXT_BLOCK_TAG 0x00 +#define XDP_TX_DISPID_VER_REV 0x00 +#define XDP_TX_DISPID_SIZE 0x01 +#define XDP_TX_DISPID_TYPE 0x02 +#define XDP_TX_DISPID_EXT_COUNT 0x03 +#define XDP_TX_DISPID_PAYLOAD_START 0x04 +#define XDP_TX_DISPID_DB_SEC_TAG 0x00 +#define XDP_TX_DISPID_DB_SEC_REV 0x01 +#define XDP_TX_DISPID_DB_SEC_SIZE 0x02 +/* @} */ + +/** @name Extended Display Identification Data: Masks, shifts, and register + * values for the DisplayID extension block. + * @{ + */ +#define XDP_EDID_EXT_BLOCK_TAG_DISPID 0x70 +#define XDP_TX_DISPID_TDT_TAG 0x12 +/* @} */ + +/** @name Extended Display Identification Data: Register offsets for the + * Tiled Display Topology (TDT) section data block. + * @{ + */ +#define XDP_TX_DISPID_TDT_TOP0 0x04 +#define XDP_TX_DISPID_TDT_TOP1 0x05 +#define XDP_TX_DISPID_TDT_TOP2 0x06 +#define XDP_TX_DISPID_TDT_HSIZE0 0x07 +#define XDP_TX_DISPID_TDT_HSIZE1 0x08 +#define XDP_TX_DISPID_TDT_VSIZE0 0x09 +#define XDP_TX_DISPID_TDT_VSIZE1 0x0A +#define XDP_TX_DISPID_TDT_VENID0 0x10 +#define XDP_TX_DISPID_TDT_VENID1 0x11 +#define XDP_TX_DISPID_TDT_VENID2 0x12 +#define XDP_TX_DISPID_TDT_PCODE0 0x13 +#define XDP_TX_DISPID_TDT_PCODE1 0x14 +#define XDP_TX_DISPID_TDT_SN0 0x15 +#define XDP_TX_DISPID_TDT_SN1 0x16 +#define XDP_TX_DISPID_TDT_SN2 0x17 +#define XDP_TX_DISPID_TDT_SN3 0x18 +/* @} */ + +/** @name Extended Display Identification Data: Masks, shifts, and register + * values for the Tiled Display Topology (TDT) section data block. + * @{ + */ +#define XDP_TX_DISPID_TDT_TOP0_HTOT_L_SHIFT 4 +#define XDP_TX_DISPID_TDT_TOP0_HTOT_L_MASK (0xF << 4) +#define XDP_TX_DISPID_TDT_TOP0_VTOT_L_MASK 0xF +#define XDP_TX_DISPID_TDT_TOP1_HLOC_L_SHIFT 4 +#define XDP_TX_DISPID_TDT_TOP1_HLOC_L_MASK (0xF << 4) +#define XDP_TX_DISPID_TDT_TOP1_VLOC_L_MASK 0xF +#define XDP_TX_DISPID_TDT_TOP2_HTOT_H_SHIFT 6 +#define XDP_TX_DISPID_TDT_TOP2_HTOT_H_MASK (0x3 << 6) +#define XDP_TX_DISPID_TDT_TOP2_VTOT_H_SHIFT 4 +#define XDP_TX_DISPID_TDT_TOP2_VTOT_H_MASK (0x3 << 4) +#define XDP_TX_DISPID_TDT_TOP2_HLOC_H_SHIFT 2 +#define XDP_TX_DISPID_TDT_TOP2_HLOC_H_MASK (0x3 << 2) +#define XDP_TX_DISPID_TDT_TOP2_VLOC_H_MASK 0x3 +/* @} */ + +/******************************************************************************/ +/** + * Multi-stream transport (MST) definitions. + * +*******************************************************************************/ +/** @name Stream identification. + * @{ + */ +#define XDP_TX_STREAM_ID1 1 +#define XDP_TX_STREAM_ID2 2 +#define XDP_TX_STREAM_ID3 3 +#define XDP_TX_STREAM_ID4 4 +/* @} */ + +/** @name Sideband message codes when the driver is in MST mode. + * @{ + */ +#define XDP_TX_SBMSG_LINK_ADDRESS 0x01 +#define XDP_TX_SBMSG_ENUM_PATH_RESOURCES 0x10 +#define XDP_TX_SBMSG_ALLOCATE_PAYLOAD 0x11 +#define XDP_TX_SBMSG_CLEAR_PAYLOAD_ID_TABLE 0x14 +#define XDP_TX_SBMSG_REMOTE_DPCD_READ 0x20 +#define XDP_TX_SBMSG_REMOTE_DPCD_WRITE 0x21 +#define XDP_TX_SBMSG_REMOTE_I2C_READ 0x22 +#define XDP_TX_SBMSG_REMOTE_I2C_WRITE 0x23 +/* @} */ + +/******************* Macros (Inline Functions) Definitions ********************/ + +/** @name Register access macro definitions. + * @{ + */ +#define XDp_In32 Xil_In32 +#define XDp_Out32 Xil_Out32 +/* @} */ + +/******************************************************************************/ +/** + * This is a low-level function that reads from the specified register. + * + * @param BaseAddress is the base address of the device. + * @param RegOffset is the register offset to be read from. + * + * @return The 32-bit value of the specified register. + * + * @note C-style signature: + * u32 XDp_ReadReg(u32 BaseAddress, u32 RegOffset) + * +*******************************************************************************/ +#define XDp_ReadReg(BaseAddress, RegOffset) \ + XDp_In32((BaseAddress) + (RegOffset)) + +/******************************************************************************/ +/** + * This is a low-level function that writes to the specified register. + * + * @param BaseAddress is the base address of the device. + * @param RegOffset is the register offset to write to. + * @param Data is the 32-bit data to write to the specified register. + * + * @return None. + * + * @note C-style signature: + * void XDp_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) + * +*******************************************************************************/ +#define XDp_WriteReg(BaseAddress, RegOffset, Data) \ + XDp_Out32((BaseAddress) + (RegOffset), (Data)) + + +/******************************************************************************/ +/** + * Check if an Extended Display Identification Data (EDID) extension block is of + * type DisplayID. + * + * @param Ext is a pointer to the EDID extension block under comparison. + * + * @return + * - 1 if the extension block is of type DisplayID. + * - Otherwise. + * + * @note C-style signature: + * u8 XDp_TxIsEdidExtBlockDispId(u8 *Ext) + * +*******************************************************************************/ +#define XDp_TxIsEdidExtBlockDispId(Ext) \ + (Ext[XDP_EDID_EXT_BLOCK_TAG] == XDP_EDID_EXT_BLOCK_TAG_DISPID) + +/******************************************************************************/ +/** + * Given a Tiled Display Topology (TDT) data block, retrieve the total number of + * horizontal tiles in the tiled display. The TDT block is part of an Extended + * Display Identification Data (EDID) extension block of type DisplayID. + * + * @param Tdt is a pointer to the TDT data block. + * + * @return The total number of horizontal tiles in the tiled display. + * + * @note C-style signature: + * u8 XDp_TxGetDispIdTdtHTotal(u8 *Tdt) + * +*******************************************************************************/ +#define XDp_TxGetDispIdTdtHTotal(Tdt) \ + (((((Tdt[XDP_TX_DISPID_TDT_TOP2] & XDP_TX_DISPID_TDT_TOP2_HTOT_H_MASK) \ + >> XDP_TX_DISPID_TDT_TOP2_HTOT_H_SHIFT) << 4) | \ + ((Tdt[XDP_TX_DISPID_TDT_TOP0] & XDP_TX_DISPID_TDT_TOP0_HTOT_L_MASK) >> \ + XDP_TX_DISPID_TDT_TOP0_HTOT_L_SHIFT)) + 1) + +/******************************************************************************/ +/** + * Given a Tiled Display Topology (TDT) data block, retrieve the total number of + * vertical tiles in the tiled display. The TDT block is part of an Extended + * Display Identification Data (EDID) extension block of type DisplayID. + * + * @param Tdt is a pointer to the TDT data block. + * + * @return The total number of vertical tiles in the tiled display. + * + * @note C-style signature: + * u8 XDp_TxGetDispIdTdtVTotal(u8 *Tdt) + * +*******************************************************************************/ +#define XDp_TxGetDispIdTdtVTotal(Tdt) \ + (((((Tdt[XDP_TX_DISPID_TDT_TOP2] & XDP_TX_DISPID_TDT_TOP2_VTOT_H_MASK) \ + >> XDP_TX_DISPID_TDT_TOP2_VTOT_H_SHIFT) << 4) | \ + (Tdt[XDP_TX_DISPID_TDT_TOP0] & XDP_TX_DISPID_TDT_TOP0_VTOT_L_MASK)) + 1) + +/******************************************************************************/ +/** + * Given a Tiled Display Topology (TDT) data block, retrieve the horizontal tile + * location in the tiled display. The TDT block is part of an Extended Display + * Identification Data (EDID) extension block of type DisplayID. + * + * @param Tdt is a pointer to the TDT data block. + * + * @return The horizontal tile location in the tiled display represented by + * the specified TDT. + * + * @note C-style signature: + * u8 XDp_TxGetDispIdTdtHLoc(u8 *Tdt) + * +*******************************************************************************/ +#define XDp_TxGetDispIdTdtHLoc(Tdt) \ + ((((Tdt[XDP_TX_DISPID_TDT_TOP2] & XDP_TX_DISPID_TDT_TOP2_HLOC_H_MASK) \ + >> XDP_TX_DISPID_TDT_TOP2_HLOC_H_SHIFT) << 4) | \ + ((Tdt[XDP_TX_DISPID_TDT_TOP1] & XDP_TX_DISPID_TDT_TOP1_HLOC_L_MASK) >> \ + XDP_TX_DISPID_TDT_TOP1_HLOC_L_SHIFT)) + +/******************************************************************************/ +/** + * Given a Tiled Display Topology (TDT) data block, retrieve the vertical tile + * location in the tiled display. The TDT block is part of an Extended Display + * Identification Data (EDID) extension block of type DisplayID. + * + * @param Tdt is a pointer to the TDT data block. + * + * @return The vertical tile location in the tiled display represented by + * the specified TDT. + * + * @note C-style signature: + * u8 XDp_TxGetDispIdTdtVLoc(u8 *Tdt) + * +*******************************************************************************/ +#define XDp_TxGetDispIdTdtVLoc(Tdt) \ + (((Tdt[XDP_TX_DISPID_TDT_TOP2] & XDP_TX_DISPID_TDT_TOP2_VLOC_H_MASK) << \ + 4) | (Tdt[XDP_TX_DISPID_TDT_TOP1] & XDP_TX_DISPID_TDT_TOP1_VLOC_L_MASK)) + +/******************************************************************************/ +/** + * Given a Tiled Display Topology (TDT) data block, retrieve the total number of + * tiles in the tiled display. The TDT block is part of an Extended Display + * Identification Data (EDID) extension block of type DisplayID. + * + * @param Tdt is a pointer to the TDT data block. + * + * @return The total number of tiles in the tiled display. + * + * @note C-style signature: + * u8 XDp_TxGetDispIdTdtNumTiles(u8 *Tdt) + * +*******************************************************************************/ +#define XDp_TxGetDispIdTdtNumTiles(Tdt) \ + (XDp_TxGetDispIdTdtHTotal(Tdt) * XDp_TxGetDispIdTdtVTotal(Tdt)) + +/******************************************************************************/ +/** + * Given a Tiled Display Topology (TDT) data block, calculate the tiling order + * of the associated tile. The TDT block is part of an Extended Display + * Identification Data (EDID) extension block of type DisplayID. + * The tiling order starts at 0 for x,y coordinate 0,0 and increments as the + * horizontal location increases. Once the last horizontal tile has been + * reached, the next tile in the order is 0,y+1. + * + * @param Tdt is a pointer to the TDT data block. + * + * @return The total number of horizontal tiles in the tiled display. + * + * @note C-style signature: + * u8 XDp_TxGetDispIdTdtTileOrder(u8 *Tdt) + * +*******************************************************************************/ +#define XDp_TxGetDispIdTdtTileOrder(Tdt) \ + ((XDp_TxGetDispIdTdtVLoc(Tdt) * XDp_TxGetDispIdTdtHTotal(Tdt)) + \ + XDp_TxGetDispIdTdtHLoc(Tdt)) + +#endif /* XDP_HW_H_ */ diff --git a/XilinxProcessorIPLib/drivers/dp/src/xdp_intr.c b/XilinxProcessorIPLib/drivers/dp/src/xdp_intr.c new file mode 100644 index 00000000..c3e2db16 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/src/xdp_intr.c @@ -0,0 +1,761 @@ +/******************************************************************************* + * + * 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 xdp_intr.c + * + * This file contains functions related to XDp interrupt handling. + * + * @note None. + * + *
+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial release. TX code merged from the dptx driver. + *+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdp.h" + +/**************************** Function Prototypes *****************************/ + +static void XDp_TxInterruptHandler(XDp *InstancePtr); +static void XDp_RxInterruptHandler(XDp *InstancePtr); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function is the interrupt handler for the XDp driver. + * When an interrupt happens, this interrupt handler will check which TX/RX mode + * of operation the core is running in, and will call the appropriate interrupt + * handler. The called interrupt handler will first detect what kind of + * interrupt happened, then decides which callback function to invoke. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_InterruptHandler(XDp *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (XDp_GetCoreType(InstancePtr) == XDP_TX) { + XDp_TxInterruptHandler(InstancePtr); + } + else { + XDp_RxInterruptHandler(InstancePtr); + } +} + +/******************************************************************************/ +/** + * This function generates a pulse on the hot-plug-detect (HPD) line of the + * specified duration. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param DurationUs is the duration of the HPD pulse, in microseconds. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxGenerateHpdInterrupt(XDp *InstancePtr, u16 DurationUs) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_HPD_INTERRUPT, + (DurationUs << XDP_RX_HPD_INTERRUPT_LENGTH_US_SHIFT) | + XDP_RX_HPD_INTERRUPT_ASSERT_MASK); +} + +/******************************************************************************/ +/** + * This function enables interrupts associated with the specified mask. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Mask specifies which interrupts should be enabled. Bits set to + * 1 will enable the corresponding interrupts. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxInterruptEnable(XDp *InstancePtr, u32 Mask) +{ + u32 MaskVal; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + + MaskVal = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_RX_INTERRUPT_CAUSE); + MaskVal &= ~Mask; + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_INTERRUPT_MASK, + MaskVal); +} + +/******************************************************************************/ +/** + * This function disables interrupts associated with the specified mask. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Mask specifies which interrupts should be disabled. Bits set to + * 1 will disable the corresponding interrupts. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxInterruptDisable(XDp *InstancePtr, u32 Mask) +{ + u32 MaskVal; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + + MaskVal = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_RX_INTERRUPT_CAUSE); + MaskVal |= Mask; + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_INTERRUPT_MASK, + MaskVal); +} + + +/******************************************************************************/ +/** + * This function installs a callback function for when a hot-plug-detect event + * interrupt occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item that will be passed to the + * callback function when it is invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxSetHpdEventHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->TxInstance.HpdEventHandler = CallbackFunc; + InstancePtr->TxInstance.HpdEventCallbackRef = CallbackRef; +} + +/******************************************************************************/ +/** + * This function installs a callback function for when a hot-plug-detect pulse + * interrupt occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item that will be passed to the + * callback function when it is invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxSetHpdPulseHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->TxInstance.HpdPulseHandler = CallbackFunc; + InstancePtr->TxInstance.HpdPulseCallbackRef = CallbackRef; +} + +/******************************************************************************/ +/** + * This function installs a callback function for when a video mode change + * interrupt occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item that will be passed to the + * callback function when it is invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxSetIntrVmChangeHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->RxInstance.IntrVmChangeHandler = CallbackFunc; + InstancePtr->RxInstance.IntrVmChangeCallbackRef = CallbackRef; +} + +/******************************************************************************/ +/** + * This function installs a callback function for when the power state interrupt + * occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item that will be passed to the + * callback function when it is invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxSetIntrPowerStateHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->RxInstance.IntrPowerStateHandler = CallbackFunc; + InstancePtr->RxInstance.IntrPowerStateCallbackRef = CallbackRef; +} + +/******************************************************************************/ +/** + * This function installs a callback function for when a no video interrupt + * occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item that will be passed to the + * callback function when it is invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxSetIntrNoVideoHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->RxInstance.IntrNoVideoHandler = CallbackFunc; + InstancePtr->RxInstance.IntrNoVideoCallbackRef = CallbackRef; +} + +/******************************************************************************/ +/** + * This function installs a callback function for when a vertical blanking + * interrupt occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item that will be passed to the + * callback function when it is invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxSetIntrVBlankHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->RxInstance.IntrVBlankHandler = CallbackFunc; + InstancePtr->RxInstance.IntrVBlankCallbackRef = CallbackRef; +} + +/******************************************************************************/ +/** + * This function installs a callback function for when a training lost interrupt + * occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item that will be passed to the + * callback function when it is invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxSetIntrTrainingLostHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->RxInstance.IntrTrainingLostHandler = CallbackFunc; + InstancePtr->RxInstance.IntrTrainingLostCallbackRef = CallbackRef; +} + +/******************************************************************************/ +/** + * This function installs a callback function for when a valid video interrupt + * occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item that will be passed to the + * callback function when it is invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxSetIntrVideoHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->RxInstance.IntrVideoHandler = CallbackFunc; + InstancePtr->RxInstance.IntrVideoCallbackRef = CallbackRef; +} + +/******************************************************************************/ +/** + * This function installs a callback function for when an audio info packet + * interrupt occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item that will be passed to the + * callback function when it is invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxSetIntrInfoPktHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->RxInstance.IntrInfoPktHandler = CallbackFunc; + InstancePtr->RxInstance.IntrInfoPktCallbackRef = CallbackRef; +} + +/******************************************************************************/ +/** + * This function installs a callback function for when an audio extension packet + * interrupt occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item that will be passed to the + * callback function when it is invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxSetIntrExtPktHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->RxInstance.IntrExtPktHandler = CallbackFunc; + InstancePtr->RxInstance.IntrExtPktCallbackRef = CallbackRef; +} + +/******************************************************************************/ +/** + * This function installs a callback function for when a training done interrupt + * occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item that will be passed to the + * callback function when it is invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxSetIntrTrainingDoneHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->RxInstance.IntrTrainingDoneHandler = CallbackFunc; + InstancePtr->RxInstance.IntrTrainingDoneCallbackRef = CallbackRef; +} + +/******************************************************************************/ +/** + * This function installs a callback function for when a bandwidth change + * interrupt occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item that will be passed to the + * callback function when it is invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxSetIntrBwChangeHandler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->RxInstance.IntrBwChangeHandler = CallbackFunc; + InstancePtr->RxInstance.IntrBwChangeCallbackRef = CallbackRef; +} + +/******************************************************************************/ +/** + * This function installs a callback function for when a training pattern 1 + * interrupt occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item that will be passed to the + * callback function when it is invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxSetIntrTp1Handler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->RxInstance.IntrTp1Handler = CallbackFunc; + InstancePtr->RxInstance.IntrTp1CallbackRef = CallbackRef; +} + +/******************************************************************************/ +/** + * This function installs a callback function for when a training pattern 2 + * interrupt occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item that will be passed to the + * callback function when it is invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxSetIntrTp2Handler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->RxInstance.IntrTp2Handler = CallbackFunc; + InstancePtr->RxInstance.IntrTp2CallbackRef = CallbackRef; +} + +/******************************************************************************/ +/** + * This function installs a callback function for when a training pattern 3 + * interrupt occurs. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item that will be passed to the + * callback function when it is invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxSetIntrTp3Handler(XDp *InstancePtr, + XDp_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->RxInstance.IntrTp3Handler = CallbackFunc; + InstancePtr->RxInstance.IntrTp3CallbackRef = CallbackRef; +} + +/******************************************************************************/ +/** + * This function is the interrupt handler for the XDp driver operating in TX + * mode. + * + * When an interrupt happens, it first detects what kind of interrupt happened, + * then decides which callback function to invoke. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void XDp_TxInterruptHandler(XDp *InstancePtr) +{ + u32 IntrStatus; + u8 HpdEventDetected; + u8 HpdPulseDetected; + u32 HpdDuration; + u32 IntrMask; + + /* Determine what kind of interrupt occurred. + * Note: XDP_TX_INTERRUPT_STATUS is an RC (read-clear) register. */ + IntrStatus = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_TX_INTERRUPT_STATUS); + IntrStatus &= ~XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_TX_INTERRUPT_MASK); + IntrMask = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_TX_INTERRUPT_MASK); + + HpdEventDetected = IntrStatus & XDP_TX_INTERRUPT_STATUS_HPD_EVENT_MASK; + HpdPulseDetected = IntrStatus & + XDP_TX_INTERRUPT_STATUS_HPD_PULSE_DETECTED_MASK; + + if (HpdEventDetected) { + /* Mask interrupts while event handling is taking place. API + * will error out in case of a disconnection event anyway. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, + XDP_TX_INTERRUPT_MASK, IntrMask | + XDP_TX_INTERRUPT_MASK_HPD_EVENT_MASK); + + InstancePtr->TxInstance.HpdEventHandler( + InstancePtr->TxInstance.HpdEventCallbackRef); + } + else if (HpdPulseDetected && XDp_TxIsConnected(InstancePtr)) { + /* Mask interrupts while event handling is taking place. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, + XDP_TX_INTERRUPT_MASK, IntrMask | + XDP_TX_INTERRUPT_MASK_HPD_PULSE_DETECTED_MASK); + + /* The source device must debounce the incoming HPD signal by + * sampling the value at an interval greater than 0.500 ms. An + * HPD pulse should be of width 0.5 ms - 1.0 ms. */ + HpdDuration = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_TX_HPD_DURATION); + if (HpdDuration >= 500) { + InstancePtr->TxInstance.HpdPulseHandler( + InstancePtr->TxInstance.HpdPulseCallbackRef); + } + } + + /* Unmask previously masked interrupts once handling is done. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_INTERRUPT_MASK, + IntrMask); +} + +/******************************************************************************/ +/** + * This function is the interrupt handler for the XDp driver operating in RX + * mode. + * + * When an interrupt happens, it first detects what kind of interrupt happened, + * then decides which callback function to invoke. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void XDp_RxInterruptHandler(XDp *InstancePtr) +{ + u32 IntrStatus; + + /* Determine what kind of interrupts have occurred. + * Note: XDP_RX_INTERRUPT_CAUSE is a RC (read-clear) register. */ + IntrStatus = XDp_ReadReg(InstancePtr->Config.BaseAddr, + XDP_RX_INTERRUPT_CAUSE); + + /* Training pattern 1 has started. */ + if (IntrStatus & XDP_RX_INTERRUPT_CAUSE_TP1_MASK) { + InstancePtr->RxInstance.IntrTp1Handler( + InstancePtr->RxInstance.IntrTp1CallbackRef); + } + /* Training pattern 2 has started. */ + if (IntrStatus & XDP_RX_INTERRUPT_CAUSE_TP2_MASK) { + InstancePtr->RxInstance.IntrTp2Handler( + InstancePtr->RxInstance.IntrTp2CallbackRef); + } + /* Training pattern 3 has started. */ + if (IntrStatus & XDP_RX_INTERRUPT_CAUSE_TP3_MASK) { + InstancePtr->RxInstance.IntrTp3Handler( + InstancePtr->RxInstance.IntrTp3CallbackRef); + } + /* Training lost - the link has been lost. */ + if (IntrStatus & XDP_RX_INTERRUPT_CAUSE_TRAINING_LOST_MASK) { + InstancePtr->RxInstance.IntrTrainingLostHandler( + InstancePtr->RxInstance.IntrTrainingLostCallbackRef); + } + /* The link has been trained. */ + else if (IntrStatus & XDP_RX_INTERRUPT_CAUSE_TRAINING_DONE_MASK) { + InstancePtr->RxInstance.IntrTrainingDoneHandler( + InstancePtr->RxInstance.IntrTrainingDoneCallbackRef); + } + + /* A change has been detected in the current video transmitted on the + * link as indicated by the main stream attributes (MSA) fields. The + * horizontal and vertical resolution parameters are monitored for + * changes. */ + if (IntrStatus & XDP_RX_INTERRUPT_CAUSE_VM_CHANGE_MASK) { + InstancePtr->RxInstance.IntrVmChangeHandler( + InstancePtr->RxInstance.IntrVmChangeCallbackRef); + } + /* The VerticalBlanking_Flag in the VB-ID field of the received stream + * indicates the start of the vertical blanking interval. */ + if (IntrStatus & XDP_RX_INTERRUPT_CAUSE_VBLANK_MASK) { + InstancePtr->RxInstance.IntrVBlankHandler( + InstancePtr->RxInstance.IntrVBlankCallbackRef); + } + /* The receiver has detected the no-video flags in the VB-ID field after + * active video has been received. */ + if (IntrStatus & XDP_RX_INTERRUPT_CAUSE_NO_VIDEO_MASK) { + InstancePtr->RxInstance.IntrNoVideoHandler( + InstancePtr->RxInstance.IntrNoVideoCallbackRef); + } + /* A valid video frame is detected on the main link. */ + else if (IntrStatus & XDP_RX_INTERRUPT_CAUSE_VIDEO_MASK) { + InstancePtr->RxInstance.IntrVideoHandler( + InstancePtr->RxInstance.IntrVideoCallbackRef); + } + + /* The transmitter has requested a change in the current power state of + * the receiver core. */ + if (IntrStatus & XDP_RX_INTERRUPT_CAUSE_POWER_STATE_MASK) { + InstancePtr->RxInstance.IntrPowerStateHandler( + InstancePtr->RxInstance.IntrPowerStateCallbackRef); + } + /* A change in the bandwidth has been detected. */ + if (IntrStatus & XDP_RX_INTERRUPT_CAUSE_BW_CHANGE_MASK) { + InstancePtr->RxInstance.IntrBwChangeHandler( + InstancePtr->RxInstance.IntrBwChangeCallbackRef); + } + + /* An audio info packet has been received. */ + if (IntrStatus & XDP_RX_INTERRUPT_CAUSE_INFO_PKT_MASK) { + InstancePtr->RxInstance.IntrInfoPktHandler( + InstancePtr->RxInstance.IntrInfoPktCallbackRef); + } + /* An audio extension packet has been received. */ + if (IntrStatus & XDP_RX_INTERRUPT_CAUSE_EXT_PKT_MASK) { + InstancePtr->RxInstance.IntrExtPktHandler( + InstancePtr->RxInstance.IntrExtPktCallbackRef); + } +} diff --git a/XilinxProcessorIPLib/drivers/dp/src/xdp_mst.c b/XilinxProcessorIPLib/drivers/dp/src/xdp_mst.c new file mode 100644 index 00000000..2e7c72d6 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/src/xdp_mst.c @@ -0,0 +1,3071 @@ +/******************************************************************************* + * + * 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 xdp_mst.c + * + *
+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial release. TX code merged from the dptx driver. + *+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "string.h" +#include "xdp.h" + +/**************************** Constant Definitions ****************************/ + +/* Error out if waiting for a sideband message reply or waiting for the payload + * ID table to be updated takes more than 5000 AUX read iterations. */ +#define XDP_TX_MAX_SBMSG_REPLY_TIMEOUT_COUNT 5000 +/* Error out if waiting for the RX device to indicate that it has received an + * ACT trigger takes more than 30 AUX read iterations. */ +#define XDP_TX_VCP_TABLE_MAX_TIMEOUT_COUNT 30 + +/****************************** Type Definitions ******************************/ + +/** + * This typedef stores the sideband message header. + */ +typedef struct +{ + u8 LinkCountTotal; /**< The total number of DisplayPort + links connecting the device + device that this sideband + message is targeted from the + DisplayPort TX. */ + u8 LinkCountRemaining; /**< The remaining link count until + the sideband message reaches + the target device. */ + u8 RelativeAddress[15]; /**< The relative address from the + DisplayPort TX to the target + device. */ + u8 BroadcastMsg; /**< Specifies that this message is + a broadcast message, to be + handled by all downstream + devices. */ + u8 PathMsg; /**< Specifies that this message is + a path message, to be handled by + all the devices between the + origin and the target device. */ + u8 MsgBodyLength; /**< The total number of data bytes that + are stored in the sideband + message body. */ + u8 StartOfMsgTransaction; /**< This message is the first sideband + message in the transaction. */ + u8 EndOfMsgTransaction; /**< This message is the last sideband + message in the transaction. */ + u8 MsgSequenceNum; /**< Identifies invidiual message + transactions to a given + DisplayPort device. */ + u8 Crc; /**< The cyclic-redundancy check (CRC) + value of the header data. */ + + u8 MsgHeaderLength; /**< The number of data bytes stored as + part of the sideband message + header. */ +} XDp_SidebandMsgHeader; + +/** + * This typedef stores the sideband message body. + */ +typedef struct +{ + u8 MsgData[62]; /**< The raw body data of the sideband + message. */ + u8 MsgDataLength; /**< The number of data bytes stored as + part of the sideband message + body. */ + u8 Crc; /**< The cyclic-redundancy check (CRC) + value of the body data. */ +} XDp_SidebandMsgBody; + +/** + * This typedef stores the entire sideband message. + */ +typedef struct +{ + XDp_SidebandMsgHeader Header; /**< The header segment of the sideband + message. */ + XDp_SidebandMsgBody Body; /**< The body segment of the sideband + message. */ +} XDp_SidebandMsg; + +/** + * This typedef describes a sideband message reply. + */ +typedef struct +{ + u8 Length; /**< The number of bytes of reply + data. */ + u8 Data[256]; /**< The raw reply data. */ +} XDp_SidebandReply; + +/**************************** Function Prototypes *****************************/ + +static void XDp_TxIssueGuid(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, XDp_TxTopology *Topology, + u32 *Guid); +static void XDp_TxAddBranchToList(XDp *InstancePtr, + XDp_TxSbMsgLinkAddressReplyDeviceInfo *DeviceInfo, + u8 LinkCountTotal, u8 *RelativeAddress); +static void XDp_TxAddSinkToList(XDp *InstancePtr, + XDp_TxSbMsgLinkAddressReplyPortDetail *SinkDevice, + u8 LinkCountTotal, u8 *RelativeAddress); +static void XDp_TxGetDeviceInfoFromSbMsgLinkAddress( + XDp_SidebandReply *SbReply, + XDp_TxSbMsgLinkAddressReplyDeviceInfo *FormatReply); +static u32 XDp_TxGetFirstAvailableTs(XDp *InstancePtr, u8 *FirstTs); +static u32 XDp_TxSendActTrigger(XDp *InstancePtr); +static u32 XDp_TxSendSbMsg(XDp *InstancePtr, XDp_SidebandMsg *Msg); +static u32 XDp_TxReceiveSbMsg(XDp *InstancePtr, XDp_SidebandReply *SbReply); +static u32 XDp_TxWaitSbReply(XDp *InstancePtr); +static u32 XDp_TxTransaction2MsgFormat(u8 *Transaction, XDp_SidebandMsg *Msg); +static u8 XDp_TxCrc4CalculateHeader(XDp_SidebandMsgHeader *Header); +static u8 XDp_TxCrc8CalculateBody(XDp_SidebandMsgBody *Body); +static u8 XDp_TxCrcCalculate(const u8 *Data, u32 NumberOfBits, u8 Polynomial); +static u32 XDp_TxIsSameTileDisplay(u8 *DispIdSecTile0, u8 *DispIdSecTile1); + +/**************************** Variable Definitions ****************************/ + +/** + * This table contains a list of global unique identifiers (GUIDs) that will be + * issued when exploring the topology using the algorithm in the + * XDp_TxFindAccessibleDpDevices function. + */ +u32 GuidTable[16][4] = { + {0x12341234, 0x43214321, 0x56785678, 0x87658765}, + {0xDEADBEEF, 0xBEEFDEAD, 0x10011001, 0xDADADADA}, + {0xDABADABA, 0x10011001, 0xBADABADA, 0x5AD5AD5A}, + {0x12345678, 0x43214321, 0xABCDEF98, 0x87658765}, + {0x12141214, 0x41214121, 0x56785678, 0x87658765}, + {0xD1CDB11F, 0xB11FD1CD, 0xFEBCDA90, 0xDCDCDCDC}, + {0xDCBCDCBC, 0xE000E000, 0xBCDCBCDC, 0x5CD5CD5C}, + {0x11111111, 0x11111111, 0x11111111, 0x11111111}, + {0x22222222, 0x22222222, 0x22222222, 0x22222222}, + {0x33333333, 0x33333333, 0x33333333, 0x33333333}, + {0xAAAAAAAA, 0xFFFFFFFF, 0xFEBCDA90, 0xDCDCDCDC}, + {0xBBBBBBBB, 0xE000E000, 0xFFFFFFFF, 0x5CD5CD5C}, + {0xCCCCCCCC, 0x11111111, 0x11111111, 0xFFFFFFFF}, + {0xDDDDDDDD, 0x22222222, 0xFFFFFFFF, 0x22222222}, + {0xEEEEEEEE, 0xFFFFFFFF, 0x33333333, 0x33333333}, + {0x12145678, 0x41214121, 0xCBCD1F98, 0x87658765} +}; + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function will enable multi-stream transport (MST) mode for the driver. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxMstCfgModeEnable(XDp *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + + InstancePtr->TxInstance.MstEnable = 1; +} + +/******************************************************************************/ +/** + * This function will disable multi-stream transport (MST) mode for the driver. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note When disabled, the driver will behave in single-stream transport + * (SST) mode. + * +*******************************************************************************/ +void XDp_TxMstCfgModeDisable(XDp *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + + InstancePtr->TxInstance.MstEnable = 0; +} + +/******************************************************************************/ +/** + * This function will check if the immediate downstream RX device is capable of + * multi-stream transport (MST) mode. A DisplayPort Configuration Data (DPCD) + * version of 1.2 or higher is required and the MST capability bit in the DPCD + * must be set for this function to return XST_SUCCESS. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the RX device is MST capable. + * - XST_NO_FEATURE if the RX device does not support MST. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if an AUX read request timed out. + * - XST_FAILURE otherwise - if an AUX read transaction failed. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxMstCapable(XDp *InstancePtr) +{ + u32 Status; + u8 AuxData; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + + if (InstancePtr->Config.MstSupport == 0) { + return XST_NO_FEATURE; + } + + /* Check that the RX device has a DisplayPort Configuration Data (DPCD) + * version greater than or equal to 1.2 to be able to support MST + * functionality. */ + Status = XDp_TxAuxRead(InstancePtr, XDP_DPCD_REV, 1, &AuxData); + if (Status != XST_SUCCESS) { + /* The AUX read transaction failed. */ + return Status; + } + else if (AuxData < 0x12) { + return XST_NO_FEATURE; + } + + /* Check if the RX device has MST capabilities.. */ + Status = XDp_TxAuxRead(InstancePtr, XDP_DPCD_MSTM_CAP, 1, &AuxData); + if (Status != XST_SUCCESS) { + /* The AUX read transaction failed. */ + return Status; + } + else if ((AuxData & XDP_DPCD_MST_CAP_MASK) != + XDP_DPCD_MST_CAP_MASK) { + return XST_NO_FEATURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will enable multi-stream transport (MST) mode in both the + * DisplayPort TX and the immediate downstream RX device. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if MST mode has been successful enabled in + * hardware. + * - XST_NO_FEATURE if the immediate downstream RX device does not + * support MST - that is, if its DisplayPort Configuration Data + * (DPCD) version is less than 1.2, or if the DPCD indicates that + * it has no DPCD capabilities. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if an AUX request timed out. + * - XST_FAILURE otherwise - if an AUX read or write transaction + * failed. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxMstEnable(XDp *InstancePtr) +{ + u32 Status; + u8 AuxData; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + + /* Check if the immediate downstream RX device has MST capabilities. */ + Status = XDp_TxMstCapable(InstancePtr); + if (Status != XST_SUCCESS) { + /* The RX device is not downstream capable. */ + return Status; + } + + /* HPD long pulse used for upstream notification. */ + AuxData = 0; + Status = XDp_TxAuxWrite(InstancePtr, XDP_DPCD_BRANCH_DEVICE_CTRL, 1, + &AuxData); + if (Status != XST_SUCCESS) { + /* The AUX write transaction failed. */ + return Status; + } + + /* Enable MST in the immediate branch device and tell it that its + * upstream device is a source (the DisplayPort TX). */ + AuxData = XDP_DPCD_UP_IS_SRC_MASK | XDP_DPCD_UP_REQ_EN_MASK | + XDP_DPCD_MST_EN_MASK; + Status = XDp_TxAuxWrite(InstancePtr, XDP_DPCD_MSTM_CTRL, 1, &AuxData); + if (Status != XST_SUCCESS) { + /* The AUX write transaction failed. */ + return Status; + } + + /* Enable MST in the DisplayPort TX. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_MST_CONFIG, + XDP_TX_MST_CONFIG_MST_EN_MASK); + + XDp_TxMstCfgModeEnable(InstancePtr); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will disable multi-stream transport (MST) mode in both the + * DisplayPort TX and the immediate downstream RX device. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if MST mode has been successful disabled in + * hardware. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if the AUX write request timed out. + * - XST_FAILURE otherwise - if the AUX write transaction failed. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxMstDisable(XDp *InstancePtr) +{ + u32 Status; + u8 AuxData; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + + /* Disable MST mode in the immediate branch device. */ + AuxData = 0; + Status = XDp_TxAuxWrite(InstancePtr, XDP_DPCD_MSTM_CTRL, 1, &AuxData); + if (Status != XST_SUCCESS) { + /* The AUX write transaction failed. */ + return Status; + } + + /* Disable MST mode in the DisplayPort TX. */ + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_MST_CONFIG, 0x0); + + XDp_TxMstCfgModeDisable(InstancePtr); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will check whether + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Stream is the stream ID to check for enable/disable status. + * + * @return + * - 1 if the specified stream is enabled. + * - 0 if the specified stream is disabled. + * + * @note None. + * +*******************************************************************************/ +u8 XDp_TxMstStreamIsEnabled(XDp *InstancePtr, u8 Stream) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid((Stream == XDP_TX_STREAM_ID1) || + (Stream == XDP_TX_STREAM_ID2) || + (Stream == XDP_TX_STREAM_ID3) || + (Stream == XDP_TX_STREAM_ID4)); + + return InstancePtr->TxInstance. + MstStreamConfig[Stream - 1].MstStreamEnable; +} + +/******************************************************************************/ +/** + * This function will configure the InstancePtr->TxInstance.MstStreamConfig + * structure to enable the specified stream. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Stream is the stream ID that will be enabled. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxMstCfgStreamEnable(XDp *InstancePtr, u8 Stream) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Stream == XDP_TX_STREAM_ID1) || + (Stream == XDP_TX_STREAM_ID2) || + (Stream == XDP_TX_STREAM_ID3) || + (Stream == XDP_TX_STREAM_ID4)); + + InstancePtr->TxInstance.MstStreamConfig[Stream - 1].MstStreamEnable = 1; +} + +/******************************************************************************/ +/** + * This function will configure the InstancePtr->TxInstance.MstStreamConfig + * structure to disable the specified stream. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Stream is the stream ID that will be disabled. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxMstCfgStreamDisable(XDp *InstancePtr, u8 Stream) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Stream == XDP_TX_STREAM_ID1) || + (Stream == XDP_TX_STREAM_ID2) || + (Stream == XDP_TX_STREAM_ID3) || + (Stream == XDP_TX_STREAM_ID4)); + + InstancePtr->TxInstance.MstStreamConfig[Stream - 1].MstStreamEnable = 0; +} + +/******************************************************************************/ +/** + * This function will map a stream to a downstream DisplayPort TX device that is + * associated with a sink from the InstancePtr->TxInstance.Topology.SinkList. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Stream is the stream ID that will be mapped to a DisplayPort + * device. + * @param SinkNum is the sink ID in the sink list that will be mapped to + * the stream. + * + * @return None. + * + * @note The contents of the InstancePtr->TxInstance. + * MstStreamConfig[Stream] will be modified. + * @note The topology will need to be determined prior to calling this + * function using the XDp_TxFindAccessibleDpDevices. + * +*******************************************************************************/ +void XDp_TxSetStreamSelectFromSinkList(XDp *InstancePtr, u8 Stream, u8 SinkNum) +{ + u8 Index; + XDp_TxMstStream *MstStream; + XDp_TxTopology *Topology; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Stream == XDP_TX_STREAM_ID1) || + (Stream == XDP_TX_STREAM_ID2) || + (Stream == XDP_TX_STREAM_ID3) || + (Stream == XDP_TX_STREAM_ID4)); + + MstStream = &InstancePtr->TxInstance.MstStreamConfig[Stream - 1]; + Topology = &InstancePtr->TxInstance.Topology; + + MstStream->LinkCountTotal = Topology->SinkList[SinkNum]->LinkCountTotal; + for (Index = 0; Index < MstStream->LinkCountTotal - 1; Index++) { + MstStream->RelativeAddress[Index] = + Topology->SinkList[SinkNum]->RelativeAddress[Index]; + } +} + +/******************************************************************************/ +/** + * This function will map a stream to a downstream DisplayPort TX device + * determined by the relative address. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Stream is the stream number that will be mapped to a DisplayPort + * device. + * @param LinkCountTotal is the total DisplayPort links connecting the + * DisplayPort TX to the targeted downstream device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the targeted DisplayPort device. + * + * @return None. + * + * @note The contents of the InstancePtr->TxInstance. + * MstStreamConfig[Stream] will be modified. + * +*******************************************************************************/ +void XDp_TxSetStreamSinkRad(XDp *InstancePtr, u8 Stream, u8 LinkCountTotal, + u8 *RelativeAddress) +{ + u8 Index; + XDp_TxMstStream *MstStream; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Stream == XDP_TX_STREAM_ID1) || + (Stream == XDP_TX_STREAM_ID2) || + (Stream == XDP_TX_STREAM_ID3) || + (Stream == XDP_TX_STREAM_ID4)); + Xil_AssertVoid(LinkCountTotal > 0); + Xil_AssertVoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + + MstStream = &InstancePtr->TxInstance.MstStreamConfig[Stream - 1]; + + MstStream->LinkCountTotal = LinkCountTotal; + for (Index = 0; Index < MstStream->LinkCountTotal - 1; Index++) { + MstStream->RelativeAddress[Index] = RelativeAddress[Index]; + } +} + +/******************************************************************************/ +/** + * This function will explore the DisplayPort topology of downstream devices + * connected to the DisplayPort TX. It will recursively go through each branch + * device, obtain its information by sending a LINK_ADDRESS sideband message, + * and add this information to the the topology's node table. For each sink + * device connected to a branch's downstream port, this function will obtain + * the details of the sink, add it to the topology's node table, as well as + * add it to the topology's sink list. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the topology discovery is successful. + * - XST_FAILURE otherwise - if sending a LINK_ADDRESS sideband + * message to one of the branch devices in the topology failed. + * + * @note The contents of the InstancePtr->TxInstance.Topology structure + * will be modified. + * +*******************************************************************************/ +u32 XDp_TxDiscoverTopology(XDp *InstancePtr) +{ + u8 RelativeAddress[15]; + + return XDp_TxFindAccessibleDpDevices(InstancePtr, 1, RelativeAddress); +} + +/******************************************************************************/ +/** + * This function will explore the DisplayPort topology of downstream devices + * starting from the branch device specified by the LinkCountTotal and + * RelativeAddress parameters. It will recursively go through each branch + * device, obtain its information by sending a LINK_ADDRESS sideband message, + * and add this information to the the topology's node table. For each sink + * device connected to a branch's downstream port, this function will obtain + * the details of the sink, add it to the topology's node table, as well as + * add it to the topology's sink list. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkCountTotal is the total DisplayPort links connecting the + * DisplayPort TX to the current downstream device in the + * recursion. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the current target DisplayPort device in the + * recursion. + * + * @return + * - XST_SUCCESS if the topology discovery is successful. + * - XST_FAILURE otherwise - if sending a LINK_ADDRESS sideband + * message to one of the branch devices in the topology failed. + * + * @note The contents of the InstancePtr->TxInstance.Topology structure + * will be modified. + * +*******************************************************************************/ +u32 XDp_TxFindAccessibleDpDevices(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress) +{ + u32 Status; + u8 Index; + u8 NumDownBranches = 0; + u8 OverallFailures = 0; + XDp_TxTopology *Topology; + XDp_TxSbMsgLinkAddressReplyPortDetail *PortDetails; + static XDp_TxSbMsgLinkAddressReplyDeviceInfo DeviceInfo; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + + Topology = &InstancePtr->TxInstance.Topology; + + /* Send a LINK_ADDRESS sideband message to the branch device in order to + * obtain information on it and its downstream devices. */ + Status = XDp_TxSendSbMsgLinkAddress(InstancePtr, LinkCountTotal, + RelativeAddress, &DeviceInfo); + if (Status != XST_SUCCESS) { + /* The LINK_ADDRESS was sent to a device that cannot reply; exit + * from this recursion path. */ + return XST_FAILURE; + } + + /* Write GUID to the branch device if it doesn't already have one. */ + XDp_TxIssueGuid(InstancePtr, LinkCountTotal, RelativeAddress, Topology, + DeviceInfo.Guid); + + /* Add the branch device to the topology table. */ + XDp_TxAddBranchToList(InstancePtr, &DeviceInfo, LinkCountTotal, + RelativeAddress); + + /* Downstream devices will be an extra link away from the source than + * this branch device. */ + LinkCountTotal++; + + u8 DownBranchesDownPorts[DeviceInfo.NumPorts]; + for (Index = 0; Index < DeviceInfo.NumPorts; Index++) { + PortDetails = &DeviceInfo.PortDetails[Index]; + /* Any downstream device downstream device will have the RAD of + * the current branch device appended with the port number. */ + RelativeAddress[LinkCountTotal - 2] = PortDetails->PortNum; + + if ((PortDetails->InputPort == 0) && + (PortDetails->PeerDeviceType != 0x2) && + (PortDetails->DpDevPlugStatus == 1)) { + + if ((PortDetails->MsgCapStatus == 1) && + (PortDetails->DpcdRev >= 0x12)) { + /* Write GUID to the branch device if it + * doesn't already have one. */ + XDp_TxIssueGuid(InstancePtr, + LinkCountTotal, RelativeAddress, + Topology, PortDetails->Guid); + } + + XDp_TxAddSinkToList(InstancePtr, PortDetails, + LinkCountTotal, + RelativeAddress); + } + + if (PortDetails->PeerDeviceType == 0x2) { + DownBranchesDownPorts[NumDownBranches] = + PortDetails->PortNum; + NumDownBranches++; + } + } + + for (Index = 0; Index < NumDownBranches; Index++) { + /* Any downstream device downstream device will have the RAD of + * the current branch device appended with the port number. */ + RelativeAddress[LinkCountTotal - 2] = + DownBranchesDownPorts[Index]; + + /* Found a branch device; recurse the algorithm to see what + * DisplayPort devices are connected to it with the appended + * RAD. */ + Status = XDp_TxFindAccessibleDpDevices(InstancePtr, + LinkCountTotal, RelativeAddress); + if (Status != XST_SUCCESS) { + /* Keep trying to discover the topology, but the top + * level function call should indicate that a failure + * was detected. */ + OverallFailures++; + } + } + + if (OverallFailures != 0) { + return XST_FAILURE; + } + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * Swap the ordering of the sinks in the topology's sink list. All sink + * information is preserved in the node table - the swapping takes place only on + * the pointers to the sinks in the node table. The reason this swapping is done + * is so that functions that use the sink list will act on the sinks in a + * different order. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Index0 is the sink list's index of one of the sink pointers to + * be swapped. + * @param Index1 is the sink list's index of the other sink pointer to be + * swapped. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxTopologySwapSinks(XDp *InstancePtr, u8 Index0, u8 Index1) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + + XDp_TxTopologyNode *TmpSink = + InstancePtr->TxInstance.Topology.SinkList[Index0]; + + InstancePtr->TxInstance.Topology.SinkList[Index0] = + InstancePtr->TxInstance.Topology.SinkList[Index1]; + + InstancePtr->TxInstance.Topology.SinkList[Index1] = TmpSink; +} + +/******************************************************************************/ +/** + * Order the sink list with all sinks of the same tiled display being sorted by + * 'tile order'. Refer to the XDp_TxGetDispIdTdtTileOrder macro on how to + * determine the 'tile order'. Sinks of a tiled display will have an index in + * the sink list that is lower than all indices of other sinks within that same + * tiled display that have a greater 'tile order'. + * When operations are done on the sink list, this ordering will ensure that + * sinks within the same tiled display will be acted upon in a consistent + * manner - with an incrementing sink list index, sinks with a lower 'tile + * order' will be acted upon first relative to the other sinks in the same tiled + * display. Multiple tiled displays may exist in the sink list. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxTopologySortSinksByTiling(XDp *InstancePtr) +{ + u32 Status; + XDp_TxTopologyNode *CurrSink, *CmpSink; + u8 CurrIndex, CmpIndex, NewIndex; + u8 CurrEdidExt[128], CmpEdidExt[128]; + u8 *CurrTdt, *CmpTdt; + u8 CurrTileOrder, CmpTileOrder; + u8 SameTileDispCount, SameTileDispNum; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + + for (CurrIndex = 0; CurrIndex < + (InstancePtr->TxInstance.Topology.SinkTotal - 1); + CurrIndex++) { + CurrSink = InstancePtr->TxInstance.Topology.SinkList[CurrIndex]; + + Status = XDp_TxGetRemoteTiledDisplayDb(InstancePtr, CurrEdidExt, + CurrSink->LinkCountTotal, + CurrSink->RelativeAddress, &CurrTdt); + if (Status != XST_SUCCESS) { + /* No Tiled Display Topology (TDT) data block exists. */ + continue; + } + + /* Start by using the tiling parameters of the current sink + * index. */ + CurrTileOrder = XDp_TxGetDispIdTdtTileOrder(CurrTdt); + NewIndex = CurrIndex; + SameTileDispCount = 1; + SameTileDispNum = XDp_TxGetDispIdTdtNumTiles(CurrTdt); + + /* Try to find a sink that is part of the same tiled display, + * but has a smaller tile location - the sink with a smallest + * tile location should be ordered first in the topology's sink + * list. */ + for (CmpIndex = (CurrIndex + 1); + (CmpIndex < + InstancePtr->TxInstance.Topology.SinkTotal) + && (SameTileDispCount < SameTileDispNum); + CmpIndex++) { + CmpSink = InstancePtr->TxInstance.Topology.SinkList[ + CmpIndex]; + + Status = XDp_TxGetRemoteTiledDisplayDb( + InstancePtr, CmpEdidExt, + CmpSink->LinkCountTotal, + CmpSink->RelativeAddress, &CmpTdt); + if (Status != XST_SUCCESS) { + /* No TDT data block. */ + continue; + } + + if (!XDp_TxIsSameTileDisplay(CurrTdt, CmpTdt)) { + /* The sink under comparison does not belong to + * the same tiled display. */ + continue; + } + + /* Keep track of the sink with a tile location that + * should be ordered first out of the remaining sinks + * that are part of the same tiled display. */ + CmpTileOrder = XDp_TxGetDispIdTdtTileOrder(CmpTdt); + if (CurrTileOrder > CmpTileOrder) { + CurrTileOrder = CmpTileOrder; + NewIndex = CmpIndex; + SameTileDispCount++; + } + } + + /* If required, swap the current sink with the sink that is a + * part of the same tiled display, but has a smaller tile + * location. */ + if (CurrIndex != NewIndex) { + XDp_TxTopologySwapSinks(InstancePtr, CurrIndex, + NewIndex); + } + } +} + +/******************************************************************************/ +/** + * This function performs a remote DisplayPort Configuration Data (DPCD) read + * by sending a sideband message. In case message is directed at the RX device + * connected immediately to the TX, the message is issued over the AUX channel. + * The read message will be divided into multiple transactions which read a + * maximum of 16 bytes each. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkCountTotal is the number of DisplayPort links from the + * DisplayPort source to the target DisplayPort device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the target DisplayPort device. + * @param DpcdAddress is the starting address to read from the RX device. + * @param BytesToRead is the number of bytes to read. + * @param ReadData is a pointer to the data buffer that will be filled + * with read data. + * + * @return + * - XST_SUCCESS if the DPCD read has successfully completed (has + * been acknowledged). + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for a reply, or an AUX + * request timed out. + * - XST_DATA_LOST if the requested number of BytesToRead does not + * equal that actually received. + * - XST_FAILURE otherwise - if an AUX read or write transaction + * failed, the header or body CRC of the sideband message did not + * match the calculated value, or the a reply was negative + * acknowledged (NACK'ed). + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxRemoteDpcdRead(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u32 DpcdAddress, u32 BytesToRead, u8 *ReadData) +{ + u32 Status; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertNonvoid(ReadData != NULL); + + /* Target RX device is immediately connected to the TX. */ + if (LinkCountTotal == 1) { + Status = XDp_TxAuxRead(InstancePtr, DpcdAddress, BytesToRead, + ReadData); + return Status; + } + + u32 BytesLeft = BytesToRead; + u8 CurrBytesToRead; + + /* Send read message in 16 byte chunks. */ + while (BytesLeft > 0) { + /* Read a maximum of 16 bytes. */ + if (BytesLeft > 16) { + CurrBytesToRead = 16; + } + /* Read the remaining number of bytes as requested. */ + else { + CurrBytesToRead = BytesLeft; + } + + /* Send remote DPCD read sideband message. */ + Status = XDp_TxSendSbMsgRemoteDpcdRead(InstancePtr, + LinkCountTotal, RelativeAddress, DpcdAddress, + CurrBytesToRead, ReadData); + if (Status != XST_SUCCESS) { + return Status; + } + + /* Previous DPCD read was 16 bytes; prepare for next read. */ + if (BytesLeft > 16) { + BytesLeft -= 16; + DpcdAddress += 16; + ReadData += 16; + } + /* Last DPCD read. */ + else { + BytesLeft = 0; + } + } + + return Status; +} + +/******************************************************************************/ +/** + * This function performs a remote DisplayPort Configuration Data (DPCD) write + * by sending a sideband message. In case message is directed at the RX device + * connected immediately to the TX, the message is issued over the AUX channel. + * The write message will be divided into multiple transactions which write a + * maximum of 16 bytes each. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkCountTotal is the number of DisplayPort links from the + * DisplayPort source to the target DisplayPort device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the target DisplayPort device. + * @param DpcdAddress is the starting address to write to the RX device. + * @param BytesToWrite is the number of bytes to write. + * @param WriteData is a pointer to a buffer which will be used as the + * data source for the write. + * + * @return + * - XST_SUCCESS if the DPCD write has successfully completed (has + * been acknowledged). + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for a reply, or an AUX + * request timed out. + * - XST_DATA_LOST if the requested number of BytesToWrite does not + * equal that actually received. + * - XST_FAILURE otherwise - if an AUX read or write transaction + * failed, the header or body CRC of the sideband message did not + * match the calculated value, or the a reply was negative + * acknowledged (NACK'ed). + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxRemoteDpcdWrite(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u32 DpcdAddress, u32 BytesToWrite, u8 *WriteData) +{ + u32 Status; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertNonvoid(WriteData != NULL); + + /* Target RX device is immediately connected to the TX. */ + if (LinkCountTotal == 1) { + Status = XDp_TxAuxWrite(InstancePtr, DpcdAddress, BytesToWrite, + WriteData); + return Status; + } + + u32 BytesLeft = BytesToWrite; + u8 CurrBytesToWrite; + + /* Send write message in 16 byte chunks. */ + while (BytesLeft > 0) { + /* Write a maximum of 16 bytes. */ + if (BytesLeft > 16) { + CurrBytesToWrite = 16; + } + /* Write the remaining number of bytes as requested. */ + else { + CurrBytesToWrite = BytesLeft; + } + + /* Send remote DPCD write sideband message. */ + Status = XDp_TxSendSbMsgRemoteDpcdWrite(InstancePtr, + LinkCountTotal, RelativeAddress, DpcdAddress, + CurrBytesToWrite, WriteData); + if (Status != XST_SUCCESS) { + return Status; + } + + /* Previous DPCD write was 16 bytes; prepare for next read. */ + if (BytesLeft > 16) { + BytesLeft -= 16; + DpcdAddress += 16; + WriteData += 16; + } + /* Last DPCD write. */ + else { + BytesLeft = 0; + } + } + + return Status; +} + +/******************************************************************************/ +/** + * This function performs a remote I2C read by sending a sideband message. In + * case message is directed at the RX device connected immediately to the TX, + * the message is sent over the AUX channel. The read message will be divided + * into multiple transactions which read a maximum of 16 bytes each. The segment + * pointer is automatically incremented and the offset is calibrated as needed. + * E.g. For an overall offset of: + * - 128, an I2C read is done on segptr=0; offset=128. + * - 256, an I2C read is done on segptr=1; offset=0. + * - 384, an I2C read is done on segptr=1; offset=128. + * - 512, an I2C read is done on segptr=2; offset=0. + * - etc. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkCountTotal is the number of DisplayPort links from the + * DisplayPort source to the target DisplayPort device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the target DisplayPort device. + * @param IicAddress is the address on the I2C bus of the target device. + * @param Offset is the offset at the specified address of the targeted + * I2C device that the read will start from. + * @param BytesToRead is the number of bytes to read. + * @param ReadData is a pointer to a buffer that will be filled with the + * I2C read data. + * + * @return + * - XST_SUCCESS if the I2C read has successfully completed with no + * errors. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for a reply, or an AUX + * request timed out. + * - XST_DATA_LOST if the requested number of BytesToRead does not + * equal that actually received. + * - XST_FAILURE otherwise - if an AUX read or write transaction + * failed, the header or body CRC of the sideband message did not + * match the calculated value, or the a reply was negative + * acknowledged (NACK'ed). + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxRemoteIicRead(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 IicAddress, u16 Offset, u16 BytesToRead, + u8 *ReadData) +{ + u32 Status; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertNonvoid(ReadData != NULL); + + /* Target RX device is immediately connected to the TX. */ + if (LinkCountTotal == 1) { + Status = XDp_TxIicRead(InstancePtr, IicAddress, Offset, + BytesToRead, ReadData); + return Status; + } + + u8 SegPtr; + u16 NumBytesLeftInSeg; + u16 BytesLeft = BytesToRead; + u8 CurrBytesToRead; + + /* Reposition based on a segment length of 256 bytes. */ + SegPtr = 0; + if (Offset > 255) { + SegPtr += Offset / 256; + Offset %= 256; + } + NumBytesLeftInSeg = 256 - Offset; + + /* Set the segment pointer to 0. */ + Status = XDp_TxRemoteIicWrite(InstancePtr, LinkCountTotal, + RelativeAddress, XDP_SEGPTR_ADDR, 1, &SegPtr); + if (Status != XST_SUCCESS) { + return Status; + } + + /* Send I2C read message in 16 byte chunks. */ + while (BytesLeft > 0) { + /* Read a maximum of 16 bytes. */ + if ((NumBytesLeftInSeg >= 16) && (BytesLeft >= 16)) { + CurrBytesToRead = 16; + } + /* Read the remaining number of bytes as requested. */ + else if (NumBytesLeftInSeg >= BytesLeft) { + CurrBytesToRead = BytesLeft; + } + /* Read the remaining data in the current segment boundary. */ + else { + CurrBytesToRead = NumBytesLeftInSeg; + } + + /* Send remote I2C read sideband message. */ + Status = XDp_TxSendSbMsgRemoteIicRead(InstancePtr, + LinkCountTotal, RelativeAddress, IicAddress, Offset, + BytesLeft, ReadData); + if (Status != XST_SUCCESS) { + return Status; + } + + /* Previous I2C read was 16 bytes; prepare for next read. */ + if (BytesLeft > CurrBytesToRead) { + BytesLeft -= CurrBytesToRead; + Offset += CurrBytesToRead; + ReadData += CurrBytesToRead; + NumBytesLeftInSeg -= CurrBytesToRead; + } + /* Last I2C read. */ + else { + BytesLeft = 0; + } + + /* Increment the segment pointer to access more I2C address + * space. */ + if ((NumBytesLeftInSeg == 0) && (BytesLeft > 0)) { + SegPtr++; + Offset %= 256; + NumBytesLeftInSeg = 256; + + Status = XDp_TxRemoteIicWrite(InstancePtr, + LinkCountTotal, RelativeAddress, + XDP_SEGPTR_ADDR, 1, &SegPtr); + if (Status != XST_SUCCESS) { + return Status; + } + } + } + + /* Reset the segment pointer to 0. */ + SegPtr = 0; + Status = XDp_TxRemoteIicWrite(InstancePtr, LinkCountTotal, + RelativeAddress, XDP_SEGPTR_ADDR, 1, &SegPtr); + + return Status; +} + +/******************************************************************************/ +/** + * This function performs a remote I2C write by sending a sideband message. In + * case message is directed at the RX device connected immediately to the TX, + * the message is sent over the AUX channel. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkCountTotal is the number of DisplayPort links from the + * DisplayPort source to the target DisplayPort device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the target DisplayPort device. + * @param IicAddress is the address on the I2C bus of the target device. + * @param BytesToWrite is the number of bytes to write. + * @param WriteData is a pointer to a buffer which will be used as the + * data source for the write. + * + * @return + * - XST_SUCCESS if the I2C write has successfully completed with + * no errors. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for a reply, or an AUX + * request timed out. + * - XST_DATA_LOST if the requested number of BytesToWrite does not + * equal that actually received. + * - XST_FAILURE otherwise - if an AUX read or write transaction + * failed, the header or body CRC of the sideband message did not + * match the calculated value, or the a reply was negative + * acknowledged (NACK'ed). + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxRemoteIicWrite(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 IicAddress, u8 BytesToWrite, + u8 *WriteData) +{ + u32 Status; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertNonvoid(WriteData != NULL); + + /* Target RX device is immediately connected to the TX. */ + if (LinkCountTotal == 1) { + Status = XDp_TxIicWrite(InstancePtr, IicAddress, BytesToWrite, + WriteData); + } + /* Send remote I2C sideband message. */ + else { + Status = XDp_TxSendSbMsgRemoteIicWrite(InstancePtr, + LinkCountTotal, RelativeAddress, IicAddress, + BytesToWrite, WriteData); + } + + return Status; +} + +/******************************************************************************/ +/** + * This function will allocate bandwidth for all enabled stream. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the payload ID tables were successfully updated + * with the new allocation. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for a reply, waiting for + * the payload ID table to be cleared or updated, or an AUX + * request timed out. + * - XST_BUFFER_TOO_SMALL if there is not enough free timeslots in + * the payload ID table for the requested Ts. + * - XST_FAILURE otherwise - if an AUX read or write transaction + * failed, the header or body CRC of a sideband message did not + * match the calculated value, or the a reply was negative + * acknowledged (NACK'ed). + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxAllocatePayloadStreams(XDp *InstancePtr) +{ + u32 Status; + u8 StreamIndex; + XDp_TxMstStream *MstStream; + XDp_TxMainStreamAttributes *MsaConfig; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + + /* Allocate the payload table for each stream in both the DisplayPort TX + * and RX device. */ + for (StreamIndex = 0; StreamIndex < 4; StreamIndex++) { + MstStream = + &InstancePtr->TxInstance.MstStreamConfig[StreamIndex]; + MsaConfig = + &InstancePtr->TxInstance.MsaConfig[StreamIndex]; + + if (XDp_TxMstStreamIsEnabled(InstancePtr, StreamIndex + 1)) { + Status = XDp_TxAllocatePayloadVcIdTable(InstancePtr, + StreamIndex + 1, MsaConfig->TransferUnitSize); + if (Status != XST_SUCCESS) { + return Status; + } + } + } + + /* Generate an ACT event. */ + Status = XDp_TxSendActTrigger(InstancePtr); + if (Status != XST_SUCCESS) { + return Status; + } + + /* Send ALLOCATE_PAYLOAD request. */ + for (StreamIndex = 0; StreamIndex < 4; StreamIndex++) { + MstStream = + &InstancePtr->TxInstance.MstStreamConfig[StreamIndex]; + + if (XDp_TxMstStreamIsEnabled(InstancePtr, StreamIndex + 1)) { + Status = XDp_TxSendSbMsgAllocatePayload(InstancePtr, + MstStream->LinkCountTotal, + MstStream->RelativeAddress, StreamIndex + 1, + MstStream->MstPbn); + if (Status != XST_SUCCESS) { + return Status; + } + } + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will allocate a bandwidth for a virtual channel in the payload + * ID table in both the DisplayPort TX and the downstream DisplayPort devices + * on the path to the target device specified by LinkCountTotal and + * RelativeAddress. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param VcId is the unique virtual channel ID to allocate into the + * payload ID tables. + * @param Ts is the number of timeslots to allocate in the payload ID + * tables. + * + * @return + * - XST_SUCCESS if the payload ID tables were successfully updated + * with the new allocation. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for a reply, or an AUX + * request timed out. + * - XST_BUFFER_TOO_SMALL if there is not enough free timeslots in + * the payload ID table for the requested Ts. + * - XST_FAILURE otherwise - if an AUX read or write transaction + * failed, the header or body CRC of a sideband message did not + * match the calculated value, or the a reply was negative + * acknowledged (NACK'ed). + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxAllocatePayloadVcIdTable(XDp *InstancePtr, u8 VcId, u8 Ts) +{ + u32 Status; + u8 AuxData[3]; + u8 Index; + u8 StartTs = 0; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(VcId >= 0); + Xil_AssertNonvoid((Ts >= 0) && (Ts <= 64)); + + /* Clear the VC payload ID table updated bit. */ + AuxData[0] = 0x1; + Status = XDp_TxAuxWrite(InstancePtr, + XDP_DPCD_PAYLOAD_TABLE_UPDATE_STATUS, 1, AuxData); + if (Status != XST_SUCCESS) { + /* The AUX write transaction failed. */ + return Status; + } + + if (VcId != 0) { + /* Find next available timeslot. */ + Status = XDp_TxGetFirstAvailableTs(InstancePtr, &StartTs); + if (Status != XST_SUCCESS) { + /* The AUX read transaction failed. */ + return Status; + } + + /* Check that there are enough time slots available. */ + if (((63 - StartTs + 1) < Ts) || + (StartTs == 0)) { + /* Clearing the payload ID table is required to + * re-allocate streams. */ + return XST_BUFFER_TOO_SMALL; + } + } + + /* Allocate timeslots in TX. */ + for (Index = StartTs; Index < (StartTs + Ts); Index++) { + XDp_WriteReg(InstancePtr->Config.BaseAddr, + (XDP_TX_VC_PAYLOAD_BUFFER_ADDR + (4 * Index)), VcId); + } + + XDp_WaitUs(InstancePtr, 1000); + + /* Allocate timeslots in sink. */ + + /* Allocate VC with VcId. */ + AuxData[0] = VcId; + /* Start timeslot for VC with VcId. */ + AuxData[1] = StartTs; + /* Timeslot count for VC with VcId. */ + if (VcId == 0) { + AuxData[2] = 0x3F; + } + else { + AuxData[2] = Ts; + } + Status = XDp_TxAuxWrite(InstancePtr, XDP_DPCD_PAYLOAD_ALLOCATE_SET, 3, + AuxData); + if (Status != XST_SUCCESS) { + /* The AUX write transaction failed. */ + return Status; + } + + /* Wait for the VC table to be updated. */ + do { + Status = XDp_TxAuxRead(InstancePtr, + XDP_DPCD_PAYLOAD_TABLE_UPDATE_STATUS, 1, AuxData); + if (Status != XST_SUCCESS) { + /* The AUX read transaction failed. */ + return Status; + } + } while ((AuxData[0] & 0x01) != 0x01); + + XDp_WaitUs(InstancePtr, 1000); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will clear the virtual channel payload ID table in both the + * DisplayPort TX and all downstream DisplayPort devices. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the payload ID tables were successfully + * cleared. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for a reply, or an AUX + * request timed out. + * - XST_FAILURE otherwise - if an AUX read or write transaction + * failed, the header or body CRC of a sideband message did not + * match the calculated value, or the a reply was negative + * acknowledged (NACK'ed). + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxClearPayloadVcIdTable(XDp *InstancePtr) +{ + u32 Status; + u8 Index; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + + Status = XDp_TxAllocatePayloadVcIdTable(InstancePtr, 0, 64); + if (Status != XST_SUCCESS) { + return Status; + } + + /* Send CLEAR_PAYLOAD_ID_TABLE request. */ + Status = XDp_TxSendSbMsgClearPayloadIdTable(InstancePtr); + + return Status; +} + +/******************************************************************************/ +/** + * This function will send a REMOTE_DPCD_WRITE sideband message which will write + * some data to the specified DisplayPort Configuration Data (DPCD) address of a + * downstream DisplayPort device. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkCountTotal is the number of DisplayPort links from the + * DisplayPort source to the target DisplayPort device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the target DisplayPort device. + * @param DpcdAddress is the DPCD address of the target device that data + * will be written to. + * @param BytesToWrite is the number of bytes to write to the specified + * DPCD address. + * @param WriteData is a pointer to a buffer that stores the data to write + * to the DPCD location. + * + * @return + * - XST_SUCCESS if the reply to the sideband message was + * successfully obtained and it indicates an acknowledge. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for a reply, or an AUX + * request timed out. + * - XST_FAILURE otherwise - if an AUX read or write transaction + * failed, the header or body CRC of the sideband message did not + * match the calculated value, or the a reply was negative + * acknowledged (NACK'ed). + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxSendSbMsgRemoteDpcdWrite(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u32 DpcdAddress, u32 BytesToWrite, u8 *WriteData) +{ + u32 Status; + XDp_SidebandMsg Msg; + XDp_SidebandReply SbMsgReply; + u8 Index; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertNonvoid(DpcdAddress <= 0xFFFFF); + Xil_AssertNonvoid(BytesToWrite <= 0xFFFFF); + Xil_AssertNonvoid(WriteData != NULL); + + /* Prepare the sideband message header. */ + Msg.Header.LinkCountTotal = LinkCountTotal - 1; + for (Index = 0; Index < (Msg.Header.LinkCountTotal - 1); Index++) { + Msg.Header.RelativeAddress[Index] = RelativeAddress[Index]; + } + Msg.Header.LinkCountRemaining = Msg.Header.LinkCountTotal - 1; + Msg.Header.BroadcastMsg = 0; + Msg.Header.PathMsg = 0; + Msg.Header.MsgBodyLength = 6 + BytesToWrite; + Msg.Header.StartOfMsgTransaction = 1; + Msg.Header.EndOfMsgTransaction = 1; + Msg.Header.MsgSequenceNum = 0; + Msg.Header.Crc = XDp_TxCrc4CalculateHeader(&Msg.Header); + + /* Prepare the sideband message body. */ + Msg.Body.MsgData[0] = XDP_TX_SBMSG_REMOTE_DPCD_WRITE; + Msg.Body.MsgData[1] = (RelativeAddress[Msg.Header.LinkCountTotal - 1] << + 4) | (DpcdAddress >> 16); + Msg.Body.MsgData[2] = (DpcdAddress & 0x0000FF00) >> 8; + Msg.Body.MsgData[3] = (DpcdAddress & 0x000000FF); + Msg.Body.MsgData[4] = BytesToWrite; + for (Index = 0; Index < BytesToWrite; Index++) { + Msg.Body.MsgData[5 + Index] = WriteData[Index]; + } + Msg.Body.MsgDataLength = Msg.Header.MsgBodyLength - 1; + Msg.Body.Crc = XDp_TxCrc8CalculateBody(&Msg.Body); + + /* Submit the REMOTE_DPCD_WRITE transaction message request. */ + Status = XDp_TxSendSbMsg(InstancePtr, &Msg); + if (Status != XST_SUCCESS) { + /* The AUX write transaction used to send the sideband message + * failed. */ + return Status; + } + Status = XDp_TxReceiveSbMsg(InstancePtr, &SbMsgReply); + + return Status; +} + +/******************************************************************************/ +/** + * This function will send a REMOTE_DPCD_READ sideband message which will read + * from the specified DisplayPort Configuration Data (DPCD) address of a + * downstream DisplayPort device. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkCountTotal is the number of DisplayPort links from the + * DisplayPort source to the target DisplayPort device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the target DisplayPort device. + * @param DpcdAddress is the DPCD address of the target device that data + * will be read from. + * @param BytesToRead is the number of bytes to read from the specified + * DPCD address. + * @param ReadData is a pointer to a buffer that will be filled with the + * DPCD read data. + * + * @return + * - XST_SUCCESS if the reply to the sideband message was + * successfully obtained and it indicates an acknowledge. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for a reply, or an AUX + * request timed out. + * - XST_DATA_LOST if the requested number of BytesToRead does not + * equal that actually received. + * - XST_FAILURE otherwise - if an AUX read or write transaction + * failed, the header or body CRC of the sideband message did not + * match the calculated value, or the a reply was negative + * acknowledged (NACK'ed). + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxSendSbMsgRemoteDpcdRead(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u32 DpcdAddress, u32 BytesToRead, u8 *ReadData) +{ + u32 Status; + XDp_SidebandMsg Msg; + XDp_SidebandReply SbMsgReply; + u8 Index; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertNonvoid(DpcdAddress <= 0xFFFFF); + Xil_AssertNonvoid(BytesToRead <= 0xFFFFF); + Xil_AssertNonvoid(ReadData != NULL); + + /* Prepare the sideband message header. */ + Msg.Header.LinkCountTotal = LinkCountTotal - 1; + for (Index = 0; Index < (Msg.Header.LinkCountTotal - 1); Index++) { + Msg.Header.RelativeAddress[Index] = RelativeAddress[Index]; + } + Msg.Header.LinkCountRemaining = Msg.Header.LinkCountTotal - 1; + Msg.Header.BroadcastMsg = 0; + Msg.Header.PathMsg = 0; + Msg.Header.MsgBodyLength = 6; + Msg.Header.StartOfMsgTransaction = 1; + Msg.Header.EndOfMsgTransaction = 1; + Msg.Header.MsgSequenceNum = 0; + Msg.Header.Crc = XDp_TxCrc4CalculateHeader(&Msg.Header); + + /* Prepare the sideband message body. */ + Msg.Body.MsgData[0] = XDP_TX_SBMSG_REMOTE_DPCD_READ; + Msg.Body.MsgData[1] = (RelativeAddress[Msg.Header.LinkCountTotal - 1] << + 4) | (DpcdAddress >> 16); + Msg.Body.MsgData[2] = (DpcdAddress & 0x0000FF00) >> 8; + Msg.Body.MsgData[3] = (DpcdAddress & 0x000000FF); + Msg.Body.MsgData[4] = BytesToRead; + Msg.Body.MsgDataLength = Msg.Header.MsgBodyLength - 1; + Msg.Body.Crc = XDp_TxCrc8CalculateBody(&Msg.Body); + + /* Submit the REMOTE_DPCD_READ transaction message request. */ + Status = XDp_TxSendSbMsg(InstancePtr, &Msg); + if (Status != XST_SUCCESS) { + /* The AUX write transaction used to send the sideband message + * failed. */ + return Status; + } + Status = XDp_TxReceiveSbMsg(InstancePtr, &SbMsgReply); + if (Status != XST_SUCCESS) { + /* Either the reply indicates a NACK, an AUX read or write + * transaction failed, there was a time out waiting for a reply, + * or a CRC check failed. */ + return Status; + } + + /* Collect body data into an array. */ + for (Index = 3; Index < SbMsgReply.Length; Index++) { + ReadData[Index - 3] = SbMsgReply.Data[Index]; + } + + /* The number of bytes actually read does not match that requested. */ + if (Index < BytesToRead) { + return XST_DATA_LOST; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will send a REMOTE_I2C_WRITE sideband message which will write + * to the specified I2C address of a downstream DisplayPort device. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkCountTotal is the number of DisplayPort links from the + * DisplayPort source to the target DisplayPort device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the target DisplayPort device. + * @param IicDeviceId is the address on the I2C bus of the target device. + * @param BytesToWrite is the number of bytes to write to the I2C address. + * @param WriteData is a pointer to a buffer that will be written. + * + * @return + * - XST_SUCCESS if the reply to the sideband message was + * successfully obtained and it indicates an acknowledge. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for a reply, or an AUX + * request timed out. + * - XST_FAILURE otherwise - if an AUX read or write transaction + * failed, the header or body CRC of the sideband message did not + * match the calculated value, or the a reply was negative + * acknowledged (NACK'ed). + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxSendSbMsgRemoteIicWrite(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 IicDeviceId, u8 BytesToWrite, u8 *WriteData) +{ + u32 Status; + XDp_SidebandMsg Msg; + XDp_SidebandReply SbMsgReply; + u8 Index; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertNonvoid(IicDeviceId <= 0xFF); + Xil_AssertNonvoid(BytesToWrite <= 0xFF); + Xil_AssertNonvoid(WriteData != NULL); + + /* Prepare the sideband message header. */ + Msg.Header.LinkCountTotal = LinkCountTotal - 1; + for (Index = 0; Index < (Msg.Header.LinkCountTotal - 1); Index++) { + Msg.Header.RelativeAddress[Index] = RelativeAddress[Index]; + } + Msg.Header.LinkCountRemaining = Msg.Header.LinkCountTotal - 1; + Msg.Header.BroadcastMsg = 0; + Msg.Header.PathMsg = 0; + Msg.Header.MsgBodyLength = 5 + BytesToWrite; + Msg.Header.StartOfMsgTransaction = 1; + Msg.Header.EndOfMsgTransaction = 1; + Msg.Header.MsgSequenceNum = 0; + Msg.Header.Crc = XDp_TxCrc4CalculateHeader(&Msg.Header); + + /* Prepare the sideband message body. */ + Msg.Body.MsgData[0] = XDP_TX_SBMSG_REMOTE_I2C_WRITE; + Msg.Body.MsgData[1] = RelativeAddress[Msg.Header.LinkCountTotal - 1] << + 4; + Msg.Body.MsgData[2] = IicDeviceId; /* Write I2C device ID. */ + Msg.Body.MsgData[3] = BytesToWrite; /* Number of bytes to write. */ + for (Index = 0; Index < BytesToWrite; Index++) { + Msg.Body.MsgData[Index + 4] = WriteData[Index]; + } + Msg.Body.MsgDataLength = Msg.Header.MsgBodyLength - 1; + Msg.Body.Crc = XDp_TxCrc8CalculateBody(&Msg.Body); + + /* Submit the REMOTE_I2C_WRITE transaction message request. */ + Status = XDp_TxSendSbMsg(InstancePtr, &Msg); + if (Status != XST_SUCCESS) { + /* The AUX write transaction used to send the sideband message + * failed. */ + return Status; + } + Status = XDp_TxReceiveSbMsg(InstancePtr, &SbMsgReply); + + return Status; +} + +/******************************************************************************/ +/** + * This function will send a REMOTE_I2C_READ sideband message which will read + * from the specified I2C address of a downstream DisplayPort device. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkCountTotal is the number of DisplayPort links from the + * DisplayPort source to the target DisplayPort device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the target DisplayPort device. + * @param IicDeviceId is the address on the I2C bus of the target device. + * @param Offset is the offset at the specified address of the targeted + * I2C device that the read will start from. + * @param BytesToRead is the number of bytes to read from the I2C address. + * @param ReadData is a pointer to a buffer that will be filled with the + * I2C read data. + * + * @return + * - XST_SUCCESS if the reply to the sideband message was + * successfully obtained and it indicates an acknowledge. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for a reply, or an AUX + * request timed out. + * - XST_DATA_LOST if the requested number of BytesToRead does not + * equal that actually received. + * - XST_FAILURE otherwise - if an AUX read or write transaction + * failed, the header or body CRC of the sideband message did not + * match the calculated value, or the a reply was negative + * acknowledged (NACK'ed). + * + * @note None. + * +*******************************************************************************/ +u32 XDp_TxSendSbMsgRemoteIicRead(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 IicDeviceId, u8 Offset, u8 BytesToRead, + u8 *ReadData) +{ + u32 Status; + XDp_SidebandMsg Msg; + XDp_SidebandReply SbMsgReply; + u8 Index; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertNonvoid(IicDeviceId <= 0xFF); + Xil_AssertNonvoid(BytesToRead <= 0xFF); + Xil_AssertNonvoid(ReadData != NULL); + + /* Prepare the sideband message header. */ + Msg.Header.LinkCountTotal = LinkCountTotal - 1; + for (Index = 0; Index < (Msg.Header.LinkCountTotal - 1); Index++) { + Msg.Header.RelativeAddress[Index] = RelativeAddress[Index]; + } + Msg.Header.LinkCountRemaining = Msg.Header.LinkCountTotal - 1; + Msg.Header.BroadcastMsg = 0; + Msg.Header.PathMsg = 0; + Msg.Header.MsgBodyLength = 9; + Msg.Header.StartOfMsgTransaction = 1; + Msg.Header.EndOfMsgTransaction = 1; + Msg.Header.MsgSequenceNum = 0; + Msg.Header.Crc = XDp_TxCrc4CalculateHeader(&Msg.Header); + + /* Prepare the sideband message body. */ + Msg.Body.MsgData[0] = XDP_TX_SBMSG_REMOTE_I2C_READ; + Msg.Body.MsgData[1] = (RelativeAddress[Msg.Header.LinkCountTotal - 1] << + 4) | 1; + Msg.Body.MsgData[2] = IicDeviceId; /* Write I2C device ID. */ + Msg.Body.MsgData[3] = 1; /* Number of bytes to write. */ + Msg.Body.MsgData[4] = Offset; + Msg.Body.MsgData[5] = (0 << 4) | 0; + Msg.Body.MsgData[6] = IicDeviceId; /* Read I2C device ID. */ + Msg.Body.MsgData[7] = BytesToRead; + Msg.Body.MsgDataLength = Msg.Header.MsgBodyLength - 1; + Msg.Body.Crc = XDp_TxCrc8CalculateBody(&Msg.Body); + + /* Submit the REMOTE_I2C_READ transaction message request. */ + Status = XDp_TxSendSbMsg(InstancePtr, &Msg); + if (Status != XST_SUCCESS) { + /* The AUX write transaction used to send the sideband message + * failed. */ + return Status; + } + Status = XDp_TxReceiveSbMsg(InstancePtr, &SbMsgReply); + if (Status != XST_SUCCESS) { + /* Either the reply indicates a NACK, an AUX read or write + * transaction failed, there was a time out waiting for a reply, + * or a CRC check failed. */ + return Status; + } + + /* Collect body data into an array. */ + for (Index = 3; Index < SbMsgReply.Length; Index++) { + ReadData[Index - 3] = SbMsgReply.Data[Index]; + } + + /* The number of bytes actually read does not match that requested. */ + if (Index < BytesToRead) { + return XST_DATA_LOST; + } + + return Status; +} + +/******************************************************************************/ +/** + * This function will send a LINK_ADDRESS sideband message to a target + * DisplayPort branch device. It is used to determine the resources available + * for that device and some device information for each of the ports connected + * to the branch device. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkCountTotal is the number of DisplayPort links from the + * DisplayPort source to the target DisplayPort branch device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the target DisplayPort branch device. + * @param DeviceInfo is a pointer to the device information structure + * whose contents will be filled in with the information obtained + * by the LINK_ADDRESS sideband message. + * + * @return + * - XST_SUCCESS if the reply to the sideband message was + * successfully obtained and it indicates an acknowledge. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for a reply, or an AUX + * request timed out. + * - XST_FAILURE otherwise - if an AUX read or write transaction + * failed, the header or body CRC of the sideband message did not + * match the calculated value, or the a reply was negative + * acknowledged (NACK'ed). + * + * @note The contents of the DeviceInfo structure will be modified with + * the information obtained from the LINK_ADDRESS sideband message + * reply. + * +*******************************************************************************/ +u32 XDp_TxSendSbMsgLinkAddress(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, XDp_TxSbMsgLinkAddressReplyDeviceInfo *DeviceInfo) +{ + u32 Status; + XDp_SidebandMsg Msg; + XDp_SidebandReply SbMsgReply; + u8 Index; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertNonvoid(DeviceInfo != NULL); + + /* Prepare the sideband message header. */ + Msg.Header.LinkCountTotal = LinkCountTotal; + for (Index = 0; Index < (LinkCountTotal - 1); Index++) { + Msg.Header.RelativeAddress[Index] = RelativeAddress[Index]; + } + Msg.Header.LinkCountRemaining = Msg.Header.LinkCountTotal - 1; + Msg.Header.BroadcastMsg = 0; + Msg.Header.PathMsg = 0; + Msg.Header.MsgBodyLength = 2; + Msg.Header.StartOfMsgTransaction = 1; + Msg.Header.EndOfMsgTransaction = 1; + Msg.Header.MsgSequenceNum = 0; + Msg.Header.Crc = XDp_TxCrc4CalculateHeader(&Msg.Header); + + /* Prepare the sideband message body. */ + Msg.Body.MsgData[0] = XDP_TX_SBMSG_LINK_ADDRESS; + Msg.Body.MsgDataLength = Msg.Header.MsgBodyLength - 1; + Msg.Body.Crc = XDp_TxCrc8CalculateBody(&Msg.Body); + + /* Submit the LINK_ADDRESS transaction message request. */ + Status = XDp_TxSendSbMsg(InstancePtr, &Msg); + if (Status != XST_SUCCESS) { + /* The AUX write transaction used to send the sideband message + * failed. */ + return Status; + } + + Status = XDp_TxReceiveSbMsg(InstancePtr, &SbMsgReply); + if (Status != XST_SUCCESS) { + /* Either the reply indicates a NACK, an AUX read or write + * transaction failed, there was a time out waiting for a reply, + * or a CRC check failed. */ + return Status; + } + XDp_TxGetDeviceInfoFromSbMsgLinkAddress(&SbMsgReply, DeviceInfo); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will send an ENUM_PATH_RESOURCES sideband message which will + * determine the available payload bandwidth number (PBN) for a path to a target + * device. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkCountTotal is the number of DisplayPort links from the + * DisplayPort source to the target DisplayPort device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the target DisplayPort device. + * @param AvailPbn is a pointer to the available PBN of the path whose + * value will be filled in by this function. + * @param FullPbn is a pointer to the total PBN of the path whose value + * will be filled in by this function. + * + * @return + * - XST_SUCCESS if the reply to the sideband message was + * successfully obtained and it indicates an acknowledge. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for a reply, or an AUX + * request timed out. + * - XST_FAILURE otherwise - if an AUX read or write transaction + * failed, the header or body CRC of the sideband message did not + * match the calculated value, or the a reply was negative + * acknowledged (NACK'ed). + * + * @note ENUM_PATH_RESOURCES is a path message that will be serviced by + * all downstream DisplayPort devices connecting the DisplayPort TX + * and the target device. + * @note AvailPbn will be modified with the available PBN from the reply. + * @note FullPbn will be modified with the total PBN of the path from the + * reply. + * +*******************************************************************************/ +u32 XDp_TxSendSbMsgEnumPathResources(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u16 *AvailPbn, u16 *FullPbn) +{ + u32 Status; + XDp_SidebandMsg Msg; + XDp_SidebandReply SbMsgReply; + u8 Index; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertNonvoid(AvailPbn != NULL); + Xil_AssertNonvoid(FullPbn != NULL); + + /* Prepare the sideband message header. */ + Msg.Header.LinkCountTotal = LinkCountTotal - 1; + for (Index = 0; Index < (LinkCountTotal - 1); Index++) { + Msg.Header.RelativeAddress[Index] = RelativeAddress[Index]; + } + Msg.Header.LinkCountRemaining = Msg.Header.LinkCountTotal - 1; + Msg.Header.BroadcastMsg = 0; + Msg.Header.PathMsg = 1; + Msg.Header.MsgBodyLength = 3; + Msg.Header.StartOfMsgTransaction = 1; + Msg.Header.EndOfMsgTransaction = 1; + Msg.Header.MsgSequenceNum = 0; + Msg.Header.Crc = XDp_TxCrc4CalculateHeader(&Msg.Header); + + /* Prepare the sideband message body. */ + Msg.Body.MsgData[0] = XDP_TX_SBMSG_ENUM_PATH_RESOURCES; + Msg.Body.MsgData[1] = (RelativeAddress[Msg.Header.LinkCountTotal - 1] << + 4); + Msg.Body.MsgDataLength = Msg.Header.MsgBodyLength - 1; + Msg.Body.Crc = XDp_TxCrc8CalculateBody(&Msg.Body); + + /* Submit the LINK_ADDRESS transaction message request. */ + Status = XDp_TxSendSbMsg(InstancePtr, &Msg); + if (Status != XST_SUCCESS) { + /* The AUX write transaction used to send the sideband message + * failed. */ + return Status; + } + Status = XDp_TxReceiveSbMsg(InstancePtr, &SbMsgReply); + if (Status != XST_SUCCESS) { + /* Either the reply indicates a NACK, an AUX read or write + * transaction failed, there was a time out waiting for a reply, + * or a CRC check failed. */ + return Status; + } + + *AvailPbn = ((SbMsgReply.Data[4] << 8) | SbMsgReply.Data[5]); + *FullPbn = ((SbMsgReply.Data[2] << 8) | SbMsgReply.Data[3]); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will send an ALLOCATE_PAYLOAD sideband message which will + * allocate bandwidth for a virtual channel in the payload ID tables of the + * downstream devices connecting the DisplayPort TX to the target device. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkCountTotal is the number of DisplayPort links from the + * DisplayPort source to the target DisplayPort device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the target DisplayPort device. + * @param VcId is the unique virtual channel ID to allocate into the + * payload ID tables. + * @param Pbn is the payload bandwidth number that determines how much + * bandwidth will be allocated for the virtual channel. + * + * @return + * - XST_SUCCESS if the reply to the sideband message was + * successfully obtained and it indicates an acknowledge. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for a reply, or an AUX + * request timed out. + * - XST_FAILURE otherwise - if an AUX read or write transaction + * failed, the header or body CRC of the sideband message did not + * match the calculated value, or the a reply was negative + * acknowledged (NACK'ed). + * + * @note ALLOCATE_PAYLOAD is a path message that will be serviced by all + * downstream DisplayPort devices connecting the DisplayPort TX and + * the target device. + * +*******************************************************************************/ +u32 XDp_TxSendSbMsgAllocatePayload(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 VcId, u16 Pbn) +{ + u32 Status; + XDp_SidebandMsg Msg; + XDp_SidebandReply SbMsgReply; + u8 Index; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertNonvoid(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertNonvoid(VcId > 0); + Xil_AssertNonvoid(Pbn > 0); + + /* Prepare the sideband message header. */ + Msg.Header.LinkCountTotal = LinkCountTotal - 1; + for (Index = 0; Index < (LinkCountTotal - 1); Index++) { + Msg.Header.RelativeAddress[Index] = RelativeAddress[Index]; + } + Msg.Header.LinkCountRemaining = Msg.Header.LinkCountTotal - 1; + Msg.Header.BroadcastMsg = 0; + Msg.Header.PathMsg = 1; + Msg.Header.MsgBodyLength = 6; + Msg.Header.StartOfMsgTransaction = 1; + Msg.Header.EndOfMsgTransaction = 1; + Msg.Header.MsgSequenceNum = 0; + Msg.Header.Crc = XDp_TxCrc4CalculateHeader(&Msg.Header); + + /* Prepare the sideband message body. */ + Msg.Body.MsgData[0] = XDP_TX_SBMSG_ALLOCATE_PAYLOAD; + Msg.Body.MsgData[1] = (RelativeAddress[Msg.Header.LinkCountTotal - 1] << + 4); + Msg.Body.MsgData[2] = VcId; + Msg.Body.MsgData[3] = (Pbn >> 8); + Msg.Body.MsgData[4] = (Pbn & 0xFFFFFFFF); + Msg.Body.MsgDataLength = Msg.Header.MsgBodyLength - 1; + Msg.Body.Crc = XDp_TxCrc8CalculateBody(&Msg.Body); + + /* Submit the ALLOCATE_PAYLOAD transaction message request. */ + Status = XDp_TxSendSbMsg(InstancePtr, &Msg); + if (Status != XST_SUCCESS) { + /* The AUX write transaction used to send the sideband message + * failed. */ + return Status; + } + Status = XDp_TxReceiveSbMsg(InstancePtr, &SbMsgReply); + + return Status; +} + +/******************************************************************************/ +/** + * This function will send a CLEAR_PAYLOAD_ID_TABLE sideband message which will + * de-allocate all virtual channel payload ID tables. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the reply to the sideband message was + * successfully obtained and it indicates an acknowledge. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for a reply, or an AUX + * request timed out. + * - XST_FAILURE otherwise - if an AUX read or write transaction + * failed, the header or body CRC of the sideband message did not + * match the calculated value, or the a reply was negative + * acknowledged (NACK'ed). + * + * @note CLEAR_PAYLOAD_ID_TABLE is a broadcast message sent to all + * downstream devices. + * +*******************************************************************************/ +u32 XDp_TxSendSbMsgClearPayloadIdTable(XDp *InstancePtr) +{ + u32 Status; + XDp_SidebandMsg Msg; + XDp_SidebandReply SbMsgReply; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + + /* Prepare the sideband message header. */ + Msg.Header.LinkCountTotal = 1; + Msg.Header.LinkCountRemaining = 6; + Msg.Header.BroadcastMsg = 1; + Msg.Header.PathMsg = 1; + Msg.Header.MsgBodyLength = 2; + Msg.Header.StartOfMsgTransaction = 1; + Msg.Header.EndOfMsgTransaction = 1; + Msg.Header.MsgSequenceNum = 0; + Msg.Header.Crc = XDp_TxCrc4CalculateHeader(&Msg.Header); + + /* Prepare the sideband message body. */ + Msg.Body.MsgData[0] = XDP_TX_SBMSG_CLEAR_PAYLOAD_ID_TABLE; + Msg.Body.MsgDataLength = Msg.Header.MsgBodyLength - 1; + Msg.Body.Crc = XDp_TxCrc8CalculateBody(&Msg.Body); + + /* Submit the CLEAR_PAYLOAD_ID_TABLE transaction message request. */ + Status = XDp_TxSendSbMsg(InstancePtr, &Msg); + if (Status != XST_SUCCESS) { + /* The AUX write transaction used to send the sideband message + * failed. */ + return Status; + } + Status = XDp_TxReceiveSbMsg(InstancePtr, &SbMsgReply); + + return Status; +} + +/******************************************************************************/ +/** + * This function will write a global unique identifier (GUID) to the target + * DisplayPort device. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkCountTotal is the number of DisplayPort links from the + * DisplayPort source to the target device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the target device. + * @param Guid is a the GUID to write to the target device. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxWriteGuid(XDp *InstancePtr, u8 LinkCountTotal, u8 *RelativeAddress, + u32 Guid[4]) +{ + u8 AuxData[16]; + u8 Index; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid(LinkCountTotal > 0); + Xil_AssertVoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertVoid((Guid[0] != 0) || (Guid[1] != 0) || (Guid[2] != 0) || + (Guid[3] != 0)); + + memset(AuxData, 0, 16); + for (Index = 0; Index < 16; Index++) { + AuxData[Index] = (Guid[Index / 4] >> ((3 - (Index % 4)) * 8)) & + 0xFF; + } + + XDp_TxRemoteDpcdWrite(InstancePtr, LinkCountTotal, RelativeAddress, + XDP_DPCD_GUID, 16, AuxData); +} + +/******************************************************************************/ +/** + * This function will obtain the global unique identifier (GUID) for the target + * DisplayPort device. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkCountTotal is the number of DisplayPort links from the + * DisplayPort source to the target device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the target device. + * @param Guid is a pointer to the GUID that will store the existing GUID + * of the target device. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxGetGuid(XDp *InstancePtr, u8 LinkCountTotal, u8 *RelativeAddress, + u32 *Guid) +{ + u8 Index; + u8 Data[16]; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid(LinkCountTotal > 0); + Xil_AssertVoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertVoid(Guid != NULL); + + XDp_TxRemoteDpcdRead(InstancePtr, LinkCountTotal, RelativeAddress, + XDP_DPCD_GUID, 16, Data); + + memset(Guid, 0, 16); + for (Index = 0; Index < 16; Index++) { + Guid[Index / 4] <<= 8; + Guid[Index / 4] |= Data[Index]; + } +} + +/******************************************************************************/ +/** + * This function will check whether or not a DisplayPort device has a global + * unique identifier (GUID). If it doesn't (the GUID is all zeros), then it will + * issue one. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param LinkCountTotal is the number of DisplayPort links from the + * DisplayPort source to the target device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the target device. + * @param Topology is a pointer to the downstream topology. + * @param Guid is a pointer to the GUID that will store the new, or + * existing GUID for the target device. + * + * @return None. + * + * @note The GUID will be issued from the GuidTable. + * +*******************************************************************************/ +static void XDp_TxIssueGuid(XDp *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, XDp_TxTopology *Topology, u32 *Guid) +{ + XDp_TxGetGuid(InstancePtr, LinkCountTotal, RelativeAddress, Guid); + if ((Guid[0] == 0) && (Guid[1] == 0) && (Guid[2] == 0) && + (Guid[3] == 0)) { + XDp_TxWriteGuid(InstancePtr, LinkCountTotal, RelativeAddress, + GuidTable[Topology->NodeTotal]); + + XDp_TxGetGuid(InstancePtr, LinkCountTotal, RelativeAddress, + Guid); + } +} + +/******************************************************************************/ +/** + * This function will copy the branch device's information into the topology's + * node table. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param DeviceInfo is a pointer to the device information of the branch + * device to add to the list. + * @param LinkCountTotal is the number of DisplayPort links from the + * DisplayPort source to the branch device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the branch device. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void XDp_TxAddBranchToList(XDp *InstancePtr, + XDp_TxSbMsgLinkAddressReplyDeviceInfo *DeviceInfo, + u8 LinkCountTotal, u8 *RelativeAddress) +{ + u8 Index; + XDp_TxTopologyNode *TopologyNode; + + /* Add this node to the topology's node list. */ + TopologyNode = &InstancePtr->TxInstance.Topology.NodeTable[ + InstancePtr->TxInstance.Topology.NodeTotal]; + + for (Index = 0; Index < 4; Index++) { + TopologyNode->Guid[Index] = DeviceInfo->Guid[Index]; + } + for (Index = 0; Index < (LinkCountTotal - 1); Index++) { + TopologyNode->RelativeAddress[Index] = RelativeAddress[Index]; + } + TopologyNode->DeviceType = 0x02; + TopologyNode->LinkCountTotal = LinkCountTotal; + TopologyNode->DpcdRev = 0x12; + TopologyNode->MsgCapStatus = 1; + + /* The branch device has been added to the topology node list. */ + InstancePtr->TxInstance.Topology.NodeTotal++; +} + +/******************************************************************************/ +/** + * This function will copy the sink device's information into the topology's + * node table and also add this entry into the topology's sink list. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param SinkDevice is a pointer to the device information of the sink + * device to add to the lists. + * @param LinkCountTotal is the number of DisplayPort links from the + * DisplayPort source to the sink device. + * @param RelativeAddress is the relative address from the DisplayPort + * source to the sink device. + * + * @return None. + * + * @note The sink device is added to both the node and sink list of the + * topology structure. + * +*******************************************************************************/ +static void XDp_TxAddSinkToList(XDp *InstancePtr, + XDp_TxSbMsgLinkAddressReplyPortDetail *SinkDevice, + u8 LinkCountTotal, u8 *RelativeAddress) +{ + u8 Index; + XDp_TxTopology *Topology = &InstancePtr->TxInstance.Topology; + XDp_TxTopologyNode *TopologyNode; + + /* Add this node to the topology's node list. */ + TopologyNode = &Topology->NodeTable[Topology->NodeTotal]; + + /* Copy the GUID of the sink for the new entry in the topology node + * table. */ + for (Index = 0; Index < 4; Index++) { + TopologyNode->Guid[Index] = SinkDevice->Guid[Index]; + } + /* Copy the RAD of the sink for the new entry in the topology node + * table. */ + for (Index = 0; Index < (LinkCountTotal - 2); Index++) { + TopologyNode->RelativeAddress[Index] = RelativeAddress[Index]; + } + TopologyNode->RelativeAddress[Index] = SinkDevice->PortNum; + TopologyNode->DeviceType = SinkDevice->PeerDeviceType; + TopologyNode->LinkCountTotal = LinkCountTotal; + TopologyNode->DpcdRev = SinkDevice->DpcdRev; + TopologyNode->MsgCapStatus = SinkDevice->MsgCapStatus; + + /* Add this node to the sink list by linking it to the appropriate node + * in the topology's node list. */ + Topology->SinkList[Topology->SinkTotal] = TopologyNode; + + /* This node is a sink device, so both the node and sink total are + * incremented. */ + Topology->NodeTotal++; + Topology->SinkTotal++; +} + +/******************************************************************************/ +/** + * This function will fill in a device information structure from data obtained + * by reading the sideband reply from a LINK_ADDRESS sideband message. + * + * @param SbReply is a pointer to the sideband reply structure that stores + * the reply data. + * @param FormatReply is a pointer to the device information structure + * that will filled in with the sideband reply data. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void XDp_TxGetDeviceInfoFromSbMsgLinkAddress(XDp_SidebandReply + *SbReply, XDp_TxSbMsgLinkAddressReplyDeviceInfo *FormatReply) +{ + u8 ReplyIndex = 0; + u8 Index, Index2; + XDp_TxSbMsgLinkAddressReplyPortDetail *PortDetails; + + /* Determine the device information from the sideband message reply + * structure. */ + FormatReply->ReplyType = (SbReply->Data[ReplyIndex] >> 7); + FormatReply->RequestId = (SbReply->Data[ReplyIndex++] & 0x7F); + + memset(FormatReply->Guid, 0, 16); + for (Index = 0; Index < 16; Index++) { + FormatReply->Guid[Index / 4] <<= 8; + FormatReply->Guid[Index / 4] |= SbReply->Data[ReplyIndex++]; + } + + FormatReply->NumPorts = SbReply->Data[ReplyIndex++]; + + /* For each port of the current device, obtain the details. */ + for (Index = 0; Index < FormatReply->NumPorts; Index++) { + PortDetails = &FormatReply->PortDetails[Index]; + + PortDetails->InputPort = (SbReply->Data[ReplyIndex] >> 7); + PortDetails->PeerDeviceType = + ((SbReply->Data[ReplyIndex] & 0x70) >> 4); + PortDetails->PortNum = (SbReply->Data[ReplyIndex++] & 0x0F); + PortDetails->MsgCapStatus = (SbReply->Data[ReplyIndex] >> 7); + PortDetails->DpDevPlugStatus = + ((SbReply->Data[ReplyIndex] & 0x40) >> 6); + + if (PortDetails->InputPort == 0) { + /* Get the port details of the downstream device. */ + PortDetails->LegacyDevPlugStatus = + ((SbReply->Data[ReplyIndex++] & 0x20) >> 5); + PortDetails->DpcdRev = (SbReply->Data[ReplyIndex++]); + + memset(PortDetails->Guid, 0, 16); + for (Index2 = 0; Index2 < 16; Index2++) { + PortDetails->Guid[Index2 / 4] <<= 8; + PortDetails->Guid[Index2 / 4] |= + SbReply->Data[ReplyIndex++]; + } + + PortDetails->NumSdpStreams = + (SbReply->Data[ReplyIndex] >> 4); + PortDetails->NumSdpStreamSinks = + (SbReply->Data[ReplyIndex++] & 0x0F); + } + else { + ReplyIndex++; + } + } +} + +/******************************************************************************/ +/** + * This function will read the payload ID table from the immediate downstream RX + * device and determine what the first available time slot is in the table. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the immediate downstream RX device's payload ID + * table was successfully read (regardless of whether there are + * any available time slots or not). + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if waiting for the the AUX read request to + * read the RX device's payload ID table timed out. + * - XST_FAILURE if the AUX read transaction failed while trying to + * read the RX device's payload ID table. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxGetFirstAvailableTs(XDp *InstancePtr, u8 *FirstTs) +{ + u32 Status; + u8 Index; + u8 AuxData[64]; + + Status = XDp_TxAuxRead(InstancePtr, XDP_DPCD_VC_PAYLOAD_ID_SLOT(1), + 64, AuxData); + if (Status != XST_SUCCESS) { + /* The AUX read transaction failed. */ + return Status; + } + + for (Index = 0; Index < 64; Index++) { + /* A zero in the payload ID table indicates that the timeslot is + * available. */ + if (AuxData[Index] == 0) { + *FirstTs = (Index + 1); + return XST_SUCCESS; + } + } + + /* No free time slots available. */ + *FirstTs = 0; + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will send a sideband message by creating a data array from the + * supplied sideband message structure and submitting an AUX write transaction. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the RX device indicates that the ACT trigger + * has taken effect and the payload ID table has been updated. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for the payload ID table + * to indicate that it has been updated, or the AUX read request + * timed out. + * - XST_FAILURE if the AUX read transaction failed while accessing + * the RX device. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxSendActTrigger(XDp *InstancePtr) +{ + u32 Status; + u8 AuxData; + u8 TimeoutCount = 0; + + XDp_WaitUs(InstancePtr, 10000); + + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_TX_MST_CONFIG, 0x3); + + do { + Status = XDp_TxAuxRead(InstancePtr, + XDP_DPCD_PAYLOAD_TABLE_UPDATE_STATUS, 1, &AuxData); + if (Status != XST_SUCCESS) { + /* The AUX read transaction failed. */ + return Status; + } + + /* Error out if timed out. */ + if (TimeoutCount > XDP_TX_VCP_TABLE_MAX_TIMEOUT_COUNT) { + return XST_ERROR_COUNT_MAX; + } + + TimeoutCount++; + XDp_WaitUs(InstancePtr, 1000); + } while ((AuxData & 0x02) != 0x02); + + /* Clear the ACT event received bit. */ + AuxData = 0x2; + Status = XDp_TxAuxWrite(InstancePtr, + XDP_DPCD_PAYLOAD_TABLE_UPDATE_STATUS, 1, &AuxData); + if (Status != XST_SUCCESS) { + /* The AUX write transaction failed. */ + return Status; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will send a sideband message by creating a data array from the + * supplied sideband message structure and submitting an AUX write transaction. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Msg is a pointer to the sideband message structure that holds + * the contents of the data to be submitted. + * + * @return + * - XST_SUCCESS if the AUX write transaction used to transmit the + * sideband message was successful. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if the AUX write request timed out. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxSendSbMsg(XDp *InstancePtr, XDp_SidebandMsg *Msg) +{ + u32 Status; + u8 AuxData[10+63]; + XDp_SidebandMsgHeader *Header = &Msg->Header; + XDp_SidebandMsgBody *Body = &Msg->Body; + u8 Index; + + XDp_WaitUs(InstancePtr, InstancePtr->TxInstance.SbMsgDelayUs); + + /* First, clear the DOWN_REP_MSG_RDY in case the RX device is in a weird + * state. */ + AuxData[0] = 0x10; + Status = XDp_TxAuxWrite(InstancePtr, + XDP_DPCD_SINK_DEVICE_SERVICE_IRQ_VECTOR_ESI0, 1, + AuxData); + if (Status != XST_SUCCESS) { + return Status; + } + + /* Add the header to the sideband message transaction. */ + Msg->Header.MsgHeaderLength = 0; + AuxData[Msg->Header.MsgHeaderLength++] = + (Msg->Header.LinkCountTotal << 4) | + Msg->Header.LinkCountRemaining; + for (Index = 0; Index < (Header->LinkCountTotal - 1); Index += 2) { + AuxData[Header->MsgHeaderLength] = + (Header->RelativeAddress[Index] << 4); + + if ((Index + 1) < (Header->LinkCountTotal - 1)) { + AuxData[Header->MsgHeaderLength] |= + Header->RelativeAddress[Index + 1]; + } + /* Else, the lower (4-bit) nibble is all zeros (for + * byte-alignment). */ + + Header->MsgHeaderLength++; + } + AuxData[Header->MsgHeaderLength++] = (Header->BroadcastMsg << 7) | + (Header->PathMsg << 6) | Header->MsgBodyLength; + AuxData[Header->MsgHeaderLength++] = (Header->StartOfMsgTransaction << + 7) | (Header->EndOfMsgTransaction << 6) | + (Header->MsgSequenceNum << 4) | Header->Crc; + + /* Add the body to the transaction. */ + for (Index = 0; Index < Body->MsgDataLength; Index++) { + AuxData[Index + Header->MsgHeaderLength] = Body->MsgData[Index]; + } + AuxData[Index + Header->MsgHeaderLength] = Body->Crc; + + /* Submit the LINK_ADDRESS transaction message request. */ + Status = XDp_TxAuxWrite(InstancePtr, XDP_DPCD_DOWN_REQ, + Msg->Header.MsgHeaderLength + Msg->Header.MsgBodyLength, + AuxData); + + return Status; +} + +/******************************************************************************/ +/** + * This function will wait for a sideband message reply and fill in the SbReply + * structure with the reply data for use by higher-level functions. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param SbReply is a pointer to the reply structure that this function + * will fill in for use by higher-level functions. + * + * @return + * - XST_SUCCESS if the reply was successfully obtained and it + * indicates an acknowledge. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for a reply, or an AUX + * request timed out. + * - XST_FAILURE otherwise - if an AUX read or write transaction + * failed, the header or body CRC did not match the calculated + * value, or the reply was negative acknowledged (NACK'ed). + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxReceiveSbMsg(XDp *InstancePtr, XDp_SidebandReply *SbReply) +{ + u32 Status; + u8 Index = 0; + u8 AuxData[80]; + XDp_SidebandMsg Msg; + + SbReply->Length = 0; + + do { + XDp_WaitUs(InstancePtr, InstancePtr->TxInstance.SbMsgDelayUs); + + /* Wait for a reply. */ + Status = XDp_TxWaitSbReply(InstancePtr); + if (Status != XST_SUCCESS) { + return Status; + } + + /* Receive reply. */ + Status = XDp_TxAuxRead(InstancePtr, XDP_DPCD_DOWN_REP, 80, + AuxData); + if (Status != XST_SUCCESS) { + /* The AUX read transaction failed. */ + return Status; + } + + /* Convert the reply transaction into XDp_SidebandReply + * format. */ + Status = XDp_TxTransaction2MsgFormat(AuxData, &Msg); + if (Status != XST_SUCCESS) { + /* The CRC of the header or the body did not match the + * calculated value. */ + return XST_FAILURE; + } + + /* Collect body data into an array. */ + for (Index = 0; Index < Msg.Body.MsgDataLength; Index++) { + SbReply->Data[SbReply->Length++] = + Msg.Body.MsgData[Index]; + } + + /* Clear. */ + AuxData[0] = 0x10; + Status = XDp_TxAuxWrite(InstancePtr, + XDP_DPCD_SINK_DEVICE_SERVICE_IRQ_VECTOR_ESI0, + 1, AuxData); + if (Status != XST_SUCCESS) { + /* The AUX write transaction failed. */ + return Status; + } + } + while (Msg.Header.EndOfMsgTransaction == 0); + + /* Check if the reply indicates a NACK. */ + if ((SbReply->Data[0] & 0x80) == 0x80) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will wait until the RX device directly downstream to the + * DisplayPort TX indicates that a sideband reply is ready to be received by + * the source. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if a reply message is ready. + * - XST_DEVICE_NOT_FOUND if no RX device is connected. + * - XST_ERROR_COUNT_MAX if either waiting for a reply, or the AUX + * read request timed out. + * - XST_FAILURE if the AUX read transaction failed while accessing + * the RX device. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxWaitSbReply(XDp *InstancePtr) +{ + u32 Status; + u8 AuxData; + u16 TimeoutCount = 0; + + do { + Status = XDp_TxAuxRead(InstancePtr, + XDP_DPCD_SINK_DEVICE_SERVICE_IRQ_VECTOR_ESI0, + 1, &AuxData); + if (Status != XST_SUCCESS) { + /* The AUX read transaction failed. */ + return Status; + } + + /* Error out if timed out. */ + if (TimeoutCount > XDP_TX_MAX_SBMSG_REPLY_TIMEOUT_COUNT) { + return XST_ERROR_COUNT_MAX; + } + + TimeoutCount++; + XDp_WaitUs(InstancePtr, 1000); + } + while ((AuxData & 0x10) != 0x10); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will take a byte array and convert it into a sideband message + * format by filling in the XDp_SidebandMsg structure with the array data. + * + * @param Transaction is the pointer to the data used to fill in the + * sideband message structure. + * @param Msg is a pointer to the sideband message structure that will be + * filled in with the transaction data. + * + * @return + * - XST_SUCCESS if the transaction data was successfully converted + * into the sideband message structure format. + * - XST_FAILURE otherwise, if the calculated header or body CRC + * does not match that contained in the transaction data. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxTransaction2MsgFormat(u8 *Transaction, XDp_SidebandMsg *Msg) +{ + XDp_SidebandMsgHeader *Header = &Msg->Header; + XDp_SidebandMsgBody *Body = &Msg->Body; + + u8 Index = 0; + u8 CrcCheck; + + /* Fill the header structure from the reply transaction. */ + Header->MsgHeaderLength = 0; + /* Byte 0. */ + Header->LinkCountTotal = Transaction[Header->MsgHeaderLength] >> 4; + Header->LinkCountRemaining = Transaction[Header->MsgHeaderLength] & + 0x0F; + Header->MsgHeaderLength++; + /* If LinkCountTotal > 1, Byte 1 to Byte (_(LinkCountTotal / 2)_) */ + for (Index = 0; Index < (Header->LinkCountTotal - 1); Index += 2) { + Header->RelativeAddress[Index] = + Transaction[Header->MsgHeaderLength] >> 4; + + if ((Index + 1) < (Header->LinkCountTotal - 1)) { + Header->RelativeAddress[Index + 1] = + Transaction[Header->MsgHeaderLength] & 0x0F; + } + + Header->MsgHeaderLength++; + } + /* Byte (1 + _(LinkCountTotal / 2)_). */ + Header->BroadcastMsg = Transaction[Header->MsgHeaderLength] >> 7; + Header->PathMsg = (Transaction[Header->MsgHeaderLength] & 0x40) >> 6; + Header->MsgBodyLength = Transaction[Header->MsgHeaderLength] & 0x3F; + Header->MsgHeaderLength++; + /* Byte (2 + _(LinkCountTotal / 2)_). */ + Header->StartOfMsgTransaction = Transaction[Header->MsgHeaderLength] >> + 7; + Header->EndOfMsgTransaction = (Transaction[Header->MsgHeaderLength] & + 0x40) >> 6; + Header->MsgSequenceNum = (Transaction[Header->MsgHeaderLength] & + 0x10) >> 4; + Header->Crc = Transaction[Header->MsgHeaderLength] & 0x0F; + Header->MsgHeaderLength++; + /* Verify the header CRC. */ + CrcCheck = XDp_TxCrc4CalculateHeader(Header); + if (CrcCheck != Header->Crc) { + /* The calculated CRC for the header did not match the + * response. */ + return XST_FAILURE; + } + + /* Fill the body structure from the reply transaction. */ + Body->MsgDataLength = Header->MsgBodyLength - 1; + for (Index = 0; Index < Body->MsgDataLength; Index++) { + Body->MsgData[Index] = Transaction[Header->MsgHeaderLength + + Index]; + } + Body->Crc = Transaction[Header->MsgHeaderLength + Index]; + /* Verify the body CRC. */ + CrcCheck = XDp_TxCrc8CalculateBody(Body); + if (CrcCheck != Body->Crc) { + /* The calculated CRC for the body did not match the + * response. */ + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will perform a cyclic redundancy check (CRC) on the header of a + * sideband message using a generator polynomial of 4. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Header is a pointer sideband message header that the CRC + * algorithm is to be run on. + * + * @return The CRC value obtained by running the algorithm on the sideband + * message header. + * + * @note The header is divided into 4-bit nibbles for use by the lower- + * level XDp_TxCrcCalculate function. + * +*******************************************************************************/ +static u8 XDp_TxCrc4CalculateHeader(XDp_SidebandMsgHeader *Header) +{ + u8 Nibbles[20]; + u8 RadOffset = 0; + + /* Arrange header into nibbles for the CRC. */ + Nibbles[0] = Header->LinkCountTotal; + Nibbles[1] = Header->LinkCountRemaining; + + for (RadOffset = 0; RadOffset < (Header->LinkCountTotal - 1); + RadOffset += 2) { + Nibbles[2 + RadOffset] = Header->RelativeAddress[RadOffset]; + + /* Byte (8-bits) align the nibbles (4-bits). */ + if ((RadOffset + 1) < (Header->LinkCountTotal - 1)) { + Nibbles[2 + RadOffset + 1] = + Header->RelativeAddress[RadOffset + 1]; + } + else { + Nibbles[2 + RadOffset + 1] = 0; + } + } + + Nibbles[2 + RadOffset] = (Header->BroadcastMsg << 3) | + (Header->PathMsg << 2) | ((Header->MsgBodyLength & 0x30) >> 4); + Nibbles[3 + RadOffset] = Header->MsgBodyLength & 0x0F; + Nibbles[4 + RadOffset] = (Header->StartOfMsgTransaction << 3) | + (Header->EndOfMsgTransaction << 2) | Header->MsgSequenceNum; + + return XDp_TxCrcCalculate(Nibbles, 4 * (5 + RadOffset), 4); +} + +/******************************************************************************/ +/** + * This function will perform a cyclic redundancy check (CRC) on the body of a + * sideband message using a generator polynomial of 8. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Body is a pointer sideband message body that the CRC algorithm + * is to be run on. + * + * @return The CRC value obtained by running the algorithm on the sideband + * message body. + * + * @note None. + * +*******************************************************************************/ +static u8 XDp_TxCrc8CalculateBody(XDp_SidebandMsgBody *Body) +{ + return XDp_TxCrcCalculate(Body->MsgData, 8 * Body->MsgDataLength, 8); +} + +/******************************************************************************/ +/** + * This function will run a cyclic redundancy check (CRC) algorithm on some data + * given a generator polynomial. + * + * @param Data is a pointer to the data that the algorithm is to run on. + * @param NumberOfBits is the total number of data bits that the algorithm + * is to run on. + * @param Polynomial is the generator polynomial for the CRC algorithm and + * will be used as the divisor in the polynomial long division. + * + * @return The CRC value obtained by running the algorithm on the data + * using the specified polynomial. + * + * @note None. + * +*******************************************************************************/ +static u8 XDp_TxCrcCalculate(const u8 *Data, u32 NumberOfBits, u8 Polynomial) +{ + u8 BitMask; + u8 BitShift; + u8 ArrayIndex = 0; + u16 Remainder = 0; + + if (Polynomial == 4) { + /* For CRC4, expecting nibbles (4-bits). */ + BitMask = 0x08; + BitShift = 3; + } + else { + /* For CRC8, expecting bytes (8-bits). */ + BitMask = 0x80; + BitShift = 7; + } + + while (NumberOfBits != 0) { + NumberOfBits--; + + Remainder <<= 1; + Remainder |= (Data[ArrayIndex] & BitMask) >> BitShift; + + BitMask >>= 1; + BitShift--; + + if (BitMask == 0) { + if (Polynomial == 4) { + BitMask = 0x08; + BitShift = 3; + } + else { + BitMask = 0x80; + BitShift = 7; + } + ArrayIndex++; + } + + if ((Remainder & (1 << Polynomial)) != 0) { + if (Polynomial == 4) { + Remainder ^= 0x13; + } + else { + Remainder ^= 0xD5; + } + } + } + + NumberOfBits = Polynomial; + while (NumberOfBits != 0) { + NumberOfBits--; + + Remainder <<= 1; + + if ((Remainder & (1 << Polynomial)) != 0) { + if (Polynomial == 4) { + Remainder ^= 0x13; + Remainder &= 0xFF; + } + else { + Remainder ^= 0xD5; + } + } + } + + return Remainder & 0xFF; +} + +/******************************************************************************/ +/** + * Check whether or not the two specified Tiled Display Topology (TDT) data + * blocks represent devices that are part of the same tiled display. This is + * done by comparing the TDT ID descriptor (tiled display manufacturer/vendor + * ID, product ID and serial number fields). + * + * @param TileDisp0 is one of the TDT data blocks to be compared. + * @param TileDisp1 is the other TDT data block to be compared. + * + * @return + * - 1 if the two TDT sections represent devices that are part of + * the same tiled display. + * - 0 otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxIsSameTileDisplay(u8 *TileDisp0, u8 *TileDisp1) +{ + if ((TileDisp0[XDP_TX_DISPID_TDT_VENID0] != + TileDisp1[XDP_TX_DISPID_TDT_VENID0]) || + (TileDisp0[XDP_TX_DISPID_TDT_VENID1] != + TileDisp1[XDP_TX_DISPID_TDT_VENID1]) || + (TileDisp0[XDP_TX_DISPID_TDT_VENID2] != + TileDisp1[XDP_TX_DISPID_TDT_VENID2]) || + (TileDisp0[XDP_TX_DISPID_TDT_PCODE0] != + TileDisp1[XDP_TX_DISPID_TDT_PCODE0]) || + (TileDisp0[XDP_TX_DISPID_TDT_PCODE1] != + TileDisp1[XDP_TX_DISPID_TDT_PCODE1]) || + (TileDisp0[XDP_TX_DISPID_TDT_SN0] != + TileDisp1[XDP_TX_DISPID_TDT_SN0]) || + (TileDisp0[XDP_TX_DISPID_TDT_SN1] != + TileDisp1[XDP_TX_DISPID_TDT_SN1]) || + (TileDisp0[XDP_TX_DISPID_TDT_SN2] != + TileDisp1[XDP_TX_DISPID_TDT_SN2]) || + (TileDisp0[XDP_TX_DISPID_TDT_SN3] != + TileDisp1[XDP_TX_DISPID_TDT_SN3]) ) { + return 0; + } + + return 1; +} diff --git a/XilinxProcessorIPLib/drivers/dp/src/xdp_selftest.c b/XilinxProcessorIPLib/drivers/dp/src/xdp_selftest.c new file mode 100644 index 00000000..b3e17d74 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/src/xdp_selftest.c @@ -0,0 +1,339 @@ +/******************************************************************************* + * + * 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 xdp_selftest.c + * + * This file contains a diagnostic self-test function for the XDp driver. It + * will check many of the DisplayPort core's register values against the default + * reset values as a sanity-check that the core is ready to be used. + * + * @note None. + * + *
+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial release. TX code merged from the dptx driver. + *+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdp.h" + +/**************************** Function Prototypes *****************************/ + +static u32 XDp_TxSelfTest(XDp *InstancePtr); +static u32 XDp_RxSelfTest(XDp *InstancePtr); + +/**************************** Variable Definitions ****************************/ + +/** + * This table contains the default values for the DisplayPort TX core's general + * usage registers. + */ +u32 TxResetValues[53][2] = +{ + {XDP_TX_LINK_BW_SET, 0}, + {XDP_TX_LANE_COUNT_SET, 0}, + {XDP_TX_ENHANCED_FRAME_EN, 0}, + {XDP_TX_TRAINING_PATTERN_SET, 0}, + {XDP_TX_LINK_QUAL_PATTERN_SET, 0}, + {XDP_TX_SCRAMBLING_DISABLE, 0}, + {XDP_TX_DOWNSPREAD_CTRL, 0}, + {XDP_TX_SOFT_RESET, 0}, + {XDP_TX_ENABLE, 0}, + {XDP_TX_ENABLE_MAIN_STREAM, 0}, + {XDP_TX_ENABLE_SEC_STREAM, 0}, + {XDP_TX_FORCE_SCRAMBLER_RESET, 0}, + {XDP_TX_MST_CONFIG, 0}, + {XDP_TX_AUX_CMD, 0}, + {XDP_TX_AUX_WRITE_FIFO, 0}, + {XDP_TX_AUX_ADDRESS, 0}, + {XDP_TX_AUX_CLK_DIVIDER, 0}, + {XDP_TX_USER_FIFO_OVERFLOW, 0}, + {XDP_TX_AUX_REPLY_DATA, 0}, + {XDP_TX_AUX_REPLY_CODE, 0}, + {XDP_TX_AUX_REPLY_COUNT, 0}, + {XDP_TX_INTERRUPT_MASK, 0x3F}, + {XDP_TX_REPLY_DATA_COUNT, 0}, + {XDP_TX_REPLY_STATUS, 0x10}, + {XDP_TX_STREAM1, 0}, + {XDP_TX_STREAM2, 0}, + {XDP_TX_STREAM3, 0}, + {XDP_TX_STREAM4, 0}, + {XDP_TX_PHY_CONFIG, 0x03}, + {XDP_TX_PHY_VOLTAGE_DIFF_LANE_0, 0}, + {XDP_TX_PHY_VOLTAGE_DIFF_LANE_1, 0}, + {XDP_TX_PHY_VOLTAGE_DIFF_LANE_2, 0}, + {XDP_TX_PHY_VOLTAGE_DIFF_LANE_3, 0}, + {XDP_TX_PHY_TRANSMIT_PRBS7, 0}, + {XDP_TX_PHY_CLOCK_SELECT, 0}, + {XDP_TX_PHY_POWER_DOWN, 0}, + {XDP_TX_PHY_PRECURSOR_LANE_0, 0}, + {XDP_TX_PHY_PRECURSOR_LANE_1, 0}, + {XDP_TX_PHY_PRECURSOR_LANE_2, 0}, + {XDP_TX_PHY_PRECURSOR_LANE_3, 0}, + {XDP_TX_PHY_POSTCURSOR_LANE_0, 0}, + {XDP_TX_PHY_POSTCURSOR_LANE_1, 0}, + {XDP_TX_PHY_POSTCURSOR_LANE_2, 0}, + {XDP_TX_PHY_POSTCURSOR_LANE_3, 0}, + {XDP_TX_GT_DRP_COMMAND, 0}, + {XDP_TX_GT_DRP_READ_DATA, 0}, + {XDP_TX_GT_DRP_CHANNEL_STATUS, 0}, + {XDP_TX_AUDIO_CONTROL, 0}, + {XDP_TX_AUDIO_CHANNELS, 0}, + {XDP_TX_AUDIO_INFO_DATA(1), 0}, + {XDP_TX_AUDIO_MAUD, 0}, + {XDP_TX_AUDIO_NAUD, 0}, + {XDP_TX_AUDIO_EXT_DATA(1), 0} +}; + +/** + * This table contains the default values for the DisplayPort TX core's main + * stream attribute (MSA) registers. + */ +u32 TxResetValuesMsa[20][2] = +{ + {XDP_TX_MAIN_STREAM_HTOTAL, 0}, + {XDP_TX_MAIN_STREAM_VTOTAL, 0}, + {XDP_TX_MAIN_STREAM_POLARITY, 0}, + {XDP_TX_MAIN_STREAM_HSWIDTH, 0}, + {XDP_TX_MAIN_STREAM_VSWIDTH, 0}, + {XDP_TX_MAIN_STREAM_HRES, 0}, + {XDP_TX_MAIN_STREAM_VRES, 0}, + {XDP_TX_MAIN_STREAM_HSTART, 0}, + {XDP_TX_MAIN_STREAM_VSTART, 0}, + {XDP_TX_MAIN_STREAM_MISC0, 0}, + {XDP_TX_MAIN_STREAM_MISC1, 0}, + {XDP_TX_M_VID, 0}, + {XDP_TX_TU_SIZE, 0}, + {XDP_TX_N_VID, 0}, + {XDP_TX_USER_PIXEL_WIDTH, 0}, + {XDP_TX_USER_DATA_COUNT_PER_LANE, 0}, + {XDP_TX_MAIN_STREAM_INTERLACED, 0}, + {XDP_TX_MIN_BYTES_PER_TU, 0}, + {XDP_TX_FRAC_BYTES_PER_TU, 0}, + {XDP_TX_INIT_WAIT, 32} +}; + +/** + * This table contains the default values for the DisplayPort RX core's general + * usage registers. + */ +u32 RxResetValues[46][2] = +{ + {XDP_RX_LINK_ENABLE, 0}, + {XDP_RX_AUX_CLK_DIVIDER, 0}, + {XDP_RX_DTG_ENABLE, 0}, + {XDP_RX_USER_PIXEL_WIDTH, 0}, + {XDP_RX_INTERRUPT_MASK, 0x7FFF}, + {XDP_RX_MISC_CTRL, 0}, + {XDP_RX_SOFT_RESET, 0}, + {XDP_RX_AUX_REQ_IN_PROGRESS, 0}, + {XDP_RX_REQ_ERROR_COUNT, 0}, + {XDP_RX_REQ_COUNT, 0}, + {XDP_RX_HPD_INTERRUPT, 0}, + {XDP_RX_REQ_CLK_WIDTH, 0}, + {XDP_RX_REQ_CMD, 0}, + {XDP_RX_REQ_ADDRESS, 0}, + {XDP_RX_REQ_LENGTH, 0}, + {XDP_RX_INTERRUPT_CAUSE, 0}, + {XDP_RX_INTERRUPT_MASK_1, 0}, + {XDP_RX_INTERRUPT_CAUSE_1, 0}, + {XDP_RX_HSYNC_WIDTH, 0xF0F}, + {XDP_RX_FAST_I2C_DIVIDER, 0}, + {XDP_RX_LOCAL_EDID_VIDEO, 0}, + {XDP_RX_LOCAL_EDID_AUDIO, 0}, + {XDP_RX_REMOTE_CMD, 0}, + {XDP_RX_DEVICE_SERVICE_IRQ, 0}, + {XDP_RX_VIDEO_UNSUPPORTED, 0}, + {XDP_RX_AUDIO_UNSUPPORTED, 0}, + {XDP_RX_OVER_LINK_BW_SET, 0}, + {XDP_RX_OVER_LANE_COUNT_SET, 0}, + {XDP_RX_OVER_TP_SET, 0}, + {XDP_RX_OVER_TRAINING_LANE0_SET, 0}, + {XDP_RX_OVER_TRAINING_LANE1_SET, 0}, + {XDP_RX_OVER_TRAINING_LANE2_SET, 0}, + {XDP_RX_OVER_TRAINING_LANE3_SET, 0}, + {XDP_RX_OVER_CTRL_DPCD, 0}, + {XDP_RX_OVER_DOWNSPREAD_CTRL, 0}, + {XDP_RX_OVER_LINK_QUAL_LANE0_SET, 0}, + {XDP_RX_OVER_LINK_QUAL_LANE1_SET, 0}, + {XDP_RX_OVER_LINK_QUAL_LANE2_SET, 0}, + {XDP_RX_OVER_LINK_QUAL_LANE3_SET, 0}, + {XDP_RX_MST_CAP, 0}, + {XDP_RX_SINK_COUNT, 0}, + {XDP_RX_GUID0, 0}, + {XDP_RX_GUID1, 0}, + {XDP_RX_GUID2, 0}, + {XDP_RX_GUID3, 0}, + {XDP_RX_OVER_GUID, 0} +}; + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function runs a self-test on the XDp driver/device depending on whether + * the core is operating in TX or RX mode. The sanity test checks whether or not + * all tested registers hold their default reset values. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the self-test passed - all tested registers + * hold their default reset values. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDp_SelfTest(XDp *InstancePtr) +{ + u32 Status; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (XDp_GetCoreType(InstancePtr) == XDP_TX) { + Status = XDp_TxSelfTest(InstancePtr); + } + else { + Status = XDp_RxSelfTest(InstancePtr); + } + + return Status; +} + +/******************************************************************************/ +/** + * This function runs a self-test on the XDp driver/device. The sanity test + * checks whether or not all tested registers hold their default reset values. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the self-test passed - all tested registers + * hold their default reset values. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_TxSelfTest(XDp *InstancePtr) +{ + u8 Index; + u8 StreamIndex; + u32 StreamOffset; + u32 Val; + + /* Compare general usage registers with their default values. */ + for (Index = 0; Index < 53; Index++) { + Val = XDp_ReadReg(InstancePtr->Config.BaseAddr, + TxResetValues[Index][0]); + /* Fail if register does not hold default value. */ + if (Val != TxResetValues[Index][1]) { + return XST_FAILURE; + } + } + + /* Compare main stream attribute (MSA) registers for all 4 streams with + * their default values. */ + for (StreamIndex = 0; StreamIndex < 4; StreamIndex++) { + /* Determine the MSA register offset for each stream. */ + if (StreamIndex == 0) { + StreamOffset = 0; + } + else if (StreamIndex == 1) { + StreamOffset = XDP_TX_STREAM2_MSA_START_OFFSET; + } + else if (StreamIndex == 2) { + StreamOffset = XDP_TX_STREAM3_MSA_START_OFFSET; + } + else if (StreamIndex == 3) { + StreamOffset = XDP_TX_STREAM4_MSA_START_OFFSET; + } + + for (Index = 0; Index < 20; Index++) { + Val = XDp_ReadReg(InstancePtr->Config.BaseAddr, + StreamOffset + TxResetValuesMsa[Index][0]); + /* Fail if register does not hold default value. */ + if (Val != TxResetValuesMsa[Index][1]) { + return XST_FAILURE; + } + } + } + + /* All tested registers hold their default reset values. */ + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function runs a self-test on the XDp driver/device running in RX mode. + * The sanity test checks whether or not all tested registers hold their default + * reset values. + * + * @param InstancePtr is a pointer to the XDp instance. + * + * @return + * - XST_SUCCESS if the self-test passed - all tested registers + * hold their default reset values. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XDp_RxSelfTest(XDp *InstancePtr) +{ + u8 Index; + u32 Val; + + /* Compare general usage registers with their default values. */ + for (Index = 0; Index < 46; Index++) { + Val = XDp_ReadReg(InstancePtr->Config.BaseAddr, + RxResetValues[Index][0]); + /* Fail if register does not hold default value. */ + if (Val != RxResetValues[Index][1]) { + return XST_FAILURE; + } + } + + /* All tested registers hold their default reset values. */ + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/dp/src/xdp_sinit.c b/XilinxProcessorIPLib/drivers/dp/src/xdp_sinit.c new file mode 100644 index 00000000..d125f66e --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/src/xdp_sinit.c @@ -0,0 +1,93 @@ +/******************************************************************************* + * + * 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 xdp_sinit.c + * + * This file contains static initialization methods for the XDp driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial release. TX code merged from the dptx driver. + *+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdp.h" +#include "xparameters.h" + +/*************************** Variable Declarations ****************************/ + +/** + * A table of configuration structures containing the configuration information + * for each DisplayPort TX core in the system. + */ +extern XDp_Config XDp_ConfigTable[XPAR_XDP_NUM_INSTANCES]; + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function looks for the device configuration based on the unique device + * ID. The table XDp_ConfigTable[] contains the configuration information for + * each device in the system. + * + * @param DeviceId is the unique device ID of the device being looked up. + * + * @return A pointer to the configuration table entry corresponding to the + * given device ID, or NULL if no match is found. + * + * @note None. + * +*******************************************************************************/ +XDp_Config *XDp_LookupConfig(u16 DeviceId) +{ + XDp_Config *CfgPtr; + u32 Index; + + for (Index = 0; Index < XPAR_XDP_NUM_INSTANCES; Index++) { + if (XDp_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XDp_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} diff --git a/XilinxProcessorIPLib/drivers/dp/src/xdp_spm.c b/XilinxProcessorIPLib/drivers/dp/src/xdp_spm.c new file mode 100644 index 00000000..a898dfc1 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dp/src/xdp_spm.c @@ -0,0 +1,950 @@ +/******************************************************************************* + * + * 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 xdp_spm.c + * + * This file contains the stream policy maker functions for the XDp driver. + * These functions set up the DisplayPort TX core's main stream attributes (MSA) + * that determine how a video stream will be displayed and also some DisplayPort + * RX MSA-related functions. + * + * @note None. + * + *
+ * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 01/20/15 Initial release. TX code merged from the dptx driver. + *+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdp.h" + +/**************************** Function Prototypes *****************************/ + +static void XDp_TxCalculateTs(XDp *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 XDp 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 XDp_TxCfgMsaRecalculate(XDp *InstancePtr, u8 Stream) +{ + u32 VideoBw; + u32 LinkBw; + u32 WordsPerLine; + u8 BitsPerPixel; + XDp_TxMainStreamAttributes *MsaConfig; + XDp_TxLinkConfig *LinkConfig; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Stream == XDP_TX_STREAM_ID1) || + (Stream == XDP_TX_STREAM_ID2) || (Stream == XDP_TX_STREAM_ID3) || + (Stream == XDP_TX_STREAM_ID4)); + + MsaConfig = &InstancePtr->TxInstance.MsaConfig[Stream - 1]; + LinkConfig = &InstancePtr->TxInstance.LinkConfig; + + /* Verify the rest of the values used. */ + Xil_AssertVoid((LinkConfig->LinkRate == XDP_TX_LINK_BW_SET_162GBPS) || + (LinkConfig->LinkRate == XDP_TX_LINK_BW_SET_270GBPS) || + (LinkConfig->LinkRate == XDP_TX_LINK_BW_SET_540GBPS)); + Xil_AssertVoid((LinkConfig->LaneCount == XDP_TX_LANE_COUNT_SET_1) || + (LinkConfig->LaneCount == XDP_TX_LANE_COUNT_SET_2) || + (LinkConfig->LaneCount == XDP_TX_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->PixelClockHz > 300000000) && + (LinkConfig->LaneCount == XDP_TX_LANE_COUNT_SET_4)) { + MsaConfig->UserPixelWidth = 4; + } + else if ((MsaConfig->PixelClockHz > 75000000) && + (LinkConfig->LaneCount != XDP_TX_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; + + /* Miscellaneous attributes. */ + if (MsaConfig->BitsPerColor == 6) { + MsaConfig->Misc0 = XDP_TX_MAIN_STREAMX_MISC0_BDC_6BPC; + } + else if (MsaConfig->BitsPerColor == 8) { + MsaConfig->Misc0 = XDP_TX_MAIN_STREAMX_MISC0_BDC_8BPC; + } + else if (MsaConfig->BitsPerColor == 10) { + MsaConfig->Misc0 = XDP_TX_MAIN_STREAMX_MISC0_BDC_10BPC; + } + else if (MsaConfig->BitsPerColor == 12) { + MsaConfig->Misc0 = XDP_TX_MAIN_STREAMX_MISC0_BDC_12BPC; + } + else if (MsaConfig->BitsPerColor == 16) { + MsaConfig->Misc0 = XDP_TX_MAIN_STREAMX_MISC0_BDC_16BPC; + } + MsaConfig->Misc0 = (MsaConfig->Misc0 << + XDP_TX_MAIN_STREAMX_MISC0_BDC_SHIFT) | + (MsaConfig->YCbCrColorimetry << + XDP_TX_MAIN_STREAMX_MISC0_YCBCR_COLORIMETRY_SHIFT) | + (MsaConfig->DynamicRange << + XDP_TX_MAIN_STREAMX_MISC0_DYNAMIC_RANGE_SHIFT) | + (MsaConfig->ComponentFormat << + XDP_TX_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 == + XDP_TX_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->TxInstance.MstEnable == 1) { + /* Do time slot (and payload bandwidth number) calculations for + * MST. */ + XDp_TxCalculateTs(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->PixelClockHz / 1000) * 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 XDp_TxDmtModes[] standard Display Monitor Timing (DMT) table. The + * XDp_TxVideoMode enumeration in xvidc.h lists the available video modes. + * + * @param InstancePtr is a pointer to the XDp 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->TxInstance.MsaConfig structure is modified to + * reflect the MSA values associated to the specified video mode. + * +*******************************************************************************/ +void XDp_TxCfgMsaUseStandardVideoMode(XDp *InstancePtr, u8 Stream, + XVidC_VideoMode VideoMode) +{ + XDp_TxMainStreamAttributes *MsaConfig; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid(VideoMode < XVIDC_VM_NUM_SUPPORTED); + Xil_AssertVoid((Stream == XDP_TX_STREAM_ID1) || + (Stream == XDP_TX_STREAM_ID2) || (Stream == XDP_TX_STREAM_ID3) || + (Stream == XDP_TX_STREAM_ID4)); + + MsaConfig = &InstancePtr->TxInstance.MsaConfig[Stream - 1]; + + /* Configure the MSA values from the display monitor DMT table. */ + MsaConfig->Vtm.VmId = XVidC_VideoTimingModes[VideoMode].VmId; + MsaConfig->Vtm.FrameRate = XVidC_VideoTimingModes[VideoMode].FrameRate; + MsaConfig->Vtm.Timing.HActive = + XVidC_VideoTimingModes[VideoMode].Timing.HActive; + MsaConfig->Vtm.Timing.HFrontPorch = + XVidC_VideoTimingModes[VideoMode].Timing.HFrontPorch; + MsaConfig->Vtm.Timing.HSyncWidth = + XVidC_VideoTimingModes[VideoMode].Timing.HSyncWidth; + MsaConfig->Vtm.Timing.HBackPorch = + XVidC_VideoTimingModes[VideoMode].Timing.HBackPorch; + MsaConfig->Vtm.Timing.HTotal = + XVidC_VideoTimingModes[VideoMode].Timing.HTotal; + MsaConfig->Vtm.Timing.HSyncPolarity = + XVidC_VideoTimingModes[VideoMode].Timing.HSyncPolarity; + MsaConfig->Vtm.Timing.VActive = + XVidC_VideoTimingModes[VideoMode].Timing.VActive; + MsaConfig->Vtm.Timing.F0PVFrontPorch = + XVidC_VideoTimingModes[VideoMode].Timing.F0PVFrontPorch; + MsaConfig->Vtm.Timing.F0PVSyncWidth = + XVidC_VideoTimingModes[VideoMode].Timing.F0PVSyncWidth; + MsaConfig->Vtm.Timing.F0PVBackPorch = + XVidC_VideoTimingModes[VideoMode].Timing.F0PVBackPorch; + MsaConfig->Vtm.Timing.F0PVTotal = + XVidC_VideoTimingModes[VideoMode].Timing.F0PVTotal; + MsaConfig->Vtm.Timing.F1VFrontPorch = + XVidC_VideoTimingModes[VideoMode].Timing.F1VFrontPorch; + MsaConfig->Vtm.Timing.F1VSyncWidth = + XVidC_VideoTimingModes[VideoMode].Timing.F1VSyncWidth; + MsaConfig->Vtm.Timing.F1VBackPorch = + XVidC_VideoTimingModes[VideoMode].Timing.F1VBackPorch; + MsaConfig->Vtm.Timing.F1VTotal = + XVidC_VideoTimingModes[VideoMode].Timing.F1VTotal; + MsaConfig->Vtm.Timing.VSyncPolarity = + XVidC_VideoTimingModes[VideoMode].Timing.VSyncPolarity; + + /* Calculate the pixel clock frequency. */ + MsaConfig->PixelClockHz = + XVidC_GetPixelClockHzByVmId(MsaConfig->Vtm.VmId); + + /* Calculate the rest of the MSA values. */ + XDp_TxCfgMsaRecalculate(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 XDp 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->TxInstance.MsaConfig structure is modified to + * reflect the main stream attribute values associated to the + * preferred timing of the sink monitor. + * +*******************************************************************************/ +void XDp_TxCfgMsaUseEdidPreferredTiming(XDp *InstancePtr, u8 Stream, u8 *Edid) +{ + XDp_TxMainStreamAttributes *MsaConfig; + u8 *Ptm; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Stream == XDP_TX_STREAM_ID1) || + (Stream == XDP_TX_STREAM_ID2) || + (Stream == XDP_TX_STREAM_ID3) || + (Stream == XDP_TX_STREAM_ID4)); + Xil_AssertVoid(Edid != NULL); + + MsaConfig = &InstancePtr->TxInstance.MsaConfig[Stream - 1]; + Ptm = &Edid[XDP_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[XDP_EDID_DTD_HRES_HBLANK_U4] & + XDP_EDID_DTD_XRES_XBLANK_U4_XBLANK_MASK) << 8) | + Ptm[XDP_EDID_DTD_HBLANK_LSB]; + + u16 VBlank = ((Ptm[XDP_EDID_DTD_VRES_VBLANK_U4] & + XDP_EDID_DTD_XRES_XBLANK_U4_XBLANK_MASK) << 8) | + Ptm[XDP_EDID_DTD_VBLANK_LSB]; + + MsaConfig->Vtm.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]; + + MsaConfig->Vtm.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]; + + MsaConfig->PixelClockHz = (((Ptm[XDP_EDID_DTD_PIXEL_CLK_KHZ_MSB] << + 8) | Ptm[XDP_EDID_DTD_PIXEL_CLK_KHZ_LSB]) * 10) * 1000; + + MsaConfig->Vtm.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]; + + MsaConfig->Vtm.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]; + + MsaConfig->Vtm.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); + + MsaConfig->Vtm.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. */ + 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); + + MsaConfig->Vtm.Timing.HTotal = (MsaConfig->Vtm.Timing.HSyncWidth + + MsaConfig->Vtm.Timing.HFrontPorch + + MsaConfig->Vtm.Timing.HActive + + MsaConfig->Vtm.Timing.HBackPorch); + + MsaConfig->Vtm.Timing.F0PVTotal = (MsaConfig->Vtm.Timing.F0PVSyncWidth + + MsaConfig->Vtm.Timing.F0PVFrontPorch + + MsaConfig->Vtm.Timing.VActive + + MsaConfig->Vtm.Timing.F0PVBackPorch); + + MsaConfig->Vtm.FrameRate = MsaConfig->PixelClockHz / + (MsaConfig->Vtm.Timing.HTotal * + MsaConfig->Vtm.Timing.F0PVTotal); + + MsaConfig->Vtm.VmId = XVIDC_VM_USE_EDID_PREFERRED; + + /* Calculate the rest of the MSA values. */ + XDp_TxCfgMsaRecalculate(InstancePtr, Stream); +} + +/******************************************************************************/ +/** + * This function takes a the main stream attributes from MsaConfigCustom and + * copies them into InstancePtr->TxInstance.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 Hz) + * - Frame rate + * - Horizontal active resolution + * - Horizontal front porch + * - Horizontal sync pulse width + * - Horizontal back porch + * - Horizontal total + * - Horizontal sync polarity + * - Vertical active resolution + * - Vertical back porch + * - Vertical sync pulse width + * - Vertical front porch + * - Vertical total + * - Vertical sync polarity + * + * @param InstancePtr is a pointer to the XDp 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->TxInstance.MsaConfig). + * @param Recalculate is a boolean enable that determines whether or not + * the main stream attributes should be recalculated. + * + * @return None. + * + * @note The InstancePtr->TxInstance.MsaConfig structure is modified with + * the new values. + * +*******************************************************************************/ +void XDp_TxCfgMsaUseCustom(XDp *InstancePtr, u8 Stream, + XDp_TxMainStreamAttributes *MsaConfigCustom, u8 Recalculate) +{ + XDp_TxMainStreamAttributes *MsaConfig; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Stream == XDP_TX_STREAM_ID1) || + (Stream == XDP_TX_STREAM_ID2) || + (Stream == XDP_TX_STREAM_ID3) || + (Stream == XDP_TX_STREAM_ID4)); + Xil_AssertVoid(MsaConfigCustom != NULL); + + MsaConfig = &InstancePtr->TxInstance.MsaConfig[Stream - 1]; + + /* Copy the MSA values from the user configuration structure. */ + MsaConfig->PixelClockHz = MsaConfigCustom->PixelClockHz; + MsaConfig->Vtm.VmId = MsaConfigCustom->Vtm.VmId; + MsaConfig->Vtm.FrameRate = MsaConfigCustom->Vtm.FrameRate; + MsaConfig->Vtm.Timing.HActive = + MsaConfigCustom->Vtm.Timing.HActive; + 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.HTotal = + MsaConfigCustom->Vtm.Timing.HTotal; + MsaConfig->Vtm.Timing.HSyncPolarity = + MsaConfigCustom->Vtm.Timing.HSyncPolarity; + MsaConfig->Vtm.Timing.VActive = + MsaConfigCustom->Vtm.Timing.VActive; + MsaConfig->Vtm.Timing.F0PVFrontPorch = + MsaConfigCustom->Vtm.Timing.F0PVFrontPorch; + MsaConfig->Vtm.Timing.F0PVSyncWidth = + MsaConfigCustom->Vtm.Timing.F0PVSyncWidth; + MsaConfig->Vtm.Timing.F0PVBackPorch = + MsaConfigCustom->Vtm.Timing.F0PVBackPorch; + MsaConfig->Vtm.Timing.F0PVTotal = + MsaConfigCustom->Vtm.Timing.F0PVTotal; + MsaConfig->Vtm.Timing.F1VFrontPorch = + MsaConfigCustom->Vtm.Timing.F1VFrontPorch; + MsaConfig->Vtm.Timing.F1VSyncWidth = + MsaConfigCustom->Vtm.Timing.F1VSyncWidth; + MsaConfig->Vtm.Timing.F1VBackPorch = + MsaConfigCustom->Vtm.Timing.F1VBackPorch; + MsaConfig->Vtm.Timing.F1VTotal = + MsaConfigCustom->Vtm.Timing.F1VTotal; + MsaConfig->Vtm.Timing.VSyncPolarity = + MsaConfigCustom->Vtm.Timing.VSyncPolarity; + + if (Recalculate) { + /* Calculate the rest of the MSA values. */ + XDp_TxCfgMsaRecalculate(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->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 XDp 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->TxInstance.MsaConfig structure is modified to + * reflect the new main stream attributes associated with a new + * bits per color value. + * +*******************************************************************************/ +void XDp_TxCfgMsaSetBpc(XDp *InstancePtr, u8 Stream, u8 BitsPerColor) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Stream == XDP_TX_STREAM_ID1) || + (Stream == XDP_TX_STREAM_ID2) || + (Stream == XDP_TX_STREAM_ID3) || + (Stream == XDP_TX_STREAM_ID4)); + Xil_AssertVoid((BitsPerColor == 6) || (BitsPerColor == 8) || + (BitsPerColor == 10) || (BitsPerColor == 12) || + (BitsPerColor == 16)); + + InstancePtr->TxInstance.MsaConfig[Stream - 1].BitsPerColor = + BitsPerColor; + + /* Calculate the rest of the MSA values. */ + XDp_TxCfgMsaRecalculate(InstancePtr, Stream); +} + +/******************************************************************************/ +/** + * This function enables or disables synchronous clock mode for a video stream. + * + * @param InstancePtr is a pointer to the XDp 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 XDp_TxCfgMsaEnSynchClkMode(XDp *InstancePtr, u8 Stream, u8 Enable) +{ + XDp_TxMainStreamAttributes *MsaConfig; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Stream == XDP_TX_STREAM_ID1) || + (Stream == XDP_TX_STREAM_ID2) || + (Stream == XDP_TX_STREAM_ID3) || + (Stream == XDP_TX_STREAM_ID4)); + Xil_AssertVoid((Enable == 0) || (Enable == 1)); + + MsaConfig = &InstancePtr->TxInstance.MsaConfig[Stream - 1]; + + MsaConfig->SynchronousClockMode = Enable; + + if (Enable == 1) { + MsaConfig->Misc0 |= (1 << + XDP_TX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_SHIFT); + } + else { + MsaConfig->Misc0 &= ~(1 << + XDP_TX_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 XDp instance. + * @param Stream is the stream number for which to set the MSA values for. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxSetVideoMode(XDp *InstancePtr, u8 Stream) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((Stream == XDP_TX_STREAM_ID1) || + (Stream == XDP_TX_STREAM_ID2) || + (Stream == XDP_TX_STREAM_ID3) || + (Stream == XDP_TX_STREAM_ID4)); + + XDp_TxClearMsaValues(InstancePtr, Stream); + XDp_TxSetMsaValues(InstancePtr, Stream); +} + +/******************************************************************************/ +/** + * This function clears the main stream attributes registers of the DisplayPort + * TX core. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param Stream is the stream number for which to clear the MSA values. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxClearMsaValues(XDp *InstancePtr, u8 Stream) +{ + XDp_Config *Config; + u32 StreamOffset[4] = {0, XDP_TX_STREAM2_MSA_START_OFFSET, + XDP_TX_STREAM3_MSA_START_OFFSET, + XDP_TX_STREAM4_MSA_START_OFFSET}; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Stream == XDP_TX_STREAM_ID1) || + (Stream == XDP_TX_STREAM_ID2) || + (Stream == XDP_TX_STREAM_ID3) || + (Stream == XDP_TX_STREAM_ID4)); + + Config = &InstancePtr->Config; + + XDp_WriteReg(Config->BaseAddr, XDP_TX_MAIN_STREAM_HTOTAL + + StreamOffset[Stream - 1], 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_MAIN_STREAM_VTOTAL + + StreamOffset[Stream - 1], 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_MAIN_STREAM_POLARITY + + StreamOffset[Stream - 1], 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_MAIN_STREAM_HSWIDTH + + StreamOffset[Stream - 1], 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_MAIN_STREAM_VSWIDTH + + StreamOffset[Stream - 1], 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_MAIN_STREAM_HRES + + StreamOffset[Stream - 1], 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_MAIN_STREAM_VRES + + StreamOffset[Stream - 1], 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_MAIN_STREAM_HSTART + + StreamOffset[Stream - 1], 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_MAIN_STREAM_VSTART + + StreamOffset[Stream - 1], 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_MAIN_STREAM_MISC0 + + StreamOffset[Stream - 1], 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_MAIN_STREAM_MISC1 + + StreamOffset[Stream - 1], 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_USER_PIXEL_WIDTH + + StreamOffset[Stream - 1], 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_USER_DATA_COUNT_PER_LANE + + StreamOffset[Stream - 1], 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_M_VID + + StreamOffset[Stream - 1], 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_N_VID + + StreamOffset[Stream - 1], 0); + + XDp_WriteReg(Config->BaseAddr, XDP_TX_STREAM1 + (Stream - 1) * 4, 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_TU_SIZE + + StreamOffset[Stream - 1], 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_MIN_BYTES_PER_TU + + StreamOffset[Stream - 1], 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_FRAC_BYTES_PER_TU + + StreamOffset[Stream - 1], 0); + XDp_WriteReg(Config->BaseAddr, XDP_TX_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 XDp instance. + * @param Stream is the stream number for which to set the MSA values for. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_TxSetMsaValues(XDp *InstancePtr, u8 Stream) +{ + XDp_Config *ConfigPtr; + XDp_TxMainStreamAttributes *MsaConfig; + u32 StreamOffset[4] = {0, XDP_TX_STREAM2_MSA_START_OFFSET, + XDP_TX_STREAM3_MSA_START_OFFSET, + XDP_TX_STREAM4_MSA_START_OFFSET}; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_TX); + Xil_AssertVoid((Stream == XDP_TX_STREAM_ID1) || + (Stream == XDP_TX_STREAM_ID2) || + (Stream == XDP_TX_STREAM_ID3) || + (Stream == XDP_TX_STREAM_ID4)); + + ConfigPtr = &InstancePtr->Config; + MsaConfig = &InstancePtr->TxInstance.MsaConfig[Stream - 1]; + + /* Set the main stream attributes to the associated DisplayPort TX core + * registers. */ + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_MAIN_STREAM_HTOTAL + + StreamOffset[Stream - 1], MsaConfig->Vtm.Timing.HTotal); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_MAIN_STREAM_VTOTAL + + StreamOffset[Stream - 1], + MsaConfig->Vtm.Timing.F0PVTotal); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_MAIN_STREAM_POLARITY + + StreamOffset[Stream - 1], + MsaConfig->Vtm.Timing.HSyncPolarity | + (MsaConfig->Vtm.Timing.VSyncPolarity << + XDP_TX_MAIN_STREAMX_POLARITY_VSYNC_POL_SHIFT)); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_MAIN_STREAM_HSWIDTH + + StreamOffset[Stream - 1], MsaConfig->Vtm.Timing.HSyncWidth); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_MAIN_STREAM_VSWIDTH + + StreamOffset[Stream - 1], MsaConfig->Vtm.Timing.F0PVSyncWidth); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_MAIN_STREAM_HRES + + StreamOffset[Stream - 1], + MsaConfig->Vtm.Timing.HActive); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_MAIN_STREAM_VRES + + StreamOffset[Stream - 1], + MsaConfig->Vtm.Timing.VActive); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_MAIN_STREAM_HSTART + + StreamOffset[Stream - 1], MsaConfig->HStart); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_MAIN_STREAM_VSTART + + StreamOffset[Stream - 1], MsaConfig->VStart); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_MAIN_STREAM_MISC0 + + StreamOffset[Stream - 1], MsaConfig->Misc0); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_MAIN_STREAM_MISC1 + + StreamOffset[Stream - 1], MsaConfig->Misc1); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_M_VID + + StreamOffset[Stream - 1], + MsaConfig->PixelClockHz / 1000); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_N_VID + + StreamOffset[Stream - 1], MsaConfig->NVid); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_USER_PIXEL_WIDTH + + StreamOffset[Stream - 1], MsaConfig->UserPixelWidth); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_USER_DATA_COUNT_PER_LANE + + StreamOffset[Stream - 1], MsaConfig->DataPerLane); + + /* Set the transfer unit values to the associated DisplayPort TX core + * registers. */ + if (InstancePtr->TxInstance.MstEnable == 1) { + XDp_WriteReg(ConfigPtr->BaseAddr, + XDP_TX_STREAM1 + (Stream - 1) * 4, + ((MsaConfig->AvgBytesPerTU / 1000) << 16) | + (MsaConfig->AvgBytesPerTU % 1000)); + } + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_TU_SIZE + + StreamOffset[Stream - 1], MsaConfig->TransferUnitSize); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_MIN_BYTES_PER_TU + + StreamOffset[Stream - 1], MsaConfig->AvgBytesPerTU / 1000); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_FRAC_BYTES_PER_TU + + StreamOffset[Stream - 1], MsaConfig->AvgBytesPerTU % 1000); + XDp_WriteReg(ConfigPtr->BaseAddr, XDP_TX_INIT_WAIT + + StreamOffset[Stream - 1], MsaConfig->InitWait); +} + +/******************************************************************************/ +/** + * This function configures the number of pixels output through the user data + * interface. + * + * @param InstancePtr is a pointer to the XDp instance. + * @param UserPixelWidth is the user pixel width to be configured. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDp_RxSetUserPixelWidth(XDp *InstancePtr, u8 UserPixelWidth) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XDp_GetCoreType(InstancePtr) == XDP_RX); + Xil_AssertVoid((UserPixelWidth == 1) || (UserPixelWidth == 2) || + (UserPixelWidth == 4)); + + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_USER_PIXEL_WIDTH, + UserPixelWidth); + + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_SOFT_RESET, 0x1); + XDp_WriteReg(InstancePtr->Config.BaseAddr, XDP_RX_SOFT_RESET, 0x0); +} + +/******************************************************************************/ +/** + * 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 XDp 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 XDp_TxCalculateTs(XDp *InstancePtr, u8 Stream, u8 BitsPerPixel) +{ + XDp_TxMainStreamAttributes *MsaConfig = + &InstancePtr->TxInstance.MsaConfig[Stream - 1]; + XDp_TxLinkConfig *LinkConfig = &InstancePtr->TxInstance.LinkConfig; + double PeakPixelBw; + u32 LinkBw; + double Average_StreamSymbolTimeSlotsPerMTP; + double Target_Average_StreamSymbolTimeSlotsPerMTP; + double MaximumTarget_Average_StreamSymbolTimeSlotsPerMTP; + u32 TsInt; + u32 TsFrac; + + PeakPixelBw = ((double)MsaConfig->PixelClockHz / 1000000) * + ((double)BitsPerPixel / 8); + LinkBw = (LinkConfig->LaneCount * LinkConfig->LinkRate * 27); + + /* Calculate the payload bandiwdth number (PBN). */ + InstancePtr->TxInstance.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->TxInstance.MstStreamConfig[ + Stream - 1].MstPbn)) { + InstancePtr->TxInstance.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->TxInstance.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->TxInstance.MstStreamConfig[Stream - 1].MstPbn = + MsaConfig->TransferUnitSize * + (LinkConfig->LaneCount * LinkConfig->LinkRate / 2); +}