diff --git a/XilinxProcessorIPLib/drivers/dptx/data/dependencies.props b/XilinxProcessorIPLib/drivers/dptx/data/dependencies.props new file mode 100644 index 00000000..0ce1307f --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/data/dependencies.props @@ -0,0 +1,6 @@ +xdptx_audio_example.c=xdptx_example_common.h,xdptx_example_common.c +xdptx_intr_example.c=xdptx_example_common.h,xdptx_example_common.c +xdptx_mst_example.c=xdptx_example_common.h,xdptx_example_common.c +xdptx_poll_example.c=xdptx_example_common.h,xdptx_example_common.c +xdptx_selftest_example.c=xdptx_example_common.h,xdptx_example_common.c +xdptx_timer_example.c=xdptx_example_common.h,xdptx_example_common.c diff --git a/XilinxProcessorIPLib/drivers/dptx/data/dptx.mdd b/XilinxProcessorIPLib/drivers/dptx/data/dptx.mdd new file mode 100644 index 00000000..4d9bea53 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/data/dptx.mdd @@ -0,0 +1,41 @@ +##****************************************************************************** +## +## Copyright (C) 2014 Xilinx, Inc. All rights reserved. +## +## Permission is hereby granted, free of charge, to any person obtaining a copy +## of this software and associated documentation files (the "Software"), to deal +## in the Software without restriction, including without limitation the rights +## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +## copies of the Software, and to permit persons to whom the Software is +## furnished to do so, subject to the following conditions: +## +## The above copyright notice and this permission notice shall be included in +## all copies or substantial portions of the Software. +## +## Use of the Software is limited solely to applications: +## (a) running on a Xilinx device, or +## (b) that interact with a Xilinx device through a bus or interconnect. +## +## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +## XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +## WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +## OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +## SOFTWARE. +## +## Except as contained in this notice, the name of the Xilinx shall not be used +## in advertising or otherwise to promote the sale, use or other dealings in +## this Software without prior written authorization from Xilinx. +## +##*****************************************************************************/ + +OPTION psf_version = 2.1; + +BEGIN driver dptx + OPTION supported_peripherals = (displayport); + OPTION driver_state = ACTIVE; + OPTION copyfiles = all; + OPTION VERSION = 3.0; + OPTION NAME = dptx; +END driver diff --git a/XilinxProcessorIPLib/drivers/dptx/data/dptx.tcl b/XilinxProcessorIPLib/drivers/dptx/data/dptx.tcl new file mode 100644 index 00000000..3a93308e --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/data/dptx.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 THE +## XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +## WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +## OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +## SOFTWARE. +## +## Except as contained in this notice, the name of the Xilinx shall not be used +## in advertising or otherwise to promote the sale, use or other dealings in +## this Software without prior written authorization from Xilinx. +## +##*****************************************************************************/ +proc generate {drv_handle} { + xdefine_include_file $drv_handle "xparameters.h" "XDptx" "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" "S_AXI_ACLK" + xdefine_config_file $drv_handle "xdptx_g.c" "XDptx" "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" + xdefine_canonical_xpars $drv_handle "xparameters.h" "XDptx" "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" "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/dptx/examples/index.html b/XilinxProcessorIPLib/drivers/dptx/examples/index.html new file mode 100755 index 00000000..20f79700 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/examples/index.html @@ -0,0 +1,22 @@ + + + + + +Driver example applications + + + +

Example applications for the dptx_v2_0 driver.

+
+ +

Copyright © 1995-2014 Xilinx, Inc. All rights reserved.

+ + diff --git a/XilinxProcessorIPLib/drivers/dptx/examples/readme.txt b/XilinxProcessorIPLib/drivers/dptx/examples/readme.txt new file mode 100644 index 00000000..d8cee776 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/examples/readme.txt @@ -0,0 +1,62 @@ +There are 6 examples included in this directory: +1) xdptx_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) xdptx_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) xdptx_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) xdptx_poll_example.c : This interrupt example shows how to poll the + DisplayPort TX instance's registers for DisplayPort interrupt events. + +5) xdptx_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) xdptx_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 +xdptx_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 + xdptx_example_common.c. + +Note: All example functions start with Dptx_*, while all driver functions start +with XDptx_*. diff --git a/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_audio_example.c b/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_audio_example.c new file mode 100644 index 00000000..8ac33645 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_audio_example.c @@ -0,0 +1,268 @@ +/******************************************************************************* + * + * Copyright (C) 2014 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xdptx_audio_example.c + * + * Contains a design example using the XDptx driver 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 xdptx_example_common.c). See + * XAPP1178 for reference. + * @note The functions Dptx_PlatformInit and Dptx_StreamSrc* are declared + * extern in xdptx_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  07/29/14 Initial creation.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdptx_example_common.h" + +/**************************** Function Prototypes *****************************/ + +u32 Dptx_AudioExample(XDptx *InstancePtr, u16 DeviceId); +static void Dptx_AudioInit(XDptx *InstancePtr); +static void Dptx_ConfigureAudioSrc(XDptx *InstancePtr); +static void Dptx_AudioSendInfoFrame(XDptx *InstancePtr); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function is the main function of the XDptx 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 XDptx audio example. */ + Status = Dptx_AudioExample(&DptxInstance, DPTX_DEVICE_ID); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * The main entry point for the audio example using the XDptx 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 XDptx 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(XDptx *InstancePtr, u16 DeviceId) +{ + u32 Status; + + /* Use single-stream transport (SST) mode for this example. Audio is + * not supported in multi-stream transport (MST) mode. */ + XDptx_MstCfgModeDisable(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); + + XDptx_EnableTrainAdaptive(InstancePtr, TRAIN_ADAPTIVE); + XDptx_SetHasRedriverInPath(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 XDptx 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(XDptx *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. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_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 + * XDPTX_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->LinkConfig.LinkRate == XDPTX_LINK_BW_SET_540GBPS) { + MAud = 512 * Fs; + } + else if (InstancePtr->LinkConfig.LinkRate == + XDPTX_LINK_BW_SET_270GBPS) { + MAud = 512 * Fs; + } + else if (InstancePtr->LinkConfig.LinkRate == + XDPTX_LINK_BW_SET_162GBPS) { + MAud = 512 * Fs; + } + + /* Write the channel count. The value is (actual count - 1). */ + NumChs = 2; + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_TX_AUDIO_CHANNELS, + NumChs - 1); + + /* NAud = 540000 | 270000 | 162000 */ + NAud = 27 * InstancePtr->LinkConfig.LinkRate * 1000; + + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_TX_AUDIO_MAUD, MAud); + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_TX_AUDIO_NAUD, NAud); + + /* Enable audio in the DisplayPort TX. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_TX_AUDIO_CONTROL, + 0x1); +} + +/******************************************************************************/ +/** + * This function needs to configure the audio source. + * + * @param InstancePtr is a pointer to the XDptx instance. + * + * @return None. + * + * @note The user needs to implement this. See XAPP1178 and the IP + * documentation for reference. + * +*******************************************************************************/ +static void Dptx_ConfigureAudioSrc(XDptx *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 XDptx 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 + * XDPTX_TX_AUDIO_INFO_DATA. See XAPP1178 and the IP documentation + * for reference. + * +*******************************************************************************/ +static void Dptx_AudioSendInfoFrame(XDptx *InstancePtr) +{ + xil_printf("Dptx_AudioSendInfoFrame: User defined function here.\n"); +} diff --git a/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_example_common.c b/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_example_common.c new file mode 100644 index 00000000..be710932 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_example_common.c @@ -0,0 +1,347 @@ +/******************************************************************************* + * + * Copyright (C) 2014 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xdptx_example_common.c + * + * Contains a design example using the XDptx driver. 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 XDptx driver + * functions. See XAPP1178 as a reference. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  06/17/14 Initial creation.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdptx_example_common.h" +#include "xstatus.h" + +/**************************** Function Prototypes *****************************/ + +static void Dptx_StartVideoStream(XDptx *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 XDptx 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(XDptx *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 XDptx 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(XDptx *InstancePtr, u16 DeviceId) +{ + XDptx_Config *ConfigPtr; + u32 Status; + + /* Obtain the device configuration for the DisplayPort TX core. */ + ConfigPtr = XDptx_LookupConfig(DeviceId); + if (!ConfigPtr) { + return XST_FAILURE; + } + /* Copy the device configuration into the InstancePtr's Config + * structure. */ + XDptx_CfgInitialize(InstancePtr, ConfigPtr, ConfigPtr->BaseAddr); + + /* Initialize the DisplayPort TX core. */ + Status = XDptx_InitializeTx(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 XDptx instance. + * + * @return + * - XST_SUCCESS the if main link was successfully established. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 Dptx_StartLink(XDptx *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 = XDptx_GetRxCapabilities(InstancePtr); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + +#if (TRAIN_USE_MAX_LINK == 1) + LaneCount = InstancePtr->LinkConfig.MaxLaneCount; + LinkRate = InstancePtr->LinkConfig.MaxLinkRate; +#else + LaneCount = TRAIN_USE_LANE_COUNT; + LinkRate = TRAIN_USE_LINK_RATE; +#endif + + /* Check if the link is already trained */ + Status = XDptx_CheckLinkStatus(InstancePtr, LaneCount); + if (Status == XST_SUCCESS) { + xil_printf("-> Link is already trained on %d lanes.\n", + LaneCount); + if (XDptx_ReadReg(InstancePtr->Config.BaseAddr, + XDPTX_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; + } + + XDptx_SetEnhancedFrameMode(InstancePtr, 1); + XDptx_SetDownspread(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 = XDptx_CfgMainLinkMax(InstancePtr); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } +#else + XDptx_SetLinkRate(InstancePtr, LinkRate); + XDptx_SetLaneCount(InstancePtr, LaneCount); +#endif + + /* Train the link. */ + xil_printf("******************************************\n"); + Status = XDptx_EstablishLink(InstancePtr); + if (Status != XST_SUCCESS) { + xil_printf("!!! Training failed !!!\n"); + xil_printf("******************************************\n"); + return XST_FAILURE; + } + + VsLevelTx = XDptx_ReadReg(InstancePtr->Config.BaseAddr, + XDPTX_PHY_VOLTAGE_DIFF_LANE_0); + PeLevelTx = XDptx_ReadReg(InstancePtr->Config.BaseAddr, + XDPTX_PHY_POSTCURSOR_LANE_0); + xil_printf("!!! Training passed at LR:0x%02lx LC:%d !!!\n", + InstancePtr->LinkConfig.LinkRate, + InstancePtr->LinkConfig.LaneCount); + xil_printf("VS:%d (TX:%d) PE:%d (TX:%d)\n", + InstancePtr->LinkConfig.VsLevel, VsLevelTx, + InstancePtr->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 XDptx 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(XDptx *InstancePtr) +{ + u32 Status; + u8 Edid[XDPTX_EDID_SIZE]; + + /* Set the bits per color. If not set, the default is 6. */ + XDptx_CfgMsaSetBpc(InstancePtr, XDPTX_STREAM_ID0, 8); + + /* Set synchronous clock mode. */ + XDptx_CfgMsaEnSynchClkMode(InstancePtr, XDPTX_STREAM_ID0, 1); + + XDptx_ClearMsaValues(InstancePtr, XDPTX_STREAM_ID0); + XDptx_ClearMsaValues(InstancePtr, XDPTX_STREAM_ID1); + XDptx_ClearMsaValues(InstancePtr, XDPTX_STREAM_ID2); + XDptx_ClearMsaValues(InstancePtr, XDPTX_STREAM_ID3); + +/* 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[XDPTX_EDID_SIZE]; + * XDptx_GetEdid(InstancePtr, Edid); + * XDptx_CfgMsaUseEdidPreferredTiming(InstancePtr, XDPTX_STREAM_ID0, Edid); + * + * 2) Use a standard video timing mode (see mode_table.h): + * XDptx_CfgMsaUseStandardVideoMode(InstancePtr, XDPTX_STREAM_ID0, + XDPTX_VM_640x480_60_P); + * + * 3) Use a custom configuration for the main stream attributes (MSA): + * XDptx_MainStreamAttributes 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; + * XDptx_CfgMsaUseCustom(InstancePtr, XDPTX_STREAM_ID0, + * &MsaConfigCustom, 1); + * + * To override the user pixel width: + * InstancePtr->MsaConfig[_STREAM#_].OverrideUserPixelWidth = 1; + * InstancePtr->MsaConfig[_STREAM#_].UserPixelWidth = _DESIRED_VALUE_; + * Then, use one of the methods above to calculate the rest of the MSA. + */ + Status = XDptx_GetEdid(InstancePtr, Edid); + if (Status == XST_SUCCESS) { + XDptx_CfgMsaUseEdidPreferredTiming(InstancePtr, + XDPTX_STREAM_ID0, Edid); + } + else { + XDptx_CfgMsaUseStandardVideoMode(InstancePtr, XDPTX_STREAM_ID0, + XDPTX_VM_640x480_60_P); + } + + /* Disable MST for this example. */ + XDptx_MstDisable(InstancePtr); + + /* Disable main stream to force sending of IDLE patterns. */ + XDptx_DisableMainLink(InstancePtr); + + /* Reset the transmitter. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_SOFT_RESET, + XDPTX_SOFT_RESET_VIDEO_STREAM_ALL_MASK); + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_SOFT_RESET, 0x0); + + /* Set the DisplayPort TX video mode. */ + XDptx_SetVideoMode(InstancePtr, XDPTX_STREAM_ID0); + + /* 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); + /*********************************/ + + XDptx_EnableMainLink(InstancePtr); +} diff --git a/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_example_common.h b/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_example_common.h new file mode 100644 index 00000000..62a4c6b0 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_example_common.h @@ -0,0 +1,136 @@ +/******************************************************************************* + * + * Copyright (C) 2014 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xdptx_example_common.h + * + * Contains a design example using the XDptx driver. 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 XDptx driver + * functions. See XAPP1178 as a reference. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  06/17/14 Initial creation.
+ * 
+ * +*******************************************************************************/ + +#ifndef XDPTX_EXAMPLE_COMMON_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XDPTX_EXAMPLE_COMMON_H_ + +/******************************* Include Files ********************************/ + +#include "xdptx.h" +#include "xil_printf.h" +#include "xil_types.h" +#include "xparameters.h" +#include "xstatus.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 + * XDptx_EnableTrainAdaptive 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 + * XDptx_SetHasRedriverInPath 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: + * XDPTX_LINK_BW_SET_540GBPS, XDPTX_LINK_BW_SET_270GBPS, and + * XDPTX_LINK_BW_SET_162GBPS. */ +#define TRAIN_USE_LINK_RATE XDPTX_LINK_BW_SET_540GBPS +/* The lane count setting to begin link training with. Valid values are: + * XDPTX_LANE_COUNT_SET_4, XDPTX_LANE_COUNT_SET_2, and + * XDPTX_LANE_COUNT_SET_1. */ +#define TRAIN_USE_LANE_COUNT XDPTX_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(XDptx *InstancePtr); +extern u32 Dptx_StreamSrcSetup(XDptx *InstancePtr); +extern u32 Dptx_StreamSrcConfigure(XDptx *InstancePtr); + +u32 Dptx_SetupExample(XDptx *InstancePtr, u16 DeviceId); +u32 Dptx_StartLink(XDptx *InstancePtr); +u32 Dptx_Run(XDptx *InstancePtr); + +/*************************** Variable Declarations ****************************/ + +XDptx DptxInstance; + +#endif /* XDPTX_EXAMPLE_COMMON_H_ */ diff --git a/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_intr_example.c b/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_intr_example.c new file mode 100644 index 00000000..69a0f44f --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_intr_example.c @@ -0,0 +1,351 @@ +/******************************************************************************* + * + * Copyright (C) 2014 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xdptx_intr_example.c + * + * Contains a design example using the XDptx driver 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 xdptx_example_common.c). See + * XAPP1178 for reference. + * @note The functions Dptx_PlatformInit and Dptx_StreamSrc* are declared + * extern in xdptx_example_common.h and are left up to the user to + * implement. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  06/17/14 Initial creation.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdptx_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(XDptx *InstancePtr, u16 DeviceId, INTC *IntcPtr, + u16 IntrId, u16 DpIntrId, XDptx_HpdEventHandler HpdEventHandler, + XDptx_HpdPulseHandler HpdPulseHandler); +static u32 Dptx_SetupInterruptHandler(XDptx *InstancePtr, INTC *IntcPtr, + u16 IntrId, u16 DpIntrId, XDptx_HpdEventHandler HpdEventHandler, + XDptx_HpdPulseHandler 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(&DptxInstance, 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 XDptx 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 XDptx 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(XDptx *InstancePtr, u16 DeviceId, INTC *IntcPtr, + u16 IntrId, u16 DpIntrId, XDptx_HpdEventHandler HpdEventHandler, + XDptx_HpdPulseHandler HpdPulseHandler) +{ + u32 Status; + + /* Use single-stream transport (SST) mode for this example. */ + XDptx_MstCfgModeDisable(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; + } + + XDptx_EnableTrainAdaptive(InstancePtr, TRAIN_ADAPTIVE); + XDptx_SetHasRedriverInPath(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 XDptx 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(XDptx *InstancePtr, INTC *IntcPtr, + u16 IntrId, u16 DpIntrId, XDptx_HpdEventHandler HpdEventHandler, + XDptx_HpdPulseHandler HpdPulseHandler) +{ + u32 Status; + + /* Set the HPD interrupt handlers. */ + XDptx_SetHpdEventHandler(InstancePtr, HpdEventHandler, InstancePtr); + XDptx_SetHpdPulseHandler(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)XDptx_HpdInterruptHandler, InstancePtr); +#else + Status = XScuGic_Connect(IntcPtr, DpIntrId, + (Xil_InterruptHandler)XDptx_HpdInterruptHandler, 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 XDPTX_INTERRUPT_STATUS_HPD_EVENT_MASK bit of the + * core's XDPTX_INTERRUPT_STATUS register indicates that an HPD event has + * occurred. + * + * @param InstancePtr is a pointer to the XDptx instance. + * + * @return None. + * + * @note Use the XDptx_SetHpdEventHandler driver function to set this + * function as the handler for HPD pulses. + * +*******************************************************************************/ +static void Dptx_HpdEventHandler(void *InstancePtr) +{ + XDptx *XDptx_InstancePtr = (XDptx *)InstancePtr; + + if (XDptx_IsConnected(XDptx_InstancePtr)) { + xil_printf("+===> HPD connection event detected.\n"); + + Dptx_Run(XDptx_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 XDPTX_INTERRUPT_STATUS_HPD_PULSE_DETECTED_MASK bit + * of the core's XDPTX_INTERRUPT_STATUS register indicates that an HPD event has + * occurred. + * + * @param InstancePtr is a pointer to the XDptx instance. + * + * @return None. + * + * @note Use the XDptx_SetHpdPulseHandler driver function to set this + * function as the handler for HPD pulses. + * +*******************************************************************************/ +static void Dptx_HpdPulseHandler(void *InstancePtr) +{ + XDptx *XDptx_InstancePtr = (XDptx *)InstancePtr; + + xil_printf("===> HPD pulse detected.\n"); + + Dptx_Run(XDptx_InstancePtr); +} diff --git a/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_mst_example.c b/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_mst_example.c new file mode 100644 index 00000000..18eb2c24 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_mst_example.c @@ -0,0 +1,385 @@ +/******************************************************************************* + * + * Copyright (C) 2014 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xdptx_mst_example.c + * + * Contains a design example using the XDptx driver 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 xdptx_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  08/07/14 Initial creation.
+ * 2.0   als  09/23/14 Improved programming sequence for payload allocation.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdptx_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 XDptx_SetStreamSelectFromSinkList 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 XDptx_FindAccessibleDpDevices driver + * function. */ +#define STREAM0_USE_SINKNUM 0 +#define STREAM1_USE_SINKNUM 1 +#define STREAM2_USE_SINKNUM 2 +#define STREAM3_USE_SINKNUM 3 +#endif + +/* The video resolution from the display mode timings (DMT) table to use for + * each stream. */ +#define USE_VIDEO_MODE XDPTX_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(XDptx *InstancePtr, u16 DeviceId); +u32 Dptx_MstExampleRun(XDptx *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(&DptxInstance, DPTX_DEVICE_ID); + + return XST_FAILURE; +} + +/******************************************************************************/ +/** + * The main entry point for the multi-stream transport (MST) example using the + * XDptx 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 XDptx 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(XDptx *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 = XDptx_MstCapable(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 XDptx 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(XDptx *InstancePtr) +{ + u32 Status; + u32 MaskVal; + u8 StreamIndex; + XDptx_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; + } + + XDptx_EnableTrainAdaptive(InstancePtr, TRAIN_ADAPTIVE); + XDptx_SetHasRedriverInPath(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->AuxDelayUs = 30000; + InstancePtr->SbMsgDelayUs = 100000; +#else + InstancePtr->AuxDelayUs = 0; + InstancePtr->SbMsgDelayUs = 0; +#endif + + XDptx_ClearMsaValues(InstancePtr, XDPTX_STREAM_ID0); + XDptx_ClearMsaValues(InstancePtr, XDPTX_STREAM_ID1); + XDptx_ClearMsaValues(InstancePtr, XDPTX_STREAM_ID2); + XDptx_ClearMsaValues(InstancePtr, XDPTX_STREAM_ID3); + +#ifdef ALLOCATE_FROM_SINKLIST + /* Run topology discovery to determine what devices are accessible to + * the DisplayPort TX. */ + xil_printf("Find topology >>>\n"); + InstancePtr->Topology.NodeTotal = 0; + InstancePtr->Topology.SinkTotal = 0; + + Status = XDptx_DiscoverTopology(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->Topology.SinkTotal); + + if (NumStreams > InstancePtr->Topology.SinkTotal) { + NumStreams = InstancePtr->Topology.SinkTotal; + } +#endif + + /* Enable multi-stream transport (MST) mode for this example. */ + XDptx_MstCfgModeEnable(InstancePtr); + for (StreamIndex = 0; StreamIndex < NumStreams; StreamIndex++) { + XDptx_MstCfgStreamEnable(InstancePtr, XDPTX_STREAM_ID0 + + StreamIndex); + } + for (StreamIndex = NumStreams; StreamIndex < 4; StreamIndex++) { + XDptx_MstCfgStreamDisable(InstancePtr, XDPTX_STREAM_ID0 + + 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 (XDptx_MstStreamIsEnabled(InstancePtr, XDPTX_STREAM_ID0)) { + Lct = 2; Rad[0] = 8; + XDptx_SetStreamSinkRad(InstancePtr, XDPTX_STREAM_ID0, Lct, Rad); + } + if (XDptx_MstStreamIsEnabled(InstancePtr, XDPTX_STREAM_ID1)) { + Lct = 3; Rad[0] = 1; Rad[1] = 8; + XDptx_SetStreamSinkRad(InstancePtr, XDPTX_STREAM_ID1, Lct, Rad); + } + if (XDptx_MstStreamIsEnabled(InstancePtr, XDPTX_STREAM_ID2)) { + Lct = 4; Rad[0] = 1; Rad[1] = 1; Rad[2] = 8; + XDptx_SetStreamSinkRad(InstancePtr, XDPTX_STREAM_ID2, Lct, Rad); + } + if (XDptx_MstStreamIsEnabled(InstancePtr, XDPTX_STREAM_ID3)) { + Lct = 4; Rad[0] = 1; Rad[1] = 1; Rad[2] = 9; + XDptx_SetStreamSinkRad(InstancePtr, XDPTX_STREAM_ID3, 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 (XDptx_MstStreamIsEnabled(InstancePtr, XDPTX_STREAM_ID0)) { + XDptx_SetStreamSelectFromSinkList(InstancePtr, XDPTX_STREAM_ID0, + STREAM0_USE_SINKNUM); + } + if (XDptx_MstStreamIsEnabled(InstancePtr, XDPTX_STREAM_ID1)) { + XDptx_SetStreamSelectFromSinkList(InstancePtr, XDPTX_STREAM_ID1, + STREAM1_USE_SINKNUM); + } + if (XDptx_MstStreamIsEnabled(InstancePtr, XDPTX_STREAM_ID2)) { + XDptx_SetStreamSelectFromSinkList(InstancePtr, XDPTX_STREAM_ID2, + STREAM2_USE_SINKNUM); + } + if (XDptx_MstStreamIsEnabled(InstancePtr, XDPTX_STREAM_ID3)) { + XDptx_SetStreamSelectFromSinkList(InstancePtr, XDPTX_STREAM_ID3, + STREAM3_USE_SINKNUM); + } +#endif + + /* Reset MST mode in both the RX and TX. */ + XDptx_MstDisable(InstancePtr); + XDptx_MstEnable(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 (XDptx_MstStreamIsEnabled(InstancePtr, XDPTX_STREAM_ID0 + + StreamIndex)) { + XDptx_CfgMsaSetBpc(InstancePtr, XDPTX_STREAM_ID0 + + StreamIndex, Bpc); + XDptx_CfgMsaEnSynchClkMode(InstancePtr, + XDPTX_STREAM_ID0 + StreamIndex, 1); + + XDptx_CfgMsaUseStandardVideoMode(InstancePtr, + XDPTX_STREAM_ID0 + StreamIndex, VideoMode); + XDptx_SetVideoMode(InstancePtr, XDPTX_STREAM_ID0 + + 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 = XDptx_ReadReg(InstancePtr->Config.BaseAddr, + XDPTX_INTERRUPT_MASK); + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_INTERRUPT_MASK, + 0x3F); + + /* Clear the payload ID table first. */ + Status = XDptx_ClearPayloadVcIdTable(InstancePtr); + if (Status != XST_SUCCESS) { + return XST_DATA_LOST; + } + + /* Allocate payloads. */ + Status = XDptx_AllocatePayloadStreams(InstancePtr); + if (Status != XST_SUCCESS) { + return XST_DATA_LOST; + } + + /* Enable the main link. */ + XDptx_EnableMainLink(InstancePtr); + + /* Unmask interrupts. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_INTERRUPT_MASK, + MaskVal); + + /* Do a final check to verify that the link wasn't lost. */ + Status = XDptx_CheckLinkStatus(InstancePtr, + InstancePtr->LinkConfig.LaneCount); + if (Status != XST_SUCCESS) { + XDptx_WaitUs(InstancePtr, 10000); + return XST_DATA_LOST; + } + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_poll_example.c b/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_poll_example.c new file mode 100644 index 00000000..3e16eeea --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_poll_example.c @@ -0,0 +1,200 @@ +/******************************************************************************* + * + * Copyright (C) 2014 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xdptx_poll_example.c + * + * Contains a design example using the XDptx driver 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 xdptx_example_common.c). See + * XAPP1178 for reference. + * @note The functions Dptx_PlatformInit and Dptx_StreamSrc* are declared + * extern in xdptx_example_common.h and are left up to the user to + * implement. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  06/17/14 Initial creation.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdptx_example_common.h" + +/**************************** Function Prototypes *****************************/ + +u32 Dptx_PollExample(XDptx *InstancePtr, u16 DeviceId); +static void Dptx_HpdPoll(XDptx *InstancePtr); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function is the main function of the XDptx 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 XDptx polling example. */ + Dptx_PollExample(&DptxInstance, DPTX_DEVICE_ID); + + return XST_FAILURE; +} + +/******************************************************************************/ +/** + * The main entry point for the polling example using the XDptx 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 XDptx 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(XDptx *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; + } + + XDptx_EnableTrainAdaptive(InstancePtr, TRAIN_ADAPTIVE); + XDptx_SetHasRedriverInPath(InstancePtr, TRAIN_HAS_REDRIVER); + + /* Continuously poll for HPD events. */ + while (1) { + Dptx_HpdPoll(InstancePtr); + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function polls the XDPTX_INTERRUPT_SIG_STATE and XDPTX_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 XDptx instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void Dptx_HpdPoll(XDptx *InstancePtr) +{ + u32 InterruptSignalState; + u32 InterruptStatus; + u32 HpdState; + u32 HpdEvent; + u32 HpdPulseDetected; + u32 HpdDuration; + + /* Read interrupt registers. */ + InterruptSignalState = XDptx_ReadReg(InstancePtr->Config.BaseAddr, + XDPTX_INTERRUPT_SIG_STATE); + InterruptStatus = XDptx_ReadReg(InstancePtr->Config.BaseAddr, + XDPTX_INTERRUPT_STATUS); + + /* Check for HPD events. */ + HpdState = InterruptSignalState & + XDPTX_INTERRUPT_SIG_STATE_HPD_STATE_MASK; + HpdEvent = InterruptStatus & XDPTX_INTERRUPT_STATUS_HPD_EVENT_MASK; + HpdPulseDetected = InterruptStatus & + XDPTX_INTERRUPT_STATUS_HPD_PULSE_DETECTED_MASK; + if (HpdPulseDetected) { + HpdDuration = XDptx_ReadReg(InstancePtr->Config.BaseAddr, + XDPTX_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. */ + XDptx_DisableMainLink(InstancePtr); + } +} diff --git a/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_selftest_example.c b/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_selftest_example.c new file mode 100644 index 00000000..60a8575c --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_selftest_example.c @@ -0,0 +1,128 @@ +/******************************************************************************* + * + * Copyright (C) 2014 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xdptx_selftest_example.c + * + * Contains a design example using the XDptx driver. It performs a self test on + * the DisplayPort TX core that will compare many of the DisplayPort TX core's + * registers against their default reset values. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  06/17/14 Initial creation.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdptx_example_common.h" + +/**************************** Function Prototypes *****************************/ + +u32 Dptx_SelfTestExample(XDptx *InstancePtr, u16 DeviceId); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function is the main function of the XDptx 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 = Dptx_SelfTestExample(&DptxInstance, DPTX_DEVICE_ID); + if (Status != XST_SUCCESS) { + xil_printf("XDptx_SelfTest failed, check register values.\n"); + return XST_FAILURE; + } + xil_printf("XDptx_SelfTest passed.\n"); + return Status; +} + +/******************************************************************************/ +/** + * The main entry point for the selftest example using the XDptx 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 XDptx 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 Dptx_SelfTestExample(XDptx *InstancePtr, u16 DeviceId) +{ + u32 Status; + XDptx_Config *ConfigPtr; + + /* Obtain the device configuration for the DisplayPort TX core. */ + ConfigPtr = XDptx_LookupConfig(DeviceId); + if (!ConfigPtr) { + return XST_FAILURE; + } + /* Copy the device configuration into the InstancePtr's Config + * structure. */ + XDptx_CfgInitialize(InstancePtr, ConfigPtr, ConfigPtr->BaseAddr); + + /* Run the self test. */ + Status = XDptx_SelfTest(InstancePtr); + return Status; +} diff --git a/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_timer_example.c b/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_timer_example.c new file mode 100644 index 00000000..0dc56cf6 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/examples/xdptx_timer_example.c @@ -0,0 +1,201 @@ +/******************************************************************************* + * + * Copyright (C) 2014 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xdptx_timer_example.c + * + * Contains a design example using the XDptx 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. + * + * @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 xdptx_example_common.c). See + * XAPP1178 for reference. + * @note The functions Dptx_PlatformInit and Dptx_StreamSrc* are declared + * extern in xdptx_example_common.h and are left up to the user to + * implement. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  06/17/14 Initial creation.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdptx_example_common.h" +#include "xtmrctr.h" + +/**************************** Function Prototypes *****************************/ + +u32 Dptx_TimerExample(XDptx *InstancePtr, u16 DeviceId, + XTmrCtr *TimerCounterPtr, XDptx_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(&DptxInstance, 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 XDptx 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 XDptx 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(XDptx *InstancePtr, u16 DeviceId, + XTmrCtr *TimerCounterPtr, XDptx_TimerHandler UserSleepFunc) +{ + u32 Status; + + /* Use single-stream transport (SST) mode for this example. */ + XDptx_MstCfgModeDisable(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. */ + XDptx_SetUserTimerHandler(InstancePtr, UserSleepFunc, TimerCounterPtr); + + Status = Dptx_SetupExample(InstancePtr, DeviceId); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + XDptx_EnableTrainAdaptive(InstancePtr, TRAIN_ADAPTIVE); + XDptx_SetHasRedriverInPath(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 XDptx_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 - XDptx_WaitUs will ignore this custom timer handler. + * + * @param InstancePtr is a pointer to the XDptx instance. + * + * @return None. + * + * @note Use the XDptx_SetUserTimerHandler driver function to set this + * function as the handler for when the XDptx_WaitUs driver + * function is called. + * +*******************************************************************************/ +static void Dptx_CustomWaitUs(void *InstancePtr, u32 MicroSeconds) +{ + XDptx *XDptx_InstancePtr = (XDptx *)InstancePtr; + u32 TimerVal; + + XTmrCtr_Start(XDptx_InstancePtr->UserTimerPtr, 0); + + /* Wait specified number of useconds. */ + do { + TimerVal = XTmrCtr_GetValue(XDptx_InstancePtr->UserTimerPtr, 0); + } + while (TimerVal < (MicroSeconds * + (XDptx_InstancePtr->Config.SAxiClkHz / 1000000))); + + XTmrCtr_Stop(XDptx_InstancePtr->UserTimerPtr, 0); +} diff --git a/XilinxProcessorIPLib/drivers/dptx/src/Makefile b/XilinxProcessorIPLib/drivers/dptx/src/Makefile new file mode 100755 index 00000000..a0e0c61a --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/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 xdptx_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling dptx" + +xdptx_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xdptx_includes + +xdptx_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/XilinxProcessorIPLib/drivers/dptx/src/xdptx.c b/XilinxProcessorIPLib/drivers/dptx/src/xdptx.c new file mode 100644 index 00000000..9a636971 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/src/xdptx.c @@ -0,0 +1,2626 @@ +/******************************************************************************* + * + * Copyright (C) 2014 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xdptx.c + * + * Contains a minimal set of functions for the XDptx driver that allow access + * to all of the DisplayPort TX core's functionality. See xdptx.h for a detailed + * description of the driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  05/17/14 Initial release.
+ * 2.0   als  09/21/14 Added XDptx_IsConnected (previously a macro).
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdptx.h" +#include "xstatus.h" +#if defined(__MICROBLAZE__) +#include "microblaze_sleep.h" +#elif defined(__arm__) +#include "sleep.h" +#endif +#include "xenv.h" + +/**************************** Constant Definitions ****************************/ + +/* The maximum voltage swing level is 3. */ +#define XDPTX_MAXIMUM_VS_LEVEL 3 +/* The maximum pre-emphasis level is 3. */ +#define XDPTX_MAXIMUM_PE_LEVEL 3 + +/* Error out if an AUX request yields a defer reply more than 50 times. */ +#define XDPTX_AUX_MAX_DEFER_COUNT 50 +/* Error out if an AUX request times out more than 50 times awaiting a reply. */ +#define XDPTX_AUX_MAX_TIMEOUT_COUNT 50 +/* Error out if checking for a connected device times out more than 50 times. */ +#define XDPTX_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 { + XDPTX_TS_CLOCK_RECOVERY, + XDPTX_TS_CHANNEL_EQUALIZATION, + XDPTX_TS_ADJUST_LINK_RATE, + XDPTX_TS_ADJUST_LANE_COUNT, + XDPTX_TS_FAILURE, + XDPTX_TS_SUCCESS +} XDptx_TrainingState; + +/** + * 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. */ +} XDptx_AuxTransaction; + +/**************************** Function Prototypes *****************************/ + +/* Training functions. */ +static u32 XDptx_RunTraining(XDptx *InstancePtr); +static XDptx_TrainingState XDptx_TrainingStateClockRecovery(XDptx *InstancePtr); +static XDptx_TrainingState XDptx_TrainingStateChannelEqualization( + XDptx *InstancePtr, u32 MaxIterations); +static XDptx_TrainingState XDptx_TrainingStateAdjustLinkRate( + XDptx *InstancePtr); +static XDptx_TrainingState XDptx_TrainingStateAdjustLaneCount( + XDptx *InstancePtr); +static u32 XDptx_GetLaneStatusAdjReqs(XDptx *InstancePtr); +static u32 XDptx_CheckClockRecovery(XDptx *InstancePtr, u8 LaneCount); +static u32 XDptx_CheckChannelEqualization(XDptx *InstancePtr, u8 LaneCount); +static u32 XDptx_SetVswingPreemp(XDptx *InstancePtr); +static u32 XDptx_AdjVswingPreemp(XDptx *InstancePtr); +static u32 XDptx_SetTrainingPattern(XDptx *InstancePtr, u32 Pattern); +static u32 XDptx_GetTrainingDelay(XDptx *InstancePtr, + XDptx_TrainingState TrainingState); +/* AUX transaction functions. */ +static u32 XDptx_AuxCommon(XDptx *InstancePtr, u32 CmdType, u32 Address, + u32 NumBytes, u8 *Data); +static u32 XDptx_AuxRequest(XDptx *InstancePtr, XDptx_AuxTransaction *Request); +static u32 XDptx_AuxRequestSend(XDptx *InstancePtr, + XDptx_AuxTransaction *Request); +static u32 XDptx_AuxWaitReply(XDptx *InstancePtr); +static u32 XDptx_AuxWaitReady(XDptx *InstancePtr); +/* Miscellaneous functions. */ +static u32 XDptx_SetClkSpeed(XDptx *InstancePtr, u32 Speed); +static u32 XDptx_WaitPhyReady(XDptx *InstancePtr); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function prepares the DisplayPort TX core for use. + * + * @param InstancePtr is a pointer to the XDptx instance. + * + * @return + * - XST_SUCCESS if the DisplayPort TX core was successfully + * initialized. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDptx_InitializeTx(XDptx *InstancePtr) +{ + u32 Status; + u32 RegVal; + XDptx_Config *Config = &InstancePtr->Config; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Place the PHY (and GTTXRESET) into reset. */ + XDptx_WriteReg(Config->BaseAddr, XDPTX_PHY_CONFIG, + XDPTX_PHY_CONFIG_GT_ALL_RESET_MASK); + + /* Disable the DisplayPort TX core. */ + XDptx_WriteReg(Config->BaseAddr, XDPTX_ENABLE, 0); + + /* Set the clock divider. */ + RegVal = (XDptx_ReadReg(Config->BaseAddr, XDPTX_AUX_CLK_DIVIDER) & + ~XDPTX_AUX_CLK_DIVIDER_VAL_MASK) | + (Config->SAxiClkHz / 1000000); + XDptx_WriteReg(Config->BaseAddr, XDPTX_AUX_CLK_DIVIDER, RegVal); + + /* Set the DisplayPort TX core's clock speed. */ + switch (Config->MaxLinkRate) { + case XDPTX_LINK_BW_SET_540GBPS: + XDptx_WriteReg(Config->BaseAddr, XDPTX_PHY_CLOCK_SELECT, + XDPTX_PHY_CLOCK_SELECT_540GBPS); + break; + case XDPTX_LINK_BW_SET_270GBPS: + XDptx_WriteReg(Config->BaseAddr, XDPTX_PHY_CLOCK_SELECT, + XDPTX_PHY_CLOCK_SELECT_270GBPS); + break; + case XDPTX_LINK_BW_SET_162GBPS: + XDptx_WriteReg(Config->BaseAddr, XDPTX_PHY_CLOCK_SELECT, + XDPTX_PHY_CLOCK_SELECT_162GBPS); + break; + default: + break; + } + + /* Bring the PHY (and GTTXRESET) out of reset. */ + XDptx_WriteReg(Config->BaseAddr, XDPTX_PHY_CONFIG, + XDPTX_PHY_CONFIG_PHY_RESET_ENABLE_MASK); + + /* Wait for the PHY to be ready. */ + Status = XDptx_WaitPhyReady(InstancePtr); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* Enable the DisplayPort TX core. */ + XDptx_WriteReg(Config->BaseAddr, XDPTX_ENABLE, 1); + + /* Unmask Hot-Plug-Detect (HPD) interrupts. */ + XDptx_WriteReg(Config->BaseAddr, XDPTX_INTERRUPT_MASK, + ~XDPTX_INTERRUPT_MASK_HPD_PULSE_DETECTED_MASK & + ~XDPTX_INTERRUPT_MASK_HPD_EVENT_MASK & + ~XDPTX_INTERRUPT_MASK_HPD_IRQ_MASK); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function retrieves the configuration for this DisplayPort TX instance + * and fills in the InstancePtr->Config structure. + * + * @param InstancePtr is a pointer to the XDptx 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 XDptx_CfgInitialize(XDptx *InstancePtr, XDptx_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; + + /* Set the DisplayPort TX's voltage swing and pre-emphasis levels to + * their defaults. */ + XDptx_CfgTxVsOffset(InstancePtr, XDPTX_VS_LEVEL_OFFSET); + XDptx_CfgTxVsLevel(InstancePtr, 0, XDPTX_VS_LEVEL_0); + XDptx_CfgTxVsLevel(InstancePtr, 1, XDPTX_VS_LEVEL_1); + XDptx_CfgTxVsLevel(InstancePtr, 2, XDPTX_VS_LEVEL_2); + XDptx_CfgTxVsLevel(InstancePtr, 3, XDPTX_VS_LEVEL_3); + XDptx_CfgTxPeLevel(InstancePtr, 0, XDPTX_PE_LEVEL_0); + XDptx_CfgTxPeLevel(InstancePtr, 1, XDPTX_PE_LEVEL_1); + XDptx_CfgTxPeLevel(InstancePtr, 2, XDPTX_PE_LEVEL_2); + XDptx_CfgTxPeLevel(InstancePtr, 3, XDPTX_PE_LEVEL_3); + + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; +} + +/******************************************************************************/ +/** + * This function retrieves the RX device's capabilities from the RX device's + * DisplayPort Configuration Data (DPCD). + * + * @param InstancePtr is a pointer to the XDptx 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 XDptx_GetRxCapabilities(XDptx *InstancePtr) +{ + u32 Status; + u8 *Dpcd = InstancePtr->RxConfig.DpcdRxCapsField; + XDptx_LinkConfig *LinkConfig = &InstancePtr->LinkConfig; + XDptx_Config *Config = &InstancePtr->Config; + u8 RxMaxLinkRate; + u8 RxMaxLaneCount; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Dpcd != NULL); + Xil_AssertNonvoid(LinkConfig != NULL); + Xil_AssertNonvoid(Config != NULL); + + if (!XDptx_IsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + Status = XDptx_AuxRead(InstancePtr, XDPTX_DPCD_RECEIVER_CAP_FIELD_START, + XDPTX_DPCD_RECEIVER_CAP_FIELD_SIZE, Dpcd); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + RxMaxLinkRate = Dpcd[XDPTX_DPCD_MAX_LINK_RATE]; + RxMaxLaneCount = Dpcd[XDPTX_DPCD_MAX_LANE_COUNT] & + XDPTX_DPCD_MAX_LANE_COUNT_MASK; + LinkConfig->MaxLinkRate = (RxMaxLinkRate > Config->MaxLinkRate) ? + Config->MaxLinkRate : RxMaxLinkRate; + LinkConfig->MaxLaneCount = (RxMaxLaneCount > Config->MaxLaneCount) ? + Config->MaxLaneCount : RxMaxLaneCount; + + LinkConfig->SupportEnhancedFramingMode = + Dpcd[XDPTX_DPCD_MAX_LANE_COUNT] & + XDPTX_DPCD_ENHANCED_FRAME_SUPPORT_MASK; + LinkConfig->SupportDownspreadControl = + Dpcd[XDPTX_DPCD_MAX_DOWNSPREAD] & + XDPTX_DPCD_MAX_DOWNSPREAD_MASK; + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function retrieves the RX device's Extended Display Identification Data + * (EDID). + * + * @param InstancePtr is a pointer to the XDptx 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 XDptx_GetEdid(XDptx *InstancePtr, u8 *Edid) +{ + u32 Status; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Edid != NULL); + + Status = XDptx_IicRead(InstancePtr, XDPTX_EDID_ADDR, 0, XDPTX_EDID_SIZE, + Edid); + + return Status; +} + +/******************************************************************************/ +/** + * This function determines the common capabilities between the DisplayPort TX + * core and the RX device. + * + * @param InstancePtr is a pointer to the XDptx 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 XDptx_CfgMainLinkMax(XDptx *InstancePtr) +{ + u32 Status; + XDptx_LinkConfig *LinkConfig = &InstancePtr->LinkConfig; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + /* The link rate and lane count will be checked in XDptx_SetLinkRate and + * XDptx_SetLaneCount. */ + + if (!XDptx_IsConnected(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 = XDptx_SetLinkRate(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 = XDptx_SetLaneCount(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 XDptx 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 XDptx_EstablishLink(XDptx *InstancePtr) +{ + u32 Status; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((InstancePtr->LinkConfig.LinkRate == + XDPTX_LINK_BW_SET_162GBPS) || + (InstancePtr->LinkConfig.LinkRate == + XDPTX_LINK_BW_SET_270GBPS) || + (InstancePtr->LinkConfig.LinkRate == + XDPTX_LINK_BW_SET_540GBPS)); + /* The lane count will be checked in XDptx_CheckLinkStatus. */ + Xil_AssertNonvoid(InstancePtr->RxConfig.LaneStatusAdjReqs != NULL); + Xil_AssertNonvoid(InstancePtr->RxConfig.DpcdRxCapsField != NULL); + + Status = XDptx_CheckLinkStatus(InstancePtr, + InstancePtr->LinkConfig.LaneCount); + if (Status != XST_FAILURE) { + return Status; + } + + XDptx_ResetPhy(InstancePtr, XDPTX_PHY_CONFIG_PHY_RESET_MASK); + + XDptx_DisableMainLink(InstancePtr); + + /* Train main link. */ + Status = XDptx_RunTraining(InstancePtr); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + XDptx_EnableMainLink(InstancePtr); + + 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 XDptx 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 XDptx_CheckLinkStatus(XDptx *InstancePtr, u8 LaneCount) +{ + u32 Status; + u8 RetryCount = 0; + XDptx_LinkConfig *LinkConfig = &InstancePtr->LinkConfig; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((LaneCount == XDPTX_LANE_COUNT_SET_1) || + (LaneCount == XDPTX_LANE_COUNT_SET_2) || + (LaneCount == XDPTX_LANE_COUNT_SET_4)); + + if (!XDptx_IsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + /* Retrieve AUX info. */ + do { + /* Get lane and adjustment requests. */ + Status = XDptx_GetLaneStatusAdjReqs(InstancePtr); + if (Status != XST_SUCCESS) { + /* The AUX read failed. */ + return XST_FAILURE; + } + + /* Check if the link needs training. */ + if ((XDptx_CheckClockRecovery( + InstancePtr, LaneCount) == XST_SUCCESS) && + (XDptx_CheckChannelEqualization( + 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 XDptx instance. + * @param Enable controls the downshift feature in the training process. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDptx_EnableTrainAdaptive(XDptx *InstancePtr, u8 Enable) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((Enable == 1) || (Enable == 0)); + + InstancePtr->TrainAdaptive = Enable; +} + +/******************************************************************************/ +/** + * This function sets a software switch that signifies whether or not a redriver + * exists on the DisplayPort output path. XDptx_SetVswingPreemp 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 XDptx instance. + * @param Set establishes that a redriver exists in the DisplayPort output + * path. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDptx_SetHasRedriverInPath(XDptx *InstancePtr, u8 Set) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((Set == 1) || (Set == 0)); + + InstancePtr->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 XDptx instance. + * @param Offset is the value to set for the voltage swing offset. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDptx_CfgTxVsOffset(XDptx *InstancePtr, u8 Offset) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((Offset >= 0) && (Offset < 16)); + + InstancePtr->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 XDptx 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 XDptx_CfgTxVsLevel(XDptx *InstancePtr, u8 Level, u8 TxLevel) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((Level >= 0) && (Level < 4)); + Xil_AssertVoid((TxLevel >= 0) && (TxLevel < 16)); + + InstancePtr->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 XDptx 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 XDptx_CfgTxPeLevel(XDptx *InstancePtr, u8 Level, u8 TxLevel) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((Level >= 0) && (Level < 4)); + Xil_AssertVoid((TxLevel >= 0) && (TxLevel < 32)); + + InstancePtr->BoardChar.TxPeLevels[Level] = TxLevel; +} + +/******************************************************************************/ +/** + * This function checks if there is a connected RX device. + * + * @param InstancePtr is a pointer to the XDptx instance. + * + * @return + * - TRUE if there is a connection. + * - FALSE if there is no connection. + * +*******************************************************************************/ +u32 XDptx_IsConnected(XDptx *InstancePtr) +{ + u32 Status; + u8 Retries = 0; + + do { + Status = XDptx_ReadReg(InstancePtr->Config.BaseAddr, + XDPTX_INTERRUPT_SIG_STATE) & + XDPTX_INTERRUPT_SIG_STATE_HPD_STATE_MASK; + + if (Retries > XDPTX_IS_CONNECTED_MAX_TIMEOUT_COUNT) { + return 0; + } + + Retries++; + XDptx_WaitUs(InstancePtr, 1000); + } while (Status == 0); + + return 1; +} + +/******************************************************************************/ +/** + * This function issues a read request over the AUX channel. + * + * @param InstancePtr is a pointer to the XDptx instance. + * @param Address is the starting address to read from the RX device. + * @param NumBytes is the number of bytes to read from the RX device. + * @param Data 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 XDptx_AuxRead(XDptx *InstancePtr, u32 Address, u32 NumBytes, void *Data) +{ + u32 Status; + XDptx_AuxTransaction Request; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Address <= 0xFFFFF); + Xil_AssertNonvoid(NumBytes <= 0xFFFFF); + Xil_AssertNonvoid(Data != NULL); + + if (!XDptx_IsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + /* Send AUX read transaction. */ + Status = XDptx_AuxCommon(InstancePtr, XDPTX_AUX_CMD_READ, Address, + NumBytes, (u8 *)Data); + + return Status; +} + +/******************************************************************************/ +/** + * This function issues a write request over the AUX channel. + * + * @param InstancePtr is a pointer to the XDptx instance. + * @param Address is the starting address to write to the RX device. + * @param NumBytes is the number of bytes to write to the RX device. + * @param Data 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 XDptx_AuxWrite(XDptx *InstancePtr, u32 Address, u32 NumBytes, void *Data) +{ + u32 Status; + XDptx_AuxTransaction Request; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(Address <= 0xFFFFF); + Xil_AssertNonvoid(NumBytes <= 0xFFFFF); + Xil_AssertNonvoid(Data != NULL); + + if (!XDptx_IsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + /* Send AUX write transaction. */ + Status = XDptx_AuxCommon(InstancePtr, XDPTX_AUX_CMD_WRITE, Address, + NumBytes, (u8 *)Data); + + return Status; +} + +/******************************************************************************/ +/** + * This function performs an I2C read over the AUX channel. + * + * @param InstancePtr is a pointer to the XDptx instance. + * @param IicAddress is the address on the I2C bus of the target device. + * @param RegStartAddress is the subaddress of the targeted I2C device + * that the read will start from. + * @param NumBytes is the number of bytes to read. + * @param Data 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 XDptx_IicRead(XDptx *InstancePtr, u8 IicAddress, u8 RegStartAddress, + u8 NumBytes, void *Data) +{ + u32 Status; + XDptx_AuxTransaction Request; + u8 AuxData[2]; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(IicAddress <= 0xFF); + Xil_AssertNonvoid(RegStartAddress <= 0xFF); + Xil_AssertNonvoid(NumBytes <= 0xFF); + Xil_AssertNonvoid(Data != NULL); + + if (!XDptx_IsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + /* Setup the I2C-over-AUX read transaction with the address. */ + Request.Address = IicAddress; + Request.CmdCode = XDPTX_AUX_CMD_I2C_WRITE_MOT; + Request.NumBytes = 2; + AuxData[0] = RegStartAddress; + AuxData[1] = 0; + Request.Data = AuxData; + Status = XDptx_AuxRequest(InstancePtr, &Request); + if (Status != XST_SUCCESS) { + return Status; + } + + /* Send I2C-over-AUX read transaction. */ + Status = XDptx_AuxCommon(InstancePtr, XDPTX_AUX_CMD_I2C_READ, + IicAddress, NumBytes, (u8 *)Data); + + return Status; +} + +/******************************************************************************/ +/** + * This function performs an I2C write over the AUX channel. + * + * @param InstancePtr is a pointer to the XDptx instance. + * @param IicAddress is the address on the I2C bus of the target device. + * @param RegStartAddress is the sub-address of the targeted I2C device + * that the write will start at. + * @param NumBytes is the number of bytes to write. + * @param Data 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 XDptx_IicWrite(XDptx *InstancePtr, u8 IicAddress, u8 RegStartAddress, + u8 NumBytes, void *Data) +{ + u32 Status; + XDptx_AuxTransaction Request; + u8 AuxData[2]; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(IicAddress <= 0xFF); + Xil_AssertNonvoid(RegStartAddress <= 0xFF); + Xil_AssertNonvoid(NumBytes <= 0xFF); + Xil_AssertNonvoid(Data != NULL); + + if (!XDptx_IsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + /* Setup the I2C-over-AUX write transaction with the address. */ + Request.Address = IicAddress; + Request.CmdCode = XDPTX_AUX_CMD_I2C_WRITE_MOT; + Request.NumBytes = 2; + AuxData[0] = RegStartAddress; + AuxData[1] = 0; + Request.Data = AuxData; + Status = XDptx_AuxRequest(InstancePtr, &Request); + if (Status != XST_SUCCESS) { + return Status; + } + + /* Send I2C-over-AUX read transaction. */ + Status = XDptx_AuxCommon(InstancePtr, XDPTX_AUX_CMD_I2C_READ, + IicAddress, NumBytes, (u8 *)Data); + + 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 XDptx 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 XDptx_SetDownspread(XDptx *InstancePtr, u8 Enable) +{ + u32 Status; + u8 RegVal; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((Enable == 1) || (Enable == 0)); + + if (!XDptx_IsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + InstancePtr->LinkConfig.DownspreadControl = Enable; + + /* Write downspread enable to the DisplayPort TX core. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_DOWNSPREAD_CTRL, + InstancePtr->LinkConfig.DownspreadControl); + + /* Preserve the current RX device settings. */ + Status = XDptx_AuxRead(InstancePtr, XDPTX_DPCD_DOWNSPREAD_CTRL, 0x1, + &RegVal); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + if (InstancePtr->LinkConfig.DownspreadControl) { + RegVal |= XDPTX_DPCD_SPREAD_AMP_MASK; + } + else { + RegVal &= ~XDPTX_DPCD_SPREAD_AMP_MASK; + } + + /* Write downspread enable to the RX device. */ + Status = XDptx_AuxWrite(InstancePtr, XDPTX_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 XDptx 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 XDptx_SetEnhancedFrameMode(XDptx *InstancePtr, u8 Enable) +{ + u32 Status; + u8 RegVal; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((Enable == 1) || (Enable == 0)); + + if (!XDptx_IsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + InstancePtr->LinkConfig.EnhancedFramingMode = Enable; + + /* Write enhanced frame mode enable to the DisplayPort TX core. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_ENHANCED_FRAME_EN, + InstancePtr->LinkConfig.EnhancedFramingMode); + + /* Preserve the current RX device settings. */ + Status = XDptx_AuxRead(InstancePtr, XDPTX_DPCD_LANE_COUNT_SET, 0x1, + &RegVal); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + if (InstancePtr->LinkConfig.EnhancedFramingMode) { + RegVal |= XDPTX_DPCD_ENHANCED_FRAME_EN_MASK; + } + else { + RegVal &= ~XDPTX_DPCD_ENHANCED_FRAME_EN_MASK; + } + + /* Write enhanced frame mode enable to the RX device. */ + Status = XDptx_AuxWrite(InstancePtr, XDPTX_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 XDptx 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 XDptx_SetLaneCount(XDptx *InstancePtr, u8 LaneCount) +{ + u32 Status; + u8 RegVal; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((LaneCount == XDPTX_LANE_COUNT_SET_1) || + (LaneCount == XDPTX_LANE_COUNT_SET_2) || + (LaneCount == XDPTX_LANE_COUNT_SET_4)); + + if (!XDptx_IsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + InstancePtr->LinkConfig.LaneCount = LaneCount; + + /* Write the new lane count to the DisplayPort TX core. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_LANE_COUNT_SET, + InstancePtr->LinkConfig.LaneCount); + + /* Preserve the current RX device settings. */ + Status = XDptx_AuxRead(InstancePtr, XDPTX_DPCD_LANE_COUNT_SET, 0x1, + &RegVal); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + RegVal &= ~XDPTX_DPCD_LANE_COUNT_SET_MASK; + RegVal |= InstancePtr->LinkConfig.LaneCount; + + /* Write the new lane count to the RX device. */ + Status = XDptx_AuxWrite(InstancePtr, XDPTX_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 XDptx instance. + * @param LinkRate is the link rate to be used over the main link based on + * one of the following selects: + * - XDPTX_LINK_BW_SET_162GBPS = 0x06 (for a 1.62 Gbps data rate) + * - XDPTX_LINK_BW_SET_270GBPS = 0x0A (for a 2.70 Gbps data rate) + * - XDPTX_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 XDptx_SetLinkRate(XDptx *InstancePtr, u8 LinkRate) +{ + u32 Status; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((LinkRate == XDPTX_LINK_BW_SET_162GBPS) || + (LinkRate == XDPTX_LINK_BW_SET_270GBPS) || + (LinkRate == XDPTX_LINK_BW_SET_540GBPS)); + + if (!XDptx_IsConnected(InstancePtr)) { + return XST_DEVICE_NOT_FOUND; + } + + /* Write a corresponding clock frequency to the DisplayPort TX core. */ + switch (LinkRate) { + case XDPTX_LINK_BW_SET_162GBPS: + Status = XDptx_SetClkSpeed(InstancePtr, + XDPTX_PHY_CLOCK_SELECT_162GBPS); + break; + case XDPTX_LINK_BW_SET_270GBPS: + Status = XDptx_SetClkSpeed(InstancePtr, + XDPTX_PHY_CLOCK_SELECT_270GBPS); + break; + case XDPTX_LINK_BW_SET_540GBPS: + Status = XDptx_SetClkSpeed(InstancePtr, + XDPTX_PHY_CLOCK_SELECT_540GBPS); + break; + default: + break; + } + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + InstancePtr->LinkConfig.LinkRate = LinkRate; + + /* Write new link rate to the DisplayPort TX core. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_LINK_BW_SET, + InstancePtr->LinkConfig.LinkRate); + + /* Write new link rate to the RX device. */ + Status = XDptx_AuxWrite(InstancePtr, XDPTX_DPCD_LINK_BW_SET, 0x1, + &InstancePtr->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 XDptx instance. + * @param Enable will enable or disable scrambling. + * + * @return + * - XST_SUCCESS if setting the scrambling enable was successful. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDptx_SetScrambler(XDptx *InstancePtr, u8 Enable) +{ + u32 Status; + u8 RegVal; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid((Enable == 1) || (Enable == 0)); + + InstancePtr->LinkConfig.ScramblerEn = Enable; + + /* Write scrambler disable to the DisplayPort TX core. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_SCRAMBLING_DISABLE, + Enable ? 0x0 : 0x1); + + /* Preserve the current RX device settings. */ + Status = XDptx_AuxRead(InstancePtr, XDPTX_DPCD_TP_SET, 0x1, &RegVal); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + if (Enable) { + RegVal &= ~XDPTX_DPCD_TP_SET_SCRAMB_DIS_MASK; + } + else { + RegVal |= XDPTX_DPCD_TP_SET_SCRAMB_DIS_MASK; + } + + /* Write scrambler disable to the RX device. */ + Status = XDptx_AuxWrite(InstancePtr, XDPTX_DPCD_TP_SET, 0x1, &RegVal); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function enables the main link. + * + * @param InstancePtr is a pointer to the XDptx instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDptx_EnableMainLink(XDptx *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Reset the scrambler. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, + XDPTX_FORCE_SCRAMBLER_RESET, 0x1); + + /* Enable the main stream. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, + XDPTX_ENABLE_MAIN_STREAM, 0x1); +} + +/******************************************************************************/ +/** + * This function disables the main link. + * + * @param InstancePtr is a pointer to the XDptx instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDptx_DisableMainLink(XDptx *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Reset the scrambler. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, + XDPTX_FORCE_SCRAMBLER_RESET, 0x1); + + /* Disable the main stream. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, + XDPTX_ENABLE_MAIN_STREAM, 0x0); +} + +/******************************************************************************/ +/** + * This function does a PHY reset. + * + * @param InstancePtr is a pointer to the XDptx instance. + * @param Reset is the type of reset to assert. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDptx_ResetPhy(XDptx *InstancePtr, u32 Reset) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_ENABLE, 0x0); + + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_PHY_CONFIG, Reset); + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_PHY_CONFIG, + XDPTX_PHY_CONFIG_PHY_RESET_ENABLE_MASK); + XDptx_WaitPhyReady(InstancePtr); + + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_ENABLE, 0x1); +} + +/******************************************************************************/ +/** + * This function installs a custom delay/sleep function to be used by the XDdptx + * driver. + * + * @param InstancePtr is a pointer to the XDptx 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 XDptx_SetUserTimerHandler(XDptx *InstancePtr, + XDptx_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 XDptx 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 XDptx instance. + * @param MicroSeconds is the number of microseconds to delay/sleep for. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDptx_WaitUs(XDptx *InstancePtr, u32 MicroSeconds) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (MicroSeconds == 0) { + return; + } + +#if 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); + } +#elif defined(__arm__) + /* Wait the requested amount of time. */ + usleep(MicroSeconds); +#endif +} + +/******************************************************************************/ +/** + * 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 XDptx instance. + * + * @return + * - XST_SUCCESS if the training process succeeded. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XDptx_RunTraining(XDptx *InstancePtr) +{ + u32 Status; + XDptx_TrainingState TrainingState = XDPTX_TS_CLOCK_RECOVERY; + + /* Disable scrambler. */ + Status = XDptx_SetScrambler(InstancePtr, 0); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + while (1) { + switch (TrainingState) { + case XDPTX_TS_CLOCK_RECOVERY: + TrainingState = XDptx_TrainingStateClockRecovery( + InstancePtr); + break; + case XDPTX_TS_CHANNEL_EQUALIZATION: + TrainingState = XDptx_TrainingStateChannelEqualization( + InstancePtr, 5); + break; + case XDPTX_TS_ADJUST_LINK_RATE: + TrainingState = XDptx_TrainingStateAdjustLinkRate( + InstancePtr); + break; + case XDPTX_TS_ADJUST_LANE_COUNT: + TrainingState = XDptx_TrainingStateAdjustLaneCount( + InstancePtr); + break; + default: + break; + } + + if (TrainingState == XDPTX_TS_SUCCESS) { + break; + } + else if (TrainingState == XDPTX_TS_FAILURE) { + return XST_FAILURE; + } + + if ((InstancePtr->TrainAdaptive == 0) && + ((TrainingState == XDPTX_TS_ADJUST_LANE_COUNT) || + (TrainingState == XDPTX_TS_ADJUST_LINK_RATE))) { + return XST_FAILURE; + } + } + + /* Turn off the training pattern. */ + Status = XDptx_SetTrainingPattern(InstancePtr, + XDPTX_TRAINING_PATTERN_SET_OFF); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* Enable scrambler. */ + Status = XDptx_SetScrambler(InstancePtr, 1); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* Final status check. */ + Status = XDptx_CheckLinkStatus(InstancePtr, + InstancePtr->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 XDptx instance. + * + * @return The next training state: + * - XDPTX_TS_CHANNEL_EQUALIZATION if the clock recovery sequence + * completed successfully. + * - XDPTX_TS_FAILURE if writing the drive settings to the RX + * device was unsuccesful. + * - XDPTX_TS_ADJUST_LINK_RATE if the clock recovery sequence + * did not complete successfully. + * + * @note None. + * +*******************************************************************************/ +static XDptx_TrainingState XDptx_TrainingStateClockRecovery(XDptx *InstancePtr) +{ + u32 Status; + u32 DelayUs; + u8 PrevVsLevel = 0; + u8 SameVsLevelCount = 0; + XDptx_LinkConfig *LinkConfig = &InstancePtr->LinkConfig; + + /* Obtain the required delay for clock recovery as specified by the + * RX device. */ + DelayUs = XDptx_GetTrainingDelay(InstancePtr, XDPTX_TS_CLOCK_RECOVERY); + + /* Start CRLock. */ + + /* Transmit training pattern 1. */ + Status = XDptx_SetTrainingPattern(InstancePtr, + XDPTX_TRAINING_PATTERN_SET_TP1); + if (Status != XST_SUCCESS) { + return XDPTX_TS_FAILURE; + } + + /* Start from minimal voltage swing and pre-emphasis levels. */ + LinkConfig->VsLevel = 0; + LinkConfig->PeLevel = 0; + Status = XDptx_SetVswingPreemp(InstancePtr); + if (Status != XST_SUCCESS) { + return XDPTX_TS_FAILURE; + } + + while (1) { + /* Wait delay specified in TRAINING_AUX_RD_INTERVAL. */ + XDptx_WaitUs(InstancePtr, DelayUs); + + /* Get lane and adjustment requests. */ + Status = XDptx_GetLaneStatusAdjReqs(InstancePtr); + if (Status != XST_SUCCESS) { + /* The AUX read failed. */ + return XDPTX_TS_FAILURE; + } + + /* Check if all lanes have realized and maintained the frequency + * lock and get adjustment requests. */ + Status = XDptx_CheckClockRecovery(InstancePtr, + InstancePtr->LinkConfig.LaneCount); + if (Status == XST_SUCCESS) { + return XDPTX_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; + } + + /* Adjust the drive settings as requested by the RX device. */ + Status = XDptx_AdjVswingPreemp(InstancePtr); + if (Status != XST_SUCCESS) { + /* The AUX write failed. */ + return XDPTX_TS_FAILURE; + } + } + + return XDPTX_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 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 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 XDptx instance. + * @param MaxIterations is the maximum number of times to loop through the + * clock recovery sequence before down-shifting to a reduced data + * rate or a reduced number of lanes. + * + * @return The next training state: + * - XDPTX_TS_SUCCESS if training succeeded. + * - XDPTX_TS_FAILURE if writing the drive settings to the RX + * device was unsuccesful. + * - XDPTX_TS_ADJUST_LINK_RATE if, after MaxIterations loop + * iterations, the channel equalization sequence did not complete + * successfully. + * + * @note None. + * +*******************************************************************************/ +static XDptx_TrainingState XDptx_TrainingStateChannelEqualization( + XDptx *InstancePtr, u32 MaxIterations) +{ + u32 Status; + u32 DelayUs; + u32 IterationCount = 0; + u8 PrevVsLevel = 0; + u8 SameVsLevelCount = 0; + XDptx_LinkConfig *LinkConfig = &InstancePtr->LinkConfig; + + /* Obtain the required delay for channel equalization as specified by + * the RX device. */ + DelayUs = XDptx_GetTrainingDelay(InstancePtr, + XDPTX_TS_CHANNEL_EQUALIZATION); + + /* Start channel equalization. */ + + /* Write the current drive settings to the RX device. */ + Status = XDptx_SetVswingPreemp(InstancePtr); + if (Status != XST_SUCCESS) { + return XDPTX_TS_FAILURE; + } + + /* Transmit training pattern 2/3. */ + if (InstancePtr->RxConfig.DpcdRxCapsField[XDPTX_DPCD_MAX_LANE_COUNT] & + XDPTX_DPCD_TPS3_SUPPORT_MASK) { + Status = XDptx_SetTrainingPattern(InstancePtr, + XDPTX_TRAINING_PATTERN_SET_TP3); + } + else { + Status = XDptx_SetTrainingPattern(InstancePtr, + XDPTX_TRAINING_PATTERN_SET_TP2); + } + if (Status != XST_SUCCESS) { + return XDPTX_TS_FAILURE; + } + + while (IterationCount < MaxIterations) { + /* Wait delay specified in TRAINING_AUX_RD_INTERVAL. */ + XDptx_WaitUs(InstancePtr, DelayUs); + + /* Get lane and adjustment requests. */ + Status = XDptx_GetLaneStatusAdjReqs(InstancePtr); + if (Status != XST_SUCCESS) { + /* The AUX read failed. */ + return XDPTX_TS_FAILURE; + } + + /* Check that all lanes still have their clocks locked. */ + Status = XDptx_CheckClockRecovery(InstancePtr, + InstancePtr->LinkConfig.LaneCount); + if (Status != XST_SUCCESS) { + break; + } + + /* Check that all lanes stihave accomplished channel + * equalization, symbol lock, and interlane alignment. */ + Status = XDptx_CheckChannelEqualization(InstancePtr, + InstancePtr->LinkConfig.LaneCount); + if (Status == XST_SUCCESS) { + return XDPTX_TS_SUCCESS; + } + + /* 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; + } + + /* Adjust the drive settings as requested by the RX device. */ + Status = XDptx_AdjVswingPreemp(InstancePtr); + if (Status != XST_SUCCESS) { + /* The AUX write failed. */ + return XDPTX_TS_FAILURE; + } + + IterationCount++; + } + + /* Tried MaxIteration times with no success. Try a reduced bitrate + * first, then reduce the number of lanes. */ + return XDPTX_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 XDptx instance. + * + * @return The next training state: + * - XDPTX_TS_ADJUST_LANE_COUNT if the minimal data rate is already + * in use. Re-attempt training at a reduced lane count. + * - XDPTX_TS_CLOCK_RECOVERY otherwise. Re-attempt training. + * + * @note None. + * +*******************************************************************************/ +static XDptx_TrainingState XDptx_TrainingStateAdjustLinkRate(XDptx *InstancePtr) +{ + u32 Status; + + switch (InstancePtr->LinkConfig.LinkRate) { + case XDPTX_LINK_BW_SET_540GBPS: + Status = XDptx_SetLinkRate(InstancePtr, + XDPTX_LINK_BW_SET_270GBPS); + if (Status != XST_SUCCESS) { + Status = XDPTX_TS_FAILURE; + break; + } + Status = XDPTX_TS_CLOCK_RECOVERY; + break; + case XDPTX_LINK_BW_SET_270GBPS: + Status = XDptx_SetLinkRate(InstancePtr, + XDPTX_LINK_BW_SET_162GBPS); + if (Status != XST_SUCCESS) { + Status = XDPTX_TS_FAILURE; + break; + } + Status = XDPTX_TS_CLOCK_RECOVERY; + break; + default: + /* Already at the lowest link rate. Try reducing the lane + * count next. */ + Status = XDPTX_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 XDptx instance. + * + * @return The next training state: + * - XDPTX_TS_FAILURE if only one lane is already in use. + * - XDPTX_TS_CLOCK_RECOVERY otherwise. Re-attempt training. + * + * @note None. + * +*******************************************************************************/ +static XDptx_TrainingState XDptx_TrainingStateAdjustLaneCount( + XDptx *InstancePtr) +{ + u32 Status; + XDptx_LinkConfig *LinkConfig = &InstancePtr->LinkConfig; + + switch (LinkConfig->LaneCount) { + case XDPTX_LANE_COUNT_SET_4: + Status = XDptx_SetLaneCount(InstancePtr, + XDPTX_LANE_COUNT_SET_2); + if (Status != XST_SUCCESS) { + Status = XDPTX_TS_FAILURE; + break; + } + + Status = XDptx_SetLinkRate(InstancePtr, + LinkConfig->MaxLinkRate); + if (Status != XST_SUCCESS) { + Status = XDPTX_TS_FAILURE; + break; + } + Status = XDPTX_TS_CLOCK_RECOVERY; + break; + case XDPTX_LANE_COUNT_SET_2: + Status = XDptx_SetLaneCount(InstancePtr, + XDPTX_LANE_COUNT_SET_1); + if (Status != XST_SUCCESS) { + Status = XDPTX_TS_FAILURE; + break; + } + + Status = XDptx_SetLinkRate(InstancePtr, + LinkConfig->MaxLinkRate); + if (Status != XST_SUCCESS) { + Status = XDPTX_TS_FAILURE; + break; + } + Status = XDPTX_TS_CLOCK_RECOVERY; + break; + default: + /* Already at the lowest lane count. Training has failed at the + * lowest lane count and link rate. */ + Status = XDPTX_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 + * XDptx_CheckClockRecovery, XDptx_CheckChannelEqualization, and + * XDptx_AdjVswingPreemp. + * + * @param InstancePtr is a pointer to the XDptx instance. + * + * @return + * - XST_SUCCESS if the AUX read was successful. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XDptx_GetLaneStatusAdjReqs(XDptx *InstancePtr) +{ + u32 Status; + + /* Read and store 4 bytes of lane status and 2 bytes of adjustment + * requests. */ + Status = XDptx_AuxRead(InstancePtr, XDPTX_DPCD_STATUS_LANE_0_1, + 6, InstancePtr->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 XDptx 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 XDptx_CheckClockRecovery(XDptx *InstancePtr, u8 LaneCount) +{ + u32 Status; + u8 AuxData[6]; + + u8 *LaneStatus = InstancePtr->RxConfig.LaneStatusAdjReqs; + + /* Check that all LANEx_CR_DONE bits are set. */ + switch (LaneCount) { + case XDPTX_LANE_COUNT_SET_4: + if (!(LaneStatus[1] & + XDPTX_DPCD_STATUS_LANE_3_CR_DONE_MASK)) { + return XST_FAILURE; + } + if (!(LaneStatus[1] & + XDPTX_DPCD_STATUS_LANE_2_CR_DONE_MASK)) { + return XST_FAILURE; + } + /* Drop through and check lane 1. */ + case XDPTX_LANE_COUNT_SET_2: + if (!(LaneStatus[0] & + XDPTX_DPCD_STATUS_LANE_1_CR_DONE_MASK)) { + return XST_FAILURE; + } + /* Drop through and check lane 0. */ + case XDPTX_LANE_COUNT_SET_1: + if (!(LaneStatus[0] & + XDPTX_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 XDptx 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 XDptx_CheckChannelEqualization(XDptx *InstancePtr, u8 LaneCount) +{ + u32 Status; + u8 AuxData[6]; + u8 *LaneStatus = InstancePtr->RxConfig.LaneStatusAdjReqs; + + /* Check that all LANEx_CHANNEL_EQ_DONE bits are set. */ + switch (LaneCount) { + case XDPTX_LANE_COUNT_SET_4: + if (!(LaneStatus[1] & + XDPTX_DPCD_STATUS_LANE_3_CE_DONE_MASK)) { + return XST_FAILURE; + } + if (!(LaneStatus[1] & + XDPTX_DPCD_STATUS_LANE_2_CE_DONE_MASK)) { + return XST_FAILURE; + } + /* Drop through and check lane 1. */ + case XDPTX_LANE_COUNT_SET_2: + if (!(LaneStatus[0] & + XDPTX_DPCD_STATUS_LANE_1_CE_DONE_MASK)) { + return XST_FAILURE; + } + /* Drop through and check lane 0. */ + case XDPTX_LANE_COUNT_SET_1: + if (!(LaneStatus[0] & + XDPTX_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 XDPTX_LANE_COUNT_SET_4: + if (!(LaneStatus[1] & + XDPTX_DPCD_STATUS_LANE_3_SL_DONE_MASK)) { + return XST_FAILURE; + } + if (!(LaneStatus[1] & + XDPTX_DPCD_STATUS_LANE_2_SL_DONE_MASK)) { + return XST_FAILURE; + } + /* Drop through and check lane 1. */ + case XDPTX_LANE_COUNT_SET_2: + if (!(LaneStatus[0] & + XDPTX_DPCD_STATUS_LANE_1_SL_DONE_MASK)) { + return XST_FAILURE; + } + /* Drop through and check lane 0. */ + case XDPTX_LANE_COUNT_SET_1: + if (!(LaneStatus[0] & + XDPTX_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] & + XDPTX_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 XDptx instance. + * + * @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 u32 XDptx_SetVswingPreemp(XDptx *InstancePtr) +{ + u32 Status; + u8 Data; + u8 AuxData[4]; + u8 Index; + u8 VsLevelRx = InstancePtr->LinkConfig.VsLevel; + u8 PeLevelRx = InstancePtr->LinkConfig.PeLevel; + u32 VsLevel; + u32 PeLevel; + + if (InstancePtr->BoardChar.HasRedriverInPath == 0) { + PeLevel = InstancePtr->BoardChar.TxPeLevels[PeLevelRx]; + VsLevel = InstancePtr->BoardChar.TxVsLevels[VsLevelRx]; + + /* Need to compensate due to no redriver in the path. */ + if (PeLevelRx != 0) { + VsLevel += InstancePtr->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 << XDPTX_DPCD_TRAINING_LANEX_SET_PE_SHIFT) | + VsLevelRx; + /* The maximum voltage swing has been reached. */ + if (VsLevelRx == XDPTX_MAXIMUM_VS_LEVEL) { + Data |= XDPTX_DPCD_TRAINING_LANEX_SET_MAX_VS_MASK; + } + /* The maximum pre-emphasis level has been reached. */ + if (PeLevelRx == XDPTX_MAXIMUM_PE_LEVEL) { + Data |= XDPTX_DPCD_TRAINING_LANEX_SET_MAX_PE_MASK; + } + memset(AuxData, Data, InstancePtr->LinkConfig.LaneCount); + + for (Index = 0; Index < InstancePtr->LinkConfig.LaneCount; Index++) { + /* Disable pre-cursor levels. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, + XDPTX_PHY_PRECURSOR_LANE_0 + 4 * Index, 0x0); + + /* Write new voltage swing levels to the TX registers. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, + XDPTX_PHY_VOLTAGE_DIFF_LANE_0 + 4 * Index, VsLevel); + + /* Write new pre-emphasis levels to the TX registers. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, + XDPTX_PHY_POSTCURSOR_LANE_0 + 4 * Index, PeLevel); + } + + /* Write the voltage swing and pre-emphasis levels for each lane to the + * RX device. */ + Status = XDptx_AuxWrite(InstancePtr, XDPTX_DPCD_TRAINING_LANE0_SET, + InstancePtr->LinkConfig.LaneCount, AuxData); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * 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 XDptx instance. + * + * @return + * - XST_SUCCESS if the new levels were written successfully. + * - XST_FAILURE otherwise (an AUX transaction failed). + * + * @note None. + * +*******************************************************************************/ +static u32 XDptx_AdjVswingPreemp(XDptx *InstancePtr) +{ + u32 Status; + u8 Index; + u8 VsLevelAdjReq[4]; + u8 PeLevelAdjReq[4]; + u8 *AdjReqs = &InstancePtr->RxConfig.LaneStatusAdjReqs[4]; + + /* Analyze the adjustment requests for changes in voltage swing and + * pre-emphasis levels. */ + VsLevelAdjReq[0] = AdjReqs[0] & XDPTX_DPCD_ADJ_REQ_LANE_0_2_VS_MASK; + VsLevelAdjReq[1] = (AdjReqs[0] & XDPTX_DPCD_ADJ_REQ_LANE_1_3_VS_MASK) >> + XDPTX_DPCD_ADJ_REQ_LANE_1_3_VS_SHIFT; + VsLevelAdjReq[2] = AdjReqs[1] & XDPTX_DPCD_ADJ_REQ_LANE_0_2_VS_MASK; + VsLevelAdjReq[3] = (AdjReqs[1] & XDPTX_DPCD_ADJ_REQ_LANE_1_3_VS_MASK) >> + XDPTX_DPCD_ADJ_REQ_LANE_1_3_VS_SHIFT; + PeLevelAdjReq[0] = (AdjReqs[0] & XDPTX_DPCD_ADJ_REQ_LANE_0_2_PE_MASK) >> + XDPTX_DPCD_ADJ_REQ_LANE_0_2_PE_SHIFT; + PeLevelAdjReq[1] = (AdjReqs[0] & XDPTX_DPCD_ADJ_REQ_LANE_1_3_PE_MASK) >> + XDPTX_DPCD_ADJ_REQ_LANE_1_3_PE_SHIFT; + PeLevelAdjReq[2] = (AdjReqs[1] & XDPTX_DPCD_ADJ_REQ_LANE_0_2_PE_MASK) >> + XDPTX_DPCD_ADJ_REQ_LANE_0_2_PE_SHIFT; + PeLevelAdjReq[3] = (AdjReqs[1] & XDPTX_DPCD_ADJ_REQ_LANE_1_3_PE_MASK) >> + XDPTX_DPCD_ADJ_REQ_LANE_1_3_PE_SHIFT; + + /* Change the drive settings to match the adjustment requests. Use the + * greatest level requested. */ + InstancePtr->LinkConfig.VsLevel = 0; + InstancePtr->LinkConfig.PeLevel = 0; + for (Index = 0; Index < InstancePtr->LinkConfig.LaneCount; Index++) { + if (VsLevelAdjReq[Index] >InstancePtr->LinkConfig.VsLevel) { + InstancePtr->LinkConfig.VsLevel = VsLevelAdjReq[Index]; + } + if (PeLevelAdjReq[Index] >InstancePtr->LinkConfig.PeLevel) { + InstancePtr->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->LinkConfig.PeLevel > + (4 - InstancePtr->LinkConfig.VsLevel)) { + InstancePtr->LinkConfig.PeLevel = + 4 - InstancePtr->LinkConfig.VsLevel; + } + + /* Make the adjustments to both the DisplayPort TX core and the RX + * device. */ + Status = XDptx_SetVswingPreemp(InstancePtr); + 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 XDptx instance. + * @param Pattern selects the pattern to be used. One of the following: + * - XDPTX_TRAINING_PATTERN_SET_OFF + * - XDPTX_TRAINING_PATTERN_SET_TP1 + * - XDPTX_TRAINING_PATTERN_SET_TP2 + * - XDPTX_TRAINING_PATTERN_SET_TP3 + * + * @return + * - XST_SUCCESS if setting the pattern was successful. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XDptx_SetTrainingPattern(XDptx *InstancePtr, u32 Pattern) +{ + u32 Status; + u8 RegVal; + + /* Write to the DisplayPort TX core. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, + XDPTX_TRAINING_PATTERN_SET, Pattern); + + /* Preserve the current RX device settings. */ + Status = XDptx_AuxRead(InstancePtr, XDPTX_DPCD_TP_SET, 1, &RegVal); + RegVal &= ~XDPTX_DPCD_TP_SEL_MASK; + RegVal |= (Pattern & XDPTX_DPCD_TP_SEL_MASK); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* Write to the RX device. */ + Status = XDptx_AuxWrite(InstancePtr, XDPTX_DPCD_TP_SET, 1, &RegVal); + 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 XDptx 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, + * XDPTX_DPCD_TRAIN_AUX_RD_INTERVAL. + * + * @note None. + * +*******************************************************************************/ +static u32 XDptx_GetTrainingDelay(XDptx *InstancePtr, + XDptx_TrainingState TrainingState) +{ + u8 *Dpcd = InstancePtr->RxConfig.DpcdRxCapsField; + u16 Delay; + + switch (Dpcd[XDPTX_DPCD_TRAIN_AUX_RD_INTERVAL]) { + case XDPTX_DPCD_TRAIN_AUX_RD_INT_100_400US: + if (TrainingState == XDPTX_TS_CLOCK_RECOVERY) { + /* Delay for the clock recovery phase. */ + Delay = 100; + } + else { + /* Delay for the channel equalization phase. */ + Delay = 400; + } + break; + case XDPTX_DPCD_TRAIN_AUX_RD_INT_4MS: + Delay = 4000; + break; + case XDPTX_DPCD_TRAIN_AUX_RD_INT_8MS: + Delay = 8000; + break; + case XDPTX_DPCD_TRAIN_AUX_RD_INT_12MS: + Delay = 12000; + break; + case XDPTX_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. + * + * @param InstancePtr is a pointer to the XDptx instance. + * @param CmdType is the type of AUX command (one of: XDPTX_AUX_CMD_READ, + * XDPTX_AUX_CMD_WRITE, XDPTX_AUX_CMD_I2C_READ, or + * XDPTX_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 XDptx_AuxCommon(XDptx *InstancePtr, u32 CmdType, u32 Address, + u32 NumBytes, u8 *Data) +{ + u32 Status; + XDptx_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 == XDPTX_AUX_CMD_READ) || + (CmdType == XDPTX_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 == XDPTX_AUX_CMD_I2C_READ) && (BytesLeft > 0)) { + /* Middle of a transaction I2C read request. Override + * the command code that was set to CmdType. */ + Request.CmdCode = XDPTX_AUX_CMD_I2C_READ_MOT; + } + else if ((CmdType == XDPTX_AUX_CMD_I2C_WRITE) && + (BytesLeft > 0)) { + /* Middle of a transaction I2C write request. Override + * the command code that was set to CmdType. */ + Request.CmdCode = XDPTX_AUX_CMD_I2C_WRITE_MOT; + } + + XDptx_WaitUs(InstancePtr, InstancePtr->AuxDelayUs); + + Status = XDptx_AuxRequest(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 XDPTX_AUX_MAX_DEFER_COUNT|XDPTX_AUX_MAX_TIMEOUT_COUNT). + * + * @param InstancePtr is a pointer to the XDptx instance. + * @param Request is a pointer to an initialized XDptx_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 XDptx_AuxRequest(XDptx *InstancePtr, XDptx_AuxTransaction *Request) +{ + u32 Status; + u32 DeferCount = 0; + u32 TimeoutCount = 0; + + while ((DeferCount < XDPTX_AUX_MAX_DEFER_COUNT) && + (TimeoutCount < XDPTX_AUX_MAX_TIMEOUT_COUNT)) { + Status = XDptx_AuxWaitReady(InstancePtr); + if (Status != XST_SUCCESS) { + /* The RX device isn't ready yet. */ + TimeoutCount++; + continue; + } + + /* Send the request. */ + Status = XDptx_AuxRequestSend(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; + } + + XDptx_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 XDptx instance. + * @param Request is a pointer to an initialized XDptx_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 XDptx_AuxRequestSend(XDptx *InstancePtr, + XDptx_AuxTransaction *Request) +{ + u32 Status; + u8 Index; + + /* Set the address for the request. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_AUX_ADDRESS, + Request->Address); + + if ((Request->CmdCode == XDPTX_AUX_CMD_WRITE) || + (Request->CmdCode == XDPTX_AUX_CMD_I2C_WRITE) || + (Request->CmdCode == XDPTX_AUX_CMD_I2C_WRITE_MOT)) { + /* Feed write data into the DisplayPort TX core's write FIFO. */ + for (Index = 0; Index < Request->NumBytes; Index++) { + XDptx_WriteReg(InstancePtr->Config.BaseAddr, + XDPTX_AUX_WRITE_FIFO, Request->Data[Index]); + } + } + + /* Submit the command and the data size. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_AUX_CMD, + ((Request->CmdCode << XDPTX_AUX_CMD_SHIFT) | + ((Request->NumBytes - 1) & + XDPTX_AUX_CMD_NBYTES_TRANSFER_MASK))); + + /* Check for a reply from the RX device to the submitted request. */ + Status = XDptx_AuxWaitReply(InstancePtr); + if (Status != XST_SUCCESS) { + /* Waiting for a reply timed out. */ + return XST_ERROR_COUNT_MAX; + } + + /* Analyze the reply. */ + Status = XDptx_ReadReg(InstancePtr->Config.BaseAddr, + XDPTX_AUX_REPLY_CODE); + if ((Status == XDPTX_AUX_REPLY_CODE_DEFER) || + (Status == XDPTX_AUX_REPLY_CODE_I2C_DEFER)) { + /* The request was deferred. */ + return XST_SEND_ERROR; + } + else if ((Status == XDPTX_AUX_REPLY_CODE_NACK) || + (Status == XDPTX_AUX_REPLY_CODE_I2C_NACK)) { + /* The request was not acknowledged. */ + return XST_FAILURE; + } + + /* The request was acknowledged. */ + + if ((Request->CmdCode == XDPTX_AUX_CMD_READ) || + (Request->CmdCode == XDPTX_AUX_CMD_I2C_READ) || + (Request->CmdCode == XDPTX_AUX_CMD_I2C_READ_MOT)) { + /* Obtain the read data from the reply FIFO. */ + for (Index = 0; Index < Request->NumBytes; Index++) { + Request->Data[Index] = XDptx_ReadReg( + InstancePtr->Config.BaseAddr, + XDPTX_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 XDptx 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 XDptx_AuxWaitReply(XDptx *InstancePtr) +{ + u32 Timeout = 100; + u32 Status; + + while (0 < Timeout) { + Status = XDptx_ReadReg(InstancePtr->Config.BaseAddr, + XDPTX_INTERRUPT_STATUS); + + /* Check for a timeout. */ + if (Status & XDPTX_INTERRUPT_STATUS_REPLY_TIMEOUT_MASK) { + return XST_ERROR_COUNT_MAX; + } + + /* Check for a reply. */ + if (Status & XDPTX_INTERRUPT_STATUS_REPLY_RECEIVED_MASK) { + return XST_SUCCESS; + } + + Timeout--; + XDptx_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 XDptx 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 XDptx_AuxWaitReady(XDptx *InstancePtr) +{ + u32 Status; + u32 Timeout = 100; + + /* Wait until the DisplayPort TX core is ready. */ + do { + Status = XDptx_ReadReg(InstancePtr->Config.BaseAddr, + XDPTX_INTERRUPT_SIG_STATE); + + /* Protect against an infinite loop. */ + if (!Timeout--) { + return XST_ERROR_COUNT_MAX; + } + XDptx_WaitUs(InstancePtr, 20); + } + while (Status & XDPTX_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 XDptx instance. + * @param Speed determines what clock frequency will be used based on one + * of the following selects: + * - XDPTX_PHY_CLOCK_SELECT_162GBPS = 0x01 + * - XDPTX_PHY_CLOCK_SELECT_270GBPS = 0x03 + * - XDPTX_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 XDptx_SetClkSpeed(XDptx *InstancePtr, u32 Speed) +{ + u32 Status; + u32 RegVal; + + /* Disable the DisplayPort TX core first. */ + RegVal = XDptx_ReadReg(InstancePtr->Config.BaseAddr, XDPTX_ENABLE); + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_ENABLE, 0x0); + + /* Change speed of the feedback clock. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, + XDPTX_PHY_CLOCK_SELECT, Speed); + + /* Re-enable the DisplayPort TX core if it was previously enabled. */ + if (RegVal != 0x0) { + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_ENABLE, 0x1); + } + + /* Wait until the PHY is ready. */ + Status = XDptx_WaitPhyReady(InstancePtr); + 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 XDptx instance. + * + * @return + * - XST_ERROR_COUNT_MAX if the PHY failed to be ready. + * - XST_SUCCESS otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XDptx_WaitPhyReady(XDptx *InstancePtr) +{ + u32 Timeout = 100; + u32 PhyStatus; + + /* Wait until the PHY is ready. */ + do { + PhyStatus = XDptx_ReadReg(InstancePtr->Config.BaseAddr, + XDPTX_PHY_STATUS) & + XDPTX_PHY_STATUS_ALL_LANES_READY_MASK; + + /* Protect against an infinite loop. */ + if (!Timeout--) { + return XST_ERROR_COUNT_MAX; + } + XDptx_WaitUs(InstancePtr, 20); + } + while (PhyStatus != XDPTX_PHY_STATUS_ALL_LANES_READY_MASK); + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/dptx/src/xdptx.h b/XilinxProcessorIPLib/drivers/dptx/src/xdptx.h new file mode 100644 index 00000000..1267f094 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/src/xdptx.h @@ -0,0 +1,865 @@ +/******************************************************************************* + * + * Copyright (C) 2014 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xdptx.h + * + * The Xilinx DisplayPort transmitter (DPTX) driver. This driver supports the + * Xilinx DisplayPort soft IP core in source (TX) mode. This driver follows the + * DisplayPort 1.2a specification. + * + * 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. + * + * Driver description + * + * 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 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. + * + * Device configuration + * + * The device can be configured in various ways during the FPGA implementation + * process. Configuration parameters are stored in the xdptx_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/dptx.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. + * + * Interrupt processing + * + * 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 XDptx_HpdInterruptHandler handler will service DisplayPort interrupts. + * When the XDptx_HpdInterruptHandler 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 XDPTX_INTERRUPT_STATUS register indicates the type of + * interrupt that has occured, and the XDptx_HpdInterruptHandler will use this + * information to decide which handler to call. An HPD event is identified if + * bit XDPTX_INTERRUPT_STATUS_HPD_EVENT_MASK is set, and an HPD pulse is + * identified from the XDPTX_INTERRUPT_STATUS_HPD_PULSE_DETECTED_MASK bit. + * + * The HPD event handler may be set up by using the XDptx_SetHpdEventHandler + * function and, for the HPD pulse handler, the XDptx_SetHpdPulseHandler + * function. + * + * Multi-stream transport (MST) mode + * + * The driver handles MST mode functionality, including sideband messaging, + * topology discovery, virtual channel payload ID table management, and + * directing streams to different sinks. + * + * MST testing has been done at 5.40Gbps per 4 lanes, with 4 sinks in a daisy- + * chain configuration, with each stream having the same resolution. Testing has + * been done at the following resolutions: 640x480, 720x480, 800x600, 848x480, + * 1024x768, 1280x720, 1280x1024, 1080p, and UHD (UHD/2 on 2 streams). Each + * resolutions was tested at 24 bits per pixel using 1, 2, 3, and 4 streams. + * Color depths of 18, 30, 36, and 48 bits per pixel were also tested. + * + * Audio + * + * The driver does not handle audio. For an example as to how to configure and + * transmit audio, dptx_v2_0/examples/xdptx_audio_example.c illustrates the + * required sequence. 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 and known issues + * + * - 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  05/17/14 Initial release.
+ *       als  08/03/14 Initial MST addition.
+ * 2.0   als  09/21/14 Added XDptx_DiscoverTopology function and changed
+ *                     XDptx_IsConnected from macro to function.
+ * 
+ * +*******************************************************************************/ + +#ifndef XDPTX_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XDPTX_H_ + +/******************************* Include Files ********************************/ + +#include "xdptx_hw.h" +#include "xil_assert.h" +#include "xil_types.h" + +/****************************** Type Definitions ******************************/ + +/** + * This typedef enumerates the list of available standard display monitor + * timings as specified in the mode_table.c file. The naming format is: + * + * XDPTX_VM___ + * + * Where RB stands for reduced blanking. + */ +typedef enum { + XDPTX_VM_640x480_60_P, + XDPTX_VM_800x600_60_P, + XDPTX_VM_848x480_60_P, + XDPTX_VM_1024x768_60_P, + XDPTX_VM_1280x768_60_P_RB, + XDPTX_VM_1280x768_60_P, + XDPTX_VM_1280x800_60_P_RB, + XDPTX_VM_1280x800_60_P, + XDPTX_VM_1280x960_60_P, + XDPTX_VM_1280x1024_60_P, + XDPTX_VM_1360x768_60_P, + XDPTX_VM_1400x1050_60_P_RB, + XDPTX_VM_1400x1050_60_P, + XDPTX_VM_1440x900_60_P_RB, + XDPTX_VM_1440x900_60_P, + XDPTX_VM_1600x1200_60_P, + XDPTX_VM_1680x1050_60_P_RB, + XDPTX_VM_1680x1050_60_P, + XDPTX_VM_1792x1344_60_P, + XDPTX_VM_1856x1392_60_P, + XDPTX_VM_1920x1200_60_P_RB, + XDPTX_VM_1920x1200_60_P, + XDPTX_VM_1920x1440_60_P, + XDPTX_VM_2560x1600_60_P_RB, + XDPTX_VM_2560x1600_60_P, + XDPTX_VM_800x600_56_P, + XDPTX_VM_1600x1200_65_P, + XDPTX_VM_1600x1200_70_P, + XDPTX_VM_1024x768_70_P, + XDPTX_VM_640x480_72_P, + XDPTX_VM_800x600_72_P, + XDPTX_VM_640x480_75_P, + XDPTX_VM_800x600_75_P, + XDPTX_VM_1024x768_75_P, + XDPTX_VM_1152x864_75_P, + XDPTX_VM_1280x768_75_P, + XDPTX_VM_1280x800_75_P, + XDPTX_VM_1280x1024_75_P, + XDPTX_VM_1400x1050_75_P, + XDPTX_VM_1440x900_75_P, + XDPTX_VM_1600x1200_75_P, + XDPTX_VM_1680x1050_75_P, + XDPTX_VM_1792x1344_75_P, + XDPTX_VM_1856x1392_75_P, + XDPTX_VM_1920x1200_75_P, + XDPTX_VM_1920x1440_75_P, + XDPTX_VM_2560x1600_75_P, + XDPTX_VM_640x350_85_P, + XDPTX_VM_640x400_85_P, + XDPTX_VM_720x400_85_P, + XDPTX_VM_640x480_85_P, + XDPTX_VM_800x600_85_P, + XDPTX_VM_1024x768_85_P, + XDPTX_VM_1280x768_85_P, + XDPTX_VM_1280x800_85_P, + XDPTX_VM_1280x960_85_P, + XDPTX_VM_1280x1024_85_P, + XDPTX_VM_1400x1050_85_P, + XDPTX_VM_1440x900_85_P, + XDPTX_VM_1600x1200_85_P, + XDPTX_VM_1680x1050_85_P, + XDPTX_VM_1920x1200_85_P, + XDPTX_VM_2560x1600_85_P, + XDPTX_VM_800x600_120_P_RB, + XDPTX_VM_1024x768_120_P_RB, + XDPTX_VM_1280x768_120_P_RB, + XDPTX_VM_1280x800_120_P_RB, + XDPTX_VM_1280x960_120_P_RB, + XDPTX_VM_1280x1024_120_P_RB, + XDPTX_VM_1360x768_120_P_RB, + XDPTX_VM_1400x1050_120_P_RB, + XDPTX_VM_1440x900_120_P_RB, + XDPTX_VM_1600x1200_120_P_RB, + XDPTX_VM_1680x1050_120_P_RB, + XDPTX_VM_1792x1344_120_P_RB, + XDPTX_VM_1856x1392_120_P_RB, + XDPTX_VM_1920x1200_120_P_RB, + XDPTX_VM_1920x1440_120_P_RB, + XDPTX_VM_2560x1600_120_P_RB, + XDPTX_VM_1366x768_60_P, + XDPTX_VM_1920x1080_60_P, + XDPTX_VM_UHD_30_P, + XDPTX_VM_720_60_P, + XDPTX_VM_480_60_P, + XDPTX_VM_UHD2_60_P, + XDPTX_VM_UHD_60, + XDPTX_VM_USE_EDID_PREFERRED, + XDPTX_VM_LAST = XDPTX_VM_USE_EDID_PREFERRED +} XDptx_VideoMode; + +/** + * This typedef contains configuration information for the DisplayPort TX 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. */ +} XDptx_Config; + +/** + * This typedef contains configuration information about the RX device. + */ +typedef struct { + u8 DpcdRxCapsField[XDPTX_DPCD_RECEIVER_CAP_FIELD_SIZE]; + /**< 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. */ +} XDptx_SinkConfig; + +/** + * 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. */ +} XDptx_LinkConfig; + +/** + * This typedef contains the display monitor timing attributes for a video mode. + */ +typedef struct { + XDptx_VideoMode VideoMode; /**< Enumerated key. */ + u8 DmtId; /**< Standard Display Monitor Timing + (DMT) ID number. */ + u16 HResolution; /**< Horizontal resolution (in + pixels). */ + u16 VResolution; /**< Vertical resolution (in lines). */ + u32 PixelClkKhz; /**< Pixel frequency (in KHz). This is + also the M value for the video + stream (MVid). */ + u8 Interlaced; /**< Input stream interlaced scan + (0=non-interlaced/ + 1=interlaced). */ + u8 HSyncPolarity; /**< Horizontal synchronization polarity + (0=positive/1=negative). */ + u8 VSyncPolarity; /**< Vertical synchronization polarity + (0=positive/1=negative). */ + u32 HFrontPorch; /**< Horizontal front porch (in + pixels). */ + u32 HSyncPulseWidth; /**< Horizontal synchronization time + (pulse width in pixels). */ + u32 HBackPorch; /**< Horizontal back porch (in + pixels). */ + u32 VFrontPorch; /**< Vertical front porch (in lines). */ + u32 VSyncPulseWidth; /**< Vertical synchronization time + (pulse width in lines). */ + u32 VBackPorch; /**< Vertical back porch (in lines). */ +} XDptx_DmtMode; + +/** + * This typedef contains the main stream attributes which determine how the + * video will be displayed. + */ +typedef struct { + XDptx_DmtMode Dmt; /**< Holds the set of Display Mode + Timing (DMT) attributes that + correspond to the information + stored in the XDptx_DmtModes + table. */ + u32 HClkTotal; /**< Horizontal total time (in + pixels). */ + u32 VClkTotal; /**< Vertical total time (in pixels). */ + 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. */ +} XDptx_MainStreamAttributes; + +/** + * 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. */ +} XDptx_MstStream; + +/** + * 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. */ +} XDptx_BoardChar; + +/** + * 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. */ +} XDptx_TopologyNode; + +/** + * 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. */ + XDptx_TopologyNode NodeTable[63]; /**< A table listing all the nodes in + the MST topology. */ + u8 SinkTotal; /**< The total number of sinks in the + MST topology. */ + XDptx_TopologyNode *SinkList[63]; /**< A pointer list of sinks in the + MST topology. The entries will + point to the sinks in the + NodeTable. */ +} XDptx_Topology; + +/** + * 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. */ +} XDptx_SbMsgLinkAddressReplyPortDetail; + +/** + * 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. */ + XDptx_SbMsgLinkAddressReplyPortDetail PortDetails[16]; /**< An array + describing all ports attached to + this branch device. */ +} XDptx_SbMsgLinkAddressReplyDeviceInfo; + +/******************************************************************************/ +/** + * 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 XDptx instance. + * @param MicroSeconds is the number of microseconds to be passed to the + * timer function. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XDptx_TimerHandler)(void *InstancePtr, u32 MicroSeconds); + +/******************************************************************************/ +/** + * Callback type which represents the handler for a Hot-Plug-Detect (HPD) event + * interrupt. + * + * @param InstancePtr is a pointer to the XDptx instance. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XDptx_HpdEventHandler)(void *InstancePtr); + +/******************************************************************************/ +/** + * Callback type which represents the handler for a Hot-Plug-Detect (HPD) pulse + * interrupt. + * + * @param InstancePtr is a pointer to the XDptx instance. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XDptx_HpdPulseHandler)(void *InstancePtr); + +/** + * The XDptx driver instance data. The user is required to allocate a variable + * of this type for every XDptx device in the system. A pointer to a variable of + * this type is then passed to the driver API functions. + */ +typedef struct { + u32 MstEnable; /**< Multi-stream transport + (MST) mode. Enables + functionality, allowing + multiple streams to be + sent over the main + link. */ + u32 IsReady; /**< Device is initialized and + ready. */ + u8 TrainAdaptive; /**< Downshift lane count and + link rate if necessary + during training. */ + XDptx_Config Config; /**< Configuration structure for + the DisplayPort TX + core. */ + XDptx_SinkConfig RxConfig; /**< Configuration structure for + the RX device. */ + XDptx_LinkConfig LinkConfig; /**< Configuration structure for + the main link. */ + XDptx_BoardChar BoardChar; /**< Some board characteristics + information that affects + link training. */ + XDptx_MainStreamAttributes 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. */ + XDptx_MstStream MstStreamConfig[4]; /**< Configuration structure + for a multi-stream + transport (MST) + stream. */ + XDptx_Topology 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. */ + XDptx_TimerHandler UserTimerWaitUs; /**< Custom user function for + delay/sleep. */ + void *UserTimerPtr; /**< Pointer to a timer instance + used by the custom user + delay/sleep function. */ + XDptx_HpdEventHandler 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. */ + XDptx_HpdPulseHandler 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. */ +} XDptx; + +/*************************** Variable Declarations ****************************/ + +extern XDptx_DmtMode XDptx_DmtModes[]; + +/**************************** Function Prototypes *****************************/ + +/* xdptx.c: Setup and initialization functions. */ +u32 XDptx_InitializeTx(XDptx *InstancePtr); +void XDptx_CfgInitialize(XDptx *InstancePtr, XDptx_Config *ConfigPtr, + u32 EffectiveAddr); +u32 XDptx_GetRxCapabilities(XDptx *InstancePtr); +u32 XDptx_GetEdid(XDptx *InstancePtr, u8 *Edid); + +/* xdptx.c: Link policy maker functions. */ +u32 XDptx_CfgMainLinkMax(XDptx *InstancePtr); +u32 XDptx_EstablishLink(XDptx *InstancePtr); +u32 XDptx_CheckLinkStatus(XDptx *InstancePtr, u8 LaneCount); +void XDptx_EnableTrainAdaptive(XDptx *InstancePtr, u8 Enable); +void XDptx_SetHasRedriverInPath(XDptx *InstancePtr, u8 Set); +void XDptx_CfgTxVsOffset(XDptx *InstancePtr, u8 Offset); +void XDptx_CfgTxVsLevel(XDptx *InstancePtr, u8 Level, u8 TxLevel); +void XDptx_CfgTxPeLevel(XDptx *InstancePtr, u8 Level, u8 TxLevel); + +/* xdptx.c: AUX transaction functions. */ +u32 XDptx_AuxRead(XDptx *InstancePtr, u32 Address, u32 NumBytes, void *Data); +u32 XDptx_AuxWrite(XDptx *InstancePtr, u32 Address, u32 NumBytes, void *Data); +u32 XDptx_IicRead(XDptx *InstancePtr, u8 IicAddress, u8 RegStartAddress, + u8 NumBytes, void *Data); +u32 XDptx_IicWrite(XDptx *InstancePtr, u8 IicAddress, u8 RegStartAddress, + u8 NumBytes, void *Data); + +/* xdptx.c: Functions for controlling the link configuration. */ +u32 XDptx_SetDownspread(XDptx *InstancePtr, u8 Enable); +u32 XDptx_SetEnhancedFrameMode(XDptx *InstancePtr, u8 Enable); +u32 XDptx_SetLaneCount(XDptx *InstancePtr, u8 LaneCount); +u32 XDptx_SetLinkRate(XDptx *InstancePtr, u8 LinkRate); +u32 XDptx_SetScrambler(XDptx *InstancePtr, u8 Enable); + +/* xdptx.c: General usage functions. */ +u32 XDptx_IsConnected(XDptx *InstancePtr); +void XDptx_EnableMainLink(XDptx *InstancePtr); +void XDptx_DisableMainLink(XDptx *InstancePtr); +void XDptx_ResetPhy(XDptx *InstancePtr, u32 Reset); +void XDptx_WaitUs(XDptx *InstancePtr, u32 MicroSeconds); +void XDptx_SetUserTimerHandler(XDptx *InstancePtr, + XDptx_TimerHandler CallbackFunc, void *CallbackRef); + +/* xdptx_spm.c: Stream policy maker functions. */ +void XDptx_CfgMsaRecalculate(XDptx *InstancePtr, u8 Stream); +void XDptx_CfgMsaUseStandardVideoMode(XDptx *InstancePtr, u8 Stream, + XDptx_VideoMode VideoMode); +void XDptx_CfgMsaUseEdidPreferredTiming(XDptx *InstancePtr, u8 Stream, + u8 *Edid); +void XDptx_CfgMsaUseCustom(XDptx *InstancePtr, u8 Stream, + XDptx_MainStreamAttributes *MsaConfigCustom, u8 Recalculate); +void XDptx_CfgMsaSetBpc(XDptx *InstancePtr, u8 Stream, u8 BitsPerColor); +void XDptx_CfgMsaEnSynchClkMode(XDptx *InstancePtr, u8 Stream, u8 Enable); +void XDptx_SetVideoMode(XDptx *InstancePtr, u8 Stream); +void XDptx_ClearMsaValues(XDptx *InstancePtr, u8 Stream); +void XDptx_SetMsaValues(XDptx *InstancePtr, u8 Stream); + +/* xdptx_intr.c: Interrupt handling functions. */ +void XDptx_SetHpdEventHandler(XDptx *InstancePtr, + XDptx_HpdEventHandler CallbackFunc, void *CallbackRef); +void XDptx_SetHpdPulseHandler(XDptx *InstancePtr, + XDptx_HpdPulseHandler CallbackFunc, void *CallbackRef); +void XDptx_HpdInterruptHandler(XDptx *InstancePtr); + +/* xdptx_selftest.c: Self test function. */ +u32 XDptx_SelfTest(XDptx *InstancePtr); + +/* xdptx_sinit.c: Configuration extraction function.*/ +XDptx_Config *XDptx_LookupConfig(u16 DeviceId); + +/* xdptx_mst.c: Multi-stream transport (MST) functions for enabling or disabling + * MST mode. */ +void XDptx_MstCfgModeEnable(XDptx *InstancePtr); +void XDptx_MstCfgModeDisable(XDptx *InstancePtr); +u32 XDptx_MstCapable(XDptx *InstancePtr); +u32 XDptx_MstEnable(XDptx *InstancePtr); +u32 XDptx_MstDisable(XDptx *InstancePtr); + +/* xdptx_mst.c: Multi-stream transport (MST) functions for enabling or disabling + * MST streams and selecting their associated target sinks. */ +void XDptx_MstCfgStreamEnable(XDptx *InstancePtr, u8 Stream); +void XDptx_MstCfgStreamDisable(XDptx *InstancePtr, u8 Stream); +u8 XDptx_MstStreamIsEnabled(XDptx *InstancePtr, u8 Stream); +void XDptx_SetStreamSelectFromSinkList(XDptx *InstancePtr, u8 Stream, u8 + SinkNum); +void XDptx_SetStreamSinkRad(XDptx *InstancePtr, u8 Stream, u8 LinkCountTotal, + u8 *RelativeAddress); + +/* xdptx_mst.c: Multi-stream transport (MST) functions related to MST topology + * discovery. */ +u32 XDptx_DiscoverTopology(XDptx *InstancePtr); +u32 XDptx_FindAccessibleDpDevices(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress); + +/* xdptx_mst.c: Multi-stream transport (MST) functions related to MST stream + * allocation. */ +u32 XDptx_AllocatePayloadStreams(XDptx *InstancePtr); +u32 XDptx_AllocatePayloadVcIdTable(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 VcId, u16 Pbn, u8 Ts); +u32 XDptx_ClearPayloadVcIdTable(XDptx *InstancePtr); + +/* xdptx_mst.c: Multi-stream transport (MST) functions for issuing sideband + * messages. */ +u32 XDptx_SendSbMsgRemoteDpcdWrite(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u32 DpcdAddress, u32 BytesToWrite, u8 *WriteData); +u32 XDptx_SendSbMsgRemoteDpcdRead(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u32 DpcdAddress, u32 BytesToRead, u8 *ReadData); +u32 XDptx_SendSbMsgRemoteIicRead(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 IicDeviceId, u8 BytesToRead, u8 *ReadData); +u32 XDptx_SendSbMsgLinkAddress(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, XDptx_SbMsgLinkAddressReplyDeviceInfo *DeviceInfo); +u32 XDptx_SendSbMsgEnumPathResources(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u16 *AvailPbn, u16 *FullPbn); +u32 XDptx_SendSbMsgAllocatePayload(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 VcId, u16 Pbn); +u32 XDptx_SendSbMsgClearPayloadIdTable(XDptx *InstancePtr); + +/* xdptx_mst.c: Multi-stream transport (MST) utility functions. */ +void XDptx_WriteGuid(XDptx *InstancePtr, u8 LinkCountTotal, u8 *RelativeAddress, + u32 Guid[4]); +void XDptx_GetGuid(XDptx *InstancePtr, u8 LinkCountTotal, u8 *RelativeAddress, + u32 *Guid); +u32 XDptx_GetRemoteEdid(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 *Edid); + +#endif /* XDPTX_H_ */ diff --git a/XilinxProcessorIPLib/drivers/dptx/src/xdptx_hw.h b/XilinxProcessorIPLib/drivers/dptx/src/xdptx_hw.h new file mode 100644 index 00000000..7c1b48a5 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/src/xdptx_hw.h @@ -0,0 +1,1228 @@ +/******************************************************************************* + * + * Copyright (C) 2014 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xdptx_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 xdptx.h. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  05/17/14 Initial release.
+ *       als  08/03/14 Initial MST addition.
+ * 
+ * +*******************************************************************************/ + +#ifndef XDPTX_HW_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XDPTX_HW_H_ + +/***************************** Include Files **********************************/ + +#include "xil_io.h" +#include "xil_types.h" + +/************************** Constant Definitions ******************************/ + +/******************************************************************************/ +/** + * Address mapping for the DisplayPort TX core. + * +*******************************************************************************/ +/** @name DPTX core registers: Link configuration field. + * @{ + */ +#define XDPTX_LINK_BW_SET 0x0000 /**< Set main link bandwidth + setting. */ +#define XDPTX_LANE_COUNT_SET 0x0004 /**< Set lane count setting. */ +#define XDPTX_ENHANCED_FRAME_EN 0x0008 /**< Enable enhanced framing + symbol sequence. */ +#define XDPTX_TRAINING_PATTERN_SET 0x000C /**< Set the link training + pattern. */ +#define XDPTX_LINK_QUAL_PATTERN_SET 0x0010 /**< Transmit the link quality + pattern. */ +#define XDPTX_SCRAMBLING_DISABLE 0x0014 /**< Disable scrambler and + transmit all symbols. */ +#define XDPTX_DOWNSPREAD_CTRL 0x0018 /**< Enable a 0.5% spreading of + the clock. */ +#define XDPTX_SOFT_RESET 0x001C /**< Software reset. */ +/* @} */ + +/** @name DPTX core registers: Core enables. + * @{ + */ +#define XDPTX_ENABLE 0x0080 /**< Enable the basic operations + of the DisplayPort TX + core or output stuffing + symbols if disabled. */ +#define XDPTX_ENABLE_MAIN_STREAM 0x0084 /**< Enable transmission of main + link video info. */ +#define XDPTX_ENABLE_SEC_STREAM 0x0088 /**< Enable the transmission of + secondary link info. */ +#define XDPTX_FORCE_SCRAMBLER_RESET 0x00C0 /**< Force a scrambler reset. */ +#define XDPTX_TX_MST_CONFIG 0x00D0 /**< Enable MST. */ +/* @} */ + +/** @name DPTX core registers: Core ID. + * @{ + */ +#define XDPTX_VERSION 0x00F8 /**< Core version. */ +#define XDPTX_CORE_ID 0x00FC /**< DisplayPort revision. */ +/* @} */ + +/** @name DPTX core registers: AUX channel interface. + * @{ + */ +#define XDPTX_AUX_CMD 0x0100 /**< Initiates AUX commands. */ +#define XDPTX_AUX_WRITE_FIFO 0x0104 /**< Write data for the current + AUX command. */ +#define XDPTX_AUX_ADDRESS 0x0108 /**< Specifies the address of + current AUX command. */ +#define XDPTX_AUX_CLK_DIVIDER 0x010C /**< Clock divider value for + generating the internal + 1MHz clock. */ +#define XDPTX_TX_USER_FIFO_OVERFLOW 0x0110 /**< Indicates an overflow in + user FIFO. */ +#define XDPTX_INTERRUPT_SIG_STATE 0x0130 /**< The raw signal values for + interupt events. */ +#define XDPTX_AUX_REPLY_DATA 0x0134 /**< Reply data received during + the AUX reply. */ +#define XDPTX_AUX_REPLY_CODE 0x0138 /**< Reply code received from + the most recent AUX + command. */ +#define XDPTX_AUX_REPLY_COUNT 0x013C /**< Number of reply + transactions receieved + over AUX. */ +#define XDPTX_INTERRUPT_STATUS 0x0140 /**< Status for interrupt + events. */ +#define XDPTX_INTERRUPT_MASK 0x0144 /**< Masks the specified + interrupt sources. */ +#define XDPTX_REPLY_DATA_COUNT 0x0148 /**< Total number of data bytes + actually received during + a transaction. */ +#define XDPTX_REPLY_STATUS 0x014C /**< Reply status of most recent + AUX transaction. */ +#define XDPTX_HPD_DURATION 0x0150 /**< Duration of the HPD pulse + in microseconds. */ +/* @} */ + +/** @name DPTX core registers: Main stream attributes for SST / MST STREAM0. + * @{ + */ +#define XDPTX_STREAM0_MSA_START 0x0180 /**< Start of the MSA registers + for stream 0. */ +#define XDPTX_MAIN_STREAM_HTOTAL 0x0180 /**< Total number of clocks in + the horizontal framing + period. */ +#define XDPTX_MAIN_STREAM_VTOTAL 0x0184 /**< Total number of lines in + the video frame. */ +#define XDPTX_MAIN_STREAM_POLARITY 0x0188 /**< Polarity for the video + sync signals. */ +#define XDPTX_MAIN_STREAM_HSWIDTH 0x018C /**< Width of the horizontal + sync pulse. */ +#define XDPTX_MAIN_STREAM_VSWIDTH 0x0190 /**< Width of the vertical sync + pulse. */ +#define XDPTX_MAIN_STREAM_HRES 0x0194 /**< Number of active pixels per + line (the horizontal + resolution). */ +#define XDPTX_MAIN_STREAM_VRES 0x0198 /**< Number of active lines (the + vertical resolution). */ +#define XDPTX_MAIN_STREAM_HSTART 0x019C /**< Number of clocks between + the leading edge of the + horizontal sync and the + start of active data. */ +#define XDPTX_MAIN_STREAM_VSTART 0x01A0 /**< Number of lines between the + leading edge of the + vertical sync and the + first line of active + data. */ +#define XDPTX_MAIN_STREAM_MISC0 0x01A4 /**< Miscellaneous stream + attributes. */ +#define XDPTX_MAIN_STREAM_MISC1 0x01A8 /**< Miscellaneous stream + attributes. */ +#define XDPTX_M_VID 0x01AC /**< M value for the video + stream as computed by + the source core in + asynchronous clock + mode. Must be written + in synchronous mode. */ +#define XDPTX_TU_SIZE 0x01B0 /**< Size of a transfer unit in + the framing logic. */ +#define XDPTX_N_VID 0x01B4 /**< N value for the video + stream as computed by + the source core in + asynchronous clock mode. + Must be written in + synchronous mode. */ +#define XDPTX_USER_PIXEL_WIDTH 0x01B8 /**< Selects the width of the + user data input port. */ +#define XDPTX_USER_DATA_COUNT_PER_LANE 0x01BC /**< Used to translate the + number of pixels per + line to the native + internal 16-bit + datapath. */ +#define XDPTX_MAIN_STREAM_INTERLACED 0x01C0 /**< Video is interlaced. */ +#define XDPTX_MIN_BYTES_PER_TU 0x01C4 /**< The minimum number of bytes + per transfer unit. */ +#define XDPTX_FRAC_BYTES_PER_TU 0x01C8 /**< The fractional component + when calculated the + XDPTX_MIN_BYTES_PER_TU + register value. */ +#define XDPTX_INIT_WAIT 0x01CC /**< 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 XDPTX_STREAM0 0x01D0 /**< Average stream symbol + timeslots per MTP + config. */ +#define XDPTX_STREAM1 0x01D4 /**< Average stream symbol + timeslots per MTP + config. */ +#define XDPTX_STREAM2 0x01D8 /**< Average stream symbol + timeslots per MTP + config. */ +#define XDPTX_STREAM3 0x01DC /**< Average stream symbol + timeslots per MTP + config. */ +/* @} */ + +/** @name DPTX core registers: PHY configuration status. + * @{ + */ +#define XDPTX_PHY_CONFIG 0x0200 /**< Transceiver PHY reset and + configuration. */ +#define XDPTX_PHY_VOLTAGE_DIFF_LANE_0 0x0220 /**< Controls the differential + voltage swing. */ +#define XDPTX_PHY_VOLTAGE_DIFF_LANE_1 0x0224 /**< Controls the differential + voltage swing. */ +#define XDPTX_PHY_VOLTAGE_DIFF_LANE_2 0x0228 /**< Controls the differential + voltage swing. */ +#define XDPTX_PHY_VOLTAGE_DIFF_LANE_3 0x022C /**< Controls the differential + voltage swing. */ +#define XDPTX_PHY_TRANSMIT_PRBS7 0x0230 /**< Enable pseudo random bit + sequence 7 pattern + transmission for link + quality assessment. */ +#define XDPTX_PHY_CLOCK_SELECT 0x0234 /**< Instructs the PHY PLL to + generate the proper + clock frequency for the + required link rate. */ +#define XDPTX_TX_PHY_POWER_DOWN 0x0238 /**< Controls PHY power down. */ +#define XDPTX_PHY_PRECURSOR_LANE_0 0x023C /**< Controls the pre-cursor + level. */ +#define XDPTX_PHY_PRECURSOR_LANE_1 0x0240 /**< Controls the pre-cursor + level. */ +#define XDPTX_PHY_PRECURSOR_LANE_2 0x0244 /**< Controls the pre-cursor + level. */ +#define XDPTX_PHY_PRECURSOR_LANE_3 0x0248 /**< Controls the pre-cursor + level. */ +#define XDPTX_PHY_POSTCURSOR_LANE_0 0x024C /**< Controls the post-cursor + level. */ +#define XDPTX_PHY_POSTCURSOR_LANE_1 0x0250 /**< Controls the post-cursor + level. */ +#define XDPTX_PHY_POSTCURSOR_LANE_2 0x0254 /**< Controls the post-cursor + level. */ +#define XDPTX_PHY_POSTCURSOR_LANE_3 0x0258 /**< Controls the post-cursor + level. */ +#define XDPTX_PHY_STATUS 0x0280 /**< Current PHY status. */ +#define XDPTX_GT_DRP_COMMAND 0x02A0 /**< Provides acces to the GT + DRP ports. */ +#define XDPTX_GT_DRP_READ_DATA 0x02A4 /**< Provides access to GT DRP + read data. */ +#define XDPTX_GT_DRP_CHANNEL_STATUS 0x02A8 /**< Provides access to GT DRP + channel status. */ +/* @} */ + +/** @name DPTX core registers: DisplayPort audio. + * @{ + */ +#define XDPTX_TX_AUDIO_CONTROL 0x0300 /**< Enables audio stream + packets in main link and + buffer control. */ +#define XDPTX_TX_AUDIO_CHANNELS 0x0304 /**< Used to input active + channel count. */ +#define XDPTX_TX_AUDIO_INFO_DATA 0x0308 /**< Word formatted as per + CEA 861-C info frame. */ +#define XDPTX_TX_AUDIO_MAUD 0x0328 /**< M value of audio stream + as computed by the + DisplayPort TX core when + audio and link clocks + are synchronous. */ +#define XDPTX_TX_AUDIO_NAUD 0x032C /**< N value of audio stream + as computed by the + DisplayPort TX core when + audio and link clocks + are synchronous. */ +#define XDPTX_TX_AUDIO_EXT_DATA 0x0330 /**< Word formatted as per + extension packet. */ +/* @} */ + +/** @name DPTX core registers: Main stream attributes for MST STREAM1, 2, and 3. + * @{ + */ +#define XDPTX_STREAM1_MSA_START 0x0500 /**< Start of the MSA registers + for stream 1. */ +#define XDPTX_STREAM1_MSA_START_OFFSET (XDPTX_STREAM1_MSA_START - \ + XDPTX_STREAM0_MSA_START) /**< The MSA registers for + stream 1 are at an + offset from the + corresponding registers + of stream 0. */ +#define XDPTX_STREAM2_MSA_START 0x0550 /**< Start of the MSA registers + for stream 2. */ +#define XDPTX_STREAM2_MSA_START_OFFSET (XDPTX_STREAM2_MSA_START - \ + XDPTX_STREAM0_MSA_START) /**< The MSA registers for + stream 2 are at an + offset from the + corresponding registers + of stream 0. */ +#define XDPTX_STREAM3_MSA_START 0x05A0 /**< Start of the MSA registers + for stream 3. */ +#define XDPTX_STREAM3_MSA_START_OFFSET (XDPTX_STREAM3_MSA_START - \ + XDPTX_STREAM0_MSA_START) /**< The MSA registers for + stream 3 are at an + offset from the + corresponding registers + of stream 0. */ +/* @} */ + +#define XDPTX_VC_PAYLOAD_BUFFER_ADDR 0x0800 /**< Virtual channel payload + table (0xFF bytes). */ + +/******************************************************************************/ + +/** @name DPTX core masks, shifts, and register values. + * @{ + */ +/* 0x000: LINK_BW_SET */ +#define XDPTX_LINK_BW_SET_162GBPS 0x06 /**< 1.62 Gbps link rate. */ +#define XDPTX_LINK_BW_SET_270GBPS 0x0A /**< 2.70 Gbps link rate. */ +#define XDPTX_LINK_BW_SET_540GBPS 0x14 /**< 5.40 Gbps link rate. */ +/* 0x001: LANE_COUNT_SET */ +#define XDPTX_LANE_COUNT_SET_1 0x01 /**< Lane count of 1. */ +#define XDPTX_LANE_COUNT_SET_2 0x02 /**< Lane count of 2. */ +#define XDPTX_LANE_COUNT_SET_4 0x04 /**< Lane count of 4. */ +/* 0x00C: TRAINING_PATTERN_SET */ +#define XDPTX_TRAINING_PATTERN_SET_OFF 0x0 /**< Training off. */ +#define XDPTX_TRAINING_PATTERN_SET_TP1 0x1 /**< Training pattern 1 used for + clock recovery. */ +#define XDPTX_TRAINING_PATTERN_SET_TP2 0x2 /**< Training pattern 2 used for + channel equalization. */ +#define XDPTX_TRAINING_PATTERN_SET_TP3 0x3 /**< Training pattern 3 used for + channel equalization for + cores with DP v1.2. */ +/* 0x010: LINK_QUAL_PATTERN_SET */ +#define XDPTX_LINK_QUAL_PATTERN_SET_OFF 0x0 /**< Link quality test pattern + not transmitted. */ +#define XDPTX_LINK_QUAL_PATTERN_SET_D102_TEST \ + 0x1 /**< D10.2 unscrambled test + pattern transmitted. */ +#define XDPTX_LINK_QUAL_PATTERN_SET_SER_MES \ + 0x2 /**< Symbol error rate + measurement pattern + transmitted. */ +#define XDPTX_LINK_QUAL_PATTERN_SET_PRBS7 \ + 0x3 /**< Pseudo random bit sequence + 7 transmitted. */ +/* 0x01C: SOFTWARE_RESET */ +#define XDPTX_SOFT_RESET_VIDEO_STREAM0_MASK \ + 0x00000001 /**< Reset video logic. */ +#define XDPTX_SOFT_RESET_VIDEO_STREAM1_MASK \ + 0x00000002 /**< Reset video logic. */ +#define XDPTX_SOFT_RESET_VIDEO_STREAM2_MASK \ + 0x00000004 /**< Reset video logic. */ +#define XDPTX_SOFT_RESET_VIDEO_STREAM3_MASK \ + 0x00000008 /**< Reset video logic. */ +#define XDPTX_SOFT_RESET_AUX_MASK \ + 0x00000080 /**< Reset AUX logic. */ +#define XDPTX_SOFT_RESET_VIDEO_STREAM_ALL_MASK \ + 0x0000000F /**< Reset video logic for all + streams. */ +/* 0x0D0: TX_MST_CONFIG */ +#define XDPTX_TX_MST_CONFIG_MST_EN_MASK \ + 0x00000001 /**< Enable MST. */ +#define XDPTX_TX_MST_CONFIG_VCP_UPDATED_MASK \ + 0x00000002 /**< The VC payload has been + updated in the sink. */ +/* 0x0F8 : VERSION_REGISTER */ +#define XDPTX_VERSION_INTER_REV_MASK \ + 0x0000000F /**< Internal revision. */ +#define XDPTX_VERSION_CORE_PATCH_MASK \ + 0x00000030 /**< Core patch details. */ +#define XDPTX_VERSION_CORE_PATCH_SHIFT \ + 8 /**< Shift bits for core patch + details. */ +#define XDPTX_VERSION_CORE_VER_REV_MASK \ + 0x000000C0 /**< Core version revision. */ +#define XDPTX_VERSION_CORE_VER_REV_SHIFT \ + 12 /**< Shift bits for core version + revision. */ +#define XDPTX_VERSION_CORE_VER_MNR_MASK \ + 0x00000F00 /**< Core minor version. */ +#define XDPTX_VERSION_CORE_VER_MNR_SHIFT \ + 16 /**< Shift bits for core minor + version. */ +#define XDPTX_VERSION_CORE_VER_MJR_MASK \ + 0x0000F000 /**< Core major version. */ +#define XDPTX_VERSION_CORE_VER_MJR_SHIFT \ + 24 /**< Shift bits for core major + version. */ +/* 0x0FC : CORE_ID */ +#define XDPTX_CORE_ID_TYPE_MASK 0x0000000F /**< Core type. */ +#define XDPTX_CORE_ID_TYPE_TX 0x0 /**< Core is a transmitter. */ +#define XDPTX_CORE_ID_TYPE_RX 0x1 /**< Core is a receiver. */ +#define XDPTX_CORE_ID_DP_REV_MASK \ + 0x000000F0 /**< DisplayPort protocol + revision. */ +#define XDPTX_CORE_ID_DP_REV_SHIFT \ + 8 /**< Shift bits for DisplayPort + protocol revision. */ +#define XDPTX_CORE_ID_DP_MNR_VER_MASK \ + 0x00000F00 /**< DisplayPort protocol minor + version. */ +#define XDPTX_CORE_ID_DP_MNR_VER_SHIFT \ + 16 /**< Shift bits for DisplayPort + protocol major + version. */ +#define XDPTX_CORE_ID_DP_MJR_VER_MASK \ + 0x0000F000 /**< DisplayPort protocol major + version. */ +#define XDPTX_CORE_ID_DP_MJR_VER_SHIFT \ + 24 /**< Shift bits for DisplayPort + protocol major + version. */ +/* 0x100 AUX_CMD */ +#define XDPTX_AUX_CMD_NBYTES_TRANSFER_MASK \ + 0x0000000F /**< Number of bytes to transfer + with the current AUX + command. */ +#define XDPTX_AUX_CMD_MASK 0x00000F00 /**< AUX command. */ +#define XDPTX_AUX_CMD_SHIFT 8 /**< Shift bits for command. */ +#define XDPTX_AUX_CMD_I2C_WRITE 0x0 /**< I2C-over-AUX write + command. */ +#define XDPTX_AUX_CMD_I2C_READ 0x1 /**< I2C-over-AUX read + command. */ +#define XDPTX_AUX_CMD_I2C_WRITE_STATUS 0x2 /**< I2C-over-AUX write status + command. */ +#define XDPTX_AUX_CMD_I2C_WRITE_MOT 0x4 /**< I2C-over-AUX write MOT + (middle-of-transaction) + command. */ +#define XDPTX_AUX_CMD_I2C_READ_MOT 0x5 /**< I2C-over-AUX read MOT + (middle-of-transaction) + command. */ +#define XDPTX_AUX_CMD_I2C_WRITE_STATUS_MOT \ + 0x6 /**< I2C-over-AUX write status + MOT (middle-of- + transaction) command. */ +#define XDPTX_AUX_CMD_WRITE 0x8 /**< AUX write command. */ +#define XDPTX_AUX_CMD_READ 0x9 /**< AUX read command. */ +#define XDPTX_AUX_CMD_ADDR_ONLY_TRANSFER_EN \ + 0x00001000 /**< Address only transfer + enable (STOP will be + sent after command). */ +/* 0x10C: AUX_CLK_DIVIDER */ +#define XDPTX_AUX_CLK_DIVIDER_VAL_MASK \ + 0x0000000F /**< Clock divider value. */ +#define XDPTX_AUX_CLK_DIVIDER_AUX_SIG_WIDTH_FILT_MASK \ + 0x00000F00 /**< AUX (noise) signal width + filter. */ +#define XDPTX_AUX_CLK_DIVIDER_AUX_SIG_WIDTH_FILT_SHIFT \ + 8 /**< Shift bits for AUX signal + width filter. */ +/* 0x130: INTERRUPT_SIG_STATE */ +#define XDPTX_INTERRUPT_SIG_STATE_HPD_STATE_MASK \ + 0x00000001 /**< Raw state of the HPD pin on + the DP connector. */ +#define XDPTX_INTERRUPT_SIG_STATE_REQUEST_STATE_MASK \ + 0x00000002 /**< A request is currently + being sent. */ +#define XDPTX_INTERRUPT_SIG_STATE_REPLY_STATE_MASK \ + 0x00000004 /**< A reply is currently being + received. */ +#define XDPTX_INTERRUPT_SIG_STATE_REPLY_TIMEOUT_MASK \ + 0x00000008 /**< A reply timeout has + occurred. */ +/* 0x138: AUX_REPLY_CODE */ +#define XDPTX_AUX_REPLY_CODE_ACK 0x0 /**< AUX command ACKed. */ +#define XDPTX_AUX_REPLY_CODE_I2C_ACK 0x0 /**< I2C-over-AUX command + not ACKed. */ +#define XDPTX_AUX_REPLY_CODE_NACK 0x1 /**< AUX command not ACKed. */ +#define XDPTX_AUX_REPLY_CODE_DEFER 0x2 /**< AUX command deferred. */ +#define XDPTX_AUX_REPLY_CODE_I2C_NACK 0x4 /**< I2C-over-AUX command not + ACKed. */ +#define XDPTX_AUX_REPLY_CODE_I2C_DEFER 0x8 /**< I2C-over-AUX command + deferred. */ +/* 0x140: INTERRUPT_STATUS */ +#define XDPTX_INTERRUPT_STATUS_HPD_IRQ_MASK \ + 0x00000001 /**< Detected an IRQ framed with + the proper timing on the + HPD signal. */ +#define XDPTX_INTERRUPT_STATUS_HPD_EVENT_MASK \ + 0x00000002 /**< Detected the presence of + the HPD signal. */ +#define XDPTX_INTERRUPT_STATUS_REPLY_RECEIVED_MASK \ + 0x00000004 /**< An AUX reply transaction + has been detected. */ +#define XDPTX_INTERRUPT_STATUS_REPLY_TIMEOUT_MASK \ + 0x00000008 /**< A reply timeout has + occurred. */ +#define XDPTX_INTERRUPT_STATUS_HPD_PULSE_DETECTED_MASK \ + 0x00000010 /**< A pulse on the HPD line was + detected. */ +#define XDPTX_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 XDPTX_INTERRUPT_MASK_HPD_IRQ_MASK \ + 0x00000001 /**< Mask HPD IRQ interrupt. */ +#define XDPTX_INTERRUPT_MASK_HPD_EVENT_MASK \ + 0x00000002 /**< Mask HPD event + interrupt. */ +#define XDPTX_INTERRUPT_MASK_REPLY_RECEIVED_MASK \ + 0x00000004 /**< Mask reply received + interrupt. */ +#define XDPTX_INTERRUPT_MASK_REPLY_TIMEOUT_MASK \ + 0x00000008 /**< Mask reply received + interrupt. */ +#define XDPTX_INTERRUPT_MASK_HPD_PULSE_DETECTED_MASK \ + 0x00000010 /**< Mask HPD pulse detected + interrupt. */ +#define XDPTX_INTERRUPT_MASK_EXT_PKT_TXD_MASK \ + 0x00000020 /**< Mask extended packet + transmit interrupt. */ +/* 0x14C: REPLY_STATUS */ +#define XDPTX_REPLY_STATUS_REPLY_RECEIVED_MASK \ + 0x00000001 /**< AUX transaction is complete + and a valid reply + transaction received. */ +#define XDPTX_REPLY_STATUS_REPLY_IN_PROGRESS_MASK \ + 0x00000002 /**< AUX reply is currently + being received. */ +#define XDPTX_REPLY_STATUS_REQUEST_IN_PROGRESS_MASK \ + 0x00000004 /**< AUX request is currently + being transmitted. */ +#define XDPTX_REPLY_STATUS_REPLY_ERROR_MASK \ + 0x00000008 /**< Detected an error in the + AUX reply of the most + recent transaction. */ +#define XDPTX_REPLY_STATUS_REPLY_STATUS_STATE_MASK \ + 0x00000FF0 /**< Internal AUX reply state + machine status bits. */ +#define XDPTX_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 XDPTX_MAIN_STREAMX_POLARITY_HSYNC_POL_MASK \ + 0x00000001 /**< Polarity of the horizontal + sync pulse. */ +#define XDPTX_MAIN_STREAMX_POLARITY_VSYNC_POL_MASK \ + 0x00000002 /**< Polarity of the vertical + sync pulse. */ +#define XDPTX_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 XDPTX_MAIN_STREAMX_MISC0_SYNC_CLK_MASK \ + 0x00000001 /**< Synchronous clock. */ +#define XDPTX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_MASK \ + 0x00000006 /**< Component format. */ +#define XDPTX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_SHIFT \ + 1 /**< Shift bits for component + format. */ +#define XDPTX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_RGB \ + 0x0 /**< Stream's component format + is RGB. */ +#define XDPTX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_YCBCR422 \ + 0x1 /**< Stream's component format + is YcbCr 4:2:2. */ +#define XDPTX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_YCBCR444 \ + 0x2 /**< Stream's component format + is YcbCr 4:4:4. */ +#define XDPTX_MAIN_STREAMX_MISC0_DYNAMIC_RANGE_MASK \ + 0x00000008 /**< Dynamic range. */ +#define XDPTX_MAIN_STREAMX_MISC0_DYNAMIC_RANGE_SHIFT \ + 3 /**< Shift bits for dynamic + range. */ +#define XDPTX_MAIN_STREAMX_MISC0_YCBCR_COLORIMETRY_MASK \ + 0x00000010 /**< YCbCr colorimetry. */ +#define XDPTX_MAIN_STREAMX_MISC0_YCBCR_COLORIMETRY_SHIFT \ + 4 /**< Shift bits for YCbCr + colorimetry. */ +#define XDPTX_MAIN_STREAMX_MISC0_BDC_MASK \ + 0x000000E0 /**< Bit depth per color + component (BDC). */ +#define XDPTX_MAIN_STREAMX_MISC0_BDC_SHIFT \ + 5 /**< Shift bits for BDC.*/ +#define XDPTX_MAIN_STREAMX_MISC0_BDC_6BPC \ + 0x0 /**< 6 bits per component.*/ +#define XDPTX_MAIN_STREAMX_MISC0_BDC_8BPC \ + 0x1 /**< 8 bits per component.*/ +#define XDPTX_MAIN_STREAMX_MISC0_BDC_10BPC \ + 0x2 /**< 10 bits per component.*/ +#define XDPTX_MAIN_STREAMX_MISC0_BDC_12BPC \ + 0x3 /**< 12 bits per component.*/ +#define XDPTX_MAIN_STREAMX_MISC0_BDC_16BPC \ + 0x4 /**< 16 bits per component.*/ +/* 0x1A8, 0x528, 0x578, 0x5C8: MAIN_STREAM[1-4]_MISC1 */ +#define XDPTX_MAIN_STREAMX_MISC1_INTERLACED_VTOTAL_GIVEN_MASK \ + 0x00000001 /**< Interlaced vertical total + even. */ +#define XDPTX_MAIN_STREAMX_MISC1_STEREO_VID_ATTR_MASK \ + 0x00000006 /**< Stereo video attribute. */ +#define XDPTX_MAIN_STREAMX_MISC1_STEREO_VID_ATTR_SHIFT \ + 1 /**< Shift bits for stereo video + attribute. */ +/* 0x200: PHY_CONFIG */ +#define XDPTX_PHY_CONFIG_PHY_RESET_ENABLE_MASK \ + 0x0010000 /**< Release reset. */ +#define XDPTX_PHY_CONFIG_PHY_RESET_MASK \ + 0x0010001 /**< Hold the PHY in reset. */ +#define XDPTX_PHY_CONFIG_GTTX_RESET_MASK \ + 0x0010002 /**< Hold GTTXRESET in reset. */ +#define XDPTX_PHY_CONFIG_TX_PHY_PMA_RESET_MASK \ + 0x0010100 /**< Hold TX_PHY_PMA reset. */ +#define XDPTX_PHY_CONFIG_TX_PHY_PCS_RESET_MASK \ + 0x0010200 /**< HOLD TX_PHY_PCS reset. */ +#define XDPTX_PHY_CONFIG_TX_PHY_POLARITY_MASK \ + 0x0010400 /**< Set TX_PHY_POLARITY. */ +#define XDPTX_PHY_CONFIG_TX_PHY_PRBSFORCEERR_MASK \ + 0x0011000 /**< Set TX_PHY_PRBSFORCEERR. */ +#define XDPTX_PHY_CONFIG_TX_PHY_LOOPBACK_MASK \ + 0x001E000 /**< Set TX_PHY_LOOPBACK. */ +#define XDPTX_PHY_CONFIG_GT_ALL_RESET_MASK \ + 0x0010003 /**< Rest GT and PHY. */ +/* 0x234: PHY_CLOCK_SELECT */ +#define XDPTX_PHY_CLOCK_SELECT_162GBPS 0x1 /**< 1.62 Gbps link. */ +#define XDPTX_PHY_CLOCK_SELECT_270GBPS 0x3 /**< 2.70 Gbps link. */ +#define XDPTX_PHY_CLOCK_SELECT_540GBPS 0x5 /**< 5.40 Gbps link. */ +/* 0x0220, 0x0224, 0x0228, 0x022C: XDPTX_PHY_VOLTAGE_DIFF_LANE_[0-3] */ +#define XDPTX_VS_LEVEL_0 0x2 /**< Voltage swing level 0. */ +#define XDPTX_VS_LEVEL_1 0x5 /**< Voltage swing level 1. */ +#define XDPTX_VS_LEVEL_2 0x8 /**< Voltage swing level 2. */ +#define XDPTX_VS_LEVEL_3 0xF /**< Voltage swing level 3. */ +#define XDPTX_VS_LEVEL_OFFSET 0x4 /**< Voltage swing compensation + offset used when there's + no redriver in display + path. */ +/* 0x024C, 0x0250, 0x0254, 0x0258: XDPTX_PHY_POSTCURSOR_LANE_[0-3] */ +#define XDPTX_PE_LEVEL_0 0x00 /**< Pre-emphasis level 0. */ +#define XDPTX_PE_LEVEL_1 0x0E /**< Pre-emphasis level 1. */ +#define XDPTX_PE_LEVEL_2 0x14 /**< Pre-emphasis level 2. */ +#define XDPTX_PE_LEVEL_3 0x1B /**< Pre-emphasis level 3. */ +/* 0x280: PHY_STATUS */ +#define XDPTX_PHY_STATUS_RESET_LANE_0_1_DONE_MASK \ + 0x00000003 /**< Reset done for lanes + 0 and 1. */ +#define XDPTX_PHY_STATUS_RESET_LANE_2_3_DONE_MASK \ + 0x0000000C /**< Reset done for lanes + 2 and 3. */ +#define XDPTX_PHY_STATUS_PLL_LANE0_1_LOCK_MASK \ + 0x00000010 /**< PLL locked for lanes + 0 and 1. */ +#define XDPTX_PHY_STATUS_PLL_LANE2_3_LOCK_MASK \ + 0x00000020 /**< PLL locked for lanes + 2 and 3. */ +#define XDPTX_PHY_STATUS_PLL_FABRIC_LOCK_MASK \ + 0x00000020 /**< FPGA fabric clock PLL + locked. */ +#define XDPTX_PHY_STATUS_TX_BUFFER_STATUS_LANE_0_MASK \ + 0x00030000 /**< TX buffer status lane 0. */ +#define XDPTX_PHY_STATUS_TX_BUFFER_STATUS_LANE_0_SHIFT \ + 16 /**< Shift bits for TX buffer + status lane 0. */ +#define XDPTX_PHY_STATUS_TX_ERROR_LANE_0_MASK \ + 0x000C0000 /**< TX error on lane 0. */ +#define XDPTX_PHY_STATUS_TX_ERROR_LANE_0_SHIFT \ + 18 /**< Shift bits for TX error on + lane 0. */ +#define XDPTX_PHY_STATUS_TX_BUFFER_STATUS_LANE_1_MASK \ + 0x00300000 /**< TX buffer status lane 1. */ +#define XDPTX_PHY_STATUS_TX_BUFFER_STATUS_LANE_1_SHIFT \ + 20 /**< Shift bits for TX buffer + status lane 1. */ +#define XDPTX_PHY_STATUS_TX_ERROR_LANE_1_MASK \ + 0x00C00000 /**< TX error on lane 1. */ +#define XDPTX_PHY_STATUS_TX_ERROR_LANE_1_SHIFT \ + 22 /**< Shift bits for TX error on + lane 1. */ +#define XDPTX_PHY_STATUS_TX_BUFFER_STATUS_LANE_2_MASK \ + 0x03000000 /**< TX buffer status lane 2. */ +#define XDPTX_PHY_STATUS_TX_BUFFER_STATUS_LANE_2_SHIFT \ + 24 /**< Shift bits for TX buffer + status lane 2. */ +#define XDPTX_PHY_STATUS_TX_ERROR_LANE_2_MASK \ + 0x0C000000 /**< TX error on lane 2. */ +#define XDPTX_PHY_STATUS_TX_ERROR_LANE_2_SHIFT \ + 26 /**< Shift bits for TX error on + lane 2. */ +#define XDPTX_PHY_STATUS_TX_BUFFER_STATUS_LANE_3_MASK \ + 0x30000000 /**< TX buffer status lane 3. */ +#define XDPTX_PHY_STATUS_TX_BUFFER_STATUS_LANE_3_SHIFT \ + 28 /**< Shift bits for TX buffer + status lane 3. */ +#define XDPTX_PHY_STATUS_TX_ERROR_LANE_3_MASK \ + 0xC0000000 /**< TX error on lane 3. */ +#define XDPTX_PHY_STATUS_TX_ERROR_LANE_3_SHIFT \ + 30 /**< Shift bits for TX error on + lane 3. */ +#define XDPTX_PHY_STATUS_ALL_LANES_READY_MASK \ + 0x0000003F /**< All lanes are ready. */ +/* 0x2A0: XDPTX_GT_DRP_COMMAND */ +#define XDPTX_GT_DRP_COMMAND_DRP_ADDR_MASK \ + 0x000F /**< DRP address. */ +#define XDPTX_GT_DRP_COMMAND_DRP_RW_CMD_MASK \ + 0x0080 /**< DRP read/write command + (Read=0, Write=1). */ +#define XDPTX_GT_DRP_COMMAND_DRP_W_DATA_MASK \ + 0xFF00 /**< DRP write data. */ +#define XDPTX_GT_DRP_COMMAND_DRP_W_DATA_SHIFT \ + 16 /**< Shift bits for DRP write + data. */ +/* @} */ + +/******************************************************************************/ + +/******************************************************************************/ +/** + * Address mapping for the DisplayPort Configuration Data (DPCD) of the + * downstream device. + * +*******************************************************************************/ +/** @name DisplayPort Configuration Data: Receiver capability field. + * @{ + */ +#define XDPTX_DPCD_REV 0x00000 +#define XDPTX_DPCD_MAX_LINK_RATE 0x00001 +#define XDPTX_DPCD_MAX_LANE_COUNT 0x00002 +#define XDPTX_DPCD_MAX_DOWNSPREAD 0x00003 +#define XDPTX_DPCD_NORP_PWR_V_CAP 0x00004 +#define XDPTX_DPCD_DOWNSP_PRESENT 0x00005 +#define XDPTX_DPCD_ML_CH_CODING_CAP 0x00006 +#define XDPTX_DPCD_DOWNSP_COUNT_MSA_OUI 0x00007 +#define XDPTX_DPCD_RX_PORT0_CAP_0 0x00008 +#define XDPTX_DPCD_RX_PORT0_CAP_1 0x00009 +#define XDPTX_DPCD_RX_PORT1_CAP_0 0x0000A +#define XDPTX_DPCD_RX_PORT1_CAP_1 0x0000B +#define XDPTX_DPCD_I2C_SPEED_CTL_CAP 0x0000C +#define XDPTX_DPCD_EDP_CFG_CAP 0x0000D +#define XDPTX_DPCD_TRAIN_AUX_RD_INTERVAL 0x0000E +#define XDPTX_DPCD_ADAPTER_CAP 0x0000F +#define XDPTX_DPCD_FAUX_CAP 0x00020 +#define XDPTX_DPCD_MSTM_CAP 0x00021 +#define XDPTX_DPCD_NUM_AUDIO_EPS 0x00022 +#define XDPTX_DPCD_AV_GRANULARITY 0x00023 +#define XDPTX_DPCD_AUD_DEC_LAT_7_0 0x00024 +#define XDPTX_DPCD_AUD_DEC_LAT_15_8 0x00025 +#define XDPTX_DPCD_AUD_PP_LAT_7_0 0x00026 +#define XDPTX_DPCD_AUD_PP_LAT_15_8 0x00027 +#define XDPTX_DPCD_VID_INTER_LAT 0x00028 +#define XDPTX_DPCD_VID_PROG_LAT 0x00029 +#define XDPTX_DPCD_REP_LAT 0x0002A +#define XDPTX_DPCD_AUD_DEL_INS_7_0 0x0002B +#define XDPTX_DPCD_AUD_DEL_INS_15_8 0x0002C +#define XDPTX_DPCD_AUD_DEL_INS_23_16 0x0002D +#define XDPTX_DPCD_GUID 0x00030 +#define XDPTX_DPCD_RX_GTC_VALUE_7_0 0x00054 +#define XDPTX_DPCD_RX_GTC_VALUE_15_8 0x00055 +#define XDPTX_DPCD_RX_GTC_VALUE_23_16 0x00056 +#define XDPTX_DPCD_RX_GTC_VALUE_31_24 0x00057 +#define XDPTX_DPCD_RX_GTC_MSTR_REQ 0x00058 +#define XDPTX_DPCD_RX_GTC_FREQ_LOCK_DONE 0x00059 +#define XDPTX_DPCD_DOWNSP_0_CAP 0x00080 +#define XDPTX_DPCD_DOWNSP_1_CAP 0x00081 +#define XDPTX_DPCD_DOWNSP_2_CAP 0x00082 +#define XDPTX_DPCD_DOWNSP_3_CAP 0x00083 +#define XDPTX_DPCD_DOWNSP_0_DET_CAP 0x00080 +#define XDPTX_DPCD_DOWNSP_1_DET_CAP 0x00084 +#define XDPTX_DPCD_DOWNSP_2_DET_CAP 0x00088 +#define XDPTX_DPCD_DOWNSP_3_DET_CAP 0x0008C +/* @} */ + +/** @name DisplayPort Configuration Data: Link configuration field. + * @{ + */ +#define XDPTX_DPCD_LINK_BW_SET 0x00100 +#define XDPTX_DPCD_LANE_COUNT_SET 0x00101 +#define XDPTX_DPCD_TP_SET 0x00102 +#define XDPTX_DPCD_TRAINING_LANE0_SET 0x00103 +#define XDPTX_DPCD_TRAINING_LANE1_SET 0x00104 +#define XDPTX_DPCD_TRAINING_LANE2_SET 0x00105 +#define XDPTX_DPCD_TRAINING_LANE3_SET 0x00106 +#define XDPTX_DPCD_DOWNSPREAD_CTRL 0x00107 +#define XDPTX_DPCD_ML_CH_CODING_SET 0x00108 +#define XDPTX_DPCD_I2C_SPEED_CTL_SET 0x00109 +#define XDPTX_DPCD_EDP_CFG_SET 0x0010A +#define XDPTX_DPCD_LINK_QUAL_LANE0_SET 0x0010B +#define XDPTX_DPCD_LINK_QUAL_LANE1_SET 0x0010C +#define XDPTX_DPCD_LINK_QUAL_LANE2_SET 0x0010D +#define XDPTX_DPCD_LINK_QUAL_LANE3_SET 0x0010E +#define XDPTX_DPCD_TRAINING_LANE0_1_SET2 0x0010F +#define XDPTX_DPCD_TRAINING_LANE2_3_SET2 0x00110 +#define XDPTX_DPCD_MSTM_CTRL 0x00111 +#define XDPTX_DPCD_AUDIO_DELAY_7_0 0x00112 +#define XDPTX_DPCD_AUDIO_DELAY_15_8 0x00113 +#define XDPTX_DPCD_AUDIO_DELAY_23_6 0x00114 +#define XDPTX_DPCD_UPSTREAM_DEVICE_DP_PWR_NEED 0x00118 +#define XDPTX_DPCD_FAUX_MODE_CTRL 0x00120 +#define XDPTX_DPCD_FAUX_FORWARD_CH_DRIVE_SET 0x00121 +#define XDPTX_DPCD_BACK_CH_STATUS 0x00122 +#define XDPTX_DPCD_FAUX_BACK_CH_SYMBOL_ERROR_COUNT 0x00123 +#define XDPTX_DPCD_FAUX_BACK_CH_TRAINING_PATTERN_TIME 0x00125 +#define XDPTX_DPCD_TX_GTC_VALUE_7_0 0x00154 +#define XDPTX_DPCD_TX_GTC_VALUE_15_8 0x00155 +#define XDPTX_DPCD_TX_GTC_VALUE_23_16 0x00156 +#define XDPTX_DPCD_TX_GTC_VALUE_31_24 0x00157 +#define XDPTX_DPCD_RX_GTC_VALUE_PHASE_SKEW_EN 0x00158 +#define XDPTX_DPCD_TX_GTC_FREQ_LOCK_DONE 0x00159 +#define XDPTX_DPCD_ADAPTER_CTRL 0x001A0 +#define XDPTX_DPCD_BRANCH_DEVICE_CTRL 0x001A1 +#define XDPTX_DPCD_PAYLOAD_ALLOCATE_SET 0x001C0 +#define XDPTX_DPCD_PAYLOAD_ALLOCATE_START_TIME_SLOT 0x001C1 +#define XDPTX_DPCD_PAYLOAD_ALLOCATE_TIME_SLOT_COUNT 0x001C2 +/* @} */ + +/** @name DisplayPort Configuration Data: Link/sink status field. + * @{ + */ +#define XDPTX_DPCD_SINK_COUNT 0x00200 +#define XDPTX_DPCD_DEVICE_SERVICE_IRQ 0x00201 +#define XDPTX_DPCD_STATUS_LANE_0_1 0x00202 +#define XDPTX_DPCD_STATUS_LANE_2_3 0x00203 +#define XDPTX_DPCD_LANE_ALIGN_STATUS_UPDATED 0x00204 +#define XDPTX_DPCD_SINK_STATUS 0x00205 +#define XDPTX_DPCD_ADJ_REQ_LANE_0_1 0x00206 +#define XDPTX_DPCD_ADJ_REQ_LANE_2_3 0x00207 +#define XDPTX_DPCD_TRAINING_SCORE_LANE_0 0x00208 +#define XDPTX_DPCD_TRAINING_SCORE_LANE_1 0x00209 +#define XDPTX_DPCD_TRAINING_SCORE_LANE_2 0x0020A +#define XDPTX_DPCD_TRAINING_SCORE_LANE_3 0x0020B +#define XDPTX_DPCD_ADJ_REQ_PC2 0x0020C +#define XDPTX_DPCD_FAUX_FORWARD_CH_SYMBOL_ERROR_COUNT 0x0020D +#define XDPTX_DPCD_SYMBOL_ERROR_COUNT_LANE_0 0x00210 +#define XDPTX_DPCD_SYMBOL_ERROR_COUNT_LANE_1 0x00212 +#define XDPTX_DPCD_SYMBOL_ERROR_COUNT_LANE_2 0x00214 +#define XDPTX_DPCD_SYMBOL_ERROR_COUNT_LANE_3 0x00216 +/* @} */ + +/** @name DisplayPort Configuration Data: Automated testing sub-field. + * @{ + */ +#define XDPTX_DPCD_FAUX_FORWARD_CH_STATUS 0x00280 +#define XDPTX_DPCD_FAUX_BACK_CH_DRIVE_SET 0x00281 +#define XDPTX_DPCD_FAUX_BACK_CH_SYM_ERR_COUNT_CTRL 0x00282 +#define XDPTX_DPCD_PAYLOAD_TABLE_UPDATE_STATUS 0x002C0 +#define XDPTX_DPCD_VC_PAYLOAD_ID_SLOT(SlotNum) \ + (XDPTX_DPCD_PAYLOAD_TABLE_UPDATE_STATUS + SlotNum) +/* @} */ + +/** @name DisplayPort Configuration Data: Sink control field. + * @{ + */ +#define XDPTX_DPCD_SET_POWER_DP_PWR_VOLTAGE 0x00600 +/* @} */ + +/** @name DisplayPort Configuration Data: Sideband message buffers. + * @{ + */ +#define XDPTX_DPCD_DOWN_REQ 0x01000 +#define XDPTX_DPCD_UP_REP 0x01200 +#define XDPTX_DPCD_DOWN_REP 0x01400 +#define XDPTX_DPCD_UP_REQ 0x01600 +/* @} */ + +/** @name DisplayPort Configuration Data: Event status indicator field. + * @{ + */ +#define XDPTX_DPCD_SINK_COUNT_ESI 0x02002 +#define XDPTX_DPCD_SINK_DEVICE_SERVICE_IRQ_VECTOR_ESI0 0x02003 +#define XDPTX_DPCD_SINK_DEVICE_SERVICE_IRQ_VECTOR_ESI1 0x02004 +#define XDPTX_DPCD_SINK_LINK_SERVICE_IRQ_VECTOR_ESI0 0x02005 +#define XDPTX_DPCD_SINK_LANE0_1_STATUS 0x0200C +#define XDPTX_DPCD_SINK_LANE2_3_STATUS 0x0200D +#define XDPTX_DPCD_SINK_ALIGN_STATUS_UPDATED_ESI 0x0200E +#define XDPTX_DPCD_SINK_STATUS_ESI 0x0200F +/* @} */ + +/** @name DisplayPort Configuration Data: Field addresses and sizes. + * @{ + */ +#define XDPTX_DPCD_RECEIVER_CAP_FIELD_START XDPTX_DPCD_REV +#define XDPTX_DPCD_RECEIVER_CAP_FIELD_SIZE 0x100 +#define XDPTX_DPCD_LINK_CFG_FIELD_START XDPTX_DPCD_LINK_BW_SET +#define XDPTX_DPCD_LINK_CFG_FIELD_SIZE 0x100 +#define XDPTX_DPCD_LINK_SINK_STATUS_FIELD_START XDPTX_DPCD_SINK_COUNT +#define XDPTX_DPCD_LINK_SINK_STATUS_FIELD_SIZE 0x17 +/* @} */ + +/******************************************************************************/ + +/** @name DisplayPort Configuration Data: Receiver capability field masks, + * shifts, and register values. + * @{ + */ +/* 0x00000: DPCD_REV */ +#define XDPTX_DPCD_REV_MNR_MASK 0x0F +#define XDPTX_DPCD_REV_MJR_MASK 0xF0 +#define XDPTX_DPCD_REV_MJR_SHIFT 4 +/* 0x00001: MAX_LINK_RATE */ +#define XDPTX_DPCD_MAX_LINK_RATE_162GBPS 0x06 +#define XDPTX_DPCD_MAX_LINK_RATE_270GBPS 0x0A +#define XDPTX_DPCD_MAX_LINK_RATE_540GBPS 0x14 +/* 0x00002: MAX_LANE_COUNT */ +#define XDPTX_DPCD_MAX_LANE_COUNT_MASK 0x1F +#define XDPTX_DPCD_MAX_LANE_COUNT_1 0x01 +#define XDPTX_DPCD_MAX_LANE_COUNT_2 0x02 +#define XDPTX_DPCD_MAX_LANE_COUNT_4 0x04 +#define XDPTX_DPCD_TPS3_SUPPORT_MASK 0x40 +#define XDPTX_DPCD_ENHANCED_FRAME_SUPPORT_MASK 0x80 +/* 0x00003: MAX_DOWNSPREAD */ +#define XDPTX_DPCD_MAX_DOWNSPREAD_MASK 0x01 +#define XDPTX_DPCD_NO_AUX_HANDSHAKE_LINK_TRAIN_MASK 0x40 +/* 0x00005: DOWNSP_PRESENT */ +#define XDPTX_DPCD_DOWNSP_PRESENT_MASK 0x01 +#define XDPTX_DPCD_DOWNSP_TYPE_MASK 0x06 +#define XDPTX_DPCD_DOWNSP_TYPE_SHIFT 1 +#define XDPTX_DPCD_DOWNSP_TYPE_DP 0x0 +#define XDPTX_DPCD_DOWNSP_TYPE_AVGA_ADVII 0x1 +#define XDPTX_DPCD_DOWNSP_TYPE_DVI_HDMI_DPPP 0x2 +#define XDPTX_DPCD_DOWNSP_TYPE_OTHERS 0x3 +#define XDPTX_DPCD_DOWNSP_FORMAT_CONV_MASK 0x08 +#define XDPTX_DPCD_DOWNSP_DCAP_INFO_AVAIL_MASK 0x10 +/* 0x00006, 0x00108: ML_CH_CODING_SUPPORT, ML_CH_CODING_SET */ +#define XDPTX_DPCD_ML_CH_CODING_MASK 0x01 +/* 0x00007: DOWNSP_COUNT_MSA_OUI */ +#define XDPTX_DPCD_DOWNSP_COUNT_MASK 0x0F +#define XDPTX_DPCD_MSA_TIMING_PAR_IGNORED_MASK 0x40 +#define XDPTX_DPCD_OUI_SUPPORT_MASK 0x80 +/* 0x00008, 0x0000A: RX_PORT[0-1]_CAP_0 */ +#define XDPTX_DPCD_RX_PORTX_CAP_0_LOCAL_EDID_PRESENT_MASK 0x02 +#define XDPTX_DPCD_RX_PORTX_CAP_0_ASSOC_TO_PRECEDING_PORT_MASK 0x04 +/* 0x0000C, 0x00109: I2C_SPEED_CTL_CAP, I2C_SPEED_CTL_SET */ +#define XDPTX_DPCD_I2C_SPEED_CTL_NONE 0x00 +#define XDPTX_DPCD_I2C_SPEED_CTL_1KBIPS 0x01 +#define XDPTX_DPCD_I2C_SPEED_CTL_5KBIPS 0x02 +#define XDPTX_DPCD_I2C_SPEED_CTL_10KBIPS 0x04 +#define XDPTX_DPCD_I2C_SPEED_CTL_100KBIPS 0x08 +#define XDPTX_DPCD_I2C_SPEED_CTL_400KBIPS 0x10 +#define XDPTX_DPCD_I2C_SPEED_CTL_1MBIPS 0x20 +/* 0x0000E: TRAIN_AUX_RD_INTERVAL */ +#define XDPTX_DPCD_TRAIN_AUX_RD_INT_100_400US 0x00 +#define XDPTX_DPCD_TRAIN_AUX_RD_INT_4MS 0x01 +#define XDPTX_DPCD_TRAIN_AUX_RD_INT_8MS 0x02 +#define XDPTX_DPCD_TRAIN_AUX_RD_INT_12MS 0x03 +#define XDPTX_DPCD_TRAIN_AUX_RD_INT_16MS 0x04 +/* 0x00020: DPCD_FAUX_CAP */ +#define XDPTX_DPCD_FAUX_CAP_MASK 0x01 +/* 0x00021: MSTM_CAP */ +#define XDPTX_DPCD_MST_CAP_MASK 0x01 +/* 0x00080, 0x00081|4, 0x00082|8, 0x00083|C: DOWNSP_X_(DET_)CAP */ +#define XDPTX_DPCD_DOWNSP_X_CAP_TYPE_MASK 0x07 +#define XDPTX_DPCD_DOWNSP_X_CAP_TYPE_DP 0x0 +#define XDPTX_DPCD_DOWNSP_X_CAP_TYPE_AVGA 0x1 +#define XDPTX_DPCD_DOWNSP_X_CAP_TYPE_DVI 0x2 +#define XDPTX_DPCD_DOWNSP_X_CAP_TYPE_HDMI 0x3 +#define XDPTX_DPCD_DOWNSP_X_CAP_TYPE_OTHERS 0x4 +#define XDPTX_DPCD_DOWNSP_X_CAP_TYPE_DPPP 0x5 +#define XDPTX_DPCD_DOWNSP_X_CAP_HPD_MASK 0x80 +#define XDPTX_DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_MASK 0xF0 +#define XDPTX_DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_SHIFT 4 +#define XDPTX_DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_720_480_I_60 0x1 +#define XDPTX_DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_720_480_I_50 0x2 +#define XDPTX_DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_1920_1080_I_60 0x3 +#define XDPTX_DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_1920_1080_I_50 0x4 +#define XDPTX_DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_1280_720_P_60 0x5 +#define XDPTX_DPCD_DOWNSP_X_CAP_NON_EDID_ATTR_1280_720_P_50 0x7 +/* 0x00082, 0x00086, 0x0008A, 0x0008E: DOWNSP_X_(DET_)CAP2 */ +#define XDPTX_DPCD_DOWNSP_X_DCAP_MAX_BPC_MASK 0x03 +#define XDPTX_DPCD_DOWNSP_X_DCAP_MAX_BPC_8 0x0 +#define XDPTX_DPCD_DOWNSP_X_DCAP_MAX_BPC_10 0x1 +#define XDPTX_DPCD_DOWNSP_X_DCAP_MAX_BPC_12 0x2 +#define XDPTX_DPCD_DOWNSP_X_DCAP_MAX_BPC_16 0x3 +/* 0x00082, 0x00086, 0x0008A, 0x0008E: DOWNSP_X_(DET_)CAP2 */ +#define XDPTX_DPCD_DOWNSP_X_DCAP_HDMI_DPPP_FS2FP_MASK 0x01 +#define XDPTX_DPCD_DOWNSP_X_DCAP_DVI_DL_MASK 0x02 +#define XDPTX_DPCD_DOWNSP_X_DCAP_DVI_HCD_MASK 0x04 +/* @} */ + +/** @name DisplayPort Configuration Data: Link configuration field masks, + * shifts, and register values. + * @{ + */ +/* 0x00100: XDPTX_DPCD_LINK_BW_SET */ +#define XDPTX_DPCD_LINK_BW_SET_162GBPS 0x06 +#define XDPTX_DPCD_LINK_BW_SET_270GBPS 0x0A +#define XDPTX_DPCD_LINK_BW_SET_540GBPS 0x14 +/* 0x00101: LANE_COUNT_SET */ +#define XDPTX_DPCD_LANE_COUNT_SET_MASK 0x1F +#define XDPTX_DPCD_LANE_COUNT_SET_1 0x01 +#define XDPTX_DPCD_LANE_COUNT_SET_2 0x02 +#define XDPTX_DPCD_LANE_COUNT_SET_4 0x04 +#define XDPTX_DPCD_ENHANCED_FRAME_EN_MASK 0x80 +/* 0x00102: TP_SET */ +#define XDPTX_DPCD_TP_SEL_MASK 0x03 +#define XDPTX_DPCD_TP_SEL_OFF 0x0 +#define XDPTX_DPCD_TP_SEL_TP1 0x1 +#define XDPTX_DPCD_TP_SEL_TP2 0x2 +#define XDPTX_DPCD_TP_SEL_TP3 0x3 +#define XDPTX_DPCD_TP_SET_LQP_MASK 0x06 +#define XDPTX_DPCD_TP_SET_LQP_SHIFT 2 +#define XDPTX_DPCD_TP_SET_LQP_OFF 0x0 +#define XDPTX_DPCD_TP_SET_LQP_D102_TEST 0x1 +#define XDPTX_DPCD_TP_SET_LQP_SER_MES 0x2 +#define XDPTX_DPCD_TP_SET_LQP_PRBS7 0x3 +#define XDPTX_DPCD_TP_SET_REC_CLK_OUT_EN_MASK 0x10 +#define XDPTX_DPCD_TP_SET_SCRAMB_DIS_MASK 0x20 +#define XDPTX_DPCD_TP_SET_SE_COUNT_SEL_MASK 0xC0 +#define XDPTX_DPCD_TP_SET_SE_COUNT_SEL_SHIFT 6 +#define XDPTX_DPCD_TP_SET_SE_COUNT_SEL_DE_ISE 0x0 +#define XDPTX_DPCD_TP_SET_SE_COUNT_SEL_DE 0x1 +#define XDPTX_DPCD_TP_SET_SE_COUNT_SEL_ISE 0x2 +/* 0x00103-0x00106: TRAINING_LANE[0-3]_SET */ +#define XDPTX_DPCD_TRAINING_LANEX_SET_VS_MASK 0x03 +#define XDPTX_DPCD_TRAINING_LANEX_SET_MAX_VS_MASK 0x04 +#define XDPTX_DPCD_TRAINING_LANEX_SET_PE_MASK 0x18 +#define XDPTX_DPCD_TRAINING_LANEX_SET_PE_SHIFT 3 +#define XDPTX_DPCD_TRAINING_LANEX_SET_MAX_PE_MASK 0x20 +/* 0x00107: DOWNSPREAD_CTRL */ +#define XDPTX_DPCD_SPREAD_AMP_MASK 0x10 +#define XDPTX_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 XDPTX_DPCD_TRAINING_LANE_0_2_SET_PC2_MASK 0x03 +#define XDPTX_DPCD_TRAINING_LANE_0_2_SET_MAX_PC2_MASK 0x04 +#define XDPTX_DPCD_TRAINING_LANE_1_3_SET_PC2_MASK 0x30 +#define XDPTX_DPCD_TRAINING_LANE_1_3_SET_PC2_SHIFT 4 +#define XDPTX_DPCD_TRAINING_LANE_1_3_SET_MAX_PC2_MASK 0x40 +/* 0x00111: MSTM_CTRL */ +#define XDPTX_DPCD_MST_EN_MASK 0x01 +#define XDPTX_DPCD_UP_REQ_EN_MASK 0x02 +#define XDPTX_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 XDPTX_DPCD_STATUS_LANE_0_CR_DONE_MASK 0x01 +#define XDPTX_DPCD_STATUS_LANE_0_CE_DONE_MASK 0x02 +#define XDPTX_DPCD_STATUS_LANE_0_SL_DONE_MASK 0x04 +#define XDPTX_DPCD_STATUS_LANE_1_CR_DONE_MASK 0x10 +#define XDPTX_DPCD_STATUS_LANE_1_CE_DONE_MASK 0x20 +#define XDPTX_DPCD_STATUS_LANE_1_SL_DONE_MASK 0x40 +/* 0x00202: STATUS_LANE_2_3 */ +#define XDPTX_DPCD_STATUS_LANE_2_CR_DONE_MASK 0x01 +#define XDPTX_DPCD_STATUS_LANE_2_CE_DONE_MASK 0x02 +#define XDPTX_DPCD_STATUS_LANE_2_SL_DONE_MASK 0x04 +#define XDPTX_DPCD_STATUS_LANE_3_CR_DONE_MASK 0x10 +#define XDPTX_DPCD_STATUS_LANE_3_CE_DONE_MASK 0x20 +#define XDPTX_DPCD_STATUS_LANE_3_SL_DONE_MASK 0x40 +/* 0x00204: LANE_ALIGN_STATUS_UPDATED */ +#define XDPTX_DPCD_LANE_ALIGN_STATUS_UPDATED_IA_DONE_MASK \ + 0x01 +#define XDPTX_DPCD_LANE_ALIGN_STATUS_UPDATED_DOWNSP_STATUS_CHANGED_MASK \ + 0x40 +#define XDPTX_DPCD_LANE_ALIGN_STATUS_UPDATED_LINK_STATUS_UPDATED_MASK \ + 0x80 +/* 0x00205: SINK_STATUS */ +#define XDPTX_DPCD_SINK_STATUS_RX_PORT0_SYNC_STATUS_MASK 0x01 +#define XDPTX_DPCD_SINK_STATUS_RX_PORT1_SYNC_STATUS_MASK 0x02 + +/* 0x00206, 0x00207: ADJ_REQ_LANE_[0,2]_[1,3] */ +#define XDPTX_DPCD_ADJ_REQ_LANE_0_2_VS_MASK 0x03 +#define XDPTX_DPCD_ADJ_REQ_LANE_0_2_PE_MASK 0x0C +#define XDPTX_DPCD_ADJ_REQ_LANE_0_2_PE_SHIFT 2 +#define XDPTX_DPCD_ADJ_REQ_LANE_1_3_VS_MASK 0x30 +#define XDPTX_DPCD_ADJ_REQ_LANE_1_3_VS_SHIFT 4 +#define XDPTX_DPCD_ADJ_REQ_LANE_1_3_PE_MASK 0xC0 +#define XDPTX_DPCD_ADJ_REQ_LANE_1_3_PE_SHIFT 6 +/* 0x0020C: ADJ_REQ_PC2 */ +#define XDPTX_DPCD_ADJ_REQ_PC2_LANE_0_MASK 0x03 +#define XDPTX_DPCD_ADJ_REQ_PC2_LANE_1_MASK 0x0C +#define XDPTX_DPCD_ADJ_REQ_PC2_LANE_1_SHIFT 2 +#define XDPTX_DPCD_ADJ_REQ_PC2_LANE_2_MASK 0x30 +#define XDPTX_DPCD_ADJ_REQ_PC2_LANE_2_SHIFT 4 +#define XDPTX_DPCD_ADJ_REQ_PC2_LANE_3_MASK 0xC0 +#define XDPTX_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 XDPTX_EDID_ADDR 0x50 +#define XDPTX_EDID_SIZE 128 +#define XDPTX_EDID_DTD_DD(Num) (0x36 + (18 * Num)) +#define XDPTX_EDID_PTM XDPTX_EDID_DTD_DD(0) +/* @} */ + +/** @name Extended Display Identification Data: Register offsets for the + * Detailed Timing Descriptor (DTD). + * @{ + */ +#define XDPTX_EDID_DTD_PIXEL_CLK_KHZ_LSB 0x00 +#define XDPTX_EDID_DTD_PIXEL_CLK_KHZ_MSB 0x01 +#define XDPTX_EDID_DTD_HRES_LSB 0x02 +#define XDPTX_EDID_DTD_HBLANK_LSB 0x03 +#define XDPTX_EDID_DTD_HRES_HBLANK_U4 0x04 +#define XDPTX_EDID_DTD_VRES_LSB 0x05 +#define XDPTX_EDID_DTD_VBLANK_LSB 0x06 +#define XDPTX_EDID_DTD_VRES_VBLANK_U4 0x07 +#define XDPTX_EDID_DTD_HFPORCH_LSB 0x08 +#define XDPTX_EDID_DTD_HSPW_LSB 0x09 +#define XDPTX_EDID_DTD_VFPORCH_VSPW_L4 0x0A +#define XDPTX_EDID_DTD_XFPORCH_XSPW_U2 0x0B +#define XDPTX_EDID_DTD_HIMGSIZE_MM_LSB 0x0C +#define XDPTX_EDID_DTD_VIMGSIZE_MM_LSB 0x0D +#define XDPTX_EDID_DTD_XIMGSIZE_MM_U4 0x0E +#define XDPTX_EDID_DTD_HBORDER 0x0F +#define XDPTX_EDID_DTD_VBORDER 0x10 +#define XDPTX_EDID_DTD_SIGNAL 0x11 + +/** @name Extended Display Identification Data: Masks, shifts, and register + * values. + * @{ + */ +#define XDPTX_EDID_DTD_XRES_XBLANK_U4_XBLANK_MASK 0x0F +#define XDPTX_EDID_DTD_XRES_XBLANK_U4_XRES_MASK 0xF0 +#define XDPTX_EDID_DTD_XRES_XBLANK_U4_XRES_SHIFT 4 +#define XDPTX_EDID_DTD_VFPORCH_VSPW_L4_VSPW_MASK 0x0F +#define XDPTX_EDID_DTD_VFPORCH_VSPW_L4_VFPORCH_MASK 0xF0 +#define XDPTX_EDID_DTD_VFPORCH_VSPW_L4_VFPORCH_SHIFT 4 +#define XDPTX_EDID_DTD_XFPORCH_XSPW_U2_HFPORCH_MASK 0xC0 +#define XDPTX_EDID_DTD_XFPORCH_XSPW_U2_HSPW_MASK 0x30 +#define XDPTX_EDID_DTD_XFPORCH_XSPW_U2_VFPORCH_MASK 0x0C +#define XDPTX_EDID_DTD_XFPORCH_XSPW_U2_VSPW_MASK 0x03 +#define XDPTX_EDID_DTD_XFPORCH_XSPW_U2_HFPORCH_SHIFT 6 +#define XDPTX_EDID_DTD_XFPORCH_XSPW_U2_HSPW_SHIFT 4 +#define XDPTX_EDID_DTD_XFPORCH_XSPW_U2_VFPORCH_SHIFT 2 +#define XDPTX_EDID_DTD_XIMGSIZE_MM_U4_VIMGSIZE_MM_MASK 0x0F +#define XDPTX_EDID_DTD_XIMGSIZE_MM_U4_HIMGSIZE_MM_MASK 0xF0 +#define XDPTX_EDID_DTD_XIMGSIZE_MM_U4_HIMGSIZE_MM_SHIFT 4 +#define XDPTX_EDID_DTD_SIGNAL_HPOLARITY_MASK 0x02 +#define XDPTX_EDID_DTD_SIGNAL_VPOLARITY_MASK 0x04 +#define XDPTX_EDID_DTD_SIGNAL_HPOLARITY_SHIFT 1 +#define XDPTX_EDID_DTD_SIGNAL_VPOLARITY_SHIFT 2 +/* @} */ + +/******************************************************************************/ +/** + * Multi-stream transport (MST) definitions. + * +*******************************************************************************/ +/** @name Stream identification. + * @{ + */ +#define XDPTX_STREAM_ID0 0 +#define XDPTX_STREAM_ID1 1 +#define XDPTX_STREAM_ID2 2 +#define XDPTX_STREAM_ID3 3 +/* @} */ + +/** @name Sideband message codes when the driver is in MST mode. + * @{ + */ +#define XDPTX_SBMSG_LINK_ADDRESS 0x01 +#define XDPTX_SBMSG_ENUM_PATH_RESOURCES 0x10 +#define XDPTX_SBMSG_ALLOCATE_PAYLOAD 0x11 +#define XDPTX_SBMSG_CLEAR_PAYLOAD_ID_TABLE 0x14 +#define XDPTX_SBMSG_REMOTE_DPCD_READ 0x20 +#define XDPTX_SBMSG_REMOTE_DPCD_WRITE 0x21 +#define XDPTX_SBMSG_REMOTE_I2C_READ 0x22 +/* @} */ + +/******************* Macros (Inline Functions) Definitions ********************/ + +/** @name Register access macro definitions. + * @{ + */ +#define XDptx_In32 Xil_In32 +#define XDptx_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 XDptx_ReadReg(u32 BaseAddress, u32 RegOffset) + * +*******************************************************************************/ +#define XDptx_ReadReg(BaseAddress, RegOffset) \ + XDptx_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 XDptx_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) + * +*******************************************************************************/ +#define XDptx_WriteReg(BaseAddress, RegOffset, Data) \ + XDptx_Out32((BaseAddress) + (RegOffset), (Data)) + +#endif /* XDPTX_HW_H_ */ diff --git a/XilinxProcessorIPLib/drivers/dptx/src/xdptx_intr.c b/XilinxProcessorIPLib/drivers/dptx/src/xdptx_intr.c new file mode 100644 index 00000000..30c56caf --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/src/xdptx_intr.c @@ -0,0 +1,160 @@ +/******************************************************************************* + * + * Copyright (C) 2014 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xdptx_intr.c + * + * This file contains functions related to XDptx interrupt handling. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  05/17/14 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdptx.h" + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function installs a callback function for when a hot-plug-detect event + * interrupt occurs. + * + * @param InstancePtr is a pointer to the XDptx 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 XDptx_SetHpdEventHandler(XDptx *InstancePtr, + XDptx_HpdEventHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->HpdEventHandler = CallbackFunc; + InstancePtr->HpdEventCallbackRef = CallbackRef; +} + +/******************************************************************************/ +/** + * This function installs a callback function for when a hot-plug-detect pulse + * interrupt occurs. + * + * @param InstancePtr is a pointer to the XDptx 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 XDptx_SetHpdPulseHandler(XDptx *InstancePtr, + XDptx_HpdPulseHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->HpdPulseHandler = CallbackFunc; + InstancePtr->HpdPulseCallbackRef = CallbackRef; +} + +/******************************************************************************/ +/** + * This function is the interrupt handler for the XDptx driver. + * + * 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 XDptx instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDptx_HpdInterruptHandler(XDptx *InstancePtr) +{ + u32 IntrStatus; + u8 HpdEventDetected; + u8 HpdPulseDetected; + u32 HpdDuration; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + + /* Determine what kind of interrupt occurred. + * Note: XDPTX_INTERRUPT_STATUS is an RC (read-clear) register. */ + IntrStatus = XDptx_ReadReg(InstancePtr->Config.BaseAddr, + XDPTX_INTERRUPT_STATUS); + IntrStatus &= ~XDptx_ReadReg(InstancePtr->Config.BaseAddr, + XDPTX_INTERRUPT_MASK); + + HpdEventDetected = IntrStatus & XDPTX_INTERRUPT_STATUS_HPD_EVENT_MASK; + HpdPulseDetected = IntrStatus & + XDPTX_INTERRUPT_STATUS_HPD_PULSE_DETECTED_MASK; + + if (HpdEventDetected) { + InstancePtr->HpdEventHandler(InstancePtr->HpdEventCallbackRef); + } + + if (HpdPulseDetected) { + /* The source device must debounce the incoming HPD signal by + * sampling the value at an interval greater than 250 ms. */ + HpdDuration = XDptx_ReadReg(InstancePtr->Config.BaseAddr, + XDPTX_HPD_DURATION); + if (HpdDuration >= 250) { + InstancePtr->HpdPulseHandler( + InstancePtr->HpdPulseCallbackRef); + } + } +} diff --git a/XilinxProcessorIPLib/drivers/dptx/src/xdptx_mst.c b/XilinxProcessorIPLib/drivers/dptx/src/xdptx_mst.c new file mode 100644 index 00000000..a1d2b7ca --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/src/xdptx_mst.c @@ -0,0 +1,2482 @@ +/******************************************************************************* + * + * Copyright (C) 2014 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xdptx_mst.c + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  08/03/14 Initial release.
+ * 2.0   als  09/21/14 Improvements to topology discovery and sideband messages.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "string.h" +#include "xdptx.h" +#include "xstatus.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 XDPTX_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 XDPTX_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. */ +} XDptx_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. */ +} XDptx_SidebandMsgBody; + +/** + * This typedef stores the entire sideband message. + */ +typedef struct +{ + XDptx_SidebandMsgHeader Header; /**< The header segment of the sideband + message. */ + XDptx_SidebandMsgBody Body; /**< The body segment of the sideband + message. */ +} XDptx_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. */ +} XDptx_SidebandReply; + +/**************************** Function Prototypes *****************************/ + +static void XDptx_IssueGuid(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, XDptx_Topology *Topology, + u32 *Guid); +static void XDptx_AddBranchToList(XDptx *InstancePtr, + XDptx_SbMsgLinkAddressReplyDeviceInfo *DeviceInfo, + u8 LinkCountTotal, u8 *RelativeAddress); +static void XDptx_AddSinkToList(XDptx *InstancePtr, + XDptx_SbMsgLinkAddressReplyPortDetail *SinkDevice, + u8 LinkCountTotal, u8 *RelativeAddress); +static void XDptx_GetDeviceInfoFromSbMsgLinkAddress( + XDptx_SidebandReply *SbReply, + XDptx_SbMsgLinkAddressReplyDeviceInfo *FormatReply); +static u32 XDptx_GetFirstAvailableTs(XDptx *InstancePtr, u8 *FirstTs); +static u32 XDptx_SendActTrigger(XDptx *InstancePtr); +static u32 XDptx_SendSbMsg(XDptx *InstancePtr, XDptx_SidebandMsg *Msg); +static u32 XDptx_ReceiveSbMsg(XDptx *InstancePtr, XDptx_SidebandReply *SbReply); +static u32 XDptx_WaitSbReply(XDptx *InstancePtr); +static u32 XDptx_Transaction2MsgFormat(u8 *Transaction, XDptx_SidebandMsg *Msg); +static u8 XDptx_Crc4CalculateHeader(XDptx_SidebandMsgHeader *Header); +static u8 XDptx_Crc8CalculateBody(XDptx_SidebandMsgBody *Body); +static u8 XDptx_CrcCalculate(const u8 *Data, u32 NumberOfBits, u8 Polynomial); + +/**************************** 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 + * XDptx_FindAccessibleDpDevices 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 XDptx instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDptx_MstCfgModeEnable(XDptx *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + + InstancePtr->MstEnable = 1; +} + +/******************************************************************************/ +/** + * This function will disable multi-stream transport (MST) mode for the driver. + * + * @param InstancePtr is a pointer to the XDptx instance. + * + * @return None. + * + * @note When disabled, the driver will behave in single-stream transport + * (SST) mode. + * +*******************************************************************************/ +void XDptx_MstCfgModeDisable(XDptx *InstancePtr) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + + InstancePtr->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 XDptx 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 XDptx_MstCapable(XDptx *InstancePtr) +{ + u32 Status; + u8 AuxData; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + 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 = XDptx_AuxRead(InstancePtr, XDPTX_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 = XDptx_AuxRead(InstancePtr, XDPTX_DPCD_MSTM_CAP, 1, &AuxData); + if (Status != XST_SUCCESS) { + /* The AUX read transaction failed. */ + return Status; + } + else if ((AuxData & XDPTX_DPCD_MST_CAP_MASK) != + XDPTX_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 XDptx 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 XDptx_MstEnable(XDptx *InstancePtr) +{ + u32 Status; + u8 AuxData; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Check if the immediate downstream RX device has MST capabilities. */ + Status = XDptx_MstCapable(InstancePtr); + if (Status != XST_SUCCESS) { + /* The RX device is not downstream capable. */ + return Status; + } + + /* HPD long pulse used for upstream notification. */ + AuxData = 0; + Status = XDptx_AuxWrite(InstancePtr, XDPTX_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 = XDPTX_DPCD_UP_IS_SRC_MASK | XDPTX_DPCD_UP_REQ_EN_MASK | + XDPTX_DPCD_MST_EN_MASK; + Status = XDptx_AuxWrite(InstancePtr, XDPTX_DPCD_MSTM_CTRL, 1, &AuxData); + if (Status != XST_SUCCESS) { + /* The AUX write transaction failed. */ + return Status; + } + + /* Enable MST in the DisplayPort TX. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_TX_MST_CONFIG, + XDPTX_TX_MST_CONFIG_MST_EN_MASK); + + 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 XDptx 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 XDptx_MstDisable(XDptx *InstancePtr) +{ + u32 Status; + u8 AuxData; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Disable MST mode in the immediate branch device. */ + AuxData = 0; + Status = XDptx_AuxWrite(InstancePtr, XDPTX_DPCD_MSTM_CTRL, 1, &AuxData); + if (Status != XST_SUCCESS) { + /* The AUX write transaction failed. */ + return Status; + } + + /* Disable MST mode in the DisplayPort TX. */ + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_TX_MST_CONFIG, 0x0); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function will check whether + * + * @param InstancePtr is a pointer to the XDptx 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 XDptx_MstStreamIsEnabled(XDptx *InstancePtr, u8 Stream) +{ + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid((Stream == XDPTX_STREAM_ID0) || + (Stream == XDPTX_STREAM_ID1) || (Stream == XDPTX_STREAM_ID2) || + (Stream == XDPTX_STREAM_ID3)); + + return InstancePtr->MstStreamConfig[Stream].MstStreamEnable; +} + +/******************************************************************************/ +/** + * This function will configure the InstancePtr->MstStreamConfig structure to + * enable the specified stream. + * + * @param InstancePtr is a pointer to the XDptx instance. + * @param Stream is the stream ID that will be enabled. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDptx_MstCfgStreamEnable(XDptx *InstancePtr, u8 Stream) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((Stream == XDPTX_STREAM_ID0) || + (Stream == XDPTX_STREAM_ID1) || (Stream == XDPTX_STREAM_ID2) || + (Stream == XDPTX_STREAM_ID3)); + + InstancePtr->MstStreamConfig[Stream].MstStreamEnable = 1; +} + +/******************************************************************************/ +/** + * This function will configure the InstancePtr->MstStreamConfig structure to + * disable the specified stream. + * + * @param InstancePtr is a pointer to the XDptx instance. + * @param Stream is the stream ID that will be disabled. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDptx_MstCfgStreamDisable(XDptx *InstancePtr, u8 Stream) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((Stream == XDPTX_STREAM_ID0) || + (Stream == XDPTX_STREAM_ID1) || (Stream == XDPTX_STREAM_ID2) || + (Stream == XDPTX_STREAM_ID3)); + + InstancePtr->MstStreamConfig[Stream].MstStreamEnable = 0; +} + +/******************************************************************************/ +/** + * This function will map a stream to a downstream DisplayPort TX device that is + * associated with a sink from the InstancePtr->Topology.SinkList. + * + * @param InstancePtr is a pointer to the XDptx 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->MstStreamConfig[Stream] will be + * modified. + * @note The topology will need to be determined prior to calling this + * function using the XDptx_FindAccessibleDpDevices. + * +*******************************************************************************/ +void XDptx_SetStreamSelectFromSinkList(XDptx *InstancePtr, u8 Stream, u8 + SinkNum) +{ + u8 Index; + XDptx_MstStream *MstStream; + XDptx_Topology *Topology; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((Stream == XDPTX_STREAM_ID0) || + (Stream == XDPTX_STREAM_ID1) || (Stream == XDPTX_STREAM_ID2) || + (Stream == XDPTX_STREAM_ID3)); + + MstStream = &InstancePtr->MstStreamConfig[Stream]; + Topology = &InstancePtr->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 XDptx 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->MstStreamConfig[Stream] will be + * modified. + * +*******************************************************************************/ +void XDptx_SetStreamSinkRad(XDptx *InstancePtr, u8 Stream, u8 LinkCountTotal, + u8 *RelativeAddress) +{ + u8 Index; + XDptx_MstStream *MstStream; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((Stream == XDPTX_STREAM_ID0) || + (Stream == XDPTX_STREAM_ID1) || (Stream == XDPTX_STREAM_ID2) || + (Stream == XDPTX_STREAM_ID3)); + Xil_AssertVoid(LinkCountTotal > 0); + Xil_AssertVoid(RelativeAddress != NULL); + + MstStream = &InstancePtr->MstStreamConfig[Stream]; + + 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 XDptx 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->Topology structure will be + * modified. + * +*******************************************************************************/ +u32 XDptx_DiscoverTopology(XDptx *InstancePtr) +{ + u8 RelativeAddress[15]; + + return XDptx_FindAccessibleDpDevices(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 XDptx 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->Topology structure will be + * modified. + * +*******************************************************************************/ +u32 XDptx_FindAccessibleDpDevices(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress) +{ + u32 Status; + u8 Index; + u8 NumDownBranches = 0; + u8 OverallFailures = 0; + XDptx_Topology *Topology; + XDptx_SbMsgLinkAddressReplyPortDetail *PortDetails; + static XDptx_SbMsgLinkAddressReplyDeviceInfo DeviceInfo; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(LinkCountTotal > 0); + Xil_AssertVoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + + Topology = &InstancePtr->Topology; + + /* Send a LINK_ADDRESS sideband message to the branch device in order to + * obtain information on it and its downstream devices. */ + Status = XDptx_SendSbMsgLinkAddress(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. */ + XDptx_IssueGuid(InstancePtr, LinkCountTotal, RelativeAddress, Topology, + DeviceInfo.Guid); + + /* Add the branch device to the topology table. */ + XDptx_AddBranchToList(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. */ + XDptx_IssueGuid(InstancePtr, + LinkCountTotal, RelativeAddress, + Topology, PortDetails->Guid); + } + + XDptx_AddSinkToList(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 = XDptx_FindAccessibleDpDevices(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; +} + +/******************************************************************************/ +/** + * This function will allocate bandwidth for all enabled stream. + * + * @param InstancePtr is a pointer to the XDptx 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 XDptx_AllocatePayloadStreams(XDptx *InstancePtr) +{ + u32 Status; + u8 StreamIndex; + XDptx_MstStream *MstStream; + XDptx_MainStreamAttributes *MsaConfig; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Allocate the payload table for each stream in both the DisplayPort TX + * and RX device. */ + for (StreamIndex = 0; StreamIndex < 4; StreamIndex++) { + MstStream = &InstancePtr->MstStreamConfig[StreamIndex]; + MsaConfig = &InstancePtr->MsaConfig[StreamIndex]; + + if (XDptx_MstStreamIsEnabled(InstancePtr, StreamIndex)) { + Status = XDptx_AllocatePayloadVcIdTable(InstancePtr, + MstStream->LinkCountTotal, + MstStream->RelativeAddress, StreamIndex + 1, + MstStream->MstPbn, MsaConfig->TransferUnitSize); + if (Status != XST_SUCCESS) { + return Status; + } + } + } + + /* Generate an ACT event. */ + Status = XDptx_SendActTrigger(InstancePtr); + if (Status != XST_SUCCESS) { + return Status; + } + + /* Send ALLOCATE_PAYLOAD request. */ + for (StreamIndex = 0; StreamIndex < 4; StreamIndex++) { + MstStream = &InstancePtr->MstStreamConfig[StreamIndex]; + + if (XDptx_MstStreamIsEnabled(InstancePtr, StreamIndex)) { + Status = XDptx_SendSbMsgAllocatePayload(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 XDptx 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. + * @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 XDptx_AllocatePayloadVcIdTable(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 VcId, u16 Pbn, u8 Ts) +{ + u32 Status; + u8 AuxData[3]; + u8 Index; + u8 StartTs; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertNonvoid(VcId > 0); + Xil_AssertNonvoid(Pbn > 0); + Xil_AssertNonvoid(Ts > 0); + + /* Find next available timeslot. */ + Status = XDptx_GetFirstAvailableTs(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++) { + XDptx_WriteReg(InstancePtr->Config.BaseAddr, + (XDPTX_VC_PAYLOAD_BUFFER_ADDR + (4 * Index)), VcId); + } + + XDptx_WaitUs(InstancePtr, 1000); + + /* Allocate timeslots in sink. */ + + /* Clear the VCP table update bit. */ + AuxData[0] = 0x01; + Status = XDptx_AuxWrite(InstancePtr, + XDPTX_DPCD_PAYLOAD_TABLE_UPDATE_STATUS, 1, AuxData); + if (Status != XST_SUCCESS) { + /* The AUX write transaction failed. */ + return Status; + } + + /* Allocate VC with VcId. */ + AuxData[0] = VcId; + /* Start timeslot for VC with VcId. */ + AuxData[1] = StartTs; + /* Timeslot count for VC with VcId. */ + AuxData[2] = Ts; + Status = XDptx_AuxWrite(InstancePtr, XDPTX_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 = XDptx_AuxRead(InstancePtr, + XDPTX_DPCD_PAYLOAD_TABLE_UPDATE_STATUS, 1, AuxData); + if (Status != XST_SUCCESS) { + /* The AUX read transaction failed. */ + return Status; + } + } while ((AuxData[0] & 0x01) != 0x01); + + XDptx_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 XDptx 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 XDptx_ClearPayloadVcIdTable(XDptx *InstancePtr) +{ + u32 Status; + u8 AuxData[3]; + u8 Index; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Clear the payload table in the transmitter. */ + for (Index = 0; Index < 64; Index++) { + XDptx_WriteReg(InstancePtr->Config.BaseAddr, + (XDPTX_VC_PAYLOAD_BUFFER_ADDR + (4 * Index)), 0); + } + + XDptx_WaitUs(InstancePtr, 1000); + + /* Clear the payload table in the immediate downstream branch device. */ + + /* Clear the VCP table update bit. */ + AuxData[0] = 0x01; + Status = XDptx_AuxWrite(InstancePtr, + XDPTX_DPCD_PAYLOAD_TABLE_UPDATE_STATUS, 1, AuxData); + if (Status != XST_SUCCESS) { + /* The AUX write transaction failed. */ + return Status; + } + + /* Allocate VC with VcId. */ + AuxData[0] = 0; + /* Start timeslot for VC with VcId. */ + AuxData[1] = 0; + /* Timeslot count for VC with VcId. */ + AuxData[2] = 0x3F; + Status = XDptx_AuxWrite(InstancePtr, XDPTX_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 = XDptx_AuxRead(InstancePtr, + XDPTX_DPCD_PAYLOAD_TABLE_UPDATE_STATUS, 1, AuxData); + if (Status != XST_SUCCESS) { + /* The AUX read transaction failed. */ + return Status; + } + } while ((AuxData[0] & 0x01) != 0x01); + + XDptx_WaitUs(InstancePtr, 1000); + + Status = XDptx_SendActTrigger(InstancePtr); + if (Status != XST_SUCCESS) { + return Status; + } + + /* Send CLEAR_PAYLOAD_ID_TABLE request. */ + Status = XDptx_SendSbMsgClearPayloadIdTable(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 XDptx 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 XDptx_SendSbMsgRemoteDpcdWrite(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u32 DpcdAddress, u32 BytesToWrite, u8 *WriteData) +{ + u32 Status; + XDptx_SidebandMsg Msg; + XDptx_SidebandReply SbMsgReply; + u8 Index; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + 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 = XDptx_Crc4CalculateHeader(&Msg.Header); + + /* Prepare the sideband message body. */ + Msg.Body.MsgData[0] = XDPTX_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 = XDptx_Crc8CalculateBody(&Msg.Body); + + /* Submit the REMOTE_DPCD_WRITE transaction message request. */ + Status = XDptx_SendSbMsg(InstancePtr, &Msg); + if (Status != XST_SUCCESS) { + /* The AUX write transaction used to send the sideband message + * failed. */ + return Status; + } + Status = XDptx_ReceiveSbMsg(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 XDptx 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 XDptx_SendSbMsgRemoteDpcdRead(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u32 DpcdAddress, u32 BytesToRead, u8 *ReadData) +{ + u32 Status; + XDptx_SidebandMsg Msg; + XDptx_SidebandReply SbMsgReply; + u8 Index; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + 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 = XDptx_Crc4CalculateHeader(&Msg.Header); + + /* Prepare the sideband message body. */ + Msg.Body.MsgData[0] = XDPTX_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 = XDptx_Crc8CalculateBody(&Msg.Body); + + /* Submit the REMOTE_DPCD_READ transaction message request. */ + Status = XDptx_SendSbMsg(InstancePtr, &Msg); + if (Status != XST_SUCCESS) { + /* The AUX write transaction used to send the sideband message + * failed. */ + return Status; + } + Status = XDptx_ReceiveSbMsg(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_READ sideband message which will read + * from the specified I2C address of a downstream DisplayPort device. + * + * @param InstancePtr is a pointer to the XDptx 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 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 XDptx_SendSbMsgRemoteIicRead(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 IicDeviceId, u8 BytesToRead, u8 *ReadData) +{ + u32 Status; + XDptx_SidebandMsg Msg; + XDptx_SidebandReply SbMsgReply; + u8 Index; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + 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 = XDptx_Crc4CalculateHeader(&Msg.Header); + + /* Prepare the sideband message body. */ + Msg.Body.MsgData[0] = XDPTX_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] = 0; /* Write byte[0]. */ + 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 = XDptx_Crc8CalculateBody(&Msg.Body); + + /* Submit the REMOTE_I2C_READ transaction message request. */ + Status = XDptx_SendSbMsg(InstancePtr, &Msg); + if (Status != XST_SUCCESS) { + /* The AUX write transaction used to send the sideband message + * failed. */ + return Status; + } + Status = XDptx_ReceiveSbMsg(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 XDptx 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 XDptx_SendSbMsgLinkAddress(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, XDptx_SbMsgLinkAddressReplyDeviceInfo *DeviceInfo) +{ + u32 Status; + XDptx_SidebandMsg Msg; + XDptx_SidebandReply SbMsgReply; + u8 Index; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + 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 = XDptx_Crc4CalculateHeader(&Msg.Header); + + /* Prepare the sideband message body. */ + Msg.Body.MsgData[0] = XDPTX_SBMSG_LINK_ADDRESS; + Msg.Body.MsgDataLength = Msg.Header.MsgBodyLength - 1; + Msg.Body.Crc = XDptx_Crc8CalculateBody(&Msg.Body); + + /* Submit the LINK_ADDRESS transaction message request. */ + Status = XDptx_SendSbMsg(InstancePtr, &Msg); + if (Status != XST_SUCCESS) { + /* The AUX write transaction used to send the sideband message + * failed. */ + return Status; + } + + Status = XDptx_ReceiveSbMsg(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; + } + XDptx_GetDeviceInfoFromSbMsgLinkAddress(&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 XDptx 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 XDptx_SendSbMsgEnumPathResources(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u16 *AvailPbn, u16 *FullPbn) +{ + u32 Status; + XDptx_SidebandMsg Msg; + XDptx_SidebandReply SbMsgReply; + u8 Index; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + 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 = XDptx_Crc4CalculateHeader(&Msg.Header); + + /* Prepare the sideband message body. */ + Msg.Body.MsgData[0] = XDPTX_SBMSG_ENUM_PATH_RESOURCES; + Msg.Body.MsgData[1] = (RelativeAddress[Msg.Header.LinkCountTotal - 1] << + 4); + Msg.Body.MsgDataLength = Msg.Header.MsgBodyLength - 1; + Msg.Body.Crc = XDptx_Crc8CalculateBody(&Msg.Body); + + /* Submit the LINK_ADDRESS transaction message request. */ + Status = XDptx_SendSbMsg(InstancePtr, &Msg); + if (Status != XST_SUCCESS) { + /* The AUX write transaction used to send the sideband message + * failed. */ + return Status; + } + Status = XDptx_ReceiveSbMsg(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 XDptx 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 XDptx_SendSbMsgAllocatePayload(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, u8 VcId, u16 Pbn) +{ + u32 Status; + XDptx_SidebandMsg Msg; + XDptx_SidebandReply SbMsgReply; + u8 Index; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + 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 = XDptx_Crc4CalculateHeader(&Msg.Header); + + /* Prepare the sideband message body. */ + Msg.Body.MsgData[0] = XDPTX_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 = XDptx_Crc8CalculateBody(&Msg.Body); + + /* Submit the ALLOCATE_PAYLOAD transaction message request. */ + Status = XDptx_SendSbMsg(InstancePtr, &Msg); + if (Status != XST_SUCCESS) { + /* The AUX write transaction used to send the sideband message + * failed. */ + return Status; + } + Status = XDptx_ReceiveSbMsg(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 XDptx 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 XDptx_SendSbMsgClearPayloadIdTable(XDptx *InstancePtr) +{ + u32 Status; + XDptx_SidebandMsg Msg; + XDptx_SidebandReply SbMsgReply; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* 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 = XDptx_Crc4CalculateHeader(&Msg.Header); + + /* Prepare the sideband message body. */ + Msg.Body.MsgData[0] = XDPTX_SBMSG_CLEAR_PAYLOAD_ID_TABLE; + Msg.Body.MsgDataLength = Msg.Header.MsgBodyLength - 1; + Msg.Body.Crc = XDptx_Crc8CalculateBody(&Msg.Body); + + /* Submit the CLEAR_PAYLOAD_ID_TABLE transaction message request. */ + Status = XDptx_SendSbMsg(InstancePtr, &Msg); + if (Status != XST_SUCCESS) { + /* The AUX write transaction used to send the sideband message + * failed. */ + return Status; + } + Status = XDptx_ReceiveSbMsg(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 XDptx 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 XDptx_WriteGuid(XDptx *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(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; + } + + if (LinkCountTotal == 1) { + XDptx_AuxWrite(InstancePtr, XDPTX_DPCD_GUID, 16, AuxData); + } + else { + XDptx_SendSbMsgRemoteDpcdWrite(InstancePtr, LinkCountTotal, + RelativeAddress, XDPTX_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 XDptx 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 XDptx_GetGuid(XDptx *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(LinkCountTotal > 0); + Xil_AssertVoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertVoid(Guid != NULL); + + if (LinkCountTotal == 1) { + XDptx_AuxRead(InstancePtr, XDPTX_DPCD_GUID, 16, Data); + } + else { + XDptx_SendSbMsgRemoteDpcdRead(InstancePtr, LinkCountTotal, + RelativeAddress, XDPTX_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 retrieves a remote RX device's Extended Display Identification + * Data (EDID). + * + * @param InstancePtr is a pointer to the XDptx 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 XDptx_GetRemoteEdid(XDptx *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(LinkCountTotal > 0); + Xil_AssertNonvoid((RelativeAddress != NULL) || (LinkCountTotal == 1)); + Xil_AssertNonvoid(Edid != NULL); + + if (LinkCountTotal == 1) { + Status = XDptx_GetEdid(InstancePtr, Edid); + } + else { + Status = XDptx_SendSbMsgRemoteIicRead(InstancePtr, + LinkCountTotal, RelativeAddress, + XDPTX_EDID_ADDR, XDPTX_EDID_SIZE, Edid); + } + + return Status; +} + +/******************************************************************************/ +/** + * 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 XDptx 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 XDptx_IssueGuid(XDptx *InstancePtr, u8 LinkCountTotal, + u8 *RelativeAddress, XDptx_Topology *Topology, u32 *Guid) +{ + XDptx_GetGuid(InstancePtr, LinkCountTotal, RelativeAddress, Guid); + if ((Guid[0] == 0) && (Guid[1] == 0) && (Guid[2] == 0) && + (Guid[3] == 0)) { + XDptx_WriteGuid(InstancePtr, LinkCountTotal, RelativeAddress, + GuidTable[Topology->NodeTotal]); + + XDptx_GetGuid(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 XDptx 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 XDptx_AddBranchToList(XDptx *InstancePtr, + XDptx_SbMsgLinkAddressReplyDeviceInfo *DeviceInfo, + u8 LinkCountTotal, u8 *RelativeAddress) +{ + u8 Index; + XDptx_TopologyNode *TopologyNode; + + /* Add this node to the topology's node list. */ + TopologyNode = &InstancePtr->Topology.NodeTable[ + InstancePtr->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->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 XDptx 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 XDptx_AddSinkToList(XDptx *InstancePtr, + XDptx_SbMsgLinkAddressReplyPortDetail *SinkDevice, + u8 LinkCountTotal, u8 *RelativeAddress) +{ + u8 Index; + XDptx_Topology *Topology = &InstancePtr->Topology; + XDptx_TopologyNode *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 XDptx_GetDeviceInfoFromSbMsgLinkAddress(XDptx_SidebandReply + *SbReply, XDptx_SbMsgLinkAddressReplyDeviceInfo *FormatReply) +{ + u8 ReplyIndex = 0; + u8 Index, Index2; + XDptx_SbMsgLinkAddressReplyPortDetail *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 XDptx 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 XDptx_GetFirstAvailableTs(XDptx *InstancePtr, u8 *FirstTs) +{ + u32 Status; + u8 Index; + u8 AuxData[64]; + + Status = XDptx_AuxRead(InstancePtr, XDPTX_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 XDptx 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 XDptx_SendActTrigger(XDptx *InstancePtr) +{ + u32 Status; + u8 AuxData; + u8 TimeoutCount = 0; + + XDptx_WaitUs(InstancePtr, 10000); + + XDptx_WriteReg(InstancePtr->Config.BaseAddr, XDPTX_TX_MST_CONFIG, 0x3); + + do { + Status = XDptx_AuxRead(InstancePtr, + XDPTX_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 > XDPTX_VCP_TABLE_MAX_TIMEOUT_COUNT) { + return XST_ERROR_COUNT_MAX; + } + + TimeoutCount++; + XDptx_WaitUs(InstancePtr, 1000); + } while ((AuxData & 0x02) != 0x02); + + 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 XDptx 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 XDptx_SendSbMsg(XDptx *InstancePtr, XDptx_SidebandMsg *Msg) +{ + u32 Status; + u8 AuxData[10+63]; + XDptx_SidebandMsgHeader *Header = &Msg->Header; + XDptx_SidebandMsgBody *Body = &Msg->Body; + u8 Index; + + XDptx_WaitUs(InstancePtr, InstancePtr->SbMsgDelayUs); + + /* First, clear the DOWN_REP_MSG_RDY in case the RX device is in a weird + * state. */ + AuxData[0] = 0x10; + Status = XDptx_AuxWrite(InstancePtr, + XDPTX_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 = XDptx_AuxWrite(InstancePtr, XDPTX_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 XDptx 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 XDptx_ReceiveSbMsg(XDptx *InstancePtr, XDptx_SidebandReply *SbReply) +{ + u32 Status; + u8 Index = 0; + u8 AuxData[80]; + XDptx_SidebandMsg Msg; + + SbReply->Length = 0; + + do { + XDptx_WaitUs(InstancePtr, InstancePtr->SbMsgDelayUs); + + /* Wait for a reply. */ + Status = XDptx_WaitSbReply(InstancePtr); + if (Status != XST_SUCCESS) { + return Status; + } + + /* Receive reply. */ + Status = XDptx_AuxRead(InstancePtr, XDPTX_DPCD_DOWN_REP, 80, + AuxData); + if (Status != XST_SUCCESS) { + /* The AUX read transaction failed. */ + return Status; + } + + /* Convert the reply transaction into XDptx_SidebandReply + * format. */ + Status = XDptx_Transaction2MsgFormat(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 = XDptx_AuxWrite(InstancePtr, + XDPTX_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 XDptx 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 XDptx_WaitSbReply(XDptx *InstancePtr) +{ + u32 Status; + u8 AuxData; + u16 TimeoutCount = 0; + + do { + Status = XDptx_AuxRead(InstancePtr, + XDPTX_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 > XDPTX_MAX_SBMSG_REPLY_TIMEOUT_COUNT) { + return XST_ERROR_COUNT_MAX; + } + + TimeoutCount++; + XDptx_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 XDptx_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 XDptx_Transaction2MsgFormat(u8 *Transaction, XDptx_SidebandMsg *Msg) +{ + XDptx_SidebandMsgHeader *Header = &Msg->Header; + XDptx_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 = XDptx_Crc4CalculateHeader(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 = XDptx_Crc8CalculateBody(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 XDptx 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 XDptx_CrcCalculate function. + * +*******************************************************************************/ +static u8 XDptx_Crc4CalculateHeader(XDptx_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 XDptx_CrcCalculate(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 XDptx 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 XDptx_Crc8CalculateBody(XDptx_SidebandMsgBody *Body) +{ + return XDptx_CrcCalculate(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 XDptx_CrcCalculate(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; +} diff --git a/XilinxProcessorIPLib/drivers/dptx/src/xdptx_selftest.c b/XilinxProcessorIPLib/drivers/dptx/src/xdptx_selftest.c new file mode 100644 index 00000000..61a1bcf3 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/src/xdptx_selftest.c @@ -0,0 +1,212 @@ +/******************************************************************************* + * + * Copyright (C) 2014 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xdptx_selftest.c + * + * This file contains a diagnostic self-test function for the XDptx driver. It + * will check many of the DisplayPort TX'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  05/17/14 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdptx.h" +#include "xstatus.h" + +/**************************** Variable Definitions ****************************/ + +/** + * This table contains the default values for the DisplayPort TX core's general + * usage registers. + */ +u32 ResetValues[53][2] = +{ + {XDPTX_LINK_BW_SET, 0}, + {XDPTX_LANE_COUNT_SET, 0}, + {XDPTX_ENHANCED_FRAME_EN, 0}, + {XDPTX_TRAINING_PATTERN_SET, 0}, + {XDPTX_LINK_QUAL_PATTERN_SET, 0}, + {XDPTX_SCRAMBLING_DISABLE, 0}, + {XDPTX_DOWNSPREAD_CTRL, 0}, + {XDPTX_SOFT_RESET, 0}, + {XDPTX_ENABLE, 0}, + {XDPTX_ENABLE_MAIN_STREAM, 0}, + {XDPTX_ENABLE_SEC_STREAM, 0}, + {XDPTX_FORCE_SCRAMBLER_RESET, 0}, + {XDPTX_TX_MST_CONFIG, 0}, + {XDPTX_AUX_CMD, 0}, + {XDPTX_AUX_WRITE_FIFO, 0}, + {XDPTX_AUX_ADDRESS, 0}, + {XDPTX_AUX_CLK_DIVIDER, 0}, + {XDPTX_TX_USER_FIFO_OVERFLOW, 0}, + {XDPTX_AUX_REPLY_DATA, 0}, + {XDPTX_AUX_REPLY_CODE, 0}, + {XDPTX_AUX_REPLY_COUNT, 0}, + {XDPTX_INTERRUPT_MASK, 0x3F}, + {XDPTX_REPLY_DATA_COUNT, 0}, + {XDPTX_REPLY_STATUS, 0x10}, + {XDPTX_STREAM0, 0}, + {XDPTX_STREAM1, 0}, + {XDPTX_STREAM2, 0}, + {XDPTX_STREAM3, 0}, + {XDPTX_PHY_CONFIG, 0x03}, + {XDPTX_PHY_VOLTAGE_DIFF_LANE_0, 0}, + {XDPTX_PHY_VOLTAGE_DIFF_LANE_1, 0}, + {XDPTX_PHY_VOLTAGE_DIFF_LANE_2, 0}, + {XDPTX_PHY_VOLTAGE_DIFF_LANE_3, 0}, + {XDPTX_PHY_TRANSMIT_PRBS7, 0}, + {XDPTX_PHY_CLOCK_SELECT, 0}, + {XDPTX_TX_PHY_POWER_DOWN, 0}, + {XDPTX_PHY_PRECURSOR_LANE_0, 0}, + {XDPTX_PHY_PRECURSOR_LANE_1, 0}, + {XDPTX_PHY_PRECURSOR_LANE_2, 0}, + {XDPTX_PHY_PRECURSOR_LANE_3, 0}, + {XDPTX_PHY_POSTCURSOR_LANE_0, 0}, + {XDPTX_PHY_POSTCURSOR_LANE_1, 0}, + {XDPTX_PHY_POSTCURSOR_LANE_2, 0}, + {XDPTX_PHY_POSTCURSOR_LANE_3, 0}, + {XDPTX_GT_DRP_COMMAND, 0}, + {XDPTX_GT_DRP_READ_DATA, 0}, + {XDPTX_GT_DRP_CHANNEL_STATUS, 0}, + {XDPTX_TX_AUDIO_CONTROL, 0}, + {XDPTX_TX_AUDIO_CHANNELS, 0}, + {XDPTX_TX_AUDIO_INFO_DATA, 0}, + {XDPTX_TX_AUDIO_MAUD, 0}, + {XDPTX_TX_AUDIO_NAUD, 0}, + {XDPTX_TX_AUDIO_EXT_DATA, 0} +}; + +/** + * This table contains the default values for the DisplayPort TX core's main + * stream attribute (MSA) registers. + */ +u32 ResetValuesMsa[20][2] = +{ + {XDPTX_MAIN_STREAM_HTOTAL, 0}, + {XDPTX_MAIN_STREAM_VTOTAL, 0}, + {XDPTX_MAIN_STREAM_POLARITY, 0}, + {XDPTX_MAIN_STREAM_HSWIDTH, 0}, + {XDPTX_MAIN_STREAM_VSWIDTH, 0}, + {XDPTX_MAIN_STREAM_HRES, 0}, + {XDPTX_MAIN_STREAM_VRES, 0}, + {XDPTX_MAIN_STREAM_HSTART, 0}, + {XDPTX_MAIN_STREAM_VSTART, 0}, + {XDPTX_MAIN_STREAM_MISC0, 0}, + {XDPTX_MAIN_STREAM_MISC1, 0}, + {XDPTX_M_VID, 0}, + {XDPTX_TU_SIZE, 0}, + {XDPTX_N_VID, 0}, + {XDPTX_USER_PIXEL_WIDTH, 0}, + {XDPTX_USER_DATA_COUNT_PER_LANE, 0}, + {XDPTX_MAIN_STREAM_INTERLACED, 0}, + {XDPTX_MIN_BYTES_PER_TU, 0}, + {XDPTX_FRAC_BYTES_PER_TU, 0}, + {XDPTX_INIT_WAIT, 32} +}; + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function runs a self-test on the XDptx driver/device. The sanity test + * checks whether or not all tested registers hold their default reset values. + * + * @param InstancePtr is a pointer to the XDptx instance. + * + * @return + * - XST_SUCCESS if the self-test passed - all tested registers + * hold their default reset values. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XDptx_SelfTest(XDptx *InstancePtr) +{ + u8 Index; + u8 StreamIndex; + u32 StreamOffset; + u32 Val; + + /* Compare general usage registers with their default values. */ + for (Index = 0; Index < 53; Index++) { + Val = XDptx_ReadReg(InstancePtr->Config.BaseAddr, + ResetValues[Index][0]); + /* Fail if register does not hold default value. */ + if (Val != ResetValues[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 = XDPTX_STREAM1_MSA_START_OFFSET; + } + else if (StreamIndex == 2) { + StreamOffset = XDPTX_STREAM2_MSA_START_OFFSET; + } + else if (StreamIndex == 3) { + StreamOffset = XDPTX_STREAM3_MSA_START_OFFSET; + } + + for (Index = 0; Index < 20; Index++) { + Val = XDptx_ReadReg(InstancePtr->Config.BaseAddr, + StreamOffset + ResetValuesMsa[Index][0]); + /* Fail if register does not hold default value. */ + if (Val != ResetValuesMsa[Index][1]) { + return XST_FAILURE; + } + } + } + + /* All tested registers hold their default reset values. */ + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/dptx/src/xdptx_sinit.c b/XilinxProcessorIPLib/drivers/dptx/src/xdptx_sinit.c new file mode 100644 index 00000000..55d15208 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/src/xdptx_sinit.c @@ -0,0 +1,93 @@ +/******************************************************************************* + * + * Copyright (C) 2014 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xdptx_sinit.c + * + * This file contains static initialization methods for the XDptx driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  05/17/14 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdptx.h" +#include "xparameters.h" + +/*************************** Variable Declarations ****************************/ + +/** + * A table of configuration structures containing the configuration information + * for each DisplayPort TX core in the system. + */ +extern XDptx_Config XDptx_ConfigTable[XPAR_XDPTX_NUM_INSTANCES]; + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function looks for the device configuration based on the unique device + * ID. The table XDptx_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. + * +*******************************************************************************/ +XDptx_Config *XDptx_LookupConfig(u16 DeviceId) +{ + XDptx_Config *CfgPtr; + u32 Index; + + for (Index = 0; Index < XPAR_XDPTX_NUM_INSTANCES; Index++) { + if (XDptx_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XDptx_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} diff --git a/XilinxProcessorIPLib/drivers/dptx/src/xdptx_spm.c b/XilinxProcessorIPLib/drivers/dptx/src/xdptx_spm.c new file mode 100644 index 00000000..696c5238 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/src/xdptx_spm.c @@ -0,0 +1,834 @@ +/******************************************************************************* + * + * Copyright (C) 2014 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xdptx_spm.c + * + * This file contains the stream policy maker functions for the XDptx driver. + * These functions set up the DisplayPort TX core's main stream attributes that + * determine how a video stream will be displayed. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  05/17/14 Initial release.
+ *       als  08/03/14 Initial MST addition.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xdptx.h" +#include "xdptx_hw.h" +#include "xstatus.h" + +/**************************** Function Prototypes *****************************/ + +static void XDptx_CalculateTs(XDptx *InstancePtr, u8 Stream, u8 BitsPerPixel); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function calculates the following Main Stream Attributes (MSA): + * - Transfer unit size + * - User pixel width + * - Horizontal start + * - Vertical start + * - Horizontal total clock + * - Vertical total clock + * - Misc0 + * - Misc1 + * - Data per lane + * - Average number of bytes per transfer unit + * - Number of initial wait cycles + * These values are derived from: + * - Bits per color + * - Horizontal resolution + * - Vertical resolution + * - Pixel clock (in KHz) + * - Horizontal sync polarity + * - Vertical sync polarity + * - Horizontal front porch + * - Horizontal sync pulse width + * - Horizontal back porch + * - Vertical front porch + * - Vertical sync pulse width + * - Vertical back porch + * + * @param InstancePtr is a pointer to the XDptx instance. + * @param Stream is the stream number for which to calculate the MSA + * values. + * + * @return None. + * + * @note The MsaConfig structure is modified with the new, calculated + * values. The main stream attributes that were used to derive the + * calculated values are untouched in the MsaConfig structure. + * +*******************************************************************************/ +void XDptx_CfgMsaRecalculate(XDptx *InstancePtr, u8 Stream) +{ + u32 VideoBw; + u8 BitsPerPixel; + XDptx_MainStreamAttributes *MsaConfig; + XDptx_LinkConfig *LinkConfig; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((Stream == XDPTX_STREAM_ID0) || + (Stream == XDPTX_STREAM_ID1) || (Stream == XDPTX_STREAM_ID2) || + (Stream == XDPTX_STREAM_ID3)); + + MsaConfig = &InstancePtr->MsaConfig[Stream]; + LinkConfig = &InstancePtr->LinkConfig; + + /* Verify the rest of the values used. */ + Xil_AssertVoid((LinkConfig->LinkRate == XDPTX_LINK_BW_SET_162GBPS) || + (LinkConfig->LinkRate == XDPTX_LINK_BW_SET_270GBPS) || + (LinkConfig->LinkRate == XDPTX_LINK_BW_SET_540GBPS)); + Xil_AssertVoid((LinkConfig->LaneCount == XDPTX_LANE_COUNT_SET_1) || + (LinkConfig->LaneCount == XDPTX_LANE_COUNT_SET_2) || + (LinkConfig->LaneCount == XDPTX_LANE_COUNT_SET_4)); + Xil_AssertVoid((MsaConfig->SynchronousClockMode == 0) || + (MsaConfig->SynchronousClockMode == 1)); + Xil_AssertVoid((MsaConfig->DynamicRange == 0) || + (MsaConfig->DynamicRange == 1)); + Xil_AssertVoid((MsaConfig->YCbCrColorimetry == 0) || + (MsaConfig->YCbCrColorimetry == 1)); + Xil_AssertVoid((MsaConfig->BitsPerColor == 6) || + (MsaConfig->BitsPerColor == 8) || + (MsaConfig->BitsPerColor == 10) || + (MsaConfig->BitsPerColor == 12) || + (MsaConfig->BitsPerColor == 16)); + + /* Set the user pixel width to handle clocks that exceed the + * capabilities of the DisplayPort TX core. */ + if (MsaConfig->OverrideUserPixelWidth == 0) { + if ((MsaConfig->Dmt.PixelClkKhz > 300000) && + (LinkConfig->LaneCount == XDPTX_LANE_COUNT_SET_4)) { + MsaConfig->UserPixelWidth = 4; + } + else if ((MsaConfig->Dmt.PixelClkKhz > 75000) && + (LinkConfig->LaneCount != XDPTX_LANE_COUNT_SET_1)) { + MsaConfig->UserPixelWidth = 2; + } + else { + MsaConfig->UserPixelWidth = 1; + } + } + + /* Compute the rest of the MSA values. */ + MsaConfig->NVid = 27 * 1000 * LinkConfig->LinkRate; + MsaConfig->HStart = MsaConfig->Dmt.HSyncPulseWidth + + MsaConfig->Dmt.HBackPorch; + MsaConfig->VStart = MsaConfig->Dmt.VSyncPulseWidth + + MsaConfig->Dmt.VBackPorch; + MsaConfig->HClkTotal = (MsaConfig->Dmt.HSyncPulseWidth + + MsaConfig->Dmt.HBackPorch + + MsaConfig->Dmt.HFrontPorch + + MsaConfig->Dmt.HResolution); + MsaConfig->VClkTotal = (MsaConfig->Dmt.VSyncPulseWidth + + MsaConfig->Dmt.VBackPorch + + MsaConfig->Dmt.VFrontPorch + + MsaConfig->Dmt.VResolution); + + /* Miscellaneous attributes. */ + if (MsaConfig->BitsPerColor == 6) { + MsaConfig->Misc0 = XDPTX_MAIN_STREAMX_MISC0_BDC_6BPC; + } + else if (MsaConfig->BitsPerColor == 8) { + MsaConfig->Misc0 = XDPTX_MAIN_STREAMX_MISC0_BDC_8BPC; + } + else if (MsaConfig->BitsPerColor == 10) { + MsaConfig->Misc0 = XDPTX_MAIN_STREAMX_MISC0_BDC_10BPC; + } + else if (MsaConfig->BitsPerColor == 12) { + MsaConfig->Misc0 = XDPTX_MAIN_STREAMX_MISC0_BDC_12BPC; + } + else if (MsaConfig->BitsPerColor == 16) { + MsaConfig->Misc0 = XDPTX_MAIN_STREAMX_MISC0_BDC_16BPC; + } + MsaConfig->Misc0 = (MsaConfig->Misc0 << + XDPTX_MAIN_STREAMX_MISC0_BDC_SHIFT) | + (MsaConfig->YCbCrColorimetry << + XDPTX_MAIN_STREAMX_MISC0_YCBCR_COLORIMETRY_SHIFT) | + (MsaConfig->DynamicRange << + XDPTX_MAIN_STREAMX_MISC0_DYNAMIC_RANGE_SHIFT) | + (MsaConfig->ComponentFormat << + XDPTX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_SHIFT) | + (MsaConfig->SynchronousClockMode); + MsaConfig->Misc1 = 0; + + /* Determine the number of bits per pixel for the specified color + * component format. */ + if (MsaConfig->ComponentFormat == + XDPTX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_YCBCR422) { + /* YCbCr422 color component format. */ + BitsPerPixel = MsaConfig->BitsPerColor * 2; + } + else { + /* RGB or YCbCr 4:4:4 color component format. */ + BitsPerPixel = MsaConfig->BitsPerColor * 3; + } + + + if (InstancePtr->MstEnable == 1) { + MsaConfig->DataPerLane = (MsaConfig->Dmt.HResolution * + MsaConfig->BitsPerColor * 3 / 16) - 4; + + /* Do time slot (and payload bandwidth number) calculations for + * MST. */ + XDptx_CalculateTs(InstancePtr, Stream, BitsPerPixel); + + MsaConfig->InitWait = 0; + } + else { + MsaConfig->DataPerLane = (MsaConfig->Dmt.HResolution * + MsaConfig->BitsPerColor * 3 / 16) - + LinkConfig->LaneCount; + + /* 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->Dmt.PixelClkKhz * BitsPerPixel) / 8; + MsaConfig->AvgBytesPerTU = (VideoBw * + MsaConfig->TransferUnitSize) / + (LinkConfig->LaneCount * + (MsaConfig->NVid / 1000)); + + /* 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. */ + MsaConfig->InitWait = (MsaConfig->TransferUnitSize - + (MsaConfig->AvgBytesPerTU / 1000)); + if ((MsaConfig->AvgBytesPerTU / 1000) > + MsaConfig->TransferUnitSize) { + MsaConfig->InitWait = 0; + } + else if (MsaConfig->InitWait > 10) { + MsaConfig->InitWait -= 10; + } + else { + MsaConfig->InitWait = 0; + } + } +} + + +/******************************************************************************/ +/** + * This function sets the Main Stream Attribute (MSA) values in the + * configuration structure to match one of the standard display mode timings + * from the XDptx_DmtModes[] standard Display Monitor Timing (DMT) table. The + * XDptx_VideoMode enumeration in xdptx.h lists the available video modes. + * + * @param InstancePtr is a pointer to the XDptx instance. + * @param Stream is the stream number for which the MSA values will be + * used for. + * @param VideoMode is one of the enumerated standard video modes that is + * used to determine the MSA values to be used. + * + * @return None. + * + * @note The InstancePtr->MsaConfig structure is modified to reflect the + * MSA values associated to the specified video mode. + * +*******************************************************************************/ +void XDptx_CfgMsaUseStandardVideoMode(XDptx *InstancePtr, u8 Stream, + XDptx_VideoMode VideoMode) +{ + XDptx_MainStreamAttributes *MsaConfig; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(VideoMode <= XDPTX_VM_LAST); + Xil_AssertVoid((Stream == XDPTX_STREAM_ID0) || + (Stream == XDPTX_STREAM_ID1) || (Stream == XDPTX_STREAM_ID2) || + (Stream == XDPTX_STREAM_ID3)); + + MsaConfig = &InstancePtr->MsaConfig[Stream]; + + /* Configure the MSA values from the display monitor DMT table. */ + MsaConfig->Dmt.HResolution = XDptx_DmtModes[VideoMode].HResolution; + MsaConfig->Dmt.VResolution = XDptx_DmtModes[VideoMode].VResolution; + MsaConfig->Dmt.PixelClkKhz = XDptx_DmtModes[VideoMode].PixelClkKhz; + MsaConfig->Dmt.HSyncPolarity = XDptx_DmtModes[VideoMode].HSyncPolarity; + MsaConfig->Dmt.VSyncPolarity = XDptx_DmtModes[VideoMode].VSyncPolarity; + MsaConfig->Dmt.HFrontPorch = XDptx_DmtModes[VideoMode].HFrontPorch; + MsaConfig->Dmt.HSyncPulseWidth = + XDptx_DmtModes[VideoMode].HSyncPulseWidth; + MsaConfig->Dmt.HBackPorch = XDptx_DmtModes[VideoMode].HBackPorch; + MsaConfig->Dmt.VFrontPorch = XDptx_DmtModes[VideoMode].VFrontPorch; + MsaConfig->Dmt.VSyncPulseWidth = + XDptx_DmtModes[VideoMode].VSyncPulseWidth; + MsaConfig->Dmt.VBackPorch = XDptx_DmtModes[VideoMode].VBackPorch; + + /* Calculate the rest of the MSA values. */ + XDptx_CfgMsaRecalculate(InstancePtr, Stream); +} + +/******************************************************************************/ +/** + * This function sets the main stream attribute values in the configuration + * structure to match the preferred timing of the sink monitor. This Preferred + * Timing Mode (PTM) information is stored in the sink's Extended Display + * Identification Data (EDID). + * + * @param InstancePtr is a pointer to the XDptx instance + * @param Stream is the stream number for which the MSA values will be + * used for. + * @param Edid is a pointer to the Edid to use for the specified stream. + * + * @return None. + * + * @note The InstancePtr->MsaConfig structure is modified to reflect the + * main stream attribute values associated to the preferred timing + * of the sink monitor. + * +*******************************************************************************/ +void XDptx_CfgMsaUseEdidPreferredTiming(XDptx *InstancePtr, u8 Stream, u8 *Edid) +{ + XDptx_MainStreamAttributes *MsaConfig; + u8 *Ptm; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((Stream == XDPTX_STREAM_ID0) || + (Stream == XDPTX_STREAM_ID1) || (Stream == XDPTX_STREAM_ID2) || + (Stream == XDPTX_STREAM_ID3)); + Xil_AssertVoid(Edid != NULL); + + MsaConfig = &InstancePtr->MsaConfig[Stream]; + Ptm = &Edid[XDPTX_EDID_PTM]; + + /* Configure the MSA values with the PTM information as + * specified by the preferred Detailed Timing Descriptor (DTD) of the + * monitor's EDID. + * Note, the PTM is only required for EDID versions 1.3 a newer. Earlier + * versions may not contain this information. */ + u16 HBlank = ((Ptm[XDPTX_EDID_DTD_HRES_HBLANK_U4] & + XDPTX_EDID_DTD_XRES_XBLANK_U4_XBLANK_MASK) << 8) | + Ptm[XDPTX_EDID_DTD_HBLANK_LSB]; + + u16 VBlank = ((Ptm[XDPTX_EDID_DTD_VRES_VBLANK_U4] & + XDPTX_EDID_DTD_XRES_XBLANK_U4_XBLANK_MASK) << 8) | + Ptm[XDPTX_EDID_DTD_VBLANK_LSB]; + + MsaConfig->Dmt.HResolution = + (((Ptm[XDPTX_EDID_DTD_HRES_HBLANK_U4] & + XDPTX_EDID_DTD_XRES_XBLANK_U4_XRES_MASK) >> + XDPTX_EDID_DTD_XRES_XBLANK_U4_XRES_SHIFT) << 8) | + Ptm[XDPTX_EDID_DTD_HRES_LSB]; + + MsaConfig->Dmt.VResolution = (((Ptm[XDPTX_EDID_DTD_VRES_VBLANK_U4] & + XDPTX_EDID_DTD_XRES_XBLANK_U4_XRES_MASK) >> + XDPTX_EDID_DTD_XRES_XBLANK_U4_XRES_SHIFT) << 8) | + Ptm[XDPTX_EDID_DTD_VRES_LSB]; + + MsaConfig->Dmt.PixelClkKhz = ((Ptm[XDPTX_EDID_DTD_PIXEL_CLK_KHZ_MSB] << + 8) | Ptm[XDPTX_EDID_DTD_PIXEL_CLK_KHZ_LSB]) * 10; + + MsaConfig->Dmt.HFrontPorch = (((Ptm[XDPTX_EDID_DTD_XFPORCH_XSPW_U2] & + XDPTX_EDID_DTD_XFPORCH_XSPW_U2_HFPORCH_MASK) >> + XDPTX_EDID_DTD_XFPORCH_XSPW_U2_HFPORCH_SHIFT) << 8) | + Ptm[XDPTX_EDID_DTD_HFPORCH_LSB]; + + MsaConfig->Dmt.HSyncPulseWidth = + (((Ptm[XDPTX_EDID_DTD_XFPORCH_XSPW_U2] & + XDPTX_EDID_DTD_XFPORCH_XSPW_U2_HSPW_MASK) >> + XDPTX_EDID_DTD_XFPORCH_XSPW_U2_HSPW_SHIFT) << 8) | + Ptm[XDPTX_EDID_DTD_HSPW_LSB]; + + MsaConfig->Dmt.VFrontPorch = (((Ptm[XDPTX_EDID_DTD_XFPORCH_XSPW_U2] & + XDPTX_EDID_DTD_XFPORCH_XSPW_U2_VFPORCH_MASK) >> + XDPTX_EDID_DTD_XFPORCH_XSPW_U2_VFPORCH_SHIFT) << 8) | + ((Ptm[XDPTX_EDID_DTD_VFPORCH_VSPW_L4] & + XDPTX_EDID_DTD_VFPORCH_VSPW_L4_VFPORCH_MASK) >> + XDPTX_EDID_DTD_VFPORCH_VSPW_L4_VFPORCH_SHIFT); + + MsaConfig->Dmt.VSyncPulseWidth = + ((Ptm[XDPTX_EDID_DTD_XFPORCH_XSPW_U2] & + XDPTX_EDID_DTD_XFPORCH_XSPW_U2_VSPW_MASK) << 8) | + (Ptm[XDPTX_EDID_DTD_VFPORCH_VSPW_L4] & + XDPTX_EDID_DTD_VFPORCH_VSPW_L4_VSPW_MASK); + + MsaConfig->Dmt.HBackPorch = HBlank - (MsaConfig->Dmt.HFrontPorch + + MsaConfig->Dmt.HSyncPulseWidth); + + MsaConfig->Dmt.VBackPorch = VBlank - (MsaConfig->Dmt.VFrontPorch + + MsaConfig->Dmt.VSyncPulseWidth); + + /* Calculate the rest of the MSA values. */ + XDptx_CfgMsaRecalculate(InstancePtr, Stream); +} + +/******************************************************************************/ +/** + * This function takes a the main stream attributes from MsaConfigCustom and + * copies them into InstancePtr->MsaConfig. If desired, given a base set of + * attributes, the rest of the attributes may be derived. The minimal required + * main stream attributes (MSA) that must be contained in the MsaConfigCustom + * structure are: + * - Pixel clock (in KHz) + * - Horizontal sync polarity + * - Vertical sync polarity + * - Horizontal sync pulse width + * - Vertical sync pulse width + * - Horizontal resolution + * - Vertical resolution + * - Vertical back porch + * - Vertical front porch + * - Horizontal back porch + * - Horizontal front porch + * + * @param InstancePtr is a pointer to the XDptx instance. + * @param Stream is the stream number for which the MSA values will be + * used for. + * @param MsaConfigCustom is the structure that will be used to copy the + * main stream attributes from (into InstancePtr->MsaConfig). + * @param Recalculate is a boolean enable that determines whether or not + * the main stream attributes should be recalculated. + * + * @return None. + * + * @note The InstancePtr->MsaConfig structure is modified with the new + * values. + * +*******************************************************************************/ +void XDptx_CfgMsaUseCustom(XDptx *InstancePtr, u8 Stream, + XDptx_MainStreamAttributes *MsaConfigCustom, u8 Recalculate) +{ + XDptx_MainStreamAttributes *MsaConfig; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((Stream == XDPTX_STREAM_ID0) || + (Stream == XDPTX_STREAM_ID1) || (Stream == XDPTX_STREAM_ID2) || + (Stream == XDPTX_STREAM_ID3)); + Xil_AssertVoid(MsaConfigCustom != NULL); + + MsaConfig = &InstancePtr->MsaConfig[Stream]; + + /* Copy the MSA values from the user configuration structure. */ + MsaConfig->Dmt.HResolution = MsaConfigCustom->Dmt.HResolution; + MsaConfig->Dmt.VResolution = MsaConfigCustom->Dmt.VResolution; + MsaConfig->Dmt.PixelClkKhz = MsaConfigCustom->Dmt.PixelClkKhz; + MsaConfig->Dmt.HSyncPolarity = MsaConfigCustom->Dmt.HSyncPolarity; + MsaConfig->Dmt.VSyncPolarity = MsaConfigCustom->Dmt.VSyncPolarity; + MsaConfig->Dmt.HFrontPorch = MsaConfigCustom->Dmt.HFrontPorch; + MsaConfig->Dmt.HSyncPulseWidth = MsaConfigCustom->Dmt.HSyncPulseWidth; + MsaConfig->Dmt.HBackPorch = MsaConfigCustom->Dmt.HBackPorch; + MsaConfig->Dmt.VFrontPorch = MsaConfigCustom->Dmt.VFrontPorch; + MsaConfig->Dmt.VSyncPulseWidth = MsaConfigCustom->Dmt.VSyncPulseWidth; + MsaConfig->Dmt.VBackPorch = MsaConfigCustom->Dmt.VBackPorch; + + if (Recalculate) { + /* Calculate the rest of the MSA values. */ + XDptx_CfgMsaRecalculate(InstancePtr, Stream); + } + else { + /* Use the custom values for the rest. */ + MsaConfig->TransferUnitSize = MsaConfigCustom->TransferUnitSize; + MsaConfig->UserPixelWidth = MsaConfigCustom->UserPixelWidth; + MsaConfig->NVid = MsaConfigCustom->NVid; + MsaConfig->HStart = MsaConfigCustom->HStart; + MsaConfig->VStart = MsaConfigCustom->VStart; + MsaConfig->HClkTotal = MsaConfigCustom->HClkTotal; + MsaConfig->VClkTotal = MsaConfigCustom->VClkTotal; + MsaConfig->Misc0 = MsaConfigCustom->Misc0; + MsaConfig->Misc1 = MsaConfigCustom->Misc1; + MsaConfig->DataPerLane = MsaConfigCustom->DataPerLane; + MsaConfig->AvgBytesPerTU = MsaConfigCustom->AvgBytesPerTU; + MsaConfig->InitWait = MsaConfigCustom->InitWait; + } +} + +/******************************************************************************/ +/** + * This function sets the bits per color value of the video stream. + * + * @param InstancePtr is a pointer to the XDptx instance + * @param Stream is the stream number for which to set the color depth. + * @param BitsPerColor is the new number of bits per color to use. + * + * @return None. + * + * @note The InstancePtr->MsaConfig structure is modified to reflect the + * new main stream attributes associated with a new bits per color + * value. + * +*******************************************************************************/ +void XDptx_CfgMsaSetBpc(XDptx *InstancePtr, u8 Stream, u8 BitsPerColor) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((Stream == XDPTX_STREAM_ID0) || + (Stream == XDPTX_STREAM_ID1) || (Stream == XDPTX_STREAM_ID2) || + (Stream == XDPTX_STREAM_ID3)); + Xil_AssertVoid((BitsPerColor == 6) || (BitsPerColor == 8) || + (BitsPerColor == 10) || (BitsPerColor == 12) || + (BitsPerColor == 16)); + + InstancePtr->MsaConfig[Stream].BitsPerColor = BitsPerColor; + + /* Calculate the rest of the MSA values. */ + XDptx_CfgMsaRecalculate(InstancePtr, Stream); +} + +/******************************************************************************/ +/** + * This function enables or disables synchronous clock mode for a video stream. + * + * @param InstancePtr is a pointer to the XDptx instance + * @param Stream is the stream number for which to enable or disable + * synchronous clock mode. + * @param Enable if set to 1, will enable synchronous clock mode. + * Otherwise, if set to 0, synchronous clock mode will be disabled. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDptx_CfgMsaEnSynchClkMode(XDptx *InstancePtr, u8 Stream, u8 Enable) +{ + XDptx_MainStreamAttributes *MsaConfig; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((Stream == XDPTX_STREAM_ID0) || + (Stream == XDPTX_STREAM_ID1) || (Stream == XDPTX_STREAM_ID2) || + (Stream == XDPTX_STREAM_ID3)); + Xil_AssertVoid((Enable == 0) || (Enable == 1)); + + MsaConfig = &InstancePtr->MsaConfig[Stream]; + + MsaConfig->SynchronousClockMode = Enable; + + if (Enable == 1) { + MsaConfig->Misc0 |= (1 << + XDPTX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_SHIFT); + } + else { + MsaConfig->Misc0 &= ~(1 << + XDPTX_MAIN_STREAMX_MISC0_COMPONENT_FORMAT_SHIFT); + } +} + +/******************************************************************************/ +/** + * This function clears the main stream attributes registers of the DisplayPort + * TX core and sets them to the values specified in the main stream attributes + * configuration structure. + * + * @param InstancePtr is a pointer to the XDptx instance + * @param Stream is the stream number for which to set the MSA values for. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDptx_SetVideoMode(XDptx *InstancePtr, u8 Stream) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((Stream == XDPTX_STREAM_ID0) || + (Stream == XDPTX_STREAM_ID1) || (Stream == XDPTX_STREAM_ID2) || + (Stream == XDPTX_STREAM_ID3)); + + XDptx_ClearMsaValues(InstancePtr, Stream); + XDptx_SetMsaValues(InstancePtr, Stream); +} + +/******************************************************************************/ +/** + * This function clears the main stream attributes registers of the DisplayPort + * TX core. + * + * @param InstancePtr is a pointer to the XDptx instance. + * @param Stream is the stream number for which to clear the MSA values. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDptx_ClearMsaValues(XDptx *InstancePtr, u8 Stream) +{ + XDptx_Config *Config; + u32 StreamOffset[4] = {0, XDPTX_STREAM1_MSA_START_OFFSET, + XDPTX_STREAM2_MSA_START_OFFSET, XDPTX_STREAM3_MSA_START_OFFSET}; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((Stream == XDPTX_STREAM_ID0) || + (Stream == XDPTX_STREAM_ID1) || (Stream == XDPTX_STREAM_ID2) || + (Stream == XDPTX_STREAM_ID3)); + + Config = &InstancePtr->Config; + + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_HTOTAL + + StreamOffset[Stream], 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_VTOTAL + + StreamOffset[Stream], 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_POLARITY + + StreamOffset[Stream], 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_HSWIDTH + + StreamOffset[Stream], 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_VSWIDTH + + StreamOffset[Stream], 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_HRES + + StreamOffset[Stream], 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_VRES + + StreamOffset[Stream], 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_HSTART + + StreamOffset[Stream], 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_VSTART + + StreamOffset[Stream], 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_MISC0 + + StreamOffset[Stream], 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_MISC1 + + StreamOffset[Stream], 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_USER_PIXEL_WIDTH + + StreamOffset[Stream], 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_USER_DATA_COUNT_PER_LANE + + StreamOffset[Stream], 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_M_VID + + StreamOffset[Stream], 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_N_VID + + StreamOffset[Stream], 0); + + XDptx_WriteReg(Config->BaseAddr, XDPTX_STREAM0 + (Stream) * 4, 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_TU_SIZE + + StreamOffset[Stream], 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MIN_BYTES_PER_TU + + StreamOffset[Stream], 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_FRAC_BYTES_PER_TU + + StreamOffset[Stream], 0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_INIT_WAIT + + StreamOffset[Stream], 0); +} + +/******************************************************************************/ +/** + * This function sets the main stream attributes registers of the DisplayPort TX + * core with the values specified in the main stream attributes configuration + * structure. + * + * @param InstancePtr is a pointer to the XDptx instance. + * @param Stream is the stream number for which to set the MSA values for. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XDptx_SetMsaValues(XDptx *InstancePtr, u8 Stream) +{ + XDptx_Config *Config; + XDptx_MainStreamAttributes *MsaConfig; + u32 StreamOffset[4] = {0, XDPTX_STREAM1_MSA_START_OFFSET, + XDPTX_STREAM2_MSA_START_OFFSET, XDPTX_STREAM3_MSA_START_OFFSET}; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid((Stream == XDPTX_STREAM_ID0) || + (Stream == XDPTX_STREAM_ID1) || (Stream == XDPTX_STREAM_ID2) || + (Stream == XDPTX_STREAM_ID3)); + + Config = &InstancePtr->Config; + MsaConfig = &InstancePtr->MsaConfig[Stream]; + + /* Set the main stream attributes to the associated DisplayPort TX core + * registers. */ + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_HTOTAL + + StreamOffset[Stream], MsaConfig->HClkTotal); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_VTOTAL + + StreamOffset[Stream], MsaConfig->VClkTotal); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_POLARITY + + StreamOffset[Stream], MsaConfig->Dmt.HSyncPolarity | + (MsaConfig->Dmt.VSyncPolarity << + XDPTX_MAIN_STREAMX_POLARITY_VSYNC_POL_SHIFT)); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_HSWIDTH + + StreamOffset[Stream], MsaConfig->Dmt.HSyncPulseWidth); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_VSWIDTH + + StreamOffset[Stream], MsaConfig->Dmt.VSyncPulseWidth); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_HRES + + StreamOffset[Stream], MsaConfig->Dmt.HResolution); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_VRES + + StreamOffset[Stream], MsaConfig->Dmt.VResolution); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_HSTART + + StreamOffset[Stream], MsaConfig->HStart); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_VSTART + + StreamOffset[Stream], MsaConfig->VStart); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_MISC0 + + StreamOffset[Stream], MsaConfig->Misc0); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MAIN_STREAM_MISC1 + + StreamOffset[Stream], MsaConfig->Misc1); + XDptx_WriteReg(Config->BaseAddr, XDPTX_M_VID + + StreamOffset[Stream], MsaConfig->Dmt.PixelClkKhz); + XDptx_WriteReg(Config->BaseAddr, XDPTX_N_VID + + StreamOffset[Stream], MsaConfig->NVid); + XDptx_WriteReg(Config->BaseAddr, XDPTX_USER_PIXEL_WIDTH + + StreamOffset[Stream], MsaConfig->UserPixelWidth); + XDptx_WriteReg(Config->BaseAddr, XDPTX_USER_DATA_COUNT_PER_LANE + + StreamOffset[Stream], MsaConfig->DataPerLane); + + /* Set the transfer unit values to the associated DisplayPort TX core + * registers. */ + if (InstancePtr->MstEnable == 1) { + XDptx_WriteReg(Config->BaseAddr, + XDPTX_STREAM0 + (Stream) * 4, + ((MsaConfig->AvgBytesPerTU / 1000) << 16) | + (MsaConfig->AvgBytesPerTU % 1000)); + } + XDptx_WriteReg(Config->BaseAddr, XDPTX_TU_SIZE + + StreamOffset[Stream], MsaConfig->TransferUnitSize); + XDptx_WriteReg(Config->BaseAddr, XDPTX_MIN_BYTES_PER_TU + + StreamOffset[Stream], MsaConfig->AvgBytesPerTU / 1000); + XDptx_WriteReg(Config->BaseAddr, XDPTX_FRAC_BYTES_PER_TU + + StreamOffset[Stream], MsaConfig->AvgBytesPerTU % 1000); + XDptx_WriteReg(Config->BaseAddr, XDPTX_INIT_WAIT + + StreamOffset[Stream], MsaConfig->InitWait); +} + +/******************************************************************************/ +/** + * When the driver is in multi-stream transport (MST) mode, this function will + * make the necessary calculations to describe a stream in MST mode. The key + * values are the payload bandwidth number (PBN), the number of timeslots + * required for allocating the bandwidth, and the average bytes per transfer + * unit (both the integer and the fractional part). + * + * @param InstancePtr is a pointer to the XDptx instance. + * @param Stream is the stream number to make the calculations for. + * @param BitsPerPixel is the number of bits that is used to store one + * pixel. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +static void XDptx_CalculateTs(XDptx *InstancePtr, u8 Stream, u8 BitsPerPixel) +{ + XDptx_MainStreamAttributes *MsaConfig = + &InstancePtr->MsaConfig[Stream]; + XDptx_LinkConfig *LinkConfig = &InstancePtr->LinkConfig; + double PeakPixelBw; + u32 LinkBw; + double Average_StreamSymbolTimeSlotsPerMTP; + double Target_Average_StreamSymbolTimeSlotsPerMTP; + double MaximumTarget_Average_StreamSymbolTimeSlotsPerMTP; + u32 TsInt; + u32 TsFrac; + + PeakPixelBw = ((double)MsaConfig->Dmt.PixelClkKhz / 1000) * + ((double)BitsPerPixel / 8); + LinkBw = (LinkConfig->LaneCount * LinkConfig->LinkRate * 27); + + /* Calculate the payload bandiwdth number (PBN). */ + InstancePtr->MstStreamConfig[Stream].MstPbn = + 1.006 * PeakPixelBw * ((double)64 / 54); + /* Ceil - round up if required, avoiding overhead of math.h. */ + if ((double)(1.006 * PeakPixelBw * ((double)64 / 54)) > + ((double)InstancePtr->MstStreamConfig[Stream].MstPbn)) { + InstancePtr->MstStreamConfig[Stream].MstPbn++; + } + + /* Calculate the average stream symbol time slots per MTP. */ + Average_StreamSymbolTimeSlotsPerMTP = (64.0 * PeakPixelBw / LinkBw); + MaximumTarget_Average_StreamSymbolTimeSlotsPerMTP = (54.0 * + ((double)InstancePtr->MstStreamConfig[Stream].MstPbn / + LinkBw)); + + /* The target value to be found needs to follow the condition: + * Average_StreamSymbolTimeSlotsPerMTP <= + * Target_Average_StreamSymbolTimeSlotsPerMTP + * >= MaximumTarget_Average_StreamSymbolTimeSlotsPerMTP + * Obtain the greatest target value that satisfies the above condition + * and still a multiple of 1/TsFrac_Denominator. + * Note: TsFrac_Denominator = 8. */ + /* Round down. */ + Target_Average_StreamSymbolTimeSlotsPerMTP = + (u32)Average_StreamSymbolTimeSlotsPerMTP; + /* Find the greatest multiple that is less than the maximum. */ + Target_Average_StreamSymbolTimeSlotsPerMTP += ((1.0 / 8.0) * (u32)(8.0 * + (MaximumTarget_Average_StreamSymbolTimeSlotsPerMTP - + Target_Average_StreamSymbolTimeSlotsPerMTP))); + + /* Determine the integer and the fractional part of the number of time + * slots that will be allocated for the stream. */ + TsInt = Target_Average_StreamSymbolTimeSlotsPerMTP; + TsFrac = (((double)Target_Average_StreamSymbolTimeSlotsPerMTP * 1000) - + (TsInt * 1000)); + + /* Store TsInt and TsFrac in AvgBytesPerTU. */ + MsaConfig->AvgBytesPerTU = TsInt * 1000 + TsFrac; + + /* Set the number of time slots to allocate for this stream. */ + MsaConfig->TransferUnitSize = TsInt; + if (TsFrac != 0) { + /* Round up. */ + MsaConfig->TransferUnitSize++; + } + if ((InstancePtr->Config.PayloadDataWidth == 4) && + (MsaConfig->TransferUnitSize % 4) != 0) { + /* Set to a multiple of 4 boundary. */ + MsaConfig->TransferUnitSize += (4 - + (MsaConfig->TransferUnitSize % 4)); + } + else if ((MsaConfig->TransferUnitSize % 2) != 0) { + /* Set to an even boundary. */ + MsaConfig->TransferUnitSize++; + } + + /* Determine the PBN for the stream. */ + InstancePtr->MstStreamConfig[Stream].MstPbn = + MsaConfig->TransferUnitSize * + (LinkConfig->LaneCount * LinkConfig->LinkRate / 2); +} diff --git a/XilinxProcessorIPLib/drivers/dptx/src/xdptx_vidmodetable.c b/XilinxProcessorIPLib/drivers/dptx/src/xdptx_vidmodetable.c new file mode 100644 index 00000000..581a9219 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/dptx/src/xdptx_vidmodetable.c @@ -0,0 +1,250 @@ +/******************************************************************************* + * + * Copyright (C) 2014 Xilinx, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * Use of the Software is limited solely to applications: + * (a) running on a Xilinx device, or + * (b) that interact with a Xilinx device through a bus or interconnect. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the Xilinx shall not be used + * in advertising or otherwise to promote the sale, use or other dealings in + * this Software without prior written authorization from Xilinx. + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xdptx_vidmodetable.c + * + * Contains display monitor timing (DMT) modes for various standard resolutions. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   als  05/17/14 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xil_types.h" +#include "xdptx.h" + +/**************************** Variable Definitions ****************************/ + +/** + * This table contains the main stream attributes for various standard + * resolutions. Each entry is of the format: + * 1) XDPTX_VM_x__P(_RB = Reduced Blanking) + * 2) Display Monitor Timing (DMT) ID + * 3) Horizontal resolution (pixels) + * 4) Vertical resolution (lines) + * 5) Pixel clock (KHz) + * 6) Interlaced (0=non-interlaced|1=interlaced) + * 7) Horizontal sync polarity (0=positive|1=negative) + * 8) Vertical sync polarity (0=positive|1=negative) + * 9) Horizontal front porch (pixels) + * 10) Horizontal sync time (pixels) + * 11) Horizontal back porch (pixels) + * 12) Vertical front porch (lines) + * 13) Vertical sync time (lines) + * 14) Vertical back porch (lines) + */ +XDptx_DmtMode XDptx_DmtModes[] = +{ + {XDPTX_VM_640x480_60_P, 0x04, 640, 480, 25175, + 0, 1, 1, 8, 96, 40, 2, 2, 25}, + {XDPTX_VM_800x600_60_P, 0x09, 800, 600, 40000, + 0, 0, 0, 40, 128, 88, 1, 4, 23}, + {XDPTX_VM_848x480_60_P, 0x0E, 848, 480, 33750, + 0, 0, 0, 16, 112, 112, 6, 8, 23}, + {XDPTX_VM_1024x768_60_P, 0x10, 1024, 768, 65000, + 0, 1, 1, 24, 136, 160, 3, 6, 29}, + {XDPTX_VM_1280x768_60_P_RB, 0x16, 1280, 768, 68250, + 0, 0, 1, 48, 32, 80, 3, 7, 12}, + {XDPTX_VM_1280x768_60_P, 0x17, 1280, 768, 79500, + 0, 1, 0, 64, 128, 192, 3, 7, 20}, + {XDPTX_VM_1280x800_60_P_RB, 0x1B, 1280, 800, 71000, + 0, 0, 1, 48, 32, 80, 3, 6, 14}, + {XDPTX_VM_1280x800_60_P, 0x1C, 1280, 800, 83500, + 0, 1, 0, 72, 128, 200, 3, 6, 22}, + {XDPTX_VM_1280x960_60_P, 0x20, 1280, 960, 108000, + 0, 0, 0, 96, 112, 312, 1, 3, 36}, + {XDPTX_VM_1280x1024_60_P, 0x23, 1280, 1024, 108000, + 0, 0, 0, 48, 112, 248, 1, 3, 38}, + {XDPTX_VM_1360x768_60_P, 0x27, 1360, 768, 85500, + 0, 0, 0, 64, 112, 256, 3, 6, 18}, + {XDPTX_VM_1400x1050_60_P_RB, 0x29, 1400, 1050, 101000, + 0, 0, 1, 48, 32, 80, 3, 4, 23}, + {XDPTX_VM_1400x1050_60_P, 0x2A, 1400, 1050, 121750, + 0, 1, 0, 88, 144, 232, 3, 4, 32}, + {XDPTX_VM_1440x900_60_P_RB, 0x2E, 1440, 900, 88750, + 0, 0, 1, 48, 32, 80, 3, 6, 17}, + {XDPTX_VM_1440x900_60_P, 0x2F, 1440, 900, 106500, + 0, 1, 0, 80, 152, 232, 3, 6, 25}, + {XDPTX_VM_1600x1200_60_P, 0x33, 1600, 1200, 162000, + 0, 0, 0, 64, 192, 304, 1, 3, 46}, + {XDPTX_VM_1680x1050_60_P_RB, 0x39, 1680, 1050, 119000, + 0, 1, 0, 48, 32, 80, 3, 6, 21}, + {XDPTX_VM_1680x1050_60_P, 0x3A, 1680, 1050, 146250, + 0, 1, 0, 104, 176, 280, 3, 6, 30}, + {XDPTX_VM_1792x1344_60_P, 0x3E, 1792, 1344, 204750, + 0, 1, 0, 128, 200, 328, 1, 3, 46}, + {XDPTX_VM_1856x1392_60_P, 0x41, 1856, 1392, 218250, + 0, 1, 0, 96, 224, 352, 1, 3, 43}, + {XDPTX_VM_1920x1200_60_P_RB, 0x44, 1920, 1200, 154000, + 0, 0, 1, 48, 32, 80, 3, 6, 26}, + {XDPTX_VM_1920x1200_60_P, 0x45, 1920, 1200, 193250, + 0, 1, 0, 136, 200, 336, 3, 6, 36}, + {XDPTX_VM_1920x1440_60_P, 0x49, 1920, 1440, 234000, + 0, 1, 0, 128, 208, 344, 1, 3, 56}, + {XDPTX_VM_2560x1600_60_P_RB, 0x4C, 2560, 1600, 268500, + 0, 0, 1, 48, 32, 80, 3, 6, 37}, + {XDPTX_VM_2560x1600_60_P, 0x4D, 2560, 1600, 348500, + 0, 1, 0, 192, 280, 472, 3, 6, 49}, + {XDPTX_VM_800x600_56_P, 0x08, 800, 600, 36000, + 0, 0, 0, 24, 72, 128, 1, 2, 22}, + {XDPTX_VM_1600x1200_65_P, 0x34, 1600, 1200, 175500, + 0, 0, 0, 64, 192, 304, 1, 3, 46}, + {XDPTX_VM_1600x1200_70_P, 0x35, 1600, 1200, 189000, + 0, 0, 0, 64, 192, 304, 1, 3, 46}, + {XDPTX_VM_1024x768_70_P, 0x11, 1024, 768, 75000, + 0, 1, 1, 24, 136, 144, 3, 6, 29}, + {XDPTX_VM_640x480_72_P, 0x05, 640, 480, 31500, + 0, 1, 1, 16, 40, 120, 1, 3, 20}, + {XDPTX_VM_800x600_72_P, 0x0A, 800, 600, 50000, + 0, 0, 0, 56, 120, 64, 37, 6, 23}, + {XDPTX_VM_640x480_75_P, 0x06, 640, 480, 31500, + 0, 1, 1, 16, 64, 120, 1, 3, 16}, + {XDPTX_VM_800x600_75_P, 0x0B, 800, 600, 49500, + 0, 0, 0, 16, 80, 160, 1, 3, 21}, + {XDPTX_VM_1024x768_75_P, 0x12, 1024, 768, 78750, + 0, 0, 0, 16, 96, 176, 1, 3, 28}, + {XDPTX_VM_1152x864_75_P, 0x15, 1152, 864, 108000, + 0, 0, 0, 64, 128, 256, 1, 3, 32}, + {XDPTX_VM_1280x768_75_P, 0x18, 1280, 768, 102250, + 0, 1, 0, 80, 128, 208, 3, 7, 27}, + {XDPTX_VM_1280x800_75_P, 0x1D, 1280, 800, 106500, + 0, 1, 0, 80, 128, 208, 3, 6, 29}, + {XDPTX_VM_1280x1024_75_P, 0x24, 1280, 1024, 135000, + 0, 0, 0, 16, 144, 248, 1, 3, 38}, + {XDPTX_VM_1400x1050_75_P, 0x2B, 1400, 1050, 156000, + 0, 1, 0, 104, 144, 248, 3, 4, 42}, + {XDPTX_VM_1440x900_75_P, 0x30, 1440, 900, 136750, + 0, 1, 0, 96, 152, 31, 3, 6, 33}, + {XDPTX_VM_1600x1200_75_P, 0x36, 1600, 1200, 202500, + 0, 0, 0, 64, 192, 304, 1, 3, 46}, + {XDPTX_VM_1680x1050_75_P, 0x3B, 1680, 1050, 187000, + 0, 1, 0, 120, 176, 37, 3, 6, 40}, + {XDPTX_VM_1792x1344_75_P, 0x3F, 1792, 1344, 261000, + 0, 1, 0, 96, 216, 352, 1, 3, 69}, + {XDPTX_VM_1856x1392_75_P, 0x42, 1856, 1392, 288000, + 0, 1, 0, 128, 224, 352, 1, 3, 104}, + {XDPTX_VM_1920x1200_75_P, 0x46, 1920, 1200, 245250, + 0, 1, 0, 136, 208, 344, 3, 6, 46}, + {XDPTX_VM_1920x1440_75_P, 0x4A, 1920, 1440, 297000, + 0, 1, 0, 144, 224, 352, 1, 3, 56}, + {XDPTX_VM_2560x1600_75_P, 0x4E, 2560, 1600, 443250, + 0, 1, 0, 208, 280, 488, 3, 6, 63}, + {XDPTX_VM_640x350_85_P, 0x01, 640, 350, 31500, + 0, 0, 1, 32, 64, 96, 32, 3, 60}, + {XDPTX_VM_640x400_85_P, 0x02, 640, 400, 31500, + 0, 1, 0, 32, 64, 96, 1, 3, 41}, + {XDPTX_VM_720x400_85_P, 0x03, 720, 400, 35500, + 0, 1, 0, 36, 72, 108, 1, 3, 42}, + {XDPTX_VM_640x480_85_P, 0x07, 640, 480, 36000, + 0, 1, 1, 56, 56, 80, 1, 3, 25}, + {XDPTX_VM_800x600_85_P, 0x0C, 800, 600, 56250, + 0, 0, 0, 32, 64, 152, 1, 3, 27}, + {XDPTX_VM_1024x768_85_P, 0x13, 1024, 768, 94500, + 0, 0, 0, 48, 96, 208, 1, 3, 36}, + {XDPTX_VM_1280x768_85_P, 0x19, 1280, 768, 117500, + 0, 1, 0, 80, 136, 216, 3, 7, 31}, + {XDPTX_VM_1280x800_85_P, 0x1E, 1280, 800, 122500, + 0, 1, 0, 80, 136, 216, 3, 6, 34}, + {XDPTX_VM_1280x960_85_P, 0x21, 1280, 960, 148500, + 0, 0, 0, 64, 160, 224, 1, 3, 47}, + {XDPTX_VM_1280x1024_85_P, 0x25, 1280, 1024, 157500, + 0, 0, 0, 64, 160, 224, 1, 3, 44}, + {XDPTX_VM_1400x1050_85_P, 0x2C, 1400, 1050, 179500, + 0, 1, 0, 104, 152, 256, 3, 4, 48}, + {XDPTX_VM_1440x900_85_P, 0x31, 1440, 900, 157000, + 0, 1, 0, 104, 152, 32, 3, 6, 39}, + {XDPTX_VM_1600x1200_85_P, 0x37, 1600, 1200, 229500, + 0, 0, 0, 64, 192, 304, 1, 3, 46}, + {XDPTX_VM_1680x1050_85_P, 0x3C, 1680, 1050, 214750, + 0, 1, 0, 128, 176, 304, 3, 6, 46}, + {XDPTX_VM_1920x1200_85_P, 0x47, 1920, 1200, 281250, + 0, 1, 0, 144, 208, 352, 3, 6, 53}, + {XDPTX_VM_2560x1600_85_P, 0x4F, 2560, 1600, 505250, + 0, 1, 0, 208, 280, 488, 3, 6, 73}, + {XDPTX_VM_800x600_120_P_RB, 0x0D, 800, 600, 73250, + 0, 0, 1, 48, 32, 80, 3, 4, 29}, + {XDPTX_VM_1024x768_120_P_RB, 0x14, 1024, 768, 115500, + 0, 0, 1, 48, 32, 80, 3, 4, 38}, + {XDPTX_VM_1280x768_120_P_RB, 0x1A, 1280, 768, 140250, + 0, 0, 1, 48, 32, 80, 3, 7, 35}, + {XDPTX_VM_1280x800_120_P_RB, 0x1F, 1280, 800, 146250, + 0, 0, 1, 48, 32, 80, 3, 6, 38}, + {XDPTX_VM_1280x960_120_P_RB, 0x22, 1280, 960, 175500, + 0, 0, 1, 48, 32, 80, 3, 4, 50}, + {XDPTX_VM_1280x1024_120_P_RB, 0x26, 1280, 1024, 187250, + 0, 0, 1, 48, 32, 80, 3, 7, 50}, + {XDPTX_VM_1360x768_120_P_RB, 0x28, 1360, 768, 148250, + 0, 0, 1, 48, 32, 80, 3, 5, 37}, + {XDPTX_VM_1400x1050_120_P_RB, 0x2D, 1400, 1050, 208000, + 0, 0, 1, 48, 32, 80, 3, 4, 55}, + {XDPTX_VM_1440x900_120_P_RB, 0x32, 1440, 900, 182750, + 0, 0, 1, 48, 32, 80, 3, 6, 44}, + {XDPTX_VM_1600x1200_120_P_RB, 0x38, 1600, 1200, 268250, + 0, 0, 1, 48, 32, 80, 3, 4, 64}, + {XDPTX_VM_1680x1050_120_P_RB, 0x3D, 1680, 1050, 245500, + 0, 0, 1, 48, 32, 80, 3, 6, 53}, + {XDPTX_VM_1792x1344_120_P_RB, 0x40, 1792, 1344, 333250, + 0, 0, 1, 48, 32, 80, 3, 4, 72}, + {XDPTX_VM_1856x1392_120_P_RB, 0x43, 1856, 1392, 356500, + 0, 0, 1, 48, 32, 80, 3, 4, 75}, + {XDPTX_VM_1920x1200_120_P_RB, 0x48, 1920, 1200, 317000, + 0, 0, 1, 48, 32, 80, 3, 6, 62}, + {XDPTX_VM_1920x1440_120_P_RB, 0x4B, 1920, 1440, 380500, + 0, 0, 1, 48, 32, 80, 3, 4, 78}, + {XDPTX_VM_2560x1600_120_P_RB, 0x50, 2560, 1600, 552750, + 0, 0, 1, 48, 32, 80, 3, 6, 85}, + {XDPTX_VM_1366x768_60_P, 0x00, 1366, 768, 72000, + 0, 0, 0, 14, 56, 64, 1, 3, 28}, + {XDPTX_VM_1920x1080_60_P, 0x00, 1920, 1080, 148500, + 0, 1, 1, 88, 44, 148, 4, 5, 36}, + {XDPTX_VM_UHD_30_P, 0x00, 3840, 2160, 297000, + 0, 0, 1, 176, 88, 296, 20, 10, 60}, + {XDPTX_VM_720_60_P, 0x00, 1280, 720, 74250, + 0, 1, 1, 110, 40, 220, 5, 5, 20}, + {XDPTX_VM_480_60_P, 0x00, 720, 480, 27027, + 0, 1, 1, 16, 62, 60, 9, 6, 30}, + {XDPTX_VM_UHD2_60_P, 0x00, 1920, 2160, 297000, + 0, 0, 1, 88, 44, 148, 20, 10, 60}, + {XDPTX_VM_UHD_60, 0x00, 3840, 2160, 594000, + 0, 0, 1, 176, 88, 296, 20, 10, 60} +};