1e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han/*
2e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han * Samsung DP (Display port) register interface driver.
3e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han *
4e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han * Author: Jingoo Han <jg1.han@samsung.com>
6e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han *
7e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han * This program is free software; you can redistribute it and/or modify it
8e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han * under the terms of the GNU General Public License as published by the
9e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han * Free Software Foundation; either version 2 of the License, or (at your
10e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han * option) any later version.
11e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han */
12e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
13e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han#include <linux/device.h>
14e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han#include <linux/io.h>
15e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han#include <linux/delay.h>
16b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker#include <linux/gpio.h>
17e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
18e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han#include "exynos_dp_core.h"
19e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han#include "exynos_dp_reg.h"
20e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
21c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul#define COMMON_INT_MASK_1	0
22c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul#define COMMON_INT_MASK_2	0
23c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul#define COMMON_INT_MASK_3	0
24c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul#define COMMON_INT_MASK_4	(HOTPLUG_CHG | HPD_LOST | PLUG)
25c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul#define INT_STA_MASK		INT_HPD
26e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
27e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable)
28e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
29e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
30e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
31e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	if (enable) {
32e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
33e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg |= HDCP_VIDEO_MUTE;
34e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
35e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	} else {
36e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
37e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg &= ~HDCP_VIDEO_MUTE;
38e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
39e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
40e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
41e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
42e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_stop_video(struct exynos_dp_device *dp)
43e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
44e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
45e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
46e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
47e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg &= ~VIDEO_EN;
48e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
49e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
50e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
51e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable)
52e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
53e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
54e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
55e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	if (enable)
56e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
57e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
58e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	else
59e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
60e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
61e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
62e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP);
63e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
64e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
658affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Hanvoid exynos_dp_init_analog_param(struct exynos_dp_device *dp)
668affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han{
678affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han	u32 reg;
688affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han
698affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han	reg = TX_TERMINAL_CTRL_50_OHM;
708affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_1);
718affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han
728affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han	reg = SEL_24M | TX_DVDD_BIT_1_0625V;
738affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_2);
748affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han
758affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han	reg = DRIVE_DVDD_BIT_1_0625V | VCO_BIT_600_MICRO;
768affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_ANALOG_CTL_3);
778affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han
788affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han	reg = PD_RING_OSC | AUX_TERMINAL_CTRL_50_OHM |
795fdc62ca62d7e896ef8ad64b68127e81eb3bdc3fJingoo Han		TX_CUR1_2X | TX_CUR_16_MA;
808affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_PLL_FILTER_CTL_1);
818affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han
828affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han	reg = CH3_AMP_400_MV | CH2_AMP_400_MV |
838affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han		CH1_AMP_400_MV | CH0_AMP_400_MV;
848affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_TX_AMP_TUNING_CTL);
858affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han}
868affaf5c7698c627b133bfcafd9869ef17faff31Jingoo Han
87e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_init_interrupt(struct exynos_dp_device *dp)
88e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
89e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Set interrupt pin assertion polarity as high */
902f85f97e460a4bcfad678151fcc13dbf0b8181b3Ajay Kumar	writel(INT_POL1 | INT_POL0, dp->reg_base + EXYNOS_DP_INT_CTL);
91e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
92e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Clear pending regisers */
93e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
94e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2);
95e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3);
96e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
97e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA);
98e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
99e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* 0:mask,1: unmask */
100e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
101e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
102e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
103e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
104e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
105e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
106e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
107e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_reset(struct exynos_dp_device *dp)
108e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
109e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
110e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
111e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	exynos_dp_stop_video(dp);
112e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	exynos_dp_enable_video_mute(dp, 0);
113e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
114e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
115e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
116e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		HDCP_FUNC_EN_N | SW_FUNC_EN_N;
117e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
118e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
119e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
120e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		SERDES_FIFO_FUNC_EN_N |
121e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		LS_CLK_DOMAIN_FUNC_EN_N;
122e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
123e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
124a2c81bc12c81189928a03a94da1565d0c14e32ebJingoo Han	usleep_range(20, 30);
125e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
126e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	exynos_dp_lane_swap(dp, 0);
127e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
128e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
129e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
130e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
131e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
132e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
133e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL);
134e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL);
135e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
136e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L);
137e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H);
138e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
139e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL);
140e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
141e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST);
142e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
143e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD);
144e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN);
145e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
146e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH);
147e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
148e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
149e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
150e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
151e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
15224db03a834089a3600780ea1c7abe08e483e5d29Jingoo Hanvoid exynos_dp_swreset(struct exynos_dp_device *dp)
15324db03a834089a3600780ea1c7abe08e483e5d29Jingoo Han{
15424db03a834089a3600780ea1c7abe08e483e5d29Jingoo Han	writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
15524db03a834089a3600780ea1c7abe08e483e5d29Jingoo Han}
15624db03a834089a3600780ea1c7abe08e483e5d29Jingoo Han
157e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_config_interrupt(struct exynos_dp_device *dp)
158e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
159e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
160e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
161e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* 0: mask, 1: unmask */
162e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = COMMON_INT_MASK_1;
163e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
164e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
165e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = COMMON_INT_MASK_2;
166e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
167e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
168e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = COMMON_INT_MASK_3;
169e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
170e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
171e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = COMMON_INT_MASK_4;
172e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
173e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
174e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = INT_STA_MASK;
175e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
176e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
177e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
17809d00d170f8da388761cc29de1cf8c12c69c1300Sean Paulenum pll_status exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)
179e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
180e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
181e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
182e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
183e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	if (reg & PLL_LOCK)
184e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		return PLL_LOCKED;
185e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	else
186e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		return PLL_UNLOCKED;
187e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
188e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
189e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable)
190e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
191e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
192e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
193e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	if (enable) {
194e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
195e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg |= DP_PLL_PD;
196e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
197e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	} else {
198e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
199e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg &= ~DP_PLL_PD;
200e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
201e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
202e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
203e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
204e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
205e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				enum analog_power_block block,
206e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				bool enable)
207e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
208e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
209e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
210e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	switch (block) {
211e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	case AUX_BLOCK:
212e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		if (enable) {
213e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
214e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg |= AUX_PD;
215e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
216e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		} else {
217e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
218e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg &= ~AUX_PD;
219e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
220e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		}
221e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		break;
222e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	case CH0_BLOCK:
223e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		if (enable) {
224e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
225e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg |= CH0_PD;
226e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
227e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		} else {
228e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
229e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg &= ~CH0_PD;
230e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
231e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		}
232e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		break;
233e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	case CH1_BLOCK:
234e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		if (enable) {
235e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
236e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg |= CH1_PD;
237e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
238e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		} else {
239e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
240e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg &= ~CH1_PD;
241e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
242e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		}
243e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		break;
244e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	case CH2_BLOCK:
245e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		if (enable) {
246e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
247e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg |= CH2_PD;
248e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
249e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		} else {
250e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
251e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg &= ~CH2_PD;
252e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
253e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		}
254e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		break;
255e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	case CH3_BLOCK:
256e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		if (enable) {
257e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
258e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg |= CH3_PD;
259e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
260e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		} else {
261e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
262e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg &= ~CH3_PD;
263e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
264e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		}
265e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		break;
266e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	case ANALOG_TOTAL:
267e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		if (enable) {
268e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
269e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg |= DP_PHY_PD;
270e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
271e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		} else {
272e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
273e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg &= ~DP_PHY_PD;
274e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
275e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		}
276e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		break;
277e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	case POWER_ALL:
278e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		if (enable) {
279e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD |
280e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				CH1_PD | CH0_PD;
281e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
282e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		} else {
283e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD);
284e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		}
285e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		break;
286e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	default:
287e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		break;
288e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
289e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
290e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
291e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_init_analog_func(struct exynos_dp_device *dp)
292e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
293e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
294b5cfeed6cf90a4bb619b7ac640ba1a6dd002364dJingoo Han	int timeout_loop = 0;
295e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
296e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
297e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
298e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = PLL_LOCK_CHG;
299e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
300e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
301e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
302e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
303e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL);
304e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
305e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Power up PLL */
306b5cfeed6cf90a4bb619b7ac640ba1a6dd002364dJingoo Han	if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
307e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		exynos_dp_set_pll_power_down(dp, 0);
308e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
309b5cfeed6cf90a4bb619b7ac640ba1a6dd002364dJingoo Han		while (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
310b5cfeed6cf90a4bb619b7ac640ba1a6dd002364dJingoo Han			timeout_loop++;
311b5cfeed6cf90a4bb619b7ac640ba1a6dd002364dJingoo Han			if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
312b5cfeed6cf90a4bb619b7ac640ba1a6dd002364dJingoo Han				dev_err(dp->dev, "failed to get pll lock status\n");
313b5cfeed6cf90a4bb619b7ac640ba1a6dd002364dJingoo Han				return;
314b5cfeed6cf90a4bb619b7ac640ba1a6dd002364dJingoo Han			}
315b5cfeed6cf90a4bb619b7ac640ba1a6dd002364dJingoo Han			usleep_range(10, 20);
316b5cfeed6cf90a4bb619b7ac640ba1a6dd002364dJingoo Han		}
317b5cfeed6cf90a4bb619b7ac640ba1a6dd002364dJingoo Han	}
318b5cfeed6cf90a4bb619b7ac640ba1a6dd002364dJingoo Han
319e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Enable Serdes FIFO function and Link symbol clock domain module */
320e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
321e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
322e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		| AUX_FUNC_EN_N);
323e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
324e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
325e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
326c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paulvoid exynos_dp_clear_hotplug_interrupts(struct exynos_dp_device *dp)
327e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
328e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
329e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
330b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker	if (gpio_is_valid(dp->hpd_gpio))
331b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker		return;
332b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker
333e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = HOTPLUG_CHG | HPD_LOST | PLUG;
334e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
335e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
336e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = INT_HPD;
337e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
338c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul}
339c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul
340c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paulvoid exynos_dp_init_hpd(struct exynos_dp_device *dp)
341c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul{
342c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul	u32 reg;
343c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul
344b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker	if (gpio_is_valid(dp->hpd_gpio))
345b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker		return;
346b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker
347c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul	exynos_dp_clear_hotplug_interrupts(dp);
348e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
349e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
350e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg &= ~(F_HPD | HPD_CTRL);
351e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
352e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
353e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
354c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paulenum dp_irq_type exynos_dp_get_irq_type(struct exynos_dp_device *dp)
355c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul{
356c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul	u32 reg;
357c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul
358b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker	if (gpio_is_valid(dp->hpd_gpio)) {
359b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker		reg = gpio_get_value(dp->hpd_gpio);
360b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker		if (reg)
361b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker			return DP_IRQ_TYPE_HP_CABLE_IN;
362b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker		else
363b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker			return DP_IRQ_TYPE_HP_CABLE_OUT;
364b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker	} else {
365b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker		/* Parse hotplug interrupt status register */
366b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker		reg = readl(dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
367c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul
368b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker		if (reg & PLUG)
369b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker			return DP_IRQ_TYPE_HP_CABLE_IN;
370c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul
371b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker		if (reg & HPD_LOST)
372b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker			return DP_IRQ_TYPE_HP_CABLE_OUT;
373c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul
374b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker		if (reg & HOTPLUG_CHG)
375b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker			return DP_IRQ_TYPE_HP_CHANGE;
376c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul
377b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker		return DP_IRQ_TYPE_UNKNOWN;
378b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker	}
379c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul}
380c30ffb904cff819dc2423b1c3edd4f2e48f7acb0Sean Paul
381e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_reset_aux(struct exynos_dp_device *dp)
382e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
383e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
384e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
385e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Disable AUX channel module */
386e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
387e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg |= AUX_FUNC_EN_N;
388e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
389e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
390e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
391e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_init_aux(struct exynos_dp_device *dp)
392e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
393e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
394e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
395e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Clear inerrupts related to AUX channel */
396e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = RPLY_RECEIV | AUX_ERR;
397e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
398e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
399e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	exynos_dp_reset_aux(dp);
400e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
401e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Disable AUX transaction H/W retry */
402e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0)|
403e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
4047a80ec79f0328cc8829c901666adca968026f82dSachin Kamat	writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL);
405e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
406e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
407e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = DEFER_CTRL_EN | DEFER_COUNT(1);
408e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_DEFER_CTL);
409e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
410e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Enable AUX channel module */
411e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
412e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg &= ~AUX_FUNC_EN_N;
413e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
414e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
415e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
416e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanint exynos_dp_get_plug_in_status(struct exynos_dp_device *dp)
417e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
418e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
419e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
420b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker	if (gpio_is_valid(dp->hpd_gpio)) {
421b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker		if (gpio_get_value(dp->hpd_gpio))
422b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker			return 0;
423b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker	} else {
424b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
425b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker		if (reg & HPD_STATUS)
426b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker			return 0;
427b8b52471e87a713e61d26fa2f546fda0fb04e8fdAndrew Bresticker	}
428e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
429e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	return -EINVAL;
430e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
431e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
432e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_enable_sw_function(struct exynos_dp_device *dp)
433e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
434e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
435e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
436e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
437e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg &= ~SW_FUNC_EN_N;
438e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
439e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
440e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
441e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanint exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
442e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
443e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	int reg;
444e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	int retval = 0;
445bada55371fb2b3615983ba231cad61ef21bdf9c3Jingoo Han	int timeout_loop = 0;
446e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
447e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Enable AUX CH operation */
448e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
449e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg |= AUX_EN;
450e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
451e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
452e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Is AUX CH command reply received? */
453e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
454bada55371fb2b3615983ba231cad61ef21bdf9c3Jingoo Han	while (!(reg & RPLY_RECEIV)) {
455bada55371fb2b3615983ba231cad61ef21bdf9c3Jingoo Han		timeout_loop++;
456bada55371fb2b3615983ba231cad61ef21bdf9c3Jingoo Han		if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
457bada55371fb2b3615983ba231cad61ef21bdf9c3Jingoo Han			dev_err(dp->dev, "AUX CH command reply failed!\n");
458bada55371fb2b3615983ba231cad61ef21bdf9c3Jingoo Han			return -ETIMEDOUT;
459bada55371fb2b3615983ba231cad61ef21bdf9c3Jingoo Han		}
460e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
461bada55371fb2b3615983ba231cad61ef21bdf9c3Jingoo Han		usleep_range(10, 11);
462bada55371fb2b3615983ba231cad61ef21bdf9c3Jingoo Han	}
463e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
464e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Clear interrupt source for AUX CH command reply */
465e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
466e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
467e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Clear interrupt source for AUX CH access error */
468e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
469e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	if (reg & AUX_ERR) {
470e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA);
471e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		return -EREMOTEIO;
472e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
473e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
474e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Check AUX CH error access status */
475e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_STA);
476e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	if ((reg & AUX_STATUS_MASK) != 0) {
477e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		dev_err(dp->dev, "AUX CH error happens: %d\n\n",
478e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg & AUX_STATUS_MASK);
479e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		return -EREMOTEIO;
480e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
481e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
482e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	return retval;
483e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
484e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
485e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanint exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
486e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned int reg_addr,
487e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned char data)
488e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
489e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
490e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	int i;
491e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	int retval;
492e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
493e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	for (i = 0; i < 3; i++) {
494e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		/* Clear AUX CH data buffer */
495e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = BUF_CLR;
496e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
497e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
498e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		/* Select DPCD device address */
499e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = AUX_ADDR_7_0(reg_addr);
500e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
501e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = AUX_ADDR_15_8(reg_addr);
502e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
503e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = AUX_ADDR_19_16(reg_addr);
504e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
505e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
506e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		/* Write data buffer */
507e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = (unsigned int)data;
508e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
509e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
510e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		/*
511e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		 * Set DisplayPort transaction and write 1 byte
512e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		 * If bit 3 is 1, DisplayPort transaction.
513e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		 * If Bit 3 is 0, I2C transaction.
514e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		 */
515e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
516e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
517e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
518e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		/* Start AUX transaction */
519e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		retval = exynos_dp_start_aux_transaction(dp);
520e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		if (retval == 0)
521e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			break;
522e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		else
5238fefbb7519a37ad6c0752da1f939607d73a04edeSean Paul			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
5248fefbb7519a37ad6c0752da1f939607d73a04edeSean Paul				__func__);
525e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
526e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
527e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	return retval;
528e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
529e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
530e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanint exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
531e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned int reg_addr,
532e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned char *data)
533e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
534e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
535e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	int i;
536e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	int retval;
537e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
53899f541524c8cd7b54a4f64a1c225de940e950833Sean Paul	for (i = 0; i < 3; i++) {
539e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		/* Clear AUX CH data buffer */
540e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = BUF_CLR;
541e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
542e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
543e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		/* Select DPCD device address */
544e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = AUX_ADDR_7_0(reg_addr);
545e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
546e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = AUX_ADDR_15_8(reg_addr);
547e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
548e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = AUX_ADDR_19_16(reg_addr);
549e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
550e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
551e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		/*
552e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		 * Set DisplayPort transaction and read 1 byte
553e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		 * If bit 3 is 1, DisplayPort transaction.
554e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		 * If Bit 3 is 0, I2C transaction.
555e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		 */
556e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
557e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
558e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
559e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		/* Start AUX transaction */
560e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		retval = exynos_dp_start_aux_transaction(dp);
561e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		if (retval == 0)
562e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			break;
563e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		else
5648fefbb7519a37ad6c0752da1f939607d73a04edeSean Paul			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
5658fefbb7519a37ad6c0752da1f939607d73a04edeSean Paul				__func__);
566e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
567e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
568e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Read data buffer */
569e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
570e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	*data = (unsigned char)(reg & 0xff);
571e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
572e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	return retval;
573e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
574e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
575e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanint exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
576e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned int reg_addr,
577e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned int count,
578e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned char data[])
579e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
580e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
581e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	unsigned int start_offset;
582e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	unsigned int cur_data_count;
583e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	unsigned int cur_data_idx;
584e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	int i;
585e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	int retval = 0;
586e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
587e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Clear AUX CH data buffer */
588e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = BUF_CLR;
589e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
590e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
591e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	start_offset = 0;
592e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	while (start_offset < count) {
593e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		/* Buffer size of AUX CH is 16 * 4bytes */
594e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		if ((count - start_offset) > 16)
595e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			cur_data_count = 16;
596e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		else
597e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			cur_data_count = count - start_offset;
598e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
59999f541524c8cd7b54a4f64a1c225de940e950833Sean Paul		for (i = 0; i < 3; i++) {
600e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			/* Select DPCD device address */
601e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = AUX_ADDR_7_0(reg_addr + start_offset);
602e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
603e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = AUX_ADDR_15_8(reg_addr + start_offset);
604e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
605e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = AUX_ADDR_19_16(reg_addr + start_offset);
606e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
607e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
608e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			for (cur_data_idx = 0; cur_data_idx < cur_data_count;
609e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			     cur_data_idx++) {
610e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				reg = data[start_offset + cur_data_idx];
611e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0
612e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han							  + 4 * cur_data_idx);
613e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			}
614e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
615e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			/*
616e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			 * Set DisplayPort transaction and write
617e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			 * If bit 3 is 1, DisplayPort transaction.
618e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			 * If Bit 3 is 0, I2C transaction.
619e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			 */
620e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = AUX_LENGTH(cur_data_count) |
621e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
622e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
623e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
624e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			/* Start AUX transaction */
625e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			retval = exynos_dp_start_aux_transaction(dp);
626e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			if (retval == 0)
627e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				break;
628e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			else
6298fefbb7519a37ad6c0752da1f939607d73a04edeSean Paul				dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
6308fefbb7519a37ad6c0752da1f939607d73a04edeSean Paul					__func__);
631e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		}
632e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
633e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		start_offset += cur_data_count;
634e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
635e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
636e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	return retval;
637e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
638e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
639e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanint exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
640e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned int reg_addr,
641e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned int count,
642e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned char data[])
643e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
644e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
645e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	unsigned int start_offset;
646e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	unsigned int cur_data_count;
647e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	unsigned int cur_data_idx;
648e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	int i;
649e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	int retval = 0;
650e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
651e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Clear AUX CH data buffer */
652e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = BUF_CLR;
653e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
654e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
655e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	start_offset = 0;
656e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	while (start_offset < count) {
657e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		/* Buffer size of AUX CH is 16 * 4bytes */
658e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		if ((count - start_offset) > 16)
659e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			cur_data_count = 16;
660e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		else
661e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			cur_data_count = count - start_offset;
662e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
663e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		/* AUX CH Request Transaction process */
66499f541524c8cd7b54a4f64a1c225de940e950833Sean Paul		for (i = 0; i < 3; i++) {
665e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			/* Select DPCD device address */
666e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = AUX_ADDR_7_0(reg_addr + start_offset);
667e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
668e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = AUX_ADDR_15_8(reg_addr + start_offset);
669e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
670e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = AUX_ADDR_19_16(reg_addr + start_offset);
671e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
672e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
673e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			/*
674e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			 * Set DisplayPort transaction and read
675e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			 * If bit 3 is 1, DisplayPort transaction.
676e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			 * If Bit 3 is 0, I2C transaction.
677e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			 */
678e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = AUX_LENGTH(cur_data_count) |
679e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
680e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
681e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
682e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			/* Start AUX transaction */
683e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			retval = exynos_dp_start_aux_transaction(dp);
684e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			if (retval == 0)
685e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				break;
686e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			else
6878fefbb7519a37ad6c0752da1f939607d73a04edeSean Paul				dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
6888fefbb7519a37ad6c0752da1f939607d73a04edeSean Paul					__func__);
689e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		}
690e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
691e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		for (cur_data_idx = 0; cur_data_idx < cur_data_count;
692e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		    cur_data_idx++) {
693e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
694e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han						 + 4 * cur_data_idx);
695e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			data[start_offset + cur_data_idx] =
696e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				(unsigned char)reg;
697e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		}
698e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
699e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		start_offset += cur_data_count;
700e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
701e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
702e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	return retval;
703e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
704e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
705e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanint exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
706e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned int device_addr,
707e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned int reg_addr)
708e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
709e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
710e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	int retval;
711e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
712e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Set EDID device address */
713e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = device_addr;
714e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
715e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
716e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
717e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
718e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Set offset from base address of EDID device */
719e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg_addr, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
720e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
721e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/*
722e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	 * Set I2C transaction and write address
723e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	 * If bit 3 is 1, DisplayPort transaction.
724e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	 * If Bit 3 is 0, I2C transaction.
725e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	 */
726e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
727e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		AUX_TX_COMM_WRITE;
728e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
729e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
730e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Start AUX transaction */
731e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	retval = exynos_dp_start_aux_transaction(dp);
732e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	if (retval != 0)
7338fefbb7519a37ad6c0752da1f939607d73a04edeSean Paul		dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
734e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
735e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	return retval;
736e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
737e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
738e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanint exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
739e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned int device_addr,
740e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned int reg_addr,
741e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned int *data)
742e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
743e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
744e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	int i;
745e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	int retval;
746e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
74799f541524c8cd7b54a4f64a1c225de940e950833Sean Paul	for (i = 0; i < 3; i++) {
748e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		/* Clear AUX CH data buffer */
749e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = BUF_CLR;
750e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
751e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
752e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		/* Select EDID device */
753e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr);
75499f541524c8cd7b54a4f64a1c225de940e950833Sean Paul		if (retval != 0)
755e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			continue;
756e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
757e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		/*
758e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		 * Set I2C transaction and read data
759e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		 * If bit 3 is 1, DisplayPort transaction.
760e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		 * If Bit 3 is 0, I2C transaction.
761e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		 */
762e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = AUX_TX_COMM_I2C_TRANSACTION |
763e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			AUX_TX_COMM_READ;
764e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
765e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
766e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		/* Start AUX transaction */
767e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		retval = exynos_dp_start_aux_transaction(dp);
768e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		if (retval == 0)
769e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			break;
770e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		else
7718fefbb7519a37ad6c0752da1f939607d73a04edeSean Paul			dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
7728fefbb7519a37ad6c0752da1f939607d73a04edeSean Paul				__func__);
773e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
774e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
775e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Read data */
776e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	if (retval == 0)
777e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		*data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
778e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
779e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	return retval;
780e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
781e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
782e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanint exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
783e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned int device_addr,
784e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned int reg_addr,
785e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned int count,
786e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				unsigned char edid[])
787e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
788e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
789e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	unsigned int i, j;
790e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	unsigned int cur_data_idx;
791e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	unsigned int defer = 0;
792e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	int retval = 0;
793e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
794e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	for (i = 0; i < count; i += 16) {
79599f541524c8cd7b54a4f64a1c225de940e950833Sean Paul		for (j = 0; j < 3; j++) {
796e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			/* Clear AUX CH data buffer */
797e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = BUF_CLR;
798e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
799e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
800e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			/* Set normal AUX CH command */
801e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
802e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg &= ~ADDR_ONLY;
803e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
804e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
805e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			/*
806e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			 * If Rx sends defer, Tx sends only reads
807ff0c26424c1d993d8d1e04f72f1d428e935798daMasanari Iida			 * request without sending address
808e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			 */
809e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			if (!defer)
810e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				retval = exynos_dp_select_i2c_device(dp,
811e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han						device_addr, reg_addr + i);
812e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			else
813e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				defer = 0;
814e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
815e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			if (retval == 0) {
816e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				/*
817e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				 * Set I2C transaction and write data
818e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				 * If bit 3 is 1, DisplayPort transaction.
819e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				 * If Bit 3 is 0, I2C transaction.
820e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				 */
821e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				reg = AUX_LENGTH(16) |
822e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han					AUX_TX_COMM_I2C_TRANSACTION |
823e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han					AUX_TX_COMM_READ;
824e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				writel(reg, dp->reg_base +
825e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han					EXYNOS_DP_AUX_CH_CTL_1);
826e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
827e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				/* Start AUX transaction */
828e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				retval = exynos_dp_start_aux_transaction(dp);
829e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				if (retval == 0)
830e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han					break;
831e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				else
8328fefbb7519a37ad6c0752da1f939607d73a04edeSean Paul					dev_dbg(dp->dev,
8338fefbb7519a37ad6c0752da1f939607d73a04edeSean Paul						"%s: Aux Transaction fail!\n",
8348fefbb7519a37ad6c0752da1f939607d73a04edeSean Paul						__func__);
835e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			}
836e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			/* Check if Rx sends defer */
837e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
838e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			if (reg == AUX_RX_COMM_AUX_DEFER ||
839e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				reg == AUX_RX_COMM_I2C_DEFER) {
840e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				dev_err(dp->dev, "Defer: %d\n\n", reg);
841e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				defer = 1;
842e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			}
843e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		}
844e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
845e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
846e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
847e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han						 + 4 * cur_data_idx);
848e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			edid[i + cur_data_idx] = (unsigned char)reg;
849e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		}
850e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
851e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
852e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	return retval;
853e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
854e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
855e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype)
856e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
857e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
858e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
859e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = bwtype;
860e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype == LINK_RATE_1_62GBPS))
861e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_LINK_BW_SET);
862e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
863e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
864e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype)
865e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
866e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
867e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
868e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET);
869e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	*bwtype = reg;
870e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
871e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
872e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count)
873e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
874e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
875e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
876e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = count;
877e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
878e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
879e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
880e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count)
881e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
882e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
883e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
884e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
885e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	*count = reg;
886e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
887e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
888e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable)
889e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
890e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
891e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
892e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	if (enable) {
893e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
894e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg |= ENHANCED;
895e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
896e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	} else {
897e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
898e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg &= ~ENHANCED;
899e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
900e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
901e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
902e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
903e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
904e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han				 enum pattern_set pattern)
905e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
906e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
907e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
908e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	switch (pattern) {
909e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	case PRBS7:
910e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
911e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
912e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		break;
913e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	case D10_2:
914e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
915e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
916e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		break;
917e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	case TRAINING_PTN1:
918e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
919e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
920e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		break;
921e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	case TRAINING_PTN2:
922e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
923e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
924e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		break;
925e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	case DP_NONE:
926e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = SCRAMBLING_ENABLE |
927e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			LINK_QUAL_PATTERN_SET_DISABLE |
928e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han			SW_TRAINING_PATTERN_SET_NORMAL;
929e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
930e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		break;
931e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	default:
932e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		break;
933e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
934e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
935e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
936e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level)
937e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
938e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
939e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
940e3c02009003eebf84f7c56c7f330521553c8d299Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
941e3c02009003eebf84f7c56c7f330521553c8d299Jingoo Han	reg &= ~PRE_EMPHASIS_SET_MASK;
942e3c02009003eebf84f7c56c7f330521553c8d299Jingoo Han	reg |= level << PRE_EMPHASIS_SET_SHIFT;
943e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
944e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
945e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
946e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level)
947e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
948e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
949e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
950e3c02009003eebf84f7c56c7f330521553c8d299Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
951e3c02009003eebf84f7c56c7f330521553c8d299Jingoo Han	reg &= ~PRE_EMPHASIS_SET_MASK;
952e3c02009003eebf84f7c56c7f330521553c8d299Jingoo Han	reg |= level << PRE_EMPHASIS_SET_SHIFT;
953e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
954e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
955e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
956e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level)
957e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
958e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
959e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
960e3c02009003eebf84f7c56c7f330521553c8d299Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
961e3c02009003eebf84f7c56c7f330521553c8d299Jingoo Han	reg &= ~PRE_EMPHASIS_SET_MASK;
962e3c02009003eebf84f7c56c7f330521553c8d299Jingoo Han	reg |= level << PRE_EMPHASIS_SET_SHIFT;
963e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
964e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
965e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
966e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level)
967e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
968e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
969e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
970e3c02009003eebf84f7c56c7f330521553c8d299Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
971e3c02009003eebf84f7c56c7f330521553c8d299Jingoo Han	reg &= ~PRE_EMPHASIS_SET_MASK;
972e3c02009003eebf84f7c56c7f330521553c8d299Jingoo Han	reg |= level << PRE_EMPHASIS_SET_SHIFT;
973e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
974e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
975e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
976e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
977e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han					u32 training_lane)
978e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
979e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
980e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
981e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = training_lane;
982e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
983e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
984e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
985e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
986e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han					u32 training_lane)
987e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
988e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
989e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
990e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = training_lane;
991e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
992e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
993e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
994e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
995e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han					u32 training_lane)
996e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
997e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
998e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
999e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = training_lane;
1000e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
1001e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1002e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1003e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
1004e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han					u32 training_lane)
1005e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
1006e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
1007e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1008e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = training_lane;
1009e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
1010e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1011e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1012e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanu32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp)
1013e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
1014e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
1015e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1016e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
1017e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	return reg;
1018e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1019e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1020e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanu32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp)
1021e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
1022e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
1023e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1024e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
1025e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	return reg;
1026e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1027e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1028e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanu32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp)
1029e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
1030e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
1031e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1032e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
1033e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	return reg;
1034e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1035e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1036e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanu32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp)
1037e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
1038e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
1039e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1040e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
1041e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	return reg;
1042e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1043e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1044e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_reset_macro(struct exynos_dp_device *dp)
1045e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
1046e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
1047e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1048e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST);
1049e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg |= MACRO_RST;
1050e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
1051e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1052e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* 10 us is the minimum reset time. */
1053a2c81bc12c81189928a03a94da1565d0c14e32ebJingoo Han	usleep_range(10, 20);
1054e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1055e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg &= ~MACRO_RST;
1056e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
1057e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1058e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
10591ec7be9c9f3ee416d5c97c1c649f3cba9e41ee1dJingoo Hanvoid exynos_dp_init_video(struct exynos_dp_device *dp)
1060e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
1061e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
1062e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1063e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
1064e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
1065e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1066e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = 0x0;
1067e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
1068e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1069e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = CHA_CRI(4) | CHA_CTRL;
1070e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
1071e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1072e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = 0x0;
1073e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
1074e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1075e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = VID_HRES_TH(2) | VID_VRES_TH(0);
1076e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
1077e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1078e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
10793fcb6eb4063ab4eef05601c266afa2af667c8e1fAjay Kumarvoid exynos_dp_set_video_color_format(struct exynos_dp_device *dp)
1080e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
1081e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
1082e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1083e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Configure the input color depth, color space, dynamic range */
10843fcb6eb4063ab4eef05601c266afa2af667c8e1fAjay Kumar	reg = (dp->video_info->dynamic_range << IN_D_RANGE_SHIFT) |
10853fcb6eb4063ab4eef05601c266afa2af667c8e1fAjay Kumar		(dp->video_info->color_depth << IN_BPC_SHIFT) |
10863fcb6eb4063ab4eef05601c266afa2af667c8e1fAjay Kumar		(dp->video_info->color_space << IN_COLOR_F_SHIFT);
1087e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
1088e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1089e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	/* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
1090e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
1091e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg &= ~IN_YC_COEFFI_MASK;
10923fcb6eb4063ab4eef05601c266afa2af667c8e1fAjay Kumar	if (dp->video_info->ycbcr_coeff)
1093e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg |= IN_YC_COEFFI_ITU709;
1094e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	else
1095e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg |= IN_YC_COEFFI_ITU601;
1096e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
1097e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1098e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1099e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanint exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp)
1100e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
1101e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
1102e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1103e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
1104e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
1105e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1106e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
1107e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1108e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	if (!(reg & DET_STA)) {
1109e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		dev_dbg(dp->dev, "Input stream clock not detected.\n");
1110e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		return -EINVAL;
1111e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
1112e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1113e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
1114e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
1115e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1116e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
1117e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	dev_dbg(dp->dev, "wait SYS_CTL_2.\n");
1118e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1119e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	if (reg & CHA_STA) {
1120e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		dev_dbg(dp->dev, "Input stream clk is changing\n");
1121e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		return -EINVAL;
1122e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
1123e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1124e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	return 0;
1125e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1126e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1127e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
1128e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		enum clock_recovery_m_value_type type,
1129e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		u32 m_value,
1130e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		u32 n_value)
1131e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
1132e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
1133e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1134e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	if (type == REGISTER_M) {
1135e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
1136e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg |= FIX_M_VID;
1137e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
1138e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = m_value & 0xff;
1139e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0);
1140e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = (m_value >> 8) & 0xff;
1141e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1);
1142e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = (m_value >> 16) & 0xff;
1143e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2);
1144e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1145e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = n_value & 0xff;
1146e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0);
1147e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = (n_value >> 8) & 0xff;
1148e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1);
1149e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = (n_value >> 16) & 0xff;
1150e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2);
1151e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	} else  {
1152e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
1153e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg &= ~FIX_M_VID;
1154e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
1155e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1156e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0);
1157e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1);
1158e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2);
1159e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
1160e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1161e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1162e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type)
1163e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
1164e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
1165e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1166e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	if (type == VIDEO_TIMING_FROM_CAPTURE) {
1167e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1168e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg &= ~FORMAT_SEL;
1169e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1170e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	} else {
1171e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1172e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg |= FORMAT_SEL;
1173e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1174e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
1175e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1176e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1177e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable)
1178e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
1179e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
1180e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1181e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	if (enable) {
1182e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1183e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg &= ~VIDEO_MODE_MASK;
1184e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
1185e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1186e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	} else {
1187e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1188e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg &= ~VIDEO_MODE_MASK;
1189e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		reg |= VIDEO_MODE_SLAVE_MODE;
1190e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1191e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
1192e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1193e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1194e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_start_video(struct exynos_dp_device *dp)
1195e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
1196e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
1197e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1198e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
1199e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg |= VIDEO_EN;
1200e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
1201e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1202e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1203e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanint exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
1204e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
1205e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
1206e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1207e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
1208e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
1209e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1210e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
1211e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	if (!(reg & STRM_VALID)) {
1212e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		dev_dbg(dp->dev, "Input video stream is not detected.\n");
1213e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han		return -EINVAL;
1214e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	}
1215e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1216e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	return 0;
1217e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1218e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
12193fcb6eb4063ab4eef05601c266afa2af667c8e1fAjay Kumarvoid exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp)
1220e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
1221e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
1222e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1223e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
1224e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
1225e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg |= MASTER_VID_FUNC_EN_N;
1226e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
1227e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1228e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1229e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg &= ~INTERACE_SCAN_CFG;
12303fcb6eb4063ab4eef05601c266afa2af667c8e1fAjay Kumar	reg |= (dp->video_info->interlaced << 2);
1231e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1232e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1233e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1234e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg &= ~VSYNC_POLARITY_CFG;
12353fcb6eb4063ab4eef05601c266afa2af667c8e1fAjay Kumar	reg |= (dp->video_info->v_sync_polarity << 1);
1236e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1237e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1238e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1239e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg &= ~HSYNC_POLARITY_CFG;
12403fcb6eb4063ab4eef05601c266afa2af667c8e1fAjay Kumar	reg |= (dp->video_info->h_sync_polarity << 0);
1241e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1242e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1243e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
1244e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1245e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1246e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1247e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_enable_scrambling(struct exynos_dp_device *dp)
1248e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
1249e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
1250e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1251e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
1252e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg &= ~SCRAMBLING_DISABLE;
1253e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
1254e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1255e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1256e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Hanvoid exynos_dp_disable_scrambling(struct exynos_dp_device *dp)
1257e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han{
1258e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	u32 reg;
1259e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han
1260e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
1261e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	reg |= SCRAMBLING_DISABLE;
1262e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han	writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
1263e9474be4eb6918c91cb0d296f9744e8ec0e08c11Jingoo Han}
1264