From 1c30701408c62f2b878c2a661b2b9e91734da41d Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Thu, 30 Aug 2018 16:21:39 +0800 Subject: [PATCH] MLK-19413-30 drm/imx: hdp: Add dual mode support 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 --- drivers/gpu/drm/imx/hdp/imx-hdp.c | 62 +++++++++++++++++++++++++------ drivers/gpu/drm/imx/hdp/imx-hdp.h | 3 ++ 2 files changed, 54 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/imx/hdp/imx-hdp.c b/drivers/gpu/drm/imx/hdp/imx-hdp.c index def6934846c5..d2d391b5fb96 100644 --- a/drivers/gpu/drm/imx/hdp/imx-hdp.c +++ b/drivers/gpu/drm/imx/hdp/imx-hdp.c @@ -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"); diff --git a/drivers/gpu/drm/imx/hdp/imx-hdp.h b/drivers/gpu/drm/imx/hdp/imx-hdp.h index 0f0b9461b091..a0e35e11ae45 100644 --- a/drivers/gpu/drm/imx/hdp/imx-hdp.h +++ b/drivers/gpu/drm/imx/hdp/imx-hdp.h @@ -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) -- 2.17.1