コード例 #1
0
/**
 * xilinx_drm_dp_link_train - Train the link
 * @dp: DisplayPort IP core structure
 *
 * Return: 0 if all trains are done successfully, or corresponding error code.
 */
static int xilinx_drm_dp_train(struct xilinx_drm_dp *dp)
{
	u32 reg;
	u8 bw_code = dp->mode.bw_code;
	u8 lane_cnt = dp->mode.lane_cnt;
	u8 aux_lane_cnt;
	bool enhanced;
	int ret;

	xilinx_drm_writel(dp->iomem, XILINX_DP_TX_LANE_CNT_SET, lane_cnt);

	enhanced = drm_dp_enhanced_frame_cap(dp->dpcd);
	if (enhanced) {
		xilinx_drm_writel(dp->iomem, XILINX_DP_TX_ENHANCED_FRAME_EN, 1);
		aux_lane_cnt = lane_cnt | DP_LANE_COUNT_ENHANCED_FRAME_EN;
	}

	ret = xilinx_drm_dp_aux_write_byte(dp, DP_LANE_COUNT_SET, aux_lane_cnt);
	if (ret) {
		DRM_ERROR("failed to set lane count\n");
		return ret;
	}

	ret = xilinx_drm_dp_aux_write_byte(dp, DP_LINK_BW_SET, bw_code);
	if (ret) {
		DRM_ERROR("failed to set DP bandwidth\n");
		return ret;
	}

	xilinx_drm_writel(dp->iomem, XILINX_DP_TX_LINK_BW_SET, bw_code);

	switch (bw_code) {
	case DP_LINK_BW_1_62:
		reg = XILINX_DP_TX_PHY_CLOCK_FEEDBACK_SETTING_162;
		break;
	case DP_LINK_BW_2_7:
		reg = XILINX_DP_TX_PHY_CLOCK_FEEDBACK_SETTING_270;
		break;
	case DP_LINK_BW_5_4:
		reg = XILINX_DP_TX_PHY_CLOCK_FEEDBACK_SETTING_540;
		break;
	}

	xilinx_drm_writel(dp->iomem, XILINX_DP_TX_PHY_CLOCK_FEEDBACK_SETTING,
			  reg);
	ret = xilinx_drm_dp_phy_ready(dp);
	if (ret < 0)
		return ret;

	xilinx_drm_writel(dp->iomem, XILINX_DP_TX_SCRAMBLING_DISABLE, 1);

	memset(dp->train_set, 0, 4);

	ret = xilinx_drm_dp_link_train_cr(dp);
	if (ret) {
		DRM_ERROR("failed to train clock recovery\n");
		reg = xilinx_drm_readl(dp->iomem, XILINX_DP_TX_PHY_STATUS);
		return ret;
	}

	ret = xilinx_drm_dp_link_train_ce(dp);
	if (ret) {
		DRM_ERROR("failed to train channel eq\n");
		reg = xilinx_drm_readl(dp->iomem, XILINX_DP_TX_PHY_STATUS);
		return ret;
	}

	xilinx_drm_writel(dp->iomem, XILINX_DP_TX_TRAINING_PATTERN_SET,
			  DP_TRAINING_PATTERN_DISABLE);
	ret = xilinx_drm_dp_aux_write_byte(dp, DP_TRAINING_PATTERN_SET,
					   DP_TRAINING_PATTERN_DISABLE);
	if (ret) {
		DRM_ERROR("failed to disable training pattern\n");
		return ret;
	}

	xilinx_drm_writel(dp->iomem, XILINX_DP_TX_SCRAMBLING_DISABLE, 0);

	return 0;
}
コード例 #2
0
ファイル: xilinx_drm_dp.c プロジェクト: bambreeze/linux-xlnx
/**
 * xilinx_drm_dp_link_train - Train the link
 * @dp: DisplayPort IP core structure
 *
 * Return: 0 if all trains are done successfully, or corresponding error code.
 */
static int xilinx_drm_dp_train(struct xilinx_drm_dp *dp)
{
	u32 reg;
	u8 bw_code = dp->mode.bw_code;
	u8 lane_cnt = dp->mode.lane_cnt;
	u8 aux_lane_cnt = lane_cnt;
	bool enhanced;
	int ret;

	xilinx_drm_writel(dp->iomem, XILINX_DP_TX_LANE_CNT_SET, lane_cnt);

	enhanced = drm_dp_enhanced_frame_cap(dp->dpcd);
	if (enhanced) {
		xilinx_drm_writel(dp->iomem, XILINX_DP_TX_ENHANCED_FRAME_EN, 1);
		aux_lane_cnt |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
	}

	if (dp->dpcd[3] & 0x1) {
		xilinx_drm_writel(dp->iomem, XILINX_DP_TX_DOWNSPREAD_CTL, 1);
		drm_dp_dpcd_writeb(&dp->aux, DP_DOWNSPREAD_CTRL,
				   DP_SPREAD_AMP_0_5);
	} else {
		xilinx_drm_writel(dp->iomem, XILINX_DP_TX_DOWNSPREAD_CTL, 0);
		drm_dp_dpcd_writeb(&dp->aux, DP_DOWNSPREAD_CTRL, 0);
	}

	ret = drm_dp_dpcd_writeb(&dp->aux, DP_LANE_COUNT_SET, aux_lane_cnt);
	if (ret < 0) {
		DRM_ERROR("failed to set lane count\n");
		return ret;
	}

	ret = drm_dp_dpcd_writeb(&dp->aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
				 DP_SET_ANSI_8B10B);
	if (ret < 0) {
		DRM_ERROR("failed to set ANSI 8B/10B encoding\n");
		return ret;
	}

	ret = drm_dp_dpcd_writeb(&dp->aux, DP_LINK_BW_SET, bw_code);
	if (ret < 0) {
		DRM_ERROR("failed to set DP bandwidth\n");
		return ret;
	}

	xilinx_drm_writel(dp->iomem, XILINX_DP_TX_LINK_BW_SET, bw_code);

	switch (bw_code) {
	case DP_LINK_BW_1_62:
		reg = XILINX_DP_TX_PHY_CLOCK_FEEDBACK_SETTING_162;
		break;
	case DP_LINK_BW_2_7:
		reg = XILINX_DP_TX_PHY_CLOCK_FEEDBACK_SETTING_270;
		break;
	case DP_LINK_BW_5_4:
	default:
		reg = XILINX_DP_TX_PHY_CLOCK_FEEDBACK_SETTING_540;
		break;
	}

	xilinx_drm_writel(dp->iomem, XILINX_DP_TX_PHY_CLOCK_FEEDBACK_SETTING,
			  reg);
	ret = xilinx_drm_dp_phy_ready(dp);
	if (ret < 0)
		return ret;

	xilinx_drm_writel(dp->iomem, XILINX_DP_TX_SCRAMBLING_DISABLE, 1);

	memset(dp->train_set, 0, 4);

	ret = xilinx_drm_dp_link_train_cr(dp);
	if (ret) {
		DRM_ERROR("failed to train clock recovery\n");
		return ret;
	}

	ret = xilinx_drm_dp_link_train_ce(dp);
	if (ret) {
		DRM_ERROR("failed to train channel eq\n");
		return ret;
	}

	xilinx_drm_writel(dp->iomem, XILINX_DP_TX_TRAINING_PATTERN_SET,
			  DP_TRAINING_PATTERN_DISABLE);
	ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET,
				 DP_TRAINING_PATTERN_DISABLE);
	if (ret < 0) {
		DRM_ERROR("failed to disable training pattern\n");
		return ret;
	}

	xilinx_drm_writel(dp->iomem, XILINX_DP_TX_SCRAMBLING_DISABLE, 0);

	return 0;
}