drm/exynos: enable dvi mode for dvi monitor
[GitHub/LineageOS/android_kernel_samsung_universal7580.git] / drivers / gpu / drm / exynos / exynos_hdmi.c
CommitLineData
d8408326
SWK
1/*
2 * Copyright (C) 2011 Samsung Electronics Co.Ltd
3 * Authors:
4 * Seung-Woo Kim <sw0312.kim@samsung.com>
5 * Inki Dae <inki.dae@samsung.com>
6 * Joonyoung Shim <jy0922.shim@samsung.com>
7 *
8 * Based on drivers/media/video/s5p-tv/hdmi_drv.c
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 */
16
17#include "drmP.h"
18#include "drm_edid.h"
19#include "drm_crtc_helper.h"
20
21#include "regs-hdmi.h"
22
23#include <linux/kernel.h>
24#include <linux/spinlock.h>
25#include <linux/wait.h>
26#include <linux/i2c.h>
27#include <linux/module.h>
28#include <linux/platform_device.h>
29#include <linux/interrupt.h>
30#include <linux/irq.h>
31#include <linux/delay.h>
32#include <linux/pm_runtime.h>
33#include <linux/clk.h>
34#include <linux/regulator/consumer.h>
35
36#include <drm/exynos_drm.h>
37
38#include "exynos_drm_drv.h"
39#include "exynos_drm_hdmi.h"
40
41#include "exynos_hdmi.h"
42
1de425b0
ID
43#define MAX_WIDTH 1920
44#define MAX_HEIGHT 1080
d8408326
SWK
45#define get_hdmi_context(dev) platform_get_drvdata(to_platform_device(dev))
46
590f418a
JS
47struct hdmi_resources {
48 struct clk *hdmi;
49 struct clk *sclk_hdmi;
50 struct clk *sclk_pixel;
51 struct clk *sclk_hdmiphy;
52 struct clk *hdmiphy;
53 struct regulator_bulk_data *regul_bulk;
54 int regul_count;
55};
56
57struct hdmi_context {
58 struct device *dev;
59 struct drm_device *drm_dev;
cf8fc4f1
JS
60 bool hpd;
61 bool powered;
7ecd34e8 62 bool is_v13;
872d20d6 63 bool dvi_mode;
cf8fc4f1 64 struct mutex hdmi_mutex;
590f418a
JS
65
66 struct resource *regs_res;
67 void __iomem *regs;
cf8fc4f1
JS
68 unsigned int external_irq;
69 unsigned int internal_irq;
590f418a
JS
70
71 struct i2c_client *ddc_port;
72 struct i2c_client *hdmiphy_port;
73
74 /* current hdmiphy conf index */
75 int cur_conf;
76
77 struct hdmi_resources res;
78 void *parent_ctx;
7ecd34e8
JS
79
80 void (*cfg_hpd)(bool external);
81 int (*get_hpd)(void);
590f418a
JS
82};
83
3ecd70b1
JS
84/* HDMI Version 1.3 */
85static const u8 hdmiphy_v13_conf27[32] = {
d8408326
SWK
86 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
3ecd70b1 92static const u8 hdmiphy_v13_conf27_027[32] = {
d8408326
SWK
93 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
3ecd70b1 99static const u8 hdmiphy_v13_conf74_175[32] = {
d8408326
SWK
100 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
3ecd70b1 106static const u8 hdmiphy_v13_conf74_25[32] = {
d8408326
SWK
107 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
3ecd70b1 113static const u8 hdmiphy_v13_conf148_5[32] = {
d8408326
SWK
114 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
3ecd70b1 120struct hdmi_v13_tg_regs {
d8408326
SWK
121 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
3ecd70b1 152struct hdmi_v13_core_regs {
d8408326
SWK
153 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
3ecd70b1
JS
165struct hdmi_v13_preset_conf {
166 struct hdmi_v13_core_regs core;
167 struct hdmi_v13_tg_regs tg;
168};
169
170struct 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;
d8408326
SWK
177};
178
3ecd70b1 179static const struct hdmi_v13_preset_conf hdmi_v13_conf_480p = {
d8408326
SWK
180 .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
3ecd70b1 205static const struct hdmi_v13_preset_conf hdmi_v13_conf_720p60 = {
d8408326
SWK
206 .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
3ecd70b1 233static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i50 = {
d8408326
SWK
234 .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
3ecd70b1 261static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p50 = {
d8408326
SWK
262 .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
3ecd70b1 289static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i60 = {
d8408326
SWK
290 .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
3ecd70b1 317static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p60 = {
d8408326
SWK
318 .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
3ecd70b1
JS
345static 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
d8408326 862static const struct hdmi_conf hdmi_confs[] = {
3ecd70b1
JS
863 { 720, 480, 60, false, hdmiphy_conf27_027, &hdmi_conf_480p60 },
864 { 1280, 720, 50, false, hdmiphy_conf74_25, &hdmi_conf_720p50 },
d8408326 865 { 1280, 720, 60, false, hdmiphy_conf74_25, &hdmi_conf_720p60 },
d8408326 866 { 1920, 1080, 50, true, hdmiphy_conf74_25, &hdmi_conf_1080i50 },
d8408326 867 { 1920, 1080, 60, true, hdmiphy_conf74_25, &hdmi_conf_1080i60 },
3ecd70b1 868 { 1920, 1080, 50, false, hdmiphy_conf148_5, &hdmi_conf_1080p50 },
d8408326
SWK
869 { 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
3ecd70b1 892static void hdmi_v13_regs_dump(struct hdmi_context *hdata, char *prefix)
d8408326
SWK
893{
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);
3ecd70b1
JS
901 DUMPREG(HDMI_V13_PHY_RSTOUT);
902 DUMPREG(HDMI_V13_PHY_VPLL);
903 DUMPREG(HDMI_V13_PHY_CMU);
904 DUMPREG(HDMI_V13_CORE_RSTOUT);
905
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);
911 DUMPREG(HDMI_V13_PHY_STATUS);
912 DUMPREG(HDMI_STATUS_EN);
913 DUMPREG(HDMI_HPD);
914 DUMPREG(HDMI_MODE_SEL);
915 DUMPREG(HDMI_V13_HPD_GEN);
916 DUMPREG(HDMI_V13_DC_CONTROL);
917 DUMPREG(HDMI_V13_VIDEO_PATTERN_GEN);
918
919 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
920 DUMPREG(HDMI_H_BLANK_0);
921 DUMPREG(HDMI_H_BLANK_1);
922 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);
928 DUMPREG(HDMI_VSYNC_POL);
929 DUMPREG(HDMI_INT_PRO_MODE);
930 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);
945
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
979static 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);
d8408326
SWK
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);
3ecd70b1 1006 DUMPREG(HDMI_PHY_STATUS_0);
d8408326
SWK
1007 DUMPREG(HDMI_STATUS_EN);
1008 DUMPREG(HDMI_HPD);
1009 DUMPREG(HDMI_MODE_SEL);
3ecd70b1 1010 DUMPREG(HDMI_ENC_EN);
d8408326
SWK
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);
3ecd70b1
JS
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
d8408326
SWK
1027 DUMPREG(HDMI_VSYNC_POL);
1028 DUMPREG(HDMI_INT_PRO_MODE);
3ecd70b1
JS
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);
d8408326
SWK
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);
3ecd70b1
JS
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);
d8408326
SWK
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);
3ecd70b1
JS
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
d8408326
SWK
1143#undef DUMPREG
1144}
1145
3ecd70b1
JS
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
1de425b0 1167 return -EINVAL;
3ecd70b1
JS
1168}
1169
1170static int hdmi_v14_conf_index(struct drm_display_mode *mode)
d8408326
SWK
1171{
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
1de425b0 1183 return -EINVAL;
d8408326
SWK
1184}
1185
3ecd70b1
JS
1186static 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);
1de425b0
ID
1191
1192 return hdmi_v14_conf_index(mode);
3ecd70b1
JS
1193}
1194
d8408326
SWK
1195static bool hdmi_is_connected(void *ctx)
1196{
f9309d1b 1197 struct hdmi_context *hdata = ctx;
d8408326 1198
cf8fc4f1 1199 return hdata->hpd;
d8408326
SWK
1200}
1201
1202static int hdmi_get_edid(void *ctx, struct drm_connector *connector,
1203 u8 *edid, int len)
1204{
1205 struct edid *raw_edid;
f9309d1b 1206 struct hdmi_context *hdata = ctx;
d8408326
SWK
1207
1208 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1209
1210 if (!hdata->ddc_port)
1211 return -ENODEV;
1212
1213 raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
1214 if (raw_edid) {
872d20d6 1215 hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
d8408326
SWK
1216 memcpy(edid, raw_edid, min((1 + raw_edid->extensions)
1217 * EDID_LENGTH, len));
872d20d6
SWK
1218 DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
1219 (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
1220 raw_edid->width_cm, raw_edid->height_cm);
d8408326
SWK
1221 } else {
1222 return -ENODEV;
1223 }
1224
1225 return 0;
1226}
1227
3ecd70b1 1228static int hdmi_v13_check_timing(struct fb_videomode *check_timing)
d8408326 1229{
d8408326
SWK
1230 int i;
1231
1de425b0
ID
1232 DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
1233 check_timing->xres, check_timing->yres,
1234 check_timing->refresh, (check_timing->vmode &
1235 FB_VMODE_INTERLACED) ? true : false);
1236
3ecd70b1
JS
1237 for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i)
1238 if (hdmi_v13_confs[i].width == check_timing->xres &&
1239 hdmi_v13_confs[i].height == check_timing->yres &&
1240 hdmi_v13_confs[i].vrefresh == check_timing->refresh &&
1241 hdmi_v13_confs[i].interlace ==
1242 ((check_timing->vmode & FB_VMODE_INTERLACED) ?
1243 true : false))
1de425b0
ID
1244 return 0;
1245
1246 /* TODO */
d8408326 1247
3ecd70b1
JS
1248 return -EINVAL;
1249}
1250
1251static int hdmi_v14_check_timing(struct fb_videomode *check_timing)
1252{
1253 int i;
d8408326 1254
1de425b0
ID
1255 DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
1256 check_timing->xres, check_timing->yres,
1257 check_timing->refresh, (check_timing->vmode &
1258 FB_VMODE_INTERLACED) ? true : false);
1259
1260 for (i = 0; i < ARRAY_SIZE(hdmi_confs); i++)
d8408326
SWK
1261 if (hdmi_confs[i].width == check_timing->xres &&
1262 hdmi_confs[i].height == check_timing->yres &&
1263 hdmi_confs[i].vrefresh == check_timing->refresh &&
1264 hdmi_confs[i].interlace ==
1265 ((check_timing->vmode & FB_VMODE_INTERLACED) ?
1266 true : false))
1de425b0
ID
1267 return 0;
1268
1269 /* TODO */
d8408326
SWK
1270
1271 return -EINVAL;
1272}
1273
3ecd70b1
JS
1274static int hdmi_check_timing(void *ctx, void *timing)
1275{
f9309d1b 1276 struct hdmi_context *hdata = ctx;
3ecd70b1
JS
1277 struct fb_videomode *check_timing = timing;
1278
1279 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1280
1281 DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", check_timing->xres,
1282 check_timing->yres, check_timing->refresh,
1283 check_timing->vmode);
1284
1285 if (hdata->is_v13)
1286 return hdmi_v13_check_timing(check_timing);
1287 else
1288 return hdmi_v14_check_timing(check_timing);
1289}
1290
3e148baf
SWK
1291static void hdmi_set_acr(u32 freq, u8 *acr)
1292{
1293 u32 n, cts;
1294
1295 switch (freq) {
1296 case 32000:
1297 n = 4096;
1298 cts = 27000;
1299 break;
1300 case 44100:
1301 n = 6272;
1302 cts = 30000;
1303 break;
1304 case 88200:
1305 n = 12544;
1306 cts = 30000;
1307 break;
1308 case 176400:
1309 n = 25088;
1310 cts = 30000;
1311 break;
1312 case 48000:
1313 n = 6144;
1314 cts = 27000;
1315 break;
1316 case 96000:
1317 n = 12288;
1318 cts = 27000;
1319 break;
1320 case 192000:
1321 n = 24576;
1322 cts = 27000;
1323 break;
1324 default:
1325 n = 0;
1326 cts = 0;
1327 break;
1328 }
1329
1330 acr[1] = cts >> 16;
1331 acr[2] = cts >> 8 & 0xff;
1332 acr[3] = cts & 0xff;
1333
1334 acr[4] = n >> 16;
1335 acr[5] = n >> 8 & 0xff;
1336 acr[6] = n & 0xff;
1337}
1338
1339static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
1340{
1341 hdmi_reg_writeb(hdata, HDMI_ACR_N0, acr[6]);
1342 hdmi_reg_writeb(hdata, HDMI_ACR_N1, acr[5]);
1343 hdmi_reg_writeb(hdata, HDMI_ACR_N2, acr[4]);
1344 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS0, acr[3]);
1345 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS1, acr[2]);
1346 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS2, acr[1]);
1347 hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]);
1348 hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
1349 hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
1350
1351 if (hdata->is_v13)
1352 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4);
1353 else
1354 hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
1355}
1356
1357static void hdmi_audio_init(struct hdmi_context *hdata)
1358{
1359 u32 sample_rate, bits_per_sample, frame_size_code;
1360 u32 data_num, bit_ch, sample_frq;
1361 u32 val;
1362 u8 acr[7];
1363
1364 sample_rate = 44100;
1365 bits_per_sample = 16;
1366 frame_size_code = 0;
1367
1368 switch (bits_per_sample) {
1369 case 20:
1370 data_num = 2;
1371 bit_ch = 1;
1372 break;
1373 case 24:
1374 data_num = 3;
1375 bit_ch = 1;
1376 break;
1377 default:
1378 data_num = 1;
1379 bit_ch = 0;
1380 break;
1381 }
1382
1383 hdmi_set_acr(sample_rate, acr);
1384 hdmi_reg_acr(hdata, acr);
1385
1386 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
1387 | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
1388 | HDMI_I2S_MUX_ENABLE);
1389
1390 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
1391 | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
1392
1393 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
1394
1395 sample_frq = (sample_rate == 44100) ? 0 :
1396 (sample_rate == 48000) ? 2 :
1397 (sample_rate == 32000) ? 3 :
1398 (sample_rate == 96000) ? 0xa : 0x0;
1399
1400 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
1401 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
1402
1403 val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01;
1404 hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val);
1405
1406 /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
1407 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
1408 | HDMI_I2S_SEL_LRCK(6));
1409 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1)
1410 | HDMI_I2S_SEL_SDATA2(4));
1411 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
1412 | HDMI_I2S_SEL_SDATA2(2));
1413 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
1414
1415 /* I2S_CON_1 & 2 */
1416 hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
1417 | HDMI_I2S_L_CH_LOW_POL);
1418 hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
1419 | HDMI_I2S_SET_BIT_CH(bit_ch)
1420 | HDMI_I2S_SET_SDATA_BIT(data_num)
1421 | HDMI_I2S_BASIC_FORMAT);
1422
1423 /* Configure register related to CUV information */
1424 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0
1425 | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH
1426 | HDMI_I2S_COPYRIGHT
1427 | HDMI_I2S_LINEAR_PCM
1428 | HDMI_I2S_CONSUMER_FORMAT);
1429 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
1430 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
1431 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
1432 | HDMI_I2S_SET_SMP_FREQ(sample_frq));
1433 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4,
1434 HDMI_I2S_ORG_SMP_FREQ_44_1
1435 | HDMI_I2S_WORD_LEN_MAX24_24BITS
1436 | HDMI_I2S_WORD_LEN_MAX_24BITS);
1437
1438 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
1439}
1440
1441static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff)
1442{
872d20d6 1443 if (hdata->dvi_mode)
3e148baf
SWK
1444 return;
1445
1446 hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0);
1447 hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ?
1448 HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
1449}
1450
d8408326
SWK
1451static void hdmi_conf_reset(struct hdmi_context *hdata)
1452{
3ecd70b1
JS
1453 u32 reg;
1454
3ecd70b1
JS
1455 if (hdata->is_v13)
1456 reg = HDMI_V13_CORE_RSTOUT;
1457 else
1458 reg = HDMI_CORE_RSTOUT;
1459
d8408326 1460 /* resetting HDMI core */
3ecd70b1 1461 hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT);
d8408326 1462 mdelay(10);
3ecd70b1 1463 hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT);
d8408326 1464 mdelay(10);
d8408326
SWK
1465}
1466
1467static void hdmi_conf_init(struct hdmi_context *hdata)
1468{
d8408326
SWK
1469 /* enable HPD interrupts */
1470 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1471 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
1472 mdelay(10);
1473 hdmi_reg_writemask(hdata, HDMI_INTC_CON, ~0, HDMI_INTC_EN_GLOBAL |
1474 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
1475
1476 /* choose HDMI mode */
1477 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1478 HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
1479 /* disable bluescreen */
1480 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
3ecd70b1 1481
872d20d6
SWK
1482 if (hdata->dvi_mode) {
1483 /* choose DVI mode */
1484 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1485 HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
1486 hdmi_reg_writeb(hdata, HDMI_CON_2,
1487 HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
1488 }
1489
3ecd70b1
JS
1490 if (hdata->is_v13) {
1491 /* choose bluescreen (fecal) color */
1492 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1493 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1494 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1495
1496 /* enable AVI packet every vsync, fixes purple line problem */
1497 hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1498 /* force RGB, look to CEA-861-D, table 7 for more detail */
1499 hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1500 hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1501
1502 hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1503 hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1504 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1505 } else {
1506 /* enable AVI packet every vsync, fixes purple line problem */
1507 hdmi_reg_writeb(hdata, HDMI_AVI_CON, 0x02);
1508 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 2 << 5);
1509 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1510 }
d8408326
SWK
1511}
1512
3ecd70b1 1513static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
d8408326 1514{
3ecd70b1
JS
1515 const struct hdmi_v13_preset_conf *conf =
1516 hdmi_v13_confs[hdata->cur_conf].conf;
1517 const struct hdmi_v13_core_regs *core = &conf->core;
1518 const struct hdmi_v13_tg_regs *tg = &conf->tg;
1519 int tries;
1520
1521 /* setting core registers */
1522 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1523 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
1524 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]);
1525 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]);
1526 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]);
1527 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]);
1528 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]);
1529 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]);
1530 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1531 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
1532 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]);
1533 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]);
1534 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]);
1535 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]);
1536 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]);
1537 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]);
1538 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
1539 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
1540 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
1541 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
1542 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
1543 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
1544 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
1545 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
1546 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
1547 /* Timing generator registers */
1548 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
1549 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
1550 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
1551 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
1552 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
1553 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
1554 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
1555 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
1556 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
1557 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
1558 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
1559 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
1560 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
1561 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
1562 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
1563 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
1564 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
1565 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
1566 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
1567 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
1568 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
1569 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
1570 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
1571 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
1572 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
1573 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
1574 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
1575 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
1576
1577 /* waiting for HDMIPHY's PLL to get to steady state */
1578 for (tries = 100; tries; --tries) {
1579 u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
1580 if (val & HDMI_PHY_STATUS_READY)
1581 break;
1582 mdelay(1);
1583 }
1584 /* steady state not achieved */
1585 if (tries == 0) {
1586 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1587 hdmi_regs_dump(hdata, "timing apply");
1588 }
1589
1590 clk_disable(hdata->res.sclk_hdmi);
1591 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
1592 clk_enable(hdata->res.sclk_hdmi);
1593
1594 /* enable HDMI and timing generator */
1595 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1596 if (core->int_pro_mode[0])
1597 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1598 HDMI_FIELD_EN);
1599 else
1600 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1601}
1602
1603static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
1604{
1605 const struct hdmi_preset_conf *conf = hdmi_confs[hdata->cur_conf].conf;
d8408326
SWK
1606 const struct hdmi_core_regs *core = &conf->core;
1607 const struct hdmi_tg_regs *tg = &conf->tg;
1608 int tries;
1609
1610 /* setting core registers */
1611 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1612 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
3ecd70b1
JS
1613 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_0, core->v2_blank[0]);
1614 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_1, core->v2_blank[1]);
1615 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_0, core->v1_blank[0]);
1616 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_1, core->v1_blank[1]);
1617 hdmi_reg_writeb(hdata, HDMI_V_LINE_0, core->v_line[0]);
1618 hdmi_reg_writeb(hdata, HDMI_V_LINE_1, core->v_line[1]);
1619 hdmi_reg_writeb(hdata, HDMI_H_LINE_0, core->h_line[0]);
1620 hdmi_reg_writeb(hdata, HDMI_H_LINE_1, core->h_line[1]);
1621 hdmi_reg_writeb(hdata, HDMI_HSYNC_POL, core->hsync_pol[0]);
d8408326
SWK
1622 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1623 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
3ecd70b1
JS
1624 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_0, core->v_blank_f0[0]);
1625 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_1, core->v_blank_f0[1]);
1626 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_0, core->v_blank_f1[0]);
1627 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_1, core->v_blank_f1[1]);
1628 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_0, core->h_sync_start[0]);
1629 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_1, core->h_sync_start[1]);
1630 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_0, core->h_sync_end[0]);
1631 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_1, core->h_sync_end[1]);
1632 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_0,
1633 core->v_sync_line_bef_2[0]);
1634 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_1,
1635 core->v_sync_line_bef_2[1]);
1636 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_0,
1637 core->v_sync_line_bef_1[0]);
1638 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_1,
1639 core->v_sync_line_bef_1[1]);
1640 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_0,
1641 core->v_sync_line_aft_2[0]);
1642 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_1,
1643 core->v_sync_line_aft_2[1]);
1644 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_0,
1645 core->v_sync_line_aft_1[0]);
1646 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_1,
1647 core->v_sync_line_aft_1[1]);
1648 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0,
1649 core->v_sync_line_aft_pxl_2[0]);
1650 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_1,
1651 core->v_sync_line_aft_pxl_2[1]);
1652 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0,
1653 core->v_sync_line_aft_pxl_1[0]);
1654 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_1,
1655 core->v_sync_line_aft_pxl_1[1]);
1656 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_0, core->v_blank_f2[0]);
1657 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_1, core->v_blank_f2[1]);
1658 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_0, core->v_blank_f3[0]);
1659 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_1, core->v_blank_f3[1]);
1660 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_0, core->v_blank_f4[0]);
1661 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_1, core->v_blank_f4[1]);
1662 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_0, core->v_blank_f5[0]);
1663 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_1, core->v_blank_f5[1]);
1664 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_0,
1665 core->v_sync_line_aft_3[0]);
1666 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_1,
1667 core->v_sync_line_aft_3[1]);
1668 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_0,
1669 core->v_sync_line_aft_4[0]);
1670 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_1,
1671 core->v_sync_line_aft_4[1]);
1672 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_0,
1673 core->v_sync_line_aft_5[0]);
1674 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_1,
1675 core->v_sync_line_aft_5[1]);
1676 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_0,
1677 core->v_sync_line_aft_6[0]);
1678 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_1,
1679 core->v_sync_line_aft_6[1]);
1680 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0,
1681 core->v_sync_line_aft_pxl_3[0]);
1682 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_1,
1683 core->v_sync_line_aft_pxl_3[1]);
1684 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0,
1685 core->v_sync_line_aft_pxl_4[0]);
1686 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_1,
1687 core->v_sync_line_aft_pxl_4[1]);
1688 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0,
1689 core->v_sync_line_aft_pxl_5[0]);
1690 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_1,
1691 core->v_sync_line_aft_pxl_5[1]);
1692 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0,
1693 core->v_sync_line_aft_pxl_6[0]);
1694 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_1,
1695 core->v_sync_line_aft_pxl_6[1]);
1696 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_0, core->vact_space_1[0]);
1697 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_1, core->vact_space_1[1]);
1698 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_0, core->vact_space_2[0]);
1699 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_1, core->vact_space_2[1]);
1700 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_0, core->vact_space_3[0]);
1701 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_1, core->vact_space_3[1]);
1702 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_0, core->vact_space_4[0]);
1703 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_1, core->vact_space_4[1]);
1704 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_0, core->vact_space_5[0]);
1705 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_1, core->vact_space_5[1]);
1706 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_0, core->vact_space_6[0]);
1707 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]);
1708
d8408326
SWK
1709 /* Timing generator registers */
1710 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
1711 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
1712 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
1713 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
1714 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
1715 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
1716 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
1717 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
1718 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
1719 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
1720 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
1721 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
1722 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
1723 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
1724 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
1725 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
1726 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
1727 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
1728 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
1729 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
3ecd70b1
JS
1730 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3_l);
1731 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3_h);
1732 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4_l);
1733 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4_h);
d8408326
SWK
1734 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
1735 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
1736 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
1737 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
1738 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
1739 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
1740 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
1741 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
3ecd70b1 1742 hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d);
d8408326
SWK
1743
1744 /* waiting for HDMIPHY's PLL to get to steady state */
1745 for (tries = 100; tries; --tries) {
3ecd70b1 1746 u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
d8408326
SWK
1747 if (val & HDMI_PHY_STATUS_READY)
1748 break;
1749 mdelay(1);
1750 }
1751 /* steady state not achieved */
1752 if (tries == 0) {
1753 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1754 hdmi_regs_dump(hdata, "timing apply");
1755 }
1756
1757 clk_disable(hdata->res.sclk_hdmi);
1758 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
1759 clk_enable(hdata->res.sclk_hdmi);
1760
1761 /* enable HDMI and timing generator */
1762 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1763 if (core->int_pro_mode[0])
1764 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1765 HDMI_FIELD_EN);
1766 else
1767 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1768}
1769
3ecd70b1
JS
1770static void hdmi_timing_apply(struct hdmi_context *hdata)
1771{
1772 if (hdata->is_v13)
1773 hdmi_v13_timing_apply(hdata);
1774 else
1775 hdmi_v14_timing_apply(hdata);
1776}
1777
d8408326
SWK
1778static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1779{
1780 u8 buffer[2];
3ecd70b1 1781 u32 reg;
d8408326
SWK
1782
1783 clk_disable(hdata->res.sclk_hdmi);
1784 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_pixel);
1785 clk_enable(hdata->res.sclk_hdmi);
1786
1787 /* operation mode */
1788 buffer[0] = 0x1f;
1789 buffer[1] = 0x00;
1790
1791 if (hdata->hdmiphy_port)
1792 i2c_master_send(hdata->hdmiphy_port, buffer, 2);
1793
3ecd70b1
JS
1794 if (hdata->is_v13)
1795 reg = HDMI_V13_PHY_RSTOUT;
1796 else
1797 reg = HDMI_PHY_RSTOUT;
1798
d8408326 1799 /* reset hdmiphy */
3ecd70b1 1800 hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
d8408326 1801 mdelay(10);
3ecd70b1 1802 hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
d8408326
SWK
1803 mdelay(10);
1804}
1805
1806static void hdmiphy_conf_apply(struct hdmi_context *hdata)
1807{
3ecd70b1 1808 const u8 *hdmiphy_data;
d8408326
SWK
1809 u8 buffer[32];
1810 u8 operation[2];
1811 u8 read_buffer[32] = {0, };
1812 int ret;
1813 int i;
1814
1815 if (!hdata->hdmiphy_port) {
1816 DRM_ERROR("hdmiphy is not attached\n");
1817 return;
1818 }
1819
1820 /* pixel clock */
3ecd70b1
JS
1821 if (hdata->is_v13)
1822 hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data;
1823 else
1824 hdmiphy_data = hdmi_confs[hdata->cur_conf].hdmiphy_data;
1825
1826 memcpy(buffer, hdmiphy_data, 32);
d8408326
SWK
1827 ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32);
1828 if (ret != 32) {
1829 DRM_ERROR("failed to configure HDMIPHY via I2C\n");
1830 return;
1831 }
1832
1833 mdelay(10);
1834
1835 /* operation mode */
1836 operation[0] = 0x1f;
1837 operation[1] = 0x80;
1838
1839 ret = i2c_master_send(hdata->hdmiphy_port, operation, 2);
1840 if (ret != 2) {
1841 DRM_ERROR("failed to enable hdmiphy\n");
1842 return;
1843 }
1844
1845 ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32);
1846 if (ret < 0) {
1847 DRM_ERROR("failed to read hdmiphy config\n");
1848 return;
1849 }
1850
1851 for (i = 0; i < ret; i++)
1852 DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - "
1853 "recv [0x%02x]\n", i, buffer[i], read_buffer[i]);
1854}
1855
1856static void hdmi_conf_apply(struct hdmi_context *hdata)
1857{
d8408326
SWK
1858 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1859
1860 hdmiphy_conf_reset(hdata);
1861 hdmiphy_conf_apply(hdata);
1862
cf8fc4f1 1863 mutex_lock(&hdata->hdmi_mutex);
d8408326
SWK
1864 hdmi_conf_reset(hdata);
1865 hdmi_conf_init(hdata);
cf8fc4f1
JS
1866 mutex_unlock(&hdata->hdmi_mutex);
1867
3e148baf 1868 hdmi_audio_init(hdata);
d8408326
SWK
1869
1870 /* setting core registers */
3ecd70b1 1871 hdmi_timing_apply(hdata);
3e148baf 1872 hdmi_audio_control(hdata, true);
d8408326
SWK
1873
1874 hdmi_regs_dump(hdata, "start");
1875}
1876
1de425b0
ID
1877static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,
1878 struct drm_display_mode *mode,
1879 struct drm_display_mode *adjusted_mode)
1880{
1881 struct drm_display_mode *m;
f9309d1b 1882 struct hdmi_context *hdata = ctx;
1de425b0
ID
1883 int index;
1884
1885 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1886
1887 drm_mode_set_crtcinfo(adjusted_mode, 0);
1888
1889 if (hdata->is_v13)
1890 index = hdmi_v13_conf_index(adjusted_mode);
1891 else
1892 index = hdmi_v14_conf_index(adjusted_mode);
1893
1894 /* just return if user desired mode exists. */
1895 if (index >= 0)
1896 return;
1897
1898 /*
1899 * otherwise, find the most suitable mode among modes and change it
1900 * to adjusted_mode.
1901 */
1902 list_for_each_entry(m, &connector->modes, head) {
1903 if (hdata->is_v13)
1904 index = hdmi_v13_conf_index(m);
1905 else
1906 index = hdmi_v14_conf_index(m);
1907
1908 if (index >= 0) {
1909 DRM_INFO("desired mode doesn't exist so\n");
1910 DRM_INFO("use the most suitable mode among modes.\n");
1911 memcpy(adjusted_mode, m, sizeof(*m));
1912 break;
1913 }
1914 }
1915}
1916
d8408326
SWK
1917static void hdmi_mode_set(void *ctx, void *mode)
1918{
f9309d1b 1919 struct hdmi_context *hdata = ctx;
d8408326
SWK
1920 int conf_idx;
1921
1922 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1923
3ecd70b1
JS
1924 conf_idx = hdmi_conf_index(hdata, mode);
1925 if (conf_idx >= 0)
d8408326
SWK
1926 hdata->cur_conf = conf_idx;
1927 else
1928 DRM_DEBUG_KMS("not supported mode\n");
1929}
1930
1de425b0
ID
1931static void hdmi_get_max_resol(void *ctx, unsigned int *width,
1932 unsigned int *height)
1933{
1934 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1935
1936 *width = MAX_WIDTH;
1937 *height = MAX_HEIGHT;
1938}
1939
d8408326
SWK
1940static void hdmi_commit(void *ctx)
1941{
f9309d1b 1942 struct hdmi_context *hdata = ctx;
d8408326
SWK
1943
1944 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1945
1946 hdmi_conf_apply(hdata);
cf8fc4f1
JS
1947}
1948
1949static void hdmi_poweron(struct hdmi_context *hdata)
1950{
1951 struct hdmi_resources *res = &hdata->res;
1952
1953 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1954
1955 mutex_lock(&hdata->hdmi_mutex);
1956 if (hdata->powered) {
1957 mutex_unlock(&hdata->hdmi_mutex);
1958 return;
1959 }
d8408326 1960
cf8fc4f1
JS
1961 hdata->powered = true;
1962
1963 if (hdata->cfg_hpd)
1964 hdata->cfg_hpd(true);
1965 mutex_unlock(&hdata->hdmi_mutex);
1966
1967 pm_runtime_get_sync(hdata->dev);
1968
1969 regulator_bulk_enable(res->regul_count, res->regul_bulk);
1970 clk_enable(res->hdmiphy);
1971 clk_enable(res->hdmi);
1972 clk_enable(res->sclk_hdmi);
1973}
1974
1975static void hdmi_poweroff(struct hdmi_context *hdata)
1976{
1977 struct hdmi_resources *res = &hdata->res;
1978
1979 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1980
1981 mutex_lock(&hdata->hdmi_mutex);
1982 if (!hdata->powered)
1983 goto out;
1984 mutex_unlock(&hdata->hdmi_mutex);
1985
1986 /*
1987 * The TV power domain needs any condition of hdmiphy to turn off and
1988 * its reset state seems to meet the condition.
1989 */
1990 hdmiphy_conf_reset(hdata);
1991
1992 clk_disable(res->sclk_hdmi);
1993 clk_disable(res->hdmi);
1994 clk_disable(res->hdmiphy);
1995 regulator_bulk_disable(res->regul_count, res->regul_bulk);
1996
1997 pm_runtime_put_sync(hdata->dev);
1998
1999 mutex_lock(&hdata->hdmi_mutex);
2000 if (hdata->cfg_hpd)
2001 hdata->cfg_hpd(false);
2002
2003 hdata->powered = false;
2004
2005out:
2006 mutex_unlock(&hdata->hdmi_mutex);
d8408326
SWK
2007}
2008
cf8fc4f1 2009static void hdmi_dpms(void *ctx, int mode)
d8408326 2010{
f9309d1b 2011 struct hdmi_context *hdata = ctx;
d8408326
SWK
2012
2013 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2014
cf8fc4f1
JS
2015 switch (mode) {
2016 case DRM_MODE_DPMS_ON:
2017 hdmi_poweron(hdata);
2018 break;
2019 case DRM_MODE_DPMS_STANDBY:
2020 case DRM_MODE_DPMS_SUSPEND:
2021 case DRM_MODE_DPMS_OFF:
2022 hdmi_poweroff(hdata);
2023 break;
2024 default:
2025 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
2026 break;
d8408326
SWK
2027 }
2028}
2029
578b6065
JS
2030static struct exynos_hdmi_ops hdmi_ops = {
2031 /* display */
2032 .is_connected = hdmi_is_connected,
2033 .get_edid = hdmi_get_edid,
2034 .check_timing = hdmi_check_timing,
578b6065
JS
2035
2036 /* manager */
1de425b0 2037 .mode_fixup = hdmi_mode_fixup,
d8408326 2038 .mode_set = hdmi_mode_set,
1de425b0 2039 .get_max_resol = hdmi_get_max_resol,
d8408326 2040 .commit = hdmi_commit,
cf8fc4f1 2041 .dpms = hdmi_dpms,
d8408326
SWK
2042};
2043
cf8fc4f1
JS
2044static irqreturn_t hdmi_external_irq_thread(int irq, void *arg)
2045{
2046 struct exynos_drm_hdmi_context *ctx = arg;
2047 struct hdmi_context *hdata = ctx->ctx;
2048
2049 if (!hdata->get_hpd)
2050 goto out;
2051
2052 mutex_lock(&hdata->hdmi_mutex);
2053 hdata->hpd = hdata->get_hpd();
2054 mutex_unlock(&hdata->hdmi_mutex);
2055
2056 if (ctx->drm_dev)
2057 drm_helper_hpd_irq_event(ctx->drm_dev);
2058
2059out:
2060 return IRQ_HANDLED;
2061}
2062
2063static irqreturn_t hdmi_internal_irq_thread(int irq, void *arg)
d8408326
SWK
2064{
2065 struct exynos_drm_hdmi_context *ctx = arg;
f9309d1b 2066 struct hdmi_context *hdata = ctx->ctx;
d8408326
SWK
2067 u32 intc_flag;
2068
2069 intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG);
2070 /* clearing flags for HPD plug/unplug */
2071 if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
cf8fc4f1 2072 DRM_DEBUG_KMS("unplugged\n");
d8408326
SWK
2073 hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
2074 HDMI_INTC_FLAG_HPD_UNPLUG);
2075 }
2076 if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
cf8fc4f1 2077 DRM_DEBUG_KMS("plugged\n");
d8408326
SWK
2078 hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
2079 HDMI_INTC_FLAG_HPD_PLUG);
2080 }
2081
cf8fc4f1
JS
2082 mutex_lock(&hdata->hdmi_mutex);
2083 hdata->hpd = hdmi_reg_read(hdata, HDMI_HPD_STATUS);
2084 if (hdata->powered && hdata->hpd) {
2085 mutex_unlock(&hdata->hdmi_mutex);
2086 goto out;
2087 }
2088 mutex_unlock(&hdata->hdmi_mutex);
2089
2090 if (ctx->drm_dev)
66265a2e 2091 drm_helper_hpd_irq_event(ctx->drm_dev);
d8408326 2092
cf8fc4f1 2093out:
d8408326
SWK
2094 return IRQ_HANDLED;
2095}
2096
2097static int __devinit hdmi_resources_init(struct hdmi_context *hdata)
2098{
2099 struct device *dev = hdata->dev;
2100 struct hdmi_resources *res = &hdata->res;
2101 static char *supply[] = {
2102 "hdmi-en",
2103 "vdd",
2104 "vdd_osc",
2105 "vdd_pll",
2106 };
2107 int i, ret;
2108
2109 DRM_DEBUG_KMS("HDMI resource init\n");
2110
2111 memset(res, 0, sizeof *res);
2112
2113 /* get clocks, power */
2114 res->hdmi = clk_get(dev, "hdmi");
2115 if (IS_ERR_OR_NULL(res->hdmi)) {
2116 DRM_ERROR("failed to get clock 'hdmi'\n");
2117 goto fail;
2118 }
2119 res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
2120 if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
2121 DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
2122 goto fail;
2123 }
2124 res->sclk_pixel = clk_get(dev, "sclk_pixel");
2125 if (IS_ERR_OR_NULL(res->sclk_pixel)) {
2126 DRM_ERROR("failed to get clock 'sclk_pixel'\n");
2127 goto fail;
2128 }
2129 res->sclk_hdmiphy = clk_get(dev, "sclk_hdmiphy");
2130 if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) {
2131 DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
2132 goto fail;
2133 }
2134 res->hdmiphy = clk_get(dev, "hdmiphy");
2135 if (IS_ERR_OR_NULL(res->hdmiphy)) {
2136 DRM_ERROR("failed to get clock 'hdmiphy'\n");
2137 goto fail;
2138 }
2139
2140 clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
2141
2142 res->regul_bulk = kzalloc(ARRAY_SIZE(supply) *
2143 sizeof res->regul_bulk[0], GFP_KERNEL);
2144 if (!res->regul_bulk) {
2145 DRM_ERROR("failed to get memory for regulators\n");
2146 goto fail;
2147 }
2148 for (i = 0; i < ARRAY_SIZE(supply); ++i) {
2149 res->regul_bulk[i].supply = supply[i];
2150 res->regul_bulk[i].consumer = NULL;
2151 }
2152 ret = regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
2153 if (ret) {
2154 DRM_ERROR("failed to get regulators\n");
2155 goto fail;
2156 }
2157 res->regul_count = ARRAY_SIZE(supply);
2158
2159 return 0;
2160fail:
2161 DRM_ERROR("HDMI resource init - failed\n");
2162 return -ENODEV;
2163}
2164
2165static int hdmi_resources_cleanup(struct hdmi_context *hdata)
2166{
2167 struct hdmi_resources *res = &hdata->res;
2168
2169 regulator_bulk_free(res->regul_count, res->regul_bulk);
2170 /* kfree is NULL-safe */
2171 kfree(res->regul_bulk);
2172 if (!IS_ERR_OR_NULL(res->hdmiphy))
2173 clk_put(res->hdmiphy);
2174 if (!IS_ERR_OR_NULL(res->sclk_hdmiphy))
2175 clk_put(res->sclk_hdmiphy);
2176 if (!IS_ERR_OR_NULL(res->sclk_pixel))
2177 clk_put(res->sclk_pixel);
2178 if (!IS_ERR_OR_NULL(res->sclk_hdmi))
2179 clk_put(res->sclk_hdmi);
2180 if (!IS_ERR_OR_NULL(res->hdmi))
2181 clk_put(res->hdmi);
2182 memset(res, 0, sizeof *res);
2183
2184 return 0;
2185}
2186
d8408326
SWK
2187static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;
2188
2189void hdmi_attach_ddc_client(struct i2c_client *ddc)
2190{
2191 if (ddc)
2192 hdmi_ddc = ddc;
2193}
d8408326
SWK
2194
2195void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)
2196{
2197 if (hdmiphy)
2198 hdmi_hdmiphy = hdmiphy;
2199}
d8408326
SWK
2200
2201static int __devinit hdmi_probe(struct platform_device *pdev)
2202{
2203 struct device *dev = &pdev->dev;
2204 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
2205 struct hdmi_context *hdata;
2206 struct exynos_drm_hdmi_pdata *pdata;
2207 struct resource *res;
2208 int ret;
2209
2210 DRM_DEBUG_KMS("[%d]\n", __LINE__);
2211
2212 pdata = pdev->dev.platform_data;
2213 if (!pdata) {
2214 DRM_ERROR("no platform data specified\n");
2215 return -EINVAL;
2216 }
2217
2218 drm_hdmi_ctx = kzalloc(sizeof(*drm_hdmi_ctx), GFP_KERNEL);
2219 if (!drm_hdmi_ctx) {
2220 DRM_ERROR("failed to allocate common hdmi context.\n");
2221 return -ENOMEM;
2222 }
2223
2224 hdata = kzalloc(sizeof(struct hdmi_context), GFP_KERNEL);
2225 if (!hdata) {
2226 DRM_ERROR("out of memory\n");
2227 kfree(drm_hdmi_ctx);
2228 return -ENOMEM;
2229 }
2230
cf8fc4f1
JS
2231 mutex_init(&hdata->hdmi_mutex);
2232
d8408326
SWK
2233 drm_hdmi_ctx->ctx = (void *)hdata;
2234 hdata->parent_ctx = (void *)drm_hdmi_ctx;
2235
2236 platform_set_drvdata(pdev, drm_hdmi_ctx);
2237
3ecd70b1 2238 hdata->is_v13 = pdata->is_v13;
7ecd34e8
JS
2239 hdata->cfg_hpd = pdata->cfg_hpd;
2240 hdata->get_hpd = pdata->get_hpd;
d8408326
SWK
2241 hdata->dev = dev;
2242
2243 ret = hdmi_resources_init(hdata);
2244 if (ret) {
2245 ret = -EINVAL;
2246 goto err_data;
2247 }
2248
2249 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2250 if (!res) {
2251 DRM_ERROR("failed to find registers\n");
2252 ret = -ENOENT;
2253 goto err_resource;
2254 }
2255
2256 hdata->regs_res = request_mem_region(res->start, resource_size(res),
2257 dev_name(dev));
2258 if (!hdata->regs_res) {
2259 DRM_ERROR("failed to claim register region\n");
2260 ret = -ENOENT;
2261 goto err_resource;
2262 }
2263
2264 hdata->regs = ioremap(res->start, resource_size(res));
2265 if (!hdata->regs) {
2266 DRM_ERROR("failed to map registers\n");
2267 ret = -ENXIO;
2268 goto err_req_region;
2269 }
2270
2271 /* DDC i2c driver */
2272 if (i2c_add_driver(&ddc_driver)) {
2273 DRM_ERROR("failed to register ddc i2c driver\n");
2274 ret = -ENOENT;
2275 goto err_iomap;
2276 }
2277
2278 hdata->ddc_port = hdmi_ddc;
2279
2280 /* hdmiphy i2c driver */
2281 if (i2c_add_driver(&hdmiphy_driver)) {
2282 DRM_ERROR("failed to register hdmiphy i2c driver\n");
2283 ret = -ENOENT;
2284 goto err_ddc;
2285 }
2286
2287 hdata->hdmiphy_port = hdmi_hdmiphy;
2288
cf8fc4f1
JS
2289 hdata->external_irq = platform_get_irq_byname(pdev, "external_irq");
2290 if (hdata->external_irq < 0) {
ce80a2d1 2291 DRM_ERROR("failed to get platform irq\n");
cf8fc4f1 2292 ret = hdata->external_irq;
d8408326
SWK
2293 goto err_hdmiphy;
2294 }
2295
cf8fc4f1
JS
2296 hdata->internal_irq = platform_get_irq_byname(pdev, "internal_irq");
2297 if (hdata->internal_irq < 0) {
2298 DRM_ERROR("failed to get platform internal irq\n");
2299 ret = hdata->internal_irq;
2300 goto err_hdmiphy;
2301 }
2302
2303 ret = request_threaded_irq(hdata->external_irq, NULL,
2304 hdmi_external_irq_thread, IRQF_TRIGGER_RISING |
2305 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
2306 "hdmi_external", drm_hdmi_ctx);
d8408326 2307 if (ret) {
cf8fc4f1 2308 DRM_ERROR("failed to register hdmi internal interrupt\n");
66265a2e 2309 goto err_hdmiphy;
d8408326 2310 }
d8408326 2311
cf8fc4f1
JS
2312 if (hdata->cfg_hpd)
2313 hdata->cfg_hpd(false);
2314
2315 ret = request_threaded_irq(hdata->internal_irq, NULL,
2316 hdmi_internal_irq_thread, IRQF_ONESHOT,
2317 "hdmi_internal", drm_hdmi_ctx);
2318 if (ret) {
2319 DRM_ERROR("failed to register hdmi internal interrupt\n");
2320 goto err_free_irq;
2321 }
2322
d8408326 2323 /* register specific callbacks to common hdmi. */
578b6065 2324 exynos_hdmi_ops_register(&hdmi_ops);
d8408326 2325
cf8fc4f1 2326 pm_runtime_enable(dev);
d8408326
SWK
2327
2328 return 0;
2329
cf8fc4f1
JS
2330err_free_irq:
2331 free_irq(hdata->external_irq, drm_hdmi_ctx);
d8408326
SWK
2332err_hdmiphy:
2333 i2c_del_driver(&hdmiphy_driver);
2334err_ddc:
2335 i2c_del_driver(&ddc_driver);
2336err_iomap:
2337 iounmap(hdata->regs);
2338err_req_region:
485bc54c
SWK
2339 release_mem_region(hdata->regs_res->start,
2340 resource_size(hdata->regs_res));
d8408326
SWK
2341err_resource:
2342 hdmi_resources_cleanup(hdata);
2343err_data:
2344 kfree(hdata);
2345 kfree(drm_hdmi_ctx);
2346 return ret;
2347}
2348
2349static int __devexit hdmi_remove(struct platform_device *pdev)
2350{
cf8fc4f1 2351 struct device *dev = &pdev->dev;
d8408326 2352 struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev);
f9309d1b 2353 struct hdmi_context *hdata = ctx->ctx;
d8408326
SWK
2354
2355 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2356
cf8fc4f1 2357 pm_runtime_disable(dev);
d8408326 2358
cf8fc4f1 2359 free_irq(hdata->internal_irq, hdata);
d8408326 2360
d8408326
SWK
2361 hdmi_resources_cleanup(hdata);
2362
2363 iounmap(hdata->regs);
2364
485bc54c
SWK
2365 release_mem_region(hdata->regs_res->start,
2366 resource_size(hdata->regs_res));
d8408326
SWK
2367
2368 /* hdmiphy i2c driver */
2369 i2c_del_driver(&hdmiphy_driver);
2370 /* DDC i2c driver */
2371 i2c_del_driver(&ddc_driver);
2372
2373 kfree(hdata);
2374
2375 return 0;
2376}
2377
ab27af85
JS
2378#ifdef CONFIG_PM_SLEEP
2379static int hdmi_suspend(struct device *dev)
2380{
2381 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2382 struct hdmi_context *hdata = ctx->ctx;
2383
2384 disable_irq(hdata->internal_irq);
2385 disable_irq(hdata->external_irq);
2386
2387 hdata->hpd = false;
2388 if (ctx->drm_dev)
2389 drm_helper_hpd_irq_event(ctx->drm_dev);
2390
2391 hdmi_poweroff(hdata);
2392
2393 return 0;
2394}
2395
2396static int hdmi_resume(struct device *dev)
2397{
2398 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2399 struct hdmi_context *hdata = ctx->ctx;
2400
2401 enable_irq(hdata->external_irq);
2402 enable_irq(hdata->internal_irq);
2403 return 0;
2404}
2405#endif
2406
2407static SIMPLE_DEV_PM_OPS(hdmi_pm_ops, hdmi_suspend, hdmi_resume);
2408
d8408326
SWK
2409struct platform_driver hdmi_driver = {
2410 .probe = hdmi_probe,
2411 .remove = __devexit_p(hdmi_remove),
2412 .driver = {
2413 .name = "exynos4-hdmi",
2414 .owner = THIS_MODULE,
ab27af85 2415 .pm = &hdmi_pm_ops,
d8408326
SWK
2416 },
2417};