aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRohit Consul <rohit.consul@xilinx.com>2017-08-02 16:05:19 -0700
committerMichal Simek <michal.simek@xilinx.com>2017-08-03 12:08:47 +0200
commita0892f4a67a0d89330a4ea6cb7e59f53ff6ac1ea (patch)
tree5deb4a28664388764ca43097acde35cec28acfb9
parent7437a36ebb3dc99f4ae5099af0a953f4e0bd6598 (diff)
downloadlinux-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>
-rw-r--r--drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitx.h129
-rw-r--r--drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitx_hw.h24
-rw-r--r--drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitxss.c11
-rw-r--r--drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitxss_coreinit.c2
-rw-r--r--drivers/staging/xilinx/hdmi/xilinx-hdmi-tx/xv_hdmitxss_hdcp.c73
-rw-r--r--drivers/staging/xilinx/hdmi/xilinx_drm_hdmi.c156
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;
}