MLK-19413-30 drm/imx: hdp: Add dual mode support
authorLiu Ying <victor.liu@nxp.com>
Thu, 30 Aug 2018 08:21:39 +0000 (16:21 +0800)
committerLeonard Crestez <leonard.crestez@nxp.com>
Wed, 17 Apr 2019 23:51:34 +0000 (02:51 +0300)
This patch adds dual mode support in the i.MX HDP driver.
The single mode and dual mode can be switched dynamically
according to the input video mode(pixel clock rate and
active horizontal display width).

Signed-off-by: Liu Ying <victor.liu@nxp.com>
drivers/gpu/drm/imx/hdp/imx-hdp.c
drivers/gpu/drm/imx/hdp/imx-hdp.h

index def6934..d2d391b 100644 (file)
@@ -66,6 +66,12 @@ static inline struct imx_hdp *enc_to_imx_hdp(struct drm_encoder *e)
        return container_of(e, struct imx_hdp, encoder);
 }
 
+static inline bool imx_hdp_is_dual_mode(struct drm_display_mode *mode)
+{
+       return (mode->clock > HDP_DUAL_MODE_MIN_PCLK_RATE ||
+               mode->hdisplay > HDP_SINGLE_MODE_MAX_WIDTH) ? true : false;
+}
+
 static void imx_hdp_state_init(struct imx_hdp *hdp)
 {
        state_struct *state = &hdp->state;
@@ -100,7 +106,9 @@ static void imx8qm_pixel_link_mux(state_struct *state, struct drm_display_mode *
        struct imx_hdp *hdp = state_to_imx_hdp(state);
        u32 val;
 
-       val = 4; /* RGB */
+       val = 0x4;      /* RGB */
+       if (hdp->dual_mode)
+               val |= 0x2;     /* pixel link 0 and 1 are active */
        if (mode->flags & DRM_MODE_FLAG_PVSYNC)
                val |= 1 << PL_MUX_CTL_VCP_OFFSET;
        if (mode->flags & DRM_MODE_FLAG_PHSYNC)
@@ -134,6 +142,14 @@ static int imx8qm_pixel_link_validate(state_struct *state)
                DRM_ERROR("SC_R_DC_0:SC_C_PXL_LINK_MST1_VLD sc_misc_set_control failed! (sciError = %d)\n", sciErr);
                return -EINVAL;
        }
+       if (hdp->dual_mode) {
+               sciErr = sc_misc_set_control(hdp->ipcHndl, SC_R_DC_0,
+                                               SC_C_PXL_LINK_MST2_VLD, 1);
+               if (sciErr != SC_ERR_NONE) {
+                       DRM_ERROR("SC_R_DC_0:SC_C_PXL_LINK_MST2_VLD sc_misc_set_control failed! (sciError = %d)\n", sciErr);
+                       return -EINVAL;
+               }
+       }
 
        sc_ipc_close(hdp->mu_id);
 
@@ -162,6 +178,14 @@ static int imx8qm_pixel_link_invalidate(state_struct *state)
                DRM_ERROR("SC_R_DC_0:SC_C_PXL_LINK_MST1_VLD sc_misc_set_control failed! (sciError = %d)\n", sciErr);
                return -EINVAL;
        }
+       if (hdp->dual_mode) {
+               sciErr = sc_misc_set_control(hdp->ipcHndl, SC_R_DC_0,
+                                               SC_C_PXL_LINK_MST2_VLD, 0);
+               if (sciErr != SC_ERR_NONE) {
+                       DRM_ERROR("SC_R_DC_0:SC_C_PXL_LINK_MST2_VLD sc_misc_set_control failed! (sciError = %d)\n", sciErr);
+                       return -EINVAL;
+               }
+       }
 
        sc_ipc_close(hdp->mu_id);
 
@@ -185,10 +209,18 @@ static int imx8qm_pixel_link_sync_ctrl_enable(state_struct *state)
                return -EINVAL;
        }
 
-       sciErr = sc_misc_set_control(hdp->ipcHndl, SC_R_DC_0, SC_C_SYNC_CTRL0, 1);
-       if (sciErr != SC_ERR_NONE) {
-               DRM_ERROR("SC_R_DC_0:SC_C_SYNC_CTRL0 sc_misc_set_control failed! (sciError = %d)\n", sciErr);
-               return -EINVAL;
+       if (hdp->dual_mode) {
+               sciErr = sc_misc_set_control(hdp->ipcHndl, SC_R_DC_0, SC_C_SYNC_CTRL, 3);
+               if (sciErr != SC_ERR_NONE) {
+                       DRM_ERROR("SC_R_DC_0:SC_C_SYNC_CTRL sc_misc_set_control failed! (sciError = %d)\n", sciErr);
+                       return -EINVAL;
+               }
+       } else {
+               sciErr = sc_misc_set_control(hdp->ipcHndl, SC_R_DC_0, SC_C_SYNC_CTRL0, 1);
+               if (sciErr != SC_ERR_NONE) {
+                       DRM_ERROR("SC_R_DC_0:SC_C_SYNC_CTRL0 sc_misc_set_control failed! (sciError = %d)\n", sciErr);
+                       return -EINVAL;
+               }
        }
 
        sc_ipc_close(hdp->mu_id);
@@ -213,10 +245,18 @@ static int imx8qm_pixel_link_sync_ctrl_disable(state_struct *state)
                return -EINVAL;
        }
 
-       sciErr = sc_misc_set_control(hdp->ipcHndl, SC_R_DC_0, SC_C_SYNC_CTRL0, 0);
-       if (sciErr != SC_ERR_NONE) {
-               DRM_ERROR("SC_R_DC_0:SC_C_SYNC_CTRL0 sc_misc_set_control failed! (sciError = %d)\n", sciErr);
-               return -EINVAL;
+       if (hdp->dual_mode) {
+               sciErr = sc_misc_set_control(hdp->ipcHndl, SC_R_DC_0, SC_C_SYNC_CTRL, 0);
+               if (sciErr != SC_ERR_NONE) {
+                       DRM_ERROR("SC_R_DC_0:SC_C_SYNC_CTRL sc_misc_set_control failed! (sciError = %d)\n", sciErr);
+                       return -EINVAL;
+               }
+       } else {
+               sciErr = sc_misc_set_control(hdp->ipcHndl, SC_R_DC_0, SC_C_SYNC_CTRL0, 0);
+               if (sciErr != SC_ERR_NONE) {
+                       DRM_ERROR("SC_R_DC_0:SC_C_SYNC_CTRL0 sc_misc_set_control failed! (sciError = %d)\n", sciErr);
+                       return -EINVAL;
+               }
        }
 
        sc_ipc_close(hdp->mu_id);
@@ -662,6 +702,8 @@ static void imx_hdp_bridge_mode_set(struct drm_bridge *bridge,
 
        mutex_lock(&hdp->mutex);
 
+       hdp->dual_mode = imx_hdp_is_dual_mode(mode);
+
        memcpy(&hdp->video.cur_mode, mode, sizeof(hdp->video.cur_mode));
        imx_hdp_mode_setup(hdp, mode);
        /* Store the display mode for plugin/DKMS poweron events */
@@ -1324,8 +1366,6 @@ static int imx_hdp_imx_bind(struct device *dev, struct device *master,
 
        hdp->link_rate = AFE_LINK_RATE_1_6;
 
-       hdp->dual_mode = false;
-
        ret = imx_hdp_call(hdp, clock_init, &hdp->clks);
        if (ret < 0) {
                DRM_ERROR("Failed to initialize clock\n");
index 0f0b946..a0e35e1 100644 (file)
@@ -29,6 +29,9 @@
 #include "../../../../mxc/hdp/all.h"
 #include "../../../../mxc/hdp-cec/imx-hdp-cec.h"
 
+#define HDP_DUAL_MODE_MIN_PCLK_RATE    300000  /* KHz */
+#define HDP_SINGLE_MODE_MAX_WIDTH      1920
+
 /* For testing hdp firmware define DEBUG_FW_LOAD */
 #undef DEBUG_FW_LOAD
 #define PLL_1188MHZ (1188000000)