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; }
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; }
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, ®s->buf_data_ctl); /* Select DPCD device address */ writel(AUX_ADDR_7_0(val_addr), ®s->aux_addr_7_0); writel(AUX_ADDR_15_8(val_addr), ®s->aux_addr_15_8); writel(AUX_ADDR_19_16(val_addr), ®s->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++, ®s->buf_data[i]); } else val = AUX_LENGTH(len) | AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ; writel(val, ®s->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(®s->buf_data[i]); } length -= len; val_addr += len; in_data += len; } return 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; }