diff options
author | Rohit Consul <rohitco@xilinx.com> | 2017-05-05 11:44:18 -0700 |
---|---|---|
committer | Jeffrey Mouroux <jmouroux@xilinx.com> | 2017-06-28 11:16:02 -0700 |
commit | 7290bf423f13ec6a996b443160bfd4a1f9629deb (patch) | |
tree | ebe589e94ab073df1ac419b09a52cb75cabdeef1 | |
parent | d38208141cf2590ac864ff58afd18e3e8a417cd5 (diff) | |
download | linux-7290bf423f13ec6a996b443160bfd4a1f9629deb.tar.gz |
phy: xilinx-vphy: Initial release of xilinx video phy soft IP driver
Xilinx Video Phy implements the physical layer for enabling the plug-and-play
connectivity with HDMI MAC transmit and receive subsystems.
Driver is being released in staging area and is in experimental state.
Signed-off-by: Rohit Consul <rohitco@xilinx.com>
29 files changed, 16468 insertions, 0 deletions
diff --git a/drivers/staging/xilinx/hdmi/include/linux/phy/phy-vphy.h b/drivers/staging/xilinx/hdmi/include/linux/phy/phy-vphy.h new file mode 100644 index 00000000000000..e6681f9a9e6a99 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/include/linux/phy/phy-vphy.h @@ -0,0 +1,52 @@ +/* + * Xilinx VPHY header + * + * Copyright (C) 2016-2017 Xilinx, Inc. + * + * Author: Leon Woestenberg <leon@sidebranch.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef _PHY_VPHY_H_ +#define _PHY_VPHY_H_ + +/* @TODO change directory name on production release */ +#include "xvphy.h" + +struct phy; + +/* VPHY is built (either as module or built-in) */ +#if defined(CONFIG_PHY_XILINX_VPHY) + +extern XVphy *xvphy_get_xvphy(struct phy *phy); +extern void xvphy_mutex_lock(struct phy *phy); +extern void xvphy_mutex_unlock(struct phy *phy); +extern int xvphy_do_something(struct phy *phy); + +/* VPHY is not compiled in, make sure RX and TX fail */ +#else + +static inline XVphy *xvphy_get_xvphy(struct phy *phy) +{ + return NULL; +} + +static inline void xvphy_mutex_lock(struct phy *phy) {} +static inline void xvphy_mutex_unlock(struct phy *phy) {} + +static inline int xvphy_do_something(struct phy *phy) +{ + return -ENODEV; +} + +#endif /* (defined(CONFIG_PHY_XILINX_VPHY)) */ + +#endif /* _PHY_VPHY_H_ */ diff --git a/drivers/staging/xilinx/hdmi/include/linux/phy/xvphy.h b/drivers/staging/xilinx/hdmi/include/linux/phy/xvphy.h new file mode 100644 index 00000000000000..ac3647b0771ea3 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/include/linux/phy/xvphy.h @@ -0,0 +1,846 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy.h + * + * The Xilinx Video PHY (VPHY) driver. This driver supports the Xilinx Video PHY + * IP core. + * Version 1.0 supports: + * - GTXE2 and GTHE3 GT types. + * - DisplayPort and HDMI protocols. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 10/19/15 Initial release. + * 1.1 gm 02/01/16 Added EAST, WEST, PLL0 and PLL1 definitions + * for GTPE2. + * Added more events to XVphy_LogEvent definitions + * Added TxBufferBypass in XVphy_Config structure + * Added XVphy_SetDefaultPpc and XVphy_SetPpc functions + * als Added XVphy_GetLineRateHz function. + * 1.2 gm Added HdmiFastSwitch in XVphy_Config + * Changed EffectiveAddr datatype in XVphy_CfgInitialize + * to UINTPTR + * Added log events for debugging + * 1.2 gm 11/11/19 Added TransceiverWidth in XVphy_Config + * 1.4 gm 29/11/16 Moved internally used APIs to xvphy_i.c/h + * Added preprocessor directives for sw footprint reduction + * Made debug log optional (can be disabled via makefile) + * Added ERR_IRQ type_defs (not for official use for + * Xilinx debugging) + * Added transceiver width, AXIlite clk frequency and + * err_irq in XVphy_Config + * </pre> + * +*******************************************************************************/ + +#ifndef XVPHY_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XVPHY_H_ + +#if !defined(XV_CONFIG_LOG_VPHY_DISABLE) && !defined(XV_CONFIG_LOG_DISABLE_ALL) +#define XV_VPHY_LOG_ENABLE +#endif + +/******************************* Include Files ********************************/ + +#include "xil_assert.h" +#include "xvphy_hw.h" +#include "xil_printf.h" +#include "xvidc.h" +//#include "xvphy_dp.h" + +/****************************** Type Definitions ******************************/ + +/* This typedef enumerates the different GT types available. */ +typedef enum { + XVPHY_GT_TYPE_GTXE2 = 1, + XVPHY_GT_TYPE_GTHE2 = 2, + XVPHY_GT_TYPE_GTPE2 = 3, + XVPHY_GT_TYPE_GTHE3 = 4, + XVPHY_GT_TYPE_GTHE4 = 5, +} XVphy_GtType; + +/** + * This typedef enumerates the various protocols handled by the Video PHY + * controller (VPHY). + */ +typedef enum { + XVPHY_PROTOCOL_DP = 0, + XVPHY_PROTOCOL_HDMI, + XVPHY_PROTOCOL_NONE +} XVphy_ProtocolType; + +/* This typedef enumerates is used to specify RX/TX direction information. */ +typedef enum { + XVPHY_DIR_RX = 0, + XVPHY_DIR_TX +} XVphy_DirectionType; + +/** + * This typedef enumerates the list of available interrupt handler types. The + * values are used as parameters to the XVphy_SetIntrHandler function. + */ +typedef enum { + XVPHY_INTR_HANDLER_TYPE_TXRESET_DONE = XVPHY_INTR_TXRESETDONE_MASK, + XVPHY_INTR_HANDLER_TYPE_RXRESET_DONE = XVPHY_INTR_RXRESETDONE_MASK, + XVPHY_INTR_HANDLER_TYPE_CPLL_LOCK = XVPHY_INTR_CPLL_LOCK_MASK, + XVPHY_INTR_HANDLER_TYPE_QPLL_LOCK = XVPHY_INTR_QPLL_LOCK_MASK, + XVPHY_INTR_HANDLER_TYPE_QPLL0_LOCK = XVPHY_INTR_QPLL_LOCK_MASK, + XVPHY_INTR_HANDLER_TYPE_TXALIGN_DONE = XVPHY_INTR_TXALIGNDONE_MASK, + XVPHY_INTR_HANDLER_TYPE_QPLL1_LOCK = XVPHY_INTR_QPLL1_LOCK_MASK, + XVPHY_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE = + XVPHY_INTR_TXCLKDETFREQCHANGE_MASK, + XVPHY_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE = + XVPHY_INTR_RXCLKDETFREQCHANGE_MASK, + XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT = XVPHY_INTR_TXTMRTIMEOUT_MASK, + XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT = XVPHY_INTR_RXTMRTIMEOUT_MASK, +} XVphy_IntrHandlerType; + +/** + * This typedef enumerates the list of available hdmi handler types. The + * values are used as parameters to the XVphy_SetHdmiCallback function. + */ +typedef enum { + XVPHY_HDMI_HANDLER_TXINIT = 1, /**< TX init handler. */ + XVPHY_HDMI_HANDLER_TXREADY, /**< TX ready handler. */ + XVPHY_HDMI_HANDLER_RXINIT, /**< RX init handler. */ + XVPHY_HDMI_HANDLER_RXREADY /**< RX ready handler. */ +} XVphy_HdmiHandlerType; + +/** + * This typedef enumerates the different PLL types for a given GT channel. + */ +typedef enum { + XVPHY_PLL_TYPE_CPLL = 1, + XVPHY_PLL_TYPE_QPLL = 2, + XVPHY_PLL_TYPE_QPLL0 = 3, + XVPHY_PLL_TYPE_QPLL1 = 4, + XVPHY_PLL_TYPE_PLL0 = 5, + XVPHY_PLL_TYPE_PLL1 = 6, + XVPHY_PLL_TYPE_UNKNOWN = 7, +} XVphy_PllType; + +/** + * This typedef enumerates the available channels. + */ +typedef enum { + XVPHY_CHANNEL_ID_CH1 = 1, + XVPHY_CHANNEL_ID_CH2 = 2, + XVPHY_CHANNEL_ID_CH3 = 3, + XVPHY_CHANNEL_ID_CH4 = 4, + XVPHY_CHANNEL_ID_CMN0 = 5, + XVPHY_CHANNEL_ID_CMN1 = 6, + XVPHY_CHANNEL_ID_CHA = 7, + XVPHY_CHANNEL_ID_CMNA = 8, + XVPHY_CHANNEL_ID_CMN = XVPHY_CHANNEL_ID_CMN0, +} XVphy_ChannelId; + +/** + * This typedef enumerates the available reference clocks for the PLL clock + * selection multiplexer. + */ +typedef enum { + XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0 = XVPHY_REF_CLK_SEL_XPLL_GTREFCLK0, + XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK1 = XVPHY_REF_CLK_SEL_XPLL_GTREFCLK1, + XVPHY_PLL_REFCLKSEL_TYPE_GTNORTHREFCLK0 = + XVPHY_REF_CLK_SEL_XPLL_GTNORTHREFCLK0, + XVPHY_PLL_REFCLKSEL_TYPE_GTNORTHREFCLK1 = + XVPHY_REF_CLK_SEL_XPLL_GTNORTHREFCLK1, + XVPHY_PLL_REFCLKSEL_TYPE_GTSOUTHREFCLK0 = + XVPHY_REF_CLK_SEL_XPLL_GTSOUTHREFCLK0, + XVPHY_PLL_REFCLKSEL_TYPE_GTSOUTHREFCLK1 = + XVPHY_REF_CLK_SEL_XPLL_GTSOUTHREFCLK1, + XVPHY_PLL_REFCLKSEL_TYPE_GTEASTREFCLK0 = + XVPHY_REF_CLK_SEL_XPLL_GTEASTREFCLK0, + XVPHY_PLL_REFCLKSEL_TYPE_GTEASTREFCLK1 = + XVPHY_REF_CLK_SEL_XPLL_GTEASTREFCLK1, + XVPHY_PLL_REFCLKSEL_TYPE_GTWESTREFCLK0 = + XVPHY_REF_CLK_SEL_XPLL_GTWESTREFCLK0, + XVPHY_PLL_REFCLKSEL_TYPE_GTWESTREFCLK1 = + XVPHY_REF_CLK_SEL_XPLL_GTWESTREFCLK1, + XVPHY_PLL_REFCLKSEL_TYPE_GTGREFCLK = + XVPHY_REF_CLK_SEL_XPLL_GTGREFCLK, +} XVphy_PllRefClkSelType; + +/** + * This typedef enumerates the available reference clocks used to drive the + * RX/TX datapaths. + */ +typedef enum { + XVPHY_SYSCLKSELDATA_TYPE_PLL0_OUTCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_PLL0, + XVPHY_SYSCLKSELDATA_TYPE_PLL1_OUTCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_PLL1, + XVPHY_SYSCLKSELDATA_TYPE_CPLL_OUTCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_CPLL, + XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL, + XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL0, + XVPHY_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL1, +} XVphy_SysClkDataSelType; + +/** + * This typedef enumerates the available reference clocks used to drive the + * RX/TX output clocks. + */ +typedef enum { + XVPHY_SYSCLKSELOUT_TYPE_CPLL_REFCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CH, + XVPHY_SYSCLKSELOUT_TYPE_QPLL_REFCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN, + XVPHY_SYSCLKSELOUT_TYPE_QPLL0_REFCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN0, + XVPHY_SYSCLKSELOUT_TYPE_QPLL1_REFCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN1, + XVPHY_SYSCLKSELOUT_TYPE_PLL0_REFCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CH, + XVPHY_SYSCLKSELOUT_TYPE_PLL1_REFCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN, +} XVphy_SysClkOutSelType; + +/** + * This typedef enumerates the available clocks that are used as multiplexer + * input selections for the RX/TX output clock. + */ +typedef enum { + XVPHY_OUTCLKSEL_TYPE_OUTCLKPCS = 1, + XVPHY_OUTCLKSEL_TYPE_OUTCLKPMA, + XVPHY_OUTCLKSEL_TYPE_PLLREFCLK_DIV1, + XVPHY_OUTCLKSEL_TYPE_PLLREFCLK_DIV2, + XVPHY_OUTCLKSEL_TYPE_PROGDIVCLK +} XVphy_OutClkSelType; + +/* This typedef enumerates the possible states a transceiver can be in. */ +typedef enum { + XVPHY_GT_STATE_IDLE, /**< Idle state. */ + XVPHY_GT_STATE_LOCK, /**< Lock state. */ + XVPHY_GT_STATE_RESET, /**< Reset state. */ + XVPHY_GT_STATE_ALIGN, /**< Align state. */ + XVPHY_GT_STATE_READY, /**< Ready state. */ +} XVphy_GtState; + +#ifdef XV_VPHY_LOG_ENABLE +typedef enum { + XVPHY_LOG_EVT_NONE = 1, /**< Log event none. */ + XVPHY_LOG_EVT_QPLL_EN, /**< Log event QPLL enable. */ + XVPHY_LOG_EVT_QPLL_RST, /**< Log event QPLL reset. */ + XVPHY_LOG_EVT_QPLL_LOCK, /**< Log event QPLL lock. */ + XVPHY_LOG_EVT_QPLL_RECONFIG, /**< Log event QPLL reconfig. */ + XVPHY_LOG_EVT_QPLL0_EN, /**< Log event QPLL0 enable. */ + XVPHY_LOG_EVT_QPLL0_RST, /**< Log event QPLL0 reset. */ + XVPHY_LOG_EVT_QPLL0_LOCK, /**< Log event QPLL0 lock. */ + XVPHY_LOG_EVT_QPLL0_RECONFIG, /**< Log event QPLL0 reconfig. */ + XVPHY_LOG_EVT_QPLL1_EN, /**< Log event QPLL1 enable. */ + XVPHY_LOG_EVT_QPLL1_RST, /**< Log event QPLL1 reset. */ + XVPHY_LOG_EVT_QPLL1_LOCK, /**< Log event QPLL1 lock. */ + XVPHY_LOG_EVT_QPLL1_RECONFIG, /**< Log event QPLL1 reconfig. */ + XVPHY_LOG_EVT_PLL0_EN, /**< Log event PLL0 reset. */ + XVPHY_LOG_EVT_PLL0_RST, /**< Log event PLL0 reset. */ + XVPHY_LOG_EVT_PLL0_LOCK, /**< Log event PLL0 lock. */ + XVPHY_LOG_EVT_PLL0_RECONFIG, /**< Log event PLL0 reconfig. */ + XVPHY_LOG_EVT_PLL1_EN, /**< Log event PLL1 reset. */ + XVPHY_LOG_EVT_PLL1_RST, /**< Log event PLL1 reset. */ + XVPHY_LOG_EVT_PLL1_LOCK, /**< Log event PLL1 lock. */ + XVPHY_LOG_EVT_PLL1_RECONFIG, /**< Log event PLL1 reconfig. */ + XVPHY_LOG_EVT_CPLL_EN, /**< Log event CPLL reset. */ + XVPHY_LOG_EVT_CPLL_RST, /**< Log event CPLL reset. */ + XVPHY_LOG_EVT_CPLL_LOCK, /**< Log event CPLL lock. */ + XVPHY_LOG_EVT_CPLL_RECONFIG, /**< Log event CPLL reconfig. */ + XVPHY_LOG_EVT_TXPLL_EN, /**< Log event TXPLL enable. */ + XVPHY_LOG_EVT_TXPLL_RST, /**< Log event TXPLL reset. */ + XVPHY_LOG_EVT_RXPLL_EN, /**< Log event RXPLL enable. */ + XVPHY_LOG_EVT_RXPLL_RST, /**< Log event RXPLL reset. */ + XVPHY_LOG_EVT_GTRX_RST, /**< Log event GT RX reset. */ + XVPHY_LOG_EVT_GTTX_RST, /**< Log event GT TX reset. */ + XVPHY_LOG_EVT_VID_TX_RST, /**< Log event Vid TX reset. */ + XVPHY_LOG_EVT_VID_RX_RST, /**< Log event Vid RX reset. */ + XVPHY_LOG_EVT_TX_ALIGN, /**< Log event TX align. */ + XVPHY_LOG_EVT_TX_ALIGN_TMOUT, /**< Log event TX align Timeout. */ + XVPHY_LOG_EVT_TX_TMR, /**< Log event TX timer. */ + XVPHY_LOG_EVT_RX_TMR, /**< Log event RX timer. */ + XVPHY_LOG_EVT_GT_RECONFIG, /**< Log event GT reconfig. */ + XVPHY_LOG_EVT_GT_TX_RECONFIG, /**< Log event GT reconfig. */ + XVPHY_LOG_EVT_GT_RX_RECONFIG, /**< Log event GT reconfig. */ + XVPHY_LOG_EVT_INIT, /**< Log event init. */ + XVPHY_LOG_EVT_TXPLL_RECONFIG, /**< Log event TXPLL reconfig. */ + XVPHY_LOG_EVT_RXPLL_RECONFIG, /**< Log event RXPLL reconfig. */ + XVPHY_LOG_EVT_RXPLL_LOCK, /**< Log event RXPLL lock. */ + XVPHY_LOG_EVT_TXPLL_LOCK, /**< Log event TXPLL lock. */ + XVPHY_LOG_EVT_TX_RST_DONE, /**< Log event TX reset done. */ + XVPHY_LOG_EVT_RX_RST_DONE, /**< Log event RX reset done. */ + XVPHY_LOG_EVT_TX_FREQ, /**< Log event TX frequency. */ + XVPHY_LOG_EVT_RX_FREQ, /**< Log event RX frequency. */ + XVPHY_LOG_EVT_DRU_EN, /**< Log event DRU enable/disable. */ + XVPHY_LOG_EVT_GT_PLL_LAYOUT,/**< Log event GT PLL Layout Change. */ + XVPHY_LOG_EVT_GT_UNBONDED, /**< Log event GT Unbonded Change. */ + XVPHY_LOG_EVT_1PPC_ERR, /**< Log event 1 PPC Error. */ + XVPHY_LOG_EVT_PPC_MSMTCH_ERR,/**< Log event PPC MismatchError. */ + XVPHY_LOG_EVT_VDCLK_HIGH_ERR,/**< Log event VidClk more than 148.5 MHz. */ + XVPHY_LOG_EVT_NO_DRU, /**< Log event Vid not supported no DRU. */ + XVPHY_LOG_EVT_GT_QPLL_CFG_ERR,/**< Log event QPLL Config not found. */ + XVPHY_LOG_EVT_GT_CPLL_CFG_ERR,/**< Log event QPLL Config not found. */ + XVPHY_LOG_EVT_VD_NOT_SPRTD_ERR,/**< Log event Vid format not supported. */ + XVPHY_LOG_EVT_MMCM_ERR, /**< Log event MMCM Config not found. */ + XVPHY_LOG_EVT_DUMMY, /**< Dummy Event should be last */ +} XVphy_LogEvent; +#endif + +/* This typedef enumerates the possible error conditions. */ +typedef enum { + XVPHY_ERRIRQ_QPLL_CFG = 0x1, /**< QPLL CFG not found. */ + XVPHY_ERRIRQ_CPLL_CFG = 0x2, /**< CPLL CFG not found. */ + XVPHY_ERRIRQ_NO_DRU = 0x4, /**< No DRU in design. */ + XVPHY_ERRIRQ_VD_NOT_SPRTD= 0x8, /**< Video Not Supported. */ + XVPHY_ERRIRQ_MMCM_CFG = 0x10,/**< MMCM CFG not found. */ + XVPHY_ERRIRQ_PLL_LAYOUT = 0x20,/**< PLL Error. */ +} XVphy_ErrIrqType; + +/******************************************************************************/ +/** + * Callback type which represents the handler for interrupts. + * + * @param InstancePtr is a pointer to the XVphy instance. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XVphy_IntrHandler)(void *InstancePtr); + +/******************************************************************************/ +/** + * Callback type which represents a custom timer wait handler. This is only + * used for Microblaze since it doesn't have a native sleep function. To avoid + * dependency on a hardware timer, the default wait functionality is implemented + * using loop iterations; this isn't too accurate. If a custom timer handler is + * used, the user may implement their own wait implementation using a hardware + * timer (see example/) for better accuracy. + * + * @param InstancePtr is a pointer to the XVphy instance. + * @param MicroSeconds is the number of microseconds to be passed to the + * timer function. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XVphy_TimerHandler)(void *InstancePtr, u32 MicroSeconds); + +/******************************************************************************/ +/** + * Generic callback type. + * + * @param CallbackRef is a pointer to the callback reference. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XVphy_Callback)(void *CallbackRef); + +/** + * This typedef contains configuration information for CPLL/QPLL programming. + */ +typedef struct { + u8 MRefClkDiv; + /* Aliases for N (QPLL) and N1/N2 (CPLL). */ + union { + u8 NFbDivs[2]; + u8 NFbDiv; + struct { + u8 N1FbDiv; + u8 N2FbDiv; + }; + }; + u16 Cdr[5]; + u8 IsLowerBand; +} XVphy_PllParam; + +/** + * This typedef contains configuration information for PLL type and its + * reference clock. + */ +typedef struct { + /* Below members are common between CPLL/QPLL. */ + u64 LineRateHz; /**< The line rate for the + channel. */ + union { + XVphy_PllParam QpllParams; + XVphy_PllParam CpllParams; /**< Parameters for a CPLL. */ + XVphy_PllParam PllParams; + }; + union { + XVphy_PllRefClkSelType CpllRefClkSel; + /**< Multiplexer selection for + the reference clock of + the CPLL. */ + XVphy_PllRefClkSelType PllRefClkSel; + }; + /* Below members are CPLL specific. */ + union { + struct { + u8 RxOutDiv; /**< Output clock divider D for + the RX datapath. */ + u8 TxOutDiv; /**< Output clock divider D for + the TX datapath. */ + }; + u8 OutDiv[2]; + }; + union { + struct { + XVphy_GtState RxState; /**< Current state of RX GT. */ + XVphy_GtState TxState; /**< Current state of TX GT. */ + }; + XVphy_GtState GtState[2]; + }; + union { + struct { + XVphy_ProtocolType RxProtocol; + /**< The protocol which the RX + path is used for. */ + XVphy_ProtocolType TxProtocol; + /**< The protocol which the TX + path is used for. */ + }; + XVphy_ProtocolType Protocol[2]; + }; + union { + struct { + XVphy_SysClkDataSelType RxDataRefClkSel; + /**< Multiplexer selection for + the reference clock of + the RX datapath. */ + XVphy_SysClkDataSelType TxDataRefClkSel; + /**< Multiplexer selection for + the reference clock of + the TX datapath. */ + }; + XVphy_SysClkDataSelType DataRefClkSel[2]; + }; + union { + struct { + XVphy_SysClkOutSelType RxOutRefClkSel; + /**< Multiplexer selection for + the reference clock of + the RX output clock. */ + XVphy_SysClkOutSelType TxOutRefClkSel; + /**< Multiplexer selection for + the reference clock of + the TX output clock. */ + }; + XVphy_SysClkOutSelType OutRefClkSel[2]; + }; + union { + struct { + XVphy_OutClkSelType RxOutClkSel; + /**< Multiplexer selection for + which clock to use as + the RX output clock. */ + XVphy_OutClkSelType TxOutClkSel; + /**< Multiplexer selection for + which clock to use as + the TX output clock. */ + }; + XVphy_OutClkSelType OutClkSel[2]; + }; + union { + struct { + u8 RxDelayBypass; /**< Bypasses the delay + alignment block for the + RX output clock. */ + u8 TxDelayBypass; /**< Bypasses the delay + alignment block for the + TX output clock. */ + }; + u8 DelayBypass; + }; + u8 RxDataWidth; /**< In bits. */ + u8 RxIntDataWidth; /**< In bytes. */ + u8 TxDataWidth; /**< In bits. */ + u8 TxIntDataWidth; /**< In bytes. */ +} XVphy_Channel; + +/** + * This typedef contains configuration information for MMCM programming. + */ +typedef struct { + u8 DivClkDivide; + u8 ClkFbOutMult; + u16 ClkFbOutFrac; + u8 ClkOut0Div; + u16 ClkOut0Frac; + u8 ClkOut1Div; + u8 ClkOut2Div; +} XVphy_Mmcm; + +/** + * This typedef represents a GT quad. + */ +typedef struct { + union { + struct { + XVphy_Mmcm RxMmcm; /**< Mixed-mode clock manager + (MMCM) parameters for + RX. */ + XVphy_Mmcm TxMmcm; /**< MMCM parameters for TX. */ + }; + XVphy_Mmcm Mmcm[2]; /**< MMCM parameters. */ + }; + union { + struct { + XVphy_Channel Ch1; + XVphy_Channel Ch2; + XVphy_Channel Ch3; + XVphy_Channel Ch4; + XVphy_Channel Cmn0; + XVphy_Channel Cmn1; + }; + XVphy_Channel Plls[6]; + }; + union { + struct { + u32 GtRefClk0Hz; + u32 GtRefClk1Hz; + u32 GtNorthRefClk0Hz; + u32 GtNorthRefClk1Hz; + u32 GtSouthRefClk0Hz; + u32 GtSouthRefClk1Hz; + u32 GtgRefClkHz; + }; + u32 RefClkHz[7]; + }; +} XVphy_Quad; + +#ifdef XV_VPHY_LOG_ENABLE +/** + * This typedef contains the logging mechanism for debug. + */ +typedef struct { + u16 DataBuffer[256]; /**< Log buffer with event data. */ + u8 HeadIndex; /**< Index of the head entry of the + Event/DataBuffer. */ + u8 TailIndex; /**< Index of the tail entry of the + Event/DataBuffer. */ +} XVphy_Log; +#endif + +/** + * This typedef contains configuration information for the Video PHY core. + */ +typedef struct { + u16 DeviceId; /**< Device instance ID. */ + UINTPTR BaseAddr; /**< The base address of the core + instance. */ + XVphy_GtType XcvrType; /**< VPHY Transceiver Type */ + u8 TxChannels; /**< No. of active channels in TX */ + u8 RxChannels; /**< No. of active channels in RX */ + XVphy_ProtocolType TxProtocol; /**< Protocol which TX is used for. */ + XVphy_ProtocolType RxProtocol; /**< Protocol which RX is used for. */ + XVphy_PllRefClkSelType TxRefClkSel; /**< TX REFCLK selection. */ + XVphy_PllRefClkSelType RxRefClkSel; /**< RX REFCLK selection. */ + XVphy_SysClkDataSelType TxSysPllClkSel; /**< TX SYSCLK selection. */ + XVphy_SysClkDataSelType RxSysPllClkSel; /**< RX SYSCLK selectino. */ + u8 DruIsPresent; /**< A data recovery unit (DRU) exists + in the design .*/ + XVphy_PllRefClkSelType DruRefClkSel; /**< DRU REFCLK selection. */ + XVidC_PixelsPerClock Ppc; /**< Number of input pixels per + clock. */ + u8 TxBufferBypass; /**< TX Buffer Bypass is enabled in the + design. */ + u8 HdmiFastSwitch; /**< HDMI fast switching is enabled in the + design. */ + u8 TransceiverWidth; /**< Transceiver Width seeting in the design */ + u32 ErrIrq; /**< Error IRQ is enalbed in design */ + u32 AxiLiteClkFreq; /**< AXI Lite Clock Frequency in Hz */ +} XVphy_Config; + +/* Forward declaration. */ +struct XVphy_GtConfigS; + +/** + * The XVphy driver instance data. The user is required to allocate a variable + * of this type for every XVphy device in the system. A pointer to a variable of + * this type is then passed to the driver API functions. + */ +typedef struct { + u32 IsReady; /**< Device is initialized and + ready. */ + XVphy_Config Config; /**< Configuration structure for + the Video PHY core. */ + const struct XVphy_GtConfigS *GtAdaptor; +#ifdef XV_VPHY_LOG_ENABLE + XVphy_Log Log; /**< A log of events. */ +#endif + XVphy_Quad Quads[2]; /**< The quads available to the + Video PHY core.*/ + u32 HdmiRxRefClkHz; /**< HDMI RX refclk. */ + u32 HdmiTxRefClkHz; /**< HDMI TX refclk. */ + u8 HdmiRxTmdsClockRatio; /**< HDMI TMDS clock ratio. */ + u8 HdmiTxSampleRate; /**< HDMI TX sample rate. */ + u8 HdmiRxDruIsEnabled; /**< The DRU is enabled. */ + XVphy_IntrHandler IntrCpllLockHandler; /**< Callback function for CPLL + lock interrupts. */ + void *IntrCpllLockCallbackRef; /**< A pointer to the user data + passed to the CPLL lock + callback function. */ + XVphy_IntrHandler IntrQpllLockHandler; /**< Callback function for QPLL + lock interrupts. */ + void *IntrQpllLockCallbackRef; /**< A pointer to the user data + passed to the QPLL lock + callback function. */ + XVphy_IntrHandler IntrQpll1LockHandler; /**< Callback function for QPLL + lock interrupts. */ + void *IntrQpll1LockCallbackRef; /**< A pointer to the user data + passed to the QPLL lock + callback function. */ + XVphy_IntrHandler IntrTxResetDoneHandler; /**< Callback function for TX + reset done lock + interrupts. */ + void *IntrTxResetDoneCallbackRef; /**< A pointer to the user data + passed to the TX reset + done lock callback + function. */ + XVphy_IntrHandler IntrRxResetDoneHandler; /**< Callback function for RX + reset done lock + interrupts. */ + void *IntrRxResetDoneCallbackRef; /**< A pointer to the user data + passed to the RX reset + done lock callback + function. */ + XVphy_IntrHandler IntrTxAlignDoneHandler; /**< Callback function for TX + align done lock + interrupts. */ + void *IntrTxAlignDoneCallbackRef; /**< A pointer to the user data + passed to the TX align + done lock callback + function. */ + XVphy_IntrHandler IntrTxClkDetFreqChangeHandler; /**< Callback function + for TX clock detector + frequency change + interrupts. */ + void *IntrTxClkDetFreqChangeCallbackRef; /**< A pointer to the user data + passed to the TX clock + detector frequency + change callback + function. */ + XVphy_IntrHandler IntrRxClkDetFreqChangeHandler; /**< Callback function + for RX clock detector + frequency change + interrupts. */ + void *IntrRxClkDetFreqChangeCallbackRef; /**< A pointer to the user data + passed to the RX clock + detector frequency + change callback + function. */ + XVphy_IntrHandler IntrTxTmrTimeoutHandler; /**< Callback function for TX + timer timeout + interrupts. */ + void *IntrTxTmrTimeoutCallbackRef; /**< A pointer to the user data + passed to the TX timer + timeout callback + function. */ + XVphy_IntrHandler IntrRxTmrTimeoutHandler; /**< Callback function for RX + timer timeout + interrupts. */ + void *IntrRxTmrTimeoutCallbackRef; /**< A pointer to the user data + passed to the RX timer + timeout callback + function. */ + /* HDMI callbacks. */ + XVphy_Callback HdmiTxInitCallback; /**< Callback for TX init. */ + void *HdmiTxInitRef; /**< To be passed to the TX init + callback. */ + XVphy_Callback HdmiTxReadyCallback; /**< Callback for TX ready. */ + void *HdmiTxReadyRef; /**< To be passed to the TX + ready callback. */ + XVphy_Callback HdmiRxInitCallback; /**< Callback for RX init. */ + void *HdmiRxInitRef; /**< To be passed to the RX + init callback. */ + XVphy_Callback HdmiRxReadyCallback; /**< Callback for RX ready. */ + void *HdmiRxReadyRef; /**< To be passed to the RX + ready callback. */ + XVphy_TimerHandler UserTimerWaitUs; /**< Custom user function for + delay/sleep. */ + void *UserTimerPtr; /**< Pointer to a timer instance + used by the custom user + delay/sleep function. */ +} XVphy; + +/**************************** Function Prototypes *****************************/ + +/* xvphy.c: Setup and initialization functions. */ +void XVphy_CfgInitialize(XVphy *InstancePtr, XVphy_Config *ConfigPtr, + UINTPTR EffectiveAddr); +u32 XVphy_PllInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_PllRefClkSelType QpllRefClkSel, + XVphy_PllRefClkSelType CpllxRefClkSel, + XVphy_PllType TxPllSelect, XVphy_PllType RxPllSelect); +#if defined (XPAR_XDP_0_DEVICE_ID) +u32 XVphy_ClkInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir); +#endif +u32 XVphy_GetVersion(XVphy *InstancePtr); +void XVphy_WaitUs(XVphy *InstancePtr, u32 MicroSeconds); +void XVphy_SetUserTimerHandler(XVphy *InstancePtr, + XVphy_TimerHandler CallbackFunc, void *CallbackRef); + +/* xvphy.c: Channel configuration functions - setters. */ +u32 XVphy_CfgLineRate(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u64 LineRateHz); +#if defined (XPAR_XDP_0_DEVICE_ID) +u32 XVphy_CfgQuadRefClkFreq(XVphy *InstancePtr, u8 QuadId, + XVphy_PllRefClkSelType RefClkType, u32 FreqHz); +#endif + +/* xvphy.c: Channel configuration functions - getters. */ +XVphy_PllType XVphy_GetPllType(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_ChannelId ChId); +u64 XVphy_GetLineRateHz(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); + +/* xvphy.c: Reset functions. */ +#if defined (XPAR_XDP_0_DEVICE_ID) +u32 XVphy_WaitForPmaResetDone(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir); +u32 XVphy_WaitForResetDone(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir); +u32 XVphy_WaitForPllLock(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +#endif +u32 XVphy_ResetGtPll(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Hold); +u32 XVphy_ResetGtTxRx(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Hold); + +/* xvphy.c: GT/MMCM DRP access. */ +u32 XVphy_DrpWrite(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u16 Addr, u16 Val); +u16 XVphy_DrpRead(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u16 Addr); +void XVphy_MmcmPowerDown(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir, + u8 Hold); +void XVphy_MmcmStart(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir); +void XVphy_IBufDsEnable(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir, + u8 Enable); +void XVphy_Clkout1OBufTdsEnable(XVphy *InstancePtr, XVphy_DirectionType Dir, + u8 Enable); +#if defined (XPAR_XDP_0_DEVICE_ID) +void XVphy_BufgGtReset(XVphy *InstancePtr, XVphy_DirectionType Dir, u8 Reset); + +/* xvphy.c Miscellaneous control. */ +void XVphy_Set8b10b(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Enable); +#endif +u32 XVphy_IsBonded(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); + +/* xvphy_log.c: Logging functions. */ +void XVphy_LogDisplay(XVphy *InstancePtr); +void XVphy_LogReset(XVphy *InstancePtr); +u16 XVphy_LogRead(XVphy *InstancePtr); +#ifdef XV_VPHY_LOG_ENABLE +void XVphy_LogWrite(XVphy *InstancePtr, XVphy_LogEvent Evt, u8 Data); +#else +#define XVphy_LogWrite(...) +#endif + +/* xvphy_intr.c: Interrupt handling functions. */ +void XVphy_InterruptHandler(XVphy *InstancePtr); + +/* xvphy_selftest.c: Self test function. */ +u32 XVphy_SelfTest(XVphy *InstancePtr); + +/* xvphy_sinit.c: Configuration extraction function. */ +XVphy_Config *XVphy_LookupConfig(u16 DeviceId); + +/* xvphy_dp.c, xvphy_hdmi.c, xvphy_hdmi_intr.c: Protocol specific functions. */ +u32 XVphy_DpInitialize(XVphy *InstancePtr, XVphy_Config *CfgPtr, u8 QuadId, + XVphy_PllRefClkSelType CpllRefClkSel, + XVphy_PllRefClkSelType QpllRefClkSel, + XVphy_PllType TxPllSelect, XVphy_PllType RxPllSelect, + u8 LinkRate); +u32 XVphy_HdmiInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_Config *CfgPtr, + u32 SystemFrequency); +u32 XVphy_SetHdmiTxParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVidC_PixelsPerClock Ppc, XVidC_ColorDepth Bpc, + XVidC_ColorFormat ColorFormat); +u32 XVphy_SetHdmiRxParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); + +u32 XVphy_HdmiCfgCalcMmcmParam(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir, + XVidC_PixelsPerClock Ppc, XVidC_ColorDepth Bpc); + +void XVphy_HdmiUpdateClockSelection(XVphy *InstancePtr, u8 QuadId, + XVphy_SysClkDataSelType TxSysPllClkSel, + XVphy_SysClkDataSelType RxSysPllClkSel); +void XVphy_ClkDetFreqReset(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir); +u32 XVphy_ClkDetGetRefClkFreqHz(XVphy *InstancePtr, XVphy_DirectionType Dir); +u32 XVphy_DruGetRefClkFreqHz(XVphy *InstancePtr); +void XVphy_HdmiDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +void XVphy_DpDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +void XVphy_SetHdmiCallback(XVphy *InstancePtr, + XVphy_HdmiHandlerType HandlerType, + void *CallbackFunc, void *CallbackRef); + +/******************* Macros (Inline Functions) Definitions ********************/ + +#define XVPHY_CH2IDX(Id) ((Id) - XVPHY_CHANNEL_ID_CH1) +#define XVPHY_ISCH(Id) (((Id) == XVPHY_CHANNEL_ID_CHA) || \ + ((XVPHY_CHANNEL_ID_CH1 <= (Id)) && ((Id) <= XVPHY_CHANNEL_ID_CH4))) +#define XVPHY_ISCMN(Id) (((Id) == XVPHY_CHANNEL_ID_CMNA) || \ + ((XVPHY_CHANNEL_ID_CMN0 <= (Id)) && ((Id) <= XVPHY_CHANNEL_ID_CMN1))) + +#define XVphy_IsTxUsingQpll(InstancePtr, QuadId, ChId) \ + ((XVPHY_PLL_TYPE_QPLL == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_TX, ChId)) || \ + (XVPHY_PLL_TYPE_QPLL0 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_TX, ChId)) || \ + (XVPHY_PLL_TYPE_QPLL1 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_TX, ChId)) || \ + (XVPHY_PLL_TYPE_PLL0 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_TX, ChId)) || \ + (XVPHY_PLL_TYPE_PLL1 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_TX, ChId))) +#define XVphy_IsRxUsingQpll(InstancePtr, QuadId, ChId) \ + ((XVPHY_PLL_TYPE_QPLL == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_RX, ChId)) || \ + (XVPHY_PLL_TYPE_QPLL0 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_RX, ChId)) || \ + (XVPHY_PLL_TYPE_QPLL1 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_RX, ChId)) || \ + (XVPHY_PLL_TYPE_PLL0 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_RX, ChId)) || \ + (XVPHY_PLL_TYPE_PLL1 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_RX, ChId))) +#define XVphy_IsTxUsingCpll(InstancePtr, QuadId, ChId) \ + (XVPHY_PLL_TYPE_CPLL == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_TX, ChId)) +#define XVphy_IsRxUsingCpll(InstancePtr, QuadId, ChId) \ + (XVPHY_PLL_TYPE_CPLL == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_RX, ChId)) + +#define XVPHY_GTXE2 1 +#define XVPHY_GTHE2 2 +#define XVPHY_GTPE2 3 +#define XVPHY_GTHE3 4 +#define XVPHY_GTHE4 5 + +#endif /* XVPHY_H_ */ diff --git a/drivers/staging/xilinx/hdmi/include/linux/phy/xvphy_hw.h b/drivers/staging/xilinx/hdmi/include/linux/phy/xvphy_hw.h new file mode 100644 index 00000000000000..6e06e8dc902ae2 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/include/linux/phy/xvphy_hw.h @@ -0,0 +1,567 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_hw.h + * + * This header file contains the identifiers and low-level driver functions (or + * macros) that can be used to access the device. High-level driver functions + * are defined in xvphy.h. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 10/19/15 Initial release. + * 1.1 gm 02/01/16 Added GTPE2 and GTHE4 support + * 1.4 gm 29/11/16 Added ERR_IRQ register offset + * </pre> + * +*******************************************************************************/ + +#ifndef XVPHY_HW_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XVPHY_HW_H_ + +/***************************** Include Files **********************************/ + +#include "xil_io.h" +#include "xil_types.h" + +/************************** Constant Definitions ******************************/ + +/******************************************************************************/ +/** + * Address mapping for the Video PHY core. + * +*******************************************************************************/ +/** @name VPHY core registers: General registers. + * @{ + */ +#define XVPHY_VERSION_REG 0x000 +#define XVPHY_BANK_SELECT_REG 0x00C +#define XVPHY_REF_CLK_SEL_REG 0x010 +#define XVPHY_PLL_RESET_REG 0x014 +#define XVPHY_PLL_LOCK_STATUS_REG 0x018 +#define XVPHY_TX_INIT_REG 0x01C +#define XVPHY_TX_INIT_STATUS_REG 0x020 +#define XVPHY_RX_INIT_REG 0x024 +#define XVPHY_RX_INIT_STATUS_REG 0x028 +#define XVPHY_IBUFDS_GTXX_CTRL_REG 0x02C +#define XVPHY_POWERDOWN_CONTROL_REG 0x030 +#define XVPHY_LOOPBACK_CONTROL_REG 0x038 +/* @} */ + +/** @name VPHY core registers: Dynamic reconfiguration port (DRP) registers. + * @{ + */ +#define XVPHY_DRP_CONTROL_CH1_REG 0x040 +#define XVPHY_DRP_CONTROL_CH2_REG 0x044 +#define XVPHY_DRP_CONTROL_CH3_REG 0x048 +#define XVPHY_DRP_CONTROL_CH4_REG 0x04C +#define XVPHY_DRP_STATUS_CH1_REG 0x050 +#define XVPHY_DRP_STATUS_CH2_REG 0x054 +#define XVPHY_DRP_STATUS_CH3_REG 0x058 +#define XVPHY_DRP_STATUS_CH4_REG 0x05C +#define XVPHY_DRP_CONTROL_COMMON_REG 0x060 +#define XVPHY_DRP_STATUS_COMMON_REG 0x064 +/* @} */ + +/** @name VPHY core registers: Transmitter function registers. + * @{ + */ +#define XVPHY_TX_CONTROL_REG 0x070 +#define XVPHY_TX_BUFFER_BYPASS_REG 0x074 +#define XVPHY_TX_STATUS_REG 0x078 +#define XVPHY_TX_DRIVER_CH12_REG 0x07C +#define XVPHY_TX_DRIVER_CH34_REG 0x080 +/* @} */ + +/** @name VPHY core registers: Receiver function registers. + * @{ + */ +#define XVPHY_RX_CONTROL_REG 0x100 +#define XVPHY_RX_STATUS_REG 0x104 +#define XVPHY_RX_EQ_CDR_REG 0x108 +#define XVPHY_RX_TDLOCK_REG 0x10C +/* @} */ + +/** @name VPHY core registers: Interrupt registers. + * @{ + */ +#define XVPHY_ERR_IRQ 0x03C +#define XVPHY_INTR_EN_REG 0x110 +#define XVPHY_INTR_DIS_REG 0x114 +#define XVPHY_INTR_MASK_REG 0x118 +#define XVPHY_INTR_STS_REG 0x11C +/* @} */ + +/** @name User clocking registers: MMCM and BUFGGT registers. + * @{ + */ +#define XVPHY_MMCM_TXUSRCLK_CTRL_REG 0x0120 +#define XVPHY_MMCM_TXUSRCLK_REG1 0x0124 +#define XVPHY_MMCM_TXUSRCLK_REG2 0x0128 +#define XVPHY_MMCM_TXUSRCLK_REG3 0x012C +#define XVPHY_MMCM_TXUSRCLK_REG4 0x0130 +#define XVPHY_BUFGGT_TXUSRCLK_REG 0x0134 +#define XVPHY_MISC_TXUSRCLK_REG 0x0138 + +#define XVPHY_MMCM_RXUSRCLK_CTRL_REG 0x0140 +#define XVPHY_MMCM_RXUSRCLK_REG1 0x0144 +#define XVPHY_MMCM_RXUSRCLK_REG2 0x0148 +#define XVPHY_MMCM_RXUSRCLK_REG3 0x014C +#define XVPHY_MMCM_RXUSRCLK_REG4 0x0150 +#define XVPHY_BUFGGT_RXUSRCLK_REG 0x0154 +#define XVPHY_MISC_RXUSRCLK_REG 0x0158 +/* @} */ + +/** @name Clock detector (HDMI) registers. + * @{ + */ +#define XVPHY_CLKDET_CTRL_REG 0x0200 +#define XVPHY_CLKDET_STAT_REG 0x0204 +#define XVPHY_CLKDET_FREQ_TMR_TO_REG 0x0208 +#define XVPHY_CLKDET_FREQ_TX_REG 0x020C +#define XVPHY_CLKDET_FREQ_RX_REG 0x0210 +#define XVPHY_CLKDET_TMR_TX_REG 0x0214 +#define XVPHY_CLKDET_TMR_RX_REG 0x0218 +#define XVPHY_CLKDET_FREQ_DRU_REG 0x021C +/* @} */ + +/** @name Data recovery unit registers (HDMI). + * @{ + */ +#define XVPHY_DRU_CTRL_REG 0x0300 +#define XVPHY_DRU_STAT_REG 0x0304 + +#define XVPHY_DRU_CFREQ_L_REG(Ch) (0x0308 + (12 * (Ch - 1))) +#define XVPHY_DRU_CFREQ_H_REG(Ch) (0x030C + (12 * (Ch - 1))) +#define XVPHY_DRU_GAIN_REG(Ch) (0x0310 + (12 * (Ch - 1))) +/* @} */ + +/******************************************************************************/ + +/** @name VPHY core masks, shifts, and register values. + * @{ + */ +/* 0x0F8: VERSION */ +#define XVPHY_VERSION_INTER_REV_MASK \ + 0x000000FF /**< Internal revision. */ +#define XVPHY_VERSION_CORE_PATCH_MASK \ + 0x00000F00 /**< Core patch details. */ +#define XVPHY_VERSION_CORE_PATCH_SHIFT 8 /**< Shift bits for core patch + details. */ +#define XVPHY_VERSION_CORE_VER_REV_MASK \ + 0x0000F000 /**< Core version revision. */ +#define XVPHY_VERSION_CORE_VER_REV_SHIFT 12 /**< Shift bits for core version + revision. */ +#define XVPHY_VERSION_CORE_VER_MNR_MASK \ + 0x00FF0000 /**< Core minor version. */ +#define XVPHY_VERSION_CORE_VER_MNR_SHIFT 16 /**< Shift bits for core minor + version. */ +#define XVPHY_VERSION_CORE_VER_MJR_MASK \ + 0xFF000000 /**< Core major version. */ +#define XVPHY_VERSION_CORE_VER_MJR_SHIFT 24 /**< Shift bits for core major + version. */ +/* 0x00C: BANK_SELECT_REG */ +#define XVPHY_BANK_SELECT_TX_MASK 0x00F +#define XVPHY_BANK_SELECT_RX_MASK 0xF00 +#define XVPHY_BANK_SELECT_RX_SHIFT 8 +/* 0x010: REF_CLK_SEL */ +#define XVPHY_REF_CLK_SEL_QPLL0_MASK 0x0000000F +#define XVPHY_REF_CLK_SEL_CPLL_MASK 0x000000F0 +#define XVPHY_REF_CLK_SEL_CPLL_SHIFT 4 +#define XVPHY_REF_CLK_SEL_QPLL1_MASK 0x00000F00 +#define XVPHY_REF_CLK_SEL_QPLL1_SHIFT 8 +#define XVPHY_REF_CLK_SEL_XPLL_GTREFCLK0 1 +#define XVPHY_REF_CLK_SEL_XPLL_GTREFCLK1 2 +#define XVPHY_REF_CLK_SEL_XPLL_GTNORTHREFCLK0 3 +#define XVPHY_REF_CLK_SEL_XPLL_GTNORTHREFCLK1 4 +#define XVPHY_REF_CLK_SEL_XPLL_GTSOUTHREFCLK0 5 +#define XVPHY_REF_CLK_SEL_XPLL_GTSOUTHREFCLK1 6 +#define XVPHY_REF_CLK_SEL_XPLL_GTEASTREFCLK0 3 +#define XVPHY_REF_CLK_SEL_XPLL_GTEASTREFCLK1 4 +#define XVPHY_REF_CLK_SEL_XPLL_GTWESTREFCLK0 5 +#define XVPHY_REF_CLK_SEL_XPLL_GTWESTREFCLK1 6 +#define XVPHY_REF_CLK_SEL_XPLL_GTGREFCLK 7 +#define XVPHY_REF_CLK_SEL_SYSCLKSEL_MASK 0x0F000000 +#define XVPHY_REF_CLK_SEL_SYSCLKSEL_SHIFT 24 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_PLL0 0 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_PLL1 1 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_CPLL 0 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL 1 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL0 3 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL1 2 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CH 0 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN 1 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN0 2 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN1 3 +#define XVPHY_REF_CLK_SEL_RXSYSCLKSEL_OUT_MASK(G) \ + ((((G) == XVPHY_GT_TYPE_GTHE3) || \ + ((G) == XVPHY_GT_TYPE_GTHE4)) ? 0x03000000 : 0x02000000) +#define XVPHY_REF_CLK_SEL_TXSYSCLKSEL_OUT_MASK(G) \ + ((((G) == XVPHY_GT_TYPE_GTHE3) || \ + ((G) == XVPHY_GT_TYPE_GTHE4)) ? 0x0C000000 : 0x08000000) +#define XVPHY_REF_CLK_SEL_RXSYSCLKSEL_DATA_MASK(G) \ + ((((G) == XVPHY_GT_TYPE_GTHE3) || \ + ((G) == XVPHY_GT_TYPE_GTHE4)) ? 0x30000000 : 0x01000000) +#define XVPHY_REF_CLK_SEL_TXSYSCLKSEL_DATA_MASK(G) \ + ((((G) == XVPHY_GT_TYPE_GTHE3) || \ + ((G) == XVPHY_GT_TYPE_GTHE4)) ? 0xC0000000 : 0x04000000) +#define XVPHY_REF_CLK_SEL_RXSYSCLKSEL_OUT_SHIFT(G) \ + ((((G) == XVPHY_GT_TYPE_GTHE3) || \ + ((G) == XVPHY_GT_TYPE_GTHE4)) ? 24 : 25) +#define XVPHY_REF_CLK_SEL_TXSYSCLKSEL_OUT_SHIFT(G) \ + ((((G) == XVPHY_GT_TYPE_GTHE3) || \ + ((G) == XVPHY_GT_TYPE_GTHE4)) ? 26 : 27) +#define XVPHY_REF_CLK_SEL_RXSYSCLKSEL_DATA_SHIFT(G) \ + ((((G) == XVPHY_GT_TYPE_GTHE3) || \ + ((G) == XVPHY_GT_TYPE_GTHE4)) ? 28 : 24) +#define XVPHY_REF_CLK_SEL_TXSYSCLKSEL_DATA_SHIFT(G) \ + ((((G) == XVPHY_GT_TYPE_GTHE3) || \ + ((G) == XVPHY_GT_TYPE_GTHE4)) ? 30 : 26) +/* 0x014: PLL_RESET */ +#define XVPHY_PLL_RESET_CPLL_MASK 0x1 +#define XVPHY_PLL_RESET_QPLL0_MASK 0x2 +#define XVPHY_PLL_RESET_QPLL1_MASK 0x4 +/* 0x018: PLL_LOCK_STATUS */ +#define XVPHY_PLL_LOCK_STATUS_CPLL_MASK(Ch) \ + (0x01 << (Ch - 1)) +#define XVPHY_PLL_LOCK_STATUS_QPLL0_MASK 0x10 +#define XVPHY_PLL_LOCK_STATUS_QPLL1_MASK 0x20 +#define XVPHY_PLL_LOCK_STATUS_CPLL_ALL_MASK \ + (XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_PLL_LOCK_STATUS_CPLL_HDMI_MASK \ + (XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH3)) +/* 0x01C, 0x024: TX_INIT, RX_INIT */ +#define XVPHY_TXRX_INIT_GTRESET_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_PMARESET_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_PCSRESET_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_TX_INIT_USERRDY_MASK(Ch) \ + (0x08 << (8 * (Ch - 1))) +#define XVPHY_RX_INIT_USERRDY_MASK(Ch) \ + (0x40 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_PLLGTRESET_MASK(Ch) \ + (0x80 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_GTRESET_ALL_MASK \ + (XVPHY_TXRX_INIT_GTRESET_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TXRX_INIT_GTRESET_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TXRX_INIT_GTRESET_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TXRX_INIT_GTRESET_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_TX_INIT_USERRDY_ALL_MASK \ + (XVPHY_TX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_RX_INIT_USERRDY_ALL_MASK \ + (XVPHY_RX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_RX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_RX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_RX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_TXRX_INIT_PLLGTRESET_ALL_MASK \ + (XVPHY_TXRX_INIT_PLLGTRESET_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TXRX_INIT_PLLGTRESET_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TXRX_INIT_PLLGTRESET_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TXRX_INIT_PLLGTRESET_MASK(XVPHY_CHANNEL_ID_CH4)) +/* 0x020, 0x028: TX_STATUS, RX_STATUS */ +#define XVPHY_TXRX_INIT_STATUS_RESETDONE_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_STATUS_PMARESETDONE_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_STATUS_POWERGOOD_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_STATUS_RESETDONE_ALL_MASK \ + (XVPHY_TXRX_INIT_STATUS_RESETDONE_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TXRX_INIT_STATUS_RESETDONE_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TXRX_INIT_STATUS_RESETDONE_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TXRX_INIT_STATUS_RESETDONE_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_TXRX_INIT_STATUS_PMARESETDONE_ALL_MASK \ + (XVPHY_TXRX_INIT_STATUS_PMARESETDONE_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TXRX_INIT_STATUS_PMARESETDONE_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TXRX_INIT_STATUS_PMARESETDONE_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TXRX_INIT_STATUS_PMARESETDONE_MASK(XVPHY_CHANNEL_ID_CH4)) +/* 0x02C: IBUFDS_GTXX_CTRL */ +#define XVPHY_IBUFDS_GTXX_CTRL_GTREFCLK0_CEB_MASK 0x1 +#define XVPHY_IBUFDS_GTXX_CTRL_GTREFCLK1_CEB_MASK 0x2 +/* 0x030: POWERDOWN_CONTROL */ +#define XVPHY_POWERDOWN_CONTROL_CPLLPD_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_QPLL0PD_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_QPLL1PD_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_RXPD_MASK(Ch) \ + (0x18 << (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_RXPD_SHIFT(Ch) \ + (3 + (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_TXPD_MASK(Ch) \ + (0x60 << (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_TXPD_SHIFT(Ch) \ + (5 + (8 * (Ch - 1))) +/* 0x038: LOOPBACK_CONTROL */ +#define XVPHY_LOOPBACK_CONTROL_CH_MASK(Ch) \ + (0x03 << (8 * (Ch - 1))) +#define XVPHY_LOOPBACK_CONTROL_CH_SHIFT(Ch) \ + (8 * (Ch - 1)) +/* 0x040, 0x044, 0x048, 0x04C, 0x060: DRP_CONTROL_CH[1-4], DRP_CONTROL_COMMON */ +#define XVPHY_DRP_CONTROL_DRPADDR_MASK 0x00000FFF +#define XVPHY_DRP_CONTROL_DRPEN_MASK 0x00001000 +#define XVPHY_DRP_CONTROL_DRPWE_MASK 0x00002000 +#define XVPHY_DRP_CONTROL_DRPRESET_MASK 0x00004000 +#define XVPHY_DRP_CONTROL_DRPDI_MASK 0xFFFF0000 +#define XVPHY_DRP_CONTROL_DRPDI_SHIFT 16 +/* 0x050, 0x054, 0x058, 0x05C, 0x064: DRP_STATUS_CH[1-4], DRP_STATUS_COMMON */ +#define XVPHY_DRP_STATUS_DRPO_MASK 0x0FFFF +#define XVPHY_DRP_STATUS_DRPRDY_MASK 0x10000 +#define XVPHY_DRP_STATUS_DRPBUSY_MASK 0x20000 +/* 0x070: TX_CONTROL */ +#define XVPHY_TX_CONTROL_TX8B10BEN_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_TX_CONTROL_TX8B10BEN_ALL_MASK \ + (XVPHY_TX_CONTROL_TX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TX_CONTROL_TX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TX_CONTROL_TX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TX_CONTROL_TX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_TX_CONTROL_TXPOLARITY_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_TX_CONTROL_TXPRBSSEL_MASK(Ch) \ + (0x1C << (8 * (Ch - 1))) +#define XVPHY_TX_CONTROL_TXPRBSSEL_SHIFT(Ch) \ + (2 + (8 * (Ch - 1))) +#define XVPHY_TX_CONTROL_TXPRBSFORCEERR_MASK(Ch) \ + (0x20 << (8 * (Ch - 1))) +/* 0x074: TX_BUFFER_BYPASS */ +#define XVPHY_TX_BUFFER_BYPASS_TXPHDLYRESET_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXPHALIGN_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXPHALIGNEN_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXPHDLYPD_MASK(Ch) \ + (0x08 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXPHINIT_MASK(Ch) \ + (0x10 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXDLYRESET_MASK(Ch) \ + (0x20 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXDLYBYPASS_MASK(Ch) \ + (0x40 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXDLYEN_MASK(Ch) \ + (0x80 << (8 * (Ch - 1))) +/* 0x078: TX_STATUS */ +#define XVPHY_TX_STATUS_TXPHALIGNDONE_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_TX_STATUS_TXPHINITDONE_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_TX_STATUS_TXDLYRESETDONE_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_TX_STATUS_TXBUFSTATUS_MASK(Ch) \ + (0x18 << (8 * (Ch - 1))) +#define XVPHY_TX_STATUS_TXBUFSTATUS_SHIFT(Ch) \ + (3 + (8 * (Ch - 1))) +/* 0x07C, 0x080: TX_DRIVER_CH12, TX_DRIVER_CH34 */ +#define XVPHY_TX_DRIVER_TXDIFFCTRL_MASK(Ch) \ + (0x000F << (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXDIFFCTRL_SHIFT(Ch) \ + (16 * ((Ch - 1) % 2)) +#define XVPHY_TX_DRIVER_TXELECIDLE_MASK(Ch) \ + (0x0010 << (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXELECIDLE_SHIFT(Ch) \ + (4 + (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXINHIBIT_MASK(Ch) \ + (0x0020 << (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXINHIBIT_SHIFT(Ch) \ + (5 + (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXPOSTCURSOR_MASK(Ch) \ + (0x07C0 << (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXPOSTCURSOR_SHIFT(Ch) \ + (6 + (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXPRECURSOR_MASK(Ch) \ + (0xF800 << (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXPRECURSOR_SHIFT(Ch) \ + (11 + (16 * ((Ch - 1) % 2))) +/* 0x100: RX_CONTROL */ +#define XVPHY_RX_CONTROL_RX8B10BEN_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_RX_CONTROL_RX8B10BEN_ALL_MASK \ + (XVPHY_RX_CONTROL_RX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_RX_CONTROL_RX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_RX_CONTROL_RX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_RX_CONTROL_RX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_RX_CONTROL_RXPOLARITY_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_RX_CONTROL_RXPRBSCNTRESET_MASK(Ch) \ + (0x08 << (8 * (Ch - 1))) +#define XVPHY_RX_CONTROL_RXPRBSSEL_MASK(Ch) \ + (0x70 << (8 * (Ch - 1))) +#define XVPHY_RX_CONTROL_RXPRBSSEL_SHIFT(Ch) \ + (4 + (8 * (Ch - 1))) +/* 0x104: RX_STATUS */ +#define XVPHY_RX_STATUS_RXCDRLOCK_MASK(Ch) \ + (0x1 << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXBUFSTATUS_MASK(Ch) \ + (0xE << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXBUFSTATUS_SHIFT(Ch) \ + (1 + (8 * (Ch - 1))) +/* 0x104: RX_EQ_CDR */ +#define XVPHY_RX_CONTROL_RXLPMEN_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXCDRHOLD_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXOSOVRDEN_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXLPMLFKLOVRDEN_MASK(Ch) \ + (0x08 << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXLPMHFOVRDEN_MASK(Ch) \ + (0x10 << (8 * (Ch - 1))) +#define XVPHY_RX_CONTROL_RXLPMEN_ALL_MASK \ + (XVPHY_RX_CONTROL_RXLPMEN_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_RX_CONTROL_RXLPMEN_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_RX_CONTROL_RXLPMEN_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_RX_CONTROL_RXLPMEN_MASK(XVPHY_CHANNEL_ID_CH4)) +/* 0x110, 0x114, 0x118, 0x11C: INTR_EN, INTR_DIS, INTR_MASK, INTR_STS */ +#define XVPHY_INTR_TXRESETDONE_MASK 0x00000001 +#define XVPHY_INTR_RXRESETDONE_MASK 0x00000002 +#define XVPHY_INTR_CPLL_LOCK_MASK 0x00000004 +#define XVPHY_INTR_QPLL0_LOCK_MASK 0x00000008 +#define XVPHY_INTR_TXALIGNDONE_MASK 0x00000010 +#define XVPHY_INTR_QPLL1_LOCK_MASK 0x00000020 +#define XVPHY_INTR_TXCLKDETFREQCHANGE_MASK 0x00000040 +#define XVPHY_INTR_RXCLKDETFREQCHANGE_MASK 0x00000080 +#define XVPHY_INTR_TXTMRTIMEOUT_MASK 0x40000000 +#define XVPHY_INTR_RXTMRTIMEOUT_MASK 0x80000000 +#define XVPHY_INTR_QPLL_LOCK_MASK XVPHY_INTR_QPLL0_LOCK_MASK +/* 0x120, 0x140: MMCM_TXUSRCLK_CTRL, MMCM_RXUSRCLK_CTRL */ +#define XVPHY_MMCM_USRCLK_CTRL_CFG_NEW_MASK 0x01 +#define XVPHY_MMCM_USRCLK_CTRL_RST_MASK 0x02 +#define XVPHY_MMCM_USRCLK_CTRL_CFG_SUCCESS_MASK 0x10 +#define XVPHY_MMCM_USRCLK_CTRL_LOCKED_MASK 0x20 +#define XVPHY_MMCM_USRCLK_CTRL_PWRDWN_MASK 0x400 +#define XVPHY_MMCM_USRCLK_CTRL_LOCKED_MASK_MASK 0x800 +/* 0x124, 0x144: MMCM_TXUSRCLK_REG1, MMCM_RXUSRCLK_REG1 */ +#define XVPHY_MMCM_USRCLK_REG1_DIVCLK_MASK \ + 0x00000FF +#define XVPHY_MMCM_USRCLK_REG1_CLKFBOUT_MULT_MASK \ + 0x000FF00 +#define XVPHY_MMCM_USRCLK_REG1_CLKFBOUT_MULT_SHIFT \ + 8 +#define XVPHY_MMCM_USRCLK_REG1_CLKFBOUT_FRAC_MASK \ + 0x3FF0000 +#define XVPHY_MMCM_USRCLK_REG1_CLKFBOUT_FRAC_SHIFT \ + 16 +/* 0x128, 0x148: MMCM_TXUSRCLK_REG2, MMCM_RXUSRCLK_REG2 */ +#define XVPHY_MMCM_USRCLK_REG2_DIVCLK_MASK \ + 0x00000FF +#define XVPHY_MMCM_USRCLK_REG2_CLKOUT0_FRAC_MASK \ + 0x3FF0000 +#define XVPHY_MMCM_USRCLK_REG2_CLKOUT0_FRAC_SHIFT \ + 16 +/* 0x12C, 0x130, 0x14C, 0x150: MMCM_TXUSRCLK_REG[3,4], MMCM_RXUSRCLK_REG[3,4] */ +#define XVPHY_MMCM_USRCLK_REG34_DIVCLK_MASK \ + 0x00000FF +/* 0x134, 0x154: BUFGT_TXUSRCLK, BUFGT_RXUSRCLK */ +#define XVPHY_BUFGGT_XXUSRCLK_CLR_MASK 0x1 +#define XVPHY_BUFGGT_XXUSRCLK_DIV_MASK 0xE +#define XVPHY_BUFGGT_XXUSRCLK_DIV_SHIFT 1 +/* 0x138, 0x158: MISC_TXUSRCLK_REG, MISC_RXUSERCLK_REG */ +#define XVPHY_MISC_XXUSRCLK_CKOUT1_OEN_MASK 0x1 +#define XVPHY_MISC_XXUSRCLK_REFCLK_CEB_MASK 0x2 +/* 0x200: CLKDET_CTRL */ +#define XVPHY_CLKDET_CTRL_RUN_MASK 0x1 +#define XVPHY_CLKDET_CTRL_TX_TMR_CLR_MASK 0x2 +#define XVPHY_CLKDET_CTRL_RX_TMR_CLR_MASK 0x4 +#define XVPHY_CLKDET_CTRL_TX_FREQ_RST_MASK 0x8 +#define XVPHY_CLKDET_CTRL_RX_FREQ_RST_MASK 0x10 +#define XVPHY_CLKDET_CTRL_FREQ_LOCK_THRESH_MASK 0x1FE0 +#define XVPHY_CLKDET_CTRL_FREQ_LOCK_THRESH_SHIFT 5 +/* 0x204: CLKDET_STAT */ +#define XVPHY_CLKDET_STAT_TX_FREQ_ZERO_MASK 0x1 +#define XVPHY_CLKDET_STAT_RX_FREQ_ZERO_MASK 0x2 +#define XVPHY_CLKDET_STAT_TX_REFCLK_LOCK_MASK 0x3 +#define XVPHY_CLKDET_STAT_TX_REFCLK_LOCK_CAP_MASK 0x4 +/* 0x300: DRU_CTRL */ +#define XVPHY_DRU_CTRL_RST_MASK(Ch) (0x01 << (8 * (Ch - 1))) +#define XVPHY_DRU_CTRL_EN_MASK(Ch) (0x02 << (8 * (Ch - 1))) +/* 0x304: DRU_STAT */ +#define XVPHY_DRU_STAT_ACTIVE_MASK(Ch) (0x01 << (8 * (Ch - 1))) +#define XVPHY_DRU_STAT_VERSION_MASK 0xFF000000 +#define XVPHY_DRU_STAT_VERSION_SHIFT 24 +/* 0x30C, 0x318, 0x324, 0x330: DRU_CFREQ_H_CH[1-4] */ +#define XVPHY_DRU_CFREQ_H_MASK 0x1F +/* 0x310, 0x31C, 0x328, 0x334: DRU_GAIN_CH[1-4] */ +#define XVPHY_DRU_GAIN_G1_MASK 0x00001F +#define XVPHY_DRU_GAIN_G1_SHIFT 0 +#define XVPHY_DRU_GAIN_G1_P_MASK 0x001F00 +#define XVPHY_DRU_GAIN_G1_P_SHIFT 8 +#define XVPHY_DRU_GAIN_G2_MASK 0x1F0000 +#define XVPHY_DRU_GAIN_G2_SHIFT 16 +/* @} */ + +/******************* Macros (Inline Functions) Definitions ********************/ + +/** @name Register access macro definitions. + * @{ + */ +#define XVphy_In32 Xil_In32 +#define XVphy_Out32 Xil_Out32 +/* @} */ + +/******************************************************************************/ +/** + * This is a low-level function that reads from the specified register. + * + * @param BaseAddress is the base address of the device. + * @param RegOffset is the register offset to be read from. + * + * @return The 32-bit value of the specified register. + * + * @note C-style signature: + * u32 XVphy_ReadReg(u32 BaseAddress, u32 RegOffset) + * +*******************************************************************************/ +#define XVphy_ReadReg(BaseAddress, RegOffset) \ + XVphy_In32((BaseAddress) + (RegOffset)) + +/******************************************************************************/ +/** + * This is a low-level function that writes to the specified register. + * + * @param BaseAddress is the base address of the device. + * @param RegOffset is the register offset to write to. + * @param Data is the 32-bit data to write to the specified register. + * + * @return None. + * + * @note C-style signature: + * void XVphy_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) + * +*******************************************************************************/ +#define XVphy_WriteReg(BaseAddress, RegOffset, Data) \ + XVphy_Out32((BaseAddress) + (RegOffset), (Data)) + +#endif /* XVPHY_HW_H_ */ diff --git a/drivers/staging/xilinx/hdmi/phy-vphy.c b/drivers/staging/xilinx/hdmi/phy-vphy.c new file mode 100644 index 00000000000000..58c951f3ff07cb --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-vphy.c @@ -0,0 +1,633 @@ +/* + * Xilinx VPHY driver + * + * The Video Phy is a high-level wrapper around the GT to configure it + * for video applications. The driver also provides common functionality + * for its tightly-bound video protocol drivers such as HDMI RX/TX. + * + * Copyright (C) 2016, 2017 Leon Woestenberg <leon@sidebranch.com> + * Copyright (C) 2014, 2015, 2017 Xilinx, Inc. + * + * Authors: Leon Woestenberg <leon@sidebranch.com> + * Rohit Consul <rohitco@xilinx.com> + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/* if both both DEBUG and DEBUG_TRACE are defined, trace_printk() is used */ +//#define DEBUG +//#define DEBUG_TRACE + +//#define DEBUG_MUTEX + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/of_address.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <dt-bindings/phy/phy.h> +#include <linux/list.h> +#include <linux/slab.h> +#include <linux/interrupt.h> + +#include "linux/phy/phy-vphy.h" + +/* baseline driver includes */ +#include "phy-xilinx-vphy/xvphy.h" +#include "phy-xilinx-vphy/xvphy_i.h" +#include "phy-xilinx-vphy/xil_printf.h" +#include "phy-xilinx-vphy/xstatus.h" + +/* common RX/TX */ +#include "phy-xilinx-vphy/xvidc.h" +#include "phy-xilinx-vphy/xvidc_edid.h" + +#define XVPHY_DRU_REF_CLK_HZ 156250000 + + +/* select either trace or printk logging */ +#ifdef DEBUG_TRACE +#define do_hdmi_dbg(format, ...) do { \ + trace_printk("xlnx-hdmi-vphy: " format, ##__VA_ARGS__); \ +} while(0) +#else +#define do_hdmi_dbg(format, ...) do { \ + printk(KERN_DEBUG "xlnx-hdmi-vphy: " format, ##__VA_ARGS__); \ +} while(0) +#endif + +/* either enable or disable debugging */ +#ifdef DEBUG +# define hdmi_dbg(x...) do_hdmi_dbg(x) +#else +# define hdmi_dbg(x...) +#endif + +#if (defined(DEBUG_MUTEX) && defined(DEBUG)) +/* storage for source code line number where mutex was last locked, -1 otherwise */ +static int hdmi_mutex_line = -1; +/* If mutex is locked, print the line number of where it was locked. lock the mutex. + * Please keep this macro on a single line, so that the C __LINE__ macro is correct. + */ +# define hdmi_mutex_lock(x) do { if (mutex_is_locked(x)) { hdmi_dbg("@line %d waiting for mutex owner @line %d\n", __LINE__, hdmi_mutex_line); } mutex_lock(x); hdmi_mutex_line = __LINE__; } while(0) +# define hdmi_mutex_unlock(x) do { hdmi_mutex_line = -1; mutex_unlock(x); } while(0) +/* non-debug variant */ +#else +# define hdmi_mutex_lock(x) mutex_lock(x) +# define hdmi_mutex_unlock(x) mutex_unlock(x) +#endif + +/** + * struct xvphy_lane - representation of a lane + * @phy: pointer to the kernel PHY device + * + * @type: controller which uses this lane + * @lane: lane number + * @protocol: protocol in which the lane operates + * @ref_clk: enum of allowed ref clock rates for this lane PLL + * @pll_lock: PLL status + * @data: pointer to hold private data + * @direction: 0=rx, 1=tx + * @share_laneclk: lane number of the clock to be shared + */ +struct xvphy_lane { + struct phy *phy; + u8 type; + u8 lane; + u8 protocol; + bool pll_lock; + /* data is pointer to parent xvphy_dev */ + void *data; + bool direction_tx; + u32 share_laneclk; +}; + +/** + * struct xvphy_dev - representation of a Xilinx Video PHY + * @dev: pointer to device + * @iomem: serdes base address + */ +struct xvphy_dev { + struct device *dev; + /* virtual remapped I/O memory */ + void __iomem *iomem; + int irq; + /* protects the XVphy baseline against concurrent access */ + struct mutex xvphy_mutex; + struct xvphy_lane *lanes[4]; + /* bookkeeping for the baseline subsystem driver instance */ + XVphy xvphy; + /* AXI Lite clock drives the clock detector */ + struct clk *axi_lite_clk; + /* NI-DRU clock input */ + struct clk *clkp; +}; + +/* given the (Linux) phy handle, return the xvphy */ +XVphy *xvphy_get_xvphy(struct phy *phy) +{ + struct xvphy_lane *vphy_lane = phy_get_drvdata(phy); + struct xvphy_dev *vphy_dev = vphy_lane->data; + return &vphy_dev->xvphy; +} +EXPORT_SYMBOL_GPL(xvphy_get_xvphy); + +/* given the (Linux) phy handle, enter critical section of xvphy baseline code + * XVphy functions must be called with mutex acquired to prevent concurrent access + * by XVphy and upper-layer video protocol drivers */ +void xvphy_mutex_lock(struct phy *phy) +{ + struct xvphy_lane *vphy_lane = phy_get_drvdata(phy); + struct xvphy_dev *vphy_dev = vphy_lane->data; + hdmi_mutex_lock(&vphy_dev->xvphy_mutex); +} +EXPORT_SYMBOL_GPL(xvphy_mutex_lock); + +void xvphy_mutex_unlock(struct phy *phy) +{ + struct xvphy_lane *vphy_lane = phy_get_drvdata(phy); + struct xvphy_dev *vphy_dev = vphy_lane->data; + hdmi_mutex_unlock(&vphy_dev->xvphy_mutex); +} +EXPORT_SYMBOL_GPL(xvphy_mutex_unlock); + +/* XVphy functions must be called with mutex acquired to prevent concurrent access + * by XVphy and upper-layer video protocol drivers */ +EXPORT_SYMBOL_GPL(XVphy_GetPllType); +EXPORT_SYMBOL_GPL(XVphy_IBufDsEnable); +EXPORT_SYMBOL_GPL(XVphy_SetHdmiCallback); +EXPORT_SYMBOL_GPL(XVphy_HdmiCfgCalcMmcmParam); +EXPORT_SYMBOL_GPL(XVphy_MmcmStart); + +/* exclusively required by TX */ +EXPORT_SYMBOL_GPL(XVphy_Clkout1OBufTdsEnable); +EXPORT_SYMBOL_GPL(XVphy_SetHdmiTxParam); +EXPORT_SYMBOL_GPL(XVphy_IsBonded); + +static irqreturn_t xvphy_irq_handler(int irq, void *dev_id) +{ + struct xvphy_dev *vphydev; + BUG_ON(!dev_id); + vphydev = (struct xvphy_dev *)dev_id; + BUG_ON(!vphydev); + if (!vphydev) + return IRQ_NONE; + + /* disable interrupts in the VPHY, they are re-enabled once serviced */ + XVphy_IntrDisable(&vphydev->xvphy, XVPHY_INTR_HANDLER_TYPE_TXRESET_DONE | + XVPHY_INTR_HANDLER_TYPE_RXRESET_DONE | + XVPHY_INTR_HANDLER_TYPE_CPLL_LOCK | + XVPHY_INTR_HANDLER_TYPE_QPLL0_LOCK | + XVPHY_INTR_HANDLER_TYPE_TXALIGN_DONE | + XVPHY_INTR_HANDLER_TYPE_QPLL1_LOCK | + XVPHY_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE | + XVPHY_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE | + XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT | + XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); + + return IRQ_WAKE_THREAD; +} + +static irqreturn_t xvphy_irq_thread(int irq, void *dev_id) +{ + struct xvphy_dev *vphydev; + u32 IntrStatus; + BUG_ON(!dev_id); + vphydev = (struct xvphy_dev *)dev_id; + BUG_ON(!vphydev); + if (!vphydev) + return IRQ_NONE; + + /* call baremetal interrupt handler with mutex locked */ + hdmi_mutex_lock(&vphydev->xvphy_mutex); + + IntrStatus = XVphy_ReadReg(vphydev->xvphy.Config.BaseAddr, XVPHY_INTR_STS_REG); + printk(KERN_DEBUG "XVphy IntrStatus = 0x%08x\n", IntrStatus); + + /* handle pending interrupts */ + XVphy_InterruptHandler(&vphydev->xvphy); + hdmi_mutex_unlock(&vphydev->xvphy_mutex); + + /* enable interrupt requesting in the VPHY */ + XVphy_IntrEnable(&vphydev->xvphy, XVPHY_INTR_HANDLER_TYPE_TXRESET_DONE | + XVPHY_INTR_HANDLER_TYPE_RXRESET_DONE | + XVPHY_INTR_HANDLER_TYPE_CPLL_LOCK | + XVPHY_INTR_HANDLER_TYPE_QPLL0_LOCK | + XVPHY_INTR_HANDLER_TYPE_TXALIGN_DONE | + XVPHY_INTR_HANDLER_TYPE_QPLL1_LOCK | + XVPHY_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE | + XVPHY_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE | + XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT | + XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); + +#ifdef DEBUG + XVphy_LogDisplay(&vphydev->xvphy); +#endif + return IRQ_HANDLED; +} + +/** + * xvphy_phy_init - initializes a lane + * @phy: pointer to kernel PHY device + * + * Return: 0 on success or error on failure + */ +static int xvphy_phy_init(struct phy *phy) +{ + BUG_ON(!phy); + printk(KERN_INFO "xvphy_phy_init(%p).\n", phy); + + return 0; +} + +/** + * xvphy_xlate - provides a PHY specific to a controller + * @dev: pointer to device + * @args: arguments from dts + * + * Return: pointer to kernel PHY device or error on failure + * + * + */ +static struct phy *xvphy_xlate(struct device *dev, + struct of_phandle_args *args) +{ + struct xvphy_dev *vphydev = dev_get_drvdata(dev); + struct xvphy_lane *vphy_lane = NULL; + struct device_node *phynode = args->np; + int index; + u8 controller; + u8 instance_num; + + if (args->args_count != 4) { + dev_err(dev, "Invalid number of cells in 'phy' property\n"); + return ERR_PTR(-EINVAL); + } + if (!of_device_is_available(phynode)) { + dev_warn(dev, "requested PHY is disabled\n"); + return ERR_PTR(-ENODEV); + } + for (index = 0; index < of_get_child_count(dev->of_node); index++) { + if (phynode == vphydev->lanes[index]->phy->dev.of_node) { + vphy_lane = vphydev->lanes[index]; + break; + } + } + if (!vphy_lane) { + dev_err(dev, "failed to find appropriate phy\n"); + return ERR_PTR(-EINVAL); + } + + /* get type of controller from lanes */ + controller = args->args[0]; + + /* get controller instance number */ + instance_num = args->args[1]; + + /* Check if lane sharing is required */ + vphy_lane->share_laneclk = args->args[2]; + + /* get the direction for controller from lanes */ + vphy_lane->direction_tx = args->args[3]; + + BUG_ON(!vphy_lane->phy); + return vphy_lane->phy; +} + +/* Local Global table for phy instance(s) configuration settings */ +XVphy_Config XVphy_ConfigTable[XPAR_XVPHY_NUM_INSTANCES]; + +static struct phy_ops xvphy_phyops = { + .init = xvphy_phy_init, + .owner = THIS_MODULE, +}; + +static int instance = 0; +/* TX uses [1, 127] and RX uses [128, 254], VPHY uses [256, ...] */ +#define VPHY_DEVICE_ID_BASE 256 + +static int vphy_parse_of(struct xvphy_dev *vphydev, XVphy_Config *c) +{ + struct device *dev = vphydev->dev; + struct device_node *node = dev->of_node; + int rc; + u32 val; + bool has_err_irq; + + rc = of_property_read_u32(node, "xlnx,transceiver-type", &val); + if (rc < 0) + goto error_dt; + c->XcvrType = val; + + rc = of_property_read_u32(node, "xlnx,tx-buffer-bypass", &val); + if (rc < 0) + goto error_dt; + c->TxBufferBypass = val; + + rc = of_property_read_u32(node, "xlnx,input-pixels-per-clock", &val); + if (rc < 0) + goto error_dt; + c->Ppc = val; + + rc = of_property_read_u32(node, "xlnx,nidru", &val); + if (rc < 0) + goto error_dt; + c->DruIsPresent = val; + + rc = of_property_read_u32(node, "xlnx,nidru-refclk-sel", &val); + if (rc < 0) + goto error_dt; + c->DruRefClkSel = val; + + rc = of_property_read_u32(node, "xlnx,rx-no-of-channels", &val); + if (rc < 0) + goto error_dt; + c->RxChannels = val; + + rc = of_property_read_u32(node, "xlnx,tx-no-of-channels", &val); + if (rc < 0) + goto error_dt; + c->TxChannels = val; + + rc = of_property_read_u32(node, "xlnx,rx-protocol", &val); + if (rc < 0) + goto error_dt; + c->RxProtocol = val; + + rc = of_property_read_u32(node, "xlnx,tx-protocol", &val); + if (rc < 0) + goto error_dt; + c->TxProtocol = val; + + rc = of_property_read_u32(node, "xlnx,rx-refclk-sel", &val); + if (rc < 0) + goto error_dt; + c->RxRefClkSel = val; + + rc = of_property_read_u32(node, "xlnx,tx-refclk-sel", &val); + if (rc < 0) + goto error_dt; + c->TxRefClkSel = val; + + rc = of_property_read_u32(node, "xlnx,rx-pll-selection", &val); + if (rc < 0) + goto error_dt; + c->RxSysPllClkSel = val; + + rc = of_property_read_u32(node, "xlnx,tx-pll-selection", &val); + if (rc < 0) + goto error_dt; + c->TxSysPllClkSel = val; + + rc = of_property_read_u32(node, "xlnx,hdmi-fast-switch", &val); + if (rc < 0) + goto error_dt; + c->HdmiFastSwitch = val; + + rc = of_property_read_u32(node, "xlnx,transceiver-width", &val); + if (rc < 0) + goto error_dt; + c->TransceiverWidth = val; + + has_err_irq = false; + has_err_irq = of_property_read_bool(node, "xlnx,err-irq-en"); + c->ErrIrq = has_err_irq; + return 0; + +error_dt: + dev_err(vphydev->dev, "Error parsing device tree"); + return -EINVAL; +} + +/** + * xvphy_probe - The device probe function for driver initialization. + * @pdev: pointer to the platform device structure. + * + * Return: 0 for success and error value on failure + */ +static int xvphy_probe(struct platform_device *pdev) +{ + struct device_node *child, *np = pdev->dev.of_node; + struct xvphy_dev *vphydev; + struct phy_provider *provider; + struct phy *phy; + unsigned long axi_lite_rate; + unsigned long dru_clk_rate; + + struct resource *res; + int port = 0, index = 0; + int ret; + u32 Status; + u32 Data; + u16 DrpVal; + + hdmi_dbg("xvphy probed\n"); + vphydev = devm_kzalloc(&pdev->dev, sizeof(*vphydev), GFP_KERNEL); + if (!vphydev) + return -ENOMEM; + + /* mutex that protects against concurrent access */ + mutex_init(&vphydev->xvphy_mutex); + + vphydev->dev = &pdev->dev; + /* set a pointer to our driver data */ + platform_set_drvdata(pdev, vphydev); + + BUG_ON(!np); + + XVphy_ConfigTable[instance].DeviceId = VPHY_DEVICE_ID_BASE + instance; + + hdmi_dbg("xvphy_probe DT parse start\n"); + ret = vphy_parse_of(vphydev, &XVphy_ConfigTable[instance]); + if (ret) return ret; + hdmi_dbg("xvphy_probe DT parse done\n"); + + for_each_child_of_node(np, child) { + struct xvphy_lane *vphy_lane; + + vphy_lane = devm_kzalloc(&pdev->dev, sizeof(*vphy_lane), + GFP_KERNEL); + if (!vphy_lane) + return -ENOMEM; + + /* Assign lane number to gtr_phy instance */ + vphy_lane->lane = index; + + /* Disable lane sharing as default */ + vphy_lane->share_laneclk = -1; + + BUG_ON(port >= 4); + /* array of pointer to vphy_lane structs */ + vphydev->lanes[port] = vphy_lane; + + /* create phy device for each lane */ + phy = devm_phy_create(&pdev->dev, child, &xvphy_phyops); + if (IS_ERR(phy)) { + ret = PTR_ERR(phy); + if (ret == -EPROBE_DEFER) + hdmi_dbg("xvphy probe deferred\n"); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "failed to create PHY\n"); + return ret; + } + /* array of pointer to phy */ + vphydev->lanes[port]->phy = phy; + /* where each phy device has vphy_lane as driver data */ + phy_set_drvdata(phy, vphydev->lanes[port]); + /* and each vphy_lane points back to parent device */ + vphy_lane->data = vphydev; + port++; + index++; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + vphydev->iomem = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(vphydev->iomem)) + return PTR_ERR(vphydev->iomem); + + /* set address in configuration data */ + XVphy_ConfigTable[instance].BaseAddr = (uintptr_t)vphydev->iomem; + + vphydev->irq = platform_get_irq(pdev, 0); + if (vphydev->irq <= 0) { + dev_err(&pdev->dev, "platform_get_irq() failed\n"); + return vphydev->irq; + } + + /* the AXI lite clock is used for the clock rate detector */ + vphydev->axi_lite_clk = devm_clk_get(&pdev->dev, "axi-lite"); + if (IS_ERR(vphydev->axi_lite_clk)) { + ret = PTR_ERR(vphydev->axi_lite_clk); + vphydev->axi_lite_clk = NULL; + if (ret == -EPROBE_DEFER) + hdmi_dbg("axi-lite-clk not ready -EPROBE_DEFER\n"); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "failed to get the axi lite clk.\n"); + return ret; + } + + ret = clk_prepare_enable(vphydev->axi_lite_clk); + if (ret) { + dev_err(&pdev->dev, "failed to enable axi-lite clk\n"); + return ret; + } + axi_lite_rate = clk_get_rate(vphydev->axi_lite_clk); + hdmi_dbg("AXI Lite clock rate = %lu Hz\n", axi_lite_rate); + + /* set axi-lite clk in configuration data */ + XVphy_ConfigTable[instance].AxiLiteClkFreq = axi_lite_rate; + + /* dru-clk is used for the nidru block for low res support */ + vphydev->clkp = devm_clk_get(&pdev->dev, "dru-clk"); + if (IS_ERR(vphydev->clkp)) { + ret = PTR_ERR(vphydev->clkp); + vphydev->clkp = NULL; + if (ret == -EPROBE_DEFER) + hdmi_dbg("dru-clk not ready -EPROBE_DEFER\n"); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "failed to get the nidru clk.\n"); + return ret; + } + + ret = clk_prepare_enable(vphydev->clkp); + if (ret) { + dev_err(&pdev->dev, "failed to enable nidru clk\n"); + return ret; + } + + dru_clk_rate = clk_get_rate(vphydev->clkp); + hdmi_dbg("default dru-clk rate = %lu\n", dru_clk_rate); + if (dru_clk_rate != XVPHY_DRU_REF_CLK_HZ) { + ret = clk_set_rate(vphydev->clkp, XVPHY_DRU_REF_CLK_HZ); + if (ret != 0) { + dev_err(&pdev->dev, "Cannot set rate : %d\n", ret); + } + dru_clk_rate = clk_get_rate(vphydev->clkp); + hdmi_dbg("ref dru-clk rate = %lu\n", dru_clk_rate); + } + + provider = devm_of_phy_provider_register(&pdev->dev, xvphy_xlate); + if (IS_ERR(provider)) { + dev_err(&pdev->dev, "registering provider failed\n"); + return PTR_ERR(provider); + } + + + /* Initialize HDMI VPHY */ + Status = XVphy_HdmiInitialize(&vphydev->xvphy, 0/*QuadID*/, + &XVphy_ConfigTable[instance], axi_lite_rate); + if (Status != XST_SUCCESS) { + printk(KERN_INFO "HDMI VPHY initialization error\n"); + return XST_FAILURE; + } + + Data = XVphy_GetVersion(&vphydev->xvphy); + printk(KERN_INFO "VPhy version : %02d.%02d (%04x)\n", ((Data >> 24) & 0xFF), ((Data >> 16) & 0xFF), (Data & 0xFFFF)); + + DrpVal = XVphy_DrpRead(&vphydev->xvphy, 0/*QuadId*/, 1/*ChId*/, 0x7C); + hdmi_dbg("DrpVal @0x7C : 0x%08x%s\n", DrpVal, DrpVal & 0x2000?" GEARBOX ENABLED(?!)":" GEARBOX DISABLED"); + + ret = devm_request_threaded_irq(&pdev->dev, vphydev->irq, xvphy_irq_handler, xvphy_irq_thread, + IRQF_TRIGGER_HIGH /*IRQF_SHARED*/, "xilinx-vphy", vphydev/*dev_id*/); + + if (ret) { + dev_err(&pdev->dev, "unable to request IRQ %d\n", vphydev->irq); + return ret; + } + + hdmi_dbg("config.DruIsPresent = %d\n", XVphy_ConfigTable[instance].DruIsPresent); + if (vphydev->xvphy.Config.DruIsPresent == (TRUE)) { + hdmi_dbg("DRU reference clock frequency %0d Hz\n\r", + XVphy_DruGetRefClkFreqHz(&vphydev->xvphy)); + } + hdmi_dbg("HDMI VPHY initialization completed\n"); + /* probe has succeeded for this instance, increment instance index */ + instance++; + return 0; +} + +/* Match table for of_platform binding */ +static const struct of_device_id xvphy_of_match[] = { + { .compatible = "xlnx,vid-phy-controller-2.0" }, + {}, +}; +MODULE_DEVICE_TABLE(of, xvphy_of_match); + +static struct platform_driver xvphy_driver = { + .probe = xvphy_probe, + .driver = { + .name = "xilinx-vphy", + .of_match_table = xvphy_of_match, + }, +}; +module_platform_driver(xvphy_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Leon Woestenberg <leon@sidebranch.com>"); +MODULE_DESCRIPTION("Xilinx Vphy driver"); + +/* common functionality shared between RX and TX */ +EXPORT_SYMBOL_GPL(XVidC_ReportTiming); +EXPORT_SYMBOL_GPL(XVidC_SetVideoStream); +EXPORT_SYMBOL_GPL(XVidC_ReportStreamInfo); +EXPORT_SYMBOL_GPL(XVidC_EdidGetManName); +EXPORT_SYMBOL_GPL(XVidC_Set3DVideoStream); +EXPORT_SYMBOL_GPL(XVidC_GetPixelClockHzByVmId); +EXPORT_SYMBOL_GPL(XVidC_GetVideoModeId); +EXPORT_SYMBOL_GPL(XVidC_GetPixelClockHzByHVFr); + + diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/sleep.h b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/sleep.h new file mode 100644 index 00000000000000..363ab8b051fb22 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/sleep.h @@ -0,0 +1,34 @@ +/****************************************************************************** +* + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details +* +******************************************************************************/ + +#ifndef SLEEP_H +#define SLEEP_H + +#include "xil_types.h" +#include "xil_io.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int usleep(unsigned long useconds); +unsigned sleep(unsigned int seconds); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xdebug.h b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xdebug.h new file mode 100644 index 00000000000000..650946bd01f455 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xdebug.h @@ -0,0 +1,32 @@ +#ifndef XDEBUG /* prevent circular inclusions */ +#define XDEBUG /* by using protection macros */ + +#if defined(DEBUG) && !defined(NDEBUG) + +#ifndef XDEBUG_WARNING +#define XDEBUG_WARNING +#warning DEBUG is enabled +#endif + +int printf(const char *format, ...); + +#define XDBG_DEBUG_ERROR 0x00000001U /* error condition messages */ +#define XDBG_DEBUG_GENERAL 0x00000002U /* general debug messages */ +#define XDBG_DEBUG_ALL 0xFFFFFFFFU /* all debugging data */ + +#define xdbg_current_types (XDBG_DEBUG_GENERAL) + +#define xdbg_stmnt(x) x + +#define xdbg_printf(type, ...) (((type) & xdbg_current_types) ? printf (__VA_ARGS__) : 0) + + +#else /* defined(DEBUG) && !defined(NDEBUG) */ + +#define xdbg_stmnt(x) + +#define xdbg_printf(...) + +#endif /* defined(DEBUG) && !defined(NDEBUG) */ + +#endif /* XDEBUG */ diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xil_assert.h b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xil_assert.h new file mode 100644 index 00000000000000..c9c84757713d8b --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xil_assert.h @@ -0,0 +1,90 @@ +/****************************************************************************** +* +* Copyright (C) 2009 - 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 xil_assert.h +* +* This file contains assert related functions. +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- ------------------------------------------------------- +* 1.00a hbm 07/14/09 First release +* </pre> +* +******************************************************************************/ + +#ifndef XIL_ASSERT_H /* prevent circular inclusions */ +#define XIL_ASSERT_H /* by using protection macros */ + +#include "xil_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + + +/************************** Constant Definitions *****************************/ + +#define XIL_ASSERT_NONE 0U +#define XIL_ASSERT_OCCURRED 1U +#define XNULL NULL + +/** + * This data type defines a callback to be invoked when an + * assert occurs. The callback is invoked only when asserts are enabled + */ +//typedef void (*Xil_AssertCallback) (const char8 *File, s32 Line); + +/***************** Macros (Inline Functions) Definitions *********************/ + +//#define Xil_Assert(const char8 *File, s32 Line) +//#define Xil_AssertSetCallback(Xil_AssertCallback Routine) + +#define Xil_AssertVoid(Expression) +#define Xil_AssertVoidAlways() +#define Xil_AssertNonvoid(Expression) +#define Xil_AssertNonvoidAlways() + + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xil_io.h b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xil_io.h new file mode 100644 index 00000000000000..3b24af4346411d --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xil_io.h @@ -0,0 +1,72 @@ +/****************************************************************************** +* +* Copyright (C) 2014 - 2015 Xilinx, Inc. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* Use of the Software is limited solely to applications: +* (a) running on a Xilinx device, or +* (b) that interact with a Xilinx device through a bus or interconnect. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +* SOFTWARE. +* +* Except as contained in this notice, the name of the Xilinx shall not be used +* in advertising or otherwise to promote the sale, use or other dealings in +* this Software without prior written authorization from Xilinx. +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_io.h +* +* This file contains the interface for the general IO component, which +* encapsulates the Input/Output functions for processors that do not +* require any special I/O handling. +* +* +* <pre> +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- -------- -------- ----------------------------------------------- +* 5.00 pkp 05/29/14 First release +* </pre> +******************************************************************************/ + +#ifndef XIL_IO_H /* prevent circular inclusions */ +#define XIL_IO_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include <linux/io.h> + +static inline void Xil_Out32(INTPTR Addr, u32 Value) +{ + iowrite32(Value, (volatile void *)Addr); +} +static inline u32 Xil_In32(INTPTR Addr) +{ + return ioread32((const volatile void *)Addr); +} + +#endif /* end of protection macro */ diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xil_printf.h b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xil_printf.h new file mode 100644 index 00000000000000..a90679ed2daecc --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xil_printf.h @@ -0,0 +1,50 @@ + #ifndef XIL_PRINTF_H + #define XIL_PRINTF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __KERNEL__ +#include <ctype.h> +#include <string.h> +#include <stdarg.h> +#endif +#include "xil_types.h" + + +/*----------------------------------------------------*/ +/* Use the following parameter passing structure to */ +/* make xil_printf re-entrant. */ +/*----------------------------------------------------*/ + +struct params_s; + + +/*---------------------------------------------------*/ +/* The purpose of this routine is to output data the */ +/* same as the standard printf function without the */ +/* overhead most run-time libraries involve. Usually */ +/* the printf brings in many kilobytes of code and */ +/* that is unacceptable in most embedded systems. */ +/*---------------------------------------------------*/ + +typedef char8* charptr; +typedef s32 (*func_ptr)(int c); + +/* */ + +void xil_printf( const char8 *ctrl1, ...); +void print( const char8 *ptr); +extern void outbyte (char8 c); +extern char8 inbyte(void); + +#ifdef __cplusplus +} +#endif + +#include <linux/module.h> +#define xil_printf(format, ...) printk(KERN_INFO format, ## __VA_ARGS__) +#define print(format) printk(KERN_INFO format) + +#endif /* end of protection macro */ diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xil_types.h b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xil_types.h new file mode 100644 index 00000000000000..f1dc072a378149 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xil_types.h @@ -0,0 +1,200 @@ +/****************************************************************************** +* + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xil_types.h +* +* @addtogroup common_types Basic Data types for Xilinx® Software IP +* +* The xil_types.h file contains basic types for Xilinx software IP. These data types +* are applicable for all processors supported by Xilinx. +* @{ +* <pre> +* MODIFICATION HISTORY: +* +* Ver Who Date Changes +* ----- ---- -------- ------------------------------------------------------- +* 1.00a hbm 07/14/09 First release +* 3.03a sdm 05/30/11 Added Xuint64 typedef and XUINT64_MSW/XUINT64_LSW macros +* 5.00 pkp 05/29/14 Made changes for 64 bit architecture +* srt 07/14/14 Use standard definitions from stdint.h and stddef.h +* Define LONG and ULONG datatypes and mask values +* </pre> +* +******************************************************************************/ + +#ifndef XIL_TYPES_H /* prevent circular inclusions */ +#define XIL_TYPES_H /* by using protection macros */ + +#ifndef __KERNEL__ +#include <stdint.h> +#include <stddef.h> +#endif + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +# define TRUE 1U +#endif + +#ifndef FALSE +# define FALSE 0U +#endif + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#define XIL_COMPONENT_IS_READY 0x11111111U /**< In device drivers, This macro will be + assigend to "IsReady" member of driver + instance to indicate that driver + instance is initialized and ready to use. */ +#define XIL_COMPONENT_IS_STARTED 0x22222222U /**< In device drivers, This macro will be assigend to + "IsStarted" member of driver instance + to indicate that driver instance is + started and it can be enabled. */ + +/* @name New types + * New simple types. + * @{ + */ +#ifndef __KERNEL__ +#ifndef XBASIC_TYPES_H +/* + * guarded against xbasic_types.h. + */ +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +/** @}*/ +#define __XUINT64__ +typedef struct +{ + u32 Upper; + u32 Lower; +} Xuint64; + + +/*****************************************************************************/ +/** +* @brief Return the most significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The upper 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_MSW(x) ((x).Upper) + +/*****************************************************************************/ +/** +* @brief Return the least significant half of the 64 bit data type. +* +* @param x is the 64 bit word. +* +* @return The lower 32 bits of the 64 bit word. +* +******************************************************************************/ +#define XUINT64_LSW(x) ((x).Lower) + +#endif /* XBASIC_TYPES_H */ + +/* + * xbasic_types.h does not typedef s* or u64 + */ +/** @{ */ +typedef char char8; +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; +typedef uint64_t u64; +typedef int sint32; + +typedef intptr_t INTPTR; +typedef uintptr_t UINTPTR; +typedef ptrdiff_t PTRDIFF; +/** @}*/ +#if !defined(LONG) || !defined(ULONG) +typedef long LONG; +typedef unsigned long ULONG; +#endif + +#define ULONG64_HI_MASK 0xFFFFFFFF00000000U +#define ULONG64_LO_MASK ~ULONG64_HI_MASK + +#else +#include <linux/types.h> +// Used by xil_io.h +typedef char char8; +typedef long INTPTR; +typedef uintptr_t UINTPTR; +typedef ptrdiff_t PTRDIFF; +#endif + +/** @{ */ +/** + * This data type defines an interrupt handler for a device. + * The argument points to the instance of the component + */ +typedef void (*XInterruptHandler) (void *InstancePtr); + +/** + * This data type defines an exception handler for a processor. + * The argument points to the instance of the component + */ +typedef void (*XExceptionHandler) (void *InstancePtr); + +/** + * @brief Returns 32-63 bits of a number. + * @param n : Number being accessed. + * @return Bits 32-63 of number. + * + * @note A basic shift-right of a 64- or 32-bit quantity. + * Use this to suppress the "right shift count >= width of type" + * warning when that quantity is 32-bits. + */ +#define UPPER_32_BITS(n) ((u32)(((n) >> 16) >> 16)) + +/** + * @brief Returns 0-31 bits of a number + * @param n : Number being accessed. + * @return Bits 0-31 of number + */ +#define LOWER_32_BITS(n) ((u32)(n)) + + + + +/************************** Constant Definitions *****************************/ + +#ifndef TRUE +#define TRUE 1U +#endif + +#ifndef FALSE +#define FALSE 0U +#endif + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_types". +*/ diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xstatus.h b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xstatus.h new file mode 100644 index 00000000000000..5f4835fa66094a --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xstatus.h @@ -0,0 +1,519 @@ +/****************************************************************************** +* + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details +* +******************************************************************************/ +/*****************************************************************************/ +/** +* +* @file xstatus.h +* +* @addtogroup common_status_codes Xilinx® software status codes +* +* The xstatus.h file contains the Xilinx® software status codes.These codes are +* used throughout the Xilinx device drivers. +* +* @{ +******************************************************************************/ + +#ifndef XSTATUS_H /* prevent circular inclusions */ +#define XSTATUS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" + +/************************** Constant Definitions *****************************/ + +/*********************** Common statuses 0 - 500 *****************************/ +/** +@name Common Status Codes for All Device Drivers +@{ +*/ +#define XST_SUCCESS 0L +#define XST_FAILURE 1L +#define XST_DEVICE_NOT_FOUND 2L +#define XST_DEVICE_BLOCK_NOT_FOUND 3L +#define XST_INVALID_VERSION 4L +#define XST_DEVICE_IS_STARTED 5L +#define XST_DEVICE_IS_STOPPED 6L +#define XST_FIFO_ERROR 7L /*!< An error occurred during an + operation with a FIFO such as + an underrun or overrun, this + error requires the device to + be reset */ +#define XST_RESET_ERROR 8L /*!< An error occurred which requires + the device to be reset */ +#define XST_DMA_ERROR 9L /*!< A DMA error occurred, this error + typically requires the device + using the DMA to be reset */ +#define XST_NOT_POLLED 10L /*!< The device is not configured for + polled mode operation */ +#define XST_FIFO_NO_ROOM 11L /*!< A FIFO did not have room to put + the specified data into */ +#define XST_BUFFER_TOO_SMALL 12L /*!< The buffer is not large enough + to hold the expected data */ +#define XST_NO_DATA 13L /*!< There was no data available */ +#define XST_REGISTER_ERROR 14L /*!< A register did not contain the + expected value */ +#define XST_INVALID_PARAM 15L /*!< An invalid parameter was passed + into the function */ +#define XST_NOT_SGDMA 16L /*!< The device is not configured for + scatter-gather DMA operation */ +#define XST_LOOPBACK_ERROR 17L /*!< A loopback test failed */ +#define XST_NO_CALLBACK 18L /*!< A callback has not yet been + registered */ +#define XST_NO_FEATURE 19L /*!< Device is not configured with + the requested feature */ +#define XST_NOT_INTERRUPT 20L /*!< Device is not configured for + interrupt mode operation */ +#define XST_DEVICE_BUSY 21L /*!< Device is busy */ +#define XST_ERROR_COUNT_MAX 22L /*!< The error counters of a device + have maxed out */ +#define XST_IS_STARTED 23L /*!< Used when part of device is + already started i.e. + sub channel */ +#define XST_IS_STOPPED 24L /*!< Used when part of device is + already stopped i.e. + sub channel */ +#define XST_DATA_LOST 26L /*!< Driver defined error */ +#define XST_RECV_ERROR 27L /*!< Generic receive error */ +#define XST_SEND_ERROR 28L /*!< Generic transmit error */ +#define XST_NOT_ENABLED 29L /*!< A requested service is not + available because it has not + been enabled */ +/** @} */ +/***************** Utility Component statuses 401 - 500 *********************/ +/** +@name Utility Component Status Codes 401 - 500 +@{ +*/ +#define XST_MEMTEST_FAILED 401L /*!< Memory test failed */ + +/** @} */ +/***************** Common Components statuses 501 - 1000 *********************/ +/** +@name Packet Fifo Status Codes 501 - 510 +@{ +*/ +/********************* Packet Fifo statuses 501 - 510 ************************/ + +#define XST_PFIFO_LACK_OF_DATA 501L /*!< Not enough data in FIFO */ +#define XST_PFIFO_NO_ROOM 502L /*!< Not enough room in FIFO */ +#define XST_PFIFO_BAD_REG_VALUE 503L /*!< Self test, a register value + was invalid after reset */ +#define XST_PFIFO_ERROR 504L /*!< Generic packet FIFO error */ +#define XST_PFIFO_DEADLOCK 505L /*!< Packet FIFO is reporting + * empty and full simultaneously + */ +/** @} */ +/** +@name DMA Status Codes 511 - 530 +@{ +*/ +/************************** DMA statuses 511 - 530 ***************************/ + +#define XST_DMA_TRANSFER_ERROR 511L /*!< Self test, DMA transfer + failed */ +#define XST_DMA_RESET_REGISTER_ERROR 512L /*!< Self test, a register value + was invalid after reset */ +#define XST_DMA_SG_LIST_EMPTY 513L /*!< Scatter gather list contains + no buffer descriptors ready + to be processed */ +#define XST_DMA_SG_IS_STARTED 514L /*!< Scatter gather not stopped */ +#define XST_DMA_SG_IS_STOPPED 515L /*!< Scatter gather not running */ +#define XST_DMA_SG_LIST_FULL 517L /*!< All the buffer desciptors of + the scatter gather list are + being used */ +#define XST_DMA_SG_BD_LOCKED 518L /*!< The scatter gather buffer + descriptor which is to be + copied over in the scatter + list is locked */ +#define XST_DMA_SG_NOTHING_TO_COMMIT 519L /*!< No buffer descriptors have been + put into the scatter gather + list to be commited */ +#define XST_DMA_SG_COUNT_EXCEEDED 521L /*!< The packet count threshold + specified was larger than the + total # of buffer descriptors + in the scatter gather list */ +#define XST_DMA_SG_LIST_EXISTS 522L /*!< The scatter gather list has + already been created */ +#define XST_DMA_SG_NO_LIST 523L /*!< No scatter gather list has + been created */ +#define XST_DMA_SG_BD_NOT_COMMITTED 524L /*!< The buffer descriptor which was + being started was not committed + to the list */ +#define XST_DMA_SG_NO_DATA 525L /*!< The buffer descriptor to start + has already been used by the + hardware so it can't be reused + */ +#define XST_DMA_SG_LIST_ERROR 526L /*!< General purpose list access + error */ +#define XST_DMA_BD_ERROR 527L /*!< General buffer descriptor + error */ +/** @} */ +/** +@name IPIF Status Codes Codes 531 - 550 +@{ +*/ +/************************** IPIF statuses 531 - 550 ***************************/ + +#define XST_IPIF_REG_WIDTH_ERROR 531L /*!< An invalid register width + was passed into the function */ +#define XST_IPIF_RESET_REGISTER_ERROR 532L /*!< The value of a register at + reset was not valid */ +#define XST_IPIF_DEVICE_STATUS_ERROR 533L /*!< A write to the device interrupt + status register did not read + back correctly */ +#define XST_IPIF_DEVICE_ACK_ERROR 534L /*!< The device interrupt status + register did not reset when + acked */ +#define XST_IPIF_DEVICE_ENABLE_ERROR 535L /*!< The device interrupt enable + register was not updated when + other registers changed */ +#define XST_IPIF_IP_STATUS_ERROR 536L /*!< A write to the IP interrupt + status register did not read + back correctly */ +#define XST_IPIF_IP_ACK_ERROR 537L /*!< The IP interrupt status register + did not reset when acked */ +#define XST_IPIF_IP_ENABLE_ERROR 538L /*!< IP interrupt enable register was + not updated correctly when other + registers changed */ +#define XST_IPIF_DEVICE_PENDING_ERROR 539L /*!< The device interrupt pending + register did not indicate the + expected value */ +#define XST_IPIF_DEVICE_ID_ERROR 540L /*!< The device interrupt ID register + did not indicate the expected + value */ +#define XST_IPIF_ERROR 541L /*!< Generic ipif error */ +/** @} */ + +/****************** Device specific statuses 1001 - 4095 *********************/ +/** +@name Ethernet Status Codes 1001 - 1050 +@{ +*/ +/********************* Ethernet statuses 1001 - 1050 *************************/ + +#define XST_EMAC_MEMORY_SIZE_ERROR 1001L /*!< Memory space is not big enough + * to hold the minimum number of + * buffers or descriptors */ +#define XST_EMAC_MEMORY_ALLOC_ERROR 1002L /*!< Memory allocation failed */ +#define XST_EMAC_MII_READ_ERROR 1003L /*!< MII read error */ +#define XST_EMAC_MII_BUSY 1004L /*!< An MII operation is in progress */ +#define XST_EMAC_OUT_OF_BUFFERS 1005L /*!< Driver is out of buffers */ +#define XST_EMAC_PARSE_ERROR 1006L /*!< Invalid driver init string */ +#define XST_EMAC_COLLISION_ERROR 1007L /*!< Excess deferral or late + * collision on polled send */ +/** @} */ +/** +@name UART Status Codes 1051 - 1075 +@{ +*/ +/*********************** UART statuses 1051 - 1075 ***************************/ +#define XST_UART + +#define XST_UART_INIT_ERROR 1051L +#define XST_UART_START_ERROR 1052L +#define XST_UART_CONFIG_ERROR 1053L +#define XST_UART_TEST_FAIL 1054L +#define XST_UART_BAUD_ERROR 1055L +#define XST_UART_BAUD_RANGE 1056L + +/** @} */ +/** +@name IIC Status Codes 1076 - 1100 +@{ +*/ +/************************ IIC statuses 1076 - 1100 ***************************/ + +#define XST_IIC_SELFTEST_FAILED 1076 /*!< self test failed */ +#define XST_IIC_BUS_BUSY 1077 /*!< bus found busy */ +#define XST_IIC_GENERAL_CALL_ADDRESS 1078 /*!< mastersend attempted with */ + /* general call address */ +#define XST_IIC_STAND_REG_RESET_ERROR 1079 /*!< A non parameterizable reg */ + /* value after reset not valid */ +#define XST_IIC_TX_FIFO_REG_RESET_ERROR 1080 /*!< Tx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_RX_FIFO_REG_RESET_ERROR 1081 /*!< Rx fifo included in design */ + /* value after reset not valid */ +#define XST_IIC_TBA_REG_RESET_ERROR 1082 /*!< 10 bit addr incl in design */ + /* value after reset not valid */ +#define XST_IIC_CR_READBACK_ERROR 1083 /*!< Read of the control register */ + /* didn't return value written */ +#define XST_IIC_DTR_READBACK_ERROR 1084 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_DRR_READBACK_ERROR 1085 /*!< Read of the data Receive reg */ + /* didn't return value written */ +#define XST_IIC_ADR_READBACK_ERROR 1086 /*!< Read of the data Tx reg */ + /* didn't return value written */ +#define XST_IIC_TBA_READBACK_ERROR 1087 /*!< Read of the 10 bit addr reg */ + /* didn't return written value */ +#define XST_IIC_NOT_SLAVE 1088 /*!< The device isn't a slave */ +/** @} */ +/** +@name ATMC Status Codes 1101 - 1125 +@{ +*/ +/*********************** ATMC statuses 1101 - 1125 ***************************/ + +#define XST_ATMC_ERROR_COUNT_MAX 1101L /*!< the error counters in the ATM + controller hit the max value + which requires the statistics + to be cleared */ +/** @} */ +/** +@name Flash Status Codes 1126 - 1150 +@{ +*/ +/*********************** Flash statuses 1126 - 1150 **************************/ + +#define XST_FLASH_BUSY 1126L /*!< Flash is erasing or programming + */ +#define XST_FLASH_READY 1127L /*!< Flash is ready for commands */ +#define XST_FLASH_ERROR 1128L /*!< Flash had detected an internal + error. Use XFlash_DeviceControl + to retrieve device specific codes + */ +#define XST_FLASH_ERASE_SUSPENDED 1129L /*!< Flash is in suspended erase state + */ +#define XST_FLASH_WRITE_SUSPENDED 1130L /*!< Flash is in suspended write state + */ +#define XST_FLASH_PART_NOT_SUPPORTED 1131L /*!< Flash type not supported by + driver */ +#define XST_FLASH_NOT_SUPPORTED 1132L /*!< Operation not supported */ +#define XST_FLASH_TOO_MANY_REGIONS 1133L /*!< Too many erase regions */ +#define XST_FLASH_TIMEOUT_ERROR 1134L /*!< Programming or erase operation + aborted due to a timeout */ +#define XST_FLASH_ADDRESS_ERROR 1135L /*!< Accessed flash outside its + addressible range */ +#define XST_FLASH_ALIGNMENT_ERROR 1136L /*!< Write alignment error */ +#define XST_FLASH_BLOCKING_CALL_ERROR 1137L /*!< Couldn't return immediately from + write/erase function with + XFL_NON_BLOCKING_WRITE/ERASE + option cleared */ +#define XST_FLASH_CFI_QUERY_ERROR 1138L /*!< Failed to query the device */ +/** @} */ +/** +@name SPI Status Codes 1151 - 1175 +@{ +*/ +/*********************** SPI statuses 1151 - 1175 ****************************/ + +#define XST_SPI_MODE_FAULT 1151 /*!< master was selected as slave */ +#define XST_SPI_TRANSFER_DONE 1152 /*!< data transfer is complete */ +#define XST_SPI_TRANSMIT_UNDERRUN 1153 /*!< slave underruns transmit register */ +#define XST_SPI_RECEIVE_OVERRUN 1154 /*!< device overruns receive register */ +#define XST_SPI_NO_SLAVE 1155 /*!< no slave has been selected yet */ +#define XST_SPI_TOO_MANY_SLAVES 1156 /*!< more than one slave is being + * selected */ +#define XST_SPI_NOT_MASTER 1157 /*!< operation is valid only as master */ +#define XST_SPI_SLAVE_ONLY 1158 /*!< device is configured as slave-only + */ +#define XST_SPI_SLAVE_MODE_FAULT 1159 /*!< slave was selected while disabled */ +#define XST_SPI_SLAVE_MODE 1160 /*!< device has been addressed as slave */ +#define XST_SPI_RECEIVE_NOT_EMPTY 1161 /*!< device received data in slave mode */ + +#define XST_SPI_COMMAND_ERROR 1162 /*!< unrecognised command - qspi only */ +#define XST_SPI_POLL_DONE 1163 /*!< controller completed polling the + device for status */ +/** @} */ +/** +@name OPB Arbiter Status Codes 1176 - 1200 +@{ +*/ +/********************** OPB Arbiter statuses 1176 - 1200 *********************/ + +#define XST_OPBARB_INVALID_PRIORITY 1176 /*!< the priority registers have either + * one master assigned to two or more + * priorities, or one master not + * assigned to any priority + */ +#define XST_OPBARB_NOT_SUSPENDED 1177 /*!< an attempt was made to modify the + * priority levels without first + * suspending the use of priority + * levels + */ +#define XST_OPBARB_PARK_NOT_ENABLED 1178 /*!< bus parking by id was enabled but + * bus parking was not enabled + */ +#define XST_OPBARB_NOT_FIXED_PRIORITY 1179 /*!< the arbiter must be in fixed + * priority mode to allow the + * priorities to be changed + */ +/** @} */ +/** +@name INTC Status Codes 1201 - 1225 +@{ +*/ +/************************ Intc statuses 1201 - 1225 **************************/ + +#define XST_INTC_FAIL_SELFTEST 1201 /*!< self test failed */ +#define XST_INTC_CONNECT_ERROR 1202 /*!< interrupt already in use */ +/** @} */ +/** +@name TmrCtr Status Codes 1226 - 1250 +@{ +*/ +/********************** TmrCtr statuses 1226 - 1250 **************************/ + +#define XST_TMRCTR_TIMER_FAILED 1226 /*!< self test failed */ +/** @} */ +/** +@name WdtTb Status Codes 1251 - 1275 +@{ +*/ +/********************** WdtTb statuses 1251 - 1275 ***************************/ + +#define XST_WDTTB_TIMER_FAILED 1251L +/** @} */ +/** +@name PlbArb status Codes 1276 - 1300 +@{ +*/ +/********************** PlbArb statuses 1276 - 1300 **************************/ + +#define XST_PLBARB_FAIL_SELFTEST 1276L +/** @} */ +/** +@name Plb2Opb Status Codes 1301 - 1325 +@{ +*/ +/********************** Plb2Opb statuses 1301 - 1325 *************************/ + +#define XST_PLB2OPB_FAIL_SELFTEST 1301L +/** @} */ +/** +@name Opb2Plb Status 1326 - 1350 +@{ +*/ +/********************** Opb2Plb statuses 1326 - 1350 *************************/ + +#define XST_OPB2PLB_FAIL_SELFTEST 1326L +/** @} */ +/** +@name SysAce Status Codes 1351 - 1360 +@{ +*/ +/********************** SysAce statuses 1351 - 1360 **************************/ + +#define XST_SYSACE_NO_LOCK 1351L /*!< No MPU lock has been granted */ +/** @} */ +/** +@name PCI Bridge Status Codes 1361 - 1375 +@{ +*/ +/********************** PCI Bridge statuses 1361 - 1375 **********************/ + +#define XST_PCI_INVALID_ADDRESS 1361L +/** @} */ +/** +@name FlexRay Constants 1400 - 1409 +@{ +*/ +/********************** FlexRay constants 1400 - 1409 *************************/ + +#define XST_FR_TX_ERROR 1400 +#define XST_FR_TX_BUSY 1401 +#define XST_FR_BUF_LOCKED 1402 +#define XST_FR_NO_BUF 1403 +/** @} */ +/** +@name USB constants 1410 - 1420 +@{ +*/ +/****************** USB constants 1410 - 1420 *******************************/ + +#define XST_USB_ALREADY_CONFIGURED 1410 +#define XST_USB_BUF_ALIGN_ERROR 1411 +#define XST_USB_NO_DESC_AVAILABLE 1412 +#define XST_USB_BUF_TOO_BIG 1413 +#define XST_USB_NO_BUF 1414 +/** @} */ +/** +@name HWICAP constants 1421 - 1429 +@{ +*/ +/****************** HWICAP constants 1421 - 1429 *****************************/ + +#define XST_HWICAP_WRITE_DONE 1421 + +/** @} */ +/** +@name AXI VDMA constants 1430 - 1440 +@{ +*/ +/****************** AXI VDMA constants 1430 - 1440 *****************************/ + +#define XST_VDMA_MISMATCH_ERROR 1430 +/** @} */ +/** +@name NAND Flash Status Codes 1441 - 1459 +@{ +*/ +/*********************** NAND Flash statuses 1441 - 1459 *********************/ + +#define XST_NAND_BUSY 1441L /*!< Flash is erasing or + * programming + */ +#define XST_NAND_READY 1442L /*!< Flash is ready for commands + */ +#define XST_NAND_ERROR 1443L /*!< Flash had detected an + * internal error. + */ +#define XST_NAND_PART_NOT_SUPPORTED 1444L /*!< Flash type not supported by + * driver + */ +#define XST_NAND_OPT_NOT_SUPPORTED 1445L /*!< Operation not supported + */ +#define XST_NAND_TIMEOUT_ERROR 1446L /*!< Programming or erase + * operation aborted due to a + * timeout + */ +#define XST_NAND_ADDRESS_ERROR 1447L /*!< Accessed flash outside its + * addressible range + */ +#define XST_NAND_ALIGNMENT_ERROR 1448L /*!< Write alignment error + */ +#define XST_NAND_PARAM_PAGE_ERROR 1449L /*!< Failed to read parameter + * page of the device + */ +#define XST_NAND_CACHE_ERROR 1450L /*!< Flash page buffer error + */ + +#define XST_NAND_WRITE_PROTECTED 1451L /*!< Flash is write protected + */ +/** @} */ + +/**************************** Type Definitions *******************************/ + +typedef s32 XStatus; + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ +/** +* @} End of "addtogroup common_status_codes". +*/ diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvidc.c b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvidc.c new file mode 100644 index 00000000000000..318bf7f926e3cd --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvidc.c @@ -0,0 +1,1013 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvidc.c + * @addtogroup video_common_v4_0 + * @{ + * + * Contains common utility functions that are typically used by video-related + * drivers and applications. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 rc, 01/10/15 Initial release. + * als + * 2.2 als 02/01/16 Functions with pointer arguments that don't modify + * contents now const. + * Added ability to insert a custom video timing table. + * yh Added 3D support. + * 3.0 aad 05/13/16 Added API to search for RB video modes. + * 3.1 rco 07/26/16 Added extern definition for timing table array + * Added video-in-memory color formats + * Updated XVidC_RegisterCustomTimingModes API signature + * 4.1 rco 11/23/16 Added new memory formats + * Added new API to get video mode id that matches exactly + * with provided timing information + * Fix c++ warnings + * </pre> + * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xil_assert.h" +#include "xstatus.h" +#include "xvidc.h" + +/*************************** Variable Declarations ****************************/ +extern const XVidC_VideoTimingMode XVidC_VideoTimingModes[XVIDC_VM_NUM_SUPPORTED]; + +const XVidC_VideoTimingMode *XVidC_CustomTimingModes = NULL; +int XVidC_NumCustomModes = 0; + +/**************************** Function Prototypes *****************************/ + +static const XVidC_VideoTimingMode *XVidC_GetCustomVideoModeData( + XVidC_VideoMode VmId); +static u8 XVidC_IsVtmRb(const char *VideoModeStr, u8 RbN); + +/*************************** Function Definitions *****************************/ + +/******************************************************************************/ +/** + * This function registers a user-defined custom video mode timing table with + * video_common. Functions which search the available video modes, or take VmId + * as an input, will operate on or check the custom video mode timing table in + * addition to the pre-defined video mode timing table (XVidC_VideoTimingModes). + * + * @param CustomTable is a pointer to the user-defined custom vide mode + * timing table to register. + * @param NumElems is the number of video modes supported by CustomTable. + * + * @return + * - XST_SUCCESS if the custom table was successfully registered. + * - XST_FAILURE if an existing custom table is already present. + * + * @note IDs in the custom table may not conflict with IDs reserved by + * the XVidC_VideoMode enum. + * +*******************************************************************************/ +u32 XVidC_RegisterCustomTimingModes(const XVidC_VideoTimingMode *CustomTable, + u16 NumElems) +{ + u16 Index; + + /* Verify arguments. */ + Xil_AssertNonvoid(CustomTable != NULL); + for (Index = 0; Index < NumElems; Index++) { + Xil_AssertNonvoid((CustomTable[Index].VmId > XVIDC_VM_CUSTOM)); + /* The IDs of each video mode in the custom table must not + * conflict with IDs reserved by video_common. */ + } + + /* Fail if a custom table is currently already registered. */ + if (XVidC_CustomTimingModes) { + return XST_FAILURE; + } + + XVidC_CustomTimingModes = CustomTable; + XVidC_NumCustomModes = NumElems; + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function unregisters the user-defined custom video mode timing table + * previously registered by XVidC_RegisterCustomTimingModes(). + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XVidC_UnregisterCustomTimingModes(void) +{ + XVidC_CustomTimingModes = NULL; + XVidC_NumCustomModes = 0; +} + +/******************************************************************************/ +/** + * This function calculates pixel clock based on the inputs. + * + * @param HTotal specifies horizontal total. + * @param VTotal specifies vertical total. + * @param FrameRate specifies rate at which frames are generated. + * + * @return Pixel clock in Hz. + * + * @note None. + * +*******************************************************************************/ +u32 XVidC_GetPixelClockHzByHVFr(u32 HTotal, u32 VTotal, u8 FrameRate) +{ + return (HTotal * VTotal * FrameRate); +} + +/******************************************************************************/ +/** + * This function calculates pixel clock from video mode. + * + * @param VmId specifies the resolution id. + * + * @return Pixel clock in Hz. + * + * @note None. + * +*******************************************************************************/ +u32 XVidC_GetPixelClockHzByVmId(XVidC_VideoMode VmId) +{ + u32 ClkHz; + const XVidC_VideoTimingMode *VmPtr; + + VmPtr = XVidC_GetVideoModeData(VmId); + if (!VmPtr) { + return 0; + } + + if (XVidC_IsInterlaced(VmId)) { + /* For interlaced mode, use both frame 0 and frame 1 vertical + * totals. */ + ClkHz = VmPtr->Timing.F0PVTotal + VmPtr->Timing.F1VTotal; + + /* Multiply the number of pixels by the frame rate of each + * individual frame (half of the total frame rate). */ + ClkHz *= VmPtr->FrameRate / 2; + } + else { + /* For progressive mode, use only frame 0 vertical total. */ + ClkHz = VmPtr->Timing.F0PVTotal; + + /* Multiply the number of pixels by the frame rate. */ + ClkHz *= VmPtr->FrameRate; + } + + /* Multiply the vertical total by the horizontal total for number of + * pixels. */ + ClkHz *= VmPtr->Timing.HTotal; + + return ClkHz; +} + +/******************************************************************************/ +/** + * This function checks if the input video mode is interlaced/progressive based + * on its ID from the video timings table. + * + * @param VmId specifies the resolution ID from the video timings table. + * + * @return Video format. + * - XVIDC_VF_PROGRESSIVE + * - XVIDC_VF_INTERLACED + * + * @note None. + * +*******************************************************************************/ +XVidC_VideoFormat XVidC_GetVideoFormat(XVidC_VideoMode VmId) +{ + const XVidC_VideoTimingMode *VmPtr; + + VmPtr = XVidC_GetVideoModeData(VmId); + if (!VmPtr) { + return XVIDC_VF_UNKNOWN; + } + + if (VmPtr->Timing.F1VTotal == 0) { + return (XVIDC_VF_PROGRESSIVE); + } + + return (XVIDC_VF_INTERLACED); +} + +/******************************************************************************/ +/** + * This function checks if the input video mode is interlaced based on its ID + * from the video timings table. + * + * @param VmId specifies the resolution ID from the video timings table. + * + * @return + * - 1 if the video timing with the supplied table ID is + * interlaced. + * - 0 if the video timing is progressive. + * + * @note None. + * +*******************************************************************************/ +u8 XVidC_IsInterlaced(XVidC_VideoMode VmId) +{ + if (XVidC_GetVideoFormat(VmId) == XVIDC_VF_INTERLACED) { + return 1; + } + + return 0; +} + +/******************************************************************************/ +/** + * This function returns the Video Mode ID that matches the detected input + * timing, frame rate and I/P flag + * + * @param Timing is the pointer to timing parameters to match + * @param FrameRate specifies refresh rate in HZ + * @param IsInterlaced is flag. + * - 0 = Progressive + * - 1 = Interlaced. + * + * @return Id of a supported video mode. + * + * @note This is an extension of XVidC_GetVideoModeId API to include + * blanking information in match process. No attempt is made to + * search for reduced blanking entries, if any. + * +*******************************************************************************/ +XVidC_VideoMode XVidC_GetVideoModeIdWBlanking(const XVidC_VideoTiming *Timing, + u32 FrameRate, u8 IsInterlaced) +{ + XVidC_VideoMode VmId; + XVidC_VideoTiming const *StdTiming = NULL; + + /* First search for ID with matching Width & Height */ + VmId = XVidC_GetVideoModeId(Timing->HActive, Timing->VActive, FrameRate, + IsInterlaced); + + if(VmId == XVIDC_VM_NOT_SUPPORTED) { + return(VmId); + } else { + + /* Get standard timing info from default timing table */ + StdTiming = XVidC_GetTimingInfo(VmId); + + /* Match against detected timing parameters */ + if((Timing->HActive == StdTiming->HActive) && + (Timing->VActive == StdTiming->VActive) && + (Timing->HTotal == StdTiming->HTotal) && + (Timing->F0PVTotal == StdTiming->F0PVTotal) && + (Timing->HFrontPorch == StdTiming->HFrontPorch) && + (Timing->HSyncWidth == StdTiming->HSyncWidth) && + (Timing->HBackPorch == StdTiming->HBackPorch) && + (Timing->F0PVFrontPorch == StdTiming->F0PVFrontPorch) && + (Timing->F0PVSyncWidth == StdTiming->F0PVSyncWidth) && + (Timing->F0PVBackPorch == StdTiming->F0PVBackPorch)) { + return(VmId); + } else { + return(XVIDC_VM_NOT_SUPPORTED); + } + } +} + +/******************************************************************************/ +/** + * This function returns the Video Mode ID that matches the detected input + * width, height, frame rate and I/P flag + * + * @param Width specifies the number pixels per scanline. + * @param Height specifies the number of scanline's. + * @param FrameRate specifies refresh rate in HZ + * @param IsInterlaced is flag. + * - 0 = Progressive + * - 1 = Interlaced. + * + * @return Id of a supported video mode. + * + * @note None. + * +*******************************************************************************/ +XVidC_VideoMode XVidC_GetVideoModeId(u32 Width, u32 Height, u32 FrameRate, + u8 IsInterlaced) +{ + u32 Low; + u32 High; + u32 Mid; + u32 HActive; + u32 VActive; + u32 Rate; + u32 ResFound = (FALSE); + XVidC_VideoMode Mode; + u16 Index; + + /* First, attempt a linear search on the custom video timing table. */ + if(XVidC_CustomTimingModes) { + for (Index = 0; Index < XVidC_NumCustomModes; Index++) { + HActive = XVidC_CustomTimingModes[Index].Timing.HActive; + VActive = XVidC_CustomTimingModes[Index].Timing.VActive; + Rate = XVidC_CustomTimingModes[Index].FrameRate; + if ((Width == HActive) && + (Height == VActive) && + (FrameRate == Rate)) { + return XVidC_CustomTimingModes[Index].VmId; + } + } + } + + if (IsInterlaced) { + Low = (XVIDC_VM_INTL_START); + High = (XVIDC_VM_INTL_END); + } + else { + Low = (XVIDC_VM_PROG_START); + High = (XVIDC_VM_PROG_END); + } + + HActive = VActive = Rate = 0; + + /* Binary search finds item in sorted array. + * And returns index (zero based) of item + * If item is not found returns flag remains + * FALSE. Search key is "width or HActive" + */ + while (Low <= High) { + Mid = (Low + High) / 2; + HActive = XVidC_VideoTimingModes[Mid].Timing.HActive; + if (Width == HActive) { + ResFound = (TRUE); + break; + } + else if (Width < HActive) { + if (Mid == 0) { + break; + } + else { + High = Mid - 1; + } + } + else { + Low = Mid + 1; + } + } + + /* HActive matched at middle */ + if (ResFound) { + /* Rewind to start index of mode with matching width */ + while ((Mid > 0) && + (XVidC_VideoTimingModes[Mid - 1].Timing.HActive == + Width)) { + --Mid; + } + + ResFound = (FALSE); + VActive = XVidC_VideoTimingModes[Mid].Timing.VActive; + Rate = XVidC_VideoTimingModes[Mid].FrameRate; + + /* Now do a linear search for matching VActive and Frame + * Rate + */ + while (HActive == Width) { + /* check current entry */ + if ((VActive == Height) && (Rate == FrameRate)) { + ResFound = (TRUE); + break; + } + /* Check next entry */ + else { + Mid = Mid + 1; + HActive = + XVidC_VideoTimingModes[Mid].Timing.HActive; + VActive = + XVidC_VideoTimingModes[Mid].Timing.VActive; + Rate = XVidC_VideoTimingModes[Mid].FrameRate; + } + } + Mode = + (ResFound) ? (XVidC_VideoMode)Mid : (XVIDC_VM_NOT_SUPPORTED); + } + else { + Mode = (XVIDC_VM_NOT_SUPPORTED); + } + + return (Mode); +} + +/******************************************************************************/ +/** + * This function returns the video mode ID that matches the detected input + * width, height, frame rate, interlaced or progressive, and reduced blanking. + * + * @param Width specifies the number pixels per scanline. + * @param Height specifies the number of scanline's. + * @param FrameRate specifies refresh rate in HZ + * @param IsInterlaced specifies interlaced or progressive mode: + * - 0 = Progressive + * - 1 = Interlaced. + * @param RbN specifies the type of reduced blanking: + * - 0 = No reduced blanking + * - 1 = RB + * - 2 = RB2 + * + * @return ID of a supported video mode. + * + * @note None. + * +*******************************************************************************/ +XVidC_VideoMode XVidC_GetVideoModeIdRb(u32 Width, u32 Height, + u32 FrameRate, u8 IsInterlaced, u8 RbN) +{ + XVidC_VideoMode VmId; + const XVidC_VideoTimingMode *VtmPtr; + u8 Found = 0; + + VmId = XVidC_GetVideoModeId(Width, Height, FrameRate, + IsInterlaced); + + VtmPtr = XVidC_GetVideoModeData(VmId); + if (!VtmPtr) { + return XVIDC_VM_NOT_SUPPORTED; + } + + while (!Found) { + VtmPtr = XVidC_GetVideoModeData(VmId); + if ((Height != VtmPtr->Timing.VActive) || + (Width != VtmPtr->Timing.HActive) || + (FrameRate != VtmPtr->FrameRate) || + (IsInterlaced && !XVidC_IsInterlaced(VmId))) { + VmId = XVIDC_VM_NOT_SUPPORTED; + break; + } + Found = XVidC_IsVtmRb(XVidC_GetVideoModeStr(VmId), RbN); + if (Found) { + break; + } + VmId = (XVidC_VideoMode)((int)VmId + 1); + } + + return VmId; +} + +/******************************************************************************/ +/** + * This function returns the pointer to video mode data at index provided. + * + * @param VmId specifies the resolution id. + * + * @return Pointer to XVidC_VideoTimingMode structure based on the given + * video mode. + * + * @note None. + * +*******************************************************************************/ +const XVidC_VideoTimingMode *XVidC_GetVideoModeData(XVidC_VideoMode VmId) +{ + if (VmId < XVIDC_VM_NUM_SUPPORTED) { + return &XVidC_VideoTimingModes[VmId]; + } + + return XVidC_GetCustomVideoModeData(VmId); +} + +/******************************************************************************/ +/** + * + * This function returns the resolution name for index specified. + * + * @param VmId specifies the resolution id. + * + * @return Pointer to a resolution name string. + * + * @note None. + * +*******************************************************************************/ +const char *XVidC_GetVideoModeStr(XVidC_VideoMode VmId) +{ + const XVidC_VideoTimingMode *VmPtr; + + if (VmId == XVIDC_VM_CUSTOM) { + return ("Custom video mode"); + } + + VmPtr = XVidC_GetVideoModeData(VmId); + if (!VmPtr) { + return ("Video mode not supported"); + } + + return VmPtr->Name; +} + +/******************************************************************************/ +/** + * This function returns the frame rate name for index specified. + * + * @param VmId specifies the resolution id. + * + * @return Pointer to a frame rate name string. + * + * @note None. + * +*******************************************************************************/ +const char *XVidC_GetFrameRateStr(XVidC_VideoMode VmId) +{ + const XVidC_VideoTimingMode *VmPtr; + + VmPtr = XVidC_GetVideoModeData(VmId); + if (!VmPtr) { + return ("Video mode not supported"); + } + + switch (VmPtr->FrameRate) { + case (XVIDC_FR_24HZ): return ("24Hz"); + case (XVIDC_FR_25HZ): return ("25Hz"); + case (XVIDC_FR_30HZ): return ("30Hz"); + case (XVIDC_FR_50HZ): return ("50Hz"); + case (XVIDC_FR_56HZ): return ("56Hz"); + case (XVIDC_FR_60HZ): return ("60Hz"); + case (XVIDC_FR_65HZ): return ("65Hz"); + case (XVIDC_FR_67HZ): return ("67Hz"); + case (XVIDC_FR_70HZ): return ("70Hz"); + case (XVIDC_FR_72HZ): return ("72Hz"); + case (XVIDC_FR_75HZ): return ("75Hz"); + case (XVIDC_FR_85HZ): return ("85Hz"); + case (XVIDC_FR_87HZ): return ("87Hz"); + case (XVIDC_FR_88HZ): return ("88Hz"); + case (XVIDC_FR_100HZ): return ("100Hz"); + case (XVIDC_FR_120HZ): return ("120Hz"); + + default: + return ("Frame rate not supported"); + } +} + +/******************************************************************************/ +/** + * This function returns a string representation of the enumerated type, + * XVidC_3DFormat. + * + * @param Format specifies the value to convert. + * + * @return Pointer to the converted string. + * + * @note None. + * +*******************************************************************************/ +const char *XVidC_Get3DFormatStr(XVidC_3DFormat Format) +{ + switch (Format) { + case XVIDC_3D_FRAME_PACKING: + return ("Frame Packing"); + + case XVIDC_3D_FIELD_ALTERNATIVE: + return ("Field Alternative"); + + case XVIDC_3D_LINE_ALTERNATIVE: + return ("Line Alternative"); + + case XVIDC_3D_SIDE_BY_SIDE_FULL: + return ("Side-by-Side(full)"); + + case XVIDC_3D_TOP_AND_BOTTOM_HALF: + return ("Top-and-Bottom(half)"); + + case XVIDC_3D_SIDE_BY_SIDE_HALF: + return ("Side-by-Side(half)"); + + default: + return ("Unknown"); + } +} + +/******************************************************************************/ +/** + * This function returns the color format name for index specified. + * + * @param ColorFormatId specifies the index of color format space. + * + * @return Pointer to a color space name string. + * + * @note None. + * +*******************************************************************************/ +const char *XVidC_GetColorFormatStr(XVidC_ColorFormat ColorFormatId) +{ + switch (ColorFormatId) { + case XVIDC_CSF_RGB: return ("RGB"); + case XVIDC_CSF_YCRCB_444: return ("YUV_444"); + case XVIDC_CSF_YCRCB_422: return ("YUV_422"); + case XVIDC_CSF_YCRCB_420: return ("YUV_420"); + case XVIDC_CSF_YONLY: return ("Y_ONLY"); + case XVIDC_CSF_MEM_RGBX8: return ("RGBX8"); + case XVIDC_CSF_MEM_YUVX8: return ("YUVX8"); + case XVIDC_CSF_MEM_YUYV8: return ("YUYV8"); + case XVIDC_CSF_MEM_RGBA8: return ("RGBA8"); + case XVIDC_CSF_MEM_YUVA8: return ("YUVA8"); + case XVIDC_CSF_MEM_RGBX10: return ("RGBX10"); + case XVIDC_CSF_MEM_YUVX10: return ("YUVX10"); + case XVIDC_CSF_MEM_RGB565: return ("RGB565"); + case XVIDC_CSF_MEM_Y_UV8: return ("Y_UV8"); + case XVIDC_CSF_MEM_Y_UV8_420: return ("Y_UV8_420"); + case XVIDC_CSF_MEM_RGB8: return ("RGB8"); + case XVIDC_CSF_MEM_YUV8: return ("YUV8"); + case XVIDC_CSF_MEM_Y_UV10: return ("Y_UV10"); + case XVIDC_CSF_MEM_Y_UV10_420: return ("Y_UV10_420"); + case XVIDC_CSF_MEM_Y8: return ("Y8"); + case XVIDC_CSF_MEM_Y10: return ("Y10"); + case XVIDC_CSF_MEM_BGRA8: return ("BGRA8"); + + default: + return ("Color space format not supported"); + } +} + +/******************************************************************************/ +/** + * This function returns the frame rate for index specified. + * + * @param VmId specifies the resolution id. + * + * @return Frame rate in Hz. + * + * @note None. + * +*******************************************************************************/ +XVidC_FrameRate XVidC_GetFrameRate(XVidC_VideoMode VmId) +{ + const XVidC_VideoTimingMode *VmPtr; + + VmPtr = XVidC_GetVideoModeData(VmId); + if (!VmPtr) { + return XVIDC_FR_NUM_SUPPORTED; + } + + return VmPtr->FrameRate; +} + +/******************************************************************************/ +/** + * This function returns the timing parameters for specified resolution. + * + * @param VmId specifies the resolution id. + * + * @return Pointer to a XVidC_VideoTiming structure. + * + * @note None. + * +*******************************************************************************/ +const XVidC_VideoTiming *XVidC_GetTimingInfo(XVidC_VideoMode VmId) +{ + const XVidC_VideoTimingMode *VmPtr; + + VmPtr = XVidC_GetVideoModeData(VmId); + if (!VmPtr) { + return NULL; + } + + return &VmPtr->Timing; +} + +/******************************************************************************/ +/** + * This function sets the VideoStream structure for the specified video format. + * + * @param VidStrmPtr is a pointer to the XVidC_VideoStream structure to be + * set. + * @param VmId specifies the resolution ID. + * @param ColorFormat specifies the color format type. + * @param Bpc specifies the color depth/bits per color component. + * @param Ppc specifies the pixels per clock. + * + * @return + * - XST_SUCCESS if the timing for the supplied ID was found. + * - XST_FAILURE, otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XVidC_SetVideoStream(XVidC_VideoStream *VidStrmPtr, XVidC_VideoMode VmId, + XVidC_ColorFormat ColorFormat, XVidC_ColorDepth Bpc, + XVidC_PixelsPerClock Ppc) +{ + const XVidC_VideoTiming *TimingPtr; + + /* Verify arguments. */ + Xil_AssertNonvoid(VidStrmPtr != NULL); + Xil_AssertNonvoid((ColorFormat == XVIDC_CSF_RGB) || + (ColorFormat == XVIDC_CSF_YCRCB_444) || + (ColorFormat == XVIDC_CSF_YCRCB_422) || + (ColorFormat == XVIDC_CSF_YCRCB_420) || + (ColorFormat == XVIDC_CSF_UNKNOWN)); + Xil_AssertNonvoid((Bpc == XVIDC_BPC_6) || + (Bpc == XVIDC_BPC_8) || + (Bpc == XVIDC_BPC_10) || + (Bpc == XVIDC_BPC_12) || + (Bpc == XVIDC_BPC_14) || + (Bpc == XVIDC_BPC_16) || + (Bpc == XVIDC_BPC_UNKNOWN)); + Xil_AssertNonvoid((Ppc == XVIDC_PPC_1) || + (Ppc == XVIDC_PPC_2) || + (Ppc == XVIDC_PPC_4)); + + /* Get the timing from the video timing table. */ + if (VmId != XVIDC_VM_CUSTOM) { + TimingPtr = XVidC_GetTimingInfo(VmId); + if (!TimingPtr) { + return XST_FAILURE; + } + + VidStrmPtr->Timing = *TimingPtr; + VidStrmPtr->FrameRate = XVidC_GetFrameRate(VmId); + VidStrmPtr->IsInterlaced = XVidC_IsInterlaced(VmId); + + } else { //Custom Timing - use as-is + VidStrmPtr->IsInterlaced = FALSE; + } + VidStrmPtr->VmId = VmId; + VidStrmPtr->ColorFormatId = ColorFormat; + VidStrmPtr->ColorDepth = Bpc; + VidStrmPtr->PixPerClk = Ppc; + + /* Set stream to 2D. */ + VidStrmPtr->Is3D = FALSE; + VidStrmPtr->Info_3D.Format = XVIDC_3D_UNKNOWN; + VidStrmPtr->Info_3D.Sampling.Method = XVIDC_3D_SAMPLING_UNKNOWN; + VidStrmPtr->Info_3D.Sampling.Position = XVIDC_3D_SAMPPOS_UNKNOWN; + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function sets the VideoStream structure for the specified 3D video + * format. + * + * @param VidStrmPtr is a pointer to the XVidC_VideoStream structure to be + * set. + * @param VmId specifies the resolution ID. + * @param ColorFormat specifies the color format type. + * @param Bpc specifies the color depth/bits per color component. + * @param Ppc specifies the pixels per clock. + * @param Info3DPtr is a pointer to a XVidC_3DInfo structure. + * + * @return + * - XST_SUCCESS if the timing for the supplied ID was found. + * - XST_FAILURE, otherwise. + * + * @return + * - XST_SUCCESS + * - XST_FAILURE + * + * @note None. + * +*******************************************************************************/ +u32 XVidC_Set3DVideoStream(XVidC_VideoStream *VidStrmPtr, XVidC_VideoMode VmId, + XVidC_ColorFormat ColorFormat, XVidC_ColorDepth Bpc, + XVidC_PixelsPerClock Ppc, XVidC_3DInfo *Info3DPtr) +{ + u32 Status; + u16 Vblank0; + u16 Vblank1; + + /* Verify arguments */ + Xil_AssertNonvoid(Info3DPtr != NULL); + + /* Initialize with info for 2D frame. */ + Status = XVidC_SetVideoStream(VidStrmPtr, VmId, ColorFormat, Bpc, Ppc); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* Set stream to 3D. */ + VidStrmPtr->Is3D = TRUE; + VidStrmPtr->Info_3D = *Info3DPtr; + + /* Only 3D format supported is frame packing. */ + if (Info3DPtr->Format != XVIDC_3D_FRAME_PACKING) { + return XST_FAILURE; + } + + /* Update the timing based on the 3D format. */ + + /* An interlaced format is converted to a progressive frame: */ + /* 3D VActive = (2D VActive * 4) + (2D VBlank field0) + + (2D Vblank field1 * 2) */ + if (VidStrmPtr->IsInterlaced) { + Vblank0 = VidStrmPtr->Timing.F0PVTotal - + VidStrmPtr->Timing.VActive; + Vblank1 = VidStrmPtr->Timing.F1VTotal - + VidStrmPtr->Timing.VActive; + VidStrmPtr->Timing.VActive = (VidStrmPtr->Timing.VActive * 4) + + Vblank0 + (Vblank1 * 2); + + /* Set VTotal */ + VidStrmPtr->Timing.F0PVTotal *= 2; + VidStrmPtr->Timing.F0PVTotal += VidStrmPtr->Timing.F1VTotal * 2; + + /* Clear field 1 values. */ + VidStrmPtr->Timing.F1VFrontPorch = 0; + VidStrmPtr->Timing.F1VSyncWidth = 0; + VidStrmPtr->Timing.F1VBackPorch = 0; + VidStrmPtr->Timing.F1VTotal = 0; + + /* Set format to progressive */ + VidStrmPtr->IsInterlaced = FALSE; + } + /* Progressive */ + else { + /* 3D Vactive = (2D VActive * 2) + (2D VBlank) */ + Vblank0 = VidStrmPtr->Timing.F0PVTotal - + VidStrmPtr->Timing.VActive; + VidStrmPtr->Timing.VActive = (VidStrmPtr->Timing.VActive * 2) + + Vblank0; + + /* Set VTotal. */ + VidStrmPtr->Timing.F0PVTotal = VidStrmPtr->Timing.F0PVTotal * 2; + } + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** + * This function prints the stream information on STDIO/UART console. + * + * @param Stream is a pointer to video stream. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XVidC_ReportStreamInfo(const XVidC_VideoStream *Stream) +{ + if (!XVidC_GetVideoModeData(Stream->VmId) && + (Stream->VmId != XVIDC_VM_CUSTOM)) { + xil_printf("\tThe stream ID (%d) is not supported.\r\n", + Stream->VmId); + return; + } + + xil_printf("\tColor Format: %s\r\n", + XVidC_GetColorFormatStr(Stream->ColorFormatId)); + xil_printf("\tColor Depth: %d\r\n", Stream->ColorDepth); + xil_printf("\tPixels Per Clock: %d\r\n", Stream->PixPerClk); + xil_printf("\tMode: %s\r\n", + Stream->IsInterlaced ? "Interlaced" : "Progressive"); + + if (Stream->Is3D) { + xil_printf("\t3D Format: %s\r\n", + XVidC_Get3DFormatStr(Stream->Info_3D.Format)); + } + + if (Stream->VmId == XVIDC_VM_CUSTOM) { + xil_printf("\tFrame Rate: %dHz\r\n", + Stream->FrameRate); + xil_printf("\tResolution: %dx%d [Custom Mode]\r\n", + Stream->Timing.HActive, Stream->Timing.VActive); + xil_printf("\tPixel Clock: %d\r\n", + XVidC_GetPixelClockHzByHVFr( + Stream->Timing.HTotal, + Stream->Timing.F0PVTotal, + Stream->FrameRate)); + } + else { + xil_printf("\tFrame Rate: %s\r\n", + XVidC_GetFrameRateStr(Stream->VmId)); + xil_printf("\tResolution: %s\r\n", + XVidC_GetVideoModeStr(Stream->VmId)); + xil_printf("\tPixel Clock: %d\r\n", + XVidC_GetPixelClockHzByVmId(Stream->VmId)); + } +} + +/******************************************************************************/ +/** + * This function prints timing information on STDIO/Uart console. + * + * @param Timing is a pointer to Video Timing structure of the stream. + * @param IsInterlaced is a TRUE/FALSE flag that denotes the timing + * parameter is for interlaced/progressive stream. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XVidC_ReportTiming(const XVidC_VideoTiming *Timing, u8 IsInterlaced) +{ + xil_printf("\r\n\tHSYNC Timing: hav=%04d, hfp=%02d, hsw=%02d(hsp=%d), " + "hbp=%03d, htot=%04d \n\r", Timing->HActive, + Timing->HFrontPorch, Timing->HSyncWidth, + Timing->HSyncPolarity, + Timing->HBackPorch, Timing->HTotal); + + /* Interlaced */ + if (IsInterlaced) { + xil_printf("\tVSYNC Timing (Field 0): vav=%04d, vfp=%02d, " + "vsw=%02d(vsp=%d), vbp=%03d, vtot=%04d\n\r", + Timing->VActive, Timing->F0PVFrontPorch, + Timing->F0PVSyncWidth, Timing->VSyncPolarity, + Timing->F0PVBackPorch, Timing->F0PVTotal); + xil_printf("\tVSYNC Timing (Field 1): vav=%04d, vfp=%02d, " + "vsw=%02d(vsp=%d), vbp=%03d, vtot=%04d\n\r", + Timing->VActive, Timing->F1VFrontPorch, + Timing->F1VSyncWidth, Timing->VSyncPolarity, + Timing->F1VBackPorch, Timing->F1VTotal); + } + /* Progressive */ + else { + xil_printf("\tVSYNC Timing: vav=%04d, vfp=%02d, " + "vsw=%02d(vsp=%d), vbp=%03d, vtot=%04d\n\r", + Timing->VActive, Timing->F0PVFrontPorch, + Timing->F0PVSyncWidth, Timing->VSyncPolarity, + Timing->F0PVBackPorch, Timing->F0PVTotal); + } +} + +/******************************************************************************/ +/** + * This function returns the pointer to video mode data at the provided index + * of the custom video mode table. + * + * @param VmId specifies the resolution ID. + * + * @return Pointer to XVidC_VideoTimingMode structure based on the given + * video mode. + * + * @note None. + * +*******************************************************************************/ +static const XVidC_VideoTimingMode *XVidC_GetCustomVideoModeData( + XVidC_VideoMode VmId) +{ + u16 Index; + + for (Index = 0; Index < XVidC_NumCustomModes; Index++) { + if (VmId == (XVidC_CustomTimingModes[Index].VmId)) { + return &(XVidC_CustomTimingModes[Index]); + } + } + + /* ID not found within the custom video mode table. */ + return NULL; +} + +/******************************************************************************/ +/** + * This function returns whether or not the video timing mode is a reduced + * blanking mode or not. + * + * @param VideoModeStr specifies the resolution name string. + * @param RbN specifies the type of reduced blanking: + * - 0 = No Reduced Blanking + * - 1 = RB + * - 2 = RB2 + * + * @return If the reduced blanking type is compatible with the video mode: + * - 0 = Not supported + * - 1 = Video mode supports the RB type + * + * @note None. + * +*******************************************************************************/ +static u8 XVidC_IsVtmRb(const char *VideoModeStr, u8 RbN) +{ + while ((*VideoModeStr !='\0') && (*VideoModeStr != 'R')) { + VideoModeStr++; + } + + if (*(VideoModeStr + 2) == ')') { + return RbN == 1; + } + if (*(VideoModeStr + 2) == '2') { + return RbN == 2; + } + return 0; +} +/** @} */ diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvidc.h b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvidc.h new file mode 100644 index 00000000000000..e566881d78c306 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvidc.h @@ -0,0 +1,542 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvidc.h + * @addtogroup video_common_v4_0 + * @{ + * @details + * + * Contains common structures, definitions, macros, and utility functions that + * are typically used by video-related drivers and applications. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 rc, 01/10/15 Initial release. + * als + * 2.0 als 08/14/15 Added new video timings. + * 2.2 als 02/01/16 Functions with pointer arguments that don't modify + * contents now const. + * Added ability to insert a custom video timing table: + * XVidC_RegisterCustomTimingModes + * XVidC_UnregisterCustomTimingMode + * yh Added 3D support. + * 3.0 aad 05/13/16 Added API to search for RB video modes. + * als 05/16/16 Added Y-only to color format enum. + * 3.1 rco 07/26/17 Moved timing table extern definition to xvidc.c + * Added video-in-memory color formats + * Updated XVidC_RegisterCustomTimingModes API signature + * 4.1 rco 11/23/17 Added new memory formats + * Added xil_printf include statement + * Added new API XVidC_GetVideoModeIdWBlanking + * Fix C++ warnings + * </pre> + * +*******************************************************************************/ + +#ifndef XVIDC_H_ /* Prevent circular inclusions by using protection macros. */ +#define XVIDC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************* Include Files ********************************/ + +#include "xil_types.h" +#include "xil_printf.h" + +/************************** Constant Definitions ******************************/ + +/** + * This typedef enumerates the list of available standard display monitor + * timings as specified in the xvidc_timings_table.c file. The naming format is: + * + * XVIDC_VM_<RESOLUTION>_<REFRESH RATE (HZ)>_<P|I>(_RB) + * + * Where RB stands for reduced blanking. + */ +typedef enum { + /* Interlaced modes. */ + XVIDC_VM_720x480_60_I = 0, + XVIDC_VM_720x576_50_I, + XVIDC_VM_1440x480_60_I, + XVIDC_VM_1440x576_50_I, + XVIDC_VM_1920x1080_50_I, + XVIDC_VM_1920x1080_60_I, + + /* Progressive modes. */ + XVIDC_VM_640x350_85_P, + XVIDC_VM_640x480_60_P, + XVIDC_VM_640x480_72_P, + XVIDC_VM_640x480_75_P, + XVIDC_VM_640x480_85_P, + XVIDC_VM_720x400_85_P, + XVIDC_VM_720x480_60_P, + XVIDC_VM_720x576_50_P, + XVIDC_VM_800x600_56_P, + XVIDC_VM_800x600_60_P, + XVIDC_VM_800x600_72_P, + XVIDC_VM_800x600_75_P, + XVIDC_VM_800x600_85_P, + XVIDC_VM_800x600_120_P_RB, + XVIDC_VM_848x480_60_P, + XVIDC_VM_1024x768_60_P, + XVIDC_VM_1024x768_70_P, + XVIDC_VM_1024x768_75_P, + XVIDC_VM_1024x768_85_P, + XVIDC_VM_1024x768_120_P_RB, + XVIDC_VM_1152x864_75_P, + XVIDC_VM_1280x720_50_P, + XVIDC_VM_1280x720_60_P, + XVIDC_VM_1280x768_60_P, + XVIDC_VM_1280x768_60_P_RB, + XVIDC_VM_1280x768_75_P, + XVIDC_VM_1280x768_85_P, + XVIDC_VM_1280x768_120_P_RB, + XVIDC_VM_1280x800_60_P, + XVIDC_VM_1280x800_60_P_RB, + XVIDC_VM_1280x800_75_P, + XVIDC_VM_1280x800_85_P, + XVIDC_VM_1280x800_120_P_RB, + XVIDC_VM_1280x960_60_P, + XVIDC_VM_1280x960_85_P, + XVIDC_VM_1280x960_120_P_RB, + XVIDC_VM_1280x1024_60_P, + XVIDC_VM_1280x1024_75_P, + XVIDC_VM_1280x1024_85_P, + XVIDC_VM_1280x1024_120_P_RB, + XVIDC_VM_1360x768_60_P, + XVIDC_VM_1360x768_120_P_RB, + XVIDC_VM_1366x768_60_P, + XVIDC_VM_1400x1050_60_P, + XVIDC_VM_1400x1050_60_P_RB, + XVIDC_VM_1400x1050_75_P, + XVIDC_VM_1400x1050_85_P, + XVIDC_VM_1400x1050_120_P_RB, + XVIDC_VM_1440x240_60_P, + XVIDC_VM_1440x900_60_P, + XVIDC_VM_1440x900_60_P_RB, + XVIDC_VM_1440x900_75_P, + XVIDC_VM_1440x900_85_P, + XVIDC_VM_1440x900_120_P_RB, + XVIDC_VM_1600x1200_60_P, + XVIDC_VM_1600x1200_65_P, + XVIDC_VM_1600x1200_70_P, + XVIDC_VM_1600x1200_75_P, + XVIDC_VM_1600x1200_85_P, + XVIDC_VM_1600x1200_120_P_RB, + XVIDC_VM_1680x720_50_P, + XVIDC_VM_1680x720_60_P, + XVIDC_VM_1680x720_100_P, + XVIDC_VM_1680x720_120_P, + XVIDC_VM_1680x1050_50_P, + XVIDC_VM_1680x1050_60_P, + XVIDC_VM_1680x1050_60_P_RB, + XVIDC_VM_1680x1050_75_P, + XVIDC_VM_1680x1050_85_P, + XVIDC_VM_1680x1050_120_P_RB, + XVIDC_VM_1792x1344_60_P, + XVIDC_VM_1792x1344_75_P, + XVIDC_VM_1792x1344_120_P_RB, + XVIDC_VM_1856x1392_60_P, + XVIDC_VM_1856x1392_75_P, + XVIDC_VM_1856x1392_120_P_RB, + XVIDC_VM_1920x1080_24_P, + XVIDC_VM_1920x1080_25_P, + XVIDC_VM_1920x1080_30_P, + XVIDC_VM_1920x1080_50_P, + XVIDC_VM_1920x1080_60_P, + XVIDC_VM_1920x1080_100_P, + XVIDC_VM_1920x1080_120_P, + XVIDC_VM_1920x1200_60_P, + XVIDC_VM_1920x1200_60_P_RB, + XVIDC_VM_1920x1200_75_P, + XVIDC_VM_1920x1200_85_P, + XVIDC_VM_1920x1200_120_P_RB, + XVIDC_VM_1920x1440_60_P, + XVIDC_VM_1920x1440_75_P, + XVIDC_VM_1920x1440_120_P_RB, + XVIDC_VM_1920x2160_60_P, + XVIDC_VM_2560x1080_50_P, + XVIDC_VM_2560x1080_60_P, + XVIDC_VM_2560x1080_100_P, + XVIDC_VM_2560x1080_120_P, + XVIDC_VM_2560x1600_60_P, + XVIDC_VM_2560x1600_60_P_RB, + XVIDC_VM_2560x1600_75_P, + XVIDC_VM_2560x1600_85_P, + XVIDC_VM_2560x1600_120_P_RB, + XVIDC_VM_3840x2160_24_P, + XVIDC_VM_3840x2160_25_P, + XVIDC_VM_3840x2160_30_P, + XVIDC_VM_3840x2160_50_P, + XVIDC_VM_3840x2160_60_P, + XVIDC_VM_4096x2160_24_P, + XVIDC_VM_4096x2160_25_P, + XVIDC_VM_4096x2160_30_P, + XVIDC_VM_4096x2160_50_P, + XVIDC_VM_4096x2160_60_P, + XVIDC_VM_4096x2160_60_P_RB, + + XVIDC_VM_NUM_SUPPORTED, + XVIDC_VM_USE_EDID_PREFERRED, + XVIDC_VM_NO_INPUT, + XVIDC_VM_NOT_SUPPORTED, + XVIDC_VM_CUSTOM, + + /* Marks beginning/end of interlaced/progressive modes in the table. */ + XVIDC_VM_INTL_START = XVIDC_VM_720x480_60_I, + XVIDC_VM_PROG_START = XVIDC_VM_640x350_85_P, + XVIDC_VM_INTL_END = (XVIDC_VM_PROG_START - 1), + XVIDC_VM_PROG_END = (XVIDC_VM_NUM_SUPPORTED - 1), + + /* Common naming. */ + XVIDC_VM_480_60_I = XVIDC_VM_720x480_60_I, + XVIDC_VM_576_50_I = XVIDC_VM_720x576_50_I, + XVIDC_VM_1080_50_I = XVIDC_VM_1920x1080_50_I, + XVIDC_VM_1080_60_I = XVIDC_VM_1920x1080_60_I, + XVIDC_VM_VGA_60_P = XVIDC_VM_640x480_60_P, + XVIDC_VM_480_60_P = XVIDC_VM_720x480_60_P, + XVIDC_VM_SVGA_60_P = XVIDC_VM_800x600_60_P, + XVIDC_VM_XGA_60_P = XVIDC_VM_1024x768_60_P, + XVIDC_VM_720_50_P = XVIDC_VM_1280x720_50_P, + XVIDC_VM_720_60_P = XVIDC_VM_1280x720_60_P, + XVIDC_VM_WXGA_60_P = XVIDC_VM_1366x768_60_P, + XVIDC_VM_UXGA_60_P = XVIDC_VM_1600x1200_60_P, + XVIDC_VM_WSXGA_60_P = XVIDC_VM_1680x1050_60_P, + XVIDC_VM_1080_24_P = XVIDC_VM_1920x1080_24_P, + XVIDC_VM_1080_25_P = XVIDC_VM_1920x1080_25_P, + XVIDC_VM_1080_30_P = XVIDC_VM_1920x1080_30_P, + XVIDC_VM_1080_50_P = XVIDC_VM_1920x1080_50_P, + XVIDC_VM_1080_60_P = XVIDC_VM_1920x1080_60_P, + XVIDC_VM_WUXGA_60_P = XVIDC_VM_1920x1200_60_P, + XVIDC_VM_UHD2_60_P = XVIDC_VM_1920x2160_60_P, + XVIDC_VM_UHD_24_P = XVIDC_VM_3840x2160_24_P, + XVIDC_VM_UHD_25_P = XVIDC_VM_3840x2160_25_P, + XVIDC_VM_UHD_30_P = XVIDC_VM_3840x2160_30_P, + XVIDC_VM_UHD_60_P = XVIDC_VM_3840x2160_60_P, + XVIDC_VM_4K2K_60_P = XVIDC_VM_4096x2160_60_P, + XVIDC_VM_4K2K_60_P_RB = XVIDC_VM_4096x2160_60_P_RB, +} XVidC_VideoMode; + +/** + * Progressive/interlaced video format. + */ +typedef enum { + XVIDC_VF_PROGRESSIVE = 0, + XVIDC_VF_INTERLACED, + XVIDC_VF_UNKNOWN +} XVidC_VideoFormat; + +/** + * Frame rate. + */ +typedef enum { + XVIDC_FR_24HZ = 24, + XVIDC_FR_25HZ = 25, + XVIDC_FR_30HZ = 30, + XVIDC_FR_50HZ = 50, + XVIDC_FR_56HZ = 56, + XVIDC_FR_60HZ = 60, + XVIDC_FR_65HZ = 65, + XVIDC_FR_67HZ = 67, + XVIDC_FR_70HZ = 70, + XVIDC_FR_72HZ = 72, + XVIDC_FR_75HZ = 75, + XVIDC_FR_85HZ = 85, + XVIDC_FR_87HZ = 87, + XVIDC_FR_88HZ = 88, + XVIDC_FR_100HZ = 100, + XVIDC_FR_120HZ = 120, + XVIDC_FR_NUM_SUPPORTED = 16, + XVIDC_FR_UNKNOWN +} XVidC_FrameRate; + +/** + * Color depth - bits per color component. + */ +typedef enum { + XVIDC_BPC_6 = 6, + XVIDC_BPC_8 = 8, + XVIDC_BPC_10 = 10, + XVIDC_BPC_12 = 12, + XVIDC_BPC_14 = 14, + XVIDC_BPC_16 = 16, + XVIDC_BPC_NUM_SUPPORTED = 6, + XVIDC_BPC_UNKNOWN +} XVidC_ColorDepth; + +/** + * Pixels per clock. + */ +typedef enum { + XVIDC_PPC_1 = 1, + XVIDC_PPC_2 = 2, + XVIDC_PPC_4 = 4, + XVIDC_PPC_8 = 8, + XVIDC_PPC_NUM_SUPPORTED = 4, +} XVidC_PixelsPerClock; + +/** + * Color space format. + */ +typedef enum { + /* Streaming video formats */ + XVIDC_CSF_RGB = 0, + XVIDC_CSF_YCRCB_444, + XVIDC_CSF_YCRCB_422, + XVIDC_CSF_YCRCB_420, + XVIDC_CSF_YONLY, + + /* 6 empty slots reserved for video formats for future + * extension + */ + + /* Video in memory formats */ + XVIDC_CSF_MEM_RGBX8 = 10, // [31:0] x:B:G:R 8:8:8:8 + XVIDC_CSF_MEM_YUVX8, // [31:0] x:V:U:Y 8:8:8:8 + XVIDC_CSF_MEM_YUYV8, // [31:0] V:Y:U:Y 8:8:8:8 + XVIDC_CSF_MEM_RGBA8, // [31:0] A:B:G:R 8:8:8:8 + XVIDC_CSF_MEM_YUVA8, // [31:0] A:V:U:Y 8:8:8:8 + XVIDC_CSF_MEM_RGBX10, // [31:0] x:B:G:R 2:10:10:10 + XVIDC_CSF_MEM_YUVX10, // [31:0] x:V:U:Y 2:10:10:10 + XVIDC_CSF_MEM_RGB565, // [15:0] B:G:R 5:6:5 + XVIDC_CSF_MEM_Y_UV8, // [15:0] Y:Y 8:8, [15:0] V:U 8:8 + XVIDC_CSF_MEM_Y_UV8_420, // [15:0] Y:Y 8:8, [15:0] V:U 8:8 + XVIDC_CSF_MEM_RGB8, // [23:0] B:G:R 8:8:8 + XVIDC_CSF_MEM_YUV8, // [24:0] V:U:Y 8:8:8 + XVIDC_CSF_MEM_Y_UV10, // [31:0] x:Y:Y:Y 2:10:10:10 [31:0] x:U:V:U 2:10:10:10 + XVIDC_CSF_MEM_Y_UV10_420, // [31:0] x:Y:Y:Y 2:10:10:10 [31:0] x:U:V:U 2:10:10:10 + XVIDC_CSF_MEM_Y8, // [31:0] Y:Y:Y:Y 8:8:8:8 + XVIDC_CSF_MEM_Y10, // [31:0] x:Y:Y:Y 2:10:10:10 + XVIDC_CSF_MEM_BGRA8, // [31:0] A:R:G:B 8:8:8:8 + + XVIDC_CSF_NUM_SUPPORTED, // includes the reserved slots + XVIDC_CSF_UNKNOWN, + XVIDC_CSF_STRM_START = XVIDC_CSF_RGB, + XVIDC_CSF_STRM_END = XVIDC_CSF_YONLY, + XVIDC_CSF_MEM_START = XVIDC_CSF_MEM_RGBX8, + XVIDC_CSF_MEM_END = (XVIDC_CSF_NUM_SUPPORTED - 1), + XVIDC_CSF_NUM_STRM = (XVIDC_CSF_STRM_END - XVIDC_CSF_STRM_START + 1), + XVIDC_CSF_NUM_MEM = (XVIDC_CSF_MEM_END - XVIDC_CSF_MEM_START + 1) +} XVidC_ColorFormat; + +/** + * Color space conversion standard. + */ +typedef enum { + XVIDC_BT_2020 = 0, + XVIDC_BT_709, + XVIDC_BT_601, + XVIDC_BT_NUM_SUPPORTED, + XVIDC_BT_UNKNOWN +} XVidC_ColorStd; + +/** + * Color conversion output range. + */ +typedef enum { + XVIDC_CR_16_235 = 0, + XVIDC_CR_16_240, + XVIDC_CR_0_255, + XVIDC_CR_NUM_SUPPORTED, + XVIDC_CR_UNKNOWN_RANGE +} XVidC_ColorRange; + +/** + * 3D formats. + */ +typedef enum { + XVIDC_3D_FRAME_PACKING = 0, /**< Frame packing. */ + XVIDC_3D_FIELD_ALTERNATIVE, /**< Field alternative. */ + XVIDC_3D_LINE_ALTERNATIVE, /**< Line alternative. */ + XVIDC_3D_SIDE_BY_SIDE_FULL, /**< Side-by-side (full). */ + XVIDC_3D_TOP_AND_BOTTOM_HALF, /**< Top-and-bottom (half). */ + XVIDC_3D_SIDE_BY_SIDE_HALF, /**< Side-by-side (half). */ + XVIDC_3D_UNKNOWN +} XVidC_3DFormat; + +/** + * 3D Sub-sampling methods. + */ +typedef enum { + XVIDC_3D_SAMPLING_HORIZONTAL = 0, /**< Horizontal sub-sampling. */ + XVIDC_3D_SAMPLING_QUINCUNX, /**< Quincunx matrix. */ + XVIDC_3D_SAMPLING_UNKNOWN +} XVidC_3DSamplingMethod; + +/** + * 3D Sub-sampling positions. + */ +typedef enum { + XVIDC_3D_SAMPPOS_OLOR = 0, /**< Odd/Left, Odd/Right. */ + XVIDC_3D_SAMPPOS_OLER, /**< Odd/Left, Even/Right. */ + XVIDC_3D_SAMPPOS_ELOR, /**< Even/Left, Odd/Right. */ + XVIDC_3D_SAMPPOS_ELER, /**< Even/Left, Even/Right. */ + XVIDC_3D_SAMPPOS_UNKNOWN +} XVidC_3DSamplingPosition; + +/****************************** Type Definitions ******************************/ + +/** + * Video timing structure. + */ +typedef struct { + u16 HActive; + u16 HFrontPorch; + u16 HSyncWidth; + u16 HBackPorch; + u16 HTotal; + u8 HSyncPolarity; + u16 VActive; + u16 F0PVFrontPorch; + u16 F0PVSyncWidth; + u16 F0PVBackPorch; + u16 F0PVTotal; + u16 F1VFrontPorch; + u16 F1VSyncWidth; + u16 F1VBackPorch; + u16 F1VTotal; + u8 VSyncPolarity; +} XVidC_VideoTiming; + +/** + * 3D Sampling info structure. + */ +typedef struct { + XVidC_3DSamplingMethod Method; + XVidC_3DSamplingPosition Position; +} XVidC_3DSamplingInfo; + +/** + * 3D info structure. + */ +typedef struct { + XVidC_3DFormat Format; + XVidC_3DSamplingInfo Sampling; +} XVidC_3DInfo; + +/** + * Video stream structure. + */ +typedef struct { + XVidC_ColorFormat ColorFormatId; + XVidC_ColorDepth ColorDepth; + XVidC_PixelsPerClock PixPerClk; + XVidC_FrameRate FrameRate; + u8 IsInterlaced; + u8 Is3D; + XVidC_3DInfo Info_3D; + XVidC_VideoMode VmId; + XVidC_VideoTiming Timing; +} XVidC_VideoStream; + +/** + * Video window structure. + */ +typedef struct { + u32 StartX; + u32 StartY; + u32 Width; + u32 Height; +} XVidC_VideoWindow; + +/** + * Video timing mode from the video timing table. + */ +typedef struct { + XVidC_VideoMode VmId; + const char Name[21]; + XVidC_FrameRate FrameRate; + XVidC_VideoTiming Timing; +} XVidC_VideoTimingMode; + +/** + * Callback type which represents a custom timer wait handler. This is only + * used for Microblaze since it doesn't have a native sleep function. To avoid + * dependency on a hardware timer, the default wait functionality is implemented + * using loop iterations; this isn't too accurate. Therefore a custom timer + * handler is used, the user may implement their own wait implementation. + * + * @param TimerPtr is a pointer to the timer instance. + * @param Delay is the duration (msec/usec) to be passed to the timer + * function. + * +*******************************************************************************/ +typedef void (*XVidC_DelayHandler)(void *TimerPtr, u32 Delay); + +/**************************** Function Prototypes *****************************/ + +u32 XVidC_RegisterCustomTimingModes(const XVidC_VideoTimingMode *CustomTable, + u16 NumElems); +void XVidC_UnregisterCustomTimingModes(void); +u32 XVidC_GetPixelClockHzByHVFr(u32 HTotal, u32 VTotal, u8 FrameRate); +u32 XVidC_GetPixelClockHzByVmId(XVidC_VideoMode VmId); +XVidC_VideoFormat XVidC_GetVideoFormat(XVidC_VideoMode VmId); +u8 XVidC_IsInterlaced(XVidC_VideoMode VmId); +const XVidC_VideoTimingMode* XVidC_GetVideoModeData(XVidC_VideoMode VmId); +const char *XVidC_GetVideoModeStr(XVidC_VideoMode VmId); +const char *XVidC_GetFrameRateStr(XVidC_VideoMode VmId); +const char *XVidC_GetColorFormatStr(XVidC_ColorFormat ColorFormatId); +XVidC_FrameRate XVidC_GetFrameRate(XVidC_VideoMode VmId); +const XVidC_VideoTiming* XVidC_GetTimingInfo(XVidC_VideoMode VmId); +void XVidC_ReportStreamInfo(const XVidC_VideoStream *Stream); +void XVidC_ReportTiming(const XVidC_VideoTiming *Timing, u8 IsInterlaced); +const char *XVidC_Get3DFormatStr(XVidC_3DFormat Format); +u32 XVidC_SetVideoStream(XVidC_VideoStream *VidStrmPtr, XVidC_VideoMode VmId, + XVidC_ColorFormat ColorFormat, XVidC_ColorDepth Bpc, + XVidC_PixelsPerClock Ppc); +u32 XVidC_Set3DVideoStream(XVidC_VideoStream *VidStrmPtr, XVidC_VideoMode VmId, + XVidC_ColorFormat ColorFormat, XVidC_ColorDepth Bpc, + XVidC_PixelsPerClock Ppc, XVidC_3DInfo *Info3DPtr); +XVidC_VideoMode XVidC_GetVideoModeId(u32 Width, u32 Height, u32 FrameRate, + u8 IsInterlaced); +XVidC_VideoMode XVidC_GetVideoModeIdRb(u32 Width, u32 Height, u32 FrameRate, + u8 IsInterlaced, u8 RbN); +XVidC_VideoMode XVidC_GetVideoModeIdWBlanking(const XVidC_VideoTiming *Timing, + u32 FrameRate, u8 IsInterlaced); + +/******************* Macros (Inline Functions) Definitions ********************/ + +/*****************************************************************************/ +/** + * This macro check if video stream is 3D or 2D. + * + * @param VidStreamPtr is a pointer to the XVidC_VideoStream structure. + * + * @return 3D(1)/2D(0) + * + * @note C-style signature: + * u8 XDp_IsStream3D(XVidC_VideoStream *VidStreamPtr) + * + *****************************************************************************/ +#define XVidC_IsStream3D(VidStreamPtr) ((VidStreamPtr)->Is3D) + +/*************************** Variable Declarations ****************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* XVIDC_H_ */ +/** @} */ diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvidc_edid.c b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvidc_edid.c new file mode 100644 index 00000000000000..c28dccedfc5395 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvidc_edid.c @@ -0,0 +1,691 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvidc_edid.c + * @addtogroup video_common_v4_0 + * @{ + * + * Contains function definitions related to the Extended Display Identification + * Data (EDID) structure which is present in all monitors. All content in this + * file is agnostic of communication interface protocol. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 11/09/14 Initial release. + * 2.2 als 02/01/16 Functions with pointer arguments that don't modify + * contents now const. + * 4.0 aad 10/26/16 Added API for colormetry which returns fixed point + * in Q0.10 format instead of float. + * </pre> + * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xvidc_edid.h" + +/**************************** Function Prototypes *****************************/ + +static u32 XVidC_EdidIsVideoTimingSupportedPreferredTiming(const u8 *EdidRaw, + const XVidC_VideoTimingMode *VtMode); +static u32 XVidC_EdidIsVideoTimingSupportedEstablishedTimings(const u8 *EdidRaw, + const XVidC_VideoTimingMode *VtMode); +static u32 XVidC_EdidIsVideoTimingSupportedStandardTimings(const u8 *EdidRaw, + const XVidC_VideoTimingMode *VtMode); +static int XVidC_CalculatePower(u8 Base, u8 Power); +static int XVidC_CalculateBinaryFraction_QFormat(u16 Val, u8 DecPtIndex); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * Get the manufacturer name as specified in the vendor and product ID field of + * the supplied base Extended Display Identification Data (EDID). + * + * @param EdidRaw is the supplied base EDID to retrieve the manufacturer + * name from. + * @param ManName is the string that will be modified to hold the + * retrieved manufacturer name. + * + * @return None. + * + * @note The ManName argument is modified with the manufacturer name. + * +*******************************************************************************/ +void XVidC_EdidGetManName(const u8 *EdidRaw, char ManName[4]) +{ + ManName[0] = 0x40 + ((EdidRaw[XVIDC_EDID_VPI_ID_MAN_NAME0] & + XVIDC_EDID_VPI_ID_MAN_NAME0_CHAR0_MASK) >> + XVIDC_EDID_VPI_ID_MAN_NAME0_CHAR0_SHIFT); + ManName[1] = 0x40 + (((EdidRaw[XVIDC_EDID_VPI_ID_MAN_NAME0] & + XVIDC_EDID_VPI_ID_MAN_NAME0_CHAR1_MASK) << + XVIDC_EDID_VPI_ID_MAN_NAME0_CHAR1_POS) | + (EdidRaw[XVIDC_EDID_VPI_ID_MAN_NAME1] >> + XVIDC_EDID_VPI_ID_MAN_NAME1_CHAR1_SHIFT)); + ManName[2] = 0x40 + (EdidRaw[XVIDC_EDID_VPI_ID_MAN_NAME1] & + XVIDC_EDID_VPI_ID_MAN_NAME1_CHAR2_MASK); + ManName[3] = '\0'; +} + +/******************************************************************************/ +/** + * Get the color bit depth (bits per primary color) as specified in the basic + * display parameters and features, video input definition field of the supplied + * base Extended Display Identification Data (EDID). + * + * @param EdidRaw is the supplied base EDID to retrieve color depth + * information from. + * + * @return The number of bits per primary color as specified by the + * supplied base EDID. + * + * @note None. + * +*******************************************************************************/ +XVidC_ColorDepth XVidC_EdidGetColorDepth(const u8 *EdidRaw) +{ + XVidC_ColorDepth Bpc; + + switch (((EdidRaw[XVIDC_EDID_BDISP_VID] & + XVIDC_EDID_BDISP_VID_DIG_BPC_MASK) >> + XVIDC_EDID_BDISP_VID_DIG_BPC_SHIFT)) { + case XVIDC_EDID_BDISP_VID_DIG_BPC_6: + Bpc = XVIDC_BPC_6; + break; + + case XVIDC_EDID_BDISP_VID_DIG_BPC_8: + Bpc = XVIDC_BPC_8; + break; + + case XVIDC_EDID_BDISP_VID_DIG_BPC_10: + Bpc = XVIDC_BPC_10; + break; + + case XVIDC_EDID_BDISP_VID_DIG_BPC_12: + Bpc = XVIDC_BPC_12; + break; + + case XVIDC_EDID_BDISP_VID_DIG_BPC_14: + Bpc = XVIDC_BPC_14; + break; + + case XVIDC_EDID_BDISP_VID_DIG_BPC_16: + Bpc = XVIDC_BPC_16; + break; + + default: + Bpc = XVIDC_BPC_UNKNOWN; + break; + } + + return Bpc; +} + +/******************************************************************************/ +/** + * Calculates the x chromaticity coordinate for red by converting a 10 bit + * binary fraction representation from the supplied base Extended Display + * Identification Data (EDID) to a integer in Q0.10 Format. To convert back + * to float divide the fixed point value by 2^10. + * + * @param EdidRaw is the supplied base EDID to retrieve chromaticity + * information from. + * + * @return The x chromatacity coordinate for red. + * + * @note All values will be accurate to +/-0.0005. + * +*******************************************************************************/ +int XVidC_EdidGetCcRedX(const u8 *EdidRaw) +{ + return XVidC_CalculateBinaryFraction_QFormat( + (EdidRaw[XVIDC_EDID_CC_REDX_HIGH] << + XVIDC_EDID_CC_HIGH_SHIFT) | (EdidRaw[XVIDC_EDID_CC_RG_LOW] >> + XVIDC_EDID_CC_RBX_LOW_SHIFT), 10); +} + +/******************************************************************************/ +/** + * Calculates the y chromaticity coordinate for red by converting a 10 bit + * binary fraction representation from the supplied base Extended Display + * Identification Data (EDID) to a integer in Q0.10 Format. To convert back + * to float divide the fixed point value by 2^10. + * + * @param EdidRaw is the supplied base EDID to retrieve chromaticity + * information from. + * + * @return The y chromatacity coordinate for red. + * + * @note All values will be accurate to +/-0.0005. + * +*******************************************************************************/ +int XVidC_EdidGetCcRedY(const u8 *EdidRaw) +{ + return XVidC_CalculateBinaryFraction_QFormat( + (EdidRaw[XVIDC_EDID_CC_REDY_HIGH] << + XVIDC_EDID_CC_HIGH_SHIFT) | ((EdidRaw[XVIDC_EDID_CC_RG_LOW] & + XVIDC_EDID_CC_RBY_LOW_MASK) >> + XVIDC_EDID_CC_RBY_LOW_SHIFT), 10); +} + +/******************************************************************************/ +/** + * Calculates the x chromaticity coordinate for green by converting a 10 bit + * binary fraction representation from the supplied base Extended Display + * Identification Data (EDID) to a integer in Q0.10 Format. To convert back + * to float divide the fixed point value by 2^10. + * + * @param EdidRaw is the supplied base EDID to retrieve chromaticity + * information from. + * + * @return The x chromatacity coordinate for green. + * + * @note All values will be accurate to +/-0.0005. + * +*******************************************************************************/ +int XVidC_EdidGetCcGreenX(const u8 *EdidRaw) +{ + return XVidC_CalculateBinaryFraction_QFormat( + (EdidRaw[XVIDC_EDID_CC_GREENX_HIGH] << + XVIDC_EDID_CC_HIGH_SHIFT) | ((EdidRaw[XVIDC_EDID_CC_RG_LOW] & + XVIDC_EDID_CC_GWX_LOW_MASK) >> + XVIDC_EDID_CC_GWX_LOW_SHIFT), 10); +} + +/******************************************************************************/ +/** + * Calculates the y chromaticity coordinate for green by converting a 10 bit + * binary fraction representation from the supplied base Extended Display + * Identification Data (EDID) to a integer in Q0.10 Format. To convert back + * to float divide the fixed point value by 2^10. + * + * @param EdidRaw is the supplied base EDID to retrieve chromaticity + * information from. + * + * @return The y chromatacity coordinate for green. + * + * @note All values will be accurate to +/-0.0005. + * +*******************************************************************************/ +int XVidC_EdidGetCcGreenY(const u8 *EdidRaw) +{ + return XVidC_CalculateBinaryFraction_QFormat( + (EdidRaw[XVIDC_EDID_CC_GREENY_HIGH] << + XVIDC_EDID_CC_HIGH_SHIFT) | (EdidRaw[XVIDC_EDID_CC_RG_LOW] & + XVIDC_EDID_CC_GWY_LOW_MASK), 10); +} + +/******************************************************************************/ +/** + * Calculates the x chromaticity coordinate for blue by converting a 10 bit + * binary fraction representation from the supplied base Extended Display + * Identification Data (EDID) to a integer in Q0.10 Format. To convert back + * to float divide the fixed point value by 2^10. + * + * @param EdidRaw is the supplied base EDID to retrieve chromaticity + * information from. + * + * @return The x chromatacity coordinate for blue. + * + * @note All values will be accurate to +/-0.0005. + * +*******************************************************************************/ +int XVidC_EdidGetCcBlueX(const u8 *EdidRaw) +{ + return XVidC_CalculateBinaryFraction_QFormat( + (EdidRaw[XVIDC_EDID_CC_BLUEX_HIGH] << + XVIDC_EDID_CC_HIGH_SHIFT) | (EdidRaw[XVIDC_EDID_CC_BW_LOW] >> + XVIDC_EDID_CC_RBX_LOW_SHIFT), 10); +} + +/******************************************************************************/ +/** + * Calculates the y chromaticity coordinate for blue by converting a 10 bit + * binary fraction representation from the supplied base Extended Display + * Identification Data (EDID) to a integer in Q0.10 Format. To convert back + * to float divide the fixed point value by 2^10. + * + * @param EdidRaw is the supplied base EDID to retrieve chromaticity + * information from. + * + * @return The y chromatacity coordinate for blue. + * + * @note All values will be accurate to +/-0.0005. + * +*******************************************************************************/ +int XVidC_EdidGetCcBlueY(const u8 *EdidRaw) +{ + return XVidC_CalculateBinaryFraction_QFormat( + (EdidRaw[XVIDC_EDID_CC_BLUEY_HIGH] << + XVIDC_EDID_CC_HIGH_SHIFT) | ((EdidRaw[XVIDC_EDID_CC_BW_LOW] & + XVIDC_EDID_CC_RBY_LOW_MASK) >> + XVIDC_EDID_CC_RBY_LOW_SHIFT), 10); +} + +/******************************************************************************/ +/** + * Calculates the x chromaticity coordinate for white by converting a 10 bit + * binary fraction representation from the supplied base Extended Display + * Identification Data (EDID) to a integer in Q0.10 Format. To convert back + * to float divide the fixed point value by 2^10. + * + * @param EdidRaw is the supplied base EDID to retrieve chromaticity + * information from. + * + * @return The x chromatacity coordinate for white. + * + * @note All values will be accurate to +/-0.0005. + * +*******************************************************************************/ +int XVidC_EdidGetCcWhiteX(const u8 *EdidRaw) +{ + return XVidC_CalculateBinaryFraction_QFormat( + (EdidRaw[XVIDC_EDID_CC_WHITEX_HIGH] << + XVIDC_EDID_CC_HIGH_SHIFT) | ((EdidRaw[XVIDC_EDID_CC_BW_LOW] & + XVIDC_EDID_CC_GWX_LOW_MASK) >> XVIDC_EDID_CC_GWX_LOW_SHIFT), 10); +} + +/******************************************************************************/ +/** + * Calculates the y chromaticity coordinate for white by converting a 10 bit + * binary fraction representation from the supplied base Extended Display + * Identification Data (EDID) to an integer in Q0.10 Format. To convert back + * to float divide the fixed point value by 2^10. + * + * @param EdidRaw is the supplied base EDID to retrieve chromaticity + * information from. + * + * @return The y chromatacity coordinate for white. + * + * @note All values will be accurate to +/-0.0005. + * +*******************************************************************************/ +int XVidC_EdidGetCcWhiteY(const u8 *EdidRaw) +{ + return XVidC_CalculateBinaryFraction_QFormat( + (EdidRaw[XVIDC_EDID_CC_WHITEY_HIGH] << + XVIDC_EDID_CC_HIGH_SHIFT) | (EdidRaw[XVIDC_EDID_CC_BW_LOW] & + XVIDC_EDID_CC_GWY_LOW_MASK), 10); +} + +/******************************************************************************/ +/** + * Retrieves the active vertical resolution from the standard timings field of + * the supplied base Extended Display Identification Data (EDID). + * + * @param EdidRaw is the supplied base EDID to check the timing against. + * @param StdTimingsNum specifies which one of the standard timings to + * retrieve from the standard timings field. + * + * @return The vertical active resolution of the specified standard timing + * from the supplied base EDID. + * + * @note StdTimingsNum is an index 1-8. + * +*******************************************************************************/ +u16 XVidC_EdidGetStdTimingsV(const u8 *EdidRaw, u8 StdTimingsNum) +{ + u16 V; + + switch (XVidC_EdidGetStdTimingsAr(EdidRaw, StdTimingsNum)) { + case XVIDC_EDID_STD_TIMINGS_AR_16_10: + V = (10 * XVidC_EdidGetStdTimingsH(EdidRaw, + StdTimingsNum)) / 16; + break; + + case XVIDC_EDID_STD_TIMINGS_AR_4_3: + V = (3 * XVidC_EdidGetStdTimingsH(EdidRaw, + StdTimingsNum)) / 4; + break; + + case XVIDC_EDID_STD_TIMINGS_AR_5_4: + V = (4 * XVidC_EdidGetStdTimingsH(EdidRaw, + StdTimingsNum)) / 5; + break; + + case XVIDC_EDID_STD_TIMINGS_AR_16_9: + V = (9 * XVidC_EdidGetStdTimingsH(EdidRaw, + StdTimingsNum)) / 16; + break; + default: + V = 0; + break; + } + + return V; +} + +/******************************************************************************/ +/** + * Checks whether or not a specified video timing mode is supported as specified + * in the supplied base Extended Display Identification Data (EDID). The + * preferred timing, established timings (I, II, II), and the standard timings + * fields are checked for support. + * + * @param EdidRaw is the supplied base EDID to check the timing against. + * @param VtMode is the video timing mode to check for support. + * + * @return + * - XST_SUCCESS if the video timing mode is supported as specified + * in the supplied base EDID. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +u32 XVidC_EdidIsVideoTimingSupported(const u8 *EdidRaw, + const XVidC_VideoTimingMode *VtMode) +{ + u32 Status; + + /* Check if the video mode is the preferred timing. */ + Status = XVidC_EdidIsVideoTimingSupportedPreferredTiming(EdidRaw, + VtMode); + if (Status == XST_SUCCESS) { + return Status; + } + + /* Check established timings I, II, and III. */ + Status = XVidC_EdidIsVideoTimingSupportedEstablishedTimings(EdidRaw, + VtMode); + if (Status == XST_SUCCESS) { + return Status; + } + + /* Check in standard timings support. */ + Status = XVidC_EdidIsVideoTimingSupportedStandardTimings(EdidRaw, + VtMode); + + return Status; +} + +/******************************************************************************/ +/** + * Checks whether or not a specified video timing mode is the preferred timing + * of the supplied base Extended Display Identification Data (EDID). + * + * @param EdidRaw is the supplied base EDID to check the timing against. + * @param VtMode is the video timing mode to check for support. + * + * @return + * - XST_SUCCESS if the video timing mode is the preferred timing + * as specified in the base EDID. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XVidC_EdidIsVideoTimingSupportedPreferredTiming(const u8 *EdidRaw, + const XVidC_VideoTimingMode *VtMode) +{ + const u8 *Ptm; + + Ptm = &EdidRaw[XVIDC_EDID_PTM]; + + u32 HActive = (((Ptm[XVIDC_EDID_DTD_PTM_HRES_HBLANK_U4] & + XVIDC_EDID_DTD_PTM_XRES_XBLANK_U4_XRES_MASK) >> + XVIDC_EDID_DTD_PTM_XRES_XBLANK_U4_XRES_SHIFT) << 8) | + Ptm[XVIDC_EDID_DTD_PTM_HRES_LSB]; + + u32 VActive = (((Ptm[XVIDC_EDID_DTD_PTM_VRES_VBLANK_U4] & + XVIDC_EDID_DTD_PTM_XRES_XBLANK_U4_XRES_MASK) >> + XVIDC_EDID_DTD_PTM_XRES_XBLANK_U4_XRES_SHIFT) << 8) | + Ptm[XVIDC_EDID_DTD_PTM_VRES_LSB]; + + if (VtMode->Timing.F1VTotal != XVidC_EdidIsDtdPtmInterlaced(EdidRaw)) { + return (XST_FAILURE); + } + else if ((VtMode->Timing.HActive == HActive) && + (VtMode->Timing.VActive == VActive)) { + return (XST_SUCCESS); + } + + return XST_FAILURE; +} + +/******************************************************************************/ +/** + * Checks whether or not a specified video timing mode is supported in the + * established timings field of the supplied base Extended Display + * Identification Data (EDID). + * + * @param EdidRaw is the supplied base EDID to check the timing against. + * @param VtMode is the video timing mode to check for support. + * + * @return + * - XST_SUCCESS if the video timing mode is supported in the + * base EDID's established timings field. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XVidC_EdidIsVideoTimingSupportedEstablishedTimings(const u8 *EdidRaw, + const XVidC_VideoTimingMode *VtMode) +{ + u32 Status = XST_FAILURE; + + /* Check established timings I, II, and III. */ + if ((VtMode->Timing.HActive == 800) && + (VtMode->Timing.VActive == 640) && + (VtMode->FrameRate == XVIDC_FR_56HZ) && + XVidC_EdidSuppEstTimings800x600_56(EdidRaw)) { + Status = XST_SUCCESS; + } + else if ((VtMode->Timing.HActive == 640) && + (VtMode->Timing.VActive == 480) && + (VtMode->FrameRate == XVIDC_FR_60HZ) && + XVidC_EdidSuppEstTimings640x480_60(EdidRaw)) { + Status = XST_SUCCESS; + } + else if ((VtMode->Timing.HActive == 800) && + (VtMode->Timing.VActive == 600) && + (VtMode->FrameRate == XVIDC_FR_60HZ) && + XVidC_EdidSuppEstTimings800x600_60(EdidRaw)) { + Status = XST_SUCCESS; + } + else if ((VtMode->Timing.HActive == 1024) && + (VtMode->Timing.VActive == 768) && + (VtMode->FrameRate == XVIDC_FR_60HZ) && + XVidC_EdidSuppEstTimings1024x768_60(EdidRaw)) { + Status = XST_SUCCESS; + } + else if ((VtMode->Timing.HActive == 640) && + (VtMode->Timing.VActive == 480) && + (VtMode->FrameRate == XVIDC_FR_67HZ) && + XVidC_EdidSuppEstTimings640x480_67(EdidRaw)) { + Status = XST_SUCCESS; + } + else if ((VtMode->Timing.HActive == 720) && + (VtMode->Timing.VActive == 400) && + (VtMode->FrameRate == XVIDC_FR_70HZ) && + XVidC_EdidSuppEstTimings720x400_70(EdidRaw)) { + Status = XST_SUCCESS; + } + else if ((VtMode->Timing.HActive == 1024) && + (VtMode->Timing.VActive == 768) && + (VtMode->FrameRate == XVIDC_FR_70HZ) && + XVidC_EdidSuppEstTimings1024x768_70(EdidRaw)) { + Status = XST_SUCCESS; + } + else if ((VtMode->Timing.HActive == 640) && + (VtMode->Timing.VActive == 480) && + (VtMode->FrameRate == XVIDC_FR_72HZ) && + XVidC_EdidSuppEstTimings640x480_72(EdidRaw)) { + Status = XST_SUCCESS; + } + else if ((VtMode->Timing.HActive == 800) && + (VtMode->Timing.VActive == 600) && + (VtMode->FrameRate == XVIDC_FR_72HZ) && + XVidC_EdidSuppEstTimings800x600_72(EdidRaw)) { + Status = XST_SUCCESS; + } + else if ((VtMode->Timing.HActive == 640) && + (VtMode->Timing.VActive == 480) && + (VtMode->FrameRate == XVIDC_FR_75HZ) && + XVidC_EdidSuppEstTimings640x480_75(EdidRaw)) { + Status = XST_SUCCESS; + } + else if ((VtMode->Timing.HActive == 800) && + (VtMode->Timing.VActive == 600) && + (VtMode->FrameRate == XVIDC_FR_75HZ) && + XVidC_EdidSuppEstTimings800x600_75(EdidRaw)) { + Status = XST_SUCCESS; + } + else if ((VtMode->Timing.HActive == 832) && + (VtMode->Timing.VActive == 624) && + (VtMode->FrameRate == XVIDC_FR_75HZ) && + XVidC_EdidSuppEstTimings832x624_75(EdidRaw)) { + Status = XST_SUCCESS; + } + else if ((VtMode->Timing.HActive == 1024) && + (VtMode->Timing.VActive == 768) && + (VtMode->FrameRate == XVIDC_FR_75HZ) && + XVidC_EdidSuppEstTimings1024x768_75(EdidRaw)) { + Status = XST_SUCCESS; + } + else if ((VtMode->Timing.HActive == 1152) && + (VtMode->Timing.VActive == 870) && + (VtMode->FrameRate == XVIDC_FR_75HZ) && + XVidC_EdidSuppEstTimings1152x870_75(EdidRaw)) { + Status = XST_SUCCESS; + } + else if ((VtMode->Timing.HActive == 1280) && + (VtMode->Timing.VActive == 1024) && + (VtMode->FrameRate == XVIDC_FR_75HZ) && + XVidC_EdidSuppEstTimings1280x1024_75(EdidRaw)) { + Status = XST_SUCCESS; + } + else if ((VtMode->Timing.HActive == 1024) && + (VtMode->Timing.VActive == 768) && + (VtMode->FrameRate == XVIDC_FR_87HZ) && + XVidC_EdidSuppEstTimings1024x768_87(EdidRaw)) { + Status = XST_SUCCESS; + } + else if ((VtMode->Timing.HActive == 720) && + (VtMode->Timing.VActive == 400) && + (VtMode->FrameRate == XVIDC_FR_88HZ) && + XVidC_EdidSuppEstTimings720x400_88(EdidRaw)) { + Status = XST_SUCCESS; + } + + return Status; +} + +/******************************************************************************/ +/** + * Checks whether or not a specified video timing mode is supported in the + * standard timings field of the supplied base Extended Display Identification + * Data (EDID). + * + * @param EdidRaw is the supplied base EDID to check the timing against. + * @param VtMode is the video timing mode to check for support. + * + * @return + * - XST_SUCCESS if the video timing mode is supported in the + * base EDID's standard timings fields. + * - XST_FAILURE otherwise. + * + * @note None. + * +*******************************************************************************/ +static u32 XVidC_EdidIsVideoTimingSupportedStandardTimings(const u8 *EdidRaw, + const XVidC_VideoTimingMode *VtMode) +{ + u8 Index; + + for (Index = 0; Index < 8; Index++) { + if ((VtMode->Timing.HActive == + XVidC_EdidGetStdTimingsH(EdidRaw, Index + 1)) && + (VtMode->Timing.VActive == + XVidC_EdidGetStdTimingsV(EdidRaw, Index + 1)) && + (VtMode->FrameRate == (u8)XVidC_EdidGetStdTimingsFrr( + EdidRaw, Index + 1))) { + return XST_SUCCESS; + } + } + + return XST_FAILURE; +} + +/******************************************************************************/ +/** + * Perform a power operation. + * + * @param Base is b in the power operation, b^n. + * @param Power is n in the power operation, b^n. + * + * @return Base^Power (Base to the power of Power). + * + * @note None. + * +*******************************************************************************/ +static int XVidC_CalculatePower(u8 Base, u8 Power) +{ + u8 Index; + u32 Res = 1; + + for (Index = 0; Index < Power; Index++) { + Res *= Base; + } + + return Res; +} + + +/******************************************************************************/ +/** + * Convert a fractional binary number into a fixed point Q0.DecPtIndex number + * Binary digits to the right of the decimal point represent 2^-1 to + * 2^-(DecPtIndex+1). Binary digits to the left of the decimal point represent + * 2^0, 2^1, etc. For a given Q format, using an unsigned integer container with + * n fractional bits: + * its range is [0, 2^-n] + * its resolution is 2^n + * + * @param Val is the binary representation of the fraction. + * @param DecPtIndex is the index of the decimal point in the binary + * number. The decimal point is between the binary digits at Val's + * indices (DecPtIndex -1) and (DecPtIndex). DecPtIndex will + * determine the Q format resolution. + * + * @return Fixed point representation of the fractional part of the binary + * number in Q format. + * + * @note None. + * +*******************************************************************************/ +static int XVidC_CalculateBinaryFraction_QFormat(u16 Val, u8 DecPtIndex) +{ + int Index; + u32 Res; + + for (Index = DecPtIndex - 1, Res = 0; Index >= 0; Index--) { + if (((Val >> Index) & 0x1) == 1) { + Res += XVidC_CalculatePower(2 , Index); + } + } + + return Res; +} +/** @} */ diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvidc_edid.h b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvidc_edid.h new file mode 100644 index 00000000000000..e18f36623830db --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvidc_edid.h @@ -0,0 +1,468 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvidc_edid.h + * @addtogroup video_common_v4_0 + * @{ + * + * Contains macros, definitions, and function declarations related to the + * Extended Display Identification Data (EDID) structure which is present in all + * monitors. All content in this file is agnostic of communication interface + * protocol. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 11/09/14 Initial release. + * 2.2 als 02/01/16 Functions with pointer arguments that don't modify + * contents now const. + * 4.0 aad 10/26/16 Functions which return fixed point values instead of + * float + * </pre> + * +*******************************************************************************/ + +#ifndef XVIDC_EDID_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XVIDC_EDID_H_ + +#ifdef __cplusplus +extern "C" { +#endif +/******************************* Include Files ********************************/ + +#include "xstatus.h" +#include "xvidc.h" + +/************************** Constant Definitions ******************************/ + +/** @name Address mapping for the base EDID block. + * @{ + */ +#define XVIDC_EDID_HEADER 0x00 +/* Vendor and product identification. */ +#define XVIDC_EDID_VPI_ID_MAN_NAME0 0x08 +#define XVIDC_EDID_VPI_ID_MAN_NAME1 0x09 +#define XVIDC_EDID_VPI_ID_PROD_CODE_LSB 0x0A +#define XVIDC_EDID_VPI_ID_PROD_CODE_MSB 0x0B +#define XVIDC_EDID_VPI_ID_SN0 0x0C +#define XVIDC_EDID_VPI_ID_SN1 0x0D +#define XVIDC_EDID_VPI_ID_SN2 0x0E +#define XVIDC_EDID_VPI_ID_SN3 0x0F +#define XVIDC_EDID_VPI_WEEK_MAN 0x10 +#define XVIDC_EDID_VPI_YEAR 0x11 +/* EDID structure version and revision. */ +#define XVIDC_EDID_STRUCT_VER 0x12 +#define XVIDC_EDID_STRUCT_REV 0x13 +/* Basic display parameters and features. */ +#define XVIDC_EDID_BDISP_VID 0x14 +#define XVIDC_EDID_BDISP_H_SSAR 0x15 +#define XVIDC_EDID_BDISP_V_SSAR 0x16 +#define XVIDC_EDID_BDISP_GAMMA 0x17 +#define XVIDC_EDID_BDISP_FEATURE 0x18 +/* Color characteristics (display x,y chromaticity coordinates). */ +#define XVIDC_EDID_CC_RG_LOW 0x19 +#define XVIDC_EDID_CC_BW_LOW 0x1A +#define XVIDC_EDID_CC_REDX_HIGH 0x1B +#define XVIDC_EDID_CC_REDY_HIGH 0x1C +#define XVIDC_EDID_CC_GREENX_HIGH 0x1D +#define XVIDC_EDID_CC_GREENY_HIGH 0x1E +#define XVIDC_EDID_CC_BLUEX_HIGH 0x1F +#define XVIDC_EDID_CC_BLUEY_HIGH 0x20 +#define XVIDC_EDID_CC_WHITEX_HIGH 0x21 +#define XVIDC_EDID_CC_WHITEY_HIGH 0x22 +/* Established timings. */ +#define XVIDC_EDID_EST_TIMINGS_I 0x23 +#define XVIDC_EDID_EST_TIMINGS_II 0x24 +#define XVIDC_EDID_EST_TIMINGS_MAN 0x25 +/* Standard timings. */ +#define XVIDC_EDID_STD_TIMINGS_H(N) (0x26 + 2 * (N - 1)) +#define XVIDC_EDID_STD_TIMINGS_AR_FRR(N) (0x27 + 2 * (N - 1)) +/* 18 byte descriptors. */ +#define XVIDC_EDID_18BYTE_DESCRIPTOR(N) (0x36 + 18 * (N - 1)) +#define XVIDC_EDID_PTM (XVIDC_EDID_18BYTE_DESCRIPTOR(1)) +/* - Detailed timing descriptor (DTD) / Preferred timing mode (PTM). */ +#define XVIDC_EDID_DTD_PTM_PIXEL_CLK_KHZ_LSB 0x00 +#define XVIDC_EDID_DTD_PTM_PIXEL_CLK_KHZ_MSB 0x01 +#define XVIDC_EDID_DTD_PTM_HRES_LSB 0x02 +#define XVIDC_EDID_DTD_PTM_HBLANK_LSB 0x03 +#define XVIDC_EDID_DTD_PTM_HRES_HBLANK_U4 0x04 +#define XVIDC_EDID_DTD_PTM_VRES_LSB 0x05 +#define XVIDC_EDID_DTD_PTM_VBLANK_LSB 0x06 +#define XVIDC_EDID_DTD_PTM_VRES_VBLANK_U4 0x07 +#define XVIDC_EDID_DTD_PTM_HFPORCH_LSB 0x08 +#define XVIDC_EDID_DTD_PTM_HSPW_LSB 0x09 +#define XVIDC_EDID_DTD_PTM_VFPORCH_VSPW_L4 0x0A +#define XVIDC_EDID_DTD_PTM_XFPORCH_XSPW_U2 0x0B +#define XVIDC_EDID_DTD_PTM_HIMGSIZE_MM_LSB 0x0C +#define XVIDC_EDID_DTD_PTM_VIMGSIZE_MM_LSB 0x0D +#define XVIDC_EDID_DTD_PTM_XIMGSIZE_MM_U4 0x0E +#define XVIDC_EDID_DTD_PTM_HBORDER 0x0F +#define XVIDC_EDID_DTD_PTM_VBORDER 0x10 +#define XVIDC_EDID_DTD_PTM_SIGNAL 0x11 + +/* Extension block count. */ +#define XVIDC_EDID_EXT_BLK_COUNT 0x7E +/* Checksum. */ +#define XVIDC_EDID_CHECKSUM 0x7F +/* @} */ + +/******************************************************************************/ + +/** @name Extended Display Identification Data: Masks, shifts, and values. + * @{ + */ +#define XVIDC_EDID_VPI_ID_MAN_NAME0_CHAR0_SHIFT 2 +#define XVIDC_EDID_VPI_ID_MAN_NAME0_CHAR0_MASK (0x1F << 2) +#define XVIDC_EDID_VPI_ID_MAN_NAME0_CHAR1_MASK 0x03 +#define XVIDC_EDID_VPI_ID_MAN_NAME0_CHAR1_POS 3 +#define XVIDC_EDID_VPI_ID_MAN_NAME1_CHAR1_SHIFT 5 +#define XVIDC_EDID_VPI_ID_MAN_NAME1_CHAR2_MASK 0x1F + +/* Basic display parameters and features: Video input definition. */ +#define XVIDC_EDID_BDISP_VID_VSI_SHIFT 7 +#define XVIDC_EDID_BDISP_VID_VSI_MASK (0x01 << 7) +#define XVIDC_EDID_BDISP_VID_ANA_SLS_SHIFT 5 +#define XVIDC_EDID_BDISP_VID_ANA_SLS_MASK (0x03 << 5) +#define XVIDC_EDID_BDISP_VID_ANA_SLS_0700_0300_1000 0x0 +#define XVIDC_EDID_BDISP_VID_ANA_SLS_0714_0286_1000 0x1 +#define XVIDC_EDID_BDISP_VID_ANA_SLS_1000_0400_1400 0x2 +#define XVIDC_EDID_BDISP_VID_ANA_SLS_0700_0000_0700 0x3 +#define XVIDC_EDID_BDISP_VID_ANA_VID_SETUP_MASK (0x01 << 4) +#define XVIDC_EDID_BDISP_VID_ANA_SEP_SYNC_HV_MASK (0x01 << 3) +#define XVIDC_EDID_BDISP_VID_ANA_COMP_SYNC_H_MASK (0x01 << 2) +#define XVIDC_EDID_BDISP_VID_ANA_COMP_SYNC_G_MASK (0x01 << 1) +#define XVIDC_EDID_BDISP_VID_ANA_SERR_V_SYNC_MASK (0x01) +#define XVIDC_EDID_BDISP_VID_DIG_BPC_SHIFT 4 +#define XVIDC_EDID_BDISP_VID_DIG_BPC_MASK (0x7 << 4) +#define XVIDC_EDID_BDISP_VID_DIG_BPC_UNDEF 0x0 +#define XVIDC_EDID_BDISP_VID_DIG_BPC_6 0x1 +#define XVIDC_EDID_BDISP_VID_DIG_BPC_8 0x2 +#define XVIDC_EDID_BDISP_VID_DIG_BPC_10 0x3 +#define XVIDC_EDID_BDISP_VID_DIG_BPC_12 0x4 +#define XVIDC_EDID_BDISP_VID_DIG_BPC_14 0x5 +#define XVIDC_EDID_BDISP_VID_DIG_BPC_16 0x6 +#define XVIDC_EDID_BDISP_VID_DIG_VIS_MASK 0xF +#define XVIDC_EDID_BDISP_VID_DIG_VIS_UNDEF 0x0 +#define XVIDC_EDID_BDISP_VID_DIG_VIS_DVI 0x1 +#define XVIDC_EDID_BDISP_VID_DIG_VIS_HDMIA 0x2 +#define XVIDC_EDID_BDISP_VID_DIG_VIS_HDMIB 0x3 +#define XVIDC_EDID_BDISP_VID_DIG_VIS_MDDI 0x4 +#define XVIDC_EDID_BDISP_VID_DIG_VIS_DP 0x5 + +/* Basic display parameters and features: Feature support. */ +#define XVIDC_EDID_BDISP_FEATURE_PM_STANDBY_MASK (0x1 << 7) +#define XVIDC_EDID_BDISP_FEATURE_PM_SUSPEND_MASK (0x1 << 6) +#define XVIDC_EDID_BDISP_FEATURE_PM_OFF_VLP_MASK (0x1 << 5) +#define XVIDC_EDID_BDISP_FEATURE_ANA_COLORTYPE_SHIFT 3 +#define XVIDC_EDID_BDISP_FEATURE_ANA_COLORTYPE_MASK (0x3 << 3) +#define XVIDC_EDID_BDISP_FEATURE_ANA_COLORTYPE_MCG 0x0 +#define XVIDC_EDID_BDISP_FEATURE_ANA_COLORTYPE_RGB 0x1 +#define XVIDC_EDID_BDISP_FEATURE_ANA_COLORTYPE_NRGB 0x2 +#define XVIDC_EDID_BDISP_FEATURE_ANA_COLORTYPE_UNDEF 0x3 +#define XVIDC_EDID_BDISP_FEATURE_DIG_COLORENC_YCRCB444_MASK (0x1 << 3) +#define XVIDC_EDID_BDISP_FEATURE_DIG_COLORENC_YCRCB422_MASK (0x1 << 4) +#define XVIDC_EDID_BDISP_FEATURE_SRGB_DEF_MASK (0x1 << 2) +#define XVIDC_EDID_BDISP_FEATURE_PTM_INC_MASK (0x1 << 1) +#define XVIDC_EDID_BDISP_FEATURE_CONTFREQ_MASK (0x1) + +/* Color characteristics (display x,y chromaticity coordinates). */ +#define XVIDC_EDID_CC_HIGH_SHIFT 2 +#define XVIDC_EDID_CC_RBX_LOW_SHIFT 6 +#define XVIDC_EDID_CC_RBY_LOW_SHIFT 4 +#define XVIDC_EDID_CC_RBY_LOW_MASK (0x3 << 4) +#define XVIDC_EDID_CC_GWX_LOW_SHIFT 2 +#define XVIDC_EDID_CC_GWX_LOW_MASK (0x3 << 2) +#define XVIDC_EDID_CC_GWY_LOW_MASK (0x3) +#define XVIDC_EDID_CC_GREENY_HIGH 0x1E +#define XVIDC_EDID_CC_BLUEX_HIGH 0x1F +#define XVIDC_EDID_CC_BLUEY_HIGH 0x20 +#define XVIDC_EDID_CC_WHITEX_HIGH 0x21 +#define XVIDC_EDID_CC_WHITEY_HIGH 0x22 + +/* Established timings. */ +#define XVIDC_EDID_EST_TIMINGS_I_720x400_70_MASK (0x1 << 7) +#define XVIDC_EDID_EST_TIMINGS_I_720x400_88_MASK (0x1 << 6) +#define XVIDC_EDID_EST_TIMINGS_I_640x480_60_MASK (0x1 << 5) +#define XVIDC_EDID_EST_TIMINGS_I_640x480_67_MASK (0x1 << 4) +#define XVIDC_EDID_EST_TIMINGS_I_640x480_72_MASK (0x1 << 3) +#define XVIDC_EDID_EST_TIMINGS_I_640x480_75_MASK (0x1 << 2) +#define XVIDC_EDID_EST_TIMINGS_I_800x600_56_MASK (0x1 << 1) +#define XVIDC_EDID_EST_TIMINGS_I_800x600_60_MASK (0x1) +#define XVIDC_EDID_EST_TIMINGS_II_800x600_72_MASK (0x1 << 7) +#define XVIDC_EDID_EST_TIMINGS_II_800x600_75_MASK (0x1 << 6) +#define XVIDC_EDID_EST_TIMINGS_II_832x624_75_MASK (0x1 << 5) +#define XVIDC_EDID_EST_TIMINGS_II_1024x768_87_MASK (0x1 << 4) +#define XVIDC_EDID_EST_TIMINGS_II_1024x768_60_MASK (0x1 << 3) +#define XVIDC_EDID_EST_TIMINGS_II_1024x768_70_MASK (0x1 << 2) +#define XVIDC_EDID_EST_TIMINGS_II_1024x768_75_MASK (0x1 << 1) +#define XVIDC_EDID_EST_TIMINGS_II_1280x1024_75_MASK (0x1) +#define XVIDC_EDID_EST_TIMINGS_MAN_1152x870_75_MASK (0x1 << 7) +#define XVIDC_EDID_EST_TIMINGS_MAN_MASK (0x7F) + +/* Standard timings. */ +#define XVIDC_EDID_STD_TIMINGS_AR_SHIFT 6 +#define XVIDC_EDID_STD_TIMINGS_AR_16_10 0x0 +#define XVIDC_EDID_STD_TIMINGS_AR_4_3 0x1 +#define XVIDC_EDID_STD_TIMINGS_AR_5_4 0x2 +#define XVIDC_EDID_STD_TIMINGS_AR_16_9 0x3 +#define XVIDC_EDID_STD_TIMINGS_FRR_MASK (0x3F) + +/* Detailed timing descriptor (DTD) / Preferred timing mode (PTM). */ +#define XVIDC_EDID_DTD_PTM_XRES_XBLANK_U4_XBLANK_MASK 0x0F +#define XVIDC_EDID_DTD_PTM_XRES_XBLANK_U4_XRES_MASK 0xF0 +#define XVIDC_EDID_DTD_PTM_XRES_XBLANK_U4_XRES_SHIFT 4 +#define XVIDC_EDID_DTD_PTM_VFPORCH_VSPW_L4_VSPW_MASK 0x0F +#define XVIDC_EDID_DTD_PTM_VFPORCH_VSPW_L4_VFPORCH_MASK 0xF0 +#define XVIDC_EDID_DTD_PTM_VFPORCH_VSPW_L4_VFPORCH_SHIFT 4 +#define XVIDC_EDID_DTD_PTM_XFPORCH_XSPW_U2_HFPORCH_MASK 0xC0 +#define XVIDC_EDID_DTD_PTM_XFPORCH_XSPW_U2_HSPW_MASK 0x30 +#define XVIDC_EDID_DTD_PTM_XFPORCH_XSPW_U2_VFPORCH_MASK 0x0C +#define XVIDC_EDID_DTD_PTM_XFPORCH_XSPW_U2_VSPW_MASK 0x03 +#define XVIDC_EDID_DTD_PTM_XFPORCH_XSPW_U2_HFPORCH_SHIFT 6 +#define XVIDC_EDID_DTD_PTM_XFPORCH_XSPW_U2_HSPW_SHIFT 4 +#define XVIDC_EDID_DTD_PTM_XFPORCH_XSPW_U2_VFPORCH_SHIFT 2 +#define XVIDC_EDID_DTD_PTM_XIMGSIZE_MM_U4_VIMGSIZE_MM_MASK 0x0F +#define XVIDC_EDID_DTD_PTM_XIMGSIZE_MM_U4_HIMGSIZE_MM_MASK 0xF0 +#define XVIDC_EDID_DTD_PTM_XIMGSIZE_MM_U4_HIMGSIZE_MM_SHIFT 4 +#define XVIDC_EDID_DTD_PTM_SIGNAL_INTERLACED_MASK 0x80 +#define XVIDC_EDID_DTD_PTM_SIGNAL_INTERLACED_SHIFT 7 +#define XVIDC_EDID_DTD_PTM_SIGNAL_HPOLARITY_MASK 0x02 +#define XVIDC_EDID_DTD_PTM_SIGNAL_VPOLARITY_MASK 0x04 +#define XVIDC_EDID_DTD_PTM_SIGNAL_HPOLARITY_SHIFT 1 +#define XVIDC_EDID_DTD_PTM_SIGNAL_VPOLARITY_SHIFT 2 +/* @} */ + +/******************* Macros (Inline Functions) Definitions ********************/ + +#define XVidC_EdidIsHeaderValid(E) \ + !memcmp(E, "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00", 8) + +/* Vendor and product identification: ID manufacturer name. */ +/* void XVidC_EdidGetManName(const u8 *EdidRaw, char ManName[4]); */ + +/* Vendor and product identification: ID product code. */ +#define XVidC_EdidGetIdProdCode(E) \ + ((u16)((E[XVIDC_EDID_VPI_ID_PROD_CODE_MSB] << 8) | \ + E[XVIDC_EDID_VPI_ID_PROD_CODE_LSB])) + +/* Vendor and product identification: ID serial number. */ +#define XVidC_EdidGetIdSn(E) \ + ((u32)((E[XVIDC_EDID_VPI_ID_SN3] << 24) | \ + (E[XVIDC_EDID_VPI_ID_SN2] << 16) | (E[XVIDC_EDID_VPI_ID_SN1] << 8) | \ + E[XVIDC_EDID_VPI_ID_SN0])) + +/* Vendor and product identification: Week and year of manufacture or model + * year. */ +#define XVidC_EdidGetManWeek(E) (E[XVIDC_EDID_VPI_WEEK_MAN]) +#define XVidC_EdidGetModManYear(E) (E[XVIDC_EDID_VPI_YEAR] + 1990) +#define XVidC_EdidIsYearModel(E) (XVidC_EdidGetManWeek(E) == 0xFF) +#define XVidC_EdidIsYearMan(E) (XVidC_EdidGetManWeek(E) != 0xFF) + +/* EDID structure version and revision. */ +#define XVidC_EdidGetStructVer(E) (E[XVIDC_EDID_STRUCT_VER]) +#define XVidC_EdidGetStructRev(E) (E[XVIDC_EDID_STRUCT_REV]) + +/* Basic display parameters and features: Video input definition. */ +#define XVidC_EdidIsDigitalSig(E) \ + ((E[XVIDC_EDID_BDISP_VID] & XVIDC_EDID_BDISP_VID_VSI_MASK) != 0) +#define XVidC_EdidIsAnalogSig(E) \ + ((E[XVIDC_EDID_BDISP_VID] & XVIDC_EDID_BDISP_VID_VSI_MASK) == 0) +#define XVidC_EdidGetAnalogSigLvlStd(E) \ + ((E[XVIDC_EDID_BDISP_VID] & XVIDC_EDID_BDISP_VID_ANA_SLS_MASK) >> \ + XVIDC_EDID_BDISP_VID_ANA_SLS_SHIFT) +#define XVidC_EdidGetAnalogSigVidSetup(E) \ + ((E[XVIDC_EDID_BDISP_VID] & \ + XVIDC_EDID_BDISP_VID_ANA_VID_SETUP_MASK) != 0) +#define XVidC_EdidSuppAnalogSigSepSyncHv(E) \ + ((E[XVIDC_EDID_BDISP_VID] & \ + XVIDC_EDID_BDISP_VID_ANA_SEP_SYNC_HV_MASK) != 0) +#define XVidC_EdidSuppAnalogSigCompSyncH(E) \ + ((E[XVIDC_EDID_BDISP_VID] & \ + XVIDC_EDID_BDISP_VID_ANA_COMP_SYNC_H_MASK) != 0) +#define XVidC_EdidSuppAnalogSigCompSyncG(E) \ + ((E[XVIDC_EDID_BDISP_VID] & \ + XVIDC_EDID_BDISP_VID_ANA_COMP_SYNC_G_MASK) != 0) +#define XVidC_EdidSuppAnalogSigSerrVsync(E) \ + ((E[XVIDC_EDID_BDISP_VID] & \ + XVIDC_EDID_BDISP_VID_ANA_SERR_V_SYNC_MASK) != 0) +/* XVidC_ColorDepth XVidC_EdidGetColorDepth(const u8 *EdidRaw); */ +#define XVidC_EdidGetDigitalSigIfaceStd(E) \ + (E[XVIDC_EDID_BDISP_VID] & XVIDC_EDID_BDISP_VID_DIG_VIS_MASK) + +/* Basic display parameters and features: Horizontal and vertical screen size or + * aspect ratio. */ +#define XVidC_EdidIsSsArDefined(E) \ + ((E[XVIDC_EDID_BDISP_H_SSAR] | E[XVIDC_EDID_BDISP_V_SSAR]) != 0) +#define XVidC_EdidGetSsArH(E) E[XVIDC_EDID_BDISP_H_SSAR] +#define XVidC_EdidGetSsArV(E) E[XVIDC_EDID_BDISP_V_SSAR] +#define XVidC_EdidIsSsArSs(E) \ + ((XVidC_EdidGetSsArH(E) != 0) && (XVidC_EdidGetSsArV(E) != 0)) +#define XVidC_EdidIsSsArArL(E) \ + ((XVidC_EdidGetSsArH(E) != 0) && (XVidC_EdidGetSsArV(E) == 0)) +#define XVidC_EdidIsSsArArP(E) \ + ((XVidC_EdidGetSsArH(E) == 0) && (XVidC_EdidGetSsArV(E) != 0)) +#define XVidC_EdidGetSsArArL(E) \ + ((float)((XVidC_EdidGetSsArH(E) + 99.0) / 100.0)) +#define XVidC_EdidGetSsArArP(E) \ + ((float)(100.0 / (XVidC_EdidGetSsArV(E) + 99.0))) + +/* Basic display parameters and features: Gamma. */ +#define XVidC_EdidIsGammaInExt(E) (E[XVIDC_EDID_BDISP_GAMMA] == 0xFF) +#define XVidC_EdidGetGamma(E) \ + ((float)((E[XVIDC_EDID_BDISP_GAMMA] + 100.0) / 100.0)) + +/* Basic display parameters and features: Feature support. */ +#define XVidC_EdidSuppFeaturePmStandby(E) \ + ((E[XVIDC_EDID_BDISP_FEATURE] & \ + XVIDC_EDID_BDISP_FEATURE_PM_STANDBY_MASK) != 0) +#define XVidC_EdidSuppFeaturePmSuspend(E) \ + ((E[XVIDC_EDID_BDISP_FEATURE] & \ + XVIDC_EDID_BDISP_FEATURE_PM_SUSPEND_MASK) != 0) +#define XVidC_EdidSuppFeaturePmOffVlp(E) \ + ((E[XVIDC_EDID_BDISP_FEATURE] & \ + XVIDC_EDID_BDISP_FEATURE_PM_OFF_VLP_MASK) != 0) +#define XVidC_EdidGetFeatureAnaColorType(E) \ + ((E[XVIDC_EDID_BDISP_FEATURE] & \ + XVIDC_EDID_BDISP_FEATURE_ANA_COLORTYPE_MASK) >> \ + XVIDC_EDID_BDISP_FEATURE_ANA_COLORTYPE_SHIFT) +#define XVidC_EdidSuppFeatureDigColorEncYCrCb444(E) \ + ((E[XVIDC_EDID_BDISP_FEATURE] & \ + XVIDC_EDID_BDISP_FEATURE_DIG_COLORENC_YCRCB444_MASK) != 0) +#define XVidC_EdidSuppFeatureDigColorEncYCrCb422(E) \ + ((E[XVIDC_EDID_BDISP_FEATURE] & \ + XVIDC_EDID_BDISP_FEATURE_DIG_COLORENC_YCRCB422_MASK) != 0) +#define XVidC_EdidIsFeatureSrgbDef(E) \ + ((E[XVIDC_EDID_BDISP_FEATURE] & \ + XVIDC_EDID_BDISP_FEATURE_SRGB_DEF_MASK) != 0) +#define XVidC_EdidIsFeaturePtmInc(E) \ + ((E[XVIDC_EDID_BDISP_FEATURE] & \ + XVIDC_EDID_BDISP_FEATURE_PTM_INC_MASK) != 0) +#define XVidC_EdidIsFeatureContFreq(E) \ + ((E[XVIDC_EDID_BDISP_FEATURE] & \ + XVIDC_EDID_BDISP_FEATURE_CONTFREQ_MASK) != 0) + +/* Established timings. */ +#define XVidC_EdidSuppEstTimings720x400_70(E) \ + ((E[XVIDC_EDID_EST_TIMINGS_I] & \ + XVIDC_EDID_EST_TIMINGS_I_720x400_70_MASK) != 0) +#define XVidC_EdidSuppEstTimings720x400_88(E) \ + ((E[XVIDC_EDID_EST_TIMINGS_I] & \ + XVIDC_EDID_EST_TIMINGS_I_720x400_88_MASK) != 0) +#define XVidC_EdidSuppEstTimings640x480_60(E) \ + ((E[XVIDC_EDID_EST_TIMINGS_I] & \ + XVIDC_EDID_EST_TIMINGS_I_640x480_60_MASK) != 0) +#define XVidC_EdidSuppEstTimings640x480_67(E) \ + ((E[XVIDC_EDID_EST_TIMINGS_I] & \ + XVIDC_EDID_EST_TIMINGS_I_640x480_67_MASK) != 0) +#define XVidC_EdidSuppEstTimings640x480_72(E) \ + ((E[XVIDC_EDID_EST_TIMINGS_I] & \ + XVIDC_EDID_EST_TIMINGS_I_640x480_72_MASK) != 0) +#define XVidC_EdidSuppEstTimings640x480_75(E) \ + ((E[XVIDC_EDID_EST_TIMINGS_I] & \ + XVIDC_EDID_EST_TIMINGS_I_640x480_75_MASK) != 0) +#define XVidC_EdidSuppEstTimings800x600_56(E) \ + ((E[XVIDC_EDID_EST_TIMINGS_I] & \ + XVIDC_EDID_EST_TIMINGS_I_800x600_56_MASK) != 0) +#define XVidC_EdidSuppEstTimings800x600_60(E) \ + ((E[XVIDC_EDID_EST_TIMINGS_I] & \ + XVIDC_EDID_EST_TIMINGS_I_800x600_60_MASK) != 0) +#define XVidC_EdidSuppEstTimings800x600_72(E) \ + ((E[XVIDC_EDID_EST_TIMINGS_II] & \ + XVIDC_EDID_EST_TIMINGS_II_800x600_72_MASK) != 0) +#define XVidC_EdidSuppEstTimings800x600_75(E) \ + ((E[XVIDC_EDID_EST_TIMINGS_II] & \ + XVIDC_EDID_EST_TIMINGS_II_800x600_75_MASK) != 0) +#define XVidC_EdidSuppEstTimings832x624_75(E) \ + ((E[XVIDC_EDID_EST_TIMINGS_II] & \ + XVIDC_EDID_EST_TIMINGS_II_832x624_75_MASK) != 0) +#define XVidC_EdidSuppEstTimings1024x768_87(E) \ + ((E[XVIDC_EDID_EST_TIMINGS_II] & \ + XVIDC_EDID_EST_TIMINGS_II_1024x768_87_MASK) != 0) +#define XVidC_EdidSuppEstTimings1024x768_60(E) \ + ((E[XVIDC_EDID_EST_TIMINGS_II] & \ + XVIDC_EDID_EST_TIMINGS_II_1024x768_60_MASK) != 0) +#define XVidC_EdidSuppEstTimings1024x768_70(E) \ + ((E[XVIDC_EDID_EST_TIMINGS_II] & \ + XVIDC_EDID_EST_TIMINGS_II_1024x768_70_MASK) != 0) +#define XVidC_EdidSuppEstTimings1024x768_75(E) \ + ((E[XVIDC_EDID_EST_TIMINGS_II] & \ + XVIDC_EDID_EST_TIMINGS_II_1024x768_75_MASK) != 0) +#define XVidC_EdidSuppEstTimings1280x1024_75(E) \ + ((E[XVIDC_EDID_EST_TIMINGS_II] & \ + XVIDC_EDID_EST_TIMINGS_II_1280x1024_75_MASK) != 0) +#define XVidC_EdidSuppEstTimings1152x870_75(E) \ + ((E[XVIDC_EDID_EST_TIMINGS_MAN] & \ + XVIDC_EDID_EST_TIMINGS_MAN_1152x870_75_MASK) != 0) +#define XVidC_EdidGetTimingsMan(E) \ + (E[XVIDC_EDID_EST_TIMINGS_MAN] & XVIDC_EDID_EST_TIMINGS_MAN_MASK) + +/* Standard timings. */ +#define XVidC_EdidGetStdTimingsH(E, N) \ + ((E[XVIDC_EDID_STD_TIMINGS_H(N)] + 31) * 8) +#define XVidC_EdidGetStdTimingsAr(E, N) \ + (E[XVIDC_EDID_STD_TIMINGS_AR_FRR(N)] >> XVIDC_EDID_STD_TIMINGS_AR_SHIFT) +#define XVidC_EdidGetStdTimingsFrr(E, N) \ + ((E[XVIDC_EDID_STD_TIMINGS_AR_FRR(N)] & \ + XVIDC_EDID_STD_TIMINGS_FRR_MASK) + 60) +/* u16 XVidC_EdidGetStdTimingsV(const u8 *EdidRaw, u8 StdTimingsNum); */ +#define XVidC_EdidIsDtdPtmInterlaced(E) \ + ((E[XVIDC_EDID_PTM + XVIDC_EDID_DTD_PTM_SIGNAL] & \ + XVIDC_EDID_DTD_PTM_SIGNAL_INTERLACED_MASK) >> \ + XVIDC_EDID_DTD_PTM_SIGNAL_INTERLACED_SHIFT) + +/* Extension block count. */ +#define XVidC_EdidGetExtBlkCount(E) (E[XVIDC_EDID_EXT_BLK_COUNT]) + +/* Checksum. */ +#define XVidC_EdidGetChecksum(E) (E[XVIDC_EDID_CHECKSUM]) + +/**************************** Function Prototypes *****************************/ + +/* Vendor and product identification: ID manufacturer name. */ +void XVidC_EdidGetManName(const u8 *EdidRaw, char ManName[4]); + +/* Basic display parameters and features: Video input definition. */ +XVidC_ColorDepth XVidC_EdidGetColorDepth(const u8 *EdidRaw); + +/* Color characteristics (display x,y chromaticity coordinates). */ +int XVidC_EdidGetCcRedX(const u8 *EdidRaw); +int XVidC_EdidGetCcRedY(const u8 *EdidRaw); +int XVidC_EdidGetCcGreenX(const u8 *EdidRaw); +int XVidC_EdidGetCcGreenY(const u8 *EdidRaw); +int XVidC_EdidGetCcBlueX(const u8 *EdidRaw); +int XVidC_EdidGetCcBlueY(const u8 *EdidRaw); +int XVidC_EdidGetCcWhiteX(const u8 *EdidRaw); +int XVidC_EdidGetCcWhiteY(const u8 *EdidRaw); + +/* Standard timings. */ +u16 XVidC_EdidGetStdTimingsV(const u8 *EdidRaw, u8 StdTimingsNum); + +/* Utility functions. */ +u32 XVidC_EdidIsVideoTimingSupported(const u8 *EdidRaw, + const XVidC_VideoTimingMode *VtMode); + +#ifdef __cplusplus +} +#endif +#endif /* XVIDC_EDID_H_ */ +/** @} */ diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvidc_timings_table.c b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvidc_timings_table.c new file mode 100644 index 00000000000000..872367a5ab9f93 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvidc_timings_table.c @@ -0,0 +1,435 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvidc_timings_table.c + * @addtogroup video_common_v4_0 + * @{ + * + * Contains video timings for various standard resolutions. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als, 01/10/15 Initial release. + * rc + * 2.0 als 08/14/15 Added new video timings. + * 2.1 als 11/04/15 Fixed video timings for some resolutions. + * rco 02/09/17 Fix c++ compilation warnings + * </pre> + * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xvidc.h" + +/**************************** Variable Definitions ****************************/ + +/** + * This table contains the main stream attributes for various standard + * resolutions. Each entry is of the format: + * 1) ID: XVIDC_VM_<HRES>x<VRES>_<FRAME RATE (HZ)>_<P|I>(_RB = Reduced Blanking) + * 2) Resolution naming: "<HRES>x<VRES>@<FRAME RATE (HZ)>" + * 3) Frame rate: XVIDC_FR_<FRAME RATE (HZ)> + * 4) Video timing structure: + * 1) Horizontal active resolution (pixels) + * 2) Horizontal front porch (pixels) + * 3) Horizontal sync width (pixels) + * 4) Horizontal back porch (pixels) + * 5) Horizontal total (pixels) + * 6) Horizontal sync polarity (0=negative|1=positive) + * 7) Vertical active resolution (lines) + * 8) Frame 0: Vertical front porch (lines) + * 9) Frame 0: Vertical sync width (lines) + * 10) Frame 0: Vertical back porch (lines) + * 11) Frame 0: Vertical total (lines) + * 12) Frame 1: Vertical front porch (lines) + * 13) Frame 1: Vertical sync width (lines) + * 14) Frame 1: Vertical back porch (lines) + * 15) Frame 1: Vertical total (lines) + * 16) Vertical sync polarity (0=negative|1=positive) + */ +#ifdef __cplusplus +extern "C" +#endif +const XVidC_VideoTimingMode XVidC_VideoTimingModes[XVIDC_VM_NUM_SUPPORTED] = +{ + /* Interlaced modes. */ + { XVIDC_VM_720x480_60_I, "720x480@60Hz (I)", XVIDC_FR_60HZ, + {720, 19, 62, 57, 858, 0, + 240, 4, 3, 15, 262, 5, 3, 15, 263, 0} }, + { XVIDC_VM_720x576_50_I, "720x576@50Hz (I)", XVIDC_FR_50HZ, + {720, 12, 63, 69, 864, 0, + 288, 2, 3, 19, 312, 3, 3, 19, 313, 0} }, + { XVIDC_VM_1440x480_60_I, "1440x480@60Hz (I)", XVIDC_FR_60HZ, + {1440, 38, 124, 114, 1716, 0, + 240, 4, 3, 15, 262, 5, 3, 15, 263, 0} }, + { XVIDC_VM_1440x576_50_I, "1440x576@50Hz (I)", XVIDC_FR_50HZ, + {1440, 24, 126, 138, 1728, 0, + 288, 2, 3, 19, 312, 3, 3, 19, 313, 0} }, + { XVIDC_VM_1920x1080_50_I, "1920x1080@50Hz (I)", XVIDC_FR_50HZ, + {1920, 528, 44, 148, 2640, 1, + 540, 2, 5, 15, 562, 3, 5, 15, 563, 1} }, + { XVIDC_VM_1920x1080_60_I, "1920x1080@60Hz (I)", XVIDC_FR_60HZ, + {1920, 88, 44, 148, 2200, 1, + 540, 2, 5, 15, 562, 3, 5, 15, 563, 1} }, + + /* Progressive modes. */ + { XVIDC_VM_640x350_85_P, "640x350@85Hz", XVIDC_FR_85HZ, + {640, 32, 64, 96, 832, 1, + 350, 32, 3, 60, 445, 0, 0, 0, 0, 0} }, + { XVIDC_VM_640x480_60_P, "640x480@60Hz", XVIDC_FR_60HZ, + {640, 8+8, 96, 40+8, 800, 0, + 480, 2+8, 2, 25+8, 525, 0, 0, 0, 0, 0} }, + { XVIDC_VM_640x480_72_P, "640x480@72Hz", XVIDC_FR_72HZ, + {640, 8+16, 40, 120+8, 832, 0, + 480, 8+1, 3, 20+8, 520, 0, 0, 0, 0, 0} }, + { XVIDC_VM_640x480_75_P, "640x480@75Hz", XVIDC_FR_75HZ, + {640, 16, 64, 120, 840, 0, + 480, 1, 3, 16, 500, 0, 0, 0, 0, 0} }, + { XVIDC_VM_640x480_85_P, "640x480@85Hz", XVIDC_FR_85HZ, + {640, 56, 56, 80, 832, 0, + 480, 1, 3, 25, 509, 0, 0, 0, 0, 0} }, + { XVIDC_VM_720x400_85_P, "720x400@85Hz", XVIDC_FR_85HZ, + {720, 36, 72, 108, 936, 0, + 400, 1, 3, 42, 446, 0, 0, 0, 0, 1} }, + { XVIDC_VM_720x480_60_P, "720x480@60Hz", XVIDC_FR_60HZ, + {720, 16, 62, 60, 858, 0, + 480, 9, 6, 30, 525, 0, 0, 0, 0, 0} }, + { XVIDC_VM_720x576_50_P, "720x576@50Hz", XVIDC_FR_50HZ, + {720, 12, 64, 68, 864, 0, + 576, 5, 5, 39, 625, 0, 0, 0, 0, 0} }, + { XVIDC_VM_800x600_56_P, "800x600@56Hz", XVIDC_FR_56HZ, + {800, 24, 72, 128, 1024, 1, + 600, 1, 2, 22, 625, 0, 0, 0, 0, 1} }, + { XVIDC_VM_800x600_60_P, "800x600@60Hz", XVIDC_FR_60HZ, + {800, 40, 128, 88, 1056, 1, + 600, 1, 4, 23, 628, 0, 0, 0, 0, 1} }, + { XVIDC_VM_800x600_72_P, "800x600@72Hz", XVIDC_FR_72HZ, + {800, 56, 120, 64, 1040, 1, + 600, 37, 6, 23, 666, 0, 0, 0, 0, 1} }, + { XVIDC_VM_800x600_75_P, "800x600@75Hz", XVIDC_FR_75HZ, + {800, 16, 80, 160, 1056, 1, + 600, 1, 3, 21, 625, 0, 0, 0, 0, 1} }, + { XVIDC_VM_800x600_85_P, "800x600@85Hz", XVIDC_FR_85HZ, + {800, 32, 64, 152, 1048, 1, + 600, 1, 3, 27, 631, 0, 0, 0, 0, 1} }, + { XVIDC_VM_800x600_120_P_RB, "800x600@120Hz (RB)", XVIDC_FR_120HZ, + {800, 48, 32, 80, 960, 1, + 600, 3, 4, 29, 636, 0, 0, 0, 0, 0} }, + { XVIDC_VM_848x480_60_P, "848x480@60Hz", XVIDC_FR_60HZ, + {848, 16, 112, 112, 1088, 1, + 480, 6, 8, 23, 517, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1024x768_60_P, "1024x768@60Hz", XVIDC_FR_60HZ, + {1024, 24, 136, 160, 1344, 0, + 768, 3, 6, 29, 806, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1024x768_70_P, "1024x768@70Hz", XVIDC_FR_70HZ, + {1024, 24, 136, 144, 1328, 0, + 768, 3, 6, 29, 806, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1024x768_75_P, "1024x768@75Hz", XVIDC_FR_75HZ, + {1024, 16, 96, 176, 1312, 1, + 768, 1, 3, 28, 800, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1024x768_85_P, "1024x768@85Hz", XVIDC_FR_85HZ, + {1024, 48, 96, 208, 1376, 1, + 768, 1, 3, 36, 808, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1024x768_120_P_RB, "1024x768@120Hz (RB)", XVIDC_FR_120HZ, + {1024, 48, 32, 80, 1184, 1, + 768, 3, 4, 38, 813, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1152x864_75_P, "1152x864@75Hz", XVIDC_FR_75HZ, + {1152, 64, 128, 256, 1600, 1, + 864, 1, 3, 32, 900, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1280x720_50_P, "1280x720@50Hz", XVIDC_FR_50HZ, + {1280, 440, 40, 220, 1980, 1, + 720, 5, 5, 20, 750, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1280x720_60_P, "1280x720@60Hz", XVIDC_FR_60HZ, + {1280, 110, 40, 220, 1650, 1, + 720, 5, 5, 20, 750, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1280x768_60_P, "1280x768@60Hz", XVIDC_FR_60HZ, + {1280, 64, 128, 192, 1664, 0, + 768, 3, 7, 20, 798, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1280x768_60_P_RB, "1280x768@60Hz (RB)", XVIDC_FR_60HZ, + {1280, 48, 32, 80, 1440, 1, + 768, 3, 7, 12, 790, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1280x768_75_P, "1280x768@75Hz", XVIDC_FR_75HZ, + {1280, 80, 128, 208, 1696, 0, + 768, 3, 7, 27, 805, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1280x768_85_P, "1280x768@85Hz", XVIDC_FR_85HZ, + {1280, 80, 136, 216, 1712, 0, + 768, 3, 7, 31, 809, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1280x768_120_P_RB, "1280x768@120Hz (RB)", XVIDC_FR_120HZ, + {1280, 48, 32, 80, 1440, 1, + 768, 3, 7, 35, 813, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1280x800_60_P, "1280x800@60Hz", XVIDC_FR_60HZ, + {1280, 72, 128, 200, 1680, 0, + 800, 3, 6, 22, 831, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1280x800_60_P_RB, "1280x800@60Hz (RB)", XVIDC_FR_60HZ, + {1280, 48, 32, 80, 1440, 1, + 800, 3, 6, 14, 823, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1280x800_75_P, "1280x800@75Hz", XVIDC_FR_75HZ, + {1280, 80, 128, 208, 1696, 0, + 800, 3, 6, 29, 838, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1280x800_85_P, "1280x800@85Hz", XVIDC_FR_85HZ, + {1280, 80, 136, 216, 1712, 0, + 800, 3, 6, 34, 843, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1280x800_120_P_RB, "1280x800@120Hz (RB)", XVIDC_FR_120HZ, + {1280, 48, 32, 80, 1440, 1, + 800, 3, 6, 38, 847, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1280x960_60_P, "1280x960@60Hz", XVIDC_FR_60HZ, + {1280, 96, 112, 312, 1800, 1, + 960, 1, 3, 36, 1000, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1280x960_85_P, "1280x960@85Hz", XVIDC_FR_85HZ, + {1280, 64, 160, 224, 1728, 1, + 960, 1, 3, 47, 1011, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1280x960_120_P_RB, "1280x960@120Hz (RB)", XVIDC_FR_120HZ, + {1280, 48, 32, 80, 1440, 1, + 960, 3, 4, 50, 1017, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1280x1024_60_P, "1280x1024@60Hz", XVIDC_FR_60HZ, + {1280, 48, 112, 248, 1688, 1, + 1024, 1, 3, 38, 1066, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1280x1024_75_P, "1280x1024@75Hz", XVIDC_FR_75HZ, + {1280, 16, 144, 248, 1688, 1, + 1024, 1, 3, 38, 1066, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1280x1024_85_P, "1280x1024@85Hz", XVIDC_FR_85HZ, + {1280, 64, 160, 224, 1728, 1, + 1024, 1, 3, 44, 1072, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1280x1024_120_P_RB, "1280x1024@120Hz (RB)", XVIDC_FR_120HZ, + {1280, 48, 32, 80, 1440, 1, + 1024, 3, 7, 50, 1084, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1360x768_60_P, "1360x768@60Hz", XVIDC_FR_60HZ, + {1360, 64, 112, 256, 1792, 1, + 768, 3, 6, 18, 795, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1360x768_120_P_RB, "1360x768@120Hz (RB)", XVIDC_FR_120HZ, + {1360, 48, 32, 80, 1520, 1, + 768, 3, 5, 37, 813, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1366x768_60_P, "1366x768@60Hz", XVIDC_FR_60HZ, + {1366, 14, 56, 64, 1500, 1, + 768, 1, 3, 28, 800, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1400x1050_60_P, "1400x1050@60Hz", XVIDC_FR_60HZ, + {1400, 88, 144, 232, 1864, 0, + 1050, 3, 4, 32, 1089, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1400x1050_60_P_RB, "1400x1050@60Hz (RB)", XVIDC_FR_60HZ, + {1400, 48, 32, 80, 1560, 1, + 1050, 3, 4, 23, 1080, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1400x1050_75_P, "1400x1050@75Hz", XVIDC_FR_75HZ, + {1400, 104, 144, 248, 1896, 0, + 1050, 3, 4, 42, 1099, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1400x1050_85_P, "1400x1050@85Hz", XVIDC_FR_85HZ, + {1400, 104, 152, 256, 1912, 0, + 1050, 3, 4, 48, 1105, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1400x1050_120_P_RB, "1400x1050@120Hz (RB)", XVIDC_FR_120HZ, + {1400, 48, 32, 80, 1560, 1, + 1050, 3, 4, 55, 1112, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1440x240_60_P, "1440x240@60Hz", XVIDC_FR_60HZ, + {1440, 38, 124, 114, 1716, 0, + 240, 14, 3, 4, 262, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1440x900_60_P, "1440x900@60Hz", XVIDC_FR_60HZ, + {1440, 80, 152, 232, 1904, 0, + 900, 3, 6, 25, 934, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1440x900_60_P_RB, "1440x900@60Hz (RB)", XVIDC_FR_60HZ, + {1440, 48, 32, 80, 1600, 1, + 900, 3, 6, 17, 926, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1440x900_75_P, "1440x900@75Hz", XVIDC_FR_75HZ, + {1440, 96, 152, 248, 1936, 0, + 900, 3, 6, 33, 942, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1440x900_85_P, "1440x900@85Hz", XVIDC_FR_85HZ, + {1440, 104, 152, 256, 1952, 0, + 900, 3, 6, 39, 948, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1440x900_120_P_RB, "1440x900@120Hz (RB)", XVIDC_FR_120HZ, + {1440, 48, 32, 80, 1600, 1, + 900, 3, 6, 44, 953, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1600x1200_60_P, "1600x1200@60Hz", XVIDC_FR_60HZ, + {1600, 64, 192, 304, 2160, 1, + 1200, 1, 3, 46, 1250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1600x1200_65_P, "1600x1200@65Hz", XVIDC_FR_65HZ, + {1600, 64, 192, 304, 2160, 1, + 1200, 1, 3, 46, 1250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1600x1200_70_P, "1600x1200@70Hz", XVIDC_FR_70HZ, + {1600, 64, 192, 304, 2160, 1, + 1200, 1, 3, 46, 1250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1600x1200_75_P, "1600x1200@75Hz", XVIDC_FR_75HZ, + {1600, 64, 192, 304, 2160, 1, + 1200, 1, 3, 46, 1250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1600x1200_85_P, "1600x1200@85Hz", XVIDC_FR_85HZ, + {1600, 64, 192, 304, 2160, 1, + 1200, 1, 3, 46, 1250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1600x1200_120_P_RB, "1600x1200@120Hz (RB)", XVIDC_FR_120HZ, + {1600, 48, 32, 80, 1760, 1, + 1200, 3, 4, 64, 1271, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1680x720_50_P, "1680x720@50Hz", XVIDC_FR_50HZ, + {1680, 260, 40, 220, 2200, 1, + 720, 5, 5, 20, 750, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1680x720_60_P, "1680x720@60Hz", XVIDC_FR_60HZ, + {1680, 260, 40, 220, 2200, 1, + 720, 5, 5, 20, 750, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1680x720_100_P, "1680x720@100Hz", XVIDC_FR_100HZ, + {1680, 60, 40, 220, 2000, 1, + 720, 5, 5, 95, 825, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1680x720_120_P, "1680x720@120Hz", XVIDC_FR_120HZ, + {1680, 60, 40, 220, 2000, 1, + 720, 5, 5, 95, 825, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1680x1050_50_P, "1680x1050@50Hz", XVIDC_FR_50HZ, + {1680, 88, 176, 264, 2208, 0, + 1050, 3, 6, 24, 1083, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1680x1050_60_P, "1680x1050@60Hz", XVIDC_FR_60HZ, + {1680, 104, 176, 280, 2240, 0, + 1050, 3, 6, 30, 1089, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1680x1050_60_P_RB, "1680x1050@60Hz (RB)", XVIDC_FR_60HZ, + {1680, 48, 32, 80, 1840, 1, + 1050, 3, 6, 21, 1080, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1680x1050_75_P, "1680x1050@75Hz", XVIDC_FR_75HZ, + {1680, 120, 176, 296, 2272, 0, + 1050, 3, 6, 40, 1099, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1680x1050_85_P, "1680x1050@85Hz", XVIDC_FR_85HZ, + {1680, 128, 176, 304, 2288, 0, + 1050, 3, 6, 46, 1105, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1680x1050_120_P_RB, "1680x1050@120Hz (RB)", XVIDC_FR_120HZ, + {1680, 48, 32, 80, 1840, 1, + 1050, 3, 6, 53, 1112, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1792x1344_60_P, "1792x1344@60Hz", XVIDC_FR_60HZ, + {1792, 128, 200, 328, 2448, 0, + 1344, 1, 3, 46, 1394, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1792x1344_75_P, "1792x1344@75Hz", XVIDC_FR_75HZ, + {1792, 96, 216, 352, 2456, 0, + 1344, 1, 3, 69, 1417, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1792x1344_120_P_RB, "1792x1344@120Hz (RB)", XVIDC_FR_120HZ, + {1792, 48, 32, 80, 1952, 1, + 1344, 3, 4, 72, 1423, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1856x1392_60_P, "1856x1392@60Hz", XVIDC_FR_60HZ, + {1856, 96, 224, 352, 2528, 0, + 1392, 1, 3, 43, 1439, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1856x1392_75_P, "1856x1392@75Hz", XVIDC_FR_75HZ, + {1856, 128, 224, 352, 2560, 0, + 1392, 1, 3, 104, 1500, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1856x1392_120_P_RB, "1856x1392@120Hz (RB)", XVIDC_FR_120HZ, + {1856, 48, 32, 80, 2016, 1, + 1392, 3, 4, 75, 1474, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1920x1080_24_P, "1920x1080@24Hz", XVIDC_FR_24HZ, + {1920, 638, 44, 148, 2750, 1, + 1080, 4, 5, 36, 1125, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1920x1080_25_P, "1920x1080@25Hz", XVIDC_FR_25HZ, + {1920, 528, 44, 148, 2640, 1, + 1080, 4, 5, 36, 1125, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1920x1080_30_P, "1920x1080@30Hz", XVIDC_FR_30HZ, + {1920, 88, 44, 148, 2200, 1, + 1080, 4, 5, 36, 1125, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1920x1080_50_P, "1920x1080@50Hz", XVIDC_FR_50HZ, + {1920, 528, 44, 148, 2640, 1, + 1080, 4, 5, 36, 1125, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1920x1080_60_P, "1920x1080@60Hz", XVIDC_FR_60HZ, + {1920, 88, 44, 148, 2200, 1, + 1080, 4, 5, 36, 1125, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1920x1080_100_P, "1920x1080@100Hz", XVIDC_FR_100HZ, + {1920, 528, 44, 148, 2640, 1, + 1080, 4, 5, 36, 1125, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1920x1080_120_P, "1920x1080@120Hz", XVIDC_FR_120HZ, + {1920, 88, 44, 148, 2200, 1, + 1080, 4, 5, 36, 1125, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1920x1200_60_P, "1920x1200@60Hz", XVIDC_FR_60HZ, + {1920, 136, 200, 336, 2592, 0, + 1200, 3, 6, 36, 1245, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1920x1200_60_P_RB, "1920x1200@60Hz (RB)", XVIDC_FR_60HZ, + {1920, 48, 32, 80, 2080, 1, + 1200, 3, 6, 26, 1235, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1920x1200_75_P, "1920x1200@75Hz", XVIDC_FR_75HZ, + {1920, 136, 208, 344, 2608, 0, + 1200, 3, 6, 46, 1255, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1920x1200_85_P, "1920x1200@85Hz", XVIDC_FR_85HZ, + {1920, 144, 208, 352, 2624, 0, + 1200, 3, 6, 53, 1262, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1920x1200_120_P_RB, "1920x1200@120Hz (RB)", XVIDC_FR_120HZ, + {1920, 48, 32, 80, 2080, 1, + 1200, 3, 6, 62, 1271, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1920x1440_60_P, "1920x1440@60Hz", XVIDC_FR_60HZ, + {1920, 128, 208, 344, 2600, 0, + 1440, 1, 3, 56, 1500, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1920x1440_75_P, "1920x1440@75Hz", XVIDC_FR_75HZ, + {1920, 144, 224, 352, 2640, 0, + 1440, 1, 3, 56, 1500, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1920x1440_120_P_RB, "1920x1440@120Hz (RB)", XVIDC_FR_120HZ, + {1920, 48, 32, 80, 2080, 1, + 1440, 3, 4, 78, 1525, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1920x2160_60_P, "1920x2160@60Hz", XVIDC_FR_60HZ, + {1920, 88, 44, 148, 2200, 1, + 2160, 20, 10, 60, 2250, 0, 0, 0, 0, 0} }, + { XVIDC_VM_2560x1080_50_P, "2560x1080@50Hz", XVIDC_FR_50HZ, + {2560, 548, 44, 148, 3300, 1, + 1080, 4, 5, 36, 1125, 0, 0, 0, 0, 1} }, + { XVIDC_VM_2560x1080_60_P, "2560x1080@60Hz", XVIDC_FR_60HZ, + {2560, 248, 44, 148, 3000, 1, + 1080, 4, 5, 11, 1100, 0, 0, 0, 0, 1} }, + { XVIDC_VM_2560x1080_100_P, "2560x1080@100Hz", XVIDC_FR_100HZ, + {2560, 218, 44, 148, 2970, 1, + 1080, 4, 5, 161, 1250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_2560x1080_120_P, "2560x1080@120Hz", XVIDC_FR_120HZ, + {2560, 548, 44, 148, 3300, 1, + 1080, 4, 5, 161, 1250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_2560x1600_60_P, "2560x1600@60Hz", XVIDC_FR_60HZ, + {2560, 192, 280, 472, 3504, 0, + 1600, 3, 6, 49, 1658, 0, 0, 0, 0, 1} }, + { XVIDC_VM_2560x1600_60_P_RB, "2560x1600@60Hz (RB)", XVIDC_FR_60HZ, + {2560, 48, 32, 80, 2720, 1, + 1600, 3, 6, 37, 1646, 0, 0, 0, 0, 0} }, + { XVIDC_VM_2560x1600_75_P, "2560x1600@75Hz", XVIDC_FR_75HZ, + {2560, 208, 280, 488, 3536, 0, + 1600, 3, 6, 63, 1672, 0, 0, 0, 0, 1} }, + { XVIDC_VM_2560x1600_85_P, "2560x1600@85Hz", XVIDC_FR_85HZ, + {2560, 208, 280, 488, 3536, 0, + 1600, 3, 6, 73, 1682, 0, 0, 0, 0, 1} }, + { XVIDC_VM_2560x1600_120_P_RB, "2560x1600@120Hz (RB)", XVIDC_FR_120HZ, + {2560, 48, 32, 80, 2720, 1, + 1600, 3, 6, 85, 1694, 0, 0, 0, 0, 0} }, + { XVIDC_VM_3840x2160_24_P, "3840x2160@24Hz", XVIDC_FR_24HZ, + {3840, 1276, 88, 296, 5500, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_3840x2160_25_P, "3840x2160@25Hz", XVIDC_FR_25HZ, + {3840, 1056, 88, 296, 5280, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_3840x2160_30_P, "3840x2160@30Hz", XVIDC_FR_30HZ, + {3840, 176, 88, 296, 4400, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_3840x2160_50_P, "3840x2160@50Hz", XVIDC_FR_50HZ, + {3840, 1056, 88, 296, 5280, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_3840x2160_60_P, "3840x2160@60Hz", XVIDC_FR_60HZ, + {3840, 176, 88, 296, 4400, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_4096x2160_24_P, "4096x2160@24Hz", XVIDC_FR_24HZ, + {4096, 1020, 88, 296, 5500, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_4096x2160_25_P, "4096x2160@25Hz", XVIDC_FR_25HZ, + {4096, 968, 88, 128, 5280, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_4096x2160_30_P, "4096x2160@30Hz", XVIDC_FR_30HZ, + {4096, 88, 88, 128, 4400, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_4096x2160_50_P, "4096x2160@50Hz", XVIDC_FR_50HZ, + {4096, 968, 88, 128, 5280, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_4096x2160_60_P, "4096x2160@60Hz", XVIDC_FR_60HZ, + {4096, 88, 88, 128, 4400, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_4096x2160_60_P_RB, "4096x2160@60Hz (RB)", XVIDC_FR_60HZ, + {4096, 8, 32, 40, 4176, 1, + 2160, 48, 8, 6, 2222, 0, 0, 0, 0, 0} }, +}; + +/** @} */ diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy.c b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy.c new file mode 100644 index 00000000000000..2048f3eb4eb0bf --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy.c @@ -0,0 +1,1342 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy.c + * + * Contains a minimal set of functions for the XVphy driver that allow access + * to all of the Video PHY core's functionality. See xvphy.h for a detailed + * description of the driver. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als, 10/19/15 Initial release. + * gm + * 1.1 gm 02/01/16 Added GTPE2 and GTHE4 support + * Added more events to XVphy_LogEvent definitions. + * Added TxBufferBypass in XVphy_Config structure. + * Added XVphy_SetDefaultPpc and XVphy_SetPpc functions. + * als Added XVphy_GetLineRateHz function. + * gm 20/04/16 Added XVphy_GetRcfgChId function + * 1.2 gm Added HdmiFastSwitch in XVphy_Config + * Fixed bug in XVphy_IsPllLocked function + * Changed EffectiveAddr datatype in XVphy_CfgInitialize + * to UINTPTR + * Used usleep API instead of MB_Sleep API + * Fixed Null pointer dereference in XVphy_IBufDsEnable + * Suppressed warning messages due to unused arguments + * 1.4 gm 29/11/16 Moved internally used APIs to xvphy_i.c/h + * Added preprocessor directives for sw footprint reduction + * Fixed c++ compiler warnings + * </pre> + * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include <linux/string.h> +#include "xstatus.h" +#include "xvphy.h" +#include "xvphy_i.h" +#include "xvphy_hdmi.h" +#include <linux/delay.h> +#include "xvphy_gt.h" + +/**************************** Function Prototypes *****************************/ +static u32 XVphy_MmcmWriteParameters(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir); +static u32 XVphy_DrpAccess(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u16 Addr, u16 *Val); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function retrieves the configuration for this Video PHY instance and + * fills in the InstancePtr->Config structure. + * + * @param InstancePtr is a pointer to the XVphy instance. + * @param ConfigPtr is a pointer to the configuration structure that will + * be used to copy the settings from. + * @param EffectiveAddr is the device base address in the virtual memory + * space. If the address translation is not used, then the physical + * address is passed. + * + * @return None. + * + * @note Unexpected errors may occur if the address mapping is changed + * after this function is invoked. + * +*******************************************************************************/ +void XVphy_CfgInitialize(XVphy *InstancePtr, XVphy_Config *ConfigPtr, + UINTPTR EffectiveAddr) +{ + u8 Sel; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(ConfigPtr != NULL); + Xil_AssertVoid(EffectiveAddr != 0x0); + + (void)memset((void *)InstancePtr, 0, sizeof(XVphy)); + InstancePtr->IsReady = 0; + + InstancePtr->Config = *ConfigPtr; + InstancePtr->Config.BaseAddr = EffectiveAddr; + +#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTXE2) + InstancePtr->GtAdaptor = &Gtxe2Config; +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE2) + InstancePtr->GtAdaptor = &Gthe2Config; +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTPE2) + InstancePtr->GtAdaptor = &Gtpe2Config; +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE3) + InstancePtr->GtAdaptor = &Gthe3Config; +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE4) + InstancePtr->GtAdaptor = &Gthe4Config; +#endif + + const XVphy_SysClkDataSelType SysClkCfg[7][2] = { + {(XVphy_SysClkDataSelType)0, XVPHY_SYSCLKSELDATA_TYPE_CPLL_OUTCLK}, + {(XVphy_SysClkDataSelType)1, XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK}, + {(XVphy_SysClkDataSelType)2, XVPHY_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK}, + {(XVphy_SysClkDataSelType)3, XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK}, + {(XVphy_SysClkDataSelType)4, XVPHY_SYSCLKSELDATA_TYPE_PLL0_OUTCLK}, + {(XVphy_SysClkDataSelType)5, XVPHY_SYSCLKSELDATA_TYPE_PLL1_OUTCLK}, + {(XVphy_SysClkDataSelType)6, XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK}, + }; + for (Sel = 0; Sel < 7; Sel++) { + if (InstancePtr->Config.TxSysPllClkSel == SysClkCfg[Sel][0]) { + InstancePtr->Config.TxSysPllClkSel = SysClkCfg[Sel][1]; + } + if (InstancePtr->Config.RxSysPllClkSel == SysClkCfg[Sel][0]) { + InstancePtr->Config.RxSysPllClkSel = SysClkCfg[Sel][1]; + } + } + + InstancePtr->Config.TxRefClkSel = (XVphy_PllRefClkSelType) + (InstancePtr->Config.TxRefClkSel + + XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0); + InstancePtr->Config.RxRefClkSel = (XVphy_PllRefClkSelType) + (InstancePtr->Config.RxRefClkSel + + XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0); + InstancePtr->Config.DruRefClkSel = (XVphy_PllRefClkSelType) + (InstancePtr->Config.DruRefClkSel + + XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0); + + /* Correct RefClkSel offsets for GTPE2 EAST and WEST RefClks */ + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2) { + if (InstancePtr->Config.TxRefClkSel > 6) { + InstancePtr->Config.TxRefClkSel = (XVphy_PllRefClkSelType) + (InstancePtr->Config.TxRefClkSel - 4); + } + if (InstancePtr->Config.RxRefClkSel > 6) { + InstancePtr->Config.RxRefClkSel = (XVphy_PllRefClkSelType) + (InstancePtr->Config.RxRefClkSel - 4); + } + if (InstancePtr->Config.DruRefClkSel > 6) { + InstancePtr->Config.DruRefClkSel = (XVphy_PllRefClkSelType) + (InstancePtr->Config.DruRefClkSel - 4); + } + } + + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; +} + +/*****************************************************************************/ +/** +* This function will initialize the PLL selection for a given channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param QpllRefClkSel is the QPLL reference clock selection for the +* quad. +* - In GTP, this is used to hold PLL0 refclk selection. +* @param CpllRefClkSel is the CPLL reference clock selection for the +* quad. +* - In GTP, this is used to hold PLL1 refclk selection. +* @param TxPllSelect is the reference clock selection for the quad's +* TX PLL dividers. +* @param RxPllSelect is the reference clock selection for the quad's +* RX PLL dividers. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_PllInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_PllRefClkSelType QpllRefClkSel, + XVphy_PllRefClkSelType CpllRefClkSel, + XVphy_PllType TxPllSelect, XVphy_PllType RxPllSelect) +{ + /* Suppress Warning Messages */ + ChId = ChId; + + /* Set configuration in software. */ + if (InstancePtr->Config.XcvrType != XVPHY_GT_TYPE_GTPE2) { + XVphy_CfgPllRefClkSel(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMNA, QpllRefClkSel); + XVphy_CfgPllRefClkSel(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CHA, CpllRefClkSel); + } + /* GTP. */ + else { + XVphy_CfgPllRefClkSel(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMN0, QpllRefClkSel); + XVphy_CfgPllRefClkSel(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMN1, CpllRefClkSel); + } + XVphy_CfgSysClkDataSel(InstancePtr, QuadId, XVPHY_DIR_TX, + Pll2SysClkData(TxPllSelect)); + XVphy_CfgSysClkDataSel(InstancePtr, QuadId, XVPHY_DIR_RX, + Pll2SysClkData(RxPllSelect)); + XVphy_CfgSysClkOutSel(InstancePtr, QuadId, XVPHY_DIR_TX, + Pll2SysClkOut(TxPllSelect)); + XVphy_CfgSysClkOutSel(InstancePtr, QuadId, XVPHY_DIR_RX, + Pll2SysClkOut(RxPllSelect)); + + /* Write configuration to hardware at once. */ + XVphy_WriteCfgRefClkSelReg(InstancePtr, QuadId); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/* +* This function installs a custom delay/sleep function to be used by the XVphy +* driver. +* +* @param InstancePtr is a pointer to the XVphy 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 XVphy_SetUserTimerHandler(XVphy *InstancePtr, + XVphy_TimerHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->UserTimerWaitUs = CallbackFunc; + InstancePtr->UserTimerPtr = CallbackRef; +} + +/******************************************************************************/ +/** +* This function is the delay/sleep function for the XVphy 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 XVphy instance. +* @param MicroSeconds is the number of microseconds to delay/sleep for. +* +* @return None. +* +* @note None. +* +*******************************************************************************/ +void XVphy_WaitUs(XVphy *InstancePtr, u32 MicroSeconds) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + if (MicroSeconds == 0) { + return; + } + + if (InstancePtr->UserTimerWaitUs != NULL) { + /* Use the timer handler specified by the user for better + * accuracy. */ + InstancePtr->UserTimerWaitUs(InstancePtr, MicroSeconds); + } + else { + /* Wait the requested amount of time. */ + usleep_range(MicroSeconds, MicroSeconds + MicroSeconds/10); + } +} + +#if defined (XPAR_XDP_0_DEVICE_ID) +/*****************************************************************************/ +/** +* This function will initialize the clocking for a given channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for TX or RX. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_ClkInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir) +{ + u32 Status; + + Status = XVphy_ClkCalcParams(InstancePtr, QuadId, ChId, Dir, 0); + if (Status != XST_SUCCESS) { + return Status; + } + + Status = XVphy_ClkReconfig(InstancePtr, QuadId, ChId); + if (Status != XST_SUCCESS) { + return Status; + } + + Status = XVphy_OutDivReconfig(InstancePtr, QuadId, ChId, Dir); + if (Status != XST_SUCCESS) { + return Status; + } + + Status = XVphy_DirReconfig(InstancePtr, QuadId, ChId, Dir); + + return Status; +} +#endif + +/*****************************************************************************/ +/** +* This function will obtian the IP version. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return The IP version of the Video PHY core. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_GetVersion(XVphy *InstancePtr) +{ + return XVphy_ReadReg(InstancePtr->Config.BaseAddr, XVPHY_VERSION_REG); +} + +/*****************************************************************************/ +/** +* Configure the channel's line rate. This is a software only configuration and +* this value is used in the PLL calculator. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param LineRate is the line rate to configure software. +* +* @return +* - XST_SUCCESS if the reference clock type is valid. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_CfgLineRate(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u64 LineRateHz) +{ + u8 Id; + u8 Id0; + u8 Id1; + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)].LineRateHz = + LineRateHz; + } + + return XST_SUCCESS; +} + +#if defined (XPAR_XDP_0_DEVICE_ID) +/*****************************************************************************/ +/** +* Configure the quad's reference clock frequency. This is a software only +* configuration and this value is used in the PLL calculator. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param RefClkType is the reference clock type to operate on. +* @param FreqHz is the reference clock frequency to configure software. +* +* @return +* - XST_SUCCESS if the reference clock type is valid. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_CfgQuadRefClkFreq(XVphy *InstancePtr, u8 QuadId, + XVphy_PllRefClkSelType RefClkType, u32 FreqHz) +{ + u8 RefClkIndex = RefClkType - XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0; + + if (RefClkType > XVPHY_PLL_REFCLKSEL_TYPE_GTGREFCLK) { + return XST_FAILURE; + } + InstancePtr->Quads[QuadId].RefClkHz[RefClkIndex] = FreqHz; + + return XST_SUCCESS; +} +#endif + +/*****************************************************************************/ +/** +* Obtain the channel's PLL reference clock selection. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param ChId is the channel ID which to operate on. +* +* @return The PLL type being used by the channel. +* +* @note None. +* +******************************************************************************/ +XVphy_PllType XVphy_GetPllType(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_ChannelId ChId) +{ + XVphy_SysClkDataSelType SysClkDataSel; + XVphy_SysClkOutSelType SysClkOutSel; + XVphy_PllType PllType; + + SysClkDataSel = XVphy_GetSysClkDataSel(InstancePtr, QuadId, Dir, ChId); + SysClkOutSel = XVphy_GetSysClkOutSel(InstancePtr, QuadId, Dir, ChId); + + /* The sysclk data and output reference clocks should match. */ + + if ((SysClkDataSel == XVPHY_SYSCLKSELDATA_TYPE_CPLL_OUTCLK) && + (SysClkOutSel == XVPHY_SYSCLKSELOUT_TYPE_CPLL_REFCLK)) { + PllType = XVPHY_PLL_TYPE_CPLL; + } + else if ((SysClkDataSel == XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK) && + (SysClkOutSel == XVPHY_SYSCLKSELOUT_TYPE_QPLL_REFCLK)) { + PllType = XVPHY_PLL_TYPE_QPLL; + } + else if ((SysClkDataSel == XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK) && + (SysClkOutSel == XVPHY_SYSCLKSELOUT_TYPE_QPLL0_REFCLK)) { + PllType = XVPHY_PLL_TYPE_QPLL0; + } + else if ((SysClkDataSel == XVPHY_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK) && + (SysClkOutSel == XVPHY_SYSCLKSELOUT_TYPE_QPLL1_REFCLK)) { + PllType = XVPHY_PLL_TYPE_QPLL1; + } + else { + PllType = XVPHY_PLL_TYPE_UNKNOWN; + } + /* For GTHE2, GTHE3, GTHE4, and GTXE2. */ + if (InstancePtr->Config.XcvrType != XVPHY_GT_TYPE_GTPE2) { + return PllType; + } + + if ((SysClkDataSel == XVPHY_SYSCLKSELDATA_TYPE_PLL0_OUTCLK) && + (SysClkOutSel == XVPHY_SYSCLKSELOUT_TYPE_PLL0_REFCLK)) { + PllType = XVPHY_PLL_TYPE_PLL0; + } + else if ((SysClkDataSel == XVPHY_SYSCLKSELDATA_TYPE_PLL1_OUTCLK) && + (SysClkOutSel == XVPHY_SYSCLKSELOUT_TYPE_PLL1_REFCLK)) { + PllType = XVPHY_PLL_TYPE_PLL1; + } + else { + PllType = XVPHY_PLL_TYPE_UNKNOWN; + } + /* For GTPE2. */ + return PllType; +} + +/*****************************************************************************/ +/** +* This function will return the line rate in Hz for a given channel / quad. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to check. +* @param ChId is the channel ID for which to retrieve the line rate. +* +* @return The line rate in Hz. +* +* @note None. +* +******************************************************************************/ +u64 XVphy_GetLineRateHz(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid((XVPHY_CHANNEL_ID_CH1 <= ChId) && + (ChId <= XVPHY_CHANNEL_ID_CMN1)); + + return InstancePtr->Quads[QuadId].Plls[ChId - + XVPHY_CHANNEL_ID_CH1].LineRateHz; +} + +#if defined (XPAR_XDP_0_DEVICE_ID) +/*****************************************************************************/ +/** +* This function will wait for a PMA reset done on the specified channel(s) or +* time out. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID which to operate on. +* @param Dir is an indicator for TX or RX. +* +* @return +* - XST_SUCCESS if the PMA reset has finalized. +* - XST_FAILURE otherwise; waiting for the reset done timed out. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_WaitForPmaResetDone(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + u8 Retry = 0; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_TX_INIT_STATUS_REG; + } + else { + RegOffset = XVPHY_RX_INIT_STATUS_REG; + } + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_TXRX_INIT_STATUS_PMARESETDONE_ALL_MASK; + } + else { + MaskVal = XVPHY_TXRX_INIT_STATUS_PMARESETDONE_MASK(ChId); + } + do { + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + if (!(RegVal & MaskVal)){ + XVphy_WaitUs(InstancePtr, 1000); + Retry++; + } + } while ((!(RegVal & MaskVal)) && (Retry < 15)); + + if (Retry == 15){ + return XST_FAILURE; + } + else { + return XST_SUCCESS; + } +} + +/*****************************************************************************/ +/** +* This function will wait for a reset done on the specified channel(s) or time +* out. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID which to operate on. +* @param Dir is an indicator for TX or RX. +* +* @return +* - XST_SUCCESS if the reset has finalized. +* - XST_FAILURE otherwise; waiting for the reset done timed out. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_WaitForResetDone(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + u8 Retry = 0; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_TX_INIT_STATUS_REG; + } + else { + RegOffset = XVPHY_RX_INIT_STATUS_REG; + } + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_TXRX_INIT_STATUS_RESETDONE_ALL_MASK; + } + else { + MaskVal = XVPHY_TXRX_INIT_STATUS_RESETDONE_MASK(ChId); + } + do { + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + if (!(RegVal & MaskVal)){ + XVphy_WaitUs(InstancePtr, 1000); + Retry++; + } + } while ((!(RegVal & MaskVal)) && (Retry < 15)); + + if (Retry == 15){ + return XST_FAILURE; + } + else { + return XST_SUCCESS; + } +} + +/*****************************************************************************/ +/** +* This function will wait for a PLL lock on the specified channel(s) or time +* out. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID which to operate on. +* +* @return +* - XST_SUCCESS if the PLL(s) have locked. +* - XST_FAILURE otherwise; waiting for the lock timed out. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_WaitForPllLock(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + u32 Status = XST_FAILURE; + u8 Retry = 0; + + do { + XVphy_WaitUs(InstancePtr, 1000); + Status = XVphy_IsPllLocked(InstancePtr, QuadId, ChId); + Retry++; + } while ((Status != XST_SUCCESS) && (Retry < 15)); + + return Status; +} +#endif + +/*****************************************************************************/ +/** +* This function will reset the GT's PLL logic. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID which to operate on. +* @param Dir is an indicator for TX or RX. +* @param Hold is an indicator whether to "hold" the reset if set to 1. +* If set to 0: reset, then enable. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_ResetGtPll(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Hold) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_TX_INIT_REG; + } + else { + RegOffset = XVPHY_RX_INIT_REG; + } + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_TXRX_INIT_PLLGTRESET_ALL_MASK; + } + else { + MaskVal = XVPHY_TXRX_INIT_PLLGTRESET_MASK(ChId); + } + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + /* Assert reset. */ + RegVal |= MaskVal; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + + if (!Hold) { + /* De-assert reset. */ + RegVal &= ~MaskVal; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will reset the GT's TX/RX logic. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID which to operate on. +* @param Dir is an indicator for TX or RX. +* @param Hold is an indicator whether to "hold" the reset if set to 1. +* If set to 0: reset, then enable. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_ResetGtTxRx(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Hold) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_TX_INIT_REG; + } + else { + RegOffset = XVPHY_RX_INIT_REG; + } + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_TXRX_INIT_GTRESET_ALL_MASK; + } + else { + MaskVal = XVPHY_TXRX_INIT_GTRESET_MASK(ChId); + } + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + /* Assert reset. */ + RegVal |= MaskVal; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + + if (!Hold) { + /* De-assert reset. */ + RegVal &= ~MaskVal; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will initiate a write DRP transaction. It is a wrapper around +* XVphy_DrpAccess. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID on which to direct the DRP access. +* @param Dir is an indicator for write (TX) or read (RX). +* @param Addr is the DRP address to issue the DRP access to. +* @param Val is the value to write to the DRP address. +* +* @return +* - XST_SUCCESS if the DRP access was successful. +* - XST_FAILURE otherwise, if the busy bit did not go low, or if +* the ready bit did not go high. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_DrpWrite(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u16 Addr, u16 Val) +{ + return XVphy_DrpAccess(InstancePtr, QuadId, ChId, + XVPHY_DIR_TX, /* Write. */ + Addr, &Val); +} + +/*****************************************************************************/ +/** +* This function will initiate a read DRP transaction. It is a wrapper around +* XVphy_DrpAccess. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID on which to direct the DRP access. +* @param Dir is an indicator for write (TX) or read (RX). +* @param Addr is the DRP address to issue the DRP access to. +* +* @return +* - XST_SUCCESS if the DRP access was successful. +* - XST_FAILURE otherwise, if the busy bit did not go low, or if +* the ready bit did not go high. +* +* @note None. +* +******************************************************************************/ +u16 XVphy_DrpRead(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, u16 Addr) +{ + u32 Status; + u16 Val; + + Status = XVphy_DrpAccess(InstancePtr, QuadId, ChId, + XVPHY_DIR_RX, /* Read. */ + Addr, &Val); + + return (Status == XST_SUCCESS) ? Val : 0; +} + +/*****************************************************************************/ +/** +* This function will power down the mixed-mode clock manager (MMCM) core. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param Hold is an indicator whether to "hold" the power down if set +* to 1. If set to 0: power down, then power back up. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +void XVphy_MmcmPowerDown(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir, + u8 Hold) +{ + u32 RegOffsetCtrl; + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XVPHY_DIR_TX) { + RegOffsetCtrl = XVPHY_MMCM_TXUSRCLK_CTRL_REG; + } + else { + RegOffsetCtrl = XVPHY_MMCM_RXUSRCLK_CTRL_REG; + } + + /* Power down. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl); + RegVal |= XVPHY_MMCM_USRCLK_CTRL_PWRDWN_MASK; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, RegVal); + + if (!Hold) { + /* Power up. */ + RegVal &= ~XVPHY_MMCM_USRCLK_CTRL_PWRDWN_MASK; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, + RegVal); + } +} + +/*****************************************************************************/ +/** +* This function will start the mixed-mode clock manager (MMCM) core. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_MmcmStart(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir) +{ +#if defined (XPAR_XDP_0_DEVICE_ID) + u32 Status; + u8 Retry; + + /* Enable MMCM. */ + XVphy_MmcmPowerDown(InstancePtr, QuadId, Dir, FALSE); + + XVphy_WaitUs(InstancePtr, 10000); + + /* Toggle MMCM reset. */ + XVphy_MmcmReset(InstancePtr, QuadId, Dir, FALSE); + + XVphy_WaitUs(InstancePtr, 10000); + + /* Configure MMCM. */ + Retry = 0; + do { + XVphy_WaitUs(InstancePtr, 10000); + Status = XVphy_MmcmWriteParameters(InstancePtr, QuadId, Dir); + Retry++; + } while ((Status != XST_SUCCESS) && (Retry < 3)); + + XVphy_WaitUs(InstancePtr, 10000); + + /* Toggle MMCM reset. */ + XVphy_MmcmReset(InstancePtr, QuadId, Dir, FALSE); +#else + /* Toggle MMCM reset. */ + XVphy_MmcmReset(InstancePtr, QuadId, Dir, FALSE); + + /* Configure MMCM. */ + XVphy_MmcmWriteParameters(InstancePtr, QuadId, Dir); + + /* Unmask the MMCM Lock */ + XVphy_MmcmLockedMaskEnable(InstancePtr, 0, Dir, FALSE); +#endif + + XVphy_LogWrite(InstancePtr, (Dir == XVPHY_DIR_TX) ? + XVPHY_LOG_EVT_TXPLL_RECONFIG : XVPHY_LOG_EVT_RXPLL_RECONFIG, 1); +} + +/*****************************************************************************/ +/** +* This function enables the TX or RX IBUFDS peripheral. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Dir is an indicator for TX or RX. +* @param Enable specifies TRUE/FALSE value to either enable or disable +* the IBUFDS, respectively. +* +* @return None. +* +******************************************************************************/ +void XVphy_IBufDsEnable(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir, + u8 Enable) +{ + XVphy_PllRefClkSelType *TypePtr, *DruTypePtr, DruTypeDummy; + u32 RegAddr = XVPHY_IBUFDS_GTXX_CTRL_REG; + u32 RegVal; + u32 MaskVal = 0; + DruTypeDummy = XVPHY_PLL_REFCLKSEL_TYPE_GTGREFCLK; + DruTypePtr = &DruTypeDummy; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XVPHY_DIR_TX) { + TypePtr = &InstancePtr->Config.TxRefClkSel; + } + else { + TypePtr = &InstancePtr->Config.RxRefClkSel; + if (InstancePtr->Config.DruIsPresent) { + DruTypePtr = &InstancePtr->Config.DruRefClkSel; + } + } + + if ((*TypePtr == XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0) || + ((InstancePtr->Config.DruIsPresent) && + (*DruTypePtr == XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0))) { + MaskVal = XVPHY_IBUFDS_GTXX_CTRL_GTREFCLK0_CEB_MASK; + } + else if ((*TypePtr == XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK1) || + ((InstancePtr->Config.DruIsPresent) && + (*DruTypePtr == XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK1))) { + MaskVal = XVPHY_IBUFDS_GTXX_CTRL_GTREFCLK1_CEB_MASK; + } + else { + if (Dir == XVPHY_DIR_TX) { + RegAddr = XVPHY_MISC_TXUSRCLK_REG; + } + else { + RegAddr = XVPHY_MISC_RXUSRCLK_REG; + } + MaskVal = XVPHY_MISC_XXUSRCLK_REFCLK_CEB_MASK; + } + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegAddr); + + if (Enable) { + RegVal &= ~MaskVal; + } + else { + RegVal |= MaskVal; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegAddr, RegVal); +} + +/*****************************************************************************/ +/** +* This function enables the TX or RX CLKOUT1 OBUFTDS peripheral. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Dir is an indicator for TX or RX. +* @param Enable specifies TRUE/FALSE value to either enable or disable +* the OBUFTDS, respectively. +* +* @return None. +* +******************************************************************************/ +void XVphy_Clkout1OBufTdsEnable(XVphy *InstancePtr, XVphy_DirectionType Dir, + u8 Enable) +{ + u32 RegVal; + u32 RegOffset; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_MISC_TXUSRCLK_REG; + } + else { + RegOffset = XVPHY_MISC_RXUSRCLK_REG; + } + + /* Read XXUSRCLK MISC register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + + /* Write new value to XXUSRCLK MISC register. */ + if (Enable) { + RegVal |= XVPHY_MISC_XXUSRCLK_CKOUT1_OEN_MASK; + } + else { + RegVal &= ~XVPHY_MISC_XXUSRCLK_CKOUT1_OEN_MASK; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); +} + +#if defined (XPAR_XDP_0_DEVICE_ID) +/*****************************************************************************/ +/** +* This function resets the BUFG_GT peripheral. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Dir is an indicator for TX or RX +* @param Reset specifies TRUE/FALSE value to either assert or deassert +* reset on the BUFG_GT, respectively. +* +* @return None. +* +******************************************************************************/ +void XVphy_BufgGtReset(XVphy *InstancePtr, XVphy_DirectionType Dir, u8 Reset) +{ + u32 RegVal; + u32 RegOffset; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_BUFGGT_TXUSRCLK_REG; + } + else { + RegOffset = XVPHY_BUFGGT_RXUSRCLK_REG; + } + + /* Read BUFG_GT register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + + /* Write new value to BUFG_GT register. */ + if (Reset) { + RegVal |= XVPHY_BUFGGT_XXUSRCLK_CLR_MASK; + } + else { + RegVal &= ~XVPHY_BUFGGT_XXUSRCLK_CLR_MASK; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); +} + +/*****************************************************************************/ +/** +* This function will set 8b10b encoding for the specified GT PLL. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param Enable is an indicator to enable/disable 8b10b encoding. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +void XVphy_Set8b10b(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Enable) +{ + u32 RegOffset; + u32 MaskVal; + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_TX_CONTROL_REG; + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_TX_CONTROL_TX8B10BEN_ALL_MASK; + } + else { + MaskVal = XVPHY_TX_CONTROL_TX8B10BEN_MASK(ChId); + } + } + else { + RegOffset = XVPHY_RX_CONTROL_REG; + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_RX_CONTROL_RX8B10BEN_ALL_MASK; + } + else { + MaskVal = XVPHY_RX_CONTROL_RX8B10BEN_MASK(ChId); + } + } + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + if (Enable) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); +} +#endif + +/*****************************************************************************/ +/** +* This function returns true when the RX and TX are bonded and are running +* from the same (RX) reference clock. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return TRUE if the RX and TX are using the same PLL, FALSE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_IsBonded(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + XVphy_SysClkDataSelType RxSysClkDataSel; + XVphy_SysClkOutSelType RxSysClkOutSel; + XVphy_SysClkDataSelType TxSysClkDataSel; + XVphy_SysClkOutSelType TxSysClkOutSel; + + if (ChId == XVPHY_CHANNEL_ID_CHA) { + ChId = XVPHY_CHANNEL_ID_CH1; + } + + RxSysClkDataSel = XVphy_GetSysClkDataSel(InstancePtr, QuadId, + XVPHY_DIR_RX, ChId); + RxSysClkOutSel = XVphy_GetSysClkOutSel(InstancePtr, QuadId, + XVPHY_DIR_RX, ChId); + TxSysClkDataSel = XVphy_GetSysClkDataSel(InstancePtr, QuadId, + XVPHY_DIR_TX, ChId); + TxSysClkOutSel = XVphy_GetSysClkOutSel(InstancePtr, QuadId, + XVPHY_DIR_TX, ChId); + + if ((RxSysClkDataSel == TxSysClkDataSel) && + (RxSysClkOutSel == TxSysClkOutSel)) { + return TRUE; + } + + return FALSE; +} + +/*****************************************************************************/ +/** +* This function will write the mixed-mode clock manager (MMCM) values currently +* stored in the driver's instance structure to hardware . +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* +* @return +* - XST_SUCCESS if the MMCM write was successful. +* - XST_FAILURE otherwise, if the configuration success bit did +* not go low. +* +* @note None. +* +******************************************************************************/ +static u32 XVphy_MmcmWriteParameters(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir) +{ + u32 RegOffsetCtrl; + u32 RegOffsetClk; + u32 RegVal; + XVphy_Mmcm *MmcmParams; +#if defined (XPAR_XDP_0_DEVICE_ID) + u8 Retry; +#endif + + if (Dir == XVPHY_DIR_TX) { + RegOffsetCtrl = XVPHY_MMCM_TXUSRCLK_CTRL_REG; + RegOffsetClk = XVPHY_MMCM_TXUSRCLK_REG1; + } + else { + RegOffsetCtrl = XVPHY_MMCM_RXUSRCLK_CTRL_REG; + RegOffsetClk = XVPHY_MMCM_RXUSRCLK_REG1; + } + MmcmParams = &InstancePtr->Quads[QuadId].Mmcm[Dir]; + + /* Check Parameters if has been Initialized */ + if (!MmcmParams->DivClkDivide && !MmcmParams->ClkFbOutMult && + !MmcmParams->ClkFbOutFrac && !MmcmParams->ClkOut0Frac && + !MmcmParams->ClkOut0Div && !MmcmParams->ClkOut1Div && + !MmcmParams->ClkOut2Div) { + return XST_FAILURE; + } + + /* MMCM_[TX|RX]USRCLK_REG1 */ + RegVal = MmcmParams->DivClkDivide; + RegVal |= (MmcmParams->ClkFbOutMult << + XVPHY_MMCM_USRCLK_REG1_CLKFBOUT_MULT_SHIFT); + RegVal |= (MmcmParams->ClkFbOutFrac << + XVPHY_MMCM_USRCLK_REG1_CLKFBOUT_FRAC_SHIFT); + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetClk, RegVal); + + /* MMCM_[TX|RX]USRCLK_REG2 */ + RegOffsetClk += 4; + RegVal = MmcmParams->ClkOut0Div; + RegVal |= (MmcmParams->ClkOut0Frac << + XVPHY_MMCM_USRCLK_REG2_CLKOUT0_FRAC_SHIFT); + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetClk, RegVal); + + /* MMCM_[TX|RX]USRCLK_REG3 */ + RegOffsetClk += 4; + RegVal = MmcmParams->ClkOut1Div; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetClk, RegVal); + + /* MMCM_[TX|RX]USRCLK_REG4 */ + RegOffsetClk += 4; + RegVal = MmcmParams->ClkOut2Div; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetClk, RegVal); + + /* Update the MMCM. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl); + RegVal |= XVPHY_MMCM_USRCLK_CTRL_CFG_NEW_MASK; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, RegVal); + +#if defined (XPAR_XDP_0_DEVICE_ID) + /* Wait until the MMCM indicates configuration has succeeded. */ + Retry = 0; + do { + XVphy_WaitUs(InstancePtr, 1000); + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + RegOffsetCtrl); + if (Retry > 15) { + return XST_FAILURE; + } + Retry++; + } while (!(RegVal & XVPHY_MMCM_USRCLK_CTRL_CFG_SUCCESS_MASK)); +#endif + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will initiate a DRP transaction (either read or write). +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID on which to direct the DRP access. +* @param Dir is an indicator for write (TX) or read (RX). +* @param Addr is the DRP address to issue the DRP access to. +* @param Val is a pointer to the data value. In write mode, this pointer +* will hold the value to write. In read mode, this pointer will +* be populated with the read value. +* +* @return +* - XST_SUCCESS if the DRP access was successful. +* - XST_FAILURE otherwise, if the busy bit did not go low, or if +* the ready bit did not go high. +* +* @note In read mode (Dir == XVPHY_DIR_RX), the data pointed to by Val +* will be populated with the u16 value that was read._ +* +******************************************************************************/ +static u32 XVphy_DrpAccess(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u16 Addr, u16 *Val) +{ + u32 RegOffsetCtrl; + u32 RegOffsetSts; + u32 RegVal; + u8 Retry; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + /* Determine which DRP registers to use based on channel. */ + if (XVPHY_ISCMN(ChId)) { + RegOffsetCtrl = XVPHY_DRP_CONTROL_COMMON_REG; + RegOffsetSts = XVPHY_DRP_STATUS_COMMON_REG; + } + else { + RegOffsetCtrl = XVPHY_DRP_CONTROL_CH1_REG + + (4 * XVPHY_CH2IDX(ChId)); + RegOffsetSts = XVPHY_DRP_STATUS_CH1_REG + + (4 * (XVPHY_CH2IDX(ChId))); + } + + if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2) && + ((InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_DP) || + (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_DP))) { + ChId = XVPHY_CHANNEL_ID_CHA; + XVphy_WaitUs(InstancePtr, 3000); + } + + /* Wait until the DRP status indicates that it is not busy.*/ + Retry = 0; + do { + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + RegOffsetSts); + if (Retry > 150) { + return XST_FAILURE; + } + Retry++; + } while (RegVal & XVPHY_DRP_STATUS_DRPBUSY_MASK); + + /* Write the command to the channel's DRP. */ + RegVal = (Addr & XVPHY_DRP_CONTROL_DRPADDR_MASK); + RegVal |= XVPHY_DRP_CONTROL_DRPEN_MASK; + if (Dir == XVPHY_DIR_TX) { + /* Enable write. */ + RegVal |= XVPHY_DRP_CONTROL_DRPWE_MASK; + RegVal |= ((*Val << XVPHY_DRP_CONTROL_DRPDI_SHIFT) & + XVPHY_DRP_CONTROL_DRPDI_MASK); + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, RegVal); + + /* Wait until the DRP status indicates ready.*/ + Retry = 0; + do { + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + RegOffsetSts); + if (Retry > 150) { + return XST_FAILURE; + } + Retry++; + } while (!(RegVal & XVPHY_DRP_STATUS_DRPRDY_MASK)); + + if (Dir == XVPHY_DIR_RX) { + /* Mask non-data out for read. */ + RegVal &= XVPHY_DRP_STATUS_DRPO_MASK; + /* Populate Val with read contents. */ + *Val = RegVal; + } + return XST_SUCCESS; +} + diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy.h b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy.h new file mode 100644 index 00000000000000..ac3647b0771ea3 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy.h @@ -0,0 +1,846 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy.h + * + * The Xilinx Video PHY (VPHY) driver. This driver supports the Xilinx Video PHY + * IP core. + * Version 1.0 supports: + * - GTXE2 and GTHE3 GT types. + * - DisplayPort and HDMI protocols. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 10/19/15 Initial release. + * 1.1 gm 02/01/16 Added EAST, WEST, PLL0 and PLL1 definitions + * for GTPE2. + * Added more events to XVphy_LogEvent definitions + * Added TxBufferBypass in XVphy_Config structure + * Added XVphy_SetDefaultPpc and XVphy_SetPpc functions + * als Added XVphy_GetLineRateHz function. + * 1.2 gm Added HdmiFastSwitch in XVphy_Config + * Changed EffectiveAddr datatype in XVphy_CfgInitialize + * to UINTPTR + * Added log events for debugging + * 1.2 gm 11/11/19 Added TransceiverWidth in XVphy_Config + * 1.4 gm 29/11/16 Moved internally used APIs to xvphy_i.c/h + * Added preprocessor directives for sw footprint reduction + * Made debug log optional (can be disabled via makefile) + * Added ERR_IRQ type_defs (not for official use for + * Xilinx debugging) + * Added transceiver width, AXIlite clk frequency and + * err_irq in XVphy_Config + * </pre> + * +*******************************************************************************/ + +#ifndef XVPHY_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XVPHY_H_ + +#if !defined(XV_CONFIG_LOG_VPHY_DISABLE) && !defined(XV_CONFIG_LOG_DISABLE_ALL) +#define XV_VPHY_LOG_ENABLE +#endif + +/******************************* Include Files ********************************/ + +#include "xil_assert.h" +#include "xvphy_hw.h" +#include "xil_printf.h" +#include "xvidc.h" +//#include "xvphy_dp.h" + +/****************************** Type Definitions ******************************/ + +/* This typedef enumerates the different GT types available. */ +typedef enum { + XVPHY_GT_TYPE_GTXE2 = 1, + XVPHY_GT_TYPE_GTHE2 = 2, + XVPHY_GT_TYPE_GTPE2 = 3, + XVPHY_GT_TYPE_GTHE3 = 4, + XVPHY_GT_TYPE_GTHE4 = 5, +} XVphy_GtType; + +/** + * This typedef enumerates the various protocols handled by the Video PHY + * controller (VPHY). + */ +typedef enum { + XVPHY_PROTOCOL_DP = 0, + XVPHY_PROTOCOL_HDMI, + XVPHY_PROTOCOL_NONE +} XVphy_ProtocolType; + +/* This typedef enumerates is used to specify RX/TX direction information. */ +typedef enum { + XVPHY_DIR_RX = 0, + XVPHY_DIR_TX +} XVphy_DirectionType; + +/** + * This typedef enumerates the list of available interrupt handler types. The + * values are used as parameters to the XVphy_SetIntrHandler function. + */ +typedef enum { + XVPHY_INTR_HANDLER_TYPE_TXRESET_DONE = XVPHY_INTR_TXRESETDONE_MASK, + XVPHY_INTR_HANDLER_TYPE_RXRESET_DONE = XVPHY_INTR_RXRESETDONE_MASK, + XVPHY_INTR_HANDLER_TYPE_CPLL_LOCK = XVPHY_INTR_CPLL_LOCK_MASK, + XVPHY_INTR_HANDLER_TYPE_QPLL_LOCK = XVPHY_INTR_QPLL_LOCK_MASK, + XVPHY_INTR_HANDLER_TYPE_QPLL0_LOCK = XVPHY_INTR_QPLL_LOCK_MASK, + XVPHY_INTR_HANDLER_TYPE_TXALIGN_DONE = XVPHY_INTR_TXALIGNDONE_MASK, + XVPHY_INTR_HANDLER_TYPE_QPLL1_LOCK = XVPHY_INTR_QPLL1_LOCK_MASK, + XVPHY_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE = + XVPHY_INTR_TXCLKDETFREQCHANGE_MASK, + XVPHY_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE = + XVPHY_INTR_RXCLKDETFREQCHANGE_MASK, + XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT = XVPHY_INTR_TXTMRTIMEOUT_MASK, + XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT = XVPHY_INTR_RXTMRTIMEOUT_MASK, +} XVphy_IntrHandlerType; + +/** + * This typedef enumerates the list of available hdmi handler types. The + * values are used as parameters to the XVphy_SetHdmiCallback function. + */ +typedef enum { + XVPHY_HDMI_HANDLER_TXINIT = 1, /**< TX init handler. */ + XVPHY_HDMI_HANDLER_TXREADY, /**< TX ready handler. */ + XVPHY_HDMI_HANDLER_RXINIT, /**< RX init handler. */ + XVPHY_HDMI_HANDLER_RXREADY /**< RX ready handler. */ +} XVphy_HdmiHandlerType; + +/** + * This typedef enumerates the different PLL types for a given GT channel. + */ +typedef enum { + XVPHY_PLL_TYPE_CPLL = 1, + XVPHY_PLL_TYPE_QPLL = 2, + XVPHY_PLL_TYPE_QPLL0 = 3, + XVPHY_PLL_TYPE_QPLL1 = 4, + XVPHY_PLL_TYPE_PLL0 = 5, + XVPHY_PLL_TYPE_PLL1 = 6, + XVPHY_PLL_TYPE_UNKNOWN = 7, +} XVphy_PllType; + +/** + * This typedef enumerates the available channels. + */ +typedef enum { + XVPHY_CHANNEL_ID_CH1 = 1, + XVPHY_CHANNEL_ID_CH2 = 2, + XVPHY_CHANNEL_ID_CH3 = 3, + XVPHY_CHANNEL_ID_CH4 = 4, + XVPHY_CHANNEL_ID_CMN0 = 5, + XVPHY_CHANNEL_ID_CMN1 = 6, + XVPHY_CHANNEL_ID_CHA = 7, + XVPHY_CHANNEL_ID_CMNA = 8, + XVPHY_CHANNEL_ID_CMN = XVPHY_CHANNEL_ID_CMN0, +} XVphy_ChannelId; + +/** + * This typedef enumerates the available reference clocks for the PLL clock + * selection multiplexer. + */ +typedef enum { + XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0 = XVPHY_REF_CLK_SEL_XPLL_GTREFCLK0, + XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK1 = XVPHY_REF_CLK_SEL_XPLL_GTREFCLK1, + XVPHY_PLL_REFCLKSEL_TYPE_GTNORTHREFCLK0 = + XVPHY_REF_CLK_SEL_XPLL_GTNORTHREFCLK0, + XVPHY_PLL_REFCLKSEL_TYPE_GTNORTHREFCLK1 = + XVPHY_REF_CLK_SEL_XPLL_GTNORTHREFCLK1, + XVPHY_PLL_REFCLKSEL_TYPE_GTSOUTHREFCLK0 = + XVPHY_REF_CLK_SEL_XPLL_GTSOUTHREFCLK0, + XVPHY_PLL_REFCLKSEL_TYPE_GTSOUTHREFCLK1 = + XVPHY_REF_CLK_SEL_XPLL_GTSOUTHREFCLK1, + XVPHY_PLL_REFCLKSEL_TYPE_GTEASTREFCLK0 = + XVPHY_REF_CLK_SEL_XPLL_GTEASTREFCLK0, + XVPHY_PLL_REFCLKSEL_TYPE_GTEASTREFCLK1 = + XVPHY_REF_CLK_SEL_XPLL_GTEASTREFCLK1, + XVPHY_PLL_REFCLKSEL_TYPE_GTWESTREFCLK0 = + XVPHY_REF_CLK_SEL_XPLL_GTWESTREFCLK0, + XVPHY_PLL_REFCLKSEL_TYPE_GTWESTREFCLK1 = + XVPHY_REF_CLK_SEL_XPLL_GTWESTREFCLK1, + XVPHY_PLL_REFCLKSEL_TYPE_GTGREFCLK = + XVPHY_REF_CLK_SEL_XPLL_GTGREFCLK, +} XVphy_PllRefClkSelType; + +/** + * This typedef enumerates the available reference clocks used to drive the + * RX/TX datapaths. + */ +typedef enum { + XVPHY_SYSCLKSELDATA_TYPE_PLL0_OUTCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_PLL0, + XVPHY_SYSCLKSELDATA_TYPE_PLL1_OUTCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_PLL1, + XVPHY_SYSCLKSELDATA_TYPE_CPLL_OUTCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_CPLL, + XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL, + XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL0, + XVPHY_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL1, +} XVphy_SysClkDataSelType; + +/** + * This typedef enumerates the available reference clocks used to drive the + * RX/TX output clocks. + */ +typedef enum { + XVPHY_SYSCLKSELOUT_TYPE_CPLL_REFCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CH, + XVPHY_SYSCLKSELOUT_TYPE_QPLL_REFCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN, + XVPHY_SYSCLKSELOUT_TYPE_QPLL0_REFCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN0, + XVPHY_SYSCLKSELOUT_TYPE_QPLL1_REFCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN1, + XVPHY_SYSCLKSELOUT_TYPE_PLL0_REFCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CH, + XVPHY_SYSCLKSELOUT_TYPE_PLL1_REFCLK = + XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN, +} XVphy_SysClkOutSelType; + +/** + * This typedef enumerates the available clocks that are used as multiplexer + * input selections for the RX/TX output clock. + */ +typedef enum { + XVPHY_OUTCLKSEL_TYPE_OUTCLKPCS = 1, + XVPHY_OUTCLKSEL_TYPE_OUTCLKPMA, + XVPHY_OUTCLKSEL_TYPE_PLLREFCLK_DIV1, + XVPHY_OUTCLKSEL_TYPE_PLLREFCLK_DIV2, + XVPHY_OUTCLKSEL_TYPE_PROGDIVCLK +} XVphy_OutClkSelType; + +/* This typedef enumerates the possible states a transceiver can be in. */ +typedef enum { + XVPHY_GT_STATE_IDLE, /**< Idle state. */ + XVPHY_GT_STATE_LOCK, /**< Lock state. */ + XVPHY_GT_STATE_RESET, /**< Reset state. */ + XVPHY_GT_STATE_ALIGN, /**< Align state. */ + XVPHY_GT_STATE_READY, /**< Ready state. */ +} XVphy_GtState; + +#ifdef XV_VPHY_LOG_ENABLE +typedef enum { + XVPHY_LOG_EVT_NONE = 1, /**< Log event none. */ + XVPHY_LOG_EVT_QPLL_EN, /**< Log event QPLL enable. */ + XVPHY_LOG_EVT_QPLL_RST, /**< Log event QPLL reset. */ + XVPHY_LOG_EVT_QPLL_LOCK, /**< Log event QPLL lock. */ + XVPHY_LOG_EVT_QPLL_RECONFIG, /**< Log event QPLL reconfig. */ + XVPHY_LOG_EVT_QPLL0_EN, /**< Log event QPLL0 enable. */ + XVPHY_LOG_EVT_QPLL0_RST, /**< Log event QPLL0 reset. */ + XVPHY_LOG_EVT_QPLL0_LOCK, /**< Log event QPLL0 lock. */ + XVPHY_LOG_EVT_QPLL0_RECONFIG, /**< Log event QPLL0 reconfig. */ + XVPHY_LOG_EVT_QPLL1_EN, /**< Log event QPLL1 enable. */ + XVPHY_LOG_EVT_QPLL1_RST, /**< Log event QPLL1 reset. */ + XVPHY_LOG_EVT_QPLL1_LOCK, /**< Log event QPLL1 lock. */ + XVPHY_LOG_EVT_QPLL1_RECONFIG, /**< Log event QPLL1 reconfig. */ + XVPHY_LOG_EVT_PLL0_EN, /**< Log event PLL0 reset. */ + XVPHY_LOG_EVT_PLL0_RST, /**< Log event PLL0 reset. */ + XVPHY_LOG_EVT_PLL0_LOCK, /**< Log event PLL0 lock. */ + XVPHY_LOG_EVT_PLL0_RECONFIG, /**< Log event PLL0 reconfig. */ + XVPHY_LOG_EVT_PLL1_EN, /**< Log event PLL1 reset. */ + XVPHY_LOG_EVT_PLL1_RST, /**< Log event PLL1 reset. */ + XVPHY_LOG_EVT_PLL1_LOCK, /**< Log event PLL1 lock. */ + XVPHY_LOG_EVT_PLL1_RECONFIG, /**< Log event PLL1 reconfig. */ + XVPHY_LOG_EVT_CPLL_EN, /**< Log event CPLL reset. */ + XVPHY_LOG_EVT_CPLL_RST, /**< Log event CPLL reset. */ + XVPHY_LOG_EVT_CPLL_LOCK, /**< Log event CPLL lock. */ + XVPHY_LOG_EVT_CPLL_RECONFIG, /**< Log event CPLL reconfig. */ + XVPHY_LOG_EVT_TXPLL_EN, /**< Log event TXPLL enable. */ + XVPHY_LOG_EVT_TXPLL_RST, /**< Log event TXPLL reset. */ + XVPHY_LOG_EVT_RXPLL_EN, /**< Log event RXPLL enable. */ + XVPHY_LOG_EVT_RXPLL_RST, /**< Log event RXPLL reset. */ + XVPHY_LOG_EVT_GTRX_RST, /**< Log event GT RX reset. */ + XVPHY_LOG_EVT_GTTX_RST, /**< Log event GT TX reset. */ + XVPHY_LOG_EVT_VID_TX_RST, /**< Log event Vid TX reset. */ + XVPHY_LOG_EVT_VID_RX_RST, /**< Log event Vid RX reset. */ + XVPHY_LOG_EVT_TX_ALIGN, /**< Log event TX align. */ + XVPHY_LOG_EVT_TX_ALIGN_TMOUT, /**< Log event TX align Timeout. */ + XVPHY_LOG_EVT_TX_TMR, /**< Log event TX timer. */ + XVPHY_LOG_EVT_RX_TMR, /**< Log event RX timer. */ + XVPHY_LOG_EVT_GT_RECONFIG, /**< Log event GT reconfig. */ + XVPHY_LOG_EVT_GT_TX_RECONFIG, /**< Log event GT reconfig. */ + XVPHY_LOG_EVT_GT_RX_RECONFIG, /**< Log event GT reconfig. */ + XVPHY_LOG_EVT_INIT, /**< Log event init. */ + XVPHY_LOG_EVT_TXPLL_RECONFIG, /**< Log event TXPLL reconfig. */ + XVPHY_LOG_EVT_RXPLL_RECONFIG, /**< Log event RXPLL reconfig. */ + XVPHY_LOG_EVT_RXPLL_LOCK, /**< Log event RXPLL lock. */ + XVPHY_LOG_EVT_TXPLL_LOCK, /**< Log event TXPLL lock. */ + XVPHY_LOG_EVT_TX_RST_DONE, /**< Log event TX reset done. */ + XVPHY_LOG_EVT_RX_RST_DONE, /**< Log event RX reset done. */ + XVPHY_LOG_EVT_TX_FREQ, /**< Log event TX frequency. */ + XVPHY_LOG_EVT_RX_FREQ, /**< Log event RX frequency. */ + XVPHY_LOG_EVT_DRU_EN, /**< Log event DRU enable/disable. */ + XVPHY_LOG_EVT_GT_PLL_LAYOUT,/**< Log event GT PLL Layout Change. */ + XVPHY_LOG_EVT_GT_UNBONDED, /**< Log event GT Unbonded Change. */ + XVPHY_LOG_EVT_1PPC_ERR, /**< Log event 1 PPC Error. */ + XVPHY_LOG_EVT_PPC_MSMTCH_ERR,/**< Log event PPC MismatchError. */ + XVPHY_LOG_EVT_VDCLK_HIGH_ERR,/**< Log event VidClk more than 148.5 MHz. */ + XVPHY_LOG_EVT_NO_DRU, /**< Log event Vid not supported no DRU. */ + XVPHY_LOG_EVT_GT_QPLL_CFG_ERR,/**< Log event QPLL Config not found. */ + XVPHY_LOG_EVT_GT_CPLL_CFG_ERR,/**< Log event QPLL Config not found. */ + XVPHY_LOG_EVT_VD_NOT_SPRTD_ERR,/**< Log event Vid format not supported. */ + XVPHY_LOG_EVT_MMCM_ERR, /**< Log event MMCM Config not found. */ + XVPHY_LOG_EVT_DUMMY, /**< Dummy Event should be last */ +} XVphy_LogEvent; +#endif + +/* This typedef enumerates the possible error conditions. */ +typedef enum { + XVPHY_ERRIRQ_QPLL_CFG = 0x1, /**< QPLL CFG not found. */ + XVPHY_ERRIRQ_CPLL_CFG = 0x2, /**< CPLL CFG not found. */ + XVPHY_ERRIRQ_NO_DRU = 0x4, /**< No DRU in design. */ + XVPHY_ERRIRQ_VD_NOT_SPRTD= 0x8, /**< Video Not Supported. */ + XVPHY_ERRIRQ_MMCM_CFG = 0x10,/**< MMCM CFG not found. */ + XVPHY_ERRIRQ_PLL_LAYOUT = 0x20,/**< PLL Error. */ +} XVphy_ErrIrqType; + +/******************************************************************************/ +/** + * Callback type which represents the handler for interrupts. + * + * @param InstancePtr is a pointer to the XVphy instance. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XVphy_IntrHandler)(void *InstancePtr); + +/******************************************************************************/ +/** + * Callback type which represents a custom timer wait handler. This is only + * used for Microblaze since it doesn't have a native sleep function. To avoid + * dependency on a hardware timer, the default wait functionality is implemented + * using loop iterations; this isn't too accurate. If a custom timer handler is + * used, the user may implement their own wait implementation using a hardware + * timer (see example/) for better accuracy. + * + * @param InstancePtr is a pointer to the XVphy instance. + * @param MicroSeconds is the number of microseconds to be passed to the + * timer function. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XVphy_TimerHandler)(void *InstancePtr, u32 MicroSeconds); + +/******************************************************************************/ +/** + * Generic callback type. + * + * @param CallbackRef is a pointer to the callback reference. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XVphy_Callback)(void *CallbackRef); + +/** + * This typedef contains configuration information for CPLL/QPLL programming. + */ +typedef struct { + u8 MRefClkDiv; + /* Aliases for N (QPLL) and N1/N2 (CPLL). */ + union { + u8 NFbDivs[2]; + u8 NFbDiv; + struct { + u8 N1FbDiv; + u8 N2FbDiv; + }; + }; + u16 Cdr[5]; + u8 IsLowerBand; +} XVphy_PllParam; + +/** + * This typedef contains configuration information for PLL type and its + * reference clock. + */ +typedef struct { + /* Below members are common between CPLL/QPLL. */ + u64 LineRateHz; /**< The line rate for the + channel. */ + union { + XVphy_PllParam QpllParams; + XVphy_PllParam CpllParams; /**< Parameters for a CPLL. */ + XVphy_PllParam PllParams; + }; + union { + XVphy_PllRefClkSelType CpllRefClkSel; + /**< Multiplexer selection for + the reference clock of + the CPLL. */ + XVphy_PllRefClkSelType PllRefClkSel; + }; + /* Below members are CPLL specific. */ + union { + struct { + u8 RxOutDiv; /**< Output clock divider D for + the RX datapath. */ + u8 TxOutDiv; /**< Output clock divider D for + the TX datapath. */ + }; + u8 OutDiv[2]; + }; + union { + struct { + XVphy_GtState RxState; /**< Current state of RX GT. */ + XVphy_GtState TxState; /**< Current state of TX GT. */ + }; + XVphy_GtState GtState[2]; + }; + union { + struct { + XVphy_ProtocolType RxProtocol; + /**< The protocol which the RX + path is used for. */ + XVphy_ProtocolType TxProtocol; + /**< The protocol which the TX + path is used for. */ + }; + XVphy_ProtocolType Protocol[2]; + }; + union { + struct { + XVphy_SysClkDataSelType RxDataRefClkSel; + /**< Multiplexer selection for + the reference clock of + the RX datapath. */ + XVphy_SysClkDataSelType TxDataRefClkSel; + /**< Multiplexer selection for + the reference clock of + the TX datapath. */ + }; + XVphy_SysClkDataSelType DataRefClkSel[2]; + }; + union { + struct { + XVphy_SysClkOutSelType RxOutRefClkSel; + /**< Multiplexer selection for + the reference clock of + the RX output clock. */ + XVphy_SysClkOutSelType TxOutRefClkSel; + /**< Multiplexer selection for + the reference clock of + the TX output clock. */ + }; + XVphy_SysClkOutSelType OutRefClkSel[2]; + }; + union { + struct { + XVphy_OutClkSelType RxOutClkSel; + /**< Multiplexer selection for + which clock to use as + the RX output clock. */ + XVphy_OutClkSelType TxOutClkSel; + /**< Multiplexer selection for + which clock to use as + the TX output clock. */ + }; + XVphy_OutClkSelType OutClkSel[2]; + }; + union { + struct { + u8 RxDelayBypass; /**< Bypasses the delay + alignment block for the + RX output clock. */ + u8 TxDelayBypass; /**< Bypasses the delay + alignment block for the + TX output clock. */ + }; + u8 DelayBypass; + }; + u8 RxDataWidth; /**< In bits. */ + u8 RxIntDataWidth; /**< In bytes. */ + u8 TxDataWidth; /**< In bits. */ + u8 TxIntDataWidth; /**< In bytes. */ +} XVphy_Channel; + +/** + * This typedef contains configuration information for MMCM programming. + */ +typedef struct { + u8 DivClkDivide; + u8 ClkFbOutMult; + u16 ClkFbOutFrac; + u8 ClkOut0Div; + u16 ClkOut0Frac; + u8 ClkOut1Div; + u8 ClkOut2Div; +} XVphy_Mmcm; + +/** + * This typedef represents a GT quad. + */ +typedef struct { + union { + struct { + XVphy_Mmcm RxMmcm; /**< Mixed-mode clock manager + (MMCM) parameters for + RX. */ + XVphy_Mmcm TxMmcm; /**< MMCM parameters for TX. */ + }; + XVphy_Mmcm Mmcm[2]; /**< MMCM parameters. */ + }; + union { + struct { + XVphy_Channel Ch1; + XVphy_Channel Ch2; + XVphy_Channel Ch3; + XVphy_Channel Ch4; + XVphy_Channel Cmn0; + XVphy_Channel Cmn1; + }; + XVphy_Channel Plls[6]; + }; + union { + struct { + u32 GtRefClk0Hz; + u32 GtRefClk1Hz; + u32 GtNorthRefClk0Hz; + u32 GtNorthRefClk1Hz; + u32 GtSouthRefClk0Hz; + u32 GtSouthRefClk1Hz; + u32 GtgRefClkHz; + }; + u32 RefClkHz[7]; + }; +} XVphy_Quad; + +#ifdef XV_VPHY_LOG_ENABLE +/** + * This typedef contains the logging mechanism for debug. + */ +typedef struct { + u16 DataBuffer[256]; /**< Log buffer with event data. */ + u8 HeadIndex; /**< Index of the head entry of the + Event/DataBuffer. */ + u8 TailIndex; /**< Index of the tail entry of the + Event/DataBuffer. */ +} XVphy_Log; +#endif + +/** + * This typedef contains configuration information for the Video PHY core. + */ +typedef struct { + u16 DeviceId; /**< Device instance ID. */ + UINTPTR BaseAddr; /**< The base address of the core + instance. */ + XVphy_GtType XcvrType; /**< VPHY Transceiver Type */ + u8 TxChannels; /**< No. of active channels in TX */ + u8 RxChannels; /**< No. of active channels in RX */ + XVphy_ProtocolType TxProtocol; /**< Protocol which TX is used for. */ + XVphy_ProtocolType RxProtocol; /**< Protocol which RX is used for. */ + XVphy_PllRefClkSelType TxRefClkSel; /**< TX REFCLK selection. */ + XVphy_PllRefClkSelType RxRefClkSel; /**< RX REFCLK selection. */ + XVphy_SysClkDataSelType TxSysPllClkSel; /**< TX SYSCLK selection. */ + XVphy_SysClkDataSelType RxSysPllClkSel; /**< RX SYSCLK selectino. */ + u8 DruIsPresent; /**< A data recovery unit (DRU) exists + in the design .*/ + XVphy_PllRefClkSelType DruRefClkSel; /**< DRU REFCLK selection. */ + XVidC_PixelsPerClock Ppc; /**< Number of input pixels per + clock. */ + u8 TxBufferBypass; /**< TX Buffer Bypass is enabled in the + design. */ + u8 HdmiFastSwitch; /**< HDMI fast switching is enabled in the + design. */ + u8 TransceiverWidth; /**< Transceiver Width seeting in the design */ + u32 ErrIrq; /**< Error IRQ is enalbed in design */ + u32 AxiLiteClkFreq; /**< AXI Lite Clock Frequency in Hz */ +} XVphy_Config; + +/* Forward declaration. */ +struct XVphy_GtConfigS; + +/** + * The XVphy driver instance data. The user is required to allocate a variable + * of this type for every XVphy device in the system. A pointer to a variable of + * this type is then passed to the driver API functions. + */ +typedef struct { + u32 IsReady; /**< Device is initialized and + ready. */ + XVphy_Config Config; /**< Configuration structure for + the Video PHY core. */ + const struct XVphy_GtConfigS *GtAdaptor; +#ifdef XV_VPHY_LOG_ENABLE + XVphy_Log Log; /**< A log of events. */ +#endif + XVphy_Quad Quads[2]; /**< The quads available to the + Video PHY core.*/ + u32 HdmiRxRefClkHz; /**< HDMI RX refclk. */ + u32 HdmiTxRefClkHz; /**< HDMI TX refclk. */ + u8 HdmiRxTmdsClockRatio; /**< HDMI TMDS clock ratio. */ + u8 HdmiTxSampleRate; /**< HDMI TX sample rate. */ + u8 HdmiRxDruIsEnabled; /**< The DRU is enabled. */ + XVphy_IntrHandler IntrCpllLockHandler; /**< Callback function for CPLL + lock interrupts. */ + void *IntrCpllLockCallbackRef; /**< A pointer to the user data + passed to the CPLL lock + callback function. */ + XVphy_IntrHandler IntrQpllLockHandler; /**< Callback function for QPLL + lock interrupts. */ + void *IntrQpllLockCallbackRef; /**< A pointer to the user data + passed to the QPLL lock + callback function. */ + XVphy_IntrHandler IntrQpll1LockHandler; /**< Callback function for QPLL + lock interrupts. */ + void *IntrQpll1LockCallbackRef; /**< A pointer to the user data + passed to the QPLL lock + callback function. */ + XVphy_IntrHandler IntrTxResetDoneHandler; /**< Callback function for TX + reset done lock + interrupts. */ + void *IntrTxResetDoneCallbackRef; /**< A pointer to the user data + passed to the TX reset + done lock callback + function. */ + XVphy_IntrHandler IntrRxResetDoneHandler; /**< Callback function for RX + reset done lock + interrupts. */ + void *IntrRxResetDoneCallbackRef; /**< A pointer to the user data + passed to the RX reset + done lock callback + function. */ + XVphy_IntrHandler IntrTxAlignDoneHandler; /**< Callback function for TX + align done lock + interrupts. */ + void *IntrTxAlignDoneCallbackRef; /**< A pointer to the user data + passed to the TX align + done lock callback + function. */ + XVphy_IntrHandler IntrTxClkDetFreqChangeHandler; /**< Callback function + for TX clock detector + frequency change + interrupts. */ + void *IntrTxClkDetFreqChangeCallbackRef; /**< A pointer to the user data + passed to the TX clock + detector frequency + change callback + function. */ + XVphy_IntrHandler IntrRxClkDetFreqChangeHandler; /**< Callback function + for RX clock detector + frequency change + interrupts. */ + void *IntrRxClkDetFreqChangeCallbackRef; /**< A pointer to the user data + passed to the RX clock + detector frequency + change callback + function. */ + XVphy_IntrHandler IntrTxTmrTimeoutHandler; /**< Callback function for TX + timer timeout + interrupts. */ + void *IntrTxTmrTimeoutCallbackRef; /**< A pointer to the user data + passed to the TX timer + timeout callback + function. */ + XVphy_IntrHandler IntrRxTmrTimeoutHandler; /**< Callback function for RX + timer timeout + interrupts. */ + void *IntrRxTmrTimeoutCallbackRef; /**< A pointer to the user data + passed to the RX timer + timeout callback + function. */ + /* HDMI callbacks. */ + XVphy_Callback HdmiTxInitCallback; /**< Callback for TX init. */ + void *HdmiTxInitRef; /**< To be passed to the TX init + callback. */ + XVphy_Callback HdmiTxReadyCallback; /**< Callback for TX ready. */ + void *HdmiTxReadyRef; /**< To be passed to the TX + ready callback. */ + XVphy_Callback HdmiRxInitCallback; /**< Callback for RX init. */ + void *HdmiRxInitRef; /**< To be passed to the RX + init callback. */ + XVphy_Callback HdmiRxReadyCallback; /**< Callback for RX ready. */ + void *HdmiRxReadyRef; /**< To be passed to the RX + ready callback. */ + XVphy_TimerHandler UserTimerWaitUs; /**< Custom user function for + delay/sleep. */ + void *UserTimerPtr; /**< Pointer to a timer instance + used by the custom user + delay/sleep function. */ +} XVphy; + +/**************************** Function Prototypes *****************************/ + +/* xvphy.c: Setup and initialization functions. */ +void XVphy_CfgInitialize(XVphy *InstancePtr, XVphy_Config *ConfigPtr, + UINTPTR EffectiveAddr); +u32 XVphy_PllInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_PllRefClkSelType QpllRefClkSel, + XVphy_PllRefClkSelType CpllxRefClkSel, + XVphy_PllType TxPllSelect, XVphy_PllType RxPllSelect); +#if defined (XPAR_XDP_0_DEVICE_ID) +u32 XVphy_ClkInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir); +#endif +u32 XVphy_GetVersion(XVphy *InstancePtr); +void XVphy_WaitUs(XVphy *InstancePtr, u32 MicroSeconds); +void XVphy_SetUserTimerHandler(XVphy *InstancePtr, + XVphy_TimerHandler CallbackFunc, void *CallbackRef); + +/* xvphy.c: Channel configuration functions - setters. */ +u32 XVphy_CfgLineRate(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u64 LineRateHz); +#if defined (XPAR_XDP_0_DEVICE_ID) +u32 XVphy_CfgQuadRefClkFreq(XVphy *InstancePtr, u8 QuadId, + XVphy_PllRefClkSelType RefClkType, u32 FreqHz); +#endif + +/* xvphy.c: Channel configuration functions - getters. */ +XVphy_PllType XVphy_GetPllType(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_ChannelId ChId); +u64 XVphy_GetLineRateHz(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); + +/* xvphy.c: Reset functions. */ +#if defined (XPAR_XDP_0_DEVICE_ID) +u32 XVphy_WaitForPmaResetDone(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir); +u32 XVphy_WaitForResetDone(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir); +u32 XVphy_WaitForPllLock(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +#endif +u32 XVphy_ResetGtPll(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Hold); +u32 XVphy_ResetGtTxRx(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Hold); + +/* xvphy.c: GT/MMCM DRP access. */ +u32 XVphy_DrpWrite(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u16 Addr, u16 Val); +u16 XVphy_DrpRead(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u16 Addr); +void XVphy_MmcmPowerDown(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir, + u8 Hold); +void XVphy_MmcmStart(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir); +void XVphy_IBufDsEnable(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir, + u8 Enable); +void XVphy_Clkout1OBufTdsEnable(XVphy *InstancePtr, XVphy_DirectionType Dir, + u8 Enable); +#if defined (XPAR_XDP_0_DEVICE_ID) +void XVphy_BufgGtReset(XVphy *InstancePtr, XVphy_DirectionType Dir, u8 Reset); + +/* xvphy.c Miscellaneous control. */ +void XVphy_Set8b10b(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Enable); +#endif +u32 XVphy_IsBonded(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); + +/* xvphy_log.c: Logging functions. */ +void XVphy_LogDisplay(XVphy *InstancePtr); +void XVphy_LogReset(XVphy *InstancePtr); +u16 XVphy_LogRead(XVphy *InstancePtr); +#ifdef XV_VPHY_LOG_ENABLE +void XVphy_LogWrite(XVphy *InstancePtr, XVphy_LogEvent Evt, u8 Data); +#else +#define XVphy_LogWrite(...) +#endif + +/* xvphy_intr.c: Interrupt handling functions. */ +void XVphy_InterruptHandler(XVphy *InstancePtr); + +/* xvphy_selftest.c: Self test function. */ +u32 XVphy_SelfTest(XVphy *InstancePtr); + +/* xvphy_sinit.c: Configuration extraction function. */ +XVphy_Config *XVphy_LookupConfig(u16 DeviceId); + +/* xvphy_dp.c, xvphy_hdmi.c, xvphy_hdmi_intr.c: Protocol specific functions. */ +u32 XVphy_DpInitialize(XVphy *InstancePtr, XVphy_Config *CfgPtr, u8 QuadId, + XVphy_PllRefClkSelType CpllRefClkSel, + XVphy_PllRefClkSelType QpllRefClkSel, + XVphy_PllType TxPllSelect, XVphy_PllType RxPllSelect, + u8 LinkRate); +u32 XVphy_HdmiInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_Config *CfgPtr, + u32 SystemFrequency); +u32 XVphy_SetHdmiTxParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVidC_PixelsPerClock Ppc, XVidC_ColorDepth Bpc, + XVidC_ColorFormat ColorFormat); +u32 XVphy_SetHdmiRxParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); + +u32 XVphy_HdmiCfgCalcMmcmParam(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir, + XVidC_PixelsPerClock Ppc, XVidC_ColorDepth Bpc); + +void XVphy_HdmiUpdateClockSelection(XVphy *InstancePtr, u8 QuadId, + XVphy_SysClkDataSelType TxSysPllClkSel, + XVphy_SysClkDataSelType RxSysPllClkSel); +void XVphy_ClkDetFreqReset(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir); +u32 XVphy_ClkDetGetRefClkFreqHz(XVphy *InstancePtr, XVphy_DirectionType Dir); +u32 XVphy_DruGetRefClkFreqHz(XVphy *InstancePtr); +void XVphy_HdmiDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +void XVphy_DpDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +void XVphy_SetHdmiCallback(XVphy *InstancePtr, + XVphy_HdmiHandlerType HandlerType, + void *CallbackFunc, void *CallbackRef); + +/******************* Macros (Inline Functions) Definitions ********************/ + +#define XVPHY_CH2IDX(Id) ((Id) - XVPHY_CHANNEL_ID_CH1) +#define XVPHY_ISCH(Id) (((Id) == XVPHY_CHANNEL_ID_CHA) || \ + ((XVPHY_CHANNEL_ID_CH1 <= (Id)) && ((Id) <= XVPHY_CHANNEL_ID_CH4))) +#define XVPHY_ISCMN(Id) (((Id) == XVPHY_CHANNEL_ID_CMNA) || \ + ((XVPHY_CHANNEL_ID_CMN0 <= (Id)) && ((Id) <= XVPHY_CHANNEL_ID_CMN1))) + +#define XVphy_IsTxUsingQpll(InstancePtr, QuadId, ChId) \ + ((XVPHY_PLL_TYPE_QPLL == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_TX, ChId)) || \ + (XVPHY_PLL_TYPE_QPLL0 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_TX, ChId)) || \ + (XVPHY_PLL_TYPE_QPLL1 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_TX, ChId)) || \ + (XVPHY_PLL_TYPE_PLL0 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_TX, ChId)) || \ + (XVPHY_PLL_TYPE_PLL1 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_TX, ChId))) +#define XVphy_IsRxUsingQpll(InstancePtr, QuadId, ChId) \ + ((XVPHY_PLL_TYPE_QPLL == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_RX, ChId)) || \ + (XVPHY_PLL_TYPE_QPLL0 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_RX, ChId)) || \ + (XVPHY_PLL_TYPE_QPLL1 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_RX, ChId)) || \ + (XVPHY_PLL_TYPE_PLL0 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_RX, ChId)) || \ + (XVPHY_PLL_TYPE_PLL1 == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_RX, ChId))) +#define XVphy_IsTxUsingCpll(InstancePtr, QuadId, ChId) \ + (XVPHY_PLL_TYPE_CPLL == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_TX, ChId)) +#define XVphy_IsRxUsingCpll(InstancePtr, QuadId, ChId) \ + (XVPHY_PLL_TYPE_CPLL == \ + XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_RX, ChId)) + +#define XVPHY_GTXE2 1 +#define XVPHY_GTHE2 2 +#define XVPHY_GTPE2 3 +#define XVPHY_GTHE3 4 +#define XVPHY_GTHE4 5 + +#endif /* XVPHY_H_ */ diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_gt.h b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_gt.h new file mode 100644 index 00000000000000..5c18a8ee76c117 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_gt.h @@ -0,0 +1,117 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_gt.h + * + * The Xilinx Video PHY (VPHY) driver. This driver supports the Xilinx Video PHY + * IP core. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 10/19/15 Initial release. + * 1.1 gm 02/01/16 Added Gtpe2Config and Gtpe4Config variables. + * 1.4 gm 29/11/16 Added preprocessor directives for sw footprint reduction + * Changed TX reconfig hook from TxPllRefClkDiv1Reconfig to + * TxChReconfig + * Fixed c++ compiler warnings + * Added xcvr adaptor functions for C++ compilations + * </pre> + * +*******************************************************************************/ + +#ifndef XVPHY_GT_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XVPHY_GT_H_ + +/******************************* Include Files ********************************/ + +#include "xvphy.h" +#include "xvphy_i.h" +#include "xil_assert.h" + +/****************************** Type Definitions ******************************/ + +typedef struct { + const u8 *M; + const u8 *N1; + const u8 *N2; + const u8 *D; +} XVphy_GtPllDivs; + +typedef struct XVphy_GtConfigS { + u32 (*CfgSetCdr)(XVphy *, u8, XVphy_ChannelId); + u32 (*CheckPllOpRange)(XVphy *, u8, XVphy_ChannelId, u64); + u32 (*OutDivChReconfig)(XVphy *, u8, XVphy_ChannelId, + XVphy_DirectionType); + u32 (*ClkChReconfig)(XVphy *, u8, XVphy_ChannelId); + u32 (*ClkCmnReconfig)(XVphy *, u8, XVphy_ChannelId); + u32 (*RxChReconfig)(XVphy *, u8, XVphy_ChannelId); + u32 (*TxChReconfig)(XVphy *, u8, XVphy_ChannelId); + + XVphy_GtPllDivs CpllDivs; + XVphy_GtPllDivs QpllDivs; +} XVphy_GtConfig; + +/******************* Macros (Inline Functions) Definitions ********************/ +#ifdef __cplusplus +u32 XVphy_CfgSetCdr(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +u32 XVphy_CheckPllOpRange(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u64 PllClkOutFreqHz); +u32 XVphy_OutDivChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir); +u32 XVphy_ClkChReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +u32 XVphy_ClkCmnReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +u32 XVphy_RxChReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +u32 XVphy_TxChReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +#else +#define XVphy_CfgSetCdr(Ip, ...) \ + ((Ip)->GtAdaptor->CfgSetCdr(Ip, __VA_ARGS__)) +#define XVphy_CheckPllOpRange(Ip, ...) \ + ((Ip)->GtAdaptor->CheckPllOpRange(Ip, __VA_ARGS__)) +#define XVphy_OutDivChReconfig(Ip, ...) \ + ((Ip)->GtAdaptor->OutDivChReconfig(Ip, __VA_ARGS__)) +#define XVphy_ClkChReconfig(Ip, ...) \ + ((Ip)->GtAdaptor->ClkChReconfig(Ip, __VA_ARGS__)) +#define XVphy_ClkCmnReconfig(Ip, ...) \ + ((Ip)->GtAdaptor->ClkCmnReconfig(Ip, __VA_ARGS__)) +#define XVphy_RxChReconfig(Ip, ...) \ + ((Ip)->GtAdaptor->RxChReconfig(Ip, __VA_ARGS__)) +#define XVphy_TxChReconfig(Ip, ...) \ + ((Ip)->GtAdaptor->TxChReconfig(Ip, __VA_ARGS__)) +#endif + +/*************************** Variable Declarations ****************************/ + +#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTXE2) +extern const XVphy_GtConfig Gtxe2Config; +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE2) +extern const XVphy_GtConfig Gthe2Config; +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTPE2) +extern const XVphy_GtConfig Gtpe2Config; +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE3) +extern const XVphy_GtConfig Gthe3Config; +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE4) +extern const XVphy_GtConfig Gthe4Config; +#endif + +#endif /* XVPHY_GT_H_ */ diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_gthe4.c b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_gthe4.c new file mode 100644 index 00000000000000..ac18b77cde9660 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_gthe4.c @@ -0,0 +1,1277 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_gthe4.c + * + * Contains a minimal set of functions for the XVphy driver that allow access + * to all of the Video PHY core's functionality. See xvphy.h for a detailed + * description of the driver. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 10/19/15 Initial release. + * 1.1 gm 03/18/16 Added XVphy_Gthe4RxPllRefClkDiv1Reconfig function + * Added XVphy_Gthe4TxChReconfig function + * Corrected RXCDRCFG2 values + * 1.2 gm 08/26/16 Suppressed warning messages due to unused arguments + * 1.4 gm 29/11/16 Added preprocessor directives for sw footprint reduction + * Changed TX reconfig hook from TxPllRefClkDiv1Reconfig to + * TxChReconfig + * Added TX datawidth dynamic reconfiguration + * Added N2=8 divider for CPLL for DP + * Added CPLL_CFGx reconfiguration in + * XVphy_Gthe4ClkChReconfig API + * Corrected the default return value of DRP encoding + * APIs to prevent overwritting the reserved bits + * </pre> + * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xvphy_gt.h" +#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE4) +#include "xstatus.h" + +/**************************** Function Prototypes *****************************/ + +static u8 XVphy_MToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); +static u16 XVphy_NToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u8 NId); +static u8 XVphy_DToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir); +static u8 XVphy_DrpEncodeQpllMCpllMN2(u8 AttrEncode); +static u8 XVphy_DrpEncodeCpllN1(u8 AttrEncode); +static u8 XVphy_DrpEncodeCpllTxRxD(u8 AttrEncode); +static u16 XVphy_DrpEncodeQpllN(u8 AttrEncode); +static u8 Xvphy_DrpEncodeDataWidth(u8 AttrEncode); +static u8 Xvphy_DrpEncodeIntDataWidth(u8 AttrEncode); +static u16 XVphy_DrpEncodeClk25(u32 RefClkFreqHz); + +u32 XVphy_Gthe4CfgSetCdr(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +u32 XVphy_Gthe4CheckPllOpRange(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u64 PllClkOutFreqHz); +u32 XVphy_Gthe4OutDivChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir); +u32 XVphy_Gthe4ClkChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); +u32 XVphy_Gthe4ClkCmnReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId CmnId); +u32 XVphy_Gthe4RxChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); +u32 XVphy_Gthe4TxChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); +u32 XVphy_Gthe4TxPllRefClkDiv1Reconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); +u32 XVphy_Gthe4RxPllRefClkDiv1Reconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); + +/************************** Constant Definitions ******************************/ + +/* DRP register space. */ +#define XVPHY_DRP_RXCDR_CFG(n) (0x0E + n) +#define XVPHY_DRP_RXCDR_CFG_GEN3(n) (0xA2 + n) +#define XVPHY_DRP_RXCDR_CFG_GEN4(n) (0x119 + n) + +#define XVPHY_DRP_CPLL_FBDIV 0x28 +#define XVPHY_DRP_CPLL_REFCLK_DIV 0x2A +#define XVPHY_DRP_RXOUT_DIV 0x63 +#define XVPHY_DRP_RXCLK25 0x6D +#define XVPHY_DRP_TXCLK25 0x7A +#define XVPHY_DRP_TXOUT_DIV 0x7C +#define XVPHY_DRP_QPLL1_FBDIV 0x94 +#define XVPHY_DRP_QPLL1_REFCLK_DIV 0x98 +#define XVPHY_DRP_RXCDR_CFG_WORD0 0x0E +#define XVPHY_DRP_RXCDR_CFG_WORD1 0x0F +#define XVPHY_DRP_RXCDR_CFG_WORD2 0x10 +#define XVPHY_DRP_RXCDR_CFG_WORD3 0x11 +#define XVPHY_DRP_RXCDR_CFG_WORD4 0x12 + +/* PLL operating ranges. */ +#define XVPHY_QPLL0_MIN 9800000000LL +#define XVPHY_QPLL0_MAX 16300000000LL +#define XVPHY_QPLL1_MIN 8000000000LL +#define XVPHY_QPLL1_MAX 13000000000LL +#define XVPHY_CPLL_MIN 2000000000LL +#define XVPHY_CPLL_MAX 6250000000LL + +const u8 Gthe4CpllDivsM[] = {1, 2, 0}; +const u8 Gthe4CpllDivsN1[] = {4, 5, 0}; +#if (XPAR_VPHY_0_TX_PROTOCOL == 0 || XPAR_VPHY_0_RX_PROTOCOL == 0) +const u8 Gthe4CpllDivsN2[] = {1, 2, 3, 4, 5, 8, 0}; +#else +const u8 Gthe4CpllDivsN2[] = {1, 2, 3, 4, 5, 0}; +#endif +const u8 Gthe4CpllDivsD[] = {1, 2, 4, 8, 0}; + +const u8 Gthe4QpllDivsM[] = {4, 3, 2, 1, 0}; +const u8 Gthe4QpllDivsN1[] = {16, 20, 32, 40, 60, 64, 66, 75, 80, 84, 90, + 96, 100, 112, 120, 125, 150, 160, 0}; +const u8 Gthe4QpllDivsN2[] = {1, 0}; +const u8 Gthe4QpllDivsD[] = {16, 8, 4, 2, 1, 0}; + +const XVphy_GtConfig Gthe4Config = { + .CfgSetCdr = XVphy_Gthe4CfgSetCdr, + .CheckPllOpRange = XVphy_Gthe4CheckPllOpRange, + .OutDivChReconfig = XVphy_Gthe4OutDivChReconfig, + .ClkChReconfig = XVphy_Gthe4ClkChReconfig, + .ClkCmnReconfig = XVphy_Gthe4ClkCmnReconfig, + .RxChReconfig = XVphy_Gthe4RxChReconfig, + .TxChReconfig = XVphy_Gthe4TxChReconfig, + + .CpllDivs = { + .M = Gthe4CpllDivsM, + .N1 = Gthe4CpllDivsN1, + .N2 = Gthe4CpllDivsN2, + .D = Gthe4CpllDivsD, + }, + .QpllDivs = { + .M = Gthe4QpllDivsM, + .N1 = Gthe4QpllDivsN1, + .N2 = Gthe4QpllDivsN2, + .D = Gthe4QpllDivsD, + }, +}; + +/**************************** Function Definitions ****************************/ + +/*****************************************************************************/ +/** +* This function will set the clock and data recovery (CDR) values for a given +* channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe4CfgSetCdr(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + u32 PllClkInFreqHz; + XVphy_Channel *ChPtr; + u32 Status = XST_SUCCESS; + + /* Set CDR values only for CPLLs. */ + if ((ChId < XVPHY_CHANNEL_ID_CH1) || (ChId > XVPHY_CHANNEL_ID_CH4)) { + return XST_FAILURE; + } + + /* This is DP specific. */ + ChPtr = &InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]; + + ChPtr->PllParams.Cdr[0] = 0x0000; + ChPtr->PllParams.Cdr[1] = 0x0000; + ChPtr->PllParams.Cdr[3] = 0x0000; + ChPtr->PllParams.Cdr[4] = 0x0000; + if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_DP) { + PllClkInFreqHz = XVphy_GetQuadRefClkFreq(InstancePtr, QuadId, + ChPtr->CpllRefClkSel); + if (PllClkInFreqHz == 270000000) { + ChPtr->PllParams.Cdr[2] = 0x01B4; + } + else if (PllClkInFreqHz == 135000000) { + ChPtr->PllParams.Cdr[2] = 0x01C4; + } + /* RBR does not use DP159 forwarded clock and expects 162MHz. */ + else { + ChPtr->PllParams.Cdr[2] = 0x01A3; + } + } + else if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + /* RxOutDiv = 1 => Cdr[2] = 0x0269 + * RxOutDiv = 2 => Cdr[2] = 0x0259 + * RxOutDiv = 4 => Cdr[2] = 0x0249 + * RxOutDiv = 8 => Cdr[2] = 0x0239 + * RxOutDiv = 16 => Cdr[2] = 0x0229 */ + ChPtr->PllParams.Cdr[2] = 0x0269; + while (ChPtr->RxOutDiv >>= 1) { + ChPtr->PllParams.Cdr[2] -= 0x10; + } + /* Restore RxOutDiv. */ + ChPtr->RxOutDiv = 1 << ((0x0269 - ChPtr->PllParams.Cdr[2]) >> 4); + } + else { + Status = XST_FAILURE; + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function will check if a given PLL output frequency is within the +* operating range of the PLL for the GT type. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param PllClkOutFreqHz is the frequency to check. +* +* @return +* - XST_SUCCESS if the frequency resides within the PLL's range. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe4CheckPllOpRange(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u64 PllClkOutFreqHz) +{ + u32 Status = XST_FAILURE; + + /* Suppress Warning Messages */ + InstancePtr = InstancePtr; + QuadId = QuadId; + + if (((ChId == XVPHY_CHANNEL_ID_CMN0) && + (XVPHY_QPLL0_MIN <= PllClkOutFreqHz) && + (PllClkOutFreqHz <= XVPHY_QPLL0_MAX)) || + ((ChId == XVPHY_CHANNEL_ID_CMN1) && + (XVPHY_QPLL1_MIN <= PllClkOutFreqHz) && + (PllClkOutFreqHz <= XVPHY_QPLL1_MAX)) || + ((ChId >= XVPHY_CHANNEL_ID_CH1) && + (ChId <= XVPHY_CHANNEL_ID_CH4) && + (XVPHY_CPLL_MIN <= PllClkOutFreqHz) && + (PllClkOutFreqHz <= XVPHY_CPLL_MAX))) { + Status = XST_SUCCESS; + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function will set the output divider logic for a given channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for RX or TX. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe4OutDivChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir) +{ + u16 DrpVal; + u16 WriteVal; + + if (Dir == XVPHY_DIR_RX) { + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x63); + /* Mask out RX_OUT_DIV. */ + DrpVal &= ~0x07; + /* Set RX_OUT_DIV. */ + WriteVal = (XVphy_DToDrpEncoding(InstancePtr, QuadId, ChId, + XVPHY_DIR_RX) & 0x7); + DrpVal |= WriteVal; + /* Write new DRP register value for RX dividers. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x63, DrpVal); + } + else { + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x7C); + /* Mask out TX_OUT_DIV. */ + DrpVal &= ~0x700; + /* Set TX_OUT_DIV. */ + WriteVal = (XVphy_DToDrpEncoding(InstancePtr, QuadId, ChId, + XVPHY_DIR_TX) & 0x7); + DrpVal |= (WriteVal << 8); + /* Write new DRP register value for RX dividers. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x7C, DrpVal); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will configure the channel clock settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe4ClkChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId) +{ + u16 DrpVal; + u16 WriteVal; + u32 CpllxVcoRateMHz; + + /* Obtain current DRP register value for PLL dividers. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x28); + /* Mask out clock divider bits. */ + DrpVal &= ~(0xFF80); + /* Set CPLL_FBDIV. */ + WriteVal = (XVphy_NToDrpEncoding(InstancePtr, QuadId, ChId, 2) & 0xFF); + DrpVal |= (WriteVal << 8); + /* Set CPLL_FBDIV_45. */ + WriteVal = (XVphy_NToDrpEncoding(InstancePtr, QuadId, ChId, 1) & 0x1); + DrpVal |= (WriteVal << 7); + /* Write new DRP register value for PLL dividers. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x28, DrpVal); + + /* Write CPLL Ref Clk Div. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x2A); + /* Mask out clock divider bits. */ + DrpVal &= ~(0xF800); + /* Set CPLL_REFCLKDIV. */ + WriteVal = (XVphy_MToDrpEncoding(InstancePtr, QuadId, ChId) & 0x1F); + DrpVal |= (WriteVal << 11); + /* Write new DRP register value for PLL dividers. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x2A, DrpVal); + + CpllxVcoRateMHz = XVphy_GetPllVcoFreqHz(InstancePtr, QuadId, ChId, + XVphy_IsTxUsingCpll(InstancePtr, QuadId, ChId) ? + XVPHY_DIR_TX : XVPHY_DIR_RX) / 1000000; + + /* CPLL_CFG0 */ + if (CpllxVcoRateMHz <= 3000) { + DrpVal = 0x01FA; + } + else if (CpllxVcoRateMHz <= 4250) { + DrpVal = 0x0FFA; + } + else { + DrpVal = 0x03FE; + } + /* Write new DRP register value for CPLL_CFG0. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0xCB, DrpVal); + + /* CPLL_CFG1 */ + if (CpllxVcoRateMHz <= 3000) { + DrpVal = 0x0023; + } + else { + DrpVal = 0x0021; + } + /* Write new DRP register value for CPLL_CFG1. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0xCC, DrpVal); + + /* CPLL_CFG2 */ + if (CpllxVcoRateMHz <= 3000) { + DrpVal = 0x0002; + } + else if (CpllxVcoRateMHz <= 4250) { + DrpVal = 0x0202; + } + else { + DrpVal = 0x0203; + } + /* Write new DRP register value for CPLL_CFG2. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0xBC, DrpVal); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will configure the common channel clock settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param CmnId is the common channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe4ClkCmnReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId CmnId) +{ + u16 DrpVal; + u16 WriteVal; + u32 QpllxVcoRateMHz; + u32 QpllxClkOutMHz; + + /* Obtain current DRP register value for QPLLx_FBDIV. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x14 : 0x94); + /* Mask out QPLLx_FBDIV. */ + DrpVal &= ~(0xFF); + /* Set QPLLx_FBDIV. */ + WriteVal = (XVphy_NToDrpEncoding(InstancePtr, QuadId, CmnId, 0) & 0xFF); + DrpVal |= WriteVal; + /* Write new DRP register value for QPLLx_FBDIV. */ + XVphy_DrpWrite(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x14 : 0x94, DrpVal); + + /* Obtain current DRP register value for QPLLx_REFCLK_DIV. */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x18 : 0x98); + /* Mask out QPLLx_REFCLK_DIV. */ + DrpVal &= ~(0xF80); + /* Set QPLLx_REFCLK_DIV. */ + WriteVal = (XVphy_MToDrpEncoding(InstancePtr, QuadId, CmnId) & 0x1F); + DrpVal |= (WriteVal << 7); + /* Write new DRP register value for QPLLx_REFCLK_DIV. */ + XVphy_DrpWrite(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x18 : 0x98, DrpVal); + + if ((InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) || + (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI)) { + + QpllxVcoRateMHz = XVphy_GetPllVcoFreqHz(InstancePtr, QuadId, CmnId, + XVphy_IsTxUsingQpll(InstancePtr, QuadId, CmnId) ? + XVPHY_DIR_TX : XVPHY_DIR_RX) / 1000000; + QpllxClkOutMHz = QpllxVcoRateMHz / 2; + + /* PPFx_CFG */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x0D : 0x8D); + DrpVal &= ~(0x0FC0); + /* PPF_MUX_CRNT_CTRL0 */ + if (QpllxVcoRateMHz >= 15000) { + DrpVal |= 0x0E00; + } + else if (QpllxVcoRateMHz >= 11000) { + DrpVal |= 0x0800; + } + else if (QpllxVcoRateMHz >= 7000) { + DrpVal |= 0x0600; + } + else { + DrpVal |= 0x0400; + } + /* PPF_MUX_TERM_CTRL0 */ + if (QpllxVcoRateMHz >= 13000) { + DrpVal |= 0x0100; + } + else { + DrpVal |= 0x0000; + } + /* Write new DRP register value for PPFx_CFG. */ + XVphy_DrpWrite(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x0D : 0x8D, DrpVal); + + /* QPLLx_CP */ + if (InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.NFbDiv <= 40) { + DrpVal = 0x007F; + } + else { + DrpVal = 0x03FF; + } + /* Write new DRP register value for QPLLx_CP. */ + XVphy_DrpWrite(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x16 : 0x96, DrpVal); + + /* QPLLx_LPF */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x19 : 0x99); + DrpVal &= ~(0x0003); + if (InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.NFbDiv <= 40) { + DrpVal |= 0x3; + } + else { + DrpVal |= 0x1; + } + /* Write new DRP register value for QPLLx_LPF. */ + XVphy_DrpWrite(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x19 : 0x99, DrpVal); + + /* QPLLx_CFG4 */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x30 : 0xB0); + DrpVal &= ~(0x00E7); + /* Q_TERM_CLK */ + if (QpllxClkOutMHz >= 7500) { + DrpVal |= 0x2 << 5; + } + else if (QpllxClkOutMHz >= 3500) { + DrpVal |= 0x0 << 5; + } + else { + DrpVal |= 0x6 << 5; + } + /* Q_DCRNT_CLK */ + if (QpllxClkOutMHz >= 7500) { + DrpVal |= 0x5; + } + else if (QpllxClkOutMHz >= 5500) { + DrpVal |= 0x4; + } + else { + DrpVal |= 0x3; + } + /* Write new DRP register value for QPLLx_CFG4. */ + XVphy_DrpWrite(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMN, + (CmnId == XVPHY_CHANNEL_ID_CMN0) ? 0x30 : 0xB0, DrpVal); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will configure the channel's RX settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe4RxChReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + XVphy_Channel *ChPtr; + u16 DrpVal; + u16 WriteVal; + u8 CfgIndex; + XVphy_ChannelId ChIdPll; + XVphy_PllType PllType; + u32 PllxVcoRateMHz; + u32 PllxClkOutMHz; + u32 PllxClkOutDiv; + + ChPtr = &InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]; + + /* RXCDR_CFG(CfgIndex) */ + for (CfgIndex = 0; CfgIndex < 5; CfgIndex++) { + DrpVal = ChPtr->PllParams.Cdr[CfgIndex]; + if (!DrpVal) { + /* Don't modify RX_CDR configuration. */ + continue; + } + XVphy_DrpWrite(InstancePtr, QuadId, ChId, + XVPHY_DRP_RXCDR_CFG(CfgIndex), DrpVal); + if (CfgIndex == 2) { + XVphy_DrpWrite(InstancePtr, QuadId, ChId, + XVPHY_DRP_RXCDR_CFG_GEN3(CfgIndex), DrpVal); + XVphy_DrpWrite(InstancePtr, QuadId, ChId, + XVPHY_DRP_RXCDR_CFG_GEN4(CfgIndex), DrpVal); + + } + } + + if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + /* RX_INT_DATAWIDTH */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x66); + DrpVal &= ~(0x3); + WriteVal = (Xvphy_DrpEncodeIntDataWidth(ChPtr->RxIntDataWidth) & 0x3); + DrpVal |= WriteVal; + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x66, DrpVal); + + /* RX_DATA_WIDTH */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x03); + DrpVal &= ~(0x1E0); + WriteVal = (Xvphy_DrpEncodeDataWidth(ChPtr->RxDataWidth) & 0xF); + WriteVal <<= 5; + DrpVal |= WriteVal; + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x03, DrpVal); + + /* Determine PLL type. */ + PllType = XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_RX, ChId); + /* Determine which channel(s) to operate on. */ + switch (PllType) { + case XVPHY_PLL_TYPE_QPLL: + case XVPHY_PLL_TYPE_QPLL0: + case XVPHY_PLL_TYPE_PLL0: + ChIdPll = XVPHY_CHANNEL_ID_CMN0; + PllxClkOutDiv = 2; + break; + case XVPHY_PLL_TYPE_QPLL1: + case XVPHY_PLL_TYPE_PLL1: + ChIdPll = XVPHY_CHANNEL_ID_CMN1; + PllxClkOutDiv = 2; + break; + default: + ChIdPll = ChId; + PllxClkOutDiv = 1; + break; + } + + PllxVcoRateMHz = XVphy_GetPllVcoFreqHz(InstancePtr, QuadId, ChIdPll, + XVPHY_DIR_RX) / 1000000; + PllxClkOutMHz = PllxVcoRateMHz / PllxClkOutDiv; + + /* CH_HSPMUX_RX */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x116); + DrpVal &= ~(0x00FF); + if (PllxClkOutMHz >= 7500) { + DrpVal |= 0x68; + } + else if (PllxClkOutMHz >= 5500) { + DrpVal |= 0x44; + } + else if (PllxClkOutMHz >= 3500) { + DrpVal |= 0x24; + } + else { + DrpVal |= 0x3C; + } + /* Write new DRP register value for CH_HSPMUX_RX. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x116, DrpVal); + + /* PREIQ_FREQ_BST */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0xFB); + DrpVal &= ~(0x0030); + if (PllxClkOutMHz > 14110) { + DrpVal |= 3 << 4; + } + else if (PllxClkOutMHz >= 14000) { + DrpVal |= 2 << 4; /* LPM Mode */ + } + else if (PllxClkOutMHz >= 10000) { + DrpVal |= 2 << 4; + } + else if (PllxClkOutMHz >= 6000) { + DrpVal |= 1 << 4; + } + /* Write new DRP register value for PREIQ_FREQ_BST. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0xFB, DrpVal); + + /* RXPI_CFG0 */ + if (PllxClkOutMHz >= 8500) { + DrpVal = 0x0004; + } + else if (PllxClkOutMHz >= 7500) { + DrpVal = 0x0104; + } + else if (PllxClkOutMHz >= 6500) { + DrpVal = 0x0204; + } + else if (PllxClkOutMHz >= 5500) { + DrpVal = 0x2304; + } + else if (PllxClkOutMHz >= 4500) { + DrpVal = 0x0002; + } + else if (PllxClkOutMHz >= 3500) { + DrpVal = 0x2202; + } + else if (PllxClkOutMHz >= 3000) { + DrpVal = 0x0000; + } + else if (PllxClkOutMHz >= 2500) { + DrpVal = 0x1200; + } + else { + DrpVal = 0x3300; + } + /* Write new DRP register value for RXPI_CFG0. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x9D, DrpVal); + + /* RXPI_CFG1 */ + if (PllxClkOutMHz >= 5500) { + DrpVal = 0x0000; + } + else if (PllxClkOutMHz >= 4500) { + DrpVal = 0x0015; + } + else if (PllxClkOutMHz >= 3500) { + DrpVal = 0x0045; + } + else if (PllxClkOutMHz >= 2000) { + DrpVal = 0x00FD; + } + else { + DrpVal = 0x00FF; + } + /* Write new DRP register value for RXPI_CFG1. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x100, DrpVal); + } + + XVphy_Gthe4RxPllRefClkDiv1Reconfig(InstancePtr, QuadId, ChId); + + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* This function will configure the channel's TX settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe4TxChReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + XVphy_Channel *ChPtr; + u32 ReturnVal; + u16 DrpVal; + u16 WriteVal; + XVphy_ChannelId ChIdPll; + XVphy_PllType PllType; + u32 PllxVcoRateMHz; + u32 PllxClkOutMHz; + u32 PllxClkOutDiv; + + ReturnVal = XVphy_Gthe4TxPllRefClkDiv1Reconfig(InstancePtr, QuadId, ChId); + if (InstancePtr->Config.TxProtocol != XVPHY_PROTOCOL_HDMI) { + return ReturnVal; + } + + /* Determine PLL type. */ + PllType = XVphy_GetPllType(InstancePtr, QuadId, XVPHY_DIR_TX, ChId); + /* Determine which channel(s) to operate on. */ + switch (PllType) { + case XVPHY_PLL_TYPE_QPLL: + case XVPHY_PLL_TYPE_QPLL0: + case XVPHY_PLL_TYPE_PLL0: + ChIdPll = XVPHY_CHANNEL_ID_CMN0; + PllxClkOutDiv = 2; + break; + case XVPHY_PLL_TYPE_QPLL1: + case XVPHY_PLL_TYPE_PLL1: + ChIdPll = XVPHY_CHANNEL_ID_CMN1; + PllxClkOutDiv = 2; + break; + default: + ChIdPll = ChId; + PllxClkOutDiv = 1; + break; + } + + if (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) { + + ChPtr = &InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]; + /* TX_INT_DATAWIDTH */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x85); + DrpVal &= ~(0x3 << 10); + WriteVal = ((Xvphy_DrpEncodeIntDataWidth(ChPtr-> + TxIntDataWidth) & 0x3) << 10); + DrpVal |= WriteVal; + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x85, DrpVal); + + /* TX_DATA_WIDTH */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x7A); + DrpVal &= ~(0xF); + WriteVal = (Xvphy_DrpEncodeDataWidth(ChPtr->TxDataWidth) & 0xF); + DrpVal |= WriteVal; + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x7A, DrpVal); + + /* TX_PROGDIV_CFG */ + /* XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x3E, 0xE062); */ + + PllxVcoRateMHz = XVphy_GetPllVcoFreqHz(InstancePtr, QuadId, ChIdPll, + XVPHY_DIR_TX) / 1000000; + PllxClkOutMHz = PllxVcoRateMHz / PllxClkOutDiv; + + /* TXPI_CFG */ + if (PllxClkOutMHz >= 5500) { + DrpVal = 0x0000; + } + else if (PllxClkOutMHz >= 3500) { + DrpVal = 0x0054; + } + else { + DrpVal = 0x03DF; + } + /* Write new DRP register value for TXPI_CFG. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0xFF, DrpVal); + + /* TXPI_CFG3 */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x9C); + DrpVal &= ~(0x0040); + if (PllxClkOutMHz < 7500 && PllxClkOutMHz >= 5500) { + DrpVal |= 1 << 6; + } + /* Write new DRP register value for TXPI_CFG3. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x9C, DrpVal); + + /* TX_PI_BIASSET */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0xFB); + DrpVal &= ~(0x0006); + if (PllxClkOutMHz >= 7500) { + DrpVal |= 3 << 1; + } + else if (PllxClkOutMHz >= 5500) { + DrpVal |= 2 << 1; + } + else if (PllxClkOutMHz >= 3500) { + DrpVal |= 1 << 1; + } + /* Write new DRP register value for TX_PI_BIASSET. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0xFB, DrpVal); + + /* CH_HSPMUX_TX */ + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, 0x116); + DrpVal &= ~(0xFF00); + if (PllxClkOutMHz >= 7500) { + DrpVal |= 0x68 << 8; + } + else if (PllxClkOutMHz >= 5500) { + DrpVal |= 0x44 << 8; + } + else if (PllxClkOutMHz >= 3500) { + DrpVal |= 0x24 << 8; + } + else { + DrpVal |= 0x3C << 8; + } + /* Write new DRP register value for CH_HSPMUX_TX. */ + XVphy_DrpWrite(InstancePtr, QuadId, ChId, 0x116, DrpVal); + } + return (XST_SUCCESS); +} + +/*****************************************************************************/ +/** +* This function will configure the channel's TX CLKDIV1 settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe4TxPllRefClkDiv1Reconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId) +{ + u16 DrpVal; + u32 TxRefClkHz; + XVphy_Channel *PllPtr = &InstancePtr->Quads[QuadId]. + Plls[XVPHY_CH2IDX(ChId)]; + + if (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) { + TxRefClkHz = InstancePtr->HdmiTxRefClkHz; + } + else { + TxRefClkHz = XVphy_GetQuadRefClkFreq(InstancePtr, QuadId, + PllPtr->PllRefClkSel); + } + + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, XVPHY_DRP_TXCLK25); + DrpVal &= ~(0xF800); + DrpVal |= XVphy_DrpEncodeClk25(TxRefClkHz) << 11; + + return XVphy_DrpWrite(InstancePtr, QuadId, ChId, XVPHY_DRP_TXCLK25, + DrpVal); +} + +/*****************************************************************************/ +/** +* This function will configure the channel's RX CLKDIV1 settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_Gthe4RxPllRefClkDiv1Reconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId) +{ + u16 DrpVal; + u32 RxRefClkHz; + XVphy_Channel *PllPtr = &InstancePtr->Quads[QuadId]. + Plls[XVPHY_CH2IDX(ChId)]; + + if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + RxRefClkHz = InstancePtr->HdmiRxRefClkHz; + } + else { + RxRefClkHz = XVphy_GetQuadRefClkFreq(InstancePtr, QuadId, + PllPtr->PllRefClkSel); + } + + DrpVal = XVphy_DrpRead(InstancePtr, QuadId, ChId, XVPHY_DRP_RXCLK25); + DrpVal &= ~(0x00F8); + DrpVal |= XVphy_DrpEncodeClk25(RxRefClkHz) << 3; + + return XVphy_DrpWrite(InstancePtr, QuadId, ChId, XVPHY_DRP_RXCLK25, + DrpVal); +} + +/*****************************************************************************/ +/** +* This function will translate the configured M value to DRP encoding. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return The DRP encoding for M. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_MToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId) +{ + u8 MRefClkDiv; + u8 DrpEncode; + + if ((ChId >= XVPHY_CHANNEL_ID_CH1) && (ChId <= XVPHY_CHANNEL_ID_CH4)) { + MRefClkDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)] + .PllParams.MRefClkDiv; + } + else if ((ChId == XVPHY_CHANNEL_ID_CMN0) || + (ChId == XVPHY_CHANNEL_ID_CMN1)) { + MRefClkDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)] + .PllParams.MRefClkDiv; + } + else { + MRefClkDiv = 0; + } + + DrpEncode = XVphy_DrpEncodeQpllMCpllMN2(MRefClkDiv); + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured D value to DRP encoding. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for RX or TX. +* +* @return The DRP encoding for D. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_DToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir) +{ + u8 OutDiv; + u8 DrpEncode; + + OutDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]. + OutDiv[Dir]; + + DrpEncode = XVphy_DrpEncodeCpllTxRxD(OutDiv); + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured N1/N2 value to DRP encoding. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param NId specified to operate on N1 (if == 1) or N2 (if == 2). +* +* @return The DRP encoding for N1/N2. +* +* @note None. +* +******************************************************************************/ +static u16 XVphy_NToDrpEncoding(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u8 NId) +{ + u8 NFbDiv; + u16 DrpEncode; + + if ((ChId == XVPHY_CHANNEL_ID_CMN0) || + (ChId == XVPHY_CHANNEL_ID_CMN1)) { + NFbDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]. + PllParams.NFbDiv; + DrpEncode = XVphy_DrpEncodeQpllN(NFbDiv); + } + else if (NId == 1) { + NFbDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]. + PllParams.N1FbDiv; + DrpEncode = XVphy_DrpEncodeCpllN1(NFbDiv); + } + else { + NFbDiv = InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]. + PllParams.N2FbDiv; + DrpEncode = XVphy_DrpEncodeQpllMCpllMN2(NFbDiv); + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured QPLL's M or CPLL's M or N2 +* values to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the QPLL's M or CPLL's M or N2 values. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_DrpEncodeQpllMCpllMN2(u8 AttrEncode) +{ + u8 DrpEncode; + + switch (AttrEncode) { + case 1: + DrpEncode = 16; + break; + case 6: + DrpEncode = 5; + break; + case 10: + DrpEncode = 7; + break; + case 12: + DrpEncode = 13; + break; + case 20: + DrpEncode = 15; + break; + case 2: + case 3: + case 4: + case 5: + case 8: + case 16: + DrpEncode = (AttrEncode - 2); + break; + default: + DrpEncode = 0xF; + break; + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured CPLL's N1 value to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the CPLL's N1 value. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_DrpEncodeCpllN1(u8 AttrEncode) +{ + u8 DrpEncode; + + DrpEncode = (AttrEncode - 4) & 0x1; + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured CPLL's D values to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the CPLL's D value. +* +* @note None. +* +******************************************************************************/ +static u8 XVphy_DrpEncodeCpllTxRxD(u8 AttrEncode) +{ + u8 DrpEncode; + + switch (AttrEncode) { + case 1: + DrpEncode = 0; + break; + case 2: + DrpEncode = 1; + break; + case 4: + DrpEncode = 2; + break; + case 8: + DrpEncode = 3; + break; + case 16: + DrpEncode = 4; + break; + default: + DrpEncode = 0x4; + break; + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured QPLL's N value to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the QPLL's N value. +* +* @note None. +* +******************************************************************************/ +static u16 XVphy_DrpEncodeQpllN(u8 AttrEncode) +{ + u16 DrpEncode; + + if ((16 <= AttrEncode) && (AttrEncode <= 160)) { + DrpEncode = AttrEncode - 2; + } + else { + DrpEncode = 0xFF; + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured RXDATAWIDTH to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the RXDATAWIDTH value. +* +* @note None. +* +******************************************************************************/ +static u8 Xvphy_DrpEncodeDataWidth(u8 AttrEncode) +{ + u8 DrpEncode; + + switch (AttrEncode) { + case 16: + DrpEncode = 2; + break; + case 20: + DrpEncode = 3; + break; + case 32: + DrpEncode = 4; + break; + case 40: + DrpEncode = 5; + break; + case 64: + DrpEncode = 6; + break; + case 80: + DrpEncode = 7; + break; + case 128: + DrpEncode = 8; + break; + case 160: + DrpEncode = 9; + break; + default: + DrpEncode = 0xF; + break; + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured RXINTDATAWIDTH to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the RXINTDATAWIDTH value. +* +* @note None. +* +******************************************************************************/ +static u8 Xvphy_DrpEncodeIntDataWidth(u8 AttrEncode) +{ + u8 DrpEncode; + + switch (AttrEncode) { + case 2: + DrpEncode = 0; + break; + case 4: + DrpEncode = 1; + break; + default: + DrpEncode = 2; + break; + } + + return DrpEncode; +} + +/*****************************************************************************/ +/** +* This function will translate the configured CLK25 to DRP encoding. +* +* @param AttrEncode is the attribute to encode. +* +* @return The DRP encoding for the CLK25 value. +* +* @note None. +* +******************************************************************************/ +static u16 XVphy_DrpEncodeClk25(u32 RefClkFreqHz) +{ + u16 DrpEncode; + u32 RefClkFreqMHz = RefClkFreqHz / 1000000; + + DrpEncode = ((RefClkFreqMHz / 25) + + (((RefClkFreqMHz % 25) > 0) ? 1 : 0)) - 1; + + return (DrpEncode & 0x1F); +} +#endif diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_hdmi.c b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_hdmi.c new file mode 100644 index 00000000000000..145224026d7c3e --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_hdmi.c @@ -0,0 +1,2384 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_hdmi.c + * + * This file contains video PHY functionality specific to the HDMI protocol. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 gm 10/19/15 Initial release. + * 1.1 gm 02/01/16 Added GTPE2 and GTHE4 support. + * MG 03/08/16 Fixed issue in function XVphy_HdmiCfgCalcMmcmParam + * for single pixel calculation. + * 1.2 gm Added XVphy_HdmiMmcmStart and + * XVphy_HdmiMmcmWriteParameters functions + * Replaced xil_printf with log events + * Modified XVphy_DruGetRefClkFreqHz + * Suppressed warning messages due to unused arguments + * 1.3 gm 01/11/16 Added error message in XVphy_HdmiCpllParam when DRU is + * enabled and RX TMDS ratio is 1/40 + * Fixed rounding of DRU refclk frequency + * Fixed a bug in XVphy_SetHdmiRxParam to update the ChId + * when DRU is enabled + * 1.4 gm 29/11/16 Added preprocessor directives for sw footprint reduction + * Added TX datawidth dynamic reconfiguration + * Incorporated AXIlite Freq auto extraction + * Added extra routine for 2/4 byte tranceiver modes + * Added logging and register access for ERR_IRQ impl + * Removed XVphy_HdmiMmcmStart API + * Fixed c++ compiler warnings + * </pre> + * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#if defined (XPAR_XV_HDMITX_0_DEVICE_ID) || defined (XPAR_XV_HDMIRX_0_DEVICE_ID) +#include "xstatus.h" +#include "xvphy.h" +#include "xvphy_i.h" +#include "xvphy_hdmi.h" + +/****************************** Type Definitions ******************************/ + +typedef struct { + u64 DruLineRate; + u16 PllScale; + u32 Qpll0RefClkMin; + u32 Qpll1RefClkMin; + u32 CpllRefClkMin; + u16 TxMmcmScale; + u32 TxMmcmFvcoMin; + u32 TxMmcmFvcoMax; + u16 RxMmcmScale; + u32 RxMmcmFvcoMin; + u32 RxMmcmFvcoMax; +} XVphy_GtHdmiChars; + +/**************************** Function Prototypes *****************************/ + +extern void XVphy_Ch2Ids(XVphy *InstancePtr, XVphy_ChannelId ChId, + u8 *Id0, u8 *Id1); +static const XVphy_GtHdmiChars *GetGtHdmiPtr(XVphy *InstancePtr); +static void XVphy_HdmiSetSystemClockSelection(XVphy *InstancePtr, u8 QuadId); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function initializes the Video PHY for HDMI. + * + * @param InstancePtr is a pointer to the XVphy instance. + * @param CfgPtr is a pointer to the configuration structure that will + * be used to copy the settings from. + * @param SystemFrequency is the system frequency for the HDMI logic + * to be based on. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +u32 XVphy_HdmiInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_Config *CfgPtr, + u32 SystemFrequency) +{ + u8 Id, Id0, Id1; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CfgPtr != NULL); + + /* Init done. */ + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_INIT, 0); + + /* Setup the instance. */ + XVphy_CfgInitialize(InstancePtr, CfgPtr, CfgPtr->BaseAddr); + + /* Set default. */ + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_IDLE; + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)].RxState = + XVPHY_GT_STATE_IDLE; + //Initialize Transceiver Width values + if (InstancePtr->Config.TransceiverWidth == 2) { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + TxDataWidth = 20; + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + TxIntDataWidth = 2; + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + RxDataWidth = 20; + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + RxIntDataWidth = 2; + } + else { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + TxDataWidth = 40; + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + TxIntDataWidth = 4; + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + RxDataWidth = 40; + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + RxIntDataWidth = 4; + } + } + /* Interrupt Disable. */ + XVphy_IntrDisable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_TXRESET_DONE); + XVphy_IntrDisable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_RXRESET_DONE); + XVphy_IntrDisable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_CPLL_LOCK); + XVphy_IntrDisable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_QPLL0_LOCK); + XVphy_IntrDisable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_TXALIGN_DONE); + XVphy_IntrDisable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_QPLL1_LOCK); + XVphy_IntrDisable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE); + XVphy_IntrDisable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE); + XVphy_IntrDisable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT); + XVphy_IntrDisable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); + + /* Setup HDMI interrupt handler callback*/ + XVphy_HdmiIntrHandlerCallbackInit(InstancePtr); + + /* Configure clock detector. */ + XVphy_ClkDetEnable(InstancePtr, FALSE); + XVphy_ClkDetSetFreqTimeout(InstancePtr, SystemFrequency); + XVphy_ClkDetSetFreqLockThreshold(InstancePtr, 40); + + /* Start capturing logs. */ + XVphy_LogReset(InstancePtr); + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_INIT, 0); + + XVphy_HdmiSetSystemClockSelection(InstancePtr, QuadId); + + if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE3) || + (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE4)) { + XVphy_SetBufgGtDiv(InstancePtr, XVPHY_DIR_TX, 1); + XVphy_SetBufgGtDiv(InstancePtr, XVPHY_DIR_RX, 1); + } + XVphy_ResetGtPll(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, TRUE); + XVphy_ResetGtPll(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) || + (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2)) { + XVphy_ResetGtTxRx(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, TRUE); + XVphy_ResetGtTxRx(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + } + if (InstancePtr->Config.XcvrType != XVPHY_GT_TYPE_GTPE2) { + XVphy_PowerDownGtPll(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMNA, + TRUE); + XVphy_PowerDownGtPll(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, + TRUE); + } + XVphy_MmcmReset(InstancePtr, QuadId, XVPHY_DIR_TX, TRUE); + XVphy_MmcmReset(InstancePtr, QuadId, XVPHY_DIR_RX, TRUE); + XVphy_IBufDsEnable(InstancePtr, QuadId, XVPHY_DIR_TX, (FALSE)); + XVphy_IBufDsEnable(InstancePtr, QuadId, XVPHY_DIR_RX, (FALSE)); + + + /* DRU Settings. */ + if (InstancePtr->Config.DruIsPresent) { + XVphy_IBufDsEnable(InstancePtr, QuadId, XVPHY_DIR_RX, TRUE); + XVphy_DruReset(InstancePtr, XVPHY_CHANNEL_ID_CHA, TRUE); + XVphy_DruEnable(InstancePtr, XVPHY_CHANNEL_ID_CHA, FALSE); + if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) || + (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2)) { + XVphy_DruSetGain(InstancePtr, XVPHY_CHANNEL_ID_CHA, + 9, 16, 5); + } + else { + XVphy_DruSetGain(InstancePtr, XVPHY_CHANNEL_ID_CHA, + 9, 16, 4); + } + } + + XVphy_SetRxLpm(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX, + 1); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + XVphy_SetTxVoltageSwing(InstancePtr, QuadId, (XVphy_ChannelId)Id, 0x1); + XVphy_SetTxPreEmphasis(InstancePtr, QuadId, (XVphy_ChannelId)Id, 0x1); + } + + /* Clear Interrupt Register */ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_INTR_STS_REG, + 0xFFFFFFFF); + + /* Interrupt Enable. */ + XVphy_IntrEnable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_TXRESET_DONE); + XVphy_IntrEnable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_RXRESET_DONE); + XVphy_IntrEnable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_CPLL_LOCK); + XVphy_IntrEnable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_QPLL0_LOCK); + XVphy_IntrEnable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_TXALIGN_DONE); + XVphy_IntrEnable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_QPLL1_LOCK); + XVphy_IntrEnable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE); + XVphy_IntrEnable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE); + XVphy_IntrEnable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT); + XVphy_IntrEnable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); + XVphy_ClkDetEnable(InstancePtr, TRUE); + + /* Set the flag to indicate the driver is. */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + /* Init done. */ + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_INIT, 1); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function Sets the System Clock Selection +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void XVphy_HdmiSetSystemClockSelection(XVphy *InstancePtr, u8 QuadId) +{ + XVphy_PllType XVphy_QPllType; + + if (InstancePtr->Config.XcvrType != XVPHY_GT_TYPE_GTPE2) { + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + XVphy_QPllType = XVPHY_PLL_TYPE_QPLL; + } + else { + XVphy_QPllType = XVPHY_PLL_TYPE_QPLL0; + } + + /* Set system clock selections */ + if (InstancePtr->Config.TxSysPllClkSel == + InstancePtr->Config.RxSysPllClkSel) { + if (InstancePtr->Config.RxSysPllClkSel == + XVPHY_SYSCLKSELDATA_TYPE_CPLL_OUTCLK) { + XVphy_PllInitialize(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CHA, + InstancePtr->Config.RxRefClkSel, + InstancePtr->Config.RxRefClkSel, + XVPHY_PLL_TYPE_CPLL, + XVPHY_PLL_TYPE_CPLL); + } + else { + XVphy_PllInitialize(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMN0, + InstancePtr->Config.RxRefClkSel, + InstancePtr->Config.RxRefClkSel, + XVphy_QPllType, + XVphy_QPllType); + } + } + else if (InstancePtr->Config.TxSysPllClkSel == + XVPHY_SYSCLKSELDATA_TYPE_CPLL_OUTCLK) { + XVphy_PllInitialize(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CHA, + InstancePtr->Config.RxRefClkSel, + InstancePtr->Config.TxRefClkSel, + XVPHY_PLL_TYPE_CPLL, + XVphy_QPllType); + } + else { + XVphy_PllInitialize(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMN0, + InstancePtr->Config.TxRefClkSel, + InstancePtr->Config.RxRefClkSel, + XVphy_QPllType, + XVPHY_PLL_TYPE_CPLL); + } + } + /* GTPE2 */ + else { + if (InstancePtr->Config.TxSysPllClkSel == + XVPHY_SYSCLKSELDATA_TYPE_PLL0_OUTCLK) { + XVphy_PllInitialize(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMN0, + InstancePtr->Config.TxRefClkSel, + InstancePtr->Config.RxRefClkSel, + XVPHY_PLL_TYPE_PLL0, + XVPHY_PLL_TYPE_PLL1); + } + else { + XVphy_PllInitialize(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMN0, + InstancePtr->Config.RxRefClkSel, + InstancePtr->Config.TxRefClkSel, + XVPHY_PLL_TYPE_PLL1, + XVPHY_PLL_TYPE_PLL0); + } + } +} + +/*****************************************************************************/ +/** +* This function Updates the VPHY clocking. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param TxSysPllClkSel is the SYSCLKDATA selection for TX. +* @param RxSysPllClkSel is the SYSCLKDATA selection for RX. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiUpdateClockSelection(XVphy *InstancePtr, u8 QuadId, + XVphy_SysClkDataSelType TxSysPllClkSel, + XVphy_SysClkDataSelType RxSysPllClkSel) +{ + u8 Id, Id0, Id1; + + /* Reset PLL */ + XVphy_ResetGtPll(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, TRUE); + XVphy_ResetGtPll(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + + /* Set default. */ + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_IDLE; + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)].RxState = + XVPHY_GT_STATE_IDLE; + } + + /* Update VPhy Clocking */ + InstancePtr->Config.TxSysPllClkSel = TxSysPllClkSel; + InstancePtr->Config.RxSysPllClkSel = RxSysPllClkSel; + XVphy_HdmiSetSystemClockSelection(InstancePtr, QuadId); +} + +/*****************************************************************************/ +/** +* This function resets the GT TX alignment module. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param ChId is the channel ID to operate on. +* @param Reset specifies TRUE/FALSE value to either assert or deassert +* reset on the TX alignment module, respectively. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_TxAlignReset(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 Reset) +{ + u32 RegVal; + u32 MaskVal = 0; + u8 Id, Id0, Id1; + + /* Read TX align register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_TX_BUFFER_BYPASS_REG); + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + MaskVal |= XVPHY_TX_BUFFER_BYPASS_TXPHDLYRESET_MASK(Id); + } + + /* Write new value to BUFG_GT register. */ + if (Reset) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_TX_BUFFER_BYPASS_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function resets the GT TX alignment module. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param ChId is the channel ID to operate on. +* @param Start specifies TRUE/FALSE value to either start or ttop the TX +* alignment module, respectively. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_TxAlignStart(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 Start) +{ + u32 RegVal; + u32 MaskVal = 0; + u8 Id, Id0, Id1; + + /* Read TX align register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_TX_BUFFER_BYPASS_REG); + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + MaskVal |= XVPHY_TX_BUFFER_BYPASS_TXPHALIGN_MASK(Id); + } + + /* Write new value to BUFG_GT register. */ + if (Start) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_TX_BUFFER_BYPASS_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function enables the VPHY's detector peripheral. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Enable specifies TRUE/FALSE value to either enable or disable +* the clock detector respectively. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_ClkDetEnable(XVphy *InstancePtr, u8 Enable) +{ + u32 RegVal; + + /* Read clkdet ctrl register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_CLKDET_CTRL_REG); + + /* Write new value to clkdet ctrl register. */ + if (Enable) { + RegVal |= XVPHY_CLKDET_CTRL_RUN_MASK; + } + else { + RegVal &= ~XVPHY_CLKDET_CTRL_RUN_MASK; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_CLKDET_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function clears the clock detector TX/RX timer. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for RX or TX. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_ClkDetTimerClear(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir) +{ + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + /* Read the clock detector control register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_CLKDET_CTRL_REG); + + if (Dir == XVPHY_DIR_TX) { + RegVal |= XVPHY_CLKDET_CTRL_TX_TMR_CLR_MASK; + } + else { + RegVal |= XVPHY_CLKDET_CTRL_RX_TMR_CLR_MASK; + } + + /* Write new value to clkdet ctrl register. */ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_CLKDET_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function resets clock detector TX/RX frequency. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for RX or TX. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_ClkDetFreqReset(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir) +{ + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + /* Read clkdet ctrl register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_CLKDET_CTRL_REG); + + if (Dir == XVPHY_DIR_TX) { + RegVal |= XVPHY_CLKDET_CTRL_TX_FREQ_RST_MASK; + } + else { + RegVal |= XVPHY_CLKDET_CTRL_RX_FREQ_RST_MASK; + } + + /* Write new value to clkdet ctrl register. */ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_CLKDET_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function sets the clock detector frequency lock counter threshold value. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param ThresholdVal is the threshold value to be set. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_ClkDetSetFreqLockThreshold(XVphy *InstancePtr, u16 ThresholdVal) +{ + u32 RegVal; + + /* Read clkdet ctrl register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_CLKDET_CTRL_REG); + RegVal &= ~XVPHY_CLKDET_CTRL_RX_FREQ_RST_MASK; + + /* Update with new threshold. */ + RegVal |= (ThresholdVal << XVPHY_CLKDET_CTRL_FREQ_LOCK_THRESH_SHIFT); + + /* Write new value to clkdet ctrl register. */ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_CLKDET_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function checks clock detector RX/TX frequency zero indicator bit. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Dir is an indicator for RX or TX. +* +* @return - TRUE if zero frequency. +* - FALSE otherwise, if non-zero frequency. +* +* @note None. +* +******************************************************************************/ +u8 XVphy_ClkDetCheckFreqZero(XVphy *InstancePtr, XVphy_DirectionType Dir) +{ + u32 MaskVal = 0; + u32 RegVal; + + if (Dir == XVPHY_DIR_TX) { + MaskVal = XVPHY_CLKDET_STAT_TX_FREQ_ZERO_MASK; + } + else { + MaskVal = XVPHY_CLKDET_STAT_RX_FREQ_ZERO_MASK; + } + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_DRU_STAT_REG); + RegVal &= MaskVal; + + if (RegVal) { + return (TRUE); + } + + return (FALSE); +} + +/*****************************************************************************/ +/** +* This function sets clock detector frequency lock counter threshold value. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param TimeoutVal is the timeout value and is normally the system clock +* frequency. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_ClkDetSetFreqTimeout(XVphy *InstancePtr, u32 TimeoutVal) +{ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, + XVPHY_CLKDET_FREQ_TMR_TO_REG, TimeoutVal); +} + +/*****************************************************************************/ +/** +* This function loads the timer to TX/RX in the clock detector. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for RX or TX. +* @param TimeoutVal is the timeout value to store in the clock detector. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_ClkDetTimerLoad(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, u32 TimeoutVal) +{ + u32 RegOffset; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_CLKDET_TMR_TX_REG; + } + else { + RegOffset = XVPHY_CLKDET_TMR_RX_REG; + } + + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, TimeoutVal); +} + +/*****************************************************************************/ +/** +* This function returns the frequency of the RX/TX reference clock as +* measured by the clock detector peripheral. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Dir is an indicator for RX or TX. +* +* @return The measured frequency of the RX/TX reference clock. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_ClkDetGetRefClkFreqHz(XVphy *InstancePtr, XVphy_DirectionType Dir) +{ + u32 RegOffset; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_CLKDET_FREQ_TX_REG; + } + else { + RegOffset = XVPHY_CLKDET_FREQ_RX_REG; + } + + return XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); +} + +/*****************************************************************************/ +/** +* This function returns the frequency of the DRU reference clock as measured by +* the clock detector peripheral. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return The measured frequency of the DRU reference clock. +* +* @note The design must have a DRU for this function to return a valid +* value. +* +******************************************************************************/ +u32 XVphy_DruGetRefClkFreqHz(XVphy *InstancePtr) +{ + u32 DruFreqHz = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_CLKDET_FREQ_DRU_REG); + + + + /* Verify argument. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + if (DruFreqHz > XVPHY_HDMI_GTXE2_DRU_REFCLK_MIN && + DruFreqHz < XVPHY_HDMI_GTXE2_DRU_REFCLK_MAX){ + return XVPHY_HDMI_GTXE2_DRU_REFCLK; + } + } + else if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE2) { + if (DruFreqHz > XVPHY_HDMI_GTHE2_DRU_REFCLK_MIN && + DruFreqHz < XVPHY_HDMI_GTHE2_DRU_REFCLK_MAX){ + return XVPHY_HDMI_GTHE2_DRU_REFCLK; + } + } + else if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2) { + if (DruFreqHz > XVPHY_HDMI_GTPE2_DRU_REFCLK_MIN && + DruFreqHz < XVPHY_HDMI_GTPE2_DRU_REFCLK_MAX){ + return XVPHY_HDMI_GTPE2_DRU_REFCLK; + } + } + else if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE3) { + if (DruFreqHz > XVPHY_HDMI_GTHE3_DRU_REFCLK_MIN && + DruFreqHz < XVPHY_HDMI_GTHE3_DRU_REFCLK_MAX){ + return XVPHY_HDMI_GTHE3_DRU_REFCLK; + } + } + else { + if (DruFreqHz > XVPHY_HDMI_GTHE4_DRU_REFCLK_MIN && + DruFreqHz < XVPHY_HDMI_GTHE4_DRU_REFCLK_MAX){ + return XVPHY_HDMI_GTHE4_DRU_REFCLK; + } + } + /* Return Failure */ + return XST_FAILURE; +} + +/*****************************************************************************/ +/** +* This function resets the DRU in the VPHY. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param ChId is the channel ID to operate on. +* @param Reset specifies TRUE/FALSE value to either enable or disable +* the DRU respectively. +* +* @return None. +* +******************************************************************************/ +void XVphy_DruReset(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 Reset) +{ + u32 RegVal; + u32 MaskVal = 0; + u8 Id, Id0, Id1; + + /* Read DRU ctrl register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_DRU_CTRL_REG); + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + MaskVal |= XVPHY_DRU_CTRL_RST_MASK(Id); + } + + /* Write DRU ctrl register. */ + if (Reset) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_DRU_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function enabled/disables the DRU in the VPHY. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param ChId is the channel ID to operate on. +* @param Enable specifies TRUE/FALSE value to either enable or disable +* the DRU, respectively. +* +* @return None. +* +******************************************************************************/ +void XVphy_DruEnable(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 Enable) +{ + u32 RegVal; + u32 MaskVal = 0; + u8 Id, Id0, Id1; + + /* Read DRU ctrl register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_DRU_CTRL_REG); + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + MaskVal |= XVPHY_DRU_CTRL_EN_MASK(Id); + } + + /* Write DRU ctrl register. */ + if (Enable) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_DRU_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function gets the DRU version +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return None. +* +******************************************************************************/ +u16 XVphy_DruGetVersion(XVphy *InstancePtr) +{ + u32 RegVal; + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_DRU_STAT_REG); + RegVal &= XVPHY_DRU_STAT_VERSION_MASK; + RegVal >>= XVPHY_DRU_STAT_VERSION_SHIFT; + + return ((u16)RegVal); +} + +/*****************************************************************************/ +/** +* This function sets the DRU center frequency. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param ChId specifies the channel ID. +* @param CenterFreqHz is the frequency value to set. +* +* @return None. +* +******************************************************************************/ +void XVphy_DruSetCenterFreqHz(XVphy *InstancePtr, XVphy_ChannelId ChId, + u64 CenterFreqHz) +{ + u32 CenterFreqL; + u32 CenterFreqH; + u32 RegOffset; + u8 Id, Id0, Id1; + + /* Split the 64-bit input into 2 32-bit values. */ + CenterFreqL = (u32)CenterFreqHz; + CenterFreqHz >>= 32; + CenterFreqHz &= XVPHY_DRU_CFREQ_H_MASK;; + CenterFreqH = (u32)CenterFreqHz; + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + RegOffset = XVPHY_DRU_CFREQ_L_REG(Id); + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, + CenterFreqL); + + RegOffset = XVPHY_DRU_CFREQ_H_REG(Id); + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, + CenterFreqH); + } +} + +/*****************************************************************************/ +/** +* This function sets the DRU gain. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param ChId is the channel ID to operate on. +* @param G1 gain value. +* @param G1_P gain value. +* @param G2 gain value. +* +* @return None. +* +******************************************************************************/ +void XVphy_DruSetGain(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 G1, u8 G1_P, + u8 G2) +{ + u32 RegVal; + u32 RegOffset; + u8 Id, Id0, Id1; + + RegVal = G1 & XVPHY_DRU_GAIN_G1_MASK; + RegVal |= (G1_P << XVPHY_DRU_GAIN_G1_P_SHIFT) & + XVPHY_DRU_GAIN_G1_P_MASK; + RegVal |= (G2 << XVPHY_DRU_GAIN_G2_SHIFT) & XVPHY_DRU_GAIN_G2_MASK; + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + RegOffset = XVPHY_DRU_GAIN_REG(Id); + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + } +} + +/*****************************************************************************/ +/** +* This function calculates the center frequency value for the DRU. +* +* @param InstancePtr is a pointer to the XVphy GT core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return The calculated DRU Center frequency value. +* +* @note According to XAPP875: +* Center_f = fDIN * (2^32)/fdruclk +* The DRU clock is derived from the measured reference clock and +* the current QPLL settings. +* +******************************************************************************/ +u64 XVphy_DruCalcCenterFreqHz(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId) +{ + XVphy_Channel *ChPtr, *CmnPtr; + u64 DruRefClk; + u64 ClkDetRefClk; + u64 DataRate; + u64 FDin; + u64 FDruClk; + + DruRefClk = XVphy_DruGetRefClkFreqHz(InstancePtr); + ClkDetRefClk = XVphy_ClkDetGetRefClkFreqHz(InstancePtr, XVPHY_DIR_RX); + + /* Take the master channel (channel 1). */ + ChPtr = &InstancePtr->Quads[QuadId].Ch1; + + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2) { + CmnPtr = &InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]; + FDruClk = (DruRefClk * CmnPtr->PllParams.N1FbDiv * + CmnPtr->PllParams.N2FbDiv * 2) / + (CmnPtr->PllParams.MRefClkDiv * ChPtr->RxOutDiv * 20); + } + else if ((ChId == XVPHY_CHANNEL_ID_CMN0) || + (ChId == XVPHY_CHANNEL_ID_CMN1)) { + FDruClk = (DruRefClk * InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(ChId)].PllParams.NFbDiv) / + (ChPtr->RxOutDiv * 20); + } + else { + FDruClk = (DruRefClk * ChPtr->PllParams.N1FbDiv * + ChPtr->PllParams.N2FbDiv * 2) / + (ChPtr->PllParams.MRefClkDiv * ChPtr->RxOutDiv * 20); + } + + DataRate = 10 * ClkDetRefClk; + FDin = DataRate * ((u64)1 << 32); + + /* Check for divide by zero. */ + if (FDin && FDruClk) { + return (FDin / FDruClk); + } + return 0; +} + +/*****************************************************************************/ +/** +* This function sets the GT RX CDR and Equalization for DRU mode. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Enable enables the DRU logic (when 1), or disables (when 0). +* +* @return None. +* +******************************************************************************/ +void XVphy_HdmiGtDruModeEnable(XVphy *InstancePtr, u8 Enable) +{ + u32 RegVal; + u32 RegMask = 0; + u8 Id, Id0, Id1; + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_DRU_EN, Enable); + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_RX_EQ_CDR_REG); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + RegMask |= XVPHY_RX_STATUS_RXCDRHOLD_MASK(Id) | + XVPHY_RX_STATUS_RXOSOVRDEN_MASK(Id) | + XVPHY_RX_STATUS_RXLPMLFKLOVRDEN_MASK(Id) | + XVPHY_RX_STATUS_RXLPMHFOVRDEN_MASK(Id); + } + + if (Enable) { + RegVal |= RegMask; + } + else { + RegVal &= ~RegMask; + } + + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_RX_EQ_CDR_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function calculates the HDMI MMCM parameters. +* +* @param InstancePtr is a pointer to the Vphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for RX or TX. +* @param Ppc specifies the total number of pixels per clock. +* - 1 = XVIDC_PPC_1 +* - 2 = XVIDC_PPC_2 +* - 4 = XVIDC_PPC_4 +* @param Bpc specifies the color depth/bits per color component. +* - 6 = XVIDC_BPC_6 +* - 8 = XVIDC_BPC_8 +* - 10 = XVIDC_BPC_10 +* - 12 = XVIDC_BPC_12 +* - 16 = XVIDC_BPC_16 +* +* @return +* - XST_SUCCESS if calculated PLL parameters updated successfully. +* - XST_FAILURE if parameters not updated. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_HdmiCfgCalcMmcmParam(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir, + XVidC_PixelsPerClock Ppc, XVidC_ColorDepth Bpc) +{ + u32 RefClk; + u8 Div; + u8 Mult; + u8 Valid; + u64 LineRate = 0; + XVphy_Mmcm *MmcmPtr; + XVphy_PllType PllType; + + /* Suppress Warning Messages */ + ChId = ChId; + + if (Dir == XVPHY_DIR_RX) { + RefClk = InstancePtr->HdmiRxRefClkHz; + MmcmPtr= &InstancePtr->Quads[QuadId].RxMmcm; + + RefClk = RefClk / (GetGtHdmiPtr(InstancePtr))->RxMmcmScale; + Mult = (GetGtHdmiPtr(InstancePtr))->RxMmcmFvcoMax / RefClk; + } + else { + RefClk = InstancePtr->HdmiTxRefClkHz; + MmcmPtr= &InstancePtr->Quads[QuadId].TxMmcm; + + RefClk = RefClk / (GetGtHdmiPtr(InstancePtr))->TxMmcmScale; + Mult = (GetGtHdmiPtr(InstancePtr))->TxMmcmFvcoMax / RefClk; + + /* Get line rate. */ + PllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_TX, + XVPHY_CHANNEL_ID_CH1); + + switch (PllType) { + case XVPHY_PLL_TYPE_QPLL: + case XVPHY_PLL_TYPE_QPLL0: + case XVPHY_PLL_TYPE_PLL0: + LineRate = InstancePtr->Quads[QuadId].Cmn0.LineRateHz; + break; + case XVPHY_PLL_TYPE_QPLL1: + case XVPHY_PLL_TYPE_PLL1: + LineRate = InstancePtr->Quads[QuadId].Cmn1.LineRateHz; + break; + default: + LineRate = InstancePtr->Quads[QuadId].Ch1.LineRateHz; + break; + } + } + + Div = 1; + + if (((LineRate / 1000000) > 2970) && (Ppc == XVIDC_PPC_1)) { + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_1PPC_ERR, 1); + XVphy_CfgErrIntr(InstancePtr, XVPHY_ERRIRQ_MMCM_CFG, 1); + return (XST_FAILURE); + } + + /* In case of 4 pixels per clock, the M must be a multiple of four. */ + if (Ppc == XVIDC_PPC_4) { + Mult = Mult / 4; + Mult = Mult * 4; + } + /* Else the M must be a multiple of two. */ + else if (Ppc == XVIDC_PPC_2) { + Mult = Mult / 2; + Mult = Mult * 2; + } + + if (!((Mult >= 1) && (Mult < 65))) { + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_MMCM_ERR, 1); + XVphy_CfgErrIntr(InstancePtr, XVPHY_ERRIRQ_MMCM_CFG, 1); + return (XST_FAILURE); /* Mult is out of range. */ + } + + Valid = (FALSE); + do { + MmcmPtr->ClkFbOutMult = Mult; + MmcmPtr->DivClkDivide = Div; + + if (InstancePtr->Config.TransceiverWidth == 4) { + /* Link clock: TMDS clock ratio 1/40. */ + if ((LineRate / 1000000) >= 3400) { + MmcmPtr->ClkOut0Div = Mult; + } + /* Link clock: TMDS clock ratio 1/10. */ + else { + MmcmPtr->ClkOut0Div = Mult * 4; + } + } + else {//2 Byte Mode + /* Link clock: TMDS clock ratio 1/40. */ + if ((LineRate / 1000000) >= 3400) { + MmcmPtr->ClkOut0Div = Mult / 2; + } + /* Link clock: TMDS clock ratio 1/10. */ + else { + MmcmPtr->ClkOut0Div = Mult * 2; + } + } + + /* TMDS Clock */ + MmcmPtr->ClkOut1Div = Mult * ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1); + + /* Video clock. */ + MmcmPtr->ClkOut2Div = 0; + + switch (Bpc) { + case XVIDC_BPC_10: + /* Quad pixel. */ + if (Ppc == (XVIDC_PPC_4)) { + MmcmPtr->ClkOut2Div = (Mult * 5 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + /* Dual pixel. */ + else if (Ppc == (XVIDC_PPC_2)) { + /* The clock ratio is 2.5 */ + /* The PLL only supports integer values */ + /* The mult must be dividable by two (2 * 2.5 = 5) + to get an integer number */ + if ((Mult % 2) == 0) { + MmcmPtr->ClkOut2Div = (Mult * 5 / 2 * + ((Dir == XVPHY_DIR_TX)? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + } + /* Single pixel. */ + else { + /* The clock ratio is 1.25 */ + /* The PLL only supports integer values */ + /* The mult must be dividable by four (4 * 1.25 = 5) + to get an integer number */ + if ((Mult % 4) == 0) { + MmcmPtr->ClkOut2Div = (Mult * 5 / 4 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + } + break; + case XVIDC_BPC_12: + /* Quad pixel. */ + if (Ppc == (XVIDC_PPC_4)) { + MmcmPtr->ClkOut2Div = (Mult * 6 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + /* Dual pixel. */ + else if (Ppc == (XVIDC_PPC_2)) { + MmcmPtr->ClkOut2Div = (Mult * 3 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + /* Single pixel. */ + else { + /* The clock ratio is 1.5 */ + /* The PLL only supports integer values */ + /* The mult must be dividable by two (2 * 1.5 = 3) + to get an integer number */ + if ((Mult % 2) == 0) { + MmcmPtr->ClkOut2Div = (Mult * 3 / 2 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + } + break; + case XVIDC_BPC_16 : + /* Quad pixel. */ + if (Ppc == (XVIDC_PPC_4)) { + MmcmPtr->ClkOut2Div = (Mult * 8 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + /* Dual pixel. */ + else if (Ppc == (XVIDC_PPC_2)) { + MmcmPtr->ClkOut2Div = (Mult * 4 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + /* Single pixel. */ + else { + MmcmPtr->ClkOut2Div = (Mult * 2 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + break; + case XVIDC_BPC_8: + default: + /* Quad pixel. */ + if (Ppc == (XVIDC_PPC_4)) { + MmcmPtr->ClkOut2Div = (Mult * 4 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + /* Dual pixel. */ + else if (Ppc == (XVIDC_PPC_2)) { + MmcmPtr->ClkOut2Div = (Mult * 2 * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + /* Single pixel. */ + else { + MmcmPtr->ClkOut2Div = (Mult * + ((Dir == XVPHY_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + break; + } + + /* Only do this when the ClkOut2Div has been set */ + if (MmcmPtr->ClkOut2Div) { + if (Dir == XVPHY_DIR_RX) { + /* Correct divider value if TMDS clock ratio is 1/40. */ + if (InstancePtr->HdmiRxTmdsClockRatio) { + if ((MmcmPtr->ClkOut2Div % 4) == 0) { + MmcmPtr->ClkOut2Div = + MmcmPtr->ClkOut2Div / 4; + } + /* Not divisible by 4: repeat loop with a lower + * multiply value. */ + else { + MmcmPtr->ClkOut2Div = 255; + } + } + } + /* TX. */ + else if ((LineRate / 1000000) >= 3400) { + if ((MmcmPtr->ClkOut2Div % 4) == 0) { + MmcmPtr->ClkOut2Div = + MmcmPtr->ClkOut2Div / 4; + } + /* Not divisible by 4: repeat loop with a lower + * multiply value. */ + else { + MmcmPtr->ClkOut2Div = 255; + } + } + } + + /* Check values. */ + if ((MmcmPtr->ClkOut0Div <= 128) && + (MmcmPtr->ClkOut1Div <= 128) && + (MmcmPtr->ClkOut2Div <= 128) && + (MmcmPtr->ClkOut2Div > 0)) { + Valid = (TRUE); + } + else { + /* 4 pixels per clock. */ + if (Ppc == (XVIDC_PPC_4)) { + /* Decrease Mult value. */ + Mult -= 4; + } + /* 2 pixels per clock. */ + else if (Ppc == (XVIDC_PPC_2)) { + /* Decrease M value. */ + Mult -= 2; + } + /* 1 pixel per clock */ + else { + /* Decrease M value */ + Mult -= 1; + } + } + } while (!Valid); + + if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2) && + (((RefClk/1000)*(Mult/MmcmPtr->ClkOut2Div)) > 148500)) { + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_VDCLK_HIGH_ERR, 1); + XVphy_CfgErrIntr(InstancePtr, XVPHY_ERRIRQ_MMCM_CFG, 1); + return (XST_FAILURE); + } + + if (Valid) { + XVphy_CfgErrIntr(InstancePtr, XVPHY_ERRIRQ_MMCM_CFG, 0); + return (XST_SUCCESS); + } + else { + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_MMCM_ERR, 1); + XVphy_CfgErrIntr(InstancePtr, XVPHY_ERRIRQ_MMCM_CFG, 1); + return (XST_FAILURE); + } +} + +/*****************************************************************************/ +/** +* This function calculates the QPLL parameters. +* +* @param InstancePtr is a pointer to the HDMI GT core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for RX or TX. +* +* @return +* - XST_SUCCESS if calculated QPLL parameters updated +* successfully. +* - XST_FAILURE if parameters not updated. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_HdmiQpllParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir) +{ + u32 Status; + u64 RefClk = 0; + u32 *RefClkPtr; + u64 TxLineRate = 0; + u8 Id, Id0, Id1; + + u8 SRArray[] = {1, 3, 5}; + u8 SRIndex; + u8 SRValue; + + /* Suppress Warning Messages */ + ChId = ChId; + + XVphy_SysClkDataSelType SysClkDataSel = (XVphy_SysClkDataSelType) 0; + XVphy_SysClkOutSelType SysClkOutSel = (XVphy_SysClkOutSelType) 0; + XVphy_ChannelId ActiveCmnId = XVPHY_CHANNEL_ID_CMN0; + + u32 QpllRefClk; + u32 QpllClkMin = 0; + + /* Determine QPLL reference clock from the first (master) channel. */ + if (Dir == XVPHY_DIR_RX) { + QpllRefClk = InstancePtr->HdmiRxRefClkHz; + RefClkPtr = &InstancePtr->HdmiRxRefClkHz; + } + else { + QpllRefClk = InstancePtr->HdmiTxRefClkHz; + RefClkPtr = &InstancePtr->HdmiTxRefClkHz; + } + +#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE3) + /* Determine which QPLL to use. */ + if (((101875000 <= QpllRefClk) && (QpllRefClk <= 122500000)) || + ((203750000 <= QpllRefClk) && + (QpllRefClk <= 245000000)) || + ((407000000 <= QpllRefClk) && + (QpllRefClk <= 490000000))) { + SysClkDataSel = XVPHY_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK; + SysClkOutSel = XVPHY_SYSCLKSELOUT_TYPE_QPLL1_REFCLK; + ActiveCmnId = XVPHY_CHANNEL_ID_CMN1; + QpllClkMin = (u32) XVPHY_HDMI_GTHE3_QPLL1_REFCLK_MIN; + } + else { + SysClkDataSel = XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK; + SysClkOutSel = XVPHY_SYSCLKSELOUT_TYPE_QPLL0_REFCLK; + ActiveCmnId = XVPHY_CHANNEL_ID_CMN0; + QpllClkMin = (u32) XVPHY_HDMI_GTHE3_QPLL0_REFCLK_MIN; + } +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE4) + /* Determine which QPLL to use. */ + if (((101875000 <= QpllRefClk) && (QpllRefClk <= 122500000)) || + ((203750000 <= QpllRefClk) && (QpllRefClk <= 245000000)) || + ((407000000 <= QpllRefClk) && (QpllRefClk <= 490000000))) { + SysClkDataSel = XVPHY_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK; + SysClkOutSel = XVPHY_SYSCLKSELOUT_TYPE_QPLL1_REFCLK; + ActiveCmnId = XVPHY_CHANNEL_ID_CMN1; + QpllClkMin = (u32) XVPHY_HDMI_GTHE4_QPLL1_REFCLK_MIN; + } + else { + SysClkDataSel = XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK; + SysClkOutSel = XVPHY_SYSCLKSELOUT_TYPE_QPLL0_REFCLK; + ActiveCmnId = XVPHY_CHANNEL_ID_CMN0; + QpllClkMin = (u32) XVPHY_HDMI_GTHE4_QPLL0_REFCLK_MIN; + } +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE2) + SysClkDataSel = XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK; + SysClkOutSel = XVPHY_SYSCLKSELOUT_TYPE_QPLL_REFCLK; + ActiveCmnId = XVPHY_CHANNEL_ID_CMN; + QpllClkMin = (GetGtHdmiPtr(InstancePtr))->Qpll0RefClkMin; +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTXE2) + SysClkDataSel = XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK; + SysClkOutSel = XVPHY_SYSCLKSELOUT_TYPE_QPLL_REFCLK; + ActiveCmnId = XVPHY_CHANNEL_ID_CMN; + QpllClkMin = (GetGtHdmiPtr(InstancePtr))->Qpll0RefClkMin; +#endif + + /* Update QPLL clock selections. */ + XVphy_CfgSysClkDataSel(InstancePtr, QuadId, Dir, SysClkDataSel); + XVphy_CfgSysClkOutSel(InstancePtr, QuadId, Dir, SysClkOutSel); + + /* RX is using QPLL. */ + if (Dir == XVPHY_DIR_RX) { + /* Check if the reference clock is not below the minimum QPLL + * input frequency. */ + if (QpllRefClk >= QpllClkMin) { + RefClk = QpllRefClk; + + /* Scaled line rate. */ + if (InstancePtr->HdmiRxTmdsClockRatio) { + XVphy_CfgLineRate(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMNA, (RefClk * 40)); + } + else { + XVphy_CfgLineRate(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMNA, (RefClk * 10)); + } + + /* Clear DRU is enabled flag. */ + InstancePtr->HdmiRxDruIsEnabled = 0; + + /* Set RX data width. */ + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, + &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + if (InstancePtr->Config.TransceiverWidth == 2) { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + RxDataWidth = 20; + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + RxIntDataWidth = 2; + } + else { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + RxDataWidth = 40; + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + RxIntDataWidth = 4; + } + } + + } + /* The reference clock is below the minimum frequency thus + * select the DRU. */ + else if (InstancePtr->Config.DruIsPresent) { + RefClk = XVphy_DruGetRefClkFreqHz(InstancePtr); + + /* Round input frequency to 10 kHz. */ + RefClk = (RefClk+5000) / 10000; + RefClk = RefClk * 10000; + + /* Set the DRU to operate at a linerate of 2.5 Gbps. */ + XVphy_CfgLineRate(InstancePtr, + QuadId, XVPHY_CHANNEL_ID_CMNA, + (GetGtHdmiPtr(InstancePtr))->DruLineRate); + + /* Set DRU is enabled flag. */ + InstancePtr->HdmiRxDruIsEnabled = 1; + + /* Set RX data width to 40 and 4 bytes. */ + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, + &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(Id)].RxDataWidth = 20; + InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(Id)].RxIntDataWidth = 2; + } + } + else { + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_NO_DRU, 1); + XVphy_CfgErrIntr(InstancePtr, XVPHY_ERRIRQ_NO_DRU, 1); + return (XST_FAILURE); + } + } + + /* TX is using QPLL. */ + else { + /* Update TX line rates. */ + XVphy_CfgLineRate(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CMNA, + (u64)((*RefClkPtr) * 10)); + TxLineRate = (*RefClkPtr) / 100000;; + + /* Set default TX sample rate. */ + InstancePtr->HdmiTxSampleRate = 1; + + /* Check if the linerate is above the 340 Mcsc. */ + if ((TxLineRate) >= 3400) { + (*RefClkPtr) = (*RefClkPtr) / 4; + } + } + + /* Calculate QPLL values. */ + for (SRIndex = 0; SRIndex < sizeof(SRArray); SRIndex++) { + /* Only use oversampling when then TX is using the QPLL. */ + if (Dir == XVPHY_DIR_TX) { + SRValue = SRArray[SRIndex]; + + /* TX reference clock is below the minimum QPLL clock + * input frequency. */ + if ((*RefClkPtr) < QpllClkMin) { + RefClk = ((*RefClkPtr) * SRValue); + + /* Calculate scaled line rate. */ + if (TxLineRate >= 3400) { + XVphy_CfgLineRate(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMNA, + (u64)(RefClk * 40)); + } + else { + XVphy_CfgLineRate(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMNA, + (u64)(RefClk * 10)); + } + } + /* TX reference clock is in QPLL clock input range. + * In this case don't increase the reference clock, but + * increase the line rate. */ + else { + RefClk = (*RefClkPtr); + + /* Calculate scaled line rate. */ + if (TxLineRate >= 3400) { + XVphy_CfgLineRate(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMNA, + (u64)(RefClk * 40 *SRValue)); + } + + else { + XVphy_CfgLineRate(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CMNA, + (u64)(RefClk * 10 *SRValue)); + } + } + } + /* For all other reference clocks force sample rate to one. */ + else { + SRValue = 1; + } + + Status = XVphy_ClkCalcParams(InstancePtr, QuadId, ActiveCmnId, + Dir, RefClk); + if (Status == (XST_SUCCESS)) { + /* Only execute when the TX is using the QPLL. */ + if (Dir == XVPHY_DIR_TX) { + /* Set TX sample rate. */ + InstancePtr->HdmiTxSampleRate = SRValue; + + /* Update reference clock only when the + * reference clock is below the minimum QPLL + * input frequency. */ + if ((*RefClkPtr) < QpllClkMin) { + (*RefClkPtr) = (*RefClkPtr) * SRValue; + } + else if (SRValue > 1) { + XVphy_LogWrite(InstancePtr, + XVPHY_LOG_EVT_GT_PLL_LAYOUT, 1); + XVphy_CfgErrIntr(InstancePtr, + XVPHY_ERRIRQ_QPLL_CFG, 1); + return (XST_FAILURE); + } + } + if (Dir == XVPHY_DIR_RX) { + XVphy_CfgErrIntr(InstancePtr, + XVPHY_ERRIRQ_NO_DRU, 0); + } + XVphy_CfgErrIntr(InstancePtr, + XVPHY_ERRIRQ_QPLL_CFG, 0); + return (XST_SUCCESS); + } + } + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_GT_QPLL_CFG_ERR, 1); + XVphy_CfgErrIntr(InstancePtr, XVPHY_ERRIRQ_QPLL_CFG, 1); + return (XST_FAILURE); +} + +/*****************************************************************************/ +/** +* This function calculates the CPLL parameters. +* +* @param InstancePtr is a pointer to the HDMI GT core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for RX or TX. +* +* @return +* - XST_SUCCESS if calculated CPLL parameters updated +* successfully. +* - XST_FAILURE if parameters not updated. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_HdmiCpllParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir) +{ + u32 Status; + u64 RefClk = 0; + u32 *RefClkPtr; + u32 TxLineRate = 0; + XVphy_ChannelId ChannelId = XVPHY_CHANNEL_ID_CHA; + u8 Id, Id0, Id1; + + u8 SRArray[] = {1, 3, 5}; + u8 SRIndex; + u8 SRValue; + + XVphy_PllType PllType; + + /* Suppress Warning Messages */ + ChId = ChId; + + /* Change Channel ID to Common if GTPE2 */ + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2) { + PllType = XVphy_GetPllType(InstancePtr, QuadId, Dir, + XVPHY_CHANNEL_ID_CH1); + if (PllType == XVPHY_PLL_TYPE_PLL0) { + ChannelId = XVPHY_CHANNEL_ID_CMN0; + } + else { + ChannelId = XVPHY_CHANNEL_ID_CMN1; + } + } + + /* TX is using CPLL. */ + if ((Dir == XVPHY_DIR_TX) && (!XVphy_IsBonded(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH1))) { + + /* Set default TX sample rate. */ + InstancePtr->HdmiTxSampleRate = 1; + + /* Set line rate. */ + RefClkPtr = &InstancePtr->HdmiTxRefClkHz; + XVphy_CfgLineRate(InstancePtr, QuadId, ChannelId, + (u64)((*RefClkPtr) * 10)); + TxLineRate = (*RefClkPtr) / 100000; + + /* Check if the line rate is above the 340 Mcsc. */ + if (TxLineRate >= 3400) { + (*RefClkPtr) = (*RefClkPtr) / 4; + } + } + /* RX is using CPLL. */ + else { + RefClkPtr = &InstancePtr->HdmiRxRefClkHz; + + /* Check if the reference clock is not below the minimum CPLL + * input frequency. */ + if ((*RefClkPtr) >= + (GetGtHdmiPtr(InstancePtr))->CpllRefClkMin) { + RefClk = (*RefClkPtr); + + /* Scaled linerate */ + if (InstancePtr->HdmiRxTmdsClockRatio) { + XVphy_CfgLineRate(InstancePtr, QuadId, + ChannelId, (RefClk * 40)); + } + else { + XVphy_CfgLineRate(InstancePtr, QuadId, + ChannelId, (RefClk * 10)); + } + + /* Clear DRU is enabled flag. */ + InstancePtr->HdmiRxDruIsEnabled = 0; + + /* Set RX data width. */ + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, + &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + if ((InstancePtr->Config.TransceiverWidth == 2) || + (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2)) { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + RxDataWidth = 20; + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + RxIntDataWidth = 2; + } + else { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + RxDataWidth = 40; + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + RxIntDataWidth = 4; + } + } + + } + /* The reference clock is below the minimum frequency thus + * select the DRU. */ + else { + if (InstancePtr->Config.DruIsPresent) { + /* Return config not found error when TMDS ratio is 1/40 */ + if (InstancePtr->HdmiRxTmdsClockRatio) { + XVphy_LogWrite(InstancePtr, + XVPHY_LOG_EVT_GT_CPLL_CFG_ERR, 1); + XVphy_CfgErrIntr(InstancePtr, + XVPHY_ERRIRQ_CPLL_CFG, 1); + return (XST_FAILURE); + } + + RefClk = XVphy_DruGetRefClkFreqHz(InstancePtr); + + /* Round input frequency to 10 kHz. */ + RefClk = (RefClk+5000) / 10000; + RefClk = RefClk * 10000; + + /* Set the DRU to operate at a linerate of + * 2.5 Gbps. */ + XVphy_CfgLineRate(InstancePtr, QuadId, + ChannelId, + (GetGtHdmiPtr(InstancePtr))-> + DruLineRate); + + /* Set DRU is enabled flag. */ + InstancePtr->HdmiRxDruIsEnabled = 1; + + /* Set RX data width. */ + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, + &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(Id)]. + RxDataWidth = 20; + InstancePtr->Quads[QuadId].Plls[ + XVPHY_CH2IDX(Id)]. + RxIntDataWidth = 2; + } + + if (TxLineRate > (((GetGtHdmiPtr(InstancePtr)) + ->DruLineRate) / 1000000)) { + XVphy_LogWrite(InstancePtr, + XVPHY_LOG_EVT_VD_NOT_SPRTD_ERR, 1); + XVphy_CfgErrIntr(InstancePtr, + XVPHY_ERRIRQ_CPLL_CFG, 1); + return (XST_FAILURE); + } + } + else { + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_NO_DRU, 1); + XVphy_CfgErrIntr(InstancePtr, + XVPHY_ERRIRQ_NO_DRU, 1); + return (XST_FAILURE); + } + } + } + + /* Try different sample rates. */ + for (SRIndex = 0; SRIndex < sizeof(SRArray); SRIndex++) { + /* Only use oversampling when then TX is using the CPLL. */ + if ((Dir == XVPHY_DIR_TX) && (!XVphy_IsBonded(InstancePtr, + QuadId, XVPHY_CHANNEL_ID_CH1))) { + SRValue = SRArray[SRIndex]; + + /* Multiply the reference clock with the sample rate + * value. */ + RefClk = ((*RefClkPtr) * SRValue); + + /* Calculate scaled line rate. */ + if (TxLineRate >= 3400) { + XVphy_CfgLineRate(InstancePtr, QuadId, + ChannelId, (RefClk * 40)); + } + else { + XVphy_CfgLineRate(InstancePtr, QuadId, + ChannelId, (RefClk * 10)); + } + } + /* For all other reference clocks force sample rate to one. */ + else { + SRValue = 1; + } + + Status = XVphy_ClkCalcParams(InstancePtr, QuadId, + ChannelId, Dir, RefClk); + if (Status == (XST_SUCCESS)) { + /* Only execute when the TX is using the QPLL. */ + if ((Dir == XVPHY_DIR_TX) && (!XVphy_IsBonded( + InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH1))) { + InstancePtr->HdmiTxSampleRate = SRValue; + + (*RefClkPtr) = (*RefClkPtr) * SRValue; + } + if (Dir == XVPHY_DIR_RX) { + XVphy_CfgErrIntr(InstancePtr, + XVPHY_ERRIRQ_NO_DRU, 0); + } + XVphy_CfgErrIntr(InstancePtr, XVPHY_ERRIRQ_CPLL_CFG, 0); + return (XST_SUCCESS); + } + } + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_GT_CPLL_CFG_ERR, 1); + XVphy_CfgErrIntr(InstancePtr, XVPHY_ERRIRQ_CPLL_CFG, 1); + return (XST_FAILURE); +} + +/*****************************************************************************/ +/** +* This function update/set the HDMI TX parameter. +* +* @param InstancePtr is a pointer to the Vphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Ppc is the pixels per clock to set. +* @param Bpc is the bits per color to set. +* @param ColorFormat is the color format to set. +* +* @return +* - XST_SUCCESS if TX parameters set/updated. +* - XST_FAILURE if low resolution video not supported. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_SetHdmiTxParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVidC_PixelsPerClock Ppc, XVidC_ColorDepth Bpc, + XVidC_ColorFormat ColorFormat) +{ + u32 Status; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid((Ppc == (XVIDC_PPC_1)) || (Ppc == (XVIDC_PPC_2)) || + (Ppc == (XVIDC_PPC_4))); + Xil_AssertNonvoid((Bpc == (XVIDC_BPC_8)) || (Bpc == (XVIDC_BPC_10)) || + (Bpc == (XVIDC_BPC_12)) || (Bpc == (XVIDC_BPC_16))); + Xil_AssertNonvoid((ColorFormat == (XVIDC_CSF_RGB)) || + (ColorFormat == (XVIDC_CSF_YCRCB_444)) || + (ColorFormat == (XVIDC_CSF_YCRCB_422)) || + (ColorFormat == (XVIDC_CSF_YCRCB_420))); + + /* Only calculate the QPLL/CPLL parameters when the GT TX and RX are not + * coupled. */ + if (!XVphy_IsBonded(InstancePtr, QuadId, ChId)) { + if (XVphy_IsTxUsingCpll(InstancePtr, QuadId, ChId)) { + Status = XVphy_HdmiCpllParam(InstancePtr, QuadId, ChId, + XVPHY_DIR_TX); + } + else if (InstancePtr->Config.XcvrType != XVPHY_GT_TYPE_GTPE2) { + Status = XVphy_HdmiQpllParam(InstancePtr, QuadId, ChId, + XVPHY_DIR_TX); + /* Update SysClk and PLL Clk registers immediately. */ + XVphy_WriteCfgRefClkSelReg(InstancePtr, QuadId); + } + else { + /* GTP divider calculation is same with CPLL */ + Status = XVphy_HdmiCpllParam(InstancePtr, QuadId, ChId, + XVPHY_DIR_TX); + } + + if (Status == XST_FAILURE) { + return Status; + } + } + /* Bonded mode. */ + else { + /* Copy reference clock. */ + InstancePtr->HdmiTxRefClkHz = InstancePtr->HdmiRxRefClkHz; + + /* Copy the line rate. */ + if (XVphy_IsRxUsingQpll(InstancePtr, QuadId, + XVPHY_CHANNEL_ID_CH1)) { + InstancePtr->Quads[QuadId].Ch1.LineRateHz = + InstancePtr->Quads[QuadId].Cmn0.LineRateHz; + } + else { + InstancePtr->Quads[QuadId].Cmn0.LineRateHz = + InstancePtr->Quads[QuadId].Ch1.LineRateHz; + } + + InstancePtr->HdmiTxSampleRate = 1; + + Status = (XST_SUCCESS); + } + + /* Is HDMITXSS PPC match with VPHY PPC? */ + if (Ppc == InstancePtr->Config.Ppc) { + XVphy_CfgErrIntr(InstancePtr, XVPHY_ERRIRQ_VD_NOT_SPRTD, 0); + Status = (XST_SUCCESS); + } + else { + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_PPC_MSMTCH_ERR, 1); + XVphy_CfgErrIntr(InstancePtr, XVPHY_ERRIRQ_VD_NOT_SPRTD, 1); + Status = (XST_FAILURE); + } + if (Status == (XST_SUCCESS)) { + /* Calculate TXPLL parameters. + * 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 (ColorFormat == XVIDC_CSF_YCRCB_422) { + Status = XVphy_HdmiCfgCalcMmcmParam(InstancePtr, QuadId, + ChId, XVPHY_DIR_TX, Ppc, XVIDC_BPC_8); + } + /* Other colorspaces. */ + else { + Status = XVphy_HdmiCfgCalcMmcmParam(InstancePtr, QuadId, + ChId, XVPHY_DIR_TX, Ppc, Bpc); + } + } + else { + Status = (XST_FAILURE); + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function update/set the HDMI RX parameter. +* +* @param InstancePtr is a pointer to the Vphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if RX parameters set/updated. +* - XST_FAILURE if low resolution video not supported. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_SetHdmiRxParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + XVphy_ChannelId ChanId = ChId; + XVphy_PllType PllType; + u32 Status; + u64 DruCenterFreq; + u8 Id, Id0, Id1; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + if (XVphy_IsRxUsingCpll(InstancePtr, QuadId, ChId)) { + Status = XVphy_HdmiCpllParam(InstancePtr, QuadId, ChId, + XVPHY_DIR_RX); + } + else if (InstancePtr->Config.XcvrType != XVPHY_GT_TYPE_GTPE2) { + Status = XVphy_HdmiQpllParam(InstancePtr, QuadId, ChId, + XVPHY_DIR_RX); + /* Update SysClk and PLL Clk registers immediately */ + XVphy_WriteCfgRefClkSelReg(InstancePtr, QuadId); + } + else { + /* GTP divider calculation is same with CPLL */ + Status = XVphy_HdmiCpllParam(InstancePtr, QuadId, ChId, + XVPHY_DIR_RX); + } + + if (XVphy_IsBonded(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CH1)) { + /* Same divisor value for all channels. */ + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. + TxOutDiv = InstancePtr->Quads[QuadId]. + Plls[XVPHY_CH2IDX(Id)].RxOutDiv; + } + } + + if (InstancePtr->HdmiRxDruIsEnabled) { + /* Determine PLL type. */ + PllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_RX, + XVPHY_CHANNEL_ID_CH1); + /* Update the ChId */ + ChanId = XVphy_GetRcfgChId(InstancePtr, 0, XVPHY_DIR_RX, PllType); + + DruCenterFreq = XVphy_DruCalcCenterFreqHz(InstancePtr, QuadId, + ChanId); + XVphy_DruSetCenterFreqHz(InstancePtr, XVPHY_CHANNEL_ID_CHA, + DruCenterFreq); + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function prints Video PHY debug information related to HDMI. +* +* @param InstancePtr is a pointer to the Vphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + u32 RegValue; + XVphy_Channel *ChPtr; + XVphy_ChannelId CmnId = XVPHY_CHANNEL_ID_CMN0; + u8 CpllDVal; + u8 QpllDVal; + u8 UsesQpll0 = 0; + u8 TxUsesPll0 = 0; + + ChPtr = &InstancePtr->Quads[QuadId].Plls[0]; + + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2) { + UsesQpll0 = (FALSE); + if (ChPtr->TxDataRefClkSel == + XVPHY_SYSCLKSELDATA_TYPE_PLL0_OUTCLK) { + TxUsesPll0 = 1; + xil_printf("TX => PLL0 / "); + } + else { + xil_printf("TX => PLL1 / "); + } + } + else if (XVphy_IsTxUsingCpll(InstancePtr, QuadId, ChId)) { + xil_printf("TX => CPLL / "); + } + else { + if ((ChPtr->TxDataRefClkSel == + XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK) || + (ChPtr->TxDataRefClkSel == + XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK)) { + UsesQpll0 = (TRUE); + CmnId = XVPHY_CHANNEL_ID_CMN0; + } + else { + UsesQpll0 = (FALSE); + CmnId = XVPHY_CHANNEL_ID_CMN1; + } + xil_printf("TX => QPLL%d / ", (UsesQpll0 ? 0 : 1)); + } + + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2) { + xil_printf("RX => PLL%d\n\r", (TxUsesPll0 ? 1 : 0)); + } + else if (XVphy_IsRxUsingCpll(InstancePtr, QuadId, ChId)) { + xil_printf("RX => CPLL\n\r"); + } + else { + if ((ChPtr->RxDataRefClkSel == + XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK) || + (ChPtr->RxDataRefClkSel == + XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK)) { + UsesQpll0 = (TRUE); + CmnId = XVPHY_CHANNEL_ID_CMN0; + } + else { + UsesQpll0 = (FALSE); + CmnId = XVPHY_CHANNEL_ID_CMN1; + } + xil_printf("RX => QPLL%d\n\r", (UsesQpll0 ? 0 : 1)); + } + + xil_printf("RX state: "); + switch (InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)].RxState) { + case (XVPHY_GT_STATE_IDLE): + xil_printf("idle\n\r"); + break; + case (XVPHY_GT_STATE_LOCK): + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2) { + xil_printf("PLL%d lock\n\r", (TxUsesPll0 ? 1 : 0)); + } + else if (XVphy_IsRxUsingCpll(InstancePtr, QuadId, ChId)) { + xil_printf("CPLL lock\n\r"); + } + else { + xil_printf("QPLL%d lock\n\r", (UsesQpll0 ? 0 : 1)); + } + break; + case (XVPHY_GT_STATE_RESET): + xil_printf("GT reset\n\r"); + break; + case (XVPHY_GT_STATE_READY): + xil_printf("ready\n\r"); + break; + default: + xil_printf("unknown\n\r"); + break; + } + + xil_printf("TX state: "); + switch (InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)].TxState) { + case (XVPHY_GT_STATE_IDLE): + xil_printf("idle\n\r"); + break; + case (XVPHY_GT_STATE_LOCK): + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2) { + xil_printf("PLL%d lock\n\r", (TxUsesPll0 ? 0 : 1)); + } + else if (XVphy_IsTxUsingCpll(InstancePtr, QuadId, ChId)) { + xil_printf("CPLL lock\n\r"); + } + else { + xil_printf("QPLL%d lock\n\r", (UsesQpll0 ? 0 : 1)); + } + break; + case (XVPHY_GT_STATE_RESET): + xil_printf("GT reset\n\r"); + break; + case (XVPHY_GT_STATE_ALIGN): + xil_printf("align\n\r"); + break; + case (XVPHY_GT_STATE_READY): + xil_printf("ready\n\r"); + break; + default: + xil_printf("unknown\n\r"); + break; + } + + if (XVphy_IsTxUsingCpll(InstancePtr, QuadId, ChId)) { + QpllDVal = ChPtr->RxOutDiv; + CpllDVal = ChPtr->TxOutDiv; + } + else { + CpllDVal = ChPtr->RxOutDiv; + QpllDVal = ChPtr->TxOutDiv; + } + + xil_printf("\n\r"); + if (InstancePtr->Config.XcvrType != XVPHY_GT_TYPE_GTPE2) { + xil_printf("QPLL%d settings\n\r", (UsesQpll0 ? 0 : 1)); + xil_printf("-------------\n\r"); + xil_printf("M : %d - N : %d - D : %d\n\r", + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.MRefClkDiv, + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.NFbDiv, QpllDVal); + xil_printf("\n\r"); + + xil_printf("CPLL settings\n\r"); + xil_printf("-------------\n\r"); + xil_printf("M : %d - N1 : %d - N2 : %d - D : %d\n\r", + ChPtr->PllParams.MRefClkDiv, + ChPtr->PllParams.N1FbDiv, ChPtr->PllParams.N2FbDiv, + CpllDVal); + xil_printf("\n\r"); + } + else { + CmnId = XVPHY_CHANNEL_ID_CMN0; + xil_printf("PLL0 settings\n\r"); + xil_printf("-------------\n\r"); + xil_printf("M : %d - N1 : %d - N2 : %d - D : %d\n\r", + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.MRefClkDiv, + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.N1FbDiv, + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.N2FbDiv, + (TxUsesPll0 ? ChPtr->TxOutDiv : ChPtr->RxOutDiv)); + xil_printf("\n\r"); + + CmnId = XVPHY_CHANNEL_ID_CMN1; + xil_printf("PLL1 settings\n\r"); + xil_printf("-------------\n\r"); + xil_printf("M : %d - N1 : %d - N2 : %d - D : %d\n\r", + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.MRefClkDiv, + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.N1FbDiv, + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(CmnId)]. + PllParams.N2FbDiv, + (TxUsesPll0 ? ChPtr->RxOutDiv : ChPtr->TxOutDiv)); + xil_printf("\n\r"); + } + + xil_printf("RX MMCM settings\n\r"); + xil_printf("-------------\n\r"); + xil_printf("Mult : %d - Div : %d - Clk0Div : %d - Clk1Div : %d - " + "Clk2Div : %d\n\r", + InstancePtr->Quads[QuadId].RxMmcm.ClkFbOutMult, + InstancePtr->Quads[QuadId].RxMmcm.DivClkDivide, + InstancePtr->Quads[QuadId].RxMmcm.ClkOut0Div, + InstancePtr->Quads[QuadId].RxMmcm.ClkOut1Div, + InstancePtr->Quads[QuadId].RxMmcm.ClkOut2Div); + xil_printf("\n\r"); + + xil_printf("TX MMCM settings\n\r"); + xil_printf("-------------\n\r"); + xil_printf("Mult : %d - Div : %d - Clk0Div : %d - Clk1Div : %d - " + "Clk2Div : %d\n\r", + InstancePtr->Quads[QuadId].TxMmcm.ClkFbOutMult, + InstancePtr->Quads[QuadId].TxMmcm.DivClkDivide, + InstancePtr->Quads[QuadId].TxMmcm.ClkOut0Div, + InstancePtr->Quads[QuadId].TxMmcm.ClkOut1Div, + InstancePtr->Quads[QuadId].TxMmcm.ClkOut2Div); + xil_printf("\n\r"); + + if (InstancePtr->Config.DruIsPresent) { + xil_printf("DRU Settings\n\r"); + xil_printf("-------------\n\r"); + RegValue = XVphy_DruGetVersion(InstancePtr); + xil_printf("Version : %d\n\r", RegValue); + + if (InstancePtr->HdmiRxDruIsEnabled) { + RegValue = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_DRU_GAIN_REG(ChId)); + + xil_printf("G1 : %d\n\rG1_P : %d\n\r" + "G2 : %d\n\r", + ((RegValue & XVPHY_DRU_GAIN_G1_MASK)), + ((RegValue & XVPHY_DRU_GAIN_G1_P_MASK) >> + XVPHY_DRU_GAIN_G1_P_SHIFT), + ((RegValue & XVPHY_DRU_GAIN_G2_MASK) >> + XVPHY_DRU_GAIN_G2_SHIFT)); + + RegValue = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_DRU_CFREQ_H_REG(ChId)); + xil_printf("Center_F : %x", RegValue); + + RegValue = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_DRU_CFREQ_L_REG(ChId)); + xil_printf("%x\n\r", RegValue); + } + else { + xil_printf("DRU is disabled\n\r"); + } + + xil_printf(" \n\r"); + } +} + +#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE3) +static const XVphy_GtHdmiChars Gthe3HdmiChars = { + .DruLineRate = XVPHY_HDMI_GTHE3_DRU_LRATE, + .PllScale = XVPHY_HDMI_GTHE3_PLL_SCALE, + .Qpll0RefClkMin = XVPHY_HDMI_GTHE3_QPLL0_REFCLK_MIN, + .Qpll1RefClkMin = XVPHY_HDMI_GTHE3_QPLL1_REFCLK_MIN, + .CpllRefClkMin = XVPHY_HDMI_GTHE3_CPLL_REFCLK_MIN, + .TxMmcmScale = XVPHY_HDMI_GTHE3_TX_MMCM_SCALE, + .TxMmcmFvcoMin = XVPHY_HDMI_GTHE3_TX_MMCM_FVCO_MIN, + .TxMmcmFvcoMax = XVPHY_HDMI_GTHE3_TX_MMCM_FVCO_MAX, + .RxMmcmScale = XVPHY_HDMI_GTHE3_RX_MMCM_SCALE, + .RxMmcmFvcoMin = XVPHY_HDMI_GTHE3_RX_MMCM_FVCO_MIN, + .RxMmcmFvcoMax = XVPHY_HDMI_GTHE3_RX_MMCM_FVCO_MAX, +}; +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE4) +static const XVphy_GtHdmiChars Gthe4HdmiChars = { + .DruLineRate = XVPHY_HDMI_GTHE4_DRU_LRATE, + .PllScale = XVPHY_HDMI_GTHE4_PLL_SCALE, + .Qpll0RefClkMin = XVPHY_HDMI_GTHE4_QPLL0_REFCLK_MIN, + .Qpll1RefClkMin = XVPHY_HDMI_GTHE4_QPLL1_REFCLK_MIN, + .CpllRefClkMin = XVPHY_HDMI_GTHE4_CPLL_REFCLK_MIN, + .TxMmcmScale = XVPHY_HDMI_GTHE4_TX_MMCM_SCALE, + .TxMmcmFvcoMin = XVPHY_HDMI_GTHE4_TX_MMCM_FVCO_MIN, + .TxMmcmFvcoMax = XVPHY_HDMI_GTHE4_TX_MMCM_FVCO_MAX, + .RxMmcmScale = XVPHY_HDMI_GTHE4_RX_MMCM_SCALE, + .RxMmcmFvcoMin = XVPHY_HDMI_GTHE4_RX_MMCM_FVCO_MIN, + .RxMmcmFvcoMax = XVPHY_HDMI_GTHE4_RX_MMCM_FVCO_MAX, +}; +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE2) +static const XVphy_GtHdmiChars Gthe2HdmiChars = { + .DruLineRate = XVPHY_HDMI_GTHE2_DRU_LRATE, + .PllScale = XVPHY_HDMI_GTHE2_PLL_SCALE, + .Qpll0RefClkMin = XVPHY_HDMI_GTHE2_QPLL_REFCLK_MIN, + .Qpll1RefClkMin = 0, + .CpllRefClkMin = XVPHY_HDMI_GTHE2_CPLL_REFCLK_MIN, + .TxMmcmScale = XVPHY_HDMI_GTHE2_TX_MMCM_SCALE, + .TxMmcmFvcoMin = XVPHY_HDMI_GTHE2_TX_MMCM_FVCO_MIN, + .TxMmcmFvcoMax = XVPHY_HDMI_GTHE2_TX_MMCM_FVCO_MAX, + .RxMmcmScale = XVPHY_HDMI_GTHE2_RX_MMCM_SCALE, + .RxMmcmFvcoMin = XVPHY_HDMI_GTHE2_RX_MMCM_FVCO_MIN, + .RxMmcmFvcoMax = XVPHY_HDMI_GTHE2_RX_MMCM_FVCO_MAX, +}; +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTPE2) +static const XVphy_GtHdmiChars Gtpe2HdmiChars = { + .DruLineRate = XVPHY_HDMI_GTPE2_DRU_LRATE, + .PllScale = XVPHY_HDMI_GTPE2_PLL_SCALE, + .Qpll0RefClkMin = XVPHY_HDMI_GTPE2_QPLL_REFCLK_MIN, + .Qpll1RefClkMin = 0, + .CpllRefClkMin = XVPHY_HDMI_GTPE2_CPLL_REFCLK_MIN, + .TxMmcmScale = XVPHY_HDMI_GTPE2_TX_MMCM_SCALE, + .TxMmcmFvcoMin = XVPHY_HDMI_GTPE2_TX_MMCM_FVCO_MIN, + .TxMmcmFvcoMax = XVPHY_HDMI_GTPE2_TX_MMCM_FVCO_MAX, + .RxMmcmScale = XVPHY_HDMI_GTPE2_RX_MMCM_SCALE, + .RxMmcmFvcoMin = XVPHY_HDMI_GTPE2_RX_MMCM_FVCO_MIN, + .RxMmcmFvcoMax = XVPHY_HDMI_GTPE2_RX_MMCM_FVCO_MAX, +}; +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTXE2) +static const XVphy_GtHdmiChars Gtxe2HdmiChars = { + .DruLineRate = XVPHY_HDMI_GTXE2_DRU_LRATE, + .PllScale = XVPHY_HDMI_GTXE2_PLL_SCALE, + .Qpll0RefClkMin = XVPHY_HDMI_GTXE2_QPLL_REFCLK_MIN, + .Qpll1RefClkMin = 0, + .CpllRefClkMin = XVPHY_HDMI_GTXE2_CPLL_REFCLK_MIN, + .TxMmcmScale = XVPHY_HDMI_GTXE2_TX_MMCM_SCALE, + .TxMmcmFvcoMin = XVPHY_HDMI_GTXE2_TX_MMCM_FVCO_MIN, + .TxMmcmFvcoMax = XVPHY_HDMI_GTXE2_TX_MMCM_FVCO_MAX, + .RxMmcmScale = XVPHY_HDMI_GTXE2_RX_MMCM_SCALE, + .RxMmcmFvcoMin = XVPHY_HDMI_GTXE2_RX_MMCM_FVCO_MIN, + .RxMmcmFvcoMax = XVPHY_HDMI_GTXE2_RX_MMCM_FVCO_MAX, +}; +#endif + +/*****************************************************************************/ +/** +* This function returns a pointer to the HDMI parameters based on the GT type. +* +* @param InstancePtr is a pointer to the Vphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - A pointer to the HDMI GT characteristics. +* - NULL if the GT type is unsupported. +* +* @note None. +* +******************************************************************************/ +static const XVphy_GtHdmiChars *GetGtHdmiPtr(XVphy *InstancePtr) +{ + /* Suppress Warning Messages */ + InstancePtr = InstancePtr; + +#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTXE2) + return &Gtxe2HdmiChars; +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE2) + return &Gthe2HdmiChars; +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTPE2) + return &Gtpe2HdmiChars; +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE3) + return &Gthe3HdmiChars; +#elif (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE4) + return &Gthe4HdmiChars; +#endif + + return NULL; +} + + +#endif diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_hdmi.h b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_hdmi.h new file mode 100644 index 00000000000000..23fe59346b2e74 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_hdmi.h @@ -0,0 +1,149 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_hdmi.h + * + * The Xilinx Video PHY (VPHY) driver. This driver supports the Xilinx Video PHY + * IP core. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 gm 10/19/15 Initial release. + * 1.1 gm 02/01/16 Added GTPE2 and GTHE4 constants + * 1.2 gm Added XVphy_HdmiMmcmStart function + * 1.4 gm 29/11/16 Added preprocessor directives for sw footprint reduction + * Removed XVphy_HdmiMmcmStart API + * Corrected GTPE2 DRU REFCLK range + * </pre> + * +*******************************************************************************/ +#if defined (XPAR_XV_HDMITX_0_DEVICE_ID) || defined (XPAR_XV_HDMIRX_0_DEVICE_ID) + +#ifndef XVPHY_HDMI_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XVPHY_HDMI_H_ + +/************************** Constant Definitions ******************************/ + +#define XVPHY_HDMI_GTHE4_DRU_LRATE 2500000000U +#define XVPHY_HDMI_GTHE4_DRU_REFCLK 156250000LL +#define XVPHY_HDMI_GTHE4_DRU_REFCLK_MIN 156240000LL +#define XVPHY_HDMI_GTHE4_DRU_REFCLK_MAX 156260000LL +#define XVPHY_HDMI_GTHE4_PLL_SCALE 1000 +#define XVPHY_HDMI_GTHE4_QPLL0_REFCLK_MIN 61250000LL +#define XVPHY_HDMI_GTHE4_QPLL1_REFCLK_MIN 50000000LL +#define XVPHY_HDMI_GTHE4_CPLL_REFCLK_MIN 100000000LL +#define XVPHY_HDMI_GTHE4_TX_MMCM_SCALE 1 +#define XVPHY_HDMI_GTHE4_TX_MMCM_FVCO_MIN 600000000U +#define XVPHY_HDMI_GTHE4_TX_MMCM_FVCO_MAX 1200000000U +#define XVPHY_HDMI_GTHE4_RX_MMCM_SCALE 1 +#define XVPHY_HDMI_GTHE4_RX_MMCM_FVCO_MIN 600000000U +#define XVPHY_HDMI_GTHE4_RX_MMCM_FVCO_MAX 1200000000U + +#define XVPHY_HDMI_GTHE3_DRU_LRATE 2500000000U +#define XVPHY_HDMI_GTHE3_DRU_REFCLK 156250000LL +#define XVPHY_HDMI_GTHE3_DRU_REFCLK_MIN 156240000LL +#define XVPHY_HDMI_GTHE3_DRU_REFCLK_MAX 156260000LL +#define XVPHY_HDMI_GTHE3_PLL_SCALE 1000 +#define XVPHY_HDMI_GTHE3_QPLL0_REFCLK_MIN 61250000LL +#define XVPHY_HDMI_GTHE3_QPLL1_REFCLK_MIN 50000000LL +#define XVPHY_HDMI_GTHE3_CPLL_REFCLK_MIN 100000000LL +#define XVPHY_HDMI_GTHE3_TX_MMCM_SCALE 1 +#define XVPHY_HDMI_GTHE3_TX_MMCM_FVCO_MIN 600000000U +#define XVPHY_HDMI_GTHE3_TX_MMCM_FVCO_MAX 1200000000U +#define XVPHY_HDMI_GTHE3_RX_MMCM_SCALE 1 +#define XVPHY_HDMI_GTHE3_RX_MMCM_FVCO_MIN 600000000U +#define XVPHY_HDMI_GTHE3_RX_MMCM_FVCO_MAX 1200000000U + +#define XVPHY_HDMI_GTHE2_DRU_LRATE 2500000000U +#define XVPHY_HDMI_GTHE2_DRU_REFCLK 125000000LL +#define XVPHY_HDMI_GTHE2_DRU_REFCLK_MIN 124990000LL +#define XVPHY_HDMI_GTHE2_DRU_REFCLK_MAX 125010000LL +#define XVPHY_HDMI_GTHE2_PLL_SCALE 1000 +#define XVPHY_HDMI_GTHE2_QPLL_REFCLK_MIN 61250000LL +#define XVPHY_HDMI_GTHE2_CPLL_REFCLK_MIN 80000000LL +#define XVPHY_HDMI_GTHE2_TX_MMCM_SCALE 1 +#define XVPHY_HDMI_GTHE2_TX_MMCM_FVCO_MIN 600000000U +#define XVPHY_HDMI_GTHE2_TX_MMCM_FVCO_MAX 1200000000U +#define XVPHY_HDMI_GTHE2_RX_MMCM_SCALE 1 +#define XVPHY_HDMI_GTHE2_RX_MMCM_FVCO_MIN 600000000U +#define XVPHY_HDMI_GTHE2_RX_MMCM_FVCO_MAX 1200000000U + +#define XVPHY_HDMI_GTXE2_DRU_LRATE 2000000000U +#define XVPHY_HDMI_GTXE2_DRU_REFCLK 125000000LL +#define XVPHY_HDMI_GTXE2_DRU_REFCLK_MIN 124990000LL +#define XVPHY_HDMI_GTXE2_DRU_REFCLK_MAX 125010000LL +#define XVPHY_HDMI_GTXE2_PLL_SCALE 1000 +#define XVPHY_HDMI_GTXE2_QPLL_REFCLK_MIN 74125000LL +#define XVPHY_HDMI_GTXE2_CPLL_REFCLK_MIN 80000000LL +#define XVPHY_HDMI_GTXE2_TX_MMCM_SCALE 1 +#define XVPHY_HDMI_GTXE2_TX_MMCM_FVCO_MIN 800000000U +#define XVPHY_HDMI_GTXE2_TX_MMCM_FVCO_MAX 1866000000U +#define XVPHY_HDMI_GTXE2_RX_MMCM_SCALE 1 +#define XVPHY_HDMI_GTXE2_RX_MMCM_FVCO_MIN 600000000U +#define XVPHY_HDMI_GTXE2_RX_MMCM_FVCO_MAX 1200000000U + +#define XVPHY_HDMI_GTPE2_DRU_LRATE 2500000000U +#define XVPHY_HDMI_GTPE2_DRU_REFCLK 100000000LL +#define XVPHY_HDMI_GTPE2_DRU_REFCLK_MIN 99990000LL +#define XVPHY_HDMI_GTPE2_DRU_REFCLK_MAX 100010000LL +#define XVPHY_HDMI_GTPE2_PLL_SCALE 1000 +#define XVPHY_HDMI_GTPE2_QPLL_REFCLK_MIN 80000000LL +#define XVPHY_HDMI_GTPE2_CPLL_REFCLK_MIN 80000000LL +#define XVPHY_HDMI_GTPE2_TX_MMCM_SCALE 1 +#define XVPHY_HDMI_GTPE2_TX_MMCM_FVCO_MIN 800000000U +#define XVPHY_HDMI_GTPE2_TX_MMCM_FVCO_MAX 1866000000U +#define XVPHY_HDMI_GTPE2_RX_MMCM_SCALE 1 +#define XVPHY_HDMI_GTPE2_RX_MMCM_FVCO_MIN 600000000U +#define XVPHY_HDMI_GTPE2_RX_MMCM_FVCO_MAX 1200000000U + +/**************************** Function Prototypes *****************************/ + +u32 XVphy_HdmiQpllParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir); +u32 XVphy_HdmiCpllParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir); +void XVphy_TxAlignReset(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 Reset); +void XVphy_TxAlignStart(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 Start); +void XVphy_ClkDetEnable(XVphy *InstancePtr, u8 Enable); +void XVphy_ClkDetTimerClear(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir); +void XVphy_ClkDetSetFreqLockThreshold(XVphy *InstancePtr, u16 ThresholdVal); +u8 XVphy_ClkDetCheckFreqZero(XVphy *InstancePtr, XVphy_DirectionType Dir); +void XVphy_ClkDetSetFreqTimeout(XVphy *InstancePtr, u32 TimeoutVal); +void XVphy_ClkDetTimerLoad(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, u32 TimeoutVal); +void XVphy_DruReset(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 Reset); +void XVphy_DruEnable(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 Enable); +u16 XVphy_DruGetVersion(XVphy *InstancePtr); +void XVphy_DruSetCenterFreqHz(XVphy *InstancePtr, XVphy_ChannelId ChId, + u64 CenterFreqHz); +void XVphy_DruSetGain(XVphy *InstancePtr, XVphy_ChannelId ChId, u8 G1, u8 G1_P, + u8 G2); +u64 XVphy_DruCalcCenterFreqHz(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId); +void XVphy_HdmiGtDruModeEnable(XVphy *InstancePtr, u8 Enable); +void XVphy_HdmiIntrHandlerCallbackInit(XVphy *InstancePtr); + +#endif /* XVPHY_HDMI_H_ */ +#endif diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_hdmi_intr.c b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_hdmi_intr.c new file mode 100644 index 00000000000000..9ba7e4bf65ff08 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_hdmi_intr.c @@ -0,0 +1,1153 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_hdmi_intr.c + * + * This file contains video PHY functionality specific to the HDMI protocol + * related to interrupts. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 gm 10/19/15 Initial release. + * 1.1 gm 02/01/16 Added GTPE2 and GTHE4 support + * Added XVphy_HdmiGtpPllLockHandler for GTPE2 + * 1.2 gm Replaced xil_printf with log events for debugging + * 1.3 gm 01/11/16 Fixed rounding of RX refclk frequency + * Fixed race condition in + * XVphy_HdmiRxClkDetFreqChangeHandler when storing + * RxRefClkHz value + * 1.4 gm 29/11/16 Added preprocessor directives for sw footprint reduction + * Incorporated AXIlite Freq auto extraction + * Added logging and register access for ERR_IRQ impl + * Added mechanism to re-trigger GT TX reset when TX align + * get stuck + * Fixed c++ compiler warnings + * </pre> + * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#if defined (XPAR_XV_HDMITX_0_DEVICE_ID) || defined (XPAR_XV_HDMIRX_0_DEVICE_ID) +#include "xstatus.h" +#include "xvphy.h" +#include "xvphy_i.h" +#include "xvphy_hdmi.h" +#include "xvphy_gt.h" + +/************************** Function Prototypes ******************************/ + +extern void XVphy_Ch2Ids(XVphy *InstancePtr, XVphy_ChannelId ChId, + u8 *Id0, u8 *Id1); + +static void XVphy_HdmiGtHandler(XVphy *InstancePtr); +static void XVphy_ClkDetHandler(XVphy *InstancePtr); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** +* This function installs an HDMI callback function for the specified handler +* type +* +* @param InstancePtr is a pointer to the XVPhy instance. +* @param HandlerType is the interrupt handler type which specifies which +* interrupt event to attach the callback for. +* @param CallbackFunc is the address to the callback function. +* @param CallbackRef is the user data item that will be passed to the +* callback function when it is invoked. +* +* @return None. +* +* @note None. +* +*******************************************************************************/ +void XVphy_SetHdmiCallback(XVphy *InstancePtr, + XVphy_HdmiHandlerType HandlerType, + void *CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((HandlerType == XVPHY_HDMI_HANDLER_TXINIT) || + (HandlerType == XVPHY_HDMI_HANDLER_TXREADY) || + (HandlerType == XVPHY_HDMI_HANDLER_RXINIT) || + (HandlerType == XVPHY_HDMI_HANDLER_RXREADY)); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + switch (HandlerType) { + case XVPHY_HDMI_HANDLER_TXINIT: + InstancePtr->HdmiTxInitCallback = (XVphy_Callback)CallbackFunc; + InstancePtr->HdmiTxInitRef = CallbackRef; + break; + + case XVPHY_HDMI_HANDLER_TXREADY: + InstancePtr->HdmiTxReadyCallback = (XVphy_Callback)CallbackFunc; + InstancePtr->HdmiTxReadyRef = CallbackRef; + break; + + case XVPHY_HDMI_HANDLER_RXINIT: + InstancePtr->HdmiRxInitCallback = (XVphy_Callback)CallbackFunc; + InstancePtr->HdmiRxInitRef = CallbackRef; + break; + + case XVPHY_HDMI_HANDLER_RXREADY: + InstancePtr->HdmiRxReadyCallback = (XVphy_Callback)CallbackFunc; + InstancePtr->HdmiRxReadyRef = CallbackRef; + break; + + default: + break; + } +} + +/*****************************************************************************/ +/** +* This function sets the appropriate HDMI interupt handlers. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiIntrHandlerCallbackInit(XVphy *InstancePtr) +{ + /* GT Interrupts */ + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_TXRESET_DONE, + (XVphy_IntrHandler)XVphy_HdmiGtHandler, InstancePtr); + + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_RXRESET_DONE, + (XVphy_IntrHandler)XVphy_HdmiGtHandler, InstancePtr); + + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_CPLL_LOCK, + (XVphy_IntrHandler)XVphy_HdmiGtHandler, InstancePtr); + + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_QPLL_LOCK, + (XVphy_IntrHandler)XVphy_HdmiGtHandler, InstancePtr); + + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_TXALIGN_DONE, + (XVphy_IntrHandler)XVphy_HdmiGtHandler, InstancePtr); + + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_QPLL1_LOCK, + (XVphy_IntrHandler)XVphy_HdmiGtHandler, InstancePtr); + + /* Clock Detector Interrupts */ + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE, + (XVphy_IntrHandler)XVphy_ClkDetHandler, InstancePtr); + + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE, + (XVphy_IntrHandler)XVphy_ClkDetHandler, InstancePtr); + + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT, + (XVphy_IntrHandler)XVphy_ClkDetHandler, InstancePtr); + + XVphy_SetIntrHandler(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT, + (XVphy_IntrHandler)XVphy_ClkDetHandler, InstancePtr); +} + +#if (XPAR_VPHY_0_TRANSCEIVER != XVPHY_GTPE2) +/*****************************************************************************/ +/** +* This function is the handler for events triggered by QPLL lock done. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiQpllLockHandler(XVphy *InstancePtr) +{ + XVphy_PllType TxPllType; + XVphy_PllType RxPllType; + u8 Id, Id0, Id1; + XVphy_ChannelId ChId; + + /* Determine PLL type. */ + TxPllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_TX, + XVPHY_CHANNEL_ID_CH1); + RxPllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_RX, + XVPHY_CHANNEL_ID_CH1); + + /* RX is using QPLL. */ + if ((RxPllType == XVPHY_PLL_TYPE_QPLL) || + (RxPllType == XVPHY_PLL_TYPE_QPLL0) || + (RxPllType == XVPHY_PLL_TYPE_QPLL1) || + (RxPllType == XVPHY_PLL_TYPE_PLL0) || + (RxPllType == XVPHY_PLL_TYPE_PLL1)) { + + /* Determine which channel(s) to operate on. */ + ChId = XVphy_GetRcfgChId(InstancePtr, 0, XVPHY_DIR_RX, RxPllType); + + if (XVphy_IsPllLocked(InstancePtr, 0, ChId) == XST_SUCCESS) { + /* Log, lock */ + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_QPLL_LOCK, 1); + + /* GT RX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, FALSE); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, + &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)]. + RxState = XVPHY_GT_STATE_RESET; + } + + /* If the GT TX and RX are coupled, then update the GT + * TX state as well. */ + if (XVphy_IsBonded(InstancePtr, 0, + XVPHY_CHANNEL_ID_CH1)) { + /* GT TX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, + XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, + &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[ + XVPHY_CH2IDX(Id)]. + TxState = XVPHY_GT_STATE_RESET; + } + } + } + else { + /* Log, Lost lock */ + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_QPLL_LOCK, 0); + } + } + /* TX is using QPLL. */ + else { + /* Determine which channel(s) to operate on. */ + ChId = XVphy_GetRcfgChId(InstancePtr, 0, XVPHY_DIR_TX, TxPllType); + + if (XVphy_IsPllLocked(InstancePtr, 0, ChId) == XST_SUCCESS) { + /* Log, lock */ + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_QPLL_LOCK, 1); + + /* GT TX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, FALSE); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, + &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)]. + TxState = XVPHY_GT_STATE_RESET; + } + } + else { + /* Log, Lost lock */ + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_QPLL_LOCK, 0); + } + } +} +#endif + +#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTPE2) +/*****************************************************************************/ +/** +* This function is the handler for events triggered by GTP PLL0/1 lock done. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiGtpPllLockHandler(XVphy *InstancePtr, u8 Pll) +{ + XVphy_PllType TxPllType; + XVphy_PllType RxPllType; + u8 Id, Id0, Id1; + XVphy_ChannelId ChId; + + /* Determine PLL type. */ + TxPllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_TX, + XVPHY_CHANNEL_ID_CH1); + RxPllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_RX, + XVPHY_CHANNEL_ID_CH1); + + /* RX is using QPLL. */ + if (((RxPllType == XVPHY_PLL_TYPE_PLL0) && (Pll == 0)) || + ((RxPllType == XVPHY_PLL_TYPE_PLL1) && (Pll == 1))) { + + /* Determine which channel(s) to operate on. */ + ChId = XVphy_GetRcfgChId(InstancePtr, 0, XVPHY_DIR_RX, RxPllType); + + if (XVphy_IsPllLocked(InstancePtr, 0, ChId) == XST_SUCCESS) { + /* Log, lock */ + XVphy_LogWrite(InstancePtr, (Pll == 0) ? + XVPHY_LOG_EVT_PLL0_LOCK : + XVPHY_LOG_EVT_PLL1_LOCK, 1); + + /* GT RX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, FALSE); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, + &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)]. + RxState = XVPHY_GT_STATE_RESET; + } + + /* If the GT TX and RX are coupled, then update the GT + * TX state as well. */ + if (XVphy_IsBonded(InstancePtr, 0, + XVPHY_CHANNEL_ID_CH1)) { + /* GT TX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, + XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, + &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[ + XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_RESET; + } + } + } + else { + /* Log, Lost lock */ + XVphy_LogWrite(InstancePtr, (Pll == 0) ? + XVPHY_LOG_EVT_PLL0_LOCK : + XVPHY_LOG_EVT_PLL1_LOCK, 0); + } + } + /* TX is using QPLL. */ + else { + /* Determine which channel(s) to operate on. */ + ChId = XVphy_GetRcfgChId(InstancePtr, 0, XVPHY_DIR_TX, TxPllType); + + if (XVphy_IsPllLocked(InstancePtr, 0, ChId) == XST_SUCCESS) { + /* Log, lock */ + XVphy_LogWrite(InstancePtr, (Pll == 0) ? + XVPHY_LOG_EVT_PLL0_LOCK : + XVPHY_LOG_EVT_PLL1_LOCK, 1); + + /* GT TX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, FALSE); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, + &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)]. + TxState = XVPHY_GT_STATE_RESET; + } + } + else { + /* Log, Lost lock */ + XVphy_LogWrite(InstancePtr, (Pll == 0) ? + XVPHY_LOG_EVT_PLL0_LOCK : + XVPHY_LOG_EVT_PLL1_LOCK, 0); + } + } +} +#endif + +#if (XPAR_VPHY_0_TRANSCEIVER != XVPHY_GTPE2) +/*****************************************************************************/ +/** +* This function is the handler for events triggered by CPLL lock done. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiCpllLockHandler(XVphy *InstancePtr) +{ + XVphy_PllType TxPllType; + XVphy_PllType RxPllType; + u8 Id, Id0, Id1; + XVphy_ChannelId ChId; + + /* Determine PLL type. */ + TxPllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_TX, + XVPHY_CHANNEL_ID_CH1); + RxPllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_RX, + XVPHY_CHANNEL_ID_CH1); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + + /* RX is using CPLL. */ + if (RxPllType == XVPHY_PLL_TYPE_CPLL) { + /* Determine which channel(s) to operate on. */ + ChId = XVphy_GetRcfgChId(InstancePtr, 0, XVPHY_DIR_RX, RxPllType); + + if (XVphy_IsPllLocked(InstancePtr, 0, ChId) == XST_SUCCESS) { + /* Log, lock */ + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_CPLL_LOCK, 1); + /* GT RX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, FALSE); + + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)]. + RxState = XVPHY_GT_STATE_RESET; + } + + /* If the GT TX and RX are coupled, then update the GT + * TX state as well. */ + if (XVphy_IsBonded(InstancePtr, 0, + XVPHY_CHANNEL_ID_CH1)) { + /* GT TX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, + XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[ + XVPHY_CH2IDX(Id)]. + TxState = XVPHY_GT_STATE_RESET; + } + } + } + else { + /* Log, Lost lock */ + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_CPLL_LOCK, 0); + } + } + /* TX is using CPLL. */ + else { + /* Determine which channel(s) to operate on. */ + ChId = XVphy_GetRcfgChId(InstancePtr, 0, XVPHY_DIR_TX, TxPllType); + + if (XVphy_IsPllLocked(InstancePtr, 0, ChId) == XST_SUCCESS) { + /* Log, lock */ + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_CPLL_LOCK, 1); + /* GT TX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, FALSE); + + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)]. + TxState = XVPHY_GT_STATE_RESET; + } + } + else { + /* Log, Lost lock */ + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_CPLL_LOCK, 0); + } + } +} +#endif + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by GT TX reset lock done. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiGtTxResetDoneLockHandler(XVphy *InstancePtr) +{ + u8 Id, Id0, Id1; + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_TX_RST_DONE, 0); + + if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE3) || + (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE4)) { + XVphy_TxAlignReset(InstancePtr, XVPHY_CHANNEL_ID_CHA, TRUE); + XVphy_TxAlignReset(InstancePtr, XVPHY_CHANNEL_ID_CHA, FALSE); + } + + /* GT alignment. */ + XVphy_TxAlignStart(InstancePtr, XVPHY_CHANNEL_ID_CHA, TRUE); + XVphy_TxAlignStart(InstancePtr, XVPHY_CHANNEL_ID_CHA, FALSE); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_READY; + + /* TX ready callback. */ + if (InstancePtr->HdmiTxReadyCallback) { + InstancePtr->HdmiTxReadyCallback( + InstancePtr->HdmiTxReadyRef); + } + } else { +#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTXE2) + XVphy_ClkDetTimerLoad(InstancePtr, 0, XVPHY_DIR_TX, + InstancePtr->Config.AxiLiteClkFreq/100); +#endif + + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_ALIGN; + } + } +} + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by GT TX alignment done. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiGtTxAlignDoneLockHandler(XVphy *InstancePtr) +{ + u8 Id, Id0, Id1; + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_TX_ALIGN, 1); + +#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTXE2) + /* Clear TX timer. */ + XVphy_ClkDetTimerClear(InstancePtr, 0, XVPHY_DIR_TX); +#endif + + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_READY; + } + + /* TX ready callback. */ + if (InstancePtr->HdmiTxReadyCallback) { + InstancePtr->HdmiTxReadyCallback(InstancePtr->HdmiTxReadyRef); + } +} + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by GT RX reset lock done. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiGtRxResetDoneLockHandler(XVphy *InstancePtr) +{ + u8 Id, Id0, Id1; + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_RX_RST_DONE, 0); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].RxState = + XVPHY_GT_STATE_READY; + } + + /* If DRU is use/d, release its reset. */ + if (InstancePtr->HdmiRxDruIsEnabled) { + XVphy_DruReset(InstancePtr, XVPHY_CHANNEL_ID_CHA, FALSE); + } + + /* RX ready callback. */ + if (InstancePtr->HdmiRxReadyCallback) { + InstancePtr->HdmiRxReadyCallback(InstancePtr->HdmiRxReadyRef); + } + + /* If the GT TX and RX are coupled, then update the GT TX state + * as well. */ + if (XVphy_IsBonded(InstancePtr, 0, XVPHY_CHANNEL_ID_CH1)) { + /* GT TX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, FALSE); + + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_RESET; + } + } +} + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by a change in TX frequency +* as detected by the HDMI clock detector logic. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiTxClkDetFreqChangeHandler(XVphy *InstancePtr) +{ + XVphy_PllType PllType; + u8 Id, Id0, Id1; + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_TX_FREQ, 0); + + /* Determine PLL type. */ + PllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_TX, + XVPHY_CHANNEL_ID_CH1); + + /* Assert GT TX reset. */ + if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) || + (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2)) { + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + } + + /* If the TX frequency has changed, the PLL is always disabled. */ + if (InstancePtr->Config.XcvrType != XVPHY_GT_TYPE_GTPE2) { + XVphy_PowerDownGtPll(InstancePtr, 0, + (PllType == XVPHY_PLL_TYPE_CPLL) ? + XVPHY_CHANNEL_ID_CHA : XVPHY_CHANNEL_ID_CMNA, TRUE); + } + XVphy_ResetGtPll(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_TX, + TRUE); + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + XVphy_GtUserRdyEnable(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, FALSE); + } + + /* Mask the MMCM Lock */ + XVphy_MmcmLockedMaskEnable(InstancePtr, 0, XVPHY_DIR_TX, TRUE); + + /* Disable TX MMCM. */ + //XVphy_MmcmPowerDown(InstancePtr, 0, XVPHY_DIR_TX, TRUE); + + /* Clear TX timer. */ + XVphy_ClkDetTimerClear(InstancePtr, 0, XVPHY_DIR_TX); + + /* Clear GT alignment. */ + XVphy_TxAlignStart(InstancePtr, XVPHY_CHANNEL_ID_CHA, FALSE); + + /* De-assert GT TX reset. */ + if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) || + (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2)) { + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, FALSE); + } + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_IDLE; + } + + /* If there is no reference clock, load TX timer in usec. */ + if (XVphy_ClkDetGetRefClkFreqHz(InstancePtr, XVPHY_DIR_TX)) { + XVphy_ClkDetTimerLoad(InstancePtr, 0, XVPHY_DIR_TX, + InstancePtr->Config.AxiLiteClkFreq/1000); + } + + /* Callback to re-initialize. */ + if (InstancePtr->HdmiTxInitCallback) { + InstancePtr->HdmiTxInitCallback(InstancePtr->HdmiTxInitRef); + } +} + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by a change in RX frequency +* as detected by the HDMI clock detector logic. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiRxClkDetFreqChangeHandler(XVphy *InstancePtr) +{ + XVphy_PllType PllType; + u32 RxRefClkHz; + u8 Id, Id0, Id1; + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_RX_FREQ, 0); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].RxState = + XVPHY_GT_STATE_IDLE; + } + + /* Mask the MMCM Lock */ + XVphy_MmcmLockedMaskEnable(InstancePtr, 0, XVPHY_DIR_RX, TRUE); + + /* Determine PLL type and RX reference clock selection. */ + PllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_RX, + XVPHY_CHANNEL_ID_CH1); + + /* Fetch New RX Reference Clock Frequency */ + RxRefClkHz = XVphy_ClkDetGetRefClkFreqHz(InstancePtr, XVPHY_DIR_RX); + + /* Round input frequency to 10 kHz. */ + RxRefClkHz = (RxRefClkHz+5000) / 10000; + RxRefClkHz = RxRefClkHz * 10000; + + /* Store RX reference clock. */ + InstancePtr->HdmiRxRefClkHz = RxRefClkHz; + + /* If the RX frequency has changed, the PLL is always disabled. */ + if (InstancePtr->Config.XcvrType != XVPHY_GT_TYPE_GTPE2) { + XVphy_PowerDownGtPll(InstancePtr, 0, + (PllType == XVPHY_PLL_TYPE_CPLL) ? + XVPHY_CHANNEL_ID_CHA : XVPHY_CHANNEL_ID_CMNA, TRUE); + } + + XVphy_ResetGtPll(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX, + TRUE); + + /* When the GT TX and RX are coupled, then disable the QPLL. */ + if (XVphy_IsBonded(InstancePtr, 0, XVPHY_CHANNEL_ID_CH1)) { + XVphy_PowerDownGtPll(InstancePtr, 0, + (PllType == XVPHY_PLL_TYPE_CPLL) ? + XVPHY_CHANNEL_ID_CMNA : XVPHY_CHANNEL_ID_CHA, TRUE); + XVphy_ResetGtPll(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, 1); +// if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { +// XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, +// XVPHY_DIR_TX, TRUE); +// } + + } + + /* Disable RX MMCM */ + //XVphy_MmcmPowerDown(InstancePtr, 0, XVPHY_DIR_RX, TRUE); + /* When the GT TX and RX are coupled, then disable the TX MMCM. */ + //if (XVphy_IsBonded(InstancePtr, 0, XVPHY_CHANNEL_ID_CH1)) { + // XVphy_MmcmPowerDown(InstancePtr, 0, XVPHY_DIR_TX, TRUE); + //} + + /* Assert GT RX reset */ + if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) || + (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2)) { + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, FALSE); + } + + /* If DRU is present, disable it and assert reset. */ + if (InstancePtr->Config.DruIsPresent) { + XVphy_DruReset(InstancePtr, XVPHY_CHANNEL_ID_CHA, TRUE); + XVphy_DruEnable(InstancePtr, XVPHY_CHANNEL_ID_CHA, FALSE); + } + + /* Clear RX timer. */ + XVphy_ClkDetTimerClear(InstancePtr, 0, XVPHY_DIR_RX); + + /* If there is reference clock, load RX timer in usec. + * The reference clock should be larger than 25Mhz. We are using a 20Mhz + * instead to keep some margin for errors. */ + if (RxRefClkHz > 20000000) { + XVphy_ClkDetTimerLoad(InstancePtr, 0, XVPHY_DIR_RX, + InstancePtr->Config.AxiLiteClkFreq/1000); + + /* Callback to re-initialize. */ + if (InstancePtr->HdmiRxInitCallback) { + InstancePtr->HdmiRxInitCallback(InstancePtr->HdmiRxInitRef); + } + } +} + +/*****************************************************************************/ +/** +* This function is the handler for TX timer timeout events. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiTxTimerTimeoutHandler(XVphy *InstancePtr) +{ + XVphy_ChannelId ChId; + XVphy_PllType PllType; + u8 Id, Id0, Id1; + +#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTXE2) + /* Check if timer timed out while waiting for TX Alignment + * If yes, reset the GT TX + */ + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + if (InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id0)].TxState == + XVPHY_GT_STATE_ALIGN) { + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_TX_ALIGN_TMOUT, 1); + /* GT TX reset. */ + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, FALSE); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, + &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)]. + TxState = XVPHY_GT_STATE_RESET; + } + return; + } +#endif + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_TX_TMR, 1); + + /* Determine PLL type. */ + PllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_TX, + XVPHY_CHANNEL_ID_CH1); + /* Determine which channel(s) to operate on. */ + ChId = XVphy_GetRcfgChId(InstancePtr, 0, XVPHY_DIR_TX, PllType); + + /* Start TX MMCM. */ + XVphy_MmcmStart(InstancePtr, 0, XVPHY_DIR_TX); + + /* Enable PLL. */ + if (InstancePtr->Config.XcvrType != XVPHY_GT_TYPE_GTPE2) { + XVphy_PowerDownGtPll(InstancePtr, 0, + (PllType == XVPHY_PLL_TYPE_CPLL) ? + XVPHY_CHANNEL_ID_CHA : XVPHY_CHANNEL_ID_CMNA, FALSE); + } + + if (PllType != XVPHY_PLL_TYPE_CPLL) { + /* Set QPLL Selection in PIO. */ + XVphy_WriteCfgRefClkSelReg(InstancePtr, 0); + } + + XVphy_ClkReconfig(InstancePtr, 0, ChId); + XVphy_OutDivReconfig(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX); + if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE3) || + (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE4)) { + XVphy_SetBufgGtDiv(InstancePtr, XVPHY_DIR_TX, + (PllType == XVPHY_PLL_TYPE_CPLL) ? + InstancePtr->Quads[0].Plls[0].TxOutDiv : + InstancePtr->Quads[0].Plls[0].TxOutDiv / 2); + } + XVphy_DirReconfig(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_TX); + + /* Assert PLL reset. */ + XVphy_ResetGtPll(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + + /* Assert GT TX reset. */ + if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) || + (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2)) { + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, TRUE); + } + + /* De-assert PLL reset. */ + XVphy_ResetGtPll(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, FALSE); + + if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE3) || + (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE4)) { + /* Clear GT alignment. */ + XVphy_TxAlignStart(InstancePtr, ChId, FALSE); + } + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].TxState = + XVPHY_GT_STATE_LOCK; + } +} + +/*****************************************************************************/ +/** +* This function is the handler for RX timer timeout events. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiRxTimerTimeoutHandler(XVphy *InstancePtr) +{ + XVphy_ChannelId ChId; + XVphy_PllType PllType; + u32 Status; + u8 Id, Id0, Id1; + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_RX_TMR, 1); + + /* Determine PLL type. */ + PllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_RX, + XVPHY_CHANNEL_ID_CH1); + /* Determine which channel(s) to operate on. */ + ChId = XVphy_GetRcfgChId(InstancePtr, 0, XVPHY_DIR_RX, PllType); + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + + /* Set RX parameters. */ + Status = XVphy_SetHdmiRxParam(InstancePtr, 0, ChId); + if (Status != XST_SUCCESS) { + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_GT_PLL_LAYOUT, 1); + XVphy_CfgErrIntr(InstancePtr, XVPHY_ERRIRQ_PLL_LAYOUT, 1); + } + + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].RxState = + XVPHY_GT_STATE_IDLE; + if (XVphy_IsBonded(InstancePtr, 0, + XVPHY_CHANNEL_ID_CH1)) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)]. + TxState = XVPHY_GT_STATE_IDLE; + } + } + + return; + } + else { + XVphy_CfgErrIntr(InstancePtr, XVPHY_ERRIRQ_PLL_LAYOUT, 0); + } + + /* Enable PLL. */ + if (InstancePtr->Config.XcvrType != XVPHY_GT_TYPE_GTPE2) { + XVphy_PowerDownGtPll(InstancePtr, 0, + (PllType == XVPHY_PLL_TYPE_CPLL) ? + XVPHY_CHANNEL_ID_CHA : XVPHY_CHANNEL_ID_CMNA, FALSE); + } + + /* Enable DRU to set the clock muxes. */ + XVphy_DruEnable(InstancePtr, XVPHY_CHANNEL_ID_CHA, + InstancePtr->HdmiRxDruIsEnabled); + + /* Update reference clock election. */ + if (InstancePtr->Config.XcvrType != XVPHY_GT_TYPE_GTPE2) { + XVphy_CfgPllRefClkSel(InstancePtr, 0, + ((PllType == XVPHY_PLL_TYPE_CPLL) ? + XVPHY_CHANNEL_ID_CHA : XVPHY_CHANNEL_ID_CMNA), + ((InstancePtr->HdmiRxDruIsEnabled) ? + InstancePtr->Config.DruRefClkSel : + InstancePtr->Config.RxRefClkSel)); + } + /* GTP */ + else { + XVphy_CfgPllRefClkSel(InstancePtr, 0, + ((PllType == XVPHY_PLL_TYPE_PLL0) ? + XVPHY_CHANNEL_ID_CMN0 : XVPHY_CHANNEL_ID_CMN1), + ((InstancePtr->HdmiRxDruIsEnabled) ? + InstancePtr->Config.DruRefClkSel : + InstancePtr->Config.RxRefClkSel)); + } + + /* Update GT DRU mode. */ + XVphy_HdmiGtDruModeEnable(InstancePtr, InstancePtr->HdmiRxDruIsEnabled); + + /* Update RefClk selection. */ + XVphy_WriteCfgRefClkSelReg(InstancePtr, 0); + + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2) { + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, TRUE); + /* GTP Wizard locks the DRP access to its internal FSM during reset */ + /* Wait for reset sequence to release DRP port. */ + XVphy_WaitUs(InstancePtr, 5000); + } + + /* Determine PLL type. */ + PllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_RX, + XVPHY_CHANNEL_ID_CH1); + /* Determine which channel(s) to operate on. */ + ChId = XVphy_GetRcfgChId(InstancePtr, 0, XVPHY_DIR_RX, PllType); + + XVphy_ClkReconfig(InstancePtr, 0, ChId); + XVphy_OutDivReconfig(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX); + if (XVphy_IsBonded(InstancePtr, 0, XVPHY_CHANNEL_ID_CH1)) { + XVphy_OutDivReconfig(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX); + } + + XVphy_DirReconfig(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX); + + /* Assert RX PLL reset. */ + XVphy_ResetGtPll(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, XVPHY_DIR_RX, + TRUE); + + if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTXE2) { + XVphy_ResetGtTxRx(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, TRUE); + } + + /* De-assert RX PLL reset. */ + XVphy_ResetGtPll(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_RX, FALSE); + + /* When the TX and RX are coupled, clear GT alignment. */ + if (XVphy_IsBonded(InstancePtr, 0, XVPHY_CHANNEL_ID_CH1)) { + if (InstancePtr->HdmiRxDruIsEnabled) { + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_GT_UNBONDED, 1); + XVphy_CfgErrIntr(InstancePtr, XVPHY_ERRIRQ_PLL_LAYOUT, 1); + } + else { + XVphy_CfgErrIntr(InstancePtr, XVPHY_ERRIRQ_PLL_LAYOUT, 0); + } + XVphy_ResetGtPll(InstancePtr, 0, XVPHY_CHANNEL_ID_CHA, + XVPHY_DIR_TX, 0); + XVphy_TxAlignStart(InstancePtr, ChId, FALSE); + } + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XVPHY_CH2IDX(Id)].RxState = + XVPHY_GT_STATE_LOCK; + } +} + +/*****************************************************************************/ +/** +* This function is the interrupt handler for the GT events. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiGtHandler(XVphy *InstancePtr) +{ + u32 Event; + u32 EventMask; + u32 EventAck; + XVphy_GtState *TxStatePtr; + XVphy_GtState *RxStatePtr; + + EventMask = XVPHY_INTR_QPLL0_LOCK_MASK | XVPHY_INTR_CPLL_LOCK_MASK | + XVPHY_INTR_QPLL1_LOCK_MASK | XVPHY_INTR_TXRESETDONE_MASK | + XVPHY_INTR_TXALIGNDONE_MASK | XVPHY_INTR_RXRESETDONE_MASK; + + u8 QuadId = 0; + + /* Read Interrupt Status register */ + Event = XVphy_ReadReg(InstancePtr->Config.BaseAddr, XVPHY_INTR_STS_REG); + + EventAck = EventMask & Event; + + /* Read States for Quad=0 Ch1 */ + TxStatePtr = &InstancePtr->Quads[QuadId].Ch1.TxState; + RxStatePtr = &InstancePtr->Quads[QuadId].Ch1.RxState; + + if ((Event & XVPHY_INTR_QPLL0_LOCK_MASK) || + (Event & XVPHY_INTR_QPLL1_LOCK_MASK)) { +#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTPE2) + if (Event & XVPHY_INTR_QPLL0_LOCK_MASK) { /* PLL0. */ + XVphy_HdmiGtpPllLockHandler(InstancePtr, 0); + } + if (Event & XVPHY_INTR_QPLL1_LOCK_MASK) { /* PLL1. */ + XVphy_HdmiGtpPllLockHandler(InstancePtr, 1); + } +#else + XVphy_HdmiQpllLockHandler(InstancePtr); +#endif + } +#if (XPAR_VPHY_0_TRANSCEIVER != XVPHY_GTPE2) + if (Event & XVPHY_INTR_CPLL_LOCK_MASK) { + XVphy_HdmiCpllLockHandler(InstancePtr); + } +#endif + if ((Event & XVPHY_INTR_TXRESETDONE_MASK) + && (*TxStatePtr == XVPHY_GT_STATE_RESET)) { + XVphy_HdmiGtTxResetDoneLockHandler(InstancePtr); + } + if ((Event & XVPHY_INTR_TXALIGNDONE_MASK) + && (*TxStatePtr == XVPHY_GT_STATE_ALIGN)) { + XVphy_HdmiGtTxAlignDoneLockHandler(InstancePtr); + } + if ((Event & XVPHY_INTR_RXRESETDONE_MASK) + && (*RxStatePtr == XVPHY_GT_STATE_RESET)) { + XVphy_HdmiGtRxResetDoneLockHandler(InstancePtr); + } + + /* Clear event flags by writing to Interrupt Status register */ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_INTR_STS_REG, + EventAck); +} + +/*****************************************************************************/ +/** +* This function is the interrupt handler for the clock detector events. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_ClkDetHandler(XVphy *InstancePtr) +{ + u32 Event; + u32 EventMask; + u32 EventAck; + + EventMask = XVPHY_INTR_TXCLKDETFREQCHANGE_MASK | + XVPHY_INTR_RXCLKDETFREQCHANGE_MASK | + XVPHY_INTR_TXTMRTIMEOUT_MASK | + XVPHY_INTR_RXTMRTIMEOUT_MASK; + + /* Read Interrupt Status register */ + Event = XVphy_ReadReg(InstancePtr->Config.BaseAddr, XVPHY_INTR_STS_REG); + + EventAck = EventMask & Event; + + if (Event & XVPHY_INTR_TXCLKDETFREQCHANGE_MASK) { + XVphy_HdmiTxClkDetFreqChangeHandler(InstancePtr); + } + if (Event & XVPHY_INTR_RXCLKDETFREQCHANGE_MASK) { + XVphy_HdmiRxClkDetFreqChangeHandler(InstancePtr); + } + if (Event & XVPHY_INTR_TXTMRTIMEOUT_MASK) { + XVphy_HdmiTxTimerTimeoutHandler(InstancePtr); + } + if (Event & XVPHY_INTR_RXTMRTIMEOUT_MASK) { + XVphy_HdmiRxTimerTimeoutHandler(InstancePtr); + } + + /* Clear event flags by writing to Interrupt Status register */ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_INTR_STS_REG, + EventAck); +} +#endif diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_hw.h b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_hw.h new file mode 100644 index 00000000000000..6e06e8dc902ae2 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_hw.h @@ -0,0 +1,567 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_hw.h + * + * This header file contains the identifiers and low-level driver functions (or + * macros) that can be used to access the device. High-level driver functions + * are defined in xvphy.h. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 10/19/15 Initial release. + * 1.1 gm 02/01/16 Added GTPE2 and GTHE4 support + * 1.4 gm 29/11/16 Added ERR_IRQ register offset + * </pre> + * +*******************************************************************************/ + +#ifndef XVPHY_HW_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XVPHY_HW_H_ + +/***************************** Include Files **********************************/ + +#include "xil_io.h" +#include "xil_types.h" + +/************************** Constant Definitions ******************************/ + +/******************************************************************************/ +/** + * Address mapping for the Video PHY core. + * +*******************************************************************************/ +/** @name VPHY core registers: General registers. + * @{ + */ +#define XVPHY_VERSION_REG 0x000 +#define XVPHY_BANK_SELECT_REG 0x00C +#define XVPHY_REF_CLK_SEL_REG 0x010 +#define XVPHY_PLL_RESET_REG 0x014 +#define XVPHY_PLL_LOCK_STATUS_REG 0x018 +#define XVPHY_TX_INIT_REG 0x01C +#define XVPHY_TX_INIT_STATUS_REG 0x020 +#define XVPHY_RX_INIT_REG 0x024 +#define XVPHY_RX_INIT_STATUS_REG 0x028 +#define XVPHY_IBUFDS_GTXX_CTRL_REG 0x02C +#define XVPHY_POWERDOWN_CONTROL_REG 0x030 +#define XVPHY_LOOPBACK_CONTROL_REG 0x038 +/* @} */ + +/** @name VPHY core registers: Dynamic reconfiguration port (DRP) registers. + * @{ + */ +#define XVPHY_DRP_CONTROL_CH1_REG 0x040 +#define XVPHY_DRP_CONTROL_CH2_REG 0x044 +#define XVPHY_DRP_CONTROL_CH3_REG 0x048 +#define XVPHY_DRP_CONTROL_CH4_REG 0x04C +#define XVPHY_DRP_STATUS_CH1_REG 0x050 +#define XVPHY_DRP_STATUS_CH2_REG 0x054 +#define XVPHY_DRP_STATUS_CH3_REG 0x058 +#define XVPHY_DRP_STATUS_CH4_REG 0x05C +#define XVPHY_DRP_CONTROL_COMMON_REG 0x060 +#define XVPHY_DRP_STATUS_COMMON_REG 0x064 +/* @} */ + +/** @name VPHY core registers: Transmitter function registers. + * @{ + */ +#define XVPHY_TX_CONTROL_REG 0x070 +#define XVPHY_TX_BUFFER_BYPASS_REG 0x074 +#define XVPHY_TX_STATUS_REG 0x078 +#define XVPHY_TX_DRIVER_CH12_REG 0x07C +#define XVPHY_TX_DRIVER_CH34_REG 0x080 +/* @} */ + +/** @name VPHY core registers: Receiver function registers. + * @{ + */ +#define XVPHY_RX_CONTROL_REG 0x100 +#define XVPHY_RX_STATUS_REG 0x104 +#define XVPHY_RX_EQ_CDR_REG 0x108 +#define XVPHY_RX_TDLOCK_REG 0x10C +/* @} */ + +/** @name VPHY core registers: Interrupt registers. + * @{ + */ +#define XVPHY_ERR_IRQ 0x03C +#define XVPHY_INTR_EN_REG 0x110 +#define XVPHY_INTR_DIS_REG 0x114 +#define XVPHY_INTR_MASK_REG 0x118 +#define XVPHY_INTR_STS_REG 0x11C +/* @} */ + +/** @name User clocking registers: MMCM and BUFGGT registers. + * @{ + */ +#define XVPHY_MMCM_TXUSRCLK_CTRL_REG 0x0120 +#define XVPHY_MMCM_TXUSRCLK_REG1 0x0124 +#define XVPHY_MMCM_TXUSRCLK_REG2 0x0128 +#define XVPHY_MMCM_TXUSRCLK_REG3 0x012C +#define XVPHY_MMCM_TXUSRCLK_REG4 0x0130 +#define XVPHY_BUFGGT_TXUSRCLK_REG 0x0134 +#define XVPHY_MISC_TXUSRCLK_REG 0x0138 + +#define XVPHY_MMCM_RXUSRCLK_CTRL_REG 0x0140 +#define XVPHY_MMCM_RXUSRCLK_REG1 0x0144 +#define XVPHY_MMCM_RXUSRCLK_REG2 0x0148 +#define XVPHY_MMCM_RXUSRCLK_REG3 0x014C +#define XVPHY_MMCM_RXUSRCLK_REG4 0x0150 +#define XVPHY_BUFGGT_RXUSRCLK_REG 0x0154 +#define XVPHY_MISC_RXUSRCLK_REG 0x0158 +/* @} */ + +/** @name Clock detector (HDMI) registers. + * @{ + */ +#define XVPHY_CLKDET_CTRL_REG 0x0200 +#define XVPHY_CLKDET_STAT_REG 0x0204 +#define XVPHY_CLKDET_FREQ_TMR_TO_REG 0x0208 +#define XVPHY_CLKDET_FREQ_TX_REG 0x020C +#define XVPHY_CLKDET_FREQ_RX_REG 0x0210 +#define XVPHY_CLKDET_TMR_TX_REG 0x0214 +#define XVPHY_CLKDET_TMR_RX_REG 0x0218 +#define XVPHY_CLKDET_FREQ_DRU_REG 0x021C +/* @} */ + +/** @name Data recovery unit registers (HDMI). + * @{ + */ +#define XVPHY_DRU_CTRL_REG 0x0300 +#define XVPHY_DRU_STAT_REG 0x0304 + +#define XVPHY_DRU_CFREQ_L_REG(Ch) (0x0308 + (12 * (Ch - 1))) +#define XVPHY_DRU_CFREQ_H_REG(Ch) (0x030C + (12 * (Ch - 1))) +#define XVPHY_DRU_GAIN_REG(Ch) (0x0310 + (12 * (Ch - 1))) +/* @} */ + +/******************************************************************************/ + +/** @name VPHY core masks, shifts, and register values. + * @{ + */ +/* 0x0F8: VERSION */ +#define XVPHY_VERSION_INTER_REV_MASK \ + 0x000000FF /**< Internal revision. */ +#define XVPHY_VERSION_CORE_PATCH_MASK \ + 0x00000F00 /**< Core patch details. */ +#define XVPHY_VERSION_CORE_PATCH_SHIFT 8 /**< Shift bits for core patch + details. */ +#define XVPHY_VERSION_CORE_VER_REV_MASK \ + 0x0000F000 /**< Core version revision. */ +#define XVPHY_VERSION_CORE_VER_REV_SHIFT 12 /**< Shift bits for core version + revision. */ +#define XVPHY_VERSION_CORE_VER_MNR_MASK \ + 0x00FF0000 /**< Core minor version. */ +#define XVPHY_VERSION_CORE_VER_MNR_SHIFT 16 /**< Shift bits for core minor + version. */ +#define XVPHY_VERSION_CORE_VER_MJR_MASK \ + 0xFF000000 /**< Core major version. */ +#define XVPHY_VERSION_CORE_VER_MJR_SHIFT 24 /**< Shift bits for core major + version. */ +/* 0x00C: BANK_SELECT_REG */ +#define XVPHY_BANK_SELECT_TX_MASK 0x00F +#define XVPHY_BANK_SELECT_RX_MASK 0xF00 +#define XVPHY_BANK_SELECT_RX_SHIFT 8 +/* 0x010: REF_CLK_SEL */ +#define XVPHY_REF_CLK_SEL_QPLL0_MASK 0x0000000F +#define XVPHY_REF_CLK_SEL_CPLL_MASK 0x000000F0 +#define XVPHY_REF_CLK_SEL_CPLL_SHIFT 4 +#define XVPHY_REF_CLK_SEL_QPLL1_MASK 0x00000F00 +#define XVPHY_REF_CLK_SEL_QPLL1_SHIFT 8 +#define XVPHY_REF_CLK_SEL_XPLL_GTREFCLK0 1 +#define XVPHY_REF_CLK_SEL_XPLL_GTREFCLK1 2 +#define XVPHY_REF_CLK_SEL_XPLL_GTNORTHREFCLK0 3 +#define XVPHY_REF_CLK_SEL_XPLL_GTNORTHREFCLK1 4 +#define XVPHY_REF_CLK_SEL_XPLL_GTSOUTHREFCLK0 5 +#define XVPHY_REF_CLK_SEL_XPLL_GTSOUTHREFCLK1 6 +#define XVPHY_REF_CLK_SEL_XPLL_GTEASTREFCLK0 3 +#define XVPHY_REF_CLK_SEL_XPLL_GTEASTREFCLK1 4 +#define XVPHY_REF_CLK_SEL_XPLL_GTWESTREFCLK0 5 +#define XVPHY_REF_CLK_SEL_XPLL_GTWESTREFCLK1 6 +#define XVPHY_REF_CLK_SEL_XPLL_GTGREFCLK 7 +#define XVPHY_REF_CLK_SEL_SYSCLKSEL_MASK 0x0F000000 +#define XVPHY_REF_CLK_SEL_SYSCLKSEL_SHIFT 24 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_PLL0 0 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_PLL1 1 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_CPLL 0 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL 1 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL0 3 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL1 2 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CH 0 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN 1 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN0 2 +#define XVPHY_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN1 3 +#define XVPHY_REF_CLK_SEL_RXSYSCLKSEL_OUT_MASK(G) \ + ((((G) == XVPHY_GT_TYPE_GTHE3) || \ + ((G) == XVPHY_GT_TYPE_GTHE4)) ? 0x03000000 : 0x02000000) +#define XVPHY_REF_CLK_SEL_TXSYSCLKSEL_OUT_MASK(G) \ + ((((G) == XVPHY_GT_TYPE_GTHE3) || \ + ((G) == XVPHY_GT_TYPE_GTHE4)) ? 0x0C000000 : 0x08000000) +#define XVPHY_REF_CLK_SEL_RXSYSCLKSEL_DATA_MASK(G) \ + ((((G) == XVPHY_GT_TYPE_GTHE3) || \ + ((G) == XVPHY_GT_TYPE_GTHE4)) ? 0x30000000 : 0x01000000) +#define XVPHY_REF_CLK_SEL_TXSYSCLKSEL_DATA_MASK(G) \ + ((((G) == XVPHY_GT_TYPE_GTHE3) || \ + ((G) == XVPHY_GT_TYPE_GTHE4)) ? 0xC0000000 : 0x04000000) +#define XVPHY_REF_CLK_SEL_RXSYSCLKSEL_OUT_SHIFT(G) \ + ((((G) == XVPHY_GT_TYPE_GTHE3) || \ + ((G) == XVPHY_GT_TYPE_GTHE4)) ? 24 : 25) +#define XVPHY_REF_CLK_SEL_TXSYSCLKSEL_OUT_SHIFT(G) \ + ((((G) == XVPHY_GT_TYPE_GTHE3) || \ + ((G) == XVPHY_GT_TYPE_GTHE4)) ? 26 : 27) +#define XVPHY_REF_CLK_SEL_RXSYSCLKSEL_DATA_SHIFT(G) \ + ((((G) == XVPHY_GT_TYPE_GTHE3) || \ + ((G) == XVPHY_GT_TYPE_GTHE4)) ? 28 : 24) +#define XVPHY_REF_CLK_SEL_TXSYSCLKSEL_DATA_SHIFT(G) \ + ((((G) == XVPHY_GT_TYPE_GTHE3) || \ + ((G) == XVPHY_GT_TYPE_GTHE4)) ? 30 : 26) +/* 0x014: PLL_RESET */ +#define XVPHY_PLL_RESET_CPLL_MASK 0x1 +#define XVPHY_PLL_RESET_QPLL0_MASK 0x2 +#define XVPHY_PLL_RESET_QPLL1_MASK 0x4 +/* 0x018: PLL_LOCK_STATUS */ +#define XVPHY_PLL_LOCK_STATUS_CPLL_MASK(Ch) \ + (0x01 << (Ch - 1)) +#define XVPHY_PLL_LOCK_STATUS_QPLL0_MASK 0x10 +#define XVPHY_PLL_LOCK_STATUS_QPLL1_MASK 0x20 +#define XVPHY_PLL_LOCK_STATUS_CPLL_ALL_MASK \ + (XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_PLL_LOCK_STATUS_CPLL_HDMI_MASK \ + (XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_PLL_LOCK_STATUS_CPLL_MASK(XVPHY_CHANNEL_ID_CH3)) +/* 0x01C, 0x024: TX_INIT, RX_INIT */ +#define XVPHY_TXRX_INIT_GTRESET_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_PMARESET_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_PCSRESET_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_TX_INIT_USERRDY_MASK(Ch) \ + (0x08 << (8 * (Ch - 1))) +#define XVPHY_RX_INIT_USERRDY_MASK(Ch) \ + (0x40 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_PLLGTRESET_MASK(Ch) \ + (0x80 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_GTRESET_ALL_MASK \ + (XVPHY_TXRX_INIT_GTRESET_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TXRX_INIT_GTRESET_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TXRX_INIT_GTRESET_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TXRX_INIT_GTRESET_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_TX_INIT_USERRDY_ALL_MASK \ + (XVPHY_TX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_RX_INIT_USERRDY_ALL_MASK \ + (XVPHY_RX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_RX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_RX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_RX_INIT_USERRDY_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_TXRX_INIT_PLLGTRESET_ALL_MASK \ + (XVPHY_TXRX_INIT_PLLGTRESET_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TXRX_INIT_PLLGTRESET_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TXRX_INIT_PLLGTRESET_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TXRX_INIT_PLLGTRESET_MASK(XVPHY_CHANNEL_ID_CH4)) +/* 0x020, 0x028: TX_STATUS, RX_STATUS */ +#define XVPHY_TXRX_INIT_STATUS_RESETDONE_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_STATUS_PMARESETDONE_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_STATUS_POWERGOOD_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_TXRX_INIT_STATUS_RESETDONE_ALL_MASK \ + (XVPHY_TXRX_INIT_STATUS_RESETDONE_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TXRX_INIT_STATUS_RESETDONE_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TXRX_INIT_STATUS_RESETDONE_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TXRX_INIT_STATUS_RESETDONE_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_TXRX_INIT_STATUS_PMARESETDONE_ALL_MASK \ + (XVPHY_TXRX_INIT_STATUS_PMARESETDONE_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TXRX_INIT_STATUS_PMARESETDONE_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TXRX_INIT_STATUS_PMARESETDONE_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TXRX_INIT_STATUS_PMARESETDONE_MASK(XVPHY_CHANNEL_ID_CH4)) +/* 0x02C: IBUFDS_GTXX_CTRL */ +#define XVPHY_IBUFDS_GTXX_CTRL_GTREFCLK0_CEB_MASK 0x1 +#define XVPHY_IBUFDS_GTXX_CTRL_GTREFCLK1_CEB_MASK 0x2 +/* 0x030: POWERDOWN_CONTROL */ +#define XVPHY_POWERDOWN_CONTROL_CPLLPD_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_QPLL0PD_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_QPLL1PD_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_RXPD_MASK(Ch) \ + (0x18 << (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_RXPD_SHIFT(Ch) \ + (3 + (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_TXPD_MASK(Ch) \ + (0x60 << (8 * (Ch - 1))) +#define XVPHY_POWERDOWN_CONTROL_TXPD_SHIFT(Ch) \ + (5 + (8 * (Ch - 1))) +/* 0x038: LOOPBACK_CONTROL */ +#define XVPHY_LOOPBACK_CONTROL_CH_MASK(Ch) \ + (0x03 << (8 * (Ch - 1))) +#define XVPHY_LOOPBACK_CONTROL_CH_SHIFT(Ch) \ + (8 * (Ch - 1)) +/* 0x040, 0x044, 0x048, 0x04C, 0x060: DRP_CONTROL_CH[1-4], DRP_CONTROL_COMMON */ +#define XVPHY_DRP_CONTROL_DRPADDR_MASK 0x00000FFF +#define XVPHY_DRP_CONTROL_DRPEN_MASK 0x00001000 +#define XVPHY_DRP_CONTROL_DRPWE_MASK 0x00002000 +#define XVPHY_DRP_CONTROL_DRPRESET_MASK 0x00004000 +#define XVPHY_DRP_CONTROL_DRPDI_MASK 0xFFFF0000 +#define XVPHY_DRP_CONTROL_DRPDI_SHIFT 16 +/* 0x050, 0x054, 0x058, 0x05C, 0x064: DRP_STATUS_CH[1-4], DRP_STATUS_COMMON */ +#define XVPHY_DRP_STATUS_DRPO_MASK 0x0FFFF +#define XVPHY_DRP_STATUS_DRPRDY_MASK 0x10000 +#define XVPHY_DRP_STATUS_DRPBUSY_MASK 0x20000 +/* 0x070: TX_CONTROL */ +#define XVPHY_TX_CONTROL_TX8B10BEN_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_TX_CONTROL_TX8B10BEN_ALL_MASK \ + (XVPHY_TX_CONTROL_TX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_TX_CONTROL_TX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_TX_CONTROL_TX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_TX_CONTROL_TX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_TX_CONTROL_TXPOLARITY_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_TX_CONTROL_TXPRBSSEL_MASK(Ch) \ + (0x1C << (8 * (Ch - 1))) +#define XVPHY_TX_CONTROL_TXPRBSSEL_SHIFT(Ch) \ + (2 + (8 * (Ch - 1))) +#define XVPHY_TX_CONTROL_TXPRBSFORCEERR_MASK(Ch) \ + (0x20 << (8 * (Ch - 1))) +/* 0x074: TX_BUFFER_BYPASS */ +#define XVPHY_TX_BUFFER_BYPASS_TXPHDLYRESET_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXPHALIGN_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXPHALIGNEN_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXPHDLYPD_MASK(Ch) \ + (0x08 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXPHINIT_MASK(Ch) \ + (0x10 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXDLYRESET_MASK(Ch) \ + (0x20 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXDLYBYPASS_MASK(Ch) \ + (0x40 << (8 * (Ch - 1))) +#define XVPHY_TX_BUFFER_BYPASS_TXDLYEN_MASK(Ch) \ + (0x80 << (8 * (Ch - 1))) +/* 0x078: TX_STATUS */ +#define XVPHY_TX_STATUS_TXPHALIGNDONE_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_TX_STATUS_TXPHINITDONE_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_TX_STATUS_TXDLYRESETDONE_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_TX_STATUS_TXBUFSTATUS_MASK(Ch) \ + (0x18 << (8 * (Ch - 1))) +#define XVPHY_TX_STATUS_TXBUFSTATUS_SHIFT(Ch) \ + (3 + (8 * (Ch - 1))) +/* 0x07C, 0x080: TX_DRIVER_CH12, TX_DRIVER_CH34 */ +#define XVPHY_TX_DRIVER_TXDIFFCTRL_MASK(Ch) \ + (0x000F << (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXDIFFCTRL_SHIFT(Ch) \ + (16 * ((Ch - 1) % 2)) +#define XVPHY_TX_DRIVER_TXELECIDLE_MASK(Ch) \ + (0x0010 << (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXELECIDLE_SHIFT(Ch) \ + (4 + (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXINHIBIT_MASK(Ch) \ + (0x0020 << (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXINHIBIT_SHIFT(Ch) \ + (5 + (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXPOSTCURSOR_MASK(Ch) \ + (0x07C0 << (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXPOSTCURSOR_SHIFT(Ch) \ + (6 + (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXPRECURSOR_MASK(Ch) \ + (0xF800 << (16 * ((Ch - 1) % 2))) +#define XVPHY_TX_DRIVER_TXPRECURSOR_SHIFT(Ch) \ + (11 + (16 * ((Ch - 1) % 2))) +/* 0x100: RX_CONTROL */ +#define XVPHY_RX_CONTROL_RX8B10BEN_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_RX_CONTROL_RX8B10BEN_ALL_MASK \ + (XVPHY_RX_CONTROL_RX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_RX_CONTROL_RX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_RX_CONTROL_RX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_RX_CONTROL_RX8B10BEN_MASK(XVPHY_CHANNEL_ID_CH4)) +#define XVPHY_RX_CONTROL_RXPOLARITY_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_RX_CONTROL_RXPRBSCNTRESET_MASK(Ch) \ + (0x08 << (8 * (Ch - 1))) +#define XVPHY_RX_CONTROL_RXPRBSSEL_MASK(Ch) \ + (0x70 << (8 * (Ch - 1))) +#define XVPHY_RX_CONTROL_RXPRBSSEL_SHIFT(Ch) \ + (4 + (8 * (Ch - 1))) +/* 0x104: RX_STATUS */ +#define XVPHY_RX_STATUS_RXCDRLOCK_MASK(Ch) \ + (0x1 << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXBUFSTATUS_MASK(Ch) \ + (0xE << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXBUFSTATUS_SHIFT(Ch) \ + (1 + (8 * (Ch - 1))) +/* 0x104: RX_EQ_CDR */ +#define XVPHY_RX_CONTROL_RXLPMEN_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXCDRHOLD_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXOSOVRDEN_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXLPMLFKLOVRDEN_MASK(Ch) \ + (0x08 << (8 * (Ch - 1))) +#define XVPHY_RX_STATUS_RXLPMHFOVRDEN_MASK(Ch) \ + (0x10 << (8 * (Ch - 1))) +#define XVPHY_RX_CONTROL_RXLPMEN_ALL_MASK \ + (XVPHY_RX_CONTROL_RXLPMEN_MASK(XVPHY_CHANNEL_ID_CH1) | \ + XVPHY_RX_CONTROL_RXLPMEN_MASK(XVPHY_CHANNEL_ID_CH2) | \ + XVPHY_RX_CONTROL_RXLPMEN_MASK(XVPHY_CHANNEL_ID_CH3) | \ + XVPHY_RX_CONTROL_RXLPMEN_MASK(XVPHY_CHANNEL_ID_CH4)) +/* 0x110, 0x114, 0x118, 0x11C: INTR_EN, INTR_DIS, INTR_MASK, INTR_STS */ +#define XVPHY_INTR_TXRESETDONE_MASK 0x00000001 +#define XVPHY_INTR_RXRESETDONE_MASK 0x00000002 +#define XVPHY_INTR_CPLL_LOCK_MASK 0x00000004 +#define XVPHY_INTR_QPLL0_LOCK_MASK 0x00000008 +#define XVPHY_INTR_TXALIGNDONE_MASK 0x00000010 +#define XVPHY_INTR_QPLL1_LOCK_MASK 0x00000020 +#define XVPHY_INTR_TXCLKDETFREQCHANGE_MASK 0x00000040 +#define XVPHY_INTR_RXCLKDETFREQCHANGE_MASK 0x00000080 +#define XVPHY_INTR_TXTMRTIMEOUT_MASK 0x40000000 +#define XVPHY_INTR_RXTMRTIMEOUT_MASK 0x80000000 +#define XVPHY_INTR_QPLL_LOCK_MASK XVPHY_INTR_QPLL0_LOCK_MASK +/* 0x120, 0x140: MMCM_TXUSRCLK_CTRL, MMCM_RXUSRCLK_CTRL */ +#define XVPHY_MMCM_USRCLK_CTRL_CFG_NEW_MASK 0x01 +#define XVPHY_MMCM_USRCLK_CTRL_RST_MASK 0x02 +#define XVPHY_MMCM_USRCLK_CTRL_CFG_SUCCESS_MASK 0x10 +#define XVPHY_MMCM_USRCLK_CTRL_LOCKED_MASK 0x20 +#define XVPHY_MMCM_USRCLK_CTRL_PWRDWN_MASK 0x400 +#define XVPHY_MMCM_USRCLK_CTRL_LOCKED_MASK_MASK 0x800 +/* 0x124, 0x144: MMCM_TXUSRCLK_REG1, MMCM_RXUSRCLK_REG1 */ +#define XVPHY_MMCM_USRCLK_REG1_DIVCLK_MASK \ + 0x00000FF +#define XVPHY_MMCM_USRCLK_REG1_CLKFBOUT_MULT_MASK \ + 0x000FF00 +#define XVPHY_MMCM_USRCLK_REG1_CLKFBOUT_MULT_SHIFT \ + 8 +#define XVPHY_MMCM_USRCLK_REG1_CLKFBOUT_FRAC_MASK \ + 0x3FF0000 +#define XVPHY_MMCM_USRCLK_REG1_CLKFBOUT_FRAC_SHIFT \ + 16 +/* 0x128, 0x148: MMCM_TXUSRCLK_REG2, MMCM_RXUSRCLK_REG2 */ +#define XVPHY_MMCM_USRCLK_REG2_DIVCLK_MASK \ + 0x00000FF +#define XVPHY_MMCM_USRCLK_REG2_CLKOUT0_FRAC_MASK \ + 0x3FF0000 +#define XVPHY_MMCM_USRCLK_REG2_CLKOUT0_FRAC_SHIFT \ + 16 +/* 0x12C, 0x130, 0x14C, 0x150: MMCM_TXUSRCLK_REG[3,4], MMCM_RXUSRCLK_REG[3,4] */ +#define XVPHY_MMCM_USRCLK_REG34_DIVCLK_MASK \ + 0x00000FF +/* 0x134, 0x154: BUFGT_TXUSRCLK, BUFGT_RXUSRCLK */ +#define XVPHY_BUFGGT_XXUSRCLK_CLR_MASK 0x1 +#define XVPHY_BUFGGT_XXUSRCLK_DIV_MASK 0xE +#define XVPHY_BUFGGT_XXUSRCLK_DIV_SHIFT 1 +/* 0x138, 0x158: MISC_TXUSRCLK_REG, MISC_RXUSERCLK_REG */ +#define XVPHY_MISC_XXUSRCLK_CKOUT1_OEN_MASK 0x1 +#define XVPHY_MISC_XXUSRCLK_REFCLK_CEB_MASK 0x2 +/* 0x200: CLKDET_CTRL */ +#define XVPHY_CLKDET_CTRL_RUN_MASK 0x1 +#define XVPHY_CLKDET_CTRL_TX_TMR_CLR_MASK 0x2 +#define XVPHY_CLKDET_CTRL_RX_TMR_CLR_MASK 0x4 +#define XVPHY_CLKDET_CTRL_TX_FREQ_RST_MASK 0x8 +#define XVPHY_CLKDET_CTRL_RX_FREQ_RST_MASK 0x10 +#define XVPHY_CLKDET_CTRL_FREQ_LOCK_THRESH_MASK 0x1FE0 +#define XVPHY_CLKDET_CTRL_FREQ_LOCK_THRESH_SHIFT 5 +/* 0x204: CLKDET_STAT */ +#define XVPHY_CLKDET_STAT_TX_FREQ_ZERO_MASK 0x1 +#define XVPHY_CLKDET_STAT_RX_FREQ_ZERO_MASK 0x2 +#define XVPHY_CLKDET_STAT_TX_REFCLK_LOCK_MASK 0x3 +#define XVPHY_CLKDET_STAT_TX_REFCLK_LOCK_CAP_MASK 0x4 +/* 0x300: DRU_CTRL */ +#define XVPHY_DRU_CTRL_RST_MASK(Ch) (0x01 << (8 * (Ch - 1))) +#define XVPHY_DRU_CTRL_EN_MASK(Ch) (0x02 << (8 * (Ch - 1))) +/* 0x304: DRU_STAT */ +#define XVPHY_DRU_STAT_ACTIVE_MASK(Ch) (0x01 << (8 * (Ch - 1))) +#define XVPHY_DRU_STAT_VERSION_MASK 0xFF000000 +#define XVPHY_DRU_STAT_VERSION_SHIFT 24 +/* 0x30C, 0x318, 0x324, 0x330: DRU_CFREQ_H_CH[1-4] */ +#define XVPHY_DRU_CFREQ_H_MASK 0x1F +/* 0x310, 0x31C, 0x328, 0x334: DRU_GAIN_CH[1-4] */ +#define XVPHY_DRU_GAIN_G1_MASK 0x00001F +#define XVPHY_DRU_GAIN_G1_SHIFT 0 +#define XVPHY_DRU_GAIN_G1_P_MASK 0x001F00 +#define XVPHY_DRU_GAIN_G1_P_SHIFT 8 +#define XVPHY_DRU_GAIN_G2_MASK 0x1F0000 +#define XVPHY_DRU_GAIN_G2_SHIFT 16 +/* @} */ + +/******************* Macros (Inline Functions) Definitions ********************/ + +/** @name Register access macro definitions. + * @{ + */ +#define XVphy_In32 Xil_In32 +#define XVphy_Out32 Xil_Out32 +/* @} */ + +/******************************************************************************/ +/** + * This is a low-level function that reads from the specified register. + * + * @param BaseAddress is the base address of the device. + * @param RegOffset is the register offset to be read from. + * + * @return The 32-bit value of the specified register. + * + * @note C-style signature: + * u32 XVphy_ReadReg(u32 BaseAddress, u32 RegOffset) + * +*******************************************************************************/ +#define XVphy_ReadReg(BaseAddress, RegOffset) \ + XVphy_In32((BaseAddress) + (RegOffset)) + +/******************************************************************************/ +/** + * This is a low-level function that writes to the specified register. + * + * @param BaseAddress is the base address of the device. + * @param RegOffset is the register offset to write to. + * @param Data is the 32-bit data to write to the specified register. + * + * @return None. + * + * @note C-style signature: + * void XVphy_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) + * +*******************************************************************************/ +#define XVphy_WriteReg(BaseAddress, RegOffset, Data) \ + XVphy_Out32((BaseAddress) + (RegOffset), (Data)) + +#endif /* XVPHY_HW_H_ */ diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_i.c b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_i.c new file mode 100644 index 00000000000000..99ba00e53f07df --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_i.c @@ -0,0 +1,1441 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_i.c + * + * Contains generic APIs that are locally called or used within the + * VPHY driver. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 gm, 11/09/16 Initial release. + * 1.4 gm 29/11/16 Fixed c++ compiler warnings + * Added xcvr adaptor functions for C++ compilations + * </pre> + * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include <linux/string.h> +#include "xstatus.h" +#include "xvphy.h" +#include "xvphy_i.h" +#include "xvphy_hdmi.h" +#include <linux/delay.h> +#include "xvphy_gt.h" + +/**************************** Function Prototypes *****************************/ + + +/**************************** Function Definitions ****************************/ + +/*****************************************************************************/ +/** +* This function will enable or disable the LPM logic in the Video PHY core. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param Enable will enable (if 1) or disable (if 0) the LPM logic. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_SetRxLpm(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Enable) +{ + u32 RegVal; + u32 MaskVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + Dir = Dir; + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_RX_EQ_CDR_REG); + + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_RX_CONTROL_RXLPMEN_ALL_MASK; + } + else { + MaskVal = XVPHY_RX_CONTROL_RXLPMEN_MASK(ChId); + } + + if (Enable) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_RX_EQ_CDR_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function will set the TX voltage swing value for a given channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Vs is the voltage swing value to write. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_SetTxVoltageSwing(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u8 Vs) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if ((ChId == XVPHY_CHANNEL_ID_CH1) || (ChId == XVPHY_CHANNEL_ID_CH2)) { + RegOffset = XVPHY_TX_DRIVER_CH12_REG; + } + else { + RegOffset = XVPHY_TX_DRIVER_CH34_REG; + } + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + + MaskVal = XVPHY_TX_DRIVER_TXDIFFCTRL_MASK(ChId); + RegVal &= ~MaskVal; + RegVal |= (Vs << XVPHY_TX_DRIVER_TXDIFFCTRL_SHIFT(ChId)); + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); +} + +/*****************************************************************************/ +/** +* This function will set the TX pre-emphasis value for a given channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Pe is the pre-emphasis value to write. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_SetTxPreEmphasis(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u8 Pe) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if ((ChId == XVPHY_CHANNEL_ID_CH1) || (ChId == XVPHY_CHANNEL_ID_CH2)) { + RegOffset = XVPHY_TX_DRIVER_CH12_REG; + } + else { + RegOffset = XVPHY_TX_DRIVER_CH34_REG; + } + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + + MaskVal = XVPHY_TX_DRIVER_TXPRECURSOR_MASK(ChId); + RegVal &= ~MaskVal; + RegVal |= (Pe << XVPHY_TX_DRIVER_TXPRECURSOR_SHIFT(ChId)); + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); +} + +/*****************************************************************************/ +/** +* This function writes the current software configuration for the reference +* clock selections to hardware for the specified quad on all channels. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_WriteCfgRefClkSelReg(XVphy *InstancePtr, u8 QuadId) +{ + u32 RegVal = 0; + XVphy_Channel *ChPtr; + XVphy_GtType GtType = InstancePtr->Config.XcvrType; + + /* Point to the first channel since settings apply to all channels. */ + ChPtr = &InstancePtr->Quads[QuadId].Ch1; + + /* PllRefClkSel. */ + /* - QPLL0. */ + RegVal &= ~XVPHY_REF_CLK_SEL_QPLL0_MASK; + RegVal = InstancePtr->Quads[QuadId].Cmn0.PllRefClkSel; + /* - CPLL. */ + RegVal &= ~XVPHY_REF_CLK_SEL_CPLL_MASK; + RegVal |= (ChPtr->CpllRefClkSel << XVPHY_REF_CLK_SEL_CPLL_SHIFT); + if ((GtType == XVPHY_GT_TYPE_GTHE3) || + (GtType == XVPHY_GT_TYPE_GTHE4) || + (GtType == XVPHY_GT_TYPE_GTPE2)) { + /* - QPLL1. */ + RegVal &= ~XVPHY_REF_CLK_SEL_QPLL1_MASK; + RegVal |= (InstancePtr->Quads[QuadId].Cmn1.PllRefClkSel << + XVPHY_REF_CLK_SEL_QPLL1_SHIFT); + } + + /* SysClkDataSel. PLLCLKSEL */ + RegVal &= ~XVPHY_REF_CLK_SEL_SYSCLKSEL_MASK; + /* - TXSYSCLKSEL[0]. TXPLLCLKSEL*/ + RegVal |= (ChPtr->TxDataRefClkSel << + XVPHY_REF_CLK_SEL_TXSYSCLKSEL_DATA_SHIFT(GtType)) & + XVPHY_REF_CLK_SEL_TXSYSCLKSEL_DATA_MASK(GtType); + /* - RXSYSCLKSEL[0]. RXPLLCLKSEL*/ + RegVal |= (ChPtr->RxDataRefClkSel << + XVPHY_REF_CLK_SEL_RXSYSCLKSEL_DATA_SHIFT(GtType)) & + XVPHY_REF_CLK_SEL_RXSYSCLKSEL_DATA_MASK(GtType); + + /* SysClkOutSel. */ + /* - TXSYSCLKSEL[1]. */ + RegVal |= (ChPtr->TxOutRefClkSel << + XVPHY_REF_CLK_SEL_TXSYSCLKSEL_OUT_SHIFT(GtType)) & + XVPHY_REF_CLK_SEL_TXSYSCLKSEL_OUT_MASK(GtType); + /* - RXSYSCLKSEL[1]. */ + RegVal |= (ChPtr->RxOutRefClkSel << + XVPHY_REF_CLK_SEL_RXSYSCLKSEL_OUT_SHIFT(GtType)) & + XVPHY_REF_CLK_SEL_RXSYSCLKSEL_OUT_MASK(GtType); + + /* Write to hardware. */ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_REF_CLK_SEL_REG, + RegVal); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* Configure the PLL reference clock selection for the specified channel(s). +* This is applied to both direction to the software configuration only. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param SysClkDataSel is the reference clock selection to configure. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_CfgPllRefClkSel(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_PllRefClkSelType RefClkSel) +{ + u8 Id, Id0, Id1; + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)].PllRefClkSel = + RefClkSel; + } +} + +/*****************************************************************************/ +/** +* Configure the SYSCLKDATA reference clock selection for the direction. Same +* configuration applies to all channels in the quad. This is applied to the +* software configuration only. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param SysClkDataSel is the reference clock selection to configure. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_CfgSysClkDataSel(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_SysClkDataSelType SysClkDataSel) +{ + XVphy_Channel *ChPtr; + u8 Id, Id0, Id1; + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + /* Select in software - same for all channels. */ + for (Id = Id0; Id <= Id1; Id++) { + ChPtr = &InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]; + ChPtr->DataRefClkSel[Dir] = SysClkDataSel; + } +} + +/*****************************************************************************/ +/** +* Configure the SYSCLKOUT reference clock selection for the direction. Same +* configuration applies to all channels in the quad. This is applied to the +* software configuration only. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param SysClkOutSel is the reference clock selection to configure. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_CfgSysClkOutSel(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_SysClkOutSelType SysClkOutSel) +{ + XVphy_Channel *ChPtr; + u8 Id, Id0, Id1; + + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + /* Select in software - same for all channels. */ + for (Id = Id0; Id <= Id1; Id++) { + ChPtr = &InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]; + ChPtr->OutRefClkSel[Dir] = SysClkOutSel; + } +} + +/*****************************************************************************/ +/** +* Obtain the reconfiguration channel ID for given PLL type +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param PllType is the PLL type being used by the channel. +* +* @return The Channel ID to be used for reconfiguration +* +* @note None. +* +******************************************************************************/ +XVphy_ChannelId XVphy_GetRcfgChId(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_PllType PllType) +{ + XVphy_ChannelId ChId; + + /* Suppress Warning Messages */ + InstancePtr = InstancePtr; + QuadId = QuadId; + Dir = Dir; + + /* Determine which channel(s) to operate on. */ + switch (PllType) { + case XVPHY_PLL_TYPE_QPLL: + case XVPHY_PLL_TYPE_QPLL0: + case XVPHY_PLL_TYPE_PLL0: + ChId = XVPHY_CHANNEL_ID_CMN0; + break; + case XVPHY_PLL_TYPE_QPLL1: + case XVPHY_PLL_TYPE_PLL1: + ChId = XVPHY_CHANNEL_ID_CMN1; + break; + default: + ChId = XVPHY_CHANNEL_ID_CHA; + break; + } + + return ChId; +} + +/*****************************************************************************/ +/** +* Obtain the current reference clock frequency for the quad based on the +* reference clock type. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param RefClkType is the type to obtain the clock selection for. +* +* @return The current reference clock frequency for the quad for the +* specified type selection. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_GetQuadRefClkFreq(XVphy *InstancePtr, u8 QuadId, + XVphy_PllRefClkSelType RefClkType) +{ + u32 FreqHz; + + u8 RefClkIndex = RefClkType - XVPHY_PLL_REFCLKSEL_TYPE_GTREFCLK0; + + FreqHz = (RefClkType > XVPHY_PLL_REFCLKSEL_TYPE_GTGREFCLK) ? 0 : + InstancePtr->Quads[QuadId].RefClkHz[RefClkIndex]; + + return FreqHz; +} + +/*****************************************************************************/ +/** +* Obtain the current [RT]XSYSCLKSEL[0] configuration. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param ChId is the channel ID which to operate on. +* +* @return The current [RT]XSYSCLKSEL[0] selection. +* +* @note None. +* +******************************************************************************/ +XVphy_SysClkDataSelType XVphy_GetSysClkDataSel(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_ChannelId ChId) +{ + u32 Sel; + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + ChId = ChId; + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_REF_CLK_SEL_REG); + + if (Dir == XVPHY_DIR_TX) { + /* Synchronize software configuration to hardware. */ + Sel = RegVal & XVPHY_REF_CLK_SEL_TXSYSCLKSEL_DATA_MASK( + InstancePtr->Config.XcvrType); + Sel >>= XVPHY_REF_CLK_SEL_TXSYSCLKSEL_DATA_SHIFT( + InstancePtr->Config.XcvrType); + } + else { + /* Synchronize software configuration to hardware. */ + Sel = RegVal & XVPHY_REF_CLK_SEL_RXSYSCLKSEL_DATA_MASK( + InstancePtr->Config.XcvrType); + Sel >>= XVPHY_REF_CLK_SEL_RXSYSCLKSEL_DATA_SHIFT( + InstancePtr->Config.XcvrType); + } + + return (XVphy_SysClkDataSelType) Sel; +} + +/*****************************************************************************/ +/** +* Obtain the current [RT]XSYSCLKSEL[1] configuration. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param ChId is the channel ID which to operate on. +* +* @return The current [RT]XSYSCLKSEL[1] selection. +* +* @note None. +* +******************************************************************************/ +XVphy_SysClkOutSelType XVphy_GetSysClkOutSel(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_ChannelId ChId) +{ + u32 Sel; + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + ChId = ChId; + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_REF_CLK_SEL_REG); + + if (Dir == XVPHY_DIR_TX) { + /* Synchronize software configuration to hardware. */ + Sel = RegVal & XVPHY_REF_CLK_SEL_TXSYSCLKSEL_OUT_MASK( + InstancePtr->Config.XcvrType); + Sel >>= XVPHY_REF_CLK_SEL_TXSYSCLKSEL_OUT_SHIFT( + InstancePtr->Config.XcvrType); + } + else { + /* Synchronize software configuration to hardware. */ + Sel = RegVal & XVPHY_REF_CLK_SEL_RXSYSCLKSEL_OUT_MASK( + InstancePtr->Config.XcvrType); + Sel >>= XVPHY_REF_CLK_SEL_RXSYSCLKSEL_OUT_SHIFT( + InstancePtr->Config.XcvrType); + } + + return (XVphy_SysClkOutSelType)Sel; +} + +/*****************************************************************************/ +/** +* This function will check the status of a PLL lock on the specified channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID which to operate on. +* +* @return +* - XST_SUCCESS if the specified PLL is locked. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_IsPllLocked(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + u32 RegVal; + u32 MaskVal; + XVphy_PllType TxPllType; + XVphy_PllType RxPllType; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (ChId == XVPHY_CHANNEL_ID_CMN0) { + MaskVal = XVPHY_PLL_LOCK_STATUS_QPLL0_MASK; + } + else if (ChId == XVPHY_CHANNEL_ID_CMN1) { + MaskVal = XVPHY_PLL_LOCK_STATUS_QPLL1_MASK; + } + else if (ChId == XVPHY_CHANNEL_ID_CMNA) { + MaskVal = XVPHY_PLL_LOCK_STATUS_QPLL0_MASK | + XVPHY_PLL_LOCK_STATUS_QPLL1_MASK; + } + else if (ChId == XVPHY_CHANNEL_ID_CHA) { + TxPllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_TX, + XVPHY_CHANNEL_ID_CH1); + RxPllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_RX, + XVPHY_CHANNEL_ID_CH1); + if (RxPllType == XVPHY_PLL_TYPE_CPLL && + InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + MaskVal = XVPHY_PLL_LOCK_STATUS_CPLL_HDMI_MASK; + } + else if (TxPllType == XVPHY_PLL_TYPE_CPLL && + InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) { + MaskVal = XVPHY_PLL_LOCK_STATUS_CPLL_HDMI_MASK; + } + else { + MaskVal = XVPHY_PLL_LOCK_STATUS_CPLL_ALL_MASK; + } + } + else { + MaskVal = XVPHY_PLL_LOCK_STATUS_CPLL_MASK(ChId); + } + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_PLL_LOCK_STATUS_REG); + + if ((RegVal & MaskVal) == MaskVal) { + return XST_SUCCESS; + } + + return XST_FAILURE; +} + +/*****************************************************************************/ +/** +* This function will reset and enable the Video PHY's user core logic. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID which to operate on. +* @param Dir is an indicator for TX or RX. +* @param Hold is an indicator whether to "hold" the reset if set to 1. +* If set to 0: reset, then enable. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_GtUserRdyEnable(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Hold) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_TX_INIT_REG; + + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_TX_INIT_USERRDY_ALL_MASK; + } + else { + MaskVal = XVPHY_TX_INIT_USERRDY_MASK(ChId); + } + } + else { + RegOffset = XVPHY_RX_INIT_REG; + if (ChId == XVPHY_CHANNEL_ID_CHA) { + MaskVal = XVPHY_RX_INIT_USERRDY_ALL_MASK; + } + else { + MaskVal = XVPHY_RX_INIT_USERRDY_MASK(ChId); + } + } + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + /* Assert reset. */ + RegVal |= MaskVal; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + + if (!Hold) { + /* De-assert reset. */ + RegVal &= ~MaskVal; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will reset the mixed-mode clock manager (MMCM) core. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param Hold is an indicator whether to "hold" the reset if set to 1. +* If set to 0: reset, then enable. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +void XVphy_MmcmReset(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir, + u8 Hold) +{ + u32 RegOffsetCtrl; + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XVPHY_DIR_TX) { + RegOffsetCtrl = XVPHY_MMCM_TXUSRCLK_CTRL_REG; + } + else { + RegOffsetCtrl = XVPHY_MMCM_RXUSRCLK_CTRL_REG; + } + + /* Assert reset. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl); + RegVal |= XVPHY_MMCM_USRCLK_CTRL_RST_MASK; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, RegVal); + + if (!Hold) { + /* De-assert reset. */ + RegVal &= ~XVPHY_MMCM_USRCLK_CTRL_RST_MASK; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, + RegVal); + } +} + +/*****************************************************************************/ +/** +* This function will reset the mixed-mode clock manager (MMCM) core. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param Enable is an indicator whether to "Enable" the locked mask +* if set to 1. If set to 0: reset, then disable. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_MmcmLockedMaskEnable(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, u8 Enable) +{ + u32 RegOffsetCtrl; + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XVPHY_DIR_TX) { + RegOffsetCtrl = XVPHY_MMCM_TXUSRCLK_CTRL_REG; + } + else { + RegOffsetCtrl = XVPHY_MMCM_RXUSRCLK_CTRL_REG; + } + + /* Assert reset. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl); + RegVal |= XVPHY_MMCM_USRCLK_CTRL_LOCKED_MASK_MASK; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, RegVal); + + if (!Enable) { + /* De-assert reset. */ + RegVal &= ~XVPHY_MMCM_USRCLK_CTRL_LOCKED_MASK_MASK; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, + RegVal); + } +} + +/*****************************************************************************/ +/** +* This function obtains the divider value of the BUFG_GT peripheral. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Dir is an indicator for TX or RX +* @param Div 3-bit divider value +* +* @return None. +* +******************************************************************************/ +void XVphy_SetBufgGtDiv(XVphy *InstancePtr, XVphy_DirectionType Dir, u8 Div) +{ + u32 RegVal; + u32 RegOffset; + u8 Divider = Div; + + if (Divider == 0) { + Divider = 1; + } + else { + Divider = Divider - 1; + } + + + if (Dir == XVPHY_DIR_TX) { + RegOffset = XVPHY_BUFGGT_TXUSRCLK_REG; + } + else { + RegOffset = XVPHY_BUFGGT_RXUSRCLK_REG; + } + + /* Read BUFG_GT register. */ + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + RegVal &= ~XVPHY_BUFGGT_XXUSRCLK_DIV_MASK; + + /* Shift divider value to correct position. */ + Divider <<= XVPHY_BUFGGT_XXUSRCLK_DIV_SHIFT; + Divider &= XVPHY_BUFGGT_XXUSRCLK_DIV_MASK; + RegVal |= Divider; + + /* Write new value to BUFG_GT ctrl register. */ + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); +} + +/*****************************************************************************/ +/** +* This function will power down the specified GT PLL. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to power down the PLL for. +* @param Dir is an indicator for TX or RX. +* @param Hold is an indicator whether to "hold" the power down if set +* to 1. If set to 0: power down, then power back up. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_PowerDownGtPll(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u8 Hold) +{ + u32 MaskVal = 0; + u32 RegVal; + u8 Id, Id0, Id1; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (XVPHY_ISCH(ChId)) { + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + } + else { + /* When powering down a QPLL, power down for all channels. */ + XVphy_Ch2Ids(InstancePtr, XVPHY_CHANNEL_ID_CHA, &Id0, &Id1); + } + for (Id = Id0; Id <= Id1; Id++) { + if (ChId == XVPHY_CHANNEL_ID_CMN0) { + MaskVal |= XVPHY_POWERDOWN_CONTROL_QPLL0PD_MASK(Id); + } + else if (ChId == XVPHY_CHANNEL_ID_CMN1) { + MaskVal |= XVPHY_POWERDOWN_CONTROL_QPLL1PD_MASK(Id); + } + else if (ChId == XVPHY_CHANNEL_ID_CMNA) { + MaskVal |= XVPHY_POWERDOWN_CONTROL_QPLL0PD_MASK(Id) | + XVPHY_POWERDOWN_CONTROL_QPLL1PD_MASK(Id); + } + else { + MaskVal |= XVPHY_POWERDOWN_CONTROL_CPLLPD_MASK(Id); + } + } + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_POWERDOWN_CONTROL_REG); + RegVal |= MaskVal; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, + XVPHY_POWERDOWN_CONTROL_REG, RegVal); + + if (!Hold) { + RegVal &= ~MaskVal; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, + XVPHY_POWERDOWN_CONTROL_REG, RegVal); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will try to find the necessary PLL divisor values to produce +* the configured line rate given the specified PLL input frequency. This will +* be done for all channels specified by ChId. +* This function is a wrapper for XVphy_PllCalculator. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to calculate the PLL values for. +* @param ChId is the channel ID to calculate the PLL values for. +* @param Dir is an indicator for TX or RX. +* @param PllClkInFreqHz is the PLL input frequency on which to base the +* calculations on. A value of 0 indicates to use the currently +* configured quad PLL reference clock. A non-zero value indicates +* to ignore what is currently configured in SW, and use a custom +* frequency instead. +* +* @return +* - XST_SUCCESS if valid PLL values were found to satisfy the +* constraints. +* - XST_FAILURE otherwise. +* +* @note If successful, the channel's PllParams structure will be +* modified with the valid PLL parameters. +* +******************************************************************************/ +u32 XVphy_ClkCalcParams(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u32 PllClkInFreqHz) +{ + u32 Status = XST_SUCCESS; + u8 Id, Id0, Id1; + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + Status = XVphy_PllCalculator(InstancePtr, QuadId, + (XVphy_ChannelId)Id, Dir, PllClkInFreqHz); + if (Status != XST_SUCCESS) { + return Status; + } + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function will set the current output divider configuration over DRP. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID for which to write the settings for. +* @param Dir is an indicator for RX or TX. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_OutDivReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir) +{ + u32 Status; + u8 Id; + u8 Id0; + u8 Id1; + + if (!XVPHY_ISCH(ChId)) { + ChId = XVPHY_CHANNEL_ID_CHA; + } + + XVphy_LogWrite(InstancePtr, (Dir == XVPHY_DIR_TX) ? + XVPHY_LOG_EVT_GT_TX_RECONFIG : XVPHY_LOG_EVT_GT_RX_RECONFIG, 0); + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + Status = XVphy_OutDivChReconfig(InstancePtr, QuadId, + (XVphy_ChannelId)Id, Dir); + if (Status != XST_SUCCESS) { + break; + } + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function will set the current RX/TX configuration over DRP. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID for which to write the settings for. +* @param Dir is an indicator for RX or TX. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_DirReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir) +{ + u32 Status = XST_SUCCESS; + u8 Id, Id0, Id1; + + if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE2) && + (Dir == XVPHY_DIR_TX)) { + return XST_SUCCESS; + } + + if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2) && + ((InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_DP) || + (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_DP))) { + ChId = XVPHY_CHANNEL_ID_CHA; + } + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + if (Dir == XVPHY_DIR_TX) { + Status = XVphy_TxChReconfig(InstancePtr, QuadId, + (XVphy_ChannelId)Id); + } + else { + Status = XVphy_RxChReconfig(InstancePtr, QuadId, + (XVphy_ChannelId)Id); + } + if (Status != XST_SUCCESS) { + break; + } + } + + XVphy_LogWrite(InstancePtr, (Dir == XVPHY_DIR_TX) ? + XVPHY_LOG_EVT_GT_TX_RECONFIG : XVPHY_LOG_EVT_GT_RX_RECONFIG, 1); + + return Status; +} + +/*****************************************************************************/ +/** +* This function will set the current clocking settings for each channel to +* hardware based on the configuration stored in the driver's instance. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID for which to write the settings for. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_ClkReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + u32 Status; + u8 Id; + u8 Id0; + u8 Id1; + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + if (XVPHY_ISCH(Id)) { + Status = XVphy_ClkChReconfig(InstancePtr, QuadId, + (XVphy_ChannelId)Id); + } + else if (XVPHY_ISCMN(ChId)) { + Status = XVphy_ClkCmnReconfig(InstancePtr, QuadId, + (XVphy_ChannelId)Id); + } + if (Status != XST_SUCCESS) { + return Status; + } + } + + if (XVPHY_ISCH(Id)) { + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_CPLL_RECONFIG, 1); + } + else if (XVPHY_ISCMN(ChId) && + (InstancePtr->Config.XcvrType != XVPHY_GT_TYPE_GTPE2)) { + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_QPLL_RECONFIG, 1); + } + else if (XVPHY_ISCMN(ChId)) { /* GTPE2. */ + XVphy_LogWrite(InstancePtr, (ChId == XVPHY_CHANNEL_ID_CMN0) ? + XVPHY_LOG_EVT_PLL0_RECONFIG : + XVPHY_LOG_EVT_PLL1_RECONFIG, 1); + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function will set the channel IDs to correspond with the supplied +* channel ID based on the protocol. HDMI uses 3 channels; DP uses 4. This ID +* translation is done to allow other functions to operate iteratively over +* multiple channels. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param ChId is the channel ID used to determine the indices. +* @param Id0 is a pointer to the start channel ID to set. +* @param Id1 is a pointer to the end channel ID to set. +* +* @return None. +* +* @note The contents of Id0 and Id1 will be set according to ChId. +* +******************************************************************************/ +void XVphy_Ch2Ids(XVphy *InstancePtr, XVphy_ChannelId ChId, + u8 *Id0, u8 *Id1) +{ + u8 Channels = 4; + + if (ChId == XVPHY_CHANNEL_ID_CHA) { + *Id0 = XVPHY_CHANNEL_ID_CH1; + if ((InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) || + (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI)) { + *Id1 = XVPHY_CHANNEL_ID_CH3; + } + else { + Channels = ((InstancePtr->Config.TxChannels >= + InstancePtr->Config.RxChannels) ? + InstancePtr->Config.TxChannels : + InstancePtr->Config.RxChannels); + + if (Channels == 1) { + *Id1 = XVPHY_CHANNEL_ID_CH1; + } + else if (Channels == 2) { + *Id1 = XVPHY_CHANNEL_ID_CH2; + } + else if (Channels == 3) { + *Id1 = XVPHY_CHANNEL_ID_CH3; + } + else { + *Id1 = XVPHY_CHANNEL_ID_CH4; + } + } + } + else if (ChId == XVPHY_CHANNEL_ID_CMNA) { + *Id0 = XVPHY_CHANNEL_ID_CMN0; + if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE3) || + (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE4)) { + *Id1 = XVPHY_CHANNEL_ID_CMN1; + } + else { + *Id1 = XVPHY_CHANNEL_ID_CMN0; + } + } + else { + *Id0 = *Id1 = ChId; + } +} + +/*****************************************************************************/ +/** +* This function will translate from XVphy_PllType to XVphy_SysClkDataSelType. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return The reference clock type based on the PLL selection. +* +* @note None. +* +******************************************************************************/ +XVphy_SysClkDataSelType Pll2SysClkData(XVphy_PllType PllSelect) +{ + return (PllSelect == XVPHY_PLL_TYPE_CPLL) ? + XVPHY_SYSCLKSELDATA_TYPE_CPLL_OUTCLK : + (PllSelect == XVPHY_PLL_TYPE_QPLL) ? + XVPHY_SYSCLKSELDATA_TYPE_QPLL_OUTCLK : + (PllSelect == XVPHY_PLL_TYPE_QPLL0) ? + XVPHY_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK : + (PllSelect == XVPHY_PLL_TYPE_QPLL1) ? + XVPHY_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK : + (PllSelect == XVPHY_PLL_TYPE_PLL0) ? + XVPHY_SYSCLKSELDATA_TYPE_PLL0_OUTCLK : + XVPHY_SYSCLKSELDATA_TYPE_PLL1_OUTCLK; +} + +/*****************************************************************************/ +/** +* This function will translate from XVphy_PllType to XVphy_SysClkOutSelType. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return The reference clock type based on the PLL selection. +* +* @note None. +* +******************************************************************************/ +XVphy_SysClkOutSelType Pll2SysClkOut(XVphy_PllType PllSelect) +{ + return (PllSelect == XVPHY_PLL_TYPE_CPLL) ? + XVPHY_SYSCLKSELOUT_TYPE_CPLL_REFCLK : + (PllSelect == XVPHY_PLL_TYPE_QPLL) ? + XVPHY_SYSCLKSELOUT_TYPE_QPLL_REFCLK : + (PllSelect == XVPHY_PLL_TYPE_QPLL0) ? + XVPHY_SYSCLKSELOUT_TYPE_QPLL0_REFCLK : + (PllSelect == XVPHY_PLL_TYPE_QPLL1) ? + XVPHY_SYSCLKSELOUT_TYPE_QPLL1_REFCLK : + (PllSelect == XVPHY_PLL_TYPE_PLL0) ? + XVPHY_SYSCLKSELOUT_TYPE_PLL0_REFCLK : + XVPHY_SYSCLKSELOUT_TYPE_PLL1_REFCLK; +} + +/*****************************************************************************/ +/** +* This function will try to find the necessary PLL divisor values to produce +* the configured line rate given the specified PLL input frequency. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to calculate the PLL values for. +* @param ChId is the channel ID to calculate the PLL values for. +* @param Dir is an indicator for TX or RX. +* @param PllClkInFreqHz is the PLL input frequency on which to base the +* calculations on. A value of 0 indicates to use the currently +* configured quad PLL reference clock. A non-zero value indicates +* to ignore what is currently configured in SW, and use a custom +* frequency instead. +* +* @return +* - XST_SUCCESS if valid PLL values were found to satisfy the +* constraints. +* - XST_FAILURE otherwise. +* +* @note If successful, the channel's PllParams structure will be +* modified with the valid PLL parameters. +* +******************************************************************************/ +u32 XVphy_PllCalculator(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir, + u32 PllClkInFreqHz) +{ + u32 Status; + u64 PllClkOutFreqHz; + u64 CalcLineRateFreqHz; + u8 Id, Id0, Id1; + u64 PllClkInFreqHzIn = PllClkInFreqHz; + XVphy_Channel *PllPtr = &InstancePtr->Quads[QuadId]. + Plls[XVPHY_CH2IDX(ChId)]; + + if (!PllClkInFreqHzIn) { + PllClkInFreqHzIn = XVphy_GetQuadRefClkFreq(InstancePtr, QuadId, + PllPtr->PllRefClkSel); + } + + /* Select PLL value table offsets. */ + const XVphy_GtPllDivs *GtPllDivs; + if (XVPHY_ISCH(ChId)) { + GtPllDivs = &InstancePtr->GtAdaptor->CpllDivs; + } + else { + GtPllDivs = &InstancePtr->GtAdaptor->QpllDivs; + } + + const u8 *M, *N1, *N2, *D; + for (N2 = GtPllDivs->N2; *N2 != 0; N2++) { + for (N1 = GtPllDivs->N1; *N1 != 0; N1++) { + for (M = GtPllDivs->M; *M != 0; M++) { + PllClkOutFreqHz = (PllClkInFreqHzIn * *N1 * *N2) / *M; + + /* Test if the calculated PLL clock is in the VCO range. */ + Status = XVphy_CheckPllOpRange(InstancePtr, QuadId, ChId, + PllClkOutFreqHz); + if (Status != XST_SUCCESS) { + continue; + } + + if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2) || + (XVPHY_ISCH(ChId))) { + PllClkOutFreqHz *= 2; + } + /* Apply TX/RX divisor. */ + for (D = GtPllDivs->D; *D != 0; D++) { + CalcLineRateFreqHz = PllClkOutFreqHz / *D; + if (CalcLineRateFreqHz == PllPtr->LineRateHz) { + goto calc_done; + } + } + } + } + } + /* Calculation failed, don't change divisor settings. */ + return XST_FAILURE; + +calc_done: + /* Found the multiplier and divisor values for requested line rate. */ + PllPtr->PllParams.MRefClkDiv = *M; + PllPtr->PllParams.NFbDiv = *N1; + PllPtr->PllParams.N2FbDiv = *N2; /* Won't be used for QPLL.*/ + PllPtr->PllParams.IsLowerBand = 1; /* Won't be used for CPLL. */ + + if (XVPHY_ISCMN(ChId)) { + /* Same divisor value for all channels if using a QPLL. */ + ChId = XVPHY_CHANNEL_ID_CHA; + } + + XVphy_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)].OutDiv[Dir] = + *D; + if (Dir == XVPHY_DIR_RX) { + XVphy_CfgSetCdr(InstancePtr, QuadId, (XVphy_ChannelId)Id); + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function calculates the PLL VCO operating frequency. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* +* @return PLL VCO frequency in Hz +* +* @note None. +* +******************************************************************************/ +u64 XVphy_GetPllVcoFreqHz(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir) +{ + u64 PllxVcoRateHz; + u64 PllRefClkHz; + XVphy_Channel *PllPtr = &InstancePtr->Quads[QuadId]. + Plls[XVPHY_CH2IDX(ChId)]; + + if (Dir == XVPHY_DIR_TX) { + if (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) { + PllRefClkHz = InstancePtr->HdmiTxRefClkHz; + } + else { + PllRefClkHz = XVphy_GetQuadRefClkFreq(InstancePtr, QuadId, + PllPtr->PllRefClkSel); + } + } + else { + if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { +#if defined (XPAR_XV_HDMITX_0_DEVICE_ID) || defined (XPAR_XV_HDMIRX_0_DEVICE_ID) + if (InstancePtr->HdmiRxDruIsEnabled) { + PllRefClkHz = XVphy_DruGetRefClkFreqHz(InstancePtr); + } + else { + PllRefClkHz = InstancePtr->HdmiRxRefClkHz; + } +#else + PllRefClkHz = 0; +#endif + } + else { + PllRefClkHz = XVphy_GetQuadRefClkFreq(InstancePtr, QuadId, + PllPtr->PllRefClkSel); + } + } + + PllxVcoRateHz = (PllRefClkHz * + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]. + PllParams.N1FbDiv * + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]. + PllParams.N2FbDiv) / + InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]. + PllParams.MRefClkDiv; + + return PllxVcoRateHz; +} + +#ifdef __cplusplus +/*****************************************************************************/ +/** +* This function is a transceiver adaptor to set the clock and data recovery +* (CDR) values for a given channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_CfgSetCdr(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + return InstancePtr->GtAdaptor->CfgSetCdr(InstancePtr, QuadId, ChId); +} + +/*****************************************************************************/ +/** +* This function is a transceiver adaptor to check if a given PLL output +* frequency is within the operating range of the PLL for the GT type. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param PllClkOutFreqHz is the frequency to check. +* +* @return +* - XST_SUCCESS if the frequency resides within the PLL's range. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_CheckPllOpRange(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u64 PllClkOutFreqHz) +{ + return InstancePtr->GtAdaptor->CheckPllOpRange(InstancePtr, QuadId, ChId, + PllClkOutFreqHz); +} + +/*****************************************************************************/ +/** +* This function is a transceiver adaptor to set the output divider logic for +* a given channel. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param Dir is an indicator for RX or TX. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_OutDivChReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir) +{ + return InstancePtr->GtAdaptor->OutDivChReconfig(InstancePtr, QuadId, + ChId, Dir); +} + +/*****************************************************************************/ +/** +* This function is a transceiver adaptor to configure the channel +* clock settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_ClkChReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + return InstancePtr->GtAdaptor->ClkChReconfig(InstancePtr, QuadId, ChId); +} + +/*****************************************************************************/ +/** +* This function is a transceiver adaptor to configure the common channel +* clock settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param CmnId is the common channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_ClkCmnReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + return InstancePtr->GtAdaptor->ClkCmnReconfig(InstancePtr, QuadId, ChId); +} + +/*****************************************************************************/ +/** +* This function is a transceiver adaptor to configure the channel's +* RX settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_RxChReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + return InstancePtr->GtAdaptor->RxChReconfig(InstancePtr, QuadId, ChId); +} + +/*****************************************************************************/ +/** +* This function is a transceiver adaptor to configure the channel's +* TX settings. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* +* @return +* - XST_SUCCESS if the configuration was successful. +* - XST_FAILURE otherwise. +* +* @note None. +* +******************************************************************************/ +u32 XVphy_TxChReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) +{ + return InstancePtr->GtAdaptor->TxChReconfig(InstancePtr, QuadId, ChId); +} +#endif diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_i.h b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_i.h new file mode 100644 index 00000000000000..ec6d424cf1a470 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_i.h @@ -0,0 +1,126 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_i.h + * + * Contains generic APIs that are locally called or used within the + * VPHY driver. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 gm, 11/09/16 Initial release. + * 1.4 gm 11/24/16 Made debug log optional (can be disabled via makefile) + * </pre> + * +*******************************************************************************/ + +#ifndef XVPHY_I_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XVPHY_I_H_ + +/******************************* Include Files ********************************/ + +#include "xil_assert.h" +#include "xvphy.h" +#include "xvphy_hw.h" +#include "xvidc.h" +//#include "xvphy_dp.h" + +/****************************** Type Definitions ******************************/ + + +/**************************** Function Prototypes *****************************/ + + +void XVphy_Ch2Ids(XVphy *InstancePtr, XVphy_ChannelId ChId, + u8 *Id0, u8 *Id1); +XVphy_SysClkDataSelType Pll2SysClkData(XVphy_PllType PllSelect); +XVphy_SysClkOutSelType Pll2SysClkOut(XVphy_PllType PllSelect); +u32 XVphy_PllCalculator(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir, + u32 PllClkInFreqHz); + +/* xvphy.c: Voltage swing and preemphasis. */ +void XVphy_SetRxLpm(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Enable); +void XVphy_SetTxVoltageSwing(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u8 Vs); +void XVphy_SetTxPreEmphasis(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u8 Pe); + +/* xvphy.c: Channel configuration functions - setters. */ +u32 XVphy_WriteCfgRefClkSelReg(XVphy *InstancePtr, u8 QuadId); +void XVphy_CfgPllRefClkSel(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_PllRefClkSelType RefClkSel); +void XVphy_CfgSysClkDataSel(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_SysClkDataSelType SysClkDataSel); +void XVphy_CfgSysClkOutSel(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_SysClkOutSelType SysClkOutSel); + +u32 XVphy_ClkCalcParams(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u32 PllClkInFreqHz); +u32 XVphy_OutDivReconfig(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir); +u32 XVphy_DirReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir); +u32 XVphy_ClkReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); + +/* xvphy.c: Channel configuration functions - getters. */ +XVphy_ChannelId XVphy_GetRcfgChId(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_PllType PllType); +u32 XVphy_GetQuadRefClkFreq(XVphy *InstancePtr, u8 QuadId, + XVphy_PllRefClkSelType RefClkType); +XVphy_SysClkDataSelType XVphy_GetSysClkDataSel(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_ChannelId ChId); +XVphy_SysClkOutSelType XVphy_GetSysClkOutSel(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, XVphy_ChannelId ChId); +u32 XVphy_IsPllLocked(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId); +u32 XVphy_GtUserRdyEnable(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Hold); + +/* xvphy.c: GT/MMCM DRP access. */ +void XVphy_MmcmReset(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir, + u8 Hold); +void XVphy_MmcmLockedMaskEnable(XVphy *InstancePtr, u8 QuadId, + XVphy_DirectionType Dir, u8 Enable); +void XVphy_SetBufgGtDiv(XVphy *InstancePtr, XVphy_DirectionType Dir, u8 Div); +/* xvphy.c Miscellaneous control. */ +u32 XVphy_PowerDownGtPll(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u8 Hold); + + +/* xvphy_intr.c: Interrupt handling functions. */ +void XVphy_SetIntrHandler(XVphy *InstancePtr, XVphy_IntrHandlerType HandlerType, + XVphy_IntrHandler CallbackFunc, void *CallbackRef); +void XVphy_IntrEnable(XVphy *InstancePtr, XVphy_IntrHandlerType Intr); +void XVphy_IntrDisable(XVphy *InstancePtr, XVphy_IntrHandlerType Intr); +void XVphy_CfgErrIntr(XVphy *InstancePtr, XVphy_ErrIrqType ErrIrq, u8 Set); + +u64 XVphy_GetPllVcoFreqHz(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, XVphy_DirectionType Dir); + +/******************* Macros (Inline Functions) Definitions ********************/ + +#endif /* XVPHY_I_H_ */ diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_intr.c b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_intr.c new file mode 100644 index 00000000000000..11f2b55dd4c271 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_intr.c @@ -0,0 +1,274 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_intr.c + * + * This file contains functions related to XVphy interrupt handling. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 10/19/15 Initial release. + * 1.4 gm 29/11/16 Added XVphy_CfgErrIntr for ERR_IRQ impl + * </pre> + * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xvphy.h" +#include "xvphy_i.h" + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function enables interrupts associated with the specified interrupt type. + * + * @param InstancePtr is a pointer to the XVphy instance. + * @param Intr is the interrupt type/mask to enable. + * + * @return None. + * + * @note None. +* +*******************************************************************************/ +void XVphy_IntrEnable(XVphy *InstancePtr, XVphy_IntrHandlerType Intr) +{ + u32 RegVal; + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, XVPHY_INTR_EN_REG); + RegVal |= Intr; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_INTR_EN_REG, RegVal); +} + +/******************************************************************************/ +/** + * This function disabled interrupts associated with the specified interrupt + * type. + * + * @param InstancePtr is a pointer to the XVphy instance. + * @param Intr is the interrupt type/mask to disable. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XVphy_IntrDisable(XVphy *InstancePtr, XVphy_IntrHandlerType Intr) +{ + u32 RegVal; + + RegVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_INTR_DIS_REG); + RegVal |= Intr; + XVphy_WriteReg(InstancePtr->Config.BaseAddr, XVPHY_INTR_DIS_REG, + RegVal); +} + +/******************************************************************************/ +/** + * This function installs a callback function for the specified handler type. + * + * @param InstancePtr is a pointer to the XVPhy instance. + * @param HandlerType is the interrupt handler type which specifies which + * interrupt event to attach the callback for. + * @param CallbackFunc is the address to the callback function. + * @param CallbackRef is the user data item that will be passed to the + * callback function when it is invoked. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XVphy_SetIntrHandler(XVphy *InstancePtr, XVphy_IntrHandlerType HandlerType, + XVphy_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((HandlerType == XVPHY_INTR_HANDLER_TYPE_TXRESET_DONE) || + (HandlerType == XVPHY_INTR_HANDLER_TYPE_RXRESET_DONE) || + (HandlerType == XVPHY_INTR_HANDLER_TYPE_CPLL_LOCK) || + (HandlerType == XVPHY_INTR_HANDLER_TYPE_QPLL_LOCK) || + (HandlerType == XVPHY_INTR_HANDLER_TYPE_TXALIGN_DONE) || + (HandlerType == XVPHY_INTR_HANDLER_TYPE_QPLL1_LOCK) || + (HandlerType == + XVPHY_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE) || + (HandlerType == + XVPHY_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE) || + (HandlerType == XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT) || + (HandlerType == XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT)); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + switch (HandlerType) { + case XVPHY_INTR_HANDLER_TYPE_TXRESET_DONE: + InstancePtr->IntrTxResetDoneHandler = CallbackFunc; + InstancePtr->IntrTxResetDoneCallbackRef = CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_RXRESET_DONE: + InstancePtr->IntrRxResetDoneHandler = CallbackFunc; + InstancePtr->IntrRxResetDoneCallbackRef = CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_CPLL_LOCK: + InstancePtr->IntrCpllLockHandler = CallbackFunc; + InstancePtr->IntrCpllLockCallbackRef = CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_QPLL_LOCK: + InstancePtr->IntrQpllLockHandler = CallbackFunc; + InstancePtr->IntrQpllLockCallbackRef = CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_TXALIGN_DONE: + InstancePtr->IntrTxAlignDoneHandler = CallbackFunc; + InstancePtr->IntrTxAlignDoneCallbackRef = CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_QPLL1_LOCK: + InstancePtr->IntrQpll1LockHandler = CallbackFunc; + InstancePtr->IntrQpll1LockCallbackRef = CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE: + InstancePtr->IntrTxClkDetFreqChangeHandler = + CallbackFunc; + InstancePtr->IntrTxClkDetFreqChangeCallbackRef = + CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE: + InstancePtr->IntrRxClkDetFreqChangeHandler = + CallbackFunc; + InstancePtr->IntrRxClkDetFreqChangeCallbackRef = + CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT: + InstancePtr->IntrTxTmrTimeoutHandler = CallbackFunc; + InstancePtr->IntrTxTmrTimeoutCallbackRef = CallbackRef; + break; + case XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT: + InstancePtr->IntrRxTmrTimeoutHandler = CallbackFunc; + InstancePtr->IntrRxTmrTimeoutCallbackRef = CallbackRef; + break; + default: + break; + } +} + +/******************************************************************************/ +/** + * This function is the interrupt handler for the XVphy driver. It will detect + * what kind of interrupt has happened, and will invoke the appropriate callback + * function. + * + * @param InstancePtr is a pointer to the XVphy instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XVphy_InterruptHandler(XVphy *InstancePtr) +{ + u32 IntrStatus; + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* Determine what kind of interrupts have occurred. */ + IntrStatus = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_INTR_STS_REG); + + if (IntrStatus & XVPHY_INTR_CPLL_LOCK_MASK) { + InstancePtr->IntrCpllLockHandler( + InstancePtr->IntrCpllLockCallbackRef); + } + if (IntrStatus & XVPHY_INTR_QPLL_LOCK_MASK) { + InstancePtr->IntrQpllLockHandler( + InstancePtr->IntrQpllLockCallbackRef); + } + if (IntrStatus & XVPHY_INTR_QPLL1_LOCK_MASK) { + InstancePtr->IntrQpll1LockHandler( + InstancePtr->IntrQpll1LockCallbackRef); + } + if (IntrStatus & XVPHY_INTR_TXRESETDONE_MASK) { + InstancePtr->IntrTxResetDoneHandler( + InstancePtr->IntrTxResetDoneCallbackRef); + } + if (IntrStatus & XVPHY_INTR_TXALIGNDONE_MASK) { + InstancePtr->IntrTxAlignDoneHandler( + InstancePtr->IntrTxAlignDoneCallbackRef); + } + if (IntrStatus & XVPHY_INTR_RXRESETDONE_MASK) { + InstancePtr->IntrRxResetDoneHandler( + InstancePtr->IntrRxResetDoneCallbackRef); + } + if (IntrStatus & XVPHY_INTR_TXCLKDETFREQCHANGE_MASK) { + InstancePtr->IntrTxClkDetFreqChangeHandler( + InstancePtr->IntrTxClkDetFreqChangeCallbackRef); + } + if (IntrStatus & XVPHY_INTR_RXCLKDETFREQCHANGE_MASK) { + InstancePtr->IntrRxClkDetFreqChangeHandler( + InstancePtr->IntrRxClkDetFreqChangeCallbackRef); + } + if (IntrStatus & XVPHY_INTR_TXTMRTIMEOUT_MASK) { + InstancePtr->IntrTxTmrTimeoutHandler( + InstancePtr->IntrTxTmrTimeoutCallbackRef); + } + if (IntrStatus & XVPHY_INTR_RXTMRTIMEOUT_MASK) { + InstancePtr->IntrRxTmrTimeoutHandler( + InstancePtr->IntrRxTmrTimeoutCallbackRef); + } +} + +/******************************************************************************/ +/** + * This function configures the error IRQ register based on the condition + * to generate an ERR_IRQ event + * + * @param InstancePtr is a pointer to the XVphy instance. + * ErrIrq is the IRQ type as define in XVphy_ErrIrqType + * Set is the flag to set or clear the ErrIrq param + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XVphy_CfgErrIntr(XVphy *InstancePtr, XVphy_ErrIrqType ErrIrq, u8 Set) +{ + u32 ErrIrqVal; + u32 WriteVal; + + ErrIrqVal = XVphy_ReadReg(InstancePtr->Config.BaseAddr, + XVPHY_ERR_IRQ); + + WriteVal = (u32)ErrIrq; + + if (Set) { + ErrIrqVal |= WriteVal; + } + else { + ErrIrqVal &= ~WriteVal; + } + + XVphy_WriteReg(InstancePtr->Config.BaseAddr, + XVPHY_ERR_IRQ, ErrIrqVal); +} diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_log.c b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_log.c new file mode 100644 index 00000000000000..4c256198eb1c28 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_log.c @@ -0,0 +1,467 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy.c + * + * Contains a minimal set of functions for the XVphy driver that allow access + * to all of the Video PHY core's functionality. See xvphy.h for a detailed + * description of the driver. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 10/19/15 Initial release. + * 1.1 gm 02/01/16 Additional events for event log printout + * 1.2 gm Added log events for debugging + * 1.4 gm 11/24/16 Made debug log optional (can be disabled via makefile) + * Added XVPHY_LOG_EVT_TX_ALIGN_TMOUT log event + * </pre> + * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xvphy.h" +#include "xvphy_i.h" + +/**************************** Function Prototypes *****************************/ + +/**************************** Function Definitions ****************************/ + +/*****************************************************************************/ +/** +* This function will reset the driver's logginc mechanism. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_LogReset(XVphy *InstancePtr) +{ +#ifdef XV_VPHY_LOG_ENABLE + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + + InstancePtr->Log.HeadIndex = 0; + InstancePtr->Log.TailIndex = 0; +#endif +} + +#ifdef XV_VPHY_LOG_ENABLE +/*****************************************************************************/ +/** +* This function will insert an event in the driver's logginc mechanism. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param Evt is the event type to log. +* @param Data is the associated data for the event. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_LogWrite(XVphy *InstancePtr, XVphy_LogEvent Evt, u8 Data) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Evt <= (XVPHY_LOG_EVT_DUMMY)); + Xil_AssertVoid(Data < 0xFF); + + /* Write data and event into log buffer */ + InstancePtr->Log.DataBuffer[InstancePtr->Log.HeadIndex] = + (Data << 8) | Evt; + + /* Update head pointer if reached to end of the buffer */ + if (InstancePtr->Log.HeadIndex == + (u8)((sizeof(InstancePtr->Log.DataBuffer) / 2) - 1)) { + /* Clear pointer */ + InstancePtr->Log.HeadIndex = 0; + } + else { + /* Increment pointer */ + InstancePtr->Log.HeadIndex++; + } + + /* Check tail pointer. When the two pointer are equal, then the buffer + * is full. In this case then increment the tail pointer as well to + * remove the oldest entry from the buffer. */ + if (InstancePtr->Log.TailIndex == InstancePtr->Log.HeadIndex) { + if (InstancePtr->Log.TailIndex == + (u8)((sizeof(InstancePtr->Log.DataBuffer) / 2) - 1)) { + InstancePtr->Log.TailIndex = 0; + } + else { + InstancePtr->Log.TailIndex++; + } + } +} +#endif + +/*****************************************************************************/ +/** +* This function will read the last event from the log. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return The log data. +* +* @note None. +* +******************************************************************************/ +u16 XVphy_LogRead(XVphy *InstancePtr) +{ +#ifdef XV_VPHY_LOG_ENABLE + u16 Log; + + /* Verify argument. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + /* Check if there is any data in the log */ + if (InstancePtr->Log.TailIndex == InstancePtr->Log.HeadIndex) { + Log = 0; + } + else { + Log = InstancePtr->Log.DataBuffer[InstancePtr->Log.TailIndex]; + + /* Increment tail pointer */ + if (InstancePtr->Log.TailIndex == + (u8)((sizeof(InstancePtr->Log.DataBuffer) / 2) - 1)) { + InstancePtr->Log.TailIndex = 0; + } + else { + InstancePtr->Log.TailIndex++; + } + } + + return Log; +#endif +} + +/*****************************************************************************/ +/** +* This function will print the entire log. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_LogDisplay(XVphy *InstancePtr) +{ +#ifdef XV_VPHY_LOG_ENABLE + u16 Log; + u8 Evt; + u8 Data; + + /* Verify argument. */ + Xil_AssertVoid(InstancePtr != NULL); + + xil_printf("\r\n\n\nVPHY log\r\n"); + xil_printf("------\r\n"); + + /* Read log data */ + Log = XVphy_LogRead(InstancePtr); + + while (Log != 0) { + /* Event */ + Evt = Log & 0xff; + + /* Data */ + Data = (Log >> 8) & 0xFF; + + switch (Evt) { + case (XVPHY_LOG_EVT_NONE): + xil_printf("GT log end\r\n-------\r\n"); + break; + case (XVPHY_LOG_EVT_QPLL_EN): + xil_printf("QPLL enable (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_QPLL_RST): + xil_printf("QPLL reset (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_CPLL_EN): + xil_printf("CPLL enable (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_CPLL_RST): + xil_printf("CPLL reset (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_TXPLL_EN): + xil_printf("TX MMCM enable (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_TXPLL_RST): + xil_printf("TX MMCM reset (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_RXPLL_EN): + xil_printf("RX MMCM enable (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_RXPLL_RST): + xil_printf("RX MMCM reset (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_GTRX_RST): + xil_printf("GT RX reset (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_GTTX_RST): + xil_printf("GT TX reset (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_VID_TX_RST): + xil_printf("Video TX reset (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_VID_RX_RST): + xil_printf("Video RX reset (%0d)\r\n", Data); + break; + case (XVPHY_LOG_EVT_TX_ALIGN): + if (Data == 1) { + xil_printf("TX alignment done\r\n"); + } + else { + xil_printf("TX alignment start.\r\n."); + } + break; + case (XVPHY_LOG_EVT_TX_ALIGN_TMOUT): + xil_printf("TX alignment watchdog timed out.\r\n"); + break; + case (XVPHY_LOG_EVT_TX_TMR): + if (Data == 1) { + xil_printf("TX timer event\r\n"); + } + else { + xil_printf("TX timer load\r\n"); + } + break; + case (XVPHY_LOG_EVT_RX_TMR): + if (Data == 1) { + xil_printf("RX timer event\r\n"); + } + else { + xil_printf("RX timer load\r\n"); + } + break; + case (XVPHY_LOG_EVT_CPLL_RECONFIG): + if (Data == 1) { + xil_printf("CPLL reconfig done\r\n"); + } + else { + xil_printf("CPLL reconfig start\r\n"); + } + break; + case (XVPHY_LOG_EVT_GT_RECONFIG): + if (Data == 1) { + xil_printf("GT reconfig done\r\n"); + } + else { + xil_printf("GT reconfig start\r\n"); + } + break; + case (XVPHY_LOG_EVT_GT_TX_RECONFIG): + if (Data == 1) { + xil_printf("GT TX reconfig done\r\n"); + } + else { + xil_printf("GT TX reconfig start\r\n"); + } + break; + case (XVPHY_LOG_EVT_GT_RX_RECONFIG): + if (Data == 1) { + xil_printf("GT RX reconfig done\r\n"); + } + else { + xil_printf("GT RX reconfig start\r\n"); + } + break; + case (XVPHY_LOG_EVT_QPLL_RECONFIG): + if (Data == 1) { + xil_printf("QPLL reconfig done\r\n"); + } + else { + xil_printf("QPLL reconfig start\r\n"); + } + break; + case (XVPHY_LOG_EVT_PLL0_RECONFIG): + if (Data == 1) { + xil_printf("PLL0 reconfig done\r\n"); + } + else { + xil_printf("PLL0 reconfig start\r\n"); + } + break; + case (XVPHY_LOG_EVT_PLL1_RECONFIG): + if (Data == 1) { + xil_printf("PLL1 reconfig done\r\n"); + } + else { + xil_printf("PLL1 reconfig start\r\n"); + } + break; + case (XVPHY_LOG_EVT_INIT): + if (Data == 1) { + xil_printf("GT init done\r\n"); + } + else { + xil_printf("GT init start\r\n"); + } + break; + case (XVPHY_LOG_EVT_TXPLL_RECONFIG): + if (Data == 1) { + xil_printf("TX MMCM reconfig done\r\n"); + } + else { + xil_printf("TX MMCM reconfig start\r\n"); + } + break; + case (XVPHY_LOG_EVT_RXPLL_RECONFIG): + if (Data == 1) { + xil_printf("RX MMCM reconfig done\r\n"); + } + else { + xil_printf("RX MMCM reconfig start\r\n"); + } + break; + case (XVPHY_LOG_EVT_QPLL_LOCK): + if (Data == 1) { + xil_printf("QPLL lock\r\n"); + } + else { + xil_printf("QPLL lost lock\r\n"); + } + break; + case (XVPHY_LOG_EVT_PLL0_LOCK): + if (Data == 1) { + xil_printf("PLL0 lock\r\n"); + } + else { + xil_printf("PLL0 lost lock\r\n"); + } + break; + case (XVPHY_LOG_EVT_PLL1_LOCK): + if (Data == 1) { + xil_printf("PLL1 lock\r\n"); + } + else { + xil_printf("PLL1 lost lock\r\n"); + } + break; + case (XVPHY_LOG_EVT_CPLL_LOCK): + if (Data == 1) { + xil_printf("CPLL lock\r\n"); + } + else { + xil_printf("CPLL lost lock\r\n"); + } + break; + case (XVPHY_LOG_EVT_RXPLL_LOCK): + if (Data == 1) { + xil_printf("RX MMCM lock\r\n"); + } + else { + xil_printf("RX MMCM lost lock\r\n"); + } + break; + case (XVPHY_LOG_EVT_TXPLL_LOCK): + if (Data == 1) { + xil_printf("TX MMCM lock\r\n"); + } + else { + xil_printf("TX MMCM lost lock\r\n"); + } + break; + case (XVPHY_LOG_EVT_TX_RST_DONE): + xil_printf("TX reset done\r\n"); + break; + case (XVPHY_LOG_EVT_RX_RST_DONE): + xil_printf("RX reset done\r\n"); + break; + case (XVPHY_LOG_EVT_TX_FREQ): + xil_printf("TX frequency event\r\n"); + break; + case (XVPHY_LOG_EVT_RX_FREQ): + xil_printf("RX frequency event\r\n"); + break; + case (XVPHY_LOG_EVT_DRU_EN): + if (Data == 1) { + xil_printf("DRU enable\r\n"); + } + else { + xil_printf("DRU disable\r\n"); + } + break; + case (XVPHY_LOG_EVT_GT_PLL_LAYOUT): + xil_printf("Error! Couldn't find the correct GT " + "parameters for this video resolution.\n\r"); + xil_printf("Try another GT PLL layout.\n\r"); + break; + case (XVPHY_LOG_EVT_GT_UNBONDED): + xil_printf("WARNING: " + "Transmitter cannot be used on\r\n"); + xil_printf(" " + "bonded mode when DRU is enabled\r\n"); + xil_printf("Switch to unbonded PLL layout\r\n"); + break; + case (XVPHY_LOG_EVT_1PPC_ERR): + xil_printf("Error! The Video PHY cannot support this video "); + xil_printf("format at PPC = 1\r\n"); + break; + case (XVPHY_LOG_EVT_PPC_MSMTCH_ERR): + xil_printf("Warning: HDMI TX SS PPC value, doesn't match with" + " VPhy PPC value\r\n"); + break; + case (XVPHY_LOG_EVT_VDCLK_HIGH_ERR): + xil_printf("Error! GTPE2 Video PHY cannot" + "support resolutions"); + xil_printf("\r\n\twith video clock > 148.5 MHz.\r\n"); + break; + case (XVPHY_LOG_EVT_NO_DRU): + xil_printf("Low resolution video isn't supported in " + "this version.\r\n No DRU instance found.\r\n"); + break; + case (XVPHY_LOG_EVT_GT_QPLL_CFG_ERR): + xil_printf("QPLL config not found!\r\n"); + break; + case (XVPHY_LOG_EVT_GT_CPLL_CFG_ERR): + xil_printf("CPLL config not found!\r\n"); + break; + case (XVPHY_LOG_EVT_VD_NOT_SPRTD_ERR): + xil_printf("Warning: This video format is not " + "supported by this device\r\n"); + xil_printf(" " + "Change to another format\r\n"); + break; + case (XVPHY_LOG_EVT_MMCM_ERR): + xil_printf("MMCM config not found!\r\n"); + break; + default: + xil_printf("Unknown event\r\n"); + break; + } + + /* Read log data */ + Log = XVphy_LogRead(InstancePtr); + } +#else + xil_printf("\r\nINFO:: VPHY Log Feature is Disabled \r\n"); +#endif +} diff --git a/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_sinit.c b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_sinit.c new file mode 100644 index 00000000000000..3b45d098236c72 --- /dev/null +++ b/drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xvphy_sinit.c @@ -0,0 +1,81 @@ +/******************************************************************************* + * + * + * Copyright (C) 2015, 2016, 2017 Xilinx, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * +*******************************************************************************/ +/******************************************************************************/ +/** + * + * @file xvphy_sinit.c + * + * This file contains static initialization methods for the XVphy driver. + * + * @note None. + * + * <pre> + * MODIFICATION HISTORY: + * + * Ver Who Date Changes + * ----- ---- -------- ----------------------------------------------- + * 1.0 als 10/19/15 Initial release. + * </pre> + * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xvphy.h" +#include "xvphy_i.h" + +/*************************** Variable Declarations ****************************/ + +#ifndef XPAR_XVPHY_NUM_INSTANCES +#define XPAR_XVPHY_NUM_INSTANCES 0 +#endif + +/** + * A table of configuration structures containing the configuration information + * for each Video PHY core in the system. + */ +extern XVphy_Config XVphy_ConfigTable[XPAR_XVPHY_NUM_INSTANCES]; + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function looks for the device configuration based on the unique device + * ID. The table XVphy_ConfigTable[] contains the configuration information for + * each device in the system. + * + * @param DeviceId is the unique device ID of the device being looked up. + * + * @return A pointer to the configuration table entry corresponding to the + * given device ID, or NULL if no match is found. + * + * @note None. + * +*******************************************************************************/ +XVphy_Config *XVphy_LookupConfig(u16 DeviceId) +{ + XVphy_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0; Index < XPAR_XVPHY_NUM_INSTANCES; Index++) { + if (XVphy_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XVphy_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} |