int exynos_dp_select_i2c_device(u32 device_addr, u32 reg_addr) { u32 reg; int retval; /* Set EDID device address */ reg = device_addr; lwrite32(reg, &dp_regs->aux_addr_7_0); lwrite32(0x0, &dp_regs->aux_addr_15_8); lwrite32(0x0, &dp_regs->aux_addr_19_16); /* Set offset from base address of EDID device */ lwrite32(reg_addr, &dp_regs->buf_data0); /* * Set I2C transaction and write address * If bit 3 is 1, DisplayPort transaction. * If Bit 3 is 0, I2C transaction. */ reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT | AUX_TX_COMM_WRITE; lwrite32(reg, &dp_regs->aux_ch_ctl1); /* Start AUX transaction */ retval = exynos_dp_start_aux_transaction(); if (retval != 0) printk(BIOS_DEBUG, "%s: DP Aux Transaction fail!\n", __func__); return retval; }
int exynos_dp_read_byte_from_i2c(u32 device_addr, u32 reg_addr, unsigned int *data) { u32 reg; int i; int retval; for (i = 0; i < 10; i++) { /* Clear AUX CH data buffer */ reg = BUF_CLR; lwrite32(reg, &dp_regs->buffer_data_ctl); /* Select EDID device */ retval = exynos_dp_select_i2c_device(device_addr, reg_addr); if (retval != 0) { printk(BIOS_DEBUG, "DP Select EDID device fail. retry !\n"); continue; } /* * Set I2C transaction and read data * If bit 3 is 1, DisplayPort transaction. * If Bit 3 is 0, I2C transaction. */ reg = 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 != EXYNOS_DP_SUCCESS) printk(BIOS_DEBUG, "%s: DP Aux Transaction fail!\n", __func__); } /* Read data */ if (retval == 0) *data = lread32(&dp_regs->buf_data0); return retval; }
unsigned int exynos_dp_write_byte_to_dpcd(unsigned int reg_addr, unsigned char data) { unsigned int reg, ret; /* Clear AUX CH data buffer */ reg = BUF_CLR; writel(reg, &dp_regs->buffer_data_ctl); /* Select DPCD device address */ reg = AUX_ADDR_7_0(reg_addr); writel(reg, &dp_regs->aux_addr_7_0); reg = AUX_ADDR_15_8(reg_addr); writel(reg, &dp_regs->aux_addr_15_8); reg = AUX_ADDR_19_16(reg_addr); writel(reg, &dp_regs->aux_addr_19_16); /* Write data buffer */ reg = (unsigned int)data; writel(reg, &dp_regs->buf_data0); /* * Set DisplayPort transaction and write 1 byte * If bit 3 is 1, DisplayPort transaction. * If Bit 3 is 0, I2C transaction. */ reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE; writel(reg, &dp_regs->aux_ch_ctl1); /* Start AUX transaction */ ret = exynos_dp_start_aux_transaction(); if (ret != EXYNOS_DP_SUCCESS) { printf("DP Aux transaction failed\n"); return ret; } return ret; }
unsigned int exynos_dp_read_byte_from_dpcd(u32 reg_addr, unsigned char *data) { u32 reg; int retval; /* Clear AUX CH data buffer */ reg = BUF_CLR; lwrite32(reg, &dp_regs->buffer_data_ctl); /* Select DPCD device address */ reg = AUX_ADDR_7_0(reg_addr); lwrite32(reg, &dp_regs->aux_addr_7_0); reg = AUX_ADDR_15_8(reg_addr); lwrite32(reg, &dp_regs->aux_addr_15_8); reg = AUX_ADDR_19_16(reg_addr); lwrite32(reg, &dp_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. */ reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ; lwrite32(reg, &dp_regs->aux_ch_ctl1); /* Start AUX transaction */ retval = exynos_dp_start_aux_transaction(); if (retval != EXYNOS_DP_SUCCESS) printk(BIOS_DEBUG, "DP Aux Transaction fail!\n"); /* Read data buffer */ reg = lread32(&dp_regs->buf_data0); *data = (unsigned char)(reg & 0xff); return retval; }
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; }
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; }