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