示例#1
0
static int rk_edp_dpcd_transfer(struct rk_edp *edp,
				unsigned int val_addr, u8 *data,
				unsigned int length,
				enum dpcd_request request)
{
	int val;
	int i, try_times;
	int retval = 0;
	u32 len = 0;

	while (length) {
		len = MIN(length, 16);
		for (try_times = 0; try_times < 10; try_times++) {

			/* Clear AUX CH data buffer */
			val = BUF_CLR;
			write32(&edp->regs->buf_data_ctl, val);

			/* Select DPCD device address */
			val = AUX_ADDR_7_0(val_addr);
			write32(&edp->regs->aux_addr_7_0, val);
			val = AUX_ADDR_15_8(val_addr);
			write32(&edp->regs->aux_addr_15_8, val);
			val = AUX_ADDR_19_16(val_addr);
			write32(&edp->regs->aux_addr_19_16, val);

			/*
			 * Set DisplayPort transaction and read 1 byte
			 * If bit 3 is 1, DisplayPort transaction.
			 * If Bit 3 is 0, I2C transaction.
			 */
			if (request == DPCD_WRITE) {
				val = AUX_LENGTH(len) |
					AUX_TX_COMM_DP_TRANSACTION |
					AUX_TX_COMM_WRITE;
				for (i = 0; i < len; i++)
					write32(&edp->regs->buf_data[i],
						*data++);
			} else
				val = AUX_LENGTH(len) |
					AUX_TX_COMM_DP_TRANSACTION |
					AUX_TX_COMM_READ;

			write32(&edp->regs->aux_ch_ctl_1, val);

			/* Start AUX transaction */
			retval = rk_edp_start_aux_transaction(edp);
			if (retval == 0)
				break;
			else
				printk(BIOS_WARNING, "read dpcd Aux Transaction fail!\n");

		}

		if (retval)
			return -1;

		if (request == DPCD_READ) {
			for (i = 0; i < len; i++)
				*data++ = (u8)read32(&edp->regs->buf_data[i]);
		}

		length -= len;
		val_addr += 16;
	}
	return 0;
}
示例#2
0
int exynos_dp_read_bytes_from_i2c(u32 device_addr,
		u32 reg_addr, unsigned int count, unsigned char edid[])
{
	u32 reg;
	unsigned int i, j;
	unsigned int cur_data_idx;
	unsigned int defer = 0;
	int retval = 0;

	for (i = 0; i < count; i += 16) { /* use 16 burst */
		for (j = 0; j < 100; j++) {
			/* Clear AUX CH data buffer */
			reg = BUF_CLR;
			lwrite32(reg, &dp_regs->buffer_data_ctl);

			/* Set normal AUX CH command */
			reg = lread32(&dp_regs->aux_ch_ctl2);
			reg &= ~ADDR_ONLY;
			lwrite32(reg, &dp_regs->aux_ch_ctl2);

			/*
			 * If Rx sends defer, Tx sends only reads
			 * request without sending address
			 */
			if (!defer)
				retval =
					exynos_dp_select_i2c_device(device_addr,
							reg_addr + i);
			else
				defer = 0;

			if (retval == EXYNOS_DP_SUCCESS) {
				/*
				 * Set I2C transaction and write data
				 * If bit 3 is 1, DisplayPort transaction.
				 * If Bit 3 is 0, I2C transaction.
				 */
				reg = AUX_LENGTH(16) |
					AUX_TX_COMM_I2C_TRANSACTION |
					AUX_TX_COMM_READ;
				lwrite32(reg, &dp_regs->aux_ch_ctl1);

				/* Start AUX transaction */
				retval = exynos_dp_start_aux_transaction();
				if (retval == 0)
					break;
				else
					printk(BIOS_ERR, "DP Aux Transaction fail!\n");
			}
			/* Check if Rx sends defer */
			reg = lread32(&dp_regs->aux_rx_comm);
			if (reg == AUX_RX_COMM_AUX_DEFER ||
				reg == AUX_RX_COMM_I2C_DEFER) {
				printk(BIOS_ERR, "DP Defer: %d\n\n", reg);
				defer = 1;
			}
		}

		for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
			reg = lread32((void *)((u32)&dp_regs->buf_data0
					      + 4 * cur_data_idx));
			edid[i + cur_data_idx] = (unsigned char)reg;
		}
	}

	return retval;
}
示例#3
0
static int rk_edp_dpcd_transfer(struct rk3288_edp *regs,
				unsigned int val_addr, u8 *in_data,
				unsigned int length,
				enum dpcd_request request)
{
	int val;
	int i, try_times;
	u8 *data;
	int ret = 0;
	u32 len = 0;

	while (length) {
		len = min(length, 16U);
		for (try_times = 0; try_times < 10; try_times++) {
			data = in_data;
			/* Clear AUX CH data buffer */
			writel(BUF_CLR, &regs->buf_data_ctl);

			/* Select DPCD device address */
			writel(AUX_ADDR_7_0(val_addr), &regs->aux_addr_7_0);
			writel(AUX_ADDR_15_8(val_addr), &regs->aux_addr_15_8);
			writel(AUX_ADDR_19_16(val_addr), &regs->aux_addr_19_16);

			/*
			 * Set DisplayPort transaction and read 1 byte
			 * If bit 3 is 1, DisplayPort transaction.
			 * If Bit 3 is 0, I2C transaction.
			 */
			if (request == DPCD_WRITE) {
				val = AUX_LENGTH(len) |
					AUX_TX_COMM_DP_TRANSACTION |
					AUX_TX_COMM_WRITE;
				for (i = 0; i < len; i++)
					writel(*data++, &regs->buf_data[i]);
			} else
				val = AUX_LENGTH(len) |
					AUX_TX_COMM_DP_TRANSACTION |
					AUX_TX_COMM_READ;

			writel(val, &regs->aux_ch_ctl_1);

			/* Start AUX transaction */
			ret = rk_edp_start_aux_transaction(regs);
			if (ret == 0)
				break;
			else
				printf("read dpcd Aux Transaction fail!\n");
		}

		if (ret)
			return ret;

		if (request == DPCD_READ) {
			for (i = 0; i < len; i++)
				*data++ = (u8)readl(&regs->buf_data[i]);
		}

		length -= len;
		val_addr += len;
		in_data += len;
	}

	return 0;
}
示例#4
0
unsigned int exynos_dp_read_bytes_from_dpcd(u32 reg_addr,
				unsigned int count,
				unsigned char data[])
{
	u32 reg;
	unsigned int start_offset;
	unsigned int cur_data_count;
	unsigned int cur_data_idx;
	unsigned int retry_cnt;
	unsigned int ret = 0;

	/* Clear AUX CH data buffer */
	reg = BUF_CLR;
	lwrite32(reg, &dp_regs->buffer_data_ctl);

	start_offset = 0;
	while (start_offset < count) {
		/* Buffer size of AUX CH is 16 * 4bytes */
		if ((count - start_offset) > 16)
			cur_data_count = 16;
		else
			cur_data_count = count - start_offset;

		retry_cnt = 5;
		while (retry_cnt) {
			/* Select DPCD device address */
			reg = AUX_ADDR_7_0(reg_addr + start_offset);
			lwrite32(reg, &dp_regs->aux_addr_7_0);
			reg = AUX_ADDR_15_8(reg_addr + start_offset);
			lwrite32(reg, &dp_regs->aux_addr_15_8);
			reg = AUX_ADDR_19_16(reg_addr + start_offset);
			lwrite32(reg, &dp_regs->aux_addr_19_16);
			/*
			 * Set DisplayPort transaction and read
			 * If bit 3 is 1, DisplayPort transaction.
			 * If Bit 3 is 0, I2C transaction.
			 */
			reg = AUX_LENGTH(cur_data_count) |
				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
			lwrite32(reg, &dp_regs->aux_ch_ctl1);

			/* Start AUX transaction */
			ret = exynos_dp_start_aux_transaction();
			if (ret != EXYNOS_DP_SUCCESS) {
				if (retry_cnt == 0) {
					printk(BIOS_ERR, "DP Aux Transaction failed\n");
					return ret;
				}
				retry_cnt--;
			} else
				break;
		}

		for (cur_data_idx = 0; cur_data_idx < cur_data_count;
				cur_data_idx++) {
			reg = lread32((void *)((u32)&dp_regs->buf_data0 +
					      4 * cur_data_idx));
			data[start_offset + cur_data_idx] = (unsigned char)reg;
		}

		start_offset += cur_data_count;
	}

	return ret;
}