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