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