drm/exynos: remove module of exynos drm subdrv
[deliverable/linux.git] / drivers / gpu / drm / exynos / exynos_hdmi.c
1 /*
2 * Copyright (C) 2011 Samsung Electronics Co.Ltd
3 * Authors:
4 * Seung-Woo Kim <sw0312.kim@samsung.com>
5 * Inki Dae <inki.dae@samsung.com>
6 * Joonyoung Shim <jy0922.shim@samsung.com>
7 *
8 * Based on drivers/media/video/s5p-tv/hdmi_drv.c
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 */
16
17 #include "drmP.h"
18 #include "drm_edid.h"
19 #include "drm_crtc_helper.h"
20
21 #include "regs-hdmi.h"
22
23 #include <linux/kernel.h>
24 #include <linux/spinlock.h>
25 #include <linux/wait.h>
26 #include <linux/i2c.h>
27 #include <linux/module.h>
28 #include <linux/platform_device.h>
29 #include <linux/interrupt.h>
30 #include <linux/irq.h>
31 #include <linux/delay.h>
32 #include <linux/pm_runtime.h>
33 #include <linux/clk.h>
34 #include <linux/regulator/consumer.h>
35
36 #include <drm/exynos_drm.h>
37
38 #include "exynos_drm_drv.h"
39 #include "exynos_drm_hdmi.h"
40
41 #include "exynos_hdmi.h"
42
43 #define HDMI_OVERLAY_NUMBER 3
44 #define MAX_WIDTH 1920
45 #define MAX_HEIGHT 1080
46 #define get_hdmi_context(dev) platform_get_drvdata(to_platform_device(dev))
47
48 /* HDMI Version 1.3 */
49 static const u8 hdmiphy_v13_conf27[32] = {
50 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
51 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
52 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
53 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
54 };
55
56 static const u8 hdmiphy_v13_conf27_027[32] = {
57 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
58 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
59 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
60 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
61 };
62
63 static const u8 hdmiphy_v13_conf74_175[32] = {
64 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
65 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
66 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
67 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
68 };
69
70 static const u8 hdmiphy_v13_conf74_25[32] = {
71 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
72 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
73 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
74 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
75 };
76
77 static const u8 hdmiphy_v13_conf148_5[32] = {
78 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
79 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
80 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
81 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
82 };
83
84 struct hdmi_v13_tg_regs {
85 u8 cmd;
86 u8 h_fsz_l;
87 u8 h_fsz_h;
88 u8 hact_st_l;
89 u8 hact_st_h;
90 u8 hact_sz_l;
91 u8 hact_sz_h;
92 u8 v_fsz_l;
93 u8 v_fsz_h;
94 u8 vsync_l;
95 u8 vsync_h;
96 u8 vsync2_l;
97 u8 vsync2_h;
98 u8 vact_st_l;
99 u8 vact_st_h;
100 u8 vact_sz_l;
101 u8 vact_sz_h;
102 u8 field_chg_l;
103 u8 field_chg_h;
104 u8 vact_st2_l;
105 u8 vact_st2_h;
106 u8 vsync_top_hdmi_l;
107 u8 vsync_top_hdmi_h;
108 u8 vsync_bot_hdmi_l;
109 u8 vsync_bot_hdmi_h;
110 u8 field_top_hdmi_l;
111 u8 field_top_hdmi_h;
112 u8 field_bot_hdmi_l;
113 u8 field_bot_hdmi_h;
114 };
115
116 struct hdmi_v13_core_regs {
117 u8 h_blank[2];
118 u8 v_blank[3];
119 u8 h_v_line[3];
120 u8 vsync_pol[1];
121 u8 int_pro_mode[1];
122 u8 v_blank_f[3];
123 u8 h_sync_gen[3];
124 u8 v_sync_gen1[3];
125 u8 v_sync_gen2[3];
126 u8 v_sync_gen3[3];
127 };
128
129 struct hdmi_v13_preset_conf {
130 struct hdmi_v13_core_regs core;
131 struct hdmi_v13_tg_regs tg;
132 };
133
134 struct hdmi_v13_conf {
135 int width;
136 int height;
137 int vrefresh;
138 bool interlace;
139 const u8 *hdmiphy_data;
140 const struct hdmi_v13_preset_conf *conf;
141 };
142
143 static const struct hdmi_v13_preset_conf hdmi_v13_conf_480p = {
144 .core = {
145 .h_blank = {0x8a, 0x00},
146 .v_blank = {0x0d, 0x6a, 0x01},
147 .h_v_line = {0x0d, 0xa2, 0x35},
148 .vsync_pol = {0x01},
149 .int_pro_mode = {0x00},
150 .v_blank_f = {0x00, 0x00, 0x00},
151 .h_sync_gen = {0x0e, 0x30, 0x11},
152 .v_sync_gen1 = {0x0f, 0x90, 0x00},
153 /* other don't care */
154 },
155 .tg = {
156 0x00, /* cmd */
157 0x5a, 0x03, /* h_fsz */
158 0x8a, 0x00, 0xd0, 0x02, /* hact */
159 0x0d, 0x02, /* v_fsz */
160 0x01, 0x00, 0x33, 0x02, /* vsync */
161 0x2d, 0x00, 0xe0, 0x01, /* vact */
162 0x33, 0x02, /* field_chg */
163 0x49, 0x02, /* vact_st2 */
164 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
165 0x01, 0x00, 0x33, 0x02, /* field top/bot */
166 },
167 };
168
169 static const struct hdmi_v13_preset_conf hdmi_v13_conf_720p60 = {
170 .core = {
171 .h_blank = {0x72, 0x01},
172 .v_blank = {0xee, 0xf2, 0x00},
173 .h_v_line = {0xee, 0x22, 0x67},
174 .vsync_pol = {0x00},
175 .int_pro_mode = {0x00},
176 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
177 .h_sync_gen = {0x6c, 0x50, 0x02},
178 .v_sync_gen1 = {0x0a, 0x50, 0x00},
179 .v_sync_gen2 = {0x01, 0x10, 0x00},
180 .v_sync_gen3 = {0x01, 0x10, 0x00},
181 /* other don't care */
182 },
183 .tg = {
184 0x00, /* cmd */
185 0x72, 0x06, /* h_fsz */
186 0x71, 0x01, 0x01, 0x05, /* hact */
187 0xee, 0x02, /* v_fsz */
188 0x01, 0x00, 0x33, 0x02, /* vsync */
189 0x1e, 0x00, 0xd0, 0x02, /* vact */
190 0x33, 0x02, /* field_chg */
191 0x49, 0x02, /* vact_st2 */
192 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
193 0x01, 0x00, 0x33, 0x02, /* field top/bot */
194 },
195 };
196
197 static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i50 = {
198 .core = {
199 .h_blank = {0xd0, 0x02},
200 .v_blank = {0x32, 0xB2, 0x00},
201 .h_v_line = {0x65, 0x04, 0xa5},
202 .vsync_pol = {0x00},
203 .int_pro_mode = {0x01},
204 .v_blank_f = {0x49, 0x2A, 0x23},
205 .h_sync_gen = {0x0E, 0xEA, 0x08},
206 .v_sync_gen1 = {0x07, 0x20, 0x00},
207 .v_sync_gen2 = {0x39, 0x42, 0x23},
208 .v_sync_gen3 = {0x38, 0x87, 0x73},
209 /* other don't care */
210 },
211 .tg = {
212 0x00, /* cmd */
213 0x50, 0x0A, /* h_fsz */
214 0xCF, 0x02, 0x81, 0x07, /* hact */
215 0x65, 0x04, /* v_fsz */
216 0x01, 0x00, 0x33, 0x02, /* vsync */
217 0x16, 0x00, 0x1c, 0x02, /* vact */
218 0x33, 0x02, /* field_chg */
219 0x49, 0x02, /* vact_st2 */
220 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
221 0x01, 0x00, 0x33, 0x02, /* field top/bot */
222 },
223 };
224
225 static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p50 = {
226 .core = {
227 .h_blank = {0xd0, 0x02},
228 .v_blank = {0x65, 0x6c, 0x01},
229 .h_v_line = {0x65, 0x04, 0xa5},
230 .vsync_pol = {0x00},
231 .int_pro_mode = {0x00},
232 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
233 .h_sync_gen = {0x0e, 0xea, 0x08},
234 .v_sync_gen1 = {0x09, 0x40, 0x00},
235 .v_sync_gen2 = {0x01, 0x10, 0x00},
236 .v_sync_gen3 = {0x01, 0x10, 0x00},
237 /* other don't care */
238 },
239 .tg = {
240 0x00, /* cmd */
241 0x50, 0x0A, /* h_fsz */
242 0xCF, 0x02, 0x81, 0x07, /* hact */
243 0x65, 0x04, /* v_fsz */
244 0x01, 0x00, 0x33, 0x02, /* vsync */
245 0x2d, 0x00, 0x38, 0x04, /* vact */
246 0x33, 0x02, /* field_chg */
247 0x48, 0x02, /* vact_st2 */
248 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
249 0x01, 0x00, 0x33, 0x02, /* field top/bot */
250 },
251 };
252
253 static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i60 = {
254 .core = {
255 .h_blank = {0x18, 0x01},
256 .v_blank = {0x32, 0xB2, 0x00},
257 .h_v_line = {0x65, 0x84, 0x89},
258 .vsync_pol = {0x00},
259 .int_pro_mode = {0x01},
260 .v_blank_f = {0x49, 0x2A, 0x23},
261 .h_sync_gen = {0x56, 0x08, 0x02},
262 .v_sync_gen1 = {0x07, 0x20, 0x00},
263 .v_sync_gen2 = {0x39, 0x42, 0x23},
264 .v_sync_gen3 = {0xa4, 0x44, 0x4a},
265 /* other don't care */
266 },
267 .tg = {
268 0x00, /* cmd */
269 0x98, 0x08, /* h_fsz */
270 0x17, 0x01, 0x81, 0x07, /* hact */
271 0x65, 0x04, /* v_fsz */
272 0x01, 0x00, 0x33, 0x02, /* vsync */
273 0x16, 0x00, 0x1c, 0x02, /* vact */
274 0x33, 0x02, /* field_chg */
275 0x49, 0x02, /* vact_st2 */
276 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
277 0x01, 0x00, 0x33, 0x02, /* field top/bot */
278 },
279 };
280
281 static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p60 = {
282 .core = {
283 .h_blank = {0x18, 0x01},
284 .v_blank = {0x65, 0x6c, 0x01},
285 .h_v_line = {0x65, 0x84, 0x89},
286 .vsync_pol = {0x00},
287 .int_pro_mode = {0x00},
288 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
289 .h_sync_gen = {0x56, 0x08, 0x02},
290 .v_sync_gen1 = {0x09, 0x40, 0x00},
291 .v_sync_gen2 = {0x01, 0x10, 0x00},
292 .v_sync_gen3 = {0x01, 0x10, 0x00},
293 /* other don't care */
294 },
295 .tg = {
296 0x00, /* cmd */
297 0x98, 0x08, /* h_fsz */
298 0x17, 0x01, 0x81, 0x07, /* hact */
299 0x65, 0x04, /* v_fsz */
300 0x01, 0x00, 0x33, 0x02, /* vsync */
301 0x2d, 0x00, 0x38, 0x04, /* vact */
302 0x33, 0x02, /* field_chg */
303 0x48, 0x02, /* vact_st2 */
304 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
305 0x01, 0x00, 0x33, 0x02, /* field top/bot */
306 },
307 };
308
309 static const struct hdmi_v13_conf hdmi_v13_confs[] = {
310 { 1280, 720, 60, false, hdmiphy_v13_conf74_25, &hdmi_v13_conf_720p60 },
311 { 1280, 720, 50, false, hdmiphy_v13_conf74_25, &hdmi_v13_conf_720p60 },
312 { 720, 480, 60, false, hdmiphy_v13_conf27_027, &hdmi_v13_conf_480p },
313 { 1920, 1080, 50, true, hdmiphy_v13_conf74_25, &hdmi_v13_conf_1080i50 },
314 { 1920, 1080, 50, false, hdmiphy_v13_conf148_5,
315 &hdmi_v13_conf_1080p50 },
316 { 1920, 1080, 60, true, hdmiphy_v13_conf74_25, &hdmi_v13_conf_1080i60 },
317 { 1920, 1080, 60, false, hdmiphy_v13_conf148_5,
318 &hdmi_v13_conf_1080p60 },
319 };
320
321 /* HDMI Version 1.4 */
322 static const u8 hdmiphy_conf27_027[32] = {
323 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
324 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
325 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
326 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
327 };
328
329 static const u8 hdmiphy_conf74_25[32] = {
330 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
331 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
332 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
333 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
334 };
335
336 static const u8 hdmiphy_conf148_5[32] = {
337 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
338 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
339 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
340 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
341 };
342
343 struct hdmi_tg_regs {
344 u8 cmd;
345 u8 h_fsz_l;
346 u8 h_fsz_h;
347 u8 hact_st_l;
348 u8 hact_st_h;
349 u8 hact_sz_l;
350 u8 hact_sz_h;
351 u8 v_fsz_l;
352 u8 v_fsz_h;
353 u8 vsync_l;
354 u8 vsync_h;
355 u8 vsync2_l;
356 u8 vsync2_h;
357 u8 vact_st_l;
358 u8 vact_st_h;
359 u8 vact_sz_l;
360 u8 vact_sz_h;
361 u8 field_chg_l;
362 u8 field_chg_h;
363 u8 vact_st2_l;
364 u8 vact_st2_h;
365 u8 vact_st3_l;
366 u8 vact_st3_h;
367 u8 vact_st4_l;
368 u8 vact_st4_h;
369 u8 vsync_top_hdmi_l;
370 u8 vsync_top_hdmi_h;
371 u8 vsync_bot_hdmi_l;
372 u8 vsync_bot_hdmi_h;
373 u8 field_top_hdmi_l;
374 u8 field_top_hdmi_h;
375 u8 field_bot_hdmi_l;
376 u8 field_bot_hdmi_h;
377 u8 tg_3d;
378 };
379
380 struct hdmi_core_regs {
381 u8 h_blank[2];
382 u8 v2_blank[2];
383 u8 v1_blank[2];
384 u8 v_line[2];
385 u8 h_line[2];
386 u8 hsync_pol[1];
387 u8 vsync_pol[1];
388 u8 int_pro_mode[1];
389 u8 v_blank_f0[2];
390 u8 v_blank_f1[2];
391 u8 h_sync_start[2];
392 u8 h_sync_end[2];
393 u8 v_sync_line_bef_2[2];
394 u8 v_sync_line_bef_1[2];
395 u8 v_sync_line_aft_2[2];
396 u8 v_sync_line_aft_1[2];
397 u8 v_sync_line_aft_pxl_2[2];
398 u8 v_sync_line_aft_pxl_1[2];
399 u8 v_blank_f2[2]; /* for 3D mode */
400 u8 v_blank_f3[2]; /* for 3D mode */
401 u8 v_blank_f4[2]; /* for 3D mode */
402 u8 v_blank_f5[2]; /* for 3D mode */
403 u8 v_sync_line_aft_3[2];
404 u8 v_sync_line_aft_4[2];
405 u8 v_sync_line_aft_5[2];
406 u8 v_sync_line_aft_6[2];
407 u8 v_sync_line_aft_pxl_3[2];
408 u8 v_sync_line_aft_pxl_4[2];
409 u8 v_sync_line_aft_pxl_5[2];
410 u8 v_sync_line_aft_pxl_6[2];
411 u8 vact_space_1[2];
412 u8 vact_space_2[2];
413 u8 vact_space_3[2];
414 u8 vact_space_4[2];
415 u8 vact_space_5[2];
416 u8 vact_space_6[2];
417 };
418
419 struct hdmi_preset_conf {
420 struct hdmi_core_regs core;
421 struct hdmi_tg_regs tg;
422 };
423
424 struct hdmi_conf {
425 int width;
426 int height;
427 int vrefresh;
428 bool interlace;
429 const u8 *hdmiphy_data;
430 const struct hdmi_preset_conf *conf;
431 };
432
433 static const struct hdmi_preset_conf hdmi_conf_480p60 = {
434 .core = {
435 .h_blank = {0x8a, 0x00},
436 .v2_blank = {0x0d, 0x02},
437 .v1_blank = {0x2d, 0x00},
438 .v_line = {0x0d, 0x02},
439 .h_line = {0x5a, 0x03},
440 .hsync_pol = {0x01},
441 .vsync_pol = {0x01},
442 .int_pro_mode = {0x00},
443 .v_blank_f0 = {0xff, 0xff},
444 .v_blank_f1 = {0xff, 0xff},
445 .h_sync_start = {0x0e, 0x00},
446 .h_sync_end = {0x4c, 0x00},
447 .v_sync_line_bef_2 = {0x0f, 0x00},
448 .v_sync_line_bef_1 = {0x09, 0x00},
449 .v_sync_line_aft_2 = {0xff, 0xff},
450 .v_sync_line_aft_1 = {0xff, 0xff},
451 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
452 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
453 .v_blank_f2 = {0xff, 0xff},
454 .v_blank_f3 = {0xff, 0xff},
455 .v_blank_f4 = {0xff, 0xff},
456 .v_blank_f5 = {0xff, 0xff},
457 .v_sync_line_aft_3 = {0xff, 0xff},
458 .v_sync_line_aft_4 = {0xff, 0xff},
459 .v_sync_line_aft_5 = {0xff, 0xff},
460 .v_sync_line_aft_6 = {0xff, 0xff},
461 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
462 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
463 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
464 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
465 .vact_space_1 = {0xff, 0xff},
466 .vact_space_2 = {0xff, 0xff},
467 .vact_space_3 = {0xff, 0xff},
468 .vact_space_4 = {0xff, 0xff},
469 .vact_space_5 = {0xff, 0xff},
470 .vact_space_6 = {0xff, 0xff},
471 /* other don't care */
472 },
473 .tg = {
474 0x00, /* cmd */
475 0x5a, 0x03, /* h_fsz */
476 0x8a, 0x00, 0xd0, 0x02, /* hact */
477 0x0d, 0x02, /* v_fsz */
478 0x01, 0x00, 0x33, 0x02, /* vsync */
479 0x2d, 0x00, 0xe0, 0x01, /* vact */
480 0x33, 0x02, /* field_chg */
481 0x48, 0x02, /* vact_st2 */
482 0x00, 0x00, /* vact_st3 */
483 0x00, 0x00, /* vact_st4 */
484 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
485 0x01, 0x00, 0x33, 0x02, /* field top/bot */
486 0x00, /* 3d FP */
487 },
488 };
489
490 static const struct hdmi_preset_conf hdmi_conf_720p50 = {
491 .core = {
492 .h_blank = {0xbc, 0x02},
493 .v2_blank = {0xee, 0x02},
494 .v1_blank = {0x1e, 0x00},
495 .v_line = {0xee, 0x02},
496 .h_line = {0xbc, 0x07},
497 .hsync_pol = {0x00},
498 .vsync_pol = {0x00},
499 .int_pro_mode = {0x00},
500 .v_blank_f0 = {0xff, 0xff},
501 .v_blank_f1 = {0xff, 0xff},
502 .h_sync_start = {0xb6, 0x01},
503 .h_sync_end = {0xde, 0x01},
504 .v_sync_line_bef_2 = {0x0a, 0x00},
505 .v_sync_line_bef_1 = {0x05, 0x00},
506 .v_sync_line_aft_2 = {0xff, 0xff},
507 .v_sync_line_aft_1 = {0xff, 0xff},
508 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
509 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
510 .v_blank_f2 = {0xff, 0xff},
511 .v_blank_f3 = {0xff, 0xff},
512 .v_blank_f4 = {0xff, 0xff},
513 .v_blank_f5 = {0xff, 0xff},
514 .v_sync_line_aft_3 = {0xff, 0xff},
515 .v_sync_line_aft_4 = {0xff, 0xff},
516 .v_sync_line_aft_5 = {0xff, 0xff},
517 .v_sync_line_aft_6 = {0xff, 0xff},
518 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
519 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
520 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
521 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
522 .vact_space_1 = {0xff, 0xff},
523 .vact_space_2 = {0xff, 0xff},
524 .vact_space_3 = {0xff, 0xff},
525 .vact_space_4 = {0xff, 0xff},
526 .vact_space_5 = {0xff, 0xff},
527 .vact_space_6 = {0xff, 0xff},
528 /* other don't care */
529 },
530 .tg = {
531 0x00, /* cmd */
532 0xbc, 0x07, /* h_fsz */
533 0xbc, 0x02, 0x00, 0x05, /* hact */
534 0xee, 0x02, /* v_fsz */
535 0x01, 0x00, 0x33, 0x02, /* vsync */
536 0x1e, 0x00, 0xd0, 0x02, /* vact */
537 0x33, 0x02, /* field_chg */
538 0x48, 0x02, /* vact_st2 */
539 0x00, 0x00, /* vact_st3 */
540 0x00, 0x00, /* vact_st4 */
541 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
542 0x01, 0x00, 0x33, 0x02, /* field top/bot */
543 0x00, /* 3d FP */
544 },
545 };
546
547 static const struct hdmi_preset_conf hdmi_conf_720p60 = {
548 .core = {
549 .h_blank = {0x72, 0x01},
550 .v2_blank = {0xee, 0x02},
551 .v1_blank = {0x1e, 0x00},
552 .v_line = {0xee, 0x02},
553 .h_line = {0x72, 0x06},
554 .hsync_pol = {0x00},
555 .vsync_pol = {0x00},
556 .int_pro_mode = {0x00},
557 .v_blank_f0 = {0xff, 0xff},
558 .v_blank_f1 = {0xff, 0xff},
559 .h_sync_start = {0x6c, 0x00},
560 .h_sync_end = {0x94, 0x00},
561 .v_sync_line_bef_2 = {0x0a, 0x00},
562 .v_sync_line_bef_1 = {0x05, 0x00},
563 .v_sync_line_aft_2 = {0xff, 0xff},
564 .v_sync_line_aft_1 = {0xff, 0xff},
565 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
566 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
567 .v_blank_f2 = {0xff, 0xff},
568 .v_blank_f3 = {0xff, 0xff},
569 .v_blank_f4 = {0xff, 0xff},
570 .v_blank_f5 = {0xff, 0xff},
571 .v_sync_line_aft_3 = {0xff, 0xff},
572 .v_sync_line_aft_4 = {0xff, 0xff},
573 .v_sync_line_aft_5 = {0xff, 0xff},
574 .v_sync_line_aft_6 = {0xff, 0xff},
575 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
576 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
577 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
578 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
579 .vact_space_1 = {0xff, 0xff},
580 .vact_space_2 = {0xff, 0xff},
581 .vact_space_3 = {0xff, 0xff},
582 .vact_space_4 = {0xff, 0xff},
583 .vact_space_5 = {0xff, 0xff},
584 .vact_space_6 = {0xff, 0xff},
585 /* other don't care */
586 },
587 .tg = {
588 0x00, /* cmd */
589 0x72, 0x06, /* h_fsz */
590 0x72, 0x01, 0x00, 0x05, /* hact */
591 0xee, 0x02, /* v_fsz */
592 0x01, 0x00, 0x33, 0x02, /* vsync */
593 0x1e, 0x00, 0xd0, 0x02, /* vact */
594 0x33, 0x02, /* field_chg */
595 0x48, 0x02, /* vact_st2 */
596 0x00, 0x00, /* vact_st3 */
597 0x00, 0x00, /* vact_st4 */
598 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
599 0x01, 0x00, 0x33, 0x02, /* field top/bot */
600 0x00, /* 3d FP */
601 },
602 };
603
604 static const struct hdmi_preset_conf hdmi_conf_1080i50 = {
605 .core = {
606 .h_blank = {0xd0, 0x02},
607 .v2_blank = {0x32, 0x02},
608 .v1_blank = {0x16, 0x00},
609 .v_line = {0x65, 0x04},
610 .h_line = {0x50, 0x0a},
611 .hsync_pol = {0x00},
612 .vsync_pol = {0x00},
613 .int_pro_mode = {0x01},
614 .v_blank_f0 = {0x49, 0x02},
615 .v_blank_f1 = {0x65, 0x04},
616 .h_sync_start = {0x0e, 0x02},
617 .h_sync_end = {0x3a, 0x02},
618 .v_sync_line_bef_2 = {0x07, 0x00},
619 .v_sync_line_bef_1 = {0x02, 0x00},
620 .v_sync_line_aft_2 = {0x39, 0x02},
621 .v_sync_line_aft_1 = {0x34, 0x02},
622 .v_sync_line_aft_pxl_2 = {0x38, 0x07},
623 .v_sync_line_aft_pxl_1 = {0x38, 0x07},
624 .v_blank_f2 = {0xff, 0xff},
625 .v_blank_f3 = {0xff, 0xff},
626 .v_blank_f4 = {0xff, 0xff},
627 .v_blank_f5 = {0xff, 0xff},
628 .v_sync_line_aft_3 = {0xff, 0xff},
629 .v_sync_line_aft_4 = {0xff, 0xff},
630 .v_sync_line_aft_5 = {0xff, 0xff},
631 .v_sync_line_aft_6 = {0xff, 0xff},
632 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
633 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
634 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
635 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
636 .vact_space_1 = {0xff, 0xff},
637 .vact_space_2 = {0xff, 0xff},
638 .vact_space_3 = {0xff, 0xff},
639 .vact_space_4 = {0xff, 0xff},
640 .vact_space_5 = {0xff, 0xff},
641 .vact_space_6 = {0xff, 0xff},
642 /* other don't care */
643 },
644 .tg = {
645 0x00, /* cmd */
646 0x50, 0x0a, /* h_fsz */
647 0xd0, 0x02, 0x80, 0x07, /* hact */
648 0x65, 0x04, /* v_fsz */
649 0x01, 0x00, 0x33, 0x02, /* vsync */
650 0x16, 0x00, 0x1c, 0x02, /* vact */
651 0x33, 0x02, /* field_chg */
652 0x49, 0x02, /* vact_st2 */
653 0x00, 0x00, /* vact_st3 */
654 0x00, 0x00, /* vact_st4 */
655 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
656 0x01, 0x00, 0x33, 0x02, /* field top/bot */
657 0x00, /* 3d FP */
658 },
659 };
660
661 static const struct hdmi_preset_conf hdmi_conf_1080i60 = {
662 .core = {
663 .h_blank = {0x18, 0x01},
664 .v2_blank = {0x32, 0x02},
665 .v1_blank = {0x16, 0x00},
666 .v_line = {0x65, 0x04},
667 .h_line = {0x98, 0x08},
668 .hsync_pol = {0x00},
669 .vsync_pol = {0x00},
670 .int_pro_mode = {0x01},
671 .v_blank_f0 = {0x49, 0x02},
672 .v_blank_f1 = {0x65, 0x04},
673 .h_sync_start = {0x56, 0x00},
674 .h_sync_end = {0x82, 0x00},
675 .v_sync_line_bef_2 = {0x07, 0x00},
676 .v_sync_line_bef_1 = {0x02, 0x00},
677 .v_sync_line_aft_2 = {0x39, 0x02},
678 .v_sync_line_aft_1 = {0x34, 0x02},
679 .v_sync_line_aft_pxl_2 = {0xa4, 0x04},
680 .v_sync_line_aft_pxl_1 = {0xa4, 0x04},
681 .v_blank_f2 = {0xff, 0xff},
682 .v_blank_f3 = {0xff, 0xff},
683 .v_blank_f4 = {0xff, 0xff},
684 .v_blank_f5 = {0xff, 0xff},
685 .v_sync_line_aft_3 = {0xff, 0xff},
686 .v_sync_line_aft_4 = {0xff, 0xff},
687 .v_sync_line_aft_5 = {0xff, 0xff},
688 .v_sync_line_aft_6 = {0xff, 0xff},
689 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
690 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
691 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
692 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
693 .vact_space_1 = {0xff, 0xff},
694 .vact_space_2 = {0xff, 0xff},
695 .vact_space_3 = {0xff, 0xff},
696 .vact_space_4 = {0xff, 0xff},
697 .vact_space_5 = {0xff, 0xff},
698 .vact_space_6 = {0xff, 0xff},
699 /* other don't care */
700 },
701 .tg = {
702 0x00, /* cmd */
703 0x98, 0x08, /* h_fsz */
704 0x18, 0x01, 0x80, 0x07, /* hact */
705 0x65, 0x04, /* v_fsz */
706 0x01, 0x00, 0x33, 0x02, /* vsync */
707 0x16, 0x00, 0x1c, 0x02, /* vact */
708 0x33, 0x02, /* field_chg */
709 0x49, 0x02, /* vact_st2 */
710 0x00, 0x00, /* vact_st3 */
711 0x00, 0x00, /* vact_st4 */
712 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
713 0x01, 0x00, 0x33, 0x02, /* field top/bot */
714 0x00, /* 3d FP */
715 },
716 };
717
718 static const struct hdmi_preset_conf hdmi_conf_1080p50 = {
719 .core = {
720 .h_blank = {0xd0, 0x02},
721 .v2_blank = {0x65, 0x04},
722 .v1_blank = {0x2d, 0x00},
723 .v_line = {0x65, 0x04},
724 .h_line = {0x50, 0x0a},
725 .hsync_pol = {0x00},
726 .vsync_pol = {0x00},
727 .int_pro_mode = {0x00},
728 .v_blank_f0 = {0xff, 0xff},
729 .v_blank_f1 = {0xff, 0xff},
730 .h_sync_start = {0x0e, 0x02},
731 .h_sync_end = {0x3a, 0x02},
732 .v_sync_line_bef_2 = {0x09, 0x00},
733 .v_sync_line_bef_1 = {0x04, 0x00},
734 .v_sync_line_aft_2 = {0xff, 0xff},
735 .v_sync_line_aft_1 = {0xff, 0xff},
736 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
737 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
738 .v_blank_f2 = {0xff, 0xff},
739 .v_blank_f3 = {0xff, 0xff},
740 .v_blank_f4 = {0xff, 0xff},
741 .v_blank_f5 = {0xff, 0xff},
742 .v_sync_line_aft_3 = {0xff, 0xff},
743 .v_sync_line_aft_4 = {0xff, 0xff},
744 .v_sync_line_aft_5 = {0xff, 0xff},
745 .v_sync_line_aft_6 = {0xff, 0xff},
746 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
747 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
748 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
749 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
750 .vact_space_1 = {0xff, 0xff},
751 .vact_space_2 = {0xff, 0xff},
752 .vact_space_3 = {0xff, 0xff},
753 .vact_space_4 = {0xff, 0xff},
754 .vact_space_5 = {0xff, 0xff},
755 .vact_space_6 = {0xff, 0xff},
756 /* other don't care */
757 },
758 .tg = {
759 0x00, /* cmd */
760 0x50, 0x0a, /* h_fsz */
761 0xd0, 0x02, 0x80, 0x07, /* hact */
762 0x65, 0x04, /* v_fsz */
763 0x01, 0x00, 0x33, 0x02, /* vsync */
764 0x2d, 0x00, 0x38, 0x04, /* vact */
765 0x33, 0x02, /* field_chg */
766 0x48, 0x02, /* vact_st2 */
767 0x00, 0x00, /* vact_st3 */
768 0x00, 0x00, /* vact_st4 */
769 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
770 0x01, 0x00, 0x33, 0x02, /* field top/bot */
771 0x00, /* 3d FP */
772 },
773 };
774
775 static const struct hdmi_preset_conf hdmi_conf_1080p60 = {
776 .core = {
777 .h_blank = {0x18, 0x01},
778 .v2_blank = {0x65, 0x04},
779 .v1_blank = {0x2d, 0x00},
780 .v_line = {0x65, 0x04},
781 .h_line = {0x98, 0x08},
782 .hsync_pol = {0x00},
783 .vsync_pol = {0x00},
784 .int_pro_mode = {0x00},
785 .v_blank_f0 = {0xff, 0xff},
786 .v_blank_f1 = {0xff, 0xff},
787 .h_sync_start = {0x56, 0x00},
788 .h_sync_end = {0x82, 0x00},
789 .v_sync_line_bef_2 = {0x09, 0x00},
790 .v_sync_line_bef_1 = {0x04, 0x00},
791 .v_sync_line_aft_2 = {0xff, 0xff},
792 .v_sync_line_aft_1 = {0xff, 0xff},
793 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
794 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
795 .v_blank_f2 = {0xff, 0xff},
796 .v_blank_f3 = {0xff, 0xff},
797 .v_blank_f4 = {0xff, 0xff},
798 .v_blank_f5 = {0xff, 0xff},
799 .v_sync_line_aft_3 = {0xff, 0xff},
800 .v_sync_line_aft_4 = {0xff, 0xff},
801 .v_sync_line_aft_5 = {0xff, 0xff},
802 .v_sync_line_aft_6 = {0xff, 0xff},
803 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
804 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
805 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
806 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
807 /* other don't care */
808 },
809 .tg = {
810 0x00, /* cmd */
811 0x98, 0x08, /* h_fsz */
812 0x18, 0x01, 0x80, 0x07, /* hact */
813 0x65, 0x04, /* v_fsz */
814 0x01, 0x00, 0x33, 0x02, /* vsync */
815 0x2d, 0x00, 0x38, 0x04, /* vact */
816 0x33, 0x02, /* field_chg */
817 0x48, 0x02, /* vact_st2 */
818 0x00, 0x00, /* vact_st3 */
819 0x00, 0x00, /* vact_st4 */
820 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
821 0x01, 0x00, 0x33, 0x02, /* field top/bot */
822 0x00, /* 3d FP */
823 },
824 };
825
826 static const struct hdmi_conf hdmi_confs[] = {
827 { 720, 480, 60, false, hdmiphy_conf27_027, &hdmi_conf_480p60 },
828 { 1280, 720, 50, false, hdmiphy_conf74_25, &hdmi_conf_720p50 },
829 { 1280, 720, 60, false, hdmiphy_conf74_25, &hdmi_conf_720p60 },
830 { 1920, 1080, 50, true, hdmiphy_conf74_25, &hdmi_conf_1080i50 },
831 { 1920, 1080, 60, true, hdmiphy_conf74_25, &hdmi_conf_1080i60 },
832 { 1920, 1080, 50, false, hdmiphy_conf148_5, &hdmi_conf_1080p50 },
833 { 1920, 1080, 60, false, hdmiphy_conf148_5, &hdmi_conf_1080p60 },
834 };
835
836
837 static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
838 {
839 return readl(hdata->regs + reg_id);
840 }
841
842 static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
843 u32 reg_id, u8 value)
844 {
845 writeb(value, hdata->regs + reg_id);
846 }
847
848 static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
849 u32 reg_id, u32 value, u32 mask)
850 {
851 u32 old = readl(hdata->regs + reg_id);
852 value = (value & mask) | (old & ~mask);
853 writel(value, hdata->regs + reg_id);
854 }
855
856 static void hdmi_v13_regs_dump(struct hdmi_context *hdata, char *prefix)
857 {
858 #define DUMPREG(reg_id) \
859 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
860 readl(hdata->regs + reg_id))
861 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
862 DUMPREG(HDMI_INTC_FLAG);
863 DUMPREG(HDMI_INTC_CON);
864 DUMPREG(HDMI_HPD_STATUS);
865 DUMPREG(HDMI_V13_PHY_RSTOUT);
866 DUMPREG(HDMI_V13_PHY_VPLL);
867 DUMPREG(HDMI_V13_PHY_CMU);
868 DUMPREG(HDMI_V13_CORE_RSTOUT);
869
870 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
871 DUMPREG(HDMI_CON_0);
872 DUMPREG(HDMI_CON_1);
873 DUMPREG(HDMI_CON_2);
874 DUMPREG(HDMI_SYS_STATUS);
875 DUMPREG(HDMI_V13_PHY_STATUS);
876 DUMPREG(HDMI_STATUS_EN);
877 DUMPREG(HDMI_HPD);
878 DUMPREG(HDMI_MODE_SEL);
879 DUMPREG(HDMI_V13_HPD_GEN);
880 DUMPREG(HDMI_V13_DC_CONTROL);
881 DUMPREG(HDMI_V13_VIDEO_PATTERN_GEN);
882
883 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
884 DUMPREG(HDMI_H_BLANK_0);
885 DUMPREG(HDMI_H_BLANK_1);
886 DUMPREG(HDMI_V13_V_BLANK_0);
887 DUMPREG(HDMI_V13_V_BLANK_1);
888 DUMPREG(HDMI_V13_V_BLANK_2);
889 DUMPREG(HDMI_V13_H_V_LINE_0);
890 DUMPREG(HDMI_V13_H_V_LINE_1);
891 DUMPREG(HDMI_V13_H_V_LINE_2);
892 DUMPREG(HDMI_VSYNC_POL);
893 DUMPREG(HDMI_INT_PRO_MODE);
894 DUMPREG(HDMI_V13_V_BLANK_F_0);
895 DUMPREG(HDMI_V13_V_BLANK_F_1);
896 DUMPREG(HDMI_V13_V_BLANK_F_2);
897 DUMPREG(HDMI_V13_H_SYNC_GEN_0);
898 DUMPREG(HDMI_V13_H_SYNC_GEN_1);
899 DUMPREG(HDMI_V13_H_SYNC_GEN_2);
900 DUMPREG(HDMI_V13_V_SYNC_GEN_1_0);
901 DUMPREG(HDMI_V13_V_SYNC_GEN_1_1);
902 DUMPREG(HDMI_V13_V_SYNC_GEN_1_2);
903 DUMPREG(HDMI_V13_V_SYNC_GEN_2_0);
904 DUMPREG(HDMI_V13_V_SYNC_GEN_2_1);
905 DUMPREG(HDMI_V13_V_SYNC_GEN_2_2);
906 DUMPREG(HDMI_V13_V_SYNC_GEN_3_0);
907 DUMPREG(HDMI_V13_V_SYNC_GEN_3_1);
908 DUMPREG(HDMI_V13_V_SYNC_GEN_3_2);
909
910 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
911 DUMPREG(HDMI_TG_CMD);
912 DUMPREG(HDMI_TG_H_FSZ_L);
913 DUMPREG(HDMI_TG_H_FSZ_H);
914 DUMPREG(HDMI_TG_HACT_ST_L);
915 DUMPREG(HDMI_TG_HACT_ST_H);
916 DUMPREG(HDMI_TG_HACT_SZ_L);
917 DUMPREG(HDMI_TG_HACT_SZ_H);
918 DUMPREG(HDMI_TG_V_FSZ_L);
919 DUMPREG(HDMI_TG_V_FSZ_H);
920 DUMPREG(HDMI_TG_VSYNC_L);
921 DUMPREG(HDMI_TG_VSYNC_H);
922 DUMPREG(HDMI_TG_VSYNC2_L);
923 DUMPREG(HDMI_TG_VSYNC2_H);
924 DUMPREG(HDMI_TG_VACT_ST_L);
925 DUMPREG(HDMI_TG_VACT_ST_H);
926 DUMPREG(HDMI_TG_VACT_SZ_L);
927 DUMPREG(HDMI_TG_VACT_SZ_H);
928 DUMPREG(HDMI_TG_FIELD_CHG_L);
929 DUMPREG(HDMI_TG_FIELD_CHG_H);
930 DUMPREG(HDMI_TG_VACT_ST2_L);
931 DUMPREG(HDMI_TG_VACT_ST2_H);
932 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
933 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
934 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
935 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
936 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
937 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
938 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
939 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
940 #undef DUMPREG
941 }
942
943 static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix)
944 {
945 int i;
946
947 #define DUMPREG(reg_id) \
948 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
949 readl(hdata->regs + reg_id))
950
951 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
952 DUMPREG(HDMI_INTC_CON);
953 DUMPREG(HDMI_INTC_FLAG);
954 DUMPREG(HDMI_HPD_STATUS);
955 DUMPREG(HDMI_INTC_CON_1);
956 DUMPREG(HDMI_INTC_FLAG_1);
957 DUMPREG(HDMI_PHY_STATUS_0);
958 DUMPREG(HDMI_PHY_STATUS_PLL);
959 DUMPREG(HDMI_PHY_CON_0);
960 DUMPREG(HDMI_PHY_RSTOUT);
961 DUMPREG(HDMI_PHY_VPLL);
962 DUMPREG(HDMI_PHY_CMU);
963 DUMPREG(HDMI_CORE_RSTOUT);
964
965 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
966 DUMPREG(HDMI_CON_0);
967 DUMPREG(HDMI_CON_1);
968 DUMPREG(HDMI_CON_2);
969 DUMPREG(HDMI_SYS_STATUS);
970 DUMPREG(HDMI_PHY_STATUS_0);
971 DUMPREG(HDMI_STATUS_EN);
972 DUMPREG(HDMI_HPD);
973 DUMPREG(HDMI_MODE_SEL);
974 DUMPREG(HDMI_ENC_EN);
975 DUMPREG(HDMI_DC_CONTROL);
976 DUMPREG(HDMI_VIDEO_PATTERN_GEN);
977
978 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
979 DUMPREG(HDMI_H_BLANK_0);
980 DUMPREG(HDMI_H_BLANK_1);
981 DUMPREG(HDMI_V2_BLANK_0);
982 DUMPREG(HDMI_V2_BLANK_1);
983 DUMPREG(HDMI_V1_BLANK_0);
984 DUMPREG(HDMI_V1_BLANK_1);
985 DUMPREG(HDMI_V_LINE_0);
986 DUMPREG(HDMI_V_LINE_1);
987 DUMPREG(HDMI_H_LINE_0);
988 DUMPREG(HDMI_H_LINE_1);
989 DUMPREG(HDMI_HSYNC_POL);
990
991 DUMPREG(HDMI_VSYNC_POL);
992 DUMPREG(HDMI_INT_PRO_MODE);
993 DUMPREG(HDMI_V_BLANK_F0_0);
994 DUMPREG(HDMI_V_BLANK_F0_1);
995 DUMPREG(HDMI_V_BLANK_F1_0);
996 DUMPREG(HDMI_V_BLANK_F1_1);
997
998 DUMPREG(HDMI_H_SYNC_START_0);
999 DUMPREG(HDMI_H_SYNC_START_1);
1000 DUMPREG(HDMI_H_SYNC_END_0);
1001 DUMPREG(HDMI_H_SYNC_END_1);
1002
1003 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_0);
1004 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_1);
1005 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_0);
1006 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_1);
1007
1008 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_0);
1009 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_1);
1010 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_0);
1011 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_1);
1012
1013 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_0);
1014 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_1);
1015 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_0);
1016 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_1);
1017
1018 DUMPREG(HDMI_V_BLANK_F2_0);
1019 DUMPREG(HDMI_V_BLANK_F2_1);
1020 DUMPREG(HDMI_V_BLANK_F3_0);
1021 DUMPREG(HDMI_V_BLANK_F3_1);
1022 DUMPREG(HDMI_V_BLANK_F4_0);
1023 DUMPREG(HDMI_V_BLANK_F4_1);
1024 DUMPREG(HDMI_V_BLANK_F5_0);
1025 DUMPREG(HDMI_V_BLANK_F5_1);
1026
1027 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_0);
1028 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_1);
1029 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_0);
1030 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_1);
1031 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_0);
1032 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_1);
1033 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_0);
1034 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_1);
1035
1036 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_0);
1037 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_1);
1038 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_0);
1039 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_1);
1040 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_0);
1041 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_1);
1042 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_0);
1043 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_1);
1044
1045 DUMPREG(HDMI_VACT_SPACE_1_0);
1046 DUMPREG(HDMI_VACT_SPACE_1_1);
1047 DUMPREG(HDMI_VACT_SPACE_2_0);
1048 DUMPREG(HDMI_VACT_SPACE_2_1);
1049 DUMPREG(HDMI_VACT_SPACE_3_0);
1050 DUMPREG(HDMI_VACT_SPACE_3_1);
1051 DUMPREG(HDMI_VACT_SPACE_4_0);
1052 DUMPREG(HDMI_VACT_SPACE_4_1);
1053 DUMPREG(HDMI_VACT_SPACE_5_0);
1054 DUMPREG(HDMI_VACT_SPACE_5_1);
1055 DUMPREG(HDMI_VACT_SPACE_6_0);
1056 DUMPREG(HDMI_VACT_SPACE_6_1);
1057
1058 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
1059 DUMPREG(HDMI_TG_CMD);
1060 DUMPREG(HDMI_TG_H_FSZ_L);
1061 DUMPREG(HDMI_TG_H_FSZ_H);
1062 DUMPREG(HDMI_TG_HACT_ST_L);
1063 DUMPREG(HDMI_TG_HACT_ST_H);
1064 DUMPREG(HDMI_TG_HACT_SZ_L);
1065 DUMPREG(HDMI_TG_HACT_SZ_H);
1066 DUMPREG(HDMI_TG_V_FSZ_L);
1067 DUMPREG(HDMI_TG_V_FSZ_H);
1068 DUMPREG(HDMI_TG_VSYNC_L);
1069 DUMPREG(HDMI_TG_VSYNC_H);
1070 DUMPREG(HDMI_TG_VSYNC2_L);
1071 DUMPREG(HDMI_TG_VSYNC2_H);
1072 DUMPREG(HDMI_TG_VACT_ST_L);
1073 DUMPREG(HDMI_TG_VACT_ST_H);
1074 DUMPREG(HDMI_TG_VACT_SZ_L);
1075 DUMPREG(HDMI_TG_VACT_SZ_H);
1076 DUMPREG(HDMI_TG_FIELD_CHG_L);
1077 DUMPREG(HDMI_TG_FIELD_CHG_H);
1078 DUMPREG(HDMI_TG_VACT_ST2_L);
1079 DUMPREG(HDMI_TG_VACT_ST2_H);
1080 DUMPREG(HDMI_TG_VACT_ST3_L);
1081 DUMPREG(HDMI_TG_VACT_ST3_H);
1082 DUMPREG(HDMI_TG_VACT_ST4_L);
1083 DUMPREG(HDMI_TG_VACT_ST4_H);
1084 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
1085 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
1086 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
1087 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
1088 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
1089 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
1090 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
1091 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
1092 DUMPREG(HDMI_TG_3D);
1093
1094 DRM_DEBUG_KMS("%s: ---- PACKET REGISTERS ----\n", prefix);
1095 DUMPREG(HDMI_AVI_CON);
1096 DUMPREG(HDMI_AVI_HEADER0);
1097 DUMPREG(HDMI_AVI_HEADER1);
1098 DUMPREG(HDMI_AVI_HEADER2);
1099 DUMPREG(HDMI_AVI_CHECK_SUM);
1100 DUMPREG(HDMI_VSI_CON);
1101 DUMPREG(HDMI_VSI_HEADER0);
1102 DUMPREG(HDMI_VSI_HEADER1);
1103 DUMPREG(HDMI_VSI_HEADER2);
1104 for (i = 0; i < 7; ++i)
1105 DUMPREG(HDMI_VSI_DATA(i));
1106
1107 #undef DUMPREG
1108 }
1109
1110 static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix)
1111 {
1112 if (hdata->is_v13)
1113 hdmi_v13_regs_dump(hdata, prefix);
1114 else
1115 hdmi_v14_regs_dump(hdata, prefix);
1116 }
1117
1118 static int hdmi_v13_conf_index(struct drm_display_mode *mode)
1119 {
1120 int i;
1121
1122 for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i)
1123 if (hdmi_v13_confs[i].width == mode->hdisplay &&
1124 hdmi_v13_confs[i].height == mode->vdisplay &&
1125 hdmi_v13_confs[i].vrefresh == mode->vrefresh &&
1126 hdmi_v13_confs[i].interlace ==
1127 ((mode->flags & DRM_MODE_FLAG_INTERLACE) ?
1128 true : false))
1129 return i;
1130
1131 return -EINVAL;
1132 }
1133
1134 static int hdmi_v14_conf_index(struct drm_display_mode *mode)
1135 {
1136 int i;
1137
1138 for (i = 0; i < ARRAY_SIZE(hdmi_confs); ++i)
1139 if (hdmi_confs[i].width == mode->hdisplay &&
1140 hdmi_confs[i].height == mode->vdisplay &&
1141 hdmi_confs[i].vrefresh == mode->vrefresh &&
1142 hdmi_confs[i].interlace ==
1143 ((mode->flags & DRM_MODE_FLAG_INTERLACE) ?
1144 true : false))
1145 return i;
1146
1147 return -EINVAL;
1148 }
1149
1150 static int hdmi_conf_index(struct hdmi_context *hdata,
1151 struct drm_display_mode *mode)
1152 {
1153 if (hdata->is_v13)
1154 return hdmi_v13_conf_index(mode);
1155
1156 return hdmi_v14_conf_index(mode);
1157 }
1158
1159 static bool hdmi_is_connected(void *ctx)
1160 {
1161 struct hdmi_context *hdata = (struct hdmi_context *)ctx;
1162 u32 val = hdmi_reg_read(hdata, HDMI_HPD_STATUS);
1163
1164 if (val)
1165 return true;
1166
1167 return false;
1168 }
1169
1170 static int hdmi_get_edid(void *ctx, struct drm_connector *connector,
1171 u8 *edid, int len)
1172 {
1173 struct edid *raw_edid;
1174 struct hdmi_context *hdata = (struct hdmi_context *)ctx;
1175
1176 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1177
1178 if (!hdata->ddc_port)
1179 return -ENODEV;
1180
1181 raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
1182 if (raw_edid) {
1183 memcpy(edid, raw_edid, min((1 + raw_edid->extensions)
1184 * EDID_LENGTH, len));
1185 DRM_DEBUG_KMS("width[%d] x height[%d]\n",
1186 raw_edid->width_cm, raw_edid->height_cm);
1187 } else {
1188 return -ENODEV;
1189 }
1190
1191 return 0;
1192 }
1193
1194 static int hdmi_v13_check_timing(struct fb_videomode *check_timing)
1195 {
1196 int i;
1197
1198 DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
1199 check_timing->xres, check_timing->yres,
1200 check_timing->refresh, (check_timing->vmode &
1201 FB_VMODE_INTERLACED) ? true : false);
1202
1203 for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i)
1204 if (hdmi_v13_confs[i].width == check_timing->xres &&
1205 hdmi_v13_confs[i].height == check_timing->yres &&
1206 hdmi_v13_confs[i].vrefresh == check_timing->refresh &&
1207 hdmi_v13_confs[i].interlace ==
1208 ((check_timing->vmode & FB_VMODE_INTERLACED) ?
1209 true : false))
1210 return 0;
1211
1212 /* TODO */
1213
1214 return -EINVAL;
1215 }
1216
1217 static int hdmi_v14_check_timing(struct fb_videomode *check_timing)
1218 {
1219 int i;
1220
1221 DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
1222 check_timing->xres, check_timing->yres,
1223 check_timing->refresh, (check_timing->vmode &
1224 FB_VMODE_INTERLACED) ? true : false);
1225
1226 for (i = 0; i < ARRAY_SIZE(hdmi_confs); i++)
1227 if (hdmi_confs[i].width == check_timing->xres &&
1228 hdmi_confs[i].height == check_timing->yres &&
1229 hdmi_confs[i].vrefresh == check_timing->refresh &&
1230 hdmi_confs[i].interlace ==
1231 ((check_timing->vmode & FB_VMODE_INTERLACED) ?
1232 true : false))
1233 return 0;
1234
1235 /* TODO */
1236
1237 return -EINVAL;
1238 }
1239
1240 static int hdmi_check_timing(void *ctx, void *timing)
1241 {
1242 struct hdmi_context *hdata = (struct hdmi_context *)ctx;
1243 struct fb_videomode *check_timing = timing;
1244
1245 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1246
1247 DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", check_timing->xres,
1248 check_timing->yres, check_timing->refresh,
1249 check_timing->vmode);
1250
1251 if (hdata->is_v13)
1252 return hdmi_v13_check_timing(check_timing);
1253 else
1254 return hdmi_v14_check_timing(check_timing);
1255 }
1256
1257 static int hdmi_display_power_on(void *ctx, int mode)
1258 {
1259 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1260
1261 switch (mode) {
1262 case DRM_MODE_DPMS_ON:
1263 DRM_DEBUG_KMS("hdmi [on]\n");
1264 break;
1265 case DRM_MODE_DPMS_STANDBY:
1266 break;
1267 case DRM_MODE_DPMS_SUSPEND:
1268 break;
1269 case DRM_MODE_DPMS_OFF:
1270 DRM_DEBUG_KMS("hdmi [off]\n");
1271 break;
1272 default:
1273 break;
1274 }
1275
1276 return 0;
1277 }
1278
1279 static struct exynos_hdmi_display_ops display_ops = {
1280 .is_connected = hdmi_is_connected,
1281 .get_edid = hdmi_get_edid,
1282 .check_timing = hdmi_check_timing,
1283 .power_on = hdmi_display_power_on,
1284 };
1285
1286 static void hdmi_conf_reset(struct hdmi_context *hdata)
1287 {
1288 u32 reg;
1289
1290 /* disable hpd handle for drm */
1291 hdata->hpd_handle = false;
1292
1293 if (hdata->is_v13)
1294 reg = HDMI_V13_CORE_RSTOUT;
1295 else
1296 reg = HDMI_CORE_RSTOUT;
1297
1298 /* resetting HDMI core */
1299 hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT);
1300 mdelay(10);
1301 hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT);
1302 mdelay(10);
1303
1304 /* enable hpd handle for drm */
1305 hdata->hpd_handle = true;
1306 }
1307
1308 static void hdmi_conf_init(struct hdmi_context *hdata)
1309 {
1310 /* disable hpd handle for drm */
1311 hdata->hpd_handle = false;
1312
1313 /* enable HPD interrupts */
1314 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1315 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
1316 mdelay(10);
1317 hdmi_reg_writemask(hdata, HDMI_INTC_CON, ~0, HDMI_INTC_EN_GLOBAL |
1318 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
1319
1320 /* choose HDMI mode */
1321 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1322 HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
1323 /* disable bluescreen */
1324 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
1325
1326 if (hdata->is_v13) {
1327 /* choose bluescreen (fecal) color */
1328 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1329 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1330 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1331
1332 /* enable AVI packet every vsync, fixes purple line problem */
1333 hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1334 /* force RGB, look to CEA-861-D, table 7 for more detail */
1335 hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1336 hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1337
1338 hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1339 hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1340 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1341 } else {
1342 /* enable AVI packet every vsync, fixes purple line problem */
1343 hdmi_reg_writeb(hdata, HDMI_AVI_CON, 0x02);
1344 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 2 << 5);
1345 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1346 }
1347
1348 /* enable hpd handle for drm */
1349 hdata->hpd_handle = true;
1350 }
1351
1352 static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
1353 {
1354 const struct hdmi_v13_preset_conf *conf =
1355 hdmi_v13_confs[hdata->cur_conf].conf;
1356 const struct hdmi_v13_core_regs *core = &conf->core;
1357 const struct hdmi_v13_tg_regs *tg = &conf->tg;
1358 int tries;
1359
1360 /* setting core registers */
1361 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1362 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
1363 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]);
1364 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]);
1365 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]);
1366 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]);
1367 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]);
1368 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]);
1369 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1370 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
1371 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]);
1372 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]);
1373 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]);
1374 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]);
1375 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]);
1376 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]);
1377 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
1378 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
1379 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
1380 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
1381 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
1382 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
1383 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
1384 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
1385 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
1386 /* Timing generator registers */
1387 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
1388 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
1389 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
1390 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
1391 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
1392 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
1393 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
1394 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
1395 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
1396 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
1397 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
1398 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
1399 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
1400 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
1401 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
1402 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
1403 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
1404 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
1405 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
1406 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
1407 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
1408 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
1409 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
1410 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
1411 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
1412 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
1413 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
1414 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
1415
1416 /* waiting for HDMIPHY's PLL to get to steady state */
1417 for (tries = 100; tries; --tries) {
1418 u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
1419 if (val & HDMI_PHY_STATUS_READY)
1420 break;
1421 mdelay(1);
1422 }
1423 /* steady state not achieved */
1424 if (tries == 0) {
1425 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1426 hdmi_regs_dump(hdata, "timing apply");
1427 }
1428
1429 clk_disable(hdata->res.sclk_hdmi);
1430 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
1431 clk_enable(hdata->res.sclk_hdmi);
1432
1433 /* enable HDMI and timing generator */
1434 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1435 if (core->int_pro_mode[0])
1436 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1437 HDMI_FIELD_EN);
1438 else
1439 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1440 }
1441
1442 static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
1443 {
1444 const struct hdmi_preset_conf *conf = hdmi_confs[hdata->cur_conf].conf;
1445 const struct hdmi_core_regs *core = &conf->core;
1446 const struct hdmi_tg_regs *tg = &conf->tg;
1447 int tries;
1448
1449 /* setting core registers */
1450 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1451 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
1452 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_0, core->v2_blank[0]);
1453 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_1, core->v2_blank[1]);
1454 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_0, core->v1_blank[0]);
1455 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_1, core->v1_blank[1]);
1456 hdmi_reg_writeb(hdata, HDMI_V_LINE_0, core->v_line[0]);
1457 hdmi_reg_writeb(hdata, HDMI_V_LINE_1, core->v_line[1]);
1458 hdmi_reg_writeb(hdata, HDMI_H_LINE_0, core->h_line[0]);
1459 hdmi_reg_writeb(hdata, HDMI_H_LINE_1, core->h_line[1]);
1460 hdmi_reg_writeb(hdata, HDMI_HSYNC_POL, core->hsync_pol[0]);
1461 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1462 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
1463 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_0, core->v_blank_f0[0]);
1464 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_1, core->v_blank_f0[1]);
1465 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_0, core->v_blank_f1[0]);
1466 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_1, core->v_blank_f1[1]);
1467 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_0, core->h_sync_start[0]);
1468 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_1, core->h_sync_start[1]);
1469 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_0, core->h_sync_end[0]);
1470 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_1, core->h_sync_end[1]);
1471 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_0,
1472 core->v_sync_line_bef_2[0]);
1473 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_1,
1474 core->v_sync_line_bef_2[1]);
1475 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_0,
1476 core->v_sync_line_bef_1[0]);
1477 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_1,
1478 core->v_sync_line_bef_1[1]);
1479 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_0,
1480 core->v_sync_line_aft_2[0]);
1481 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_1,
1482 core->v_sync_line_aft_2[1]);
1483 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_0,
1484 core->v_sync_line_aft_1[0]);
1485 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_1,
1486 core->v_sync_line_aft_1[1]);
1487 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0,
1488 core->v_sync_line_aft_pxl_2[0]);
1489 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_1,
1490 core->v_sync_line_aft_pxl_2[1]);
1491 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0,
1492 core->v_sync_line_aft_pxl_1[0]);
1493 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_1,
1494 core->v_sync_line_aft_pxl_1[1]);
1495 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_0, core->v_blank_f2[0]);
1496 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_1, core->v_blank_f2[1]);
1497 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_0, core->v_blank_f3[0]);
1498 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_1, core->v_blank_f3[1]);
1499 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_0, core->v_blank_f4[0]);
1500 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_1, core->v_blank_f4[1]);
1501 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_0, core->v_blank_f5[0]);
1502 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_1, core->v_blank_f5[1]);
1503 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_0,
1504 core->v_sync_line_aft_3[0]);
1505 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_1,
1506 core->v_sync_line_aft_3[1]);
1507 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_0,
1508 core->v_sync_line_aft_4[0]);
1509 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_1,
1510 core->v_sync_line_aft_4[1]);
1511 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_0,
1512 core->v_sync_line_aft_5[0]);
1513 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_1,
1514 core->v_sync_line_aft_5[1]);
1515 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_0,
1516 core->v_sync_line_aft_6[0]);
1517 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_1,
1518 core->v_sync_line_aft_6[1]);
1519 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0,
1520 core->v_sync_line_aft_pxl_3[0]);
1521 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_1,
1522 core->v_sync_line_aft_pxl_3[1]);
1523 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0,
1524 core->v_sync_line_aft_pxl_4[0]);
1525 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_1,
1526 core->v_sync_line_aft_pxl_4[1]);
1527 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0,
1528 core->v_sync_line_aft_pxl_5[0]);
1529 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_1,
1530 core->v_sync_line_aft_pxl_5[1]);
1531 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0,
1532 core->v_sync_line_aft_pxl_6[0]);
1533 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_1,
1534 core->v_sync_line_aft_pxl_6[1]);
1535 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_0, core->vact_space_1[0]);
1536 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_1, core->vact_space_1[1]);
1537 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_0, core->vact_space_2[0]);
1538 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_1, core->vact_space_2[1]);
1539 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_0, core->vact_space_3[0]);
1540 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_1, core->vact_space_3[1]);
1541 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_0, core->vact_space_4[0]);
1542 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_1, core->vact_space_4[1]);
1543 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_0, core->vact_space_5[0]);
1544 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_1, core->vact_space_5[1]);
1545 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_0, core->vact_space_6[0]);
1546 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]);
1547
1548 /* Timing generator registers */
1549 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
1550 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
1551 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
1552 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
1553 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
1554 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
1555 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
1556 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
1557 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
1558 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
1559 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
1560 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
1561 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
1562 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
1563 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
1564 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
1565 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
1566 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
1567 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
1568 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
1569 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3_l);
1570 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3_h);
1571 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4_l);
1572 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4_h);
1573 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
1574 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
1575 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
1576 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
1577 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
1578 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
1579 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
1580 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
1581 hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d);
1582
1583 /* waiting for HDMIPHY's PLL to get to steady state */
1584 for (tries = 100; tries; --tries) {
1585 u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
1586 if (val & HDMI_PHY_STATUS_READY)
1587 break;
1588 mdelay(1);
1589 }
1590 /* steady state not achieved */
1591 if (tries == 0) {
1592 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1593 hdmi_regs_dump(hdata, "timing apply");
1594 }
1595
1596 clk_disable(hdata->res.sclk_hdmi);
1597 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
1598 clk_enable(hdata->res.sclk_hdmi);
1599
1600 /* enable HDMI and timing generator */
1601 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1602 if (core->int_pro_mode[0])
1603 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1604 HDMI_FIELD_EN);
1605 else
1606 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1607 }
1608
1609 static void hdmi_timing_apply(struct hdmi_context *hdata)
1610 {
1611 if (hdata->is_v13)
1612 hdmi_v13_timing_apply(hdata);
1613 else
1614 hdmi_v14_timing_apply(hdata);
1615 }
1616
1617 static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1618 {
1619 u8 buffer[2];
1620 u32 reg;
1621
1622 clk_disable(hdata->res.sclk_hdmi);
1623 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_pixel);
1624 clk_enable(hdata->res.sclk_hdmi);
1625
1626 /* operation mode */
1627 buffer[0] = 0x1f;
1628 buffer[1] = 0x00;
1629
1630 if (hdata->hdmiphy_port)
1631 i2c_master_send(hdata->hdmiphy_port, buffer, 2);
1632
1633 if (hdata->is_v13)
1634 reg = HDMI_V13_PHY_RSTOUT;
1635 else
1636 reg = HDMI_PHY_RSTOUT;
1637
1638 /* reset hdmiphy */
1639 hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
1640 mdelay(10);
1641 hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
1642 mdelay(10);
1643 }
1644
1645 static void hdmiphy_conf_apply(struct hdmi_context *hdata)
1646 {
1647 const u8 *hdmiphy_data;
1648 u8 buffer[32];
1649 u8 operation[2];
1650 u8 read_buffer[32] = {0, };
1651 int ret;
1652 int i;
1653
1654 if (!hdata->hdmiphy_port) {
1655 DRM_ERROR("hdmiphy is not attached\n");
1656 return;
1657 }
1658
1659 /* pixel clock */
1660 if (hdata->is_v13)
1661 hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data;
1662 else
1663 hdmiphy_data = hdmi_confs[hdata->cur_conf].hdmiphy_data;
1664
1665 memcpy(buffer, hdmiphy_data, 32);
1666 ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32);
1667 if (ret != 32) {
1668 DRM_ERROR("failed to configure HDMIPHY via I2C\n");
1669 return;
1670 }
1671
1672 mdelay(10);
1673
1674 /* operation mode */
1675 operation[0] = 0x1f;
1676 operation[1] = 0x80;
1677
1678 ret = i2c_master_send(hdata->hdmiphy_port, operation, 2);
1679 if (ret != 2) {
1680 DRM_ERROR("failed to enable hdmiphy\n");
1681 return;
1682 }
1683
1684 ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32);
1685 if (ret < 0) {
1686 DRM_ERROR("failed to read hdmiphy config\n");
1687 return;
1688 }
1689
1690 for (i = 0; i < ret; i++)
1691 DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - "
1692 "recv [0x%02x]\n", i, buffer[i], read_buffer[i]);
1693 }
1694
1695 static void hdmi_conf_apply(struct hdmi_context *hdata)
1696 {
1697 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1698
1699 hdmiphy_conf_reset(hdata);
1700 hdmiphy_conf_apply(hdata);
1701
1702 hdmi_conf_reset(hdata);
1703 hdmi_conf_init(hdata);
1704
1705 /* setting core registers */
1706 hdmi_timing_apply(hdata);
1707
1708 hdmi_regs_dump(hdata, "start");
1709 }
1710
1711 static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,
1712 struct drm_display_mode *mode,
1713 struct drm_display_mode *adjusted_mode)
1714 {
1715 struct drm_display_mode *m;
1716 struct hdmi_context *hdata = (struct hdmi_context *)ctx;
1717 int index;
1718
1719 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1720
1721 drm_mode_set_crtcinfo(adjusted_mode, 0);
1722
1723 if (hdata->is_v13)
1724 index = hdmi_v13_conf_index(adjusted_mode);
1725 else
1726 index = hdmi_v14_conf_index(adjusted_mode);
1727
1728 /* just return if user desired mode exists. */
1729 if (index >= 0)
1730 return;
1731
1732 /*
1733 * otherwise, find the most suitable mode among modes and change it
1734 * to adjusted_mode.
1735 */
1736 list_for_each_entry(m, &connector->modes, head) {
1737 if (hdata->is_v13)
1738 index = hdmi_v13_conf_index(m);
1739 else
1740 index = hdmi_v14_conf_index(m);
1741
1742 if (index >= 0) {
1743 DRM_INFO("desired mode doesn't exist so\n");
1744 DRM_INFO("use the most suitable mode among modes.\n");
1745 memcpy(adjusted_mode, m, sizeof(*m));
1746 break;
1747 }
1748 }
1749 }
1750
1751 static void hdmi_mode_set(void *ctx, void *mode)
1752 {
1753 struct hdmi_context *hdata = (struct hdmi_context *)ctx;
1754 int conf_idx;
1755
1756 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1757
1758 conf_idx = hdmi_conf_index(hdata, mode);
1759 if (conf_idx >= 0)
1760 hdata->cur_conf = conf_idx;
1761 else
1762 DRM_DEBUG_KMS("not supported mode\n");
1763 }
1764
1765 static void hdmi_get_max_resol(void *ctx, unsigned int *width,
1766 unsigned int *height)
1767 {
1768 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1769
1770 *width = MAX_WIDTH;
1771 *height = MAX_HEIGHT;
1772 }
1773
1774 static void hdmi_commit(void *ctx)
1775 {
1776 struct hdmi_context *hdata = (struct hdmi_context *)ctx;
1777
1778 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1779
1780 hdmi_conf_apply(hdata);
1781
1782 hdata->enabled = true;
1783 }
1784
1785 static void hdmi_disable(void *ctx)
1786 {
1787 struct hdmi_context *hdata = (struct hdmi_context *)ctx;
1788
1789 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1790
1791 if (hdata->enabled) {
1792 hdmiphy_conf_reset(hdata);
1793 hdmi_conf_reset(hdata);
1794 }
1795 }
1796
1797 static struct exynos_hdmi_manager_ops manager_ops = {
1798 .mode_fixup = hdmi_mode_fixup,
1799 .mode_set = hdmi_mode_set,
1800 .get_max_resol = hdmi_get_max_resol,
1801 .commit = hdmi_commit,
1802 .disable = hdmi_disable,
1803 };
1804
1805 /*
1806 * Handle hotplug events outside the interrupt handler proper.
1807 */
1808 static void hdmi_hotplug_func(struct work_struct *work)
1809 {
1810 struct hdmi_context *hdata =
1811 container_of(work, struct hdmi_context, hotplug_work);
1812 struct exynos_drm_hdmi_context *ctx =
1813 (struct exynos_drm_hdmi_context *)hdata->parent_ctx;
1814
1815 drm_helper_hpd_irq_event(ctx->drm_dev);
1816 }
1817
1818 static irqreturn_t hdmi_irq_handler(int irq, void *arg)
1819 {
1820 struct exynos_drm_hdmi_context *ctx = arg;
1821 struct hdmi_context *hdata = (struct hdmi_context *)ctx->ctx;
1822 u32 intc_flag;
1823
1824 intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG);
1825 /* clearing flags for HPD plug/unplug */
1826 if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
1827 DRM_DEBUG_KMS("unplugged, handling:%d\n", hdata->hpd_handle);
1828 hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
1829 HDMI_INTC_FLAG_HPD_UNPLUG);
1830 }
1831 if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
1832 DRM_DEBUG_KMS("plugged, handling:%d\n", hdata->hpd_handle);
1833 hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
1834 HDMI_INTC_FLAG_HPD_PLUG);
1835 }
1836
1837 if (ctx->drm_dev && hdata->hpd_handle)
1838 queue_work(hdata->wq, &hdata->hotplug_work);
1839
1840 return IRQ_HANDLED;
1841 }
1842
1843 static int __devinit hdmi_resources_init(struct hdmi_context *hdata)
1844 {
1845 struct device *dev = hdata->dev;
1846 struct hdmi_resources *res = &hdata->res;
1847 static char *supply[] = {
1848 "hdmi-en",
1849 "vdd",
1850 "vdd_osc",
1851 "vdd_pll",
1852 };
1853 int i, ret;
1854
1855 DRM_DEBUG_KMS("HDMI resource init\n");
1856
1857 memset(res, 0, sizeof *res);
1858
1859 /* get clocks, power */
1860 res->hdmi = clk_get(dev, "hdmi");
1861 if (IS_ERR_OR_NULL(res->hdmi)) {
1862 DRM_ERROR("failed to get clock 'hdmi'\n");
1863 goto fail;
1864 }
1865 res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
1866 if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
1867 DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
1868 goto fail;
1869 }
1870 res->sclk_pixel = clk_get(dev, "sclk_pixel");
1871 if (IS_ERR_OR_NULL(res->sclk_pixel)) {
1872 DRM_ERROR("failed to get clock 'sclk_pixel'\n");
1873 goto fail;
1874 }
1875 res->sclk_hdmiphy = clk_get(dev, "sclk_hdmiphy");
1876 if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) {
1877 DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
1878 goto fail;
1879 }
1880 res->hdmiphy = clk_get(dev, "hdmiphy");
1881 if (IS_ERR_OR_NULL(res->hdmiphy)) {
1882 DRM_ERROR("failed to get clock 'hdmiphy'\n");
1883 goto fail;
1884 }
1885
1886 clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
1887
1888 res->regul_bulk = kzalloc(ARRAY_SIZE(supply) *
1889 sizeof res->regul_bulk[0], GFP_KERNEL);
1890 if (!res->regul_bulk) {
1891 DRM_ERROR("failed to get memory for regulators\n");
1892 goto fail;
1893 }
1894 for (i = 0; i < ARRAY_SIZE(supply); ++i) {
1895 res->regul_bulk[i].supply = supply[i];
1896 res->regul_bulk[i].consumer = NULL;
1897 }
1898 ret = regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
1899 if (ret) {
1900 DRM_ERROR("failed to get regulators\n");
1901 goto fail;
1902 }
1903 res->regul_count = ARRAY_SIZE(supply);
1904
1905 return 0;
1906 fail:
1907 DRM_ERROR("HDMI resource init - failed\n");
1908 return -ENODEV;
1909 }
1910
1911 static int hdmi_resources_cleanup(struct hdmi_context *hdata)
1912 {
1913 struct hdmi_resources *res = &hdata->res;
1914
1915 regulator_bulk_free(res->regul_count, res->regul_bulk);
1916 /* kfree is NULL-safe */
1917 kfree(res->regul_bulk);
1918 if (!IS_ERR_OR_NULL(res->hdmiphy))
1919 clk_put(res->hdmiphy);
1920 if (!IS_ERR_OR_NULL(res->sclk_hdmiphy))
1921 clk_put(res->sclk_hdmiphy);
1922 if (!IS_ERR_OR_NULL(res->sclk_pixel))
1923 clk_put(res->sclk_pixel);
1924 if (!IS_ERR_OR_NULL(res->sclk_hdmi))
1925 clk_put(res->sclk_hdmi);
1926 if (!IS_ERR_OR_NULL(res->hdmi))
1927 clk_put(res->hdmi);
1928 memset(res, 0, sizeof *res);
1929
1930 return 0;
1931 }
1932
1933 static void hdmi_resource_poweron(struct hdmi_context *hdata)
1934 {
1935 struct hdmi_resources *res = &hdata->res;
1936
1937 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1938
1939 /* turn HDMI power on */
1940 regulator_bulk_enable(res->regul_count, res->regul_bulk);
1941 /* power-on hdmi physical interface */
1942 clk_enable(res->hdmiphy);
1943 /* turn clocks on */
1944 clk_enable(res->hdmi);
1945 clk_enable(res->sclk_hdmi);
1946
1947 hdmiphy_conf_reset(hdata);
1948 hdmi_conf_reset(hdata);
1949 hdmi_conf_init(hdata);
1950 }
1951
1952 static void hdmi_resource_poweroff(struct hdmi_context *hdata)
1953 {
1954 struct hdmi_resources *res = &hdata->res;
1955
1956 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1957
1958 /* turn clocks off */
1959 clk_disable(res->sclk_hdmi);
1960 clk_disable(res->hdmi);
1961 /* power-off hdmiphy */
1962 clk_disable(res->hdmiphy);
1963 /* turn HDMI power off */
1964 regulator_bulk_disable(res->regul_count, res->regul_bulk);
1965 }
1966
1967 static int hdmi_runtime_suspend(struct device *dev)
1968 {
1969 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
1970
1971 DRM_DEBUG_KMS("%s\n", __func__);
1972
1973 hdmi_resource_poweroff((struct hdmi_context *)ctx->ctx);
1974
1975 return 0;
1976 }
1977
1978 static int hdmi_runtime_resume(struct device *dev)
1979 {
1980 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
1981
1982 DRM_DEBUG_KMS("%s\n", __func__);
1983
1984 hdmi_resource_poweron((struct hdmi_context *)ctx->ctx);
1985
1986 return 0;
1987 }
1988
1989 static const struct dev_pm_ops hdmi_pm_ops = {
1990 .runtime_suspend = hdmi_runtime_suspend,
1991 .runtime_resume = hdmi_runtime_resume,
1992 };
1993
1994 static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;
1995
1996 void hdmi_attach_ddc_client(struct i2c_client *ddc)
1997 {
1998 if (ddc)
1999 hdmi_ddc = ddc;
2000 }
2001
2002 void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)
2003 {
2004 if (hdmiphy)
2005 hdmi_hdmiphy = hdmiphy;
2006 }
2007
2008 static int __devinit hdmi_probe(struct platform_device *pdev)
2009 {
2010 struct device *dev = &pdev->dev;
2011 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
2012 struct hdmi_context *hdata;
2013 struct exynos_drm_hdmi_pdata *pdata;
2014 struct resource *res;
2015 int ret;
2016
2017 DRM_DEBUG_KMS("[%d]\n", __LINE__);
2018
2019 pdata = pdev->dev.platform_data;
2020 if (!pdata) {
2021 DRM_ERROR("no platform data specified\n");
2022 return -EINVAL;
2023 }
2024
2025 drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL);
2026 if (!drm_hdmi_ctx) {
2027 DRM_ERROR("failed to allocate common hdmi context.\n");
2028 return -ENOMEM;
2029 }
2030
2031 hdata = kzalloc(sizeof(struct hdmi_context), GFP_KERNEL);
2032 if (!hdata) {
2033 DRM_ERROR("out of memory\n");
2034 kfree(drm_hdmi_ctx);
2035 return -ENOMEM;
2036 }
2037
2038 drm_hdmi_ctx->ctx = (void *)hdata;
2039 hdata->parent_ctx = (void *)drm_hdmi_ctx;
2040
2041 platform_set_drvdata(pdev, drm_hdmi_ctx);
2042
2043 hdata->is_v13 = pdata->is_v13;
2044 hdata->default_win = pdata->default_win;
2045 hdata->default_timing = &pdata->timing;
2046 hdata->default_bpp = pdata->bpp;
2047 hdata->dev = dev;
2048
2049 ret = hdmi_resources_init(hdata);
2050 if (ret) {
2051 ret = -EINVAL;
2052 goto err_data;
2053 }
2054
2055 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2056 if (!res) {
2057 DRM_ERROR("failed to find registers\n");
2058 ret = -ENOENT;
2059 goto err_resource;
2060 }
2061
2062 hdata->regs_res = request_mem_region(res->start, resource_size(res),
2063 dev_name(dev));
2064 if (!hdata->regs_res) {
2065 DRM_ERROR("failed to claim register region\n");
2066 ret = -ENOENT;
2067 goto err_resource;
2068 }
2069
2070 hdata->regs = ioremap(res->start, resource_size(res));
2071 if (!hdata->regs) {
2072 DRM_ERROR("failed to map registers\n");
2073 ret = -ENXIO;
2074 goto err_req_region;
2075 }
2076
2077 /* DDC i2c driver */
2078 if (i2c_add_driver(&ddc_driver)) {
2079 DRM_ERROR("failed to register ddc i2c driver\n");
2080 ret = -ENOENT;
2081 goto err_iomap;
2082 }
2083
2084 hdata->ddc_port = hdmi_ddc;
2085
2086 /* hdmiphy i2c driver */
2087 if (i2c_add_driver(&hdmiphy_driver)) {
2088 DRM_ERROR("failed to register hdmiphy i2c driver\n");
2089 ret = -ENOENT;
2090 goto err_ddc;
2091 }
2092
2093 hdata->hdmiphy_port = hdmi_hdmiphy;
2094
2095 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
2096 if (res == NULL) {
2097 DRM_ERROR("get interrupt resource failed.\n");
2098 ret = -ENXIO;
2099 goto err_hdmiphy;
2100 }
2101
2102 /* create workqueue and hotplug work */
2103 hdata->wq = alloc_workqueue("exynos-drm-hdmi",
2104 WQ_UNBOUND | WQ_NON_REENTRANT, 1);
2105 if (hdata->wq == NULL) {
2106 DRM_ERROR("Failed to create workqueue.\n");
2107 ret = -ENOMEM;
2108 goto err_hdmiphy;
2109 }
2110 INIT_WORK(&hdata->hotplug_work, hdmi_hotplug_func);
2111
2112 /* register hpd interrupt */
2113 ret = request_irq(res->start, hdmi_irq_handler, 0, "drm_hdmi",
2114 drm_hdmi_ctx);
2115 if (ret) {
2116 DRM_ERROR("request interrupt failed.\n");
2117 goto err_workqueue;
2118 }
2119 hdata->irq = res->start;
2120
2121 /* register specific callbacks to common hdmi. */
2122 exynos_drm_display_ops_register(&display_ops);
2123 exynos_drm_manager_ops_register(&manager_ops);
2124
2125 hdmi_resource_poweron(hdata);
2126
2127 return 0;
2128
2129 err_workqueue:
2130 destroy_workqueue(hdata->wq);
2131 err_hdmiphy:
2132 i2c_del_driver(&hdmiphy_driver);
2133 err_ddc:
2134 i2c_del_driver(&ddc_driver);
2135 err_iomap:
2136 iounmap(hdata->regs);
2137 err_req_region:
2138 release_mem_region(hdata->regs_res->start,
2139 resource_size(hdata->regs_res));
2140 err_resource:
2141 hdmi_resources_cleanup(hdata);
2142 err_data:
2143 kfree(hdata);
2144 kfree(drm_hdmi_ctx);
2145 return ret;
2146 }
2147
2148 static int __devexit hdmi_remove(struct platform_device *pdev)
2149 {
2150 struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev);
2151 struct hdmi_context *hdata = (struct hdmi_context *)ctx->ctx;
2152
2153 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2154
2155 hdmi_resource_poweroff(hdata);
2156
2157 disable_irq(hdata->irq);
2158 free_irq(hdata->irq, hdata);
2159
2160 cancel_work_sync(&hdata->hotplug_work);
2161 destroy_workqueue(hdata->wq);
2162
2163 hdmi_resources_cleanup(hdata);
2164
2165 iounmap(hdata->regs);
2166
2167 release_mem_region(hdata->regs_res->start,
2168 resource_size(hdata->regs_res));
2169
2170 /* hdmiphy i2c driver */
2171 i2c_del_driver(&hdmiphy_driver);
2172 /* DDC i2c driver */
2173 i2c_del_driver(&ddc_driver);
2174
2175 kfree(hdata);
2176
2177 return 0;
2178 }
2179
2180 struct platform_driver hdmi_driver = {
2181 .probe = hdmi_probe,
2182 .remove = __devexit_p(hdmi_remove),
2183 .driver = {
2184 .name = "exynos4-hdmi",
2185 .owner = THIS_MODULE,
2186 .pm = &hdmi_pm_ops,
2187 },
2188 };
This page took 0.13008 seconds and 5 git commands to generate.