mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-09 12:17:12 +09:00
rk32 edp:add bist/hw link traing support
This commit is contained in:
@@ -170,6 +170,7 @@
|
||||
rockchip,check-idle = <1>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
||||
i2c5: i2c@ff170000 {
|
||||
compatible = "rockchip,rk30-i2c";
|
||||
@@ -186,6 +187,12 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
edp: edp@ff970000 {
|
||||
compatible = "rockchip,rk32-edp";
|
||||
reg = <0xff970000 0x4000>;
|
||||
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
|
||||
status = "disabled";
|
||||
}
|
||||
adc: adc@ff100000 {
|
||||
compatible = "rockchip,saradc";
|
||||
reg = <0xff100000 0x100>;
|
||||
@@ -202,7 +209,7 @@
|
||||
compatible = "rockchip,rga";
|
||||
reg = <0xff920000 0x1000>;
|
||||
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clock-names = "hclk_rga", "aclk_rga";
|
||||
clock-names = "hclk_rga", "aclk_rga";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#include "../../edid.h"
|
||||
|
||||
#define DPCD_REV 0x00
|
||||
#define DPCD_MAX_LINK_RATE 0x01
|
||||
#define DPCD_MAX_LANE_CNT 0x02
|
||||
#define DPCD_MAX_LINK_RATE 0x01
|
||||
#define DPCD_MAX_LANE_CNT 0x02
|
||||
|
||||
#define DPCD_MAX_DOWNSPREAD 0x03
|
||||
#define DPCD_NORP 0x04
|
||||
@@ -120,7 +120,7 @@
|
||||
#define EDID_EXTENSION_FLAG 0x7e
|
||||
#define EDID_CHECKSUM 0x7f
|
||||
|
||||
static unsigned char edp_calc_edid_check_sum(unsigned char *edid_data)
|
||||
static unsigned char inline edp_calc_edid_check_sum(unsigned char *edid_data)
|
||||
{
|
||||
int i;
|
||||
unsigned char sum = 0;
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/rk_fb.h>
|
||||
#include "rk32_dp.h"
|
||||
#include "../../../arch/arm/mach-rockchip/iomap.h"
|
||||
#include "../../../arch/arm/mach-rockchip/grf.h"
|
||||
@@ -32,7 +31,7 @@
|
||||
#include <linux/of.h>
|
||||
#endif
|
||||
|
||||
/*#define BIST_MODE*/
|
||||
/*#define EDP_BIST_MODE*/
|
||||
|
||||
static int rk32_edp_init_edp(struct rk32_edp *edp)
|
||||
{
|
||||
@@ -70,20 +69,9 @@ static int rk32_edp_detect_hpd(struct rk32_edp *edp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned char rk32_edp_calc_edid_check_sum(unsigned char *edid_data)
|
||||
{
|
||||
int i;
|
||||
unsigned char sum = 0;
|
||||
|
||||
for (i = 0; i < EDID_BLOCK_LENGTH; i++)
|
||||
sum = sum + edid_data[i];
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
static int rk32_edp_read_edid(struct rk32_edp *edp)
|
||||
{
|
||||
unsigned char edid[EDID_BLOCK_LENGTH * 2];
|
||||
unsigned char edid[EDID_LENGTH * 2];
|
||||
unsigned int extend_block = 0;
|
||||
unsigned char sum;
|
||||
unsigned char test_vector;
|
||||
@@ -96,9 +84,8 @@ static int rk32_edp_read_edid(struct rk32_edp *edp)
|
||||
*/
|
||||
|
||||
/* Read Extension Flag, Number of 128-byte EDID extension blocks */
|
||||
retval = rk32_edp_read_byte_from_i2c(edp, I2C_EDID_DEVICE_ADDR,
|
||||
EDID_EXTENSION_FLAG,
|
||||
&extend_block);
|
||||
retval = rk32_edp_read_byte_from_i2c(edp, EDID_ADDR, EDID_EXTENSION_FLAG,
|
||||
&extend_block);
|
||||
if (retval < 0) {
|
||||
dev_err(edp->dev, "EDID extension flag failed!\n");
|
||||
return -EIO;
|
||||
@@ -108,39 +95,33 @@ static int rk32_edp_read_edid(struct rk32_edp *edp)
|
||||
dev_dbg(edp->dev, "EDID data includes a single extension!\n");
|
||||
|
||||
/* Read EDID data */
|
||||
retval = rk32_edp_read_bytes_from_i2c(edp, I2C_EDID_DEVICE_ADDR,
|
||||
EDID_HEADER_PATTERN,
|
||||
EDID_BLOCK_LENGTH,
|
||||
&edid[EDID_HEADER_PATTERN]);
|
||||
retval = rk32_edp_read_bytes_from_i2c(edp, EDID_ADDR, EDID_HEADER,
|
||||
EDID_LENGTH, &edid[EDID_HEADER]);
|
||||
if (retval != 0) {
|
||||
dev_err(edp->dev, "EDID Read failed!\n");
|
||||
return -EIO;
|
||||
}
|
||||
sum = rk32_edp_calc_edid_check_sum(edid);
|
||||
sum = edp_calc_edid_check_sum(edid);
|
||||
if (sum != 0) {
|
||||
dev_warn(edp->dev, "EDID bad checksum!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read additional EDID data */
|
||||
retval = rk32_edp_read_bytes_from_i2c(edp,
|
||||
I2C_EDID_DEVICE_ADDR,
|
||||
EDID_BLOCK_LENGTH,
|
||||
EDID_BLOCK_LENGTH,
|
||||
&edid[EDID_BLOCK_LENGTH]);
|
||||
retval = rk32_edp_read_bytes_from_i2c(edp, EDID_ADDR, EDID_LENGTH,
|
||||
EDID_LENGTH, &edid[EDID_LENGTH]);
|
||||
if (retval != 0) {
|
||||
dev_err(edp->dev, "EDID Read failed!\n");
|
||||
return -EIO;
|
||||
}
|
||||
sum = rk32_edp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
|
||||
sum = edp_calc_edid_check_sum(&edid[EDID_LENGTH]);
|
||||
if (sum != 0) {
|
||||
dev_warn(edp->dev, "EDID bad checksum!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
retval = rk32_edp_read_byte_from_dpcd(edp,
|
||||
DPCD_ADDR_TEST_REQUEST,
|
||||
&test_vector);
|
||||
retval = rk32_edp_read_byte_from_dpcd(edp, DPCD_TEST_REQUEST,
|
||||
&test_vector);
|
||||
if (retval < 0) {
|
||||
dev_err(edp->dev, "DPCD EDID Read failed!\n");
|
||||
return retval;
|
||||
@@ -148,14 +129,14 @@ static int rk32_edp_read_edid(struct rk32_edp *edp)
|
||||
|
||||
if (test_vector & DPCD_TEST_EDID_READ) {
|
||||
retval = rk32_edp_write_byte_to_dpcd(edp,
|
||||
DPCD_ADDR_TEST_EDID_CHECKSUM,
|
||||
edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
|
||||
DPCD_TEST_EDID_CHECKSUM,
|
||||
edid[EDID_LENGTH + EDID_CHECKSUM]);
|
||||
if (retval < 0) {
|
||||
dev_err(edp->dev, "DPCD EDID Write failed!\n");
|
||||
return retval;
|
||||
}
|
||||
retval = rk32_edp_write_byte_to_dpcd(edp,
|
||||
DPCD_ADDR_TEST_RESPONSE,
|
||||
DPCD_TEST_RESPONSE,
|
||||
DPCD_TEST_EDID_CHECKSUM_WRITE);
|
||||
if (retval < 0) {
|
||||
dev_err(edp->dev, "DPCD EDID checksum failed!\n");
|
||||
@@ -166,24 +147,20 @@ static int rk32_edp_read_edid(struct rk32_edp *edp)
|
||||
dev_info(edp->dev, "EDID data does not include any extensions.\n");
|
||||
|
||||
/* Read EDID data */
|
||||
retval = rk32_edp_read_bytes_from_i2c(edp,
|
||||
I2C_EDID_DEVICE_ADDR,
|
||||
EDID_HEADER_PATTERN,
|
||||
EDID_BLOCK_LENGTH,
|
||||
&edid[EDID_HEADER_PATTERN]);
|
||||
retval = rk32_edp_read_bytes_from_i2c(edp, EDID_ADDR, EDID_HEADER,
|
||||
EDID_LENGTH, &edid[EDID_HEADER]);
|
||||
if (retval != 0) {
|
||||
dev_err(edp->dev, "EDID Read failed!\n");
|
||||
return -EIO;
|
||||
}
|
||||
sum = rk32_edp_calc_edid_check_sum(edid);
|
||||
sum = edp_calc_edid_check_sum(edid);
|
||||
if (sum != 0) {
|
||||
dev_warn(edp->dev, "EDID bad checksum!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
retval = rk32_edp_read_byte_from_dpcd(edp,
|
||||
DPCD_ADDR_TEST_REQUEST,
|
||||
&test_vector);
|
||||
retval = rk32_edp_read_byte_from_dpcd(edp,DPCD_TEST_REQUEST,
|
||||
&test_vector);
|
||||
if (retval < 0) {
|
||||
dev_err(edp->dev, "DPCD EDID Read failed!\n");
|
||||
return retval;
|
||||
@@ -191,14 +168,14 @@ static int rk32_edp_read_edid(struct rk32_edp *edp)
|
||||
|
||||
if (test_vector & DPCD_TEST_EDID_READ) {
|
||||
retval = rk32_edp_write_byte_to_dpcd(edp,
|
||||
DPCD_ADDR_TEST_EDID_CHECKSUM,
|
||||
DPCD_TEST_EDID_CHECKSUM,
|
||||
edid[EDID_CHECKSUM]);
|
||||
if (retval < 0) {
|
||||
dev_err(edp->dev, "DPCD EDID Write failed!\n");
|
||||
return retval;
|
||||
}
|
||||
retval = rk32_edp_write_byte_to_dpcd(edp,
|
||||
DPCD_ADDR_TEST_RESPONSE,
|
||||
DPCD_TEST_RESPONSE,
|
||||
DPCD_TEST_EDID_CHECKSUM_WRITE);
|
||||
if (retval < 0) {
|
||||
dev_err(edp->dev, "DPCD EDID checksum failed!\n");
|
||||
@@ -218,8 +195,7 @@ static int rk32_edp_handle_edid(struct rk32_edp *edp)
|
||||
int retval;
|
||||
|
||||
/* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
|
||||
retval = rk32_edp_read_bytes_from_dpcd(edp, DPCD_ADDR_DPCD_REV,
|
||||
12, buf);
|
||||
retval = rk32_edp_read_bytes_from_dpcd(edp, DPCD_REV, 12, buf);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
@@ -240,13 +216,13 @@ static int rk32_edp_enable_rx_to_enhanced_mode(struct rk32_edp *edp,
|
||||
int retval;
|
||||
|
||||
retval = rk32_edp_read_byte_from_dpcd(edp,
|
||||
DPCD_ADDR_LANE_COUNT_SET, &data);
|
||||
DPCD_LANE_CNT_SET, &data);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
if (enable) {
|
||||
retval = rk32_edp_write_byte_to_dpcd(edp,
|
||||
DPCD_ADDR_LANE_COUNT_SET,
|
||||
DPCD_LANE_CNT_SET,
|
||||
DPCD_ENHANCED_FRAME_EN |
|
||||
DPCD_LANE_COUNT_SET(data));
|
||||
} else {
|
||||
@@ -254,7 +230,7 @@ static int rk32_edp_enable_rx_to_enhanced_mode(struct rk32_edp *edp,
|
||||
DPCD_ADDR_CONFIGURATION_SET, 0);*/
|
||||
|
||||
retval = rk32_edp_write_byte_to_dpcd(edp,
|
||||
DPCD_ADDR_LANE_COUNT_SET,
|
||||
DPCD_LANE_CNT_SET,
|
||||
DPCD_LANE_COUNT_SET(data));
|
||||
}
|
||||
|
||||
@@ -280,7 +256,7 @@ static int rk32_edp_is_enhanced_mode_available(struct rk32_edp *edp)
|
||||
int retval;
|
||||
|
||||
retval = rk32_edp_read_byte_from_dpcd(edp,
|
||||
DPCD_ADDR_MAX_LANE_COUNT, &data);
|
||||
DPCD_MAX_LANE_CNT, &data);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
@@ -323,7 +299,7 @@ static int rk32_edp_training_pattern_dis(struct rk32_edp *edp)
|
||||
rk32_edp_set_training_pattern(edp, DP_NONE);
|
||||
|
||||
retval = rk32_edp_write_byte_to_dpcd(edp,
|
||||
DPCD_ADDR_TRAINING_PATTERN_SET,
|
||||
DPCD_TRAINING_PATTERN_SET,
|
||||
DPCD_TRAINING_PATTERN_DISABLED);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
@@ -368,7 +344,7 @@ static int rk32_edp_link_start(struct rk32_edp *edp)
|
||||
edp->link_train.cr_loop[lane] = 0;
|
||||
|
||||
/* Set sink to D0 (Sink Not Ready) mode. */
|
||||
retval = rk32_edp_write_byte_to_dpcd(edp, DPCD_ADDR_SINK_POWER_STATE,
|
||||
retval = rk32_edp_write_byte_to_dpcd(edp, DPCD_SINK_POWER_STATE,
|
||||
DPCD_SET_POWER_STATE_D0);
|
||||
if (retval < 0) {
|
||||
dev_err(edp->dev, "failed to set sink device to D0!\n");
|
||||
@@ -382,7 +358,7 @@ static int rk32_edp_link_start(struct rk32_edp *edp)
|
||||
/* Setup RX configuration */
|
||||
buf[0] = edp->link_train.link_rate;
|
||||
buf[1] = edp->link_train.lane_count;
|
||||
retval = rk32_edp_write_bytes_to_dpcd(edp, DPCD_ADDR_LINK_BW_SET,
|
||||
retval = rk32_edp_write_bytes_to_dpcd(edp, DPCD_LINK_BW_SET,
|
||||
2, buf);
|
||||
if (retval < 0) {
|
||||
dev_err(edp->dev, "failed to set bandwidth and lane count!\n");
|
||||
@@ -399,7 +375,7 @@ static int rk32_edp_link_start(struct rk32_edp *edp)
|
||||
|
||||
/* Set RX training pattern */
|
||||
retval = rk32_edp_write_byte_to_dpcd(edp,
|
||||
DPCD_ADDR_TRAINING_PATTERN_SET,
|
||||
DPCD_TRAINING_PATTERN_SET,
|
||||
DPCD_SCRAMBLING_DISABLED |
|
||||
DPCD_TRAINING_PATTERN_1);
|
||||
if (retval < 0) {
|
||||
@@ -411,7 +387,7 @@ static int rk32_edp_link_start(struct rk32_edp *edp)
|
||||
buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
|
||||
DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
|
||||
retval = rk32_edp_write_bytes_to_dpcd(edp,
|
||||
DPCD_ADDR_TRAINING_LANE0_SET,
|
||||
DPCD_TRAINING_LANE0_SET,
|
||||
lane_count, buf);
|
||||
if (retval < 0) {
|
||||
dev_err(edp->dev, "failed to set training lane!\n");
|
||||
@@ -550,7 +526,7 @@ static int rk32_edp_process_clock_recovery(struct rk32_edp *edp)
|
||||
lane_count = edp->link_train.lane_count;
|
||||
|
||||
retval = rk32_edp_read_bytes_from_dpcd(edp,
|
||||
DPCD_ADDR_LANE0_1_STATUS,
|
||||
DPCD_LANE0_1_STATUS,
|
||||
2, link_status);
|
||||
if (retval < 0) {
|
||||
dev_err(edp->dev, "failed to read lane status!\n");
|
||||
@@ -563,7 +539,7 @@ static int rk32_edp_process_clock_recovery(struct rk32_edp *edp)
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
retval = rk32_edp_read_bytes_from_dpcd(edp,
|
||||
DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
|
||||
DPCD_ADJUST_REQUEST_LANE0_1,
|
||||
2, adjust_request);
|
||||
if (retval < 0) {
|
||||
dev_err(edp->dev, "failed to read adjust request!\n");
|
||||
@@ -590,7 +566,7 @@ static int rk32_edp_process_clock_recovery(struct rk32_edp *edp)
|
||||
}
|
||||
|
||||
retval = rk32_edp_write_byte_to_dpcd(edp,
|
||||
DPCD_ADDR_TRAINING_PATTERN_SET,
|
||||
DPCD_TRAINING_PATTERN_SET,
|
||||
DPCD_SCRAMBLING_DISABLED |
|
||||
DPCD_TRAINING_PATTERN_2);
|
||||
if (retval < 0) {
|
||||
@@ -599,7 +575,7 @@ static int rk32_edp_process_clock_recovery(struct rk32_edp *edp)
|
||||
}
|
||||
|
||||
retval = rk32_edp_write_bytes_to_dpcd(edp,
|
||||
DPCD_ADDR_TRAINING_LANE0_SET,
|
||||
DPCD_TRAINING_LANE0_SET,
|
||||
lane_count,
|
||||
edp->link_train.training_lane);
|
||||
if (retval < 0) {
|
||||
@@ -614,7 +590,7 @@ static int rk32_edp_process_clock_recovery(struct rk32_edp *edp)
|
||||
training_lane = rk32_edp_get_lane_link_training(
|
||||
edp, lane);
|
||||
retval = rk32_edp_read_bytes_from_dpcd(edp,
|
||||
DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
|
||||
DPCD_ADJUST_REQUEST_LANE0_1,
|
||||
2, adjust_request);
|
||||
if (retval < 0) {
|
||||
dev_err(edp->dev, "failed to read adjust request!\n");
|
||||
@@ -658,7 +634,7 @@ static int rk32_edp_process_clock_recovery(struct rk32_edp *edp)
|
||||
}
|
||||
|
||||
retval = rk32_edp_write_bytes_to_dpcd(edp,
|
||||
DPCD_ADDR_TRAINING_LANE0_SET,
|
||||
DPCD_TRAINING_LANE0_SET,
|
||||
lane_count,
|
||||
edp->link_train.training_lane);
|
||||
if (retval < 0) {
|
||||
@@ -693,7 +669,7 @@ static int rk32_edp_process_equalizer_training(struct rk32_edp *edp)
|
||||
lane_count = edp->link_train.lane_count;
|
||||
|
||||
retval = rk32_edp_read_bytes_from_dpcd(edp,
|
||||
DPCD_ADDR_LANE0_1_STATUS,
|
||||
DPCD_LANE0_1_STATUS,
|
||||
2, link_status);
|
||||
if (retval < 0) {
|
||||
dev_err(edp->dev, "failed to read lane status!\n");
|
||||
@@ -705,7 +681,7 @@ static int rk32_edp_process_equalizer_training(struct rk32_edp *edp)
|
||||
link_align[1] = link_status[1];
|
||||
|
||||
retval = rk32_edp_read_byte_from_dpcd(edp,
|
||||
DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED,
|
||||
DPCD_LANE_ALIGN_STATUS_UPDATED,
|
||||
&link_align[2]);
|
||||
if (retval < 0) {
|
||||
dev_err(edp->dev, "failed to read lane aligne status!\n");
|
||||
@@ -714,7 +690,7 @@ static int rk32_edp_process_equalizer_training(struct rk32_edp *edp)
|
||||
|
||||
for (lane = 0; lane < lane_count; lane++) {
|
||||
retval = rk32_edp_read_bytes_from_dpcd(edp,
|
||||
DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
|
||||
DPCD_ADJUST_REQUEST_LANE0_1,
|
||||
2, adjust_request);
|
||||
if (retval < 0) {
|
||||
dev_err(edp->dev, "failed to read adjust request!\n");
|
||||
@@ -772,7 +748,7 @@ static int rk32_edp_process_equalizer_training(struct rk32_edp *edp)
|
||||
lane);
|
||||
|
||||
retval = rk32_edp_write_bytes_to_dpcd(edp,
|
||||
DPCD_ADDR_TRAINING_LANE0_SET,
|
||||
DPCD_TRAINING_LANE0_SET,
|
||||
lane_count,
|
||||
edp->link_train.training_lane);
|
||||
if (retval < 0) {
|
||||
@@ -802,7 +778,7 @@ static int rk32_edp_get_max_rx_bandwidth(struct rk32_edp *edp,
|
||||
* 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
|
||||
*/
|
||||
retval = rk32_edp_read_byte_from_dpcd(edp,
|
||||
DPCD_ADDR_MAX_LINK_RATE, &data);
|
||||
DPCD_MAX_LINK_RATE, &data);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
@@ -821,7 +797,7 @@ static int rk32_edp_get_max_rx_lane_count(struct rk32_edp *edp,
|
||||
* 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
|
||||
*/
|
||||
retval = rk32_edp_read_byte_from_dpcd(edp,
|
||||
DPCD_ADDR_MAX_LANE_COUNT, &data);
|
||||
DPCD_MAX_LANE_CNT, &data);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
@@ -849,7 +825,11 @@ static int rk32_edp_init_training(struct rk32_edp *edp,
|
||||
retval = rk32_edp_get_max_rx_lane_count(edp, &edp->link_train.lane_count);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
dev_info(edp->dev, "max link rate:%d.%dGps max number of lanes:%d\n",
|
||||
edp->link_train.link_rate * 27/100,
|
||||
edp->link_train.link_rate*27%100,
|
||||
edp->link_train.lane_count);
|
||||
|
||||
if ((edp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
|
||||
(edp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
|
||||
dev_err(edp->dev, "Rx Max Link Rate is abnormal :%x !\n",
|
||||
@@ -911,6 +891,32 @@ static int rk32_edp_sw_link_training(struct rk32_edp *edp)
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static int rk32_edp_hw_link_training(struct rk32_edp *edp)
|
||||
{
|
||||
u32 cnt = 50;
|
||||
u32 val;
|
||||
/* Set link rate and count as you want to establish*/
|
||||
rk32_edp_set_link_bandwidth(edp, edp->link_train.link_rate);
|
||||
rk32_edp_set_lane_count(edp, edp->link_train.lane_count);
|
||||
rk32_edp_hw_link_training_en(edp);
|
||||
mdelay(1);
|
||||
val = rk32_edp_wait_hw_lt_done(edp);
|
||||
while (val) {
|
||||
if (cnt-- <= 0) {
|
||||
dev_err(edp->dev, "hw lt timeout");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
mdelay(1);
|
||||
val = rk32_edp_wait_hw_lt_done(edp);
|
||||
}
|
||||
|
||||
val = rk32_edp_get_hw_lt_status(edp);
|
||||
if (val)
|
||||
dev_err(edp->dev, "hw lt err:%d\n", val);
|
||||
return val;
|
||||
|
||||
}
|
||||
static int rk32_edp_set_link_train(struct rk32_edp *edp,
|
||||
u32 count,
|
||||
u32 bwtype)
|
||||
@@ -920,10 +926,11 @@ static int rk32_edp_set_link_train(struct rk32_edp *edp,
|
||||
retval = rk32_edp_init_training(edp, count, bwtype);
|
||||
if (retval < 0)
|
||||
dev_err(edp->dev, "DP LT init failed!\n");
|
||||
|
||||
#if 0
|
||||
retval = rk32_edp_sw_link_training(edp);
|
||||
if (retval < 0)
|
||||
dev_err(edp->dev, "DP LT failed!\n");
|
||||
#else
|
||||
retval = rk32_edp_hw_link_training(edp);
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
@@ -1008,13 +1015,13 @@ static int rk32_edp_enable_scramble(struct rk32_edp *edp, bool enable)
|
||||
rk32_edp_enable_scrambling(edp);
|
||||
|
||||
retval = rk32_edp_read_byte_from_dpcd(edp,
|
||||
DPCD_ADDR_TRAINING_PATTERN_SET,
|
||||
DPCD_TRAINING_PATTERN_SET,
|
||||
&data);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
retval = rk32_edp_write_byte_to_dpcd(edp,
|
||||
DPCD_ADDR_TRAINING_PATTERN_SET,
|
||||
DPCD_TRAINING_PATTERN_SET,
|
||||
(u8)(data & ~DPCD_SCRAMBLING_DISABLED));
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
@@ -1022,13 +1029,13 @@ static int rk32_edp_enable_scramble(struct rk32_edp *edp, bool enable)
|
||||
rk32_edp_disable_scrambling(edp);
|
||||
|
||||
retval = rk32_edp_read_byte_from_dpcd(edp,
|
||||
DPCD_ADDR_TRAINING_PATTERN_SET,
|
||||
DPCD_TRAINING_PATTERN_SET,
|
||||
&data);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
retval = rk32_edp_write_byte_to_dpcd(edp,
|
||||
DPCD_ADDR_TRAINING_PATTERN_SET,
|
||||
DPCD_TRAINING_PATTERN_SET,
|
||||
(u8)(data | DPCD_SCRAMBLING_DISABLED));
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
@@ -1037,11 +1044,11 @@ static int rk32_edp_enable_scramble(struct rk32_edp *edp, bool enable)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static irqreturn_t rk32_edp_irq_handler(int irq, void *arg)
|
||||
static irqreturn_t rk32_edp_isr(int irq, void *arg)
|
||||
{
|
||||
struct rk32_edp *edp = arg;
|
||||
|
||||
dev_err(edp->dev, "rk32_edp_irq_handler\n");
|
||||
dev_info(edp->dev, "rk32_edp_isr\n");
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -1090,7 +1097,7 @@ edp_phy_init:
|
||||
/* Link Training */
|
||||
ret = rk32_edp_set_link_train(edp, LANE_CNT4, LINK_RATE_2_70GBPS);
|
||||
if (ret) {
|
||||
dev_err(edp->dev, "unable to do link train\n");
|
||||
dev_err(edp->dev, "link train failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1100,12 +1107,16 @@ edp_phy_init:
|
||||
rk32_edp_set_lane_count(edp, edp->video_info.lane_count);
|
||||
rk32_edp_set_link_bandwidth(edp, edp->video_info.link_rate);
|
||||
|
||||
#ifdef EDP_BIST_MODE
|
||||
rk32_edp_bist_cfg(edp);
|
||||
#else
|
||||
rk32_edp_init_video(edp);
|
||||
ret = rk32_edp_config_video(edp, &edp->video_info);
|
||||
if (ret) {
|
||||
dev_err(edp->dev, "unable to config video\n");
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1147,7 +1158,7 @@ static int rk32_edp_probe(struct platform_device *pdev)
|
||||
struct rk32_edp *edp;
|
||||
struct resource *res;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
u32 version;
|
||||
int ret;
|
||||
|
||||
if (!np) {
|
||||
dev_err(&pdev->dev, "Missing device tree node.\n");
|
||||
@@ -1170,7 +1181,11 @@ static int rk32_edp_probe(struct platform_device *pdev)
|
||||
|
||||
edp->video_info.link_rate = LINK_RATE_2_70GBPS;
|
||||
edp->video_info.lane_count = LANE_CNT4;
|
||||
|
||||
rk_fb_get_prmry_screen(&edp->screen);
|
||||
if (edp->screen.type != SCREEN_EDP) {
|
||||
dev_err(&pdev->dev, "screen is not edp!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
platform_set_drvdata(pdev, edp);
|
||||
dev_set_name(edp->dev, "rk32-edp");
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
@@ -1179,8 +1194,13 @@ static int rk32_edp_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "ioremap reg failed\n");
|
||||
return PTR_ERR(edp->regs);
|
||||
}
|
||||
version = readl_relaxed(edp->regs + DP_VERSION);
|
||||
dev_info(&pdev->dev, "edp version:0x%08x\n", version);
|
||||
ret = devm_request_irq(&pdev->dev, edp->irq, rk32_edp_isr, 0,
|
||||
dev_name(&pdev->dev), edp);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "cannot claim IRQ %d\n", edp->irq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rk32_edp_init(edp);
|
||||
dev_info(&pdev->dev, "rk32 edp driver probe success\n");
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#ifndef __RK32_DP_H
|
||||
#define __RK32_DP_H
|
||||
#include <linux/rk_fb.h>
|
||||
#include "dpcd_edid.h"
|
||||
|
||||
#define DP_VERSION 0x10
|
||||
|
||||
@@ -68,6 +70,24 @@
|
||||
#define VSYNC_POLARITY_CFG (0x1 << 1)
|
||||
#define HSYNC_POLARITY_CFG (0x1 << 0)
|
||||
|
||||
#define TOTAL_LINE_CFG_L 0x48
|
||||
#define TOTAL_LINE_CFG_H 0x4c
|
||||
#define ATV_LINE_CFG_L 0x50
|
||||
#define ATV_LINE_CFG_H 0x54
|
||||
#define VF_PORCH_REG 0x58
|
||||
#define VSYNC_CFG_REG 0x5c
|
||||
#define VB_PORCH_REG 0x60
|
||||
#define TOTAL_PIXELL_REG 0x64
|
||||
#define TOTAL_PIXELH_REG 0x68
|
||||
#define ATV_PIXELL_REG 0x6c
|
||||
#define ATV_PIXELH_REG 0x70
|
||||
#define HF_PORCHL_REG 0x74
|
||||
#define HF_PORCHH_REG 0x78
|
||||
#define HSYNC_CFGL_REG 0x7c
|
||||
#define HSYNC_CFGH_REG 0x80
|
||||
#define HB_PORCHL_REG 0x84
|
||||
#define HB_PORCHH_REG 0x88
|
||||
|
||||
#define PLL_REG_1 0xfc
|
||||
#define REF_CLK_24M (0x01 << 1)
|
||||
#define REF_CLK_27M (0x0 << 1)
|
||||
@@ -212,6 +232,7 @@
|
||||
#define LN3_LINK_TRAINING_CTL 0x698
|
||||
|
||||
#define HW_LT_CTL 0x6a0
|
||||
#define HW_LT_ERR_CODE_MASK 0x70
|
||||
#define HW_LT_EN (0x1 << 0)
|
||||
|
||||
#define DEBUG_CTL 0x6C0
|
||||
@@ -247,9 +268,6 @@
|
||||
#define DEFER_COUNT(x) (((x) & 0x7f) << 0)
|
||||
|
||||
#define AUX_RX_COMM 0x78C
|
||||
#define AUX_RX_COMM_I2C_DEFER (0x2 << 2)
|
||||
#define AUX_RX_COMM_AUX_DEFER (0x2 << 0)
|
||||
|
||||
#define BUFFER_DATA_CTL 0x790
|
||||
#define BUF_CLR (0x1 << 7)
|
||||
#define BUF_HAVE_DATA (0x1 << 4)
|
||||
@@ -338,90 +356,9 @@
|
||||
|
||||
|
||||
|
||||
/* AUX_ADDR_7_0 */
|
||||
#define AUX_ADDR_7_0(x) (((x) >> 0) & 0xff)
|
||||
|
||||
/* AUX_ADDR_15_8 */
|
||||
#define AUX_ADDR_15_8(x) (((x) >> 8) & 0xff)
|
||||
|
||||
/* AUX_ADDR_19_16 */
|
||||
#define AUX_ADDR_19_16(x) (((x) >> 16) & 0x0f)
|
||||
|
||||
|
||||
/* I2C EDID Chip ID, Slave Address */
|
||||
#define I2C_EDID_DEVICE_ADDR 0x50
|
||||
#define I2C_E_EDID_DEVICE_ADDR 0x30
|
||||
|
||||
#define EDID_BLOCK_LENGTH 0x80
|
||||
#define EDID_HEADER_PATTERN 0x00
|
||||
#define EDID_EXTENSION_FLAG 0x7e
|
||||
#define EDID_CHECKSUM 0x7f
|
||||
|
||||
|
||||
/* Definition for DPCD Register */
|
||||
#define DPCD_ADDR_DPCD_REV 0x0000
|
||||
#define DPCD_ADDR_MAX_LINK_RATE 0x0001
|
||||
#define DPCD_ADDR_MAX_LANE_COUNT 0x0002
|
||||
#define DPCD_ADDR_LINK_BW_SET 0x0100
|
||||
#define DPCD_ADDR_LANE_COUNT_SET 0x0101
|
||||
#define DPCD_ADDR_TRAINING_PATTERN_SET 0x0102
|
||||
#define DPCD_ADDR_TRAINING_LANE0_SET 0x0103
|
||||
#define DPCD_ADDR_LANE0_1_STATUS 0x0202
|
||||
#define DPCD_ADDR_LANE_ALIGN_STATUS_UPDATED 0x0204
|
||||
#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1 0x0206
|
||||
#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3 0x0207
|
||||
#define DPCD_ADDR_TEST_REQUEST 0x0218
|
||||
#define DPCD_ADDR_TEST_RESPONSE 0x0260
|
||||
#define DPCD_ADDR_TEST_EDID_CHECKSUM 0x0261
|
||||
#define DPCD_ADDR_SINK_POWER_STATE 0x0600
|
||||
|
||||
/* DPCD_ADDR_MAX_LANE_COUNT */
|
||||
#define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1)
|
||||
#define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f)
|
||||
|
||||
/* DPCD_ADDR_LANE_COUNT_SET */
|
||||
#define DPCD_ENHANCED_FRAME_EN (0x1 << 7)
|
||||
#define DPCD_LANE_COUNT_SET(x) ((x) & 0x1f)
|
||||
|
||||
/* DPCD_ADDR_TRAINING_PATTERN_SET */
|
||||
#define DPCD_SCRAMBLING_DISABLED (0x1 << 5)
|
||||
#define DPCD_SCRAMBLING_ENABLED (0x0 << 5)
|
||||
#define DPCD_TRAINING_PATTERN_2 (0x2 << 0)
|
||||
#define DPCD_TRAINING_PATTERN_1 (0x1 << 0)
|
||||
#define DPCD_TRAINING_PATTERN_DISABLED (0x0 << 0)
|
||||
|
||||
/* DPCD_ADDR_TRAINING_LANE0_SET */
|
||||
#define DPCD_MAX_PRE_EMPHASIS_REACHED (0x1 << 5)
|
||||
#define DPCD_PRE_EMPHASIS_SET(x) (((x) & 0x3) << 3)
|
||||
#define DPCD_PRE_EMPHASIS_GET(x) (((x) >> 3) & 0x3)
|
||||
#define DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 (0x0 << 3)
|
||||
#define DPCD_MAX_SWING_REACHED (0x1 << 2)
|
||||
#define DPCD_VOLTAGE_SWING_SET(x) (((x) & 0x3) << 0)
|
||||
#define DPCD_VOLTAGE_SWING_GET(x) (((x) >> 0) & 0x3)
|
||||
#define DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0 (0x0 << 0)
|
||||
|
||||
/* DPCD_ADDR_LANE0_1_STATUS */
|
||||
#define DPCD_LANE_SYMBOL_LOCKED (0x1 << 2)
|
||||
#define DPCD_LANE_CHANNEL_EQ_DONE (0x1 << 1)
|
||||
#define DPCD_LANE_CR_DONE (0x1 << 0)
|
||||
#define DPCD_CHANNEL_EQ_BITS (DPCD_LANE_CR_DONE| \
|
||||
DPCD_LANE_CHANNEL_EQ_DONE|\
|
||||
DPCD_LANE_SYMBOL_LOCKED)
|
||||
|
||||
/* DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED */
|
||||
#define DPCD_LINK_STATUS_UPDATED (0x1 << 7)
|
||||
#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED (0x1 << 6)
|
||||
#define DPCD_INTERLANE_ALIGN_DONE (0x1 << 0)
|
||||
|
||||
/* DPCD_ADDR_TEST_REQUEST */
|
||||
#define DPCD_TEST_EDID_READ (0x1 << 2)
|
||||
|
||||
/* DPCD_ADDR_TEST_RESPONSE */
|
||||
#define DPCD_TEST_EDID_CHECKSUM_WRITE (0x1 << 2)
|
||||
|
||||
/* DPCD_ADDR_SINK_POWER_STATE */
|
||||
#define DPCD_SET_POWER_STATE_D0 (0x1 << 0)
|
||||
#define DPCD_SET_POWER_STATE_D4 (0x2 << 0)
|
||||
|
||||
#define DP_TIMEOUT_LOOP_CNT 100
|
||||
#define MAX_CR_LOOP 5
|
||||
@@ -549,10 +486,12 @@ struct link_train {
|
||||
struct rk32_edp {
|
||||
struct device *dev;
|
||||
void __iomem *regs;
|
||||
unsigned int irq;
|
||||
struct clk *clk_edp;
|
||||
struct clk *clk_24m;
|
||||
struct link_train link_train;
|
||||
struct video_info video_info;
|
||||
struct rk_screen screen;
|
||||
int enabled;
|
||||
};
|
||||
|
||||
@@ -644,6 +583,8 @@ void rk32_edp_config_video_slave_mode(struct rk32_edp *edp,
|
||||
void rk32_edp_enable_scrambling(struct rk32_edp *edp);
|
||||
void rk32_edp_disable_scrambling(struct rk32_edp *edp);
|
||||
void rk32_edp_rx_control(struct rk32_edp *edp, bool enable);
|
||||
|
||||
|
||||
int rk32_edp_bist_cfg(struct rk32_edp *edp);
|
||||
void rk32_edp_hw_link_training_en(struct rk32_edp * edp);
|
||||
int rk32_edp_get_hw_lt_status(struct rk32_edp *edp);
|
||||
int rk32_edp_wait_hw_lt_done(struct rk32_edp *edp);
|
||||
#endif
|
||||
|
||||
@@ -70,7 +70,7 @@ void rk32_edp_init_analog_param(struct rk32_edp *edp)
|
||||
|
||||
#ifndef CONFIG_RK_FPGA
|
||||
val = (REF_CLK_FROM_INTER << 16) | REF_CLK_FROM_INTER;
|
||||
writel_relaxed(val,RK_GRF_VIRT + GRF_SOC_CON12);
|
||||
writel_relaxed(val,RK_GRF_VIRT + RK3288_GRF_SOC_CON12);
|
||||
#endif
|
||||
|
||||
val = SEL_24M;
|
||||
@@ -764,6 +764,36 @@ void rk32_edp_get_link_bandwidth(struct rk32_edp *edp, u32 *bwtype)
|
||||
*bwtype = val;
|
||||
}
|
||||
|
||||
void rk32_edp_hw_link_training_en(struct rk32_edp * edp)
|
||||
{
|
||||
u32 val;
|
||||
val = HW_LT_EN;
|
||||
writel(val, edp->regs + HW_LT_CTL);
|
||||
}
|
||||
|
||||
int rk32_edp_wait_hw_lt_done(struct rk32_edp *edp)
|
||||
{
|
||||
u32 val;
|
||||
#if 0
|
||||
val = readl(edp->regs + HW_LT_CTL);
|
||||
return val&0x01;
|
||||
#else
|
||||
val = readl(edp->regs + DP_INT_STA);
|
||||
if (val&HW_LT_DONE) {
|
||||
writel(val,edp->regs + DP_INT_STA);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int rk32_edp_get_hw_lt_status(struct rk32_edp * edp)
|
||||
{
|
||||
u32 val;
|
||||
val = readl(edp->regs + HW_LT_CTL);
|
||||
return (val & HW_LT_ERR_CODE_MASK) >> 4;
|
||||
}
|
||||
void rk32_edp_set_lane_count(struct rk32_edp *edp, u32 count)
|
||||
{
|
||||
u32 val;
|
||||
@@ -1017,6 +1047,7 @@ int rk32_edp_is_slave_video_stream_clock_on(struct rk32_edp *edp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void rk32_edp_set_video_cr_mn(struct rk32_edp *edp,
|
||||
enum clock_recovery_m_value_type type,
|
||||
u32 m_value,
|
||||
@@ -1067,6 +1098,70 @@ void rk32_edp_set_video_timing_mode(struct rk32_edp *edp, u32 type)
|
||||
}
|
||||
}
|
||||
|
||||
int rk32_edp_bist_cfg(struct rk32_edp *edp)
|
||||
{
|
||||
struct video_info *video_info = &edp->video_info;
|
||||
struct rk_screen *screen = &edp->screen;
|
||||
u16 x_total ,y_total, x_act;
|
||||
u32 val;
|
||||
x_total = screen->mode.left_margin + screen->mode.right_margin +
|
||||
screen->mode.xres + screen->mode.hsync_len;
|
||||
y_total = screen->mode.upper_margin + screen->mode.lower_margin +
|
||||
screen->mode.yres + screen->mode.vsync_len;
|
||||
x_act = screen->mode.xres;
|
||||
rk32_edp_set_video_cr_mn(edp, CALCULATED_M, 0, 0);
|
||||
rk32_edp_set_video_color_format(edp, video_info->color_depth,
|
||||
video_info->color_space,
|
||||
video_info->dynamic_range,
|
||||
video_info->ycbcr_coeff);
|
||||
val = y_total & 0xff;
|
||||
writel(val, edp->regs + TOTAL_LINE_CFG_L);
|
||||
val = (y_total >> 8);
|
||||
writel(val, edp->regs + TOTAL_LINE_CFG_H);
|
||||
val = (screen->mode.yres & 0xff);
|
||||
writel(val, edp->regs + ATV_LINE_CFG_L);
|
||||
val = (screen->mode.yres >> 8);
|
||||
writel(val, edp->regs + ATV_LINE_CFG_H);
|
||||
val = screen->mode.lower_margin;
|
||||
writel(val, edp->regs + VF_PORCH_REG);
|
||||
val = screen->mode.vsync_len;
|
||||
writel(val, edp->regs + VSYNC_CFG_REG);
|
||||
val = screen->mode.upper_margin;
|
||||
writel(val, edp->regs + VB_PORCH_REG);
|
||||
val = x_total & 0xff;
|
||||
writel(val, edp->regs + TOTAL_PIXELL_REG);
|
||||
val = x_total >> 8;
|
||||
writel(val, edp->regs + TOTAL_PIXELH_REG);
|
||||
val = (x_act & 0xff);
|
||||
writel(val, edp->regs + ATV_PIXELL_REG);
|
||||
val = (x_act >> 8);
|
||||
writel(val, edp->regs + ATV_PIXELH_REG);
|
||||
val = screen->mode.right_margin & 0xff;
|
||||
writel(val, edp->regs + HF_PORCHL_REG);
|
||||
val = screen->mode.right_margin >> 8;
|
||||
writel(val, edp->regs + HF_PORCHH_REG);
|
||||
val = screen->mode.hsync_len & 0xff;
|
||||
writel(val, edp->regs + HSYNC_CFGL_REG);
|
||||
val = screen->mode.hsync_len >> 8;
|
||||
writel(val, edp->regs + HSYNC_CFGH_REG);
|
||||
val = screen->mode.left_margin & 0xff;
|
||||
writel(val, edp->regs + HB_PORCHL_REG);
|
||||
val = screen->mode.left_margin >> 8;
|
||||
writel(val, edp->regs + HB_PORCHH_REG);
|
||||
|
||||
val = BIST_EN;
|
||||
writel(val, edp->regs + VIDEO_CTL_4);
|
||||
|
||||
val = readl(edp->regs + VIDEO_CTL_10);
|
||||
val &= ~F_SEL;
|
||||
writel(val, edp->regs + VIDEO_CTL_10);
|
||||
|
||||
rk32_edp_start_video(edp);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void rk32_edp_enable_video_master(struct rk32_edp *edp, bool enable)
|
||||
{
|
||||
/*u32 val;
|
||||
@@ -1115,7 +1210,7 @@ void rk32_edp_config_video_slave_mode(struct rk32_edp *edp,
|
||||
u32 val;
|
||||
|
||||
val = readl(edp->regs + FUNC_EN_1);
|
||||
val &= ~(VID_FIFO_FUNC_EN_N);
|
||||
val &= ~(VID_FIFO_FUNC_EN_N | VID_CAP_FUNC_EN_N);
|
||||
writel(val, edp->regs + FUNC_EN_1);
|
||||
|
||||
val = readl(edp->regs + VIDEO_CTL_10);
|
||||
|
||||
Reference in New Issue
Block a user