mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 02:50:49 +09:00
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:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user