blob: c9579316e2a993a5d74808cf2a58756fc961f122 [file] [log] [blame]
Ronald G. Minnich6bde1492013-03-01 10:18:14 -08001/*
Stefan Reinauer08dc3572013-05-14 16:57:50 -07002 * This file is part of the coreboot project.
Ronald G. Minnich6bde1492013-03-01 10:18:14 -08003 *
Stefan Reinauer08dc3572013-05-14 16:57:50 -07004 * Copyright (C) 2012 Samsung Electronics
Ronald G. Minnich6bde1492013-03-01 10:18:14 -08005 *
Stefan Reinauer08dc3572013-05-14 16:57:50 -07006 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080014 */
15
Stefan Reinauer08dc3572013-05-14 16:57:50 -070016/* Samsung DP (Display port) register interface driver. */
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080017
Stefan Reinauer08dc3572013-05-14 16:57:50 -070018#include <arch/io.h>
Julius Werner1ed0c8c2014-10-20 13:16:29 -070019#include <console/console.h>
Stefan Reinauer08dc3572013-05-14 16:57:50 -070020#include <delay.h>
Julius Werner1ed0c8c2014-10-20 13:16:29 -070021#include <soc/clk.h>
22#include <soc/cpu.h>
23#include <soc/dp.h>
24#include <soc/dp-core.h>
25#include <soc/fimd.h>
26#include <soc/periph.h>
27#include <timer.h>
Ronald G. Minnich7576f252013-04-09 14:39:34 -070028
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080029void s5p_dp_reset(struct s5p_dp_device *dp)
30{
31 u32 reg;
32 struct exynos5_dp *base = dp->base;
33
Julius Werner2f37bd62015-02-19 14:51:15 -080034 write32(&base->dp_tx_sw_reset, RESET_DP_TX);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080035
36 /* Stop Video */
37 clrbits_le32(&base->video_ctl_1, VIDEO_EN);
38 clrbits_le32(&base->video_ctl_1, HDCP_VIDEO_MUTE);
39
40 reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
41 AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
42 HDCP_FUNC_EN_N | SW_FUNC_EN_N;
Julius Werner2f37bd62015-02-19 14:51:15 -080043 write32(&base->func_en_1, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080044
45 reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
46 SERDES_FIFO_FUNC_EN_N |
47 LS_CLK_DOMAIN_FUNC_EN_N;
Julius Werner2f37bd62015-02-19 14:51:15 -080048 write32(&base->func_en_2, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080049
50 udelay(20);
51
52 reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
53 LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
54
Julius Werner2f37bd62015-02-19 14:51:15 -080055 write32(&base->lane_map, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080056
Julius Werner2f37bd62015-02-19 14:51:15 -080057 write32(&base->sys_ctl_1, 0x0);
58 write32(&base->sys_ctl_2, 0x40);
59 write32(&base->sys_ctl_3, 0x0);
60 write32(&base->sys_ctl_4, 0x0);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080061
Julius Werner2f37bd62015-02-19 14:51:15 -080062 write32(&base->pkt_send_ctl, 0x0);
63 write32(&base->dp_hdcp_ctl, 0x0);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080064
Julius Werner2f37bd62015-02-19 14:51:15 -080065 write32(&base->dp_hpd_deglitch_l, 0x5e);
66 write32(&base->dp_hpd_deglitch_h, 0x1a);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080067
Julius Werner2f37bd62015-02-19 14:51:15 -080068 write32(&base->dp_debug_ctl, 0x10);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080069
Julius Werner2f37bd62015-02-19 14:51:15 -080070 write32(&base->dp_phy_test, 0x0);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080071
Julius Werner2f37bd62015-02-19 14:51:15 -080072 write32(&base->dp_video_fifo_thrd, 0x0);
73 write32(&base->dp_audio_margin, 0x20);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080074
Julius Werner2f37bd62015-02-19 14:51:15 -080075 write32(&base->m_vid_gen_filter_th, 0x4);
76 write32(&base->m_aud_gen_filter_th, 0x2);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080077
Julius Werner2f37bd62015-02-19 14:51:15 -080078 write32(&base->soc_general_ctl, 0x00000101);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080079
80 /* Set Analog Parameters */
Julius Werner2f37bd62015-02-19 14:51:15 -080081 write32(&base->analog_ctl_1, 0x10);
82 write32(&base->analog_ctl_2, 0x0C);
83 write32(&base->analog_ctl_3, 0x85);
84 write32(&base->pll_filter_ctl_1, 0x66);
85 write32(&base->tx_amp_tuning_ctl, 0x0);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080086
87 /* Set interrupt pin assertion polarity as high */
Julius Werner2f37bd62015-02-19 14:51:15 -080088 write32(&base->int_ctl, INT_POL0 | INT_POL1);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080089
Martin Roth4c3ab732013-07-08 16:23:54 -060090 /* Clear pending registers */
Julius Werner2f37bd62015-02-19 14:51:15 -080091 write32(&base->common_int_sta_1, 0xff);
92 write32(&base->common_int_sta_2, 0x4f);
93 write32(&base->common_int_sta_3, 0xe0);
94 write32(&base->common_int_sta_4, 0xe7);
95 write32(&base->dp_int_sta, 0x63);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -080096
97 /* 0:mask,1: unmask */
Julius Werner2f37bd62015-02-19 14:51:15 -080098 write32(&base->common_int_mask_1, 0x00);
99 write32(&base->common_int_mask_2, 0x00);
100 write32(&base->common_int_mask_3, 0x00);
101 write32(&base->common_int_mask_4, 0x00);
102 write32(&base->int_sta_mask, 0x00);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800103}
104
105unsigned int s5p_dp_get_pll_lock_status(struct s5p_dp_device *dp)
106{
107 u32 reg;
108
Julius Werner2f37bd62015-02-19 14:51:15 -0800109 reg = read32(&dp->base->dp_debug_ctl);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800110 if (reg & PLL_LOCK)
111 return PLL_LOCKED;
112 else
113 return PLL_UNLOCKED;
114}
115
116int s5p_dp_init_analog_func(struct s5p_dp_device *dp)
117{
118 u32 reg;
Aaron Durbin43933462014-09-24 10:27:29 -0500119 struct stopwatch sw;
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800120 struct exynos5_dp *base = dp->base;
121
Julius Werner2f37bd62015-02-19 14:51:15 -0800122 write32(&base->dp_phy_pd, 0x00);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800123
124 reg = PLL_LOCK_CHG;
Julius Werner2f37bd62015-02-19 14:51:15 -0800125 write32(&base->common_int_sta_1, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800126
127 clrbits_le32(&base->dp_debug_ctl, (F_PLL_LOCK | PLL_LOCK_CTRL));
128
129 /* Power up PLL */
130 if (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
131
132 clrbits_le32(&base->dp_pll_ctl, DP_PLL_PD);
133
Aaron Durbin43933462014-09-24 10:27:29 -0500134 stopwatch_init_msecs_expire(&sw, PLL_LOCK_TIMEOUT);
Gabe Black9b764a02013-07-30 15:11:35 -0700135
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800136 while (s5p_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
Aaron Durbin43933462014-09-24 10:27:29 -0500137 if (stopwatch_expired(&sw)) {
Ronald G. Minnich2810afa2013-04-18 18:09:24 -0700138 printk(BIOS_ERR, "%s: PLL is not locked\n",
139 __func__);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800140 return -1;
141 }
142 }
143 }
144
145 /* Enable Serdes FIFO function and Link symbol clock domain module */
146 clrbits_le32(&base->func_en_2, (SERDES_FIFO_FUNC_EN_N |
147 LS_CLK_DOMAIN_FUNC_EN_N | AUX_FUNC_EN_N));
148 return 0;
149}
150
151void s5p_dp_init_aux(struct s5p_dp_device *dp)
152{
153 u32 reg;
154 struct exynos5_dp *base = dp->base;
155
Martin Roth4c3ab732013-07-08 16:23:54 -0600156 /* Clear interrupts related to AUX channel */
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800157 reg = RPLY_RECEIV | AUX_ERR;
Julius Werner2f37bd62015-02-19 14:51:15 -0800158 write32(&base->dp_int_sta, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800159
160 /* Disable AUX channel module */
161 setbits_le32(&base->func_en_2, AUX_FUNC_EN_N);
162
163 /* Disable AUX transaction H/W retry */
164 reg = (3 & AUX_BIT_PERIOD_MASK) << AUX_BIT_PERIOD_SHIFT;
165 reg |= (0 & AUX_HW_RETRY_COUNT_MASK) << AUX_HW_RETRY_COUNT_SHIFT;
166 reg |= (AUX_HW_RETRY_INTERVAL_600_US << AUX_HW_RETRY_INTERVAL_SHIFT);
Julius Werner2f37bd62015-02-19 14:51:15 -0800167 write32(&base->aux_hw_retry_ctl, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800168
169 /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
170 reg = DEFER_CTRL_EN;
171 reg |= (1 & DEFER_COUNT_MASK) << DEFER_COUNT_SHIFT;
Julius Werner2f37bd62015-02-19 14:51:15 -0800172 write32(&base->aux_ch_defer_dtl, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800173
174 /* Enable AUX channel module */
175 clrbits_le32(&base->func_en_2, AUX_FUNC_EN_N);
176}
177
178int s5p_dp_start_aux_transaction(struct s5p_dp_device *dp)
179{
180 int reg;
181 struct exynos5_dp *base = dp->base;
182
183 /* Enable AUX CH operation */
184 setbits_le32(&base->aux_ch_ctl_2, AUX_EN);
185
186 /* Is AUX CH command reply received? */
Julius Werner2f37bd62015-02-19 14:51:15 -0800187 reg = read32(&base->dp_int_sta);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800188 while (!(reg & RPLY_RECEIV))
Julius Werner2f37bd62015-02-19 14:51:15 -0800189 reg = read32(&base->dp_int_sta);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800190
191 /* Clear interrupt source for AUX CH command reply */
Julius Werner2f37bd62015-02-19 14:51:15 -0800192 write32(&base->dp_int_sta, RPLY_RECEIV);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800193
194 /* Clear interrupt source for AUX CH access error */
Julius Werner2f37bd62015-02-19 14:51:15 -0800195 reg = read32(&base->dp_int_sta);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800196 if (reg & AUX_ERR) {
Ronald G. Minnich2810afa2013-04-18 18:09:24 -0700197 printk(BIOS_ERR, "%s: AUX_ERR encountered, dp_int_sta: "
198 "0x%02x\n", __func__, reg);
Julius Werner2f37bd62015-02-19 14:51:15 -0800199 write32(&base->dp_int_sta, AUX_ERR);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800200 return -1;
201 }
202
203 /* Check AUX CH error access status */
Julius Werner2f37bd62015-02-19 14:51:15 -0800204 reg = read32(&base->dp_int_sta);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800205 if ((reg & AUX_STATUS_MASK) != 0) {
Ronald G. Minnich2810afa2013-04-18 18:09:24 -0700206 printk(BIOS_ERR, "AUX CH error happens: %d\n\n",
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800207 reg & AUX_STATUS_MASK);
208 return -1;
209 }
210
211 return 0;
212}
213
214int s5p_dp_write_byte_to_dpcd(struct s5p_dp_device *dp,
215 unsigned int reg_addr,
216 unsigned char data)
217{
218 u32 reg;
219 int i;
220 int retval;
221 struct exynos5_dp *base = dp->base;
222
223 for (i = 0; i < MAX_AUX_RETRY_COUNT; i++) {
224 /* Clear AUX CH data buffer */
Julius Werner2f37bd62015-02-19 14:51:15 -0800225 write32(&base->buf_data_ctl, BUF_CLR);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800226
227 /* Select DPCD device address */
228 reg = reg_addr >> AUX_ADDR_7_0_SHIFT;
229 reg &= AUX_ADDR_7_0_MASK;
Julius Werner2f37bd62015-02-19 14:51:15 -0800230 write32(&base->aux_addr_7_0, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800231 reg = reg_addr >> AUX_ADDR_15_8_SHIFT;
232 reg &= AUX_ADDR_15_8_MASK;
Julius Werner2f37bd62015-02-19 14:51:15 -0800233 write32(&base->aux_addr_15_8, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800234 reg = reg_addr >> AUX_ADDR_19_16_SHIFT;
235 reg &= AUX_ADDR_19_16_MASK;
Julius Werner2f37bd62015-02-19 14:51:15 -0800236 write32(&base->aux_addr_19_16, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800237
238 /* Write data buffer */
239 reg = (unsigned int)data;
Julius Werner2f37bd62015-02-19 14:51:15 -0800240 write32(&base->buf_data_0, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800241
242 /*
243 * Set DisplayPort transaction and write 1 byte
244 * If bit 3 is 1, DisplayPort transaction.
245 * If Bit 3 is 0, I2C transaction.
246 */
247 reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
Julius Werner2f37bd62015-02-19 14:51:15 -0800248 write32(&base->aux_ch_ctl_1, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800249
250 /* Start AUX transaction */
251 retval = s5p_dp_start_aux_transaction(dp);
252 if (retval == 0)
253 break;
254 else
Ronald G. Minnich7576f252013-04-09 14:39:34 -0700255 printk(BIOS_DEBUG, "Aux Transaction fail!\n");
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800256 }
257
258 return retval;
259}
260
261int s5p_dp_read_byte_from_dpcd(struct s5p_dp_device *dp,
262 unsigned int reg_addr,
263 unsigned char *data)
264{
265 u32 reg;
266 int i;
267 int retval;
268 struct exynos5_dp *base = dp->base;
269
270 for (i = 0; i < MAX_AUX_RETRY_COUNT; i++) {
271 /* Clear AUX CH data buffer */
Julius Werner2f37bd62015-02-19 14:51:15 -0800272 write32(&base->buf_data_ctl, BUF_CLR);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800273
274 /* Select DPCD device address */
275 reg = reg_addr >> AUX_ADDR_7_0_SHIFT;
276 reg &= AUX_ADDR_7_0_MASK;
Julius Werner2f37bd62015-02-19 14:51:15 -0800277 write32(&base->aux_addr_7_0, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800278 reg = reg_addr >> AUX_ADDR_15_8_SHIFT;
279 reg &= AUX_ADDR_15_8_MASK;
Julius Werner2f37bd62015-02-19 14:51:15 -0800280 write32(&base->aux_addr_15_8, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800281 reg = reg_addr >> AUX_ADDR_19_16_SHIFT;
282 reg &= AUX_ADDR_19_16_MASK;
Julius Werner2f37bd62015-02-19 14:51:15 -0800283 write32(&base->aux_addr_19_16, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800284
285 /*
286 * Set DisplayPort transaction and read 1 byte
287 * If bit 3 is 1, DisplayPort transaction.
288 * If Bit 3 is 0, I2C transaction.
289 */
290 reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
Julius Werner2f37bd62015-02-19 14:51:15 -0800291 write32(&base->aux_ch_ctl_1, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800292
293 /* Start AUX transaction */
294 retval = s5p_dp_start_aux_transaction(dp);
295 if (retval == 0)
296 break;
297 else
Ronald G. Minnich7576f252013-04-09 14:39:34 -0700298 printk(BIOS_DEBUG, "Aux Transaction fail!\n");
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800299 }
300
301 /* Read data buffer */
302 if (!retval) {
Julius Werner2f37bd62015-02-19 14:51:15 -0800303 reg = read32(&base->buf_data_0);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800304 *data = (unsigned char)(reg & 0xff);
305 }
306
307 return retval;
308}
309
310void s5p_dp_init_video(struct s5p_dp_device *dp)
311{
312 u32 reg;
313 struct exynos5_dp *base = dp->base;
314
315 reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
Julius Werner2f37bd62015-02-19 14:51:15 -0800316 write32(&base->common_int_sta_1, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800317
318 reg = 0x0;
Julius Werner2f37bd62015-02-19 14:51:15 -0800319 write32(&base->sys_ctl_1, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800320
321 reg = (4 & CHA_CRI_MASK) << CHA_CRI_SHIFT;
322 reg |= CHA_CTRL;
Julius Werner2f37bd62015-02-19 14:51:15 -0800323 write32(&base->sys_ctl_2, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800324
325 reg = 0x0;
Julius Werner2f37bd62015-02-19 14:51:15 -0800326 write32(&base->sys_ctl_3, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800327}
328
329void s5p_dp_set_video_color_format(struct s5p_dp_device *dp,
330 unsigned int color_depth,
331 unsigned int color_space,
332 unsigned int dynamic_range,
333 unsigned int coeff)
334{
335 u32 reg;
336 struct exynos5_dp *base = dp->base;
337
338 /* Configure the input color depth, color space, dynamic range */
339 reg = (dynamic_range << IN_D_RANGE_SHIFT) |
340 (color_depth << IN_BPC_SHIFT) |
341 (color_space << IN_COLOR_F_SHIFT);
Julius Werner2f37bd62015-02-19 14:51:15 -0800342 write32(&base->video_ctl_2, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800343
344 /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
Julius Werner2f37bd62015-02-19 14:51:15 -0800345 reg = read32(&base->video_ctl_3);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800346 reg &= ~IN_YC_COEFFI_MASK;
347 if (coeff)
348 reg |= IN_YC_COEFFI_ITU709;
349 else
350 reg |= IN_YC_COEFFI_ITU601;
Julius Werner2f37bd62015-02-19 14:51:15 -0800351 write32(&base->video_ctl_3, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800352}
353
354int s5p_dp_is_slave_video_stream_clock_on(struct s5p_dp_device *dp)
355{
356 u32 reg;
357 struct exynos5_dp *base = dp->base;
358
Julius Werner2f37bd62015-02-19 14:51:15 -0800359 reg = read32(&base->sys_ctl_1);
360 write32(&base->sys_ctl_1, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800361
Julius Werner2f37bd62015-02-19 14:51:15 -0800362 reg = read32(&base->sys_ctl_1);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800363
364 if (!(reg & DET_STA))
365 return -1;
366
Julius Werner2f37bd62015-02-19 14:51:15 -0800367 reg = read32(&base->sys_ctl_2);
368 write32(&base->sys_ctl_2, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800369
Julius Werner2f37bd62015-02-19 14:51:15 -0800370 reg = read32(&base->sys_ctl_2);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800371
372 if (reg & CHA_STA) {
Ronald G. Minnich7576f252013-04-09 14:39:34 -0700373 printk(BIOS_DEBUG, "Input stream clk is changing\n");
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800374 return -1;
375 }
376
377 return 0;
378}
379
380void s5p_dp_set_video_cr_mn(struct s5p_dp_device *dp,
381 enum clock_recovery_m_value_type type,
382 unsigned int m_value,
383 unsigned int n_value)
384{
385 u32 reg;
386 struct exynos5_dp *base = dp->base;
387
388 if (type == REGISTER_M) {
389 setbits_le32(&base->sys_ctl_4, FIX_M_VID);
390
391 reg = m_value >> M_VID_0_VALUE_SHIFT;
Julius Werner2f37bd62015-02-19 14:51:15 -0800392 write32(&base->m_vid_0, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800393
394 reg = (m_value >> M_VID_1_VALUE_SHIFT);
Julius Werner2f37bd62015-02-19 14:51:15 -0800395 write32(&base->m_vid_1, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800396
397 reg = (m_value >> M_VID_2_VALUE_SHIFT);
Julius Werner2f37bd62015-02-19 14:51:15 -0800398 write32(&base->m_vid_2, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800399
400 reg = n_value >> N_VID_0_VALUE_SHIFT;
Julius Werner2f37bd62015-02-19 14:51:15 -0800401 write32(&base->n_vid_0, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800402
403 reg = (n_value >> N_VID_1_VALUE_SHIFT);
Julius Werner2f37bd62015-02-19 14:51:15 -0800404 write32(&base->n_vid_1, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800405
406 reg = (n_value >> N_VID_2_VALUE_SHIFT);
Julius Werner2f37bd62015-02-19 14:51:15 -0800407 write32(&base->n_vid_2, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800408 } else {
409 clrbits_le32(&base->sys_ctl_4, FIX_M_VID);
410
Julius Werner2f37bd62015-02-19 14:51:15 -0800411 write32(&base->n_vid_0, 0x00);
412 write32(&base->n_vid_1, 0x80);
413 write32(&base->n_vid_2, 0x00);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800414 }
415}
416
417void s5p_dp_enable_video_master(struct s5p_dp_device *dp)
418{
419 u32 reg;
420 struct exynos5_dp *base = dp->base;
421
Julius Werner2f37bd62015-02-19 14:51:15 -0800422 reg = read32(&base->soc_general_ctl);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800423 reg &= ~VIDEO_MODE_MASK;
424 reg |= VIDEO_MODE_SLAVE_MODE;
Julius Werner2f37bd62015-02-19 14:51:15 -0800425 write32(&base->soc_general_ctl, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800426}
427
428int s5p_dp_is_video_stream_on(struct s5p_dp_device *dp)
429{
430 u32 reg, i = 0;
Aaron Durbin43933462014-09-24 10:27:29 -0500431 struct stopwatch sw;
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800432 struct exynos5_dp *base = dp->base;
433
434 /* Wait for 4 VSYNC_DET interrupts */
Aaron Durbin43933462014-09-24 10:27:29 -0500435 stopwatch_init_msecs_expire(&sw, STREAM_ON_TIMEOUT);
Gabe Black9b764a02013-07-30 15:11:35 -0700436
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800437 do {
Julius Werner2f37bd62015-02-19 14:51:15 -0800438 reg = read32(&base->common_int_sta_1);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800439 if (reg & VSYNC_DET) {
440 i++;
Julius Werner2f37bd62015-02-19 14:51:15 -0800441 write32(&base->common_int_sta_1, reg | VSYNC_DET);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800442 }
443 if (i == 4)
444 break;
Aaron Durbin43933462014-09-24 10:27:29 -0500445 } while (!stopwatch_expired(&sw));
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800446
447 if (i != 4) {
Ronald G. Minnich7576f252013-04-09 14:39:34 -0700448 printk(BIOS_DEBUG, "s5p_dp_is_video_stream_on timeout\n");
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800449 return -1;
450 }
451
452 return 0;
453}
454
455void s5p_dp_config_video_slave_mode(struct s5p_dp_device *dp,
456 struct video_info *video_info)
457{
458 u32 reg;
459 struct exynos5_dp *base = dp->base;
460
Julius Werner2f37bd62015-02-19 14:51:15 -0800461 reg = read32(&base->func_en_1);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800462 reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
463 reg |= MASTER_VID_FUNC_EN_N;
Julius Werner2f37bd62015-02-19 14:51:15 -0800464 write32(&base->func_en_1, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800465
Julius Werner2f37bd62015-02-19 14:51:15 -0800466 reg = read32(&base->video_ctl_10);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800467 reg &= ~INTERACE_SCAN_CFG;
468 reg |= (video_info->interlaced << 2);
Julius Werner2f37bd62015-02-19 14:51:15 -0800469 write32(&base->video_ctl_10, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800470
Julius Werner2f37bd62015-02-19 14:51:15 -0800471 reg = read32(&base->video_ctl_10);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800472 reg &= ~VSYNC_POLARITY_CFG;
473 reg |= (video_info->v_sync_polarity << 1);
Julius Werner2f37bd62015-02-19 14:51:15 -0800474 write32(&base->video_ctl_10, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800475
Julius Werner2f37bd62015-02-19 14:51:15 -0800476 reg = read32(&base->video_ctl_10);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800477 reg &= ~HSYNC_POLARITY_CFG;
478 reg |= (video_info->h_sync_polarity << 0);
Julius Werner2f37bd62015-02-19 14:51:15 -0800479 write32(&base->video_ctl_10, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800480
481 reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
Julius Werner2f37bd62015-02-19 14:51:15 -0800482 write32(&base->soc_general_ctl, reg);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800483}
484
485void s5p_dp_wait_hw_link_training_done(struct s5p_dp_device *dp)
486{
487 u32 reg;
488 struct exynos5_dp *base = dp->base;
489
Julius Werner2f37bd62015-02-19 14:51:15 -0800490 reg = read32(&base->dp_hw_link_training);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800491 while (reg & HW_TRAINING_EN)
Julius Werner2f37bd62015-02-19 14:51:15 -0800492 reg = read32(&base->dp_hw_link_training);
Ronald G. Minnich6bde1492013-03-01 10:18:14 -0800493}