blob: 90dce8c45f8df1b9724cbfbdb498fb64aa7d74f9 [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{
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001535 /* enable HPD interrupts */
1536 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1537 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
1538 mdelay(10);
1539 hdmi_reg_writemask(hdata, HDMI_INTC_CON, ~0, HDMI_INTC_EN_GLOBAL |
1540 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
1541
1542 /* choose HDMI mode */
1543 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1544 HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
1545 /* disable bluescreen */
1546 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001547
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001548 if (hdata->dvi_mode) {
1549 /* choose DVI mode */
1550 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1551 HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
1552 hdmi_reg_writeb(hdata, HDMI_CON_2,
1553 HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
1554 }
1555
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001556 if (hdata->is_v13) {
1557 /* choose bluescreen (fecal) color */
1558 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1559 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1560 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1561
1562 /* enable AVI packet every vsync, fixes purple line problem */
1563 hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1564 /* force RGB, look to CEA-861-D, table 7 for more detail */
1565 hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1566 hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1567
1568 hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1569 hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1570 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1571 } else {
1572 /* enable AVI packet every vsync, fixes purple line problem */
1573 hdmi_reg_writeb(hdata, HDMI_AVI_CON, 0x02);
1574 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 2 << 5);
1575 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1576 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001577}
1578
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001579static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001580{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001581 const struct hdmi_v13_preset_conf *conf =
1582 hdmi_v13_confs[hdata->cur_conf].conf;
1583 const struct hdmi_v13_core_regs *core = &conf->core;
1584 const struct hdmi_v13_tg_regs *tg = &conf->tg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001585 int tries;
1586
1587 /* setting core registers */
1588 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1589 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001590 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]);
1591 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]);
1592 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]);
1593 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]);
1594 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]);
1595 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001596 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1597 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001598 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]);
1599 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]);
1600 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]);
1601 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]);
1602 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]);
1603 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]);
1604 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
1605 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
1606 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
1607 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
1608 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
1609 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
1610 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
1611 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
1612 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001613 /* Timing generator registers */
1614 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
1615 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
1616 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
1617 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
1618 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
1619 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
1620 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
1621 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
1622 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
1623 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
1624 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
1625 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
1626 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
1627 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
1628 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
1629 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
1630 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
1631 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
1632 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
1633 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
1634 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
1635 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
1636 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
1637 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
1638 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
1639 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
1640 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
1641 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
1642
1643 /* waiting for HDMIPHY's PLL to get to steady state */
1644 for (tries = 100; tries; --tries) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001645 u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001646 if (val & HDMI_PHY_STATUS_READY)
1647 break;
1648 mdelay(1);
1649 }
1650 /* steady state not achieved */
1651 if (tries == 0) {
1652 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1653 hdmi_regs_dump(hdata, "timing apply");
1654 }
1655
1656 clk_disable(hdata->res.sclk_hdmi);
1657 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
1658 clk_enable(hdata->res.sclk_hdmi);
1659
1660 /* enable HDMI and timing generator */
1661 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1662 if (core->int_pro_mode[0])
1663 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1664 HDMI_FIELD_EN);
1665 else
1666 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1667}
1668
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001669static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
1670{
1671 const struct hdmi_preset_conf *conf = hdmi_confs[hdata->cur_conf].conf;
1672 const struct hdmi_core_regs *core = &conf->core;
1673 const struct hdmi_tg_regs *tg = &conf->tg;
1674 int tries;
1675
1676 /* setting core registers */
1677 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1678 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
1679 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_0, core->v2_blank[0]);
1680 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_1, core->v2_blank[1]);
1681 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_0, core->v1_blank[0]);
1682 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_1, core->v1_blank[1]);
1683 hdmi_reg_writeb(hdata, HDMI_V_LINE_0, core->v_line[0]);
1684 hdmi_reg_writeb(hdata, HDMI_V_LINE_1, core->v_line[1]);
1685 hdmi_reg_writeb(hdata, HDMI_H_LINE_0, core->h_line[0]);
1686 hdmi_reg_writeb(hdata, HDMI_H_LINE_1, core->h_line[1]);
1687 hdmi_reg_writeb(hdata, HDMI_HSYNC_POL, core->hsync_pol[0]);
1688 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1689 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
1690 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_0, core->v_blank_f0[0]);
1691 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_1, core->v_blank_f0[1]);
1692 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_0, core->v_blank_f1[0]);
1693 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_1, core->v_blank_f1[1]);
1694 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_0, core->h_sync_start[0]);
1695 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_1, core->h_sync_start[1]);
1696 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_0, core->h_sync_end[0]);
1697 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_1, core->h_sync_end[1]);
1698 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_0,
1699 core->v_sync_line_bef_2[0]);
1700 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_1,
1701 core->v_sync_line_bef_2[1]);
1702 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_0,
1703 core->v_sync_line_bef_1[0]);
1704 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_1,
1705 core->v_sync_line_bef_1[1]);
1706 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_0,
1707 core->v_sync_line_aft_2[0]);
1708 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_1,
1709 core->v_sync_line_aft_2[1]);
1710 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_0,
1711 core->v_sync_line_aft_1[0]);
1712 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_1,
1713 core->v_sync_line_aft_1[1]);
1714 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0,
1715 core->v_sync_line_aft_pxl_2[0]);
1716 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_1,
1717 core->v_sync_line_aft_pxl_2[1]);
1718 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0,
1719 core->v_sync_line_aft_pxl_1[0]);
1720 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_1,
1721 core->v_sync_line_aft_pxl_1[1]);
1722 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_0, core->v_blank_f2[0]);
1723 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_1, core->v_blank_f2[1]);
1724 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_0, core->v_blank_f3[0]);
1725 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_1, core->v_blank_f3[1]);
1726 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_0, core->v_blank_f4[0]);
1727 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_1, core->v_blank_f4[1]);
1728 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_0, core->v_blank_f5[0]);
1729 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_1, core->v_blank_f5[1]);
1730 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_0,
1731 core->v_sync_line_aft_3[0]);
1732 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_1,
1733 core->v_sync_line_aft_3[1]);
1734 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_0,
1735 core->v_sync_line_aft_4[0]);
1736 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_1,
1737 core->v_sync_line_aft_4[1]);
1738 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_0,
1739 core->v_sync_line_aft_5[0]);
1740 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_1,
1741 core->v_sync_line_aft_5[1]);
1742 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_0,
1743 core->v_sync_line_aft_6[0]);
1744 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_1,
1745 core->v_sync_line_aft_6[1]);
1746 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0,
1747 core->v_sync_line_aft_pxl_3[0]);
1748 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_1,
1749 core->v_sync_line_aft_pxl_3[1]);
1750 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0,
1751 core->v_sync_line_aft_pxl_4[0]);
1752 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_1,
1753 core->v_sync_line_aft_pxl_4[1]);
1754 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0,
1755 core->v_sync_line_aft_pxl_5[0]);
1756 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_1,
1757 core->v_sync_line_aft_pxl_5[1]);
1758 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0,
1759 core->v_sync_line_aft_pxl_6[0]);
1760 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_1,
1761 core->v_sync_line_aft_pxl_6[1]);
1762 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_0, core->vact_space_1[0]);
1763 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_1, core->vact_space_1[1]);
1764 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_0, core->vact_space_2[0]);
1765 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_1, core->vact_space_2[1]);
1766 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_0, core->vact_space_3[0]);
1767 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_1, core->vact_space_3[1]);
1768 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_0, core->vact_space_4[0]);
1769 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_1, core->vact_space_4[1]);
1770 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_0, core->vact_space_5[0]);
1771 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_1, core->vact_space_5[1]);
1772 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_0, core->vact_space_6[0]);
1773 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]);
1774
1775 /* Timing generator registers */
1776 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
1777 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
1778 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
1779 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
1780 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
1781 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
1782 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
1783 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
1784 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
1785 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
1786 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
1787 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
1788 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
1789 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
1790 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
1791 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
1792 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
1793 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
1794 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
1795 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
1796 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3_l);
1797 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3_h);
1798 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4_l);
1799 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4_h);
1800 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
1801 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
1802 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
1803 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
1804 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
1805 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
1806 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
1807 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
1808 hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d);
1809
1810 /* waiting for HDMIPHY's PLL to get to steady state */
1811 for (tries = 100; tries; --tries) {
1812 u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
1813 if (val & HDMI_PHY_STATUS_READY)
1814 break;
1815 mdelay(1);
1816 }
1817 /* steady state not achieved */
1818 if (tries == 0) {
1819 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1820 hdmi_regs_dump(hdata, "timing apply");
1821 }
1822
1823 clk_disable(hdata->res.sclk_hdmi);
1824 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
1825 clk_enable(hdata->res.sclk_hdmi);
1826
1827 /* enable HDMI and timing generator */
1828 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1829 if (core->int_pro_mode[0])
1830 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1831 HDMI_FIELD_EN);
1832 else
1833 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1834}
1835
1836static void hdmi_timing_apply(struct hdmi_context *hdata)
1837{
1838 if (hdata->is_v13)
1839 hdmi_v13_timing_apply(hdata);
1840 else
1841 hdmi_v14_timing_apply(hdata);
1842}
1843
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001844static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1845{
1846 u8 buffer[2];
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001847 u32 reg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001848
1849 clk_disable(hdata->res.sclk_hdmi);
1850 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_pixel);
1851 clk_enable(hdata->res.sclk_hdmi);
1852
1853 /* operation mode */
1854 buffer[0] = 0x1f;
1855 buffer[1] = 0x00;
1856
1857 if (hdata->hdmiphy_port)
1858 i2c_master_send(hdata->hdmiphy_port, buffer, 2);
1859
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001860 if (hdata->is_v13)
1861 reg = HDMI_V13_PHY_RSTOUT;
1862 else
1863 reg = HDMI_PHY_RSTOUT;
1864
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001865 /* reset hdmiphy */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001866 hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001867 mdelay(10);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001868 hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001869 mdelay(10);
1870}
1871
1872static void hdmiphy_conf_apply(struct hdmi_context *hdata)
1873{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001874 const u8 *hdmiphy_data;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001875 u8 buffer[32];
1876 u8 operation[2];
1877 u8 read_buffer[32] = {0, };
1878 int ret;
1879 int i;
1880
1881 if (!hdata->hdmiphy_port) {
1882 DRM_ERROR("hdmiphy is not attached\n");
1883 return;
1884 }
1885
1886 /* pixel clock */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001887 if (hdata->is_v13)
1888 hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data;
1889 else
1890 hdmiphy_data = hdmi_confs[hdata->cur_conf].hdmiphy_data;
1891
1892 memcpy(buffer, hdmiphy_data, 32);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001893 ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32);
1894 if (ret != 32) {
1895 DRM_ERROR("failed to configure HDMIPHY via I2C\n");
1896 return;
1897 }
1898
1899 mdelay(10);
1900
1901 /* operation mode */
1902 operation[0] = 0x1f;
1903 operation[1] = 0x80;
1904
1905 ret = i2c_master_send(hdata->hdmiphy_port, operation, 2);
1906 if (ret != 2) {
1907 DRM_ERROR("failed to enable hdmiphy\n");
1908 return;
1909 }
1910
1911 ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32);
1912 if (ret < 0) {
1913 DRM_ERROR("failed to read hdmiphy config\n");
1914 return;
1915 }
1916
1917 for (i = 0; i < ret; i++)
1918 DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - "
1919 "recv [0x%02x]\n", i, buffer[i], read_buffer[i]);
1920}
1921
1922static void hdmi_conf_apply(struct hdmi_context *hdata)
1923{
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001924 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1925
1926 hdmiphy_conf_reset(hdata);
1927 hdmiphy_conf_apply(hdata);
1928
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001929 mutex_lock(&hdata->hdmi_mutex);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001930 hdmi_conf_reset(hdata);
1931 hdmi_conf_init(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001932 mutex_unlock(&hdata->hdmi_mutex);
1933
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001934 hdmi_audio_init(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001935
1936 /* setting core registers */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001937 hdmi_timing_apply(hdata);
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001938 hdmi_audio_control(hdata, true);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001939
1940 hdmi_regs_dump(hdata, "start");
1941}
1942
Inki Dae1de425b2012-03-16 18:47:04 +09001943static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,
Laurent Pincharte811f5a2012-07-17 17:56:50 +02001944 const struct drm_display_mode *mode,
Inki Dae1de425b2012-03-16 18:47:04 +09001945 struct drm_display_mode *adjusted_mode)
1946{
1947 struct drm_display_mode *m;
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001948 struct hdmi_context *hdata = ctx;
Inki Dae1de425b2012-03-16 18:47:04 +09001949 int index;
1950
1951 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1952
1953 drm_mode_set_crtcinfo(adjusted_mode, 0);
1954
1955 if (hdata->is_v13)
1956 index = hdmi_v13_conf_index(adjusted_mode);
1957 else
1958 index = hdmi_v14_conf_index(adjusted_mode);
1959
1960 /* just return if user desired mode exists. */
1961 if (index >= 0)
1962 return;
1963
1964 /*
1965 * otherwise, find the most suitable mode among modes and change it
1966 * to adjusted_mode.
1967 */
1968 list_for_each_entry(m, &connector->modes, head) {
1969 if (hdata->is_v13)
1970 index = hdmi_v13_conf_index(m);
1971 else
1972 index = hdmi_v14_conf_index(m);
1973
1974 if (index >= 0) {
1975 DRM_INFO("desired mode doesn't exist so\n");
1976 DRM_INFO("use the most suitable mode among modes.\n");
1977 memcpy(adjusted_mode, m, sizeof(*m));
1978 break;
1979 }
1980 }
1981}
1982
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001983static void hdmi_mode_set(void *ctx, void *mode)
1984{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001985 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001986 int conf_idx;
1987
1988 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1989
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001990 conf_idx = hdmi_conf_index(hdata, mode);
1991 if (conf_idx >= 0)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001992 hdata->cur_conf = conf_idx;
1993 else
1994 DRM_DEBUG_KMS("not supported mode\n");
1995}
1996
Inki Dae1de425b2012-03-16 18:47:04 +09001997static void hdmi_get_max_resol(void *ctx, unsigned int *width,
1998 unsigned int *height)
1999{
2000 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2001
2002 *width = MAX_WIDTH;
2003 *height = MAX_HEIGHT;
2004}
2005
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002006static void hdmi_commit(void *ctx)
2007{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002008 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002009
2010 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2011
2012 hdmi_conf_apply(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002013}
2014
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002015static void hdmi_poweron(struct hdmi_context *hdata)
2016{
2017 struct hdmi_resources *res = &hdata->res;
2018
2019 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2020
2021 mutex_lock(&hdata->hdmi_mutex);
2022 if (hdata->powered) {
2023 mutex_unlock(&hdata->hdmi_mutex);
2024 return;
2025 }
2026
2027 hdata->powered = true;
2028
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002029 mutex_unlock(&hdata->hdmi_mutex);
2030
2031 pm_runtime_get_sync(hdata->dev);
2032
2033 regulator_bulk_enable(res->regul_count, res->regul_bulk);
2034 clk_enable(res->hdmiphy);
2035 clk_enable(res->hdmi);
2036 clk_enable(res->sclk_hdmi);
2037}
2038
2039static void hdmi_poweroff(struct hdmi_context *hdata)
2040{
2041 struct hdmi_resources *res = &hdata->res;
2042
2043 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2044
2045 mutex_lock(&hdata->hdmi_mutex);
2046 if (!hdata->powered)
2047 goto out;
2048 mutex_unlock(&hdata->hdmi_mutex);
2049
2050 /*
2051 * The TV power domain needs any condition of hdmiphy to turn off and
2052 * its reset state seems to meet the condition.
2053 */
2054 hdmiphy_conf_reset(hdata);
2055
2056 clk_disable(res->sclk_hdmi);
2057 clk_disable(res->hdmi);
2058 clk_disable(res->hdmiphy);
2059 regulator_bulk_disable(res->regul_count, res->regul_bulk);
2060
2061 pm_runtime_put_sync(hdata->dev);
2062
2063 mutex_lock(&hdata->hdmi_mutex);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002064
2065 hdata->powered = false;
2066
2067out:
2068 mutex_unlock(&hdata->hdmi_mutex);
2069}
2070
2071static void hdmi_dpms(void *ctx, int mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002072{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002073 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002074
2075 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2076
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002077 switch (mode) {
2078 case DRM_MODE_DPMS_ON:
2079 hdmi_poweron(hdata);
2080 break;
2081 case DRM_MODE_DPMS_STANDBY:
2082 case DRM_MODE_DPMS_SUSPEND:
2083 case DRM_MODE_DPMS_OFF:
2084 hdmi_poweroff(hdata);
2085 break;
2086 default:
2087 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
2088 break;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002089 }
2090}
2091
Joonyoung Shim578b6062012-04-05 20:49:26 +09002092static struct exynos_hdmi_ops hdmi_ops = {
2093 /* display */
2094 .is_connected = hdmi_is_connected,
2095 .get_edid = hdmi_get_edid,
2096 .check_timing = hdmi_check_timing,
Joonyoung Shim578b6062012-04-05 20:49:26 +09002097
2098 /* manager */
Inki Dae1de425b2012-03-16 18:47:04 +09002099 .mode_fixup = hdmi_mode_fixup,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002100 .mode_set = hdmi_mode_set,
Inki Dae1de425b2012-03-16 18:47:04 +09002101 .get_max_resol = hdmi_get_max_resol,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002102 .commit = hdmi_commit,
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002103 .dpms = hdmi_dpms,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002104};
2105
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002106static irqreturn_t hdmi_external_irq_thread(int irq, void *arg)
2107{
2108 struct exynos_drm_hdmi_context *ctx = arg;
2109 struct hdmi_context *hdata = ctx->ctx;
2110
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002111 mutex_lock(&hdata->hdmi_mutex);
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302112 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002113 mutex_unlock(&hdata->hdmi_mutex);
2114
2115 if (ctx->drm_dev)
2116 drm_helper_hpd_irq_event(ctx->drm_dev);
2117
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002118 return IRQ_HANDLED;
2119}
2120
2121static irqreturn_t hdmi_internal_irq_thread(int irq, void *arg)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002122{
2123 struct exynos_drm_hdmi_context *ctx = arg;
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002124 struct hdmi_context *hdata = ctx->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002125 u32 intc_flag;
2126
2127 intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG);
2128 /* clearing flags for HPD plug/unplug */
2129 if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002130 DRM_DEBUG_KMS("unplugged\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002131 hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
2132 HDMI_INTC_FLAG_HPD_UNPLUG);
2133 }
2134 if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002135 DRM_DEBUG_KMS("plugged\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002136 hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
2137 HDMI_INTC_FLAG_HPD_PLUG);
2138 }
2139
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002140 if (ctx->drm_dev)
Joonyoung Shim66265a22012-04-23 19:35:49 +09002141 drm_helper_hpd_irq_event(ctx->drm_dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002142
2143 return IRQ_HANDLED;
2144}
2145
2146static int __devinit hdmi_resources_init(struct hdmi_context *hdata)
2147{
2148 struct device *dev = hdata->dev;
2149 struct hdmi_resources *res = &hdata->res;
2150 static char *supply[] = {
2151 "hdmi-en",
2152 "vdd",
2153 "vdd_osc",
2154 "vdd_pll",
2155 };
2156 int i, ret;
2157
2158 DRM_DEBUG_KMS("HDMI resource init\n");
2159
Sachin Kamatadc837a2012-08-31 15:50:47 +05302160 memset(res, 0, sizeof(*res));
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002161
2162 /* get clocks, power */
2163 res->hdmi = clk_get(dev, "hdmi");
2164 if (IS_ERR_OR_NULL(res->hdmi)) {
2165 DRM_ERROR("failed to get clock 'hdmi'\n");
2166 goto fail;
2167 }
2168 res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
2169 if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
2170 DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
2171 goto fail;
2172 }
2173 res->sclk_pixel = clk_get(dev, "sclk_pixel");
2174 if (IS_ERR_OR_NULL(res->sclk_pixel)) {
2175 DRM_ERROR("failed to get clock 'sclk_pixel'\n");
2176 goto fail;
2177 }
2178 res->sclk_hdmiphy = clk_get(dev, "sclk_hdmiphy");
2179 if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) {
2180 DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
2181 goto fail;
2182 }
2183 res->hdmiphy = clk_get(dev, "hdmiphy");
2184 if (IS_ERR_OR_NULL(res->hdmiphy)) {
2185 DRM_ERROR("failed to get clock 'hdmiphy'\n");
2186 goto fail;
2187 }
2188
2189 clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
2190
2191 res->regul_bulk = kzalloc(ARRAY_SIZE(supply) *
Sachin Kamatadc837a2012-08-31 15:50:47 +05302192 sizeof(res->regul_bulk[0]), GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002193 if (!res->regul_bulk) {
2194 DRM_ERROR("failed to get memory for regulators\n");
2195 goto fail;
2196 }
2197 for (i = 0; i < ARRAY_SIZE(supply); ++i) {
2198 res->regul_bulk[i].supply = supply[i];
2199 res->regul_bulk[i].consumer = NULL;
2200 }
2201 ret = regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
2202 if (ret) {
2203 DRM_ERROR("failed to get regulators\n");
2204 goto fail;
2205 }
2206 res->regul_count = ARRAY_SIZE(supply);
2207
2208 return 0;
2209fail:
2210 DRM_ERROR("HDMI resource init - failed\n");
2211 return -ENODEV;
2212}
2213
2214static int hdmi_resources_cleanup(struct hdmi_context *hdata)
2215{
2216 struct hdmi_resources *res = &hdata->res;
2217
2218 regulator_bulk_free(res->regul_count, res->regul_bulk);
2219 /* kfree is NULL-safe */
2220 kfree(res->regul_bulk);
2221 if (!IS_ERR_OR_NULL(res->hdmiphy))
2222 clk_put(res->hdmiphy);
2223 if (!IS_ERR_OR_NULL(res->sclk_hdmiphy))
2224 clk_put(res->sclk_hdmiphy);
2225 if (!IS_ERR_OR_NULL(res->sclk_pixel))
2226 clk_put(res->sclk_pixel);
2227 if (!IS_ERR_OR_NULL(res->sclk_hdmi))
2228 clk_put(res->sclk_hdmi);
2229 if (!IS_ERR_OR_NULL(res->hdmi))
2230 clk_put(res->hdmi);
Sachin Kamatadc837a2012-08-31 15:50:47 +05302231 memset(res, 0, sizeof(*res));
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002232
2233 return 0;
2234}
2235
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002236static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;
2237
2238void hdmi_attach_ddc_client(struct i2c_client *ddc)
2239{
2240 if (ddc)
2241 hdmi_ddc = ddc;
2242}
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002243
2244void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)
2245{
2246 if (hdmiphy)
2247 hdmi_hdmiphy = hdmiphy;
2248}
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002249
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302250enum hdmi_type {
2251 HDMI_TYPE13,
2252 HDMI_TYPE14,
2253};
2254
2255static struct platform_device_id hdmi_driver_types[] = {
2256 {
2257 .name = "s5pv210-hdmi",
2258 .driver_data = HDMI_TYPE13,
2259 }, {
2260 .name = "exynos4-hdmi",
2261 .driver_data = HDMI_TYPE13,
2262 }, {
2263 .name = "exynos4-hdmi14",
2264 .driver_data = HDMI_TYPE14,
2265 }, {
2266 /* end node */
2267 }
2268};
2269
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002270static int __devinit hdmi_probe(struct platform_device *pdev)
2271{
2272 struct device *dev = &pdev->dev;
2273 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
2274 struct hdmi_context *hdata;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302275 struct s5p_hdmi_platform_data *pdata;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002276 struct resource *res;
2277 int ret;
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302278 enum hdmi_type hdmi_type;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002279
2280 DRM_DEBUG_KMS("[%d]\n", __LINE__);
2281
2282 pdata = pdev->dev.platform_data;
2283 if (!pdata) {
2284 DRM_ERROR("no platform data specified\n");
2285 return -EINVAL;
2286 }
2287
Sachin Kamata6e65072012-06-19 11:47:40 +05302288 drm_hdmi_ctx = devm_kzalloc(&pdev->dev, sizeof(*drm_hdmi_ctx),
2289 GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002290 if (!drm_hdmi_ctx) {
2291 DRM_ERROR("failed to allocate common hdmi context.\n");
2292 return -ENOMEM;
2293 }
2294
Sachin Kamata6e65072012-06-19 11:47:40 +05302295 hdata = devm_kzalloc(&pdev->dev, sizeof(struct hdmi_context),
2296 GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002297 if (!hdata) {
2298 DRM_ERROR("out of memory\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002299 return -ENOMEM;
2300 }
2301
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002302 mutex_init(&hdata->hdmi_mutex);
2303
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002304 drm_hdmi_ctx->ctx = (void *)hdata;
2305 hdata->parent_ctx = (void *)drm_hdmi_ctx;
2306
2307 platform_set_drvdata(pdev, drm_hdmi_ctx);
2308
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302309 hdmi_type = platform_get_device_id(pdev)->driver_data;
2310 hdata->is_v13 = (hdmi_type == HDMI_TYPE13);
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302311 hdata->hpd_gpio = pdata->hpd_gpio;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002312 hdata->dev = dev;
2313
2314 ret = hdmi_resources_init(hdata);
2315 if (ret) {
2316 ret = -EINVAL;
2317 goto err_data;
2318 }
2319
2320 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002321
Sachin Kamata6e65072012-06-19 11:47:40 +05302322 hdata->regs = devm_request_and_ioremap(&pdev->dev, res);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002323 if (!hdata->regs) {
2324 DRM_ERROR("failed to map registers\n");
2325 ret = -ENXIO;
Sachin Kamata6e65072012-06-19 11:47:40 +05302326 goto err_resource;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002327 }
2328
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302329 ret = gpio_request(hdata->hpd_gpio, "HPD");
2330 if (ret) {
2331 DRM_ERROR("failed to request HPD gpio\n");
2332 goto err_resource;
2333 }
2334
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002335 /* DDC i2c driver */
2336 if (i2c_add_driver(&ddc_driver)) {
2337 DRM_ERROR("failed to register ddc i2c driver\n");
2338 ret = -ENOENT;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302339 goto err_gpio;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002340 }
2341
2342 hdata->ddc_port = hdmi_ddc;
2343
2344 /* hdmiphy i2c driver */
2345 if (i2c_add_driver(&hdmiphy_driver)) {
2346 DRM_ERROR("failed to register hdmiphy i2c driver\n");
2347 ret = -ENOENT;
2348 goto err_ddc;
2349 }
2350
2351 hdata->hdmiphy_port = hdmi_hdmiphy;
2352
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302353 hdata->external_irq = gpio_to_irq(hdata->hpd_gpio);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002354 if (hdata->external_irq < 0) {
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302355 DRM_ERROR("failed to get GPIO external irq\n");
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002356 ret = hdata->external_irq;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002357 goto err_hdmiphy;
2358 }
2359
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302360 hdata->internal_irq = platform_get_irq(pdev, 0);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002361 if (hdata->internal_irq < 0) {
2362 DRM_ERROR("failed to get platform internal irq\n");
2363 ret = hdata->internal_irq;
Joonyoung Shim66265a22012-04-23 19:35:49 +09002364 goto err_hdmiphy;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002365 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002366
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302367 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2368
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002369 ret = request_threaded_irq(hdata->external_irq, NULL,
2370 hdmi_external_irq_thread, IRQF_TRIGGER_RISING |
2371 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
2372 "hdmi_external", drm_hdmi_ctx);
2373 if (ret) {
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302374 DRM_ERROR("failed to register hdmi external interrupt\n");
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002375 goto err_hdmiphy;
2376 }
2377
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002378 ret = request_threaded_irq(hdata->internal_irq, NULL,
2379 hdmi_internal_irq_thread, IRQF_ONESHOT,
2380 "hdmi_internal", drm_hdmi_ctx);
2381 if (ret) {
2382 DRM_ERROR("failed to register hdmi internal interrupt\n");
2383 goto err_free_irq;
2384 }
2385
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002386 /* register specific callbacks to common hdmi. */
Joonyoung Shim578b6062012-04-05 20:49:26 +09002387 exynos_hdmi_ops_register(&hdmi_ops);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002388
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002389 pm_runtime_enable(dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002390
2391 return 0;
2392
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002393err_free_irq:
2394 free_irq(hdata->external_irq, drm_hdmi_ctx);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002395err_hdmiphy:
2396 i2c_del_driver(&hdmiphy_driver);
2397err_ddc:
2398 i2c_del_driver(&ddc_driver);
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302399err_gpio:
2400 gpio_free(hdata->hpd_gpio);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002401err_resource:
2402 hdmi_resources_cleanup(hdata);
2403err_data:
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002404 return ret;
2405}
2406
2407static int __devexit hdmi_remove(struct platform_device *pdev)
2408{
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002409 struct device *dev = &pdev->dev;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002410 struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev);
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002411 struct hdmi_context *hdata = ctx->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002412
2413 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2414
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002415 pm_runtime_disable(dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002416
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002417 free_irq(hdata->internal_irq, hdata);
Tomasz Stanislawski07c8bdd2012-10-04 20:48:45 +05302418 free_irq(hdata->external_irq, hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002419
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302420 gpio_free(hdata->hpd_gpio);
2421
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002422 hdmi_resources_cleanup(hdata);
2423
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002424 /* hdmiphy i2c driver */
2425 i2c_del_driver(&hdmiphy_driver);
2426 /* DDC i2c driver */
2427 i2c_del_driver(&ddc_driver);
2428
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002429 return 0;
2430}
2431
Joonyoung Shimab27af82012-04-23 19:35:51 +09002432#ifdef CONFIG_PM_SLEEP
2433static int hdmi_suspend(struct device *dev)
2434{
2435 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2436 struct hdmi_context *hdata = ctx->ctx;
2437
2438 disable_irq(hdata->internal_irq);
2439 disable_irq(hdata->external_irq);
2440
2441 hdata->hpd = false;
2442 if (ctx->drm_dev)
2443 drm_helper_hpd_irq_event(ctx->drm_dev);
2444
2445 hdmi_poweroff(hdata);
2446
2447 return 0;
2448}
2449
2450static int hdmi_resume(struct device *dev)
2451{
2452 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2453 struct hdmi_context *hdata = ctx->ctx;
2454
2455 enable_irq(hdata->external_irq);
2456 enable_irq(hdata->internal_irq);
2457 return 0;
2458}
2459#endif
2460
2461static SIMPLE_DEV_PM_OPS(hdmi_pm_ops, hdmi_suspend, hdmi_resume);
2462
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002463struct platform_driver hdmi_driver = {
2464 .probe = hdmi_probe,
2465 .remove = __devexit_p(hdmi_remove),
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302466 .id_table = hdmi_driver_types,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002467 .driver = {
2468 .name = "exynos4-hdmi",
2469 .owner = THIS_MODULE,
Joonyoung Shimab27af82012-04-23 19:35:51 +09002470 .pm = &hdmi_pm_ops,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002471 },
2472};