diff options
author | Rohit Consul <rohit.consul@xilinx.com> | 2017-08-02 16:05:19 -0700 |
---|---|---|
committer | Michal Simek <michal.simek@xilinx.com> | 2017-08-03 12:08:47 +0200 |
commit | a0892f4a67a0d89330a4ea6cb7e59f53ff6ac1ea (patch) | |
tree | 5deb4a28664388764ca43097acde35cec28acfb9 | |
parent | 7437a36ebb3dc99f4ae5099af0a953f4e0bd6598 (diff) | |
download | linux-a0892f4a67a0d89330a4ea6cb7e59f53ff6ac1ea.tar.gz |
drm: xilinx-hdmi-tx: Fix multiple instance support
Bug fix to support multiple instances of Tx IP.
Added updates for 2017.2.
Signed-off-by: Rohit Consul <rohit.consul@xilinx.com>
6 files changed, 247 insertions, 148 deletions
diff --git a/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitx.h b/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitx.h index 54b0e47370778f..12567b82ed5018 100644 --- a/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitx.h +++ b/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitx.h @@ -852,6 +852,135 @@ typedef struct { (XV_HDMITX_PIO_IN_OFFSET) ) ) >> (XV_HDMITX_PIO_IN_PPP_SHIFT)) \ & (XV_HDMITX_PIO_IN_PPP_MASK)) +/*****************************************************************************/ +/** +* +* This macro disables video mask in HDMI TX core. +* +* @param InstancePtr is a pointer to the XV_HdmiTx core instance. +* +* @return None. +* +* @note C-style signature: +* void XV_HdmiTx_MaskDisable(XV_HdmiTx *InstancePtr) +* +******************************************************************************/ +#define XV_HdmiTx_MaskDisable(InstancePtr) \ +{ \ + XV_HdmiTx_WriteReg((InstancePtr)->Config.BaseAddress, \ + (XV_HDMITX_MASK_CTRL_CLR_OFFSET), (XV_HDMITX_MASK_CTRL_RUN_MASK)); \ +} + +/*****************************************************************************/ +/** +* +* This macro enables video mask in HDMI TX core. +* +* @param InstancePtr is a pointer to the XV_HdmiTx core instance. +* +* @return None. +* +* @note C-style signature: +* void XV_HdmiTx_MaskEnable(XV_HdmiTx *InstancePtr) +* +******************************************************************************/ +#define XV_HdmiTx_MaskEnable(InstancePtr) \ +{ \ + XV_HdmiTx_WriteReg((InstancePtr)->Config.BaseAddress, \ + (XV_HDMITX_MASK_CTRL_SET_OFFSET), (XV_HDMITX_MASK_CTRL_RUN_MASK)); \ +} + +/*****************************************************************************/ +/** +* +* This macro enables or disables the noise in the video mask. +* +* @param InstancePtr is a pointer to the XHdmi_Tx core instance. +* @param SetClr specifies TRUE/FALSE value to either enable or disable the +* Noise. +* +* @return None. +* +* @note C-style signature: +* void XV_HdmiTx_MaskNoise(XV_HdmiTx *InstancePtr, u8 SetClr) +* +******************************************************************************/ +#define XV_HdmiTx_MaskNoise(InstancePtr, SetClr) \ +{ \ + if (SetClr) { \ + XV_HdmiTx_WriteReg((InstancePtr)->Config.BaseAddress, \ + (XV_HDMITX_MASK_CTRL_SET_OFFSET), \ + (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)); \ + } \ +} + +/*****************************************************************************/ +/** +* +* This macro sets the red component value in the video mask. +* +* @param InstancePtr is a pointer to the XHdmi_Tx core instance. +* @param Value +* +* @return None. +* +* @note C-style signature: +* void XV_HdmiTx_MaskSetRed(XV_HdmiTx *InstancePtr, u16 Value) +* +******************************************************************************/ +#define XV_HdmiTx_MaskSetRed(InstancePtr, Value) \ +{ \ + XV_HdmiTx_WriteReg((InstancePtr)->Config.BaseAddress, \ + (XV_HDMITX_MASK_RED_OFFSET), \ + (Value)); \ +} + +/*****************************************************************************/ +/** +* +* This macro sets the green component value in the video mask. +* +* @param InstancePtr is a pointer to the XHdmi_Tx core instance. +* @param Value +* +* @return None. +* +* @note C-style signature: +* void XV_HdmiTx_MaskSetGreen(XV_HdmiTx *InstancePtr, u16 Value) +* +******************************************************************************/ +#define XV_HdmiTx_MaskSetGreen(InstancePtr, Value) \ +{ \ + XV_HdmiTx_WriteReg((InstancePtr)->Config.BaseAddress, \ + (XV_HDMITX_MASK_GREEN_OFFSET), \ + (Value)); \ +} + +/*****************************************************************************/ +/** +* +* This macro sets the blue component value in the video mask. +* +* @param InstancePtr is a pointer to the XHdmi_Tx core instance. +* @param Value +* +* @return None. +* +* @note C-style signature: +* void XV_HdmiTx_MaskSetBlue(XV_HdmiTx *InstancePtr, u16 Value) +* +******************************************************************************/ +#define XV_HdmiTx_MaskSetBlue(InstancePtr, Value) \ +{ \ + XV_HdmiTx_WriteReg((InstancePtr)->Config.BaseAddress, \ + (XV_HDMITX_MASK_BLUE_OFFSET), \ + (Value)); \ +} /************************** Function Prototypes ******************************/ /* Initialization function in xv_hdmitx_sinit.c */ diff --git a/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitx_hw.h b/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitx_hw.h index eb2a621f76ea85..a055bb5ffe4671 100644 --- a/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitx_hw.h +++ b/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitx_hw.h @@ -253,6 +253,30 @@ extern "C" { // Audio peripheral Status register masks #define XV_HDMITX_AUD_STA_IRQ_MASK (1<<0) /**< AUD Status Interrupt mask */ +// Video Mask (MASK) peripheral register offsets +// The mask is the fifth peripheral on the local bus +#define XV_HDMITX_MASK_BASE (5*64) +#define XV_HDMITX_MASK_ID_OFFSET ((XV_HDMITX_MASK_BASE)+(0*4)) /**< MASK + * Identification * Register offset */ +#define XV_HDMITX_MASK_CTRL_OFFSET ((XV_HDMITX_MASK_BASE)+(1*4)) /**< MASK + * Control Register * offset */ +#define XV_HDMITX_MASK_CTRL_SET_OFFSET ((XV_HDMITX_MASK_BASE)+(2*4)) /**< MASK + * Control Register Set * offset */ +#define XV_HDMITX_MASK_CTRL_CLR_OFFSET ((XV_HDMITX_MASK_BASE)+(3*4)) /**< MASK + * Control Register Clear * offset */ +#define XV_HDMITX_MASK_STA_OFFSET ((XV_HDMITX_MASK_BASE)+(4*4)) /**< MASK + * Status Register * offset */ +#define XV_HDMITX_MASK_RED_OFFSET ((XV_HDMITX_MASK_BASE)+(5*4)) /**< MASK + * Red Component Register * offset */ +#define XV_HDMITX_MASK_GREEN_OFFSET ((XV_HDMITX_MASK_BASE)+(6*4)) /**< MASK + * Green Component Register * offset */ +#define XV_HDMITX_MASK_BLUE_OFFSET ((XV_HDMITX_MASK_BASE)+(7*4)) /**< MASK + * Blue Component Register * offset */ + +// Video mask peripheral Control register masks +#define XV_HDMITX_MASK_CTRL_RUN_MASK (1<<0) /**< MASK Control Run mask */ +#define XV_HDMITX_MASK_CTRL_NOISE_MASK (1<<2) /**< MASK Control Noise */ + // Peripheral ID and General shift values. #define XV_HDMITX_SHIFT_16 16 /**< 16 shift value */ #define XV_HDMITX_MASK_16 0xFFFF /**< 16 bit mask value */ diff --git a/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitxss.c b/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitxss.c index baafe3e9b12328..2ab8580ee23fc3 100644 --- a/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitxss.c +++ b/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitxss.c @@ -180,6 +180,11 @@ static void XV_HdmiTxSs_ConfigBridgeMode(XV_HdmiTxSs *InstancePtr); void XV_HdmiTxSS_SetHdmiMode(XV_HdmiTxSs *InstancePtr) { XV_HdmiTx_SetHdmiMode(InstancePtr->HdmiTxPtr); +#ifdef XPAR_XHDCP_NUM_INSTANCES + if (InstancePtr->Hdcp14Ptr) { + XHdcp1x_SetHdmiMode(InstancePtr->Hdcp14Ptr, TRUE); + } +#endif } /*****************************************************************************/ @@ -192,6 +197,12 @@ void XV_HdmiTxSS_SetHdmiMode(XV_HdmiTxSs *InstancePtr) void XV_HdmiTxSS_SetDviMode(XV_HdmiTxSs *InstancePtr) { XV_HdmiTx_SetDviMode(InstancePtr->HdmiTxPtr); + +#ifdef XPAR_XHDCP_NUM_INSTANCES + if (InstancePtr->Hdcp14Ptr) { + XHdcp1x_SetHdmiMode(InstancePtr->Hdcp14Ptr, FALSE); + } +#endif } /*****************************************************************************/ diff --git a/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitxss_coreinit.c b/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitxss_coreinit.c index b279fd1113a120..cac3bc436fe9f7 100644 --- a/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitxss_coreinit.c +++ b/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitxss_coreinit.c @@ -103,6 +103,8 @@ int XV_HdmiTxSs_SubcoreInitHdmiTx(XV_HdmiTxSs *HdmiTxSsPtr) "HDMITXSS ERR:: HDMI TX Initialization failed\r\n"); return(XST_FAILURE); } + /* Set default transmitter mode to HDMI */ + XV_HdmiTxSS_SetHdmiMode(HdmiTxSsPtr); } return(XST_SUCCESS); } diff --git a/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitxss_hdcp.c b/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitxss_hdcp.c index b5067969f93eec..2a4a787d3ded1f 100644 --- a/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitxss_hdcp.c +++ b/drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitxss_hdcp.c @@ -1134,12 +1134,7 @@ int XV_HdmiTxSs_HdcpDisableBlank(XV_HdmiTxSs *InstancePtr) /*****************************************************************************/ /** * -* This function determines if the connected HDMI sink has HDCP 1.4 capabilities. -* The sink is determined to be HDCP 1.4 capable the BKSV indicates 20 ones and -* 20 zeros. If the sink is capable of HDCP 1.4, then this function checks if -* the Bcaps register indicates that the connected device a DVI or HDMI receiver. -* If the receiver is determined to be HDMI, then the function will return FALSE -* until the receiver has set the HDMI_MODE in the Bstatus register. +* This function determines if the connected HDMI sink is HDCP 1.4 capable * * @param InstancePtr is a pointer to the XV_HdmiTxSs instance. * @@ -1154,53 +1149,13 @@ u8 XV_HdmiTxSs_IsSinkHdcp14Capable(XV_HdmiTxSs *InstancePtr) Xil_AssertNonvoid(InstancePtr != NULL); #ifdef XPAR_XHDCP_NUM_INSTANCES - int status; - u8 buffer[5]; - u8 temp = 0; - int zero_count = 0; - int one_count = 0; - int i,j; - if (InstancePtr->Hdcp14Ptr) { - buffer[0] = 0x0; // XHDCP14_BKSV_REG - status = XV_HdmiTx_DdcWrite(InstancePtr->HdmiTxPtr, - 0x3A, - 1, - (u8*)&buffer, - FALSE); - if (status != XST_SUCCESS) - return FALSE; - - /* Read the receiver KSV and count the number of ones and zeros. - A valid KSV has 20 ones and 20 zeros. */ - status = XV_HdmiTx_DdcRead(InstancePtr->HdmiTxPtr, - 0x3A, - 5, - (u8*)&buffer, - TRUE); - if (status != XST_SUCCESS) - return FALSE; - - for(i = 0; i < 5; i++) { - temp = buffer[i]; - - for(j = 0; j < 8; j++) { - if(temp & 0x1) - one_count++; - else - zero_count++; - - temp = temp >> 1; - } - } - - if (one_count != 20 || zero_count != 20) - return FALSE; - - /* Check if the sink device is ready to authenticate */ if (XHdcp1x_IsDwnstrmCapable(InstancePtr->Hdcp14Ptr)) { return TRUE; } + else { + return FALSE; + } } else { return FALSE; @@ -1228,25 +1183,13 @@ u8 XV_HdmiTxSs_IsSinkHdcp22Capable(XV_HdmiTxSs *InstancePtr) Xil_AssertNonvoid(InstancePtr != NULL); #ifdef XPAR_XHDCP22_TX_NUM_INSTANCES - int status; - u8 data = 0x50; // XHDCP2_VERSION_REG - if (InstancePtr->Hdcp22Ptr) { - /* Write the register offset */ - status = XV_HdmiTx_DdcWrite(InstancePtr->HdmiTxPtr, 0x3A, 1, (u8*)&data, FALSE); - if (status != XST_SUCCESS) - return FALSE; - - /* Read the HDCP2 version */ - status = XV_HdmiTx_DdcRead(InstancePtr->HdmiTxPtr, 0x3A, 1, (u8*)&data, TRUE); - if (status != XST_SUCCESS) - return FALSE; - - /* Check the HDCP2.2 version */ - if(data & 0x4) + if (XHdcp22Tx_IsDwnstrmCapable(InstancePtr->Hdcp22Ptr)) { return TRUE; - else + } + else { return FALSE; + } } else { return FALSE; diff --git a/drivers/staging/xilinx/hdmi/xilinx_drm_hdmi.c b/drivers/staging/xilinx/hdmi/xilinx_drm_hdmi.c index 1b7c68f49c37dc..7d5f727611a888 100644 --- a/drivers/staging/xilinx/hdmi/xilinx_drm_hdmi.c +++ b/drivers/staging/xilinx/hdmi/xilinx_drm_hdmi.c @@ -160,13 +160,13 @@ void HdmiTx_PioIntrHandler(XV_HdmiTx *InstancePtr); void HdmiTx_DdcIntrHandler(XV_HdmiTx *InstancePtr); void HdmiTx_AuxIntrHandler(XV_HdmiTx *InstancePtr); -void XV_HdmiTxSs_IntrEnable(XV_HdmiTxSs *HdmiTxSsPtr) +static void XV_HdmiTxSs_IntrEnable(XV_HdmiTxSs *HdmiTxSsPtr) { XV_HdmiTx_PioIntrEnable(HdmiTxSsPtr->HdmiTxPtr); XV_HdmiTx_DdcIntrEnable(HdmiTxSsPtr->HdmiTxPtr); } -void XV_HdmiTxSs_IntrDisable(XV_HdmiTxSs *HdmiTxSsPtr) +static void XV_HdmiTxSs_IntrDisable(XV_HdmiTxSs *HdmiTxSsPtr) { XV_HdmiTx_PioIntrDisable(HdmiTxSsPtr->HdmiTxPtr); XV_HdmiTx_DdcIntrDisable(HdmiTxSsPtr->HdmiTxPtr); @@ -241,6 +241,17 @@ static irqreturn_t hdmitx_irq_thread(int irq, void *dev_id) return IRQ_HANDLED; } +static void TxToggleCallback(void *CallbackRef) +{ + struct xilinx_drm_hdmi *xhdmi = (struct xilinx_drm_hdmi *)CallbackRef; + BUG_ON(!xhdmi); + + XV_HdmiTxSs *HdmiTxSsPtr = &xhdmi->xv_hdmitxss; + BUG_ON(!HdmiTxSsPtr); + hdmi_dbg("TxToggleCallback()\n"); + + XV_HdmiTxSs_StreamStart(HdmiTxSsPtr); +} static void TxConnectCallback(void *CallbackRef) { @@ -263,6 +274,7 @@ static void TxConnectCallback(void *CallbackRef) (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)); + XV_HdmiTxSs_StreamStart(HdmiTxSsPtr); } else { hdmi_dbg("TxConnectCallback(): TX disconnected\n"); @@ -281,7 +293,9 @@ static void TxStreamUpCallback(void *CallbackRef) struct xilinx_drm_hdmi *xhdmi = (struct xilinx_drm_hdmi *)CallbackRef; XVphy *VphyPtr; XV_HdmiTxSs *HdmiTxSsPtr; +#ifdef DEBUG XVidC_VideoStream *HdmiTxSsVidStreamPtr; +#endif XVphy_PllType TxPllType; u64 TxLineRate; @@ -329,6 +343,7 @@ static void TxStreamUpCallback(void *CallbackRef) HdmiTxSsVidStreamPtr = XV_HdmiTxSs_GetVideoStream(HdmiTxSsPtr); XVidC_ReportStreamInfo(HdmiTxSsVidStreamPtr); #endif + hdmi_dbg("TxStreamUpCallback(): done\n"); } static void TxStreamDownCallback(void *CallbackRef) @@ -647,10 +662,10 @@ static void xilinx_drm_hdmi_mode_set(struct drm_encoder *encoder, return; } - /* Enable si5324 LOL signal (disable gpio override) */ - hdmi_dbg("force phy freq change event: TxRefClkRdy = High\n"); - gpiod_set_value_cansleep(xhdmi->freqchg_gpio, (is_gpio_active_low) ? - XVPHY_TXREFCLK_RDY_LOW : XVPHY_TXREFCLK_RDY_HIGH); + /* Enable si5324 LOL signal (disable gpio override) */ + hdmi_dbg("force phy freq change event: TxRefClkRdy = High\n"); + gpiod_set_value_cansleep(xhdmi->freqchg_gpio, (is_gpio_active_low) ? + XVPHY_TXREFCLK_RDY_LOW : XVPHY_TXREFCLK_RDY_HIGH); adjusted_mode->clock = VphyPtr->HdmiTxRefClkHz / 1000; hdmi_dbg("adjusted_mode->clock = %u Hz\n", adjusted_mode->clock); @@ -791,9 +806,6 @@ static struct drm_encoder_slave_funcs xilinx_drm_hdmi_encoder_funcs = { .get_modes = xilinx_drm_hdmi_get_modes, }; -/* forward declaration */ -static XV_HdmiTxSs_Config config; - static int xilinx_drm_hdmi_encoder_init(struct platform_device *pdev, struct drm_device *dev, struct drm_encoder_slave *encoder) @@ -820,7 +832,7 @@ static int xilinx_drm_hdmi_encoder_init(struct platform_device *pdev, BUG_ON(!HdmiTxSsPtr); - Status = XV_HdmiTxSs_CfgInitialize(HdmiTxSsPtr, &config, (uintptr_t)xhdmi->iomem); + Status = XV_HdmiTxSs_CfgInitialize(HdmiTxSsPtr, &xhdmi->config, (uintptr_t)xhdmi->iomem); if (Status != XST_SUCCESS) { dev_err(xhdmi->dev, "initialization failed with error %d\n", Status); @@ -834,6 +846,8 @@ static int xilinx_drm_hdmi_encoder_init(struct platform_device *pdev, /* TX SS callback setup */ XV_HdmiTxSs_SetCallback(HdmiTxSsPtr, XV_HDMITXSS_HANDLER_CONNECT, TxConnectCallback, (void *)xhdmi); + XV_HdmiTxSs_SetCallback(HdmiTxSsPtr, XV_HDMITXSS_HANDLER_TOGGLE, + TxToggleCallback, (void *)xhdmi); XV_HdmiTxSs_SetCallback(HdmiTxSsPtr, XV_HDMITXSS_HANDLER_VS, TxVsCallback, (void *)xhdmi); XV_HdmiTxSs_SetCallback(HdmiTxSsPtr, XV_HDMITXSS_HANDLER_STREAM_UP, @@ -873,40 +887,14 @@ static int xilinx_drm_hdmi_encoder_init(struct platform_device *pdev, return 0; } -static XV_HdmiTxSs_Config config = -{ - .DeviceId = 0, - .BaseAddress = 0, - .HighAddress = 0, - .Ppc = 2, - .MaxBitsPerPixel = 8, - .AxiLiteClkFreq = 50000000, - .HdcpTimer = { - .IsPresent = 0, - .DeviceId = 255, - .AbsAddr = 0 - }, - .Hdcp14 = { - .IsPresent = 0, - .DeviceId = 255, - .AbsAddr = 0 - }, - .Hdcp22 = { - .IsPresent = 0, - .DeviceId = 255, - .AbsAddr = 0 - }, - .HdmiTx = { - .IsPresent = 1, - .DeviceId = 0, - .AbsAddr = 0 - }, - .Vtc = { - .IsPresent = 1, - .DeviceId = 0, - .AbsAddr = 0, - }, -}; +/* ----------------------------------------------------------------------------- + * Platform Device Driver + */ + +static int instance = 0; +/* TX uses [1, 127] and RX uses [128, 254] */ +/* The HDCP22 timer uses an additional offset of +64 */ +#define TX_DEVICE_ID_BASE 1 /* Local Global table for all sub-core instance(s) configuration settings */ XVtc_Config XVtc_ConfigTable[XPAR_XVTC_NUM_INSTANCES]; @@ -936,43 +924,34 @@ static int xhdmi_drm_subcore_AbsAddr(uintptr_t SubSys_BaseAddr, /* Each sub-core within the subsystem has defined offset read from device-tree. */ -static int xhdmi_drm_compute_subcore_AbsAddr(uintptr_t SubSys_BaseAddr, - uintptr_t SubSys_HighAddr ) +static int xhdmi_drm_compute_subcore_AbsAddr(XV_HdmiTxSs_Config *config) { int ret; /* Subcore: Tx */ - ret = xhdmi_drm_subcore_AbsAddr(SubSys_BaseAddr, - SubSys_HighAddr, - config.HdmiTx.AbsAddr, - &config.HdmiTx.AbsAddr); + ret = xhdmi_drm_subcore_AbsAddr(config->BaseAddress, + config->HighAddress, + config->HdmiTx.AbsAddr, + &(config->HdmiTx.AbsAddr)); if (ret != XST_SUCCESS) { hdmi_dbg("hdmitx sub-core address out-of range\n"); return -EFAULT; } + XV_HdmiTx_ConfigTable[instance].BaseAddress = config->HdmiTx.AbsAddr; /* Subcore: Vtc */ - ret = xhdmi_drm_subcore_AbsAddr(SubSys_BaseAddr, - SubSys_HighAddr, - config.Vtc.AbsAddr, - &config.Vtc.AbsAddr); + ret = xhdmi_drm_subcore_AbsAddr(config->BaseAddress, + config->HighAddress, + config->Vtc.AbsAddr, + &(config->Vtc.AbsAddr)); if (ret != XST_SUCCESS) { hdmi_dbg("vtc sub-core address out-of range\n"); return -EFAULT; } - + XVtc_ConfigTable[instance].BaseAddress = config->Vtc.AbsAddr; return (ret); } -/* ----------------------------------------------------------------------------- - * Platform Device Driver - */ - -static int instance = 0; -/* TX uses [1, 127] and RX uses [128, 254] */ -/* The HDCP22 timer uses an additional offset of +64 */ -#define TX_DEVICE_ID_BASE 1 - static int xilinx_drm_hdmi_parse_of(struct xilinx_drm_hdmi *xhdmi, XV_HdmiTxSs_Config *config) { struct device *dev = xhdmi->dev; @@ -992,7 +971,9 @@ static int xilinx_drm_hdmi_parse_of(struct xilinx_drm_hdmi *xhdmi, XV_HdmiTxSs_C config->MaxBitsPerPixel = val; rc = of_property_read_u32(node, "xlnx,hdmi-tx-offset", &val); - if (rc == 0) { + if (rc < 0) { + goto error_dt; + } else if (rc == 0) { config->HdmiTx.DeviceId = TX_DEVICE_ID_BASE + instance; config->HdmiTx.IsPresent = 1; config->HdmiTx.AbsAddr = val; @@ -1002,8 +983,7 @@ static int xilinx_drm_hdmi_parse_of(struct xilinx_drm_hdmi *xhdmi, XV_HdmiTxSs_C rc = of_property_read_u32(node, "xlnx,vtc-offset", &val); if (rc < 0) { - hdmi_dbg("Not using an internal VTC."); - config->Vtc.IsPresent = 0; + goto error_dt; } else if (rc == 0) { config->Vtc.IsPresent = 1; config->Vtc.DeviceId = TX_DEVICE_ID_BASE + instance; @@ -1046,7 +1026,7 @@ static int xilinx_drm_hdmi_probe(struct platform_device *pdev) struct resource *res; unsigned long axi_clk_rate; - hdmi_dbg("hdmi-tx probed\n"); + dev_info(&pdev->dev, "xlnx-hdmi-tx probed\n"); /* allocate zeroed HDMI TX device structure */ xhdmi = devm_kzalloc(&pdev->dev, sizeof(*xhdmi), GFP_KERNEL); if (!xhdmi) @@ -1066,7 +1046,7 @@ static int xilinx_drm_hdmi_probe(struct platform_device *pdev) hdmi_dbg("xilinx_drm_hdmi DT parse start\n"); /* parse open firmware device tree data */ - ret = xilinx_drm_hdmi_parse_of(xhdmi, &config); + ret = xilinx_drm_hdmi_parse_of(xhdmi, &xhdmi->config); if (ret < 0) return ret; hdmi_dbg("xilinx_drm_hdmi DT parse done\n"); @@ -1080,7 +1060,7 @@ static int xilinx_drm_hdmi_probe(struct platform_device *pdev) ret = PTR_ERR(xhdmi->phy[index]); xhdmi->phy[index] = NULL; if (ret == -EPROBE_DEFER) { - hdmi_dbg("xvphy not ready -EPROBE_DEFER\n"); + dev_info(xhdmi->dev, "xvphy not ready -EPROBE_DEFER\n"); return ret; } if (ret != -EPROBE_DEFER) @@ -1102,12 +1082,12 @@ static int xilinx_drm_hdmi_probe(struct platform_device *pdev) if (IS_ERR(xhdmi->iomem)) return PTR_ERR(xhdmi->iomem); - config.BaseAddress = (uintptr_t)xhdmi->iomem; - config.HighAddress = config.BaseAddress + resource_size(res) - 1; + xhdmi->config.DeviceId = instance; + xhdmi->config.BaseAddress = (uintptr_t)xhdmi->iomem; + xhdmi->config.HighAddress = xhdmi->config.BaseAddress + resource_size(res) - 1; /* Compute sub-core AbsAddres */ - ret = xhdmi_drm_compute_subcore_AbsAddr(config.BaseAddress, - config.HighAddress); + ret = xhdmi_drm_compute_subcore_AbsAddr(&xhdmi->config); if (ret == -EFAULT) { dev_err(xhdmi->dev, "hdmi-tx sub-core address out-of range\n"); return ret; @@ -1118,7 +1098,7 @@ static int xilinx_drm_hdmi_probe(struct platform_device *pdev) if (IS_ERR(xhdmi->clk)) { ret = PTR_ERR(xhdmi->clk); if (ret == -EPROBE_DEFER) - hdmi_dbg("video-clk not ready -EPROBE_DEFER\n"); + dev_info(xhdmi->dev, "video-clk not ready -EPROBE_DEFER\n"); if (ret != -EPROBE_DEFER) dev_err(xhdmi->dev, "failed to get video clk\n"); return ret; @@ -1131,7 +1111,7 @@ static int xilinx_drm_hdmi_probe(struct platform_device *pdev) if (IS_ERR(xhdmi->axi_lite_clk)) { ret = PTR_ERR(xhdmi->clk); if (ret == -EPROBE_DEFER) - hdmi_dbg("axi-lite-clk not ready -EPROBE_DEFER\n"); + dev_info(xhdmi->dev, "axi-lite-clk not ready -EPROBE_DEFER\n"); if (ret != -EPROBE_DEFER) dev_err(xhdmi->dev, "failed to get axi-lite clk\n"); return ret; @@ -1140,7 +1120,7 @@ static int xilinx_drm_hdmi_probe(struct platform_device *pdev) clk_prepare_enable(xhdmi->axi_lite_clk); axi_clk_rate = clk_get_rate(xhdmi->axi_lite_clk); hdmi_dbg("axi_clk_rate = %lu Hz\n", axi_clk_rate); - config.AxiLiteClkFreq = axi_clk_rate; + xhdmi->config.AxiLiteClkFreq = axi_clk_rate; /* get irq */ xhdmi->irq = platform_get_irq(pdev, 0); @@ -1156,15 +1136,15 @@ static int xilinx_drm_hdmi_probe(struct platform_device *pdev) ret = PTR_ERR(xhdmi->retimer_clk); xhdmi->retimer_clk = NULL; if (ret == -EPROBE_DEFER) - hdmi_dbg("retimer-clk not ready -EPROBE_DEFER\n"); + dev_info(xhdmi->dev, "retimer-clk not ready -EPROBE_DEFER\n"); if (ret != -EPROBE_DEFER) - hdmi_dbg("Did not find a retimer-clk, not driving an external retimer device driver.\n"); + dev_err(xhdmi->dev, "Did not find a retimer-clk, not driving an external retimer device driver.\n"); return ret; } else if (xhdmi->retimer_clk) { hdmi_dbg("got retimer-clk\n"); ret = clk_prepare_enable(xhdmi->retimer_clk); if (ret) { - dev_err(&pdev->dev, "failed to enable retimer-clk\n"); + dev_err(xhdmi->dev, "failed to enable retimer-clk\n"); return ret; } hdmi_dbg("prepared and enabled retimer-clk\n"); @@ -1178,9 +1158,9 @@ static int xilinx_drm_hdmi_probe(struct platform_device *pdev) if (IS_ERR(xhdmi->freqchg_gpio)) { ret = (IS_ERR(xhdmi->freqchg_gpio)); if (ret == -EPROBE_DEFER) - hdmi_dbg("gpio tx_refclk_rdy_en not ready -EPROBE_DEFER\n"); + dev_info(xhdmi->dev, "gpio tx_refclk_rdy_en not ready -EPROBE_DEFER\n"); if (ret != EPROBE_DEFER) - dev_err(&pdev->dev, "ERROR failed to locate gpio tx_refclk_rdy_en in dt\n"); + dev_err(xhdmi->dev, "ERROR failed to locate gpio tx_refclk_rdy_en in dt\n"); return ret; } @@ -1191,11 +1171,21 @@ static int xilinx_drm_hdmi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, xhdmi); /* remainder of initialization is in encoder_init() */ - hdmi_dbg("hdmi-tx probe successful\n"); + dev_info(xhdmi->dev, "xlnx-hdmi-txss probe successful\n"); /* probe has succeeded for this instance, increment instance index */ instance++; return 0; + error_phy: + printk(KERN_INFO "xhdmitx_probe() error_phy:\n"); + index = 0; + /* release the lanes that we did get, if we did not get all lanes */ + if (xhdmi->phy[index]) { + printk(KERN_INFO "phy_exit() xhdmi->phy[%d] = %p\n", index, xhdmi->phy[index]); + phy_exit(xhdmi->phy[index]); + xhdmi->phy[index] = NULL; + } + return ret; } |