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