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