blob: 6716ecd3b3e983dfe5327d7ea1dff4b09ffa8ea8 [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
David Howells760285e2012-10-02 18:01:07 +010017#include <drm/drmP.h>
18#include <drm/drm_edid.h>
19#include <drm/drm_crtc_helper.h>
Seung-Woo Kimd8408322011-12-21 17:39:39 +090020
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>
Rahul Sharma22c4f422012-10-04 20:48:55 +053035#include <linux/io.h>
36#include <linux/of_gpio.h>
37#include <plat/gpio-cfg.h>
Seung-Woo Kimd8408322011-12-21 17:39:39 +090038
39#include <drm/exynos_drm.h>
40
41#include "exynos_drm_drv.h"
42#include "exynos_drm_hdmi.h"
43
44#include "exynos_hdmi.h"
45
Tomasz Stanislawskifca57122012-10-04 20:48:46 +053046#include <linux/gpio.h>
47#include <media/s5p_hdmi.h>
48
Inki Dae1de425b2012-03-16 18:47:04 +090049#define MAX_WIDTH 1920
50#define MAX_HEIGHT 1080
Seung-Woo Kimd8408322011-12-21 17:39:39 +090051#define get_hdmi_context(dev) platform_get_drvdata(to_platform_device(dev))
52
Rahul Sharma5a325072012-10-04 20:48:54 +053053enum hdmi_type {
54 HDMI_TYPE13,
55 HDMI_TYPE14,
56};
57
Joonyoung Shim590f4182012-03-16 18:47:14 +090058struct hdmi_resources {
59 struct clk *hdmi;
60 struct clk *sclk_hdmi;
61 struct clk *sclk_pixel;
62 struct clk *sclk_hdmiphy;
63 struct clk *hdmiphy;
64 struct regulator_bulk_data *regul_bulk;
65 int regul_count;
66};
67
68struct hdmi_context {
69 struct device *dev;
70 struct drm_device *drm_dev;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +090071 bool hpd;
72 bool powered;
Seung-Woo Kim872d20d62012-04-24 17:39:15 +090073 bool dvi_mode;
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +090074 struct mutex hdmi_mutex;
Joonyoung Shim590f4182012-03-16 18:47:14 +090075
Joonyoung Shim590f4182012-03-16 18:47:14 +090076 void __iomem *regs;
Inki Dae1055b392012-10-19 17:37:35 +090077 void *parent_ctx;
Tomasz Stanislawski07c8bdd2012-10-04 20:48:45 +053078 int external_irq;
79 int internal_irq;
Joonyoung Shim590f4182012-03-16 18:47:14 +090080
81 struct i2c_client *ddc_port;
82 struct i2c_client *hdmiphy_port;
83
84 /* current hdmiphy conf index */
85 int cur_conf;
86
87 struct hdmi_resources res;
Joonyoung Shim7ecd34e2012-04-23 19:35:47 +090088
Tomasz Stanislawskifca57122012-10-04 20:48:46 +053089 int hpd_gpio;
Rahul Sharma5a325072012-10-04 20:48:54 +053090
91 enum hdmi_type type;
Joonyoung Shim590f4182012-03-16 18:47:14 +090092};
93
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +090094/* HDMI Version 1.3 */
95static const u8 hdmiphy_v13_conf27[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +090096 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
97 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
98 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
99 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
100};
101
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900102static const u8 hdmiphy_v13_conf27_027[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900103 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
104 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
105 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
106 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00,
107};
108
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900109static const u8 hdmiphy_v13_conf74_175[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900110 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
111 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
112 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
113 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
114};
115
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900116static const u8 hdmiphy_v13_conf74_25[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900117 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
118 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
119 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xe0,
120 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
121};
122
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900123static const u8 hdmiphy_v13_conf148_5[32] = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900124 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
125 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
126 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
127 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
128};
129
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900130struct hdmi_v13_tg_regs {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900131 u8 cmd;
132 u8 h_fsz_l;
133 u8 h_fsz_h;
134 u8 hact_st_l;
135 u8 hact_st_h;
136 u8 hact_sz_l;
137 u8 hact_sz_h;
138 u8 v_fsz_l;
139 u8 v_fsz_h;
140 u8 vsync_l;
141 u8 vsync_h;
142 u8 vsync2_l;
143 u8 vsync2_h;
144 u8 vact_st_l;
145 u8 vact_st_h;
146 u8 vact_sz_l;
147 u8 vact_sz_h;
148 u8 field_chg_l;
149 u8 field_chg_h;
150 u8 vact_st2_l;
151 u8 vact_st2_h;
152 u8 vsync_top_hdmi_l;
153 u8 vsync_top_hdmi_h;
154 u8 vsync_bot_hdmi_l;
155 u8 vsync_bot_hdmi_h;
156 u8 field_top_hdmi_l;
157 u8 field_top_hdmi_h;
158 u8 field_bot_hdmi_l;
159 u8 field_bot_hdmi_h;
160};
161
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900162struct hdmi_v13_core_regs {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900163 u8 h_blank[2];
164 u8 v_blank[3];
165 u8 h_v_line[3];
166 u8 vsync_pol[1];
167 u8 int_pro_mode[1];
168 u8 v_blank_f[3];
169 u8 h_sync_gen[3];
170 u8 v_sync_gen1[3];
171 u8 v_sync_gen2[3];
172 u8 v_sync_gen3[3];
173};
174
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900175struct hdmi_v13_preset_conf {
176 struct hdmi_v13_core_regs core;
177 struct hdmi_v13_tg_regs tg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900178};
179
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900180struct hdmi_v13_conf {
181 int width;
182 int height;
183 int vrefresh;
184 bool interlace;
185 const u8 *hdmiphy_data;
186 const struct hdmi_v13_preset_conf *conf;
187};
188
189static const struct hdmi_v13_preset_conf hdmi_v13_conf_480p = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900190 .core = {
191 .h_blank = {0x8a, 0x00},
192 .v_blank = {0x0d, 0x6a, 0x01},
193 .h_v_line = {0x0d, 0xa2, 0x35},
194 .vsync_pol = {0x01},
195 .int_pro_mode = {0x00},
196 .v_blank_f = {0x00, 0x00, 0x00},
197 .h_sync_gen = {0x0e, 0x30, 0x11},
198 .v_sync_gen1 = {0x0f, 0x90, 0x00},
199 /* other don't care */
200 },
201 .tg = {
202 0x00, /* cmd */
203 0x5a, 0x03, /* h_fsz */
204 0x8a, 0x00, 0xd0, 0x02, /* hact */
205 0x0d, 0x02, /* v_fsz */
206 0x01, 0x00, 0x33, 0x02, /* vsync */
207 0x2d, 0x00, 0xe0, 0x01, /* vact */
208 0x33, 0x02, /* field_chg */
209 0x49, 0x02, /* vact_st2 */
210 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
211 0x01, 0x00, 0x33, 0x02, /* field top/bot */
212 },
213};
214
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900215static const struct hdmi_v13_preset_conf hdmi_v13_conf_720p60 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900216 .core = {
217 .h_blank = {0x72, 0x01},
218 .v_blank = {0xee, 0xf2, 0x00},
219 .h_v_line = {0xee, 0x22, 0x67},
220 .vsync_pol = {0x00},
221 .int_pro_mode = {0x00},
222 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
223 .h_sync_gen = {0x6c, 0x50, 0x02},
224 .v_sync_gen1 = {0x0a, 0x50, 0x00},
225 .v_sync_gen2 = {0x01, 0x10, 0x00},
226 .v_sync_gen3 = {0x01, 0x10, 0x00},
227 /* other don't care */
228 },
229 .tg = {
230 0x00, /* cmd */
231 0x72, 0x06, /* h_fsz */
232 0x71, 0x01, 0x01, 0x05, /* hact */
233 0xee, 0x02, /* v_fsz */
234 0x01, 0x00, 0x33, 0x02, /* vsync */
235 0x1e, 0x00, 0xd0, 0x02, /* vact */
236 0x33, 0x02, /* field_chg */
237 0x49, 0x02, /* vact_st2 */
238 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
239 0x01, 0x00, 0x33, 0x02, /* field top/bot */
240 },
241};
242
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900243static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i50 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900244 .core = {
245 .h_blank = {0xd0, 0x02},
246 .v_blank = {0x32, 0xB2, 0x00},
247 .h_v_line = {0x65, 0x04, 0xa5},
248 .vsync_pol = {0x00},
249 .int_pro_mode = {0x01},
250 .v_blank_f = {0x49, 0x2A, 0x23},
251 .h_sync_gen = {0x0E, 0xEA, 0x08},
252 .v_sync_gen1 = {0x07, 0x20, 0x00},
253 .v_sync_gen2 = {0x39, 0x42, 0x23},
254 .v_sync_gen3 = {0x38, 0x87, 0x73},
255 /* other don't care */
256 },
257 .tg = {
258 0x00, /* cmd */
259 0x50, 0x0A, /* h_fsz */
260 0xCF, 0x02, 0x81, 0x07, /* hact */
261 0x65, 0x04, /* v_fsz */
262 0x01, 0x00, 0x33, 0x02, /* vsync */
263 0x16, 0x00, 0x1c, 0x02, /* vact */
264 0x33, 0x02, /* field_chg */
265 0x49, 0x02, /* vact_st2 */
266 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
267 0x01, 0x00, 0x33, 0x02, /* field top/bot */
268 },
269};
270
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900271static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p50 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900272 .core = {
273 .h_blank = {0xd0, 0x02},
274 .v_blank = {0x65, 0x6c, 0x01},
275 .h_v_line = {0x65, 0x04, 0xa5},
276 .vsync_pol = {0x00},
277 .int_pro_mode = {0x00},
278 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
279 .h_sync_gen = {0x0e, 0xea, 0x08},
280 .v_sync_gen1 = {0x09, 0x40, 0x00},
281 .v_sync_gen2 = {0x01, 0x10, 0x00},
282 .v_sync_gen3 = {0x01, 0x10, 0x00},
283 /* other don't care */
284 },
285 .tg = {
286 0x00, /* cmd */
287 0x50, 0x0A, /* h_fsz */
288 0xCF, 0x02, 0x81, 0x07, /* hact */
289 0x65, 0x04, /* v_fsz */
290 0x01, 0x00, 0x33, 0x02, /* vsync */
291 0x2d, 0x00, 0x38, 0x04, /* vact */
292 0x33, 0x02, /* field_chg */
293 0x48, 0x02, /* vact_st2 */
294 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
295 0x01, 0x00, 0x33, 0x02, /* field top/bot */
296 },
297};
298
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900299static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080i60 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900300 .core = {
301 .h_blank = {0x18, 0x01},
302 .v_blank = {0x32, 0xB2, 0x00},
303 .h_v_line = {0x65, 0x84, 0x89},
304 .vsync_pol = {0x00},
305 .int_pro_mode = {0x01},
306 .v_blank_f = {0x49, 0x2A, 0x23},
307 .h_sync_gen = {0x56, 0x08, 0x02},
308 .v_sync_gen1 = {0x07, 0x20, 0x00},
309 .v_sync_gen2 = {0x39, 0x42, 0x23},
310 .v_sync_gen3 = {0xa4, 0x44, 0x4a},
311 /* other don't care */
312 },
313 .tg = {
314 0x00, /* cmd */
315 0x98, 0x08, /* h_fsz */
316 0x17, 0x01, 0x81, 0x07, /* hact */
317 0x65, 0x04, /* v_fsz */
318 0x01, 0x00, 0x33, 0x02, /* vsync */
319 0x16, 0x00, 0x1c, 0x02, /* vact */
320 0x33, 0x02, /* field_chg */
321 0x49, 0x02, /* vact_st2 */
322 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
323 0x01, 0x00, 0x33, 0x02, /* field top/bot */
324 },
325};
326
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900327static const struct hdmi_v13_preset_conf hdmi_v13_conf_1080p60 = {
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900328 .core = {
329 .h_blank = {0x18, 0x01},
330 .v_blank = {0x65, 0x6c, 0x01},
331 .h_v_line = {0x65, 0x84, 0x89},
332 .vsync_pol = {0x00},
333 .int_pro_mode = {0x00},
334 .v_blank_f = {0x00, 0x00, 0x00}, /* don't care */
335 .h_sync_gen = {0x56, 0x08, 0x02},
336 .v_sync_gen1 = {0x09, 0x40, 0x00},
337 .v_sync_gen2 = {0x01, 0x10, 0x00},
338 .v_sync_gen3 = {0x01, 0x10, 0x00},
339 /* other don't care */
340 },
341 .tg = {
342 0x00, /* cmd */
343 0x98, 0x08, /* h_fsz */
344 0x17, 0x01, 0x81, 0x07, /* hact */
345 0x65, 0x04, /* v_fsz */
346 0x01, 0x00, 0x33, 0x02, /* vsync */
347 0x2d, 0x00, 0x38, 0x04, /* vact */
348 0x33, 0x02, /* field_chg */
349 0x48, 0x02, /* vact_st2 */
350 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
351 0x01, 0x00, 0x33, 0x02, /* field top/bot */
352 },
353};
354
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900355static const struct hdmi_v13_conf hdmi_v13_confs[] = {
356 { 1280, 720, 60, false, hdmiphy_v13_conf74_25, &hdmi_v13_conf_720p60 },
357 { 1280, 720, 50, false, hdmiphy_v13_conf74_25, &hdmi_v13_conf_720p60 },
358 { 720, 480, 60, false, hdmiphy_v13_conf27_027, &hdmi_v13_conf_480p },
359 { 1920, 1080, 50, true, hdmiphy_v13_conf74_25, &hdmi_v13_conf_1080i50 },
360 { 1920, 1080, 50, false, hdmiphy_v13_conf148_5,
361 &hdmi_v13_conf_1080p50 },
362 { 1920, 1080, 60, true, hdmiphy_v13_conf74_25, &hdmi_v13_conf_1080i60 },
363 { 1920, 1080, 60, false, hdmiphy_v13_conf148_5,
364 &hdmi_v13_conf_1080p60 },
365};
366
367/* HDMI Version 1.4 */
368static const u8 hdmiphy_conf27_027[32] = {
369 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08,
370 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80,
371 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
372 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00,
373};
374
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900375static const u8 hdmiphy_conf74_176[32] = {
376 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x5b, 0xef, 0x08,
377 0x81, 0xa0, 0xb9, 0xd8, 0x45, 0xa0, 0xac, 0x80,
378 0x5a, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
379 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
380};
381
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900382static const u8 hdmiphy_conf74_25[32] = {
383 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08,
384 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
385 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
386 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00,
387};
388
389static const u8 hdmiphy_conf148_5[32] = {
390 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08,
391 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80,
392 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86,
393 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00,
394};
395
396struct hdmi_tg_regs {
397 u8 cmd;
398 u8 h_fsz_l;
399 u8 h_fsz_h;
400 u8 hact_st_l;
401 u8 hact_st_h;
402 u8 hact_sz_l;
403 u8 hact_sz_h;
404 u8 v_fsz_l;
405 u8 v_fsz_h;
406 u8 vsync_l;
407 u8 vsync_h;
408 u8 vsync2_l;
409 u8 vsync2_h;
410 u8 vact_st_l;
411 u8 vact_st_h;
412 u8 vact_sz_l;
413 u8 vact_sz_h;
414 u8 field_chg_l;
415 u8 field_chg_h;
416 u8 vact_st2_l;
417 u8 vact_st2_h;
418 u8 vact_st3_l;
419 u8 vact_st3_h;
420 u8 vact_st4_l;
421 u8 vact_st4_h;
422 u8 vsync_top_hdmi_l;
423 u8 vsync_top_hdmi_h;
424 u8 vsync_bot_hdmi_l;
425 u8 vsync_bot_hdmi_h;
426 u8 field_top_hdmi_l;
427 u8 field_top_hdmi_h;
428 u8 field_bot_hdmi_l;
429 u8 field_bot_hdmi_h;
430 u8 tg_3d;
431};
432
433struct hdmi_core_regs {
434 u8 h_blank[2];
435 u8 v2_blank[2];
436 u8 v1_blank[2];
437 u8 v_line[2];
438 u8 h_line[2];
439 u8 hsync_pol[1];
440 u8 vsync_pol[1];
441 u8 int_pro_mode[1];
442 u8 v_blank_f0[2];
443 u8 v_blank_f1[2];
444 u8 h_sync_start[2];
445 u8 h_sync_end[2];
446 u8 v_sync_line_bef_2[2];
447 u8 v_sync_line_bef_1[2];
448 u8 v_sync_line_aft_2[2];
449 u8 v_sync_line_aft_1[2];
450 u8 v_sync_line_aft_pxl_2[2];
451 u8 v_sync_line_aft_pxl_1[2];
452 u8 v_blank_f2[2]; /* for 3D mode */
453 u8 v_blank_f3[2]; /* for 3D mode */
454 u8 v_blank_f4[2]; /* for 3D mode */
455 u8 v_blank_f5[2]; /* for 3D mode */
456 u8 v_sync_line_aft_3[2];
457 u8 v_sync_line_aft_4[2];
458 u8 v_sync_line_aft_5[2];
459 u8 v_sync_line_aft_6[2];
460 u8 v_sync_line_aft_pxl_3[2];
461 u8 v_sync_line_aft_pxl_4[2];
462 u8 v_sync_line_aft_pxl_5[2];
463 u8 v_sync_line_aft_pxl_6[2];
464 u8 vact_space_1[2];
465 u8 vact_space_2[2];
466 u8 vact_space_3[2];
467 u8 vact_space_4[2];
468 u8 vact_space_5[2];
469 u8 vact_space_6[2];
470};
471
472struct hdmi_preset_conf {
473 struct hdmi_core_regs core;
474 struct hdmi_tg_regs tg;
475};
476
477struct hdmi_conf {
478 int width;
479 int height;
480 int vrefresh;
481 bool interlace;
482 const u8 *hdmiphy_data;
483 const struct hdmi_preset_conf *conf;
484};
485
486static const struct hdmi_preset_conf hdmi_conf_480p60 = {
487 .core = {
488 .h_blank = {0x8a, 0x00},
489 .v2_blank = {0x0d, 0x02},
490 .v1_blank = {0x2d, 0x00},
491 .v_line = {0x0d, 0x02},
492 .h_line = {0x5a, 0x03},
493 .hsync_pol = {0x01},
494 .vsync_pol = {0x01},
495 .int_pro_mode = {0x00},
496 .v_blank_f0 = {0xff, 0xff},
497 .v_blank_f1 = {0xff, 0xff},
498 .h_sync_start = {0x0e, 0x00},
499 .h_sync_end = {0x4c, 0x00},
500 .v_sync_line_bef_2 = {0x0f, 0x00},
501 .v_sync_line_bef_1 = {0x09, 0x00},
502 .v_sync_line_aft_2 = {0xff, 0xff},
503 .v_sync_line_aft_1 = {0xff, 0xff},
504 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
505 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
506 .v_blank_f2 = {0xff, 0xff},
507 .v_blank_f3 = {0xff, 0xff},
508 .v_blank_f4 = {0xff, 0xff},
509 .v_blank_f5 = {0xff, 0xff},
510 .v_sync_line_aft_3 = {0xff, 0xff},
511 .v_sync_line_aft_4 = {0xff, 0xff},
512 .v_sync_line_aft_5 = {0xff, 0xff},
513 .v_sync_line_aft_6 = {0xff, 0xff},
514 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
515 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
516 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
517 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
518 .vact_space_1 = {0xff, 0xff},
519 .vact_space_2 = {0xff, 0xff},
520 .vact_space_3 = {0xff, 0xff},
521 .vact_space_4 = {0xff, 0xff},
522 .vact_space_5 = {0xff, 0xff},
523 .vact_space_6 = {0xff, 0xff},
524 /* other don't care */
525 },
526 .tg = {
527 0x00, /* cmd */
528 0x5a, 0x03, /* h_fsz */
529 0x8a, 0x00, 0xd0, 0x02, /* hact */
530 0x0d, 0x02, /* v_fsz */
531 0x01, 0x00, 0x33, 0x02, /* vsync */
532 0x2d, 0x00, 0xe0, 0x01, /* vact */
533 0x33, 0x02, /* field_chg */
534 0x48, 0x02, /* vact_st2 */
535 0x00, 0x00, /* vact_st3 */
536 0x00, 0x00, /* vact_st4 */
537 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
538 0x01, 0x00, 0x33, 0x02, /* field top/bot */
539 0x00, /* 3d FP */
540 },
541};
542
543static const struct hdmi_preset_conf hdmi_conf_720p50 = {
544 .core = {
545 .h_blank = {0xbc, 0x02},
546 .v2_blank = {0xee, 0x02},
547 .v1_blank = {0x1e, 0x00},
548 .v_line = {0xee, 0x02},
549 .h_line = {0xbc, 0x07},
550 .hsync_pol = {0x00},
551 .vsync_pol = {0x00},
552 .int_pro_mode = {0x00},
553 .v_blank_f0 = {0xff, 0xff},
554 .v_blank_f1 = {0xff, 0xff},
555 .h_sync_start = {0xb6, 0x01},
556 .h_sync_end = {0xde, 0x01},
557 .v_sync_line_bef_2 = {0x0a, 0x00},
558 .v_sync_line_bef_1 = {0x05, 0x00},
559 .v_sync_line_aft_2 = {0xff, 0xff},
560 .v_sync_line_aft_1 = {0xff, 0xff},
561 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
562 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
563 .v_blank_f2 = {0xff, 0xff},
564 .v_blank_f3 = {0xff, 0xff},
565 .v_blank_f4 = {0xff, 0xff},
566 .v_blank_f5 = {0xff, 0xff},
567 .v_sync_line_aft_3 = {0xff, 0xff},
568 .v_sync_line_aft_4 = {0xff, 0xff},
569 .v_sync_line_aft_5 = {0xff, 0xff},
570 .v_sync_line_aft_6 = {0xff, 0xff},
571 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
572 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
573 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
574 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
575 .vact_space_1 = {0xff, 0xff},
576 .vact_space_2 = {0xff, 0xff},
577 .vact_space_3 = {0xff, 0xff},
578 .vact_space_4 = {0xff, 0xff},
579 .vact_space_5 = {0xff, 0xff},
580 .vact_space_6 = {0xff, 0xff},
581 /* other don't care */
582 },
583 .tg = {
584 0x00, /* cmd */
585 0xbc, 0x07, /* h_fsz */
586 0xbc, 0x02, 0x00, 0x05, /* hact */
587 0xee, 0x02, /* v_fsz */
588 0x01, 0x00, 0x33, 0x02, /* vsync */
589 0x1e, 0x00, 0xd0, 0x02, /* vact */
590 0x33, 0x02, /* field_chg */
591 0x48, 0x02, /* vact_st2 */
592 0x00, 0x00, /* vact_st3 */
593 0x00, 0x00, /* vact_st4 */
594 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
595 0x01, 0x00, 0x33, 0x02, /* field top/bot */
596 0x00, /* 3d FP */
597 },
598};
599
600static const struct hdmi_preset_conf hdmi_conf_720p60 = {
601 .core = {
602 .h_blank = {0x72, 0x01},
603 .v2_blank = {0xee, 0x02},
604 .v1_blank = {0x1e, 0x00},
605 .v_line = {0xee, 0x02},
606 .h_line = {0x72, 0x06},
607 .hsync_pol = {0x00},
608 .vsync_pol = {0x00},
609 .int_pro_mode = {0x00},
610 .v_blank_f0 = {0xff, 0xff},
611 .v_blank_f1 = {0xff, 0xff},
612 .h_sync_start = {0x6c, 0x00},
613 .h_sync_end = {0x94, 0x00},
614 .v_sync_line_bef_2 = {0x0a, 0x00},
615 .v_sync_line_bef_1 = {0x05, 0x00},
616 .v_sync_line_aft_2 = {0xff, 0xff},
617 .v_sync_line_aft_1 = {0xff, 0xff},
618 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
619 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
620 .v_blank_f2 = {0xff, 0xff},
621 .v_blank_f3 = {0xff, 0xff},
622 .v_blank_f4 = {0xff, 0xff},
623 .v_blank_f5 = {0xff, 0xff},
624 .v_sync_line_aft_3 = {0xff, 0xff},
625 .v_sync_line_aft_4 = {0xff, 0xff},
626 .v_sync_line_aft_5 = {0xff, 0xff},
627 .v_sync_line_aft_6 = {0xff, 0xff},
628 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
629 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
630 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
631 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
632 .vact_space_1 = {0xff, 0xff},
633 .vact_space_2 = {0xff, 0xff},
634 .vact_space_3 = {0xff, 0xff},
635 .vact_space_4 = {0xff, 0xff},
636 .vact_space_5 = {0xff, 0xff},
637 .vact_space_6 = {0xff, 0xff},
638 /* other don't care */
639 },
640 .tg = {
641 0x00, /* cmd */
642 0x72, 0x06, /* h_fsz */
643 0x72, 0x01, 0x00, 0x05, /* hact */
644 0xee, 0x02, /* v_fsz */
645 0x01, 0x00, 0x33, 0x02, /* vsync */
646 0x1e, 0x00, 0xd0, 0x02, /* vact */
647 0x33, 0x02, /* field_chg */
648 0x48, 0x02, /* vact_st2 */
649 0x00, 0x00, /* vact_st3 */
650 0x00, 0x00, /* vact_st4 */
651 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
652 0x01, 0x00, 0x33, 0x02, /* field top/bot */
653 0x00, /* 3d FP */
654 },
655};
656
657static const struct hdmi_preset_conf hdmi_conf_1080i50 = {
658 .core = {
659 .h_blank = {0xd0, 0x02},
660 .v2_blank = {0x32, 0x02},
661 .v1_blank = {0x16, 0x00},
662 .v_line = {0x65, 0x04},
663 .h_line = {0x50, 0x0a},
664 .hsync_pol = {0x00},
665 .vsync_pol = {0x00},
666 .int_pro_mode = {0x01},
667 .v_blank_f0 = {0x49, 0x02},
668 .v_blank_f1 = {0x65, 0x04},
669 .h_sync_start = {0x0e, 0x02},
670 .h_sync_end = {0x3a, 0x02},
671 .v_sync_line_bef_2 = {0x07, 0x00},
672 .v_sync_line_bef_1 = {0x02, 0x00},
673 .v_sync_line_aft_2 = {0x39, 0x02},
674 .v_sync_line_aft_1 = {0x34, 0x02},
675 .v_sync_line_aft_pxl_2 = {0x38, 0x07},
676 .v_sync_line_aft_pxl_1 = {0x38, 0x07},
677 .v_blank_f2 = {0xff, 0xff},
678 .v_blank_f3 = {0xff, 0xff},
679 .v_blank_f4 = {0xff, 0xff},
680 .v_blank_f5 = {0xff, 0xff},
681 .v_sync_line_aft_3 = {0xff, 0xff},
682 .v_sync_line_aft_4 = {0xff, 0xff},
683 .v_sync_line_aft_5 = {0xff, 0xff},
684 .v_sync_line_aft_6 = {0xff, 0xff},
685 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
686 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
687 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
688 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
689 .vact_space_1 = {0xff, 0xff},
690 .vact_space_2 = {0xff, 0xff},
691 .vact_space_3 = {0xff, 0xff},
692 .vact_space_4 = {0xff, 0xff},
693 .vact_space_5 = {0xff, 0xff},
694 .vact_space_6 = {0xff, 0xff},
695 /* other don't care */
696 },
697 .tg = {
698 0x00, /* cmd */
699 0x50, 0x0a, /* h_fsz */
700 0xd0, 0x02, 0x80, 0x07, /* hact */
701 0x65, 0x04, /* v_fsz */
702 0x01, 0x00, 0x33, 0x02, /* vsync */
703 0x16, 0x00, 0x1c, 0x02, /* vact */
704 0x33, 0x02, /* field_chg */
705 0x49, 0x02, /* vact_st2 */
706 0x00, 0x00, /* vact_st3 */
707 0x00, 0x00, /* vact_st4 */
708 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
709 0x01, 0x00, 0x33, 0x02, /* field top/bot */
710 0x00, /* 3d FP */
711 },
712};
713
714static const struct hdmi_preset_conf hdmi_conf_1080i60 = {
715 .core = {
716 .h_blank = {0x18, 0x01},
717 .v2_blank = {0x32, 0x02},
718 .v1_blank = {0x16, 0x00},
719 .v_line = {0x65, 0x04},
720 .h_line = {0x98, 0x08},
721 .hsync_pol = {0x00},
722 .vsync_pol = {0x00},
723 .int_pro_mode = {0x01},
724 .v_blank_f0 = {0x49, 0x02},
725 .v_blank_f1 = {0x65, 0x04},
726 .h_sync_start = {0x56, 0x00},
727 .h_sync_end = {0x82, 0x00},
728 .v_sync_line_bef_2 = {0x07, 0x00},
729 .v_sync_line_bef_1 = {0x02, 0x00},
730 .v_sync_line_aft_2 = {0x39, 0x02},
731 .v_sync_line_aft_1 = {0x34, 0x02},
732 .v_sync_line_aft_pxl_2 = {0xa4, 0x04},
733 .v_sync_line_aft_pxl_1 = {0xa4, 0x04},
734 .v_blank_f2 = {0xff, 0xff},
735 .v_blank_f3 = {0xff, 0xff},
736 .v_blank_f4 = {0xff, 0xff},
737 .v_blank_f5 = {0xff, 0xff},
738 .v_sync_line_aft_3 = {0xff, 0xff},
739 .v_sync_line_aft_4 = {0xff, 0xff},
740 .v_sync_line_aft_5 = {0xff, 0xff},
741 .v_sync_line_aft_6 = {0xff, 0xff},
742 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
743 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
744 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
745 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
746 .vact_space_1 = {0xff, 0xff},
747 .vact_space_2 = {0xff, 0xff},
748 .vact_space_3 = {0xff, 0xff},
749 .vact_space_4 = {0xff, 0xff},
750 .vact_space_5 = {0xff, 0xff},
751 .vact_space_6 = {0xff, 0xff},
752 /* other don't care */
753 },
754 .tg = {
755 0x00, /* cmd */
756 0x98, 0x08, /* h_fsz */
757 0x18, 0x01, 0x80, 0x07, /* hact */
758 0x65, 0x04, /* v_fsz */
759 0x01, 0x00, 0x33, 0x02, /* vsync */
760 0x16, 0x00, 0x1c, 0x02, /* vact */
761 0x33, 0x02, /* field_chg */
762 0x49, 0x02, /* vact_st2 */
763 0x00, 0x00, /* vact_st3 */
764 0x00, 0x00, /* vact_st4 */
765 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */
766 0x01, 0x00, 0x33, 0x02, /* field top/bot */
767 0x00, /* 3d FP */
768 },
769};
770
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900771static const struct hdmi_preset_conf hdmi_conf_1080p30 = {
772 .core = {
773 .h_blank = {0x18, 0x01},
774 .v2_blank = {0x65, 0x04},
775 .v1_blank = {0x2d, 0x00},
776 .v_line = {0x65, 0x04},
777 .h_line = {0x98, 0x08},
778 .hsync_pol = {0x00},
779 .vsync_pol = {0x00},
780 .int_pro_mode = {0x00},
781 .v_blank_f0 = {0xff, 0xff},
782 .v_blank_f1 = {0xff, 0xff},
783 .h_sync_start = {0x56, 0x00},
784 .h_sync_end = {0x82, 0x00},
785 .v_sync_line_bef_2 = {0x09, 0x00},
786 .v_sync_line_bef_1 = {0x04, 0x00},
787 .v_sync_line_aft_2 = {0xff, 0xff},
788 .v_sync_line_aft_1 = {0xff, 0xff},
789 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
790 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
791 .v_blank_f2 = {0xff, 0xff},
792 .v_blank_f3 = {0xff, 0xff},
793 .v_blank_f4 = {0xff, 0xff},
794 .v_blank_f5 = {0xff, 0xff},
795 .v_sync_line_aft_3 = {0xff, 0xff},
796 .v_sync_line_aft_4 = {0xff, 0xff},
797 .v_sync_line_aft_5 = {0xff, 0xff},
798 .v_sync_line_aft_6 = {0xff, 0xff},
799 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
800 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
801 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
802 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
803 .vact_space_1 = {0xff, 0xff},
804 .vact_space_2 = {0xff, 0xff},
805 .vact_space_3 = {0xff, 0xff},
806 .vact_space_4 = {0xff, 0xff},
807 .vact_space_5 = {0xff, 0xff},
808 .vact_space_6 = {0xff, 0xff},
809 /* other don't care */
810 },
811 .tg = {
812 0x00, /* cmd */
813 0x98, 0x08, /* h_fsz */
814 0x18, 0x01, 0x80, 0x07, /* hact */
815 0x65, 0x04, /* v_fsz */
816 0x01, 0x00, 0x33, 0x02, /* vsync */
817 0x2d, 0x00, 0x38, 0x04, /* vact */
818 0x33, 0x02, /* field_chg */
819 0x48, 0x02, /* vact_st2 */
820 0x00, 0x00, /* vact_st3 */
821 0x00, 0x00, /* vact_st4 */
822 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
823 0x01, 0x00, 0x33, 0x02, /* field top/bot */
824 0x00, /* 3d FP */
825 },
826};
827
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900828static const struct hdmi_preset_conf hdmi_conf_1080p50 = {
829 .core = {
830 .h_blank = {0xd0, 0x02},
831 .v2_blank = {0x65, 0x04},
832 .v1_blank = {0x2d, 0x00},
833 .v_line = {0x65, 0x04},
834 .h_line = {0x50, 0x0a},
835 .hsync_pol = {0x00},
836 .vsync_pol = {0x00},
837 .int_pro_mode = {0x00},
838 .v_blank_f0 = {0xff, 0xff},
839 .v_blank_f1 = {0xff, 0xff},
840 .h_sync_start = {0x0e, 0x02},
841 .h_sync_end = {0x3a, 0x02},
842 .v_sync_line_bef_2 = {0x09, 0x00},
843 .v_sync_line_bef_1 = {0x04, 0x00},
844 .v_sync_line_aft_2 = {0xff, 0xff},
845 .v_sync_line_aft_1 = {0xff, 0xff},
846 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
847 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
848 .v_blank_f2 = {0xff, 0xff},
849 .v_blank_f3 = {0xff, 0xff},
850 .v_blank_f4 = {0xff, 0xff},
851 .v_blank_f5 = {0xff, 0xff},
852 .v_sync_line_aft_3 = {0xff, 0xff},
853 .v_sync_line_aft_4 = {0xff, 0xff},
854 .v_sync_line_aft_5 = {0xff, 0xff},
855 .v_sync_line_aft_6 = {0xff, 0xff},
856 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
857 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
858 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
859 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
860 .vact_space_1 = {0xff, 0xff},
861 .vact_space_2 = {0xff, 0xff},
862 .vact_space_3 = {0xff, 0xff},
863 .vact_space_4 = {0xff, 0xff},
864 .vact_space_5 = {0xff, 0xff},
865 .vact_space_6 = {0xff, 0xff},
866 /* other don't care */
867 },
868 .tg = {
869 0x00, /* cmd */
870 0x50, 0x0a, /* h_fsz */
871 0xd0, 0x02, 0x80, 0x07, /* hact */
872 0x65, 0x04, /* v_fsz */
873 0x01, 0x00, 0x33, 0x02, /* vsync */
874 0x2d, 0x00, 0x38, 0x04, /* vact */
875 0x33, 0x02, /* field_chg */
876 0x48, 0x02, /* vact_st2 */
877 0x00, 0x00, /* vact_st3 */
878 0x00, 0x00, /* vact_st4 */
879 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
880 0x01, 0x00, 0x33, 0x02, /* field top/bot */
881 0x00, /* 3d FP */
882 },
883};
884
885static const struct hdmi_preset_conf hdmi_conf_1080p60 = {
886 .core = {
887 .h_blank = {0x18, 0x01},
888 .v2_blank = {0x65, 0x04},
889 .v1_blank = {0x2d, 0x00},
890 .v_line = {0x65, 0x04},
891 .h_line = {0x98, 0x08},
892 .hsync_pol = {0x00},
893 .vsync_pol = {0x00},
894 .int_pro_mode = {0x00},
895 .v_blank_f0 = {0xff, 0xff},
896 .v_blank_f1 = {0xff, 0xff},
897 .h_sync_start = {0x56, 0x00},
898 .h_sync_end = {0x82, 0x00},
899 .v_sync_line_bef_2 = {0x09, 0x00},
900 .v_sync_line_bef_1 = {0x04, 0x00},
901 .v_sync_line_aft_2 = {0xff, 0xff},
902 .v_sync_line_aft_1 = {0xff, 0xff},
903 .v_sync_line_aft_pxl_2 = {0xff, 0xff},
904 .v_sync_line_aft_pxl_1 = {0xff, 0xff},
905 .v_blank_f2 = {0xff, 0xff},
906 .v_blank_f3 = {0xff, 0xff},
907 .v_blank_f4 = {0xff, 0xff},
908 .v_blank_f5 = {0xff, 0xff},
909 .v_sync_line_aft_3 = {0xff, 0xff},
910 .v_sync_line_aft_4 = {0xff, 0xff},
911 .v_sync_line_aft_5 = {0xff, 0xff},
912 .v_sync_line_aft_6 = {0xff, 0xff},
913 .v_sync_line_aft_pxl_3 = {0xff, 0xff},
914 .v_sync_line_aft_pxl_4 = {0xff, 0xff},
915 .v_sync_line_aft_pxl_5 = {0xff, 0xff},
916 .v_sync_line_aft_pxl_6 = {0xff, 0xff},
917 /* other don't care */
918 },
919 .tg = {
920 0x00, /* cmd */
921 0x98, 0x08, /* h_fsz */
922 0x18, 0x01, 0x80, 0x07, /* hact */
923 0x65, 0x04, /* v_fsz */
924 0x01, 0x00, 0x33, 0x02, /* vsync */
925 0x2d, 0x00, 0x38, 0x04, /* vact */
926 0x33, 0x02, /* field_chg */
927 0x48, 0x02, /* vact_st2 */
928 0x00, 0x00, /* vact_st3 */
929 0x00, 0x00, /* vact_st4 */
930 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */
931 0x01, 0x00, 0x33, 0x02, /* field top/bot */
932 0x00, /* 3d FP */
933 },
934};
935
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900936static const struct hdmi_conf hdmi_confs[] = {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900937 { 720, 480, 60, false, hdmiphy_conf27_027, &hdmi_conf_480p60 },
938 { 1280, 720, 50, false, hdmiphy_conf74_25, &hdmi_conf_720p50 },
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900939 { 1280, 720, 60, false, hdmiphy_conf74_25, &hdmi_conf_720p60 },
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900940 { 1920, 1080, 50, true, hdmiphy_conf74_25, &hdmi_conf_1080i50 },
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900941 { 1920, 1080, 60, true, hdmiphy_conf74_25, &hdmi_conf_1080i60 },
Seung-Woo Kime540adf2012-04-24 17:55:06 +0900942 { 1920, 1080, 30, false, hdmiphy_conf74_176, &hdmi_conf_1080p30 },
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900943 { 1920, 1080, 50, false, hdmiphy_conf148_5, &hdmi_conf_1080p50 },
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900944 { 1920, 1080, 60, false, hdmiphy_conf148_5, &hdmi_conf_1080p60 },
945};
946
947
948static inline u32 hdmi_reg_read(struct hdmi_context *hdata, u32 reg_id)
949{
950 return readl(hdata->regs + reg_id);
951}
952
953static inline void hdmi_reg_writeb(struct hdmi_context *hdata,
954 u32 reg_id, u8 value)
955{
956 writeb(value, hdata->regs + reg_id);
957}
958
959static inline void hdmi_reg_writemask(struct hdmi_context *hdata,
960 u32 reg_id, u32 value, u32 mask)
961{
962 u32 old = readl(hdata->regs + reg_id);
963 value = (value & mask) | (old & ~mask);
964 writel(value, hdata->regs + reg_id);
965}
966
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900967static void hdmi_v13_regs_dump(struct hdmi_context *hdata, char *prefix)
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900968{
969#define DUMPREG(reg_id) \
970 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
971 readl(hdata->regs + reg_id))
972 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
973 DUMPREG(HDMI_INTC_FLAG);
974 DUMPREG(HDMI_INTC_CON);
975 DUMPREG(HDMI_HPD_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900976 DUMPREG(HDMI_V13_PHY_RSTOUT);
977 DUMPREG(HDMI_V13_PHY_VPLL);
978 DUMPREG(HDMI_V13_PHY_CMU);
979 DUMPREG(HDMI_V13_CORE_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900980
981 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
982 DUMPREG(HDMI_CON_0);
983 DUMPREG(HDMI_CON_1);
984 DUMPREG(HDMI_CON_2);
985 DUMPREG(HDMI_SYS_STATUS);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900986 DUMPREG(HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900987 DUMPREG(HDMI_STATUS_EN);
988 DUMPREG(HDMI_HPD);
989 DUMPREG(HDMI_MODE_SEL);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900990 DUMPREG(HDMI_V13_HPD_GEN);
991 DUMPREG(HDMI_V13_DC_CONTROL);
992 DUMPREG(HDMI_V13_VIDEO_PATTERN_GEN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +0900993
994 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
995 DUMPREG(HDMI_H_BLANK_0);
996 DUMPREG(HDMI_H_BLANK_1);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +0900997 DUMPREG(HDMI_V13_V_BLANK_0);
998 DUMPREG(HDMI_V13_V_BLANK_1);
999 DUMPREG(HDMI_V13_V_BLANK_2);
1000 DUMPREG(HDMI_V13_H_V_LINE_0);
1001 DUMPREG(HDMI_V13_H_V_LINE_1);
1002 DUMPREG(HDMI_V13_H_V_LINE_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001003 DUMPREG(HDMI_VSYNC_POL);
1004 DUMPREG(HDMI_INT_PRO_MODE);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001005 DUMPREG(HDMI_V13_V_BLANK_F_0);
1006 DUMPREG(HDMI_V13_V_BLANK_F_1);
1007 DUMPREG(HDMI_V13_V_BLANK_F_2);
1008 DUMPREG(HDMI_V13_H_SYNC_GEN_0);
1009 DUMPREG(HDMI_V13_H_SYNC_GEN_1);
1010 DUMPREG(HDMI_V13_H_SYNC_GEN_2);
1011 DUMPREG(HDMI_V13_V_SYNC_GEN_1_0);
1012 DUMPREG(HDMI_V13_V_SYNC_GEN_1_1);
1013 DUMPREG(HDMI_V13_V_SYNC_GEN_1_2);
1014 DUMPREG(HDMI_V13_V_SYNC_GEN_2_0);
1015 DUMPREG(HDMI_V13_V_SYNC_GEN_2_1);
1016 DUMPREG(HDMI_V13_V_SYNC_GEN_2_2);
1017 DUMPREG(HDMI_V13_V_SYNC_GEN_3_0);
1018 DUMPREG(HDMI_V13_V_SYNC_GEN_3_1);
1019 DUMPREG(HDMI_V13_V_SYNC_GEN_3_2);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001020
1021 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
1022 DUMPREG(HDMI_TG_CMD);
1023 DUMPREG(HDMI_TG_H_FSZ_L);
1024 DUMPREG(HDMI_TG_H_FSZ_H);
1025 DUMPREG(HDMI_TG_HACT_ST_L);
1026 DUMPREG(HDMI_TG_HACT_ST_H);
1027 DUMPREG(HDMI_TG_HACT_SZ_L);
1028 DUMPREG(HDMI_TG_HACT_SZ_H);
1029 DUMPREG(HDMI_TG_V_FSZ_L);
1030 DUMPREG(HDMI_TG_V_FSZ_H);
1031 DUMPREG(HDMI_TG_VSYNC_L);
1032 DUMPREG(HDMI_TG_VSYNC_H);
1033 DUMPREG(HDMI_TG_VSYNC2_L);
1034 DUMPREG(HDMI_TG_VSYNC2_H);
1035 DUMPREG(HDMI_TG_VACT_ST_L);
1036 DUMPREG(HDMI_TG_VACT_ST_H);
1037 DUMPREG(HDMI_TG_VACT_SZ_L);
1038 DUMPREG(HDMI_TG_VACT_SZ_H);
1039 DUMPREG(HDMI_TG_FIELD_CHG_L);
1040 DUMPREG(HDMI_TG_FIELD_CHG_H);
1041 DUMPREG(HDMI_TG_VACT_ST2_L);
1042 DUMPREG(HDMI_TG_VACT_ST2_H);
1043 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
1044 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
1045 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
1046 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
1047 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
1048 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
1049 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
1050 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
1051#undef DUMPREG
1052}
1053
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001054static void hdmi_v14_regs_dump(struct hdmi_context *hdata, char *prefix)
1055{
1056 int i;
1057
1058#define DUMPREG(reg_id) \
1059 DRM_DEBUG_KMS("%s:" #reg_id " = %08x\n", prefix, \
1060 readl(hdata->regs + reg_id))
1061
1062 DRM_DEBUG_KMS("%s: ---- CONTROL REGISTERS ----\n", prefix);
1063 DUMPREG(HDMI_INTC_CON);
1064 DUMPREG(HDMI_INTC_FLAG);
1065 DUMPREG(HDMI_HPD_STATUS);
1066 DUMPREG(HDMI_INTC_CON_1);
1067 DUMPREG(HDMI_INTC_FLAG_1);
1068 DUMPREG(HDMI_PHY_STATUS_0);
1069 DUMPREG(HDMI_PHY_STATUS_PLL);
1070 DUMPREG(HDMI_PHY_CON_0);
1071 DUMPREG(HDMI_PHY_RSTOUT);
1072 DUMPREG(HDMI_PHY_VPLL);
1073 DUMPREG(HDMI_PHY_CMU);
1074 DUMPREG(HDMI_CORE_RSTOUT);
1075
1076 DRM_DEBUG_KMS("%s: ---- CORE REGISTERS ----\n", prefix);
1077 DUMPREG(HDMI_CON_0);
1078 DUMPREG(HDMI_CON_1);
1079 DUMPREG(HDMI_CON_2);
1080 DUMPREG(HDMI_SYS_STATUS);
1081 DUMPREG(HDMI_PHY_STATUS_0);
1082 DUMPREG(HDMI_STATUS_EN);
1083 DUMPREG(HDMI_HPD);
1084 DUMPREG(HDMI_MODE_SEL);
1085 DUMPREG(HDMI_ENC_EN);
1086 DUMPREG(HDMI_DC_CONTROL);
1087 DUMPREG(HDMI_VIDEO_PATTERN_GEN);
1088
1089 DRM_DEBUG_KMS("%s: ---- CORE SYNC REGISTERS ----\n", prefix);
1090 DUMPREG(HDMI_H_BLANK_0);
1091 DUMPREG(HDMI_H_BLANK_1);
1092 DUMPREG(HDMI_V2_BLANK_0);
1093 DUMPREG(HDMI_V2_BLANK_1);
1094 DUMPREG(HDMI_V1_BLANK_0);
1095 DUMPREG(HDMI_V1_BLANK_1);
1096 DUMPREG(HDMI_V_LINE_0);
1097 DUMPREG(HDMI_V_LINE_1);
1098 DUMPREG(HDMI_H_LINE_0);
1099 DUMPREG(HDMI_H_LINE_1);
1100 DUMPREG(HDMI_HSYNC_POL);
1101
1102 DUMPREG(HDMI_VSYNC_POL);
1103 DUMPREG(HDMI_INT_PRO_MODE);
1104 DUMPREG(HDMI_V_BLANK_F0_0);
1105 DUMPREG(HDMI_V_BLANK_F0_1);
1106 DUMPREG(HDMI_V_BLANK_F1_0);
1107 DUMPREG(HDMI_V_BLANK_F1_1);
1108
1109 DUMPREG(HDMI_H_SYNC_START_0);
1110 DUMPREG(HDMI_H_SYNC_START_1);
1111 DUMPREG(HDMI_H_SYNC_END_0);
1112 DUMPREG(HDMI_H_SYNC_END_1);
1113
1114 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_0);
1115 DUMPREG(HDMI_V_SYNC_LINE_BEF_2_1);
1116 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_0);
1117 DUMPREG(HDMI_V_SYNC_LINE_BEF_1_1);
1118
1119 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_0);
1120 DUMPREG(HDMI_V_SYNC_LINE_AFT_2_1);
1121 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_0);
1122 DUMPREG(HDMI_V_SYNC_LINE_AFT_1_1);
1123
1124 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_0);
1125 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_2_1);
1126 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_0);
1127 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_1_1);
1128
1129 DUMPREG(HDMI_V_BLANK_F2_0);
1130 DUMPREG(HDMI_V_BLANK_F2_1);
1131 DUMPREG(HDMI_V_BLANK_F3_0);
1132 DUMPREG(HDMI_V_BLANK_F3_1);
1133 DUMPREG(HDMI_V_BLANK_F4_0);
1134 DUMPREG(HDMI_V_BLANK_F4_1);
1135 DUMPREG(HDMI_V_BLANK_F5_0);
1136 DUMPREG(HDMI_V_BLANK_F5_1);
1137
1138 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_0);
1139 DUMPREG(HDMI_V_SYNC_LINE_AFT_3_1);
1140 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_0);
1141 DUMPREG(HDMI_V_SYNC_LINE_AFT_4_1);
1142 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_0);
1143 DUMPREG(HDMI_V_SYNC_LINE_AFT_5_1);
1144 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_0);
1145 DUMPREG(HDMI_V_SYNC_LINE_AFT_6_1);
1146
1147 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_0);
1148 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_3_1);
1149 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_0);
1150 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_4_1);
1151 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_0);
1152 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_5_1);
1153 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_0);
1154 DUMPREG(HDMI_V_SYNC_LINE_AFT_PXL_6_1);
1155
1156 DUMPREG(HDMI_VACT_SPACE_1_0);
1157 DUMPREG(HDMI_VACT_SPACE_1_1);
1158 DUMPREG(HDMI_VACT_SPACE_2_0);
1159 DUMPREG(HDMI_VACT_SPACE_2_1);
1160 DUMPREG(HDMI_VACT_SPACE_3_0);
1161 DUMPREG(HDMI_VACT_SPACE_3_1);
1162 DUMPREG(HDMI_VACT_SPACE_4_0);
1163 DUMPREG(HDMI_VACT_SPACE_4_1);
1164 DUMPREG(HDMI_VACT_SPACE_5_0);
1165 DUMPREG(HDMI_VACT_SPACE_5_1);
1166 DUMPREG(HDMI_VACT_SPACE_6_0);
1167 DUMPREG(HDMI_VACT_SPACE_6_1);
1168
1169 DRM_DEBUG_KMS("%s: ---- TG REGISTERS ----\n", prefix);
1170 DUMPREG(HDMI_TG_CMD);
1171 DUMPREG(HDMI_TG_H_FSZ_L);
1172 DUMPREG(HDMI_TG_H_FSZ_H);
1173 DUMPREG(HDMI_TG_HACT_ST_L);
1174 DUMPREG(HDMI_TG_HACT_ST_H);
1175 DUMPREG(HDMI_TG_HACT_SZ_L);
1176 DUMPREG(HDMI_TG_HACT_SZ_H);
1177 DUMPREG(HDMI_TG_V_FSZ_L);
1178 DUMPREG(HDMI_TG_V_FSZ_H);
1179 DUMPREG(HDMI_TG_VSYNC_L);
1180 DUMPREG(HDMI_TG_VSYNC_H);
1181 DUMPREG(HDMI_TG_VSYNC2_L);
1182 DUMPREG(HDMI_TG_VSYNC2_H);
1183 DUMPREG(HDMI_TG_VACT_ST_L);
1184 DUMPREG(HDMI_TG_VACT_ST_H);
1185 DUMPREG(HDMI_TG_VACT_SZ_L);
1186 DUMPREG(HDMI_TG_VACT_SZ_H);
1187 DUMPREG(HDMI_TG_FIELD_CHG_L);
1188 DUMPREG(HDMI_TG_FIELD_CHG_H);
1189 DUMPREG(HDMI_TG_VACT_ST2_L);
1190 DUMPREG(HDMI_TG_VACT_ST2_H);
1191 DUMPREG(HDMI_TG_VACT_ST3_L);
1192 DUMPREG(HDMI_TG_VACT_ST3_H);
1193 DUMPREG(HDMI_TG_VACT_ST4_L);
1194 DUMPREG(HDMI_TG_VACT_ST4_H);
1195 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_L);
1196 DUMPREG(HDMI_TG_VSYNC_TOP_HDMI_H);
1197 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_L);
1198 DUMPREG(HDMI_TG_VSYNC_BOT_HDMI_H);
1199 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_L);
1200 DUMPREG(HDMI_TG_FIELD_TOP_HDMI_H);
1201 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_L);
1202 DUMPREG(HDMI_TG_FIELD_BOT_HDMI_H);
1203 DUMPREG(HDMI_TG_3D);
1204
1205 DRM_DEBUG_KMS("%s: ---- PACKET REGISTERS ----\n", prefix);
1206 DUMPREG(HDMI_AVI_CON);
1207 DUMPREG(HDMI_AVI_HEADER0);
1208 DUMPREG(HDMI_AVI_HEADER1);
1209 DUMPREG(HDMI_AVI_HEADER2);
1210 DUMPREG(HDMI_AVI_CHECK_SUM);
1211 DUMPREG(HDMI_VSI_CON);
1212 DUMPREG(HDMI_VSI_HEADER0);
1213 DUMPREG(HDMI_VSI_HEADER1);
1214 DUMPREG(HDMI_VSI_HEADER2);
1215 for (i = 0; i < 7; ++i)
1216 DUMPREG(HDMI_VSI_DATA(i));
1217
1218#undef DUMPREG
1219}
1220
1221static void hdmi_regs_dump(struct hdmi_context *hdata, char *prefix)
1222{
Rahul Sharma5a325072012-10-04 20:48:54 +05301223 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001224 hdmi_v13_regs_dump(hdata, prefix);
1225 else
1226 hdmi_v14_regs_dump(hdata, prefix);
1227}
1228
1229static int hdmi_v13_conf_index(struct drm_display_mode *mode)
1230{
1231 int i;
1232
1233 for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i)
1234 if (hdmi_v13_confs[i].width == mode->hdisplay &&
1235 hdmi_v13_confs[i].height == mode->vdisplay &&
1236 hdmi_v13_confs[i].vrefresh == mode->vrefresh &&
1237 hdmi_v13_confs[i].interlace ==
1238 ((mode->flags & DRM_MODE_FLAG_INTERLACE) ?
1239 true : false))
1240 return i;
1241
Inki Dae1de425b2012-03-16 18:47:04 +09001242 return -EINVAL;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001243}
1244
1245static int hdmi_v14_conf_index(struct drm_display_mode *mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001246{
1247 int i;
1248
1249 for (i = 0; i < ARRAY_SIZE(hdmi_confs); ++i)
1250 if (hdmi_confs[i].width == mode->hdisplay &&
1251 hdmi_confs[i].height == mode->vdisplay &&
1252 hdmi_confs[i].vrefresh == mode->vrefresh &&
1253 hdmi_confs[i].interlace ==
1254 ((mode->flags & DRM_MODE_FLAG_INTERLACE) ?
1255 true : false))
1256 return i;
1257
Inki Dae1de425b2012-03-16 18:47:04 +09001258 return -EINVAL;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001259}
1260
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001261static int hdmi_conf_index(struct hdmi_context *hdata,
1262 struct drm_display_mode *mode)
1263{
Rahul Sharma5a325072012-10-04 20:48:54 +05301264 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001265 return hdmi_v13_conf_index(mode);
Inki Dae1de425b2012-03-16 18:47:04 +09001266
1267 return hdmi_v14_conf_index(mode);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001268}
1269
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001270static bool hdmi_is_connected(void *ctx)
1271{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001272 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001273
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001274 return hdata->hpd;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001275}
1276
1277static int hdmi_get_edid(void *ctx, struct drm_connector *connector,
1278 u8 *edid, int len)
1279{
1280 struct edid *raw_edid;
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001281 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001282
1283 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1284
1285 if (!hdata->ddc_port)
1286 return -ENODEV;
1287
1288 raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
1289 if (raw_edid) {
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001290 hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001291 memcpy(edid, raw_edid, min((1 + raw_edid->extensions)
1292 * EDID_LENGTH, len));
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001293 DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
1294 (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
1295 raw_edid->width_cm, raw_edid->height_cm);
Egbert Eich3dc5fa92012-11-20 04:30:16 -05001296 kfree(raw_edid);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001297 } else {
1298 return -ENODEV;
1299 }
1300
1301 return 0;
1302}
1303
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001304static int hdmi_v13_check_timing(struct fb_videomode *check_timing)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001305{
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001306 int i;
1307
Inki Dae1de425b2012-03-16 18:47:04 +09001308 DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
1309 check_timing->xres, check_timing->yres,
1310 check_timing->refresh, (check_timing->vmode &
1311 FB_VMODE_INTERLACED) ? true : false);
1312
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001313 for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i)
1314 if (hdmi_v13_confs[i].width == check_timing->xres &&
1315 hdmi_v13_confs[i].height == check_timing->yres &&
1316 hdmi_v13_confs[i].vrefresh == check_timing->refresh &&
1317 hdmi_v13_confs[i].interlace ==
1318 ((check_timing->vmode & FB_VMODE_INTERLACED) ?
1319 true : false))
Inki Dae1de425b2012-03-16 18:47:04 +09001320 return 0;
1321
1322 /* TODO */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001323
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001324 return -EINVAL;
1325}
1326
1327static int hdmi_v14_check_timing(struct fb_videomode *check_timing)
1328{
1329 int i;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001330
Inki Dae1de425b2012-03-16 18:47:04 +09001331 DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
1332 check_timing->xres, check_timing->yres,
1333 check_timing->refresh, (check_timing->vmode &
1334 FB_VMODE_INTERLACED) ? true : false);
1335
1336 for (i = 0; i < ARRAY_SIZE(hdmi_confs); i++)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001337 if (hdmi_confs[i].width == check_timing->xres &&
1338 hdmi_confs[i].height == check_timing->yres &&
1339 hdmi_confs[i].vrefresh == check_timing->refresh &&
1340 hdmi_confs[i].interlace ==
1341 ((check_timing->vmode & FB_VMODE_INTERLACED) ?
1342 true : false))
Inki Dae1de425b2012-03-16 18:47:04 +09001343 return 0;
1344
1345 /* TODO */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001346
1347 return -EINVAL;
1348}
1349
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001350static int hdmi_check_timing(void *ctx, void *timing)
1351{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001352 struct hdmi_context *hdata = ctx;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001353 struct fb_videomode *check_timing = timing;
1354
1355 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1356
1357 DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", check_timing->xres,
1358 check_timing->yres, check_timing->refresh,
1359 check_timing->vmode);
1360
Rahul Sharma5a325072012-10-04 20:48:54 +05301361 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001362 return hdmi_v13_check_timing(check_timing);
1363 else
1364 return hdmi_v14_check_timing(check_timing);
1365}
1366
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001367static void hdmi_set_acr(u32 freq, u8 *acr)
1368{
1369 u32 n, cts;
1370
1371 switch (freq) {
1372 case 32000:
1373 n = 4096;
1374 cts = 27000;
1375 break;
1376 case 44100:
1377 n = 6272;
1378 cts = 30000;
1379 break;
1380 case 88200:
1381 n = 12544;
1382 cts = 30000;
1383 break;
1384 case 176400:
1385 n = 25088;
1386 cts = 30000;
1387 break;
1388 case 48000:
1389 n = 6144;
1390 cts = 27000;
1391 break;
1392 case 96000:
1393 n = 12288;
1394 cts = 27000;
1395 break;
1396 case 192000:
1397 n = 24576;
1398 cts = 27000;
1399 break;
1400 default:
1401 n = 0;
1402 cts = 0;
1403 break;
1404 }
1405
1406 acr[1] = cts >> 16;
1407 acr[2] = cts >> 8 & 0xff;
1408 acr[3] = cts & 0xff;
1409
1410 acr[4] = n >> 16;
1411 acr[5] = n >> 8 & 0xff;
1412 acr[6] = n & 0xff;
1413}
1414
1415static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
1416{
1417 hdmi_reg_writeb(hdata, HDMI_ACR_N0, acr[6]);
1418 hdmi_reg_writeb(hdata, HDMI_ACR_N1, acr[5]);
1419 hdmi_reg_writeb(hdata, HDMI_ACR_N2, acr[4]);
1420 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS0, acr[3]);
1421 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS1, acr[2]);
1422 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS2, acr[1]);
1423 hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]);
1424 hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
1425 hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
1426
Rahul Sharma5a325072012-10-04 20:48:54 +05301427 if (hdata->type == HDMI_TYPE13)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001428 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4);
1429 else
1430 hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
1431}
1432
1433static void hdmi_audio_init(struct hdmi_context *hdata)
1434{
1435 u32 sample_rate, bits_per_sample, frame_size_code;
1436 u32 data_num, bit_ch, sample_frq;
1437 u32 val;
1438 u8 acr[7];
1439
1440 sample_rate = 44100;
1441 bits_per_sample = 16;
1442 frame_size_code = 0;
1443
1444 switch (bits_per_sample) {
1445 case 20:
1446 data_num = 2;
1447 bit_ch = 1;
1448 break;
1449 case 24:
1450 data_num = 3;
1451 bit_ch = 1;
1452 break;
1453 default:
1454 data_num = 1;
1455 bit_ch = 0;
1456 break;
1457 }
1458
1459 hdmi_set_acr(sample_rate, acr);
1460 hdmi_reg_acr(hdata, acr);
1461
1462 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
1463 | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
1464 | HDMI_I2S_MUX_ENABLE);
1465
1466 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
1467 | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
1468
1469 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
1470
1471 sample_frq = (sample_rate == 44100) ? 0 :
1472 (sample_rate == 48000) ? 2 :
1473 (sample_rate == 32000) ? 3 :
1474 (sample_rate == 96000) ? 0xa : 0x0;
1475
1476 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
1477 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
1478
1479 val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01;
1480 hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val);
1481
1482 /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
1483 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
1484 | HDMI_I2S_SEL_LRCK(6));
1485 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1)
1486 | HDMI_I2S_SEL_SDATA2(4));
1487 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
1488 | HDMI_I2S_SEL_SDATA2(2));
1489 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
1490
1491 /* I2S_CON_1 & 2 */
1492 hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
1493 | HDMI_I2S_L_CH_LOW_POL);
1494 hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
1495 | HDMI_I2S_SET_BIT_CH(bit_ch)
1496 | HDMI_I2S_SET_SDATA_BIT(data_num)
1497 | HDMI_I2S_BASIC_FORMAT);
1498
1499 /* Configure register related to CUV information */
1500 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0
1501 | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH
1502 | HDMI_I2S_COPYRIGHT
1503 | HDMI_I2S_LINEAR_PCM
1504 | HDMI_I2S_CONSUMER_FORMAT);
1505 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
1506 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
1507 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
1508 | HDMI_I2S_SET_SMP_FREQ(sample_frq));
1509 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4,
1510 HDMI_I2S_ORG_SMP_FREQ_44_1
1511 | HDMI_I2S_WORD_LEN_MAX24_24BITS
1512 | HDMI_I2S_WORD_LEN_MAX_24BITS);
1513
1514 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
1515}
1516
1517static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff)
1518{
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001519 if (hdata->dvi_mode)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001520 return;
1521
1522 hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0);
1523 hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ?
1524 HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
1525}
1526
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001527static void hdmi_conf_reset(struct hdmi_context *hdata)
1528{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001529 u32 reg;
1530
Rahul Sharma5a325072012-10-04 20:48:54 +05301531 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001532 reg = HDMI_V13_CORE_RSTOUT;
1533 else
1534 reg = HDMI_CORE_RSTOUT;
1535
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001536 /* resetting HDMI core */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001537 hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001538 mdelay(10);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001539 hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001540 mdelay(10);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001541}
1542
1543static void hdmi_conf_init(struct hdmi_context *hdata)
1544{
Tomasz Stanislawski5295e53d2012-10-04 20:48:47 +05301545 /* disable HPD interrupts */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001546 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1547 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001548
1549 /* choose HDMI mode */
1550 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1551 HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
1552 /* disable bluescreen */
1553 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001554
Seung-Woo Kim872d20d62012-04-24 17:39:15 +09001555 if (hdata->dvi_mode) {
1556 /* choose DVI mode */
1557 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1558 HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
1559 hdmi_reg_writeb(hdata, HDMI_CON_2,
1560 HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
1561 }
1562
Rahul Sharma5a325072012-10-04 20:48:54 +05301563 if (hdata->type == HDMI_TYPE13) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001564 /* choose bluescreen (fecal) color */
1565 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1566 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1567 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1568
1569 /* enable AVI packet every vsync, fixes purple line problem */
1570 hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1571 /* force RGB, look to CEA-861-D, table 7 for more detail */
1572 hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1573 hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1574
1575 hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1576 hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1577 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1578 } else {
1579 /* enable AVI packet every vsync, fixes purple line problem */
1580 hdmi_reg_writeb(hdata, HDMI_AVI_CON, 0x02);
1581 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 2 << 5);
1582 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1583 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001584}
1585
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001586static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001587{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001588 const struct hdmi_v13_preset_conf *conf =
1589 hdmi_v13_confs[hdata->cur_conf].conf;
1590 const struct hdmi_v13_core_regs *core = &conf->core;
1591 const struct hdmi_v13_tg_regs *tg = &conf->tg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001592 int tries;
1593
1594 /* setting core registers */
1595 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1596 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001597 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]);
1598 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]);
1599 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]);
1600 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]);
1601 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]);
1602 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001603 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1604 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001605 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]);
1606 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]);
1607 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]);
1608 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]);
1609 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]);
1610 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]);
1611 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
1612 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
1613 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
1614 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
1615 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
1616 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
1617 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
1618 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
1619 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001620 /* Timing generator registers */
1621 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
1622 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
1623 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
1624 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
1625 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
1626 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
1627 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
1628 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
1629 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
1630 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
1631 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
1632 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
1633 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
1634 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
1635 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
1636 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
1637 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
1638 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
1639 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
1640 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
1641 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
1642 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
1643 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
1644 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
1645 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
1646 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
1647 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
1648 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
1649
1650 /* waiting for HDMIPHY's PLL to get to steady state */
1651 for (tries = 100; tries; --tries) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001652 u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001653 if (val & HDMI_PHY_STATUS_READY)
1654 break;
1655 mdelay(1);
1656 }
1657 /* steady state not achieved */
1658 if (tries == 0) {
1659 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1660 hdmi_regs_dump(hdata, "timing apply");
1661 }
1662
1663 clk_disable(hdata->res.sclk_hdmi);
1664 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
1665 clk_enable(hdata->res.sclk_hdmi);
1666
1667 /* enable HDMI and timing generator */
1668 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1669 if (core->int_pro_mode[0])
1670 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1671 HDMI_FIELD_EN);
1672 else
1673 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1674}
1675
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001676static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
1677{
1678 const struct hdmi_preset_conf *conf = hdmi_confs[hdata->cur_conf].conf;
1679 const struct hdmi_core_regs *core = &conf->core;
1680 const struct hdmi_tg_regs *tg = &conf->tg;
1681 int tries;
1682
1683 /* setting core registers */
1684 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1685 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
1686 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_0, core->v2_blank[0]);
1687 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_1, core->v2_blank[1]);
1688 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_0, core->v1_blank[0]);
1689 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_1, core->v1_blank[1]);
1690 hdmi_reg_writeb(hdata, HDMI_V_LINE_0, core->v_line[0]);
1691 hdmi_reg_writeb(hdata, HDMI_V_LINE_1, core->v_line[1]);
1692 hdmi_reg_writeb(hdata, HDMI_H_LINE_0, core->h_line[0]);
1693 hdmi_reg_writeb(hdata, HDMI_H_LINE_1, core->h_line[1]);
1694 hdmi_reg_writeb(hdata, HDMI_HSYNC_POL, core->hsync_pol[0]);
1695 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1696 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
1697 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_0, core->v_blank_f0[0]);
1698 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_1, core->v_blank_f0[1]);
1699 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_0, core->v_blank_f1[0]);
1700 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_1, core->v_blank_f1[1]);
1701 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_0, core->h_sync_start[0]);
1702 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_1, core->h_sync_start[1]);
1703 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_0, core->h_sync_end[0]);
1704 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_1, core->h_sync_end[1]);
1705 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_0,
1706 core->v_sync_line_bef_2[0]);
1707 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_1,
1708 core->v_sync_line_bef_2[1]);
1709 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_0,
1710 core->v_sync_line_bef_1[0]);
1711 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_1,
1712 core->v_sync_line_bef_1[1]);
1713 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_0,
1714 core->v_sync_line_aft_2[0]);
1715 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_1,
1716 core->v_sync_line_aft_2[1]);
1717 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_0,
1718 core->v_sync_line_aft_1[0]);
1719 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_1,
1720 core->v_sync_line_aft_1[1]);
1721 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0,
1722 core->v_sync_line_aft_pxl_2[0]);
1723 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_1,
1724 core->v_sync_line_aft_pxl_2[1]);
1725 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0,
1726 core->v_sync_line_aft_pxl_1[0]);
1727 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_1,
1728 core->v_sync_line_aft_pxl_1[1]);
1729 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_0, core->v_blank_f2[0]);
1730 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_1, core->v_blank_f2[1]);
1731 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_0, core->v_blank_f3[0]);
1732 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_1, core->v_blank_f3[1]);
1733 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_0, core->v_blank_f4[0]);
1734 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_1, core->v_blank_f4[1]);
1735 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_0, core->v_blank_f5[0]);
1736 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_1, core->v_blank_f5[1]);
1737 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_0,
1738 core->v_sync_line_aft_3[0]);
1739 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_1,
1740 core->v_sync_line_aft_3[1]);
1741 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_0,
1742 core->v_sync_line_aft_4[0]);
1743 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_1,
1744 core->v_sync_line_aft_4[1]);
1745 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_0,
1746 core->v_sync_line_aft_5[0]);
1747 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_1,
1748 core->v_sync_line_aft_5[1]);
1749 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_0,
1750 core->v_sync_line_aft_6[0]);
1751 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_1,
1752 core->v_sync_line_aft_6[1]);
1753 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0,
1754 core->v_sync_line_aft_pxl_3[0]);
1755 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_1,
1756 core->v_sync_line_aft_pxl_3[1]);
1757 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0,
1758 core->v_sync_line_aft_pxl_4[0]);
1759 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_1,
1760 core->v_sync_line_aft_pxl_4[1]);
1761 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0,
1762 core->v_sync_line_aft_pxl_5[0]);
1763 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_1,
1764 core->v_sync_line_aft_pxl_5[1]);
1765 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0,
1766 core->v_sync_line_aft_pxl_6[0]);
1767 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_1,
1768 core->v_sync_line_aft_pxl_6[1]);
1769 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_0, core->vact_space_1[0]);
1770 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_1, core->vact_space_1[1]);
1771 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_0, core->vact_space_2[0]);
1772 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_1, core->vact_space_2[1]);
1773 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_0, core->vact_space_3[0]);
1774 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_1, core->vact_space_3[1]);
1775 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_0, core->vact_space_4[0]);
1776 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_1, core->vact_space_4[1]);
1777 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_0, core->vact_space_5[0]);
1778 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_1, core->vact_space_5[1]);
1779 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_0, core->vact_space_6[0]);
1780 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]);
1781
1782 /* Timing generator registers */
1783 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
1784 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
1785 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
1786 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
1787 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
1788 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
1789 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
1790 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
1791 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
1792 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
1793 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
1794 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
1795 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
1796 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
1797 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
1798 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
1799 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
1800 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
1801 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
1802 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
1803 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3_l);
1804 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3_h);
1805 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4_l);
1806 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4_h);
1807 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
1808 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
1809 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
1810 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
1811 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
1812 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
1813 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
1814 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
1815 hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d);
1816
1817 /* waiting for HDMIPHY's PLL to get to steady state */
1818 for (tries = 100; tries; --tries) {
1819 u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
1820 if (val & HDMI_PHY_STATUS_READY)
1821 break;
1822 mdelay(1);
1823 }
1824 /* steady state not achieved */
1825 if (tries == 0) {
1826 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1827 hdmi_regs_dump(hdata, "timing apply");
1828 }
1829
1830 clk_disable(hdata->res.sclk_hdmi);
1831 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
1832 clk_enable(hdata->res.sclk_hdmi);
1833
1834 /* enable HDMI and timing generator */
1835 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1836 if (core->int_pro_mode[0])
1837 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1838 HDMI_FIELD_EN);
1839 else
1840 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1841}
1842
1843static void hdmi_timing_apply(struct hdmi_context *hdata)
1844{
Rahul Sharma5a325072012-10-04 20:48:54 +05301845 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001846 hdmi_v13_timing_apply(hdata);
1847 else
1848 hdmi_v14_timing_apply(hdata);
1849}
1850
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001851static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1852{
1853 u8 buffer[2];
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001854 u32 reg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001855
1856 clk_disable(hdata->res.sclk_hdmi);
1857 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_pixel);
1858 clk_enable(hdata->res.sclk_hdmi);
1859
1860 /* operation mode */
1861 buffer[0] = 0x1f;
1862 buffer[1] = 0x00;
1863
1864 if (hdata->hdmiphy_port)
1865 i2c_master_send(hdata->hdmiphy_port, buffer, 2);
1866
Rahul Sharma5a325072012-10-04 20:48:54 +05301867 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001868 reg = HDMI_V13_PHY_RSTOUT;
1869 else
1870 reg = HDMI_PHY_RSTOUT;
1871
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001872 /* reset hdmiphy */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001873 hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001874 mdelay(10);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001875 hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001876 mdelay(10);
1877}
1878
1879static void hdmiphy_conf_apply(struct hdmi_context *hdata)
1880{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001881 const u8 *hdmiphy_data;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001882 u8 buffer[32];
1883 u8 operation[2];
1884 u8 read_buffer[32] = {0, };
1885 int ret;
1886 int i;
1887
1888 if (!hdata->hdmiphy_port) {
1889 DRM_ERROR("hdmiphy is not attached\n");
1890 return;
1891 }
1892
1893 /* pixel clock */
Rahul Sharma5a325072012-10-04 20:48:54 +05301894 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001895 hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data;
1896 else
1897 hdmiphy_data = hdmi_confs[hdata->cur_conf].hdmiphy_data;
1898
1899 memcpy(buffer, hdmiphy_data, 32);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001900 ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32);
1901 if (ret != 32) {
1902 DRM_ERROR("failed to configure HDMIPHY via I2C\n");
1903 return;
1904 }
1905
1906 mdelay(10);
1907
1908 /* operation mode */
1909 operation[0] = 0x1f;
1910 operation[1] = 0x80;
1911
1912 ret = i2c_master_send(hdata->hdmiphy_port, operation, 2);
1913 if (ret != 2) {
1914 DRM_ERROR("failed to enable hdmiphy\n");
1915 return;
1916 }
1917
1918 ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32);
1919 if (ret < 0) {
1920 DRM_ERROR("failed to read hdmiphy config\n");
1921 return;
1922 }
1923
1924 for (i = 0; i < ret; i++)
1925 DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - "
1926 "recv [0x%02x]\n", i, buffer[i], read_buffer[i]);
1927}
1928
1929static void hdmi_conf_apply(struct hdmi_context *hdata)
1930{
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001931 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1932
1933 hdmiphy_conf_reset(hdata);
1934 hdmiphy_conf_apply(hdata);
1935
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001936 mutex_lock(&hdata->hdmi_mutex);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001937 hdmi_conf_reset(hdata);
1938 hdmi_conf_init(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001939 mutex_unlock(&hdata->hdmi_mutex);
1940
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001941 hdmi_audio_init(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001942
1943 /* setting core registers */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001944 hdmi_timing_apply(hdata);
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001945 hdmi_audio_control(hdata, true);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001946
1947 hdmi_regs_dump(hdata, "start");
1948}
1949
Inki Dae1de425b2012-03-16 18:47:04 +09001950static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,
Laurent Pincharte811f5a2012-07-17 17:56:50 +02001951 const struct drm_display_mode *mode,
Inki Dae1de425b2012-03-16 18:47:04 +09001952 struct drm_display_mode *adjusted_mode)
1953{
1954 struct drm_display_mode *m;
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001955 struct hdmi_context *hdata = ctx;
Inki Dae1de425b2012-03-16 18:47:04 +09001956 int index;
1957
1958 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1959
1960 drm_mode_set_crtcinfo(adjusted_mode, 0);
1961
Rahul Sharma5a325072012-10-04 20:48:54 +05301962 if (hdata->type == HDMI_TYPE13)
Inki Dae1de425b2012-03-16 18:47:04 +09001963 index = hdmi_v13_conf_index(adjusted_mode);
1964 else
1965 index = hdmi_v14_conf_index(adjusted_mode);
1966
1967 /* just return if user desired mode exists. */
1968 if (index >= 0)
1969 return;
1970
1971 /*
1972 * otherwise, find the most suitable mode among modes and change it
1973 * to adjusted_mode.
1974 */
1975 list_for_each_entry(m, &connector->modes, head) {
Rahul Sharma5a325072012-10-04 20:48:54 +05301976 if (hdata->type == HDMI_TYPE13)
Inki Dae1de425b2012-03-16 18:47:04 +09001977 index = hdmi_v13_conf_index(m);
1978 else
1979 index = hdmi_v14_conf_index(m);
1980
1981 if (index >= 0) {
1982 DRM_INFO("desired mode doesn't exist so\n");
1983 DRM_INFO("use the most suitable mode among modes.\n");
1984 memcpy(adjusted_mode, m, sizeof(*m));
1985 break;
1986 }
1987 }
1988}
1989
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001990static void hdmi_mode_set(void *ctx, void *mode)
1991{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001992 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001993 int conf_idx;
1994
1995 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1996
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001997 conf_idx = hdmi_conf_index(hdata, mode);
1998 if (conf_idx >= 0)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001999 hdata->cur_conf = conf_idx;
2000 else
2001 DRM_DEBUG_KMS("not supported mode\n");
2002}
2003
Inki Dae1de425b2012-03-16 18:47:04 +09002004static void hdmi_get_max_resol(void *ctx, unsigned int *width,
2005 unsigned int *height)
2006{
2007 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2008
2009 *width = MAX_WIDTH;
2010 *height = MAX_HEIGHT;
2011}
2012
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002013static void hdmi_commit(void *ctx)
2014{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002015 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002016
2017 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2018
2019 hdmi_conf_apply(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002020}
2021
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002022static void hdmi_poweron(struct hdmi_context *hdata)
2023{
2024 struct hdmi_resources *res = &hdata->res;
2025
2026 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2027
2028 mutex_lock(&hdata->hdmi_mutex);
2029 if (hdata->powered) {
2030 mutex_unlock(&hdata->hdmi_mutex);
2031 return;
2032 }
2033
2034 hdata->powered = true;
2035
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002036 mutex_unlock(&hdata->hdmi_mutex);
2037
2038 pm_runtime_get_sync(hdata->dev);
2039
2040 regulator_bulk_enable(res->regul_count, res->regul_bulk);
2041 clk_enable(res->hdmiphy);
2042 clk_enable(res->hdmi);
2043 clk_enable(res->sclk_hdmi);
2044}
2045
2046static void hdmi_poweroff(struct hdmi_context *hdata)
2047{
2048 struct hdmi_resources *res = &hdata->res;
2049
2050 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2051
2052 mutex_lock(&hdata->hdmi_mutex);
2053 if (!hdata->powered)
2054 goto out;
2055 mutex_unlock(&hdata->hdmi_mutex);
2056
2057 /*
2058 * The TV power domain needs any condition of hdmiphy to turn off and
2059 * its reset state seems to meet the condition.
2060 */
2061 hdmiphy_conf_reset(hdata);
2062
2063 clk_disable(res->sclk_hdmi);
2064 clk_disable(res->hdmi);
2065 clk_disable(res->hdmiphy);
2066 regulator_bulk_disable(res->regul_count, res->regul_bulk);
2067
2068 pm_runtime_put_sync(hdata->dev);
2069
2070 mutex_lock(&hdata->hdmi_mutex);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002071
2072 hdata->powered = false;
2073
2074out:
2075 mutex_unlock(&hdata->hdmi_mutex);
2076}
2077
2078static void hdmi_dpms(void *ctx, int mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002079{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002080 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002081
2082 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2083
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002084 switch (mode) {
2085 case DRM_MODE_DPMS_ON:
2086 hdmi_poweron(hdata);
2087 break;
2088 case DRM_MODE_DPMS_STANDBY:
2089 case DRM_MODE_DPMS_SUSPEND:
2090 case DRM_MODE_DPMS_OFF:
2091 hdmi_poweroff(hdata);
2092 break;
2093 default:
2094 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
2095 break;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002096 }
2097}
2098
Joonyoung Shim578b6062012-04-05 20:49:26 +09002099static struct exynos_hdmi_ops hdmi_ops = {
2100 /* display */
2101 .is_connected = hdmi_is_connected,
2102 .get_edid = hdmi_get_edid,
2103 .check_timing = hdmi_check_timing,
Joonyoung Shim578b6062012-04-05 20:49:26 +09002104
2105 /* manager */
Inki Dae1de425b2012-03-16 18:47:04 +09002106 .mode_fixup = hdmi_mode_fixup,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002107 .mode_set = hdmi_mode_set,
Inki Dae1de425b2012-03-16 18:47:04 +09002108 .get_max_resol = hdmi_get_max_resol,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002109 .commit = hdmi_commit,
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002110 .dpms = hdmi_dpms,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002111};
2112
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002113static irqreturn_t hdmi_external_irq_thread(int irq, void *arg)
2114{
2115 struct exynos_drm_hdmi_context *ctx = arg;
2116 struct hdmi_context *hdata = ctx->ctx;
2117
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002118 mutex_lock(&hdata->hdmi_mutex);
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302119 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002120 mutex_unlock(&hdata->hdmi_mutex);
2121
2122 if (ctx->drm_dev)
2123 drm_helper_hpd_irq_event(ctx->drm_dev);
2124
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002125 return IRQ_HANDLED;
2126}
2127
2128static irqreturn_t hdmi_internal_irq_thread(int irq, void *arg)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002129{
2130 struct exynos_drm_hdmi_context *ctx = arg;
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002131 struct hdmi_context *hdata = ctx->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002132 u32 intc_flag;
2133
2134 intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG);
2135 /* clearing flags for HPD plug/unplug */
2136 if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002137 DRM_DEBUG_KMS("unplugged\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002138 hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
2139 HDMI_INTC_FLAG_HPD_UNPLUG);
2140 }
2141 if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002142 DRM_DEBUG_KMS("plugged\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002143 hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
2144 HDMI_INTC_FLAG_HPD_PLUG);
2145 }
2146
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002147 if (ctx->drm_dev)
Joonyoung Shim66265a22012-04-23 19:35:49 +09002148 drm_helper_hpd_irq_event(ctx->drm_dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002149
2150 return IRQ_HANDLED;
2151}
2152
2153static int __devinit hdmi_resources_init(struct hdmi_context *hdata)
2154{
2155 struct device *dev = hdata->dev;
2156 struct hdmi_resources *res = &hdata->res;
2157 static char *supply[] = {
2158 "hdmi-en",
2159 "vdd",
2160 "vdd_osc",
2161 "vdd_pll",
2162 };
2163 int i, ret;
2164
2165 DRM_DEBUG_KMS("HDMI resource init\n");
2166
Sachin Kamatadc837a2012-08-31 15:50:47 +05302167 memset(res, 0, sizeof(*res));
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002168
2169 /* get clocks, power */
2170 res->hdmi = clk_get(dev, "hdmi");
2171 if (IS_ERR_OR_NULL(res->hdmi)) {
2172 DRM_ERROR("failed to get clock 'hdmi'\n");
2173 goto fail;
2174 }
2175 res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
2176 if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
2177 DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
2178 goto fail;
2179 }
2180 res->sclk_pixel = clk_get(dev, "sclk_pixel");
2181 if (IS_ERR_OR_NULL(res->sclk_pixel)) {
2182 DRM_ERROR("failed to get clock 'sclk_pixel'\n");
2183 goto fail;
2184 }
2185 res->sclk_hdmiphy = clk_get(dev, "sclk_hdmiphy");
2186 if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) {
2187 DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
2188 goto fail;
2189 }
2190 res->hdmiphy = clk_get(dev, "hdmiphy");
2191 if (IS_ERR_OR_NULL(res->hdmiphy)) {
2192 DRM_ERROR("failed to get clock 'hdmiphy'\n");
2193 goto fail;
2194 }
2195
2196 clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
2197
2198 res->regul_bulk = kzalloc(ARRAY_SIZE(supply) *
Sachin Kamatadc837a2012-08-31 15:50:47 +05302199 sizeof(res->regul_bulk[0]), GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002200 if (!res->regul_bulk) {
2201 DRM_ERROR("failed to get memory for regulators\n");
2202 goto fail;
2203 }
2204 for (i = 0; i < ARRAY_SIZE(supply); ++i) {
2205 res->regul_bulk[i].supply = supply[i];
2206 res->regul_bulk[i].consumer = NULL;
2207 }
2208 ret = regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
2209 if (ret) {
2210 DRM_ERROR("failed to get regulators\n");
2211 goto fail;
2212 }
2213 res->regul_count = ARRAY_SIZE(supply);
2214
2215 return 0;
2216fail:
2217 DRM_ERROR("HDMI resource init - failed\n");
2218 return -ENODEV;
2219}
2220
2221static int hdmi_resources_cleanup(struct hdmi_context *hdata)
2222{
2223 struct hdmi_resources *res = &hdata->res;
2224
2225 regulator_bulk_free(res->regul_count, res->regul_bulk);
2226 /* kfree is NULL-safe */
2227 kfree(res->regul_bulk);
2228 if (!IS_ERR_OR_NULL(res->hdmiphy))
2229 clk_put(res->hdmiphy);
2230 if (!IS_ERR_OR_NULL(res->sclk_hdmiphy))
2231 clk_put(res->sclk_hdmiphy);
2232 if (!IS_ERR_OR_NULL(res->sclk_pixel))
2233 clk_put(res->sclk_pixel);
2234 if (!IS_ERR_OR_NULL(res->sclk_hdmi))
2235 clk_put(res->sclk_hdmi);
2236 if (!IS_ERR_OR_NULL(res->hdmi))
2237 clk_put(res->hdmi);
Sachin Kamatadc837a2012-08-31 15:50:47 +05302238 memset(res, 0, sizeof(*res));
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002239
2240 return 0;
2241}
2242
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002243static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;
2244
2245void hdmi_attach_ddc_client(struct i2c_client *ddc)
2246{
2247 if (ddc)
2248 hdmi_ddc = ddc;
2249}
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002250
2251void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)
2252{
2253 if (hdmiphy)
2254 hdmi_hdmiphy = hdmiphy;
2255}
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002256
Rahul Sharma22c4f422012-10-04 20:48:55 +05302257#ifdef CONFIG_OF
2258static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
2259 (struct device *dev)
2260{
2261 struct device_node *np = dev->of_node;
2262 struct s5p_hdmi_platform_data *pd;
2263 enum of_gpio_flags flags;
2264 u32 value;
2265
2266 pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
2267 if (!pd) {
2268 DRM_ERROR("memory allocation for pdata failed\n");
2269 goto err_data;
2270 }
2271
2272 if (!of_find_property(np, "hpd-gpio", &value)) {
2273 DRM_ERROR("no hpd gpio property found\n");
2274 goto err_data;
2275 }
2276
2277 pd->hpd_gpio = of_get_named_gpio_flags(np, "hpd-gpio", 0, &flags);
2278
2279 return pd;
2280
2281err_data:
2282 return NULL;
2283}
2284#else
2285static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
2286 (struct device *dev)
2287{
2288 return NULL;
2289}
2290#endif
2291
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302292static struct platform_device_id hdmi_driver_types[] = {
2293 {
2294 .name = "s5pv210-hdmi",
2295 .driver_data = HDMI_TYPE13,
2296 }, {
2297 .name = "exynos4-hdmi",
2298 .driver_data = HDMI_TYPE13,
2299 }, {
2300 .name = "exynos4-hdmi14",
Rahul Sharma22c4f422012-10-04 20:48:55 +05302301 .driver_data = HDMI_TYPE14,
2302 }, {
2303 .name = "exynos5-hdmi",
2304 .driver_data = HDMI_TYPE14,
2305 }, {
2306 /* end node */
2307 }
2308};
2309
2310static struct of_device_id hdmi_match_types[] = {
2311 {
2312 .compatible = "samsung,exynos5-hdmi",
2313 .data = (void *)HDMI_TYPE14,
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302314 }, {
2315 /* end node */
2316 }
2317};
2318
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002319static int __devinit hdmi_probe(struct platform_device *pdev)
2320{
2321 struct device *dev = &pdev->dev;
2322 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
2323 struct hdmi_context *hdata;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302324 struct s5p_hdmi_platform_data *pdata;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002325 struct resource *res;
2326 int ret;
2327
2328 DRM_DEBUG_KMS("[%d]\n", __LINE__);
2329
Rahul Sharma22c4f422012-10-04 20:48:55 +05302330 if (pdev->dev.of_node) {
2331 pdata = drm_hdmi_dt_parse_pdata(dev);
2332 if (IS_ERR(pdata)) {
2333 DRM_ERROR("failed to parse dt\n");
2334 return PTR_ERR(pdata);
2335 }
2336 } else {
2337 pdata = pdev->dev.platform_data;
2338 }
2339
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002340 if (!pdata) {
2341 DRM_ERROR("no platform data specified\n");
2342 return -EINVAL;
2343 }
2344
Sachin Kamata6e65072012-06-19 11:47:40 +05302345 drm_hdmi_ctx = devm_kzalloc(&pdev->dev, sizeof(*drm_hdmi_ctx),
2346 GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002347 if (!drm_hdmi_ctx) {
2348 DRM_ERROR("failed to allocate common hdmi context.\n");
2349 return -ENOMEM;
2350 }
2351
Sachin Kamata6e65072012-06-19 11:47:40 +05302352 hdata = devm_kzalloc(&pdev->dev, sizeof(struct hdmi_context),
2353 GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002354 if (!hdata) {
2355 DRM_ERROR("out of memory\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002356 return -ENOMEM;
2357 }
2358
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002359 mutex_init(&hdata->hdmi_mutex);
2360
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002361 drm_hdmi_ctx->ctx = (void *)hdata;
2362 hdata->parent_ctx = (void *)drm_hdmi_ctx;
2363
2364 platform_set_drvdata(pdev, drm_hdmi_ctx);
2365
Rahul Sharma22c4f422012-10-04 20:48:55 +05302366 if (dev->of_node) {
2367 const struct of_device_id *match;
2368 match = of_match_node(of_match_ptr(hdmi_match_types),
2369 pdev->dev.of_node);
2370 hdata->type = (enum hdmi_type)match->data;
2371 } else {
2372 hdata->type = (enum hdmi_type)platform_get_device_id
Rahul Sharma5a325072012-10-04 20:48:54 +05302373 (pdev)->driver_data;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302374 }
2375
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302376 hdata->hpd_gpio = pdata->hpd_gpio;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002377 hdata->dev = dev;
2378
2379 ret = hdmi_resources_init(hdata);
Rahul Sharma22c4f422012-10-04 20:48:55 +05302380
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002381 if (ret) {
2382 ret = -EINVAL;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302383 DRM_ERROR("hdmi_resources_init failed\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002384 goto err_data;
2385 }
2386
2387 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Rahul Sharma22c4f422012-10-04 20:48:55 +05302388 if (!res) {
2389 DRM_ERROR("failed to find registers\n");
2390 ret = -ENOENT;
2391 goto err_resource;
2392 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002393
Sachin Kamata6e65072012-06-19 11:47:40 +05302394 hdata->regs = devm_request_and_ioremap(&pdev->dev, res);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002395 if (!hdata->regs) {
2396 DRM_ERROR("failed to map registers\n");
2397 ret = -ENXIO;
Sachin Kamata6e65072012-06-19 11:47:40 +05302398 goto err_resource;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002399 }
2400
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302401 ret = gpio_request(hdata->hpd_gpio, "HPD");
2402 if (ret) {
2403 DRM_ERROR("failed to request HPD gpio\n");
2404 goto err_resource;
2405 }
2406
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002407 /* DDC i2c driver */
2408 if (i2c_add_driver(&ddc_driver)) {
2409 DRM_ERROR("failed to register ddc i2c driver\n");
2410 ret = -ENOENT;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302411 goto err_gpio;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002412 }
2413
2414 hdata->ddc_port = hdmi_ddc;
2415
2416 /* hdmiphy i2c driver */
2417 if (i2c_add_driver(&hdmiphy_driver)) {
2418 DRM_ERROR("failed to register hdmiphy i2c driver\n");
2419 ret = -ENOENT;
2420 goto err_ddc;
2421 }
2422
2423 hdata->hdmiphy_port = hdmi_hdmiphy;
2424
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302425 hdata->external_irq = gpio_to_irq(hdata->hpd_gpio);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002426 if (hdata->external_irq < 0) {
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302427 DRM_ERROR("failed to get GPIO external irq\n");
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002428 ret = hdata->external_irq;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002429 goto err_hdmiphy;
2430 }
2431
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302432 hdata->internal_irq = platform_get_irq(pdev, 0);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002433 if (hdata->internal_irq < 0) {
2434 DRM_ERROR("failed to get platform internal irq\n");
2435 ret = hdata->internal_irq;
Joonyoung Shim66265a22012-04-23 19:35:49 +09002436 goto err_hdmiphy;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002437 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002438
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302439 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2440
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002441 ret = request_threaded_irq(hdata->external_irq, NULL,
2442 hdmi_external_irq_thread, IRQF_TRIGGER_RISING |
2443 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
2444 "hdmi_external", drm_hdmi_ctx);
2445 if (ret) {
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302446 DRM_ERROR("failed to register hdmi external interrupt\n");
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002447 goto err_hdmiphy;
2448 }
2449
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002450 ret = request_threaded_irq(hdata->internal_irq, NULL,
2451 hdmi_internal_irq_thread, IRQF_ONESHOT,
2452 "hdmi_internal", drm_hdmi_ctx);
2453 if (ret) {
2454 DRM_ERROR("failed to register hdmi internal interrupt\n");
2455 goto err_free_irq;
2456 }
2457
Rahul Sharma768c3052012-10-04 20:48:56 +05302458 /* Attach HDMI Driver to common hdmi. */
2459 exynos_hdmi_drv_attach(drm_hdmi_ctx);
2460
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002461 /* register specific callbacks to common hdmi. */
Joonyoung Shim578b6062012-04-05 20:49:26 +09002462 exynos_hdmi_ops_register(&hdmi_ops);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002463
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002464 pm_runtime_enable(dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002465
2466 return 0;
2467
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002468err_free_irq:
2469 free_irq(hdata->external_irq, drm_hdmi_ctx);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002470err_hdmiphy:
2471 i2c_del_driver(&hdmiphy_driver);
2472err_ddc:
2473 i2c_del_driver(&ddc_driver);
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302474err_gpio:
2475 gpio_free(hdata->hpd_gpio);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002476err_resource:
2477 hdmi_resources_cleanup(hdata);
2478err_data:
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002479 return ret;
2480}
2481
2482static int __devexit hdmi_remove(struct platform_device *pdev)
2483{
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002484 struct device *dev = &pdev->dev;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002485 struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev);
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002486 struct hdmi_context *hdata = ctx->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002487
2488 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2489
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002490 pm_runtime_disable(dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002491
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002492 free_irq(hdata->internal_irq, hdata);
Tomasz Stanislawski07c8bdd2012-10-04 20:48:45 +05302493 free_irq(hdata->external_irq, hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002494
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302495 gpio_free(hdata->hpd_gpio);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002496
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002497 hdmi_resources_cleanup(hdata);
2498
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002499 /* hdmiphy i2c driver */
2500 i2c_del_driver(&hdmiphy_driver);
2501 /* DDC i2c driver */
2502 i2c_del_driver(&ddc_driver);
2503
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002504 return 0;
2505}
2506
Joonyoung Shimab27af82012-04-23 19:35:51 +09002507#ifdef CONFIG_PM_SLEEP
2508static int hdmi_suspend(struct device *dev)
2509{
2510 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2511 struct hdmi_context *hdata = ctx->ctx;
2512
2513 disable_irq(hdata->internal_irq);
2514 disable_irq(hdata->external_irq);
2515
2516 hdata->hpd = false;
2517 if (ctx->drm_dev)
2518 drm_helper_hpd_irq_event(ctx->drm_dev);
2519
2520 hdmi_poweroff(hdata);
2521
2522 return 0;
2523}
2524
2525static int hdmi_resume(struct device *dev)
2526{
2527 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2528 struct hdmi_context *hdata = ctx->ctx;
2529
2530 enable_irq(hdata->external_irq);
2531 enable_irq(hdata->internal_irq);
2532 return 0;
2533}
2534#endif
2535
2536static SIMPLE_DEV_PM_OPS(hdmi_pm_ops, hdmi_suspend, hdmi_resume);
2537
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002538struct platform_driver hdmi_driver = {
2539 .probe = hdmi_probe,
2540 .remove = __devexit_p(hdmi_remove),
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302541 .id_table = hdmi_driver_types,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002542 .driver = {
Rahul Sharma22c4f422012-10-04 20:48:55 +05302543 .name = "exynos-hdmi",
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002544 .owner = THIS_MODULE,
Joonyoung Shimab27af82012-04-23 19:35:51 +09002545 .pm = &hdmi_pm_ops,
Rahul Sharma22c4f422012-10-04 20:48:55 +05302546 .of_match_table = hdmi_match_types,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002547 },
2548};