aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJingoo Han <jg1.han@samsung.com>2012-02-03 04:01:55 -0500
committerFlorian Tobias Schandinat <FlorianSchandinat@gmx.de>2012-02-12 22:02:30 -0500
commite9474be4eb6918c91cb0d296f9744e8ec0e08c11 (patch)
treea7f0b9282258ab3153a7870b09de553d5080bcbe
parent9befe40f6e018e508b047eb76d189ede9b4ff03d (diff)
video: support DP controller driver
Samsung EXYNOS SoC such Exynos5 has DP controller and embedded DP panel can be used. This patch supports DP driver based on Samsung EXYNOS SoC chip. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Florian Tobias Schandinat <FlorianSchandinat@gmx.de>
-rw-r--r--drivers/video/exynos/Kconfig7
-rw-r--r--drivers/video/exynos/Makefile1
-rw-r--r--drivers/video/exynos/exynos_dp_core.c1058
-rw-r--r--drivers/video/exynos/exynos_dp_core.h206
-rw-r--r--drivers/video/exynos/exynos_dp_reg.c1173
-rw-r--r--drivers/video/exynos/exynos_dp_reg.h335
-rw-r--r--include/video/exynos_dp.h131
7 files changed, 2911 insertions, 0 deletions
diff --git a/drivers/video/exynos/Kconfig b/drivers/video/exynos/Kconfig
index 7032ad9f3fb..1b035b2eb6b 100644
--- a/drivers/video/exynos/Kconfig
+++ b/drivers/video/exynos/Kconfig
@@ -27,4 +27,11 @@ config EXYNOS_LCD_S6E8AX0
27 If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its 27 If you have an S6E8AX0 MIPI AMOLED LCD Panel, say Y to enable its
28 LCD control driver. 28 LCD control driver.
29 29
30config EXYNOS_DP
31 bool "EXYNOS DP driver support"
32 depends on ARCH_EXYNOS
33 default n
34 help
35 This enables support for DP device.
36
30endif # EXYNOS_VIDEO 37endif # EXYNOS_VIDEO
diff --git a/drivers/video/exynos/Makefile b/drivers/video/exynos/Makefile
index b5b1bd228ab..ec7772e452a 100644
--- a/drivers/video/exynos/Makefile
+++ b/drivers/video/exynos/Makefile
@@ -5,3 +5,4 @@
5obj-$(CONFIG_EXYNOS_MIPI_DSI) += exynos_mipi_dsi.o exynos_mipi_dsi_common.o \ 5obj-$(CONFIG_EXYNOS_MIPI_DSI) += exynos_mipi_dsi.o exynos_mipi_dsi_common.o \
6 exynos_mipi_dsi_lowlevel.o 6 exynos_mipi_dsi_lowlevel.o
7obj-$(CONFIG_EXYNOS_LCD_S6E8AX0) += s6e8ax0.o 7obj-$(CONFIG_EXYNOS_LCD_S6E8AX0) += s6e8ax0.o
8obj-$(CONFIG_EXYNOS_DP) += exynos_dp_core.o exynos_dp_reg.o
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
new file mode 100644
index 00000000000..2a4481cf260
--- /dev/null
+++ b/drivers/video/exynos/exynos_dp_core.c
@@ -0,0 +1,1058 @@
1/*
2 * Samsung SoC DP (Display Port) interface driver.
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Author: Jingoo Han <jg1.han@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/module.h>
14#include <linux/platform_device.h>
15#include <linux/slab.h>
16#include <linux/err.h>
17#include <linux/clk.h>
18#include <linux/io.h>
19#include <linux/interrupt.h>
20#include <linux/delay.h>
21
22#include <video/exynos_dp.h>
23
24#include <plat/cpu.h>
25
26#include "exynos_dp_core.h"
27
28static int exynos_dp_init_dp(struct exynos_dp_device *dp)
29{
30 exynos_dp_reset(dp);
31
32 /* SW defined function Normal operation */
33 exynos_dp_enable_sw_function(dp);
34
35 exynos_dp_config_interrupt(dp);
36 exynos_dp_init_analog_func(dp);
37
38 exynos_dp_init_hpd(dp);
39 exynos_dp_init_aux(dp);
40
41 return 0;
42}
43
44static int exynos_dp_detect_hpd(struct exynos_dp_device *dp)
45{
46 int timeout_loop = 0;
47
48 exynos_dp_init_hpd(dp);
49
50 udelay(200);
51
52 while (exynos_dp_get_plug_in_status(dp) != 0) {
53 timeout_loop++;
54 if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
55 dev_err(dp->dev, "failed to get hpd plug status\n");
56 return -ETIMEDOUT;
57 }
58 udelay(10);
59 }
60
61 return 0;
62}
63
64static unsigned char exynos_dp_calc_edid_check_sum(unsigned char *edid_data)
65{
66 int i;
67 unsigned char sum = 0;
68
69 for (i = 0; i < EDID_BLOCK_LENGTH; i++)
70 sum = sum + edid_data[i];
71
72 return sum;
73}
74
75static int exynos_dp_read_edid(struct exynos_dp_device *dp)
76{
77 unsigned char edid[EDID_BLOCK_LENGTH * 2];
78 unsigned int extend_block = 0;
79 unsigned char sum;
80 unsigned char test_vector;
81 int retval;
82
83 /*
84 * EDID device address is 0x50.
85 * However, if necessary, you must have set upper address
86 * into E-EDID in I2C device, 0x30.
87 */
88
89 /* Read Extension Flag, Number of 128-byte EDID extension blocks */
90 exynos_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
91 EDID_EXTENSION_FLAG,
92 &extend_block);
93
94 if (extend_block > 0) {
95 dev_dbg(dp->dev, "EDID data includes a single extension!\n");
96
97 /* Read EDID data */
98 retval = exynos_dp_read_bytes_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
99 EDID_HEADER_PATTERN,
100 EDID_BLOCK_LENGTH,
101 &edid[EDID_HEADER_PATTERN]);
102 if (retval != 0) {
103 dev_err(dp->dev, "EDID Read failed!\n");
104 return -EIO;
105 }
106 sum = exynos_dp_calc_edid_check_sum(edid);
107 if (sum != 0) {
108 dev_err(dp->dev, "EDID bad checksum!\n");
109 return -EIO;
110 }
111
112 /* Read additional EDID data */
113 retval = exynos_dp_read_bytes_from_i2c(dp,
114 I2C_EDID_DEVICE_ADDR,
115 EDID_BLOCK_LENGTH,
116 EDID_BLOCK_LENGTH,
117 &edid[EDID_BLOCK_LENGTH]);
118 if (retval != 0) {
119 dev_err(dp->dev, "EDID Read failed!\n");
120 return -EIO;
121 }
122 sum = exynos_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
123 if (sum != 0) {
124 dev_err(dp->dev, "EDID bad checksum!\n");
125 return -EIO;
126 }
127
128 exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_TEST_REQUEST,
129 &test_vector);
130 if (test_vector & DPCD_TEST_EDID_READ) {
131 exynos_dp_write_byte_to_dpcd(dp,
132 DPCD_ADDR_TEST_EDID_CHECKSUM,
133 edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
134 exynos_dp_write_byte_to_dpcd(dp,
135 DPCD_ADDR_TEST_RESPONSE,
136 DPCD_TEST_EDID_CHECKSUM_WRITE);
137 }
138 } else {
139 dev_info(dp->dev, "EDID data does not include any extensions.\n");
140
141 /* Read EDID data */
142 retval = exynos_dp_read_bytes_from_i2c(dp,
143 I2C_EDID_DEVICE_ADDR,
144 EDID_HEADER_PATTERN,
145 EDID_BLOCK_LENGTH,
146 &edid[EDID_HEADER_PATTERN]);
147 if (retval != 0) {
148 dev_err(dp->dev, "EDID Read failed!\n");
149 return -EIO;
150 }
151 sum = exynos_dp_calc_edid_check_sum(edid);
152 if (sum != 0) {
153 dev_err(dp->dev, "EDID bad checksum!\n");
154 return -EIO;
155 }
156
157 exynos_dp_read_byte_from_dpcd(dp,
158 DPCD_ADDR_TEST_REQUEST,
159 &test_vector);
160 if (test_vector & DPCD_TEST_EDID_READ) {
161 exynos_dp_write_byte_to_dpcd(dp,
162 DPCD_ADDR_TEST_EDID_CHECKSUM,
163 edid[EDID_CHECKSUM]);
164 exynos_dp_write_byte_to_dpcd(dp,
165 DPCD_ADDR_TEST_RESPONSE,
166 DPCD_TEST_EDID_CHECKSUM_WRITE);
167 }
168 }
169
170 dev_err(dp->dev, "EDID Read success!\n");
171 return 0;
172}
173
174static int exynos_dp_handle_edid(struct exynos_dp_device *dp)
175{
176 u8 buf[12];
177 int i;
178 int retval;
179
180 /* Read DPCD DPCD_ADDR_DPCD_REV~RECEIVE_PORT1_CAP_1 */
181 exynos_dp_read_bytes_from_dpcd(dp,
182 DPCD_ADDR_DPCD_REV,
183 12, buf);
184
185 /* Read EDID */
186 for (i = 0; i < 3; i++) {
187 retval = exynos_dp_read_edid(dp);
188 if (retval == 0)
189 break;
190 }
191
192 return retval;
193}
194
195static void exynos_dp_enable_rx_to_enhanced_mode(struct exynos_dp_device *dp,
196 bool enable)
197{
198 u8 data;
199
200 exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET, &data);
201
202 if (enable)
203 exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
204 DPCD_ENHANCED_FRAME_EN |
205 DPCD_LANE_COUNT_SET(data));
206 else
207 exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_LANE_COUNT_SET,
208 DPCD_LANE_COUNT_SET(data));
209}
210
211static int exynos_dp_is_enhanced_mode_available(struct exynos_dp_device *dp)
212{
213 u8 data;
214 int retval;
215
216 exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
217 retval = DPCD_ENHANCED_FRAME_CAP(data);
218
219 return retval;
220}
221
222static void exynos_dp_set_enhanced_mode(struct exynos_dp_device *dp)
223{
224 u8 data;
225
226 data = exynos_dp_is_enhanced_mode_available(dp);
227 exynos_dp_enable_rx_to_enhanced_mode(dp, data);
228 exynos_dp_enable_enhanced_mode(dp, data);
229}
230
231static void exynos_dp_training_pattern_dis(struct exynos_dp_device *dp)
232{
233 exynos_dp_set_training_pattern(dp, DP_NONE);
234
235 exynos_dp_write_byte_to_dpcd(dp,
236 DPCD_ADDR_TRAINING_PATTERN_SET,
237 DPCD_TRAINING_PATTERN_DISABLED);
238}
239
240static void exynos_dp_set_lane_lane_pre_emphasis(struct exynos_dp_device *dp,
241 int pre_emphasis, int lane)
242{
243 switch (lane) {
244 case 0:
245 exynos_dp_set_lane0_pre_emphasis(dp, pre_emphasis);
246 break;
247 case 1:
248 exynos_dp_set_lane1_pre_emphasis(dp, pre_emphasis);
249 break;
250
251 case 2:
252 exynos_dp_set_lane2_pre_emphasis(dp, pre_emphasis);
253 break;
254
255 case 3:
256 exynos_dp_set_lane3_pre_emphasis(dp, pre_emphasis);
257 break;
258 }
259}
260
261static void exynos_dp_link_start(struct exynos_dp_device *dp)
262{
263 u8 buf[5];
264 int lane;
265 int lane_count;
266
267 lane_count = dp->link_train.lane_count;
268
269 dp->link_train.lt_state = CLOCK_RECOVERY;
270 dp->link_train.eq_loop = 0;
271
272 for (lane = 0; lane < lane_count; lane++)
273 dp->link_train.cr_loop[lane] = 0;
274
275 /* Set sink to D0 (Sink Not Ready) mode. */
276 exynos_dp_write_byte_to_dpcd(dp, DPCD_ADDR_SINK_POWER_STATE,
277 DPCD_SET_POWER_STATE_D0);
278
279 /* Set link rate and count as you want to establish*/
280 exynos_dp_set_link_bandwidth(dp, dp->link_train.link_rate);
281 exynos_dp_set_lane_count(dp, dp->link_train.lane_count);
282
283 /* Setup RX configuration */
284 buf[0] = dp->link_train.link_rate;
285 buf[1] = dp->link_train.lane_count;
286 exynos_dp_write_bytes_to_dpcd(dp, DPCD_ADDR_LINK_BW_SET,
287 2, buf);
288
289 /* Set TX pre-emphasis to minimum */
290 for (lane = 0; lane < lane_count; lane++)
291 exynos_dp_set_lane_lane_pre_emphasis(dp,
292 PRE_EMPHASIS_LEVEL_0, lane);
293
294 /* Set training pattern 1 */
295 exynos_dp_set_training_pattern(dp, TRAINING_PTN1);
296
297 /* Set RX training pattern */
298 buf[0] = DPCD_SCRAMBLING_DISABLED |
299 DPCD_TRAINING_PATTERN_1;
300 exynos_dp_write_byte_to_dpcd(dp,
301 DPCD_ADDR_TRAINING_PATTERN_SET, buf[0]);
302
303 for (lane = 0; lane < lane_count; lane++)
304 buf[lane] = DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 |
305 DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0;
306 exynos_dp_write_bytes_to_dpcd(dp,
307 DPCD_ADDR_TRAINING_PATTERN_SET,
308 lane_count, buf);
309}
310
311static unsigned char exynos_dp_get_lane_status(u8 link_status[6], int lane)
312{
313 int shift = (lane & 1) * 4;
314 u8 link_value = link_status[lane>>1];
315
316 return (link_value >> shift) & 0xf;
317}
318
319static int exynos_dp_clock_recovery_ok(u8 link_status[6], int lane_count)
320{
321 int lane;
322 u8 lane_status;
323
324 for (lane = 0; lane < lane_count; lane++) {
325 lane_status = exynos_dp_get_lane_status(link_status, lane);
326 if ((lane_status & DPCD_LANE_CR_DONE) == 0)
327 return -EINVAL;
328 }
329 return 0;
330}
331
332static int exynos_dp_channel_eq_ok(u8 link_status[6], int lane_count)
333{
334 int lane;
335 u8 lane_align;
336 u8 lane_status;
337
338 lane_align = link_status[2];
339 if ((lane_align == DPCD_INTERLANE_ALIGN_DONE) == 0)
340 return -EINVAL;
341
342 for (lane = 0; lane < lane_count; lane++) {
343 lane_status = exynos_dp_get_lane_status(link_status, lane);
344 lane_status &= DPCD_CHANNEL_EQ_BITS;
345 if (lane_status != DPCD_CHANNEL_EQ_BITS)
346 return -EINVAL;
347 }
348 return 0;
349}
350
351static unsigned char exynos_dp_get_adjust_request_voltage(u8 adjust_request[2],
352 int lane)
353{
354 int shift = (lane & 1) * 4;
355 u8 link_value = adjust_request[lane>>1];
356
357 return (link_value >> shift) & 0x3;
358}
359
360static unsigned char exynos_dp_get_adjust_request_pre_emphasis(
361 u8 adjust_request[2],
362 int lane)
363{
364 int shift = (lane & 1) * 4;
365 u8 link_value = adjust_request[lane>>1];
366
367 return ((link_value >> shift) & 0xc) >> 2;
368}
369
370static void exynos_dp_set_lane_link_training(struct exynos_dp_device *dp,
371 u8 training_lane_set, int lane)
372{
373 switch (lane) {
374 case 0:
375 exynos_dp_set_lane0_link_training(dp, training_lane_set);
376 break;
377 case 1:
378 exynos_dp_set_lane1_link_training(dp, training_lane_set);
379 break;
380
381 case 2:
382 exynos_dp_set_lane2_link_training(dp, training_lane_set);
383 break;
384
385 case 3:
386 exynos_dp_set_lane3_link_training(dp, training_lane_set);
387 break;
388 }
389}
390
391static unsigned int exynos_dp_get_lane_link_training(
392 struct exynos_dp_device *dp,
393 int lane)
394{
395 u32 reg;
396
397 switch (lane) {
398 case 0:
399 reg = exynos_dp_get_lane0_link_training(dp);
400 break;
401 case 1:
402 reg = exynos_dp_get_lane1_link_training(dp);
403 break;
404 case 2:
405 reg = exynos_dp_get_lane2_link_training(dp);
406 break;
407 case 3:
408 reg = exynos_dp_get_lane3_link_training(dp);
409 break;
410 }
411
412 return reg;
413}
414
415static void exynos_dp_reduce_link_rate(struct exynos_dp_device *dp)
416{
417 if (dp->link_train.link_rate == LINK_RATE_2_70GBPS) {
418 /* set to reduced bit rate */
419 dp->link_train.link_rate = LINK_RATE_1_62GBPS;
420 dev_err(dp->dev, "set to bandwidth %.2x\n",
421 dp->link_train.link_rate);
422 dp->link_train.lt_state = START;
423 } else {
424 exynos_dp_training_pattern_dis(dp);
425 /* set enhanced mode if available */
426 exynos_dp_set_enhanced_mode(dp);
427 dp->link_train.lt_state = FAILED;
428 }
429}
430
431static void exynos_dp_get_adjust_train(struct exynos_dp_device *dp,
432 u8 adjust_request[2])
433{
434 int lane;
435 int lane_count;
436 u8 voltage_swing;
437 u8 pre_emphasis;
438 u8 training_lane;
439
440 lane_count = dp->link_train.lane_count;
441 for (lane = 0; lane < lane_count; lane++) {
442 voltage_swing = exynos_dp_get_adjust_request_voltage(
443 adjust_request, lane);
444 pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
445 adjust_request, lane);
446 training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
447 DPCD_PRE_EMPHASIS_SET(pre_emphasis);
448
449 if (voltage_swing == VOLTAGE_LEVEL_3 ||
450 pre_emphasis == PRE_EMPHASIS_LEVEL_3) {
451 training_lane |= DPCD_MAX_SWING_REACHED;
452 training_lane |= DPCD_MAX_PRE_EMPHASIS_REACHED;
453 }
454 dp->link_train.training_lane[lane] = training_lane;
455 }
456}
457
458static int exynos_dp_check_max_cr_loop(struct exynos_dp_device *dp,
459 u8 voltage_swing)
460{
461 int lane;
462 int lane_count;
463
464 lane_count = dp->link_train.lane_count;
465 for (lane = 0; lane < lane_count; lane++) {
466 if (voltage_swing == VOLTAGE_LEVEL_3 ||
467 dp->link_train.cr_loop[lane] == MAX_CR_LOOP)
468 return -EINVAL;
469 }
470 return 0;
471}
472
473static int exynos_dp_process_clock_recovery(struct exynos_dp_device *dp)
474{
475 u8 data;
476 u8 link_status[6];
477 int lane;
478 int lane_count;
479 u8 buf[5];
480
481 u8 *adjust_request;
482 u8 voltage_swing;
483 u8 pre_emphasis;
484 u8 training_lane;
485
486 udelay(100);
487
488 exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
489 6, link_status);
490 lane_count = dp->link_train.lane_count;
491
492 if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
493 /* set training pattern 2 for EQ */
494 exynos_dp_set_training_pattern(dp, TRAINING_PTN2);
495
496 adjust_request = link_status + (DPCD_ADDR_ADJUST_REQUEST_LANE0_1
497 - DPCD_ADDR_LANE0_1_STATUS);
498
499 exynos_dp_get_adjust_train(dp, adjust_request);
500
501 buf[0] = DPCD_SCRAMBLING_DISABLED |
502 DPCD_TRAINING_PATTERN_2;
503 exynos_dp_write_byte_to_dpcd(dp,
504 DPCD_ADDR_TRAINING_LANE0_SET,
505 buf[0]);
506
507 for (lane = 0; lane < lane_count; lane++) {
508 exynos_dp_set_lane_link_training(dp,
509 dp->link_train.training_lane[lane],
510 lane);
511 buf[lane] = dp->link_train.training_lane[lane];
512 exynos_dp_write_byte_to_dpcd(dp,
513 DPCD_ADDR_TRAINING_LANE0_SET + lane,
514 buf[lane]);
515 }
516 dp->link_train.lt_state = EQUALIZER_TRAINING;
517 } else {
518 exynos_dp_read_byte_from_dpcd(dp,
519 DPCD_ADDR_ADJUST_REQUEST_LANE0_1,
520 &data);
521 adjust_request[0] = data;
522
523 exynos_dp_read_byte_from_dpcd(dp,
524 DPCD_ADDR_ADJUST_REQUEST_LANE2_3,
525 &data);
526 adjust_request[1] = data;
527
528 for (lane = 0; lane < lane_count; lane++) {
529 training_lane = exynos_dp_get_lane_link_training(
530 dp, lane);
531 voltage_swing = exynos_dp_get_adjust_request_voltage(
532 adjust_request, lane);
533 pre_emphasis = exynos_dp_get_adjust_request_pre_emphasis(
534 adjust_request, lane);
535 if ((DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing) &&
536 (DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis))
537 dp->link_train.cr_loop[lane]++;
538 dp->link_train.training_lane[lane] = training_lane;
539 }
540
541 if (exynos_dp_check_max_cr_loop(dp, voltage_swing) != 0) {
542 exynos_dp_reduce_link_rate(dp);
543 } else {
544 exynos_dp_get_adjust_train(dp, adjust_request);
545
546 for (lane = 0; lane < lane_count; lane++) {
547 exynos_dp_set_lane_link_training(dp,
548 dp->link_train.training_lane[lane],
549 lane);
550 buf[lane] = dp->link_train.training_lane[lane];
551 exynos_dp_write_byte_to_dpcd(dp,
552 DPCD_ADDR_TRAINING_LANE0_SET + lane,
553 buf[lane]);
554 }
555 }
556 }
557
558 return 0;
559}
560
561static int exynos_dp_process_equalizer_training(struct exynos_dp_device *dp)
562{
563 u8 link_status[6];
564 int lane;
565 int lane_count;
566 u8 buf[5];
567 u32 reg;
568
569 u8 *adjust_request;
570
571 udelay(400);
572
573 exynos_dp_read_bytes_from_dpcd(dp, DPCD_ADDR_LANE0_1_STATUS,
574 6, link_status);
575 lane_count = dp->link_train.lane_count;
576
577 if (exynos_dp_clock_recovery_ok(link_status, lane_count) == 0) {
578 adjust_request = link_status + (DPCD_ADDR_ADJUST_REQUEST_LANE0_1
579 - DPCD_ADDR_LANE0_1_STATUS);
580
581 if (exynos_dp_channel_eq_ok(link_status, lane_count) == 0) {
582 /* traing pattern Set to Normal */
583 exynos_dp_training_pattern_dis(dp);
584
585 dev_info(dp->dev, "Link Training success!\n");
586
587 exynos_dp_get_link_bandwidth(dp, &reg);
588 dp->link_train.link_rate = reg;
589 dev_dbg(dp->dev, "final bandwidth = %.2x\n",
590 dp->link_train.link_rate);
591
592 exynos_dp_get_lane_count(dp, &reg);
593 dp->link_train.lane_count = reg;
594 dev_dbg(dp->dev, "final lane count = %.2x\n",
595 dp->link_train.lane_count);
596 /* set enhanced mode if available */
597 exynos_dp_set_enhanced_mode(dp);
598
599 dp->link_train.lt_state = FINISHED;
600 } else {
601 /* not all locked */
602 dp->link_train.eq_loop++;
603
604 if (dp->link_train.eq_loop > MAX_EQ_LOOP) {
605 exynos_dp_reduce_link_rate(dp);
606 } else {
607 exynos_dp_get_adjust_train(dp, adjust_request);
608
609 for (lane = 0; lane < lane_count; lane++) {
610 exynos_dp_set_lane_link_training(dp,
611 dp->link_train.training_lane[lane],
612 lane);
613 buf[lane] = dp->link_train.training_lane[lane];
614 exynos_dp_write_byte_to_dpcd(dp,
615 DPCD_ADDR_TRAINING_LANE0_SET + lane,
616 buf[lane]);
617 }
618 }
619 }
620 } else {
621 exynos_dp_reduce_link_rate(dp);
622 }
623
624 return 0;
625}
626
627static void exynos_dp_get_max_rx_bandwidth(struct exynos_dp_device *dp,
628 u8 *bandwidth)
629{
630 u8 data;
631
632 /*
633 * For DP rev.1.1, Maximum link rate of Main Link lanes
634 * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps
635 */
636 exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LINK_RATE, &data);
637 *bandwidth = data;
638}
639
640static void exynos_dp_get_max_rx_lane_count(struct exynos_dp_device *dp,
641 u8 *lane_count)
642{
643 u8 data;
644
645 /*
646 * For DP rev.1.1, Maximum number of Main Link lanes
647 * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
648 */
649 exynos_dp_read_byte_from_dpcd(dp, DPCD_ADDR_MAX_LANE_COUNT, &data);
650 *lane_count = DPCD_MAX_LANE_COUNT(data);
651}
652
653static void exynos_dp_init_training(struct exynos_dp_device *dp,
654 enum link_lane_count_type max_lane,
655 enum link_rate_type max_rate)
656{
657 /*
658 * MACRO_RST must be applied after the PLL_LOCK to avoid
659 * the DP inter pair skew issue for at least 10 us
660 */
661 exynos_dp_reset_macro(dp);
662
663 /* Initialize by reading RX's DPCD */
664 exynos_dp_get_max_rx_bandwidth(dp, &dp->link_train.link_rate);
665 exynos_dp_get_max_rx_lane_count(dp, &dp->link_train.lane_count);
666
667 if ((dp->link_train.link_rate != LINK_RATE_1_62GBPS) &&
668 (dp->link_train.link_rate != LINK_RATE_2_70GBPS)) {
669 dev_err(dp->dev, "Rx Max Link Rate is abnormal :%x !\n",
670 dp->link_train.link_rate);
671 dp->link_train.link_rate = LINK_RATE_1_62GBPS;
672 }
673
674 if (dp->link_train.lane_count == 0) {
675 dev_err(dp->dev, "Rx Max Lane count is abnormal :%x !\n",
676 dp->link_train.lane_count);
677 dp->link_train.lane_count = (u8)LANE_COUNT1;
678 }
679
680 /* Setup TX lane count & rate */
681 if (dp->link_train.lane_count > max_lane)
682 dp->link_train.lane_count = max_lane;
683 if (dp->link_train.link_rate > max_rate)
684 dp->link_train.link_rate = max_rate;
685
686 /* All DP analog module power up */
687 exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
688}
689
690static int exynos_dp_sw_link_training(struct exynos_dp_device *dp)
691{
692 int retval = 0;
693 int training_finished;
694
695 /* Turn off unnecessary lane */
696 if (dp->link_train.lane_count == 1)
697 exynos_dp_set_analog_power_down(dp, CH1_BLOCK, 1);
698
699 training_finished = 0;
700
701 dp->link_train.lt_state = START;
702
703 /* Process here */
704 while (!training_finished) {
705 switch (dp->link_train.lt_state) {
706 case START:
707 exynos_dp_link_start(dp);
708 break;
709 case CLOCK_RECOVERY:
710 exynos_dp_process_clock_recovery(dp);
711 break;
712 case EQUALIZER_TRAINING:
713 exynos_dp_process_equalizer_training(dp);
714 break;
715 case FINISHED:
716 training_finished = 1;
717 break;
718 case FAILED:
719 return -EREMOTEIO;
720 }
721 }
722
723 return retval;
724}
725
726static int exynos_dp_set_link_train(struct exynos_dp_device *dp,
727 u32 count,
728 u32 bwtype)
729{
730 int i;
731 int retval;
732
733 for (i = 0; i < DP_TIMEOUT_LOOP_COUNT; i++) {
734 exynos_dp_init_training(dp, count, bwtype);
735 retval = exynos_dp_sw_link_training(dp);
736 if (retval == 0)
737 break;
738
739 udelay(100);
740 }
741
742 return retval;
743}
744
745static int exynos_dp_config_video(struct exynos_dp_device *dp,
746 struct video_info *video_info)
747{
748 int retval = 0;
749 int timeout_loop = 0;
750 int done_count = 0;
751
752 exynos_dp_config_video_slave_mode(dp, video_info);
753
754 exynos_dp_set_video_color_format(dp, video_info->color_depth,
755 video_info->color_space,
756 video_info->dynamic_range,
757 video_info->ycbcr_coeff);
758
759 if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED) {
760 dev_err(dp->dev, "PLL is not locked yet.\n");
761 return -EINVAL;
762 }
763
764 for (;;) {
765 timeout_loop++;
766 if (exynos_dp_is_slave_video_stream_clock_on(dp) == 0)
767 break;
768 if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
769 dev_err(dp->dev, "Timeout of video streamclk ok\n");
770 return -ETIMEDOUT;
771 }
772
773 mdelay(100);
774 }
775
776 /* Set to use the register calculated M/N video */
777 exynos_dp_set_video_cr_mn(dp, CALCULATED_M, 0, 0);
778
779 /* For video bist, Video timing must be generated by register */
780 exynos_dp_set_video_timing_mode(dp, VIDEO_TIMING_FROM_CAPTURE);
781
782 /* Disable video mute */
783 exynos_dp_enable_video_mute(dp, 0);
784
785 /* Configure video slave mode */
786 exynos_dp_enable_video_master(dp, 0);
787
788 /* Enable video */
789 exynos_dp_start_video(dp);
790
791 timeout_loop = 0;
792
793 for (;;) {
794 timeout_loop++;
795 if (exynos_dp_is_video_stream_on(dp) == 0) {
796 done_count++;
797 if (done_count > 10)
798 break;
799 } else if (done_count) {
800 done_count = 0;
801 }
802 if (DP_TIMEOUT_LOOP_COUNT < timeout_loop) {
803 dev_err(dp->dev, "Timeout of video streamclk ok\n");
804 return -ETIMEDOUT;
805 }
806
807 mdelay(100);
808 }
809
810 if (retval != 0)
811 dev_err(dp->dev, "Video stream is not detected!\n");
812
813 return retval;
814}
815
816static void exynos_dp_enable_scramble(struct exynos_dp_device *dp, bool enable)
817{
818 u8 data;
819
820 if (enable) {
821 exynos_dp_enable_scrambling(dp);
822
823 exynos_dp_read_byte_from_dpcd(dp,
824 DPCD_ADDR_TRAINING_PATTERN_SET,
825 &data);
826 exynos_dp_write_byte_to_dpcd(dp,
827 DPCD_ADDR_TRAINING_PATTERN_SET,
828 (u8)(data & ~DPCD_SCRAMBLING_DISABLED));
829 } else {
830 exynos_dp_disable_scrambling(dp);
831
832 exynos_dp_read_byte_from_dpcd(dp,
833 DPCD_ADDR_TRAINING_PATTERN_SET,
834 &data);
835 exynos_dp_write_byte_to_dpcd(dp,
836 DPCD_ADDR_TRAINING_PATTERN_SET,
837 (u8)(data | DPCD_SCRAMBLING_DISABLED));
838 }
839}
840
841static irqreturn_t exynos_dp_irq_handler(int irq, void *arg)
842{
843 struct exynos_dp_device *dp = arg;
844
845 dev_err(dp->dev, "exynos_dp_irq_handler\n");
846 return IRQ_HANDLED;
847}
848
849static int __devinit exynos_dp_probe(struct platform_device *pdev)
850{
851 struct resource *res;
852 struct exynos_dp_device *dp;
853 struct exynos_dp_platdata *pdata;
854
855 int ret = 0;
856
857 pdata = pdev->dev.platform_data;
858 if (!pdata) {
859 dev_err(&pdev->dev, "no platform data\n");
860 return -EINVAL;
861 }
862
863 dp = kzalloc(sizeof(struct exynos_dp_device), GFP_KERNEL);
864 if (!dp) {
865 dev_err(&pdev->dev, "no memory for device data\n");
866 return -ENOMEM;
867 }
868
869 dp->dev = &pdev->dev;
870
871 dp->clock = clk_get(&pdev->dev, "dp");
872 if (IS_ERR(dp->clock)) {
873 dev_err(&pdev->dev, "failed to get clock\n");
874 ret = PTR_ERR(dp->clock);
875 goto err_dp;
876 }
877
878 clk_enable(dp->clock);
879
880 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
881 if (!res) {
882 dev_err(&pdev->dev, "failed to get registers\n");
883 ret = -EINVAL;
884 goto err_clock;
885 }
886
887 res = request_mem_region(res->start, resource_size(res),
888 dev_name(&pdev->dev));
889 if (!res) {
890 dev_err(&pdev->dev, "failed to request registers region\n");
891 ret = -EINVAL;
892 goto err_clock;
893 }
894
895 dp->res = res;
896
897 dp->reg_base = ioremap(res->start, resource_size(res));
898 if (!dp->reg_base) {
899 dev_err(&pdev->dev, "failed to ioremap\n");
900 ret = -ENOMEM;
901 goto err_req_region;
902 }
903
904 dp->irq = platform_get_irq(pdev, 0);
905 if (!dp->irq) {
906 dev_err(&pdev->dev, "failed to get irq\n");
907 ret = -ENODEV;
908 goto err_ioremap;
909 }
910
911 ret = request_irq(dp->irq, exynos_dp_irq_handler, 0,
912 "exynos-dp", dp);
913 if (ret) {
914 dev_err(&pdev->dev, "failed to request irq\n");
915 goto err_ioremap;
916 }
917
918 dp->video_info = pdata->video_info;
919 if (pdata->phy_init)
920 pdata->phy_init();
921
922 exynos_dp_init_dp(dp);
923
924 ret = exynos_dp_detect_hpd(dp);
925 if (ret) {
926 dev_err(&pdev->dev, "unable to detect hpd\n");
927 goto err_irq;
928 }
929
930 exynos_dp_handle_edid(dp);
931
932 ret = exynos_dp_set_link_train(dp, dp->video_info->lane_count,
933 dp->video_info->link_rate);
934 if (ret) {
935 dev_err(&pdev->dev, "unable to do link train\n");
936 goto err_irq;
937 }
938
939 exynos_dp_enable_scramble(dp, 1);
940 exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
941 exynos_dp_enable_enhanced_mode(dp, 1);
942
943 exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
944 exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
945
946 exynos_dp_init_video(dp);
947 ret = exynos_dp_config_video(dp, dp->video_info);
948 if (ret) {
949 dev_err(&pdev->dev, "unable to config video\n");
950 goto err_irq;
951 }
952
953 platform_set_drvdata(pdev, dp);
954
955 return 0;
956
957err_irq:
958 free_irq(dp->irq, dp);
959err_ioremap:
960 iounmap(dp->reg_base);
961err_req_region:
962 release_mem_region(res->start, resource_size(res));
963err_clock:
964 clk_put(dp->clock);
965err_dp:
966 kfree(dp);
967
968 return ret;
969}
970
971static int __devexit exynos_dp_remove(struct platform_device *pdev)
972{
973 struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
974 struct exynos_dp_device *dp = platform_get_drvdata(pdev);
975
976 if (pdata && pdata->phy_exit)
977 pdata->phy_exit();
978
979 free_irq(dp->irq, dp);
980 iounmap(dp->reg_base);
981
982 clk_disable(dp->clock);
983 clk_put(dp->clock);
984
985 release_mem_region(dp->res->start, resource_size(dp->res));
986
987 kfree(dp);
988
989 return 0;
990}
991
992#ifdef CONFIG_PM_SLEEP
993static int exynos_dp_suspend(struct device *dev)
994{
995 struct platform_device *pdev = to_platform_device(dev);
996 struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
997 struct exynos_dp_device *dp = platform_get_drvdata(pdev);
998
999 if (pdata && pdata->phy_exit)
1000 pdata->phy_exit();
1001
1002 clk_disable(dp->clock);
1003
1004 return 0;
1005}
1006
1007static int exynos_dp_resume(struct device *dev)
1008{
1009 struct platform_device *pdev = to_platform_device(dev);
1010 struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
1011 struct exynos_dp_device *dp = platform_get_drvdata(pdev);
1012
1013 if (pdata && pdata->phy_init)
1014 pdata->phy_init();
1015
1016 clk_enable(dp->clock);
1017
1018 exynos_dp_init_dp(dp);
1019
1020 exynos_dp_detect_hpd(dp);
1021 exynos_dp_handle_edid(dp);
1022
1023 exynos_dp_set_link_train(dp, dp->video_info->lane_count,
1024 dp->video_info->link_rate);
1025
1026 exynos_dp_enable_scramble(dp, 1);
1027 exynos_dp_enable_rx_to_enhanced_mode(dp, 1);
1028 exynos_dp_enable_enhanced_mode(dp, 1);
1029
1030 exynos_dp_set_lane_count(dp, dp->video_info->lane_count);
1031 exynos_dp_set_link_bandwidth(dp, dp->video_info->link_rate);
1032
1033 exynos_dp_init_video(dp);
1034 exynos_dp_config_video(dp, dp->video_info);
1035
1036 return 0;
1037}
1038#endif
1039
1040static const struct dev_pm_ops exynos_dp_pm_ops = {
1041 SET_SYSTEM_SLEEP_PM_OPS(exynos_dp_suspend, exynos_dp_resume)
1042};
1043
1044static struct platform_driver exynos_dp_driver = {
1045 .probe = exynos_dp_probe,
1046 .remove = __devexit_p(exynos_dp_remove),
1047 .driver = {
1048 .name = "exynos-dp",
1049 .owner = THIS_MODULE,
1050 .pm = &exynos_dp_pm_ops,
1051 },
1052};
1053
1054module_platform_driver(exynos_dp_driver);
1055
1056MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
1057MODULE_DESCRIPTION("Samsung SoC DP Driver");
1058MODULE_LICENSE("GPL");
diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
new file mode 100644
index 00000000000..90ceaca0fa2
--- /dev/null
+++ b/drivers/video/exynos/exynos_dp_core.h
@@ -0,0 +1,206 @@
1/*
2 * Header file for Samsung DP (Display Port) interface driver.
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Author: Jingoo Han <jg1.han@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#ifndef _EXYNOS_DP_CORE_H
14#define _EXYNOS_DP_CORE_H
15
16struct link_train {
17 int eq_loop;
18 int cr_loop[4];
19
20 u8 link_rate;
21 u8 lane_count;
22 u8 training_lane[4];
23
24 enum link_training_state lt_state;
25};
26
27struct exynos_dp_device {
28 struct device *dev;
29 struct resource *res;
30 struct clk *clock;
31 unsigned int irq;
32 void __iomem *reg_base;
33
34 struct video_info *video_info;
35 struct link_train link_train;
36};
37
38/* exynos_dp_reg.c */
39void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable);
40void exynos_dp_stop_video(struct exynos_dp_device *dp);
41void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable);
42void exynos_dp_init_interrupt(struct exynos_dp_device *dp);
43void exynos_dp_reset(struct exynos_dp_device *dp);
44void exynos_dp_config_interrupt(struct exynos_dp_device *dp);
45u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp);
46void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable);
47void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
48 enum analog_power_block block,
49 bool enable);
50void exynos_dp_init_analog_func(struct exynos_dp_device *dp);
51void exynos_dp_init_hpd(struct exynos_dp_device *dp);
52void exynos_dp_reset_aux(struct exynos_dp_device *dp);
53void exynos_dp_init_aux(struct exynos_dp_device *dp);
54int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp);
55void exynos_dp_enable_sw_function(struct exynos_dp_device *dp);
56int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp);
57int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
58 unsigned int reg_addr,
59 unsigned char data);
60int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
61 unsigned int reg_addr,
62 unsigned char *data);
63int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
64 unsigned int reg_addr,
65 unsigned int count,
66 unsigned char data[]);
67int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
68 unsigned int reg_addr,
69 unsigned int count,
70 unsigned char data[]);
71int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
72 unsigned int device_addr,
73 unsigned int reg_addr);
74int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
75 unsigned int device_addr,
76 unsigned int reg_addr,
77 unsigned int *data);
78int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
79 unsigned int device_addr,
80 unsigned int reg_addr,
81 unsigned int count,
82 unsigned char edid[]);
83void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype);
84void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype);
85void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
86void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
87void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype);
88void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype);
89void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count);
90void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count);
91void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable);
92void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
93 enum pattern_set pattern);
94void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level);
95void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level);
96void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level);
97void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level);
98void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
99 u32 training_lane);
100void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
101 u32 training_lane);
102void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
103 u32 training_lane);
104void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
105 u32 training_lane);
106u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp);
107u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp);
108u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp);
109u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp);
110void exynos_dp_reset_macro(struct exynos_dp_device *dp);
111int exynos_dp_init_video(struct exynos_dp_device *dp);
112
113void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
114 u32 color_depth,
115 u32 color_space,
116 u32 dynamic_range,
117 u32 ycbcr_coeff);
118int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp);
119void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
120 enum clock_recovery_m_value_type type,
121 u32 m_value,
122 u32 n_value);
123void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type);
124void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable);
125void exynos_dp_start_video(struct exynos_dp_device *dp);
126int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp);
127void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
128 struct video_info *video_info);
129void exynos_dp_enable_scrambling(struct exynos_dp_device *dp);
130void exynos_dp_disable_scrambling(struct exynos_dp_device *dp);
131
132/* I2C EDID Chip ID, Slave Address */
133#define I2C_EDID_DEVICE_ADDR 0x50
134#define I2C_E_EDID_DEVICE_ADDR 0x30
135
136#define EDID_BLOCK_LENGTH 0x80
137#define EDID_HEADER_PATTERN 0x00
138#define EDID_EXTENSION_FLAG 0x7e
139#define EDID_CHECKSUM 0x7f
140
141/* Definition for DPCD Register */
142#define DPCD_ADDR_DPCD_REV 0x0000
143#define DPCD_ADDR_MAX_LINK_RATE 0x0001
144#define DPCD_ADDR_MAX_LANE_COUNT 0x0002
145#define DPCD_ADDR_LINK_BW_SET 0x0100
146#define DPCD_ADDR_LANE_COUNT_SET 0x0101
147#define DPCD_ADDR_TRAINING_PATTERN_SET 0x0102
148#define DPCD_ADDR_TRAINING_LANE0_SET 0x0103
149#define DPCD_ADDR_LANE0_1_STATUS 0x0202
150#define DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED 0x0204
151#define DPCD_ADDR_ADJUST_REQUEST_LANE0_1 0x0206
152#define DPCD_ADDR_ADJUST_REQUEST_LANE2_3 0x0207
153#define DPCD_ADDR_TEST_REQUEST 0x0218
154#define DPCD_ADDR_TEST_RESPONSE 0x0260
155#define DPCD_ADDR_TEST_EDID_CHECKSUM 0x0261
156#define DPCD_ADDR_SINK_POWER_STATE 0x0600
157
158/* DPCD_ADDR_MAX_LANE_COUNT */
159#define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1)
160#define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f)
161
162/* DPCD_ADDR_LANE_COUNT_SET */
163#define DPCD_ENHANCED_FRAME_EN (0x1 << 7)
164#define DPCD_LANE_COUNT_SET(x) ((x) & 0x1f)
165
166/* DPCD_ADDR_TRAINING_PATTERN_SET */
167#define DPCD_SCRAMBLING_DISABLED (0x1 << 5)
168#define DPCD_SCRAMBLING_ENABLED (0x0 << 5)
169#define DPCD_TRAINING_PATTERN_2 (0x2 << 0)
170#define DPCD_TRAINING_PATTERN_1 (0x1 << 0)
171#define DPCD_TRAINING_PATTERN_DISABLED (0x0 << 0)
172
173/* DPCD_ADDR_TRAINING_LANE0_SET */
174#define DPCD_MAX_PRE_EMPHASIS_REACHED (0x1 << 5)
175#define DPCD_PRE_EMPHASIS_SET(x) (((x) & 0x3) << 3)
176#define DPCD_PRE_EMPHASIS_GET(x) (((x) >> 3) & 0x3)
177#define DPCD_PRE_EMPHASIS_PATTERN2_LEVEL0 (0x0 << 3)
178#define DPCD_MAX_SWING_REACHED (0x1 << 2)
179#define DPCD_VOLTAGE_SWING_SET(x) (((x) & 0x3) << 0)
180#define DPCD_VOLTAGE_SWING_GET(x) (((x) >> 0) & 0x3)
181#define DPCD_VOLTAGE_SWING_PATTERN1_LEVEL0 (0x0 << 0)
182
183/* DPCD_ADDR_LANE0_1_STATUS */
184#define DPCD_LANE_SYMBOL_LOCKED (0x1 << 2)
185#define DPCD_LANE_CHANNEL_EQ_DONE (0x1 << 1)
186#define DPCD_LANE_CR_DONE (0x1 << 0)
187#define DPCD_CHANNEL_EQ_BITS (DPCD_LANE_CR_DONE| \
188 DPCD_LANE_CHANNEL_EQ_DONE|\
189 DPCD_LANE_SYMBOL_LOCKED)
190
191/* DPCD_ADDR_LANE_ALIGN__STATUS_UPDATED */
192#define DPCD_LINK_STATUS_UPDATED (0x1 << 7)
193#define DPCD_DOWNSTREAM_PORT_STATUS_CHANGED (0x1 << 6)
194#define DPCD_INTERLANE_ALIGN_DONE (0x1 << 0)
195
196/* DPCD_ADDR_TEST_REQUEST */
197#define DPCD_TEST_EDID_READ (0x1 << 2)
198
199/* DPCD_ADDR_TEST_RESPONSE */
200#define DPCD_TEST_EDID_CHECKSUM_WRITE (0x1 << 2)
201
202/* DPCD_ADDR_SINK_POWER_STATE */
203#define DPCD_SET_POWER_STATE_D0 (0x1 << 0)
204#define DPCD_SET_POWER_STATE_D4 (0x2 << 0)
205
206#endif /* _EXYNOS_DP_CORE_H */
diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c
new file mode 100644
index 00000000000..6548afa0e3d
--- /dev/null
+++ b/drivers/video/exynos/exynos_dp_reg.c
@@ -0,0 +1,1173 @@
1/*
2 * Samsung DP (Display port) register interface driver.
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Author: Jingoo Han <jg1.han@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/device.h>
14#include <linux/io.h>
15#include <linux/delay.h>
16
17#include <video/exynos_dp.h>
18
19#include <plat/cpu.h>
20
21#include "exynos_dp_core.h"
22#include "exynos_dp_reg.h"
23
24#define COMMON_INT_MASK_1 (0)
25#define COMMON_INT_MASK_2 (0)
26#define COMMON_INT_MASK_3 (0)
27#define COMMON_INT_MASK_4 (0)
28#define INT_STA_MASK (0)
29
30void exynos_dp_enable_video_mute(struct exynos_dp_device *dp, bool enable)
31{
32 u32 reg;
33
34 if (enable) {
35 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
36 reg |= HDCP_VIDEO_MUTE;
37 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
38 } else {
39 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
40 reg &= ~HDCP_VIDEO_MUTE;
41 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
42 }
43}
44
45void exynos_dp_stop_video(struct exynos_dp_device *dp)
46{
47 u32 reg;
48
49 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
50 reg &= ~VIDEO_EN;
51 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
52}
53
54void exynos_dp_lane_swap(struct exynos_dp_device *dp, bool enable)
55{
56 u32 reg;
57
58 if (enable)
59 reg = LANE3_MAP_LOGIC_LANE_0 | LANE2_MAP_LOGIC_LANE_1 |
60 LANE1_MAP_LOGIC_LANE_2 | LANE0_MAP_LOGIC_LANE_3;
61 else
62 reg = LANE3_MAP_LOGIC_LANE_3 | LANE2_MAP_LOGIC_LANE_2 |
63 LANE1_MAP_LOGIC_LANE_1 | LANE0_MAP_LOGIC_LANE_0;
64
65 writel(reg, dp->reg_base + EXYNOS_DP_LANE_MAP);
66}
67
68void exynos_dp_init_interrupt(struct exynos_dp_device *dp)
69{
70 /* Set interrupt pin assertion polarity as high */
71 writel(INT_POL, dp->reg_base + EXYNOS_DP_INT_CTL);
72
73 /* Clear pending regisers */
74 writel(0xff, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
75 writel(0x4f, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_2);
76 writel(0xe0, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_3);
77 writel(0xe7, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
78 writel(0x63, dp->reg_base + EXYNOS_DP_INT_STA);
79
80 /* 0:mask,1: unmask */
81 writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
82 writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
83 writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
84 writel(0x00, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
85 writel(0x00, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
86}
87
88void exynos_dp_reset(struct exynos_dp_device *dp)
89{
90 u32 reg;
91
92 writel(RESET_DP_TX, dp->reg_base + EXYNOS_DP_TX_SW_RESET);
93
94 exynos_dp_stop_video(dp);
95 exynos_dp_enable_video_mute(dp, 0);
96
97 reg = MASTER_VID_FUNC_EN_N | SLAVE_VID_FUNC_EN_N |
98 AUD_FIFO_FUNC_EN_N | AUD_FUNC_EN_N |
99 HDCP_FUNC_EN_N | SW_FUNC_EN_N;
100 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
101
102 reg = SSC_FUNC_EN_N | AUX_FUNC_EN_N |
103 SERDES_FIFO_FUNC_EN_N |
104 LS_CLK_DOMAIN_FUNC_EN_N;
105 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
106
107 udelay(20);
108
109 exynos_dp_lane_swap(dp, 0);
110
111 writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
112 writel(0x40, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
113 writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
114 writel(0x0, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
115
116 writel(0x0, dp->reg_base + EXYNOS_DP_PKT_SEND_CTL);
117 writel(0x0, dp->reg_base + EXYNOS_DP_HDCP_CTL);
118
119 writel(0x5e, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_L);
120 writel(0x1a, dp->reg_base + EXYNOS_DP_HPD_DEGLITCH_H);
121
122 writel(0x10, dp->reg_base + EXYNOS_DP_LINK_DEBUG_CTL);
123
124 writel(0x0, dp->reg_base + EXYNOS_DP_PHY_TEST);
125
126 writel(0x0, dp->reg_base + EXYNOS_DP_VIDEO_FIFO_THRD);
127 writel(0x20, dp->reg_base + EXYNOS_DP_AUDIO_MARGIN);
128
129 writel(0x4, dp->reg_base + EXYNOS_DP_M_VID_GEN_FILTER_TH);
130 writel(0x2, dp->reg_base + EXYNOS_DP_M_AUD_GEN_FILTER_TH);
131
132 writel(0x00000101, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
133
134 exynos_dp_init_interrupt(dp);
135}
136
137void exynos_dp_config_interrupt(struct exynos_dp_device *dp)
138{
139 u32 reg;
140
141 /* 0: mask, 1: unmask */
142 reg = COMMON_INT_MASK_1;
143 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_1);
144
145 reg = COMMON_INT_MASK_2;
146 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_2);
147
148 reg = COMMON_INT_MASK_3;
149 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_3);
150
151 reg = COMMON_INT_MASK_4;
152 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_MASK_4);
153
154 reg = INT_STA_MASK;
155 writel(reg, dp->reg_base + EXYNOS_DP_INT_STA_MASK);
156}
157
158u32 exynos_dp_get_pll_lock_status(struct exynos_dp_device *dp)
159{
160 u32 reg;
161
162 reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
163 if (reg & PLL_LOCK)
164 return PLL_LOCKED;
165 else
166 return PLL_UNLOCKED;
167}
168
169void exynos_dp_set_pll_power_down(struct exynos_dp_device *dp, bool enable)
170{
171 u32 reg;
172
173 if (enable) {
174 reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
175 reg |= DP_PLL_PD;
176 writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
177 } else {
178 reg = readl(dp->reg_base + EXYNOS_DP_PLL_CTL);
179 reg &= ~DP_PLL_PD;
180 writel(reg, dp->reg_base + EXYNOS_DP_PLL_CTL);
181 }
182}
183
184void exynos_dp_set_analog_power_down(struct exynos_dp_device *dp,
185 enum analog_power_block block,
186 bool enable)
187{
188 u32 reg;
189
190 switch (block) {
191 case AUX_BLOCK:
192 if (enable) {
193 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
194 reg |= AUX_PD;
195 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
196 } else {
197 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
198 reg &= ~AUX_PD;
199 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
200 }
201 break;
202 case CH0_BLOCK:
203 if (enable) {
204 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
205 reg |= CH0_PD;
206 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
207 } else {
208 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
209 reg &= ~CH0_PD;
210 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
211 }
212 break;
213 case CH1_BLOCK:
214 if (enable) {
215 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
216 reg |= CH1_PD;
217 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
218 } else {
219 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
220 reg &= ~CH1_PD;
221 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
222 }
223 break;
224 case CH2_BLOCK:
225 if (enable) {
226 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
227 reg |= CH2_PD;
228 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
229 } else {
230 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
231 reg &= ~CH2_PD;
232 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
233 }
234 break;
235 case CH3_BLOCK:
236 if (enable) {
237 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
238 reg |= CH3_PD;
239 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
240 } else {
241 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
242 reg &= ~CH3_PD;
243 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
244 }
245 break;
246 case ANALOG_TOTAL:
247 if (enable) {
248 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
249 reg |= DP_PHY_PD;
250 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
251 } else {
252 reg = readl(dp->reg_base + EXYNOS_DP_PHY_PD);
253 reg &= ~DP_PHY_PD;
254 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
255 }
256 break;
257 case POWER_ALL:
258 if (enable) {
259 reg = DP_PHY_PD | AUX_PD | CH3_PD | CH2_PD |
260 CH1_PD | CH0_PD;
261 writel(reg, dp->reg_base + EXYNOS_DP_PHY_PD);
262 } else {
263 writel(0x00, dp->reg_base + EXYNOS_DP_PHY_PD);
264 }
265 break;
266 default:
267 break;
268 }
269}
270
271void exynos_dp_init_analog_func(struct exynos_dp_device *dp)
272{
273 u32 reg;
274
275 exynos_dp_set_analog_power_down(dp, POWER_ALL, 0);
276
277 reg = PLL_LOCK_CHG;
278 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
279
280 reg = readl(dp->reg_base + EXYNOS_DP_DEBUG_CTL);
281 reg &= ~(F_PLL_LOCK | PLL_LOCK_CTRL);
282 writel(reg, dp->reg_base + EXYNOS_DP_DEBUG_CTL);
283
284 /* Power up PLL */
285 if (exynos_dp_get_pll_lock_status(dp) == PLL_UNLOCKED)
286 exynos_dp_set_pll_power_down(dp, 0);
287
288 /* Enable Serdes FIFO function and Link symbol clock domain module */
289 reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
290 reg &= ~(SERDES_FIFO_FUNC_EN_N | LS_CLK_DOMAIN_FUNC_EN_N
291 | AUX_FUNC_EN_N);
292 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
293}
294
295void exynos_dp_init_hpd(struct exynos_dp_device *dp)
296{
297 u32 reg;
298
299 reg = HOTPLUG_CHG | HPD_LOST | PLUG;
300 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_4);
301
302 reg = INT_HPD;
303 writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
304
305 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
306 reg &= ~(F_HPD | HPD_CTRL);
307 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
308}
309
310void exynos_dp_reset_aux(struct exynos_dp_device *dp)
311{
312 u32 reg;
313
314 /* Disable AUX channel module */
315 reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
316 reg |= AUX_FUNC_EN_N;
317 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
318}
319
320void exynos_dp_init_aux(struct exynos_dp_device *dp)
321{
322 u32 reg;
323
324 /* Clear inerrupts related to AUX channel */
325 reg = RPLY_RECEIV | AUX_ERR;
326 writel(reg, dp->reg_base + EXYNOS_DP_INT_STA);
327
328 exynos_dp_reset_aux(dp);
329
330 /* Disable AUX transaction H/W retry */
331 reg = AUX_BIT_PERIOD_EXPECTED_DELAY(3) | AUX_HW_RETRY_COUNT_SEL(0)|
332 AUX_HW_RETRY_INTERVAL_600_MICROSECONDS;
333 writel(reg, dp->reg_base + EXYNOS_DP_AUX_HW_RETRY_CTL) ;
334
335 /* Receive AUX Channel DEFER commands equal to DEFFER_COUNT*64 */
336 reg = DEFER_CTRL_EN | DEFER_COUNT(1);
337 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_DEFER_CTL);
338
339 /* Enable AUX channel module */
340 reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_2);
341 reg &= ~AUX_FUNC_EN_N;
342 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_2);
343}
344
345int exynos_dp_get_plug_in_status(struct exynos_dp_device *dp)
346{
347 u32 reg;
348
349 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
350 if (reg & HPD_STATUS)
351 return 0;
352
353 return -EINVAL;
354}
355
356void exynos_dp_enable_sw_function(struct exynos_dp_device *dp)
357{
358 u32 reg;
359
360 reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
361 reg &= ~SW_FUNC_EN_N;
362 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
363}
364
365int exynos_dp_start_aux_transaction(struct exynos_dp_device *dp)
366{
367 int reg;
368 int retval = 0;
369
370 /* Enable AUX CH operation */
371 reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
372 reg |= AUX_EN;
373 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
374
375 /* Is AUX CH command reply received? */
376 reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
377 while (!(reg & RPLY_RECEIV))
378 reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
379
380 /* Clear interrupt source for AUX CH command reply */
381 writel(RPLY_RECEIV, dp->reg_base + EXYNOS_DP_INT_STA);
382
383 /* Clear interrupt source for AUX CH access error */
384 reg = readl(dp->reg_base + EXYNOS_DP_INT_STA);
385 if (reg & AUX_ERR) {
386 writel(AUX_ERR, dp->reg_base + EXYNOS_DP_INT_STA);
387 return -EREMOTEIO;
388 }
389
390 /* Check AUX CH error access status */
391 reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_STA);
392 if ((reg & AUX_STATUS_MASK) != 0) {
393 dev_err(dp->dev, "AUX CH error happens: %d\n\n",
394 reg & AUX_STATUS_MASK);
395 return -EREMOTEIO;
396 }
397
398 return retval;
399}
400
401int exynos_dp_write_byte_to_dpcd(struct exynos_dp_device *dp,
402 unsigned int reg_addr,
403 unsigned char data)
404{
405 u32 reg;
406 int i;
407 int retval;
408
409 for (i = 0; i < 3; i++) {
410 /* Clear AUX CH data buffer */
411 reg = BUF_CLR;
412 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
413
414 /* Select DPCD device address */
415 reg = AUX_ADDR_7_0(reg_addr);
416 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
417 reg = AUX_ADDR_15_8(reg_addr);
418 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
419 reg = AUX_ADDR_19_16(reg_addr);
420 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
421
422 /* Write data buffer */
423 reg = (unsigned int)data;
424 writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
425
426 /*
427 * Set DisplayPort transaction and write 1 byte
428 * If bit 3 is 1, DisplayPort transaction.
429 * If Bit 3 is 0, I2C transaction.
430 */
431 reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
432 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
433
434 /* Start AUX transaction */
435 retval = exynos_dp_start_aux_transaction(dp);
436 if (retval == 0)
437 break;
438 else
439 dev_err(dp->dev, "Aux Transaction fail!\n");
440 }
441
442 return retval;
443}
444
445int exynos_dp_read_byte_from_dpcd(struct exynos_dp_device *dp,
446 unsigned int reg_addr,
447 unsigned char *data)
448{
449 u32 reg;
450 int i;
451 int retval;
452
453 for (i = 0; i < 10; i++) {
454 /* Clear AUX CH data buffer */
455 reg = BUF_CLR;
456 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
457
458 /* Select DPCD device address */
459 reg = AUX_ADDR_7_0(reg_addr);
460 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
461 reg = AUX_ADDR_15_8(reg_addr);
462 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
463 reg = AUX_ADDR_19_16(reg_addr);
464 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
465
466 /*
467 * Set DisplayPort transaction and read 1 byte
468 * If bit 3 is 1, DisplayPort transaction.
469 * If Bit 3 is 0, I2C transaction.
470 */
471 reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
472 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
473
474 /* Start AUX transaction */
475 retval = exynos_dp_start_aux_transaction(dp);
476 if (retval == 0)
477 break;
478 else
479 dev_err(dp->dev, "Aux Transaction fail!\n");
480 }
481
482 /* Read data buffer */
483 reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
484 *data = (unsigned char)(reg & 0xff);
485
486 return retval;
487}
488
489int exynos_dp_write_bytes_to_dpcd(struct exynos_dp_device *dp,
490 unsigned int reg_addr,
491 unsigned int count,
492 unsigned char data[])
493{
494 u32 reg;
495 unsigned int start_offset;
496 unsigned int cur_data_count;
497 unsigned int cur_data_idx;
498 int i;
499 int retval = 0;
500
501 /* Clear AUX CH data buffer */
502 reg = BUF_CLR;
503 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
504
505 start_offset = 0;
506 while (start_offset < count) {
507 /* Buffer size of AUX CH is 16 * 4bytes */
508 if ((count - start_offset) > 16)
509 cur_data_count = 16;
510 else
511 cur_data_count = count - start_offset;
512
513 for (i = 0; i < 10; i++) {
514 /* Select DPCD device address */
515 reg = AUX_ADDR_7_0(reg_addr + start_offset);
516 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
517 reg = AUX_ADDR_15_8(reg_addr + start_offset);
518 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
519 reg = AUX_ADDR_19_16(reg_addr + start_offset);
520 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
521
522 for (cur_data_idx = 0; cur_data_idx < cur_data_count;
523 cur_data_idx++) {
524 reg = data[start_offset + cur_data_idx];
525 writel(reg, dp->reg_base + EXYNOS_DP_BUF_DATA_0
526 + 4 * cur_data_idx);
527 }
528
529 /*
530 * Set DisplayPort transaction and write
531 * If bit 3 is 1, DisplayPort transaction.
532 * If Bit 3 is 0, I2C transaction.
533 */
534 reg = AUX_LENGTH(cur_data_count) |
535 AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
536 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
537
538 /* Start AUX transaction */
539 retval = exynos_dp_start_aux_transaction(dp);
540 if (retval == 0)
541 break;
542 else
543 dev_err(dp->dev, "Aux Transaction fail!\n");
544 }
545
546 start_offset += cur_data_count;
547 }
548
549 return retval;
550}
551
552int exynos_dp_read_bytes_from_dpcd(struct exynos_dp_device *dp,
553 unsigned int reg_addr,
554 unsigned int count,
555 unsigned char data[])
556{
557 u32 reg;
558 unsigned int start_offset;
559 unsigned int cur_data_count;
560 unsigned int cur_data_idx;
561 int i;
562 int retval = 0;
563
564 /* Clear AUX CH data buffer */
565 reg = BUF_CLR;
566 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
567
568 start_offset = 0;
569 while (start_offset < count) {
570 /* Buffer size of AUX CH is 16 * 4bytes */
571 if ((count - start_offset) > 16)
572 cur_data_count = 16;
573 else
574 cur_data_count = count - start_offset;
575
576 /* AUX CH Request Transaction process */
577 for (i = 0; i < 10; i++) {
578 /* Select DPCD device address */
579 reg = AUX_ADDR_7_0(reg_addr + start_offset);
580 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
581 reg = AUX_ADDR_15_8(reg_addr + start_offset);
582 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
583 reg = AUX_ADDR_19_16(reg_addr + start_offset);
584 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
585
586 /*
587 * Set DisplayPort transaction and read
588 * If bit 3 is 1, DisplayPort transaction.
589 * If Bit 3 is 0, I2C transaction.
590 */
591 reg = AUX_LENGTH(cur_data_count) |
592 AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
593 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
594
595 /* Start AUX transaction */
596 retval = exynos_dp_start_aux_transaction(dp);
597 if (retval == 0)
598 break;
599 else
600 dev_err(dp->dev, "Aux Transaction fail!\n");
601 }
602
603 for (cur_data_idx = 0; cur_data_idx < cur_data_count;
604 cur_data_idx++) {
605 reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
606 + 4 * cur_data_idx);
607 data[start_offset + cur_data_idx] =
608 (unsigned char)reg;
609 }
610
611 start_offset += cur_data_count;
612 }
613
614 return retval;
615}
616
617int exynos_dp_select_i2c_device(struct exynos_dp_device *dp,
618 unsigned int device_addr,
619 unsigned int reg_addr)
620{
621 u32 reg;
622 int retval;
623
624 /* Set EDID device address */
625 reg = device_addr;
626 writel(reg, dp->reg_base + EXYNOS_DP_AUX_ADDR_7_0);
627 writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_15_8);
628 writel(0x0, dp->reg_base + EXYNOS_DP_AUX_ADDR_19_16);
629
630 /* Set offset from base address of EDID device */
631 writel(reg_addr, dp->reg_base + EXYNOS_DP_BUF_DATA_0);
632
633 /*
634 * Set I2C transaction and write address
635 * If bit 3 is 1, DisplayPort transaction.
636 * If Bit 3 is 0, I2C transaction.
637 */
638 reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
639 AUX_TX_COMM_WRITE;
640 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
641
642 /* Start AUX transaction */
643 retval = exynos_dp_start_aux_transaction(dp);
644 if (retval != 0)
645 dev_err(dp->dev, "Aux Transaction fail!\n");
646
647 return retval;
648}
649
650int exynos_dp_read_byte_from_i2c(struct exynos_dp_device *dp,
651 unsigned int device_addr,
652 unsigned int reg_addr,
653 unsigned int *data)
654{
655 u32 reg;
656 int i;
657 int retval;
658
659 for (i = 0; i < 10; i++) {
660 /* Clear AUX CH data buffer */
661 reg = BUF_CLR;
662 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
663
664 /* Select EDID device */
665 retval = exynos_dp_select_i2c_device(dp, device_addr, reg_addr);
666 if (retval != 0) {
667 dev_err(dp->dev, "Select EDID device fail!\n");
668 continue;
669 }
670
671 /*
672 * Set I2C transaction and read data
673 * If bit 3 is 1, DisplayPort transaction.
674 * If Bit 3 is 0, I2C transaction.
675 */
676 reg = AUX_TX_COMM_I2C_TRANSACTION |
677 AUX_TX_COMM_READ;
678 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_1);
679
680 /* Start AUX transaction */
681 retval = exynos_dp_start_aux_transaction(dp);
682 if (retval == 0)
683 break;
684 else
685 dev_err(dp->dev, "Aux Transaction fail!\n");
686 }
687
688 /* Read data */
689 if (retval == 0)
690 *data = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0);
691
692 return retval;
693}
694
695int exynos_dp_read_bytes_from_i2c(struct exynos_dp_device *dp,
696 unsigned int device_addr,
697 unsigned int reg_addr,
698 unsigned int count,
699 unsigned char edid[])
700{
701 u32 reg;
702 unsigned int i, j;
703 unsigned int cur_data_idx;
704 unsigned int defer = 0;
705 int retval = 0;
706
707 for (i = 0; i < count; i += 16) {
708 for (j = 0; j < 100; j++) {
709 /* Clear AUX CH data buffer */
710 reg = BUF_CLR;
711 writel(reg, dp->reg_base + EXYNOS_DP_BUFFER_DATA_CTL);
712
713 /* Set normal AUX CH command */
714 reg = readl(dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
715 reg &= ~ADDR_ONLY;
716 writel(reg, dp->reg_base + EXYNOS_DP_AUX_CH_CTL_2);
717
718 /*
719 * If Rx sends defer, Tx sends only reads
720 * request without sending addres
721 */
722 if (!defer)
723 retval = exynos_dp_select_i2c_device(dp,
724 device_addr, reg_addr + i);
725 else
726 defer = 0;
727
728 if (retval == 0) {
729 /*
730 * Set I2C transaction and write data
731 * If bit 3 is 1, DisplayPort transaction.
732 * If Bit 3 is 0, I2C transaction.
733 */
734 reg = AUX_LENGTH(16) |
735 AUX_TX_COMM_I2C_TRANSACTION |
736 AUX_TX_COMM_READ;
737 writel(reg, dp->reg_base +
738 EXYNOS_DP_AUX_CH_CTL_1);
739
740 /* Start AUX transaction */
741 retval = exynos_dp_start_aux_transaction(dp);
742 if (retval == 0)
743 break;
744 else
745 dev_err(dp->dev, "Aux Transaction fail!\n");
746 }
747 /* Check if Rx sends defer */
748 reg = readl(dp->reg_base + EXYNOS_DP_AUX_RX_COMM);
749 if (reg == AUX_RX_COMM_AUX_DEFER ||
750 reg == AUX_RX_COMM_I2C_DEFER) {
751 dev_err(dp->dev, "Defer: %d\n\n", reg);
752 defer = 1;
753 }
754 }
755
756 for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
757 reg = readl(dp->reg_base + EXYNOS_DP_BUF_DATA_0
758 + 4 * cur_data_idx);
759 edid[i + cur_data_idx] = (unsigned char)reg;
760 }
761 }
762
763 return retval;
764}
765
766void exynos_dp_set_link_bandwidth(struct exynos_dp_device *dp, u32 bwtype)
767{
768 u32 reg;
769
770 reg = bwtype;
771 if ((bwtype == LINK_RATE_2_70GBPS) || (bwtype == LINK_RATE_1_62GBPS))
772 writel(reg, dp->reg_base + EXYNOS_DP_LINK_BW_SET);
773}
774
775void exynos_dp_get_link_bandwidth(struct exynos_dp_device *dp, u32 *bwtype)
776{
777 u32 reg;
778
779 reg = readl(dp->reg_base + EXYNOS_DP_LINK_BW_SET);
780 *bwtype = reg;
781}
782
783void exynos_dp_set_lane_count(struct exynos_dp_device *dp, u32 count)
784{
785 u32 reg;
786
787 reg = count;
788 writel(reg, dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
789}
790
791void exynos_dp_get_lane_count(struct exynos_dp_device *dp, u32 *count)
792{
793 u32 reg;
794
795 reg = readl(dp->reg_base + EXYNOS_DP_LANE_COUNT_SET);
796 *count = reg;
797}
798
799void exynos_dp_enable_enhanced_mode(struct exynos_dp_device *dp, bool enable)
800{
801 u32 reg;
802
803 if (enable) {
804 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
805 reg |= ENHANCED;
806 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
807 } else {
808 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
809 reg &= ~ENHANCED;
810 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
811 }
812}
813
814void exynos_dp_set_training_pattern(struct exynos_dp_device *dp,
815 enum pattern_set pattern)
816{
817 u32 reg;
818
819 switch (pattern) {
820 case PRBS7:
821 reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_PRBS7;
822 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
823 break;
824 case D10_2:
825 reg = SCRAMBLING_ENABLE | LINK_QUAL_PATTERN_SET_D10_2;
826 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
827 break;
828 case TRAINING_PTN1:
829 reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN1;
830 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
831 break;
832 case TRAINING_PTN2:
833 reg = SCRAMBLING_DISABLE | SW_TRAINING_PATTERN_SET_PTN2;
834 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
835 break;
836 case DP_NONE:
837 reg = SCRAMBLING_ENABLE |
838 LINK_QUAL_PATTERN_SET_DISABLE |
839 SW_TRAINING_PATTERN_SET_NORMAL;
840 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
841 break;
842 default:
843 break;
844 }
845}
846
847void exynos_dp_set_lane0_pre_emphasis(struct exynos_dp_device *dp, u32 level)
848{
849 u32 reg;
850
851 reg = level << PRE_EMPHASIS_SET_SHIFT;
852 writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
853}
854
855void exynos_dp_set_lane1_pre_emphasis(struct exynos_dp_device *dp, u32 level)
856{
857 u32 reg;
858
859 reg = level << PRE_EMPHASIS_SET_SHIFT;
860 writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
861}
862
863void exynos_dp_set_lane2_pre_emphasis(struct exynos_dp_device *dp, u32 level)
864{
865 u32 reg;
866
867 reg = level << PRE_EMPHASIS_SET_SHIFT;
868 writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
869}
870
871void exynos_dp_set_lane3_pre_emphasis(struct exynos_dp_device *dp, u32 level)
872{
873 u32 reg;
874
875 reg = level << PRE_EMPHASIS_SET_SHIFT;
876 writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
877}
878
879void exynos_dp_set_lane0_link_training(struct exynos_dp_device *dp,
880 u32 training_lane)
881{
882 u32 reg;
883
884 reg = training_lane;
885 writel(reg, dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
886}
887
888void exynos_dp_set_lane1_link_training(struct exynos_dp_device *dp,
889 u32 training_lane)
890{
891 u32 reg;
892
893 reg = training_lane;
894 writel(reg, dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
895}
896
897void exynos_dp_set_lane2_link_training(struct exynos_dp_device *dp,
898 u32 training_lane)
899{
900 u32 reg;
901
902 reg = training_lane;
903 writel(reg, dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
904}
905
906void exynos_dp_set_lane3_link_training(struct exynos_dp_device *dp,
907 u32 training_lane)
908{
909 u32 reg;
910
911 reg = training_lane;
912 writel(reg, dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
913}
914
915u32 exynos_dp_get_lane0_link_training(struct exynos_dp_device *dp)
916{
917 u32 reg;
918
919 reg = readl(dp->reg_base + EXYNOS_DP_LN0_LINK_TRAINING_CTL);
920 return reg;
921}
922
923u32 exynos_dp_get_lane1_link_training(struct exynos_dp_device *dp)
924{
925 u32 reg;
926
927 reg = readl(dp->reg_base + EXYNOS_DP_LN1_LINK_TRAINING_CTL);
928 return reg;
929}
930
931u32 exynos_dp_get_lane2_link_training(struct exynos_dp_device *dp)
932{
933 u32 reg;
934
935 reg = readl(dp->reg_base + EXYNOS_DP_LN2_LINK_TRAINING_CTL);
936 return reg;
937}
938
939u32 exynos_dp_get_lane3_link_training(struct exynos_dp_device *dp)
940{
941 u32 reg;
942
943 reg = readl(dp->reg_base + EXYNOS_DP_LN3_LINK_TRAINING_CTL);
944 return reg;
945}
946
947void exynos_dp_reset_macro(struct exynos_dp_device *dp)
948{
949 u32 reg;
950
951 reg = readl(dp->reg_base + EXYNOS_DP_PHY_TEST);
952 reg |= MACRO_RST;
953 writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
954
955 /* 10 us is the minimum reset time. */
956 udelay(10);
957
958 reg &= ~MACRO_RST;
959 writel(reg, dp->reg_base + EXYNOS_DP_PHY_TEST);
960}
961
962int exynos_dp_init_video(struct exynos_dp_device *dp)
963{
964 u32 reg;
965
966 reg = VSYNC_DET | VID_FORMAT_CHG | VID_CLK_CHG;
967 writel(reg, dp->reg_base + EXYNOS_DP_COMMON_INT_STA_1);
968
969 reg = 0x0;
970 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
971
972 reg = CHA_CRI(4) | CHA_CTRL;
973 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
974
975 reg = 0x0;
976 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
977
978 reg = VID_HRES_TH(2) | VID_VRES_TH(0);
979 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_8);
980
981 return 0;
982}
983
984void exynos_dp_set_video_color_format(struct exynos_dp_device *dp,
985 u32 color_depth,
986 u32 color_space,
987 u32 dynamic_range,
988 u32 ycbcr_coeff)
989{
990 u32 reg;
991
992 /* Configure the input color depth, color space, dynamic range */
993 reg = (dynamic_range << IN_D_RANGE_SHIFT) |
994 (color_depth << IN_BPC_SHIFT) |
995 (color_space << IN_COLOR_F_SHIFT);
996 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_2);
997
998 /* Set Input Color YCbCr Coefficients to ITU601 or ITU709 */
999 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
1000 reg &= ~IN_YC_COEFFI_MASK;
1001 if (ycbcr_coeff)
1002 reg |= IN_YC_COEFFI_ITU709;
1003 else
1004 reg |= IN_YC_COEFFI_ITU601;
1005 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_3);
1006}
1007
1008int exynos_dp_is_slave_video_stream_clock_on(struct exynos_dp_device *dp)
1009{
1010 u32 reg;
1011
1012 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
1013 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_1);
1014
1015 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_1);
1016
1017 if (!(reg & DET_STA)) {
1018 dev_dbg(dp->dev, "Input stream clock not detected.\n");
1019 return -EINVAL;
1020 }
1021
1022 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
1023 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_2);
1024
1025 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_2);
1026 dev_dbg(dp->dev, "wait SYS_CTL_2.\n");
1027
1028 if (reg & CHA_STA) {
1029 dev_dbg(dp->dev, "Input stream clk is changing\n");
1030 return -EINVAL;
1031 }
1032
1033 return 0;
1034}
1035
1036void exynos_dp_set_video_cr_mn(struct exynos_dp_device *dp,
1037 enum clock_recovery_m_value_type type,
1038 u32 m_value,
1039 u32 n_value)
1040{
1041 u32 reg;
1042
1043 if (type == REGISTER_M) {
1044 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
1045 reg |= FIX_M_VID;
1046 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
1047 reg = m_value & 0xff;
1048 writel(reg, dp->reg_base + EXYNOS_DP_M_VID_0);
1049 reg = (m_value >> 8) & 0xff;
1050 writel(reg, dp->reg_base + EXYNOS_DP_M_VID_1);
1051 reg = (m_value >> 16) & 0xff;
1052 writel(reg, dp->reg_base + EXYNOS_DP_M_VID_2);
1053
1054 reg = n_value & 0xff;
1055 writel(reg, dp->reg_base + EXYNOS_DP_N_VID_0);
1056 reg = (n_value >> 8) & 0xff;
1057 writel(reg, dp->reg_base + EXYNOS_DP_N_VID_1);
1058 reg = (n_value >> 16) & 0xff;
1059 writel(reg, dp->reg_base + EXYNOS_DP_N_VID_2);
1060 } else {
1061 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_4);
1062 reg &= ~FIX_M_VID;
1063 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_4);
1064
1065 writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_0);
1066 writel(0x80, dp->reg_base + EXYNOS_DP_N_VID_1);
1067 writel(0x00, dp->reg_base + EXYNOS_DP_N_VID_2);
1068 }
1069}
1070
1071void exynos_dp_set_video_timing_mode(struct exynos_dp_device *dp, u32 type)
1072{
1073 u32 reg;
1074
1075 if (type == VIDEO_TIMING_FROM_CAPTURE) {
1076 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1077 reg &= ~FORMAT_SEL;
1078 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1079 } else {
1080 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1081 reg |= FORMAT_SEL;
1082 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1083 }
1084}
1085
1086void exynos_dp_enable_video_master(struct exynos_dp_device *dp, bool enable)
1087{
1088 u32 reg;
1089
1090 if (enable) {
1091 reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1092 reg &= ~VIDEO_MODE_MASK;
1093 reg |= VIDEO_MASTER_MODE_EN | VIDEO_MODE_MASTER_MODE;
1094 writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1095 } else {
1096 reg = readl(dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1097 reg &= ~VIDEO_MODE_MASK;
1098 reg |= VIDEO_MODE_SLAVE_MODE;
1099 writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1100 }
1101}
1102
1103void exynos_dp_start_video(struct exynos_dp_device *dp)
1104{
1105 u32 reg;
1106
1107 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
1108 reg |= VIDEO_EN;
1109 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_1);
1110}
1111
1112int exynos_dp_is_video_stream_on(struct exynos_dp_device *dp)
1113{
1114 u32 reg;
1115
1116 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
1117 writel(reg, dp->reg_base + EXYNOS_DP_SYS_CTL_3);
1118
1119 reg = readl(dp->reg_base + EXYNOS_DP_SYS_CTL_3);
1120 if (!(reg & STRM_VALID)) {
1121 dev_dbg(dp->dev, "Input video stream is not detected.\n");
1122 return -EINVAL;
1123 }
1124
1125 return 0;
1126}
1127
1128void exynos_dp_config_video_slave_mode(struct exynos_dp_device *dp,
1129 struct video_info *video_info)
1130{
1131 u32 reg;
1132
1133 reg = readl(dp->reg_base + EXYNOS_DP_FUNC_EN_1);
1134 reg &= ~(MASTER_VID_FUNC_EN_N|SLAVE_VID_FUNC_EN_N);
1135 reg |= MASTER_VID_FUNC_EN_N;
1136 writel(reg, dp->reg_base + EXYNOS_DP_FUNC_EN_1);
1137
1138 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1139 reg &= ~INTERACE_SCAN_CFG;
1140 reg |= (video_info->interlaced << 2);
1141 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1142
1143 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1144 reg &= ~VSYNC_POLARITY_CFG;
1145 reg |= (video_info->v_sync_polarity << 1);
1146 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1147
1148 reg = readl(dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1149 reg &= ~HSYNC_POLARITY_CFG;
1150 reg |= (video_info->h_sync_polarity << 0);
1151 writel(reg, dp->reg_base + EXYNOS_DP_VIDEO_CTL_10);
1152
1153 reg = AUDIO_MODE_SPDIF_MODE | VIDEO_MODE_SLAVE_MODE;
1154 writel(reg, dp->reg_base + EXYNOS_DP_SOC_GENERAL_CTL);
1155}
1156
1157void exynos_dp_enable_scrambling(struct exynos_dp_device *dp)
1158{
1159 u32 reg;
1160
1161 reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
1162 reg &= ~SCRAMBLING_DISABLE;
1163 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
1164}
1165
1166void exynos_dp_disable_scrambling(struct exynos_dp_device *dp)
1167{
1168 u32 reg;
1169
1170 reg = readl(dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
1171 reg |= SCRAMBLING_DISABLE;
1172 writel(reg, dp->reg_base + EXYNOS_DP_TRAINING_PTN_SET);
1173}
diff --git a/drivers/video/exynos/exynos_dp_reg.h b/drivers/video/exynos/exynos_dp_reg.h
new file mode 100644
index 00000000000..42f608e2a43
--- /dev/null
+++ b/drivers/video/exynos/exynos_dp_reg.h
@@ -0,0 +1,335 @@
1/*
2 * Register definition file for Samsung DP driver
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Author: Jingoo Han <jg1.han@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _EXYNOS_DP_REG_H
13#define _EXYNOS_DP_REG_H
14
15#define EXYNOS_DP_TX_SW_RESET 0x14
16#define EXYNOS_DP_FUNC_EN_1 0x18
17#define EXYNOS_DP_FUNC_EN_2 0x1C
18#define EXYNOS_DP_VIDEO_CTL_1 0x20
19#define EXYNOS_DP_VIDEO_CTL_2 0x24
20#define EXYNOS_DP_VIDEO_CTL_3 0x28
21
22#define EXYNOS_DP_VIDEO_CTL_8 0x3C
23#define EXYNOS_DP_VIDEO_CTL_10 0x44
24
25#define EXYNOS_DP_LANE_MAP 0x35C
26
27#define EXYNOS_DP_AUX_HW_RETRY_CTL 0x390
28
29#define EXYNOS_DP_COMMON_INT_STA_1 0x3C4
30#define EXYNOS_DP_COMMON_INT_STA_2 0x3C8
31#define EXYNOS_DP_COMMON_INT_STA_3 0x3CC
32#define EXYNOS_DP_COMMON_INT_STA_4 0x3D0
33#define EXYNOS_DP_INT_STA 0x3DC
34#define EXYNOS_DP_COMMON_INT_MASK_1 0x3E0
35#define EXYNOS_DP_COMMON_INT_MASK_2 0x3E4
36#define EXYNOS_DP_COMMON_INT_MASK_3 0x3E8
37#define EXYNOS_DP_COMMON_INT_MASK_4 0x3EC
38#define EXYNOS_DP_INT_STA_MASK 0x3F8
39#define EXYNOS_DP_INT_CTL 0x3FC
40
41#define EXYNOS_DP_SYS_CTL_1 0x600
42#define EXYNOS_DP_SYS_CTL_2 0x604
43#define EXYNOS_DP_SYS_CTL_3 0x608
44#define EXYNOS_DP_SYS_CTL_4 0x60C
45
46#define EXYNOS_DP_PKT_SEND_CTL 0x640
47#define EXYNOS_DP_HDCP_CTL 0x648
48
49#define EXYNOS_DP_LINK_BW_SET 0x680
50#define EXYNOS_DP_LANE_COUNT_SET 0x684
51#define EXYNOS_DP_TRAINING_PTN_SET 0x688
52#define EXYNOS_DP_LN0_LINK_TRAINING_CTL 0x68C
53#define EXYNOS_DP_LN1_LINK_TRAINING_CTL 0x690
54#define EXYNOS_DP_LN2_LINK_TRAINING_CTL 0x694
55#define EXYNOS_DP_LN3_LINK_TRAINING_CTL 0x698
56
57#define EXYNOS_DP_DEBUG_CTL 0x6C0
58#define EXYNOS_DP_HPD_DEGLITCH_L 0x6C4
59#define EXYNOS_DP_HPD_DEGLITCH_H 0x6C8
60#define EXYNOS_DP_LINK_DEBUG_CTL 0x6E0
61
62#define EXYNOS_DP_M_VID_0 0x700
63#define EXYNOS_DP_M_VID_1 0x704
64#define EXYNOS_DP_M_VID_2 0x708
65#define EXYNOS_DP_N_VID_0 0x70C
66#define EXYNOS_DP_N_VID_1 0x710
67#define EXYNOS_DP_N_VID_2 0x714
68
69#define EXYNOS_DP_PLL_CTL 0x71C
70#define EXYNOS_DP_PHY_PD 0x720
71#define EXYNOS_DP_PHY_TEST 0x724
72
73#define EXYNOS_DP_VIDEO_FIFO_THRD 0x730
74#define EXYNOS_DP_AUDIO_MARGIN 0x73C
75
76#define EXYNOS_DP_M_VID_GEN_FILTER_TH 0x764
77#define EXYNOS_DP_M_AUD_GEN_FILTER_TH 0x778
78#define EXYNOS_DP_AUX_CH_STA 0x780
79#define EXYNOS_DP_AUX_CH_DEFER_CTL 0x788
80#define EXYNOS_DP_AUX_RX_COMM 0x78C
81#define EXYNOS_DP_BUFFER_DATA_CTL 0x790
82#define EXYNOS_DP_AUX_CH_CTL_1 0x794
83#define EXYNOS_DP_AUX_ADDR_7_0 0x798
84#define EXYNOS_DP_AUX_ADDR_15_8 0x79C
85#define EXYNOS_DP_AUX_ADDR_19_16 0x7A0
86#define EXYNOS_DP_AUX_CH_CTL_2 0x7A4
87
88#define EXYNOS_DP_BUF_DATA_0 0x7C0
89
90#define EXYNOS_DP_SOC_GENERAL_CTL 0x800
91
92/* EXYNOS_DP_TX_SW_RESET */
93#define RESET_DP_TX (0x1 << 0)
94
95/* EXYNOS_DP_FUNC_EN_1 */
96#define MASTER_VID_FUNC_EN_N (0x1 << 7)
97#define SLAVE_VID_FUNC_EN_N (0x1 << 5)
98#define AUD_FIFO_FUNC_EN_N (0x1 << 4)
99#define AUD_FUNC_EN_N (0x1 << 3)
100#define HDCP_FUNC_EN_N (0x1 << 2)
101#define CRC_FUNC_EN_N (0x1 << 1)
102#define SW_FUNC_EN_N (0x1 << 0)
103
104/* EXYNOS_DP_FUNC_EN_2 */
105#define SSC_FUNC_EN_N (0x1 << 7)
106#define AUX_FUNC_EN_N (0x1 << 2)
107#define SERDES_FIFO_FUNC_EN_N (0x1 << 1)
108#define LS_CLK_DOMAIN_FUNC_EN_N (0x1 << 0)
109
110/* EXYNOS_DP_VIDEO_CTL_1 */
111#define VIDEO_EN (0x1 << 7)
112#define HDCP_VIDEO_MUTE (0x1 << 6)
113
114/* EXYNOS_DP_VIDEO_CTL_1 */
115#define IN_D_RANGE_MASK (0x1 << 7)
116#define IN_D_RANGE_SHIFT (7)
117#define IN_D_RANGE_CEA (0x1 << 7)
118#define IN_D_RANGE_VESA (0x0 << 7)
119#define IN_BPC_MASK (0x7 << 4)
120#define IN_BPC_SHIFT (4)
121#define IN_BPC_12_BITS (0x3 << 4)
122#define IN_BPC_10_BITS (0x2 << 4)
123#define IN_BPC_8_BITS (0x1 << 4)
124#define IN_BPC_6_BITS (0x0 << 4)
125#define IN_COLOR_F_MASK (0x3 << 0)
126#define IN_COLOR_F_SHIFT (0)
127#define IN_COLOR_F_YCBCR444 (0x2 << 0)
128#define IN_COLOR_F_YCBCR422 (0x1 << 0)
129#define IN_COLOR_F_RGB (0x0 << 0)
130
131/* EXYNOS_DP_VIDEO_CTL_3 */
132#define IN_YC_COEFFI_MASK (0x1 << 7)
133#define IN_YC_COEFFI_SHIFT (7)
134#define IN_YC_COEFFI_ITU709 (0x1 << 7)
135#define IN_YC_COEFFI_ITU601 (0x0 << 7)
136#define VID_CHK_UPDATE_TYPE_MASK (0x1 << 4)
137#define VID_CHK_UPDATE_TYPE_SHIFT (4)
138#define VID_CHK_UPDATE_TYPE_1 (0x1 << 4)
139#define VID_CHK_UPDATE_TYPE_0 (0x0 << 4)
140
141/* EXYNOS_DP_VIDEO_CTL_8 */
142#define VID_HRES_TH(x) (((x) & 0xf) << 4)
143#define VID_VRES_TH(x) (((x) & 0xf) << 0)
144
145/* EXYNOS_DP_VIDEO_CTL_10 */
146#define FORMAT_SEL (0x1 << 4)
147#define INTERACE_SCAN_CFG (0x1 << 2)
148#define VSYNC_POLARITY_CFG (0x1 << 1)
149#define HSYNC_POLARITY_CFG (0x1 << 0)
150
151/* EXYNOS_DP_LANE_MAP */
152#define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6)
153#define LANE3_MAP_LOGIC_LANE_1 (0x1 << 6)
154#define LANE3_MAP_LOGIC_LANE_2 (0x2 << 6)
155#define LANE3_MAP_LOGIC_LANE_3 (0x3 << 6)
156#define LANE2_MAP_LOGIC_LANE_0 (0x0 << 4)
157#define LANE2_MAP_LOGIC_LANE_1 (0x1 << 4)
158#define LANE2_MAP_LOGIC_LANE_2 (0x2 << 4)
159#define LANE2_MAP_LOGIC_LANE_3 (0x3 << 4)
160#define LANE1_MAP_LOGIC_LANE_0 (0x0 << 2)
161#define LANE1_MAP_LOGIC_LANE_1 (0x1 << 2)
162#define LANE1_MAP_LOGIC_LANE_2 (0x2 << 2)
163#define LANE1_MAP_LOGIC_LANE_3 (0x3 << 2)
164#define LANE0_MAP_LOGIC_LANE_0 (0x0 << 0)
165#define LANE0_MAP_LOGIC_LANE_1 (0x1 << 0)
166#define LANE0_MAP_LOGIC_LANE_2 (0x2 << 0)
167#define LANE0_MAP_LOGIC_LANE_3 (0x3 << 0)
168
169/* EXYNOS_DP_AUX_HW_RETRY_CTL */
170#define AUX_BIT_PERIOD_EXPECTED_DELAY(x) (((x) & 0x7) << 8)
171#define AUX_HW_RETRY_INTERVAL_MASK (0x3 << 3)
172#define AUX_HW_RETRY_INTERVAL_600_MICROSECONDS (0x0 << 3)
173#define AUX_HW_RETRY_INTERVAL_800_MICROSECONDS (0x1 << 3)
174#define AUX_HW_RETRY_INTERVAL_1000_MICROSECONDS (0x2 << 3)
175#define AUX_HW_RETRY_INTERVAL_1800_MICROSECONDS (0x3 << 3)
176#define AUX_HW_RETRY_COUNT_SEL(x) (((x) & 0x7) << 0)
177
178/* EXYNOS_DP_COMMON_INT_STA_1 */
179#define VSYNC_DET (0x1 << 7)
180#define PLL_LOCK_CHG (0x1 << 6)
181#define SPDIF_ERR (0x1 << 5)
182#define SPDIF_UNSTBL (0x1 << 4)
183#define VID_FORMAT_CHG (0x1 << 3)
184#define AUD_CLK_CHG (0x1 << 2)
185#define VID_CLK_CHG (0x1 << 1)
186#define SW_INT (0x1 << 0)
187
188/* EXYNOS_DP_COMMON_INT_STA_2 */
189#define ENC_EN_CHG (0x1 << 6)
190#define HW_BKSV_RDY (0x1 << 3)
191#define HW_SHA_DONE (0x1 << 2)
192#define HW_AUTH_STATE_CHG (0x1 << 1)
193#define HW_AUTH_DONE (0x1 << 0)
194
195/* EXYNOS_DP_COMMON_INT_STA_3 */
196#define AFIFO_UNDER (0x1 << 7)
197#define AFIFO_OVER (0x1 << 6)
198#define R0_CHK_FLAG (0x1 << 5)
199
200/* EXYNOS_DP_COMMON_INT_STA_4 */
201#define PSR_ACTIVE (0x1 << 7)
202#define PSR_INACTIVE (0x1 << 6)
203#define SPDIF_BI_PHASE_ERR (0x1 << 5)
204#define HOTPLUG_CHG (0x1 << 2)
205#define HPD_LOST (0x1 << 1)
206#define PLUG (0x1 << 0)
207
208/* EXYNOS_DP_INT_STA */
209#define INT_HPD (0x1 << 6)
210#define HW_TRAINING_FINISH (0x1 << 5)
211#define RPLY_RECEIV (0x1 << 1)
212#define AUX_ERR (0x1 << 0)
213
214/* EXYNOS_DP_INT_CTL */
215#define SOFT_INT_CTRL (0x1 << 2)
216#define INT_POL (0x1 << 0)
217
218/* EXYNOS_DP_SYS_CTL_1 */
219#define DET_STA (0x1 << 2)
220#define FORCE_DET (0x1 << 1)
221#define DET_CTRL (0x1 << 0)
222
223/* EXYNOS_DP_SYS_CTL_2 */
224#define CHA_CRI(x) (((x) & 0xf) << 4)
225#define CHA_STA (0x1 << 2)
226#define FORCE_CHA (0x1 << 1)
227#define CHA_CTRL (0x1 << 0)
228
229/* EXYNOS_DP_SYS_CTL_3 */
230#define HPD_STATUS (0x1 << 6)
231#define F_HPD (0x1 << 5)
232#define HPD_CTRL (0x1 << 4)
233#define HDCP_RDY (0x1 << 3)
234#define STRM_VALID (0x1 << 2)
235#define F_VALID (0x1 << 1)
236#define VALID_CTRL (0x1 << 0)
237
238/* EXYNOS_DP_SYS_CTL_4 */
239#define FIX_M_AUD (0x1 << 4)
240#define ENHANCED (0x1 << 3)
241#define FIX_M_VID (0x1 << 2)
242#define M_VID_UPDATE_CTRL (0x3 << 0)
243
244/* EXYNOS_DP_TRAINING_PTN_SET */
245#define SCRAMBLER_TYPE (0x1 << 9)
246#define HW_LINK_TRAINING_PATTERN (0x1 << 8)
247#define SCRAMBLING_DISABLE (0x1 << 5)
248#define SCRAMBLING_ENABLE (0x0 << 5)
249#define LINK_QUAL_PATTERN_SET_MASK (0x3 << 2)
250#define LINK_QUAL_PATTERN_SET_PRBS7 (0x3 << 2)
251#define LINK_QUAL_PATTERN_SET_D10_2 (0x1 << 2)
252#define LINK_QUAL_PATTERN_SET_DISABLE (0x0 << 2)
253#define SW_TRAINING_PATTERN_SET_MASK (0x3 << 0)
254#define SW_TRAINING_PATTERN_SET_PTN2 (0x2 << 0)
255#define SW_TRAINING_PATTERN_SET_PTN1 (0x1 << 0)
256#define SW_TRAINING_PATTERN_SET_NORMAL (0x0 << 0)
257
258/* EXYNOS_DP_LN0_LINK_TRAINING_CTL */
259#define PRE_EMPHASIS_SET_SHIFT (3)
260
261/* EXYNOS_DP_DEBUG_CTL */
262#define PLL_LOCK (0x1 << 4)
263#define F_PLL_LOCK (0x1 << 3)
264#define PLL_LOCK_CTRL (0x1 << 2)
265#define PN_INV (0x1 << 0)
266
267/* EXYNOS_DP_PLL_CTL */
268#define DP_PLL_PD (0x1 << 7)
269#define DP_PLL_RESET (0x1 << 6)
270#define DP_PLL_LOOP_BIT_DEFAULT (0x1 << 4)
271#define DP_PLL_REF_BIT_1_1250V (0x5 << 0)
272#define DP_PLL_REF_BIT_1_2500V (0x7 << 0)
273
274/* EXYNOS_DP_PHY_PD */
275#define DP_PHY_PD (0x1 << 5)
276#define AUX_PD (0x1 << 4)
277#define CH3_PD (0x1 << 3)
278#define CH2_PD (0x1 << 2)
279#define CH1_PD (0x1 << 1)
280#define CH0_PD (0x1 << 0)
281
282/* EXYNOS_DP_PHY_TEST */
283#define MACRO_RST (0x1 << 5)
284#define CH1_TEST (0x1 << 1)
285#define CH0_TEST (0x1 << 0)
286
287/* EXYNOS_DP_AUX_CH_STA */
288#define AUX_BUSY (0x1 << 4)
289#define AUX_STATUS_MASK (0xf << 0)
290
291/* EXYNOS_DP_AUX_CH_DEFER_CTL */
292#define DEFER_CTRL_EN (0x1 << 7)
293#define DEFER_COUNT(x) (((x) & 0x7f) << 0)
294
295/* EXYNOS_DP_AUX_RX_COMM */
296#define AUX_RX_COMM_I2C_DEFER (0x2 << 2)
297#define AUX_RX_COMM_AUX_DEFER (0x2 << 0)
298
299/* EXYNOS_DP_BUFFER_DATA_CTL */
300#define BUF_CLR (0x1 << 7)
301#define BUF_DATA_COUNT(x) (((x) & 0x1f) << 0)
302
303/* EXYNOS_DP_AUX_CH_CTL_1 */
304#define AUX_LENGTH(x) (((x - 1) & 0xf) << 4)
305#define AUX_TX_COMM_MASK (0xf << 0)
306#define AUX_TX_COMM_DP_TRANSACTION (0x1 << 3)
307#define AUX_TX_COMM_I2C_TRANSACTION (0x0 << 3)
308#define AUX_TX_COMM_MOT (0x1 << 2)
309#define AUX_TX_COMM_WRITE (0x0 << 0)
310#define AUX_TX_COMM_READ (0x1 << 0)
311
312/* EXYNOS_DP_AUX_ADDR_7_0 */
313#define AUX_ADDR_7_0(x) (((x) >> 0) & 0xff)
314
315/* EXYNOS_DP_AUX_ADDR_15_8 */
316#define AUX_ADDR_15_8(x) (((x) >> 8) & 0xff)
317
318/* EXYNOS_DP_AUX_ADDR_19_16 */
319#define AUX_ADDR_19_16(x) (((x) >> 16) & 0x0f)
320
321/* EXYNOS_DP_AUX_CH_CTL_2 */
322#define ADDR_ONLY (0x1 << 1)
323#define AUX_EN (0x1 << 0)
324
325/* EXYNOS_DP_SOC_GENERAL_CTL */
326#define AUDIO_MODE_SPDIF_MODE (0x1 << 8)
327#define AUDIO_MODE_MASTER_MODE (0x0 << 8)
328#define MASTER_VIDEO_INTERLACE_EN (0x1 << 4)
329#define VIDEO_MASTER_CLK_SEL (0x1 << 2)
330#define VIDEO_MASTER_MODE_EN (0x1 << 1)
331#define VIDEO_MODE_MASK (0x1 << 0)
332#define VIDEO_MODE_SLAVE_MODE (0x1 << 0)
333#define VIDEO_MODE_MASTER_MODE (0x0 << 0)
334
335#endif /* _EXYNOS_DP_REG_H */
diff --git a/include/video/exynos_dp.h b/include/video/exynos_dp.h
new file mode 100644
index 00000000000..8847a9d6dd4
--- /dev/null
+++ b/include/video/exynos_dp.h
@@ -0,0 +1,131 @@
1/*
2 * Samsung SoC DP device support
3 *
4 * Copyright (C) 2012 Samsung Electronics Co., Ltd.
5 * Author: Jingoo Han <jg1.han@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef _EXYNOS_DP_H
13#define _EXYNOS_DP_H
14
15#define DP_TIMEOUT_LOOP_COUNT 100
16#define MAX_CR_LOOP 5
17#define MAX_EQ_LOOP 4
18
19enum link_rate_type {
20 LINK_RATE_1_62GBPS = 0x06,
21 LINK_RATE_2_70GBPS = 0x0a
22};
23
24enum link_lane_count_type {
25 LANE_COUNT1 = 1,
26 LANE_COUNT2 = 2,
27 LANE_COUNT4 = 4
28};
29
30enum link_training_state {
31 START,
32 CLOCK_RECOVERY,
33 EQUALIZER_TRAINING,
34 FINISHED,
35 FAILED
36};
37
38enum voltage_swing_level {
39 VOLTAGE_LEVEL_0,
40 VOLTAGE_LEVEL_1,
41 VOLTAGE_LEVEL_2,
42 VOLTAGE_LEVEL_3,
43};
44
45enum pre_emphasis_level {
46 PRE_EMPHASIS_LEVEL_0,
47 PRE_EMPHASIS_LEVEL_1,
48 PRE_EMPHASIS_LEVEL_2,
49 PRE_EMPHASIS_LEVEL_3,
50};
51
52enum pattern_set {
53 PRBS7,
54 D10_2,
55 TRAINING_PTN1,
56 TRAINING_PTN2,
57 DP_NONE
58};
59
60enum color_space {
61 COLOR_RGB,
62 COLOR_YCBCR422,
63 COLOR_YCBCR444
64};
65
66enum color_depth {
67 COLOR_6,
68 COLOR_8,
69 COLOR_10,
70 COLOR_12
71};
72
73enum color_coefficient {
74 COLOR_YCBCR601,
75 COLOR_YCBCR709
76};
77
78enum dynamic_range {
79 VESA,
80 CEA
81};
82
83enum pll_status {
84 PLL_UNLOCKED,
85 PLL_LOCKED
86};
87
88enum clock_recovery_m_value_type {
89 CALCULATED_M,
90 REGISTER_M
91};
92
93enum video_timing_recognition_type {
94 VIDEO_TIMING_FROM_CAPTURE,
95 VIDEO_TIMING_FROM_REGISTER
96};
97
98enum analog_power_block {
99 AUX_BLOCK,
100 CH0_BLOCK,
101 CH1_BLOCK,
102 CH2_BLOCK,
103 CH3_BLOCK,
104 ANALOG_TOTAL,
105 POWER_ALL
106};
107
108struct video_info {
109 char *name;
110
111 bool h_sync_polarity;
112 bool v_sync_polarity;
113 bool interlaced;
114
115 enum color_space color_space;
116 enum dynamic_range dynamic_range;
117 enum color_coefficient ycbcr_coeff;
118 enum color_depth color_depth;
119
120 enum link_rate_type link_rate;
121 enum link_lane_count_type lane_count;
122};
123
124struct exynos_dp_platdata {
125 struct video_info *video_info;
126
127 void (*phy_init)(void);
128 void (*phy_exit)(void);
129};
130
131#endif /* _EXYNOS_DP_H */