diff --git a/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt b/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt index 027d76c27a41..496f68605a86 100644 --- a/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt +++ b/Documentation/devicetree/bindings/display/bridge/analogix_dp.txt @@ -21,6 +21,8 @@ Required properties for dp-controller: from general PHY binding: Should be "dp". Optional properties for dp-controller: + -analogix,video-bist-enable: + Enable video bist pattern for DP_TX debugging. -force-hpd: Indicate driver need force hpd when hpd detect failed, this is used for some eDP screen which don't have hpd signal. diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index aa1bb86293fd..76a9662097f9 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -938,6 +938,7 @@ static int analogix_dp_fast_link_train_detection(struct analogix_dp_device *dp) static int analogix_dp_commit(struct analogix_dp_device *dp) { + struct video_info *video = &dp->video_info; int ret; /* Keep the panel disabled while we configure video */ @@ -959,6 +960,11 @@ static int analogix_dp_commit(struct analogix_dp_device *dp) } analogix_dp_init_video(dp); + analogix_dp_set_video_format(dp); + + if (video->video_bist_enable) + analogix_dp_video_bist_enable(dp); + ret = analogix_dp_config_video(dp); if (ret) { dev_err(dp->dev, "unable to config video\n"); @@ -1500,6 +1506,8 @@ static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge, struct device_node *dp_node = dp->dev->of_node; int vic; + drm_mode_copy(&video->mode, mode); + /* Input video interlaces & hsync pol & vsync pol */ video->interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC); @@ -1632,6 +1640,9 @@ static int analogix_dp_dt_parse_pdata(struct analogix_dp_device *dp) break; } + video_info->video_bist_enable = + of_property_read_bool(dp_node, "analogix,video-bist-enable"); + return 0; } diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h index c051502d7fbf..0b364899eba7 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h @@ -129,6 +129,7 @@ enum dp_irq_type { struct video_info { char *name; + struct drm_display_mode mode; bool h_sync_polarity; bool v_sync_polarity; @@ -141,6 +142,8 @@ struct video_info { int max_link_rate; enum link_lane_count_type max_lane_count; + + bool video_bist_enable; }; struct link_train { @@ -255,5 +258,7 @@ int analogix_dp_send_psr_spd(struct analogix_dp_device *dp, struct dp_sdp *vsc, bool blocking); ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, struct drm_dp_aux_msg *msg); +void analogix_dp_set_video_format(struct analogix_dp_device *dp); +void analogix_dp_video_bist_enable(struct analogix_dp_device *dp); #endif /* _ANALOGIX_DP_CORE_H */ diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index cab6c8b92efd..4ecd552f97c5 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -1142,3 +1142,69 @@ aux_error: return -EREMOTEIO; } + +void analogix_dp_set_video_format(struct analogix_dp_device *dp) +{ + struct video_info *video = &dp->video_info; + const struct drm_display_mode *mode = &video->mode; + unsigned int hsw, hfp, hbp, vsw, vfp, vbp; + + hsw = mode->hsync_end - mode->hsync_start; + hfp = mode->hsync_start - mode->hdisplay; + hbp = mode->htotal - mode->hsync_end; + vsw = mode->vsync_end - mode->vsync_start; + vfp = mode->vsync_start - mode->vdisplay; + vbp = mode->vtotal - mode->vsync_end; + + /* Set Video Format Parameters */ + writel(TOTAL_LINE_CFG_L(mode->vtotal), + dp->reg_base + ANALOGIX_DP_TOTAL_LINE_CFG_L); + writel(TOTAL_LINE_CFG_H(mode->vtotal >> 8), + dp->reg_base + ANALOGIX_DP_TOTAL_LINE_CFG_H); + writel(ACTIVE_LINE_CFG_L(mode->vdisplay), + dp->reg_base + ANALOGIX_DP_ACTIVE_LINE_CFG_L); + writel(ACTIVE_LINE_CFG_H(mode->vdisplay >> 8), + dp->reg_base + ANALOGIX_DP_ACTIVE_LINE_CFG_H); + writel(V_F_PORCH_CFG(vfp), + dp->reg_base + ANALOGIX_DP_V_F_PORCH_CFG); + writel(V_SYNC_WIDTH_CFG(vsw), + dp->reg_base + ANALOGIX_DP_V_SYNC_WIDTH_CFG); + writel(V_B_PORCH_CFG(vbp), + dp->reg_base + ANALOGIX_DP_V_B_PORCH_CFG); + writel(TOTAL_PIXEL_CFG_L(mode->htotal), + dp->reg_base + ANALOGIX_DP_TOTAL_PIXEL_CFG_L); + writel(TOTAL_PIXEL_CFG_H(mode->htotal >> 8), + dp->reg_base + ANALOGIX_DP_TOTAL_PIXEL_CFG_H); + writel(ACTIVE_PIXEL_CFG_L(mode->hdisplay), + dp->reg_base + ANALOGIX_DP_ACTIVE_PIXEL_CFG_L); + writel(ACTIVE_PIXEL_CFG_H(mode->hdisplay >> 8), + dp->reg_base + ANALOGIX_DP_ACTIVE_PIXEL_CFG_H); + writel(H_F_PORCH_CFG_L(hfp), + dp->reg_base + ANALOGIX_DP_H_F_PORCH_CFG_L); + writel(H_F_PORCH_CFG_H(hfp >> 8), + dp->reg_base + ANALOGIX_DP_H_F_PORCH_CFG_H); + writel(H_SYNC_CFG_L(hsw), + dp->reg_base + ANALOGIX_DP_H_SYNC_CFG_L); + writel(H_SYNC_CFG_H(hsw >> 8), + dp->reg_base + ANALOGIX_DP_H_SYNC_CFG_H); + writel(H_B_PORCH_CFG_L(hbp), + dp->reg_base + ANALOGIX_DP_H_B_PORCH_CFG_L); + writel(H_B_PORCH_CFG_H(hbp >> 8), + dp->reg_base + ANALOGIX_DP_H_B_PORCH_CFG_H); +} + +void analogix_dp_video_bist_enable(struct analogix_dp_device *dp) +{ + u32 reg; + + /* Enable Video BIST */ + writel(BIST_EN, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_4); + + /* + * Note that if BIST_EN is set to 1, F_SEL must be cleared to 0 + * although video format information comes from registers set by user. + */ + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + reg &= ~FORMAT_SEL; + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); +} diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h index e284ee8da58b..81ce406d97b5 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h @@ -15,9 +15,27 @@ #define ANALOGIX_DP_VIDEO_CTL_1 0x20 #define ANALOGIX_DP_VIDEO_CTL_2 0x24 #define ANALOGIX_DP_VIDEO_CTL_3 0x28 +#define ANALOGIX_DP_VIDEO_CTL_4 0x2C #define ANALOGIX_DP_VIDEO_CTL_8 0x3C #define ANALOGIX_DP_VIDEO_CTL_10 0x44 +#define ANALOGIX_DP_TOTAL_LINE_CFG_L 0x48 +#define ANALOGIX_DP_TOTAL_LINE_CFG_H 0x4C +#define ANALOGIX_DP_ACTIVE_LINE_CFG_L 0x50 +#define ANALOGIX_DP_ACTIVE_LINE_CFG_H 0x54 +#define ANALOGIX_DP_V_F_PORCH_CFG 0x58 +#define ANALOGIX_DP_V_SYNC_WIDTH_CFG 0x5C +#define ANALOGIX_DP_V_B_PORCH_CFG 0x60 +#define ANALOGIX_DP_TOTAL_PIXEL_CFG_L 0x64 +#define ANALOGIX_DP_TOTAL_PIXEL_CFG_H 0x68 +#define ANALOGIX_DP_ACTIVE_PIXEL_CFG_L 0x6C +#define ANALOGIX_DP_ACTIVE_PIXEL_CFG_H 0x70 +#define ANALOGIX_DP_H_F_PORCH_CFG_L 0x74 +#define ANALOGIX_DP_H_F_PORCH_CFG_H 0x78 +#define ANALOGIX_DP_H_SYNC_CFG_L 0x7C +#define ANALOGIX_DP_H_SYNC_CFG_H 0x80 +#define ANALOGIX_DP_H_B_PORCH_CFG_L 0x84 +#define ANALOGIX_DP_H_B_PORCH_CFG_H 0x88 #define ANALOGIX_DP_SPDIF_AUDIO_CTL_0 0xD8 @@ -171,6 +189,11 @@ #define VID_CHK_UPDATE_TYPE_0 (0x0 << 4) #define REUSE_SPD_EN (0x1 << 3) +/* ANALOGIX_DP_VIDEO_CTL_4 */ +#define BIST_EN (0x1 << 3) +#define BIST_WIDTH(x) (((x) & 0x1) << 2) +#define BIST_TYPE(x) (((x) & 0x3) << 0) + /* ANALOGIX_DP_VIDEO_CTL_8 */ #define VID_HRES_TH(x) (((x) & 0xf) << 4) #define VID_VRES_TH(x) (((x) & 0xf) << 0) @@ -181,6 +204,57 @@ #define VSYNC_POLARITY_CFG (0x1 << 1) #define HSYNC_POLARITY_CFG (0x1 << 0) +/* ANALOGIX_DP_TOTAL_LINE_CFG_L */ +#define TOTAL_LINE_CFG_L(x) (((x) & 0xff) << 0) + +/* ANALOGIX_DP_TOTAL_LINE_CFG_H */ +#define TOTAL_LINE_CFG_H(x) (((x) & 0xf) << 0) + +/* ANALOGIX_DP_ACTIVE_LINE_CFG_L */ +#define ACTIVE_LINE_CFG_L(x) (((x) & 0xff) << 0) + +/* ANALOGIX_DP_ACTIVE_LINE_CFG_H */ +#define ACTIVE_LINE_CFG_H(x) (((x) & 0xf) << 0) + +/* ANALOGIX_DP_V_F_PORCH_CFG */ +#define V_F_PORCH_CFG(x) (((x) & 0xff) << 0) + +/* ANALOGIX_DP_V_SYNC_WIDTH_CFG */ +#define V_SYNC_WIDTH_CFG(x) (((x) & 0xff) << 0) + +/* ANALOGIX_DP_V_B_PORCH_CFG */ +#define V_B_PORCH_CFG(x) (((x) & 0xff) << 0) + +/* ANALOGIX_DP_TOTAL_PIXEL_CFG_L */ +#define TOTAL_PIXEL_CFG_L(x) (((x) & 0xff) << 0) + +/* ANALOGIX_DP_TOTAL_PIXEL_CFG_H */ +#define TOTAL_PIXEL_CFG_H(x) (((x) & 0x3f) << 0) + +/* ANALOGIX_DP_ACTIVE_PIXEL_CFG_L */ +#define ACTIVE_PIXEL_CFG_L(x) (((x) & 0xff) << 0) + +/* ANALOGIX_DP_ACTIVE_PIXEL_CFG_H */ +#define ACTIVE_PIXEL_CFG_H(x) (((x) & 0x3f) << 0) + +/* ANALOGIX_DP_H_F_PORCH_CFG_L */ +#define H_F_PORCH_CFG_L(x) (((x) & 0xff) << 0) + +/* ANALOGIX_DP_H_F_PORCH_CFG_H */ +#define H_F_PORCH_CFG_H(x) (((x) & 0xf) << 0) + +/* ANALOGIX_DP_H_SYNC_CFG_L */ +#define H_SYNC_CFG_L(x) (((x) & 0xff) << 0) + +/* ANALOGIX_DP_H_SYNC_CFG_H */ +#define H_SYNC_CFG_H(x) (((x) & 0xf) << 0) + +/* ANALOGIX_DP_H_B_PORCH_CFG_L */ +#define H_B_PORCH_CFG_L(x) (((x) & 0xff) << 0) + +/* ANALOGIX_DP_H_B_PORCH_CFG_H */ +#define H_B_PORCH_CFG_H(x) (((x) & 0xf) << 0) + /* ANALOGIX_DP_PLL_REG_1 */ #define REF_CLK_24M (0x1 << 0) #define REF_CLK_27M (0x0 << 0)