Message ID | 1438870763-23796-1-git-send-email-ykk@rock-chips.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thursday, August 06, 2015 11:19 PM, Yakir Yang wrote: > > Split the dp core driver from exynos directory to bridge > directory, and rename the core driver to analogix_dp_*, > leave the platform code to analogix_dp-exynos. > > Signed-off-by: Yakir Yang <ykk@rock-chips.com> > --- > drivers/gpu/drm/bridge/Kconfig | 5 + > drivers/gpu/drm/bridge/Makefile | 1 + > .../exynos_dp_core.c => bridge/analogix_dp_core.c} | 751 +++++------- > drivers/gpu/drm/bridge/analogix_dp_core.h | 286 +++++ > drivers/gpu/drm/bridge/analogix_dp_reg.c | 1266 ++++++++++++++++++++ > .../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 260 ++-- > drivers/gpu/drm/exynos/Kconfig | 5 +- > drivers/gpu/drm/exynos/Makefile | 2 +- > drivers/gpu/drm/exynos/analogix_dp-exynos.c | 240 ++++ > drivers/gpu/drm/exynos/exynos_dp_core.h | 283 ----- > include/drm/bridge/analogix_dp.h | 22 + > 11 files changed, 2287 insertions(+), 834 deletions(-) > rename drivers/gpu/drm/{exynos/exynos_dp_core.c => bridge/analogix_dp_core.c} (54%) > create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.h > create mode 100644 drivers/gpu/drm/bridge/analogix_dp_reg.c > rename drivers/gpu/drm/{exynos/exynos_dp_reg.h => bridge/analogix_dp_reg.h} (63%) > create mode 100644 drivers/gpu/drm/exynos/analogix_dp-exynos.c > delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h > create mode 100644 include/drm/bridge/analogix_dp.h > > diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig > index acef322..c7638b5 100644 > --- a/drivers/gpu/drm/bridge/Kconfig > +++ b/drivers/gpu/drm/bridge/Kconfig > @@ -3,6 +3,11 @@ config DRM_DW_HDMI > depends on DRM > select DRM_KMS_HELPER > > +config DRM_ANALOGIX_DP > + tristate > + depends on DRM > + select DRM_KMS_HELPER > + > config DRM_PTN3460 > tristate "PTN3460 DP/LVDS bridge" > depends on DRM > diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile > index 8dfebd9..a7ee559 100644 > --- a/drivers/gpu/drm/bridge/Makefile > +++ b/drivers/gpu/drm/bridge/Makefile > @@ -3,3 +3,4 @@ ccflags-y := -Iinclude/drm > obj-$(CONFIG_DRM_PS8622) += ps8622.o > obj-$(CONFIG_DRM_PTN3460) += ptn3460.o > obj-$(CONFIG_DRM_DW_HDMI) += dw_hdmi.o > +obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix_dp_core.o analogix_dp_reg.o > diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/bridge/analogix_dp_core.c > similarity index 54% > rename from drivers/gpu/drm/exynos/exynos_dp_core.c > rename to drivers/gpu/drm/bridge/analogix_dp_core.c > index aa99e23..28724d4 100644 > --- a/drivers/gpu/drm/exynos/exynos_dp_core.c > +++ b/drivers/gpu/drm/bridge/analogix_dp_core.c > @@ -1,7 +1,8 @@ > /* > - * Samsung SoC DP (Display Port) interface driver. > + * Analogix Core DP (Display Port) interface driver. > * > * Copyright (C) 2012 Samsung Electronics Co., Ltd. > + * Copyright (C) FuZhou Rockchip Electronics Co., Ltd. What is the reason to add this copyright? You just replace 'exynos' prefix with 'analogix' prefix. I cannot find the reason to add the copyright. > * Author: Jingoo Han <jg1.han@samsung.com> > * Yakir Yang <ykk@rock-chips.com> > * > @@ -32,51 +33,42 @@ > #include <drm/drm_atomic_helper.h> > #include <drm/drm_panel.h> > > -#include "exynos_dp_core.h" > +#include <drm/bridge/analogix_dp.h> > > -#define ctx_from_connector(c) container_of(c, struct exynos_dp_device, \ > - connector) > +#include "analogix_dp_core.h" > > -static inline struct exynos_drm_crtc *dp_to_crtc(struct exynos_dp_device *dp) > -{ > - return to_exynos_crtc(dp->encoder->crtc); > -} > - > -static inline struct exynos_dp_device * > -display_to_dp(struct exynos_drm_display *d) > -{ > - return container_of(d, struct exynos_dp_device, display); > -} > +#define connector_to_dp(c) container_of(c, struct analogix_dp_device, \ > + connector) > > struct bridge_init { > struct i2c_client *client; > struct device_node *node; > }; > > -static void exynos_dp_init_dp(struct exynos_dp_device *dp) > +static void analogix_dp_init_dp(struct analogix_dp_device *dp) > { > - exynos_dp_reset(dp); > + analogix_dp_reset(dp); > > - exynos_dp_swreset(dp); > + analogix_dp_swreset(dp); > > - exynos_dp_init_analog_param(dp); > - exynos_dp_init_interrupt(dp); > + analogix_dp_init_analog_param(dp); > + analogix_dp_init_interrupt(dp); > > /* SW defined function Normal operation */ > - exynos_dp_enable_sw_function(dp); > + analogix_dp_enable_sw_function(dp); > > - exynos_dp_config_interrupt(dp); > - exynos_dp_init_analog_func(dp); > + analogix_dp_config_interrupt(dp); > + analogix_dp_init_analog_func(dp); > > - exynos_dp_init_hpd(dp); > - exynos_dp_init_aux(dp); > + analogix_dp_init_hpd(dp); > + analogix_dp_init_aux(dp); > } > > -static int exynos_dp_detect_hpd(struct exynos_dp_device *dp) > +static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) > { > int timeout_loop = 0; > > - while (exynos_dp_get_plug_in_status(dp) != 0) { > + while (analogix_dp_get_plug_in_status(dp) != 0) { > timeout_loop++; > if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { > dev_err(dp->dev, "failed to get hpd plug status\n"); > @@ -88,7 +80,7 @@ static int exynos_dp_detect_hpd(struct exynos_dp_device *dp) > return 0; > } > > -static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data) > +static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data) > { > int i; > unsigned char sum = 0; > @@ -99,7 +91,7 @@ static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data) > return sum; > } > > -static int exynos_dp_read_edid(struct exynos_dp_device *dp) > +static int analogix_dp_read_edid(struct analogix_dp_device *dp) > { > unsigned char edid[EDID_BLOCK_LENGTH * 2]; > unsigned int extend_block = 0; > @@ -114,9 +106,9 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) > */ > > /* Read Extension Flag, Number of 128-byte EDID extension blocks */ > - retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR, > - EDID_EXTENSION_FLAG, > - &extend_block); > + retval = analogix_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR, > + EDID_EXTENSION_FLAG, > + &extend_block); > if (retval) > return retval; > > @@ -125,15 +117,15 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) > > /* Read EDID data */ > retval = > - exynos_dp_read_bytes_from_i2c(dp, I2C_EDID_DEVICE_ADDR, > - EDID_HEADER_PATTERN, > - EDID_BLOCK_LENGTH, > - &edid[EDID_HEADER_PATTERN]); > + analogix_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 = exynos_dp_calc_edid_check_sum(edid); > + sum = analogix_dp_calc_edid_check_sum(edid); > if (sum != 0) { > dev_err(dp->dev, "EDID bad checksum!\n"); > return -EIO; > @@ -141,27 +133,27 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) > > /* Read additional EDID data */ > retval = > - exynos_dp_read_bytes_from_i2c(dp, I2C_EDID_DEVICE_ADDR, > - EDID_BLOCK_LENGTH, > - EDID_BLOCK_LENGTH, > - &edid[EDID_BLOCK_LENGTH]); > + analogix_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 = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]); > + sum = analogix_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]); > if (sum != 0) { > dev_err(dp->dev, "EDID bad checksum!\n"); > return -EIO; > } > > - exynos_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST, > - &test_vector); > + analogix_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST, > + &test_vector); > if (test_vector & DP_TEST_LINK_EDID_READ) { > - exynos_dp_write_byte_to_dpcd( > + analogix_dp_write_byte_to_dpcd( > dp, DP_TEST_EDID_CHECKSUM, > edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]); > - exynos_dp_write_byte_to_dpcd( > + analogix_dp_write_byte_to_dpcd( > dp, DP_TEST_RESPONSE, > DP_TEST_EDID_CHECKSUM_WRITE); > } > @@ -169,26 +161,26 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) > dev_info(dp->dev, "EDID data does not include any extensions.\n"); > > /* Read EDID data */ > - retval = exynos_dp_read_bytes_from_i2c( > + retval = analogix_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 = exynos_dp_calc_edid_check_sum(edid); > + sum = analogix_dp_calc_edid_check_sum(edid); > if (sum != 0) { > dev_err(dp->dev, "EDID bad checksum!\n"); > return -EIO; > } > > - exynos_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST, > - &test_vector); > + analogix_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST, > + &test_vector); > if (test_vector & DP_TEST_LINK_EDID_READ) { > - exynos_dp_write_byte_to_dpcd( > + analogix_dp_write_byte_to_dpcd( > dp, DP_TEST_EDID_CHECKSUM, > edid[EDID_CHECKSUM]); > - exynos_dp_write_byte_to_dpcd( > + analogix_dp_write_byte_to_dpcd( > dp, DP_TEST_RESPONSE, > DP_TEST_EDID_CHECKSUM_WRITE); > } > @@ -198,20 +190,20 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) > return 0; > } > > -static int exynos_dp_handle_edid(struct exynos_dp_device *dp) > +static int analogix_dp_handle_edid(struct analogix_dp_device *dp) > { > u8 buf[12]; > int i; > int retval; > > /* Read DPCD DP_DPCD_REV~RECEIVE_PORT1_CAP_1 */ > - retval = exynos_dp_read_bytes_from_dpcd(dp, DP_DPCD_REV, 12, buf); > + retval = analogix_dp_read_bytes_from_dpcd(dp, DP_DPCD_REV, 12, buf); > if (retval) > return retval; > > /* Read EDID */ > for (i = 0; i < 3; i++) { > - retval = exynos_dp_read_edid(dp); > + retval = analogix_dp_read_edid(dp); > if (!retval) > break; > } > @@ -219,74 +211,74 @@ static int exynos_dp_handle_edid(struct exynos_dp_device *dp) > return retval; > } > > -static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device *dp, > - bool enable) > +static void analogix_dp_enable_rx_to_enhanced_mode(struct analogixdp_device *dp, > + bool enable) > { > u8 data; > > - exynos_dp_read_byte_from_dpcd(dp, DP_LANE_COUNT_SET, &data); > + analogix_dp_read_byte_from_dpcd(dp, DP_LANE_COUNT_SET, &data); > > if (enable) > - exynos_dp_write_byte_to_dpcd( > + analogix_dp_write_byte_to_dpcd( > dp, DP_LANE_COUNT_SET, > DP_LANE_COUNT_ENHANCED_FRAME_EN | > DPCD_LANE_COUNT_SET(data)); > else > - exynos_dp_write_byte_to_dpcd( > + analogix_dp_write_byte_to_dpcd( > dp, DP_LANE_COUNT_SET, > DPCD_LANE_COUNT_SET(data)); > } > > -static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device *dp) > +static int analogix_dp_is_enhanced_mode_available(struct analogix_dp_device *dp) > { > u8 data; > int retval; > > - exynos_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data); > + analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data); > retval = DPCD_ENHANCED_FRAME_CAP(data); > > return retval; > } > > -static void exynos_dp_set_enhanced_mode(struct exynos_dp_device *dp) > +static void analogix_dp_set_enhanced_mode(struct analogix_dp_device *dp) > { > u8 data; > > - data = exynos_dp_is_enhanced_mode_available(dp); > - exynos_dp_enable_rx_to_enhanced_mode(dp, data); > - exynos_dp_enable_enhanced_mode(dp, data); > + data = analogix_dp_is_enhanced_mode_available(dp); > + analogix_dp_enable_rx_to_enhanced_mode(dp, data); > + analogix_dp_enable_enhanced_mode(dp, data); > } > > -static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp) > +static void analogix_dp_training_pattern_dis(struct analogix_dp_device *dp) > { > - exynos_dp_set_training_pattern(dp, DP_NONE); > + analogix_dp_set_training_pattern(dp, DP_NONE); > > - exynos_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET, > - DP_TRAINING_PATTERN_DISABLE); > + analogix_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET, > + DP_TRAINING_PATTERN_DISABLE); > } > > -static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp, > - int pre_emphasis, int lane) > +static void analogix_dp_set_lane_lane_pre_emphasis(struct analogixdp_device *dp, > + int pre_emphasis, int lane) > { > switch (lane) { > case 0: > - exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis); > + analogix_dp_set_lane0_pre_emphasis(dp, pre_emphasis); > break; > case 1: > - exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis); > + analogix_dp_set_lane1_pre_emphasis(dp, pre_emphasis); > break; > > case 2: > - exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis); > + analogix_dp_set_lane2_pre_emphasis(dp, pre_emphasis); > break; > > case 3: > - exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis); > + analogix_dp_set_lane3_pre_emphasis(dp, pre_emphasis); > break; > } > } > > -static int exynos_dp_link_start(struct exynos_dp_device *dp) > +static int analogix_dp_link_start(struct analogix_dp_device *dp) > { > u8 buf[4]; > int lane, lane_count, pll_tries, retval; > @@ -300,24 +292,24 @@ static int exynos_dp_link_start(struct exynos_dp_device *dp) > dp->link_train.cr_loop[lane] = 0; > > /* Set link rate and count as you want to establish*/ > - exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate); > - exynos_dp_set_lane_count(dp, dp->link_train.lane_count); > + analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); > + analogix_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 = exynos_dp_write_bytes_to_dpcd(dp, DP_LINK_BW_SET, 2, buf); > + retval = analogix_dp_write_bytes_to_dpcd(dp, DP_LINK_BW_SET, 2, buf); > if (retval) > return retval; > > /* Set TX pre-emphasis to minimum */ > for (lane = 0; lane < lane_count; lane++) > - exynos_dp_set_lane_lane_pre_emphasis(dp, PRE_EMPHASIS_LEVEL_0, > - lane); > + analogix_dp_set_lane_lane_pre_emphasis( > + dp, PRE_EMPHASIS_LEVEL_0, lane); > > /* Wait for PLL lock */ > pll_tries = 0; > - while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { > + while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { > if (pll_tries == DP_TIMEOUT_LOOP_COUNT) { > dev_err(dp->dev, "Wait for PLL lock timed out\n"); > return -ETIMEDOUT; > @@ -328,12 +320,12 @@ static int exynos_dp_link_start(struct exynos_dp_device *dp) > } > > /* Set training pattern 1 */ > - exynos_dp_set_training_pattern(dp, TRAINING_PTN1); > + analogix_dp_set_training_pattern(dp, TRAINING_PTN1); > > /* Set RX training pattern */ > - retval = exynos_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET, > - DP_LINK_SCRAMBLING_DISABLE | > - DP_TRAINING_PATTERN_1); > + retval = analogix_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET, > + DP_LINK_SCRAMBLING_DISABLE | > + DP_TRAINING_PATTERN_1); > if (retval) > return retval; > > @@ -341,13 +333,13 @@ static int exynos_dp_link_start(struct exynos_dp_device *dp) > buf[lane] = DP_TRAIN_PRE_EMPH_LEVEL_0 | > DP_TRAIN_VOLTAGE_SWING_LEVEL_0; > > - retval = exynos_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET, > - lane_count, buf); > + retval = analogix_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET, > + lane_count, buf); > > return retval; > } > > -static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane) > +static unsigned char analogix_dp_get_lane_status(u8 link_status[2], int lane) > { > int shift = (lane & 1) * 4; > u8 link_value = link_status[lane >> 1]; > @@ -355,21 +347,21 @@ static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane) > return (link_value >> shift) & 0xf; > } > > -static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count) > +static int analogix_dp_clock_recovery_ok(u8 link_status[2], int lane_count) > { > int lane; > u8 lane_status; > > for (lane = 0; lane < lane_count; lane++) { > - lane_status = exynos_dp_get_lane_status(link_status, lane); > + lane_status = analogix_dp_get_lane_status(link_status, lane); > if ((lane_status & DP_LANE_CR_DONE) == 0) > return -EINVAL; > } > return 0; > } > > -static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align, > - int lane_count) > +static int analogix_dp_channel_eq_ok(u8 link_status[2], u8 link_align, > + int lane_count) > { > int lane; > u8 lane_status; > @@ -378,7 +370,7 @@ static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align, > return -EINVAL; > > for (lane = 0; lane < lane_count; lane++) { > - lane_status = exynos_dp_get_lane_status(link_status, lane); > + lane_status = analogix_dp_get_lane_status(link_status, lane); > lane_status &= DP_CHANNEL_EQ_BITS; > if (lane_status != DP_CHANNEL_EQ_BITS) > return -EINVAL; > @@ -387,8 +379,8 @@ static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align, > return 0; > } > > -static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request[2], > - int lane) > +static unsigned char > +analogix_dp_get_adjust_request_voltage(u8 adjust_request[2], int lane) > { > int shift = (lane & 1) * 4; > u8 link_value = adjust_request[lane >> 1]; > @@ -396,7 +388,7 @@ static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request[2], > return (link_value >> shift) & 0x3; > } > > -static unsigned char exynos_dp_get_adjust_request_pre_emphasis( > +static unsigned char analogix_dp_get_adjust_request_pre_emphasis( > u8 adjust_request[2], > int lane) > { > @@ -406,45 +398,45 @@ static unsigned char exynos_dp_get_adjust_request_pre_emphasis( > return ((link_value >> shift) & 0xc) >> 2; > } > > -static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp, > - u8 training_lane_set, int lane) > +static void analogix_dp_set_lane_link_training(struct analogixdp_device *dp, > + u8 training_lane_set, int lane) > { > switch (lane) { > case 0: > - exynos_dp_set_lane0_link_training(dp, training_lane_set); > + analogix_dp_set_lane0_link_training(dp, training_lane_set); > break; > case 1: > - exynos_dp_set_lane1_link_training(dp, training_lane_set); > + analogix_dp_set_lane1_link_training(dp, training_lane_set); > break; > > case 2: > - exynos_dp_set_lane2_link_training(dp, training_lane_set); > + analogix_dp_set_lane2_link_training(dp, training_lane_set); > break; > > case 3: > - exynos_dp_set_lane3_link_training(dp, training_lane_set); > + analogix_dp_set_lane3_link_training(dp, training_lane_set); > break; > } > } > > -static unsigned int exynos_dp_get_lane_link_training( > - struct exynos_dp_device *dp, > +static unsigned int analogix_dp_get_lane_link_training( > + struct analogix_dp_device *dp, > int lane) > { > u32 reg; > > switch (lane) { > case 0: > - reg = exynos_dp_get_lane0_link_training(dp); > + reg = analogix_dp_get_lane0_link_training(dp); > break; > case 1: > - reg = exynos_dp_get_lane1_link_training(dp); > + reg = analogix_dp_get_lane1_link_training(dp); > break; > case 2: > - reg = exynos_dp_get_lane2_link_training(dp); > + reg = analogix_dp_get_lane2_link_training(dp); > break; > case 3: > - reg = exynos_dp_get_lane3_link_training(dp); > + reg = analogix_dp_get_lane3_link_training(dp); > break; > default: > WARN_ON(1); > @@ -454,25 +446,25 @@ static unsigned int exynos_dp_get_lane_link_training( > return reg; > } > > -static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp) > +static void analogix_dp_reduce_link_rate(struct analogix_dp_device *dp) > { > - exynos_dp_training_pattern_dis(dp); > - exynos_dp_set_enhanced_mode(dp); > + analogix_dp_training_pattern_dis(dp); > + analogix_dp_set_enhanced_mode(dp); > > dp->link_train.lt_state = FAILED; > } > > -static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp, > - u8 adjust_request[2]) > +static void analogix_dp_get_adjust_training_lane(struct analogixdp_device *dp, > + u8 adjust_request[2]) > { > int lane, lane_count; > u8 voltage_swing, pre_emphasis, training_lane; > > lane_count = dp->link_train.lane_count; > for (lane = 0; lane < lane_count; lane++) { > - voltage_swing = exynos_dp_get_adjust_request_voltage( > + voltage_swing = analogix_dp_get_adjust_request_voltage( > adjust_request, lane); > - pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( > + pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis( > adjust_request, lane); > training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | > DPCD_PRE_EMPHASIS_SET(pre_emphasis); > @@ -486,7 +478,7 @@ static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp, > } > } > > -static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) > +static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp) > { > int lane, lane_count, retval; > u8 voltage_swing, pre_emphasis, training_lane; > @@ -496,24 +488,24 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) > > lane_count = dp->link_train.lane_count; > > - retval = exynos_dp_read_bytes_from_dpcd(dp, DP_LANE0_1_STATUS, > - 2, link_status); > + retval = analogix_dp_read_bytes_from_dpcd( > + dp, DP_LANE0_1_STATUS, 2, link_status); > if (retval) > return retval; > > - retval = exynos_dp_read_bytes_from_dpcd(dp, DP_ADJUST_REQUEST_LANE0_1, > - 2, adjust_request); > + retval = analogix_dp_read_bytes_from_dpcd( > + dp, DP_ADJUST_REQUEST_LANE0_1, 2, adjust_request); > if (retval) > return retval; > > - if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) { > + if (analogix_dp_clock_recovery_ok(link_status, lane_count) == 0) { > /* set training pattern 2 for EQ */ > - exynos_dp_set_training_pattern(dp, TRAINING_PTN2); > + analogix_dp_set_training_pattern(dp, TRAINING_PTN2); > > - retval = exynos_dp_write_byte_to_dpcd( > - dp, DP_TRAINING_PATTERN_SET, > - DP_LINK_SCRAMBLING_DISABLE | > - DP_TRAINING_PATTERN_2); > + retval = analogix_dp_write_byte_to_dpcd( > + dp, DP_TRAINING_PATTERN_SET, > + DP_LINK_SCRAMBLING_DISABLE | > + DP_TRAINING_PATTERN_2); > if (retval) > return retval; > > @@ -521,12 +513,12 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) > dp->link_train.lt_state = EQUALIZER_TRAINING; > } else { > for (lane = 0; lane < lane_count; lane++) { > - training_lane = exynos_dp_get_lane_link_training( > + training_lane = analogix_dp_get_lane_link_training( > dp, lane); > - voltage_swing = exynos_dp_get_adjust_request_voltage( > + voltage_swing = analogix_dp_get_adjust_request_voltage( > adjust_request, lane); > pre_emphasis = > - exynos_dp_get_adjust_request_pre_emphasis( > + analogix_dp_get_adjust_request_pre_emphasis( > adjust_request, lane); > > if (DPCD_VOLTAGE_SWING_GET(training_lane) == > @@ -541,19 +533,19 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) > dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n", > dp->link_train.cr_loop[lane], > voltage_swing, pre_emphasis); > - exynos_dp_reduce_link_rate(dp); > + analogix_dp_reduce_link_rate(dp); > return -EIO; > } > } > } > > - exynos_dp_get_adjust_training_lane(dp, adjust_request); > + analogix_dp_get_adjust_training_lane(dp, adjust_request); > > for (lane = 0; lane < lane_count; lane++) > - exynos_dp_set_lane_link_training( > + analogix_dp_set_lane_link_training( > dp, dp->link_train.training_lane[lane], lane); > > - retval = exynos_dp_write_bytes_to_dpcd( > + retval = analogix_dp_write_bytes_to_dpcd( > dp, DP_TRAINING_LANE0_SET, lane_count, > dp->link_train.training_lane); > if (retval) > @@ -562,7 +554,7 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) > return retval; > } > > -static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) > +static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp) > { > int lane, lane_count, retval; > u32 reg; > @@ -572,46 +564,46 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) > > lane_count = dp->link_train.lane_count; > > - retval = exynos_dp_read_bytes_from_dpcd(dp, DP_LANE0_1_STATUS, > - 2, link_status); > + retval = analogix_dp_read_bytes_from_dpcd(dp, DP_LANE0_1_STATUS, > + 2, link_status); > if (retval) > return retval; > > - if (exynos_dp_clock_recovery_ok(link_status, lane_count)) { > - exynos_dp_reduce_link_rate(dp); > + if (analogix_dp_clock_recovery_ok(link_status, lane_count)) { > + analogix_dp_reduce_link_rate(dp); > return -EIO; > } > > - retval = exynos_dp_read_bytes_from_dpcd(dp, DP_ADJUST_REQUEST_LANE0_1, > - 2, adjust_request); > + retval = analogix_dp_read_bytes_from_dpcd(dp, DP_ADJUST_REQUEST_LANE0_1, > + 2, adjust_request); > if (retval) > return retval; > > - retval = exynos_dp_read_byte_from_dpcd( > + retval = analogix_dp_read_byte_from_dpcd( > dp, DP_LANE_ALIGN_STATUS_UPDATED, &link_align); > if (retval) > return retval; > > - exynos_dp_get_adjust_training_lane(dp, adjust_request); > + analogix_dp_get_adjust_training_lane(dp, adjust_request); > > - if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count)) { > + if (!analogix_dp_channel_eq_ok(link_status, link_align, lane_count)) { > /* traing pattern Set to Normal */ > - exynos_dp_training_pattern_dis(dp); > + analogix_dp_training_pattern_dis(dp); > > dev_info(dp->dev, "Link Training success!\n"); > > - exynos_dp_get_link_bandwidth(dp, ®); > + analogix_dp_get_link_bandwidth(dp, ®); > dp->link_train.link_rate = reg; > dev_dbg(dp->dev, "final bandwidth = %.2x\n", > dp->link_train.link_rate); > > - exynos_dp_get_lane_count(dp, ®); > + analogix_dp_get_lane_count(dp, ®); > dp->link_train.lane_count = reg; > dev_dbg(dp->dev, "final lane count = %.2x\n", > dp->link_train.lane_count); > > /* set enhanced mode if available */ > - exynos_dp_set_enhanced_mode(dp); > + analogix_dp_set_enhanced_mode(dp); > dp->link_train.lt_state = FINISHED; > > return 0; > @@ -622,23 +614,23 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) > > if (dp->link_train.eq_loop > MAX_EQ_LOOP) { > dev_err(dp->dev, "EQ Max loop\n"); > - exynos_dp_reduce_link_rate(dp); > + analogix_dp_reduce_link_rate(dp); > return -EIO; > } > > for (lane = 0; lane < lane_count; lane++) > - exynos_dp_set_lane_link_training( > + analogix_dp_set_lane_link_training( > dp, dp->link_train.training_lane[lane], lane); > > - retval = exynos_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET, > - lane_count, > - dp->link_train.training_lane); > + retval = analogix_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET, > + lane_count, > + dp->link_train.training_lane); > > return retval; > } > > -static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp, > - u8 *bandwidth) > +static void analogix_dp_get_max_rx_bandwidth(struct analogixdp_device *dp, > + u8 *bandwidth) > { > u8 data; > > @@ -646,12 +638,12 @@ static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp, > * For DP rev.1.1, Maximum link rate of Main Link lanes > * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps > */ > - exynos_dp_read_byte_from_dpcd(dp, DP_MAX_LINK_RATE, &data); > + analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LINK_RATE, &data); > *bandwidth = data; > } > > -static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp, > - u8 *lane_count) > +static void analogix_dp_get_max_rx_lane_count(struct analogixdp_device *dp, > + u8 *lane_count) > { > u8 data; > > @@ -659,23 +651,23 @@ static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp, > * For DP rev.1.1, Maximum number of Main Link lanes > * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes > */ > - exynos_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data); > + analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data); > *lane_count = DPCD_MAX_LANE_COUNT(data); > } > > -static void exynos_dp_init_training(struct exynos_dp_device *dp, > - enum link_lane_count_type max_lane, > - enum link_rate_type max_rate) > +static void analogix_dp_init_training(struct analogixdp_device *dp, > + enum link_lane_count_type max_lane, > + enum link_rate_type max_rate) > { > /* > * MACRO_RST must be applied after the PLL_LOCK to avoid > * the DP inter pair skew issue for at least 10 us > */ > - exynos_dp_reset_macro(dp); > + analogix_dp_reset_macro(dp); > > /* Initialize by reading RX's DPCD */ > - exynos_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate); > - exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count); > + analogix_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate); > + analogix_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count); > > if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) && > (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) { > @@ -697,10 +689,10 @@ static void exynos_dp_init_training(struct exynos_dp_device *dp, > dp->link_train.link_rate = max_rate; > > /* All DP analog module power up */ > - exynos_dp_set_analog_power_down(dp, POWER_ALL, 0); > + analogix_dp_set_analog_power_down(dp, POWER_ALL, 0); > } > > -static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) > +static int analogix_dp_sw_link_training(struct analogix_dp_device *dp) > { > int retval = 0, training_finished = 0; > > @@ -710,17 +702,17 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) > while (!retval && !training_finished) { > switch (dp->link_train.lt_state) { > case START: > - retval = exynos_dp_link_start(dp); > + retval = analogix_dp_link_start(dp); > if (retval) > dev_err(dp->dev, "LT link start failed!\n"); > break; > case CLOCK_RECOVERY: > - retval = exynos_dp_process_clock_recovery(dp); > + retval = analogix_dp_process_clock_recovery(dp); > if (retval) > dev_err(dp->dev, "LT CR failed!\n"); > break; > case EQUALIZER_TRAINING: > - retval = exynos_dp_process_equalizer_training(dp); > + retval = analogix_dp_process_equalizer_training(dp); > if (retval) > dev_err(dp->dev, "LT EQ failed!\n"); > break; > @@ -737,15 +729,15 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) > return retval; > } > > -static int exynos_dp_set_link_train(struct exynos_dp_device *dp, > - u32 count, u32 bwtype) > +static int analogix_dp_set_link_train(struct analogixdp_device *dp, > + u32 count, u32 bwtype) > { > int i; > int retval; > > for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) { > - exynos_dp_init_training(dp, count, bwtype); > - retval = exynos_dp_sw_link_training(dp); > + analogix_dp_init_training(dp, count, bwtype); > + retval = analogix_dp_sw_link_training(dp); > if (retval == 0) > break; > > @@ -755,24 +747,24 @@ static int exynos_dp_set_link_train(struct exynos_dp_device *dp, > return retval; > } > > -static int exynos_dp_config_video(struct exynos_dp_device *dp) > +static int analogix_dp_config_video(struct analogix_dp_device *dp) > { > int retval = 0; > int timeout_loop = 0; > int done_count = 0; > > - exynos_dp_config_video_slave_mode(dp); > + analogix_dp_config_video_slave_mode(dp); > > - exynos_dp_set_video_color_format(dp); > + analogix_dp_set_video_color_format(dp); > > - if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { > + if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { > dev_err(dp->dev, "PLL is not locked yet.\n"); > return -EINVAL; > } > > for (;;) { > timeout_loop++; > - if (exynos_dp_is_slave_video_stream_clock_on(dp) == 0) > + if (analogix_dp_is_slave_video_stream_clock_on(dp) == 0) > break; > if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { > dev_err(dp->dev, "Timeout of video streamclk ok\n"); > @@ -783,25 +775,25 @@ static int exynos_dp_config_video(struct exynos_dp_device *dp) > } > > /* Set to use the register calculated M/N video */ > - exynos_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0); > + analogix_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0); > > /* For video bist, Video timing must be generated by register */ > - exynos_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE); > + analogix_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE); > > /* Disable video mute */ > - exynos_dp_enable_video_mute(dp, 0); > + analogix_dp_enable_video_mute(dp, 0); > > /* Configure video slave mode */ > - exynos_dp_enable_video_master(dp, 0); > + analogix_dp_enable_video_master(dp, 0); > > /* Enable video */ > - exynos_dp_start_video(dp); > + analogix_dp_start_video(dp); > > timeout_loop = 0; > > for (;;) { > timeout_loop++; > - if (exynos_dp_is_video_stream_on(dp) == 0) { > + if (analogix_dp_is_video_stream_on(dp) == 0) { > done_count++; > if (done_count > 10) > break; > @@ -822,45 +814,46 @@ static int exynos_dp_config_video(struct exynos_dp_device *dp) > return retval; > } > > -static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool enable) > +static void analogix_dp_enable_scramble(struct analogix_dp_device *dp, > + bool enable) > { > u8 data; > > if (enable) { > - exynos_dp_enable_scrambling(dp); > + analogix_dp_enable_scrambling(dp); > > - exynos_dp_read_byte_from_dpcd(dp, DP_TRAINING_PATTERN_SET, > - &data); > - exynos_dp_write_byte_to_dpcd( > - dp, DP_TRAINING_PATTERN_SET, > - (u8)(data & ~DP_LINK_SCRAMBLING_DISABLE)); > + analogix_dp_read_byte_from_dpcd( > + dp, DP_TRAINING_PATTERN_SET, &data); > + analogix_dp_write_byte_to_dpcd( > + dp, DP_TRAINING_PATTERN_SET, > + (u8)(data & ~DP_LINK_SCRAMBLING_DISABLE)); > } else { > - exynos_dp_disable_scrambling(dp); > + analogix_dp_disable_scrambling(dp); > > - exynos_dp_read_byte_from_dpcd(dp, DP_TRAINING_PATTERN_SET, > - &data); > - exynos_dp_write_byte_to_dpcd( > + analogix_dp_read_byte_from_dpcd(dp, DP_TRAINING_PATTERN_SET, > + &data); > + analogix_dp_write_byte_to_dpcd( > dp, DP_TRAINING_PATTERN_SET, > (u8)(data | DP_LINK_SCRAMBLING_DISABLE)); > } > } > > -static irqreturn_t exynos_dp_irq_handler(int irq, void *arg) > +static irqreturn_t analogix_dp_irq_handler(int irq, void *arg) > { > - struct exynos_dp_device *dp = arg; > + struct analogix_dp_device *dp = arg; > > enum dp_irq_type irq_type; > > - irq_type = exynos_dp_get_irq_type(dp); > + irq_type = analogix_dp_get_irq_type(dp); > switch (irq_type) { > case DP_IRQ_TYPE_HP_CABLE_IN: > dev_dbg(dp->dev, "Received irq - cable in\n"); > schedule_work(&dp->hotplug_work); > - exynos_dp_clear_hotplug_interrupts(dp); > + analogix_dp_clear_hotplug_interrupts(dp); > break; > case DP_IRQ_TYPE_HP_CABLE_OUT: > dev_dbg(dp->dev, "Received irq - cable out\n"); > - exynos_dp_clear_hotplug_interrupts(dp); > + analogix_dp_clear_hotplug_interrupts(dp); > break; > case DP_IRQ_TYPE_HP_CHANGE: > /* > @@ -869,7 +862,7 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg) > * only handle cable changes. > */ > dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n"); > - exynos_dp_clear_hotplug_interrupts(dp); > + analogix_dp_clear_hotplug_interrupts(dp); > break; > default: > dev_err(dp->dev, "Received irq - unknown type!\n"); > @@ -878,94 +871,93 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg) > return IRQ_HANDLED; > } > > -static void exynos_dp_hotplug(struct work_struct *work) > +static void analogix_dp_hotplug(struct work_struct *work) > { > - struct exynos_dp_device *dp; > + struct analogix_dp_device *dp; > > - dp = container_of(work, struct exynos_dp_device, hotplug_work); > + dp = container_of(work, struct analogix_dp_device, hotplug_work); > > if (dp->drm_dev) > drm_helper_hpd_irq_event(dp->drm_dev); > } > > -static void exynos_dp_commit(struct exynos_drm_display *display) > +static void analogix_dp_commit(struct analogix_dp_device *dp) > { > - struct exynos_dp_device *dp = display_to_dp(display); > int ret; > > /* Keep the panel disabled while we configure video */ > - if (dp->panel) { > - if (drm_panel_disable(dp->panel)) > + if (dp->plat_data && dp->plat_data->panel) { > + if (drm_panel_disable(dp->plat_data->panel)) > DRM_ERROR("failed to disable the panel\n"); > } > > - ret = exynos_dp_detect_hpd(dp); > + ret = analogix_dp_detect_hpd(dp); > if (ret) { > /* Cable has been disconnected, we're done */ > return; > } > > - ret = exynos_dp_handle_edid(dp); > + ret = analogix_dp_handle_edid(dp); > if (ret) { > dev_err(dp->dev, "unable to handle edid\n"); > return; > } > > - ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count, > - dp->video_info->link_rate); > + ret = analogix_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"); > return; > } > > - exynos_dp_enable_scramble(dp, 1); > - exynos_dp_enable_rx_to_enhanced_mode(dp, 1); > - exynos_dp_enable_enhanced_mode(dp, 1); > + analogix_dp_enable_scramble(dp, 1); > + analogix_dp_enable_rx_to_enhanced_mode(dp, 1); > + analogix_dp_enable_enhanced_mode(dp, 1); > > - exynos_dp_set_lane_count(dp, dp->video_info->lane_count); > - exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate); > + analogix_dp_set_lane_count(dp, dp->video_info->lane_count); > + analogix_dp_set_link_bandwidth(dp, dp->video_info->link_rate); > > - exynos_dp_init_video(dp); > - ret = exynos_dp_config_video(dp); > + analogix_dp_init_video(dp); > + ret = analogix_dp_config_video(dp); > if (ret) > dev_err(dp->dev, "unable to config video\n"); > > /* Safe to enable the panel now */ > - if (dp->panel) { > - if (drm_panel_enable(dp->panel)) > + if (dp->plat_data && dp->plat_data->panel) { > + if (drm_panel_enable(dp->plat_data->panel)) > DRM_ERROR("failed to enable the panel\n"); > } > } > > -static enum drm_connector_status exynos_dp_detect( > +static enum drm_connector_status analogix_dp_detect( > struct drm_connector *connector, bool force) > { > return connector_status_connected; > } > > -static void exynos_dp_connector_destroy(struct drm_connector *connector) > +static void analogix_dp_connector_destroy(struct drm_connector *connector) > { > drm_connector_unregister(connector); > drm_connector_cleanup(connector); > } > > -static struct drm_connector_funcs exynos_dp_connector_funcs = { > +static struct drm_connector_funcs analogix_dp_connector_funcs = { > .dpms = drm_atomic_helper_connector_dpms, > .fill_modes = drm_helper_probe_single_connector_modes, > - .detect = exynos_dp_detect, > - .destroy = exynos_dp_connector_destroy, > + .detect = analogix_dp_detect, > + .destroy = analogix_dp_connector_destroy, > .reset = drm_atomic_helper_connector_reset, > .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, > .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, > }; > > -static int exynos_dp_get_modes(struct drm_connector *connector) > +static int analogix_dp_get_modes(struct drm_connector *connector) > { > - struct exynos_dp_device *dp = ctx_from_connector(connector); > + struct analogix_dp_device *dp = connector_to_dp(connector); > struct drm_display_mode *mode; > > - if (dp->panel) > - return drm_panel_get_modes(dp->panel); > + if (dp->plat_data && dp->plat_data->panel) > + return drm_panel_get_modes(dp->plat_data->panel); > > mode = drm_mode_create(connector->dev); > if (!mode) { > @@ -986,64 +978,60 @@ static int exynos_dp_get_modes(struct drm_connector *connector) > return 1; > } > > -static struct drm_encoder *exynos_dp_best_encoder( > +static struct drm_encoder *analogix_dp_best_encoder( > struct drm_connector *connector) > { > - struct exynos_dp_device *dp = ctx_from_connector(connector); > + struct analogix_dp_device *dp = connector_to_dp(connector); > > return dp->encoder; > } > > -static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = { > - .get_modes = exynos_dp_get_modes, > - .best_encoder = exynos_dp_best_encoder, > +static struct drm_connector_helper_funcs analogix_dp_connector_helper_funcs = { > + .get_modes = analogix_dp_get_modes, > + .best_encoder = analogix_dp_best_encoder, > }; > > -static void exynos_dp_phy_init(struct exynos_dp_device *dp) > +static void analogix_dp_phy_init(struct analogix_dp_device *dp) > { > if (dp->phy) > phy_power_on(dp->phy); > } > > -static void exynos_dp_phy_exit(struct exynos_dp_device *dp) > +static void analogix_dp_phy_exit(struct analogix_dp_device *dp) > { > if (dp->phy) > phy_power_off(dp->phy); > } > > -static void exynos_dp_poweron(struct exynos_dp_device *dp) > +static void analogix_dp_poweron(struct analogix_dp_device *dp) > { > - struct exynos_drm_crtc *crtc = dp_to_crtc(dp); > - > if (dp->dpms_mode == DRM_MODE_DPMS_ON) > return; > > - if (dp->panel) { > - if (drm_panel_prepare(dp->panel)) { > + if (dp->plat_data && dp->plat_data->panel) { > + if (drm_panel_prepare(dp->plat_data->panel)) { > DRM_ERROR("failed to setup the panel\n"); > return; > } > } > > - if (crtc->ops->clock_enable) > - crtc->ops->clock_enable(dp_to_crtc(dp), true); > + if (dp->plat_data && dp->plat_data->power_on) > + dp->plat_data->power_on(dp->plat_data); > > clk_prepare_enable(dp->clock); > - exynos_dp_phy_init(dp); > - exynos_dp_init_dp(dp); > + analogix_dp_phy_init(dp); > + analogix_dp_init_dp(dp); > enable_irq(dp->irq); > - exynos_dp_commit(&dp->display); > + analogix_dp_commit(dp); > } > > -static void exynos_dp_poweroff(struct exynos_dp_device *dp) > +static void analogix_dp_poweroff(struct analogix_dp_device *dp) > { > - struct exynos_drm_crtc *crtc = dp_to_crtc(dp); > - > if (dp->dpms_mode != DRM_MODE_DPMS_ON) > return; > > - if (dp->panel) { > - if (drm_panel_disable(dp->panel)) { > + if (dp->plat_data && dp->plat_data->panel) { > + if (drm_panel_disable(dp->plat_data->panel)) { > DRM_ERROR("failed to disable the panel\n"); > return; > } > @@ -1051,39 +1039,21 @@ static void exynos_dp_poweroff(struct exynos_dp_device *dp) > > disable_irq(dp->irq); > flush_work(&dp->hotplug_work); > - exynos_dp_phy_exit(dp); > + analogix_dp_phy_exit(dp); > clk_disable_unprepare(dp->clock); > > - if (crtc->ops->clock_enable) > - crtc->ops->clock_enable(dp_to_crtc(dp), false); > + if (dp->plat_data && dp->plat_data->power_off) > + dp->plat_data->power_off(dp->plat_data); > > - if (dp->panel) { > - if (drm_panel_unprepare(dp->panel)) > + if (dp->plat_data && dp->plat_data->panel) { > + if (drm_panel_unprepare(dp->plat_data->panel)) > DRM_ERROR("failed to turnoff the panel\n"); > } > } > > -/* returns the number of bridges attached */ > -static int exynos_drm_attach_lcd_bridge(struct exynos_dp_device *dp, > - struct drm_encoder *encoder) > -{ > - int ret; > - > - dp->bridge->next = dp->ptn_bridge; > - dp->bridge->encoder = encoder; > - ret = drm_bridge_attach(encoder->dev, dp->bridge); > - if (ret) { > - DRM_ERROR("Failed to attach ptn bridge to drm\n"); > - return ret; > - } > - > - return 0; > -} > - > -static int exynos_dp_bridge_attach(struct drm_bridge *bridge) > +static int analogix_dp_bridge_attach(struct drm_bridge *bridge) > { > - > - struct exynos_dp_device *dp = bridge->driver_private; > + struct analogix_dp_device *dp = bridge->driver_private; > struct drm_encoder *encoder = dp->encoder; > struct drm_connector *connector = &dp->connector; > int ret; > @@ -1095,66 +1065,77 @@ static int exynos_dp_bridge_attach(struct drm_bridge *bridge) > > encoder->bridge = bridge; > > - /* Pre-empt DP connector creation if there's a bridge */ > - if (dp->ptn_bridge) { > - ret = exynos_drm_attach_lcd_bridge(dp, encoder); > - if (ret) > - return -ENODEV; > - } > - > connector->polled = DRM_CONNECTOR_POLL_HPD; > > ret = drm_connector_init(dp->drm_dev, connector, > - &exynos_dp_connector_funcs, DRM_MODE_CONNECTOR_eDP); > + &analogix_dp_connector_funcs, > + DRM_MODE_CONNECTOR_eDP); > if (ret) { > DRM_ERROR("Failed to initialize connector with drm\n"); > return ret; > } > > - drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs); > + drm_connector_helper_add(connector, > + &analogix_dp_connector_helper_funcs); > drm_connector_register(connector); > drm_mode_connector_attach_encoder(connector, encoder); > > - if (dp->panel) > - ret = drm_panel_attach(dp->panel, &dp->connector); > + if (dp->plat_data && dp->plat_data->panel) { > + ret = drm_panel_attach(dp->plat_data->panel, &dp->connector); > + if (ret) { > + DRM_ERROR("Failed to attach panel\n"); > + return ret; > + } > + } > + > + /* > + * This should be the end of attach function, caused > + * we should ensure dp bridge could attach first. > + */ > + if (dp->plat_data && dp->plat_data->attach) { > + ret = dp->plat_data->attach(dp->plat_data, bridge); > + if (ret) { > + DRM_ERROR("Failed at platform attch func\n"); > + return ret; > + } > + } > > - return ret; > + return 0; > } > > -static void exynos_dp_bridge_nop(struct drm_bridge *bridge) > +static void analogix_dp_bridge_nop(struct drm_bridge *bridge) > { > /* do nothing */ > } > > -static void exynos_dp_bridge_enable(struct drm_bridge *bridge) > +static void analogix_dp_bridge_enable(struct drm_bridge *bridge) > { > - struct exynos_dp_device *dp = bridge->driver_private; > + struct analogix_dp_device *dp = bridge->driver_private; > > - exynos_dp_poweron(dp); > + analogix_dp_poweron(dp); > dp->dpms_mode = DRM_MODE_DPMS_ON; > } > > -static void exynos_dp_bridge_disable(struct drm_bridge *bridge) > +static void analogix_dp_bridge_disable(struct drm_bridge *bridge) > { > - struct exynos_dp_device *dp = bridge->driver_private; > + struct analogix_dp_device *dp = bridge->driver_private; > > - exynos_dp_poweroff(dp); > + analogix_dp_poweroff(dp); > dp->dpms_mode = DRM_MODE_DPMS_OFF; > } > > -static const struct drm_bridge_funcs exynos_dp_bridge_funcs = { > - .enable = exynos_dp_bridge_enable, > - .disable = exynos_dp_bridge_disable, > - .pre_enable = exynos_dp_bridge_nop, > - .post_disable = exynos_dp_bridge_nop, > - .attach = exynos_dp_bridge_attach, > +static const struct drm_bridge_funcs analogix_dp_bridge_funcs = { > + .enable = analogix_dp_bridge_enable, > + .disable = analogix_dp_bridge_disable, > + .pre_enable = analogix_dp_bridge_nop, > + .post_disable = analogix_dp_bridge_nop, > + .attach = analogix_dp_bridge_attach, > }; > > -static int exynos_dp_create_connector(struct exynos_drm_display *display, > - struct drm_encoder *encoder) > +static int analogix_dp_bridge_register(struct drm_device *drm_dev, > + struct analogix_dp_device *dp) > + > { > - struct exynos_dp_device *dp = display_to_dp(display); > - struct drm_device *drm_dev = dp->drm_dev; > struct drm_bridge *bridge; > int ret; > > @@ -1165,11 +1146,10 @@ static int exynos_dp_create_connector(struct exynos_drm_display *display, > } > > dp->bridge = bridge; > - dp->encoder = encoder; > > bridge->driver_private = dp; > bridge->encoder = dp->encoder; > - bridge->funcs = &exynos_dp_bridge_funcs; > + bridge->funcs = &analogix_dp_bridge_funcs; > > ret = drm_bridge_attach(drm_dev, bridge); > if (ret) { > @@ -1180,18 +1160,7 @@ static int exynos_dp_create_connector(struct exynos_drm_display *display, > return 0; > } > > -static void exynos_dp_dpms(struct exynos_drm_display *display, int mode) > -{ > - /* do nothing */ > -} > - > -static struct exynos_drm_display_ops exynos_dp_display_ops = { > - .create_connector = exynos_dp_create_connector, > - .dpms = exynos_dp_dpms, > - .commit = exynos_dp_commit, > -}; > - > -static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev) > +static struct video_info *analogix_dp_dt_parse_pdata(struct device *dev) > { > struct device_node *dp_node = dev->of_node; > struct video_info *dp_video_config; > @@ -1249,7 +1218,7 @@ static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev) > return dp_video_config; > } > > -static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp) > +static int analogix_dp_dt_parse_panel(struct analogix_dp_device *dp) > { > int ret; > > @@ -1262,19 +1231,33 @@ static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp) > return 0; > } > > -static int exynos_dp_bind(struct device *dev, struct device *master, void *data) > +int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, > + struct drm_encoder *encoder, > + struct analogix_dp_plat_data *plat_data) > { > - struct exynos_dp_device *dp = dev_get_drvdata(dev); > struct platform_device *pdev = to_platform_device(dev); > - struct drm_device *drm_dev = data; > + struct analogix_dp_device *dp; > struct resource *res; > unsigned int irq_flags; > int ret = 0; > > + dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL); > + if (!dp) > + return -ENOMEM; > + > + dev_set_drvdata(dev, dp); > + > dp->dev = &pdev->dev; > dp->dpms_mode = DRM_MODE_DPMS_OFF; > > - dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev); > + /* > + * platform dp driver need containor_of the plat_data to get > + * the driver private data, so we need to store the point of > + * plat_data, not the context of plat_data. > + */ > + dp->plat_data = plat_data; > + > + dp->video_info = analogix_dp_dt_parse_pdata(&pdev->dev); > if (IS_ERR(dp->video_info)) > return PTR_ERR(dp->video_info); > > @@ -1294,8 +1277,8 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) > } > } > > - if (!dp->panel && !dp->ptn_bridge) { > - ret = exynos_dp_dt_parse_panel(dp); > + if (!dp->plat_data || !dp->plat_data->panel) { > + ret = analogix_dp_dt_parse_panel(dp); > if (ret) > return ret; > } > @@ -1343,14 +1326,14 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void > *data) > return -ENODEV; > } > > - INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug); > + INIT_WORK(&dp->hotplug_work, analogix_dp_hotplug); > > - exynos_dp_phy_init(dp); > + analogix_dp_phy_init(dp); > > - exynos_dp_init_dp(dp); > + analogix_dp_init_dp(dp); > > - ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, > - irq_flags, "exynos-dp", dp); > + ret = devm_request_irq(&pdev->dev, dp->irq, analogix_dp_irq_handler, > + irq_flags, "analogix-dp", dp); > if (ret) { > dev_err(&pdev->dev, "failed to request irq\n"); > return ret; > @@ -1358,109 +1341,39 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void > *data) > disable_irq(dp->irq); > > dp->drm_dev = drm_dev; > + dp->encoder = encoder; > > - return exynos_drm_create_enc_conn(drm_dev, &dp->display); > -} > - > -static void exynos_dp_unbind(struct device *dev, struct device *master, > - void *data) > -{ > - struct exynos_dp_device *dp = dev_get_drvdata(dev); > - > - exynos_dp_bridge_disable(dp->bridge); > -} > - > -static const struct component_ops exynos_dp_ops = { > - .bind = exynos_dp_bind, > - .unbind = exynos_dp_unbind, > -}; > - > -static int exynos_dp_probe(struct platform_device *pdev) > -{ > - struct device *dev = &pdev->dev; > - struct device_node *panel_node, *bridge_node, *endpoint; > - struct exynos_dp_device *dp; > - > - dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), > - GFP_KERNEL); > - if (!dp) > - return -ENOMEM; > - > - dp->display.type = EXYNOS_DISPLAY_TYPE_LCD; > - dp->display.ops = &exynos_dp_display_ops; > - platform_set_drvdata(pdev, dp); > - > - panel_node = of_parse_phandle(dev->of_node, "panel", 0); > - if (panel_node) { > - dp->panel = of_drm_find_panel(panel_node); > - of_node_put(panel_node); > - if (!dp->panel) > - return -EPROBE_DEFER; > - } > - > - endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); > - if (endpoint) { > - bridge_node = of_graph_get_remote_port_parent(endpoint); > - if (bridge_node) { > - dp->ptn_bridge = of_drm_find_bridge(bridge_node); > - of_node_put(bridge_node); > - if (!dp->ptn_bridge) > - return -EPROBE_DEFER; > - } else { > - return -EPROBE_DEFER; > - } > - } > - > - return component_add(&pdev->dev, &exynos_dp_ops); > + return analogix_dp_bridge_register(drm_dev, dp); > } > +EXPORT_SYMBOL_GPL(analogix_dp_bind); > > -static int exynos_dp_remove(struct platform_device *pdev) > +void analogix_dp_unbind(struct device *dev, struct device *master, void *data) > { > - component_del(&pdev->dev, &exynos_dp_ops); > + struct analogix_dp_device *dp = dev_get_drvdata(dev); > > - return 0; > + analogix_dp_bridge_disable(dp->bridge); > } > +EXPORT_SYMBOL_GPL(analogix_dp_unbind); > > -#ifdef CONFIG_PM_SLEEP > -static int exynos_dp_suspend(struct device *dev) > +int analogix_dp_suspend(struct device *dev) > { > - struct exynos_dp_device *dp = dev_get_drvdata(dev); > + struct analogix_dp_device *dp = dev_get_drvdata(dev); > > - exynos_dp_bridge_disable(dp->bridge); > + analogix_dp_bridge_disable(dp->bridge); > return 0; > } > +EXPORT_SYMBOL_GPL(analogix_dp_suspend); > > -static int exynos_dp_resume(struct device *dev) > +int analogix_dp_resume(struct device *dev) > { > - struct exynos_dp_device *dp = dev_get_drvdata(dev); > + struct analogix_dp_device *dp = dev_get_drvdata(dev); > > - exynos_dp_bridge_enable(dp->bridge); > + analogix_dp_bridge_enable(dp->bridge); > return 0; > } > -#endif > - > -static const struct dev_pm_ops exynos_dp_pm_ops = { > - SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume) > -}; > - > -static const struct of_device_id exynos_dp_match[] = { > - { .compatible = "samsung,exynos5-dp" }, > - {}, > -}; > -MODULE_DEVICE_TABLE(of, exynos_dp_match); > - > -struct platform_driver dp_driver = { > - .probe = exynos_dp_probe, > - .remove = exynos_dp_remove, > - .driver = { > - .name = "exynos-dp", > - .owner = THIS_MODULE, > - .pm = &exynos_dp_pm_ops, > - .of_match_table = exynos_dp_match, > - }, > -}; > +EXPORT_SYMBOL_GPL(analogix_dp_resume); > > MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); > MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>"); > -MODULE_DESCRIPTION("Samsung SoC DP Driver"); > +MODULE_DESCRIPTION("Analogix Core DP Driver"); > MODULE_LICENSE("GPL v2"); > diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix_dp_core.h > new file mode 100644 > index 0000000..fe72695 > --- /dev/null > +++ b/drivers/gpu/drm/bridge/analogix_dp_core.h > @@ -0,0 +1,286 @@ > +/* > + * Header file for Samsung DP (Display Port) interface driver. > + * > + * Copyright (C) 2012 Samsung Electronics Co., Ltd. > + * Author: Jingoo Han <jg1.han@samsung.com> > + * Yakir Yang <ykk@rock-chips.com> Please don't the author 'Yakir Yang'. This code is same with what I did. You just modified a little. > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of the GNU General Public License as published by the > + * Free Software Foundation; either version 2 of the License, or (at your > + * option) any later version. > + */ > + > +#ifndef _ANALOGIX_DP_CORE_H > +#define _ANALOGIX_DP_CORE_H > + > +#include <drm/drm_crtc.h> > +#include <drm/drm_dp_helper.h> > +#include <drm/exynos_drm.h> > + > +#define DP_TIMEOUT_LOOP_COUNT 100 > +#define MAX_CR_LOOP 5 > +#define MAX_EQ_LOOP 5 > + > +enum link_rate_type { > + LINK_RATE_1_62GBPS = 0x06, > + LINK_RATE_2_70GBPS = 0x0a > +}; > + > +enum link_lane_count_type { > + LANE_COUNT1 = 1, > + LANE_COUNT2 = 2, > + LANE_COUNT4 = 4 > +}; > + > +enum link_training_state { > + START, > + CLOCK_RECOVERY, > + EQUALIZER_TRAINING, > + FINISHED, > + FAILED > +}; > + > +enum voltage_swing_level { > + VOLTAGE_LEVEL_0, > + VOLTAGE_LEVEL_1, > + VOLTAGE_LEVEL_2, > + VOLTAGE_LEVEL_3, > +}; > + > +enum pre_emphasis_level { > + PRE_EMPHASIS_LEVEL_0, > + PRE_EMPHASIS_LEVEL_1, > + PRE_EMPHASIS_LEVEL_2, > + PRE_EMPHASIS_LEVEL_3, > +}; > + > +enum pattern_set { > + PRBS7, > + D10_2, > + TRAINING_PTN1, > + TRAINING_PTN2, > + DP_NONE > +}; > + > +enum color_space { > + COLOR_RGB, > + COLOR_YCBCR422, > + COLOR_YCBCR444 > +}; > + > +enum color_depth { > + COLOR_6, > + COLOR_8, > + COLOR_10, > + COLOR_12 > +}; > + > +enum color_coefficient { > + COLOR_YCBCR601, > + COLOR_YCBCR709 > +}; > + > +enum dynamic_range { > + VESA, > + CEA > +}; > + > +enum pll_status { > + PLL_UNLOCKED, > + PLL_LOCKED > +}; > + > +enum clock_recovery_m_value_type { > + CALCULATED_M, > + REGISTER_M > +}; > + > +enum video_timing_recognition_type { > + VIDEO_TIMING_FROM_CAPTURE, > + VIDEO_TIMING_FROM_REGISTER > +}; > + > +enum analog_power_block { > + AUX_BLOCK, > + CH0_BLOCK, > + CH1_BLOCK, > + CH2_BLOCK, > + CH3_BLOCK, > + ANALOG_TOTAL, > + POWER_ALL > +}; > + > +enum dp_irq_type { > + DP_IRQ_TYPE_HP_CABLE_IN, > + DP_IRQ_TYPE_HP_CABLE_OUT, > + DP_IRQ_TYPE_HP_CHANGE, > + DP_IRQ_TYPE_UNKNOWN, > +}; > + > +struct video_info { > + char *name; > + > + bool h_sync_polarity; > + bool v_sync_polarity; > + bool interlaced; > + > + enum color_space color_space; > + enum dynamic_range dynamic_range; > + enum color_coefficient ycbcr_coeff; > + enum color_depth color_depth; > + > + enum link_rate_type link_rate; > + enum link_lane_count_type lane_count; > +}; > + > +struct link_train { > + int eq_loop; > + int cr_loop[4]; > + > + u8 link_rate; > + u8 lane_count; > + u8 training_lane[4]; > + > + enum link_training_state lt_state; > +}; > + > +struct analogix_dp_device { > + struct device *dev; > + struct drm_device *drm_dev; > + struct drm_connector connector; > + struct drm_encoder *encoder; > + struct drm_bridge *bridge; > + struct clk *clock; > + unsigned int irq; > + void __iomem *reg_base; > + > + struct video_info *video_info; > + struct link_train link_train; > + struct work_struct hotplug_work; > + struct phy *phy; > + int dpms_mode; > + int hpd_gpio; > + > + struct analogix_dp_plat_data *plat_data; > + > + struct exynos_drm_panel_info priv; > +}; > + > +/* analogix_dp_reg.c */ > +void analogix_dp_enable_video_mute(struct analogix_dp_device *dp, bool enable); > +void analogix_dp_stop_video(struct analogix_dp_device *dp); > +void analogix_dp_lane_swap(struct analogix_dp_device *dp, bool enable); > +void analogix_dp_init_analog_param(struct analogix_dp_device *dp); > +void analogix_dp_init_interrupt(struct analogix_dp_device *dp); > +void analogix_dp_reset(struct analogix_dp_device *dp); > +void analogix_dp_swreset(struct analogix_dp_device *dp); > +void analogix_dp_config_interrupt(struct analogix_dp_device *dp); > +enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp); > +void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable); > +void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp, > + enum analog_power_block block, > + bool enable); > +void analogix_dp_init_analog_func(struct analogix_dp_device *dp); > +void analogix_dp_init_hpd(struct analogix_dp_device *dp); > +enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp); > +void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp); > +void analogix_dp_reset_aux(struct analogix_dp_device *dp); > +void analogix_dp_init_aux(struct analogix_dp_device *dp); > +int analogix_dp_get_plug_in_status(struct analogix_dp_device *dp); > +void analogix_dp_enable_sw_function(struct analogix_dp_device *dp); > +int analogix_dp_start_aux_transaction(struct analogix_dp_device *dp); > +int analogix_dp_write_byte_to_dpcd(struct analogix_dp_device *dp, > + unsigned int reg_addr, > + unsigned char data); > +int analogix_dp_read_byte_from_dpcd(struct analogix_dp_device *dp, > + unsigned int reg_addr, > + unsigned char *data); > +int analogix_dp_write_bytes_to_dpcd(struct analogix_dp_device *dp, > + unsigned int reg_addr, > + unsigned int count, > + unsigned char data[]); > +int analogix_dp_read_bytes_from_dpcd(struct analogix_dp_device *dp, > + unsigned int reg_addr, > + unsigned int count, > + unsigned char data[]); > +int analogix_dp_select_i2c_device(struct analogix_dp_device *dp, > + unsigned int device_addr, > + unsigned int reg_addr); > +int analogix_dp_read_byte_from_i2c(struct analogix_dp_device *dp, > + unsigned int device_addr, > + unsigned int reg_addr, > + unsigned int *data); > +int analogix_dp_read_bytes_from_i2c(struct analogix_dp_device *dp, > + unsigned int device_addr, > + unsigned int reg_addr, > + unsigned int count, > + unsigned char edid[]); > +void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype); > +void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype); > +void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count); > +void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count); > +void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp, > + bool enable); > +void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, > + enum pattern_set pattern); > +void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp, > + u32 level); > +void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp, > + u32 level); > +void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp, > + u32 level); > +void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp, > + u32 level); > +void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp, > + u32 training_lane); > +void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp, > + u32 training_lane); > +void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp, > + u32 training_lane); > +void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp, > + u32 training_lane); > +u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp); > +u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp); > +u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp); > +u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp); > +void analogix_dp_reset_macro(struct analogix_dp_device *dp); > +void analogix_dp_init_video(struct analogix_dp_device *dp); > + > +void analogix_dp_set_video_color_format(struct analogix_dp_device *dp); > +int analogix_dp_is_slave_video_stream_clock_on(struct analogix_dp_device *dp); > +void analogix_dp_set_video_cr_mn(struct analogix_dp_device *dp, > + enum clock_recovery_m_value_type type, > + u32 m_value, u32 n_value); > +void analogix_dp_set_video_timing_mode(struct analogix_dp_device *dp, u32 type); > +void analogix_dp_enable_video_master(struct analogix_dp_device *dp, > + bool enable); > +void analogix_dp_start_video(struct analogix_dp_device *dp); > +int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp); > +void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp); > +void analogix_dp_enable_scrambling(struct analogix_dp_device *dp); > +void analogix_dp_disable_scrambling(struct analogix_dp_device *dp); > + > +/* 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 > + > +/* DP_MAX_LANE_COUNT */ > +#define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1) > +#define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f) > + > +/* DP_LANE_COUNT_SET */ > +#define DPCD_LANE_COUNT_SET(x) ((x) & 0x1f) > + > +/* DP_TRAINING_LANE0_SET */ > +#define DPCD_PRE_EMPHASIS_SET(x) (((x) & 0x3) << 3) > +#define DPCD_PRE_EMPHASIS_GET(x) (((x) >> 3) & 0x3) > +#define DPCD_VOLTAGE_SWING_SET(x) (((x) & 0x3) << 0) > +#define DPCD_VOLTAGE_SWING_GET(x) (((x) >> 0) & 0x3) > + > +#endif /* _ANALOGIX_DP_CORE_H */ > diff --git a/drivers/gpu/drm/bridge/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix_dp_reg.c > new file mode 100644 > index 0000000..dfbbde7 > --- /dev/null > +++ b/drivers/gpu/drm/bridge/analogix_dp_reg.c > @@ -0,0 +1,1266 @@ > +/* > + * Samsung DP (Display port) register interface driver. > + * > + * Copyright (C) 2012 Samsung Electronics Co., Ltd. > + * Author: Jingoo Han <jg1.han@samsung.com> > + * Yakir Yang <ykk@rock-chips.com> The same as above. > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of the GNU General Public License as published by the > + * Free Software Foundation; either version 2 of the License, or (at your > + * option) any later version. > + */ > + > +#include <linux/device.h> > +#include <linux/io.h> > +#include <linux/delay.h> > +#include <linux/gpio.h> > + > +#include "analogix_dp_core.h" > +#include "analogix_dp_reg.h" > + > +#define COMMON_INT_MASK_1 0 > +#define COMMON_INT_MASK_2 0 > +#define COMMON_INT_MASK_3 0 > +#define COMMON_INT_MASK_4 (HOTPLUG_CHG | HPD_LOST | PLUG) > +#define INT_STA_MASK INT_HPD > + > +void analogix_dp_enable_video_mute(struct analogix_dp_device *dp, bool enable) > +{ > + u32 reg; > + > + if (enable) { > + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); > + reg |= HDCP_VIDEO_MUTE; > + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); > + } else { > + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); > + reg &= ~HDCP_VIDEO_MUTE; > + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); > + } > +} > + > +void analogix_dp_stop_video(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); > + reg &= ~VIDEO_EN; > + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); > +} > + > +void analogix_dp_lane_swap(struct analogix_dp_device *dp, bool enable) > +{ > + u32 reg; > + > + if (enable) > + reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 | > + LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3; > + else > + reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 | > + LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0; > + > + writel(reg, dp->reg_base + ANALOGIX_DP_LANE_MAP); > +} > + > +void analogix_dp_init_analog_param(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + reg = TX_TERMINAL_CTRL_50_OHM; > + writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_1); > + > + reg = SEL_24M | TX_DVDD_BIT_1_0625V; > + writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_2); > + > + reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO; > + writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_3); > + > + reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM | > + TX_CUR1_2X | TX_CUR_16_MA; > + writel(reg, dp->reg_base + ANALOGIX_DP_PLL_FILTER_CTL_1); > + > + reg = CH3_AMP_400_MV | CH2_AMP_400_MV | > + CH1_AMP_400_MV | CH0_AMP_400_MV; > + writel(reg, dp->reg_base + ANALOGIX_DP_TX_AMP_TUNING_CTL); > +} > + > +void analogix_dp_init_interrupt(struct analogix_dp_device *dp) > +{ > + /* Set interrupt pin assertion polarity as high */ > + writel(INT_POL1 | INT_POL0, dp->reg_base + ANALOGIX_DP_INT_CTL); > + > + /* Clear pending regisers */ > + writel(0xff, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1); > + writel(0x4f, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_2); > + writel(0xe0, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_3); > + writel(0xe7, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4); > + writel(0x63, dp->reg_base + ANALOGIX_DP_INT_STA); > + > + /* 0:mask,1: unmask */ > + writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_1); > + writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2); > + writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3); > + writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4); > + writel(0x00, dp->reg_base + ANALOGIX_DP_INT_STA_MASK); > +} > + > +void analogix_dp_reset(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + analogix_dp_stop_video(dp); > + analogix_dp_enable_video_mute(dp, 0); > + > + reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N | > + AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N | > + HDCP_FUNC_EN_N | SW_FUNC_EN_N; > + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1); > + > + reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N | > + SERDES_FIFO_FUNC_EN_N | > + LS_CLK_DOMAIN_FUNC_EN_N; > + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); > + > + usleep_range(20, 30); > + > + analogix_dp_lane_swap(dp, 0); > + > + writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_1); > + writel(0x40, dp->reg_base + ANALOGIX_DP_SYS_CTL_2); > + writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); > + writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); > + > + writel(0x0, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); > + writel(0x0, dp->reg_base + ANALOGIX_DP_HDCP_CTL); > + > + writel(0x5e, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_L); > + writel(0x1a, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_H); > + > + writel(0x10, dp->reg_base + ANALOGIX_DP_LINK_DEBUG_CTL); > + > + writel(0x0, dp->reg_base + ANALOGIX_DP_PHY_TEST); > + > + writel(0x0, dp->reg_base + ANALOGIX_DP_VIDEO_FIFO_THRD); > + writel(0x20, dp->reg_base + ANALOGIX_DP_AUDIO_MARGIN); > + > + writel(0x4, dp->reg_base + ANALOGIX_DP_M_VID_GEN_FILTER_TH); > + writel(0x2, dp->reg_base + ANALOGIX_DP_M_AUD_GEN_FILTER_TH); > + > + writel(0x00000101, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); > +} > + > +void analogix_dp_swreset(struct analogix_dp_device *dp) > +{ > + writel(RESET_DP_TX, dp->reg_base + ANALOGIX_DP_TX_SW_RESET); > +} > + > +void analogix_dp_config_interrupt(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + /* 0: mask, 1: unmask */ > + reg = COMMON_INT_MASK_1; > + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_1); > + > + reg = COMMON_INT_MASK_2; > + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2); > + > + reg = COMMON_INT_MASK_3; > + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3); > + > + reg = COMMON_INT_MASK_4; > + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4); > + > + reg = INT_STA_MASK; > + writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK); > +} > + > +enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_DEBUG_CTL); > + if (reg & PLL_LOCK) > + return PLL_LOCKED; > + else > + return PLL_UNLOCKED; > +} > + > +void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable) > +{ > + u32 reg; > + > + if (enable) { > + reg = readl(dp->reg_base + ANALOGIX_DP_PLL_CTL); > + reg |= DP_PLL_PD; > + writel(reg, dp->reg_base + ANALOGIX_DP_PLL_CTL); > + } else { > + reg = readl(dp->reg_base + ANALOGIX_DP_PLL_CTL); > + reg &= ~DP_PLL_PD; > + writel(reg, dp->reg_base + ANALOGIX_DP_PLL_CTL); > + } > +} > + > +void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp, > + enum analog_power_block block, > + bool enable) > +{ > + u32 reg; > + > + switch (block) { > + case AUX_BLOCK: > + if (enable) { > + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); > + reg |= AUX_PD; > + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); > + } else { > + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); > + reg &= ~AUX_PD; > + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); > + } > + break; > + case CH0_BLOCK: > + if (enable) { > + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); > + reg |= CH0_PD; > + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); > + } else { > + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); > + reg &= ~CH0_PD; > + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); > + } > + break; > + case CH1_BLOCK: > + if (enable) { > + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); > + reg |= CH1_PD; > + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); > + } else { > + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); > + reg &= ~CH1_PD; > + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); > + } > + break; > + case CH2_BLOCK: > + if (enable) { > + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); > + reg |= CH2_PD; > + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); > + } else { > + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); > + reg &= ~CH2_PD; > + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); > + } > + break; > + case CH3_BLOCK: > + if (enable) { > + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); > + reg |= CH3_PD; > + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); > + } else { > + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); > + reg &= ~CH3_PD; > + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); > + } > + break; > + case ANALOG_TOTAL: > + if (enable) { > + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); > + reg |= DP_PHY_PD; > + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); > + } else { > + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); > + reg &= ~DP_PHY_PD; > + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); > + } > + break; > + case POWER_ALL: > + if (enable) { > + reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD | > + CH1_PD | CH0_PD; > + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); > + } else { > + writel(0x00, dp->reg_base + ANALOGIX_DP_PHY_PD); > + } > + break; > + default: > + break; > + } > +} > + > +void analogix_dp_init_analog_func(struct analogix_dp_device *dp) > +{ > + u32 reg; > + int timeout_loop = 0; > + > + analogix_dp_set_analog_power_down(dp, POWER_ALL, 0); > + > + reg = PLL_LOCK_CHG; > + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1); > + > + reg = readl(dp->reg_base + ANALOGIX_DP_DEBUG_CTL); > + reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL); > + writel(reg, dp->reg_base + ANALOGIX_DP_DEBUG_CTL); > + > + /* Power up PLL */ > + if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { > + analogix_dp_set_pll_power_down(dp, 0); > + > + while (analogix_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"); > + return; > + } > + usleep_range(10, 20); > + } > + } > + > + /* Enable Serdes FIFO function and Link symbol clock domain module */ > + reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2); > + reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N > + | AUX_FUNC_EN_N); > + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); > +} > + > +void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + if (gpio_is_valid(dp->hpd_gpio)) > + return; > + > + reg = HOTPLUG_CHG | HPD_LOST | PLUG; > + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4); > + > + reg = INT_HPD; > + writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA); > +} > + > +void analogix_dp_init_hpd(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + if (gpio_is_valid(dp->hpd_gpio)) > + return; > + > + analogix_dp_clear_hotplug_interrupts(dp); > + > + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3); > + reg &= ~(F_HPD | HPD_CTRL); > + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); > +} > + > +enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + if (gpio_is_valid(dp->hpd_gpio)) { > + reg = gpio_get_value(dp->hpd_gpio); > + if (reg) > + return DP_IRQ_TYPE_HP_CABLE_IN; > + else > + return DP_IRQ_TYPE_HP_CABLE_OUT; > + } else { > + /* Parse hotplug interrupt status register */ > + reg = readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4); > + > + if (reg & PLUG) > + return DP_IRQ_TYPE_HP_CABLE_IN; > + > + if (reg & HPD_LOST) > + return DP_IRQ_TYPE_HP_CABLE_OUT; > + > + if (reg & HOTPLUG_CHG) > + return DP_IRQ_TYPE_HP_CHANGE; > + > + return DP_IRQ_TYPE_UNKNOWN; > + } > +} > + > +void analogix_dp_reset_aux(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + /* Disable AUX channel module */ > + reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2); > + reg |= AUX_FUNC_EN_N; > + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); > +} > + > +void analogix_dp_init_aux(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + /* Clear inerrupts related to AUX channel */ > + reg = RPLY_RECEIV | AUX_ERR; > + writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA); > + > + analogix_dp_reset_aux(dp); > + > + /* Disable AUX transaction H/W retry */ > + reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0) | > + AUX_HW_RETRY_INTERVAL_600_MICROSECONDS; > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_HW_RETRY_CTL); > + > + /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */ > + reg = DEFER_CTRL_EN | DEFER_COUNT(1); > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_DEFER_CTL); > + > + /* Enable AUX channel module */ > + reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2); > + reg &= ~AUX_FUNC_EN_N; > + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); > +} > + > +int analogix_dp_get_plug_in_status(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + if (gpio_is_valid(dp->hpd_gpio)) { > + if (gpio_get_value(dp->hpd_gpio)) > + return 0; > + } else { > + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3); > + if (reg & HPD_STATUS) > + return 0; > + } > + > + return -EINVAL; > +} > + > +void analogix_dp_enable_sw_function(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_1); > + reg &= ~SW_FUNC_EN_N; > + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1); > +} > + > +int analogix_dp_start_aux_transaction(struct analogix_dp_device *dp) > +{ > + int reg; > + int retval = 0; > + int timeout_loop = 0; > + > + /* Enable AUX CH operation */ > + reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2); > + reg |= AUX_EN; > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2); > + > + /* Is AUX CH command reply received? */ > + reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA); > + while (!(reg & RPLY_RECEIV)) { > + timeout_loop++; > + if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { > + dev_err(dp->dev, "AUX CH command reply failed!\n"); > + return -ETIMEDOUT; > + } > + reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA); > + usleep_range(10, 11); > + } > + > + /* Clear interrupt source for AUX CH command reply */ > + writel(RPLY_RECEIV, dp->reg_base + ANALOGIX_DP_INT_STA); > + > + /* Clear interrupt source for AUX CH access error */ > + reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA); > + if (reg & AUX_ERR) { > + writel(AUX_ERR, dp->reg_base + ANALOGIX_DP_INT_STA); > + return -EREMOTEIO; > + } > + > + /* Check AUX CH error access status */ > + reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_STA); > + if ((reg & AUX_STATUS_MASK) != 0) { > + dev_err(dp->dev, "AUX CH error happens: %d\n\n", > + reg & AUX_STATUS_MASK); > + return -EREMOTEIO; > + } > + > + return retval; > +} > + > +int analogix_dp_write_byte_to_dpcd(struct analogix_dp_device *dp, > + unsigned int reg_addr, > + unsigned char data) > +{ > + u32 reg; > + int i; > + int retval; > + > + for (i = 0; i < 3; i++) { > + /* Clear AUX CH data buffer */ > + reg = BUF_CLR; > + writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); > + > + /* Select DPCD device address */ > + reg = AUX_ADDR_7_0(reg_addr); > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); > + reg = AUX_ADDR_15_8(reg_addr); > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); > + reg = AUX_ADDR_19_16(reg_addr); > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16); > + > + /* Write data buffer */ > + reg = (unsigned int)data; > + writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0); > + > + /* > + * 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->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); > + > + /* Start AUX transaction */ > + retval = analogix_dp_start_aux_transaction(dp); > + if (retval == 0) > + break; > + > + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); > + } > + > + return retval; > +} > + > +int analogix_dp_read_byte_from_dpcd(struct analogix_dp_device *dp, > + unsigned int reg_addr, > + unsigned char *data) > +{ > + u32 reg; > + int i; > + int retval; > + > + for (i = 0; i < 3; i++) { > + /* Clear AUX CH data buffer */ > + reg = BUF_CLR; > + writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); > + > + /* Select DPCD device address */ > + reg = AUX_ADDR_7_0(reg_addr); > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); > + reg = AUX_ADDR_15_8(reg_addr); > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); > + reg = AUX_ADDR_19_16(reg_addr); > + writel(reg, dp->reg_base + ANALOGIX_DP_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; > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); > + > + /* Start AUX transaction */ > + retval = analogix_dp_start_aux_transaction(dp); > + if (retval == 0) > + break; > + > + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); > + } > + > + /* Read data buffer */ > + reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0); > + *data = (unsigned char)(reg & 0xff); > + > + return retval; > +} > + > +int analogix_dp_write_bytes_to_dpcd(struct analogix_dp_device *dp, > + unsigned int reg_addr, > + unsigned int count, > + unsigned char data[]) > +{ > + u32 reg; > + unsigned int start_offset; > + unsigned int cur_data_count; > + unsigned int cur_data_idx; > + int i; > + int retval = 0; > + > + /* Clear AUX CH data buffer */ > + reg = BUF_CLR; > + writel(reg, dp->reg_base + ANALOGIX_DP_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; > + > + for (i = 0; i < 3; i++) { > + /* Select DPCD device address */ > + reg = AUX_ADDR_7_0(reg_addr + start_offset); > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); > + reg = AUX_ADDR_15_8(reg_addr + start_offset); > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); > + reg = AUX_ADDR_19_16(reg_addr + start_offset); > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16); > + > + for (cur_data_idx = 0; cur_data_idx < cur_data_count; > + cur_data_idx++) { > + reg = data[start_offset + cur_data_idx]; > + writel(reg, dp->reg_base + > + ANALOGIX_DP_BUF_DATA_0 + > + 4 * cur_data_idx); > + } > + > + /* > + * Set DisplayPort transaction and write > + * 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_WRITE; > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); > + > + /* Start AUX transaction */ > + retval = analogix_dp_start_aux_transaction(dp); > + if (retval == 0) > + break; > + > + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", > + __func__); > + } > + > + start_offset += cur_data_count; > + } > + > + return retval; > +} > + > +int analogix_dp_read_bytes_from_dpcd(struct analogix_dp_device *dp, > + unsigned int reg_addr, > + unsigned int count, > + unsigned char data[]) > +{ > + u32 reg; > + unsigned int start_offset; > + unsigned int cur_data_count; > + unsigned int cur_data_idx; > + int i; > + int retval = 0; > + > + /* Clear AUX CH data buffer */ > + reg = BUF_CLR; > + writel(reg, dp->reg_base + ANALOGIX_DP_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; > + > + /* AUX CH Request Transaction process */ > + for (i = 0; i < 3; i++) { > + /* Select DPCD device address */ > + reg = AUX_ADDR_7_0(reg_addr + start_offset); > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); > + reg = AUX_ADDR_15_8(reg_addr + start_offset); > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); > + reg = AUX_ADDR_19_16(reg_addr + start_offset); > + writel(reg, dp->reg_base + ANALOGIX_DP_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; > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); > + > + /* Start AUX transaction */ > + retval = analogix_dp_start_aux_transaction(dp); > + if (retval == 0) > + break; > + > + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", > + __func__); > + } > + > + for (cur_data_idx = 0; cur_data_idx < cur_data_count; > + cur_data_idx++) { > + reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 > + + 4 * cur_data_idx); > + data[start_offset + cur_data_idx] = > + (unsigned char)reg; > + } > + > + start_offset += cur_data_count; > + } > + > + return retval; > +} > + > +int analogix_dp_select_i2c_device(struct analogix_dp_device *dp, > + unsigned int device_addr, > + unsigned int reg_addr) > +{ > + u32 reg; > + int retval; > + > + /* Set EDID device address */ > + reg = device_addr; > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); > + writel(0x0, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); > + writel(0x0, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16); > + > + /* Set offset from base address of EDID device */ > + writel(reg_addr, dp->reg_base + ANALOGIX_DP_BUF_DATA_0); > + > + /* > + * 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; > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); > + > + /* Start AUX transaction */ > + retval = analogix_dp_start_aux_transaction(dp); > + if (retval != 0) > + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); > + > + return retval; > +} > + > +int analogix_dp_read_byte_from_i2c(struct analogix_dp_device *dp, > + unsigned int device_addr, > + unsigned int reg_addr, > + unsigned int *data) > +{ > + u32 reg; > + int i; > + int retval; > + > + for (i = 0; i < 3; i++) { > + /* Clear AUX CH data buffer */ > + reg = BUF_CLR; > + writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); > + > + /* Select EDID device */ > + retval = analogix_dp_select_i2c_device(dp, device_addr, > + reg_addr); > + if (retval != 0) > + 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; > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); > + > + /* Start AUX transaction */ > + retval = analogix_dp_start_aux_transaction(dp); > + if (retval == 0) > + break; > + > + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); > + } > + > + /* Read data */ > + if (retval == 0) > + *data = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0); > + > + return retval; > +} > + > +int analogix_dp_read_bytes_from_i2c(struct analogix_dp_device *dp, > + unsigned int device_addr, > + unsigned int 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) { > + for (j = 0; j < 3; j++) { > + /* Clear AUX CH data buffer */ > + reg = BUF_CLR; > + writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); > + > + /* Set normal AUX CH command */ > + reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2); > + reg &= ~ADDR_ONLY; > + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2); > + > + /* > + * If Rx sends defer, Tx sends only reads > + * request without sending address > + */ > + if (!defer) > + retval = analogix_dp_select_i2c_device( > + dp, device_addr, reg_addr + i); > + else > + defer = 0; > + > + if (retval == 0) { > + /* > + * 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; > + writel(reg, dp->reg_base + > + ANALOGIX_DP_AUX_CH_CTL_1); > + > + /* Start AUX transaction */ > + retval = analogix_dp_start_aux_transaction(dp); > + if (retval == 0) > + break; > + > + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", > + __func__); > + } > + /* Check if Rx sends defer */ > + reg = readl(dp->reg_base + ANALOGIX_DP_AUX_RX_COMM); > + if (reg == AUX_RX_COMM_AUX_DEFER || > + reg == AUX_RX_COMM_I2C_DEFER) { > + dev_err(dp->dev, "Defer: %d\n\n", reg); > + defer = 1; > + } > + } > + > + for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) { > + reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 > + + 4 * cur_data_idx); > + edid[i + cur_data_idx] = (unsigned char)reg; > + } > + } > + > + return retval; > +} > + > +void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype) > +{ > + u32 reg; > + > + reg = bwtype; > + if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype == LINK_RATE_1_62GBPS)) > + writel(reg, dp->reg_base + ANALOGIX_DP_LINK_BW_SET); > +} > + > +void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_LINK_BW_SET); > + *bwtype = reg; > +} > + > +void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count) > +{ > + u32 reg; > + > + reg = count; > + writel(reg, dp->reg_base + ANALOGIX_DP_LANE_COUNT_SET); > +} > + > +void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_LANE_COUNT_SET); > + *count = reg; > +} > + > +void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp, > + bool enable) > +{ > + u32 reg; > + > + if (enable) { > + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4); > + reg |= ENHANCED; > + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); > + } else { > + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4); > + reg &= ~ENHANCED; > + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); > + } > +} > + > +void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, > + enum pattern_set pattern) > +{ > + u32 reg; > + > + switch (pattern) { > + case PRBS7: > + reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7; > + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); > + break; > + case D10_2: > + reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2; > + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); > + break; > + case TRAINING_PTN1: > + reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1; > + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); > + break; > + case TRAINING_PTN2: > + reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2; > + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); > + break; > + case DP_NONE: > + reg = SCRAMBLING_ENABLE | > + LINK_QUAL_PATTERN_SET_DISABLE | > + SW_TRAINING_PATTERN_SET_NORMAL; > + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); > + break; > + default: > + break; > + } > +} > + > +void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp, > + u32 level) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); > + reg &= ~PRE_EMPHASIS_SET_MASK; > + reg |= level << PRE_EMPHASIS_SET_SHIFT; > + writel(reg, dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); > +} > + > +void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp, > + u32 level) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); > + reg &= ~PRE_EMPHASIS_SET_MASK; > + reg |= level << PRE_EMPHASIS_SET_SHIFT; > + writel(reg, dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); > +} > + > +void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp, > + u32 level) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); > + reg &= ~PRE_EMPHASIS_SET_MASK; > + reg |= level << PRE_EMPHASIS_SET_SHIFT; > + writel(reg, dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); > +} > + > +void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp, > + u32 level) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); > + reg &= ~PRE_EMPHASIS_SET_MASK; > + reg |= level << PRE_EMPHASIS_SET_SHIFT; > + writel(reg, dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); > +} > + > +void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp, > + u32 training_lane) > +{ > + u32 reg; > + > + reg = training_lane; > + writel(reg, dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); > +} > + > +void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp, > + u32 training_lane) > +{ > + u32 reg; > + > + reg = training_lane; > + writel(reg, dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); > +} > + > +void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp, > + u32 training_lane) > +{ > + u32 reg; > + > + reg = training_lane; > + writel(reg, dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); > +} > + > +void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp, > + u32 training_lane) > +{ > + u32 reg; > + > + reg = training_lane; > + writel(reg, dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); > +} > + > +u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); > + return reg; > +} > + > +u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); > + return reg; > +} > + > +u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); > + return reg; > +} > + > +u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); > + return reg; > +} > + > +void analogix_dp_reset_macro(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_TEST); > + reg |= MACRO_RST; > + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_TEST); > + > + /* 10 us is the minimum reset time. */ > + usleep_range(10, 20); > + > + reg &= ~MACRO_RST; > + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_TEST); > +} > + > +void analogix_dp_init_video(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG; > + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1); > + > + reg = 0x0; > + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_1); > + > + reg = CHA_CRI(4) | CHA_CTRL; > + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_2); > + > + reg = 0x0; > + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); > + > + reg = VID_HRES_TH(2) | VID_VRES_TH(0); > + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_8); > +} > + > +void analogix_dp_set_video_color_format(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + /* Configure the input color depth, color space, dynamic range */ > + reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) | > + (dp->video_info->color_depth << IN_BPC_SHIFT) | > + (dp->video_info->color_space << IN_COLOR_F_SHIFT); > + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_2); > + > + /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */ > + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3); > + reg &= ~IN_YC_COEFFI_MASK; > + if (dp->video_info->ycbcr_coeff) > + reg |= IN_YC_COEFFI_ITU709; > + else > + reg |= IN_YC_COEFFI_ITU601; > + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3); > +} > + > +int analogix_dp_is_slave_video_stream_clock_on(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_1); > + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_1); > + > + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_1); > + > + if (!(reg & DET_STA)) { > + dev_dbg(dp->dev, "Input stream clock not detected.\n"); > + return -EINVAL; > + } > + > + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_2); > + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_2); > + > + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_2); > + dev_dbg(dp->dev, "wait SYS_CTL_2.\n"); > + > + if (reg & CHA_STA) { > + dev_dbg(dp->dev, "Input stream clk is changing\n"); > + return -EINVAL; > + } > + > + return 0; > +} > + > +void analogix_dp_set_video_cr_mn(struct analogix_dp_device *dp, > + enum clock_recovery_m_value_type type, > + u32 m_value, u32 n_value) > +{ > + u32 reg; > + > + if (type == REGISTER_M) { > + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4); > + reg |= FIX_M_VID; > + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); > + reg = m_value & 0xff; > + writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_0); > + reg = (m_value >> 8) & 0xff; > + writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_1); > + reg = (m_value >> 16) & 0xff; > + writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_2); > + > + reg = n_value & 0xff; > + writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_0); > + reg = (n_value >> 8) & 0xff; > + writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_1); > + reg = (n_value >> 16) & 0xff; > + writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_2); > + } else { > + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4); > + reg &= ~FIX_M_VID; > + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); > + > + writel(0x00, dp->reg_base + ANALOGIX_DP_N_VID_0); > + writel(0x80, dp->reg_base + ANALOGIX_DP_N_VID_1); > + writel(0x00, dp->reg_base + ANALOGIX_DP_N_VID_2); > + } > +} > + > +void analogix_dp_set_video_timing_mode(struct analogix_dp_device *dp, u32 type) > +{ > + u32 reg; > + > + if (type == VIDEO_TIMING_FROM_CAPTURE) { > + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); > + reg &= ~FORMAT_SEL; > + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); > + } else { > + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); > + reg |= FORMAT_SEL; > + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); > + } > +} > + > +void analogix_dp_enable_video_master(struct analogix_dp_device *dp, bool enable) > +{ > + u32 reg; > + > + if (enable) { > + reg = readl(dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); > + reg &= ~VIDEO_MODE_MASK; > + reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE; > + writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); > + } else { > + reg = readl(dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); > + reg &= ~VIDEO_MODE_MASK; > + reg |= VIDEO_MODE_SLAVE_MODE; > + writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); > + } > +} > + > +void analogix_dp_start_video(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); > + reg |= VIDEO_EN; > + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); > +} > + > +int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3); > + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); > + > + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3); > + if (!(reg & STRM_VALID)) { > + dev_dbg(dp->dev, "Input video stream is not detected.\n"); > + return -EINVAL; > + } > + > + return 0; > +} > + > +void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_1); > + reg &= ~(MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N); > + reg |= MASTER_VID_FUNC_EN_N; > + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1); > + > + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); > + reg &= ~INTERACE_SCAN_CFG; > + reg |= (dp->video_info->interlaced << 2); > + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); > + > + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); > + reg &= ~VSYNC_POLARITY_CFG; > + reg |= (dp->video_info->v_sync_polarity << 1); > + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); > + > + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); > + reg &= ~HSYNC_POLARITY_CFG; > + reg |= (dp->video_info->h_sync_polarity << 0); > + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); > + > + reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE; > + writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); > +} > + > +void analogix_dp_enable_scrambling(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); > + reg &= ~SCRAMBLING_DISABLE; > + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); > +} > + > +void analogix_dp_disable_scrambling(struct analogix_dp_device *dp) > +{ > + u32 reg; > + > + reg = readl(dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); > + reg |= SCRAMBLING_DISABLE; > + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); > +} > diff --git a/drivers/gpu/drm/exynos/exynos_dp_reg.h b/drivers/gpu/drm/bridge/analogix_dp_reg.h > similarity index 63% > rename from drivers/gpu/drm/exynos/exynos_dp_reg.h > rename to drivers/gpu/drm/bridge/analogix_dp_reg.h > index 2e9bd0e..98153e2 100644 > --- a/drivers/gpu/drm/exynos/exynos_dp_reg.h > +++ b/drivers/gpu/drm/bridge/analogix_dp_reg.h > @@ -1,104 +1,106 @@ > /* > - * Register definition file for Samsung DP driver > + * Register definition file for Analogix Core DP driver > * > * Copyright (C) 2012 Samsung Electronics Co., Ltd. > + * Copyright (C) FuZhou Rockchip Electronics Co., Ltd. > * Author: Jingoo Han <jg1.han@samsung.com> > + * Yakir Yang <ykk@rock-chips.com> The same as above. > * > * This program is free software; you can redistribute it and/or modify > * it under the terms of the GNU General Public License version 2 as > * published by the Free Software Foundation. > */ > > -#ifndef _EXYNOS_DP_REG_H > -#define _EXYNOS_DP_REG_H > - > -#define EXYNOS_DP_TX_SW_RESET 0x14 > -#define EXYNOS_DP_FUNC_EN_1 0x18 > -#define EXYNOS_DP_FUNC_EN_2 0x1C > -#define EXYNOS_DP_VIDEO_CTL_1 0x20 > -#define EXYNOS_DP_VIDEO_CTL_2 0x24 > -#define EXYNOS_DP_VIDEO_CTL_3 0x28 > - > -#define EXYNOS_DP_VIDEO_CTL_8 0x3C > -#define EXYNOS_DP_VIDEO_CTL_10 0x44 > - > -#define EXYNOS_DP_LANE_MAP 0x35C > - > -#define EXYNOS_DP_ANALOG_CTL_1 0x370 > -#define EXYNOS_DP_ANALOG_CTL_2 0x374 > -#define EXYNOS_DP_ANALOG_CTL_3 0x378 > -#define EXYNOS_DP_PLL_FILTER_CTL_1 0x37C > -#define EXYNOS_DP_TX_AMP_TUNING_CTL 0x380 > - > -#define EXYNOS_DP_AUX_HW_RETRY_CTL 0x390 > - > -#define EXYNOS_DP_COMMON_INT_STA_1 0x3C4 > -#define EXYNOS_DP_COMMON_INT_STA_2 0x3C8 > -#define EXYNOS_DP_COMMON_INT_STA_3 0x3CC > -#define EXYNOS_DP_COMMON_INT_STA_4 0x3D0 > -#define EXYNOS_DP_INT_STA 0x3DC > -#define EXYNOS_DP_COMMON_INT_MASK_1 0x3E0 > -#define EXYNOS_DP_COMMON_INT_MASK_2 0x3E4 > -#define EXYNOS_DP_COMMON_INT_MASK_3 0x3E8 > -#define EXYNOS_DP_COMMON_INT_MASK_4 0x3EC > -#define EXYNOS_DP_INT_STA_MASK 0x3F8 > -#define EXYNOS_DP_INT_CTL 0x3FC > - > -#define EXYNOS_DP_SYS_CTL_1 0x600 > -#define EXYNOS_DP_SYS_CTL_2 0x604 > -#define EXYNOS_DP_SYS_CTL_3 0x608 > -#define EXYNOS_DP_SYS_CTL_4 0x60C > - > -#define EXYNOS_DP_PKT_SEND_CTL 0x640 > -#define EXYNOS_DP_HDCP_CTL 0x648 > - > -#define EXYNOS_DP_LINK_BW_SET 0x680 > -#define EXYNOS_DP_LANE_COUNT_SET 0x684 > -#define EXYNOS_DP_TRAINING_PTN_SET 0x688 > -#define EXYNOS_DP_LN0_LINK_TRAINING_CTL 0x68C > -#define EXYNOS_DP_LN1_LINK_TRAINING_CTL 0x690 > -#define EXYNOS_DP_LN2_LINK_TRAINING_CTL 0x694 > -#define EXYNOS_DP_LN3_LINK_TRAINING_CTL 0x698 > - > -#define EXYNOS_DP_DEBUG_CTL 0x6C0 > -#define EXYNOS_DP_HPD_DEGLITCH_L 0x6C4 > -#define EXYNOS_DP_HPD_DEGLITCH_H 0x6C8 > -#define EXYNOS_DP_LINK_DEBUG_CTL 0x6E0 > - > -#define EXYNOS_DP_M_VID_0 0x700 > -#define EXYNOS_DP_M_VID_1 0x704 > -#define EXYNOS_DP_M_VID_2 0x708 > -#define EXYNOS_DP_N_VID_0 0x70C > -#define EXYNOS_DP_N_VID_1 0x710 > -#define EXYNOS_DP_N_VID_2 0x714 > - > -#define EXYNOS_DP_PLL_CTL 0x71C > -#define EXYNOS_DP_PHY_PD 0x720 > -#define EXYNOS_DP_PHY_TEST 0x724 > - > -#define EXYNOS_DP_VIDEO_FIFO_THRD 0x730 > -#define EXYNOS_DP_AUDIO_MARGIN 0x73C > - > -#define EXYNOS_DP_M_VID_GEN_FILTER_TH 0x764 > -#define EXYNOS_DP_M_AUD_GEN_FILTER_TH 0x778 > -#define EXYNOS_DP_AUX_CH_STA 0x780 > -#define EXYNOS_DP_AUX_CH_DEFER_CTL 0x788 > -#define EXYNOS_DP_AUX_RX_COMM 0x78C > -#define EXYNOS_DP_BUFFER_DATA_CTL 0x790 > -#define EXYNOS_DP_AUX_CH_CTL_1 0x794 > -#define EXYNOS_DP_AUX_ADDR_7_0 0x798 > -#define EXYNOS_DP_AUX_ADDR_15_8 0x79C > -#define EXYNOS_DP_AUX_ADDR_19_16 0x7A0 > -#define EXYNOS_DP_AUX_CH_CTL_2 0x7A4 > - > -#define EXYNOS_DP_BUF_DATA_0 0x7C0 > - > -#define EXYNOS_DP_SOC_GENERAL_CTL 0x800 > - > -/* EXYNOS_DP_TX_SW_RESET */ > +#ifndef _ANALOGIX_DP_REG_H > +#define _ANALOGIX_DP_REG_H > + > +#define ANALOGIX_DP_TX_SW_RESET 0x14 > +#define ANALOGIX_DP_FUNC_EN_1 0x18 > +#define ANALOGIX_DP_FUNC_EN_2 0x1C > +#define ANALOGIX_DP_VIDEO_CTL_1 0x20 > +#define ANALOGIX_DP_VIDEO_CTL_2 0x24 > +#define ANALOGIX_DP_VIDEO_CTL_3 0x28 > + > +#define ANALOGIX_DP_VIDEO_CTL_8 0x3C > +#define ANALOGIX_DP_VIDEO_CTL_10 0x44 > + > +#define ANALOGIX_DP_LANE_MAP 0x35C > + > +#define ANALOGIX_DP_ANALOG_CTL_1 0x370 > +#define ANALOGIX_DP_ANALOG_CTL_2 0x374 > +#define ANALOGIX_DP_ANALOG_CTL_3 0x378 > +#define ANALOGIX_DP_PLL_FILTER_CTL_1 0x37C > +#define ANALOGIX_DP_TX_AMP_TUNING_CTL 0x380 > + > +#define ANALOGIX_DP_AUX_HW_RETRY_CTL 0x390 > + > +#define ANALOGIX_DP_COMMON_INT_STA_1 0x3C4 > +#define ANALOGIX_DP_COMMON_INT_STA_2 0x3C8 > +#define ANALOGIX_DP_COMMON_INT_STA_3 0x3CC > +#define ANALOGIX_DP_COMMON_INT_STA_4 0x3D0 > +#define ANALOGIX_DP_INT_STA 0x3DC > +#define ANALOGIX_DP_COMMON_INT_MASK_1 0x3E0 > +#define ANALOGIX_DP_COMMON_INT_MASK_2 0x3E4 > +#define ANALOGIX_DP_COMMON_INT_MASK_3 0x3E8 > +#define ANALOGIX_DP_COMMON_INT_MASK_4 0x3EC > +#define ANALOGIX_DP_INT_STA_MASK 0x3F8 > +#define ANALOGIX_DP_INT_CTL 0x3FC > + > +#define ANALOGIX_DP_SYS_CTL_1 0x600 > +#define ANALOGIX_DP_SYS_CTL_2 0x604 > +#define ANALOGIX_DP_SYS_CTL_3 0x608 > +#define ANALOGIX_DP_SYS_CTL_4 0x60C > + > +#define ANALOGIX_DP_PKT_SEND_CTL 0x640 > +#define ANALOGIX_DP_HDCP_CTL 0x648 > + > +#define ANALOGIX_DP_LINK_BW_SET 0x680 > +#define ANALOGIX_DP_LANE_COUNT_SET 0x684 > +#define ANALOGIX_DP_TRAINING_PTN_SET 0x688 > +#define ANALOGIX_DP_LN0_LINK_TRAINING_CTL 0x68C > +#define ANALOGIX_DP_LN1_LINK_TRAINING_CTL 0x690 > +#define ANALOGIX_DP_LN2_LINK_TRAINING_CTL 0x694 > +#define ANALOGIX_DP_LN3_LINK_TRAINING_CTL 0x698 > + > +#define ANALOGIX_DP_DEBUG_CTL 0x6C0 > +#define ANALOGIX_DP_HPD_DEGLITCH_L 0x6C4 > +#define ANALOGIX_DP_HPD_DEGLITCH_H 0x6C8 > +#define ANALOGIX_DP_LINK_DEBUG_CTL 0x6E0 > + > +#define ANALOGIX_DP_M_VID_0 0x700 > +#define ANALOGIX_DP_M_VID_1 0x704 > +#define ANALOGIX_DP_M_VID_2 0x708 > +#define ANALOGIX_DP_N_VID_0 0x70C > +#define ANALOGIX_DP_N_VID_1 0x710 > +#define ANALOGIX_DP_N_VID_2 0x714 > + > +#define ANALOGIX_DP_PLL_CTL 0x71C > +#define ANALOGIX_DP_PHY_PD 0x720 > +#define ANALOGIX_DP_PHY_TEST 0x724 > + > +#define ANALOGIX_DP_VIDEO_FIFO_THRD 0x730 > +#define ANALOGIX_DP_AUDIO_MARGIN 0x73C > + > +#define ANALOGIX_DP_M_VID_GEN_FILTER_TH 0x764 > +#define ANALOGIX_DP_M_AUD_GEN_FILTER_TH 0x778 > +#define ANALOGIX_DP_AUX_CH_STA 0x780 > +#define ANALOGIX_DP_AUX_CH_DEFER_CTL 0x788 > +#define ANALOGIX_DP_AUX_RX_COMM 0x78C > +#define ANALOGIX_DP_BUFFER_DATA_CTL 0x790 > +#define ANALOGIX_DP_AUX_CH_CTL_1 0x794 > +#define ANALOGIX_DP_AUX_ADDR_7_0 0x798 > +#define ANALOGIX_DP_AUX_ADDR_15_8 0x79C > +#define ANALOGIX_DP_AUX_ADDR_19_16 0x7A0 > +#define ANALOGIX_DP_AUX_CH_CTL_2 0x7A4 > + > +#define ANALOGIX_DP_BUF_DATA_0 0x7C0 > + > +#define ANALOGIX_DP_SOC_GENERAL_CTL 0x800 > + > +/* ANALOGIX_DP_TX_SW_RESET */ > #define RESET_DP_TX (0x1 << 0) > > -/* EXYNOS_DP_FUNC_EN_1 */ > +/* ANALOGIX_DP_FUNC_EN_1 */ > #define MASTER_VID_FUNC_EN_N (0x1 << 7) > #define SLAVE_VID_FUNC_EN_N (0x1 << 5) > #define AUD_FIFO_FUNC_EN_N (0x1 << 4) > @@ -107,17 +109,17 @@ > #define CRC_FUNC_EN_N (0x1 << 1) > #define SW_FUNC_EN_N (0x1 << 0) > > -/* EXYNOS_DP_FUNC_EN_2 */ > +/* ANALOGIX_DP_FUNC_EN_2 */ > #define SSC_FUNC_EN_N (0x1 << 7) > #define AUX_FUNC_EN_N (0x1 << 2) > #define SERDES_FIFO_FUNC_EN_N (0x1 << 1) > #define LS_CLK_DOMAIN_FUNC_EN_N (0x1 << 0) > > -/* EXYNOS_DP_VIDEO_CTL_1 */ > +/* ANALOGIX_DP_VIDEO_CTL_1 */ > #define VIDEO_EN (0x1 << 7) > #define HDCP_VIDEO_MUTE (0x1 << 6) > > -/* EXYNOS_DP_VIDEO_CTL_1 */ > +/* ANALOGIX_DP_VIDEO_CTL_1 */ > #define IN_D_RANGE_MASK (0x1 << 7) > #define IN_D_RANGE_SHIFT (7) > #define IN_D_RANGE_CEA (0x1 << 7) > @@ -134,7 +136,7 @@ > #define IN_COLOR_F_YCBCR422 (0x1 << 0) > #define IN_COLOR_F_RGB (0x0 << 0) > > -/* EXYNOS_DP_VIDEO_CTL_3 */ > +/* ANALOGIX_DP_VIDEO_CTL_3 */ > #define IN_YC_COEFFI_MASK (0x1 << 7) > #define IN_YC_COEFFI_SHIFT (7) > #define IN_YC_COEFFI_ITU709 (0x1 << 7) > @@ -144,17 +146,17 @@ > #define VID_CHK_UPDATE_TYPE_1 (0x1 << 4) > #define VID_CHK_UPDATE_TYPE_0 (0x0 << 4) > > -/* EXYNOS_DP_VIDEO_CTL_8 */ > +/* ANALOGIX_DP_VIDEO_CTL_8 */ > #define VID_HRES_TH(x) (((x) & 0xf) << 4) > #define VID_VRES_TH(x) (((x) & 0xf) << 0) > > -/* EXYNOS_DP_VIDEO_CTL_10 */ > +/* ANALOGIX_DP_VIDEO_CTL_10 */ > #define FORMAT_SEL (0x1 << 4) > #define INTERACE_SCAN_CFG (0x1 << 2) > #define VSYNC_POLARITY_CFG (0x1 << 1) > #define HSYNC_POLARITY_CFG (0x1 << 0) > > -/* EXYNOS_DP_LANE_MAP */ > +/* ANALOGIX_DP_LANE_MAP */ > #define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6) > #define LANE3_MAP_LOGIC_LANE_1 (0x1 << 6) > #define LANE3_MAP_LOGIC_LANE_2 (0x2 << 6) > @@ -172,30 +174,30 @@ > #define LANE0_MAP_LOGIC_LANE_2 (0x2 << 0) > #define LANE0_MAP_LOGIC_LANE_3 (0x3 << 0) > > -/* EXYNOS_DP_ANALOG_CTL_1 */ > +/* ANALOGIX_DP_ANALOG_CTL_1 */ > #define TX_TERMINAL_CTRL_50_OHM (0x1 << 4) > > -/* EXYNOS_DP_ANALOG_CTL_2 */ > +/* ANALOGIX_DP_ANALOG_CTL_2 */ > #define SEL_24M (0x1 << 3) > #define TX_DVDD_BIT_1_0625V (0x4 << 0) > > -/* EXYNOS_DP_ANALOG_CTL_3 */ > +/* ANALOGIX_DP_ANALOG_CTL_3 */ > #define DRIVE_DVDD_BIT_1_0625V (0x4 << 5) > #define VCO_BIT_600_MICRO (0x5 << 0) > > -/* EXYNOS_DP_PLL_FILTER_CTL_1 */ > +/* ANALOGIX_DP_PLL_FILTER_CTL_1 */ > #define PD_RING_OSC (0x1 << 6) > #define AUX_TERMINAL_CTRL_50_OHM (0x2 << 4) > #define TX_CUR1_2X (0x1 << 2) > #define TX_CUR_16_MA (0x3 << 0) > > -/* EXYNOS_DP_TX_AMP_TUNING_CTL */ > +/* ANALOGIX_DP_TX_AMP_TUNING_CTL */ > #define CH3_AMP_400_MV (0x0 << 24) > #define CH2_AMP_400_MV (0x0 << 16) > #define CH1_AMP_400_MV (0x0 << 8) > #define CH0_AMP_400_MV (0x0 << 0) > > -/* EXYNOS_DP_AUX_HW_RETRY_CTL */ > +/* ANALOGIX_DP_AUX_HW_RETRY_CTL */ > #define AUX_BIT_PERIOD_EXPECTED_DELAY(x) (((x) & 0x7) << 8) > #define AUX_HW_RETRY_INTERVAL_MASK (0x3 << 3) > #define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS (0x0 << 3) > @@ -204,7 +206,7 @@ > #define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS (0x3 << 3) > #define AUX_HW_RETRY_COUNT_SEL(x) (((x) & 0x7) << 0) > > -/* EXYNOS_DP_COMMON_INT_STA_1 */ > +/* ANALOGIX_DP_COMMON_INT_STA_1 */ > #define VSYNC_DET (0x1 << 7) > #define PLL_LOCK_CHG (0x1 << 6) > #define SPDIF_ERR (0x1 << 5) > @@ -214,19 +216,19 @@ > #define VID_CLK_CHG (0x1 << 1) > #define SW_INT (0x1 << 0) > > -/* EXYNOS_DP_COMMON_INT_STA_2 */ > +/* ANALOGIX_DP_COMMON_INT_STA_2 */ > #define ENC_EN_CHG (0x1 << 6) > #define HW_BKSV_RDY (0x1 << 3) > #define HW_SHA_DONE (0x1 << 2) > #define HW_AUTH_STATE_CHG (0x1 << 1) > #define HW_AUTH_DONE (0x1 << 0) > > -/* EXYNOS_DP_COMMON_INT_STA_3 */ > +/* ANALOGIX_DP_COMMON_INT_STA_3 */ > #define AFIFO_UNDER (0x1 << 7) > #define AFIFO_OVER (0x1 << 6) > #define R0_CHK_FLAG (0x1 << 5) > > -/* EXYNOS_DP_COMMON_INT_STA_4 */ > +/* ANALOGIX_DP_COMMON_INT_STA_4 */ > #define PSR_ACTIVE (0x1 << 7) > #define PSR_INACTIVE (0x1 << 6) > #define SPDIF_BI_PHASE_ERR (0x1 << 5) > @@ -234,29 +236,29 @@ > #define HPD_LOST (0x1 << 1) > #define PLUG (0x1 << 0) > > -/* EXYNOS_DP_INT_STA */ > +/* ANALOGIX_DP_INT_STA */ > #define INT_HPD (0x1 << 6) > #define HW_TRAINING_FINISH (0x1 << 5) > #define RPLY_RECEIV (0x1 << 1) > #define AUX_ERR (0x1 << 0) > > -/* EXYNOS_DP_INT_CTL */ > +/* ANALOGIX_DP_INT_CTL */ > #define SOFT_INT_CTRL (0x1 << 2) > #define INT_POL1 (0x1 << 1) > #define INT_POL0 (0x1 << 0) > > -/* EXYNOS_DP_SYS_CTL_1 */ > +/* ANALOGIX_DP_SYS_CTL_1 */ > #define DET_STA (0x1 << 2) > #define FORCE_DET (0x1 << 1) > #define DET_CTRL (0x1 << 0) > > -/* EXYNOS_DP_SYS_CTL_2 */ > +/* ANALOGIX_DP_SYS_CTL_2 */ > #define CHA_CRI(x) (((x) & 0xf) << 4) > #define CHA_STA (0x1 << 2) > #define FORCE_CHA (0x1 << 1) > #define CHA_CTRL (0x1 << 0) > > -/* EXYNOS_DP_SYS_CTL_3 */ > +/* ANALOGIX_DP_SYS_CTL_3 */ > #define HPD_STATUS (0x1 << 6) > #define F_HPD (0x1 << 5) > #define HPD_CTRL (0x1 << 4) > @@ -265,13 +267,13 @@ > #define F_VALID (0x1 << 1) > #define VALID_CTRL (0x1 << 0) > > -/* EXYNOS_DP_SYS_CTL_4 */ > +/* ANALOGIX_DP_SYS_CTL_4 */ > #define FIX_M_AUD (0x1 << 4) > #define ENHANCED (0x1 << 3) > #define FIX_M_VID (0x1 << 2) > #define M_VID_UPDATE_CTRL (0x3 << 0) > > -/* EXYNOS_DP_TRAINING_PTN_SET */ > +/* ANALOGIX_DP_TRAINING_PTN_SET */ > #define SCRAMBLER_TYPE (0x1 << 9) > #define HW_LINK_TRAINING_PATTERN (0x1 << 8) > #define SCRAMBLING_DISABLE (0x1 << 5) > @@ -285,24 +287,24 @@ > #define SW_TRAINING_PATTERN_SET_PTN1 (0x1 << 0) > #define SW_TRAINING_PATTERN_SET_NORMAL (0x0 << 0) > > -/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */ > +/* ANALOGIX_DP_LN0_LINK_TRAINING_CTL */ > #define PRE_EMPHASIS_SET_MASK (0x3 << 3) > #define PRE_EMPHASIS_SET_SHIFT (3) > > -/* EXYNOS_DP_DEBUG_CTL */ > +/* ANALOGIX_DP_DEBUG_CTL */ > #define PLL_LOCK (0x1 << 4) > #define F_PLL_LOCK (0x1 << 3) > #define PLL_LOCK_CTRL (0x1 << 2) > #define PN_INV (0x1 << 0) > > -/* EXYNOS_DP_PLL_CTL */ > +/* ANALOGIX_DP_PLL_CTL */ > #define DP_PLL_PD (0x1 << 7) > #define DP_PLL_RESET (0x1 << 6) > #define DP_PLL_LOOP_BIT_DEFAULT (0x1 << 4) > #define DP_PLL_REF_BIT_1_1250V (0x5 << 0) > #define DP_PLL_REF_BIT_1_2500V (0x7 << 0) > > -/* EXYNOS_DP_PHY_PD */ > +/* ANALOGIX_DP_PHY_PD */ > #define DP_PHY_PD (0x1 << 5) > #define AUX_PD (0x1 << 4) > #define CH3_PD (0x1 << 3) > @@ -310,28 +312,28 @@ > #define CH1_PD (0x1 << 1) > #define CH0_PD (0x1 << 0) > > -/* EXYNOS_DP_PHY_TEST */ > +/* ANALOGIX_DP_PHY_TEST */ > #define MACRO_RST (0x1 << 5) > #define CH1_TEST (0x1 << 1) > #define CH0_TEST (0x1 << 0) > > -/* EXYNOS_DP_AUX_CH_STA */ > +/* ANALOGIX_DP_AUX_CH_STA */ > #define AUX_BUSY (0x1 << 4) > #define AUX_STATUS_MASK (0xf << 0) > > -/* EXYNOS_DP_AUX_CH_DEFER_CTL */ > +/* ANALOGIX_DP_AUX_CH_DEFER_CTL */ > #define DEFER_CTRL_EN (0x1 << 7) > #define DEFER_COUNT(x) (((x) & 0x7f) << 0) > > -/* EXYNOS_DP_AUX_RX_COMM */ > +/* ANALOGIX_DP_AUX_RX_COMM */ > #define AUX_RX_COMM_I2C_DEFER (0x2 << 2) > #define AUX_RX_COMM_AUX_DEFER (0x2 << 0) > > -/* EXYNOS_DP_BUFFER_DATA_CTL */ > +/* ANALOGIX_DP_BUFFER_DATA_CTL */ > #define BUF_CLR (0x1 << 7) > #define BUF_DATA_COUNT(x) (((x) & 0x1f) << 0) > > -/* EXYNOS_DP_AUX_CH_CTL_1 */ > +/* ANALOGIX_DP_AUX_CH_CTL_1 */ > #define AUX_LENGTH(x) (((x - 1) & 0xf) << 4) > #define AUX_TX_COMM_MASK (0xf << 0) > #define AUX_TX_COMM_DP_TRANSACTION (0x1 << 3) > @@ -340,20 +342,20 @@ > #define AUX_TX_COMM_WRITE (0x0 << 0) > #define AUX_TX_COMM_READ (0x1 << 0) > > -/* EXYNOS_DP_AUX_ADDR_7_0 */ > +/* ANALOGIX_DP_AUX_ADDR_7_0 */ > #define AUX_ADDR_7_0(x) (((x) >> 0) & 0xff) > > -/* EXYNOS_DP_AUX_ADDR_15_8 */ > +/* ANALOGIX_DP_AUX_ADDR_15_8 */ > #define AUX_ADDR_15_8(x) (((x) >> 8) & 0xff) > > -/* EXYNOS_DP_AUX_ADDR_19_16 */ > +/* ANALOGIX_DP_AUX_ADDR_19_16 */ > #define AUX_ADDR_19_16(x) (((x) >> 16) & 0x0f) > > -/* EXYNOS_DP_AUX_CH_CTL_2 */ > +/* ANALOGIX_DP_AUX_CH_CTL_2 */ > #define ADDR_ONLY (0x1 << 1) > #define AUX_EN (0x1 << 0) > > -/* EXYNOS_DP_SOC_GENERAL_CTL */ > +/* ANALOGIX_DP_SOC_GENERAL_CTL */ > #define AUDIO_MODE_SPDIF_MODE (0x1 << 8) > #define AUDIO_MODE_MASTER_MODE (0x0 << 8) > #define MASTER_VIDEO_INTERLACE_EN (0x1 << 4) > @@ -363,4 +365,4 @@ > #define VIDEO_MODE_SLAVE_MODE (0x1 << 0) > #define VIDEO_MODE_MASTER_MODE (0x0 << 0) > > -#endif /* _EXYNOS_DP_REG_H */ > +#endif /* _ANALOGIX_DP_REG_H */ > diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig > index 43003c4..b33549c 100644 > --- a/drivers/gpu/drm/exynos/Kconfig > +++ b/drivers/gpu/drm/exynos/Kconfig > @@ -54,9 +54,10 @@ config DRM_EXYNOS_DSI > help > This enables support for Exynos MIPI-DSI device. > > -config DRM_EXYNOS_DP > - bool "EXYNOS DRM DP driver support" > +config DRM_EXYNOS_ANALOGIX_DP > + bool "EXYNOS specific extensions for Analogix DP driver" > depends on DRM_EXYNOS && (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON) && (DRM_PTN3460=n || > DRM_PTN3460=y || DRM_PTN3460=DRM_EXYNOS) > + select DRM_ANALOGIX_DP > default DRM_EXYNOS > select DRM_PANEL > help > diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile > index 7de0b10..cda4d26 100644 > --- a/drivers/gpu/drm/exynos/Makefile > +++ b/drivers/gpu/drm/exynos/Makefile > @@ -14,7 +14,7 @@ exynosdrm-$(CONFIG_DRM_EXYNOS5433_DECON) += exynos5433_drm_decon.o > exynosdrm-$(CONFIG_DRM_EXYNOS7_DECON) += exynos7_drm_decon.o > exynosdrm-$(CONFIG_DRM_EXYNOS_DPI) += exynos_drm_dpi.o > exynosdrm-$(CONFIG_DRM_EXYNOS_DSI) += exynos_drm_dsi.o > -exynosdrm-$(CONFIG_DRM_EXYNOS_DP) += exynos_dp_core.o exynos_dp_reg.o > +exynosdrm-$(CONFIG_DRM_EXYNOS_ANALOGIX_DP) += analogix_dp-exynos.o > exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o > exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o > exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o > diff --git a/drivers/gpu/drm/exynos/analogix_dp-exynos.c b/drivers/gpu/drm/exynos/analogix_dp-exynos.c > new file mode 100644 > index 0000000..b8d09d4 > --- /dev/null > +++ b/drivers/gpu/drm/exynos/analogix_dp-exynos.c > @@ -0,0 +1,240 @@ > +/* > + * Samsung SoC DP (Display Port) interface driver. > + * > + * Copyright (C) 2012 Samsung Electronics Co., Ltd. > + * Copyright (C) FuZhou Rockchip Electronics Co., Ltd. > + * Author: Jingoo Han <jg1.han@samsung.com> > + * Yakir Yang <ykk@rock-chips.com> The same as above. > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of the GNU General Public License as published by the > + * Free Software Foundation; either version 2 of the License, or (at your > + * option) any later version. > + */ > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/err.h> > +#include <linux/clk.h> > +#include <linux/component.h> > + > +#include <drm/drmP.h> > +#include <drm/drm_panel.h> > +#include <drm/bridge/ptn3460.h> > + > +#include <drm/exynos_drm.h> > +#include "exynos_drm_drv.h" > + > +#define plat_data_to_dp(pd) \ > + container_of(pd, struct exynos_dp_device, plat_data) > + > +struct exynos_dp_device { > + struct exynos_drm_display display; > + struct drm_bridge *ptn_bridge; > + struct drm_device *drm_dev; > + struct device *dev; > + > + struct analogix_dp_plat_data plat_data; > +}; > + > +int exynos_dp_crtc_clock_enable(struct analogix_dp_plat_data *plat_data, > + bool enable) > +{ > + struct exynos_dp_device *dp = plat_data_to_dp(plat_data); > + struct drm_encoder *encoder = dp->display.encoder; > + struct exynos_drm_crtc *crtc; > + > + if (!encoder) > + return -1; > + > + crtc = to_exynos_crtc(encoder->crtc); > + if (crtc && crtc->ops && crtc->ops->clock_enable) > + crtc->ops->clock_enable(crtc, enable); > + > + return 0; > +} > + > +static int exynos_dp_poweron(struct analogix_dp_plat_data *plat_data) > +{ > + exynos_dp_crtc_clock_enable(plat_data, true); > +} > + > +static int exynos_dp_poweroff(struct analogix_dp_plat_data *plat_data) > +{ > + exynos_dp_crtc_clock_enable(plat_data, false); > +} > + > +static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data, > + struct drm_bridge *bridge) > +{ > + struct exynos_dp_device *dp = plat_data_to_dp(plat_data); > + struct drm_encoder *encoder = dp->display.encoder; > + int ret; > + > + /* Pre-empt DP connector creation if there's a bridge */ > + if (dp->ptn_bridge) { > + dp->bridge->next = dp->ptn_bridge; > + dp->bridge->encoder = encoder; > + ret = drm_bridge_attach(encoder->dev, dp->bridge); > + if (ret) { > + DRM_ERROR("Failed to attach bridge to drm\n"); > + bridge->next = NULL; > + return ret; > + } > + } > + > + return 0; > +} > + > +static void exynos_dp_dpms(struct exynos_drm_display *display, int mode) > +{ > + /* do nothing */ > +} > + > +static int exynos_dp_create_connector(struct exynos_drm_display *display, > + struct drm_encoder *encoder) > +{ > + /* do nothing */ > + return 0; > +} > + > +static void exynos_dp_commit(struct exynos_drm_display *display) > +{ > + /* do nothing */ > +} > + > +static struct exynos_drm_display_ops exynos_dp_display_ops = { > + .create_connector = exynos_dp_create_connector, > + .dpms = exynos_dp_dpms, > + .commit = exynos_dp_commit, > +}; > + > +static int exynos_dp_bind(struct device *dev, struct device *master, void *data) > +{ > + struct exynos_dp_device *dp = dev_get_drvdata(dev); > + struct drm_device *drm_dev = data; > + int ret; > + > + /* > + * Just like the probe function said, we don't need the > + * device drvrate anymore, we should leave the charge to > + * analogix dp driver, set the device drvdata to NULL. > + */ > + dev_set_drvdata(dev, NULL); > + > + dp->dev = dev; > + dp->drm_dev = drm_dev; > + > + dp->plat_data.power_on = exynos_dp_poweron; > + dp->plat_data.power_off = exynos_dp_poweroff; > + dp->plat_data.attach = exynos_dp_bridge_attach; > + > + ret = exynos_drm_create_enc_conn(dp->drm_dev, &dp->display); > + if (ret) { > + DRM_ERROR("exynos dp create enc_conn failed\n"); > + return ret; > + } > + > + return analogix_dp_bind(dev, dp->drm_dev, dp->display.encoder, > + &dp->plat_data); > +} > + > +static void exynos_dp_unbind(struct device *dev, struct device *master, > + void *data) > +{ > + return analogix_dp_unbind(dev, master, data); > +} > + > +static const struct component_ops exynos_dp_ops = { > + .bind = exynos_dp_bind, > + .unbind = exynos_dp_unbind, > +}; > + > +static int exynos_dp_probe(struct platform_device *pdev) > +{ > + struct device *dev = &pdev->dev; > + struct device_node *panel_node, *bridge_node, *endpoint; > + struct exynos_dp_device *dp; > + > + dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), > + GFP_KERNEL); > + if (!dp) > + return -ENOMEM; > + > + /* > + * We just use the drvdata until driver run into component > + * add function, and then we would set drvdata to null, so > + * that analogix dp driver would take charge of the drvdata. > + */ > + platform_set_drvdata(pdev, dp); > + > + dp->display.type = EXYNOS_DISPLAY_TYPE_LCD; > + dp->display.ops = &exynos_dp_display_ops; > + > + panel_node = of_parse_phandle(dev->of_node, "panel", 0); > + if (panel_node) { > + dp->panel = of_drm_find_panel(panel_node); > + of_node_put(panel_node); > + if (!dp->panel) > + return -EPROBE_DEFER; > + } > + > + endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); > + if (endpoint) { > + bridge_node = of_graph_get_remote_port_parent(endpoint); > + if (bridge_node) { > + dp->ptn_bridge = of_drm_find_bridge(bridge_node); > + of_node_put(bridge_node); > + if (!dp->ptn_bridge) > + return -EPROBE_DEFER; > + } else { > + return -EPROBE_DEFER; > + } > + } > + > + return component_add(&pdev->dev, &exynos_dp_ops); > +} > + > +static int exynos_dp_remove(struct platform_device *pdev) > +{ > + component_del(&pdev->dev, &exynos_dp_ops); > + > + return 0; > +} > + > +#ifdef CONFIG_PM_SLEEP > +static int exynos_dp_suspend(struct device *dev) > +{ > + return analogix_dp_suspend(dev); > +} > + > +static int exynos_dp_resume(struct device *dev) > +{ > + return analogix_dp_resume(dev); > +} > +#endif > + > +static const struct dev_pm_ops exynos_dp_pm_ops = { > + SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume) > +}; > + > +static const struct of_device_id exynos_dp_match[] = { > + { .compatible = "samsung,exynos5-dp" }, > + {}, > +}; > +MODULE_DEVICE_TABLE(of, exynos_dp_match); > + > +struct platform_driver dp_driver = { > + .probe = exynos_dp_probe, > + .remove = exynos_dp_remove, > + .driver = { > + .name = "exynos-dp", > + .owner = THIS_MODULE, > + .pm = &exynos_dp_pm_ops, > + .of_match_table = exynos_dp_match, > + }, > +}; > + > +MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); > +MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>"); The same as above. Best regards, Jingoo Han > +MODULE_DESCRIPTION("Samsung Specific Analogix-DP Driver Extension"); > +MODULE_LICENSE("GPL v2"); > diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h > deleted file mode 100644 > index f2584b8..0000000 > --- a/drivers/gpu/drm/exynos/exynos_dp_core.h > +++ /dev/null > @@ -1,283 +0,0 @@ > -/* > - * Header file for Samsung DP (Display Port) interface driver. > - * > - * Copyright (C) 2012 Samsung Electronics Co., Ltd. > - * Author: Jingoo Han <jg1.han@samsung.com> > - * Yakir Yang <ykk@rock-chips.com> > - * > - * This program is free software; you can redistribute it and/or modify it > - * under the terms of the GNU General Public License as published by the > - * Free Software Foundation; either version 2 of the License, or (at your > - * option) any later version. > - */ > - > -#ifndef _EXYNOS_DP_CORE_H > -#define _EXYNOS_DP_CORE_H > - > -#include <drm/drm_crtc.h> > -#include <drm/drm_dp_helper.h> > -#include <drm/exynos_drm.h> > - > -#include "exynos_drm_drv.h" > - > -#define DP_TIMEOUT_LOOP_COUNT 100 > -#define MAX_CR_LOOP 5 > -#define MAX_EQ_LOOP 5 > - > -enum link_rate_type { > - LINK_RATE_1_62GBPS = 0x06, > - LINK_RATE_2_70GBPS = 0x0a > -}; > - > -enum link_lane_count_type { > - LANE_COUNT1 = 1, > - LANE_COUNT2 = 2, > - LANE_COUNT4 = 4 > -}; > - > -enum link_training_state { > - START, > - CLOCK_RECOVERY, > - EQUALIZER_TRAINING, > - FINISHED, > - FAILED > -}; > - > -enum voltage_swing_level { > - VOLTAGE_LEVEL_0, > - VOLTAGE_LEVEL_1, > - VOLTAGE_LEVEL_2, > - VOLTAGE_LEVEL_3, > -}; > - > -enum pre_emphasis_level { > - PRE_EMPHASIS_LEVEL_0, > - PRE_EMPHASIS_LEVEL_1, > - PRE_EMPHASIS_LEVEL_2, > - PRE_EMPHASIS_LEVEL_3, > -}; > - > -enum pattern_set { > - PRBS7, > - D10_2, > - TRAINING_PTN1, > - TRAINING_PTN2, > - DP_NONE > -}; > - > -enum color_space { > - COLOR_RGB, > - COLOR_YCBCR422, > - COLOR_YCBCR444 > -}; > - > -enum color_depth { > - COLOR_6, > - COLOR_8, > - COLOR_10, > - COLOR_12 > -}; > - > -enum color_coefficient { > - COLOR_YCBCR601, > - COLOR_YCBCR709 > -}; > - > -enum dynamic_range { > - VESA, > - CEA > -}; > - > -enum pll_status { > - PLL_UNLOCKED, > - PLL_LOCKED > -}; > - > -enum clock_recovery_m_value_type { > - CALCULATED_M, > - REGISTER_M > -}; > - > -enum video_timing_recognition_type { > - VIDEO_TIMING_FROM_CAPTURE, > - VIDEO_TIMING_FROM_REGISTER > -}; > - > -enum analog_power_block { > - AUX_BLOCK, > - CH0_BLOCK, > - CH1_BLOCK, > - CH2_BLOCK, > - CH3_BLOCK, > - ANALOG_TOTAL, > - POWER_ALL > -}; > - > -enum dp_irq_type { > - DP_IRQ_TYPE_HP_CABLE_IN, > - DP_IRQ_TYPE_HP_CABLE_OUT, > - DP_IRQ_TYPE_HP_CHANGE, > - DP_IRQ_TYPE_UNKNOWN, > -}; > - > -struct video_info { > - char *name; > - > - bool h_sync_polarity; > - bool v_sync_polarity; > - bool interlaced; > - > - enum color_space color_space; > - enum dynamic_range dynamic_range; > - enum color_coefficient ycbcr_coeff; > - enum color_depth color_depth; > - > - enum link_rate_type link_rate; > - enum link_lane_count_type lane_count; > -}; > - > -struct link_train { > - int eq_loop; > - int cr_loop[4]; > - > - u8 link_rate; > - u8 lane_count; > - u8 training_lane[4]; > - > - enum link_training_state lt_state; > -}; > - > -struct exynos_dp_device { > - struct exynos_drm_display display; > - struct device *dev; > - struct drm_device *drm_dev; > - struct drm_connector connector; > - struct drm_encoder *encoder; > - struct drm_panel *panel; > - struct drm_bridge *bridge; > - struct drm_bridge *ptn_bridge; > - struct clk *clock; > - unsigned int irq; > - void __iomem *reg_base; > - > - struct video_info *video_info; > - struct link_train link_train; > - struct work_struct hotplug_work; > - struct phy *phy; > - int dpms_mode; > - int hpd_gpio; > - > - struct exynos_drm_panel_info priv; > -}; > - > -/* exynos_dp_reg.c */ > -void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable); > -void exynos_dp_stop_video(struct exynos_dp_device *dp); > -void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable); > -void exynos_dp_init_analog_param(struct exynos_dp_device *dp); > -void exynos_dp_init_interrupt(struct exynos_dp_device *dp); > -void exynos_dp_reset(struct exynos_dp_device *dp); > -void exynos_dp_swreset(struct exynos_dp_device *dp); > -void exynos_dp_config_interrupt(struct exynos_dp_device *dp); > -enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp); > -void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable); > -void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp, > - enum analog_power_block block, > - bool enable); > -void exynos_dp_init_analog_func(struct exynos_dp_device *dp); > -void exynos_dp_init_hpd(struct exynos_dp_device *dp); > -enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp); > -void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp); > -void exynos_dp_reset_aux(struct exynos_dp_device *dp); > -void exynos_dp_init_aux(struct exynos_dp_device *dp); > -int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp); > -void exynos_dp_enable_sw_function(struct exynos_dp_device *dp); > -int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp); > -int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp, > - unsigned int reg_addr, > - unsigned char data); > -int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp, > - unsigned int reg_addr, > - unsigned char *data); > -int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp, > - unsigned int reg_addr, > - unsigned int count, > - unsigned char data[]); > -int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp, > - unsigned int reg_addr, > - unsigned int count, > - unsigned char data[]); > -int exynos_dp_select_i2c_device(struct exynos_dp_device *dp, > - unsigned int device_addr, > - unsigned int reg_addr); > -int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp, > - unsigned int device_addr, > - unsigned int reg_addr, > - unsigned int *data); > -int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp, > - unsigned int device_addr, > - unsigned int reg_addr, > - unsigned int count, > - unsigned char edid[]); > -void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype); > -void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype); > -void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count); > -void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count); > -void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable); > -void exynos_dp_set_training_pattern(struct exynos_dp_device *dp, > - enum pattern_set pattern); > -void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level); > -void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level); > -void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level); > -void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level); > -void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp, > - u32 training_lane); > -void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp, > - u32 training_lane); > -void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp, > - u32 training_lane); > -void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp, > - u32 training_lane); > -u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp); > -u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp); > -u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp); > -u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp); > -void exynos_dp_reset_macro(struct exynos_dp_device *dp); > -void exynos_dp_init_video(struct exynos_dp_device *dp); > - > -void exynos_dp_set_video_color_format(struct exynos_dp_device *dp); > -int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp); > -void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp, > - enum clock_recovery_m_value_type type, > - u32 m_value, u32 n_value); > -void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type); > -void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable); > -void exynos_dp_start_video(struct exynos_dp_device *dp); > -int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp); > -void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp); > -void exynos_dp_enable_scrambling(struct exynos_dp_device *dp); > -void exynos_dp_disable_scrambling(struct exynos_dp_device *dp); > - > -/* 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 > - > -/* DP_MAX_LANE_COUNT */ > -#define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1) > -#define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f) > - > -/* DP_LANE_COUNT_SET */ > -#define DPCD_LANE_COUNT_SET(x) ((x) & 0x1f) > - > -/* DP_TRAINING_LANE0_SET */ > -#define DPCD_PRE_EMPHASIS_SET(x) (((x) & 0x3) << 3) > -#define DPCD_PRE_EMPHASIS_GET(x) (((x) >> 3) & 0x3) > -#define DPCD_VOLTAGE_SWING_SET(x) (((x) & 0x3) << 0) > -#define DPCD_VOLTAGE_SWING_GET(x) (((x) >> 0) & 0x3) > - > -#endif /* _EXYNOS_DP_CORE_H */ > diff --git a/include/drm/bridge/analogix_dp.h b/include/drm/bridge/analogix_dp.h > new file mode 100644 > index 0000000..9a207f8 > --- /dev/null > +++ b/include/drm/bridge/analogix_dp.h > @@ -0,0 +1,22 @@ > +#ifndef _ANALOGIX_DP_H_ > +#define _ANALOGIX_DP_H_ > + > +#include <drm/drm_crtc.h> > + > +struct analogix_dp_plat_data { > + struct drm_panel *panel; > + > + int (*power_on)(struct analogix_dp_plat_data *); > + int (*power_off)(struct analogix_dp_plat_data *); > + int (*attach)(struct analogix_dp_plat_data *, struct drm_bridge *); > +}; > + > +int analogix_dp_resume(struct device *dev); > +int analogix_dp_suspend(struct device *dev); > + > +int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, > + struct drm_encoder *encoder, > + struct analogix_dp_plat_data *plat_data); > +void analogix_dp_unbind(struct device *dev, struct device *master, void *data); > + > +#endif /* _ANALOGIX_DP_H_ */ > -- > 2.1.2
Jingoo, ? 2015/8/6 22:33, Jingoo Han ??: > On Thursday, August 06, 2015 11:19 PM, Yakir Yang wrote: >> Split the dp core driver from exynos directory to bridge >> directory, and rename the core driver to analogix_dp_*, >> leave the platform code to analogix_dp-exynos. >> >> Signed-off-by: Yakir Yang <ykk@rock-chips.com> >> --- >> drivers/gpu/drm/bridge/Kconfig | 5 + >> drivers/gpu/drm/bridge/Makefile | 1 + >> .../exynos_dp_core.c => bridge/analogix_dp_core.c} | 751 +++++------- >> drivers/gpu/drm/bridge/analogix_dp_core.h | 286 +++++ >> drivers/gpu/drm/bridge/analogix_dp_reg.c | 1266 ++++++++++++++++++++ >> .../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 260 ++-- >> drivers/gpu/drm/exynos/Kconfig | 5 +- >> drivers/gpu/drm/exynos/Makefile | 2 +- >> drivers/gpu/drm/exynos/analogix_dp-exynos.c | 240 ++++ >> drivers/gpu/drm/exynos/exynos_dp_core.h | 283 ----- >> include/drm/bridge/analogix_dp.h | 22 + >> 11 files changed, 2287 insertions(+), 834 deletions(-) >> rename drivers/gpu/drm/{exynos/exynos_dp_core.c => bridge/analogix_dp_core.c} (54%) >> create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.h >> create mode 100644 drivers/gpu/drm/bridge/analogix_dp_reg.c >> rename drivers/gpu/drm/{exynos/exynos_dp_reg.h => bridge/analogix_dp_reg.h} (63%) >> create mode 100644 drivers/gpu/drm/exynos/analogix_dp-exynos.c >> delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h >> create mode 100644 include/drm/bridge/analogix_dp.h >> >> [...] >> rename from drivers/gpu/drm/exynos/exynos_dp_core.c >> rename to drivers/gpu/drm/bridge/analogix_dp_core.c >> index aa99e23..28724d4 100644 >> --- a/drivers/gpu/drm/exynos/exynos_dp_core.c >> +++ b/drivers/gpu/drm/bridge/analogix_dp_core.c >> @@ -1,7 +1,8 @@ >> /* >> - * Samsung SoC DP (Display Port) interface driver. >> + * Analogix Core DP (Display Port) interface driver. >> * >> * Copyright (C) 2012 Samsung Electronics Co., Ltd. >> + * Copyright (C) FuZhou Rockchip Electronics Co., Ltd. > What is the reason to add this copyright? > You just replace 'exynos' prefix with 'analogix' prefix. > I cannot find the reason to add the copyright. > Oh! Thanks for your point out, sorry for this one - Yakir >> * >> -- >> 2.1.2 > > > >
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index acef322..c7638b5 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -3,6 +3,11 @@ config DRM_DW_HDMI depends on DRM select DRM_KMS_HELPER +config DRM_ANALOGIX_DP + tristate + depends on DRM + select DRM_KMS_HELPER + config DRM_PTN3460 tristate "PTN3460 DP/LVDS bridge" depends on DRM diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile index 8dfebd9..a7ee559 100644 --- a/drivers/gpu/drm/bridge/Makefile +++ b/drivers/gpu/drm/bridge/Makefile @@ -3,3 +3,4 @@ ccflags-y := -Iinclude/drm obj-$(CONFIG_DRM_PS8622) += ps8622.o obj-$(CONFIG_DRM_PTN3460) += ptn3460.o obj-$(CONFIG_DRM_DW_HDMI) += dw_hdmi.o +obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix_dp_core.o analogix_dp_reg.o diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/bridge/analogix_dp_core.c similarity index 54% rename from drivers/gpu/drm/exynos/exynos_dp_core.c rename to drivers/gpu/drm/bridge/analogix_dp_core.c index aa99e23..28724d4 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix_dp_core.c @@ -1,7 +1,8 @@ /* - * Samsung SoC DP (Display Port) interface driver. + * Analogix Core DP (Display Port) interface driver. * * Copyright (C) 2012 Samsung Electronics Co., Ltd. + * Copyright (C) FuZhou Rockchip Electronics Co., Ltd. * Author: Jingoo Han <jg1.han@samsung.com> * Yakir Yang <ykk@rock-chips.com> * @@ -32,51 +33,42 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_panel.h> -#include "exynos_dp_core.h" +#include <drm/bridge/analogix_dp.h> -#define ctx_from_connector(c) container_of(c, struct exynos_dp_device, \ - connector) +#include "analogix_dp_core.h" -static inline struct exynos_drm_crtc *dp_to_crtc(struct exynos_dp_device *dp) -{ - return to_exynos_crtc(dp->encoder->crtc); -} - -static inline struct exynos_dp_device * -display_to_dp(struct exynos_drm_display *d) -{ - return container_of(d, struct exynos_dp_device, display); -} +#define connector_to_dp(c) container_of(c, struct analogix_dp_device, \ + connector) struct bridge_init { struct i2c_client *client; struct device_node *node; }; -static void exynos_dp_init_dp(struct exynos_dp_device *dp) +static void analogix_dp_init_dp(struct analogix_dp_device *dp) { - exynos_dp_reset(dp); + analogix_dp_reset(dp); - exynos_dp_swreset(dp); + analogix_dp_swreset(dp); - exynos_dp_init_analog_param(dp); - exynos_dp_init_interrupt(dp); + analogix_dp_init_analog_param(dp); + analogix_dp_init_interrupt(dp); /* SW defined function Normal operation */ - exynos_dp_enable_sw_function(dp); + analogix_dp_enable_sw_function(dp); - exynos_dp_config_interrupt(dp); - exynos_dp_init_analog_func(dp); + analogix_dp_config_interrupt(dp); + analogix_dp_init_analog_func(dp); - exynos_dp_init_hpd(dp); - exynos_dp_init_aux(dp); + analogix_dp_init_hpd(dp); + analogix_dp_init_aux(dp); } -static int exynos_dp_detect_hpd(struct exynos_dp_device *dp) +static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) { int timeout_loop = 0; - while (exynos_dp_get_plug_in_status(dp) != 0) { + while (analogix_dp_get_plug_in_status(dp) != 0) { timeout_loop++; if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { dev_err(dp->dev, "failed to get hpd plug status\n"); @@ -88,7 +80,7 @@ static int exynos_dp_detect_hpd(struct exynos_dp_device *dp) return 0; } -static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data) +static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data) { int i; unsigned char sum = 0; @@ -99,7 +91,7 @@ static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data) return sum; } -static int exynos_dp_read_edid(struct exynos_dp_device *dp) +static int analogix_dp_read_edid(struct analogix_dp_device *dp) { unsigned char edid[EDID_BLOCK_LENGTH * 2]; unsigned int extend_block = 0; @@ -114,9 +106,9 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) */ /* Read Extension Flag, Number of 128-byte EDID extension blocks */ - retval = exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR, - EDID_EXTENSION_FLAG, - &extend_block); + retval = analogix_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR, + EDID_EXTENSION_FLAG, + &extend_block); if (retval) return retval; @@ -125,15 +117,15 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) /* Read EDID data */ retval = - exynos_dp_read_bytes_from_i2c(dp, I2C_EDID_DEVICE_ADDR, - EDID_HEADER_PATTERN, - EDID_BLOCK_LENGTH, - &edid[EDID_HEADER_PATTERN]); + analogix_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 = exynos_dp_calc_edid_check_sum(edid); + sum = analogix_dp_calc_edid_check_sum(edid); if (sum != 0) { dev_err(dp->dev, "EDID bad checksum!\n"); return -EIO; @@ -141,27 +133,27 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) /* Read additional EDID data */ retval = - exynos_dp_read_bytes_from_i2c(dp, I2C_EDID_DEVICE_ADDR, - EDID_BLOCK_LENGTH, - EDID_BLOCK_LENGTH, - &edid[EDID_BLOCK_LENGTH]); + analogix_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 = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]); + sum = analogix_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]); if (sum != 0) { dev_err(dp->dev, "EDID bad checksum!\n"); return -EIO; } - exynos_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST, - &test_vector); + analogix_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST, + &test_vector); if (test_vector & DP_TEST_LINK_EDID_READ) { - exynos_dp_write_byte_to_dpcd( + analogix_dp_write_byte_to_dpcd( dp, DP_TEST_EDID_CHECKSUM, edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]); - exynos_dp_write_byte_to_dpcd( + analogix_dp_write_byte_to_dpcd( dp, DP_TEST_RESPONSE, DP_TEST_EDID_CHECKSUM_WRITE); } @@ -169,26 +161,26 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) dev_info(dp->dev, "EDID data does not include any extensions.\n"); /* Read EDID data */ - retval = exynos_dp_read_bytes_from_i2c( + retval = analogix_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 = exynos_dp_calc_edid_check_sum(edid); + sum = analogix_dp_calc_edid_check_sum(edid); if (sum != 0) { dev_err(dp->dev, "EDID bad checksum!\n"); return -EIO; } - exynos_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST, - &test_vector); + analogix_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST, + &test_vector); if (test_vector & DP_TEST_LINK_EDID_READ) { - exynos_dp_write_byte_to_dpcd( + analogix_dp_write_byte_to_dpcd( dp, DP_TEST_EDID_CHECKSUM, edid[EDID_CHECKSUM]); - exynos_dp_write_byte_to_dpcd( + analogix_dp_write_byte_to_dpcd( dp, DP_TEST_RESPONSE, DP_TEST_EDID_CHECKSUM_WRITE); } @@ -198,20 +190,20 @@ static int exynos_dp_read_edid(struct exynos_dp_device *dp) return 0; } -static int exynos_dp_handle_edid(struct exynos_dp_device *dp) +static int analogix_dp_handle_edid(struct analogix_dp_device *dp) { u8 buf[12]; int i; int retval; /* Read DPCD DP_DPCD_REV~RECEIVE_PORT1_CAP_1 */ - retval = exynos_dp_read_bytes_from_dpcd(dp, DP_DPCD_REV, 12, buf); + retval = analogix_dp_read_bytes_from_dpcd(dp, DP_DPCD_REV, 12, buf); if (retval) return retval; /* Read EDID */ for (i = 0; i < 3; i++) { - retval = exynos_dp_read_edid(dp); + retval = analogix_dp_read_edid(dp); if (!retval) break; } @@ -219,74 +211,74 @@ static int exynos_dp_handle_edid(struct exynos_dp_device *dp) return retval; } -static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device *dp, - bool enable) +static void analogix_dp_enable_rx_to_enhanced_mode(struct analogixdp_device *dp, + bool enable) { u8 data; - exynos_dp_read_byte_from_dpcd(dp, DP_LANE_COUNT_SET, &data); + analogix_dp_read_byte_from_dpcd(dp, DP_LANE_COUNT_SET, &data); if (enable) - exynos_dp_write_byte_to_dpcd( + analogix_dp_write_byte_to_dpcd( dp, DP_LANE_COUNT_SET, DP_LANE_COUNT_ENHANCED_FRAME_EN | DPCD_LANE_COUNT_SET(data)); else - exynos_dp_write_byte_to_dpcd( + analogix_dp_write_byte_to_dpcd( dp, DP_LANE_COUNT_SET, DPCD_LANE_COUNT_SET(data)); } -static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device *dp) +static int analogix_dp_is_enhanced_mode_available(struct analogix_dp_device *dp) { u8 data; int retval; - exynos_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data); + analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data); retval = DPCD_ENHANCED_FRAME_CAP(data); return retval; } -static void exynos_dp_set_enhanced_mode(struct exynos_dp_device *dp) +static void analogix_dp_set_enhanced_mode(struct analogix_dp_device *dp) { u8 data; - data = exynos_dp_is_enhanced_mode_available(dp); - exynos_dp_enable_rx_to_enhanced_mode(dp, data); - exynos_dp_enable_enhanced_mode(dp, data); + data = analogix_dp_is_enhanced_mode_available(dp); + analogix_dp_enable_rx_to_enhanced_mode(dp, data); + analogix_dp_enable_enhanced_mode(dp, data); } -static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp) +static void analogix_dp_training_pattern_dis(struct analogix_dp_device *dp) { - exynos_dp_set_training_pattern(dp, DP_NONE); + analogix_dp_set_training_pattern(dp, DP_NONE); - exynos_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET, - DP_TRAINING_PATTERN_DISABLE); + analogix_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET, + DP_TRAINING_PATTERN_DISABLE); } -static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp, - int pre_emphasis, int lane) +static void analogix_dp_set_lane_lane_pre_emphasis(struct analogixdp_device *dp, + int pre_emphasis, int lane) { switch (lane) { case 0: - exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis); + analogix_dp_set_lane0_pre_emphasis(dp, pre_emphasis); break; case 1: - exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis); + analogix_dp_set_lane1_pre_emphasis(dp, pre_emphasis); break; case 2: - exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis); + analogix_dp_set_lane2_pre_emphasis(dp, pre_emphasis); break; case 3: - exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis); + analogix_dp_set_lane3_pre_emphasis(dp, pre_emphasis); break; } } -static int exynos_dp_link_start(struct exynos_dp_device *dp) +static int analogix_dp_link_start(struct analogix_dp_device *dp) { u8 buf[4]; int lane, lane_count, pll_tries, retval; @@ -300,24 +292,24 @@ static int exynos_dp_link_start(struct exynos_dp_device *dp) dp->link_train.cr_loop[lane] = 0; /* Set link rate and count as you want to establish*/ - exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate); - exynos_dp_set_lane_count(dp, dp->link_train.lane_count); + analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); + analogix_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 = exynos_dp_write_bytes_to_dpcd(dp, DP_LINK_BW_SET, 2, buf); + retval = analogix_dp_write_bytes_to_dpcd(dp, DP_LINK_BW_SET, 2, buf); if (retval) return retval; /* Set TX pre-emphasis to minimum */ for (lane = 0; lane < lane_count; lane++) - exynos_dp_set_lane_lane_pre_emphasis(dp, PRE_EMPHASIS_LEVEL_0, - lane); + analogix_dp_set_lane_lane_pre_emphasis( + dp, PRE_EMPHASIS_LEVEL_0, lane); /* Wait for PLL lock */ pll_tries = 0; - while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { + while (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { if (pll_tries == DP_TIMEOUT_LOOP_COUNT) { dev_err(dp->dev, "Wait for PLL lock timed out\n"); return -ETIMEDOUT; @@ -328,12 +320,12 @@ static int exynos_dp_link_start(struct exynos_dp_device *dp) } /* Set training pattern 1 */ - exynos_dp_set_training_pattern(dp, TRAINING_PTN1); + analogix_dp_set_training_pattern(dp, TRAINING_PTN1); /* Set RX training pattern */ - retval = exynos_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET, - DP_LINK_SCRAMBLING_DISABLE | - DP_TRAINING_PATTERN_1); + retval = analogix_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET, + DP_LINK_SCRAMBLING_DISABLE | + DP_TRAINING_PATTERN_1); if (retval) return retval; @@ -341,13 +333,13 @@ static int exynos_dp_link_start(struct exynos_dp_device *dp) buf[lane] = DP_TRAIN_PRE_EMPH_LEVEL_0 | DP_TRAIN_VOLTAGE_SWING_LEVEL_0; - retval = exynos_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET, - lane_count, buf); + retval = analogix_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET, + lane_count, buf); return retval; } -static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane) +static unsigned char analogix_dp_get_lane_status(u8 link_status[2], int lane) { int shift = (lane & 1) * 4; u8 link_value = link_status[lane >> 1]; @@ -355,21 +347,21 @@ static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane) return (link_value >> shift) & 0xf; } -static int exynos_dp_clock_recovery_ok(u8 link_status[2], int lane_count) +static int analogix_dp_clock_recovery_ok(u8 link_status[2], int lane_count) { int lane; u8 lane_status; for (lane = 0; lane < lane_count; lane++) { - lane_status = exynos_dp_get_lane_status(link_status, lane); + lane_status = analogix_dp_get_lane_status(link_status, lane); if ((lane_status & DP_LANE_CR_DONE) == 0) return -EINVAL; } return 0; } -static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align, - int lane_count) +static int analogix_dp_channel_eq_ok(u8 link_status[2], u8 link_align, + int lane_count) { int lane; u8 lane_status; @@ -378,7 +370,7 @@ static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align, return -EINVAL; for (lane = 0; lane < lane_count; lane++) { - lane_status = exynos_dp_get_lane_status(link_status, lane); + lane_status = analogix_dp_get_lane_status(link_status, lane); lane_status &= DP_CHANNEL_EQ_BITS; if (lane_status != DP_CHANNEL_EQ_BITS) return -EINVAL; @@ -387,8 +379,8 @@ static int exynos_dp_channel_eq_ok(u8 link_status[2], u8 link_align, return 0; } -static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request[2], - int lane) +static unsigned char +analogix_dp_get_adjust_request_voltage(u8 adjust_request[2], int lane) { int shift = (lane & 1) * 4; u8 link_value = adjust_request[lane >> 1]; @@ -396,7 +388,7 @@ static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request[2], return (link_value >> shift) & 0x3; } -static unsigned char exynos_dp_get_adjust_request_pre_emphasis( +static unsigned char analogix_dp_get_adjust_request_pre_emphasis( u8 adjust_request[2], int lane) { @@ -406,45 +398,45 @@ static unsigned char exynos_dp_get_adjust_request_pre_emphasis( return ((link_value >> shift) & 0xc) >> 2; } -static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp, - u8 training_lane_set, int lane) +static void analogix_dp_set_lane_link_training(struct analogixdp_device *dp, + u8 training_lane_set, int lane) { switch (lane) { case 0: - exynos_dp_set_lane0_link_training(dp, training_lane_set); + analogix_dp_set_lane0_link_training(dp, training_lane_set); break; case 1: - exynos_dp_set_lane1_link_training(dp, training_lane_set); + analogix_dp_set_lane1_link_training(dp, training_lane_set); break; case 2: - exynos_dp_set_lane2_link_training(dp, training_lane_set); + analogix_dp_set_lane2_link_training(dp, training_lane_set); break; case 3: - exynos_dp_set_lane3_link_training(dp, training_lane_set); + analogix_dp_set_lane3_link_training(dp, training_lane_set); break; } } -static unsigned int exynos_dp_get_lane_link_training( - struct exynos_dp_device *dp, +static unsigned int analogix_dp_get_lane_link_training( + struct analogix_dp_device *dp, int lane) { u32 reg; switch (lane) { case 0: - reg = exynos_dp_get_lane0_link_training(dp); + reg = analogix_dp_get_lane0_link_training(dp); break; case 1: - reg = exynos_dp_get_lane1_link_training(dp); + reg = analogix_dp_get_lane1_link_training(dp); break; case 2: - reg = exynos_dp_get_lane2_link_training(dp); + reg = analogix_dp_get_lane2_link_training(dp); break; case 3: - reg = exynos_dp_get_lane3_link_training(dp); + reg = analogix_dp_get_lane3_link_training(dp); break; default: WARN_ON(1); @@ -454,25 +446,25 @@ static unsigned int exynos_dp_get_lane_link_training( return reg; } -static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp) +static void analogix_dp_reduce_link_rate(struct analogix_dp_device *dp) { - exynos_dp_training_pattern_dis(dp); - exynos_dp_set_enhanced_mode(dp); + analogix_dp_training_pattern_dis(dp); + analogix_dp_set_enhanced_mode(dp); dp->link_train.lt_state = FAILED; } -static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp, - u8 adjust_request[2]) +static void analogix_dp_get_adjust_training_lane(struct analogixdp_device *dp, + u8 adjust_request[2]) { int lane, lane_count; u8 voltage_swing, pre_emphasis, training_lane; lane_count = dp->link_train.lane_count; for (lane = 0; lane < lane_count; lane++) { - voltage_swing = exynos_dp_get_adjust_request_voltage( + voltage_swing = analogix_dp_get_adjust_request_voltage( adjust_request, lane); - pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis( + pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis( adjust_request, lane); training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) | DPCD_PRE_EMPHASIS_SET(pre_emphasis); @@ -486,7 +478,7 @@ static void exynos_dp_get_adjust_training_lane(struct exynos_dp_device *dp, } } -static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) +static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp) { int lane, lane_count, retval; u8 voltage_swing, pre_emphasis, training_lane; @@ -496,24 +488,24 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) lane_count = dp->link_train.lane_count; - retval = exynos_dp_read_bytes_from_dpcd(dp, DP_LANE0_1_STATUS, - 2, link_status); + retval = analogix_dp_read_bytes_from_dpcd( + dp, DP_LANE0_1_STATUS, 2, link_status); if (retval) return retval; - retval = exynos_dp_read_bytes_from_dpcd(dp, DP_ADJUST_REQUEST_LANE0_1, - 2, adjust_request); + retval = analogix_dp_read_bytes_from_dpcd( + dp, DP_ADJUST_REQUEST_LANE0_1, 2, adjust_request); if (retval) return retval; - if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) { + if (analogix_dp_clock_recovery_ok(link_status, lane_count) == 0) { /* set training pattern 2 for EQ */ - exynos_dp_set_training_pattern(dp, TRAINING_PTN2); + analogix_dp_set_training_pattern(dp, TRAINING_PTN2); - retval = exynos_dp_write_byte_to_dpcd( - dp, DP_TRAINING_PATTERN_SET, - DP_LINK_SCRAMBLING_DISABLE | - DP_TRAINING_PATTERN_2); + retval = analogix_dp_write_byte_to_dpcd( + dp, DP_TRAINING_PATTERN_SET, + DP_LINK_SCRAMBLING_DISABLE | + DP_TRAINING_PATTERN_2); if (retval) return retval; @@ -521,12 +513,12 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) dp->link_train.lt_state = EQUALIZER_TRAINING; } else { for (lane = 0; lane < lane_count; lane++) { - training_lane = exynos_dp_get_lane_link_training( + training_lane = analogix_dp_get_lane_link_training( dp, lane); - voltage_swing = exynos_dp_get_adjust_request_voltage( + voltage_swing = analogix_dp_get_adjust_request_voltage( adjust_request, lane); pre_emphasis = - exynos_dp_get_adjust_request_pre_emphasis( + analogix_dp_get_adjust_request_pre_emphasis( adjust_request, lane); if (DPCD_VOLTAGE_SWING_GET(training_lane) == @@ -541,19 +533,19 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n", dp->link_train.cr_loop[lane], voltage_swing, pre_emphasis); - exynos_dp_reduce_link_rate(dp); + analogix_dp_reduce_link_rate(dp); return -EIO; } } } - exynos_dp_get_adjust_training_lane(dp, adjust_request); + analogix_dp_get_adjust_training_lane(dp, adjust_request); for (lane = 0; lane < lane_count; lane++) - exynos_dp_set_lane_link_training( + analogix_dp_set_lane_link_training( dp, dp->link_train.training_lane[lane], lane); - retval = exynos_dp_write_bytes_to_dpcd( + retval = analogix_dp_write_bytes_to_dpcd( dp, DP_TRAINING_LANE0_SET, lane_count, dp->link_train.training_lane); if (retval) @@ -562,7 +554,7 @@ static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp) return retval; } -static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) +static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp) { int lane, lane_count, retval; u32 reg; @@ -572,46 +564,46 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) lane_count = dp->link_train.lane_count; - retval = exynos_dp_read_bytes_from_dpcd(dp, DP_LANE0_1_STATUS, - 2, link_status); + retval = analogix_dp_read_bytes_from_dpcd(dp, DP_LANE0_1_STATUS, + 2, link_status); if (retval) return retval; - if (exynos_dp_clock_recovery_ok(link_status, lane_count)) { - exynos_dp_reduce_link_rate(dp); + if (analogix_dp_clock_recovery_ok(link_status, lane_count)) { + analogix_dp_reduce_link_rate(dp); return -EIO; } - retval = exynos_dp_read_bytes_from_dpcd(dp, DP_ADJUST_REQUEST_LANE0_1, - 2, adjust_request); + retval = analogix_dp_read_bytes_from_dpcd(dp, DP_ADJUST_REQUEST_LANE0_1, + 2, adjust_request); if (retval) return retval; - retval = exynos_dp_read_byte_from_dpcd( + retval = analogix_dp_read_byte_from_dpcd( dp, DP_LANE_ALIGN_STATUS_UPDATED, &link_align); if (retval) return retval; - exynos_dp_get_adjust_training_lane(dp, adjust_request); + analogix_dp_get_adjust_training_lane(dp, adjust_request); - if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count)) { + if (!analogix_dp_channel_eq_ok(link_status, link_align, lane_count)) { /* traing pattern Set to Normal */ - exynos_dp_training_pattern_dis(dp); + analogix_dp_training_pattern_dis(dp); dev_info(dp->dev, "Link Training success!\n"); - exynos_dp_get_link_bandwidth(dp, ®); + analogix_dp_get_link_bandwidth(dp, ®); dp->link_train.link_rate = reg; dev_dbg(dp->dev, "final bandwidth = %.2x\n", dp->link_train.link_rate); - exynos_dp_get_lane_count(dp, ®); + analogix_dp_get_lane_count(dp, ®); dp->link_train.lane_count = reg; dev_dbg(dp->dev, "final lane count = %.2x\n", dp->link_train.lane_count); /* set enhanced mode if available */ - exynos_dp_set_enhanced_mode(dp); + analogix_dp_set_enhanced_mode(dp); dp->link_train.lt_state = FINISHED; return 0; @@ -622,23 +614,23 @@ static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp) if (dp->link_train.eq_loop > MAX_EQ_LOOP) { dev_err(dp->dev, "EQ Max loop\n"); - exynos_dp_reduce_link_rate(dp); + analogix_dp_reduce_link_rate(dp); return -EIO; } for (lane = 0; lane < lane_count; lane++) - exynos_dp_set_lane_link_training( + analogix_dp_set_lane_link_training( dp, dp->link_train.training_lane[lane], lane); - retval = exynos_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET, - lane_count, - dp->link_train.training_lane); + retval = analogix_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET, + lane_count, + dp->link_train.training_lane); return retval; } -static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp, - u8 *bandwidth) +static void analogix_dp_get_max_rx_bandwidth(struct analogixdp_device *dp, + u8 *bandwidth) { u8 data; @@ -646,12 +638,12 @@ static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp, * For DP rev.1.1, Maximum link rate of Main Link lanes * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps */ - exynos_dp_read_byte_from_dpcd(dp, DP_MAX_LINK_RATE, &data); + analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LINK_RATE, &data); *bandwidth = data; } -static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp, - u8 *lane_count) +static void analogix_dp_get_max_rx_lane_count(struct analogixdp_device *dp, + u8 *lane_count) { u8 data; @@ -659,23 +651,23 @@ static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp, * For DP rev.1.1, Maximum number of Main Link lanes * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes */ - exynos_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data); + analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data); *lane_count = DPCD_MAX_LANE_COUNT(data); } -static void exynos_dp_init_training(struct exynos_dp_device *dp, - enum link_lane_count_type max_lane, - enum link_rate_type max_rate) +static void analogix_dp_init_training(struct analogixdp_device *dp, + enum link_lane_count_type max_lane, + enum link_rate_type max_rate) { /* * MACRO_RST must be applied after the PLL_LOCK to avoid * the DP inter pair skew issue for at least 10 us */ - exynos_dp_reset_macro(dp); + analogix_dp_reset_macro(dp); /* Initialize by reading RX's DPCD */ - exynos_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate); - exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count); + analogix_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate); + analogix_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count); if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) && (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) { @@ -697,10 +689,10 @@ static void exynos_dp_init_training(struct exynos_dp_device *dp, dp->link_train.link_rate = max_rate; /* All DP analog module power up */ - exynos_dp_set_analog_power_down(dp, POWER_ALL, 0); + analogix_dp_set_analog_power_down(dp, POWER_ALL, 0); } -static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) +static int analogix_dp_sw_link_training(struct analogix_dp_device *dp) { int retval = 0, training_finished = 0; @@ -710,17 +702,17 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) while (!retval && !training_finished) { switch (dp->link_train.lt_state) { case START: - retval = exynos_dp_link_start(dp); + retval = analogix_dp_link_start(dp); if (retval) dev_err(dp->dev, "LT link start failed!\n"); break; case CLOCK_RECOVERY: - retval = exynos_dp_process_clock_recovery(dp); + retval = analogix_dp_process_clock_recovery(dp); if (retval) dev_err(dp->dev, "LT CR failed!\n"); break; case EQUALIZER_TRAINING: - retval = exynos_dp_process_equalizer_training(dp); + retval = analogix_dp_process_equalizer_training(dp); if (retval) dev_err(dp->dev, "LT EQ failed!\n"); break; @@ -737,15 +729,15 @@ static int exynos_dp_sw_link_training(struct exynos_dp_device *dp) return retval; } -static int exynos_dp_set_link_train(struct exynos_dp_device *dp, - u32 count, u32 bwtype) +static int analogix_dp_set_link_train(struct analogixdp_device *dp, + u32 count, u32 bwtype) { int i; int retval; for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) { - exynos_dp_init_training(dp, count, bwtype); - retval = exynos_dp_sw_link_training(dp); + analogix_dp_init_training(dp, count, bwtype); + retval = analogix_dp_sw_link_training(dp); if (retval == 0) break; @@ -755,24 +747,24 @@ static int exynos_dp_set_link_train(struct exynos_dp_device *dp, return retval; } -static int exynos_dp_config_video(struct exynos_dp_device *dp) +static int analogix_dp_config_video(struct analogix_dp_device *dp) { int retval = 0; int timeout_loop = 0; int done_count = 0; - exynos_dp_config_video_slave_mode(dp); + analogix_dp_config_video_slave_mode(dp); - exynos_dp_set_video_color_format(dp); + analogix_dp_set_video_color_format(dp); - if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { + if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { dev_err(dp->dev, "PLL is not locked yet.\n"); return -EINVAL; } for (;;) { timeout_loop++; - if (exynos_dp_is_slave_video_stream_clock_on(dp) == 0) + if (analogix_dp_is_slave_video_stream_clock_on(dp) == 0) break; if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { dev_err(dp->dev, "Timeout of video streamclk ok\n"); @@ -783,25 +775,25 @@ static int exynos_dp_config_video(struct exynos_dp_device *dp) } /* Set to use the register calculated M/N video */ - exynos_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0); + analogix_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0); /* For video bist, Video timing must be generated by register */ - exynos_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE); + analogix_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE); /* Disable video mute */ - exynos_dp_enable_video_mute(dp, 0); + analogix_dp_enable_video_mute(dp, 0); /* Configure video slave mode */ - exynos_dp_enable_video_master(dp, 0); + analogix_dp_enable_video_master(dp, 0); /* Enable video */ - exynos_dp_start_video(dp); + analogix_dp_start_video(dp); timeout_loop = 0; for (;;) { timeout_loop++; - if (exynos_dp_is_video_stream_on(dp) == 0) { + if (analogix_dp_is_video_stream_on(dp) == 0) { done_count++; if (done_count > 10) break; @@ -822,45 +814,46 @@ static int exynos_dp_config_video(struct exynos_dp_device *dp) return retval; } -static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool enable) +static void analogix_dp_enable_scramble(struct analogix_dp_device *dp, + bool enable) { u8 data; if (enable) { - exynos_dp_enable_scrambling(dp); + analogix_dp_enable_scrambling(dp); - exynos_dp_read_byte_from_dpcd(dp, DP_TRAINING_PATTERN_SET, - &data); - exynos_dp_write_byte_to_dpcd( - dp, DP_TRAINING_PATTERN_SET, - (u8)(data & ~DP_LINK_SCRAMBLING_DISABLE)); + analogix_dp_read_byte_from_dpcd( + dp, DP_TRAINING_PATTERN_SET, &data); + analogix_dp_write_byte_to_dpcd( + dp, DP_TRAINING_PATTERN_SET, + (u8)(data & ~DP_LINK_SCRAMBLING_DISABLE)); } else { - exynos_dp_disable_scrambling(dp); + analogix_dp_disable_scrambling(dp); - exynos_dp_read_byte_from_dpcd(dp, DP_TRAINING_PATTERN_SET, - &data); - exynos_dp_write_byte_to_dpcd( + analogix_dp_read_byte_from_dpcd(dp, DP_TRAINING_PATTERN_SET, + &data); + analogix_dp_write_byte_to_dpcd( dp, DP_TRAINING_PATTERN_SET, (u8)(data | DP_LINK_SCRAMBLING_DISABLE)); } } -static irqreturn_t exynos_dp_irq_handler(int irq, void *arg) +static irqreturn_t analogix_dp_irq_handler(int irq, void *arg) { - struct exynos_dp_device *dp = arg; + struct analogix_dp_device *dp = arg; enum dp_irq_type irq_type; - irq_type = exynos_dp_get_irq_type(dp); + irq_type = analogix_dp_get_irq_type(dp); switch (irq_type) { case DP_IRQ_TYPE_HP_CABLE_IN: dev_dbg(dp->dev, "Received irq - cable in\n"); schedule_work(&dp->hotplug_work); - exynos_dp_clear_hotplug_interrupts(dp); + analogix_dp_clear_hotplug_interrupts(dp); break; case DP_IRQ_TYPE_HP_CABLE_OUT: dev_dbg(dp->dev, "Received irq - cable out\n"); - exynos_dp_clear_hotplug_interrupts(dp); + analogix_dp_clear_hotplug_interrupts(dp); break; case DP_IRQ_TYPE_HP_CHANGE: /* @@ -869,7 +862,7 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg) * only handle cable changes. */ dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n"); - exynos_dp_clear_hotplug_interrupts(dp); + analogix_dp_clear_hotplug_interrupts(dp); break; default: dev_err(dp->dev, "Received irq - unknown type!\n"); @@ -878,94 +871,93 @@ static irqreturn_t exynos_dp_irq_handler(int irq, void *arg) return IRQ_HANDLED; } -static void exynos_dp_hotplug(struct work_struct *work) +static void analogix_dp_hotplug(struct work_struct *work) { - struct exynos_dp_device *dp; + struct analogix_dp_device *dp; - dp = container_of(work, struct exynos_dp_device, hotplug_work); + dp = container_of(work, struct analogix_dp_device, hotplug_work); if (dp->drm_dev) drm_helper_hpd_irq_event(dp->drm_dev); } -static void exynos_dp_commit(struct exynos_drm_display *display) +static void analogix_dp_commit(struct analogix_dp_device *dp) { - struct exynos_dp_device *dp = display_to_dp(display); int ret; /* Keep the panel disabled while we configure video */ - if (dp->panel) { - if (drm_panel_disable(dp->panel)) + if (dp->plat_data && dp->plat_data->panel) { + if (drm_panel_disable(dp->plat_data->panel)) DRM_ERROR("failed to disable the panel\n"); } - ret = exynos_dp_detect_hpd(dp); + ret = analogix_dp_detect_hpd(dp); if (ret) { /* Cable has been disconnected, we're done */ return; } - ret = exynos_dp_handle_edid(dp); + ret = analogix_dp_handle_edid(dp); if (ret) { dev_err(dp->dev, "unable to handle edid\n"); return; } - ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count, - dp->video_info->link_rate); + ret = analogix_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"); return; } - exynos_dp_enable_scramble(dp, 1); - exynos_dp_enable_rx_to_enhanced_mode(dp, 1); - exynos_dp_enable_enhanced_mode(dp, 1); + analogix_dp_enable_scramble(dp, 1); + analogix_dp_enable_rx_to_enhanced_mode(dp, 1); + analogix_dp_enable_enhanced_mode(dp, 1); - exynos_dp_set_lane_count(dp, dp->video_info->lane_count); - exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate); + analogix_dp_set_lane_count(dp, dp->video_info->lane_count); + analogix_dp_set_link_bandwidth(dp, dp->video_info->link_rate); - exynos_dp_init_video(dp); - ret = exynos_dp_config_video(dp); + analogix_dp_init_video(dp); + ret = analogix_dp_config_video(dp); if (ret) dev_err(dp->dev, "unable to config video\n"); /* Safe to enable the panel now */ - if (dp->panel) { - if (drm_panel_enable(dp->panel)) + if (dp->plat_data && dp->plat_data->panel) { + if (drm_panel_enable(dp->plat_data->panel)) DRM_ERROR("failed to enable the panel\n"); } } -static enum drm_connector_status exynos_dp_detect( +static enum drm_connector_status analogix_dp_detect( struct drm_connector *connector, bool force) { return connector_status_connected; } -static void exynos_dp_connector_destroy(struct drm_connector *connector) +static void analogix_dp_connector_destroy(struct drm_connector *connector) { drm_connector_unregister(connector); drm_connector_cleanup(connector); } -static struct drm_connector_funcs exynos_dp_connector_funcs = { +static struct drm_connector_funcs analogix_dp_connector_funcs = { .dpms = drm_atomic_helper_connector_dpms, .fill_modes = drm_helper_probe_single_connector_modes, - .detect = exynos_dp_detect, - .destroy = exynos_dp_connector_destroy, + .detect = analogix_dp_detect, + .destroy = analogix_dp_connector_destroy, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; -static int exynos_dp_get_modes(struct drm_connector *connector) +static int analogix_dp_get_modes(struct drm_connector *connector) { - struct exynos_dp_device *dp = ctx_from_connector(connector); + struct analogix_dp_device *dp = connector_to_dp(connector); struct drm_display_mode *mode; - if (dp->panel) - return drm_panel_get_modes(dp->panel); + if (dp->plat_data && dp->plat_data->panel) + return drm_panel_get_modes(dp->plat_data->panel); mode = drm_mode_create(connector->dev); if (!mode) { @@ -986,64 +978,60 @@ static int exynos_dp_get_modes(struct drm_connector *connector) return 1; } -static struct drm_encoder *exynos_dp_best_encoder( +static struct drm_encoder *analogix_dp_best_encoder( struct drm_connector *connector) { - struct exynos_dp_device *dp = ctx_from_connector(connector); + struct analogix_dp_device *dp = connector_to_dp(connector); return dp->encoder; } -static struct drm_connector_helper_funcs exynos_dp_connector_helper_funcs = { - .get_modes = exynos_dp_get_modes, - .best_encoder = exynos_dp_best_encoder, +static struct drm_connector_helper_funcs analogix_dp_connector_helper_funcs = { + .get_modes = analogix_dp_get_modes, + .best_encoder = analogix_dp_best_encoder, }; -static void exynos_dp_phy_init(struct exynos_dp_device *dp) +static void analogix_dp_phy_init(struct analogix_dp_device *dp) { if (dp->phy) phy_power_on(dp->phy); } -static void exynos_dp_phy_exit(struct exynos_dp_device *dp) +static void analogix_dp_phy_exit(struct analogix_dp_device *dp) { if (dp->phy) phy_power_off(dp->phy); } -static void exynos_dp_poweron(struct exynos_dp_device *dp) +static void analogix_dp_poweron(struct analogix_dp_device *dp) { - struct exynos_drm_crtc *crtc = dp_to_crtc(dp); - if (dp->dpms_mode == DRM_MODE_DPMS_ON) return; - if (dp->panel) { - if (drm_panel_prepare(dp->panel)) { + if (dp->plat_data && dp->plat_data->panel) { + if (drm_panel_prepare(dp->plat_data->panel)) { DRM_ERROR("failed to setup the panel\n"); return; } } - if (crtc->ops->clock_enable) - crtc->ops->clock_enable(dp_to_crtc(dp), true); + if (dp->plat_data && dp->plat_data->power_on) + dp->plat_data->power_on(dp->plat_data); clk_prepare_enable(dp->clock); - exynos_dp_phy_init(dp); - exynos_dp_init_dp(dp); + analogix_dp_phy_init(dp); + analogix_dp_init_dp(dp); enable_irq(dp->irq); - exynos_dp_commit(&dp->display); + analogix_dp_commit(dp); } -static void exynos_dp_poweroff(struct exynos_dp_device *dp) +static void analogix_dp_poweroff(struct analogix_dp_device *dp) { - struct exynos_drm_crtc *crtc = dp_to_crtc(dp); - if (dp->dpms_mode != DRM_MODE_DPMS_ON) return; - if (dp->panel) { - if (drm_panel_disable(dp->panel)) { + if (dp->plat_data && dp->plat_data->panel) { + if (drm_panel_disable(dp->plat_data->panel)) { DRM_ERROR("failed to disable the panel\n"); return; } @@ -1051,39 +1039,21 @@ static void exynos_dp_poweroff(struct exynos_dp_device *dp) disable_irq(dp->irq); flush_work(&dp->hotplug_work); - exynos_dp_phy_exit(dp); + analogix_dp_phy_exit(dp); clk_disable_unprepare(dp->clock); - if (crtc->ops->clock_enable) - crtc->ops->clock_enable(dp_to_crtc(dp), false); + if (dp->plat_data && dp->plat_data->power_off) + dp->plat_data->power_off(dp->plat_data); - if (dp->panel) { - if (drm_panel_unprepare(dp->panel)) + if (dp->plat_data && dp->plat_data->panel) { + if (drm_panel_unprepare(dp->plat_data->panel)) DRM_ERROR("failed to turnoff the panel\n"); } } -/* returns the number of bridges attached */ -static int exynos_drm_attach_lcd_bridge(struct exynos_dp_device *dp, - struct drm_encoder *encoder) -{ - int ret; - - dp->bridge->next = dp->ptn_bridge; - dp->bridge->encoder = encoder; - ret = drm_bridge_attach(encoder->dev, dp->bridge); - if (ret) { - DRM_ERROR("Failed to attach ptn bridge to drm\n"); - return ret; - } - - return 0; -} - -static int exynos_dp_bridge_attach(struct drm_bridge *bridge) +static int analogix_dp_bridge_attach(struct drm_bridge *bridge) { - - struct exynos_dp_device *dp = bridge->driver_private; + struct analogix_dp_device *dp = bridge->driver_private; struct drm_encoder *encoder = dp->encoder; struct drm_connector *connector = &dp->connector; int ret; @@ -1095,66 +1065,77 @@ static int exynos_dp_bridge_attach(struct drm_bridge *bridge) encoder->bridge = bridge; - /* Pre-empt DP connector creation if there's a bridge */ - if (dp->ptn_bridge) { - ret = exynos_drm_attach_lcd_bridge(dp, encoder); - if (ret) - return -ENODEV; - } - connector->polled = DRM_CONNECTOR_POLL_HPD; ret = drm_connector_init(dp->drm_dev, connector, - &exynos_dp_connector_funcs, DRM_MODE_CONNECTOR_eDP); + &analogix_dp_connector_funcs, + DRM_MODE_CONNECTOR_eDP); if (ret) { DRM_ERROR("Failed to initialize connector with drm\n"); return ret; } - drm_connector_helper_add(connector, &exynos_dp_connector_helper_funcs); + drm_connector_helper_add(connector, + &analogix_dp_connector_helper_funcs); drm_connector_register(connector); drm_mode_connector_attach_encoder(connector, encoder); - if (dp->panel) - ret = drm_panel_attach(dp->panel, &dp->connector); + if (dp->plat_data && dp->plat_data->panel) { + ret = drm_panel_attach(dp->plat_data->panel, &dp->connector); + if (ret) { + DRM_ERROR("Failed to attach panel\n"); + return ret; + } + } + + /* + * This should be the end of attach function, caused + * we should ensure dp bridge could attach first. + */ + if (dp->plat_data && dp->plat_data->attach) { + ret = dp->plat_data->attach(dp->plat_data, bridge); + if (ret) { + DRM_ERROR("Failed at platform attch func\n"); + return ret; + } + } - return ret; + return 0; } -static void exynos_dp_bridge_nop(struct drm_bridge *bridge) +static void analogix_dp_bridge_nop(struct drm_bridge *bridge) { /* do nothing */ } -static void exynos_dp_bridge_enable(struct drm_bridge *bridge) +static void analogix_dp_bridge_enable(struct drm_bridge *bridge) { - struct exynos_dp_device *dp = bridge->driver_private; + struct analogix_dp_device *dp = bridge->driver_private; - exynos_dp_poweron(dp); + analogix_dp_poweron(dp); dp->dpms_mode = DRM_MODE_DPMS_ON; } -static void exynos_dp_bridge_disable(struct drm_bridge *bridge) +static void analogix_dp_bridge_disable(struct drm_bridge *bridge) { - struct exynos_dp_device *dp = bridge->driver_private; + struct analogix_dp_device *dp = bridge->driver_private; - exynos_dp_poweroff(dp); + analogix_dp_poweroff(dp); dp->dpms_mode = DRM_MODE_DPMS_OFF; } -static const struct drm_bridge_funcs exynos_dp_bridge_funcs = { - .enable = exynos_dp_bridge_enable, - .disable = exynos_dp_bridge_disable, - .pre_enable = exynos_dp_bridge_nop, - .post_disable = exynos_dp_bridge_nop, - .attach = exynos_dp_bridge_attach, +static const struct drm_bridge_funcs analogix_dp_bridge_funcs = { + .enable = analogix_dp_bridge_enable, + .disable = analogix_dp_bridge_disable, + .pre_enable = analogix_dp_bridge_nop, + .post_disable = analogix_dp_bridge_nop, + .attach = analogix_dp_bridge_attach, }; -static int exynos_dp_create_connector(struct exynos_drm_display *display, - struct drm_encoder *encoder) +static int analogix_dp_bridge_register(struct drm_device *drm_dev, + struct analogix_dp_device *dp) + { - struct exynos_dp_device *dp = display_to_dp(display); - struct drm_device *drm_dev = dp->drm_dev; struct drm_bridge *bridge; int ret; @@ -1165,11 +1146,10 @@ static int exynos_dp_create_connector(struct exynos_drm_display *display, } dp->bridge = bridge; - dp->encoder = encoder; bridge->driver_private = dp; bridge->encoder = dp->encoder; - bridge->funcs = &exynos_dp_bridge_funcs; + bridge->funcs = &analogix_dp_bridge_funcs; ret = drm_bridge_attach(drm_dev, bridge); if (ret) { @@ -1180,18 +1160,7 @@ static int exynos_dp_create_connector(struct exynos_drm_display *display, return 0; } -static void exynos_dp_dpms(struct exynos_drm_display *display, int mode) -{ - /* do nothing */ -} - -static struct exynos_drm_display_ops exynos_dp_display_ops = { - .create_connector = exynos_dp_create_connector, - .dpms = exynos_dp_dpms, - .commit = exynos_dp_commit, -}; - -static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev) +static struct video_info *analogix_dp_dt_parse_pdata(struct device *dev) { struct device_node *dp_node = dev->of_node; struct video_info *dp_video_config; @@ -1249,7 +1218,7 @@ static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev) return dp_video_config; } -static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp) +static int analogix_dp_dt_parse_panel(struct analogix_dp_device *dp) { int ret; @@ -1262,19 +1231,33 @@ static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp) return 0; } -static int exynos_dp_bind(struct device *dev, struct device *master, void *data) +int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, + struct drm_encoder *encoder, + struct analogix_dp_plat_data *plat_data) { - struct exynos_dp_device *dp = dev_get_drvdata(dev); struct platform_device *pdev = to_platform_device(dev); - struct drm_device *drm_dev = data; + struct analogix_dp_device *dp; struct resource *res; unsigned int irq_flags; int ret = 0; + dp = devm_kzalloc(dev, sizeof(struct analogix_dp_device), GFP_KERNEL); + if (!dp) + return -ENOMEM; + + dev_set_drvdata(dev, dp); + dp->dev = &pdev->dev; dp->dpms_mode = DRM_MODE_DPMS_OFF; - dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev); + /* + * platform dp driver need containor_of the plat_data to get + * the driver private data, so we need to store the point of + * plat_data, not the context of plat_data. + */ + dp->plat_data = plat_data; + + dp->video_info = analogix_dp_dt_parse_pdata(&pdev->dev); if (IS_ERR(dp->video_info)) return PTR_ERR(dp->video_info); @@ -1294,8 +1277,8 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) } } - if (!dp->panel && !dp->ptn_bridge) { - ret = exynos_dp_dt_parse_panel(dp); + if (!dp->plat_data || !dp->plat_data->panel) { + ret = analogix_dp_dt_parse_panel(dp); if (ret) return ret; } @@ -1343,14 +1326,14 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) return -ENODEV; } - INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug); + INIT_WORK(&dp->hotplug_work, analogix_dp_hotplug); - exynos_dp_phy_init(dp); + analogix_dp_phy_init(dp); - exynos_dp_init_dp(dp); + analogix_dp_init_dp(dp); - ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler, - irq_flags, "exynos-dp", dp); + ret = devm_request_irq(&pdev->dev, dp->irq, analogix_dp_irq_handler, + irq_flags, "analogix-dp", dp); if (ret) { dev_err(&pdev->dev, "failed to request irq\n"); return ret; @@ -1358,109 +1341,39 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data) disable_irq(dp->irq); dp->drm_dev = drm_dev; + dp->encoder = encoder; - return exynos_drm_create_enc_conn(drm_dev, &dp->display); -} - -static void exynos_dp_unbind(struct device *dev, struct device *master, - void *data) -{ - struct exynos_dp_device *dp = dev_get_drvdata(dev); - - exynos_dp_bridge_disable(dp->bridge); -} - -static const struct component_ops exynos_dp_ops = { - .bind = exynos_dp_bind, - .unbind = exynos_dp_unbind, -}; - -static int exynos_dp_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *panel_node, *bridge_node, *endpoint; - struct exynos_dp_device *dp; - - dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), - GFP_KERNEL); - if (!dp) - return -ENOMEM; - - dp->display.type = EXYNOS_DISPLAY_TYPE_LCD; - dp->display.ops = &exynos_dp_display_ops; - platform_set_drvdata(pdev, dp); - - panel_node = of_parse_phandle(dev->of_node, "panel", 0); - if (panel_node) { - dp->panel = of_drm_find_panel(panel_node); - of_node_put(panel_node); - if (!dp->panel) - return -EPROBE_DEFER; - } - - endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); - if (endpoint) { - bridge_node = of_graph_get_remote_port_parent(endpoint); - if (bridge_node) { - dp->ptn_bridge = of_drm_find_bridge(bridge_node); - of_node_put(bridge_node); - if (!dp->ptn_bridge) - return -EPROBE_DEFER; - } else { - return -EPROBE_DEFER; - } - } - - return component_add(&pdev->dev, &exynos_dp_ops); + return analogix_dp_bridge_register(drm_dev, dp); } +EXPORT_SYMBOL_GPL(analogix_dp_bind); -static int exynos_dp_remove(struct platform_device *pdev) +void analogix_dp_unbind(struct device *dev, struct device *master, void *data) { - component_del(&pdev->dev, &exynos_dp_ops); + struct analogix_dp_device *dp = dev_get_drvdata(dev); - return 0; + analogix_dp_bridge_disable(dp->bridge); } +EXPORT_SYMBOL_GPL(analogix_dp_unbind); -#ifdef CONFIG_PM_SLEEP -static int exynos_dp_suspend(struct device *dev) +int analogix_dp_suspend(struct device *dev) { - struct exynos_dp_device *dp = dev_get_drvdata(dev); + struct analogix_dp_device *dp = dev_get_drvdata(dev); - exynos_dp_bridge_disable(dp->bridge); + analogix_dp_bridge_disable(dp->bridge); return 0; } +EXPORT_SYMBOL_GPL(analogix_dp_suspend); -static int exynos_dp_resume(struct device *dev) +int analogix_dp_resume(struct device *dev) { - struct exynos_dp_device *dp = dev_get_drvdata(dev); + struct analogix_dp_device *dp = dev_get_drvdata(dev); - exynos_dp_bridge_enable(dp->bridge); + analogix_dp_bridge_enable(dp->bridge); return 0; } -#endif - -static const struct dev_pm_ops exynos_dp_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume) -}; - -static const struct of_device_id exynos_dp_match[] = { - { .compatible = "samsung,exynos5-dp" }, - {}, -}; -MODULE_DEVICE_TABLE(of, exynos_dp_match); - -struct platform_driver dp_driver = { - .probe = exynos_dp_probe, - .remove = exynos_dp_remove, - .driver = { - .name = "exynos-dp", - .owner = THIS_MODULE, - .pm = &exynos_dp_pm_ops, - .of_match_table = exynos_dp_match, - }, -}; +EXPORT_SYMBOL_GPL(analogix_dp_resume); MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>"); -MODULE_DESCRIPTION("Samsung SoC DP Driver"); +MODULE_DESCRIPTION("Analogix Core DP Driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/bridge/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix_dp_core.h new file mode 100644 index 0000000..fe72695 --- /dev/null +++ b/drivers/gpu/drm/bridge/analogix_dp_core.h @@ -0,0 +1,286 @@ +/* + * Header file for Samsung DP (Display Port) interface driver. + * + * Copyright (C) 2012 Samsung Electronics Co., Ltd. + * Author: Jingoo Han <jg1.han@samsung.com> + * Yakir Yang <ykk@rock-chips.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef _ANALOGIX_DP_CORE_H +#define _ANALOGIX_DP_CORE_H + +#include <drm/drm_crtc.h> +#include <drm/drm_dp_helper.h> +#include <drm/exynos_drm.h> + +#define DP_TIMEOUT_LOOP_COUNT 100 +#define MAX_CR_LOOP 5 +#define MAX_EQ_LOOP 5 + +enum link_rate_type { + LINK_RATE_1_62GBPS = 0x06, + LINK_RATE_2_70GBPS = 0x0a +}; + +enum link_lane_count_type { + LANE_COUNT1 = 1, + LANE_COUNT2 = 2, + LANE_COUNT4 = 4 +}; + +enum link_training_state { + START, + CLOCK_RECOVERY, + EQUALIZER_TRAINING, + FINISHED, + FAILED +}; + +enum voltage_swing_level { + VOLTAGE_LEVEL_0, + VOLTAGE_LEVEL_1, + VOLTAGE_LEVEL_2, + VOLTAGE_LEVEL_3, +}; + +enum pre_emphasis_level { + PRE_EMPHASIS_LEVEL_0, + PRE_EMPHASIS_LEVEL_1, + PRE_EMPHASIS_LEVEL_2, + PRE_EMPHASIS_LEVEL_3, +}; + +enum pattern_set { + PRBS7, + D10_2, + TRAINING_PTN1, + TRAINING_PTN2, + DP_NONE +}; + +enum color_space { + COLOR_RGB, + COLOR_YCBCR422, + COLOR_YCBCR444 +}; + +enum color_depth { + COLOR_6, + COLOR_8, + COLOR_10, + COLOR_12 +}; + +enum color_coefficient { + COLOR_YCBCR601, + COLOR_YCBCR709 +}; + +enum dynamic_range { + VESA, + CEA +}; + +enum pll_status { + PLL_UNLOCKED, + PLL_LOCKED +}; + +enum clock_recovery_m_value_type { + CALCULATED_M, + REGISTER_M +}; + +enum video_timing_recognition_type { + VIDEO_TIMING_FROM_CAPTURE, + VIDEO_TIMING_FROM_REGISTER +}; + +enum analog_power_block { + AUX_BLOCK, + CH0_BLOCK, + CH1_BLOCK, + CH2_BLOCK, + CH3_BLOCK, + ANALOG_TOTAL, + POWER_ALL +}; + +enum dp_irq_type { + DP_IRQ_TYPE_HP_CABLE_IN, + DP_IRQ_TYPE_HP_CABLE_OUT, + DP_IRQ_TYPE_HP_CHANGE, + DP_IRQ_TYPE_UNKNOWN, +}; + +struct video_info { + char *name; + + bool h_sync_polarity; + bool v_sync_polarity; + bool interlaced; + + enum color_space color_space; + enum dynamic_range dynamic_range; + enum color_coefficient ycbcr_coeff; + enum color_depth color_depth; + + enum link_rate_type link_rate; + enum link_lane_count_type lane_count; +}; + +struct link_train { + int eq_loop; + int cr_loop[4]; + + u8 link_rate; + u8 lane_count; + u8 training_lane[4]; + + enum link_training_state lt_state; +}; + +struct analogix_dp_device { + struct device *dev; + struct drm_device *drm_dev; + struct drm_connector connector; + struct drm_encoder *encoder; + struct drm_bridge *bridge; + struct clk *clock; + unsigned int irq; + void __iomem *reg_base; + + struct video_info *video_info; + struct link_train link_train; + struct work_struct hotplug_work; + struct phy *phy; + int dpms_mode; + int hpd_gpio; + + struct analogix_dp_plat_data *plat_data; + + struct exynos_drm_panel_info priv; +}; + +/* analogix_dp_reg.c */ +void analogix_dp_enable_video_mute(struct analogix_dp_device *dp, bool enable); +void analogix_dp_stop_video(struct analogix_dp_device *dp); +void analogix_dp_lane_swap(struct analogix_dp_device *dp, bool enable); +void analogix_dp_init_analog_param(struct analogix_dp_device *dp); +void analogix_dp_init_interrupt(struct analogix_dp_device *dp); +void analogix_dp_reset(struct analogix_dp_device *dp); +void analogix_dp_swreset(struct analogix_dp_device *dp); +void analogix_dp_config_interrupt(struct analogix_dp_device *dp); +enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp); +void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable); +void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp, + enum analog_power_block block, + bool enable); +void analogix_dp_init_analog_func(struct analogix_dp_device *dp); +void analogix_dp_init_hpd(struct analogix_dp_device *dp); +enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp); +void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp); +void analogix_dp_reset_aux(struct analogix_dp_device *dp); +void analogix_dp_init_aux(struct analogix_dp_device *dp); +int analogix_dp_get_plug_in_status(struct analogix_dp_device *dp); +void analogix_dp_enable_sw_function(struct analogix_dp_device *dp); +int analogix_dp_start_aux_transaction(struct analogix_dp_device *dp); +int analogix_dp_write_byte_to_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned char data); +int analogix_dp_read_byte_from_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned char *data); +int analogix_dp_write_bytes_to_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]); +int analogix_dp_read_bytes_from_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]); +int analogix_dp_select_i2c_device(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int reg_addr); +int analogix_dp_read_byte_from_i2c(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int reg_addr, + unsigned int *data); +int analogix_dp_read_bytes_from_i2c(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int reg_addr, + unsigned int count, + unsigned char edid[]); +void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype); +void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype); +void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count); +void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count); +void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp, + bool enable); +void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, + enum pattern_set pattern); +void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp, + u32 level); +void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp, + u32 level); +void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp, + u32 level); +void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp, + u32 level); +void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp, + u32 training_lane); +void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp, + u32 training_lane); +void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp, + u32 training_lane); +void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp, + u32 training_lane); +u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp); +u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp); +u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp); +u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp); +void analogix_dp_reset_macro(struct analogix_dp_device *dp); +void analogix_dp_init_video(struct analogix_dp_device *dp); + +void analogix_dp_set_video_color_format(struct analogix_dp_device *dp); +int analogix_dp_is_slave_video_stream_clock_on(struct analogix_dp_device *dp); +void analogix_dp_set_video_cr_mn(struct analogix_dp_device *dp, + enum clock_recovery_m_value_type type, + u32 m_value, u32 n_value); +void analogix_dp_set_video_timing_mode(struct analogix_dp_device *dp, u32 type); +void analogix_dp_enable_video_master(struct analogix_dp_device *dp, + bool enable); +void analogix_dp_start_video(struct analogix_dp_device *dp); +int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp); +void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp); +void analogix_dp_enable_scrambling(struct analogix_dp_device *dp); +void analogix_dp_disable_scrambling(struct analogix_dp_device *dp); + +/* 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 + +/* DP_MAX_LANE_COUNT */ +#define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1) +#define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f) + +/* DP_LANE_COUNT_SET */ +#define DPCD_LANE_COUNT_SET(x) ((x) & 0x1f) + +/* DP_TRAINING_LANE0_SET */ +#define DPCD_PRE_EMPHASIS_SET(x) (((x) & 0x3) << 3) +#define DPCD_PRE_EMPHASIS_GET(x) (((x) >> 3) & 0x3) +#define DPCD_VOLTAGE_SWING_SET(x) (((x) & 0x3) << 0) +#define DPCD_VOLTAGE_SWING_GET(x) (((x) >> 0) & 0x3) + +#endif /* _ANALOGIX_DP_CORE_H */ diff --git a/drivers/gpu/drm/bridge/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix_dp_reg.c new file mode 100644 index 0000000..dfbbde7 --- /dev/null +++ b/drivers/gpu/drm/bridge/analogix_dp_reg.c @@ -0,0 +1,1266 @@ +/* + * Samsung DP (Display port) register interface driver. + * + * Copyright (C) 2012 Samsung Electronics Co., Ltd. + * Author: Jingoo Han <jg1.han@samsung.com> + * Yakir Yang <ykk@rock-chips.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/device.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/gpio.h> + +#include "analogix_dp_core.h" +#include "analogix_dp_reg.h" + +#define COMMON_INT_MASK_1 0 +#define COMMON_INT_MASK_2 0 +#define COMMON_INT_MASK_3 0 +#define COMMON_INT_MASK_4 (HOTPLUG_CHG | HPD_LOST | PLUG) +#define INT_STA_MASK INT_HPD + +void analogix_dp_enable_video_mute(struct analogix_dp_device *dp, bool enable) +{ + u32 reg; + + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); + reg |= HDCP_VIDEO_MUTE; + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); + reg &= ~HDCP_VIDEO_MUTE; + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); + } +} + +void analogix_dp_stop_video(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); + reg &= ~VIDEO_EN; + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); +} + +void analogix_dp_lane_swap(struct analogix_dp_device *dp, bool enable) +{ + u32 reg; + + if (enable) + reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 | + LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3; + else + reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 | + LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0; + + writel(reg, dp->reg_base + ANALOGIX_DP_LANE_MAP); +} + +void analogix_dp_init_analog_param(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = TX_TERMINAL_CTRL_50_OHM; + writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_1); + + reg = SEL_24M | TX_DVDD_BIT_1_0625V; + writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_2); + + reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO; + writel(reg, dp->reg_base + ANALOGIX_DP_ANALOG_CTL_3); + + reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM | + TX_CUR1_2X | TX_CUR_16_MA; + writel(reg, dp->reg_base + ANALOGIX_DP_PLL_FILTER_CTL_1); + + reg = CH3_AMP_400_MV | CH2_AMP_400_MV | + CH1_AMP_400_MV | CH0_AMP_400_MV; + writel(reg, dp->reg_base + ANALOGIX_DP_TX_AMP_TUNING_CTL); +} + +void analogix_dp_init_interrupt(struct analogix_dp_device *dp) +{ + /* Set interrupt pin assertion polarity as high */ + writel(INT_POL1 | INT_POL0, dp->reg_base + ANALOGIX_DP_INT_CTL); + + /* Clear pending regisers */ + writel(0xff, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1); + writel(0x4f, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_2); + writel(0xe0, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_3); + writel(0xe7, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4); + writel(0x63, dp->reg_base + ANALOGIX_DP_INT_STA); + + /* 0:mask,1: unmask */ + writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_1); + writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2); + writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3); + writel(0x00, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4); + writel(0x00, dp->reg_base + ANALOGIX_DP_INT_STA_MASK); +} + +void analogix_dp_reset(struct analogix_dp_device *dp) +{ + u32 reg; + + analogix_dp_stop_video(dp); + analogix_dp_enable_video_mute(dp, 0); + + reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N | + AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N | + HDCP_FUNC_EN_N | SW_FUNC_EN_N; + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1); + + reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N | + SERDES_FIFO_FUNC_EN_N | + LS_CLK_DOMAIN_FUNC_EN_N; + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); + + usleep_range(20, 30); + + analogix_dp_lane_swap(dp, 0); + + writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_1); + writel(0x40, dp->reg_base + ANALOGIX_DP_SYS_CTL_2); + writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); + writel(0x0, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + + writel(0x0, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); + writel(0x0, dp->reg_base + ANALOGIX_DP_HDCP_CTL); + + writel(0x5e, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_L); + writel(0x1a, dp->reg_base + ANALOGIX_DP_HPD_DEGLITCH_H); + + writel(0x10, dp->reg_base + ANALOGIX_DP_LINK_DEBUG_CTL); + + writel(0x0, dp->reg_base + ANALOGIX_DP_PHY_TEST); + + writel(0x0, dp->reg_base + ANALOGIX_DP_VIDEO_FIFO_THRD); + writel(0x20, dp->reg_base + ANALOGIX_DP_AUDIO_MARGIN); + + writel(0x4, dp->reg_base + ANALOGIX_DP_M_VID_GEN_FILTER_TH); + writel(0x2, dp->reg_base + ANALOGIX_DP_M_AUD_GEN_FILTER_TH); + + writel(0x00000101, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); +} + +void analogix_dp_swreset(struct analogix_dp_device *dp) +{ + writel(RESET_DP_TX, dp->reg_base + ANALOGIX_DP_TX_SW_RESET); +} + +void analogix_dp_config_interrupt(struct analogix_dp_device *dp) +{ + u32 reg; + + /* 0: mask, 1: unmask */ + reg = COMMON_INT_MASK_1; + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_1); + + reg = COMMON_INT_MASK_2; + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_2); + + reg = COMMON_INT_MASK_3; + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_3); + + reg = COMMON_INT_MASK_4; + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_MASK_4); + + reg = INT_STA_MASK; + writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA_MASK); +} + +enum pll_status analogix_dp_get_pll_lock_status(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_DEBUG_CTL); + if (reg & PLL_LOCK) + return PLL_LOCKED; + else + return PLL_UNLOCKED; +} + +void analogix_dp_set_pll_power_down(struct analogix_dp_device *dp, bool enable) +{ + u32 reg; + + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_PLL_CTL); + reg |= DP_PLL_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PLL_CTL); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_PLL_CTL); + reg &= ~DP_PLL_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PLL_CTL); + } +} + +void analogix_dp_set_analog_power_down(struct analogix_dp_device *dp, + enum analog_power_block block, + bool enable) +{ + u32 reg; + + switch (block) { + case AUX_BLOCK: + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg |= AUX_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg &= ~AUX_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } + break; + case CH0_BLOCK: + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg |= CH0_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg &= ~CH0_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } + break; + case CH1_BLOCK: + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg |= CH1_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg &= ~CH1_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } + break; + case CH2_BLOCK: + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg |= CH2_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg &= ~CH2_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } + break; + case CH3_BLOCK: + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg |= CH3_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg &= ~CH3_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } + break; + case ANALOG_TOTAL: + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg |= DP_PHY_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_PD); + reg &= ~DP_PHY_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } + break; + case POWER_ALL: + if (enable) { + reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD | + CH1_PD | CH0_PD; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_PD); + } else { + writel(0x00, dp->reg_base + ANALOGIX_DP_PHY_PD); + } + break; + default: + break; + } +} + +void analogix_dp_init_analog_func(struct analogix_dp_device *dp) +{ + u32 reg; + int timeout_loop = 0; + + analogix_dp_set_analog_power_down(dp, POWER_ALL, 0); + + reg = PLL_LOCK_CHG; + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1); + + reg = readl(dp->reg_base + ANALOGIX_DP_DEBUG_CTL); + reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL); + writel(reg, dp->reg_base + ANALOGIX_DP_DEBUG_CTL); + + /* Power up PLL */ + if (analogix_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) { + analogix_dp_set_pll_power_down(dp, 0); + + while (analogix_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"); + return; + } + usleep_range(10, 20); + } + } + + /* Enable Serdes FIFO function and Link symbol clock domain module */ + reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2); + reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N + | AUX_FUNC_EN_N); + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); +} + +void analogix_dp_clear_hotplug_interrupts(struct analogix_dp_device *dp) +{ + u32 reg; + + if (gpio_is_valid(dp->hpd_gpio)) + return; + + reg = HOTPLUG_CHG | HPD_LOST | PLUG; + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4); + + reg = INT_HPD; + writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA); +} + +void analogix_dp_init_hpd(struct analogix_dp_device *dp) +{ + u32 reg; + + if (gpio_is_valid(dp->hpd_gpio)) + return; + + analogix_dp_clear_hotplug_interrupts(dp); + + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3); + reg &= ~(F_HPD | HPD_CTRL); + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); +} + +enum dp_irq_type analogix_dp_get_irq_type(struct analogix_dp_device *dp) +{ + u32 reg; + + if (gpio_is_valid(dp->hpd_gpio)) { + reg = gpio_get_value(dp->hpd_gpio); + if (reg) + return DP_IRQ_TYPE_HP_CABLE_IN; + else + return DP_IRQ_TYPE_HP_CABLE_OUT; + } else { + /* Parse hotplug interrupt status register */ + reg = readl(dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_4); + + if (reg & PLUG) + return DP_IRQ_TYPE_HP_CABLE_IN; + + if (reg & HPD_LOST) + return DP_IRQ_TYPE_HP_CABLE_OUT; + + if (reg & HOTPLUG_CHG) + return DP_IRQ_TYPE_HP_CHANGE; + + return DP_IRQ_TYPE_UNKNOWN; + } +} + +void analogix_dp_reset_aux(struct analogix_dp_device *dp) +{ + u32 reg; + + /* Disable AUX channel module */ + reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2); + reg |= AUX_FUNC_EN_N; + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); +} + +void analogix_dp_init_aux(struct analogix_dp_device *dp) +{ + u32 reg; + + /* Clear inerrupts related to AUX channel */ + reg = RPLY_RECEIV | AUX_ERR; + writel(reg, dp->reg_base + ANALOGIX_DP_INT_STA); + + analogix_dp_reset_aux(dp); + + /* Disable AUX transaction H/W retry */ + reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0) | + AUX_HW_RETRY_INTERVAL_600_MICROSECONDS; + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_HW_RETRY_CTL); + + /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */ + reg = DEFER_CTRL_EN | DEFER_COUNT(1); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_DEFER_CTL); + + /* Enable AUX channel module */ + reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_2); + reg &= ~AUX_FUNC_EN_N; + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_2); +} + +int analogix_dp_get_plug_in_status(struct analogix_dp_device *dp) +{ + u32 reg; + + if (gpio_is_valid(dp->hpd_gpio)) { + if (gpio_get_value(dp->hpd_gpio)) + return 0; + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3); + if (reg & HPD_STATUS) + return 0; + } + + return -EINVAL; +} + +void analogix_dp_enable_sw_function(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_1); + reg &= ~SW_FUNC_EN_N; + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1); +} + +int analogix_dp_start_aux_transaction(struct analogix_dp_device *dp) +{ + int reg; + int retval = 0; + int timeout_loop = 0; + + /* Enable AUX CH operation */ + reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2); + reg |= AUX_EN; + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2); + + /* Is AUX CH command reply received? */ + reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA); + while (!(reg & RPLY_RECEIV)) { + timeout_loop++; + if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) { + dev_err(dp->dev, "AUX CH command reply failed!\n"); + return -ETIMEDOUT; + } + reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA); + usleep_range(10, 11); + } + + /* Clear interrupt source for AUX CH command reply */ + writel(RPLY_RECEIV, dp->reg_base + ANALOGIX_DP_INT_STA); + + /* Clear interrupt source for AUX CH access error */ + reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA); + if (reg & AUX_ERR) { + writel(AUX_ERR, dp->reg_base + ANALOGIX_DP_INT_STA); + return -EREMOTEIO; + } + + /* Check AUX CH error access status */ + reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_STA); + if ((reg & AUX_STATUS_MASK) != 0) { + dev_err(dp->dev, "AUX CH error happens: %d\n\n", + reg & AUX_STATUS_MASK); + return -EREMOTEIO; + } + + return retval; +} + +int analogix_dp_write_byte_to_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned char data) +{ + u32 reg; + int i; + int retval; + + for (i = 0; i < 3; i++) { + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); + + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); + reg = AUX_ADDR_15_8(reg_addr); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); + reg = AUX_ADDR_19_16(reg_addr); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16); + + /* Write data buffer */ + reg = (unsigned int)data; + writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0); + + /* + * 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->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); + } + + return retval; +} + +int analogix_dp_read_byte_from_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned char *data) +{ + u32 reg; + int i; + int retval; + + for (i = 0; i < 3; i++) { + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); + + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); + reg = AUX_ADDR_15_8(reg_addr); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); + reg = AUX_ADDR_19_16(reg_addr); + writel(reg, dp->reg_base + ANALOGIX_DP_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; + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); + } + + /* Read data buffer */ + reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0); + *data = (unsigned char)(reg & 0xff); + + return retval; +} + +int analogix_dp_write_bytes_to_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]) +{ + u32 reg; + unsigned int start_offset; + unsigned int cur_data_count; + unsigned int cur_data_idx; + int i; + int retval = 0; + + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + ANALOGIX_DP_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; + + for (i = 0; i < 3; i++) { + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr + start_offset); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); + reg = AUX_ADDR_15_8(reg_addr + start_offset); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); + reg = AUX_ADDR_19_16(reg_addr + start_offset); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16); + + for (cur_data_idx = 0; cur_data_idx < cur_data_count; + cur_data_idx++) { + reg = data[start_offset + cur_data_idx]; + writel(reg, dp->reg_base + + ANALOGIX_DP_BUF_DATA_0 + + 4 * cur_data_idx); + } + + /* + * Set DisplayPort transaction and write + * 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_WRITE; + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", + __func__); + } + + start_offset += cur_data_count; + } + + return retval; +} + +int analogix_dp_read_bytes_from_dpcd(struct analogix_dp_device *dp, + unsigned int reg_addr, + unsigned int count, + unsigned char data[]) +{ + u32 reg; + unsigned int start_offset; + unsigned int cur_data_count; + unsigned int cur_data_idx; + int i; + int retval = 0; + + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + ANALOGIX_DP_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; + + /* AUX CH Request Transaction process */ + for (i = 0; i < 3; i++) { + /* Select DPCD device address */ + reg = AUX_ADDR_7_0(reg_addr + start_offset); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); + reg = AUX_ADDR_15_8(reg_addr + start_offset); + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); + reg = AUX_ADDR_19_16(reg_addr + start_offset); + writel(reg, dp->reg_base + ANALOGIX_DP_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; + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", + __func__); + } + + for (cur_data_idx = 0; cur_data_idx < cur_data_count; + cur_data_idx++) { + reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 + + 4 * cur_data_idx); + data[start_offset + cur_data_idx] = + (unsigned char)reg; + } + + start_offset += cur_data_count; + } + + return retval; +} + +int analogix_dp_select_i2c_device(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int reg_addr) +{ + u32 reg; + int retval; + + /* Set EDID device address */ + reg = device_addr; + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0); + writel(0x0, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8); + writel(0x0, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16); + + /* Set offset from base address of EDID device */ + writel(reg_addr, dp->reg_base + ANALOGIX_DP_BUF_DATA_0); + + /* + * 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; + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval != 0) + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); + + return retval; +} + +int analogix_dp_read_byte_from_i2c(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int reg_addr, + unsigned int *data) +{ + u32 reg; + int i; + int retval; + + for (i = 0; i < 3; i++) { + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); + + /* Select EDID device */ + retval = analogix_dp_select_i2c_device(dp, device_addr, + reg_addr); + if (retval != 0) + 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; + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__); + } + + /* Read data */ + if (retval == 0) + *data = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0); + + return retval; +} + +int analogix_dp_read_bytes_from_i2c(struct analogix_dp_device *dp, + unsigned int device_addr, + unsigned int 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) { + for (j = 0; j < 3; j++) { + /* Clear AUX CH data buffer */ + reg = BUF_CLR; + writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL); + + /* Set normal AUX CH command */ + reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2); + reg &= ~ADDR_ONLY; + writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2); + + /* + * If Rx sends defer, Tx sends only reads + * request without sending address + */ + if (!defer) + retval = analogix_dp_select_i2c_device( + dp, device_addr, reg_addr + i); + else + defer = 0; + + if (retval == 0) { + /* + * 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; + writel(reg, dp->reg_base + + ANALOGIX_DP_AUX_CH_CTL_1); + + /* Start AUX transaction */ + retval = analogix_dp_start_aux_transaction(dp); + if (retval == 0) + break; + + dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", + __func__); + } + /* Check if Rx sends defer */ + reg = readl(dp->reg_base + ANALOGIX_DP_AUX_RX_COMM); + if (reg == AUX_RX_COMM_AUX_DEFER || + reg == AUX_RX_COMM_I2C_DEFER) { + dev_err(dp->dev, "Defer: %d\n\n", reg); + defer = 1; + } + } + + for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) { + reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 + + 4 * cur_data_idx); + edid[i + cur_data_idx] = (unsigned char)reg; + } + } + + return retval; +} + +void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype) +{ + u32 reg; + + reg = bwtype; + if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype == LINK_RATE_1_62GBPS)) + writel(reg, dp->reg_base + ANALOGIX_DP_LINK_BW_SET); +} + +void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LINK_BW_SET); + *bwtype = reg; +} + +void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count) +{ + u32 reg; + + reg = count; + writel(reg, dp->reg_base + ANALOGIX_DP_LANE_COUNT_SET); +} + +void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LANE_COUNT_SET); + *count = reg; +} + +void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp, + bool enable) +{ + u32 reg; + + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + reg |= ENHANCED; + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + reg &= ~ENHANCED; + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + } +} + +void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, + enum pattern_set pattern) +{ + u32 reg; + + switch (pattern) { + case PRBS7: + reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7; + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); + break; + case D10_2: + reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2; + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); + break; + case TRAINING_PTN1: + reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1; + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); + break; + case TRAINING_PTN2: + reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2; + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); + break; + case DP_NONE: + reg = SCRAMBLING_ENABLE | + LINK_QUAL_PATTERN_SET_DISABLE | + SW_TRAINING_PATTERN_SET_NORMAL; + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); + break; + default: + break; + } +} + +void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp, + u32 level) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); + reg &= ~PRE_EMPHASIS_SET_MASK; + reg |= level << PRE_EMPHASIS_SET_SHIFT; + writel(reg, dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp, + u32 level) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); + reg &= ~PRE_EMPHASIS_SET_MASK; + reg |= level << PRE_EMPHASIS_SET_SHIFT; + writel(reg, dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp, + u32 level) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); + reg &= ~PRE_EMPHASIS_SET_MASK; + reg |= level << PRE_EMPHASIS_SET_SHIFT; + writel(reg, dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp, + u32 level) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); + reg &= ~PRE_EMPHASIS_SET_MASK; + reg |= level << PRE_EMPHASIS_SET_SHIFT; + writel(reg, dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp, + u32 training_lane) +{ + u32 reg; + + reg = training_lane; + writel(reg, dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp, + u32 training_lane) +{ + u32 reg; + + reg = training_lane; + writel(reg, dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp, + u32 training_lane) +{ + u32 reg; + + reg = training_lane; + writel(reg, dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); +} + +void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp, + u32 training_lane) +{ + u32 reg; + + reg = training_lane; + writel(reg, dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); +} + +u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); + return reg; +} + +u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); + return reg; +} + +u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); + return reg; +} + +u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); + return reg; +} + +void analogix_dp_reset_macro(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_PHY_TEST); + reg |= MACRO_RST; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_TEST); + + /* 10 us is the minimum reset time. */ + usleep_range(10, 20); + + reg &= ~MACRO_RST; + writel(reg, dp->reg_base + ANALOGIX_DP_PHY_TEST); +} + +void analogix_dp_init_video(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG; + writel(reg, dp->reg_base + ANALOGIX_DP_COMMON_INT_STA_1); + + reg = 0x0; + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_1); + + reg = CHA_CRI(4) | CHA_CTRL; + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_2); + + reg = 0x0; + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); + + reg = VID_HRES_TH(2) | VID_VRES_TH(0); + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_8); +} + +void analogix_dp_set_video_color_format(struct analogix_dp_device *dp) +{ + u32 reg; + + /* Configure the input color depth, color space, dynamic range */ + reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) | + (dp->video_info->color_depth << IN_BPC_SHIFT) | + (dp->video_info->color_space << IN_COLOR_F_SHIFT); + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_2); + + /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */ + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3); + reg &= ~IN_YC_COEFFI_MASK; + if (dp->video_info->ycbcr_coeff) + reg |= IN_YC_COEFFI_ITU709; + else + reg |= IN_YC_COEFFI_ITU601; + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3); +} + +int analogix_dp_is_slave_video_stream_clock_on(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_1); + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_1); + + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_1); + + if (!(reg & DET_STA)) { + dev_dbg(dp->dev, "Input stream clock not detected.\n"); + return -EINVAL; + } + + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_2); + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_2); + + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_2); + dev_dbg(dp->dev, "wait SYS_CTL_2.\n"); + + if (reg & CHA_STA) { + dev_dbg(dp->dev, "Input stream clk is changing\n"); + return -EINVAL; + } + + return 0; +} + +void analogix_dp_set_video_cr_mn(struct analogix_dp_device *dp, + enum clock_recovery_m_value_type type, + u32 m_value, u32 n_value) +{ + u32 reg; + + if (type == REGISTER_M) { + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + reg |= FIX_M_VID; + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + reg = m_value & 0xff; + writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_0); + reg = (m_value >> 8) & 0xff; + writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_1); + reg = (m_value >> 16) & 0xff; + writel(reg, dp->reg_base + ANALOGIX_DP_M_VID_2); + + reg = n_value & 0xff; + writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_0); + reg = (n_value >> 8) & 0xff; + writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_1); + reg = (n_value >> 16) & 0xff; + writel(reg, dp->reg_base + ANALOGIX_DP_N_VID_2); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + reg &= ~FIX_M_VID; + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_4); + + writel(0x00, dp->reg_base + ANALOGIX_DP_N_VID_0); + writel(0x80, dp->reg_base + ANALOGIX_DP_N_VID_1); + writel(0x00, dp->reg_base + ANALOGIX_DP_N_VID_2); + } +} + +void analogix_dp_set_video_timing_mode(struct analogix_dp_device *dp, u32 type) +{ + u32 reg; + + if (type == VIDEO_TIMING_FROM_CAPTURE) { + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + reg &= ~FORMAT_SEL; + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + reg |= FORMAT_SEL; + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + } +} + +void analogix_dp_enable_video_master(struct analogix_dp_device *dp, bool enable) +{ + u32 reg; + + if (enable) { + reg = readl(dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); + reg &= ~VIDEO_MODE_MASK; + reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE; + writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); + } else { + reg = readl(dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); + reg &= ~VIDEO_MODE_MASK; + reg |= VIDEO_MODE_SLAVE_MODE; + writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); + } +} + +void analogix_dp_start_video(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); + reg |= VIDEO_EN; + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_1); +} + +int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3); + writel(reg, dp->reg_base + ANALOGIX_DP_SYS_CTL_3); + + reg = readl(dp->reg_base + ANALOGIX_DP_SYS_CTL_3); + if (!(reg & STRM_VALID)) { + dev_dbg(dp->dev, "Input video stream is not detected.\n"); + return -EINVAL; + } + + return 0; +} + +void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_FUNC_EN_1); + reg &= ~(MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N); + reg |= MASTER_VID_FUNC_EN_N; + writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1); + + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + reg &= ~INTERACE_SCAN_CFG; + reg |= (dp->video_info->interlaced << 2); + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + reg &= ~VSYNC_POLARITY_CFG; + reg |= (dp->video_info->v_sync_polarity << 1); + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + + reg = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + reg &= ~HSYNC_POLARITY_CFG; + reg |= (dp->video_info->h_sync_polarity << 0); + writel(reg, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_10); + + reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE; + writel(reg, dp->reg_base + ANALOGIX_DP_SOC_GENERAL_CTL); +} + +void analogix_dp_enable_scrambling(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); + reg &= ~SCRAMBLING_DISABLE; + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); +} + +void analogix_dp_disable_scrambling(struct analogix_dp_device *dp) +{ + u32 reg; + + reg = readl(dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); + reg |= SCRAMBLING_DISABLE; + writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); +} diff --git a/drivers/gpu/drm/exynos/exynos_dp_reg.h b/drivers/gpu/drm/bridge/analogix_dp_reg.h similarity index 63% rename from drivers/gpu/drm/exynos/exynos_dp_reg.h rename to drivers/gpu/drm/bridge/analogix_dp_reg.h index 2e9bd0e..98153e2 100644 --- a/drivers/gpu/drm/exynos/exynos_dp_reg.h +++ b/drivers/gpu/drm/bridge/analogix_dp_reg.h @@ -1,104 +1,106 @@ /* - * Register definition file for Samsung DP driver + * Register definition file for Analogix Core DP driver * * Copyright (C) 2012 Samsung Electronics Co., Ltd. + * Copyright (C) FuZhou Rockchip Electronics Co., Ltd. * Author: Jingoo Han <jg1.han@samsung.com> + * Yakir Yang <ykk@rock-chips.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ -#ifndef _EXYNOS_DP_REG_H -#define _EXYNOS_DP_REG_H - -#define EXYNOS_DP_TX_SW_RESET 0x14 -#define EXYNOS_DP_FUNC_EN_1 0x18 -#define EXYNOS_DP_FUNC_EN_2 0x1C -#define EXYNOS_DP_VIDEO_CTL_1 0x20 -#define EXYNOS_DP_VIDEO_CTL_2 0x24 -#define EXYNOS_DP_VIDEO_CTL_3 0x28 - -#define EXYNOS_DP_VIDEO_CTL_8 0x3C -#define EXYNOS_DP_VIDEO_CTL_10 0x44 - -#define EXYNOS_DP_LANE_MAP 0x35C - -#define EXYNOS_DP_ANALOG_CTL_1 0x370 -#define EXYNOS_DP_ANALOG_CTL_2 0x374 -#define EXYNOS_DP_ANALOG_CTL_3 0x378 -#define EXYNOS_DP_PLL_FILTER_CTL_1 0x37C -#define EXYNOS_DP_TX_AMP_TUNING_CTL 0x380 - -#define EXYNOS_DP_AUX_HW_RETRY_CTL 0x390 - -#define EXYNOS_DP_COMMON_INT_STA_1 0x3C4 -#define EXYNOS_DP_COMMON_INT_STA_2 0x3C8 -#define EXYNOS_DP_COMMON_INT_STA_3 0x3CC -#define EXYNOS_DP_COMMON_INT_STA_4 0x3D0 -#define EXYNOS_DP_INT_STA 0x3DC -#define EXYNOS_DP_COMMON_INT_MASK_1 0x3E0 -#define EXYNOS_DP_COMMON_INT_MASK_2 0x3E4 -#define EXYNOS_DP_COMMON_INT_MASK_3 0x3E8 -#define EXYNOS_DP_COMMON_INT_MASK_4 0x3EC -#define EXYNOS_DP_INT_STA_MASK 0x3F8 -#define EXYNOS_DP_INT_CTL 0x3FC - -#define EXYNOS_DP_SYS_CTL_1 0x600 -#define EXYNOS_DP_SYS_CTL_2 0x604 -#define EXYNOS_DP_SYS_CTL_3 0x608 -#define EXYNOS_DP_SYS_CTL_4 0x60C - -#define EXYNOS_DP_PKT_SEND_CTL 0x640 -#define EXYNOS_DP_HDCP_CTL 0x648 - -#define EXYNOS_DP_LINK_BW_SET 0x680 -#define EXYNOS_DP_LANE_COUNT_SET 0x684 -#define EXYNOS_DP_TRAINING_PTN_SET 0x688 -#define EXYNOS_DP_LN0_LINK_TRAINING_CTL 0x68C -#define EXYNOS_DP_LN1_LINK_TRAINING_CTL 0x690 -#define EXYNOS_DP_LN2_LINK_TRAINING_CTL 0x694 -#define EXYNOS_DP_LN3_LINK_TRAINING_CTL 0x698 - -#define EXYNOS_DP_DEBUG_CTL 0x6C0 -#define EXYNOS_DP_HPD_DEGLITCH_L 0x6C4 -#define EXYNOS_DP_HPD_DEGLITCH_H 0x6C8 -#define EXYNOS_DP_LINK_DEBUG_CTL 0x6E0 - -#define EXYNOS_DP_M_VID_0 0x700 -#define EXYNOS_DP_M_VID_1 0x704 -#define EXYNOS_DP_M_VID_2 0x708 -#define EXYNOS_DP_N_VID_0 0x70C -#define EXYNOS_DP_N_VID_1 0x710 -#define EXYNOS_DP_N_VID_2 0x714 - -#define EXYNOS_DP_PLL_CTL 0x71C -#define EXYNOS_DP_PHY_PD 0x720 -#define EXYNOS_DP_PHY_TEST 0x724 - -#define EXYNOS_DP_VIDEO_FIFO_THRD 0x730 -#define EXYNOS_DP_AUDIO_MARGIN 0x73C - -#define EXYNOS_DP_M_VID_GEN_FILTER_TH 0x764 -#define EXYNOS_DP_M_AUD_GEN_FILTER_TH 0x778 -#define EXYNOS_DP_AUX_CH_STA 0x780 -#define EXYNOS_DP_AUX_CH_DEFER_CTL 0x788 -#define EXYNOS_DP_AUX_RX_COMM 0x78C -#define EXYNOS_DP_BUFFER_DATA_CTL 0x790 -#define EXYNOS_DP_AUX_CH_CTL_1 0x794 -#define EXYNOS_DP_AUX_ADDR_7_0 0x798 -#define EXYNOS_DP_AUX_ADDR_15_8 0x79C -#define EXYNOS_DP_AUX_ADDR_19_16 0x7A0 -#define EXYNOS_DP_AUX_CH_CTL_2 0x7A4 - -#define EXYNOS_DP_BUF_DATA_0 0x7C0 - -#define EXYNOS_DP_SOC_GENERAL_CTL 0x800 - -/* EXYNOS_DP_TX_SW_RESET */ +#ifndef _ANALOGIX_DP_REG_H +#define _ANALOGIX_DP_REG_H + +#define ANALOGIX_DP_TX_SW_RESET 0x14 +#define ANALOGIX_DP_FUNC_EN_1 0x18 +#define ANALOGIX_DP_FUNC_EN_2 0x1C +#define ANALOGIX_DP_VIDEO_CTL_1 0x20 +#define ANALOGIX_DP_VIDEO_CTL_2 0x24 +#define ANALOGIX_DP_VIDEO_CTL_3 0x28 + +#define ANALOGIX_DP_VIDEO_CTL_8 0x3C +#define ANALOGIX_DP_VIDEO_CTL_10 0x44 + +#define ANALOGIX_DP_LANE_MAP 0x35C + +#define ANALOGIX_DP_ANALOG_CTL_1 0x370 +#define ANALOGIX_DP_ANALOG_CTL_2 0x374 +#define ANALOGIX_DP_ANALOG_CTL_3 0x378 +#define ANALOGIX_DP_PLL_FILTER_CTL_1 0x37C +#define ANALOGIX_DP_TX_AMP_TUNING_CTL 0x380 + +#define ANALOGIX_DP_AUX_HW_RETRY_CTL 0x390 + +#define ANALOGIX_DP_COMMON_INT_STA_1 0x3C4 +#define ANALOGIX_DP_COMMON_INT_STA_2 0x3C8 +#define ANALOGIX_DP_COMMON_INT_STA_3 0x3CC +#define ANALOGIX_DP_COMMON_INT_STA_4 0x3D0 +#define ANALOGIX_DP_INT_STA 0x3DC +#define ANALOGIX_DP_COMMON_INT_MASK_1 0x3E0 +#define ANALOGIX_DP_COMMON_INT_MASK_2 0x3E4 +#define ANALOGIX_DP_COMMON_INT_MASK_3 0x3E8 +#define ANALOGIX_DP_COMMON_INT_MASK_4 0x3EC +#define ANALOGIX_DP_INT_STA_MASK 0x3F8 +#define ANALOGIX_DP_INT_CTL 0x3FC + +#define ANALOGIX_DP_SYS_CTL_1 0x600 +#define ANALOGIX_DP_SYS_CTL_2 0x604 +#define ANALOGIX_DP_SYS_CTL_3 0x608 +#define ANALOGIX_DP_SYS_CTL_4 0x60C + +#define ANALOGIX_DP_PKT_SEND_CTL 0x640 +#define ANALOGIX_DP_HDCP_CTL 0x648 + +#define ANALOGIX_DP_LINK_BW_SET 0x680 +#define ANALOGIX_DP_LANE_COUNT_SET 0x684 +#define ANALOGIX_DP_TRAINING_PTN_SET 0x688 +#define ANALOGIX_DP_LN0_LINK_TRAINING_CTL 0x68C +#define ANALOGIX_DP_LN1_LINK_TRAINING_CTL 0x690 +#define ANALOGIX_DP_LN2_LINK_TRAINING_CTL 0x694 +#define ANALOGIX_DP_LN3_LINK_TRAINING_CTL 0x698 + +#define ANALOGIX_DP_DEBUG_CTL 0x6C0 +#define ANALOGIX_DP_HPD_DEGLITCH_L 0x6C4 +#define ANALOGIX_DP_HPD_DEGLITCH_H 0x6C8 +#define ANALOGIX_DP_LINK_DEBUG_CTL 0x6E0 + +#define ANALOGIX_DP_M_VID_0 0x700 +#define ANALOGIX_DP_M_VID_1 0x704 +#define ANALOGIX_DP_M_VID_2 0x708 +#define ANALOGIX_DP_N_VID_0 0x70C +#define ANALOGIX_DP_N_VID_1 0x710 +#define ANALOGIX_DP_N_VID_2 0x714 + +#define ANALOGIX_DP_PLL_CTL 0x71C +#define ANALOGIX_DP_PHY_PD 0x720 +#define ANALOGIX_DP_PHY_TEST 0x724 + +#define ANALOGIX_DP_VIDEO_FIFO_THRD 0x730 +#define ANALOGIX_DP_AUDIO_MARGIN 0x73C + +#define ANALOGIX_DP_M_VID_GEN_FILTER_TH 0x764 +#define ANALOGIX_DP_M_AUD_GEN_FILTER_TH 0x778 +#define ANALOGIX_DP_AUX_CH_STA 0x780 +#define ANALOGIX_DP_AUX_CH_DEFER_CTL 0x788 +#define ANALOGIX_DP_AUX_RX_COMM 0x78C +#define ANALOGIX_DP_BUFFER_DATA_CTL 0x790 +#define ANALOGIX_DP_AUX_CH_CTL_1 0x794 +#define ANALOGIX_DP_AUX_ADDR_7_0 0x798 +#define ANALOGIX_DP_AUX_ADDR_15_8 0x79C +#define ANALOGIX_DP_AUX_ADDR_19_16 0x7A0 +#define ANALOGIX_DP_AUX_CH_CTL_2 0x7A4 + +#define ANALOGIX_DP_BUF_DATA_0 0x7C0 + +#define ANALOGIX_DP_SOC_GENERAL_CTL 0x800 + +/* ANALOGIX_DP_TX_SW_RESET */ #define RESET_DP_TX (0x1 << 0) -/* EXYNOS_DP_FUNC_EN_1 */ +/* ANALOGIX_DP_FUNC_EN_1 */ #define MASTER_VID_FUNC_EN_N (0x1 << 7) #define SLAVE_VID_FUNC_EN_N (0x1 << 5) #define AUD_FIFO_FUNC_EN_N (0x1 << 4) @@ -107,17 +109,17 @@ #define CRC_FUNC_EN_N (0x1 << 1) #define SW_FUNC_EN_N (0x1 << 0) -/* EXYNOS_DP_FUNC_EN_2 */ +/* ANALOGIX_DP_FUNC_EN_2 */ #define SSC_FUNC_EN_N (0x1 << 7) #define AUX_FUNC_EN_N (0x1 << 2) #define SERDES_FIFO_FUNC_EN_N (0x1 << 1) #define LS_CLK_DOMAIN_FUNC_EN_N (0x1 << 0) -/* EXYNOS_DP_VIDEO_CTL_1 */ +/* ANALOGIX_DP_VIDEO_CTL_1 */ #define VIDEO_EN (0x1 << 7) #define HDCP_VIDEO_MUTE (0x1 << 6) -/* EXYNOS_DP_VIDEO_CTL_1 */ +/* ANALOGIX_DP_VIDEO_CTL_1 */ #define IN_D_RANGE_MASK (0x1 << 7) #define IN_D_RANGE_SHIFT (7) #define IN_D_RANGE_CEA (0x1 << 7) @@ -134,7 +136,7 @@ #define IN_COLOR_F_YCBCR422 (0x1 << 0) #define IN_COLOR_F_RGB (0x0 << 0) -/* EXYNOS_DP_VIDEO_CTL_3 */ +/* ANALOGIX_DP_VIDEO_CTL_3 */ #define IN_YC_COEFFI_MASK (0x1 << 7) #define IN_YC_COEFFI_SHIFT (7) #define IN_YC_COEFFI_ITU709 (0x1 << 7) @@ -144,17 +146,17 @@ #define VID_CHK_UPDATE_TYPE_1 (0x1 << 4) #define VID_CHK_UPDATE_TYPE_0 (0x0 << 4) -/* EXYNOS_DP_VIDEO_CTL_8 */ +/* ANALOGIX_DP_VIDEO_CTL_8 */ #define VID_HRES_TH(x) (((x) & 0xf) << 4) #define VID_VRES_TH(x) (((x) & 0xf) << 0) -/* EXYNOS_DP_VIDEO_CTL_10 */ +/* ANALOGIX_DP_VIDEO_CTL_10 */ #define FORMAT_SEL (0x1 << 4) #define INTERACE_SCAN_CFG (0x1 << 2) #define VSYNC_POLARITY_CFG (0x1 << 1) #define HSYNC_POLARITY_CFG (0x1 << 0) -/* EXYNOS_DP_LANE_MAP */ +/* ANALOGIX_DP_LANE_MAP */ #define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6) #define LANE3_MAP_LOGIC_LANE_1 (0x1 << 6) #define LANE3_MAP_LOGIC_LANE_2 (0x2 << 6) @@ -172,30 +174,30 @@ #define LANE0_MAP_LOGIC_LANE_2 (0x2 << 0) #define LANE0_MAP_LOGIC_LANE_3 (0x3 << 0) -/* EXYNOS_DP_ANALOG_CTL_1 */ +/* ANALOGIX_DP_ANALOG_CTL_1 */ #define TX_TERMINAL_CTRL_50_OHM (0x1 << 4) -/* EXYNOS_DP_ANALOG_CTL_2 */ +/* ANALOGIX_DP_ANALOG_CTL_2 */ #define SEL_24M (0x1 << 3) #define TX_DVDD_BIT_1_0625V (0x4 << 0) -/* EXYNOS_DP_ANALOG_CTL_3 */ +/* ANALOGIX_DP_ANALOG_CTL_3 */ #define DRIVE_DVDD_BIT_1_0625V (0x4 << 5) #define VCO_BIT_600_MICRO (0x5 << 0) -/* EXYNOS_DP_PLL_FILTER_CTL_1 */ +/* ANALOGIX_DP_PLL_FILTER_CTL_1 */ #define PD_RING_OSC (0x1 << 6) #define AUX_TERMINAL_CTRL_50_OHM (0x2 << 4) #define TX_CUR1_2X (0x1 << 2) #define TX_CUR_16_MA (0x3 << 0) -/* EXYNOS_DP_TX_AMP_TUNING_CTL */ +/* ANALOGIX_DP_TX_AMP_TUNING_CTL */ #define CH3_AMP_400_MV (0x0 << 24) #define CH2_AMP_400_MV (0x0 << 16) #define CH1_AMP_400_MV (0x0 << 8) #define CH0_AMP_400_MV (0x0 << 0) -/* EXYNOS_DP_AUX_HW_RETRY_CTL */ +/* ANALOGIX_DP_AUX_HW_RETRY_CTL */ #define AUX_BIT_PERIOD_EXPECTED_DELAY(x) (((x) & 0x7) << 8) #define AUX_HW_RETRY_INTERVAL_MASK (0x3 << 3) #define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS (0x0 << 3) @@ -204,7 +206,7 @@ #define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS (0x3 << 3) #define AUX_HW_RETRY_COUNT_SEL(x) (((x) & 0x7) << 0) -/* EXYNOS_DP_COMMON_INT_STA_1 */ +/* ANALOGIX_DP_COMMON_INT_STA_1 */ #define VSYNC_DET (0x1 << 7) #define PLL_LOCK_CHG (0x1 << 6) #define SPDIF_ERR (0x1 << 5) @@ -214,19 +216,19 @@ #define VID_CLK_CHG (0x1 << 1) #define SW_INT (0x1 << 0) -/* EXYNOS_DP_COMMON_INT_STA_2 */ +/* ANALOGIX_DP_COMMON_INT_STA_2 */ #define ENC_EN_CHG (0x1 << 6) #define HW_BKSV_RDY (0x1 << 3) #define HW_SHA_DONE (0x1 << 2) #define HW_AUTH_STATE_CHG (0x1 << 1) #define HW_AUTH_DONE (0x1 << 0) -/* EXYNOS_DP_COMMON_INT_STA_3 */ +/* ANALOGIX_DP_COMMON_INT_STA_3 */ #define AFIFO_UNDER (0x1 << 7) #define AFIFO_OVER (0x1 << 6) #define R0_CHK_FLAG (0x1 << 5) -/* EXYNOS_DP_COMMON_INT_STA_4 */ +/* ANALOGIX_DP_COMMON_INT_STA_4 */ #define PSR_ACTIVE (0x1 << 7) #define PSR_INACTIVE (0x1 << 6) #define SPDIF_BI_PHASE_ERR (0x1 << 5) @@ -234,29 +236,29 @@ #define HPD_LOST (0x1 << 1) #define PLUG (0x1 << 0) -/* EXYNOS_DP_INT_STA */ +/* ANALOGIX_DP_INT_STA */ #define INT_HPD (0x1 << 6) #define HW_TRAINING_FINISH (0x1 << 5) #define RPLY_RECEIV (0x1 << 1) #define AUX_ERR (0x1 << 0) -/* EXYNOS_DP_INT_CTL */ +/* ANALOGIX_DP_INT_CTL */ #define SOFT_INT_CTRL (0x1 << 2) #define INT_POL1 (0x1 << 1) #define INT_POL0 (0x1 << 0) -/* EXYNOS_DP_SYS_CTL_1 */ +/* ANALOGIX_DP_SYS_CTL_1 */ #define DET_STA (0x1 << 2) #define FORCE_DET (0x1 << 1) #define DET_CTRL (0x1 << 0) -/* EXYNOS_DP_SYS_CTL_2 */ +/* ANALOGIX_DP_SYS_CTL_2 */ #define CHA_CRI(x) (((x) & 0xf) << 4) #define CHA_STA (0x1 << 2) #define FORCE_CHA (0x1 << 1) #define CHA_CTRL (0x1 << 0) -/* EXYNOS_DP_SYS_CTL_3 */ +/* ANALOGIX_DP_SYS_CTL_3 */ #define HPD_STATUS (0x1 << 6) #define F_HPD (0x1 << 5) #define HPD_CTRL (0x1 << 4) @@ -265,13 +267,13 @@ #define F_VALID (0x1 << 1) #define VALID_CTRL (0x1 << 0) -/* EXYNOS_DP_SYS_CTL_4 */ +/* ANALOGIX_DP_SYS_CTL_4 */ #define FIX_M_AUD (0x1 << 4) #define ENHANCED (0x1 << 3) #define FIX_M_VID (0x1 << 2) #define M_VID_UPDATE_CTRL (0x3 << 0) -/* EXYNOS_DP_TRAINING_PTN_SET */ +/* ANALOGIX_DP_TRAINING_PTN_SET */ #define SCRAMBLER_TYPE (0x1 << 9) #define HW_LINK_TRAINING_PATTERN (0x1 << 8) #define SCRAMBLING_DISABLE (0x1 << 5) @@ -285,24 +287,24 @@ #define SW_TRAINING_PATTERN_SET_PTN1 (0x1 << 0) #define SW_TRAINING_PATTERN_SET_NORMAL (0x0 << 0) -/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */ +/* ANALOGIX_DP_LN0_LINK_TRAINING_CTL */ #define PRE_EMPHASIS_SET_MASK (0x3 << 3) #define PRE_EMPHASIS_SET_SHIFT (3) -/* EXYNOS_DP_DEBUG_CTL */ +/* ANALOGIX_DP_DEBUG_CTL */ #define PLL_LOCK (0x1 << 4) #define F_PLL_LOCK (0x1 << 3) #define PLL_LOCK_CTRL (0x1 << 2) #define PN_INV (0x1 << 0) -/* EXYNOS_DP_PLL_CTL */ +/* ANALOGIX_DP_PLL_CTL */ #define DP_PLL_PD (0x1 << 7) #define DP_PLL_RESET (0x1 << 6) #define DP_PLL_LOOP_BIT_DEFAULT (0x1 << 4) #define DP_PLL_REF_BIT_1_1250V (0x5 << 0) #define DP_PLL_REF_BIT_1_2500V (0x7 << 0) -/* EXYNOS_DP_PHY_PD */ +/* ANALOGIX_DP_PHY_PD */ #define DP_PHY_PD (0x1 << 5) #define AUX_PD (0x1 << 4) #define CH3_PD (0x1 << 3) @@ -310,28 +312,28 @@ #define CH1_PD (0x1 << 1) #define CH0_PD (0x1 << 0) -/* EXYNOS_DP_PHY_TEST */ +/* ANALOGIX_DP_PHY_TEST */ #define MACRO_RST (0x1 << 5) #define CH1_TEST (0x1 << 1) #define CH0_TEST (0x1 << 0) -/* EXYNOS_DP_AUX_CH_STA */ +/* ANALOGIX_DP_AUX_CH_STA */ #define AUX_BUSY (0x1 << 4) #define AUX_STATUS_MASK (0xf << 0) -/* EXYNOS_DP_AUX_CH_DEFER_CTL */ +/* ANALOGIX_DP_AUX_CH_DEFER_CTL */ #define DEFER_CTRL_EN (0x1 << 7) #define DEFER_COUNT(x) (((x) & 0x7f) << 0) -/* EXYNOS_DP_AUX_RX_COMM */ +/* ANALOGIX_DP_AUX_RX_COMM */ #define AUX_RX_COMM_I2C_DEFER (0x2 << 2) #define AUX_RX_COMM_AUX_DEFER (0x2 << 0) -/* EXYNOS_DP_BUFFER_DATA_CTL */ +/* ANALOGIX_DP_BUFFER_DATA_CTL */ #define BUF_CLR (0x1 << 7) #define BUF_DATA_COUNT(x) (((x) & 0x1f) << 0) -/* EXYNOS_DP_AUX_CH_CTL_1 */ +/* ANALOGIX_DP_AUX_CH_CTL_1 */ #define AUX_LENGTH(x) (((x - 1) & 0xf) << 4) #define AUX_TX_COMM_MASK (0xf << 0) #define AUX_TX_COMM_DP_TRANSACTION (0x1 << 3) @@ -340,20 +342,20 @@ #define AUX_TX_COMM_WRITE (0x0 << 0) #define AUX_TX_COMM_READ (0x1 << 0) -/* EXYNOS_DP_AUX_ADDR_7_0 */ +/* ANALOGIX_DP_AUX_ADDR_7_0 */ #define AUX_ADDR_7_0(x) (((x) >> 0) & 0xff) -/* EXYNOS_DP_AUX_ADDR_15_8 */ +/* ANALOGIX_DP_AUX_ADDR_15_8 */ #define AUX_ADDR_15_8(x) (((x) >> 8) & 0xff) -/* EXYNOS_DP_AUX_ADDR_19_16 */ +/* ANALOGIX_DP_AUX_ADDR_19_16 */ #define AUX_ADDR_19_16(x) (((x) >> 16) & 0x0f) -/* EXYNOS_DP_AUX_CH_CTL_2 */ +/* ANALOGIX_DP_AUX_CH_CTL_2 */ #define ADDR_ONLY (0x1 << 1) #define AUX_EN (0x1 << 0) -/* EXYNOS_DP_SOC_GENERAL_CTL */ +/* ANALOGIX_DP_SOC_GENERAL_CTL */ #define AUDIO_MODE_SPDIF_MODE (0x1 << 8) #define AUDIO_MODE_MASTER_MODE (0x0 << 8) #define MASTER_VIDEO_INTERLACE_EN (0x1 << 4) @@ -363,4 +365,4 @@ #define VIDEO_MODE_SLAVE_MODE (0x1 << 0) #define VIDEO_MODE_MASTER_MODE (0x0 << 0) -#endif /* _EXYNOS_DP_REG_H */ +#endif /* _ANALOGIX_DP_REG_H */ diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 43003c4..b33549c 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -54,9 +54,10 @@ config DRM_EXYNOS_DSI help This enables support for Exynos MIPI-DSI device. -config DRM_EXYNOS_DP - bool "EXYNOS DRM DP driver support" +config DRM_EXYNOS_ANALOGIX_DP + bool "EXYNOS specific extensions for Analogix DP driver" depends on DRM_EXYNOS && (DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON) && (DRM_PTN3460=n || DRM_PTN3460=y || DRM_PTN3460=DRM_EXYNOS) + select DRM_ANALOGIX_DP default DRM_EXYNOS select DRM_PANEL help diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile index 7de0b10..cda4d26 100644 --- a/drivers/gpu/drm/exynos/Makefile +++ b/drivers/gpu/drm/exynos/Makefile @@ -14,7 +14,7 @@ exynosdrm-$(CONFIG_DRM_EXYNOS5433_DECON) += exynos5433_drm_decon.o exynosdrm-$(CONFIG_DRM_EXYNOS7_DECON) += exynos7_drm_decon.o exynosdrm-$(CONFIG_DRM_EXYNOS_DPI) += exynos_drm_dpi.o exynosdrm-$(CONFIG_DRM_EXYNOS_DSI) += exynos_drm_dsi.o -exynosdrm-$(CONFIG_DRM_EXYNOS_DP) += exynos_dp_core.o exynos_dp_reg.o +exynosdrm-$(CONFIG_DRM_EXYNOS_ANALOGIX_DP) += analogix_dp-exynos.o exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o exynos_mixer.o exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o exynosdrm-$(CONFIG_DRM_EXYNOS_G2D) += exynos_drm_g2d.o diff --git a/drivers/gpu/drm/exynos/analogix_dp-exynos.c b/drivers/gpu/drm/exynos/analogix_dp-exynos.c new file mode 100644 index 0000000..b8d09d4 --- /dev/null +++ b/drivers/gpu/drm/exynos/analogix_dp-exynos.c @@ -0,0 +1,240 @@ +/* + * Samsung SoC DP (Display Port) interface driver. + * + * Copyright (C) 2012 Samsung Electronics Co., Ltd. + * Copyright (C) FuZhou Rockchip Electronics Co., Ltd. + * Author: Jingoo Han <jg1.han@samsung.com> + * Yakir Yang <ykk@rock-chips.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/component.h> + +#include <drm/drmP.h> +#include <drm/drm_panel.h> +#include <drm/bridge/ptn3460.h> + +#include <drm/exynos_drm.h> +#include "exynos_drm_drv.h" + +#define plat_data_to_dp(pd) \ + container_of(pd, struct exynos_dp_device, plat_data) + +struct exynos_dp_device { + struct exynos_drm_display display; + struct drm_bridge *ptn_bridge; + struct drm_device *drm_dev; + struct device *dev; + + struct analogix_dp_plat_data plat_data; +}; + +int exynos_dp_crtc_clock_enable(struct analogix_dp_plat_data *plat_data, + bool enable) +{ + struct exynos_dp_device *dp = plat_data_to_dp(plat_data); + struct drm_encoder *encoder = dp->display.encoder; + struct exynos_drm_crtc *crtc; + + if (!encoder) + return -1; + + crtc = to_exynos_crtc(encoder->crtc); + if (crtc && crtc->ops && crtc->ops->clock_enable) + crtc->ops->clock_enable(crtc, enable); + + return 0; +} + +static int exynos_dp_poweron(struct analogix_dp_plat_data *plat_data) +{ + exynos_dp_crtc_clock_enable(plat_data, true); +} + +static int exynos_dp_poweroff(struct analogix_dp_plat_data *plat_data) +{ + exynos_dp_crtc_clock_enable(plat_data, false); +} + +static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data, + struct drm_bridge *bridge) +{ + struct exynos_dp_device *dp = plat_data_to_dp(plat_data); + struct drm_encoder *encoder = dp->display.encoder; + int ret; + + /* Pre-empt DP connector creation if there's a bridge */ + if (dp->ptn_bridge) { + dp->bridge->next = dp->ptn_bridge; + dp->bridge->encoder = encoder; + ret = drm_bridge_attach(encoder->dev, dp->bridge); + if (ret) { + DRM_ERROR("Failed to attach bridge to drm\n"); + bridge->next = NULL; + return ret; + } + } + + return 0; +} + +static void exynos_dp_dpms(struct exynos_drm_display *display, int mode) +{ + /* do nothing */ +} + +static int exynos_dp_create_connector(struct exynos_drm_display *display, + struct drm_encoder *encoder) +{ + /* do nothing */ + return 0; +} + +static void exynos_dp_commit(struct exynos_drm_display *display) +{ + /* do nothing */ +} + +static struct exynos_drm_display_ops exynos_dp_display_ops = { + .create_connector = exynos_dp_create_connector, + .dpms = exynos_dp_dpms, + .commit = exynos_dp_commit, +}; + +static int exynos_dp_bind(struct device *dev, struct device *master, void *data) +{ + struct exynos_dp_device *dp = dev_get_drvdata(dev); + struct drm_device *drm_dev = data; + int ret; + + /* + * Just like the probe function said, we don't need the + * device drvrate anymore, we should leave the charge to + * analogix dp driver, set the device drvdata to NULL. + */ + dev_set_drvdata(dev, NULL); + + dp->dev = dev; + dp->drm_dev = drm_dev; + + dp->plat_data.power_on = exynos_dp_poweron; + dp->plat_data.power_off = exynos_dp_poweroff; + dp->plat_data.attach = exynos_dp_bridge_attach; + + ret = exynos_drm_create_enc_conn(dp->drm_dev, &dp->display); + if (ret) { + DRM_ERROR("exynos dp create enc_conn failed\n"); + return ret; + } + + return analogix_dp_bind(dev, dp->drm_dev, dp->display.encoder, + &dp->plat_data); +} + +static void exynos_dp_unbind(struct device *dev, struct device *master, + void *data) +{ + return analogix_dp_unbind(dev, master, data); +} + +static const struct component_ops exynos_dp_ops = { + .bind = exynos_dp_bind, + .unbind = exynos_dp_unbind, +}; + +static int exynos_dp_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *panel_node, *bridge_node, *endpoint; + struct exynos_dp_device *dp; + + dp = devm_kzalloc(&pdev->dev, sizeof(struct exynos_dp_device), + GFP_KERNEL); + if (!dp) + return -ENOMEM; + + /* + * We just use the drvdata until driver run into component + * add function, and then we would set drvdata to null, so + * that analogix dp driver would take charge of the drvdata. + */ + platform_set_drvdata(pdev, dp); + + dp->display.type = EXYNOS_DISPLAY_TYPE_LCD; + dp->display.ops = &exynos_dp_display_ops; + + panel_node = of_parse_phandle(dev->of_node, "panel", 0); + if (panel_node) { + dp->panel = of_drm_find_panel(panel_node); + of_node_put(panel_node); + if (!dp->panel) + return -EPROBE_DEFER; + } + + endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); + if (endpoint) { + bridge_node = of_graph_get_remote_port_parent(endpoint); + if (bridge_node) { + dp->ptn_bridge = of_drm_find_bridge(bridge_node); + of_node_put(bridge_node); + if (!dp->ptn_bridge) + return -EPROBE_DEFER; + } else { + return -EPROBE_DEFER; + } + } + + return component_add(&pdev->dev, &exynos_dp_ops); +} + +static int exynos_dp_remove(struct platform_device *pdev) +{ + component_del(&pdev->dev, &exynos_dp_ops); + + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int exynos_dp_suspend(struct device *dev) +{ + return analogix_dp_suspend(dev); +} + +static int exynos_dp_resume(struct device *dev) +{ + return analogix_dp_resume(dev); +} +#endif + +static const struct dev_pm_ops exynos_dp_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume) +}; + +static const struct of_device_id exynos_dp_match[] = { + { .compatible = "samsung,exynos5-dp" }, + {}, +}; +MODULE_DEVICE_TABLE(of, exynos_dp_match); + +struct platform_driver dp_driver = { + .probe = exynos_dp_probe, + .remove = exynos_dp_remove, + .driver = { + .name = "exynos-dp", + .owner = THIS_MODULE, + .pm = &exynos_dp_pm_ops, + .of_match_table = exynos_dp_match, + }, +}; + +MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); +MODULE_AUTHOR("Yakir Yang <ykk@rock-chips.com>"); +MODULE_DESCRIPTION("Samsung Specific Analogix-DP Driver Extension"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.h b/drivers/gpu/drm/exynos/exynos_dp_core.h deleted file mode 100644 index f2584b8..0000000 --- a/drivers/gpu/drm/exynos/exynos_dp_core.h +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Header file for Samsung DP (Display Port) interface driver. - * - * Copyright (C) 2012 Samsung Electronics Co., Ltd. - * Author: Jingoo Han <jg1.han@samsung.com> - * Yakir Yang <ykk@rock-chips.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#ifndef _EXYNOS_DP_CORE_H -#define _EXYNOS_DP_CORE_H - -#include <drm/drm_crtc.h> -#include <drm/drm_dp_helper.h> -#include <drm/exynos_drm.h> - -#include "exynos_drm_drv.h" - -#define DP_TIMEOUT_LOOP_COUNT 100 -#define MAX_CR_LOOP 5 -#define MAX_EQ_LOOP 5 - -enum link_rate_type { - LINK_RATE_1_62GBPS = 0x06, - LINK_RATE_2_70GBPS = 0x0a -}; - -enum link_lane_count_type { - LANE_COUNT1 = 1, - LANE_COUNT2 = 2, - LANE_COUNT4 = 4 -}; - -enum link_training_state { - START, - CLOCK_RECOVERY, - EQUALIZER_TRAINING, - FINISHED, - FAILED -}; - -enum voltage_swing_level { - VOLTAGE_LEVEL_0, - VOLTAGE_LEVEL_1, - VOLTAGE_LEVEL_2, - VOLTAGE_LEVEL_3, -}; - -enum pre_emphasis_level { - PRE_EMPHASIS_LEVEL_0, - PRE_EMPHASIS_LEVEL_1, - PRE_EMPHASIS_LEVEL_2, - PRE_EMPHASIS_LEVEL_3, -}; - -enum pattern_set { - PRBS7, - D10_2, - TRAINING_PTN1, - TRAINING_PTN2, - DP_NONE -}; - -enum color_space { - COLOR_RGB, - COLOR_YCBCR422, - COLOR_YCBCR444 -}; - -enum color_depth { - COLOR_6, - COLOR_8, - COLOR_10, - COLOR_12 -}; - -enum color_coefficient { - COLOR_YCBCR601, - COLOR_YCBCR709 -}; - -enum dynamic_range { - VESA, - CEA -}; - -enum pll_status { - PLL_UNLOCKED, - PLL_LOCKED -}; - -enum clock_recovery_m_value_type { - CALCULATED_M, - REGISTER_M -}; - -enum video_timing_recognition_type { - VIDEO_TIMING_FROM_CAPTURE, - VIDEO_TIMING_FROM_REGISTER -}; - -enum analog_power_block { - AUX_BLOCK, - CH0_BLOCK, - CH1_BLOCK, - CH2_BLOCK, - CH3_BLOCK, - ANALOG_TOTAL, - POWER_ALL -}; - -enum dp_irq_type { - DP_IRQ_TYPE_HP_CABLE_IN, - DP_IRQ_TYPE_HP_CABLE_OUT, - DP_IRQ_TYPE_HP_CHANGE, - DP_IRQ_TYPE_UNKNOWN, -}; - -struct video_info { - char *name; - - bool h_sync_polarity; - bool v_sync_polarity; - bool interlaced; - - enum color_space color_space; - enum dynamic_range dynamic_range; - enum color_coefficient ycbcr_coeff; - enum color_depth color_depth; - - enum link_rate_type link_rate; - enum link_lane_count_type lane_count; -}; - -struct link_train { - int eq_loop; - int cr_loop[4]; - - u8 link_rate; - u8 lane_count; - u8 training_lane[4]; - - enum link_training_state lt_state; -}; - -struct exynos_dp_device { - struct exynos_drm_display display; - struct device *dev; - struct drm_device *drm_dev; - struct drm_connector connector; - struct drm_encoder *encoder; - struct drm_panel *panel; - struct drm_bridge *bridge; - struct drm_bridge *ptn_bridge; - struct clk *clock; - unsigned int irq; - void __iomem *reg_base; - - struct video_info *video_info; - struct link_train link_train; - struct work_struct hotplug_work; - struct phy *phy; - int dpms_mode; - int hpd_gpio; - - struct exynos_drm_panel_info priv; -}; - -/* exynos_dp_reg.c */ -void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable); -void exynos_dp_stop_video(struct exynos_dp_device *dp); -void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable); -void exynos_dp_init_analog_param(struct exynos_dp_device *dp); -void exynos_dp_init_interrupt(struct exynos_dp_device *dp); -void exynos_dp_reset(struct exynos_dp_device *dp); -void exynos_dp_swreset(struct exynos_dp_device *dp); -void exynos_dp_config_interrupt(struct exynos_dp_device *dp); -enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp); -void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable); -void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp, - enum analog_power_block block, - bool enable); -void exynos_dp_init_analog_func(struct exynos_dp_device *dp); -void exynos_dp_init_hpd(struct exynos_dp_device *dp); -enum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp); -void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp); -void exynos_dp_reset_aux(struct exynos_dp_device *dp); -void exynos_dp_init_aux(struct exynos_dp_device *dp); -int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp); -void exynos_dp_enable_sw_function(struct exynos_dp_device *dp); -int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp); -int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned char data); -int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned char *data); -int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned int count, - unsigned char data[]); -int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp, - unsigned int reg_addr, - unsigned int count, - unsigned char data[]); -int exynos_dp_select_i2c_device(struct exynos_dp_device *dp, - unsigned int device_addr, - unsigned int reg_addr); -int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp, - unsigned int device_addr, - unsigned int reg_addr, - unsigned int *data); -int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp, - unsigned int device_addr, - unsigned int reg_addr, - unsigned int count, - unsigned char edid[]); -void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype); -void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype); -void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count); -void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count); -void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable); -void exynos_dp_set_training_pattern(struct exynos_dp_device *dp, - enum pattern_set pattern); -void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level); -void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level); -void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level); -void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level); -void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp, - u32 training_lane); -void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp, - u32 training_lane); -void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp, - u32 training_lane); -void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp, - u32 training_lane); -u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp); -u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp); -u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp); -u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp); -void exynos_dp_reset_macro(struct exynos_dp_device *dp); -void exynos_dp_init_video(struct exynos_dp_device *dp); - -void exynos_dp_set_video_color_format(struct exynos_dp_device *dp); -int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp); -void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp, - enum clock_recovery_m_value_type type, - u32 m_value, u32 n_value); -void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type); -void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable); -void exynos_dp_start_video(struct exynos_dp_device *dp); -int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp); -void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp); -void exynos_dp_enable_scrambling(struct exynos_dp_device *dp); -void exynos_dp_disable_scrambling(struct exynos_dp_device *dp); - -/* 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 - -/* DP_MAX_LANE_COUNT */ -#define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1) -#define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f) - -/* DP_LANE_COUNT_SET */ -#define DPCD_LANE_COUNT_SET(x) ((x) & 0x1f) - -/* DP_TRAINING_LANE0_SET */ -#define DPCD_PRE_EMPHASIS_SET(x) (((x) & 0x3) << 3) -#define DPCD_PRE_EMPHASIS_GET(x) (((x) >> 3) & 0x3) -#define DPCD_VOLTAGE_SWING_SET(x) (((x) & 0x3) << 0) -#define DPCD_VOLTAGE_SWING_GET(x) (((x) >> 0) & 0x3) - -#endif /* _EXYNOS_DP_CORE_H */ diff --git a/include/drm/bridge/analogix_dp.h b/include/drm/bridge/analogix_dp.h new file mode 100644 index 0000000..9a207f8 --- /dev/null +++ b/include/drm/bridge/analogix_dp.h @@ -0,0 +1,22 @@ +#ifndef _ANALOGIX_DP_H_ +#define _ANALOGIX_DP_H_ + +#include <drm/drm_crtc.h> + +struct analogix_dp_plat_data { + struct drm_panel *panel; + + int (*power_on)(struct analogix_dp_plat_data *); + int (*power_off)(struct analogix_dp_plat_data *); + int (*attach)(struct analogix_dp_plat_data *, struct drm_bridge *); +}; + +int analogix_dp_resume(struct device *dev); +int analogix_dp_suspend(struct device *dev); + +int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, + struct drm_encoder *encoder, + struct analogix_dp_plat_data *plat_data); +void analogix_dp_unbind(struct device *dev, struct device *master, void *data); + +#endif /* _ANALOGIX_DP_H_ */
Split the dp core driver from exynos directory to bridge directory, and rename the core driver to analogix_dp_*, leave the platform code to analogix_dp-exynos. Signed-off-by: Yakir Yang <ykk@rock-chips.com> --- drivers/gpu/drm/bridge/Kconfig | 5 + drivers/gpu/drm/bridge/Makefile | 1 + .../exynos_dp_core.c => bridge/analogix_dp_core.c} | 751 +++++------- drivers/gpu/drm/bridge/analogix_dp_core.h | 286 +++++ drivers/gpu/drm/bridge/analogix_dp_reg.c | 1266 ++++++++++++++++++++ .../exynos_dp_reg.h => bridge/analogix_dp_reg.h} | 260 ++-- drivers/gpu/drm/exynos/Kconfig | 5 +- drivers/gpu/drm/exynos/Makefile | 2 +- drivers/gpu/drm/exynos/analogix_dp-exynos.c | 240 ++++ drivers/gpu/drm/exynos/exynos_dp_core.h | 283 ----- include/drm/bridge/analogix_dp.h | 22 + 11 files changed, 2287 insertions(+), 834 deletions(-) rename drivers/gpu/drm/{exynos/exynos_dp_core.c => bridge/analogix_dp_core.c} (54%) create mode 100644 drivers/gpu/drm/bridge/analogix_dp_core.h create mode 100644 drivers/gpu/drm/bridge/analogix_dp_reg.c rename drivers/gpu/drm/{exynos/exynos_dp_reg.h => bridge/analogix_dp_reg.h} (63%) create mode 100644 drivers/gpu/drm/exynos/analogix_dp-exynos.c delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h create mode 100644 include/drm/bridge/analogix_dp.h