From a6f402d2257ddff5f4c5846fefc38e43adcbad74 Mon Sep 17 00:00:00 2001 From: Rohit Consul Date: Fri, 9 Oct 2015 06:37:50 +0800 Subject: [PATCH] v_hdmitxss: Add initial version of hdmi tx subsystem driver Added hdmi tx subsystem driver v1.0 (on behalf of Gilbert Magnaye) Signed-off-by: Rohit Consul Acked-by: Andrei-Liviu Simion --- .../drivers/v_hdmitxss/data/v_hdmitxss.mdd | 44 + .../drivers/v_hdmitxss/data/v_hdmitxss.tcl | 355 +++ .../drivers/v_hdmitxss/src/Makefile | 40 + .../drivers/v_hdmitxss/src/xv_hdmitxss.c | 1964 +++++++++++++++++ .../drivers/v_hdmitxss/src/xv_hdmitxss.h | 251 +++ .../v_hdmitxss/src/xv_hdmitxss_coreinit.c | 326 +++ .../v_hdmitxss/src/xv_hdmitxss_coreinit.h | 79 + .../drivers/v_hdmitxss/src/xv_hdmitxss_g.c | 105 + .../v_hdmitxss/src/xv_hdmitxss_sinit.c | 97 + 9 files changed, 3261 insertions(+) create mode 100755 XilinxProcessorIPLib/drivers/v_hdmitxss/data/v_hdmitxss.mdd create mode 100755 XilinxProcessorIPLib/drivers/v_hdmitxss/data/v_hdmitxss.tcl create mode 100755 XilinxProcessorIPLib/drivers/v_hdmitxss/src/Makefile create mode 100755 XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss.c create mode 100755 XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss.h create mode 100755 XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss_coreinit.c create mode 100755 XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss_coreinit.h create mode 100755 XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss_g.c create mode 100755 XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss_sinit.c diff --git a/XilinxProcessorIPLib/drivers/v_hdmitxss/data/v_hdmitxss.mdd b/XilinxProcessorIPLib/drivers/v_hdmitxss/data/v_hdmitxss.mdd new file mode 100755 index 00000000..5c003e24 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/v_hdmitxss/data/v_hdmitxss.mdd @@ -0,0 +1,44 @@ +################################################################################ +# +# Copyright (C) 2015 Xilinx, Inc. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and#or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# Use of the Software is limited solely to applications: +# (a) running on a Xilinx device, or +# (b) that interact with a Xilinx device through a bus or interconnect. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +################################################################################ + +OPTION psf_version = 2.1; + +BEGIN driver v_hdmitxss + + OPTION supported_peripherals = (v_hdmi_tx_ss_v1_0); + OPTION driver_state = ACTIVE; + OPTION copyfiles = all; + OPTION VERSION = 1.0; + OPTION DEPENDS = (v_hdmitx_v1_0 vtc_v7_0 hdcp1x_v2_0 tmrctr_v4_0); + OPTION NAME = v_hdmitxss; + +END driver diff --git a/XilinxProcessorIPLib/drivers/v_hdmitxss/data/v_hdmitxss.tcl b/XilinxProcessorIPLib/drivers/v_hdmitxss/data/v_hdmitxss.tcl new file mode 100755 index 00000000..be7bf5ab --- /dev/null +++ b/XilinxProcessorIPLib/drivers/v_hdmitxss/data/v_hdmitxss.tcl @@ -0,0 +1,355 @@ +################################################################################ +# +# Copyright (C) 2015 Xilinx, Inc. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and#or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# Use of the Software is limited solely to applications: +# (a) running on a Xilinx device, or +# (b) that interact with a Xilinx device through a bus or interconnect. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# Except as contained in this notice, the name of the Xilinx shall not be used +# in advertising or otherwise to promote the sale, use or other dealings in +# this Software without prior written authorization from Xilinx. +# +################################################################################ +## +## MODIFICATION HISTORY: +## Ver Who Date Changes +## -------- ------ -------- ---------------------------------------------------- +## 1.0 gmagnay 08/14/15 Initial version of subsystem tcl +# +################################################################################ + +proc generate {drv_handle} { + ::hsi::utils::define_include_file $drv_handle "xparameters.h" "XV_HdmiTxSs" \ + "NUM_INSTANCES" \ + "C_BASEADDR" \ + "C_HIGHADDR" \ + "DEVICE_ID" \ + "C_INPUT_PIXELS_PER_CLOCK" \ + "C_MAX_BITS_PER_COMPONENT" + + hier_ip_define_config_file $drv_handle "xv_hdmitxss_g.c" "XV_HdmiTxSs" \ + "DEVICE_ID" \ + "C_BASEADDR" \ + "C_HIGHADDR" \ + "C_INPUT_PIXELS_PER_CLOCK" \ + "C_MAX_BITS_PER_COMPONENT" + + ::hsi::utils::define_canonical_xpars $drv_handle "xparameters.h" \ + "XV_HdmiTxSs" \ + "C_BASEADDR" \ + "C_HIGHADDR" \ + "DEVICE_ID" \ + "C_INPUT_PIXELS_PER_CLOCK" \ + "C_MAX_BITS_PER_COMPONENT" +} + + +proc hier_ip_define_config_file {drv_handle file_name drv_string args} { + set args [::hsi::utils::get_exact_arg_list $args] + set hw_instance_name [::common::get_property HW_INSTANCE $drv_handle]; + + set filename [file join "src" $file_name] + set config_file [open $filename w] + + ::hsi::utils::write_c_header $config_file "Driver configuration" + + puts $config_file "#include \"xparameters.h\"" + puts $config_file "#include \"[string tolower $drv_string].h\"" + puts $config_file "\n/*" + puts $config_file "* List of Sub-cores included in the subsystem" + puts $config_file "* Sub-core device id will be set by its driver in xparameters.h" + puts $config_file "*/\n" + + set periphs_g [::hsi::utils::get_common_driver_ips $drv_handle] + + array set sub_core_inst { + axi_timer 1 + hdcp 1 + v_hdmi_tx 1 + v_tc 1 + } + +#MAGS +#foreach name [array names sub_core_inst] { +# puts $config_file "//sub_core_inst: $name $sub_core_inst($name)" +#} + + foreach periph_g $periphs_g { + set mem_ranges [::hsi::get_mem_ranges $periph_g] + + ::hsi::current_hw_instance $periph_g; + + set child_cells_g [::hsi::get_cells -hier] + + foreach child_cell_g $child_cells_g { + set child_cell_vlnv [::common::get_property VLNV $child_cell_g] + set child_cell_name_g [common::get_property NAME $child_cell_g] + set vlnv_arr [split $child_cell_vlnv :] + + lassign $vlnv_arr ip_vendor ip_library ip_name ip_version + set ip_type_g [common::get_property IP_TYPE $child_cell_g] + + puts "IP type $ip_type_g\n" + if { [string compare -nocase "BUS" $ip_type_g] != 0 } { + set interfaces [hsi::get_intf_pins -of_objects $child_cell_g] + set is_slave 0 + + foreach interface $interfaces { + set intf_type [common::get_property TYPE $interface] + #puts "Interface type $intf_type\n" + if { [string compare -nocase "SLAVE" $intf_type] == 0 } { + set is_slave 1 + } + } + if { $is_slave != 0 } { + #puts "Processing Periph: $ip_name $child_cell_name_g" +#puts $config_file "//Processing Periph: $ip_name $child_cell_name_g" + set final_child_cell_instance_name_present_g XPAR_${child_cell_name_g}_PRESENT + puts -nonewline $config_file "#define [string toupper $final_child_cell_instance_name_present_g]\t 1\n" + + # create dictionary for ip name and it's instance names "ip_name {inst1_name inst2_name}" + dict lappend ss_ip_list $ip_name $child_cell_name_g + } + } + } + + puts $config_file "\n\n/*" + puts $config_file "* List of Sub-cores excluded from the subsystem" + puts $config_file "* - Excluded sub-core device id is set to 255" + puts $config_file "* - Excluded sub-core baseaddr is set to 0" + puts $config_file "*/\n" + + foreach sub_core [lsort [array names sub_core_inst]] { + #puts $config_file "//sub_core_inst: $sub_core $sub_core_inst($sub_core)" + if {[dict exists $ss_ip_list $sub_core]} { + set max_instances $sub_core_inst($sub_core) + #check if core can have multiple instances + #It is possible that not all instances are used in the design + if {$max_instances > 1} { + set ip_instances [dict get $ss_ip_list $sub_core] + set avail_instances [llength $ip_instances] + + #puts "Sub-Core: $sub_core" + #puts "instances: $ip_instances" + + #check if available instances are less than MAX + #if yes, mark the missing instance + #if all instances are present then skip the core + if {$avail_instances < $max_instances} { + if {[string compare -nocase "axi_gpio" $sub_core] == 0} { + set ip_inst_name [lindex $ip_instances 0] + set srcstr "${periph_g}_reset_sel_axi_mm" + if {[string compare -nocase $srcstr $ip_inst_name] == 0} { + set strval "RESET_SEL_AXIS" + } else { + set strval "RESET_SEL_AXI_MM" + } + } elseif {[string compare -nocase "v_vcresampler" $sub_core]} { + set ip_inst_name [lindex $ip_instances 0] + set srcstr "${periph_g}_v_vcresampler_in" + if {[string compare -nocase $srcstr $ip_inst_name] == 0} { + set strval "V_VCRESAMPLER_OUT" + } else { + set strval "V_VCRESAMPLER_IN" + } + } + #puts "String Selected: $strval" + set final_child_cell_instance_name_g "XPAR_${periph_g}_${strval}_PRESENT" + set final_child_cell_instance_devid_g "XPAR_${periph_g}_${strval}_DEVICE_ID" + set final_child_cell_instance_baseaddr_g "XPAR_${periph_g}_${strval}_BASEADDR" + puts -nonewline $config_file "#define [string toupper $final_child_cell_instance_name_g] 0\n" + puts -nonewline $config_file "#define [string toupper $final_child_cell_instance_devid_g] 255\n" + puts -nonewline $config_file "#define [string toupper $final_child_cell_instance_baseaddr_g] 0\n\n" + } + + } + #puts -nonewline $config_file "#define [string toupper $final_child_cell_instance_name_g] 1\n" + } else { + set count 0 + while {$count<$sub_core_inst($sub_core)} { + set final_child_cell_instance_name_g "XPAR_${periph_g}_${sub_core}_${count}_PRESENT" + set final_child_cell_instance_devid_g "XPAR_${periph_g}_${sub_core}_${count}_DEVICE_ID" + set final_child_cell_instance_baseaddr_g "XPAR_${periph_g}_${sub_core}_${count}_BASEADDR" + puts -nonewline $config_file "#define [string toupper $final_child_cell_instance_name_g] 0\n" + puts -nonewline $config_file "#define [string toupper $final_child_cell_instance_devid_g] 255\n" + puts -nonewline $config_file "#define [string toupper $final_child_cell_instance_baseaddr_g] 0\n\n" + incr count + } + } + } + ::hsi::current_hw_instance + } + + + puts $config_file "\n\n" + puts $config_file [format "%s_Config %s_ConfigTable\[\] =" $drv_string $drv_string] + puts $config_file "\{" + set periphs [::hsi::utils::get_common_driver_ips $drv_handle] + set start_comma "" + foreach periph $periphs { +#puts $config_file "//$periph $periphs" + puts $config_file [format "%s\t\{" $start_comma] + set comma "" + foreach arg $args { + if {[string compare -nocase "DEVICE_ID" $arg] == 0} { + puts -nonewline $config_file [format "%s\t\t%s,\n" $comma [::hsi::utils::get_ip_param_name $periph $arg]] + continue + } + + # Check if this is a driver parameter or a peripheral parameter + set value [common::get_property CONFIG.$arg $drv_handle] + if {[llength $value] == 0} { + set local_value [common::get_property CONFIG.$arg $periph ] + # If a parameter isn't found locally (in the current + # peripheral), we will (for some obscure and ancient reason) + # look in peripherals connected via point to point links + if { [string compare -nocase $local_value ""] == 0} { + set p2p_name [::hsi::utils::get_p2p_name $periph $arg] + if { [string compare -nocase $p2p_name ""] == 0} { + puts -nonewline $config_file [format "%s\t\t%s" $comma [::hsi::utils::get_ip_param_name $periph $arg]] + } else { + puts -nonewline $config_file [format "%s\t\t%s" $comma $p2p_name] + } + } else { + puts -nonewline $config_file [format "%s\t\t%s" $comma [::hsi::utils::get_ip_param_name $periph $arg]] + } + } else { + puts -nonewline $config_file [format "%s\t\t%s" $comma [::hsi::utils::get_driver_param_name $drv_string $arg]] + } + set comma ",\n" + } + + ::hsi::current_hw_instance $periph + set child_cells [::hsi::get_cells -hier] + puts $config_file ",\n" + + foreach sub_core [lsort [array names sub_core_inst]] { + set max_instances $sub_core_inst($sub_core) + #puts "\nProcessing sub-core: $sub_core" + #puts "Max Instances: $max_instances" + + if {[dict exists $ss_ip_list $sub_core]} { + #puts "****Sub-core found in dictionary****" + if {[string match -nocase v_t* $sub_core]} { + set base_addr_name "BASEADDR" + } elseif {[string match -nocase v_* $sub_core]} { + set base_addr_name "BASEADDR" + } else { + set base_addr_name "BASEADDR" + } + + set ip_instances [dict get $ss_ip_list $sub_core] + set avail_instances [llength $ip_instances] + + #check if core can have multiple instances + #It is possible that not all instances are used in the design + if {$max_instances > 1} { + + #check if available instances are less than MAX + #if yes, include the missing instance + if {$avail_instances < $max_instances} { + set ip_inst_name [lindex $ip_instances 0] + set count 0 + set str_name "unknown" + #puts "IP Inst. Name: $ip_inst_name" + while {$count < $max_instances} { + if {[string compare -nocase "axi_gpio" $sub_core] == 0} { + set str_name [expr {$count == 0 ? "RESET_SEL_AXI_MM" : "RESET_SEL_AXIS"}] + } elseif {[string compare -nocase "v_vcresampler" $sub_core]} { + set str_name [expr {$count == 0 ? "V_VCRESAMPLER_IN" : "V_VCRESAMPLER_OUT"}] + } + #write the ip instance entry to the table + set final_child_cell_instance_name_present "XPAR_${periph}_${str_name}_PRESENT" + set final_child_cell_instance_devid "XPAR_${periph}_${str_name}_DEVICE_ID" + set final_child_cell_instance_name_baseaddr "XPAR_${periph}_${str_name}_${base_addr_name}" + + puts $config_file "\t\t\{" + puts -nonewline $config_file [format "\t\t\t%s" [string toupper $final_child_cell_instance_name_present]] + puts $config_file "," + puts -nonewline $config_file [format "\t\t\t%s" [string toupper $final_child_cell_instance_devid]] + puts $config_file "," + puts -nonewline $config_file [format "\t\t\t%s" [string toupper $final_child_cell_instance_name_baseaddr]] + puts $config_file "\n\t\t\}," + incr count + } + } else { + foreach ip_inst $ip_instances { + #puts "instance = $ip_inst" + set final_child_cell_instance_name_present "XPAR_${ip_inst}_PRESENT" + set final_child_cell_instance_devid "XPAR_${ip_inst}_DEVICE_ID" + set final_child_cell_instance_name_baseaddr "XPAR_${ip_inst}_${base_addr_name}" + + puts $config_file "\t\t\{" + puts -nonewline $config_file [format "\t\t\t%s" [string toupper $final_child_cell_instance_name_present]] + puts $config_file "," + puts -nonewline $config_file [format "\t\t\t%s" [string toupper $final_child_cell_instance_devid]] + puts $config_file "," + puts -nonewline $config_file [format "\t\t\t%s" [string toupper $final_child_cell_instance_name_baseaddr]] + puts $config_file "\n\t\t\}," + } + } + } else { + set ip_inst_name [lindex $ip_instances 0] + #puts "instance = $ip_inst" + set final_child_cell_instance_name_present "XPAR_${ip_inst_name}_PRESENT" + set final_child_cell_instance_devid "XPAR_${ip_inst_name}_DEVICE_ID" + set final_child_cell_instance_name_baseaddr "XPAR_${ip_inst_name}_${base_addr_name}" + + puts $config_file "\t\t\{" + puts -nonewline $config_file [format "\t\t\t%s" [string toupper $final_child_cell_instance_name_present]] + puts $config_file "," + puts -nonewline $config_file [format "\t\t\t%s" [string toupper $final_child_cell_instance_devid]] + puts $config_file "," + puts -nonewline $config_file [format "\t\t\t%s" [string toupper $final_child_cell_instance_name_baseaddr]] + puts $config_file "\n\t\t\}," + } + } else { + #puts "****sub-core not in dictionary****" + set count 0 + + while {$count< $max_instances} { + set final_child_cell_instance_name_present "XPAR_${periph}_${sub_core}_${count}_PRESENT" + set final_child_cell_instance_devid "XPAR_${periph}_${sub_core}_${count}_DEVICE_ID" + set final_child_cell_instance_name_baseaddr "XPAR_${periph}_${sub_core}_${count}_BASEADDR" + + puts $config_file "\t\t\{" + puts -nonewline $config_file [format "\t\t\t%s" [string toupper $final_child_cell_instance_name_present]] + puts $config_file "," + puts -nonewline $config_file [format "\t\t\t%s" [string toupper $final_child_cell_instance_devid]] + puts $config_file "," + puts -nonewline $config_file [format "\t\t\t%s" [string toupper $final_child_cell_instance_name_baseaddr]] + puts $config_file "\n\t\t\}," + incr count + } + } + } + + ::hsi::current_hw_instance + + puts -nonewline $config_file "\t\}" + set start_comma ",\n" + } + + puts $config_file "\n\};" + puts $config_file "\n"; + close $config_file +} diff --git a/XilinxProcessorIPLib/drivers/v_hdmitxss/src/Makefile b/XilinxProcessorIPLib/drivers/v_hdmitxss/src/Makefile new file mode 100755 index 00000000..9436f54d --- /dev/null +++ b/XilinxProcessorIPLib/drivers/v_hdmitxss/src/Makefile @@ -0,0 +1,40 @@ +COMPILER= +ARCHIVER= +CP=cp +COMPILER_FLAGS= +EXTRA_COMPILER_FLAGS=-Wall -Wextra +LIB=libxil.a + +CC_FLAGS = $(COMPILER_FLAGS) +ECC_FLAGS = $(EXTRA_COMPILER_FLAGS) + +RELEASEDIR=../../../lib +INCLUDEDIR=../../../include +INCLUDES=-I./. -I${INCLUDEDIR} + +OUTS = *.o + +INCLUDEFILES=*.h +LIBSOURCES=*.c + +OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c))) + +libs: banner xvhdmitxss_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling HDMI TX Subsystem" + +xvhdmitxss_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xvhdmitxss_includes + +xvhdmitxss_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss.c b/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss.c new file mode 100755 index 00000000..602689ba --- /dev/null +++ b/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss.c @@ -0,0 +1,1964 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xv_hdmitxss.c +* +* This is main code of Xilinx HDMI Transmitter Subsystem device driver. +* Please see xv_hdmitxss.h for more details of the driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00         10/07/15 Initial release.
+
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xenv.h" +#if defined(__MICROBLAZE__) +#include "microblaze_sleep.h" +#elif defined(__arm__) +#include "sleep.h" +#endif +#include "xv_hdmitxss.h" +#include "xv_hdmitxss_coreinit.h" + + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ +/** + * This typedef declares the driver instances of all the cores in the subsystem + */ +typedef struct +{ + XTmrCtr HdcpTimer; + XHdcp1x Hdcp; + XV_HdmiTx HdmiTx; + XVtc Vtc; +}XV_HdmiTxSs_SubCores; + +/**************************** Local Global ***********************************/ +XV_HdmiTxSs_SubCores XV_HdmiTxSs_SubCoreRepo[XPAR_XV_HDMITXSS_NUM_INSTANCES]; + /**< Define Driver instance of all sub-core + included in the design */ + + +/************************** Function Prototypes ******************************/ +static void XV_HdmiTxSs_GetIncludedSubcores(XV_HdmiTxSs *HdmiTxSsPtr, + u16 DevId); +static XV_HdmiTxSs_SubCores *XV_HdmiTxSs_GetSubSysStruct(void *SubCorePtr); +static void XV_HdmiTxSs_WaitUs(XV_HdmiTxSs *InstancePtr, u32 MicroSeconds); +static int XV_HdmiTxSs_RegisterSubsysCallbacks(XV_HdmiTxSs *InstancePtr); +static int XV_HdmiTxSs_VtcSetup(XVtc *XVtcPtr, XV_HdmiTx *HdmiTxPtr); +static void XV_HdmiTxSs_SendAviInfoframe(XV_HdmiTx *HdmiTxPtr); +static void XV_HdmiTxSs_SendGeneralControlPacket(XV_HdmiTx *HdmiTxPtr); +static void XV_HdmiTxSs_ConnectCallback(void *CallbackRef); +static void XV_HdmiTxSs_VsCallback(void *CallbackRef); +static void XV_HdmiTxSs_StreamUpCallback(void *CallbackRef); +static void XV_HdmiTxSs_StreamDownCallback(void *CallbackRef); +static u32 XV_HdmiTxSs_HdcpTimerConvUsToTicks(u32 TimeoutInUs, + u32 ClockFrequency); + +/***************** Macros (Inline Functions) Definitions *********************/ +/************************** Function Definition ******************************/ + + +/*****************************************************************************/ +/** +* This function reports list of cores included in Video Processing Subsystem +* +* @param InstancePtr is a pointer to the Subsystem instance. +* +* @return None +* +******************************************************************************/ +void XV_HdmiTxSs_ReportCoreInfo(XV_HdmiTxSs *InstancePtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + + xil_printf("\r\n ->HDMI TX Subsystem Cores\r\n"); + + /* Report all the included cores in the subsystem instance */ + if (InstancePtr->HdmiTxPtr) { + xil_printf(" : HDMI TX \r\n"); + } + + if (InstancePtr->VtcPtr) { + xil_printf(" : VTC Core \r\n"); + } + + if (InstancePtr->HdcpPtr) { + xil_printf(" : HDCP TX \r\n"); + } + + if (InstancePtr->HdcpTimerPtr) { + xil_printf(" : HDCP: AXIS Timer\r\n"); + } +} + +/******************************************************************************/ +/** + * This function installs a custom delay/sleep function to be used by the XV_HdmiTxSs + * 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 XV_HdmiTxSs_SetUserTimerHandler(XV_HdmiTxSs *InstancePtr, + XVidC_DelayHandler 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 XV_HdmiTxSs 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 XV_HdmiTxSs_WaitUs(XV_HdmiTxSs *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 registers the user defined delay/sleep function with subsystem +//* +//* @param InstancePtr is a pointer to the Subsystem instance +//* @param waitmsec is the function pointer to the user defined delay function +//* @param pTimer is the pointer to timer instance used by the delay function +//* +//* @return None +//* +//******************************************************************************/ +//void XV_HdmiTxSs_RegisterDelayHandler(XV_HdmiTxSs *InstancePtr, +// XVidC_DelayHandler WaitMsec, +// void *TimerPtr) +//{ +// Xil_AssertVoid(InstancePtr != NULL); +// +// InstancePtr->UsrDelaymsec = WaitMsec; +// InstancePtr->UsrTmrPtr = TimerPtr; +//} + +/*****************************************************************************/ +/** + * This function calls the interrupt handler for HDMI TX + * + * @param InstancePtr is a pointer to the HDMI TX Subsystem + * + *****************************************************************************/ +void XV_HdmiTxSS_HdmiTxIntrHandler(XV_HdmiTxSs *InstancePtr) +{ + XV_HdmiTx_IntrHandler(InstancePtr->HdmiTxPtr); +} + +/*****************************************************************************/ +/** + * This function calls the interrupt handler for HDCP + * + * @param InstancePtr is a pointer to the HDMI TX Subsystem + * + *****************************************************************************/ +void XV_HdmiTxSS_HdcpIntrHandler(XV_HdmiTxSs *InstancePtr) +{ + XHdcp1x_CipherIntrHandler(InstancePtr->HdcpPtr); +} + +/*****************************************************************************/ +/** + * This function calls the interrupt handler for HDCP Timer + * + * @param InstancePtr is a pointer to the HDMI TX Subsystem + * + *****************************************************************************/ +void XV_HdmiTxSS_HdcpTimerIntrHandler(XV_HdmiTxSs *InstancePtr) +{ + XTmrCtr_InterruptHandler(InstancePtr->HdcpTimerPtr); +} + +/*****************************************************************************/ +/** + * This function register's all sub-core ISR's with interrupt controller and + * any subsystem level call back function with requisite sub-core + * + * @param InstancePtr is a pointer to the Subsystem instance to be + * worked on. + * + *****************************************************************************/ +static int XV_HdmiTxSs_RegisterSubsysCallbacks(XV_HdmiTxSs *InstancePtr) +{ + XV_HdmiTxSs *HdmiTxSsPtr = InstancePtr; + int Status; + + /** Register HDMI Tx ISR */ + if (HdmiTxSsPtr->HdmiTxPtr) { + /* + * Register call back for Tx Core Interrupts. + */ + XV_HdmiTx_SetCallback(HdmiTxSsPtr->HdmiTxPtr, + XV_HDMITX_HANDLER_CONNECT, + XV_HdmiTxSs_ConnectCallback, + InstancePtr); + + XV_HdmiTx_SetCallback(HdmiTxSsPtr->HdmiTxPtr, + XV_HDMITX_HANDLER_VS, + XV_HdmiTxSs_VsCallback, + InstancePtr); + + XV_HdmiTx_SetCallback(HdmiTxSsPtr->HdmiTxPtr, + XV_HDMITX_HANDLER_STREAM_UP, + XV_HdmiTxSs_StreamUpCallback, + InstancePtr); + + XV_HdmiTx_SetCallback(HdmiTxSsPtr->HdmiTxPtr, + XV_HDMITX_HANDLER_STREAM_DOWN, + XV_HdmiTxSs_StreamDownCallback, + InstancePtr); + } + + /** Register HDCP TX Timer ISR */ + if (HdmiTxSsPtr->HdcpTimerPtr) { + } + + /** Register HDCP TX ISR */ + if (HdmiTxSsPtr->HdcpPtr) { + } + + return(XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* This function queries the subsystem instance configuration to determine +* the included sub-cores. For each sub-core that is present in the design +* the sub-core driver instance is binded with the subsystem sub-core driver +* handle +* +* @param HdmiTxSsPtr is a pointer to the Subsystem instance to be worked on. +* +* @return None +* +******************************************************************************/ +static void XV_HdmiTxSs_GetIncludedSubcores(XV_HdmiTxSs *HdmiTxSsPtr, u16 DevId) +{ + HdmiTxSsPtr->HdmiTxPtr = ((HdmiTxSsPtr->Config.HdmiTx.IsPresent) \ + ? (&XV_HdmiTxSs_SubCoreRepo[DevId].HdmiTx) : NULL); + HdmiTxSsPtr->VtcPtr = ((HdmiTxSsPtr->Config.Vtc.IsPresent) \ + ? (&XV_HdmiTxSs_SubCoreRepo[DevId].Vtc) : NULL); + HdmiTxSsPtr->HdcpPtr = ((HdmiTxSsPtr->Config.Hdcp.IsPresent) \ + ? (&XV_HdmiTxSs_SubCoreRepo[DevId].Hdcp) : NULL); + HdmiTxSsPtr->HdcpTimerPtr = ((HdmiTxSsPtr->Config.HdcpTimer.IsPresent) \ + ? (&XV_HdmiTxSs_SubCoreRepo[DevId].HdcpTimer) : NULL); +} + +/*****************************************************************************/ +/** +* This function searches for the XV_HdmiTxSs_SubCores pointer +* +* @param SubCorePtr address of reference subcore +* +* @return Pointer to XV_HdmiTxSs_SubCoreRepo +* +******************************************************************************/ +static XV_HdmiTxSs_SubCores *XV_HdmiTxSs_GetSubSysStruct(void *SubCorePtr) +{ + int i; + + for (i=0; iConfig), (const void *)CfgPtr, + sizeof(XV_HdmiTxSs_Config)); + HdmiTxSsPtr->Config.BaseAddress = EffectiveAddr; + + /* Determine sub-cores included in the provided instance of subsystem */ + XV_HdmiTxSs_GetIncludedSubcores(HdmiTxSsPtr, CfgPtr->DeviceId); + + /* Initialize all included sub_cores */ + if (HdmiTxSsPtr->HdcpTimerPtr) { + if (XV_HdmiTxSs_SubcoreInitHdcpTimer(HdmiTxSsPtr) != XST_SUCCESS){ + return(XST_FAILURE); + } + } + + if (HdmiTxSsPtr->HdcpPtr) { + if (XV_HdmiTxSs_SubcoreInitHdcp(HdmiTxSsPtr) != XST_SUCCESS){ + return(XST_FAILURE); + } + } + + if (HdmiTxSsPtr->HdmiTxPtr) { + if (XV_HdmiTxSs_SubcoreInitHdmiTx(HdmiTxSsPtr) != XST_SUCCESS) { + return(XST_FAILURE); + } + } + + if (HdmiTxSsPtr->VtcPtr) { + if (XV_HdmiTxSs_SubcoreInitVtc(HdmiTxSsPtr) != XST_SUCCESS) { + return(XST_FAILURE); + } + } + + /* Register Callbacks */ + XV_HdmiTxSs_RegisterSubsysCallbacks(HdmiTxSsPtr); + + /* Reset the hardware and set the flag to indicate the + subsystem is ready + */ + XV_HdmiTxSs_Reset(HdmiTxSsPtr); + HdmiTxSsPtr->IsReady = XIL_COMPONENT_IS_READY; + + return(XST_SUCCESS); +} + +/****************************************************************************/ +/** +* This function starts the HDMI TX subsystem including all sub-cores that are +* included in the processing pipeline for a given use-case. Video pipe is +* started from back to front +* @param InstancePtr is a pointer to the Subsystem instance to be worked on. +* +* @return None +* +* @note Cores are started only if the corresponding start flag in the scratch +* pad memory is set. This allows to selectively start only those cores +* included in the processing chain +******************************************************************************/ +void XV_HdmiTxSs_Start(XV_HdmiTxSs *InstancePtr) +{ +// u8 *pStartCore; + + Xil_AssertVoid(InstancePtr != NULL); + +// pStartCore = &InstancePtr->idata.startCore[0]; + xdbg_printf(XDBG_DEBUG_GENERAL," ->Start HDMI TX Subsystem.... \r\n"); + +} + +/*****************************************************************************/ +/** +* This function stops the HDMI TX subsystem including all sub-cores +* Stop the video pipe starting from front to back +* +* @param InstancePtr is a pointer to the Subsystem instance to be worked on. +* +* @return None +* +******************************************************************************/ +void XV_HdmiTxSs_Stop(XV_HdmiTxSs *InstancePtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + + xdbg_printf(XDBG_DEBUG_GENERAL," ->Stop HDMI TX Subsystem.... \r\n"); + + /* Disable VTC */ + XVtc_DisableGenerator(InstancePtr->VtcPtr); +} + +/*****************************************************************************/ +/** +* This function resets the video subsystem sub-cores. There are 2 reset +* networks within the subsystem +* - For cores that are on AXIS interface +* - For cores that are on AXI-MM interface +* +* @param InstancePtr is a pointer to the Subsystem instance to be worked on. +* +* @return None +* +******************************************************************************/ +void XV_HdmiTxSs_Reset(XV_HdmiTxSs *InstancePtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + + xdbg_printf(XDBG_DEBUG_GENERAL," ->Reset HDMI TX Subsystem.... \r\n"); + + XVtc_Reset(InstancePtr->VtcPtr); +} + +/*****************************************************************************/ +/** +* +* This function configures Video Timing Controller (VTC). +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static int XV_HdmiTxSs_VtcSetup(XVtc *XVtcPtr, XV_HdmiTx *HdmiTxPtr) +{ + /* Polarity configuration */ + XVtc_Polarity Polarity; + XVtc_SourceSelect SourceSelect; + XVtc_Timing VideoTiming; + u32 HdmiTx_Hblank; + u32 Vtc_Hblank; + + /* Disable Generator */ + XVtc_Reset(XVtcPtr); + XVtc_DisableGenerator(XVtcPtr); + XVtc_Disable(XVtcPtr); + + /* Set up source select */ + memset((void *)&SourceSelect, 0, sizeof(SourceSelect)); + + /* 1 = Generator registers, 0 = Detector registers */ + SourceSelect.VChromaSrc = 1; + SourceSelect.VActiveSrc = 1; + SourceSelect.VBackPorchSrc = 1; + SourceSelect.VSyncSrc = 1; + SourceSelect.VFrontPorchSrc = 1; + SourceSelect.VTotalSrc = 1; + SourceSelect.HActiveSrc = 1; + SourceSelect.HBackPorchSrc = 1; + SourceSelect.HSyncSrc = 1; + SourceSelect.HFrontPorchSrc = 1; + SourceSelect.HTotalSrc = 1; + + XVtc_SetSource(XVtcPtr, &SourceSelect); + + VideoTiming.HActiveVideo = HdmiTxPtr->Stream.Video.Timing.HActive; + VideoTiming.HFrontPorch = HdmiTxPtr->Stream.Video.Timing.HFrontPorch; + VideoTiming.HSyncWidth = HdmiTxPtr->Stream.Video.Timing.HSyncWidth; + VideoTiming.HBackPorch = HdmiTxPtr->Stream.Video.Timing.HBackPorch; + VideoTiming.HSyncPolarity = HdmiTxPtr->Stream.Video.Timing.HSyncPolarity; + + /* Vertical Timing */ + VideoTiming.VActiveVideo = HdmiTxPtr->Stream.Video.Timing.VActive; + + // The VTC has an offset issue. + // This results into a wrong front porch and back porch value. + // As a workaround the front porch and back porch need to be adjusted. + VideoTiming.V0FrontPorch = HdmiTxPtr->Stream.Video.Timing.F0PVFrontPorch - 1; + VideoTiming.V0BackPorch = HdmiTxPtr->Stream.Video.Timing.F0PVBackPorch + 1; + VideoTiming.V0SyncWidth = HdmiTxPtr->Stream.Video.Timing.F0PVSyncWidth; + + VideoTiming.V1FrontPorch = HdmiTxPtr->Stream.Video.Timing.F1VFrontPorch; + VideoTiming.V1SyncWidth = HdmiTxPtr->Stream.Video.Timing.F1VSyncWidth; + VideoTiming.V1BackPorch = HdmiTxPtr->Stream.Video.Timing.F1VBackPorch; + + VideoTiming.VSyncPolarity = HdmiTxPtr->Stream.Video.Timing.VSyncPolarity; + + VideoTiming.Interlaced = HdmiTxPtr->Stream.Video.IsInterlaced; + + /* YUV420 */ + if (HdmiTxPtr->Stream.Video.ColorFormatId == XVIDC_CSF_YCRCB_420) { + VideoTiming.HActiveVideo = VideoTiming.HActiveVideo/4; + VideoTiming.HFrontPorch = VideoTiming.HFrontPorch/4; + VideoTiming.HBackPorch = VideoTiming.HBackPorch/4; + VideoTiming.HSyncWidth = VideoTiming.HSyncWidth/4; + } + + /* Other color spaces */ + else + { + /* 4 pixels per clock */ + if (HdmiTxPtr->Stream.Video.PixPerClk == XVIDC_PPC_4) { + VideoTiming.HActiveVideo = VideoTiming.HActiveVideo/4; + VideoTiming.HFrontPorch = VideoTiming.HFrontPorch/4; + VideoTiming.HBackPorch = VideoTiming.HBackPorch/4; + VideoTiming.HSyncWidth = VideoTiming.HSyncWidth/4; + } + + /* 2 pixels per clock */ + else { + VideoTiming.HActiveVideo = VideoTiming.HActiveVideo/2; + VideoTiming.HFrontPorch = VideoTiming.HFrontPorch/2; + VideoTiming.HBackPorch = VideoTiming.HBackPorch/2; + VideoTiming.HSyncWidth = VideoTiming.HSyncWidth/2; + } + } + +/** When compensating the vtc horizontal timing parameters for the pixel mode +* (quad or dual) rounding errors might be introduced (due to the divide) +* If this happens, the vtc total horizontal blanking is less than the hdmi tx +* horizontal blanking. +* As a result the hdmi tx vid out bridge is not able to lock to +* the incoming video stream. +* This process will check the horizontal blank timing and compensate +* for this condition. +* Calculate hdmi tx horizontal blanking */ + + HdmiTx_Hblank = HdmiTxPtr->Stream.Video.Timing.HFrontPorch + + HdmiTxPtr->Stream.Video.Timing.HSyncWidth + + HdmiTxPtr->Stream.Video.Timing.HBackPorch; + + do { + // Calculate vtc horizontal blanking + Vtc_Hblank = VideoTiming.HFrontPorch + + VideoTiming.HBackPorch + + VideoTiming.HSyncWidth; + + // Quad pixel mode + if (HdmiTxPtr->Stream.Video.PixPerClk == XVIDC_PPC_4) { + Vtc_Hblank *= 4; + } + + // Dual pixel mode + else { + Vtc_Hblank *= 2; + } + + // If the horizontal total blanking differs, + // then increment the Vtc horizontal front porch. + if (Vtc_Hblank != HdmiTx_Hblank) { + VideoTiming.HFrontPorch++; + } + + } while (Vtc_Hblank != HdmiTx_Hblank); + + XVtc_SetGeneratorTiming(XVtcPtr, &VideoTiming); + + /* Set up Polarity of all outputs */ + memset((void *)&Polarity, 0, sizeof(XVtc_Polarity)); + Polarity.ActiveChromaPol = 1; + Polarity.ActiveVideoPol = 1; + + //Polarity.FieldIdPol = 0; + if (VideoTiming.Interlaced) { + Polarity.FieldIdPol = 1; + } + else { + Polarity.FieldIdPol = 0; + } + + Polarity.VBlankPol = VideoTiming.VSyncPolarity; + Polarity.VSyncPol = VideoTiming.VSyncPolarity; + Polarity.HBlankPol = VideoTiming.HSyncPolarity; + Polarity.HSyncPol = VideoTiming.HSyncPolarity; + + XVtc_SetPolarity(XVtcPtr, &Polarity); + + /* VTC driver does not take care of the setting of the VTC in + * interlaced operation. As a work around the register + * is set manually */ + if (VideoTiming.Interlaced) { + /* Interlaced mode */ + XVtc_WriteReg(XVtcPtr->Config.BaseAddress, 0x68, 0x42); + } + else { + /* Progressive mode */ + XVtc_WriteReg(XVtcPtr->Config.BaseAddress, 0x68, 0x2); + } + + /* Enable generator module */ + XVtc_Enable(XVtcPtr); + XVtc_EnableGenerator(XVtcPtr); + XVtc_RegUpdateEnable(XVtcPtr); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* +* This function is called when a TX connect event has occurred. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_ConnectCallback(void *CallbackRef) +{ + XV_HdmiTxSs *HdmiTxSsPtr = (XV_HdmiTxSs *)CallbackRef; + + // Is the cable connected? + if (XV_HdmiTx_IsStreamConnected(HdmiTxSsPtr->HdmiTxPtr)) { + HdmiTxSsPtr->IsStreamConnected = (TRUE); + xil_printf("TX cable is connected\n\r"); + } + + // TX cable is disconnected + else { + HdmiTxSsPtr->IsStreamConnected = (FALSE); + xil_printf("TX cable is disconnected\n\r"); + } + + // Check if user callback has been registered + if (HdmiTxSsPtr->ConnectCallback) { + HdmiTxSsPtr->ConnectCallback(HdmiTxSsPtr->ConnectRef); + } + +} + +/*****************************************************************************/ +/** +* +* This function is called when a TX vsync has occurred. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_VsCallback(void *CallbackRef) +{ + XV_HdmiTxSs *HdmiTxSsPtr = (XV_HdmiTxSs *)CallbackRef; + + // AVI infoframe + XV_HdmiTxSs_SendAviInfoframe(HdmiTxSsPtr->HdmiTxPtr); + + // General control packet + XV_HdmiTxSs_SendGeneralControlPacket(HdmiTxSsPtr->HdmiTxPtr); + + // Check if user callback has been registered + if (HdmiTxSsPtr->VsCallback) { + HdmiTxSsPtr->VsCallback(HdmiTxSsPtr->VsRef); + } +} + +/*****************************************************************************/ +/** +* +* This function sends AVI info frames. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void XV_HdmiTxSs_SendAviInfoframe(XV_HdmiTx *HdmiTx) +{ + u8 Index; + u8 Data; + u8 Crc; + + /* Header, Packet type*/ + HdmiTx->Aux.Header.Byte[0] = 0x82; + + /* Version */ + HdmiTx->Aux.Header.Byte[1] = 0x02; + + /* Length */ + HdmiTx->Aux.Header.Byte[2] = 13; + + /* Checksum (this will be calculated by the HDMI TX IP) */ + HdmiTx->Aux.Header.Byte[3] = 0; + + /* Data */ + switch (HdmiTx->Stream.Video.ColorFormatId) { + case XVIDC_CSF_YCRCB_422: + Data = 1 << 5; + break; + + case XVIDC_CSF_YCRCB_444: + Data = 2 << 5; + break; + + case XVIDC_CSF_YCRCB_420: + Data = 3 << 5; + break; + + default: + Data = 0; + break; + } + + HdmiTx->Aux.Data.Byte[1] = Data; + + HdmiTx->Aux.Data.Byte[2] = 0; + HdmiTx->Aux.Data.Byte[3] = 0; + HdmiTx->Aux.Data.Byte[4] = HdmiTx->Stream.Vic; + + for (Index = 5; Index < 32; Index++) { + HdmiTx->Aux.Data.Byte[Index] = 0; + } + + /* Calculate AVI infoframe checksum */ + Crc = 0; + + /* Header */ + for (Index = 0; Index < 3; Index++) { + Crc += HdmiTx->Aux.Header.Byte[Index]; + } + + /* Data */ + for (Index = 1; Index < 5; Index++) { + Crc += HdmiTx->Aux.Data.Byte[Index]; + } + + Crc = 256 - Crc; + + HdmiTx->Aux.Data.Byte[0] = Crc; + + XV_HdmiTx_AuxSend(HdmiTx); +} + +/*****************************************************************************/ +/** +* +* This function sends the general control packet. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void XV_HdmiTxSs_SendGeneralControlPacket(XV_HdmiTx *HdmiTx) +{ + u8 Index; + u8 Data; + + // Pre-Process SB1 data + // Pixel Packing Phase + switch (XV_HdmiTx_GetPixelPackingPhase(HdmiTx)) { + + case 1 : + Data = 1; + break; + + case 2 : + Data = 2; + break; + + case 3 : + Data = 3; + break; + + default : + Data = 0; + break; + } + + /**< Shift pixel packing phase to the upper nibble */ + Data <<= 4; + + /** In HDMI the colordepth in YUV422 is always 12 bits, although on the + * link itself it is being transmitted as 8-bits. Therefore if the colorspace + * is YUV422, then force the colordepth to 8 bits. */ + if (HdmiTx->Stream.Video.ColorFormatId == XVIDC_CSF_YCRCB_422) { + Data |= 0; + } + + else { + + // Colordepth + switch (HdmiTx->Stream.Video.ColorDepth) { + + // 10 bpc + case XVIDC_BPC_10: + // Color depth + Data |= 5; + break; + + // 12 bpc + case XVIDC_BPC_12: + // Color depth + Data |= 6; + break; + + // 16 bpc + case XVIDC_BPC_16: + // Color depth + Data |= 7; + break; + + // Not indicated + default: + Data = 0; + break; + } + } + + // Packet type + HdmiTx->Aux.Header.Byte[0] = 0x3; + + // Reserved + HdmiTx->Aux.Header.Byte[1] = 0; + + // Reserved + HdmiTx->Aux.Header.Byte[2] = 0; + + // Checksum (this will be calculated by the HDMI TX IP) + HdmiTx->Aux.Header.Byte[3] = 0; + + // Data + // The packet contains four identical subpackets + for (Index = 0; Index < 4; Index++) { + // SB0 + HdmiTx->Aux.Data.Byte[(Index*8)] = 0; + + // SB1 + HdmiTx->Aux.Data.Byte[(Index*8)+1] = Data; + + // SB2 + HdmiTx->Aux.Data.Byte[(Index*8)+2] = 0; + + // SB3 + HdmiTx->Aux.Data.Byte[(Index*8)+3] = 0; + + // SB4 + HdmiTx->Aux.Data.Byte[(Index*8)+4] = 0; + + // SB5 + HdmiTx->Aux.Data.Byte[(Index*8)+5] = 0; + + // SB6 + HdmiTx->Aux.Data.Byte[(Index*8)+6] = 0; + + // SB ECC + HdmiTx->Aux.Data.Byte[(Index*8)+7] = 0; + + } + + XV_HdmiTx_AuxSend(HdmiTx); +} + +/*****************************************************************************/ +/** +* +* This function is called when the TX stream is up. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_StreamUpCallback(void *CallbackRef) +{ + XV_HdmiTxSs *HdmiTxSsPtr = (XV_HdmiTxSs *)CallbackRef; + + // Check if user callback has been registered + if (HdmiTxSsPtr->StreamUpCallback) { + HdmiTxSsPtr->StreamUpCallback(HdmiTxSsPtr->StreamUpRef); + } + + /* Set TX sample rate */ + XV_HdmiTx_SetSampleRate(HdmiTxSsPtr->HdmiTxPtr, HdmiTxSsPtr->SamplingRate); + + /* Release HDMI TX reset */ + XV_HdmiTx_Reset(HdmiTxSsPtr->HdmiTxPtr, FALSE); + + /* Setup VTC */ + XV_HdmiTxSs_VtcSetup(HdmiTxSsPtr->VtcPtr, HdmiTxSsPtr->HdmiTxPtr); + + if (HdmiTxSsPtr->AudioEnabled) { + /* HDMI TX unmute audio */ + HdmiTxSsPtr->AudioMute = (FALSE); + XV_HdmiTx_AudioUnmute(HdmiTxSsPtr->HdmiTxPtr); + } + + + if (HdmiTxSsPtr->HdcpPtr) { + /* Set the TX HDCP state to up */ + XHdcp1x_SetPhysicalState(HdmiTxSsPtr->HdcpPtr, TRUE); + } + +} + +/*****************************************************************************/ +/** +* +* This function is called when the TX stream is down. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_StreamDownCallback(void *CallbackRef) +{ + XV_HdmiTxSs *HdmiTxSsPtr = (XV_HdmiTxSs *)CallbackRef; + + // Assert HDMI TX reset + XV_HdmiTx_Reset(HdmiTxSsPtr->HdmiTxPtr, TRUE); + + if (HdmiTxSsPtr->HdcpPtr) { + /* Set the TX HDCP state to down */ + XHdcp1x_SetPhysicalState(HdmiTxSsPtr->HdcpPtr, FALSE); + } + + // Check if user callback has been registered + if (HdmiTxSsPtr->StreamDownCallback) { + HdmiTxSsPtr->StreamDownCallback(HdmiTxSsPtr->StreamDownRef); + } + +} + +/*****************************************************************************/ +/** +* +* This function installs an asynchronous callback function for the given +* HandlerType: +* +*
+* HandlerType                     Callback Function Type
+* -----------------------         ---------------------------------------------
+* (XV_HDMITXSS_HANDLER_CONNECT)       HpdCallback
+* (XV_HDMITXSS_HANDLER_VS)            VsCallback
+* (XV_HDMITXSS_HANDLER_STREAM_DOWN)   SreamDownCallback
+* (XV_HDMITXSS_HANDLER_STREAM_UP)     SreamUpCallback
+* 
+* +* @param InstancePtr is a pointer to the HDMI TX Subsystem instance. +* @param HandlerType specifies the type of handler. +* @param CallbackFunc is the address of the callback function. +* @param CallbackRef is a user data item that will be passed to the +* callback function when it is invoked. +* +* @return +* - XST_SUCCESS if callback function installed successfully. +* - XST_INVALID_PARAM when HandlerType is invalid. +* +* @note Invoking this function for a handler that already has been +* installed replaces it with the new handler. +* +******************************************************************************/ +int XV_HdmiTxSs_SetCallback(XV_HdmiTxSs *InstancePtr, + u32 HandlerType, + void *CallbackFunc, + void *CallbackRef) +{ + u32 Status; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(HandlerType >= (XV_HDMITXSS_HANDLER_CONNECT)); + Xil_AssertNonvoid(CallbackFunc != NULL); + Xil_AssertNonvoid(CallbackRef != NULL); + + /* Check for handler type */ + switch (HandlerType) { + case (XV_HDMITXSS_HANDLER_CONNECT): + InstancePtr->ConnectCallback = (XV_HdmiTxSs_Callback)CallbackFunc; + InstancePtr->ConnectRef = CallbackRef; + Status = (XST_SUCCESS); + break; + + case (XV_HDMITXSS_HANDLER_VS): + InstancePtr->VsCallback = (XV_HdmiTxSs_Callback)CallbackFunc; + InstancePtr->VsRef = CallbackRef; + Status = (XST_SUCCESS); + break; + + // Stream down + case (XV_HDMITXSS_HANDLER_STREAM_DOWN): + InstancePtr->StreamDownCallback = + (XV_HdmiTxSs_Callback)CallbackFunc; + InstancePtr->StreamDownRef = CallbackRef; + Status = (XST_SUCCESS); + break; + + // Stream up + case (XV_HDMITXSS_HANDLER_STREAM_UP): + InstancePtr->StreamUpCallback = (XV_HdmiTxSs_Callback)CallbackFunc; + InstancePtr->StreamUpRef = CallbackRef; + Status = (XST_SUCCESS); + break; + + default: + Status = (XST_INVALID_PARAM); + break; + } + + return Status; +} + +/*****************************************************************************/ +/** +* +* This function reads the HDMI Sink EDID. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +int XV_HdmiTxSs_ReadEdid(XV_HdmiTxSs *InstancePtr, u8 *Buffer) +{ + u32 Status; + + // Default + Status = (XST_FAILURE); + + // Check if a sink is connected + if (InstancePtr->IsStreamConnected == (TRUE)) { + + *Buffer = 0x00; // Offset zero + Status = XV_HdmiTx_DdcWrite(InstancePtr->HdmiTxPtr, 0x50, 1, Buffer, + (FALSE)); + + // Check if write was successful + if (Status == (XST_SUCCESS)) { + // Read edid + Status = XV_HdmiTx_DdcRead(InstancePtr->HdmiTxPtr, 0x50, 256, Buffer, + (TRUE)); + } + } + + else { + print("No sink is connected.\n\r"); + print("Please connect a HDMI sink.\n\r"); + } + return Status; +} + +/*****************************************************************************/ +/** +* +* This function shows the HDMI source edid. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_ShowEdid(XV_HdmiTxSs *InstancePtr) +{ + u8 Buffer[256]; + u8 Row; + u8 Column; + u8 Valid; + u32 Status; + u8 EdidManName[4]; + + // Check if a sink is connected + if (InstancePtr->IsStreamConnected == (TRUE)) { + + // Default + Valid = (FALSE); + + // Read TX edid + Status = XV_HdmiTxSs_ReadEdid(InstancePtr, (u8*)&Buffer); + + // Check if read was successful + if (Status == (XST_SUCCESS)) { + + print("\n\r"); + + XVidC_EdidGetManName(&Buffer[0], (char *) EdidManName); + xil_printf("Manufacturer name : %S\n\r", EdidManName); + + print("\n\rRaw data\n\r"); + print("----------------------------------------------------\n\r"); + for (Row = 0; Row < 16; Row++) { + xil_printf("%02X : ", (Row*16)); + for (Column = 0; Column < 16; Column++) { + xil_printf("%02X ", Buffer[(Row*16)+Column]); + } + print("\n\r"); + } + Valid = (TRUE); + } + + if (!Valid) { + print("Error reading EDID\n\r"); + } + } + + else { + print("No sink is connected.\n\r"); + print("Please connect a HDMI sink.\n\r"); + } +} + + +/*****************************************************************************/ +/** +* +* This function starts the HDMI TX stream +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_StreamStart(XV_HdmiTxSs *InstancePtr) +{ + // Set TX pixel rate + XV_HdmiTx_SetPixelRate(InstancePtr->HdmiTxPtr); + + // Set TX color depth + XV_HdmiTx_SetColorDepth(InstancePtr->HdmiTxPtr); + + // Set TX color format + XV_HdmiTx_SetColorFormat(InstancePtr->HdmiTxPtr); + + // Set TX scrambler + XV_HdmiTx_Scrambler(InstancePtr->HdmiTxPtr); + + // Set TX clock ratio + XV_HdmiTx_ClockRatio(InstancePtr->HdmiTxPtr); +} + +/*****************************************************************************/ +/** +* +* This function sends audio info frames. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_SendAudioInfoframe(XV_HdmiTxSs *InstancePtr, void *Aux) +{ + u8 Index; + u8 Crc; + XV_HdmiTx_Aux *tx_aux = Aux; + + if (Aux == (NULL)) { + /* Header, Packet type */ + InstancePtr->HdmiTxPtr->Aux.Header.Byte[0] = 0x84; + + /* Version */ + InstancePtr->HdmiTxPtr->Aux.Header.Byte[1] = 0x01; + + /* Length */ + InstancePtr->HdmiTxPtr->Aux.Header.Byte[2] = 10; + + /* Checksum (this will be calculated by the HDMI TX IP) */ + InstancePtr->HdmiTxPtr->Aux.Header.Byte[3] = 0; + + /* 2 Channel count. Audio coding type refer to stream */ + InstancePtr->HdmiTxPtr->Aux.Data.Byte[1] = 0x1; + + for (Index = 2; Index < 32; Index++) { + InstancePtr->HdmiTxPtr->Aux.Data.Byte[Index] = 0; + } + + /* Calculate AVI infoframe checksum */ + Crc = 0; + + /* Header */ + for (Index = 0; Index < 3; Index++) { + Crc += InstancePtr->HdmiTxPtr->Aux.Header.Byte[Index]; + } + + /* Data */ + for (Index = 1; Index < 5; Index++) { + Crc += InstancePtr->HdmiTxPtr->Aux.Data.Byte[Index]; + } + + Crc = 256 - Crc; + InstancePtr->HdmiTxPtr->Aux.Data.Byte[0] = Crc; + + XV_HdmiTx_AuxSend(InstancePtr->HdmiTxPtr); + + } + + else { + // Copy Audio Infoframe + if (InstancePtr->HdmiTxPtr->Aux.Header.Byte[0] == 0x84) { + // Header + InstancePtr->HdmiTxPtr->Aux.Header.Data = tx_aux->Header.Data; + + // Data + for (Index = 0; Index < 8; Index++) { + InstancePtr->HdmiTxPtr->Aux.Data.Data[Index] = + tx_aux->Data.Data[Index]; + } + } + } + + /* Send packet */ + XV_HdmiTx_AuxSend(InstancePtr->HdmiTxPtr); +} + +/*****************************************************************************/ +/** +* +* This function Sets the HDMI TX SS number of active audio channels +* +* @param InstancePtr pointer to XV_HdmiTxSs instance +* @param AudioChannels +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_SetAudioChannels(XV_HdmiTxSs *InstancePtr, u8 AudioChannels) +{ + InstancePtr->AudioChannels = AudioChannels; +} + +/*****************************************************************************/ +/** +* +* This function set HDMI TX audio parameters +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_AudioMute(XV_HdmiTxSs *InstancePtr, u8 Enable) +{ + //Audio Mute Mode + if (Enable){ + XV_HdmiTx_AudioMute(InstancePtr->HdmiTxPtr); + } + else{ + XV_HdmiTx_AudioUnmute(InstancePtr->HdmiTxPtr); + } +} + +/*****************************************************************************/ +/** +* +* This function set HDMI TX susbsystem stream parameters +* +* @param None. +* +* @return Calculated TMDS Clock +* +* @note None. +* +******************************************************************************/ +u32 XV_HdmiTxSs_SetStream(XV_HdmiTxSs *InstancePtr, + XVidC_VideoMode VideoMode, XVidC_ColorFormat ColorFormat, + XVidC_ColorDepth Bpc, XVidC_PixelsPerClock Ppc) +{ + u32 TmdsClock = 0; + u32 Loop; + u8 ReachedEnd = 0; + + if (VideoMode < XVIDC_VM_NUM_SUPPORTED) { + Loop = 0; + do + { + switch (Loop) { + case 0 : + TmdsClock = XV_HdmiTx_SetStream(InstancePtr->HdmiTxPtr, VideoMode, + ColorFormat, Bpc, Ppc); + break; + + // Try YCrCb 4:2:0 Colorspace at 4 pixels per clock + case 1 : + TmdsClock = XV_HdmiTx_SetStream(InstancePtr->HdmiTxPtr, VideoMode, + XVIDC_CSF_YCRCB_420, XVIDC_BPC_8, XVIDC_PPC_2); + break; + + default : + ReachedEnd = (TRUE); + } + + if (ReachedEnd) + break; + + Loop++; + } + while (TmdsClock == 0); + } + + // Default 1080p colorbar + else { + TmdsClock = XV_HdmiTx_SetStream(InstancePtr->HdmiTxPtr, + XVIDC_VM_1920x1080_60_P, XVIDC_CSF_RGB, XVIDC_BPC_8, XVIDC_PPC_2); + } + + return TmdsClock; +} + +/*****************************************************************************/ +/** +* +* This function set HDMI TX susbsystem stream reduced blanking parameters +* +* @param None. +* +* @return Calculated TMDS Clock +* +* @note None. +* +******************************************************************************/ +u32 XV_HdmiTxSs_SetStreamReducedBlanking(XV_HdmiTxSs *InstancePtr) +{ + u32 TmdsClock = 0; + + TmdsClock = XV_HdmiTx_SetStreamReducedBlanking(InstancePtr->HdmiTxPtr); + + return TmdsClock; +} + +/*****************************************************************************/ +/** +* +* This function returns the pointer to HDMI TX SS video stream +* +* @param InstancePtr pointer to XV_HdmiTxSs instance +* +* @return XVidC_VideoStream pointer +* +* @note None. +* +******************************************************************************/ +XVidC_VideoStream *XV_HdmiTxSs_GetVideoStream(XV_HdmiTxSs *InstancePtr) +{ + return (&InstancePtr->HdmiTxPtr->Stream.Video); +} + +/*****************************************************************************/ +/** +* +* This function Sets the HDMI TX SS video stream +* +* @param InstancePtr pointer to XV_HdmiTxSs instance +* @param +* +* @return XVidC_VideoStream pointer +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_SetVideoStream(XV_HdmiTxSs *InstancePtr, + XVidC_VideoStream VidStream) +{ + InstancePtr->HdmiTxPtr->Stream.Video = VidStream; +} + +/*****************************************************************************/ +/** +* +* This function Sets the HDMI TX SS video Identification code +* +* @param InstancePtr pointer to XV_HdmiTxSs instance +* @param SamplingRate Value +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_SetSamplingRate(XV_HdmiTxSs *InstancePtr, u8 SamplingRate) +{ + InstancePtr->SamplingRate = SamplingRate; +} + +/*****************************************************************************/ +/** +* +* This function Sets the HDMI TX SS video Identification code +* +* @param InstancePtr pointer to XV_HdmiTxSs instance +* @param InstancePtr VIC Flag Value +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_SetVideoIDCode(XV_HdmiTxSs *InstancePtr, u8 Vic) +{ + InstancePtr->HdmiTxPtr->Stream.Vic = Vic; +} + +/*****************************************************************************/ +/** +* +* This function Sets the HDMI TX SS video stream type +* +* @param InstancePtr pointer to XV_HdmiTxSs instance +* @param InstancePtr VIC Value 1:HDMI 0:DVI +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_SetVideoStreamType(XV_HdmiTxSs *InstancePtr, u8 StreamType) +{ + InstancePtr->HdmiTxPtr->Stream.IsHdmi = StreamType; +} + +/*****************************************************************************/ +/** +* +* This function Sets the HDMI TX SS video stream type +* +* @param InstancePtr pointer to XV_HdmiTxSs instance +* @param IsScrambled 1:IsScrambled 0: not Scrambled +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_SetVideoStreamScramblingFlag(XV_HdmiTxSs *InstancePtr, + u8 IsScrambled) +{ + InstancePtr->HdmiTxPtr->Stream.IsScrambled = IsScrambled; +} + +/*****************************************************************************/ +/** +* +* This function Sets the HDMI TX SS TMDS Cock Ratio +* +* @param InstancePtr pointer to XV_HdmiTxSs instance +* @param Ratio 0 - 1/10, 1 - 1/40 +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_SetTmdsClockRatio(XV_HdmiTxSs *InstancePtr, u8 Ratio) +{ + InstancePtr->HdmiTxPtr->Stream.TMDSClockRatio = Ratio; +} + +/*****************************************************************************/ +/** +* +* This function Sets the HDMI TX SS video Identification code +* +* @param InstancePtr pointer to XV_HdmiTxSs instance +* @param SamplingRate Value +* +* @return None. +* +* @note None. +* +******************************************************************************/ +u32 XV_HdmiTxSs_GetTmdsClockFreqHz(XV_HdmiTxSs *InstancePtr) +{ + return (InstancePtr->HdmiTxPtr->Stream.TMDSClock); +} + +/*****************************************************************************/ +/** +* +* This function detects connected sink is a HDMI 2.0/HDMI 1.4 sink device +* +* @param InstancePtr is a pointer to the XV_HdmiTxSs core instance. +* +* @return +* - XST_SUCCESS if HDMI 2.0 +* - XST_FAILURE if HDMI 1.4 +* +* @note None. +* +******************************************************************************/ +int XV_HdmiTxSs_DetectHdmi20(XV_HdmiTxSs *InstancePtr) +{ + return (XV_HdmiTx_DetectHdmi20(InstancePtr->HdmiTxPtr)); +} + +/*****************************************************************************/ +/** +* +* This function is called when HDMI TX SS TMDS clock changes +* +* @param None. +* +* @return None +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_RefClockChangeInit(XV_HdmiTxSs *InstancePtr) +{ + /* Assert HDMI TX reset */ + XV_HdmiTx_Reset(InstancePtr->HdmiTxPtr, TRUE); + + /* Clear variables */ + XV_HdmiTx_Clear(InstancePtr->HdmiTxPtr); +} + +/*****************************************************************************/ +/** +* +* This function prints the HDMI TX SS timing information +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_ReportTiming(XV_HdmiTxSs *InstancePtr) +{ + XV_HdmiTx_DebugInfo(InstancePtr->HdmiTxPtr); + xil_printf("Scrambled: %0d\n\r", + (XV_HdmiTx_IsStreamScrambled(InstancePtr->HdmiTxPtr))); + xil_printf("Sample rate: %0d\n\r", + (XV_HdmiTx_GetSampleRate(InstancePtr->HdmiTxPtr))); + xil_printf("Audio channels: %0d\n\r", + (XV_HdmiTx_GetAudioChannels(InstancePtr->HdmiTxPtr))); + print("\r\n"); + +} + +/*****************************************************************************/ +/** +* +* This function prints the HDMI TX SS subcore versions +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XV_HdmiTxSs_ReportSubcoreVersion(XV_HdmiTxSs *InstancePtr) +{ + u32 Data; + + if (InstancePtr->HdmiTxPtr) { + Data = XV_HdmiTx_GetVersion(InstancePtr->HdmiTxPtr); + xil_printf(" HDMI TX version : %02d.%02d (%04x)\n\r", + ((Data >> 24) & 0xFF), ((Data >> 16) & 0xFF), (Data & 0xFFFF)); + } + + if (InstancePtr->VtcPtr){ + Data = XVtc_GetVersion(InstancePtr->VtcPtr); + xil_printf(" VTC version : %02d.%02d (%04x)\n\r", + ((Data >> 24) & 0xFF), ((Data >> 16) & 0xFF), (Data & 0xFFFF)); + } + + if (InstancePtr->HdcpPtr){ + Data = XHdcp1x_GetVersion(InstancePtr->HdcpPtr); + xil_printf(" HDCP TX version : %02d.%02d (%04x)\n\r", + ((Data >> 24) & 0xFF), ((Data >> 16) & 0xFF), (Data & 0xFFFF)); + } +} + +/*****************************************************************************/ +/** +* +* This function enables the hdcp module +* +* @return +* XST_SUCCESS if successful. +* +* @note +* None. +* +******************************************************************************/ +void XV_HdmiTxSs_HdcpEnable(XV_HdmiTxSs *InstancePtr, u8 Enable) +{ + XV_HdmiTxSs *HdmiTxSsPtr = InstancePtr; + + if (Enable) { + /* Enable hdcp interface */ + XHdcp1x_Enable(HdmiTxSsPtr->HdcpPtr); + + /* Set the TX HDCP state to up */ + XHdcp1x_SetPhysicalState(HdmiTxSsPtr->HdcpPtr, TRUE); + } + else { + /* Set the TX HDCP state to down */ + XHdcp1x_SetPhysicalState(HdmiTxSsPtr->HdcpPtr, FALSE); + + /* Disable hdcp interface */ + XHdcp1x_Disable(HdmiTxSsPtr->HdcpPtr); + } +} + +/*****************************************************************************/ +/** +* +* This function polls the hdcp example module and determines if the video +* stream is encrypted. The traffic is encrypted if the encryption bit map +* is non-zero and the interface is authenticated. +* +* @return Truth value indicating encrypted (TRUE) or not (FALSE). +* +* @note +* This function is intended to be called from within the main loop of the +* software utilizing this module. +* +******************************************************************************/ +u8 XV_HdmiTxSs_HdcpPoll(XV_HdmiTxSs *InstancePtr) +{ + /* Locals */ + XV_HdmiTxSs *HdmiTxSsPtr = InstancePtr; + + /* Poll hdcp interface */ + XHdcp1x_Poll(HdmiTxSsPtr->HdcpPtr); + + /* Return */ + return (XHdcp1x_IsEncrypted(HdmiTxSsPtr->HdcpPtr)); +} + + +/*****************************************************************************/ +/** +* +* This function initiates HDCP authentication and enable encryption +* +* @return Truth value indicating encryption was enabled (TRUE) or not (FALSE). +* +* @note +* This function is intended to be called from within the main loop of the +* software utilizing this module. +* +******************************************************************************/ +u8 XV_HdmiTxSs_HdcpStart(XV_HdmiTxSs *InstancePtr) +{ + /* Locals */ + XV_HdmiTxSs *HdmiTxSsPtr = InstancePtr; + u8 retval = FALSE; + + if (XHdcp1x_TxIsAuthenticated(HdmiTxSsPtr->HdcpPtr)==0) + { + XHdcp1x_Authenticate(HdmiTxSsPtr->HdcpPtr); + retval = FALSE; + } + else + { + XHdcp1x_EnableEncryption(HdmiTxSsPtr->HdcpPtr,0x1); + retval = TRUE; + } + + return retval; +} + +/******************************************************************************/ +/** +* +* This function converts from microseconds to timer ticks +* +* @param TimeoutInUs the timeout to convert +* @param ClockFrequency the clock frequency to use in the conversion +* +* @return +* The number of "ticks" +* +* @note +* None. +* +******************************************************************************/ +static u32 XV_HdmiTxSs_HdcpTimerConvUsToTicks(u32 TimeoutInUs, + u32 ClockFrequency) +{ + u32 TimeoutFreq = 0; + u32 NumTicks = 0; + + /* Check for greater than one second */ + if (TimeoutInUs > 1000000ul) { + u32 NumSeconds = 0; + + /* Determine theNumSeconds */ + NumSeconds = (TimeoutInUs/1000000ul); + + /* Update theNumTicks */ + NumTicks = (NumSeconds*ClockFrequency); + + /* Adjust theTimeoutInUs */ + TimeoutInUs -= (NumSeconds*1000000ul); + } + + /* Convert TimeoutFreq to a frequency */ + TimeoutFreq = 1000; + TimeoutFreq *= 1000; + TimeoutFreq /= TimeoutInUs; + + /* Update NumTicks */ + NumTicks += ((ClockFrequency / TimeoutFreq) + 1); + + return (NumTicks); +} + +/*****************************************************************************/ +/** +* +* This function serves as the timer callback function +* +* @param CallBackRef the callback reference value +* @param TimerChannel the channel within the timer that expired +* +* @return +* void +* +* @note +* None +* +******************************************************************************/ +void XV_HdmiTxSs_HdcpTimerCallback(void* CallBackRef, u8 TimerChannel) +{ + XHdcp1x* HdcpPtr = CallBackRef; + + XHdcp1x_HandleTimeout(HdcpPtr); + return; +} + +/******************************************************************************/ +/** +* +* This function starts a timer on behalf of an hdcp interface +* +* @param InstancePtr the hdcp interface +* @param TimeoutInMs the timer duration in milliseconds +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XV_HdmiTxSs_HdcpTimerStart(const XHdcp1x* InstancePtr, u16 TimeoutInMs) +{ + XV_HdmiTxSs_SubCores *SubCorePtr; + XTmrCtr *TimerPtr; + u8 TimerChannel = 0; + u32 TimerOptions = 0; + u32 NumTicks = 0; + + SubCorePtr = XV_HdmiTxSs_GetSubSysStruct((void*)InstancePtr); + TimerPtr = &SubCorePtr->HdcpTimer; + + /* Determine NumTicks */ + NumTicks = XV_HdmiTxSs_HdcpTimerConvUsToTicks((TimeoutInMs*1000ul), + XPAR_CPU_CORE_CLOCK_FREQ_HZ); + + /* Stop it */ + XTmrCtr_Stop(TimerPtr, TimerChannel); + + /* Configure the callback */ + XTmrCtr_SetHandler(TimerPtr, &XV_HdmiTxSs_HdcpTimerCallback, + (void*) InstancePtr); + + /* Configure the timer options */ + TimerOptions = XTmrCtr_GetOptions(TimerPtr, TimerChannel); + TimerOptions |= XTC_DOWN_COUNT_OPTION; + TimerOptions |= XTC_INT_MODE_OPTION; + TimerOptions &= ~XTC_AUTO_RELOAD_OPTION; + XTmrCtr_SetOptions(TimerPtr, TimerChannel, TimerOptions); + + /* Set the timeout and start */ + XTmrCtr_SetResetValue(TimerPtr, TimerChannel, NumTicks); + XTmrCtr_Start(TimerPtr, TimerChannel); + + return (XST_SUCCESS); +} + + +/******************************************************************************/ +/** +* +* This function stops a timer on behalf of an hdcp interface +* +* @param InstancePtr the hdcp interface +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XV_HdmiTxSs_HdcpTimerStop(const XHdcp1x* InstancePtr) +{ + XV_HdmiTxSs_SubCores *SubCorePtr; + XTmrCtr *TimerPtr; + u8 TimerChannel = 0; + + SubCorePtr = XV_HdmiTxSs_GetSubSysStruct((void*)InstancePtr); + TimerPtr = &SubCorePtr->HdcpTimer; + + /* Stop it */ + XTmrCtr_Stop(TimerPtr, TimerChannel); + + return (XST_SUCCESS); +} + + +/******************************************************************************/ +/** +* +* This function busy waits for an interval on behalf of an hdcp interface +* +* @param InstancePtr the hdcp interface +* @param DelayInMs the delay duration in milliseconds +* +* @return +* XST_SUCCESS if successful +* +* @note +* None. +* +******************************************************************************/ +int XV_HdmiTxSs_HdcpTimerBusyDelay(const XHdcp1x* InstancePtr, u16 DelayInMs) +{ + XV_HdmiTxSs_SubCores *SubCorePtr; + XTmrCtr *TimerPtr; + u8 TimerChannel = 0; + u32 TimerOptions = 0; + u32 NumTicks = 0; + + SubCorePtr = XV_HdmiTxSs_GetSubSysStruct((void*)InstancePtr); + TimerPtr = &SubCorePtr->HdcpTimer; + + /* Determine NumTicks */ + NumTicks = XV_HdmiTxSs_HdcpTimerConvUsToTicks((DelayInMs*1000ul), + XPAR_CPU_CORE_CLOCK_FREQ_HZ); + + /* Stop it */ + XTmrCtr_Stop(TimerPtr, TimerChannel); + + /* Configure the timer options */ + TimerOptions = XTmrCtr_GetOptions(TimerPtr, TimerChannel); + TimerOptions |= XTC_DOWN_COUNT_OPTION; + TimerOptions &= ~XTC_INT_MODE_OPTION; + TimerOptions &= ~XTC_AUTO_RELOAD_OPTION; + XTmrCtr_SetOptions(TimerPtr, TimerChannel, TimerOptions); + + /* Set the timeout and start */ + XTmrCtr_SetResetValue(TimerPtr, TimerChannel, NumTicks); + XTmrCtr_Start(TimerPtr, TimerChannel); + + /* Wait until done */ + while (!XTmrCtr_IsExpired(TimerPtr, TimerChannel)); + + return (XST_SUCCESS); +} diff --git a/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss.h b/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss.h new file mode 100755 index 00000000..df9cb1ff --- /dev/null +++ b/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss.h @@ -0,0 +1,251 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xv_hdmitxss.h +* +* This is main header file of the Xilinx HDMI TX Subsystem driver +* +* HDMI Transmitter Subsystem Overview +* +* HDMI TX Subsystem is a collection of IP cores bounded together by software +* to provide an abstract view of the processing pipe. It hides all the +* complexities of programming the underlying cores from end user. +* +* Subsystem Driver Features +* +* HDMI Subsystem supports following features +* - AXI Stream Input/Output interface +* - 1, 2 or 4 pixel-wide video interface +* - 8/10/12/16 bits per component +* - RGB & YCbCr color space +* - Up to 4k2k 60Hz resolution at both Input and Output interface +* - Interlaced input support (1080i 50Hz/60Hz) + +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00         10/07/15 Initial release.
+
+* 
+* +******************************************************************************/ + +#ifndef HDMITXSS_H /**< prevent circular inclusions by using protection macros*/ +#define HDMITXSS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ +#include "xstatus.h" +#include "xintc.h" +#include "xvidc.h" +#include "xvidc_edid.h" +#include "xv_hdmitx.h" +#include "xvtc.h" +#include "xtmrctr.h" +#include "xhdcp1x.h" + +#define XV_HDMITXSS_HDCP_KEYSEL 0x00u + + +/****************************** Type Definitions ******************************/ +/** @name Handler Types +* @{ +*/ +/** +* These constants specify different types of handler and used to differentiate +* interrupt requests from peripheral. +*/ +typedef enum { + XV_HDMITXSS_HANDLER_CONNECT = 1, /**< Handler for connect */ + XV_HDMITXSS_HANDLER_VS, /**< Handler for vsync */ + XV_HDMITXSS_HANDLER_STREAM_DOWN, /**< Handler for stream down */ + XV_HDMITXSS_HANDLER_STREAM_UP /**< Handler for stream up */ +} XV_HdmiTxSs_HandlerType; +/*@}*/ + +/** + * Sub-Core Configuration Table + */ +typedef struct +{ + u16 IsPresent; /**< Flag to indicate if sub-core is present in the design*/ + u16 DeviceId; /**< Device ID of the sub-core */ + u32 AddrOffset; /**< sub-core offset from subsystem base address */ +}XV_HdmiTxSs_SubCore; + +/** + * Video Processing Subsystem configuration structure. + * Each subsystem device should have a configuration structure associated + * that defines the MAX supported sub-cores within subsystem + */ + +typedef struct +{ + u16 DeviceId; /**< DeviceId is the unique ID of the device */ + u32 BaseAddress; /**< BaseAddress is the physical base address of the + subsystem address range */ + u32 HighAddress; /**< HighAddress is the physical MAX address of the + subsystem address range */ + u8 MaxPixelsPerClock; /**< Maximum Supported Pixel per Clock */ + u8 MaxBitsPerPixel; /**< Maximum Supported Color Depth */ + XV_HdmiTxSs_SubCore HdcpTimer; /**< Sub-core instance configuration */ + XV_HdmiTxSs_SubCore Hdcp; /**< Sub-core instance configuration */ + XV_HdmiTxSs_SubCore HdmiTx; /**< Sub-core instance configuration */ + XV_HdmiTxSs_SubCore Vtc; /**< Sub-core instance configuration */ +} XV_HdmiTxSs_Config; + +/** +* Callback type for interrupt. +* +* @param CallbackRef is a callback reference passed in by the upper +* layer when setting the callback functions, and passed back to +* the upper layer when the callback is invoked. +* +* @return None. +* +* @note None. +* +*/ +typedef void (*XV_HdmiTxSs_Callback)(void *CallbackRef); + +/** +* The XVprocss driver instance data. The user is required to allocate a variable +* of this type for every XVprocss device in the system. A pointer to a variable +* of this type is then passed to the driver API functions. +*/ +typedef struct +{ + XV_HdmiTxSs_Config Config; /**< Hardware configuration */ + u32 IsReady; /**< Device and the driver instance are initialized */ + + XTmrCtr *HdcpTimerPtr; /**< handle to sub-core driver instance */ + XHdcp1x *HdcpPtr; /**< handle to sub-core driver instance */ + XV_HdmiTx *HdmiTxPtr; /**< handle to sub-core driver instance */ + XVtc *VtcPtr; /**< handle to sub-core driver instance */ + + /* Callbacks */ + XV_HdmiTxSs_Callback ConnectCallback; /**< Callback for connect + * event interrupt */ + void *ConnectRef; /**< To be passed to the connect + * interrupt callback */ + + XV_HdmiTxSs_Callback VsCallback; /**< Callback for Vsync event interrupt */ + void *VsRef; /**< To be passed to the Vsync interrupt callback */ + + XV_HdmiTxSs_Callback StreamDownCallback; /**< Callback for stream + * down callback */ + void *StreamDownRef; /**< To be passed to the stream down callback */ + + XV_HdmiTxSs_Callback StreamUpCallback; /**< Callback for stream up + * callback */ + void *StreamUpRef; /**< To be passed to the stream up callback */ + + /**< Scratch pad */ + u8 SamplingRate; /**< HDMI TX Sampling rate */ + u8 IsStreamConnected; /**< HDMI TX Stream Connected */ + u8 AudioEnabled; /**< HDMI TX Audio Enabled */ + u8 AudioMute; /**< HDMI TX Audio Mute */ + u8 AudioChannels; /**< Number of Audio Channels */ + + XVidC_DelayHandler UserTimerWaitUs; /**< Custom user function for + delay/sleep. */ + void *UserTimerPtr; /**< Pointer to a timer instance + used by the custom user + delay/sleep function. */ +} XV_HdmiTxSs; + +/************************** Macros Definitions *******************************/ + +/************************** Function Prototypes ******************************/ +XV_HdmiTxSs_Config *XV_HdmiTxSs_LookupConfig(u32 DeviceId); +void XV_HdmiTxSs_ReportCoreInfo(XV_HdmiTxSs *InstancePtr); +void XV_HdmiTxSs_SetUserTimerHandler(XV_HdmiTxSs *InstancePtr, + XVidC_DelayHandler CallbackFunc, void *CallbackRef); +void XV_HdmiTxSS_HdmiTxIntrHandler(XV_HdmiTxSs *InstancePtr); +void XV_HdmiTxSS_HdcpIntrHandler(XV_HdmiTxSs *InstancePtr); +void XV_HdmiTxSS_HdcpTimerIntrHandler(XV_HdmiTxSs *InstancePtr); +int XV_HdmiTxSs_CfgInitialize(XV_HdmiTxSs *InstancePtr, + XV_HdmiTxSs_Config *CfgPtr, + u32 EffectiveAddr); +void XV_HdmiTxSs_Start(XV_HdmiTxSs *InstancePtr); +void XV_HdmiTxSs_Stop(XV_HdmiTxSs *InstancePtr); +void XV_HdmiTxSs_Reset(XV_HdmiTxSs *InstancePtr); +int XV_HdmiTxSs_SetCallback(XV_HdmiTxSs *InstancePtr, + u32 HandlerType, + void *CallbackFuncPtr, + void *CallbackRef); +int XV_HdmiTxSs_ReadEdid(XV_HdmiTxSs *InstancePtr, u8 *BufferPtr); +void XV_HdmiTxSs_ShowEdid(XV_HdmiTxSs *InstancePtr); +void XV_HdmiTxSs_StreamStart(XV_HdmiTxSs *InstancePtr); +void XV_HdmiTxSs_SendAudioInfoframe(XV_HdmiTxSs *InstancePtr, void *AuxPtr); +void XV_HdmiTxSs_SetAudioChannels(XV_HdmiTxSs *InstancePtr, u8 AudioChannels); +void XV_HdmiTxSs_AudioMute(XV_HdmiTxSs *InstancePtr, u8 Enable); +u32 XV_HdmiTxSs_SetStream(XV_HdmiTxSs *InstancePtr, + XVidC_VideoMode VideoMode, + XVidC_ColorFormat ColorFormat, + XVidC_ColorDepth Bpc, + XVidC_PixelsPerClock Ppc); +u32 XV_HdmiTxSs_SetStreamReducedBlanking(XV_HdmiTxSs *InstancePtr); +XVidC_VideoStream *XV_HdmiTxSs_GetVideoStream(XV_HdmiTxSs *InstancePtr); +void XV_HdmiTxSs_SetVideoStream(XV_HdmiTxSs *InstancePtr, + XVidC_VideoStream VidStream); +void XV_HdmiTxSs_SetSamplingRate(XV_HdmiTxSs *InstancePtr, u8 SamplingRate); +void XV_HdmiTxSs_SetVideoIDCode(XV_HdmiTxSs *InstancePtr, u8 Vic); +void XV_HdmiTxSs_SetVideoStreamType(XV_HdmiTxSs *InstancePtr, u8 StreamType); +void XV_HdmiTxSs_SetVideoStreamScramblingFlag(XV_HdmiTxSs *InstancePtr, + u8 IsScrambled); +void XV_HdmiTxSs_SetTmdsClockRatio(XV_HdmiTxSs *InstancePtr, u8 Ratio); +u32 XV_HdmiTxSs_GetTmdsClockFreqHz(XV_HdmiTxSs *InstancePtr); +int XV_HdmiTxSs_DetectHdmi20(XV_HdmiTxSs *InstancePtr); +void XV_HdmiTxSs_RefClockChangeInit(XV_HdmiTxSs *InstancePtr); +void XV_HdmiTxSs_ReportTiming(XV_HdmiTxSs *InstancePtr); +void XV_HdmiTxSs_ReportSubcoreVersion(XV_HdmiTxSs *InstancePtr); +void XV_HdmiTxSs_HdcpEnable(XV_HdmiTxSs *InstancePtr, u8 Enable); +u8 XV_HdmiTxSs_HdcpPoll(XV_HdmiTxSs *InstancePtr); +u8 XV_HdmiTxSs_HdcpStart(XV_HdmiTxSs *InstancePtr); +void XV_HdmiTxSs_HdcpTimerCallback(void *CallBackRef, u8 TimerChannel); +int XV_HdmiTxSs_HdcpTimerStart(const XHdcp1x *InstancePtr, u16 TimeoutInMs); +int XV_HdmiTxSs_HdcpTimerStop(const XHdcp1x *InstancePtr); +int XV_HdmiTxSs_HdcpTimerBusyDelay(const XHdcp1x *InstancePtr, u16 DelayInMs); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss_coreinit.c b/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss_coreinit.c new file mode 100755 index 00000000..1e52c0e4 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss_coreinit.c @@ -0,0 +1,326 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xv_hdmitxss_coreinit.c +* @addtogroup v_hdmitxss +* @{ +* @details + +* HDMI TX Subsystem Sub-Cores initialization +* The functions in this file provides an abstraction from the initialization +* sequence for included sub-cores. Subsystem is assigned an address and range +* on the axi-lite interface. This address space is condensed where-in each +* sub-core is at a fixed offset from the subsystem base address. For processor +* to be able to access the sub-core this offset needs to be transalted into a +* absolute address within the subsystems addressable range +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00         10/07/15 Initial release.
+
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xv_hdmitxss_coreinit.h" + +/************************** Constant Definitions *****************************/ + +/************************** Function Prototypes ******************************/ +static int XV_HdmiTxSs_ComputeSubcoreAbsAddr(u32 SubSys_BaseAddr, + u32 SubSys_HighAddr, + u32 SubCore_Offset, + u32 *SubCore_BaseAddr); + +/*****************************************************************************/ +/** +* This function computes the subcore absolute address on axi-lite interface +* Subsystem is mapped at an absolute address and all included sub-cores are +* at pre-defined offset from the subsystem base address. To access the subcore +* register map from host CPU an absolute address is required. +* Subsystem has address range of 1MB (0x00000-0xFFFFF) +* +* @param SubSys_BaseAddr is the base address of the the Subsystem instance +* @param SubSys_HighAddr is the max address of the Subsystem instance +* @param SubCore_Offset is the offset of the specified core +* @param SubCore_BaseAddr is the computed absolute base address of the subcore +* +* @return XST_SUCCESS if base address computation is successful and within +* subsystem address range else XST_FAILURE +* +******************************************************************************/ +static int XV_HdmiTxSs_ComputeSubcoreAbsAddr(u32 SubSys_BaseAddr, + u32 SubSys_HighAddr, + u32 SubCore_Offset, + u32 *SubCore_BaseAddr) +{ + int Status; + u32 AbsAddr; + + AbsAddr = SubSys_BaseAddr | SubCore_Offset; + if ((AbsAddr>=SubSys_BaseAddr) && (AbsAddrHdmiTxPtr) { + /* Get core configuration */ + xdbg_printf(XDBG_DEBUG_GENERAL," ->Initializing HDMI TX core.... \r\n"); + ConfigPtr = XV_HdmiTx_LookupConfig(HdmiTxSsPtr->Config.HdmiTx.DeviceId); + if (ConfigPtr == NULL) { + xil_printf("HDMITXSS ERR:: HDMI TX device not found\r\n"); + return(XST_FAILURE); + } + + /* Compute absolute base address */ + AbsAddr = 0; + Status = XV_HdmiTxSs_ComputeSubcoreAbsAddr(HdmiTxSsPtr->Config.BaseAddress, + HdmiTxSsPtr->Config.HighAddress, + HdmiTxSsPtr->Config.HdmiTx.AddrOffset, + &AbsAddr); + + if (Status != XST_SUCCESS) { + xil_printf("HDMITXSS ERR:: HDMI TX core base address (0x%x) \ + invalid %d\r\n", AbsAddr); + return(XST_FAILURE); + } + + /* Initialize core */ + Status = XV_HdmiTx_CfgInitialize(HdmiTxSsPtr->HdmiTxPtr, + ConfigPtr, + AbsAddr); + + if (Status != XST_SUCCESS) { + xil_printf("HDMITXSS ERR:: HDMI TX Initialization failed\r\n"); + return(XST_FAILURE); + } + } + return(XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* This function initializes the included sub-core to it's static configuration +* +* @param HdmiTxSsPtr is a pointer to the Subsystem instance to be worked on. +* +* @return XST_SUCCESS/XST_FAILURE +* +******************************************************************************/ +int XV_HdmiTxSs_SubcoreInitVtc(XV_HdmiTxSs *HdmiTxSsPtr) +{ + int Status; + u32 AbsAddr; + XVtc_Config *ConfigPtr; + + if (HdmiTxSsPtr->VtcPtr) { + /* Get core configuration */ + xdbg_printf(XDBG_DEBUG_GENERAL," ->Initializing VTC core.... \r\n"); + ConfigPtr = XVtc_LookupConfig(HdmiTxSsPtr->Config.Vtc.DeviceId); + if (ConfigPtr == NULL) { + xil_printf("HDMITXSS ERR:: VTC device not found\r\n"); + return(XST_FAILURE); + } + + /* Compute absolute base address */ + AbsAddr = 0; + Status = XV_HdmiTxSs_ComputeSubcoreAbsAddr(HdmiTxSsPtr->Config.BaseAddress, + HdmiTxSsPtr->Config.HighAddress, + HdmiTxSsPtr->Config.Vtc.AddrOffset, + &AbsAddr); + + if (Status != XST_SUCCESS) { + xil_printf("HDMITXSS ERR:: CSC core base address (0x%x) \ + invalid %d\r\n", AbsAddr); + return(XST_FAILURE); + } + + /* Initialize core */ + Status = XVtc_CfgInitialize(HdmiTxSsPtr->VtcPtr, + ConfigPtr, + AbsAddr); + + if (Status != XST_SUCCESS) { + xil_printf("HDMITXSS ERR:: VTC Initialization failed\r\n"); + return(XST_FAILURE); + } + } + return(XST_SUCCESS); +} + + +/*****************************************************************************/ +/** +* This function initializes the included sub-core to it's static configuration +* +* @param HdmiTxSsPtr is a pointer to the Subsystem instance to be worked on. +* +* @return XST_SUCCESS/XST_FAILURE +* +******************************************************************************/ +int XV_HdmiTxSs_SubcoreInitHdcpTimer(XV_HdmiTxSs *HdmiTxSsPtr) +{ + int Status; + u32 AbsAddr; + XTmrCtr_Config *ConfigPtr; + + if (HdmiTxSsPtr->HdcpTimerPtr) { + /* Get core configuration */ + xdbg_printf(XDBG_DEBUG_GENERAL," ->Initializing AXI Timer core.... \r\n"); + ConfigPtr = XTmrCtr_LookupConfig(HdmiTxSsPtr->Config.HdcpTimer.DeviceId); + if (ConfigPtr == NULL) { + xil_printf("HDMITXSS ERR:: AXIS Timer device not found\r\n"); + return(XST_FAILURE); + } + + /* Compute absolute base address */ + AbsAddr = 0; + Status = XV_HdmiTxSs_ComputeSubcoreAbsAddr(HdmiTxSsPtr->Config.BaseAddress, + HdmiTxSsPtr->Config.HighAddress, + HdmiTxSsPtr->Config.HdcpTimer.AddrOffset, + &AbsAddr); + + if (Status != XST_SUCCESS) { + xil_printf("HDMITXSS ERR:: AXI Timer core base address (0x%x) \ + invalid %d\r\n", AbsAddr); + return(XST_FAILURE); + } + + /* Setup the instance */ + memset(HdmiTxSsPtr->HdcpTimerPtr, 0, sizeof(XTmrCtr)); + + /* Initialize core */ + XTmrCtr_CfgInitialize(HdmiTxSsPtr->HdcpTimerPtr, ConfigPtr, AbsAddr); + Status = XTmrCtr_InitHw(HdmiTxSsPtr->HdcpTimerPtr); + + /* Initialize the hdcp timer functions */ + XHdcp1x_SetTimerStart(&XV_HdmiTxSs_HdcpTimerStart); + XHdcp1x_SetTimerStop(&XV_HdmiTxSs_HdcpTimerStop); + XHdcp1x_SetTimerDelay(&XV_HdmiTxSs_HdcpTimerBusyDelay); + + if (Status != XST_SUCCESS) { + xil_printf("HDMITXSS ERR:: AXI Timer Initialization failed\r\n"); + return(XST_FAILURE); + } + } + return(XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* This function initializes the included sub-core to it's static configuration +* +* @param HdmiTxSsPtr is a pointer to the Subsystem instance to be worked on. +* +* @return XST_SUCCESS/XST_FAILURE +* +******************************************************************************/ +int XV_HdmiTxSs_SubcoreInitHdcp(XV_HdmiTxSs *HdmiTxSsPtr) +{ + int Status; + u32 AbsAddr; + XHdcp1x_Config *ConfigPtr; + + if (HdmiTxSsPtr->HdcpPtr){ + /* Get core configuration */ + xdbg_printf(XDBG_DEBUG_GENERAL," ->Initializing HDCP core.... \r\n"); + ConfigPtr = XHdcp1x_LookupConfig(HdmiTxSsPtr->Config.Hdcp.DeviceId); + if (ConfigPtr == NULL){ + xil_printf("HDMITXSS ERR:: HDCP device not found\r\n"); + return(XST_FAILURE); + } + + /* Compute absolute base address */ + AbsAddr = 0; + Status = XV_HdmiTxSs_ComputeSubcoreAbsAddr(HdmiTxSsPtr->Config.BaseAddress, + HdmiTxSsPtr->Config.HighAddress, + HdmiTxSsPtr->Config.Hdcp.AddrOffset, + &AbsAddr); + + if (Status != XST_SUCCESS){ + xil_printf("HDMITXSS ERR:: HDCP core base address (0x%x) invalid %d\r\n", + AbsAddr); + return(XST_FAILURE); + } + + /* Initialize core */ + void *PhyIfPtr = HdmiTxSsPtr->HdmiTxPtr; + + Status = XHdcp1x_CfgInitialize(HdmiTxSsPtr->HdcpPtr, + ConfigPtr, + PhyIfPtr, + AbsAddr); + + /* Self-test the hdcp interface */ + if (XHdcp1x_SelfTest(HdmiTxSsPtr->HdcpPtr) != XST_SUCCESS) { + Status = XST_FAILURE; + } + + if (Status != XST_SUCCESS) { + xil_printf("HDMITXSS ERR:: HDCP Initialization failed\r\n"); + return(XST_FAILURE); + } + + XHdcp1x_SetKeySelect(HdmiTxSsPtr->HdcpPtr, XV_HDMITXSS_HDCP_KEYSEL); + } + return(XST_SUCCESS); +} + +/** @} */ diff --git a/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss_coreinit.h b/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss_coreinit.h new file mode 100755 index 00000000..3b74c007 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss_coreinit.h @@ -0,0 +1,79 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xv_hdmitxss_coreinit.h +* @addtogroup v_hdmitxss +* @{ +* @details +* +* This header file contains the hdmi tx subsystem sub-cores +* initialization routines and helper functions. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00         10/07/15 Initial release.
+
+* 
+* +******************************************************************************/ +#ifndef XV_HDMITXSS_COREINIT_H__ /* prevent circular inclusions */ +#define XV_HDMITXSS_COREINIT_H__ /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif +#include +#include +#include "xv_hdmitxss.h" +#include "xv_hdmitx.h" +#include "xvtc.h" +#include "xtmrctr.h" +#include "xhdcp1x.h" +/************************** Constant Definitions *****************************/ + +/************************** Function Prototypes ******************************/ +int XV_HdmiTxSs_SubcoreInitHdmiTx(XV_HdmiTxSs *HdmiTxSsPtr); +int XV_HdmiTxSs_SubcoreInitVtc(XV_HdmiTxSs *HdmiTxSsPtr); +int XV_HdmiTxSs_SubcoreInitHdcpTimer(XV_HdmiTxSs *HdmiTxSsPtr); +int XV_HdmiTxSs_SubcoreInitHdcp(XV_HdmiTxSs *HdmiTxSsPtr); + +#ifdef __cplusplus +} +#endif + +#endif +/** @} */ diff --git a/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss_g.c b/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss_g.c new file mode 100755 index 00000000..bf882ed4 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss_g.c @@ -0,0 +1,105 @@ + +/******************************************************************* +* +* CAUTION: This file is automatically generated by HSI. +* Version: +* DO NOT EDIT. +* +* Copyright (C) 2010-2015 Xilinx, Inc. All Rights Reserved.* +*Permission is hereby granted, free of charge, to any person obtaining a copy +*of this software and associated documentation files (the Software), to deal +*in the Software without restriction, including without limitation the rights +*to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +*copies of the Software, and to permit persons to whom the Software is +*furnished to do so, subject to the following conditions: +* +*The above copyright notice and this permission notice shall be included in +*all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +*(a) running on a Xilinx device, or +*(b) that interact with a Xilinx device through a bus or interconnect. +* +*THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +*IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +*FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +*XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +*WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +*OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +* +*Except as contained in this notice, the name of the Xilinx shall not be used +*in advertising or otherwise to promote the sale, use or other dealings in +*this Software without prior written authorization from Xilinx. +* + +* +* Description: Driver configuration +* +*******************************************************************/ + +#include "xparameters.h" +#include "xv_hdmitxss.h" + +/* +* List of Sub-cores included in the subsystem +* Sub-core device id will be set by its driver in xparameters.h +* Excluded sub-core device id is set to 255 +* Excluded sub-core baseaddr is set to 0xFFFFFFFF +*/ + +#ifndef XPAR_V_HDMI_TX_SS_0_AXI_TIMER_DEVICE_ID +#define XPAR_V_HDMI_TX_SS_0_AXI_TIMER_PRESENT 0 +#define XPAR_V_HDMI_TX_SS_0_AXI_TIMER_DEVICE_ID 255 +#define XPAR_V_HDMI_TX_SS_0_AXI_TIMER_BASEADDR 0xFFFFFFFF +#endif + +#ifndef XPAR_V_HDMI_TX_SS_0_HDCP_1_4_DEVICE_ID +#define XPAR_V_HDMI_TX_SS_0_HDCP_1_4_PRESENT 0 +#define XPAR_V_HDMI_TX_SS_0_HDCP_1_4_DEVICE_ID 255 +#define XPAR_V_HDMI_TX_SS_0_HDCP_1_4_BASEADDR 0xFFFFFFFF +#endif + +#ifndef XPAR_V_HDMI_TX_SS_0_V_HDMI_TX_DEVICE_ID +#define XPAR_V_HDMI_TX_SS_0_V_HDMI_TX_PRESENT 0 +#define XPAR_V_HDMI_TX_SS_0_V_HDMI_TX_DEVICE_ID 255 +#define XPAR_V_HDMI_TX_SS_0_V_HDMI_TX_BASEADDR 0xFFFFFFFF +#endif + +#ifndef XPAR_V_HDMI_TX_SS_0_V_TC_DEVICE_ID +#define XPAR_V_HDMI_TX_SS_0_V_TC_PRESENT 0 +#define XPAR_V_HDMI_TX_SS_0_V_TC_DEVICE_ID 255 +#define XPAR_V_HDMI_TX_SS_0_V_TC_BASEADDR 0xFFFFFFFF +#endif + + +XV_HdmiTxSs_Config XV_HdmiTxSs_ConfigTable[] = +{ + { + XPAR_V_HDMI_TX_SS_0_DEVICE_ID, + XPAR_V_HDMI_TX_SS_0_BASEADDR, + XPAR_V_HDMI_TX_SS_0_HIGHADDR, + XPAR_V_HDMI_TX_SS_0_INPUT_PIXELS_PER_CLOCK, + XPAR_V_HDMI_TX_SS_0_MAX_BITS_PER_COMPONENT, + + { + XPAR_V_HDMI_TX_SS_0_AXI_TIMER_0_PRESENT, + XPAR_V_HDMI_TX_SS_0_AXI_TIMER_0_DEVICE_ID, + XPAR_V_HDMI_TX_SS_0_AXI_TIMER_0_BASEADDR + }, + { + XPAR_V_HDMI_TX_SS_0_HDCP_0_PRESENT, + XPAR_V_HDMI_TX_SS_0_HDCP_0_DEVICE_ID, + XPAR_V_HDMI_TX_SS_0_HDCP_0_BASEADDR + }, + { + XPAR_V_HDMI_TX_SS_0_V_HDMI_TX_PRESENT, + XPAR_V_HDMI_TX_SS_0_V_HDMI_TX_DEVICE_ID, + XPAR_V_HDMI_TX_SS_0_V_HDMI_TX_BASEADDR + }, + { + XPAR_V_HDMI_TX_SS_0_V_TC_PRESENT, + XPAR_V_HDMI_TX_SS_0_V_TC_DEVICE_ID, + XPAR_V_HDMI_TX_SS_0_V_TC_BASEADDR + }, + } +}; diff --git a/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss_sinit.c b/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss_sinit.c new file mode 100755 index 00000000..316be037 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/v_hdmitxss/src/xv_hdmitxss_sinit.c @@ -0,0 +1,97 @@ +/****************************************************************************** +* +* Copyright (C) 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xv_hdmitxss_sinit.c +* @addtogroup v_hdmitxss +* @{ +* @details +* +* This file contains the implementation of the HDMI TX Subsystem +* driver's static initialization functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ---- -------- -------------------------------------------------------
+* 1.00         10/07/15 Initial release.
+
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xparameters.h" +#include "xv_hdmitxss.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +extern XV_HdmiTxSs_Config XV_HdmiTxSs_ConfigTable[]; + +/*****************************************************************************/ +/** +* This function looks for the device configuration based on the unique device +* ID. The table XV_HdmiTxSs_ConfigTable[] contains the configuration information +* for each instance of the 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 +* +*******************************************************************************/ +XV_HdmiTxSs_Config* XV_HdmiTxSs_LookupConfig(u32 DeviceId) +{ + XV_HdmiTxSs_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0U; Index < (u32)XPAR_XV_HDMITXSS_NUM_INSTANCES; Index++) { + if (XV_HdmiTxSs_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XV_HdmiTxSs_ConfigTable[Index]; + break; + } + } + return (CfgPtr); +} +/** @} */