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