Hi Samsung Guys,

Can you take your time to test or review for exynos controller?:-)

Anyway, verified on rockchip controller.
So feel free add my test tag for this patch.


在 2016年03月18日 05:47, Heiko Stübner 写道:
> Split the dp core driver from exynos directory to bridge directory,
> and rename the core driver to analogix_dp_*, rename the platform
> code to exynos_dp.
>
> Beside the new analogix_dp driver would export six hooks.
> "analogix_dp_bind()" and "analogix_dp_unbind()"
> "analogix_dp_suspned()" and "analogix_dp_resume()"
> "analogix_dp_detect()" and "analogix_dp_get_modes()"
>
> The bind/unbind symbols is used for analogix platform driver to connect
> with analogix_dp core driver. And the detect/get_modes is used for analogix
> platform driver to init the connector.
>
> They reason why connector need register in helper driver is rockchip drm
> haven't implement the atomic API, but Exynos drm have implement it, so
> there would need two different connector helper functions, that's why we
> leave the connector register in helper driver.
>
> Signed-off-by: Yakir Yang <ykk at rock-chips.com>

Tested-by: Caesar Wang <wxt at rock-chips.com>

> ---
> Changes in v14.1:
> - Rebase against drm-next from 2016-03-17
>    (adapt to another round of exynos-dp changes)
>
> Changes in v14:
> - Rebase the new changes in imx-dp driver
> - Split up this patch into 3 parts, make this easy to review (Heiko)
>
> Changes in v13: None
> Changes in v12:
> - Move the connector init to analogix_dp driver, and using ATOMIC helper 
> (Heiko)
>
> Changes in v11:
> - Uses tabs to fix the indentation issues in analogix_dp_core.h (Heiko)
>
> Changes in v10: None
> Changes in v9: None
> Changes in v8: None
> Changes in v7: None
> Changes in v6:
> - Fix the Kconfig recursive dependency (Javier)
>
> Changes in v5:
> - Correct the check condition of gpio_is_valid when driver try to get
>    the "hpd-gpios" DT propery. (Heiko)
> - Move the platform attach callback in the front of core driver bridge
>    attch function. Cause once platform failed at attach, core driver should
>    still failed, so no need to init connector before platform attached 
> (Krzysztof)
> - Keep code style no changes with the previous exynos_dp_code.c in this
>    patch, and update commit message about the new export symbol (Krzysztof)
> - Gather the device type patch (v4 11/16) into this one. (Krzysztof)
> - leave out the connector registration to analogix platform driver. (Thierry)
>
> Changes in v4:
> - Update "analogix,hpd-gpios" to "hpd-gpios" DT propery. (Rob)
> - Rename "analogix_dp-exynos.c" file name to "exynos_dp.c" (Jingoo)
> - Create a separate folder for analogix code in bridge/ (Archit)
>
> Changes in v3:
> - Move exynos's video_timing code to analogix_dp-exynos platform driver,
>    add get_modes method to struct analogix_dp_plat_data. (Thierry)
> - Rename some "samsung*" dts propery to "analogix*". (Heiko)
>
> Changes in v2:
> - Remove new copyright (Jingoo)
> - Fix compiled failed due to analogix_dp_device misspell
>
>
>   drivers/gpu/drm/bridge/Kconfig                     |    2 +
>   drivers/gpu/drm/bridge/Makefile                    |    1 +
>   drivers/gpu/drm/bridge/analogix/Kconfig            |    3 +
>   drivers/gpu/drm/bridge/analogix/Makefile           |    1 +
>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 1351 
> +++++++++++++++++++
>   drivers/gpu/drm/bridge/analogix/analogix_dp_core.h |  277 ++++
>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c  | 1263 ++++++++++++++++++
>   drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h  |  366 ++++++
>   drivers/gpu/drm/exynos/Kconfig                     |    3 +-
>   drivers/gpu/drm/exynos/Makefile                    |    2 +-
>   drivers/gpu/drm/exynos/exynos_dp_core.c            | 1353 
> ++------------------
>   drivers/gpu/drm/exynos/exynos_dp_core.h            |  282 ----
>   drivers/gpu/drm/exynos/exynos_dp_reg.c             | 1263 ------------------
>   drivers/gpu/drm/exynos/exynos_dp_reg.h             |  366 ------
>   include/drm/bridge/analogix_dp.h                   |   40 +
>   15 files changed, 3391 insertions(+), 3182 deletions(-)
>   create mode 100644 drivers/gpu/drm/bridge/analogix/Kconfig
>   create mode 100644 drivers/gpu/drm/bridge/analogix/Makefile
>   create mode 100644 drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>   create mode 100644 drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
>   create mode 100644 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
>   create mode 100644 drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
>   delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_core.h
>   delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.c
>   delete mode 100644 drivers/gpu/drm/exynos/exynos_dp_reg.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 27e2022..efd94e0 100644
> --- a/drivers/gpu/drm/bridge/Kconfig
> +++ b/drivers/gpu/drm/bridge/Kconfig
> @@ -40,4 +40,6 @@ config DRM_PARADE_PS8622
>       ---help---
>         Parade eDP-LVDS bridge chip driver.
>   
> +source "drivers/gpu/drm/bridge/analogix/Kconfig"
> +
>   endmenu
> diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
> index f13c33d..ff821f4 100644
> --- a/drivers/gpu/drm/bridge/Makefile
> +++ b/drivers/gpu/drm/bridge/Makefile
> @@ -4,3 +4,4 @@ obj-$(CONFIG_DRM_DW_HDMI) += dw-hdmi.o
>   obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
>   obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
>   obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
> +obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
> diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig 
> b/drivers/gpu/drm/bridge/analogix/Kconfig
> new file mode 100644
> index 0000000..80f286f
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/analogix/Kconfig
> @@ -0,0 +1,3 @@
> +config DRM_ANALOGIX_DP
> +     tristate
> +     depends on DRM
> diff --git a/drivers/gpu/drm/bridge/analogix/Makefile 
> b/drivers/gpu/drm/bridge/analogix/Makefile
> new file mode 100644
> index 0000000..9107b86
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/analogix/Makefile
> @@ -0,0 +1 @@
> +obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix_dp_core.o analogix_dp_reg.o
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c 
> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> new file mode 100644
> index 0000000..392c296
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
> @@ -0,0 +1,1351 @@
> +/*
> +* Analogix DP (Display Port) core interface driver.
> +*
> +* Copyright (C) 2012 Samsung Electronics Co., Ltd.
> +* Author: Jingoo Han <jg1.han at samsung.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/io.h>
> +#include <linux/interrupt.h>
> +#include <linux/of.h>
> +#include <linux/of_gpio.h>
> +#include <linux/gpio.h>
> +#include <linux/component.h>
> +#include <linux/phy/phy.h>
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_atomic_helper.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_panel.h>
> +
> +#include <drm/bridge/analogix_dp.h>
> +
> +#include "analogix_dp_core.h"
> +
> +#define to_dp(nm)    container_of(nm, struct analogix_dp_device, nm)
> +
> +struct bridge_init {
> +     struct i2c_client *client;
> +     struct device_node *node;
> +};
> +
> +static void analogix_dp_init_dp(struct analogix_dp_device *dp)
> +{
> +     analogix_dp_reset(dp);
> +
> +     analogix_dp_swreset(dp);
> +
> +     analogix_dp_init_analog_param(dp);
> +     analogix_dp_init_interrupt(dp);
> +
> +     /* SW defined function Normal operation */
> +     analogix_dp_enable_sw_function(dp);
> +
> +     analogix_dp_config_interrupt(dp);
> +     analogix_dp_init_analog_func(dp);
> +
> +     analogix_dp_init_hpd(dp);
> +     analogix_dp_init_aux(dp);
> +}
> +
> +static int analogix_dp_detect_hpd(struct analogix_dp_device *dp)
> +{
> +     int timeout_loop = 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");
> +                     return -ETIMEDOUT;
> +             }
> +             usleep_range(10, 11);
> +     }
> +
> +     return 0;
> +}
> +
> +static unsigned char analogix_dp_calc_edid_check_sum(unsigned char 
> *edid_data)
> +{
> +     int i;
> +     unsigned char sum = 0;
> +
> +     for (i = 0; i < EDID_BLOCK_LENGTH; i++)
> +             sum = sum + edid_data[i];
> +
> +     return sum;
> +}
> +
> +static int analogix_dp_read_edid(struct analogix_dp_device *dp)
> +{
> +     unsigned char edid[EDID_BLOCK_LENGTH * 2];
> +     unsigned int extend_block = 0;
> +     unsigned char sum;
> +     unsigned char test_vector;
> +     int retval;
> +
> +     /*
> +      * EDID device address is 0x50.
> +      * However, if necessary, you must have set upper address
> +      * into E-EDID in I2C device, 0x30.
> +      */
> +
> +     /* Read Extension Flag, Number of 128-byte EDID extension blocks */
> +     retval = analogix_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
> +                             EDID_EXTENSION_FLAG,
> +                             &extend_block);
> +     if (retval)
> +             return retval;
> +
> +     if (extend_block > 0) {
> +             dev_dbg(dp->dev, "EDID data includes a single extension!\n");
> +
> +             /* Read EDID data */
> +             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 = analogix_dp_calc_edid_check_sum(edid);
> +             if (sum != 0) {
> +                     dev_err(dp->dev, "EDID bad checksum!\n");
> +                     return -EIO;
> +             }
> +
> +             /* Read additional EDID data */
> +             retval = 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 = analogix_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
> +             if (sum != 0) {
> +                     dev_err(dp->dev, "EDID bad checksum!\n");
> +                     return -EIO;
> +             }
> +
> +             analogix_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST,
> +                                     &test_vector);
> +             if (test_vector & DP_TEST_LINK_EDID_READ) {
> +                     analogix_dp_write_byte_to_dpcd(dp,
> +                             DP_TEST_EDID_CHECKSUM,
> +                             edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
> +                     analogix_dp_write_byte_to_dpcd(dp,
> +                             DP_TEST_RESPONSE,
> +                             DP_TEST_EDID_CHECKSUM_WRITE);
> +             }
> +     } else {
> +             dev_info(dp->dev, "EDID data does not include any 
> extensions.\n");
> +
> +             /* Read EDID data */
> +             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 = analogix_dp_calc_edid_check_sum(edid);
> +             if (sum != 0) {
> +                     dev_err(dp->dev, "EDID bad checksum!\n");
> +                     return -EIO;
> +             }
> +
> +             analogix_dp_read_byte_from_dpcd(dp,
> +                     DP_TEST_REQUEST,
> +                     &test_vector);
> +             if (test_vector & DP_TEST_LINK_EDID_READ) {
> +                     analogix_dp_write_byte_to_dpcd(dp,
> +                             DP_TEST_EDID_CHECKSUM,
> +                             edid[EDID_CHECKSUM]);
> +                     analogix_dp_write_byte_to_dpcd(dp,
> +                             DP_TEST_RESPONSE,
> +                             DP_TEST_EDID_CHECKSUM_WRITE);
> +             }
> +     }
> +
> +     dev_dbg(dp->dev, "EDID Read success!\n");
> +     return 0;
> +}
> +
> +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 = 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 = analogix_dp_read_edid(dp);
> +             if (!retval)
> +                     break;
> +     }
> +
> +     return retval;
> +}
> +
> +static void analogix_dp_enable_rx_to_enhanced_mode(struct analogix_dp_device 
> *dp,
> +                                             bool enable)
> +{
> +     u8 data;
> +
> +     analogix_dp_read_byte_from_dpcd(dp, DP_LANE_COUNT_SET, &data);
> +
> +     if (enable)
> +             analogix_dp_write_byte_to_dpcd(dp, DP_LANE_COUNT_SET,
> +                     DP_LANE_COUNT_ENHANCED_FRAME_EN |
> +                     DPCD_LANE_COUNT_SET(data));
> +     else
> +             analogix_dp_write_byte_to_dpcd(dp, DP_LANE_COUNT_SET,
> +                     DPCD_LANE_COUNT_SET(data));
> +}
> +
> +static int analogix_dp_is_enhanced_mode_available(struct analogix_dp_device 
> *dp)
> +{
> +     u8 data;
> +     int retval;
> +
> +     analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data);
> +     retval = DPCD_ENHANCED_FRAME_CAP(data);
> +
> +     return retval;
> +}
> +
> +static void analogix_dp_set_enhanced_mode(struct analogix_dp_device *dp)
> +{
> +     u8 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 analogix_dp_training_pattern_dis(struct analogix_dp_device *dp)
> +{
> +     analogix_dp_set_training_pattern(dp, DP_NONE);
> +
> +     analogix_dp_write_byte_to_dpcd(dp,
> +             DP_TRAINING_PATTERN_SET,
> +             DP_TRAINING_PATTERN_DISABLE);
> +}
> +
> +static void analogix_dp_set_lane_lane_pre_emphasis(struct analogix_dp_device 
> *dp,
> +                                     int pre_emphasis, int lane)
> +{
> +     switch (lane) {
> +     case 0:
> +             analogix_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
> +             break;
> +     case 1:
> +             analogix_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
> +             break;
> +
> +     case 2:
> +             analogix_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
> +             break;
> +
> +     case 3:
> +             analogix_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
> +             break;
> +     }
> +}
> +
> +static int analogix_dp_link_start(struct analogix_dp_device *dp)
> +{
> +     u8 buf[4];
> +     int lane, lane_count, pll_tries, retval;
> +
> +     lane_count = dp->link_train.lane_count;
> +
> +     dp->link_train.lt_state = CLOCK_RECOVERY;
> +     dp->link_train.eq_loop = 0;
> +
> +     for (lane = 0; lane < lane_count; lane++)
> +             dp->link_train.cr_loop[lane] = 0;
> +
> +     /* Set link rate and count as you want to establish*/
> +     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 = 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++)
> +             analogix_dp_set_lane_lane_pre_emphasis(dp,
> +                     PRE_EMPHASIS_LEVEL_0, lane);
> +
> +     /* Wait for PLL lock */
> +     pll_tries = 0;
> +     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;
> +             }
> +
> +             pll_tries++;
> +             usleep_range(90, 120);
> +     }
> +
> +     /* Set training pattern 1 */
> +     analogix_dp_set_training_pattern(dp, TRAINING_PTN1);
> +
> +     /* Set RX training pattern */
> +     retval = analogix_dp_write_byte_to_dpcd(dp,
> +                     DP_TRAINING_PATTERN_SET,
> +                     DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_1);
> +     if (retval)
> +             return retval;
> +
> +     for (lane = 0; lane < lane_count; lane++)
> +             buf[lane] = DP_TRAIN_PRE_EMPH_LEVEL_0 |
> +                         DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
> +
> +     retval = analogix_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET,
> +                     lane_count, buf);
> +
> +     return retval;
> +}
> +
> +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];
> +
> +     return (link_value >> shift) & 0xf;
> +}
> +
> +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 = analogix_dp_get_lane_status(link_status, lane);
> +             if ((lane_status & DP_LANE_CR_DONE) == 0)
> +                     return -EINVAL;
> +     }
> +     return 0;
> +}
> +
> +static int analogix_dp_channel_eq_ok(u8 link_status[2], u8 link_align,
> +                             int lane_count)
> +{
> +     int lane;
> +     u8 lane_status;
> +
> +     if ((link_align & DP_INTERLANE_ALIGN_DONE) == 0)
> +             return -EINVAL;
> +
> +     for (lane = 0; lane < lane_count; 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;
> +     }
> +
> +     return 0;
> +}
> +
> +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];
> +
> +     return (link_value >> shift) & 0x3;
> +}
> +
> +static unsigned char analogix_dp_get_adjust_request_pre_emphasis(
> +                                     u8 adjust_request[2],
> +                                     int lane)
> +{
> +     int shift = (lane & 1) * 4;
> +     u8 link_value = adjust_request[lane>>1];
> +
> +     return ((link_value >> shift) & 0xc) >> 2;
> +}
> +
> +static void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp,
> +                                     u8 training_lane_set, int lane)
> +{
> +     switch (lane) {
> +     case 0:
> +             analogix_dp_set_lane0_link_training(dp, training_lane_set);
> +             break;
> +     case 1:
> +             analogix_dp_set_lane1_link_training(dp, training_lane_set);
> +             break;
> +
> +     case 2:
> +             analogix_dp_set_lane2_link_training(dp, training_lane_set);
> +             break;
> +
> +     case 3:
> +             analogix_dp_set_lane3_link_training(dp, training_lane_set);
> +             break;
> +     }
> +}
> +
> +static unsigned int analogix_dp_get_lane_link_training(
> +                             struct analogix_dp_device *dp,
> +                             int lane)
> +{
> +     u32 reg;
> +
> +     switch (lane) {
> +     case 0:
> +             reg = analogix_dp_get_lane0_link_training(dp);
> +             break;
> +     case 1:
> +             reg = analogix_dp_get_lane1_link_training(dp);
> +             break;
> +     case 2:
> +             reg = analogix_dp_get_lane2_link_training(dp);
> +             break;
> +     case 3:
> +             reg = analogix_dp_get_lane3_link_training(dp);
> +             break;
> +     default:
> +             WARN_ON(1);
> +             return 0;
> +     }
> +
> +     return reg;
> +}
> +
> +static void analogix_dp_reduce_link_rate(struct analogix_dp_device *dp)
> +{
> +     analogix_dp_training_pattern_dis(dp);
> +     analogix_dp_set_enhanced_mode(dp);
> +
> +     dp->link_train.lt_state = FAILED;
> +}
> +
> +static void analogix_dp_get_adjust_training_lane(struct analogix_dp_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 = analogix_dp_get_adjust_request_voltage(
> +                                             adjust_request, lane);
> +             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);
> +
> +             if (voltage_swing == VOLTAGE_LEVEL_3)
> +                     training_lane |= DP_TRAIN_MAX_SWING_REACHED;
> +             if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
> +                     training_lane |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
> +
> +             dp->link_train.training_lane[lane] = training_lane;
> +     }
> +}
> +
> +static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
> +{
> +     int lane, lane_count, retval;
> +     u8 voltage_swing, pre_emphasis, training_lane;
> +     u8 link_status[2], adjust_request[2];
> +
> +     usleep_range(100, 101);
> +
> +     lane_count = dp->link_train.lane_count;
> +
> +     retval =  analogix_dp_read_bytes_from_dpcd(dp,
> +                     DP_LANE0_1_STATUS, 2, link_status);
> +     if (retval)
> +             return retval;
> +
> +     retval =  analogix_dp_read_bytes_from_dpcd(dp,
> +                     DP_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
> +     if (retval)
> +             return retval;
> +
> +     if (analogix_dp_clock_recovery_ok(link_status, lane_count) == 0) {
> +             /* set training pattern 2 for EQ */
> +             analogix_dp_set_training_pattern(dp, TRAINING_PTN2);
> +
> +             retval = analogix_dp_write_byte_to_dpcd(dp,
> +                             DP_TRAINING_PATTERN_SET,
> +                             DP_LINK_SCRAMBLING_DISABLE |
> +                             DP_TRAINING_PATTERN_2);
> +             if (retval)
> +                     return retval;
> +
> +             dev_info(dp->dev, "Link Training Clock Recovery success\n");
> +             dp->link_train.lt_state = EQUALIZER_TRAINING;
> +     } else {
> +             for (lane = 0; lane < lane_count; lane++) {
> +                     training_lane = analogix_dp_get_lane_link_training(
> +                                                     dp, lane);
> +                     voltage_swing = analogix_dp_get_adjust_request_voltage(
> +                                                     adjust_request, lane);
> +                     pre_emphasis = 
> analogix_dp_get_adjust_request_pre_emphasis(
> +                                                     adjust_request, lane);
> +
> +                     if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
> +                                     voltage_swing &&
> +                         DPCD_PRE_EMPHASIS_GET(training_lane) ==
> +                                     pre_emphasis)
> +                             dp->link_train.cr_loop[lane]++;
> +
> +                     if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
> +                         voltage_swing == VOLTAGE_LEVEL_3 ||
> +                         pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
> +                             dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n",
> +                                     dp->link_train.cr_loop[lane],
> +                                     voltage_swing, pre_emphasis);
> +                             analogix_dp_reduce_link_rate(dp);
> +                             return -EIO;
> +                     }
> +             }
> +     }
> +
> +     analogix_dp_get_adjust_training_lane(dp, adjust_request);
> +
> +     for (lane = 0; lane < lane_count; lane++)
> +             analogix_dp_set_lane_link_training(dp,
> +                     dp->link_train.training_lane[lane], lane);
> +
> +     retval = analogix_dp_write_bytes_to_dpcd(dp,
> +                     DP_TRAINING_LANE0_SET, lane_count,
> +                     dp->link_train.training_lane);
> +     if (retval)
> +             return retval;
> +
> +     return retval;
> +}
> +
> +static int analogix_dp_process_equalizer_training(struct analogix_dp_device 
> *dp)
> +{
> +     int lane, lane_count, retval;
> +     u32 reg;
> +     u8 link_align, link_status[2], adjust_request[2];
> +
> +     usleep_range(400, 401);
> +
> +     lane_count = dp->link_train.lane_count;
> +
> +     retval = analogix_dp_read_bytes_from_dpcd(dp,
> +                     DP_LANE0_1_STATUS, 2, link_status);
> +     if (retval)
> +             return retval;
> +
> +     if (analogix_dp_clock_recovery_ok(link_status, lane_count)) {
> +             analogix_dp_reduce_link_rate(dp);
> +             return -EIO;
> +     }
> +
> +     retval = analogix_dp_read_bytes_from_dpcd(dp,
> +                     DP_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
> +     if (retval)
> +             return retval;
> +
> +     retval = analogix_dp_read_byte_from_dpcd(dp,
> +                     DP_LANE_ALIGN_STATUS_UPDATED, &link_align);
> +     if (retval)
> +             return retval;
> +
> +     analogix_dp_get_adjust_training_lane(dp, adjust_request);
> +
> +     if (!analogix_dp_channel_eq_ok(link_status, link_align, lane_count)) {
> +             /* traing pattern Set to Normal */
> +             analogix_dp_training_pattern_dis(dp);
> +
> +             dev_info(dp->dev, "Link Training success!\n");
> +
> +             analogix_dp_get_link_bandwidth(dp, &reg);
> +             dp->link_train.link_rate = reg;
> +             dev_dbg(dp->dev, "final bandwidth = %.2x\n",
> +                     dp->link_train.link_rate);
> +
> +             analogix_dp_get_lane_count(dp, &reg);
> +             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 */
> +             analogix_dp_set_enhanced_mode(dp);
> +             dp->link_train.lt_state = FINISHED;
> +
> +             return 0;
> +     }
> +
> +     /* not all locked */
> +     dp->link_train.eq_loop++;
> +
> +     if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
> +             dev_err(dp->dev, "EQ Max loop\n");
> +             analogix_dp_reduce_link_rate(dp);
> +             return -EIO;
> +     }
> +
> +     for (lane = 0; lane < lane_count; lane++)
> +             analogix_dp_set_lane_link_training(dp,
> +                     dp->link_train.training_lane[lane], lane);
> +
> +     retval = analogix_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET,
> +                     lane_count, dp->link_train.training_lane);
> +
> +     return retval;
> +}
> +
> +static void analogix_dp_get_max_rx_bandwidth(struct analogix_dp_device *dp,
> +                                     u8 *bandwidth)
> +{
> +     u8 data;
> +
> +     /*
> +      * For DP rev.1.1, Maximum link rate of Main Link lanes
> +      * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
> +      */
> +     analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LINK_RATE, &data);
> +     *bandwidth = data;
> +}
> +
> +static void analogix_dp_get_max_rx_lane_count(struct analogix_dp_device *dp,
> +                                     u8 *lane_count)
> +{
> +     u8 data;
> +
> +     /*
> +      * For DP rev.1.1, Maximum number of Main Link lanes
> +      * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
> +      */
> +     analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data);
> +     *lane_count = DPCD_MAX_LANE_COUNT(data);
> +}
> +
> +static void analogix_dp_init_training(struct analogix_dp_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
> +      */
> +     analogix_dp_reset_macro(dp);
> +
> +     /* Initialize by reading RX's DPCD */
> +     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)) {
> +             dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
> +                     dp->link_train.link_rate);
> +             dp->link_train.link_rate = LINK_RATE_1_62GBPS;
> +     }
> +
> +     if (dp->link_train.lane_count == 0) {
> +             dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
> +                     dp->link_train.lane_count);
> +             dp->link_train.lane_count = (u8)LANE_COUNT1;
> +     }
> +
> +     /* Setup TX lane count & rate */
> +     if (dp->link_train.lane_count > max_lane)
> +             dp->link_train.lane_count = max_lane;
> +     if (dp->link_train.link_rate > max_rate)
> +             dp->link_train.link_rate = max_rate;
> +
> +     /* All DP analog module power up */
> +     analogix_dp_set_analog_power_down(dp, POWER_ALL, 0);
> +}
> +
> +static int analogix_dp_sw_link_training(struct analogix_dp_device *dp)
> +{
> +     int retval = 0, training_finished = 0;
> +
> +     dp->link_train.lt_state = START;
> +
> +     /* Process here */
> +     while (!retval && !training_finished) {
> +             switch (dp->link_train.lt_state) {
> +             case START:
> +                     retval = analogix_dp_link_start(dp);
> +                     if (retval)
> +                             dev_err(dp->dev, "LT link start failed!\n");
> +                     break;
> +             case CLOCK_RECOVERY:
> +                     retval = analogix_dp_process_clock_recovery(dp);
> +                     if (retval)
> +                             dev_err(dp->dev, "LT CR failed!\n");
> +                     break;
> +             case EQUALIZER_TRAINING:
> +                     retval = analogix_dp_process_equalizer_training(dp);
> +                     if (retval)
> +                             dev_err(dp->dev, "LT EQ failed!\n");
> +                     break;
> +             case FINISHED:
> +                     training_finished = 1;
> +                     break;
> +             case FAILED:
> +                     return -EREMOTEIO;
> +             }
> +     }
> +     if (retval)
> +             dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
> +
> +     return retval;
> +}
> +
> +static int analogix_dp_set_link_train(struct analogix_dp_device *dp,
> +                             u32 count,
> +                             u32 bwtype)
> +{
> +     int i;
> +     int retval;
> +
> +     for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) {
> +             analogix_dp_init_training(dp, count, bwtype);
> +             retval = analogix_dp_sw_link_training(dp);
> +             if (retval == 0)
> +                     break;
> +
> +             usleep_range(100, 110);
> +     }
> +
> +     return retval;
> +}
> +
> +static int analogix_dp_config_video(struct analogix_dp_device *dp)
> +{
> +     int retval = 0;
> +     int timeout_loop = 0;
> +     int done_count = 0;
> +
> +     analogix_dp_config_video_slave_mode(dp);
> +
> +     analogix_dp_set_video_color_format(dp);
> +
> +     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 (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");
> +                     return -ETIMEDOUT;
> +             }
> +
> +             usleep_range(1, 2);
> +     }
> +
> +     /* Set to use the register calculated M/N video */
> +     analogix_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
> +
> +     /* For video bist, Video timing must be generated by register */
> +     analogix_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
> +
> +     /* Disable video mute */
> +     analogix_dp_enable_video_mute(dp, 0);
> +
> +     /* Configure video slave mode */
> +     analogix_dp_enable_video_master(dp, 0);
> +
> +     timeout_loop = 0;
> +
> +     for (;;) {
> +             timeout_loop++;
> +             if (analogix_dp_is_video_stream_on(dp) == 0) {
> +                     done_count++;
> +                     if (done_count > 10)
> +                             break;
> +             } else if (done_count) {
> +                     done_count = 0;
> +             }
> +             if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
> +                     dev_err(dp->dev, "Timeout of video streamclk ok\n");
> +                     return -ETIMEDOUT;
> +             }
> +
> +             usleep_range(1000, 1001);
> +     }
> +
> +     if (retval != 0)
> +             dev_err(dp->dev, "Video stream is not detected!\n");
> +
> +     return retval;
> +}
> +
> +static void analogix_dp_enable_scramble(struct analogix_dp_device *dp, bool 
> enable)
> +{
> +     u8 data;
> +
> +     if (enable) {
> +             analogix_dp_enable_scrambling(dp);
> +
> +             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 {
> +             analogix_dp_disable_scrambling(dp);
> +
> +             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 analogix_dp_irq_handler(int irq, void *arg)
> +{
> +     struct analogix_dp_device *dp = arg;
> +
> +     enum dp_irq_type irq_type;
> +
> +     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);
> +             analogix_dp_clear_hotplug_interrupts(dp);
> +             break;
> +     case DP_IRQ_TYPE_HP_CABLE_OUT:
> +             dev_dbg(dp->dev, "Received irq - cable out\n");
> +             analogix_dp_clear_hotplug_interrupts(dp);
> +             break;
> +     case DP_IRQ_TYPE_HP_CHANGE:
> +             /*
> +              * We get these change notifications once in a while, but there
> +              * is nothing we can do with them. Just ignore it for now and
> +              * only handle cable changes.
> +              */
> +             dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n");
> +             analogix_dp_clear_hotplug_interrupts(dp);
> +             break;
> +     default:
> +             dev_err(dp->dev, "Received irq - unknown type!\n");
> +             break;
> +     }
> +     return IRQ_HANDLED;
> +}
> +
> +static void analogix_dp_hotplug(struct work_struct *work)
> +{
> +     struct analogix_dp_device *dp;
> +
> +     dp = container_of(work, struct analogix_dp_device, hotplug_work);
> +
> +     if (dp->drm_dev)
> +             drm_helper_hpd_irq_event(dp->drm_dev);
> +}
> +
> +static void analogix_dp_commit(struct analogix_dp_device *dp)
> +{
> +     int ret;
> +
> +     /* Keep the panel disabled while we configure video */
> +     if (dp->plat_data->panel) {
> +             if (drm_panel_disable(dp->plat_data->panel))
> +                     DRM_ERROR("failed to disable the panel\n");
> +     }
> +
> +     ret = analogix_dp_detect_hpd(dp);
> +     if (ret) {
> +             /* Cable has been disconnected, we're done */
> +             return;
> +     }
> +
> +     ret = analogix_dp_handle_edid(dp);
> +     if (ret) {
> +             dev_err(dp->dev, "unable to handle edid\n");
> +             return;
> +     }
> +
> +     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;
> +     }
> +
> +     analogix_dp_enable_scramble(dp, 1);
> +     analogix_dp_enable_rx_to_enhanced_mode(dp, 1);
> +     analogix_dp_enable_enhanced_mode(dp, 1);
> +
> +     analogix_dp_set_lane_count(dp, dp->video_info->lane_count);
> +     analogix_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
> +
> +     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->plat_data->panel) {
> +             if (drm_panel_enable(dp->plat_data->panel))
> +                     DRM_ERROR("failed to enable the panel\n");
> +     }
> +
> +     /* Enable video */
> +     analogix_dp_start_video(dp);
> +}
> +
> +int analogix_dp_get_modes(struct drm_connector *connector)
> +{
> +     struct analogix_dp_device *dp = to_dp(connector);
> +     int num_modes = 0;
> +
> +     if (dp->plat_data->panel)
> +             num_modes += drm_panel_get_modes(dp->plat_data->panel);
> +
> +     if (dp->plat_data->get_modes)
> +             num_modes += dp->plat_data->get_modes(dp->plat_data);
> +
> +     return num_modes;
> +}
> +
> +static struct drm_encoder *
> +analogix_dp_best_encoder(struct drm_connector *connector)
> +{
> +     struct analogix_dp_device *dp = to_dp(connector);
> +
> +     return dp->encoder;
> +}
> +
> +static const struct drm_connector_helper_funcs 
> analogix_dp_connector_helper_funcs = {
> +     .get_modes = analogix_dp_get_modes,
> +     .best_encoder = analogix_dp_best_encoder,
> +};
> +
> +enum drm_connector_status
> +analogix_dp_detect(struct drm_connector *connector, bool force)
> +{
> +     return connector_status_connected;
> +}
> +
> +static void analogix_dp_connector_destroy(struct drm_connector *connector)
> +{
> +     drm_connector_unregister(connector);
> +     drm_connector_cleanup(connector);
> +}
> +
> +static const struct drm_connector_funcs analogix_dp_connector_funcs = {
> +     .dpms = drm_atomic_helper_connector_dpms,
> +     .fill_modes = drm_helper_probe_single_connector_modes,
> +     .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 analogix_dp_bridge_attach(struct drm_bridge *bridge)
> +{
> +     struct analogix_dp_device *dp = bridge->driver_private;
> +     struct drm_encoder *encoder = dp->encoder;
> +     struct drm_connector *connector = &dp->connector;
> +     int ret;
> +
> +     if (!bridge->encoder) {
> +             DRM_ERROR("Parent encoder object not found");
> +             return -ENODEV;
> +     }
> +
> +     connector->polled = DRM_CONNECTOR_POLL_HPD;
> +
> +     ret = drm_connector_init(dp->drm_dev, connector,
> +                              &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,
> +                              &analogix_dp_connector_helper_funcs);
> +     drm_mode_connector_attach_encoder(connector, encoder);
> +
> +     /*
> +      * NOTE: the connector registration is implemented in analogix
> +      * platform driver, that to say connector would be exist after
> +      * plat_data->attch return, that's why we record the connector
> +      * point after plat attached.
> +      */
> +      if (dp->plat_data->attach) {
> +              ret = dp->plat_data->attach(dp->plat_data, bridge, connector);
> +              if (ret) {
> +                      DRM_ERROR("Failed at platform attch func\n");
> +                      return ret;
> +              }
> +     }
> +
> +     if (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;
> +             }
> +     }
> +
> +     return 0;
> +}
> +
> +static void analogix_dp_bridge_enable(struct drm_bridge *bridge)
> +{
> +     struct analogix_dp_device *dp = bridge->driver_private;
> +
> +     if (dp->dpms_mode == DRM_MODE_DPMS_ON)
> +             return;
> +
> +     pm_runtime_get_sync(dp->dev);
> +
> +     if (dp->plat_data->panel) {
> +             if (drm_panel_prepare(dp->plat_data->panel)) {
> +                     DRM_ERROR("failed to setup the panel\n");
> +                     return;
> +             }
> +     }
> +
> +     if (dp->plat_data->power_on)
> +             dp->plat_data->power_on(dp->plat_data);
> +
> +     phy_power_on(dp->phy);
> +     analogix_dp_init_dp(dp);
> +     enable_irq(dp->irq);
> +     analogix_dp_commit(dp);
> +
> +     dp->dpms_mode = DRM_MODE_DPMS_ON;
> +}
> +
> +static void analogix_dp_bridge_disable(struct drm_bridge *bridge)
> +{
> +     struct analogix_dp_device *dp = bridge->driver_private;
> +
> +     if (dp->dpms_mode != DRM_MODE_DPMS_ON)
> +             return;
> +
> +     if (dp->plat_data->panel) {
> +             if (drm_panel_disable(dp->plat_data->panel)) {
> +                     DRM_ERROR("failed to disable the panel\n");
> +                     return;
> +             }
> +     }
> +
> +     disable_irq(dp->irq);
> +     flush_work(&dp->hotplug_work);
> +     phy_power_off(dp->phy);
> +
> +     if (dp->plat_data->power_off)
> +             dp->plat_data->power_off(dp->plat_data);
> +
> +     if (dp->plat_data->panel) {
> +             if (drm_panel_unprepare(dp->plat_data->panel))
> +                     DRM_ERROR("failed to turnoff the panel\n");
> +     }
> +
> +     pm_runtime_put_sync(dp->dev);
> +
> +     dp->dpms_mode = DRM_MODE_DPMS_OFF;
> +}
> +
> +static void analogix_dp_bridge_nop(struct drm_bridge *bridge)
> +{
> +     /* do nothing */
> +}
> +
> +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 analogix_dp_create_bridge(struct drm_device *drm_dev,
> +                                  struct analogix_dp_device *dp)
> +{
> +     struct drm_bridge *bridge;
> +     int ret;
> +
> +     bridge = devm_kzalloc(drm_dev->dev, sizeof(*bridge), GFP_KERNEL);
> +     if (!bridge) {
> +             DRM_ERROR("failed to allocate for drm bridge\n");
> +             return -ENOMEM;
> +     }
> +
> +     dp->bridge = bridge;
> +
> +     dp->encoder->bridge = bridge;
> +     bridge->driver_private = dp;
> +     bridge->encoder = dp->encoder;
> +     bridge->funcs = &analogix_dp_bridge_funcs;
> +
> +     ret = drm_bridge_attach(drm_dev, bridge);
> +     if (ret) {
> +             DRM_ERROR("failed to attach drm bridge\n");
> +             return -EINVAL;
> +     }
> +
> +     return 0;
> +}
> +
> +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;
> +
> +     dp_video_config = devm_kzalloc(dev,
> +                             sizeof(*dp_video_config), GFP_KERNEL);
> +     if (!dp_video_config)
> +             return ERR_PTR(-ENOMEM);
> +
> +     dp_video_config->h_sync_polarity =
> +             of_property_read_bool(dp_node, "hsync-active-high");
> +
> +     dp_video_config->v_sync_polarity =
> +             of_property_read_bool(dp_node, "vsync-active-high");
> +
> +     dp_video_config->interlaced =
> +             of_property_read_bool(dp_node, "interlaced");
> +
> +     if (of_property_read_u32(dp_node, "samsung,color-space",
> +                             &dp_video_config->color_space)) {
> +             dev_err(dev, "failed to get color-space\n");
> +             return ERR_PTR(-EINVAL);
> +     }
> +
> +     if (of_property_read_u32(dp_node, "samsung,dynamic-range",
> +                             &dp_video_config->dynamic_range)) {
> +             dev_err(dev, "failed to get dynamic-range\n");
> +             return ERR_PTR(-EINVAL);
> +     }
> +
> +     if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
> +                             &dp_video_config->ycbcr_coeff)) {
> +             dev_err(dev, "failed to get ycbcr-coeff\n");
> +             return ERR_PTR(-EINVAL);
> +     }
> +
> +     if (of_property_read_u32(dp_node, "samsung,color-depth",
> +                             &dp_video_config->color_depth)) {
> +             dev_err(dev, "failed to get color-depth\n");
> +             return ERR_PTR(-EINVAL);
> +     }
> +
> +     if (of_property_read_u32(dp_node, "samsung,link-rate",
> +                             &dp_video_config->link_rate)) {
> +             dev_err(dev, "failed to get link-rate\n");
> +             return ERR_PTR(-EINVAL);
> +     }
> +
> +     if (of_property_read_u32(dp_node, "samsung,lane-count",
> +                             &dp_video_config->lane_count)) {
> +             dev_err(dev, "failed to get lane-count\n");
> +             return ERR_PTR(-EINVAL);
> +     }
> +
> +     return dp_video_config;
> +}
> +
> +int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
> +                  struct analogix_dp_plat_data *plat_data)
> +{
> +     struct platform_device *pdev = to_platform_device(dev);
> +     struct analogix_dp_device *dp;
> +     struct resource *res;
> +     unsigned int irq_flags;
> +     int ret;
> +
> +     if (!plat_data) {
> +             dev_err(dev, "Invalided input plat_data\n");
> +             return -EINVAL;
> +     }
> +
> +     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;
> +
> +     /*
> +      * 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);
> +
> +     dp->phy = devm_phy_get(dp->dev, "dp");
> +     if (IS_ERR(dp->phy)) {
> +             dev_err(dp->dev, "no DP phy configured\n");
> +             ret = PTR_ERR(dp->phy);
> +             if (ret) {
> +                     /*
> +                      * phy itself is not enabled, so we can move forward
> +                      * assigning NULL to phy pointer.
> +                      */
> +                     if (ret == -ENOSYS || ret == -ENODEV)
> +                             dp->phy = NULL;
> +                     else
> +                             return ret;
> +             }
> +     }
> +
> +     dp->clock = devm_clk_get(&pdev->dev, "dp");
> +     if (IS_ERR(dp->clock)) {
> +             dev_err(&pdev->dev, "failed to get clock\n");
> +             return PTR_ERR(dp->clock);
> +     }
> +
> +     clk_prepare_enable(dp->clock);
> +
> +     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +     dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
> +     if (IS_ERR(dp->reg_base))
> +             return PTR_ERR(dp->reg_base);
> +
> +     dp->hpd_gpio = of_get_named_gpio(dev->of_node, "hpd-gpios", 0);
> +     if (!gpio_is_valid(dp->hpd_gpio))
> +             dp->hpd_gpio = of_get_named_gpio(dev->of_node,
> +                                              "samsung,hpd-gpio", 0);
> +
> +     if (gpio_is_valid(dp->hpd_gpio)) {
> +             /*
> +              * Set up the hotplug GPIO from the device tree as an interrupt.
> +              * Simply specifying a different interrupt in the device tree
> +              * doesn't work since we handle hotplug rather differently when
> +              * using a GPIO.  We also need the actual GPIO specifier so
> +              * that we can get the current state of the GPIO.
> +              */
> +             ret = devm_gpio_request_one(&pdev->dev, dp->hpd_gpio, GPIOF_IN,
> +                                         "hpd_gpio");
> +             if (ret) {
> +                     dev_err(&pdev->dev, "failed to get hpd gpio\n");
> +                     return ret;
> +             }
> +             dp->irq = gpio_to_irq(dp->hpd_gpio);
> +             irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
> +     } else {
> +             dp->hpd_gpio = -ENODEV;
> +             dp->irq = platform_get_irq(pdev, 0);
> +             irq_flags = 0;
> +     }
> +
> +     if (dp->irq == -ENXIO) {
> +             dev_err(&pdev->dev, "failed to get irq\n");
> +             return -ENODEV;
> +     }
> +
> +     INIT_WORK(&dp->hotplug_work, analogix_dp_hotplug);
> +
> +     pm_runtime_enable(dev);
> +
> +     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");
> +             goto err_disable_pm_runtime;
> +     }
> +     disable_irq(dp->irq);
> +
> +     dp->drm_dev = drm_dev;
> +     dp->encoder = dp->plat_data->encoder;
> +
> +     ret = analogix_dp_create_bridge(drm_dev, dp);
> +     if (ret) {
> +             DRM_ERROR("failed to create bridge (%d)\n", ret);
> +             drm_encoder_cleanup(dp->encoder);
> +             goto err_disable_pm_runtime;
> +     }
> +
> +     return 0;
> +
> +err_disable_pm_runtime:
> +     pm_runtime_disable(dev);
> +
> +     return ret;
> +}
> +EXPORT_SYMBOL_GPL(analogix_dp_bind);
> +
> +void analogix_dp_unbind(struct device *dev, struct device *master,
> +                     void *data)
> +{
> +     struct analogix_dp_device *dp = dev_get_drvdata(dev);
> +
> +     analogix_dp_bridge_disable(dp->bridge);
> +     pm_runtime_disable(dev);
> +}
> +EXPORT_SYMBOL_GPL(analogix_dp_unbind);
> +
> +#ifdef CONFIG_PM
> +int analogix_dp_suspend(struct device *dev)
> +{
> +     struct analogix_dp_device *dp = dev_get_drvdata(dev);
> +
> +     clk_disable_unprepare(dp->clock);
> +     return 0;
> +}
> +EXPORT_SYMBOL_GPL(analogix_dp_suspend);
> +
> +int analogix_dp_resume(struct device *dev)
> +{
> +     struct analogix_dp_device *dp = dev_get_drvdata(dev);
> +     int ret;
> +
> +     ret = clk_prepare_enable(dp->clock);
> +     if (ret < 0) {
> +             DRM_ERROR("Failed to prepare_enable the clock clk [%d]\n", ret);
> +             return ret;
> +     }
> +
> +     return 0;
> +}
> +EXPORT_SYMBOL_GPL(analogix_dp_resume);
> +#endif
> +
> +MODULE_AUTHOR("Jingoo Han <jg1.han at samsung.com>");
> +MODULE_DESCRIPTION("Analogix DP Core Driver");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h 
> b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
> new file mode 100644
> index 0000000..0fff745
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
> @@ -0,0 +1,277 @@
> +/*
> + * Header file for Analogix DP (Display Port) core interface driver.
> + *
> + * Copyright (C) 2012 Samsung Electronics Co., Ltd.
> + * Author: Jingoo Han <jg1.han at samsung.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>
> +
> +#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 drm_encoder      *encoder;
> +     struct device           *dev;
> +     struct drm_device       *drm_dev;
> +     struct drm_connector    connector;
> +     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;
> +};
> +
> +/* 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/analogix_dp_reg.c 
> b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
> new file mode 100644
> index 0000000..0b926ea
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
> @@ -0,0 +1,1263 @@
> +/*
> + * Analogix DP (Display port) core register interface driver.
> + *
> + * Copyright (C) 2012 Samsung Electronics Co., Ltd.
> + * Author: Jingoo Han <jg1.han at samsung.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 + EXYNOS_DP_VIDEO_CTL_1);
> +             reg |= HDCP_VIDEO_MUTE;
> +             writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> +     } else {
> +             reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> +             reg &= ~HDCP_VIDEO_MUTE;
> +             writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> +     }
> +}
> +
> +void analogix_dp_stop_video(struct analogix_dp_device *dp)
> +{
> +     u32 reg;
> +
> +     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> +     reg &= ~VIDEO_EN;
> +     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_ANALOG_CTL_1);
> +
> +     reg = SEL_24M | TX_DVDD_BIT_1_0625V;
> +     writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2);
> +
> +     reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
> +     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_INT_CTL);
> +
> +     /* Clear pending regisers */
> +     writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
> +     writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2);
> +     writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3);
> +     writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
> +     writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA);
> +
> +     /* 0:mask,1: unmask */
> +     writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
> +     writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
> +     writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
> +     writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
> +     writel(0x00, dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_FUNC_EN_2);
> +
> +     usleep_range(20, 30);
> +
> +     analogix_dp_lane_swap(dp, 0);
> +
> +     writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
> +     writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
> +     writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> +     writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> +
> +     writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL);
> +     writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL);
> +
> +     writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L);
> +     writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H);
> +
> +     writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL);
> +
> +     writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST);
> +
> +     writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD);
> +     writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN);
> +
> +     writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH);
> +     writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
> +
> +     writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> +}
> +
> +void analogix_dp_swreset(struct analogix_dp_device *dp)
> +{
> +     writel(RESET_DP_TX, dp->reg_base + EXYNOS_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 + EXYNOS_DP_COMMON_INT_MASK_1);
> +
> +     reg = COMMON_INT_MASK_2;
> +     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
> +
> +     reg = COMMON_INT_MASK_3;
> +     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
> +
> +     reg = COMMON_INT_MASK_4;
> +     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
> +
> +     reg = INT_STA_MASK;
> +     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_PLL_CTL);
> +             reg |= DP_PLL_PD;
> +             writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
> +     } else {
> +             reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
> +             reg &= ~DP_PLL_PD;
> +             writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_PHY_PD);
> +                     reg |= AUX_PD;
> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +             } else {
> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +                     reg &= ~AUX_PD;
> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +             }
> +             break;
> +     case CH0_BLOCK:
> +             if (enable) {
> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +                     reg |= CH0_PD;
> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +             } else {
> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +                     reg &= ~CH0_PD;
> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +             }
> +             break;
> +     case CH1_BLOCK:
> +             if (enable) {
> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +                     reg |= CH1_PD;
> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +             } else {
> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +                     reg &= ~CH1_PD;
> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +             }
> +             break;
> +     case CH2_BLOCK:
> +             if (enable) {
> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +                     reg |= CH2_PD;
> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +             } else {
> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +                     reg &= ~CH2_PD;
> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +             }
> +             break;
> +     case CH3_BLOCK:
> +             if (enable) {
> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +                     reg |= CH3_PD;
> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +             } else {
> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +                     reg &= ~CH3_PD;
> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +             }
> +             break;
> +     case ANALOG_TOTAL:
> +             if (enable) {
> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +                     reg |= DP_PHY_PD;
> +                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> +             } else {
> +                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> +                     reg &= ~DP_PHY_PD;
> +                     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_PHY_PD);
> +             } else {
> +                     writel(0x00, dp->reg_base + EXYNOS_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 + EXYNOS_DP_COMMON_INT_STA_1);
> +
> +     reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
> +     reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
> +     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_COMMON_INT_STA_4);
> +
> +     reg = INT_HPD;
> +     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_SYS_CTL_3);
> +     reg &= ~(F_HPD | HPD_CTRL);
> +     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_FUNC_EN_2);
> +     reg |= AUX_FUNC_EN_N;
> +     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_AUX_CH_DEFER_CTL);
> +
> +     /* Enable AUX channel module */
> +     reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> +     reg &= ~AUX_FUNC_EN_N;
> +     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_FUNC_EN_1);
> +     reg &= ~SW_FUNC_EN_N;
> +     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_AUX_CH_CTL_2);
> +     reg |= AUX_EN;
> +     writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
> +
> +     /* Is AUX CH command reply received? */
> +     reg = readl(dp->reg_base + EXYNOS_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 + EXYNOS_DP_INT_STA);
> +             usleep_range(10, 11);
> +     }
> +
> +     /* Clear interrupt source for AUX CH command reply */
> +     writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
> +
> +     /* Clear interrupt source for AUX CH access error */
> +     reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
> +     if (reg & AUX_ERR) {
> +             writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA);
> +             return -EREMOTEIO;
> +     }
> +
> +     /* Check AUX CH error access status */
> +     reg = readl(dp->reg_base + EXYNOS_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 + EXYNOS_DP_BUFFER_DATA_CTL);
> +
> +             /* Select DPCD device address */
> +             reg = AUX_ADDR_7_0(reg_addr);
> +             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
> +             reg = AUX_ADDR_15_8(reg_addr);
> +             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> +             reg = AUX_ADDR_19_16(reg_addr);
> +             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
> +
> +             /* Write data buffer */
> +             reg = (unsigned int)data;
> +             writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_AUX_CH_CTL_1);
> +
> +             /* Start AUX transaction */
> +             retval = analogix_dp_start_aux_transaction(dp);
> +             if (retval == 0)
> +                     break;
> +             else
> +                     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 + EXYNOS_DP_BUFFER_DATA_CTL);
> +
> +             /* Select DPCD device address */
> +             reg = AUX_ADDR_7_0(reg_addr);
> +             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
> +             reg = AUX_ADDR_15_8(reg_addr);
> +             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> +             reg = AUX_ADDR_19_16(reg_addr);
> +             writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_AUX_CH_CTL_1);
> +
> +             /* Start AUX transaction */
> +             retval = analogix_dp_start_aux_transaction(dp);
> +             if (retval == 0)
> +                     break;
> +             else
> +                     dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
> +                             __func__);
> +     }
> +
> +     /* Read data buffer */
> +     reg = readl(dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_AUX_ADDR_7_0);
> +                     reg = AUX_ADDR_15_8(reg_addr + start_offset);
> +                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> +                     reg = AUX_ADDR_19_16(reg_addr + start_offset);
> +                     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_AUX_CH_CTL_1);
> +
> +                     /* Start AUX transaction */
> +                     retval = analogix_dp_start_aux_transaction(dp);
> +                     if (retval == 0)
> +                             break;
> +                     else
> +                             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 + EXYNOS_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 + EXYNOS_DP_AUX_ADDR_7_0);
> +                     reg = AUX_ADDR_15_8(reg_addr + start_offset);
> +                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> +                     reg = AUX_ADDR_19_16(reg_addr + start_offset);
> +                     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_AUX_CH_CTL_1);
> +
> +                     /* Start AUX transaction */
> +                     retval = analogix_dp_start_aux_transaction(dp);
> +                     if (retval == 0)
> +                             break;
> +                     else
> +                             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 + EXYNOS_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 + EXYNOS_DP_AUX_ADDR_7_0);
> +     writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> +     writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
> +
> +     /* Set offset from base address of EDID device */
> +     writel(reg_addr, dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_AUX_CH_CTL_1);
> +
> +             /* Start AUX transaction */
> +             retval = analogix_dp_start_aux_transaction(dp);
> +             if (retval == 0)
> +                     break;
> +             else
> +                     dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
> +                             __func__);
> +     }
> +
> +     /* Read data */
> +     if (retval == 0)
> +             *data = readl(dp->reg_base + EXYNOS_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 + EXYNOS_DP_BUFFER_DATA_CTL);
> +
> +                     /* Set normal AUX CH command */
> +                     reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
> +                     reg &= ~ADDR_ONLY;
> +                     writel(reg, dp->reg_base + EXYNOS_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 +
> +                                     EXYNOS_DP_AUX_CH_CTL_1);
> +
> +                             /* Start AUX transaction */
> +                             retval = analogix_dp_start_aux_transaction(dp);
> +                             if (retval == 0)
> +                                     break;
> +                             else
> +                                     dev_dbg(dp->dev,
> +                                             "%s: Aux Transaction fail!\n",
> +                                             __func__);
> +                     }
> +                     /* Check if Rx sends defer */
> +                     reg = readl(dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_LINK_BW_SET);
> +}
> +
> +void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 
> *bwtype)
> +{
> +     u32 reg;
> +
> +     reg = readl(dp->reg_base + EXYNOS_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 + EXYNOS_DP_LANE_COUNT_SET);
> +}
> +
> +void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count)
> +{
> +     u32 reg;
> +
> +     reg = readl(dp->reg_base + EXYNOS_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 + EXYNOS_DP_SYS_CTL_4);
> +             reg |= ENHANCED;
> +             writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> +     } else {
> +             reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> +             reg &= ~ENHANCED;
> +             writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_TRAINING_PTN_SET);
> +             break;
> +     case D10_2:
> +             reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
> +             writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> +             break;
> +     case TRAINING_PTN1:
> +             reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
> +             writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> +             break;
> +     case TRAINING_PTN2:
> +             reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
> +             writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
> +     reg &= ~PRE_EMPHASIS_SET_MASK;
> +     reg |= level << PRE_EMPHASIS_SET_SHIFT;
> +     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
> +     reg &= ~PRE_EMPHASIS_SET_MASK;
> +     reg |= level << PRE_EMPHASIS_SET_SHIFT;
> +     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
> +     reg &= ~PRE_EMPHASIS_SET_MASK;
> +     reg |= level << PRE_EMPHASIS_SET_SHIFT;
> +     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
> +     reg &= ~PRE_EMPHASIS_SET_MASK;
> +     reg |= level << PRE_EMPHASIS_SET_SHIFT;
> +     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
> +}
> +
> +u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp)
> +{
> +     u32 reg;
> +
> +     reg = readl(dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
> +     return reg;
> +}
> +
> +void analogix_dp_reset_macro(struct analogix_dp_device *dp)
> +{
> +     u32 reg;
> +
> +     reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST);
> +     reg |= MACRO_RST;
> +     writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
> +
> +     /* 10 us is the minimum reset time. */
> +     usleep_range(10, 20);
> +
> +     reg &= ~MACRO_RST;
> +     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_COMMON_INT_STA_1);
> +
> +     reg = 0x0;
> +     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
> +
> +     reg = CHA_CRI(4) | CHA_CTRL;
> +     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
> +
> +     reg = 0x0;
> +     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> +
> +     reg = VID_HRES_TH(2) | VID_VRES_TH(0);
> +     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_VIDEO_CTL_2);
> +
> +     /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
> +     reg = readl(dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_SYS_CTL_1);
> +     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
> +
> +     reg = readl(dp->reg_base + EXYNOS_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 + EXYNOS_DP_SYS_CTL_2);
> +     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
> +
> +     reg = readl(dp->reg_base + EXYNOS_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 + EXYNOS_DP_SYS_CTL_4);
> +             reg |= FIX_M_VID;
> +             writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> +             reg = m_value & 0xff;
> +             writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0);
> +             reg = (m_value >> 8) & 0xff;
> +             writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1);
> +             reg = (m_value >> 16) & 0xff;
> +             writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2);
> +
> +             reg = n_value & 0xff;
> +             writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0);
> +             reg = (n_value >> 8) & 0xff;
> +             writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1);
> +             reg = (n_value >> 16) & 0xff;
> +             writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2);
> +     } else  {
> +             reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> +             reg &= ~FIX_M_VID;
> +             writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> +
> +             writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0);
> +             writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1);
> +             writel(0x00, dp->reg_base + EXYNOS_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 + EXYNOS_DP_VIDEO_CTL_10);
> +             reg &= ~FORMAT_SEL;
> +             writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +     } else {
> +             reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +             reg |= FORMAT_SEL;
> +             writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_SOC_GENERAL_CTL);
> +             reg &= ~VIDEO_MODE_MASK;
> +             reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
> +             writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> +     } else {
> +             reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> +             reg &= ~VIDEO_MODE_MASK;
> +             reg |= VIDEO_MODE_SLAVE_MODE;
> +             writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> +     }
> +}
> +
> +void analogix_dp_start_video(struct analogix_dp_device *dp)
> +{
> +     u32 reg;
> +
> +     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> +     reg |= VIDEO_EN;
> +     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> +}
> +
> +int analogix_dp_is_video_stream_on(struct analogix_dp_device *dp)
> +{
> +     u32 reg;
> +
> +     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> +     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> +
> +     reg = readl(dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_FUNC_EN_1);
> +
> +     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +     reg &= ~INTERACE_SCAN_CFG;
> +     reg |= (dp->video_info->interlaced << 2);
> +     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +
> +     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +     reg &= ~VSYNC_POLARITY_CFG;
> +     reg |= (dp->video_info->v_sync_polarity << 1);
> +     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +
> +     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +     reg &= ~HSYNC_POLARITY_CFG;
> +     reg |= (dp->video_info->h_sync_polarity << 0);
> +     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> +
> +     reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
> +     writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> +}
> +
> +void analogix_dp_enable_scrambling(struct analogix_dp_device *dp)
> +{
> +     u32 reg;
> +
> +     reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> +     reg &= ~SCRAMBLING_DISABLE;
> +     writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> +}
> +
> +void analogix_dp_disable_scrambling(struct analogix_dp_device *dp)
> +{
> +     u32 reg;
> +
> +     reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> +     reg |= SCRAMBLING_DISABLE;
> +     writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> +}
> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h 
> b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
> new file mode 100644
> index 0000000..b9661c9
> --- /dev/null
> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
> @@ -0,0 +1,366 @@
> +/*
> + * Register definition file for Analogix DP core driver
> + *
> + * Copyright (C) 2012 Samsung Electronics Co., Ltd.
> + * Author: Jingoo Han <jg1.han at samsung.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 _ANALOGIX_DP_REG_H
> +#define _ANALOGIX_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 */
> +#define RESET_DP_TX                          (0x1 << 0)
> +
> +/* EXYNOS_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)
> +#define AUD_FUNC_EN_N                                (0x1 << 3)
> +#define HDCP_FUNC_EN_N                               (0x1 << 2)
> +#define CRC_FUNC_EN_N                                (0x1 << 1)
> +#define SW_FUNC_EN_N                         (0x1 << 0)
> +
> +/* EXYNOS_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 */
> +#define VIDEO_EN                             (0x1 << 7)
> +#define HDCP_VIDEO_MUTE                              (0x1 << 6)
> +
> +/* EXYNOS_DP_VIDEO_CTL_1 */
> +#define IN_D_RANGE_MASK                              (0x1 << 7)
> +#define IN_D_RANGE_SHIFT                     (7)
> +#define IN_D_RANGE_CEA                               (0x1 << 7)
> +#define IN_D_RANGE_VESA                              (0x0 << 7)
> +#define IN_BPC_MASK                          (0x7 << 4)
> +#define IN_BPC_SHIFT                         (4)
> +#define IN_BPC_12_BITS                               (0x3 << 4)
> +#define IN_BPC_10_BITS                               (0x2 << 4)
> +#define IN_BPC_8_BITS                                (0x1 << 4)
> +#define IN_BPC_6_BITS                                (0x0 << 4)
> +#define IN_COLOR_F_MASK                              (0x3 << 0)
> +#define IN_COLOR_F_SHIFT                     (0)
> +#define IN_COLOR_F_YCBCR444                  (0x2 << 0)
> +#define IN_COLOR_F_YCBCR422                  (0x1 << 0)
> +#define IN_COLOR_F_RGB                               (0x0 << 0)
> +
> +/* EXYNOS_DP_VIDEO_CTL_3 */
> +#define IN_YC_COEFFI_MASK                    (0x1 << 7)
> +#define IN_YC_COEFFI_SHIFT                   (7)
> +#define IN_YC_COEFFI_ITU709                  (0x1 << 7)
> +#define IN_YC_COEFFI_ITU601                  (0x0 << 7)
> +#define VID_CHK_UPDATE_TYPE_MASK             (0x1 << 4)
> +#define VID_CHK_UPDATE_TYPE_SHIFT            (4)
> +#define VID_CHK_UPDATE_TYPE_1                        (0x1 << 4)
> +#define VID_CHK_UPDATE_TYPE_0                        (0x0 << 4)
> +
> +/* EXYNOS_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 */
> +#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 */
> +#define LANE3_MAP_LOGIC_LANE_0                       (0x0 << 6)
> +#define LANE3_MAP_LOGIC_LANE_1                       (0x1 << 6)
> +#define LANE3_MAP_LOGIC_LANE_2                       (0x2 << 6)
> +#define LANE3_MAP_LOGIC_LANE_3                       (0x3 << 6)
> +#define LANE2_MAP_LOGIC_LANE_0                       (0x0 << 4)
> +#define LANE2_MAP_LOGIC_LANE_1                       (0x1 << 4)
> +#define LANE2_MAP_LOGIC_LANE_2                       (0x2 << 4)
> +#define LANE2_MAP_LOGIC_LANE_3                       (0x3 << 4)
> +#define LANE1_MAP_LOGIC_LANE_0                       (0x0 << 2)
> +#define LANE1_MAP_LOGIC_LANE_1                       (0x1 << 2)
> +#define LANE1_MAP_LOGIC_LANE_2                       (0x2 << 2)
> +#define LANE1_MAP_LOGIC_LANE_3                       (0x3 << 2)
> +#define LANE0_MAP_LOGIC_LANE_0                       (0x0 << 0)
> +#define LANE0_MAP_LOGIC_LANE_1                       (0x1 << 0)
> +#define LANE0_MAP_LOGIC_LANE_2                       (0x2 << 0)
> +#define LANE0_MAP_LOGIC_LANE_3                       (0x3 << 0)
> +
> +/* EXYNOS_DP_ANALOG_CTL_1 */
> +#define TX_TERMINAL_CTRL_50_OHM                      (0x1 << 4)
> +
> +/* EXYNOS_DP_ANALOG_CTL_2 */
> +#define SEL_24M                                      (0x1 << 3)
> +#define TX_DVDD_BIT_1_0625V                  (0x4 << 0)
> +
> +/* EXYNOS_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 */
> +#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 */
> +#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 */
> +#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)
> +#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS       (0x1 << 3)
> +#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS      (0x2 << 3)
> +#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 */
> +#define VSYNC_DET                            (0x1 << 7)
> +#define PLL_LOCK_CHG                         (0x1 << 6)
> +#define SPDIF_ERR                            (0x1 << 5)
> +#define SPDIF_UNSTBL                         (0x1 << 4)
> +#define VID_FORMAT_CHG                               (0x1 << 3)
> +#define AUD_CLK_CHG                          (0x1 << 2)
> +#define VID_CLK_CHG                          (0x1 << 1)
> +#define SW_INT                                       (0x1 << 0)
> +
> +/* EXYNOS_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 */
> +#define AFIFO_UNDER                          (0x1 << 7)
> +#define AFIFO_OVER                           (0x1 << 6)
> +#define R0_CHK_FLAG                          (0x1 << 5)
> +
> +/* EXYNOS_DP_COMMON_INT_STA_4 */
> +#define PSR_ACTIVE                           (0x1 << 7)
> +#define PSR_INACTIVE                         (0x1 << 6)
> +#define SPDIF_BI_PHASE_ERR                   (0x1 << 5)
> +#define HOTPLUG_CHG                          (0x1 << 2)
> +#define HPD_LOST                             (0x1 << 1)
> +#define PLUG                                 (0x1 << 0)
> +
> +/* EXYNOS_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 */
> +#define SOFT_INT_CTRL                                (0x1 << 2)
> +#define INT_POL1                             (0x1 << 1)
> +#define INT_POL0                             (0x1 << 0)
> +
> +/* EXYNOS_DP_SYS_CTL_1 */
> +#define DET_STA                                      (0x1 << 2)
> +#define FORCE_DET                            (0x1 << 1)
> +#define DET_CTRL                             (0x1 << 0)
> +
> +/* EXYNOS_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 */
> +#define HPD_STATUS                           (0x1 << 6)
> +#define F_HPD                                        (0x1 << 5)
> +#define HPD_CTRL                             (0x1 << 4)
> +#define HDCP_RDY                             (0x1 << 3)
> +#define STRM_VALID                           (0x1 << 2)
> +#define F_VALID                                      (0x1 << 1)
> +#define VALID_CTRL                           (0x1 << 0)
> +
> +/* EXYNOS_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 */
> +#define SCRAMBLER_TYPE                               (0x1 << 9)
> +#define HW_LINK_TRAINING_PATTERN             (0x1 << 8)
> +#define SCRAMBLING_DISABLE                   (0x1 << 5)
> +#define SCRAMBLING_ENABLE                    (0x0 << 5)
> +#define LINK_QUAL_PATTERN_SET_MASK           (0x3 << 2)
> +#define LINK_QUAL_PATTERN_SET_PRBS7          (0x3 << 2)
> +#define LINK_QUAL_PATTERN_SET_D10_2          (0x1 << 2)
> +#define LINK_QUAL_PATTERN_SET_DISABLE                (0x0 << 2)
> +#define SW_TRAINING_PATTERN_SET_MASK         (0x3 << 0)
> +#define SW_TRAINING_PATTERN_SET_PTN2         (0x2 << 0)
> +#define SW_TRAINING_PATTERN_SET_PTN1         (0x1 << 0)
> +#define SW_TRAINING_PATTERN_SET_NORMAL               (0x0 << 0)
> +
> +/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
> +#define PRE_EMPHASIS_SET_MASK                        (0x3 << 3)
> +#define PRE_EMPHASIS_SET_SHIFT                       (3)
> +
> +/* EXYNOS_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 */
> +#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 */
> +#define DP_PHY_PD                            (0x1 << 5)
> +#define AUX_PD                                       (0x1 << 4)
> +#define CH3_PD                                       (0x1 << 3)
> +#define CH2_PD                                       (0x1 << 2)
> +#define CH1_PD                                       (0x1 << 1)
> +#define CH0_PD                                       (0x1 << 0)
> +
> +/* EXYNOS_DP_PHY_TEST */
> +#define MACRO_RST                            (0x1 << 5)
> +#define CH1_TEST                             (0x1 << 1)
> +#define CH0_TEST                             (0x1 << 0)
> +
> +/* EXYNOS_DP_AUX_CH_STA */
> +#define AUX_BUSY                             (0x1 << 4)
> +#define AUX_STATUS_MASK                              (0xf << 0)
> +
> +/* EXYNOS_DP_AUX_CH_DEFER_CTL */
> +#define DEFER_CTRL_EN                                (0x1 << 7)
> +#define DEFER_COUNT(x)                               (((x) & 0x7f) << 0)
> +
> +/* EXYNOS_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 */
> +#define BUF_CLR                                      (0x1 << 7)
> +#define BUF_DATA_COUNT(x)                    (((x) & 0x1f) << 0)
> +
> +/* EXYNOS_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)
> +#define AUX_TX_COMM_I2C_TRANSACTION          (0x0 << 3)
> +#define AUX_TX_COMM_MOT                              (0x1 << 2)
> +#define AUX_TX_COMM_WRITE                    (0x0 << 0)
> +#define AUX_TX_COMM_READ                     (0x1 << 0)
> +
> +/* EXYNOS_DP_AUX_ADDR_7_0 */
> +#define AUX_ADDR_7_0(x)                              (((x) >> 0) & 0xff)
> +
> +/* EXYNOS_DP_AUX_ADDR_15_8 */
> +#define AUX_ADDR_15_8(x)                     (((x) >> 8) & 0xff)
> +
> +/* EXYNOS_DP_AUX_ADDR_19_16 */
> +#define AUX_ADDR_19_16(x)                    (((x) >> 16) & 0x0f)
> +
> +/* EXYNOS_DP_AUX_CH_CTL_2 */
> +#define ADDR_ONLY                            (0x1 << 1)
> +#define AUX_EN                                       (0x1 << 0)
> +
> +/* EXYNOS_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)
> +#define VIDEO_MASTER_CLK_SEL                 (0x1 << 2)
> +#define VIDEO_MASTER_MODE_EN                 (0x1 << 1)
> +#define VIDEO_MODE_MASK                              (0x1 << 0)
> +#define VIDEO_MODE_SLAVE_MODE                        (0x1 << 0)
> +#define VIDEO_MODE_MASTER_MODE                       (0x0 << 0)
> +
> +#endif /* _ANALOGIX_DP_REG_H */
> diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
> index f17d392..2fadd82 100644
> --- a/drivers/gpu/drm/exynos/Kconfig
> +++ b/drivers/gpu/drm/exynos/Kconfig
> @@ -71,8 +71,9 @@ config DRM_EXYNOS_DSI
>         This enables support for Exynos MIPI-DSI device.
>   
>   config DRM_EXYNOS_DP
> -     bool "Display Port"
> +     bool "EXYNOS specific extensions for Analogix DP driver"
>       depends on DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON
> +     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 968b31c..2bdd949 100644
> --- a/drivers/gpu/drm/exynos/Makefile
> +++ b/drivers/gpu/drm/exynos/Makefile
> @@ -12,7 +12,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_DP)    += exynos_dp_core.o
>   exynosdrm-$(CONFIG_DRM_EXYNOS_MIXER)        += exynos_mixer.o
>   exynosdrm-$(CONFIG_DRM_EXYNOS_HDMI) += exynos_hdmi.o
>   exynosdrm-$(CONFIG_DRM_EXYNOS_VIDI) += exynos_drm_vidi.o
> diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c 
> b/drivers/gpu/drm/exynos/exynos_dp_core.c
> index cff8dc7..8456794 100644
> --- a/drivers/gpu/drm/exynos/exynos_dp_core.c
> +++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
> @@ -14,967 +14,76 @@
>   #include <linux/platform_device.h>
>   #include <linux/err.h>
>   #include <linux/clk.h>
> -#include <linux/io.h>
> -#include <linux/interrupt.h>
> -#include <linux/of.h>
> -#include <linux/of_gpio.h>
>   #include <linux/of_graph.h>
> -#include <linux/gpio.h>
>   #include <linux/component.h>
> -#include <linux/phy/phy.h>
>   #include <video/of_display_timing.h>
>   #include <video/of_videomode.h>
> +#include <video/videomode.h>
>   
>   #include <drm/drmP.h>
>   #include <drm/drm_crtc.h>
>   #include <drm/drm_crtc_helper.h>
> -#include <drm/drm_atomic_helper.h>
>   #include <drm/drm_panel.h>
>   
> -#include "exynos_dp_core.h"
> +#include <drm/bridge/analogix_dp.h>
> +#include <drm/exynos_drm.h>
> +
>   #include "exynos_drm_crtc.h"
>   
> -#define ctx_from_connector(c)        container_of(c, struct 
> exynos_dp_device, \
> -                                     connector)
> +#define to_dp(nm)    container_of(nm, struct exynos_dp_device, nm)
>   
> -static inline struct exynos_drm_crtc *dp_to_crtc(struct exynos_dp_device *dp)
> -{
> -     return to_exynos_crtc(dp->encoder.crtc);
> -}
> +struct exynos_dp_device {
> +     struct drm_encoder         encoder;
> +     struct drm_connector       connector;
> +     struct drm_bridge          *ptn_bridge;
> +     struct drm_device          *drm_dev;
> +     struct device              *dev;
>   
> -static inline struct exynos_dp_device *encoder_to_dp(
> -                                             struct drm_encoder *e)
> -{
> -     return container_of(e, struct exynos_dp_device, encoder);
> -}
> -
> -struct bridge_init {
> -     struct i2c_client *client;
> -     struct device_node *node;
> +     struct videomode           vm;
> +     struct analogix_dp_plat_data plat_data;
>   };
>   
> -static void exynos_dp_init_dp(struct exynos_dp_device *dp)
> -{
> -     exynos_dp_reset(dp);
> -
> -     exynos_dp_swreset(dp);
> -
> -     exynos_dp_init_analog_param(dp);
> -     exynos_dp_init_interrupt(dp);
> -
> -     /* SW defined function Normal operation */
> -     exynos_dp_enable_sw_function(dp);
> -
> -     exynos_dp_config_interrupt(dp);
> -     exynos_dp_init_analog_func(dp);
> -
> -     exynos_dp_init_hpd(dp);
> -     exynos_dp_init_aux(dp);
> -}
> -
> -static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
> -{
> -     int timeout_loop = 0;
> -
> -     while (exynos_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");
> -                     return -ETIMEDOUT;
> -             }
> -             usleep_range(10, 11);
> -     }
> -
> -     return 0;
> -}
> -
> -static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data)
> -{
> -     int i;
> -     unsigned char sum = 0;
> -
> -     for (i = 0; i < EDID_BLOCK_LENGTH; i++)
> -             sum = sum + edid_data[i];
> -
> -     return sum;
> -}
> -
> -static int exynos_dp_read_edid(struct exynos_dp_device *dp)
> -{
> -     unsigned char edid[EDID_BLOCK_LENGTH * 2];
> -     unsigned int extend_block = 0;
> -     unsigned char sum;
> -     unsigned char test_vector;
> -     int retval;
> -
> -     /*
> -      * EDID device address is 0x50.
> -      * However, if necessary, you must have set upper address
> -      * into E-EDID in I2C device, 0x30.
> -      */
> -
> -     /* 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);
> -     if (retval)
> -             return retval;
> -
> -     if (extend_block > 0) {
> -             dev_dbg(dp->dev, "EDID data includes a single extension!\n");
> -
> -             /* 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]);
> -             if (retval != 0) {
> -                     dev_err(dp->dev, "EDID Read failed!\n");
> -                     return -EIO;
> -             }
> -             sum = exynos_dp_calc_edid_check_sum(edid);
> -             if (sum != 0) {
> -                     dev_err(dp->dev, "EDID bad checksum!\n");
> -                     return -EIO;
> -             }
> -
> -             /* 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]);
> -             if (retval != 0) {
> -                     dev_err(dp->dev, "EDID Read failed!\n");
> -                     return -EIO;
> -             }
> -             sum = exynos_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);
> -             if (test_vector & DP_TEST_LINK_EDID_READ) {
> -                     exynos_dp_write_byte_to_dpcd(dp,
> -                             DP_TEST_EDID_CHECKSUM,
> -                             edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
> -                     exynos_dp_write_byte_to_dpcd(dp,
> -                             DP_TEST_RESPONSE,
> -                             DP_TEST_EDID_CHECKSUM_WRITE);
> -             }
> -     } else {
> -             dev_info(dp->dev, "EDID data does not include any 
> extensions.\n");
> -
> -             /* 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]);
> -             if (retval != 0) {
> -                     dev_err(dp->dev, "EDID Read failed!\n");
> -                     return -EIO;
> -             }
> -             sum = exynos_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);
> -             if (test_vector & DP_TEST_LINK_EDID_READ) {
> -                     exynos_dp_write_byte_to_dpcd(dp,
> -                             DP_TEST_EDID_CHECKSUM,
> -                             edid[EDID_CHECKSUM]);
> -                     exynos_dp_write_byte_to_dpcd(dp,
> -                             DP_TEST_RESPONSE,
> -                             DP_TEST_EDID_CHECKSUM_WRITE);
> -             }
> -     }
> -
> -     dev_dbg(dp->dev, "EDID Read success!\n");
> -     return 0;
> -}
> -
> -static int exynos_dp_handle_edid(struct exynos_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);
> -     if (retval)
> -             return retval;
> -
> -     /* Read EDID */
> -     for (i = 0; i < 3; i++) {
> -             retval = exynos_dp_read_edid(dp);
> -             if (!retval)
> -                     break;
> -     }
> -
> -     return retval;
> -}
> -
> -static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device *dp,
> -                                             bool enable)
> -{
> -     u8 data;
> -
> -     exynos_dp_read_byte_from_dpcd(dp, DP_LANE_COUNT_SET, &data);
> -
> -     if (enable)
> -             exynos_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(dp, DP_LANE_COUNT_SET,
> -                     DPCD_LANE_COUNT_SET(data));
> -}
> -
> -static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device *dp)
> -{
> -     u8 data;
> -     int retval;
> -
> -     exynos_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)
> -{
> -     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);
> -}
> -
> -static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp)
> -{
> -     exynos_dp_set_training_pattern(dp, DP_NONE);
> -
> -     exynos_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)
> -{
> -     switch (lane) {
> -     case 0:
> -             exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
> -             break;
> -     case 1:
> -             exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
> -             break;
> -
> -     case 2:
> -             exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
> -             break;
> -
> -     case 3:
> -             exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
> -             break;
> -     }
> -}
> -
> -static int exynos_dp_link_start(struct exynos_dp_device *dp)
> -{
> -     u8 buf[4];
> -     int lane, lane_count, pll_tries, retval;
> -
> -     lane_count = dp->link_train.lane_count;
> -
> -     dp->link_train.lt_state = CLOCK_RECOVERY;
> -     dp->link_train.eq_loop = 0;
> -
> -     for (lane = 0; lane < lane_count; lane++)
> -             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);
> -
> -     /* 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);
> -     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);
> -
> -     /* Wait for PLL lock */
> -     pll_tries = 0;
> -     while (exynos_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;
> -             }
> -
> -             pll_tries++;
> -             usleep_range(90, 120);
> -     }
> -
> -     /* Set training pattern 1 */
> -     exynos_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);
> -     if (retval)
> -             return retval;
> -
> -     for (lane = 0; lane < lane_count; lane++)
> -             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);
> -
> -     return retval;
> -}
> -
> -static unsigned char exynos_dp_get_lane_status(u8 link_status[2], int lane)
> -{
> -     int shift = (lane & 1) * 4;
> -     u8 link_value = link_status[lane>>1];
> -
> -     return (link_value >> shift) & 0xf;
> -}
> -
> -static int exynos_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);
> -             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)
> +int exynos_dp_crtc_clock_enable(struct analogix_dp_plat_data *plat_data,
> +                             bool enable)
>   {
> -     int lane;
> -     u8 lane_status;
> +     struct exynos_dp_device *dp = to_dp(plat_data);
> +     struct drm_encoder *encoder = &dp->encoder;
> +     struct exynos_drm_crtc *crtc;
>   
> -     if ((link_align & DP_INTERLANE_ALIGN_DONE) == 0)
> -             return -EINVAL;
> +     if (!encoder)
> +             return -1;
>   
> -     for (lane = 0; lane < lane_count; lane++) {
> -             lane_status = exynos_dp_get_lane_status(link_status, lane);
> -             lane_status &= DP_CHANNEL_EQ_BITS;
> -             if (lane_status != DP_CHANNEL_EQ_BITS)
> -                     return -EINVAL;
> -     }
> +     crtc = to_exynos_crtc(encoder->crtc);
> +     if (crtc && crtc->ops && crtc->ops->clock_enable)
> +             crtc->ops->clock_enable(crtc, enable);
>   
>       return 0;
>   }
>   
> -static unsigned char exynos_dp_get_adjust_request_voltage(u8 
> adjust_request[2],
> -                                                     int lane)
> -{
> -     int shift = (lane & 1) * 4;
> -     u8 link_value = adjust_request[lane>>1];
> -
> -     return (link_value >> shift) & 0x3;
> -}
> -
> -static unsigned char exynos_dp_get_adjust_request_pre_emphasis(
> -                                     u8 adjust_request[2],
> -                                     int lane)
> -{
> -     int shift = (lane & 1) * 4;
> -     u8 link_value = adjust_request[lane>>1];
> -
> -     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)
> -{
> -     switch (lane) {
> -     case 0:
> -             exynos_dp_set_lane0_link_training(dp, training_lane_set);
> -             break;
> -     case 1:
> -             exynos_dp_set_lane1_link_training(dp, training_lane_set);
> -             break;
> -
> -     case 2:
> -             exynos_dp_set_lane2_link_training(dp, training_lane_set);
> -             break;
> -
> -     case 3:
> -             exynos_dp_set_lane3_link_training(dp, training_lane_set);
> -             break;
> -     }
> -}
> -
> -static unsigned int exynos_dp_get_lane_link_training(
> -                             struct exynos_dp_device *dp,
> -                             int lane)
> -{
> -     u32 reg;
> -
> -     switch (lane) {
> -     case 0:
> -             reg = exynos_dp_get_lane0_link_training(dp);
> -             break;
> -     case 1:
> -             reg = exynos_dp_get_lane1_link_training(dp);
> -             break;
> -     case 2:
> -             reg = exynos_dp_get_lane2_link_training(dp);
> -             break;
> -     case 3:
> -             reg = exynos_dp_get_lane3_link_training(dp);
> -             break;
> -     default:
> -             WARN_ON(1);
> -             return 0;
> -     }
> -
> -     return reg;
> -}
> -
> -static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
> -{
> -     exynos_dp_training_pattern_dis(dp);
> -     exynos_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])
> -{
> -     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(
> -                                             adjust_request, lane);
> -             pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
> -                                             adjust_request, lane);
> -             training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
> -                             DPCD_PRE_EMPHASIS_SET(pre_emphasis);
> -
> -             if (voltage_swing == VOLTAGE_LEVEL_3)
> -                     training_lane |= DP_TRAIN_MAX_SWING_REACHED;
> -             if (pre_emphasis == PRE_EMPHASIS_LEVEL_3)
> -                     training_lane |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
> -
> -             dp->link_train.training_lane[lane] = training_lane;
> -     }
> -}
> -
> -static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
> -{
> -     int lane, lane_count, retval;
> -     u8 voltage_swing, pre_emphasis, training_lane;
> -     u8 link_status[2], adjust_request[2];
> -
> -     usleep_range(100, 101);
> -
> -     lane_count = dp->link_train.lane_count;
> -
> -     retval =  exynos_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);
> -     if (retval)
> -             return retval;
> -
> -     if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
> -             /* set training pattern 2 for EQ */
> -             exynos_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);
> -             if (retval)
> -                     return retval;
> -
> -             dev_info(dp->dev, "Link Training Clock Recovery success\n");
> -             dp->link_train.lt_state = EQUALIZER_TRAINING;
> -     } else {
> -             for (lane = 0; lane < lane_count; lane++) {
> -                     training_lane = exynos_dp_get_lane_link_training(
> -                                                     dp, lane);
> -                     voltage_swing = exynos_dp_get_adjust_request_voltage(
> -                                                     adjust_request, lane);
> -                     pre_emphasis = 
> exynos_dp_get_adjust_request_pre_emphasis(
> -                                                     adjust_request, lane);
> -
> -                     if (DPCD_VOLTAGE_SWING_GET(training_lane) ==
> -                                     voltage_swing &&
> -                         DPCD_PRE_EMPHASIS_GET(training_lane) ==
> -                                     pre_emphasis)
> -                             dp->link_train.cr_loop[lane]++;
> -
> -                     if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP ||
> -                         voltage_swing == VOLTAGE_LEVEL_3 ||
> -                         pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
> -                             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);
> -                             return -EIO;
> -                     }
> -             }
> -     }
> -
> -     exynos_dp_get_adjust_training_lane(dp, adjust_request);
> -
> -     for (lane = 0; lane < lane_count; lane++)
> -             exynos_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);
> -     if (retval)
> -             return retval;
> -
> -     return retval;
> -}
> -
> -static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
> -{
> -     int lane, lane_count, retval;
> -     u32 reg;
> -     u8 link_align, link_status[2], adjust_request[2];
> -
> -     usleep_range(400, 401);
> -
> -     lane_count = dp->link_train.lane_count;
> -
> -     retval = exynos_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);
> -             return -EIO;
> -     }
> -
> -     retval = exynos_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(dp,
> -                     DP_LANE_ALIGN_STATUS_UPDATED, &link_align);
> -     if (retval)
> -             return retval;
> -
> -     exynos_dp_get_adjust_training_lane(dp, adjust_request);
> -
> -     if (!exynos_dp_channel_eq_ok(link_status, link_align, lane_count)) {
> -             /* traing pattern Set to Normal */
> -             exynos_dp_training_pattern_dis(dp);
> -
> -             dev_info(dp->dev, "Link Training success!\n");
> -
> -             exynos_dp_get_link_bandwidth(dp, &reg);
> -             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, &reg);
> -             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);
> -             dp->link_train.lt_state = FINISHED;
> -
> -             return 0;
> -     }
> -
> -     /* not all locked */
> -     dp->link_train.eq_loop++;
> -
> -     if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
> -             dev_err(dp->dev, "EQ Max loop\n");
> -             exynos_dp_reduce_link_rate(dp);
> -             return -EIO;
> -     }
> -
> -     for (lane = 0; lane < lane_count; lane++)
> -             exynos_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);
> -
> -     return retval;
> -}
> -
> -static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
> -                                     u8 *bandwidth)
> -{
> -     u8 data;
> -
> -     /*
> -      * 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);
> -     *bandwidth = data;
> -}
> -
> -static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
> -                                     u8 *lane_count)
> -{
> -     u8 data;
> -
> -     /*
> -      * 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);
> -     *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)
> -{
> -     /*
> -      * 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);
> -
> -     /* 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);
> -
> -     if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
> -        (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
> -             dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
> -                     dp->link_train.link_rate);
> -             dp->link_train.link_rate = LINK_RATE_1_62GBPS;
> -     }
> -
> -     if (dp->link_train.lane_count == 0) {
> -             dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
> -                     dp->link_train.lane_count);
> -             dp->link_train.lane_count = (u8)LANE_COUNT1;
> -     }
> -
> -     /* Setup TX lane count & rate */
> -     if (dp->link_train.lane_count > max_lane)
> -             dp->link_train.lane_count = max_lane;
> -     if (dp->link_train.link_rate > max_rate)
> -             dp->link_train.link_rate = max_rate;
> -
> -     /* All DP analog module power up */
> -     exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
> -}
> -
> -static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
> +static int exynos_dp_poweron(struct analogix_dp_plat_data *plat_data)
>   {
> -     int retval = 0, training_finished = 0;
> -
> -     dp->link_train.lt_state = START;
> -
> -     /* Process here */
> -     while (!retval && !training_finished) {
> -             switch (dp->link_train.lt_state) {
> -             case START:
> -                     retval = exynos_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);
> -                     if (retval)
> -                             dev_err(dp->dev, "LT CR failed!\n");
> -                     break;
> -             case EQUALIZER_TRAINING:
> -                     retval = exynos_dp_process_equalizer_training(dp);
> -                     if (retval)
> -                             dev_err(dp->dev, "LT EQ failed!\n");
> -                     break;
> -             case FINISHED:
> -                     training_finished = 1;
> -                     break;
> -             case FAILED:
> -                     return -EREMOTEIO;
> -             }
> -     }
> -     if (retval)
> -             dev_err(dp->dev, "eDP link training failed (%d)\n", retval);
> -
> -     return retval;
> +     return exynos_dp_crtc_clock_enable(plat_data, true);
>   }
>   
> -static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
> -                             u32 count,
> -                             u32 bwtype)
> +static int exynos_dp_poweroff(struct analogix_dp_plat_data *plat_data)
>   {
> -     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);
> -             if (retval == 0)
> -                     break;
> -
> -             usleep_range(100, 110);
> -     }
> -
> -     return retval;
> +     return exynos_dp_crtc_clock_enable(plat_data, false);
>   }
>   
> -static int exynos_dp_config_video(struct exynos_dp_device *dp)
> +static int exynos_dp_get_modes(struct analogix_dp_plat_data *plat_data)
>   {
> -     int retval = 0;
> -     int timeout_loop = 0;
> -     int done_count = 0;
> -
> -     exynos_dp_config_video_slave_mode(dp);
> -
> -     exynos_dp_set_video_color_format(dp);
> -
> -     if (exynos_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)
> -                     break;
> -             if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
> -                     dev_err(dp->dev, "Timeout of video streamclk ok\n");
> -                     return -ETIMEDOUT;
> -             }
> -
> -             usleep_range(1, 2);
> -     }
> -
> -     /* Set to use the register calculated M/N video */
> -     exynos_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);
> -
> -     /* Disable video mute */
> -     exynos_dp_enable_video_mute(dp, 0);
> -
> -     /* Configure video slave mode */
> -     exynos_dp_enable_video_master(dp, 0);
> -
> -     timeout_loop = 0;
> -
> -     for (;;) {
> -             timeout_loop++;
> -             if (exynos_dp_is_video_stream_on(dp) == 0) {
> -                     done_count++;
> -                     if (done_count > 10)
> -                             break;
> -             } else if (done_count) {
> -                     done_count = 0;
> -             }
> -             if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
> -                     dev_err(dp->dev, "Timeout of video streamclk ok\n");
> -                     return -ETIMEDOUT;
> -             }
> -
> -             usleep_range(1000, 1001);
> -     }
> -
> -     if (retval != 0)
> -             dev_err(dp->dev, "Video stream is not detected!\n");
> -
> -     return retval;
> -}
> -
> -static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool 
> enable)
> -{
> -     u8 data;
> -
> -     if (enable) {
> -             exynos_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));
> -     } else {
> -             exynos_dp_disable_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));
> -     }
> -}
> -
> -static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
> -{
> -     struct exynos_dp_device *dp = arg;
> -
> -     enum dp_irq_type irq_type;
> -
> -     irq_type = exynos_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);
> -             break;
> -     case DP_IRQ_TYPE_HP_CABLE_OUT:
> -             dev_dbg(dp->dev, "Received irq - cable out\n");
> -             exynos_dp_clear_hotplug_interrupts(dp);
> -             break;
> -     case DP_IRQ_TYPE_HP_CHANGE:
> -             /*
> -              * We get these change notifications once in a while, but there
> -              * is nothing we can do with them. Just ignore it for now and
> -              * only handle cable changes.
> -              */
> -             dev_dbg(dp->dev, "Received irq - hotplug change; ignoring.\n");
> -             exynos_dp_clear_hotplug_interrupts(dp);
> -             break;
> -     default:
> -             dev_err(dp->dev, "Received irq - unknown type!\n");
> -             break;
> -     }
> -     return IRQ_HANDLED;
> -}
> -
> -static void exynos_dp_hotplug(struct work_struct *work)
> -{
> -     struct exynos_dp_device *dp;
> -
> -     dp = container_of(work, struct exynos_dp_device, hotplug_work);
> -
> -     if (dp->drm_dev)
> -             drm_helper_hpd_irq_event(dp->drm_dev);
> -}
> -
> -static void exynos_dp_commit(struct drm_encoder *encoder)
> -{
> -     struct exynos_dp_device *dp = encoder_to_dp(encoder);
> -     int ret;
> -
> -     /* Keep the panel disabled while we configure video */
> -     if (dp->panel) {
> -             if (drm_panel_disable(dp->panel))
> -                     DRM_ERROR("failed to disable the panel\n");
> -     }
> -
> -     ret = exynos_dp_detect_hpd(dp);
> -     if (ret) {
> -             /* Cable has been disconnected, we're done */
> -             return;
> -     }
> -
> -     ret = exynos_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);
> -     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);
> -
> -     exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
> -     exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
> -
> -     exynos_dp_init_video(dp);
> -     ret = exynos_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))
> -                     DRM_ERROR("failed to enable the panel\n");
> -     }
> -
> -     /* Enable video */
> -     exynos_dp_start_video(dp);
> -}
> -
> -static enum drm_connector_status exynos_dp_detect(
> -                             struct drm_connector *connector, bool force)
> -{
> -     return connector_status_connected;
> -}
> -
> -static void exynos_dp_connector_destroy(struct drm_connector *connector)
> -{
> -     drm_connector_unregister(connector);
> -     drm_connector_cleanup(connector);
> -}
> -
> -static const struct drm_connector_funcs exynos_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,
> -     .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)
> -{
> -     struct exynos_dp_device *dp = ctx_from_connector(connector);
> +     struct exynos_dp_device *dp = to_dp(plat_data);
> +     struct drm_connector *connector = &dp->connector;
>       struct drm_display_mode *mode;
> +     int num_modes = 0;
>   
> -     if (dp->panel)
> -             return drm_panel_get_modes(dp->panel);
> +     if (dp->plat_data.panel)
> +             return num_modes;
>   
>       mode = drm_mode_create(connector->dev);
>       if (!mode) {
>               DRM_ERROR("failed to create a new display mode.\n");
> -             return 0;
> +             return num_modes;
>       }
>   
>       drm_display_mode_from_videomode(&dp->vm, mode);
> @@ -985,171 +94,31 @@ static int exynos_dp_get_modes(struct drm_connector 
> *connector)
>       drm_mode_set_name(mode);
>       drm_mode_probed_add(connector, mode);
>   
> -     return 1;
> -}
> -
> -static struct drm_encoder *exynos_dp_best_encoder(
> -                     struct drm_connector *connector)
> -{
> -     struct exynos_dp_device *dp = ctx_from_connector(connector);
> -
> -     return &dp->encoder;
> -}
> -
> -static const struct drm_connector_helper_funcs 
> exynos_dp_connector_helper_funcs = {
> -     .get_modes = exynos_dp_get_modes,
> -     .best_encoder = exynos_dp_best_encoder,
> -};
> -
> -/* returns the number of bridges attached */
> -static int exynos_drm_attach_lcd_bridge(struct exynos_dp_device *dp,
> -             struct drm_encoder *encoder)
> -{
> -     int ret;
> -
> -     encoder->bridge->next = dp->ptn_bridge;
> -     dp->ptn_bridge->encoder = encoder;
> -     ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
> -     if (ret) {
> -             DRM_ERROR("Failed to attach bridge to drm\n");
> -             return ret;
> -     }
> -
> -     return 0;
> +     return num_modes + 1;
>   }
>   
> -static int exynos_dp_bridge_attach(struct drm_bridge *bridge)
> +static int exynos_dp_bridge_attach(struct analogix_dp_plat_data *plat_data,
> +                                struct drm_bridge *bridge,
> +                                struct drm_connector *connector)
>   {
> -     struct exynos_dp_device *dp = bridge->driver_private;
> +     struct exynos_dp_device *dp = to_dp(plat_data);
>       struct drm_encoder *encoder = &dp->encoder;
> -     struct drm_connector *connector = &dp->connector;
>       int ret;
>   
> -     /* 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 0;
> -     }
> -
> -     connector->polled = DRM_CONNECTOR_POLL_HPD;
> -
> -     ret = drm_connector_init(dp->drm_dev, connector,
> -                     &exynos_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_register(connector);
> -     drm_mode_connector_attach_encoder(connector, encoder);
> -
> -     if (dp->panel)
> -             ret = drm_panel_attach(dp->panel, &dp->connector);
> -
> -     return ret;
> -}
> -
> -static void exynos_dp_bridge_enable(struct drm_bridge *bridge)
> -{
> -     struct exynos_dp_device *dp = bridge->driver_private;
> -     struct exynos_drm_crtc *crtc = dp_to_crtc(dp);
> -
> -     if (dp->dpms_mode == DRM_MODE_DPMS_ON)
> -             return;
> -
> -     pm_runtime_get_sync(dp->dev);
> -
> -     if (dp->panel) {
> -             if (drm_panel_prepare(dp->panel)) {
> -                     DRM_ERROR("failed to setup the panel\n");
> -                     return;
> -             }
> -     }
> -
> -     if (crtc->ops->clock_enable)
> -             crtc->ops->clock_enable(dp_to_crtc(dp), true);
> -
> -     phy_power_on(dp->phy);
> -     exynos_dp_init_dp(dp);
> -     enable_irq(dp->irq);
> -     exynos_dp_commit(&dp->encoder);
>   
> -     dp->dpms_mode = DRM_MODE_DPMS_ON;
> -}
> -
> -static void exynos_dp_bridge_disable(struct drm_bridge *bridge)
> -{
> -     struct exynos_dp_device *dp = bridge->driver_private;
> -     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)) {
> -                     DRM_ERROR("failed to disable the panel\n");
> -                     return;
> +     /* Pre-empt DP connector creation if there's a bridge */
> +     if (dp->ptn_bridge) {
> +             bridge->next = dp->ptn_bridge;
> +             dp->ptn_bridge->encoder = encoder;
> +             ret = drm_bridge_attach(encoder->dev, dp->ptn_bridge);
> +             if (ret) {
> +                     DRM_ERROR("Failed to attach bridge to drm\n");
> +                     bridge->next = NULL;
> +                     return ret;
>               }
>       }
>   
> -     disable_irq(dp->irq);
> -     flush_work(&dp->hotplug_work);
> -     phy_power_off(dp->phy);
> -
> -     if (crtc->ops->clock_enable)
> -             crtc->ops->clock_enable(dp_to_crtc(dp), false);
> -
> -     if (dp->panel) {
> -             if (drm_panel_unprepare(dp->panel))
> -                     DRM_ERROR("failed to turnoff the panel\n");
> -     }
> -
> -     pm_runtime_put_sync(dp->dev);
> -
> -     dp->dpms_mode = DRM_MODE_DPMS_OFF;
> -}
> -
> -static void exynos_dp_bridge_nop(struct drm_bridge *bridge)
> -{
> -     /* do nothing */
> -}
> -
> -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 int exynos_dp_create_connector(struct drm_encoder *encoder)
> -{
> -     struct exynos_dp_device *dp = encoder_to_dp(encoder);
> -     struct drm_device *drm_dev = dp->drm_dev;
> -     struct drm_bridge *bridge;
> -     int ret;
> -
> -     bridge = devm_kzalloc(drm_dev->dev, sizeof(*bridge), GFP_KERNEL);
> -     if (!bridge) {
> -             DRM_ERROR("failed to allocate for drm bridge\n");
> -             return -ENOMEM;
> -     }
> -
> -     dp->bridge = bridge;
> -
> -     encoder->bridge = bridge;
> -     bridge->driver_private = dp;
> -     bridge->encoder = encoder;
> -     bridge->funcs = &exynos_dp_bridge_funcs;
> -
> -     ret = drm_bridge_attach(drm_dev, bridge);
> -     if (ret) {
> -             DRM_ERROR("failed to attach drm bridge\n");
> -             return -EINVAL;
> -     }
> -
>       return 0;
>   }
>   
> @@ -1159,82 +128,21 @@ static void exynos_dp_mode_set(struct drm_encoder 
> *encoder,
>   {
>   }
>   
> -static void exynos_dp_enable(struct drm_encoder *encoder)
> -{
> -}
> -
> -static void exynos_dp_disable(struct drm_encoder *encoder)
> +static void exynos_dp_nop(struct drm_encoder *encoder)
>   {
> +     /* do nothing */
>   }
>   
>   static const struct drm_encoder_helper_funcs exynos_dp_encoder_helper_funcs 
> = {
>       .mode_set = exynos_dp_mode_set,
> -     .enable = exynos_dp_enable,
> -     .disable = exynos_dp_disable,
> +     .enable = exynos_dp_nop,
> +     .disable = exynos_dp_nop,
>   };
>   
>   static const struct drm_encoder_funcs exynos_dp_encoder_funcs = {
>       .destroy = drm_encoder_cleanup,
>   };
>   
> -static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev)
> -{
> -     struct device_node *dp_node = dev->of_node;
> -     struct video_info *dp_video_config;
> -
> -     dp_video_config = devm_kzalloc(dev,
> -                             sizeof(*dp_video_config), GFP_KERNEL);
> -     if (!dp_video_config)
> -             return ERR_PTR(-ENOMEM);
> -
> -     dp_video_config->h_sync_polarity =
> -             of_property_read_bool(dp_node, "hsync-active-high");
> -
> -     dp_video_config->v_sync_polarity =
> -             of_property_read_bool(dp_node, "vsync-active-high");
> -
> -     dp_video_config->interlaced =
> -             of_property_read_bool(dp_node, "interlaced");
> -
> -     if (of_property_read_u32(dp_node, "samsung,color-space",
> -                             &dp_video_config->color_space)) {
> -             dev_err(dev, "failed to get color-space\n");
> -             return ERR_PTR(-EINVAL);
> -     }
> -
> -     if (of_property_read_u32(dp_node, "samsung,dynamic-range",
> -                             &dp_video_config->dynamic_range)) {
> -             dev_err(dev, "failed to get dynamic-range\n");
> -             return ERR_PTR(-EINVAL);
> -     }
> -
> -     if (of_property_read_u32(dp_node, "samsung,ycbcr-coeff",
> -                             &dp_video_config->ycbcr_coeff)) {
> -             dev_err(dev, "failed to get ycbcr-coeff\n");
> -             return ERR_PTR(-EINVAL);
> -     }
> -
> -     if (of_property_read_u32(dp_node, "samsung,color-depth",
> -                             &dp_video_config->color_depth)) {
> -             dev_err(dev, "failed to get color-depth\n");
> -             return ERR_PTR(-EINVAL);
> -     }
> -
> -     if (of_property_read_u32(dp_node, "samsung,link-rate",
> -                             &dp_video_config->link_rate)) {
> -             dev_err(dev, "failed to get link-rate\n");
> -             return ERR_PTR(-EINVAL);
> -     }
> -
> -     if (of_property_read_u32(dp_node, "samsung,lane-count",
> -                             &dp_video_config->lane_count)) {
> -             dev_err(dev, "failed to get lane-count\n");
> -             return ERR_PTR(-EINVAL);
> -     }
> -
> -     return dp_video_config;
> -}
> -
>   static int exynos_dp_dt_parse_panel(struct exynos_dp_device *dp)
>   {
>       int ret;
> @@ -1250,97 +158,32 @@ static int exynos_dp_dt_parse_panel(struct 
> exynos_dp_device *dp)
>   static int exynos_dp_bind(struct device *dev, struct device *master, void 
> *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 drm_encoder *encoder = &dp->encoder;
> -     struct resource *res;
> -     unsigned int irq_flags;
> -     int pipe, ret = 0;
> +     struct drm_device *drm_dev = data;
> +     int pipe, ret;
>   
> -     dp->dev = &pdev->dev;
> -     dp->dpms_mode = DRM_MODE_DPMS_OFF;
> +     /*
> +      * 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->video_info = exynos_dp_dt_parse_pdata(&pdev->dev);
> -     if (IS_ERR(dp->video_info))
> -             return PTR_ERR(dp->video_info);
> +     dp->dev = dev;
> +     dp->drm_dev = drm_dev;
>   
> -     dp->phy = devm_phy_get(dp->dev, "dp");
> -     if (IS_ERR(dp->phy)) {
> -             dev_err(dp->dev, "no DP phy configured\n");
> -             ret = PTR_ERR(dp->phy);
> -             if (ret) {
> -                     /*
> -                      * phy itself is not enabled, so we can move forward
> -                      * assigning NULL to phy pointer.
> -                      */
> -                     if (ret == -ENOSYS || ret == -ENODEV)
> -                             dp->phy = NULL;
> -                     else
> -                             return ret;
> -             }
> -     }
> +     dp->plat_data.dev_type = EXYNOS_DP;
> +     dp->plat_data.power_on = exynos_dp_poweron;
> +     dp->plat_data.power_off = exynos_dp_poweroff;
> +     dp->plat_data.attach = exynos_dp_bridge_attach;
> +     dp->plat_data.get_modes = exynos_dp_get_modes;
>   
> -     if (!dp->panel && !dp->ptn_bridge) {
> +     if (!dp->plat_data.panel && !dp->ptn_bridge) {
>               ret = exynos_dp_dt_parse_panel(dp);
>               if (ret)
>                       return ret;
>       }
>   
> -     dp->clock = devm_clk_get(&pdev->dev, "dp");
> -     if (IS_ERR(dp->clock)) {
> -             dev_err(&pdev->dev, "failed to get clock\n");
> -             return PTR_ERR(dp->clock);
> -     }
> -
> -     clk_prepare_enable(dp->clock);
> -
> -     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -
> -     dp->reg_base = devm_ioremap_resource(&pdev->dev, res);
> -     if (IS_ERR(dp->reg_base))
> -             return PTR_ERR(dp->reg_base);
> -
> -     dp->hpd_gpio = of_get_named_gpio(dev->of_node, "samsung,hpd-gpio", 0);
> -
> -     if (gpio_is_valid(dp->hpd_gpio)) {
> -             /*
> -              * Set up the hotplug GPIO from the device tree as an interrupt.
> -              * Simply specifying a different interrupt in the device tree
> -              * doesn't work since we handle hotplug rather differently when
> -              * using a GPIO.  We also need the actual GPIO specifier so
> -              * that we can get the current state of the GPIO.
> -              */
> -             ret = devm_gpio_request_one(&pdev->dev, dp->hpd_gpio, GPIOF_IN,
> -                                         "hpd_gpio");
> -             if (ret) {
> -                     dev_err(&pdev->dev, "failed to get hpd gpio\n");
> -                     return ret;
> -             }
> -             dp->irq = gpio_to_irq(dp->hpd_gpio);
> -             irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
> -     } else {
> -             dp->hpd_gpio = -ENODEV;
> -             dp->irq = platform_get_irq(pdev, 0);
> -             irq_flags = 0;
> -     }
> -
> -     if (dp->irq == -ENXIO) {
> -             dev_err(&pdev->dev, "failed to get irq\n");
> -             return -ENODEV;
> -     }
> -
> -     INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
> -
> -     ret = devm_request_irq(&pdev->dev, dp->irq, exynos_dp_irq_handler,
> -                     irq_flags, "exynos-dp", dp);
> -     if (ret) {
> -             dev_err(&pdev->dev, "failed to request irq\n");
> -             return ret;
> -     }
> -     disable_irq(dp->irq);
> -
> -     dp->drm_dev = drm_dev;
> -
>       pipe = exynos_drm_crtc_get_pipe_from_type(drm_dev,
>                                                 EXYNOS_DISPLAY_TYPE_LCD);
>       if (pipe < 0)
> @@ -1355,22 +198,15 @@ static int exynos_dp_bind(struct device *dev, struct 
> device *master, void *data)
>   
>       drm_encoder_helper_add(encoder, &exynos_dp_encoder_helper_funcs);
>   
> -     ret = exynos_dp_create_connector(encoder);
> -     if (ret) {
> -             DRM_ERROR("failed to create connector ret = %d\n", ret);
> -             drm_encoder_cleanup(encoder);
> -             return ret;
> -     }
> +     dp->plat_data.encoder = encoder;
>   
> -     return 0;
> +     return analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data);
>   }
>   
>   static void exynos_dp_unbind(struct device *dev, struct device *master,
>                               void *data)
>   {
> -     struct exynos_dp_device *dp = dev_get_drvdata(dev);
> -
> -     exynos_dp_disable(&dp->encoder);
> +     return analogix_dp_unbind(dev, master, data);
>   }
>   
>   static const struct component_ops exynos_dp_ops = {
> @@ -1383,21 +219,25 @@ static int exynos_dp_probe(struct platform_device 
> *pdev)
>       struct device *dev = &pdev->dev;
>       struct device_node *np = NULL, *endpoint = NULL;
>       struct exynos_dp_device *dp;
> -     int ret;
>   
>       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);
>   
>       /* This is for the backward compatibility. */
>       np = of_parse_phandle(dev->of_node, "panel", 0);
>       if (np) {
> -             dp->panel = of_drm_find_panel(np);
> +             dp->plat_data.panel = of_drm_find_panel(np);
>               of_node_put(np);
> -             if (!dp->panel)
> +             if (!dp->plat_data.panel)
>                       return -EPROBE_DEFER;
>               goto out;
>       }
> @@ -1407,8 +247,8 @@ static int exynos_dp_probe(struct platform_device *pdev)
>               np = of_graph_get_remote_port_parent(endpoint);
>               if (np) {
>                       /* The remote port can be either a panel or a bridge */
> -                     dp->panel = of_drm_find_panel(np);
> -                     if (!dp->panel) {
> +                     dp->plat_data.panel = of_drm_find_panel(np);
> +                     if (!dp->plat_data.panel) {
>                               dp->ptn_bridge = of_drm_find_bridge(np);
>                               if (!dp->ptn_bridge) {
>                                       of_node_put(np);
> @@ -1426,23 +266,11 @@ static int exynos_dp_probe(struct platform_device 
> *pdev)
>       }
>   
>   out:
> -     pm_runtime_enable(dev);
> -
> -     ret = component_add(&pdev->dev, &exynos_dp_ops);
> -     if (ret)
> -             goto err_disable_pm_runtime;
> -
> -     return ret;
> -
> -err_disable_pm_runtime:
> -     pm_runtime_disable(dev);
> -
> -     return ret;
> +     return component_add(&pdev->dev, &exynos_dp_ops);
>   }
>   
>   static int exynos_dp_remove(struct platform_device *pdev)
>   {
> -     pm_runtime_disable(&pdev->dev);
>       component_del(&pdev->dev, &exynos_dp_ops);
>   
>       return 0;
> @@ -1451,25 +279,12 @@ static int exynos_dp_remove(struct platform_device 
> *pdev)
>   #ifdef CONFIG_PM
>   static int exynos_dp_suspend(struct device *dev)
>   {
> -     struct exynos_dp_device *dp = dev_get_drvdata(dev);
> -
> -     clk_disable_unprepare(dp->clock);
> -
> -     return 0;
> +     return analogix_dp_suspend(dev);
>   }
>   
>   static int exynos_dp_resume(struct device *dev)
>   {
> -     struct exynos_dp_device *dp = dev_get_drvdata(dev);
> -     int ret;
> -
> -     ret = clk_prepare_enable(dp->clock);
> -     if (ret < 0) {
> -             DRM_ERROR("Failed to prepare_enable the clock clk [%d]\n", ret);
> -             return ret;
> -     }
> -
> -     return 0;
> +     return analogix_dp_resume(dev);
>   }
>   #endif
>   
> @@ -1495,5 +310,5 @@ struct platform_driver dp_driver = {
>   };
>   
>   MODULE_AUTHOR("Jingoo Han <jg1.han at samsung.com>");
> -MODULE_DESCRIPTION("Samsung SoC DP Driver");
> +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 b5c2d8f..0000000
> --- a/drivers/gpu/drm/exynos/exynos_dp_core.h
> +++ /dev/null
> @@ -1,282 +0,0 @@
> -/*
> - * Header file for Samsung DP (Display Port) interface driver.
> - *
> - * Copyright (C) 2012 Samsung Electronics Co., Ltd.
> - * Author: Jingoo Han <jg1.han at samsung.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 <video/videomode.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 drm_encoder      encoder;
> -     struct device           *dev;
> -     struct drm_device       *drm_dev;
> -     struct drm_connector    connector;
> -     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 videomode        vm;
> -};
> -
> -/* 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/drivers/gpu/drm/exynos/exynos_dp_reg.c 
> b/drivers/gpu/drm/exynos/exynos_dp_reg.c
> deleted file mode 100644
> index c1f87a2..0000000
> --- a/drivers/gpu/drm/exynos/exynos_dp_reg.c
> +++ /dev/null
> @@ -1,1263 +0,0 @@
> -/*
> - * Samsung DP (Display port) register interface driver.
> - *
> - * Copyright (C) 2012 Samsung Electronics Co., Ltd.
> - * Author: Jingoo Han <jg1.han at samsung.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 "exynos_dp_core.h"
> -#include "exynos_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 exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable)
> -{
> -     u32 reg;
> -
> -     if (enable) {
> -             reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> -             reg |= HDCP_VIDEO_MUTE;
> -             writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> -     } else {
> -             reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> -             reg &= ~HDCP_VIDEO_MUTE;
> -             writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> -     }
> -}
> -
> -void exynos_dp_stop_video(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> -     reg &= ~VIDEO_EN;
> -     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> -}
> -
> -void exynos_dp_lane_swap(struct exynos_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 + EXYNOS_DP_LANE_MAP);
> -}
> -
> -void exynos_dp_init_analog_param(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     reg = TX_TERMINAL_CTRL_50_OHM;
> -     writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1);
> -
> -     reg = SEL_24M | TX_DVDD_BIT_1_0625V;
> -     writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2);
> -
> -     reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
> -     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_TX_AMP_TUNING_CTL);
> -}
> -
> -void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
> -{
> -     /* Set interrupt pin assertion polarity as high */
> -     writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL);
> -
> -     /* Clear pending regisers */
> -     writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
> -     writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2);
> -     writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3);
> -     writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
> -     writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA);
> -
> -     /* 0:mask,1: unmask */
> -     writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
> -     writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
> -     writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
> -     writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
> -     writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
> -}
> -
> -void exynos_dp_reset(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     exynos_dp_stop_video(dp);
> -     exynos_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 + EXYNOS_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 + EXYNOS_DP_FUNC_EN_2);
> -
> -     usleep_range(20, 30);
> -
> -     exynos_dp_lane_swap(dp, 0);
> -
> -     writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
> -     writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
> -     writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> -     writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> -
> -     writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL);
> -     writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL);
> -
> -     writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L);
> -     writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H);
> -
> -     writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL);
> -
> -     writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST);
> -
> -     writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD);
> -     writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN);
> -
> -     writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH);
> -     writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
> -
> -     writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> -}
> -
> -void exynos_dp_swreset(struct exynos_dp_device *dp)
> -{
> -     writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
> -}
> -
> -void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     /* 0: mask, 1: unmask */
> -     reg = COMMON_INT_MASK_1;
> -     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
> -
> -     reg = COMMON_INT_MASK_2;
> -     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
> -
> -     reg = COMMON_INT_MASK_3;
> -     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
> -
> -     reg = COMMON_INT_MASK_4;
> -     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
> -
> -     reg = INT_STA_MASK;
> -     writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
> -}
> -
> -enum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
> -     if (reg & PLL_LOCK)
> -             return PLL_LOCKED;
> -     else
> -             return PLL_UNLOCKED;
> -}
> -
> -void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable)
> -{
> -     u32 reg;
> -
> -     if (enable) {
> -             reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
> -             reg |= DP_PLL_PD;
> -             writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
> -     } else {
> -             reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
> -             reg &= ~DP_PLL_PD;
> -             writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
> -     }
> -}
> -
> -void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
> -                             enum analog_power_block block,
> -                             bool enable)
> -{
> -     u32 reg;
> -
> -     switch (block) {
> -     case AUX_BLOCK:
> -             if (enable) {
> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -                     reg |= AUX_PD;
> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -             } else {
> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -                     reg &= ~AUX_PD;
> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -             }
> -             break;
> -     case CH0_BLOCK:
> -             if (enable) {
> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -                     reg |= CH0_PD;
> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -             } else {
> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -                     reg &= ~CH0_PD;
> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -             }
> -             break;
> -     case CH1_BLOCK:
> -             if (enable) {
> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -                     reg |= CH1_PD;
> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -             } else {
> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -                     reg &= ~CH1_PD;
> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -             }
> -             break;
> -     case CH2_BLOCK:
> -             if (enable) {
> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -                     reg |= CH2_PD;
> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -             } else {
> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -                     reg &= ~CH2_PD;
> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -             }
> -             break;
> -     case CH3_BLOCK:
> -             if (enable) {
> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -                     reg |= CH3_PD;
> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -             } else {
> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -                     reg &= ~CH3_PD;
> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -             }
> -             break;
> -     case ANALOG_TOTAL:
> -             if (enable) {
> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -                     reg |= DP_PHY_PD;
> -                     writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
> -             } else {
> -                     reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
> -                     reg &= ~DP_PHY_PD;
> -                     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_PHY_PD);
> -             } else {
> -                     writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD);
> -             }
> -             break;
> -     default:
> -             break;
> -     }
> -}
> -
> -void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -     int timeout_loop = 0;
> -
> -     exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
> -
> -     reg = PLL_LOCK_CHG;
> -     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
> -     reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
> -     writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL);
> -
> -     /* Power up PLL */
> -     if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
> -             exynos_dp_set_pll_power_down(dp, 0);
> -
> -             while (exynos_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 + EXYNOS_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 + EXYNOS_DP_FUNC_EN_2);
> -}
> -
> -void exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     if (gpio_is_valid(dp->hpd_gpio))
> -             return;
> -
> -     reg = HOTPLUG_CHG | HPD_LOST | PLUG;
> -     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
> -
> -     reg = INT_HPD;
> -     writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
> -}
> -
> -void exynos_dp_init_hpd(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     if (gpio_is_valid(dp->hpd_gpio))
> -             return;
> -
> -     exynos_dp_clear_hotplug_interrupts(dp);
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> -     reg &= ~(F_HPD | HPD_CTRL);
> -     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> -}
> -
> -enum dp_irq_type exynos_dp_get_irq_type(struct exynos_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 + EXYNOS_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 exynos_dp_reset_aux(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     /* Disable AUX channel module */
> -     reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> -     reg |= AUX_FUNC_EN_N;
> -     writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> -}
> -
> -void exynos_dp_init_aux(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     /* Clear inerrupts related to AUX channel */
> -     reg = RPLY_RECEIV | AUX_ERR;
> -     writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
> -
> -     exynos_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 + EXYNOS_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 + EXYNOS_DP_AUX_CH_DEFER_CTL);
> -
> -     /* Enable AUX channel module */
> -     reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> -     reg &= ~AUX_FUNC_EN_N;
> -     writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
> -}
> -
> -int exynos_dp_get_plug_in_status(struct exynos_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 + EXYNOS_DP_SYS_CTL_3);
> -             if (reg & HPD_STATUS)
> -                     return 0;
> -     }
> -
> -     return -EINVAL;
> -}
> -
> -void exynos_dp_enable_sw_function(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
> -     reg &= ~SW_FUNC_EN_N;
> -     writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
> -}
> -
> -int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
> -{
> -     int reg;
> -     int retval = 0;
> -     int timeout_loop = 0;
> -
> -     /* Enable AUX CH operation */
> -     reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
> -     reg |= AUX_EN;
> -     writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
> -
> -     /* Is AUX CH command reply received? */
> -     reg = readl(dp->reg_base + EXYNOS_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 + EXYNOS_DP_INT_STA);
> -             usleep_range(10, 11);
> -     }
> -
> -     /* Clear interrupt source for AUX CH command reply */
> -     writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
> -
> -     /* Clear interrupt source for AUX CH access error */
> -     reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
> -     if (reg & AUX_ERR) {
> -             writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA);
> -             return -EREMOTEIO;
> -     }
> -
> -     /* Check AUX CH error access status */
> -     reg = readl(dp->reg_base + EXYNOS_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 exynos_dp_write_byte_to_dpcd(struct exynos_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 + EXYNOS_DP_BUFFER_DATA_CTL);
> -
> -             /* Select DPCD device address */
> -             reg = AUX_ADDR_7_0(reg_addr);
> -             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
> -             reg = AUX_ADDR_15_8(reg_addr);
> -             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> -             reg = AUX_ADDR_19_16(reg_addr);
> -             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
> -
> -             /* Write data buffer */
> -             reg = (unsigned int)data;
> -             writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_AUX_CH_CTL_1);
> -
> -             /* Start AUX transaction */
> -             retval = exynos_dp_start_aux_transaction(dp);
> -             if (retval == 0)
> -                     break;
> -             else
> -                     dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
> -                             __func__);
> -     }
> -
> -     return retval;
> -}
> -
> -int exynos_dp_read_byte_from_dpcd(struct exynos_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 + EXYNOS_DP_BUFFER_DATA_CTL);
> -
> -             /* Select DPCD device address */
> -             reg = AUX_ADDR_7_0(reg_addr);
> -             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
> -             reg = AUX_ADDR_15_8(reg_addr);
> -             writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> -             reg = AUX_ADDR_19_16(reg_addr);
> -             writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_AUX_CH_CTL_1);
> -
> -             /* Start AUX transaction */
> -             retval = exynos_dp_start_aux_transaction(dp);
> -             if (retval == 0)
> -                     break;
> -             else
> -                     dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
> -                             __func__);
> -     }
> -
> -     /* Read data buffer */
> -     reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
> -     *data = (unsigned char)(reg & 0xff);
> -
> -     return retval;
> -}
> -
> -int exynos_dp_write_bytes_to_dpcd(struct exynos_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 + EXYNOS_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 + EXYNOS_DP_AUX_ADDR_7_0);
> -                     reg = AUX_ADDR_15_8(reg_addr + start_offset);
> -                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> -                     reg = AUX_ADDR_19_16(reg_addr + start_offset);
> -                     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_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 + EXYNOS_DP_AUX_CH_CTL_1);
> -
> -                     /* Start AUX transaction */
> -                     retval = exynos_dp_start_aux_transaction(dp);
> -                     if (retval == 0)
> -                             break;
> -                     else
> -                             dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
> -                                     __func__);
> -             }
> -
> -             start_offset += cur_data_count;
> -     }
> -
> -     return retval;
> -}
> -
> -int exynos_dp_read_bytes_from_dpcd(struct exynos_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 + EXYNOS_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 + EXYNOS_DP_AUX_ADDR_7_0);
> -                     reg = AUX_ADDR_15_8(reg_addr + start_offset);
> -                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> -                     reg = AUX_ADDR_19_16(reg_addr + start_offset);
> -                     writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_AUX_CH_CTL_1);
> -
> -                     /* Start AUX transaction */
> -                     retval = exynos_dp_start_aux_transaction(dp);
> -                     if (retval == 0)
> -                             break;
> -                     else
> -                             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 + EXYNOS_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 exynos_dp_select_i2c_device(struct exynos_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 + EXYNOS_DP_AUX_ADDR_7_0);
> -     writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
> -     writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
> -
> -     /* Set offset from base address of EDID device */
> -     writel(reg_addr, dp->reg_base + EXYNOS_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 + EXYNOS_DP_AUX_CH_CTL_1);
> -
> -     /* Start AUX transaction */
> -     retval = exynos_dp_start_aux_transaction(dp);
> -     if (retval != 0)
> -             dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
> -
> -     return retval;
> -}
> -
> -int exynos_dp_read_byte_from_i2c(struct exynos_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 + EXYNOS_DP_BUFFER_DATA_CTL);
> -
> -             /* Select EDID device */
> -             retval = exynos_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 + EXYNOS_DP_AUX_CH_CTL_1);
> -
> -             /* Start AUX transaction */
> -             retval = exynos_dp_start_aux_transaction(dp);
> -             if (retval == 0)
> -                     break;
> -             else
> -                     dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
> -                             __func__);
> -     }
> -
> -     /* Read data */
> -     if (retval == 0)
> -             *data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
> -
> -     return retval;
> -}
> -
> -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[])
> -{
> -     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 + EXYNOS_DP_BUFFER_DATA_CTL);
> -
> -                     /* Set normal AUX CH command */
> -                     reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
> -                     reg &= ~ADDR_ONLY;
> -                     writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
> -
> -                     /*
> -                      * If Rx sends defer, Tx sends only reads
> -                      * request without sending address
> -                      */
> -                     if (!defer)
> -                             retval = exynos_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 +
> -                                     EXYNOS_DP_AUX_CH_CTL_1);
> -
> -                             /* Start AUX transaction */
> -                             retval = exynos_dp_start_aux_transaction(dp);
> -                             if (retval == 0)
> -                                     break;
> -                             else
> -                                     dev_dbg(dp->dev,
> -                                             "%s: Aux Transaction fail!\n",
> -                                             __func__);
> -                     }
> -                     /* Check if Rx sends defer */
> -                     reg = readl(dp->reg_base + EXYNOS_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 + EXYNOS_DP_BUF_DATA_0
> -                                              + 4 * cur_data_idx);
> -                     edid[i + cur_data_idx] = (unsigned char)reg;
> -             }
> -     }
> -
> -     return retval;
> -}
> -
> -void exynos_dp_set_link_bandwidth(struct exynos_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 + EXYNOS_DP_LINK_BW_SET);
> -}
> -
> -void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET);
> -     *bwtype = reg;
> -}
> -
> -void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count)
> -{
> -     u32 reg;
> -
> -     reg = count;
> -     writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
> -}
> -
> -void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
> -     *count = reg;
> -}
> -
> -void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable)
> -{
> -     u32 reg;
> -
> -     if (enable) {
> -             reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> -             reg |= ENHANCED;
> -             writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> -     } else {
> -             reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> -             reg &= ~ENHANCED;
> -             writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> -     }
> -}
> -
> -void exynos_dp_set_training_pattern(struct exynos_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 + EXYNOS_DP_TRAINING_PTN_SET);
> -             break;
> -     case D10_2:
> -             reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
> -             writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> -             break;
> -     case TRAINING_PTN1:
> -             reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
> -             writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> -             break;
> -     case TRAINING_PTN2:
> -             reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
> -             writel(reg, dp->reg_base + EXYNOS_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 + EXYNOS_DP_TRAINING_PTN_SET);
> -             break;
> -     default:
> -             break;
> -     }
> -}
> -
> -void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
> -     reg &= ~PRE_EMPHASIS_SET_MASK;
> -     reg |= level << PRE_EMPHASIS_SET_SHIFT;
> -     writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
> -}
> -
> -void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
> -     reg &= ~PRE_EMPHASIS_SET_MASK;
> -     reg |= level << PRE_EMPHASIS_SET_SHIFT;
> -     writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
> -}
> -
> -void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
> -     reg &= ~PRE_EMPHASIS_SET_MASK;
> -     reg |= level << PRE_EMPHASIS_SET_SHIFT;
> -     writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
> -}
> -
> -void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
> -     reg &= ~PRE_EMPHASIS_SET_MASK;
> -     reg |= level << PRE_EMPHASIS_SET_SHIFT;
> -     writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
> -}
> -
> -void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
> -                                     u32 training_lane)
> -{
> -     u32 reg;
> -
> -     reg = training_lane;
> -     writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
> -}
> -
> -void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
> -                                     u32 training_lane)
> -{
> -     u32 reg;
> -
> -     reg = training_lane;
> -     writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
> -}
> -
> -void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
> -                                     u32 training_lane)
> -{
> -     u32 reg;
> -
> -     reg = training_lane;
> -     writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
> -}
> -
> -void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
> -                                     u32 training_lane)
> -{
> -     u32 reg;
> -
> -     reg = training_lane;
> -     writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
> -}
> -
> -u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
> -     return reg;
> -}
> -
> -u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
> -     return reg;
> -}
> -
> -u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
> -     return reg;
> -}
> -
> -u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
> -     return reg;
> -}
> -
> -void exynos_dp_reset_macro(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST);
> -     reg |= MACRO_RST;
> -     writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
> -
> -     /* 10 us is the minimum reset time. */
> -     usleep_range(10, 20);
> -
> -     reg &= ~MACRO_RST;
> -     writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
> -}
> -
> -void exynos_dp_init_video(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
> -     writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
> -
> -     reg = 0x0;
> -     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
> -
> -     reg = CHA_CRI(4) | CHA_CTRL;
> -     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
> -
> -     reg = 0x0;
> -     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> -
> -     reg = VID_HRES_TH(2) | VID_VRES_TH(0);
> -     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
> -}
> -
> -void exynos_dp_set_video_color_format(struct exynos_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 + EXYNOS_DP_VIDEO_CTL_2);
> -
> -     /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
> -     reg = readl(dp->reg_base + EXYNOS_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 + EXYNOS_DP_VIDEO_CTL_3);
> -}
> -
> -int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
> -     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
> -
> -     reg = readl(dp->reg_base + EXYNOS_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 + EXYNOS_DP_SYS_CTL_2);
> -     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
> -
> -     reg = readl(dp->reg_base + EXYNOS_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 exynos_dp_set_video_cr_mn(struct exynos_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 + EXYNOS_DP_SYS_CTL_4);
> -             reg |= FIX_M_VID;
> -             writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> -             reg = m_value & 0xff;
> -             writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0);
> -             reg = (m_value >> 8) & 0xff;
> -             writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1);
> -             reg = (m_value >> 16) & 0xff;
> -             writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2);
> -
> -             reg = n_value & 0xff;
> -             writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0);
> -             reg = (n_value >> 8) & 0xff;
> -             writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1);
> -             reg = (n_value >> 16) & 0xff;
> -             writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2);
> -     } else  {
> -             reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> -             reg &= ~FIX_M_VID;
> -             writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
> -
> -             writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0);
> -             writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1);
> -             writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2);
> -     }
> -}
> -
> -void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type)
> -{
> -     u32 reg;
> -
> -     if (type == VIDEO_TIMING_FROM_CAPTURE) {
> -             reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -             reg &= ~FORMAT_SEL;
> -             writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -     } else {
> -             reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -             reg |= FORMAT_SEL;
> -             writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -     }
> -}
> -
> -void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable)
> -{
> -     u32 reg;
> -
> -     if (enable) {
> -             reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> -             reg &= ~VIDEO_MODE_MASK;
> -             reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
> -             writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> -     } else {
> -             reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> -             reg &= ~VIDEO_MODE_MASK;
> -             reg |= VIDEO_MODE_SLAVE_MODE;
> -             writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> -     }
> -}
> -
> -void exynos_dp_start_video(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> -     reg |= VIDEO_EN;
> -     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
> -}
> -
> -int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> -     writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
> -     if (!(reg & STRM_VALID)) {
> -             dev_dbg(dp->dev, "Input video stream is not detected.\n");
> -             return -EINVAL;
> -     }
> -
> -     return 0;
> -}
> -
> -void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_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 + EXYNOS_DP_FUNC_EN_1);
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -     reg &= ~INTERACE_SCAN_CFG;
> -     reg |= (dp->video_info->interlaced << 2);
> -     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -     reg &= ~VSYNC_POLARITY_CFG;
> -     reg |= (dp->video_info->v_sync_polarity << 1);
> -     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -     reg &= ~HSYNC_POLARITY_CFG;
> -     reg |= (dp->video_info->h_sync_polarity << 0);
> -     writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
> -
> -     reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
> -     writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
> -}
> -
> -void exynos_dp_enable_scrambling(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> -     reg &= ~SCRAMBLING_DISABLE;
> -     writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> -}
> -
> -void exynos_dp_disable_scrambling(struct exynos_dp_device *dp)
> -{
> -     u32 reg;
> -
> -     reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> -     reg |= SCRAMBLING_DISABLE;
> -     writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
> -}
> diff --git a/drivers/gpu/drm/exynos/exynos_dp_reg.h 
> b/drivers/gpu/drm/exynos/exynos_dp_reg.h
> deleted file mode 100644
> index 2e9bd0e..0000000
> --- a/drivers/gpu/drm/exynos/exynos_dp_reg.h
> +++ /dev/null
> @@ -1,366 +0,0 @@
> -/*
> - * Register definition file for Samsung DP driver
> - *
> - * Copyright (C) 2012 Samsung Electronics Co., Ltd.
> - * Author: Jingoo Han <jg1.han at samsung.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 */
> -#define RESET_DP_TX                          (0x1 << 0)
> -
> -/* EXYNOS_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)
> -#define AUD_FUNC_EN_N                                (0x1 << 3)
> -#define HDCP_FUNC_EN_N                               (0x1 << 2)
> -#define CRC_FUNC_EN_N                                (0x1 << 1)
> -#define SW_FUNC_EN_N                         (0x1 << 0)
> -
> -/* EXYNOS_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 */
> -#define VIDEO_EN                             (0x1 << 7)
> -#define HDCP_VIDEO_MUTE                              (0x1 << 6)
> -
> -/* EXYNOS_DP_VIDEO_CTL_1 */
> -#define IN_D_RANGE_MASK                              (0x1 << 7)
> -#define IN_D_RANGE_SHIFT                     (7)
> -#define IN_D_RANGE_CEA                               (0x1 << 7)
> -#define IN_D_RANGE_VESA                              (0x0 << 7)
> -#define IN_BPC_MASK                          (0x7 << 4)
> -#define IN_BPC_SHIFT                         (4)
> -#define IN_BPC_12_BITS                               (0x3 << 4)
> -#define IN_BPC_10_BITS                               (0x2 << 4)
> -#define IN_BPC_8_BITS                                (0x1 << 4)
> -#define IN_BPC_6_BITS                                (0x0 << 4)
> -#define IN_COLOR_F_MASK                              (0x3 << 0)
> -#define IN_COLOR_F_SHIFT                     (0)
> -#define IN_COLOR_F_YCBCR444                  (0x2 << 0)
> -#define IN_COLOR_F_YCBCR422                  (0x1 << 0)
> -#define IN_COLOR_F_RGB                               (0x0 << 0)
> -
> -/* EXYNOS_DP_VIDEO_CTL_3 */
> -#define IN_YC_COEFFI_MASK                    (0x1 << 7)
> -#define IN_YC_COEFFI_SHIFT                   (7)
> -#define IN_YC_COEFFI_ITU709                  (0x1 << 7)
> -#define IN_YC_COEFFI_ITU601                  (0x0 << 7)
> -#define VID_CHK_UPDATE_TYPE_MASK             (0x1 << 4)
> -#define VID_CHK_UPDATE_TYPE_SHIFT            (4)
> -#define VID_CHK_UPDATE_TYPE_1                        (0x1 << 4)
> -#define VID_CHK_UPDATE_TYPE_0                        (0x0 << 4)
> -
> -/* EXYNOS_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 */
> -#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 */
> -#define LANE3_MAP_LOGIC_LANE_0                       (0x0 << 6)
> -#define LANE3_MAP_LOGIC_LANE_1                       (0x1 << 6)
> -#define LANE3_MAP_LOGIC_LANE_2                       (0x2 << 6)
> -#define LANE3_MAP_LOGIC_LANE_3                       (0x3 << 6)
> -#define LANE2_MAP_LOGIC_LANE_0                       (0x0 << 4)
> -#define LANE2_MAP_LOGIC_LANE_1                       (0x1 << 4)
> -#define LANE2_MAP_LOGIC_LANE_2                       (0x2 << 4)
> -#define LANE2_MAP_LOGIC_LANE_3                       (0x3 << 4)
> -#define LANE1_MAP_LOGIC_LANE_0                       (0x0 << 2)
> -#define LANE1_MAP_LOGIC_LANE_1                       (0x1 << 2)
> -#define LANE1_MAP_LOGIC_LANE_2                       (0x2 << 2)
> -#define LANE1_MAP_LOGIC_LANE_3                       (0x3 << 2)
> -#define LANE0_MAP_LOGIC_LANE_0                       (0x0 << 0)
> -#define LANE0_MAP_LOGIC_LANE_1                       (0x1 << 0)
> -#define LANE0_MAP_LOGIC_LANE_2                       (0x2 << 0)
> -#define LANE0_MAP_LOGIC_LANE_3                       (0x3 << 0)
> -
> -/* EXYNOS_DP_ANALOG_CTL_1 */
> -#define TX_TERMINAL_CTRL_50_OHM                      (0x1 << 4)
> -
> -/* EXYNOS_DP_ANALOG_CTL_2 */
> -#define SEL_24M                                      (0x1 << 3)
> -#define TX_DVDD_BIT_1_0625V                  (0x4 << 0)
> -
> -/* EXYNOS_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 */
> -#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 */
> -#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 */
> -#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)
> -#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS       (0x1 << 3)
> -#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS      (0x2 << 3)
> -#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 */
> -#define VSYNC_DET                            (0x1 << 7)
> -#define PLL_LOCK_CHG                         (0x1 << 6)
> -#define SPDIF_ERR                            (0x1 << 5)
> -#define SPDIF_UNSTBL                         (0x1 << 4)
> -#define VID_FORMAT_CHG                               (0x1 << 3)
> -#define AUD_CLK_CHG                          (0x1 << 2)
> -#define VID_CLK_CHG                          (0x1 << 1)
> -#define SW_INT                                       (0x1 << 0)
> -
> -/* EXYNOS_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 */
> -#define AFIFO_UNDER                          (0x1 << 7)
> -#define AFIFO_OVER                           (0x1 << 6)
> -#define R0_CHK_FLAG                          (0x1 << 5)
> -
> -/* EXYNOS_DP_COMMON_INT_STA_4 */
> -#define PSR_ACTIVE                           (0x1 << 7)
> -#define PSR_INACTIVE                         (0x1 << 6)
> -#define SPDIF_BI_PHASE_ERR                   (0x1 << 5)
> -#define HOTPLUG_CHG                          (0x1 << 2)
> -#define HPD_LOST                             (0x1 << 1)
> -#define PLUG                                 (0x1 << 0)
> -
> -/* EXYNOS_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 */
> -#define SOFT_INT_CTRL                                (0x1 << 2)
> -#define INT_POL1                             (0x1 << 1)
> -#define INT_POL0                             (0x1 << 0)
> -
> -/* EXYNOS_DP_SYS_CTL_1 */
> -#define DET_STA                                      (0x1 << 2)
> -#define FORCE_DET                            (0x1 << 1)
> -#define DET_CTRL                             (0x1 << 0)
> -
> -/* EXYNOS_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 */
> -#define HPD_STATUS                           (0x1 << 6)
> -#define F_HPD                                        (0x1 << 5)
> -#define HPD_CTRL                             (0x1 << 4)
> -#define HDCP_RDY                             (0x1 << 3)
> -#define STRM_VALID                           (0x1 << 2)
> -#define F_VALID                                      (0x1 << 1)
> -#define VALID_CTRL                           (0x1 << 0)
> -
> -/* EXYNOS_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 */
> -#define SCRAMBLER_TYPE                               (0x1 << 9)
> -#define HW_LINK_TRAINING_PATTERN             (0x1 << 8)
> -#define SCRAMBLING_DISABLE                   (0x1 << 5)
> -#define SCRAMBLING_ENABLE                    (0x0 << 5)
> -#define LINK_QUAL_PATTERN_SET_MASK           (0x3 << 2)
> -#define LINK_QUAL_PATTERN_SET_PRBS7          (0x3 << 2)
> -#define LINK_QUAL_PATTERN_SET_D10_2          (0x1 << 2)
> -#define LINK_QUAL_PATTERN_SET_DISABLE                (0x0 << 2)
> -#define SW_TRAINING_PATTERN_SET_MASK         (0x3 << 0)
> -#define SW_TRAINING_PATTERN_SET_PTN2         (0x2 << 0)
> -#define SW_TRAINING_PATTERN_SET_PTN1         (0x1 << 0)
> -#define SW_TRAINING_PATTERN_SET_NORMAL               (0x0 << 0)
> -
> -/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
> -#define PRE_EMPHASIS_SET_MASK                        (0x3 << 3)
> -#define PRE_EMPHASIS_SET_SHIFT                       (3)
> -
> -/* EXYNOS_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 */
> -#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 */
> -#define DP_PHY_PD                            (0x1 << 5)
> -#define AUX_PD                                       (0x1 << 4)
> -#define CH3_PD                                       (0x1 << 3)
> -#define CH2_PD                                       (0x1 << 2)
> -#define CH1_PD                                       (0x1 << 1)
> -#define CH0_PD                                       (0x1 << 0)
> -
> -/* EXYNOS_DP_PHY_TEST */
> -#define MACRO_RST                            (0x1 << 5)
> -#define CH1_TEST                             (0x1 << 1)
> -#define CH0_TEST                             (0x1 << 0)
> -
> -/* EXYNOS_DP_AUX_CH_STA */
> -#define AUX_BUSY                             (0x1 << 4)
> -#define AUX_STATUS_MASK                              (0xf << 0)
> -
> -/* EXYNOS_DP_AUX_CH_DEFER_CTL */
> -#define DEFER_CTRL_EN                                (0x1 << 7)
> -#define DEFER_COUNT(x)                               (((x) & 0x7f) << 0)
> -
> -/* EXYNOS_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 */
> -#define BUF_CLR                                      (0x1 << 7)
> -#define BUF_DATA_COUNT(x)                    (((x) & 0x1f) << 0)
> -
> -/* EXYNOS_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)
> -#define AUX_TX_COMM_I2C_TRANSACTION          (0x0 << 3)
> -#define AUX_TX_COMM_MOT                              (0x1 << 2)
> -#define AUX_TX_COMM_WRITE                    (0x0 << 0)
> -#define AUX_TX_COMM_READ                     (0x1 << 0)
> -
> -/* EXYNOS_DP_AUX_ADDR_7_0 */
> -#define AUX_ADDR_7_0(x)                              (((x) >> 0) & 0xff)
> -
> -/* EXYNOS_DP_AUX_ADDR_15_8 */
> -#define AUX_ADDR_15_8(x)                     (((x) >> 8) & 0xff)
> -
> -/* EXYNOS_DP_AUX_ADDR_19_16 */
> -#define AUX_ADDR_19_16(x)                    (((x) >> 16) & 0x0f)
> -
> -/* EXYNOS_DP_AUX_CH_CTL_2 */
> -#define ADDR_ONLY                            (0x1 << 1)
> -#define AUX_EN                                       (0x1 << 0)
> -
> -/* EXYNOS_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)
> -#define VIDEO_MASTER_CLK_SEL                 (0x1 << 2)
> -#define VIDEO_MASTER_MODE_EN                 (0x1 << 1)
> -#define VIDEO_MODE_MASK                              (0x1 << 0)
> -#define VIDEO_MODE_SLAVE_MODE                        (0x1 << 0)
> -#define VIDEO_MODE_MASTER_MODE                       (0x0 << 0)
> -
> -#endif /* _EXYNOS_DP_REG_H */
> diff --git a/include/drm/bridge/analogix_dp.h 
> b/include/drm/bridge/analogix_dp.h
> new file mode 100644
> index 0000000..d1188db
> --- /dev/null
> +++ b/include/drm/bridge/analogix_dp.h
> @@ -0,0 +1,40 @@
> +/*
> + * Analogix DP (Display Port) Core interface driver.
> + *
> + * Copyright (C) 2015 Rockchip Electronics Co., Ltd.
> + *
> + * 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_H_
> +#define _ANALOGIX_DP_H_
> +
> +#include <drm/drm_crtc.h>
> +
> +enum analogix_dp_devtype {
> +     EXYNOS_DP,
> +};
> +
> +struct analogix_dp_plat_data {
> +     enum analogix_dp_devtype dev_type;
> +     struct drm_panel *panel;
> +     struct drm_encoder *encoder;
> +     struct drm_connector *connector;
> +
> +     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 *,
> +                   struct drm_connector *);
> +     int (*get_modes)(struct analogix_dp_plat_data *);
> +};
> +
> +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 analogix_dp_plat_data *plat_data);
> +void analogix_dp_unbind(struct device *dev, struct device *master, void 
> *data);
> +
> +#endif /* _ANALOGIX_DP_H_ */


-- 
Thanks,
Caesar

Reply via email to