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