static int s5p_dp_enable_rx_to_enhanced_mode(struct s5p_dp_device *dp,
						bool enable)
{
	u8 data;
	int retval;

	retval = s5p_dp_read_byte_from_dpcd(dp,
			DPCD_ADDR_LANE_COUNT_SET, &data);
	if (retval < 0)
		return retval;

	if (enable) {
		retval = s5p_dp_write_byte_to_dpcd(dp,
				DPCD_ADDR_LANE_COUNT_SET,
				DPCD_ENHANCED_FRAME_EN |
				DPCD_LANE_COUNT_SET(data));
	} else {
		retval = s5p_dp_write_byte_to_dpcd(dp,
				DPCD_ADDR_CONFIGURATION_SET, 0);

		retval = s5p_dp_write_byte_to_dpcd(dp,
				DPCD_ADDR_LANE_COUNT_SET,
				DPCD_LANE_COUNT_SET(data));
	}

	return retval;
}
static void s5p_dp_disable_rx_zmux(struct s5p_dp_device *dp)
{
	s5p_dp_write_byte_to_dpcd(dp,
			DPCD_ADDR_USER_DEFINED1, 0);
	s5p_dp_write_byte_to_dpcd(dp,
			DPCD_ADDR_USER_DEFINED2, 0x83);
	s5p_dp_write_byte_to_dpcd(dp,
			DPCD_ADDR_USER_DEFINED3, 0x27);
}
void s5p_dp_rx_control(struct s5p_dp_device *dp, bool enable)
{
	s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_USER_DEFINED1,0);
	s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_USER_DEFINED2,0x90);

	if (enable) {
		s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_USER_DEFINED3,0x84);
		s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_USER_DEFINED3,0x00);
	} else {
		s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_USER_DEFINED3,0x80);
	}
}
Пример #4
0
static void s5p_dp_link_start_for_psr(struct s5p_dp_device *dp)
{
	u8 buf[4];
	int lane;
	int lane_count;

	lane_count = dp->link_train.lane_count;
	dp->link_train.lt_state = CLOCK_RECOVERY;
	dp->link_train.eq_loop = 0;
	for (lane = 0; lane < lane_count; lane++)
		dp->link_train.cr_loop[lane] = 0;

	/* Set training pattern 1 */
	s5p_dp_set_training_pattern(dp, TRAINING_PTN1);

	/* Set RX training pattern */
	buf[0] = DPCD_SCRAMBLING_DISABLED |
		DPCD_TRAINING_PATTERN_1;
	s5p_dp_write_byte_to_dpcd(dp,
		DPCD_ADDR_TRAINING_PATTERN_SET, buf[0]);

	for (lane = 0; lane < lane_count; lane++)
		buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
		DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
	s5p_dp_write_bytes_to_dpcd(dp,
		DPCD_ADDR_TRAINING_LANE0_SET,
		lane_count, buf);
}
Пример #5
0
static int s5p_dp_process_equalizer_training_for_psr(struct s5p_dp_device *dp)
{
	u8 link_status[6];
	int lane;
	int lane_count;
	u8 buf[5];
	u32 reg;
	u8 adjust_request[2];

	s5p_dp_sr_wait_on(dp);
	s5p_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
		6, link_status);
	lane_count = dp->link_train.lane_count;
	if (s5p_dp_clock_recovery_ok(link_status, lane_count) == 0) {
		adjust_request[0] = link_status[4];
		adjust_request[1] = link_status[5];
		if (s5p_dp_channel_eq_ok(link_status, lane_count) == 0) {
			/* traing pattern Set to Normal */
			s5p_dp_training_pattern_dis(dp);
			dev_dbg(dp->dev, "Link Training success!\n");
			s5p_dp_get_link_bandwidth(dp, &reg);
			dp->link_train.link_rate = reg;
			dev_dbg(dp->dev, "final bandwidth = %.2x\n",
				dp->link_train.link_rate);
			s5p_dp_get_lane_count(dp, &reg);
			dp->link_train.lane_count = reg;
			dev_dbg(dp->dev, "final lane count = %.2x\n",
				dp->link_train.lane_count);
			dp->link_train.lt_state = FINISHED;
		} else {
			/* not all locked */
			dp->link_train.eq_loop++;
			if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
				s5p_dp_reduce_link_rate(dp);
			} else {
				s5p_dp_get_adjust_train(dp, adjust_request);
				for (lane = 0; lane < lane_count; lane++) {
					s5p_dp_set_lane_link_training(dp,
						dp->link_train.training_lane[lane],
							lane);
					buf[lane] = dp->link_train.training_lane[lane];
					s5p_dp_write_byte_to_dpcd(dp,
						DPCD_ADDR_TRAINING_LANE0_SET + lane,
						buf[lane]);
				}
			}
		}
	} else {
		s5p_dp_reduce_link_rate(dp);
	}
	return 0;
}
static int s5p_dp_training_pattern_dis(struct s5p_dp_device *dp)
{
	int retval;

	s5p_dp_set_training_pattern(dp, DP_NONE);

	retval = s5p_dp_write_byte_to_dpcd(dp,
			DPCD_ADDR_TRAINING_PATTERN_SET,
			DPCD_TRAINING_PATTERN_DISABLED);
	if (retval < 0)
		return retval;

	return 0;
}
static int s5p_dp_enable_scramble(struct s5p_dp_device *dp, bool enable)
{
	u8 data;
	int retval;

	if (enable) {
		s5p_dp_enable_scrambling(dp);

		retval = s5p_dp_read_byte_from_dpcd(dp,
				DPCD_ADDR_TRAINING_PATTERN_SET,
				&data);
		if (retval < 0)
			return retval;

		retval = s5p_dp_write_byte_to_dpcd(dp,
				DPCD_ADDR_TRAINING_PATTERN_SET,
				(u8)(data & ~DPCD_SCRAMBLING_DISABLED));
		if (retval < 0)
			return retval;
	} else {
		s5p_dp_disable_scrambling(dp);

		retval = s5p_dp_read_byte_from_dpcd(dp,
				DPCD_ADDR_TRAINING_PATTERN_SET,
				&data);
		if (retval < 0)
			return retval;

		retval = s5p_dp_write_byte_to_dpcd(dp,
				DPCD_ADDR_TRAINING_PATTERN_SET,
				(u8)(data | DPCD_SCRAMBLING_DISABLED));
		if (retval < 0)
			return retval;
	}

	return 0;
}
Пример #8
0
Файл: fb.c Проект: 0ida/coreboot
/*
 * Set DP to enhanced mode. We use this for EVT1
 * param dp	pointer to main s5p-dp structure
 * return	status
 */
static int s5p_dp_enable_rx_to_enhanced_mode(struct s5p_dp_device *dp)
{
	u8 data;

	if (s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, &data)) {
		printk(BIOS_DEBUG, "DPCD read error\n");
		return -ERR_DPCD_READ_ERROR1;
	}
	if (s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
				      DPCD_ENHANCED_FRAME_EN |
				      (data & DPCD_LANE_COUNT_SET_MASK))) {
		printk(BIOS_DEBUG, "DPCD write error\n");
		return -ERR_DPCD_WRITE_ERROR1;
	}

	return 0;
}
Пример #9
0
Файл: fb.c Проект: 0ida/coreboot
/*
 * Enable scrambles mode. We use this for EVT1
 * param dp	pointer to main s5p-dp structure
 * return	status
 */
static int s5p_dp_enable_scramble(struct s5p_dp_device *dp)
{
	u8 data;
	struct exynos5_dp *base = dp->base;

	clrbits_le32(&base->dp_training_ptn_set, SCRAMBLING_DISABLE);

	if (s5p_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TRAINING_PATTERN_SET,
				       &data)) {
		printk(BIOS_DEBUG, "DPCD read error\n");
		return -ERR_DPCD_READ_ERROR2;
	}

	if (s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_TRAINING_PATTERN_SET,
			      (u8)(data & ~DPCD_SCRAMBLING_DISABLED))) {
		printk(BIOS_DEBUG, "DPCD write error\n");
		return -ERR_DPCD_WRITE_ERROR2;
	}

	return 0;
}
Пример #10
0
static int s5p_dp_psr_pre_entry(struct s5p_dp_device *dp)
{
	struct platform_device *pdev;
	struct s5p_dp_platdata *pdata;
	int timeout_loop = 0;
	struct fb_event event;

	pdev = to_platform_device(dp->dev);
	pdata = pdev->dev.platform_data;

	mutex_lock(&dp->lock);
	dev_dbg(dp->dev, "%s +\n", __func__);

	s5p_dp_write_byte_to_dpcd(dp,
		DPCD_ADDR_PRE_ENTRY, 0x1);
	dp->psr_enter_state = PSR_PRE_ENTRY_DONE;

	dev_dbg(dp->dev, "%s -\n", __func__);
	mutex_unlock(&dp->lock);

	return 0;
}
static int s5p_dp_read_edid(struct s5p_dp_device *dp)
{
	unsigned char edid[EDID_BLOCK_LENGTH * 2];
	unsigned int extend_block = 0;
	unsigned char sum;
	unsigned char test_vector;
	int retval;

	/*
	 * EDID device address is 0x50.
	 * However, if necessary, you must have set upper address
	 * into E-EDID in I2C device, 0x30.
	 */

	/* Read Extension Flag, Number of 128-byte EDID extension blocks */
	retval = s5p_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
				EDID_EXTENSION_FLAG,
				&extend_block);
	if (retval < 0) {
		dev_err(dp->dev, "EDID extension flag failed!\n");
		return -EIO;
	}

	if (extend_block > 0) {
		dev_dbg(dp->dev, "EDID data includes a single extension!\n");

		/* Read EDID data */
		retval = s5p_dp_read_bytes_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
						EDID_HEADER_PATTERN,
						EDID_BLOCK_LENGTH,
						&edid[EDID_HEADER_PATTERN]);
		if (retval != 0) {
			dev_err(dp->dev, "EDID Read failed!\n");
			return -EIO;
		}
		sum = s5p_dp_calc_edid_check_sum(edid);
		if (sum != 0) {
			dev_err(dp->dev, "EDID bad checksum!\n");
			return -EIO;
		}

		/* Read additional EDID data */
		retval = s5p_dp_read_bytes_from_i2c(dp,
				I2C_EDID_DEVICE_ADDR,
				EDID_BLOCK_LENGTH,
				EDID_BLOCK_LENGTH,
				&edid[EDID_BLOCK_LENGTH]);
		if (retval != 0) {
			dev_err(dp->dev, "EDID Read failed!\n");
			return -EIO;
		}
		sum = s5p_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
		if (sum != 0) {
			dev_err(dp->dev, "EDID bad checksum!\n");
			return -EIO;
		}

		retval = s5p_dp_read_byte_from_dpcd(dp,
				DPCD_ADDR_TEST_REQUEST,
				&test_vector);
		if (retval < 0) {
			dev_err(dp->dev, "DPCD EDID Read failed!\n");
			return retval;
		}

		if (test_vector & DPCD_TEST_EDID_READ) {
			retval = s5p_dp_write_byte_to_dpcd(dp,
					DPCD_ADDR_TEST_EDID_CHECKSUM,
					edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
			if (retval < 0) {
				dev_err(dp->dev, "DPCD EDID Write failed!\n");
				return retval;
			}
			retval = s5p_dp_write_byte_to_dpcd(dp,
					DPCD_ADDR_TEST_RESPONSE,
					DPCD_TEST_EDID_CHECKSUM_WRITE);
			if (retval < 0) {
				dev_err(dp->dev, "DPCD EDID checksum failed!\n");
				return retval;
			}
		}
	} else {
		dev_info(dp->dev, "EDID data does not include any extensions.\n");

		/* Read EDID data */
		retval = s5p_dp_read_bytes_from_i2c(dp,
				I2C_EDID_DEVICE_ADDR,
				EDID_HEADER_PATTERN,
				EDID_BLOCK_LENGTH,
				&edid[EDID_HEADER_PATTERN]);
		if (retval != 0) {
			dev_err(dp->dev, "EDID Read failed!\n");
			return -EIO;
		}
		sum = s5p_dp_calc_edid_check_sum(edid);
		if (sum != 0) {
			dev_err(dp->dev, "EDID bad checksum!\n");
			return -EIO;
		}

		retval = s5p_dp_read_byte_from_dpcd(dp,
				DPCD_ADDR_TEST_REQUEST,
				&test_vector);
		if (retval < 0) {
			dev_err(dp->dev, "DPCD EDID Read failed!\n");
			return retval;
		}

		if (test_vector & DPCD_TEST_EDID_READ) {
			retval = s5p_dp_write_byte_to_dpcd(dp,
					DPCD_ADDR_TEST_EDID_CHECKSUM,
					edid[EDID_CHECKSUM]);
			if (retval < 0) {
				dev_err(dp->dev, "DPCD EDID Write failed!\n");
				return retval;
			}
			retval = s5p_dp_write_byte_to_dpcd(dp,
					DPCD_ADDR_TEST_RESPONSE,
					DPCD_TEST_EDID_CHECKSUM_WRITE);
			if (retval < 0) {
				dev_err(dp->dev, "DPCD EDID checksum failed!\n");
				return retval;
			}
		}
	}

	dev_err(dp->dev, "EDID Read success!\n");
	return 0;
}
static int s5p_dp_process_clock_recovery(struct s5p_dp_device *dp)
{
	u8 link_status[2];
	int lane;
	int lane_count;

	u8 adjust_request[2];
	u8 voltage_swing;
	u8 pre_emphasis;
	u8 training_lane;
	int retval;

	udelay(100);

	lane_count = dp->link_train.lane_count;

	retval = s5p_dp_read_bytes_from_dpcd(dp,
			DPCD_ADDR_LANE0_1_STATUS,
			2, link_status);
	if (retval < 0) {
		dev_err(dp->dev, "failed to read lane status!\n");
		return retval;
	}

    dev_err(dp->dev, "link status[0] : %x\n", link_status[0]);
    dev_err(dp->dev, "link status[1] : %x\n", link_status[1]);

	if (s5p_dp_clock_recovery_ok(link_status, lane_count) == 0) {
		/* set training pattern 2 for EQ */
		s5p_dp_set_training_pattern(dp, TRAINING_PTN2);

		for (lane = 0; lane < lane_count; lane++) {
			retval = s5p_dp_read_bytes_from_dpcd(dp,
					DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
					2, adjust_request);
			if (retval < 0) {
				dev_err(dp->dev, "failed to read adjust request!\n");
				return retval;
			}

			voltage_swing = s5p_dp_get_adjust_request_voltage(
							adjust_request, lane);
			pre_emphasis = s5p_dp_get_adjust_request_pre_emphasis(
							adjust_request, lane);
			training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
					DPCD_PRE_EMPHASIS_SET(pre_emphasis);

			if (voltage_swing == VOLTAGE_LEVEL_3)
				training_lane |= DPCD_MAX_SWING_REACHED;
			if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
				training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;

			dp->link_train.training_lane[lane] = training_lane;

			s5p_dp_set_lane_link_training(dp,
				dp->link_train.training_lane[lane],
				lane);
		}

		retval = s5p_dp_write_byte_to_dpcd(dp,
				DPCD_ADDR_TRAINING_PATTERN_SET,
				DPCD_SCRAMBLING_DISABLED |
				DPCD_TRAINING_PATTERN_2);
		if (retval < 0) {
			dev_err(dp->dev, "failed to set training pattern 2!\n");
			return retval;
		}

		retval = s5p_dp_write_bytes_to_dpcd(dp,
				DPCD_ADDR_TRAINING_LANE0_SET,
				lane_count,
				dp->link_train.training_lane);
		if (retval < 0) {
			dev_err(dp->dev, "failed to set training lane!\n");
			return retval;
		}

		dev_info(dp->dev, "Link Training Clock Recovery success\n");
		dp->link_train.lt_state = EQUALIZER_TRAINING;
	} else {
		for (lane = 0; lane < lane_count; lane++) {
			training_lane = s5p_dp_get_lane_link_training(
							dp, lane);
			retval = s5p_dp_read_bytes_from_dpcd(dp,
					DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
					2, adjust_request);
			if (retval < 0) {
				dev_err(dp->dev, "failed to read adjust request!\n");
				return retval;
			}

			voltage_swing = s5p_dp_get_adjust_request_voltage(
							adjust_request, lane);
			pre_emphasis = s5p_dp_get_adjust_request_pre_emphasis(
							adjust_request, lane);

			if (voltage_swing == VOLTAGE_LEVEL_3 ||
			    pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
				dev_err(dp->dev, "voltage or pre emphasis reached max level\n");
				goto reduce_link_rate;
			}

			if ((DPCD_VOLTAGE_SWING_GET(training_lane) ==
					voltage_swing) &&
			   (DPCD_PRE_EMPHASIS_GET(training_lane) ==
					pre_emphasis)) {
				dp->link_train.cr_loop[lane]++;
				if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP) {
					dev_err(dp->dev, "CR Max loop\n");
					goto reduce_link_rate;
				}
			}

			training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
					DPCD_PRE_EMPHASIS_SET(pre_emphasis);

			if (voltage_swing == VOLTAGE_LEVEL_3)
				training_lane |= DPCD_MAX_SWING_REACHED;
			if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
				training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;

			dp->link_train.training_lane[lane] = training_lane;

			s5p_dp_set_lane_link_training(dp,
				dp->link_train.training_lane[lane], lane);
		}

		retval = s5p_dp_write_bytes_to_dpcd(dp,
				DPCD_ADDR_TRAINING_LANE0_SET,
				lane_count,
				dp->link_train.training_lane);
		if (retval < 0) {
			dev_err(dp->dev, "failed to set training lane!\n");
			return retval;
		}
	}

	return 0;

reduce_link_rate:
	s5p_dp_reduce_link_rate(dp);
	return -EIO;
}
static int s5p_dp_link_start(struct s5p_dp_device *dp)
{
	u8 buf[4];
	int lane;
	int lane_count;
	int retval;

	lane_count = dp->link_train.lane_count;

	dp->link_train.lt_state = CLOCK_RECOVERY;
	dp->link_train.eq_loop = 0;

	for (lane = 0; lane < lane_count; lane++)
		dp->link_train.cr_loop[lane] = 0;

	/* Set sink to D0 (Sink Not Ready) mode. */
	retval = s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE,
				DPCD_SET_POWER_STATE_D0);
	if (retval < 0) {
		dev_err(dp->dev, "failed to set sink device to D0!\n");
		return retval;
	}

	/* Set link rate and count as you want to establish*/
	s5p_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
	s5p_dp_set_lane_count(dp, dp->link_train.lane_count);

	/* Setup RX configuration */
	buf[0] = dp->link_train.link_rate;
	buf[1] = dp->link_train.lane_count;
	retval = s5p_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
					2, buf);
	if (retval < 0) {
		dev_err(dp->dev, "failed to set bandwidth and lane count!\n");
		return retval;
	}

	/* Set TX pre-emphasis to level1 */
	for (lane = 0; lane < lane_count; lane++)
		s5p_dp_set_lane_lane_pre_emphasis(dp,
			PRE_EMPHASIS_LEVEL_1, lane);

	/* Set training pattern 1 */
	s5p_dp_set_training_pattern(dp, TRAINING_PTN1);

	/* Set RX training pattern */
	retval = s5p_dp_write_byte_to_dpcd(dp,
			DPCD_ADDR_TRAINING_PATTERN_SET,
			DPCD_SCRAMBLING_DISABLED |
			DPCD_TRAINING_PATTERN_1);
	if (retval < 0) {
		dev_err(dp->dev, "failed to set training pattern 1!\n");
		return retval;
	}

	for (lane = 0; lane < lane_count; lane++)
		buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
			    DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
	retval = s5p_dp_write_bytes_to_dpcd(dp,
			DPCD_ADDR_TRAINING_LANE0_SET,
			lane_count, buf);
	if (retval < 0) {
		dev_err(dp->dev, "failed to set training lane!\n");
		return retval;
	}

	return 0;
}
Пример #14
0
static int s5p_dp_init_training(struct s5p_dp_device *dp,
			enum link_lane_count_type max_lane,
			enum link_rate_type max_rate)
{
	int retval;
#ifdef CONFIG_S5P_DP_PSR
	u8 data;
#endif
	/*
	 * MACRO_RST must be applied after the PLL_LOCK to avoid
	 * the DP inter pair skew issue for at least 10 us
	 */
	s5p_dp_reset_macro(dp);

#ifdef CONFIG_S5P_DP_PSR
	s5p_dp_enable_rx_to_enhanced_mode(dp, 0);
	s5p_dp_read_byte_from_dpcd(dp,
		DPCD_ADDR_EDP_CONFIGURATION_SET,
			&data);
	s5p_dp_write_byte_to_dpcd(dp,
		DPCD_ADDR_EDP_CONFIGURATION_SET,
		data | (1<<1));
	s5p_dp_enable_enhanced_mode(dp, 1);
#endif

	/* Initialize by reading RX's DPCD */
	retval = s5p_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
	if (retval < 0)
		return retval;

	retval = s5p_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
	if (retval < 0)
		return retval;

	if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
	   (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
		dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
			dp->link_train.link_rate);
		dp->link_train.link_rate = LINK_RATE_1_62GBPS;
	}

	if (dp->link_train.lane_count == 0) {
		dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
			dp->link_train.lane_count);
		dp->link_train.lane_count = (u8)LANE_COUNT1;
	}

	/* Setup TX lane count & rate */
	if (dp->link_train.lane_count > max_lane)
		dp->link_train.lane_count = max_lane;
	if (dp->link_train.link_rate > max_rate)
		dp->link_train.link_rate = max_rate;

#ifdef CONFIG_S5P_DP_PSR
	s5p_dp_enable_ssc(dp, 0);
#endif

	/* All DP analog module power up */
	s5p_dp_set_analog_power_down(dp, POWER_ALL, 0);

	return 0;
}
Пример #15
0
static int s5p_dp_enable(struct s5p_dp_device *dp)
{
	int ret = 0;
	int retry = 0;
	struct s5p_dp_platdata *pdata = dp->dev->platform_data;
	u32 reg;

#ifdef CONFIG_S5P_DP_PSR
	if ((dp->psr_enter_state == PSR_PRE_ENTER) || (dp->psr_enter_state == PSR_ENTER_DONE)) {
		s5p_dp_psr_exit(dp);
	}
#endif

	mutex_lock(&dp->lock);

#ifdef CONFIG_S5P_DP_ESD_RECOVERY
	if (dp->enabled)
		s5p_dp_disable_esd_interrupt(dp);
#endif

	if (dp->enabled)
		goto out;

	dp->enabled = 1;

	clk_enable(dp->clock);
	pm_runtime_get_sync(dp->dev);

dp_phy_init:

	s5p_dp_init_dp(dp);

#if 0
	if (!soc_is_exynos5250()) {
		ret = s5p_dp_detect_hpd(dp);
		if (ret) {
			dev_err(dp->dev, "unable to detect hpd\n");
			goto out;
		}
	}
#endif

#if 0
	ret = s5p_dp_handle_edid(dp);
	if (ret) {
		dev_err(dp->dev, "unable to handle edid\n");
		goto out;
	}
#endif
	if (soc_is_exynos5250())
		s5p_dp_disable_rx_zmux(dp);

	/* Non-enhance mode setting */
	ret = s5p_dp_enable_scramble(dp, 0);
	if (ret) {
		dev_err(dp->dev, "unable to set scramble\n");
		goto out;
	}

	ret = s5p_dp_enable_rx_to_enhanced_mode(dp, 0);
	if (ret) {
		dev_err(dp->dev, "unable to set enhanced mode\n");
		goto out;
	}
	s5p_dp_enable_enhanced_mode(dp, 0);

	/* Rx data disable */
	if (soc_is_exynos5250())
		s5p_dp_rx_control(dp,0);

       /* Link Training */
	ret = s5p_dp_set_link_train(dp, dp->video_info->lane_count,
				dp->video_info->link_rate);
	if (ret) {
		dev_err(dp->dev, "unable to do link train\n");
		goto out;
	}

	/* Rx data enable */
	if (soc_is_exynos5250())
		s5p_dp_rx_control(dp,1);

	s5p_dp_set_lane_count(dp, dp->video_info->lane_count);
	s5p_dp_set_link_bandwidth(dp, dp->video_info->link_rate);

	s5p_dp_init_video(dp);
	ret = s5p_dp_config_video(dp, dp->video_info);
	if (ret) {
		dev_err(dp->dev, "unable to config video\n");
		goto out;
	}

#ifdef CONFIG_S5P_DP_PSR
	s5p_dp_scramber_rst_cnt(dp);

	s5p_dp_write_byte_to_dpcd(dp, 0x491, 0x80);
	s5p_dp_write_byte_to_dpcd(dp, 0x492, 0x04);
	s5p_dp_write_byte_to_dpcd(dp, 0x493, 0x31);

	writel(0x2F, dp->reg_base + 0x730); /* S5P_DP_VIDEO_FIFO_THRD */

	reg = readl(dp->reg_base + 0x800); /* S5P_DP_SOC_GENERAL_CTL */
	reg |= (1<<31);
	writel(reg, dp->reg_base + 0x800);

	s5p_dp_write_byte_to_dpcd(dp,
		DPCD_ADDR_PSR_CONFIGURATION,
		DPCD_PSR_ENABLE);

	s5p_dp_set_video_timing(dp);
#endif

	if (pdata->backlight_on)
		pdata->backlight_on();

#ifdef CONFIG_S5P_DP_ESD_RECOVERY
	s5p_dp_enable_esd_interrupt(dp);
#endif

	mutex_unlock(&dp->lock);
	return 0;

out:

	if (retry < 3) {
		if (pdata->lcd_off)
			pdata->lcd_off();

		if (pdata->lcd_on)
			pdata->lcd_on();

		retry++;
		goto dp_phy_init;
	}
	dev_err(dp->dev, "DP LT exceeds max retry count");

	if (pdata->backlight_off)
		pdata->backlight_off();

	if (pdata->lcd_off)
		pdata->lcd_off();

	mutex_unlock(&dp->lock);
	return ret;
}
Пример #16
0
int s5p_dp_psr_exit(struct s5p_dp_device *dp)
{
	struct platform_device *pdev;
	struct s5p_dp_platdata *pdata;
	int timeout_loop = 0;
	u8 data;
	u32 reg;
	int ret = 0;

	pdev = to_platform_device(dp->dev);
	pdata = pdev->dev.platform_data;

	mutex_lock(&dp->lock);
	dev_dbg(dp->dev, "%s +\n", __func__);

	if (dp->psr_enter_state == PSR_NONE) {
		dev_info(dp->dev, "%s: Already edP PSR_EXIT state\n", __func__);
		dp->psr_exit_state = PSR_NONE;
		mutex_unlock(&dp->lock);
		return 0;
	}

	clk_enable(dp->clock);

	s5p_dp_exit_psr(dp);

	s5p_dp_set_fifo_reset(dp);
	s5p_dp_reset_macro_onoff(dp, 1);
	s5p_dp_set_analog_power_down(dp, ANALOG_TOTAL, 0);

	if (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
		while (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
			timeout_loop++;
			if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
				dev_err(dp->dev, "failed to get pll lock status\n");
				ret = -ETIMEDOUT;
				goto err_exit;
			}
			udelay(10);
		}
	}

	ndelay(600);
	s5p_dp_clear_fifo_reset(dp);
	s5p_dp_reset_macro_onoff(dp, 0);
	s5p_dp_reset_serdes_fifo(dp);

	/* Set sink to D0 (Normal operation) mode. */
	s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE,
		DPCD_SET_POWER_STATE_D0);

	s5p_dp_set_link_train_for_psr(dp, dp->video_info->lane_count,
		dp->video_info->link_rate);

	s5p_dp_set_idle_en(dp);
	timeout_loop = 0;

	for (;;) {
		timeout_loop++;
		if (s5p_dp_get_psr_status(dp) == PSR_STATUS_INACTIVE)
			break;
		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
			dev_err(dp->dev, "DP: Timeout of PSR inactive\n");
			ret = -ETIMEDOUT;
			goto err_exit;
		}
		usleep_range(100, 110);
	}

	s5p_dp_set_force_stream_valid(dp);

	timeout_loop = 0;

	for (;;) {
		timeout_loop++;
		if (s5p_dp_is_video_stream_on(dp) == 0)
			break;
		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
			dev_err(dp->dev, "Timeout of video streamclk ok\n");
			ret = -ETIMEDOUT;
			goto err_exit;
		}
		usleep_range(1000, 1100);
	}

	timeout_loop = 0;
	for (;;) {
		timeout_loop++;
		s5p_dp_read_byte_from_dpcd(dp,
			DPCD_ADDR_SINK_PSR_STATUS,
			&data);
		if (data == SINK_PSR_INACTIVE_STATE || data == 4) {
			break;
		}
		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
			dev_err(dp->dev, "LCD: Timeout of Sink PSR inactive\n");
			ret = -ETIMEDOUT;
			goto err_exit;
		}
		usleep_range(100, 110);
	}

	dp->psr_enter_state = PSR_NONE;
	dp->psr_exit_state = PSR_EXIT_DONE;

	dev_dbg(dp->dev, "%s -\n", __func__);
	mutex_unlock(&dp->lock);
	return ret;

err_exit:
	dp->psr_exit_state = PSR_NONE;
	dev_dbg(dp->dev, "%s -\n", __func__);
	mutex_unlock(&dp->lock);
	return ret;
}
Пример #17
0
Файл: fb.c Проект: 0ida/coreboot
/*
 * DP H/w Link Training. Set DPCD link rate and bandwidth.
 * param dp		pointer to main s5p-dp structure
 * param max_lane	No of lanes
 * param max_rate	bandwidth
 * return status
 */
static int s5p_dp_hw_link_training(struct s5p_dp_device *dp,
				   unsigned int max_lane,
				   unsigned int max_rate)
{
	int pll_is_locked = 0;
	u32 data;
	int lane;
	struct mono_time current, end;
	struct exynos5_dp *base = dp->base;

	/* Stop Video */
	clrbits_le32(&base->video_ctl_1, VIDEO_EN);

	timer_monotonic_get(&current);
	end = current;
	mono_time_add_msecs(&end, PLL_LOCK_TIMEOUT);

	while ((pll_is_locked = s5p_dp_get_pll_lock_status(dp)) == PLL_UNLOCKED) {
		if (mono_time_after(&current, &end)) {
			/* Ignore this error, and try to continue */
			printk(BIOS_ERR, "PLL is not locked yet.\n");
			break;
		}
		timer_monotonic_get(&current);
	}
	printk(BIOS_SPEW, "PLL is %slocked\n",
			pll_is_locked == PLL_LOCKED ? "": "not ");
	/* Reset Macro */
	setbits_le32(&base->dp_phy_test, MACRO_RST);

	/* 10 us is the minimum reset time. */
	udelay(10);

	clrbits_le32(&base->dp_phy_test, MACRO_RST);

	/* Set TX pre-emphasis to minimum */
	for (lane = 0; lane < max_lane; lane++)
		if (s5p_dp_set_lane_lane_pre_emphasis(dp,
					      PRE_EMPHASIS_LEVEL_0, lane)) {
			printk(BIOS_DEBUG, "Unable to set pre emphasis level\n");
			return -ERR_PRE_EMPHASIS_LEVELS;
		}

	/* All DP analog module power up */
	writel(0x00, &base->dp_phy_pd);

	/* Initialize by reading RX's DPCD */
	s5p_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
	s5p_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);

	printk(BIOS_SPEW, "%s: rate 0x%x, lane_count %d\n", __func__,
		dp->link_train.link_rate, dp->link_train.lane_count);

	if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
	    (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
		printk(BIOS_DEBUG, "Rx Max Link Rate is abnormal :%x !\n",
		      dp->link_train.link_rate);
		/* Not Retrying */
		return -ERR_LINK_RATE_ABNORMAL;
	}

	if (dp->link_train.lane_count == 0) {
		printk(BIOS_DEBUG, "Rx Max Lane count is abnormal :%x !\n",
		      dp->link_train.lane_count);
		/* Not retrying */
		return -ERR_MAX_LANE_COUNT_ABNORMAL;
	}

	/* Setup TX lane count & rate */
	if (dp->link_train.lane_count > max_lane)
		dp->link_train.lane_count = max_lane;
	if (dp->link_train.link_rate > max_rate)
		dp->link_train.link_rate = max_rate;

	/* Set link rate and count as you want to establish*/
	writel(dp->link_train.lane_count, &base->lane_count_set);
	writel(dp->link_train.link_rate, &base->link_bw_set);

	/* Set sink to D0 (Sink Not Ready) mode. */
	s5p_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE,
				  DPCD_SET_POWER_STATE_D0);

	/* Start HW link training */
	writel(HW_TRAINING_EN, &base->dp_hw_link_training);

	/* Wait until HW link training done */
	s5p_dp_wait_hw_link_training_done(dp);

	/* Get hardware link training status */
	data = readl(&base->dp_hw_link_training);
	printk(BIOS_SPEW, "hardware link training status: 0x%08x\n", data);
	if (data != 0) {
		printk(BIOS_ERR, " H/W link training failure: 0x%x\n", data);
		return -ERR_LINK_TRAINING_FAILURE;
	}

	/* Get Link Bandwidth */
	data = readl(&base->link_bw_set);

	dp->link_train.link_rate = data;

	data = readl(&base->lane_count_set);
	dp->link_train.lane_count = data;
	printk(BIOS_SPEW, "Done training: Link bandwidth: 0x%x, lane_count: %d\n",
		dp->link_train.link_rate, data);

	return 0;
}
Пример #18
0
static int s5p_dp_process_clock_recovery_for_psr(struct s5p_dp_device *dp)
{
	u8 data;
	u8 link_status[6];
	int lane;
	int lane_count;
	u8 buf[5];

	u8 adjust_request[2];
	u8 voltage_swing;
	u8 pre_emphasis;
	u8 training_lane;

	s5p_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
		6, link_status);
	lane_count = dp->link_train.lane_count;

	if (s5p_dp_clock_recovery_ok(link_status, lane_count) == 0) {
		/* set training pattern 2 for EQ */
		s5p_dp_set_training_pattern(dp, TRAINING_PTN2);

		adjust_request[0] = link_status[4];
		adjust_request[1] = link_status[5];

		s5p_dp_get_adjust_train(dp, adjust_request);

		buf[0] = DPCD_SCRAMBLING_DISABLED |
			DPCD_TRAINING_PATTERN_2;
		s5p_dp_write_byte_to_dpcd(dp,
			DPCD_ADDR_TRAINING_PATTERN_SET,
			buf[0]);
		for (lane = 0; lane < lane_count; lane++) {
			s5p_dp_set_lane_link_training(dp,
				dp->link_train.training_lane[lane],
								lane);
			buf[lane] = dp->link_train.training_lane[lane];
			s5p_dp_write_byte_to_dpcd(dp,
				DPCD_ADDR_TRAINING_LANE0_SET + lane,
				buf[lane]);
			}
		dp->link_train.lt_state = EQUALIZER_TRAINING;
	} else {
		s5p_dp_read_byte_from_dpcd(dp,
			DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
			&data);
		adjust_request[0] = data;
		s5p_dp_read_byte_from_dpcd(dp,
			DPCD_ADDR_ADJUST_REQUEST_LANE2_3,
			&data);
		adjust_request[1] = data;
		for (lane = 0; lane < lane_count; lane++) {
			training_lane = s5p_dp_get_lane_link_training(dp, lane);
			voltage_swing = s5p_dp_get_adjust_request_voltage(
				adjust_request, lane);
			pre_emphasis = s5p_dp_get_adjust_request_pre_emphasis(
				adjust_request, lane);
			if ((DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing) &&
				(DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis))
				dp->link_train.cr_loop[lane]++;
			dp->link_train.training_lane[lane] = training_lane;
		}

		if (s5p_dp_check_max_cr_loop(dp, voltage_swing) != 0) {
			s5p_dp_reduce_link_rate(dp);
		} else {
			s5p_dp_get_adjust_train(dp, adjust_request);
			for (lane = 0; lane < lane_count; lane++) {
				s5p_dp_set_lane_link_training(dp,
					dp->link_train.training_lane[lane],
					lane);
				buf[lane] = dp->link_train.training_lane[lane];
				s5p_dp_write_byte_to_dpcd(dp,
					DPCD_ADDR_TRAINING_LANE0_SET + lane,
					buf[lane]);
			}
		}
	}
	return 0;
}