drm/bridge: analogix_dp: support video BIST generation

The video BIST function of the DP_TX generates arbitrary video formats
internally according to the specified format configuration and selection.
These BIST video formats simplify DP_TX debugging.

Change-Id: Ia019c8f40fdd4ebea3e5250be8e2c15540481a6c
Signed-off-by: Wyon Bi <bivvy.bi@rock-chips.com>
This commit is contained in:
Wyon Bi
2018-08-14 09:25:36 +08:00
committed by Tao Huang
parent b6ca87397d
commit ac306bb254
5 changed files with 158 additions and 0 deletions

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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 */

View File

@@ -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);
}

View File

@@ -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)