From e7802db09dda867e2844cf5099ab11d1c7771ac6 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Fri, 12 Oct 2018 15:15:26 +0800 Subject: [PATCH 01/46] vphy: make dru optional Before acquiring dru clock, during probe, verify if dru feature is enabled in IP configuration. This can be checked by exammining the dru presence flag in device-tree Signed-off-by: Shikhar Mishra --- hdmi/phy-vphy.c | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/hdmi/phy-vphy.c b/hdmi/phy-vphy.c index 0b083a3..5285182 100644 --- a/hdmi/phy-vphy.c +++ b/hdmi/phy-vphy.c @@ -507,32 +507,34 @@ static int xvphy_probe(struct platform_device *pdev) XVphy_ConfigTable[instance].DrpClkFreq = 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) - dev_info(&pdev->dev, "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; - } + if (vphydev->xvphy.Config.DruIsPresent == (TRUE)) { + 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) + dev_info(&pdev->dev, "dru-clk not ready -EPROBE_DEFER\n"); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "failed to get the nidru clk.\n"); + return ret; + } - dru_clk_rate = clk_get_rate(vphydev->clkp); - dev_dbg(vphydev->dev,"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); + 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); - dev_dbg(vphydev->dev,"ref dru-clk rate = %lu\n", dru_clk_rate); + dev_dbg(vphydev->dev,"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); + dev_dbg(vphydev->dev,"ref dru-clk rate = %lu\n", dru_clk_rate); + } } provider = devm_of_phy_provider_register(&pdev->dev, xvphy_xlate); From a0771bf3fe52e797d3b6a12db189db6abce6942a Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Sat, 13 Oct 2018 06:59:37 +0800 Subject: [PATCH 02/46] hdmitx: Correction in XVidC_GetVideoModeIdExtensive XVidC_GetVideoModeIdExtensive() API was getting called with isExtensive flag as false which leads to selection of wrong VmID from video timing table. Now we are calling with isExtensive as TRUE. Signed-off-by: Shikhar Mishra --- hdmi/xilinx_drm_hdmi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index 305440f..9cfa534 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -1003,7 +1003,9 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, /* Disable TX TDMS clock */ XVphy_Clkout1OBufTdsEnable(VphyPtr, XVPHY_DIR_TX, (FALSE)); - VmId = XVidC_GetVideoModeIdExtensive(&vt, mode->vrefresh, FALSE, FALSE); + /* The isExtensive is made true to get the correct video timing by matching + * all the parameters */ + VmId = XVidC_GetVideoModeIdExtensive(&vt, mode->vrefresh, FALSE, TRUE); dev_dbg(xhdmi->dev,"VmId = %d\n", VmId); if (VmId == XVIDC_VM_NOT_SUPPORTED) { //no match found in timing table From b8508ae87e657e3ccd2a3c9afef4ae0b6e2861bf Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Sat, 13 Oct 2018 07:03:31 +0800 Subject: [PATCH 03/46] hdmitx:hdmirx:dt:bindings: Integration of audio Audio code added Signed-off-by: Shikhar Mishra --- .../devicetree/bindings/xlnx,v-hdmi-rx-ss.txt | 10 +- .../devicetree/bindings/xlnx,v-hdmi-tx-ss.txt | 11 + hdmi/Makefile | 3 +- hdmi/xilinx-hdmirx.c | 80 +++++- hdmi/xilinx_drm_hdmi.c | 104 ++++++- hdmi/xlnx_hdmirx_audio.c | 267 ++++++++++++++++++ hdmi/xlnx_hdmirx_audio.h | 22 ++ hdmi/xlnx_hdmitx_audio.c | 243 ++++++++++++++++ hdmi/xlnx_hdmitx_audio.h | 26 ++ 9 files changed, 759 insertions(+), 7 deletions(-) create mode 100644 hdmi/xlnx_hdmirx_audio.c create mode 100644 hdmi/xlnx_hdmirx_audio.h create mode 100644 hdmi/xlnx_hdmitx_audio.c create mode 100644 hdmi/xlnx_hdmitx_audio.h diff --git a/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt b/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt index 07788d1..7fba622 100644 --- a/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt +++ b/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt @@ -51,6 +51,9 @@ Required Properties: If present indicates inclusion of the optional core - xlnx,include-hdcp-2-2: Boolean parameter that denotes if hdcp22 is included. If present indicates inclusion of the optional core + - xlnx,audio-enabled: Boolean parameter to convey that design has audio + functionality + - xlnx,aes_parser: alias to audio channel status extractor block - ports: Video ports, using the DT bindings defined in ../video-interfaces.txt. The Rx only has an output port (0). @@ -63,6 +66,10 @@ added to the device tree reg = <0x0 0xa0270000 0x0 0x10000>; }; + hdmi_audio_aes_parser_0: hdmi_audio_aes_parser@a00b0000 { + reg = <0x0 0xa00b0000 0x0 0x10000>; + }; + hdmi_input_v_hdmi_rx_ss_0: v_hdmi_rx_ss@a0000000 { compatible = "xlnx,v-hdmi-rx-ss-3.1"; reg = <0x0 0xa0000000 0x0 0x100000>, <0x0 0xa0270000 0x0 0x10000>; @@ -79,7 +86,8 @@ added to the device tree xlnx,edid-ram-size = <0x100>; xlnx,include-hdcp-1-4; xlnx,include-hdcp-2-2; - + xlnx,audio-enabled = "true"; + xlnx,aes_parser = <&hdmi_audio_aes_parser_0>; ports { #address-cells = <1>; #size-cells = <0>; diff --git a/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt b/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt index f83083d..b75eacc 100644 --- a/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt +++ b/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt @@ -63,6 +63,9 @@ Required properties: Applicable when either hdcp14 or hdcp22 is included in the design - xlnx,hdcp-encrypt: Flag to enable/disable stream encryption Applicable when either hdcp14 or hdcp22 is included in the design + - xlnx,audio-enabled: Boolean parameter to convey that design has audio + functionality + - xlnx,xlnx-hdmi-acr-ctrl: alias to audio clock recovery block Sub-Node Properties: The device tree will need to include a sub-node for the encoder endpoint @@ -87,6 +90,12 @@ added to the device tree reg = <0x0 0xa0280000 0x0 0x10000>; }; + hdmi_acr_ctrl_0: hdmi_acr_ctrl@a0059000 { + /* This is a place holder node for a custom IP, user may need to update the entries */ + compatible = "xlnx,hdmi-acr-ctrl-1.0"; + reg = <0x0 0xa0059000 0x0 0x1000>; + }; + hdmi_output_v_hdmi_tx_ss_0: v_hdmi_tx_ss@a0080000 { compatible = "xlnx,v-hdmi-tx-ss-3.1"; reg = <0x0 0xa0080000 0x0 0x80000>, <0x0 0xa0280000 0x0 0x10000>; @@ -107,6 +116,8 @@ added to the device tree /* settings for HDCP */ xlnx,hdcp-authenticate = <0x1>; xlnx,hdcp-encrypt = <0x1>; + xlnx,audio-enabled = "true"; + xlnx,xlnx-hdmi-acr-ctrl = <&hdmi_acr_ctrl_0>; ports { #address-cells = <1>; diff --git a/hdmi/Makefile b/hdmi/Makefile index 6310f01..10be8d1 100644 --- a/hdmi/Makefile +++ b/hdmi/Makefile @@ -45,6 +45,7 @@ xilinx-hdmi-rx-objs += xilinx-hdmi-rx/xv_hdmirxss.o xilinx-hdmi-rx-objs += xilinx-hdmi-rx/xv_hdmirxss_log.o xilinx-hdmi-rx-objs += xilinx-hdmi-rx/xv_hdmirxss_coreinit.o xilinx-hdmi-rx-objs += xilinx-hdmi-rx/xv_hdmirxss_hdcp.o +xilinx-hdmi-rx-objs += xlnx_hdmirx_audio.o # DRM (HDMI TX) xilinx-hdmi-tx-objs := xilinx_drm_hdmi.o @@ -63,7 +64,7 @@ xilinx-hdmi-tx-objs += xilinx-hdmi-tx/xv_hdmitxss_hdcp.o xilinx-hdmi-tx-objs += xilinx-hdmi-tx/xvtc.o xilinx-hdmi-tx-objs += xilinx-hdmi-tx/xvtc_intr.o xilinx-hdmi-tx-objs += xilinx-hdmi-tx/xvtc_sinit.o - +xilinx-hdmi-tx-objs += xlnx_hdmitx_audio.o # PHY (HDMI RX/TX) xilinx-vphy-objs := phy-vphy.o diff --git a/hdmi/xilinx-hdmirx.c b/hdmi/xilinx-hdmirx.c index dc69825..0dd1b2e 100644 --- a/hdmi/xilinx-hdmirx.c +++ b/hdmi/xilinx-hdmirx.c @@ -39,6 +39,7 @@ /* for the HMAC, using password to decrypt HDCP keys */ #include "phy-xilinx-vphy/xhdcp22_common.h" #include "phy-xilinx-vphy/aes256.h" +#include "xlnx_hdmirx_audio.h" #define hdmi_mutex_lock(x) mutex_lock(x) #define hdmi_mutex_unlock(x) mutex_unlock(x) @@ -128,6 +129,12 @@ struct xhdmi_device { u8 Hdcp22PrivateKey[902]; u8 Hdcp14KeyA[328]; u8 Hdcp14KeyB[328]; + /* flag to indicate audio is enabled in device tree */ + bool audio_enabled; + /* flag to indicate audio is initialized */ + bool audio_init; + /* audio data to be shared with audio module */ + struct xlnx_hdmirx_audio_data *rx_audio_data; }; // Xilinx EDID @@ -814,6 +821,11 @@ static void RxStreamUpCallback(void *CallbackRef) /* notify source format change event */ v4l2_subdev_notify_event(&xhdmi->subdev, &xhdmi_ev_fmt); + /* TODO: As subsystem API XV_HdmiRxSs_AudioEnable is not available, + * core API is used currently. + */ + if (xhdmi->audio_init) + XV_HdmiRx_AudioEnable(HdmiRxSsPtr->HdmiRxPtr); #ifdef DEBUG v4l2_print_dv_timings("xilinx-hdmi-rx", "", & xhdmi->detected_timings, 1); #endif @@ -1586,6 +1598,8 @@ static int xhdmi_parse_of(struct xhdmi_device *xhdmi, XV_HdmiRxSs_Config *config isHdcp14_en = of_property_read_bool(node, "xlnx,include-hdcp-1-4"); isHdcp22_en = of_property_read_bool(node, "xlnx,include-hdcp-2-2"); + xhdmi->audio_enabled = + of_property_read_bool(node, "xlnx,audio-enabled"); if (isHdcp14_en) { /* HDCP14 Core */ @@ -1638,6 +1652,16 @@ static int xhdmi_parse_of(struct xhdmi_device *xhdmi, XV_HdmiRxSs_Config *config XHdcp22_Rng_ConfigTable[XPAR_XHDCP22_RNG_NUM_INSTANCES/2 + instance].BaseAddress = RX_HDCP22_RNG_OFFSET; } + if (xhdmi->audio_enabled) { + xhdmi->rx_audio_data->aes_base = hdmirx_parse_aud_dt(dev); + if (!xhdmi->rx_audio_data->aes_base) { + xhdmi->audio_init = false; + dev_err(dev, "audio rx: aes parser not found!\n"); + } + } else { + dev_info(dev, "hdmi rx audio disabled in DT\n"); + } + return 0; error_dt: @@ -1666,6 +1690,12 @@ static int xhdmi_probe(struct platform_device *pdev) xhdmi = devm_kzalloc(&pdev->dev, sizeof(*xhdmi), GFP_KERNEL); if (!xhdmi) return -ENOMEM; + xhdmi->rx_audio_data = + devm_kzalloc(&pdev->dev, sizeof(struct xlnx_hdmirx_audio_data), + GFP_KERNEL); + if (!xhdmi->rx_audio_data) + return -ENOMEM; + /* store pointer of the real device inside platform device */ xhdmi->dev = &pdev->dev; @@ -2002,12 +2032,22 @@ static int xhdmi_probe(struct platform_device *pdev) spin_lock_irqsave(&xhdmi->irq_lock, flags); XV_HdmiRxSs_IntrEnable(HdmiRxSsPtr); spin_unlock_irqrestore(&xhdmi->irq_lock, flags); - + /* probe has succeeded for this instance, increment instance index */ instance++; - dev_info(xhdmi->dev, "probe successful\n"); + if (xhdmi->audio_enabled && xhdmi->rx_audio_data->aes_base) { + ret = hdmirx_register_aud_dev(xhdmi->dev); + if (ret < 0) { + xhdmi->audio_init = false; + dev_err(xhdmi->dev, "hdmi rx audio init failed\n"); + } else { + xhdmi->audio_init = true; + dev_info(xhdmi->dev, "hdmi rx audio initialized\n"); + } + } /* return success */ + dev_info(xhdmi->dev, "probe successful\n"); return 0; error: @@ -2048,6 +2088,8 @@ static int xhdmi_remove(struct platform_device *pdev) v4l2_ctrl_handler_free(&xhdmi->ctrl_handler); media_entity_cleanup(&subdev->entity); clk_disable_unprepare(xhdmi->clk); + if (xhdmi->audio_init) + hdmirx_unregister_aud_dev(&pdev->dev); dev_dbg(xhdmi->dev,"removed.\n"); return 0; } @@ -2070,6 +2112,40 @@ static struct platform_driver xhdmi_driver = { .remove = xhdmi_remove, }; +struct xlnx_hdmirx_audio_data *hdmirx_get_audio_data(struct device *dev) +{ + struct xhdmi_device *xhdmi = dev_get_drvdata(dev); + + if (!xhdmi) + return NULL; + else + return xhdmi->rx_audio_data; +} + +u32 hdmirx_audio_startup(struct device *dev) +{ + u32 channel_count; + struct xhdmi_device *xhdmi = dev_get_drvdata(dev); + XV_HdmiRxSs *HdmiRxSsPtr = &xhdmi->xv_hdmirxss; + + hdmi_mutex_lock(&xhdmi->xhdmi_mutex); + XV_HdmiRx_AudioEnable(HdmiRxSsPtr->HdmiRxPtr); + channel_count = XV_HdmiRxSs_GetAudioChannels(HdmiRxSsPtr); + hdmi_mutex_unlock(&xhdmi->xhdmi_mutex); + + return channel_count; +} + +void hdmirx_audio_shutdown(struct device *dev) +{ + struct xhdmi_device *xhdmi = dev_get_drvdata(dev); + XV_HdmiRxSs *HdmiRxSsPtr = &xhdmi->xv_hdmirxss; + + hdmi_mutex_lock(&xhdmi->xhdmi_mutex); + XV_HdmiRx_AudioDisable(HdmiRxSsPtr->HdmiRxPtr); + hdmi_mutex_unlock(&xhdmi->xhdmi_mutex); +} + module_platform_driver(xhdmi_driver); MODULE_DESCRIPTION("Xilinx HDMI RXSS V4L2 driver"); diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index 9cfa534..08bcbb2 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -50,6 +50,8 @@ #include "phy-xilinx-vphy/xhdcp22_common.h" #include "phy-xilinx-vphy/aes256.h" +#include "xlnx_hdmitx_audio.h" + #define HDMI_MAX_LANES 4 #define XVPHY_TXREFCLK_RDY_LOW 0 @@ -107,6 +109,10 @@ * @xv_hdmitxss: IP low level driver structure * @IntrStatus: Flag to indicate irq status * @xvphy: pointer to xilinx video phy + * @audio_enabled: flag to indicate audio is enabled in device tree + * @audio_init: flag to indicate audio is initialized + * @tx_audio_data: audio data to be shared with audio module + * @audio_pdev: audio platform device */ struct xlnx_drm_hdmi { struct drm_encoder encoder; @@ -171,6 +177,10 @@ struct xlnx_drm_hdmi { u8 Hdcp22PrivateKey[902]; u8 Hdcp14KeyA[328]; u8 Hdcp14KeyB[328]; + bool audio_enabled; + bool audio_init; + struct xlnx_hdmitx_audio_data *tx_audio_data; + struct platform_device *audio_pdev; }; static const u8 Hdcp22Srm[] = { @@ -467,8 +477,6 @@ static void SendInfoframe(XV_HdmiTxSs *HdmiTxSsPtr) /* GCP does not need to be sent out because GCP packets on the TX side is handled by the HDMI TX core fully. */ - AuxFifo = XV_HdmiC_AudioIF_GeneratePacket(AudioInfoFramePtr); - XV_HdmiTxSs_SendGenericAuxInfoframe(HdmiTxSsPtr, &AuxFifo); SendVSInfoframe(HdmiTxSsPtr); } @@ -601,11 +609,29 @@ static void TxStreamDownCallback(void *CallbackRef) static void TxVsCallback(void *CallbackRef) { + XHdmiC_Aux aud_aux_fifo; struct xlnx_drm_hdmi *xhdmi = (struct xlnx_drm_hdmi *)CallbackRef; XV_HdmiTxSs *HdmiTxSsPtr = &xhdmi->xv_hdmitxss; /* Send NULL Aux packet */ SendInfoframe(HdmiTxSsPtr); + + if (xhdmi->audio_init) { + aud_aux_fifo.Header.Byte[0] = xhdmi->tx_audio_data->buffer[0]; + aud_aux_fifo.Header.Byte[1] = xhdmi->tx_audio_data->buffer[1]; + aud_aux_fifo.Header.Byte[2] = xhdmi->tx_audio_data->buffer[2]; + aud_aux_fifo.Header.Byte[3] = 0; + + aud_aux_fifo.Data.Byte[0] = xhdmi->tx_audio_data->buffer[3]; + aud_aux_fifo.Data.Byte[1] = xhdmi->tx_audio_data->buffer[4]; + aud_aux_fifo.Data.Byte[2] = xhdmi->tx_audio_data->buffer[5]; + aud_aux_fifo.Data.Byte[3] = xhdmi->tx_audio_data->buffer[6]; + aud_aux_fifo.Data.Byte[4] = xhdmi->tx_audio_data->buffer[7]; + aud_aux_fifo.Data.Byte[5] = xhdmi->tx_audio_data->buffer[8]; + + XV_HdmiTxSs_SendGenericAuxInfoframe(HdmiTxSsPtr, + &aud_aux_fifo); + } } void TxHdcpAuthenticatedCallback(void *CallbackRef) @@ -2001,6 +2027,8 @@ static int xlnx_drm_hdmi_parse_of(struct xlnx_drm_hdmi *xhdmi, XV_HdmiTxSs_Confi isHdcp14_en = of_property_read_bool(node, "xlnx,include-hdcp-1-4"); isHdcp22_en = of_property_read_bool(node, "xlnx,include-hdcp-2-2"); + xhdmi->audio_enabled = + of_property_read_bool(node, "xlnx,audio-enabled"); if (isHdcp14_en) { /* HDCP14 Core */ @@ -2064,7 +2092,16 @@ static int xlnx_drm_hdmi_parse_of(struct xlnx_drm_hdmi *xhdmi, XV_HdmiTxSs_Confi } // set default color format to RGB xhdmi->xvidc_colorfmt = XVIDC_CSF_RGB; - return 0; + + if (xhdmi->audio_enabled) { + xhdmi->tx_audio_data->acr_base = hdmitx_parse_aud_dt(dev); + if (!xhdmi->tx_audio_data->acr_base) { + xhdmi->audio_init = false; + dev_err(dev, "tx audio: acr base parse failed\n"); + } + } else { + dev_info(dev, "hdmi tx audio disabled in DT\n"); + } error_dt: dev_err(xhdmi->dev, "Error parsing device tree"); @@ -2084,6 +2121,13 @@ static int xlnx_drm_hdmi_probe(struct platform_device *pdev) xhdmi = devm_kzalloc(&pdev->dev, sizeof(*xhdmi), GFP_KERNEL); if (!xhdmi) return -ENOMEM; + + xhdmi->tx_audio_data = + devm_kzalloc(&pdev->dev, sizeof(struct xlnx_hdmitx_audio_data), + GFP_KERNEL); + if (!xhdmi->tx_audio_data) + return -ENOMEM; + /* store pointer of the real device inside platform device */ xhdmi->dev = &pdev->dev; @@ -2198,6 +2242,7 @@ static int xlnx_drm_hdmi_probe(struct platform_device *pdev) return ret; } + xhdmi->tx_audio_data->tmds_clk = clk_get_rate(xhdmi->tmds_clk); /* support to drive an external retimer IC on the TX path, depending on TX clock line rate */ xhdmi->retimer_clk = devm_clk_get(&pdev->dev, "retimer-clk"); if (IS_ERR(xhdmi->retimer_clk)) { @@ -2275,6 +2320,16 @@ static int xlnx_drm_hdmi_probe(struct platform_device *pdev) /* probe has succeeded for this instance, increment instance index */ instance++; + if (xhdmi->audio_enabled && xhdmi->tx_audio_data->acr_base) { + xhdmi->audio_pdev = hdmitx_register_aud_dev(xhdmi->dev); + if (IS_ERR(xhdmi->audio_pdev)) { + xhdmi->audio_init = false; + dev_err(xhdmi->dev, "hdmi tx audio init failed\n"); + } else { + xhdmi->audio_init = true; + dev_info(xhdmi->dev, "hdmi tx audio initialized\n"); + } + } dev_info(xhdmi->dev, "probe successful\n"); return component_add(xhdmi->dev, &xlnx_drm_hdmi_component_ops); @@ -2294,12 +2349,55 @@ static int xlnx_drm_hdmi_probe(struct platform_device *pdev) static int xlnx_drm_hdmi_remove(struct platform_device *pdev) { struct platform_driver *pdrv; + struct xlnx_drm_hdmi *xhdmi = platform_get_drvdata(pdev); + if (xhdmi->audio_init) + platform_device_unregister(xhdmi->audio_pdev); sysfs_remove_group(&pdev->dev.kobj, &attr_group); component_del(&pdev->dev, &xlnx_drm_hdmi_component_ops); return 0; } +struct xlnx_hdmitx_audio_data *hdmitx_get_audio_data(struct device *dev) +{ + struct xlnx_drm_hdmi *xhdmi = dev_get_drvdata(dev); + + if (!xhdmi) + return NULL; + else + return xhdmi->tx_audio_data; +} + +void hdmitx_audio_startup(struct device *dev) +{ + XV_HdmiTxSs *HdmiTxSsPtr; + struct xlnx_drm_hdmi *xhdmi = dev_get_drvdata(dev); + XV_HdmiTxSs *xv_hdmitxss = (XV_HdmiTxSs *)&xhdmi->xv_hdmitxss; + + hdmi_mutex_lock(&xhdmi->hdmi_mutex); + XV_HdmiTxSs_AudioMute(xv_hdmitxss, 0); + hdmi_mutex_unlock(&xhdmi->hdmi_mutex); +} + +void hdmitx_audio_shutdown(struct device *dev) +{ + XV_HdmiTxSs *HdmiTxSsPtr; + struct xlnx_drm_hdmi *xhdmi = dev_get_drvdata(dev); + XV_HdmiTxSs *xv_hdmitxss = (XV_HdmiTxSs *)&xhdmi->xv_hdmitxss; + + hdmi_mutex_lock(&xhdmi->hdmi_mutex); + XV_HdmiTxSs_AudioMute(xv_hdmitxss, 1); + hdmi_mutex_unlock(&xhdmi->hdmi_mutex); +} + +void hdmitx_audio_mute(struct device *dev, bool enable) +{ + if (enable) + hdmitx_audio_shutdown(dev); + else + hdmitx_audio_startup(dev); +} + static const struct of_device_id xlnx_drm_hdmi_of_match[] = { { .compatible = "xlnx,v-hdmi-tx-ss-3.1", }, { /* end of table */ }, diff --git a/hdmi/xlnx_hdmirx_audio.c b/hdmi/xlnx_hdmirx_audio.c new file mode 100644 index 0000000..8a34a42 --- /dev/null +++ b/hdmi/xlnx_hdmirx_audio.c @@ -0,0 +1,267 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Xilinx ALSA SoC HDMI audio capture support + * + * Copyright (C) 2017-2018 Xilinx, Inc. + * + */ + +#include +#include +#include + +#include "xlnx_hdmirx_audio.h" + +#define XV_AES_ENABLE 0x8 +#define XV_AES_CH_STS_REG1 0x50 +#define XV_AES_CH_STS_REG2 0x54 + +/* hdmirx_parse_aud_dt - parse AES node from DT + * @dev: device + * + * Parse the DT entry related to AES IP. This IP AES header + * from incoming audio stream. + * + */ +void __iomem *hdmirx_parse_aud_dt(struct device *dev) +{ + struct device_node *aes_node; + struct resource res; + void __iomem *aes_base; + int rc; + struct device_node *node = dev->of_node; + + /* audio errors are not considered fatal */ + aes_node = of_parse_phandle(node, "xlnx,aes_parser", 0); + if (!aes_node) { + dev_err(dev, "aes parser not found\n"); + aes_base = NULL; + } else { + rc = of_address_to_resource(aes_node, 0, &res); + if (rc) { + dev_err(dev, "aes parser:addr to resource failed\n"); + aes_base = NULL; + } else { + aes_base = devm_ioremap_resource(dev, &res); + if (IS_ERR(aes_base)) { + dev_err(dev, "aes ioremap failed\n"); + aes_base = NULL; + } else + writel(1, aes_base + XV_AES_ENABLE); + } + of_node_put(aes_node); + } + return aes_base; +} + +/* parse_consumer_format - parse AES stream header + * @reg1_val: AES register content + * @reg2_val: AES register content + * @srate: sampling rate + * @sig_bits: valid bits in given container format + * + * This function parses AES header in consumer format + */ +static void parse_consumer_format(u32 reg1_val, u32 reg2_val, + u32 *srate, u32 *sig_bits) +{ + u32 max_word_length; + + switch ((reg1_val & 0x0F000000) >> 24) { + case 0: + *srate = 44100; + break; + case 2: + *srate = 48000; + break; + case 3: + *srate = 32000; + break; + } + + if (reg2_val & 0x1) { + max_word_length = 24; + reg2_val = (reg2_val & 0xE) >> 1; + switch (reg2_val) { + case 0: + /* not indicated */ + *sig_bits = 0; + break; + case 1: + *sig_bits = 20; + break; + case 6: + *sig_bits = 21; + break; + case 2: + *sig_bits = 22; + break; + case 4: + *sig_bits = 23; + break; + case 5: + *sig_bits = 24; + break; + } + } else { + max_word_length = 20; + reg2_val = (reg2_val & 0xE) >> 1; + switch (reg2_val) { + case 0: + /* not indicated */ + *sig_bits = 0; + break; + case 1: + *sig_bits = 16; + break; + case 6: + *sig_bits = 17; + break; + case 2: + *sig_bits = 18; + break; + case 4: + *sig_bits = 19; + break; + case 5: + *sig_bits = 20; + break; + } + } +} + +static void parse_professional_format(u32 reg1_val, u32 reg2_val, + u32 *srate, u32 *sig_bits) +{ +} + +/* xlnx_rx_pcm_startup - initialze audio during audio usecase + * + * This function is called by ALSA framework before audio + * capture begins. This callback initializes audio and extracts + * channel status bits and sets them as constraints + * + * Return: 0 on success + */ +static int xlnx_rx_pcm_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + int rate, err; + u32 channels, srate, sig_bits, reg1_val, reg2_val, status; + + struct snd_soc_codec *codec = dai->codec; + struct snd_pcm_runtime *rtd = substream->runtime; + struct xlnx_hdmirx_audio_data *adata = hdmirx_get_audio_data(dai->dev); + + if (!adata) + return -EINVAL; + + channels = hdmirx_audio_startup(dai->dev); + + reg1_val = readl(adata->aes_base + XV_AES_CH_STS_REG1); + reg2_val = readl(adata->aes_base + XV_AES_CH_STS_REG2); + if (reg1_val & 0x1) + parse_professional_format(reg1_val, reg2_val, &srate, + &sig_bits); + else + parse_consumer_format(reg1_val, reg2_val, &srate, &sig_bits); + + err = snd_pcm_hw_constraint_minmax(rtd, SNDRV_PCM_HW_PARAM_RATE, + srate, srate); + if (err < 0) { + dev_err(codec->dev, "failed to constrain samplerate to %dHz\n", + srate); + return err; + } + + /* During record, after AES bits(8) are removed, pcm is at max 24bits. + * Out of 24 bits, sig_bits represent valid number of audio bits from + * input stream + */ + err = snd_pcm_hw_constraint_msbits(rtd, 0, 24, sig_bits); + + if (err < 0) { + dev_err(codec->dev, + "failed to constrain 'bits per sample' %d bits\n", sig_bits); + return err; + } + err = snd_pcm_hw_constraint_minmax(rtd, SNDRV_PCM_HW_PARAM_CHANNELS, + channels, channels); + if (err < 0) { + dev_err(codec->dev, + "failed to constrain channel count to %d\n", channels); + return err; + } + + dev_info(codec->dev, "set samplerate constraint to %dHz\n", srate); + dev_info(codec->dev, "set 'bits per sample' constraint to %d\n", + sig_bits); + dev_info(codec->dev, "set channels constraint to %d\n", channels); + + return 0; +} + +/* xlnx_rx_pcm_shutdown - Deinitialze audio when audio usecase is stopped + * + * This function is called by ALSA framework before audio capture usecase + * ends. + */ +static void xlnx_rx_pcm_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + hdmirx_audio_shutdown(dai->dev); +} + +static const struct snd_soc_dai_ops xlnx_rx_dai_ops = { + .startup = xlnx_rx_pcm_startup, + .shutdown = xlnx_rx_pcm_shutdown, +}; + +static struct snd_soc_dai_driver xlnx_rx_audio_dai = { + .name = "xlnx_hdmi_rx", + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S24_LE, + }, + .ops = &xlnx_rx_dai_ops, +}; + +static int xlnx_rx_codec_probe(struct snd_soc_codec *codec) +{ + return 0; +} + +static int xlnx_rx_codec_remove(struct snd_soc_codec *codec) +{ + return 0; +} + +static struct snd_soc_codec_driver xlnx_rx_codec_driver = { + .probe = xlnx_rx_codec_probe, + .remove = xlnx_rx_codec_remove, +}; + +/* hdmirx_register_aud_dev - register audio device + * + * This functions registers codec DAI device as part of + * ALSA SoC framework. + */ +int hdmirx_register_aud_dev(struct device *dev) +{ + return snd_soc_register_codec(dev, &xlnx_rx_codec_driver, + &xlnx_rx_audio_dai, 1); +} + +/* hdmirx_register_aud_dev - register audio device + * + * This functions unregisters codec DAI device + */ +void hdmirx_unregister_aud_dev(struct device *dev) +{ + snd_soc_unregister_codec(dev); +} + diff --git a/hdmi/xlnx_hdmirx_audio.h b/hdmi/xlnx_hdmirx_audio.h new file mode 100644 index 0000000..0411fab --- /dev/null +++ b/hdmi/xlnx_hdmirx_audio.h @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Xilinx ALSA SoC HDMI audio capture support + * + * Copyright (C) 2017-2018 Xilinx, Inc. + * + */ + +#ifndef __XILINX_HDMI_RX_AUD_H__ +#define __XILINX_HDMI_RX_AUD_H__ + +struct xlnx_hdmirx_audio_data *hdmirx_get_audio_data(struct device *dev); +int hdmirx_register_aud_dev(struct device *dev); +void hdmirx_unregister_aud_dev(struct device *dev); +void __iomem *hdmirx_parse_aud_dt(struct device *dev); +u32 hdmirx_audio_startup(struct device *dev); +void hdmirx_audio_shutdown(struct device *dev); + +struct xlnx_hdmirx_audio_data { + void __iomem *aes_base; +}; +#endif /* __XILINX_HDMI_RX_AUD_H__ */ diff --git a/hdmi/xlnx_hdmitx_audio.c b/hdmi/xlnx_hdmitx_audio.c new file mode 100644 index 0000000..a6b902d --- /dev/null +++ b/hdmi/xlnx_hdmitx_audio.c @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Xilinx ALSA SoC HDMI audio playback support + * + * Copyright (C) 2017-2018 Xilinx, Inc. + * + */ + +#include +#include + +#include "xlnx_hdmitx_audio.h" + +#define XV_ACR_ENABLE 0x4 +#define XV_ACR_N 0xc + +struct acr_n_table { + u32 tmds_rate; + u32 acr_nval[7]; +}; + +/* N values for Audio Clock Regeneration */ +const struct acr_n_table acr_n_table[] = { + /* TMDSClk 32k 44k1 48k 88k2 96k 176k4 192k */ + { 0, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + { 25200000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + { 27000000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + { 31500000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + { 33750000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + { 37800000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + { 40500000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + { 50400000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + { 54000000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + { 67500000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + { 74250000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + { 81000000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + { 92812500, { 8192, 6272, 12288, 12544, 24576, 25088, 49152} }, + {108000000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + {111375000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + {148500000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + {185625000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + {222750000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + {297000000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + {371250000, { 6144, 4704, 5120, 9408, 10240, 18816, 20480} }, + {445500000, { 4096, 4704, 5120, 9408, 10240, 18816, 20480} }, + {594000000, { 3072, 4704, 5120, 9408, 10240, 18816, 20480} } +}; + +static u16 srate_to_index(u32 srate) +{ + u16 index; + + switch (srate) { + case 32000: + index = 0; + break; + case 44100: + index = 1; + break; + case 48000: + index = 2; + break; + case 96000: + index = 3; + break; + case 176400: + index = 4; + break; + case 192000: + index = 5; + break; + default: + index = 0; + break; + } + + return index; +} + +/* xhdmi_acr_get_n - calculate N value from lookup table + * @tmds_rate: TMDS clock + * @srate: sampling rate + * + * This function retrieves N value from the lookup table using + * TMDS clock and sampling rate + * + * Return: N value + */ +static const unsigned int xhdmi_acr_get_n(unsigned int tmds_rate, int srate) +{ + struct acr_n_table const *item; + u16 i, idx; + + for (i = 0; i < sizeof(acr_n_table)/sizeof(struct acr_n_table); i++) { + item = &acr_n_table[i]; + if (item->tmds_rate == tmds_rate) { + idx = srate_to_index(srate); + return item->acr_nval[idx]; + } + } + + /* if not found return default */ + item = &acr_n_table[0]; + idx = srate_to_index(srate); + return item->acr_nval[idx]; +} + +/* hdmitx_parse_aud_dt - parse ACR node from DT + * @dev: device + * + * Parse the DT entry related to ACR IP. + */ +void __iomem *hdmitx_parse_aud_dt(struct device *dev) +{ + u32 val; + int rc; + struct device_node *node, *acr_node; + void __iomem *acr_base; + struct resource acr_res; + + node = dev->of_node; + acr_node = of_parse_phandle(node, "xlnx,xlnx-hdmi-acr-ctrl", 0); + if (!acr_node) { + dev_err(dev, "failed to get acr_node!\n"); + acr_base = NULL; + } else { + rc = of_address_to_resource(acr_node, 0, &acr_res); + if (rc) { + dev_err(dev, "acr resource failed: %d\n", rc); + acr_base = NULL; + } else { + acr_base = devm_ioremap_resource(dev, &acr_res); + if (IS_ERR(acr_base)) { + dev_err(dev, "acr ioremap failed\n"); + acr_base = NULL; + } + } + of_node_put(acr_node); + } + return acr_base; +} + +/* audio_codec_startup - initialze audio during audio usecase + * + * This function is called by ALSA framework before audio + * playback begins. This callback initializes audio + * + * Return: 0 on success + */ +static int audio_codec_startup(struct device *dev, void *data) +{ + hdmitx_audio_startup(dev); + + return 0; +} + +/* audio_codec_hw_params - sets the playback stream properties + * @dev: device + * @data: optional data set during registration + * @fmt: Protocol between ASoC cpu-dai and HDMI-encoder + * @hparams: stream parameters + * + * This function is called by ALSA framework after startup callback + * packs the audio infoframe from stream paremters and programs ACR + * block + * + * Return: 0 on success + */ +static int audio_codec_hw_params(struct device *dev, void *data, + struct hdmi_codec_daifmt *fmt, + struct hdmi_codec_params *hparams) +{ + u32 n, i; + struct hdmi_audio_infoframe *frame = &hparams->cea; + struct xlnx_hdmitx_audio_data *adata = hdmitx_get_audio_data(dev); + + if (!adata) + return -EINVAL; + + hdmi_audio_infoframe_pack(&hparams->cea, adata->buffer, + HDMI_INFOFRAME_SIZE(AUDIO)); + n = xhdmi_acr_get_n(adata->tmds_clk, hparams->sample_rate); + + writel(2, adata->acr_base + XV_ACR_ENABLE); + writel(n, adata->acr_base + XV_ACR_N); + writel(3, adata->acr_base + XV_ACR_ENABLE); + + return 0; +} + +/* audio_codec_shutdown - Deinitialze audio when audio usecase is stopped + * + * This function is called by ALSA framework before audio playback usecase + * ends. + */ +static void audio_codec_shutdown(struct device *dev, void *data) +{ + hdmitx_audio_shutdown(dev); +} + +/* audio_codec_digital_mute - mute or unmute audio + * + * This function is called by ALSA framework before audio usecase + * starts and before audio usecase ends + */ + +static int audio_codec_digital_mute(struct device *dev, void *data, bool enable) +{ + hdmitx_audio_mute(dev, enable); + + return 0; +} + +static const struct hdmi_codec_ops audio_ops = { + .audio_startup = audio_codec_startup, + .hw_params = audio_codec_hw_params, + .audio_shutdown = audio_codec_shutdown, + .digital_mute = audio_codec_digital_mute, +}; + +/* hdmitx_register_aud_dev - register audio device + * @dev: device + * + * This functions registers a new platform device and a corresponding + * module is loaded which registers a audio codec device and + * calls the registered callbacks + * + * Return: platform device + */ +struct platform_device *hdmitx_register_aud_dev(struct device *dev) +{ + struct platform_device *audio_pdev; + struct hdmi_codec_pdata codec_pdata = { + .ops = &audio_ops, + .i2s = 1, + .max_i2s_channels = 2, + }; + + audio_pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME, + 0, &codec_pdata, sizeof(codec_pdata)); + + return audio_pdev; +} diff --git a/hdmi/xlnx_hdmitx_audio.h b/hdmi/xlnx_hdmitx_audio.h new file mode 100644 index 0000000..224a539 --- /dev/null +++ b/hdmi/xlnx_hdmitx_audio.h @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Xilinx ALSA SoC HDMI audio playback support + * + * Copyright (C) 2017-2018 Xilinx, Inc. + * + */ + +#ifndef __XILINX_HDMI_TX_AUD_H__ +#define __XILINX_HDMI_TX_AUD_H__ + +struct xlnx_hdmitx_audio_data { + u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)]; + unsigned int tmds_clk; + void __iomem *acr_base; +}; + +struct xlnx_hdmitx_audio_data *hdmitx_get_audio_data(struct device *dev); +void __iomem *hdmitx_parse_aud_dt(struct device *dev); +struct platform_device *hdmitx_register_aud_dev(struct device *dev); + +void hdmitx_audio_startup(struct device *dev); +void hdmitx_audio_shutdown(struct device *dev); +void hdmitx_audio_mute(struct device *dev, bool enable); + +#endif /* __XILINX_HDMI_TX_AUD_H__ */ From 5bc312b0310da47c0f21a5bb3790a6a4691a888a Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Sat, 13 Oct 2018 07:05:46 +0800 Subject: [PATCH 04/46] hdmitx: Disable IbufD when cable disconnect Disable IbufD when cable disconnect Signed-off-by: Shikhar Mishra --- hdmi/xilinx_drm_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index 08bcbb2..435eb6c 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -524,7 +524,7 @@ static void TxConnectCallback(void *CallbackRef) xhdmi->have_edid = 0; xhdmi->is_hdmi_20_sink = 0; /* do not disable ibufds - stream will not go down*/ -// XVphy_IBufDsEnable(VphyPtr, 0, XVPHY_DIR_TX, (FALSE)); + XVphy_IBufDsEnable(VphyPtr, 0, XVPHY_DIR_TX, (FALSE)); } xvphy_mutex_unlock(xhdmi->phy[0]); dev_dbg(xhdmi->dev,"TxConnectCallback() done\n"); From f9994e8fc406a610af2ee72ac845bf033e754b70 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Sat, 13 Oct 2018 07:08:48 +0800 Subject: [PATCH 05/46] hdmitx:hdmirx:phy: Updated driver IP version Update of all driver code Signed-off-by: Shikhar Mishra --- hdmi/phy-xilinx-vphy/xhdcp1x_cipher.c | 2 +- hdmi/phy-xilinx-vphy/xhdcp1x_rx.c | 5 ++- hdmi/phy-xilinx-vphy/xhdcp1x_tx.c | 3 +- hdmi/phy-xilinx-vphy/xv_hdmic.c | 6 ++- hdmi/phy-xilinx-vphy/xvidc_timings_table.c | 8 ++-- hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c | 8 ++++ hdmi/xilinx-hdmi-rx/xv_hdmirxss.c | 44 ++++++++++++++++------ hdmi/xilinx-hdmirx.c | 15 ++++---- 8 files changed, 63 insertions(+), 28 deletions(-) diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_cipher.c b/hdmi/phy-xilinx-vphy/xhdcp1x_cipher.c index 47c365f..cf46e14 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_cipher.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_cipher.c @@ -313,7 +313,7 @@ int XHdcp1x_CipherDoRequest(XHdcp1x *InstancePtr, /* Verify arguments. */ Xil_AssertNonvoid(InstancePtr != NULL); - Xil_AssertNonvoid(Request >= (XHDCP1X_CIPHER_REQUEST_BLOCK)); + Xil_AssertNonvoid(Request < (XHDCP1X_CIPHER_REQUEST_MAX)); /* Check that it is not disabled */ if (!XHdcp1x_CipherIsEnabled(InstancePtr)) { diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_rx.c b/hdmi/phy-xilinx-vphy/xhdcp1x_rx.c index 72821fe..55c389c 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_rx.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_rx.c @@ -890,10 +890,11 @@ int XHdcp1x_RxGetRepeaterInfo(XHdcp1x *InstancePtr, ******************************************************************************/ static void XHdcp1x_RxDebugLog(const XHdcp1x *InstancePtr, const char *LogMsg) { - char Label[20]; + char Label[16]; /* Format Label */ - snprintf(Label, 20, "hdcp-rx(%d) - ", InstancePtr->Config.DeviceId); + snprintf(Label, sizeof(Label), "hdcp-rx(%hu) - ", + InstancePtr->Config.DeviceId); /* Log it */ XHDCP1X_DEBUG_LOGMSG(Label); diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_tx.c b/hdmi/phy-xilinx-vphy/xhdcp1x_tx.c index 373343f..2122062 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_tx.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_tx.c @@ -987,7 +987,8 @@ static void XHdcp1x_TxDebugLog(const XHdcp1x *InstancePtr, const char *LogMsg) char Label[16]; /* Format Label */ - snprintf(Label, 16, "hdcp-tx(%d) - ", InstancePtr->Config.DeviceId); + snprintf(Label, sizeof(Label), "hdcp-tx(%hu) - ", + InstancePtr->Config.DeviceId); /* Log it */ XHDCP1X_DEBUG_LOGMSG(Label); diff --git a/hdmi/phy-xilinx-vphy/xv_hdmic.c b/hdmi/phy-xilinx-vphy/xv_hdmic.c index 9d16af7..927a4fd 100644 --- a/hdmi/phy-xilinx-vphy/xv_hdmic.c +++ b/hdmi/phy-xilinx-vphy/xv_hdmic.c @@ -29,6 +29,7 @@ * Ver Who Date Changes * ----- ---- -------- ----------------------------------------------- * 1.0 EB 21/12/17 Initial release. + * 1.1 EB 10/04/18 Fixed a bug in XV_HdmiC_ParseAudioInfoFrame * * *******************************************************************************/ @@ -210,7 +211,8 @@ void XV_HdmiC_ParseAudioInfoFrame(XHdmiC_Aux *AuxPtr, XHdmiC_AudioInfoFrame *Aud AudIFPtr->ChannelCount = (AuxPtr->Data.Byte[1]) & 0x7; /* PB2 */ - AudIFPtr->SampleFrequency = AuxPtr->Data.Byte[2] & 0x1f; + AudIFPtr->SampleFrequency = (AuxPtr->Data.Byte[2] >> 2) & 0x7; + AudIFPtr->SampleSize = AuxPtr->Data.Byte[2] & 0x3; /* PB4 */ AudIFPtr->ChannelAllocation = AuxPtr->Data.Byte[4]; @@ -281,7 +283,7 @@ XHdmiC_Aux XV_HdmiC_AVIIF_GeneratePacket(XHdmiC_AVI_InfoFrame *infoFramePtr) /* PB6 */ aux.Data.Byte[6] = infoFramePtr->TopBar & 0xff; - + aux.Data.Byte[7] = 0; /* PB8 */ diff --git a/hdmi/phy-xilinx-vphy/xvidc_timings_table.c b/hdmi/phy-xilinx-vphy/xvidc_timings_table.c index 3764926..aede471 100644 --- a/hdmi/phy-xilinx-vphy/xvidc_timings_table.c +++ b/hdmi/phy-xilinx-vphy/xvidc_timings_table.c @@ -38,6 +38,8 @@ * aad 07/10/17 Add XVIDC_VM_3840x2160_60_P_RB video format * aad 09/05/17 Fixed timings for 1366x768_60_P * aad 09/05/17 Added 1366x768_60_P_RB + * 4.4 eb 09/04/18 Fixed timings for 1280x720_24_P, 1280x720_25_P, + * 1280x720_30_P * * *******************************************************************************/ @@ -193,13 +195,13 @@ const XVidC_VideoTimingMode XVidC_VideoTimingModes[XVIDC_VM_NUM_SUPPORTED] = {1152, 64, 128, 256, 1600, 1, 864, 1, 3, 32, 900, 0, 0, 0, 0, 1} }, { XVIDC_VM_1280x720_24_P, "1280x720@24Hz", XVIDC_FR_24HZ, - {1280, 970, 905, 970, 4125, 1, + {1280, 1760, 40, 220, 3300, 1, 720, 5, 5, 20, 750, 0, 0, 0, 0, 1} }, { XVIDC_VM_1280x720_25_P, "1280x720@25Hz", XVIDC_FR_25HZ, - {1280, 970, 740, 970, 3960, 1, + {1280, 2420, 40, 220, 3960, 1, 720, 5, 5, 20, 750, 0, 0, 0, 0, 1} }, { XVIDC_VM_1280x720_30_P, "1280x720@30Hz", XVIDC_FR_30HZ, - {1280, 970, 80, 970, 3300, 1, + {1280, 1760, 40, 220, 3300, 1, 720, 5, 5, 20, 750, 0, 0, 0, 0, 1} }, { XVIDC_VM_1280x720_50_P, "1280x720@50Hz", XVIDC_FR_50HZ, {1280, 440, 40, 220, 1980, 1, diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c b/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c index 45e563a..1ba4bbc 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c @@ -46,6 +46,7 @@ * 16/11/17 Update Reset sequence with dedicated reset for * each clock domain * MMO 08/02/18 Adding proper handling for Sync Loss/Sync Recover +* 2.10 YH 13/04/18 Fixed a bug in PioIntrHandler * * ******************************************************************************/ @@ -693,6 +694,13 @@ void HdmiRx_PioIntrHandler(XV_HdmiRx *InstancePtr) } } + /* Bridge Overflow event has occurred */ + if ((Event) & (XV_HDMIRX_PIO_IN_BRDG_OVERFLOW_MASK)) { + // Check if user callback has been registered + if (InstancePtr->IsBrdgOverflowCallbackSet) { + InstancePtr->BrdgOverflowCallback(InstancePtr->BrdgOverflowRef); + } + } } diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c index c1b215f..a387980 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c @@ -97,6 +97,10 @@ * XV_HdmiRxSs_GetVSIF * Updated XV_HdmiRxSs_ConfigBridgeMode so Pixel * Pepetition is based on received AVI InfoFrame +* 5.10 MMO 06/04/18 Updated XV_HdmiRxSs_ToggleHpd and XV_HdmiRxSs_Stop +* for cleaner HPD flow during transition from HDMI2.0 +* to HDMI1.4 +* YH 13/04/18 Fixed a bug in XV_HdmiRxSs_BrdgOverflowCallback ******************************************************************************/ /***************************** Include Files *********************************/ @@ -617,7 +621,7 @@ void XV_HdmiRxSs_Start(XV_HdmiRxSs *InstancePtr) #ifdef XV_HDMIRXSS_LOG_ENABLE XV_HdmiRxSs_LogWrite(InstancePtr, XV_HDMIRXSS_LOG_EVT_START, 0); #endif - /* Set RX hot plug detect */ + /* Drive HDMI RX HPD High */ XV_HdmiRx_SetHpd(InstancePtr->HdmiRxPtr, TRUE); /* Disable Audio Peripheral */ @@ -638,6 +642,16 @@ void XV_HdmiRxSs_Start(XV_HdmiRxSs *InstancePtr) void XV_HdmiRxSs_Stop(XV_HdmiRxSs *InstancePtr) { Xil_AssertVoid(InstancePtr != NULL); + + /* Clear SCDC variables */ + XV_HdmiRx_DdcScdcClear(InstancePtr->HdmiRxPtr); + + /* Disable the scrambler */ + XV_HdmiRx_SetScrambler(InstancePtr->HdmiRxPtr, (FALSE)); + + /* Drive HDMI RX HPD Low */ + XV_HdmiRx_SetHpd(InstancePtr->HdmiRxPtr, (FALSE)); + #ifdef XV_HDMIRXSS_LOG_ENABLE XV_HdmiRxSs_LogWrite(InstancePtr, XV_HDMIRXSS_LOG_EVT_STOP, 0); #endif @@ -762,8 +776,8 @@ static void XV_HdmiRxSs_BrdgOverflowCallback(void *CallbackRef) XV_HdmiRxSs *HdmiRxSsPtr = (XV_HdmiRxSs *)CallbackRef; // Check if user callback has been registered - if (HdmiRxSsPtr->ConnectCallback) { - HdmiRxSsPtr->ConnectCallback(HdmiRxSsPtr->ConnectRef); + if (HdmiRxSsPtr->BrdgOverflowCallback) { + HdmiRxSsPtr->BrdgOverflowCallback(HdmiRxSsPtr->BrdgOverflowRef); } } @@ -862,7 +876,7 @@ static void XV_HdmiRxSs_AuxCallback(void *CallbackRef) // Parse Aux to retrieve Avi InfoFrame XV_HdmiC_ParseAVIInfoFrame(AuxPtr, AviInfoFramePtr); HdmiRxSsPtr->HdmiRxPtr->Stream.Video.ColorFormatId = - XV_HdmiRx_GetAviColorSpace(HdmiRxSsPtr->HdmiRxPtr); + XV_HdmiRx_GetAviColorSpace(HdmiRxSsPtr->HdmiRxPtr); HdmiRxSsPtr->HdmiRxPtr->Stream.Vic = XV_HdmiRx_GetAviVic(HdmiRxSsPtr->HdmiRxPtr); HdmiRxSsPtr->HdmiRxPtr->Stream.Video.AspectRatio = @@ -903,7 +917,7 @@ static void XV_HdmiRxSs_SyncLossCallback(void *CallbackRef) XV_HdmiRxSs *HdmiRxSsPtr = (XV_HdmiRxSs *)CallbackRef; if (HdmiRxSsPtr->HdmiRxPtr->Stream.SyncStatus == - XV_HDMIRX_SYNCSTAT_SYNC_LOSS) { + XV_HDMIRX_SYNCSTAT_SYNC_LOSS) { // Push sync loss event to HDCP event queue #ifdef XV_HDMIRXSS_LOG_ENABLE XV_HdmiRxSs_LogWrite(HdmiRxSsPtr, XV_HDMIRXSS_LOG_EVT_SYNCLOSS, 0); @@ -915,7 +929,7 @@ static void XV_HdmiRxSs_SyncLossCallback(void *CallbackRef) } // Sync is recovered/establish else if (HdmiRxSsPtr->HdmiRxPtr->Stream.SyncStatus == - XV_HDMIRX_SYNCSTAT_SYNC_EST) { + XV_HDMIRX_SYNCSTAT_SYNC_EST) { // Push sync loss event to HDCP event queue #ifdef XV_HDMIRXSS_LOG_ENABLE XV_HdmiRxSs_LogWrite(HdmiRxSsPtr, XV_HDMIRXSS_LOG_EVT_SYNCEST, 0); @@ -1542,7 +1556,7 @@ void XV_HdmiRxSs_LoadEdid(XV_HdmiRxSs *InstancePtr, u8 *EdidDataPtr, ******************************************************************************/ void XV_HdmiRxSs_SetHpd(XV_HdmiRxSs *InstancePtr, u8 Value) { - /* Drive HPD low */ + /* Drive HDMI RX HPD based on the input value */ XV_HdmiRx_SetHpd(InstancePtr->HdmiRxPtr, Value); } @@ -1558,13 +1572,19 @@ void XV_HdmiRxSs_SetHpd(XV_HdmiRxSs *InstancePtr, u8 Value) ******************************************************************************/ void XV_HdmiRxSs_ToggleHpd(XV_HdmiRxSs *InstancePtr) { - /* Drive HPD low */ + /* Clear SCDC variables */ + XV_HdmiRx_DdcScdcClear(InstancePtr->HdmiRxPtr); + + /* Disable the scrambler */ + XV_HdmiRx_SetScrambler(InstancePtr->HdmiRxPtr, (FALSE)); + + /* Drive HDMI RX HPD Low */ XV_HdmiRx_SetHpd(InstancePtr->HdmiRxPtr, (FALSE)); /* Wait 500 ms */ XV_HdmiRxSs_WaitUs(InstancePtr, 500000); - /* Drive HPD high */ + /* Drive HDMI RX HPD High */ XV_HdmiRx_SetHpd(InstancePtr->HdmiRxPtr, (TRUE)); } @@ -2042,11 +2062,11 @@ static void XV_HdmiRxSs_ConfigBridgeMode(XV_HdmiRxSs *InstancePtr) { // Pixel Repetition factor of 3 and above are not supported by the bridge if (AviInfoFramePtr->PixelRepetition > XHDMIC_PIXEL_REPETITION_FACTOR_2) { #ifdef XV_HDMIRXSS_LOG_ENABLE - XV_HdmiRxSs_LogWrite(InstancePtr, XV_HDMIRXSS_LOG_EVT_PIX_REPEAT_ERR, - AviInfoFramePtr->PixelRepetition); + XV_HdmiRxSs_LogWrite(InstancePtr, XV_HDMIRXSS_LOG_EVT_PIX_REPEAT_ERR, + AviInfoFramePtr->PixelRepetition); #endif - return; + return; } if (HdmiRxSsVidStreamPtr->ColorFormatId == XVIDC_CSF_YCRCB_420) { diff --git a/hdmi/xilinx-hdmirx.c b/hdmi/xilinx-hdmirx.c index 0dd1b2e..6ac9c59 100644 --- a/hdmi/xilinx-hdmirx.c +++ b/hdmi/xilinx-hdmirx.c @@ -147,14 +147,15 @@ static const u8 xilinx_edid[] = { 0x58, 0x2C, 0x45, 0x00, 0x40, 0x84, 0x63, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0xFD, 0x00, 0x18, 0x4B, 0x0F, 0x8C, 0x3C, 0x00, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x58, 0x49, 0x4C, 0x49, 0x4E, 0x58, 0x20, 0x48, 0x44, 0x4D, 0x49, 0x0A, 0x20, 0x01, 0x85, - 0x02, 0x03, 0x37, 0xF0, 0x57, 0x61, 0x10, 0x1F, 0x04, 0x13, 0x05, 0x14, 0x20, 0x21, 0x22, 0x5D, + + 0x02, 0x03, 0x3B, 0xF1, 0x57, 0x61, 0x10, 0x1F, 0x04, 0x13, 0x05, 0x14, 0x20, 0x21, 0x22, 0x5D, 0x5E, 0x5F, 0x60, 0x65, 0x66, 0x62, 0x63, 0x64, 0x07, 0x16, 0x03, 0x12, 0x23, 0x09, 0x07, 0x07, - 0x67, 0x03, 0x0C, 0x00, 0x10, 0x00, 0x78, 0x78, 0x67, 0xD8, 0x5D, 0xC4, 0x01, 0x78, 0xC0, 0x07, - 0xE3, 0x0F, 0x01, 0xE0, 0xE2, 0x00, 0xCF, 0x02, 0x3A, 0x80, 0x18, 0x71, 0x38, 0x2D, 0x40, 0x58, - 0x2C, 0x45, 0x00, 0x20, 0xC2, 0x31, 0x00, 0x00, 0x1E, 0x08, 0xE8, 0x00, 0x30, 0xF2, 0x70, 0x5A, - 0x80, 0xB0, 0x58, 0x8A, 0x00, 0x20, 0xC2, 0x31, 0x00, 0x00, 0x1E, 0x04, 0x74, 0x00, 0x30, 0xF2, - 0x70, 0x5A, 0x80, 0xB0, 0x58, 0x8A, 0x00, 0x20, 0x52, 0x31, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC + 0x6B, 0x03, 0x0C, 0x00, 0x10, 0x00, 0x78, 0x3C, 0x20, 0x00, 0x20, 0x03, 0x67, 0xD8, 0x5D, 0xC4, + 0x01, 0x78, 0x80, 0x07, 0xE3, 0x0F, 0x01, 0xE0, 0xE2, 0x00, 0xCF, 0x02, 0x3A, 0x80, 0x18, 0x71, + 0x38, 0x2D, 0x40, 0x58, 0x2C, 0x45, 0x00, 0x20, 0xC2, 0x31, 0x00, 0x00, 0x1E, 0x08, 0xE8, 0x00, + 0x30, 0xF2, 0x70, 0x5A, 0x80, 0xB0, 0x58, 0x8A, 0x00, 0x20, 0xC2, 0x31, 0x00, 0x00, 0x1E, 0x04, + 0x74, 0x00, 0x30, 0xF2, 0x70, 0x5A, 0x80, 0xB0, 0x58, 0x8A, 0x00, 0x20, 0x52, 0x31, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC }; static inline struct xhdmi_device *to_xhdmi(struct v4l2_subdev *subdev) From 309e4f340d36d9179bce2d86ff17514b418d9885 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Sat, 13 Oct 2018 07:10:02 +0800 Subject: [PATCH 06/46] phy: Enabling DRU clock This to enable the dru clock if it is enabled in DT Signed-off-by: Shikhar Mishra --- hdmi/phy-vphy.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hdmi/phy-vphy.c b/hdmi/phy-vphy.c index 5285182..df2eb07 100644 --- a/hdmi/phy-vphy.c +++ b/hdmi/phy-vphy.c @@ -507,7 +507,7 @@ static int xvphy_probe(struct platform_device *pdev) XVphy_ConfigTable[instance].DrpClkFreq = axi_lite_rate; /* dru-clk is used for the nidru block for low res support */ - if (vphydev->xvphy.Config.DruIsPresent == (TRUE)) { + if (XVphy_ConfigTable[instance].DruIsPresent == (TRUE)) { vphydev->clkp = devm_clk_get(&pdev->dev, "dru-clk"); if (IS_ERR(vphydev->clkp)) { ret = PTR_ERR(vphydev->clkp); @@ -536,6 +536,10 @@ static int xvphy_probe(struct platform_device *pdev) dev_dbg(vphydev->dev,"ref dru-clk rate = %lu\n", dru_clk_rate); } } + else + { + dev_dbg(vphydev->dev,"DRU is not enabled from device tree\n"); + } provider = devm_of_phy_provider_register(&pdev->dev, xvphy_xlate); if (IS_ERR(provider)) { From 99b8e7c69e30a12827a7ecfd5f912f653102c1a8 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Sat, 13 Oct 2018 07:27:01 +0800 Subject: [PATCH 07/46] hdmitx:hdmirx:dt:bindings: Updating comments and doc for audio Updated comment header in audio files Removed warnings in audio code Updated the DT documentation Signed-off-by: Shikhar Mishra --- .../devicetree/bindings/xlnx,v-hdmi-rx-ss.txt | 11 +++++++++-- .../devicetree/bindings/xlnx,v-hdmi-tx-ss.txt | 11 +++++++++-- hdmi/xilinx_drm_hdmi.c | 1 + hdmi/xlnx_hdmirx_audio.c | 13 ++++++++++++- hdmi/xlnx_hdmirx_audio.h | 11 ++++++++++- hdmi/xlnx_hdmitx_audio.c | 11 ++++++++++- hdmi/xlnx_hdmitx_audio.h | 11 ++++++++++- 7 files changed, 61 insertions(+), 8 deletions(-) diff --git a/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt b/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt index 7fba622..39e954c 100644 --- a/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt +++ b/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt @@ -52,8 +52,11 @@ Required Properties: - xlnx,include-hdcp-2-2: Boolean parameter that denotes if hdcp22 is included. If present indicates inclusion of the optional core - xlnx,audio-enabled: Boolean parameter to convey that design has audio - functionality + functionality. If present, indicates optional audio core needed + for audio usecase is included. - xlnx,aes_parser: alias to audio channel status extractor block + - xlnx,xlnx-snd-pcm: reference to audio formatter block. Add this if, + audio formatter is going to be used for HDMI audio. - ports: Video ports, using the DT bindings defined in ../video-interfaces.txt. The Rx only has an output port (0). @@ -86,8 +89,9 @@ added to the device tree xlnx,edid-ram-size = <0x100>; xlnx,include-hdcp-1-4; xlnx,include-hdcp-2-2; - xlnx,audio-enabled = "true"; + xlnx,audio-enabled; xlnx,aes_parser = <&hdmi_audio_aes_parser_0>; + xlnx,xlnx-snd-pcm = <&audio_ss_0_audio_formatter_0>; ports { #address-cells = <1>; #size-cells = <0>; @@ -101,3 +105,6 @@ added to the device tree }; }; }; + + Documentation of "audio_ss_0_audio_formatter_0" node is located + at Documentation/devicetree/bindings/sound/xlnx,audio-formatter.txt diff --git a/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt b/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt index b75eacc..2b647e8 100644 --- a/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt +++ b/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt @@ -64,7 +64,10 @@ Required properties: - xlnx,hdcp-encrypt: Flag to enable/disable stream encryption Applicable when either hdcp14 or hdcp22 is included in the design - xlnx,audio-enabled: Boolean parameter to convey that design has audio - functionality + functionality. If present, indicates optional audio core needed + for audio usecase is included. + - xlnx,xlnx-snd-pcm: reference to audio formatter block. Add this if, + audio formatter is going to be used for HDMI audio - xlnx,xlnx-hdmi-acr-ctrl: alias to audio clock recovery block Sub-Node Properties: @@ -116,8 +119,9 @@ added to the device tree /* settings for HDCP */ xlnx,hdcp-authenticate = <0x1>; xlnx,hdcp-encrypt = <0x1>; - xlnx,audio-enabled = "true"; + xlnx,audio-enabled; xlnx,xlnx-hdmi-acr-ctrl = <&hdmi_acr_ctrl_0>; + xlnx,xlnx-snd-pcm = <&audio_ss_0_audio_formatter_0>; ports { #address-cells = <1>; @@ -145,3 +149,6 @@ added to the device tree }; }; }; + + Documentation of "audio_ss_0_audio_formatter_0" node is located + at Documentation/devicetree/bindings/sound/xlnx,audio-formatter.txt diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index 435eb6c..6043cfa 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -2102,6 +2102,7 @@ static int xlnx_drm_hdmi_parse_of(struct xlnx_drm_hdmi *xhdmi, XV_HdmiTxSs_Confi } else { dev_info(dev, "hdmi tx audio disabled in DT\n"); } + return 0; error_dt: dev_err(xhdmi->dev, "Error parsing device tree"); diff --git a/hdmi/xlnx_hdmirx_audio.c b/hdmi/xlnx_hdmirx_audio.c index 8a34a42..d86e95a 100644 --- a/hdmi/xlnx_hdmirx_audio.c +++ b/hdmi/xlnx_hdmirx_audio.c @@ -1,9 +1,18 @@ -// SPDX-License-Identifier: GPL-2.0 /* * Xilinx ALSA SoC HDMI audio capture support * * Copyright (C) 2017-2018 Xilinx, Inc. * + * Author: Maruthi Srinivas Bayyavarapu + * + * 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. */ #include @@ -158,6 +167,8 @@ static int xlnx_rx_pcm_startup(struct snd_pcm_substream *substream, channels = hdmirx_audio_startup(dai->dev); + srate = 0; + sig_bits = 0; reg1_val = readl(adata->aes_base + XV_AES_CH_STS_REG1); reg2_val = readl(adata->aes_base + XV_AES_CH_STS_REG2); if (reg1_val & 0x1) diff --git a/hdmi/xlnx_hdmirx_audio.h b/hdmi/xlnx_hdmirx_audio.h index 0411fab..f4d6414 100644 --- a/hdmi/xlnx_hdmirx_audio.h +++ b/hdmi/xlnx_hdmirx_audio.h @@ -1,9 +1,18 @@ -// SPDX-License-Identifier: GPL-2.0 /* * Xilinx ALSA SoC HDMI audio capture support * * Copyright (C) 2017-2018 Xilinx, Inc. * + * Author: Maruthi Srinivas Bayyavarapu + * + * 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 __XILINX_HDMI_RX_AUD_H__ diff --git a/hdmi/xlnx_hdmitx_audio.c b/hdmi/xlnx_hdmitx_audio.c index a6b902d..e073eb2 100644 --- a/hdmi/xlnx_hdmitx_audio.c +++ b/hdmi/xlnx_hdmitx_audio.c @@ -1,9 +1,18 @@ -// SPDX-License-Identifier: GPL-2.0 /* * Xilinx ALSA SoC HDMI audio playback support * * Copyright (C) 2017-2018 Xilinx, Inc. * + * Author: Maruthi Srinivas Bayyavarapu + * + * 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. */ #include diff --git a/hdmi/xlnx_hdmitx_audio.h b/hdmi/xlnx_hdmitx_audio.h index 224a539..0a05987 100644 --- a/hdmi/xlnx_hdmitx_audio.h +++ b/hdmi/xlnx_hdmitx_audio.h @@ -1,9 +1,18 @@ -// SPDX-License-Identifier: GPL-2.0 /* * Xilinx ALSA SoC HDMI audio playback support * * Copyright (C) 2017-2018 Xilinx, Inc. * + * Author: Maruthi Srinivas Bayyavarapu + * + * 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 __XILINX_HDMI_TX_AUD_H__ From f61a0feaab9e4d00e1d2e800b2f893867e6aae25 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Sat, 13 Oct 2018 07:28:12 +0800 Subject: [PATCH 08/46] hdmirx: Update AES audio header parsing Update AES audio header parsing in HDMI Rx audio Signed-off-by: Shikhar Mishra --- hdmi/xlnx_hdmirx_audio.c | 260 +++++++++++++++++++++++++++------------ hdmi/xlnx_hdmirx_audio.h | 13 ++ 2 files changed, 193 insertions(+), 80 deletions(-) diff --git a/hdmi/xlnx_hdmirx_audio.c b/hdmi/xlnx_hdmirx_audio.c index d86e95a..db2bbbe 100644 --- a/hdmi/xlnx_hdmirx_audio.c +++ b/hdmi/xlnx_hdmirx_audio.c @@ -25,6 +25,39 @@ #define XV_AES_CH_STS_REG1 0x50 #define XV_AES_CH_STS_REG2 0x54 +/* audio params macros */ +#define PROF_SAMPLERATE_MASK GENMASK(7, 6) +#define PROF_SAMPLERATE_SHIFT 6 +#define PROF_CHANNEL_COUNT_MASK GENMASK(11, 8) +#define PROF_CHANNEL_COUNT_SHIFT 8 +#define PROF_MAX_BITDEPTH_MASK GENMASK(18, 16) +#define PROF_MAX_BITDEPTH_SHIFT 16 +#define PROF_BITDEPTH_MASK GENMASK(21, 19) +#define PROF_BITDEPTH_SHIFT 19 + +#define AES_FORMAT_MASK BIT(0) +#define PROF_SAMPLERATE_UNDEFINED 0 +#define PROF_SAMPLERATE_44100 1 +#define PROF_SAMPLERATE_48000 2 +#define PROF_SAMPLERATE_32000 3 +#define PROF_CHANNELS_UNDEFINED 0 +#define PROF_TWO_CHANNELS 8 +#define PROF_STEREO_CHANNELS 2 +#define PROF_MAX_BITDEPTH_UNDEFINED 0 +#define PROF_MAX_BITDEPTH_20 2 +#define PROF_MAX_BITDEPTH_24 4 + +#define CON_SAMPLE_RATE_MASK GENMASK(27, 24) +#define CON_SAMPLE_RATE_SHIFT 24 +#define CON_CHANNEL_COUNT_MASK GENMASK(23, 20) +#define CON_CHANNEL_COUNT_SHIFT 20 +#define CON_MAX_BITDEPTH_MASK BIT(1) +#define CON_BITDEPTH_MASK GENMASK(3, 1) +#define CON_BITDEPTH_SHIFT 0x1 + +#define CON_SAMPLERATE_44100 0 +#define CON_SAMPLERATE_48000 2 +#define CON_SAMPLERATE_32000 3 /* hdmirx_parse_aud_dt - parse AES node from DT * @dev: device * @@ -63,85 +96,145 @@ void __iomem *hdmirx_parse_aud_dt(struct device *dev) return aes_base; } -/* parse_consumer_format - parse AES stream header - * @reg1_val: AES register content - * @reg2_val: AES register content - * @srate: sampling rate - * @sig_bits: valid bits in given container format - * - * This function parses AES header in consumer format - */ -static void parse_consumer_format(u32 reg1_val, u32 reg2_val, - u32 *srate, u32 *sig_bits) +static struct audio_params *parse_professional_format(u32 reg1_val, + u32 reg2_val) { - u32 max_word_length; + u32 padded, val; + struct audio_params *params; - switch ((reg1_val & 0x0F000000) >> 24) { - case 0: - *srate = 44100; - break; - case 2: - *srate = 48000; - break; - case 3: - *srate = 32000; - break; - } + params = kzalloc(sizeof(*params), GFP_KERNEL); + if (!params) + return NULL; - if (reg2_val & 0x1) { - max_word_length = 24; - reg2_val = (reg2_val & 0xE) >> 1; - switch (reg2_val) { - case 0: - /* not indicated */ - *sig_bits = 0; - break; - case 1: - *sig_bits = 20; + val = (reg1_val & PROF_SAMPLERATE_MASK) >> PROF_SAMPLERATE_SHIFT; + switch (val) { + case PROF_SAMPLERATE_44100: + params->srate = 44100; break; - case 6: - *sig_bits = 21; + case PROF_SAMPLERATE_48000: + params->srate = 48000; break; - case 2: - *sig_bits = 22; + case PROF_SAMPLERATE_32000: + params->srate = 32000; break; - case 4: - *sig_bits = 23; + case PROF_SAMPLERATE_UNDEFINED: + default: + /* not indicated */ + kfree(params); + return NULL; + } + + val = (reg1_val & PROF_CHANNEL_COUNT_MASK) >> PROF_CHANNEL_COUNT_SHIFT; + switch (val) { + case PROF_CHANNELS_UNDEFINED: + case PROF_STEREO_CHANNELS: + case PROF_TWO_CHANNELS: + params->channels = 2; break; - case 5: - *sig_bits = 24; + default: + /* TODO: handle more channels in future*/ + kfree(params); + return NULL; + } + + val = (reg1_val & PROF_MAX_BITDEPTH_MASK) >> PROF_MAX_BITDEPTH_SHIFT; + switch (val) { + case PROF_MAX_BITDEPTH_UNDEFINED: + case PROF_MAX_BITDEPTH_20: + padded = 0; break; - } - } else { - max_word_length = 20; - reg2_val = (reg2_val & 0xE) >> 1; - switch (reg2_val) { - case 0: - /* not indicated */ - *sig_bits = 0; + case PROF_MAX_BITDEPTH_24: + padded = 4; break; - case 1: - *sig_bits = 16; + default: + /* user defined values are not supported */ + kfree(params); + return NULL; + } + + val = (reg1_val & PROF_BITDEPTH_MASK) >> PROF_BITDEPTH_SHIFT; + switch (val) { + case 1: + params->sig_bits = 16 + padded; break; - case 6: - *sig_bits = 17; + case 2: + params->sig_bits = 18 + padded; break; - case 2: - *sig_bits = 18; + case 4: + params->sig_bits = 19 + padded; break; - case 4: - *sig_bits = 19; + case 5: + params->sig_bits = 20 + padded; break; - case 5: - *sig_bits = 20; + case 6: + params->sig_bits = 17 + padded; break; - } + case 0: + default: + kfree(params); + return NULL; } + + return params; } -static void parse_professional_format(u32 reg1_val, u32 reg2_val, - u32 *srate, u32 *sig_bits) +static struct audio_params *parse_consumer_format(u32 reg1_val, u32 reg2_val) { + u32 padded, val; + struct audio_params *params; + + params = kzalloc(sizeof(*params), GFP_KERNEL); + if (!params) + return NULL; + + val = (reg1_val & CON_SAMPLE_RATE_MASK) >> CON_SAMPLE_RATE_SHIFT; + switch (val) { + case CON_SAMPLERATE_44100: + params->srate = 44100; + break; + case CON_SAMPLERATE_48000: + params->srate = 48000; + break; + case CON_SAMPLERATE_32000: + params->srate = 32000; + break; + default: + kfree(params); + return NULL; + } + + val = (reg1_val & CON_CHANNEL_COUNT_MASK) >> CON_CHANNEL_COUNT_SHIFT; + params->channels = val; + + if (reg2_val & CON_MAX_BITDEPTH_MASK) + padded = 4; + else + padded = 0; + + val = (reg2_val & CON_BITDEPTH_MASK) >> CON_BITDEPTH_SHIFT; + switch (val) { + case 1: + params->sig_bits = 16 + padded; + break; + case 2: + params->sig_bits = 18 + padded; + break; + case 4: + params->sig_bits = 19 + padded; + break; + case 5: + params->sig_bits = 20 + padded; + break; + case 6: + params->sig_bits = 17 + padded; + break; + case 0: + default: + kfree(params); + return NULL; + } + + return params; } /* xlnx_rx_pcm_startup - initialze audio during audio usecase @@ -156,7 +249,7 @@ static int xlnx_rx_pcm_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { int rate, err; - u32 channels, srate, sig_bits, reg1_val, reg2_val, status; + u32 reg1_val, reg2_val; struct snd_soc_codec *codec = dai->codec; struct snd_pcm_runtime *rtd = substream->runtime; @@ -165,23 +258,29 @@ static int xlnx_rx_pcm_startup(struct snd_pcm_substream *substream, if (!adata) return -EINVAL; - channels = hdmirx_audio_startup(dai->dev); - - srate = 0; - sig_bits = 0; reg1_val = readl(adata->aes_base + XV_AES_CH_STS_REG1); reg2_val = readl(adata->aes_base + XV_AES_CH_STS_REG2); if (reg1_val & 0x1) - parse_professional_format(reg1_val, reg2_val, &srate, - &sig_bits); + adata->params = parse_professional_format(reg1_val, reg2_val); else - parse_consumer_format(reg1_val, reg2_val, &srate, &sig_bits); + adata->params = parse_consumer_format(reg1_val, reg2_val); + + if (!adata->params) + return -EINVAL; + + if (!adata->params->channels) + adata->params->channels = hdmirx_audio_startup(dai->dev); + + dev_info(codec->dev, + "Audio properties: srate %d sig_bits = %d channels = %d\n", + adata->params->srate, adata->params->sig_bits, + adata->params->channels); err = snd_pcm_hw_constraint_minmax(rtd, SNDRV_PCM_HW_PARAM_RATE, - srate, srate); + adata->params->srate, adata->params->srate); if (err < 0) { dev_err(codec->dev, "failed to constrain samplerate to %dHz\n", - srate); + adata->params->srate); return err; } @@ -189,26 +288,24 @@ static int xlnx_rx_pcm_startup(struct snd_pcm_substream *substream, * Out of 24 bits, sig_bits represent valid number of audio bits from * input stream */ - err = snd_pcm_hw_constraint_msbits(rtd, 0, 24, sig_bits); + err = snd_pcm_hw_constraint_msbits(rtd, 0, 24, adata->params->sig_bits); if (err < 0) { dev_err(codec->dev, - "failed to constrain 'bits per sample' %d bits\n", sig_bits); + "failed to constrain 'bits per sample' %d bits\n", + adata->params->sig_bits); return err; } err = snd_pcm_hw_constraint_minmax(rtd, SNDRV_PCM_HW_PARAM_CHANNELS, - channels, channels); + adata->params->channels, + adata->params->channels); if (err < 0) { dev_err(codec->dev, - "failed to constrain channel count to %d\n", channels); + "failed to constrain channel count to %d\n", + adata->params->channels); return err; } - dev_info(codec->dev, "set samplerate constraint to %dHz\n", srate); - dev_info(codec->dev, "set 'bits per sample' constraint to %d\n", - sig_bits); - dev_info(codec->dev, "set channels constraint to %d\n", channels); - return 0; } @@ -220,6 +317,9 @@ static int xlnx_rx_pcm_startup(struct snd_pcm_substream *substream, static void xlnx_rx_pcm_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { + struct xlnx_hdmirx_audio_data *adata = hdmirx_get_audio_data(dai->dev); + + kfree(adata->params); hdmirx_audio_shutdown(dai->dev); } diff --git a/hdmi/xlnx_hdmirx_audio.h b/hdmi/xlnx_hdmirx_audio.h index f4d6414..5986cd3 100644 --- a/hdmi/xlnx_hdmirx_audio.h +++ b/hdmi/xlnx_hdmirx_audio.h @@ -25,7 +25,20 @@ void __iomem *hdmirx_parse_aud_dt(struct device *dev); u32 hdmirx_audio_startup(struct device *dev); void hdmirx_audio_shutdown(struct device *dev); +/* + * struct audio_params - audio stream parameters + * @srate: sampling rate + * @sig_bits: significant bits in container + * @channels: number of channels + */ +struct audio_params { + u32 srate; + u32 sig_bits; + u32 channels; +}; + struct xlnx_hdmirx_audio_data { void __iomem *aes_base; + struct audio_params *params; }; #endif /* __XILINX_HDMI_RX_AUD_H__ */ From 1c0710ad4aea06a1d31c1d9b765fceb7cee5b3c7 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Sat, 13 Oct 2018 07:29:10 +0800 Subject: [PATCH 09/46] hdmitx:hdmirx:phy: Update driver version 20180817 Updated to new drivers version Signed-off-by: Shikhar Mishra --- hdmi/phy-xilinx-vphy/xhdcp1x.h | 10 +- hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_rx.c | 4 +- hdmi/phy-xilinx-vphy/xhdcp1x_tx.c | 76 +++++- hdmi/phy-xilinx-vphy/xvidc.c | 16 +- hdmi/phy-xilinx-vphy/xvidc.h | 4 + hdmi/phy-xilinx-vphy/xvidc_timings_table.c | 17 +- hdmi/phy-xilinx-vphy/xvphy.c | 129 +++++++---- hdmi/phy-xilinx-vphy/xvphy.h | 15 +- hdmi/phy-xilinx-vphy/xvphy_hdmi.c | 10 +- hdmi/phy-xilinx-vphy/xvphy_i.c | 78 +------ hdmi/phy-xilinx-vphy/xvphy_i.h | 6 +- hdmi/xilinx-hdmi-rx/xv_hdmirx.c | 12 +- hdmi/xilinx-hdmi-rx/xv_hdmirx.h | 68 +++++- hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c | 84 ++++--- hdmi/xilinx-hdmi-rx/xv_hdmirxss.c | 27 ++- hdmi/xilinx-hdmi-rx/xv_hdmirxss.h | 20 +- hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.c | 74 ++++++ hdmi/xilinx-hdmi-rx/xv_hdmirxss_hdcp.c | 8 +- hdmi/xilinx-hdmi-tx/xv_hdmitx.c | 34 ++- hdmi/xilinx-hdmi-tx/xv_hdmitx.h | 88 +++++-- hdmi/xilinx-hdmi-tx/xv_hdmitx_hw.h | 27 ++- hdmi/xilinx-hdmi-tx/xv_hdmitx_intr.c | 33 +++ hdmi/xilinx-hdmi-tx/xv_hdmitxss.c | 244 +++++++++++--------- hdmi/xilinx-hdmi-tx/xv_hdmitxss.h | 36 ++- hdmi/xilinx-hdmi-tx/xv_hdmitxss_log.c | 4 + hdmi/xilinx-hdmi-tx/xvtc.c | 28 +++ hdmi/xilinx-hdmi-tx/xvtc_hw.h | 3 + hdmi/xilinx_drm_hdmi.c | 28 +++ 28 files changed, 853 insertions(+), 330 deletions(-) diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x.h b/hdmi/phy-xilinx-vphy/xhdcp1x.h index c9aa559..b4c64d1 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x.h +++ b/hdmi/phy-xilinx-vphy/xhdcp1x.h @@ -705,6 +705,9 @@ * 4.1 yas 11/10/16 Added function XHdcp1x_SetHdmiMode. * 4.1 yas 08/03/17 Added flag IsAuthReqPending to the XHdcp1x_Tx data * structure to track any pending authentication requests. +* 4.2 yas 13/08/18 Addded hdcp14_PropagateTopoErrUpstream flag to track +* topology failures and ready the topology for the +* repeater application to read. * * ******************************************************************************/ @@ -933,6 +936,7 @@ typedef struct { u8 Depth; /**< Depth of the Repeater's downstream topology*/ u8 DeviceCount; /**< Number of downstream devices attached * to the Repeater*/ + u8 hdcp14_PropagateTopoErrUpstream; } XHdcp1x_RepeaterExchange; /** @@ -1069,9 +1073,9 @@ typedef struct { * second part of * authentication" callback * set flag*/ - XHdcp1x_Callback AuthenticatedCallback; /**< Unauthenticated callback*/ - void *AuthenticatedCallbackRef; /**< Unauthenticated reference */ - u32 IsAuthenticatedCallbackSet; /**< Unauthenticated config flag */ + XHdcp1x_Callback AuthenticatedCallback; /**< Authenticated callback*/ + void *AuthenticatedCallbackRef; /**< Authenticated reference */ + u32 IsAuthenticatedCallbackSet; /**< Authenticated config flag */ XHdcp1x_Callback UnauthenticatedCallback; /**< Unauthenticated * callback */ void *UnauthenticatedCallbackRef; /**< Unauthenticated diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_rx.c b/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_rx.c index bb479e2..dc6f7c8 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_rx.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_rx.c @@ -37,6 +37,8 @@ * 3.1 yas 07/28/16 Added function XHdcp1x_PortHdmiRxSetRepeater * 3.2 yas 10/27/16 Updated the XHdcp1x_PortHdmiRxDisable function to not * clear the AKSV, An and AInfo values in the DDC space. +* 4.2 yas 08/15/18 Updated XHdcp1x_PortHdmiRxDisable function to clear +* KSV_FIFO. * * ******************************************************************************/ @@ -175,7 +177,7 @@ static int XHdcp1x_PortHdmiRxDisable(XHdcp1x *InstancePtr) /* Clear HDCP register space for KSV FIFO (0x43) */ Value = 0; - XHdcp1x_PortHdmiRxWrite(InstancePtr, XHDCP1X_PORT_OFFSET_BCAPS, + XHdcp1x_PortHdmiRxWrite(InstancePtr, XHDCP1X_PORT_OFFSET_KSVFIFO, &Value, 1); return (Status); diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_tx.c b/hdmi/phy-xilinx-vphy/xhdcp1x_tx.c index 2122062..29c1f12 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_tx.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_tx.c @@ -57,6 +57,11 @@ * Increase timeout for topology propagation. * 4.1 yas 08/03/17 Updated the XHdcp1x_TxIsInProgress to track any * pending authentication requests. +* 4.2 yas 08/14/18 Updated the XHdcp1x_TxPollForWaitForReady function to +* ready topology in case of a topology error, and make +* it available in XHdcp1x_TxGetTopology(). +* Updating the XHdcp1x_TxReset() to clear the +* Authentication Request flag. * * *****************************************************************************/ @@ -366,8 +371,9 @@ int XHdcp1x_TxReset(XHdcp1x *InstancePtr) XHdcp1x_TxPostEvent(InstancePtr, XHDCP1X_EVENT_DISABLE); XHdcp1x_TxPostEvent(InstancePtr, XHDCP1X_EVENT_ENABLE); - /* Reset the Authentication In Progress Flag */ + /* Reset the Authentication In Progress Flag. */ InstancePtr->Tx.IsAuthReqPending = (FALSE); + return (Status); } @@ -1204,6 +1210,7 @@ static void XHdcp1x_TxEnableEncryptionState(XHdcp1x *InstancePtr) /* Enable it */ XHdcp1x_CipherEnableEncryption(InstancePtr, InstancePtr->Tx.EncryptionMap); + } } } @@ -1771,7 +1778,9 @@ static void XHdcp1x_TxPollForWaitForReady(XHdcp1x *InstancePtr, Status = XHdcp1x_PortGetRepeaterInfo(InstancePtr, &RepeaterInfo); if (Status == XST_SUCCESS) { /* Check that neither cascade or device numbers exceeded */ - if ((RepeaterInfo & 0x0880u) == 0) { + if ((!XHdcp1x_TxGetTopologyMaxCascadeExceeded(InstancePtr)) && + (!XHdcp1x_TxGetTopologyMaxDevsExceeded(InstancePtr))) { + /* Check for at least one attached device */ if ((RepeaterInfo & 0x007Fu) != 0) { /* Update InstancePtr */ @@ -1780,14 +1789,30 @@ static void XHdcp1x_TxPollForWaitForReady(XHdcp1x *InstancePtr, /* Update NextStatePtr */ *NextStatePtr = XHDCP1X_STATE_READKSVLIST; + /* No topology errors. */ + InstancePtr->RepeaterValues.hdcp14_PropagateTopoErrUpstream = FALSE; + /* Log */ XHdcp1x_TxDebugLog(InstancePtr, "devices attached: ksv list ready"); } /* Otherwise */ else { + /* + * Check if Repeater. If repeater, goto + * unauthenticated state and wait for the + * Repeater RX interface to trigger + * authentication after timing out of + * WaitForDownstream state. + * Otherwise, restart authentication on the TX. + */ + if (InstancePtr->IsRepeater) { + /* Update NextStatePtr */ + *NextStatePtr = XHDCP1X_STATE_UNAUTHENTICATED; + } else { /* Update NextStatePtr */ *NextStatePtr = XHDCP1X_STATE_DETERMINERXCAPABLE; + } /* Log */ XHdcp1x_TxDebugLog(InstancePtr, @@ -1800,6 +1825,46 @@ static void XHdcp1x_TxPollForWaitForReady(XHdcp1x *InstancePtr, /* Disable the hdcp encryption for both HDMI and DP. * But currently only doing it for HDMI. */ XHdcp1x_TxDisableEncryptionState(InstancePtr); + + /* Propagate the failure upstream */ + InstancePtr->RepeaterValues.Depth = + ((RepeaterInfo & 0x0700u) >> + XHDCP1X_PORT_BSTATUS_DEPTH_SHIFT); + InstancePtr->RepeaterValues.DeviceCount = + (RepeaterInfo & + XHDCP1X_PORT_BSTATUS_DEV_CNT_MASK); + /* Set the KSV List to include the downstream + * device's BKSV. Do not Validate or assemble the KSV + * List from downstream.*/ + u8 Bksv[8]; + + XHdcp1x_PortRead(InstancePtr, XHDCP1X_PORT_OFFSET_BKSV, + Bksv, 5); + + u64 RemoteKsv = 0; + + /* Determine theRemoteKsv */ + XHDCP1X_PORT_BUF_TO_UINT(RemoteKsv, Bksv, + XHDCP1X_PORT_SIZE_BKSV * 8); + + /* Check for invalid */ + if (!XHdcp1x_TxIsKsvValid(RemoteKsv)) { + InstancePtr->RepeaterValues.KsvList[0] = + RemoteKsv; + } else { + InstancePtr->RepeaterValues.KsvList[0] = 0x0; + } + + /* Set V' to 0x0. */ + memset(InstancePtr->RepeaterValues.V, 0x0, + sizeof(u32)*5); + + InstancePtr->RepeaterValues.hdcp14_PropagateTopoErrUpstream = TRUE; + + if (InstancePtr->Tx.IsRepeaterExchangeCallbackSet) { + InstancePtr->Tx.RepeaterExchangeCallback( + InstancePtr->Tx.RepeaterExchangeRef); + } #endif /* Update NextStatePtr */ @@ -2326,7 +2391,9 @@ XHdcp1x_RepeaterExchange *XHdcp1x_TxGetTopology(XHdcp1x *InstancePtr) Xil_AssertNonvoid(InstancePtr != NULL); if (InstancePtr->IsRepeater) { - if (InstancePtr->Rx.CurrentState == XHDCP1X_STATE_AUTHENTICATED) { + if (InstancePtr->Tx.CurrentState == XHDCP1X_STATE_AUTHENTICATED) { + return &InstancePtr->RepeaterValues; + } else if (InstancePtr->RepeaterValues.hdcp14_PropagateTopoErrUpstream == TRUE) { return &InstancePtr->RepeaterValues; } } @@ -3129,11 +3196,14 @@ static void XHdcp1x_TxEnterState(XHdcp1x *InstancePtr, XHdcp1x_StateType State, switch (State) { /* For the disabled state */ case XHDCP1X_STATE_DISABLED: + /* Clear auth request pending flag */ + InstancePtr->Tx.IsAuthReqPending = FALSE; XHdcp1x_TxDisableState(InstancePtr); break; /* For determine rx capable */ case XHDCP1X_STATE_DETERMINERXCAPABLE: + InstancePtr->RepeaterValues.hdcp14_PropagateTopoErrUpstream = FALSE; InstancePtr->Tx.Flags |= XVPHY_FLAG_PHY_UP; XHdcp1x_TxSetCheckLinkState(InstancePtr, FALSE); XHdcp1x_TxDisableEncryptionState(InstancePtr); diff --git a/hdmi/phy-xilinx-vphy/xvidc.c b/hdmi/phy-xilinx-vphy/xvidc.c index ad2e644..63a12a8 100644 --- a/hdmi/phy-xilinx-vphy/xvidc.c +++ b/hdmi/phy-xilinx-vphy/xvidc.c @@ -925,10 +925,12 @@ u32 XVidC_SetVideoStream(XVidC_VideoStream *VidStrmPtr, XVidC_VideoMode VmId, VidStrmPtr->Timing = *TimingPtr; VidStrmPtr->FrameRate = XVidC_GetFrameRate(VmId); VidStrmPtr->IsInterlaced = XVidC_IsInterlaced(VmId); - - } else { //Custom Timing - use as-is - VidStrmPtr->IsInterlaced = FALSE; + + } else { + /* In custom timing no need to set Timing, FrameRate and IsInterlaced + * as they are already set previously in wrapper code */ } + VidStrmPtr->VmId = VmId; VidStrmPtr->ColorFormatId = ColorFormat; VidStrmPtr->ColorDepth = Bpc; @@ -1103,7 +1105,7 @@ void XVidC_ReportStreamInfo(const XVidC_VideoStream *Stream) 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, + "hbp=%03d, htot=%04d \r\n", Timing->HActive, Timing->HFrontPorch, Timing->HSyncWidth, Timing->HSyncPolarity, Timing->HBackPorch, Timing->HTotal); @@ -1111,12 +1113,12 @@ void XVidC_ReportTiming(const XVidC_VideoTiming *Timing, u8 IsInterlaced) /* Interlaced */ if (IsInterlaced) { xil_printf("\tVSYNC Timing (Field 0): vav=%04d, vfp=%02d, " - "vsw=%02d(vsp=%d), vbp=%03d, vtot=%04d\n\r", + "vsw=%02d(vsp=%d), vbp=%03d, vtot=%04d\r\n", 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", + "vsw=%02d(vsp=%d), vbp=%03d, vtot=%04d\r\n", Timing->VActive, Timing->F1VFrontPorch, Timing->F1VSyncWidth, Timing->VSyncPolarity, Timing->F1VBackPorch, Timing->F1VTotal); @@ -1124,7 +1126,7 @@ void XVidC_ReportTiming(const XVidC_VideoTiming *Timing, u8 IsInterlaced) /* Progressive */ else { xil_printf("\tVSYNC Timing: vav=%04d, vfp=%02d, " - "vsw=%02d(vsp=%d), vbp=%03d, vtot=%04d\n\r", + "vsw=%02d(vsp=%d), vbp=%03d, vtot=%04d\r\n", Timing->VActive, Timing->F0PVFrontPorch, Timing->F0PVSyncWidth, Timing->VSyncPolarity, Timing->F0PVBackPorch, Timing->F0PVTotal); diff --git a/hdmi/phy-xilinx-vphy/xvidc.h b/hdmi/phy-xilinx-vphy/xvidc.h index a7a34cb..bb7c3e5 100644 --- a/hdmi/phy-xilinx-vphy/xvidc.h +++ b/hdmi/phy-xilinx-vphy/xvidc.h @@ -59,6 +59,7 @@ * 4.3 eb 26/01/18 Added API XVidC_GetVideoModeIdExtensive * jsr 02/22/18 Added XVIDC_CSF_YCBCR_420 color space format * vyc 04/04/18 Added BGR8 memory format + * 4.5 jsr 07/03/18 Added XVIDC_VM_720x486_60_I video format * * *******************************************************************************/ @@ -88,6 +89,7 @@ extern "C" { typedef enum { /* Interlaced modes. */ XVIDC_VM_720x480_60_I = 0, + XVIDC_VM_720x486_60_I, XVIDC_VM_720x576_50_I, XVIDC_VM_1440x480_60_I, XVIDC_VM_1440x576_50_I, @@ -249,6 +251,7 @@ typedef enum { /* Common naming. */ XVIDC_VM_480_60_I = XVIDC_VM_720x480_60_I, + XVIDC_VM_486_60_I = XVIDC_VM_720x486_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, @@ -380,6 +383,7 @@ typedef enum { XVIDC_CSF_YCBCR_422 = 64, XVIDC_CSF_YCBCR_420, + XVIDC_CSF_NUM_SUPPORTED, // includes the reserved slots XVIDC_CSF_UNKNOWN, XVIDC_CSF_STRM_START = XVIDC_CSF_RGB, diff --git a/hdmi/phy-xilinx-vphy/xvidc_timings_table.c b/hdmi/phy-xilinx-vphy/xvidc_timings_table.c index aede471..c22d445 100644 --- a/hdmi/phy-xilinx-vphy/xvidc_timings_table.c +++ b/hdmi/phy-xilinx-vphy/xvidc_timings_table.c @@ -40,6 +40,8 @@ * aad 09/05/17 Added 1366x768_60_P_RB * 4.4 eb 09/04/18 Fixed timings for 1280x720_24_P, 1280x720_25_P, * 1280x720_30_P + * 4.5 jsr 07/03/18 Added timing for new video mode XVIDC_VM_720x486_60_I + * * * *******************************************************************************/ @@ -83,6 +85,9 @@ const XVidC_VideoTimingMode XVidC_VideoTimingModes[XVIDC_VM_NUM_SUPPORTED] = { 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_720x486_60_I, "720x486@60Hz (I)", XVIDC_FR_60HZ, + {720, 19, 62, 57, 858, 0, + 243, 1, 3, 15, 262, 2, 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} }, @@ -103,13 +108,13 @@ const XVidC_VideoTimingMode XVidC_VideoTimingModes[XVIDC_VM_NUM_SUPPORTED] = 540, 2, 5, 15, 562, 3, 5, 15, 563, 1} }, { XVIDC_VM_1920x1080_96_I, "1920x1080@96Hz (I)", XVIDC_FR_96HZ, {1920, 371, 88, 371, 2750, 1, - 1080, 4, 10, 30, 1124, 6, 10, 30, 1126, 1} }, + 540, 2, 5, 15, 562, 3, 5, 15, 563, 1} }, { XVIDC_VM_1920x1080_100_I, "1920x1080@100Hz (I)", XVIDC_FR_100HZ, {1920, 528, 44, 148, 2640, 1, - 1080, 4, 10, 30, 1124, 6, 10, 30, 1126, 1} }, + 540, 2, 5, 15, 562, 3, 5, 15, 563, 1} }, { XVIDC_VM_1920x1080_120_I, "1920x1080@120Hz (I)", XVIDC_FR_120HZ, {1920, 88, 44, 148, 2200, 1, - 1080, 4, 10, 30, 1124, 6, 10, 30, 1126, 1} }, + 540, 2, 5, 15, 562, 3, 5, 15, 563, 1} }, { XVIDC_VM_2048x1080_48_I, "2048x1080@48Hz (I)", XVIDC_FR_48HZ, {2048, 329, 44, 329, 2750, 1, 540, 2, 5, 15, 562, 3, 5, 15, 563, 1} }, @@ -121,13 +126,13 @@ const XVidC_VideoTimingMode XVidC_VideoTimingModes[XVIDC_VM_NUM_SUPPORTED] = 540, 2, 5, 15, 562, 3, 5, 15, 563, 1} }, { XVIDC_VM_2048x1080_96_I, "2048x1080@96Hz (I)", XVIDC_FR_96HZ, {2048, 329, 44, 329, 2750, 1, - 1080, 4, 10, 30, 1124, 6, 10, 30, 1126, 1} }, + 540, 2, 5, 15, 562, 3, 5, 15, 563, 1} }, { XVIDC_VM_2048x1080_100_I, "2048x1080@100Hz (I)", XVIDC_FR_100HZ, {2048, 274, 44, 274, 2640, 1, - 1080, 4, 10, 30, 1124, 6, 10, 30, 1126, 1} }, + 540, 2, 5, 15, 562, 3, 5, 15, 563, 1} }, { XVIDC_VM_2048x1080_120_I, "2048x1080@120Hz (I)", XVIDC_FR_120HZ, {2048, 66, 20, 66, 2200, 1, - 1080, 4, 10, 30, 1124, 6, 10, 30, 1126, 1} }, + 540, 2, 5, 15, 562, 3, 5, 15, 563, 1} }, /* Progressive modes. */ diff --git a/hdmi/phy-xilinx-vphy/xvphy.c b/hdmi/phy-xilinx-vphy/xvphy.c index e70845f..59d0ac5 100644 --- a/hdmi/phy-xilinx-vphy/xvphy.c +++ b/hdmi/phy-xilinx-vphy/xvphy.c @@ -61,6 +61,10 @@ * Moved XVphy_MmcmWriteParameters to xvphy_mmcme2/3/4.c * Added XVphy_SetPolarity, XVphy_SetPrbsSel and * XVphy_TxPrbsForceError APIs + * 1.8 gm 05/14/18 Removed XVphy_DrpWrite and XVphy_DrpRead APIs + * 23/07/18 Added APIs XVphy_SetTxVoltageSwing and + * XVphy_SetTxPreEmphasis from xvphy_i.c/h + * Added XVphy_SetTxPostCursor API * * *******************************************************************************/ @@ -945,71 +949,116 @@ u32 XVphy_TxPrbsForceError(XVphy *InstancePtr, u8 QuadId, /*****************************************************************************/ /** -* This function will initiate a write DRP transaction. It is a wrapper around -* XVphy_DrpAccess. +* 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 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. +* @param ChId is the channel ID to operate on. +* @param Vs is the voltage swing value to write. * -* @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. +* @return None. * * @note None. * -* @deprecated XVphy_DrpWrite will be deprecated in 2018.3 and replaced by -* XVphy_DrpWr to align with new naming of XVphy_DrpRd API. -* No functional change between XVphy_DrpWrite & XVphy_DrpWr. -* ******************************************************************************/ -u32 XVphy_DrpWrite(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, - u16 Addr, u16 Val) +void XVphy_SetTxVoltageSwing(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u8 Vs) { - return XVphy_DrpAccess(InstancePtr, QuadId, ChId, - XVPHY_DIR_TX, /* Write. */ - Addr, &Val); + 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 initiate a read DRP transaction. It is a wrapper around -* XVphy_DrpAccess. +* 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 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 ChId is the channel ID to operate on. +* @param Pe is the pre-emphasis value to write. * -* @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. +* @return None. * * @note None. * -* @deprecated XVphy_DrpRead will be deprecated in 2018.3 and replaced by -* XVphy_DrpRd to separate the return value of DRP register -* content and XST_SUCCESS/XST_FAILURE. -* A new argument (*RetVal) was added in XVphy_DrpRd to hold the -* DRP register content +******************************************************************************/ +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 will set the TX post-curosr 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. * ******************************************************************************/ -u16 XVphy_DrpRead(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, u16 Addr) +void XVphy_SetTxPostCursor(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u8 Pc) { - u32 Status; - u16 Val; + u32 RegVal; + u32 MaskVal; + u32 RegOffset; - Status = XVphy_DrpAccess(InstancePtr, QuadId, ChId, - XVPHY_DIR_RX, /* Read. */ - Addr, &Val); + /* 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); - return (Status == XST_SUCCESS) ? Val : 0xDEAD; + MaskVal = XVPHY_TX_DRIVER_TXPOSTCURSOR_MASK(ChId); + RegVal &= ~MaskVal; + RegVal |= (Pc << XVPHY_TX_DRIVER_TXPOSTCURSOR_SHIFT(ChId)); + XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); } /*****************************************************************************/ diff --git a/hdmi/phy-xilinx-vphy/xvphy.h b/hdmi/phy-xilinx-vphy/xvphy.h index 5f0fbc1..10a4ff9 100644 --- a/hdmi/phy-xilinx-vphy/xvphy.h +++ b/hdmi/phy-xilinx-vphy/xvphy.h @@ -80,6 +80,11 @@ * 1.7 gm 13/09/17 Added GTYE4 support * Added XVphy_SetPolarity, XVphy_SetPrbsSel and * XVphy_TxPrbsForceError APIs + * 1.8 gm 05/14/18 Updated CDR values for DP in xvphy_gtye4.c + * Removed XVphy_DrpWrite and XVphy_DrpRead APIs + * 23/07/18 Added APIs XVphy_SetTxVoltageSwing and + * XVphy_SetTxPreEmphasis from xvphy_i.c/h + * Added XVphy_SetTxPostCursor API * * *******************************************************************************/ @@ -857,12 +862,14 @@ u32 XVphy_SetPrbsSel(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, XVphy_DirectionType Dir, XVphy_PrbsPattern Pattern); u32 XVphy_TxPrbsForceError(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, u8 ForceErr); +void XVphy_SetTxVoltageSwing(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u8 Vs); +void XVphy_SetTxPreEmphasis(XVphy *InstancePtr, u8 QuadId, + XVphy_ChannelId ChId, u8 Pe); +void XVphy_SetTxPostCursor(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + u8 Pc); /* xvphy.c: GT/MMCM DRP access. */ -u32 XVphy_DrpWrite(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, - u16 Addr, u16 Val) __attribute__ ((deprecated)); -u16 XVphy_DrpRead(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, - u16 Addr) __attribute__ ((deprecated)); u32 XVphy_DrpWr(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, u16 Addr, u16 Val); u16 XVphy_DrpRd(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, diff --git a/hdmi/phy-xilinx-vphy/xvphy_hdmi.c b/hdmi/phy-xilinx-vphy/xvphy_hdmi.c index f663f47..1267f36 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_hdmi.c +++ b/hdmi/phy-xilinx-vphy/xvphy_hdmi.c @@ -70,6 +70,8 @@ * Added userclk freq checking in XVphy_HdmiCpllParam & * XVphy_HdmiQpllParam API * Removed XVphy_DruSetGain API + * 1.8 gm 05/14/18 Fixed a bug in XVphy_HdmiQpllParam where linerate is + * obtained from CH1 instead of QPLL0/1 * * * @@ -148,7 +150,7 @@ u32 XVphy_HdmiInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_Config *CfgPtr, XVPHY_GT_STATE_IDLE; InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)].RxState = XVPHY_GT_STATE_IDLE; - //Initialize Transceiver Width values + /* Initialize Transceiver Width values */ if (InstancePtr->Config.TransceiverWidth == 2) { InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. TxDataWidth = 20; @@ -350,7 +352,7 @@ u32 XVphy_Hdmi_CfgInitialize(XVphy *InstancePtr, u8 QuadId, XVPHY_GT_STATE_IDLE; InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)].RxState = XVPHY_GT_STATE_IDLE; - //Initialize Transceiver Width values + /* Initialize Transceiver Width values */ if (InstancePtr->Config.TransceiverWidth == 2) { InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(Id)]. TxDataWidth = 20; @@ -1404,7 +1406,7 @@ u32 XVphy_HdmiCfgCalcMmcmParam(XVphy *InstancePtr, u8 QuadId, MmcmPtr->ClkOut0Div = MultDiv * 4; } } - else {//2 Byte Mode + else { /* 2 Byte Mode */ /* Link clock: TMDS clock ratio 1/40. */ if ((LineRate / 1000000) >= 3400) { if ((Dir == XVPHY_DIR_TX) && @@ -1918,7 +1920,7 @@ u32 XVphy_HdmiQpllParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, /* (297 MHz + 0.5%) + 10 KHz (Clkdet accuracy) */ if (298495000 < (XVphy_GetLineRateHz(InstancePtr, QuadId, - XVPHY_CHANNEL_ID_CH1) / + ActiveCmnId) / (InstancePtr->Config.TransceiverWidth * 10))) { XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_USRCLK_ERR, 1); XVphy_CfgErrIntr(InstancePtr, XVPHY_ERR_USRCLK, 1); diff --git a/hdmi/phy-xilinx-vphy/xvphy_i.c b/hdmi/phy-xilinx-vphy/xvphy_i.c index d89a382..4747c79 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_i.c +++ b/hdmi/phy-xilinx-vphy/xvphy_i.c @@ -34,6 +34,8 @@ * 1.6 gm 06/08/17 Added XVphy_MmcmLocked, XVphy_ErrorHandler and * XVphy_PllLayoutErrorHandler APIs * 1.7 gm 13/09/17 Added GTYE4 support + * 1.8 gm 23/07/18 Moved APIs XVphy_SetTxVoltageSwing and + * XVphy_SetTxPreEmphasis to xvphy.c/h * * *******************************************************************************/ @@ -98,82 +100,6 @@ void XVphy_SetRxLpm(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, 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 diff --git a/hdmi/phy-xilinx-vphy/xvphy_i.h b/hdmi/phy-xilinx-vphy/xvphy_i.h index 0103f48..9efee09 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_i.h +++ b/hdmi/phy-xilinx-vphy/xvphy_i.h @@ -36,6 +36,8 @@ * 1.6 gm 06/08/17 Added XVphy_MmcmLocked, XVphy_ErrorHandler and * XVphy_PllLayoutErrorHandler APIs * 1.7 gm 13/09/17 Removed XVphy_MmcmWriteParameters API + * 1.8 gm 23/07/18 Moved APIs XVphy_SetTxVoltageSwing and + * XVphy_SetTxPreEmphasis to xvphy.c/h * * * @addtogroup xvphy @@ -70,10 +72,6 @@ u32 XVphy_PllCalculator(XVphy *InstancePtr, u8 QuadId, /* 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); diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirx.c b/hdmi/xilinx-hdmi-rx/xv_hdmirx.c index bc9c2ad..737690c 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirx.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirx.c @@ -46,6 +46,9 @@ * EB 18/01/18 Moved VicTable to Hdmi Common library * EB 26/01/18 Updated XV_HdmiRx_GetVideoTiming to use * XVidC_GetVideoModeIdExtensive +* 2.20 EB 16/08/18 Replaced TIME_10MS, TIME_16MS, TIME_200MS with +* XV_HdmiRx_GetTime10Ms, XV_HdmiRx_GetTime16Ms +* XV_HdmiRx_GetTime200Ms * * ******************************************************************************/ @@ -97,7 +100,6 @@ static void StubCallback(void *CallbackRef); int XV_HdmiRx_CfgInitialize(XV_HdmiRx *InstancePtr, XV_HdmiRx_Config *CfgPtr, UINTPTR EffectiveAddr) { u32 RegValue; - u32 Time_16ms; /* Verify arguments. */ Xil_AssertNonvoid(InstancePtr != NULL); @@ -116,7 +118,6 @@ int XV_HdmiRx_CfgInitialize(XV_HdmiRx *InstancePtr, XV_HdmiRx_Config *CfgPtr, UI return (XST_FAILURE); } - Time_16ms = (InstancePtr->Config.AxiLiteClkFreq * 10)/625; /* Callbacks These are placeholders pointing to the StubCallback @@ -223,8 +224,8 @@ int XV_HdmiRx_CfgInitialize(XV_HdmiRx *InstancePtr, XV_HdmiRx_Config *CfgPtr, UI Video Timing detector peripheral */ - // Set timebase - XV_HdmiRx_VtdSetTimebase(InstancePtr, Time_16ms); // 16 ms + // Set timebase - 16 ms + XV_HdmiRx_VtdSetTimebase(InstancePtr, XV_HdmiRx_GetTime16Ms(InstancePtr)); // The VTD run flag is set in the armed state @@ -399,6 +400,7 @@ int XV_HdmiRx_SetStream(XV_HdmiRx *InstancePtr, XVidC_PixelsPerClock Ppc, u32 Cl ******************************************************************************/ void XV_HdmiRx_INT_VRST(XV_HdmiRx *InstancePtr, u8 Reset) { + /* Verify argument. */ Xil_AssertVoid(InstancePtr != NULL); @@ -1727,7 +1729,7 @@ int XV_HdmiRx_GetVideoTiming(XV_HdmiRx *InstancePtr) // Lookup the video mode id InstancePtr->Stream.Video.VmId = XVidC_GetVideoModeIdExtensive(&InstancePtr->Stream.Video.Timing, - InstancePtr->Stream.Video.FrameRate, + InstancePtr->Stream.Video.FrameRate, InstancePtr->Stream.Video.IsInterlaced, (TRUE)); diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirx.h b/hdmi/xilinx-hdmi-rx/xv_hdmirx.h index dda2a4f..39d8232 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirx.h +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirx.h @@ -129,6 +129,12 @@ * MMO 08/02/18 Added XV_HdmiRx_SyncStatus enumaration, and as * an element in XV_HdmiRx_Stream for Sync Loss * handling +* 2.20 EB 16/08/18 Replaced TIME_10MS, TIME_16MS, TIME_200MS with +* XV_HdmiRx_GetTime10Ms, XV_HdmiRx_GetTime16Ms +* XV_HdmiRx_GetTime200Ms +* YB 08/15/18 Added new callbacks for HDCP 1.4 & 2.2 protocol events. +* Enumerated new entries for HDCP 1.4 & 2.2 protocol +* events in XV_HdmiRx_HandlerType enum. * * ******************************************************************************/ @@ -160,7 +166,8 @@ extern "C" { */ typedef enum { XV_HDMIRX_HANDLER_CONNECT = 1, /**< A connect event interrupt type */ - XV_HDMIRX_HANDLER_BRDG_OVERFLOW, /**< Interrupt type for bridge overflow */ + XV_HDMIRX_HANDLER_BRDG_OVERFLOW, /**< Interrupt type for bridge + overflow */ XV_HDMIRX_HANDLER_AUX, /**< Interrupt type for AUX peripheral */ XV_HDMIRX_HANDLER_AUD, /**< Interrupt type for AUD peripheral */ XV_HDMIRX_HANDLER_LNKSTA, /**< Interrupt type for LNKSTA peripheral */ @@ -169,6 +176,8 @@ typedef enum { XV_HDMIRX_HANDLER_STREAM_INIT, /**< Interrupt type for stream init */ XV_HDMIRX_HANDLER_STREAM_UP, /**< Interrupt type for stream up */ XV_HDMIRX_HANDLER_HDCP, /**< Interrupt type for hdcp */ + XV_HDMIRX_HANDLER_DDC_HDCP_14_PROT, /**< Interrupt type for HDCP14PROT event */ + XV_HDMIRX_HANDLER_DDC_HDCP_22_PROT, /**< Interrupt type for HDCP22PROT event */ XV_HDMIRX_HANDLER_LINK_ERROR, /**< Interrupt type for link error */ XV_HDMIRX_HANDLER_SYNC_LOSS, /**< Interrupt type for sync loss */ XV_HDMIRX_HANDLER_MODE /**< Interrupt type for mode */ @@ -216,6 +225,7 @@ typedef struct { u16 DeviceId; /**< DeviceId is the unique ID of the HDMI RX core */ UINTPTR BaseAddress; /**< BaseAddress is the physical base address * of the core's registers */ + u32 AxiLiteClkFreq; } XV_HdmiRx_Config; @@ -306,6 +316,15 @@ typedef struct { XV_HdmiRx_HdcpCallback HdcpCallback; /**< Callback for hdcp callback */ void *HdcpRef; /**< To be passed to the hdcp callback */ u32 IsHdcpCallbackSet; /**< Set flag. This flag is set to true when the callback has been registered */ + + XV_HdmiRx_Callback Hdcp14ProtEvtCallback; /**< Callback for hdcp 1.4 protocol event written on the ddc. */ + void *Hdcp14ProtEvtRef; /**< To be passed to the hdcp 1.4 protocol event callback */ + u32 IsHdcp14ProtEvtCallbackSet; /**< Set flag. This flag is set to true when the callback has been registered */ + + XV_HdmiRx_Callback Hdcp22ProtEvtCallback; /**< Callback for hdcp 2.2 protocol event written on the ddc. */ + void *Hdcp22ProtEvtRef; /**< To be passed to the hdcp 2.2 protocol event callback */ + u32 IsHdcp22ProtEvtCallbackSet; /**< Set flag. This flag is set to true when the callback has been registered */ + XV_HdmiRx_Callback LinkErrorCallback; /**< Callback for link error callback */ void *LinkErrorRef; /**< To be passed to the link error callback */ u32 IsLinkErrorCallbackSet; /**< Set flag. This flag is set to true when the callback has been registered */ @@ -336,6 +355,51 @@ typedef struct { /***************** Macros (Inline Functions) Definitions *********************/ +/*****************************************************************************/ +/** +* +* This macro returns the clock cycles required to count up to 10MS with respect +* to AXI Lite Frequency +* +* @param InstancePtr is a pointer to the XV_HdmiRX core instance. +* +* @return None. +* +* +******************************************************************************/ +#define XV_HdmiRx_GetTime10Ms(InstancePtr) \ + (InstancePtr)->Config.AxiLiteClkFreq/100 + +/*****************************************************************************/ +/** +* +* This macro returns the clock cycles required to count up to 16MS with +* respect to AXI Lite Frequency +* +* @param InstancePtr is a pointer to the XV_HdmiRX core instance. +* +* @return None. +* +* +******************************************************************************/ +#define XV_HdmiRx_GetTime16Ms(InstancePtr) \ + ((InstancePtr)->Config.AxiLiteClkFreq*10)/625 + +/*****************************************************************************/ +/** +* +* This macro returns the clock cycles required to count up to 200MS with +* respect to AXI Lite Frequency +* +* @param InstancePtr is a pointer to the XV_HdmiRX core instance. +* +* @return None. +* +* +******************************************************************************/ +#define XV_HdmiRx_GetTime200Ms(InstancePtr) \ + (InstancePtr)->Config.AxiLiteClkFreq/5 + /*****************************************************************************/ /** * @@ -438,7 +502,7 @@ typedef struct { * * This macro controls the HDMI RX Scrambler. * -* @param InstancePtr is a pointer to the XHdmi_Tx core instance. +* @param InstancePtr is a pointer to the XHdmi_Rx core instance. * @param SetClr specifies TRUE/FALSE value to either enable or disable the * scrambler. * diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c b/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c index 1ba4bbc..8be923e 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c @@ -47,6 +47,12 @@ * each clock domain * MMO 08/02/18 Adding proper handling for Sync Loss/Sync Recover * 2.10 YH 13/04/18 Fixed a bug in PioIntrHandler +* 2.20 EB 16/08/18 Replaced TIME_10MS, TIME_16MS, TIME_200MS with +* XV_HdmiRx_GetTime10Ms, XV_HdmiRx_GetTime16Ms +* XV_HdmiRx_GetTime200Ms +* YB 08/15/18 Added new cases for HDCP 1.4 & 2.2 protocol events in +* XV_HdmiRx_SetCallback function. +* Updated the HdmiRx_DdcIntrHandler() function. * * ******************************************************************************/ @@ -286,12 +292,28 @@ int XV_HdmiRx_SetCallback(XV_HdmiRx *InstancePtr, u32 HandlerType, void *Callbac Status = (XST_SUCCESS); break; - case (XV_HDMIRX_HANDLER_LINK_ERROR): - InstancePtr->LinkErrorCallback = (XV_HdmiRx_Callback)CallbackFunc; - InstancePtr->LinkErrorRef = CallbackRef; - InstancePtr->IsLinkErrorCallbackSet = (TRUE); + // HDCP 1.4 Event + case (XV_HDMIRX_HANDLER_DDC_HDCP_14_PROT): + InstancePtr->Hdcp14ProtEvtCallback = (XV_HdmiRx_Callback)CallbackFunc; + InstancePtr->Hdcp14ProtEvtRef = CallbackRef; + InstancePtr->IsHdcp14ProtEvtCallbackSet = (TRUE); Status = (XST_SUCCESS); - break; + break; + + // HDCP 2.2 Event + case (XV_HDMIRX_HANDLER_DDC_HDCP_22_PROT): + InstancePtr->Hdcp22ProtEvtCallback = (XV_HdmiRx_Callback)CallbackFunc; + InstancePtr->Hdcp22ProtEvtRef = CallbackRef; + InstancePtr->IsHdcp22ProtEvtCallbackSet = (TRUE); + Status = (XST_SUCCESS); + break; + + case (XV_HDMIRX_HANDLER_LINK_ERROR): + InstancePtr->LinkErrorCallback = (XV_HdmiRx_Callback)CallbackFunc; + InstancePtr->LinkErrorRef = CallbackRef; + InstancePtr->IsLinkErrorCallbackSet = (TRUE); + Status = (XST_SUCCESS); + break; // Bridge FIFO Overflow case (XV_HDMIRX_HANDLER_BRDG_OVERFLOW): @@ -394,8 +416,8 @@ void HdmiRx_VtdIntrHandler(XV_HdmiRx *InstancePtr) InstancePtr->Stream.State = XV_HDMIRX_STATE_STREAM_LOCK; } else if (InstancePtr->Stream.SyncStatus == XV_HDMIRX_SYNCSTAT_SYNC_LOSS) { - // Sync Est/Recover Flag - InstancePtr->Stream.SyncStatus = XV_HDMIRX_SYNCSTAT_SYNC_EST; + // Sync Est/Recover Flag + InstancePtr->Stream.SyncStatus = XV_HDMIRX_SYNCSTAT_SYNC_EST; // Call sync lost callback if (InstancePtr->IsSyncLossCallbackSet) { @@ -413,8 +435,8 @@ void HdmiRx_VtdIntrHandler(XV_HdmiRx *InstancePtr) XV_HdmiRx_WriteReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_STA_OFFSET), (XV_HDMIRX_VTD_STA_SYNC_LOSS_EVT_MASK)); if (InstancePtr->Stream.State == XV_HDMIRX_STATE_STREAM_UP) { - // Enable the Stream Up + Sync Loss Flag - InstancePtr->Stream.SyncStatus = XV_HDMIRX_SYNCSTAT_SYNC_LOSS; + // Enable the Stream Up + Sync Loss Flag + InstancePtr->Stream.SyncStatus = XV_HDMIRX_SYNCSTAT_SYNC_LOSS; // Call sync lost callback if (InstancePtr->IsSyncLossCallbackSet) { @@ -498,8 +520,8 @@ void HdmiRx_DdcIntrHandler(XV_HdmiRx *InstancePtr) XV_HdmiRx_WriteReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_DDC_STA_OFFSET), (XV_HDMIRX_DDC_STA_HDCP_1_PROT_EVT_MASK)); /* Callback */ - if (InstancePtr->IsHdcpCallbackSet) { - InstancePtr->HdcpCallback(InstancePtr->HdcpRef, XV_HDMIRX_DDC_STA_HDCP_1_PROT_EVT_MASK); + if (InstancePtr->IsHdcp14ProtEvtCallbackSet) { + InstancePtr->Hdcp14ProtEvtCallback(InstancePtr->Hdcp14ProtEvtRef); } } @@ -510,8 +532,8 @@ void HdmiRx_DdcIntrHandler(XV_HdmiRx *InstancePtr) XV_HdmiRx_WriteReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_DDC_STA_OFFSET), (XV_HDMIRX_DDC_STA_HDCP_2_PROT_EVT_MASK)); /* Callback */ - if (InstancePtr->IsHdcpCallbackSet) { - InstancePtr->HdcpCallback(InstancePtr->HdcpRef, XV_HDMIRX_DDC_STA_HDCP_2_PROT_EVT_MASK); + if (InstancePtr->IsHdcp22ProtEvtCallbackSet) { + InstancePtr->Hdcp22ProtEvtCallback(InstancePtr->Hdcp22ProtEvtRef); } } @@ -533,8 +555,6 @@ void HdmiRx_PioIntrHandler(XV_HdmiRx *InstancePtr) { u32 Event; u32 Data; - u32 Time_10ms = InstancePtr->Config.AxiLiteClkFreq/100; - u32 Time_200ms = InstancePtr->Config.AxiLiteClkFreq/5; /* Read PIO IN Event register.*/ Event = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_PIO_IN_EVT_OFFSET)); @@ -576,7 +596,8 @@ void HdmiRx_PioIntrHandler(XV_HdmiRx *InstancePtr) InstancePtr->Stream.State = XV_HDMIRX_STATE_STREAM_IDLE; // The stream idle // Load timer - XV_HdmiRx_TmrStart(InstancePtr, Time_10ms); // 10 ms + XV_HdmiRx_TmrStart(InstancePtr, + XV_HdmiRx_GetTime10Ms(InstancePtr)); // 10 ms } // Video ready event has occurred @@ -603,8 +624,9 @@ void HdmiRx_PioIntrHandler(XV_HdmiRx *InstancePtr) // Set stream status to arm InstancePtr->Stream.State = XV_HDMIRX_STATE_STREAM_ARM; // The stream is armed - // Load timer - XV_HdmiRx_TmrStart(InstancePtr, Time_200ms); // 200 ms (one UHD frame is 40 ms, 5 frames) + // Load timer - 200 ms (one UHD frame is 40 ms, 5 frames) + XV_HdmiRx_TmrStart(InstancePtr, + XV_HdmiRx_GetTime200Ms(InstancePtr)); } } @@ -681,11 +703,12 @@ void HdmiRx_PioIntrHandler(XV_HdmiRx *InstancePtr) /* Clear variables */ XV_HdmiRx_Clear(InstancePtr); - // Set stream status to idle + // Set stream status to idle InstancePtr->Stream.State = XV_HDMIRX_STATE_STREAM_IDLE; // Load timer - XV_HdmiRx_TmrStart(InstancePtr, Time_10ms); // 10 ms + XV_HdmiRx_TmrStart(InstancePtr, + XV_HdmiRx_GetTime10Ms(InstancePtr)); // 10 ms } // Call mode callback @@ -719,7 +742,6 @@ void HdmiRx_PioIntrHandler(XV_HdmiRx *InstancePtr) void HdmiRx_TmrIntrHandler(XV_HdmiRx *InstancePtr) { u32 Status; - u32 Time_200ms = InstancePtr->Config.AxiLiteClkFreq/5; /* Read Status register */ Status = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_TMR_STA_OFFSET)); @@ -751,8 +773,9 @@ void HdmiRx_TmrIntrHandler(XV_HdmiRx *InstancePtr) // Clear GetVideoPropertiesTries InstancePtr->Stream.GetVideoPropertiesTries = 0; - // Load timer - XV_HdmiRx_TmrStart(InstancePtr, Time_200ms); // 200 ms (one UHD frame is 40 ms, 5 frames) + // Load timer - 200 ms (one UHD frame is 40 ms, 5 frames) + XV_HdmiRx_TmrStart(InstancePtr, + XV_HdmiRx_GetTime200Ms(InstancePtr)); } // Init state @@ -797,8 +820,9 @@ void HdmiRx_TmrIntrHandler(XV_HdmiRx *InstancePtr) } else { - // Load timer - XV_HdmiRx_TmrStart(InstancePtr, Time_200ms); // 200 ms (one UHD frame is 40 ms, 5 frames) + // Load timer - 200 ms (one UHD frame is 40 ms, 5 frames) + XV_HdmiRx_TmrStart(InstancePtr, + XV_HdmiRx_GetTime200Ms(InstancePtr)); } } @@ -839,12 +863,12 @@ void HdmiRx_AuxIntrHandler(XV_HdmiRx *InstancePtr) /* Check for GCP colordepth event */ if ((Status) & (XV_HDMIRX_AUX_STA_GCP_CD_EVT_MASK)) { - /* Clear event flag */ - XV_HdmiRx_WriteReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_AUX_STA_OFFSET), (XV_HDMIRX_AUX_STA_GCP_CD_EVT_MASK)); + /* Clear event flag */ + XV_HdmiRx_WriteReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_AUX_STA_OFFSET), (XV_HDMIRX_AUX_STA_GCP_CD_EVT_MASK)); - if ((Status) & (XV_HDMIRX_AUX_STA_GCP_MASK)) { - InstancePtr->Stream.Video.ColorDepth = XV_HdmiRx_GetGcpColorDepth(InstancePtr); - } + if ((Status) & (XV_HDMIRX_AUX_STA_GCP_MASK)) { + InstancePtr->Stream.Video.ColorDepth = XV_HdmiRx_GetGcpColorDepth(InstancePtr); + } } /* Check for new packet */ diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c index a387980..5d41a75 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c @@ -101,6 +101,7 @@ * for cleaner HPD flow during transition from HDMI2.0 * to HDMI1.4 * YH 13/04/18 Fixed a bug in XV_HdmiRxSs_BrdgOverflowCallback +* 5.20 EB 03/08/18 Added function XV_HdmiRxSs_AudioMute ******************************************************************************/ /***************************** Include Files *********************************/ @@ -174,7 +175,7 @@ static void XV_HdmiRxSs_ConfigBridgeMode(XV_HdmiRxSs *InstancePtr); /** * This macros selects the bridge pixel repeat mode * -* @param InstancePtr is a pointer to the HDMI TX Subsystem +* @param InstancePtr is a pointer to the HDMI RX Subsystem * *****************************************************************************/ #define XV_HdmiRxSs_BridgePixelDrop(InstancePtr,Enable) \ @@ -195,7 +196,8 @@ void XV_HdmiRxSs_ReportInfo(XV_HdmiRxSs *InstancePtr) xil_printf("HDMI RX Mode - "); if (InstancePtr->HdmiRxPtr->Stream.IsHdmi == (TRUE)) { xil_printf("HDMI\r\n"); - } else { + } + else { xil_printf("DVI\r\n"); } xil_printf("------------\r\n"); @@ -2219,3 +2221,24 @@ int XV_HdmiRxSs_ShowInfo(XV_HdmiRxSs *InstancePtr, char *buff, int buff_size) return strSize; } + +/* +* This function set HDMI RX audio parameters +* +* @param Enable 0: Unmute the audio 1: Mute the audio. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XV_HdmiRxSs_AudioMute(XV_HdmiRxSs *InstancePtr, u8 Enable) +{ + //Audio Mute Mode + if (Enable){ + XV_HdmiRx_AudioDisable(InstancePtr->HdmiRxPtr); + } + else{ + XV_HdmiRx_AudioEnable(InstancePtr->HdmiRxPtr); + } +} diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h index b90c9ed..705d6a5 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h @@ -75,6 +75,11 @@ * Added functions XV_HdmiRxSs_GetAviInfoframe, * XV_HdmiRxSs_GetGCP, XV_HdmiRxSs_GetAudioInfoframe, * XV_HdmiRxSs_GetVSIF +* 5.2 YB 08/14/18 Added dedicated callbacks for HDCP 1.4 and HDCP 2.2 +* protocol events. +* EB 03/08/18 Added function XV_HdmiRxSs_AudioMute +* YB 08/17/18 Marked XV_HDMIRXSS_HDCP_1_PROT_EVT and +* XV_HDMIRXSS_HDCP_2_PROT_EVT as deprecated. * * ******************************************************************************/ @@ -97,6 +102,10 @@ extern "C" { #if defined(XPAR_XHDCP_NUM_INSTANCES) || defined(XPAR_XHDCP22_RX_NUM_INSTANCES) #define USE_HDCP_RX +#define USE_HDCP_14_PROT_EVT_ENUM +_Pragma ("GCC warning \"'XV_HDMIRXSS_HDCP_1_PROT_EVT' event is deprecated\"") +#define USE_HDCP_22_PROT_EVT_ENUM +_Pragma ("GCC warning \"'XV_HDMIRXSS_HDCP_2_PROT_EVT' event is deprecated\"") #define XV_HDMIRXSS_HDCP_KEYSEL 0x00u #define XV_HDMIRXSS_HDCP_MAX_QUEUE_SIZE 16 #endif @@ -114,6 +123,10 @@ extern "C" { * @{ */ +#define ANSI_COLOR_RED "\x1b[31m" +#define ANSI_COLOR_YELLOW "\x1b[33m" +#define ANSI_COLOR_RESET "\x1b[0m" + #ifdef XV_HDMIRXSS_LOG_ENABLE typedef enum { XV_HDMIRXSS_LOG_EVT_NONE = 1, /**< Log event none. */ @@ -180,8 +193,12 @@ typedef enum XV_HDMIRXSS_HDCP_STREAMDOWN_EVT, XV_HDMIRXSS_HDCP_CONNECT_EVT, XV_HDMIRXSS_HDCP_DISCONNECT_EVT, +#ifdef USE_HDCP_14_PROT_EVT_ENUM XV_HDMIRXSS_HDCP_1_PROT_EVT, +#endif +#ifdef USE_HDCP_22_PROT_EVT_ENUM XV_HDMIRXSS_HDCP_2_PROT_EVT, +#endif XV_HDMIRXSS_HDCP_DVI_MODE_EVT, XV_HDMIRXSS_HDCP_HDMI_MODE_EVT, XV_HDMIRXSS_HDCP_SYNC_LOSS_EVT, @@ -236,7 +253,7 @@ typedef enum { event */ XV_HDMIRXSS_HANDLER_BRDGOVERFLOW, /**< Handler for bridge fifo overflow - event */ + event */ XV_HDMIRXSS_HANDLER_AUX, /**< Handler for AUX peripheral event */ XV_HDMIRXSS_HANDLER_AUD, /**< Handler for AUD @@ -465,6 +482,7 @@ int XV_HdmiRxSs_IsStreamConnected(XV_HdmiRxSs *InstancePtr); void XV_HdmiRxSs_SetDefaultPpc(XV_HdmiRxSs *InstancePtr, u8 Id); void XV_HdmiRxSs_SetPpc(XV_HdmiRxSs *InstancePtr, u8 Id, u8 Ppc); +void XV_HdmiRxSs_AudioMute(XV_HdmiRxSs *InstancePtr, u8 Enable); #ifdef XV_HDMIRXSS_LOG_ENABLE void XV_HdmiRxSs_LogReset(XV_HdmiRxSs *InstancePtr); diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.c b/hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.c index d643ef5..8509644 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.c @@ -57,6 +57,8 @@ * Add compiler option(XV_HDMIRXSS_LOG_ENABLE) to enable Log * 3.2 MH 04/07/17 Fixed issue to prevent HDCP protocol switching when only * one protocol is in the design. +* 5.2 YB 13/08/18 Added XV_HdmiRxSs_DdcHdcp14ProtocolEvtCallback() and +* XV_HdmiRxSs_DdcHdcp22ProtocolEvtCallback() functions. * * ******************************************************************************/ @@ -72,6 +74,8 @@ static void XV_HdmiRxSs_DdcSetRegAddrHandler(void *RefPtr, u32 Data); static void XV_HdmiRxSs_DdcSetRegDataHandler(void *RefPtr, u32 Data); static u32 XV_HdmiRxSs_DdcGetRegDataHandler(void *RefPtr); static void XV_HdmiRxSs_DdcHdcpCallback(void *RefPtr, int Type); +static void XV_HdmiRxSs_DdcHdcp14ProtocolEvtCallback(void *RefPtr); +static void XV_HdmiRxSs_DdcHdcp22ProtocolEvtCallback(void *RefPtr); #endif #ifdef XPAR_XHDCP22_RX_NUM_INSTANCES static u32 XV_HdmiRxSs_DdcGetWriteMessageBufferWordsHandler(void *RefPtr); @@ -268,6 +272,12 @@ int XV_HdmiRxSs_SubcoreInitHdcp14(XV_HdmiRxSs *HdmiRxSsPtr) (void *)XV_HdmiRxSs_DdcHdcpCallback, (void *)HdmiRxSsPtr); + /* Set-up the HDMI RX HDCP 1.4 Protocol Event Callback Handler */ + XV_HdmiRx_SetCallback(HdmiRxSsPtr->HdmiRxPtr, + XV_HDMIRX_HANDLER_DDC_HDCP_14_PROT, + (void *)XV_HdmiRxSs_DdcHdcp14ProtocolEvtCallback, + (void *)HdmiRxSsPtr); + /* Enable HDMI-RX DDC interrupts */ XV_HdmiRx_DdcIntrEnable(HdmiRxSsPtr->HdmiRxPtr); @@ -380,6 +390,12 @@ int XV_HdmiRxSs_SubcoreInitHdcp22(XV_HdmiRxSs *HdmiRxSsPtr) (void *)XV_HdmiRxSs_DdcHdcpCallback, (void *)HdmiRxSsPtr); + /* Set-up the HDMI RX HDCP 2.2 Protocol Event Callback Handler */ + XV_HdmiRx_SetCallback(HdmiRxSsPtr->HdmiRxPtr, + XV_HDMIRX_HANDLER_DDC_HDCP_22_PROT, + (void *)XV_HdmiRxSs_DdcHdcp22ProtocolEvtCallback, + (void *)HdmiRxSsPtr); + /* Set-up the HDMI RX Link error Callback Handler */ XV_HdmiRx_SetCallback(HdmiRxSsPtr->HdmiRxPtr, XV_HDMIRX_HANDLER_LINK_ERROR, @@ -637,7 +653,9 @@ static void XV_HdmiRxSs_DdcHdcpCallback(void *RefPtr, int Type) case XV_HDMIRX_DDC_STA_HDCP_1_PROT_EVT_MASK: #if defined(XPAR_XHDCP_NUM_INSTANCES) && defined(XPAR_XHDCP22_RX_NUM_INSTANCES) if (HdmiRxSsPtr->Hdcp14Ptr && HdmiRxSsPtr->Hdcp22Ptr) { +#ifdef USE_HDCP_14_PROT_EVT_ENUM XV_HdmiRxSs_HdcpPushEvent(HdmiRxSsPtr, XV_HDMIRXSS_HDCP_1_PROT_EVT); +#endif } #endif break; @@ -646,7 +664,9 @@ static void XV_HdmiRxSs_DdcHdcpCallback(void *RefPtr, int Type) case XV_HDMIRX_DDC_STA_HDCP_2_PROT_EVT_MASK: #if defined(XPAR_XHDCP_NUM_INSTANCES) && defined(XPAR_XHDCP22_RX_NUM_INSTANCES) if (HdmiRxSsPtr->Hdcp14Ptr && HdmiRxSsPtr->Hdcp22Ptr) { +#ifdef USE_HDCP_22_PROT_EVT_ENUM XV_HdmiRxSs_HdcpPushEvent(HdmiRxSsPtr, XV_HDMIRXSS_HDCP_2_PROT_EVT); +#endif } #endif break; @@ -655,6 +675,33 @@ static void XV_HdmiRxSs_DdcHdcpCallback(void *RefPtr, int Type) break; } } + +/*****************************************************************************/ +/** +* This function is called when the HDMI-RX DDC HDCP 1.4 Protocol Event +* interrupt has occurred. +* +* @param RefPtr is a callback reference to the HDCP22 RX instance. +* +* @return None. +* +* @note None. +******************************************************************************/ +static void XV_HdmiRxSs_DdcHdcp14ProtocolEvtCallback(void *RefPtr) +{ + XV_HdmiRxSs *HdmiRxSsPtr; + HdmiRxSsPtr = (XV_HdmiRxSs*) RefPtr; + + /* Enable HDCP 1.4 */ +#if defined(XPAR_XHDCP_NUM_INSTANCES) && defined(XPAR_XHDCP22_RX_NUM_INSTANCES) + if (HdmiRxSsPtr->Hdcp14Ptr && HdmiRxSsPtr->Hdcp22Ptr) { + if (XV_HdmiRxSs_HdcpSetProtocol(HdmiRxSsPtr, XV_HDMIRXSS_HDCP_14) != + XST_SUCCESS) { + XV_HdmiRxSs_HdcpSetProtocol(HdmiRxSsPtr, XV_HDMIRXSS_HDCP_22); + } + } +#endif +} #endif #ifdef XPAR_XHDCP22_RX_NUM_INSTANCES @@ -680,6 +727,33 @@ static void XV_HdmiRxSs_LinkErrorCallback(void *RefPtr) } } } + +/*****************************************************************************/ +/** +* This function is called when the HDMI-RX DDC HDCP 2.2 Protocol Event +* interrupt has occurred. +* +* @param RefPtr is a callback reference to the HDCP22 RX instance. +* +* @return None. +* +* @note None. +******************************************************************************/ +static void XV_HdmiRxSs_DdcHdcp22ProtocolEvtCallback(void *RefPtr) +{ + XV_HdmiRxSs *HdmiRxSsPtr; + HdmiRxSsPtr = (XV_HdmiRxSs*) RefPtr; + + /* Enable HDCP 2.2 */ +#if defined(XPAR_XHDCP_NUM_INSTANCES) && defined(XPAR_XHDCP22_RX_NUM_INSTANCES) + if (HdmiRxSsPtr->Hdcp14Ptr && HdmiRxSsPtr->Hdcp22Ptr) { + if (XV_HdmiRxSs_HdcpSetProtocol(HdmiRxSsPtr, XV_HDMIRXSS_HDCP_22) != + XST_SUCCESS) { + XV_HdmiRxSs_HdcpSetProtocol(HdmiRxSsPtr, XV_HDMIRXSS_HDCP_14); + } + } +#endif +} #endif /** @} */ diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss_hdcp.c b/hdmi/xilinx-hdmi-rx/xv_hdmirxss_hdcp.c index 75e1dc9..1038197 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss_hdcp.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss_hdcp.c @@ -507,6 +507,7 @@ static int XV_HdmiRxSs_HdcpProcessEvents(XV_HdmiRxSs *InstancePtr) #endif break; +#ifdef USE_HDCP_14_PROT_EVT_ENUM // HDCP 1.4 protocol event // Enable HDCP 1.4 case XV_HDMIRXSS_HDCP_1_PROT_EVT : @@ -518,7 +519,9 @@ static int XV_HdmiRxSs_HdcpProcessEvents(XV_HdmiRxSs *InstancePtr) } #endif break; +#endif +#ifdef USE_HDCP_22_PROT_EVT_ENUM // HDCP 2.2 protocol event // Enable HDCP 2.2 case XV_HDMIRXSS_HDCP_2_PROT_EVT : @@ -530,6 +533,7 @@ static int XV_HdmiRxSs_HdcpProcessEvents(XV_HdmiRxSs *InstancePtr) } #endif break; +#endif // DVI mode event case XV_HDMIRXSS_HDCP_DVI_MODE_EVT: @@ -560,11 +564,11 @@ static int XV_HdmiRxSs_HdcpProcessEvents(XV_HdmiRxSs *InstancePtr) // Sync est/recover event case XV_HDMIRXSS_HDCP_SYNC_EST_EVT: -#ifdef XPAR_XHDCP_NUM_INSTANCES + #ifdef XPAR_XHDCP_NUM_INSTANCES if (InstancePtr->Hdcp14Ptr) { XHdcp1x_SetHdmiMode(InstancePtr->Hdcp14Ptr, TRUE); } -#endif + #endif break; default : diff --git a/hdmi/xilinx-hdmi-tx/xv_hdmitx.c b/hdmi/xilinx-hdmi-tx/xv_hdmitx.c index 6358dc1..3597795 100644 --- a/hdmi/xilinx-hdmi-tx/xv_hdmitx.c +++ b/hdmi/xilinx-hdmi-tx/xv_hdmitx.c @@ -53,6 +53,9 @@ * EB 23/01/18 Updated XV_HdmiTx_SetAudioChannels to fix an issue * where setting audio channel value will unmute the * audio regardless of the current status +* 2.02 MMO 11/08/18 Added Bridge Overflow and Bridge Underflow (PIO IN) +* EB 14/08/18 Updated XV_HdmiTx_CfgInitialize to initialize +* HPD pulse periods * * ******************************************************************************/ @@ -174,6 +177,8 @@ int XV_HdmiTx_CfgInitialize(XV_HdmiTx *InstancePtr, XV_HdmiTx_Config *CfgPtr, /* PIO: Set event rising edge masks */ XV_HdmiTx_WriteReg(InstancePtr->Config.BaseAddress, (XV_HDMITX_PIO_IN_EVT_RE_OFFSET), + (XV_HDMITX_PIO_IN_BRDG_UNDERFLOW_MASK) | + (XV_HDMITX_PIO_IN_BRDG_OVERFLOW_MASK) | (XV_HDMITX_PIO_IN_HPD_TOGGLE_MASK) | (XV_HDMITX_PIO_IN_HPD_MASK) | (XV_HDMITX_PIO_IN_VS_MASK) | @@ -188,6 +193,27 @@ int XV_HdmiTx_CfgInitialize(XV_HdmiTx *InstancePtr, XV_HdmiTx_Config *CfgPtr, (XV_HDMITX_PIO_IN_LNK_RDY_MASK) ); + /* Set the Timegrid for HPD Pulse for Connect and Toggle Event */ + XV_HdmiTx_WriteReg(InstancePtr->Config.BaseAddress, + XV_HDMITX_HPD_TIMEGRID_OFFSET, + XV_HdmiTx_GetTime1Ms(InstancePtr)); + + /* Toggle HPD Pulse (50ms - 99ms)*/ + RegValue = ((99 << XV_HDMITX_SHIFT_16) | /* 99 ms on Bit 31:16 */ + (50)); /* 50 ms on Bit 15:0 */ + + XV_HdmiTx_WriteReg(InstancePtr->Config.BaseAddress, + XV_HDMITX_TOGGLE_CONF_OFFSET, + RegValue); + + /* HPD/Connect Trigger (100ms + 0ms)*/ + RegValue = ((10 << XV_HDMITX_SHIFT_16) | /* 10 ms on Bit 31:16 */ + (100)); /* 100 ms on Bit 15:0 */ + + XV_HdmiTx_WriteReg(InstancePtr->Config.BaseAddress, + XV_HDMITX_CONNECT_CONF_OFFSET, + RegValue); + /* Enable the PIO peripheral interrupt */ XV_HdmiTx_PioIntrEnable(InstancePtr); @@ -229,8 +255,8 @@ void XV_HdmiTx_SetAxiClkFreq(XV_HdmiTx *InstancePtr, u32 ClkFreq) { InstancePtr->CpuClkFreq = ClkFreq; - /* Initialize DDC */ - XV_HdmiTx_DdcInit(InstancePtr, InstancePtr->CpuClkFreq); + /* Initialize DDC */ + XV_HdmiTx_DdcInit(InstancePtr, InstancePtr->CpuClkFreq); } /*****************************************************************************/ @@ -379,6 +405,7 @@ u32 XV_HdmiTx_GetTmdsClk (XV_HdmiTx *InstancePtr, u32 TmdsClock; /* Calculate reference clock. First calculate the pixel clock */ + /* TODO - Not same as BM code */ if (VideoMode != XVIDC_VM_CUSTOM) { TmdsClock = XVidC_GetPixelClockHzByVmId(VideoMode); } else { @@ -796,6 +823,7 @@ XVidC_3DInfo *Info3D) ******************************************************************************/ void XV_HdmiTx_INT_VRST(XV_HdmiTx *InstancePtr, u8 Reset) { + /* Verify argument. */ Xil_AssertVoid(InstancePtr != NULL); @@ -1342,6 +1370,7 @@ static u32 XV_HdmiTx_DdcWriteCommand(XV_HdmiTx *InstancePtr, u32 Cmd) Status &= XV_HDMITX_DDC_STA_CMD_FULL; // Check if the command fifo isn't full + /* TODO - Not same as BM code */ if (!Status) { XV_HdmiTx_WriteReg(InstancePtr->Config.BaseAddress, (XV_HDMITX_DDC_CMD_OFFSET), (Cmd)); @@ -1400,6 +1429,7 @@ static u8 XV_HdmiTx_DdcReadData(XV_HdmiTx *InstancePtr) Status &= XV_HDMITX_DDC_STA_DAT_EMPTY; // Check if the data fifo has data + /* TODO - Not same as BM code */ if (!Status) { Data = XV_HdmiTx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMITX_DDC_DAT_OFFSET)); diff --git a/hdmi/xilinx-hdmi-tx/xv_hdmitx.h b/hdmi/xilinx-hdmi-tx/xv_hdmitx.h index 8f233df..12a918b 100644 --- a/hdmi/xilinx-hdmi-tx/xv_hdmitx.h +++ b/hdmi/xilinx-hdmi-tx/xv_hdmitx.h @@ -135,6 +135,9 @@ * XV_HdmiTx_VSIF_3DSampPosToString APIs * Moved VicTable, XV_HdmiTx_Aux to Hdmi Common library * EB 24/01/18 Added OverrideHdmi14Scrambler to XV_HdmiTx_Stream +* 2.2 EB 03/08/18 Marked XV_HdmiTx_AudioMute and XV_HdmiTx_AudioUnmute +* as deprecated +* MMO 11/08/18 Added Bridge Overflow and Bridge Underflow (PIO IN) * * ******************************************************************************/ @@ -168,12 +171,14 @@ extern "C" { * interrupt requests from peripheral. */ typedef enum { - XV_HDMITX_HANDLER_CONNECT = 1, // Handler for connect - XV_HDMITX_HANDLER_TOGGLE, // Handler for toggle + XV_HDMITX_HANDLER_CONNECT = 1, // Handler for connect + XV_HDMITX_HANDLER_TOGGLE, // Handler for toggle XV_HDMITX_HANDLER_BRDGUNLOCK, // Handler for bridge unlocked - XV_HDMITX_HANDLER_VS, // Handler for vsync - XV_HDMITX_HANDLER_STREAM_DOWN, // Handler for stream down - XV_HDMITX_HANDLER_STREAM_UP // Handler for stream up + XV_HDMITX_HANDLER_BRDGOVERFLOW, // Handler for bridge overflow + XV_HDMITX_HANDLER_BRDGUNDERFLOW,// Handler for bridge underflow + XV_HDMITX_HANDLER_VS, // Handler for vsync + XV_HDMITX_HANDLER_STREAM_DOWN, // Handler for stream down + XV_HDMITX_HANDLER_STREAM_UP // Handler for stream up } XV_HdmiTx_HandlerType; /*@}*/ @@ -224,7 +229,8 @@ typedef struct { u8 IsHdmi20; /**< HDMI 2.0 flag */ u8 IsScrambled; /**< Scrambler flag 1 - scrambled data , 0 - non scrambled data */ - u8 OverrideScrambler; /**< Override scramble flag */ + u8 OverrideScrambler; /**< Override scramble + flag */ u32 TMDSClock; /**< TMDS clock */ u8 TMDSClockRatio; /**< TMDS clock ration 0 - 1/10, 1 - 1/40 */ @@ -279,13 +285,28 @@ typedef struct { u32 IsVsCallbackSet; /**< Set flag. This flag is set to true when the callback has been registered */ - XV_HdmiTx_Callback BrdgUnlockedCallback; /**< Callback for Bridge UnLocked - event interrupt */ + XV_HdmiTx_Callback BrdgUnlockedCallback; /**< Callback for Bridge + *UnLocked event interrupt */ void *BrdgUnlockedRef; /**< To be passed to the Bridge Unlocked interrupt callback */ u32 IsBrdgUnlockedCallbackSet; /**< Set flag. This flag is set to true when the callback has been registered */ + XV_HdmiTx_Callback BrdgOverflowCallback; /**< Callback for Bridge + * Overflow event interrupt */ + void *BrdgOverflowRef; /**< To be passed to the Bridge + Overflow interrupt callback */ + u32 IsBrdgOverflowCallbackSet; /**< Set flag. This flag is set to + true when the callback has been registered */ + + XV_HdmiTx_Callback BrdgUnderflowCallback; /**< Callback for Bridge + * Underflow event + * interrupt */ + void *BrdgUnderflowRef; /**< To be passed to the Bridge + Underflow interrupt callback */ + u32 IsBrdgUnderflowCallbackSet; /**< Set flag. This flag is set to + true when the callback has been registered */ + XV_HdmiTx_Callback StreamDownCallback; /**< Callback for stream down callback */ void *StreamDownRef; /**< To be passed to the stream @@ -304,13 +325,28 @@ typedef struct { XHdmiC_Aux Aux; /**< AUX peripheral information */ /* HDMI TX stream */ - XV_HdmiTx_Stream Stream; /**< HDMI TX stream information */ - u32 CpuClkFreq; /* CPU Clock frequency */ + XV_HdmiTx_Stream Stream; /**< HDMI TX stream information */ + u32 CpuClkFreq; /* CPU Clock frequency */ } XV_HdmiTx; /***************** Macros (Inline Functions) Definitions *********************/ +/*****************************************************************************/ +/** +* +* This macro returns the clock cycles required to count up to 1MS with respect +* to AXI Lite Frequency +* +* @param InstancePtr is a pointer to the XV_HdmiTX core instance. +* +* @return None. +* +* +******************************************************************************/ +#define XV_HdmiTx_GetTime1Ms(InstancePtr) \ + (InstancePtr)->Config.AxiLiteClkFreq/1000 + /*****************************************************************************/ /** * @@ -435,12 +471,12 @@ typedef struct { if (SetClr) { \ XV_HdmiTx_WriteReg((InstancePtr)->Config.BaseAddress, \ (XV_HDMITX_PIO_OUT_SET_OFFSET), \ - (XV_HDMITX_PIO_OUT_BRIDGE_PIXEL_MASK)); \ + (XV_HDMITX_PIO_OUT_BRIDGE_PIXEL_MASK)); \ } \ else { \ XV_HdmiTx_WriteReg((InstancePtr)->Config.BaseAddress, \ (XV_HDMITX_PIO_OUT_CLR_OFFSET), \ - (XV_HDMITX_PIO_OUT_BRIDGE_PIXEL_MASK)); \ + (XV_HDMITX_PIO_OUT_BRIDGE_PIXEL_MASK)); \ } \ } @@ -734,12 +770,16 @@ typedef struct { * @return None. * * @note C-style signature: -* void XV_HdmiTx_AudioEnable(XV_HdmiTx *InstancePtr) +* void XV_HdmiTx_AudioUnmute(XV_HdmiTx *InstancePtr) +* +* @deprecated XV_HdmiTx_AudioUnmute will be deprecated in 2019.3 and replaced +* by XV_HdmiTx_AudioEnable. * ******************************************************************************/ #define XV_HdmiTx_AudioUnmute(InstancePtr) \ XV_HdmiTx_WriteReg((InstancePtr)->Config.BaseAddress, \ - (XV_HDMITX_AUD_CTRL_SET_OFFSET), (XV_HDMITX_AUD_CTRL_RUN_MASK)) + (XV_HDMITX_AUD_CTRL_SET_OFFSET), (XV_HDMITX_AUD_CTRL_RUN_MASK)) \ + _Pragma ("GCC warning \"'XV_HdmiTx_AudioUnmute' macro is deprecated\"") /*****************************************************************************/ /** @@ -751,12 +791,16 @@ typedef struct { * @return None. * * @note C-style signature: -* void XV_HdmiTx_AudioDisable(XV_HdmiTx *InstancePtr) +* void XV_HdmiTx_AudioMute(XV_HdmiTx *InstancePtr) +* +* @deprecated XV_HdmiTx_AudioMute will be deprecated in 2019.3 and replaced +* by XV_HdmiTx_AudioDisable. * ******************************************************************************/ #define XV_HdmiTx_AudioMute(InstancePtr) \ XV_HdmiTx_WriteReg((InstancePtr)->Config.BaseAddress, \ - (XV_HDMITX_AUD_CTRL_CLR_OFFSET), (XV_HDMITX_AUD_CTRL_RUN_MASK)) + (XV_HDMITX_AUD_CTRL_CLR_OFFSET), (XV_HDMITX_AUD_CTRL_RUN_MASK)) \ + _Pragma ("GCC warning \"'XV_HdmiTx_AudioMute' macro is deprecated\"") /*****************************************************************************/ /** @@ -821,7 +865,7 @@ typedef struct { * @return Sample rate * * @note C-style signature: -* u8 XV_HdmiTx_GetMode(XV_HdmiTx *InstancePtr) +* u8 XV_HdmiTx_GetSampleRate(XV_HdmiTx *InstancePtr) * ******************************************************************************/ #define XV_HdmiTx_GetSampleRate(InstancePtr) \ @@ -915,12 +959,12 @@ typedef struct { if (SetClr) { \ XV_HdmiTx_WriteReg((InstancePtr)->Config.BaseAddress, \ (XV_HDMITX_MASK_CTRL_SET_OFFSET), \ - (XV_HDMITX_MASK_CTRL_NOISE_MASK)); \ + (XV_HDMITX_MASK_CTRL_NOISE_MASK)); \ } \ else { \ XV_HdmiTx_WriteReg((InstancePtr)->Config.BaseAddress, \ (XV_HDMITX_MASK_CTRL_CLR_OFFSET), \ - (XV_HDMITX_MASK_CTRL_NOISE_MASK)); \ + (XV_HDMITX_MASK_CTRL_NOISE_MASK)); \ } \ } @@ -942,7 +986,7 @@ typedef struct { { \ XV_HdmiTx_WriteReg((InstancePtr)->Config.BaseAddress, \ (XV_HDMITX_MASK_RED_OFFSET), \ - (Value)); \ + (Value)); \ } /*****************************************************************************/ @@ -963,7 +1007,7 @@ typedef struct { { \ XV_HdmiTx_WriteReg((InstancePtr)->Config.BaseAddress, \ (XV_HDMITX_MASK_GREEN_OFFSET), \ - (Value)); \ + (Value)); \ } /*****************************************************************************/ @@ -984,7 +1028,7 @@ typedef struct { { \ XV_HdmiTx_WriteReg((InstancePtr)->Config.BaseAddress, \ (XV_HDMITX_MASK_BLUE_OFFSET), \ - (Value)); \ + (Value)); \ } /*****************************************************************************/ diff --git a/hdmi/xilinx-hdmi-tx/xv_hdmitx_hw.h b/hdmi/xilinx-hdmi-tx/xv_hdmitx_hw.h index 45a164e..a0b191f 100644 --- a/hdmi/xilinx-hdmi-tx/xv_hdmitx_hw.h +++ b/hdmi/xilinx-hdmi-tx/xv_hdmitx_hw.h @@ -36,13 +36,17 @@ * 1.02 YH 14/11/16 Added BRIDGE_YUV420 and BRIDGE_PIXEL mask to PIO Out * 1.03 MG 06/03/17 Added XV_HDMITX_AUX_STA_PKT_RDY_MASK * 1.04 MMO 03/05/17 Updated the comments for XV_HdmiTx_ReadReg and -* XV_HdmiTx_WriteReg +* XV_HdmiTx_WriteReg * 1.1 MG 03/05/17 Introduced video mask peripheral * 1.2 YH 22/08/17 Added XV_HDMITX_AUD_CTRL_AUDFMT_MASK (Audio Format) * 1.3 YH 06/10/17 Added XV_HDMITX_AUD_CTRL_AUDFMT_SHIFT (Audio Format) * 1.4 YH 16/01/18 Added PIO_OUT for dedicated reset for each clock domain * Added PIO_IN to bridge unlock interrupt * Added PIO_OUT to set GCP_AVMUTE +* 1.5 MMO 11/08/18 Added PIO_IN to bridge overflow and underflow interrupt +* EB 14/08/18 Added XV_HDMITX_HPD_TIMEGRID_OFFSET, +* XV_HDMITX_TOGGLE_CONF_OFFSET and +* XV_HDMITX_CONNECT_CONF_OFFSET * * ******************************************************************************/ @@ -94,9 +98,17 @@ extern "C" { #define XV_HDMITX_PIO_IN_EVT_OFFSET ((XV_HDMITX_PIO_BASE)+(10*4))/**< PIO * In Event Register * offset */ #define XV_HDMITX_PIO_IN_EVT_RE_OFFSET ((XV_HDMITX_PIO_BASE)+(11*4))/**< PIO - * In Event Rising Edge * Register offset */ + * In Event Rising Edge + * Register offset */ #define XV_HDMITX_PIO_IN_EVT_FE_OFFSET ((XV_HDMITX_PIO_BASE)+(12*4))/**< PIO - * In Event Falling Edge * Register offset */ + * In Event Falling Edge + * Register offset */ +#define XV_HDMITX_HPD_TIMEGRID_OFFSET ((XV_HDMITX_PIO_BASE)+(13*4))/**< PIO + * HPD Config. * offset */ +#define XV_HDMITX_TOGGLE_CONF_OFFSET ((XV_HDMITX_PIO_BASE)+(14*4))/**< PIO + * HPD Config. * Register offset */ +#define XV_HDMITX_CONNECT_CONF_OFFSET ((XV_HDMITX_PIO_BASE)+(15*4))/**< PIO + * HPD Config. * Register offset */ // PIO peripheral Control register masks #define XV_HDMITX_PIO_CTRL_RUN_MASK (1<<0) /**< PIO Control Run mask */ @@ -129,7 +141,7 @@ extern "C" { #define XV_HDMITX_PIO_OUT_COLOR_SPACE_SHIFT 10 /**< PIO Out Color Space * shift */ #define XV_HDMITX_PIO_OUT_GCP_CLEARAVMUTE_MASK (1<<28) /**< PIO Out - * GCP_CLEARAVMUTE mask */ + * GCP_CLEARAVMUTE mask */ #define XV_HDMITX_PIO_OUT_BRIDGE_YUV420_MASK (1<<29) /**< PIO Out Bridge_YUV420 * mask */ #define XV_HDMITX_PIO_OUT_BRIDGE_PIXEL_MASK (1<<30) /**< PIO Out Bridge_Pixel @@ -155,11 +167,16 @@ extern "C" { #define XV_HDMITX_PIO_IN_VS_MASK (1<<3) /**< PIO In Vsync mask */ #define XV_HDMITX_PIO_IN_PPP_MASK 0x07 /**< PIO In Pixel packing * phase mask */ -#define XV_HDMITX_PIO_IN_HPD_TOGGLE_MASK (1<<8) /**< PIO In HPD toggle mask */ +#define XV_HDMITX_PIO_IN_HPD_TOGGLE_MASK (1<<8) /**< PIO In HPD toggle + * mask */ #define XV_HDMITX_PIO_IN_PPP_SHIFT 5 /**< PIO In Pixel packing * phase shift */ #define XV_HDMITX_PIO_IN_BRDG_LOCKED_MASK (1<<9) /**< PIO In Bridge Locked * mask */ +#define XV_HDMITX_PIO_IN_BRDG_OVERFLOW_MASK (1<<10) /**< PIO In Bridge Overflow + * mask */ +#define XV_HDMITX_PIO_IN_BRDG_UNDERFLOW_MASK (1<<11) /**< PIO In Bridge + * Underflow mask */ /**< DDC (Display Data Channel) peripheral register offsets */ /**< The DDC is the second peripheral on the local bus */ diff --git a/hdmi/xilinx-hdmi-tx/xv_hdmitx_intr.c b/hdmi/xilinx-hdmi-tx/xv_hdmitx_intr.c index 5918410..a5516cb 100644 --- a/hdmi/xilinx-hdmi-tx/xv_hdmitx_intr.c +++ b/hdmi/xilinx-hdmi-tx/xv_hdmitx_intr.c @@ -29,6 +29,7 @@ * 1.00 10/07/15 Initial release. * 1.1 YH 18/08/16 squash unused variable compiler warning * 1.2 YH 16/01/18 Added bridge unlock interrupt +* 1.3 MMO 11/08/18 Added bridge overflow and underflow interrupt * * ******************************************************************************/ @@ -174,6 +175,20 @@ int XV_HdmiTx_SetCallback(XV_HdmiTx *InstancePtr, Status = (XST_SUCCESS); break; + case (XV_HDMITX_HANDLER_BRDGOVERFLOW): + InstancePtr->BrdgOverflowCallback = (XV_HdmiTx_Callback)CallbackFunc; + InstancePtr->BrdgOverflowRef = CallbackRef; + InstancePtr->IsBrdgOverflowCallbackSet = (TRUE); + Status = (XST_SUCCESS); + break; + + case (XV_HDMITX_HANDLER_BRDGUNDERFLOW): + InstancePtr->BrdgUnderflowCallback = (XV_HdmiTx_Callback)CallbackFunc; + InstancePtr->BrdgUnderflowRef = CallbackRef; + InstancePtr->IsBrdgUnderflowCallbackSet = (TRUE); + Status = (XST_SUCCESS); + break; + case (XV_HDMITX_HANDLER_VS): InstancePtr->VsCallback = (XV_HdmiTx_Callback)CallbackFunc; InstancePtr->VsRef = CallbackRef; @@ -272,6 +287,24 @@ void HdmiTx_PioIntrHandler(XV_HdmiTx *InstancePtr) } } + /* Bridge Overflow event has occurred */ + if ((Event) & (XV_HDMITX_PIO_IN_BRDG_OVERFLOW_MASK)) { + + // Check if user callback has been registered + if (InstancePtr->IsBrdgOverflowCallbackSet) { + InstancePtr->BrdgOverflowCallback(InstancePtr->BrdgOverflowRef); + } + } + + /* Bridge Underflow event has occurred */ + if ((Event) & (XV_HDMITX_PIO_IN_BRDG_UNDERFLOW_MASK)) { + + // Check if user callback has been registered + if (InstancePtr->IsBrdgUnderflowCallbackSet) { + InstancePtr->BrdgUnderflowCallback(InstancePtr->BrdgUnderflowRef); + } + } + /* Vsync event has occurred */ if ((Event) & (XV_HDMITX_PIO_IN_VS_MASK)) { diff --git a/hdmi/xilinx-hdmi-tx/xv_hdmitxss.c b/hdmi/xilinx-hdmi-tx/xv_hdmitxss.c index 602b085..fbea4be 100644 --- a/hdmi/xilinx-hdmi-tx/xv_hdmitxss.c +++ b/hdmi/xilinx-hdmi-tx/xv_hdmitxss.c @@ -130,6 +130,14 @@ * 01/02/18 Updated function XV_HdmiTxSs_VtcSetup and changed the * input parameters to it to enable logging of * unsupported video timing by VTC +* 5.20 EB 03/08/18 Updated XV_HdmiTxSS_MaskSetRed, XV_HdmiTxSS_MaskSetGreen, +* XV_HdmiTxSS_MaskSetBlue API +* Replaced XV_HdmiTx_AudioMute API call with +* XV_HdmiTx_AudioDisable +* Replaced XV_HdmiTx_AudioUnmute API call with +* XV_HdmiTx_AudioEnable +* Replaced XV_HdmiTx_AudioUnmute API call with +* MMO 11/08/18 Added Bridge Overflow and Bridge Underflow Interrupt * * ******************************************************************************/ @@ -196,9 +204,13 @@ static u32 XV_HdmiTxSS_SetTMDS(XV_HdmiTxSs *InstancePtr, static void XV_HdmiTxSs_ConnectCallback(void *CallbackRef); static void XV_HdmiTxSs_ToggleCallback(void *CallbackRef); static void XV_HdmiTxSs_BrdgUnlockedCallback(void *CallbackRef); +static void XV_HdmiTxSs_BrdgOverflowCallback(void *CallbackRef); +static void XV_HdmiTxSs_BrdgUnderflowCallback(void *CallbackRef); static void XV_HdmiTxSs_VsCallback(void *CallbackRef); static void XV_HdmiTxSs_StreamUpCallback(void *CallbackRef); static void XV_HdmiTxSs_StreamDownCallback(void *CallbackRef); +static u32 XV_HdmiTxSS_GetVidMaskColorValue(XV_HdmiTxSs *InstancePtr, + u16 Value); static void XV_HdmiTxSs_ReportCoreInfo(XV_HdmiTxSs *InstancePtr); static void XV_HdmiTxSs_ReportTiming(XV_HdmiTxSs *InstancePtr); @@ -354,6 +366,16 @@ static int XV_HdmiTxSs_RegisterSubsysCallbacks(XV_HdmiTxSs *InstancePtr) (void *)XV_HdmiTxSs_BrdgUnlockedCallback, (void *)InstancePtr); + XV_HdmiTx_SetCallback(HdmiTxSsPtr->HdmiTxPtr, + XV_HDMITX_HANDLER_BRDGOVERFLOW, + (void *)XV_HdmiTxSs_BrdgOverflowCallback, + (void *)InstancePtr); + + XV_HdmiTx_SetCallback(HdmiTxSsPtr->HdmiTxPtr, + XV_HDMITX_HANDLER_BRDGUNDERFLOW, + (void *)XV_HdmiTxSs_BrdgUnderflowCallback, + (void *)InstancePtr); + XV_HdmiTx_SetCallback(HdmiTxSsPtr->HdmiTxPtr, XV_HDMITX_HANDLER_VS, (void *)XV_HdmiTxSs_VsCallback, @@ -849,9 +871,9 @@ static int XV_HdmiTxSs_VtcSetup(XV_HdmiTxSs *HdmiTxSsPtr) /* 4 pixels per clock */ if (HdmiTxSsPtr->HdmiTxPtr->Stream.Video.PixPerClk == XVIDC_PPC_4) { - /* If the parameters below are not divisible by the current PPC setting, - * log an error as VTC does not support such video timing - */ + /* If the parameters below are not divisible by the current PPC setting, + * log an error as VTC does not support such video timing + */ if (VideoTiming.HActiveVideo & 0x3 || VideoTiming.HFrontPorch & 0x3 || VideoTiming.HBackPorch & 0x3 || VideoTiming.HSyncWidth & 0x3) { #ifdef XV_HDMITXSS_LOG_ENABLE @@ -867,9 +889,9 @@ static int XV_HdmiTxSs_VtcSetup(XV_HdmiTxSs *HdmiTxSsPtr) /* 2 pixels per clock */ else if (HdmiTxSsPtr->HdmiTxPtr->Stream.Video.PixPerClk == XVIDC_PPC_2) { - /* If the parameters below are not divisible by the current PPC setting, - * log an error as VTC does not support such video timing - */ + /* If the parameters below are not divisible by the current PPC setting, + * log an error as VTC does not support such video timing + */ if (VideoTiming.HActiveVideo & 0x1 || VideoTiming.HFrontPorch & 0x1 || VideoTiming.HBackPorch & 0x1 || VideoTiming.HSyncWidth & 0x1) { #ifdef XV_HDMITXSS_LOG_ENABLE @@ -893,9 +915,9 @@ static int XV_HdmiTxSs_VtcSetup(XV_HdmiTxSs *HdmiTxSsPtr) /* For YUV420 the line width is double there for double the blanking */ if (HdmiTxSsPtr->HdmiTxPtr->Stream.Video.ColorFormatId == XVIDC_CSF_YCRCB_420) { - /* If the parameters below are not divisible by the current PPC setting, - * log an error as VTC does not support such video timing - */ + /* If the parameters below are not divisible by the current PPC setting, + * log an error as VTC does not support such video timing + */ if (VideoTiming.HActiveVideo & 0x1 || VideoTiming.HFrontPorch & 0x1 || VideoTiming.HBackPorch & 0x1 || VideoTiming.HSyncWidth & 0x1) { #ifdef XV_HDMITXSS_LOG_ENABLE @@ -1024,6 +1046,7 @@ static u32 XV_HdmiTxSS_SetTMDS(XV_HdmiTxSs *InstancePtr, XVidC_VideoMode VideoMode, XVidC_ColorFormat ColorFormat, XVidC_ColorDepth Bpc) { + u32 TmdsClk; TmdsClk = XV_HdmiTx_GetTmdsClk(InstancePtr->HdmiTxPtr, @@ -1151,12 +1174,61 @@ static void XV_HdmiTxSs_BrdgUnlockedCallback(void *CallbackRef) { XV_HdmiTxSs *HdmiTxSsPtr = (XV_HdmiTxSs *)CallbackRef; +#ifdef XV_HDMITXSS_LOG_ENABLE + XV_HdmiTxSs_LogWrite(HdmiTxSsPtr, XV_HDMITXSS_LOG_EVT_BRDG_UNLOCKED, 0); +#endif + /* Check if user callback has been registered */ if (HdmiTxSsPtr->BrdgUnlockedCallback) { HdmiTxSsPtr->BrdgUnlockedCallback(HdmiTxSsPtr->BrdgUnlockedRef); } } +/*****************************************************************************/ +/** +* +* This function is called when a bridge Overflow has occurred. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void XV_HdmiTxSs_BrdgOverflowCallback(void *CallbackRef) +{ + XV_HdmiTxSs *HdmiTxSsPtr = (XV_HdmiTxSs *)CallbackRef; + + /* Check if user callback has been registered */ + if (HdmiTxSsPtr->BrdgOverflowCallback) { + HdmiTxSsPtr->BrdgOverflowCallback(HdmiTxSsPtr->BrdgOverflowRef); + } +} + + +/*****************************************************************************/ +/** +* +* This function is called when a bridge Underflow has occurred. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void XV_HdmiTxSs_BrdgUnderflowCallback(void *CallbackRef) +{ + XV_HdmiTxSs *HdmiTxSsPtr = (XV_HdmiTxSs *)CallbackRef; + + /* Check if user callback has been registered */ + if (HdmiTxSsPtr->BrdgUnderflowCallback) { + HdmiTxSsPtr->BrdgUnderflowCallback(HdmiTxSsPtr->BrdgUnderflowRef); + } +} + /*****************************************************************************/ /** * @@ -1175,7 +1247,7 @@ static void XV_HdmiTxSs_VsCallback(void *CallbackRef) // Check if user callback has been registered if (HdmiTxSsPtr->VsCallback) { - HdmiTxSsPtr->VsCallback(HdmiTxSsPtr->VsRef); + HdmiTxSsPtr->VsCallback(HdmiTxSsPtr->VsRef); } } @@ -1229,7 +1301,7 @@ static void XV_HdmiTxSs_StreamUpCallback(void *CallbackRef) if (HdmiTxSsPtr->AudioEnabled) { /* HDMI TX unmute audio */ HdmiTxSsPtr->AudioMute = (FALSE); - XV_HdmiTx_AudioUnmute(HdmiTxSsPtr->HdmiTxPtr); + XV_HdmiTx_AudioEnable(HdmiTxSsPtr->HdmiTxPtr); } /* Configure video bridge mode according to HW setting and video format */ @@ -1295,6 +1367,8 @@ static void XV_HdmiTxSs_StreamDownCallback(void *CallbackRef) * (XV_HDMITXSS_HANDLER_VS) VsCallback * (XV_HDMITXSS_HANDLER_STREAM_DOWN) StreamDownCallback * (XV_HDMITXSS_HANDLER_STREAM_UP) StreamUpCallback +* (XV_HDMITXSS_HANDLER_BRDGOVERFLOW) BrdgOverflowCallback +* (XV_HDMITXSS_HANDLER_BRDGUNDERFLOW) BrdgUnderflowCallback * (XV_HDMITXSS_HANDLER_HDCP_AUTHENTICATED) * (XV_HDMITXSS_HANDLER_HDCP_DOWNSTREAM_TOPOLOGY_AVAILABLE) * (XV_HDMITXSS_HANDLER_HDCP_UNAUTHENTICATED) @@ -1345,11 +1419,28 @@ int XV_HdmiTxSs_SetCallback(XV_HdmiTxSs *InstancePtr, // Bridge Unlocked case (XV_HDMITXSS_HANDLER_BRDGUNLOCK): - InstancePtr->BrdgUnlockedCallback = (XV_HdmiTxSs_Callback)CallbackFunc; + InstancePtr->BrdgUnlockedCallback = + (XV_HdmiTxSs_Callback)CallbackFunc; InstancePtr->BrdgUnlockedRef = CallbackRef; Status = (XST_SUCCESS); break; + // Bridge Overflow + case (XV_HDMITXSS_HANDLER_BRDGOVERFLOW): + InstancePtr->BrdgOverflowCallback = + (XV_HdmiTxSs_Callback)CallbackFunc; + InstancePtr->BrdgOverflowRef = CallbackRef; + Status = (XST_SUCCESS); + break; + + // Bridge Underflow + case (XV_HDMITXSS_HANDLER_BRDGUNDERFLOW): + InstancePtr->BrdgUnderflowCallback = + (XV_HdmiTxSs_Callback)CallbackFunc; + InstancePtr->BrdgUnderflowRef = CallbackRef; + Status = (XST_SUCCESS); + break; + // Vsync case (XV_HDMITXSS_HANDLER_VS): InstancePtr->VsCallback = (XV_HdmiTxSs_Callback)CallbackFunc; @@ -1595,7 +1686,7 @@ void XV_HdmiTxSs_StreamStart(XV_HdmiTxSs *InstancePtr) XV_HdmiTxSs_LogWrite(InstancePtr, XV_HDMITXSS_LOG_EVT_STREAMSTART, 0); #endif if ((InstancePtr->HdmiTxPtr->Stream.IsHdmi20 == (FALSE)) - && (TmdsClk > 340000000)) { + && (TmdsClk > 340000000)) { xdbg_printf(XDBG_DEBUG_GENERAL, "\r\nWarning: Sink does not support HDMI 2.0\r\n"); xdbg_printf(XDBG_DEBUG_GENERAL, @@ -1783,7 +1874,7 @@ void XV_HdmiTxSs_SetAudioChannels(XV_HdmiTxSs *InstancePtr, u8 AudioChannels) * * This function set HDMI TX audio parameters * -* @param None. +* @param Enable 0: Unmute the audio 1: Mute the audio. * * @return None. * @@ -1794,13 +1885,13 @@ void XV_HdmiTxSs_AudioMute(XV_HdmiTxSs *InstancePtr, u8 Enable) { //Audio Mute Mode if (Enable){ - XV_HdmiTx_AudioMute(InstancePtr->HdmiTxPtr); + XV_HdmiTx_AudioDisable(InstancePtr->HdmiTxPtr); #ifdef XV_HDMITXSS_LOG_ENABLE XV_HdmiTxSs_LogWrite(InstancePtr, XV_HDMITXSS_LOG_EVT_AUDIOMUTE, 0); #endif } else{ - XV_HdmiTx_AudioUnmute(InstancePtr->HdmiTxPtr); + XV_HdmiTx_AudioEnable(InstancePtr->HdmiTxPtr); #ifdef XV_HDMITXSS_LOG_ENABLE XV_HdmiTxSs_LogWrite(InstancePtr, XV_HDMITXSS_LOG_EVT_AUDIOUNMUTE, 0); #endif @@ -1942,7 +2033,7 @@ u32 XV_HdmiTxSs_SetStream(XV_HdmiTxSs *InstancePtr, #endif if(TmdsClock == 0) { xdbg_printf(XDBG_DEBUG_GENERAL, - "\nWarning: Sink does not support HDMI 2.0\r\n"); + "\r\nWarning: Sink does not support HDMI 2.0\r\n"); xdbg_printf(XDBG_DEBUG_GENERAL, " Connect to HDMI 2.0 Sink or \r\n"); xdbg_printf(XDBG_DEBUG_GENERAL, @@ -2042,11 +2133,11 @@ void XV_HdmiTxSs_SetVideoStreamType(XV_HdmiTxSs *InstancePtr, u8 StreamType) { //InstancePtr->HdmiTxPtr->Stream.IsHdmi = StreamType; if (StreamType) { - XV_HdmiTxSS_SetHdmiMode(InstancePtr); - XV_HdmiTxSs_AudioMute(InstancePtr, FALSE); + XV_HdmiTxSS_SetHdmiMode(InstancePtr); + XV_HdmiTxSs_AudioMute(InstancePtr, FALSE); } else { - XV_HdmiTxSs_AudioMute(InstancePtr, TRUE); - XV_HdmiTxSS_SetDviMode(InstancePtr); + XV_HdmiTxSs_AudioMute(InstancePtr, TRUE); + XV_HdmiTxSS_SetDviMode(InstancePtr); } } @@ -2164,16 +2255,17 @@ int XV_HdmiTxSs_DetectHdmi20(XV_HdmiTxSs *InstancePtr) ******************************************************************************/ void XV_HdmiTxSs_RefClockChangeInit(XV_HdmiTxSs *InstancePtr) { - /* Assert VID_IN bridge resets */ - XV_HdmiTxSs_SYSRST(InstancePtr, TRUE); - XV_HdmiTxSs_VRST(InstancePtr, TRUE); - /* Assert HDMI TXCore resets */ - XV_HdmiTxSs_TXCore_LRST(InstancePtr, TRUE); - XV_HdmiTxSs_TXCore_VRST(InstancePtr, TRUE); + /* Assert VID_IN bridge resets */ + XV_HdmiTxSs_SYSRST(InstancePtr, TRUE); + XV_HdmiTxSs_VRST(InstancePtr, TRUE); - /* Clear variables */ - XV_HdmiTx_Clear(InstancePtr->HdmiTxPtr); + /* Assert HDMI TXCore resets */ + XV_HdmiTxSs_TXCore_LRST(InstancePtr, TRUE); + XV_HdmiTxSs_TXCore_VRST(InstancePtr, TRUE); + + /* Clear variables */ + XV_HdmiTx_Clear(InstancePtr->HdmiTxPtr); } /*****************************************************************************/ @@ -2409,10 +2501,10 @@ static void XV_HdmiTxSs_ConfigBridgeMode(XV_HdmiTxSs *InstancePtr) { // Pixel Repetition factor of 3 and above are not supported by the bridge if (AviInfoFramePtr->PixelRepetition > XHDMIC_PIXEL_REPETITION_FACTOR_2) { #ifdef XV_HDMITXSS_LOG_ENABLE - XV_HdmiTxSs_LogWrite(InstancePtr, XV_HDMITXSS_LOG_EVT_PIX_REPEAT_ERR, - AviInfoFramePtr->PixelRepetition); + XV_HdmiTxSs_LogWrite(InstancePtr, XV_HDMITXSS_LOG_EVT_PIX_REPEAT_ERR, + AviInfoFramePtr->PixelRepetition); #endif - return; + return; } if (HdmiTxSsVidStreamPtr->ColorFormatId == XVIDC_CSF_YCRCB_420) { @@ -2525,6 +2617,19 @@ void XV_HdmiTxSS_MaskNoise(XV_HdmiTxSs *InstancePtr, u8 Enable) XV_HdmiTx_MaskNoise(InstancePtr->HdmiTxPtr, Enable); } +static u32 XV_HdmiTxSS_GetVidMaskColorValue(XV_HdmiTxSs *InstancePtr, + u16 Value) +{ + u32 Data; + s8 Temp; + + Temp = InstancePtr->Config.MaxBitsPerPixel - + InstancePtr->HdmiTxPtr->Stream.Video.ColorDepth; + Data = Value << ((Temp > 0) ? Temp : 0); + + return Data; +} + /*****************************************************************************/ /** * This function will set the red component in the video mask. @@ -2541,30 +2646,7 @@ void XV_HdmiTxSS_MaskSetRed(XV_HdmiTxSs *InstancePtr, u16 Value) { u32 Data; - switch (InstancePtr->HdmiTxPtr->Stream.Video.ColorDepth) { - - // 10 bpc - case XVIDC_BPC_10: - // Color depth - Data = (Value << 6); - break; - - // 12 bpc - case XVIDC_BPC_12: - // Color depth - Data = (Value << 4); - break; - - // 16 bpc - case XVIDC_BPC_16: - // Color depth - Data = Value; - break; - - default : - Data = (Value << 8); - break; - } + Data = XV_HdmiTxSS_GetVidMaskColorValue(InstancePtr, Value); XV_HdmiTx_MaskSetRed(InstancePtr->HdmiTxPtr, (Data)); } @@ -2586,30 +2668,7 @@ void XV_HdmiTxSS_MaskSetGreen(XV_HdmiTxSs *InstancePtr, u16 Value) { u32 Data; - switch (InstancePtr->HdmiTxPtr->Stream.Video.ColorDepth) { - - // 10 bpc - case XVIDC_BPC_10: - // Color depth - Data = (Value << 6); - break; - - // 12 bpc - case XVIDC_BPC_12: - // Color depth - Data = (Value << 4); - break; - - // 16 bpc - case XVIDC_BPC_16: - // Color depth - Data = Value; - break; - - default : - Data = (Value << 8); - break; - } + Data = XV_HdmiTxSS_GetVidMaskColorValue(InstancePtr, Value); XV_HdmiTx_MaskSetGreen(InstancePtr->HdmiTxPtr, (Data)); } @@ -2630,30 +2689,7 @@ void XV_HdmiTxSS_MaskSetBlue(XV_HdmiTxSs *InstancePtr, u16 Value) { u32 Data; - switch (InstancePtr->HdmiTxPtr->Stream.Video.ColorDepth) { - - // 10 bpc - case XVIDC_BPC_10: - // Color depth - Data = (Value << 6); - break; - - // 12 bpc - case XVIDC_BPC_12: - // Color depth - Data = (Value << 4); - break; - - // 16 bpc - case XVIDC_BPC_16: - // Color depth - Data = Value; - break; - - default : - Data = (Value << 8); - break; - } + Data = XV_HdmiTxSS_GetVidMaskColorValue(InstancePtr, Value); XV_HdmiTx_MaskSetBlue(InstancePtr->HdmiTxPtr, (Data)); } diff --git a/hdmi/xilinx-hdmi-tx/xv_hdmitxss.h b/hdmi/xilinx-hdmi-tx/xv_hdmitxss.h index 57d4e27..68fb5a1 100644 --- a/hdmi/xilinx-hdmi-tx/xv_hdmitxss.h +++ b/hdmi/xilinx-hdmi-tx/xv_hdmitxss.h @@ -86,6 +86,7 @@ * 25/01/18 Added function XV_HdmiTxSs_SetScrambler * mmo 08/02/18 Added LowResolutionSupp & YUV420Supp in the * XV_HdmiTxSs_Config +* MMO 11/08/18 Added Bridge Overflow and Bridge Underflow Interrupt * * ******************************************************************************/ @@ -129,6 +130,10 @@ extern "C" { /****************************** Type Definitions ******************************/ +#define ANSI_COLOR_RED "\x1b[31m" +#define ANSI_COLOR_YELLOW "\x1b[33m" +#define ANSI_COLOR_RESET "\x1b[0m" + /** * This typedef contains the different background colors available */ @@ -175,6 +180,7 @@ typedef enum { Repetition. */ XV_HDMITXSS_LOG_EVT_VTC_RES_ERR, /**< Log event Resolution Unsupported by VTC. */ + XV_HDMITXSS_LOG_EVT_BRDG_UNLOCKED, /**< VID-OUT bridge unlocked. */ XV_HDMITXSS_LOG_EVT_DUMMY /**< Dummy Event should be last */ } XV_HdmiTxSs_LogEvent; @@ -182,11 +188,11 @@ typedef enum { * 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. */ + 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. */ } XV_HdmiTxSs_Log; #endif @@ -267,6 +273,12 @@ typedef enum { XV_HDMITXSS_HANDLER_BRDGUNLOCK, /**< Handler for bridge unlocked event */ + XV_HDMITXSS_HANDLER_BRDGOVERFLOW, /**< Handler for + bridge overflow + event */ + XV_HDMITXSS_HANDLER_BRDGUNDERFLOW, /**< Handler for + bridge underflow + event */ XV_HDMITXSS_HANDLER_VS, /**< Handler for vsync event */ XV_HDMITXSS_HANDLER_STREAM_DOWN, /**< Handler for @@ -370,11 +382,21 @@ typedef struct void *ToggleRef; /**< To be passed to the toggle callback */ - XV_HdmiTxSs_Callback BrdgUnlockedCallback; /**< Callback for Bridge UnLocked - event interrupt */ + XV_HdmiTxSs_Callback BrdgUnlockedCallback; /**< Callback for Bridge + * UnLocked event interrupt */ void *BrdgUnlockedRef; /**< To be passed to the Bridge Unlocked interrupt callback */ + XV_HdmiTxSs_Callback BrdgOverflowCallback; /**< Callback for Bridge + * Overflow event interrupt */ + void *BrdgOverflowRef; /**< To be passed to the Bridge + Overflow interrupt callback */ + + XV_HdmiTxSs_Callback BrdgUnderflowCallback; /**< Callback for Bridge + * Underflow event interrupt */ + void *BrdgUnderflowRef; /**< To be passed to the Bridge + Underflow interrupt callback */ + XV_HdmiTxSs_Callback VsCallback; /**< Callback for Vsync event */ void *VsRef; /**< To be passed to the Vsync callback */ diff --git a/hdmi/xilinx-hdmi-tx/xv_hdmitxss_log.c b/hdmi/xilinx-hdmi-tx/xv_hdmitxss_log.c index 0faf534..80b46ef 100644 --- a/hdmi/xilinx-hdmi-tx/xv_hdmitxss_log.c +++ b/hdmi/xilinx-hdmi-tx/xv_hdmitxss_log.c @@ -282,6 +282,10 @@ int XV_HdmiTxSs_LogShow(XV_HdmiTxSs *InstancePtr, char *buff, int buff_size) strSize += scnprintf(buff+strSize, buff_size-strSize, "Unsupported Video by VTC\r\n"); break; + case (XV_HDMITXSS_LOG_EVT_BRDG_UNLOCKED): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "VID Bridge Unlocked\r\n"); + break; default: strSize += scnprintf(buff+strSize, buff_size-strSize, "Unknown event: %i\r\n", Data); diff --git a/hdmi/xilinx-hdmi-tx/xvtc.c b/hdmi/xilinx-hdmi-tx/xvtc.c index 8347792..a716da3 100644 --- a/hdmi/xilinx-hdmi-tx/xvtc.c +++ b/hdmi/xilinx-hdmi-tx/xvtc.c @@ -155,6 +155,10 @@ * sk 08/16/16 Used UINTPTR instead of u32 for Baseaddress as part of * adding 64 bit support. CR# 867425. * Changed the prototype of XVtc_CfgInitialize API. +* 8.0 jsr 07/03/18 Added a new register XVTC_GASIZE_F1_OFFSET for interlaced +* modes FIELD1 vactive size. This value is same as FILED0 +* vactive size for all interlaced modes except for SDI NTSC +* mode * * ******************************************************************************/ @@ -1335,6 +1339,18 @@ void XVtc_SetGenerator(XVtc *InstancePtr, XVtc_Signal *SignalCfgPtr) XVTC_ASIZE_VERT_MASK; XVtc_WriteReg(InstancePtr->Config.BaseAddress, XVTC_GASIZE_OFFSET, RegValue); + /* Only for XVIDC_VM_720x486_60_I (SDI NTSC), the FIELD1 vactive + * size is different from FIELD0. As there is no vactive FIELD1 + * entry in the video common library, program it separately as below */ + if(r_vactive != 243) + RegValue = ((r_vactive) << XVTC_ASIZE_VERT_SHIFT) & + XVTC_ASIZE_VERT_MASK; + else + RegValue = ((r_vactive+1) << XVTC_ASIZE_VERT_SHIFT) & + XVTC_ASIZE_VERT_MASK; + + XVtc_WriteReg(InstancePtr->Config.BaseAddress, + XVTC_GASIZE_F1_OFFSET, RegValue); /* Update the Generator Horizontal 1 Register */ RegValue = (SCPtr->HSyncStart + r_hactive) & @@ -1414,6 +1430,18 @@ void XVtc_SetGenerator(XVtc *InstancePtr, XVtc_Signal *SignalCfgPtr) XVTC_ASIZE_VERT_MASK; XVtc_WriteReg(InstancePtr->Config.BaseAddress, XVTC_GASIZE_OFFSET, RegValue); + /* Only for XVIDC_VM_720x486_60_I (SDI NTSC), the FIELD1 vactive + * size is different from FIELD0. As there is no vactive FIELD1 + * entry in the video common library, program it separately as below */ + if(r_vactive != 243) + RegValue = ((r_vactive) << XVTC_ASIZE_VERT_SHIFT) & + XVTC_ASIZE_VERT_MASK; + else + RegValue = ((r_vactive+1) << XVTC_ASIZE_VERT_SHIFT) & + XVTC_ASIZE_VERT_MASK; + + XVtc_WriteReg(InstancePtr->Config.BaseAddress, + XVTC_GASIZE_F1_OFFSET, RegValue); /* Update the Generator Horizontal 1 Register */ RegValue = (SCPtr->HSyncStart) & XVTC_SB_START_MASK; diff --git a/hdmi/xilinx-hdmi-tx/xvtc_hw.h b/hdmi/xilinx-hdmi-tx/xvtc_hw.h index 7ce32fc..a58b6a8 100644 --- a/hdmi/xilinx-hdmi-tx/xvtc_hw.h +++ b/hdmi/xilinx-hdmi-tx/xvtc_hw.h @@ -134,6 +134,7 @@ * Added backward compatibility macros. * 7.1 vns 10/14/15 Added XVTC_CTL_INTERLACE_MASK macro and * modified XVTC_CTL_ALLSS_MASK +* 8.0 jsr 07/03/18 Added new register XVTC_GASIZE_F1_OFFSET * * ******************************************************************************/ @@ -212,6 +213,8 @@ extern "C" { * Sync Offset */ #define XVTC_GVSHOFF_F1_OFFSET 0x090 /**< Generator Field 1 Vsync horizontal * Offset */ +#define XVTC_GASIZE_F1_OFFSET 0x094 /**< Generator Field 1 Active Size + * Offset */ #define XVTC_FS00_OFFSET 0x100 /**< Frame Sync 00 Config * Register Offset */ diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index 6043cfa..32cbeb8 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -634,6 +634,28 @@ static void TxVsCallback(void *CallbackRef) } } +void TxBrdgUnlockedCallback(void *CallbackRef) +{ + /* When video out bridge lost lock, reset TPG */ + /* ResetTpg(); */ + /* Config and Run the TPG */ + /* XV_ConfigTpg(&Tpg); */ + struct xlnx_drm_hdmi *xhdmi = (struct xlnx_drm_hdmi *)CallbackRef; + dev_dbg(xhdmi->dev,"TX Bridge Unlocked Callback\r\n"); +} + +void TxBrdgOverflowCallback(void *CallbackRef) +{ + struct xlnx_drm_hdmi *xhdmi = (struct xlnx_drm_hdmi *)CallbackRef; + dev_dbg(xhdmi->dev,"TX Video Bridge Overflow\r\n"); +} + +void TxBrdgUnderflowCallback(void *CallbackRef) +{ + struct xlnx_drm_hdmi *xhdmi = (struct xlnx_drm_hdmi *)CallbackRef; + dev_dbg(xhdmi->dev,"TX Video Bridge Underflow\r\n"); +} + void TxHdcpAuthenticatedCallback(void *CallbackRef) { struct xlnx_drm_hdmi *xhdmi = (struct xlnx_drm_hdmi *)CallbackRef; @@ -1940,6 +1962,12 @@ static void xlnx_drm_hdmi_initialize(struct xlnx_drm_hdmi *xhdmi) TxStreamDownCallback, (void *)xhdmi); XV_HdmiTxSs_SetCallback(HdmiTxSsPtr, XV_HDMITXSS_HANDLER_VS, TxVsCallback, (void *)xhdmi); + XV_HdmiTxSs_SetCallback(HdmiTxSsPtr, XV_HDMITXSS_HANDLER_BRDGUNLOCK, + TxBrdgUnlockedCallback, (void *)xhdmi); + XV_HdmiTxSs_SetCallback(HdmiTxSsPtr, XV_HDMITXSS_HANDLER_BRDGOVERFLOW, + TxBrdgOverflowCallback, (void *)xhdmi); + XV_HdmiTxSs_SetCallback(HdmiTxSsPtr, XV_HDMITXSS_HANDLER_BRDGUNDERFLOW, + TxBrdgUnderflowCallback, (void *)xhdmi); /* get a reference to the XVphy data structure */ xhdmi->xvphy = xvphy_get_xvphy(xhdmi->phy[0]); From 74a4c6288730e43b035211b10b256f129130b4f1 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Sat, 13 Oct 2018 07:30:09 +0800 Subject: [PATCH 10/46] dt:bindings: Update related to snd-pcm name Update related to snd-pcm name Signed-off-by: Shikhar Mishra --- Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt | 4 ++-- Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt b/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt index 39e954c..ca41cbb 100644 --- a/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt +++ b/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt @@ -55,7 +55,7 @@ Required Properties: functionality. If present, indicates optional audio core needed for audio usecase is included. - xlnx,aes_parser: alias to audio channel status extractor block - - xlnx,xlnx-snd-pcm: reference to audio formatter block. Add this if, + - xlnx,snd-pcm: reference to audio formatter block. Add this if, audio formatter is going to be used for HDMI audio. - ports: Video ports, using the DT bindings defined in ../video-interfaces.txt. The Rx only has an output port (0). @@ -91,7 +91,7 @@ added to the device tree xlnx,include-hdcp-2-2; xlnx,audio-enabled; xlnx,aes_parser = <&hdmi_audio_aes_parser_0>; - xlnx,xlnx-snd-pcm = <&audio_ss_0_audio_formatter_0>; + xlnx,snd-pcm = <&audio_ss_0_audio_formatter_0>; ports { #address-cells = <1>; #size-cells = <0>; diff --git a/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt b/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt index 2b647e8..027bdaa 100644 --- a/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt +++ b/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt @@ -66,10 +66,10 @@ Required properties: - xlnx,audio-enabled: Boolean parameter to convey that design has audio functionality. If present, indicates optional audio core needed for audio usecase is included. - - xlnx,xlnx-snd-pcm: reference to audio formatter block. Add this if, + - xlnx,snd-pcm: reference to audio formatter block. Add this if, audio formatter is going to be used for HDMI audio - xlnx,xlnx-hdmi-acr-ctrl: alias to audio clock recovery block - + Sub-Node Properties: The device tree will need to include a sub-node for the encoder endpoint interface. This port will bind the hdmi encoder with the crtc being used @@ -121,7 +121,7 @@ added to the device tree xlnx,hdcp-encrypt = <0x1>; xlnx,audio-enabled; xlnx,xlnx-hdmi-acr-ctrl = <&hdmi_acr_ctrl_0>; - xlnx,xlnx-snd-pcm = <&audio_ss_0_audio_formatter_0>; + xlnx,snd-pcm = <&audio_ss_0_audio_formatter_0>; ports { #address-cells = <1>; From aa2455b65870a0e42ad565061c9ee418055c2975 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Sat, 13 Oct 2018 07:35:04 +0800 Subject: [PATCH 11/46] hdmitx: Changed error to warning for non supported fourcc Changed error to warning for non supported fourcc Signed-off-by: Shikhar Mishra --- hdmi/xilinx_drm_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index 32cbeb8..f22ee99 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -951,7 +951,7 @@ static u32 hdmitx_find_media_bus(u32 drm_fourcc) return XVIDC_CSF_YCRCB_420; default: - printk("Error: Unknown drm_fourcc format code: %d\n", drm_fourcc); + printk("Warning: Unknown drm_fourcc format code: %d\n", drm_fourcc); return XVIDC_CSF_RGB; } } From f0a2a73eb8e426ef0fbfb3b9d99479871ec6f103 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Sat, 13 Oct 2018 07:36:51 +0800 Subject: [PATCH 12/46] clk: Removing si5324 from hdmi_module si5324 driver is now part of linux_xlnx and located at drivers/clk path and documentation is present at Documentation/devicetree/bindings/clock/silabs,si5324.txt Signed-off-by: Shikhar Mishra --- Kbuild | 1 - Makefile | 1 - clk/Makefile | 10 - clk/clk-si5324.c | 1509 ------------------------------------------ clk/clk-si5324.h | 64 -- clk/include/si5324.h | 82 --- clk/si5324drv.c | 380 ----------- clk/si5324drv.h | 159 ----- 8 files changed, 2206 deletions(-) delete mode 100644 clk/Makefile delete mode 100644 clk/clk-si5324.c delete mode 100644 clk/clk-si5324.h delete mode 100644 clk/include/si5324.h delete mode 100644 clk/si5324drv.c delete mode 100644 clk/si5324drv.h diff --git a/Kbuild b/Kbuild index 7ef8e47..6c9d391 100644 --- a/Kbuild +++ b/Kbuild @@ -1,3 +1,2 @@ -obj-m += clk/ obj-m += hdmi/ obj-m += misc/ diff --git a/Makefile b/Makefile index bb52865..cda7c67 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,5 @@ SRC := $(shell pwd) -obj-m += clk/ obj-m += hdmi/ obj-m += misc/ diff --git a/clk/Makefile b/clk/Makefile deleted file mode 100644 index adbdf0b..0000000 --- a/clk/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# status: implements/tested only features required by Xilinx HDMI - -ccflags-y += -Iinclude -ccflags-y += -DFALSE=0 -Dllabs=abs -ccflags-y += -Wno-unused-variable - -obj-m += si5324.o - -si5324-y := clk-si5324.o si5324drv.o - diff --git a/clk/clk-si5324.c b/clk/clk-si5324.c deleted file mode 100644 index 739af90..0000000 --- a/clk/clk-si5324.c +++ /dev/null @@ -1,1509 +0,0 @@ -/* - * clk-si5324.c: Silicon Laboratories Si5324 Clock Multiplier / Jitter Attenuator - * - * Leon Woestenberg - * - * References: - * [1] "Si5324 Data Sheet" - * https://www.silabs.com/Support%20Documents/TechnicalDocs/Si5324.pdf - * [2] http://www.silabs.com/Support%20Documents/TechnicalDocs/Si53xxReferenceManual.pdf - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - - -/* if both both DEBUG and DEBUG_TRACE are defined, trace_printk() is used */ -//#define DEBUG -//#define DEBUG_TRACE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "clk-si5324.h" -#include "si5324drv.h" -#include "include/si5324.h" - -/* select either trace or printk logging */ -#ifdef DEBUG_TRACE -#define do_si5324_dbg(format, ...) do { \ - trace_printk("si5324: " format, ##__VA_ARGS__); \ -} while(0) -#else -#define do_si5324_dbg(format, ...) do { \ - printk(KERN_DEBUG "si5324: " format, ##__VA_ARGS__); \ -} while(0) -#endif - -/* either enable or disable debugging */ -#ifdef DEBUG -# define si5324_dbg(x...) do_si5324_dbg(x) -#else -# define si5324_dbg(x...) -#endif - -/* bypass is a hardware debug function, but can be useful in applications, - * @TODO consider support through device-tree option later */ -#define FORCE_BYPASS 0 -#define NUM_NAME_IDS 6 //3 clkin, 1 pll, 2 clkout -#define MAX_NAME_LEN 11 - -struct si5324_driver_data; - -struct si5324_parameters { - // Current Si5342 parameters - - /* high-speed output divider */ - u32 n1_hs_min; - u32 n1_hs_max; - u32 n1_hs; - - /* low-speed output divider for clkout1 */ - u32 nc1_ls_min; - u32 nc1_ls_max; - u32 nc1_ls; - - /* low-speed output divider for clkout2 */ - u32 nc2_ls_min; - u32 nc2_ls_max; - u32 nc2_ls; - - /* high-speed feedback divider (PLL multiplier) */ - u32 n2_hs; - /* low-speed feedback divider (PLL multiplier) */ - u32 n2_ls_min; - u32 n2_ls_max; - u32 n2_ls; - - /* input divider for clk1 */ - u32 n31_min; - u32 n31_max; - u32 n31; - - /* input divider for clk1 */ - u32 n32_min; - u32 n32_max; - u32 n32; - - // Current frequencies (fixed point 36.28 notation) - u64 fin; - u64 fout; - u64 fosc; - // Best settings found - u64 best_delta_fout; - u64 best_fout; - u32 best_n1_hs; - u32 best_nc1_ls; - u32 best_n2_hs; - u32 best_n2_ls; - u32 best_n3; - int valid; -}; - -struct si5324_hw_data { - struct clk_hw hw; - struct si5324_driver_data *drvdata; - unsigned char num; -}; - -struct si5324_driver_data { - struct i2c_client *client; - struct regmap *regmap; - struct clk_onecell_data onecell; - - struct si5324_parameters params; - - struct clk *pxtal; - const char *pxtal_name; - struct clk_hw xtal; - - struct clk *pclkin1; - const char *pclkin1_name; - struct clk_hw clkin1; - - struct clk *pclkin2; - const char *pclkin2_name; - struct clk_hw clkin2; - - struct si5324_hw_data pll; - struct si5324_hw_data *clkout; - - /* temporary solution to provide actual rates */ - unsigned long rate_clkout0; - unsigned long rate_clkout1; -}; - -static const char * const si5324_input_names[] = { - "xtal", "clkin1", "clkin2" -}; - -static const char * const si5324_pll_name = "pll"; - -static const char * const si5324_clkout_names[] = { - "clk0", "clk1" -}; - -enum si53xx_variant { - si5319, - si5324, - si5328 -}; - -static const char * const si53xx_variant_name[] = { - "si5319", "si5324", "si5328" -}; - -/* - * Si5324 i2c regmap - */ -static inline u8 si5324_reg_read(struct si5324_driver_data *drvdata, u8 reg) -{ - u32 val; - int ret; - - ret = regmap_read(drvdata->regmap, reg, &val); - if (ret) { - dev_err(&drvdata->client->dev, - "unable to read from reg%02x\n", reg); - return 0; - } else { - dev_dbg(&drvdata->client->dev, "Read value 0x%02x @%02d\n", - (int)val, (int)reg); - } - - return (u8)val; -} - -static inline int si5324_bulk_read(struct si5324_driver_data *drvdata, - u8 reg, u8 count, u8 *buf) -{ - return regmap_bulk_read(drvdata->regmap, reg, buf, count); -} - -static inline int si5324_reg_write(struct si5324_driver_data *drvdata, - u8 reg, u8 val) -{ - u8 readback_val; - int ret = regmap_write(drvdata->regmap, reg, val); - dev_dbg(&drvdata->client->dev, "si5324_reg_write() 0x%02x @%02d\n", (int)val, (int)reg); -#if 0 - readback_val = si5324_reg_read(drvdata, reg); - if (readback_val != val) { - dev_err(&drvdata->client->dev, "readback 0x%02x @%02d, expected 0x%02x\n", (int)readback_val, (int)reg, (int)val); - } -#endif - return ret; -} - -static inline int si5324_bulk_write(struct si5324_driver_data *drvdata, - u8 reg, u8 count, const u8 *buf) -{ - return regmap_raw_write(drvdata->regmap, reg, buf, count); -} - -static inline int si5324_set_bits(struct si5324_driver_data *drvdata, - u8 reg, u8 mask, u8 val) -{ - return regmap_update_bits(drvdata->regmap, reg, mask, val); -} - -/* similar to Si5324_DoSettings() */ -static inline int si5324_bulk_scatter_write(struct si5324_driver_data *drvdata, - u8 count/*number of reg/val pairs*/, const u8 *buf) -{ - int i; - int result = 0; - for (i = 0; i < count; i++) { - result = si5324_reg_write(drvdata, buf[i * 2]/*reg*/, buf[i * 2 + 1]/*val*/); - if (result) return result; - } - return result; -} - -/* bare-metal: SI5324_DEFAULTS[] */ -static void si5324_initialize(struct si5324_driver_data *drvdata) -{ - /* keep RST_REG asserted for 10 ms */ - si5324_set_bits(drvdata, SI5324_RESET, - SI5324_RST_REG, SI5324_RST_REG); - msleep(10); - si5324_set_bits(drvdata, SI5324_RESET, - SI5324_RST_REG, 0); - /* wait 10 ms after de-assert */ - msleep(10); - - /* enable free-run */ - si5324_reg_write(drvdata, 0, 0x54); - - // Disable output clocks during calibration (bit 4 SQ_ICAL=1), - // other bits are default - si5324_reg_write(drvdata, 3, 0x15); - - /* clock selection mode: manual */ - si5324_reg_write(drvdata, 4, 0x12); - - // Disable CKOUT2 (SFOUT2_REG=001) - // set CKOUT1 to LVDS (SFOUT1_REG=111) - // (default is LVPECL for both) - si5324_reg_write(drvdata, 6, 0x0F); - // enable CKOUT1 output (bit 2 DSBL1_REG=0) - // disable CKOUT2 output (bit 3 DSBL2_REG=1) - si5324_reg_write(drvdata, 10, 0x08); - // Disable CKIN2 input buffer (bit 1 PD_CK2=1) - // enable CKIN1 buffer (bit 0 PD_CK1=0) - // (bit 6 is reserved, write default value) - si5324_reg_write(drvdata, 11, 0x42); - // XPAR_VID_PHY_CONTROLLER_HDMI_FAST_SWITCH - // Set lock time to 13.3ms (bits 2:0 LOCKT=011) - // and set valid time to 2ms (bits 4:3 VALTIME=00) - // other bits are default - si5324_reg_write(drvdata, 19, 0x23); - - /* bare-metal does not set this */ - /* ignore pin control CS_CA pin is ignored, CS_CA output pin tristated */ - si5324_reg_write(drvdata, 21, 0xfc); - - // Enable fast locking (bit 0 FASTLOCK=1) - si5324_reg_write(drvdata, 137, 0x01); -} - -#define SI5324_PARAMETERS_REG 25 -#define SI5324_PARAMETERS_LENGTH 24 - -/* - * 0 25 N1_HS[2:0] - * 6 31 NC1_LS[19:16] - * 7 32 NC1_LS[15:8] - * 8 33 NC1_LS[7:0] - * 9 34 NC2_LS[19:16] - * 10 35 NC2_LS[15:8] - * 11 36 NC2_LS[7:0] - * 15 40 N2_HS[2:0] N2_LS[19:16] - * 16 41 N2_LS[15:8] - * 17 42 N2_LS[7:0] - * 18 43 N31[18:16] - * 19 44 N31[15:8] - * 20 45 N31[7:0] - * 21 46 N32[18:16] - * 22 47 N32[15:8] - * 23 48 N32[7:0] - */ - -static void si5324_read_parameters(struct si5324_driver_data *drvdata) -{ - u8 buf[SI5324_PARAMETERS_LENGTH]; - - si5324_bulk_read(drvdata, 25, 1, &buf[0]); - si5324_bulk_read(drvdata, 31, 6, &buf[6]); - si5324_bulk_read(drvdata, 40, 9, &buf[15]); - - /* high-speed output divider */ - drvdata->params.n1_hs = (buf[0] >> 5); - drvdata->params.n1_hs += 4; - si5324_dbg("N1_HS = %u\n", drvdata->params.n1_hs); - /* low-speed output divider for clkout1 */ - drvdata->params.nc1_ls = ((buf[6] & 0x0f) << 16) | (buf[ 7] << 8) | buf[ 8]; - drvdata->params.nc1_ls += 1; - si5324_dbg("NC1_LS = %u\n", drvdata->params.nc1_ls); - /* low-speed output divider for clkout2 */ - drvdata->params.nc2_ls = ((buf[9] & 0x0f) << 16) | (buf[10] << 8) | buf[11]; - drvdata->params.nc2_ls += 1; - si5324_dbg("NC2_LS = %u\n", drvdata->params.nc2_ls); - /* low-speed feedback divider (PLL multiplier) */ - drvdata->params.n2_ls = ((buf[15] & 0x0f) << 16) | (buf[16] << 8) | buf[17]; - drvdata->params.n2_ls += 1; - si5324_dbg("N2_LS = %u\n", drvdata->params.n2_ls); - /* high-speed feedback divider (PLL multiplier) */ - drvdata->params.n2_hs = buf[15] >> 5; - drvdata->params.n2_hs += 4; - si5324_dbg("N2_HS = %u\n", drvdata->params.n2_hs); - /* input divider for clk1 */ - drvdata->params.n31 = ((buf[18] & 0x0f) << 16) | (buf[19] << 8) | buf[20]; - drvdata->params.n31 += 1; - si5324_dbg("N31 = %u\n", drvdata->params.n31); - /* input divider for clk2 */ - drvdata->params.n32 = ((buf[21] & 0x0f) << 16) | (buf[22] << 8) | buf[23]; - drvdata->params.n32 += 1; - si5324_dbg("N32 = %u\n", drvdata->params.n32); - drvdata->params.valid = 1; -} - -#if 0 -static void si5324_write_parameters(struct si5324_driver_data *drvdata) -{ - u8 buf[SI5324_PARAMETERS_LENGTH]; - u32 reg_val; - /* high-speed output divider */ - reg_val = drvdata->params.n1_hs - 4; - buf[0] = reg_val << 5; - /* low-speed output divider for clkout1 */ - reg_val = drvdata->params.nc1_ls - 1; - buf[6] = (reg_val >> 16) & 0x0f; - buf[7] = (reg_val >> 8) & 0xff; - buf[8] = reg_val & 0xff; - /* low-speed output divider for clkout2 */ - reg_val = drvdata->params.nc2_ls; - buf[ 9] = (reg_val >> 16) & 0x0f; - buf[10] = (reg_val >> 8) & 0xff; - buf[11] = reg_val & 0xff; - /* low-speed feedback divider (PLL multiplier) */ - reg_val = drvdata->params.n2_ls + 1; - buf[15] = (reg_val >> 16) & 0x0f; - buf[16] = (reg_val >> 8) & 0xff; - buf[17] = reg_val & 0xff; - /* high-speed feedback divider (PLL multiplier) */ - reg_val = drvdata->params.n2_hs - 4; - buf[15] |= reg_val << 5; - /* input divider for clk1 */ - reg_val = drvdata->params.n31; - buf[18] = (reg_val >> 16) & 0x0f; - buf[19] = (reg_val >> 8) & 0xff; - buf[20] = reg_val & 0xff; - /* input divider for clk2 */ - reg_val = drvdata->params.n31; - buf[21] = (reg_val >> 16) & 0x0f; - buf[22] = (reg_val >> 8) & 0xff; - buf[23] = reg_val & 0xff; - si5324_bulk_write(drvdata, 25, 1, &buf[0]); - si5324_bulk_write(drvdata, 31, 6, &buf[6]); - si5324_bulk_write(drvdata, 40, 9, &buf[15]); - -} -#endif - -static bool si5324_regmap_is_volatile(struct device *dev, unsigned int reg) -{ - return true; -#if 0/*@TODO */ - return false; -#endif -} - -static bool si5324_regmap_is_readable(struct device *dev, unsigned int reg) -{ - bool result = true; - /* reserved registers */ - if (reg >= 12 && reg <= 18) - result = false; - else if (reg >= 26 && reg <= 30) - result = false; - else if (reg >= 37 && reg <= 39) - result = false; - else if (reg >= 49 && reg <= 54) - result = false; - else if (reg >= 56 && reg <= 127) - result = false; - else if (reg >= 144) - result = false; -#if 0 - si5324_dbg("si5324_regmap_is_readable(reg0x%02x) = %u\n", reg, result); -#endif - return result; -} - -static bool si5324_regmap_is_writeable(struct device *dev, unsigned int reg) -{ - bool result = true; - /* reserved registers */ - if (reg >= 12 && reg <= 18) - result = false; - else if (reg >= 26 && reg <= 30) - result = false; - else if (reg >= 37 && reg <= 39) - result = false; - else if (reg >= 49 && reg <= 54) - result = false; - else if (reg >= 56 && reg <= 127) - result = false; - else if (reg >= 144) - result = false; - /* read-only */ - else if (reg >= 128 && reg <= 130) - result = false; - else if (reg >= 134 && reg <= 135) - result = false; -#if 0 - si5324_dbg("si5324_regmap_is_writeable(reg0x%02x) = %u\n", reg, result); -#endif - return result; -} - -static const struct regmap_config si5324_regmap_config = { - .reg_bits = 8, - .val_bits = 8, - .cache_type = REGCACHE_RBTREE, - .max_register = 144, - .writeable_reg = si5324_regmap_is_writeable, - .readable_reg = si5324_regmap_is_readable, - .volatile_reg = si5324_regmap_is_volatile, -}; - -/* - * Si5324 xtal clock input - */ -static int si5324_xtal_prepare(struct clk_hw *hw) -{ - struct si5324_driver_data *drvdata = - container_of(hw, struct si5324_driver_data, xtal); - - si5324_dbg("si5324_xtal_prepare-nop; set to free-running mode from xtal\n"); - return 0; -} - -static void si5324_xtal_unprepare(struct clk_hw *hw) -{ - struct si5324_driver_data *drvdata = - container_of(hw, struct si5324_driver_data, xtal); - si5324_dbg("si5324_xtal_unprepare - nop\n"); -} - -static const struct clk_ops si5324_xtal_ops = { - .prepare = si5324_xtal_prepare, - .unprepare = si5324_xtal_unprepare, -}; - -/* - * Si5324 clkin1/clkin2 clock input - */ -static int si5324_clkin_prepare(struct clk_hw *hw) -{ - struct si5324_driver_data *drvdata; - struct si5324_hw_data *hwdata = - container_of(hw, struct si5324_hw_data, hw); - si5324_dbg("si5324_clkin_prepare() for hwdata->num = %d\n", hwdata->num); - - /* clkin1? */ - if (hwdata->num == 0/*@TODO: verify if this should be 1*/) { - drvdata = container_of(hw, struct si5324_driver_data, clkin1); - /* disable free-run */ - si5324_set_bits(drvdata, SI5324_REG0, SI5324_REG0_FREE_RUN, 0); - /* clkin1 powered, clkin2 powered-down*/ - si5324_set_bits(drvdata, SI5324_POWERDOWN, - SI5324_PD_CK1 | SI5324_PD_CK2, SI5324_PD_CK2); - } else if (hwdata->num == 1/*@TODO: verify if this should be 2*/) { - drvdata = container_of(hw, struct si5324_driver_data, clkin2); - /* disable free-run */ - si5324_set_bits(drvdata, SI5324_REG0, SI5324_REG0_FREE_RUN, 0); - /* clkin2 powered, clkin1 powered-down*/ - si5324_set_bits(drvdata, SI5324_POWERDOWN, - SI5324_PD_CK1 | SI5324_PD_CK2, SI5324_PD_CK1); - } else { - } - return 0; -} - -static void si5324_clkin_unprepare(struct clk_hw *hw) -{ - struct si5324_driver_data *drvdata; - struct si5324_hw_data *hwdata = - container_of(hw, struct si5324_hw_data, hw); - si5324_dbg("si5324_clkin_unprepare\n"); - if (hwdata->num == 0/*@TODO:1?*/) { - drvdata = container_of(hw, struct si5324_driver_data, clkin1); - } else if (hwdata->num == 1/*@TODO:2?*/) { - drvdata = container_of(hw, struct si5324_driver_data, clkin2); - } else { - } -} - -/* - * @recalc_rate Recalculate the rate of this clock, by querying hardware. The - * parent rate is an input parameter. It is up to the caller to - * ensure that the prepare_mutex is held across this call. - * Returns the calculated rate. - */ -static unsigned long si5324_clkin_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return 0; -#if 0 - struct si5324_driver_data *drvdata = NULL; - unsigned long rate; - unsigned char idiv; - struct si5324_hw_data *hwdata = - container_of(hw, struct si5324_hw_data, hw); - idiv = 1; - - si5324_dbg("si5324_clkin_recalc_rate() hwdata->num = %d\n", hwdata->num); - if (hwdata->num == 0) { - drvdata = container_of(hw, struct si5324_driver_data, xtal); - si5324_dbg("si5324_clkin_recalc_rate(parent_rate=%lu for xtal)\n", parent_rate); - } else if (hwdata->num == 1) { - drvdata = container_of(hw, struct si5324_driver_data, clkin1); - si5324_dbg("si5324_clkin_recalc_rate(parent_rate=%lu for clkin1)\n", parent_rate); - } else if (hwdata->num == 2) { - drvdata = container_of(hw, struct si5324_driver_data, clkin2); - si5324_dbg("si5324_clkin_recalc_rate(parent_rate=%lu for clkin2)\n", parent_rate); - } else { - si5324_dbg("si5324_clkin_recalc_rate() hwdata->num = %d\n", hwdata->num); - return 0; - } - - rate = parent_rate; - - /* f3 (behind /N3x) is out of range, i,e, >2MHz? */ - if (rate > 2000000) { - /* set input divider */ - idiv = (rate + 2000000 - 1) / 2000000; - rate = parent_rate / idiv; - } -/* - si5324_set_bits(drvdata, SI5324_PLL_INPUT_SOURCE, - SI5324_CLKIN_DIV_MASK, idiv); -*/ - if (drvdata) - dev_dbg(&drvdata->client->dev, "%s - clkin div = %d, rate = %lu\n", - __func__, (1 << (idiv >> 6)), rate); - return rate; -#endif -} - -static const struct clk_ops si5324_clkin_ops = { - .prepare = si5324_clkin_prepare, - .unprepare = si5324_clkin_unprepare, - .recalc_rate = si5324_clkin_recalc_rate, -}; - -/* Select other clock input to the PLL - */ -static int _si5324_pll_reparent(struct si5324_driver_data *drvdata, - int num, enum si5324_pll_src parent) -{ - si5324_dbg("_si5324_pll_reparent() for parent = %d\n", (int)parent); - - if (parent == SI5324_PLL_SRC_XTAL) { - /* enable free-run */ - si5324_set_bits(drvdata, SI5324_REG0, - SI5324_REG0_FREE_RUN, SI5324_REG0_FREE_RUN); - /* clkin2 powered, clkin1 powered-down, xtal connects to clkin2 */ - si5324_set_bits(drvdata, SI5324_POWERDOWN, - SI5324_PD_CK1 | SI5324_PD_CK2, SI5324_PD_CK1); - /* select clkin2 */ - si5324_set_bits(drvdata, SI5324_CKSEL, - 3 << 6, 1 << 6); - } else if (parent == SI5324_PLL_SRC_CLKIN1) { - /* disable free-run */ - si5324_set_bits(drvdata, SI5324_REG0, - SI5324_REG0_FREE_RUN, 0); - /* clkin1 powered, clkin2 powered-down */ - si5324_set_bits(drvdata, SI5324_POWERDOWN, - SI5324_PD_CK1 | SI5324_PD_CK2, SI5324_PD_CK2); - /* select clkin1 */ - si5324_set_bits(drvdata, SI5324_CKSEL, - 3 << 6, 0); - } else if (parent == SI5324_PLL_SRC_CLKIN2) { - /* disable free-run */ - si5324_set_bits(drvdata, SI5324_REG0, - SI5324_REG0_FREE_RUN, 0); - /* clkin2 powered, clkin1 powered-down */ - si5324_set_bits(drvdata, SI5324_POWERDOWN, - SI5324_PD_CK1 | SI5324_PD_CK2, SI5324_PD_CK1); - /* select clkin2 */ - si5324_set_bits(drvdata, SI5324_CKSEL, - 3 << 6, 1 << 6); - } - dev_dbg(&drvdata->client->dev, "_si5324_pll_reparent()\n"); - si5324_reg_read(drvdata, 0); - si5324_reg_read(drvdata, 4); - si5324_reg_read(drvdata, 3); - return 0; -} - -static unsigned char si5324_pll_get_parent(struct clk_hw *hw) -{ - struct si5324_hw_data *hwdata = - container_of(hw, struct si5324_hw_data, hw); - return 0; -} - -static int si5324_pll_set_parent(struct clk_hw *hw, u8 index) -{ - struct si5324_hw_data *hwdata = - container_of(hw, struct si5324_hw_data, hw); - enum si5324_pll_src parent; - si5324_dbg("si5324_pll_set_parent(index=%d)\n", index); - - if (index == 0) - parent = SI5324_PLL_SRC_XTAL; - else if (index == 1) - parent = SI5324_PLL_SRC_CLKIN1; - else if (index == 2) - parent = SI5324_PLL_SRC_CLKIN2; - else - return -EINVAL; - - return _si5324_pll_reparent(hwdata->drvdata, hwdata->num, parent); -} - -static unsigned long si5324_pll_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - unsigned long rate; - struct si5324_hw_data *hwdata = - container_of(hw, struct si5324_hw_data, hw); - si5324_dbg("si5324_pll_recalc_rate(parent_rate=%lu)\n", - parent_rate); - - if (!hwdata->drvdata->params.valid) - si5324_read_parameters(hwdata->drvdata); - WARN_ON(!hwdata->drvdata->params.valid); - - rate = parent_rate * hwdata->drvdata->params.n2_ls * hwdata->drvdata->params.n2_hs; - - dev_dbg(&hwdata->drvdata->client->dev, - "%s - %s: n2_ls = %u, n2_hs = %u, parent_rate = %lu, rate = %lu\n", - __func__, clk_hw_get_name(hw), - hwdata->drvdata->params.n2_ls, hwdata->drvdata->params.n2_hs, - parent_rate, (unsigned long)rate); - return rate; -} - -static long si5324_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - struct si5324_hw_data *hwdata = - container_of(hw, struct si5324_hw_data, hw); - si5324_dbg("si5324_pll_round_rate(rate=%lu, parent_rate=%lu)\n", - rate, *parent_rate); - -#if 0 - unsigned long rfrac, denom, a, b, c; - unsigned long long lltmp; - - if (rate < SI5324_PLL_VCO_MIN) - rate = SI5324_PLL_VCO_MIN; - if (rate > SI5324_PLL_VCO_MAX) - rate = SI5324_PLL_VCO_MAX; - - /* determine integer part of feedback equation */ - a = rate / *parent_rate; - - if (a < SI5324_PLL_A_MIN) - rate = *parent_rate * SI5324_PLL_A_MIN; - if (a > SI5324_PLL_A_MAX) - rate = *parent_rate * SI5324_PLL_A_MAX; - - /* find best approximation for b/c = fVCO mod fIN */ - denom = 1000 * 1000; - lltmp = rate % (*parent_rate); - lltmp *= denom; - do_div(lltmp, *parent_rate); - rfrac = (unsigned long)lltmp; - - b = 0; - c = 1; - if (rfrac) - rational_best_approximation(rfrac, denom, - SI5324_PLL_B_MAX, SI5324_PLL_C_MAX, &b, &c); - - /* calculate parameters */ - hwdata->drvdata->params.p3 = c; - hwdata->drvdata->params.p2 = (128 * b) % c; - hwdata->drvdata->params.p1 = 128 * a; - hwdata->drvdata->params.p1 += (128 * b / c); - hwdata->drvdata->params.p1 -= 512; - - /* recalculate rate by fIN * (a + b/c) */ - lltmp = *parent_rate; - lltmp *= b; - do_div(lltmp, c); - - rate = (unsigned long)lltmp; - rate += *parent_rate * a; - - dev_dbg(&hwdata->drvdata->client->dev, - "%s - %s: a = %lu, b = %lu, c = %lu, parent_rate = %lu, rate = %lu\n", - __func__, clk_hw_get_name(hw), a, b, c, - *parent_rate, rate); -#endif - return rate; -} - -static int si5324_pll_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct si5324_hw_data *hwdata = - container_of(hw, struct si5324_hw_data, hw); - si5324_dbg("si5324_pll_set_rate(rate=%lu, parent_rate=%lu)\n", - rate, parent_rate); -#if 0 - u8 reg = (hwdata->num == 0) ? SI5324_PLLA_PARAMETERS : - SI5324_PLLB_PARAMETERS; - - /* write multisynth parameters */ - si5324_write_parameters(hwdata->drvdata, reg, &hwdata->drvdata->params); - - /* plla/pllb ctrl is in clk6/clk7 ctrl registers */ - si5324_set_bits(hwdata->drvdata, SI5324_CLK6_CTRL + hwdata->num, - SI5324_CLK_INTEGER_MODE, - (hwdata->drvdata->params.p2 == 0) ? SI5324_CLK_INTEGER_MODE : 0); - - dev_dbg(&hwdata->drvdata->client->dev, - "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, parent_rate = %lu, rate = %lu\n", - __func__, clk_hw_get_name(hw), - hwdata->drvdata->params.p1, hwdata->drvdata->params.p2, hwdata->drvdata->params.p3, - parent_rate, rate); -#endif - return 0; -} - -static const struct clk_ops si5324_pll_ops = { - .set_parent = si5324_pll_set_parent, - .get_parent = si5324_pll_get_parent, - .recalc_rate = si5324_pll_recalc_rate, - .round_rate = si5324_pll_round_rate, - .set_rate = si5324_pll_set_rate, -}; - -static int _si5324_clkout_set_drive_strength( - struct si5324_driver_data *drvdata, int num, - enum si5324_drive_strength drive) -{ -#if 0 - u8 mask; - - if (num > 8) - return -EINVAL; - - switch (drive) { - case SI5324_DRIVE_2MA: - mask = SI5324_CLK_DRIVE_STRENGTH_2MA; - break; - case SI5324_DRIVE_4MA: - mask = SI5324_CLK_DRIVE_STRENGTH_4MA; - break; - case SI5324_DRIVE_6MA: - mask = SI5324_CLK_DRIVE_STRENGTH_6MA; - break; - case SI5324_DRIVE_8MA: - mask = SI5324_CLK_DRIVE_STRENGTH_8MA; - break; - default: - return 0; - } - - si5324_set_bits(drvdata, SI5324_CLK0_CTRL + num, - SI5324_CLK_DRIVE_STRENGTH_MASK, mask); -#endif - return 0; -} - -static int _si5324_clkout_set_disable_state( - struct si5324_driver_data *drvdata, int num, - enum si5324_disable_state state) -{ -#if 0 - u8 reg = (num < 4) ? SI5324_CLK3_0_DISABLE_STATE : - SI5324_CLK7_4_DISABLE_STATE; - u8 shift = (num < 4) ? (2 * num) : (2 * (num-4)); - u8 mask = SI5324_CLK_DISABLE_STATE_MASK << shift; - u8 val; - - if (num > 8) - return -EINVAL; - - switch (state) { - case SI5324_DISABLE_LOW: - val = SI5324_CLK_DISABLE_STATE_LOW; - break; - case SI5324_DISABLE_HIGH: - val = SI5324_CLK_DISABLE_STATE_HIGH; - break; - case SI5324_DISABLE_FLOATING: - val = SI5324_CLK_DISABLE_STATE_FLOAT; - break; - case SI5324_DISABLE_NEVER: - val = SI5324_CLK_DISABLE_STATE_NEVER; - break; - default: - return 0; - } - - si5324_set_bits(drvdata, reg, mask, val << shift); -#endif - return 0; -} - -static int si5324_clkout_prepare(struct clk_hw *hw) -{ - struct si5324_hw_data *hwdata = - container_of(hw, struct si5324_hw_data, hw); - - si5324_dbg("si5324_clkout_prepare for hwdata->num=%d - NOP\n",hwdata->num); -#if 0 //clock always enabled for xilinx vphy operation - /* clear power-down bit for output clock num */ - si5324_set_bits(hwdata->drvdata, SI5324_DSBL_CLKOUT, - 1 << (hwdata->num + 2), 0); -#endif - return 0; -} - -static void si5324_clkout_unprepare(struct clk_hw *hw) -{ - struct si5324_hw_data *hwdata = - container_of(hw, struct si5324_hw_data, hw); - - si5324_dbg("si5324_clkout_unprepare for hwdata->num=%d - NOP\n",hwdata->num); -#if 0 //do not disable clocks for xilinx vphy operation - /* set power-down bit for output clock num */ - si5324_set_bits(hwdata->drvdata, SI5324_DSBL_CLKOUT, - 1 << (hwdata->num + 2), 1 << (hwdata->num + 2)); -#endif -} - -/* - * Si5324 clkout divider - */ -static unsigned long si5324_clkout_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct si5324_hw_data *hwdata = - container_of(hw, struct si5324_hw_data, hw); - unsigned long rate = 0; - - si5324_dbg("si5324_clkout_recalc_rate(parent_rate=%lu)\n", parent_rate); -#if 0 - si5324_dbg("si5324_clkout_recalc_rate(parent_rate=%lu) clkout%d\n", - parent_rate, hwdata->num); - - //if (!hwdata->drvdata->params.valid) - si5324_read_parameters(hwdata->drvdata, 24); - WARN_ON(!hwdata->drvdata->params.valid); - - /* clkout1? */ - if (hwdata->num == 0) - rate = (parent_rate / hwdata->drvdata->params.n1_hs) / hwdata->drvdata->params.nc1_ls; - /* clkout2? */ - else if (hwdata->num == 1) - rate = (parent_rate / hwdata->drvdata->params.n1_hs) / hwdata->drvdata->params.nc2_ls; - - si5324_dbg("si5324_clkout_recalc_rate(parent_rate=%lu) => clkout%d=%lu (invalid)\n", - parent_rate, hwdata->num, rate); -#endif - - rate = hwdata->drvdata->rate_clkout0; - - si5324_dbg("si5324_clkout_recalc_rate() = %lu\n", rate); - return rate; -} - -/* round_rate selects the rate closest to the requested one. -determine_rate does the same but even better by changing the clock’s -parent. The actual setting is done by set_rate. recalc_rate is called -when a parent changes rate. */ -static long si5324_clkout_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - struct si5324_hw_data *hwdata = - container_of(hw, struct si5324_hw_data, hw); - unsigned char rdiv; - u32 NCn_ls, N2_ls, N3n; - u8 N1_hs, N2_hs, BwSel; - u32 actual_rate; - int result; - si5324_dbg("si5324_clkout_round_rate(rate=%lu, parent_rate=%lu)\n", - rate, *parent_rate); - - si5324_dbg("%s - %s: parent_rate = %lu, rate = %lu\n", - __func__, clk_hw_get_name(hw), *parent_rate, rate); - - // Calculate the frequency settings for the Si5324 - result = Si5324_CalcFreqSettings(114285000, rate, &actual_rate, - &N1_hs, &NCn_ls, &N2_hs, &N2_ls, &N3n, &BwSel); - -#if 0 - if (rate > SI5324_CLKOUT_MAX_FREQ) - rate = SI5324_CLKOUT_MAX_FREQ; - if (rate < SI5324_CLKOUT_MIN_FREQ) - rate = SI5324_CLKOUT_MIN_FREQ; - - /* request frequency if multisync master */ - if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) { - /* use r divider for frequencies below 1MHz */ - rdiv = SI5324_OUTPUT_CLK_DIV_1; - while (rate < SI5324_MULTISYNTH_MIN_FREQ && - rdiv < SI5324_OUTPUT_CLK_DIV_128) { - rdiv += 1; - rate *= 2; - } - *parent_rate = rate; - } else { - unsigned long new_rate, new_err, err; - - /* round to closed rdiv */ - rdiv = SI5324_OUTPUT_CLK_DIV_1; - new_rate = *parent_rate; - err = abs(new_rate - rate); - do { - new_rate >>= 1; - new_err = abs(new_rate - rate); - if (new_err > err || rdiv == SI5324_OUTPUT_CLK_DIV_128) - break; - rdiv++; - err = new_err; - } while (1); - } - rate = *parent_rate >> rdiv; - - dev_dbg(&hwdata->drvdata->client->dev, - "%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n", - __func__, clk_hw_get_name(hw), (1 << rdiv), - *parent_rate, rate); -#endif - - si5324_dbg("si5324_clkout_round_rate() = %lu\n", actual_rate); - return actual_rate; -} - -static int si5324_clkout_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct si5324_hw_data *hwdata = - container_of(hw, struct si5324_hw_data, hw); - - u32 NCn_ls, N2_ls, N3n; - u8 N1_hs, N2_hs, BwSel; - u32 actual_rate; - int result; - u8 buf[14*2]; // Need to set 14 registers - int i; - int rc; - - si5324_dbg("si5324_clkout_set_rate(rate = %lu)\n", rate); - - // Calculate the frequency settings for the Si5324 - result = Si5324_CalcFreqSettings(114285000, rate, &actual_rate, - &N1_hs, &NCn_ls, &N2_hs, &N2_ls, &N3n, - &BwSel); - si5324_dbg("N1_HS = %u\n", (unsigned int)N1_hs + 4); - si5324_dbg("NC1_LS = %u\n", (unsigned int)NCn_ls + 1); - si5324_dbg("N2_HS = %u\n", (unsigned int)N2_hs + 4); - si5324_dbg("N2_LS = %u\n", (unsigned int)N2_ls + 1); - si5324_dbg("N3 = %u\n", (unsigned int)N3n + 1); - si5324_dbg("actual rate = %u\n", actual_rate); - - /* remember actual clkout0 output rate */ - hwdata->drvdata->rate_clkout0 = rate; - - i = 0; - - // Free running mode or use a reference clock - buf[i] = 0; - // Enable free running mode - buf[i+1] = 0x54; - i += 2; - - // Loop bandwidth - buf[i] = 2; - buf[i+1] = (BwSel << 4) | 0x02; - i += 2; - - // Enable reference clock 2 in free running mode - buf[i] = 11; - //Enable input clock 2, Disable input clock 1 - buf[i+1] = 0x41; - i += 2; - - // N1_HS - buf[i] = 25; - buf[i+1] = N1_hs << 5; - i += 2; - - // NC1_LS - buf[i] = 31; - buf[i+1] = (u8)((NCn_ls & 0x000F0000) >> 16); - buf[i+2] = 32; - buf[i+3] = (u8)((NCn_ls & 0x0000FF00) >> 8); - buf[i+4] = 33; - buf[i+5] = (u8)( NCn_ls & 0x000000FF ); - i += 6; - - // N2_HS and N2_LS - buf[i] = 40; - buf[i+1] = (N2_hs << 5); - // N2_LS upper bits (same register as N2_HS) - buf[i+1] |= (u8)((N2_ls & 0x000F0000) >> 16); - buf[i+2] = 41; - buf[i+3] = (u8)((N2_ls & 0x0000FF00) >> 8); - buf[i+4] = 42; - buf[i+5] = (u8)( N2_ls & 0x000000FF ); - i += 6; - - // N32 (CLKIN2 or XTAL in FREERUNNING mode) - buf[i] = 46; - buf[i+2] = 47; - buf[i+4] = 48; - buf[i+1] = (u8)((N3n & 0x00070000) >> 16); - buf[i+3] = (u8)((N3n & 0x0000FF00) >> 8); - buf[i+5] = (u8)( N3n & 0x000000FF ); - i += 6; - - // Start calibration - buf[i] = 136; - buf[i+1] = 0x40; - i += 2; - - hwdata->drvdata->params.valid = 0; - // disable CKOUT1 output (bit 2 DSBL1_REG=1) - // disable CKOUT2 output (bit 3 DSBL2_REG=1) - //si5324_reg_write(hwdata->drvdata, 10, 0x0c); - si5324_reg_read(hwdata->drvdata, 0); - si5324_reg_read(hwdata->drvdata, 3); - si5324_reg_read(hwdata->drvdata, 4); - si5324_reg_read(hwdata->drvdata, 11); - si5324_reg_read(hwdata->drvdata, 21); - rc = si5324_bulk_scatter_write(hwdata->drvdata, 14, buf); - // enable CKOUT1 output (bit 2 DSBL1_REG=1) - // disable CKOUT2 output (bit 3 DSBL2_REG=1) - //si5324_reg_write(hwdata->drvdata, 10, 0x08); - -#if 0 - /* dump all registers */ - for (i = 0; i < 145; i++) - si5324_reg_read(hwdata->drvdata, i); -#endif - return rc; -} - -static const struct clk_ops si5324_clkout_ops = { - .prepare = si5324_clkout_prepare, - .unprepare = si5324_clkout_unprepare, - .recalc_rate = si5324_clkout_recalc_rate, - .round_rate = si5324_clkout_round_rate, - .set_rate = si5324_clkout_set_rate, -}; - -/* - * Si5324 i2c probe and DT - */ -#ifdef CONFIG_OF -static const struct of_device_id si5324_dt_ids[] = { - { .compatible = "silabs,si5319" }, - { .compatible = "silabs,si5324" }, - { .compatible = "silabs,si5328" }, - { } -}; -MODULE_DEVICE_TABLE(of, si5324_dt_ids); - -static int si5324_dt_parse(struct i2c_client *client) -{ - struct device_node *child, *np = client->dev.of_node; - struct si5324_platform_data *pdata; - struct property *prop; - const __be32 *p; - int num = 0; - u32 val; - - if (np == NULL) - return 0; - - pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - /* - * property silabs,pll-source : , [<..>] - * allow to selectively set pll source - */ - of_property_for_each_u32(np, "silabs,pll-source", prop, p, num) { - if (num >= 1) { - dev_err(&client->dev, - "invalid pll %d on pll-source prop\n", num); - return -EINVAL; - } - p = of_prop_next_u32(prop, p, &val); - if (!p) { - dev_err(&client->dev, - "missing pll-source for pll %d\n", num); - return -EINVAL; - } - - switch (val) { - case 0: - dev_dbg(&client->dev, "using xtal as parent for pll\n"); - pdata->pll_src = SI5324_PLL_SRC_XTAL; - break; - case 1: - dev_dbg(&client->dev, "using clkin1 as parent for pll\n"); - pdata->pll_src = SI5324_PLL_SRC_CLKIN1; - break; - case 2: - dev_dbg(&client->dev, "using clkin2 as parent for pll\n"); - pdata->pll_src = SI5324_PLL_SRC_CLKIN2; - break; - default: - dev_err(&client->dev, - "invalid parent %d for pll %d\n", val, num); - return -EINVAL; - } - } - /* per clkout properties */ - for_each_child_of_node(np, child) { - if (of_property_read_u32(child, "reg", &num)) { - dev_err(&client->dev, "missing reg property of %s\n", - child->name); - goto put_child; - } - - if (num >= 2) { - dev_err(&client->dev, "invalid clkout %d\n", num); - goto put_child; - } - - if (!of_property_read_u32(child, "silabs,drive-strength", - &val)) { - switch (val) { - case SI5324_DRIVE_2MA: - case SI5324_DRIVE_4MA: - case SI5324_DRIVE_6MA: - case SI5324_DRIVE_8MA: - pdata->clkout[num].drive = val; - break; - default: - dev_err(&client->dev, - "invalid drive strength %d for clkout %d\n", - val, num); - goto put_child; - } - } - - if (!of_property_read_u32(child, "silabs,disable-state", - &val)) { - switch (val) { - case 0: - pdata->clkout[num].disable_state = - SI5324_DISABLE_LOW; - break; - case 1: - pdata->clkout[num].disable_state = - SI5324_DISABLE_HIGH; - break; - case 2: - pdata->clkout[num].disable_state = - SI5324_DISABLE_FLOATING; - break; - case 3: - pdata->clkout[num].disable_state = - SI5324_DISABLE_NEVER; - break; - default: - dev_err(&client->dev, - "invalid disable state %d for clkout %d\n", - val, num); - goto put_child; - } - } - - if (!of_property_read_u32(child, "clock-frequency", &val)) { - dev_dbg(&client->dev, "clock-frequency = %u\n", val); - pdata->clkout[num].rate = val; - } - - pdata->clkout[num].pll_master = - of_property_read_bool(child, "silabs,pll-master"); - } - client->dev.platform_data = pdata; - - return 0; -put_child: - of_node_put(child); - return -EINVAL; -} -#else -static int si5324_dt_parse(struct i2c_client *client) -{ - return 0; -} -#endif /* CONFIG_OF */ - -static u8 instance = 0; - -static int si5324_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct si5324_platform_data *pdata; - struct si5324_driver_data *drvdata; - struct clk_init_data init; - struct clk *clk; - const char *parent_names[3]; - char inst_names[NUM_NAME_IDS][MAX_NAME_LEN]; - u8 val; - u8 num_parents, num_clocks; - int ret, n; - enum si53xx_variant variant = id->driver_data; - - if (variant > si5328) { - dev_err(&client->dev, "si53xx device tree entry do not indicate \ - presence of Si5319 or Si5324 or Si5328.\n"); - return -ENODEV; - } - - dev_info(&client->dev, "%s probed\n", si53xx_variant_name[variant]); - ret = si5324_dt_parse(client); - if (ret) - return ret; - - pdata = client->dev.platform_data; - if (!pdata) - return -EINVAL; - - drvdata = devm_kzalloc(&client->dev, sizeof(*drvdata), GFP_KERNEL); - if (drvdata == NULL) { - dev_err(&client->dev, "unable to allocate driver data\n"); - return -ENOMEM; - } - - drvdata->client = client; - drvdata->pxtal = devm_clk_get(&client->dev, "xtal"); - drvdata->pclkin1 = devm_clk_get(&client->dev, "clkin1"); - drvdata->pclkin2 = devm_clk_get(&client->dev, "clkin2"); - - if (PTR_ERR(drvdata->pxtal) == -EPROBE_DEFER || - PTR_ERR(drvdata->pclkin1) == -EPROBE_DEFER || - PTR_ERR(drvdata->pclkin2) == -EPROBE_DEFER) - return -EPROBE_DEFER; - - drvdata->regmap = devm_regmap_init_i2c(client, &si5324_regmap_config); - if (IS_ERR(drvdata->regmap)) { - dev_err(&client->dev, "failed to allocate register map\n"); - return PTR_ERR(drvdata->regmap); - } - - i2c_set_clientdata(client, drvdata); - si5324_initialize(drvdata); - -#if (!defined(FORCE_BYPASS) || !FORCE_BYPASS) - /* setup input clock configuration */ - ret = _si5324_pll_reparent(drvdata, 0, pdata->pll_src); - if (ret) { - dev_err(&client->dev, - "failed to reparent pll to %d\n", - pdata->pll_src); - return ret; - } -#endif - - for (n = 0; n < 2; n++) { - - ret = _si5324_clkout_set_drive_strength(drvdata, n, - pdata->clkout[n].drive); - if (ret) { - dev_err(&client->dev, - "failed set drive strength of clkout%d to %d\n", - n, pdata->clkout[n].drive); - return ret; - } - - ret = _si5324_clkout_set_disable_state(drvdata, n, - pdata->clkout[n].disable_state); - if (ret) { - dev_err(&client->dev, - "failed set disable state of clkout%d to %d\n", - n, pdata->clkout[n].disable_state); - return ret; - } - } - - if (!IS_ERR(drvdata->pxtal)) { - si5324_dbg("Enabling xtal clock\n"); - clk_prepare_enable(drvdata->pxtal); - } - if (!IS_ERR(drvdata->pclkin1)) - clk_prepare_enable(drvdata->pclkin1); - if (!IS_ERR(drvdata->pclkin2)) - clk_prepare_enable(drvdata->pclkin2); - - /* create instance names by appending instance id */ - for (n = 0; n < 3; n++) { //clk_in - sprintf(inst_names[n], "%s_%d", si5324_input_names[n], instance); - } - sprintf(inst_names[3], "%s_%d", si5324_pll_name, instance); //pll - for (n = 0; n < 2; n++) { //clkout - sprintf(inst_names[n+4], "%s_%d", si5324_clkout_names[n], instance); - } - - /* register xtal input clock gate */ - memset(&init, 0, sizeof(init)); - init.name = inst_names[0]; - init.ops = &si5324_xtal_ops; - init.flags = 0; - if (!IS_ERR(drvdata->pxtal)) { - drvdata->pxtal_name = __clk_get_name(drvdata->pxtal); - init.parent_names = &drvdata->pxtal_name; - si5324_dbg("xtal parent name: %s\n", init.parent_names[0]); - init.num_parents = 1; - } - drvdata->xtal.init = &init; - clk = devm_clk_register(&client->dev, &drvdata->xtal); - if (IS_ERR(clk)) { - dev_err(&client->dev, "unable to register %s\n", init.name); - ret = PTR_ERR(clk); - goto err_clk; - } - - /* register clkin1 input clock gate */ - memset(&init, 0, sizeof(init)); - init.name = inst_names[1]; - init.ops = &si5324_clkin_ops; - if (!IS_ERR(drvdata->pclkin1)) { - drvdata->pclkin1_name = __clk_get_name(drvdata->pclkin1); - init.parent_names = &drvdata->pclkin1_name; - init.num_parents = 1; - } - drvdata->clkin1.init = &init; - clk = devm_clk_register(&client->dev, &drvdata->clkin1); - if (IS_ERR(clk)) { - dev_err(&client->dev, "unable to register %s\n", - init.name); - ret = PTR_ERR(clk); - goto err_clk; - } - - /* register clkin2 input clock gate */ - memset(&init, 0, sizeof(init)); - init.name = inst_names[2]; - init.ops = &si5324_clkin_ops; - if (!IS_ERR(drvdata->pclkin2)) { - drvdata->pclkin2_name = __clk_get_name(drvdata->pclkin2); - init.parent_names = &drvdata->pclkin2_name; - init.num_parents = 1; - } - drvdata->clkin2.init = &init; - clk = devm_clk_register(&client->dev, &drvdata->clkin2); - if (IS_ERR(clk)) { - dev_err(&client->dev, "unable to register %s\n", - init.name); - ret = PTR_ERR(clk); - goto err_clk; - } - - /* Si5324 allows to mux xtal or clkin1 or clkin2 to PLL input */ - num_parents = 3; - parent_names[0] = inst_names[0]; - parent_names[1] = inst_names[1]; - parent_names[2] = inst_names[2]; - - /* register PLL */ - drvdata->pll.num = 0; - drvdata->pll.drvdata = drvdata; - drvdata->pll.hw.init = &init; - memset(&init, 0, sizeof(init)); - init.name = inst_names[3]; - init.ops = &si5324_pll_ops; - init.flags = 0; - init.flags |= CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE; - init.parent_names = parent_names; - init.num_parents = num_parents; - clk = devm_clk_register(&client->dev, &drvdata->pll.hw); - if (IS_ERR(clk)) { - dev_err(&client->dev, "unable to register %s\n", init.name); - ret = PTR_ERR(clk); - goto err_clk; - } - - /* register clk multisync and clk out divider */ - num_clocks = 2; - num_parents = 1; - parent_names[0] = inst_names[3]; - - drvdata->clkout = devm_kzalloc(&client->dev, num_clocks * - sizeof(*drvdata->clkout), GFP_KERNEL); - - drvdata->onecell.clk_num = num_clocks; - drvdata->onecell.clks = devm_kzalloc(&client->dev, - num_clocks * sizeof(*drvdata->onecell.clks), GFP_KERNEL); - - if (WARN_ON(!drvdata->clkout) || (!drvdata->onecell.clks)) { - ret = -ENOMEM; - goto err_clk; - } - - for (n = 0; n < num_clocks; n++) { - drvdata->clkout[n].num = n; - drvdata->clkout[n].drvdata = drvdata; - drvdata->clkout[n].hw.init = &init; - memset(&init, 0, sizeof(init)); - init.name = inst_names[4+n]; - init.ops = &si5324_clkout_ops; - init.flags = 0; - init.flags |= CLK_SET_RATE_PARENT; - init.parent_names = parent_names; - init.num_parents = num_parents; - clk = devm_clk_register(&client->dev, &drvdata->clkout[n].hw); - if (IS_ERR(clk)) { - dev_err(&client->dev, "unable to register %s\n", - init.name); - ret = PTR_ERR(clk); - goto err_clk; - } - /* refer to output clock in onecell */ - drvdata->onecell.clks[n] = clk; - - /* set initial clkout rate */ - if (pdata->clkout[n].rate != 0) { - int ret; - si5324_dbg("Initializing clkout%d for DT specified frequency %d Hz.\n", n, pdata->clkout[n].rate); - ret = clk_set_rate(clk, pdata->clkout[n].rate); - if (ret != 0) { - dev_err(&client->dev, "Cannot set rate : %d\n", - ret); - } - } - } - - ret = of_clk_add_provider(client->dev.of_node, of_clk_src_onecell_get, - &drvdata->onecell); - if (ret) { - dev_err(&client->dev, "unable to add clk provider\n"); - goto err_clk; - } - - dev_info(&client->dev, "%s probe successful\n", si53xx_variant_name[variant]); - instance++; - return 0; - -err_clk: - if (!IS_ERR(drvdata->pxtal)) - clk_disable_unprepare(drvdata->pxtal); - if (!IS_ERR(drvdata->pclkin1)) - clk_disable_unprepare(drvdata->pclkin1); - if (!IS_ERR(drvdata->pclkin2)) - clk_disable_unprepare(drvdata->pclkin2); - return ret; -} - -static const struct i2c_device_id si5324_i2c_ids[] = { - { "si5319", si5319 }, - { "si5324", si5324 }, - { "si5328", si5328 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, si5324_i2c_ids); - -static struct i2c_driver si5324_driver = { - .driver = { - .name = "si5324", - .of_match_table = of_match_ptr(si5324_dt_ids), - }, - .probe = si5324_i2c_probe, - .id_table = si5324_i2c_ids, -}; -module_i2c_driver(si5324_driver); - -MODULE_AUTHOR("Leon Woestenberg "); -MODULE_DESCRIPTION("Silicon Labs Si5324 jitter attenuating clock multiplier driver"); -MODULE_LICENSE("GPL"); diff --git a/clk/clk-si5324.h b/clk/clk-si5324.h deleted file mode 100644 index 9e57495..0000000 --- a/clk/clk-si5324.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * clk-si5324.h: Silicon Laboratories Si5324A/B/C I2C Clock Generator - * - * Leon Woestenberg - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#ifndef _CLK_SI5324_H_ -#define _CLK_SI5324_H_ - -#define SI5324_BUS_BASE_ADDR 0x68 - -#define SI5324_REG0 0 -#define SI5324_REG0_FREE_RUN (1<<6) - -#define SI5324_CKSEL 3 - -#define SI5324_DSBL_CLKOUT 10 - -#define SI5324_POWERDOWN 11 -#define SI5324_PD_CK1 (1<<0) -#define SI5324_PD_CK2 (1<<1) - -/* output clock dividers */ -#define SI5324_N1_HS_OUTPUT_DIVIDER 25 -#define SI5324_NC1_LS_H 31 -#define SI5324_NC1_LS_M 32 -#define SI5324_NC1_LS_L 33 - -#define SI5324_NC2_LS_H 34 -#define SI5324_NC2_LS_M 35 -#define SI5324_NC2_LS_L 36 - -#define SI5324_RESET 136 -#define SI5324_RST_REG (1<<7) - -/* selects 2kHz to 710 MHz */ -#define SI5324_CLKIN_MIN_FREQ 2000 -#define SI5324_CLKIN_MAX_FREQ (710 * 1000 * 1000) - - -/* generates 2kHz to 945 MHz */ -#define SI5324_CLKOUT_MIN_FREQ 2000 -#define SI5324_CLKOUT_MAX_FREQ (945 * 1000 * 1000) - -/** - * The following constants define the limits of the divider settings. - */ -#define SI5324_N1_HS_MIN 6 /**< Minimum N1_HS setting (4 and 5 are for higher output frequencies than we support */ -#define SI5324_N1_HS_MAX 11 /**< Maximum N1_HS setting */ -#define SI5324_NC_LS_MIN 1 /**< Minimum NCn_LS setting (1 and even values) */ -#define SI5324_NC_LS_MAX 0x100000 /**< Maximum NCn_LS setting (1 and even values) */ -#define SI5324_N2_HS_MIN 4 /**< Minimum NC2_HS setting */ -#define SI5324_N2_HS_MAX 11 /**< Maximum NC2_HS setting */ -#define SI5324_N2_LS_MIN 2 /**< Minimum NC2_LS setting (even values only) */ -#define SI5324_N2_LS_MAX 0x100000 /**< Maximum NC2_LS setting (even values only) */ -#define SI5324_N3_MIN 1 /**< Minimum N3n setting */ -#define SI5324_N3_MAX 0x080000 /**< Maximum N3n setting */ - -#endif diff --git a/clk/include/si5324.h b/clk/include/si5324.h deleted file mode 100644 index 95d6ef5..0000000 --- a/clk/include/si5324.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Si5324A/B/C programmable clock generator platform_data. - */ - -#ifndef __LINUX_PLATFORM_DATA_SI5324_H__ -#define __LINUX_PLATFORM_DATA_SI5324_H__ - -/** - * enum si5324_pll_src - Si5324 pll clock source - * @SI5324_PLL_SRC_DEFAULT: default, do not change eeprom config - * @SI5324_PLL_SRC_XTAL: pll source clock is XTAL input - * @SI5324_PLL_SRC_CLKIN1: pll source clock is CLKIN1 input - * @SI5324_PLL_SRC_CLKIN2: pll source clock is CLKIN2 input - */ -enum si5324_pll_src { - SI5324_PLL_SRC_XTAL = 0, - SI5324_PLL_SRC_CLKIN1 = 1, - SI5324_PLL_SRC_CLKIN2 = 2, -}; - -/** - * enum si5324_drive_strength - Si5324 clock output drive strength - * @SI5324_DRIVE_DEFAULT: default, do not change eeprom config - * @SI5324_DRIVE_2MA: 2mA clock output drive strength - * @SI5324_DRIVE_4MA: 4mA clock output drive strength - * @SI5324_DRIVE_6MA: 6mA clock output drive strength - * @SI5324_DRIVE_8MA: 8mA clock output drive strength - */ -enum si5324_drive_strength { - SI5324_DRIVE_DEFAULT = 0, - SI5324_DRIVE_2MA = 2, - SI5324_DRIVE_4MA = 4, - SI5324_DRIVE_6MA = 6, - SI5324_DRIVE_8MA = 8, -}; - -/** - * enum si5324_disable_state - Si5324 clock output disable state - * @SI5324_DISABLE_DEFAULT: default, do not change eeprom config - * @SI5324_DISABLE_LOW: CLKx is set to a LOW state when disabled - * @SI5324_DISABLE_HIGH: CLKx is set to a HIGH state when disabled - * @SI5324_DISABLE_FLOATING: CLKx is set to a FLOATING state when - * disabled - * @SI5324_DISABLE_NEVER: CLKx is NEVER disabled - */ -enum si5324_disable_state { - SI5324_DISABLE_DEFAULT = 0, - SI5324_DISABLE_LOW, - SI5324_DISABLE_HIGH, - SI5324_DISABLE_FLOATING, - SI5324_DISABLE_NEVER, -}; - -/** - * struct si5324_clkout_config - Si5324 clock output configuration - * @clkout: clkout number - * @multisynth_src: multisynth source clock - * @clkout_src: clkout source clock - * @pll_master: if true, clkout can also change pll rate - * @drive: output drive strength - * @rate: initial clkout rate, or default if 0 - */ -struct si5324_clkout_config { - enum si5324_drive_strength drive; - enum si5324_disable_state disable_state; - bool pll_master; - unsigned long rate; -}; - -/** - * struct si5324_platform_data - Platform data for the Si5324 clock driver - * @clk_xtal: xtal input clock - * @clk_clkin: clkin input clock - * @pll_src: pll source clock setting - * @clkout: array of clkout configuration - */ -struct si5324_platform_data { - enum si5324_pll_src pll_src; - struct si5324_clkout_config clkout[2]; -}; - -#endif diff --git a/clk/si5324drv.c b/clk/si5324drv.c deleted file mode 100644 index 9e2a519..0000000 --- a/clk/si5324drv.c +++ /dev/null @@ -1,380 +0,0 @@ -#include -#include - -#include "si5324drv.h" - -#define xil_printf(format, ...) printk(KERN_INFO format, ## __VA_ARGS__) - -/*****************************************************************************/ -/** - * Find the closest rational approximation for the N2_LS/N3 fraction. - * - * @param f Holds the N2_LS/N3 fraction in 36.28 fixed point notation. - * @param md Holds the maximum denominator (N3) value allowed. - * @param num Will store the numinator (N2_LS) found. - * @param denom Will store the denominator (N3) found. - */ -void Si5324_RatApprox(u64 f, u64 md, u32 *num, u32 *denom) -{ - /* a: Continued fraction coefficients. */ - u64 a, h[3] = { 0, 1, 0 }, k[3] = { 1, 0, 0 }; - u64 x, d, n = 1; - int i = 0; - - // Degenerate case: only n/1 solution allowed. Return trunc(f)/1. - if (md <= 1) { - *denom = 1; - *num = (u32)(f >> 28); - return; - } - - // Multiply fraction until there are no more digits after the decimal point - n <<= 28; - for (i = 0; i < 28; i++) { - if ((f & 0x1) == 0) { - n >>= 1; - f >>= 1; - } else { - break; - } - } - d = f; - - /* Continued fraction and check denominator each step */ - for (i = 0; i < 64; i++) { - a = n ? d / n : 0; - if (i && !a) { - break; - } - - x = d; - d = n; - n = x % n; - - x = a; - if (k[1] * a + k[0] >= md) { - x = (md - k[0]) / k[1]; - if (x * 2 >= a || k[1] >= md) { - i = 65; - } else { - break; - } - } - - h[2] = x * h[1] + h[0]; - h[0] = h[1]; - h[1] = h[2]; - k[2] = x * k[1] + k[0]; - k[0] = k[1]; - k[1] = k[2]; - } - *denom = (u32)k[1]; - *num = (u32)h[1]; -} - - -/*****************************************************************************/ -/** - * Search through the possible settings for the N2_LS parameter. Finds the best - * setting for N2_LS and N3n with the values for N1_HS, NCn_LS, and N2_HS - * already set in settings. - * - * @param settings Holds the settings up till now. - * @return 1 when the best possible result has been found. - * @note Private function. - */ -int Si5324_FindN2ls(si5324_settings_t *settings) { - u32 result = 0; - u64 f3_actual; - u64 fosc_actual; - u64 fout_actual; - u64 delta_fout; - u64 n2_ls_div_n3; - u32 mult; - - n2_ls_div_n3 = settings->fosc / (settings->fin >> 28) / settings->n2_hs / 2; - Si5324_RatApprox(n2_ls_div_n3, settings->n31_max, &(settings->n2_ls), &(settings->n31)); - settings->n2_ls *= 2; - // Rational approximation returns the smalles ratio possible. Upscaling - // might be needed when when one or both of the numbers are too low. - if (settings->n2_ls < settings->n2_ls_min) { - mult = settings->n2_ls_min / settings->n2_ls; - mult = (settings->n2_ls_min % settings->n2_ls) ? mult + 1 : mult; - settings->n2_ls *= mult; - settings->n31 *= mult; - } - if (settings->n31 < settings->n31_min) { - mult = settings->n31_min / settings->n31; - mult = (settings->n31_min % settings->n31) ? mult + 1 : mult; - settings->n2_ls *= mult; - settings->n31 *= mult; - } - if (SI5324_DEBUG) { - printk(KERN_INFO "Trying N2_LS = %d N3 = %d.\n", - settings->n2_ls, settings->n31); - } - // Check if N2_LS and N3 are within the required ranges - if ((settings->n2_ls < settings->n2_ls_min) || (settings->n2_ls > settings->n2_ls_max)) { - printk(KERN_INFO "N2_LS out of range.\n"); - } else if ((settings->n31 < settings->n31_min) || (settings->n31 > settings->n31_max)) { - printk(KERN_INFO "N3 out of range.\n"); - } - else { - // N2_LS and N3 values within range: check actual output frequency - f3_actual = settings->fin / settings->n31; - fosc_actual = f3_actual * settings->n2_hs * settings->n2_ls; - fout_actual = fosc_actual / (settings->n1_hs * settings->nc1_ls); - delta_fout = fout_actual - settings->fout; - // Check actual frequencies for validity - if ((f3_actual < ((u64)SI5324_F3_MIN) << 28) || (f3_actual > ((u64)SI5324_F3_MAX) << 28)) { - if (SI5324_DEBUG) { - printk(KERN_INFO "F3 frequency out of range.\n"); - } - } else if ((fosc_actual < ((u64)SI5324_FOSC_MIN) << 28) || (fosc_actual > ((u64)SI5324_FOSC_MAX) << 28)) { - if (SI5324_DEBUG) { - printk(KERN_INFO "Fosc frequency out of range.\n"); - } - } else if ((fout_actual < ((u64)SI5324_FOUT_MIN) << 28) || (fout_actual >((u64)SI5324_FOUT_MAX) << 28)) { - if (SI5324_DEBUG) { - printk(KERN_INFO "Fout frequency out of range.\n"); - } - } else { - if (SI5324_DEBUG) { - printk(KERN_INFO "Found solution: fout = %dHz delta = %dHz.\n", - (u32)(fout_actual >> 28), (u32)(delta_fout >> 28)); - printk(KERN_INFO " fosc = %dkHz f3 = %dHz.\n", - (u32)((fosc_actual >> 28) / 1000), (u32)(f3_actual >> 28)); - } - if (((u64)llabs(delta_fout)) < settings->best_delta_fout) { - // Found a better solution: remember this one! - if (SI5324_DEBUG) { - printk(KERN_INFO "This solution is the best yet!\n"); - } - settings->best_n1_hs = settings->n1_hs; - settings->best_nc1_ls = settings->nc1_ls; - settings->best_n2_hs = settings->n2_hs; - settings->best_n2_ls = settings->n2_ls; - settings->best_n3 = settings->n31; - settings->best_fout = fout_actual; - settings->best_delta_fout = llabs(delta_fout); - if (delta_fout == 0) { - // Best possible result found. Skip the rest of the possibilities. - result = 1; - } - } - } - } - return result; -} - - -/*****************************************************************************/ -/** - * Find a valid setting for N2_HS and N2_LS. Finds the best - * setting for N2_HS, N2_LS, and N3n with the values for N1_HS, and NCn_LS - * already set in settings. Iterates over all possibilities - * of N2_HS and then performs a binary search over the N2_LS values. - * - * @param settings Holds the settings up till now. - * @return 1 when the best possible result has been found. - * @note Private function. - */ -int Si5324_FindN2(si5324_settings_t *settings) { - u32 result; - - for (settings->n2_hs = SI5324_N2_HS_MAX; settings->n2_hs >= SI5324_N2_HS_MIN; settings->n2_hs--) { - if (SI5324_DEBUG) { - printk(KERN_INFO "Trying N2_HS = %d.\n", settings->n2_hs); - } - settings->n2_ls_min = (u32)(settings->fosc / ((u64)(SI5324_F3_MAX * settings->n2_hs) << 28)); - if (settings->n2_ls_min < SI5324_N2_LS_MIN) { - settings->n2_ls_min = SI5324_N2_LS_MIN; - } - settings->n2_ls_max = (u32)(settings->fosc / ((u64)(SI5324_F3_MIN * settings->n2_hs) << 28)); - if (settings->n2_ls_max > SI5324_N2_LS_MAX) { - settings->n2_ls_max = SI5324_N2_LS_MAX; - } - result = Si5324_FindN2ls(settings); - if (result) { - // Best possible result found. Skip the rest of the possibilities. - break; - } - } - return result; -} - - -/*****************************************************************************/ -/** - * Calculates the valid range for NCn_LS with the value for the output - * frequency and N1_HS already set in settings. - * - * @param settings Holds the input and output frequencies and the setting - * for N1_HS. - * @return -1 when there are no valid settings for NCn_LS, 0 otherwise. - * @note Private function. - */ -int Si5324_CalcNclsLimits(si5324_settings_t *settings) { - // Calculate limits for NCn_LS - settings->nc1_ls_min = settings->n1_hs_min / settings->n1_hs; - if (settings->nc1_ls_min < SI5324_NC_LS_MIN) { - settings->nc1_ls_min = SI5324_NC_LS_MIN; - } - // Make sure NC_ls_min is one or even - if ((settings->nc1_ls_min > 1) && ((settings->nc1_ls_min & 0x1) == 1)) { - settings->nc1_ls_min++; - } - settings->nc1_ls_max = settings->n1_hs_max / settings->n1_hs; - if (settings->nc1_ls_max > SI5324_NC_LS_MAX) { - settings->nc1_ls_max = SI5324_NC_LS_MAX; - } - // Make sure NC_ls_max is even - if ((settings->nc1_ls_max & 0x1) == 1) { - settings->nc1_ls_max--; - } - // Check if actual N1 is within limits - if ((settings->nc1_ls_max * settings->n1_hs < settings->n1_hs_min) || - (settings->nc1_ls_min * settings->n1_hs > settings->n1_hs_max)) { - // No valid NC_ls possible: take next N1_hs - return -1; - } - return 0; -} - - -/*****************************************************************************/ -/** - * Find a valid setting for NCn_LS that can deliver the correct output - * frequency. Assumes that the valid range is relatively small so a full search - * can be done (should be true for video clock frequencies). - * - * @param settings Holds the input and output frequencies, the setting for - * N1_HS, and the limits for NCn_LS. - * @return 1 when the best possible result has been found. - * @note Private function. - */ -int Si5324_FindNcls(si5324_settings_t *settings) { - u64 fosc_1; - u32 result; - - fosc_1 = settings->fout * settings->n1_hs; - for (settings->nc1_ls = settings->nc1_ls_min; settings->nc1_ls <= settings->nc1_ls_max;) { - settings->fosc = fosc_1 * settings->nc1_ls; - if (SI5324_DEBUG) { - printk(KERN_INFO "Trying NCn_LS = %d: fosc = %dkHz.\n", - settings->nc1_ls, (u32)((settings->fosc >> 28) / 1000)); - } - result = Si5324_FindN2(settings); - if (result) { - // Best possible result found. Skip the rest of the possibilities. - break; - } - if (settings->nc1_ls == 1) { - settings->nc1_ls++; - } else { - settings->nc1_ls += 2; - } - } - return result; -} - -/*****************************************************************************/ -/** - * Calculate the frequency settings for the desired output frequency. - * - * @param ClkInFreq contains the frequency of the input clock. - * @param ClkOutFreq contains the desired output clock frequency. - * @param N1_hs will be set to the value for the N1_HS register. - * @param NCn_ls will be set to the value for the NCn_LS register. - * @param N2_hs will be set to the value for the N2_HS register. - * @param N2_ls will be set to the value for the N2_LS register. - * @param N3n will be set to the value for the N3n register. - * @param BwSel will be set to the value for the BW_SEL register. - * - * @return SI5324_SUCCESS for success, SI5324_ERR_FREQ when the requested - * frequency cannot be generated. - * @note Private function. - *****************************************************************************/ -int Si5324_CalcFreqSettings(u32 ClkInFreq, u32 ClkOutFreq, u32 *ClkActual, - u8 *N1_hs, u32 *NCn_ls, - u8 *N2_hs, u32 *N2_ls, - u32 *N3n, u8 *BwSel) { - /* TBD */ - si5324_settings_t settings; - int result; - - settings.fin = (u64)ClkInFreq << 28; // 32.28 fixed point - settings.fout= (u64)ClkOutFreq << 28; // 32.28 fixed point - settings.best_delta_fout = settings.fout; // High frequency error to start with - - // Calculate some limits for N1_HS * NCn_LS and for N3 base on the input - // and output frequencies. - settings.n1_hs_min = (int)(SI5324_FOSC_MIN / ClkOutFreq); - if (settings.n1_hs_min < SI5324_N1_HS_MIN * SI5324_NC_LS_MIN) { - settings.n1_hs_min = SI5324_N1_HS_MIN * SI5324_NC_LS_MIN; - } - settings.n1_hs_max = (int)(SI5324_FOSC_MAX / ClkOutFreq); - if (settings.n1_hs_max > SI5324_N1_HS_MAX * SI5324_NC_LS_MAX) { - settings.n1_hs_max = SI5324_N1_HS_MAX * SI5324_NC_LS_MAX; - } - settings.n31_min = ClkInFreq / SI5324_F3_MAX; - if (settings.n31_min < SI5324_N3_MIN) { - settings.n31_min = SI5324_N3_MIN; - } - settings.n31_max = ClkInFreq / SI5324_F3_MIN; - if (settings.n31_max > SI5324_N3_MAX) { - settings.n31_max = SI5324_N3_MAX; - } - // Find a valid oscillator frequency with the highest setting of N1_HS - // possible (reduces power) - for (settings.n1_hs = SI5324_N1_HS_MAX; settings.n1_hs >= SI5324_N1_HS_MIN; settings.n1_hs--) { - if (SI5324_DEBUG) { - printk(KERN_INFO "Trying N1_HS = %d.\n", settings.n1_hs); - } - result = Si5324_CalcNclsLimits(&settings); - if (result) { - if (SI5324_DEBUG) { - printk(KERN_INFO "No valid settings for NCn_LS.\n"); - } - continue; - } - result = Si5324_FindNcls(&settings); - if (result) { - // Best possible result found. Skip the rest of the possibilities. - break; - } - } - - if(SI5324_DEBUG) { - printk(KERN_INFO "Si5324: settings.best_delta_fout = %llu\n", (unsigned long long)settings.best_delta_fout); - printk(KERN_INFO "Si5324: settings.fout = %llu\n", (unsigned long long)settings.fout); - } - - if (settings.best_delta_fout == settings.fout) { - if (1 || SI5324_DEBUG) { - printk(KERN_INFO "Si5324: ERROR: No valid settings found."); - } - return SI5324_ERR_FREQ; - } - if (SI5324_DEBUG) { - printk(KERN_INFO "Si5324: Found solution: fout = %dHz.\n", - (u32)(settings.best_fout >> 28)); - } - - // Post processing: convert temporary values to actual register settings - *N1_hs = (u8)settings.best_n1_hs - 4; - *NCn_ls = settings.best_nc1_ls - 1; - *N2_hs = (u8)settings.best_n2_hs - 4; - *N2_ls = settings.best_n2_ls - 1; - *N3n = settings.best_n3 - 1; - /* How must the bandwidth selection be determined? Not all settings will - * be valid. - refclk 2, 0xA2, // BWSEL_REG=1010 (?) - free running 2, 0x42, // BWSEL_REG=0100 (?) - */ - *BwSel = 6; //4 - - if (ClkActual) *ClkActual = (settings.best_fout >> 28); - return SI5324_SUCCESS; - -} diff --git a/clk/si5324drv.h b/clk/si5324drv.h deleted file mode 100644 index dccc7df..0000000 --- a/clk/si5324drv.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2014 Xilinx, Inc. All rights reserved. - * - * Xilinx, Inc. - * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A - * COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS - * ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR - * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION - * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE - * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION. - * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO - * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO - * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE - * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. - * - */ - -/*****************************************************************************/ -/** -* -* @file si5324drv.h -* -* This file contains definitions for low-level driver functions for -* controlling the SiliconLabs Si5324 clock generator as mounted on the KC705 -* demo board. -* The user should refer to the hardware device specification for more details -* of the device operation. -* -*
-* MODIFICATION HISTORY:
-*
-* Ver   Who  Date        Changes
-* ----- --- ----------   -----------------------------------------------
-* 1.00  hf  2014/10/10   First release
-* 
-* -******************************************************************************/ - -#ifndef SI5324DRV_H_ -#define SI5324DRV_H_ - -#include - - -/****************************************************************************** - * User settable defines that depend on the specific board design. - * The defaults are for the Xilinx KC705 board. - *****************************************************************************/ - -/** - * The frequency of the crystal connected to the XA/XB pins of the Si5324 in Hz. - */ -#define SI5324_XTAL_FREQ 114285000 - - -/****************************************************************************** - * Defines independent on the specific board design. Should not be changed. - *****************************************************************************/ - -/** - * Debug output enable. Set to TRUE to enable debug prints, - * to FALSE to disable debug prints. - */ -#define SI5324_DEBUG FALSE - -/** - * The following constants are error codes generated by the functions in - * this driver. - */ -#define SI5324_SUCCESS 0 /**< Operation was successful */ -#define SI5324_ERR_IIC -1 /**< IIC error occurred */ -#define SI5324_ERR_FREQ -2 /**< Could not calculate frequency setting */ -#define SI5324_ERR_PARM -3 /**< Invalid parameter */ - -/** - * The following constants define the clock input select values. - */ -#define SI5324_CLKSRC_CLK1 1 /**< Use clock input 1 */ -#define SI5324_CLKSRC_CLK2 2 /**< Use clock input 2 */ -#define SI5324_CLKSRC_XTAL 3 /**< Use crystal (free running mode) */ - -/** - * The following constants define the limits of the Si5324 frequencies. - */ -#define SI5324_FOSC_MIN 4850000000 /**< Minimum oscillator frequency */ -#define SI5324_FOSC_MAX 5670000000 /**< Maximum oscillator frequency */ -#define SI5324_F3_MIN 10000 // 2000 /**< Minimum phase detector frequency */ -#define SI5324_F3_MAX 2000000 /**< Maximum phase detector frequency */ -#define SI5324_FIN_MIN 2000 /**< Minimum input frequency */ -#define SI5324_FIN_MAX 710000000 /**< Maximum input frequency */ -#define SI5324_FOUT_MIN 2000 /**< Minimum output frequency */ -#define SI5324_FOUT_MAX 945000000 /**< Maximum output frequency */ - -/** - * The following constants define the limits of the divider settings. - */ -#define SI5324_N1_HS_MIN 6 /**< Minimum N1_HS setting (4 and 5 are for higher output frequencies than we support */ -#define SI5324_N1_HS_MAX 11 /**< Maximum N1_HS setting */ -#define SI5324_NC_LS_MIN 1 /**< Minimum NCn_LS setting (1 and even values) */ -#define SI5324_NC_LS_MAX 0x100000 /**< Maximum NCn_LS setting (1 and even values) */ -#define SI5324_N2_HS_MIN 4 /**< Minimum NC2_HS setting */ -#define SI5324_N2_HS_MAX 11 /**< Maximum NC2_HS setting */ -#define SI5324_N2_LS_MIN 2 /**< Minimum NC2_LS setting (even values only) */ -#define SI5324_N2_LS_MAX 0x100000 /**< Maximum NC2_LS setting (even values only) */ -#define SI5324_N3_MIN 1 /**< Minimum N3n setting */ -#define SI5324_N3_MAX 0x080000 /**< Maximum N3n setting */ - - -typedef struct { - // Current Si5342 parameters - - /* high-speed output divider */ - u32 n1_hs_min; - u32 n1_hs_max; - u32 n1_hs; - - /* low-speed output divider for clkout1 */ - u32 nc1_ls_min; - u32 nc1_ls_max; - u32 nc1_ls; - - /* low-speed output divider for clkout2 */ - u32 nc2_ls_min; - u32 nc2_ls_max; - u32 nc2_ls; - - /* high-speed feedback divider (PLL multiplier) */ - u32 n2_hs; - /* low-speed feedback divider (PLL multiplier) */ - u32 n2_ls_min; - u32 n2_ls_max; - u32 n2_ls; - - /* input divider for clk1 */ - u32 n31_min; - u32 n31_max; - u32 n31; - - // Current frequencies (fixed point 36.28 notation) - u64 fin; - u64 fout; - u64 fosc; - // Best settings found - u64 best_delta_fout; - u64 best_fout; - u32 best_n1_hs; - u32 best_nc1_ls; - u32 best_n2_hs; - u32 best_n2_ls; - u32 best_n3; -} si5324_settings_t; - -int Si5324_CalcFreqSettings(u32 ClkInFreq, u32 ClkOutFreq, u32 *ClkActual, - u8 *N1_hs, u32 *NCn_ls, - u8 *N2_hs, u32 *N2_ls, - u32 *N3n, u8 *BwSel); - -#endif /* SI5324DRV_H_ */ From 47bff520ed9daade96c194db7f4fd69c57542b3d Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Sat, 13 Oct 2018 08:15:10 +0800 Subject: [PATCH 13/46] hdmitx: Enabling audio in TXstreamupCb Enabling audio in TXstreamupCallback Signed-off-by: Shikhar Mishra --- hdmi/xilinx_drm_hdmi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index f22ee99..2e2b877 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -591,6 +591,12 @@ static void TxStreamUpCallback(void *CallbackRef) if (xhdmi->hdcp_authenticate) { XHdcp_Authenticate(HdmiTxSsPtr); } + + /* Enable Audio */ + if (xhdmi->audio_enabled) { + XV_HdmiTxSs_AudioMute(HdmiTxSsPtr, 0); + } + dev_dbg(xhdmi->dev,"TxStreamUpCallback(): done\n"); } From 67648d720474c2a15f1ce7c68fd390d13256c7bc Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Sat, 13 Oct 2018 08:16:21 +0800 Subject: [PATCH 14/46] hdmirx:dt:bindings: Remove AES audio header parsing logic Removed the AES audio header parsing logic Signed-off-by: Shikhar Mishra --- .../devicetree/bindings/xlnx,v-hdmi-rx-ss.txt | 6 - hdmi/xilinx-hdmirx.c | 11 +- hdmi/xlnx_hdmirx_audio.c | 279 +----------------- hdmi/xlnx_hdmirx_audio.h | 14 - 4 files changed, 7 insertions(+), 303 deletions(-) diff --git a/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt b/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt index ca41cbb..c8192a1 100644 --- a/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt +++ b/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt @@ -54,7 +54,6 @@ Required Properties: - xlnx,audio-enabled: Boolean parameter to convey that design has audio functionality. If present, indicates optional audio core needed for audio usecase is included. - - xlnx,aes_parser: alias to audio channel status extractor block - xlnx,snd-pcm: reference to audio formatter block. Add this if, audio formatter is going to be used for HDMI audio. - ports: Video ports, using the DT bindings defined in ../video-interfaces.txt. @@ -69,10 +68,6 @@ added to the device tree reg = <0x0 0xa0270000 0x0 0x10000>; }; - hdmi_audio_aes_parser_0: hdmi_audio_aes_parser@a00b0000 { - reg = <0x0 0xa00b0000 0x0 0x10000>; - }; - hdmi_input_v_hdmi_rx_ss_0: v_hdmi_rx_ss@a0000000 { compatible = "xlnx,v-hdmi-rx-ss-3.1"; reg = <0x0 0xa0000000 0x0 0x100000>, <0x0 0xa0270000 0x0 0x10000>; @@ -90,7 +85,6 @@ added to the device tree xlnx,include-hdcp-1-4; xlnx,include-hdcp-2-2; xlnx,audio-enabled; - xlnx,aes_parser = <&hdmi_audio_aes_parser_0>; xlnx,snd-pcm = <&audio_ss_0_audio_formatter_0>; ports { #address-cells = <1>; diff --git a/hdmi/xilinx-hdmirx.c b/hdmi/xilinx-hdmirx.c index 6ac9c59..ce89adb 100644 --- a/hdmi/xilinx-hdmirx.c +++ b/hdmi/xilinx-hdmirx.c @@ -1653,15 +1653,6 @@ static int xhdmi_parse_of(struct xhdmi_device *xhdmi, XV_HdmiRxSs_Config *config XHdcp22_Rng_ConfigTable[XPAR_XHDCP22_RNG_NUM_INSTANCES/2 + instance].BaseAddress = RX_HDCP22_RNG_OFFSET; } - if (xhdmi->audio_enabled) { - xhdmi->rx_audio_data->aes_base = hdmirx_parse_aud_dt(dev); - if (!xhdmi->rx_audio_data->aes_base) { - xhdmi->audio_init = false; - dev_err(dev, "audio rx: aes parser not found!\n"); - } - } else { - dev_info(dev, "hdmi rx audio disabled in DT\n"); - } return 0; @@ -2037,7 +2028,7 @@ static int xhdmi_probe(struct platform_device *pdev) /* probe has succeeded for this instance, increment instance index */ instance++; - if (xhdmi->audio_enabled && xhdmi->rx_audio_data->aes_base) { + if (xhdmi->audio_enabled) { ret = hdmirx_register_aud_dev(xhdmi->dev); if (ret < 0) { xhdmi->audio_init = false; diff --git a/hdmi/xlnx_hdmirx_audio.c b/hdmi/xlnx_hdmirx_audio.c index db2bbbe..00284ff 100644 --- a/hdmi/xlnx_hdmirx_audio.c +++ b/hdmi/xlnx_hdmirx_audio.c @@ -22,290 +22,26 @@ #include "xlnx_hdmirx_audio.h" #define XV_AES_ENABLE 0x8 -#define XV_AES_CH_STS_REG1 0x50 -#define XV_AES_CH_STS_REG2 0x54 -/* audio params macros */ -#define PROF_SAMPLERATE_MASK GENMASK(7, 6) -#define PROF_SAMPLERATE_SHIFT 6 -#define PROF_CHANNEL_COUNT_MASK GENMASK(11, 8) -#define PROF_CHANNEL_COUNT_SHIFT 8 -#define PROF_MAX_BITDEPTH_MASK GENMASK(18, 16) -#define PROF_MAX_BITDEPTH_SHIFT 16 -#define PROF_BITDEPTH_MASK GENMASK(21, 19) -#define PROF_BITDEPTH_SHIFT 19 - -#define AES_FORMAT_MASK BIT(0) -#define PROF_SAMPLERATE_UNDEFINED 0 -#define PROF_SAMPLERATE_44100 1 -#define PROF_SAMPLERATE_48000 2 -#define PROF_SAMPLERATE_32000 3 -#define PROF_CHANNELS_UNDEFINED 0 -#define PROF_TWO_CHANNELS 8 -#define PROF_STEREO_CHANNELS 2 -#define PROF_MAX_BITDEPTH_UNDEFINED 0 -#define PROF_MAX_BITDEPTH_20 2 -#define PROF_MAX_BITDEPTH_24 4 - -#define CON_SAMPLE_RATE_MASK GENMASK(27, 24) -#define CON_SAMPLE_RATE_SHIFT 24 -#define CON_CHANNEL_COUNT_MASK GENMASK(23, 20) -#define CON_CHANNEL_COUNT_SHIFT 20 -#define CON_MAX_BITDEPTH_MASK BIT(1) -#define CON_BITDEPTH_MASK GENMASK(3, 1) -#define CON_BITDEPTH_SHIFT 0x1 - -#define CON_SAMPLERATE_44100 0 -#define CON_SAMPLERATE_48000 2 -#define CON_SAMPLERATE_32000 3 -/* hdmirx_parse_aud_dt - parse AES node from DT - * @dev: device - * - * Parse the DT entry related to AES IP. This IP AES header - * from incoming audio stream. - * - */ -void __iomem *hdmirx_parse_aud_dt(struct device *dev) -{ - struct device_node *aes_node; - struct resource res; - void __iomem *aes_base; - int rc; - struct device_node *node = dev->of_node; - - /* audio errors are not considered fatal */ - aes_node = of_parse_phandle(node, "xlnx,aes_parser", 0); - if (!aes_node) { - dev_err(dev, "aes parser not found\n"); - aes_base = NULL; - } else { - rc = of_address_to_resource(aes_node, 0, &res); - if (rc) { - dev_err(dev, "aes parser:addr to resource failed\n"); - aes_base = NULL; - } else { - aes_base = devm_ioremap_resource(dev, &res); - if (IS_ERR(aes_base)) { - dev_err(dev, "aes ioremap failed\n"); - aes_base = NULL; - } else - writel(1, aes_base + XV_AES_ENABLE); - } - of_node_put(aes_node); - } - return aes_base; -} - -static struct audio_params *parse_professional_format(u32 reg1_val, - u32 reg2_val) -{ - u32 padded, val; - struct audio_params *params; - - params = kzalloc(sizeof(*params), GFP_KERNEL); - if (!params) - return NULL; - - val = (reg1_val & PROF_SAMPLERATE_MASK) >> PROF_SAMPLERATE_SHIFT; - switch (val) { - case PROF_SAMPLERATE_44100: - params->srate = 44100; - break; - case PROF_SAMPLERATE_48000: - params->srate = 48000; - break; - case PROF_SAMPLERATE_32000: - params->srate = 32000; - break; - case PROF_SAMPLERATE_UNDEFINED: - default: - /* not indicated */ - kfree(params); - return NULL; - } - - val = (reg1_val & PROF_CHANNEL_COUNT_MASK) >> PROF_CHANNEL_COUNT_SHIFT; - switch (val) { - case PROF_CHANNELS_UNDEFINED: - case PROF_STEREO_CHANNELS: - case PROF_TWO_CHANNELS: - params->channels = 2; - break; - default: - /* TODO: handle more channels in future*/ - kfree(params); - return NULL; - } - - val = (reg1_val & PROF_MAX_BITDEPTH_MASK) >> PROF_MAX_BITDEPTH_SHIFT; - switch (val) { - case PROF_MAX_BITDEPTH_UNDEFINED: - case PROF_MAX_BITDEPTH_20: - padded = 0; - break; - case PROF_MAX_BITDEPTH_24: - padded = 4; - break; - default: - /* user defined values are not supported */ - kfree(params); - return NULL; - } - - val = (reg1_val & PROF_BITDEPTH_MASK) >> PROF_BITDEPTH_SHIFT; - switch (val) { - case 1: - params->sig_bits = 16 + padded; - break; - case 2: - params->sig_bits = 18 + padded; - break; - case 4: - params->sig_bits = 19 + padded; - break; - case 5: - params->sig_bits = 20 + padded; - break; - case 6: - params->sig_bits = 17 + padded; - break; - case 0: - default: - kfree(params); - return NULL; - } - - return params; -} - -static struct audio_params *parse_consumer_format(u32 reg1_val, u32 reg2_val) -{ - u32 padded, val; - struct audio_params *params; - - params = kzalloc(sizeof(*params), GFP_KERNEL); - if (!params) - return NULL; - - val = (reg1_val & CON_SAMPLE_RATE_MASK) >> CON_SAMPLE_RATE_SHIFT; - switch (val) { - case CON_SAMPLERATE_44100: - params->srate = 44100; - break; - case CON_SAMPLERATE_48000: - params->srate = 48000; - break; - case CON_SAMPLERATE_32000: - params->srate = 32000; - break; - default: - kfree(params); - return NULL; - } - - val = (reg1_val & CON_CHANNEL_COUNT_MASK) >> CON_CHANNEL_COUNT_SHIFT; - params->channels = val; - - if (reg2_val & CON_MAX_BITDEPTH_MASK) - padded = 4; - else - padded = 0; - - val = (reg2_val & CON_BITDEPTH_MASK) >> CON_BITDEPTH_SHIFT; - switch (val) { - case 1: - params->sig_bits = 16 + padded; - break; - case 2: - params->sig_bits = 18 + padded; - break; - case 4: - params->sig_bits = 19 + padded; - break; - case 5: - params->sig_bits = 20 + padded; - break; - case 6: - params->sig_bits = 17 + padded; - break; - case 0: - default: - kfree(params); - return NULL; - } - - return params; -} /* xlnx_rx_pcm_startup - initialze audio during audio usecase * * This function is called by ALSA framework before audio - * capture begins. This callback initializes audio and extracts - * channel status bits and sets them as constraints + * capture begins. * * Return: 0 on success */ static int xlnx_rx_pcm_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - int rate, err; - u32 reg1_val, reg2_val; - - struct snd_soc_codec *codec = dai->codec; - struct snd_pcm_runtime *rtd = substream->runtime; - struct xlnx_hdmirx_audio_data *adata = hdmirx_get_audio_data(dai->dev); + u32 channels = hdmirx_audio_startup(dai->dev); - if (!adata) + if (!channels) return -EINVAL; - reg1_val = readl(adata->aes_base + XV_AES_CH_STS_REG1); - reg2_val = readl(adata->aes_base + XV_AES_CH_STS_REG2); - if (reg1_val & 0x1) - adata->params = parse_professional_format(reg1_val, reg2_val); - else - adata->params = parse_consumer_format(reg1_val, reg2_val); - - if (!adata->params) - return -EINVAL; - - if (!adata->params->channels) - adata->params->channels = hdmirx_audio_startup(dai->dev); - - dev_info(codec->dev, - "Audio properties: srate %d sig_bits = %d channels = %d\n", - adata->params->srate, adata->params->sig_bits, - adata->params->channels); - - err = snd_pcm_hw_constraint_minmax(rtd, SNDRV_PCM_HW_PARAM_RATE, - adata->params->srate, adata->params->srate); - if (err < 0) { - dev_err(codec->dev, "failed to constrain samplerate to %dHz\n", - adata->params->srate); - return err; - } - - /* During record, after AES bits(8) are removed, pcm is at max 24bits. - * Out of 24 bits, sig_bits represent valid number of audio bits from - * input stream - */ - err = snd_pcm_hw_constraint_msbits(rtd, 0, 24, adata->params->sig_bits); - - if (err < 0) { - dev_err(codec->dev, - "failed to constrain 'bits per sample' %d bits\n", - adata->params->sig_bits); - return err; - } - err = snd_pcm_hw_constraint_minmax(rtd, SNDRV_PCM_HW_PARAM_CHANNELS, - adata->params->channels, - adata->params->channels); - if (err < 0) { - dev_err(codec->dev, - "failed to constrain channel count to %d\n", - adata->params->channels); - return err; - } - + dev_info(dai->dev, + "Detected audio with channel count = %d, starting capture\n", + channels); return 0; } @@ -317,9 +53,6 @@ static int xlnx_rx_pcm_startup(struct snd_pcm_substream *substream, static void xlnx_rx_pcm_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct xlnx_hdmirx_audio_data *adata = hdmirx_get_audio_data(dai->dev); - - kfree(adata->params); hdmirx_audio_shutdown(dai->dev); } diff --git a/hdmi/xlnx_hdmirx_audio.h b/hdmi/xlnx_hdmirx_audio.h index 5986cd3..9ec4df3 100644 --- a/hdmi/xlnx_hdmirx_audio.h +++ b/hdmi/xlnx_hdmirx_audio.h @@ -21,24 +21,10 @@ struct xlnx_hdmirx_audio_data *hdmirx_get_audio_data(struct device *dev); int hdmirx_register_aud_dev(struct device *dev); void hdmirx_unregister_aud_dev(struct device *dev); -void __iomem *hdmirx_parse_aud_dt(struct device *dev); u32 hdmirx_audio_startup(struct device *dev); void hdmirx_audio_shutdown(struct device *dev); -/* - * struct audio_params - audio stream parameters - * @srate: sampling rate - * @sig_bits: significant bits in container - * @channels: number of channels - */ -struct audio_params { - u32 srate; - u32 sig_bits; - u32 channels; -}; - struct xlnx_hdmirx_audio_data { void __iomem *aes_base; - struct audio_params *params; }; #endif /* __XILINX_HDMI_RX_AUD_H__ */ From 1255277d87e30156c129c49298436b8a6c804ec5 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Sat, 13 Oct 2018 08:17:23 +0800 Subject: [PATCH 15/46] hdmirx: Update supported audio formats and sampling rates Update supported audio formats and sampling rates Signed-off-by: Shikhar Mishra --- hdmi/xlnx_hdmirx_audio.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hdmi/xlnx_hdmirx_audio.c b/hdmi/xlnx_hdmirx_audio.c index 00284ff..987dabf 100644 --- a/hdmi/xlnx_hdmirx_audio.c +++ b/hdmi/xlnx_hdmirx_audio.c @@ -68,8 +68,10 @@ static struct snd_soc_dai_driver xlnx_rx_audio_dai = { .channels_min = 2, .channels_max = 8, .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S24_LE, + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | + SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, }, .ops = &xlnx_rx_dai_ops, }; From 6a4d274f9e2b74e58811ffbc64e4019daf0314ae Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Sat, 13 Oct 2018 08:20:48 +0800 Subject: [PATCH 16/46] hdmirx: Start audio capture only if audio is detected through channel count Start audio capture only if audio is detected through channel count Signed-off-by: Shikhar Mishra --- hdmi/xilinx-hdmirx.c | 35 ++++++++++++++++++++++++++--------- hdmi/xlnx_hdmirx_audio.h | 6 ++++++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/hdmi/xilinx-hdmirx.c b/hdmi/xilinx-hdmirx.c index ce89adb..9840e53 100644 --- a/hdmi/xilinx-hdmirx.c +++ b/hdmi/xilinx-hdmirx.c @@ -844,15 +844,19 @@ static void RxAudCallback(void *CallbackRef) { struct xhdmi_device *xhdmi = (struct xhdmi_device *)CallbackRef; XV_HdmiRxSs *HdmiRxSsPtr = &xhdmi->xv_hdmirxss; - XV_HdmiRx_AudioFormatType format; - u8 NumChannels; + struct xlnx_hdmirx_audio_data *adata = xhdmi->rx_audio_data; dev_dbg(xhdmi->dev,"%s()\n", __func__); - format = XV_HdmiRxSs_GetAudioFormat(HdmiRxSsPtr); - NumChannels = XV_HdmiRxSs_GetAudioChannels(HdmiRxSsPtr); + adata->format = XV_HdmiRxSs_GetAudioFormat(HdmiRxSsPtr); + adata->num_channels = XV_HdmiRxSs_GetAudioChannels(HdmiRxSsPtr); //ToDo: Insert registered ALSA driver call-back - dev_dbg(xhdmi->dev, "Channels = %d\n", NumChannels); - dev_dbg(xhdmi->dev, "Format = %d\n", format); + if (xhdmi->audio_init && adata->num_channels >= 2) { + adata->audio_detected = true; + wake_up_interruptible(&adata->audio_update_q); + } + + dev_dbg(xhdmi->dev, "Channels = %d\n", adata->num_channels); + dev_dbg(xhdmi->dev, "Format = %d\n", adata->format); } static void RxAuxCallback(void *CallbackRef) @@ -1675,6 +1679,7 @@ static int xhdmi_probe(struct platform_device *pdev) unsigned long axi_clk_rate; XV_HdmiRxSs *HdmiRxSsPtr; + struct xlnx_hdmirx_audio_data *adata; u32 Status; dev_info(&pdev->dev, "probed\n"); @@ -1688,6 +1693,7 @@ static int xhdmi_probe(struct platform_device *pdev) if (!xhdmi->rx_audio_data) return -ENOMEM; + adata = xhdmi->rx_audio_data; /* store pointer of the real device inside platform device */ xhdmi->dev = &pdev->dev; @@ -2035,6 +2041,7 @@ static int xhdmi_probe(struct platform_device *pdev) dev_err(xhdmi->dev, "hdmi rx audio init failed\n"); } else { xhdmi->audio_init = true; + init_waitqueue_head(&adata->audio_update_q); dev_info(xhdmi->dev, "hdmi rx audio initialized\n"); } } @@ -2116,16 +2123,26 @@ struct xlnx_hdmirx_audio_data *hdmirx_get_audio_data(struct device *dev) u32 hdmirx_audio_startup(struct device *dev) { - u32 channel_count; + int err; + struct xlnx_hdmirx_audio_data *adata; + unsigned long jiffies = msecs_to_jiffies(XHDMI_AUDIO_DETECT_TIMEOUT); struct xhdmi_device *xhdmi = dev_get_drvdata(dev); XV_HdmiRxSs *HdmiRxSsPtr = &xhdmi->xv_hdmirxss; + adata = xhdmi->rx_audio_data; hdmi_mutex_lock(&xhdmi->xhdmi_mutex); XV_HdmiRx_AudioEnable(HdmiRxSsPtr->HdmiRxPtr); - channel_count = XV_HdmiRxSs_GetAudioChannels(HdmiRxSsPtr); hdmi_mutex_unlock(&xhdmi->xhdmi_mutex); - return channel_count; + err = wait_event_interruptible_timeout(adata->audio_update_q, + adata->audio_detected, + jiffies); + if (!err) { + dev_err(dev, "No audio detected in input stream\n"); + return 0; + } + + return adata->num_channels; } void hdmirx_audio_shutdown(struct device *dev) diff --git a/hdmi/xlnx_hdmirx_audio.h b/hdmi/xlnx_hdmirx_audio.h index 9ec4df3..46a2710 100644 --- a/hdmi/xlnx_hdmirx_audio.h +++ b/hdmi/xlnx_hdmirx_audio.h @@ -18,6 +18,8 @@ #ifndef __XILINX_HDMI_RX_AUD_H__ #define __XILINX_HDMI_RX_AUD_H__ +#define XHDMI_AUDIO_DETECT_TIMEOUT 50 + struct xlnx_hdmirx_audio_data *hdmirx_get_audio_data(struct device *dev); int hdmirx_register_aud_dev(struct device *dev); void hdmirx_unregister_aud_dev(struct device *dev); @@ -26,5 +28,9 @@ void hdmirx_audio_shutdown(struct device *dev); struct xlnx_hdmirx_audio_data { void __iomem *aes_base; + bool audio_detected; + wait_queue_head_t audio_update_q; + int format; + u8 num_channels; }; #endif /* __XILINX_HDMI_RX_AUD_H__ */ From 80dbb6c094cf3388c7a68ecee37f90af88cb13d2 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Sat, 13 Oct 2018 08:21:44 +0800 Subject: [PATCH 17/46] hdmirx:hdmitx: Interlace feild 1 calculation fixed Added calculation of feild1 parameters for interlaced resolution Signed-off-by: Shikhar Mishra --- hdmi/xilinx-hdmirx.c | 5 ++- hdmi/xilinx_drm_hdmi.c | 72 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 62 insertions(+), 15 deletions(-) diff --git a/hdmi/xilinx-hdmirx.c b/hdmi/xilinx-hdmirx.c index 9840e53..14e411b 100644 --- a/hdmi/xilinx-hdmirx.c +++ b/hdmi/xilinx-hdmirx.c @@ -736,7 +736,10 @@ static void RxStreamUpCallback(void *CallbackRef) xhdmi->detected_format.width = Stream->Timing.HActive; xhdmi->detected_format.height = Stream->Timing.VActive; - xhdmi->detected_format.field = Stream->IsInterlaced? V4L2_FIELD_INTERLACED: V4L2_FIELD_NONE; + /* There is no point in setting feild V4L2_FIELD_INTERLACED as it is not getting used */ + //xhdmi->detected_format.field = Stream->IsInterlaced? V4L2_FIELD_INTERLACED: V4L2_FIELD_NONE; + xhdmi->detected_format.field = V4L2_FIELD_NONE; + /* https://linuxtv.org/downloads/v4l-dvb-apis/ch02s05.html#v4l2-colorspace */ if (Stream->ColorFormatId == XVIDC_CSF_RGB) { dev_dbg(xhdmi->dev,"xhdmi->detected_format.colorspace = V4L2_COLORSPACE_SRGB\n"); diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index 2e2b877..080fde6 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -552,9 +552,11 @@ static void TxStreamUpCallback(void *CallbackRef) (HdmiTxSsVidStreamPtr->VmId == XVIDC_VM_1440x576_50_I) ) { AVIInfoFramePtr->PixelRepetition = XHDMIC_PIXEL_REPETITION_FACTOR_2; + dev_dbg(xhdmi->dev,"Pixel repetition set to 2\n"); } else { AVIInfoFramePtr->PixelRepetition = XHDMIC_PIXEL_REPETITION_FACTOR_1; + dev_dbg(xhdmi->dev,"Pixel repetition set to 1\n"); } xvphy_mutex_lock(xhdmi->phy[0]); @@ -791,6 +793,16 @@ static int xlnx_drm_hdmi_connector_mode_valid(struct drm_connector *connector, enum drm_mode_status status = MODE_OK; dev_dbg(xhdmi->dev, "%s\n", __func__); + + /* This is done to make the functionality similar as BM code in which the + * timing table has vdisplay value of 540 for 1080i usecase. + * By this change, doing modetest -M xlnx, will give vdisplay 540 instead of + * 1080 */ + if(mode->flags & DRM_MODE_FLAG_INTERLACE) { + mode->vdisplay = mode->vdisplay / 2; + dev_dbg(xhdmi->dev, "For interlaced, divide mode->vdisplay %d\n", mode->vdisplay); + } + drm_mode_debug_printmodeline(mode); hdmi_mutex_lock(&xhdmi->hdmi_mutex); /* HDMI 2.0 sink connected? */ @@ -990,7 +1002,6 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, u32 PrevPhyTxRefClock = 0; u32 Result; u32 drm_fourcc; - XVidC_VideoMode VmId; XVidC_ColorDepth ColorDepth; int ret; @@ -1020,6 +1031,8 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, dev_dbg(xhdmi->dev,"mode->htotal = %d\n", mode->htotal); dev_dbg(xhdmi->dev,"mode->vtotal = %d\n", mode->vtotal); dev_dbg(xhdmi->dev,"mode->vrefresh = %d\n", mode->vrefresh); + dev_dbg(xhdmi->dev,"mode->flags = %d interlace = %d\n", mode->flags, + !!(mode->flags & DRM_MODE_FLAG_INTERLACE)); /* see slide 20 of http://events.linuxfoundation.org/sites/events/files/slides/brezillon-drm-kms.pdf */ vt.HActive = mode->hdisplay; @@ -1029,17 +1042,47 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, vt.HTotal = mode->htotal; vt.HSyncPolarity = !!(mode->flags & DRM_MODE_FLAG_PHSYNC); + /* Enable this code for debugging of NTSC and PAL resolution */ +#if 0 + if((mode->hdisplay == 720) && (mode->vdisplay == 240) && (mode->vrefresh == 60) + && (mode->flags & DRM_MODE_FLAG_INTERLACE)) + { + dev_dbg(xhdmi->dev,"NTSC/PAL\n\n"); + vt.HActive *= 2; + vt.HFrontPorch *= 2; + vt.HSyncWidth *= 2; + vt.HBackPorch *= 2; + vt.HTotal *= 2; + } +#endif vt.VActive = mode->vdisplay; /* Progressive timing data is stored in field 0 */ vt.F0PVFrontPorch = mode->vsync_start - mode->vdisplay; vt.F0PVSyncWidth = mode->vsync_end - mode->vsync_start; vt.F0PVBackPorch = mode->vtotal - mode->vsync_end; vt.F0PVTotal = mode->vtotal; - /* Interlaced output is not support - set field 1 to 0 */ - vt.F1VFrontPorch = 0; - vt.F1VSyncWidth = 0; - vt.F1VBackPorch = 0; - vt.F1VTotal = 0; + + if(mode->flags & DRM_MODE_FLAG_INTERLACE) { + dev_dbg(xhdmi->dev,"Programming fields for interlace"); + + vt.VActive = mode->vdisplay; + + vt.F0PVFrontPorch = (mode->vsync_start - (mode->vdisplay * 2)) / 2; + vt.F0PVSyncWidth = (mode->vsync_end - mode->vsync_start) / 2; + vt.F0PVBackPorch = (mode->vtotal - mode->vsync_end) / 2; + vt.F0PVTotal = mode->vdisplay + vt.F0PVFrontPorch + vt.F0PVSyncWidth + + vt.F0PVBackPorch; + + if((mode->vtotal - mode->vsync_end) % 2) + vt.F1VFrontPorch = 1 + (mode->vsync_start - (mode->vdisplay * 2)) / 2; + else + vt.F1VFrontPorch = (mode->vsync_start - (mode->vdisplay * 2)) / 2; + vt.F1VSyncWidth = (mode->vsync_end - mode->vsync_start) / 2; + vt.F1VBackPorch = (mode->vtotal - mode->vsync_end) / 2; + vt.F1VTotal = mode->vdisplay + vt.F1VFrontPorch + vt.F1VSyncWidth + + vt.F1VBackPorch; + } + vt.VSyncPolarity = !!(mode->flags & DRM_MODE_FLAG_PVSYNC); HdmiTxSsVidStreamPtr = XV_HdmiTxSs_GetVideoStream(HdmiTxSsPtr); @@ -1059,16 +1102,18 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, /* The isExtensive is made true to get the correct video timing by matching * all the parameters */ - VmId = XVidC_GetVideoModeIdExtensive(&vt, mode->vrefresh, FALSE, TRUE); + HdmiTxSsVidStreamPtr->VmId = XVidC_GetVideoModeIdExtensive(&vt, + mode->vrefresh, !!(mode->flags & DRM_MODE_FLAG_INTERLACE), TRUE); - dev_dbg(xhdmi->dev,"VmId = %d\n", VmId); - if (VmId == XVIDC_VM_NOT_SUPPORTED) { //no match found in timing table + dev_dbg(xhdmi->dev,"VmId = %d Interlaced = %d\n", HdmiTxSsVidStreamPtr->VmId, !!(mode->flags & DRM_MODE_FLAG_INTERLACE)); + if (HdmiTxSsVidStreamPtr->VmId == XVIDC_VM_NOT_SUPPORTED) { //no match found in timing table dev_dbg(xhdmi->dev,"Tx Video Mode not supported. Using DRM Timing\n"); - VmId = XVIDC_VM_CUSTOM; + HdmiTxSsVidStreamPtr->VmId = XVIDC_VM_CUSTOM; HdmiTxSsVidStreamPtr->FrameRate = mode->vrefresh; HdmiTxSsVidStreamPtr->Timing = vt; //overwrite with drm detected timing + HdmiTxSsVidStreamPtr->IsInterlaced = (!!(mode->flags & DRM_MODE_FLAG_INTERLACE)); #ifdef DEBUG - XVidC_ReportTiming(&HdmiTxSsVidStreamPtr->Timing, FALSE); + XVidC_ReportTiming(&HdmiTxSsVidStreamPtr->Timing, !!(mode->flags & DRM_MODE_FLAG_INTERLACE)); #endif } @@ -1090,7 +1135,7 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, break; } - TmdsClock = XV_HdmiTxSs_SetStream(HdmiTxSsPtr, VmId, xhdmi->xvidc_colorfmt, + TmdsClock = XV_HdmiTxSs_SetStream(HdmiTxSsPtr, HdmiTxSsVidStreamPtr->VmId, xhdmi->xvidc_colorfmt, ColorDepth, NULL); //Update AVI InfoFrame @@ -1111,7 +1156,6 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, HdmiTxSsVidStreamPtr->PixPerClk, HdmiTxSsVidStreamPtr->ColorDepth, HdmiTxSsVidStreamPtr->ColorFormatId); - if (Result == (XST_FAILURE)) { dev_dbg(xhdmi->dev,"Unable to set requested TX video resolution.\n\r"); xvphy_mutex_unlock(xhdmi->phy[0]); @@ -1867,7 +1911,7 @@ static int xlnx_drm_hdmi_create_connector(struct drm_encoder *encoder) DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; - connector->interlace_allowed = false; + connector->interlace_allowed = true; ret = drm_connector_init(encoder->dev, connector, &xlnx_drm_hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA); From 5d42dec66d4419c8dc78b1d5862cd1cf8e7e00e1 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Sat, 13 Oct 2018 08:22:39 +0800 Subject: [PATCH 18/46] hdmitx:hdmirx:vphy:dt:bindings: Drivers update 20181004 Drivers update till 20181004 Signed-off-by: Shikhar Mishra --- .../devicetree/bindings/xlnx,v-hdmi-rx-ss.txt | 40 ++++++------ .../devicetree/bindings/xlnx,v-hdmi-tx-ss.txt | 41 +++++++------ hdmi/phy-xilinx-vphy/xhdcp1x_port.c | 6 +- hdmi/phy-xilinx-vphy/xvphy.h | 4 +- hdmi/phy-xilinx-vphy/xvphy_gthe4.c | 13 ++-- hdmi/phy-xilinx-vphy/xvphy_i.c | 61 +++++++++++++++++++ hdmi/phy-xilinx-vphy/xvphy_i.h | 2 + hdmi/xilinx-hdmi-rx/xv_hdmirx.c | 5 ++ hdmi/xilinx-hdmi-rx/xv_hdmirx.h | 10 ++- hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c | 40 ++++++++---- hdmi/xilinx-hdmi-rx/xv_hdmirxss.c | 38 ++++++++++++ hdmi/xilinx-hdmi-rx/xv_hdmirxss.h | 25 +++++--- 12 files changed, 219 insertions(+), 66 deletions(-) diff --git a/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt b/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt index c8192a1..bcbd992 100644 --- a/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt +++ b/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt @@ -6,13 +6,13 @@ V4L2 video-capture sub-device for the Xilinx Video IP Pipeline device (xilinx-vipp). There are 2 optional HDCP cores that can be included in the IP configuration. -Below provided sample device tree depicts the configuration when both cores are -included. If an optional core is included then corresponding entries for the +Below provided sample device tree depicts the configuration when both cores are +included. If an optional core is included then corresponding entries for the core parameters (interrupts, key-management block address) must be included in the device tree Note: If HDCP cores are included in the design, the user must provide valid - HDCP keys for the encryption to work. + HDCP keys for the encryption to work. Refer to xlnx,vphy.txt for the phy specifics. @@ -25,40 +25,42 @@ Required Properties: hdcp1x. [Optional] - interrupts-parent: phandle for interrupt controller. - interrupts: Interrupt numbers for mandatory and optional blocks - - interrupt-names: Identification string that binds irq number to block + - interrupt-names: Identification string that binds irq number to block generating the interrupt "hdmirx": interrupt for rx subcore [always present] "hdcp1x": interrupt for hdcp1.4 core [optional] - "hdcp1x-timer": interrupt for hdcp1.4 timer [present if hdcp1x is + "hdcp1x-timer": interrupt for hdcp1.4 timer [present if hdcp1x is included] "hdcp22": interrupt for hdcp22 core [optional] "hdcp22-timer": interrupt for hdcp2.2 timer [present if hdcp22 is included] - + - clocks: phandle for axi-lite, video stream - clock-names: The identification string, "axi-lite", is always required for the axi-lite clock, "video" is always required for video stream clock - - - phys: phandle for phy lanes registered for hdmi protocol. HDMI always + + - phys: phandle for phy lanes registered for hdmi protocol. HDMI always require 3 lanes - phy-names: The identification string, "hdmi-phy0" and so on - + - xlnx,input-pixels-per-clock: IP configuration for samples/clk (2, 4) Note: Only 2 is supported at this time - - xlnx,edid-ram-size: Denotes amount of BRAM allocated for EDID in IP + - xlnx,edid-ram-size: Denotes amount of BRAM allocated for EDID in IP - xlnx,include-hdcp-1-4: Boolean parameter that denotes if hdcp14 is included. If present indicates inclusion of the optional core - xlnx,include-hdcp-2-2: Boolean parameter that denotes if hdcp22 is included. If present indicates inclusion of the optional core - xlnx,audio-enabled: Boolean parameter to convey that design has audio - functionality. If present, indicates optional audio core needed - for audio usecase is included. - - xlnx,snd-pcm: reference to audio formatter block. Add this if, - audio formatter is going to be used for HDMI audio. + functionality. + If present, indicates optional audio core needed for audio + usecase is included. + - xlnx,snd-pcm: Reference to audio formatter block. Add this if, audio formatter + is going to be used for HDMI audio. + Needed only if "xlnx,audio-enabled" is included. - ports: Video ports, using the DT bindings defined in ../video-interfaces.txt. The Rx only has an output port (0). - + ==Example== If hdcp1.4 is included in the design then key management block node should be added to the device tree @@ -71,7 +73,7 @@ added to the device tree hdmi_input_v_hdmi_rx_ss_0: v_hdmi_rx_ss@a0000000 { compatible = "xlnx,v-hdmi-rx-ss-3.1"; reg = <0x0 0xa0000000 0x0 0x100000>, <0x0 0xa0270000 0x0 0x10000>; - reg-names = "hdmi-rxss", "hdcp1x-keymngmt"; + reg-names = "hdmi-rxss", "hdcp1x-keymngmt"; interrupt-parent = <&gic>; interrupts = <0 91 4>, <0 108 4>, <0 109 4>, <0 110 4>, <0 111 4>; interrupt-names = "hdmirx", "hdcp1x", "hdcp1x-timer", "hdcp22", "hdcp22-timer"; @@ -79,7 +81,7 @@ added to the device tree clock-names = "axi-lite", "video"; phy-names = "hdmi-phy0", "hdmi-phy1", "hdmi-phy2"; phys = <&vphy_lane0 0 1 1 0>, <&vphy_lane1 0 1 1 0>, <&vphy_lane2 0 1 1 0>; - + xlnx,input-pixels-per-clock = <0x2>; xlnx,edid-ram-size = <0x100>; xlnx,include-hdcp-1-4; @@ -91,13 +93,13 @@ added to the device tree #size-cells = <0>; port@0 { reg = <0>; - + /* HDMI RX SS -> FB-WR */ hdmi_rxss_out: endpoint { remote-endpoint = <&vcap_hdmi_in>; }; }; - }; + }; }; Documentation of "audio_ss_0_audio_formatter_0" node is located diff --git a/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt b/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt index 027bdaa..8f98159 100644 --- a/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt +++ b/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt @@ -5,13 +5,13 @@ a HDMI Transmitter. xilinx_drm_hdmi.c implements a DRM/KMS driver encoder/connector interface in the output pipeline. There are 2 optional HDCP cores that can be included in the IP configuration. -Below provided sample device tree depicts the configuration when both cores are -included. If an optional core is included then corresponding entries for the +Below provided sample device tree depicts the configuration when both cores are +included. If an optional core is included then corresponding entries for the core parameters (interrupts, key-management block address) must be included in the device tree Note: If HDCP cores are included in the design, the user must provide valid - HDCP keys for the encryption to work. + HDCP keys for the encryption to work. Note: This version of the driver interfaces with the new Xilinx DRM component framework and is not backward compatible with the earlier encoder-slave @@ -19,7 +19,7 @@ Note: This version of the driver interfaces with the new Xilinx DRM component new interface. Refer to xlnx,vphy.txt for the phy specifics. - + Required properties: - compatible: Should be "xlnx,v-hdmi-tx-ss-3.1". - reg: Base address and size of the IP core and hdcp1x key management block @@ -30,11 +30,11 @@ Required properties: - interrupts-parent: phandle for interrupt controller. - interrupts: Interrupt numbers for mandatory and optional blocks - - interrupt-names: Identification string that binds irq number to block + - interrupt-names: Identification string that binds irq number to block generating the interrupt "hdmitx": interrupt for tx subcore [always present] "hdcp1x": interrupt for hdcp1.4 core [optional] - "hdcp1x-timer": interrupt for hdcp1.4 timer [present if hdcp1x is + "hdcp1x-timer": interrupt for hdcp1.4 timer [present if hdcp1x is included] "hdcp22": interrupt for hdcp22 core [optional] "hdcp22-timer": interrupt for hdcp2.2 timer [present if hdcp22 is @@ -43,14 +43,14 @@ Required properties: - clocks: phandle for axi-lite, video stream, tmds and retimer clock - clock-names: The identification string for various clock inputs "axi-lite", is always required for the axi-lite clock - "video" is always required for video stream clock + "video" is always required for video stream clock "txref-clk" is always required for tmds clock "retimer-clk" is required only when retimer is being used - - - phys: phandle for phy lanes registered for hdmi protocol. HDMI always + + - phys: phandle for phy lanes registered for hdmi protocol. HDMI always require 3 lanes - phy-names: The identification string, "hdmi-phy0" and so on - + - xlnx,input-pixels-per-clock: IP configuration for samples/clk (2, 4) Note: Only 2 is supported at this time - xlnx,max-bits-per-component: The data width per video component (8,10,12,16) @@ -59,16 +59,21 @@ Required properties: If present indicates inclusion of the optional core - xlnx,include-hdcp-2-2: Boolean parameter that denotes if hdcp22 is included. If present indicates inclusion of the optional core - - xlnx,hdcp-authenticate: Flag to enable/disable hdcp authentication. + - xlnx,hdcp-authenticate: Flag to enable/disable hdcp authentication. Applicable when either hdcp14 or hdcp22 is included in the design - xlnx,hdcp-encrypt: Flag to enable/disable stream encryption Applicable when either hdcp14 or hdcp22 is included in the design - xlnx,audio-enabled: Boolean parameter to convey that design has audio - functionality. If present, indicates optional audio core needed - for audio usecase is included. - - xlnx,snd-pcm: reference to audio formatter block. Add this if, - audio formatter is going to be used for HDMI audio - - xlnx,xlnx-hdmi-acr-ctrl: alias to audio clock recovery block + functionality. + If present, indicates optional audio core needed for audio + usecase is included. + - xlnx,aes_parser: Alias to audio channel status extractor block. + Needed only if "xlnx,audio-enabled" is included. + - xlnx,snd-pcm: Reference to audio formatter block. Add this if, audio formatter + is going to be used for HDMI audio. + Needed only if "xlnx,audio-enabled" is included. + - xlnx,xlnx-hdmi-acr-ctrl: Alias to audio clock recovery block. + Needed only if "xlnx,audio-enabled" is included. Sub-Node Properties: The device tree will need to include a sub-node for the encoder endpoint @@ -102,11 +107,11 @@ added to the device tree hdmi_output_v_hdmi_tx_ss_0: v_hdmi_tx_ss@a0080000 { compatible = "xlnx,v-hdmi-tx-ss-3.1"; reg = <0x0 0xa0080000 0x0 0x80000>, <0x0 0xa0280000 0x0 0x10000>; - reg-names = "hdmi-txss", "hdcp1x-keymngmt"; + reg-names = "hdmi-txss", "hdcp1x-keymngmt"; interrupt-parent = <&gic>; interrupts = <0 93 4>, <0 104 4>, <0 105 4>, <0 106 4>, <0 107 4>; interrupt-names = "hdmitx", "hdcp1x", "hdcp1x-timer", "hdcp22", "hdcp22-timer"; - + clocks = <&axi_lite_clk>, <&axi_stream_clk>, <&si5324 0>, <&dp159>; clock-names = "axi-lite", "video", "txref-clk", "retimer-clk"; phy-names = "hdmi-phy0", "hdmi-phy1", "hdmi-phy2"; diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_port.c b/hdmi/phy-xilinx-vphy/xhdcp1x_port.c index 0260162..8c2f567 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_port.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_port.c @@ -50,10 +50,12 @@ #if defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && (XPAR_XV_HDMIRX_NUM_INSTANCES > 0) #define INCLUDE_HDMI_RX #endif -#if defined(XPAR_XDP_NUM_INSTANCES) && (XPAR_XDP_NUM_INSTANCES > 0) -#define INCLUDE_DP_TX +#if defined(XPAR_XDPRXSS_NUM_INSTANCES) && (XPAR_XDPRXSS_NUM_INSTANCES > 0) #define INCLUDE_DP_RX #endif +#if defined(XPAR_XDPTXSS_NUM_INSTANCES) && (XPAR_XDPTXSS_NUM_INSTANCES > 0) +#define INCLUDE_DP_TX +#endif /**************************** Type Definitions *******************************/ diff --git a/hdmi/phy-xilinx-vphy/xvphy.h b/hdmi/phy-xilinx-vphy/xvphy.h index 10a4ff9..2c8c420 100644 --- a/hdmi/phy-xilinx-vphy/xvphy.h +++ b/hdmi/phy-xilinx-vphy/xvphy.h @@ -121,8 +121,8 @@ typedef enum { */ typedef enum { XVPHY_PROTOCOL_DP = 0, - XVPHY_PROTOCOL_HDMI, - XVPHY_PROTOCOL_NONE + XVPHY_PROTOCOL_HDMI = 1, + XVPHY_PROTOCOL_NONE = 3 } XVphy_ProtocolType; /* This typedef enumerates is used to specify RX/TX direction information. */ diff --git a/hdmi/phy-xilinx-vphy/xvphy_gthe4.c b/hdmi/phy-xilinx-vphy/xvphy_gthe4.c index 473fa75..5509f62 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_gthe4.c +++ b/hdmi/phy-xilinx-vphy/xvphy_gthe4.c @@ -29,11 +29,11 @@ * * Ver Who Date Changes * ----- ---- -------- ----------------------------------------------- - * 1.0 als 10/19/15 Initial release. - * 1.1 gm 03/18/16 Added XVphy_Gthe4RxPllRefClkDiv1Reconfig function + * 1.0 als 19/10/15 Initial release. + * 1.1 gm 18/03/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.2 gm 26/08/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 @@ -53,6 +53,8 @@ * 1.7 gm 13/09/17 Disabled intelligent clock sel in QPLL0/1 configuration * Updated DP CDR config for 8.1 Gbps * Updated XVPHY_QPLL0_MAX to 16375000000LL + * 1.8 gm 05/09/18 Enable IPS only when XVphy_GetRefClkSourcesCount + * returns more than 1. * * *******************************************************************************/ @@ -196,6 +198,7 @@ u32 XVphy_Gthe4CfgSetCdr(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) ChPtr->PllParams.Cdr[1] = 0x0000; ChPtr->PllParams.Cdr[3] = 0x0000; ChPtr->PllParams.Cdr[4] = 0x0000; + if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { /* RxOutDiv = 1 => Cdr[2] = 0x0269 * RxOutDiv = 2 => Cdr[2] = 0x0259 @@ -443,7 +446,9 @@ u32 XVphy_Gthe4ClkCmnReconfig(XVphy *InstancePtr, u8 QuadId, /* Mask out QPLLx_REFCLK_DIV. */ DrpVal &= ~(0xF80); /* Disable Intelligent Reference Clock Selection */ - DrpVal |= (1 << 6); + if (XVphy_GetRefClkSourcesCount(InstancePtr) > 1) { + DrpVal |= (1 << 6); + } /* Set QPLLx_REFCLK_DIV. */ WriteVal = (XVphy_MToDrpEncoding(InstancePtr, QuadId, CmnId) & 0x1F); DrpVal |= (WriteVal << 7); diff --git a/hdmi/phy-xilinx-vphy/xvphy_i.c b/hdmi/phy-xilinx-vphy/xvphy_i.c index 4747c79..c1ad086 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_i.c +++ b/hdmi/phy-xilinx-vphy/xvphy_i.c @@ -1269,6 +1269,67 @@ u64 XVphy_GetPllVcoFreqHz(XVphy *InstancePtr, u8 QuadId, return PllxVcoRateHz; } +/*****************************************************************************/ +/** +* This function returns the number of active reference clock sources +* based in the CFG +* +* @param InstancePtr is a pointer to the XVphy core instance. +* +* @return No of active REFCLK sources +* +* @note None. +* +******************************************************************************/ +u8 XVphy_GetRefClkSourcesCount(XVphy *InstancePtr) +{ + u8 RefClkNum = 0; + u8 RefClkNumMax = 3; + XVphy_PllRefClkSelType RefClkSel[RefClkNumMax]; + XVphy_PllRefClkSelType RefClkSelTemp[RefClkNumMax]; + u8 i, j, Match; + + /* TxRefClkSel */ + RefClkSel[0] = (InstancePtr->Config.TxProtocol != XVPHY_PROTOCOL_NONE) ? + InstancePtr->Config.TxRefClkSel : 99; + /* RxRefClkSel */ + RefClkSel[1] = (InstancePtr->Config.RxProtocol != XVPHY_PROTOCOL_NONE) ? + InstancePtr->Config.RxRefClkSel : 99; + /* DruRefClkSel */ + RefClkSel[2] = (InstancePtr->Config.DruIsPresent) ? + InstancePtr->Config.DruRefClkSel : 99; + + /* Initialize Unique RefClk holder */ + for (i=0; i * * @addtogroup xvphy @@ -128,6 +129,7 @@ void XVphy_CfgErrIntr(XVphy *InstancePtr, XVphy_ErrType ErrIrq, u8 Set); u64 XVphy_GetPllVcoFreqHz(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, XVphy_DirectionType Dir); +u8 XVphy_GetRefClkSourcesCount(XVphy *InstancePtr); void XVphy_ErrorHandler(XVphy *InstancePtr); #if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTXE2) diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirx.c b/hdmi/xilinx-hdmi-rx/xv_hdmirx.c index 737690c..2b768a4 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirx.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirx.c @@ -49,6 +49,7 @@ * 2.20 EB 16/08/18 Replaced TIME_10MS, TIME_16MS, TIME_200MS with * XV_HdmiRx_GetTime10Ms, XV_HdmiRx_GetTime16Ms * XV_HdmiRx_GetTime200Ms +* Added TMDS Clock Ratio callback support * * ******************************************************************************/ @@ -160,6 +161,10 @@ int XV_HdmiRx_CfgInitialize(XV_HdmiRx *InstancePtr, XV_HdmiRx_Config *CfgPtr, UI InstancePtr->ModeCallback = (XV_HdmiRx_Callback)((void *)StubCallback); InstancePtr->IsModeCallbackSet = (FALSE); + InstancePtr->TmdsClkRatioCallback = + (XV_HdmiRx_Callback)((void *)StubCallback); + InstancePtr->IsTmdsClkRatioCallbackSet = (FALSE); + /* Clear HDMI variables */ XV_HdmiRx_Clear(InstancePtr); diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirx.h b/hdmi/xilinx-hdmi-rx/xv_hdmirx.h index 39d8232..8baa68c 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirx.h +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirx.h @@ -132,7 +132,8 @@ * 2.20 EB 16/08/18 Replaced TIME_10MS, TIME_16MS, TIME_200MS with * XV_HdmiRx_GetTime10Ms, XV_HdmiRx_GetTime16Ms * XV_HdmiRx_GetTime200Ms -* YB 08/15/18 Added new callbacks for HDCP 1.4 & 2.2 protocol events. +* Added TMDS Clock Ratio callback support +* YB 15/08/18 Added new callbacks for HDCP 1.4 & 2.2 protocol events. * Enumerated new entries for HDCP 1.4 & 2.2 protocol * events in XV_HdmiRx_HandlerType enum. * @@ -180,7 +181,8 @@ typedef enum { XV_HDMIRX_HANDLER_DDC_HDCP_22_PROT, /**< Interrupt type for HDCP22PROT event */ XV_HDMIRX_HANDLER_LINK_ERROR, /**< Interrupt type for link error */ XV_HDMIRX_HANDLER_SYNC_LOSS, /**< Interrupt type for sync loss */ - XV_HDMIRX_HANDLER_MODE /**< Interrupt type for mode */ + XV_HDMIRX_HANDLER_MODE, /**< Interrupt type for mode */ + XV_HDMIRX_HANDLER_TMDS_CLK_RATIO /**< Interrupt type for TMDS clock ratio */ } XV_HdmiRx_HandlerType; /*@}*/ @@ -341,6 +343,10 @@ typedef struct { void *ModeRef; /**< To be passed to the link error callback */ u32 IsModeCallbackSet; /**< Set flag. This flag is set to true when the callback has been registered */ + XV_HdmiRx_Callback TmdsClkRatioCallback; /**< Callback for TMDS clock ratio change */ + void *TmdsClkRatioRef; /**< To be passed to the TMDS callback */ + u32 IsTmdsClkRatioCallbackSet; /**< Set flag. This flag is set to true when the callback has been registered */ + /* HDMI RX stream */ XV_HdmiRx_Stream Stream; /**< HDMI RX stream information */ diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c b/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c index 8be923e..6713211 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c @@ -50,7 +50,8 @@ * 2.20 EB 16/08/18 Replaced TIME_10MS, TIME_16MS, TIME_200MS with * XV_HdmiRx_GetTime10Ms, XV_HdmiRx_GetTime16Ms * XV_HdmiRx_GetTime200Ms -* YB 08/15/18 Added new cases for HDCP 1.4 & 2.2 protocol events in +* Added TMDS Clock Ratio callback support +* YB 15/08/18 Added new cases for HDCP 1.4 & 2.2 protocol events in * XV_HdmiRx_SetCallback function. * Updated the HdmiRx_DdcIntrHandler() function. * @@ -294,19 +295,19 @@ int XV_HdmiRx_SetCallback(XV_HdmiRx *InstancePtr, u32 HandlerType, void *Callbac // HDCP 1.4 Event case (XV_HDMIRX_HANDLER_DDC_HDCP_14_PROT): - InstancePtr->Hdcp14ProtEvtCallback = (XV_HdmiRx_Callback)CallbackFunc; - InstancePtr->Hdcp14ProtEvtRef = CallbackRef; - InstancePtr->IsHdcp14ProtEvtCallbackSet = (TRUE); - Status = (XST_SUCCESS); - break; + InstancePtr->Hdcp14ProtEvtCallback = (XV_HdmiRx_Callback)CallbackFunc; + InstancePtr->Hdcp14ProtEvtRef = CallbackRef; + InstancePtr->IsHdcp14ProtEvtCallbackSet = (TRUE); + Status = (XST_SUCCESS); + break; // HDCP 2.2 Event case (XV_HDMIRX_HANDLER_DDC_HDCP_22_PROT): - InstancePtr->Hdcp22ProtEvtCallback = (XV_HdmiRx_Callback)CallbackFunc; - InstancePtr->Hdcp22ProtEvtRef = CallbackRef; - InstancePtr->IsHdcp22ProtEvtCallbackSet = (TRUE); - Status = (XST_SUCCESS); - break; + InstancePtr->Hdcp22ProtEvtCallback = (XV_HdmiRx_Callback)CallbackFunc; + InstancePtr->Hdcp22ProtEvtRef = CallbackRef; + InstancePtr->IsHdcp22ProtEvtCallbackSet = (TRUE); + Status = (XST_SUCCESS); + break; case (XV_HDMIRX_HANDLER_LINK_ERROR): InstancePtr->LinkErrorCallback = (XV_HdmiRx_Callback)CallbackFunc; @@ -339,6 +340,15 @@ int XV_HdmiRx_SetCallback(XV_HdmiRx *InstancePtr, u32 HandlerType, void *Callbac Status = (XST_SUCCESS); break; + // TMDS clock ratio + case (XV_HDMIRX_HANDLER_TMDS_CLK_RATIO): + InstancePtr->TmdsClkRatioCallback = + (XV_HdmiRx_Callback)CallbackFunc; + InstancePtr->TmdsClkRatioRef = CallbackRef; + InstancePtr->IsTmdsClkRatioCallbackSet = (TRUE); + Status = (XST_SUCCESS); + break; + default: Status = (XST_INVALID_PARAM); break; @@ -717,6 +727,14 @@ void HdmiRx_PioIntrHandler(XV_HdmiRx *InstancePtr) } } + // TMDS clock ratio + if ((Event) & (XV_HDMIRX_PIO_IN_SCDC_TMDS_CLOCK_RATIO_MASK)) { + // Call TMDS Ratio callback + if (InstancePtr->IsTmdsClkRatioCallbackSet) { + InstancePtr->TmdsClkRatioCallback(InstancePtr->TmdsClkRatioRef); + } + } + /* Bridge Overflow event has occurred */ if ((Event) & (XV_HDMIRX_PIO_IN_BRDG_OVERFLOW_MASK)) { // Check if user callback has been registered diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c index 5d41a75..5527855 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c @@ -102,6 +102,7 @@ * to HDMI1.4 * YH 13/04/18 Fixed a bug in XV_HdmiRxSs_BrdgOverflowCallback * 5.20 EB 03/08/18 Added function XV_HdmiRxSs_AudioMute +* Added TMDS Clock Ratio callback support ******************************************************************************/ /***************************** Include Files *********************************/ @@ -148,6 +149,7 @@ static void XV_HdmiRxSs_StreamInitCallback(void *CallbackRef); static void XV_HdmiRxSs_StreamUpCallback(void *CallbackRef); static void XV_HdmiRxSs_SyncLossCallback(void *CallbackRef); static void XV_HdmiRxSs_ModeCallback(void *CallbackRef); +static void XV_HdmiRxSs_TmdsClkRatioCallback(void *CallbackRef); static void XV_HdmiRxSs_ReportCoreInfo(XV_HdmiRxSs *InstancePtr); static void XV_HdmiRxSs_ReportTiming(XV_HdmiRxSs *InstancePtr); @@ -408,6 +410,11 @@ static int XV_HdmiRxSs_RegisterSubsysCallbacks(XV_HdmiRxSs *InstancePtr) XV_HDMIRX_HANDLER_MODE, (void *)XV_HdmiRxSs_ModeCallback, (void *)InstancePtr); + + XV_HdmiRx_SetCallback(HdmiRxSsPtr->HdmiRxPtr, + XV_HDMIRX_HANDLER_TMDS_CLK_RATIO, + (void *)XV_HdmiRxSs_TmdsClkRatioCallback, + (void *)InstancePtr); } return(XST_SUCCESS); @@ -981,6 +988,29 @@ static void XV_HdmiRxSs_ModeCallback(void *CallbackRef) } } +/*****************************************************************************/ +/** +* +* This function is called when the TMDS CLK ratio changes. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void XV_HdmiRxSs_TmdsClkRatioCallback(void *CallbackRef) +{ + XV_HdmiRxSs *HdmiRxSsPtr = (XV_HdmiRxSs *)CallbackRef; + + // Check if user callback has been registered + if (HdmiRxSsPtr->TmdsClkRatioCallback) { + HdmiRxSsPtr->TmdsClkRatioCallback(HdmiRxSsPtr->TmdsClkRatioRef); + } + +} + /*****************************************************************************/ /** * @@ -1327,6 +1357,14 @@ int XV_HdmiRxSs_SetCallback(XV_HdmiRxSs *InstancePtr, u32 HandlerType, Status = (XST_SUCCESS); break; + // TMDS_CLK_RATIO + case (XV_HDMIRXSS_HANDLER_TMDS_CLK_RATIO): + InstancePtr->TmdsClkRatioCallback = + (XV_HdmiRxSs_Callback)CallbackFunc; + InstancePtr->TmdsClkRatioRef = CallbackRef; + Status = (XST_SUCCESS); + break; + // HDCP case (XV_HDMIRXSS_HANDLER_HDCP): InstancePtr->HdcpCallback = (XV_HdmiRxSs_Callback)CallbackFunc; diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h index 705d6a5..ce8a194 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h @@ -78,8 +78,9 @@ * 5.2 YB 08/14/18 Added dedicated callbacks for HDCP 1.4 and HDCP 2.2 * protocol events. * EB 03/08/18 Added function XV_HdmiRxSs_AudioMute -* YB 08/17/18 Marked XV_HDMIRXSS_HDCP_1_PROT_EVT and -* XV_HDMIRXSS_HDCP_2_PROT_EVT as deprecated. +* Added TMDS Clock Ratio callback support +* YB 17/08/18 Marked XV_HDMIRXSS_HDCP_1_PROT_EVT and +* XV_HDMIRXSS_HDCP_2_PROT_EVT as deprecated. * * ******************************************************************************/ @@ -103,9 +104,9 @@ extern "C" { #if defined(XPAR_XHDCP_NUM_INSTANCES) || defined(XPAR_XHDCP22_RX_NUM_INSTANCES) #define USE_HDCP_RX #define USE_HDCP_14_PROT_EVT_ENUM -_Pragma ("GCC warning \"'XV_HDMIRXSS_HDCP_1_PROT_EVT' event is deprecated\"") +#pragma message ("'XV_HDMIRXSS_HDCP_1_PROT_EVT' event is deprecated") #define USE_HDCP_22_PROT_EVT_ENUM -_Pragma ("GCC warning \"'XV_HDMIRXSS_HDCP_2_PROT_EVT' event is deprecated\"") +#pragma message ("'XV_HDMIRXSS_HDCP_2_PROT_EVT' event is deprecated") #define XV_HDMIRXSS_HDCP_KEYSEL 0x00u #define XV_HDMIRXSS_HDCP_MAX_QUEUE_SIZE 16 #endif @@ -253,7 +254,7 @@ typedef enum { event */ XV_HDMIRXSS_HANDLER_BRDGOVERFLOW, /**< Handler for bridge fifo overflow - event */ + event */ XV_HDMIRXSS_HANDLER_AUX, /**< Handler for AUX peripheral event */ XV_HDMIRXSS_HANDLER_AUD, /**< Handler for AUD @@ -276,14 +277,17 @@ typedef enum { unauthenticated event*/ XV_HDMIRXSS_HANDLER_HDCP_AUTHENTICATION_REQUEST, /**< Handler for HDCP authentication request - event */ + event */ XV_HDMIRXSS_HANDLER_HDCP_STREAM_MANAGE_REQUEST, /**< Handler for HDCP stream manage request event */ XV_HDMIRXSS_HANDLER_HDCP_TOPOLOGY_UPDATE, /**< Handler for HDCP topology update event*/ - XV_HDMIRXSS_HANDLER_HDCP_ENCRYPTION_UPDATE /**< Handler for HDCP + XV_HDMIRXSS_HANDLER_HDCP_ENCRYPTION_UPDATE, /**< Handler for HDCP encryption status - update event */ + update event */ + XV_HDMIRXSS_HANDLER_TMDS_CLK_RATIO /**< Handler type for + TMDS clock ratio + change */ } XV_HdmiRxSs_HandlerType; /*@}*/ @@ -390,6 +394,11 @@ typedef struct XV_HdmiRxSs_Callback HdcpCallback; /**< Callback for HDCP 1.4 event */ void *HdcpRef; /**< To be passed to the hdcp callback */ + XV_HdmiRxSs_Callback TmdsClkRatioCallback; /**< Callback for scdc TMDS clock + ratio change callback */ + void *TmdsClkRatioRef;/**< To be passed to the scdc tmds clock ratio change + callback */ + // Scratch pad u8 IsStreamConnected; /**< HDMI RX Stream Connected */ u8 IsStreamUp; /**< HDMI RX Stream Up */ From 2a05aade1e7bcec0ccf55a4194274a7a3dbae331 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Mon, 19 Nov 2018 12:42:57 +0800 Subject: [PATCH 19/46] hdmitx: use TMDS clock ratio flag for 4k in audio driver TMDS clock ratio flag is set, when resolution is 4k and 60fps. Audio recovery block uses this flag to run audio ot 4k@60fps. Signed-off-by: Shikhar Mishra --- hdmi/xilinx_drm_hdmi.c | 11 +++++++++++ hdmi/xlnx_hdmitx_audio.c | 19 ++++++++++++++++--- hdmi/xlnx_hdmitx_audio.h | 1 + 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index 080fde6..fd68fb7 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -1182,6 +1182,17 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, dev_dbg(xhdmi->dev,"***** Reset Phy Tx Frequency *******\n"); XVphy_ClkDetFreqReset(VphyPtr, 0, XVPHY_DIR_TX); } + + xhdmi->tx_audio_data->tmds_clk = clk_get_rate(xhdmi->tmds_clk); + /* if the mode is HDMI 2.0, use a multiplier value of 4 */ + if (HdmiTxSsPtr->HdmiTxPtr->Stream.TMDSClockRatio) { + xhdmi->tx_audio_data->tmds_clk = + xhdmi->tx_audio_data->tmds_clk * 4; + xhdmi->tx_audio_data->tmds_clk_ratio = true; + } else { + xhdmi->tx_audio_data->tmds_clk_ratio = false; + } + xvphy_mutex_unlock(xhdmi->phy[0]); hdmi_mutex_unlock(&xhdmi->hdmi_mutex); } diff --git a/hdmi/xlnx_hdmitx_audio.c b/hdmi/xlnx_hdmitx_audio.c index e073eb2..4e32985 100644 --- a/hdmi/xlnx_hdmitx_audio.c +++ b/hdmi/xlnx_hdmitx_audio.c @@ -22,6 +22,7 @@ #define XV_ACR_ENABLE 0x4 #define XV_ACR_N 0xc +#define ACR_CTRL_TMDSCLKRATIO BIT(3) struct acr_n_table { u32 tmds_rate; @@ -179,7 +180,7 @@ static int audio_codec_hw_params(struct device *dev, void *data, struct hdmi_codec_daifmt *fmt, struct hdmi_codec_params *hparams) { - u32 n, i; + u32 n, i, val; struct hdmi_audio_infoframe *frame = &hparams->cea; struct xlnx_hdmitx_audio_data *adata = hdmitx_get_audio_data(dev); @@ -188,11 +189,23 @@ static int audio_codec_hw_params(struct device *dev, void *data, hdmi_audio_infoframe_pack(&hparams->cea, adata->buffer, HDMI_INFOFRAME_SIZE(AUDIO)); - n = xhdmi_acr_get_n(adata->tmds_clk, hparams->sample_rate); + if (adata->tmds_clk >= 371250000 && adata->tmds_clk <= 594000000) + n = 5120; + else + n = xhdmi_acr_get_n(adata->tmds_clk, hparams->sample_rate); + + /* Disable ACR */ writel(2, adata->acr_base + XV_ACR_ENABLE); + /* program 'N' */ writel(n, adata->acr_base + XV_ACR_N); - writel(3, adata->acr_base + XV_ACR_ENABLE); + + val = 3; + if (adata->tmds_clk_ratio) + val |= ACR_CTRL_TMDSCLKRATIO; + + /* Enable ACR */ + writel(val, adata->acr_base + XV_ACR_ENABLE); return 0; } diff --git a/hdmi/xlnx_hdmitx_audio.h b/hdmi/xlnx_hdmitx_audio.h index 0a05987..444e055 100644 --- a/hdmi/xlnx_hdmitx_audio.h +++ b/hdmi/xlnx_hdmitx_audio.h @@ -22,6 +22,7 @@ struct xlnx_hdmitx_audio_data { u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)]; unsigned int tmds_clk; void __iomem *acr_base; + bool tmds_clk_ratio; }; struct xlnx_hdmitx_audio_data *hdmitx_get_audio_data(struct device *dev); From cccf4a9c705b44ce0b02d15361c65210c196f845 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Tue, 9 Apr 2019 13:37:06 +0800 Subject: [PATCH 20/46] hdmitx:hdmirx: Adaptation to 4.19 kernel version hdmitx: use new drm framework API in hdmi tx driver hdmirx: use new audio framework API in audio driver Signed-off-by: Shikhar Mishra --- hdmi/xilinx_drm_hdmi.c | 4 ++-- hdmi/xlnx_hdmirx_audio.c | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index fd68fb7..d63cd6c 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -880,7 +880,7 @@ static int xlnx_drm_hdmi_connector_get_modes(struct drm_connector *connector) } xhdmi->have_edid = 1; - drm_mode_connector_update_edid_property(connector, edid); + drm_connector_update_edid_property(connector, edid); ret = drm_add_edid_modes(connector, edid); kfree(edid); dev_dbg(xhdmi->dev, "xlnx_drm_hdmi_get_modes() done\n"); @@ -1937,7 +1937,7 @@ static int xlnx_drm_hdmi_create_connector(struct drm_encoder *encoder) dev_err(xhdmi->dev, "Failed to register the connector (ret=%d)\n", ret); return ret; } - ret = drm_mode_connector_attach_encoder(connector, encoder); + ret = drm_connector_attach_encoder(connector, encoder); if (ret) { dev_err(xhdmi->dev, "Failed to attch encoder to connector (ret=%d)\n", ret); diff --git a/hdmi/xlnx_hdmirx_audio.c b/hdmi/xlnx_hdmirx_audio.c index 987dabf..9c144be 100644 --- a/hdmi/xlnx_hdmirx_audio.c +++ b/hdmi/xlnx_hdmirx_audio.c @@ -76,17 +76,16 @@ static struct snd_soc_dai_driver xlnx_rx_audio_dai = { .ops = &xlnx_rx_dai_ops, }; -static int xlnx_rx_codec_probe(struct snd_soc_codec *codec) +static int xlnx_rx_codec_probe(struct snd_soc_component *component) { return 0; } -static int xlnx_rx_codec_remove(struct snd_soc_codec *codec) +void xlnx_rx_codec_remove(struct snd_soc_component *component) { - return 0; } -static struct snd_soc_codec_driver xlnx_rx_codec_driver = { +static const struct snd_soc_component_driver xlnx_rx_codec_driver = { .probe = xlnx_rx_codec_probe, .remove = xlnx_rx_codec_remove, }; @@ -98,7 +97,7 @@ static struct snd_soc_codec_driver xlnx_rx_codec_driver = { */ int hdmirx_register_aud_dev(struct device *dev) { - return snd_soc_register_codec(dev, &xlnx_rx_codec_driver, + return snd_soc_register_component(dev, &xlnx_rx_codec_driver, &xlnx_rx_audio_dai, 1); } @@ -108,6 +107,6 @@ int hdmirx_register_aud_dev(struct device *dev) */ void hdmirx_unregister_aud_dev(struct device *dev) { - snd_soc_unregister_codec(dev); + snd_soc_unregister_component(dev); } From e6284b11efd20f14fe50ec4a0bedb5d16af3e4f7 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Tue, 9 Apr 2019 13:40:02 +0800 Subject: [PATCH 21/46] hdmirx:hdmitx: NTSC and PAL resolution support Signed-off-by: Shikhar Mishra --- hdmi/xilinx-hdmi-rx/xv_hdmirxss.c | 22 ------------------- hdmi/xilinx-hdmi-rx/xv_hdmirxss.h | 27 +++++++++++++++++++++++ hdmi/xilinx-hdmirx.c | 34 +++++++++++++++++++++++++++-- hdmi/xilinx_drm_hdmi.c | 36 +++++++++++++++++++++++++------ 4 files changed, 89 insertions(+), 30 deletions(-) diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c index 5527855..3893108 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c @@ -162,28 +162,6 @@ static void XV_HdmiRxSs_ConfigBridgeMode(XV_HdmiRxSs *InstancePtr); /***************** Macros (Inline Functions) Definitions *********************/ /*****************************************************************************/ -/** -* This macros selects the bridge YUV420 mode -* -* @param InstancePtr is a pointer to the HDMI RX Subsystem -* -*****************************************************************************/ -#define XV_HdmiRxSs_BridgeYuv420(InstancePtr,Enable) \ -{ \ - XV_HdmiRx_Bridge_yuv420(InstancePtr->HdmiRxPtr, Enable); \ -} \ - -/*****************************************************************************/ -/** -* This macros selects the bridge pixel repeat mode -* -* @param InstancePtr is a pointer to the HDMI RX Subsystem -* -*****************************************************************************/ -#define XV_HdmiRxSs_BridgePixelDrop(InstancePtr,Enable) \ -{ \ - XV_HdmiRx_Bridge_pixel(InstancePtr->HdmiRxPtr, Enable); \ -} /************************** Function Definition ******************************/ diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h index ce8a194..d865aa6 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h @@ -119,6 +119,33 @@ extern "C" { #ifdef XPAR_XHDCP22_RX_NUM_INSTANCES #include "xhdcp22_rx.h" #endif + +/***************** Macros (Inline Functions) Definitions *********************/ +/*****************************************************************************/ +/** +* This macros selects the bridge YUV420 mode +* +* @param InstancePtr is a pointer to the HDMI RX Subsystem +* +*****************************************************************************/ +#define XV_HdmiRxSs_BridgeYuv420(InstancePtr,Enable) \ +{ \ + XV_HdmiRx_Bridge_yuv420(InstancePtr->HdmiRxPtr, Enable); \ +} \ + +/*****************************************************************************/ +/** +* This macros selects the bridge pixel repeat mode +* +* @param InstancePtr is a pointer to the HDMI RX Subsystem +* +*****************************************************************************/ +#define XV_HdmiRxSs_BridgePixelDrop(InstancePtr,Enable) \ +{ \ + XV_HdmiRx_Bridge_pixel(InstancePtr->HdmiRxPtr, Enable); \ +} + + /****************************** Type Definitions ******************************/ /** @name Handler Types * @{ diff --git a/hdmi/xilinx-hdmirx.c b/hdmi/xilinx-hdmirx.c index 14e411b..076a4f9 100644 --- a/hdmi/xilinx-hdmirx.c +++ b/hdmi/xilinx-hdmirx.c @@ -736,6 +736,19 @@ static void RxStreamUpCallback(void *CallbackRef) xhdmi->detected_format.width = Stream->Timing.HActive; xhdmi->detected_format.height = Stream->Timing.VActive; + /* Check for the NTSC and PAL resolutions. RX will detect the resolution as 1440x240 (NTSC resolution) + * for field 0 and field 1. + * Upon detecting this RX should drop the extra pixel and send only 720x240 per field to Frame buffer write IP. + * Therefore in the end of this function, we will have to call API to configure bridge for pixel drop. + */ + if((((Stream->Timing.HActive == 1440) && (Stream->Timing.VActive == 240) && (Stream->FrameRate == 60)) || + ((Stream->Timing.HActive == 1440) && (Stream->Timing.VActive == 288) && (Stream->FrameRate == 50))) + && (!!Stream->IsInterlaced)) + { + xhdmi->detected_format.width /= 2; + dev_dbg(xhdmi->dev, "NTSC/PAL detected_format.width after divide by 2 = %d\n", xhdmi->detected_format.width); + } + /* There is no point in setting feild V4L2_FIELD_INTERLACED as it is not getting used */ //xhdmi->detected_format.field = Stream->IsInterlaced? V4L2_FIELD_INTERLACED: V4L2_FIELD_NONE; xhdmi->detected_format.field = V4L2_FIELD_NONE; @@ -797,6 +810,23 @@ static void RxStreamUpCallback(void *CallbackRef) } xhdmi->detected_timings.bt.pixelclock *= Stream->Timing.HTotal; + /* Check for the NTSC and PAL resolutions. RX will detect the resolution as 1440x240 (NTSC resolution) + * for field 0 and field 1. + * Upon detecting this RX should drop the extra pixel and send only 720x240 per field to Frame buffer write IP. + * Therefore in the end of this function, we will have to call API to configure bridge for pixel drop. + */ + if((((Stream->Timing.HActive == 1440) && (Stream->Timing.VActive == 240) && (Stream->FrameRate == 60)) || + ((Stream->Timing.HActive == 1440) && (Stream->Timing.VActive == 288) && (Stream->FrameRate == 50))) + && (!!Stream->IsInterlaced)) + { + xhdmi->detected_timings.bt.width /= 2; + dev_dbg(xhdmi->dev, "NTSC/PAL detected_timings.bt.width after divide by 2 = %d\n", xhdmi->detected_format.width); + + dev_dbg(xhdmi->dev,"Programming RX bridge for dropping pixels\n"); + XV_HdmiRxSs_BridgeYuv420(HdmiRxSsPtr, FALSE); + XV_HdmiRxSs_BridgePixelDrop(HdmiRxSsPtr, TRUE); + } + dev_dbg(xhdmi->dev,"HdmiRxSsPtr->HdmiRxPtr->Stream.PixelClk = %d\n", HdmiRxSsPtr->HdmiRxPtr->Stream.PixelClk); /* Read HFront Porch */ xhdmi->detected_timings.bt.hfrontporch = Stream->Timing.HFrontPorch; @@ -840,7 +870,7 @@ static void RxBrdgOverflowCallback(void *CallbackRef) struct xhdmi_device *xhdmi = (struct xhdmi_device *)CallbackRef; XV_HdmiRxSs *HdmiRxSsPtr = &xhdmi->xv_hdmirxss; - dev_dbg(xhdmi->dev,"RxBrdgOverflowCallback()\n"); + //dev_dbg(xhdmi->dev,"RxBrdgOverflowCallback()\n"); } static void RxAudCallback(void *CallbackRef) @@ -871,7 +901,7 @@ static void RxAuxCallback(void *CallbackRef) AuxPtr = XV_HdmiRxSs_GetAuxiliary(HdmiRxSsPtr); - dev_dbg(xhdmi->dev,"%s()\n", __func__); + //dev_dbg(xhdmi->dev,"%s()\n", __func__); /* read out the aux packet to a local buffer * currently only 1 Aux packet (last recvd) is stored */ diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index d63cd6c..4f88fc2 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -800,7 +800,24 @@ static int xlnx_drm_hdmi_connector_mode_valid(struct drm_connector *connector, * 1080 */ if(mode->flags & DRM_MODE_FLAG_INTERLACE) { mode->vdisplay = mode->vdisplay / 2; - dev_dbg(xhdmi->dev, "For interlaced, divide mode->vdisplay %d\n", mode->vdisplay); + dev_dbg(xhdmi->dev, "For DRM_MODE_FLAG_INTERLACE, divide mode->vdisplay %d\n", mode->vdisplay); + } + + if((mode->flags & DRM_MODE_FLAG_DBLCLK) && (mode->flags & DRM_MODE_FLAG_INTERLACE)) { + mode->clock *= 2; + /* This logic is needed because the value of vrefresh is coming as zero for 480i@60 and 576i@50 + * because of which after multiplying the pixel clock by 2, the mode getting selected is 480i@120 + * 576i@100 from drm_edid.c file as this becomes the matching mode. + * Seems like bug in the kernel code for handling of DRM_MODE_FLAG_DBLCLK flag. + */ + if(mode->vrefresh == 0) + { + if(mode->vdisplay == 240) + mode->vrefresh = 60; + else if (mode->vdisplay == 288) + mode->vrefresh = 50; + } + dev_dbg(xhdmi->dev, "For DRM_MODE_FLAG_DBLCLK, multiply pixel_clk by 2, New pixel clock %d, refresh rate = %d\n", mode->clock, mode->vrefresh); } drm_mode_debug_printmodeline(mode); @@ -1043,18 +1060,18 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, vt.HSyncPolarity = !!(mode->flags & DRM_MODE_FLAG_PHSYNC); /* Enable this code for debugging of NTSC and PAL resolution */ -#if 0 - if((mode->hdisplay == 720) && (mode->vdisplay == 240) && (mode->vrefresh == 60) - && (mode->flags & DRM_MODE_FLAG_INTERLACE)) + if((((mode->hdisplay == 720) && (mode->vdisplay == 240) && (mode->vrefresh == 60)) || + ((mode->hdisplay == 720) && (mode->vdisplay == 288) && (mode->vrefresh == 50))) + && (mode->flags & DRM_MODE_FLAG_INTERLACE) && (mode->flags & DRM_MODE_FLAG_DBLCLK)) { - dev_dbg(xhdmi->dev,"NTSC/PAL\n\n"); + dev_dbg(xhdmi->dev,"NTSC/PAL\n"); vt.HActive *= 2; vt.HFrontPorch *= 2; vt.HSyncWidth *= 2; vt.HBackPorch *= 2; vt.HTotal *= 2; } -#endif + vt.VActive = mode->vdisplay; /* Progressive timing data is stored in field 0 */ vt.F0PVFrontPorch = mode->vsync_start - mode->vdisplay; @@ -1143,6 +1160,13 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, AviInfoFramePtr->ColorSpace = XV_HdmiC_XVidC_To_IfColorformat(xhdmi->xvidc_colorfmt); AviInfoFramePtr->VIC = HdmiTxSsPtr->HdmiTxPtr->Stream.Vic; + if ( (HdmiTxSsVidStreamPtr->VmId == XVIDC_VM_1440x480_60_I) || + (HdmiTxSsVidStreamPtr->VmId == XVIDC_VM_1440x576_50_I) ) { + AviInfoFramePtr->PixelRepetition = XHDMIC_PIXEL_REPETITION_FACTOR_2; + } else { + AviInfoFramePtr->PixelRepetition = XHDMIC_PIXEL_REPETITION_FACTOR_1; + } + // Set TX reference clock VphyPtr->HdmiTxRefClkHz = TmdsClock; dev_dbg(xhdmi->dev,"(TmdsClock = %u, from XV_HdmiTxSs_SetStream())\n", TmdsClock); From 1701dcdda5345c1aae496cab4f589c52acef8065 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Tue, 9 Apr 2019 13:41:50 +0800 Subject: [PATCH 22/46] hdmitx: HdmiTx is not put in DVI mode when attached to a DVI monitor - After reading edid, if the sink is non HDMI sink, stream type is set to DVI, else HDMI. - Also updated the DRM when there is failure in reading EDID Signed-off-by: Shikhar Mishra --- hdmi/xilinx_drm_hdmi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index 4f88fc2..1aa6437 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -877,6 +877,7 @@ static int xlnx_drm_hdmi_connector_get_modes(struct drm_connector *connector) struct edid *edid = NULL; struct drm_display_info *info = &connector->display_info; int ret; + bool is_hdmi_sink; dev_dbg(xhdmi->dev, "%s\n", __func__); hdmi_mutex_lock(&xhdmi->hdmi_mutex); @@ -893,10 +894,21 @@ static int xlnx_drm_hdmi_connector_get_modes(struct drm_connector *connector) if (!edid) { xhdmi->have_edid = 0; dev_err(xhdmi->dev, "xlnx_drm_hdmi_get_modes() could not obtain edid, assume <= 1024x768 works.\n"); + drm_connector_update_edid_property(connector, NULL); return 0; } xhdmi->have_edid = 1; + /* If the sink is non HDMI, set the stream type to DVI else HDMI */ + is_hdmi_sink = drm_detect_hdmi_monitor(edid); + if(is_hdmi_sink) { + XV_HdmiTxSs_SetVideoStreamType(&xhdmi->xv_hdmitxss, 1); + dev_dbg(xhdmi->dev, "EDID shows HDMI sink is connected, setting stream type to HDMI\n"); + } else { + XV_HdmiTxSs_SetVideoStreamType(&xhdmi->xv_hdmitxss, 0); + dev_dbg(xhdmi->dev, "EDID shows non HDMI sink is connected, setting stream type to DVI\n"); + } + drm_connector_update_edid_property(connector, edid); ret = drm_add_edid_modes(connector, edid); kfree(edid); From e96b835cf6df612087d707b421ffec11110029fd Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Tue, 9 Apr 2019 13:42:36 +0800 Subject: [PATCH 23/46] hdmitx:hdmirx:vphy: Support for auto DTG Code has been modified to support the auto generated device tree so that minimal modification is needed in the DT. Modification still needed after the implementation are - Adding si5324 and dp159 node (other board specific details not part of hdf) in axi_iic node - Adding refhdmi clock node for si5324 - Adding dru_clk in vphy which is also external - For hdcp design, adding hdmi_eeprom in axi_iic node - Changing the default value of "xlnx,vformat" in "v_drm_dmaengine_drv" to BG24 otherwise problem during first modeset - For hdcp design, reg-name feild needs to be added in RX and TX node to access the HDCP block key mngmnt block using reg name. Signed-off-by: Shikhar Mishra --- hdmi/phy-vphy.c | 20 ++++++++++---------- hdmi/xilinx-hdmirx.c | 12 ++++++------ hdmi/xilinx_drm_hdmi.c | 12 ++++++------ 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/hdmi/phy-vphy.c b/hdmi/phy-vphy.c index df2eb07..0dbcdb6 100644 --- a/hdmi/phy-vphy.c +++ b/hdmi/phy-vphy.c @@ -108,7 +108,7 @@ struct xvphy_dev { /* AXI Lite clock drives the clock detector */ struct clk *axi_lite_clk; /* NI-DRU clock input */ - struct clk *clkp; + struct clk *dru_clk; }; /* given the (Linux) phy handle, return the xvphy */ @@ -483,7 +483,7 @@ static int xvphy_probe(struct platform_device *pdev) } /* the AXI lite clock is used for the clock rate detector */ - vphydev->axi_lite_clk = devm_clk_get(&pdev->dev, "axi-lite"); + vphydev->axi_lite_clk = devm_clk_get(&pdev->dev, "vid_phy_axi4lite_aclk"); if (IS_ERR(vphydev->axi_lite_clk)) { ret = PTR_ERR(vphydev->axi_lite_clk); vphydev->axi_lite_clk = NULL; @@ -508,10 +508,10 @@ static int xvphy_probe(struct platform_device *pdev) /* dru-clk is used for the nidru block for low res support */ if (XVphy_ConfigTable[instance].DruIsPresent == (TRUE)) { - vphydev->clkp = devm_clk_get(&pdev->dev, "dru-clk"); - if (IS_ERR(vphydev->clkp)) { - ret = PTR_ERR(vphydev->clkp); - vphydev->clkp = NULL; + vphydev->dru_clk = devm_clk_get(&pdev->dev, "dru-clk"); + if (IS_ERR(vphydev->dru_clk)) { + ret = PTR_ERR(vphydev->dru_clk); + vphydev->dru_clk = NULL; if (ret == -EPROBE_DEFER) dev_info(&pdev->dev, "dru-clk not ready -EPROBE_DEFER\n"); if (ret != -EPROBE_DEFER) @@ -519,20 +519,20 @@ static int xvphy_probe(struct platform_device *pdev) return ret; } - ret = clk_prepare_enable(vphydev->clkp); + ret = clk_prepare_enable(vphydev->dru_clk); if (ret) { dev_err(&pdev->dev, "failed to enable nidru clk\n"); return ret; } - dru_clk_rate = clk_get_rate(vphydev->clkp); + dru_clk_rate = clk_get_rate(vphydev->dru_clk); dev_dbg(vphydev->dev,"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); + ret = clk_set_rate(vphydev->dru_clk, 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); + dru_clk_rate = clk_get_rate(vphydev->dru_clk); dev_dbg(vphydev->dev,"ref dru-clk rate = %lu\n", dru_clk_rate); } } diff --git a/hdmi/xilinx-hdmirx.c b/hdmi/xilinx-hdmirx.c index 076a4f9..6e23054 100644 --- a/hdmi/xilinx-hdmirx.c +++ b/hdmi/xilinx-hdmirx.c @@ -1799,7 +1799,7 @@ static int xhdmi_probe(struct platform_device *pdev) } /* video streaming bus clock */ - xhdmi->clk = devm_clk_get(xhdmi->dev, "video"); + xhdmi->clk = devm_clk_get(xhdmi->dev, "s_axis_video_aclk"); if (IS_ERR(xhdmi->clk)) { ret = PTR_ERR(xhdmi->clk); if (ret == -EPROBE_DEFER) @@ -1812,7 +1812,7 @@ static int xhdmi_probe(struct platform_device *pdev) clk_prepare_enable(xhdmi->clk); /* AXI lite register bus clock */ - xhdmi->axi_lite_clk = devm_clk_get(xhdmi->dev, "axi-lite"); + xhdmi->axi_lite_clk = devm_clk_get(xhdmi->dev, "s_axi_cpu_aclk"); if (IS_ERR(xhdmi->axi_lite_clk)) { ret = PTR_ERR(xhdmi->clk); if (ret == -EPROBE_DEFER) @@ -1855,16 +1855,16 @@ static int xhdmi_probe(struct platform_device *pdev) } if (xhdmi->config.Hdcp14.IsPresent) { - xhdmi->hdcp1x_irq = platform_get_irq_byname(pdev, "hdcp1x"); + xhdmi->hdcp1x_irq = platform_get_irq_byname(pdev, "hdcp14_irq"); dev_dbg(xhdmi->dev,"xhdmi->hdcp1x_irq = %d\n", xhdmi->hdcp1x_irq); - xhdmi->hdcp1x_timer_irq = platform_get_irq_byname(pdev, "hdcp1x-timer"); + xhdmi->hdcp1x_timer_irq = platform_get_irq_byname(pdev, "hdcp14_timer_irq"); dev_dbg(xhdmi->dev,"xhdmi->hdcp1x_timer_irq = %d\n", xhdmi->hdcp1x_timer_irq); } if (xhdmi->config.Hdcp22.IsPresent) { - xhdmi->hdcp22_irq = platform_get_irq_byname(pdev, "hdcp22"); + xhdmi->hdcp22_irq = platform_get_irq_byname(pdev, "hdcp22_irq"); dev_dbg(xhdmi->dev,"xhdmi->hdcp22_irq = %d\n", xhdmi->hdcp22_irq); - xhdmi->hdcp22_timer_irq = platform_get_irq_byname(pdev, "hdcp22-timer"); + xhdmi->hdcp22_timer_irq = platform_get_irq_byname(pdev, "hdcp22_timer_irq"); dev_dbg(xhdmi->dev,"xhdmi->hdcp22_timer_irq = %d\n", xhdmi->hdcp22_timer_irq); } diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index 1aa6437..9c3ec63 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -2316,7 +2316,7 @@ static int xlnx_drm_hdmi_probe(struct platform_device *pdev) /* 4 clock sources to be acquired and enabled */ /* acquire video streaming bus clock */ - xhdmi->clk = devm_clk_get(xhdmi->dev, "video"); + xhdmi->clk = devm_clk_get(xhdmi->dev, "s_axis_video_aclk"); if (IS_ERR(xhdmi->clk)) { ret = PTR_ERR(xhdmi->clk); if (ret == -EPROBE_DEFER) @@ -2329,7 +2329,7 @@ static int xlnx_drm_hdmi_probe(struct platform_device *pdev) clk_prepare_enable(xhdmi->clk); /* acquire axi-lite register bus clock */ - xhdmi->axi_lite_clk = devm_clk_get(xhdmi->dev, "axi-lite"); + xhdmi->axi_lite_clk = devm_clk_get(xhdmi->dev, "s_axi_cpu_aclk"); if (IS_ERR(xhdmi->axi_lite_clk)) { ret = PTR_ERR(xhdmi->clk); if (ret == -EPROBE_DEFER) @@ -2414,16 +2414,16 @@ static int xlnx_drm_hdmi_probe(struct platform_device *pdev) } if (xhdmi->config.Hdcp14.IsPresent) { - xhdmi->hdcp1x_irq = platform_get_irq_byname(pdev, "hdcp1x"); + xhdmi->hdcp1x_irq = platform_get_irq_byname(pdev, "hdcp14_irq"); dev_dbg(xhdmi->dev,"xhdmi->hdcp1x_irq = %d\n", xhdmi->hdcp1x_irq); - xhdmi->hdcp1x_timer_irq = platform_get_irq_byname(pdev, "hdcp1x-timer"); + xhdmi->hdcp1x_timer_irq = platform_get_irq_byname(pdev, "hdcp14_timer_irq"); dev_dbg(xhdmi->dev,"xhdmi->hdcp1x_timer_irq = %d\n", xhdmi->hdcp1x_timer_irq); } if (xhdmi->config.Hdcp22.IsPresent) { - xhdmi->hdcp22_irq = platform_get_irq_byname(pdev, "hdcp22"); + xhdmi->hdcp22_irq = platform_get_irq_byname(pdev, "hdcp22_irq"); dev_dbg(xhdmi->dev,"xhdmi->hdcp22_irq = %d\n", xhdmi->hdcp22_irq); - xhdmi->hdcp22_timer_irq = platform_get_irq_byname(pdev, "hdcp22-timer"); + xhdmi->hdcp22_timer_irq = platform_get_irq_byname(pdev, "hdcp22_timer_irq"); dev_dbg(xhdmi->dev,"xhdmi->hdcp22_timer_irq = %d\n", xhdmi->hdcp22_timer_irq); } From 53af3d91b065b0bf3a61d75d935085a80a9ccc20 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Tue, 9 Apr 2019 13:43:34 +0800 Subject: [PATCH 24/46] hdmitx: Changing tx hpd interrupt based Also solve the app hang issue on using drm_kms_helper_hotplug_event as apart from notifying user space about hotplug, it also calls output_poll_changed of drm device that is used to inform the fbdev helper of output changes. It is of no use here. Signed-off-by: Shikhar Mishra --- hdmi/xilinx_drm_hdmi.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index 9c3ec63..cb783d6 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -503,6 +503,7 @@ static void TxConnectCallback(void *CallbackRef) if (HdmiTxSsPtr->IsStreamConnected) { int xst_hdmi20; xhdmi->cable_connected = 1; + xhdmi->connector.status = connector_status_connected; /* Check HDMI sink version */ xst_hdmi20 = XV_HdmiTxSs_DetectHdmi20(HdmiTxSsPtr); dev_dbg(xhdmi->dev,"TxConnectCallback(): TX connected to HDMI %s Sink Device\n", @@ -521,12 +522,28 @@ static void TxConnectCallback(void *CallbackRef) else { dev_dbg(xhdmi->dev,"TxConnectCallback(): TX disconnected\n"); xhdmi->cable_connected = 0; + xhdmi->connector.status = connector_status_disconnected; xhdmi->have_edid = 0; xhdmi->is_hdmi_20_sink = 0; /* do not disable ibufds - stream will not go down*/ XVphy_IBufDsEnable(VphyPtr, 0, XVPHY_DIR_TX, (FALSE)); } xvphy_mutex_unlock(xhdmi->phy[0]); + + if(xhdmi->connector.dev) { + /* Not using drm_kms_helper_hotplug_event because apart from notifying + * user space about hotplug, it also calls output_poll_changed of drm device + * that is used to inform the fbdev helper of output changes. It is of no use + * here. Sometimes there were hang issue while running the application + * on using drm_kms_helper_hotplug_event API. */ + drm_sysfs_hotplug_event(xhdmi->connector.dev); + //drm_kms_helper_hotplug_event(xhdmi->drm_dev); + dev_dbg(xhdmi->dev,"Hotplug event sent to user space, Connect = %d", xhdmi->connector.status); + } else { + printk(KERN_WARNING "Not sending HOTPLUG event because " + "drm device is NULL as drm_connector_init is not called yet.\n"); + } + dev_dbg(xhdmi->dev,"TxConnectCallback() done\n"); } @@ -1954,11 +1971,9 @@ static int xlnx_drm_hdmi_create_connector(struct drm_encoder *encoder) struct drm_connector *connector = &xhdmi->connector; int ret; - connector->polled = DRM_CONNECTOR_POLL_HPD | - DRM_CONNECTOR_POLL_CONNECT | - DRM_CONNECTOR_POLL_DISCONNECT; - + connector->polled = DRM_CONNECTOR_POLL_HPD; connector->interlace_allowed = true; + ret = drm_connector_init(encoder->dev, connector, &xlnx_drm_hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA); @@ -1976,7 +1991,7 @@ static int xlnx_drm_hdmi_create_connector(struct drm_encoder *encoder) ret = drm_connector_attach_encoder(connector, encoder); if (ret) { dev_err(xhdmi->dev, - "Failed to attch encoder to connector (ret=%d)\n", ret); + "Failed to attach encoder to connector (ret=%d)\n", ret); return ret; } @@ -1991,6 +2006,11 @@ static int xlnx_drm_hdmi_bind(struct device *dev, struct device *master, struct drm_device *drm_dev = data; int ret; + /* NOTE - "xlnx-drm" is the platform driver + * "xlnx" is drm driver (Xilinx DRM KMS Driver) + * In above case - drm_dev->driver->name = xlnx + */ + /* * TODO: The possible CRTCs are 1 now as per current implementation of * HDMI tx driver. DRM framework can support more than one CRTCs and From 947f4f6adc157f0608ebf2ee954605ffffefd1c6 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Tue, 9 Apr 2019 13:45:16 +0800 Subject: [PATCH 25/46] tx: hdmirx: vphy: Driver update 14Mar2018 Signed-off-by: Shikhar Mishra --- hdmi/phy-vphy.c | 4 + hdmi/phy-xilinx-vphy/xvidc.c | 10 + hdmi/phy-xilinx-vphy/xvidc.h | 15 +- hdmi/phy-xilinx-vphy/xvphy.c | 51 ++++- hdmi/phy-xilinx-vphy/xvphy.h | 6 +- hdmi/phy-xilinx-vphy/xvphy_gthe4.c | 16 +- hdmi/phy-xilinx-vphy/xvphy_hdmi.c | 251 ++------------------- hdmi/phy-xilinx-vphy/xvphy_hdmi.h | 66 +++--- hdmi/phy-xilinx-vphy/xvphy_hdmi_intr.c | 38 +++- hdmi/phy-xilinx-vphy/xvphy_hw.h | 3 +- hdmi/phy-xilinx-vphy/xvphy_i.c | 92 ++++---- hdmi/phy-xilinx-vphy/xvphy_i.h | 10 +- hdmi/phy-xilinx-vphy/xvphy_intr.c | 2 +- hdmi/phy-xilinx-vphy/xvphy_log.c | 11 + hdmi/phy-xilinx-vphy/xvphy_mmcme4.c | 22 +- hdmi/xilinx-hdmi-rx/xv_hdmirx.c | 5 +- hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c | 10 +- hdmi/xilinx-hdmi-rx/xv_hdmirxss.c | 3 +- hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.c | 2 +- hdmi/xilinx-hdmi-tx/xv_hdmitx.c | 6 +- hdmi/xilinx-hdmi-tx/xv_hdmitxss.c | 4 +- hdmi/xilinx-hdmi-tx/xvtc.c | 58 ++--- hdmi/xilinx-hdmi-tx/xvtc.h | 2 + 23 files changed, 293 insertions(+), 394 deletions(-) diff --git a/hdmi/phy-vphy.c b/hdmi/phy-vphy.c index 0dbcdb6..8782952 100644 --- a/hdmi/phy-vphy.c +++ b/hdmi/phy-vphy.c @@ -176,6 +176,8 @@ static irqreturn_t xvphy_irq_handler(int irq, void *dev_id) 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_MMCM_LOCK_CHANGE | + XVPHY_INTR_HANDLER_TYPE_RX_MMCM_LOCK_CHANGE | XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT | XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); @@ -210,6 +212,8 @@ static irqreturn_t xvphy_irq_thread(int irq, void *dev_id) 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_MMCM_LOCK_CHANGE | + XVPHY_INTR_HANDLER_TYPE_RX_MMCM_LOCK_CHANGE | XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT | XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); diff --git a/hdmi/phy-xilinx-vphy/xvidc.c b/hdmi/phy-xilinx-vphy/xvidc.c index 63a12a8..64dff26 100644 --- a/hdmi/phy-xilinx-vphy/xvidc.c +++ b/hdmi/phy-xilinx-vphy/xvidc.c @@ -826,6 +826,16 @@ const char *XVidC_GetColorFormatStr(XVidC_ColorFormat ColorFormatId) case XVIDC_CSF_MEM_BGR8: return ("BGR8"); case XVIDC_CSF_YCBCR_422: return ("YCBCR_422"); case XVIDC_CSF_YCBCR_420: return ("YCBCR_420"); + case XVIDC_CSF_MEM_RGBX12: return ("RGBX12"); + case XVIDC_CSF_MEM_RGB16: return ("RGB16"); + case XVIDC_CSF_MEM_YUVX12: return ("YUVX12"); + case XVIDC_CSF_MEM_YUV16: return ("YUV16"); + case XVIDC_CSF_MEM_Y_UV12: return ("Y_UV12"); + case XVIDC_CSF_MEM_Y_UV16: return ("Y_UV16"); + case XVIDC_CSF_MEM_Y_UV12_420: return ("Y_UV12_420"); + case XVIDC_CSF_MEM_Y_UV16_420: return ("Y_UV16_420"); + case XVIDC_CSF_MEM_Y12: return ("Y12"); + case XVIDC_CSF_MEM_Y16: return ("Y16"); default: return ("Color space format not supported"); } diff --git a/hdmi/phy-xilinx-vphy/xvidc.h b/hdmi/phy-xilinx-vphy/xvidc.h index bb7c3e5..a4d1cd7 100644 --- a/hdmi/phy-xilinx-vphy/xvidc.h +++ b/hdmi/phy-xilinx-vphy/xvidc.h @@ -60,6 +60,7 @@ * jsr 02/22/18 Added XVIDC_CSF_YCBCR_420 color space format * vyc 04/04/18 Added BGR8 memory format * 4.5 jsr 07/03/18 Added XVIDC_VM_720x486_60_I video format + * 4.5 yas 03/08/19 Added support for frame rates 144HZ and 240HZ * * *******************************************************************************/ @@ -310,7 +311,9 @@ typedef enum { XVIDC_FR_96HZ = 96, XVIDC_FR_100HZ = 100, XVIDC_FR_120HZ = 120, - XVIDC_FR_NUM_SUPPORTED = 18, + XVIDC_FR_144HZ = 144, + XVIDC_FR_240HZ = 240, + XVIDC_FR_NUM_SUPPORTED = 20, XVIDC_FR_UNKNOWN } XVidC_FrameRate; @@ -377,6 +380,16 @@ typedef enum { XVIDC_CSF_MEM_BGRX8, // [31:0] X:R:G:B 8:8:8:8 XVIDC_CSF_MEM_UYVY8, // [31:0] Y:V:Y:U 8:8:8:8 XVIDC_CSF_MEM_BGR8, // [23:0] R:G:B 8:8:8 + XVIDC_CSF_MEM_RGBX12, // [39:0] x:R:G:B 4:12:12:12 + XVIDC_CSF_MEM_YUVX12, // [39:0] x:V:U:Y 4:12:12:12 + XVIDC_CSF_MEM_Y_UV12, // [23:0] Y:Y 12:12, [23:0] V:U 12:12 + XVIDC_CSF_MEM_Y_UV12_420, // [23:0] Y:Y 12:12, [23:0] V:U 12:12 + XVIDC_CSF_MEM_Y12, // [39:0] x:Y2:Y1:Y0 4:12:12:12 + XVIDC_CSF_MEM_RGB16, // [47:0] R:G:B 16:16:16 + XVIDC_CSF_MEM_YUV16, // [47:0] V:U:Y 16:16:16 + XVIDC_CSF_MEM_Y_UV16, // [31:0] Y:Y 16:16, [31:0] V:U 16:16 + XVIDC_CSF_MEM_Y_UV16_420, // [31:0] Y:Y 16:16, [31:0] V:U 16:16 + XVIDC_CSF_MEM_Y16, // [47:0] Y2:Y1:Y0 16:16:16 XVIDC_CSF_MEM_END, // End of memory formats /* Streaming formats with components re-ordered */ diff --git a/hdmi/phy-xilinx-vphy/xvphy.c b/hdmi/phy-xilinx-vphy/xvphy.c index 59d0ac5..540b6cb 100644 --- a/hdmi/phy-xilinx-vphy/xvphy.c +++ b/hdmi/phy-xilinx-vphy/xvphy.c @@ -65,6 +65,8 @@ * 23/07/18 Added APIs XVphy_SetTxVoltageSwing and * XVphy_SetTxPreEmphasis from xvphy_i.c/h * Added XVphy_SetTxPostCursor API + * 1.9 gm 14/05/18 Added XVphy_SetRxLpm from xvphy_i.c/.h + * * * *******************************************************************************/ @@ -1061,6 +1063,51 @@ void XVphy_SetTxPostCursor(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, XVphy_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); } +/*****************************************************************************/ +/** +* 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 initiate a write DRP transaction. It is a wrapper around @@ -1203,8 +1250,8 @@ void XVphy_MmcmStart(XVphy *InstancePtr, u8 QuadId, XVphy_DirectionType Dir) #endif #if defined (XPAR_XV_HDMITX_0_DEVICE_ID) || defined (XPAR_XV_HDMIRX_0_DEVICE_ID) #if defined (XPAR_XDP_0_DEVICE_ID) - } else if (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI || - InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + } else if (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX) || + XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX)) { #endif XVphy_Mmcm *MmcmPtr; diff --git a/hdmi/phy-xilinx-vphy/xvphy.h b/hdmi/phy-xilinx-vphy/xvphy.h index 2c8c420..99696ef 100644 --- a/hdmi/phy-xilinx-vphy/xvphy.h +++ b/hdmi/phy-xilinx-vphy/xvphy.h @@ -85,6 +85,8 @@ * 23/07/18 Added APIs XVphy_SetTxVoltageSwing and * XVphy_SetTxPreEmphasis from xvphy_i.c/h * Added XVphy_SetTxPostCursor API + * 1.9 gm 14/05/18 Added XVphy_SetRxLpm from xvphy_i.c/.h + * Removed deprecated XVphy_HdmiInitialize API * * *******************************************************************************/ @@ -868,6 +870,8 @@ void XVphy_SetTxPreEmphasis(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, u8 Pe); void XVphy_SetTxPostCursor(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, u8 Pc); +void XVphy_SetRxLpm(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, + XVphy_DirectionType Dir, u8 Enable); /* xvphy.c: GT/MMCM DRP access. */ u32 XVphy_DrpWr(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, @@ -923,8 +927,6 @@ u32 XVphy_DpInitialize(XVphy *InstancePtr, XVphy_Config *CfgPtr, u8 QuadId, XVphy_PllRefClkSelType QpllRefClkSel, XVphy_PllType TxPllSelect, XVphy_PllType RxPllSelect, u8 LinkRate); -u32 XVphy_HdmiInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_Config *CfgPtr, - u32 SystemFrequency) __attribute__ ((deprecated)); u32 XVphy_Hdmi_CfgInitialize(XVphy *InstancePtr, u8 QuadId, XVphy_Config *CfgPtr); u32 XVphy_SetHdmiTxParam(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, diff --git a/hdmi/phy-xilinx-vphy/xvphy_gthe4.c b/hdmi/phy-xilinx-vphy/xvphy_gthe4.c index 5509f62..c9cc357 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_gthe4.c +++ b/hdmi/phy-xilinx-vphy/xvphy_gthe4.c @@ -199,7 +199,7 @@ u32 XVphy_Gthe4CfgSetCdr(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) ChPtr->PllParams.Cdr[3] = 0x0000; ChPtr->PllParams.Cdr[4] = 0x0000; - if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + if (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX)) { /* RxOutDiv = 1 => Cdr[2] = 0x0269 * RxOutDiv = 2 => Cdr[2] = 0x0259 * RxOutDiv = 4 => Cdr[2] = 0x0249 @@ -456,8 +456,8 @@ u32 XVphy_Gthe4ClkCmnReconfig(XVphy *InstancePtr, u8 QuadId, Status |= XVphy_DrpWr(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)) { + if ((XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX)) || + (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX))) { QpllxVcoRateMHz = XVphy_GetPllVcoFreqHz(InstancePtr, QuadId, CmnId, XVphy_IsTxUsingQpll(InstancePtr, QuadId, CmnId) ? @@ -599,7 +599,7 @@ u32 XVphy_Gthe4RxChReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) } } - if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + if (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX)) { /* RX_INT_DATAWIDTH */ Status |= XVphy_DrpRd(InstancePtr, QuadId, ChId, 0x66, &DrpVal); DrpVal &= ~(0x3); @@ -764,7 +764,7 @@ u32 XVphy_Gthe4TxChReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) u32 Status = XST_SUCCESS; ReturnVal = XVphy_Gthe4TxPllRefClkDiv1Reconfig(InstancePtr, QuadId, ChId); - if (InstancePtr->Config.TxProtocol != XVPHY_PROTOCOL_HDMI) { + if (!XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX)) { return ReturnVal; } @@ -789,7 +789,7 @@ u32 XVphy_Gthe4TxChReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) break; } - if (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) { + if (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX)) { ChPtr = &InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]; /* TX_INT_DATAWIDTH */ @@ -893,7 +893,7 @@ u32 XVphy_Gthe4TxPllRefClkDiv1Reconfig(XVphy *InstancePtr, u8 QuadId, XVphy_Channel *PllPtr = &InstancePtr->Quads[QuadId]. Plls[XVPHY_CH2IDX(ChId)]; - if (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) { + if (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX)) { TxRefClkHz = InstancePtr->HdmiTxRefClkHz; } else { @@ -935,7 +935,7 @@ u32 XVphy_Gthe4RxPllRefClkDiv1Reconfig(XVphy *InstancePtr, u8 QuadId, XVphy_Channel *PllPtr = &InstancePtr->Quads[QuadId]. Plls[XVPHY_CH2IDX(ChId)]; - if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + if (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX)) { RxRefClkHz = InstancePtr->HdmiRxRefClkHz; } else { diff --git a/hdmi/phy-xilinx-vphy/xvphy_hdmi.c b/hdmi/phy-xilinx-vphy/xvphy_hdmi.c index 1267f36..8487d59 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_hdmi.c +++ b/hdmi/phy-xilinx-vphy/xvphy_hdmi.c @@ -72,6 +72,8 @@ * Removed XVphy_DruSetGain API * 1.8 gm 05/14/18 Fixed a bug in XVphy_HdmiQpllParam where linerate is * obtained from CH1 instead of QPLL0/1 + * 1.9 gm 14/05/18 Added TX and RX MMCM lock event logging + * Removed deprecated XVphy_HdmiInitialize API * * * @@ -110,213 +112,6 @@ 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. - * - * @deprecated XVphy_HdmiInitialize will be deprecated in 2018.3 and replaced - * by XVphy_Hdmi_CfgInitialize. - * -*******************************************************************************/ -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_MMCM_LOCK_CHANGE); - XVphy_IntrDisable(InstancePtr, - XVPHY_INTR_HANDLER_TYPE_RX_MMCM_LOCK_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); - - /* Indicate of QPLL is present in design */ - if ((XVphy_IsTxUsingQpll(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CH1) && - (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI)) || - (XVphy_IsRxUsingQpll(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CH1) && - (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI))) { - InstancePtr->HdmiIsQpllPresent = TRUE; - } else { - InstancePtr->HdmiIsQpllPresent = FALSE; - } - - if ((InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE3) || - (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE4) || - (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTYE4)) { - 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); - if (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) { - XVphy_IBufDsEnable(InstancePtr, QuadId, XVPHY_DIR_TX, (FALSE)); - } - if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { - 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); - } - - 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++) { -#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE3 || \ - XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE4 || \ - XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTYE4) - XVphy_SetTxVoltageSwing(InstancePtr, QuadId, (XVphy_ChannelId)Id, 0xC); -#else - XVphy_SetTxVoltageSwing(InstancePtr, QuadId, (XVphy_ChannelId)Id, 0x1); -#endif - 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); -#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTXE2) - XVphy_IntrEnable(InstancePtr, - XVPHY_INTR_HANDLER_TYPE_TX_MMCM_LOCK_CHANGE); -#endif - 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 initializes the Video PHY for HDMI. @@ -418,9 +213,9 @@ u32 XVphy_Hdmi_CfgInitialize(XVphy *InstancePtr, u8 QuadId, /* Indicate of QPLL is present in design */ if ((XVphy_IsTxUsingQpll(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CH1) && - (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI)) || + (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX))) || (XVphy_IsRxUsingQpll(InstancePtr, QuadId, XVPHY_CHANNEL_ID_CH1) && - (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI))) { + (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX)))) { InstancePtr->HdmiIsQpllPresent = TRUE; } else { InstancePtr->HdmiIsQpllPresent = FALSE; @@ -451,10 +246,10 @@ u32 XVphy_Hdmi_CfgInitialize(XVphy *InstancePtr, u8 QuadId, } XVphy_MmcmReset(InstancePtr, QuadId, XVPHY_DIR_TX, TRUE); XVphy_MmcmReset(InstancePtr, QuadId, XVPHY_DIR_RX, TRUE); - if (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) { + if (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX)) { XVphy_IBufDsEnable(InstancePtr, QuadId, XVPHY_DIR_TX, (FALSE)); } - if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + if (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX)) { XVphy_IBufDsEnable(InstancePtr, QuadId, XVPHY_DIR_RX, (FALSE)); } @@ -501,14 +296,14 @@ u32 XVphy_Hdmi_CfgInitialize(XVphy *InstancePtr, u8 QuadId, XVPHY_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE); XVphy_IntrEnable(InstancePtr, XVPHY_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE); -#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTXE2) XVphy_IntrEnable(InstancePtr, XVPHY_INTR_HANDLER_TYPE_TX_MMCM_LOCK_CHANGE); -#endif XVphy_IntrEnable(InstancePtr, XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT); XVphy_IntrEnable(InstancePtr, XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); + XVphy_IntrEnable(InstancePtr, + XVPHY_INTR_HANDLER_TYPE_RX_MMCM_LOCK_CHANGE); XVphy_ClkDetEnable(InstancePtr, TRUE); /* Set the flag to indicate the driver is. */ @@ -2463,7 +2258,7 @@ int XVphy_HdmiDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, } #endif - if (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) { + if (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX)) { if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2) { #if ((XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE3) || \ (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE4) || \ @@ -2509,7 +2304,7 @@ int XVphy_HdmiDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, } } - if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + if (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX)) { if (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTPE2) { strSize += scnprintf(buff+strSize, buff_size-strSize, "RX: PLL%d\n", (TxUsesPll0 ? 1 : 0)); @@ -2550,7 +2345,7 @@ int XVphy_HdmiDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, } } - if (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) { + if (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX)) { strSize += scnprintf(buff+strSize, buff_size-strSize, "TX state: "); switch (InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)].TxState) { @@ -2598,7 +2393,7 @@ int XVphy_HdmiDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, } } - if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + if (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX)) { strSize += scnprintf(buff+strSize, buff_size-strSize, "RX state: "); switch (InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)].RxState) { @@ -2654,9 +2449,9 @@ int XVphy_HdmiDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, strSize += scnprintf(buff+strSize, buff_size-strSize, "\n"); if (InstancePtr->Config.XcvrType != XVPHY_GT_TYPE_GTPE2) { if ((XVphy_IsTxUsingQpll(InstancePtr, QuadId, ChId) && - (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI)) || + (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX))) || (XVphy_IsRxUsingQpll(InstancePtr, QuadId, ChId) && - (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI))) { + (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX)))) { #if ((XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE3) || \ (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTHE4) || \ (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTYE4)) @@ -2676,9 +2471,9 @@ int XVphy_HdmiDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, } if ((XVphy_IsTxUsingCpll(InstancePtr, QuadId, ChId) && - (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI)) || + (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX))) || (XVphy_IsRxUsingCpll(InstancePtr, QuadId, ChId) && - (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI))) { + (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX)))) { strSize += scnprintf(buff+strSize, buff_size-strSize, "CPLL settings\n" \ "-------------\n" \ @@ -2691,10 +2486,10 @@ int XVphy_HdmiDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, else { if (((ChPtr->TxDataRefClkSel == XVPHY_SYSCLKSELDATA_TYPE_PLL0_OUTCLK) && - (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI)) || + (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX))) || ((ChPtr->RxDataRefClkSel == XVPHY_SYSCLKSELDATA_TYPE_PLL0_OUTCLK) && - (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI))) { + (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX)))) { CmnId = XVPHY_CHANNEL_ID_CMN0; strSize += scnprintf(buff+strSize, buff_size-strSize, "PLL0 settings\n" \ @@ -2712,10 +2507,10 @@ int XVphy_HdmiDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, if (((ChPtr->TxDataRefClkSel == XVPHY_SYSCLKSELDATA_TYPE_PLL1_OUTCLK) && - (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI)) || + (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX))) || ((ChPtr->RxDataRefClkSel == XVPHY_SYSCLKSELDATA_TYPE_PLL1_OUTCLK) && - (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI))) { + (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX)))) { CmnId = XVPHY_CHANNEL_ID_CMN1; strSize += scnprintf(buff+strSize, buff_size-strSize, "PLL1 settings\n" @@ -2731,7 +2526,7 @@ int XVphy_HdmiDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, } } - if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + if (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX)) { strSize += scnprintf(buff+strSize, buff_size-strSize, "RX MMCM settings\n" "-------------\n" @@ -2744,7 +2539,7 @@ int XVphy_HdmiDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, InstancePtr->Quads[QuadId].RxMmcm.ClkOut2Div); } - if (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) { + if (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX)) { strSize += scnprintf(buff+strSize, buff_size-strSize, "TX MMCM settings\n" \ "-------------\n" \ @@ -2758,7 +2553,7 @@ int XVphy_HdmiDebugInfo(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, } if ((InstancePtr->Config.DruIsPresent) && - (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI)) { + (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX))) { strSize += scnprintf(buff+strSize, buff_size-strSize, "DRU Settings\n" \ "-------------\n"); diff --git a/hdmi/phy-xilinx-vphy/xvphy_hdmi.h b/hdmi/phy-xilinx-vphy/xvphy_hdmi.h index 8bae360..d606a50 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_hdmi.h +++ b/hdmi/phy-xilinx-vphy/xvphy_hdmi.h @@ -50,11 +50,11 @@ /************************** Constant Definitions ******************************/ -#define XVPHY_HDMI_GTYE4_DRU_LRATE 2500000000U -#define XVPHY_HDMI_GTYE4_DRU_REFCLK 156250000LL -#define XVPHY_HDMI_GTYE4_DRU_REFCLK_MIN 156240000LL -#define XVPHY_HDMI_GTYE4_DRU_REFCLK_MAX 156260000LL -#define XVPHY_HDMI_GTYE4_PLL_SCALE 1000 +#define XVPHY_HDMI_GTYE4_DRU_LRATE 2500000000U +#define XVPHY_HDMI_GTYE4_DRU_REFCLK 156250000LL +#define XVPHY_HDMI_GTYE4_DRU_REFCLK_MIN 156240000LL +#define XVPHY_HDMI_GTYE4_DRU_REFCLK_MAX 156260000LL +#define XVPHY_HDMI_GTYE4_PLL_SCALE 1000 #define XVPHY_HDMI_GTYE4_QPLL0_REFCLK_MIN 61250000LL #define XVPHY_HDMI_GTYE4_QPLL1_REFCLK_MIN 50000000LL #define XVPHY_HDMI_GTYE4_CPLL_REFCLK_MIN 50000000LL @@ -65,11 +65,11 @@ #define XVPHY_HDMI_GTYE4_RX_MMCM_FVCO_MIN 800000000U #define XVPHY_HDMI_GTYE4_RX_MMCM_FVCO_MAX 1600000000U -#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_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 50000000LL @@ -80,11 +80,11 @@ #define XVPHY_HDMI_GTHE4_RX_MMCM_FVCO_MIN 800000000U #define XVPHY_HDMI_GTHE4_RX_MMCM_FVCO_MAX 1600000000U -#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_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 50000000LL @@ -95,11 +95,11 @@ #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_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 @@ -109,13 +109,13 @@ #define XVPHY_HDMI_GTHE2_RX_MMCM_FVCO_MIN 600000000U #define XVPHY_HDMI_GTHE2_RX_MMCM_FVCO_MAX 1200000000U -#define XVPHY_HDMI_GTXE2_DRU_LRATE_QPLL 2000000000U -#define XVPHY_HDMI_GTXE2_DRU_LRATE_CPLL 2500000000U -#define XVPHY_HDMI_GTXE2_DRU_LRATE 2500000000U -#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_DRU_LRATE_QPLL 2000000000U +#define XVPHY_HDMI_GTXE2_DRU_LRATE_CPLL 2500000000U +#define XVPHY_HDMI_GTXE2_DRU_LRATE 2500000000U +#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 @@ -125,11 +125,11 @@ #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_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 @@ -168,4 +168,4 @@ void XVphy_HdmiIntrHandlerCallbackInit(XVphy *InstancePtr); #endif /* XVPHY_HDMI_H_ */ #endif -/** @} */ \ No newline at end of file +/** @} */ diff --git a/hdmi/phy-xilinx-vphy/xvphy_hdmi_intr.c b/hdmi/phy-xilinx-vphy/xvphy_hdmi_intr.c index 48af63b..5a4e728 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_hdmi_intr.c +++ b/hdmi/phy-xilinx-vphy/xvphy_hdmi_intr.c @@ -48,6 +48,7 @@ * Improved TX initialization flow in bonded mode to * reset GT TX only when PLL and MMCM are locked * 1.7 gm 13/09/17 Added GTYE4 support + * 1.9 gm 14/05/18 Added TX and RX MMCM lock event logging * * *******************************************************************************/ @@ -698,7 +699,7 @@ void XVphy_HdmiTxClkDetFreqChangeHandler(XVphy *InstancePtr) XVphy_MmcmLockedMaskEnable(InstancePtr, 0, XVPHY_DIR_TX, TRUE); /* Disable TX MMCM. */ - //XVphy_MmcmPowerDown(InstancePtr, 0, XVPHY_DIR_TX, TRUE); + /* XVphy_MmcmPowerDown(InstancePtr, 0, XVPHY_DIR_TX, TRUE); */ /* Clear TX timer. */ XVphy_ClkDetTimerClear(InstancePtr, 0, XVPHY_DIR_TX); @@ -902,9 +903,9 @@ void XVphy_HdmiTxTimerTimeoutHandler(XVphy *InstancePtr) (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE4) || (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTYE4)) { XVphy_SetBufgGtDiv(InstancePtr, XVPHY_DIR_TX, - (PllType == XVPHY_PLL_TYPE_CPLL) ? - InstancePtr->Quads[0].Plls[0].TxOutDiv : - InstancePtr->Quads[0].Plls[0].TxOutDiv / 2); + (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); @@ -1079,7 +1080,6 @@ void XVphy_HdmiRxTimerTimeoutHandler(XVphy *InstancePtr) } } -#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTXE2) /*****************************************************************************/ /** * This function is the handler for TX MMCM Lock events. @@ -1093,12 +1093,15 @@ void XVphy_HdmiRxTimerTimeoutHandler(XVphy *InstancePtr) ******************************************************************************/ void XVphy_HdmiTxMmcmLockHandler(XVphy *InstancePtr) { +#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTXE2) XVphy_ChannelId ChId; XVphy_PllType TxPllType; u8 Id, Id0, Id1; +#endif XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_TXPLL_LOCK, 1); +#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTXE2) /* Determine PLL type. */ TxPllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_TX, XVPHY_CHANNEL_ID_CH1); @@ -1123,8 +1126,26 @@ void XVphy_HdmiTxMmcmLockHandler(XVphy *InstancePtr) TxState = XVPHY_GT_STATE_RESET; } } -} #endif +} + +/*****************************************************************************/ +/** +* This function is the handler for RX MMCM Lock events. +* +* @param InstancePtr is a pointer to the VPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XVphy_HdmiRxMmcmLockHandler(XVphy *InstancePtr) +{ + + XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_RXPLL_LOCK, 1); + +} /*****************************************************************************/ /** @@ -1161,11 +1182,12 @@ void XVphy_HdmiGtHandler(XVphy *InstancePtr) TxStatePtr = &InstancePtr->Quads[QuadId].Ch1.TxState; RxStatePtr = &InstancePtr->Quads[QuadId].Ch1.RxState; -#if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTXE2) if (Event & XVPHY_INTR_TXMMCMUSRCLK_LOCK_MASK) { XVphy_HdmiTxMmcmLockHandler(InstancePtr); } -#endif + if (Event & XVPHY_INTR_RXMMCMUSRCLK_LOCK_MASK) { + XVphy_HdmiRxMmcmLockHandler(InstancePtr); + } if ((Event & XVPHY_INTR_QPLL0_LOCK_MASK) || (Event & XVPHY_INTR_QPLL1_LOCK_MASK)) { #if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTPE2) diff --git a/hdmi/phy-xilinx-vphy/xvphy_hw.h b/hdmi/phy-xilinx-vphy/xvphy_hw.h index 2169afa..3cc2efd 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_hw.h +++ b/hdmi/phy-xilinx-vphy/xvphy_hw.h @@ -524,6 +524,7 @@ #define XVPHY_MMCM_USRCLK_CTRL_LOCKED_MASK 0x200 #define XVPHY_MMCM_USRCLK_CTRL_PWRDWN_MASK 0x400 #define XVPHY_MMCM_USRCLK_CTRL_LOCKED_MASK_MASK 0x800 +#define XVPHY_MMCM_USRCLK_CTRL_CLKINSEL_MASK 0x1000 /* 0x124, 0x144: MMCM_TXUSRCLK_REG1, MMCM_RXUSRCLK_REG1 */ #define XVPHY_MMCM_USRCLK_REG1_DIVCLK_MASK \ 0x00000FF @@ -629,4 +630,4 @@ XVphy_Out32((BaseAddress) + (RegOffset), (Data)) #endif /* XVPHY_HW_H_ */ -/** @} */ \ No newline at end of file +/** @} */ diff --git a/hdmi/phy-xilinx-vphy/xvphy_i.c b/hdmi/phy-xilinx-vphy/xvphy_i.c index c1ad086..cc141df 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_i.c +++ b/hdmi/phy-xilinx-vphy/xvphy_i.c @@ -36,6 +36,8 @@ * 1.7 gm 13/09/17 Added GTYE4 support * 1.8 gm 23/07/18 Moved APIs XVphy_SetTxVoltageSwing and * XVphy_SetTxPreEmphasis to xvphy.c/h + * 05/09/18 Added XVphy_GetRefClkSourcesCount API + * 1.9 gm 11/04/18 Added XVphy_IsHDMI API * * *******************************************************************************/ @@ -55,51 +57,6 @@ /**************************** 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 writes the current software configuration for the reference @@ -457,11 +414,11 @@ u32 XVphy_IsPllLocked(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) RxPllType = XVphy_GetPllType(InstancePtr, 0, XVPHY_DIR_RX, XVPHY_CHANNEL_ID_CH1); if (RxPllType == XVPHY_PLL_TYPE_CPLL && - InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX)) { MaskVal = XVPHY_PLL_LOCK_STATUS_CPLL_HDMI_MASK; } else if (TxPllType == XVPHY_PLL_TYPE_CPLL && - InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) { + XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX)) { MaskVal = XVPHY_PLL_LOCK_STATUS_CPLL_HDMI_MASK; } else { @@ -950,8 +907,8 @@ u32 XVphy_ClkReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) (XVphy_ChannelId)Id); } else if (XVPHY_ISCMN(ChId)) { - if (((InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) || - (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI)) && + if (((XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX)) || + (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX))) && (InstancePtr->HdmiIsQpllPresent == FALSE)) { XVphy_LogWrite(InstancePtr, XVPHY_LOG_EVT_NO_QPLL_ERR, 1); XVphy_CfgErrIntr(InstancePtr, XVPHY_ERR_NO_QPLL, 1); @@ -1008,8 +965,8 @@ void XVphy_Ch2Ids(XVphy *InstancePtr, XVphy_ChannelId ChId, if (ChId == XVPHY_CHANNEL_ID_CHA) { *Id0 = XVPHY_CHANNEL_ID_CH1; - if ((InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) || - (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI)) { + if ((XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX)) || + (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX))) { if (InstancePtr->Config.UseGtAsTxTmdsClk == TRUE) { *Id1 = XVPHY_CHANNEL_ID_CH4; } @@ -1231,7 +1188,7 @@ u64 XVphy_GetPllVcoFreqHz(XVphy *InstancePtr, u8 QuadId, Plls[XVPHY_CH2IDX(ChId)]; if (Dir == XVPHY_DIR_TX) { - if (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) { + if (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_TX)) { PllRefClkHz = InstancePtr->HdmiTxRefClkHz; } else { @@ -1240,7 +1197,7 @@ u64 XVphy_GetPllVcoFreqHz(XVphy *InstancePtr, u8 QuadId, } } else { - if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + if (XVphy_IsHDMI(InstancePtr, XVPHY_DIR_RX)) { #if defined (XPAR_XV_HDMITX_0_DEVICE_ID) || defined (XPAR_XV_HDMIRX_0_DEVICE_ID) if (InstancePtr->HdmiRxDruIsEnabled) { PllRefClkHz = XVphy_DruGetRefClkFreqHz(InstancePtr); @@ -1258,7 +1215,7 @@ u64 XVphy_GetPllVcoFreqHz(XVphy *InstancePtr, u8 QuadId, } } - PllxVcoRateHz = (PllRefClkHz * + PllxVcoRateHz = (u64)(PllRefClkHz * InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]. PllParams.N1FbDiv * InstancePtr->Quads[QuadId].Plls[XVPHY_CH2IDX(ChId)]. @@ -1485,6 +1442,33 @@ u32 XVphy_TxChReconfig(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId) } #endif +/*****************************************************************************/ +/** +* This function checks if Instance is HDMI 2.0 or HDMI 2.1 +* +* @param InstancePtr is a pointer to the VPHY instance. +* @param Dir is an indicator for RX or TX. +* +* @return TRUE if HDMI 2.0 or 2.1 else FALSE. +* +* @note None. +* +******************************************************************************/ +u8 XVphy_IsHDMI(XVphy *InstancePtr, XVphy_DirectionType Dir) +{ + if (Dir == XVPHY_DIR_TX) { + if (InstancePtr->Config.TxProtocol == XVPHY_PROTOCOL_HDMI) { + return TRUE; + } + } else { /* Dir == XVPHY_DIR_RX */ + if (InstancePtr->Config.RxProtocol == XVPHY_PROTOCOL_HDMI) { + return TRUE; + } + } + + return FALSE; +} + /*****************************************************************************/ /** * This function is the error condition handler diff --git a/hdmi/phy-xilinx-vphy/xvphy_i.h b/hdmi/phy-xilinx-vphy/xvphy_i.h index 5ff7d68..47a9ebb 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_i.h +++ b/hdmi/phy-xilinx-vphy/xvphy_i.h @@ -39,6 +39,8 @@ * 1.8 gm 23/07/18 Moved APIs XVphy_SetTxVoltageSwing and * XVphy_SetTxPreEmphasis to xvphy.c/h * 05/09/18 Added XVphy_GetRefClkSourcesCount API + * 1.9 gm 11/04/18 Added XVphy_IsHDMI API + * Moved XVphy_SetRxLpm to xvphy.c/.h * * * @addtogroup xvphy @@ -70,10 +72,6 @@ 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); - /* xvphy.c: Channel configuration functions - setters. */ u32 XVphy_WriteCfgRefClkSelReg(XVphy *InstancePtr, u8 QuadId); void XVphy_CfgPllRefClkSel(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, @@ -131,6 +129,10 @@ u64 XVphy_GetPllVcoFreqHz(XVphy *InstancePtr, u8 QuadId, XVphy_ChannelId ChId, XVphy_DirectionType Dir); u8 XVphy_GetRefClkSourcesCount(XVphy *InstancePtr); +u8 XVphy_IsHDMI(XVphy *InstancePtr, XVphy_DirectionType Dir); +void XVphy_HdmiTxTimerTimeoutHandler(XVphy *InstancePtr); +void XVphy_HdmiRxTimerTimeoutHandler(XVphy *InstancePtr); + void XVphy_ErrorHandler(XVphy *InstancePtr); #if (XPAR_VPHY_0_TRANSCEIVER == XVPHY_GTXE2) void XVphy_PllLayoutErrorHandler(XVphy *InstancePtr); diff --git a/hdmi/phy-xilinx-vphy/xvphy_intr.c b/hdmi/phy-xilinx-vphy/xvphy_intr.c index da7820a..dee1fb9 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_intr.c +++ b/hdmi/phy-xilinx-vphy/xvphy_intr.c @@ -43,7 +43,7 @@ /******************************************************************************/ /** - * This function enables interrupts associated with the specified interrupt type. + * 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. diff --git a/hdmi/phy-xilinx-vphy/xvphy_log.c b/hdmi/phy-xilinx-vphy/xvphy_log.c index c414d1d..a1fe512 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_log.c +++ b/hdmi/phy-xilinx-vphy/xvphy_log.c @@ -50,6 +50,17 @@ #include "xvphy.h" #include "xvphy_i.h" +/************************** Constant Definitions *****************************/ +#define ANSI_COLOR_RED "\x1b[31m" +#define ANSI_COLOR_GREEN "\x1b[32m" +#define ANSI_COLOR_YELLOW "\x1b[33m" +#define ANSI_COLOR_BLUE "\x1b[34m" +#define ANSI_COLOR_MAGENTA "\x1b[35m" +#define ANSI_COLOR_CYAN "\x1b[36m" +#define ANSI_COLOR_WHITE "\x1b[37m" +#define ANSI_COLOR_RESET "\x1b[0m" + + /**************************** Function Prototypes *****************************/ /**************************** Function Definitions ****************************/ diff --git a/hdmi/phy-xilinx-vphy/xvphy_mmcme4.c b/hdmi/phy-xilinx-vphy/xvphy_mmcme4.c index 10497b8..6064e80 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_mmcme4.c +++ b/hdmi/phy-xilinx-vphy/xvphy_mmcme4.c @@ -468,10 +468,10 @@ u32 XVphy_MmcmWriteParameters(XVphy *InstancePtr, u8 QuadId, } - //Write Power Register Value + /* Write Power Register Value */ XVphy_DrpWr(InstancePtr, QuadId, ChId, 0x27, 0xFFFF); - //Write CLKFBOUT Reg1 & Reg2 Values + /* Write CLKFBOUT Reg1 & Reg2 Values */ DrpVal32 = XVphy_Mmcme4DividerEncoding(MMCM_CLKFBOUT_MULT_F, MmcmParams->ClkFbOutMult); XVphy_DrpWr(InstancePtr, QuadId, ChId, 0x14, @@ -479,13 +479,13 @@ u32 XVphy_MmcmWriteParameters(XVphy *InstancePtr, u8 QuadId, XVphy_DrpWr(InstancePtr, QuadId, ChId, 0x15, (u16)((DrpVal32 >> 16) & 0xFFFF)); - //Write DIVCLK_DIVIDE Value + /* Write DIVCLK_DIVIDE Value */ DrpVal32 = XVphy_Mmcme4DividerEncoding(MMCM_DIVCLK_DIVIDE, MmcmParams->DivClkDivide) ; XVphy_DrpWr(InstancePtr, QuadId, ChId, 0x16, (u16)(DrpVal32 & 0xFFFF)); - //Write CLKOUT0 Reg1 & Reg2 Values + /* Write CLKOUT0 Reg1 & Reg2 Values */ DrpVal32 = XVphy_Mmcme4DividerEncoding(MMCM_CLKOUT_DIVIDE, MmcmParams->ClkOut0Div); XVphy_DrpWr(InstancePtr, QuadId, ChId, 0x08, @@ -493,7 +493,7 @@ u32 XVphy_MmcmWriteParameters(XVphy *InstancePtr, u8 QuadId, XVphy_DrpWr(InstancePtr, QuadId, ChId, 0x09, (u16)((DrpVal32 >> 16) & 0xFFFF)); - //Write CLKOUT1 Reg1 & Reg2 Values + /* Write CLKOUT1 Reg1 & Reg2 Values */ DrpVal32 = XVphy_Mmcme4DividerEncoding(MMCM_CLKOUT_DIVIDE, MmcmParams->ClkOut1Div); XVphy_DrpWr(InstancePtr, QuadId, ChId, 0x0A, @@ -501,7 +501,7 @@ u32 XVphy_MmcmWriteParameters(XVphy *InstancePtr, u8 QuadId, XVphy_DrpWr(InstancePtr, QuadId, ChId, 0x0B, (u16)((DrpVal32 >> 16) & 0xFFFF)); - //Write CLKOUT2 Reg1 & Reg2 Values + /* Write CLKOUT2 Reg1 & Reg2 Values */ DrpVal32 = XVphy_Mmcme4DividerEncoding(MMCM_CLKOUT_DIVIDE, MmcmParams->ClkOut2Div); XVphy_DrpWr(InstancePtr, QuadId, ChId, 0x0C, @@ -509,23 +509,23 @@ u32 XVphy_MmcmWriteParameters(XVphy *InstancePtr, u8 QuadId, XVphy_DrpWr(InstancePtr, QuadId, ChId, 0x0D, (u16)((DrpVal32 >> 16) & 0xFFFF)); - //Write Lock Reg1 Value + /* Write Lock Reg1 Value */ DrpVal = XVphy_Mmcme4LockReg1Encoding(MmcmParams->ClkFbOutMult); XVphy_DrpWr(InstancePtr, QuadId, ChId, 0x18, DrpVal); - //Write Lock Reg2 Value + /* Write Lock Reg2 Value */ DrpVal = XVphy_Mmcme4LockReg2Encoding(MmcmParams->ClkFbOutMult); XVphy_DrpWr(InstancePtr, QuadId, ChId, 0x19, DrpVal); - //Write Lock Reg3 Value + /* Write Lock Reg3 Value */ DrpVal = XVphy_Mmcme4LockReg3Encoding(MmcmParams->ClkFbOutMult); XVphy_DrpWr(InstancePtr, QuadId, ChId, 0x1A, DrpVal); - //Write Filter Reg1 Value + /* Write Filter Reg1 Value */ DrpVal = XVphy_Mmcme4FilterReg1Encoding(MmcmParams->ClkFbOutMult); XVphy_DrpWr(InstancePtr, QuadId, ChId, 0x4E, DrpVal); - //Write Filter Reg2 Value + /* Write Filter Reg2 Value */ DrpVal = XVphy_Mmcme4FilterReg2Encoding(MmcmParams->ClkFbOutMult); XVphy_DrpWr(InstancePtr, QuadId, ChId, 0x4F, DrpVal); diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirx.c b/hdmi/xilinx-hdmi-rx/xv_hdmirx.c index 2b768a4..ef77721 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirx.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirx.c @@ -50,6 +50,8 @@ * XV_HdmiRx_GetTime10Ms, XV_HdmiRx_GetTime16Ms * XV_HdmiRx_GetTime200Ms * Added TMDS Clock Ratio callback support +* 2.30 EB 05/03/19 Updated the description of the API +* XV_HdmiRx_GetLinkStatus * * ******************************************************************************/ @@ -655,9 +657,6 @@ int XV_HdmiRx_SetHpd(XV_HdmiRx *InstancePtr, u8 SetClr) * - 0 = Link error counter for channel 0. * - 1 = Link error counter for channel 1. * - 2 = Link error counter for channel 2. -* - 3 = Link phase. -* - 4 = Link delay. -* - 5 = Link line length * * @return Link status of the HDMI RX core link. * diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c b/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c index 6713211..77e43f7 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c @@ -607,7 +607,7 @@ void HdmiRx_PioIntrHandler(XV_HdmiRx *InstancePtr) // Load timer XV_HdmiRx_TmrStart(InstancePtr, - XV_HdmiRx_GetTime10Ms(InstancePtr)); // 10 ms + XV_HdmiRx_GetTime10Ms(InstancePtr)); // 10 ms } // Video ready event has occurred @@ -636,7 +636,7 @@ void HdmiRx_PioIntrHandler(XV_HdmiRx *InstancePtr) // Load timer - 200 ms (one UHD frame is 40 ms, 5 frames) XV_HdmiRx_TmrStart(InstancePtr, - XV_HdmiRx_GetTime200Ms(InstancePtr)); + XV_HdmiRx_GetTime200Ms(InstancePtr)); } } @@ -718,7 +718,7 @@ void HdmiRx_PioIntrHandler(XV_HdmiRx *InstancePtr) // Load timer XV_HdmiRx_TmrStart(InstancePtr, - XV_HdmiRx_GetTime10Ms(InstancePtr)); // 10 ms + XV_HdmiRx_GetTime10Ms(InstancePtr)); // 10 ms } // Call mode callback @@ -793,7 +793,7 @@ void HdmiRx_TmrIntrHandler(XV_HdmiRx *InstancePtr) // Load timer - 200 ms (one UHD frame is 40 ms, 5 frames) XV_HdmiRx_TmrStart(InstancePtr, - XV_HdmiRx_GetTime200Ms(InstancePtr)); + XV_HdmiRx_GetTime200Ms(InstancePtr)); } // Init state @@ -840,7 +840,7 @@ void HdmiRx_TmrIntrHandler(XV_HdmiRx *InstancePtr) else { // Load timer - 200 ms (one UHD frame is 40 ms, 5 frames) XV_HdmiRx_TmrStart(InstancePtr, - XV_HdmiRx_GetTime200Ms(InstancePtr)); + XV_HdmiRx_GetTime200Ms(InstancePtr)); } } diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c index 3893108..78b016a 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c @@ -2120,10 +2120,11 @@ static void XV_HdmiRxSs_ConfigBridgeMode(XV_HdmiRxSs *InstancePtr) { * * @return None. * -* @note None. +* @note Linux - No need to put definition inside. * ******************************************************************************/ void XV_HdmiRxSs_SetDefaultPpc(XV_HdmiRxSs *InstancePtr, u8 Id) { + } /*****************************************************************************/ diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.c b/hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.c index 8509644..f5fd6e4 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.c @@ -392,7 +392,7 @@ int XV_HdmiRxSs_SubcoreInitHdcp22(XV_HdmiRxSs *HdmiRxSsPtr) /* Set-up the HDMI RX HDCP 2.2 Protocol Event Callback Handler */ XV_HdmiRx_SetCallback(HdmiRxSsPtr->HdmiRxPtr, - XV_HDMIRX_HANDLER_DDC_HDCP_22_PROT, + XV_HDMIRX_HANDLER_DDC_HDCP_22_PROT, (void *)XV_HdmiRxSs_DdcHdcp22ProtocolEvtCallback, (void *)HdmiRxSsPtr); diff --git a/hdmi/xilinx-hdmi-tx/xv_hdmitx.c b/hdmi/xilinx-hdmi-tx/xv_hdmitx.c index 3597795..09b7cf5 100644 --- a/hdmi/xilinx-hdmi-tx/xv_hdmitx.c +++ b/hdmi/xilinx-hdmi-tx/xv_hdmitx.c @@ -203,7 +203,7 @@ int XV_HdmiTx_CfgInitialize(XV_HdmiTx *InstancePtr, XV_HdmiTx_Config *CfgPtr, (50)); /* 50 ms on Bit 15:0 */ XV_HdmiTx_WriteReg(InstancePtr->Config.BaseAddress, - XV_HDMITX_TOGGLE_CONF_OFFSET, + XV_HDMITX_TOGGLE_CONF_OFFSET, RegValue); /* HPD/Connect Trigger (100ms + 0ms)*/ @@ -211,7 +211,7 @@ int XV_HdmiTx_CfgInitialize(XV_HdmiTx *InstancePtr, XV_HdmiTx_Config *CfgPtr, (100)); /* 100 ms on Bit 15:0 */ XV_HdmiTx_WriteReg(InstancePtr->Config.BaseAddress, - XV_HDMITX_CONNECT_CONF_OFFSET, + XV_HDMITX_CONNECT_CONF_OFFSET, RegValue); /* Enable the PIO peripheral interrupt */ @@ -1858,7 +1858,7 @@ int XV_HdmiTx_SetAudioChannels(XV_HdmiTx *InstancePtr, u8 Value) u8 AudioStatus; AudioStatus = XV_HdmiTx_ReadReg((InstancePtr)->Config.BaseAddress, - XV_HDMITX_AUD_CTRL_OFFSET) & XV_HDMITX_AUD_CTRL_RUN_MASK; + XV_HDMITX_AUD_CTRL_OFFSET) & XV_HDMITX_AUD_CTRL_RUN_MASK; // Stop peripheral XV_HdmiTx_WriteReg((InstancePtr)->Config.BaseAddress, diff --git a/hdmi/xilinx-hdmi-tx/xv_hdmitxss.c b/hdmi/xilinx-hdmi-tx/xv_hdmitxss.c index fbea4be..a864940 100644 --- a/hdmi/xilinx-hdmi-tx/xv_hdmitxss.c +++ b/hdmi/xilinx-hdmi-tx/xv_hdmitxss.c @@ -1326,7 +1326,6 @@ static void XV_HdmiTxSs_StreamUpCallback(void *CallbackRef) static void XV_HdmiTxSs_StreamDownCallback(void *CallbackRef) { XV_HdmiTxSs *HdmiTxSsPtr = (XV_HdmiTxSs *)CallbackRef; - /* Assert HDMI TXCore link reset */ XV_HdmiTxSs_TXCore_LRST(HdmiTxSsPtr, TRUE); XV_HdmiTxSs_TXCore_VRST(HdmiTxSsPtr, TRUE); @@ -2543,10 +2542,11 @@ static void XV_HdmiTxSs_ConfigBridgeMode(XV_HdmiTxSs *InstancePtr) { * * @return None. * -* @note None. +* @note Linux - No need to put definition inside. * ******************************************************************************/ void XV_HdmiTxSs_SetDefaultPpc(XV_HdmiTxSs *InstancePtr, u8 Id) { + } /*****************************************************************************/ diff --git a/hdmi/xilinx-hdmi-tx/xvtc.c b/hdmi/xilinx-hdmi-tx/xvtc.c index a716da3..ace23f2 100644 --- a/hdmi/xilinx-hdmi-tx/xvtc.c +++ b/hdmi/xilinx-hdmi-tx/xvtc.c @@ -159,6 +159,12 @@ * modes FIELD1 vactive size. This value is same as FILED0 * vactive size for all interlaced modes except for SDI NTSC * mode +* jsr 10/01/18 Removed the hard coded programming of vactive size values +* based on resolutions. Moved the hard coded values for SDI +* NTSC resolution to SDI TXSS driver instead of in VTC +* driver. +* jsr 10/03/18 Corrected the VGA resoultion timing paramters w.r.t the +* timing values given in the VTC GUI for 640x480p * * ******************************************************************************/ @@ -1339,15 +1345,15 @@ void XVtc_SetGenerator(XVtc *InstancePtr, XVtc_Signal *SignalCfgPtr) XVTC_ASIZE_VERT_MASK; XVtc_WriteReg(InstancePtr->Config.BaseAddress, XVTC_GASIZE_OFFSET, RegValue); - /* Only for XVIDC_VM_720x486_60_I (SDI NTSC), the FIELD1 vactive - * size is different from FIELD0. As there is no vactive FIELD1 - * entry in the video common library, program it separately as below */ - if(r_vactive != 243) - RegValue = ((r_vactive) << XVTC_ASIZE_VERT_SHIFT) & - XVTC_ASIZE_VERT_MASK; - else - RegValue = ((r_vactive+1) << XVTC_ASIZE_VERT_SHIFT) & - XVTC_ASIZE_VERT_MASK; + /* For some resolutions, the FIELD1 vactive size is different + * from FIELD0, e.g. XVIDC_VM_720x486_60_I (SDI NTSC), + * As there is no vactive FIELD1 entry in the video common + * library, program it separately. For resolutions where + * vactive values are different, it should be taken care in + * corrosponding driver. Otherwise program same values in + * FIELD0 and FIELD1 registers */ + RegValue = ((r_vactive) << XVTC_ASIZE_VERT_SHIFT) & + XVTC_ASIZE_VERT_MASK; XVtc_WriteReg(InstancePtr->Config.BaseAddress, XVTC_GASIZE_F1_OFFSET, RegValue); @@ -1430,15 +1436,15 @@ void XVtc_SetGenerator(XVtc *InstancePtr, XVtc_Signal *SignalCfgPtr) XVTC_ASIZE_VERT_MASK; XVtc_WriteReg(InstancePtr->Config.BaseAddress, XVTC_GASIZE_OFFSET, RegValue); - /* Only for XVIDC_VM_720x486_60_I (SDI NTSC), the FIELD1 vactive - * size is different from FIELD0. As there is no vactive FIELD1 - * entry in the video common library, program it separately as below */ - if(r_vactive != 243) - RegValue = ((r_vactive) << XVTC_ASIZE_VERT_SHIFT) & - XVTC_ASIZE_VERT_MASK; - else - RegValue = ((r_vactive+1) << XVTC_ASIZE_VERT_SHIFT) & - XVTC_ASIZE_VERT_MASK; + /* For some resolutions, the FIELD1 vactive size is different + * from FIELD0, e.g. XVIDC_VM_720x486_60_I (SDI NTSC), + * As there is no vactive FIELD1 entry in the video common + * library, program it separately. For resolutions where + * vactive values are different, it should be taken care in + * corrosponding driver. Otherwise program same values in + * FIELD0 and FIELD1 registers */ + RegValue = ((r_vactive) << XVTC_ASIZE_VERT_SHIFT) & + XVTC_ASIZE_VERT_MASK; XVtc_WriteReg(InstancePtr->Config.BaseAddress, XVTC_GASIZE_F1_OFFSET, RegValue); @@ -1923,17 +1929,17 @@ void XVtc_ConvVideoMode2Timing(XVtc *InstancePtr, u16 Mode, case XVTC_VMODE_VGA: // 640x480 (VGA) { // Horizontal Timing - TimingPtr->HActiveVideo = 656; - TimingPtr->HFrontPorch = 8; + TimingPtr->HActiveVideo = 640; + TimingPtr->HFrontPorch = 16; TimingPtr->HSyncWidth = 96; - TimingPtr->HBackPorch = 40; + TimingPtr->HBackPorch = 48; TimingPtr->HSyncPolarity = 0; // Vertical Timing - TimingPtr->VActiveVideo = 496; - TimingPtr->V0FrontPorch = 2; + TimingPtr->VActiveVideo = 480; + TimingPtr->V0FrontPorch = 10; TimingPtr->V0SyncWidth = 2; - TimingPtr->V0BackPorch = 25; + TimingPtr->V0BackPorch = 33; TimingPtr->VSyncPolarity = 0; break; @@ -2351,8 +2357,8 @@ u16 XVtc_ConvTiming2VideoMode(XVtc *InstancePtr, XVtc_Timing *TimingPtr) return XVTC_VMODE_576P; } } - else if((TimingPtr->HActiveVideo == 656) && - (TimingPtr->VActiveVideo == 496)) { + else if((TimingPtr->HActiveVideo == 640) && + (TimingPtr->VActiveVideo == 480)) { return XVTC_VMODE_VGA; } else if((TimingPtr->HActiveVideo == 800) && diff --git a/hdmi/xilinx-hdmi-tx/xvtc.h b/hdmi/xilinx-hdmi-tx/xvtc.h index 08e12f0..5530917 100644 --- a/hdmi/xilinx-hdmi-tx/xvtc.h +++ b/hdmi/xilinx-hdmi-tx/xvtc.h @@ -281,6 +281,8 @@ * 7.2 sk 08/16/16 Used UINTPTR instead of u32 for Baseaddress as part of * adding 64 bit support. CR# 867425. * Changed the prototype of XVtc_CfgInitialize API. +* ms 03/17/17 Added readme.txt file in examples folder for doxygen +* generation. * * ******************************************************************************/ From 3b34842f9a6abf280dd6a6e6da917b52682e03de Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Tue, 9 Apr 2019 13:45:49 +0800 Subject: [PATCH 26/46] dt:bindings: Updated the documentation on DT bindings Updated the document for HDMI TX, HDMI RX and Vphy DT nodes Signed-off-by: Shikhar Mishra --- .../devicetree/bindings/xlnx,v-hdmi-rx-ss.txt | 43 +++++++------ .../devicetree/bindings/xlnx,v-hdmi-tx-ss.txt | 60 +++++++++++-------- .../devicetree/bindings/xlnx,vphy.txt | 30 ++++++---- 3 files changed, 78 insertions(+), 55 deletions(-) diff --git a/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt b/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt index bcbd992..f2db4f4 100644 --- a/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt +++ b/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt @@ -27,18 +27,23 @@ Required Properties: - interrupts: Interrupt numbers for mandatory and optional blocks - interrupt-names: Identification string that binds irq number to block generating the interrupt - "hdmirx": interrupt for rx subcore [always present] - "hdcp1x": interrupt for hdcp1.4 core [optional] - "hdcp1x-timer": interrupt for hdcp1.4 timer [present if hdcp1x is - included] - "hdcp22": interrupt for hdcp22 core [optional] - "hdcp22-timer": interrupt for hdcp2.2 timer [present if hdcp22 is - included] + "irq": interrupt for tx subcore [always present] + "hdcp14_irq": interrupt for hdcp1.4 core [optional - present if hdcp1x + is included] + "hdcp14_timer_irq": interrupt for hdcp1.4 timer [optional - present if + hdcp1x is included] + "hdcp22_irq": interrupt for hdcp22 core [optional - present if hdcp22 + is included] + "hdcp22_timer_irq": interrupt for hdcp2.2 timer [optional - present if + hdcp22 is included] - - clocks: phandle for axi-lite, video stream - - clock-names: The identification string, "axi-lite", is always required for - the axi-lite clock, "video" is always required for video stream - clock + - clocks: phandle of all the clocks required by IP are listed here. + - clock-names: names of all the clocks required by IP are listed here. + NOTE: Auto generated DT is providing all the clock names and handles + reuired by the IP. + NOTE: Below are the identification string that are always required. + "s_axi_cpu_aclk", is always required for the axi-lite clock + "s_axis_video_aclk" is always required for video stream clock - phys: phandle for phy lanes registered for hdmi protocol. HDMI always require 3 lanes @@ -65,20 +70,22 @@ Required Properties: If hdcp1.4 is included in the design then key management block node should be added to the device tree - hdmi_input_hdcp_keymngmt_blk_top_1: hdcp_keymngmt_blk_top@a0270000 { + hdcp_keymngmt_blk_1: hdcp_keymngmt_blk_top@88000000 { + clock-names = "s_axi_aclk", "m_axis_aclk"; + clocks = <&zynqmp_clk 71>, <&misc_clk_0>; compatible = "xlnx,hdcp-keymngmt-blk-top-1.0"; - reg = <0x0 0xa0270000 0x0 0x10000>; + reg = <0x0 0x88000000 0x0 0x10000>; }; - hdmi_input_v_hdmi_rx_ss_0: v_hdmi_rx_ss@a0000000 { + v_hdmi_rx_ss: v_hdmi_rx_ss@80000000 { compatible = "xlnx,v-hdmi-rx-ss-3.1"; reg = <0x0 0xa0000000 0x0 0x100000>, <0x0 0xa0270000 0x0 0x10000>; reg-names = "hdmi-rxss", "hdcp1x-keymngmt"; interrupt-parent = <&gic>; - interrupts = <0 91 4>, <0 108 4>, <0 109 4>, <0 110 4>, <0 111 4>; - interrupt-names = "hdmirx", "hdcp1x", "hdcp1x-timer", "hdcp22", "hdcp22-timer"; - clocks = <&vid_s_axi_clk>, <&vid_stream_clk>; - clock-names = "axi-lite", "video"; + interrupts = <0 90 4 0 104 4 0 105 4 0 108 4 0 109 4>; + interrupt-names = "irq", "hdcp14_irq", "hdcp14_timer_irq", "hdcp22_irq", "hdcp22_timer_irq"; + clock-names = "s_axi_cpu_aclk", "link_clk", "s_axis_audio_aclk", "video_clk", "s_axis_video_aclk"; + clocks = <&zynqmp_clk 71>, <&misc_clk_1>, <&zynqmp_clk 71>, <&misc_clk_2>, <&zynqmp_clk 72>; phy-names = "hdmi-phy0", "hdmi-phy1", "hdmi-phy2"; phys = <&vphy_lane0 0 1 1 0>, <&vphy_lane1 0 1 1 0>, <&vphy_lane2 0 1 1 0>; diff --git a/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt b/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt index 8f98159..7eee5fb 100644 --- a/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt +++ b/Documentation/devicetree/bindings/xlnx,v-hdmi-tx-ss.txt @@ -32,20 +32,28 @@ Required properties: - interrupts: Interrupt numbers for mandatory and optional blocks - interrupt-names: Identification string that binds irq number to block generating the interrupt - "hdmitx": interrupt for tx subcore [always present] - "hdcp1x": interrupt for hdcp1.4 core [optional] - "hdcp1x-timer": interrupt for hdcp1.4 timer [present if hdcp1x is - included] - "hdcp22": interrupt for hdcp22 core [optional] - "hdcp22-timer": interrupt for hdcp2.2 timer [present if hdcp22 is - included] - - - clocks: phandle for axi-lite, video stream, tmds and retimer clock - - clock-names: The identification string for various clock inputs - "axi-lite", is always required for the axi-lite clock - "video" is always required for video stream clock - "txref-clk" is always required for tmds clock - "retimer-clk" is required only when retimer is being used + "irq": interrupt for tx subcore [always present] + "hdcp14_irq": interrupt for hdcp1.4 core [optional - present if hdcp1x + is included] + "hdcp14_timer_irq": interrupt for hdcp1.4 timer [optional - present if + hdcp1x is included] + "hdcp22_irq": interrupt for hdcp22 core [optional - present if hdcp22 + is included] + "hdcp22_timer_irq": interrupt for hdcp2.2 timer [optional - present if + hdcp22 is included] + + - clocks: phandle of all the clocks required by IP are listed here. + - clock-names: names of all the clocks required by IP are listed here. + NOTE: Auto generated DT is providing all the clock names and handles + reuired by the IP. + NOTE: Below are the identification string that are always required. + "s_axi_cpu_aclk", is always required for the axi-lite clock + "s_axis_video_aclk" is always required for video stream clock + "txref-clk" is always required for tmds clock + "retimer-clk" is required only when retimer is being used + NOTE: "txref-clk" and "retimer-clk" needs to be explicitly added in + the list of clock-names and its phandle in clocks as its derived by + external clock. - phys: phandle for phy lanes registered for hdmi protocol. HDMI always require 3 lanes @@ -93,27 +101,29 @@ depending on the TX clock line rate. Tested with dp159.c driver. If hdcp1.4 is included in the design then key management block node should be added to the device tree - hdmi_output_hdcp_keymngmt_blk_top_0: hdcp_keymngmt_blk_top@a0280000 { + hdcp_keymngmt_blk_0: hdcp_keymngmt_blk_top@90000000 { + clock-names = "s_axi_aclk", "m_axis_aclk"; + clocks = <&zynqmp_clk 71>, <&misc_clk_0>; compatible = "xlnx,hdcp-keymngmt-blk-top-1.0"; - reg = <0x0 0xa0280000 0x0 0x10000>; + reg = <0x0 0x90000000 0x0 0x10000>; }; hdmi_acr_ctrl_0: hdmi_acr_ctrl@a0059000 { - /* This is a place holder node for a custom IP, user may need to update the entries */ - compatible = "xlnx,hdmi-acr-ctrl-1.0"; - reg = <0x0 0xa0059000 0x0 0x1000>; - }; + /* This is a place holder node for a custom IP, user may need to update the entries */ + compatible = "xlnx,hdmi-acr-ctrl-1.0"; + reg = <0x0 0xa0059000 0x0 0x1000>; + }; - hdmi_output_v_hdmi_tx_ss_0: v_hdmi_tx_ss@a0080000 { + v_hdmi_tx_ss: v_hdmi_tx_ss@80080000 { compatible = "xlnx,v-hdmi-tx-ss-3.1"; reg = <0x0 0xa0080000 0x0 0x80000>, <0x0 0xa0280000 0x0 0x10000>; reg-names = "hdmi-txss", "hdcp1x-keymngmt"; interrupt-parent = <&gic>; - interrupts = <0 93 4>, <0 104 4>, <0 105 4>, <0 106 4>, <0 107 4>; - interrupt-names = "hdmitx", "hdcp1x", "hdcp1x-timer", "hdcp22", "hdcp22-timer"; + interrupts = <0 91 4 0 106 4 0 107 4 0 110 4 0 111 4>; + interrupt-names = "irq", "hdcp14_irq", "hdcp14_timer_irq", "hdcp22_irq", "hdcp22_timer_irq"; - clocks = <&axi_lite_clk>, <&axi_stream_clk>, <&si5324 0>, <&dp159>; - clock-names = "axi-lite", "video", "txref-clk", "retimer-clk"; + clock-names = "s_axi_cpu_aclk", "link_clk", "s_axis_audio_aclk", "video_clk", "s_axis_video_aclk", "txref-clk", "retimer-clk"; + clocks = <&zynqmp_clk 71>, <&misc_clk_1>, <&zynqmp_clk 71>, <&misc_clk_2>, <&zynqmp_clk 72>, <&si5324 0>, <&dp159>; phy-names = "hdmi-phy0", "hdmi-phy1", "hdmi-phy2"; phys = <&vphy_lane0 0 1 1 1>, <&vphy_lane1 0 1 1 1>, <&vphy_lane2 0 1 1 1>; diff --git a/Documentation/devicetree/bindings/xlnx,vphy.txt b/Documentation/devicetree/bindings/xlnx,vphy.txt index 4941fb8..e1110cf 100644 --- a/Documentation/devicetree/bindings/xlnx,vphy.txt +++ b/Documentation/devicetree/bindings/xlnx,vphy.txt @@ -15,14 +15,20 @@ Required Properties: - reg: Base address and size of the IP core. - interrupts: Interrupt number. - interrupts-parent: phandle for interrupt controller. - - - clocks: phandle for axi-lite clock and dru clock - - clock-names: The identification string, "axi-lite", is always required - and "dru-clk" is required for NI DRU clock for phy - + + - clocks: phandle of all the clocks required by IP are listed here. + - clock-names: names of all the clocks required by IP are listed here. + NOTE: Auto generated DT is providing all the clock names and handles + reuired by the IP. + NOTE: The identification string, "vid_phy_axi4lite_aclk", is always + required. + NOTE: The identification string "dru-clk" is always required if + NI DRU (nidru parameter) is selected for phy. This needs to be + explicitly added in the list of clock-names and its phandle in clocks + as its derived by external clock. + - xlnx,input-pixels-per-clock: IP configuration for samples/clk (1, 2, 4) Note: Only 2 is supported at this time - - xlnx,nidru: flag to indicate if DRU is present - xlnx,nidru-refclk-sel: DRU clock selector - xlnx,rx-no-of-channels: Required Rx channels for registered protocol @@ -47,23 +53,23 @@ Required Properties: controller_type = 0 for HDMI controller_instance = [0, ...] indexes the instance of the protocol - controller - is_shared = 1 if the RX and TX can be shared across the same + controller + is_shared = 1 if the RX and TX can be shared across the same protocol/controller direction_tx = 0 for RX and 1 for TX -(These properties are intended for future steering of multiple protocols +(These properties are intended for future steering of multiple protocols sharing VPHYs, and are therefore subject to change.) ==Example== - vid_phy_controller_0: vid_phy_controller@a0090000 { + vid_phy_controller: vid_phy_controller@80120000 { compatible = "xlnx,vid-phy-controller-2.2"; reg = <0x0 0xa0090000 0x0 0x10000>; interrupts = <0 92 4>; interrupt-parent = <&gic>; - clocks = <&vid_s_axi_clk>, <&si570_2>; - clock-names = "axi-lite", "dru-clk"; + clock-names = "mgtrefclk0_pad_p_in", "mgtrefclk0_pad_n_in", "mgtrefclk1_pad_p_in", "mgtrefclk1_pad_n_in", "gtsouthrefclk0_in", "gtsouthrefclk0_odiv2_in", "vid_phy_tx_axi4s_aclk", "vid_phy_rx_axi4s_aclk", "vid_phy_sb_aclk", "vid_phy_axi4lite_aclk", "drpclk", "dru-clk"; + clocks = <&misc_clk_0>, <&misc_clk_0>, <&misc_clk_0>, <&misc_clk_0>, <&misc_clk_3>, <&misc_clk_3>, <&misc_clk_1>, <&misc_clk_1>, <&zynqmp_clk 71>, <&zynqmp_clk 71>, <&zynqmp_clk 71>, <&si570_2>; xlnx,input-pixels-per-clock = <0x2>; xlnx,nidru = <0x1>; From fe84ed726915b8fa017fd85ce5e31745fdcd979a Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Tue, 9 Apr 2019 13:46:48 +0800 Subject: [PATCH 27/46] license: Update the license obtained from legal Signed-off-by: Shikhar Mishra --- LICENSE.md | 1031 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 691 insertions(+), 340 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 3912109..76ac498 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,340 +1,691 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - 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. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. +Components: xhdmi 2019.1 + + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + + + +Copyright 2007-2009 Ilya O. Levin +Copyright (C) 1989 1991 Free Software Foundation Inc. +Copyright 2016-2017 Leon Woestenberg +Copyright (C) 2018 Rohit Consul +Copyright 2014-2019 Xilinx Inc + + +Components: di_bigdigits 2.5.0 + + +*/ + +/***** BEGIN LICENSE BLOCK ***** + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * Copyright (c) 2001-15 David Ireland, D.I. Management Services Pty Limited + * . All rights reserved. + * + * Alternatively, the contents of this file may be used under the terms + * of the GNU General Public License Version 2, as described below: + * + * 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 + * + ***** END LICENSE BLOCK *****/ +/* + * Last updated: + * $Date: 2015-10-22 10:23:00 $ + * $Revision: 2.5.0 $ + * $Author: dai $ + */ + + +Mozilla Public License +Version 2.0 +1. Definitions +1.1. ?Contributor? +means each individual or legal entity that creates, contributes to the creation of, or owns Covered Software. + +1.2. ?Contributor Version? +means the combination of the Contributions of others (if any) used by a Contributor and that particular Contributor?s Contribution. + +1.3. ?Contribution? +means Covered Software of a particular Contributor. + +1.4. ?Covered Software? +means Source Code Form to which the initial Contributor has attached the notice in Exhibit A, the Executable Form of such Source Code Form, and Modifications of such Source Code Form, in each case including portions thereof. + +1.5. ?Incompatible With Secondary Licenses? +means + +that the initial Contributor has attached the notice described in Exhibit B to the Covered Software; or + +that the Covered Software was made available under the terms of version 1.1 or earlier of the License, but not also under the terms of a Secondary License. + +1.6. ?Executable Form? +means any form of the work other than Source Code Form. + +1.7. ?Larger Work? +means a work that combines Covered Software with other material, in a separate file or files, that is not Covered Software. + +1.8. ?License? +means this document. + +1.9. ?Licensable? +means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently, any and all of the rights conveyed by this License. + +1.10. ?Modifications? +means any of the following: + +any file in Source Code Form that results from an addition to, deletion from, or modification of the contents of Covered Software; or + +any new file in Source Code Form that contains any Covered Software. + +1.11. ?Patent Claims? of a Contributor +means any patent claim(s), including without limitation, method, process, and apparatus claims, in any patent Licensable by such Contributor that would be infringed, but for the grant of the License, by the making, using, selling, offering for sale, having made, import, or transfer of either its Contributions or its Contributor Version. + +1.12. ?Secondary License? +means either the GNU General Public License, Version 2.0, the GNU Lesser General Public License, Version 2.1, the GNU Affero General Public License, Version 3.0, or any later versions of those licenses. + +1.13. ?Source Code Form? +means the form of the work preferred for making modifications. + +1.14. ?You? (or ?Your?) +means an individual or a legal entity exercising rights under this License. For legal entities, ?You? includes any entity that controls, is controlled by, or is under common control with You. For purposes of this definition, ?control? means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. + +2. License Grants and Conditions +2.1. Grants +Each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: + +under intellectual property rights (other than patent or trademark) Licensable by such Contributor to use, reproduce, make available, modify, display, perform, distribute, and otherwise exploit its Contributions, either on an unmodified basis, with Modifications, or as part of a Larger Work; and + +under Patent Claims of such Contributor to make, use, sell, offer for sale, have made, import, and otherwise transfer either its Contributions or its Contributor Version. + +2.2. Effective Date +The licenses granted in Section 2.1 with respect to any Contribution become effective for each Contribution on the date the Contributor first distributes such Contribution. + +2.3. Limitations on Grant Scope +The licenses granted in this Section 2 are the only rights granted under this License. No additional rights or licenses will be implied from the distribution or licensing of Covered Software under this License. Notwithstanding Section 2.1(b) above, no patent license is granted by a Contributor: + +for any code that a Contributor has removed from Covered Software; or + +for infringements caused by: (i) Your and any other third party?s modifications of Covered Software, or (ii) the combination of its Contributions with other software (except as part of its Contributor Version); or + +under Patent Claims infringed by Covered Software in the absence of its Contributions. + +This License does not grant any rights in the trademarks, service marks, or logos of any Contributor (except as may be necessary to comply with the notice requirements in Section 3.4). + +2.4. Subsequent Licenses +No Contributor makes additional grants as a result of Your choice to distribute the Covered Software under a subsequent version of this License (see Section 10.2) or under the terms of a Secondary License (if permitted under the terms of Section 3.3). + +2.5. Representation +Each Contributor represents that the Contributor believes its Contributions are its original creation(s) or it has sufficient rights to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use +This License is not intended to limit any rights You have under applicable copyright doctrines of fair use, fair dealing, or other equivalents. + +2.7. Conditions +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in Section 2.1. + +3. Responsibilities +3.1. Distribution of Source Form +All distribution of Covered Software in Source Code Form, including any Modifications that You create or to which You contribute, must be under the terms of this License. You must inform recipients that the Source Code Form of the Covered Software is governed by the terms of this License, and how they can obtain a copy of this License. You may not attempt to alter or restrict the recipients? rights in the Source Code Form. + +3.2. Distribution of Executable Form +If You distribute Covered Software in Executable Form then: + +such Covered Software must also be made available in Source Code Form, as described in Section 3.1, and You must inform recipients of the Executable Form how they can obtain a copy of such Source Code Form by reasonable means in a timely manner, at a charge no more than the cost of distribution to the recipient; and + +You may distribute such Executable Form under the terms of this License, or sublicense it under different terms, provided that the license for the Executable Form does not attempt to limit or alter the recipients? rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work +You may create and distribute a Larger Work under terms of Your choice, provided that You also comply with the requirements of this License for the Covered Software. If the Larger Work is a combination of Covered Software with a work governed by one or more Secondary Licenses, and the Covered Software is not Incompatible With Secondary Licenses, this License permits You to additionally distribute such Covered Software under the terms of such Secondary License(s), so that the recipient of the Larger Work may, at their option, further distribute the Covered Software under the terms of either this License or such Secondary License(s). + +3.4. Notices +You may not remove or alter the substance of any license notices (including copyright notices, patent notices, disclaimers of warranty, or limitations of liability) contained within the Source Code Form of the Covered Software, except that You may alter any license notices to the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms +You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. However, You may do so only on Your own behalf, and not on behalf of any Contributor. You must make it absolutely clear that any such warranty, support, indemnity, or liability obligation is offered by You alone, and You hereby agree to indemnify every Contributor for any liability incurred by such Contributor as a result of warranty, support, indemnity or liability terms You offer. You may include additional disclaimers of warranty and limitations of liability specific to any jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Software due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be placed in a text file included with all distributions of the Covered Software under this License. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. + +5. Termination +5.1. The rights granted under this License will terminate automatically if You fail to comply with any of its terms. However, if You become compliant, then the rights granted under this License from a particular Contributor are reinstated (a) provisionally, unless and until such Contributor explicitly and finally terminates Your grants, and (b) on an ongoing basis, if such Contributor fails to notify You of the non-compliance by some reasonable means prior to 60 days after You have come back into compliance. Moreover, Your grants from a particular Contributor are reinstated on an ongoing basis if such Contributor notifies You of the non-compliance by some reasonable means, this is the first time You have received notice of non-compliance with this License from such Contributor, and You become compliant prior to 30 days after Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent infringement claim (excluding declaratory judgment actions, counter-claims, and cross-claims) alleging that a Contributor Version directly or indirectly infringes any patent, then the rights granted to You by any and all Contributors for the Covered Software under Section 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or Your distributors under this License prior to termination shall survive termination. + +6. Disclaimer of Warranty +Covered Software is provided under this License on an ?as is? basis, without warranty of any kind, either expressed, implied, or statutory, including, without limitation, warranties that the Covered Software is free of defects, merchantable, fit for a particular purpose or non-infringing. The entire risk as to the quality and performance of the Covered Software is with You. Should any Covered Software prove defective in any respect, You (not any Contributor) assume the cost of any necessary servicing, repair, or correction. This disclaimer of warranty constitutes an essential part of this License. No use of any Covered Software is authorized under this License except under this disclaimer. + +7. Limitation of Liability +Under no circumstances and under no legal theory, whether tort (including negligence), contract, or otherwise, shall any Contributor, or anyone who distributes Covered Software as permitted above, be liable to You for any direct, indirect, special, incidental, or consequential damages of any character including, without limitation, damages for lost profits, loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses, even if such party shall have been informed of the possibility of such damages. This limitation of liability shall not apply to liability for death or personal injury resulting from such party?s negligence to the extent applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so this exclusion and limitation may not apply to You. + +8. Litigation +Any litigation relating to this License may be brought only in the courts of a jurisdiction where the defendant maintains its principal place of business and such litigation shall be governed by laws of that jurisdiction, without reference to its conflict-of-law provisions. Nothing in this Section shall prevent a party?s ability to bring cross-claims or counter-claims. + +9. Miscellaneous +This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not be used to construe this License against a Contributor. + +10. Versions of the License +10.1. New Versions +Mozilla Foundation is the license steward. Except as provided in Section 10.3, no one other than the license steward has the right to modify or publish new versions of this License. Each version will be given a distinguishing version number. + +10.2. Effect of New Versions +You may distribute the Covered Software under the terms of the version of the License under which You originally received the Covered Software, or under the terms of any subsequent version published by the license steward. + +10.3. Modified Versions +If you create software not governed by this License, and you want to create a new license for such software, you may create and use a modified version of this License if you rename the license and remove any references to the name of the license steward (except to note that such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses +If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular file, then You may include the notice in a location (such as a LICENSE file in a relevant directory) where a recipient would be likely to look for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - ?Incompatible With Secondary Licenses? Notice +This Source Code Form is ?Incompatible With Secondary Licenses?, as defined by the Mozilla Public License, v. 2.0. + + +copyright (c) 2001-15 by D.I. Management Services Pty Limited +Copyright 2001 David Ireland D.I. Management Services Pty Ltd + + +Components: dp159 + + +GNU General Public License, version 2 +The latest version of the GPL, version 3 +What to do if you see a possible GPL violation +Translations of GPLv2 +GPLv2 Frequently Asked Questions +The GNU General Public License version 2 (GPLv2) in other formats: plain text, Texinfo, LaTeX, standalone HTML, Docbook, Markdown, ODF, RTF +Table of Contents +GNU GENERAL PUBLIC LICENSE +Preamble +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +How to Apply These Terms to Your New Programs +GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. +Preamble +The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: + +a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. +b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. +c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) +These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: + +a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, +b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, +c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) +The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. + +This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS +How to Apply These Terms to Your New Programs +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. + +one line to give the program's name and an idea of what it does. +Copyright (C) yyyy name of author + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it starts in an interactive mode: + +Gnomovision version 69, Copyright (C) year name of author +Gnomovision comes with ABSOLUTELY NO WARRANTY; for details +type `show w'. This is free software, and you are welcome +to redistribute it under certain conditions; type `show c' +for details. +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright +interest in the program `Gnomovision' +(which makes passes at compilers) written +by James Hacker. + +signature of Ty Coon, 1 April 1989 +Ty Coon, President of Vice +This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. + + +Copyright (C) 2007 Hans Verkuil +Copyright 2016-2017 Leon Woestenberg + + + From 6f65b27f4a14dc97903a32ecb60371fb068af3d7 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Tue, 9 Apr 2019 13:47:38 +0800 Subject: [PATCH 28/46] hdmitx: modify lookup table for audio N parameter patch includes changes for lookup table for N, index entry for sample rate index and removing fixed N value for 4k. Signed-off-by: Shikhar Mishra --- hdmi/xlnx_hdmitx_audio.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/hdmi/xlnx_hdmitx_audio.c b/hdmi/xlnx_hdmitx_audio.c index 4e32985..03d0a8e 100644 --- a/hdmi/xlnx_hdmitx_audio.c +++ b/hdmi/xlnx_hdmitx_audio.c @@ -50,10 +50,10 @@ const struct acr_n_table acr_n_table[] = { {148500000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, {185625000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, {222750000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, - {297000000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, - {371250000, { 6144, 4704, 5120, 9408, 10240, 18816, 20480} }, - {445500000, { 4096, 4704, 5120, 9408, 10240, 18816, 20480} }, - {594000000, { 3072, 4704, 5120, 9408, 10240, 18816, 20480} } + {297000000, { 3072, 4704, 5120, 9408, 10240, 18816, 20480} }, + {371250000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + {445500000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576} }, + {594000000, { 3072, 9408, 6144, 18816, 12288, 37632, 24576} } }; static u16 srate_to_index(u32 srate) @@ -70,15 +70,18 @@ static u16 srate_to_index(u32 srate) case 48000: index = 2; break; - case 96000: + case 88200: index = 3; break; - case 176400: + case 96000: index = 4; break; - case 192000: + case 176400: index = 5; break; + case 192000: + index = 6; + break; default: index = 0; break; @@ -190,10 +193,7 @@ static int audio_codec_hw_params(struct device *dev, void *data, hdmi_audio_infoframe_pack(&hparams->cea, adata->buffer, HDMI_INFOFRAME_SIZE(AUDIO)); - if (adata->tmds_clk >= 371250000 && adata->tmds_clk <= 594000000) - n = 5120; - else - n = xhdmi_acr_get_n(adata->tmds_clk, hparams->sample_rate); + n = xhdmi_acr_get_n(adata->tmds_clk, hparams->sample_rate); /* Disable ACR */ writel(2, adata->acr_base + XV_ACR_ENABLE); From cf0a56089cdf4ae016d560057c7d2457da9cd382 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Tue, 9 Apr 2019 14:00:17 +0800 Subject: [PATCH 29/46] hdmitx: hdmirx: vphy: Driver update 5Apr2019 Signed-off-by: Shikhar Mishra --- hdmi/phy-xilinx-vphy/xhdcp22_tx.c | 10 +- hdmi/phy-xilinx-vphy/xv_hdmic.h | 4 + hdmi/phy-xilinx-vphy/xvidc.h | 46 +++++++- hdmi/phy-xilinx-vphy/xvidc_timings_table.c | 130 ++++++++++++++++++++- hdmi/phy-xilinx-vphy/xvphy_hdmi_intr.c | 6 +- hdmi/xilinx-hdmi-tx/xv_hdmitx.c | 40 +++++++ 6 files changed, 227 insertions(+), 9 deletions(-) diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_tx.c b/hdmi/phy-xilinx-vphy/xhdcp22_tx.c index c6a4c06..170fb5b 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_tx.c +++ b/hdmi/phy-xilinx-vphy/xhdcp22_tx.c @@ -60,6 +60,8 @@ * buffer. * 6. Check return status of DDC write/read when polling * RxStatus register. +* 2.31 YB 03/28/19 Moved the reading of the DDC status from +* XHdcp22Tx_TimerHandler to XHdcp22Tx_Poll. * * ******************************************************************************/ @@ -1014,6 +1016,11 @@ int XHdcp22Tx_Poll(XHdcp22_Tx *InstancePtr) /* Store the authentication status before executing the next state */ PrvAuthenticationStatus = InstancePtr->Info.AuthenticationStatus; + /* Set timer expired signaling flag */ + if (InstancePtr->Timer.TimerExpired == (TRUE) && InstancePtr->Info.IsEnabled) { + XHdcp22Tx_ReadRxStatus(InstancePtr); + } + /* continue executing the statemachine */ NewState = XHdcp22_Tx_StateTable[InstancePtr->Info.CurrentState](InstancePtr); Transition = transition_table[InstancePtr->Info.CurrentState][NewState]; @@ -3212,9 +3219,6 @@ static void XHdcp22Tx_TimerHandler(void *CallbackRef, u8 TmrCntNumber) /* Set timer expired signaling flag */ InstancePtr->Timer.TimerExpired = (TRUE); - - if (InstancePtr->Info.IsEnabled) - XHdcp22Tx_ReadRxStatus(InstancePtr); } diff --git a/hdmi/phy-xilinx-vphy/xv_hdmic.h b/hdmi/phy-xilinx-vphy/xv_hdmic.h index 78ac4e0..7e2f0cd 100644 --- a/hdmi/phy-xilinx-vphy/xv_hdmic.h +++ b/hdmi/phy-xilinx-vphy/xv_hdmic.h @@ -336,5 +336,9 @@ XHdmiC_Aux XV_HdmiC_AudioIF_GeneratePacket(XHdmiC_AudioInfoFrame *AudioInfoFrame XHdmiC_Colorspace XV_HdmiC_XVidC_To_IfColorformat(XVidC_ColorFormat ColorFormat); XVidC_AspectRatio XV_HdmiC_IFAspectRatio_To_XVidC(XHdmiC_PicAspectRatio AR); +#ifdef __cplusplus +} +#endif + #endif /* XHDMIC_H_ */ /** @} */ diff --git a/hdmi/phy-xilinx-vphy/xvidc.h b/hdmi/phy-xilinx-vphy/xvidc.h index a4d1cd7..f4c2b17 100644 --- a/hdmi/phy-xilinx-vphy/xvidc.h +++ b/hdmi/phy-xilinx-vphy/xvidc.h @@ -61,6 +61,7 @@ * vyc 04/04/18 Added BGR8 memory format * 4.5 jsr 07/03/18 Added XVIDC_VM_720x486_60_I video format * 4.5 yas 03/08/19 Added support for frame rates 144HZ and 240HZ + * 4.5 mmo 02/14/19 Added 5k, 8k, 10k and Low Resolution with 200Hz, 240Hz * * *******************************************************************************/ @@ -93,7 +94,11 @@ typedef enum { XVIDC_VM_720x486_60_I, XVIDC_VM_720x576_50_I, XVIDC_VM_1440x480_60_I, + XVIDC_VM_1440x480_120_I, + XVIDC_VM_1440x480_240_I, XVIDC_VM_1440x576_50_I, + XVIDC_VM_1440x576_100_I, + XVIDC_VM_1440x576_200_I, XVIDC_VM_1920x1080_48_I, XVIDC_VM_1920x1080_50_I, XVIDC_VM_1920x1080_60_I, @@ -116,7 +121,11 @@ typedef enum { XVIDC_VM_640x480_85_P, XVIDC_VM_720x400_85_P, XVIDC_VM_720x480_60_P, + XVIDC_VM_720x480_120_P, + XVIDC_VM_720x480_240_P, XVIDC_VM_720x576_50_P, + XVIDC_VM_720x576_100_P, + XVIDC_VM_720x576_200_P, XVIDC_VM_800x600_56_P, XVIDC_VM_800x600_60_P, XVIDC_VM_800x600_72_P, @@ -135,6 +144,8 @@ typedef enum { XVIDC_VM_1280x720_30_P, XVIDC_VM_1280x720_50_P, XVIDC_VM_1280x720_60_P, + XVIDC_VM_1280x720_100_P, + XVIDC_VM_1280x720_120_P, XVIDC_VM_1280x768_60_P, XVIDC_VM_1280x768_60_P_RB, XVIDC_VM_1280x768_75_P, @@ -214,6 +225,10 @@ typedef enum { XVIDC_VM_2048x1080_60_P, XVIDC_VM_2048x1080_100_P, XVIDC_VM_2048x1080_120_P, + XVIDC_VM_2560x1080_24_P, + XVIDC_VM_2560x1080_25_P, + XVIDC_VM_2560x1080_30_P, + XVIDC_VM_2560x1080_48_P, XVIDC_VM_2560x1080_50_P, XVIDC_VM_2560x1080_60_P, XVIDC_VM_2560x1080_100_P, @@ -229,6 +244,8 @@ typedef enum { XVIDC_VM_3840x2160_48_P, XVIDC_VM_3840x2160_50_P, XVIDC_VM_3840x2160_60_P, + XVIDC_VM_3840x2160_100_P, + XVIDC_VM_3840x2160_120_P, XVIDC_VM_3840x2160_60_P_RB, XVIDC_VM_4096x2160_24_P, XVIDC_VM_4096x2160_25_P, @@ -237,6 +254,32 @@ typedef enum { XVIDC_VM_4096x2160_50_P, XVIDC_VM_4096x2160_60_P, XVIDC_VM_4096x2160_60_P_RB, + XVIDC_VM_4096x2160_100_P, + XVIDC_VM_4096x2160_120_P, + XVIDC_VM_5120x2160_24_P, + XVIDC_VM_5120x2160_25_P, + XVIDC_VM_5120x2160_30_P, + XVIDC_VM_5120x2160_48_P, + XVIDC_VM_5120x2160_50_P, + XVIDC_VM_5120x2160_60_P, + XVIDC_VM_5120x2160_100_P, + XVIDC_VM_5120x2160_120_P, + XVIDC_VM_7680x4320_24_P, + XVIDC_VM_7680x4320_25_P, + XVIDC_VM_7680x4320_30_P, + XVIDC_VM_7680x4320_48_P, + XVIDC_VM_7680x4320_50_P, + XVIDC_VM_7680x4320_60_P, + XVIDC_VM_7680x4320_120_P, + XVIDC_VM_7680x4320_100_P, + XVIDC_VM_10240x4320_24_P, + XVIDC_VM_10240x4320_25_P, + XVIDC_VM_10240x4320_30_P, + XVIDC_VM_10240x4320_48_P, + XVIDC_VM_10240x4320_50_P, + XVIDC_VM_10240x4320_60_P, + XVIDC_VM_10240x4320_100_P, + XVIDC_VM_10240x4320_120_P, XVIDC_VM_NUM_SUPPORTED, XVIDC_VM_USE_EDID_PREFERRED, @@ -312,8 +355,9 @@ typedef enum { XVIDC_FR_100HZ = 100, XVIDC_FR_120HZ = 120, XVIDC_FR_144HZ = 144, + XVIDC_FR_200HZ = 200, XVIDC_FR_240HZ = 240, - XVIDC_FR_NUM_SUPPORTED = 20, + XVIDC_FR_NUM_SUPPORTED = 21, XVIDC_FR_UNKNOWN } XVidC_FrameRate; diff --git a/hdmi/phy-xilinx-vphy/xvidc_timings_table.c b/hdmi/phy-xilinx-vphy/xvidc_timings_table.c index c22d445..7cfbcaa 100644 --- a/hdmi/phy-xilinx-vphy/xvidc_timings_table.c +++ b/hdmi/phy-xilinx-vphy/xvidc_timings_table.c @@ -17,7 +17,7 @@ /** * * @file xvidc_timings_table.c - * @addtogroup video_common_v4_0 + * @addtogroup video_common_v4_2 * @{ * * Contains video timings for various standard resolutions. @@ -41,7 +41,7 @@ * 4.4 eb 09/04/18 Fixed timings for 1280x720_24_P, 1280x720_25_P, * 1280x720_30_P * 4.5 jsr 07/03/18 Added timing for new video mode XVIDC_VM_720x486_60_I - * + * 4.5 mmo 02/14/19 Added 5k, 8k, 10k and Low Resolution with 200Hz, 240Hz * * *******************************************************************************/ @@ -94,9 +94,21 @@ const XVidC_VideoTimingMode XVidC_VideoTimingModes[XVIDC_VM_NUM_SUPPORTED] = { 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_1440x480_120_I, "1440x480@120Hz (I)", XVIDC_FR_120HZ, + {1440, 38, 124, 114, 1716, 0, + 480, 4, 3, 15, 525, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1440x480_240_I, "1440x480@240Hz (I)", XVIDC_FR_240HZ, + {1440, 38, 124, 114, 1716, 0, + 480, 4, 3, 15, 525, 0, 0, 0, 0, 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_1440x576_100_I, "1440x576@100Hz (I)", XVIDC_FR_100HZ, + {1440, 24, 126, 138, 1728, 0, + 576, 2, 3, 19, 625, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1440x576_200_I, "1440x576@200Hz (I)", XVIDC_FR_200HZ, + {1440, 24, 126, 138, 1728, 0, + 576, 2, 3, 19, 625, 0, 0, 0, 0, 0} }, { XVIDC_VM_1920x1080_48_I, "1920x1080@48Hz (I)", XVIDC_FR_48HZ, {1920, 371, 88, 371, 2750, 1, 540, 2, 5, 15, 562, 3, 5, 15, 563, 1} }, @@ -157,9 +169,21 @@ const XVidC_VideoTimingMode XVidC_VideoTimingModes[XVIDC_VM_NUM_SUPPORTED] = { 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_720x480_120_P, "720x480@120Hz", XVIDC_FR_120HZ, + {720, 16, 62, 60, 858, 0, + 480, 9, 6, 30, 525, 0, 0, 0, 0, 0} }, + { XVIDC_VM_720x480_240_P, "720x480@240Hz", XVIDC_FR_240HZ, + {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_720x576_100_P, "720x576@100Hz", XVIDC_FR_100HZ, + {720, 12, 64, 68, 864, 0, + 576, 5, 5, 39, 625, 0, 0, 0, 0, 0} }, + { XVIDC_VM_720x576_200_P, "720x576@200Hz", XVIDC_FR_200HZ, + {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} }, @@ -214,6 +238,12 @@ const XVidC_VideoTimingMode XVidC_VideoTimingModes[XVIDC_VM_NUM_SUPPORTED] = { 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_1280x720_100_P, "1280x720@100Hz", XVIDC_FR_100HZ, + {1280, 440, 40, 220, 1980, 1, + 720, 5, 5, 20, 750, 0, 0, 0, 0, 1} }, + { XVIDC_VM_1280x720_120_P, "1280x720@120Hz", XVIDC_FR_120HZ, + {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} }, @@ -451,6 +481,18 @@ const XVidC_VideoTimingMode XVidC_VideoTimingModes[XVIDC_VM_NUM_SUPPORTED] = { XVIDC_VM_2048x1080_120_P, "2048x1080@120Hz", XVIDC_FR_120HZ, {2048, 88, 44, 148, 2200, 1, 1080, 4, 5, 36, 1125, 0, 0, 0, 0, 1} }, + { XVIDC_VM_2560x1080_24_P, "2560x1080@24Hz", XVIDC_FR_24HZ, + {2560, 998, 44, 148, 3750, 1, + 1080, 4, 5, 11, 1100, 0, 0, 0, 0, 1} }, + { XVIDC_VM_2560x1080_25_P, "2560x1080@25Hz", XVIDC_FR_25HZ, + {2560, 448, 44, 148, 3200, 1, + 1080, 4, 5, 36, 1125, 0, 0, 0, 0, 1} }, + { XVIDC_VM_2560x1080_30_P, "2560x1080@30Hz", XVIDC_FR_30HZ, + {2560, 768, 44, 148, 3520, 1, + 1080, 4, 5, 36, 1125, 0, 0, 0, 0, 1} }, + { XVIDC_VM_2560x1080_48_P, "2560x1080@48Hz", XVIDC_FR_48HZ, + {2560, 998, 44, 148, 3750, 1, + 1080, 4, 5, 11, 1100, 0, 0, 0, 0, 1} }, { 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} }, @@ -496,6 +538,12 @@ const XVidC_VideoTimingMode XVidC_VideoTimingModes[XVIDC_VM_NUM_SUPPORTED] = { 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_3840x2160_100_P, "3840x2160@100Hz", XVIDC_FR_100HZ, + {3840, 1056, 88, 296, 5280, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_3840x2160_120_P, "3840x2160@120Hz", XVIDC_FR_120HZ, + {3840, 176, 88, 296, 4400, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, { XVIDC_VM_3840x2160_60_P_RB, "3840x2160@60Hz (RB)", XVIDC_FR_60HZ, {3840, 48, 32, 80, 4000, 1, 2160, 3, 5, 54, 2222, 0, 0, 0, 0, 0} }, @@ -520,6 +568,84 @@ const XVidC_VideoTimingMode XVidC_VideoTimingModes[XVIDC_VM_NUM_SUPPORTED] = { 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} }, + { XVIDC_VM_4096x2160_100_P, "4096x2160@100Hz", XVIDC_FR_100HZ, + {4096, 800, 88, 296, 5280, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_4096x2160_120_P, "4096x2160@120Hz", XVIDC_FR_120HZ, + {4096, 88, 88, 128, 4400, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_5120x2160_24_P, "5120x2160@24Hz", XVIDC_FR_24HZ, + {5120, 1996, 88, 296, 7500, 1, + 2160, 8, 10, 22, 2200, 0, 0, 0, 0, 1} }, + { XVIDC_VM_5120x2160_25_P, "5120x2160@25Hz", XVIDC_FR_25HZ, + {5120, 1696, 88, 296, 7200, 1, + 2160, 8, 10, 22, 2200, 0, 0, 0, 0, 1} }, + { XVIDC_VM_5120x2160_30_P, "5120x2160@30Hz", XVIDC_FR_30HZ, + {5120, 664, 88, 128, 6000, 1, + 2160, 8, 10, 22, 2200, 0, 0, 0, 0, 1} }, + { XVIDC_VM_5120x2160_48_P, "5120x2160@48Hz", XVIDC_FR_48HZ, + {5120, 746, 88, 296, 6250, 1, + 2160, 8, 10, 297, 2475, 0, 0, 0, 0, 1} }, + { XVIDC_VM_5120x2160_50_P, "5120x2160@50Hz", XVIDC_FR_50HZ, + {5120, 1096, 88, 296, 6600, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_5120x2160_60_P, "5120x2160@60Hz", XVIDC_FR_60HZ, + {5120, 164, 88, 128, 5500, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_5120x2160_100_P, "5120x2160@100Hz", XVIDC_FR_100HZ, + {5120, 1096, 88, 296, 6600, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_5120x2160_120_P, "5120x2160@120Hz", XVIDC_FR_120HZ, + {5120, 164, 88, 128, 5500, 1, + 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, + { XVIDC_VM_7680x4320_24_P, "7680x4320@24Hz", XVIDC_FR_24HZ, + {7680, 2552, 176, 592, 11000, 1, + 4320, 16, 20, 144, 4500, 0, 0, 0, 0, 1} }, + { XVIDC_VM_7680x4320_25_P, "7680x4320@25Hz", XVIDC_FR_25HZ, + {7680, 2352, 176, 592, 10800, 1, + 4320, 16, 20, 44, 4400, 0, 0, 0, 0, 1} }, + { XVIDC_VM_7680x4320_30_P, "7680x4320@30Hz", XVIDC_FR_30HZ, + {7680, 552, 176, 592, 9000, 1, + 4320, 16, 20, 44, 4400, 0, 0, 0, 0, 1} }, + { XVIDC_VM_7680x4320_48_P, "7680x4320@48Hz", XVIDC_FR_48HZ, + {7680, 2552, 176, 592, 11000, 1, + 4320, 16, 20, 144, 4500, 0, 0, 0, 0, 1} }, + { XVIDC_VM_7680x4320_50_P, "7680x4320@50Hz", XVIDC_FR_50HZ, + {7680, 2352, 176, 592, 10800, 1, + 4320, 16, 20, 44, 4400, 0, 0, 0, 0, 1} }, + { XVIDC_VM_7680x4320_60_P, "7680x4320@60Hz", XVIDC_FR_60HZ, + {7680, 552, 176, 592, 9000, 1, + 4320, 16, 20, 44, 4400, 0, 0, 0, 0, 1} }, + { XVIDC_VM_7680x4320_100_P, "7680x4320@100Hz" , XVIDC_FR_100HZ, + {7680, 2112, 176, 592, 10560, 1, + 4320, 16, 20, 144, 4500, 0, 0, 0, 0, 1} }, + { XVIDC_VM_7680x4320_120_P, "7680x4320@120Hz" , XVIDC_FR_120HZ, + {7680, 352, 176, 592, 8800, 1, + 4320, 16, 20, 144, 4500, 0, 0, 0, 0, 1} }, + { XVIDC_VM_10240x4320_24_P, "10240x4320@24Hz", XVIDC_FR_24HZ, + {10240, 1492, 176, 592, 12500, 1, + 4320, 16, 20, 594, 4950, 0, 0, 0, 0, 1} }, + { XVIDC_VM_10240x4320_25_P, "10240x4320@25Hz", XVIDC_FR_25HZ, + {10240, 2492, 176, 592, 13500, 1, + 4320, 16, 20, 44, 4400, 0, 0, 0, 0, 1} }, + { XVIDC_VM_10240x4320_30_P, "10240x4320@30Hz", XVIDC_FR_30HZ, + {10240, 288, 176, 296, 11000, 1, + 4320, 16, 20, 144, 4500, 0, 0, 0, 0, 1} }, + { XVIDC_VM_10240x4320_48_P, "10240x4320@48Hz", XVIDC_FR_48HZ, + {10240, 1492, 176, 592, 12500, 1, + 4320, 16, 20, 594, 4950, 0, 0, 0, 0, 1} }, + { XVIDC_VM_10240x4320_50_P, "10240x4320@50Hz", XVIDC_FR_50HZ, + {10240, 2492, 176, 592, 13500, 1, + 4320, 16, 20, 44, 4400, 0, 0, 0, 0, 1} }, + { XVIDC_VM_10240x4320_60_P, "10240x4320@60Hz", XVIDC_FR_60HZ, + {10240, 288, 176, 296, 11000, 1, + 4320, 16, 20, 144, 4500, 0, 0, 0, 0, 1} }, + { XVIDC_VM_10240x4320_100_P, "10240x4320@100Hz", XVIDC_FR_100HZ, + {10240, 2192, 176, 592, 13200, 1, + 4320, 16, 20, 144, 4500, 0, 0, 0, 0, 1} }, + { XVIDC_VM_10240x4320_120_P, "10240x4320@120Hz", XVIDC_FR_120HZ, + {10240, 288, 176, 296, 11000, 1, + 4320, 16, 20, 144, 4500, 0, 0, 0, 0, 1} }, }; /** @} */ diff --git a/hdmi/phy-xilinx-vphy/xvphy_hdmi_intr.c b/hdmi/phy-xilinx-vphy/xvphy_hdmi_intr.c index 5a4e728..a6ccb04 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_hdmi_intr.c +++ b/hdmi/phy-xilinx-vphy/xvphy_hdmi_intr.c @@ -903,9 +903,9 @@ void XVphy_HdmiTxTimerTimeoutHandler(XVphy *InstancePtr) (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTHE4) || (InstancePtr->Config.XcvrType == XVPHY_GT_TYPE_GTYE4)) { XVphy_SetBufgGtDiv(InstancePtr, XVPHY_DIR_TX, - (PllType == XVPHY_PLL_TYPE_CPLL) ? - InstancePtr->Quads[0].Plls[0].TxOutDiv : - InstancePtr->Quads[0].Plls[0].TxOutDiv / 2); + (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); diff --git a/hdmi/xilinx-hdmi-tx/xv_hdmitx.c b/hdmi/xilinx-hdmi-tx/xv_hdmitx.c index 09b7cf5..a63013f 100644 --- a/hdmi/xilinx-hdmi-tx/xv_hdmitx.c +++ b/hdmi/xilinx-hdmi-tx/xv_hdmitx.c @@ -56,6 +56,10 @@ * 2.02 MMO 11/08/18 Added Bridge Overflow and Bridge Underflow (PIO IN) * EB 14/08/18 Updated XV_HdmiTx_CfgInitialize to initialize * HPD pulse periods +* 2.03 EB 28/03/19 Disable PIO Interrupt for XV_HdmiTx_DdcWrite and +* XV_HdmiTx_DdcRead APIs to prevent another DDC +* transactions from happening in the middle of a DDC +* transaction * * ******************************************************************************/ @@ -1489,6 +1493,16 @@ int XV_HdmiTx_DdcWrite(XV_HdmiTx *InstancePtr, u8 Slave, Xil_AssertNonvoid(Buffer != NULL); Xil_AssertNonvoid((Stop == (TRUE)) || (Stop == (FALSE))); + /* [DIFF FROM BM] Not taking this BM logic as we disable PIO interrupts in the handler and + * enabling it when interrupt is processed. + */ +#if 0 + /* Disable PIO Interrupt to prevent another DDC transactions from happening + * in the middle of an ongoing DDC transaction + */ + XV_HdmiTx_PioIntrDisable(InstancePtr); +#endif + // Status default, assume failure Status = XST_FAILURE; @@ -1582,6 +1596,14 @@ int XV_HdmiTx_DdcWrite(XV_HdmiTx *InstancePtr, u8 Slave, // Disable DDC peripheral XV_HdmiTx_DdcDisable(InstancePtr); + /* [DIFF FROM BM] Not taking this BM logic as we disable PIO interrupts in the handler and + * enabling it when interrupt is processed. + */ +#if 0 + // Enable the interrupts which were disabled earlier + XV_HdmiTx_PioIntrEnable(InstancePtr); +#endif + return Status; } @@ -1619,6 +1641,16 @@ int XV_HdmiTx_DdcRead(XV_HdmiTx *InstancePtr, u8 Slave, u16 Length, Xil_AssertNonvoid(Buffer != NULL); Xil_AssertNonvoid((Stop == (TRUE)) || (Stop == (FALSE))); + /* [DIFF FROM BM] Not taking this BM logic as we disable PIO interrupts in the handler and + * enabling it when interrupt is processed. + */ +#if 0 + /* Disable PIO Interrupt to prevent another DDC transactions from happening + * in the middle of an ongoing DDC transaction + */ + XV_HdmiTx_PioIntrDisable(InstancePtr); +#endif + // Status default, assume failure Status = XST_FAILURE; @@ -1705,6 +1737,14 @@ int XV_HdmiTx_DdcRead(XV_HdmiTx *InstancePtr, u8 Slave, u16 Length, // Disable DDC peripheral XV_HdmiTx_DdcDisable(InstancePtr); + /* [DIFF FROM BM] Not taking this BM logic as we disable PIO interrupts in the handler and + * enabling it when interrupt is processed. + */ +#if 0 + // Enable the interrupts which were disabled earlier + XV_HdmiTx_PioIntrEnable(InstancePtr); +#endif + return Status; } From 21c5376579a4f8f7e55c02346be0f1f115bd35b5 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Mon, 15 Apr 2019 11:41:48 +0800 Subject: [PATCH 30/46] hdmitx:hdmirx: 10 bit format support YUV420 10bit MEDIA_BUS_FMT_VYYUYY10_4X20 YUV422 10bit MEDIA_BUS_FMT_UYVY10_1X20 YUV444 10bit MEDIA_BUS_FMT_VUY10_1X30 RGB 10bit MEDIA_BUS_FMT_RBG101010_1X30 Signed-off-by: Shikhar Mishra --- hdmi/xilinx-hdmirx.c | 66 ++++++++++++++++++++++++++++++++++++------ hdmi/xilinx_drm_hdmi.c | 32 ++++++++++++++++---- 2 files changed, 83 insertions(+), 15 deletions(-) diff --git a/hdmi/xilinx-hdmirx.c b/hdmi/xilinx-hdmirx.c index 6e23054..822f709 100644 --- a/hdmi/xilinx-hdmirx.c +++ b/hdmi/xilinx-hdmirx.c @@ -766,18 +766,61 @@ static void RxStreamUpCallback(void *CallbackRef) /* see UG934 page 8 */ /* the V4L2 media bus fmt codes match the AXI S format, and match those from TPG */ if (Stream->ColorFormatId == XVIDC_CSF_RGB) { - /* red blue green */ - xhdmi->detected_format.code = MEDIA_BUS_FMT_RBG888_1X24; - dev_dbg(xhdmi->dev,"XVIDC_CSF_RGB -> MEDIA_BUS_FMT_RBG888_1X24\n"); + if (HdmiRxSsPtr->Config.MaxBitsPerPixel == 10) { + if(Stream->ColorDepth == XVIDC_BPC_8) { + xhdmi->detected_format.code = MEDIA_BUS_FMT_RBG888_1X24; + dev_dbg(xhdmi->dev,"XVIDC_CSF_RGB -> MEDIA_BUS_FMT_RBG888_1X24\n"); + } else { + xhdmi->detected_format.code = MEDIA_BUS_FMT_RBG101010_1X30; + dev_dbg(xhdmi->dev,"XVIDC_CSF_RGB -> MEDIA_BUS_FMT_RBG101010_1X30\n"); + } + /* Default will always be 8 */ + } else { + xhdmi->detected_format.code = MEDIA_BUS_FMT_RBG888_1X24; + dev_dbg(xhdmi->dev,"XVIDC_CSF_RGB -> MEDIA_BUS_FMT_RBG888_1X24\n"); + } + + /* YUV444 */ } else if (Stream->ColorFormatId == XVIDC_CSF_YCRCB_444) { - xhdmi->detected_format.code = MEDIA_BUS_FMT_VUY8_1X24; - dev_dbg(xhdmi->dev,"XVIDC_CSF_YCRCB_444 -> MEDIA_BUS_FMT_VUY8_1X24\n"); + if (HdmiRxSsPtr->Config.MaxBitsPerPixel == 10) { + if(Stream->ColorDepth == XVIDC_BPC_8) { + xhdmi->detected_format.code = MEDIA_BUS_FMT_VUY8_1X24; + dev_dbg(xhdmi->dev,"XVIDC_CSF_YCRCB_444 -> MEDIA_BUS_FMT_VUY8_1X24\n"); + } else { + xhdmi->detected_format.code = MEDIA_BUS_FMT_VUY10_1X30; + dev_dbg(xhdmi->dev,"XVIDC_CSF_YCRCB_444 -> MEDIA_BUS_FMT_VUY10_1X30\n"); + } + /* Default will always be 8 */ + } else { + xhdmi->detected_format.code = MEDIA_BUS_FMT_VUY8_1X24; + dev_dbg(xhdmi->dev,"XVIDC_CSF_YCRCB_444 -> MEDIA_BUS_FMT_VUY8_1X24\n"); + } + + /* Since 422 is always detected as 12 BPC, set the 8bit media bus format */ } else if (Stream->ColorFormatId == XVIDC_CSF_YCRCB_422) { - xhdmi->detected_format.code = MEDIA_BUS_FMT_UYVY8_1X16; - dev_dbg(xhdmi->dev,"XVIDC_CSF_YCRCB_422 -> MEDIA_BUS_FMT_UYVY8_1X16\n"); + if (HdmiRxSsPtr->Config.MaxBitsPerPixel == 10) { + xhdmi->detected_format.code = MEDIA_BUS_FMT_UYVY10_1X20; + dev_dbg(xhdmi->dev,"XVIDC_CSF_YCRCB_422 -> MEDIA_BUS_FMT_UYVY10_1X20\n"); + /* Default will always be 8 */ + } else { + xhdmi->detected_format.code = MEDIA_BUS_FMT_UYVY8_1X16; + dev_dbg(xhdmi->dev,"XVIDC_CSF_YCRCB_422 -> MEDIA_BUS_FMT_UYVY8_1X16\n"); + } + + /* YUV420 */ } else if (Stream->ColorFormatId == XVIDC_CSF_YCRCB_420) { - xhdmi->detected_format.code = MEDIA_BUS_FMT_VYYUYY8_1X24; - dev_dbg(xhdmi->dev,"XVIDC_CSF_YCRCB_420 -> MEDIA_BUS_FMT_VYYUYY8_1X24\n"); + if (HdmiRxSsPtr->Config.MaxBitsPerPixel == 10) { + if(Stream->ColorDepth == XVIDC_BPC_8) { + xhdmi->detected_format.code = MEDIA_BUS_FMT_VYYUYY8_1X24; + dev_dbg(xhdmi->dev,"XVIDC_CSF_YCRCB_420 -> MEDIA_BUS_FMT_VYYUYY8_1X24\n"); + } else { + xhdmi->detected_format.code = MEDIA_BUS_FMT_VYYUYY10_4X20; + dev_dbg(xhdmi->dev,"XVIDC_CSF_YCRCB_420 -> MEDIA_BUS_FMT_VYYUYY10_1X24\n"); + } + } else { + xhdmi->detected_format.code = MEDIA_BUS_FMT_VYYUYY8_1X24; + dev_dbg(xhdmi->dev,"XVIDC_CSF_YCRCB_420 -> MEDIA_BUS_FMT_VYYUYY8_1X24\n"); + } } xhdmi->detected_format.xfer_func = V4L2_XFER_FUNC_DEFAULT; @@ -1620,6 +1663,11 @@ static int xhdmi_parse_of(struct xhdmi_device *xhdmi, XV_HdmiRxSs_Config *config goto error_dt; config->Ppc = val; + rc = of_property_read_u32(node, "xlnx,max-bits-per-component", &val); + if (rc < 0) + goto error_dt; + config->MaxBitsPerPixel = val; + rc = of_property_read_u32(node, "xlnx,edid-ram-size", &val); if (rc == 0) { if (val % 128) diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index cb783d6..a9835e2 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -163,6 +163,7 @@ struct xlnx_drm_hdmi { int dpms; XVidC_ColorFormat xvidc_colorfmt; + XVidC_ColorDepth xvidc_colordepth; /* configuration for the baseline subsystem driver instance */ XV_HdmiTxSs_Config config; /* bookkeeping for the baseline subsystem driver instance */ @@ -986,7 +987,7 @@ static void xlnx_drm_hdmi_encoder_disable(struct drm_encoder *encoder) xlnx_drm_hdmi_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); } -static u32 hdmitx_find_media_bus(u32 drm_fourcc) +static u32 hdmitx_find_media_bus(struct xlnx_drm_hdmi *xhdmi, u32 drm_fourcc) { switch(drm_fourcc) { @@ -994,28 +995,41 @@ static u32 hdmitx_find_media_bus(u32 drm_fourcc) case DRM_FORMAT_XRGB8888: case DRM_FORMAT_BGR888: case DRM_FORMAT_RGB888: + xhdmi->xvidc_colordepth = XVIDC_BPC_8; + return XVIDC_CSF_RGB; case DRM_FORMAT_XBGR2101010: + xhdmi->xvidc_colordepth = XVIDC_BPC_10; return XVIDC_CSF_RGB; case DRM_FORMAT_VUY888: case DRM_FORMAT_XVUY8888: case DRM_FORMAT_Y8: + xhdmi->xvidc_colordepth = XVIDC_BPC_8; + return XVIDC_CSF_YCRCB_444; case DRM_FORMAT_XVUY2101010: case DRM_FORMAT_Y10: + xhdmi->xvidc_colordepth = XVIDC_BPC_10; return XVIDC_CSF_YCRCB_444; case DRM_FORMAT_YUYV: //packed, 8b case DRM_FORMAT_UYVY: //packed, 8b case DRM_FORMAT_NV16: //semi-planar, 8b + xhdmi->xvidc_colordepth = XVIDC_BPC_8; + return XVIDC_CSF_YCRCB_422; case DRM_FORMAT_XV20: //semi-planar, 10b + xhdmi->xvidc_colordepth = XVIDC_BPC_10; return XVIDC_CSF_YCRCB_422; case DRM_FORMAT_NV12: //semi-planar, 8b + xhdmi->xvidc_colordepth = XVIDC_BPC_8; + return XVIDC_CSF_YCRCB_420; case DRM_FORMAT_XV15: //semi-planar, 10b + xhdmi->xvidc_colordepth = XVIDC_BPC_10; return XVIDC_CSF_YCRCB_420; default: printk("Warning: Unknown drm_fourcc format code: %d\n", drm_fourcc); + xhdmi->xvidc_colordepth = XVIDC_BPC_UNKNOWN; return XVIDC_CSF_RGB; } } @@ -1060,7 +1074,9 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, drm_mode_debug_printmodeline(mode); drm_fourcc = encoder->crtc->primary->state->fb->format->format; - xhdmi->xvidc_colorfmt = hdmitx_find_media_bus(drm_fourcc); + xhdmi->xvidc_colorfmt = hdmitx_find_media_bus(xhdmi, drm_fourcc); + dev_dbg(xhdmi->dev,"xvidc_colorfmt = %d\n", xhdmi->xvidc_colorfmt); + dev_dbg(xhdmi->dev,"xvidc_colordepth = %d\n", xhdmi->xvidc_colordepth); dev_dbg(xhdmi->dev,"mode->clock = %d\n", mode->clock * 1000); dev_dbg(xhdmi->dev,"mode->crtc_clock = %d\n", mode->crtc_clock * 1000); @@ -1163,17 +1179,21 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, #endif } - ColorDepth = HdmiTxSsPtr->Config.MaxBitsPerPixel; + /* The value of xvidc_colordepth is set by calling hdmitx_find_media_bus() + * API earlier in this function. Check whether the value is valid or not */ + if (XVIDC_BPC_UNKNOWN == xhdmi->xvidc_colordepth) + xhdmi->xvidc_colordepth = HdmiTxSsPtr->Config.MaxBitsPerPixel; + /* check if resolution is supported at requested bit depth */ switch (xhdmi->xvidc_colorfmt) { case XVIDC_CSF_RGB: case XVIDC_CSF_YCRCB_444: - if ((ColorDepth > XVIDC_BPC_8) && + if ((xhdmi->xvidc_colordepth > XVIDC_BPC_8) && (mode->hdisplay >= 3840) && (mode->vdisplay >= 2160) && (mode->vrefresh >= XVIDC_FR_50HZ)) { dev_dbg(xhdmi->dev,"INFO> UHD only supports 24-bits color depth\n"); - ColorDepth = XVIDC_BPC_8; + xhdmi->xvidc_colordepth = XVIDC_BPC_8; } break; @@ -1182,7 +1202,7 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, } TmdsClock = XV_HdmiTxSs_SetStream(HdmiTxSsPtr, HdmiTxSsVidStreamPtr->VmId, xhdmi->xvidc_colorfmt, - ColorDepth, NULL); + xhdmi->xvidc_colordepth, NULL); //Update AVI InfoFrame AviInfoFramePtr->Version = 2; From 44d691f6937ad73ac974ed5b50722e73514459f6 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Thu, 25 Apr 2019 10:10:51 +0800 Subject: [PATCH 31/46] dt:bindings: Updated RX dt for max bit per component For 2019.1 driver, xlnx,max-bits-per-component is now should be part of HDMI RX device tree. Without this, RX probe will fail. This feild is part of IP configuration Signed-off-by: Shikhar Mishra --- Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt b/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt index f2db4f4..378c20b 100644 --- a/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt +++ b/Documentation/devicetree/bindings/xlnx,v-hdmi-rx-ss.txt @@ -51,6 +51,8 @@ Required Properties: - xlnx,input-pixels-per-clock: IP configuration for samples/clk (2, 4) Note: Only 2 is supported at this time + - xlnx,max-bits-per-component: The data width per video component (8,10,12,16) + Note: Only 8 & 10 is supported at this time - xlnx,edid-ram-size: Denotes amount of BRAM allocated for EDID in IP - xlnx,include-hdcp-1-4: Boolean parameter that denotes if hdcp14 is included. If present indicates inclusion of the optional core @@ -90,6 +92,7 @@ added to the device tree phys = <&vphy_lane0 0 1 1 0>, <&vphy_lane1 0 1 1 0>, <&vphy_lane2 0 1 1 0>; xlnx,input-pixels-per-clock = <0x2>; + xlnx,max-bits-per-component = <0xa>; xlnx,edid-ram-size = <0x100>; xlnx,include-hdcp-1-4; xlnx,include-hdcp-2-2; From e8da369eedd3cc9a27cecdcc68e47a22972d2612 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Thu, 15 Aug 2019 10:09:23 +0800 Subject: [PATCH 32/46] hdmitx:hdmirx:vphy: Driver update till 20190814 Signed-off-by: Shikhar Mishra --- hdmi/phy-xilinx-vphy/xhdcp1x.c | 16 +- hdmi/phy-xilinx-vphy/xhdcp1x_port.c | 9 +- hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_rx.c | 5 +- hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_tx.c | 5 +- hdmi/phy-xilinx-vphy/xhdcp1x_rx.c | 50 +- hdmi/phy-xilinx-vphy/xhdcp1x_tx.c | 92 +++- hdmi/phy-xilinx-vphy/xhdcp1x_tx.h | 2 +- hdmi/phy-xilinx-vphy/xv_hdmic.c | 513 ++++++++++++++++++-- hdmi/phy-xilinx-vphy/xv_hdmic.h | 112 ++++- hdmi/phy-xilinx-vphy/xvidc.c | 24 +- hdmi/phy-xilinx-vphy/xvidc.h | 6 +- hdmi/phy-xilinx-vphy/xvphy.h | 8 + hdmi/phy-xilinx-vphy/xvphy_gt.h | 10 +- hdmi/phy-xilinx-vphy/xvphy_hdmi.h | 8 + hdmi/phy-xilinx-vphy/xvphy_hw.h | 8 + hdmi/phy-xilinx-vphy/xvphy_i.h | 10 +- hdmi/phy-xilinx-vphy/xvphy_log.c | 7 +- hdmi/xilinx-hdmi-rx/xv_hdmirx.c | 492 ++++++++++--------- hdmi/xilinx-hdmi-rx/xv_hdmirx.h | 15 +- hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c | 38 +- hdmi/xilinx-hdmi-rx/xv_hdmirxss.c | 47 +- hdmi/xilinx-hdmi-rx/xv_hdmirxss.h | 17 +- hdmi/xilinx-hdmi-rx/xv_hdmirxss_log.c | 48 +- hdmi/xilinx-hdmi-tx/xv_hdmitx.c | 15 +- hdmi/xilinx-hdmi-tx/xv_hdmitx.h | 8 +- hdmi/xilinx-hdmi-tx/xv_hdmitx_intr.c | 8 +- hdmi/xilinx-hdmi-tx/xv_hdmitxss.c | 23 +- hdmi/xilinx-hdmi-tx/xv_hdmitxss.h | 8 +- hdmi/xilinx-hdmi-tx/xvtc.c | 5 +- hdmi/xilinx-hdmi-tx/xvtc_hw.h | 2 + hdmi/xilinx-hdmi-tx/xvtc_intr.c | 2 +- 31 files changed, 1190 insertions(+), 423 deletions(-) diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x.c b/hdmi/phy-xilinx-vphy/xhdcp1x.c index 8e91157..a6a9de7 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x.c @@ -71,6 +71,14 @@ /************************** Constant Definitions *****************************/ +#if defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0) +#define INCLUDE_TX +#endif +#if defined(XPAR_XV_HDMIRX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX1_NUM_INSTANCES > 0) +#define INCLUDE_RX +#endif #if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) #define INCLUDE_TX #endif @@ -137,9 +145,9 @@ int XHdcp1x_CfgInitialize(XHdcp1x *InstancePtr, const XHdcp1x_Config *CfgPtr, Xil_AssertNonvoid(CfgPtr != NULL); Xil_AssertNonvoid(EffectiveAddr != (UINTPTR)NULL); - /* clear instance */ - memset(InstancePtr, 0, sizeof(XHdcp1x)); - + /* Setup the InstancePtr. */ + (void)memset((void *)InstancePtr, 0, sizeof(XHdcp1x)); + /* Initialize InstancePtr. */ InstancePtr->Config = *CfgPtr; InstancePtr->Config.BaseAddress = EffectiveAddr; @@ -226,7 +234,7 @@ int XHdcp1x_CfgInitialize(XHdcp1x *InstancePtr, const XHdcp1x_Config *CfgPtr, /* Initialize RX */ XHdcp1x_RxInit(InstancePtr); } - + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; return (XST_SUCCESS); diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_port.c b/hdmi/phy-xilinx-vphy/xhdcp1x_port.c index 8c2f567..6766cea 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_port.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_port.c @@ -43,7 +43,14 @@ /************************** Constant Definitions *****************************/ - +#if defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0) +#define INCLUDE_HDMI_TX +#endif +#if defined(XPAR_XV_HDMIRX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX1_NUM_INSTANCES > 0) +#define INCLUDE_HDMI_RX +#endif #if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) #define INCLUDE_HDMI_TX #endif diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_rx.c b/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_rx.c index dc6f7c8..4945937 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_rx.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_rx.c @@ -46,7 +46,10 @@ /***************************** Include Files *********************************/ -#if defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && (XPAR_XV_HDMIRX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMIRX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX1_NUM_INSTANCES > 0)) //#include #include #include "xhdcp1x_port.h" diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_tx.c b/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_tx.c index 58cd40b..ceae72d 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_tx.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_tx.c @@ -39,7 +39,10 @@ /***************************** Include Files *********************************/ -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) //#include #include #include "xhdcp1x_port.h" diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_rx.c b/hdmi/phy-xilinx-vphy/xhdcp1x_rx.c index 55c389c..f704387 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_rx.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_rx.c @@ -72,7 +72,10 @@ #include "xhdcp1x_cipher.h" #include "xhdcp1x_debug.h" #include "xhdcp1x_port.h" -#if defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && (XPAR_XV_HDMIRX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMIRX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX1_NUM_INSTANCES > 0)) #include "xhdcp1x_port_hdmi.h" #else #include "xhdcp1x_port_dp.h" @@ -1245,7 +1248,10 @@ static void XHdcp1x_RxPollForComputations(XHdcp1x *InstancePtr, XHdcp1x_PortWrite(InstancePtr, XHDCP1X_PORT_OFFSET_RO, Buf, 2); -#if defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && (XPAR_XV_HDMIRX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMIRX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX1_NUM_INSTANCES > 0)) /* No reset required in the sofware for HDMI. KSV fifo * pointer reset is implemented in the hardware. */ @@ -1517,7 +1523,10 @@ void XHdcp1x_RxSetTopologyDeviceCnt(XHdcp1x *InstancePtr, u32 Value) ******************************************************************************/ void XHdcp1x_RxSetTopologyMaxCascadeExceeded(XHdcp1x *InstancePtr, u8 Value) { -#if defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && (XPAR_XV_HDMIRX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMIRX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX1_NUM_INSTANCES > 0)) u32 BStatus; @@ -1561,7 +1570,10 @@ void XHdcp1x_RxSetTopologyMaxDevsExceeded(XHdcp1x *InstancePtr, u8 Value) Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Value == FALSE || Value == TRUE); -#if defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && (XPAR_XV_HDMIRX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMIRX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX1_NUM_INSTANCES > 0)) u16 DevCntErr = (Value & 0xFFFF); u32 BStatus; @@ -1604,7 +1616,10 @@ void XHdcp1x_RxSetHdmiMode(XHdcp1x *InstancePtr, u8 Value) /* Verify arguments */ Xil_AssertVoid(InstancePtr != NULL); -#if defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && (XPAR_XV_HDMIRX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMIRX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX1_NUM_INSTANCES > 0)) u32 BStatus; /* Update the value of HDMI_MODE bit in the BStatus Register */ @@ -1655,7 +1670,10 @@ static void XHdcp1x_RxAssembleKSVList(XHdcp1x *InstancePtr, *NextStatePtr = XHDCP1X_STATE_UNAUTHENTICATED; } else { -#if defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && (XPAR_XV_HDMIRX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMIRX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX1_NUM_INSTANCES > 0)) u32 BCaps; #else u32 BInfo; @@ -1668,7 +1686,10 @@ static void XHdcp1x_RxAssembleKSVList(XHdcp1x *InstancePtr, u32 ksvCount, ksvsToWrite; u16 RepeaterInfo = 0; -#if defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && (XPAR_XV_HDMIRX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMIRX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX1_NUM_INSTANCES > 0)) /* Ensure that the READY bit is clear */ /* Update the Ready bit in the BCaps Register */ @@ -1718,7 +1739,10 @@ static void XHdcp1x_RxAssembleKSVList(XHdcp1x *InstancePtr, tempKsv = InstancePtr->RepeaterValues.KsvList[ksvCount]; XHDCP1X_PORT_UINT_TO_BUF(Buf, tempKsv , (XHDCP1X_PORT_SIZE_BKSV * 8)); -#if defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && (XPAR_XV_HDMIRX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMIRX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX1_NUM_INSTANCES > 0)) /* Write the KSV to the HDCP_DAT register each time, * The KSV Fifo will auto increment @@ -1737,7 +1761,10 @@ static void XHdcp1x_RxAssembleKSVList(XHdcp1x *InstancePtr, ksvsToWrite -= 1; } -#if defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && (XPAR_XV_HDMIRX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMIRX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX1_NUM_INSTANCES > 0)) RepeaterInfo = (XHDCP1X_PORT_BIT_BSTATUS_HDMI_MODE) | (XHDCP1X_PORT_BSTATUS_BIT_DEPTH_NO_ERR) | (InstancePtr->RepeaterValues.Depth << @@ -1756,7 +1783,10 @@ static void XHdcp1x_RxAssembleKSVList(XHdcp1x *InstancePtr, XHdcp1x_RxCalculateSHA1Value(InstancePtr,RepeaterInfo); -#if defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && (XPAR_XV_HDMIRX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMIRX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMIRX1_NUM_INSTANCES > 0)) /* Update the value of V'H0 */ sha1value = 0; diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_tx.c b/hdmi/phy-xilinx-vphy/xhdcp1x_tx.c index 29c1f12..0c5a0a0 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_tx.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_tx.c @@ -17,7 +17,7 @@ /** * * @file xhdcp1x_tx.c -* @addtogroup hdcp1x_v4_0 +* @addtogroup hdcp1x_v4_2 * @{ * * This contains the main implementation file for the Xilinx HDCP transmit @@ -78,7 +78,10 @@ #include "xhdcp1x_debug.h" #include "xhdcp1x_platform.h" #include "xhdcp1x_port.h" -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) #include "xhdcp1x_port_hdmi.h" #else #include "xhdcp1x_port_dp.h" @@ -806,7 +809,10 @@ void XHdcp1x_TxSetHdmiMode(XHdcp1x *InstancePtr, u8 Value) Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Value == FALSE || Value == TRUE); -#if defined(XPAR_XV_HDMIRX_NUM_INSTANCES) && (XPAR_XV_HDMIRX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) InstancePtr->Tx.TxIsHdmi = Value; #else UNUSED(Value); @@ -1821,7 +1827,10 @@ static void XHdcp1x_TxPollForWaitForReady(XHdcp1x *InstancePtr, } /* Check for cascade exceeded */ else { -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) /* Disable the hdcp encryption for both HDMI and DP. * But currently only doing it for HDMI. */ XHdcp1x_TxDisableEncryptionState(InstancePtr); @@ -1905,7 +1914,10 @@ static int XHdcp1x_TxValidateKsvList(XHdcp1x *InstancePtr, u16 RepeaterInfo) u8 ksvListHolder[127*XHDCP1X_PORT_SIZE_BKSV]; -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) #else @@ -1930,7 +1942,10 @@ static int XHdcp1x_TxValidateKsvList(XHdcp1x *InstancePtr, u16 RepeaterInfo) /* Determine theNumToRead */ NumToRead = (((RepeaterInfo & 0x7Fu) * 5)); -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) /* Read the ksv list */ /* Read the entire KSV fifo list in one go */ int ByteCount = 0; @@ -2039,7 +2054,10 @@ static int XHdcp1x_TxValidateKsvList(XHdcp1x *InstancePtr, u16 RepeaterInfo) /* Insert RepeaterInfo into the SHA-1 transform */ Buf[0] = (u8) (RepeaterInfo & 0xFFu); -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) Buf[1] = (u8) ( ((RepeaterInfo | (XHDCP1X_PORT_BIT_BSTATUS_HDMI_MODE)) >> XHDCP1X_PORT_BSTATUS_DEPTH_SHIFT) & 0xFFu); @@ -2078,7 +2096,10 @@ static int XHdcp1x_TxValidateKsvList(XHdcp1x *InstancePtr, u16 RepeaterInfo) /* Read the value from the far end */ if (XHdcp1x_PortRead(InstancePtr, Offset, Buf, 4) > 0) { -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) /* Storing the V' prime values later */ #else memcpy(&InstancePtr->RepeaterValues.V[Offset - @@ -2116,7 +2137,10 @@ static int XHdcp1x_TxValidateKsvList(XHdcp1x *InstancePtr, u16 RepeaterInfo) if (InstancePtr->IsRepeater) { -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) /* Do nothing */ #else /* Update this value in the RepeaterExchange @@ -2274,7 +2298,10 @@ u32 XHdcp1x_TxGetTopologyMaxCascadeExceeded(XHdcp1x *InstancePtr) u32 Buf; u32 Status; -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) /* Read the BStatus Register */ XHdcp1x_PortRead(InstancePtr, XHDCP1X_PORT_OFFSET_BSTATUS, &Buf, XHDCP1X_PORT_SIZE_BSTATUS); @@ -2352,7 +2379,10 @@ u32 XHdcp1x_TxGetTopologyMaxDevsExceeded(XHdcp1x *InstancePtr) u32 Buf; u32 Status; -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) /* Read the BStatus Register */ XHdcp1x_PortRead(InstancePtr, XHDCP1X_PORT_OFFSET_BSTATUS, &Buf, XHDCP1X_PORT_SIZE_BSTATUS); @@ -2422,13 +2452,19 @@ static int XHdcp1x_TxSetRepeaterInfo(XHdcp1x *InstancePtr) /* Check for repeater */ if (XHdcp1x_PortIsRepeater(InstancePtr)) { -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) u32 Buf; #else u16 RepeaterInfo; #endif -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) /* Set the SHA1 Hash value */ XHdcp1x_PortRead(InstancePtr, XHDCP1X_PORT_OFFSET_VH0, @@ -2465,7 +2501,10 @@ static int XHdcp1x_TxSetRepeaterInfo(XHdcp1x *InstancePtr) /* Do nothing for DP */ #endif -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) /* Copy the Depth read from the downstream HDCP device */ XHdcp1x_PortRead(InstancePtr, XHDCP1X_PORT_OFFSET_BSTATUS, @@ -2985,7 +3024,10 @@ static void XHdcp1x_TxRunWaitForReadyState(XHdcp1x *InstancePtr, /* For poll */ case XHDCP1X_EVENT_POLL: -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) /* Don't read the Repeater info for HDMI from a * poll from application. We'll poll every 100ms. */ #else @@ -3007,7 +3049,10 @@ static void XHdcp1x_TxRunWaitForReadyState(XHdcp1x *InstancePtr, case XHDCP1X_EVENT_TIMEOUT: XHdcp1x_TxDebugLog(InstancePtr, "wait-for-ready timeout"); -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) InstancePtr->Tx.WaitForReadyPollCntFlag++; XHdcp1x_TxStopTimer(InstancePtr); XHdcp1x_TxPollForWaitForReady(InstancePtr, @@ -3230,7 +3275,10 @@ static void XHdcp1x_TxEnterState(XHdcp1x *InstancePtr, XHdcp1x_StateType State, /* For the validate rx state */ case XHDCP1X_STATE_TESTFORREPEATER: -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) /* Enable encryption for HDMI (this will come immediately * after Ro' has been read and successfully compared). */ InstancePtr->Tx.EncryptionMap = 0x1; @@ -3246,7 +3294,10 @@ static void XHdcp1x_TxEnterState(XHdcp1x *InstancePtr, XHdcp1x_StateType State, case XHDCP1X_STATE_WAITFORREADY: InstancePtr->Tx.StateHelper = 0; -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) InstancePtr->Tx.WaitForReadyPollCntFlag = 0; /* Post the timeout */ XHdcp1x_TxPostEvent(InstancePtr, XHDCP1X_EVENT_TIMEOUT); @@ -3287,7 +3338,10 @@ static void XHdcp1x_TxEnterState(XHdcp1x *InstancePtr, XHdcp1x_StateType State, if (InstancePtr->IsRepeater == 1) { if(InstancePtr->Tx.DownstreamReady == 1) { InstancePtr->Tx.DownstreamReady = 0; -#if defined(XPAR_XV_HDMITX_NUM_INSTANCES) && (XPAR_XV_HDMITX_NUM_INSTANCES > 0) +#if (defined(XPAR_XV_HDMITX_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX_NUM_INSTANCES > 0)) || \ + (defined(XPAR_XV_HDMITX1_NUM_INSTANCES) && \ + (XPAR_XV_HDMITX1_NUM_INSTANCES > 0)) /* Do nothing for HDMI. */ #else /* In case of DisplayPort , read the Downstream Repeater diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_tx.h b/hdmi/phy-xilinx-vphy/xhdcp1x_tx.h index 09e65f8..f9a006f 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_tx.h +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_tx.h @@ -17,7 +17,7 @@ /** * * @file xhdcp1x_tx.h -* @addtogroup hdcp1x_v4_0 +* @addtogroup hdcp1x_v4_2 * @{ * * This file provides the interface of the HDCP TX state machine diff --git a/hdmi/phy-xilinx-vphy/xv_hdmic.c b/hdmi/phy-xilinx-vphy/xv_hdmic.c index 927a4fd..d306985 100644 --- a/hdmi/phy-xilinx-vphy/xv_hdmic.c +++ b/hdmi/phy-xilinx-vphy/xv_hdmic.c @@ -30,6 +30,7 @@ * ----- ---- -------- ----------------------------------------------- * 1.0 EB 21/12/17 Initial release. * 1.1 EB 10/04/18 Fixed a bug in XV_HdmiC_ParseAudioInfoFrame + * 1.2 EB 18/06/19 Added FrlRateTable * * *******************************************************************************/ @@ -47,57 +48,471 @@ * 2) Video Identification Code. */ const XHdmiC_VicTable VicTable[VICTABLE_SIZE] = { - {XVIDC_VM_640x480_60_P, 1}, // Vic 1 - {XVIDC_VM_720x480_60_P, 2}, // Vic 2 - {XVIDC_VM_720x480_60_P, 3}, // Vic 3 - {XVIDC_VM_1280x720_60_P, 4}, // Vic 4 - {XVIDC_VM_1920x1080_60_I, 5}, // Vic 5 - {XVIDC_VM_1440x480_60_I, 6}, // Vic 6 - {XVIDC_VM_1440x480_60_I, 7}, // Vic 7 - - {XVIDC_VM_1920x1080_60_P, 16}, // Vic 16 - {XVIDC_VM_720x576_50_P, 17}, // Vic 17 - {XVIDC_VM_720x576_50_P, 18}, // Vic 18 - {XVIDC_VM_1280x720_50_P, 19}, // Vic 19 - {XVIDC_VM_1920x1080_50_I, 20}, // Vic 20 - {XVIDC_VM_1440x576_50_I, 21}, // Vic 21 - {XVIDC_VM_1440x576_50_I, 22}, // Vic 22 - - // 1680 x 720 - {XVIDC_VM_1680x720_50_P, 82}, // Vic 82 - {XVIDC_VM_1680x720_60_P, 83}, // Vic 83 - {XVIDC_VM_1680x720_100_P, 84}, // Vic 84 - {XVIDC_VM_1680x720_120_P, 85}, // Vic 85 - - // 1920 x 1080 - {XVIDC_VM_1920x1080_24_P, 32}, // Vic 32 - {XVIDC_VM_1920x1080_25_P, 33}, // Vic 33 - {XVIDC_VM_1920x1080_30_P, 34}, // Vic 34 - {XVIDC_VM_1920x1080_50_P, 31}, // Vic 31 - {XVIDC_VM_1920x1080_100_P, 64}, // Vic 64 - {XVIDC_VM_1920x1080_120_P, 63}, // Vic 63 - - // 2560 x 1080 - {XVIDC_VM_2560x1080_50_P, 89}, // Vic 89 - {XVIDC_VM_2560x1080_60_P, 90}, // Vic 89 - {XVIDC_VM_2560x1080_100_P, 91}, // Vic 91 - {XVIDC_VM_2560x1080_120_P, 92}, // Vic 92 - - // 3840 x 2160 - {XVIDC_VM_3840x2160_24_P, 93}, // Vic 93 - {XVIDC_VM_3840x2160_25_P, 94}, // Vic 94 - {XVIDC_VM_3840x2160_30_P, 95}, // Vic 95 - {XVIDC_VM_3840x2160_50_P, 96}, // Vic 96 - {XVIDC_VM_3840x2160_60_P, 97}, // Vic 97 - - // 4096 x 2160 - {XVIDC_VM_4096x2160_24_P, 98}, // Vic 98 - {XVIDC_VM_4096x2160_25_P, 99}, // Vic 99 - {XVIDC_VM_4096x2160_30_P, 100}, // Vic 100 - {XVIDC_VM_4096x2160_50_P, 101}, // Vic 101 - {XVIDC_VM_4096x2160_60_P, 102} // Vic 102 + {XVIDC_VM_640x480_60_P, 1}, /* Vic 1 */ + {XVIDC_VM_720x480_60_P, 2}, /* Vic 2 */ + {XVIDC_VM_720x480_60_P, 3}, /* Vic 3 */ + {XVIDC_VM_1280x720_60_P, 4}, /* Vic 4 */ + {XVIDC_VM_1920x1080_60_I, 5}, /* Vic 5 */ + {XVIDC_VM_1440x480_60_I, 6}, /* Vic 6 */ + {XVIDC_VM_1440x480_60_I, 7}, /* Vic 7 */ + + {XVIDC_VM_1920x1080_60_P, 16}, /* Vic 16 */ + {XVIDC_VM_720x576_50_P, 17}, /* Vic 17 */ + {XVIDC_VM_720x576_50_P, 18}, /* Vic 18 */ + {XVIDC_VM_1280x720_50_P, 19}, /* Vic 19 */ + {XVIDC_VM_1920x1080_50_I, 20}, /* Vic 20 */ + {XVIDC_VM_1440x576_50_I, 21}, /* Vic 21 */ + {XVIDC_VM_1440x576_50_I, 22}, /* Vic 22 */ + + /* 1280 x 720 */ + {XVIDC_VM_1280x720_24_P, 65}, /* Vic 65 */ + {XVIDC_VM_1280x720_25_P, 66}, /* Vic 66 */ + {XVIDC_VM_1280x720_30_P, 67}, /* Vic 67 */ + {XVIDC_VM_1280x720_50_P, 68}, /* Vic 68 */ + {XVIDC_VM_1280x720_60_P, 69}, /* Vic 69 */ + {XVIDC_VM_1280x720_100_P, 70}, /* Vic 70 */ + {XVIDC_VM_1280x720_120_P, 71}, /* Vic 71 */ + + /* 1680 x 720 */ + {XVIDC_VM_1680x720_50_P, 82}, /* Vic 82 */ + {XVIDC_VM_1680x720_60_P, 83}, /* Vic 83 */ + {XVIDC_VM_1680x720_100_P, 84}, /* Vic 84 */ + {XVIDC_VM_1680x720_120_P, 85}, /* Vic 85 */ + + /* 1920 x 1080 */ + {XVIDC_VM_1920x1080_24_P, 32}, /* Vic 32 */ + {XVIDC_VM_1920x1080_25_P, 33}, /* Vic 33 */ + {XVIDC_VM_1920x1080_30_P, 34}, /* Vic 34 */ + {XVIDC_VM_1920x1080_50_P, 31}, /* Vic 31 */ + {XVIDC_VM_1920x1080_100_P, 64}, /* Vic 64 */ + {XVIDC_VM_1920x1080_120_P, 63}, /* Vic 63 */ + + /* 2560 x 1080 */ + {XVIDC_VM_2560x1080_24_P, 86}, /* Vic 86 */ + {XVIDC_VM_2560x1080_25_P, 87}, /* Vic 87 */ + {XVIDC_VM_2560x1080_30_P, 88}, /* Vic 88 */ + {XVIDC_VM_2560x1080_50_P, 89}, /* Vic 89 */ + {XVIDC_VM_2560x1080_60_P, 90}, /* Vic 90 */ + {XVIDC_VM_2560x1080_100_P, 91}, /* Vic 91 */ + {XVIDC_VM_2560x1080_120_P, 92}, /* Vic 92 */ + + /* 3840 x 2160 */ + {XVIDC_VM_3840x2160_24_P, 93}, /* Vic 93 */ + {XVIDC_VM_3840x2160_25_P, 94}, /* Vic 94 */ + {XVIDC_VM_3840x2160_30_P, 95}, /* Vic 95 */ + {XVIDC_VM_3840x2160_50_P, 96}, /* Vic 96 */ + {XVIDC_VM_3840x2160_60_P, 97}, /* Vic 97 */ + {XVIDC_VM_3840x2160_100_P, 117}, /* Vic 117 */ + {XVIDC_VM_3840x2160_120_P, 118}, /* Vic 118 */ + + /* 4096 x 2160 */ + {XVIDC_VM_4096x2160_24_P, 98}, /* Vic 98 */ + {XVIDC_VM_4096x2160_25_P, 99}, /* Vic 99 */ + {XVIDC_VM_4096x2160_30_P, 100}, /* Vic 100 */ + {XVIDC_VM_4096x2160_50_P, 101}, /* Vic 101 */ + {XVIDC_VM_4096x2160_60_P, 102}, /* Vic 102 */ + {XVIDC_VM_4096x2160_100_P, 218}, /* Vic 218 */ + {XVIDC_VM_4096x2160_120_P, 219}, /* Vic 219 */ + + /* 5120 x 2160 */ + {XVIDC_VM_5120x2160_24_P, 121}, /* Vic 121 */ + {XVIDC_VM_5120x2160_25_P, 122}, /* Vic 122 */ + {XVIDC_VM_5120x2160_30_P, 123}, /* Vic 123 */ + {XVIDC_VM_5120x2160_50_P, 125}, /* Vic 125 */ + {XVIDC_VM_5120x2160_60_P, 126}, /* Vic 126 */ + {XVIDC_VM_5120x2160_100_P, 127}, /* Vic 127 */ + {XVIDC_VM_5120x2160_120_P, 193}, /* Vic 193 */ + + /* 7680 x 4320 */ + {XVIDC_VM_7680x4320_24_P, 194}, /* Vic 194 */ + {XVIDC_VM_7680x4320_25_P, 195}, /* Vic 195 */ + {XVIDC_VM_7680x4320_30_P, 196}, /* Vic 196 */ + {XVIDC_VM_7680x4320_50_P, 198}, /* Vic 198 */ + {XVIDC_VM_7680x4320_60_P, 199}, /* Vic 199 */ + {XVIDC_VM_7680x4320_100_P, 200}, /* Vic 200 */ + {XVIDC_VM_7680x4320_120_P, 201}, /* Vic 201 */ + + /* 10240 x 4320 */ + {XVIDC_VM_10240x4320_24_P, 210}, /* Vic 210 */ + {XVIDC_VM_10240x4320_25_P, 211}, /* Vic 211 */ + {XVIDC_VM_10240x4320_30_P, 212}, /* Vic 212 */ + {XVIDC_VM_10240x4320_50_P, 214}, /* Vic 214 */ + {XVIDC_VM_10240x4320_60_P, 215}, /* Vic 215 */ + {XVIDC_VM_10240x4320_100_P, 216}, /* Vic 216 */ + {XVIDC_VM_10240x4320_120_P, 217}, /* Vic 217 */ }; +/** +* This table contains the attributes for various FRL Rate. +* Each entry is of the format: +* 1) Number of lanes +* 2) Line Rate. +*/ +const XHdmiC_FrlRate FrlRateTable[] = { + {3, 0}, /* XHDMIC_MAXFRLRATE_NOT_SUPPORTED */ + {3, 3}, /* XHDMIC_MAXFRLRATE_3X3GBITSPS */ + {3, 6}, /* XHDMIC_MAXFRLRATE_3X6GBITSPS */ + {4, 6}, /* XHDMIC_MAXFRLRATE_4X6GBITSPS */ + {4, 8}, /* XHDMIC_MAXFRLRATE_4X8GBITSPS */ + {4, 10}, /* XHDMIC_MAXFRLRATE_4X10GBITSPS */ + {4, 12}, /* XHDMIC_MAXFRLRATE_4X12GBITSPS */ +}; + +/** +* This table contains the CTS and N value of each TMDS character rate. +* Each entry is of the format: +* 1) Sample Frequency TMDS CLk, (32kHz, 44.1kHz, and 48kHz) +*/ +const XHdmiC_TMDS_N_Table TMDSChar_N_Table[] = +{ + /* TMDSClk 32k 44k1 48k 88k2 96k 176k4 192k */ + { 0, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + { 25200000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + { 27000000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + { 31500000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + { 33750000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + { 37800000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + { 40500000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + { 50400000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + { 54000000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + { 67500000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + { 74250000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + { 81000000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + { 92812500, { 8192, 6272, 12288, 12544, 24576, 25088, 49152}}, + {108000000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + {111375000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + {148500000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + {185625000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + {222750000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + {297000000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + {371250000, { 6144, 4704, 5120, 9408, 10240, 18816, 20480}}, + {445500000, { 4096, 4704, 5120, 9408, 10240, 18816, 20480}}, + {594000000, { 3072, 4704, 5120, 9408, 10240, 18816, 20480}} +}; + +/** +* This returns the the N Value based Audio Sampling Rate and TMDS +* Character Rate +*/ +u32 XHdmiC_TMDS_GetNVal(u32 TMDSCharRate, + XHdmiC_SamplingFrequency AudSampleFreq) +{ + XHdmiC_TMDS_N_Table const *item; + u32 i = 0; + + /* Proceed only with supported Audio Sampling Frequency */ + if (AudSampleFreq == XHDMIC_SAMPLING_FREQUENCY || + AudSampleFreq > XHDMIC_SAMPLING_FREQUENCY_192K) { + /* Since AudSampFreq not valid, return N Value = 0 */ + return 0; + } + + for(i = 0; i < sizeof(TMDSChar_N_Table)/sizeof(XHdmiC_TMDS_N_Table); i++) { + item = &TMDSChar_N_Table[i]; + /* 10kHz Tolerance */ + if(TMDSCharRate <= (item->TMDSCharRate + 10000) && + (TMDSCharRate >= (item->TMDSCharRate - 10000))) { + return item->ACR_NVal[AudSampleFreq-1]; + } + } + + /* If TMDS character rate could not be found return default values */ + item = &TMDSChar_N_Table[0]; + + return item->ACR_NVal[AudSampleFreq-1]; +} + +/** +* This returns the Audio Sampling Rate and TMDS +* Character Rate +*/ +XHdmiC_SamplingFrequency XHdmiC_TMDS_GetAudSampFreq(u32 TMDSCharRate, + u32 N) +{ + XHdmiC_TMDS_N_Table const *item; + u8 i = 0; + u8 j = 0; + + for(i = 0; i < sizeof(TMDSChar_N_Table)/sizeof(XHdmiC_TMDS_N_Table); i++) { + item = &TMDSChar_N_Table[i]; + if(TMDSCharRate <= (item->TMDSCharRate + 10000) && + (TMDSCharRate >= (item->TMDSCharRate - 10000))) { + for (j = 0; j < 7; j++) { + if(N == item->ACR_NVal[j]) { + return j; + break; + } + } + } + } + /* Return non-valid sample frequency */ + return XHDMIC_SAMPLING_FREQUENCY; +} + +/** +* Top level data structure for XHdmiC_FRL_CTS_N_Table_t +*/ +typedef struct { + /* 5 = FRL Rate 12,10,8,6,3 */ + XHdmiC_FRL_CTS_N_Val CTS_NVal[5]; +} XHdmiC_FRL_CTS_N_Table_t; + + +/** +* This table contains the CTS and N value of each FRL character rate. +* Each entry is of the format: +* 1) Sample Frequency (32kHz, 44.1kHz, and 48kHz) +*/ +const XHdmiC_FRL_CTS_N_Table_t FRL_CTS_N_Table[] = +{ + {/* 32kHz */ + { /* 3 Gbps */ + {171875, {4224, 8448, 16896, 33792, 67584, 135168}}, + /* 6 Gbps */ + {328125, {4032, 8064, 16128, 32256, 64512, 129024}}, + /* 8 Gbps */ + {437500, {4032, 8064, 16128, 32256, 64512, 129024}}, + /* 10 Gbps */ + {468750, {3456, 6912, 13824, 27648, 55296, 110592}}, + /* 12 Gbps */ + {500000, {3072, 6144, 12288, 24576, 49152, 98304 }}, + }, + }, + {/* 44.1kHz */ + { + {156250 ,{5292 ,10584 ,21168 ,42336 ,84672 ,169344}}, + {312500 ,{5292 ,10584 ,21168 ,42336 ,84672 ,169344}}, + {312500 ,{3969 ,7938 ,15876 ,31752 ,63504 ,127008}}, + {390625 ,{3969 ,7938 ,15876 ,31752 ,63504 ,127008}}, + {468750 ,{3969 ,7938 ,15876 ,31752 ,63504 ,127008}}, + }, + }, + {/* 48kHz */ + { + {156250 ,{5760 ,11520 ,23040 ,46080 ,92160 ,184320}}, + {328125 ,{6048 ,12096 ,24192 ,48384 ,96768 ,193536}}, + {437500 ,{6048 ,12096 ,24192 ,48384 ,96768 ,193536}}, + {468750 ,{5184 ,10368 ,20736 ,41472 ,82944 ,165888}}, + {515625 ,{4752 ,9504 ,19008 ,38016 ,76032 ,152064}}, + }, + }, +}; + +/** +* This returns the N value in FRL mode based on its Audio Sample Frequency +*/ +u32 XHdmiC_FRL_GetNVal(XHdmiC_FRLCharRate FRLCharRate, + XHdmiC_SamplingFrequencyVal AudSampleFreqVal) +{ + XHdmiC_FRL_CTS_N_Table_t const *item; + u8 SampleFreq; + u8 MultSampleFreq; + + /* Check for valid FRL Character Rate */ + if (FRLCharRate < R_166_667 && FRLCharRate > R_666_667 ) { + /* Since AudSampFreq not valid, return N Value = 0 */ + FRLCharRate = R_166_667; + } + + if (AudSampleFreqVal%XHDMIC_SAMPLING_FREQ_48K == 0) { + SampleFreq = 2; + MultSampleFreq = AudSampleFreqVal/XHDMIC_SAMPLING_FREQ_48K; + } else if (AudSampleFreqVal%XHDMIC_SAMPLING_FREQ_44_1K == 0) { + SampleFreq = 1; + MultSampleFreq = AudSampleFreqVal/XHDMIC_SAMPLING_FREQ_44_1K; + } else if (AudSampleFreqVal%XHDMIC_SAMPLING_FREQ_32K == 0) { + SampleFreq = 0; + MultSampleFreq = AudSampleFreqVal/XHDMIC_SAMPLING_FREQ_32K; + } else { + /* Not Valid Scenario */ + SampleFreq = 0; + MultSampleFreq = 0; + } + + /* MultSampleFreq is the divisible value from the 3 base + * Sample Frequency. + * However the N value array for FRL are based on the power of 2. + * {base_freq*(2^0),base_freq*(2^1),base_freq*(2^2),base_freq*(2^3),..} + */ + switch (MultSampleFreq) { + case 1: + case 2: + MultSampleFreq = MultSampleFreq - 1; + break; + + case 4: + MultSampleFreq = 2; + break; + + case 8: + MultSampleFreq = 3; + break; + + case 16: + MultSampleFreq = 4; + break; + + case 32: + MultSampleFreq = 5; + break; + + default: + MultSampleFreq = 0; + break; + } + + item = &FRL_CTS_N_Table[SampleFreq]; + return item->CTS_NVal[FRLCharRate].ACR_NVal[MultSampleFreq]; + +} + +/** +* This returns the Audio Sample Frequency for FRL +*/ +XHdmiC_SamplingFrequencyVal + XHdmiC_FRL_GetAudSampFreq(XHdmiC_FRLCharRate FRLCharRate, + u32 CTS, u32 N) +{ + XHdmiC_FRL_CTS_N_Table_t const *item; + u8 Index_0 = 0; + u8 Index_1 = 0; + XHdmiC_SamplingFrequencyVal SampleFreq = XHDMIC_SAMPLING_FREQ; + + item = &FRL_CTS_N_Table[SampleFreq]; + for (Index_0 = 0; Index_0 < 3; Index_0++) { + item = &FRL_CTS_N_Table[Index_0]; + /* Adding tolerance of 10k CTS */ + if ((CTS < (item->CTS_NVal[FRLCharRate].ACR_CTSVal + 10000)) && + (CTS > (item->CTS_NVal[FRLCharRate].ACR_CTSVal - 10000))) { + for (Index_1 = 0; Index_1 < 6; Index_1++) { + if (N == + item->CTS_NVal[FRLCharRate].ACR_NVal[Index_1]){ + if (Index_0 == 0) { + SampleFreq = + XHDMIC_SAMPLING_FREQ_32K << Index_1; + } else if (Index_0 == 1) { + SampleFreq = + XHDMIC_SAMPLING_FREQ_44_1K << Index_1; + } else { + SampleFreq = + XHDMIC_SAMPLING_FREQ_48K << Index_1; + } + break; + } + } + } + } + return SampleFreq; +} + +/** +* This converts the Aud. Sampling Freq. Value to +* Audio Info-frame Sampling Freq. Format. +*/ +XHdmiC_SamplingFrequency + XHdmiC_GetAudIFSampFreq (XHdmiC_SamplingFrequencyVal AudSampFreqVal) +{ + XHdmiC_SamplingFrequency ExtACRSampFreq; + + switch (AudSampFreqVal) { + case XHDMIC_SAMPLING_FREQ_32K: + ExtACRSampFreq = + XHDMIC_SAMPLING_FREQUENCY_32K; + break; + + case XHDMIC_SAMPLING_FREQ_44_1K: + ExtACRSampFreq = + XHDMIC_SAMPLING_FREQUENCY_44_1K; + break; + + case XHDMIC_SAMPLING_FREQ_48K: + ExtACRSampFreq = + XHDMIC_SAMPLING_FREQUENCY_48K; + break; + + case XHDMIC_SAMPLING_FREQ_88_2K: + ExtACRSampFreq = + XHDMIC_SAMPLING_FREQUENCY_88_2K; + break; + + case XHDMIC_SAMPLING_FREQ_96K: + ExtACRSampFreq = + XHDMIC_SAMPLING_FREQUENCY_96K; + break; + + case XHDMIC_SAMPLING_FREQ_176_4K: + ExtACRSampFreq = + XHDMIC_SAMPLING_FREQUENCY_176_4K; + break; + + case XHDMIC_SAMPLING_FREQ_192K: + ExtACRSampFreq = + XHDMIC_SAMPLING_FREQUENCY_192K; + break; + + default: + ExtACRSampFreq = + XHDMIC_SAMPLING_FREQ; + break; + } + + return ExtACRSampFreq; +} + +/** +* This converts the Audio Info-frame Sampling Freq. Format. to +* Audio Sampling Freq. Value. +*/ +XHdmiC_SamplingFrequencyVal + XHdmiC_GetAudSampFreqVal(XHdmiC_SamplingFrequency AudSampFreqVal) +{ + XHdmiC_SamplingFrequencyVal ExtACRSampFreq; + + switch (AudSampFreqVal) { + case XHDMIC_SAMPLING_FREQUENCY_32K: + ExtACRSampFreq = + XHDMIC_SAMPLING_FREQ_32K; + break; + + case XHDMIC_SAMPLING_FREQUENCY_44_1K: + ExtACRSampFreq = + XHDMIC_SAMPLING_FREQ_44_1K; + break; + + case XHDMIC_SAMPLING_FREQUENCY_48K: + ExtACRSampFreq = + XHDMIC_SAMPLING_FREQ_48K; + break; + + case XHDMIC_SAMPLING_FREQUENCY_88_2K: + ExtACRSampFreq = + XHDMIC_SAMPLING_FREQ_88_2K; + break; + + case XHDMIC_SAMPLING_FREQUENCY_96K: + ExtACRSampFreq = + XHDMIC_SAMPLING_FREQ_96K; + break; + + case XHDMIC_SAMPLING_FREQUENCY_176_4K: + ExtACRSampFreq = + XHDMIC_SAMPLING_FREQ_176_4K; + break; + + case XHDMIC_SAMPLING_FREQUENCY_192K: + ExtACRSampFreq = + XHDMIC_SAMPLING_FREQ_192K; + break; + + default: + ExtACRSampFreq = + XHDMIC_SAMPLING_FREQ_32K; + break; + } + + return ExtACRSampFreq; +} + /*************************** Function Definitions *****************************/ /** diff --git a/hdmi/phy-xilinx-vphy/xv_hdmic.h b/hdmi/phy-xilinx-vphy/xv_hdmic.h index 7e2f0cd..e9b8fe4 100644 --- a/hdmi/phy-xilinx-vphy/xv_hdmic.h +++ b/hdmi/phy-xilinx-vphy/xv_hdmic.h @@ -35,7 +35,8 @@ * *******************************************************************************/ -#ifndef XV_HDMIC_H_ /* Prevent circular inclusions by using protection macros. */ +#ifndef XV_HDMIC_H_ /* Prevent circular inclusions by + using protection macros. */ #define XV_HDMIC_H_ #ifdef __cplusplus @@ -50,7 +51,7 @@ extern "C" { #include "xil_assert.h" /************************** Constant Definitions ******************************/ -#define VICTABLE_SIZE 38 +#define VICTABLE_SIZE 73 #define AUX_VSIF_TYPE 0x81 #define AUX_AVI_INFOFRAME_TYPE 0x82 #define AUX_GENERAL_CONTROL_PACKET_TYPE 0x3 @@ -208,6 +209,30 @@ typedef enum { XHDMIC_SAMPLING_FREQUENCY_192K } XHdmiC_SamplingFrequency; +typedef enum { + XHDMIC_SAMPLING_FREQ = 0, + XHDMIC_SAMPLING_FREQ_32K = 32000, + XHDMIC_SAMPLING_FREQ_64K = 32000, + XHDMIC_SAMPLING_FREQ_128K = 128000, + XHDMIC_SAMPLING_FREQ_256K = 128000, + XHDMIC_SAMPLING_FREQ_512K = 128000, + XHDMIC_SAMPLING_FREQ_1024K = 1024000, + + XHDMIC_SAMPLING_FREQ_44_1K = 44100, + XHDMIC_SAMPLING_FREQ_88_2K = 88200, + XHDMIC_SAMPLING_FREQ_176_4K = 176400, + XHDMIC_SAMPLING_FREQ_352_8K = 352800, + XHDMIC_SAMPLING_FREQ_705_6K = 705600, + XHDMIC_SAMPLING_FREQ_1411_2K = 1411200, + + XHDMIC_SAMPLING_FREQ_48K = 48000, + XHDMIC_SAMPLING_FREQ_96K = 96000, + XHDMIC_SAMPLING_FREQ_192K = 192000, + XHDMIC_SAMPLING_FREQ_384K = 384000, + XHDMIC_SAMPLING_FREQ_768K = 768000, + XHDMIC_SAMPLING_FREQ_1536K = 1536000, +} XHdmiC_SamplingFrequencyVal; + typedef enum { XHDMIC_SAMPLE_SIZE, XHDMIC_SAMPLE_SIZE_16, @@ -270,7 +295,58 @@ typedef enum { } XHdmiC_LevelShiftValue; /** - * This typedef contains the data structure for Auxiliary Video Information Info frame +* FRL Character Rate Enumeration +*/ +typedef enum { + R_166_667 = 0, /* 3 Gbps */ + R_333_333, /* 6 Gbps */ + R_444_444, /* 8 Gbps */ + R_555_556, /* 10 Gbps */ + R_666_667, /* 12 Gbps */ +} XHdmiC_FRLCharRate; + +/** +* FRL Rate Enumeration +*/ +typedef enum { + XHDMIC_MAXFRLRATE_NOT_SUPPORTED, + XHDMIC_MAXFRLRATE_3X3GBITSPS, + XHDMIC_MAXFRLRATE_3X6GBITSPS, + XHDMIC_MAXFRLRATE_4X6GBITSPS, + XHDMIC_MAXFRLRATE_4X8GBITSPS, + XHDMIC_MAXFRLRATE_4X10GBITSPS, + XHDMIC_MAXFRLRATE_4X12GBITSPS, + XHDMIC_MAXFRLRATE_SIZE, + XHDMIC_MAXFRLRATE_TMDSONLY = XHDMIC_MAXFRLRATE_NOT_SUPPORTED +} XHdmiC_MaxFrlRate; + +/** +* FRL CTS/N Value Table +*/ +typedef struct { + u32 ACR_CTSVal; + u32 ACR_NVal[6]; /* multiply of 6 of the initial Sample Freq */ +} XHdmiC_FRL_CTS_N_Val; + +/** +* TMDS Char/N Value Table +*/ +typedef struct { + u32 TMDSCharRate; + u32 ACR_NVal[7]; +} XHdmiC_TMDS_N_Table; + +/** +* This typedef contains translations of FRL_Rate to Lanes and Line Rates. +*/ +typedef struct { + u8 Lanes; /**< No of Lanes */ + u8 LineRate; /**< Line Rate */ +} XHdmiC_FrlRate; + +/** + * This typedef contains the data structure for + * Auxiliary Video Information Info frame */ typedef struct XHDMIC_AVI_InfoFrame { unsigned char Version; @@ -324,18 +400,36 @@ typedef struct XHdmiC_Audio_InfoFrame { /*************************** Variable Declarations ****************************/ extern const XHdmiC_VicTable VicTable[VICTABLE_SIZE]; - +extern const XHdmiC_FrlRate FrlRateTable[]; /************************** Function Prototypes ******************************/ -void XV_HdmiC_ParseAVIInfoFrame(XHdmiC_Aux *AuxPtr, XHdmiC_AVI_InfoFrame *infoFramePtr); -void XV_HdmiC_ParseGCP(XHdmiC_Aux *AuxPtr, XHdmiC_GeneralControlPacket *GcpPtr); -void XV_HdmiC_ParseAudioInfoFrame(XHdmiC_Aux *AuxPtr, XHdmiC_AudioInfoFrame *AudIFPtr); +void XV_HdmiC_ParseAVIInfoFrame(XHdmiC_Aux *AuxPtr, + XHdmiC_AVI_InfoFrame *infoFramePtr); +void XV_HdmiC_ParseGCP(XHdmiC_Aux *AuxPtr, + XHdmiC_GeneralControlPacket *GcpPtr); +void XV_HdmiC_ParseAudioInfoFrame(XHdmiC_Aux *AuxPtr, + XHdmiC_AudioInfoFrame *AudIFPtr); XHdmiC_Aux XV_HdmiC_AVIIF_GeneratePacket(XHdmiC_AVI_InfoFrame *infoFramePtr); -XHdmiC_Aux XV_HdmiC_AudioIF_GeneratePacket(XHdmiC_AudioInfoFrame *AudioInfoFrame); -XHdmiC_Colorspace XV_HdmiC_XVidC_To_IfColorformat(XVidC_ColorFormat ColorFormat); +XHdmiC_Aux + XV_HdmiC_AudioIF_GeneratePacket(XHdmiC_AudioInfoFrame *AudioInfoFrame); +XHdmiC_Colorspace + XV_HdmiC_XVidC_To_IfColorformat(XVidC_ColorFormat ColorFormat); XVidC_AspectRatio XV_HdmiC_IFAspectRatio_To_XVidC(XHdmiC_PicAspectRatio AR); +u32 XHdmiC_FRL_GetNVal(XHdmiC_FRLCharRate FRLCharRate, + XHdmiC_SamplingFrequencyVal AudSampleFreqVal); +u32 XHdmiC_TMDS_GetNVal(u32 TMDSCharRate, + XHdmiC_SamplingFrequency AudSampleFreq); +XHdmiC_SamplingFrequencyVal + XHdmiC_FRL_GetAudSampFreq(XHdmiC_FRLCharRate FRLCharRate, + u32 CTS, u32 N); +XHdmiC_SamplingFrequency XHdmiC_TMDS_GetAudSampFreq(u32 TMDSCharRate, + u32 N); +XHdmiC_SamplingFrequency + XHdmiC_GetAudIFSampFreq (XHdmiC_SamplingFrequencyVal AudSampFreqVal); +XHdmiC_SamplingFrequencyVal + XHdmiC_GetAudSampFreqVal(XHdmiC_SamplingFrequency AudSampFreqVal); #ifdef __cplusplus } #endif diff --git a/hdmi/phy-xilinx-vphy/xvidc.c b/hdmi/phy-xilinx-vphy/xvidc.c index 64dff26..fc28f96 100644 --- a/hdmi/phy-xilinx-vphy/xvidc.c +++ b/hdmi/phy-xilinx-vphy/xvidc.c @@ -147,7 +147,7 @@ void XVidC_UnregisterCustomTimingModes(void) * @note None. * *******************************************************************************/ -u32 XVidC_GetPixelClockHzByHVFr(u32 HTotal, u32 VTotal, u8 FrameRate) +u64 XVidC_GetPixelClockHzByHVFr(u32 HTotal, u32 VTotal, u8 FrameRate) { return (HTotal * VTotal * FrameRate); } @@ -163,9 +163,9 @@ u32 XVidC_GetPixelClockHzByHVFr(u32 HTotal, u32 VTotal, u8 FrameRate) * @note None. * *******************************************************************************/ -u32 XVidC_GetPixelClockHzByVmId(XVidC_VideoMode VmId) +u64 XVidC_GetPixelClockHzByVmId(XVidC_VideoMode VmId) { - u32 ClkHz; + u64 ClkHz; const XVidC_VideoTimingMode *VmPtr; VmPtr = XVidC_GetVideoModeData(VmId); @@ -574,6 +574,13 @@ XVidC_VideoMode XVidC_GetVideoModeIdExtensive(XVidC_VideoTiming *Timing, Timing->F1VSyncWidth)) { ResFound = (TRUE); break; + } else { + Mid = Mid + 1; + HActive = + XVidC_VideoTimingModes[Mid].Timing.HActive; + VActive = + XVidC_VideoTimingModes[Mid].Timing.VActive; + Rate = XVidC_VideoTimingModes[Mid].FrameRate; } } /* Check next entry */ @@ -739,6 +746,9 @@ const char *XVidC_GetFrameRateStr(XVidC_VideoMode VmId) case (XVIDC_FR_96HZ): return ("96Hz"); case (XVIDC_FR_100HZ): return ("100Hz"); case (XVIDC_FR_120HZ): return ("120Hz"); + case (XVIDC_FR_144HZ): return ("144Hz"); + case (XVIDC_FR_200HZ): return ("200Hz"); + case (XVIDC_FR_240HZ): return ("240Hz"); default: return ("Frame rate not supported"); @@ -1083,19 +1093,19 @@ void XVidC_ReportStreamInfo(const XVidC_VideoStream *Stream) Stream->FrameRate); xil_printf("\tResolution: %dx%d [Custom Mode]\r\n", Stream->Timing.HActive, Stream->Timing.VActive); - xil_printf("\tPixel Clock: %d\r\n", + xil_printf("\tPixel Clock: %d kHz\r\n", XVidC_GetPixelClockHzByHVFr( Stream->Timing.HTotal, Stream->Timing.F0PVTotal, - Stream->FrameRate)); + Stream->FrameRate)/1000); } 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)); + xil_printf("\tPixel Clock: %d kHz\r\n", + (XVidC_GetPixelClockHzByVmId(Stream->VmId)/1000)); } } diff --git a/hdmi/phy-xilinx-vphy/xvidc.h b/hdmi/phy-xilinx-vphy/xvidc.h index f4c2b17..1304ea8 100644 --- a/hdmi/phy-xilinx-vphy/xvidc.h +++ b/hdmi/phy-xilinx-vphy/xvidc.h @@ -17,7 +17,7 @@ /** * * @file xvidc.h - * @addtogroup video_common_v4_0 + * @addtogroup video_common_v4_3 * @{ * @details * @@ -609,8 +609,8 @@ typedef void (*XVidC_DelayHandler)(void *TimerPtr, u32 Delay); 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); +u64 XVidC_GetPixelClockHzByHVFr(u32 HTotal, u32 VTotal, u8 FrameRate); +u64 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); diff --git a/hdmi/phy-xilinx-vphy/xvphy.h b/hdmi/phy-xilinx-vphy/xvphy.h index 99696ef..2ff4580 100644 --- a/hdmi/phy-xilinx-vphy/xvphy.h +++ b/hdmi/phy-xilinx-vphy/xvphy.h @@ -95,6 +95,10 @@ /* Prevent circular inclusions by using protection macros. */ #define XVPHY_H_ +#ifdef __cplusplus +extern "C" { +#endif + #if !defined(XV_CONFIG_LOG_VPHY_DISABLE) && !defined(XV_CONFIG_LOG_DISABLE_ALL) #define XV_VPHY_LOG_ENABLE #endif @@ -1000,5 +1004,9 @@ void XVphy_RegisterDebug(XVphy *InstancePtr); #define XVPHY_GTHE4 5 #define XVPHY_GTYE4 6 +#ifdef __cplusplus +} +#endif + #endif /* XVPHY_H_ */ /** @} */ diff --git a/hdmi/phy-xilinx-vphy/xvphy_gt.h b/hdmi/phy-xilinx-vphy/xvphy_gt.h index d960163..27a7040 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_gt.h +++ b/hdmi/phy-xilinx-vphy/xvphy_gt.h @@ -38,7 +38,7 @@ * 1.7 gm 13/09/17 Added GTYE4 support * * - * @addtogroup xvphy + * @addtogroup xvphy_v1_7 * @{ *******************************************************************************/ @@ -46,6 +46,10 @@ /* Prevent circular inclusions by using protection macros. */ #define XVPHY_GT_H_ +#ifdef __cplusplus +extern "C" { +#endif + /******************************* Include Files ********************************/ #include "xvphy.h" @@ -119,5 +123,9 @@ extern const XVphy_GtConfig Gthe4Config; extern const XVphy_GtConfig Gtye4Config; #endif +#ifdef __cplusplus +} +#endif + #endif /* XVPHY_GT_H_ */ /** @} */ \ No newline at end of file diff --git a/hdmi/phy-xilinx-vphy/xvphy_hdmi.h b/hdmi/phy-xilinx-vphy/xvphy_hdmi.h index d606a50..250e2f0 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_hdmi.h +++ b/hdmi/phy-xilinx-vphy/xvphy_hdmi.h @@ -48,6 +48,10 @@ /* Prevent circular inclusions by using protection macros. */ #define XVPHY_HDMI_H_ +#ifdef __cplusplus +extern "C" { +#endif + /************************** Constant Definitions ******************************/ #define XVPHY_HDMI_GTYE4_DRU_LRATE 2500000000U @@ -166,6 +170,10 @@ void XVphy_HdmiGtDruModeEnable(XVphy *InstancePtr, u8 Enable); void XVphy_PatgenSetRatio(XVphy *InstancePtr, u8 QuadId, u64 TxLineRate); void XVphy_HdmiIntrHandlerCallbackInit(XVphy *InstancePtr); +#ifdef __cplusplus +} +#endif + #endif /* XVPHY_HDMI_H_ */ #endif /** @} */ diff --git a/hdmi/phy-xilinx-vphy/xvphy_hw.h b/hdmi/phy-xilinx-vphy/xvphy_hw.h index 3cc2efd..052a12b 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_hw.h +++ b/hdmi/phy-xilinx-vphy/xvphy_hw.h @@ -45,6 +45,10 @@ /* Prevent circular inclusions by using protection macros. */ #define XVPHY_HW_H_ +#ifdef __cplusplus +extern "C" { +#endif + /***************************** Include Files **********************************/ #include "xil_io.h" @@ -629,5 +633,9 @@ #define XVphy_WriteReg(BaseAddress, RegOffset, Data) \ XVphy_Out32((BaseAddress) + (RegOffset), (Data)) +#ifdef __cplusplus +} +#endif + #endif /* XVPHY_HW_H_ */ /** @} */ diff --git a/hdmi/phy-xilinx-vphy/xvphy_i.h b/hdmi/phy-xilinx-vphy/xvphy_i.h index 47a9ebb..67695da 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_i.h +++ b/hdmi/phy-xilinx-vphy/xvphy_i.h @@ -43,7 +43,7 @@ * Moved XVphy_SetRxLpm to xvphy.c/.h * * - * @addtogroup xvphy + * @addtogroup xvphy_v1_7 * @{ *******************************************************************************/ @@ -51,6 +51,10 @@ /* Prevent circular inclusions by using protection macros. */ #define XVPHY_I_H_ +#ifdef __cplusplus +extern "C" { +#endif + /******************************* Include Files ********************************/ #include "xil_assert.h" @@ -140,5 +144,9 @@ void XVphy_PllLayoutErrorHandler(XVphy *InstancePtr); /******************* Macros (Inline Functions) Definitions ********************/ +#ifdef __cplusplus +} +#endif + #endif /* XVPHY_I_H_ */ /** @} */ \ No newline at end of file diff --git a/hdmi/phy-xilinx-vphy/xvphy_log.c b/hdmi/phy-xilinx-vphy/xvphy_log.c index a1fe512..1754d71 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_log.c +++ b/hdmi/phy-xilinx-vphy/xvphy_log.c @@ -40,7 +40,6 @@ * Changed xil_printf new lines to \r\n * Added XVPHY_LOG_EVT_DRU_CLK_ERR log event * 1.7 gm 13/09/17 Added XVPHY_LOG_EVT_USRCLK_ERR event - * eb 23/01/18 Minor cleanup * * *******************************************************************************/ @@ -114,7 +113,7 @@ void XVphy_LogWrite(XVphy *InstancePtr, XVphy_LogEvent Evt, u8 Data) /* Update head pointer if reached to end of the buffer */ if (InstancePtr->Log.HeadIndex == - (u8)((sizeof(InstancePtr->Log.DataBuffer) / sizeof(InstancePtr->Log.DataBuffer[0])) - 1)) { + (u8)((sizeof(InstancePtr->Log.DataBuffer) / 2) - 1)) { /* Clear pointer */ InstancePtr->Log.HeadIndex = 0; } @@ -128,7 +127,7 @@ void XVphy_LogWrite(XVphy *InstancePtr, XVphy_LogEvent Evt, u8 Data) * remove the oldest entry from the buffer. */ if (InstancePtr->Log.TailIndex == InstancePtr->Log.HeadIndex) { if (InstancePtr->Log.TailIndex == - (u8)((sizeof(InstancePtr->Log.DataBuffer) / sizeof(InstancePtr->Log.DataBuffer[0])) - 1)) { + (u8)((sizeof(InstancePtr->Log.DataBuffer) / 2) - 1)) { InstancePtr->Log.TailIndex = 0; } else { @@ -166,7 +165,7 @@ u16 XVphy_LogRead(XVphy *InstancePtr) /* Increment tail pointer */ if (InstancePtr->Log.TailIndex == - (u8)((sizeof(InstancePtr->Log.DataBuffer) / sizeof(InstancePtr->Log.DataBuffer[0])) - 1)) { + (u8)((sizeof(InstancePtr->Log.DataBuffer) / 2) - 1)) { InstancePtr->Log.TailIndex = 0; } else { diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirx.c b/hdmi/xilinx-hdmi-rx/xv_hdmirx.c index ef77721..2c6e148 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirx.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirx.c @@ -167,6 +167,9 @@ int XV_HdmiRx_CfgInitialize(XV_HdmiRx *InstancePtr, XV_HdmiRx_Config *CfgPtr, UI (XV_HdmiRx_Callback)((void *)StubCallback); InstancePtr->IsTmdsClkRatioCallbackSet = (FALSE); + InstancePtr->VicErrorCallback = (XV_HdmiRx_Callback)((void *)StubCallback); + InstancePtr->IsVicErrorCallbackSet = (FALSE); + /* Clear HDMI variables */ XV_HdmiRx_Clear(InstancePtr); @@ -1452,304 +1455,295 @@ int XV_HdmiRx_GetVideoTiming(XV_HdmiRx *InstancePtr) u8 YUV420_Correction; u8 IsInterlaced; - // Lookup the videomode based on the vic - InstancePtr->Stream.Video.VmId = XV_HdmiRx_LookupVmId(InstancePtr->Stream.Vic); + InstancePtr->Stream.Video.VmId = XVIDC_VM_NOT_SUPPORTED; - // Was the vic found? - // Yes, then get the timing parameters from the video library - if (InstancePtr->Stream.Video.VmId != (XVIDC_VM_NOT_SUPPORTED)) { + // If the colorspace is YUV420, then the horizontal parameters must be doubled + if (InstancePtr->Stream.Video.ColorFormatId == XVIDC_CSF_YCRCB_420) { + YUV420_Correction = 2; + } else { + YUV420_Correction = 1; + } - // Copy the current VideoStream - VidStreamCopy = InstancePtr->Stream.Video; + // First we read the video parameters from the VTD and store them in a local variable + /* Read Total Pixels */ + HTotal = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_TOT_PIX_OFFSET)) * YUV420_Correction; - if (XVidC_IsStream3D(&InstancePtr->Stream.Video)){ - XVidC_Set3DVideoStream(&InstancePtr->Stream.Video, - VidStreamCopy.VmId, - VidStreamCopy.ColorFormatId, - VidStreamCopy.ColorDepth, - VidStreamCopy.PixPerClk, - &VidStreamCopy.Info_3D); - } - else { - XVidC_SetVideoStream(&InstancePtr->Stream.Video, - VidStreamCopy.VmId, - VidStreamCopy.ColorFormatId, - VidStreamCopy.ColorDepth, - VidStreamCopy.PixPerClk); - } + /* Read Active Pixels */ + HActive = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_ACT_PIX_OFFSET)) * YUV420_Correction; - return (XST_SUCCESS); - } + /* Read Hsync Width */ + HSyncWidth = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_HSW_OFFSET)) * YUV420_Correction; + + /* Read HFront Porch */ + HFrontPorch = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_HFP_OFFSET)) * YUV420_Correction; + + /* Read HBack Porch */ + HBackPorch = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_HBP_OFFSET)) * YUV420_Correction; + + /* Total lines field 1 */ + F0PVTotal = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_TOT_LIN_OFFSET)) & (0xFFFF); + + /* Total lines field 2 */ + F1VTotal = ((XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_TOT_LIN_OFFSET))) >> 16); + + /* Active lines field 1 */ + VActive = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_ACT_LIN_OFFSET)) & (0xFFFF); + + /* Read VSync Width field 1*/ + F0PVSyncWidth = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_VSW_OFFSET)) & (0xFFFF); + + /* Read VSync Width field 2*/ + F1VSyncWidth = ((XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_VSW_OFFSET))) >> 16); + + /* Read VFront Porch field 1*/ + F0PVFrontPorch = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_VFP_OFFSET)) & (0xFFFF); + + /* Read VFront Porch field 2*/ + F1VFrontPorch = ((XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_VFP_OFFSET))) >> 16); + + /* Read VBack Porch field 1 */ + F0PVBackPorch = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_VBP_OFFSET)) & (0xFFFF); - // No, then read the timing parameters from the video timing detector + /* Read VBack Porch field 2 */ + F1VBackPorch = ((XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_VBP_OFFSET))) >> 16); + + /* Read Status register */ + Data = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_STA_OFFSET)); + + /* Check video format */ + if ((Data) & (XV_HDMIRX_VTD_STA_FMT_MASK)) { + /* Interlaced */ + IsInterlaced = 1; + } else { - // If the colorspace is YUV420, then the horizontal parameters must be doubled - if (InstancePtr->Stream.Video.ColorFormatId == XVIDC_CSF_YCRCB_420) { - YUV420_Correction = 2; - } else { - YUV420_Correction = 1; - } - // First we read the video parameters from the VTD and store them in a local variable - /* Read Total Pixels */ - HTotal = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_TOT_PIX_OFFSET)) * YUV420_Correction; + /* Progressive */ + IsInterlaced = 0; + } - /* Read Active Pixels */ - HActive = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_ACT_PIX_OFFSET)) * YUV420_Correction; + // Next, we compare these values with the previous stored values + // By default the match is true + Match = TRUE; - /* Read Hsync Width */ - HSyncWidth = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_HSW_OFFSET)) * YUV420_Correction; + if (!HActive | !HFrontPorch | !HSyncWidth | !HBackPorch | !HTotal | !VActive | + !F0PVFrontPorch | !F0PVSyncWidth | !F0PVBackPorch | !F0PVTotal) { + Match = FALSE; + } - /* Read HFront Porch */ - HFrontPorch = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_HFP_OFFSET)) * YUV420_Correction; + if ((IsInterlaced == 1) & (!F1VFrontPorch | !F1VSyncWidth | !F1VBackPorch | !F1VTotal)) { + Match = FALSE; + } - /* Read HBack Porch */ - HBackPorch = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_HBP_OFFSET)) * YUV420_Correction; + // Htotal + if (HTotal != InstancePtr->Stream.Video.Timing.HTotal) { + Match = FALSE; + } - /* Total lines field 1 */ - F0PVTotal = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_TOT_LIN_OFFSET)) & (0xFFFF); + // HActive + if (HActive != InstancePtr->Stream.Video.Timing.HActive) { + Match = FALSE; + } - /* Total lines field 2 */ - F1VTotal = ((XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_TOT_LIN_OFFSET))) >> 16); + // HSyncWidth + if (HSyncWidth != InstancePtr->Stream.Video.Timing.HSyncWidth) { + Match = FALSE; + } - /* Active lines field 1 */ - VActive = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_ACT_LIN_OFFSET)) & (0xFFFF); + // HFrontPorch + if (HFrontPorch != InstancePtr->Stream.Video.Timing.HFrontPorch) { + Match = FALSE; + } - /* Read VSync Width field 1*/ - F0PVSyncWidth = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_VSW_OFFSET)) & (0xFFFF); + // HBackPorch + if (HBackPorch != InstancePtr->Stream.Video.Timing.HBackPorch) { + Match = FALSE; + } - /* Read VSync Width field 2*/ - F1VSyncWidth = ((XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_VSW_OFFSET))) >> 16); + // F0PVTotal + if (F0PVTotal != InstancePtr->Stream.Video.Timing.F0PVTotal) { + Match = FALSE; + } - /* Read VFront Porch field 1*/ - F0PVFrontPorch = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_VFP_OFFSET)) & (0xFFFF); + // F1VTotal + if (F1VTotal != InstancePtr->Stream.Video.Timing.F1VTotal) { + Match = FALSE; + } - /* Read VFront Porch field 2*/ - F1VFrontPorch = ((XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_VFP_OFFSET))) >> 16); + // VActive + if (VActive != InstancePtr->Stream.Video.Timing.VActive) { + Match = FALSE; + } - /* Read VBack Porch field 1 */ - F0PVBackPorch = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_VBP_OFFSET)) & (0xFFFF); + // F0PVSyncWidth + if (F0PVSyncWidth != InstancePtr->Stream.Video.Timing.F0PVSyncWidth) { + Match = FALSE; + } - /* Read VBack Porch field 2 */ - F1VBackPorch = ((XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_VBP_OFFSET))) >> 16); + // F1VSyncWidth + if (F1VSyncWidth != InstancePtr->Stream.Video.Timing.F1VSyncWidth) { + Match = FALSE; + } - /* Read Status register */ - Data = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_STA_OFFSET)); + // F0PVFrontPorch + if (F0PVFrontPorch != InstancePtr->Stream.Video.Timing.F0PVFrontPorch) { + Match = FALSE; + } - /* Check video format */ - if ((Data) & (XV_HDMIRX_VTD_STA_FMT_MASK)) { - /* Interlaced */ - IsInterlaced = 1; - } - else { - /* Progressive */ - IsInterlaced = 0; - } + // F1VFrontPorch + if (F1VFrontPorch != InstancePtr->Stream.Video.Timing.F1VFrontPorch) { + Match = FALSE; + } - // Next, we compare these values with the previous stored values - // By default the match is true - Match = TRUE; + // F0PVBackPorch + if (F0PVBackPorch != InstancePtr->Stream.Video.Timing.F0PVBackPorch) { + Match = FALSE; + } - if (!HActive | !HFrontPorch | !HSyncWidth | !HBackPorch | !HTotal | !VActive | - !F0PVFrontPorch | !F0PVSyncWidth | !F0PVBackPorch | !F0PVTotal) { - Match = FALSE; - } + // F1VBackPorch + if (F1VBackPorch != InstancePtr->Stream.Video.Timing.F1VBackPorch) { + Match = FALSE; + } - if ((IsInterlaced == 1) & (!F1VFrontPorch | !F1VSyncWidth | !F1VBackPorch | !F1VTotal)) { - Match = FALSE; - } + if (HTotal != (HActive + HFrontPorch + HSyncWidth +HBackPorch)) { + Match = FALSE; + } - // Htotal - if (HTotal != InstancePtr->Stream.Video.Timing.HTotal) { - Match = FALSE; - } + if (F0PVTotal != (VActive + F0PVFrontPorch + F0PVSyncWidth +F0PVBackPorch)) { + Match = FALSE; + } - // HActive - if (HActive != InstancePtr->Stream.Video.Timing.HActive) { - Match = FALSE; - } + if ((IsInterlaced == 1) && (F1VTotal != (VActive + F1VFrontPorch + F1VSyncWidth +F1VBackPorch))) { + Match = FALSE; + } - // HSyncWidth - if (HSyncWidth != InstancePtr->Stream.Video.Timing.HSyncWidth) { - Match = FALSE; - } + // Then we store the timing parameters regardless if there was a match + /* Read Total Pixels */ + InstancePtr->Stream.Video.Timing.HTotal = HTotal; - // HFrontPorch - if (HFrontPorch != InstancePtr->Stream.Video.Timing.HFrontPorch) { - Match = FALSE; - } + /* Read Active Pixels */ + InstancePtr->Stream.Video.Timing.HActive = HActive; - // HBackPorch - if (HBackPorch != InstancePtr->Stream.Video.Timing.HBackPorch) { - Match = FALSE; - } + /* Read Hsync Width */ + InstancePtr->Stream.Video.Timing.HSyncWidth = HSyncWidth; - // F0PVTotal - if (F0PVTotal != InstancePtr->Stream.Video.Timing.F0PVTotal) { - Match = FALSE; - } + /* Read HFront Porch */ + InstancePtr->Stream.Video.Timing.HFrontPorch = HFrontPorch; - // F1VTotal - if (F1VTotal != InstancePtr->Stream.Video.Timing.F1VTotal) { - Match = FALSE; - } + /* Read HBack Porch */ + InstancePtr->Stream.Video.Timing.HBackPorch = HBackPorch; - // VActive - if (VActive != InstancePtr->Stream.Video.Timing.VActive) { - Match = FALSE; - } + /* Total lines field 1 */ + InstancePtr->Stream.Video.Timing.F0PVTotal = F0PVTotal; - // F0PVSyncWidth - if (F0PVSyncWidth != InstancePtr->Stream.Video.Timing.F0PVSyncWidth) { - Match = FALSE; - } + /* Total lines field 2 */ + InstancePtr->Stream.Video.Timing.F1VTotal = F1VTotal; - // F1VSyncWidth - if (F1VSyncWidth != InstancePtr->Stream.Video.Timing.F1VSyncWidth) { - Match = FALSE; - } + /* Active lines field 1 */ + InstancePtr->Stream.Video.Timing.VActive = VActive; - // F0PVFrontPorch - if (F0PVFrontPorch != InstancePtr->Stream.Video.Timing.F0PVFrontPorch) { - Match = FALSE; - } + /* Read VSync Width field 1*/ + InstancePtr->Stream.Video.Timing.F0PVSyncWidth = F0PVSyncWidth; - // F1VFrontPorch - if (F1VFrontPorch != InstancePtr->Stream.Video.Timing.F1VFrontPorch) { - Match = FALSE; - } + /* Read VSync Width field 2*/ + InstancePtr->Stream.Video.Timing.F1VSyncWidth = F1VSyncWidth; - // F0PVBackPorch - if (F0PVBackPorch != InstancePtr->Stream.Video.Timing.F0PVBackPorch) { - Match = FALSE; - } + /* Read VFront Porch field 1*/ + InstancePtr->Stream.Video.Timing.F0PVFrontPorch = F0PVFrontPorch; + + /* Read VFront Porch field 2*/ + InstancePtr->Stream.Video.Timing.F1VFrontPorch = F1VFrontPorch; + + /* Read VBack Porch field 1 */ + InstancePtr->Stream.Video.Timing.F0PVBackPorch = F0PVBackPorch; + + /* Read VBack Porch field 2 */ + InstancePtr->Stream.Video.Timing.F1VBackPorch = F1VBackPorch; + + // Do we have a match? + // Yes, then continue processing + if (Match) { - // F1VBackPorch - if (F1VBackPorch != InstancePtr->Stream.Video.Timing.F1VBackPorch) { - Match = FALSE; + /* Read Status register */ + Data = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_STA_OFFSET)); + + /* Check video format */ + if ((Data) & (XV_HDMIRX_VTD_STA_FMT_MASK)) { + /* Interlaced */ + InstancePtr->Stream.Video.IsInterlaced = 1; + } + else { + /* Progressive */ + InstancePtr->Stream.Video.IsInterlaced = 0; } - if (HTotal != (HActive + HFrontPorch + HSyncWidth +HBackPorch)) { - Match = FALSE; + /* Check Vsync polarity */ + if ((Data) & (XV_HDMIRX_VTD_STA_VS_POL_MASK)) { + /* Positive */ + InstancePtr->Stream.Video.Timing.VSyncPolarity = 1; + } + else { + /* Negative */ + InstancePtr->Stream.Video.Timing.VSyncPolarity = 0; } - if (F0PVTotal != (VActive + F0PVFrontPorch + F0PVSyncWidth +F0PVBackPorch)) { - Match = FALSE; + /* Check Hsync polarity */ + if ((Data) & (XV_HDMIRX_VTD_STA_HS_POL_MASK)) { + /* Positive */ + InstancePtr->Stream.Video.Timing.HSyncPolarity = 1; + } + else { + /* Negative */ + InstancePtr->Stream.Video.Timing.HSyncPolarity = 0; } - if ((IsInterlaced == 1) && (F1VTotal != (VActive + F1VFrontPorch + F1VSyncWidth +F1VBackPorch))) { - Match = FALSE; + /* Calculate and set the frame rate field assuming the stream is + * of YUV420 */ + InstancePtr->Stream.Video.FrameRate = + (XVidC_FrameRate) (XV_HdmiRx_Divide((InstancePtr->Stream.PixelClk << 1), + (InstancePtr->Stream.Video.Timing.F0PVTotal * + InstancePtr->Stream.Video.Timing.HTotal))); + + /* If the colorspace is not YUV420, then the frame rate must be + * halved */ + if (InstancePtr->Stream.Video.ColorFormatId != XVIDC_CSF_YCRCB_420) { + InstancePtr->Stream.Video.FrameRate >>= 1; } - // Then we store the timing parameters regardless if there was a match - /* Read Total Pixels */ - InstancePtr->Stream.Video.Timing.HTotal = HTotal; - - /* Read Active Pixels */ - InstancePtr->Stream.Video.Timing.HActive = HActive; - - /* Read Hsync Width */ - InstancePtr->Stream.Video.Timing.HSyncWidth = HSyncWidth; - - /* Read HFront Porch */ - InstancePtr->Stream.Video.Timing.HFrontPorch = HFrontPorch; - - /* Read HBack Porch */ - InstancePtr->Stream.Video.Timing.HBackPorch = HBackPorch; - - /* Total lines field 1 */ - InstancePtr->Stream.Video.Timing.F0PVTotal = F0PVTotal; - - /* Total lines field 2 */ - InstancePtr->Stream.Video.Timing.F1VTotal = F1VTotal; - - /* Active lines field 1 */ - InstancePtr->Stream.Video.Timing.VActive = VActive; - - /* Read VSync Width field 1*/ - InstancePtr->Stream.Video.Timing.F0PVSyncWidth = F0PVSyncWidth; - - /* Read VSync Width field 2*/ - InstancePtr->Stream.Video.Timing.F1VSyncWidth = F1VSyncWidth; - - /* Read VFront Porch field 1*/ - InstancePtr->Stream.Video.Timing.F0PVFrontPorch = F0PVFrontPorch; - - /* Read VFront Porch field 2*/ - InstancePtr->Stream.Video.Timing.F1VFrontPorch = F1VFrontPorch; - - /* Read VBack Porch field 1 */ - InstancePtr->Stream.Video.Timing.F0PVBackPorch = F0PVBackPorch; - - /* Read VBack Porch field 2 */ - InstancePtr->Stream.Video.Timing.F1VBackPorch = F1VBackPorch; - - // Do we have a match? - // Yes, then continue processing - if (Match) { - - /* Read Status register */ - Data = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_STA_OFFSET)); - - /* Check video format */ - if ((Data) & (XV_HDMIRX_VTD_STA_FMT_MASK)) { - /* Interlaced */ - InstancePtr->Stream.Video.IsInterlaced = 1; - } - else { - /* Progressive */ - InstancePtr->Stream.Video.IsInterlaced = 0; - } - - /* Check Vsync polarity */ - if ((Data) & (XV_HDMIRX_VTD_STA_VS_POL_MASK)) { - /* Positive */ - InstancePtr->Stream.Video.Timing.VSyncPolarity = 1; - } - else { - /* Negative */ - InstancePtr->Stream.Video.Timing.VSyncPolarity = 0; - } - - /* Check Hsync polarity */ - if ((Data) & (XV_HDMIRX_VTD_STA_HS_POL_MASK)) { - /* Positive */ - InstancePtr->Stream.Video.Timing.HSyncPolarity = 1; - } - else { - /* Negative */ - InstancePtr->Stream.Video.Timing.HSyncPolarity = 0; - } - - // Calculate and set the frame rate field - InstancePtr->Stream.Video.FrameRate = - (XVidC_FrameRate) (XV_HdmiRx_Divide(InstancePtr->Stream.PixelClk, - (InstancePtr->Stream.Video.Timing.F0PVTotal * InstancePtr->Stream.Video.Timing.HTotal))); - - // If the colorspace is YUV420, then the frame rate must be doubled - if (InstancePtr->Stream.Video.ColorFormatId == XVIDC_CSF_YCRCB_420) { - InstancePtr->Stream.Video.FrameRate = (XVidC_FrameRate) (InstancePtr->Stream.Video.FrameRate * 2); - } - - // Lookup the video mode id - InstancePtr->Stream.Video.VmId = - XVidC_GetVideoModeIdExtensive(&InstancePtr->Stream.Video.Timing, - InstancePtr->Stream.Video.FrameRate, - InstancePtr->Stream.Video.IsInterlaced, - (TRUE)); - - //If video mode not found in the table tag it as custom - if (InstancePtr->Stream.Video.VmId == XVIDC_VM_NOT_SUPPORTED) { - InstancePtr->Stream.Video.VmId = XVIDC_VM_CUSTOM; - } - - // Return success - return (XST_SUCCESS); + // Lookup the video mode id + InstancePtr->Stream.Video.VmId = + XVidC_GetVideoModeIdExtensive(&InstancePtr->Stream.Video.Timing, + InstancePtr->Stream.Video.FrameRate, + InstancePtr->Stream.Video.IsInterlaced, + (TRUE)); + + //If video mode not found in the table tag it as custom + if (InstancePtr->Stream.Video.VmId == XVIDC_VM_NOT_SUPPORTED) { + InstancePtr->Stream.Video.VmId = XVIDC_VM_CUSTOM; } - // No match - else { - return (XST_FAILURE); + VidStreamCopy = InstancePtr->Stream.Video; + + if (XVidC_IsStream3D(&InstancePtr->Stream.Video)){ + XVidC_Set3DVideoStream(&InstancePtr->Stream.Video, + VidStreamCopy.VmId, + VidStreamCopy.ColorFormatId, + VidStreamCopy.ColorDepth, + VidStreamCopy.PixPerClk, + &VidStreamCopy.Info_3D); + } else { + XVidC_SetVideoStream(&InstancePtr->Stream.Video, + VidStreamCopy.VmId, + VidStreamCopy.ColorFormatId, + VidStreamCopy.ColorDepth, + VidStreamCopy.PixPerClk); } + + // Return success + return (XST_SUCCESS); + } + + // No match + else { + return (XST_FAILURE); } } diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirx.h b/hdmi/xilinx-hdmi-rx/xv_hdmirx.h index 8baa68c..981ff10 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirx.h +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirx.h @@ -182,7 +182,8 @@ typedef enum { XV_HDMIRX_HANDLER_LINK_ERROR, /**< Interrupt type for link error */ XV_HDMIRX_HANDLER_SYNC_LOSS, /**< Interrupt type for sync loss */ XV_HDMIRX_HANDLER_MODE, /**< Interrupt type for mode */ - XV_HDMIRX_HANDLER_TMDS_CLK_RATIO /**< Interrupt type for TMDS clock ratio */ + XV_HDMIRX_HANDLER_TMDS_CLK_RATIO, /**< Interrupt type for TMDS clock ratio */ + XV_HDMIRX_HANDLER_VIC_ERROR /**< Interrupt type for VIC error */ } XV_HdmiRx_HandlerType; /*@}*/ @@ -347,6 +348,10 @@ typedef struct { void *TmdsClkRatioRef; /**< To be passed to the TMDS callback */ u32 IsTmdsClkRatioCallbackSet; /**< Set flag. This flag is set to true when the callback has been registered */ + XV_HdmiRx_Callback VicErrorCallback; /**< Callback for Vic error detection */ + void *VicErrorRef; /**< To be passed to the vic error callback */ + u32 IsVicErrorCallbackSet; /**< Set flag. This flag is set to true when the callback has been registered */ + /* HDMI RX stream */ XV_HdmiRx_Stream Stream; /**< HDMI RX stream information */ @@ -1279,6 +1284,7 @@ int XV_HdmiRx_GetTmdsClockRatio(XV_HdmiRx *InstancePtr); u8 XV_HdmiRx_GetAviVic(XV_HdmiRx *InstancePtr); XVidC_ColorFormat XV_HdmiRx_GetAviColorSpace(XV_HdmiRx *InstancePtr); XVidC_ColorDepth XV_HdmiRx_GetGcpColorDepth(XV_HdmiRx *InstancePtr); +XVidC_VideoMode XV_HdmiRx_LookupVmId(u8 Vic); int XV_HdmiRx_GetVideoProperties(XV_HdmiRx *InstancePtr); int XV_HdmiRx_GetVideoTiming(XV_HdmiRx *InstancePtr); u32 XV_HdmiRx_Divide(u32 Dividend, u32 Divisor); @@ -1291,8 +1297,13 @@ int XV_HdmiRx_SelfTest(XV_HdmiRx *InstancePtr); /* Interrupt related function in xv_hdmirx_intr.c */ void XV_HdmiRx_IntrHandler(void *InstancePtr); -int XV_HdmiRx_SetCallback(XV_HdmiRx *InstancePtr, u32 HandlerType, void *CallbackFunc, void *CallbackRef); +int XV_HdmiRx_SetCallback(XV_HdmiRx *InstancePtr, + XV_HdmiRx_HandlerType HandlerType, + void *CallbackFunc, + void *CallbackRef); + +/* [Linux] No need to add vendor specific API */ /************************** Variable Declarations ****************************/ /************************** Variable Declarations ****************************/ diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c b/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c index 77e43f7..c855ac9 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirx_intr.c @@ -212,7 +212,10 @@ void XV_HdmiRx_IntrHandler(void *InstancePtr) * installed replaces it with the new handler. * ******************************************************************************/ -int XV_HdmiRx_SetCallback(XV_HdmiRx *InstancePtr, u32 HandlerType, void *CallbackFunc, void *CallbackRef) +int XV_HdmiRx_SetCallback(XV_HdmiRx *InstancePtr, + XV_HdmiRx_HandlerType HandlerType, + void *CallbackFunc, + void *CallbackRef) { u32 Status; @@ -349,6 +352,15 @@ int XV_HdmiRx_SetCallback(XV_HdmiRx *InstancePtr, u32 HandlerType, void *Callbac Status = (XST_SUCCESS); break; + // Vic Error + case (XV_HDMIRX_HANDLER_VIC_ERROR): + InstancePtr->VicErrorCallback = + (XV_HdmiRx_Callback)CallbackFunc; + InstancePtr->VicErrorRef = CallbackRef; + InstancePtr->IsVicErrorCallbackSet = (TRUE); + Status = (XST_SUCCESS); + break; + default: Status = (XST_INVALID_PARAM); break; @@ -373,15 +385,19 @@ int XV_HdmiRx_SetCallback(XV_HdmiRx *InstancePtr, u32 HandlerType, void *Callbac void HdmiRx_VtdIntrHandler(XV_HdmiRx *InstancePtr) { u32 Status; + XVidC_VideoMode DecodedVmId = 0; /* Read Video timing detector Status register */ - Status = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_STA_OFFSET)); + Status = XV_HdmiRx_ReadReg(InstancePtr->Config.BaseAddress, + (XV_HDMIRX_VTD_STA_OFFSET)); /* Check for time base event */ if ((Status) & (XV_HDMIRX_VTD_STA_TIMEBASE_EVT_MASK)) { // Clear event flag - XV_HdmiRx_WriteReg(InstancePtr->Config.BaseAddress, (XV_HDMIRX_VTD_STA_OFFSET), (XV_HDMIRX_VTD_STA_TIMEBASE_EVT_MASK)); + XV_HdmiRx_WriteReg(InstancePtr->Config.BaseAddress, + (XV_HDMIRX_VTD_STA_OFFSET), + (XV_HDMIRX_VTD_STA_TIMEBASE_EVT_MASK)); // Check if we are in lock state if (InstancePtr->Stream.State == XV_HDMIRX_STATE_STREAM_LOCK) { @@ -390,12 +406,26 @@ void HdmiRx_VtdIntrHandler(XV_HdmiRx *InstancePtr) Status = XV_HdmiRx_GetVideoTiming(InstancePtr); if (Status == XST_SUCCESS) { + if (InstancePtr->Stream.Vic != 0) { + DecodedVmId = XV_HdmiRx_LookupVmId(InstancePtr->Stream.Vic); + + if (DecodedVmId != InstancePtr->Stream.Video.VmId && + !(DecodedVmId == XVIDC_VM_NOT_SUPPORTED && + InstancePtr->Stream.Video.VmId == + XVIDC_VM_CUSTOM)) { + /* Call VIC error callback */ + if (InstancePtr->VicErrorCallback) { + InstancePtr->VicErrorCallback( + InstancePtr->VicErrorRef); + } + } + } // Enable AXI Stream output XV_HdmiRx_AxisEnable(InstancePtr, (TRUE)); // Set stream status to up - InstancePtr->Stream.State = XV_HDMIRX_STATE_STREAM_UP; // The stream is up + InstancePtr->Stream.State = XV_HDMIRX_STATE_STREAM_UP; // Set stream sync status to est InstancePtr->Stream.SyncStatus = XV_HDMIRX_SYNCSTAT_SYNC_EST; diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c index 78b016a..fb95f0f 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.c @@ -103,6 +103,7 @@ * YH 13/04/18 Fixed a bug in XV_HdmiRxSs_BrdgOverflowCallback * 5.20 EB 03/08/18 Added function XV_HdmiRxSs_AudioMute * Added TMDS Clock Ratio callback support +* 5.40 EB 06/08/19 Added Vic and Video Timing mismatch callback support ******************************************************************************/ /***************************** Include Files *********************************/ @@ -150,6 +151,7 @@ static void XV_HdmiRxSs_StreamUpCallback(void *CallbackRef); static void XV_HdmiRxSs_SyncLossCallback(void *CallbackRef); static void XV_HdmiRxSs_ModeCallback(void *CallbackRef); static void XV_HdmiRxSs_TmdsClkRatioCallback(void *CallbackRef); +static void XV_HdmiRxSs_VicErrorCallback(void *CallbackRef); static void XV_HdmiRxSs_ReportCoreInfo(XV_HdmiRxSs *InstancePtr); static void XV_HdmiRxSs_ReportTiming(XV_HdmiRxSs *InstancePtr); @@ -393,6 +395,11 @@ static int XV_HdmiRxSs_RegisterSubsysCallbacks(XV_HdmiRxSs *InstancePtr) XV_HDMIRX_HANDLER_TMDS_CLK_RATIO, (void *)XV_HdmiRxSs_TmdsClkRatioCallback, (void *)InstancePtr); + + XV_HdmiRx_SetCallback(HdmiRxSsPtr->HdmiRxPtr, + XV_HDMIRX_HANDLER_VIC_ERROR, + (void *)XV_HdmiRxSs_VicErrorCallback, + (void *)InstancePtr); } return(XST_SUCCESS); @@ -989,6 +996,33 @@ static void XV_HdmiRxSs_TmdsClkRatioCallback(void *CallbackRef) } +/*****************************************************************************/ +/** +* +* This function is called when the Vic does not match with the detected video +* timing. +* +* @param None. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void XV_HdmiRxSs_VicErrorCallback(void *CallbackRef) +{ + XV_HdmiRxSs *HdmiRxSsPtr = (XV_HdmiRxSs *)CallbackRef; + +#ifdef XV_HDMIRXSS_LOG_ENABLE + XV_HdmiRxSs_LogWrite(HdmiRxSsPtr, XV_HDMIRXSS_LOG_EVT_VICERROR, 0); +#endif + + // Check if user callback has been registered + if (HdmiRxSsPtr->VicErrorCallback) { + HdmiRxSsPtr->VicErrorCallback(HdmiRxSsPtr->VicErrorRef); + } +} + /*****************************************************************************/ /** * @@ -1263,8 +1297,10 @@ static void XV_HdmiRxSs_StreamUpCallback(void *CallbackRef) * installed replaces it with the new handler. * ******************************************************************************/ -int XV_HdmiRxSs_SetCallback(XV_HdmiRxSs *InstancePtr, u32 HandlerType, - void *CallbackFunc, void *CallbackRef) +int XV_HdmiRxSs_SetCallback(XV_HdmiRxSs *InstancePtr, + XV_HdmiRxSs_HandlerType HandlerType, + void *CallbackFunc, + void *CallbackRef) { u32 Status; @@ -1343,6 +1379,13 @@ int XV_HdmiRxSs_SetCallback(XV_HdmiRxSs *InstancePtr, u32 HandlerType, Status = (XST_SUCCESS); break; + // VIC_ERROR + case (XV_HDMIRXSS_HANDLER_VIC_ERROR): + InstancePtr->VicErrorCallback = (XV_HdmiRxSs_Callback)CallbackFunc; + InstancePtr->VicErrorRef = CallbackRef; + Status = (XST_SUCCESS); + break; + // HDCP case (XV_HDMIRXSS_HANDLER_HDCP): InstancePtr->HdcpCallback = (XV_HdmiRxSs_Callback)CallbackFunc; diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h index d865aa6..b2387d0 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h @@ -182,6 +182,7 @@ typedef enum { XV_HDMIRXSS_LOG_EVT_SYNCLOSS, /**< Log event Sync Loss detected. */ XV_HDMIRXSS_LOG_EVT_PIX_REPEAT_ERR, /**< Log event Unsupported Pixel Repetition. */ XV_HDMIRXSS_LOG_EVT_SYNCEST, /**< Log event Sync Loss detected. */ + XV_HDMIRXSS_LOG_EVT_VICERROR, /**< Log event vic error detected. */ XV_HDMIRXSS_LOG_EVT_DUMMY /**< Dummy Event should be last */ } XV_HdmiRxSs_LogEvent; @@ -312,9 +313,11 @@ typedef enum { XV_HDMIRXSS_HANDLER_HDCP_ENCRYPTION_UPDATE, /**< Handler for HDCP encryption status update event */ - XV_HDMIRXSS_HANDLER_TMDS_CLK_RATIO /**< Handler type for + XV_HDMIRXSS_HANDLER_TMDS_CLK_RATIO, /**< Handler type for TMDS clock ratio change */ + XV_HDMIRXSS_HANDLER_VIC_ERROR /**< Handler type for + VIC error change */ } XV_HdmiRxSs_HandlerType; /*@}*/ @@ -373,6 +376,8 @@ typedef struct XV_HdmiRxSs_Config Config; /**< Hardware configuration */ u32 IsReady; /**< Device and the driver instance are initialized */ + u8 AppMajVer; /**< Major Version of application used by the driver */ + u8 AppMinVer; /**< Minor Version of application used by the driver */ #ifdef XV_HDMIRXSS_LOG_ENABLE XV_HdmiRxSs_Log Log; /**< A log of events. */ @@ -426,6 +431,10 @@ typedef struct void *TmdsClkRatioRef;/**< To be passed to the scdc tmds clock ratio change callback */ + XV_HdmiRxSs_Callback VicErrorCallback; /**< Callback for VIC error + detection */ + void *VicErrorRef; /**< To be passed to the VIC error callback */ + // Scratch pad u8 IsStreamConnected; /**< HDMI RX Stream Connected */ u8 IsStreamUp; /**< HDMI RX Stream Up */ @@ -487,9 +496,9 @@ void XV_HdmiRxSs_RXCore_LRST(XV_HdmiRxSs *InstancePtr, u8 Reset); void XV_HdmiRxSs_VRST(XV_HdmiRxSs *InstancePtr, u8 Reset); void XV_HdmiRxSs_SYSRST(XV_HdmiRxSs *InstancePtr, u8 Reset); int XV_HdmiRxSs_SetCallback(XV_HdmiRxSs *InstancePtr, - u32 HandlerType, - void *CallbackFunc, - void *CallbackRef); + XV_HdmiRxSs_HandlerType HandlerType, + void *CallbackFunc, + void *CallbackRef); void XV_HdmiRxSs_SetEdidParam(XV_HdmiRxSs *InstancePtr, u8 *EdidDataPtr, u16 Length); void XV_HdmiRxSs_LoadDefaultEdid(XV_HdmiRxSs *InstancePtr); diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss_log.c b/hdmi/xilinx-hdmi-rx/xv_hdmirxss_log.c index 32c7778..4318937 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss_log.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss_log.c @@ -27,12 +27,13 @@ * Ver Who Date Changes * ----- ---- -------- ----------------------------------------------- * 1.0 YH 17/08/16 Initial release. - * 1.01 MMO 03/01/17 Add compiler option(XV_HDMIRXSS_LOG_ENABLE) to enable Log - * + * 1.01 MMO 03/01/17 Add compiler option(XV_HDMIRXSS_LOG_ENABLE) to enable + * Log * 1.4 YH 07/07/17 Add new log type XV_HDMIRXSS_LOG_EVT_SETSTREAM_ERR * 5.0 EB 16/01/18 Added new log XV_HDMIRXSS_LOG_EVT_PIX_REPEAT_ERR * 23/01/18 Minor cleanup * MMO 05/02/18 Added new log XV_HDMIRXSS_LOG_EVT_SYNCEST + * 5.4 EB 06/08/19 Added new log XV_HDMIRXSS_LOG_EVT_VICERROR * * *******************************************************************************/ @@ -89,31 +90,31 @@ void XV_HdmiRxSs_LogWrite(XV_HdmiRxSs *InstancePtr, XV_HdmiRxSs_LogEvent Evt, u8 InstancePtr->Log.DataBuffer[InstancePtr->Log.HeadIndex] = (Data << 8) | Evt; - /* Update head pointer if reached to end of the buffer */ - if (InstancePtr->Log.HeadIndex == + /* Update head pointer if reached to end of the buffer */ + if (InstancePtr->Log.HeadIndex == (u8)((sizeof(InstancePtr->Log.DataBuffer) / sizeof(InstancePtr->Log.DataBuffer[0])) - 1)) { - /* Clear pointer */ - InstancePtr->Log.HeadIndex = 0; - } - else { - /* Increment pointer */ - InstancePtr->Log.HeadIndex++; - } + /* 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 == + /* 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) / sizeof(InstancePtr->Log.DataBuffer[0])) - 1)) { - InstancePtr->Log.TailIndex = 0; - } - else { - InstancePtr->Log.TailIndex++; - } - } + InstancePtr->Log.TailIndex = 0; + } + else { + InstancePtr->Log.TailIndex++; + } + } } /*****************************************************************************/ @@ -305,6 +306,9 @@ int XV_HdmiRxSs_LogShow(XV_HdmiRxSs *InstancePtr, char *buff, int buff_size) strSize += scnprintf(buff+strSize, buff_size-strSize, "RX Sync Loss recovered\r\n"); break; + case (XV_HDMIRXSS_LOG_EVT_VICERROR): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Vic and video timing mismatch\r\n"); default: strSize += scnprintf(buff+strSize, buff_size-strSize, "Unknown event: %i\r\n", Evt); diff --git a/hdmi/xilinx-hdmi-tx/xv_hdmitx.c b/hdmi/xilinx-hdmi-tx/xv_hdmitx.c index a63013f..90d7514 100644 --- a/hdmi/xilinx-hdmi-tx/xv_hdmitx.c +++ b/hdmi/xilinx-hdmi-tx/xv_hdmitx.c @@ -60,6 +60,8 @@ * XV_HdmiTx_DdcRead APIs to prevent another DDC * transactions from happening in the middle of a DDC * transaction +* EB 16/07/19 Replaced sampling rate of 4 with 2 at the API +* XV_HdmiTx_SetSampleRate * * ******************************************************************************/ @@ -591,7 +593,7 @@ int XV_HdmiTx_ClockRatio(XV_HdmiTx *InstancePtr) { Status = XV_HdmiTx_DdcWrite(InstancePtr, 0x54, 2, (u8*)&DdcBuf, (TRUE)); } - return XST_SUCCESS; + return XST_SUCCESS; } return XST_FAILURE; } @@ -1082,6 +1084,7 @@ void XV_HdmiTx_SetPixelRate(XV_HdmiTx *InstancePtr) * * @param InstancePtr is a pointer to the XV_HdmiTx core instance. * @param SampleRate specifies the value that needs to be set. +* - 2 samples per clock * - 3 samples per clock. * - 5 samples per clock. * @@ -1108,12 +1111,12 @@ void XV_HdmiTx_SetSampleRate(XV_HdmiTx *InstancePtr, u8 SampleRate) // Check for sample rate switch (SampleRate) { - case 3: - RegValue = 1; + case 2: + RegValue = 2; break; - case 4: - RegValue = 2; + case 3: + RegValue = 1; break; case 5: @@ -1565,7 +1568,7 @@ int XV_HdmiTx_DdcWrite(XV_HdmiTx *InstancePtr, u8 Slave, // Write Data for (Index = 0; Index < Length; Index++) { Status = XV_HdmiTx_DdcWriteCommand(InstancePtr, *Buffer++); - if (Status == XST_FAILURE) return(Status); + if (Status == XST_FAILURE) return(Status); } // Wait for done flag diff --git a/hdmi/xilinx-hdmi-tx/xv_hdmitx.h b/hdmi/xilinx-hdmi-tx/xv_hdmitx.h index 12a918b..53ccb20 100644 --- a/hdmi/xilinx-hdmi-tx/xv_hdmitx.h +++ b/hdmi/xilinx-hdmi-tx/xv_hdmitx.h @@ -1110,9 +1110,13 @@ int XV_HdmiTx_SelfTest(XV_HdmiTx *InstancePtr); /* Interrupt related functions in xv_hdmitx_intr.c */ void XV_HdmiTx_IntrHandler(void *InstancePtr); -int XV_HdmiTx_SetCallback(XV_HdmiTx *InstancePtr, u32 HandlerType, - void *CallbackFunc, void *CallbackRef); +int XV_HdmiTx_SetCallback(XV_HdmiTx *InstancePtr, + XV_HdmiTx_HandlerType HandlerType, + void *CallbackFunc, + void *CallbackRef); + +/* [Linux] Not supporting vendor specific APIs */ /************************** Variable Declarations ****************************/ /************************** Variable Declarations ****************************/ diff --git a/hdmi/xilinx-hdmi-tx/xv_hdmitx_intr.c b/hdmi/xilinx-hdmi-tx/xv_hdmitx_intr.c index a5516cb..d5a7cbf 100644 --- a/hdmi/xilinx-hdmi-tx/xv_hdmitx_intr.c +++ b/hdmi/xilinx-hdmi-tx/xv_hdmitx_intr.c @@ -48,7 +48,7 @@ /************************** Function Prototypes ******************************/ - +/* [Linux] Cannot make static as it is being called from TX driver wrapper code */ void HdmiTx_PioIntrHandler(XV_HdmiTx *InstancePtr); void HdmiTx_DdcIntrHandler(XV_HdmiTx *InstancePtr); @@ -140,9 +140,9 @@ void XV_HdmiTx_IntrHandler(void *InstancePtr) * ******************************************************************************/ int XV_HdmiTx_SetCallback(XV_HdmiTx *InstancePtr, - u32 HandlerType, - void *CallbackFunc, - void *CallbackRef) + XV_HdmiTx_HandlerType HandlerType, + void *CallbackFunc, + void *CallbackRef) { u32 Status; diff --git a/hdmi/xilinx-hdmi-tx/xv_hdmitxss.c b/hdmi/xilinx-hdmi-tx/xv_hdmitxss.c index a864940..2d57fc6 100644 --- a/hdmi/xilinx-hdmi-tx/xv_hdmitxss.c +++ b/hdmi/xilinx-hdmi-tx/xv_hdmitxss.c @@ -128,15 +128,16 @@ * XV_HdmiTxSs_SetVideoStreamHdmi14ScramblingOverrideFlag * 25/01/18 Added function XV_HdmiTxSs_SetScrambler * 01/02/18 Updated function XV_HdmiTxSs_VtcSetup and changed the -* input parameters to it to enable logging of -* unsupported video timing by VTC +* input parameters to it to enable logging of +* unsupported video timing by VTC +* SM 28/02/18 Added definition of XV_HdmiTxSS_SetAppVersion() API * 5.20 EB 03/08/18 Updated XV_HdmiTxSS_MaskSetRed, XV_HdmiTxSS_MaskSetGreen, -* XV_HdmiTxSS_MaskSetBlue API -* Replaced XV_HdmiTx_AudioMute API call with -* XV_HdmiTx_AudioDisable -* Replaced XV_HdmiTx_AudioUnmute API call with -* XV_HdmiTx_AudioEnable -* Replaced XV_HdmiTx_AudioUnmute API call with +* XV_HdmiTxSS_MaskSetBlue API +* Replaced XV_HdmiTx_AudioMute API call with +* XV_HdmiTx_AudioDisable +* Replaced XV_HdmiTx_AudioUnmute API call with +* XV_HdmiTx_AudioEnable +* Replaced XV_HdmiTx_AudioUnmute API call with * MMO 11/08/18 Added Bridge Overflow and Bridge Underflow Interrupt * * @@ -1388,9 +1389,9 @@ static void XV_HdmiTxSs_StreamDownCallback(void *CallbackRef) * ******************************************************************************/ int XV_HdmiTxSs_SetCallback(XV_HdmiTxSs *InstancePtr, - u32 HandlerType, - void *CallbackFunc, - void *CallbackRef) + XV_HdmiTxSs_HandlerType HandlerType, + void *CallbackFunc, + void *CallbackRef) { u32 Status; diff --git a/hdmi/xilinx-hdmi-tx/xv_hdmitxss.h b/hdmi/xilinx-hdmi-tx/xv_hdmitxss.h index 68fb5a1..fb6d41c 100644 --- a/hdmi/xilinx-hdmi-tx/xv_hdmitxss.h +++ b/hdmi/xilinx-hdmi-tx/xv_hdmitxss.h @@ -86,6 +86,8 @@ * 25/01/18 Added function XV_HdmiTxSs_SetScrambler * mmo 08/02/18 Added LowResolutionSupp & YUV420Supp in the * XV_HdmiTxSs_Config +* SM 28/02/18 Added XV_HdmiTxSS_SetAppVersion API and AppMajVer and +* AppMinVer version number in XV_HdmiTxSs structure * MMO 11/08/18 Added Bridge Overflow and Bridge Underflow Interrupt * * @@ -467,9 +469,9 @@ void XV_HdmiTxSs_SetGcpClearAvmuteBit(XV_HdmiTxSs *InstancePtr); void XV_HdmiTxSs_ClearGcpClearAvmuteBit(XV_HdmiTxSs *InstancePtr); int XV_HdmiTxSs_SetCallback(XV_HdmiTxSs *InstancePtr, - u32 HandlerType, - void *CallbackFuncPtr, - void *CallbackRef); + XV_HdmiTxSs_HandlerType HandlerType, + void *CallbackFuncPtr, + void *CallbackRef); int XV_HdmiTxSs_ReadEdid(XV_HdmiTxSs *InstancePtr, u8 *BufferPtr); int XV_HdmiTxSs_ReadEdidSegment(XV_HdmiTxSs *InstancePtr, u8 *Buffer, u8 segment); void XV_HdmiTxSs_SetScrambler(XV_HdmiTxSs *InstancePtr, u8 Enable); diff --git a/hdmi/xilinx-hdmi-tx/xvtc.c b/hdmi/xilinx-hdmi-tx/xvtc.c index ace23f2..efd24e8 100644 --- a/hdmi/xilinx-hdmi-tx/xvtc.c +++ b/hdmi/xilinx-hdmi-tx/xvtc.c @@ -193,7 +193,7 @@ * callback functions. If application is not registered any of the callback * function, these functions will be called for doing nothing. */ -static void StubCallBack(void *CallBackRef); +static void StubCallBack(void *CallBackRef, u32 Mask); static void StubErrCallBack(void *CallBackRef, u32 ErrorMask); /************************** Variable Definitions *****************************/ @@ -2614,9 +2614,10 @@ u16 XVtc_GetDetectorVideoMode(XVtc *InstancePtr) * @note None. * ******************************************************************************/ -static void StubCallBack(void *CallBackRef) +static void StubCallBack(void *CallBackRef, u32 Mask) { (void)CallBackRef; + (void)Mask; Xil_AssertVoidAlways(); } diff --git a/hdmi/xilinx-hdmi-tx/xvtc_hw.h b/hdmi/xilinx-hdmi-tx/xvtc_hw.h index a58b6a8..f3de007 100644 --- a/hdmi/xilinx-hdmi-tx/xvtc_hw.h +++ b/hdmi/xilinx-hdmi-tx/xvtc_hw.h @@ -377,6 +377,8 @@ extern "C" { XVTC_IXR_LOCKALL_MASK) /**< Mask for all * interrupts Mask */ +#define XVTC_IXR_SPURIOUS_INTR_MASK ~(XVTC_IXR_ALLINTR_MASK) + /** @name Error Register Bit Definitions * @{ */ diff --git a/hdmi/xilinx-hdmi-tx/xvtc_intr.c b/hdmi/xilinx-hdmi-tx/xvtc_intr.c index db50117..0147826 100644 --- a/hdmi/xilinx-hdmi-tx/xvtc_intr.c +++ b/hdmi/xilinx-hdmi-tx/xvtc_intr.c @@ -167,7 +167,7 @@ void XVtc_IntrHandler(void *InstancePtr) XVtc_IntrClear(XVtcPtr, PendingIntr); /* Spurious interrupt has happened */ - if (0 == (PendingIntr | XVTC_IXR_ALLINTR_MASK)) { + if (PendingIntr | XVTC_IXR_SPURIOUS_INTR_MASK) { ErrorStatus = 0; XVtcPtr->ErrCallBack(XVtcPtr->ErrRef, ErrorStatus); return; From b608fbe6411dbae4f9fb225b925f6eb7b62cdf9f Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Tue, 20 Aug 2019 10:24:27 +0800 Subject: [PATCH 33/46] hdmitx:hdmirx:phy: remove "addtogroup" from files Signed-off-by: Shikhar Mishra --- hdmi/phy-xilinx-vphy/xhdcp1x.c | 1 - hdmi/phy-xilinx-vphy/xhdcp1x.h | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_cipher.c | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_cipher.h | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_cipher_intr.c | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_debug.h | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_hw.h | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_intr.c | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_platform.c | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_platform.h | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_port.c | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_port.h | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi.h | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_rx.c | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_tx.c | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_port_intr.c | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_rx.c | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_rx.h | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_selftest.c | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_sinit.c | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_tx.c | 1 - hdmi/phy-xilinx-vphy/xhdcp1x_tx.h | 1 - hdmi/phy-xilinx-vphy/xhdcp22_cipher.c | 1 - hdmi/phy-xilinx-vphy/xhdcp22_cipher.h | 1 - hdmi/phy-xilinx-vphy/xhdcp22_cipher_hw.h | 1 - hdmi/phy-xilinx-vphy/xhdcp22_cipher_sinit.c | 1 - hdmi/phy-xilinx-vphy/xhdcp22_mmult.c | 1 - hdmi/phy-xilinx-vphy/xhdcp22_mmult.h | 1 - hdmi/phy-xilinx-vphy/xhdcp22_mmult_hw.h | 1 - hdmi/phy-xilinx-vphy/xhdcp22_mmult_sinit.c | 1 - hdmi/phy-xilinx-vphy/xhdcp22_rng.c | 1 - hdmi/phy-xilinx-vphy/xhdcp22_rng.h | 1 - hdmi/phy-xilinx-vphy/xhdcp22_rng_hw.h | 1 - hdmi/phy-xilinx-vphy/xhdcp22_rng_sinit.c | 1 - hdmi/phy-xilinx-vphy/xhdcp22_rx.c | 1 - hdmi/phy-xilinx-vphy/xhdcp22_rx.h | 1 - hdmi/phy-xilinx-vphy/xhdcp22_rx_crypt.c | 1 - hdmi/phy-xilinx-vphy/xhdcp22_rx_i.h | 1 - hdmi/phy-xilinx-vphy/xhdcp22_rx_sinit.c | 1 - hdmi/phy-xilinx-vphy/xhdcp22_tx.c | 1 - hdmi/phy-xilinx-vphy/xhdcp22_tx.h | 1 - hdmi/phy-xilinx-vphy/xhdcp22_tx_crypt.c | 1 - hdmi/phy-xilinx-vphy/xhdcp22_tx_i.h | 1 - hdmi/phy-xilinx-vphy/xhdcp22_tx_sinit.c | 1 - hdmi/phy-xilinx-vphy/xil_types.h | 2 -- hdmi/phy-xilinx-vphy/xstatus.h | 2 -- hdmi/phy-xilinx-vphy/xtmrctr.c | 1 - hdmi/phy-xilinx-vphy/xtmrctr.h | 1 - hdmi/phy-xilinx-vphy/xtmrctr_i.h | 1 - hdmi/phy-xilinx-vphy/xtmrctr_intr.c | 1 - hdmi/phy-xilinx-vphy/xtmrctr_l.c | 1 - hdmi/phy-xilinx-vphy/xtmrctr_l.h | 1 - hdmi/phy-xilinx-vphy/xtmrctr_options.c | 1 - hdmi/phy-xilinx-vphy/xtmrctr_sinit.c | 1 - hdmi/phy-xilinx-vphy/xv_hdmic.c | 1 - hdmi/phy-xilinx-vphy/xv_hdmic.h | 1 - hdmi/phy-xilinx-vphy/xvidc.c | 1 - hdmi/phy-xilinx-vphy/xvidc.h | 1 - hdmi/phy-xilinx-vphy/xvidc_timings_table.c | 1 - hdmi/phy-xilinx-vphy/xvphy.h | 1 - hdmi/phy-xilinx-vphy/xvphy_gt.h | 1 - hdmi/phy-xilinx-vphy/xvphy_hdmi.h | 1 - hdmi/phy-xilinx-vphy/xvphy_hw.h | 1 - hdmi/phy-xilinx-vphy/xvphy_i.h | 1 - hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.c | 1 - hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.h | 1 - hdmi/xilinx-hdmi-tx/xv_hdmitxss_coreinit.c | 1 - hdmi/xilinx-hdmi-tx/xv_hdmitxss_coreinit.h | 1 - hdmi/xilinx-hdmi-tx/xvtc.c | 1 - hdmi/xilinx-hdmi-tx/xvtc.h | 1 - hdmi/xilinx-hdmi-tx/xvtc_hw.h | 1 - hdmi/xilinx-hdmi-tx/xvtc_intr.c | 1 - hdmi/xilinx-hdmi-tx/xvtc_sinit.c | 1 - 73 files changed, 75 deletions(-) diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x.c b/hdmi/phy-xilinx-vphy/xhdcp1x.c index a6a9de7..030798a 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x.c @@ -17,7 +17,6 @@ /** * * @file xhdcp1x.c -* @addtogroup hdcp1x_v4_0 * @{ * * This contains the implementation of the HDCP state machine module diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x.h b/hdmi/phy-xilinx-vphy/xhdcp1x.h index b4c64d1..e699600 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x.h +++ b/hdmi/phy-xilinx-vphy/xhdcp1x.h @@ -17,7 +17,6 @@ /** * * @file xhdcp1x.h -* @addtogroup hdcp1x_v4_0 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_cipher.c b/hdmi/phy-xilinx-vphy/xhdcp1x_cipher.c index cf46e14..e74c20d 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_cipher.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_cipher.c @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_cipher.c -* @addtogroup hdcp1x_v4_0 * @{ * * This file contains the main implementation of the driver associated with diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_cipher.h b/hdmi/phy-xilinx-vphy/xhdcp1x_cipher.h index 040422b..de03590 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_cipher.h +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_cipher.h @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_cipher.h -* @addtogroup hdcp1x_v4_0 * @{ * * This is the main header file for Xilinx HDCP Cipher core. diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_cipher_intr.c b/hdmi/phy-xilinx-vphy/xhdcp1x_cipher_intr.c index 5356ff1..77e2ba0 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_cipher_intr.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_cipher_intr.c @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_cipher_intr.c -* @addtogroup hdcp1x_v4_0 * @{ * * This file contains interrupt related functions for Xilinx HDCP core. diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_debug.h b/hdmi/phy-xilinx-vphy/xhdcp1x_debug.h index a9ea10c..a58dcb2 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_debug.h +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_debug.h @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_debug.h -* @addtogroup hdcp1x_v4_0 * @{ * * This file provides the interface of the HDCP debug commands diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_hw.h b/hdmi/phy-xilinx-vphy/xhdcp1x_hw.h index adbe1cf..b19bf4b 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_hw.h +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_hw.h @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_hw.h -* @addtogroup hdcp1x_v4_0 * @{ * * This header file contains identifiers and register-level core functions (or diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_intr.c b/hdmi/phy-xilinx-vphy/xhdcp1x_intr.c index 738a03a..42f4569 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_intr.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_intr.c @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_cipher_intr.c -* @addtogroup hdcp1x_v4_0 * @{ * * This file contains interrupt related functions for Xilinx HDCP core. diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_platform.c b/hdmi/phy-xilinx-vphy/xhdcp1x_platform.c index a6eb26e..62b6037 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_platform.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_platform.c @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_platform.c -* @addtogroup hdcp1x_v4_0 * @{ * * This file provides the implementation for the hdcp platform integration diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_platform.h b/hdmi/phy-xilinx-vphy/xhdcp1x_platform.h index 05a9247..d4991bb 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_platform.h +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_platform.h @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_platform.h -* @addtogroup hdcp1x_v4_0 * @{ * * This file provides the interface for the hdcp platform integration module diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_port.c b/hdmi/phy-xilinx-vphy/xhdcp1x_port.c index 6766cea..dbef966 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_port.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_port.c @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_port.c -* @addtogroup hdcp1x_v4_0 * @{ * * This contains the main implementation file for the Xilinx HDCP Port driver diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_port.h b/hdmi/phy-xilinx-vphy/xhdcp1x_port.h index 58a03d4..ccf76c9 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_port.h +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_port.h @@ -16,7 +16,6 @@ /** * * @file xhdcp1x_port.h -* @addtogroup hdcp1x_v4_0 * @{ * * This header file contains the external declarations associated with the diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi.h b/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi.h index ce404ca..f2d09e9 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi.h +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi.h @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_port_hdmi.h -* @addtogroup hdcp1x_v4_0 * @{ * * This file contains the definitions for the hdcp port registers/offsets for diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_rx.c b/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_rx.c index 4945937..ea3ecfe 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_rx.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_rx.c @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_port_hdmi_rx.c -* @addtogroup hdcp1x_v4_0 * @{ * * This contains the implementation of the HDCP port driver for HDMI RX diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_tx.c b/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_tx.c index ceae72d..ef5e7cd 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_tx.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_port_hdmi_tx.c @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_port_hdmi_tx.c -* @addtogroup hdcp1x_v4_0 * @{ * * This contains the implementation of the HDCP port driver for HDMI TX diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_port_intr.c b/hdmi/phy-xilinx-vphy/xhdcp1x_port_intr.c index f650089..591127c 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_port_intr.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_port_intr.c @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_port_intr.c -* @addtogroup hdcp1x_v4_0 * @{ * * This contains the interrupt related functions of the Xilinx HDCP port driver diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_rx.c b/hdmi/phy-xilinx-vphy/xhdcp1x_rx.c index f704387..5f95667 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_rx.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_rx.c @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_rx.c -* @addtogroup hdcp1x_v4_0 * @{ * * This contains the main implementation file for the Xilinx HDCP receive state diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_rx.h b/hdmi/phy-xilinx-vphy/xhdcp1x_rx.h index 895166f..c2c011c 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_rx.h +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_rx.h @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_rx.h -* @addtogroup hdcp1x_v4_0 * @{ * * This file provides the interface of the HDCP RX state machine diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_selftest.c b/hdmi/phy-xilinx-vphy/xhdcp1x_selftest.c index a011403..cd45a42 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_selftest.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_selftest.c @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_selftest.c -* @addtogroup hdcp1x_v4_0 * @{ * * This file contains self test function for the hdcp interface diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_sinit.c b/hdmi/phy-xilinx-vphy/xhdcp1x_sinit.c index 19e98ca..5cd30a3 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_sinit.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_sinit.c @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_sinit.c -* @addtogroup hdcp1x_v4_0 * @{ * * This file contains static initialization method for Xilinx HDCP driver diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_tx.c b/hdmi/phy-xilinx-vphy/xhdcp1x_tx.c index 0c5a0a0..b7d1743 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_tx.c +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_tx.c @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_tx.c -* @addtogroup hdcp1x_v4_2 * @{ * * This contains the main implementation file for the Xilinx HDCP transmit diff --git a/hdmi/phy-xilinx-vphy/xhdcp1x_tx.h b/hdmi/phy-xilinx-vphy/xhdcp1x_tx.h index f9a006f..a09b273 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp1x_tx.h +++ b/hdmi/phy-xilinx-vphy/xhdcp1x_tx.h @@ -17,7 +17,6 @@ /** * * @file xhdcp1x_tx.h -* @addtogroup hdcp1x_v4_2 * @{ * * This file provides the interface of the HDCP TX state machine diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_cipher.c b/hdmi/phy-xilinx-vphy/xhdcp22_cipher.c index 60d2074..751cc87 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_cipher.c +++ b/hdmi/phy-xilinx-vphy/xhdcp22_cipher.c @@ -17,7 +17,6 @@ /** * * @file xhdcp22_cipher.c -* @addtogroup hdcp22_cipher_v1_1 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_cipher.h b/hdmi/phy-xilinx-vphy/xhdcp22_cipher.h index 86825e1..a4f7d89 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_cipher.h +++ b/hdmi/phy-xilinx-vphy/xhdcp22_cipher.h @@ -17,7 +17,6 @@ /** * * @file xhdcp22_cipher.h -* @addtogroup hdcp22_cipher_v1_1 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_cipher_hw.h b/hdmi/phy-xilinx-vphy/xhdcp22_cipher_hw.h index ee84a84..1bcb442 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_cipher_hw.h +++ b/hdmi/phy-xilinx-vphy/xhdcp22_cipher_hw.h @@ -17,7 +17,6 @@ /** * * @file xhdcp22_cipher_hw.h -* @addtogroup hdcp22_cipher_v1_1 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_cipher_sinit.c b/hdmi/phy-xilinx-vphy/xhdcp22_cipher_sinit.c index 4f9e96e..7c75008 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_cipher_sinit.c +++ b/hdmi/phy-xilinx-vphy/xhdcp22_cipher_sinit.c @@ -17,7 +17,6 @@ /** * * @file xhdcp22_cipher_sinit.c -* @addtogroup hdcp22_cipher_v1_1 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_mmult.c b/hdmi/phy-xilinx-vphy/xhdcp22_mmult.c index a816b47..b576b7e 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_mmult.c +++ b/hdmi/phy-xilinx-vphy/xhdcp22_mmult.c @@ -17,7 +17,6 @@ /** * * @file xhdcp22_mmult.c -* @addtogroup hdcp22_mmult_v1_1 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_mmult.h b/hdmi/phy-xilinx-vphy/xhdcp22_mmult.h index cba4338..60e855c 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_mmult.h +++ b/hdmi/phy-xilinx-vphy/xhdcp22_mmult.h @@ -17,7 +17,6 @@ /** * * @file xhdcp22_mmult.h -* @addtogroup hdcp22_mmult_v1_1 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_mmult_hw.h b/hdmi/phy-xilinx-vphy/xhdcp22_mmult_hw.h index b8f2165..fd3c40f 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_mmult_hw.h +++ b/hdmi/phy-xilinx-vphy/xhdcp22_mmult_hw.h @@ -17,7 +17,6 @@ /** * * @file xhdcp22_mmult_hw.h -* @addtogroup hdcp22_mmult_v1_1 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_mmult_sinit.c b/hdmi/phy-xilinx-vphy/xhdcp22_mmult_sinit.c index e6c1718..b43ede7 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_mmult_sinit.c +++ b/hdmi/phy-xilinx-vphy/xhdcp22_mmult_sinit.c @@ -17,7 +17,6 @@ /** * * @file xhdcp22_mmult_sinit.c -* @addtogroup hdcp22_mmult_v1_1 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_rng.c b/hdmi/phy-xilinx-vphy/xhdcp22_rng.c index 30d6a13..69e440f 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_rng.c +++ b/hdmi/phy-xilinx-vphy/xhdcp22_rng.c @@ -17,7 +17,6 @@ /** * * @file xhdcp22_rng.c -* @addtogroup hdcp22_rng_v1_1 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_rng.h b/hdmi/phy-xilinx-vphy/xhdcp22_rng.h index 0e79ccb..7b9bbea 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_rng.h +++ b/hdmi/phy-xilinx-vphy/xhdcp22_rng.h @@ -17,7 +17,6 @@ /** * * @file xhdcp22_rng.h -* @addtogroup hdcp22_rng_v1_1 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_rng_hw.h b/hdmi/phy-xilinx-vphy/xhdcp22_rng_hw.h index 944f685..ea5f9f7 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_rng_hw.h +++ b/hdmi/phy-xilinx-vphy/xhdcp22_rng_hw.h @@ -17,7 +17,6 @@ /** * * @file xhdcp22_rng_hw.h -* @addtogroup hdcp22_rng_v1_1 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_rng_sinit.c b/hdmi/phy-xilinx-vphy/xhdcp22_rng_sinit.c index 6d017c3..951ab77 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_rng_sinit.c +++ b/hdmi/phy-xilinx-vphy/xhdcp22_rng_sinit.c @@ -17,7 +17,6 @@ /** * * @file xhdcp22_rng_sinit.c -* @addtogroup hdcp22_rng_v1_1 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_rx.c b/hdmi/phy-xilinx-vphy/xhdcp22_rx.c index 5e61095..250616a 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_rx.c +++ b/hdmi/phy-xilinx-vphy/xhdcp22_rx.c @@ -16,7 +16,6 @@ /*****************************************************************************/ /** * @file xhdcp22_rx.c -* @addtogroup hdcp22_rx_v2_0 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_rx.h b/hdmi/phy-xilinx-vphy/xhdcp22_rx.h index 1c16bda..98cf121 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_rx.h +++ b/hdmi/phy-xilinx-vphy/xhdcp22_rx.h @@ -16,7 +16,6 @@ /*****************************************************************************/ /** * @file xhdcp22_rx.h -* @addtogroup hdcp22_rx_v2_0 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_rx_crypt.c b/hdmi/phy-xilinx-vphy/xhdcp22_rx_crypt.c index d4dc806..e9f98f2 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_rx_crypt.c +++ b/hdmi/phy-xilinx-vphy/xhdcp22_rx_crypt.c @@ -16,7 +16,6 @@ /*****************************************************************************/ /** * @file xhdcp22_rx_crypt.c -* @addtogroup hdcp22_rx_v2_0 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_rx_i.h b/hdmi/phy-xilinx-vphy/xhdcp22_rx_i.h index 10be673..08b0f52 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_rx_i.h +++ b/hdmi/phy-xilinx-vphy/xhdcp22_rx_i.h @@ -16,7 +16,6 @@ /*****************************************************************************/ /** * @file xhdcp22_rx_i.h -* @addtogroup hdcp22_rx_v2_0 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_rx_sinit.c b/hdmi/phy-xilinx-vphy/xhdcp22_rx_sinit.c index 66d4280..ad7ba5b 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_rx_sinit.c +++ b/hdmi/phy-xilinx-vphy/xhdcp22_rx_sinit.c @@ -16,7 +16,6 @@ /*****************************************************************************/ /** * @file xhdcp22_rx_sinit.c -* @addtogroup hdcp22_rx_v2_0 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_tx.c b/hdmi/phy-xilinx-vphy/xhdcp22_tx.c index 170fb5b..75722d0 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_tx.c +++ b/hdmi/phy-xilinx-vphy/xhdcp22_tx.c @@ -18,7 +18,6 @@ /** * * @file xhdcp22_tx.c -* @addtogroup hdcp22_tx_v2_0 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_tx.h b/hdmi/phy-xilinx-vphy/xhdcp22_tx.h index f5f485c..f53461d 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_tx.h +++ b/hdmi/phy-xilinx-vphy/xhdcp22_tx.h @@ -17,7 +17,6 @@ /** * * @file xhdcp22_tx.h -* @addtogroup hdcp22_tx_v2_0 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_tx_crypt.c b/hdmi/phy-xilinx-vphy/xhdcp22_tx_crypt.c index 7857ac3..5efdbfe 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_tx_crypt.c +++ b/hdmi/phy-xilinx-vphy/xhdcp22_tx_crypt.c @@ -17,7 +17,6 @@ /** * * @file xhdcp22_tx_crypt.c -* @addtogroup hdcp22_tx_v2_4 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_tx_i.h b/hdmi/phy-xilinx-vphy/xhdcp22_tx_i.h index 1e18235..e0bde36 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_tx_i.h +++ b/hdmi/phy-xilinx-vphy/xhdcp22_tx_i.h @@ -17,7 +17,6 @@ /** * * @file xhdcp22_tx_i.h -* @addtogroup hdcp22_tx_v2_0 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xhdcp22_tx_sinit.c b/hdmi/phy-xilinx-vphy/xhdcp22_tx_sinit.c index 9400d74..48a8408 100644 --- a/hdmi/phy-xilinx-vphy/xhdcp22_tx_sinit.c +++ b/hdmi/phy-xilinx-vphy/xhdcp22_tx_sinit.c @@ -17,7 +17,6 @@ /** * * @file xhdcp22_tx_sinit.c -* @addtogroup hdcp22_tx_v2_0 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xil_types.h b/hdmi/phy-xilinx-vphy/xil_types.h index f1dc072..112fd87 100644 --- a/hdmi/phy-xilinx-vphy/xil_types.h +++ b/hdmi/phy-xilinx-vphy/xil_types.h @@ -18,7 +18,6 @@ * * @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. @@ -196,5 +195,4 @@ typedef void (*XExceptionHandler) (void *InstancePtr); #endif /* end of protection macro */ /** -* @} End of "addtogroup common_types". */ diff --git a/hdmi/phy-xilinx-vphy/xstatus.h b/hdmi/phy-xilinx-vphy/xstatus.h index 5f4835f..8815f06 100644 --- a/hdmi/phy-xilinx-vphy/xstatus.h +++ b/hdmi/phy-xilinx-vphy/xstatus.h @@ -18,7 +18,6 @@ * * @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. @@ -515,5 +514,4 @@ typedef s32 XStatus; #endif /* end of protection macro */ /** -* @} End of "addtogroup common_status_codes". */ diff --git a/hdmi/phy-xilinx-vphy/xtmrctr.c b/hdmi/phy-xilinx-vphy/xtmrctr.c index d7c743a..a114277 100644 --- a/hdmi/phy-xilinx-vphy/xtmrctr.c +++ b/hdmi/phy-xilinx-vphy/xtmrctr.c @@ -17,7 +17,6 @@ /** * * @file xtmrctr.c -* @addtogroup tmrctr_v4_0 * @{ * * Contains required functions for the XTmrCtr driver. diff --git a/hdmi/phy-xilinx-vphy/xtmrctr.h b/hdmi/phy-xilinx-vphy/xtmrctr.h index 5ea572b..c2023f3 100644 --- a/hdmi/phy-xilinx-vphy/xtmrctr.h +++ b/hdmi/phy-xilinx-vphy/xtmrctr.h @@ -17,7 +17,6 @@ /** * * @file xtmrctr.h -* @addtogroup tmrctr_v4_0 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xtmrctr_i.h b/hdmi/phy-xilinx-vphy/xtmrctr_i.h index b618131..7d9eaeb 100644 --- a/hdmi/phy-xilinx-vphy/xtmrctr_i.h +++ b/hdmi/phy-xilinx-vphy/xtmrctr_i.h @@ -17,7 +17,6 @@ /** * * @file xtmrctr_i.h -* @addtogroup tmrctr_v3_0 * @{ * * This file contains data which is shared between files internal to the diff --git a/hdmi/phy-xilinx-vphy/xtmrctr_intr.c b/hdmi/phy-xilinx-vphy/xtmrctr_intr.c index 7bcf237..c872020 100644 --- a/hdmi/phy-xilinx-vphy/xtmrctr_intr.c +++ b/hdmi/phy-xilinx-vphy/xtmrctr_intr.c @@ -17,7 +17,6 @@ /** * * @file xtmrctr_intr.c -* @addtogroup tmrctr_v4_0 * @{ * * Contains interrupt-related functions for the XTmrCtr component. diff --git a/hdmi/phy-xilinx-vphy/xtmrctr_l.c b/hdmi/phy-xilinx-vphy/xtmrctr_l.c index 08a039d..a51395f 100644 --- a/hdmi/phy-xilinx-vphy/xtmrctr_l.c +++ b/hdmi/phy-xilinx-vphy/xtmrctr_l.c @@ -17,7 +17,6 @@ /** * * @file xtmrctr_l.c -* @addtogroup tmrctr_v4_0 * @{ * * This file contains low-level driver functions that can be used to access the diff --git a/hdmi/phy-xilinx-vphy/xtmrctr_l.h b/hdmi/phy-xilinx-vphy/xtmrctr_l.h index ead95f8..3fa67b6 100644 --- a/hdmi/phy-xilinx-vphy/xtmrctr_l.h +++ b/hdmi/phy-xilinx-vphy/xtmrctr_l.h @@ -17,7 +17,6 @@ /** * * @file xtmrctr_l.h -* @addtogroup tmrctr_v4_0 * @{ * * This header file contains identifiers and low-level driver functions (or diff --git a/hdmi/phy-xilinx-vphy/xtmrctr_options.c b/hdmi/phy-xilinx-vphy/xtmrctr_options.c index e696edd..97d08cf 100644 --- a/hdmi/phy-xilinx-vphy/xtmrctr_options.c +++ b/hdmi/phy-xilinx-vphy/xtmrctr_options.c @@ -17,7 +17,6 @@ /** * * @file xtmrctr_options.c -* @addtogroup tmrctr_v4_0 * @{ * * Contains configuration options functions for the XTmrCtr component. diff --git a/hdmi/phy-xilinx-vphy/xtmrctr_sinit.c b/hdmi/phy-xilinx-vphy/xtmrctr_sinit.c index 48213d2..88cfa5c 100644 --- a/hdmi/phy-xilinx-vphy/xtmrctr_sinit.c +++ b/hdmi/phy-xilinx-vphy/xtmrctr_sinit.c @@ -17,7 +17,6 @@ /** * * @file xtmrctr_sinit.c -* @addtogroup tmrctr_v4_0 * @{ * * This file contains static initialization methods for the XTmrCtr driver. diff --git a/hdmi/phy-xilinx-vphy/xv_hdmic.c b/hdmi/phy-xilinx-vphy/xv_hdmic.c index d306985..77ed4cc 100644 --- a/hdmi/phy-xilinx-vphy/xv_hdmic.c +++ b/hdmi/phy-xilinx-vphy/xv_hdmic.c @@ -15,7 +15,6 @@ /** * * @file xhdmic.c - * @addtogroup hdmi_common_v1_0 * @{ * * Contains common utility functions that are typically used by hdmi-related diff --git a/hdmi/phy-xilinx-vphy/xv_hdmic.h b/hdmi/phy-xilinx-vphy/xv_hdmic.h index e9b8fe4..b6c0b14 100644 --- a/hdmi/phy-xilinx-vphy/xv_hdmic.h +++ b/hdmi/phy-xilinx-vphy/xv_hdmic.h @@ -16,7 +16,6 @@ /** * * @file xhdmic.h - * @addtogroup hdmi_common_v1_0 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xvidc.c b/hdmi/phy-xilinx-vphy/xvidc.c index fc28f96..dbabf8a 100644 --- a/hdmi/phy-xilinx-vphy/xvidc.c +++ b/hdmi/phy-xilinx-vphy/xvidc.c @@ -17,7 +17,6 @@ /** * * @file xvidc.c - * @addtogroup video_common_v4_0 * @{ * * Contains common utility functions that are typically used by video-related diff --git a/hdmi/phy-xilinx-vphy/xvidc.h b/hdmi/phy-xilinx-vphy/xvidc.h index 1304ea8..b4bdf85 100644 --- a/hdmi/phy-xilinx-vphy/xvidc.h +++ b/hdmi/phy-xilinx-vphy/xvidc.h @@ -17,7 +17,6 @@ /** * * @file xvidc.h - * @addtogroup video_common_v4_3 * @{ * @details * diff --git a/hdmi/phy-xilinx-vphy/xvidc_timings_table.c b/hdmi/phy-xilinx-vphy/xvidc_timings_table.c index 7cfbcaa..314307b 100644 --- a/hdmi/phy-xilinx-vphy/xvidc_timings_table.c +++ b/hdmi/phy-xilinx-vphy/xvidc_timings_table.c @@ -17,7 +17,6 @@ /** * * @file xvidc_timings_table.c - * @addtogroup video_common_v4_2 * @{ * * Contains video timings for various standard resolutions. diff --git a/hdmi/phy-xilinx-vphy/xvphy.h b/hdmi/phy-xilinx-vphy/xvphy.h index 2ff4580..eedf6f2 100644 --- a/hdmi/phy-xilinx-vphy/xvphy.h +++ b/hdmi/phy-xilinx-vphy/xvphy.h @@ -17,7 +17,6 @@ /** * * @file xvphy.h - * @addtogroup xvphy * @{ * @details * This is main header file of the Xilinx Video PHY Controller driver diff --git a/hdmi/phy-xilinx-vphy/xvphy_gt.h b/hdmi/phy-xilinx-vphy/xvphy_gt.h index 27a7040..f73888b 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_gt.h +++ b/hdmi/phy-xilinx-vphy/xvphy_gt.h @@ -38,7 +38,6 @@ * 1.7 gm 13/09/17 Added GTYE4 support * * - * @addtogroup xvphy_v1_7 * @{ *******************************************************************************/ diff --git a/hdmi/phy-xilinx-vphy/xvphy_hdmi.h b/hdmi/phy-xilinx-vphy/xvphy_hdmi.h index 250e2f0..e780a59 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_hdmi.h +++ b/hdmi/phy-xilinx-vphy/xvphy_hdmi.h @@ -39,7 +39,6 @@ * 1.7 gm 13/09/17 Removed XVphy_DruSetGain API * * - * @addtogroup xvphy_v1_7 * @{ *******************************************************************************/ #if defined (XPAR_XV_HDMITX_0_DEVICE_ID) || defined (XPAR_XV_HDMIRX_0_DEVICE_ID) diff --git a/hdmi/phy-xilinx-vphy/xvphy_hw.h b/hdmi/phy-xilinx-vphy/xvphy_hw.h index 052a12b..b9f7d7d 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_hw.h +++ b/hdmi/phy-xilinx-vphy/xvphy_hw.h @@ -37,7 +37,6 @@ * 1.7 gm 13/09/17 Added GTYE4 support * * - * @addtogroup xvphy * @{ *******************************************************************************/ diff --git a/hdmi/phy-xilinx-vphy/xvphy_i.h b/hdmi/phy-xilinx-vphy/xvphy_i.h index 67695da..b061803 100644 --- a/hdmi/phy-xilinx-vphy/xvphy_i.h +++ b/hdmi/phy-xilinx-vphy/xvphy_i.h @@ -43,7 +43,6 @@ * Moved XVphy_SetRxLpm to xvphy.c/.h * * - * @addtogroup xvphy_v1_7 * @{ *******************************************************************************/ diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.c b/hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.c index f5fd6e4..f032972 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.c @@ -17,7 +17,6 @@ /** * * @file xv_hdmirxss_coreinit.c -* @addtogroup v_hdmirxss * @{ * @details diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.h b/hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.h index 5ea6fe5..5ffe218 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.h +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss_coreinit.h @@ -17,7 +17,6 @@ /** * * @file xv_hdmirxss_coreinit.h -* @addtogroup v_hdmirxss * @{ * @details * diff --git a/hdmi/xilinx-hdmi-tx/xv_hdmitxss_coreinit.c b/hdmi/xilinx-hdmi-tx/xv_hdmitxss_coreinit.c index 57f1e3a..9dbc434 100644 --- a/hdmi/xilinx-hdmi-tx/xv_hdmitxss_coreinit.c +++ b/hdmi/xilinx-hdmi-tx/xv_hdmitxss_coreinit.c @@ -17,7 +17,6 @@ /** * * @file xv_hdmitxss_coreinit.c -* @addtogroup v_hdmitxss * @{ * @details diff --git a/hdmi/xilinx-hdmi-tx/xv_hdmitxss_coreinit.h b/hdmi/xilinx-hdmi-tx/xv_hdmitxss_coreinit.h index 60c4560..bfd948c 100644 --- a/hdmi/xilinx-hdmi-tx/xv_hdmitxss_coreinit.h +++ b/hdmi/xilinx-hdmi-tx/xv_hdmitxss_coreinit.h @@ -17,7 +17,6 @@ /** * * @file xv_hdmitxss_coreinit.h -* @addtogroup v_hdmitxss * @{ * @details * diff --git a/hdmi/xilinx-hdmi-tx/xvtc.c b/hdmi/xilinx-hdmi-tx/xvtc.c index efd24e8..9dd4de7 100644 --- a/hdmi/xilinx-hdmi-tx/xvtc.c +++ b/hdmi/xilinx-hdmi-tx/xvtc.c @@ -17,7 +17,6 @@ /** * * @file xvtc.c -* @addtogroup vtc_v7_2 * @{ * * This is main code of Xilinx MVI Video Timing Controller (VTC) device driver. diff --git a/hdmi/xilinx-hdmi-tx/xvtc.h b/hdmi/xilinx-hdmi-tx/xvtc.h index 5530917..15f2e3e 100644 --- a/hdmi/xilinx-hdmi-tx/xvtc.h +++ b/hdmi/xilinx-hdmi-tx/xvtc.h @@ -17,7 +17,6 @@ /** * * @file xvtc.h -* @addtogroup vtc_v7_2 * @{ * @details * diff --git a/hdmi/xilinx-hdmi-tx/xvtc_hw.h b/hdmi/xilinx-hdmi-tx/xvtc_hw.h index f3de007..4c25ce3 100644 --- a/hdmi/xilinx-hdmi-tx/xvtc_hw.h +++ b/hdmi/xilinx-hdmi-tx/xvtc_hw.h @@ -17,7 +17,6 @@ /** * * @file xvtc_hw.h -* @addtogroup vtc_v7_2 * @{ * * This header file contains identifiers and register-level core functions (or diff --git a/hdmi/xilinx-hdmi-tx/xvtc_intr.c b/hdmi/xilinx-hdmi-tx/xvtc_intr.c index 0147826..cc66ccc 100644 --- a/hdmi/xilinx-hdmi-tx/xvtc_intr.c +++ b/hdmi/xilinx-hdmi-tx/xvtc_intr.c @@ -17,7 +17,6 @@ /** * * @file xvtc_intr.c -* @addtogroup vtc_v7_2 * @{ * * This file contains interrupt related functions of Xilinx VTC core. diff --git a/hdmi/xilinx-hdmi-tx/xvtc_sinit.c b/hdmi/xilinx-hdmi-tx/xvtc_sinit.c index 241b53e..39c3cc3 100644 --- a/hdmi/xilinx-hdmi-tx/xvtc_sinit.c +++ b/hdmi/xilinx-hdmi-tx/xvtc_sinit.c @@ -17,7 +17,6 @@ /** * * @file xvtc_sinit.c -* @addtogroup vtc_v7_2 * @{ * * This file contains static initialization methods for Xilinx VTC core. From 7eeeb1afb5427b381941f89787f269097fde953f Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Tue, 20 Aug 2019 11:35:47 +0800 Subject: [PATCH 34/46] hdmitx:hdmirx:vphy: Enabling suspend and resume Signed-off-by: Shikhar Mishra --- hdmi/phy-vphy.c | 73 ++++++++++++++++++++++++++++++------------ hdmi/xilinx-hdmirx.c | 40 ++++++++++++++++------- hdmi/xilinx_drm_hdmi.c | 29 +++++++++++++++++ 3 files changed, 109 insertions(+), 33 deletions(-) diff --git a/hdmi/phy-vphy.c b/hdmi/phy-vphy.c index 8782952..1eeadaf 100644 --- a/hdmi/phy-vphy.c +++ b/hdmi/phy-vphy.c @@ -159,15 +159,8 @@ EXPORT_SYMBOL_GPL(XVphy_IsBonded); EXPORT_SYMBOL_GPL(XVphy_ClkDetFreqReset); EXPORT_SYMBOL_GPL(XVphy_ClkDetGetRefClkFreqHz); -static irqreturn_t xvphy_irq_handler(int irq, void *dev_id) +static xvphy_intr_disable(struct xvphy_dev *vphydev) { - struct xvphy_dev *vphydev; - - vphydev = (struct xvphy_dev *)dev_id; - 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 | @@ -180,6 +173,34 @@ static irqreturn_t xvphy_irq_handler(int irq, void *dev_id) XVPHY_INTR_HANDLER_TYPE_RX_MMCM_LOCK_CHANGE | XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT | XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); +} + +static xvphy_intr_enable(struct xvphy_dev *vphydev) +{ + 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_MMCM_LOCK_CHANGE | + XVPHY_INTR_HANDLER_TYPE_RX_MMCM_LOCK_CHANGE | + XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT | + XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); +} + +static irqreturn_t xvphy_irq_handler(int irq, void *dev_id) +{ + struct xvphy_dev *vphydev; + + vphydev = (struct xvphy_dev *)dev_id; + if (!vphydev) + return IRQ_NONE; + + /* Disable interrupts in the VPHY, they are re-enabled once serviced */ + xvphy_intr_disable(vphydev); return IRQ_WAKE_THREAD; } @@ -203,19 +224,8 @@ static irqreturn_t xvphy_irq_thread(int irq, void *dev_id) 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_MMCM_LOCK_CHANGE | - XVPHY_INTR_HANDLER_TYPE_RX_MMCM_LOCK_CHANGE | - XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT | - XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); + /* Enable interrupt requesting in the VPHY */ + xvphy_intr_enable(vphydev); return IRQ_HANDLED; } @@ -584,6 +594,26 @@ static int xvphy_probe(struct platform_device *pdev) return 0; } +static int __maybe_unused xvphy_pm_suspend(struct device *dev) +{ + struct xvphy_dev *vphydev = dev_get_drvdata(dev); + dev_dbg(vphydev->dev, "Vphy suspend function called\n"); + xvphy_intr_disable(vphydev); + return 0; +} + +static int __maybe_unused xvphy_pm_resume(struct device *dev) +{ + struct xvphy_dev *vphydev = dev_get_drvdata(dev); + dev_dbg(vphydev->dev, "Vphy resume function called\n"); + xvphy_intr_enable(vphydev); + return 0; +} + +static const struct dev_pm_ops xvphy_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(xvphy_pm_suspend, xvphy_pm_resume) +}; + /* Match table for of_platform binding */ static const struct of_device_id xvphy_of_match[] = { { .compatible = "xlnx,vid-phy-controller-2.2" }, @@ -596,6 +626,7 @@ static struct platform_driver xvphy_driver = { .driver = { .name = "xilinx-vphy", .of_match_table = xvphy_of_match, + .pm = &xvphy_pm_ops, }, }; module_platform_driver(xvphy_driver); diff --git a/hdmi/xilinx-hdmirx.c b/hdmi/xilinx-hdmirx.c index 822f709..2cf037a 100644 --- a/hdmi/xilinx-hdmirx.c +++ b/hdmi/xilinx-hdmirx.c @@ -466,16 +466,6 @@ static const struct media_entity_operations xhdmi_media_ops = { * Power Management */ -static int __maybe_unused xhdmi_pm_suspend(struct device *dev) -{ - return 0; -} - -static int __maybe_unused xhdmi_pm_resume(struct device *dev) -{ - return 0; -} - void HdmiRx_PioIntrHandler(XV_HdmiRx *InstancePtr); void HdmiRx_TmrIntrHandler(XV_HdmiRx *InstancePtr); void HdmiRx_VtdIntrHandler(XV_HdmiRx *InstancePtr); @@ -505,6 +495,30 @@ static void XV_HdmiRxSs_IntrDisable(XV_HdmiRxSs *HdmiRxSsPtr) XV_HdmiRx_LinkIntrDisable(HdmiRxSsPtr->HdmiRxPtr); } +static int __maybe_unused hdmirx_pm_suspend(struct device *dev) +{ + unsigned long flags; + struct xhdmi_device *xhdmi = dev_get_drvdata(dev); + XV_HdmiRxSs *HdmiRxSsPtr = (XV_HdmiRxSs *)&xhdmi->xv_hdmirxss; + dev_dbg(xhdmi->dev,"HDMI RX suspend function called\n"); + spin_lock_irqsave(&xhdmi->irq_lock, flags); + XV_HdmiRxSs_IntrDisable(HdmiRxSsPtr); + spin_unlock_irqrestore(&xhdmi->irq_lock, flags); + return 0; +} + +static int __maybe_unused hdmirx_pm_resume(struct device *dev) +{ + unsigned long flags; + struct xhdmi_device *xhdmi = dev_get_drvdata(dev); + XV_HdmiRxSs *HdmiRxSsPtr = (XV_HdmiRxSs *)&xhdmi->xv_hdmirxss; + dev_dbg(xhdmi->dev,"HDMI RX resume function called\n"); + spin_lock_irqsave(&xhdmi->irq_lock, flags); + XV_HdmiRxSs_IntrEnable(HdmiRxSsPtr); + spin_unlock_irqrestore(&xhdmi->irq_lock, flags); + return 0; +} + static irqreturn_t hdmirx_irq_handler(int irq, void *dev_id) { struct xhdmi_device *xhdmi; @@ -2174,7 +2188,9 @@ static int xhdmi_remove(struct platform_device *pdev) return 0; } -static SIMPLE_DEV_PM_OPS(xhdmi_pm_ops, xhdmi_pm_suspend, xhdmi_pm_resume); +static const struct dev_pm_ops xhdmirx_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(hdmirx_pm_suspend, hdmirx_pm_resume) +}; static const struct of_device_id xhdmi_of_id_table[] = { { .compatible = "xlnx,v-hdmi-rx-ss-3.1" }, @@ -2185,7 +2201,7 @@ MODULE_DEVICE_TABLE(of, xhdmi_of_id_table); static struct platform_driver xhdmi_driver = { .driver = { .name = "xilinx-hdmi-rx", - .pm = &xhdmi_pm_ops, + .pm = &xhdmirx_pm_ops, .of_match_table = xhdmi_of_id_table, }, .probe = xhdmi_probe, diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index a9835e2..2b967dc 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -235,6 +235,30 @@ static void XV_HdmiTxSs_IntrDisable(XV_HdmiTxSs *HdmiTxSsPtr) XV_HdmiTx_PioIntrDisable(HdmiTxSsPtr->HdmiTxPtr); } +static int __maybe_unused hdmitx_pm_suspend(struct device *dev) +{ + unsigned long flags; + struct xlnx_drm_hdmi *xhdmi = dev_get_drvdata(dev); + XV_HdmiTxSs *HdmiTxSsPtr = (XV_HdmiTxSs *)&xhdmi->xv_hdmitxss; + dev_dbg(xhdmi->dev,"HDMI TX suspend function called\n"); + spin_lock_irqsave(&xhdmi->irq_lock, flags); + XV_HdmiTxSs_IntrDisable(HdmiTxSsPtr); + spin_unlock_irqrestore(&xhdmi->irq_lock, flags); + return 0; +} + +static int __maybe_unused hdmitx_pm_resume(struct device *dev) +{ + unsigned long flags; + struct xlnx_drm_hdmi *xhdmi = dev_get_drvdata(dev); + XV_HdmiTxSs *HdmiTxSsPtr = (XV_HdmiTxSs *)&xhdmi->xv_hdmitxss; + dev_dbg(xhdmi->dev,"HDMI TX resume function called\n"); + spin_lock_irqsave(&xhdmi->irq_lock, flags); + XV_HdmiTxSs_IntrEnable(HdmiTxSsPtr); + spin_unlock_irqrestore(&xhdmi->irq_lock, flags); + return 0; +} + /* XV_HdmiTx_IntrHandler */ static irqreturn_t hdmitx_irq_handler(int irq, void *dev_id) { @@ -2564,6 +2588,10 @@ void hdmitx_audio_mute(struct device *dev, bool enable) hdmitx_audio_startup(dev); } +static const struct dev_pm_ops xhdmitx_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(hdmitx_pm_suspend, hdmitx_pm_resume) +}; + static const struct of_device_id xlnx_drm_hdmi_of_match[] = { { .compatible = "xlnx,v-hdmi-tx-ss-3.1", }, { /* end of table */ }, @@ -2576,6 +2604,7 @@ static struct platform_driver xlnx_drm_hdmi_driver = { .driver = { .owner = THIS_MODULE, .name = "xlnx-drm-hdmi", + .pm = &xhdmitx_pm_ops, .of_match_table = xlnx_drm_hdmi_of_match, }, }; From 55a30870d68e5f427292d9037703b2556282c7c1 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Tue, 3 Sep 2019 09:28:35 +0800 Subject: [PATCH 35/46] phy: Enabling 4th GT channel in TX This code will parse "xlnx,use-gt-ch4-hdmi" parameter from DT. So above parameter also needed to be there in DT Signed-off-by: Shikhar Mishra --- Documentation/devicetree/bindings/xlnx,vphy.txt | 4 ++++ hdmi/phy-vphy.c | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/Documentation/devicetree/bindings/xlnx,vphy.txt b/Documentation/devicetree/bindings/xlnx,vphy.txt index e1110cf..58542c6 100644 --- a/Documentation/devicetree/bindings/xlnx,vphy.txt +++ b/Documentation/devicetree/bindings/xlnx,vphy.txt @@ -44,6 +44,9 @@ Required Properties: - xlnx,tx-buffer-bypass: Flag to indicate buffer bypass logic availability - xlnx,transceiver-width: Defines 4 Byte or 2 Byte mode (Note: Only 2 byte is supported at this time) + - xlnx,use-gt-ch4-hdmi: Enables the usage of 4th TX GT channel. + (Default value is 0. + If selected in GUI, then value will be 1) - lane: (port (child) nodes) lane0: @@ -86,6 +89,7 @@ sharing VPHYs, and are therefore subject to change.) xlnx,transceiver-type = <0x5>; xlnx,tx-buffer-bypass = <0x1>; xlnx,transceiver-width = <0x2>; + xlnx,use-gt-ch4-hdmi = <0>; vphy_lane0: vphy_lane@0 { #phy-cells = <4>; diff --git a/hdmi/phy-vphy.c b/hdmi/phy-vphy.c index 1eeadaf..c38093f 100644 --- a/hdmi/phy-vphy.c +++ b/hdmi/phy-vphy.c @@ -392,6 +392,12 @@ static int vphy_parse_of(struct xvphy_dev *vphydev, XVphy_Config *c) has_err_irq = false; has_err_irq = of_property_read_bool(node, "xlnx,err-irq-en"); c->ErrIrq = has_err_irq; + + rc = of_property_read_u32(node, "xlnx,use-gt-ch4-hdmi", &val); + if (rc < 0) + goto error_dt; + c->UseGtAsTxTmdsClk = val; + return 0; error_dt: From c1d04e917e71a0f4b8395a6b4e64a70959fffdc8 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Fri, 6 Sep 2019 15:05:01 +0800 Subject: [PATCH 36/46] hdmi: Driver update till 20190906 Signed-off-by: Shikhar Mishra --- hdmi/phy-xilinx-vphy/xv_hdmic.c | 8 ++++---- hdmi/phy-xilinx-vphy/xvidc.c | 7 ++++--- hdmi/phy-xilinx-vphy/xvidc.h | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/hdmi/phy-xilinx-vphy/xv_hdmic.c b/hdmi/phy-xilinx-vphy/xv_hdmic.c index 77ed4cc..322db33 100644 --- a/hdmi/phy-xilinx-vphy/xv_hdmic.c +++ b/hdmi/phy-xilinx-vphy/xv_hdmic.c @@ -183,10 +183,10 @@ const XHdmiC_TMDS_N_Table TMDSChar_N_Table[] = {148500000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, {185625000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, {222750000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, - {297000000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, - {371250000, { 6144, 4704, 5120, 9408, 10240, 18816, 20480}}, - {445500000, { 4096, 4704, 5120, 9408, 10240, 18816, 20480}}, - {594000000, { 3072, 4704, 5120, 9408, 10240, 18816, 20480}} + {297000000, { 3072, 4704, 5120, 9408, 10240, 18816, 20480}}, + {371250000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + {445500000, { 4096, 6272, 6144, 12544, 12288, 25088, 24576}}, + {594000000, { 3072, 9408, 6144, 18816, 12288, 37632, 24576}} }; /** diff --git a/hdmi/phy-xilinx-vphy/xvidc.c b/hdmi/phy-xilinx-vphy/xvidc.c index dbabf8a..663672c 100644 --- a/hdmi/phy-xilinx-vphy/xvidc.c +++ b/hdmi/phy-xilinx-vphy/xvidc.c @@ -1093,10 +1093,10 @@ void XVidC_ReportStreamInfo(const XVidC_VideoStream *Stream) xil_printf("\tResolution: %dx%d [Custom Mode]\r\n", Stream->Timing.HActive, Stream->Timing.VActive); xil_printf("\tPixel Clock: %d kHz\r\n", - XVidC_GetPixelClockHzByHVFr( + (u32)(XVidC_GetPixelClockHzByHVFr( Stream->Timing.HTotal, Stream->Timing.F0PVTotal, - Stream->FrameRate)/1000); + Stream->FrameRate)/1000)); } else { xil_printf("\tFrame Rate: %s\r\n", @@ -1104,7 +1104,8 @@ void XVidC_ReportStreamInfo(const XVidC_VideoStream *Stream) xil_printf("\tResolution: %s\r\n", XVidC_GetVideoModeStr(Stream->VmId)); xil_printf("\tPixel Clock: %d kHz\r\n", - (XVidC_GetPixelClockHzByVmId(Stream->VmId)/1000)); + (u32)(XVidC_GetPixelClockHzByVmId(Stream->VmId) + /1000)); } } diff --git a/hdmi/phy-xilinx-vphy/xvidc.h b/hdmi/phy-xilinx-vphy/xvidc.h index b4bdf85..aa6c599 100644 --- a/hdmi/phy-xilinx-vphy/xvidc.h +++ b/hdmi/phy-xilinx-vphy/xvidc.h @@ -60,7 +60,7 @@ * vyc 04/04/18 Added BGR8 memory format * 4.5 jsr 07/03/18 Added XVIDC_VM_720x486_60_I video format * 4.5 yas 03/08/19 Added support for frame rates 144HZ and 240HZ - * 4.5 mmo 02/14/19 Added 5k, 8k, 10k and Low Resolution with 200Hz, 240Hz + * 4.6 mmo 02/14/19 Added 5k, 8k, 10k and Low Resolution with 200Hz, 240Hz * * *******************************************************************************/ From c2c23ad36e891d00a16ac93a5f16d664b5f51035 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Thu, 12 Sep 2019 18:28:06 +0800 Subject: [PATCH 37/46] hdmirx: Added check for stream to be up when handling Interlaced stream. Signed-off-by: Shikhar Mishra --- hdmi/xilinx-hdmi-rx/xv_hdmirx.c | 18 +++++++++++++++--- hdmi/xilinx-hdmi-rx/xv_hdmirxss.h | 1 + 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirx.c b/hdmi/xilinx-hdmi-rx/xv_hdmirx.c index 2c6e148..4665e7c 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirx.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirx.c @@ -52,6 +52,11 @@ * Added TMDS Clock Ratio callback support * 2.30 EB 05/03/19 Updated the description of the API * XV_HdmiRx_GetLinkStatus +* 2.40 EB 30/07/19 Updated XV_HdmiRx_GetVideoTiming to fix an issue where +* FrameRate for YUV420 may be incorrect +* Updated XV_HdmiRx_GetVideoTiming to fix an issue where +* video timing values may be incorrect +* 06/08/19 Added Vic and Video Timing mismatch callback support * * ******************************************************************************/ @@ -1529,9 +1534,16 @@ int XV_HdmiRx_GetVideoTiming(XV_HdmiRx *InstancePtr) Match = FALSE; } - if ((IsInterlaced == 1) & (!F1VFrontPorch | !F1VSyncWidth | !F1VBackPorch | !F1VTotal)) { - Match = FALSE; - } + if (IsInterlaced == 1) { + if (F1VTotal != (VActive + F1VFrontPorch + + F1VSyncWidth + F1VBackPorch)) { + Match = FALSE; + } + } else { + if (F1VFrontPorch | F1VSyncWidth | F1VBackPorch) { + Match = FALSE; + } + } // Htotal if (HTotal != InstancePtr->Stream.Video.Timing.HTotal) { diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h index b2387d0..d7d69bb 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss.h @@ -81,6 +81,7 @@ * Added TMDS Clock Ratio callback support * YB 17/08/18 Marked XV_HDMIRXSS_HDCP_1_PROT_EVT and * XV_HDMIRXSS_HDCP_2_PROT_EVT as deprecated. +* 5.40 EB 06/08/19 Added Vic and Video Timing mismatch callback support * * ******************************************************************************/ From be354cc3c8889932aabede8cddda0770d77e7843 Mon Sep 17 00:00:00 2001 From: Shikhar Mishra Date: Fri, 11 Oct 2019 08:21:03 +0800 Subject: [PATCH 38/46] license: Update the license 2019.2 Signed-off-by: Shikhar Mishra --- LICENSE.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 76ac498..0b84890 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Components: xhdmi 2019.1 +Components: xhdmi 2019.2 GNU GENERAL PUBLIC LICENSE @@ -344,10 +344,13 @@ Public License instead of this License. +Copyright 2001 D.I. Management Services Pty Ltd Copyright 2007-2009 Ilya O. Levin -Copyright (C) 1989 1991 Free Software Foundation Inc. +Copyright 2018 Rohit Consul +Copyright 1989, 1991 Free Software Foundation Inc +Copyright 2001 David Ireland D.I. Management Services Pty Ltd +Copyright 2007 Hans Verkuil Copyright 2016-2017 Leon Woestenberg -Copyright (C) 2018 Rohit Consul Copyright 2014-2019 Xilinx Inc @@ -539,7 +542,7 @@ Exhibit B - ?Incompatible With Secondary Licenses? Notice This Source Code Form is ?Incompatible With Secondary Licenses?, as defined by the Mozilla Public License, v. 2.0. -copyright (c) 2001-15 by D.I. Management Services Pty Limited +Copyright 2001 D.I. Management Services Pty Ltd Copyright 2001 David Ireland D.I. Management Services Pty Ltd @@ -684,8 +687,6 @@ Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. -Copyright (C) 2007 Hans Verkuil +Copyright 2007 Hans Verkuil Copyright 2016-2017 Leon Woestenberg - - From bdc9b05e666a1604a36781dcd6b45f5006e95200 Mon Sep 17 00:00:00 2001 From: Vishal Sagar Date: Wed, 26 Feb 2020 17:24:48 +0530 Subject: [PATCH 39/46] hdmirx: Fix compilation with v5.4 kernel The compilation with v5.4 kernel fails as xilinx-vip.h is include path is not added. This is needed as the driver depends on xvip_enum_mbus_code(). Since the driver should ideally include either from local dir or from include/ dir only, the xvip_enum_mbus_code() is added to driver directly as xhdmi_enum_mbus_code(). Signed-off-by: Vishal Sagar --- hdmi/Makefile | 2 +- hdmi/xilinx-hdmirx.c | 39 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/hdmi/Makefile b/hdmi/Makefile index 10be8d1..d323c72 100644 --- a/hdmi/Makefile +++ b/hdmi/Makefile @@ -37,7 +37,7 @@ xilinx-hdmi-rx-objs := xilinx-hdmirx.o # the C API around the IP registers CFLAGS_xilinx-hdmirx.o += -I$(src)/xilinx-hdmi-rx/ -CFLAGS_xilinx-hdmirx.o += -I$(src)/include/ -Idrivers/media/platform/xilinx/ +CFLAGS_xilinx-hdmirx.o += -I$(src)/include/ xilinx-hdmi-rx-objs += xilinx-hdmi-rx/xv_hdmirx.o xilinx-hdmi-rx-objs += xilinx-hdmi-rx/xv_hdmirx_sinit.o xilinx-hdmi-rx-objs += xilinx-hdmi-rx/xv_hdmirx_intr.o diff --git a/hdmi/xilinx-hdmirx.c b/hdmi/xilinx-hdmirx.c index 2cf037a..600f721 100644 --- a/hdmi/xilinx-hdmirx.c +++ b/hdmi/xilinx-hdmirx.c @@ -31,7 +31,6 @@ #include #include "linux/phy/phy-vphy.h" -#include "xilinx-vip.h" /* baseline driver includes */ #include "xilinx-hdmi-rx/xv_hdmirxss.h" @@ -357,6 +356,42 @@ static int xhdmi_enum_frame_size(struct v4l2_subdev *subdev, return 0; } +/** + * xhdmi_enum_mbus_code - Enumerate the media format code + * @subdev: V4L2 subdevice + * @cfg: V4L2 subdev pad configuration + * @code: returning media bus code + * + * Enumerate the media bus code of the subdevice. Return the corresponding + * pad format code. This function only works for subdevices with fixed format + * on all pads. Subdevices with multiple format should have their own + * function to enumerate mbus codes. + * + * Return: 0 if the media bus code is found, or -EINVAL if the format index + * is not valid. + */ +int xhdmi_enum_mbus_code(struct v4l2_subdev *subdev, + struct v4l2_subdev_pad_config *cfg, + struct v4l2_subdev_mbus_code_enum *code) +{ + struct v4l2_mbus_framefmt *format; + + /* Enumerating frame sizes based on the active configuration isn't + * supported yet. + */ + if (code->which == V4L2_SUBDEV_FORMAT_ACTIVE) + return -EINVAL; + + if (code->index) + return -EINVAL; + + format = v4l2_subdev_get_try_format(subdev, cfg, code->pad); + + code->code = format->code; + + return 0; +} + static int xhdmi_dv_timings_cap(struct v4l2_subdev *subdev, struct v4l2_dv_timings_cap *cap) { @@ -434,7 +469,7 @@ static struct v4l2_subdev_video_ops xhdmi_video_ops = { * it must implement format related functionality using v4l2_subdev_pad_ops instead of * v4l2_subdev_video_ops. */ static struct v4l2_subdev_pad_ops xhdmi_pad_ops = { - .enum_mbus_code = xvip_enum_mbus_code, + .enum_mbus_code = xhdmi_enum_mbus_code, .enum_frame_size = xhdmi_enum_frame_size, .get_fmt = xhdmi_get_format, .set_fmt = xhdmi_set_format, From bcaad045fe50b77f52f8129a4abe7c5cbc40db8d Mon Sep 17 00:00:00 2001 From: Vishal Sagar Date: Wed, 26 Feb 2020 17:30:29 +0530 Subject: [PATCH 40/46] hdmitx: Fix compilation issues with v5.4 kernel This fixes compilation error caused by moving of drm_helper_probe_single_connector_modes() prototype to new header file. Signed-off-by: Vishal Sagar --- hdmi/xilinx_drm_hdmi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index 2b967dc..150359d 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include From 4975a5692c537ae9df0dd9f165fd4d4d75c99c02 Mon Sep 17 00:00:00 2001 From: Vishal Sagar Date: Tue, 31 Mar 2020 00:09:51 +0530 Subject: [PATCH 41/46] hdmi: Update drivers till 20200330 Update all the drivers upto 20200330. Signed-off-by: Vishal Sagar --- hdmi/phy-xilinx-vphy/sha2.c | 8 ++- hdmi/phy-xilinx-vphy/xv_hdmic.c | 72 +++++++++++++++++++--- hdmi/phy-xilinx-vphy/xv_hdmic.h | 4 +- hdmi/phy-xilinx-vphy/xv_hdmic_vsif.c | 7 +-- hdmi/phy-xilinx-vphy/xvidc.c | 5 +- hdmi/phy-xilinx-vphy/xvidc.h | 16 ++++- hdmi/phy-xilinx-vphy/xvidc_timings_table.c | 45 ++++++++++++-- hdmi/xilinx-hdmi-rx/xv_hdmirxss_log.c | 1 + hdmi/xilinx-hdmi-tx/xvtc_intr.c | 3 +- 9 files changed, 135 insertions(+), 26 deletions(-) diff --git a/hdmi/phy-xilinx-vphy/sha2.c b/hdmi/phy-xilinx-vphy/sha2.c index 04aa7bc..81c651f 100644 --- a/hdmi/phy-xilinx-vphy/sha2.c +++ b/hdmi/phy-xilinx-vphy/sha2.c @@ -25,6 +25,7 @@ * Ver Who Date Changes * ----- ---- -------- ----------------------------------------------- * 1.00 MH 10/30/15 First Release +* 1.10 GM 10/14/19 Added "volatile" attribute to all "i" variables * * *****************************************************************************/ @@ -114,7 +115,8 @@ void XHdcp22Cmn_Sha256Hash(const u8 *Data, u32 DataSize, u8 *HashedData) ******************************************************************************/ static void Sha256Transform(Sha256Type *Ctx, u8 *Data) { - u32 a,b,c,d,e,f,g,h,i,j,t1,t2,m[64]; + volatile u32 i; + u32 a,b,c,d,e,f,g,h,j,t1,t2,m[64]; for (i=0,j=0; i < 16; ++i, j += 4) m[i] = (Data[j] << 24) | (Data[j+1] << 16) | (Data[j+2] << 8) | (Data[j+3]); @@ -195,7 +197,7 @@ static void Sha256Init(Sha256Type *Ctx) ******************************************************************************/ static void Sha256Update(Sha256Type *Ctx, const u8 *Data, u32 Len) { - u32 i; + volatile u32 i; for (i=0; i < Len; ++i) { Ctx->data[Ctx->datalen] = Data[i]; @@ -223,7 +225,7 @@ static void Sha256Update(Sha256Type *Ctx, const u8 *Data, u32 Len) ******************************************************************************/ static void Sha256Final(Sha256Type *Ctx, u8 *Hash) { - u32 i; + volatile u32 i; i = Ctx->datalen; diff --git a/hdmi/phy-xilinx-vphy/xv_hdmic.c b/hdmi/phy-xilinx-vphy/xv_hdmic.c index 322db33..5c332b5 100644 --- a/hdmi/phy-xilinx-vphy/xv_hdmic.c +++ b/hdmi/phy-xilinx-vphy/xv_hdmic.c @@ -55,6 +55,15 @@ const XHdmiC_VicTable VicTable[VICTABLE_SIZE] = { {XVIDC_VM_1440x480_60_I, 6}, /* Vic 6 */ {XVIDC_VM_1440x480_60_I, 7}, /* Vic 7 */ + {XVIDC_VM_1440x240_60_P, 8}, /* Vic 8 */ + {XVIDC_VM_1440x240_60_P, 9}, /* Vic 9 */ + {XVIDC_VM_2880x480_60_I, 10}, /* Vic 10 */ + {XVIDC_VM_2880x480_60_I, 11}, /* Vic 11 */ + {XVIDC_VM_2880x240_60_P, 12}, /* Vic 12 */ + {XVIDC_VM_2880x240_60_P, 13}, /* Vic 13 */ + {XVIDC_VM_1440x480_60_P, 14}, /* Vic 14 */ + {XVIDC_VM_1440x480_60_P, 15}, /* Vic 15 */ + {XVIDC_VM_1920x1080_60_P, 16}, /* Vic 16 */ {XVIDC_VM_720x576_50_P, 17}, /* Vic 17 */ {XVIDC_VM_720x576_50_P, 18}, /* Vic 18 */ @@ -63,6 +72,48 @@ const XHdmiC_VicTable VicTable[VICTABLE_SIZE] = { {XVIDC_VM_1440x576_50_I, 21}, /* Vic 21 */ {XVIDC_VM_1440x576_50_I, 22}, /* Vic 22 */ + {XVIDC_VM_1440x288_50_P, 23}, /* Vic 23 */ + {XVIDC_VM_1440x288_50_P, 24}, /* Vic 24 */ + {XVIDC_VM_2880x576_50_I, 25}, /* Vic 25 */ + {XVIDC_VM_2880x576_50_I, 26}, /* Vic 26 */ + {XVIDC_VM_2880x288_50_P, 27}, /* Vic 27 */ + {XVIDC_VM_2880x288_50_P, 28}, /* Vic 28 */ + {XVIDC_VM_1440x576_50_P, 29}, /* Vic 29 */ + {XVIDC_VM_1440x576_50_P, 30}, /* Vic 30 */ + {XVIDC_VM_1920x1080_50_P, 31}, /* Vic 31 */ + {XVIDC_VM_1920x1080_24_P, 32}, /* Vic 32 */ + {XVIDC_VM_1920x1080_25_P, 33}, /* Vic 33 */ + {XVIDC_VM_1920x1080_30_P, 34}, /* Vic 34 */ + {XVIDC_VM_2880x480_60_P, 35}, /* Vic 35 */ + {XVIDC_VM_2880x480_60_P, 36}, /* Vic 36 */ + {XVIDC_VM_2880x576_50_P, 37}, /* Vic 37 */ + {XVIDC_VM_2880x576_50_P, 38}, /* Vic 38 */ + {XVIDC_VM_1920x1080_100_I, 40}, /* Vic 40 */ + {XVIDC_VM_1280x720_100_P, 41}, /* Vic 41 */ + {XVIDC_VM_720x576_100_P, 42}, /* Vic 42 */ + {XVIDC_VM_720x576_100_P, 43}, /* Vic 43 */ + {XVIDC_VM_1440x576_100_I, 44}, /* Vic 44 */ + {XVIDC_VM_1440x576_100_I, 45}, /* Vic 45 */ + {XVIDC_VM_1920x1080_120_I, 46}, /* Vic 46 */ + {XVIDC_VM_1280x720_120_P, 47}, /* Vic 47 */ + {XVIDC_VM_720x480_120_P, 48}, /* Vic 48 */ + {XVIDC_VM_720x480_120_P, 49}, /* Vic 49 */ + {XVIDC_VM_1440x480_120_I, 50}, /* Vic 50 */ + {XVIDC_VM_1440x480_120_I, 51}, /* Vic 51 */ + {XVIDC_VM_720x576_200_P, 52}, /* Vic 52 */ + {XVIDC_VM_720x576_200_P, 53}, /* Vic 53 */ + {XVIDC_VM_1440x576_200_I, 54}, /* Vic 54 */ + {XVIDC_VM_1440x576_200_I, 55}, /* Vic 55 */ + {XVIDC_VM_720x480_240_P, 56}, /* Vic 56 */ + {XVIDC_VM_720x480_240_P, 57}, /* Vic 57 */ + {XVIDC_VM_1440x480_240_I, 58}, /* Vic 58 */ + {XVIDC_VM_1440x480_240_I, 59}, /* Vic 59 */ + {XVIDC_VM_1280x720_24_P, 60}, /* Vic 60 */ + {XVIDC_VM_1280x720_25_P, 61}, /* Vic 61 */ + {XVIDC_VM_1280x720_30_P, 62}, /* Vic 62 */ + {XVIDC_VM_1920x1080_120_P, 63}, /* Vic 63 */ + {XVIDC_VM_1920x1080_100_P, 64}, /* Vic 64 */ + /* 1280 x 720 */ {XVIDC_VM_1280x720_24_P, 65}, /* Vic 65 */ {XVIDC_VM_1280x720_25_P, 66}, /* Vic 66 */ @@ -73,18 +124,22 @@ const XHdmiC_VicTable VicTable[VICTABLE_SIZE] = { {XVIDC_VM_1280x720_120_P, 71}, /* Vic 71 */ /* 1680 x 720 */ + {XVIDC_VM_1680x720_24_P, 79}, /* Vic 82 */ + {XVIDC_VM_1680x720_25_P, 80}, /* Vic 82 */ + {XVIDC_VM_1680x720_30_P, 81}, /* Vic 82 */ {XVIDC_VM_1680x720_50_P, 82}, /* Vic 82 */ {XVIDC_VM_1680x720_60_P, 83}, /* Vic 83 */ {XVIDC_VM_1680x720_100_P, 84}, /* Vic 84 */ {XVIDC_VM_1680x720_120_P, 85}, /* Vic 85 */ /* 1920 x 1080 */ - {XVIDC_VM_1920x1080_24_P, 32}, /* Vic 32 */ - {XVIDC_VM_1920x1080_25_P, 33}, /* Vic 33 */ - {XVIDC_VM_1920x1080_30_P, 34}, /* Vic 34 */ - {XVIDC_VM_1920x1080_50_P, 31}, /* Vic 31 */ - {XVIDC_VM_1920x1080_100_P, 64}, /* Vic 64 */ - {XVIDC_VM_1920x1080_120_P, 63}, /* Vic 63 */ + {XVIDC_VM_1920x1080_24_P, 72}, /* Vic 32 */ + {XVIDC_VM_1920x1080_25_P, 73}, /* Vic 33 */ + {XVIDC_VM_1920x1080_30_P, 74}, /* Vic 34 */ + {XVIDC_VM_1920x1080_50_P, 75}, /* Vic 75 */ + {XVIDC_VM_1920x1080_60_P, 76}, /* Vic 76 */ + {XVIDC_VM_1920x1080_100_P, 77}, /* Vic 77 */ + {XVIDC_VM_1920x1080_120_P, 78}, /* Vic 78 */ /* 2560 x 1080 */ {XVIDC_VM_2560x1080_24_P, 86}, /* Vic 86 */ @@ -513,7 +568,6 @@ XHdmiC_SamplingFrequencyVal } /*************************** Function Definitions *****************************/ - /** * * This function retrieves the Auxiliary Video Information Info Frame. @@ -658,6 +712,8 @@ XHdmiC_Aux XV_HdmiC_AVIIF_GeneratePacket(XHdmiC_AVI_InfoFrame *infoFramePtr) u8 Crc; XHdmiC_Aux aux; + (void)memset((void *)&aux, 0, sizeof(XHdmiC_Aux)); + /* Header, Packet type*/ aux.Header.Byte[0] = AUX_AVI_INFOFRAME_TYPE; @@ -767,6 +823,8 @@ XHdmiC_Aux XV_HdmiC_AudioIF_GeneratePacket(XHdmiC_AudioInfoFrame *AudioInfoFrame u8 Crc; XHdmiC_Aux aux; + (void)memset((void *)&aux, 0, sizeof(XHdmiC_Aux)); + /* Header, Packet Type */ aux.Header.Byte[0] = AUX_AUDIO_INFOFRAME_TYPE; diff --git a/hdmi/phy-xilinx-vphy/xv_hdmic.h b/hdmi/phy-xilinx-vphy/xv_hdmic.h index b6c0b14..f24025c 100644 --- a/hdmi/phy-xilinx-vphy/xv_hdmic.h +++ b/hdmi/phy-xilinx-vphy/xv_hdmic.h @@ -50,7 +50,7 @@ extern "C" { #include "xil_assert.h" /************************** Constant Definitions ******************************/ -#define VICTABLE_SIZE 73 +#define VICTABLE_SIZE 126 #define AUX_VSIF_TYPE 0x81 #define AUX_AVI_INFOFRAME_TYPE 0x82 #define AUX_GENERAL_CONTROL_PACKET_TYPE 0x3 @@ -302,6 +302,7 @@ typedef enum { R_444_444, /* 8 Gbps */ R_555_556, /* 10 Gbps */ R_666_667, /* 12 Gbps */ + XHDMIC_FRLCHARRATE_SIZE, } XHdmiC_FRLCharRate; /** @@ -429,6 +430,7 @@ XHdmiC_SamplingFrequency XHdmiC_GetAudIFSampFreq (XHdmiC_SamplingFrequencyVal AudSampFreqVal); XHdmiC_SamplingFrequencyVal XHdmiC_GetAudSampFreqVal(XHdmiC_SamplingFrequency AudSampFreqVal); + #ifdef __cplusplus } #endif diff --git a/hdmi/phy-xilinx-vphy/xv_hdmic_vsif.c b/hdmi/phy-xilinx-vphy/xv_hdmic_vsif.c index 8ed7e1a..eedc8f0 100644 --- a/hdmi/phy-xilinx-vphy/xv_hdmic_vsif.c +++ b/hdmi/phy-xilinx-vphy/xv_hdmic_vsif.c @@ -460,16 +460,13 @@ XHdmiC_Aux XV_HdmiC_VSIF_GeneratePacket(XHdmiC_VSIF *VSIFPtr) u8 ByteCount = 0; u8 Crc = 0; XHdmiC_Aux Aux; -// XHdmiC_Aux *AuxPtr; + + (void)memset((void *)&Aux, 0, sizeof(XHdmiC_Aux)); XHdmiC_3D_Struct_Field Format; XHdmiC_3D_Sampling_Method SampMethod; XHdmiC_3D_Sampling_Position SampPos; - /* Verify arguments */ -// Xil_AssertNonvoid(VSIFPtr != NULL); -// Xil_AssertNonvoid(AuxPtr != NULL); - /* Header, Packet type*/ Aux.Header.Byte[0] = AUX_VSIF_TYPE; diff --git a/hdmi/phy-xilinx-vphy/xvidc.c b/hdmi/phy-xilinx-vphy/xvidc.c index 663672c..f6b0b43 100644 --- a/hdmi/phy-xilinx-vphy/xvidc.c +++ b/hdmi/phy-xilinx-vphy/xvidc.c @@ -835,6 +835,7 @@ const char *XVidC_GetColorFormatStr(XVidC_ColorFormat ColorFormatId) case XVIDC_CSF_MEM_BGR8: return ("BGR8"); case XVIDC_CSF_YCBCR_422: return ("YCBCR_422"); case XVIDC_CSF_YCBCR_420: return ("YCBCR_420"); + case XVIDC_CSF_YCBCR_444: return ("YCBCR_444"); case XVIDC_CSF_MEM_RGBX12: return ("RGBX12"); case XVIDC_CSF_MEM_RGB16: return ("RGB16"); case XVIDC_CSF_MEM_YUVX12: return ("YUVX12"); @@ -1268,7 +1269,7 @@ int XVidC_ShowStreamInfo(const XVidC_VideoStream *Stream, char *buff, int buff_s "\tResolution: %dx%d [Custom Mode]\r\n", Stream->Timing.HActive, Stream->Timing.VActive); strSize += scnprintf(buff+strSize, buff_size-strSize, - "\tPixel Clock: %d\r\n", + "\tPixel Clock: %lld\r\n", XVidC_GetPixelClockHzByHVFr( Stream->Timing.HTotal, Stream->Timing.F0PVTotal, @@ -1282,7 +1283,7 @@ int XVidC_ShowStreamInfo(const XVidC_VideoStream *Stream, char *buff, int buff_s "\tResolution: %s\r\n", XVidC_GetVideoModeStr(Stream->VmId)); strSize += scnprintf(buff+strSize, buff_size-strSize, - "\tPixel Clock: %d\r\n", + "\tPixel Clock: %lld\r\n", XVidC_GetPixelClockHzByVmId(Stream->VmId)); } diff --git a/hdmi/phy-xilinx-vphy/xvidc.h b/hdmi/phy-xilinx-vphy/xvidc.h index aa6c599..58d2bda 100644 --- a/hdmi/phy-xilinx-vphy/xvidc.h +++ b/hdmi/phy-xilinx-vphy/xvidc.h @@ -110,6 +110,8 @@ typedef enum { XVIDC_VM_2048x1080_96_I, XVIDC_VM_2048x1080_100_I, XVIDC_VM_2048x1080_120_I, + XVIDC_VM_2880x480_60_I, + XVIDC_VM_2880x576_50_I, /* Progressive modes. */ @@ -172,6 +174,9 @@ typedef enum { XVIDC_VM_1400x1050_85_P, XVIDC_VM_1400x1050_120_P_RB, XVIDC_VM_1440x240_60_P, + XVIDC_VM_1440x288_50_P, + XVIDC_VM_1440x480_60_P, + XVIDC_VM_1440x576_50_P, XVIDC_VM_1440x900_60_P, XVIDC_VM_1440x900_60_P_RB, XVIDC_VM_1440x900_75_P, @@ -183,6 +188,9 @@ typedef enum { XVIDC_VM_1600x1200_75_P, XVIDC_VM_1600x1200_85_P, XVIDC_VM_1600x1200_120_P_RB, + XVIDC_VM_1680x720_24_P, + XVIDC_VM_1680x720_25_P, + XVIDC_VM_1680x720_30_P, XVIDC_VM_1680x720_50_P, XVIDC_VM_1680x720_60_P, XVIDC_VM_1680x720_100_P, @@ -237,15 +245,19 @@ typedef enum { XVIDC_VM_2560x1600_75_P, XVIDC_VM_2560x1600_85_P, XVIDC_VM_2560x1600_120_P_RB, + XVIDC_VM_2880x240_60_P, + XVIDC_VM_2880x288_50_P, + XVIDC_VM_2880x480_60_P, + XVIDC_VM_2880x576_50_P, XVIDC_VM_3840x2160_24_P, XVIDC_VM_3840x2160_25_P, XVIDC_VM_3840x2160_30_P, XVIDC_VM_3840x2160_48_P, XVIDC_VM_3840x2160_50_P, XVIDC_VM_3840x2160_60_P, + XVIDC_VM_3840x2160_60_P_RB, XVIDC_VM_3840x2160_100_P, XVIDC_VM_3840x2160_120_P, - XVIDC_VM_3840x2160_60_P_RB, XVIDC_VM_4096x2160_24_P, XVIDC_VM_4096x2160_25_P, XVIDC_VM_4096x2160_30_P, @@ -438,7 +450,7 @@ typedef enum { /* Streaming formats with components re-ordered */ XVIDC_CSF_YCBCR_422 = 64, XVIDC_CSF_YCBCR_420, - + XVIDC_CSF_YCBCR_444, XVIDC_CSF_NUM_SUPPORTED, // includes the reserved slots XVIDC_CSF_UNKNOWN, diff --git a/hdmi/phy-xilinx-vphy/xvidc_timings_table.c b/hdmi/phy-xilinx-vphy/xvidc_timings_table.c index 314307b..40de604 100644 --- a/hdmi/phy-xilinx-vphy/xvidc_timings_table.c +++ b/hdmi/phy-xilinx-vphy/xvidc_timings_table.c @@ -144,7 +144,12 @@ const XVidC_VideoTimingMode XVidC_VideoTimingModes[XVIDC_VM_NUM_SUPPORTED] = { XVIDC_VM_2048x1080_120_I, "2048x1080@120Hz (I)", XVIDC_FR_120HZ, {2048, 66, 20, 66, 2200, 1, 540, 2, 5, 15, 562, 3, 5, 15, 563, 1} }, - + { XVIDC_VM_2880x480_60_I, "2880x480@60Hz (I)", XVIDC_FR_60HZ, + {2880, 76, 248, 228, 3432, 0, + 240, 4, 3, 15, 262, 5, 3, 15, 263, 0} }, + {XVIDC_VM_2880x576_50_I, "2880x576@50Hz (I)", XVIDC_FR_50HZ, + {2880, 48, 252, 276, 3456, 0, + 576, 2, 3, 19, 312, 2, 3, 19, 313, 0} }, /* Progressive modes. */ { XVIDC_VM_640x350_85_P, "640x350@85Hz", XVIDC_FR_85HZ, @@ -323,7 +328,16 @@ const XVidC_VideoTimingMode XVidC_VideoTimingModes[XVIDC_VM_NUM_SUPPORTED] = 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} }, + 240, 4, 3, 15, 262, 0, 0, 0, 0, 1} }, + {XVIDC_VM_1440x288_50_P, "1440x288@50Hz", XVIDC_FR_50HZ, + {1440, 24, 126, 138, 1728, 0, + 288, 3, 3, 19, 313, 0, 0, 0, 0, 0} }, + { XVIDC_VM_1440x480_60_P, "1440x240@60Hz", XVIDC_FR_60HZ, + {1440, 32, 124, 120, 1716, 0, + 480, 9, 6, 30, 525, 0, 0, 0, 0, 0} }, + {XVIDC_VM_1440x576_50_P, "1440x576@50Hz", XVIDC_FR_50HZ, + {1440, 24, 128, 136, 1728, 0, + 576, 5, 5, 39, 625, 0, 0, 0, 0, 0} }, { 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} }, @@ -357,6 +371,15 @@ const XVidC_VideoTimingMode XVidC_VideoTimingModes[XVIDC_VM_NUM_SUPPORTED] = { 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_24_P, "1680x720@24Hz", XVIDC_FR_24HZ, + {1680, 1360, 40, 220, 3300, 1, + 720, 5, 5, 20, 750, 0, 0, 0, 0, 0} }, + {XVIDC_VM_1680x720_25_P, "1680x720@25Hz", XVIDC_FR_25HZ, + {1680, 1228, 40, 220, 3168, 1, + 720, 5, 5, 20, 750, 0, 0, 0, 0, 0} }, + {XVIDC_VM_1680x720_30_P, "1680x720@30Hz", XVIDC_FR_30HZ, + {1680, 700, 40, 220, 2640, 1, + 720, 5, 5, 20, 750, 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} }, @@ -519,6 +542,18 @@ const XVidC_VideoTimingMode XVidC_VideoTimingModes[XVIDC_VM_NUM_SUPPORTED] = { 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_2880x240_60_P, "2880x240@60Hz", XVIDC_FR_60HZ, + {2880, 76, 248, 228, 3432, 0, + 240, 14, 3, 4, 262, 0, 0, 0, 0, 1} }, + { XVIDC_VM_2880x288_50_P, "2880x288@50Hz", XVIDC_FR_50HZ, + {2880, 48, 252, 276, 3456, 0, + 288, 3, 3, 19, 313, 0, 0, 0, 0, 0} }, + {XVIDC_VM_2880x480_60_P, "2880x480@60Hz", XVIDC_FR_60HZ, + {2880, 64, 248, 240, 3432, 0, + 480, 9, 6, 30, 525, 0, 0, 0, 0, 0} }, + {XVIDC_VM_2880x576_50_P, "2880x576@50Hz", XVIDC_FR_50HZ, + {2880, 48, 256, 272, 3456, 0, + 576, 5, 5, 39, 625, 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} }, @@ -537,15 +572,15 @@ const XVidC_VideoTimingMode XVidC_VideoTimingModes[XVIDC_VM_NUM_SUPPORTED] = { 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_3840x2160_60_P_RB, "3840x2160@60Hz (RB)", XVIDC_FR_60HZ, + {3840, 48, 32, 80, 4000, 1, + 2160, 3, 5, 54, 2222, 0, 0, 0, 0, 0} }, { XVIDC_VM_3840x2160_100_P, "3840x2160@100Hz", XVIDC_FR_100HZ, {3840, 1056, 88, 296, 5280, 1, 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, { XVIDC_VM_3840x2160_120_P, "3840x2160@120Hz", XVIDC_FR_120HZ, {3840, 176, 88, 296, 4400, 1, 2160, 8, 10, 72, 2250, 0, 0, 0, 0, 1} }, - { XVIDC_VM_3840x2160_60_P_RB, "3840x2160@60Hz (RB)", XVIDC_FR_60HZ, - {3840, 48, 32, 80, 4000, 1, - 2160, 3, 5, 54, 2222, 0, 0, 0, 0, 0} }, { 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} }, diff --git a/hdmi/xilinx-hdmi-rx/xv_hdmirxss_log.c b/hdmi/xilinx-hdmi-rx/xv_hdmirxss_log.c index 4318937..17eb98f 100644 --- a/hdmi/xilinx-hdmi-rx/xv_hdmirxss_log.c +++ b/hdmi/xilinx-hdmi-rx/xv_hdmirxss_log.c @@ -309,6 +309,7 @@ int XV_HdmiRxSs_LogShow(XV_HdmiRxSs *InstancePtr, char *buff, int buff_size) case (XV_HDMIRXSS_LOG_EVT_VICERROR): strSize += scnprintf(buff+strSize, buff_size-strSize, "Vic and video timing mismatch\r\n"); + break; default: strSize += scnprintf(buff+strSize, buff_size-strSize, "Unknown event: %i\r\n", Evt); diff --git a/hdmi/xilinx-hdmi-tx/xvtc_intr.c b/hdmi/xilinx-hdmi-tx/xvtc_intr.c index cc66ccc..b425513 100644 --- a/hdmi/xilinx-hdmi-tx/xvtc_intr.c +++ b/hdmi/xilinx-hdmi-tx/xvtc_intr.c @@ -102,6 +102,7 @@ * "XTEST_FAILED" -> "XST_FAILURE" * "XTEST_PASSED" -> "XST_SUCCESS" * 6.1 adk 08/23/14 Alligned doxygen tags. +* 8.1 pg 04/03/20 Fixed interrupt handler issue * * ******************************************************************************/ @@ -166,7 +167,7 @@ void XVtc_IntrHandler(void *InstancePtr) XVtc_IntrClear(XVtcPtr, PendingIntr); /* Spurious interrupt has happened */ - if (PendingIntr | XVTC_IXR_SPURIOUS_INTR_MASK) { + if (PendingIntr & XVTC_IXR_SPURIOUS_INTR_MASK) { ErrorStatus = 0; XVtcPtr->ErrCallBack(XVtcPtr->ErrRef, ErrorStatus); return; From bb823bf1e93e31004aa915f09ac17bfc6e29d4fd Mon Sep 17 00:00:00 2001 From: Vishal Sagar Date: Tue, 31 Mar 2020 00:12:21 +0530 Subject: [PATCH 42/46] dtbindings: vphy: Add support for Versal Add support for Versal HDMI GT controller PHY. This adds two new required parameters for Rx and Tx FRL reference clock. The compatible string is also updated for Versal. Signed-off-by: Vishal Sagar --- .../devicetree/bindings/xlnx,vphy.txt | 51 ++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/xlnx,vphy.txt b/Documentation/devicetree/bindings/xlnx,vphy.txt index 58542c6..4fd6adb 100644 --- a/Documentation/devicetree/bindings/xlnx,vphy.txt +++ b/Documentation/devicetree/bindings/xlnx,vphy.txt @@ -2,6 +2,7 @@ Xilinx VPHY (Staging) The Xilinx Video PHY is a high-level video-specific wrapper around different versions of the GT PHY. Its driver is phy/phy-xilinx-vphy.c +This now supports HDMI on Versal too. It offers the PHY driver interface as well as higher-level video specific support functions. @@ -12,6 +13,7 @@ Its current users are Xilinx HDMI RX/TX SS. Required Properties: - compatible: Should be "xlnx,vid-phy-controller-2.2". + For Versal it should be "xlnx,hdmi-gt-controller-1.0". - reg: Base address and size of the IP core. - interrupts: Interrupt number. - interrupts-parent: phandle for interrupt controller. @@ -21,7 +23,7 @@ Required Properties: NOTE: Auto generated DT is providing all the clock names and handles reuired by the IP. NOTE: The identification string, "vid_phy_axi4lite_aclk", is always - required. + required in non Versal mode. In Versal, the string is "axi4lite_aclk". NOTE: The identification string "dru-clk" is always required if NI DRU (nidru parameter) is selected for phy. This needs to be explicitly added in the list of clock-names and its phandle in clocks @@ -29,7 +31,7 @@ Required Properties: - xlnx,input-pixels-per-clock: IP configuration for samples/clk (1, 2, 4) Note: Only 2 is supported at this time - - xlnx,nidru: flag to indicate if DRU is present + - xlnx,nidru: flag to indicate if DRU is present. - xlnx,nidru-refclk-sel: DRU clock selector - xlnx,rx-no-of-channels: Required Rx channels for registered protocol - xlnx,rx-pll-selection: Rx pll selector @@ -47,6 +49,8 @@ Required Properties: - xlnx,use-gt-ch4-hdmi: Enables the usage of 4th TX GT channel. (Default value is 0. If selected in GUI, then value will be 1) + - xlnx,rx-frl-refclk-sel: Reference clock for Rx in FRL mode in Versal only + - xlnx,tx-frl-refclk-sel: Reference clock for Tx in FRL mode in Versal only - lane: (port (child) nodes) lane0: @@ -104,3 +108,46 @@ sharing VPHYs, and are therefore subject to change.) #phy-cells = <4>; }; }; + +==Example for Versal== + + hdmi_gt_controller_1: hdmi_gt_controller@a4080000 { + clock-names = "gt_refclk1_odiv2", "sb_aclk", "axi4lite_aclk", "apb_clk", "dru-clk"; + clocks = <&misc_clk_0>, <&versal_clk 65>, <&versal_clk 65>, <&versal_clk 65>, <&si570_2>; + compatible = "xlnx,hdmi-gt-controller-1.0"; + interrupt-names = "irq"; + interrupt-parent = <&gic>; + interrupts = <0 84 4>; + reg = <0x0 0xa4080000 0x0 0x10000>; + xlnx,err-irq-en = <0>; + xlnx,hdmi-fast-switch = <0>; + xlnx,input-pixels-per-clock = <2>; + xlnx,nidru = <1>; + xlnx,nidru-refclk-sel = <2>; + xlnx,rx-frl-refclk-sel = <2>; + xlnx,rx-no-of-channels = <4>; + xlnx,rx-pll-selection = <8>; + xlnx,rx-protocol = <3>; + xlnx,rx-refclk-sel = <0>; + xlnx,transceiver-type = <7>; + xlnx,transceiver-width = <2>; + xlnx,tx-buffer-bypass = <1>; + xlnx,tx-frl-refclk-sel = <2>; + xlnx,tx-no-of-channels = <4>; + xlnx,tx-pll-selection = <7>; + xlnx,tx-protocol = <1>; + xlnx,tx-refclk-sel = <1>; + xlnx,use-gt-ch4-hdmi = <1>; + vphy_lane0: vphy_lane@0 { + #phy-cells = <4>; + }; + vphy_lane1: vphy_lane@1 { + #phy-cells = <4>; + }; + vphy_lane2: vphy_lane@2 { + #phy-cells = <4>; + }; + vphy_lane3: vphy_lane@3 { + #phy-cells = <4>; + }; + }; From 6cf99ed4bf16ded41863dad76244dd2e15160fa7 Mon Sep 17 00:00:00 2001 From: Vishal Sagar Date: Tue, 31 Mar 2020 00:17:23 +0530 Subject: [PATCH 43/46] hdmi: Add support for Versal PHY This patch adds support for the Versal HDMI GT controller PHY in the core driver area and the wrapper drivers. To ensure that there is only driver common between Versal and non-Versal platforms, a flag "isvphy" is introduced in the wrapper drivers. Signed-off-by: Vishal Sagar --- hdmi/Makefile | 14 + hdmi/include/linux/phy/phy-vphy.h | 3 +- hdmi/phy-vphy.c | 354 ++- hdmi/phy-xilinx-vphy/xhdmiphy1.c | 1381 ++++++++++ hdmi/phy-xilinx-vphy/xhdmiphy1.h | 1028 +++++++ hdmi/phy-xilinx-vphy/xhdmiphy1_gt.h | 127 + hdmi/phy-xilinx-vphy/xhdmiphy1_gtye5.c | 620 +++++ hdmi/phy-xilinx-vphy/xhdmiphy1_hdmi.c | 2865 ++++++++++++++++++++ hdmi/phy-xilinx-vphy/xhdmiphy1_hdmi.h | 199 ++ hdmi/phy-xilinx-vphy/xhdmiphy1_hdmi_intr.c | 1314 +++++++++ hdmi/phy-xilinx-vphy/xhdmiphy1_hw.h | 705 +++++ hdmi/phy-xilinx-vphy/xhdmiphy1_i.c | 1875 +++++++++++++ hdmi/phy-xilinx-vphy/xhdmiphy1_i.h | 171 ++ hdmi/phy-xilinx-vphy/xhdmiphy1_intr.c | 312 +++ hdmi/phy-xilinx-vphy/xhdmiphy1_log.c | 608 +++++ hdmi/phy-xilinx-vphy/xhdmiphy1_mmcme5.c | 607 +++++ hdmi/phy-xilinx-vphy/xhdmiphy1_sinit.c | 83 + hdmi/xilinx-hdmirx.c | 190 +- hdmi/xilinx_drm_hdmi.c | 207 +- 19 files changed, 12511 insertions(+), 152 deletions(-) create mode 100644 hdmi/phy-xilinx-vphy/xhdmiphy1.c create mode 100644 hdmi/phy-xilinx-vphy/xhdmiphy1.h create mode 100644 hdmi/phy-xilinx-vphy/xhdmiphy1_gt.h create mode 100644 hdmi/phy-xilinx-vphy/xhdmiphy1_gtye5.c create mode 100644 hdmi/phy-xilinx-vphy/xhdmiphy1_hdmi.c create mode 100644 hdmi/phy-xilinx-vphy/xhdmiphy1_hdmi.h create mode 100644 hdmi/phy-xilinx-vphy/xhdmiphy1_hdmi_intr.c create mode 100644 hdmi/phy-xilinx-vphy/xhdmiphy1_hw.h create mode 100644 hdmi/phy-xilinx-vphy/xhdmiphy1_i.c create mode 100644 hdmi/phy-xilinx-vphy/xhdmiphy1_i.h create mode 100644 hdmi/phy-xilinx-vphy/xhdmiphy1_intr.c create mode 100644 hdmi/phy-xilinx-vphy/xhdmiphy1_log.c create mode 100644 hdmi/phy-xilinx-vphy/xhdmiphy1_mmcme5.c create mode 100644 hdmi/phy-xilinx-vphy/xhdmiphy1_sinit.c diff --git a/hdmi/Makefile b/hdmi/Makefile index d323c72..83f6f50 100644 --- a/hdmi/Makefile +++ b/hdmi/Makefile @@ -3,6 +3,7 @@ obj-m += xilinx-vphy.o xilinx-hdmi-rx.o xilinx-hdmi-tx.o # in same cases only used to check against presence, i.e. >0, actual number is not used ccflags-y := -DXPAR_XVPHY_NUM_INSTANCES=4 +ccflags-y += -DXPAR_XHDMIPHY1_NUM_INSTANCES=4 ccflags-y += -DXPAR_XV_HDMIRXSS_NUM_INSTANCES=4 ccflags-y += -DXPAR_XV_HDMITXSS_NUM_INSTANCES=4 ccflags-y += -DXPAR_XV_HDMIRX_NUM_INSTANCES=4 @@ -12,6 +13,10 @@ ccflags-y += -DXPAR_XVTC_NUM_INSTANCES=4 ccflags-y += -DXPAR_VPHY_0_TRANSCEIVER=5 ccflags-y += -DXPAR_VPHY_0_RX_PROTOCOL=1 ccflags-y += -DXPAR_VPHY_0_TX_PROTOCOL=1 +ccflags-y += -DXPAR_HDMIPHY1_0_TRANSCEIVER=7 +# Below two parameters are notused anywhere in the code +ccflags-y += -DXPAR_HDMIPHY1_0_RX_PROTOCOL=1 +ccflags-y += -DXPAR_HDMIPHY1_0_TX_PROTOCOL=1 ccflags-y += -DXPAR_XV_HDMIRX_0_DEVICE_ID=0 ccflags-y += -DXPAR_XV_HDMITX_0_DEVICE_ID=0 @@ -82,6 +87,15 @@ xilinx-vphy-objs += phy-xilinx-vphy/xvphy_hdmi_intr.o xilinx-vphy-objs += phy-xilinx-vphy/xvphy_intr.o xilinx-vphy-objs += phy-xilinx-vphy/xvphy_log.o xilinx-vphy-objs += phy-xilinx-vphy/xvphy_sinit.o +xilinx-vphy-objs += phy-xilinx-vphy/xhdmiphy1.o +xilinx-vphy-objs += phy-xilinx-vphy/xhdmiphy1_i.o +xilinx-vphy-objs += phy-xilinx-vphy/xhdmiphy1_gtye5.o +xilinx-vphy-objs += phy-xilinx-vphy/xhdmiphy1_mmcme5.o +xilinx-vphy-objs += phy-xilinx-vphy/xhdmiphy1_hdmi.o +xilinx-vphy-objs += phy-xilinx-vphy/xhdmiphy1_hdmi_intr.o +xilinx-vphy-objs += phy-xilinx-vphy/xhdmiphy1_intr.o +xilinx-vphy-objs += phy-xilinx-vphy/xhdmiphy1_log.o +xilinx-vphy-objs += phy-xilinx-vphy/xhdmiphy1_sinit.o xilinx-vphy-objs += phy-xilinx-vphy/xvidc.o xilinx-vphy-objs += phy-xilinx-vphy/xvidc_timings_table.o diff --git a/hdmi/include/linux/phy/phy-vphy.h b/hdmi/include/linux/phy/phy-vphy.h index edb4e1d..8f19725 100644 --- a/hdmi/include/linux/phy/phy-vphy.h +++ b/hdmi/include/linux/phy/phy-vphy.h @@ -20,11 +20,12 @@ /* @TODO change directory name on production release */ #include "xvphy.h" +#include "xhdmiphy1.h" struct phy; /* VPHY is built (either as module or built-in) */ -extern XVphy *xvphy_get_xvphy(struct phy *phy); +extern void *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); diff --git a/hdmi/phy-vphy.c b/hdmi/phy-vphy.c index c38093f..f903ad0 100644 --- a/hdmi/phy-vphy.c +++ b/hdmi/phy-vphy.c @@ -43,6 +43,8 @@ /* baseline driver includes */ #include "phy-xilinx-vphy/xvphy.h" #include "phy-xilinx-vphy/xvphy_i.h" +#include "phy-xilinx-vphy/xhdmiphy1.h" +#include "phy-xilinx-vphy/xhdmiphy1_i.h" /* common RX/TX */ #include "phy-xilinx-vphy/xdebug.h" @@ -61,6 +63,8 @@ #include "phy-xilinx-vphy/xv_hdmic_vsif.h" #define XVPHY_DRU_REF_CLK_HZ 156250000 +/* TODO - [Versal] - This needs to be changed for versal */ +#define XHDMIPHY1_DRU_REF_CLK_HZ 200000000 #define hdmi_mutex_lock(x) mutex_lock(x) #define hdmi_mutex_unlock(x) mutex_unlock(x) @@ -100,29 +104,36 @@ struct xvphy_dev { /* virtual remapped I/O memory */ void __iomem *iomem; int irq; - /* protects the XVphy baseline against concurrent access */ + /* protects the XVphy/XHdmiphy1 baseline against concurrent access */ struct mutex xvphy_mutex; struct xvphy_lane *lanes[4]; /* bookkeeping for the baseline subsystem driver instance */ XVphy xvphy; + XHdmiphy1 xgtphy; /* AXI Lite clock drives the clock detector */ struct clk *axi_lite_clk; /* NI-DRU clock input */ struct clk *dru_clk; + /* If Video Phy flag */ + u32 isvphy; }; /* given the (Linux) phy handle, return the xvphy */ -XVphy *xvphy_get_xvphy(struct phy *phy) +void *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; + + if (vphy_dev->isvphy) + return (void *)&vphy_dev->xvphy; + + return (void *)&vphy_dev->xgtphy; } 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 */ + * XVphy/XHdmiphy1 functions must be called with mutex acquired to prevent concurrent access + * by XVphy/XHdmiphy1 and upper-layer video protocol drivers */ void xvphy_mutex_lock(struct phy *phy) { struct xvphy_lane *vphy_lane = phy_get_drvdata(phy); @@ -159,9 +170,30 @@ EXPORT_SYMBOL_GPL(XVphy_IsBonded); EXPORT_SYMBOL_GPL(XVphy_ClkDetFreqReset); EXPORT_SYMBOL_GPL(XVphy_ClkDetGetRefClkFreqHz); -static xvphy_intr_disable(struct xvphy_dev *vphydev) +/* XHdmiphy1 functions must be called with mutex acquired to prevent concurrent access + * by XHdmiphy1 and upper-layer video protocol drivers */ +EXPORT_SYMBOL_GPL(XHdmiphy1_GetPllType); +EXPORT_SYMBOL_GPL(XHdmiphy1_IBufDsEnable); +EXPORT_SYMBOL_GPL(XHdmiphy1_SetHdmiCallback); +EXPORT_SYMBOL_GPL(XHdmiphy1_HdmiCfgCalcMmcmParam); +EXPORT_SYMBOL_GPL(XHdmiphy1_MmcmStart); +EXPORT_SYMBOL_GPL(XHdmiphy1_HdmiDebugInfo); +EXPORT_SYMBOL_GPL(XHdmiphy1_RegisterDebug); +EXPORT_SYMBOL_GPL(XHdmiphy1_LogShow); +EXPORT_SYMBOL_GPL(XHdmiphy1_DruGetRefClkFreqHz); +EXPORT_SYMBOL_GPL(XHdmiphy1_GetLineRateHz); + +/* exclusively required by TX */ +EXPORT_SYMBOL_GPL(XHdmiphy1_Clkout1OBufTdsEnable); +EXPORT_SYMBOL_GPL(XHdmiphy1_SetHdmiTxParam); +//EXPORT_SYMBOL_GPL(XHdmiphy1_IsBonded); +EXPORT_SYMBOL_GPL(XHdmiphy1_ClkDetFreqReset); +EXPORT_SYMBOL_GPL(XHdmiphy1_ClkDetGetRefClkFreqHz); + +static void xvphy_intr_disable(struct xvphy_dev *vphydev) { - XVphy_IntrDisable(&vphydev->xvphy, XVPHY_INTR_HANDLER_TYPE_TXRESET_DONE | + if (vphydev->isvphy) + 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 | @@ -173,22 +205,49 @@ static xvphy_intr_disable(struct xvphy_dev *vphydev) XVPHY_INTR_HANDLER_TYPE_RX_MMCM_LOCK_CHANGE | XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT | XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); + else + XHdmiphy1_IntrDisable(&vphydev->xgtphy, XHDMIPHY1_INTR_HANDLER_TYPE_TXRESET_DONE | + XHDMIPHY1_INTR_HANDLER_TYPE_RXRESET_DONE | + XHDMIPHY1_INTR_HANDLER_TYPE_LCPLL_LOCK | + XHDMIPHY1_INTR_HANDLER_TYPE_RPLL_LOCK | + XHDMIPHY1_INTR_HANDLER_TYPE_TX_GPO_RISING_EDGE | + XHDMIPHY1_INTR_HANDLER_TYPE_RX_GPO_RISING_EDGE | + XHDMIPHY1_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE | + XHDMIPHY1_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE | + XHDMIPHY1_INTR_HANDLER_TYPE_TX_MMCM_LOCK_CHANGE | + XHDMIPHY1_INTR_HANDLER_TYPE_RX_MMCM_LOCK_CHANGE | + XHDMIPHY1_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT | + XHDMIPHY1_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); } -static xvphy_intr_enable(struct xvphy_dev *vphydev) +static void xvphy_intr_enable(struct xvphy_dev *vphydev) { - 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_MMCM_LOCK_CHANGE | - XVPHY_INTR_HANDLER_TYPE_RX_MMCM_LOCK_CHANGE | - XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT | - XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); + if (vphydev->isvphy) + 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_MMCM_LOCK_CHANGE | + XVPHY_INTR_HANDLER_TYPE_RX_MMCM_LOCK_CHANGE | + XVPHY_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT | + XVPHY_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); + else + XHdmiphy1_IntrEnable(&vphydev->xgtphy, XHDMIPHY1_INTR_HANDLER_TYPE_TXRESET_DONE | + XHDMIPHY1_INTR_HANDLER_TYPE_RXRESET_DONE | + XHDMIPHY1_INTR_HANDLER_TYPE_LCPLL_LOCK | + XHDMIPHY1_INTR_HANDLER_TYPE_RPLL_LOCK | + XHDMIPHY1_INTR_HANDLER_TYPE_TX_GPO_RISING_EDGE | + XHDMIPHY1_INTR_HANDLER_TYPE_RX_GPO_RISING_EDGE | + XHDMIPHY1_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE | + XHDMIPHY1_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE | + XHDMIPHY1_INTR_HANDLER_TYPE_TX_MMCM_LOCK_CHANGE | + XHDMIPHY1_INTR_HANDLER_TYPE_RX_MMCM_LOCK_CHANGE | + XHDMIPHY1_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT | + XHDMIPHY1_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); } static irqreturn_t xvphy_irq_handler(int irq, void *dev_id) @@ -217,11 +276,19 @@ static irqreturn_t xvphy_irq_thread(int irq, void *dev_id) /* call baremetal interrupt handler with mutex locked */ hdmi_mutex_lock(&vphydev->xvphy_mutex); - IntrStatus = XVphy_ReadReg(vphydev->xvphy.Config.BaseAddr, XVPHY_INTR_STS_REG); - dev_dbg(vphydev->dev,"XVphy IntrStatus = 0x%08x\n", IntrStatus); + if (vphydev->isvphy) { + IntrStatus = XVphy_ReadReg(vphydev->xvphy.Config.BaseAddr, XVPHY_INTR_STS_REG); + dev_dbg(vphydev->dev,"XVphy IntrStatus = 0x%08x\n", IntrStatus); + } else { + IntrStatus = XHdmiphy1_ReadReg(vphydev->xgtphy.Config.BaseAddr, XHDMIPHY1_INTR_STS_REG); + dev_dbg(vphydev->dev,"XHdmiphy1 IntrStatus = 0x%08x\n", IntrStatus); + } /* handle pending interrupts */ - XVphy_InterruptHandler(&vphydev->xvphy); + if (vphydev->isvphy) + XVphy_InterruptHandler(&vphydev->xvphy); + else + XHdmiphy1_InterruptHandler(&vphydev->xgtphy); hdmi_mutex_unlock(&vphydev->xvphy_mutex); /* Enable interrupt requesting in the VPHY */ @@ -238,7 +305,10 @@ static irqreturn_t xvphy_irq_thread(int irq, void *dev_id) */ static int xvphy_phy_init(struct phy *phy) { - printk(KERN_INFO "xvphy_phy_init(%p).\n", phy); + struct xvphy_lane *vphy_lane = phy_get_drvdata(phy); + struct xvphy_dev *vphy_dev = vphy_lane->data; + + dev_dbg(vphy_dev->dev, "xvphy_phy_init(%p).\n", phy); return 0; } @@ -296,6 +366,7 @@ static struct phy *xvphy_xlate(struct device *dev, /* Local Global table for phy instance(s) configuration settings */ XVphy_Config XVphy_ConfigTable[XPAR_XVPHY_NUM_INSTANCES]; +XHdmiphy1_Config XHdmiphy1_ConfigTable[XPAR_XHDMIPHY1_NUM_INSTANCES]; static struct phy_ops xvphy_phyops = { .init = xvphy_phy_init, @@ -306,97 +377,162 @@ static int instance = 0; /* TX uses [1, 127], RX uses [128, 254] and VPHY uses [256, ...]. Note that 255 is used for not-present. */ #define VPHY_DEVICE_ID_BASE 256 -static int vphy_parse_of(struct xvphy_dev *vphydev, XVphy_Config *c) +static int vphy_parse_of(struct xvphy_dev *vphydev, void *c) { struct device *dev = vphydev->dev; struct device_node *node = dev->of_node; int rc; u32 val; bool has_err_irq; + XVphy_Config *vphycfg = (XVphy_Config *)c; + XHdmiphy1_Config *xgtphycfg = (XHdmiphy1_Config *)c; rc = of_property_read_u32(node, "xlnx,transceiver-type", &val); if (rc < 0) goto error_dt; - c->XcvrType = val; + if (vphydev->isvphy) + vphycfg->XcvrType = val; + else + xgtphycfg->XcvrType = val; rc = of_property_read_u32(node, "xlnx,tx-buffer-bypass", &val); if (rc < 0) goto error_dt; - c->TxBufferBypass = val; + if (vphydev->isvphy) + vphycfg->TxBufferBypass = val; + else + xgtphycfg->TxBufferBypass = val; rc = of_property_read_u32(node, "xlnx,input-pixels-per-clock", &val); if (rc < 0) goto error_dt; - c->Ppc = val; + if (vphydev->isvphy) + vphycfg->Ppc = val; + else + xgtphycfg->Ppc = val; rc = of_property_read_u32(node, "xlnx,nidru", &val); if (rc < 0) goto error_dt; - c->DruIsPresent = val; + if (vphydev->isvphy) + vphycfg->DruIsPresent = val; + else + xgtphycfg->DruIsPresent = val; rc = of_property_read_u32(node, "xlnx,nidru-refclk-sel", &val); if (rc < 0) goto error_dt; - c->DruRefClkSel = val; + if (vphydev->isvphy) + vphycfg->DruRefClkSel = val; + else + xgtphycfg->DruRefClkSel = val; rc = of_property_read_u32(node, "xlnx,rx-no-of-channels", &val); if (rc < 0) goto error_dt; - c->RxChannels = val; + if (vphydev->isvphy) + vphycfg->RxChannels = val; + else + xgtphycfg->RxChannels = val; rc = of_property_read_u32(node, "xlnx,tx-no-of-channels", &val); if (rc < 0) goto error_dt; - c->TxChannels = val; + if (vphydev->isvphy) + vphycfg->TxChannels = val; + else + xgtphycfg->TxChannels = val; rc = of_property_read_u32(node, "xlnx,rx-protocol", &val); if (rc < 0) goto error_dt; - c->RxProtocol = val; + if (vphydev->isvphy) + vphycfg->RxProtocol = val; + else + xgtphycfg->RxProtocol = val; rc = of_property_read_u32(node, "xlnx,tx-protocol", &val); if (rc < 0) goto error_dt; - c->TxProtocol = val; + if (vphydev->isvphy) + vphycfg->TxProtocol = val; + else + xgtphycfg->TxProtocol = val; rc = of_property_read_u32(node, "xlnx,rx-refclk-sel", &val); if (rc < 0) goto error_dt; - c->RxRefClkSel = val; + if (vphydev->isvphy) + vphycfg->RxRefClkSel = val; + else + xgtphycfg->RxRefClkSel = val; rc = of_property_read_u32(node, "xlnx,tx-refclk-sel", &val); if (rc < 0) goto error_dt; - c->TxRefClkSel = val; + if (vphydev->isvphy) + vphycfg->TxRefClkSel = val; + else + xgtphycfg->TxRefClkSel = val; rc = of_property_read_u32(node, "xlnx,rx-pll-selection", &val); if (rc < 0) goto error_dt; - c->RxSysPllClkSel = val; + if (vphydev->isvphy) + vphycfg->RxSysPllClkSel = val; + else + xgtphycfg->RxSysPllClkSel = val; rc = of_property_read_u32(node, "xlnx,tx-pll-selection", &val); if (rc < 0) goto error_dt; - c->TxSysPllClkSel = val; + if (vphydev->isvphy) + vphycfg->TxSysPllClkSel = val; + else + xgtphycfg->TxSysPllClkSel = val; rc = of_property_read_u32(node, "xlnx,hdmi-fast-switch", &val); if (rc < 0) goto error_dt; - c->HdmiFastSwitch = val; + if (vphydev->isvphy) + vphycfg->HdmiFastSwitch = val; + else + xgtphycfg->HdmiFastSwitch = val; rc = of_property_read_u32(node, "xlnx,transceiver-width", &val); if (rc < 0) goto error_dt; - c->TransceiverWidth = val; + if (vphydev->isvphy) + vphycfg->TransceiverWidth = val; + else + xgtphycfg->TransceiverWidth = val; has_err_irq = false; has_err_irq = of_property_read_bool(node, "xlnx,err-irq-en"); - c->ErrIrq = has_err_irq; + if (vphydev->isvphy) + vphycfg->ErrIrq = has_err_irq; + else + xgtphycfg->ErrIrq = has_err_irq; rc = of_property_read_u32(node, "xlnx,use-gt-ch4-hdmi", &val); if (rc < 0) goto error_dt; - c->UseGtAsTxTmdsClk = val; + if (vphydev->isvphy) + vphycfg->UseGtAsTxTmdsClk = val; + else + xgtphycfg->UseGtAsTxTmdsClk = val; + + if (!vphydev->isvphy) { + rc = of_property_read_u32(node, "xlnx,rx-frl-refclk-sel", &val); + if (rc < 0) + goto error_dt; + xgtphycfg->RxFrlRefClkSel = val; + + rc = of_property_read_u32(node, "xlnx,tx-frl-refclk-sel", &val); + if (rc < 0) + goto error_dt; + xgtphycfg->TxFrlRefClkSel = val; + } return 0; @@ -405,6 +541,14 @@ static int vphy_parse_of(struct xvphy_dev *vphydev, XVphy_Config *c) return -EINVAL; } +/* Match table for of_platform binding */ +static const struct of_device_id xvphy_of_match[] = { + { .compatible = "xlnx,hdmi-gt-controller-1.0" }, + { .compatible = "xlnx,vid-phy-controller-2.2" }, + { /* end of table */ }, +}; +MODULE_DEVICE_TABLE(of, xvphy_of_match); + /** * xvphy_probe - The device probe function for driver initialization. * @pdev: pointer to the platform device structure. @@ -427,7 +571,10 @@ static int xvphy_probe(struct platform_device *pdev) u32 Data; u16 DrpVal; - dev_info(&pdev->dev, "probed\n"); + void __iomem *iomem1; + const struct of_device_id *match; + + dev_info(&pdev->dev, "probe started\n"); vphydev = devm_kzalloc(&pdev->dev, sizeof(*vphydev), GFP_KERNEL); if (!vphydev) return -ENOMEM; @@ -439,10 +586,23 @@ static int xvphy_probe(struct platform_device *pdev) /* set a pointer to our driver data */ platform_set_drvdata(pdev, vphydev); + match = of_match_node(xvphy_of_match, np); + if (!match) + return -ENODEV; + + if (strncmp(match->compatible, "xlnx,vid-phy-controller", 23) == 0) + vphydev->isvphy = 1; + else + vphydev->isvphy = 0; + XVphy_ConfigTable[instance].DeviceId = VPHY_DEVICE_ID_BASE + instance; + XHdmiphy1_ConfigTable[instance].DeviceId = VPHY_DEVICE_ID_BASE + instance; dev_dbg(vphydev->dev,"DT parse start\n"); - ret = vphy_parse_of(vphydev, &XVphy_ConfigTable[instance]); + if (vphydev->isvphy) + ret = vphy_parse_of(vphydev, &XVphy_ConfigTable[instance]); + else + ret = vphy_parse_of(vphydev, &XHdmiphy1_ConfigTable[instance]); if (ret) return ret; dev_dbg(vphydev->dev,"DT parse done\n"); @@ -495,6 +655,7 @@ static int xvphy_probe(struct platform_device *pdev) /* set address in configuration data */ XVphy_ConfigTable[instance].BaseAddr = (uintptr_t)vphydev->iomem; + XHdmiphy1_ConfigTable[instance].BaseAddr = (uintptr_t)vphydev->iomem; vphydev->irq = platform_get_irq(pdev, 0); if (vphydev->irq <= 0) { @@ -503,7 +664,10 @@ static int xvphy_probe(struct platform_device *pdev) } /* the AXI lite clock is used for the clock rate detector */ - vphydev->axi_lite_clk = devm_clk_get(&pdev->dev, "vid_phy_axi4lite_aclk"); + if (vphydev->isvphy) + vphydev->axi_lite_clk = devm_clk_get(&pdev->dev, "vid_phy_axi4lite_aclk"); + else + vphydev->axi_lite_clk = devm_clk_get(&pdev->dev, "axi4lite_aclk"); if (IS_ERR(vphydev->axi_lite_clk)) { ret = PTR_ERR(vphydev->axi_lite_clk); vphydev->axi_lite_clk = NULL; @@ -525,9 +689,12 @@ static int xvphy_probe(struct platform_device *pdev) /* set axi-lite clk in configuration data */ XVphy_ConfigTable[instance].AxiLiteClkFreq = axi_lite_rate; XVphy_ConfigTable[instance].DrpClkFreq = axi_lite_rate; + XHdmiphy1_ConfigTable[instance].AxiLiteClkFreq = axi_lite_rate; + XHdmiphy1_ConfigTable[instance].DrpClkFreq = axi_lite_rate; /* dru-clk is used for the nidru block for low res support */ - if (XVphy_ConfigTable[instance].DruIsPresent == (TRUE)) { + if ((vphydev->isvphy && (XVphy_ConfigTable[instance].DruIsPresent == (TRUE))) || + (!vphydev->isvphy && (XHdmiphy1_ConfigTable[instance].DruIsPresent == (TRUE)))) { vphydev->dru_clk = devm_clk_get(&pdev->dev, "dru-clk"); if (IS_ERR(vphydev->dru_clk)) { ret = PTR_ERR(vphydev->dru_clk); @@ -546,19 +713,25 @@ static int xvphy_probe(struct platform_device *pdev) } dru_clk_rate = clk_get_rate(vphydev->dru_clk); - dev_dbg(vphydev->dev,"default dru-clk rate = %lu\n", dru_clk_rate); - if (dru_clk_rate != XVPHY_DRU_REF_CLK_HZ) { - ret = clk_set_rate(vphydev->dru_clk, XVPHY_DRU_REF_CLK_HZ); + dev_dbg(vphydev->dev, "default dru-clk rate = %lu\n", dru_clk_rate); + if ((vphydev->isvphy && (dru_clk_rate != XVPHY_DRU_REF_CLK_HZ)) || + (!vphydev->isvphy && (dru_clk_rate != XHDMIPHY1_DRU_REF_CLK_HZ))) { + + if (vphydev->isvphy) + ret = clk_set_rate(vphydev->dru_clk, XVPHY_DRU_REF_CLK_HZ); + else + ret = clk_set_rate(vphydev->dru_clk, XHDMIPHY1_DRU_REF_CLK_HZ); + if (ret != 0) { dev_err(&pdev->dev, "Cannot set rate : %d\n", ret); } dru_clk_rate = clk_get_rate(vphydev->dru_clk); - dev_dbg(vphydev->dev,"ref dru-clk rate = %lu\n", dru_clk_rate); + dev_dbg(vphydev->dev, "ref dru-clk rate = %lu\n", dru_clk_rate); } } else { - dev_dbg(vphydev->dev,"DRU is not enabled from device tree\n"); + dev_dbg(vphydev->dev, "DRU is not enabled from device tree\n"); } provider = devm_of_phy_provider_register(&pdev->dev, xvphy_xlate); @@ -567,17 +740,64 @@ static int xvphy_probe(struct platform_device *pdev) return PTR_ERR(provider); } + if (!vphydev->isvphy) { + /* For Versal */ + iomem1 = ioremap(0xF70E000C, 4); + if (IS_ERR(iomem1)) + dev_err(vphydev->dev, "[Versal] - Error in iomem 5\n"); + XHdmiphy1_Out32((INTPTR)iomem1, 0xF9E8D7C6); + dev_dbg(vphydev->dev, "To: 0x%08x \r\n", XHdmiphy1_In32((INTPTR)iomem1)); + iounmap(iomem1); + + iomem1 = ioremap(0xF70E3C4C, 4); + if (IS_ERR(iomem1)) + dev_err(vphydev->dev, "[Versal] - Error in iomem 6\n"); + dev_dbg(vphydev->dev, "RX:HS1 RPLL IPS From: 0x%08x ", XHdmiphy1_In32((INTPTR)iomem1)); + XHdmiphy1_Out32((INTPTR)iomem1, 0x03E00810); + dev_dbg(vphydev->dev, "To: 0x%08x \r\n", XHdmiphy1_In32((INTPTR)iomem1)); + iounmap(iomem1); + + iomem1 = ioremap(0xF70E3C48, 4); + if (IS_ERR(iomem1)) + dev_err(vphydev->dev, "[Versal] - Error in iomem 7\n"); + dev_dbg(vphydev->dev, "TX:HS1 LCPLL IPS From: 0x%08x ", XHdmiphy1_In32((INTPTR)iomem1)); + XHdmiphy1_Out32((INTPTR)iomem1, 0x03E00840); + dev_dbg(vphydev->dev, "To: 0x%08x \r\n", XHdmiphy1_In32((INTPTR)iomem1)); + iounmap(iomem1); + + /* Deassert the GTWiz_RESET_ALL */ + XHdmiphy1_WriteReg(XHdmiphy1_ConfigTable[instance].BaseAddr, 0x14, + (XHdmiphy1_ReadReg(XHdmiphy1_ConfigTable[instance].BaseAddr, 0x14) & ~0x1)); + dev_dbg(vphydev->dev, "To: 0x14 PHY1 Reg 0x%08x \r\n", + XHdmiphy1_ReadReg(XHdmiphy1_ConfigTable[instance].BaseAddr, 0x14)); + + /* Release RXPLL dependency from TXPLL RESET */ + XHdmiphy1_WriteReg(XHdmiphy1_ConfigTable[instance].BaseAddr, 0x14, + (XHdmiphy1_ReadReg(XHdmiphy1_ConfigTable[instance].BaseAddr, 0x14) | 0x80000000)); + dev_dbg(vphydev->dev, "To: 0x14 PHY1 Reg 0x%08x \r\n", + XHdmiphy1_ReadReg(XHdmiphy1_ConfigTable[instance].BaseAddr, 0x14)); + + /* Delay 50ms for GT to complete initialization */ + usleep_range(50000, 50000); + } /* Initialize HDMI VPHY */ - Status = XVphy_Hdmi_CfgInitialize(&vphydev->xvphy, 0/*QuadID*/, - &XVphy_ConfigTable[instance]); + if (vphydev->isvphy) + Status = XVphy_Hdmi_CfgInitialize(&vphydev->xvphy, 0/*QuadID*/, + &XVphy_ConfigTable[instance]); + else + Status = XHdmiphy1_Hdmi_CfgInitialize(&vphydev->xgtphy, 0/*QuadID*/, + &XHdmiphy1_ConfigTable[instance]); if (Status != XST_SUCCESS) { dev_err(&pdev->dev, "HDMI VPHY initialization error\n"); return ENODEV; } - Data = XVphy_GetVersion(&vphydev->xvphy); - printk(KERN_INFO "VPhy version : %02d.%02d (%04x)\n", ((Data >> 24) & 0xFF), + if (vphydev->isvphy) + Data = XVphy_GetVersion(&vphydev->xvphy); + else + Data = XHdmiphy1_GetVersion(&vphydev->xgtphy); + dev_info(vphydev->dev, "VPhy version : %02d.%02d (%04x)\n", ((Data >> 24) & 0xFF), ((Data >> 16) & 0xFF), (Data & 0xFFFF)); @@ -589,11 +809,20 @@ static int xvphy_probe(struct platform_device *pdev) return ret; } - dev_dbg(vphydev->dev,"config.DruIsPresent = %d\n", XVphy_ConfigTable[instance].DruIsPresent); - if (vphydev->xvphy.Config.DruIsPresent == (TRUE)) { - dev_dbg(vphydev->dev,"DRU reference clock frequency %0d Hz\n\r", + if (vphydev->isvphy) { + dev_dbg(vphydev->dev,"config.DruIsPresent = %d\n", XVphy_ConfigTable[instance].DruIsPresent); + if (vphydev->xvphy.Config.DruIsPresent == (TRUE)) { + dev_dbg(vphydev->dev,"DRU reference clock frequency %0d Hz\n\r", XVphy_DruGetRefClkFreqHz(&vphydev->xvphy)); + } + } else { + dev_dbg(vphydev->dev,"config.DruIsPresent = %d\n", XHdmiphy1_ConfigTable[instance].DruIsPresent); + if (vphydev->xgtphy.Config.DruIsPresent == (TRUE)) { + dev_info(vphydev->dev,"DRU reference clock frequency %0d Hz\n", + XHdmiphy1_DruGetRefClkFreqHz(&vphydev->xgtphy)); + } } + dev_info(&pdev->dev, "probe successful\n"); /* probe has succeeded for this instance, increment instance index */ instance++; @@ -620,13 +849,6 @@ static const struct dev_pm_ops xvphy_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(xvphy_pm_suspend, xvphy_pm_resume) }; -/* Match table for of_platform binding */ -static const struct of_device_id xvphy_of_match[] = { - { .compatible = "xlnx,vid-phy-controller-2.2" }, - { /* end of table */ }, -}; -MODULE_DEVICE_TABLE(of, xvphy_of_match); - static struct platform_driver xvphy_driver = { .probe = xvphy_probe, .driver = { @@ -639,7 +861,7 @@ module_platform_driver(xvphy_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Leon Woestenberg "); -MODULE_DESCRIPTION("Xilinx Vphy driver"); +MODULE_DESCRIPTION("Xilinx Vphy / HDMI GT Controller driver"); /* phy sub-directory is used as a place holder for all shared code for hdmi-rx and hdmi-tx driver. All shared API's need to be exported */ diff --git a/hdmi/phy-xilinx-vphy/xhdmiphy1.c b/hdmi/phy-xilinx-vphy/xhdmiphy1.c new file mode 100644 index 0000000..0b43796 --- /dev/null +++ b/hdmi/phy-xilinx-vphy/xhdmiphy1.c @@ -0,0 +1,1381 @@ +/******************************************************************************* + * + * + * 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 xhdmiphy1.c + * + * Contains a minimal set of functions for the XHdmiphy1 driver that allow + * access to all of the Video PHY core's functionality. See xhdmiphy1.h for a + * detailed description of the driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ *            dd/mm/yy
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   gm   10/12/18 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include +#include "xstatus.h" +#include "xhdmiphy1.h" +#include "xhdmiphy1_i.h" +#include "xhdmiphy1_hdmi.h" +#include +#include "xhdmiphy1_gt.h" + +/**************************** Function Prototypes *****************************/ +static u32 XHdmiphy1_DrpAccess(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_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 XHdmiphy1 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 XHdmiphy1_CfgInitialize(XHdmiphy1 *InstancePtr, + XHdmiphy1_Config *ConfigPtr, + UINTPTR EffectiveAddr) +{ +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + u8 Sel; +#endif + + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(ConfigPtr != NULL); + Xil_AssertVoid(EffectiveAddr != 0x0); + + (void)memset((void *)InstancePtr, 0, sizeof(XHdmiphy1)); + InstancePtr->IsReady = 0; + + InstancePtr->Config = *ConfigPtr; + InstancePtr->Config.BaseAddr = EffectiveAddr; + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE3) + InstancePtr->GtAdaptor = &Gthe3Config; +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE4) + InstancePtr->GtAdaptor = &Gthe4Config; +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE4) + InstancePtr->GtAdaptor = &Gtye4Config; +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE5) + InstancePtr->GtAdaptor = &Gtye5Config; +#endif + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + const XHdmiphy1_SysClkDataSelType SysClkCfg[7][2] = { + {(XHdmiphy1_SysClkDataSelType)0, + XHDMIPHY1_SYSCLKSELDATA_TYPE_CPLL_OUTCLK}, + {(XHdmiphy1_SysClkDataSelType)1, + XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK}, + {(XHdmiphy1_SysClkDataSelType)2, + XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK}, + {(XHdmiphy1_SysClkDataSelType)3, + XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL_OUTCLK}, + {(XHdmiphy1_SysClkDataSelType)4, + XHDMIPHY1_SYSCLKSELDATA_TYPE_PLL0_OUTCLK}, + {(XHdmiphy1_SysClkDataSelType)5, + XHDMIPHY1_SYSCLKSELDATA_TYPE_PLL1_OUTCLK}, + {(XHdmiphy1_SysClkDataSelType)6, + XHDMIPHY1_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 = (XHdmiphy1_PllRefClkSelType) + (InstancePtr->Config.TxRefClkSel + + XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTREFCLK0); + InstancePtr->Config.RxRefClkSel = (XHdmiphy1_PllRefClkSelType) + (InstancePtr->Config.RxRefClkSel + + XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTREFCLK0); + InstancePtr->Config.TxFrlRefClkSel = (XHdmiphy1_PllRefClkSelType) + (InstancePtr->Config.TxFrlRefClkSel + + XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTREFCLK0); + InstancePtr->Config.RxFrlRefClkSel = (XHdmiphy1_PllRefClkSelType) + (InstancePtr->Config.RxFrlRefClkSel + + XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTREFCLK0); + InstancePtr->Config.DruRefClkSel = (XHdmiphy1_PllRefClkSelType) + (InstancePtr->Config.DruRefClkSel + + XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTREFCLK0); +#endif + + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; +} + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) +/*****************************************************************************/ +/** +* This function will initialize the PLL selection for a given channel. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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. +* @param CpllRefClkSel is the CPLL reference clock selection for the +* quad. +* @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 XHdmiphy1_PllInitialize(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, + XHdmiphy1_PllRefClkSelType QpllRefClkSel, + XHdmiphy1_PllRefClkSelType CpllRefClkSel, + XHdmiphy1_PllType TxPllSelect, XHdmiphy1_PllType RxPllSelect) +{ + /* Suppress Warning Messages */ + ChId = ChId; + + /* Set configuration in software. */ + XHdmiphy1_CfgPllRefClkSel(InstancePtr, QuadId, + XHDMIPHY1_CHANNEL_ID_CMNA, QpllRefClkSel); + XHdmiphy1_CfgPllRefClkSel(InstancePtr, QuadId, + XHDMIPHY1_CHANNEL_ID_CHA, CpllRefClkSel); + XHdmiphy1_CfgSysClkDataSel(InstancePtr, QuadId, XHDMIPHY1_DIR_TX, + Pll2SysClkData(TxPllSelect)); + XHdmiphy1_CfgSysClkDataSel(InstancePtr, QuadId, XHDMIPHY1_DIR_RX, + Pll2SysClkData(RxPllSelect)); + XHdmiphy1_CfgSysClkOutSel(InstancePtr, QuadId, XHDMIPHY1_DIR_TX, + Pll2SysClkOut(TxPllSelect)); + XHdmiphy1_CfgSysClkOutSel(InstancePtr, QuadId, XHDMIPHY1_DIR_RX, + Pll2SysClkOut(RxPllSelect)); + + /* Write configuration to hardware at once. */ + XHdmiphy1_WriteCfgRefClkSelReg(InstancePtr, QuadId); + + return XST_SUCCESS; +} +#endif + +/******************************************************************************/ +/* +* This function installs a custom delay/sleep function to be used by the +* XHdmiphy1 driver. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_SetUserTimerHandler(XHdmiphy1 *InstancePtr, + XHdmiphy1_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 XHdmiphy1 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 XHdmiphy1 instance. +* @param MicroSeconds is the number of microseconds to delay/sleep for. +* +* @return None. +* +* @note None. +* +*******************************************************************************/ +void XHdmiphy1_WaitUs(XHdmiphy1 *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); + } +} + +/*****************************************************************************/ +/** +* This function will obtian the IP version. +* +* @param InstancePtr is a pointer to the XHdmiphy1 core instance. +* +* @return The IP version of the Video PHY core. +* +* @note None. +* +******************************************************************************/ +u32 XHdmiphy1_GetVersion(XHdmiphy1 *InstancePtr) +{ + return XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_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 XHdmiphy1 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 XHdmiphy1_CfgLineRate(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, u64 LineRateHz) +{ + u8 Id; + u8 Id0; + u8 Id1; + + XHdmiphy1_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)].LineRateHz = + LineRateHz; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* Obtain the channel's PLL reference clock selection. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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. +* +******************************************************************************/ +XHdmiphy1_PllType XHdmiphy1_GetPllType(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, XHdmiphy1_ChannelId ChId) +{ + XHdmiphy1_PllType PllType; +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + XHdmiphy1_SysClkDataSelType SysClkDataSel; + XHdmiphy1_SysClkOutSelType SysClkOutSel; + + SysClkDataSel = XHdmiphy1_GetSysClkDataSel(InstancePtr, QuadId, Dir, ChId); + SysClkOutSel = XHdmiphy1_GetSysClkOutSel(InstancePtr, QuadId, Dir, ChId); + + /* The sysclk data and output reference clocks should match. */ + + if ((SysClkDataSel == XHDMIPHY1_SYSCLKSELDATA_TYPE_CPLL_OUTCLK) && + (SysClkOutSel == XHDMIPHY1_SYSCLKSELOUT_TYPE_CPLL_REFCLK)) { + PllType = XHDMIPHY1_PLL_TYPE_CPLL; + } + else if ((SysClkDataSel == XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL_OUTCLK) && + (SysClkOutSel == XHDMIPHY1_SYSCLKSELOUT_TYPE_QPLL_REFCLK)) { + PllType = XHDMIPHY1_PLL_TYPE_QPLL; + } + else if ((SysClkDataSel == XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK) && + (SysClkOutSel == XHDMIPHY1_SYSCLKSELOUT_TYPE_QPLL0_REFCLK)) { + PllType = XHDMIPHY1_PLL_TYPE_QPLL0; + } + else if ((SysClkDataSel == XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK) && + (SysClkOutSel == XHDMIPHY1_SYSCLKSELOUT_TYPE_QPLL1_REFCLK)) { + PllType = XHDMIPHY1_PLL_TYPE_QPLL1; + } + else { + PllType = XHDMIPHY1_PLL_TYPE_UNKNOWN; + } +#else + /* Suppress Warning Messages */ + QuadId = QuadId; + ChId = ChId; + + if (Dir == XHDMIPHY1_DIR_TX) { + PllType = (XHdmiphy1_PllType) InstancePtr->Config.TxSysPllClkSel-2; + } + else if (Dir == XHDMIPHY1_DIR_RX) { + PllType = (XHdmiphy1_PllType) InstancePtr->Config.RxSysPllClkSel-2; + } + else { + PllType = XHDMIPHY1_PLL_TYPE_UNKNOWN; + } +#endif + + return PllType; +} + +/*****************************************************************************/ +/** +* This function will return the line rate in Hz for a given channel / quad. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_GetLineRateHz(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid((ChId < XHDMIPHY1_CHANNEL_ID_CMNA)); + + XHdmiphy1_ChannelId Ch_Id = ChId; + + if (ChId == XHDMIPHY1_CHANNEL_ID_CHA) { + Ch_Id = XHDMIPHY1_CHANNEL_ID_CH1; + } else if (ChId == XHDMIPHY1_CHANNEL_ID_CMNA) { + Ch_Id = XHDMIPHY1_CHANNEL_ID_CMN0; + } + + return InstancePtr->Quads[QuadId].Plls[Ch_Id - + XHDMIPHY1_CHANNEL_ID_CH1].LineRateHz; +} + +/*****************************************************************************/ +/** +* This function will reset the GT's PLL logic. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_ResetGtPll(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, u8 Hold) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XHDMIPHY1_DIR_TX) { + RegOffset = XHDMIPHY1_TX_INIT_REG; + } + else { + RegOffset = XHDMIPHY1_RX_INIT_REG; + } + if (ChId == XHDMIPHY1_CHANNEL_ID_CHA) { + MaskVal = XHDMIPHY1_TXRX_INIT_PLLGTRESET_ALL_MASK; + } + else { + MaskVal = XHDMIPHY1_TXRX_INIT_PLLGTRESET_MASK(ChId); + } + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + /* Assert reset. */ + RegVal |= MaskVal; + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + + if (!Hold) { + /* De-assert reset. */ + RegVal &= ~MaskVal; + XHdmiphy1_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 XHdmiphy1 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 XHdmiphy1_ResetGtTxRx(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, u8 Hold) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XHDMIPHY1_DIR_TX) { + RegOffset = XHDMIPHY1_TX_INIT_REG; + } + else { + RegOffset = XHDMIPHY1_RX_INIT_REG; + } + if (ChId == XHDMIPHY1_CHANNEL_ID_CHA) { + MaskVal = XHDMIPHY1_TXRX_INIT_GTRESET_ALL_MASK; + } + else { + MaskVal = XHDMIPHY1_TXRX_INIT_GTRESET_MASK(ChId); + } + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + /* Assert reset. */ + RegVal |= MaskVal; + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + + if (!Hold) { + /* De-assert reset. */ + RegVal &= ~MaskVal; + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will set/clear the TX/RX polarity bit. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 Polarity 0-Not inverted 1-Inverted +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +u32 XHdmiphy1_SetPolarity(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, u8 Polarity) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XHDMIPHY1_DIR_TX) { + RegOffset = XHDMIPHY1_TX_CONTROL_REG; + if (ChId == XHDMIPHY1_CHANNEL_ID_CHA) { + MaskVal = XHDMIPHY1_TX_CONTROL_TXPOLARITY_ALL_MASK; + } + else { + MaskVal = XHDMIPHY1_TX_CONTROL_TXPOLARITY_MASK(ChId); + } + } + else { + RegOffset = XHDMIPHY1_RX_CONTROL_REG; + if (ChId == XHDMIPHY1_CHANNEL_ID_CHA) { + MaskVal = XHDMIPHY1_RX_CONTROL_RXPOLARITY_ALL_MASK; + } + else { + MaskVal = XHDMIPHY1_RX_CONTROL_RXPOLARITY_MASK(ChId); + } + } + + /* Read TX|RX Control Register */ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + + /* Clear Polarity Register bits */ + RegVal &= ~MaskVal; + + if (Polarity) { + RegVal |= MaskVal; + } + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will set the TX/RXPRBSEL of the GT +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 Pattern is the pattern XHdmiphy1_PrbsPattern +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +u32 XHdmiphy1_SetPrbsSel(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, + XHdmiphy1_PrbsPattern Pattern) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + u32 PrbsEnc = 0x0; + u8 Id, Id0, Id1; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XHDMIPHY1_DIR_TX) { + RegOffset = XHDMIPHY1_TX_CONTROL_REG; + if (ChId == XHDMIPHY1_CHANNEL_ID_CHA) { + MaskVal = XHDMIPHY1_TX_CONTROL_TXPRBSSEL_ALL_MASK; + } + else { + MaskVal = XHDMIPHY1_TX_CONTROL_TXPRBSSEL_MASK(ChId); + } + PrbsEnc = (u32) (((Pattern & 0x8) << 1) | (Pattern & 0x7)); + } + else { + RegOffset = XHDMIPHY1_RX_CONTROL_REG; + if (ChId == XHDMIPHY1_CHANNEL_ID_CHA) { + MaskVal = XHDMIPHY1_RX_CONTROL_RXPRBSSEL_ALL_MASK; + } + else { + MaskVal = XHDMIPHY1_RX_CONTROL_RXPRBSSEL_MASK(ChId); + } + PrbsEnc = (u32) (Pattern & 0xF); + } + + /* Read TX|RX Control Register */ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + + /* Mask out PRBS Register bits */ + RegVal &= ~MaskVal; + + XHdmiphy1_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + RegVal |= PrbsEnc << ((Dir == XHDMIPHY1_DIR_TX) ? + XHDMIPHY1_TX_CONTROL_TXPRBSSEL_SHIFT(Id) : + XHDMIPHY1_RX_CONTROL_RXPRBSSEL_SHIFT(Id)); + } + + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will set the TX/RXPRBSEL of the GT +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 ForceErr 0-No Error 1-Force Error +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +u32 XHdmiphy1_TxPrbsForceError(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, u8 ForceErr) +{ + u32 RegVal; + u32 MaskVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (ChId == XHDMIPHY1_CHANNEL_ID_CHA) { + MaskVal = XHDMIPHY1_TX_CONTROL_TXPRBSFORCEERR_ALL_MASK; + } + else { + MaskVal = XHDMIPHY1_TX_CONTROL_TXPRBSFORCEERR_MASK(ChId); + } + + /* Read TX|RX Control Register */ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_TX_CONTROL_REG); + + /* Clear Polarity Register bits */ + RegVal &= ~MaskVal; + + if (ForceErr) { + RegVal |= MaskVal; + } + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_TX_CONTROL_REG, RegVal); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will set the TX voltage swing value for a given channel. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_SetTxVoltageSwing(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, u8 Vs) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if ((ChId == XHDMIPHY1_CHANNEL_ID_CH1) || + (ChId == XHDMIPHY1_CHANNEL_ID_CH2)) { + RegOffset = XHDMIPHY1_TX_DRIVER_CH12_REG; + } + else { + RegOffset = XHDMIPHY1_TX_DRIVER_CH34_REG; + } + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + + MaskVal = XHDMIPHY1_TX_DRIVER_TXDIFFCTRL_MASK(ChId); + RegVal &= ~MaskVal; + RegVal |= ((Vs & 0xF) << XHDMIPHY1_TX_DRIVER_TXDIFFCTRL_SHIFT(ChId)); + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_TX_DRIVER_EXT_REG); + MaskVal = XHDMIPHY1_TX_DRIVER_EXT_TXDIFFCTRL_MASK(ChId); + RegVal &= ~MaskVal; + RegVal |= ((Vs && 0x10) << + XHDMIPHY1_TX_DRIVER_EXT_TXDIFFCTRL_SHIFT(ChId)); + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_TX_DRIVER_EXT_REG, RegVal); +} + +/*****************************************************************************/ +/** +* This function will set the TX pre-emphasis value for a given channel. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_SetTxPreEmphasis(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, u8 Pe) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if ((ChId == XHDMIPHY1_CHANNEL_ID_CH1) || + (ChId == XHDMIPHY1_CHANNEL_ID_CH2)) { + RegOffset = XHDMIPHY1_TX_DRIVER_CH12_REG; + } + else { + RegOffset = XHDMIPHY1_TX_DRIVER_CH34_REG; + } + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + + MaskVal = XHDMIPHY1_TX_DRIVER_TXPRECURSOR_MASK(ChId); + RegVal &= ~MaskVal; + RegVal |= (Pe << XHDMIPHY1_TX_DRIVER_TXPRECURSOR_SHIFT(ChId)); + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); +} + +/*****************************************************************************/ +/** +* This function will set the TX post-curosr value for a given channel. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_SetTxPostCursor(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, u8 Pc) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if ((ChId == XHDMIPHY1_CHANNEL_ID_CH1) || + (ChId == XHDMIPHY1_CHANNEL_ID_CH2)) { + RegOffset = XHDMIPHY1_TX_DRIVER_CH12_REG; + } + else { + RegOffset = XHDMIPHY1_TX_DRIVER_CH34_REG; + } + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + + MaskVal = XHDMIPHY1_TX_DRIVER_TXPOSTCURSOR_MASK(ChId); + RegVal &= ~MaskVal; + RegVal |= (Pc << XHDMIPHY1_TX_DRIVER_TXPOSTCURSOR_SHIFT(ChId)); + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); +} + +/*****************************************************************************/ +/** +* This function will enable or disable the LPM logic in the Video PHY core. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_SetRxLpm(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, u8 Enable) +{ + u32 RegVal; + u32 MaskVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + Dir = Dir; + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_RX_EQ_CDR_REG); + + if (ChId == XHDMIPHY1_CHANNEL_ID_CHA) { + MaskVal = XHDMIPHY1_RX_CONTROL_RXLPMEN_ALL_MASK; + } + else { + MaskVal = XHDMIPHY1_RX_CONTROL_RXLPMEN_MASK(ChId); + } + + if (Enable) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_RX_EQ_CDR_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function will initiate a write DRP transaction. It is a wrapper around +* XHdmiphy1_DrpAccess. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 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 XHdmiphy1_DrpWr(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, u16 Addr, u16 Val) +{ + return XHdmiphy1_DrpAccess(InstancePtr, QuadId, ChId, + XHDMIPHY1_DIR_TX, /* Write. */ + Addr, &Val); +} + +/*****************************************************************************/ +/** +* This function will initiate a read DRP transaction. It is a wrapper around +* XHdmiphy1_DrpAccess. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 Addr is the DRP address to issue the DRP access to. +* @param RetVal is the DRP read_value returned implicitly. +* +* @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 XHdmiphy1_DrpRd(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, u16 Addr, u16 *RetVal) +{ + u32 Status; + u16 Val; + + Status = XHdmiphy1_DrpAccess(InstancePtr, QuadId, ChId, + XHDMIPHY1_DIR_RX, /* Read. */ + Addr, &Val); + + *RetVal = Val; + + return Status; +} + +/*****************************************************************************/ +/** +* This function will power down the mixed-mode clock manager (MMCM) core. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_MmcmPowerDown(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, u8 Hold) +{ + u32 RegOffsetCtrl; + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XHDMIPHY1_DIR_TX) { + RegOffsetCtrl = XHDMIPHY1_MMCM_TXUSRCLK_CTRL_REG; + } + else { + RegOffsetCtrl = XHDMIPHY1_MMCM_RXUSRCLK_CTRL_REG; + } + + /* Power down. */ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl); + RegVal |= XHDMIPHY1_MMCM_USRCLK_CTRL_PWRDWN_MASK; + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, RegVal); + + if (!Hold) { + /* Power up. */ + RegVal &= ~XHDMIPHY1_MMCM_USRCLK_CTRL_PWRDWN_MASK; + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, + RegVal); + } +} + +/*****************************************************************************/ +/** +* This function will start the mixed-mode clock manager (MMCM) core. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_MmcmStart(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir) +{ + XHdmiphy1_Mmcm *MmcmPtr; + + if (Dir == XHDMIPHY1_DIR_RX) { + MmcmPtr= &InstancePtr->Quads[QuadId].RxMmcm; + } + else { + MmcmPtr= &InstancePtr->Quads[QuadId].TxMmcm; + } + + /* Check values if valid */ +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + if (!((MmcmPtr->ClkOut0Div > 0) && (MmcmPtr->ClkOut0Div <= 128) && + (MmcmPtr->ClkOut1Div > 0) && (MmcmPtr->ClkOut1Div <= 128) && + (MmcmPtr->ClkOut2Div > 0) && (MmcmPtr->ClkOut2Div <= 128))) { +#else + if (!((MmcmPtr->ClkOut0Div > 0) && (MmcmPtr->ClkOut0Div <= 432) && + (MmcmPtr->ClkOut1Div > 0) && (MmcmPtr->ClkOut1Div <= 432) && + (MmcmPtr->ClkOut2Div > 0) && (MmcmPtr->ClkOut2Div <= 432))) { +#endif + return; + } + + /* Assert MMCM reset. */ + XHdmiphy1_MmcmReset(InstancePtr, QuadId, Dir, TRUE); + + /* Configure MMCM. */ + XHdmiphy1_MmcmWriteParameters(InstancePtr, QuadId, Dir); + + /* Release MMCM reset. */ + XHdmiphy1_MmcmReset(InstancePtr, QuadId, Dir, FALSE); + + /* Unmask the MMCM Lock */ + XHdmiphy1_MmcmLockedMaskEnable(InstancePtr, 0, Dir, FALSE); + + XHdmiphy1_LogWrite(InstancePtr, (Dir == XHDMIPHY1_DIR_TX) ? + XHDMIPHY1_LOG_EVT_TXPLL_RECONFIG : + XHDMIPHY1_LOG_EVT_RXPLL_RECONFIG, 1); +} + +/*****************************************************************************/ +/** +* This function enables the TX or RX IBUFDS peripheral. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_IBufDsEnable(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, u8 Enable) +{ +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + XHdmiphy1_PllRefClkSelType *TypePtr, *DruTypePtr, DruTypeDummy; + DruTypeDummy = XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTGREFCLK; + DruTypePtr = &DruTypeDummy; +#endif + u32 RegAddr = XHDMIPHY1_IBUFDS_GTXX_CTRL_REG; + u32 RegVal; + u32 MaskVal = 0; + + /* Suppress Warning Messages */ + QuadId = QuadId; + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + if (Dir == XHDMIPHY1_DIR_TX) { + TypePtr = &InstancePtr->Config.TxRefClkSel; + } + else { + TypePtr = &InstancePtr->Config.RxRefClkSel; + if (InstancePtr->Config.DruIsPresent) { + DruTypePtr = &InstancePtr->Config.DruRefClkSel; + } + } + + if ((*TypePtr == XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTREFCLK0) || + ((InstancePtr->Config.DruIsPresent) && + (*DruTypePtr == XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTREFCLK0))) { + MaskVal = XHDMIPHY1_IBUFDS_GTXX_CTRL_GTREFCLK0_CEB_MASK; + } + else if ((*TypePtr == XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTREFCLK1) || + ((InstancePtr->Config.DruIsPresent) && + (*DruTypePtr == XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTREFCLK1))) { + MaskVal = XHDMIPHY1_IBUFDS_GTXX_CTRL_GTREFCLK1_CEB_MASK; + } + else { +#endif + if (Dir == XHDMIPHY1_DIR_TX) { + RegAddr = XHDMIPHY1_MISC_TXUSRCLK_REG; + } + else { + RegAddr = XHDMIPHY1_MISC_RXUSRCLK_REG; + } + MaskVal = XHDMIPHY1_MISC_XXUSRCLK_REFCLK_CEB_MASK; +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + } +#endif + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegAddr); + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + if (Enable) { + RegVal &= ~MaskVal; + } + else { + RegVal |= MaskVal; + } +#else + if (Enable) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } +#endif + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegAddr, RegVal); +} + +/*****************************************************************************/ +/** +* This function enables the TX or RX CLKOUT1 OBUFTDS peripheral. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_Clkout1OBufTdsEnable(XHdmiphy1 *InstancePtr, + XHdmiphy1_DirectionType Dir, u8 Enable) +{ + u32 RegVal; + u32 RegOffset; + + if (Dir == XHDMIPHY1_DIR_TX) { + RegOffset = XHDMIPHY1_MISC_TXUSRCLK_REG; + } + else { + RegOffset = XHDMIPHY1_MISC_RXUSRCLK_REG; + } + + /* Read XXUSRCLK MISC register. */ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + + /* Write new value to XXUSRCLK MISC register. */ + if (Enable) { + RegVal |= XHDMIPHY1_MISC_XXUSRCLK_CKOUT1_OEN_MASK; + } + else { + RegVal &= ~XHDMIPHY1_MISC_XXUSRCLK_CKOUT1_OEN_MASK; + } + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); +} + +/*****************************************************************************/ +/** +* This function will initiate a DRP transaction (either read or write). +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 == XHDMIPHY1_DIR_RX), the data pointed to by Val +* will be populated with the u16 value that was read._ +* +******************************************************************************/ +static u32 XHdmiphy1_DrpAccess(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_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 (XHDMIPHY1_ISCMN(ChId)) { + RegOffsetCtrl = XHDMIPHY1_DRP_CONTROL_COMMON_REG; + RegOffsetSts = XHDMIPHY1_DRP_STATUS_COMMON_REG; + } + else if (XHDMIPHY1_ISTXMMCM(ChId)) { + RegOffsetCtrl = XHDMIPHY1_DRP_CONTROL_TXMMCM_REG; + RegOffsetSts = XHDMIPHY1_DRP_STATUS_TXMMCM_REG; + } + else if (XHDMIPHY1_ISRXMMCM(ChId)) { + RegOffsetCtrl = XHDMIPHY1_DRP_CONTROL_RXMMCM_REG; + RegOffsetSts = XHDMIPHY1_DRP_STATUS_RXMMCM_REG; + } + else { + RegOffsetCtrl = XHDMIPHY1_DRP_CONTROL_CH1_REG + + (4 * XHDMIPHY1_CH2IDX(ChId)); + RegOffsetSts = XHDMIPHY1_DRP_STATUS_CH1_REG + + (4 * (XHDMIPHY1_CH2IDX(ChId))); + } + + /* Wait until the DRP status indicates that it is not busy.*/ + Retry = 0; + do { + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + RegOffsetSts); + if (Retry > 150) { + return XST_FAILURE; + } + Retry++; + } while (RegVal & XHDMIPHY1_DRP_STATUS_DRPBUSY_MASK); + + /* Write the command to the channel's DRP. */ + RegVal = (Addr & XHDMIPHY1_DRP_CONTROL_DRPADDR_MASK); + RegVal |= XHDMIPHY1_DRP_CONTROL_DRPEN_MASK; + if (Dir == XHDMIPHY1_DIR_TX) { + /* Enable write. */ + RegVal |= XHDMIPHY1_DRP_CONTROL_DRPWE_MASK; + RegVal |= ((*Val << XHDMIPHY1_DRP_CONTROL_DRPDI_SHIFT) & + XHDMIPHY1_DRP_CONTROL_DRPDI_MASK); + } + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, RegVal); + + /* Wait until the DRP status indicates ready.*/ + Retry = 0; + do { + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + RegOffsetSts); + if (Retry > 150) { + return XST_FAILURE; + } + Retry++; + } while (!(RegVal & XHDMIPHY1_DRP_STATUS_DRPRDY_MASK)); + + if (Dir == XHDMIPHY1_DIR_RX) { + /* Mask non-data out for read. */ + RegVal &= XHDMIPHY1_DRP_STATUS_DRPO_MASK; + /* Populate Val with read contents. */ + *Val = RegVal; + } + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function installs a callback function for the HDMIPHY error conditions +* +* @param InstancePtr is a pointer to the XHdmiphy1 instance. +* @param CallbackFunc is the address to the callback function. +* @param CallbackRef is the user data item that will be passed to the +* callback function when it is invoked. +* +* @return None. +* +* @note The XHdmiphy1_ErrorHandler API calls the registered function in +* ErrorCallback and passes two arguments: 1) CallbackRef +* 2) Error Type as defined by XHdmiphy1_ErrType. +* +* Sample Function Call: +* CallbackFunc(CallbackRef, XHdmiphy1_ErrType); +* +******************************************************************************/ +void XHdmiphy1_SetErrorCallback(XHdmiphy1 *InstancePtr, + void *CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->ErrorCallback = (XHdmiphy1_ErrorCallback)CallbackFunc; + InstancePtr->ErrorRef = CallbackRef; +} + +/*****************************************************************************/ +/** +* +* This function installs an asynchronous callback function for the LogWrite +* API: +* +* @param InstancePtr is a pointer to the XHdmiphy1 instance. +* @param CallbackFunc is the address of the callback function. +* @param CallbackRef is a user data item that will be passed to the +* callback function when it is invoked. +* +* @return None. +* +******************************************************************************/ +void XHdmiphy1_SetLogCallback(XHdmiphy1 *InstancePtr, + u64 *CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + InstancePtr->LogWriteCallback = (XHdmiphy1_LogCallback)CallbackFunc; + InstancePtr->LogWriteRef = CallbackRef; +} + +/*****************************************************************************/ +/** +* This function prints out Video PHY register and GT Channel and Common +* DRP register contents. +* +* @param InstancePtr is a pointer to the Hdmiphy core instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_RegisterDebug(XHdmiphy1 *InstancePtr) +{ + u32 RegOffset; +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + u16 DrpAddr, MaxDrpAddr; + u16 DrpVal, ChId; + u8 MaxChannels; +#endif + + xil_printf("\r\nHDMIPHY Registers\r\n"); + xil_printf("-----------------\r\n"); + xil_printf("Offset | Value\r\n"); + xil_printf("-----------------\r\n"); + for (RegOffset = 0; RegOffset <= 0x334; ) { + xil_printf("0x%04x 0x%08x\r\n",RegOffset, + XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegOffset)); + RegOffset += 4; + } + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) +#if (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE3) + MaxDrpAddr = 0x00B0; +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE4) + MaxDrpAddr = 0x00B0; +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE4) + MaxDrpAddr = 0x00B0; +#endif + + xil_printf("\r\nHDMIPHY GT COMMON DRP Registers\r\n"); + xil_printf("----------------------------\r\n"); + if (InstancePtr->HdmiIsQpllPresent == TRUE) { + xil_printf("Offset | Value\r\n"); + xil_printf("----------------------------\r\n"); + for (DrpAddr = 0x0000; DrpAddr <= MaxDrpAddr; DrpAddr++) { + XHdmiphy1_DrpRd(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CMN0, + DrpAddr, &DrpVal); + xil_printf("0x%04x 0x%04x\r\n",DrpAddr, DrpVal); + } + } else { + xil_printf("No QPLL in this HDMIPHY Instance\r\n"); + } + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE3) + MaxDrpAddr = 0x00CF; +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE4) + MaxDrpAddr = 0x0125; +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE4) + MaxDrpAddr = 0x0135; +#endif + /* Get Max number of channels in HDMIPHY */ + MaxChannels = (InstancePtr->Config.RxChannels > + InstancePtr->Config.TxChannels) ? + InstancePtr->Config.RxChannels : + InstancePtr->Config.TxChannels; + + for (ChId = 1; ChId <= MaxChannels; ChId++) { + xil_printf("\r\nHDMIPHY GT CHANNEL %d DRP Registers\r\n", ChId); + xil_printf("-------------------------------\r\n"); + xil_printf("Offset | Value\r\n"); + xil_printf("-------------------------------\r\n"); + for (DrpAddr = 0x0000; DrpAddr <= MaxDrpAddr; DrpAddr++) { + XHdmiphy1_DrpRd(InstancePtr, 0, ChId, DrpAddr, &DrpVal); + xil_printf("0x%04x 0x%04x\r\n",DrpAddr, DrpVal); + } + } +#endif +} diff --git a/hdmi/phy-xilinx-vphy/xhdmiphy1.h b/hdmi/phy-xilinx-vphy/xhdmiphy1.h new file mode 100644 index 0000000..e566a7a --- /dev/null +++ b/hdmi/phy-xilinx-vphy/xhdmiphy1.h @@ -0,0 +1,1028 @@ +/******************************************************************************* + * + * + * 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 xhdmiphy1.h + * @addtogroup xhdmiphy1_v1_0 + * @{ + * @details + * This is main header file of the Xilinx HDMI PHY Controller driver + * + * Video PHY Controller Overview + * + * The PHY is intended to simplify the use of serial transceivers and adds + * domain-specific configurability. The Video PHY Controller IP is not intended + * to be used as a stand alone IP and must be used with Xilinx Video MACs such + * as HDMI 2.1 Transmitter/Receiver Subsystems. The core enables simpler + * connectivity between MAC layers for TX and RX paths. However, it is still + * important to understand the behavior, usage, and any limitations of the + * transceivers. See the device specific transceiver user guide for details. + * + * Video PHY Controller Driver Features + * + * Video PHY Controller driver supports following features + * - Xilinx HDMI 2.1 MAC IP + * - GTHE3, GTHE4 and GTYE4 GT types + * - HDMI: + * - 4 pixel-wide video interface + * - 8/10/12 bits per component + * - RGB & YCbCr color space + * - Up to 10k resolution at both Input and Output interface + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ *            dd/mm/yy
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   gm   10/12/18 Initial release.
+ * 
+ * +*******************************************************************************/ + +#ifndef XHDMIPHY1_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XHDMIPHY1_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(XV_CONFIG_LOG_HDMIPHY1_DISABLE) && \ + !defined(XV_CONFIG_LOG_DISABLE_ALL) +#define XV_HDMIPHY1_LOG_ENABLE +#endif + +/******************************* Include Files ********************************/ + +#include "xil_assert.h" +#include "xhdmiphy1_hw.h" +#include "xvidc.h" + +/******************* Macros (Inline Functions) Definitions ********************/ + +#define XHDMIPHY1_GTHE3 4 +#define XHDMIPHY1_GTHE4 5 +#define XHDMIPHY1_GTYE4 6 +#define XHDMIPHY1_GTYE5 7 + +/****************************** Type Definitions ******************************/ + +/* This typedef enumerates the different GT types available. */ +typedef enum { + XHDMIPHY1_GT_TYPE_GTHE3 = 4, + XHDMIPHY1_GT_TYPE_GTHE4 = 5, + XHDMIPHY1_GT_TYPE_GTYE4 = 6, + XHDMIPHY1_GT_TYPE_GTYE5 = 7, +} XHdmiphy1_GtType; + +/** + * This typedef enumerates the various protocols handled by the Video PHY + * controller (HDMIPHY). + */ +typedef enum { + XHDMIPHY1_PROTOCOL_HDMI = 1, + XHDMIPHY1_PROTOCOL_HDMI21 = 2, + XHDMIPHY1_PROTOCOL_NONE = 3 +} XHdmiphy1_ProtocolType; + +/* This typedef enumerates is used to specify RX/TX direction information. */ +typedef enum { + XHDMIPHY1_DIR_RX = 0, + XHDMIPHY1_DIR_TX, + XHDMIPHY1_DIR_NONE +} XHdmiphy1_DirectionType; + +/** + * This typedef enumerates the list of available interrupt handler types. The + * values are used as parameters to the XHdmiphy1_SetIntrHandler function. + */ +typedef enum { + XHDMIPHY1_INTR_HANDLER_TYPE_TXRESET_DONE = + XHDMIPHY1_INTR_TXRESETDONE_MASK, + XHDMIPHY1_INTR_HANDLER_TYPE_RXRESET_DONE = + XHDMIPHY1_INTR_RXRESETDONE_MASK, +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + XHDMIPHY1_INTR_HANDLER_TYPE_CPLL_LOCK = + XHDMIPHY1_INTR_CPLL_LOCK_MASK, + XHDMIPHY1_INTR_HANDLER_TYPE_QPLL_LOCK = + XHDMIPHY1_INTR_QPLL_LOCK_MASK, + XHDMIPHY1_INTR_HANDLER_TYPE_QPLL0_LOCK = + XHDMIPHY1_INTR_QPLL_LOCK_MASK, + XHDMIPHY1_INTR_HANDLER_TYPE_TXALIGN_DONE = + XHDMIPHY1_INTR_TXALIGNDONE_MASK, + XHDMIPHY1_INTR_HANDLER_TYPE_QPLL1_LOCK = + XHDMIPHY1_INTR_QPLL1_LOCK_MASK, +#else + XHDMIPHY1_INTR_HANDLER_TYPE_LCPLL_LOCK = + XHDMIPHY1_INTR_LCPLL_LOCK_MASK, + XHDMIPHY1_INTR_HANDLER_TYPE_RPLL_LOCK = + XHDMIPHY1_INTR_RPLL_LOCK_MASK, +#endif + XHDMIPHY1_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE = + XHDMIPHY1_INTR_TXCLKDETFREQCHANGE_MASK, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE = + XHDMIPHY1_INTR_RXCLKDETFREQCHANGE_MASK, + XHDMIPHY1_INTR_HANDLER_TYPE_TX_MMCM_LOCK_CHANGE = + XHDMIPHY1_INTR_TXMMCMUSRCLK_LOCK_MASK, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_MMCM_LOCK_CHANGE = + XHDMIPHY1_INTR_RXMMCMUSRCLK_LOCK_MASK, +#if (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE5) + XHDMIPHY1_INTR_HANDLER_TYPE_TX_GPO_RISING_EDGE = + XHDMIPHY1_INTR_TXGPO_RE_MASK, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_GPO_RISING_EDGE = + XHDMIPHY1_INTR_RXGPO_RE_MASK, +#endif + XHDMIPHY1_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT = + XHDMIPHY1_INTR_TXTMRTIMEOUT_MASK, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT = + XHDMIPHY1_INTR_RXTMRTIMEOUT_MASK, +} XHdmiphy1_IntrHandlerType; + +/** + * This typedef enumerates the list of available hdmi handler types. The + * values are used as parameters to the XHdmiphy1_SetHdmiCallback function. + */ +typedef enum { + XHDMIPHY1_HDMI_HANDLER_TXINIT = 1, /**< TX init handler. */ + XHDMIPHY1_HDMI_HANDLER_TXREADY, /**< TX ready handler. */ + XHDMIPHY1_HDMI_HANDLER_RXINIT, /**< RX init handler. */ + XHDMIPHY1_HDMI_HANDLER_RXREADY /**< RX ready handler. */ +} XHdmiphy1_HdmiHandlerType; + +/** + * This typedef enumerates the different PLL types for a given GT channel. + */ +typedef enum { + XHDMIPHY1_PLL_TYPE_CPLL = 1, + XHDMIPHY1_PLL_TYPE_QPLL = 2, + XHDMIPHY1_PLL_TYPE_QPLL0 = 3, + XHDMIPHY1_PLL_TYPE_QPLL1 = 4, + XHDMIPHY1_PLL_TYPE_LCPLL = 5, + XHDMIPHY1_PLL_TYPE_RPLL = 6, + XHDMIPHY1_PLL_TYPE_UNKNOWN = 7, +} XHdmiphy1_PllType; + +/** + * This typedef enumerates the available channels. + */ +typedef enum { + XHDMIPHY1_CHANNEL_ID_CH1 = 1, + XHDMIPHY1_CHANNEL_ID_CH2 = 2, + XHDMIPHY1_CHANNEL_ID_CH3 = 3, + XHDMIPHY1_CHANNEL_ID_CH4 = 4, + XHDMIPHY1_CHANNEL_ID_CMN0 = 5, /* QPLL, QPLL0, LCPLL */ + XHDMIPHY1_CHANNEL_ID_CMN1 = 6, /* QPLL1, RPLL */ + XHDMIPHY1_CHANNEL_ID_CHA = 7, + XHDMIPHY1_CHANNEL_ID_CMNA = 8, + XHDMIPHY1_CHANNEL_ID_TXMMCM = 9, + XHDMIPHY1_CHANNEL_ID_RXMMCM = 10, + XHDMIPHY1_CHANNEL_ID_CMN = XHDMIPHY1_CHANNEL_ID_CMN0, +} XHdmiphy1_ChannelId; + +/** + * This typedef enumerates the available reference clocks for the PLL clock + * selection multiplexer. + */ +typedef enum { + XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTREFCLK0 = + XHDMIPHY1_REF_CLK_SEL_XPLL_GTREFCLK0, + XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTREFCLK1 = + XHDMIPHY1_REF_CLK_SEL_XPLL_GTREFCLK1, + XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTNORTHREFCLK0 = + XHDMIPHY1_REF_CLK_SEL_XPLL_GTNORTHREFCLK0, + XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTNORTHREFCLK1 = + XHDMIPHY1_REF_CLK_SEL_XPLL_GTNORTHREFCLK1, + XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTSOUTHREFCLK0 = + XHDMIPHY1_REF_CLK_SEL_XPLL_GTSOUTHREFCLK0, + XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTSOUTHREFCLK1 = + XHDMIPHY1_REF_CLK_SEL_XPLL_GTSOUTHREFCLK1, + XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTEASTREFCLK0 = + XHDMIPHY1_REF_CLK_SEL_XPLL_GTEASTREFCLK0, + XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTEASTREFCLK1 = + XHDMIPHY1_REF_CLK_SEL_XPLL_GTEASTREFCLK1, + XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTWESTREFCLK0 = + XHDMIPHY1_REF_CLK_SEL_XPLL_GTWESTREFCLK0, + XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTWESTREFCLK1 = + XHDMIPHY1_REF_CLK_SEL_XPLL_GTWESTREFCLK1, + XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTGREFCLK = + XHDMIPHY1_REF_CLK_SEL_XPLL_GTGREFCLK, +} XHdmiphy1_PllRefClkSelType; + +/** + * This typedef enumerates the available reference clocks used to drive the + * RX/TX datapaths. + */ +typedef enum { + XHDMIPHY1_SYSCLKSELDATA_TYPE_PLL0_OUTCLK = + XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_DATA_PLL0, + XHDMIPHY1_SYSCLKSELDATA_TYPE_PLL1_OUTCLK = + XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_DATA_PLL1, + XHDMIPHY1_SYSCLKSELDATA_TYPE_CPLL_OUTCLK = + XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_DATA_CPLL, + XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL_OUTCLK = + XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL, + XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK = + XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL0, + XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK = + XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL1, +} XHdmiphy1_SysClkDataSelType; + +/** + * This typedef enumerates the available reference clocks used to drive the + * RX/TX output clocks. + */ +typedef enum { + XHDMIPHY1_SYSCLKSELOUT_TYPE_CPLL_REFCLK = + XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_OUT_CH, + XHDMIPHY1_SYSCLKSELOUT_TYPE_QPLL_REFCLK = + XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN, + XHDMIPHY1_SYSCLKSELOUT_TYPE_QPLL0_REFCLK = + XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN0, + XHDMIPHY1_SYSCLKSELOUT_TYPE_QPLL1_REFCLK = + XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN1, + XHDMIPHY1_SYSCLKSELOUT_TYPE_PLL0_REFCLK = + XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_OUT_CH, + XHDMIPHY1_SYSCLKSELOUT_TYPE_PLL1_REFCLK = + XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN, +} XHdmiphy1_SysClkOutSelType; + +/** + * This typedef enumerates the available clocks that are used as multiplexer + * input selections for the RX/TX output clock. + */ +typedef enum { + XHDMIPHY1_OUTCLKSEL_TYPE_OUTCLKPCS = 1, + XHDMIPHY1_OUTCLKSEL_TYPE_OUTCLKPMA, + XHDMIPHY1_OUTCLKSEL_TYPE_PLLREFCLK_DIV1, + XHDMIPHY1_OUTCLKSEL_TYPE_PLLREFCLK_DIV2, + XHDMIPHY1_OUTCLKSEL_TYPE_PROGDIVCLK +} XHdmiphy1_OutClkSelType; + +/* This typedef enumerates the possible states a transceiver can be in. */ +typedef enum { + XHDMIPHY1_GT_STATE_IDLE, /**< Idle state. */ + XHDMIPHY1_GT_STATE_GPO_RE, /**< GPO RE state. */ + XHDMIPHY1_GT_STATE_LOCK, /**< Lock state. */ + XHDMIPHY1_GT_STATE_RESET, /**< Reset state. */ + XHDMIPHY1_GT_STATE_ALIGN, /**< Align state. */ + XHDMIPHY1_GT_STATE_READY, /**< Ready state. */ +} XHdmiphy1_GtState; + +#ifdef XV_HDMIPHY1_LOG_ENABLE +typedef enum { + XHDMIPHY1_LOG_EVT_NONE = 1, /**< Log event none. */ + XHDMIPHY1_LOG_EVT_QPLL_EN, /**< Log event QPLL enable. */ + XHDMIPHY1_LOG_EVT_QPLL_RST, /**< Log event QPLL reset. */ + XHDMIPHY1_LOG_EVT_QPLL_LOCK, /**< Log event QPLL lock. */ + XHDMIPHY1_LOG_EVT_QPLL_RECONFIG, /**< Log event QPLL reconfig. */ + XHDMIPHY1_LOG_EVT_QPLL0_EN, /**< Log event QPLL0 enable. */ + XHDMIPHY1_LOG_EVT_QPLL0_RST, /**< Log event QPLL0 reset. */ + XHDMIPHY1_LOG_EVT_QPLL0_LOCK, /**< Log event QPLL0 lock. */ + XHDMIPHY1_LOG_EVT_QPLL0_RECONFIG,/**< Log event QPLL0 reconfig. */ + XHDMIPHY1_LOG_EVT_QPLL1_EN, /**< Log event QPLL1 enable. */ + XHDMIPHY1_LOG_EVT_QPLL1_RST, /**< Log event QPLL1 reset. */ + XHDMIPHY1_LOG_EVT_QPLL1_LOCK, /**< Log event QPLL1 lock. */ + XHDMIPHY1_LOG_EVT_QPLL1_RECONFIG,/**< Log event QPLL1 reconfig. */ + XHDMIPHY1_LOG_EVT_PLL0_EN, /**< Log event PLL0 reset. */ + XHDMIPHY1_LOG_EVT_PLL0_RST, /**< Log event PLL0 reset. */ + XHDMIPHY1_LOG_EVT_PLL1_EN, /**< Log event PLL1 reset. */ + XHDMIPHY1_LOG_EVT_PLL1_RST, /**< Log event PLL1 reset. */ + XHDMIPHY1_LOG_EVT_CPLL_EN, /**< Log event CPLL reset. */ + XHDMIPHY1_LOG_EVT_CPLL_RST, /**< Log event CPLL reset. */ + XHDMIPHY1_LOG_EVT_CPLL_LOCK, /**< Log event CPLL lock. */ + XHDMIPHY1_LOG_EVT_CPLL_RECONFIG, /**< Log event CPLL reconfig. */ + XHDMIPHY1_LOG_EVT_LCPLL_LOCK, /**< Log event LCPLL lock. */ + XHDMIPHY1_LOG_EVT_RPLL_LOCK, /**< Log event RPLL lock. */ + XHDMIPHY1_LOG_EVT_TXPLL_EN, /**< Log event TXPLL enable. */ + XHDMIPHY1_LOG_EVT_TXPLL_RST, /**< Log event TXPLL reset. */ + XHDMIPHY1_LOG_EVT_RXPLL_EN, /**< Log event RXPLL enable. */ + XHDMIPHY1_LOG_EVT_RXPLL_RST, /**< Log event RXPLL reset. */ + XHDMIPHY1_LOG_EVT_GTRX_RST, /**< Log event GT RX reset. */ + XHDMIPHY1_LOG_EVT_GTTX_RST, /**< Log event GT TX reset. */ + XHDMIPHY1_LOG_EVT_VID_TX_RST, /**< Log event Vid TX reset. */ + XHDMIPHY1_LOG_EVT_VID_RX_RST, /**< Log event Vid RX reset. */ + XHDMIPHY1_LOG_EVT_TX_ALIGN, /**< Log event TX align. */ + XHDMIPHY1_LOG_EVT_TX_ALIGN_TMOUT,/**< Log event TX align Timeout. */ + XHDMIPHY1_LOG_EVT_TX_TMR, /**< Log event TX timer. */ + XHDMIPHY1_LOG_EVT_RX_TMR, /**< Log event RX timer. */ + XHDMIPHY1_LOG_EVT_GT_RECONFIG, /**< Log event GT reconfig. */ + XHDMIPHY1_LOG_EVT_GT_TX_RECONFIG,/**< Log event GT reconfig. */ + XHDMIPHY1_LOG_EVT_GT_RX_RECONFIG,/**< Log event GT reconfig. */ + XHDMIPHY1_LOG_EVT_INIT, /**< Log event init. */ + XHDMIPHY1_LOG_EVT_TXPLL_RECONFIG,/**< Log event TXPLL reconfig. */ + XHDMIPHY1_LOG_EVT_RXPLL_RECONFIG,/**< Log event RXPLL reconfig. */ + XHDMIPHY1_LOG_EVT_RXPLL_LOCK, /**< Log event RXPLL lock. */ + XHDMIPHY1_LOG_EVT_TXPLL_LOCK, /**< Log event TXPLL lock. */ + XHDMIPHY1_LOG_EVT_TX_RST_DONE, /**< Log event TX reset done. */ + XHDMIPHY1_LOG_EVT_RX_RST_DONE, /**< Log event RX reset done. */ + XHDMIPHY1_LOG_EVT_TX_FREQ, /**< Log event TX frequency. */ + XHDMIPHY1_LOG_EVT_RX_FREQ, /**< Log event RX frequency. */ + XHDMIPHY1_LOG_EVT_DRU_EN, /**< Log event DRU enable/disable. */ + XHDMIPHY1_LOG_EVT_TXGPO_RE, /**< Log event TX GPO Rising Edge. */ + XHDMIPHY1_LOG_EVT_RXGPO_RE, /**< Log event RX GPO Rising Edge. */ + XHDMIPHY1_LOG_EVT_FRL_RECONFIG, /**< Log event FRL TX Reconfig. */ + XHDMIPHY1_LOG_EVT_TMDS_RECONFIG, /**< Log event TMDS TX Reconfig. */ + XHDMIPHY1_LOG_EVT_1PPC_ERR, /**< Log event 1 PPC Error. */ + XHDMIPHY1_LOG_EVT_PPC_MSMTCH_ERR,/**< Log event PPC MismatchError. */ + XHDMIPHY1_LOG_EVT_VDCLK_HIGH_ERR,/**< Log evt VidClk > 148.5 MHz. */ + XHDMIPHY1_LOG_EVT_NO_DRU, /**< Log evt Vid not supported no DRU. */ + XHDMIPHY1_LOG_EVT_GT_QPLL_CFG_ERR,/**< Log event QPLL Config not found. */ + XHDMIPHY1_LOG_EVT_GT_CPLL_CFG_ERR,/**< Log evt LCPLL Config not found. */ + XHDMIPHY1_LOG_EVT_GT_LCPLL_CFG_ERR,/**< Log evt RPLL Config not found. */ + XHDMIPHY1_LOG_EVT_GT_RPLL_CFG_ERR,/**< Log event QPLL Config not found. */ + XHDMIPHY1_LOG_EVT_VD_NOT_SPRTD_ERR,/**< Log evt Vid fmt not supported. */ + XHDMIPHY1_LOG_EVT_MMCM_ERR, /**< Log event MMCM Config not found. */ + XHDMIPHY1_LOG_EVT_HDMI20_ERR, /**< Log event HDMI2.0 not supported. */ + XHDMIPHY1_LOG_EVT_NO_QPLL_ERR, /**< Log event QPLL not present. */ + XHDMIPHY1_LOG_EVT_DRU_CLK_ERR, /**< Log event DRU clk wrong freq. */ + XHDMIPHY1_LOG_EVT_USRCLK_ERR, /**< Log event usrclk > 297 MHz. */ + XHDMIPHY1_LOG_EVT_SPDGRDE_ERR, /**< Log event Speed Grade -1 error. */ + XHDMIPHY1_LOG_EVT_DUMMY, /**< Dummy Event should be last */ +} XHdmiphy1_LogEvent; +#endif + +/* This typedef enumerates the different MMCM Dividers */ +typedef enum { + XHDMIPHY1_MMCM_CLKFBOUT_MULT_F, /* M */ + XHDMIPHY1_MMCM_DIVCLK_DIVIDE, /* D */ + XHDMIPHY1_MMCM_CLKOUT_DIVIDE /* On */ +} XHdmiphy1_MmcmDivType; + +/* This typedef enumerates the different MMCM CLKINSEL */ +typedef enum { + XHDMIPHY1_MMCM_CLKINSEL_CLKIN1 = 1, + XHDMIPHY1_MMCM_CLKINSEL_CLKIN2 = 0, +} XHdmiphy1_MmcmClkinsel; + +/* This typedef enumerates the Linerate to TMDS Clock ratio + * for HDMI TX TMDS Clock pattern generator. */ +typedef enum { + XHDMIPHY1_Patgen_Ratio_10 = 0x1, /**< LR:Clock Ratio = 10 */ + XHDMIPHY1_Patgen_Ratio_20 = 0x2, /**< LR:Clock Ratio = 20 */ + XHDMIPHY1_Patgen_Ratio_30 = 0x3, /**< LR:Clock Ratio = 30 */ + XHDMIPHY1_Patgen_Ratio_40 = 0x4, /**< LR:Clock Ratio = 40 */ + XHDMIPHY1_Patgen_Ratio_50 = 0x5, /**< LR:Clock Ratio = 50 */ +} XHdmiphy1_HdmiTx_Patgen; + +/** + * This typedef enumerates the available PRBS patterns available + * from the + */ +typedef enum { + XHDMIPHY1_PRBSSEL_STD_MODE = 0x0, /**< Pattern gen/mon OFF */ + XHDMIPHY1_PRBSSEL_PRBS7 = 0x1, /**< PRBS-7 */ + XHDMIPHY1_PRBSSEL_PRBS9 = 0x2, /**< PRBS-9 */ + XHDMIPHY1_PRBSSEL_PRBS15 = 0x3, /**< PRBS-15 */ + XHDMIPHY1_PRBSSEL_PRBS23 = 0x4, /**< PRBS-23 */ + XHDMIPHY1_PRBSSEL_PRBS31 = 0x5, /**< PRBS-31 */ + XHDMIPHY1_PRBSSEL_PCIE = 0x8, /**< PCIE Compliance Pattern */ + XHDMIPHY1_PRBSSEL_SQUARE_2UI = 0x9, /**< Square wave with 2 UI */ + XHDMIPHY1_PRBSSEL_SQUARE_16UI = 0xA, /**< Square wave with 16 UI */ +} XHdmiphy1_PrbsPattern; + +/******************************************************************************/ +/** + * Callback type which represents the handler for interrupts. + * + * @param InstancePtr is a pointer to the XHdmiphy1 instance. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XHdmiphy1_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 XHdmiphy1 instance. + * @param MicroSeconds is the number of microseconds to be passed to the + * timer function. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XHdmiphy1_TimerHandler)(void *InstancePtr, u32 MicroSeconds); + +/******************************************************************************/ +/** + * Generic callback type. + * + * @param CallbackRef is a pointer to the callback reference. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XHdmiphy1_Callback)(void *CallbackRef); + +/******************************************************************************/ +/** + * Generic callback type. + * + * @param CallbackRef is a pointer to the callback reference. + * + * @note u8 value. + * +*******************************************************************************/ +typedef u64 (*XHdmiphy1_LogCallback)(void *CallbackRef); + +/******************************************************************************/ +/** + * Error callback type. + * + * @param CallbackRef is a pointer to the callback reference. + * + * @note None. + * +*******************************************************************************/ +typedef void (*XHdmiphy1_ErrorCallback)(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; +} XHdmiphy1_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 { + XHdmiphy1_PllParam QpllParams; + XHdmiphy1_PllParam CpllParams; /**< Parameters for a CPLL. */ + XHdmiphy1_PllParam PllParams; + u16 LineRateCfg; + }; + union { + XHdmiphy1_PllRefClkSelType CpllRefClkSel; + /**< Multiplexer selection for + the reference clock of + the CPLL. */ + XHdmiphy1_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 { + XHdmiphy1_GtState RxState; /**< Current state of RX GT. */ + XHdmiphy1_GtState TxState; /**< Current state of TX GT. */ + }; + XHdmiphy1_GtState GtState[2]; + }; + union { + struct { + XHdmiphy1_ProtocolType RxProtocol; + /**< The protocol which the RX + path is used for. */ + XHdmiphy1_ProtocolType TxProtocol; + /**< The protocol which the TX + path is used for. */ + }; + XHdmiphy1_ProtocolType Protocol[2]; + }; + union { + struct { + XHdmiphy1_SysClkDataSelType RxDataRefClkSel; + /**< Multiplexer selection for + the reference clock of + the RX datapath. */ + XHdmiphy1_SysClkDataSelType TxDataRefClkSel; + /**< Multiplexer selection for + the reference clock of + the TX datapath. */ + }; + XHdmiphy1_SysClkDataSelType DataRefClkSel[2]; + }; + union { + struct { + XHdmiphy1_SysClkOutSelType RxOutRefClkSel; + /**< Multiplexer selection for + the reference clock of + the RX output clock. */ + XHdmiphy1_SysClkOutSelType TxOutRefClkSel; + /**< Multiplexer selection for + the reference clock of + the TX output clock. */ + }; + XHdmiphy1_SysClkOutSelType OutRefClkSel[2]; + }; + union { + struct { + XHdmiphy1_OutClkSelType RxOutClkSel; + /**< Multiplexer selection for + which clock to use as + the RX output clock. */ + XHdmiphy1_OutClkSelType TxOutClkSel; + /**< Multiplexer selection for + which clock to use as + the TX output clock. */ + }; + XHdmiphy1_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. */ +} XHdmiphy1_Channel; + +/** + * This typedef contains configuration information for MMCM programming. + */ +typedef struct { + u16 DivClkDivide; + u16 ClkFbOutMult; + u16 ClkFbOutFrac; + u16 ClkOut0Div; + u16 ClkOut0Frac; + u16 ClkOut1Div; + u16 ClkOut2Div; +} XHdmiphy1_Mmcm; + +/** + * This typedef represents a GT quad. + */ +typedef struct { + union { + struct { + XHdmiphy1_Mmcm RxMmcm; /**< Mixed-mode clock manager + (MMCM) parameters for + RX. */ + XHdmiphy1_Mmcm TxMmcm; /**< MMCM parameters for TX. */ + }; + XHdmiphy1_Mmcm Mmcm[2]; /**< MMCM parameters. */ + }; + union { + struct { + XHdmiphy1_Channel Ch1; + XHdmiphy1_Channel Ch2; + XHdmiphy1_Channel Ch3; + XHdmiphy1_Channel Ch4; + union { + XHdmiphy1_Channel Cmn0; + XHdmiphy1_Channel Lcpll; + }; + union { + XHdmiphy1_Channel Cmn1; + XHdmiphy1_Channel Rpll; + }; + }; + XHdmiphy1_Channel Plls[6]; + }; + union { + struct { + u32 GtRefClk0Hz; + u32 GtRefClk1Hz; + u32 GtNorthRefClk0Hz; + u32 GtNorthRefClk1Hz; + u32 GtSouthRefClk0Hz; + u32 GtSouthRefClk1Hz; + u32 GtgRefClkHz; + }; + u32 RefClkHz[7]; + }; +} XHdmiphy1_Quad; + +#ifdef XV_HDMIPHY1_LOG_ENABLE +/** + * This typedef contains the logging mechanism for debug. + */ +typedef struct { + u16 DataBuffer[128]; /**< Log buffer with event data. */ + u64 TimeRecord[128]; /**< Log time for the event */ + u8 HeadIndex; /**< Index of the head entry of the + Event/DataBuffer. */ + u8 TailIndex; /**< Index of the tail entry of the + Event/DataBuffer. */ +} XHdmiphy1_Log; +#endif + +/** + * This typedef contains the HDMI 2.1 FRL configurations. + */ +typedef struct { + u8 IsEnabled; /**< Is HDMI operation is enabled? */ + u64 LineRate; /**< Linerate in bps. */ + u8 NChannels; /**< No of Channels. */ +} XHdmiphy1_Hdmi21Cfg; + +/** + * 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. */ + XHdmiphy1_GtType XcvrType; /**< HDMIPHY Transceiver Type */ + u8 TxChannels; /**< No. of active channels in TX */ + u8 RxChannels; /**< No. of active channels in RX */ + XHdmiphy1_ProtocolType TxProtocol; /**< Protocol which TX is used for. */ + XHdmiphy1_ProtocolType RxProtocol; /**< Protocol which RX is used for. */ + XHdmiphy1_PllRefClkSelType TxRefClkSel; /**< TX REFCLK selection. */ + XHdmiphy1_PllRefClkSelType RxRefClkSel; /**< RX REFCLK selection. */ + XHdmiphy1_PllRefClkSelType TxFrlRefClkSel; /**< TX FRL REFCLK selection. */ + XHdmiphy1_PllRefClkSelType RxFrlRefClkSel; /**< RX FRL REFCLK selection. */ + XHdmiphy1_SysClkDataSelType TxSysPllClkSel; /**< TX SYSCLK selection. */ + XHdmiphy1_SysClkDataSelType RxSysPllClkSel; /**< RX SYSCLK selectino. */ + u8 DruIsPresent; /**< A data recovery unit (DRU) exists + in the design .*/ + XHdmiphy1_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 */ + u32 DrpClkFreq; /**< DRP Clock Frequency in Hz */ + u8 UseGtAsTxTmdsClk; /**< Use 4th GT channel as TX TMDS clock */ +} XHdmiphy1_Config; + +/* Forward declaration. */ +struct XHdmiphy1_GtConfigS; + +/** + * The XHdmiphy1 driver instance data. The user is required to allocate a + * variable of this type for every XHdmiphy1 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. */ + XHdmiphy1_Config Config; /**< Configuration structure for + the Video PHY core. */ + const struct XHdmiphy1_GtConfigS *GtAdaptor; +#ifdef XV_HDMIPHY1_LOG_ENABLE + XHdmiphy1_Log Log; /**< A log of events. */ +#endif + XHdmiphy1_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. */ + u8 HdmiIsQpllPresent; /**< QPLL is present in HW */ + XHdmiphy1_Hdmi21Cfg TxHdmi21Cfg; /**< TX HDMI Config */ + XHdmiphy1_Hdmi21Cfg RxHdmi21Cfg; /**< TX HDMI Config */ +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + XHdmiphy1_IntrHandler IntrCpllLockHandler; /**< Callback function for CPLL + lock interrupts. */ + void *IntrCpllLockCallbackRef; /**< A pointer to the user data + passed to the CPLL lock + callback function. */ + XHdmiphy1_IntrHandler IntrQpllLockHandler; /**< Callback function for QPLL + lock interrupts. */ + void *IntrQpllLockCallbackRef; /**< A pointer to the user data + passed to the QPLL lock + callback function. */ + XHdmiphy1_IntrHandler IntrQpll1LockHandler; /**< Callback function for QPLL + lock interrupts. */ + void *IntrQpll1LockCallbackRef; /**< A pointer to the user data + passed to the QPLL lock + callback function. */ + XHdmiphy1_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. */ +#else + XHdmiphy1_IntrHandler IntrLcpllLockHandler; /**< Callback function for + LCPLL lock interrupts. */ + void *IntrLcpllLockCallbackRef; /**< A pointer to the user data + passed to the LCPLL lock callback function. */ + XHdmiphy1_IntrHandler IntrRpllLockHandler; /**< Callback function for + RPLL lock interrupts. */ + void *IntrRpllLockCallbackRef; /**< A pointer to the user data + passed to the RPLL lock callback function. */ + XHdmiphy1_IntrHandler IntrTxGpoRisingEdgeHandler; /**< Callback function + for TX GPO [3:0] Rising Edge. */ + void *IntrTxGpoRisingEdgeCallbackRef; /**< A pointer to the user data + passed to the TX GPO [3:0] Rising Edge + callback function. */ + XHdmiphy1_IntrHandler IntrRxGpoRisingEdgeHandler; /**< Callback function + for RX GPO [7:4] Rising Edge. */ + void *IntrRxGpoRisingEdgeCallbackRef; /**< A pointer to the user data + passed to the RX GPO [7:4] Rising Edge + callback function. */ +#endif + XHdmiphy1_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. */ + XHdmiphy1_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. */ + XHdmiphy1_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. */ + XHdmiphy1_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. */ + XHdmiphy1_IntrHandler IntrTxMmcmLockHandler; /**< Callback function + for TX MMCM lock + interrupts. */ + void *IntrTxMmcmLockCallbackRef; /**< A pointer to the user data + passed to the TX MMCM lock + callback function. */ + XHdmiphy1_IntrHandler IntrRxMmcmLockHandler; /**< Callback function + for RX MMCM lock + interrupts. */ + void *IntrRxMmcmLockCallbackRef; /**< A pointer to the user data + passed to the RX MMCM lock + callback function. */ + XHdmiphy1_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. */ + XHdmiphy1_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. */ + /* Error Condition callbacks. */ + XHdmiphy1_ErrorCallback ErrorCallback; /**< Callback for Error Condition.*/ + void *ErrorRef; /**< To be passed to the Error condition + callback. */ + XHdmiphy1_ErrorCallback PllLayoutErrorCallback; /**< Callback for Error + Condition. */ + void *PllLayoutErrorRef;/**< To be passed to the Error condition + callback. */ + /* HDMI callbacks. */ + XHdmiphy1_Callback HdmiTxInitCallback; /**< Callback for TX init. */ + void *HdmiTxInitRef; /**< To be passed to the TX init + callback. */ + XHdmiphy1_Callback HdmiTxReadyCallback; /**< Callback for TX ready. */ + void *HdmiTxReadyRef; /**< To be passed to the TX + ready callback. */ + XHdmiphy1_Callback HdmiRxInitCallback; /**< Callback for RX init. */ + void *HdmiRxInitRef; /**< To be passed to the RX + init callback. */ + XHdmiphy1_Callback HdmiRxReadyCallback; /**< Callback for RX ready. */ + void *HdmiRxReadyRef; /**< To be passed to the RX + ready callback. */ + XHdmiphy1_LogCallback LogWriteCallback; /**< Callback for log write */ + u32 *LogWriteRef; /**< To be passed to the log write callback */ + XHdmiphy1_TimerHandler UserTimerWaitUs; /**< Custom user function for + delay/sleep. */ + void *UserTimerPtr; /**< Pointer to a timer instance + used by the custom user + delay/sleep function. */ +} XHdmiphy1; + +/**************************** Function Prototypes *****************************/ + +/* xhdmiphy1.c: Setup and initialization functions. */ +void XHdmiphy1_CfgInitialize(XHdmiphy1 *InstancePtr, + XHdmiphy1_Config *ConfigPtr, + UINTPTR EffectiveAddr); +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) +u32 XHdmiphy1_PllInitialize(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, + XHdmiphy1_PllRefClkSelType QpllRefClkSel, + XHdmiphy1_PllRefClkSelType CpllxRefClkSel, + XHdmiphy1_PllType TxPllSelect, XHdmiphy1_PllType RxPllSelect); +#endif +u32 XHdmiphy1_GetVersion(XHdmiphy1 *InstancePtr); +void XHdmiphy1_WaitUs(XHdmiphy1 *InstancePtr, u32 MicroSeconds); +void XHdmiphy1_SetUserTimerHandler(XHdmiphy1 *InstancePtr, + XHdmiphy1_TimerHandler CallbackFunc, void *CallbackRef); + +/* xhdmiphy1.c: Channel configuration functions - setters. */ +u32 XHdmiphy1_CfgLineRate(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, u64 LineRateHz); + +/* xhdmiphy1.c: Channel configuration functions - getters. */ +XHdmiphy1_PllType XHdmiphy1_GetPllType(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, XHdmiphy1_ChannelId ChId); +u64 XHdmiphy1_GetLineRateHz(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId); + +/* xhdmiphy1.c: Reset functions. */ +u32 XHdmiphy1_ResetGtPll(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, u8 Hold); +u32 XHdmiphy1_ResetGtTxRx(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, u8 Hold); + +/* xhdmiphy1.c: TX|RX Control functions. */ +u32 XHdmiphy1_SetPolarity(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, u8 Polarity); +u32 XHdmiphy1_SetPrbsSel(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, + XHdmiphy1_PrbsPattern Pattern); +u32 XHdmiphy1_TxPrbsForceError(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, u8 ForceErr); +void XHdmiphy1_SetTxVoltageSwing(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, u8 Vs); +void XHdmiphy1_SetTxPreEmphasis(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, u8 Pe); +void XHdmiphy1_SetTxPostCursor(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, u8 Pc); +void XHdmiphy1_SetRxLpm(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, u8 Enable); + +/* xhdmiphy1.c: GT/MMCM DRP access. */ +u32 XHdmiphy1_DrpWr(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, u16 Addr, u16 Val); +u16 XHdmiphy1_DrpRd(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, u16 Addr, u16 *RetVal); +void XHdmiphy1_MmcmPowerDown(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, u8 Hold); +void XHdmiphy1_MmcmStart(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir); +void XHdmiphy1_IBufDsEnable(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, u8 Enable); +void XHdmiphy1_Clkout1OBufTdsEnable(XHdmiphy1 *InstancePtr, + XHdmiphy1_DirectionType Dir, u8 Enable); + +/* xhdmiphy1.c: Error Condition. */ +void XHdmiphy1_SetErrorCallback(XHdmiphy1 *InstancePtr, + void *CallbackFunc, void *CallbackRef); + +/* xhdmiphy1_log.c: Logging functions. */ +void XHdmiphy1_SetLogCallback(XHdmiphy1 *InstancePtr, + u64 *CallbackFunc, void *CallbackRef); +int XHdmiphy1_LogShow(XHdmiphy1 *InstancePtr, char *buff, int buff_size); +void XHdmiphy1_LogReset(XHdmiphy1 *InstancePtr); +u16 XHdmiphy1_LogRead(XHdmiphy1 *InstancePtr); +#ifdef XV_HDMIPHY1_LOG_ENABLE +void XHdmiphy1_LogWrite(XHdmiphy1 *InstancePtr, XHdmiphy1_LogEvent Evt, + u8 Data); +#else +#define XHdmiphy1_LogWrite(...) +#endif + +/* xhdmiphy1_intr.c: Interrupt handling functions. */ +void XHdmiphy1_InterruptHandler(XHdmiphy1 *InstancePtr); + +/* xhdmiphy1_selftest.c: Self test function. */ +u32 XHdmiphy1_SelfTest(XHdmiphy1 *InstancePtr); + +/* xhdmiphy1_sinit.c: Configuration extraction function. */ +XHdmiphy1_Config *XHdmiphy1_LookupConfig(u16 DeviceId); + +/* xhdmiphy1_hdmi.c, xhdmiphy1_hdmi_intr.c: Protocol specific functions. */ +u32 XHdmiphy1_Hdmi_CfgInitialize(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_Config *CfgPtr); +u32 XHdmiphy1_SetHdmiTxParam(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, + XVidC_PixelsPerClock Ppc, XVidC_ColorDepth Bpc, + XVidC_ColorFormat ColorFormat); +u32 XHdmiphy1_SetHdmiRxParam(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId); + +u32 XHdmiphy1_HdmiCfgCalcMmcmParam(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, + XVidC_PixelsPerClock Ppc, XVidC_ColorDepth Bpc); + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) +void XHdmiphy1_HdmiUpdateClockSelection(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_SysClkDataSelType TxSysPllClkSel, + XHdmiphy1_SysClkDataSelType RxSysPllClkSel); +#endif +void XHdmiphy1_ClkDetFreqReset(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir); +u32 XHdmiphy1_ClkDetGetRefClkFreqHz(XHdmiphy1 *InstancePtr, + XHdmiphy1_DirectionType Dir); +u32 XHdmiphy1_DruGetRefClkFreqHz(XHdmiphy1 *InstancePtr); +int XHdmiphy1_HdmiDebugInfo(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, char *buff, int buff_size); +void XHdmiphy1_SetHdmiCallback(XHdmiphy1 *InstancePtr, + XHdmiphy1_HdmiHandlerType HandlerType, + void *CallbackFunc, void *CallbackRef); +u32 XHdmiphy1_Hdmi20Config(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir); +u32 XHdmiphy1_Hdmi21Config(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, + u64 LineRate, u8 NChannels); +void XHdmiphy1_RegisterDebug(XHdmiphy1 *InstancePtr); + +/******************* Macros (Inline Functions) Definitions ********************/ + +#define XHDMIPHY1_CH2IDX(Id) ((Id) - XHDMIPHY1_CHANNEL_ID_CH1) +#define XHDMIPHY1_ISCH(Id) (((Id) == XHDMIPHY1_CHANNEL_ID_CHA) || \ + ((XHDMIPHY1_CHANNEL_ID_CH1 <= (Id)) && ((Id) <= XHDMIPHY1_CHANNEL_ID_CH4))) +#define XHDMIPHY1_ISCMN(Id) (((Id) == XHDMIPHY1_CHANNEL_ID_CMNA) || \ + ((XHDMIPHY1_CHANNEL_ID_CMN0 <= (Id)) && ((Id) <= XHDMIPHY1_CHANNEL_ID_CMN1))) +#define XHDMIPHY1_ISTXMMCM(Id) ((Id) == XHDMIPHY1_CHANNEL_ID_TXMMCM) +#define XHDMIPHY1_ISRXMMCM(Id) ((Id) == XHDMIPHY1_CHANNEL_ID_RXMMCM) + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) +#define XHdmiphy1_IsTxUsingQpll(InstancePtr, QuadId, ChId) \ + ((XHDMIPHY1_PLL_TYPE_QPLL == \ + XHdmiphy1_GetPllType(InstancePtr, QuadId, XHDMIPHY1_DIR_TX, ChId)) || \ + (XHDMIPHY1_PLL_TYPE_QPLL0 == \ + XHdmiphy1_GetPllType(InstancePtr, QuadId, XHDMIPHY1_DIR_TX, ChId)) || \ + (XHDMIPHY1_PLL_TYPE_QPLL1 == \ + XHdmiphy1_GetPllType(InstancePtr, QuadId, XHDMIPHY1_DIR_TX, ChId))) +#define XHdmiphy1_IsRxUsingQpll(InstancePtr, QuadId, ChId) \ + ((XHDMIPHY1_PLL_TYPE_QPLL == \ + XHdmiphy1_GetPllType(InstancePtr, QuadId, XHDMIPHY1_DIR_RX, ChId)) || \ + (XHDMIPHY1_PLL_TYPE_QPLL0 == \ + XHdmiphy1_GetPllType(InstancePtr, QuadId, XHDMIPHY1_DIR_RX, ChId)) || \ + (XHDMIPHY1_PLL_TYPE_QPLL1 == \ + XHdmiphy1_GetPllType(InstancePtr, QuadId, XHDMIPHY1_DIR_RX, ChId))) +#define XHdmiphy1_IsTxUsingCpll(InstancePtr, QuadId, ChId) \ + (XHDMIPHY1_PLL_TYPE_CPLL == \ + XHdmiphy1_GetPllType(InstancePtr, QuadId, XHDMIPHY1_DIR_TX, ChId)) +#define XHdmiphy1_IsRxUsingCpll(InstancePtr, QuadId, ChId) \ + (XHDMIPHY1_PLL_TYPE_CPLL == \ + XHdmiphy1_GetPllType(InstancePtr, QuadId, XHDMIPHY1_DIR_RX, ChId)) +#else +#define XHdmiphy1_IsTxUsingLcpll(InstancePtr, QuadId, ChId) \ + (XHDMIPHY1_PLL_TYPE_LCPLL == \ + XHdmiphy1_GetPllType(InstancePtr, QuadId, XHDMIPHY1_DIR_TX, ChId)) +#define XHdmiphy1_IsRxUsingLcpll(InstancePtr, QuadId, ChId) \ + (XHDMIPHY1_PLL_TYPE_LCPLL == \ + XHdmiphy1_GetPllType(InstancePtr, QuadId, XHDMIPHY1_DIR_RX, ChId)) +#define XHdmiphy1_IsTxUsingRpll(InstancePtr, QuadId, ChId) \ + (XHDMIPHY1_PLL_TYPE_RPLL == \ + XHdmiphy1_GetPllType(InstancePtr, QuadId, XHDMIPHY1_DIR_TX, ChId)) +#define XHdmiphy1_IsRxUsingRpll(InstancePtr, QuadId, ChId) \ + (XHDMIPHY1_PLL_TYPE_RPLL == \ + XHdmiphy1_GetPllType(InstancePtr, QuadId, XHDMIPHY1_DIR_RX, ChId)) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XHDMIPHY1_H_ */ +/** @} */ diff --git a/hdmi/phy-xilinx-vphy/xhdmiphy1_gt.h b/hdmi/phy-xilinx-vphy/xhdmiphy1_gt.h new file mode 100644 index 0000000..8d68e3e --- /dev/null +++ b/hdmi/phy-xilinx-vphy/xhdmiphy1_gt.h @@ -0,0 +1,127 @@ +/******************************************************************************* + * + * + * 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 xhdmiphy1_gt.h + * + * The Xilinx HDMI PHY (HDMIPHY) driver. This driver supports the + * Xilinx HDMI PHY IP core. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ *            dd/mm/yy
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   gm   10/12/18 Initial release.
+ * 
+ * + * @addtogroup xhdmiphy1_v1_0 + * @{ +*******************************************************************************/ + +#ifndef XHDMIPHY1_GT_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XHDMIPHY1_GT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************* Include Files ********************************/ + +#include "xhdmiphy1.h" +#include "xhdmiphy1_i.h" +#include "xil_assert.h" + +/****************************** Type Definitions ******************************/ + +typedef struct { + const u8 *M; + const u8 *N1; + const u8 *N2; + const u8 *D; +} XHdmiphy1_GtPllDivs; + +typedef struct XHdmiphy1_GtConfigS { + u32 (*CfgSetCdr)(XHdmiphy1 *, u8, XHdmiphy1_ChannelId); + u32 (*CheckPllOpRange)(XHdmiphy1 *, u8, XHdmiphy1_ChannelId, u64); + u32 (*OutDivChReconfig)(XHdmiphy1 *, u8, XHdmiphy1_ChannelId, + XHdmiphy1_DirectionType); + u32 (*ClkChReconfig)(XHdmiphy1 *, u8, XHdmiphy1_ChannelId); + u32 (*ClkCmnReconfig)(XHdmiphy1 *, u8, XHdmiphy1_ChannelId); + u32 (*RxChReconfig)(XHdmiphy1 *, u8, XHdmiphy1_ChannelId); + u32 (*TxChReconfig)(XHdmiphy1 *, u8, XHdmiphy1_ChannelId); + + XHdmiphy1_GtPllDivs CpllDivs; + XHdmiphy1_GtPllDivs QpllDivs; +} XHdmiphy1_GtConfig; + +/******************* Macros (Inline Functions) Definitions ********************/ +#ifdef __cplusplus +u32 XHdmiphy1_CfgSetCdr(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId); +u32 XHdmiphy1_CheckPllOpRange(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, u64 PllClkOutFreqHz); +u32 XHdmiphy1_OutDivChReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir); +u32 XHdmiphy1_ClkChReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId); +u32 XHdmiphy1_ClkCmnReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId); +u32 XHdmiphy1_RxChReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId); +u32 XHdmiphy1_TxChReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId); +#else +#define XHdmiphy1_CfgSetCdr(Ip, ...) \ + ((Ip)->GtAdaptor->CfgSetCdr(Ip, __VA_ARGS__)) +#define XHdmiphy1_CheckPllOpRange(Ip, ...) \ + ((Ip)->GtAdaptor->CheckPllOpRange(Ip, __VA_ARGS__)) +#define XHdmiphy1_OutDivChReconfig(Ip, ...) \ + ((Ip)->GtAdaptor->OutDivChReconfig(Ip, __VA_ARGS__)) +#define XHdmiphy1_ClkChReconfig(Ip, ...) \ + ((Ip)->GtAdaptor->ClkChReconfig(Ip, __VA_ARGS__)) +#define XHdmiphy1_ClkCmnReconfig(Ip, ...) \ + ((Ip)->GtAdaptor->ClkCmnReconfig(Ip, __VA_ARGS__)) +#define XHdmiphy1_RxChReconfig(Ip, ...) \ + ((Ip)->GtAdaptor->RxChReconfig(Ip, __VA_ARGS__)) +#define XHdmiphy1_TxChReconfig(Ip, ...) \ + ((Ip)->GtAdaptor->TxChReconfig(Ip, __VA_ARGS__)) +#endif + +/*************************** Variable Declarations ****************************/ + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE3) +extern const XHdmiphy1_GtConfig Gthe3Config; +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE4) +extern const XHdmiphy1_GtConfig Gthe4Config; +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE4) +extern const XHdmiphy1_GtConfig Gtye4Config; +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE5) +extern const XHdmiphy1_GtConfig Gtye5Config; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XHDMIPHY1_GT_H_ */ +/** @} */ \ No newline at end of file diff --git a/hdmi/phy-xilinx-vphy/xhdmiphy1_gtye5.c b/hdmi/phy-xilinx-vphy/xhdmiphy1_gtye5.c new file mode 100644 index 0000000..1f154c2 --- /dev/null +++ b/hdmi/phy-xilinx-vphy/xhdmiphy1_gtye5.c @@ -0,0 +1,620 @@ +/******************************************************************************* + * + * + * 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 xhdmiphy1_gtye4.c + * + * Contains a minimal set of functions for the XHdmiphy1 driver that allow + * access to all of the Video PHY core's functionality. See xhdmiphy1.h for a + * detailed description of the driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ *            dd/mm/yy
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   gm   10/12/18 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xhdmiphy1_gt.h" +#if (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE5) +#include "xstatus.h" + +/**************************** Function Prototypes *****************************/ + +u32 XHdmiphy1_Gtye5RxChReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId); +u32 XHdmiphy1_Gtye5TxChReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId); + +/************************** Constant Definitions ******************************/ +/* PLL operating ranges. */ +#define XHDMIPHY1_LCPLL_MIN 8000000000LL +#define XHDMIPHY1_LCPLL_MAX 16375000000LL +#define XHDMIPHY1_LCPLL_MIN_REFCLK 120000000LL +#define XHDMIPHY1_RPLL_MIN 4000000000LL +#define XHDMIPHY1_RPLL_MAX 8000000000LL +#define XHDMIPHY1_RPLL_MIN_REFCLK 120000000LL +#define XHDMIPHY1_HDMI_GTYE5_DRU_LRATE 3000000000U + + +const XHdmiphy1_GtConfig Gtye5Config = { +/* .CfgSetCdr = XHdmiphy1_Gtye4CfgSetCdr, + .CheckPllOpRange = XHdmiphy1_Gtye4CheckPllOpRange, + .OutDivChReconfig = XHdmiphy1_Gtye4OutDivChReconfig, + .ClkChReconfig = XHdmiphy1_Gtye4ClkChReconfig, + .ClkCmnReconfig = XHdmiphy1_Gtye4ClkCmnReconfig, */ + .RxChReconfig = XHdmiphy1_Gtye5RxChReconfig, + .TxChReconfig = XHdmiphy1_Gtye5TxChReconfig, + + .CpllDivs = { + .M = 0, + .N1 = 0, + .N2 = 0, + .D = 0, + }, + .QpllDivs = { + .M = 0, + .N1 = 0, + .N2 = 0, + .D = 0, + }, +}; + +/**************************** Function Definitions ****************************/ + +/*****************************************************************************/ +/** +* This function calculates the LCPLL 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 LCPLL parameters updated +* successfully. +* - XST_FAILURE if parameters not updated. +* +* @note None. +* +******************************************************************************/ +u32 XHdmiphy1_HdmiLcpllParam(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir) +{ + u32 Status = XST_SUCCESS; + u32 *RefClkPtr; + u8 TmdsClockRatio = 0; + u8 IsHdmi21 = 0; + u64 LineRate = 0; + + /* Suppress Warning Messages */ + ChId = ChId; + + + /* Pre-calculation. */ + if (Dir == XHDMIPHY1_DIR_RX) { + RefClkPtr = &InstancePtr->HdmiRxRefClkHz; + IsHdmi21 = InstancePtr->RxHdmi21Cfg.IsEnabled; + TmdsClockRatio = InstancePtr->HdmiRxTmdsClockRatio; + + /* Calculate Line Rate */ + if (IsHdmi21) { + LineRate = InstancePtr->RxHdmi21Cfg.LineRate; + } + else { + LineRate = (u64)(*RefClkPtr) * ((TmdsClockRatio ? 40 : 10)); + } + + /* Disable DRU */ + InstancePtr->HdmiRxDruIsEnabled = 0; + + /* Enable DRU based on incoming REFCLK */ + if ((!IsHdmi21) && (!TmdsClockRatio) && + (InstancePtr->HdmiRxRefClkHz < XHDMIPHY1_LCPLL_MIN_REFCLK)) { + if (InstancePtr->Config.DruIsPresent) { + /* Check DRU frequency */ + if (XHdmiphy1_DruGetRefClkFreqHz(InstancePtr) == XST_FAILURE) { + XHdmiphy1_LogWrite(InstancePtr, + XHDMIPHY1_LOG_EVT_DRU_CLK_ERR, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + return (XST_FAILURE); + } + + InstancePtr->HdmiRxDruIsEnabled = 1; + LineRate = XHDMIPHY1_HDMI_GTYE5_DRU_LRATE; + } + else { + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_NO_DRU, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + return (XST_FAILURE); + } + } + } + else { + RefClkPtr = &InstancePtr->HdmiTxRefClkHz; + IsHdmi21 = InstancePtr->TxHdmi21Cfg.IsEnabled; + InstancePtr->HdmiTxSampleRate = 1; + + if (!IsHdmi21) { + /* Determine if HDMI 2.0 Mode */ + if (*RefClkPtr >= 340000000) { + TmdsClockRatio = 1; + (*RefClkPtr) = (*RefClkPtr) / 4; + } + /* Check for x1 Over Sampling Mode*/ + else if (*RefClkPtr >= 124990000) { + InstancePtr->HdmiTxSampleRate = 1; + } + /* Check for x2 Over Sampling Mode*/ + else if (*RefClkPtr >= 99000000) { + InstancePtr->HdmiTxSampleRate = 2; + (*RefClkPtr) = (*RefClkPtr) * 2; + } + /* Check for x3 Over Sampling Mode*/ + else if (*RefClkPtr >= 59400000) { + InstancePtr->HdmiTxSampleRate = 3; + (*RefClkPtr) = (*RefClkPtr) * 3; + } + /* Check for x5 Over Sampling Mode*/ + else if (*RefClkPtr < 59400000) { + InstancePtr->HdmiTxSampleRate = 5; + (*RefClkPtr) = (*RefClkPtr) * 5; + } + } + + /* Calculate Line Rate */ + if (IsHdmi21) { + LineRate = InstancePtr->TxHdmi21Cfg.LineRate; + } + else { + LineRate = (u64)(*RefClkPtr) * ((TmdsClockRatio ? 40 : 10)); + } + + } + + /* Check for DRU mode */ + if ((Dir == XHDMIPHY1_DIR_RX) && + (InstancePtr->HdmiRxDruIsEnabled)) { + InstancePtr->Quads[0].Lcpll.LineRateCfg = 0; + } + /* Check for HDMI 1.4/2.0 GT LineRate Config */ + else if (!IsHdmi21) { + /* HDMI 1.4 */ + if (!TmdsClockRatio) { + if ((119990000 <= (*RefClkPtr)) && + ((*RefClkPtr) <= 204687500)) { + InstancePtr->Quads[0].Lcpll.LineRateCfg = 1; + } + else if ((204687500 <= (*RefClkPtr)) && + /* 297 MHz + 0.5% + 10 KHz error */ + ((*RefClkPtr) <= 298500000)) { + InstancePtr->Quads[0].Lcpll.LineRateCfg = 2; + } + else{ + Status = XST_FAILURE; + } + } + /* HDMI 2.0 */ + else { + if ((84570000 <= (*RefClkPtr)) && + ((*RefClkPtr) <= 102343750)) { + InstancePtr->Quads[0].Lcpll.LineRateCfg = 3; + } + else if ((102343750 <= (*RefClkPtr)) && + ((*RefClkPtr) <= 149500000)) { + InstancePtr->Quads[0].Lcpll.LineRateCfg = 4; + } + else{ + Status = XST_FAILURE; + } + } + } + /* Check for HDMI 2.1 GT LineRate Config */ + else if (IsHdmi21) { + if (LineRate == 3000000000) { + InstancePtr->Quads[0].Lcpll.LineRateCfg = 5; + } + else if (LineRate == 6000000000) { + InstancePtr->Quads[0].Lcpll.LineRateCfg = 6; + } + else if (LineRate == 8000000000) { + InstancePtr->Quads[0].Lcpll.LineRateCfg = 7; + } + else if (LineRate == 10000000000) { + InstancePtr->Quads[0].Lcpll.LineRateCfg = 8; + } + else if (LineRate == 12000000000) { + InstancePtr->Quads[0].Lcpll.LineRateCfg = 9; + } + else { + Status = XST_FAILURE; + } + } + + /* Update Line Rate Value */ + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, + /* LCPLL is CMN0 */ + XHDMIPHY1_CHANNEL_ID_CMN0, LineRate); + + if (Status == XST_FAILURE) { + XHdmiphy1_LogWrite(InstancePtr, + XHDMIPHY1_LOG_EVT_GT_LCPLL_CFG_ERR, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function calculates the RPLL 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 RPLL parameters updated +* successfully. +* - XST_FAILURE if parameters not updated. +* +* @note None. +* +******************************************************************************/ +u32 XHdmiphy1_HdmiRpllParam(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir) +{ + u32 Status = XST_SUCCESS; + u32 *RefClkPtr; + u8 TmdsClockRatio = 0; + u8 IsHdmi21 = 0; + u64 LineRate = 0; + + /* Suppress Warning Messages */ + ChId = ChId; + + + /* Pre-calculation. */ + if (Dir == XHDMIPHY1_DIR_RX) { + RefClkPtr = &InstancePtr->HdmiRxRefClkHz; + IsHdmi21 = InstancePtr->RxHdmi21Cfg.IsEnabled; + TmdsClockRatio = InstancePtr->HdmiRxTmdsClockRatio; + + /* Calculate Line Rate */ + if (IsHdmi21) { + LineRate = InstancePtr->RxHdmi21Cfg.LineRate; + } + else { + LineRate = (u64)(*RefClkPtr) * ((TmdsClockRatio ? 40 : 10)); + } + + /* Disable DRU */ + InstancePtr->HdmiRxDruIsEnabled = 0; + + /* Enable DRU based on incoming REFCLK */ + if ((!IsHdmi21) && (!TmdsClockRatio) && + (InstancePtr->HdmiRxRefClkHz < XHDMIPHY1_RPLL_MIN_REFCLK)) { + if (InstancePtr->Config.DruIsPresent) { + /* Check DRU frequency */ + if (XHdmiphy1_DruGetRefClkFreqHz(InstancePtr) == XST_FAILURE) { + XHdmiphy1_LogWrite(InstancePtr, + XHDMIPHY1_LOG_EVT_DRU_CLK_ERR, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + return (XST_FAILURE); + } + + InstancePtr->HdmiRxDruIsEnabled = 1; + LineRate = XHDMIPHY1_HDMI_GTYE5_DRU_LRATE; + } + else { + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_NO_DRU, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + return (XST_FAILURE); + } + } + } + else { + RefClkPtr = &InstancePtr->HdmiTxRefClkHz; + IsHdmi21 = InstancePtr->TxHdmi21Cfg.IsEnabled; + InstancePtr->HdmiTxSampleRate = 1; + + if (!IsHdmi21) { + /* Determine if HDMI 2.0 Mode */ + if (*RefClkPtr >= 340000000) { + TmdsClockRatio = 1; + (*RefClkPtr) = (*RefClkPtr) / 4; + } + /* Check for x1 Over Sampling Mode*/ + else if (*RefClkPtr >= 124990000) { + InstancePtr->HdmiTxSampleRate = 1; + } + /* Check for x2 Over Sampling Mode*/ + else if (*RefClkPtr >= 99000000) { + InstancePtr->HdmiTxSampleRate = 2; + (*RefClkPtr) = (*RefClkPtr) * 2; + } + /* Check for x3 Over Sampling Mode*/ + else if (*RefClkPtr >= 59400000) { + InstancePtr->HdmiTxSampleRate = 3; + (*RefClkPtr) = (*RefClkPtr) * 3; + } + /* Check for x5 Over Sampling Mode*/ + else if (*RefClkPtr < 59400000) { + InstancePtr->HdmiTxSampleRate = 5; + (*RefClkPtr) = (*RefClkPtr) * 5; + } + } + + /* Calculate Line Rate */ + if (IsHdmi21) { + LineRate = InstancePtr->TxHdmi21Cfg.LineRate; + } + else { + LineRate = (u64)(*RefClkPtr) * ((TmdsClockRatio ? 40 : 10)); + } + + } + + /* Check for DRU mode */ + if ((Dir == XHDMIPHY1_DIR_RX) && + (InstancePtr->HdmiRxDruIsEnabled)) { + InstancePtr->Quads[0].Rpll.LineRateCfg = 0; + } + /* Check for HDMI 1.4/2.0 GT LineRate Config */ + else if (!IsHdmi21) { + /* HDMI 1.4 */ + if (!TmdsClockRatio) { + if ((119990000 <= (*RefClkPtr)) && + ((*RefClkPtr) <= 200000000)) { + InstancePtr->Quads[0].Rpll.LineRateCfg = 1; + } + else if ((200000000 <= (*RefClkPtr)) && + /* 297 MHz + 0.5% + 10 KHz error */ + ((*RefClkPtr) <= 298500000)) { + InstancePtr->Quads[0].Rpll.LineRateCfg = 2; + } + else{ + Status = XST_FAILURE; + } + } + /* HDMI 2.0 */ + else { + if ((84570000 <= (*RefClkPtr)) && + ((*RefClkPtr) <= 100000000)) { + InstancePtr->Quads[0].Rpll.LineRateCfg = 3; + } + else if ((100000000 <= (*RefClkPtr)) && + ((*RefClkPtr) <= 149500000)) { + InstancePtr->Quads[0].Rpll.LineRateCfg = 4; + } + else{ + Status = XST_FAILURE; + } + } + } + /* Check for HDMI 2.1 GT LineRate Config */ + else if (IsHdmi21) { + if (LineRate == 3000000000) { + InstancePtr->Quads[0].Rpll.LineRateCfg = 5; + } + else if (LineRate == 6000000000) { + InstancePtr->Quads[0].Rpll.LineRateCfg = 6; + } + else if (LineRate == 8000000000) { + InstancePtr->Quads[0].Rpll.LineRateCfg = 7; + } + else if (LineRate == 10000000000) { + InstancePtr->Quads[0].Rpll.LineRateCfg = 8; + } + else if (LineRate == 12000000000) { + InstancePtr->Quads[0].Rpll.LineRateCfg = 9; + } + else { + Status = XST_FAILURE; + } + } + + /* Update Line Rate Value */ + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, + /* RPLL is CMN1 */ + XHDMIPHY1_CHANNEL_ID_CMN1, LineRate); + + if (Status == XST_FAILURE) { + XHdmiphy1_LogWrite(InstancePtr, + XHDMIPHY1_LOG_EVT_GT_RPLL_CFG_ERR, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function calculates the TX PLL 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. +* +* @return +* - XST_SUCCESS if calculated QPLL parameters updated +* successfully. +* - XST_FAILURE if parameters not updated. +* +* @note None. +* +******************************************************************************/ +u32 XHdmiphy1_HdmiTxPllParam(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId) +{ + u32 Status; + XHdmiphy1_PllType PllType; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + /* Determine PLL type. */ + PllType = XHdmiphy1_GetPllType(InstancePtr, 0, XHDMIPHY1_DIR_TX, + XHDMIPHY1_CHANNEL_ID_CH1); + + if (PllType == XHDMIPHY1_PLL_TYPE_LCPLL) { + Status = XHdmiphy1_HdmiLcpllParam(InstancePtr, 0, ChId, + XHDMIPHY1_DIR_TX); + } + else { /* RPLL */ + Status = XHdmiphy1_HdmiRpllParam(InstancePtr, 0, ChId, + XHDMIPHY1_DIR_TX); + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function calculates the RX PLL 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. +* +* @return +* - XST_SUCCESS if calculated QPLL parameters updated +* successfully. +* - XST_FAILURE if parameters not updated. +* +* @note None. +* +******************************************************************************/ +u32 XHdmiphy1_HdmiRxPllParam(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId) +{ + u32 Status; + XHdmiphy1_PllType PllType; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + /* Determine PLL type. */ + PllType = XHdmiphy1_GetPllType(InstancePtr, 0, XHDMIPHY1_DIR_RX, + XHDMIPHY1_CHANNEL_ID_CH1); + + if (PllType == XHDMIPHY1_PLL_TYPE_LCPLL) { + Status = XHdmiphy1_HdmiLcpllParam(InstancePtr, 0, ChId, + XHDMIPHY1_DIR_RX); + } + else { /* RPLL */ + Status = XHdmiphy1_HdmiRpllParam(InstancePtr, 0, ChId, + XHDMIPHY1_DIR_RX); + } + + return Status; +} + + +/*****************************************************************************/ +/** +* This function will configure the channel's RX settings. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_Gtye5RxChReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId) +{ + u8 CfgValComp; + + /* Compare the current and next CFG values */ + CfgValComp = XHdmiphy1_CheckLineRateCfg(InstancePtr, QuadId, ChId, + XHDMIPHY1_DIR_RX); + + if (!CfgValComp) { + /* If CFG values are different */ + XHdmiphy1_SetGtLineRateCfg(InstancePtr, QuadId, ChId, + XHDMIPHY1_DIR_RX); + } + else { + /* Toggle RX Master Reset */ + XHdmiphy1_GtMstReset(InstancePtr, QuadId, ChId, XHDMIPHY1_DIR_RX, + TRUE); + XHdmiphy1_GtMstReset(InstancePtr, QuadId, ChId, XHDMIPHY1_DIR_RX, + FALSE); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function will configure the channel's TX settings. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_Gtye5TxChReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId) +{ + u8 CfgValComp; + + /* Compare the current and next CFG values */ + CfgValComp = XHdmiphy1_CheckLineRateCfg(InstancePtr, QuadId, ChId, + XHDMIPHY1_DIR_TX); + + if (!CfgValComp) { + /* If CFG values are different */ + XHdmiphy1_SetGtLineRateCfg(InstancePtr, QuadId, ChId, + XHDMIPHY1_DIR_TX); + } + else { + /* Toggle RX Master Reset */ + XHdmiphy1_GtMstReset(InstancePtr, QuadId, ChId, XHDMIPHY1_DIR_TX, + TRUE); + XHdmiphy1_GtMstReset(InstancePtr, QuadId, ChId, XHDMIPHY1_DIR_TX, + FALSE); + } + + return XST_SUCCESS; +} + +#endif diff --git a/hdmi/phy-xilinx-vphy/xhdmiphy1_hdmi.c b/hdmi/phy-xilinx-vphy/xhdmiphy1_hdmi.c new file mode 100644 index 0000000..4d84440 --- /dev/null +++ b/hdmi/phy-xilinx-vphy/xhdmiphy1_hdmi.c @@ -0,0 +1,2865 @@ +/******************************************************************************* + * + * + * 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 xhdmiphy1_hdmi.c + * + * This file contains video PHY functionality specific to the HDMI protocol. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ *            dd/mm/yy
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   gm   10/12/18 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xstatus.h" +#include "xhdmiphy1.h" +#include "xhdmiphy1_i.h" +#include "xhdmiphy1_hdmi.h" + +/****************************** Type Definitions ******************************/ + +typedef struct { + u64 DruLineRate; + u16 PllScale; + u32 Qpll0RefClkMin; + u32 Qpll1RefClkMin; + u32 CpllRefClkMin; + u16 TxMmcmScale; + u64 TxMmcmFvcoMin; + u64 TxMmcmFvcoMax; + u16 RxMmcmScale; + u64 RxMmcmFvcoMin; + u64 RxMmcmFvcoMax; +} XHdmiphy1_GtHdmiChars; + +/**************************** Function Prototypes *****************************/ + +extern void XHdmiphy1_Ch2Ids(XHdmiphy1 *InstancePtr, XHdmiphy1_ChannelId ChId, + u8 *Id0, u8 *Id1); +static const XHdmiphy1_GtHdmiChars *GetGtHdmiPtr(XHdmiphy1 *InstancePtr); +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) +static void XHdmiphy1_HdmiSetSystemClockSelection(XHdmiphy1 *InstancePtr, + u8 QuadId); +#endif + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function initializes the Video PHY for HDMI. + * + * @param InstancePtr is a pointer to the XHdmiphy1 instance. + * @param CfgPtr is a pointer to the configuration structure that will + * be used to copy the settings from. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +u32 XHdmiphy1_Hdmi_CfgInitialize(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_Config *CfgPtr) +{ + u8 Id, Id0, Id1; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(CfgPtr != NULL); + + /* Init done. */ + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_INIT, 0); + + /* Setup the instance. */ + XHdmiphy1_CfgInitialize(InstancePtr, CfgPtr, CfgPtr->BaseAddr); + + /* Set default. */ + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)].TxState = + XHDMIPHY1_GT_STATE_IDLE; + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)].RxState = + XHDMIPHY1_GT_STATE_IDLE; + /* Initialize Transceiver Width values */ + if (InstancePtr->Config.TransceiverWidth == 2) { + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)]. + TxDataWidth = 20; + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)]. + TxIntDataWidth = 2; + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)]. + RxDataWidth = 20; + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)]. + RxIntDataWidth = 2; + } + else { + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)]. + TxDataWidth = 40; + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)]. + TxIntDataWidth = 4; + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)]. + RxDataWidth = 40; + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)]. + RxIntDataWidth = 4; + } + } + + /* Interrupt Disable. */ + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TXRESET_DONE); + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RXRESET_DONE); +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_CPLL_LOCK); + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_QPLL0_LOCK); + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TXALIGN_DONE); + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_QPLL1_LOCK); +#else + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_LCPLL_LOCK); + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RPLL_LOCK); + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TX_GPO_RISING_EDGE); + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_GPO_RISING_EDGE); +#endif + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE); + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE); + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TX_MMCM_LOCK_CHANGE); + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_MMCM_LOCK_CHANGE); + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT); + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); + + /* Setup HDMI interrupt handler callback*/ + XHdmiphy1_HdmiIntrHandlerCallbackInit(InstancePtr); + + /* Configure clock detector. */ + XHdmiphy1_ClkDetEnable(InstancePtr, FALSE); + XHdmiphy1_ClkDetSetFreqTimeout(InstancePtr, + InstancePtr->Config.AxiLiteClkFreq); + XHdmiphy1_ClkDetSetFreqLockThreshold(InstancePtr, 40); + + /* Start capturing logs. */ + XHdmiphy1_LogReset(InstancePtr); + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_INIT, 0); + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + XHdmiphy1_HdmiSetSystemClockSelection(InstancePtr, QuadId); + + /* Indicate of QPLL is present in design */ + if ((XHdmiphy1_IsTxUsingQpll(InstancePtr, + QuadId, XHDMIPHY1_CHANNEL_ID_CH1) && + (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_TX))) || + (XHdmiphy1_IsRxUsingQpll(InstancePtr, + QuadId, XHDMIPHY1_CHANNEL_ID_CH1) && + (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_RX)))) { + InstancePtr->HdmiIsQpllPresent = TRUE; + } else { + InstancePtr->HdmiIsQpllPresent = FALSE; + } + + if ((InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTHE3) || + (InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTHE4) || + (InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTYE4)) { + XHdmiphy1_SetBufgGtDiv(InstancePtr, XHDMIPHY1_DIR_TX, 1); + XHdmiphy1_SetBufgGtDiv(InstancePtr, XHDMIPHY1_DIR_RX, 1); + } + XHdmiphy1_PowerDownGtPll(InstancePtr, QuadId, XHDMIPHY1_CHANNEL_ID_CMNA, + TRUE); + XHdmiphy1_PowerDownGtPll(InstancePtr, QuadId, XHDMIPHY1_CHANNEL_ID_CHA, + TRUE); + XHdmiphy1_ResetGtPll(InstancePtr, QuadId, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_RX, TRUE); + XHdmiphy1_ResetGtPll(InstancePtr, QuadId, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_TX, TRUE); +#endif + XHdmiphy1_MmcmReset(InstancePtr, QuadId, XHDMIPHY1_DIR_TX, TRUE); + XHdmiphy1_MmcmReset(InstancePtr, QuadId, XHDMIPHY1_DIR_RX, TRUE); + if (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_TX)) { + XHdmiphy1_IBufDsEnable(InstancePtr, QuadId, XHDMIPHY1_DIR_TX, (FALSE)); + } + if (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_RX)) { + XHdmiphy1_IBufDsEnable(InstancePtr, QuadId, XHDMIPHY1_DIR_RX, (FALSE)); + } + + /* DRU Settings. */ + if (InstancePtr->Config.DruIsPresent) { + XHdmiphy1_IBufDsEnable(InstancePtr, QuadId, XHDMIPHY1_DIR_RX, TRUE); + XHdmiphy1_DruReset(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, TRUE); + XHdmiphy1_DruEnable(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, FALSE); + } + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + /* Set to DFE */ + XHdmiphy1_SetRxLpm(InstancePtr, QuadId, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_RX, 0); +#endif + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + XHdmiphy1_SetTxVoltageSwing(InstancePtr, QuadId, +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + (XHdmiphy1_ChannelId)Id, 0xB); +#else + (XHdmiphy1_ChannelId)Id, 0x1F); +#endif + XHdmiphy1_SetTxPreEmphasis(InstancePtr, QuadId, + (XHdmiphy1_ChannelId)Id, 0x4); + XHdmiphy1_SetTxPostCursor(InstancePtr, QuadId, + (XHdmiphy1_ChannelId)Id, 0x4); + } + + /* Clear Interrupt Register */ + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_INTR_STS_REG, + 0xFFFFFFFF); + + /* Interrupt Enable. */ + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TXRESET_DONE); + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RXRESET_DONE); +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_CPLL_LOCK); + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_QPLL0_LOCK); + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TXALIGN_DONE); + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_QPLL1_LOCK); +#else + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_LCPLL_LOCK); + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RPLL_LOCK); + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TX_GPO_RISING_EDGE); + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_GPO_RISING_EDGE); +#endif + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE); + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE); + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TX_MMCM_LOCK_CHANGE); + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT); + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT); + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_MMCM_LOCK_CHANGE); + XHdmiphy1_ClkDetEnable(InstancePtr, TRUE); + + /* Set the flag to indicate the driver is. */ + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + /* Init done. */ + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_INIT, 1); + + return XST_SUCCESS; +} + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) +/*****************************************************************************/ +/** +* This function Sets the System Clock Selection +* +* @param InstancePtr is a pointer to the XHdmiphy1 core instance. +* @param QuadId is the GT quad ID to operate on. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void XHdmiphy1_HdmiSetSystemClockSelection(XHdmiphy1 *InstancePtr, + u8 QuadId) +{ + XHdmiphy1_PllType XHdmiphy1_QPllType; + + XHdmiphy1_QPllType = XHDMIPHY1_PLL_TYPE_QPLL0; + + /* Set system clock selections */ + if (InstancePtr->Config.TxSysPllClkSel == + InstancePtr->Config.RxSysPllClkSel) { + if (InstancePtr->Config.RxSysPllClkSel == + XHDMIPHY1_SYSCLKSELDATA_TYPE_CPLL_OUTCLK) { + XHdmiphy1_PllInitialize(InstancePtr, QuadId, + XHDMIPHY1_CHANNEL_ID_CHA, + InstancePtr->Config.RxRefClkSel, + InstancePtr->Config.RxRefClkSel, + XHDMIPHY1_PLL_TYPE_CPLL, + XHDMIPHY1_PLL_TYPE_CPLL); + } + else { + XHdmiphy1_PllInitialize(InstancePtr, QuadId, + XHDMIPHY1_CHANNEL_ID_CMN0, + InstancePtr->Config.RxRefClkSel, + InstancePtr->Config.RxRefClkSel, + XHdmiphy1_QPllType, + XHdmiphy1_QPllType); + } + } + else if (InstancePtr->Config.TxSysPllClkSel == + XHDMIPHY1_SYSCLKSELDATA_TYPE_CPLL_OUTCLK) { + XHdmiphy1_PllInitialize(InstancePtr, QuadId, + XHDMIPHY1_CHANNEL_ID_CHA, + InstancePtr->Config.RxRefClkSel, + InstancePtr->Config.TxRefClkSel, + XHDMIPHY1_PLL_TYPE_CPLL, + XHdmiphy1_QPllType); + } + else { + XHdmiphy1_PllInitialize(InstancePtr, QuadId, + XHDMIPHY1_CHANNEL_ID_CMN0, + InstancePtr->Config.TxRefClkSel, + InstancePtr->Config.RxRefClkSel, + XHdmiphy1_QPllType, + XHDMIPHY1_PLL_TYPE_CPLL); + } +} + +/*****************************************************************************/ +/** +* This function Updates the HDMIPHY clocking. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_HdmiUpdateClockSelection(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_SysClkDataSelType TxSysPllClkSel, + XHdmiphy1_SysClkDataSelType RxSysPllClkSel) +{ + u8 Id, Id0, Id1; + + /* Reset PLL */ + XHdmiphy1_ResetGtPll(InstancePtr, QuadId, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_RX, TRUE); + XHdmiphy1_ResetGtPll(InstancePtr, QuadId, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_TX, TRUE); + + /* Set default. */ + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)].TxState = + XHDMIPHY1_GT_STATE_IDLE; + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)].RxState = + XHDMIPHY1_GT_STATE_IDLE; + } + + /* Update Hdmiphy Clocking */ + InstancePtr->Config.TxSysPllClkSel = TxSysPllClkSel; + InstancePtr->Config.RxSysPllClkSel = RxSysPllClkSel; + XHdmiphy1_HdmiSetSystemClockSelection(InstancePtr, QuadId); +} + +/*****************************************************************************/ +/** +* This function resets the GT TX alignment module. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_TxAlignReset(XHdmiphy1 *InstancePtr, XHdmiphy1_ChannelId ChId, + u8 Reset) +{ + u32 RegVal; + u32 MaskVal = 0; + u8 Id, Id0, Id1; + + /* Read TX align register. */ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_TX_BUFFER_BYPASS_REG); + + XHdmiphy1_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + MaskVal |= XHDMIPHY1_TX_BUFFER_BYPASS_TXPHDLYRESET_MASK(Id); + } + + /* Write new value to BUFG_GT register. */ + if (Reset) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_TX_BUFFER_BYPASS_REG, RegVal); +} + +/*****************************************************************************/ +/** +* This function resets the GT TX alignment module. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_TxAlignStart(XHdmiphy1 *InstancePtr, XHdmiphy1_ChannelId ChId, + u8 Start) +{ + u32 RegVal; + u32 MaskVal = 0; + u8 Id, Id0, Id1; + + /* Read TX align register. */ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_TX_BUFFER_BYPASS_REG); + + XHdmiphy1_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + MaskVal |= XHDMIPHY1_TX_BUFFER_BYPASS_TXPHALIGN_MASK(Id); + } + + /* Write new value to BUFG_GT register. */ + if (Start) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_TX_BUFFER_BYPASS_REG, RegVal); +} +#endif + +/*****************************************************************************/ +/** +* This function enables the HDMIPHY's detector peripheral. +* +* @param InstancePtr is a pointer to the XHdmiphy1 core instance. +* @param Enable specifies TRUE/FALSE value to either enable or disable +* the clock detector respectively. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_ClkDetEnable(XHdmiphy1 *InstancePtr, u8 Enable) +{ + u32 RegVal; + + /* Read clkdet ctrl register. */ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_CLKDET_CTRL_REG); + + /* Write new value to clkdet ctrl register. */ + if (Enable) { + RegVal |= XHDMIPHY1_CLKDET_CTRL_RUN_MASK; + } + else { + RegVal &= ~XHDMIPHY1_CLKDET_CTRL_RUN_MASK; + } + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_CLKDET_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function clears the clock detector TX/RX timer. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_ClkDetTimerClear(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir) +{ + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + /* Read the clock detector control register. */ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_CLKDET_CTRL_REG); + + if (Dir == XHDMIPHY1_DIR_TX) { + RegVal |= XHDMIPHY1_CLKDET_CTRL_TX_TMR_CLR_MASK; + } + else { + RegVal |= XHDMIPHY1_CLKDET_CTRL_RX_TMR_CLR_MASK; + } + + /* Write new value to clkdet ctrl register. */ + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_CLKDET_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function resets clock detector TX/RX frequency. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_ClkDetFreqReset(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir) +{ + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + /* Read clkdet ctrl register. */ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_CLKDET_CTRL_REG); + + if (Dir == XHDMIPHY1_DIR_TX) { + RegVal |= XHDMIPHY1_CLKDET_CTRL_TX_FREQ_RST_MASK; + } + else { + RegVal |= XHDMIPHY1_CLKDET_CTRL_RX_FREQ_RST_MASK; + } + + /* Write new value to clkdet ctrl register. */ + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_CLKDET_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function sets the clock detector frequency lock counter threshold value. +* +* @param InstancePtr is a pointer to the XHdmiphy1 core instance. +* @param ThresholdVal is the threshold value to be set. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_ClkDetSetFreqLockThreshold(XHdmiphy1 *InstancePtr, + u16 ThresholdVal) +{ + u32 RegVal; + + /* Read clkdet ctrl register. */ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_CLKDET_CTRL_REG); + RegVal &= ~XHDMIPHY1_CLKDET_CTRL_RX_FREQ_RST_MASK; + + /* Update with new threshold. */ + RegVal |= (ThresholdVal << XHDMIPHY1_CLKDET_CTRL_FREQ_LOCK_THRESH_SHIFT); + + /* Write new value to clkdet ctrl register. */ + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_CLKDET_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function checks clock detector RX/TX frequency zero indicator bit. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_ClkDetCheckFreqZero(XHdmiphy1 *InstancePtr, + XHdmiphy1_DirectionType Dir) +{ + u32 MaskVal = 0; + u32 RegVal; + + if (Dir == XHDMIPHY1_DIR_TX) { + MaskVal = XHDMIPHY1_CLKDET_STAT_TX_FREQ_ZERO_MASK; + } + else { + MaskVal = XHDMIPHY1_CLKDET_STAT_RX_FREQ_ZERO_MASK; + } + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_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 XHdmiphy1 core instance. +* @param TimeoutVal is the timeout value and is normally the system clock +* frequency. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_ClkDetSetFreqTimeout(XHdmiphy1 *InstancePtr, u32 TimeoutVal) +{ + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_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 XHdmiphy1 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 XHdmiphy1_ClkDetTimerLoad(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, u32 TimeoutVal) +{ + u32 RegOffset; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XHDMIPHY1_DIR_TX) { + RegOffset = XHDMIPHY1_CLKDET_TMR_TX_REG; + } + else { + RegOffset = XHDMIPHY1_CLKDET_TMR_RX_REG; + } + + XHdmiphy1_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 XHdmiphy1 core instance. +* @param Dir is an indicator for RX or TX. +* +* @return The measured frequency of the RX/TX reference clock. +* +* @note None. +* +******************************************************************************/ +u32 XHdmiphy1_ClkDetGetRefClkFreqHz(XHdmiphy1 *InstancePtr, + XHdmiphy1_DirectionType Dir) +{ + u32 RegOffset; + + if (Dir == XHDMIPHY1_DIR_TX) { + RegOffset = XHDMIPHY1_CLKDET_FREQ_TX_REG; + } + else { + RegOffset = XHDMIPHY1_CLKDET_FREQ_RX_REG; + } + + return XHdmiphy1_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 XHdmiphy1 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 XHdmiphy1_DruGetRefClkFreqHz(XHdmiphy1 *InstancePtr) +{ + u32 DruFreqHz = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_CLKDET_FREQ_DRU_REG); + + + + /* Verify argument. */ + Xil_AssertNonvoid(InstancePtr != NULL); + + if (InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTHE3) { + if (DruFreqHz > XHDMIPHY1_HDMI_GTHE3_DRU_REFCLK_MIN && + DruFreqHz < XHDMIPHY1_HDMI_GTHE3_DRU_REFCLK_MAX){ + return XHDMIPHY1_HDMI_GTHE3_DRU_REFCLK; + } + else if (DruFreqHz > XHDMIPHY1_HDMI_GTHE3_DRU_REFCLK2_MIN && + DruFreqHz < XHDMIPHY1_HDMI_GTHE3_DRU_REFCLK2_MAX){ + return XHDMIPHY1_HDMI_GTHE3_DRU_REFCLK2; + } + } + else if (InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTHE4) { + if (DruFreqHz > XHDMIPHY1_HDMI_GTHE4_DRU_REFCLK_MIN && + DruFreqHz < XHDMIPHY1_HDMI_GTHE4_DRU_REFCLK_MAX){ + return XHDMIPHY1_HDMI_GTHE4_DRU_REFCLK; + } + else if (DruFreqHz > XHDMIPHY1_HDMI_GTHE4_DRU_REFCLK2_MIN && + DruFreqHz < XHDMIPHY1_HDMI_GTHE4_DRU_REFCLK2_MAX){ + return XHDMIPHY1_HDMI_GTHE4_DRU_REFCLK2; + } + } + else if (InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTYE4) { + if (DruFreqHz > XHDMIPHY1_HDMI_GTYE4_DRU_REFCLK_MIN && + DruFreqHz < XHDMIPHY1_HDMI_GTYE4_DRU_REFCLK_MAX){ + return XHDMIPHY1_HDMI_GTYE4_DRU_REFCLK; + } + else if (DruFreqHz > XHDMIPHY1_HDMI_GTYE4_DRU_REFCLK2_MIN && + DruFreqHz < XHDMIPHY1_HDMI_GTYE4_DRU_REFCLK2_MAX){ + return XHDMIPHY1_HDMI_GTYE4_DRU_REFCLK2; + } + } + else { + if (DruFreqHz > XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK_MIN && + DruFreqHz < XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK_MAX){ + return XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK; + } + if (DruFreqHz > XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK1_MIN && + DruFreqHz < XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK1_MAX){ + return XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK1; + } + if (DruFreqHz > XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK2_MIN && + DruFreqHz < XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK2_MAX){ + return XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK2; + } + } + + /* Return Failure */ + return XST_FAILURE; +} + +/*****************************************************************************/ +/** +* This function resets the DRU in the HDMIPHY. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_DruReset(XHdmiphy1 *InstancePtr, XHdmiphy1_ChannelId ChId, + u8 Reset) +{ + u32 RegVal; + u32 MaskVal = 0; + u8 Id, Id0, Id1; + + /* Read DRU ctrl register. */ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_DRU_CTRL_REG); + + XHdmiphy1_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + MaskVal |= XHDMIPHY1_DRU_CTRL_RST_MASK(Id); + } + + /* Write DRU ctrl register. */ + if (Reset) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_DRU_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function enabled/disables the DRU in the HDMIPHY. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_DruEnable(XHdmiphy1 *InstancePtr, XHdmiphy1_ChannelId ChId, + u8 Enable) +{ + u32 RegVal; + u32 MaskVal = 0; + u8 Id, Id0, Id1; + + /* Read DRU ctrl register. */ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_DRU_CTRL_REG); + + XHdmiphy1_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + MaskVal |= XHDMIPHY1_DRU_CTRL_EN_MASK(Id); + } + + /* Write DRU ctrl register. */ + if (Enable) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_DRU_CTRL_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function gets the DRU version +* +* @param InstancePtr is a pointer to the XHdmiphy1 core instance. +* +* @return None. +* +******************************************************************************/ +u16 XHdmiphy1_DruGetVersion(XHdmiphy1 *InstancePtr) +{ + u32 RegVal; + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_DRU_STAT_REG); + RegVal &= XHDMIPHY1_DRU_STAT_VERSION_MASK; + RegVal >>= XHDMIPHY1_DRU_STAT_VERSION_SHIFT; + + return ((u16)RegVal); +} + +/*****************************************************************************/ +/** +* This function sets the DRU center frequency. +* +* @param InstancePtr is a pointer to the XHdmiphy1 core instance. +* @param ChId specifies the channel ID. +* @param CenterFreqHz is the frequency value to set. +* +* @return None. +* +******************************************************************************/ +void XHdmiphy1_DruSetCenterFreqHz(XHdmiphy1 *InstancePtr, + XHdmiphy1_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 &= XHDMIPHY1_DRU_CFREQ_H_MASK;; + CenterFreqH = (u32)CenterFreqHz; + + XHdmiphy1_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + RegOffset = XHDMIPHY1_DRU_CFREQ_L_REG(Id); + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, + CenterFreqL); + + RegOffset = XHDMIPHY1_DRU_CFREQ_H_REG(Id); + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, + CenterFreqH); + } +} + +/*****************************************************************************/ +/** +* This function calculates the center frequency value for the DRU. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XAPP1240: +* Center_f = fDIN * (2^32)/fdruclk +* The DRU clock is derived from the measured reference clock and +* the current QPLL settings. +* +******************************************************************************/ +u64 XHdmiphy1_DruCalcCenterFreqHz(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId) +{ +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + XHdmiphy1_Channel *ChPtr; + u64 DruRefClk; +#endif + u64 ClkDetRefClk; + u64 DataRate; + u64 FDin; + u64 FDruClk; + + ClkDetRefClk = XHdmiphy1_ClkDetGetRefClkFreqHz(InstancePtr, + XHDMIPHY1_DIR_RX); +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + DruRefClk = XHdmiphy1_DruGetRefClkFreqHz(InstancePtr); + + /* Take the master channel (channel 1). */ + ChPtr = &InstancePtr->Quads[QuadId].Ch1; + + if ((ChId == XHDMIPHY1_CHANNEL_ID_CMN0) || + (ChId == XHDMIPHY1_CHANNEL_ID_CMN1)) { + FDruClk = (DruRefClk * InstancePtr->Quads[QuadId].Plls[ + XHDMIPHY1_CH2IDX(ChId)].PllParams.NFbDiv) / + (InstancePtr->Quads[QuadId].Plls[ + XHDMIPHY1_CH2IDX(ChId)].PllParams.MRefClkDiv * + (ChPtr->RxOutDiv * 20)); + } + else { + FDruClk = (DruRefClk * ChPtr->PllParams.N1FbDiv * + ChPtr->PllParams.N2FbDiv * 2) / + (ChPtr->PllParams.MRefClkDiv * ChPtr->RxOutDiv * 20); + } +#else + /* Supress Warning */ + QuadId = QuadId; + ChId = ChId; + + FDruClk = (u64) (XHDMIPHY1_HDMI_GTYE5_DRU_LRATE / 20); +#endif + 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 XHdmiphy1 core instance. +* @param Enable enables the DRU logic (when 1), or disables (when 0). +* +* @return None. +* +******************************************************************************/ +void XHdmiphy1_HdmiGtDruModeEnable(XHdmiphy1 *InstancePtr, u8 Enable) +{ + u32 RegVal; + u32 RegMask = 0; + u8 Id, Id0, Id1; + + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_DRU_EN, Enable); + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_RX_EQ_CDR_REG); + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + RegMask |= XHDMIPHY1_RX_STATUS_RXCDRHOLD_MASK(Id) | + XHDMIPHY1_RX_STATUS_RXOSOVRDEN_MASK(Id) | + XHDMIPHY1_RX_STATUS_RXLPMLFKLOVRDEN_MASK(Id) | + XHDMIPHY1_RX_STATUS_RXLPMHFOVRDEN_MASK(Id); + } + + if (Enable) { + RegVal |= RegMask; + } + else { + RegVal &= ~RegMask; + } + + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_RX_EQ_CDR_REG, + RegVal); +} + +/*****************************************************************************/ +/** +* This function calculates the HDMI MMCM parameters. +* +* @param InstancePtr is a pointer to the Hdmiphy 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 XHdmiphy1_HdmiCfgCalcMmcmParam(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, + XVidC_PixelsPerClock Ppc, XVidC_ColorDepth Bpc) +{ + u32 RefClk; + u16 Div; + u16 Mult; + u16 MultDiv; + u8 Valid; + u64 LineRate = 0; + XHdmiphy1_Mmcm *MmcmPtr; + XHdmiphy1_PllType PllType; + + /* Suppress Warning Messages */ + ChId = ChId; + + /* Get line rate. */ + PllType = XHdmiphy1_GetPllType(InstancePtr, 0, Dir, + XHDMIPHY1_CHANNEL_ID_CH1); + + switch (PllType) { + case XHDMIPHY1_PLL_TYPE_QPLL: + case XHDMIPHY1_PLL_TYPE_QPLL0: + case XHDMIPHY1_PLL_TYPE_LCPLL: + LineRate = InstancePtr->Quads[QuadId].Cmn0.LineRateHz; + break; + case XHDMIPHY1_PLL_TYPE_QPLL1: + case XHDMIPHY1_PLL_TYPE_RPLL: + LineRate = InstancePtr->Quads[QuadId].Cmn1.LineRateHz; + break; + default: + LineRate = InstancePtr->Quads[QuadId].Ch1.LineRateHz; + break; + } + + if (((LineRate / 1000000) > 2970) && (Ppc == XVIDC_PPC_1)) { + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_1PPC_ERR, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + return (XST_FAILURE); + } + + Div = 1; + + do { + if (Dir == XHDMIPHY1_DIR_RX) { + RefClk = InstancePtr->HdmiRxRefClkHz; + MmcmPtr= &InstancePtr->Quads[QuadId].RxMmcm; + + RefClk = RefClk / (GetGtHdmiPtr(InstancePtr))->RxMmcmScale; + Mult = (GetGtHdmiPtr(InstancePtr))->RxMmcmFvcoMax * Div / RefClk; + } + else { + RefClk = InstancePtr->HdmiTxRefClkHz; + MmcmPtr= &InstancePtr->Quads[QuadId].TxMmcm; + + RefClk = RefClk / (GetGtHdmiPtr(InstancePtr))->TxMmcmScale; + Mult = (GetGtHdmiPtr(InstancePtr))->TxMmcmFvcoMax * Div / RefClk; + } + + /* Return if RefClk is below valid range */ + if (RefClk < 20000000) { + 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; + } + + + Valid = (FALSE); + do { + MultDiv = Mult / Div; + MmcmPtr->ClkFbOutMult = Mult; + MmcmPtr->DivClkDivide = Div; + + if (InstancePtr->Config.TransceiverWidth == 4) { + /* Link clock: TMDS clock ratio 1/40. */ + if ((LineRate / 1000000) >= 3400) { + if ((Dir == XHDMIPHY1_DIR_TX) && + (((LineRate / 1000000) / InstancePtr-> + HdmiTxSampleRate) < 3400)) { + MmcmPtr->ClkOut0Div = MultDiv * 4; + } + else { + MmcmPtr->ClkOut0Div = MultDiv; + } + } + /* Link clock: TMDS clock ratio 1/10. */ + else { + MmcmPtr->ClkOut0Div = MultDiv * 4; + } + } + else { /* 2 Byte Mode */ + /* Link clock: TMDS clock ratio 1/40. */ + if ((LineRate / 1000000) >= 3400) { + if ((Dir == XHDMIPHY1_DIR_TX) && + (((LineRate / 1000000) / InstancePtr-> + HdmiTxSampleRate) < 3400)) { + MmcmPtr->ClkOut0Div = MultDiv * 2; + } + else { + MmcmPtr->ClkOut0Div = MultDiv / 2; + } + } + /* Link clock: TMDS clock ratio 1/10. */ + else { + MmcmPtr->ClkOut0Div = MultDiv * 2; + } + } + + /* TMDS Clock */ + MmcmPtr->ClkOut1Div = MultDiv * ((Dir == XHDMIPHY1_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 = (MultDiv * 5 * + ((Dir == XHDMIPHY1_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 MultDiv must be dividable by two (2 * 2.5 = 5) + to get an integer number */ + if ((MultDiv % 2) == 0) { + MmcmPtr->ClkOut2Div = (MultDiv * 5 / 2 * + ((Dir == XHDMIPHY1_DIR_TX)? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + } + /* Single pixel. */ + else { + /* The clock ratio is 1.25 */ + /* The PLL only supports integer values */ + /* The MultDiv must be dividable by four (4 * 1.25 = 5) + to get an integer number */ + if ((MultDiv % 4) == 0) { + MmcmPtr->ClkOut2Div = (MultDiv * 5 / 4 * + ((Dir == XHDMIPHY1_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + } + break; + case XVIDC_BPC_12: + /* Quad pixel. */ + if (Ppc == (XVIDC_PPC_4)) { + MmcmPtr->ClkOut2Div = (MultDiv * 6 * + ((Dir == XHDMIPHY1_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + /* Dual pixel. */ + else if (Ppc == (XVIDC_PPC_2)) { + MmcmPtr->ClkOut2Div = (MultDiv * 3 * + ((Dir == XHDMIPHY1_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + /* Single pixel. */ + else { + /* The clock ratio is 1.5 */ + /* The PLL only supports integer values */ + /* The MultDiv must be dividable by two (2 * 1.5 = 3) + to get an integer number */ + if ((MultDiv % 2) == 0) { + MmcmPtr->ClkOut2Div = (MultDiv * 3 / 2 * + ((Dir == XHDMIPHY1_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + } + break; + case XVIDC_BPC_16 : + /* Quad pixel. */ + if (Ppc == (XVIDC_PPC_4)) { + MmcmPtr->ClkOut2Div = (MultDiv * 8 * + ((Dir == XHDMIPHY1_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + /* Dual pixel. */ + else if (Ppc == (XVIDC_PPC_2)) { + MmcmPtr->ClkOut2Div = (MultDiv * 4 * + ((Dir == XHDMIPHY1_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + /* Single pixel. */ + else { + MmcmPtr->ClkOut2Div = (MultDiv * 2 * + ((Dir == XHDMIPHY1_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + break; + case XVIDC_BPC_8: + default: + /* Quad pixel. */ + if (Ppc == (XVIDC_PPC_4)) { + MmcmPtr->ClkOut2Div = (MultDiv * 4 * + ((Dir == XHDMIPHY1_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + /* Dual pixel. */ + else if (Ppc == (XVIDC_PPC_2)) { + MmcmPtr->ClkOut2Div = (MultDiv * 2 * + ((Dir == XHDMIPHY1_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + /* Single pixel. */ + else { + MmcmPtr->ClkOut2Div = (MultDiv * + ((Dir == XHDMIPHY1_DIR_TX) ? + (InstancePtr->HdmiTxSampleRate) : 1)); + } + break; + } + + /* Only do this when the ClkOut2Div has been set */ + if (MmcmPtr->ClkOut2Div) { + if (Dir == XHDMIPHY1_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 { +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + MmcmPtr->ClkOut2Div = 255; +#else + MmcmPtr->ClkOut2Div = 65535; +#endif + } + } + } + /* TX. */ + else if ((((LineRate / 1000000) >= 3400) && + (InstancePtr->HdmiTxSampleRate == 1)) || + (((LineRate / 1000000) / InstancePtr-> + HdmiTxSampleRate) >= 3400)) { + if ((MmcmPtr->ClkOut2Div % 4) == 0) { + MmcmPtr->ClkOut2Div = MmcmPtr->ClkOut2Div / 4; + } + /* Not divisible by 4: repeat loop with a lower + * multiply value. */ + else { +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + MmcmPtr->ClkOut2Div = 255; +#else + MmcmPtr->ClkOut2Div = 65535; +#endif + } + } + } + + /* Check values. */ +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + if ((MmcmPtr->ClkOut0Div > 0) && (MmcmPtr->ClkOut0Div <= 128) && + (MmcmPtr->ClkOut1Div > 0) && (MmcmPtr->ClkOut1Div <= 128) && + (MmcmPtr->ClkOut2Div > 0) && (MmcmPtr->ClkOut2Div <= 128)) { +#else + if ((MmcmPtr->ClkOut0Div > 0) && (MmcmPtr->ClkOut0Div <= 511) && + (MmcmPtr->ClkOut1Div > 0) && (MmcmPtr->ClkOut1Div <= 511) && + (MmcmPtr->ClkOut2Div > 0) && (MmcmPtr->ClkOut2Div <= 511)) { +#endif + 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; + } + } +#if (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE5) + } while (!Valid && (Mult > 3) && (Mult < 432)); +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE4 || \ + XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE4) + } while (!Valid && (Mult > 0) && (Mult < 129)); +#else + } while (!Valid && (Mult > 0) && (Mult < 65)); +#endif + + /* Increment divider */ + Div++; +#if (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE5) + } while (!Valid && (Div > 0) && (Div < 124)); +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE4 || \ + XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE4) + } while (!Valid && (Div > 0) && (Div < 107)); +#else + } while (!Valid && (Div > 0) && (Div < 20)); +#endif + + if (Valid) { + return (XST_SUCCESS); + } + else { + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_MMCM_ERR, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + return (XST_FAILURE); + } +} + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) +/*****************************************************************************/ +/** +* 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 XHdmiphy1_HdmiQpllParam(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_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; + + XHdmiphy1_SysClkDataSelType SysClkDataSel = + (XHdmiphy1_SysClkDataSelType) 0; + XHdmiphy1_SysClkOutSelType SysClkOutSel = + (XHdmiphy1_SysClkOutSelType) 0; + XHdmiphy1_ChannelId ActiveCmnId = + XHDMIPHY1_CHANNEL_ID_CMN0; + + u32 QpllRefClk; + u32 QpllClkMin = 0; + + /* Determine QPLL reference clock from the first (master) channel. */ + if (Dir == XHDMIPHY1_DIR_RX) { + QpllRefClk = InstancePtr->HdmiRxRefClkHz; + RefClkPtr = &InstancePtr->HdmiRxRefClkHz; + } + else { + QpllRefClk = InstancePtr->HdmiTxRefClkHz; + RefClkPtr = &InstancePtr->HdmiTxRefClkHz; + } + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE3) + /* Determine which QPLL to use. */ + if (((102343750 <= QpllRefClk) && (QpllRefClk <= 122500000)) || + ((204687500 <= QpllRefClk) && (QpllRefClk <= 245000000)) || + ((409375000 <= QpllRefClk) && (QpllRefClk <= 490000000))) { + SysClkDataSel = XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK; + SysClkOutSel = XHDMIPHY1_SYSCLKSELOUT_TYPE_QPLL1_REFCLK; + ActiveCmnId = XHDMIPHY1_CHANNEL_ID_CMN1; + QpllClkMin = (u32) XHDMIPHY1_HDMI_GTHE3_QPLL1_REFCLK_MIN; + } + else { + SysClkDataSel = XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK; + SysClkOutSel = XHDMIPHY1_SYSCLKSELOUT_TYPE_QPLL0_REFCLK; + ActiveCmnId = XHDMIPHY1_CHANNEL_ID_CMN0; + QpllClkMin = (u32) XHDMIPHY1_HDMI_GTHE3_QPLL0_REFCLK_MIN; + } +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE4) + /* Determine which QPLL to use. */ + if (((102343750 <= QpllRefClk) && (QpllRefClk <= 122500000)) || + ((204687500 <= QpllRefClk) && (QpllRefClk <= 245000000)) || + ((409375000 <= QpllRefClk) && (QpllRefClk <= 490000000))) { + SysClkDataSel = XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK; + SysClkOutSel = XHDMIPHY1_SYSCLKSELOUT_TYPE_QPLL1_REFCLK; + ActiveCmnId = XHDMIPHY1_CHANNEL_ID_CMN1; + QpllClkMin = (u32) XHDMIPHY1_HDMI_GTHE4_QPLL1_REFCLK_MIN; + } + else { + SysClkDataSel = XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK; + SysClkOutSel = XHDMIPHY1_SYSCLKSELOUT_TYPE_QPLL0_REFCLK; + ActiveCmnId = XHDMIPHY1_CHANNEL_ID_CMN0; + QpllClkMin = (u32) XHDMIPHY1_HDMI_GTHE4_QPLL0_REFCLK_MIN; + } +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE4) + /* Determine which QPLL to use. */ + if (((102343750 <= QpllRefClk) && (QpllRefClk <= 122500000)) || + ((204687500 <= QpllRefClk) && (QpllRefClk <= 245000000)) || + ((409375000 <= QpllRefClk) && (QpllRefClk <= 490000000))) { + SysClkDataSel = XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK; + SysClkOutSel = XHDMIPHY1_SYSCLKSELOUT_TYPE_QPLL1_REFCLK; + ActiveCmnId = XHDMIPHY1_CHANNEL_ID_CMN1; + QpllClkMin = (u32) XHDMIPHY1_HDMI_GTYE4_QPLL1_REFCLK_MIN; + } + else { + SysClkDataSel = XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK; + SysClkOutSel = XHDMIPHY1_SYSCLKSELOUT_TYPE_QPLL0_REFCLK; + ActiveCmnId = XHDMIPHY1_CHANNEL_ID_CMN0; + QpllClkMin = (u32) XHDMIPHY1_HDMI_GTYE4_QPLL0_REFCLK_MIN; + } +#endif + + /* Update QPLL clock selections. */ + XHdmiphy1_CfgSysClkDataSel(InstancePtr, QuadId, Dir, SysClkDataSel); + XHdmiphy1_CfgSysClkOutSel(InstancePtr, QuadId, Dir, SysClkOutSel); + + /* RX is using QPLL. */ + if (Dir == XHDMIPHY1_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->RxHdmi21Cfg.IsEnabled == 0) { + if (InstancePtr->HdmiRxTmdsClockRatio) { + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, + XHDMIPHY1_CHANNEL_ID_CMNA, (RefClk * 40)); + } + else { + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, + XHDMIPHY1_CHANNEL_ID_CMNA, (RefClk * 10)); + } + } else { /* InstancePtr->RxHdmi21Cfg.IsEnabled == 1 */ + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, + XHDMIPHY1_CHANNEL_ID_CMNA, + InstancePtr->RxHdmi21Cfg.LineRate); + } + + /* Clear DRU is enabled flag. */ + InstancePtr->HdmiRxDruIsEnabled = 0; + + /* Set RX data width. */ + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, + &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + if (InstancePtr->Config.TransceiverWidth == 2) { + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)]. + RxDataWidth = 20; + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)]. + RxIntDataWidth = 2; + } + else { + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)]. + RxDataWidth = 40; + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)]. + RxIntDataWidth = 4; + } + } + + } + /* The reference clock is below the minimum frequency thus + * select the DRU. */ + else if (InstancePtr->Config.DruIsPresent) { + RefClk = XHdmiphy1_DruGetRefClkFreqHz(InstancePtr); + /* Check DRU frequency */ + if (RefClk == XST_FAILURE) { + XHdmiphy1_LogWrite(InstancePtr, + XHDMIPHY1_LOG_EVT_DRU_CLK_ERR, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + return (XST_FAILURE); + } + + + /* 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. */ + XHdmiphy1_CfgLineRate(InstancePtr, + QuadId, XHDMIPHY1_CHANNEL_ID_CMNA, + (GetGtHdmiPtr(InstancePtr))->DruLineRate); + + /* Set DRU is enabled flag. */ + InstancePtr->HdmiRxDruIsEnabled = 1; + + /* Set RX data width to 40 and 4 bytes. */ + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, + &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[ + XHDMIPHY1_CH2IDX(Id)].RxDataWidth = 20; + InstancePtr->Quads[QuadId].Plls[ + XHDMIPHY1_CH2IDX(Id)].RxIntDataWidth = 2; + } + } + else { + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_NO_DRU, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + return (XST_FAILURE); + } + } + + /* TX is using QPLL. */ + else { + /* Set default TX sample rate. */ + InstancePtr->HdmiTxSampleRate = 1; + + if (InstancePtr->TxHdmi21Cfg.IsEnabled == 0) { + /* Update TX line rates. */ + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, + XHDMIPHY1_CHANNEL_ID_CMNA, (u64)((*RefClkPtr) * 10)); + TxLineRate = (*RefClkPtr) / 100000;; + + /* Check if the linerate is above the 340 Mcsc. */ + if ((TxLineRate) >= 3400) { + (*RefClkPtr) = (*RefClkPtr) / 4; + } + } else { /* InstancePtr->TxHdmi21Cfg.IsEnabled == 1 */ + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, + XHDMIPHY1_CHANNEL_ID_CMNA, + InstancePtr->TxHdmi21Cfg.LineRate); + } + } + + /* Calculate QPLL values. */ + for (SRIndex = 0; SRIndex < sizeof(SRArray); SRIndex++) { + /* Only use oversampling when then TX is using the QPLL. */ + if (Dir == XHDMIPHY1_DIR_TX) { + SRValue = SRArray[SRIndex]; + + if (InstancePtr->TxHdmi21Cfg.IsEnabled == 0) { + /* TX reference clock is below the minimum QPLL clock + * input frequency. */ + if ((*RefClkPtr) < QpllClkMin) { + RefClk = ((*RefClkPtr) * SRValue); + + /* Calculate scaled line rate. */ + if (TxLineRate >= 3400) { + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, + XHDMIPHY1_CHANNEL_ID_CMNA, + (u64)(RefClk * 40)); + } + else { + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, + XHDMIPHY1_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) { + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, + XHDMIPHY1_CHANNEL_ID_CMNA, + (u64)(RefClk * 40 *SRValue)); + } + + else { + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, + XHDMIPHY1_CHANNEL_ID_CMNA, + (u64)(RefClk * 10 *SRValue)); + } + } + } + else { /* InstancePtr->TxHdmi21Cfg.IsEnabled == 1 */ + RefClk = (*RefClkPtr); + } + } + /* For all other reference clocks force sample rate to one. */ + else { + SRValue = 1; + } + + Status = XHdmiphy1_ClkCalcParams(InstancePtr, QuadId, ActiveCmnId, + Dir, RefClk); + if (Status == (XST_SUCCESS)) { + /* Only execute when the TX is using the QPLL. */ + if (Dir == XHDMIPHY1_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) { + XHdmiphy1_LogWrite(InstancePtr, + XHDMIPHY1_LOG_EVT_GT_QPLL_CFG_ERR, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + return (XST_FAILURE); + } + } + + /* Check Userclock Frequency */ + /* (300 MHz + 0.5%) + 10 KHz (Clkdet accuracy) */ + if (301500000 < + (XHdmiphy1_GetLineRateHz(InstancePtr, QuadId, + ActiveCmnId) / + (InstancePtr->Config.TransceiverWidth * 10))) { + XHdmiphy1_LogWrite(InstancePtr, + XHDMIPHY1_LOG_EVT_USRCLK_ERR, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + return (XST_FAILURE); + } + + return (XST_SUCCESS); + } + } + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_GT_QPLL_CFG_ERR, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + 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 XHdmiphy1_HdmiCpllParam(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir) +{ + u32 Status; + u64 RefClk = 0; + u32 *RefClkPtr; + u32 TxLineRate = 0; + XHdmiphy1_ChannelId ChannelId = XHDMIPHY1_CHANNEL_ID_CHA; + u8 Id, Id0, Id1; + + u8 SRArray[] = {1, 3, 5}; + u8 SRIndex; + u8 SRValue; + + /* Suppress Warning Messages */ + ChId = ChId; + + /* TX is using CPLL. */ + if (Dir == XHDMIPHY1_DIR_TX) { + + /* Set default TX sample rate. */ + InstancePtr->HdmiTxSampleRate = 1; + + /* Set line rate. */ + RefClkPtr = &InstancePtr->HdmiTxRefClkHz; + if (InstancePtr->TxHdmi21Cfg.IsEnabled == 0) { + XHdmiphy1_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; + } + } else { /* InstancePtr->TxHdmi21Cfg.IsEnabled == 1 */ + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, ChannelId, + (u64)(InstancePtr->TxHdmi21Cfg.LineRate)); + TxLineRate = InstancePtr->TxHdmi21Cfg.LineRate / 100000; + } + } + /* 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->RxHdmi21Cfg.IsEnabled == 0) { + if (InstancePtr->HdmiRxTmdsClockRatio) { + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, + ChannelId, (RefClk * 40)); + } + else { + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, + ChannelId, (RefClk * 10)); + } + } else { /* InstancePtr->RxHdmi21Cfg.IsEnabled == 1 */ + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, + ChannelId, InstancePtr->RxHdmi21Cfg.LineRate); + } + + /* Clear DRU is enabled flag. */ + InstancePtr->HdmiRxDruIsEnabled = 0; + + /* Set RX data width. */ + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, + &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + if (InstancePtr->Config.TransceiverWidth == 2) { + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)]. + RxDataWidth = 20; + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)]. + RxIntDataWidth = 2; + } + else { + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)]. + RxDataWidth = 40; + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_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) { + XHdmiphy1_LogWrite(InstancePtr, + XHDMIPHY1_LOG_EVT_GT_CPLL_CFG_ERR, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + return (XST_FAILURE); + } + + RefClk = XHdmiphy1_DruGetRefClkFreqHz(InstancePtr); + /* Check DRU frequency */ + if (RefClk == XST_FAILURE) { + XHdmiphy1_LogWrite(InstancePtr, + XHDMIPHY1_LOG_EVT_DRU_CLK_ERR, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + return (XST_FAILURE); + } + + /* 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. */ + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, + ChannelId, + (GetGtHdmiPtr(InstancePtr))-> + DruLineRate); + + /* Set DRU is enabled flag. */ + InstancePtr->HdmiRxDruIsEnabled = 1; + + /* Set RX data width. */ + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, + &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[ + XHDMIPHY1_CH2IDX(Id)]. + RxDataWidth = 20; + InstancePtr->Quads[QuadId].Plls[ + XHDMIPHY1_CH2IDX(Id)]. + RxIntDataWidth = 2; + } + + if (TxLineRate > (((GetGtHdmiPtr(InstancePtr)) + ->DruLineRate) / 1000000)) { + XHdmiphy1_LogWrite(InstancePtr, + XHDMIPHY1_LOG_EVT_VD_NOT_SPRTD_ERR, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + return (XST_FAILURE); + } + } + else { + /* Return config not found error when TMDS ratio is 1/40 */ + if (InstancePtr->HdmiRxTmdsClockRatio) { + XHdmiphy1_LogWrite(InstancePtr, + XHDMIPHY1_LOG_EVT_GT_CPLL_CFG_ERR, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + } + else { + XHdmiphy1_LogWrite(InstancePtr, + XHDMIPHY1_LOG_EVT_NO_DRU, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + } + 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 == XHDMIPHY1_DIR_TX) { + SRValue = SRArray[SRIndex]; + + if (InstancePtr->TxHdmi21Cfg.IsEnabled == 0) { + /* Multiply the reference clock with the sample rate + * value. */ + RefClk = ((*RefClkPtr) * SRValue); + + /* Calculate scaled line rate. */ + if (TxLineRate >= 3400) { + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, + ChannelId, (RefClk * 40)); + } + else { + XHdmiphy1_CfgLineRate(InstancePtr, QuadId, + ChannelId, (RefClk * 10)); + } + } + else { /* InstancePtr->TxHdmi21Cfg.IsEnabled == 1 */ + RefClk = (*RefClkPtr); + } + } + /* For all other reference clocks force sample rate to one. */ + else { + SRValue = 1; + } + + Status = XHdmiphy1_ClkCalcParams(InstancePtr, QuadId, + ChannelId, Dir, RefClk); + if (Status == (XST_SUCCESS)) { + /* Only execute when the TX is using the QPLL. */ + if (Dir == XHDMIPHY1_DIR_TX) { + InstancePtr->HdmiTxSampleRate = SRValue; + (*RefClkPtr) = (*RefClkPtr) * SRValue; + } + + /* Check Userclock Frequency */ + /* (300 MHz + 0.5%) + 10 KHz (Clkdet accuracy) */ + if (301500000 < (XHdmiphy1_GetLineRateHz(InstancePtr, QuadId, + XHDMIPHY1_CHANNEL_ID_CH1) / + (InstancePtr->Config.TransceiverWidth * 10))) { + XHdmiphy1_LogWrite(InstancePtr, + XHDMIPHY1_LOG_EVT_USRCLK_ERR, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + return (XST_FAILURE); + } + + return (XST_SUCCESS); + } + } + + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_GT_CPLL_CFG_ERR, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + return (XST_FAILURE); +} +#endif + +/*****************************************************************************/ +/** +* This function update/set the HDMI TX parameter. +* +* @param InstancePtr is a pointer to the Hdmiphy 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 XHdmiphy1_SetHdmiTxParam(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_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))); + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + /* Only calculate the QPLL/CPLL parameters when the GT TX and RX are not + * coupled. */ + if (XHdmiphy1_IsTxUsingCpll(InstancePtr, QuadId, ChId)) { + Status = XHdmiphy1_HdmiCpllParam(InstancePtr, QuadId, ChId, + XHDMIPHY1_DIR_TX); + } + else { + Status = XHdmiphy1_HdmiQpllParam(InstancePtr, QuadId, ChId, + XHDMIPHY1_DIR_TX); + /* Update SysClk and PLL Clk registers immediately. */ + XHdmiphy1_WriteCfgRefClkSelReg(InstancePtr, QuadId); + } +#else + Status = XHdmiphy1_HdmiTxPllParam(InstancePtr, QuadId, ChId); +#endif + + if (Status == XST_FAILURE) { + return Status; + } + + /* Is HDMITXSS PPC match with HDMIPHY PPC? */ + if (Ppc == InstancePtr->Config.Ppc) { + Status = (XST_SUCCESS); + } + else { + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_PPC_MSMTCH_ERR, 1); + XHdmiphy1_ErrorHandler(InstancePtr); + Status = (XST_FAILURE); + } + if (Status == (XST_SUCCESS)) { + /* HDMI 2.1 */ + if (InstancePtr->TxHdmi21Cfg.IsEnabled) { + InstancePtr->Quads[QuadId].TxMmcm.ClkFbOutMult = + XHDMIPHY1_FRL_VIDCLK_MMCM_FBOUTMULT; + InstancePtr->Quads[QuadId].TxMmcm.DivClkDivide = + XHDMIPHY1_FRL_VIDCLK_MMCM_DIVCLK; + InstancePtr->Quads[QuadId].TxMmcm.ClkOut0Div = + XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT0DIV; + InstancePtr->Quads[QuadId].TxMmcm.ClkOut1Div = + XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT1DIV; + InstancePtr->Quads[QuadId].TxMmcm.ClkOut2Div = + XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT2DIV; + return Status; + } + + /* 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 = XHdmiphy1_HdmiCfgCalcMmcmParam(InstancePtr, QuadId, + ChId, XHDMIPHY1_DIR_TX, Ppc, XVIDC_BPC_8); + } + /* Other colorspaces. */ + else { + Status = XHdmiphy1_HdmiCfgCalcMmcmParam(InstancePtr, QuadId, + ChId, XHDMIPHY1_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 Hdmiphy 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 XHdmiphy1_SetHdmiRxParam(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId) +{ + XHdmiphy1_ChannelId ChanId = ChId; + XHdmiphy1_PllType PllType; + u32 Status; + u64 DruCenterFreq; + + /* Verify arguments. */ + Xil_AssertNonvoid(InstancePtr != NULL); + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + if (XHdmiphy1_IsRxUsingCpll(InstancePtr, QuadId, ChId)) { + Status = XHdmiphy1_HdmiCpllParam(InstancePtr, QuadId, ChId, + XHDMIPHY1_DIR_RX); + } + else { + Status = XHdmiphy1_HdmiQpllParam(InstancePtr, QuadId, ChId, + XHDMIPHY1_DIR_RX); + /* Update SysClk and PLL Clk registers immediately */ + XHdmiphy1_WriteCfgRefClkSelReg(InstancePtr, QuadId); + } +#else + Status = XHdmiphy1_HdmiRxPllParam(InstancePtr, QuadId, ChId); +#endif + + if (InstancePtr->HdmiRxDruIsEnabled) { + /* Determine PLL type. */ + PllType = XHdmiphy1_GetPllType(InstancePtr, 0, XHDMIPHY1_DIR_RX, + XHDMIPHY1_CHANNEL_ID_CH1); + /* Update the ChId */ + ChanId = XHdmiphy1_GetRcfgChId(InstancePtr, 0, + XHDMIPHY1_DIR_RX, PllType); + + DruCenterFreq = XHdmiphy1_DruCalcCenterFreqHz(InstancePtr, QuadId, + ChanId); + XHdmiphy1_DruSetCenterFreqHz(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, + DruCenterFreq); + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function enables or disables the Pattern Generator for the GT Channel 4 +* when it isused to generate the TX TMDS Clock. +* +* @param InstancePtr is a pointer to the XHdmiphy1 core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Enable TRUE/FALSE +* +* @return None. +* +******************************************************************************/ +void XHdmiphy1_PatgenEnable(XHdmiphy1 *InstancePtr, u8 QuadId, u8 Enable) +{ + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_PATGEN_CTRL_REG); + + if (Enable) { + RegVal |= XHDMIPHY1_PATGEN_CTRL_ENABLE_MASK; + } + else { + RegVal &= ~XHDMIPHY1_PATGEN_CTRL_ENABLE_MASK; + } + + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_PATGEN_CTRL_REG, RegVal); +} + +/*****************************************************************************/ +/** +* This function sets the Pattern Generator for the GT Channel 4 when it is +* used to generate the TX TMDS Clock. +* +* @param InstancePtr is a pointer to the XHdmiphy1 core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param TxLineRate in Mbps. +* +* @return None. +* +******************************************************************************/ +void XHdmiphy1_PatgenSetRatio(XHdmiphy1 *InstancePtr, u8 QuadId, + u64 TxLineRate) +{ + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + RegVal = (XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_PATGEN_CTRL_REG) + & ~XHDMIPHY1_PATGEN_CTRL_RATIO_MASK); + + if ((TxLineRate >= 3400) && (InstancePtr->HdmiTxSampleRate == 1)) { + RegVal |= XHDMIPHY1_Patgen_Ratio_40 & + XHDMIPHY1_PATGEN_CTRL_RATIO_MASK; + } + else { + RegVal |= InstancePtr->HdmiTxSampleRate & + XHDMIPHY1_PATGEN_CTRL_RATIO_MASK; + } + + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_PATGEN_CTRL_REG, RegVal); +} + +/*****************************************************************************/ +/** +* This function will configure the HDMIPHY to HDMI 2.0 mode +* +* @param InstancePtr is a pointer to the Hdmiphy 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 TX parameters set/updated. +* - XST_FAILURE if low resolution video not supported. +* +* @note None. +* +******************************************************************************/ +u32 XHdmiphy1_Hdmi20Config(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir) +{ + XHdmiphy1_PllType PllType; + u32 Status = XST_SUCCESS; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_TMDS_RECONFIG, Dir); + + /* Determine PLL type. */ + PllType = XHdmiphy1_GetPllType(InstancePtr, 0, Dir, + XHDMIPHY1_CHANNEL_ID_CH1); + + /* Update HDMI Configurations */ + if (Dir == XHDMIPHY1_DIR_TX) { + InstancePtr->TxHdmi21Cfg.LineRate = 0; + InstancePtr->TxHdmi21Cfg.NChannels = 0; + InstancePtr->TxHdmi21Cfg.IsEnabled = FALSE; + } else { + InstancePtr->RxHdmi21Cfg.LineRate = 0; + InstancePtr->RxHdmi21Cfg.NChannels = 0; + InstancePtr->RxHdmi21Cfg.IsEnabled = FALSE; + } + + XHdmiphy1_MmcmSetClkinsel(InstancePtr, QuadId, Dir, + XHDMIPHY1_MMCM_CLKINSEL_CLKIN1); + + /* Disable Clock Detector Interrupts */ + if (Dir == XHDMIPHY1_DIR_TX) { + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE); + } else { + XHdmiphy1_IntrEnable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE); + } + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + /* Update reference clock election. */ + XHdmiphy1_CfgPllRefClkSel(InstancePtr, 0, + ((PllType == XHDMIPHY1_PLL_TYPE_CPLL) ? + XHDMIPHY1_CHANNEL_ID_CHA : XHDMIPHY1_CHANNEL_ID_CMNA), + ((Dir == XHDMIPHY1_DIR_TX) ? + InstancePtr->Config.TxRefClkSel : + InstancePtr->Config.RxRefClkSel)); + + /* Update RefClk selection. */ + XHdmiphy1_WriteCfgRefClkSelReg(InstancePtr, 0); +#else + /* Suppress Warning Messages */ + PllType = PllType; +#endif + + return Status; +} + +/*****************************************************************************/ +/** +* This function will configure the GT for HDMI 2.1 operation +* +* @param InstancePtr is a pointer to the Hdmiphy 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 TX parameters set/updated. +* - XST_FAILURE if low resolution video not supported. +* +* @note None. +* +******************************************************************************/ +u32 XHdmiphy1_Hdmi21Config(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, u64 LineRate, u8 NChannels) +{ + XHdmiphy1_PllType PllType; + u32 Status = XST_SUCCESS; + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE4) || \ + (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE4) + char SpeedGrade[5] = XPAR_HDMIPHY1_0_SPEEDGRADE_STR; + char CompVal[5] = "-1"; + char *SpeedGradePtr = &SpeedGrade[0]; + char *CompValPtr = &CompVal[0]; + + /* Look for -1 Parts. Max Line rate is 8Gbps */ + if (strncmp(SpeedGradePtr, CompValPtr, 2) == 0) { + if (LineRate > 8e9) { + XHdmiphy1_LogWrite(InstancePtr, + XHDMIPHY1_LOG_EVT_SPDGRDE_ERR, Dir); + XHdmiphy1_ErrorHandler(InstancePtr); + return XST_FAILURE; + } + } +#endif + + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_FRL_RECONFIG, Dir); + + /* Determine PLL type. */ + PllType = XHdmiphy1_GetPllType(InstancePtr, 0, Dir, + XHDMIPHY1_CHANNEL_ID_CH1); + + /* Disable Clock Detector Interrupts */ + if (Dir == XHDMIPHY1_DIR_TX) { + if (InstancePtr->Config.TxRefClkSel != + InstancePtr->Config.TxFrlRefClkSel) { + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE); + } + /* Enable 4th Channel output */ + XHdmiphy1_Clkout1OBufTdsEnable(InstancePtr, XHDMIPHY1_DIR_TX, (TRUE)); + } else { + if (InstancePtr->Config.RxRefClkSel != + InstancePtr->Config.RxFrlRefClkSel) { + XHdmiphy1_IntrDisable(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE); + } + } + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + /* Update reference clock election. */ + XHdmiphy1_CfgPllRefClkSel(InstancePtr, 0, + ((PllType == XHDMIPHY1_PLL_TYPE_CPLL) ? + XHDMIPHY1_CHANNEL_ID_CHA : XHDMIPHY1_CHANNEL_ID_CMNA), + ((Dir == XHDMIPHY1_DIR_TX) ? + InstancePtr->Config.TxFrlRefClkSel : + InstancePtr->Config.RxFrlRefClkSel)); + + /* Update RefClk selection. */ + XHdmiphy1_WriteCfgRefClkSelReg(InstancePtr, 0); +#endif + + /* Update HDMI Configurations */ + if (Dir == XHDMIPHY1_DIR_TX) { + InstancePtr->HdmiTxRefClkHz = XHDMIPHY1_HDMI21_FRL_REFCLK; + InstancePtr->TxHdmi21Cfg.LineRate = LineRate; + InstancePtr->TxHdmi21Cfg.NChannels = NChannels; + InstancePtr->TxHdmi21Cfg.IsEnabled = TRUE; + + Status = XHdmiphy1_SetHdmiTxParam(InstancePtr, 0, + ((PllType == XHDMIPHY1_PLL_TYPE_CPLL) ? + XHDMIPHY1_CHANNEL_ID_CHA : XHDMIPHY1_CHANNEL_ID_CMNA), + InstancePtr->Config.Ppc, + XVIDC_BPC_8, + XVIDC_CSF_RGB); + + /* Mask the MMCM Lock */ + XHdmiphy1_MmcmLockedMaskEnable(InstancePtr, 0, Dir, TRUE); + + if (InstancePtr->Config.TxRefClkSel == + InstancePtr->Config.TxFrlRefClkSel) { + XHdmiphy1_MmcmSetClkinsel(InstancePtr, QuadId, Dir, + XHDMIPHY1_MMCM_CLKINSEL_CLKIN1); + } else { + XHdmiphy1_MmcmSetClkinsel(InstancePtr, QuadId, Dir, + XHDMIPHY1_MMCM_CLKINSEL_CLKIN2); + } + if (InstancePtr->Config.TxRefClkSel != + InstancePtr->Config.TxFrlRefClkSel) { + XHdmiphy1_HdmiTxTimerTimeoutHandler(InstancePtr); + } + } else { + InstancePtr->HdmiRxRefClkHz = XHDMIPHY1_HDMI21_FRL_REFCLK; + InstancePtr->RxHdmi21Cfg.LineRate = LineRate; + InstancePtr->RxHdmi21Cfg.NChannels = NChannels; + InstancePtr->RxHdmi21Cfg.IsEnabled = TRUE; + + /* Set MMCM dividers for FRL mode */ + InstancePtr->Quads[QuadId].RxMmcm.ClkFbOutMult = + XHDMIPHY1_FRL_VIDCLK_MMCM_FBOUTMULT; + InstancePtr->Quads[QuadId].RxMmcm.DivClkDivide = + XHDMIPHY1_FRL_VIDCLK_MMCM_DIVCLK; + InstancePtr->Quads[QuadId].RxMmcm.ClkOut0Div = + XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT0DIV; + InstancePtr->Quads[QuadId].RxMmcm.ClkOut1Div = + XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT1DIV; + InstancePtr->Quads[QuadId].RxMmcm.ClkOut2Div = + XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT2DIV; + + /* Mask the MMCM Lock */ + XHdmiphy1_MmcmLockedMaskEnable(InstancePtr, 0, Dir, TRUE); + + if (InstancePtr->Config.RxRefClkSel != + InstancePtr->Config.RxFrlRefClkSel) { + /* Set MMCM CLKINSEL to CLK2 */ + XHdmiphy1_MmcmSetClkinsel(InstancePtr, QuadId, Dir, + XHDMIPHY1_MMCM_CLKINSEL_CLKIN2); + + /* Start RX MMCM. */ + XHdmiphy1_MmcmStart(InstancePtr, 0, XHDMIPHY1_DIR_RX); + + XHdmiphy1_HdmiRxTimerTimeoutHandler(InstancePtr); + } + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function prints Video PHY debug information related to HDMI. +* +* @param InstancePtr is a pointer to the Hdmiphy core instance. +* @param QuadId is the GT quad ID to operate on. +* @param ChId is the channel ID to operate on. +* @param buff Buffer to print to +* @param buff_size Maximum size of buff +* +* @return Number of characters printed in buff. +* +* @note None. +* +******************************************************************************/ + +int XHdmiphy1_HdmiDebugInfo(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, char *buff, int buff_size) +{ + int strSize = 0; + u32 RegValue; +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + XHdmiphy1_Channel *ChPtr; + XHdmiphy1_ChannelId CmnId = XHDMIPHY1_CHANNEL_ID_CMN0; + u8 CpllDVal; + u8 QpllDVal; + u8 UsesQpll0 = 0; + + ChPtr = &InstancePtr->Quads[QuadId].Plls[0]; + + if (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_TX)) { + if (XHdmiphy1_IsTxUsingCpll(InstancePtr, QuadId, ChId)) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX: CPLL\n"); + } + else { + if ((ChPtr->TxDataRefClkSel == + XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL_OUTCLK) || + (ChPtr->TxDataRefClkSel == + XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK)) { + UsesQpll0 = (TRUE); + CmnId = XHDMIPHY1_CHANNEL_ID_CMN0; + } + else { + UsesQpll0 = (FALSE); + CmnId = XHDMIPHY1_CHANNEL_ID_CMN1; + } + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX: QPLL%d\n", (UsesQpll0 ? 0 : 1)); + } + } + + if (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_RX)) { + if (XHdmiphy1_IsRxUsingCpll(InstancePtr, QuadId, ChId)) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX: CPLL\n"); + } + else { + if ((ChPtr->RxDataRefClkSel == + XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL_OUTCLK) || + (ChPtr->RxDataRefClkSel == + XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK)) { + UsesQpll0 = (TRUE); + CmnId = XHDMIPHY1_CHANNEL_ID_CMN0; + } + else { + UsesQpll0 = (FALSE); + CmnId = XHDMIPHY1_CHANNEL_ID_CMN1; + } + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX: QPLL%d\n", (UsesQpll0 ? 0 : 1)); + } + } + + if (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_TX)) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX state: "); + switch (InstancePtr->Quads[QuadId]. + Plls[XHDMIPHY1_CH2IDX(ChId)].TxState) { + case (XHDMIPHY1_GT_STATE_IDLE): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "idle\n"); + break; + case (XHDMIPHY1_GT_STATE_LOCK): + if (XHdmiphy1_IsTxUsingCpll(InstancePtr, QuadId, ChId)) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "CPLL lock\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "QPLL%d lock\n", (UsesQpll0 ? 0 : 1)); + } + break; + case (XHDMIPHY1_GT_STATE_RESET): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "GT reset\n"); + break; + case (XHDMIPHY1_GT_STATE_ALIGN): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "align\n"); + break; + case (XHDMIPHY1_GT_STATE_READY): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "ready\n"); + break; + default: + strSize += scnprintf(buff+strSize, buff_size-strSize, + "unknown\n"); + break; + } + } + + if (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_RX)) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX state: "); + switch (InstancePtr->Quads[QuadId]. + Plls[XHDMIPHY1_CH2IDX(ChId)].RxState) { + case (XHDMIPHY1_GT_STATE_IDLE): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "idle\n"); + break; + case (XHDMIPHY1_GT_STATE_LOCK): + if (XHdmiphy1_IsRxUsingCpll(InstancePtr, QuadId, ChId)) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "CPLL lock\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "QPLL%d lock\n", (UsesQpll0 ? 0 : 1)); + } + break; + case (XHDMIPHY1_GT_STATE_RESET): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "GT reset\n"); + break; + case (XHDMIPHY1_GT_STATE_READY): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "ready\n"); + break; + default: + strSize += scnprintf(buff+strSize, buff_size-strSize, + "unknown\n"); + break; + } + } + + if (XHdmiphy1_IsTxUsingCpll(InstancePtr, QuadId, ChId)) { + QpllDVal = ChPtr->RxOutDiv; + CpllDVal = ChPtr->TxOutDiv; + } + else { + CpllDVal = ChPtr->RxOutDiv; + QpllDVal = ChPtr->TxOutDiv; + } + + strSize += scnprintf(buff+strSize, buff_size-strSize, "\n"); + if ((XHdmiphy1_IsTxUsingQpll(InstancePtr, QuadId, ChId) && + (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_TX))) || + (XHdmiphy1_IsRxUsingQpll(InstancePtr, QuadId, ChId) && + (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_RX)))) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "QPLL%d settings\n", (UsesQpll0 ? 0 : 1)); + strSize += scnprintf(buff+strSize, buff_size-strSize, + "-------------\n" \ + "M : %d - N : %d - D : %d\n\n", + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(CmnId)]. + PllParams.MRefClkDiv, + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(CmnId)]. + PllParams.NFbDiv, QpllDVal); + } + + if ((XHdmiphy1_IsTxUsingCpll(InstancePtr, QuadId, ChId) && + (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_TX))) || + (XHdmiphy1_IsRxUsingCpll(InstancePtr, QuadId, ChId) && + (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_RX)))) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "CPLL settings\n" \ + "-------------\n" \ + "M : %d - N1 : %d - N2 : %d - D : %d\n\n", + ChPtr->PllParams.MRefClkDiv, + ChPtr->PllParams.N1FbDiv, ChPtr->PllParams.N2FbDiv, + CpllDVal); + } +#else + + if (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_TX)) { + if (XHdmiphy1_IsTxUsingLcpll(InstancePtr, QuadId, ChId)) { + xil_printf("TX: LCPLL\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX: RPLL\n"); + } + } + + if (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_RX)) { + if (XHdmiphy1_IsRxUsingLcpll(InstancePtr, QuadId, ChId)) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX: LCPLL\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX: RPLL\n"); + } + } + + if (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_TX)) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX state: "); + switch (InstancePtr->Quads[QuadId]. + Plls[XHDMIPHY1_CH2IDX(ChId)].TxState) { + case (XHDMIPHY1_GT_STATE_IDLE): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "idle\n"); + break; + case (XHDMIPHY1_GT_STATE_GPO_RE): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "GPO Assert\n"); + break; + case (XHDMIPHY1_GT_STATE_LOCK): + if (XHdmiphy1_IsTxUsingLcpll(InstancePtr, QuadId, ChId)) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "LCPLL lock\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RPLL lock\n"); + } + break; + case (XHDMIPHY1_GT_STATE_RESET): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "GT reset\n"); + break; + case (XHDMIPHY1_GT_STATE_ALIGN): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "align\n"); + break; + case (XHDMIPHY1_GT_STATE_READY): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "ready\n"); + break; + default: + strSize += scnprintf(buff+strSize, buff_size-strSize, + "unknown\n"); + break; + } + } + + if (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_RX)) { + xil_printf("RX state: "); + switch (InstancePtr->Quads[QuadId]. + Plls[XHDMIPHY1_CH2IDX(ChId)].RxState) { + case (XHDMIPHY1_GT_STATE_IDLE): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "idle\n"); + break; + case (XHDMIPHY1_GT_STATE_GPO_RE): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "GPO Assert\n"); + break; + case (XHDMIPHY1_GT_STATE_LOCK): + if (XHdmiphy1_IsRxUsingLcpll(InstancePtr, QuadId, ChId)) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "LCPLL lock\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RPLL lock\n"); + } + break; + case (XHDMIPHY1_GT_STATE_RESET): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "GT reset\n"); + break; + case (XHDMIPHY1_GT_STATE_READY): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "ready\n"); + break; + default: + strSize += scnprintf(buff+strSize, buff_size-strSize, + "unknown\n"); + break; + } + } + + strSize += scnprintf(buff+strSize, buff_size-strSize, "\n"); + if ((XHdmiphy1_IsTxUsingLcpll(InstancePtr, QuadId, ChId) && + (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_TX))) || + (XHdmiphy1_IsRxUsingLcpll(InstancePtr, QuadId, ChId) && + (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_RX)))) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "LCPLL settings\n" \ + "-------------\n" \ + "LR CFG : %d\n", + InstancePtr->Quads[QuadId].Lcpll.LineRateCfg); + strSize += scnprintf(buff+strSize, buff_size-strSize, "\n"); + } + + if ((XHdmiphy1_IsTxUsingRpll(InstancePtr, QuadId, ChId) && + (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_TX))) || + (XHdmiphy1_IsRxUsingRpll(InstancePtr, QuadId, ChId) && + (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_RX)))) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RPLL settings\n" \ + "-------------\n" \ + "LR CFG : %d\n", + InstancePtr->Quads[QuadId].Rpll.LineRateCfg); + strSize += scnprintf(buff+strSize, buff_size-strSize, "\n"); + } +#endif + if (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_RX)) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX MMCM settings\n" + "-------------\n" + "Mult : %d - Div : %d - Clk0Div : %d - Clk1Div : %d - " + "Clk2Div : %d\n\n", + 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); + } + + if (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_TX)) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX MMCM settings\n" \ + "-------------\n" \ + "Mult : %d - Div : %d - Clk0Div : %d - Clk1Div : %d - " + "Clk2Div : %d\n\n", + 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); + } + + if ((InstancePtr->Config.DruIsPresent) && + (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_RX))) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "DRU Settings\n" \ + "-------------\n"); + RegValue = XHdmiphy1_DruGetVersion(InstancePtr); + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Version : %d\n", RegValue); + + if (InstancePtr->HdmiRxDruIsEnabled) { + RegValue = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_DRU_GAIN_REG(ChId)); + + + strSize += scnprintf(buff+strSize, buff_size-strSize, + "G1 : %d\nG1_P : %d\n" + "G2 : %d\n", + ((RegValue & XHDMIPHY1_DRU_GAIN_G1_MASK)), + ((RegValue & XHDMIPHY1_DRU_GAIN_G1_P_MASK) >> + XHDMIPHY1_DRU_GAIN_G1_P_SHIFT), + ((RegValue & XHDMIPHY1_DRU_GAIN_G2_MASK) >> + XHDMIPHY1_DRU_GAIN_G2_SHIFT)); + + + RegValue = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_DRU_CFREQ_H_REG(ChId)); + + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Center_F : %x", RegValue); + + RegValue = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_DRU_CFREQ_L_REG(ChId)); + + strSize += scnprintf(buff+strSize, buff_size-strSize, + "%x\n", RegValue); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "DRU is disabled\n"); + } + + strSize += scnprintf(buff+strSize, buff_size-strSize," \n"); + } + return strSize; +} + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE3) +static const XHdmiphy1_GtHdmiChars Gthe3HdmiChars = { + .DruLineRate = XHDMIPHY1_HDMI_GTHE3_DRU_LRATE, + .PllScale = XHDMIPHY1_HDMI_GTHE3_PLL_SCALE, + .Qpll0RefClkMin = XHDMIPHY1_HDMI_GTHE3_QPLL0_REFCLK_MIN, + .Qpll1RefClkMin = XHDMIPHY1_HDMI_GTHE3_QPLL1_REFCLK_MIN, + .CpllRefClkMin = XHDMIPHY1_HDMI_GTHE3_CPLL_REFCLK_MIN, + .TxMmcmScale = XHDMIPHY1_HDMI_GTHE3_TX_MMCM_SCALE, + .TxMmcmFvcoMin = XHDMIPHY1_HDMI_GTHE3_TX_MMCM_FVCO_MIN, + .TxMmcmFvcoMax = XHDMIPHY1_HDMI_GTHE3_TX_MMCM_FVCO_MAX, + .RxMmcmScale = XHDMIPHY1_HDMI_GTHE3_RX_MMCM_SCALE, + .RxMmcmFvcoMin = XHDMIPHY1_HDMI_GTHE3_RX_MMCM_FVCO_MIN, + .RxMmcmFvcoMax = XHDMIPHY1_HDMI_GTHE3_RX_MMCM_FVCO_MAX, +}; +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE4) +static const XHdmiphy1_GtHdmiChars Gthe4HdmiChars = { + .DruLineRate = XHDMIPHY1_HDMI_GTHE4_DRU_LRATE, + .PllScale = XHDMIPHY1_HDMI_GTHE4_PLL_SCALE, + .Qpll0RefClkMin = XHDMIPHY1_HDMI_GTHE4_QPLL0_REFCLK_MIN, + .Qpll1RefClkMin = XHDMIPHY1_HDMI_GTHE4_QPLL1_REFCLK_MIN, + .CpllRefClkMin = XHDMIPHY1_HDMI_GTHE4_CPLL_REFCLK_MIN, + .TxMmcmScale = XHDMIPHY1_HDMI_GTHE4_TX_MMCM_SCALE, + .TxMmcmFvcoMin = XHDMIPHY1_HDMI_GTHE4_TX_MMCM_FVCO_MIN, + .TxMmcmFvcoMax = XHDMIPHY1_HDMI_GTHE4_TX_MMCM_FVCO_MAX, + .RxMmcmScale = XHDMIPHY1_HDMI_GTHE4_RX_MMCM_SCALE, + .RxMmcmFvcoMin = XHDMIPHY1_HDMI_GTHE4_RX_MMCM_FVCO_MIN, + .RxMmcmFvcoMax = XHDMIPHY1_HDMI_GTHE4_RX_MMCM_FVCO_MAX, +}; +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE4) +static const XHdmiphy1_GtHdmiChars Gtye4HdmiChars = { + .DruLineRate = XHDMIPHY1_HDMI_GTYE4_DRU_LRATE, + .PllScale = XHDMIPHY1_HDMI_GTYE4_PLL_SCALE, + .Qpll0RefClkMin = XHDMIPHY1_HDMI_GTYE4_QPLL0_REFCLK_MIN, + .Qpll1RefClkMin = XHDMIPHY1_HDMI_GTYE4_QPLL1_REFCLK_MIN, + .CpllRefClkMin = XHDMIPHY1_HDMI_GTYE4_CPLL_REFCLK_MIN, + .TxMmcmScale = XHDMIPHY1_HDMI_GTYE4_TX_MMCM_SCALE, + .TxMmcmFvcoMin = XHDMIPHY1_HDMI_GTYE4_TX_MMCM_FVCO_MIN, + .TxMmcmFvcoMax = XHDMIPHY1_HDMI_GTYE4_TX_MMCM_FVCO_MAX, + .RxMmcmScale = XHDMIPHY1_HDMI_GTYE4_RX_MMCM_SCALE, + .RxMmcmFvcoMin = XHDMIPHY1_HDMI_GTYE4_RX_MMCM_FVCO_MIN, + .RxMmcmFvcoMax = XHDMIPHY1_HDMI_GTYE4_RX_MMCM_FVCO_MAX, +}; +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE5) +static const XHdmiphy1_GtHdmiChars Gtye5HdmiChars = { + .DruLineRate = XHDMIPHY1_HDMI_GTYE5_DRU_LRATE, + .PllScale = XHDMIPHY1_HDMI_GTYE5_PLL_SCALE, + .Qpll0RefClkMin = XHDMIPHY1_HDMI_GTYE5_LCPLL_REFCLK_MIN, + .Qpll1RefClkMin = XHDMIPHY1_HDMI_GTYE5_RPLL_REFCLK_MIN, + .CpllRefClkMin = 0, + .TxMmcmScale = XHDMIPHY1_HDMI_GTYE5_TX_MMCM_SCALE, + .TxMmcmFvcoMin = XHDMIPHY1_HDMI_GTYE5_TX_MMCM_FVCO_MIN, + .TxMmcmFvcoMax = XHDMIPHY1_HDMI_GTYE5_TX_MMCM_FVCO_MAX, + .RxMmcmScale = XHDMIPHY1_HDMI_GTYE5_RX_MMCM_SCALE, + .RxMmcmFvcoMin = XHDMIPHY1_HDMI_GTYE5_RX_MMCM_FVCO_MIN, + .RxMmcmFvcoMax = XHDMIPHY1_HDMI_GTYE5_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 Hdmiphy 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 XHdmiphy1_GtHdmiChars *GetGtHdmiPtr(XHdmiphy1 *InstancePtr) +{ + /* Suppress Warning Messages */ + InstancePtr = InstancePtr; + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE3) + return &Gthe3HdmiChars; +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE4) + return &Gthe4HdmiChars; +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE4) + return &Gtye4HdmiChars; +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE5) + return &Gtye5HdmiChars; +#endif + + return NULL; +} diff --git a/hdmi/phy-xilinx-vphy/xhdmiphy1_hdmi.h b/hdmi/phy-xilinx-vphy/xhdmiphy1_hdmi.h new file mode 100644 index 0000000..3cfce89 --- /dev/null +++ b/hdmi/phy-xilinx-vphy/xhdmiphy1_hdmi.h @@ -0,0 +1,199 @@ +/******************************************************************************* + * + * + * 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 xhdmiphy1_hdmi.h + * + * The Xilinx HDMI PHY (HDMIPHY) driver. This driver supports the + * Xilinx HDMI PHY IP core. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ *            dd/mm/yy
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   gm   10/12/18 Initial release.
+ * 
+ * + * @addtogroup xhdmiphy1_v1_0 + * @{ +*******************************************************************************/ + +#ifndef XHDMIPHY1_HDMI_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XHDMIPHY1_HDMI_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/************************** Constant Definitions ******************************/ + +#define XHDMIPHY1_HDMI_GTYE5_DRU_LRATE 2500000000U +#define XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK 200000000LL +#define XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK_MIN 199990000LL +#define XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK_MAX 200010000LL +#define XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK1 125000000LL +#define XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK1_MIN 124990000LL +#define XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK1_MAX 125010000LL +#define XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK2 400000000LL +#define XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK2_MIN 399990000LL +#define XHDMIPHY1_HDMI_GTYE5_DRU_REFCLK2_MAX 400010000LL +#define XHDMIPHY1_HDMI_GTYE5_PLL_SCALE 1000 +#define XHDMIPHY1_HDMI_GTYE5_LCPLL_REFCLK_MIN 120000000LL +#define XHDMIPHY1_HDMI_GTYE5_RPLL_REFCLK_MIN 120000000LL +#define XHDMIPHY1_HDMI_GTYE5_TX_MMCM_SCALE 1 +#define XHDMIPHY1_HDMI_GTYE5_TX_MMCM_FVCO_MIN 2160000000U +#define XHDMIPHY1_HDMI_GTYE5_TX_MMCM_FVCO_MAX 4320000000U +#define XHDMIPHY1_HDMI_GTYE5_RX_MMCM_SCALE 1 +#define XHDMIPHY1_HDMI_GTYE5_RX_MMCM_FVCO_MIN 2160000000U +#define XHDMIPHY1_HDMI_GTYE5_RX_MMCM_FVCO_MAX 4320000000U + +#define XHDMIPHY1_HDMI_GTYE4_DRU_LRATE 2500000000U +#define XHDMIPHY1_HDMI_GTYE4_DRU_REFCLK 156250000LL +#define XHDMIPHY1_HDMI_GTYE4_DRU_REFCLK_MIN 156240000LL +#define XHDMIPHY1_HDMI_GTYE4_DRU_REFCLK_MAX 156260000LL +#define XHDMIPHY1_HDMI_GTYE4_DRU_REFCLK2 400000000LL +#define XHDMIPHY1_HDMI_GTYE4_DRU_REFCLK2_MIN 399990000LL +#define XHDMIPHY1_HDMI_GTYE4_DRU_REFCLK2_MAX 400010000LL +#define XHDMIPHY1_HDMI_GTYE4_PLL_SCALE 1000 +#define XHDMIPHY1_HDMI_GTYE4_QPLL0_REFCLK_MIN 61250000LL +#define XHDMIPHY1_HDMI_GTYE4_QPLL1_REFCLK_MIN 50000000LL +#define XHDMIPHY1_HDMI_GTYE4_CPLL_REFCLK_MIN 50000000LL +#define XHDMIPHY1_HDMI_GTYE4_TX_MMCM_SCALE 1 +#define XHDMIPHY1_HDMI_GTYE4_TX_MMCM_FVCO_MIN 800000000U +#define XHDMIPHY1_HDMI_GTYE4_TX_MMCM_FVCO_MAX 1600000000U +#define XHDMIPHY1_HDMI_GTYE4_RX_MMCM_SCALE 1 +#define XHDMIPHY1_HDMI_GTYE4_RX_MMCM_FVCO_MIN 800000000U +#define XHDMIPHY1_HDMI_GTYE4_RX_MMCM_FVCO_MAX 1600000000U + +#define XHDMIPHY1_HDMI_GTHE4_DRU_LRATE 2500000000U +#define XHDMIPHY1_HDMI_GTHE4_DRU_REFCLK 156250000LL +#define XHDMIPHY1_HDMI_GTHE4_DRU_REFCLK_MIN 156240000LL +#define XHDMIPHY1_HDMI_GTHE4_DRU_REFCLK_MAX 156260000LL +#define XHDMIPHY1_HDMI_GTHE4_DRU_REFCLK2 400000000LL +#define XHDMIPHY1_HDMI_GTHE4_DRU_REFCLK2_MIN 399980000LL +#define XHDMIPHY1_HDMI_GTHE4_DRU_REFCLK2_MAX 400020000LL +#define XHDMIPHY1_HDMI_GTHE4_PLL_SCALE 1000 +#define XHDMIPHY1_HDMI_GTHE4_QPLL0_REFCLK_MIN 61250000LL +#define XHDMIPHY1_HDMI_GTHE4_QPLL1_REFCLK_MIN 50000000LL +#define XHDMIPHY1_HDMI_GTHE4_CPLL_REFCLK_MIN 50000000LL +#define XHDMIPHY1_HDMI_GTHE4_TX_MMCM_SCALE 1 +#define XHDMIPHY1_HDMI_GTHE4_TX_MMCM_FVCO_MIN 800000000U +#define XHDMIPHY1_HDMI_GTHE4_TX_MMCM_FVCO_MAX 1600000000U +#define XHDMIPHY1_HDMI_GTHE4_RX_MMCM_SCALE 1 +#define XHDMIPHY1_HDMI_GTHE4_RX_MMCM_FVCO_MIN 800000000U +#define XHDMIPHY1_HDMI_GTHE4_RX_MMCM_FVCO_MAX 1600000000U + +#define XHDMIPHY1_HDMI_GTHE3_DRU_LRATE 2500000000U +#define XHDMIPHY1_HDMI_GTHE3_DRU_REFCLK 156250000LL +#define XHDMIPHY1_HDMI_GTHE3_DRU_REFCLK_MIN 156240000LL +#define XHDMIPHY1_HDMI_GTHE3_DRU_REFCLK_MAX 156260000LL +#define XHDMIPHY1_HDMI_GTHE3_DRU_REFCLK2 400000000LL +#define XHDMIPHY1_HDMI_GTHE3_DRU_REFCLK2_MIN 399990000LL +#define XHDMIPHY1_HDMI_GTHE3_DRU_REFCLK2_MAX 400010000LL +#define XHDMIPHY1_HDMI_GTHE3_PLL_SCALE 1000 +#define XHDMIPHY1_HDMI_GTHE3_QPLL0_REFCLK_MIN 61250000LL +#define XHDMIPHY1_HDMI_GTHE3_QPLL1_REFCLK_MIN 50000000LL +#define XHDMIPHY1_HDMI_GTHE3_CPLL_REFCLK_MIN 50000000LL +#define XHDMIPHY1_HDMI_GTHE3_TX_MMCM_SCALE 1 +#define XHDMIPHY1_HDMI_GTHE3_TX_MMCM_FVCO_MIN 600000000U +#define XHDMIPHY1_HDMI_GTHE3_TX_MMCM_FVCO_MAX 1200000000U +#define XHDMIPHY1_HDMI_GTHE3_RX_MMCM_SCALE 1 +#define XHDMIPHY1_HDMI_GTHE3_RX_MMCM_FVCO_MIN 600000000U +#define XHDMIPHY1_HDMI_GTHE3_RX_MMCM_FVCO_MAX 1200000000U + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE3) +#define XHDMIPHY1_FRL_VIDCLK_MMCM_FBOUTMULT 3 +#define XHDMIPHY1_FRL_VIDCLK_MMCM_DIVCLK 1 +#define XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT0DIV 3 +#define XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT1DIV 3 +#define XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT2DIV 4 +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTHE4) +#define XHDMIPHY1_FRL_VIDCLK_MMCM_FBOUTMULT 3 +#define XHDMIPHY1_FRL_VIDCLK_MMCM_DIVCLK 1 +#define XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT0DIV 3 +#define XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT1DIV 3 +#define XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT2DIV 3 +#elif (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE5) +#define XHDMIPHY1_FRL_VIDCLK_MMCM_FBOUTMULT 6 +#define XHDMIPHY1_FRL_VIDCLK_MMCM_DIVCLK 1 +#define XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT0DIV 6 +#define XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT1DIV 6 +#define XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT2DIV 6 +#else +#define XHDMIPHY1_FRL_VIDCLK_MMCM_FBOUTMULT 3 +#define XHDMIPHY1_FRL_VIDCLK_MMCM_DIVCLK 1 +#define XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT0DIV 3 +#define XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT1DIV 3 +#define XHDMIPHY1_FRL_VIDCLK_MMCM_CLKOUT2DIV 3 +#endif + +#define XHDMIPHY1_HDMI21_FRL_REFCLK 400000000U + +/**************************** Function Prototypes *****************************/ + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) +u32 XHdmiphy1_HdmiQpllParam(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir); +u32 XHdmiphy1_HdmiCpllParam(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir); +void XHdmiphy1_TxAlignReset(XHdmiphy1 *InstancePtr, XHdmiphy1_ChannelId ChId, + u8 Reset); +void XHdmiphy1_TxAlignStart(XHdmiphy1 *InstancePtr, XHdmiphy1_ChannelId ChId, + u8 Start); +#else +u32 XHdmiphy1_HdmiTxPllParam(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId); +u32 XHdmiphy1_HdmiRxPllParam(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId); +#endif +void XHdmiphy1_ClkDetEnable(XHdmiphy1 *InstancePtr, u8 Enable); +void XHdmiphy1_ClkDetTimerClear(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir); +void XHdmiphy1_ClkDetSetFreqLockThreshold(XHdmiphy1 *InstancePtr, + u16 ThresholdVal); +u8 XHdmiphy1_ClkDetCheckFreqZero(XHdmiphy1 *InstancePtr, + XHdmiphy1_DirectionType Dir); +void XHdmiphy1_ClkDetSetFreqTimeout(XHdmiphy1 *InstancePtr, u32 TimeoutVal); +void XHdmiphy1_ClkDetTimerLoad(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, u32 TimeoutVal); +void XHdmiphy1_DruReset(XHdmiphy1 *InstancePtr, XHdmiphy1_ChannelId ChId, + u8 Reset); +void XHdmiphy1_DruEnable(XHdmiphy1 *InstancePtr, XHdmiphy1_ChannelId ChId, + u8 Enable); +u16 XHdmiphy1_DruGetVersion(XHdmiphy1 *InstancePtr); +void XHdmiphy1_DruSetCenterFreqHz(XHdmiphy1 *InstancePtr, + XHdmiphy1_ChannelId ChId, u64 CenterFreqHz); +u64 XHdmiphy1_DruCalcCenterFreqHz(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId); +void XHdmiphy1_HdmiGtDruModeEnable(XHdmiphy1 *InstancePtr, u8 Enable); +void XHdmiphy1_PatgenSetRatio(XHdmiphy1 *InstancePtr, + u8 QuadId, u64 TxLineRate); +void XHdmiphy1_PatgenEnable(XHdmiphy1 *InstancePtr, u8 QuadId, u8 Enable); +void XHdmiphy1_HdmiIntrHandlerCallbackInit(XHdmiphy1 *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* XHDMIPHY1_HDMI_H_ */ +/** @} */ diff --git a/hdmi/phy-xilinx-vphy/xhdmiphy1_hdmi_intr.c b/hdmi/phy-xilinx-vphy/xhdmiphy1_hdmi_intr.c new file mode 100644 index 0000000..6d5cbd3 --- /dev/null +++ b/hdmi/phy-xilinx-vphy/xhdmiphy1_hdmi_intr.c @@ -0,0 +1,1314 @@ +/******************************************************************************* + * + * + * 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 xhdmiphy1_hdmi_intr.c + * + * This file contains video PHY functionality specific to the HDMI protocol + * related to interrupts. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ *            dd/mm/yy
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   gm   10/12/18 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xstatus.h" +#include "xhdmiphy1.h" +#include "xhdmiphy1_i.h" +#include "xhdmiphy1_hdmi.h" +#include "xhdmiphy1_gt.h" + +/************************** Function Prototypes ******************************/ + +extern void XHdmiphy1_Ch2Ids(XHdmiphy1 *InstancePtr, XHdmiphy1_ChannelId ChId, + u8 *Id0, u8 *Id1); + +static void XHdmiphy1_HdmiGtHandler(XHdmiphy1 *InstancePtr); +static void XHdmiphy1_ClkDetHandler(XHdmiphy1 *InstancePtr); + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** +* This function installs an HDMI callback function for the specified handler +* type +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_SetHdmiCallback(XHdmiphy1 *InstancePtr, + XHdmiphy1_HdmiHandlerType HandlerType, + void *CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((HandlerType == XHDMIPHY1_HDMI_HANDLER_TXINIT) || + (HandlerType == XHDMIPHY1_HDMI_HANDLER_TXREADY) || + (HandlerType == XHDMIPHY1_HDMI_HANDLER_RXINIT) || + (HandlerType == XHDMIPHY1_HDMI_HANDLER_RXREADY)); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + switch (HandlerType) { + case XHDMIPHY1_HDMI_HANDLER_TXINIT: + InstancePtr->HdmiTxInitCallback = (XHdmiphy1_Callback)CallbackFunc; + InstancePtr->HdmiTxInitRef = CallbackRef; + break; + + case XHDMIPHY1_HDMI_HANDLER_TXREADY: + InstancePtr->HdmiTxReadyCallback = (XHdmiphy1_Callback)CallbackFunc; + InstancePtr->HdmiTxReadyRef = CallbackRef; + break; + + case XHDMIPHY1_HDMI_HANDLER_RXINIT: + InstancePtr->HdmiRxInitCallback = (XHdmiphy1_Callback)CallbackFunc; + InstancePtr->HdmiRxInitRef = CallbackRef; + break; + + case XHDMIPHY1_HDMI_HANDLER_RXREADY: + InstancePtr->HdmiRxReadyCallback = (XHdmiphy1_Callback)CallbackFunc; + InstancePtr->HdmiRxReadyRef = CallbackRef; + break; + + default: + break; + } +} + +/*****************************************************************************/ +/** +* This function sets the appropriate HDMI interupt handlers. +* +* @param InstancePtr is a pointer to the HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_HdmiIntrHandlerCallbackInit(XHdmiphy1 *InstancePtr) +{ + /* GT Interrupts */ + XHdmiphy1_SetIntrHandler(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TXRESET_DONE, + (XHdmiphy1_IntrHandler)XHdmiphy1_HdmiGtHandler, InstancePtr); + + XHdmiphy1_SetIntrHandler(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RXRESET_DONE, + (XHdmiphy1_IntrHandler)XHdmiphy1_HdmiGtHandler, InstancePtr); + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + XHdmiphy1_SetIntrHandler(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_CPLL_LOCK, + (XHdmiphy1_IntrHandler)XHdmiphy1_HdmiGtHandler, InstancePtr); + + XHdmiphy1_SetIntrHandler(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_QPLL_LOCK, + (XHdmiphy1_IntrHandler)XHdmiphy1_HdmiGtHandler, InstancePtr); + + XHdmiphy1_SetIntrHandler(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TXALIGN_DONE, + (XHdmiphy1_IntrHandler)XHdmiphy1_HdmiGtHandler, InstancePtr); + + XHdmiphy1_SetIntrHandler(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_QPLL1_LOCK, + (XHdmiphy1_IntrHandler)XHdmiphy1_HdmiGtHandler, InstancePtr); +#else + XHdmiphy1_SetIntrHandler(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_LCPLL_LOCK, + (XHdmiphy1_IntrHandler)XHdmiphy1_HdmiGtHandler, InstancePtr); + + XHdmiphy1_SetIntrHandler(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RPLL_LOCK, + (XHdmiphy1_IntrHandler)XHdmiphy1_HdmiGtHandler, InstancePtr); + XHdmiphy1_SetIntrHandler(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TX_GPO_RISING_EDGE, + (XHdmiphy1_IntrHandler)XHdmiphy1_HdmiGtHandler, InstancePtr); + + XHdmiphy1_SetIntrHandler(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_GPO_RISING_EDGE, + (XHdmiphy1_IntrHandler)XHdmiphy1_HdmiGtHandler, InstancePtr); +#endif + + XHdmiphy1_SetIntrHandler(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TX_MMCM_LOCK_CHANGE, + (XHdmiphy1_IntrHandler)XHdmiphy1_HdmiGtHandler, InstancePtr); + + XHdmiphy1_SetIntrHandler(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_MMCM_LOCK_CHANGE, + (XHdmiphy1_IntrHandler)XHdmiphy1_HdmiGtHandler, InstancePtr); + + /* Clock Detector Interrupts */ + XHdmiphy1_SetIntrHandler(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE, + (XHdmiphy1_IntrHandler)XHdmiphy1_ClkDetHandler, InstancePtr); + + XHdmiphy1_SetIntrHandler(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE, + (XHdmiphy1_IntrHandler)XHdmiphy1_ClkDetHandler, InstancePtr); + + XHdmiphy1_SetIntrHandler(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT, + (XHdmiphy1_IntrHandler)XHdmiphy1_ClkDetHandler, InstancePtr); + + XHdmiphy1_SetIntrHandler(InstancePtr, + XHDMIPHY1_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT, + (XHdmiphy1_IntrHandler)XHdmiphy1_ClkDetHandler, InstancePtr); +} + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE5) +/*****************************************************************************/ +/** +* This function is the handler for events triggered by TX GPO Rising Edge. +* +* @param InstancePtr is a pointer to the HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_HdmiTxGpoRisingEdgeHandler(XHdmiphy1 *InstancePtr) +{ + u8 Id, Id0, Id1; + u8 CfgValComp; + + /* Compare the current and next CFG values */ + CfgValComp = XHdmiphy1_CheckLineRateCfg(InstancePtr, 0, + XHDMIPHY1_CHANNEL_ID_CH1, + XHDMIPHY1_DIR_TX); + + if (CfgValComp) { + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_TXGPO_RE, 0); + } else { + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_TXGPO_RE, 1); + } + + /* De-assert GPI port. */ + XHdmiphy1_SetGpi(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_TX, FALSE); + + /* Wait for GPO TX = 0 */ + while (XHdmiphy1_GetGpo(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_TX)); + + /* Start TX MMCM. */ + XHdmiphy1_MmcmStart(InstancePtr, 0, XHDMIPHY1_DIR_TX); + + /* Configure TXRATE Port */ + XHdmiphy1_DirReconfig(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_TX); + + /* Deassert reset on GT Reset IP TX */ + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_COMMON_INIT_REG, + (XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_COMMON_INIT_REG) & ~0x1)); + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)].TxState = + XHDMIPHY1_GT_STATE_LOCK; + } +} + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by RX GPO Rising Edge. +* +* @param InstancePtr is a pointer to the HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_HdmiRxGpoRisingEdgeHandler(XHdmiphy1 *InstancePtr) +{ + u8 Id, Id0, Id1; + u8 CfgValComp; + + /* Compare the current and next CFG values */ + CfgValComp = XHdmiphy1_CheckLineRateCfg(InstancePtr, 0, + XHDMIPHY1_CHANNEL_ID_CH1, XHDMIPHY1_DIR_RX); + + if (CfgValComp) { + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_RXGPO_RE, 0); + } else { + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_RXGPO_RE, 1); + } + + /* De-assert GPI port. */ + XHdmiphy1_SetGpi(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_RX, FALSE); + + /* Wait for GPO RX = 0 */ + while (XHdmiphy1_GetGpo(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_RX)); + + /* Configure RXRATE Port */ + XHdmiphy1_DirReconfig(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_RX); + + /* Deassert reset on GT Reset IP RX */ + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_COMMON_INIT_REG, + (XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_COMMON_INIT_REG) & ~0x2)); + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)].RxState = + XHDMIPHY1_GT_STATE_LOCK; + } +} + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by LCPLL lock done. +* +* @param InstancePtr is a pointer to the HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_HdmiLcpllLockHandler(XHdmiphy1 *InstancePtr) +{ + XHdmiphy1_PllType TxPllType; + u8 Id, Id0, Id1; + XHdmiphy1_ChannelId ChId; + + /* Determine PLL type. */ + TxPllType = XHdmiphy1_GetPllType(InstancePtr, 0, XHDMIPHY1_DIR_TX, + XHDMIPHY1_CHANNEL_ID_CH1); + + /* Determine which channel(s) to operate on. */ + ChId = XHdmiphy1_GetRcfgChId(InstancePtr, 0, + XHDMIPHY1_DIR_NONE, XHDMIPHY1_PLL_TYPE_LCPLL); + + if (XHdmiphy1_IsPllLocked(InstancePtr, 0, ChId) == XST_SUCCESS) { + /* Log, lock */ + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_LCPLL_LOCK, 1); + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, + &Id1); + for (Id = Id0; Id <= Id1; Id++) { + if (TxPllType == XHDMIPHY1_PLL_TYPE_LCPLL) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)]. + TxState = XHDMIPHY1_GT_STATE_RESET; + } + else { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)]. + RxState = XHDMIPHY1_GT_STATE_RESET; + } + } + } + else { + /* Log, Lost lock */ + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_LCPLL_LOCK, 0); + } + +} + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by RPLL lock done. +* +* @param InstancePtr is a pointer to the HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_HdmiRpllLockHandler(XHdmiphy1 *InstancePtr) +{ + XHdmiphy1_PllType TxPllType; + u8 Id, Id0, Id1; + XHdmiphy1_ChannelId ChId; + + /* Determine PLL type. */ + TxPllType = XHdmiphy1_GetPllType(InstancePtr, 0, XHDMIPHY1_DIR_TX, + XHDMIPHY1_CHANNEL_ID_CH1); + + /* Determine which channel(s) to operate on. */ + ChId = XHdmiphy1_GetRcfgChId(InstancePtr, 0, + XHDMIPHY1_DIR_NONE, XHDMIPHY1_PLL_TYPE_RPLL); + + if (XHdmiphy1_IsPllLocked(InstancePtr, 0, ChId) == XST_SUCCESS) { + /* Log, lock */ + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_RPLL_LOCK, 1); + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, + &Id1); + for (Id = Id0; Id <= Id1; Id++) { + if (TxPllType == XHDMIPHY1_PLL_TYPE_RPLL) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)]. + TxState = XHDMIPHY1_GT_STATE_RESET; + } + else { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)]. + RxState = XHDMIPHY1_GT_STATE_RESET; + } + } + } + else { + /* Log, Lost lock */ + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_RPLL_LOCK, 0); + } + +} +#else +/*****************************************************************************/ +/** +* This function is the handler for events triggered by QPLL lock done. +* +* @param InstancePtr is a pointer to the HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_HdmiQpllLockHandler(XHdmiphy1 *InstancePtr) +{ + XHdmiphy1_PllType TxPllType; + XHdmiphy1_PllType RxPllType; + u8 Id, Id0, Id1; + XHdmiphy1_ChannelId ChId; + + /* Determine PLL type. */ + TxPllType = XHdmiphy1_GetPllType(InstancePtr, 0, XHDMIPHY1_DIR_TX, + XHDMIPHY1_CHANNEL_ID_CH1); + RxPllType = XHdmiphy1_GetPllType(InstancePtr, 0, XHDMIPHY1_DIR_RX, + XHDMIPHY1_CHANNEL_ID_CH1); + + /* RX is using QPLL. */ + if ((RxPllType == XHDMIPHY1_PLL_TYPE_QPLL) || + (RxPllType == XHDMIPHY1_PLL_TYPE_QPLL0) || + (RxPllType == XHDMIPHY1_PLL_TYPE_QPLL1)) { + + /* Determine which channel(s) to operate on. */ + ChId = XHdmiphy1_GetRcfgChId(InstancePtr, 0, + XHDMIPHY1_DIR_RX, RxPllType); + + if (XHdmiphy1_IsPllLocked(InstancePtr, 0, ChId) == XST_SUCCESS) { + /* Log, lock */ + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_QPLL_LOCK, 1); + + /* GT RX reset. */ + XHdmiphy1_ResetGtTxRx(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_RX, FALSE); + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, + &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)]. + RxState = XHDMIPHY1_GT_STATE_RESET; + } + } + else { + /* Log, Lost lock */ + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_QPLL_LOCK, 0); + } + } + /* TX is using QPLL. */ + else { + /* Determine which channel(s) to operate on. */ + ChId = XHdmiphy1_GetRcfgChId(InstancePtr, 0, + XHDMIPHY1_DIR_TX, TxPllType); + + if (XHdmiphy1_IsPllLocked(InstancePtr, 0, ChId) == XST_SUCCESS) { + /* Log, lock */ + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_QPLL_LOCK, 1); + + /* GT TX reset. */ + XHdmiphy1_ResetGtTxRx(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_TX, FALSE); + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, + &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)]. + TxState = XHDMIPHY1_GT_STATE_RESET; + } + } + else { + /* Log, Lost lock */ + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_QPLL_LOCK, 0); + } + } +} + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by CPLL lock done. +* +* @param InstancePtr is a pointer to the HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_HdmiCpllLockHandler(XHdmiphy1 *InstancePtr) +{ + XHdmiphy1_PllType TxPllType; + XHdmiphy1_PllType RxPllType; + u8 Id, Id0, Id1; + XHdmiphy1_ChannelId ChId; + + /* Determine PLL type. */ + TxPllType = XHdmiphy1_GetPllType(InstancePtr, 0, XHDMIPHY1_DIR_TX, + XHDMIPHY1_CHANNEL_ID_CH1); + RxPllType = XHdmiphy1_GetPllType(InstancePtr, 0, XHDMIPHY1_DIR_RX, + XHDMIPHY1_CHANNEL_ID_CH1); + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + + /* RX is using CPLL. */ + if (RxPllType == XHDMIPHY1_PLL_TYPE_CPLL) { + /* Determine which channel(s) to operate on. */ + ChId = XHdmiphy1_GetRcfgChId(InstancePtr, 0, + XHDMIPHY1_DIR_RX, RxPllType); + + if (XHdmiphy1_IsPllLocked(InstancePtr, 0, ChId) == XST_SUCCESS) { + /* Log, lock */ + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_CPLL_LOCK, 1); + /* GT RX reset. */ + XHdmiphy1_ResetGtTxRx(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_RX, FALSE); + + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)]. + RxState = XHDMIPHY1_GT_STATE_RESET; + } + } + else { + /* Log, Lost lock */ + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_CPLL_LOCK, 0); + } + } + /* TX is using CPLL. */ + else { + /* Determine which channel(s) to operate on. */ + ChId = XHdmiphy1_GetRcfgChId(InstancePtr, 0, + XHDMIPHY1_DIR_TX, TxPllType); + + if (XHdmiphy1_IsPllLocked(InstancePtr, 0, ChId) == XST_SUCCESS) { + /* Log, lock */ + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_CPLL_LOCK, 1); + + /* GT TX reset. */ + XHdmiphy1_ResetGtTxRx(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_TX, FALSE); + + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)]. + TxState = XHDMIPHY1_GT_STATE_RESET; + } + } + else { + /* Log, Lost lock */ + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_CPLL_LOCK, 0); + } + } +} + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by GT TX alignment done. +* +* @param InstancePtr is a pointer to the HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_HdmiGtTxAlignDoneLockHandler(XHdmiphy1 *InstancePtr) +{ + u8 Id, Id0, Id1; + + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_TX_ALIGN, 1); + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)].TxState = + XHDMIPHY1_GT_STATE_READY; + } + + /* TX ready callback. */ + if (InstancePtr->HdmiTxReadyCallback) { + InstancePtr->HdmiTxReadyCallback(InstancePtr->HdmiTxReadyRef); + } +} +#endif + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by GT TX reset lock done. +* +* @param InstancePtr is a pointer to the HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_HdmiGtTxResetDoneLockHandler(XHdmiphy1 *InstancePtr) +{ + u8 Id, Id0, Id1; + XHdmiphy1_PllType PllType; + XHdmiphy1_ChannelId ChId; + + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_TX_RST_DONE, 0); + + /* Determine PLL type. */ + PllType = XHdmiphy1_GetPllType(InstancePtr, 0, XHDMIPHY1_DIR_TX, + XHDMIPHY1_CHANNEL_ID_CH1); + /* Determine which channel(s) to operate on. */ + ChId = XHdmiphy1_GetRcfgChId(InstancePtr, 0, XHDMIPHY1_DIR_TX, + PllType); + + /* Set TX TMDS Clock Pattern Generator */ + if ((InstancePtr->Config.UseGtAsTxTmdsClk == TRUE) && + ((InstancePtr->TxHdmi21Cfg.IsEnabled == 0) || + (InstancePtr->TxHdmi21Cfg.IsEnabled == 1 && + InstancePtr->TxHdmi21Cfg.NChannels == 3))) { + XHdmiphy1_PatgenSetRatio(InstancePtr, 0, + (u64)((XHdmiphy1_GetLineRateHz(InstancePtr, + 0, ChId)) / 1000000)); + XHdmiphy1_PatgenEnable(InstancePtr, 0, TRUE); + } else { + XHdmiphy1_PatgenEnable(InstancePtr, 0, FALSE); + } + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + if ((InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTHE3) || + (InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTHE4) || + (InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTYE4)) { + XHdmiphy1_TxAlignReset(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, TRUE); + XHdmiphy1_TxAlignReset(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, FALSE); + } + + /* GT alignment. */ + XHdmiphy1_TxAlignStart(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, TRUE); + XHdmiphy1_TxAlignStart(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, FALSE); + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)].TxState = + XHDMIPHY1_GT_STATE_ALIGN; + } +#else + /* Deassert TX LNKRDY MASK */ + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_TX_INIT_REG, + (XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_TX_INIT_REG) & ~0x10101010)); + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)].TxState = + XHDMIPHY1_GT_STATE_READY; + } + + /* TX ready callback. */ + if (InstancePtr->HdmiTxReadyCallback) { + InstancePtr->HdmiTxReadyCallback(InstancePtr->HdmiTxReadyRef); + } +#endif +} + +/*****************************************************************************/ +/** +* This function is the handler for events triggered by GT RX reset lock done. +* +* @param InstancePtr is a pointer to the HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_HdmiGtRxResetDoneLockHandler(XHdmiphy1 *InstancePtr) +{ + u8 Id, Id0, Id1; + + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_RX_RST_DONE, 0); + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)].RxState = + XHDMIPHY1_GT_STATE_READY; + } + + /* Deassert RX LNKRDY MASK */ + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_RX_INIT_REG, + (XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_RX_INIT_REG) & ~0x10101010)); + + /* If DRU is use/d, release its reset. */ + if (InstancePtr->HdmiRxDruIsEnabled) { + XHdmiphy1_DruReset(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, FALSE); + } + + /* RX ready callback. */ + if (InstancePtr->HdmiRxReadyCallback) { + InstancePtr->HdmiRxReadyCallback(InstancePtr->HdmiRxReadyRef); + } +} + +/*****************************************************************************/ +/** +* 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 HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_HdmiTxClkDetFreqChangeHandler(XHdmiphy1 *InstancePtr) +{ + XHdmiphy1_PllType PllType; + u8 Id, Id0, Id1; + + if (InstancePtr->TxHdmi21Cfg.IsEnabled) { + if (InstancePtr->Config.TxRefClkSel != + InstancePtr->Config.TxFrlRefClkSel) { + return; + } + } + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_TX_FREQ, 0); + + /* Set TX TMDS Clock Pattern Generator */ + if ((InstancePtr->Config.UseGtAsTxTmdsClk == TRUE) && + ((InstancePtr->TxHdmi21Cfg.IsEnabled == 0) || + (InstancePtr->TxHdmi21Cfg.IsEnabled == 1 && + InstancePtr->TxHdmi21Cfg.NChannels == 3))) { + XHdmiphy1_PatgenEnable(InstancePtr, 0, FALSE); + } + + /* Determine PLL type. */ + PllType = XHdmiphy1_GetPllType(InstancePtr, 0, XHDMIPHY1_DIR_TX, + XHDMIPHY1_CHANNEL_ID_CH1); + + /* If the TX frequency has changed, the PLL is always disabled. */ +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + XHdmiphy1_PowerDownGtPll(InstancePtr, 0, + (PllType == XHDMIPHY1_PLL_TYPE_CPLL) ? + XHDMIPHY1_CHANNEL_ID_CHA : XHDMIPHY1_CHANNEL_ID_CMNA, TRUE); + + XHdmiphy1_ResetGtPll(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_TX, TRUE); +#else + /* Suppress Warning Messages */ + PllType = PllType; + + /* Mask RESET DONE */ + /* Deassert TX LNKRDY MASK */ + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_TX_INIT_REG, + (XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_TX_INIT_REG) | 0x10101010)); +#endif + /* Mask the MMCM Lock */ + XHdmiphy1_MmcmLockedMaskEnable(InstancePtr, 0, XHDMIPHY1_DIR_TX, TRUE); + + /* Disable TX MMCM. */ + /* XHdmiphy1_MmcmPowerDown(InstancePtr, 0, XHDMIPHY1_DIR_TX, TRUE); */ + + /* Clear TX timer. */ + XHdmiphy1_ClkDetTimerClear(InstancePtr, 0, XHDMIPHY1_DIR_TX); + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + /* Clear GT alignment. */ + XHdmiphy1_TxAlignStart(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, FALSE); +#endif + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)].TxState = + XHDMIPHY1_GT_STATE_IDLE; + } + + /* If there is no reference clock, load TX timer in usec. */ + if (XHdmiphy1_ClkDetGetRefClkFreqHz(InstancePtr, XHDMIPHY1_DIR_TX)) { + XHdmiphy1_ClkDetTimerLoad(InstancePtr, 0, XHDMIPHY1_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 HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_HdmiRxClkDetFreqChangeHandler(XHdmiphy1 *InstancePtr) +{ + XHdmiphy1_PllType PllType; + u32 RxRefClkHz; + u8 Id, Id0, Id1; + + if (InstancePtr->RxHdmi21Cfg.IsEnabled) { + if (InstancePtr->Config.RxRefClkSel != + InstancePtr->Config.RxFrlRefClkSel) { + return; + } + } + + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_RX_FREQ, 0); + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)].RxState = + XHDMIPHY1_GT_STATE_IDLE; + } + + if (!InstancePtr->RxHdmi21Cfg.IsEnabled) { + /* Mask the MMCM Lock */ + XHdmiphy1_MmcmLockedMaskEnable(InstancePtr, 0, XHDMIPHY1_DIR_RX, TRUE); + } + + /* Determine PLL type and RX reference clock selection. */ + PllType = XHdmiphy1_GetPllType(InstancePtr, 0, XHDMIPHY1_DIR_RX, + XHDMIPHY1_CHANNEL_ID_CH1); + + /* Fetch New RX Reference Clock Frequency */ + RxRefClkHz = XHdmiphy1_ClkDetGetRefClkFreqHz(InstancePtr, + XHDMIPHY1_DIR_RX); + + /* Round input frequency to 10 kHz. */ + RxRefClkHz = (RxRefClkHz+5000) / 10000; + RxRefClkHz = RxRefClkHz * 10000; + + /* Store RX reference clock. */ + if (InstancePtr->RxHdmi21Cfg.IsEnabled) { + InstancePtr->HdmiRxRefClkHz = XHDMIPHY1_HDMI21_FRL_REFCLK; + } + else { + InstancePtr->HdmiRxRefClkHz = RxRefClkHz; + } + + /* If the RX frequency has changed, the PLL is always disabled. */ +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + XHdmiphy1_PowerDownGtPll(InstancePtr, 0, + (PllType == XHDMIPHY1_PLL_TYPE_CPLL) ? + XHDMIPHY1_CHANNEL_ID_CHA : XHDMIPHY1_CHANNEL_ID_CMNA, TRUE); + + XHdmiphy1_ResetGtPll(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_RX, TRUE); +#else + /* Suppress Warning Messages */ + PllType = PllType; + + /* Mask RESET DONE */ + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_RX_INIT_REG, + (XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_RX_INIT_REG) | 0x10101010)); + +#endif + + /* If DRU is present, disable it and assert reset. */ + if (InstancePtr->Config.DruIsPresent) { + XHdmiphy1_DruReset(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, TRUE); + XHdmiphy1_DruEnable(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, FALSE); + } + + /* Clear RX timer. */ + XHdmiphy1_ClkDetTimerClear(InstancePtr, 0, XHDMIPHY1_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) { + XHdmiphy1_ClkDetTimerLoad(InstancePtr, 0, XHDMIPHY1_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 HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_HdmiTxTimerTimeoutHandler(XHdmiphy1 *InstancePtr) +{ +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + XHdmiphy1_ChannelId ChId; + XHdmiphy1_PllType PllType; +#else + u8 CfgValComp; +#endif + u8 Id, Id0, Id1; + + if (!InstancePtr->TxHdmi21Cfg.IsEnabled) { + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_TX_TMR, 1); + } + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + /* Determine PLL type. */ + PllType = XHdmiphy1_GetPllType(InstancePtr, 0, XHDMIPHY1_DIR_TX, + XHDMIPHY1_CHANNEL_ID_CH1); + /* Determine which channel(s) to operate on. */ + ChId = XHdmiphy1_GetRcfgChId(InstancePtr, 0, XHDMIPHY1_DIR_TX, PllType); + + /* Start TX MMCM. */ + XHdmiphy1_MmcmStart(InstancePtr, 0, XHDMIPHY1_DIR_TX); + + /* Enable PLL. */ + XHdmiphy1_PowerDownGtPll(InstancePtr, 0, + (PllType == XHDMIPHY1_PLL_TYPE_CPLL) ? + XHDMIPHY1_CHANNEL_ID_CHA : XHDMIPHY1_CHANNEL_ID_CMNA, FALSE); + + if (PllType != XHDMIPHY1_PLL_TYPE_CPLL) { + /* Set QPLL Selection in PIO. */ + XHdmiphy1_WriteCfgRefClkSelReg(InstancePtr, 0); + } + + XHdmiphy1_ClkReconfig(InstancePtr, 0, ChId); + XHdmiphy1_OutDivReconfig(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_TX); + if ((InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTHE3) || + (InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTHE4) || + (InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTYE4)) { + XHdmiphy1_SetBufgGtDiv(InstancePtr, XHDMIPHY1_DIR_TX, + (PllType == XHDMIPHY1_PLL_TYPE_CPLL) ? + InstancePtr->Quads[0].Plls[0].TxOutDiv : + (InstancePtr->Quads[0].Plls[0].TxOutDiv != 16) ? + InstancePtr->Quads[0].Plls[0].TxOutDiv : + InstancePtr->Quads[0].Plls[0].TxOutDiv / 2); + } + + XHdmiphy1_DirReconfig(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_TX); + + /* Assert PLL reset. */ + XHdmiphy1_ResetGtPll(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_TX, TRUE); + + /* De-assert PLL reset. */ + XHdmiphy1_ResetGtPll(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_TX, FALSE); + + if ((InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTHE3) || + (InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTHE4) || + (InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTYE4)) { + /* Clear GT alignment. */ + XHdmiphy1_TxAlignStart(InstancePtr, ChId, FALSE); + } + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)].TxState = + XHDMIPHY1_GT_STATE_LOCK; + } +#else + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)].TxState = + XHDMIPHY1_GT_STATE_GPO_RE; + } + + /* Compare the current and next CFG values */ + CfgValComp = XHdmiphy1_CheckLineRateCfg(InstancePtr, 0, + XHDMIPHY1_CHANNEL_ID_CH1, XHDMIPHY1_DIR_TX); + + if (!CfgValComp) { + /* Assert GPI port. */ + XHdmiphy1_SetGpi(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_TX, TRUE); + } + else { + XHdmiphy1_HdmiTxGpoRisingEdgeHandler(InstancePtr); + } +#endif +} + +/*****************************************************************************/ +/** +* This function is the handler for RX timer timeout events. +* +* @param InstancePtr is a pointer to the HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_HdmiRxTimerTimeoutHandler(XHdmiphy1 *InstancePtr) +{ + XHdmiphy1_ChannelId ChId; + XHdmiphy1_PllType PllType; + u32 Status; + u8 Id, Id0, Id1; +#if (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE5) + u8 CfgValComp; +#endif + + if (!InstancePtr->RxHdmi21Cfg.IsEnabled) { + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_RX_TMR, 1); + } else { + if (InstancePtr->Config.RxRefClkSel == + InstancePtr->Config.RxFrlRefClkSel) { + /* Set MMCM CLKINSEL to CLK1 */ + XHdmiphy1_MmcmSetClkinsel(InstancePtr, 0, XHDMIPHY1_DIR_RX, + XHDMIPHY1_MMCM_CLKINSEL_CLKIN1); + + /* Start RX MMCM. */ + XHdmiphy1_MmcmStart(InstancePtr, 0, XHDMIPHY1_DIR_RX); + } + } + + /* Determine PLL type. */ + PllType = XHdmiphy1_GetPllType(InstancePtr, 0, XHDMIPHY1_DIR_RX, + XHDMIPHY1_CHANNEL_ID_CH1); + /* Determine which channel(s) to operate on. */ + ChId = XHdmiphy1_GetRcfgChId(InstancePtr, 0, XHDMIPHY1_DIR_RX, PllType); + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + + + /* Set RX parameters. */ + Status = XHdmiphy1_SetHdmiRxParam(InstancePtr, 0, ChId); + if (Status != XST_SUCCESS) { + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)].RxState = + XHDMIPHY1_GT_STATE_IDLE; + } + + return; + } + + /* Enable DRU to set the clock muxes. */ + XHdmiphy1_DruEnable(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, + InstancePtr->HdmiRxDruIsEnabled); + + /* Update GT DRU mode. */ + XHdmiphy1_HdmiGtDruModeEnable(InstancePtr, + InstancePtr->HdmiRxDruIsEnabled); + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + /* Enable PLL. */ + XHdmiphy1_PowerDownGtPll(InstancePtr, 0, + (PllType == XHDMIPHY1_PLL_TYPE_CPLL) ? + XHDMIPHY1_CHANNEL_ID_CHA : XHDMIPHY1_CHANNEL_ID_CMNA, FALSE); + + /* Update reference clock election. */ + if (InstancePtr->RxHdmi21Cfg.IsEnabled == FALSE) { + XHdmiphy1_CfgPllRefClkSel(InstancePtr, 0, + ((PllType == XHDMIPHY1_PLL_TYPE_CPLL) ? + XHDMIPHY1_CHANNEL_ID_CHA : XHDMIPHY1_CHANNEL_ID_CMNA), + ((InstancePtr->HdmiRxDruIsEnabled) ? + InstancePtr->Config.DruRefClkSel : + InstancePtr->Config.RxRefClkSel)); + } + + /* Update RefClk selection. */ + XHdmiphy1_WriteCfgRefClkSelReg(InstancePtr, 0); + + /* Determine PLL type. */ + PllType = XHdmiphy1_GetPllType(InstancePtr, 0, XHDMIPHY1_DIR_RX, + XHDMIPHY1_CHANNEL_ID_CH1); + /* Determine which channel(s) to operate on. */ + ChId = XHdmiphy1_GetRcfgChId(InstancePtr, 0, XHDMIPHY1_DIR_RX, PllType); + + XHdmiphy1_ClkReconfig(InstancePtr, 0, ChId); + XHdmiphy1_OutDivReconfig(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_RX); + + XHdmiphy1_DirReconfig(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_RX); + + /* Assert RX PLL reset. */ + XHdmiphy1_ResetGtPll(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_RX, TRUE); + + /* De-assert RX PLL reset. */ + XHdmiphy1_ResetGtPll(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_RX, FALSE); +#else + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[0].Plls[XHDMIPHY1_CH2IDX(Id)].RxState = + XHDMIPHY1_GT_STATE_GPO_RE; + } + + /* Compare the current and next CFG values */ + CfgValComp = XHdmiphy1_CheckLineRateCfg(InstancePtr, 0, + XHDMIPHY1_CHANNEL_ID_CH1, XHDMIPHY1_DIR_RX); + + if (!CfgValComp) { + /* Assert GPI port. */ + XHdmiphy1_SetGpi(InstancePtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, + XHDMIPHY1_DIR_RX, TRUE); + } + else { + XHdmiphy1_HdmiRxGpoRisingEdgeHandler(InstancePtr); + } +#endif +} + +/*****************************************************************************/ +/** +* This function is the handler for TX MMCM Lock events. +* +* @param InstancePtr is a pointer to the HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_HdmiTxMmcmLockHandler(XHdmiphy1 *InstancePtr) +{ + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_TXPLL_LOCK, 1); + +} + +/*****************************************************************************/ +/** +* This function is the handler for RX MMCM Lock events. +* +* @param InstancePtr is a pointer to the HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_HdmiRxMmcmLockHandler(XHdmiphy1 *InstancePtr) +{ + + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_RXPLL_LOCK, 1); + +} + +/*****************************************************************************/ +/** +* This function is the interrupt handler for the GT events. +* +* @param InstancePtr is a pointer to the HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_HdmiGtHandler(XHdmiphy1 *InstancePtr) +{ + u32 Event; + u32 EventMask; + u32 EventAck; + XHdmiphy1_GtState *TxStatePtr; + XHdmiphy1_GtState *RxStatePtr; + XHdmiphy1_PllType TxPllType; + XHdmiphy1_PllType RxPllType; + + + EventMask = +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + XHDMIPHY1_INTR_QPLL0_LOCK_MASK | XHDMIPHY1_INTR_CPLL_LOCK_MASK | + XHDMIPHY1_INTR_QPLL1_LOCK_MASK | + XHDMIPHY1_INTR_TXALIGNDONE_MASK | +#else + XHDMIPHY1_INTR_LCPLL_LOCK_MASK | XHDMIPHY1_INTR_RPLL_LOCK_MASK | + XHDMIPHY1_INTR_TXGPO_RE_MASK | XHDMIPHY1_INTR_RXGPO_RE_MASK | +#endif + XHDMIPHY1_INTR_TXRESETDONE_MASK | XHDMIPHY1_INTR_RXRESETDONE_MASK | + XHDMIPHY1_INTR_TXMMCMUSRCLK_LOCK_MASK | + XHDMIPHY1_INTR_RXMMCMUSRCLK_LOCK_MASK; + + u8 QuadId = 0; + + /* Read Interrupt Status register */ + Event = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_INTR_STS_REG); + + EventAck = EventMask & Event; + + /* Read States for Quad=0 Ch1 */ + TxStatePtr = &InstancePtr->Quads[QuadId].Ch1.TxState; + RxStatePtr = &InstancePtr->Quads[QuadId].Ch1.RxState; + + /* Determine PLL type. */ + TxPllType = XHdmiphy1_GetPllType(InstancePtr, 0, XHDMIPHY1_DIR_TX, + XHDMIPHY1_CHANNEL_ID_CH1); + RxPllType = XHdmiphy1_GetPllType(InstancePtr, 0, XHDMIPHY1_DIR_RX, + XHDMIPHY1_CHANNEL_ID_CH1); + + if (Event & XHDMIPHY1_INTR_TXMMCMUSRCLK_LOCK_MASK) { + XHdmiphy1_HdmiTxMmcmLockHandler(InstancePtr); + } + if (Event & XHDMIPHY1_INTR_RXMMCMUSRCLK_LOCK_MASK) { + XHdmiphy1_HdmiRxMmcmLockHandler(InstancePtr); + } +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + if ((Event & XHDMIPHY1_INTR_QPLL0_LOCK_MASK) || + (Event & XHDMIPHY1_INTR_QPLL1_LOCK_MASK)) { + XHdmiphy1_HdmiQpllLockHandler(InstancePtr); + } + if (Event & XHDMIPHY1_INTR_CPLL_LOCK_MASK) { + XHdmiphy1_HdmiCpllLockHandler(InstancePtr); + } + if ((Event & XHDMIPHY1_INTR_TXRESETDONE_MASK) + && (*TxStatePtr == XHDMIPHY1_GT_STATE_RESET)) { + XHdmiphy1_HdmiGtTxResetDoneLockHandler(InstancePtr); + } + if ((Event & XHDMIPHY1_INTR_TXALIGNDONE_MASK) + && (*TxStatePtr == XHDMIPHY1_GT_STATE_ALIGN)) { + XHdmiphy1_HdmiGtTxAlignDoneLockHandler(InstancePtr); + } + if ((Event & XHDMIPHY1_INTR_RXRESETDONE_MASK) + && (*RxStatePtr == XHDMIPHY1_GT_STATE_RESET)) { + XHdmiphy1_HdmiGtRxResetDoneLockHandler(InstancePtr); + } + + /* Suppress Warning Messages */ + TxPllType = TxPllType; + RxPllType = RxPllType; +#else + if (Event & XHDMIPHY1_INTR_TXGPO_RE_MASK) { + XHdmiphy1_HdmiTxGpoRisingEdgeHandler(InstancePtr); + } + if (Event & XHDMIPHY1_INTR_RXGPO_RE_MASK) { + XHdmiphy1_HdmiRxGpoRisingEdgeHandler(InstancePtr); + } + if ((Event & XHDMIPHY1_INTR_LCPLL_LOCK_MASK) && + (((*TxStatePtr != XHDMIPHY1_GT_STATE_IDLE) && + (TxPllType == XHDMIPHY1_PLL_TYPE_LCPLL)) || + ((*RxStatePtr != XHDMIPHY1_GT_STATE_IDLE) && + (RxPllType == XHDMIPHY1_PLL_TYPE_LCPLL)))) { + XHdmiphy1_HdmiLcpllLockHandler(InstancePtr); + } + if ((Event & XHDMIPHY1_INTR_RPLL_LOCK_MASK) && + (((*TxStatePtr != XHDMIPHY1_GT_STATE_IDLE) && + (TxPllType == XHDMIPHY1_PLL_TYPE_RPLL)) || + ((*RxStatePtr != XHDMIPHY1_GT_STATE_IDLE) && + (RxPllType == XHDMIPHY1_PLL_TYPE_RPLL)))) { + XHdmiphy1_HdmiRpllLockHandler(InstancePtr); + } + + /* [Versal] This is different from bare metal driver */ + if (Event & XHDMIPHY1_INTR_TXRESETDONE_MASK) + XHdmiphy1_HdmiGtTxResetDoneLockHandler(InstancePtr); + + if ((Event & XHDMIPHY1_INTR_RXRESETDONE_MASK) + && (*RxStatePtr == XHDMIPHY1_GT_STATE_RESET)) { + XHdmiphy1_HdmiGtRxResetDoneLockHandler(InstancePtr); + } + + /* Suppress Warning Messages */ + TxStatePtr = TxStatePtr; + RxStatePtr = RxStatePtr; +#endif + + /* Clear event flags by writing to Interrupt Status register */ + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_INTR_STS_REG, + EventAck); +} + +/*****************************************************************************/ +/** +* This function is the interrupt handler for the clock detector events. +* +* @param InstancePtr is a pointer to the HDMIPHY instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_ClkDetHandler(XHdmiphy1 *InstancePtr) +{ + u32 Event; + u32 EventMask; + u32 EventAck; + + EventMask = XHDMIPHY1_INTR_TXCLKDETFREQCHANGE_MASK | + XHDMIPHY1_INTR_RXCLKDETFREQCHANGE_MASK | + XHDMIPHY1_INTR_TXTMRTIMEOUT_MASK | + XHDMIPHY1_INTR_RXTMRTIMEOUT_MASK; + + /* Read Interrupt Status register */ + Event = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_INTR_STS_REG); + + EventAck = EventMask & Event; + + if (Event & XHDMIPHY1_INTR_TXCLKDETFREQCHANGE_MASK) { + XHdmiphy1_HdmiTxClkDetFreqChangeHandler(InstancePtr); + } + if (Event & XHDMIPHY1_INTR_RXCLKDETFREQCHANGE_MASK) { + XHdmiphy1_HdmiRxClkDetFreqChangeHandler(InstancePtr); + } + if (Event & XHDMIPHY1_INTR_TXTMRTIMEOUT_MASK) { + XHdmiphy1_HdmiTxTimerTimeoutHandler(InstancePtr); + } + if (Event & XHDMIPHY1_INTR_RXTMRTIMEOUT_MASK) { + XHdmiphy1_HdmiRxTimerTimeoutHandler(InstancePtr); + } + + /* Clear event flags by writing to Interrupt Status register */ + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_INTR_STS_REG, + EventAck); +} diff --git a/hdmi/phy-xilinx-vphy/xhdmiphy1_hw.h b/hdmi/phy-xilinx-vphy/xhdmiphy1_hw.h new file mode 100644 index 0000000..43e7304 --- /dev/null +++ b/hdmi/phy-xilinx-vphy/xhdmiphy1_hw.h @@ -0,0 +1,705 @@ +/******************************************************************************* + * + * + * 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 xhdmiphy1_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 xhdmiphy1.h. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ *            dd/mm/yy
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   gm   10/12/18 Initial release.
+ * 
+ * + * @addtogroup xhdmiphy1_v1_0 + * @{ +*******************************************************************************/ + +#ifndef XHDMIPHY1_HW_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XHDMIPHY1_HW_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files **********************************/ + +#include "xil_io.h" +#include "xil_types.h" + +/************************** Constant Definitions ******************************/ + +/******************************************************************************/ +/** + * Address mapping for the Video PHY core. + * +*******************************************************************************/ +/** @name HDMIPHY core registers: General registers. + * @{ + */ +#define XHDMIPHY1_VERSION_REG 0x000 +#define XHDMIPHY1_BANK_SELECT_REG 0x00C +#define XHDMIPHY1_REF_CLK_SEL_REG 0x010 +#define XHDMIPHY1_PLL_RESET_REG 0x014 +#define XHDMIPHY1_COMMON_INIT_REG 0x014 +#define XHDMIPHY1_PLL_LOCK_STATUS_REG 0x018 +#define XHDMIPHY1_TX_INIT_REG 0x01C +#define XHDMIPHY1_TX_INIT_STATUS_REG 0x020 +#define XHDMIPHY1_RX_INIT_REG 0x024 +#define XHDMIPHY1_RX_INIT_STATUS_REG 0x028 +#define XHDMIPHY1_IBUFDS_GTXX_CTRL_REG 0x02C +#define XHDMIPHY1_POWERDOWN_CONTROL_REG 0x030 +#define XHDMIPHY1_LOOPBACK_CONTROL_REG 0x038 +/* @} */ + +/** @name HDMIPHY core registers: Dynamic reconfiguration port (DRP) registers. + * @{ + */ +#define XHDMIPHY1_DRP_CONTROL_CH1_REG 0x040 +#define XHDMIPHY1_DRP_CONTROL_CH2_REG 0x044 +#define XHDMIPHY1_DRP_CONTROL_CH3_REG 0x048 +#define XHDMIPHY1_DRP_CONTROL_CH4_REG 0x04C +#define XHDMIPHY1_DRP_STATUS_CH1_REG 0x050 +#define XHDMIPHY1_DRP_STATUS_CH2_REG 0x054 +#define XHDMIPHY1_DRP_STATUS_CH3_REG 0x058 +#define XHDMIPHY1_DRP_STATUS_CH4_REG 0x05C +#define XHDMIPHY1_DRP_CONTROL_COMMON_REG 0x060 +#define XHDMIPHY1_DRP_STATUS_COMMON_REG 0x064 +#define XHDMIPHY1_DRP_CONTROL_TXMMCM_REG 0x124 +#define XHDMIPHY1_DRP_STATUS_TXMMCM_REG 0x128 +#define XHDMIPHY1_DRP_CONTROL_RXMMCM_REG 0x144 +#define XHDMIPHY1_DRP_STATUS_RXMMCM_REG 0x148 +/* @} */ + +/** @name HDMIPHY core registers: CPLL Calibration registers. + * @{ + */ +#define XHDMIPHY1_CPLL_CAL_PERIOD_REG 0x068 +#define XHDMIPHY1_CPLL_CAL_TOL_REG 0x06C +/* @} */ +/** @name HDMIPHY core registers: GT Debug INTF registers. + * @{ + */ +#define XHDMIPHY1_GT_DBG_GPI_REG 0x068 +#define XHDMIPHY1_GT_DBG_GPO_REG 0x06C +/* @} */ + +/** @name HDMIPHY core registers: Transmitter function registers. + * @{ + */ +#define XHDMIPHY1_TX_CONTROL_REG 0x070 +#define XHDMIPHY1_TX_BUFFER_BYPASS_REG 0x074 +#define XHDMIPHY1_TX_STATUS_REG 0x078 +#define XHDMIPHY1_TX_DRIVER_CH12_REG 0x07C +#define XHDMIPHY1_TX_DRIVER_CH34_REG 0x080 +#define XHDMIPHY1_TX_DRIVER_EXT_REG 0x084 +#define XHDMIPHY1_TX_RATE_CH12_REG 0x08C +#define XHDMIPHY1_TX_RATE_CH34_REG 0x090 +/* @} */ + +/** @name HDMIPHY core registers: Receiver function registers. + * @{ + */ +#define XHDMIPHY1_RX_RATE_CH12_REG 0x98 +#define XHDMIPHY1_RX_RATE_CH34_REG 0x9C +#define XHDMIPHY1_RX_CONTROL_REG 0x100 +#define XHDMIPHY1_RX_STATUS_REG 0x104 +#define XHDMIPHY1_RX_EQ_CDR_REG 0x108 +#define XHDMIPHY1_RX_TDLOCK_REG 0x10C +/* @} */ + +/** @name HDMIPHY core registers: Interrupt registers. + * @{ + */ +#define XHDMIPHY1_INTR_EN_REG 0x110 +#define XHDMIPHY1_INTR_DIS_REG 0x114 +#define XHDMIPHY1_INTR_MASK_REG 0x118 +#define XHDMIPHY1_INTR_STS_REG 0x11C +/* @} */ + +/** @name User clocking registers: MMCM and BUFGGT registers. + * @{ + */ +#define XHDMIPHY1_MMCM_TXUSRCLK_CTRL_REG 0x0120 +#define XHDMIPHY1_MMCM_TXUSRCLK_REG1 0x0124 +#define XHDMIPHY1_MMCM_TXUSRCLK_REG2 0x0128 +#define XHDMIPHY1_MMCM_TXUSRCLK_REG3 0x012C +#define XHDMIPHY1_MMCM_TXUSRCLK_REG4 0x0130 +#define XHDMIPHY1_BUFGGT_TXUSRCLK_REG 0x0134 +#define XHDMIPHY1_MISC_TXUSRCLK_REG 0x0138 + +#define XHDMIPHY1_MMCM_RXUSRCLK_CTRL_REG 0x0140 +#define XHDMIPHY1_MMCM_RXUSRCLK_REG1 0x0144 +#define XHDMIPHY1_MMCM_RXUSRCLK_REG2 0x0148 +#define XHDMIPHY1_MMCM_RXUSRCLK_REG3 0x014C +#define XHDMIPHY1_MMCM_RXUSRCLK_REG4 0x0150 +#define XHDMIPHY1_BUFGGT_RXUSRCLK_REG 0x0154 +#define XHDMIPHY1_MISC_RXUSRCLK_REG 0x0158 +/* @} */ + +/** @name Clock detector (HDMI) registers. + * @{ + */ +#define XHDMIPHY1_CLKDET_CTRL_REG 0x0200 +#define XHDMIPHY1_CLKDET_STAT_REG 0x0204 +#define XHDMIPHY1_CLKDET_FREQ_TMR_TO_REG 0x0208 +#define XHDMIPHY1_CLKDET_FREQ_TX_REG 0x020C +#define XHDMIPHY1_CLKDET_FREQ_RX_REG 0x0210 +#define XHDMIPHY1_CLKDET_TMR_TX_REG 0x0214 +#define XHDMIPHY1_CLKDET_TMR_RX_REG 0x0218 +#define XHDMIPHY1_CLKDET_FREQ_DRU_REG 0x021C +/* @} */ + +/** @name Data recovery unit registers (HDMI). + * @{ + */ +#define XHDMIPHY1_DRU_CTRL_REG 0x0300 +#define XHDMIPHY1_DRU_STAT_REG 0x0304 + +#define XHDMIPHY1_DRU_CFREQ_L_REG(Ch) (0x0308 + (12 * (Ch - 1))) +#define XHDMIPHY1_DRU_CFREQ_H_REG(Ch) (0x030C + (12 * (Ch - 1))) +#define XHDMIPHY1_DRU_GAIN_REG(Ch) (0x0310 + (12 * (Ch - 1))) +/* @} */ + +/** @name TMDS Clock Pattern Generator registers (HDMI). + * @{ + */ +#define XHDMIPHY1_PATGEN_CTRL_REG 0x0340 +/* @} */ + +/******************************************************************************/ + +/** @name HDMIPHY core masks, shifts, and register values. + * @{ + */ +/* 0x0F8: VERSION */ +#define XHDMIPHY1_VERSION_INTER_REV_MASK \ + 0x000000FF /**< Internal revision. */ +#define XHDMIPHY1_VERSION_CORE_PATCH_MASK \ + 0x00000F00 /**< Core patch details. */ +#define XHDMIPHY1_VERSION_CORE_PATCH_SHIFT 8 /**< Shift bits for core patch + details. */ +#define XHDMIPHY1_VERSION_CORE_VER_REV_MASK \ + 0x0000F000 /**< Core version revision. */ +#define XHDMIPHY1_VERSION_CORE_VER_REV_SHIFT 12 /**< Shift bits for core + version revision. */ +#define XHDMIPHY1_VERSION_CORE_VER_MNR_MASK \ + 0x00FF0000 /**< Core minor version. */ +#define XHDMIPHY1_VERSION_CORE_VER_MNR_SHIFT 16 /**< Shift bits for core minor + version. */ +#define XHDMIPHY1_VERSION_CORE_VER_MJR_MASK \ + 0xFF000000 /**< Core major version. */ +#define XHDMIPHY1_VERSION_CORE_VER_MJR_SHIFT 24 /**< Shift bits for core major + version. */ +/* 0x00C: BANK_SELECT_REG */ +#define XHDMIPHY1_BANK_SELECT_TX_MASK 0x00F +#define XHDMIPHY1_BANK_SELECT_RX_MASK 0xF00 +#define XHDMIPHY1_BANK_SELECT_RX_SHIFT 8 +/* 0x010: REF_CLK_SEL */ +#define XHDMIPHY1_REF_CLK_SEL_QPLL0_MASK 0x0000000F +#define XHDMIPHY1_REF_CLK_SEL_CPLL_MASK 0x000000F0 +#define XHDMIPHY1_REF_CLK_SEL_CPLL_SHIFT 4 +#define XHDMIPHY1_REF_CLK_SEL_QPLL1_MASK 0x00000F00 +#define XHDMIPHY1_REF_CLK_SEL_QPLL1_SHIFT 8 +#define XHDMIPHY1_REF_CLK_SEL_XPLL_GTREFCLK0 1 +#define XHDMIPHY1_REF_CLK_SEL_XPLL_GTREFCLK1 2 +#define XHDMIPHY1_REF_CLK_SEL_XPLL_GTNORTHREFCLK0 3 +#define XHDMIPHY1_REF_CLK_SEL_XPLL_GTNORTHREFCLK1 4 +#define XHDMIPHY1_REF_CLK_SEL_XPLL_GTSOUTHREFCLK0 5 +#define XHDMIPHY1_REF_CLK_SEL_XPLL_GTSOUTHREFCLK1 6 +#define XHDMIPHY1_REF_CLK_SEL_XPLL_GTEASTREFCLK0 3 +#define XHDMIPHY1_REF_CLK_SEL_XPLL_GTEASTREFCLK1 4 +#define XHDMIPHY1_REF_CLK_SEL_XPLL_GTWESTREFCLK0 5 +#define XHDMIPHY1_REF_CLK_SEL_XPLL_GTWESTREFCLK1 6 +#define XHDMIPHY1_REF_CLK_SEL_XPLL_GTGREFCLK 7 +#define XHDMIPHY1_REF_CLK_SEL_SYSCLKSEL_MASK 0x0F000000 +#define XHDMIPHY1_REF_CLK_SEL_SYSCLKSEL_SHIFT 24 +#define XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_DATA_PLL0 0 +#define XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_DATA_PLL1 1 +#define XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_DATA_CPLL 0 +#define XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL 1 +#define XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL0 3 +#define XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_DATA_QPLL1 2 +#define XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_OUT_CH 0 +#define XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN 1 +#define XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN0 2 +#define XHDMIPHY1_REF_CLK_SEL_XXSYSCLKSEL_OUT_CMN1 3 +#define XHDMIPHY1_REF_CLK_SEL_RXSYSCLKSEL_OUT_MASK(G) \ + ((((G) == XHDMIPHY1_GT_TYPE_GTHE3) || \ + ((G) == XHDMIPHY1_GT_TYPE_GTHE4) || \ + ((G) == XHDMIPHY1_GT_TYPE_GTYE4)) ? 0x03000000 : 0x02000000) +#define XHDMIPHY1_REF_CLK_SEL_TXSYSCLKSEL_OUT_MASK(G) \ + ((((G) == XHDMIPHY1_GT_TYPE_GTHE3) || \ + ((G) == XHDMIPHY1_GT_TYPE_GTHE4) || \ + ((G) == XHDMIPHY1_GT_TYPE_GTYE4)) ? 0x0C000000 : 0x08000000) +#define XHDMIPHY1_REF_CLK_SEL_RXSYSCLKSEL_DATA_MASK(G) \ + ((((G) == XHDMIPHY1_GT_TYPE_GTHE3) || \ + ((G) == XHDMIPHY1_GT_TYPE_GTHE4) || \ + ((G) == XHDMIPHY1_GT_TYPE_GTYE4)) ? 0x30000000 : 0x01000000) +#define XHDMIPHY1_REF_CLK_SEL_TXSYSCLKSEL_DATA_MASK(G) \ + ((((G) == XHDMIPHY1_GT_TYPE_GTHE3) || \ + ((G) == XHDMIPHY1_GT_TYPE_GTHE4) || \ + ((G) == XHDMIPHY1_GT_TYPE_GTYE4)) ? 0xC0000000 : 0x04000000) +#define XHDMIPHY1_REF_CLK_SEL_RXSYSCLKSEL_OUT_SHIFT(G) \ + ((((G) == XHDMIPHY1_GT_TYPE_GTHE3) || \ + ((G) == XHDMIPHY1_GT_TYPE_GTHE4) || \ + ((G) == XHDMIPHY1_GT_TYPE_GTYE4)) ? 24 : 25) +#define XHDMIPHY1_REF_CLK_SEL_TXSYSCLKSEL_OUT_SHIFT(G) \ + ((((G) == XHDMIPHY1_GT_TYPE_GTHE3) || \ + ((G) == XHDMIPHY1_GT_TYPE_GTHE4) || \ + ((G) == XHDMIPHY1_GT_TYPE_GTYE4)) ? 26 : 27) +#define XHDMIPHY1_REF_CLK_SEL_RXSYSCLKSEL_DATA_SHIFT(G) \ + ((((G) == XHDMIPHY1_GT_TYPE_GTHE3) || \ + ((G) == XHDMIPHY1_GT_TYPE_GTHE4) || \ + ((G) == XHDMIPHY1_GT_TYPE_GTYE4)) ? 28 : 24) +#define XHDMIPHY1_REF_CLK_SEL_TXSYSCLKSEL_DATA_SHIFT(G) \ + ((((G) == XHDMIPHY1_GT_TYPE_GTHE3) || \ + ((G) == XHDMIPHY1_GT_TYPE_GTHE4) || \ + ((G) == XHDMIPHY1_GT_TYPE_GTYE4)) ? 30 : 26) +/* 0x014: PLL_RESET */ +#define XHDMIPHY1_PLL_RESET_CPLL_MASK 0x1 +#define XHDMIPHY1_PLL_RESET_QPLL0_MASK 0x2 +#define XHDMIPHY1_PLL_RESET_QPLL1_MASK 0x4 +/* 0x014: COMMON INIT for Versal Only */ +#define XHDMIPHY1_GTWIZ_RESET_ALL_MASK 0x1 +#define XHDMIPHY1_PCIERST_ALL_CH_MASK 0x2 +/* 0x018: PLL_LOCK_STATUS */ +#define XHDMIPHY1_PLL_LOCK_STATUS_CPLL_MASK(Ch) \ + (0x01 << (Ch - 1)) +#define XHDMIPHY1_PLL_LOCK_STATUS_QPLL0_MASK 0x10 +#define XHDMIPHY1_PLL_LOCK_STATUS_QPLL1_MASK 0x20 +#define XHDMIPHY1_PLL_LOCK_STATUS_CPLL_ALL_MASK \ + (XHDMIPHY1_PLL_LOCK_STATUS_CPLL_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_PLL_LOCK_STATUS_CPLL_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_PLL_LOCK_STATUS_CPLL_MASK(XHDMIPHY1_CHANNEL_ID_CH3) | \ + XHDMIPHY1_PLL_LOCK_STATUS_CPLL_MASK(XHDMIPHY1_CHANNEL_ID_CH4)) +#define XHDMIPHY1_PLL_LOCK_STATUS_CPLL_HDMI_MASK \ + (XHDMIPHY1_PLL_LOCK_STATUS_CPLL_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_PLL_LOCK_STATUS_CPLL_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_PLL_LOCK_STATUS_CPLL_MASK(XHDMIPHY1_CHANNEL_ID_CH3)) +#define XHDMIPHY1_PLL_LOCK_STATUS_RPLL_MASK 0xC0 +#define XHDMIPHY1_PLL_LOCK_STATUS_LCPLL_MASK 0x300 +/* 0x01C, 0x024: TX_INIT, RX_INIT */ +#define XHDMIPHY1_TXRX_INIT_GTRESET_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XHDMIPHY1_TXRX_INIT_PMARESET_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XHDMIPHY1_TXRX_INIT_PCSRESET_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XHDMIPHY1_TX_INIT_USERRDY_MASK(Ch) \ + (0x08 << (8 * (Ch - 1))) +#define XHDMIPHY1_TXRX_LNKRDY_SB_MASK(Ch) \ + (0x10 << (8 * (Ch - 1))) +#define XHDMIPHY1_TXRX_MSTRESET_MASK(Ch) \ + (0x20 << (8 * (Ch - 1))) +#define XHDMIPHY1_RX_INIT_USERRDY_MASK(Ch) \ + (0x40 << (8 * (Ch - 1))) +#define XHDMIPHY1_TXRX_INIT_PLLGTRESET_MASK(Ch) \ + (0x80 << (8 * (Ch - 1))) +#define XHDMIPHY1_TXRX_INIT_GTRESET_ALL_MASK \ + (XHDMIPHY1_TXRX_INIT_GTRESET_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_TXRX_INIT_GTRESET_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_TXRX_INIT_GTRESET_MASK(XHDMIPHY1_CHANNEL_ID_CH3) | \ + XHDMIPHY1_TXRX_INIT_GTRESET_MASK(XHDMIPHY1_CHANNEL_ID_CH4)) +#define XHDMIPHY1_TXRX_LNKRDY_SB_ALL_MASK \ + (XHDMIPHY1_TXRX_LNKRDY_SB_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_TXRX_LNKRDY_SB_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_TXRX_LNKRDY_SB_MASK(XHDMIPHY1_CHANNEL_ID_CH3) | \ + XHDMIPHY1_TXRX_LNKRDY_SB_MASK(XHDMIPHY1_CHANNEL_ID_CH4)) +#define XHDMIPHY1_TXRX_MSTRESET_ALL_MASK \ + (XHDMIPHY1_TXRX_MSTRESET_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_TXRX_MSTRESET_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_TXRX_MSTRESET_MASK(XHDMIPHY1_CHANNEL_ID_CH3) | \ + XHDMIPHY1_TXRX_MSTRESET_MASK(XHDMIPHY1_CHANNEL_ID_CH4)) +#define XHDMIPHY1_TX_INIT_USERRDY_ALL_MASK \ + (XHDMIPHY1_TX_INIT_USERRDY_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_TX_INIT_USERRDY_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_TX_INIT_USERRDY_MASK(XHDMIPHY1_CHANNEL_ID_CH3) | \ + XHDMIPHY1_TX_INIT_USERRDY_MASK(XHDMIPHY1_CHANNEL_ID_CH4)) +#define XHDMIPHY1_RX_INIT_USERRDY_ALL_MASK \ + (XHDMIPHY1_RX_INIT_USERRDY_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_RX_INIT_USERRDY_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_RX_INIT_USERRDY_MASK(XHDMIPHY1_CHANNEL_ID_CH3) | \ + XHDMIPHY1_RX_INIT_USERRDY_MASK(XHDMIPHY1_CHANNEL_ID_CH4)) +#define XHDMIPHY1_TXRX_INIT_PLLGTRESET_ALL_MASK \ + (XHDMIPHY1_TXRX_INIT_PLLGTRESET_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_TXRX_INIT_PLLGTRESET_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_TXRX_INIT_PLLGTRESET_MASK(XHDMIPHY1_CHANNEL_ID_CH3) | \ + XHDMIPHY1_TXRX_INIT_PLLGTRESET_MASK(XHDMIPHY1_CHANNEL_ID_CH4)) +/* 0x020, 0x028: TX_STATUS, RX_STATUS */ +#define XHDMIPHY1_TXRX_INIT_STATUS_RESETDONE_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XHDMIPHY1_TXRX_INIT_STATUS_PMARESETDONE_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XHDMIPHY1_TXRX_INIT_STATUS_POWERGOOD_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XHDMIPHY1_TXRX_INIT_STATUS_RESETDONE_ALL_MASK \ + (XHDMIPHY1_TXRX_INIT_STATUS_RESETDONE_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_TXRX_INIT_STATUS_RESETDONE_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_TXRX_INIT_STATUS_RESETDONE_MASK(XHDMIPHY1_CHANNEL_ID_CH3) | \ + XHDMIPHY1_TXRX_INIT_STATUS_RESETDONE_MASK(XHDMIPHY1_CHANNEL_ID_CH4)) +#define XHDMIPHY1_TXRX_INIT_STATUS_PMARESETDONE_ALL_MASK \ + (XHDMIPHY1_TXRX_INIT_STATUS_PMARESETDONE_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_TXRX_INIT_STATUS_PMARESETDONE_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_TXRX_INIT_STATUS_PMARESETDONE_MASK(XHDMIPHY1_CHANNEL_ID_CH3) | \ + XHDMIPHY1_TXRX_INIT_STATUS_PMARESETDONE_MASK(XHDMIPHY1_CHANNEL_ID_CH4)) +/* 0x02C: IBUFDS_GTXX_CTRL */ +#define XHDMIPHY1_IBUFDS_GTXX_CTRL_GTREFCLK0_CEB_MASK 0x1 +#define XHDMIPHY1_IBUFDS_GTXX_CTRL_GTREFCLK1_CEB_MASK 0x2 +/* 0x030: POWERDOWN_CONTROL */ +#define XHDMIPHY1_POWERDOWN_CONTROL_CPLLPD_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XHDMIPHY1_POWERDOWN_CONTROL_QPLL0PD_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XHDMIPHY1_POWERDOWN_CONTROL_QPLL1PD_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XHDMIPHY1_POWERDOWN_CONTROL_RXPD_MASK(Ch) \ + (0x18 << (8 * (Ch - 1))) +#define XHDMIPHY1_POWERDOWN_CONTROL_RXPD_SHIFT(Ch) \ + (3 + (8 * (Ch - 1))) +#define XHDMIPHY1_POWERDOWN_CONTROL_TXPD_MASK(Ch) \ + (0x60 << (8 * (Ch - 1))) +#define XHDMIPHY1_POWERDOWN_CONTROL_TXPD_SHIFT(Ch) \ + (5 + (8 * (Ch - 1))) +/* 0x038: LOOPBACK_CONTROL */ +#define XHDMIPHY1_LOOPBACK_CONTROL_CH_MASK(Ch) \ + (0x03 << (8 * (Ch - 1))) +#define XHDMIPHY1_LOOPBACK_CONTROL_CH_SHIFT(Ch) \ + (8 * (Ch - 1)) +/* 0x040, 0x044, 0x048, 0x04C, 0x060: DRP_CONTROL_CH[1-4], DRP_CONTROL_COMMON*/ +#define XHDMIPHY1_DRP_CONTROL_DRPADDR_MASK 0x00000FFF +#define XHDMIPHY1_DRP_CONTROL_DRPEN_MASK 0x00001000 +#define XHDMIPHY1_DRP_CONTROL_DRPWE_MASK 0x00002000 +#define XHDMIPHY1_DRP_CONTROL_DRPRESET_MASK 0x00004000 +#define XHDMIPHY1_DRP_CONTROL_DRPDI_MASK 0xFFFF0000 +#define XHDMIPHY1_DRP_CONTROL_DRPDI_SHIFT 16 +/* 0x050, 0x054, 0x058, 0x05C, 0x064: DRP_STATUS_CH[1-4], DRP_STATUS_COMMON */ +#define XHDMIPHY1_DRP_STATUS_DRPO_MASK 0x0FFFF +#define XHDMIPHY1_DRP_STATUS_DRPRDY_MASK 0x10000 +#define XHDMIPHY1_DRP_STATUS_DRPBUSY_MASK 0x20000 +/* 0x068: CPLL CAL PERIOD */ +#define XHDMIPHY1_CPLL_CAL_PERIOD_MASK 0x3FFFF +/* 0x06C: CPLL CAL TOLERANCE */ +#define XHDMIPHY1_CPLL_CAL_TOL_MASK 0x3FFFF +/* 0x068: GPI */ +#define XHDMIPHY1_TX_GPI_MASK(Ch) \ + (0x01 << (Ch - 1)) +#define XHDMIPHY1_RX_GPI_MASK(Ch) \ + (0x10 << (Ch - 1)) +/* 0x06C: GPO */ +#define XHDMIPHY1_TX_GPO_MASK(Ch) \ + (0x01 << (Ch - 1)) +#define XHDMIPHY1_TX_GPO_MASK_ALL(NCh) \ + ((NCh == 3) ? 0x7 : 0xF) +#define XHDMIPHY1_TX_GPO_SHIFT 0 +#define XHDMIPHY1_RX_GPO_MASK(Ch) \ + (0x10 << (Ch - 1)) +#define XHDMIPHY1_RX_GPO_MASK_ALL(NCh) \ + ((NCh == 3) ? 0x70 : 0xF0) +#define XHDMIPHY1_RX_GPO_SHIFT 4 +/* 0x070: TX_CONTROL */ +#define XHDMIPHY1_TX_CONTROL_TX8B10BEN_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XHDMIPHY1_TX_CONTROL_TX8B10BEN_ALL_MASK \ + (XHDMIPHY1_TX_CONTROL_TX8B10BEN_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_TX_CONTROL_TX8B10BEN_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_TX_CONTROL_TX8B10BEN_MASK(XHDMIPHY1_CHANNEL_ID_CH3) | \ + XHDMIPHY1_TX_CONTROL_TX8B10BEN_MASK(XHDMIPHY1_CHANNEL_ID_CH4)) +#define XHDMIPHY1_TX_CONTROL_TXPOLARITY_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XHDMIPHY1_TX_CONTROL_TXPOLARITY_ALL_MASK \ + (XHDMIPHY1_TX_CONTROL_TXPOLARITY_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_TX_CONTROL_TXPOLARITY_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_TX_CONTROL_TXPOLARITY_MASK(XHDMIPHY1_CHANNEL_ID_CH3) | \ + XHDMIPHY1_TX_CONTROL_TXPOLARITY_MASK(XHDMIPHY1_CHANNEL_ID_CH4)) +#define XHDMIPHY1_TX_CONTROL_TXPRBSSEL_MASK(Ch) \ + (0x5C << (8 * (Ch - 1))) +#define XHDMIPHY1_TX_CONTROL_TXPRBSSEL_ALL_MASK \ + (XHDMIPHY1_TX_CONTROL_TXPRBSSEL_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_TX_CONTROL_TXPRBSSEL_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_TX_CONTROL_TXPRBSSEL_MASK(XHDMIPHY1_CHANNEL_ID_CH3) | \ + XHDMIPHY1_TX_CONTROL_TXPRBSSEL_MASK(XHDMIPHY1_CHANNEL_ID_CH4)) +#define XHDMIPHY1_TX_CONTROL_TXPRBSSEL_SHIFT(Ch) \ + (2 + (8 * (Ch - 1))) +#define XHDMIPHY1_TX_CONTROL_TXPRBSFORCEERR_MASK(Ch) \ + (0x20 << (8 * (Ch - 1))) +#define XHDMIPHY1_TX_CONTROL_TXPRBSFORCEERR_ALL_MASK \ + (XHDMIPHY1_TX_CONTROL_TXPRBSFORCEERR_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_TX_CONTROL_TXPRBSFORCEERR_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_TX_CONTROL_TXPRBSFORCEERR_MASK(XHDMIPHY1_CHANNEL_ID_CH3) | \ + XHDMIPHY1_TX_CONTROL_TXPRBSFORCEERR_MASK(XHDMIPHY1_CHANNEL_ID_CH4)) +/* 0x074: TX_BUFFER_BYPASS */ +#define XHDMIPHY1_TX_BUFFER_BYPASS_TXPHDLYRESET_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XHDMIPHY1_TX_BUFFER_BYPASS_TXPHALIGN_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XHDMIPHY1_TX_BUFFER_BYPASS_TXPHALIGNEN_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XHDMIPHY1_TX_BUFFER_BYPASS_TXPHDLYPD_MASK(Ch) \ + (0x08 << (8 * (Ch - 1))) +#define XHDMIPHY1_TX_BUFFER_BYPASS_TXPHINIT_MASK(Ch) \ + (0x10 << (8 * (Ch - 1))) +#define XHDMIPHY1_TX_BUFFER_BYPASS_TXDLYRESET_MASK(Ch) \ + (0x20 << (8 * (Ch - 1))) +#define XHDMIPHY1_TX_BUFFER_BYPASS_TXDLYBYPASS_MASK(Ch) \ + (0x40 << (8 * (Ch - 1))) +#define XHDMIPHY1_TX_BUFFER_BYPASS_TXDLYEN_MASK(Ch) \ + (0x80 << (8 * (Ch - 1))) +/* 0x078: TX_STATUS */ +#define XHDMIPHY1_TX_STATUS_TXPHALIGNDONE_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XHDMIPHY1_TX_STATUS_TXPHINITDONE_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XHDMIPHY1_TX_STATUS_TXDLYRESETDONE_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XHDMIPHY1_TX_STATUS_TXBUFSTATUS_MASK(Ch) \ + (0x18 << (8 * (Ch - 1))) +#define XHDMIPHY1_TX_STATUS_TXBUFSTATUS_SHIFT(Ch) \ + (3 + (8 * (Ch - 1))) +/* 0x07C, 0x080: TX_DRIVER_CH12, TX_DRIVER_CH34 */ +#define XHDMIPHY1_TX_DRIVER_TXDIFFCTRL_MASK(Ch) \ + (0x000F << (16 * ((Ch - 1) % 2))) +#define XHDMIPHY1_TX_DRIVER_TXDIFFCTRL_SHIFT(Ch) \ + (16 * ((Ch - 1) % 2)) +#define XHDMIPHY1_TX_DRIVER_TXELECIDLE_MASK(Ch) \ + (0x0010 << (16 * ((Ch - 1) % 2))) +#define XHDMIPHY1_TX_DRIVER_TXELECIDLE_SHIFT(Ch) \ + (4 + (16 * ((Ch - 1) % 2))) +#define XHDMIPHY1_TX_DRIVER_TXINHIBIT_MASK(Ch) \ + (0x0020 << (16 * ((Ch - 1) % 2))) +#define XHDMIPHY1_TX_DRIVER_TXINHIBIT_SHIFT(Ch) \ + (5 + (16 * ((Ch - 1) % 2))) +#define XHDMIPHY1_TX_DRIVER_TXPOSTCURSOR_MASK(Ch) \ + (0x07C0 << (16 * ((Ch - 1) % 2))) +#define XHDMIPHY1_TX_DRIVER_TXPOSTCURSOR_SHIFT(Ch) \ + (6 + (16 * ((Ch - 1) % 2))) +#define XHDMIPHY1_TX_DRIVER_TXPRECURSOR_MASK(Ch) \ + (0xF800 << (16 * ((Ch - 1) % 2))) +#define XHDMIPHY1_TX_DRIVER_TXPRECURSOR_SHIFT(Ch) \ + (11 + (16 * ((Ch - 1) % 2))) +/* 0x084: TX_DRIVER_EXT */ +#define XHDMIPHY1_TX_DRIVER_EXT_TXDIFFCTRL_MASK(Ch) \ + (0x0001 << (8 * (Ch - 1))) +#define XHDMIPHY1_TX_DRIVER_EXT_TXDIFFCTRL_SHIFT(Ch) \ + (8 * (Ch - 1)) +/* 0x08C, 0x090: TX_RATE_CH12, TX_RATE_CH34 */ +#define XHDMIPHY1_TX_RATE_MASK(Ch) \ + (0x00FF << (16 * ((Ch - 1) % 2))) +#define XHDMIPHY1_TX_RATE_SHIFT(Ch) \ + (16 * ((Ch - 1) % 2)) +/* 0x098, 0x09C: RX_RATE_CH12, RX_RATE_CH34 */ +#define XHDMIPHY1_RX_RATE_MASK(Ch) \ + (0x00FF << (16 * ((Ch - 1) % 2))) +#define XHDMIPHY1_RX_RATE_SHIFT(Ch) \ + (16 * ((Ch - 1) % 2)) +/* 0x100: RX_CONTROL */ +#define XHDMIPHY1_RX_CONTROL_RX8B10BEN_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XHDMIPHY1_RX_CONTROL_RX8B10BEN_ALL_MASK \ + (XHDMIPHY1_RX_CONTROL_RX8B10BEN_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_RX_CONTROL_RX8B10BEN_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_RX_CONTROL_RX8B10BEN_MASK(XHDMIPHY1_CHANNEL_ID_CH3) | \ + XHDMIPHY1_RX_CONTROL_RX8B10BEN_MASK(XHDMIPHY1_CHANNEL_ID_CH4)) +#define XHDMIPHY1_RX_CONTROL_RXPOLARITY_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XHDMIPHY1_RX_CONTROL_RXPOLARITY_ALL_MASK \ + (XHDMIPHY1_RX_CONTROL_RXPOLARITY_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_RX_CONTROL_RXPOLARITY_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_RX_CONTROL_RXPOLARITY_MASK(XHDMIPHY1_CHANNEL_ID_CH3) | \ + XHDMIPHY1_RX_CONTROL_RXPOLARITY_MASK(XHDMIPHY1_CHANNEL_ID_CH4)) +#define XHDMIPHY1_RX_CONTROL_RXPRBSCNTRESET_MASK(Ch) \ + (0x08 << (8 * (Ch - 1))) +#define XHDMIPHY1_RX_CONTROL_RXPRBSSEL_MASK(Ch) \ + (0xF0 << (8 * (Ch - 1))) +#define XHDMIPHY1_RX_CONTROL_RXPRBSSEL_ALL_MASK \ + (XHDMIPHY1_RX_CONTROL_RXPRBSSEL_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_RX_CONTROL_RXPRBSSEL_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_RX_CONTROL_RXPRBSSEL_MASK(XHDMIPHY1_CHANNEL_ID_CH3) | \ + XHDMIPHY1_RX_CONTROL_RXPRBSSEL_MASK(XHDMIPHY1_CHANNEL_ID_CH4)) +#define XHDMIPHY1_RX_CONTROL_RXPRBSSEL_SHIFT(Ch) \ + (4 + (8 * (Ch - 1))) +/* 0x104: RX_STATUS */ +#define XHDMIPHY1_RX_STATUS_RXCDRLOCK_MASK(Ch) \ + (0x1 << (8 * (Ch - 1))) +#define XHDMIPHY1_RX_STATUS_RXBUFSTATUS_MASK(Ch) \ + (0xE << (8 * (Ch - 1))) +#define XHDMIPHY1_RX_STATUS_RXBUFSTATUS_SHIFT(Ch) \ + (1 + (8 * (Ch - 1))) +/* 0x104: RX_EQ_CDR */ +#define XHDMIPHY1_RX_CONTROL_RXLPMEN_MASK(Ch) \ + (0x01 << (8 * (Ch - 1))) +#define XHDMIPHY1_RX_STATUS_RXCDRHOLD_MASK(Ch) \ + (0x02 << (8 * (Ch - 1))) +#define XHDMIPHY1_RX_STATUS_RXOSOVRDEN_MASK(Ch) \ + (0x04 << (8 * (Ch - 1))) +#define XHDMIPHY1_RX_STATUS_RXLPMLFKLOVRDEN_MASK(Ch) \ + (0x08 << (8 * (Ch - 1))) +#define XHDMIPHY1_RX_STATUS_RXLPMHFOVRDEN_MASK(Ch) \ + (0x10 << (8 * (Ch - 1))) +#define XHDMIPHY1_RX_CONTROL_RXLPMEN_ALL_MASK \ + (XHDMIPHY1_RX_CONTROL_RXLPMEN_MASK(XHDMIPHY1_CHANNEL_ID_CH1) | \ + XHDMIPHY1_RX_CONTROL_RXLPMEN_MASK(XHDMIPHY1_CHANNEL_ID_CH2) | \ + XHDMIPHY1_RX_CONTROL_RXLPMEN_MASK(XHDMIPHY1_CHANNEL_ID_CH3) | \ + XHDMIPHY1_RX_CONTROL_RXLPMEN_MASK(XHDMIPHY1_CHANNEL_ID_CH4)) +/* 0x110, 0x114, 0x118, 0x11C: INTR_EN, INTR_DIS, INTR_MASK, INTR_STS */ +#define XHDMIPHY1_INTR_TXRESETDONE_MASK 0x00000001 +#define XHDMIPHY1_INTR_RXRESETDONE_MASK 0x00000002 +#define XHDMIPHY1_INTR_CPLL_LOCK_MASK 0x00000004 +#define XHDMIPHY1_INTR_QPLL0_LOCK_MASK 0x00000008 +#define XHDMIPHY1_INTR_LCPLL_LOCK_MASK 0x00000008 +#define XHDMIPHY1_INTR_TXALIGNDONE_MASK 0x00000010 +#define XHDMIPHY1_INTR_QPLL1_LOCK_MASK 0x00000020 +#define XHDMIPHY1_INTR_RPLL_LOCK_MASK 0x00000020 +#define XHDMIPHY1_INTR_TXCLKDETFREQCHANGE_MASK 0x00000040 +#define XHDMIPHY1_INTR_RXCLKDETFREQCHANGE_MASK 0x00000080 +#define XHDMIPHY1_INTR_TXMMCMUSRCLK_LOCK_MASK 0x00000200 +#define XHDMIPHY1_INTR_RXMMCMUSRCLK_LOCK_MASK 0x00000400 +#define XHDMIPHY1_INTR_TXGPO_RE_MASK 0x00000800 +#define XHDMIPHY1_INTR_RXGPO_RE_MASK 0x00001000 +#define XHDMIPHY1_INTR_TXTMRTIMEOUT_MASK 0x40000000 +#define XHDMIPHY1_INTR_RXTMRTIMEOUT_MASK 0x80000000 +#define XHDMIPHY1_INTR_QPLL_LOCK_MASK XHDMIPHY1_INTR_QPLL0_LOCK_MASK +/* 0x120, 0x140: MMCM_TXUSRCLK_CTRL, MMCM_RXUSRCLK_CTRL */ +#define XHDMIPHY1_MMCM_USRCLK_CTRL_CFG_NEW_MASK 0x01 +#define XHDMIPHY1_MMCM_USRCLK_CTRL_RST_MASK 0x02 +#define XHDMIPHY1_MMCM_USRCLK_CTRL_CFG_SUCCESS_MASK 0x10 +#define XHDMIPHY1_MMCM_USRCLK_CTRL_LOCKED_MASK 0x200 +#define XHDMIPHY1_MMCM_USRCLK_CTRL_PWRDWN_MASK 0x400 +#define XHDMIPHY1_MMCM_USRCLK_CTRL_LOCKED_MASK_MASK 0x800 +#define XHDMIPHY1_MMCM_USRCLK_CTRL_CLKINSEL_MASK 0x1000 +/* 0x124, 0x144: MMCM_TXUSRCLK_REG1, MMCM_RXUSRCLK_REG1 */ +#define XHDMIPHY1_MMCM_USRCLK_REG1_DIVCLK_MASK \ + 0x00000FF +#define XHDMIPHY1_MMCM_USRCLK_REG1_CLKFBOUT_MULT_MASK \ + 0x000FF00 +#define XHDMIPHY1_MMCM_USRCLK_REG1_CLKFBOUT_MULT_SHIFT \ + 8 +#define XHDMIPHY1_MMCM_USRCLK_REG1_CLKFBOUT_FRAC_MASK \ + 0x3FF0000 +#define XHDMIPHY1_MMCM_USRCLK_REG1_CLKFBOUT_FRAC_SHIFT \ + 16 +/* 0x128, 0x148: MMCM_TXUSRCLK_REG2, MMCM_RXUSRCLK_REG2 */ +#define XHDMIPHY1_MMCM_USRCLK_REG2_DIVCLK_MASK \ + 0x00000FF +#define XHDMIPHY1_MMCM_USRCLK_REG2_CLKOUT0_FRAC_MASK \ + 0x3FF0000 +#define XHDMIPHY1_MMCM_USRCLK_REG2_CLKOUT0_FRAC_SHIFT \ + 16 +/* 0x12C, 0x130, 0x14C, 0x150: MMCM_TXUSRCLK_REG[3,4], MMCM_RXUSRCLK_REG[3,4]*/ +#define XHDMIPHY1_MMCM_USRCLK_REG34_DIVCLK_MASK \ + 0x00000FF +/* 0x134, 0x154: BUFGT_TXUSRCLK, BUFGT_RXUSRCLK */ +#define XHDMIPHY1_BUFGGT_XXUSRCLK_CLR_MASK 0x1 +#define XHDMIPHY1_BUFGGT_XXUSRCLK_DIV_MASK 0xE +#define XHDMIPHY1_BUFGGT_XXUSRCLK_DIV_SHIFT 1 +/* 0x138, 0x158: MISC_TXUSRCLK_REG, MISC_RXUSERCLK_REG */ +#define XHDMIPHY1_MISC_XXUSRCLK_CKOUT1_OEN_MASK 0x1 +#define XHDMIPHY1_MISC_XXUSRCLK_REFCLK_CEB_MASK 0x2 +/* 0x200: CLKDET_CTRL */ +#define XHDMIPHY1_CLKDET_CTRL_RUN_MASK 0x1 +#define XHDMIPHY1_CLKDET_CTRL_TX_TMR_CLR_MASK 0x2 +#define XHDMIPHY1_CLKDET_CTRL_RX_TMR_CLR_MASK 0x4 +#define XHDMIPHY1_CLKDET_CTRL_TX_FREQ_RST_MASK 0x8 +#define XHDMIPHY1_CLKDET_CTRL_RX_FREQ_RST_MASK 0x10 +#define XHDMIPHY1_CLKDET_CTRL_FREQ_LOCK_THRESH_MASK 0x1FE0 +#define XHDMIPHY1_CLKDET_CTRL_FREQ_LOCK_THRESH_SHIFT 5 +/* 0x204: CLKDET_STAT */ +#define XHDMIPHY1_CLKDET_STAT_TX_FREQ_ZERO_MASK 0x1 +#define XHDMIPHY1_CLKDET_STAT_RX_FREQ_ZERO_MASK 0x2 +#define XHDMIPHY1_CLKDET_STAT_TX_REFCLK_LOCK_MASK 0x3 +#define XHDMIPHY1_CLKDET_STAT_TX_REFCLK_LOCK_CAP_MASK 0x4 +/* 0x300: DRU_CTRL */ +#define XHDMIPHY1_DRU_CTRL_RST_MASK(Ch) (0x01 << (8 * (Ch - 1))) +#define XHDMIPHY1_DRU_CTRL_EN_MASK(Ch) (0x02 << (8 * (Ch - 1))) +/* 0x304: DRU_STAT */ +#define XHDMIPHY1_DRU_STAT_ACTIVE_MASK(Ch) (0x01 << (8 * (Ch - 1))) +#define XHDMIPHY1_DRU_STAT_VERSION_MASK 0xFF000000 +#define XHDMIPHY1_DRU_STAT_VERSION_SHIFT 24 +/* 0x30C, 0x318, 0x324, 0x330: DRU_CFREQ_H_CH[1-4] */ +#define XHDMIPHY1_DRU_CFREQ_H_MASK 0x1F +/* 0x310, 0x31C, 0x328, 0x334: DRU_GAIN_CH[1-4] */ +#define XHDMIPHY1_DRU_GAIN_G1_MASK 0x00001F +#define XHDMIPHY1_DRU_GAIN_G1_SHIFT 0 +#define XHDMIPHY1_DRU_GAIN_G1_P_MASK 0x001F00 +#define XHDMIPHY1_DRU_GAIN_G1_P_SHIFT 8 +#define XHDMIPHY1_DRU_GAIN_G2_MASK 0x1F0000 +#define XHDMIPHY1_DRU_GAIN_G2_SHIFT 16 +/* 0x340 TMDS PATGEN */ +#define XHDMIPHY1_PATGEN_CTRL_ENABLE_MASK 0x80000000 +#define XHDMIPHY1_PATGEN_CTRL_ENABLE_SHIFT 31 +#define XHDMIPHY1_PATGEN_CTRL_RATIO_MASK 0x7 +#define XHDMIPHY1_PATGEN_CTRL_RATIO_SHIFT 0 +/* @} */ + +/******************* Macros (Inline Functions) Definitions ********************/ + +/** @name Register access macro definitions. + * @{ + */ +#define XHdmiphy1_In32 Xil_In32 +#define XHdmiphy1_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 XHdmiphy1_ReadReg(u32 BaseAddress, u32 RegOffset) + * +*******************************************************************************/ +#define XHdmiphy1_ReadReg(BaseAddress, RegOffset) \ + XHdmiphy1_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 XHdmiphy1_WriteReg(u32 BaseAddress, u32 RegOffset, u32 Data) + * +*******************************************************************************/ +#define XHdmiphy1_WriteReg(BaseAddress, RegOffset, Data) \ + XHdmiphy1_Out32((BaseAddress) + (RegOffset), (Data)) + +#ifdef __cplusplus +} +#endif + +#endif /* XHDMIPHY1_HW_H_ */ +/** @} */ diff --git a/hdmi/phy-xilinx-vphy/xhdmiphy1_i.c b/hdmi/phy-xilinx-vphy/xhdmiphy1_i.c new file mode 100644 index 0000000..580a4c3 --- /dev/null +++ b/hdmi/phy-xilinx-vphy/xhdmiphy1_i.c @@ -0,0 +1,1875 @@ +/******************************************************************************* + * + * + * 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 xhdmiphy1_i.c + * + * Contains generic APIs that are locally called or used within the + * HDMIPHY driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ *            dd/mm/yy
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   gm   10/12/18 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include +#include "xstatus.h" +#include "xhdmiphy1.h" +#include "xhdmiphy1_i.h" +#include "xhdmiphy1_hdmi.h" +#include +#include "xhdmiphy1_gt.h" + +/**************************** Function Prototypes *****************************/ + + +/**************************** Function Definitions ****************************/ + +/*****************************************************************************/ +/** +* This function will set the channel IDs to correspond with the supplied +* channel ID based on the protocol. HDMI uses 3 channels; This ID +* translation is done to allow other functions to operate iteratively over +* multiple channels. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_Ch2Ids(XHdmiphy1 *InstancePtr, XHdmiphy1_ChannelId ChId, + u8 *Id0, u8 *Id1) +{ + u8 Channels = 4; + + if (ChId == XHDMIPHY1_CHANNEL_ID_CHA) { + *Id0 = XHDMIPHY1_CHANNEL_ID_CH1; + if ((XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_TX)) || + (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_RX))) { + if (InstancePtr->Config.UseGtAsTxTmdsClk == TRUE) { + *Id1 = XHDMIPHY1_CHANNEL_ID_CH4; + } + else { + *Id1 = XHDMIPHY1_CHANNEL_ID_CH3; + } + } + else { + Channels = ((InstancePtr->Config.TxChannels >= + InstancePtr->Config.RxChannels) ? + InstancePtr->Config.TxChannels : + InstancePtr->Config.RxChannels); + + if (Channels == 1) { + *Id1 = XHDMIPHY1_CHANNEL_ID_CH1; + } + else if (Channels == 2) { + *Id1 = XHDMIPHY1_CHANNEL_ID_CH2; + } + else if (Channels == 3) { + *Id1 = XHDMIPHY1_CHANNEL_ID_CH3; + } + else { + *Id1 = XHDMIPHY1_CHANNEL_ID_CH4; + } + } + } + else if (ChId == XHDMIPHY1_CHANNEL_ID_CMNA) { + *Id0 = XHDMIPHY1_CHANNEL_ID_CMN0; + if ((InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTHE3) || + (InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTHE4) || + (InstancePtr->Config.XcvrType == XHDMIPHY1_GT_TYPE_GTYE4)) { + *Id1 = XHDMIPHY1_CHANNEL_ID_CMN1; + } + else { + *Id1 = XHDMIPHY1_CHANNEL_ID_CMN0; + } + } + else { + *Id0 = *Id1 = ChId; + } +} + +/*****************************************************************************/ +/** +* This function will set the current RX/TX configuration over DRP. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_DirReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir) +{ + u32 Status = XST_SUCCESS; + u8 Id, Id0, Id1; + + XHdmiphy1_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + if (Dir == XHDMIPHY1_DIR_TX) { + Status |= XHdmiphy1_TxChReconfig(InstancePtr, QuadId, + (XHdmiphy1_ChannelId)Id); + } + else { + Status |= XHdmiphy1_RxChReconfig(InstancePtr, QuadId, + (XHdmiphy1_ChannelId)Id); + } + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + break; + } + } + + XHdmiphy1_LogWrite(InstancePtr, (Dir == XHDMIPHY1_DIR_TX) ? + XHDMIPHY1_LOG_EVT_GT_TX_RECONFIG : XHDMIPHY1_LOG_EVT_GT_RX_RECONFIG, 1); + + return Status; +} + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) +/*****************************************************************************/ +/** +* 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 XHdmiphy1 core instance. +* @param QuadId is the GT quad ID to operate on. +* +* @return +* - XST_SUCCESS. +* +* @note None. +* +******************************************************************************/ +u32 XHdmiphy1_WriteCfgRefClkSelReg(XHdmiphy1 *InstancePtr, u8 QuadId) +{ + u32 RegVal = 0; + XHdmiphy1_Channel *ChPtr; + XHdmiphy1_GtType GtType = InstancePtr->Config.XcvrType; + + /* Point to the first channel since settings apply to all channels. */ + ChPtr = &InstancePtr->Quads[QuadId].Ch1; + + /* PllRefClkSel. */ + /* - QPLL0. */ + RegVal &= ~XHDMIPHY1_REF_CLK_SEL_QPLL0_MASK; + RegVal = InstancePtr->Quads[QuadId].Cmn0.PllRefClkSel; + /* - CPLL. */ + RegVal &= ~XHDMIPHY1_REF_CLK_SEL_CPLL_MASK; + RegVal |= (ChPtr->CpllRefClkSel << XHDMIPHY1_REF_CLK_SEL_CPLL_SHIFT); + if ((GtType == XHDMIPHY1_GT_TYPE_GTHE3) || + (GtType == XHDMIPHY1_GT_TYPE_GTHE4) || + (GtType == XHDMIPHY1_GT_TYPE_GTYE4)) { + /* - QPLL1. */ + RegVal &= ~XHDMIPHY1_REF_CLK_SEL_QPLL1_MASK; + RegVal |= (InstancePtr->Quads[QuadId].Cmn1.PllRefClkSel << + XHDMIPHY1_REF_CLK_SEL_QPLL1_SHIFT); + } + + /* SysClkDataSel. PLLCLKSEL */ + RegVal &= ~XHDMIPHY1_REF_CLK_SEL_SYSCLKSEL_MASK; + /* - TXSYSCLKSEL[0]. TXPLLCLKSEL*/ + RegVal |= (ChPtr->TxDataRefClkSel << + XHDMIPHY1_REF_CLK_SEL_TXSYSCLKSEL_DATA_SHIFT(GtType)) & + XHDMIPHY1_REF_CLK_SEL_TXSYSCLKSEL_DATA_MASK(GtType); + /* - RXSYSCLKSEL[0]. RXPLLCLKSEL*/ + RegVal |= (ChPtr->RxDataRefClkSel << + XHDMIPHY1_REF_CLK_SEL_RXSYSCLKSEL_DATA_SHIFT(GtType)) & + XHDMIPHY1_REF_CLK_SEL_RXSYSCLKSEL_DATA_MASK(GtType); + + /* SysClkOutSel. */ + /* - TXSYSCLKSEL[1]. */ + RegVal |= (ChPtr->TxOutRefClkSel << + XHDMIPHY1_REF_CLK_SEL_TXSYSCLKSEL_OUT_SHIFT(GtType)) & + XHDMIPHY1_REF_CLK_SEL_TXSYSCLKSEL_OUT_MASK(GtType); + /* - RXSYSCLKSEL[1]. */ + RegVal |= (ChPtr->RxOutRefClkSel << + XHDMIPHY1_REF_CLK_SEL_RXSYSCLKSEL_OUT_SHIFT(GtType)) & + XHDMIPHY1_REF_CLK_SEL_RXSYSCLKSEL_OUT_MASK(GtType); + + /* Write to hardware. */ + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_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 XHdmiphy1 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 XHdmiphy1_CfgPllRefClkSel(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_PllRefClkSelType RefClkSel) +{ + u8 Id, Id0, Id1; + + XHdmiphy1_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_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 XHdmiphy1 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 XHdmiphy1_CfgSysClkDataSel(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, + XHdmiphy1_SysClkDataSelType SysClkDataSel) +{ + XHdmiphy1_Channel *ChPtr; + u8 Id, Id0, Id1; + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + /* Select in software - same for all channels. */ + for (Id = Id0; Id <= Id1; Id++) { + ChPtr = &InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_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 XHdmiphy1 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 XHdmiphy1_CfgSysClkOutSel(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, + XHdmiphy1_SysClkOutSelType SysClkOutSel) +{ + XHdmiphy1_Channel *ChPtr; + u8 Id, Id0, Id1; + + XHdmiphy1_Ch2Ids(InstancePtr, XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + /* Select in software - same for all channels. */ + for (Id = Id0; Id <= Id1; Id++) { + ChPtr = &InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)]; + ChPtr->OutRefClkSel[Dir] = SysClkOutSel; + } +} +#endif + +/*****************************************************************************/ +/** +* Obtain the reconfiguration channel ID for given PLL type +* +* @param InstancePtr is a pointer to the XHdmiphy1 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. +* +******************************************************************************/ +XHdmiphy1_ChannelId XHdmiphy1_GetRcfgChId(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, XHdmiphy1_PllType PllType) +{ + XHdmiphy1_ChannelId ChId; + + /* Suppress Warning Messages */ + InstancePtr = InstancePtr; + QuadId = QuadId; + Dir = Dir; + + /* Determine which channel(s) to operate on. */ + switch (PllType) { + case XHDMIPHY1_PLL_TYPE_QPLL: + case XHDMIPHY1_PLL_TYPE_QPLL0: + case XHDMIPHY1_PLL_TYPE_LCPLL: + ChId = XHDMIPHY1_CHANNEL_ID_CMN0; + break; + case XHDMIPHY1_PLL_TYPE_QPLL1: + case XHDMIPHY1_PLL_TYPE_RPLL: + ChId = XHDMIPHY1_CHANNEL_ID_CMN1; + break; + default: + ChId = XHDMIPHY1_CHANNEL_ID_CHA; + break; + } + + return ChId; +} + +/*****************************************************************************/ +/** +* This function will check the status of a PLL lock on the specified channel. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_IsPllLocked(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId) +{ + u32 RegVal; + u32 MaskVal; +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + XHdmiphy1_PllType TxPllType; + XHdmiphy1_PllType RxPllType; +#endif + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (ChId == XHDMIPHY1_CHANNEL_ID_CMN0) { +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + MaskVal = XHDMIPHY1_PLL_LOCK_STATUS_QPLL0_MASK; +#else + MaskVal = XHDMIPHY1_PLL_LOCK_STATUS_LCPLL_MASK; +#endif + } + else if (ChId == XHDMIPHY1_CHANNEL_ID_CMN1) { +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + MaskVal = XHDMIPHY1_PLL_LOCK_STATUS_QPLL1_MASK; +#else + MaskVal = XHDMIPHY1_PLL_LOCK_STATUS_RPLL_MASK; + } + else { + /* This will result to XST_FAILURE */ + MaskVal = XHDMIPHY1_PLL_LOCK_STATUS_CPLL_ALL_MASK; +#endif + } +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + else if (ChId == XHDMIPHY1_CHANNEL_ID_CMNA) { + MaskVal = XHDMIPHY1_PLL_LOCK_STATUS_QPLL0_MASK | + XHDMIPHY1_PLL_LOCK_STATUS_QPLL1_MASK; + } + else if (ChId == XHDMIPHY1_CHANNEL_ID_CHA) { + TxPllType = XHdmiphy1_GetPllType(InstancePtr, 0, + XHDMIPHY1_DIR_TX, XHDMIPHY1_CHANNEL_ID_CH1); + RxPllType = XHdmiphy1_GetPllType(InstancePtr, 0, + XHDMIPHY1_DIR_RX, XHDMIPHY1_CHANNEL_ID_CH1); + if (RxPllType == XHDMIPHY1_PLL_TYPE_CPLL && + XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_RX)) { + MaskVal = XHDMIPHY1_PLL_LOCK_STATUS_CPLL_HDMI_MASK; + } + else if (TxPllType == XHDMIPHY1_PLL_TYPE_CPLL && + XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_TX)) { + MaskVal = XHDMIPHY1_PLL_LOCK_STATUS_CPLL_HDMI_MASK; + } + else { + MaskVal = XHDMIPHY1_PLL_LOCK_STATUS_CPLL_ALL_MASK; + } + } + else { + MaskVal = XHDMIPHY1_PLL_LOCK_STATUS_CPLL_MASK(ChId); + } +#endif + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_PLL_LOCK_STATUS_REG); + + if ((RegVal & MaskVal) == MaskVal) { + return XST_SUCCESS; + } + + return XST_FAILURE; +} + + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) +/*****************************************************************************/ +/** +* Obtain the current reference clock frequency for the quad based on the +* reference clock type. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_GetQuadRefClkFreq(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_PllRefClkSelType RefClkType) +{ + u32 FreqHz; + + u8 RefClkIndex = RefClkType - XHDMIPHY1_PLL_REFCLKSEL_TYPE_GTREFCLK0; + + FreqHz = (RefClkType > XHDMIPHY1_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 XHdmiphy1 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. +* +******************************************************************************/ +XHdmiphy1_SysClkDataSelType XHdmiphy1_GetSysClkDataSel(XHdmiphy1 *InstancePtr, + u8 QuadId, XHdmiphy1_DirectionType Dir, XHdmiphy1_ChannelId ChId) +{ + u32 Sel; + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + ChId = ChId; + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_REF_CLK_SEL_REG); + + if (Dir == XHDMIPHY1_DIR_TX) { + /* Synchronize software configuration to hardware. */ + Sel = RegVal & XHDMIPHY1_REF_CLK_SEL_TXSYSCLKSEL_DATA_MASK( + InstancePtr->Config.XcvrType); + Sel >>= XHDMIPHY1_REF_CLK_SEL_TXSYSCLKSEL_DATA_SHIFT( + InstancePtr->Config.XcvrType); + } + else { + /* Synchronize software configuration to hardware. */ + Sel = RegVal & XHDMIPHY1_REF_CLK_SEL_RXSYSCLKSEL_DATA_MASK( + InstancePtr->Config.XcvrType); + Sel >>= XHDMIPHY1_REF_CLK_SEL_RXSYSCLKSEL_DATA_SHIFT( + InstancePtr->Config.XcvrType); + } + + return (XHdmiphy1_SysClkDataSelType) Sel; +} + +/*****************************************************************************/ +/** +* Obtain the current [RT]XSYSCLKSEL[1] configuration. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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. +* +******************************************************************************/ +XHdmiphy1_SysClkOutSelType XHdmiphy1_GetSysClkOutSel(XHdmiphy1 *InstancePtr, + u8 QuadId, XHdmiphy1_DirectionType Dir, XHdmiphy1_ChannelId ChId) +{ + u32 Sel; + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + ChId = ChId; + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_REF_CLK_SEL_REG); + + if (Dir == XHDMIPHY1_DIR_TX) { + /* Synchronize software configuration to hardware. */ + Sel = RegVal & XHDMIPHY1_REF_CLK_SEL_TXSYSCLKSEL_OUT_MASK( + InstancePtr->Config.XcvrType); + Sel >>= XHDMIPHY1_REF_CLK_SEL_TXSYSCLKSEL_OUT_SHIFT( + InstancePtr->Config.XcvrType); + } + else { + /* Synchronize software configuration to hardware. */ + Sel = RegVal & XHDMIPHY1_REF_CLK_SEL_RXSYSCLKSEL_OUT_MASK( + InstancePtr->Config.XcvrType); + Sel >>= XHDMIPHY1_REF_CLK_SEL_RXSYSCLKSEL_OUT_SHIFT( + InstancePtr->Config.XcvrType); + } + + return (XHdmiphy1_SysClkOutSelType)Sel; +} + +/*****************************************************************************/ +/** +* This function will reset and enable the Video PHY's user core logic. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_GtUserRdyEnable(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, u8 Hold) +{ + u32 RegVal; + u32 MaskVal; + u32 RegOffset; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XHDMIPHY1_DIR_TX) { + RegOffset = XHDMIPHY1_TX_INIT_REG; + + if (ChId == XHDMIPHY1_CHANNEL_ID_CHA) { + MaskVal = XHDMIPHY1_TX_INIT_USERRDY_ALL_MASK; + } + else { + MaskVal = XHDMIPHY1_TX_INIT_USERRDY_MASK(ChId); + } + } + else { + RegOffset = XHDMIPHY1_RX_INIT_REG; + if (ChId == XHDMIPHY1_CHANNEL_ID_CHA) { + MaskVal = XHDMIPHY1_RX_INIT_USERRDY_ALL_MASK; + } + else { + MaskVal = XHDMIPHY1_RX_INIT_USERRDY_MASK(ChId); + } + } + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + /* Assert reset. */ + RegVal |= MaskVal; + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); + + if (!Hold) { + /* De-assert reset. */ + RegVal &= ~MaskVal; + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, + RegOffset, RegVal); + } + + return XST_SUCCESS; +} +#else +/*****************************************************************************/ +/** +* This function will set the TXRATE or RXRATE port to select the GT Wizard +* configuration +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_SetGtLineRateCfg(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir) +{ + u32 RegVal; + u32 MaskVal; + u32 ShiftVal; + u32 RegOffset; + u16 LRCfgVal; + XHdmiphy1_PllType PllType; + + /* Determine PLL type. */ + PllType = XHdmiphy1_GetPllType(InstancePtr, 0, Dir, + XHDMIPHY1_CHANNEL_ID_CH1); + + /* Extract Line Rate Config Value */ + if (PllType == XHDMIPHY1_PLL_TYPE_LCPLL) { + LRCfgVal = InstancePtr->Quads[QuadId].Lcpll.LineRateCfg; + } + else { /* RPLL */ + LRCfgVal = InstancePtr->Quads[QuadId].Rpll.LineRateCfg; + } + + if (Dir == XHDMIPHY1_DIR_TX) { + if ((ChId == XHDMIPHY1_CHANNEL_ID_CH1) || + (ChId == XHDMIPHY1_CHANNEL_ID_CH2)) { + RegOffset = XHDMIPHY1_TX_RATE_CH12_REG; + } + else { + RegOffset = XHDMIPHY1_TX_RATE_CH34_REG; + } + MaskVal = XHDMIPHY1_TX_RATE_MASK(ChId); + ShiftVal = XHDMIPHY1_TX_RATE_SHIFT(ChId); + } + else{ + if ((ChId == XHDMIPHY1_CHANNEL_ID_CH1) || + (ChId == XHDMIPHY1_CHANNEL_ID_CH2)) { + RegOffset = XHDMIPHY1_RX_RATE_CH12_REG; + } + else { + RegOffset = XHDMIPHY1_RX_RATE_CH34_REG; + } + MaskVal = XHDMIPHY1_RX_RATE_MASK(ChId); + ShiftVal = XHDMIPHY1_RX_RATE_SHIFT(ChId); + } + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + RegVal &= ~MaskVal; + RegVal |= (LRCfgVal << ShiftVal); + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); +} + +/*****************************************************************************/ +/** +* This function will get the TXRATE or RXRATE port to select the GT Wizard +* configuration +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 None. +* +* @note None. +* +******************************************************************************/ +u16 XHdmiphy1_GetGtLineRateCfg(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir) +{ + u32 RegVal; + u32 MaskVal; + u32 ShiftVal; + u32 RegOffset; + u16 LRCfgVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XHDMIPHY1_DIR_TX) { + if ((ChId == XHDMIPHY1_CHANNEL_ID_CH1) || + (ChId == XHDMIPHY1_CHANNEL_ID_CH2)) { + RegOffset = XHDMIPHY1_TX_RATE_CH12_REG; + } + else { + RegOffset = XHDMIPHY1_TX_RATE_CH34_REG; + } + MaskVal = XHDMIPHY1_TX_RATE_MASK(ChId); + ShiftVal = XHDMIPHY1_TX_RATE_SHIFT(ChId); + } + else{ + if ((ChId == XHDMIPHY1_CHANNEL_ID_CH1) || + (ChId == XHDMIPHY1_CHANNEL_ID_CH2)) { + RegOffset = XHDMIPHY1_RX_RATE_CH12_REG; + } + else { + RegOffset = XHDMIPHY1_RX_RATE_CH34_REG; + } + MaskVal = XHDMIPHY1_RX_RATE_MASK(ChId); + ShiftVal = XHDMIPHY1_RX_RATE_SHIFT(ChId); + } + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + RegVal &= MaskVal; + LRCfgVal = (u16)(RegVal >> ShiftVal); + + return LRCfgVal; +} + +/*****************************************************************************/ +/** +* This function will set the GPI ports to the GT Wizard +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 Set Set=TRUE; Clear=FALSE +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_SetGpi(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, u8 Set) +{ + u32 RegVal; + u32 MaskVal = 0; + u8 Id, Id0, Id1; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + /* Read GPI Register*/ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_GT_DBG_GPI_REG); + + XHdmiphy1_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + if (Dir == XHDMIPHY1_DIR_TX) { + MaskVal |= XHDMIPHY1_TX_GPI_MASK(Id); + } + else { + MaskVal |= XHDMIPHY1_RX_GPI_MASK(Id); + } + } + + /* Construct Register Value */ + if (Set) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + + /* Write GPI Register*/ + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_GT_DBG_GPI_REG, RegVal); +} + +/*****************************************************************************/ +/** +* This function will get the GPI ports value from the GT Wizard +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 Value. +* +* @note None. +* +******************************************************************************/ +u8 XHdmiphy1_GetGpo(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir) +{ + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + ChId = ChId; + + /* Read GPI Register*/ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_GT_DBG_GPO_REG); + + if (Dir == XHDMIPHY1_DIR_TX) { + return ((RegVal & + XHDMIPHY1_TX_GPO_MASK_ALL(InstancePtr->Config.TxChannels)) + >> XHDMIPHY1_TX_GPO_SHIFT); + } + else { + return ((RegVal & + XHDMIPHY1_RX_GPO_MASK_ALL(InstancePtr->Config.RxChannels)) + >> XHDMIPHY1_RX_GPO_SHIFT); + } +} + +/*****************************************************************************/ +/** +* This function will set the (TX|RX) MSTRESET port of the GT +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 Reset Set=TRUE; Clear=FALSE +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_GtMstReset(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, u8 Reset) +{ + u32 RegOffsetCtrl; + u32 RegVal; + u32 MaskVal = 0; + u8 Id, Id0, Id1; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + XHdmiphy1_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + MaskVal |= XHDMIPHY1_TXRX_MSTRESET_MASK(Id); + } + + if (Dir == XHDMIPHY1_DIR_TX) { + RegOffsetCtrl = XHDMIPHY1_TX_INIT_REG; + } + else { + RegOffsetCtrl = XHDMIPHY1_RX_INIT_REG; + } + + /* Read TX|RX INIT Register*/ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + RegOffsetCtrl); + + /* Construct Register Value */ + if (Reset) { + RegVal |= MaskVal; + } + else { + RegVal &= ~MaskVal; + } + + /* Write TX|RX INIT Register*/ + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, + RegOffsetCtrl, RegVal); +} + +/*****************************************************************************/ +/** +* This function will will check the current CFG setting and compare +* it with the next CFG value +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 Reset Set=TRUE; Clear=FALSE +* +* @return TRUE if Current and Next CFG are the same +* FALSE if Current and Next CFG are different +* +* @note None. +* +******************************************************************************/ +u8 XHdmiphy1_CheckLineRateCfg(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir) +{ + u16 CurrCfgVal, LRCfgVal; + XHdmiphy1_PllType PllType; + + /* Determine PLL type. */ + PllType = XHdmiphy1_GetPllType(InstancePtr, 0, Dir, + XHDMIPHY1_CHANNEL_ID_CH1); + + /* Extract Line Rate Config Value */ + if (PllType == XHDMIPHY1_PLL_TYPE_LCPLL) { + LRCfgVal = InstancePtr->Quads[QuadId].Lcpll.LineRateCfg; + } + else { /* RPLL */ + LRCfgVal = InstancePtr->Quads[QuadId].Rpll.LineRateCfg; + } + + /* Get current line rate configuration value */ + CurrCfgVal = XHdmiphy1_GetGtLineRateCfg(InstancePtr, QuadId, ChId, Dir); + + if (CurrCfgVal != LRCfgVal) { + return FALSE; + } + else { + return TRUE; + } +} +#endif + +/*****************************************************************************/ +/** +* This function will reset the mixed-mode clock manager (MMCM) core. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_MmcmReset(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, u8 Hold) +{ + u32 RegOffsetCtrl; + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XHDMIPHY1_DIR_TX) { + RegOffsetCtrl = XHDMIPHY1_MMCM_TXUSRCLK_CTRL_REG; + } + else { + RegOffsetCtrl = XHDMIPHY1_MMCM_RXUSRCLK_CTRL_REG; + } + + /* Assert reset. */ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl); + RegVal |= XHDMIPHY1_MMCM_USRCLK_CTRL_RST_MASK; + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, RegVal); + + if (!Hold) { + /* De-assert reset. */ + RegVal &= ~XHDMIPHY1_MMCM_USRCLK_CTRL_RST_MASK; + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, + RegVal); + } +} + +/*****************************************************************************/ +/** +* This function will reset the mixed-mode clock manager (MMCM) core. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_MmcmLockedMaskEnable(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, u8 Enable) +{ + u32 RegOffsetCtrl; + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XHDMIPHY1_DIR_TX) { + RegOffsetCtrl = XHDMIPHY1_MMCM_TXUSRCLK_CTRL_REG; + } + else { + RegOffsetCtrl = XHDMIPHY1_MMCM_RXUSRCLK_CTRL_REG; + } + + /* Assert reset. */ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl); + RegVal |= XHDMIPHY1_MMCM_USRCLK_CTRL_LOCKED_MASK_MASK; + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, RegVal); + + if (!Enable) { + /* De-assert reset. */ + RegVal &= ~XHDMIPHY1_MMCM_USRCLK_CTRL_LOCKED_MASK_MASK; + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl, + RegVal); + } +} + +/*****************************************************************************/ +/** +* This function will get the lock status of the mixed-mode clock +* manager (MMCM) core. +* +* @param InstancePtr is a pointer to the XHdmiphy1 core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. + +* +* @return TRUE if Locked else FALSE. +* +* @note None. +* +******************************************************************************/ +u8 XHdmiphy1_MmcmLocked(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir) +{ + u32 RegOffsetCtrl; + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XHDMIPHY1_DIR_TX) { + RegOffsetCtrl = XHDMIPHY1_MMCM_TXUSRCLK_CTRL_REG; + } + else { + RegOffsetCtrl = XHDMIPHY1_MMCM_RXUSRCLK_CTRL_REG; + } + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + RegOffsetCtrl) & XHDMIPHY1_MMCM_USRCLK_CTRL_LOCKED_MASK; + + return (RegVal ? TRUE : FALSE); + +} + +/*****************************************************************************/ +/** +* This function will set the CLKINSEL port of the MMCM +* +* @param InstancePtr is a pointer to the XHdmiphy1 core instance. +* @param QuadId is the GT quad ID to operate on. +* @param Dir is an indicator for TX or RX. +* @param Sel CLKINSEL value +* 0 - CLKIN1 +* 1 - CLKIN2 +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_MmcmSetClkinsel(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, XHdmiphy1_MmcmClkinsel Sel) +{ + u32 RegOffsetCtrl; + u32 RegVal; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (Dir == XHDMIPHY1_DIR_TX) { + RegOffsetCtrl = XHDMIPHY1_MMCM_TXUSRCLK_CTRL_REG; + } + else { + RegOffsetCtrl = XHDMIPHY1_MMCM_RXUSRCLK_CTRL_REG; + } + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegOffsetCtrl); + + if (Sel == XHDMIPHY1_MMCM_CLKINSEL_CLKIN2) { + RegVal &= ~XHDMIPHY1_MMCM_USRCLK_CTRL_CLKINSEL_MASK; + } + else { + RegVal |= XHDMIPHY1_MMCM_USRCLK_CTRL_CLKINSEL_MASK; + } + + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, + RegOffsetCtrl, RegVal); + +} + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) +/*****************************************************************************/ +/** +* This function obtains the divider value of the BUFG_GT peripheral. +* +* @param InstancePtr is a pointer to the XHdmiphy1 core instance. +* @param Dir is an indicator for TX or RX +* @param Div 3-bit divider value +* +* @return None. +* +******************************************************************************/ +void XHdmiphy1_SetBufgGtDiv(XHdmiphy1 *InstancePtr, + XHdmiphy1_DirectionType Dir, u8 Div) +{ + u32 RegVal; + u32 RegOffset; + u8 Divider = Div; + + if (Divider == 0) { + Divider = 1; + } + else { + Divider = Divider - 1; + } + + + if (Dir == XHDMIPHY1_DIR_TX) { + RegOffset = XHDMIPHY1_BUFGGT_TXUSRCLK_REG; + } + else { + RegOffset = XHDMIPHY1_BUFGGT_RXUSRCLK_REG; + } + + /* Read BUFG_GT register. */ + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, RegOffset); + RegVal &= ~XHDMIPHY1_BUFGGT_XXUSRCLK_DIV_MASK; + + /* Shift divider value to correct position. */ + Divider <<= XHDMIPHY1_BUFGGT_XXUSRCLK_DIV_SHIFT; + Divider &= XHDMIPHY1_BUFGGT_XXUSRCLK_DIV_MASK; + RegVal |= Divider; + + /* Write new value to BUFG_GT ctrl register. */ + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, RegOffset, RegVal); +} + +/*****************************************************************************/ +/** +* This function will power down the specified GT PLL. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_PowerDownGtPll(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, u8 Hold) +{ + u32 MaskVal = 0; + u32 RegVal; + u8 Id, Id0, Id1; + + /* Suppress Warning Messages */ + QuadId = QuadId; + + if (XHDMIPHY1_ISCH(ChId)) { + XHdmiphy1_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + } + else { + /* When powering down a QPLL, power down for all channels. */ + XHdmiphy1_Ch2Ids(InstancePtr, + XHDMIPHY1_CHANNEL_ID_CHA, &Id0, &Id1); + } + for (Id = Id0; Id <= Id1; Id++) { + if (ChId == XHDMIPHY1_CHANNEL_ID_CMN0) { + MaskVal |= XHDMIPHY1_POWERDOWN_CONTROL_QPLL0PD_MASK(Id); + } + else if (ChId == XHDMIPHY1_CHANNEL_ID_CMN1) { + MaskVal |= XHDMIPHY1_POWERDOWN_CONTROL_QPLL1PD_MASK(Id); + } + else if (ChId == XHDMIPHY1_CHANNEL_ID_CMNA) { + MaskVal |= XHDMIPHY1_POWERDOWN_CONTROL_QPLL0PD_MASK(Id) | + XHDMIPHY1_POWERDOWN_CONTROL_QPLL1PD_MASK(Id); + } + else { + MaskVal |= XHDMIPHY1_POWERDOWN_CONTROL_CPLLPD_MASK(Id); + } + } + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_POWERDOWN_CONTROL_REG); + RegVal |= MaskVal; + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_POWERDOWN_CONTROL_REG, RegVal); + + if (!Hold) { + RegVal &= ~MaskVal; + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_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 XHdmiphy1_PllCalculator. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_ClkCalcParams(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, + u32 PllClkInFreqHz) +{ + u32 Status = XST_SUCCESS; + u8 Id, Id0, Id1; + + XHdmiphy1_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + Status = XHdmiphy1_PllCalculator(InstancePtr, QuadId, + (XHdmiphy1_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 XHdmiphy1 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 XHdmiphy1_OutDivReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir) +{ + u32 Status; + u8 Id; + u8 Id0; + u8 Id1; + + if (!XHDMIPHY1_ISCH(ChId)) { + ChId = XHDMIPHY1_CHANNEL_ID_CHA; + } + + XHdmiphy1_LogWrite(InstancePtr, (Dir == XHDMIPHY1_DIR_TX) ? + XHDMIPHY1_LOG_EVT_GT_TX_RECONFIG : XHDMIPHY1_LOG_EVT_GT_RX_RECONFIG, 0); + + XHdmiphy1_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + Status = XHdmiphy1_OutDivChReconfig(InstancePtr, QuadId, + (XHdmiphy1_ChannelId)Id, Dir); + if (Status != XST_SUCCESS) { + break; + } + } + + 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 XHdmiphy1 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 XHdmiphy1_ClkReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId) +{ + u32 Status = XST_SUCCESS; + u8 Id; + u8 Id0; + u8 Id1; + + XHdmiphy1_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + if (XHDMIPHY1_ISCH(Id)) { + Status |= XHdmiphy1_ClkChReconfig(InstancePtr, QuadId, + (XHdmiphy1_ChannelId)Id); + } + else if (XHDMIPHY1_ISCMN(ChId)) { + if (((XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_TX)) || + (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_RX))) && + (InstancePtr->HdmiIsQpllPresent == FALSE)) { + XHdmiphy1_LogWrite(InstancePtr, XHDMIPHY1_LOG_EVT_NO_QPLL_ERR, + 1); + XHdmiphy1_ErrorHandler(InstancePtr); + Status = XST_FAILURE; + return Status; + } + Status |= XHdmiphy1_ClkCmnReconfig(InstancePtr, QuadId, + (XHdmiphy1_ChannelId)Id); + } + if (Status != XST_SUCCESS) { + Status = XST_FAILURE; + return Status; + } + } + + if (XHDMIPHY1_ISCH(ChId)) { + XHdmiphy1_LogWrite(InstancePtr, + XHDMIPHY1_LOG_EVT_CPLL_RECONFIG, 1); + } + else if (XHDMIPHY1_ISCMN(ChId)) { + XHdmiphy1_LogWrite(InstancePtr, + XHDMIPHY1_LOG_EVT_QPLL_RECONFIG, 1); + } + + return Status; +} + +/*****************************************************************************/ +/** +* This function will translate from XHdmiphy1_PllType to +* XHdmiphy1_SysClkDataSelType. +* +* @param InstancePtr is a pointer to the XHdmiphy1 core instance. +* +* @return The reference clock type based on the PLL selection. +* +* @note None. +* +******************************************************************************/ +XHdmiphy1_SysClkDataSelType Pll2SysClkData(XHdmiphy1_PllType PllSelect) +{ + return (PllSelect == XHDMIPHY1_PLL_TYPE_CPLL) ? + XHDMIPHY1_SYSCLKSELDATA_TYPE_CPLL_OUTCLK : + (PllSelect == XHDMIPHY1_PLL_TYPE_QPLL) ? + XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL_OUTCLK : + (PllSelect == XHDMIPHY1_PLL_TYPE_QPLL0) ? + XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL0_OUTCLK : + /*(PllSelect == XHDMIPHY1_PLL_TYPE_QPLL1) ?*/ + XHDMIPHY1_SYSCLKSELDATA_TYPE_QPLL1_OUTCLK; +} + +/*****************************************************************************/ +/** +* This function will translate from XHdmiphy1_PllType to +* XHdmiphy1_SysClkOutSelType. +* +* @param InstancePtr is a pointer to the XHdmiphy1 core instance. +* +* @return The reference clock type based on the PLL selection. +* +* @note None. +* +******************************************************************************/ +XHdmiphy1_SysClkOutSelType Pll2SysClkOut(XHdmiphy1_PllType PllSelect) +{ + return (PllSelect == XHDMIPHY1_PLL_TYPE_CPLL) ? + XHDMIPHY1_SYSCLKSELOUT_TYPE_CPLL_REFCLK : + (PllSelect == XHDMIPHY1_PLL_TYPE_QPLL) ? + XHDMIPHY1_SYSCLKSELOUT_TYPE_QPLL_REFCLK : + (PllSelect == XHDMIPHY1_PLL_TYPE_QPLL0) ? + XHDMIPHY1_SYSCLKSELOUT_TYPE_QPLL0_REFCLK : + /*(PllSelect == XHDMIPHY1_PLL_TYPE_QPLL1) ?*/ + XHDMIPHY1_SYSCLKSELOUT_TYPE_QPLL1_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 XHdmiphy1 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 XHdmiphy1_PllCalculator(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, + u32 PllClkInFreqHz) +{ + u32 Status; + u64 PllClkOutFreqHz; + u64 CalcLineRateFreqHz; + u8 Id, Id0, Id1; + u64 PllClkInFreqHzIn = PllClkInFreqHz; + XHdmiphy1_Channel *PllPtr = &InstancePtr->Quads[QuadId]. + Plls[XHDMIPHY1_CH2IDX(ChId)]; + + if (!PllClkInFreqHzIn) { + PllClkInFreqHzIn = XHdmiphy1_GetQuadRefClkFreq(InstancePtr, + QuadId, + PllPtr->PllRefClkSel); + } + + /* Select PLL value table offsets. */ + const XHdmiphy1_GtPllDivs *GtPllDivs; + if (XHDMIPHY1_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 = XHdmiphy1_CheckPllOpRange(InstancePtr, QuadId, ChId, + PllClkOutFreqHz); + if (Status != XST_SUCCESS) { + continue; + } + + if ((XHDMIPHY1_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 (XHDMIPHY1_ISCMN(ChId)) { + /* Same divisor value for all channels if using a QPLL. */ + ChId = XHDMIPHY1_CHANNEL_ID_CHA; + } + + XHdmiphy1_Ch2Ids(InstancePtr, ChId, &Id0, &Id1); + for (Id = Id0; Id <= Id1; Id++) { + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(Id)].OutDiv[Dir] = + *D; + if (Dir == XHDMIPHY1_DIR_RX) { + XHdmiphy1_CfgSetCdr(InstancePtr,\ + QuadId, (XHdmiphy1_ChannelId)Id); + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function calculates the PLL VCO operating frequency. +* +* @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_GetPllVcoFreqHz(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir) +{ + u64 PllxVcoRateHz; + u64 PllRefClkHz; + XHdmiphy1_Channel *PllPtr = &InstancePtr->Quads[QuadId]. + Plls[XHDMIPHY1_CH2IDX(ChId)]; + + if (Dir == XHDMIPHY1_DIR_TX) { + if (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_TX)) { + PllRefClkHz = InstancePtr->HdmiTxRefClkHz; + } + else { + PllRefClkHz = XHdmiphy1_GetQuadRefClkFreq(InstancePtr, + QuadId, + PllPtr->PllRefClkSel); + } + } + else { + if (XHdmiphy1_IsHDMI(InstancePtr, XHDMIPHY1_DIR_RX)) { + if (InstancePtr->HdmiRxDruIsEnabled) { + PllRefClkHz = + XHdmiphy1_DruGetRefClkFreqHz(InstancePtr); + } + else { + PllRefClkHz = InstancePtr->HdmiRxRefClkHz; + } + } + else { + PllRefClkHz = XHdmiphy1_GetQuadRefClkFreq(InstancePtr, + QuadId, + PllPtr->PllRefClkSel); + } + } + + PllxVcoRateHz = (u64)(PllRefClkHz * + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(ChId)]. + PllParams.N1FbDiv * + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(ChId)]. + PllParams.N2FbDiv) / + InstancePtr->Quads[QuadId].Plls[XHDMIPHY1_CH2IDX(ChId)]. + PllParams.MRefClkDiv; + + return PllxVcoRateHz; +} + +/*****************************************************************************/ +/** +* This function returns the number of active reference clock sources +* based in the CFG +* +* @param InstancePtr is a pointer to the XHdmiphy1 core instance. +* +* @return No of active REFCLK sources +* +* @note None. +* +******************************************************************************/ +u8 XHdmiphy1_GetRefClkSourcesCount(XHdmiphy1 *InstancePtr) +{ + u8 RefClkNum = 0; + u8 RefClkNumMax = 5; + XHdmiphy1_PllRefClkSelType RefClkSel[RefClkNumMax]; + XHdmiphy1_PllRefClkSelType RefClkSelTemp[RefClkNumMax]; + u8 i, j, Match; + + /* TxRefClkSel */ + RefClkSel[0] = (InstancePtr->Config.TxProtocol != + XHDMIPHY1_PROTOCOL_NONE) ? + InstancePtr->Config.TxRefClkSel : 99; + /* RxRefClkSel */ + RefClkSel[1] = (InstancePtr->Config.RxProtocol != + XHDMIPHY1_PROTOCOL_NONE) ? + InstancePtr->Config.RxRefClkSel : 99; + /* DruRefClkSel */ + RefClkSel[2] = (InstancePtr->Config.DruIsPresent) ? + InstancePtr->Config.DruRefClkSel : 99; + /* TxFrlRefClkSel */ + RefClkSel[3] = (InstancePtr->Config.TxProtocol == + XHDMIPHY1_PROTOCOL_HDMI21) ? + InstancePtr->Config.TxFrlRefClkSel : 99; + /* RxFrlRefClkSel */ + RefClkSel[4] = (InstancePtr->Config.RxProtocol == + XHDMIPHY1_PROTOCOL_HDMI21) ? + InstancePtr->Config.RxFrlRefClkSel : 99; + + /* Initialize Unique RefClk holder */ + for (i=0; iGtAdaptor->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 XHdmiphy1 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 XHdmiphy1_CheckPllOpRange(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_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 XHdmiphy1 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 XHdmiphy1_OutDivChReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_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 XHdmiphy1 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 XHdmiphy1_ClkChReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_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 XHdmiphy1 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 XHdmiphy1_ClkCmnReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_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 XHdmiphy1 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 XHdmiphy1_RxChReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_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 XHdmiphy1 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 XHdmiphy1_TxChReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId) +{ + return InstancePtr->GtAdaptor->TxChReconfig(InstancePtr, QuadId, ChId); +} +#endif + +/*****************************************************************************/ +/** +* This function checks if Instance is HDMI 2.0 or HDMI 2.1 +* +* @param InstancePtr is a pointer to the HDMIPHY instance. +* @param Dir is an indicator for RX or TX. +* +* @return TRUE if HDMI 2.0 or 2.1 else FALSE. +* +* @note None. +* +******************************************************************************/ +u8 XHdmiphy1_IsHDMI(XHdmiphy1 *InstancePtr, XHdmiphy1_DirectionType Dir) +{ + if (Dir == XHDMIPHY1_DIR_TX) { + if ((InstancePtr->Config.TxProtocol == XHDMIPHY1_PROTOCOL_HDMI) || + (InstancePtr->Config.TxProtocol == XHDMIPHY1_PROTOCOL_HDMI21)) { + return TRUE; + } + } else { /* Dir == XHDMIPHY1_DIR_RX */ + if ((InstancePtr->Config.RxProtocol == XHDMIPHY1_PROTOCOL_HDMI) || + (InstancePtr->Config.RxProtocol == XHDMIPHY1_PROTOCOL_HDMI21)) { + return TRUE; + } + } + + return FALSE; +} + +/*****************************************************************************/ +/** +* This function is the error condition handler +* +* @param InstancePtr is a pointer to the HDMIPHY instance. +* @param ErrIrqType is the error type +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_ErrorHandler(XHdmiphy1 *InstancePtr) +{ + if (InstancePtr->ErrorCallback != NULL) { + InstancePtr->ErrorCallback(InstancePtr->ErrorRef); + } +} diff --git a/hdmi/phy-xilinx-vphy/xhdmiphy1_i.h b/hdmi/phy-xilinx-vphy/xhdmiphy1_i.h new file mode 100644 index 0000000..103490a --- /dev/null +++ b/hdmi/phy-xilinx-vphy/xhdmiphy1_i.h @@ -0,0 +1,171 @@ +/******************************************************************************* + * + * + * 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 xhdmiphy1_i.h + * + * Contains generic APIs that are locally called or used within the + * HDMIPHY driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ *            dd/mm/yy
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   gm   10/12/18 Initial release.
+ * 
+ * + * @addtogroup xhdmiphy1_v1_0 + * @{ +*******************************************************************************/ + +#ifndef XHDMIPHY1_I_H_ +/* Prevent circular inclusions by using protection macros. */ +#define XHDMIPHY1_I_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/******************************* Include Files ********************************/ + +#include "xil_assert.h" +#include "xhdmiphy1.h" +#include "xhdmiphy1_hw.h" +#include "xvidc.h" + +/****************************** Type Definitions ******************************/ + + +/**************************** Function Prototypes *****************************/ + + +void XHdmiphy1_Ch2Ids(XHdmiphy1 *InstancePtr, XHdmiphy1_ChannelId ChId, + u8 *Id0, u8 *Id1); +u32 XHdmiphy1_DirReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir); +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) +XHdmiphy1_SysClkDataSelType Pll2SysClkData(XHdmiphy1_PllType PllSelect); +XHdmiphy1_SysClkOutSelType Pll2SysClkOut(XHdmiphy1_PllType PllSelect); +u32 XHdmiphy1_PllCalculator(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, + u32 PllClkInFreqHz); + +/* xhdmiphy1.c: Channel configuration functions - setters. */ +u32 XHdmiphy1_WriteCfgRefClkSelReg(XHdmiphy1 *InstancePtr, u8 QuadId); +void XHdmiphy1_CfgPllRefClkSel(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_PllRefClkSelType RefClkSel); +void XHdmiphy1_CfgSysClkDataSel(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, XHdmiphy1_SysClkDataSelType SysClkDataSel); +void XHdmiphy1_CfgSysClkOutSel(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, XHdmiphy1_SysClkOutSelType SysClkOutSel); + +u32 XHdmiphy1_ClkCalcParams(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, + u32 PllClkInFreqHz); +u32 XHdmiphy1_OutDivReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir); +u32 XHdmiphy1_ClkReconfig(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId); +#endif + +/* xhdmiphy1.c: Channel configuration functions - getters. */ +XHdmiphy1_ChannelId XHdmiphy1_GetRcfgChId(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, XHdmiphy1_PllType PllType); +u32 XHdmiphy1_IsPllLocked(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId); +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) +u32 XHdmiphy1_GetQuadRefClkFreq(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_PllRefClkSelType RefClkType); +XHdmiphy1_SysClkDataSelType XHdmiphy1_GetSysClkDataSel(XHdmiphy1 *InstancePtr, + u8 QuadId, XHdmiphy1_DirectionType Dir, XHdmiphy1_ChannelId ChId); +XHdmiphy1_SysClkOutSelType XHdmiphy1_GetSysClkOutSel(XHdmiphy1 *InstancePtr, + u8 QuadId, XHdmiphy1_DirectionType Dir, XHdmiphy1_ChannelId ChId); +u32 XHdmiphy1_GtUserRdyEnable(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, u8 Hold); +u32 XHdmiphy1_CfgCpllCalPeriodandTol(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, + u32 FreeRunClkFreq); +#else +void XHdmiphy1_SetGtLineRateCfg(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir); +u16 XHdmiphy1_GetGtLineRateCfg(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir); +void XHdmiphy1_SetGpi(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, u8 Set); +u8 XHdmiphy1_GetGpo(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir); +void XHdmiphy1_GtMstReset(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir, u8 Reset); +u8 XHdmiphy1_CheckLineRateCfg(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir); +#endif + +/* xhdmiphy1.c: GT/MMCM DRP access. */ +u32 XHdmiphy1_MmcmWriteParameters(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir); +void XHdmiphy1_MmcmReset(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, u8 Hold); +void XHdmiphy1_MmcmLockedMaskEnable(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, u8 Enable); +u8 XHdmiphy1_MmcmLocked(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir); +void XHdmiphy1_MmcmSetClkinsel(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir, XHdmiphy1_MmcmClkinsel Sel); +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) +void XHdmiphy1_SetBufgGtDiv(XHdmiphy1 *InstancePtr, + XHdmiphy1_DirectionType Dir, u8 Div); +/* xhdmiphy1.c Miscellaneous control. */ +u32 XHdmiphy1_PowerDownGtPll(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, u8 Hold); +#endif + +/* xhdmiphy1_intr.c: Interrupt handling functions. */ +void XHdmiphy1_SetIntrHandler(XHdmiphy1 *InstancePtr, + XHdmiphy1_IntrHandlerType HandlerType, + XHdmiphy1_IntrHandler CallbackFunc, void *CallbackRef); +void XHdmiphy1_IntrEnable(XHdmiphy1 *InstancePtr, + XHdmiphy1_IntrHandlerType Intr); +void XHdmiphy1_IntrDisable(XHdmiphy1 *InstancePtr, + XHdmiphy1_IntrHandlerType Intr); + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) +u64 XHdmiphy1_GetPllVcoFreqHz(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_ChannelId ChId, XHdmiphy1_DirectionType Dir); +u8 XHdmiphy1_GetRefClkSourcesCount(XHdmiphy1 *InstancePtr); +#endif + +u8 XHdmiphy1_IsHDMI(XHdmiphy1 *InstancePtr, XHdmiphy1_DirectionType Dir); +void XHdmiphy1_HdmiTxTimerTimeoutHandler(XHdmiphy1 *InstancePtr); +void XHdmiphy1_HdmiRxTimerTimeoutHandler(XHdmiphy1 *InstancePtr); + +void XHdmiphy1_ErrorHandler(XHdmiphy1 *InstancePtr); + +/******************* Macros (Inline Functions) Definitions ********************/ + +#ifdef __cplusplus +} +#endif + +#endif /* XHDMIPHY1_I_H_ */ +/** @} */ diff --git a/hdmi/phy-xilinx-vphy/xhdmiphy1_intr.c b/hdmi/phy-xilinx-vphy/xhdmiphy1_intr.c new file mode 100644 index 0000000..8e10289 --- /dev/null +++ b/hdmi/phy-xilinx-vphy/xhdmiphy1_intr.c @@ -0,0 +1,312 @@ +/******************************************************************************* + * + * + * 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 xhdmiphy1_intr.c + * + * This file contains functions related to XHdmiphy1 interrupt handling. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ *            dd/mm/yy
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   gm   10/12/18 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xhdmiphy1.h" +#include "xhdmiphy1_i.h" + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function enables interrupts associated with the specified interrupt type + * + * @param InstancePtr is a pointer to the XHdmiphy1 instance. + * @param Intr is the interrupt type/mask to enable. + * + * @return None. + * + * @note None. +* +*******************************************************************************/ +void XHdmiphy1_IntrEnable(XHdmiphy1 *InstancePtr, + XHdmiphy1_IntrHandlerType Intr) +{ + u32 RegVal; + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_INTR_EN_REG); + RegVal |= Intr; + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_INTR_EN_REG, + RegVal); +} + +/******************************************************************************/ +/** + * This function disabled interrupts associated with the specified interrupt + * type. + * + * @param InstancePtr is a pointer to the XHdmiphy1 instance. + * @param Intr is the interrupt type/mask to disable. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XHdmiphy1_IntrDisable(XHdmiphy1 *InstancePtr, + XHdmiphy1_IntrHandlerType Intr) +{ + u32 RegVal; + + RegVal = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_INTR_DIS_REG); + RegVal |= Intr; + XHdmiphy1_WriteReg(InstancePtr->Config.BaseAddr, XHDMIPHY1_INTR_DIS_REG, + RegVal); +} + +/******************************************************************************/ +/** + * This function installs a callback function for the specified handler type. + * + * @param InstancePtr is a pointer to the XHdmiphy1 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 XHdmiphy1_SetIntrHandler(XHdmiphy1 *InstancePtr, + XHdmiphy1_IntrHandlerType HandlerType, + XHdmiphy1_IntrHandler CallbackFunc, void *CallbackRef) +{ + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid((HandlerType == XHDMIPHY1_INTR_HANDLER_TYPE_TXRESET_DONE) || + (HandlerType == XHDMIPHY1_INTR_HANDLER_TYPE_RXRESET_DONE) || +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + (HandlerType == XHDMIPHY1_INTR_HANDLER_TYPE_CPLL_LOCK) || + (HandlerType == XHDMIPHY1_INTR_HANDLER_TYPE_QPLL_LOCK) || + (HandlerType == XHDMIPHY1_INTR_HANDLER_TYPE_TXALIGN_DONE) || + (HandlerType == XHDMIPHY1_INTR_HANDLER_TYPE_QPLL1_LOCK) || +#else + (HandlerType == XHDMIPHY1_INTR_HANDLER_TYPE_LCPLL_LOCK) || + (HandlerType == XHDMIPHY1_INTR_HANDLER_TYPE_RPLL_LOCK) || + (HandlerType == XHDMIPHY1_INTR_HANDLER_TYPE_TX_GPO_RISING_EDGE) || + (HandlerType == XHDMIPHY1_INTR_HANDLER_TYPE_RX_GPO_RISING_EDGE) || +#endif + (HandlerType == + XHDMIPHY1_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE) || + (HandlerType == + XHDMIPHY1_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE) || + (HandlerType == XHDMIPHY1_INTR_HANDLER_TYPE_TX_MMCM_LOCK_CHANGE) || + (HandlerType == XHDMIPHY1_INTR_HANDLER_TYPE_RX_MMCM_LOCK_CHANGE) || + (HandlerType == XHDMIPHY1_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT) || + (HandlerType == XHDMIPHY1_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT)); + Xil_AssertVoid(CallbackFunc != NULL); + Xil_AssertVoid(CallbackRef != NULL); + + switch (HandlerType) { + case XHDMIPHY1_INTR_HANDLER_TYPE_TXRESET_DONE: + InstancePtr->IntrTxResetDoneHandler = CallbackFunc; + InstancePtr->IntrTxResetDoneCallbackRef = CallbackRef; + break; + case XHDMIPHY1_INTR_HANDLER_TYPE_RXRESET_DONE: + InstancePtr->IntrRxResetDoneHandler = CallbackFunc; + InstancePtr->IntrRxResetDoneCallbackRef = CallbackRef; + break; +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + case XHDMIPHY1_INTR_HANDLER_TYPE_CPLL_LOCK: + InstancePtr->IntrCpllLockHandler = CallbackFunc; + InstancePtr->IntrCpllLockCallbackRef = CallbackRef; + break; + case XHDMIPHY1_INTR_HANDLER_TYPE_QPLL_LOCK: + InstancePtr->IntrQpllLockHandler = CallbackFunc; + InstancePtr->IntrQpllLockCallbackRef = CallbackRef; + break; + case XHDMIPHY1_INTR_HANDLER_TYPE_TXALIGN_DONE: + InstancePtr->IntrTxAlignDoneHandler = CallbackFunc; + InstancePtr->IntrTxAlignDoneCallbackRef = CallbackRef; + break; + case XHDMIPHY1_INTR_HANDLER_TYPE_QPLL1_LOCK: + InstancePtr->IntrQpll1LockHandler = CallbackFunc; + InstancePtr->IntrQpll1LockCallbackRef = CallbackRef; + break; +#else + case XHDMIPHY1_INTR_HANDLER_TYPE_TX_GPO_RISING_EDGE: + InstancePtr->IntrTxGpoRisingEdgeHandler = CallbackFunc; + InstancePtr->IntrTxGpoRisingEdgeCallbackRef = CallbackRef; + break; + case XHDMIPHY1_INTR_HANDLER_TYPE_RX_GPO_RISING_EDGE: + InstancePtr->IntrRxGpoRisingEdgeHandler = CallbackFunc; + InstancePtr->IntrRxGpoRisingEdgeCallbackRef = CallbackRef; + break; + case XHDMIPHY1_INTR_HANDLER_TYPE_LCPLL_LOCK: + InstancePtr->IntrLcpllLockHandler = CallbackFunc; + InstancePtr->IntrLcpllLockCallbackRef = CallbackRef; + break; + case XHDMIPHY1_INTR_HANDLER_TYPE_RPLL_LOCK: + InstancePtr->IntrRpllLockHandler = CallbackFunc; + InstancePtr->IntrRpllLockCallbackRef = CallbackRef; + break; +#endif + case XHDMIPHY1_INTR_HANDLER_TYPE_TX_CLKDET_FREQ_CHANGE: + InstancePtr->IntrTxClkDetFreqChangeHandler = + CallbackFunc; + InstancePtr->IntrTxClkDetFreqChangeCallbackRef = + CallbackRef; + break; + case XHDMIPHY1_INTR_HANDLER_TYPE_RX_CLKDET_FREQ_CHANGE: + InstancePtr->IntrRxClkDetFreqChangeHandler = + CallbackFunc; + InstancePtr->IntrRxClkDetFreqChangeCallbackRef = + CallbackRef; + break; + case XHDMIPHY1_INTR_HANDLER_TYPE_TX_MMCM_LOCK_CHANGE: + InstancePtr->IntrTxMmcmLockHandler = CallbackFunc; + InstancePtr->IntrTxMmcmLockCallbackRef = CallbackRef; + break; + case XHDMIPHY1_INTR_HANDLER_TYPE_RX_MMCM_LOCK_CHANGE: + InstancePtr->IntrRxMmcmLockHandler = CallbackFunc; + InstancePtr->IntrRxMmcmLockCallbackRef = CallbackRef; + break; + case XHDMIPHY1_INTR_HANDLER_TYPE_TX_TMR_TIMEOUT: + InstancePtr->IntrTxTmrTimeoutHandler = CallbackFunc; + InstancePtr->IntrTxTmrTimeoutCallbackRef = CallbackRef; + break; + case XHDMIPHY1_INTR_HANDLER_TYPE_RX_TMR_TIMEOUT: + InstancePtr->IntrRxTmrTimeoutHandler = CallbackFunc; + InstancePtr->IntrRxTmrTimeoutCallbackRef = CallbackRef; + break; + default: + break; + } +} + +/******************************************************************************/ +/** + * This function is the interrupt handler for the XHdmiphy1 driver. It will + * detect what kind of interrupt has happened, and will invoke the appropriate + * callback function. + * + * @param InstancePtr is a pointer to the XHdmiphy1 instance. + * + * @return None. + * + * @note None. + * +*******************************************************************************/ +void XHdmiphy1_InterruptHandler(XHdmiphy1 *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 = XHdmiphy1_ReadReg(InstancePtr->Config.BaseAddr, + XHDMIPHY1_INTR_STS_REG); + +#if (XPAR_HDMIPHY1_0_TRANSCEIVER != XHDMIPHY1_GTYE5) + if (IntrStatus & XHDMIPHY1_INTR_CPLL_LOCK_MASK) { + InstancePtr->IntrCpllLockHandler( + InstancePtr->IntrCpllLockCallbackRef); + } + if (IntrStatus & XHDMIPHY1_INTR_QPLL_LOCK_MASK) { + InstancePtr->IntrQpllLockHandler( + InstancePtr->IntrQpllLockCallbackRef); + } + if (IntrStatus & XHDMIPHY1_INTR_QPLL1_LOCK_MASK) { + InstancePtr->IntrQpll1LockHandler( + InstancePtr->IntrQpll1LockCallbackRef); + } + if (IntrStatus & XHDMIPHY1_INTR_TXRESETDONE_MASK) { + InstancePtr->IntrTxResetDoneHandler( + InstancePtr->IntrTxResetDoneCallbackRef); + } + if (IntrStatus & XHDMIPHY1_INTR_TXALIGNDONE_MASK) { + InstancePtr->IntrTxAlignDoneHandler( + InstancePtr->IntrTxAlignDoneCallbackRef); + } +#else + if (IntrStatus & XHDMIPHY1_INTR_TXGPO_RE_MASK) { + InstancePtr->IntrTxGpoRisingEdgeHandler( + InstancePtr->IntrTxGpoRisingEdgeCallbackRef); + } + if (IntrStatus & XHDMIPHY1_INTR_RXGPO_RE_MASK) { + InstancePtr->IntrRxGpoRisingEdgeHandler( + InstancePtr->IntrRxGpoRisingEdgeCallbackRef); + } + if (IntrStatus & XHDMIPHY1_INTR_LCPLL_LOCK_MASK) { + InstancePtr->IntrLcpllLockHandler( + InstancePtr->IntrLcpllLockCallbackRef); + } + if (IntrStatus & XHDMIPHY1_INTR_RPLL_LOCK_MASK) { + InstancePtr->IntrRpllLockHandler( + InstancePtr->IntrRpllLockCallbackRef); + } + if (IntrStatus & XHDMIPHY1_INTR_TXRESETDONE_MASK) { + InstancePtr->IntrTxResetDoneHandler( + InstancePtr->IntrTxResetDoneCallbackRef); + } +#endif + if (IntrStatus & XHDMIPHY1_INTR_RXRESETDONE_MASK) { + InstancePtr->IntrRxResetDoneHandler( + InstancePtr->IntrRxResetDoneCallbackRef); + } + if (IntrStatus & XHDMIPHY1_INTR_TXCLKDETFREQCHANGE_MASK) { + InstancePtr->IntrTxClkDetFreqChangeHandler( + InstancePtr->IntrTxClkDetFreqChangeCallbackRef); + } + if (IntrStatus & XHDMIPHY1_INTR_RXCLKDETFREQCHANGE_MASK) { + InstancePtr->IntrRxClkDetFreqChangeHandler( + InstancePtr->IntrRxClkDetFreqChangeCallbackRef); + } + if (IntrStatus & XHDMIPHY1_INTR_TXMMCMUSRCLK_LOCK_MASK) { + InstancePtr->IntrTxMmcmLockHandler( + InstancePtr->IntrTxMmcmLockCallbackRef); + } + if (IntrStatus & XHDMIPHY1_INTR_RXMMCMUSRCLK_LOCK_MASK) { + InstancePtr->IntrRxMmcmLockHandler( + InstancePtr->IntrRxMmcmLockCallbackRef); + } + if (IntrStatus & XHDMIPHY1_INTR_TXTMRTIMEOUT_MASK) { + InstancePtr->IntrTxTmrTimeoutHandler( + InstancePtr->IntrTxTmrTimeoutCallbackRef); + } + if (IntrStatus & XHDMIPHY1_INTR_RXTMRTIMEOUT_MASK) { + InstancePtr->IntrRxTmrTimeoutHandler( + InstancePtr->IntrRxTmrTimeoutCallbackRef); + } +} diff --git a/hdmi/phy-xilinx-vphy/xhdmiphy1_log.c b/hdmi/phy-xilinx-vphy/xhdmiphy1_log.c new file mode 100644 index 0000000..1fa55bd --- /dev/null +++ b/hdmi/phy-xilinx-vphy/xhdmiphy1_log.c @@ -0,0 +1,608 @@ +/******************************************************************************* + * + * + * 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 xhdmiphy1.c + * + * Contains a minimal set of functions for the XHdmiphy1 driver that allow + * access to all of the Video PHY core's functionality. See xhdmiphy1.h for a + * detailed description of the driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ *            dd/mm/yy
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   gm   10/12/18 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xhdmiphy1.h" +#include "xhdmiphy1_i.h" + +/************************** Constant Definitions *****************************/ +#define ANSI_COLOR_RED "\x1b[31m" +#define ANSI_COLOR_GREEN "\x1b[32m" +#define ANSI_COLOR_YELLOW "\x1b[33m" +#define ANSI_COLOR_BLUE "\x1b[34m" +#define ANSI_COLOR_MAGENTA "\x1b[35m" +#define ANSI_COLOR_CYAN "\x1b[36m" +#define ANSI_COLOR_WHITE "\x1b[37m" +#define ANSI_COLOR_RESET "\x1b[0m" + + +/**************************** Function Prototypes *****************************/ + +/**************************** Function Definitions ****************************/ + +/*****************************************************************************/ +/** +* This function will reset the driver's logginc mechanism. +* +* @param InstancePtr is a pointer to the XHdmiphy1 core instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_LogReset(XHdmiphy1 *InstancePtr) +{ +#ifdef XV_HDMIPHY1_LOG_ENABLE + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + + InstancePtr->Log.HeadIndex = 0; + InstancePtr->Log.TailIndex = 0; +#endif +} + +#ifdef XV_HDMIPHY1_LOG_ENABLE +/*****************************************************************************/ +/** +* This function will insert an event in the driver's logginc mechanism. +* +* @param InstancePtr is a pointer to the XHdmiphy1 core instance. +* @param Evt is the event type to log. +* @param Data is the associated data for the event. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XHdmiphy1_LogWrite(XHdmiphy1 *InstancePtr, XHdmiphy1_LogEvent Evt, + u8 Data) +{ + u64 TimeUnit = 0; + + if (InstancePtr->LogWriteCallback) { + TimeUnit = InstancePtr->LogWriteCallback(InstancePtr->LogWriteRef); + } + /* Verify arguments. */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(Evt <= (XHDMIPHY1_LOG_EVT_DUMMY)); + Xil_AssertVoid(Data < 0xFF); + + /* Write data and event into log buffer */ + InstancePtr->Log.DataBuffer[InstancePtr->Log.HeadIndex] = + (Data << 8) | Evt; + InstancePtr->Log.TimeRecord[InstancePtr->Log.HeadIndex] = TimeUnit; + + /* Update head pointer if reached to end of the buffer */ + if (InstancePtr->Log.HeadIndex == + (u8)((sizeof(InstancePtr->Log.DataBuffer) / + sizeof(InstancePtr->Log.DataBuffer[0])) - 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) / + sizeof(InstancePtr->Log.DataBuffer[0])) - 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 XHdmiphy1 core instance. +* +* @return The log data. +* +* @note None. +* +******************************************************************************/ +u16 XHdmiphy1_LogRead(XHdmiphy1 *InstancePtr) +{ +#ifdef XV_HDMIPHY1_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) / + sizeof(InstancePtr->Log.DataBuffer[0])) - 1)) { + InstancePtr->Log.TailIndex = 0; + } + else { + InstancePtr->Log.TailIndex++; + } + } + + return Log; +#endif +} + +/*****************************************************************************/ +/** +* This function will print the entire log to the passed buffer. +* +* @param InstancePtr is a pointer to the XVphy core instance. +* @param buff Buffer to print to +* @param buff_size size off buff passed +* +* @return number of bytes written to buff. +* +* @note None. +* +******************************************************************************/ +int XHdmiphy1_LogShow(XHdmiphy1 *InstancePtr, char *buff, int buff_size) +{ + int strSize = 0; +#ifdef XV_HDMIPHY1_LOG_ENABLE + u32 Log; + u8 Evt; + u8 Data; + u64 TimeUnit; + + /* Verify argument. */ + Xil_AssertVoid(InstancePtr != NULL); + + strSize = scnprintf(buff, buff_size, + "\r\n\n\nHDMIPHY log\r\n" \ + "------\r\n"); + + /* Read time record */ + TimeUnit = InstancePtr->Log.TimeRecord[InstancePtr->Log.TailIndex]; + + /* Read log data */ + Log = XHdmiphy1_LogRead(InstancePtr); + + while (Log != 0 && (buff_size - strSize) > 30 ) { + /* Event */ + Evt = Log & 0xff; + + /* Data */ + Data = (Log >> 8) & 0xFF; + + switch (Evt) { + case (XHDMIPHY1_LOG_EVT_NONE): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "GT log end\r\n-------\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_QPLL_EN): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "QPLL enable (%0d)\r\n", Data); + break; + case (XHDMIPHY1_LOG_EVT_QPLL_RST): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "QPLL reset (%0d)\r\n", Data); + break; + case (XHDMIPHY1_LOG_EVT_CPLL_EN): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "CPLL enable (%0d)\r\n", Data); + break; + case (XHDMIPHY1_LOG_EVT_CPLL_RST): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "CPLL reset (%0d)\r\n", Data); + break; + case (XHDMIPHY1_LOG_EVT_TXPLL_EN): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX MMCM enable (%0d)\r\n", Data); + break; + case (XHDMIPHY1_LOG_EVT_TXPLL_RST): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX MMCM reset (%0d)\r\n", Data); + break; + case (XHDMIPHY1_LOG_EVT_RXPLL_EN): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX MMCM enable (%0d)\r\n", Data); + break; + case (XHDMIPHY1_LOG_EVT_RXPLL_RST): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX MMCM reset (%0d)\r\n", Data); + break; + case (XHDMIPHY1_LOG_EVT_GTRX_RST): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "GT RX reset (%0d)\r\n", Data); + break; + case (XHDMIPHY1_LOG_EVT_GTTX_RST): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "GT TX reset (%0d)\r\n", Data); + break; + case (XHDMIPHY1_LOG_EVT_VID_TX_RST): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Video TX reset (%0d)\r\n", Data); + break; + case (XHDMIPHY1_LOG_EVT_VID_RX_RST): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Video RX reset (%0d)\r\n", Data); + break; + case (XHDMIPHY1_LOG_EVT_TX_ALIGN): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX alignment done\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX alignment start.\r\n."); + } + break; + case (XHDMIPHY1_LOG_EVT_TX_ALIGN_TMOUT): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX alignment watchdog timed out.\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_TX_TMR): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX timer event\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX timer load\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_RX_TMR): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX timer event\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX timer load\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_CPLL_RECONFIG): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "CPLL reconfig done\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "CPLL reconfig start\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_GT_RECONFIG): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "GT reconfig done\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "GT reconfig start\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_GT_TX_RECONFIG): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "GT TX reconfig done\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "GT TX reconfig start\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_GT_RX_RECONFIG): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "GT RX reconfig done\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "GT RX reconfig start\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_QPLL_RECONFIG): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "QPLL reconfig done\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "QPLL reconfig start\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_INIT): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "GT init done\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "GT init start\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_TXPLL_RECONFIG): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX MMCM reconfig done\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX MMCM reconfig start\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_RXPLL_RECONFIG): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX MMCM reconfig done\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX MMCM reconfig start\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_QPLL_LOCK): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "QPLL lock\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "QPLL lost lock\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_CPLL_LOCK): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "CPLL lock\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "CPLL lost lock\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_LCPLL_LOCK): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "LCPLL lock\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "LCPLL lost lock\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_RPLL_LOCK): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RPLL lock\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RPLL lost lock\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_RXPLL_LOCK): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX MMCM lock\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX MMCM lost lock\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_TXPLL_LOCK): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX MMCM lock\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX MMCM lost lock\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_TX_RST_DONE): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX reset done\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_RX_RST_DONE): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX reset done\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_TX_FREQ): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX frequency event\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_RX_FREQ): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX frequency event\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_DRU_EN): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX DRU enable\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX DRU disable\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_TXGPO_RE): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX GPO Rising Edge Detected\r\n"); + } else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX MSTRESET Toggled\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_RXGPO_RE): + if (Data == 1) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX GPO Rising Edge Detected\r\n"); + } else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX MSTRESET Toggled\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_FRL_RECONFIG): + if (Data == XHDMIPHY1_DIR_RX) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX FRL Reconfig\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX FRL Reconfig\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_TMDS_RECONFIG): + if (Data == XHDMIPHY1_DIR_RX) { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "RX TMDS Reconfig\r\n"); + } + else { + strSize += scnprintf(buff+strSize, buff_size-strSize, + "TX TMDS Reconfig\r\n"); + } + break; + case (XHDMIPHY1_LOG_EVT_1PPC_ERR): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Error! The HDMIPHY cannot support this video "); + strSize += scnprintf(buff+strSize, buff_size-strSize, + "format at PPC = 1\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_PPC_MSMTCH_ERR): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Error! HDMI TX SS PPC value, doesn't match with" + " HDMIPHY PPC value\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_VDCLK_HIGH_ERR): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Error! Video PHY cannot" + "support resolutions with video clock" + " > 148.5 MHz.\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_NO_DRU): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Warning: No DRU instance. "); + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Low resolution video isn't supported in this " + "design.\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_GT_QPLL_CFG_ERR): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Error! QPLL config not found!\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_GT_CPLL_CFG_ERR): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Error! CPLL config not found!\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_GT_LCPLL_CFG_ERR): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Error! LCPLL config not found!\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_GT_RPLL_CFG_ERR): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Error! RPLL config not found!\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_VD_NOT_SPRTD_ERR): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Error: This video format " + "is not supported by this device\r\n"); + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Change to another format\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_MMCM_ERR): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Error! MMCM config not found!\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_HDMI20_ERR): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Error! The Video PHY doesn't " + "support HDMI 2.0 line rates\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_NO_QPLL_ERR): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Error! There's no QPLL instance in the design\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_DRU_CLK_ERR): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Error: Wrong DRU REFCLK frequency detected\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_USRCLK_ERR): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Error! User Clock frequency is more than 300 MHz\r\n"); + break; + case (XHDMIPHY1_LOG_EVT_SPDGRDE_ERR): + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Error! %s: Line rates > 8.0 " + "Gbps are not supported by -1/-1LV devices" + ANSI_COLOR_RESET "\r\n", + (Data == XHDMIPHY1_DIR_RX) ? "RX" : "TX"); + break; + default: + strSize += scnprintf(buff+strSize, buff_size-strSize, + "Unknown event %i\r\n", Evt); + break; + } + + if((buff_size - strSize) > 30) { + /* Read log data */ + Log = XHdmiphy1_LogRead(InstancePtr); + } else { + Log = 0; + } + } +#else + strSize += scnprintf(buff+strSize, buff_size-strSize, + "\r\nINFO:: HDMIPHY Log Feature is Disabled \r\n"); +#endif + return strSize; +} diff --git a/hdmi/phy-xilinx-vphy/xhdmiphy1_mmcme5.c b/hdmi/phy-xilinx-vphy/xhdmiphy1_mmcme5.c new file mode 100644 index 0000000..f0f56d1 --- /dev/null +++ b/hdmi/phy-xilinx-vphy/xhdmiphy1_mmcme5.c @@ -0,0 +1,607 @@ +/******************************************************************************* + * + * + * Copyright (C) 2018 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 xhdmiphy1_mmcme5.c + * + * Contains a minimal set of functions for the XHdmiphy1 driver that allow + * access to all of the Video PHY core's functionality. See xhdmiphy1.h for a + * detailed description of the driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ *            dd/mm/yy
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   gm   10/12/18 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xstatus.h" +#include "xhdmiphy1.h" +#include "xhdmiphy1_i.h" +#if (XPAR_HDMIPHY1_0_TRANSCEIVER == XHDMIPHY1_GTYE5) + +/**************************** Function Prototypes *****************************/ +static u32 XHdmiphy1_Mmcme5DividerEncoding(XHdmiphy1_MmcmDivType DivType, + u16 Div); +static u32 XHdmiphy1_Mmcme5CpResEncoding(u16 Mult); +static u32 XHdmiphy1_Mmcme5LockReg1Reg2Encoding(u16 Mult); + +/************************** Constant Definitions ******************************/ + +/*****************************************************************************/ +/** +* This function returns the DRP encoding of ClkFbOutMult optimized for: +* Phase = 0; Dutycycle = 0.5; No Fractional division +* The calculations are based on XAPP888 +* +* @param Div is the divider to be encoded +* +* @return +* - Encoded Value for ClkReg1 [15: 0] +* - Encoded Value for ClkReg2 [31:16] +* +* @note None. +* +******************************************************************************/ +u32 XHdmiphy1_Mmcme5DividerEncoding(XHdmiphy1_MmcmDivType DivType, u16 Div) +{ + u32 DrpEnc; + u32 ClkReg1; + u32 ClkReg2; + u8 HiTime, LoTime; + u16 Divide = Div; + + if (DivType == XHDMIPHY1_MMCM_CLKOUT_DIVIDE) { + /* Div is an odd number */ + if (Div % 2) { + Divide = (Div / 2); + } + /* Div is an even number */ + else { + Divide = (Div / 2) + (Div % 2); + } + } + + HiTime = Divide / 2; + LoTime = HiTime; + + ClkReg2 = LoTime & 0xFF; + ClkReg2 |= (HiTime & 0xFF) << 8; + + if (DivType == XHDMIPHY1_MMCM_CLKFBOUT_MULT_F) { + ClkReg1 = (Divide % 2) ? 0x00001700 : 0x00001600; + } + else { + /* Div is an odd number */ + if (Div % 2) { + ClkReg1 = (Divide % 2) ? 0x0000BB00 : 0x0000BA00; + } + /* Div is an even number */ + else { + ClkReg1 = (Divide % 2) ? 0x00001B00 : 0x00001A00; + } + } + + DrpEnc = (ClkReg2 << 16) | ClkReg1; + + return DrpEnc; +} + +/*****************************************************************************/ +/** +* This function returns the DRP encoding of CP and Res optimized for: +* Phase = 0; Dutycycle = 0.5; BW = low; No Fractional division +* +* @param Mult is the divider to be encoded +* +* @return +* - [3:0] CP +* - [20:17] RES +* +* @note None. +* +******************************************************************************/ +u32 XHdmiphy1_Mmcme5CpResEncoding(u16 Mult) +{ + u32 DrpEnc; + u16 cp; + u16 res; + + switch (Mult) { + case 4: + cp = 5; res = 15; + break; + case 5: + cp = 6; res = 15; + break; + case 6: + cp = 7; res = 15; + break; + case 7: + cp = 13; res = 15; + break; + case 8: + cp = 14; res = 15; + break; + case 9: + cp = 15; res = 15; + break; + case 10: + cp = 14; res = 7; + break; + case 11: + cp = 15; res = 7; + break; + case 12 ... 13: + cp = 15; res = 11; + break; + case 14: + cp = 15; res = 13; + break; + case 15: + cp = 15; res = 3; + break; + case 16 ... 17: + cp = 14; res = 5; + break; + case 18 ... 19: + cp = 15; res = 5; + break; + case 20 ... 21: + cp = 15; res = 9; + break; + case 22 ... 23: + cp = 14; res = 14; + break; + case 24 ... 26: + cp = 15; res = 14; + break; + case 27 ... 28: + cp = 14; res = 1; + break; + case 29 ... 33: + cp = 15; res = 1; + break; + case 34 ... 37: + cp = 14; res = 6; + break; + case 38 ... 44: + cp = 15; res = 6; + break; + case 45 ... 57: + cp = 15; res = 10; + break; + case 58 ... 63: + cp = 13; res = 12; + break; + case 64 ... 70: + cp = 14; res = 12; + break; + case 71 ... 86: + cp = 15; res = 12; + break; + case 87 ... 93: + cp = 14; res = 2; + break; + case 94: + cp = 5; res = 15; + break; + case 95: + cp = 6; res = 15; + break; + case 96: + cp = 7; res = 15; + break; + case 97: + cp = 13; res = 15; + break; + case 98: + cp = 14; res = 15; + break; + case 99: + cp = 15; res = 15; + break; + case 100: + cp = 14; res = 7; + break; + case 101: + cp = 15; res = 7; + break; + case 102 ... 103: + cp = 15; res = 11; + break; + case 104: + cp = 15; res = 13; + break; + case 105: + cp = 15; res = 3; + break; + case 106 ... 107: + cp = 14; res = 5; + break; + case 108 ... 109: + cp = 15; res = 5; + break; + case 110 ... 111: + cp = 15; res = 9; + break; + case 112 ... 113: + cp = 14; res = 14; + break; + case 114 ... 116: + cp = 15; res = 14; + break; + case 117 ... 118: + cp = 14; res = 1; + break; + case 119 ... 123: + cp = 15; res = 1; + break; + case 124 ... 127: + cp = 14; res = 6; + break; + case 128 ... 134: + cp = 15; res = 6; + break; + case 135 ... 147: + cp = 15; res = 10; + break; + case 148 ... 153: + cp = 13; res = 12; + break; + case 154 ... 160: + cp = 14; res = 12; + break; + case 161 ... 176: + cp = 15; res = 12; + break; + case 177 ... 183: + cp = 14; res = 2; + break; + case 184 ... 200: + cp = 14; res = 4; + break; + case 201 ... 273: + cp = 15; res = 4; + break; + case 274 ... 300: + cp = 13; res = 8; + break; + case 301 ... 325: + cp = 14; res = 8; + break; + case 326 ... 432: + cp = 15; res = 8; + break; + default: + cp = 13; res = 8; + break; + } + + /* Construct the return value */ + DrpEnc = ((res & 0xf) << 17) | ((cp & 0xf) | 0x160); + + return DrpEnc; +} + +/*****************************************************************************/ +/** +* This function returns the DRP encoding of Lock Reg1 & Reg2 optimized for: +* Phase = 0; Dutycycle = 0.5; BW = low; No Fractional division +* +* @param Mult is the divider to be encoded +* +* @return +* - [15:0] Lock_1 Reg +* - [31:16] Lock_2 Reg +* +* @note None. +* +******************************************************************************/ +u32 XHdmiphy1_Mmcme5LockReg1Reg2Encoding(u16 Mult) +{ + u32 DrpEnc; + u16 Lock_1; + u16 Lock_2; + u16 lock_ref_dly; + u16 lock_fb_dly; + u16 lock_cnt; + u16 lock_sat_high = 9; + + switch (Mult) { + case 4: + lock_ref_dly = 4; + lock_fb_dly = 4; + lock_cnt = 1000; + break; + case 5: + lock_ref_dly = 6; + lock_fb_dly = 6; + lock_cnt = 1000; + break; + case 6 ... 7: + lock_ref_dly = 7; + lock_fb_dly = 7; + lock_cnt = 1000; + break; + case 8: + lock_ref_dly = 9; + lock_fb_dly = 9; + lock_cnt = 1000; + break; + case 9 ... 10: + lock_ref_dly = 10; + lock_fb_dly = 10; + lock_cnt = 1000; + break; + case 11: + lock_ref_dly = 11; + lock_fb_dly = 11; + lock_cnt = 1000; + break; + case 12: + lock_ref_dly = 13; + lock_fb_dly = 13; + lock_cnt = 1000; + break; + case 13 ... 14: + lock_ref_dly = 14; + lock_fb_dly = 14; + lock_cnt = 1000; + break; + case 15: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 900; + break; + case 16 ... 17: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 825; + break; + case 18: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 750; + break; + case 19 ... 20: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 700; + break; + case 21: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 650; + break; + case 22 ... 23: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 625; + break; + case 24: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 575; + break; + case 25: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 550; + break; + case 26 ... 28: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 525; + break; + case 29 ... 30: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 475; + break; + case 31: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 450; + break; + case 32 ... 33: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 425; + break; + case 34 ... 36: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 400; + break; + case 37: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 375; + break; + case 38 ... 40: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 350; + break; + case 41 ... 43: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 325; + break; + case 44 ... 47: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 300; + break; + case 48 ... 51: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 275; + break; + case 52 ... 205: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 950; + break; + case 206 ... 432: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 925; + break; + default: + lock_ref_dly = 16; + lock_fb_dly = 16; + lock_cnt = 250; + break; + } + + /* Construct Lock_1 Reg */ + Lock_1 = ((lock_fb_dly & 0x1F) << 10) | (lock_cnt & 0x3FF); + + /* Construct Lock_2 Reg */ + Lock_2 = ((lock_ref_dly & 0x1F) << 10) | (lock_sat_high & 0x3FF); + + /* Construct Return Value */ + DrpEnc = (Lock_2 << 16) | Lock_1; + + return DrpEnc; +} + +/*****************************************************************************/ +/** +* 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 XHdmiphy1 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. +* +******************************************************************************/ +u32 XHdmiphy1_MmcmWriteParameters(XHdmiphy1 *InstancePtr, u8 QuadId, + XHdmiphy1_DirectionType Dir) +{ + u8 ChId; + u32 DrpVal32; + u16 DrpRdVal; + XHdmiphy1_Mmcm *MmcmParams; + + ChId = (Dir == XHDMIPHY1_DIR_TX) ? + XHDMIPHY1_CHANNEL_ID_TXMMCM : + XHDMIPHY1_CHANNEL_ID_RXMMCM; + + MmcmParams = &InstancePtr->Quads[QuadId].Mmcm[Dir]; + + /* Check Parameters if has been Initialized */ + if (!MmcmParams->DivClkDivide && !MmcmParams->ClkFbOutMult && + !MmcmParams->ClkOut0Div && !MmcmParams->ClkOut1Div && + !MmcmParams->ClkOut2Div) { + return XST_FAILURE; + } + + /* Write CLKFBOUT_1 & CLKFBOUT_2 Values */ + DrpVal32 = XHdmiphy1_Mmcme5DividerEncoding(XHDMIPHY1_MMCM_CLKFBOUT_MULT_F, + MmcmParams->ClkFbOutMult); + XHdmiphy1_DrpWr(InstancePtr, QuadId, ChId, 0x0C, + (u16)(DrpVal32 & 0xFFFF)); + XHdmiphy1_DrpWr(InstancePtr, QuadId, ChId, 0x0D, + (u16)((DrpVal32 >> 16) & 0xFFFF)); + + /* Write DIVCLK_DIVIDE & DESKEW_2 Values */ + DrpVal32 = XHdmiphy1_Mmcme5DividerEncoding(XHDMIPHY1_MMCM_DIVCLK_DIVIDE, + MmcmParams->DivClkDivide) ; + XHdmiphy1_DrpWr(InstancePtr, QuadId, ChId, 0x21, + (u16)((DrpVal32 >> 16) & 0xFFFF)); + XHdmiphy1_DrpWr(InstancePtr, QuadId, ChId, 0x20, + ((MmcmParams->DivClkDivide == 0) ? 0x0000 : + ((MmcmParams->DivClkDivide % 2) ? + 0x0400 : 0x0000))); + + /* Write CLKOUT0_1 & CLKOUT0_2 Values */ + DrpVal32 = XHdmiphy1_Mmcme5DividerEncoding(XHDMIPHY1_MMCM_CLKOUT_DIVIDE, + MmcmParams->ClkOut0Div); + XHdmiphy1_DrpWr(InstancePtr, QuadId, ChId, 0x0E, + (u16)(DrpVal32 & 0xFFFF)); + XHdmiphy1_DrpWr(InstancePtr, QuadId, ChId, 0x0F, + (u16)((DrpVal32 >> 16) & 0xFFFF)); + + /* Write CLKOUT1_1 & CLKOUT1_2 Values */ + DrpVal32 = XHdmiphy1_Mmcme5DividerEncoding(XHDMIPHY1_MMCM_CLKOUT_DIVIDE, + MmcmParams->ClkOut1Div); + XHdmiphy1_DrpWr(InstancePtr, QuadId, ChId, 0x10, + (u16)(DrpVal32 & 0xFFFF)); + XHdmiphy1_DrpWr(InstancePtr, QuadId, ChId, 0x11, + (u16)((DrpVal32 >> 16) & 0xFFFF)); + + /* Write CLKOUT2_1 & CLKOUT2_2 Values */ + DrpVal32 = XHdmiphy1_Mmcme5DividerEncoding(XHDMIPHY1_MMCM_CLKOUT_DIVIDE, + MmcmParams->ClkOut2Div); + XHdmiphy1_DrpWr(InstancePtr, QuadId, ChId, 0x12, + (u16)(DrpVal32 & 0xFFFF)); + XHdmiphy1_DrpWr(InstancePtr, QuadId, ChId, 0x13, + (u16)((DrpVal32 >> 16) & 0xFFFF)); + + /* Write CP & RES Values */ + DrpVal32 = XHdmiphy1_Mmcme5CpResEncoding(MmcmParams->ClkFbOutMult); + /* CP */ + DrpRdVal = XHdmiphy1_DrpRd(InstancePtr, QuadId, ChId, 0x1E, &DrpRdVal); + DrpRdVal &= ~(0xF); + + XHdmiphy1_DrpWr(InstancePtr, QuadId, ChId, 0x1E, + (u16)((DrpVal32 & 0xF) | DrpRdVal)); + + /* RES */ + DrpRdVal = XHdmiphy1_DrpRd(InstancePtr, QuadId, ChId, 0x2A, &DrpRdVal); + DrpRdVal &= ~(0x1E); + XHdmiphy1_DrpWr(InstancePtr, QuadId, ChId, 0x2A, + (u16)(((DrpVal32 >> 15) & 0x1E) | DrpRdVal)); + + /* Write Lock Reg1 & Reg2 Values */ + DrpVal32 = XHdmiphy1_Mmcme5LockReg1Reg2Encoding(MmcmParams->ClkFbOutMult); + /* LOCK_1 */ + DrpRdVal = XHdmiphy1_DrpRd(InstancePtr, QuadId, ChId, 0x27, &DrpRdVal); + DrpRdVal &= ~(0x8000); + XHdmiphy1_DrpWr(InstancePtr, QuadId, ChId, 0x27, + (u16)((DrpVal32 & 0x7FFF) | DrpRdVal)); + + /* LOCK_2 */ + DrpRdVal = XHdmiphy1_DrpRd(InstancePtr, QuadId, ChId, 0x28, &DrpRdVal); + DrpRdVal &= ~(0x8000); + XHdmiphy1_DrpWr(InstancePtr, QuadId, ChId, 0x28, + (u16)(((DrpVal32 >> 16) & 0x7FFF) | DrpRdVal)); + + return XST_SUCCESS; +} + +#endif diff --git a/hdmi/phy-xilinx-vphy/xhdmiphy1_sinit.c b/hdmi/phy-xilinx-vphy/xhdmiphy1_sinit.c new file mode 100644 index 0000000..a6c53b6 --- /dev/null +++ b/hdmi/phy-xilinx-vphy/xhdmiphy1_sinit.c @@ -0,0 +1,83 @@ +/******************************************************************************* + * + * + * 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 xhdmiphy1_sinit.c + * + * This file contains static initialization methods for the XHdmiphy1 driver. + * + * @note None. + * + *
+ * MODIFICATION HISTORY:
+ *
+ * Ver   Who  Date     Changes
+ * ----- ---- -------- -----------------------------------------------
+ *            dd/mm/yy
+ * ----- ---- -------- -----------------------------------------------
+ * 1.0   gm   10/12/18 Initial release.
+ * 
+ * +*******************************************************************************/ + +/******************************* Include Files ********************************/ + +#include "xhdmiphy1.h" +#include "xhdmiphy1_i.h" + +/*************************** Variable Declarations ****************************/ + +#ifndef XPAR_XHDMIPHY1_NUM_INSTANCES +#define XPAR_XHDMIPHY1_NUM_INSTANCES 0 +#endif + +/** + * A table of configuration structures containing the configuration information + * for each Video PHY core in the system. + */ +extern XHdmiphy1_Config XHdmiphy1_ConfigTable[XPAR_XHDMIPHY1_NUM_INSTANCES]; + +/**************************** Function Definitions ****************************/ + +/******************************************************************************/ +/** + * This function looks for the device configuration based on the unique device + * ID. The table XHdmiphy1_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. + * +*******************************************************************************/ +XHdmiphy1_Config *XHdmiphy1_LookupConfig(u16 DeviceId) +{ + XHdmiphy1_Config *CfgPtr = NULL; + u32 Index; + + for (Index = 0; Index < XPAR_XHDMIPHY1_NUM_INSTANCES; Index++) { + if (XHdmiphy1_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XHdmiphy1_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} diff --git a/hdmi/xilinx-hdmirx.c b/hdmi/xilinx-hdmirx.c index 600f721..f4e98ae 100644 --- a/hdmi/xilinx-hdmirx.c +++ b/hdmi/xilinx-hdmirx.c @@ -122,6 +122,10 @@ struct xhdmi_device { u32 IntrStatus[7]; /* pointer to xvphy */ XVphy *xvphy; + /* pointer to HDMI GT controller phy */ + XHdmiphy1 *xgtphy; + /* flag to determine which phy */ + u32 isvphy; /* HDCP keys */ u8 hdcp_password[32]; u8 Hdcp22Lc128[16]; @@ -695,7 +699,11 @@ static void RxConnectCallback(void *CallbackRef) struct xhdmi_device *xhdmi = (struct xhdmi_device *)CallbackRef; XV_HdmiRxSs *HdmiRxSsPtr = &xhdmi->xv_hdmirxss; XVphy *VphyPtr = xhdmi->xvphy; - if (!xhdmi || !HdmiRxSsPtr || !VphyPtr) return; + XHdmiphy1 *XGtPhyPtr = xhdmi->xgtphy; + + if (!xhdmi || !HdmiRxSsPtr || (xhdmi->isvphy && !VphyPtr) || + (!xhdmi->isvphy && !XGtPhyPtr)) + return; xhdmi->cable_is_connected = !!HdmiRxSsPtr->IsStreamConnected; dev_dbg(xhdmi->dev,"RxConnectCallback(): cable is %sconnected.\n", @@ -704,11 +712,20 @@ static void RxConnectCallback(void *CallbackRef) xvphy_mutex_lock(xhdmi->phy[0]); /* RX cable is connected? */ if (HdmiRxSsPtr->IsStreamConnected) { - XVphy_IBufDsEnable(VphyPtr, 0, XVPHY_DIR_RX, (TRUE)); + if (xhdmi->isvphy) + XVphy_IBufDsEnable(VphyPtr, 0, XVPHY_DIR_RX, (TRUE)); + else + XHdmiphy1_IBufDsEnable(XGtPhyPtr, 0, XHDMIPHY1_DIR_RX, (TRUE)); } else { - /* clear GT RX TMDS clock ratio */ - VphyPtr->HdmiRxTmdsClockRatio = 0; - XVphy_IBufDsEnable(VphyPtr, 0, XVPHY_DIR_RX, (FALSE)); + if (xhdmi->isvphy) { + /* clear GT RX TMDS clock ratio */ + VphyPtr->HdmiRxTmdsClockRatio = 0; + XVphy_IBufDsEnable(VphyPtr, 0, XVPHY_DIR_RX, (FALSE)); + } else { + /* clear GT RX TMDS clock ratio */ + XGtPhyPtr->HdmiRxTmdsClockRatio = 0; + XHdmiphy1_IBufDsEnable(XGtPhyPtr, 0, XHDMIPHY1_DIR_RX, (FALSE)); + } } xvphy_mutex_unlock(xhdmi->phy[0]); } @@ -730,9 +747,14 @@ static void RxStreamInitCallback(void *CallbackRef) struct xhdmi_device *xhdmi = (struct xhdmi_device *)CallbackRef; XV_HdmiRxSs *HdmiRxSsPtr = &xhdmi->xv_hdmirxss; XVphy *VphyPtr = xhdmi->xvphy; + XHdmiphy1 *XGtPhyPtr = xhdmi->xgtphy; XVidC_VideoStream *HdmiRxSsVidStreamPtr; u32 Status; - if (!xhdmi || !HdmiRxSsPtr || !VphyPtr) return; + + if (!xhdmi || !HdmiRxSsPtr || (xhdmi->isvphy && !VphyPtr) || + (!xhdmi->isvphy && !XGtPhyPtr)) + return; + dev_dbg(xhdmi->dev,"RxStreamInitCallback\r\n"); // Calculate RX MMCM parameters // In the application the YUV422 colordepth is 12 bits @@ -744,16 +766,30 @@ static void RxStreamInitCallback(void *CallbackRef) xvphy_mutex_lock(xhdmi->phy[0]); if (HdmiRxSsVidStreamPtr->ColorFormatId == XVIDC_CSF_YCRCB_422) { - Status = XVphy_HdmiCfgCalcMmcmParam(VphyPtr, 0, XVPHY_CHANNEL_ID_CH1, - XVPHY_DIR_RX, - HdmiRxSsVidStreamPtr->PixPerClk, - XVIDC_BPC_8); + if (xhdmi->isvphy) { + Status = XVphy_HdmiCfgCalcMmcmParam(VphyPtr, 0, XVPHY_CHANNEL_ID_CH1, + XVPHY_DIR_RX, + HdmiRxSsVidStreamPtr->PixPerClk, + XVIDC_BPC_8); + } else { + Status = XHdmiphy1_HdmiCfgCalcMmcmParam(XGtPhyPtr, 0, XHDMIPHY1_CHANNEL_ID_CH1, + XHDMIPHY1_DIR_RX, + HdmiRxSsVidStreamPtr->PixPerClk, + XVIDC_BPC_8); + } // Other colorspaces } else { - Status = XVphy_HdmiCfgCalcMmcmParam(VphyPtr, 0, XVPHY_CHANNEL_ID_CH1, - XVPHY_DIR_RX, - HdmiRxSsVidStreamPtr->PixPerClk, - HdmiRxSsVidStreamPtr->ColorDepth); + if (xhdmi->isvphy) { + Status = XVphy_HdmiCfgCalcMmcmParam(VphyPtr, 0, XVPHY_CHANNEL_ID_CH1, + XVPHY_DIR_RX, + HdmiRxSsVidStreamPtr->PixPerClk, + HdmiRxSsVidStreamPtr->ColorDepth); + } else { + Status = XHdmiphy1_HdmiCfgCalcMmcmParam(XGtPhyPtr, 0, XHDMIPHY1_CHANNEL_ID_CH1, + XHDMIPHY1_DIR_RX, + HdmiRxSsVidStreamPtr->PixPerClk, + HdmiRxSsVidStreamPtr->ColorDepth); + } } if (Status == XST_FAILURE) { @@ -762,7 +798,10 @@ static void RxStreamInitCallback(void *CallbackRef) } // Enable and configure RX MMCM - XVphy_MmcmStart(VphyPtr, 0, XVPHY_DIR_RX); + if (xhdmi->isvphy) + XVphy_MmcmStart(VphyPtr, 0, XVPHY_DIR_RX); + else + XHdmiphy1_MmcmStart(XGtPhyPtr, 0, XHDMIPHY1_DIR_RX); //wait 10ms for PLL to stabilize usleep_range(10000, 11000); xvphy_mutex_unlock(xhdmi->phy[0]); @@ -1010,8 +1049,12 @@ static void VphyHdmiRxInitCallback(void *CallbackRef) struct xhdmi_device *xhdmi = (struct xhdmi_device *)CallbackRef; XV_HdmiRxSs *HdmiRxSsPtr = &xhdmi->xv_hdmirxss; XVphy *VphyPtr = xhdmi->xvphy; + XHdmiphy1 *XGtPhyPtr = xhdmi->xgtphy; + + if ((!xhdmi) || (xhdmi->isvphy && !VphyPtr) || + (!xhdmi->isvphy && !XGtPhyPtr)) + return; - if (!xhdmi || !VphyPtr) return; dev_dbg(xhdmi->dev,"VphyHdmiRxInitCallback()\n"); /* a pair of mutexes must be locked in fixed order to prevent deadlock, @@ -1022,7 +1065,11 @@ static void VphyHdmiRxInitCallback(void *CallbackRef) XV_HdmiRxSs_RefClockChangeInit(HdmiRxSsPtr); /* @NOTE maybe implement xvphy_set_hdmirx_tmds_clockratio(); */ - VphyPtr->HdmiRxTmdsClockRatio = HdmiRxSsPtr->TMDSClockRatio; + if (xhdmi->isvphy) + VphyPtr->HdmiRxTmdsClockRatio = HdmiRxSsPtr->TMDSClockRatio; + else + XGtPhyPtr->HdmiRxTmdsClockRatio = HdmiRxSsPtr->TMDSClockRatio; + /* unlock RX SS but keep XVPHY locked */ hdmi_mutex_unlock(&xhdmi->xhdmi_mutex); } @@ -1034,8 +1081,13 @@ static void VphyHdmiRxReadyCallback(void *CallbackRef) struct xhdmi_device *xhdmi = (struct xhdmi_device *)CallbackRef; XVphy *VphyPtr = xhdmi->xvphy; XVphy_PllType RxPllType; + XHdmiphy1 *XGtPhyPtr = xhdmi->xgtphy; + XHdmiphy1_PllType GtRxPllType; + + if ((!xhdmi) || (xhdmi->isvphy && !VphyPtr) || + (!xhdmi->isvphy && !XGtPhyPtr)) + return; - if (!xhdmi || !VphyPtr) return; dev_dbg(xhdmi->dev,"VphyHdmiRxReadyCallback()\n"); /* a pair of mutexes must be locked in fixed order to prevent deadlock, @@ -1044,15 +1096,27 @@ static void VphyHdmiRxReadyCallback(void *CallbackRef) hdmi_mutex_lock(&xhdmi->xhdmi_mutex); xvphy_mutex_lock(xhdmi->phy[0]); - RxPllType = XVphy_GetPllType(VphyPtr, 0, XVPHY_DIR_RX, - XVPHY_CHANNEL_ID_CH1); - if (!(RxPllType == XVPHY_PLL_TYPE_CPLL)) { - XV_HdmiRxSs_SetStream(&xhdmi->xv_hdmirxss, VphyPtr->HdmiRxRefClkHz, - (XVphy_GetLineRateHz(VphyPtr, 0, XVPHY_CHANNEL_ID_CMN0)/1000000)); - } - else { - XV_HdmiRxSs_SetStream(&xhdmi->xv_hdmirxss, VphyPtr->HdmiRxRefClkHz, - (XVphy_GetLineRateHz(VphyPtr, 0, XVPHY_CHANNEL_ID_CH1)/1000000)); + if (xhdmi->isvphy) { + RxPllType = XVphy_GetPllType(VphyPtr, 0, XVPHY_DIR_RX, + XVPHY_CHANNEL_ID_CH1); + if (!(RxPllType == XVPHY_PLL_TYPE_CPLL)) { + XV_HdmiRxSs_SetStream(&xhdmi->xv_hdmirxss, VphyPtr->HdmiRxRefClkHz, + (XVphy_GetLineRateHz(VphyPtr, 0, XVPHY_CHANNEL_ID_CMN0)/1000000)); + } + else { + XV_HdmiRxSs_SetStream(&xhdmi->xv_hdmirxss, VphyPtr->HdmiRxRefClkHz, + (XVphy_GetLineRateHz(VphyPtr, 0, XVPHY_CHANNEL_ID_CH1)/1000000)); + } + } else { + GtRxPllType = XHdmiphy1_GetPllType(XGtPhyPtr, 0, XHDMIPHY1_DIR_RX, + XHDMIPHY1_CHANNEL_ID_CH1); + if (!(GtRxPllType == XHDMIPHY1_PLL_TYPE_CPLL)) { + XV_HdmiRxSs_SetStream(&xhdmi->xv_hdmirxss, XGtPhyPtr->HdmiRxRefClkHz, + (XHdmiphy1_GetLineRateHz(XGtPhyPtr, 0, XHDMIPHY1_CHANNEL_ID_CMN0)/1000000)); + } else { + XV_HdmiRxSs_SetStream(&xhdmi->xv_hdmirxss, XGtPhyPtr->HdmiRxRefClkHz, + (XHdmiphy1_GetLineRateHz(XGtPhyPtr, 0, XHDMIPHY1_CHANNEL_ID_CH1)/1000000)); + } } hdmi_mutex_unlock(&xhdmi->xhdmi_mutex); } @@ -1338,12 +1402,16 @@ static ssize_t vphy_log_show(struct device *sysfs_dev, struct device_attribute * { ssize_t count; XV_HdmiRxSs *HdmiRxSsPtr; - XVphy *VphyPtr; struct xhdmi_device *xhdmi = (struct xhdmi_device *)dev_get_drvdata(sysfs_dev); + XVphy *VphyPtr = xhdmi->xvphy; + XHdmiphy1 *XGtPhyPtr = xhdmi->xgtphy; HdmiRxSsPtr = (XV_HdmiRxSs *)&xhdmi->xv_hdmirxss; - VphyPtr = xhdmi->xvphy; - count = XVphy_LogShow(VphyPtr, buf, PAGE_SIZE); + if (xhdmi->isvphy) + count = XVphy_LogShow(VphyPtr, buf, PAGE_SIZE); + else + count = XHdmiphy1_LogShow(XGtPhyPtr, buf, PAGE_SIZE); + return count; } @@ -1353,15 +1421,26 @@ static ssize_t vphy_info_show(struct device *sysfs_dev, struct device_attribute ssize_t count; XV_HdmiRxSs *HdmiRxSsPtr; XVphy *VphyPtr; + XHdmiphy1 *XGtPhyPtr; struct xhdmi_device *xhdmi = (struct xhdmi_device *)dev_get_drvdata(sysfs_dev); HdmiRxSsPtr = (XV_HdmiRxSs *)&xhdmi->xv_hdmirxss; - VphyPtr = xhdmi->xvphy; - count = XVphy_HdmiDebugInfo(VphyPtr, 0, XVPHY_CHANNEL_ID_CHA, buf, PAGE_SIZE); - count += scnprintf(&buf[count], (PAGE_SIZE-count), "Rx Ref Clk: %0d Hz\n", - XVphy_ClkDetGetRefClkFreqHz(xhdmi->xvphy, XVPHY_DIR_RX)); - count += scnprintf(&buf[count], (PAGE_SIZE-count), "DRU Ref Clk: %0d Hz\n", - XVphy_DruGetRefClkFreqHz(xhdmi->xvphy)); + + if (xhdmi->isvphy) { + VphyPtr = xhdmi->xvphy; + count = XVphy_HdmiDebugInfo(VphyPtr, 0, XVPHY_CHANNEL_ID_CHA, buf, PAGE_SIZE); + count += scnprintf(&buf[count], (PAGE_SIZE-count), "Rx Ref Clk: %0d Hz\n", + XVphy_ClkDetGetRefClkFreqHz(xhdmi->xvphy, XVPHY_DIR_RX)); + count += scnprintf(&buf[count], (PAGE_SIZE-count), "DRU Ref Clk: %0d Hz\n", + XVphy_DruGetRefClkFreqHz(xhdmi->xvphy)); + } else { + XGtPhyPtr = xhdmi->xgtphy; + count = XHdmiphy1_HdmiDebugInfo(XGtPhyPtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, buf, PAGE_SIZE); + count += scnprintf(&buf[count], (PAGE_SIZE-count), "Rx Ref Clk: %0d Hz\n", + XHdmiphy1_ClkDetGetRefClkFreqHz(xhdmi->xgtphy, XHDMIPHY1_DIR_RX)); + count += scnprintf(&buf[count], (PAGE_SIZE-count), "DRU Ref Clk: %0d Hz\n", + XHdmiphy1_DruGetRefClkFreqHz(xhdmi->xgtphy)); + } return count; } @@ -1812,7 +1891,7 @@ static int xhdmi_probe(struct platform_device *pdev) struct xlnx_hdmirx_audio_data *adata; u32 Status; - dev_info(&pdev->dev, "probed\n"); + dev_info(&pdev->dev, "probe started\n"); /* allocate zeroed HDMI RX device structure */ xhdmi = devm_kzalloc(&pdev->dev, sizeof(*xhdmi), GFP_KERNEL); if (!xhdmi) @@ -1852,6 +1931,13 @@ static int xhdmi_probe(struct platform_device *pdev) /* acquire vphy lanes */ for (index = 0; index < 3; index++) { + static const struct of_device_id xlnx_hdmi_phy_id_table[] = { + { .compatible = "xlnx,hdmi-gt-controller-1.0", }, + { .compatible = "xlnx,vid-phy-controller-2.2", }, + { /* end of table */ }, + }; + const struct of_device_id *match; + char phy_name[16]; snprintf(phy_name, sizeof(phy_name), "hdmi-phy%d", index); xhdmi->phy[index] = devm_phy_get(xhdmi->dev, phy_name); @@ -1859,7 +1945,7 @@ static int xhdmi_probe(struct platform_device *pdev) ret = PTR_ERR(xhdmi->phy[index]); xhdmi->phy[index] = NULL; if (ret == -EPROBE_DEFER) { - dev_info(xhdmi->dev, "xvphy not ready -EPROBE_DEFER\n"); + dev_info(xhdmi->dev, "xvphy/xgtphy not ready -EPROBE_DEFER\n"); return ret; } if (ret != -EPROBE_DEFER) @@ -1868,6 +1954,12 @@ static int xhdmi_probe(struct platform_device *pdev) goto error_phy; } + match = of_match_node(xlnx_hdmi_phy_id_table, xhdmi->phy[index]->dev.parent->of_node); + if (strncmp(match->compatible, "xlnx,vid-phy-controller", 23) == 0) + xhdmi->isvphy = 1; + else + xhdmi->isvphy = 0; + ret = phy_init(xhdmi->phy[index]); if (ret) { dev_err(xhdmi->dev, @@ -2093,16 +2185,26 @@ static int xhdmi_probe(struct platform_device *pdev) XV_HdmiRxSs_SetCallback(HdmiRxSsPtr, XV_HDMIRXSS_HANDLER_AUX, RxAuxCallback, (void *)xhdmi); - /* get a reference to the XVphy data structure */ - xhdmi->xvphy = xvphy_get_xvphy(xhdmi->phy[0]); + /* get a reference to the XVphy/ XHdmiphy1 data structure */ + if (xhdmi->isvphy) + xhdmi->xvphy = xvphy_get_xvphy(xhdmi->phy[0]); + else + xhdmi->xgtphy = xvphy_get_xvphy(xhdmi->phy[0]); xvphy_mutex_lock(xhdmi->phy[0]); /* the callback is not specific to a single lane, but we need to * provide one of the phy's as reference */ - XVphy_SetHdmiCallback(xhdmi->xvphy, XVPHY_HDMI_HANDLER_RXINIT, - VphyHdmiRxInitCallback, (void *)xhdmi); - XVphy_SetHdmiCallback(xhdmi->xvphy, XVPHY_HDMI_HANDLER_RXREADY, - VphyHdmiRxReadyCallback, (void *)xhdmi); + if (xhdmi->isvphy) { + XVphy_SetHdmiCallback(xhdmi->xvphy, XVPHY_HDMI_HANDLER_RXINIT, + VphyHdmiRxInitCallback, (void *)xhdmi); + XVphy_SetHdmiCallback(xhdmi->xvphy, XVPHY_HDMI_HANDLER_RXREADY, + VphyHdmiRxReadyCallback, (void *)xhdmi); + } else { + XHdmiphy1_SetHdmiCallback(xhdmi->xgtphy, XHDMIPHY1_HDMI_HANDLER_RXINIT, + VphyHdmiRxInitCallback, (void *)xhdmi); + XHdmiphy1_SetHdmiCallback(xhdmi->xgtphy, XHDMIPHY1_HDMI_HANDLER_RXREADY, + VphyHdmiRxReadyCallback, (void *)xhdmi); + } xvphy_mutex_unlock(xhdmi->phy[0]); diff --git a/hdmi/xilinx_drm_hdmi.c b/hdmi/xilinx_drm_hdmi.c index 150359d..86b5c4b 100644 --- a/hdmi/xilinx_drm_hdmi.c +++ b/hdmi/xilinx_drm_hdmi.c @@ -57,6 +57,8 @@ #define XVPHY_TXREFCLK_RDY_LOW 0 #define XVPHY_TXREFCLK_RDY_HIGH 1 +#define XHDMIPHY1_TXREFCLK_RDY_LOW 0 +#define XHDMIPHY1_TXREFCLK_RDY_HIGH 1 #define hdmi_mutex_lock(x) mutex_lock(x) #define hdmi_mutex_unlock(x) mutex_unlock(x) @@ -110,6 +112,8 @@ * @xv_hdmitxss: IP low level driver structure * @IntrStatus: Flag to indicate irq status * @xvphy: pointer to xilinx video phy + * @xgtphy: pointer to Xilinx HDMI GT Controller phy + * @isvphy: Flag to determine which Phy * @audio_enabled: flag to indicate audio is enabled in device tree * @audio_init: flag to indicate audio is initialized * @tx_audio_data: audio data to be shared with audio module @@ -173,6 +177,10 @@ struct xlnx_drm_hdmi { u32 IntrStatus; /* pointer to xvphy */ XVphy *xvphy; + /* pointer to xgtphy */ + XHdmiphy1 *xgtphy; + /* flag to determine which Phy */ + u32 isvphy; /* HDCP keys */ u8 hdcp_password[32]; u8 Hdcp22Lc128[16]; @@ -523,6 +531,7 @@ static void TxConnectCallback(void *CallbackRef) struct xlnx_drm_hdmi *xhdmi = (struct xlnx_drm_hdmi *)CallbackRef; XV_HdmiTxSs *HdmiTxSsPtr = &xhdmi->xv_hdmitxss; XVphy *VphyPtr = xhdmi->xvphy; + XHdmiphy1 *XGtPhyPtr = xhdmi->xgtphy; dev_dbg(xhdmi->dev,"%s()\n", __func__); xvphy_mutex_lock(xhdmi->phy[0]); @@ -535,7 +544,10 @@ static void TxConnectCallback(void *CallbackRef) dev_dbg(xhdmi->dev,"TxConnectCallback(): TX connected to HDMI %s Sink Device\n", (xst_hdmi20 == XST_SUCCESS)? "2.0": "1.4"); xhdmi->is_hdmi_20_sink = (xst_hdmi20 == XST_SUCCESS); - XVphy_IBufDsEnable(VphyPtr, 0, XVPHY_DIR_TX, (TRUE)); + if (xhdmi->isvphy) + XVphy_IBufDsEnable(VphyPtr, 0, XVPHY_DIR_TX, (TRUE)); + else + XHdmiphy1_IBufDsEnable(XGtPhyPtr, 0, XHDMIPHY1_DIR_TX, (TRUE)); XV_HdmiTxSs_StreamStart(HdmiTxSsPtr); /* stream never goes down on disconnect. Force hdcp event */ if (xhdmi->hdmi_stream_up && @@ -552,7 +564,10 @@ static void TxConnectCallback(void *CallbackRef) xhdmi->have_edid = 0; xhdmi->is_hdmi_20_sink = 0; /* do not disable ibufds - stream will not go down*/ - XVphy_IBufDsEnable(VphyPtr, 0, XVPHY_DIR_TX, (FALSE)); + if (xhdmi->isvphy) + XVphy_IBufDsEnable(VphyPtr, 0, XVPHY_DIR_TX, (FALSE)); + else + XHdmiphy1_IBufDsEnable(XGtPhyPtr, 0, XHDMIPHY1_DIR_TX, (FALSE)); } xvphy_mutex_unlock(xhdmi->phy[0]); @@ -577,14 +592,18 @@ static void TxStreamUpCallback(void *CallbackRef) { struct xlnx_drm_hdmi *xhdmi = (struct xlnx_drm_hdmi *)CallbackRef; XVphy *VphyPtr; + XHdmiphy1 *XGtPhyPtr; XV_HdmiTxSs *HdmiTxSsPtr; XVphy_PllType TxPllType; - u64 TxLineRate; + XHdmiphy1_PllType GtTxPllType; + u64 TxLineRate = 0; XHdmiC_AVI_InfoFrame *AVIInfoFramePtr; XVidC_VideoStream *HdmiTxSsVidStreamPtr; HdmiTxSsPtr = &xhdmi->xv_hdmitxss; + VphyPtr = xhdmi->xvphy; + XGtPhyPtr = xhdmi->xgtphy; dev_dbg(xhdmi->dev,"TxStreamUpCallback(): TX stream is up\n"); xhdmi->hdmi_stream_up = 1; @@ -603,17 +622,33 @@ static void TxStreamUpCallback(void *CallbackRef) } xvphy_mutex_lock(xhdmi->phy[0]); - TxPllType = XVphy_GetPllType(VphyPtr, 0, XVPHY_DIR_TX, XVPHY_CHANNEL_ID_CH1); - if ((TxPllType == XVPHY_PLL_TYPE_CPLL)) { - TxLineRate = XVphy_GetLineRateHz(VphyPtr, 0, XVPHY_CHANNEL_ID_CH1); - } - else if((TxPllType == XVPHY_PLL_TYPE_QPLL) || + if (xhdmi->isvphy) { + TxPllType = XVphy_GetPllType(VphyPtr, 0, XVPHY_DIR_TX, XVPHY_CHANNEL_ID_CH1); + if ((TxPllType == XVPHY_PLL_TYPE_CPLL)) { + TxLineRate = XVphy_GetLineRateHz(VphyPtr, 0, XVPHY_CHANNEL_ID_CH1); + } + else if((TxPllType == XVPHY_PLL_TYPE_QPLL) || (TxPllType == XVPHY_PLL_TYPE_QPLL0) || (TxPllType == XVPHY_PLL_TYPE_PLL0)) { - TxLineRate = XVphy_GetLineRateHz(VphyPtr, 0, XVPHY_CHANNEL_ID_CMN0); - } - else { - TxLineRate = XVphy_GetLineRateHz(VphyPtr, 0, XVPHY_CHANNEL_ID_CMN1); + TxLineRate = XVphy_GetLineRateHz(VphyPtr, 0, XVPHY_CHANNEL_ID_CMN0); + } + else { + TxLineRate = XVphy_GetLineRateHz(VphyPtr, 0, XVPHY_CHANNEL_ID_CMN1); + } + } else { + GtTxPllType = XHdmiphy1_GetPllType(XGtPhyPtr, 0, XHDMIPHY1_DIR_TX, XHDMIPHY1_CHANNEL_ID_CH1); + /* Versal - Implementation different here */ + if (GtTxPllType == XHDMIPHY1_PLL_TYPE_LCPLL) { + TxLineRate = + XHdmiphy1_GetLineRateHz(XGtPhyPtr, 0, XHDMIPHY1_CHANNEL_ID_CMN0); + dev_dbg(xhdmi->dev, "GtPhy TxLineRate LCPLL %lld Kbps\r\n",(TxLineRate/1000)); + } else if (GtTxPllType == XHDMIPHY1_PLL_TYPE_RPLL) { + TxLineRate = + XHdmiphy1_GetLineRateHz(XGtPhyPtr, 0, XHDMIPHY1_CHANNEL_ID_CMN1); + dev_dbg(xhdmi->dev, "GtPhy TxLineRate RPLL %lld Kbps\r\n",(TxLineRate/1000)); + } else { + dev_err(xhdmi->dev, "GtPhy Error! Invalid GtTxPllType in TxStreamUpCallback.\r\n"); + } } /* configure an external retimer through a (virtual) CCF clock @@ -623,10 +658,16 @@ static void TxStreamUpCallback(void *CallbackRef) (void)clk_set_rate(xhdmi->retimer_clk, (signed long long)TxLineRate); } /* Copy Sampling Rate */ - XV_HdmiTxSs_SetSamplingRate(HdmiTxSsPtr, VphyPtr->HdmiTxSampleRate); + if (xhdmi->isvphy) + XV_HdmiTxSs_SetSamplingRate(HdmiTxSsPtr, VphyPtr->HdmiTxSampleRate); + else + XV_HdmiTxSs_SetSamplingRate(HdmiTxSsPtr, XGtPhyPtr->HdmiTxSampleRate); /* Enable TX TMDS clock*/ - XVphy_Clkout1OBufTdsEnable(VphyPtr, XVPHY_DIR_TX, (TRUE)); + if (xhdmi->isvphy) + XVphy_Clkout1OBufTdsEnable(VphyPtr, XVPHY_DIR_TX, (TRUE)); + else + XHdmiphy1_Clkout1OBufTdsEnable(XGtPhyPtr, XHDMIPHY1_DIR_TX, (TRUE)); xvphy_mutex_unlock(xhdmi->phy[0]); @@ -747,10 +788,15 @@ static void VphyHdmiTxInitCallback(void *CallbackRef) { struct xlnx_drm_hdmi *xhdmi = (struct xlnx_drm_hdmi *)CallbackRef; XVphy *VphyPtr; + XHdmiphy1 *XGtPhyPtr; XV_HdmiTxSs *HdmiTxSsPtr; HdmiTxSsPtr = &xhdmi->xv_hdmitxss; - VphyPtr = xhdmi->xvphy; + + if (xhdmi->isvphy) + VphyPtr = xhdmi->xvphy; + else + XGtPhyPtr = xhdmi->xgtphy; dev_dbg(xhdmi->dev,"VphyHdmiTxInitCallback(): XV_HdmiTxSs_RefClockChangeInit()\n"); @@ -1079,6 +1125,7 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, XVidC_VideoTiming vt; XVphy *VphyPtr; + XHdmiphy1 *XGtPhyPtr; XV_HdmiTxSs *HdmiTxSsPtr; XVidC_VideoStream *HdmiTxSsVidStreamPtr; XHdmiC_AVI_InfoFrame *AviInfoFramePtr; @@ -1092,7 +1139,9 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, dev_dbg(xhdmi->dev,"%s\n", __func__); HdmiTxSsPtr = &xhdmi->xv_hdmitxss; + VphyPtr = xhdmi->xvphy; + XGtPhyPtr = xhdmi->xgtphy; hdmi_mutex_lock(&xhdmi->hdmi_mutex); xvphy_mutex_lock(xhdmi->phy[0]); @@ -1181,11 +1230,19 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, // Reset Vendor Specific InfoFrame (void)memset((void *)VSIFPtr, 0, sizeof(XHdmiC_VSIF)); - /* Get current Tx Ref clock from PHY */ - PrevPhyTxRefClock = VphyPtr->HdmiTxRefClkHz; + if (xhdmi->isvphy) { + /* Get current Tx Ref clock from PHY */ + PrevPhyTxRefClock = VphyPtr->HdmiTxRefClkHz; + + /* Disable TX TDMS clock */ + XVphy_Clkout1OBufTdsEnable(VphyPtr, XVPHY_DIR_TX, (FALSE)); + } else { + /* Get current Tx Ref clock from PHY */ + PrevPhyTxRefClock = XGtPhyPtr->HdmiTxRefClkHz; - /* Disable TX TDMS clock */ - XVphy_Clkout1OBufTdsEnable(VphyPtr, XVPHY_DIR_TX, (FALSE)); + /* Disable TX TDMS clock */ + XHdmiphy1_Clkout1OBufTdsEnable(XGtPhyPtr, XHDMIPHY1_DIR_TX, (FALSE)); + } /* The isExtensive is made true to get the correct video timing by matching * all the parameters */ @@ -1242,18 +1299,34 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, } // Set TX reference clock - VphyPtr->HdmiTxRefClkHz = TmdsClock; + if (xhdmi->isvphy) + VphyPtr->HdmiTxRefClkHz = TmdsClock; + else + XGtPhyPtr->HdmiTxRefClkHz = TmdsClock; + dev_dbg(xhdmi->dev,"(TmdsClock = %u, from XV_HdmiTxSs_SetStream())\n", TmdsClock); - dev_dbg(xhdmi->dev,"XVphy_SetHdmiTxParam(PixPerClk = %d, ColorDepth = %d, ColorFormatId=%d)\n", + if (xhdmi->isvphy) { + dev_dbg(xhdmi->dev,"XVphy_SetHdmiTxParam(PixPerClk = %d, ColorDepth = %d, ColorFormatId=%d)\n", + (int)HdmiTxSsVidStreamPtr->PixPerClk, (int)HdmiTxSsVidStreamPtr->ColorDepth, + (int)HdmiTxSsVidStreamPtr->ColorFormatId); + + // Set GT TX parameters, this might change VphyPtr->HdmiTxRefClkHz + Result = XVphy_SetHdmiTxParam(VphyPtr, 0, XVPHY_CHANNEL_ID_CHA, + HdmiTxSsVidStreamPtr->PixPerClk, + HdmiTxSsVidStreamPtr->ColorDepth, + HdmiTxSsVidStreamPtr->ColorFormatId); + } else { + dev_dbg(xhdmi->dev,"XHdmiphy1_SetHdmiTxParam(PixPerClk = %d, ColorDepth = %d, ColorFormatId=%d)\n", (int)HdmiTxSsVidStreamPtr->PixPerClk, (int)HdmiTxSsVidStreamPtr->ColorDepth, (int)HdmiTxSsVidStreamPtr->ColorFormatId); - // Set GT TX parameters, this might change VphyPtr->HdmiTxRefClkHz - Result = XVphy_SetHdmiTxParam(VphyPtr, 0, XVPHY_CHANNEL_ID_CHA, + // Set GT TX parameters, this might change XGtPhyPtr->HdmiTxRefClkHz + Result = XHdmiphy1_SetHdmiTxParam(XGtPhyPtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, HdmiTxSsVidStreamPtr->PixPerClk, HdmiTxSsVidStreamPtr->ColorDepth, HdmiTxSsVidStreamPtr->ColorFormatId); + } if (Result == (XST_FAILURE)) { dev_dbg(xhdmi->dev,"Unable to set requested TX video resolution.\n\r"); xvphy_mutex_unlock(xhdmi->phy[0]); @@ -1261,7 +1334,11 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, return; } - adjusted_mode->clock = VphyPtr->HdmiTxRefClkHz / 1000; + if (xhdmi->isvphy) + adjusted_mode->clock = VphyPtr->HdmiTxRefClkHz / 1000; + else + adjusted_mode->clock = XGtPhyPtr->HdmiTxRefClkHz / 1000; + dev_dbg(xhdmi->dev,"adjusted_mode->clock = %u Hz\n", adjusted_mode->clock); /* request required tmds clock rate */ @@ -1274,11 +1351,20 @@ static void xlnx_drm_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, * signal must be toggled (asserted and de-asserted) to reset phy's * internal frequency detection state machine */ - dev_dbg(xhdmi->dev,"PrevPhyTxRefClock: %d, NewRefClock: %d\n", PrevPhyTxRefClock, VphyPtr->HdmiTxRefClkHz); - if (PrevPhyTxRefClock == VphyPtr->HdmiTxRefClkHz) { - /* Switching between resolutions with same frequency */ - dev_dbg(xhdmi->dev,"***** Reset Phy Tx Frequency *******\n"); - XVphy_ClkDetFreqReset(VphyPtr, 0, XVPHY_DIR_TX); + if (xhdmi->isvphy) { + dev_dbg(xhdmi->dev,"PrevPhyTxRefClock: %d, NewRefClock: %d\n", PrevPhyTxRefClock, VphyPtr->HdmiTxRefClkHz); + if (PrevPhyTxRefClock == VphyPtr->HdmiTxRefClkHz) { + /* Switching between resolutions with same frequency */ + dev_dbg(xhdmi->dev,"***** Reset Phy Tx Frequency *******\n"); + XVphy_ClkDetFreqReset(VphyPtr, 0, XVPHY_DIR_TX); + } + } else { + dev_dbg(xhdmi->dev,"PrevPhyTxRefClock: %d, NewRefClock: %d\n", PrevPhyTxRefClock, XGtPhyPtr->HdmiTxRefClkHz); + if (PrevPhyTxRefClock == XGtPhyPtr->HdmiTxRefClkHz) { + /* Switching between resolutions with same frequency */ + dev_dbg(xhdmi->dev,"***** Reset Phy Tx Frequency *******\n"); + XHdmiphy1_ClkDetFreqReset(XGtPhyPtr, 0, XHDMIPHY1_DIR_TX); + } } xhdmi->tx_audio_data->tmds_clk = clk_get_rate(xhdmi->tmds_clk); @@ -1572,10 +1658,16 @@ static ssize_t vphy_log_show(struct device *sysfs_dev, struct device_attribute * { ssize_t count; XVphy *VphyPtr; + XHdmiphy1 *XGtPhyPtr; struct xlnx_drm_hdmi *xhdmi = (struct xlnx_drm_hdmi *)dev_get_drvdata(sysfs_dev); - VphyPtr = xhdmi->xvphy; - count = XVphy_LogShow(VphyPtr, buf, PAGE_SIZE); + if (xhdmi->isvphy) { + VphyPtr = xhdmi->xvphy; + count = XVphy_LogShow(VphyPtr, buf, PAGE_SIZE); + } else { + XGtPhyPtr = xhdmi->xgtphy; + count = XHdmiphy1_LogShow(XGtPhyPtr, buf, PAGE_SIZE); + } return count; } @@ -1584,12 +1676,20 @@ static ssize_t vphy_info_show(struct device *sysfs_dev, struct device_attribute { ssize_t count; XVphy *VphyPtr; + XHdmiphy1 *XGtPhyPtr; struct xlnx_drm_hdmi *xhdmi = (struct xlnx_drm_hdmi *)dev_get_drvdata(sysfs_dev); - VphyPtr = xhdmi->xvphy; - count = XVphy_HdmiDebugInfo(VphyPtr, 0, XVPHY_CHANNEL_ID_CHA, buf, PAGE_SIZE); - count += scnprintf(&buf[count], (PAGE_SIZE-count), "Tx Ref Clk: %0d Hz\n", + if (xhdmi->isvphy) { + VphyPtr = xhdmi->xvphy; + count = XVphy_HdmiDebugInfo(VphyPtr, 0, XVPHY_CHANNEL_ID_CHA, buf, PAGE_SIZE); + count += scnprintf(&buf[count], (PAGE_SIZE-count), "Tx Ref Clk: %0d Hz\n", XVphy_ClkDetGetRefClkFreqHz(xhdmi->xvphy, XVPHY_DIR_TX)); + } else { + XGtPhyPtr = xhdmi->xgtphy; + count = XHdmiphy1_HdmiDebugInfo(XGtPhyPtr, 0, XHDMIPHY1_CHANNEL_ID_CHA, buf, PAGE_SIZE); + count += scnprintf(&buf[count], (PAGE_SIZE-count), "Tx Ref Clk: %0d Hz\n", + XHdmiphy1_ClkDetGetRefClkFreqHz(xhdmi->xgtphy, XHDMIPHY1_DIR_TX)); + } return count; } @@ -2132,14 +2232,26 @@ static void xlnx_drm_hdmi_initialize(struct xlnx_drm_hdmi *xhdmi) TxBrdgUnderflowCallback, (void *)xhdmi); /* get a reference to the XVphy data structure */ - xhdmi->xvphy = xvphy_get_xvphy(xhdmi->phy[0]); + if (xhdmi->isvphy) + xhdmi->xvphy = xvphy_get_xvphy(xhdmi->phy[0]); + else + xhdmi->xgtphy = xvphy_get_xvphy(xhdmi->phy[0]); + xvphy_mutex_lock(xhdmi->phy[0]); /* the callback is not specific to a single lane, but we need to * provide one of the phys as reference */ - XVphy_SetHdmiCallback(xhdmi->xvphy, XVPHY_HDMI_HANDLER_TXINIT, - VphyHdmiTxInitCallback, (void *)xhdmi); - XVphy_SetHdmiCallback(xhdmi->xvphy, XVPHY_HDMI_HANDLER_TXREADY, - VphyHdmiTxReadyCallback, (void *)xhdmi); + + if (xhdmi->isvphy) { + XVphy_SetHdmiCallback(xhdmi->xvphy, XVPHY_HDMI_HANDLER_TXINIT, + VphyHdmiTxInitCallback, (void *)xhdmi); + XVphy_SetHdmiCallback(xhdmi->xvphy, XVPHY_HDMI_HANDLER_TXREADY, + VphyHdmiTxReadyCallback, (void *)xhdmi); + } else { + XHdmiphy1_SetHdmiCallback(xhdmi->xgtphy, XHDMIPHY1_HDMI_HANDLER_TXINIT, + VphyHdmiTxInitCallback, (void *)xhdmi); + XHdmiphy1_SetHdmiCallback(xhdmi->xgtphy, XHDMIPHY1_HDMI_HANDLER_TXREADY, + VphyHdmiTxReadyCallback, (void *)xhdmi); + } xvphy_mutex_unlock(xhdmi->phy[0]); /* Request the interrupt */ @@ -2307,7 +2419,7 @@ static int xlnx_drm_hdmi_probe(struct platform_device *pdev) struct resource *res; unsigned long axi_clk_rate; - dev_info(&pdev->dev, "probed\n"); + dev_info(&pdev->dev, "probe started\n"); /* allocate zeroed HDMI TX device structure */ xhdmi = devm_kzalloc(&pdev->dev, sizeof(*xhdmi), GFP_KERNEL); if (!xhdmi) @@ -2344,6 +2456,13 @@ static int xlnx_drm_hdmi_probe(struct platform_device *pdev) /* acquire vphy lanes */ for (index = 0; index < 3; index++) { + static const struct of_device_id xlnx_hdmi_phy_id_table[] = { + { .compatible = "xlnx,hdmi-gt-controller-1.0", }, + { .compatible = "xlnx,vid-phy-controller-2.2", }, + { /* end of table */ }, + }; + const struct of_device_id *match; + char phy_name[16]; snprintf(phy_name, sizeof(phy_name), "hdmi-phy%d", index); xhdmi->phy[index] = devm_phy_get(xhdmi->dev, phy_name); @@ -2351,7 +2470,7 @@ static int xlnx_drm_hdmi_probe(struct platform_device *pdev) ret = PTR_ERR(xhdmi->phy[index]); xhdmi->phy[index] = NULL; if (ret == -EPROBE_DEFER) { - dev_info(xhdmi->dev, "xvphy not ready -EPROBE_DEFER\n"); + dev_info(xhdmi->dev, "xvphy/xgtphy not ready -EPROBE_DEFER\n"); return ret; } if (ret != -EPROBE_DEFER) @@ -2360,6 +2479,12 @@ static int xlnx_drm_hdmi_probe(struct platform_device *pdev) goto error_phy; } + match = of_match_node(xlnx_hdmi_phy_id_table, xhdmi->phy[index]->dev.parent->of_node); + if (strncmp(match->compatible, "xlnx,vid-phy-controller", 23) == 0) + xhdmi->isvphy = 1; + else + xhdmi->isvphy = 0; + ret = phy_init(xhdmi->phy[index]); if (ret) { dev_err(xhdmi->dev, From 1035a56a12c0d2acdd7cb3aab52e926c5fce9447 Mon Sep 17 00:00:00 2001 From: Vishal Sagar Date: Thu, 2 Apr 2020 23:45:42 +0530 Subject: [PATCH 44/46] phy: hdmigtctrl: Update the GT values The GT values need to be programmed based on the Tx PLL and Rx PLL type. These can either be LCPLL or RPLL type. The Tx PLL type and Rx PLL type will not be same. This patch updates the values to be programmed in GT for Versal. The Reset PLL register reset in HDMI GT Controller (0x14 offset) is removed too. Signed-off-by: Vishal Sagar --- hdmi/phy-vphy.c | 48 ++++++++++++++++++++---------------------------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/hdmi/phy-vphy.c b/hdmi/phy-vphy.c index f903ad0..002c4b7 100644 --- a/hdmi/phy-vphy.c +++ b/hdmi/phy-vphy.c @@ -742,6 +742,9 @@ static int xvphy_probe(struct platform_device *pdev) if (!vphydev->isvphy) { /* For Versal */ + XHdmiphy1_Config *xgtphycfg = + (XHdmiphy1_Config *)(&XHdmiphy1_ConfigTable[instance]); + iomem1 = ioremap(0xF70E000C, 4); if (IS_ERR(iomem1)) dev_err(vphydev->dev, "[Versal] - Error in iomem 5\n"); @@ -749,34 +752,23 @@ static int xvphy_probe(struct platform_device *pdev) dev_dbg(vphydev->dev, "To: 0x%08x \r\n", XHdmiphy1_In32((INTPTR)iomem1)); iounmap(iomem1); - iomem1 = ioremap(0xF70E3C4C, 4); - if (IS_ERR(iomem1)) - dev_err(vphydev->dev, "[Versal] - Error in iomem 6\n"); - dev_dbg(vphydev->dev, "RX:HS1 RPLL IPS From: 0x%08x ", XHdmiphy1_In32((INTPTR)iomem1)); - XHdmiphy1_Out32((INTPTR)iomem1, 0x03E00810); - dev_dbg(vphydev->dev, "To: 0x%08x \r\n", XHdmiphy1_In32((INTPTR)iomem1)); - iounmap(iomem1); - - iomem1 = ioremap(0xF70E3C48, 4); - if (IS_ERR(iomem1)) - dev_err(vphydev->dev, "[Versal] - Error in iomem 7\n"); - dev_dbg(vphydev->dev, "TX:HS1 LCPLL IPS From: 0x%08x ", XHdmiphy1_In32((INTPTR)iomem1)); - XHdmiphy1_Out32((INTPTR)iomem1, 0x03E00840); - dev_dbg(vphydev->dev, "To: 0x%08x \r\n", XHdmiphy1_In32((INTPTR)iomem1)); - iounmap(iomem1); - - /* Deassert the GTWiz_RESET_ALL */ - XHdmiphy1_WriteReg(XHdmiphy1_ConfigTable[instance].BaseAddr, 0x14, - (XHdmiphy1_ReadReg(XHdmiphy1_ConfigTable[instance].BaseAddr, 0x14) & ~0x1)); - dev_dbg(vphydev->dev, "To: 0x14 PHY1 Reg 0x%08x \r\n", - XHdmiphy1_ReadReg(XHdmiphy1_ConfigTable[instance].BaseAddr, 0x14)); - - /* Release RXPLL dependency from TXPLL RESET */ - XHdmiphy1_WriteReg(XHdmiphy1_ConfigTable[instance].BaseAddr, 0x14, - (XHdmiphy1_ReadReg(XHdmiphy1_ConfigTable[instance].BaseAddr, 0x14) | 0x80000000)); - dev_dbg(vphydev->dev, "To: 0x14 PHY1 Reg 0x%08x \r\n", - XHdmiphy1_ReadReg(XHdmiphy1_ConfigTable[instance].BaseAddr, 0x14)); - + if (xgtphycfg->TxSysPllClkSel == 7 || xgtphycfg->RxSysPllClkSel == 8) { + iomem1 = ioremap(0xF70E3C4C, 4); + if (IS_ERR(iomem1)) + dev_err(vphydev->dev, "[Versal] - Error in iomem 6\n"); + dev_dbg(vphydev->dev, "RX:HS1 RPLL IPS From: 0x%08x ", XHdmiphy1_In32((INTPTR)iomem1)); + XHdmiphy1_Out32((INTPTR)iomem1, 0x03000810); + dev_dbg(vphydev->dev, "To: 0x%08x \r\n", XHdmiphy1_In32((INTPTR)iomem1)); + iounmap(iomem1); + } else { + iomem1 = ioremap(0xF70E3C48, 4); + if (IS_ERR(iomem1)) + dev_err(vphydev->dev, "[Versal] - Error in iomem 7\n"); + dev_dbg(vphydev->dev, "TX:HS1 LCPLL IPS From: 0x%08x ", XHdmiphy1_In32((INTPTR)iomem1)); + XHdmiphy1_Out32((INTPTR)iomem1, 0x03E00810); + dev_dbg(vphydev->dev, "To: 0x%08x \r\n", XHdmiphy1_In32((INTPTR)iomem1)); + iounmap(iomem1); + } /* Delay 50ms for GT to complete initialization */ usleep_range(50000, 50000); } From 3a6e440b50263a3ed99492aba3e507d7c130355c Mon Sep 17 00:00:00 2001 From: Vishal Sagar Date: Fri, 10 Apr 2020 11:58:36 +0530 Subject: [PATCH 45/46] license: Update the license 2020.1 Signed-off-by: Vishal Sagar --- LICENSE.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 0b84890..66111db 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,7 +1,7 @@ -Components: xhdmi 2019.2 - - - GNU GENERAL PUBLIC LICENSE +Components: xhdmi 2020.1 + + + GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. @@ -539,13 +539,13 @@ If it is not possible or desirable to put the notice in a particular file, then You may add additional accurate notices of copyright ownership. Exhibit B - ?Incompatible With Secondary Licenses? Notice -This Source Code Form is ?Incompatible With Secondary Licenses?, as defined by the Mozilla Public License, v. 2.0. - - -Copyright 2001 D.I. Management Services Pty Ltd -Copyright 2001 David Ireland D.I. Management Services Pty Ltd - - +This Source Code Form is ?Incompatible With Secondary Licenses?, as defined by the Mozilla Public License, v. 2.0. + + +copyright (c) 2001-15 by D.I. Management Services Pty Limited +Copyright 2001 David Ireland D.I. Management Services Pty Ltd + + Components: dp159 @@ -684,9 +684,9 @@ by James Hacker. signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice -This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. - - -Copyright 2007 Hans Verkuil -Copyright 2016-2017 Leon Woestenberg - +This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. + + +Copyright (C) 2007 Hans Verkuil +Copyright 2016-2017 Leon Woestenberg + From 7c16246c93a9694987753db9a40f18c75cf906bf Mon Sep 17 00:00:00 2001 From: Timo Witte Date: Thu, 18 Jun 2020 14:27:07 +0200 Subject: [PATCH 46/46] Be more verbose why exactly device tree parsing failed --- hdmi/phy-vphy.c | 112 +++++++++++++++++++++++++++++++----------------- 1 file changed, 72 insertions(+), 40 deletions(-) diff --git a/hdmi/phy-vphy.c b/hdmi/phy-vphy.c index 002c4b7..2fd42f6 100644 --- a/hdmi/phy-vphy.c +++ b/hdmi/phy-vphy.c @@ -388,120 +388,150 @@ static int vphy_parse_of(struct xvphy_dev *vphydev, void *c) XHdmiphy1_Config *xgtphycfg = (XHdmiphy1_Config *)c; rc = of_property_read_u32(node, "xlnx,transceiver-type", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,transceiver-type not specified"); + return -EINVAL; + } if (vphydev->isvphy) vphycfg->XcvrType = val; else xgtphycfg->XcvrType = val; rc = of_property_read_u32(node, "xlnx,tx-buffer-bypass", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,tx-buffer-bypass not specified"); + return -EINVAL; + } if (vphydev->isvphy) vphycfg->TxBufferBypass = val; else xgtphycfg->TxBufferBypass = val; rc = of_property_read_u32(node, "xlnx,input-pixels-per-clock", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,input-pixels-per-clock not specified"); + return -EINVAL; + } if (vphydev->isvphy) vphycfg->Ppc = val; else xgtphycfg->Ppc = val; rc = of_property_read_u32(node, "xlnx,nidru", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,nidru not specified"); + return -EINVAL; + } if (vphydev->isvphy) vphycfg->DruIsPresent = val; else xgtphycfg->DruIsPresent = val; rc = of_property_read_u32(node, "xlnx,nidru-refclk-sel", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,nidru-refclk-sel not specified"); + return -EINVAL; + } if (vphydev->isvphy) vphycfg->DruRefClkSel = val; else xgtphycfg->DruRefClkSel = val; rc = of_property_read_u32(node, "xlnx,rx-no-of-channels", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,rx-no-of-channels not specified"); + return -EINVAL; + } if (vphydev->isvphy) vphycfg->RxChannels = val; else xgtphycfg->RxChannels = val; rc = of_property_read_u32(node, "xlnx,tx-no-of-channels", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,tx-no-of-channels not specified"); + return -EINVAL; + } if (vphydev->isvphy) vphycfg->TxChannels = val; else xgtphycfg->TxChannels = val; rc = of_property_read_u32(node, "xlnx,rx-protocol", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,rx-protocol not specified"); + return -EINVAL; + } if (vphydev->isvphy) vphycfg->RxProtocol = val; else xgtphycfg->RxProtocol = val; rc = of_property_read_u32(node, "xlnx,tx-protocol", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,tx-protocol not specified"); + return -EINVAL; + } if (vphydev->isvphy) vphycfg->TxProtocol = val; else xgtphycfg->TxProtocol = val; rc = of_property_read_u32(node, "xlnx,rx-refclk-sel", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,rx-refclk-sel not specified"); + return -EINVAL; + } if (vphydev->isvphy) vphycfg->RxRefClkSel = val; else xgtphycfg->RxRefClkSel = val; rc = of_property_read_u32(node, "xlnx,tx-refclk-sel", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,tx-refclk-sel not specified"); + return -EINVAL; + } if (vphydev->isvphy) vphycfg->TxRefClkSel = val; else xgtphycfg->TxRefClkSel = val; rc = of_property_read_u32(node, "xlnx,rx-pll-selection", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,rx-pll-selection not specified"); + return -EINVAL; + } if (vphydev->isvphy) vphycfg->RxSysPllClkSel = val; else xgtphycfg->RxSysPllClkSel = val; rc = of_property_read_u32(node, "xlnx,tx-pll-selection", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,tx-pll-selection not specified"); + return -EINVAL; + } if (vphydev->isvphy) vphycfg->TxSysPllClkSel = val; else xgtphycfg->TxSysPllClkSel = val; rc = of_property_read_u32(node, "xlnx,hdmi-fast-switch", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,hdmi-fast-switch not specified"); + return -EINVAL; + } if (vphydev->isvphy) vphycfg->HdmiFastSwitch = val; else xgtphycfg->HdmiFastSwitch = val; rc = of_property_read_u32(node, "xlnx,transceiver-width", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,transceiver-width not specified"); + return -EINVAL; + } if (vphydev->isvphy) vphycfg->TransceiverWidth = val; else @@ -515,8 +545,10 @@ static int vphy_parse_of(struct xvphy_dev *vphydev, void *c) xgtphycfg->ErrIrq = has_err_irq; rc = of_property_read_u32(node, "xlnx,use-gt-ch4-hdmi", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,use-gt-ch4-hdmi not specified"); + return -EINVAL; + } if (vphydev->isvphy) vphycfg->UseGtAsTxTmdsClk = val; else @@ -524,21 +556,21 @@ static int vphy_parse_of(struct xvphy_dev *vphydev, void *c) if (!vphydev->isvphy) { rc = of_property_read_u32(node, "xlnx,rx-frl-refclk-sel", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,rx-frl-refclk-sel not specified"); + return -EINVAL; + } xgtphycfg->RxFrlRefClkSel = val; rc = of_property_read_u32(node, "xlnx,tx-frl-refclk-sel", &val); - if (rc < 0) - goto error_dt; + if (rc < 0) { + dev_err(vphydev->dev, "Error parsing device tree: xlnx,tx-frl-refclk-sel not specified"); + return -EINVAL; + } xgtphycfg->TxFrlRefClkSel = val; } return 0; - -error_dt: - dev_err(vphydev->dev, "Error parsing device tree"); - return -EINVAL; } /* Match table for of_platform binding */