blob: 2c115f8a62a31dd47793b8306f348a870e8eef8a [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 Kim872d20d2012-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;
Tomasz Stanislawski07c8bdd2012-10-04 20:48:45 +053077 int external_irq;
78 int internal_irq;
Joonyoung Shim590f4182012-03-16 18:47:14 +090079
80 struct i2c_client *ddc_port;
81 struct i2c_client *hdmiphy_port;
82
83 /* current hdmiphy conf index */
84 int cur_conf;
85
86 struct hdmi_resources res;
87 void *parent_ctx;
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 Kim872d20d2012-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 Kim872d20d2012-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);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001296 } else {
1297 return -ENODEV;
1298 }
1299
1300 return 0;
1301}
1302
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001303static int hdmi_v13_check_timing(struct fb_videomode *check_timing)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001304{
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001305 int i;
1306
Inki Dae1de425b2012-03-16 18:47:04 +09001307 DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
1308 check_timing->xres, check_timing->yres,
1309 check_timing->refresh, (check_timing->vmode &
1310 FB_VMODE_INTERLACED) ? true : false);
1311
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001312 for (i = 0; i < ARRAY_SIZE(hdmi_v13_confs); ++i)
1313 if (hdmi_v13_confs[i].width == check_timing->xres &&
1314 hdmi_v13_confs[i].height == check_timing->yres &&
1315 hdmi_v13_confs[i].vrefresh == check_timing->refresh &&
1316 hdmi_v13_confs[i].interlace ==
1317 ((check_timing->vmode & FB_VMODE_INTERLACED) ?
1318 true : false))
Inki Dae1de425b2012-03-16 18:47:04 +09001319 return 0;
1320
1321 /* TODO */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001322
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001323 return -EINVAL;
1324}
1325
1326static int hdmi_v14_check_timing(struct fb_videomode *check_timing)
1327{
1328 int i;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001329
Inki Dae1de425b2012-03-16 18:47:04 +09001330 DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n",
1331 check_timing->xres, check_timing->yres,
1332 check_timing->refresh, (check_timing->vmode &
1333 FB_VMODE_INTERLACED) ? true : false);
1334
1335 for (i = 0; i < ARRAY_SIZE(hdmi_confs); i++)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001336 if (hdmi_confs[i].width == check_timing->xres &&
1337 hdmi_confs[i].height == check_timing->yres &&
1338 hdmi_confs[i].vrefresh == check_timing->refresh &&
1339 hdmi_confs[i].interlace ==
1340 ((check_timing->vmode & FB_VMODE_INTERLACED) ?
1341 true : false))
Inki Dae1de425b2012-03-16 18:47:04 +09001342 return 0;
1343
1344 /* TODO */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001345
1346 return -EINVAL;
1347}
1348
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001349static int hdmi_check_timing(void *ctx, void *timing)
1350{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001351 struct hdmi_context *hdata = ctx;
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001352 struct fb_videomode *check_timing = timing;
1353
1354 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1355
1356 DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", check_timing->xres,
1357 check_timing->yres, check_timing->refresh,
1358 check_timing->vmode);
1359
Rahul Sharma5a325072012-10-04 20:48:54 +05301360 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001361 return hdmi_v13_check_timing(check_timing);
1362 else
1363 return hdmi_v14_check_timing(check_timing);
1364}
1365
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001366static void hdmi_set_acr(u32 freq, u8 *acr)
1367{
1368 u32 n, cts;
1369
1370 switch (freq) {
1371 case 32000:
1372 n = 4096;
1373 cts = 27000;
1374 break;
1375 case 44100:
1376 n = 6272;
1377 cts = 30000;
1378 break;
1379 case 88200:
1380 n = 12544;
1381 cts = 30000;
1382 break;
1383 case 176400:
1384 n = 25088;
1385 cts = 30000;
1386 break;
1387 case 48000:
1388 n = 6144;
1389 cts = 27000;
1390 break;
1391 case 96000:
1392 n = 12288;
1393 cts = 27000;
1394 break;
1395 case 192000:
1396 n = 24576;
1397 cts = 27000;
1398 break;
1399 default:
1400 n = 0;
1401 cts = 0;
1402 break;
1403 }
1404
1405 acr[1] = cts >> 16;
1406 acr[2] = cts >> 8 & 0xff;
1407 acr[3] = cts & 0xff;
1408
1409 acr[4] = n >> 16;
1410 acr[5] = n >> 8 & 0xff;
1411 acr[6] = n & 0xff;
1412}
1413
1414static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
1415{
1416 hdmi_reg_writeb(hdata, HDMI_ACR_N0, acr[6]);
1417 hdmi_reg_writeb(hdata, HDMI_ACR_N1, acr[5]);
1418 hdmi_reg_writeb(hdata, HDMI_ACR_N2, acr[4]);
1419 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS0, acr[3]);
1420 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS1, acr[2]);
1421 hdmi_reg_writeb(hdata, HDMI_ACR_MCTS2, acr[1]);
1422 hdmi_reg_writeb(hdata, HDMI_ACR_CTS0, acr[3]);
1423 hdmi_reg_writeb(hdata, HDMI_ACR_CTS1, acr[2]);
1424 hdmi_reg_writeb(hdata, HDMI_ACR_CTS2, acr[1]);
1425
Rahul Sharma5a325072012-10-04 20:48:54 +05301426 if (hdata->type == HDMI_TYPE13)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001427 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 4);
1428 else
1429 hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4);
1430}
1431
1432static void hdmi_audio_init(struct hdmi_context *hdata)
1433{
1434 u32 sample_rate, bits_per_sample, frame_size_code;
1435 u32 data_num, bit_ch, sample_frq;
1436 u32 val;
1437 u8 acr[7];
1438
1439 sample_rate = 44100;
1440 bits_per_sample = 16;
1441 frame_size_code = 0;
1442
1443 switch (bits_per_sample) {
1444 case 20:
1445 data_num = 2;
1446 bit_ch = 1;
1447 break;
1448 case 24:
1449 data_num = 3;
1450 bit_ch = 1;
1451 break;
1452 default:
1453 data_num = 1;
1454 bit_ch = 0;
1455 break;
1456 }
1457
1458 hdmi_set_acr(sample_rate, acr);
1459 hdmi_reg_acr(hdata, acr);
1460
1461 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE
1462 | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE
1463 | HDMI_I2S_MUX_ENABLE);
1464
1465 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CH, HDMI_I2S_CH0_EN
1466 | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN);
1467
1468 hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN);
1469
1470 sample_frq = (sample_rate == 44100) ? 0 :
1471 (sample_rate == 48000) ? 2 :
1472 (sample_rate == 32000) ? 3 :
1473 (sample_rate == 96000) ? 0xa : 0x0;
1474
1475 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS);
1476 hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN);
1477
1478 val = hdmi_reg_read(hdata, HDMI_I2S_DSD_CON) | 0x01;
1479 hdmi_reg_writeb(hdata, HDMI_I2S_DSD_CON, val);
1480
1481 /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */
1482 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5)
1483 | HDMI_I2S_SEL_LRCK(6));
1484 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1)
1485 | HDMI_I2S_SEL_SDATA2(4));
1486 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1)
1487 | HDMI_I2S_SEL_SDATA2(2));
1488 hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0));
1489
1490 /* I2S_CON_1 & 2 */
1491 hdmi_reg_writeb(hdata, HDMI_I2S_CON_1, HDMI_I2S_SCLK_FALLING_EDGE
1492 | HDMI_I2S_L_CH_LOW_POL);
1493 hdmi_reg_writeb(hdata, HDMI_I2S_CON_2, HDMI_I2S_MSB_FIRST_MODE
1494 | HDMI_I2S_SET_BIT_CH(bit_ch)
1495 | HDMI_I2S_SET_SDATA_BIT(data_num)
1496 | HDMI_I2S_BASIC_FORMAT);
1497
1498 /* Configure register related to CUV information */
1499 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0
1500 | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH
1501 | HDMI_I2S_COPYRIGHT
1502 | HDMI_I2S_LINEAR_PCM
1503 | HDMI_I2S_CONSUMER_FORMAT);
1504 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER);
1505 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0));
1506 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2
1507 | HDMI_I2S_SET_SMP_FREQ(sample_frq));
1508 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4,
1509 HDMI_I2S_ORG_SMP_FREQ_44_1
1510 | HDMI_I2S_WORD_LEN_MAX24_24BITS
1511 | HDMI_I2S_WORD_LEN_MAX_24BITS);
1512
1513 hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD);
1514}
1515
1516static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff)
1517{
Seung-Woo Kim872d20d2012-04-24 17:39:15 +09001518 if (hdata->dvi_mode)
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001519 return;
1520
1521 hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0);
1522 hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ?
1523 HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK);
1524}
1525
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001526static void hdmi_conf_reset(struct hdmi_context *hdata)
1527{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001528 u32 reg;
1529
Rahul Sharma5a325072012-10-04 20:48:54 +05301530 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001531 reg = HDMI_V13_CORE_RSTOUT;
1532 else
1533 reg = HDMI_CORE_RSTOUT;
1534
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001535 /* resetting HDMI core */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001536 hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001537 mdelay(10);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001538 hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001539 mdelay(10);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001540}
1541
1542static void hdmi_conf_init(struct hdmi_context *hdata)
1543{
Tomasz Stanislawski5295e532012-10-04 20:48:47 +05301544 /* disable HPD interrupts */
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001545 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1546 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001547
1548 /* choose HDMI mode */
1549 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1550 HDMI_MODE_HDMI_EN, HDMI_MODE_MASK);
1551 /* disable bluescreen */
1552 hdmi_reg_writemask(hdata, HDMI_CON_0, 0, HDMI_BLUE_SCR_EN);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001553
Seung-Woo Kim872d20d2012-04-24 17:39:15 +09001554 if (hdata->dvi_mode) {
1555 /* choose DVI mode */
1556 hdmi_reg_writemask(hdata, HDMI_MODE_SEL,
1557 HDMI_MODE_DVI_EN, HDMI_MODE_MASK);
1558 hdmi_reg_writeb(hdata, HDMI_CON_2,
1559 HDMI_VID_PREAMBLE_DIS | HDMI_GUARD_BAND_DIS);
1560 }
1561
Rahul Sharma5a325072012-10-04 20:48:54 +05301562 if (hdata->type == HDMI_TYPE13) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001563 /* choose bluescreen (fecal) color */
1564 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_0, 0x12);
1565 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_1, 0x34);
1566 hdmi_reg_writeb(hdata, HDMI_V13_BLUE_SCREEN_2, 0x56);
1567
1568 /* enable AVI packet every vsync, fixes purple line problem */
1569 hdmi_reg_writeb(hdata, HDMI_V13_AVI_CON, 0x02);
1570 /* force RGB, look to CEA-861-D, table 7 for more detail */
1571 hdmi_reg_writeb(hdata, HDMI_V13_AVI_BYTE(0), 0 << 5);
1572 hdmi_reg_writemask(hdata, HDMI_CON_1, 0x10 << 5, 0x11 << 5);
1573
1574 hdmi_reg_writeb(hdata, HDMI_V13_SPD_CON, 0x02);
1575 hdmi_reg_writeb(hdata, HDMI_V13_AUI_CON, 0x02);
1576 hdmi_reg_writeb(hdata, HDMI_V13_ACR_CON, 0x04);
1577 } else {
1578 /* enable AVI packet every vsync, fixes purple line problem */
1579 hdmi_reg_writeb(hdata, HDMI_AVI_CON, 0x02);
1580 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 2 << 5);
1581 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1582 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001583}
1584
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001585static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001586{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001587 const struct hdmi_v13_preset_conf *conf =
1588 hdmi_v13_confs[hdata->cur_conf].conf;
1589 const struct hdmi_v13_core_regs *core = &conf->core;
1590 const struct hdmi_v13_tg_regs *tg = &conf->tg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001591 int tries;
1592
1593 /* setting core registers */
1594 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1595 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001596 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_0, core->v_blank[0]);
1597 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_1, core->v_blank[1]);
1598 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_2, core->v_blank[2]);
1599 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_0, core->h_v_line[0]);
1600 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_1, core->h_v_line[1]);
1601 hdmi_reg_writeb(hdata, HDMI_V13_H_V_LINE_2, core->h_v_line[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001602 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1603 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001604 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_0, core->v_blank_f[0]);
1605 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_1, core->v_blank_f[1]);
1606 hdmi_reg_writeb(hdata, HDMI_V13_V_BLANK_F_2, core->v_blank_f[2]);
1607 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_0, core->h_sync_gen[0]);
1608 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_1, core->h_sync_gen[1]);
1609 hdmi_reg_writeb(hdata, HDMI_V13_H_SYNC_GEN_2, core->h_sync_gen[2]);
1610 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_0, core->v_sync_gen1[0]);
1611 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_1, core->v_sync_gen1[1]);
1612 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_1_2, core->v_sync_gen1[2]);
1613 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_0, core->v_sync_gen2[0]);
1614 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_1, core->v_sync_gen2[1]);
1615 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_2_2, core->v_sync_gen2[2]);
1616 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_0, core->v_sync_gen3[0]);
1617 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_1, core->v_sync_gen3[1]);
1618 hdmi_reg_writeb(hdata, HDMI_V13_V_SYNC_GEN_3_2, core->v_sync_gen3[2]);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001619 /* Timing generator registers */
1620 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
1621 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
1622 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
1623 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
1624 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
1625 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
1626 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
1627 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
1628 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
1629 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
1630 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
1631 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
1632 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
1633 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
1634 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
1635 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
1636 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
1637 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
1638 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
1639 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
1640 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
1641 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
1642 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
1643 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
1644 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
1645 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
1646 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
1647 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
1648
1649 /* waiting for HDMIPHY's PLL to get to steady state */
1650 for (tries = 100; tries; --tries) {
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001651 u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001652 if (val & HDMI_PHY_STATUS_READY)
1653 break;
1654 mdelay(1);
1655 }
1656 /* steady state not achieved */
1657 if (tries == 0) {
1658 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1659 hdmi_regs_dump(hdata, "timing apply");
1660 }
1661
1662 clk_disable(hdata->res.sclk_hdmi);
1663 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
1664 clk_enable(hdata->res.sclk_hdmi);
1665
1666 /* enable HDMI and timing generator */
1667 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1668 if (core->int_pro_mode[0])
1669 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1670 HDMI_FIELD_EN);
1671 else
1672 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1673}
1674
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001675static void hdmi_v14_timing_apply(struct hdmi_context *hdata)
1676{
1677 const struct hdmi_preset_conf *conf = hdmi_confs[hdata->cur_conf].conf;
1678 const struct hdmi_core_regs *core = &conf->core;
1679 const struct hdmi_tg_regs *tg = &conf->tg;
1680 int tries;
1681
1682 /* setting core registers */
1683 hdmi_reg_writeb(hdata, HDMI_H_BLANK_0, core->h_blank[0]);
1684 hdmi_reg_writeb(hdata, HDMI_H_BLANK_1, core->h_blank[1]);
1685 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_0, core->v2_blank[0]);
1686 hdmi_reg_writeb(hdata, HDMI_V2_BLANK_1, core->v2_blank[1]);
1687 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_0, core->v1_blank[0]);
1688 hdmi_reg_writeb(hdata, HDMI_V1_BLANK_1, core->v1_blank[1]);
1689 hdmi_reg_writeb(hdata, HDMI_V_LINE_0, core->v_line[0]);
1690 hdmi_reg_writeb(hdata, HDMI_V_LINE_1, core->v_line[1]);
1691 hdmi_reg_writeb(hdata, HDMI_H_LINE_0, core->h_line[0]);
1692 hdmi_reg_writeb(hdata, HDMI_H_LINE_1, core->h_line[1]);
1693 hdmi_reg_writeb(hdata, HDMI_HSYNC_POL, core->hsync_pol[0]);
1694 hdmi_reg_writeb(hdata, HDMI_VSYNC_POL, core->vsync_pol[0]);
1695 hdmi_reg_writeb(hdata, HDMI_INT_PRO_MODE, core->int_pro_mode[0]);
1696 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_0, core->v_blank_f0[0]);
1697 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F0_1, core->v_blank_f0[1]);
1698 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_0, core->v_blank_f1[0]);
1699 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F1_1, core->v_blank_f1[1]);
1700 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_0, core->h_sync_start[0]);
1701 hdmi_reg_writeb(hdata, HDMI_H_SYNC_START_1, core->h_sync_start[1]);
1702 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_0, core->h_sync_end[0]);
1703 hdmi_reg_writeb(hdata, HDMI_H_SYNC_END_1, core->h_sync_end[1]);
1704 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_0,
1705 core->v_sync_line_bef_2[0]);
1706 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_2_1,
1707 core->v_sync_line_bef_2[1]);
1708 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_0,
1709 core->v_sync_line_bef_1[0]);
1710 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_BEF_1_1,
1711 core->v_sync_line_bef_1[1]);
1712 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_0,
1713 core->v_sync_line_aft_2[0]);
1714 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_2_1,
1715 core->v_sync_line_aft_2[1]);
1716 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_0,
1717 core->v_sync_line_aft_1[0]);
1718 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_1_1,
1719 core->v_sync_line_aft_1[1]);
1720 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_0,
1721 core->v_sync_line_aft_pxl_2[0]);
1722 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_2_1,
1723 core->v_sync_line_aft_pxl_2[1]);
1724 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_0,
1725 core->v_sync_line_aft_pxl_1[0]);
1726 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_1_1,
1727 core->v_sync_line_aft_pxl_1[1]);
1728 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_0, core->v_blank_f2[0]);
1729 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F2_1, core->v_blank_f2[1]);
1730 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_0, core->v_blank_f3[0]);
1731 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F3_1, core->v_blank_f3[1]);
1732 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_0, core->v_blank_f4[0]);
1733 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F4_1, core->v_blank_f4[1]);
1734 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_0, core->v_blank_f5[0]);
1735 hdmi_reg_writeb(hdata, HDMI_V_BLANK_F5_1, core->v_blank_f5[1]);
1736 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_0,
1737 core->v_sync_line_aft_3[0]);
1738 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_3_1,
1739 core->v_sync_line_aft_3[1]);
1740 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_0,
1741 core->v_sync_line_aft_4[0]);
1742 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_4_1,
1743 core->v_sync_line_aft_4[1]);
1744 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_0,
1745 core->v_sync_line_aft_5[0]);
1746 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_5_1,
1747 core->v_sync_line_aft_5[1]);
1748 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_0,
1749 core->v_sync_line_aft_6[0]);
1750 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_6_1,
1751 core->v_sync_line_aft_6[1]);
1752 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_0,
1753 core->v_sync_line_aft_pxl_3[0]);
1754 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_3_1,
1755 core->v_sync_line_aft_pxl_3[1]);
1756 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_0,
1757 core->v_sync_line_aft_pxl_4[0]);
1758 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_4_1,
1759 core->v_sync_line_aft_pxl_4[1]);
1760 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_0,
1761 core->v_sync_line_aft_pxl_5[0]);
1762 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_5_1,
1763 core->v_sync_line_aft_pxl_5[1]);
1764 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0,
1765 core->v_sync_line_aft_pxl_6[0]);
1766 hdmi_reg_writeb(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_1,
1767 core->v_sync_line_aft_pxl_6[1]);
1768 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_0, core->vact_space_1[0]);
1769 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_1_1, core->vact_space_1[1]);
1770 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_0, core->vact_space_2[0]);
1771 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_2_1, core->vact_space_2[1]);
1772 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_0, core->vact_space_3[0]);
1773 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_3_1, core->vact_space_3[1]);
1774 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_0, core->vact_space_4[0]);
1775 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_4_1, core->vact_space_4[1]);
1776 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_0, core->vact_space_5[0]);
1777 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_5_1, core->vact_space_5[1]);
1778 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_0, core->vact_space_6[0]);
1779 hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]);
1780
1781 /* Timing generator registers */
1782 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l);
1783 hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h);
1784 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l);
1785 hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h);
1786 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l);
1787 hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h);
1788 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l);
1789 hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h);
1790 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l);
1791 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h);
1792 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l);
1793 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h);
1794 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l);
1795 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h);
1796 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l);
1797 hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h);
1798 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l);
1799 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h);
1800 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l);
1801 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h);
1802 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3_l);
1803 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3_h);
1804 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4_l);
1805 hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4_h);
1806 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l);
1807 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h);
1808 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l);
1809 hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h);
1810 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l);
1811 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h);
1812 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l);
1813 hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h);
1814 hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d);
1815
1816 /* waiting for HDMIPHY's PLL to get to steady state */
1817 for (tries = 100; tries; --tries) {
1818 u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
1819 if (val & HDMI_PHY_STATUS_READY)
1820 break;
1821 mdelay(1);
1822 }
1823 /* steady state not achieved */
1824 if (tries == 0) {
1825 DRM_ERROR("hdmiphy's pll could not reach steady state.\n");
1826 hdmi_regs_dump(hdata, "timing apply");
1827 }
1828
1829 clk_disable(hdata->res.sclk_hdmi);
1830 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_hdmiphy);
1831 clk_enable(hdata->res.sclk_hdmi);
1832
1833 /* enable HDMI and timing generator */
1834 hdmi_reg_writemask(hdata, HDMI_CON_0, ~0, HDMI_EN);
1835 if (core->int_pro_mode[0])
1836 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN |
1837 HDMI_FIELD_EN);
1838 else
1839 hdmi_reg_writemask(hdata, HDMI_TG_CMD, ~0, HDMI_TG_EN);
1840}
1841
1842static void hdmi_timing_apply(struct hdmi_context *hdata)
1843{
Rahul Sharma5a325072012-10-04 20:48:54 +05301844 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001845 hdmi_v13_timing_apply(hdata);
1846 else
1847 hdmi_v14_timing_apply(hdata);
1848}
1849
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001850static void hdmiphy_conf_reset(struct hdmi_context *hdata)
1851{
1852 u8 buffer[2];
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001853 u32 reg;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001854
1855 clk_disable(hdata->res.sclk_hdmi);
1856 clk_set_parent(hdata->res.sclk_hdmi, hdata->res.sclk_pixel);
1857 clk_enable(hdata->res.sclk_hdmi);
1858
1859 /* operation mode */
1860 buffer[0] = 0x1f;
1861 buffer[1] = 0x00;
1862
1863 if (hdata->hdmiphy_port)
1864 i2c_master_send(hdata->hdmiphy_port, buffer, 2);
1865
Rahul Sharma5a325072012-10-04 20:48:54 +05301866 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001867 reg = HDMI_V13_PHY_RSTOUT;
1868 else
1869 reg = HDMI_PHY_RSTOUT;
1870
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001871 /* reset hdmiphy */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001872 hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001873 mdelay(10);
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001874 hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001875 mdelay(10);
1876}
1877
1878static void hdmiphy_conf_apply(struct hdmi_context *hdata)
1879{
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001880 const u8 *hdmiphy_data;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001881 u8 buffer[32];
1882 u8 operation[2];
1883 u8 read_buffer[32] = {0, };
1884 int ret;
1885 int i;
1886
1887 if (!hdata->hdmiphy_port) {
1888 DRM_ERROR("hdmiphy is not attached\n");
1889 return;
1890 }
1891
1892 /* pixel clock */
Rahul Sharma5a325072012-10-04 20:48:54 +05301893 if (hdata->type == HDMI_TYPE13)
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001894 hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data;
1895 else
1896 hdmiphy_data = hdmi_confs[hdata->cur_conf].hdmiphy_data;
1897
1898 memcpy(buffer, hdmiphy_data, 32);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001899 ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32);
1900 if (ret != 32) {
1901 DRM_ERROR("failed to configure HDMIPHY via I2C\n");
1902 return;
1903 }
1904
1905 mdelay(10);
1906
1907 /* operation mode */
1908 operation[0] = 0x1f;
1909 operation[1] = 0x80;
1910
1911 ret = i2c_master_send(hdata->hdmiphy_port, operation, 2);
1912 if (ret != 2) {
1913 DRM_ERROR("failed to enable hdmiphy\n");
1914 return;
1915 }
1916
1917 ret = i2c_master_recv(hdata->hdmiphy_port, read_buffer, 32);
1918 if (ret < 0) {
1919 DRM_ERROR("failed to read hdmiphy config\n");
1920 return;
1921 }
1922
1923 for (i = 0; i < ret; i++)
1924 DRM_DEBUG_KMS("hdmiphy[0x%02x] write[0x%02x] - "
1925 "recv [0x%02x]\n", i, buffer[i], read_buffer[i]);
1926}
1927
1928static void hdmi_conf_apply(struct hdmi_context *hdata)
1929{
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001930 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1931
1932 hdmiphy_conf_reset(hdata);
1933 hdmiphy_conf_apply(hdata);
1934
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001935 mutex_lock(&hdata->hdmi_mutex);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001936 hdmi_conf_reset(hdata);
1937 hdmi_conf_init(hdata);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09001938 mutex_unlock(&hdata->hdmi_mutex);
1939
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001940 hdmi_audio_init(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001941
1942 /* setting core registers */
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001943 hdmi_timing_apply(hdata);
Seung-Woo Kim3e148ba2012-03-16 18:47:16 +09001944 hdmi_audio_control(hdata, true);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001945
1946 hdmi_regs_dump(hdata, "start");
1947}
1948
Inki Dae1de425b2012-03-16 18:47:04 +09001949static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector,
Laurent Pincharte811f5a2012-07-17 17:56:50 +02001950 const struct drm_display_mode *mode,
Inki Dae1de425b2012-03-16 18:47:04 +09001951 struct drm_display_mode *adjusted_mode)
1952{
1953 struct drm_display_mode *m;
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001954 struct hdmi_context *hdata = ctx;
Inki Dae1de425b2012-03-16 18:47:04 +09001955 int index;
1956
1957 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1958
1959 drm_mode_set_crtcinfo(adjusted_mode, 0);
1960
Rahul Sharma5a325072012-10-04 20:48:54 +05301961 if (hdata->type == HDMI_TYPE13)
Inki Dae1de425b2012-03-16 18:47:04 +09001962 index = hdmi_v13_conf_index(adjusted_mode);
1963 else
1964 index = hdmi_v14_conf_index(adjusted_mode);
1965
1966 /* just return if user desired mode exists. */
1967 if (index >= 0)
1968 return;
1969
1970 /*
1971 * otherwise, find the most suitable mode among modes and change it
1972 * to adjusted_mode.
1973 */
1974 list_for_each_entry(m, &connector->modes, head) {
Rahul Sharma5a325072012-10-04 20:48:54 +05301975 if (hdata->type == HDMI_TYPE13)
Inki Dae1de425b2012-03-16 18:47:04 +09001976 index = hdmi_v13_conf_index(m);
1977 else
1978 index = hdmi_v14_conf_index(m);
1979
1980 if (index >= 0) {
1981 DRM_INFO("desired mode doesn't exist so\n");
1982 DRM_INFO("use the most suitable mode among modes.\n");
1983 memcpy(adjusted_mode, m, sizeof(*m));
1984 break;
1985 }
1986 }
1987}
1988
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001989static void hdmi_mode_set(void *ctx, void *mode)
1990{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09001991 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001992 int conf_idx;
1993
1994 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1995
Joonyoung Shim3ecd70b2012-03-16 18:47:03 +09001996 conf_idx = hdmi_conf_index(hdata, mode);
1997 if (conf_idx >= 0)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09001998 hdata->cur_conf = conf_idx;
1999 else
2000 DRM_DEBUG_KMS("not supported mode\n");
2001}
2002
Inki Dae1de425b2012-03-16 18:47:04 +09002003static void hdmi_get_max_resol(void *ctx, unsigned int *width,
2004 unsigned int *height)
2005{
2006 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2007
2008 *width = MAX_WIDTH;
2009 *height = MAX_HEIGHT;
2010}
2011
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002012static void hdmi_commit(void *ctx)
2013{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002014 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002015
2016 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2017
2018 hdmi_conf_apply(hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002019}
2020
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002021static void hdmi_poweron(struct hdmi_context *hdata)
2022{
2023 struct hdmi_resources *res = &hdata->res;
2024
2025 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2026
2027 mutex_lock(&hdata->hdmi_mutex);
2028 if (hdata->powered) {
2029 mutex_unlock(&hdata->hdmi_mutex);
2030 return;
2031 }
2032
2033 hdata->powered = true;
2034
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002035 mutex_unlock(&hdata->hdmi_mutex);
2036
2037 pm_runtime_get_sync(hdata->dev);
2038
2039 regulator_bulk_enable(res->regul_count, res->regul_bulk);
2040 clk_enable(res->hdmiphy);
2041 clk_enable(res->hdmi);
2042 clk_enable(res->sclk_hdmi);
2043}
2044
2045static void hdmi_poweroff(struct hdmi_context *hdata)
2046{
2047 struct hdmi_resources *res = &hdata->res;
2048
2049 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2050
2051 mutex_lock(&hdata->hdmi_mutex);
2052 if (!hdata->powered)
2053 goto out;
2054 mutex_unlock(&hdata->hdmi_mutex);
2055
2056 /*
2057 * The TV power domain needs any condition of hdmiphy to turn off and
2058 * its reset state seems to meet the condition.
2059 */
2060 hdmiphy_conf_reset(hdata);
2061
2062 clk_disable(res->sclk_hdmi);
2063 clk_disable(res->hdmi);
2064 clk_disable(res->hdmiphy);
2065 regulator_bulk_disable(res->regul_count, res->regul_bulk);
2066
2067 pm_runtime_put_sync(hdata->dev);
2068
2069 mutex_lock(&hdata->hdmi_mutex);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002070
2071 hdata->powered = false;
2072
2073out:
2074 mutex_unlock(&hdata->hdmi_mutex);
2075}
2076
2077static void hdmi_dpms(void *ctx, int mode)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002078{
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002079 struct hdmi_context *hdata = ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002080
2081 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2082
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002083 switch (mode) {
2084 case DRM_MODE_DPMS_ON:
2085 hdmi_poweron(hdata);
2086 break;
2087 case DRM_MODE_DPMS_STANDBY:
2088 case DRM_MODE_DPMS_SUSPEND:
2089 case DRM_MODE_DPMS_OFF:
2090 hdmi_poweroff(hdata);
2091 break;
2092 default:
2093 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
2094 break;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002095 }
2096}
2097
Joonyoung Shim578b6062012-04-05 20:49:26 +09002098static struct exynos_hdmi_ops hdmi_ops = {
2099 /* display */
2100 .is_connected = hdmi_is_connected,
2101 .get_edid = hdmi_get_edid,
2102 .check_timing = hdmi_check_timing,
Joonyoung Shim578b6062012-04-05 20:49:26 +09002103
2104 /* manager */
Inki Dae1de425b2012-03-16 18:47:04 +09002105 .mode_fixup = hdmi_mode_fixup,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002106 .mode_set = hdmi_mode_set,
Inki Dae1de425b2012-03-16 18:47:04 +09002107 .get_max_resol = hdmi_get_max_resol,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002108 .commit = hdmi_commit,
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002109 .dpms = hdmi_dpms,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002110};
2111
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002112static irqreturn_t hdmi_external_irq_thread(int irq, void *arg)
2113{
2114 struct exynos_drm_hdmi_context *ctx = arg;
2115 struct hdmi_context *hdata = ctx->ctx;
2116
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002117 mutex_lock(&hdata->hdmi_mutex);
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302118 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002119 mutex_unlock(&hdata->hdmi_mutex);
2120
2121 if (ctx->drm_dev)
2122 drm_helper_hpd_irq_event(ctx->drm_dev);
2123
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002124 return IRQ_HANDLED;
2125}
2126
2127static irqreturn_t hdmi_internal_irq_thread(int irq, void *arg)
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002128{
2129 struct exynos_drm_hdmi_context *ctx = arg;
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002130 struct hdmi_context *hdata = ctx->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002131 u32 intc_flag;
2132
2133 intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG);
2134 /* clearing flags for HPD plug/unplug */
2135 if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002136 DRM_DEBUG_KMS("unplugged\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002137 hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
2138 HDMI_INTC_FLAG_HPD_UNPLUG);
2139 }
2140 if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002141 DRM_DEBUG_KMS("plugged\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002142 hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
2143 HDMI_INTC_FLAG_HPD_PLUG);
2144 }
2145
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002146 if (ctx->drm_dev)
Joonyoung Shim66265a22012-04-23 19:35:49 +09002147 drm_helper_hpd_irq_event(ctx->drm_dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002148
2149 return IRQ_HANDLED;
2150}
2151
2152static int __devinit hdmi_resources_init(struct hdmi_context *hdata)
2153{
2154 struct device *dev = hdata->dev;
2155 struct hdmi_resources *res = &hdata->res;
2156 static char *supply[] = {
2157 "hdmi-en",
2158 "vdd",
2159 "vdd_osc",
2160 "vdd_pll",
2161 };
2162 int i, ret;
2163
2164 DRM_DEBUG_KMS("HDMI resource init\n");
2165
Sachin Kamatadc837a2012-08-31 15:50:47 +05302166 memset(res, 0, sizeof(*res));
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002167
2168 /* get clocks, power */
2169 res->hdmi = clk_get(dev, "hdmi");
2170 if (IS_ERR_OR_NULL(res->hdmi)) {
2171 DRM_ERROR("failed to get clock 'hdmi'\n");
2172 goto fail;
2173 }
2174 res->sclk_hdmi = clk_get(dev, "sclk_hdmi");
2175 if (IS_ERR_OR_NULL(res->sclk_hdmi)) {
2176 DRM_ERROR("failed to get clock 'sclk_hdmi'\n");
2177 goto fail;
2178 }
2179 res->sclk_pixel = clk_get(dev, "sclk_pixel");
2180 if (IS_ERR_OR_NULL(res->sclk_pixel)) {
2181 DRM_ERROR("failed to get clock 'sclk_pixel'\n");
2182 goto fail;
2183 }
2184 res->sclk_hdmiphy = clk_get(dev, "sclk_hdmiphy");
2185 if (IS_ERR_OR_NULL(res->sclk_hdmiphy)) {
2186 DRM_ERROR("failed to get clock 'sclk_hdmiphy'\n");
2187 goto fail;
2188 }
2189 res->hdmiphy = clk_get(dev, "hdmiphy");
2190 if (IS_ERR_OR_NULL(res->hdmiphy)) {
2191 DRM_ERROR("failed to get clock 'hdmiphy'\n");
2192 goto fail;
2193 }
2194
2195 clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
2196
2197 res->regul_bulk = kzalloc(ARRAY_SIZE(supply) *
Sachin Kamatadc837a2012-08-31 15:50:47 +05302198 sizeof(res->regul_bulk[0]), GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002199 if (!res->regul_bulk) {
2200 DRM_ERROR("failed to get memory for regulators\n");
2201 goto fail;
2202 }
2203 for (i = 0; i < ARRAY_SIZE(supply); ++i) {
2204 res->regul_bulk[i].supply = supply[i];
2205 res->regul_bulk[i].consumer = NULL;
2206 }
2207 ret = regulator_bulk_get(dev, ARRAY_SIZE(supply), res->regul_bulk);
2208 if (ret) {
2209 DRM_ERROR("failed to get regulators\n");
2210 goto fail;
2211 }
2212 res->regul_count = ARRAY_SIZE(supply);
2213
2214 return 0;
2215fail:
2216 DRM_ERROR("HDMI resource init - failed\n");
2217 return -ENODEV;
2218}
2219
2220static int hdmi_resources_cleanup(struct hdmi_context *hdata)
2221{
2222 struct hdmi_resources *res = &hdata->res;
2223
2224 regulator_bulk_free(res->regul_count, res->regul_bulk);
2225 /* kfree is NULL-safe */
2226 kfree(res->regul_bulk);
2227 if (!IS_ERR_OR_NULL(res->hdmiphy))
2228 clk_put(res->hdmiphy);
2229 if (!IS_ERR_OR_NULL(res->sclk_hdmiphy))
2230 clk_put(res->sclk_hdmiphy);
2231 if (!IS_ERR_OR_NULL(res->sclk_pixel))
2232 clk_put(res->sclk_pixel);
2233 if (!IS_ERR_OR_NULL(res->sclk_hdmi))
2234 clk_put(res->sclk_hdmi);
2235 if (!IS_ERR_OR_NULL(res->hdmi))
2236 clk_put(res->hdmi);
Sachin Kamatadc837a2012-08-31 15:50:47 +05302237 memset(res, 0, sizeof(*res));
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002238
2239 return 0;
2240}
2241
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002242static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;
2243
2244void hdmi_attach_ddc_client(struct i2c_client *ddc)
2245{
2246 if (ddc)
2247 hdmi_ddc = ddc;
2248}
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002249
2250void hdmi_attach_hdmiphy_client(struct i2c_client *hdmiphy)
2251{
2252 if (hdmiphy)
2253 hdmi_hdmiphy = hdmiphy;
2254}
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002255
Rahul Sharma22c4f422012-10-04 20:48:55 +05302256#ifdef CONFIG_OF
2257static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
2258 (struct device *dev)
2259{
2260 struct device_node *np = dev->of_node;
2261 struct s5p_hdmi_platform_data *pd;
2262 enum of_gpio_flags flags;
2263 u32 value;
2264
2265 pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
2266 if (!pd) {
2267 DRM_ERROR("memory allocation for pdata failed\n");
2268 goto err_data;
2269 }
2270
2271 if (!of_find_property(np, "hpd-gpio", &value)) {
2272 DRM_ERROR("no hpd gpio property found\n");
2273 goto err_data;
2274 }
2275
2276 pd->hpd_gpio = of_get_named_gpio_flags(np, "hpd-gpio", 0, &flags);
2277
2278 return pd;
2279
2280err_data:
2281 return NULL;
2282}
2283#else
2284static struct s5p_hdmi_platform_data *drm_hdmi_dt_parse_pdata
2285 (struct device *dev)
2286{
2287 return NULL;
2288}
2289#endif
2290
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302291static struct platform_device_id hdmi_driver_types[] = {
2292 {
2293 .name = "s5pv210-hdmi",
2294 .driver_data = HDMI_TYPE13,
2295 }, {
2296 .name = "exynos4-hdmi",
2297 .driver_data = HDMI_TYPE13,
2298 }, {
2299 .name = "exynos4-hdmi14",
Rahul Sharma22c4f422012-10-04 20:48:55 +05302300 .driver_data = HDMI_TYPE14,
2301 }, {
2302 .name = "exynos5-hdmi",
2303 .driver_data = HDMI_TYPE14,
2304 }, {
2305 /* end node */
2306 }
2307};
2308
2309static struct of_device_id hdmi_match_types[] = {
2310 {
2311 .compatible = "samsung,exynos5-hdmi",
2312 .data = (void *)HDMI_TYPE14,
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302313 }, {
2314 /* end node */
2315 }
2316};
2317
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002318static int __devinit hdmi_probe(struct platform_device *pdev)
2319{
2320 struct device *dev = &pdev->dev;
2321 struct exynos_drm_hdmi_context *drm_hdmi_ctx;
2322 struct hdmi_context *hdata;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302323 struct s5p_hdmi_platform_data *pdata;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002324 struct resource *res;
2325 int ret;
2326
2327 DRM_DEBUG_KMS("[%d]\n", __LINE__);
2328
Rahul Sharma22c4f422012-10-04 20:48:55 +05302329 if (pdev->dev.of_node) {
2330 pdata = drm_hdmi_dt_parse_pdata(dev);
2331 if (IS_ERR(pdata)) {
2332 DRM_ERROR("failed to parse dt\n");
2333 return PTR_ERR(pdata);
2334 }
2335 } else {
2336 pdata = pdev->dev.platform_data;
2337 }
2338
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002339 if (!pdata) {
2340 DRM_ERROR("no platform data specified\n");
2341 return -EINVAL;
2342 }
2343
Sachin Kamata6e65072012-06-19 11:47:40 +05302344 drm_hdmi_ctx = devm_kzalloc(&pdev->dev, sizeof(*drm_hdmi_ctx),
2345 GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002346 if (!drm_hdmi_ctx) {
2347 DRM_ERROR("failed to allocate common hdmi context.\n");
2348 return -ENOMEM;
2349 }
2350
Sachin Kamata6e65072012-06-19 11:47:40 +05302351 hdata = devm_kzalloc(&pdev->dev, sizeof(struct hdmi_context),
2352 GFP_KERNEL);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002353 if (!hdata) {
2354 DRM_ERROR("out of memory\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002355 return -ENOMEM;
2356 }
2357
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002358 mutex_init(&hdata->hdmi_mutex);
2359
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002360 drm_hdmi_ctx->ctx = (void *)hdata;
2361 hdata->parent_ctx = (void *)drm_hdmi_ctx;
2362
2363 platform_set_drvdata(pdev, drm_hdmi_ctx);
2364
Rahul Sharma22c4f422012-10-04 20:48:55 +05302365 if (dev->of_node) {
2366 const struct of_device_id *match;
2367 match = of_match_node(of_match_ptr(hdmi_match_types),
2368 pdev->dev.of_node);
2369 hdata->type = (enum hdmi_type)match->data;
2370 } else {
2371 hdata->type = (enum hdmi_type)platform_get_device_id
Rahul Sharma5a325072012-10-04 20:48:54 +05302372 (pdev)->driver_data;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302373 }
2374
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302375 hdata->hpd_gpio = pdata->hpd_gpio;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002376 hdata->dev = dev;
2377
2378 ret = hdmi_resources_init(hdata);
Rahul Sharma22c4f422012-10-04 20:48:55 +05302379
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002380 if (ret) {
2381 ret = -EINVAL;
Rahul Sharma22c4f422012-10-04 20:48:55 +05302382 DRM_ERROR("hdmi_resources_init failed\n");
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002383 goto err_data;
2384 }
2385
2386 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Rahul Sharma22c4f422012-10-04 20:48:55 +05302387 if (!res) {
2388 DRM_ERROR("failed to find registers\n");
2389 ret = -ENOENT;
2390 goto err_resource;
2391 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002392
Sachin Kamata6e65072012-06-19 11:47:40 +05302393 hdata->regs = devm_request_and_ioremap(&pdev->dev, res);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002394 if (!hdata->regs) {
2395 DRM_ERROR("failed to map registers\n");
2396 ret = -ENXIO;
Sachin Kamata6e65072012-06-19 11:47:40 +05302397 goto err_resource;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002398 }
2399
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302400 ret = gpio_request(hdata->hpd_gpio, "HPD");
2401 if (ret) {
2402 DRM_ERROR("failed to request HPD gpio\n");
2403 goto err_resource;
2404 }
2405
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002406 /* DDC i2c driver */
2407 if (i2c_add_driver(&ddc_driver)) {
2408 DRM_ERROR("failed to register ddc i2c driver\n");
2409 ret = -ENOENT;
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302410 goto err_gpio;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002411 }
2412
2413 hdata->ddc_port = hdmi_ddc;
2414
2415 /* hdmiphy i2c driver */
2416 if (i2c_add_driver(&hdmiphy_driver)) {
2417 DRM_ERROR("failed to register hdmiphy i2c driver\n");
2418 ret = -ENOENT;
2419 goto err_ddc;
2420 }
2421
2422 hdata->hdmiphy_port = hdmi_hdmiphy;
2423
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302424 hdata->external_irq = gpio_to_irq(hdata->hpd_gpio);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002425 if (hdata->external_irq < 0) {
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302426 DRM_ERROR("failed to get GPIO external irq\n");
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002427 ret = hdata->external_irq;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002428 goto err_hdmiphy;
2429 }
2430
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302431 hdata->internal_irq = platform_get_irq(pdev, 0);
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002432 if (hdata->internal_irq < 0) {
2433 DRM_ERROR("failed to get platform internal irq\n");
2434 ret = hdata->internal_irq;
Joonyoung Shim66265a22012-04-23 19:35:49 +09002435 goto err_hdmiphy;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002436 }
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002437
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302438 hdata->hpd = gpio_get_value(hdata->hpd_gpio);
2439
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002440 ret = request_threaded_irq(hdata->external_irq, NULL,
2441 hdmi_external_irq_thread, IRQF_TRIGGER_RISING |
2442 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
2443 "hdmi_external", drm_hdmi_ctx);
2444 if (ret) {
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302445 DRM_ERROR("failed to register hdmi external interrupt\n");
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002446 goto err_hdmiphy;
2447 }
2448
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002449 ret = request_threaded_irq(hdata->internal_irq, NULL,
2450 hdmi_internal_irq_thread, IRQF_ONESHOT,
2451 "hdmi_internal", drm_hdmi_ctx);
2452 if (ret) {
2453 DRM_ERROR("failed to register hdmi internal interrupt\n");
2454 goto err_free_irq;
2455 }
2456
Rahul Sharma768c3052012-10-04 20:48:56 +05302457 /* Attach HDMI Driver to common hdmi. */
2458 exynos_hdmi_drv_attach(drm_hdmi_ctx);
2459
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002460 /* register specific callbacks to common hdmi. */
Joonyoung Shim578b6062012-04-05 20:49:26 +09002461 exynos_hdmi_ops_register(&hdmi_ops);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002462
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002463 pm_runtime_enable(dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002464
2465 return 0;
2466
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002467err_free_irq:
2468 free_irq(hdata->external_irq, drm_hdmi_ctx);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002469err_hdmiphy:
2470 i2c_del_driver(&hdmiphy_driver);
2471err_ddc:
2472 i2c_del_driver(&ddc_driver);
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302473err_gpio:
2474 gpio_free(hdata->hpd_gpio);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002475err_resource:
2476 hdmi_resources_cleanup(hdata);
2477err_data:
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002478 return ret;
2479}
2480
2481static int __devexit hdmi_remove(struct platform_device *pdev)
2482{
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002483 struct device *dev = &pdev->dev;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002484 struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev);
Joonyoung Shimf9309d12012-04-05 20:49:22 +09002485 struct hdmi_context *hdata = ctx->ctx;
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002486
2487 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2488
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002489 pm_runtime_disable(dev);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002490
Joonyoung Shimcf8fc4f2012-04-23 19:35:50 +09002491 free_irq(hdata->internal_irq, hdata);
Tomasz Stanislawski07c8bdd2012-10-04 20:48:45 +05302492 free_irq(hdata->external_irq, hdata);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002493
Tomasz Stanislawskifca57122012-10-04 20:48:46 +05302494 gpio_free(hdata->hpd_gpio);
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002495
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002496 hdmi_resources_cleanup(hdata);
2497
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002498 /* hdmiphy i2c driver */
2499 i2c_del_driver(&hdmiphy_driver);
2500 /* DDC i2c driver */
2501 i2c_del_driver(&ddc_driver);
2502
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002503 return 0;
2504}
2505
Joonyoung Shimab27af82012-04-23 19:35:51 +09002506#ifdef CONFIG_PM_SLEEP
2507static int hdmi_suspend(struct device *dev)
2508{
2509 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2510 struct hdmi_context *hdata = ctx->ctx;
2511
2512 disable_irq(hdata->internal_irq);
2513 disable_irq(hdata->external_irq);
2514
2515 hdata->hpd = false;
2516 if (ctx->drm_dev)
2517 drm_helper_hpd_irq_event(ctx->drm_dev);
2518
2519 hdmi_poweroff(hdata);
2520
2521 return 0;
2522}
2523
2524static int hdmi_resume(struct device *dev)
2525{
2526 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2527 struct hdmi_context *hdata = ctx->ctx;
2528
2529 enable_irq(hdata->external_irq);
2530 enable_irq(hdata->internal_irq);
2531 return 0;
2532}
2533#endif
2534
2535static SIMPLE_DEV_PM_OPS(hdmi_pm_ops, hdmi_suspend, hdmi_resume);
2536
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002537struct platform_driver hdmi_driver = {
2538 .probe = hdmi_probe,
2539 .remove = __devexit_p(hdmi_remove),
Tomasz Stanislawskic119ed02012-10-04 20:48:44 +05302540 .id_table = hdmi_driver_types,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002541 .driver = {
Rahul Sharma22c4f422012-10-04 20:48:55 +05302542 .name = "exynos-hdmi",
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002543 .owner = THIS_MODULE,
Joonyoung Shimab27af82012-04-23 19:35:51 +09002544 .pm = &hdmi_pm_ops,
Rahul Sharma22c4f422012-10-04 20:48:55 +05302545 .of_match_table = hdmi_match_types,
Seung-Woo Kimd8408322011-12-21 17:39:39 +09002546 },
2547};